1 //===-- LanaiRegisterInfo.cpp - Lanai 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 Lanai implementation of the TargetRegisterInfo class. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "Lanai.h" 15 #include "LanaiRegisterInfo.h" 16 #include "LanaiSubtarget.h" 17 #include "llvm/ADT/BitVector.h" 18 #include "llvm/ADT/STLExtras.h" 19 #include "llvm/CodeGen/MachineFrameInfo.h" 20 #include "llvm/CodeGen/MachineFunction.h" 21 #include "llvm/CodeGen/MachineInstrBuilder.h" 22 #include "llvm/CodeGen/RegisterScavenging.h" 23 #include "llvm/IR/Function.h" 24 #include "llvm/IR/Type.h" 25 #include "llvm/Support/ErrorHandling.h" 26 #include "llvm/Target/TargetFrameLowering.h" 27 #include "llvm/Target/TargetInstrInfo.h" 28 29 #define GET_REGINFO_TARGET_DESC 30 #include "LanaiGenRegisterInfo.inc" 31 32 using namespace llvm; 33 34 LanaiRegisterInfo::LanaiRegisterInfo() 35 : LanaiGenRegisterInfo(Lanai::RCA) {} 36 37 const uint16_t * 38 LanaiRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { 39 return CSR_SaveList; 40 } 41 42 BitVector LanaiRegisterInfo::getReservedRegs(const MachineFunction &MF) const { 43 BitVector Reserved(getNumRegs()); 44 45 Reserved.set(Lanai::R0); 46 Reserved.set(Lanai::R1); 47 Reserved.set(Lanai::PC); 48 Reserved.set(Lanai::R2); 49 Reserved.set(Lanai::SP); 50 Reserved.set(Lanai::R4); 51 Reserved.set(Lanai::FP); 52 Reserved.set(Lanai::R5); 53 Reserved.set(Lanai::RR1); 54 Reserved.set(Lanai::R10); 55 Reserved.set(Lanai::RR2); 56 Reserved.set(Lanai::R11); 57 Reserved.set(Lanai::RCA); 58 Reserved.set(Lanai::R15); 59 if (hasBasePointer(MF)) 60 Reserved.set(getBaseRegister()); 61 return Reserved; 62 } 63 64 bool LanaiRegisterInfo::requiresRegisterScavenging( 65 const MachineFunction &MF) const { 66 return true; 67 } 68 69 bool LanaiRegisterInfo::trackLivenessAfterRegAlloc( 70 const MachineFunction &MF) const { 71 return true; 72 } 73 74 static bool isALUArithLoOpcode(unsigned Opcode) { 75 switch (Opcode) { 76 case Lanai::ADD_I_LO: 77 case Lanai::SUB_I_LO: 78 case Lanai::ADD_F_I_LO: 79 case Lanai::SUB_F_I_LO: 80 case Lanai::ADDC_I_LO: 81 case Lanai::SUBB_I_LO: 82 case Lanai::ADDC_F_I_LO: 83 case Lanai::SUBB_F_I_LO: 84 return true; 85 default: 86 return false; 87 } 88 } 89 90 static unsigned getOppositeALULoOpcode(unsigned Opcode) { 91 switch (Opcode) { 92 case Lanai::ADD_I_LO: 93 return Lanai::SUB_I_LO; 94 case Lanai::SUB_I_LO: 95 return Lanai::ADD_I_LO; 96 case Lanai::ADD_F_I_LO: 97 return Lanai::SUB_F_I_LO; 98 case Lanai::SUB_F_I_LO: 99 return Lanai::ADD_F_I_LO; 100 case Lanai::ADDC_I_LO: 101 return Lanai::SUBB_I_LO; 102 case Lanai::SUBB_I_LO: 103 return Lanai::ADDC_I_LO; 104 case Lanai::ADDC_F_I_LO: 105 return Lanai::SUBB_F_I_LO; 106 case Lanai::SUBB_F_I_LO: 107 return Lanai::ADDC_F_I_LO; 108 default: 109 llvm_unreachable("Invalid ALU lo opcode"); 110 } 111 } 112 113 static unsigned getRRMOpcodeVariant(unsigned Opcode) { 114 switch (Opcode) { 115 case Lanai::LDBs_RI: 116 return Lanai::LDBs_RR; 117 case Lanai::LDBz_RI: 118 return Lanai::LDBz_RR; 119 case Lanai::LDHs_RI: 120 return Lanai::LDHs_RR; 121 case Lanai::LDHz_RI: 122 return Lanai::LDHz_RR; 123 case Lanai::LDW_RI: 124 return Lanai::LDW_RR; 125 case Lanai::STB_RI: 126 return Lanai::STB_RR; 127 case Lanai::STH_RI: 128 return Lanai::STH_RR; 129 case Lanai::SW_RI: 130 return Lanai::SW_RR; 131 default: 132 llvm_unreachable("Opcode has no RRM variant"); 133 } 134 } 135 136 void LanaiRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, 137 int SPAdj, unsigned FIOperandNum, 138 RegScavenger *RS) const { 139 assert(SPAdj == 0 && "Unexpected"); 140 141 MachineInstr &MI = *II; 142 MachineFunction &MF = *MI.getParent()->getParent(); 143 const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo(); 144 const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering(); 145 bool HasFP = TFI->hasFP(MF); 146 DebugLoc DL = MI.getDebugLoc(); 147 148 int FrameIndex = MI.getOperand(FIOperandNum).getIndex(); 149 150 int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex) + 151 MI.getOperand(FIOperandNum + 1).getImm(); 152 153 // Addressable stack objects are addressed using neg. offsets from fp 154 // or pos. offsets from sp/basepointer 155 if (!HasFP || (needsStackRealignment(MF) && FrameIndex >= 0)) 156 Offset += MF.getFrameInfo()->getStackSize(); 157 158 unsigned FrameReg = getFrameRegister(MF); 159 if (FrameIndex >= 0) { 160 if (hasBasePointer(MF)) 161 FrameReg = getBaseRegister(); 162 else if (needsStackRealignment(MF)) 163 FrameReg = Lanai::SP; 164 } 165 166 // Replace frame index with a frame pointer reference. 167 // If the offset is small enough to fit in the immediate field, directly 168 // encode it. 169 // Otherwise scavenge a register and encode it into a MOVHI, OR_I_LO sequence. 170 if ((isSPLSOpcode(MI.getOpcode()) && !isInt<10>(Offset)) || 171 !isInt<16>(Offset)) { 172 assert(RS && "Register scavenging must be on"); 173 unsigned Reg = RS->FindUnusedReg(&Lanai::GPRRegClass); 174 if (!Reg) 175 Reg = RS->scavengeRegister(&Lanai::GPRRegClass, II, SPAdj); 176 assert(Reg && "Register scavenger failed"); 177 178 bool HasNegOffset = false; 179 // ALU ops have unsigned immediate values. If the Offset is negative, we 180 // negate it here and reverse the opcode later. 181 if (Offset < 0) { 182 HasNegOffset = true; 183 Offset = -Offset; 184 } 185 186 if (!isInt<16>(Offset)) { 187 // Reg = hi(offset) | lo(offset) 188 BuildMI(*MI.getParent(), II, DL, TII->get(Lanai::MOVHI), Reg) 189 .addImm(static_cast<uint32_t>(Offset) >> 16); 190 BuildMI(*MI.getParent(), II, DL, TII->get(Lanai::OR_I_LO), Reg) 191 .addReg(Reg) 192 .addImm(Offset & 0xffffU); 193 } else { 194 // Reg = mov(offset) 195 BuildMI(*MI.getParent(), II, DL, TII->get(Lanai::ADD_I_LO), Reg) 196 .addImm(0) 197 .addImm(Offset); 198 } 199 // Reg = FrameReg OP Reg 200 if (MI.getOpcode() == Lanai::ADD_I_LO) { 201 if (HasNegOffset) 202 MI.setDesc(TII->get(Lanai::SUB_R)); 203 else 204 MI.setDesc(TII->get(Lanai::ADD_R)); 205 } else if (isSPLSOpcode(MI.getOpcode()) || isRMOpcode(MI.getOpcode())) { 206 MI.setDesc(TII->get(getRRMOpcodeVariant(MI.getOpcode()))); 207 if (HasNegOffset) { 208 // Change the ALU op (operand 3) from LPAC::ADD (the default) to 209 // LPAC::SUB with the already negated offset. 210 assert((MI.getOperand(3).getImm() == LPAC::ADD) && 211 "Unexpected ALU op in RRM instruction"); 212 MI.getOperand(3).setImm(LPAC::SUB); 213 } 214 } else 215 llvm_unreachable("Unexpected opcode in frame index operation"); 216 217 MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, /*isDef=*/false); 218 MI.getOperand(FIOperandNum + 1) 219 .ChangeToRegister(Reg, /*isDef=*/false, /*isImp=*/false, 220 /*isKill=*/true); 221 return; 222 } 223 224 // ALU arithmetic ops take unsigned immediates. If the offset is negative, 225 // we replace the instruction with one that inverts the opcode and negates 226 // the immediate. 227 if ((Offset < 0) && isALUArithLoOpcode(MI.getOpcode())) { 228 unsigned NewOpcode = getOppositeALULoOpcode(MI.getOpcode()); 229 // We know this is an ALU op, so we know the operands are as follows: 230 // 0: destination register 231 // 1: source register (frame register) 232 // 2: immediate 233 BuildMI(*MI.getParent(), II, DL, TII->get(NewOpcode), 234 MI.getOperand(0).getReg()) 235 .addReg(FrameReg) 236 .addImm(-Offset); 237 MI.eraseFromParent(); 238 } else { 239 MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, /*isDef=*/false); 240 MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset); 241 } 242 } 243 244 bool LanaiRegisterInfo::hasBasePointer(const MachineFunction &MF) const { 245 const MachineFrameInfo *MFI = MF.getFrameInfo(); 246 // When we need stack realignment and there are dynamic allocas, we can't 247 // reference off of the stack pointer, so we reserve a base pointer. 248 if (needsStackRealignment(MF) && MFI->hasVarSizedObjects()) 249 return true; 250 251 return false; 252 } 253 254 unsigned LanaiRegisterInfo::getRARegister() const { return Lanai::RCA; } 255 256 unsigned LanaiRegisterInfo::getFrameRegister(const MachineFunction &MF) const { 257 return Lanai::FP; 258 } 259 260 unsigned LanaiRegisterInfo::getBaseRegister() const { return Lanai::R14; } 261 262 bool LanaiRegisterInfo::canRealignStack(const MachineFunction &MF) const { 263 if (!TargetRegisterInfo::canRealignStack(MF)) 264 return false; 265 return true; 266 } 267 268 unsigned LanaiRegisterInfo::getEHExceptionRegister() const { 269 llvm_unreachable("no exception support"); 270 return 0; 271 } 272 273 unsigned LanaiRegisterInfo::getEHHandlerRegister() const { 274 llvm_unreachable("no exception support"); 275 return 0; 276 } 277 278 const uint32_t * 279 LanaiRegisterInfo::getCallPreservedMask(const MachineFunction &MF, 280 CallingConv::ID CC) const { 281 return CSR_RegMask; 282 } 283