123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203 |
- //===- LoongArchRegisterInfo.cpp - LoongArch Register Information -*- C++ -*-=//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- //
- // This file contains the LoongArch implementation of the TargetRegisterInfo
- // class.
- //
- //===----------------------------------------------------------------------===//
- #include "LoongArchRegisterInfo.h"
- #include "LoongArch.h"
- #include "LoongArchInstrInfo.h"
- #include "LoongArchSubtarget.h"
- #include "MCTargetDesc/LoongArchMCTargetDesc.h"
- #include "llvm/CodeGen/MachineFrameInfo.h"
- #include "llvm/CodeGen/MachineFunction.h"
- #include "llvm/CodeGen/MachineInstrBuilder.h"
- #include "llvm/CodeGen/RegisterScavenging.h"
- #include "llvm/CodeGen/TargetFrameLowering.h"
- #include "llvm/CodeGen/TargetInstrInfo.h"
- #include "llvm/Support/ErrorHandling.h"
- using namespace llvm;
- #define GET_REGINFO_TARGET_DESC
- #include "LoongArchGenRegisterInfo.inc"
- LoongArchRegisterInfo::LoongArchRegisterInfo(unsigned HwMode)
- : LoongArchGenRegisterInfo(LoongArch::R1, /*DwarfFlavour*/ 0,
- /*EHFlavor*/ 0,
- /*PC*/ 0, HwMode) {}
- const MCPhysReg *
- LoongArchRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
- auto &Subtarget = MF->getSubtarget<LoongArchSubtarget>();
- if (MF->getFunction().getCallingConv() == CallingConv::GHC)
- return CSR_NoRegs_SaveList;
- switch (Subtarget.getTargetABI()) {
- default:
- llvm_unreachable("Unrecognized ABI");
- case LoongArchABI::ABI_ILP32S:
- case LoongArchABI::ABI_LP64S:
- return CSR_ILP32S_LP64S_SaveList;
- case LoongArchABI::ABI_ILP32F:
- case LoongArchABI::ABI_LP64F:
- return CSR_ILP32F_LP64F_SaveList;
- case LoongArchABI::ABI_ILP32D:
- case LoongArchABI::ABI_LP64D:
- return CSR_ILP32D_LP64D_SaveList;
- }
- }
- const uint32_t *
- LoongArchRegisterInfo::getCallPreservedMask(const MachineFunction &MF,
- CallingConv::ID CC) const {
- auto &Subtarget = MF.getSubtarget<LoongArchSubtarget>();
- if (CC == CallingConv::GHC)
- return CSR_NoRegs_RegMask;
- switch (Subtarget.getTargetABI()) {
- default:
- llvm_unreachable("Unrecognized ABI");
- case LoongArchABI::ABI_ILP32S:
- case LoongArchABI::ABI_LP64S:
- return CSR_ILP32S_LP64S_RegMask;
- case LoongArchABI::ABI_ILP32F:
- case LoongArchABI::ABI_LP64F:
- return CSR_ILP32F_LP64F_RegMask;
- case LoongArchABI::ABI_ILP32D:
- case LoongArchABI::ABI_LP64D:
- return CSR_ILP32D_LP64D_RegMask;
- }
- }
- const uint32_t *LoongArchRegisterInfo::getNoPreservedMask() const {
- return CSR_NoRegs_RegMask;
- }
- BitVector
- LoongArchRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
- const LoongArchFrameLowering *TFI = getFrameLowering(MF);
- BitVector Reserved(getNumRegs());
- // Use markSuperRegs to ensure any register aliases are also reserved
- markSuperRegs(Reserved, LoongArch::R0); // zero
- markSuperRegs(Reserved, LoongArch::R2); // tp
- markSuperRegs(Reserved, LoongArch::R3); // sp
- markSuperRegs(Reserved, LoongArch::R21); // non-allocatable
- if (TFI->hasFP(MF))
- markSuperRegs(Reserved, LoongArch::R22); // fp
- // Reserve the base register if we need to realign the stack and allocate
- // variable-sized objects at runtime.
- if (TFI->hasBP(MF))
- markSuperRegs(Reserved, LoongArchABI::getBPReg()); // bp
- // FIXME: To avoid generating COPY instructions between CFRs, only use $fcc0.
- // This is required to work around the fact that COPY instruction between CFRs
- // is not provided in LoongArch.
- if (MF.getSubtarget<LoongArchSubtarget>().hasBasicF())
- for (size_t Reg = LoongArch::FCC1; Reg <= LoongArch::FCC7; ++Reg)
- markSuperRegs(Reserved, Reg);
- assert(checkAllSuperRegsMarked(Reserved));
- return Reserved;
- }
- Register
- LoongArchRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
- const TargetFrameLowering *TFI = getFrameLowering(MF);
- return TFI->hasFP(MF) ? LoongArch::R22 : LoongArch::R3;
- }
- bool LoongArchRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
- int SPAdj,
- unsigned FIOperandNum,
- RegScavenger *RS) const {
- // TODO: this implementation is a temporary placeholder which does just
- // enough to allow other aspects of code generation to be tested.
- assert(SPAdj == 0 && "Unexpected non-zero SPAdj value");
- MachineInstr &MI = *II;
- assert(MI.getOperand(FIOperandNum + 1).isImm() &&
- "Unexpected FI-consuming insn");
- MachineBasicBlock &MBB = *MI.getParent();
- MachineFunction &MF = *MI.getParent()->getParent();
- MachineRegisterInfo &MRI = MF.getRegInfo();
- const LoongArchSubtarget &STI = MF.getSubtarget<LoongArchSubtarget>();
- const LoongArchInstrInfo *TII = STI.getInstrInfo();
- const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering();
- DebugLoc DL = MI.getDebugLoc();
- bool IsLA64 = STI.is64Bit();
- unsigned MIOpc = MI.getOpcode();
- int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
- Register FrameReg;
- StackOffset Offset =
- TFI->getFrameIndexReference(MF, FrameIndex, FrameReg) +
- StackOffset::getFixed(MI.getOperand(FIOperandNum + 1).getImm());
- bool FrameRegIsKill = false;
- if (!isInt<12>(Offset.getFixed())) {
- unsigned Addi = IsLA64 ? LoongArch::ADDI_D : LoongArch::ADDI_W;
- unsigned Add = IsLA64 ? LoongArch::ADD_D : LoongArch::ADD_W;
- // The offset won't fit in an immediate, so use a scratch register instead.
- // Modify Offset and FrameReg appropriately.
- Register ScratchReg = MRI.createVirtualRegister(&LoongArch::GPRRegClass);
- TII->movImm(MBB, II, DL, ScratchReg, Offset.getFixed());
- if (MIOpc == Addi) {
- BuildMI(MBB, II, DL, TII->get(Add), MI.getOperand(0).getReg())
- .addReg(FrameReg)
- .addReg(ScratchReg, RegState::Kill);
- MI.eraseFromParent();
- return true;
- }
- BuildMI(MBB, II, DL, TII->get(Add), ScratchReg)
- .addReg(FrameReg)
- .addReg(ScratchReg, RegState::Kill);
- Offset = StackOffset::getFixed(0);
- FrameReg = ScratchReg;
- FrameRegIsKill = true;
- }
- // Spill CFRs.
- if (MIOpc == LoongArch::PseudoST_CFR) {
- Register ScratchReg = MRI.createVirtualRegister(&LoongArch::GPRRegClass);
- BuildMI(MBB, II, DL, TII->get(LoongArch::MOVCF2GR), ScratchReg)
- .add(MI.getOperand(0));
- BuildMI(MBB, II, DL, TII->get(IsLA64 ? LoongArch::ST_D : LoongArch::ST_W))
- .addReg(ScratchReg, RegState::Kill)
- .addReg(FrameReg)
- .addImm(Offset.getFixed());
- MI.eraseFromParent();
- return true;
- }
- // Reload CFRs.
- if (MIOpc == LoongArch::PseudoLD_CFR) {
- Register ScratchReg = MRI.createVirtualRegister(&LoongArch::GPRRegClass);
- BuildMI(MBB, II, DL, TII->get(IsLA64 ? LoongArch::LD_D : LoongArch::LD_W),
- ScratchReg)
- .addReg(FrameReg)
- .addImm(Offset.getFixed());
- BuildMI(MBB, II, DL, TII->get(LoongArch::MOVGR2CF))
- .add(MI.getOperand(0))
- .addReg(ScratchReg, RegState::Kill);
- MI.eraseFromParent();
- return true;
- }
- MI.getOperand(FIOperandNum)
- .ChangeToRegister(FrameReg, false, false, FrameRegIsKill);
- MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset.getFixed());
- return false;
- }
|