[llvm] [RISCV] Fold shxadd into Xqcisls scaled load/store in RISCVMergeBaseOffset (PR #182221)
Sam Elliott via llvm-commits
llvm-commits at lists.llvm.org
Thu Feb 19 13:02:47 PST 2026
================
@@ -575,6 +576,114 @@ 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())
+ 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();
+ if (ShxOpc != RISCV::SH1ADD && ShxOpc != RISCV::SH2ADD &&
+ ShxOpc != RISCV::SH3ADD)
+ return false;
+
+ // shxadd Rd, Rs1, Rs2
+ Register Rd = ShxAdd.getOperand(0).getReg();
+ Register Rs1 = ShxAdd.getOperand(1).getReg();
+ Register Rs2 = ShxAdd.getOperand(2).getReg();
+
+ if (Rs2 != BaseReg)
+ return false;
+
+ if (!Rd.isVirtual() || !MRI->hasOneUse(Rd))
+ return false;
+
+ MachineInstr &TailMem = *MRI->use_instr_begin(Rd);
+ unsigned Opc = TailMem.getOpcode();
+
+ if (!TailMem.getOperand(1).isReg() || TailMem.getOperand(1).getReg() != Rd)
+ 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);
+
+ if (!isInt<32>(NewOffset))
+ return false;
+
+ 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;
+ }
+
+ Hi.getOperand(1).setOffset(NewOffset);
+ TailMem.getOperand(2).ChangeToImmediate(0);
----------------
lenary wrote:
The modification of `TailMem` is a little pointless, right? Maybe it adds clarity that you're moving the immediate into `Hi`.
https://github.com/llvm/llvm-project/pull/182221
More information about the llvm-commits
mailing list