[llvm] [RISCV] Optimize the spill/reload of segment registers (PR #153184)
Luke Lau via llvm-commits
llvm-commits at lists.llvm.org
Thu Aug 14 02:25:15 PDT 2025
================
@@ -403,148 +419,77 @@ void RISCVRegisterInfo::lowerVSPILL(MachineBasicBlock::iterator II) const {
auto ZvlssegInfo = RISCV::isRVVSpillForZvlsseg(II->getOpcode());
unsigned NF = ZvlssegInfo->first;
unsigned LMUL = ZvlssegInfo->second;
- assert(NF * LMUL <= 8 && "Invalid NF/LMUL combinations.");
- unsigned Opcode, SubRegIdx;
- switch (LMUL) {
- default:
- llvm_unreachable("LMUL must be 1, 2, or 4.");
- case 1:
- Opcode = RISCV::VS1R_V;
- SubRegIdx = RISCV::sub_vrm1_0;
- break;
- case 2:
- Opcode = RISCV::VS2R_V;
- SubRegIdx = RISCV::sub_vrm2_0;
- break;
- case 4:
- Opcode = RISCV::VS4R_V;
- SubRegIdx = RISCV::sub_vrm4_0;
- break;
- }
- static_assert(RISCV::sub_vrm1_7 == RISCV::sub_vrm1_0 + 7,
- "Unexpected subreg numbering");
- static_assert(RISCV::sub_vrm2_3 == RISCV::sub_vrm2_0 + 3,
- "Unexpected subreg numbering");
- static_assert(RISCV::sub_vrm4_1 == RISCV::sub_vrm4_0 + 1,
- "Unexpected subreg numbering");
-
- Register VL = MRI.createVirtualRegister(&RISCV::GPRRegClass);
- // Optimize for constant VLEN.
- if (auto VLEN = STI.getRealVLen()) {
- const int64_t VLENB = *VLEN / 8;
- int64_t Offset = VLENB * LMUL;
- STI.getInstrInfo()->movImm(MBB, II, DL, VL, Offset);
- } else {
- BuildMI(MBB, II, DL, TII->get(RISCV::PseudoReadVLENB), VL);
- uint32_t ShiftAmount = Log2_32(LMUL);
- if (ShiftAmount != 0)
- BuildMI(MBB, II, DL, TII->get(RISCV::SLLI), VL)
- .addReg(VL)
- .addImm(ShiftAmount);
- }
+ unsigned NumRegs = NF * LMUL;
+ assert(NumRegs <= 8 && "Invalid NF/LMUL combinations.");
- Register SrcReg = II->getOperand(0).getReg();
+ Register Reg = II->getOperand(0).getReg();
+ uint16_t RegEncoding = TRI->getEncodingValue(Reg);
Register Base = II->getOperand(1).getReg();
bool IsBaseKill = II->getOperand(1).isKill();
Register NewBase = MRI.createVirtualRegister(&RISCV::GPRRegClass);
auto *OldMMO = *(II->memoperands_begin());
LocationSize OldLoc = OldMMO->getSize();
assert(OldLoc.isPrecise() && OldLoc.getValue().isKnownMultipleOf(NF));
- TypeSize NewSize = OldLoc.getValue().divideCoefficientBy(NF);
- auto *NewMMO = MF.getMachineMemOperand(OldMMO, OldMMO->getOffset(), NewSize);
- for (unsigned I = 0; I < NF; ++I) {
- // Adding implicit-use of super register to describe we are using part of
- // super register, that prevents machine verifier complaining when part of
- // subreg is undef, see comment in MachineVerifier::checkLiveness for more
- // detail.
- BuildMI(MBB, II, DL, TII->get(Opcode))
- .addReg(TRI->getSubReg(SrcReg, SubRegIdx + I))
- .addReg(Base, getKillRegState(I == NF - 1))
- .addMemOperand(NewMMO)
- .addReg(SrcReg, RegState::Implicit);
- if (I != NF - 1)
+ TypeSize VRegSize = OldLoc.getValue().divideCoefficientBy(NumRegs);
+
+ Register VLENB = 0;
+ unsigned PreHandledNum = 0;
+ unsigned I = 0;
+ while (I != NumRegs) {
+ auto [LMulHandled, RegClass, Opcode] =
+ getSpillReloadInfo(NumRegs - I, RegEncoding, IsSpill);
+ auto [RegNumHandled, _] = RISCVVType::decodeVLMUL(LMulHandled);
+ if (PreHandledNum) {
+ Register Step;
+ // Optimize for constant VLEN.
+ if (auto VLEN = STI.getRealVLen()) {
+ int64_t Offset = *VLEN / 8 * PreHandledNum;
+ Step = MRI.createVirtualRegister(&RISCV::GPRRegClass);
+ STI.getInstrInfo()->movImm(MBB, II, DL, Step, Offset);
+ } else {
+ if (!VLENB) {
+ VLENB = MRI.createVirtualRegister(&RISCV::GPRRegClass);
+ BuildMI(MBB, II, DL, TII->get(RISCV::PseudoReadVLENB), VLENB);
+ }
+ uint32_t ShiftAmount = Log2_32(PreHandledNum);
+ if (ShiftAmount == 0)
+ Step = VLENB;
+ else {
+ Step = MRI.createVirtualRegister(&RISCV::GPRRegClass);
+ BuildMI(MBB, II, DL, TII->get(RISCV::SLLI), Step)
+ .addReg(VLENB)
----------------
lukel97 wrote:
Do we need to set the kill flag here if `I + RegNumHandled == NumRegs`?
https://github.com/llvm/llvm-project/pull/153184
More information about the llvm-commits
mailing list