[llvm] [RISCV] Fold shladd into Xqcisls scaled load/store in RISCVMergeBaseOffset (PR #182221)
Craig Topper via llvm-commits
llvm-commits at lists.llvm.org
Fri Feb 20 18:52:47 PST 2026
================
@@ -575,6 +576,126 @@ bool RISCVMergeBaseOffsetOpt::foldIntoMemoryOps(MachineInstr &Hi,
return true;
}
+// Try to fold sequences of the form:
+// Hi/lo: qc.e.li vreg1, s -> qc.e.li vreg1, s+imm
+// TailAdd: shxadd vreg2, vreg3, vreg1 -> deleted
+// Tail: lx vreg4, imm(vreg2) -> qc.lrx vreg4, vreg1, vreg3, (1/2/3)
+bool RISCVMergeBaseOffsetOpt::foldShxaddIntoScaledMemory(MachineInstr &Hi,
+ MachineInstr &Lo) {
+ if (!ST->hasVendorXqcisls() || ST->is64Bit())
+ return false;
+
+ if (Hi.getOpcode() != RISCV::QC_E_LI)
+ return false;
+
+ Register BaseReg = Hi.getOperand(0).getReg();
+ if (!BaseReg.isVirtual() || !MRI->hasOneUse(BaseReg))
+ return false;
+
+ MachineInstr &ShxAdd = *MRI->use_instr_begin(BaseReg);
+ unsigned ShxOpc = ShxAdd.getOpcode();
+ unsigned ShAmt = 0;
+ switch (ShxOpc) {
+ default:
+ return false;
+ case RISCV::SH1ADD:
+ ShAmt = 1;
+ break;
+ case RISCV::SH2ADD:
+ ShAmt = 2;
+ break;
+ case RISCV::SH3ADD:
+ ShAmt = 3;
+ break;
+ case RISCV::QC_SHLADD:
+ uint8_t ShlImm = ShxAdd.getOperand(3).getImm();
+ if (ShlImm > 7)
+ return false;
+ ShAmt = ShlImm;
+ break;
+ }
+
+ // shxadd Rd, Rs1, Rs2
+ Register ScaledReg = ShxAdd.getOperand(0).getReg();
+ Register IndexReg = ShxAdd.getOperand(1).getReg();
+
+ if (!IndexReg.isVirtual())
+ return false;
+
+ if (ShxAdd.getOperand(2).getReg() != BaseReg)
+ return false;
+
+ if (!ScaledReg.isVirtual() || !MRI->hasOneUse(ScaledReg))
+ return false;
+
+ MachineInstr &TailMem = *MRI->use_instr_begin(ScaledReg);
+ unsigned Opc = TailMem.getOpcode();
+ unsigned NewOpc = 0;
+
+ switch (Opc) {
+ case RISCV::LB:
+ NewOpc = RISCV::QC_LRB;
+ break;
+ case RISCV::LBU:
+ NewOpc = RISCV::QC_LRBU;
+ break;
+ case RISCV::LH:
+ NewOpc = RISCV::QC_LRH;
+ break;
+ case RISCV::LHU:
+ NewOpc = RISCV::QC_LRHU;
+ break;
+ case RISCV::LW:
+ NewOpc = RISCV::QC_LRW;
+ break;
+ case RISCV::SB:
+ NewOpc = RISCV::QC_SRB;
+ break;
+ case RISCV::SH:
+ NewOpc = RISCV::QC_SRH;
+ break;
+ case RISCV::SW:
+ NewOpc = RISCV::QC_SRW;
+ break;
+ default:
+ return false;
+ }
+
+ if (!TailMem.getOperand(1).isReg() ||
+ TailMem.getOperand(1).getReg() != ScaledReg)
+ return false;
+ if (!TailMem.getOperand(2).isImm())
+ return false;
+ int64_t Imm = TailMem.getOperand(2).getImm();
+
+ // Update QC_E_LI offset.
+ int64_t NewOffset = SignExtend64<32>(Hi.getOperand(1).getOffset() + Imm);
+
+ Hi.getOperand(1).setOffset(NewOffset);
+
+ // Build scaled load/store.
+ auto *TII = ST->getInstrInfo();
+ auto *MBB = TailMem.getParent();
+ RegState DestRegState;
+ DestRegState = TailMem.mayLoad()
+ ? RegState::Define
+ : getKillRegState(TailMem.getOperand(0).isKill());
+
+ // Ensure index register satisfies GPRNoX0 class required by QC_LR*/QC_SR*.
+ MRI->constrainRegClass(IndexReg, &RISCV::GPRNoX0RegClass);
+
+ BuildMI(*MBB, TailMem, TailMem.getDebugLoc(), TII->get(NewOpc))
+ .addReg(TailMem.getOperand(0).getReg(), DestRegState)
----------------
topperc wrote:
Can we use `.add(TailMem.getOperand(0))`?
https://github.com/llvm/llvm-project/pull/182221
More information about the llvm-commits
mailing list