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