1 //===-- LanaiRegisterInfo.cpp - Lanai Register Information ------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file contains the Lanai implementation of the TargetRegisterInfo class. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "LanaiRegisterInfo.h" 14 #include "LanaiAluCode.h" 15 #include "LanaiCondCode.h" 16 #include "LanaiFrameLowering.h" 17 #include "LanaiInstrInfo.h" 18 #include "llvm/ADT/BitVector.h" 19 #include "llvm/ADT/STLExtras.h" 20 #include "llvm/CodeGen/MachineFrameInfo.h" 21 #include "llvm/CodeGen/MachineFunction.h" 22 #include "llvm/CodeGen/MachineInstrBuilder.h" 23 #include "llvm/CodeGen/RegisterScavenging.h" 24 #include "llvm/CodeGen/TargetFrameLowering.h" 25 #include "llvm/CodeGen/TargetInstrInfo.h" 26 #include "llvm/IR/Function.h" 27 #include "llvm/IR/Type.h" 28 #include "llvm/Support/ErrorHandling.h" 29 30 #define GET_REGINFO_TARGET_DESC 31 #include "LanaiGenRegisterInfo.inc" 32 33 using namespace llvm; 34 35 LanaiRegisterInfo::LanaiRegisterInfo() : 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 Register 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 BuildMI(*MI.getParent(), II, DL, 202 HasNegOffset ? TII->get(Lanai::SUB_R) : TII->get(Lanai::ADD_R), 203 MI.getOperand(0).getReg()) 204 .addReg(FrameReg) 205 .addReg(Reg) 206 .addImm(LPCC::ICC_T); 207 MI.eraseFromParent(); 208 return; 209 } 210 if (isSPLSOpcode(MI.getOpcode()) || isRMOpcode(MI.getOpcode())) { 211 MI.setDesc(TII->get(getRRMOpcodeVariant(MI.getOpcode()))); 212 if (HasNegOffset) { 213 // Change the ALU op (operand 3) from LPAC::ADD (the default) to 214 // LPAC::SUB with the already negated offset. 215 assert((MI.getOperand(3).getImm() == LPAC::ADD) && 216 "Unexpected ALU op in RRM instruction"); 217 MI.getOperand(3).setImm(LPAC::SUB); 218 } 219 } else 220 llvm_unreachable("Unexpected opcode in frame index operation"); 221 222 MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, /*isDef=*/false); 223 MI.getOperand(FIOperandNum + 1) 224 .ChangeToRegister(Reg, /*isDef=*/false, /*isImp=*/false, 225 /*isKill=*/true); 226 return; 227 } 228 229 // ALU arithmetic ops take unsigned immediates. If the offset is negative, 230 // we replace the instruction with one that inverts the opcode and negates 231 // the immediate. 232 if ((Offset < 0) && isALUArithLoOpcode(MI.getOpcode())) { 233 unsigned NewOpcode = getOppositeALULoOpcode(MI.getOpcode()); 234 // We know this is an ALU op, so we know the operands are as follows: 235 // 0: destination register 236 // 1: source register (frame register) 237 // 2: immediate 238 BuildMI(*MI.getParent(), II, DL, TII->get(NewOpcode), 239 MI.getOperand(0).getReg()) 240 .addReg(FrameReg) 241 .addImm(-Offset); 242 MI.eraseFromParent(); 243 } else { 244 MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, /*isDef=*/false); 245 MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset); 246 } 247 } 248 249 bool LanaiRegisterInfo::hasBasePointer(const MachineFunction &MF) const { 250 const MachineFrameInfo &MFI = MF.getFrameInfo(); 251 // When we need stack realignment and there are dynamic allocas, we can't 252 // reference off of the stack pointer, so we reserve a base pointer. 253 if (needsStackRealignment(MF) && MFI.hasVarSizedObjects()) 254 return true; 255 256 return false; 257 } 258 259 unsigned LanaiRegisterInfo::getRARegister() const { return Lanai::RCA; } 260 261 Register 262 LanaiRegisterInfo::getFrameRegister(const MachineFunction & /*MF*/) const { 263 return Lanai::FP; 264 } 265 266 Register LanaiRegisterInfo::getBaseRegister() const { return Lanai::R14; } 267 268 const uint32_t * 269 LanaiRegisterInfo::getCallPreservedMask(const MachineFunction & /*MF*/, 270 CallingConv::ID /*CC*/) const { 271 return CSR_RegMask; 272 } 273