Path: blob/main/contrib/llvm-project/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.cpp
96353 views
//===- LoongArchRegisterInfo.cpp - LoongArch Register Information -*- C++ -*-=//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file contains the LoongArch implementation of the TargetRegisterInfo9// class.10//11//===----------------------------------------------------------------------===//1213#include "LoongArchRegisterInfo.h"14#include "LoongArch.h"15#include "LoongArchInstrInfo.h"16#include "LoongArchSubtarget.h"17#include "MCTargetDesc/LoongArchBaseInfo.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"2627using namespace llvm;2829#define GET_REGINFO_TARGET_DESC30#include "LoongArchGenRegisterInfo.inc"3132LoongArchRegisterInfo::LoongArchRegisterInfo(unsigned HwMode)33: LoongArchGenRegisterInfo(LoongArch::R1, /*DwarfFlavour*/ 0,34/*EHFlavor*/ 0,35/*PC*/ 0, HwMode) {}3637const MCPhysReg *38LoongArchRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {39auto &Subtarget = MF->getSubtarget<LoongArchSubtarget>();4041if (MF->getFunction().getCallingConv() == CallingConv::GHC)42return CSR_NoRegs_SaveList;43switch (Subtarget.getTargetABI()) {44default:45llvm_unreachable("Unrecognized ABI");46case LoongArchABI::ABI_ILP32S:47case LoongArchABI::ABI_LP64S:48return CSR_ILP32S_LP64S_SaveList;49case LoongArchABI::ABI_ILP32F:50case LoongArchABI::ABI_LP64F:51return CSR_ILP32F_LP64F_SaveList;52case LoongArchABI::ABI_ILP32D:53case LoongArchABI::ABI_LP64D:54return CSR_ILP32D_LP64D_SaveList;55}56}5758const uint32_t *59LoongArchRegisterInfo::getCallPreservedMask(const MachineFunction &MF,60CallingConv::ID CC) const {61auto &Subtarget = MF.getSubtarget<LoongArchSubtarget>();6263if (CC == CallingConv::GHC)64return CSR_NoRegs_RegMask;65switch (Subtarget.getTargetABI()) {66default:67llvm_unreachable("Unrecognized ABI");68case LoongArchABI::ABI_ILP32S:69case LoongArchABI::ABI_LP64S:70return CSR_ILP32S_LP64S_RegMask;71case LoongArchABI::ABI_ILP32F:72case LoongArchABI::ABI_LP64F:73return CSR_ILP32F_LP64F_RegMask;74case LoongArchABI::ABI_ILP32D:75case LoongArchABI::ABI_LP64D:76return CSR_ILP32D_LP64D_RegMask;77}78}7980const uint32_t *LoongArchRegisterInfo::getNoPreservedMask() const {81return CSR_NoRegs_RegMask;82}8384BitVector85LoongArchRegisterInfo::getReservedRegs(const MachineFunction &MF) const {86const LoongArchFrameLowering *TFI = getFrameLowering(MF);87BitVector Reserved(getNumRegs());8889// Use markSuperRegs to ensure any register aliases are also reserved90markSuperRegs(Reserved, LoongArch::R0); // zero91markSuperRegs(Reserved, LoongArch::R2); // tp92markSuperRegs(Reserved, LoongArch::R3); // sp93markSuperRegs(Reserved, LoongArch::R21); // non-allocatable94if (TFI->hasFP(MF))95markSuperRegs(Reserved, LoongArch::R22); // fp96// Reserve the base register if we need to realign the stack and allocate97// variable-sized objects at runtime.98if (TFI->hasBP(MF))99markSuperRegs(Reserved, LoongArchABI::getBPReg()); // bp100101assert(checkAllSuperRegsMarked(Reserved));102return Reserved;103}104105Register106LoongArchRegisterInfo::getFrameRegister(const MachineFunction &MF) const {107const TargetFrameLowering *TFI = getFrameLowering(MF);108return TFI->hasFP(MF) ? LoongArch::R22 : LoongArch::R3;109}110111bool LoongArchRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,112int SPAdj,113unsigned FIOperandNum,114RegScavenger *RS) const {115// TODO: this implementation is a temporary placeholder which does just116// enough to allow other aspects of code generation to be tested.117118assert(SPAdj == 0 && "Unexpected non-zero SPAdj value");119120MachineInstr &MI = *II;121assert(MI.getOperand(FIOperandNum + 1).isImm() &&122"Unexpected FI-consuming insn");123124MachineBasicBlock &MBB = *MI.getParent();125MachineFunction &MF = *MI.getParent()->getParent();126MachineRegisterInfo &MRI = MF.getRegInfo();127const LoongArchSubtarget &STI = MF.getSubtarget<LoongArchSubtarget>();128const LoongArchInstrInfo *TII = STI.getInstrInfo();129const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering();130DebugLoc DL = MI.getDebugLoc();131bool IsLA64 = STI.is64Bit();132unsigned MIOpc = MI.getOpcode();133134int FrameIndex = MI.getOperand(FIOperandNum).getIndex();135Register FrameReg;136StackOffset Offset =137TFI->getFrameIndexReference(MF, FrameIndex, FrameReg) +138StackOffset::getFixed(MI.getOperand(FIOperandNum + 1).getImm());139140bool FrameRegIsKill = false;141142if (!isInt<12>(Offset.getFixed())) {143unsigned Addi = IsLA64 ? LoongArch::ADDI_D : LoongArch::ADDI_W;144unsigned Add = IsLA64 ? LoongArch::ADD_D : LoongArch::ADD_W;145146// The offset won't fit in an immediate, so use a scratch register instead.147// Modify Offset and FrameReg appropriately.148Register ScratchReg = MRI.createVirtualRegister(&LoongArch::GPRRegClass);149TII->movImm(MBB, II, DL, ScratchReg, Offset.getFixed());150if (MIOpc == Addi) {151BuildMI(MBB, II, DL, TII->get(Add), MI.getOperand(0).getReg())152.addReg(FrameReg)153.addReg(ScratchReg, RegState::Kill);154MI.eraseFromParent();155return true;156}157BuildMI(MBB, II, DL, TII->get(Add), ScratchReg)158.addReg(FrameReg)159.addReg(ScratchReg, RegState::Kill);160Offset = StackOffset::getFixed(0);161FrameReg = ScratchReg;162FrameRegIsKill = true;163}164165// Spill CFRs.166if (MIOpc == LoongArch::PseudoST_CFR) {167Register ScratchReg = MRI.createVirtualRegister(&LoongArch::GPRRegClass);168BuildMI(MBB, II, DL, TII->get(LoongArch::MOVCF2GR), ScratchReg)169.add(MI.getOperand(0));170BuildMI(MBB, II, DL, TII->get(IsLA64 ? LoongArch::ST_D : LoongArch::ST_W))171.addReg(ScratchReg, RegState::Kill)172.addReg(FrameReg)173.addImm(Offset.getFixed());174MI.eraseFromParent();175return true;176}177178// Reload CFRs.179if (MIOpc == LoongArch::PseudoLD_CFR) {180Register ScratchReg = MRI.createVirtualRegister(&LoongArch::GPRRegClass);181BuildMI(MBB, II, DL, TII->get(IsLA64 ? LoongArch::LD_D : LoongArch::LD_W),182ScratchReg)183.addReg(FrameReg)184.addImm(Offset.getFixed());185BuildMI(MBB, II, DL, TII->get(LoongArch::MOVGR2CF))186.add(MI.getOperand(0))187.addReg(ScratchReg, RegState::Kill);188MI.eraseFromParent();189return true;190}191192MI.getOperand(FIOperandNum)193.ChangeToRegister(FrameReg, false, false, FrameRegIsKill);194MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset.getFixed());195return false;196}197198bool LoongArchRegisterInfo::canRealignStack(const MachineFunction &MF) const {199if (!TargetRegisterInfo::canRealignStack(MF))200return false;201202const MachineRegisterInfo *MRI = &MF.getRegInfo();203const LoongArchFrameLowering *TFI = getFrameLowering(MF);204205// Stack realignment requires a frame pointer. If we already started206// register allocation with frame pointer elimination, it is too late now.207if (!MRI->canReserveReg(LoongArch::R22))208return false;209210// We may also need a base pointer if there are dynamic allocas or stack211// pointer adjustments around calls.212if (TFI->hasReservedCallFrame(MF))213return true;214215// A base pointer is required and allowed. Check that it isn't too late to216// reserve it.217return MRI->canReserveReg(LoongArchABI::getBPReg());218}219220221