diff options
Diffstat (limited to 'llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp')
-rw-r--r-- | llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp | 122 |
1 files changed, 110 insertions, 12 deletions
diff --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp index 631077ef83f5..388cce00bdf3 100644 --- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp +++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp @@ -101,6 +101,11 @@ BitVector RISCVRegisterInfo::getReservedRegs(const MachineFunction &MF) const { markSuperRegs(Reserved, RISCV::VXSAT); markSuperRegs(Reserved, RISCV::VXRM); + // Floating point environment registers. + markSuperRegs(Reserved, RISCV::FRM); + markSuperRegs(Reserved, RISCV::FFLAGS); + markSuperRegs(Reserved, RISCV::FCSR); + assert(checkAllSuperRegsMarked(Reserved)); return Reserved; } @@ -164,12 +169,13 @@ void RISCVRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, int FrameIndex = MI.getOperand(FIOperandNum).getIndex(); Register FrameReg; - int Offset = getFrameLowering(MF) - ->getFrameIndexReference(MF, FrameIndex, FrameReg) - .getFixed() + - MI.getOperand(FIOperandNum + 1).getImm(); + StackOffset Offset = + getFrameLowering(MF)->getFrameIndexReference(MF, FrameIndex, FrameReg); + bool IsRVVSpill = TII->isRVVSpill(MI, /*CheckFIs*/ false); + if (!IsRVVSpill) + Offset += StackOffset::getFixed(MI.getOperand(FIOperandNum + 1).getImm()); - if (!isInt<32>(Offset)) { + if (!isInt<32>(Offset.getFixed())) { report_fatal_error( "Frame offsets outside of the signed 32-bit range not supported"); } @@ -177,23 +183,107 @@ void RISCVRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, MachineBasicBlock &MBB = *MI.getParent(); bool FrameRegIsKill = false; - if (!isInt<12>(Offset)) { - assert(isInt<32>(Offset) && "Int32 expected"); + // If required, pre-compute the scalable factor amount which will be used in + // later offset computation. Since this sequence requires up to two scratch + // registers -- after which one is made free -- this grants us better + // scavenging of scratch registers as only up to two are live at one time, + // rather than three. + Register ScalableFactorRegister; + unsigned ScalableAdjOpc = RISCV::ADD; + if (Offset.getScalable()) { + int64_t ScalableValue = Offset.getScalable(); + if (ScalableValue < 0) { + ScalableValue = -ScalableValue; + ScalableAdjOpc = RISCV::SUB; + } + // 1. Get vlenb && multiply vlen with the number of vector registers. + ScalableFactorRegister = + TII->getVLENFactoredAmount(MF, MBB, II, DL, ScalableValue); + } + + if (!isInt<12>(Offset.getFixed())) { // The offset won't fit in an immediate, so use a scratch register instead // Modify Offset and FrameReg appropriately Register ScratchReg = MRI.createVirtualRegister(&RISCV::GPRRegClass); - TII->movImm(MBB, II, DL, ScratchReg, Offset); + TII->movImm(MBB, II, DL, ScratchReg, Offset.getFixed()); + if (MI.getOpcode() == RISCV::ADDI && !Offset.getScalable()) { + BuildMI(MBB, II, DL, TII->get(RISCV::ADD), MI.getOperand(0).getReg()) + .addReg(FrameReg) + .addReg(ScratchReg, RegState::Kill); + MI.eraseFromParent(); + return; + } BuildMI(MBB, II, DL, TII->get(RISCV::ADD), ScratchReg) .addReg(FrameReg) .addReg(ScratchReg, RegState::Kill); - Offset = 0; + Offset = StackOffset::get(0, Offset.getScalable()); FrameReg = ScratchReg; FrameRegIsKill = true; } - MI.getOperand(FIOperandNum) - .ChangeToRegister(FrameReg, false, false, FrameRegIsKill); - MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset); + if (!Offset.getScalable()) { + // Offset = (fixed offset, 0) + MI.getOperand(FIOperandNum) + .ChangeToRegister(FrameReg, false, false, FrameRegIsKill); + if (!IsRVVSpill) + MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset.getFixed()); + else { + if (Offset.getFixed()) { + Register ScratchReg = MRI.createVirtualRegister(&RISCV::GPRRegClass); + BuildMI(MBB, II, DL, TII->get(RISCV::ADDI), ScratchReg) + .addReg(FrameReg, getKillRegState(FrameRegIsKill)) + .addImm(Offset.getFixed()); + MI.getOperand(FIOperandNum) + .ChangeToRegister(ScratchReg, false, false, true); + } + } + } else { + // Offset = (fixed offset, scalable offset) + // Step 1, the scalable offset, has already been computed. + assert(ScalableFactorRegister && + "Expected pre-computation of scalable factor in earlier step"); + + // 2. Calculate address: FrameReg + result of multiply + if (MI.getOpcode() == RISCV::ADDI && !Offset.getFixed()) { + BuildMI(MBB, II, DL, TII->get(ScalableAdjOpc), MI.getOperand(0).getReg()) + .addReg(FrameReg, getKillRegState(FrameRegIsKill)) + .addReg(ScalableFactorRegister, RegState::Kill); + MI.eraseFromParent(); + return; + } + Register VL = MRI.createVirtualRegister(&RISCV::GPRRegClass); + BuildMI(MBB, II, DL, TII->get(ScalableAdjOpc), VL) + .addReg(FrameReg, getKillRegState(FrameRegIsKill)) + .addReg(ScalableFactorRegister, RegState::Kill); + + if (IsRVVSpill && Offset.getFixed()) { + // Scalable load/store has no immediate argument. We need to add the + // fixed part into the load/store base address. + BuildMI(MBB, II, DL, TII->get(RISCV::ADDI), VL) + .addReg(VL) + .addImm(Offset.getFixed()); + } + + // 3. Replace address register with calculated address register + MI.getOperand(FIOperandNum).ChangeToRegister(VL, false, false, true); + if (!IsRVVSpill) + MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset.getFixed()); + } + + auto ZvlssegInfo = TII->isRVVSpillForZvlsseg(MI.getOpcode()); + if (ZvlssegInfo) { + Register VL = MRI.createVirtualRegister(&RISCV::GPRRegClass); + BuildMI(MBB, II, DL, TII->get(RISCV::PseudoReadVLENB), VL); + uint32_t ShiftAmount = Log2_32(ZvlssegInfo->second); + if (ShiftAmount != 0) + BuildMI(MBB, II, DL, TII->get(RISCV::SLLI), VL) + .addReg(VL) + .addImm(ShiftAmount); + // The last argument of pseudo spilling opcode for zvlsseg is the length of + // one element of zvlsseg types. For example, for vint32m2x2_t, it will be + // the length of vint32m2_t. + MI.getOperand(FIOperandNum + 1).ChangeToRegister(VL, /*isDef=*/false); + } } Register RISCVRegisterInfo::getFrameRegister(const MachineFunction &MF) const { @@ -222,3 +312,11 @@ RISCVRegisterInfo::getCallPreservedMask(const MachineFunction & MF, return CSR_ILP32D_LP64D_RegMask; } } + +const TargetRegisterClass * +RISCVRegisterInfo::getLargestLegalSuperClass(const TargetRegisterClass *RC, + const MachineFunction &) const { + if (RC == &RISCV::VMV0RegClass) + return &RISCV::VRRegClass; + return RC; +} |