1 //===- LoongArchRegisterInfo.cpp - LoongArch 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 LoongArch implementation of the TargetRegisterInfo 10 // class. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "LoongArchRegisterInfo.h" 15 #include "LoongArch.h" 16 #include "LoongArchInstrInfo.h" 17 #include "LoongArchSubtarget.h" 18 #include "MCTargetDesc/LoongArchBaseInfo.h" 19 #include "MCTargetDesc/LoongArchMCTargetDesc.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/Support/ErrorHandling.h" 27 28 using namespace llvm; 29 30 #define GET_REGINFO_TARGET_DESC 31 #include "LoongArchGenRegisterInfo.inc" 32 33 LoongArchRegisterInfo::LoongArchRegisterInfo(unsigned HwMode) 34 : LoongArchGenRegisterInfo(LoongArch::R1, /*DwarfFlavour*/ 0, 35 /*EHFlavor*/ 0, 36 /*PC*/ 0, HwMode) {} 37 38 const MCPhysReg * 39 LoongArchRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { 40 auto &Subtarget = MF->getSubtarget<LoongArchSubtarget>(); 41 42 if (MF->getFunction().getCallingConv() == CallingConv::GHC) 43 return CSR_NoRegs_SaveList; 44 switch (Subtarget.getTargetABI()) { 45 default: 46 llvm_unreachable("Unrecognized ABI"); 47 case LoongArchABI::ABI_ILP32S: 48 case LoongArchABI::ABI_LP64S: 49 return CSR_ILP32S_LP64S_SaveList; 50 case LoongArchABI::ABI_ILP32F: 51 case LoongArchABI::ABI_LP64F: 52 return CSR_ILP32F_LP64F_SaveList; 53 case LoongArchABI::ABI_ILP32D: 54 case LoongArchABI::ABI_LP64D: 55 return CSR_ILP32D_LP64D_SaveList; 56 } 57 } 58 59 const uint32_t * 60 LoongArchRegisterInfo::getCallPreservedMask(const MachineFunction &MF, 61 CallingConv::ID CC) const { 62 auto &Subtarget = MF.getSubtarget<LoongArchSubtarget>(); 63 64 if (CC == CallingConv::GHC) 65 return CSR_NoRegs_RegMask; 66 switch (Subtarget.getTargetABI()) { 67 default: 68 llvm_unreachable("Unrecognized ABI"); 69 case LoongArchABI::ABI_ILP32S: 70 case LoongArchABI::ABI_LP64S: 71 return CSR_ILP32S_LP64S_RegMask; 72 case LoongArchABI::ABI_ILP32F: 73 case LoongArchABI::ABI_LP64F: 74 return CSR_ILP32F_LP64F_RegMask; 75 case LoongArchABI::ABI_ILP32D: 76 case LoongArchABI::ABI_LP64D: 77 return CSR_ILP32D_LP64D_RegMask; 78 } 79 } 80 81 const uint32_t *LoongArchRegisterInfo::getNoPreservedMask() const { 82 return CSR_NoRegs_RegMask; 83 } 84 85 BitVector 86 LoongArchRegisterInfo::getReservedRegs(const MachineFunction &MF) const { 87 const LoongArchFrameLowering *TFI = getFrameLowering(MF); 88 BitVector Reserved(getNumRegs()); 89 90 // Use markSuperRegs to ensure any register aliases are also reserved 91 markSuperRegs(Reserved, LoongArch::R0); // zero 92 markSuperRegs(Reserved, LoongArch::R2); // tp 93 markSuperRegs(Reserved, LoongArch::R3); // sp 94 markSuperRegs(Reserved, LoongArch::R21); // non-allocatable 95 if (TFI->hasFP(MF)) 96 markSuperRegs(Reserved, LoongArch::R22); // fp 97 // Reserve the base register if we need to realign the stack and allocate 98 // variable-sized objects at runtime. 99 if (TFI->hasBP(MF)) 100 markSuperRegs(Reserved, LoongArchABI::getBPReg()); // bp 101 102 assert(checkAllSuperRegsMarked(Reserved)); 103 return Reserved; 104 } 105 106 Register 107 LoongArchRegisterInfo::getFrameRegister(const MachineFunction &MF) const { 108 const TargetFrameLowering *TFI = getFrameLowering(MF); 109 return TFI->hasFP(MF) ? LoongArch::R22 : LoongArch::R3; 110 } 111 112 bool LoongArchRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, 113 int SPAdj, 114 unsigned FIOperandNum, 115 RegScavenger *RS) const { 116 // TODO: this implementation is a temporary placeholder which does just 117 // enough to allow other aspects of code generation to be tested. 118 119 assert(SPAdj == 0 && "Unexpected non-zero SPAdj value"); 120 121 MachineInstr &MI = *II; 122 assert(MI.getOperand(FIOperandNum + 1).isImm() && 123 "Unexpected FI-consuming insn"); 124 125 MachineBasicBlock &MBB = *MI.getParent(); 126 MachineFunction &MF = *MI.getParent()->getParent(); 127 MachineRegisterInfo &MRI = MF.getRegInfo(); 128 const LoongArchSubtarget &STI = MF.getSubtarget<LoongArchSubtarget>(); 129 const LoongArchInstrInfo *TII = STI.getInstrInfo(); 130 const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering(); 131 DebugLoc DL = MI.getDebugLoc(); 132 bool IsLA64 = STI.is64Bit(); 133 unsigned MIOpc = MI.getOpcode(); 134 135 int FrameIndex = MI.getOperand(FIOperandNum).getIndex(); 136 Register FrameReg; 137 StackOffset Offset = 138 TFI->getFrameIndexReference(MF, FrameIndex, FrameReg) + 139 StackOffset::getFixed(MI.getOperand(FIOperandNum + 1).getImm()); 140 141 bool FrameRegIsKill = false; 142 143 if (!isInt<12>(Offset.getFixed())) { 144 unsigned Addi = IsLA64 ? LoongArch::ADDI_D : LoongArch::ADDI_W; 145 unsigned Add = IsLA64 ? LoongArch::ADD_D : LoongArch::ADD_W; 146 147 // The offset won't fit in an immediate, so use a scratch register instead. 148 // Modify Offset and FrameReg appropriately. 149 Register ScratchReg = MRI.createVirtualRegister(&LoongArch::GPRRegClass); 150 TII->movImm(MBB, II, DL, ScratchReg, Offset.getFixed()); 151 if (MIOpc == Addi) { 152 BuildMI(MBB, II, DL, TII->get(Add), MI.getOperand(0).getReg()) 153 .addReg(FrameReg) 154 .addReg(ScratchReg, RegState::Kill); 155 MI.eraseFromParent(); 156 return true; 157 } 158 BuildMI(MBB, II, DL, TII->get(Add), ScratchReg) 159 .addReg(FrameReg) 160 .addReg(ScratchReg, RegState::Kill); 161 Offset = StackOffset::getFixed(0); 162 FrameReg = ScratchReg; 163 FrameRegIsKill = true; 164 } 165 166 // Spill CFRs. 167 if (MIOpc == LoongArch::PseudoST_CFR) { 168 Register ScratchReg = MRI.createVirtualRegister(&LoongArch::GPRRegClass); 169 BuildMI(MBB, II, DL, TII->get(LoongArch::MOVCF2GR), ScratchReg) 170 .add(MI.getOperand(0)); 171 BuildMI(MBB, II, DL, TII->get(IsLA64 ? LoongArch::ST_D : LoongArch::ST_W)) 172 .addReg(ScratchReg, RegState::Kill) 173 .addReg(FrameReg) 174 .addImm(Offset.getFixed()); 175 MI.eraseFromParent(); 176 return true; 177 } 178 179 // Reload CFRs. 180 if (MIOpc == LoongArch::PseudoLD_CFR) { 181 Register ScratchReg = MRI.createVirtualRegister(&LoongArch::GPRRegClass); 182 BuildMI(MBB, II, DL, TII->get(IsLA64 ? LoongArch::LD_D : LoongArch::LD_W), 183 ScratchReg) 184 .addReg(FrameReg) 185 .addImm(Offset.getFixed()); 186 BuildMI(MBB, II, DL, TII->get(LoongArch::MOVGR2CF)) 187 .add(MI.getOperand(0)) 188 .addReg(ScratchReg, RegState::Kill); 189 MI.eraseFromParent(); 190 return true; 191 } 192 193 MI.getOperand(FIOperandNum) 194 .ChangeToRegister(FrameReg, false, false, FrameRegIsKill); 195 MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset.getFixed()); 196 return false; 197 } 198 199 bool LoongArchRegisterInfo::canRealignStack(const MachineFunction &MF) const { 200 if (!TargetRegisterInfo::canRealignStack(MF)) 201 return false; 202 203 const MachineRegisterInfo *MRI = &MF.getRegInfo(); 204 const LoongArchFrameLowering *TFI = getFrameLowering(MF); 205 206 // Stack realignment requires a frame pointer. If we already started 207 // register allocation with frame pointer elimination, it is too late now. 208 if (!MRI->canReserveReg(LoongArch::R22)) 209 return false; 210 211 // We may also need a base pointer if there are dynamic allocas or stack 212 // pointer adjustments around calls. 213 if (TFI->hasReservedCallFrame(MF)) 214 return true; 215 216 // A base pointer is required and allowed. Check that it isn't too late to 217 // reserve it. 218 return MRI->canReserveReg(LoongArchABI::getBPReg()); 219 } 220