1 //==- HexagonRegisterInfo.cpp - Hexagon Register Information -----*- C++ -*-==// 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 "Hexagon.h" 16 #include "HexagonRegisterInfo.h" 17 #include "HexagonSubtarget.h" 18 #include "HexagonTargetMachine.h" 19 #include "HexagonMachineFunctionInfo.h" 20 #include "llvm/CodeGen/MachineInstrBuilder.h" 21 #include "llvm/CodeGen/MachineFunction.h" 22 #include "llvm/CodeGen/MachineFrameInfo.h" 23 #include "llvm/CodeGen/MachineRegisterInfo.h" 24 #include "llvm/CodeGen/RegisterScavenging.h" 25 #include "llvm/MC/MachineLocation.h" 26 #include "llvm/Target/TargetInstrInfo.h" 27 #include "llvm/Type.h" 28 #include "llvm/ADT/BitVector.h" 29 #include "llvm/ADT/STLExtras.h" 30 #include "llvm/Support/CommandLine.h" 31 #include "llvm/Support/ErrorHandling.h" 32 #include "llvm/Target/TargetMachine.h" 33 #include "llvm/Target/TargetOptions.h" 34 #include <iostream> 35 36 #include "llvm/CodeGen/MachineFunctionPass.h" 37 #include "llvm/Function.h" 38 using namespace llvm; 39 40 41 HexagonRegisterInfo::HexagonRegisterInfo(HexagonSubtarget &st, 42 const HexagonInstrInfo &tii) 43 : HexagonGenRegisterInfo(Hexagon::R31), 44 Subtarget(st), 45 TII(tii) { 46 } 47 48 const unsigned* HexagonRegisterInfo::getCalleeSavedRegs(const MachineFunction 49 *MF) 50 const { 51 static const unsigned CalleeSavedRegsV2[] = { 52 Hexagon::R24, Hexagon::R25, Hexagon::R26, Hexagon::R27, 0 53 }; 54 static const unsigned CalleeSavedRegsV3[] = { 55 Hexagon::R16, Hexagon::R17, Hexagon::R18, Hexagon::R19, 56 Hexagon::R20, Hexagon::R21, Hexagon::R22, Hexagon::R23, 57 Hexagon::R24, Hexagon::R25, Hexagon::R26, Hexagon::R27, 0 58 }; 59 60 switch(Subtarget.getHexagonArchVersion()) { 61 case HexagonSubtarget::V1: 62 break; 63 case HexagonSubtarget::V2: 64 return CalleeSavedRegsV2; 65 case HexagonSubtarget::V3: 66 case HexagonSubtarget::V4: 67 return CalleeSavedRegsV3; 68 } 69 llvm_unreachable("Callee saved registers requested for unknown architecture " 70 "version"); 71 } 72 73 BitVector HexagonRegisterInfo::getReservedRegs(const MachineFunction &MF) 74 const { 75 BitVector Reserved(getNumRegs()); 76 Reserved.set(HEXAGON_RESERVED_REG_1); 77 Reserved.set(HEXAGON_RESERVED_REG_2); 78 Reserved.set(Hexagon::R29); 79 Reserved.set(Hexagon::R30); 80 Reserved.set(Hexagon::R31); 81 Reserved.set(Hexagon::D14); 82 Reserved.set(Hexagon::D15); 83 Reserved.set(Hexagon::LC0); 84 Reserved.set(Hexagon::LC1); 85 Reserved.set(Hexagon::SA0); 86 Reserved.set(Hexagon::SA1); 87 return Reserved; 88 } 89 90 91 const TargetRegisterClass* const* 92 HexagonRegisterInfo::getCalleeSavedRegClasses(const MachineFunction *MF) const { 93 static const TargetRegisterClass * const CalleeSavedRegClassesV2[] = { 94 &Hexagon::IntRegsRegClass, &Hexagon::IntRegsRegClass, 95 &Hexagon::IntRegsRegClass, &Hexagon::IntRegsRegClass, 96 }; 97 static const TargetRegisterClass * const CalleeSavedRegClassesV3[] = { 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 &Hexagon::IntRegsRegClass, &Hexagon::IntRegsRegClass, 104 }; 105 106 switch(Subtarget.getHexagonArchVersion()) { 107 case HexagonSubtarget::V1: 108 break; 109 case HexagonSubtarget::V2: 110 return CalleeSavedRegClassesV2; 111 case HexagonSubtarget::V3: 112 case HexagonSubtarget::V4: 113 return CalleeSavedRegClassesV3; 114 } 115 llvm_unreachable("Callee saved register classes requested for unknown " 116 "architecture version"); 117 } 118 119 void HexagonRegisterInfo:: 120 eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, 121 MachineBasicBlock::iterator I) const { 122 MachineInstr &MI = *I; 123 124 if (MI.getOpcode() == Hexagon::ADJCALLSTACKDOWN) { 125 // Hexagon_TODO: add code 126 } else if (MI.getOpcode() == Hexagon::ADJCALLSTACKUP) { 127 // Hexagon_TODO: add code 128 } else { 129 assert(0 && "Cannot handle this call frame pseudo instruction"); 130 } 131 MBB.erase(I); 132 } 133 134 void HexagonRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, 135 int SPAdj, RegScavenger *RS) const { 136 137 // 138 // Hexagon_TODO: Do we need to enforce this for Hexagon? 139 assert(SPAdj == 0 && "Unexpected"); 140 141 142 unsigned i = 0; 143 MachineInstr &MI = *II; 144 while (!MI.getOperand(i).isFI()) { 145 ++i; 146 assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!"); 147 } 148 149 int FrameIndex = MI.getOperand(i).getIndex(); 150 151 // Addressable stack objects are accessed using neg. offsets from %fp. 152 MachineFunction &MF = *MI.getParent()->getParent(); 153 int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex); 154 MachineFrameInfo &MFI = *MF.getFrameInfo(); 155 156 unsigned FrameReg = getFrameRegister(MF); 157 const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering(); 158 if (!TFI->hasFP(MF)) { 159 // We will not reserve space on the stack for the lr and fp registers. 160 Offset -= 2 * Hexagon_WordSize; 161 } 162 163 const unsigned FrameSize = MFI.getStackSize(); 164 165 if (!MFI.hasVarSizedObjects() && 166 TII.isValidOffset(MI.getOpcode(), (FrameSize+Offset)) && 167 !TII.isSpillPredRegOp(&MI)) { 168 // Replace frame index with a stack pointer reference. 169 MI.getOperand(i).ChangeToRegister(getStackRegister(), false, false, true); 170 MI.getOperand(i+1).ChangeToImmediate(FrameSize+Offset); 171 } else { 172 // Replace frame index with a frame pointer reference. 173 if (!TII.isValidOffset(MI.getOpcode(), Offset)) { 174 175 // If the offset overflows, then correct it. 176 // 177 // For loads, we do not need a reserved register 178 // r0 = memw(r30 + #10000) to: 179 // 180 // r0 = add(r30, #10000) 181 // r0 = memw(r0) 182 if ( (MI.getOpcode() == Hexagon::LDriw) || 183 (MI.getOpcode() == Hexagon::LDrid) || 184 (MI.getOpcode() == Hexagon::LDrih) || 185 (MI.getOpcode() == Hexagon::LDriuh) || 186 (MI.getOpcode() == Hexagon::LDrib) || 187 (MI.getOpcode() == Hexagon::LDriub) ) { 188 unsigned dstReg = (MI.getOpcode() == Hexagon::LDrid) ? 189 *getSubRegisters(MI.getOperand(0).getReg()) : 190 MI.getOperand(0).getReg(); 191 192 // Check if offset can fit in addi. 193 if (!TII.isValidOffset(Hexagon::ADD_ri, Offset)) { 194 BuildMI(*MI.getParent(), II, MI.getDebugLoc(), 195 TII.get(Hexagon::CONST32_Int_Real), dstReg).addImm(Offset); 196 BuildMI(*MI.getParent(), II, MI.getDebugLoc(), 197 TII.get(Hexagon::ADD_rr), 198 dstReg).addReg(FrameReg).addReg(dstReg); 199 } else { 200 BuildMI(*MI.getParent(), II, MI.getDebugLoc(), 201 TII.get(Hexagon::ADD_ri), 202 dstReg).addReg(FrameReg).addImm(Offset); 203 } 204 205 MI.getOperand(i).ChangeToRegister(dstReg, false, false, true); 206 MI.getOperand(i+1).ChangeToImmediate(0); 207 } else if ((MI.getOpcode() == Hexagon::STriw) || 208 (MI.getOpcode() == Hexagon::STrid) || 209 (MI.getOpcode() == Hexagon::STrih) || 210 (MI.getOpcode() == Hexagon::STrib) || 211 (MI.getOpcode() == Hexagon::STriwt)) { 212 // For stores, we need a reserved register. Change 213 // memw(r30 + #10000) = r0 to: 214 // 215 // rs = add(r30, #10000); 216 // memw(rs) = r0 217 unsigned resReg = HEXAGON_RESERVED_REG_1; 218 219 // Check if offset can fit in addi. 220 if (!TII.isValidOffset(Hexagon::ADD_ri, Offset)) { 221 BuildMI(*MI.getParent(), II, MI.getDebugLoc(), 222 TII.get(Hexagon::CONST32_Int_Real), resReg).addImm(Offset); 223 BuildMI(*MI.getParent(), II, MI.getDebugLoc(), 224 TII.get(Hexagon::ADD_rr), 225 resReg).addReg(FrameReg).addReg(resReg); 226 } else { 227 BuildMI(*MI.getParent(), II, MI.getDebugLoc(), 228 TII.get(Hexagon::ADD_ri), 229 resReg).addReg(FrameReg).addImm(Offset); 230 } 231 MI.getOperand(i).ChangeToRegister(resReg, false, false, true); 232 MI.getOperand(i+1).ChangeToImmediate(0); 233 } else if (TII.isMemOp(&MI)) { 234 unsigned resReg = HEXAGON_RESERVED_REG_1; 235 if (!MFI.hasVarSizedObjects() && 236 TII.isValidOffset(MI.getOpcode(), (FrameSize+Offset))) { 237 MI.getOperand(i).ChangeToRegister(getStackRegister(), false, false, 238 true); 239 MI.getOperand(i+1).ChangeToImmediate(FrameSize+Offset); 240 } else if (!TII.isValidOffset(Hexagon::ADD_ri, Offset)) { 241 BuildMI(*MI.getParent(), II, MI.getDebugLoc(), 242 TII.get(Hexagon::CONST32_Int_Real), resReg).addImm(Offset); 243 BuildMI(*MI.getParent(), II, MI.getDebugLoc(), 244 TII.get(Hexagon::ADD_rr), 245 resReg).addReg(FrameReg).addReg(resReg); 246 MI.getOperand(i).ChangeToRegister(resReg, false, false, true); 247 MI.getOperand(i+1).ChangeToImmediate(0); 248 } else { 249 BuildMI(*MI.getParent(), II, MI.getDebugLoc(), 250 TII.get(Hexagon::ADD_ri), 251 resReg).addReg(FrameReg).addImm(Offset); 252 MI.getOperand(i).ChangeToRegister(resReg, false, false, true); 253 MI.getOperand(i+1).ChangeToImmediate(0); 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(i).ChangeToRegister(dstReg, false, false, true); 264 MI.getOperand(i+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(i).ChangeToRegister(FrameReg, false); 270 MI.getOperand(i+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 void HexagonRegisterInfo::getInitialFrameState(std::vector<MachineMove> 299 &Moves) const 300 { 301 // VirtualFP = (R30 + #0). 302 unsigned FPReg = getFrameRegister(); 303 MachineLocation Dst(MachineLocation::VirtualFP); 304 MachineLocation Src(FPReg, 0); 305 Moves.push_back(MachineMove(0, Dst, Src)); 306 } 307 308 unsigned HexagonRegisterInfo::getEHExceptionRegister() const { 309 assert(0 && "What is the exception register"); 310 return 0; 311 } 312 313 unsigned HexagonRegisterInfo::getEHHandlerRegister() const { 314 assert(0 && "What is the exception handler register"); 315 return 0; 316 } 317 318 #define GET_REGINFO_TARGET_DESC 319 #include "HexagonGenRegisterInfo.inc" 320