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 static bool isALUArithLoOpcode(unsigned Opcode) { 70 switch (Opcode) { 71 case Lanai::ADD_I_LO: 72 case Lanai::SUB_I_LO: 73 case Lanai::ADD_F_I_LO: 74 case Lanai::SUB_F_I_LO: 75 case Lanai::ADDC_I_LO: 76 case Lanai::SUBB_I_LO: 77 case Lanai::ADDC_F_I_LO: 78 case Lanai::SUBB_F_I_LO: 79 return true; 80 default: 81 return false; 82 } 83 } 84 85 static unsigned getOppositeALULoOpcode(unsigned Opcode) { 86 switch (Opcode) { 87 case Lanai::ADD_I_LO: 88 return Lanai::SUB_I_LO; 89 case Lanai::SUB_I_LO: 90 return Lanai::ADD_I_LO; 91 case Lanai::ADD_F_I_LO: 92 return Lanai::SUB_F_I_LO; 93 case Lanai::SUB_F_I_LO: 94 return Lanai::ADD_F_I_LO; 95 case Lanai::ADDC_I_LO: 96 return Lanai::SUBB_I_LO; 97 case Lanai::SUBB_I_LO: 98 return Lanai::ADDC_I_LO; 99 case Lanai::ADDC_F_I_LO: 100 return Lanai::SUBB_F_I_LO; 101 case Lanai::SUBB_F_I_LO: 102 return Lanai::ADDC_F_I_LO; 103 default: 104 llvm_unreachable("Invalid ALU lo opcode"); 105 } 106 } 107 108 static unsigned getRRMOpcodeVariant(unsigned Opcode) { 109 switch (Opcode) { 110 case Lanai::LDBs_RI: 111 return Lanai::LDBs_RR; 112 case Lanai::LDBz_RI: 113 return Lanai::LDBz_RR; 114 case Lanai::LDHs_RI: 115 return Lanai::LDHs_RR; 116 case Lanai::LDHz_RI: 117 return Lanai::LDHz_RR; 118 case Lanai::LDW_RI: 119 return Lanai::LDW_RR; 120 case Lanai::STB_RI: 121 return Lanai::STB_RR; 122 case Lanai::STH_RI: 123 return Lanai::STH_RR; 124 case Lanai::SW_RI: 125 return Lanai::SW_RR; 126 default: 127 llvm_unreachable("Opcode has no RRM variant"); 128 } 129 } 130 131 void LanaiRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, 132 int SPAdj, unsigned FIOperandNum, 133 RegScavenger *RS) const { 134 assert(SPAdj == 0 && "Unexpected"); 135 136 MachineInstr &MI = *II; 137 MachineFunction &MF = *MI.getParent()->getParent(); 138 const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo(); 139 const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering(); 140 bool HasFP = TFI->hasFP(MF); 141 DebugLoc DL = MI.getDebugLoc(); 142 143 int FrameIndex = MI.getOperand(FIOperandNum).getIndex(); 144 145 int Offset = MF.getFrameInfo().getObjectOffset(FrameIndex) + 146 MI.getOperand(FIOperandNum + 1).getImm(); 147 148 // Addressable stack objects are addressed using neg. offsets from fp 149 // or pos. offsets from sp/basepointer 150 if (!HasFP || (hasStackRealignment(MF) && FrameIndex >= 0)) 151 Offset += MF.getFrameInfo().getStackSize(); 152 153 Register FrameReg = getFrameRegister(MF); 154 if (FrameIndex >= 0) { 155 if (hasBasePointer(MF)) 156 FrameReg = getBaseRegister(); 157 else if (hasStackRealignment(MF)) 158 FrameReg = Lanai::SP; 159 } 160 161 // Replace frame index with a frame pointer reference. 162 // If the offset is small enough to fit in the immediate field, directly 163 // encode it. 164 // Otherwise scavenge a register and encode it into a MOVHI, OR_I_LO sequence. 165 if ((isSPLSOpcode(MI.getOpcode()) && !isInt<10>(Offset)) || 166 !isInt<16>(Offset)) { 167 assert(RS && "Register scavenging must be on"); 168 Register Reg = RS->FindUnusedReg(&Lanai::GPRRegClass); 169 if (!Reg) 170 Reg = RS->scavengeRegister(&Lanai::GPRRegClass, II, SPAdj); 171 assert(Reg && "Register scavenger failed"); 172 173 bool HasNegOffset = false; 174 // ALU ops have unsigned immediate values. If the Offset is negative, we 175 // negate it here and reverse the opcode later. 176 if (Offset < 0) { 177 HasNegOffset = true; 178 Offset = -Offset; 179 } 180 181 if (!isInt<16>(Offset)) { 182 // Reg = hi(offset) | lo(offset) 183 BuildMI(*MI.getParent(), II, DL, TII->get(Lanai::MOVHI), Reg) 184 .addImm(static_cast<uint32_t>(Offset) >> 16); 185 BuildMI(*MI.getParent(), II, DL, TII->get(Lanai::OR_I_LO), Reg) 186 .addReg(Reg) 187 .addImm(Offset & 0xffffU); 188 } else { 189 // Reg = mov(offset) 190 BuildMI(*MI.getParent(), II, DL, TII->get(Lanai::ADD_I_LO), Reg) 191 .addImm(0) 192 .addImm(Offset); 193 } 194 // Reg = FrameReg OP Reg 195 if (MI.getOpcode() == Lanai::ADD_I_LO) { 196 BuildMI(*MI.getParent(), II, DL, 197 HasNegOffset ? TII->get(Lanai::SUB_R) : TII->get(Lanai::ADD_R), 198 MI.getOperand(0).getReg()) 199 .addReg(FrameReg) 200 .addReg(Reg) 201 .addImm(LPCC::ICC_T); 202 MI.eraseFromParent(); 203 return; 204 } 205 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 (hasStackRealignment(MF) && MFI.hasVarSizedObjects()) 249 return true; 250 251 return false; 252 } 253 254 unsigned LanaiRegisterInfo::getRARegister() const { return Lanai::RCA; } 255 256 Register 257 LanaiRegisterInfo::getFrameRegister(const MachineFunction & /*MF*/) const { 258 return Lanai::FP; 259 } 260 261 Register LanaiRegisterInfo::getBaseRegister() const { return Lanai::R14; } 262 263 const uint32_t * 264 LanaiRegisterInfo::getCallPreservedMask(const MachineFunction & /*MF*/, 265 CallingConv::ID /*CC*/) const { 266 return CSR_RegMask; 267 } 268