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