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