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::V2: 62 return CalleeSavedRegsV2; 63 break; 64 case HexagonSubtarget::V3: 65 case HexagonSubtarget::V4: 66 return CalleeSavedRegsV3; 67 break; 68 default: 69 const char *ErrorString = 70 "Callee saved registers requested for unknown archtecture version"; 71 llvm_unreachable(ErrorString); 72 } 73 } 74 75 BitVector HexagonRegisterInfo::getReservedRegs(const MachineFunction &MF) 76 const { 77 BitVector Reserved(getNumRegs()); 78 Reserved.set(HEXAGON_RESERVED_REG_1); 79 Reserved.set(HEXAGON_RESERVED_REG_2); 80 Reserved.set(Hexagon::R29); 81 Reserved.set(Hexagon::R30); 82 Reserved.set(Hexagon::R31); 83 Reserved.set(Hexagon::D14); 84 Reserved.set(Hexagon::D15); 85 Reserved.set(Hexagon::LC0); 86 Reserved.set(Hexagon::LC1); 87 Reserved.set(Hexagon::SA0); 88 Reserved.set(Hexagon::SA1); 89 return Reserved; 90 } 91 92 93 const TargetRegisterClass* const* 94 HexagonRegisterInfo::getCalleeSavedRegClasses(const MachineFunction *MF) const { 95 static const TargetRegisterClass * const CalleeSavedRegClassesV2[] = { 96 &Hexagon::IntRegsRegClass, &Hexagon::IntRegsRegClass, 97 &Hexagon::IntRegsRegClass, &Hexagon::IntRegsRegClass, 98 }; 99 static const TargetRegisterClass * const CalleeSavedRegClassesV3[] = { 100 &Hexagon::IntRegsRegClass, &Hexagon::IntRegsRegClass, 101 &Hexagon::IntRegsRegClass, &Hexagon::IntRegsRegClass, 102 &Hexagon::IntRegsRegClass, &Hexagon::IntRegsRegClass, 103 &Hexagon::IntRegsRegClass, &Hexagon::IntRegsRegClass, 104 &Hexagon::IntRegsRegClass, &Hexagon::IntRegsRegClass, 105 &Hexagon::IntRegsRegClass, &Hexagon::IntRegsRegClass, 106 }; 107 108 switch(Subtarget.getHexagonArchVersion()) { 109 case HexagonSubtarget::V2: 110 return CalleeSavedRegClassesV2; 111 break; 112 case HexagonSubtarget::V3: 113 case HexagonSubtarget::V4: 114 return CalleeSavedRegClassesV3; 115 break; 116 default: 117 const char *ErrorString = 118 "Callee saved register classes requested for unknown archtecture version"; 119 llvm_unreachable(ErrorString); 120 } 121 } 122 123 void HexagonRegisterInfo:: 124 eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, 125 MachineBasicBlock::iterator I) const { 126 MachineInstr &MI = *I; 127 128 if (MI.getOpcode() == Hexagon::ADJCALLSTACKDOWN) { 129 // Hexagon_TODO: add code 130 } else if (MI.getOpcode() == Hexagon::ADJCALLSTACKUP) { 131 // Hexagon_TODO: add code 132 } else { 133 assert(0 && "Cannot handle this call frame pseudo instruction"); 134 } 135 MBB.erase(I); 136 } 137 138 void HexagonRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, 139 int SPAdj, RegScavenger *RS) const { 140 141 // 142 // Hexagon_TODO: Do we need to enforce this for Hexagon? 143 assert(SPAdj == 0 && "Unexpected"); 144 145 146 unsigned i = 0; 147 MachineInstr &MI = *II; 148 while (!MI.getOperand(i).isFI()) { 149 ++i; 150 assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!"); 151 } 152 153 int FrameIndex = MI.getOperand(i).getIndex(); 154 155 // Addressable stack objects are accessed using neg. offsets from %fp. 156 MachineFunction &MF = *MI.getParent()->getParent(); 157 int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex); 158 MachineFrameInfo &MFI = *MF.getFrameInfo(); 159 160 unsigned FrameReg = getFrameRegister(MF); 161 const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering(); 162 if (!TFI->hasFP(MF)) { 163 // We will not reserve space on the stack for the lr and fp registers. 164 Offset -= 2 * Hexagon_WordSize; 165 } 166 167 const unsigned FrameSize = MFI.getStackSize(); 168 169 if (!MFI.hasVarSizedObjects() && 170 TII.isValidOffset(MI.getOpcode(), (FrameSize+Offset)) && 171 !TII.isSpillPredRegOp(&MI)) { 172 // Replace frame index with a stack pointer reference. 173 MI.getOperand(i).ChangeToRegister(getStackRegister(), false, false, true); 174 MI.getOperand(i+1).ChangeToImmediate(FrameSize+Offset); 175 } else { 176 // Replace frame index with a frame pointer reference. 177 if (!TII.isValidOffset(MI.getOpcode(), Offset)) { 178 179 // If the offset overflows, then correct it. 180 // 181 // For loads, we do not need a reserved register 182 // r0 = memw(r30 + #10000) to: 183 // 184 // r0 = add(r30, #10000) 185 // r0 = memw(r0) 186 if ( (MI.getOpcode() == Hexagon::LDriw) || 187 (MI.getOpcode() == Hexagon::LDrid) || 188 (MI.getOpcode() == Hexagon::LDrih) || 189 (MI.getOpcode() == Hexagon::LDriuh) || 190 (MI.getOpcode() == Hexagon::LDrib) || 191 (MI.getOpcode() == Hexagon::LDriub) ) { 192 unsigned dstReg = (MI.getOpcode() == Hexagon::LDrid) ? 193 *getSubRegisters(MI.getOperand(0).getReg()) : 194 MI.getOperand(0).getReg(); 195 196 // Check if offset can fit in addi. 197 if (!TII.isValidOffset(Hexagon::ADD_ri, Offset)) { 198 BuildMI(*MI.getParent(), II, MI.getDebugLoc(), 199 TII.get(Hexagon::CONST32_Int_Real), dstReg).addImm(Offset); 200 BuildMI(*MI.getParent(), II, MI.getDebugLoc(), 201 TII.get(Hexagon::ADD_rr), 202 dstReg).addReg(FrameReg).addReg(dstReg); 203 } else { 204 BuildMI(*MI.getParent(), II, MI.getDebugLoc(), 205 TII.get(Hexagon::ADD_ri), 206 dstReg).addReg(FrameReg).addImm(Offset); 207 } 208 209 MI.getOperand(i).ChangeToRegister(dstReg, false, false, true); 210 MI.getOperand(i+1).ChangeToImmediate(0); 211 } else if ((MI.getOpcode() == Hexagon::STriw) || 212 (MI.getOpcode() == Hexagon::STrid) || 213 (MI.getOpcode() == Hexagon::STrih) || 214 (MI.getOpcode() == Hexagon::STrib) || 215 (MI.getOpcode() == Hexagon::STriwt)) { 216 // For stores, we need a reserved register. Change 217 // memw(r30 + #10000) = r0 to: 218 // 219 // rs = add(r30, #10000); 220 // memw(rs) = r0 221 unsigned resReg = HEXAGON_RESERVED_REG_1; 222 223 // Check if offset can fit in addi. 224 if (!TII.isValidOffset(Hexagon::ADD_ri, Offset)) { 225 BuildMI(*MI.getParent(), II, MI.getDebugLoc(), 226 TII.get(Hexagon::CONST32_Int_Real), resReg).addImm(Offset); 227 BuildMI(*MI.getParent(), II, MI.getDebugLoc(), 228 TII.get(Hexagon::ADD_rr), 229 resReg).addReg(FrameReg).addReg(resReg); 230 } else { 231 BuildMI(*MI.getParent(), II, MI.getDebugLoc(), 232 TII.get(Hexagon::ADD_ri), 233 resReg).addReg(FrameReg).addImm(Offset); 234 } 235 MI.getOperand(i).ChangeToRegister(resReg, false, false, true); 236 MI.getOperand(i+1).ChangeToImmediate(0); 237 } else if (TII.isMemOp(&MI)) { 238 unsigned resReg = HEXAGON_RESERVED_REG_1; 239 if (!MFI.hasVarSizedObjects() && 240 TII.isValidOffset(MI.getOpcode(), (FrameSize+Offset))) { 241 MI.getOperand(i).ChangeToRegister(getStackRegister(), false, false, 242 true); 243 MI.getOperand(i+1).ChangeToImmediate(FrameSize+Offset); 244 } else if (!TII.isValidOffset(Hexagon::ADD_ri, Offset)) { 245 BuildMI(*MI.getParent(), II, MI.getDebugLoc(), 246 TII.get(Hexagon::CONST32_Int_Real), resReg).addImm(Offset); 247 BuildMI(*MI.getParent(), II, MI.getDebugLoc(), 248 TII.get(Hexagon::ADD_rr), 249 resReg).addReg(FrameReg).addReg(resReg); 250 MI.getOperand(i).ChangeToRegister(resReg, false, false, true); 251 MI.getOperand(i+1).ChangeToImmediate(0); 252 } else { 253 BuildMI(*MI.getParent(), II, MI.getDebugLoc(), 254 TII.get(Hexagon::ADD_ri), 255 resReg).addReg(FrameReg).addImm(Offset); 256 MI.getOperand(i).ChangeToRegister(resReg, false, false, true); 257 MI.getOperand(i+1).ChangeToImmediate(0); 258 } 259 } else { 260 unsigned dstReg = MI.getOperand(0).getReg(); 261 BuildMI(*MI.getParent(), II, MI.getDebugLoc(), 262 TII.get(Hexagon::CONST32_Int_Real), dstReg).addImm(Offset); 263 BuildMI(*MI.getParent(), II, MI.getDebugLoc(), 264 TII.get(Hexagon::ADD_rr), 265 dstReg).addReg(FrameReg).addReg(dstReg); 266 // Can we delete MI??? r2 = add (r2, #0). 267 MI.getOperand(i).ChangeToRegister(dstReg, false, false, true); 268 MI.getOperand(i+1).ChangeToImmediate(0); 269 } 270 } else { 271 // If the offset is small enough to fit in the immediate field, directly 272 // encode it. 273 MI.getOperand(i).ChangeToRegister(FrameReg, false); 274 MI.getOperand(i+1).ChangeToImmediate(Offset); 275 } 276 } 277 278 } 279 280 unsigned HexagonRegisterInfo::getRARegister() const { 281 return Hexagon::R31; 282 } 283 284 unsigned HexagonRegisterInfo::getFrameRegister(const MachineFunction 285 &MF) const { 286 const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering(); 287 if (TFI->hasFP(MF)) { 288 return Hexagon::R30; 289 } 290 291 return Hexagon::R29; 292 } 293 294 unsigned HexagonRegisterInfo::getFrameRegister() const { 295 return Hexagon::R30; 296 } 297 298 unsigned HexagonRegisterInfo::getStackRegister() const { 299 return Hexagon::R29; 300 } 301 302 void HexagonRegisterInfo::getInitialFrameState(std::vector<MachineMove> 303 &Moves) const 304 { 305 // VirtualFP = (R30 + #0). 306 unsigned FPReg = getFrameRegister(); 307 MachineLocation Dst(MachineLocation::VirtualFP); 308 MachineLocation Src(FPReg, 0); 309 Moves.push_back(MachineMove(0, Dst, Src)); 310 } 311 312 unsigned HexagonRegisterInfo::getEHExceptionRegister() const { 313 assert(0 && "What is the exception register"); 314 return 0; 315 } 316 317 unsigned HexagonRegisterInfo::getEHHandlerRegister() const { 318 assert(0 && "What is the exception handler register"); 319 return 0; 320 } 321 322 #include "HexagonGenRegisterInfo.inc" 323