261 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8//9// This file contains the LoongArch implementation of the TargetRegisterInfo10// 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 28using namespace llvm;29 30#define GET_REGINFO_TARGET_DESC31#include "LoongArchGenRegisterInfo.inc"32 33LoongArchRegisterInfo::LoongArchRegisterInfo(unsigned HwMode)34 : LoongArchGenRegisterInfo(LoongArch::R1, /*DwarfFlavour*/ 0,35 /*EHFlavor*/ 0,36 /*PC*/ 0, HwMode) {}37 38const MCPhysReg *39LoongArchRegisterInfo::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 if (MF->getFunction().getCallingConv() == CallingConv::PreserveMost)45 return CSR_MostRegs_SaveList;46 switch (Subtarget.getTargetABI()) {47 default:48 llvm_unreachable("Unrecognized ABI");49 case LoongArchABI::ABI_ILP32S:50 case LoongArchABI::ABI_LP64S:51 return CSR_ILP32S_LP64S_SaveList;52 case LoongArchABI::ABI_ILP32F:53 case LoongArchABI::ABI_LP64F:54 return CSR_ILP32F_LP64F_SaveList;55 case LoongArchABI::ABI_ILP32D:56 case LoongArchABI::ABI_LP64D:57 return CSR_ILP32D_LP64D_SaveList;58 }59}60 61const uint32_t *62LoongArchRegisterInfo::getCallPreservedMask(const MachineFunction &MF,63 CallingConv::ID CC) const {64 auto &Subtarget = MF.getSubtarget<LoongArchSubtarget>();65 66 if (CC == CallingConv::GHC)67 return CSR_NoRegs_RegMask;68 if (CC == CallingConv::PreserveMost)69 return CSR_MostRegs_RegMask;70 switch (Subtarget.getTargetABI()) {71 default:72 llvm_unreachable("Unrecognized ABI");73 case LoongArchABI::ABI_ILP32S:74 case LoongArchABI::ABI_LP64S:75 return CSR_ILP32S_LP64S_RegMask;76 case LoongArchABI::ABI_ILP32F:77 case LoongArchABI::ABI_LP64F:78 return CSR_ILP32F_LP64F_RegMask;79 case LoongArchABI::ABI_ILP32D:80 case LoongArchABI::ABI_LP64D:81 return CSR_ILP32D_LP64D_RegMask;82 }83}84 85const uint32_t *LoongArchRegisterInfo::getNoPreservedMask() const {86 return CSR_NoRegs_RegMask;87}88 89BitVector90LoongArchRegisterInfo::getReservedRegs(const MachineFunction &MF) const {91 const LoongArchFrameLowering *TFI = getFrameLowering(MF);92 BitVector Reserved(getNumRegs());93 94 // Use markSuperRegs to ensure any register aliases are also reserved95 markSuperRegs(Reserved, LoongArch::R0); // zero96 markSuperRegs(Reserved, LoongArch::R2); // tp97 markSuperRegs(Reserved, LoongArch::R3); // sp98 markSuperRegs(Reserved, LoongArch::R21); // non-allocatable99 if (TFI->hasFP(MF))100 markSuperRegs(Reserved, LoongArch::R22); // fp101 // Reserve the base register if we need to realign the stack and allocate102 // variable-sized objects at runtime.103 if (TFI->hasBP(MF))104 markSuperRegs(Reserved, LoongArchABI::getBPReg()); // bp105 106 assert(checkAllSuperRegsMarked(Reserved));107 return Reserved;108}109 110Register111LoongArchRegisterInfo::getFrameRegister(const MachineFunction &MF) const {112 const TargetFrameLowering *TFI = getFrameLowering(MF);113 return TFI->hasFP(MF) ? LoongArch::R22 : LoongArch::R3;114}115 116bool LoongArchRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,117 int SPAdj,118 unsigned FIOperandNum,119 RegScavenger *RS) const {120 // TODO: this implementation is a temporary placeholder which does just121 // enough to allow other aspects of code generation to be tested.122 123 assert(SPAdj == 0 && "Unexpected non-zero SPAdj value");124 125 MachineInstr &MI = *II;126 assert(MI.getOperand(FIOperandNum + 1).isImm() &&127 "Unexpected FI-consuming insn");128 129 MachineBasicBlock &MBB = *MI.getParent();130 MachineFunction &MF = *MI.getParent()->getParent();131 MachineRegisterInfo &MRI = MF.getRegInfo();132 const LoongArchSubtarget &STI = MF.getSubtarget<LoongArchSubtarget>();133 const LoongArchInstrInfo *TII = STI.getInstrInfo();134 const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering();135 DebugLoc DL = MI.getDebugLoc();136 bool IsLA64 = STI.is64Bit();137 unsigned MIOpc = MI.getOpcode();138 139 int FrameIndex = MI.getOperand(FIOperandNum).getIndex();140 Register FrameReg;141 StackOffset Offset =142 TFI->getFrameIndexReference(MF, FrameIndex, FrameReg) +143 StackOffset::getFixed(MI.getOperand(FIOperandNum + 1).getImm());144 145 bool FrameRegIsKill = false;146 147 int FixedOffset = Offset.getFixed();148 bool OffsetLegal = true;149 150 // Handle offsets that exceed the immediate range of the instruction.151 switch (MIOpc) {152 case LoongArch::VSTELM_B:153 case LoongArch::XVSTELM_B:154 OffsetLegal = isInt<8>(FixedOffset);155 break;156 case LoongArch::VSTELM_H:157 case LoongArch::XVSTELM_H:158 OffsetLegal = isShiftedInt<8, 1>(FixedOffset);159 break;160 case LoongArch::VSTELM_W:161 case LoongArch::XVSTELM_W:162 OffsetLegal = isShiftedInt<8, 2>(FixedOffset);163 break;164 case LoongArch::VSTELM_D:165 case LoongArch::XVSTELM_D:166 OffsetLegal = isShiftedInt<8, 3>(FixedOffset);167 break;168 }169 170 if (!OffsetLegal && isInt<12>(FixedOffset)) {171 unsigned Addi = IsLA64 ? LoongArch::ADDI_D : LoongArch::ADDI_W;172 173 // The offset fits in si12 but is not legal for the instruction,174 // so use only one scratch register instead.175 Register ScratchReg = MRI.createVirtualRegister(&LoongArch::GPRRegClass);176 BuildMI(MBB, II, DL, TII->get(Addi), ScratchReg)177 .addReg(FrameReg)178 .addImm(FixedOffset);179 Offset = StackOffset::getFixed(0);180 FrameReg = ScratchReg;181 FrameRegIsKill = true;182 }183 184 if (!isInt<12>(FixedOffset)) {185 unsigned Addi = IsLA64 ? LoongArch::ADDI_D : LoongArch::ADDI_W;186 unsigned Add = IsLA64 ? LoongArch::ADD_D : LoongArch::ADD_W;187 188 // The offset won't fit in an immediate, so use a scratch register instead.189 // Modify Offset and FrameReg appropriately.190 Register ScratchReg = MRI.createVirtualRegister(&LoongArch::GPRRegClass);191 TII->movImm(MBB, II, DL, ScratchReg, Offset.getFixed());192 if (MIOpc == Addi) {193 BuildMI(MBB, II, DL, TII->get(Add), MI.getOperand(0).getReg())194 .addReg(FrameReg)195 .addReg(ScratchReg, RegState::Kill);196 MI.eraseFromParent();197 return true;198 }199 BuildMI(MBB, II, DL, TII->get(Add), ScratchReg)200 .addReg(FrameReg)201 .addReg(ScratchReg, RegState::Kill);202 Offset = StackOffset::getFixed(0);203 FrameReg = ScratchReg;204 FrameRegIsKill = true;205 }206 207 // Spill CFRs.208 if (MIOpc == LoongArch::PseudoST_CFR) {209 Register ScratchReg = MRI.createVirtualRegister(&LoongArch::GPRRegClass);210 BuildMI(MBB, II, DL, TII->get(LoongArch::MOVCF2GR), ScratchReg)211 .add(MI.getOperand(0));212 BuildMI(MBB, II, DL, TII->get(IsLA64 ? LoongArch::ST_D : LoongArch::ST_W))213 .addReg(ScratchReg, RegState::Kill)214 .addReg(FrameReg)215 .addImm(Offset.getFixed());216 MI.eraseFromParent();217 return true;218 }219 220 // Reload CFRs.221 if (MIOpc == LoongArch::PseudoLD_CFR) {222 Register ScratchReg = MRI.createVirtualRegister(&LoongArch::GPRRegClass);223 BuildMI(MBB, II, DL, TII->get(IsLA64 ? LoongArch::LD_D : LoongArch::LD_W),224 ScratchReg)225 .addReg(FrameReg)226 .addImm(Offset.getFixed());227 BuildMI(MBB, II, DL, TII->get(LoongArch::MOVGR2CF))228 .add(MI.getOperand(0))229 .addReg(ScratchReg, RegState::Kill);230 MI.eraseFromParent();231 return true;232 }233 234 MI.getOperand(FIOperandNum)235 .ChangeToRegister(FrameReg, false, false, FrameRegIsKill);236 MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset.getFixed());237 return false;238}239 240bool LoongArchRegisterInfo::canRealignStack(const MachineFunction &MF) const {241 if (!TargetRegisterInfo::canRealignStack(MF))242 return false;243 244 const MachineRegisterInfo *MRI = &MF.getRegInfo();245 const LoongArchFrameLowering *TFI = getFrameLowering(MF);246 247 // Stack realignment requires a frame pointer. If we already started248 // register allocation with frame pointer elimination, it is too late now.249 if (!MRI->canReserveReg(LoongArch::R22))250 return false;251 252 // We may also need a base pointer if there are dynamic allocas or stack253 // pointer adjustments around calls.254 if (TFI->hasReservedCallFrame(MF))255 return true;256 257 // A base pointer is required and allowed. Check that it isn't too late to258 // reserve it.259 return MRI->canReserveReg(LoongArchABI::getBPReg());260}261