[llvm] [RISCV] Optimize the spill/reload of segment registers (PR #153184)
Craig Topper via llvm-commits
llvm-commits at lists.llvm.org
Mon Aug 18 14:57:32 PDT 2025
================
@@ -403,148 +419,78 @@ 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, getKillRegState(I + RegNumHandled == NumRegs))
+ .addImm(ShiftAmount);
+ }
+ }
+
BuildMI(MBB, II, DL, TII->get(RISCV::ADD), NewBase)
.addReg(Base, getKillRegState(I != 0 || IsBaseKill))
- .addReg(VL, getKillRegState(I == NF - 2));
- Base = NewBase;
- }
- II->eraseFromParent();
-}
+ .addReg(Step, getKillRegState(Step != VLENB ||
+ I + RegNumHandled == NumRegs));
+ Base = NewBase;
+ }
-// Split a VSPILLx_Mx pseudo into multiple whole register loads separated by
-// LMUL*VLENB bytes.
-void RISCVRegisterInfo::lowerVRELOAD(MachineBasicBlock::iterator II) const {
- DebugLoc DL = II->getDebugLoc();
- MachineBasicBlock &MBB = *II->getParent();
- MachineFunction &MF = *MBB.getParent();
- MachineRegisterInfo &MRI = MF.getRegInfo();
- const RISCVSubtarget &STI = MF.getSubtarget<RISCVSubtarget>();
- const TargetInstrInfo *TII = STI.getInstrInfo();
- const TargetRegisterInfo *TRI = STI.getRegisterInfo();
+ MCRegister ActualReg = findVRegWithEncoding(RegClass, RegEncoding);
+ MachineInstrBuilder MI;
+ if (IsSpill)
----------------
topperc wrote:
You can combine these two BuildMIs with
```
MI = BuildMI(MBB, II, DL, TII->get(Opcode)).addReg(ActualReg, getDefRegState(!IsSpill));
```
https://github.com/llvm/llvm-project/pull/153184
More information about the llvm-commits
mailing list