1*0b57cec5SDimitry Andric //===-- RISCVRegisterInfo.cpp - RISCV Register Information ------*- C++ -*-===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric // 9*0b57cec5SDimitry Andric // This file contains the RISCV implementation of the TargetRegisterInfo class. 10*0b57cec5SDimitry Andric // 11*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 12*0b57cec5SDimitry Andric 13*0b57cec5SDimitry Andric #include "RISCVRegisterInfo.h" 14*0b57cec5SDimitry Andric #include "RISCV.h" 15*0b57cec5SDimitry Andric #include "RISCVSubtarget.h" 16*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h" 17*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 18*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h" 19*0b57cec5SDimitry Andric #include "llvm/CodeGen/RegisterScavenging.h" 20*0b57cec5SDimitry Andric #include "llvm/CodeGen/TargetFrameLowering.h" 21*0b57cec5SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h" 22*0b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 23*0b57cec5SDimitry Andric 24*0b57cec5SDimitry Andric #define GET_REGINFO_TARGET_DESC 25*0b57cec5SDimitry Andric #include "RISCVGenRegisterInfo.inc" 26*0b57cec5SDimitry Andric 27*0b57cec5SDimitry Andric using namespace llvm; 28*0b57cec5SDimitry Andric 29*0b57cec5SDimitry Andric RISCVRegisterInfo::RISCVRegisterInfo(unsigned HwMode) 30*0b57cec5SDimitry Andric : RISCVGenRegisterInfo(RISCV::X1, /*DwarfFlavour*/0, /*EHFlavor*/0, 31*0b57cec5SDimitry Andric /*PC*/0, HwMode) {} 32*0b57cec5SDimitry Andric 33*0b57cec5SDimitry Andric const MCPhysReg * 34*0b57cec5SDimitry Andric RISCVRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { 35*0b57cec5SDimitry Andric auto &Subtarget = MF->getSubtarget<RISCVSubtarget>(); 36*0b57cec5SDimitry Andric if (MF->getFunction().hasFnAttribute("interrupt")) { 37*0b57cec5SDimitry Andric if (Subtarget.hasStdExtD()) 38*0b57cec5SDimitry Andric return CSR_XLEN_F64_Interrupt_SaveList; 39*0b57cec5SDimitry Andric if (Subtarget.hasStdExtF()) 40*0b57cec5SDimitry Andric return CSR_XLEN_F32_Interrupt_SaveList; 41*0b57cec5SDimitry Andric return CSR_Interrupt_SaveList; 42*0b57cec5SDimitry Andric } 43*0b57cec5SDimitry Andric 44*0b57cec5SDimitry Andric switch (Subtarget.getTargetABI()) { 45*0b57cec5SDimitry Andric default: 46*0b57cec5SDimitry Andric llvm_unreachable("Unrecognized ABI"); 47*0b57cec5SDimitry Andric case RISCVABI::ABI_ILP32: 48*0b57cec5SDimitry Andric case RISCVABI::ABI_LP64: 49*0b57cec5SDimitry Andric return CSR_ILP32_LP64_SaveList; 50*0b57cec5SDimitry Andric case RISCVABI::ABI_ILP32F: 51*0b57cec5SDimitry Andric case RISCVABI::ABI_LP64F: 52*0b57cec5SDimitry Andric return CSR_ILP32F_LP64F_SaveList; 53*0b57cec5SDimitry Andric case RISCVABI::ABI_ILP32D: 54*0b57cec5SDimitry Andric case RISCVABI::ABI_LP64D: 55*0b57cec5SDimitry Andric return CSR_ILP32D_LP64D_SaveList; 56*0b57cec5SDimitry Andric } 57*0b57cec5SDimitry Andric } 58*0b57cec5SDimitry Andric 59*0b57cec5SDimitry Andric BitVector RISCVRegisterInfo::getReservedRegs(const MachineFunction &MF) const { 60*0b57cec5SDimitry Andric const TargetFrameLowering *TFI = getFrameLowering(MF); 61*0b57cec5SDimitry Andric BitVector Reserved(getNumRegs()); 62*0b57cec5SDimitry Andric 63*0b57cec5SDimitry Andric // Use markSuperRegs to ensure any register aliases are also reserved 64*0b57cec5SDimitry Andric markSuperRegs(Reserved, RISCV::X0); // zero 65*0b57cec5SDimitry Andric markSuperRegs(Reserved, RISCV::X1); // ra 66*0b57cec5SDimitry Andric markSuperRegs(Reserved, RISCV::X2); // sp 67*0b57cec5SDimitry Andric markSuperRegs(Reserved, RISCV::X3); // gp 68*0b57cec5SDimitry Andric markSuperRegs(Reserved, RISCV::X4); // tp 69*0b57cec5SDimitry Andric if (TFI->hasFP(MF)) 70*0b57cec5SDimitry Andric markSuperRegs(Reserved, RISCV::X8); // fp 71*0b57cec5SDimitry Andric assert(checkAllSuperRegsMarked(Reserved)); 72*0b57cec5SDimitry Andric return Reserved; 73*0b57cec5SDimitry Andric } 74*0b57cec5SDimitry Andric 75*0b57cec5SDimitry Andric bool RISCVRegisterInfo::isConstantPhysReg(unsigned PhysReg) const { 76*0b57cec5SDimitry Andric return PhysReg == RISCV::X0; 77*0b57cec5SDimitry Andric } 78*0b57cec5SDimitry Andric 79*0b57cec5SDimitry Andric const uint32_t *RISCVRegisterInfo::getNoPreservedMask() const { 80*0b57cec5SDimitry Andric return CSR_NoRegs_RegMask; 81*0b57cec5SDimitry Andric } 82*0b57cec5SDimitry Andric 83*0b57cec5SDimitry Andric void RISCVRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, 84*0b57cec5SDimitry Andric int SPAdj, unsigned FIOperandNum, 85*0b57cec5SDimitry Andric RegScavenger *RS) const { 86*0b57cec5SDimitry Andric assert(SPAdj == 0 && "Unexpected non-zero SPAdj value"); 87*0b57cec5SDimitry Andric 88*0b57cec5SDimitry Andric MachineInstr &MI = *II; 89*0b57cec5SDimitry Andric MachineFunction &MF = *MI.getParent()->getParent(); 90*0b57cec5SDimitry Andric MachineRegisterInfo &MRI = MF.getRegInfo(); 91*0b57cec5SDimitry Andric const RISCVInstrInfo *TII = MF.getSubtarget<RISCVSubtarget>().getInstrInfo(); 92*0b57cec5SDimitry Andric DebugLoc DL = MI.getDebugLoc(); 93*0b57cec5SDimitry Andric 94*0b57cec5SDimitry Andric int FrameIndex = MI.getOperand(FIOperandNum).getIndex(); 95*0b57cec5SDimitry Andric unsigned FrameReg; 96*0b57cec5SDimitry Andric int Offset = 97*0b57cec5SDimitry Andric getFrameLowering(MF)->getFrameIndexReference(MF, FrameIndex, FrameReg) + 98*0b57cec5SDimitry Andric MI.getOperand(FIOperandNum + 1).getImm(); 99*0b57cec5SDimitry Andric 100*0b57cec5SDimitry Andric if (!isInt<32>(Offset)) { 101*0b57cec5SDimitry Andric report_fatal_error( 102*0b57cec5SDimitry Andric "Frame offsets outside of the signed 32-bit range not supported"); 103*0b57cec5SDimitry Andric } 104*0b57cec5SDimitry Andric 105*0b57cec5SDimitry Andric MachineBasicBlock &MBB = *MI.getParent(); 106*0b57cec5SDimitry Andric bool FrameRegIsKill = false; 107*0b57cec5SDimitry Andric 108*0b57cec5SDimitry Andric if (!isInt<12>(Offset)) { 109*0b57cec5SDimitry Andric assert(isInt<32>(Offset) && "Int32 expected"); 110*0b57cec5SDimitry Andric // The offset won't fit in an immediate, so use a scratch register instead 111*0b57cec5SDimitry Andric // Modify Offset and FrameReg appropriately 112*0b57cec5SDimitry Andric unsigned ScratchReg = MRI.createVirtualRegister(&RISCV::GPRRegClass); 113*0b57cec5SDimitry Andric TII->movImm32(MBB, II, DL, ScratchReg, Offset); 114*0b57cec5SDimitry Andric BuildMI(MBB, II, DL, TII->get(RISCV::ADD), ScratchReg) 115*0b57cec5SDimitry Andric .addReg(FrameReg) 116*0b57cec5SDimitry Andric .addReg(ScratchReg, RegState::Kill); 117*0b57cec5SDimitry Andric Offset = 0; 118*0b57cec5SDimitry Andric FrameReg = ScratchReg; 119*0b57cec5SDimitry Andric FrameRegIsKill = true; 120*0b57cec5SDimitry Andric } 121*0b57cec5SDimitry Andric 122*0b57cec5SDimitry Andric MI.getOperand(FIOperandNum) 123*0b57cec5SDimitry Andric .ChangeToRegister(FrameReg, false, false, FrameRegIsKill); 124*0b57cec5SDimitry Andric MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset); 125*0b57cec5SDimitry Andric } 126*0b57cec5SDimitry Andric 127*0b57cec5SDimitry Andric Register RISCVRegisterInfo::getFrameRegister(const MachineFunction &MF) const { 128*0b57cec5SDimitry Andric const TargetFrameLowering *TFI = getFrameLowering(MF); 129*0b57cec5SDimitry Andric return TFI->hasFP(MF) ? RISCV::X8 : RISCV::X2; 130*0b57cec5SDimitry Andric } 131*0b57cec5SDimitry Andric 132*0b57cec5SDimitry Andric const uint32_t * 133*0b57cec5SDimitry Andric RISCVRegisterInfo::getCallPreservedMask(const MachineFunction & MF, 134*0b57cec5SDimitry Andric CallingConv::ID /*CC*/) const { 135*0b57cec5SDimitry Andric auto &Subtarget = MF.getSubtarget<RISCVSubtarget>(); 136*0b57cec5SDimitry Andric if (MF.getFunction().hasFnAttribute("interrupt")) { 137*0b57cec5SDimitry Andric if (Subtarget.hasStdExtD()) 138*0b57cec5SDimitry Andric return CSR_XLEN_F64_Interrupt_RegMask; 139*0b57cec5SDimitry Andric if (Subtarget.hasStdExtF()) 140*0b57cec5SDimitry Andric return CSR_XLEN_F32_Interrupt_RegMask; 141*0b57cec5SDimitry Andric return CSR_Interrupt_RegMask; 142*0b57cec5SDimitry Andric } 143*0b57cec5SDimitry Andric 144*0b57cec5SDimitry Andric switch (Subtarget.getTargetABI()) { 145*0b57cec5SDimitry Andric default: 146*0b57cec5SDimitry Andric llvm_unreachable("Unrecognized ABI"); 147*0b57cec5SDimitry Andric case RISCVABI::ABI_ILP32: 148*0b57cec5SDimitry Andric case RISCVABI::ABI_LP64: 149*0b57cec5SDimitry Andric return CSR_ILP32_LP64_RegMask; 150*0b57cec5SDimitry Andric case RISCVABI::ABI_ILP32F: 151*0b57cec5SDimitry Andric case RISCVABI::ABI_LP64F: 152*0b57cec5SDimitry Andric return CSR_ILP32F_LP64F_RegMask; 153*0b57cec5SDimitry Andric case RISCVABI::ABI_ILP32D: 154*0b57cec5SDimitry Andric case RISCVABI::ABI_LP64D: 155*0b57cec5SDimitry Andric return CSR_ILP32D_LP64D_RegMask; 156*0b57cec5SDimitry Andric } 157*0b57cec5SDimitry Andric } 158