1 //===-- HexagonRegisterInfo.cpp - Hexagon Register Information ------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file contains the Hexagon implementation of the TargetRegisterInfo 11 // class. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "HexagonRegisterInfo.h" 16 #include "Hexagon.h" 17 #include "HexagonSubtarget.h" 18 #include "HexagonTargetMachine.h" 19 #include "HexagonMachineFunctionInfo.h" 20 #include "llvm/ADT/BitVector.h" 21 #include "llvm/ADT/STLExtras.h" 22 #include "llvm/CodeGen/MachineInstrBuilder.h" 23 #include "llvm/CodeGen/MachineFunction.h" 24 #include "llvm/CodeGen/MachineFunctionPass.h" 25 #include "llvm/CodeGen/MachineFrameInfo.h" 26 #include "llvm/CodeGen/MachineRegisterInfo.h" 27 #include "llvm/CodeGen/PseudoSourceValue.h" 28 #include "llvm/CodeGen/RegisterScavenging.h" 29 #include "llvm/IR/Function.h" 30 #include "llvm/IR/Type.h" 31 #include "llvm/MC/MachineLocation.h" 32 #include "llvm/Target/TargetInstrInfo.h" 33 #include "llvm/Target/TargetMachine.h" 34 #include "llvm/Target/TargetOptions.h" 35 #include "llvm/Support/CommandLine.h" 36 #include "llvm/Support/ErrorHandling.h" 37 38 using namespace llvm; 39 40 41 HexagonRegisterInfo::HexagonRegisterInfo(HexagonSubtarget &st) 42 : HexagonGenRegisterInfo(Hexagon::R31), 43 Subtarget(st) { 44 } 45 46 const uint16_t* HexagonRegisterInfo::getCalleeSavedRegs(const MachineFunction 47 *MF) 48 const { 49 static const uint16_t CalleeSavedRegsV2[] = { 50 Hexagon::R24, Hexagon::R25, Hexagon::R26, Hexagon::R27, 0 51 }; 52 static const uint16_t CalleeSavedRegsV3[] = { 53 Hexagon::R16, Hexagon::R17, Hexagon::R18, Hexagon::R19, 54 Hexagon::R20, Hexagon::R21, Hexagon::R22, Hexagon::R23, 55 Hexagon::R24, Hexagon::R25, Hexagon::R26, Hexagon::R27, 0 56 }; 57 58 switch(Subtarget.getHexagonArchVersion()) { 59 case HexagonSubtarget::V1: 60 break; 61 case HexagonSubtarget::V2: 62 return CalleeSavedRegsV2; 63 case HexagonSubtarget::V3: 64 case HexagonSubtarget::V4: 65 case HexagonSubtarget::V5: 66 return CalleeSavedRegsV3; 67 } 68 llvm_unreachable("Callee saved registers requested for unknown architecture " 69 "version"); 70 } 71 72 BitVector HexagonRegisterInfo::getReservedRegs(const MachineFunction &MF) 73 const { 74 BitVector Reserved(getNumRegs()); 75 Reserved.set(HEXAGON_RESERVED_REG_1); 76 Reserved.set(HEXAGON_RESERVED_REG_2); 77 Reserved.set(Hexagon::R29); 78 Reserved.set(Hexagon::R30); 79 Reserved.set(Hexagon::R31); 80 Reserved.set(Hexagon::D14); 81 Reserved.set(Hexagon::D15); 82 Reserved.set(Hexagon::LC0); 83 Reserved.set(Hexagon::LC1); 84 Reserved.set(Hexagon::SA0); 85 Reserved.set(Hexagon::SA1); 86 return Reserved; 87 } 88 89 90 const TargetRegisterClass* const* 91 HexagonRegisterInfo::getCalleeSavedRegClasses(const MachineFunction *MF) const { 92 static const TargetRegisterClass * const CalleeSavedRegClassesV2[] = { 93 &Hexagon::IntRegsRegClass, &Hexagon::IntRegsRegClass, 94 &Hexagon::IntRegsRegClass, &Hexagon::IntRegsRegClass, 95 }; 96 static const TargetRegisterClass * const CalleeSavedRegClassesV3[] = { 97 &Hexagon::IntRegsRegClass, &Hexagon::IntRegsRegClass, 98 &Hexagon::IntRegsRegClass, &Hexagon::IntRegsRegClass, 99 &Hexagon::IntRegsRegClass, &Hexagon::IntRegsRegClass, 100 &Hexagon::IntRegsRegClass, &Hexagon::IntRegsRegClass, 101 &Hexagon::IntRegsRegClass, &Hexagon::IntRegsRegClass, 102 &Hexagon::IntRegsRegClass, &Hexagon::IntRegsRegClass, 103 }; 104 105 switch(Subtarget.getHexagonArchVersion()) { 106 case HexagonSubtarget::V1: 107 break; 108 case HexagonSubtarget::V2: 109 return CalleeSavedRegClassesV2; 110 case HexagonSubtarget::V3: 111 case HexagonSubtarget::V4: 112 case HexagonSubtarget::V5: 113 return CalleeSavedRegClassesV3; 114 } 115 llvm_unreachable("Callee saved register classes requested for unknown " 116 "architecture version"); 117 } 118 119 void HexagonRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, 120 int SPAdj, unsigned FIOperandNum, 121 RegScavenger *RS) const { 122 // 123 // Hexagon_TODO: Do we need to enforce this for Hexagon? 124 assert(SPAdj == 0 && "Unexpected"); 125 126 MachineInstr &MI = *II; 127 int FrameIndex = MI.getOperand(FIOperandNum).getIndex(); 128 129 // Addressable stack objects are accessed using neg. offsets from %fp. 130 MachineFunction &MF = *MI.getParent()->getParent(); 131 const HexagonInstrInfo &TII = 132 *static_cast<const HexagonInstrInfo*>(MF.getTarget().getInstrInfo()); 133 int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex); 134 MachineFrameInfo &MFI = *MF.getFrameInfo(); 135 136 unsigned FrameReg = getFrameRegister(MF); 137 const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering(); 138 if (!TFI->hasFP(MF)) { 139 // We will not reserve space on the stack for the lr and fp registers. 140 Offset -= 2 * Hexagon_WordSize; 141 } 142 143 const unsigned FrameSize = MFI.getStackSize(); 144 145 if (!MFI.hasVarSizedObjects() && 146 TII.isValidOffset(MI.getOpcode(), (FrameSize+Offset)) && 147 !TII.isSpillPredRegOp(&MI)) { 148 // Replace frame index with a stack pointer reference. 149 MI.getOperand(FIOperandNum).ChangeToRegister(getStackRegister(), false, 150 false, true); 151 MI.getOperand(FIOperandNum + 1).ChangeToImmediate(FrameSize+Offset); 152 } else { 153 // Replace frame index with a frame pointer reference. 154 if (!TII.isValidOffset(MI.getOpcode(), Offset)) { 155 156 // If the offset overflows, then correct it. 157 // 158 // For loads, we do not need a reserved register 159 // r0 = memw(r30 + #10000) to: 160 // 161 // r0 = add(r30, #10000) 162 // r0 = memw(r0) 163 if ( (MI.getOpcode() == Hexagon::LDriw) || 164 (MI.getOpcode() == Hexagon::LDrid) || 165 (MI.getOpcode() == Hexagon::LDrih) || 166 (MI.getOpcode() == Hexagon::LDriuh) || 167 (MI.getOpcode() == Hexagon::LDrib) || 168 (MI.getOpcode() == Hexagon::LDriub) || 169 (MI.getOpcode() == Hexagon::LDriw_f) || 170 (MI.getOpcode() == Hexagon::LDrid_f)) { 171 unsigned dstReg = (MI.getOpcode() == Hexagon::LDrid) ? 172 getSubReg(MI.getOperand(0).getReg(), Hexagon::subreg_loreg) : 173 MI.getOperand(0).getReg(); 174 175 // Check if offset can fit in addi. 176 if (!TII.isValidOffset(Hexagon::ADD_ri, Offset)) { 177 BuildMI(*MI.getParent(), II, MI.getDebugLoc(), 178 TII.get(Hexagon::CONST32_Int_Real), dstReg).addImm(Offset); 179 BuildMI(*MI.getParent(), II, MI.getDebugLoc(), 180 TII.get(Hexagon::ADD_rr), 181 dstReg).addReg(FrameReg).addReg(dstReg); 182 } else { 183 BuildMI(*MI.getParent(), II, MI.getDebugLoc(), 184 TII.get(Hexagon::ADD_ri), 185 dstReg).addReg(FrameReg).addImm(Offset); 186 } 187 188 MI.getOperand(FIOperandNum).ChangeToRegister(dstReg, false, false,true); 189 MI.getOperand(FIOperandNum+1).ChangeToImmediate(0); 190 } else if ((MI.getOpcode() == Hexagon::STriw_indexed) || 191 (MI.getOpcode() == Hexagon::STriw) || 192 (MI.getOpcode() == Hexagon::STrid) || 193 (MI.getOpcode() == Hexagon::STrih) || 194 (MI.getOpcode() == Hexagon::STrib) || 195 (MI.getOpcode() == Hexagon::STrid_f) || 196 (MI.getOpcode() == Hexagon::STriw_f)) { 197 // For stores, we need a reserved register. Change 198 // memw(r30 + #10000) = r0 to: 199 // 200 // rs = add(r30, #10000); 201 // memw(rs) = r0 202 unsigned resReg = HEXAGON_RESERVED_REG_1; 203 204 // Check if offset can fit in addi. 205 if (!TII.isValidOffset(Hexagon::ADD_ri, Offset)) { 206 BuildMI(*MI.getParent(), II, MI.getDebugLoc(), 207 TII.get(Hexagon::CONST32_Int_Real), resReg).addImm(Offset); 208 BuildMI(*MI.getParent(), II, MI.getDebugLoc(), 209 TII.get(Hexagon::ADD_rr), 210 resReg).addReg(FrameReg).addReg(resReg); 211 } else { 212 BuildMI(*MI.getParent(), II, MI.getDebugLoc(), 213 TII.get(Hexagon::ADD_ri), 214 resReg).addReg(FrameReg).addImm(Offset); 215 } 216 MI.getOperand(FIOperandNum).ChangeToRegister(resReg, false, false,true); 217 MI.getOperand(FIOperandNum+1).ChangeToImmediate(0); 218 } else if (TII.isMemOp(&MI)) { 219 // use the constant extender if the instruction provides it 220 // and we are V4TOps. 221 if (Subtarget.hasV4TOps()) { 222 if (TII.isConstExtended(&MI)) { 223 MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false); 224 MI.getOperand(FIOperandNum+1).ChangeToImmediate(Offset); 225 TII.immediateExtend(&MI); 226 } else { 227 llvm_unreachable("Need to implement for memops"); 228 } 229 } else { 230 // Only V3 and older instructions here. 231 unsigned ResReg = HEXAGON_RESERVED_REG_1; 232 if (!MFI.hasVarSizedObjects() && 233 TII.isValidOffset(MI.getOpcode(), (FrameSize+Offset))) { 234 MI.getOperand(FIOperandNum).ChangeToRegister(getStackRegister(), 235 false, false, false); 236 MI.getOperand(FIOperandNum+1).ChangeToImmediate(FrameSize+Offset); 237 } else if (!TII.isValidOffset(Hexagon::ADD_ri, Offset)) { 238 BuildMI(*MI.getParent(), II, MI.getDebugLoc(), 239 TII.get(Hexagon::CONST32_Int_Real), ResReg).addImm(Offset); 240 BuildMI(*MI.getParent(), II, MI.getDebugLoc(), 241 TII.get(Hexagon::ADD_rr), ResReg).addReg(FrameReg). 242 addReg(ResReg); 243 MI.getOperand(FIOperandNum).ChangeToRegister(ResReg, false, false, 244 true); 245 MI.getOperand(FIOperandNum+1).ChangeToImmediate(0); 246 } else { 247 BuildMI(*MI.getParent(), II, MI.getDebugLoc(), 248 TII.get(Hexagon::ADD_ri), ResReg).addReg(FrameReg). 249 addImm(Offset); 250 MI.getOperand(FIOperandNum).ChangeToRegister(ResReg, false, false, 251 true); 252 MI.getOperand(FIOperandNum+1).ChangeToImmediate(0); 253 } 254 } 255 } else { 256 unsigned dstReg = MI.getOperand(0).getReg(); 257 BuildMI(*MI.getParent(), II, MI.getDebugLoc(), 258 TII.get(Hexagon::CONST32_Int_Real), dstReg).addImm(Offset); 259 BuildMI(*MI.getParent(), II, MI.getDebugLoc(), 260 TII.get(Hexagon::ADD_rr), 261 dstReg).addReg(FrameReg).addReg(dstReg); 262 // Can we delete MI??? r2 = add (r2, #0). 263 MI.getOperand(FIOperandNum).ChangeToRegister(dstReg, false, false,true); 264 MI.getOperand(FIOperandNum+1).ChangeToImmediate(0); 265 } 266 } else { 267 // If the offset is small enough to fit in the immediate field, directly 268 // encode it. 269 MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false); 270 MI.getOperand(FIOperandNum+1).ChangeToImmediate(Offset); 271 } 272 } 273 274 } 275 276 unsigned HexagonRegisterInfo::getRARegister() const { 277 return Hexagon::R31; 278 } 279 280 unsigned HexagonRegisterInfo::getFrameRegister(const MachineFunction 281 &MF) const { 282 const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering(); 283 if (TFI->hasFP(MF)) { 284 return Hexagon::R30; 285 } 286 287 return Hexagon::R29; 288 } 289 290 unsigned HexagonRegisterInfo::getFrameRegister() const { 291 return Hexagon::R30; 292 } 293 294 unsigned HexagonRegisterInfo::getStackRegister() const { 295 return Hexagon::R29; 296 } 297 298 unsigned HexagonRegisterInfo::getEHExceptionRegister() const { 299 llvm_unreachable("What is the exception register"); 300 } 301 302 unsigned HexagonRegisterInfo::getEHHandlerRegister() const { 303 llvm_unreachable("What is the exception handler register"); 304 } 305 306 #define GET_REGINFO_TARGET_DESC 307 #include "HexagonGenRegisterInfo.inc" 308