[llvm] [llvm][RISCV] Use zilsd for callee-saved register spill/restore on RV32 (PR #184794)
Brandon Wu via llvm-commits
llvm-commits at lists.llvm.org
Fri Mar 6 07:34:37 PST 2026
================
@@ -1633,6 +1651,59 @@ void RISCVFrameLowering::determineCalleeSaves(MachineFunction &MF,
if (RVFI->isPushable(MF) && SavedRegs.test(RISCV::X26))
SavedRegs.set(RISCV::X27);
+ // For Zilsd on RV32, append GPRPair registers to the CSR list. This prevents
+ // the need to create register sets for each abi which is a lot more complex.
+ // Don't use Zilsd for callee-saved coalescing if the required alignment
+ // exceeds the stack alignment.
+ bool UseZilsd = !STI.is64Bit() && STI.hasStdExtZilsd() &&
+ STI.getZilsdAlign() <= getStackAlign();
+ if (UseZilsd) {
+ SmallVector<MCPhysReg, 32> NewCSRs;
+ SmallSet<MCPhysReg, 16> CSRSet;
+ for (unsigned i = 0; CSRegs[i]; ++i) {
+ NewCSRs.push_back(CSRegs[i]);
+ CSRSet.insert(CSRegs[i]);
+ }
+
+ // Append GPRPair registers for pairs where both sub-registers are in CSR
+ // list. Iterate through all GPRPairs and check if both sub-regs are CSRs.
+ for (MCPhysReg Pair : RISCV::GPRPairRegClass) {
+ MCPhysReg EvenReg = TRI.getSubReg(Pair, RISCV::sub_gpr_even);
+ MCPhysReg OddReg = TRI.getSubReg(Pair, RISCV::sub_gpr_odd);
+ if (CSRSet.contains(EvenReg) && CSRSet.contains(OddReg))
+ NewCSRs.push_back(Pair);
+ }
+
+ MRI.setCalleeSavedRegs(NewCSRs);
+ CSRegs = MRI.getCalleeSavedRegs();
+ }
+
+ // Check if all subregisters are marked for saving. If so, set the super
+ // register bit. For GPRPair, only check sub_gpr_even and sub_gpr_odd, not
+ // aliases like X8_W or X8_H which are not set in SavedRegs.
+ for (unsigned i = 0; CSRegs[i]; ++i) {
+ unsigned CSReg = CSRegs[i];
+ bool CombineToSuperReg;
+ if (RISCV::GPRPairRegClass.contains(CSReg)) {
+ MCPhysReg EvenReg = TRI.getSubReg(CSReg, RISCV::sub_gpr_even);
+ MCPhysReg OddReg = TRI.getSubReg(CSReg, RISCV::sub_gpr_odd);
+ CombineToSuperReg = SavedRegs.test(EvenReg) && SavedRegs.test(OddReg);
+ // If s0(x8) is used as FP we can't generate load/store pair because it
+ // breaks the frame chain.
+ if (hasFP(MF) && CSReg == RISCV::X8_X9)
+ CombineToSuperReg = false;
+ } else {
+ auto SubRegs = TRI.subregs(CSReg);
+ CombineToSuperReg =
+ !SubRegs.empty() && llvm::all_of(SubRegs, [&](unsigned Reg) {
+ return SavedRegs.test(Reg);
+ });
+ }
+
+ if (CombineToSuperReg)
+ SavedRegs.set(CSReg);
----------------
4vtomat wrote:
I think later in `assignCalleeSavedSpillSlots` it will check if its super register is set to prevent double savings
https://github.com/llvm/llvm-project/pull/184794
More information about the llvm-commits
mailing list