[llvm] d9b72ba - [RISCV] Generate Xqcilsm QC_SETWMI store multiple instruction (#172438)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Dec 16 08:42:30 PST 2025
Author: Sudharsan Veeravalli
Date: 2025-12-16T22:12:26+05:30
New Revision: d9b72bafc034feb3f88823ab2b874cae5d46096a
URL: https://github.com/llvm/llvm-project/commit/d9b72bafc034feb3f88823ab2b874cae5d46096a
DIFF: https://github.com/llvm/llvm-project/commit/d9b72bafc034feb3f88823ab2b874cae5d46096a.diff
LOG: [RISCV] Generate Xqcilsm QC_SETWMI store multiple instruction (#172438)
Similar to #171079 generate `QC_SETWMI` store multiple instructions for
two adjacent store instructions in a basic block.
Added:
Modified:
llvm/lib/Target/RISCV/RISCVLoadStoreOptimizer.cpp
llvm/test/CodeGen/RISCV/xqcilsm-lwmi-swmi.mir
llvm/test/CodeGen/RISCV/xqcilsm-memset.ll
Removed:
################################################################################
diff --git a/llvm/lib/Target/RISCV/RISCVLoadStoreOptimizer.cpp b/llvm/lib/Target/RISCV/RISCVLoadStoreOptimizer.cpp
index 5eef1a998719f..ff5894e1a657d 100644
--- a/llvm/lib/Target/RISCV/RISCVLoadStoreOptimizer.cpp
+++ b/llvm/lib/Target/RISCV/RISCVLoadStoreOptimizer.cpp
@@ -214,31 +214,47 @@ bool RISCVLoadStoreOpt::tryConvertToXqcilsmLdStPair(
std::swap(Off1, Off2);
}
+ if (!isShiftedUInt<5, 2>(Off1) || (Off2 - Off1 != 4))
+ return false;
+
Register StartReg = FirstOp0.getReg();
Register NextReg = SecondOp0.getReg();
- if (StartReg == RISCV::X0 || NextReg == RISCV::X0)
- return false;
+ unsigned XqciOpc;
+ unsigned StartRegState;
+ unsigned NextRegState = 0;
+ bool AddNextReg = true;
- // If the base reg gets overwritten by one of the loads then bail out.
- if (Opc == RISCV::LW && (StartReg == Base1 || NextReg == Base1))
- return false;
+ if (Opc == RISCV::LW) {
- if (!isShiftedUInt<5, 2>(Off1) || (Off2 - Off1 != 4))
- return false;
+ if (StartReg == RISCV::X0)
+ return false;
- if (NextReg != StartReg + 1)
- return false;
+ // If the base reg gets overwritten by one of the loads bail out.
+ if (StartReg == Base1 || NextReg == Base1)
+ return false;
- unsigned XqciOpc = (Opc == RISCV::LW) ? RISCV::QC_LWMI : RISCV::QC_SWMI;
+ // The registers need to be consecutive.
+ if (NextReg != StartReg + 1)
+ return false;
- unsigned StartRegState = (Opc == RISCV::LW)
- ? static_cast<unsigned>(RegState::Define)
- : getKillRegState(FirstOp0.isKill());
- unsigned NextRegState =
- (Opc == RISCV::LW)
- ? static_cast<unsigned>(RegState::ImplicitDefine)
- : (RegState::Implicit | getKillRegState(SecondOp0.isKill()));
+ XqciOpc = RISCV::QC_LWMI;
+ StartRegState = static_cast<unsigned>(RegState::Define);
+ NextRegState = static_cast<unsigned>(RegState::ImplicitDefine);
+ } else {
+ assert(Opc == RISCV::SW && "Expected a SW instruction");
+ if (StartReg == NextReg) {
+ XqciOpc = RISCV::QC_SETWMI;
+ StartRegState = getKillRegState(FirstOp0.isKill() || SecondOp0.isKill());
+ AddNextReg = false;
+ } else if (NextReg == StartReg + 1) {
+ XqciOpc = RISCV::QC_SWMI;
+ StartRegState = getKillRegState(FirstOp0.isKill());
+ NextRegState = RegState::Implicit | getKillRegState(SecondOp0.isKill());
+ } else {
+ return false;
+ }
+ }
DebugLoc DL =
First->getDebugLoc() ? First->getDebugLoc() : Second->getDebugLoc();
@@ -247,8 +263,10 @@ bool RISCVLoadStoreOpt::tryConvertToXqcilsmLdStPair(
.addReg(Base1, getKillRegState(FirstOp1.isKill() || SecondOp1.isKill()))
.addImm(2)
.addImm(Off1)
- .cloneMergedMemRefs({&*First, &*Second})
- .addReg(NextReg, NextRegState);
+ .cloneMergedMemRefs({&*First, &*Second});
+
+ if (AddNextReg)
+ MIB.addReg(NextReg, NextRegState);
First->getParent()->insert(First, MIB);
First->removeFromParent();
diff --git a/llvm/test/CodeGen/RISCV/xqcilsm-lwmi-swmi.mir b/llvm/test/CodeGen/RISCV/xqcilsm-lwmi-swmi.mir
index 396f67326a7ca..126c1fd442000 100644
--- a/llvm/test/CodeGen/RISCV/xqcilsm-lwmi-swmi.mir
+++ b/llvm/test/CodeGen/RISCV/xqcilsm-lwmi-swmi.mir
@@ -20,6 +20,9 @@
define void @pair_if_not_adjacent() nounwind { ret void }
define void @pair_if_not_adjacent_use() nounwind { ret void }
define void @no_pair_if_not_adjacent_use() nounwind { ret void }
+ define void @pair_two_sw_into_qc_setwmi() nounwind { ret void }
+ define void @pair_two_sw_into_qc_setwmi_reversed() nounwind { ret void }
+ define void @pair_if_not_adjacent_setwmi() nounwind { ret void }
---
name: pair_two_lw_into_qc_lwmi
tracksRegLiveness: false
@@ -313,3 +316,53 @@ body: |
PseudoRET
...
+---
+name: pair_two_sw_into_qc_setwmi
+tracksRegLiveness: false
+body: |
+ bb.0:
+ liveins: $x10, $x1
+ ; CHECK-LABEL: name: pair_two_sw_into_qc_setwmi
+ ; CHECK: liveins: $x10, $x1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: QC_SETWMI $x1, $x10, 2, 20 :: (store (s32))
+ ; CHECK-NEXT: PseudoRET
+ SW $x1, $x10, 20 :: (store (s32), align 4)
+ SW $x1, $x10, 24 :: (store (s32), align 4)
+ PseudoRET
+
+...
+---
+name: pair_two_sw_into_qc_setwmi_reversed
+tracksRegLiveness: false
+body: |
+ bb.0:
+ liveins: $x10, $x2
+ ; CHECK-LABEL: name: pair_two_sw_into_qc_setwmi_reversed
+ ; CHECK: liveins: $x10, $x2
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: QC_SETWMI $x2, $x10, 2, 20 :: (store (s32))
+ ; CHECK-NEXT: PseudoRET
+ SW $x2, $x10, 24 :: (store (s32), align 4)
+ SW $x2, $x10, 20 :: (store (s32), align 4)
+ PseudoRET
+
+...
+---
+name: pair_if_not_adjacent_setwmi
+tracksRegLiveness: false
+body: |
+ bb.0:
+ liveins: $x10, $x1
+ ; CHECK-LABEL: name: pair_if_not_adjacent_setwmi
+ ; CHECK: liveins: $x10, $x1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: QC_SETWMI killed $x1, $x10, 2, 20 :: (store (s32))
+ ; CHECK-NEXT: $x2 = ADDI $x2, 10
+ ; CHECK-NEXT: PseudoRET
+ SW $x1, $x10, 20 :: (store (s32), align 4)
+ $x2 = ADDI $x2, 10
+ SW killed $x1, $x10, 24 :: (store (s32), align 4)
+ PseudoRET
+
+...
diff --git a/llvm/test/CodeGen/RISCV/xqcilsm-memset.ll b/llvm/test/CodeGen/RISCV/xqcilsm-memset.ll
index 2fad19a653f1f..e0546a41779f7 100644
--- a/llvm/test/CodeGen/RISCV/xqcilsm-memset.ll
+++ b/llvm/test/CodeGen/RISCV/xqcilsm-memset.ll
@@ -130,8 +130,7 @@ define void @test2d(ptr nocapture %p) nounwind {
; RV32IXQCILSM-NEXT: lui a3, 678490
; RV32IXQCILSM-NEXT: addi a2, a2, 1445
; RV32IXQCILSM-NEXT: addi a3, a3, 1445
-; RV32IXQCILSM-NEXT: sw a3, 0(a0)
-; RV32IXQCILSM-NEXT: sw a3, 4(a0)
+; RV32IXQCILSM-NEXT: qc.setwmi a3, 2, 0(a0)
; RV32IXQCILSM-NEXT: sh a2, 8(a0)
; RV32IXQCILSM-NEXT: sb a1, 10(a0)
; RV32IXQCILSM-NEXT: ret
@@ -380,8 +379,7 @@ define i64 @test6b_ll() nounwind {
; RV32IXQCILSM-LABEL: test6b_ll:
; RV32IXQCILSM: # %bb.0: # %entry
; RV32IXQCILSM-NEXT: addi sp, sp, -16
-; RV32IXQCILSM-NEXT: sw zero, 8(sp)
-; RV32IXQCILSM-NEXT: sw zero, 12(sp)
+; RV32IXQCILSM-NEXT: qc.setwmi zero, 2, 8(sp)
; RV32IXQCILSM-NEXT: lw a0, 8(sp)
; RV32IXQCILSM-NEXT: lw a1, 12(sp)
; RV32IXQCILSM-NEXT: addi sp, sp, 16
@@ -478,8 +476,7 @@ define i64 @test6c_ll() nounwind {
; RV32IXQCILSM-LABEL: test6c_ll:
; RV32IXQCILSM: # %bb.0: # %entry
; RV32IXQCILSM-NEXT: addi sp, sp, -16
-; RV32IXQCILSM-NEXT: sw zero, 8(sp)
-; RV32IXQCILSM-NEXT: sw zero, 12(sp)
+; RV32IXQCILSM-NEXT: qc.setwmi zero, 2, 8(sp)
; RV32IXQCILSM-NEXT: li a0, 0
; RV32IXQCILSM-NEXT: li a1, 0
; RV32IXQCILSM-NEXT: addi sp, sp, 16
@@ -504,8 +501,7 @@ define void @test7() nounwind {
; RV32IXQCILSM: # %bb.0:
; RV32IXQCILSM-NEXT: lui a0, %hi(arr1)
; RV32IXQCILSM-NEXT: addi a0, a0, %lo(arr1)
-; RV32IXQCILSM-NEXT: sw zero, 0(a0)
-; RV32IXQCILSM-NEXT: sw zero, 4(a0)
+; RV32IXQCILSM-NEXT: qc.setwmi zero, 2, 0(a0)
; RV32IXQCILSM-NEXT: ret
tail call void @llvm.memset.p0.i32(ptr align 4 @arr1, i8 0, i32 8, i1 false)
ret void
@@ -543,10 +539,8 @@ define void @test7a_unalign() nounwind {
; RV32IXQCILSM-NEXT: addi a0, a0, %lo(arr1)
; RV32IXQCILSM-NEXT: li a1, -1
; RV32IXQCILSM-NEXT: sb a1, 16(a0)
-; RV32IXQCILSM-NEXT: sw a1, 0(a0)
-; RV32IXQCILSM-NEXT: sw a1, 4(a0)
-; RV32IXQCILSM-NEXT: sw a1, 8(a0)
-; RV32IXQCILSM-NEXT: sw a1, 12(a0)
+; RV32IXQCILSM-NEXT: qc.setwmi a1, 2, 0(a0)
+; RV32IXQCILSM-NEXT: qc.setwmi a1, 2, 8(a0)
; RV32IXQCILSM-NEXT: ret
entry:
tail call void @llvm.memset.p0.i32(ptr align 4 @arr1, i8 -1, i32 17, i1 false)
@@ -660,10 +654,8 @@ define void @test8() nounwind {
; RV32IXQCILSM: # %bb.0: # %entry
; RV32IXQCILSM-NEXT: lui a0, %hi(arr1)
; RV32IXQCILSM-NEXT: addi a0, a0, %lo(arr1)
-; RV32IXQCILSM-NEXT: sw zero, 0(a0)
-; RV32IXQCILSM-NEXT: sw zero, 4(a0)
-; RV32IXQCILSM-NEXT: sw zero, 8(a0)
-; RV32IXQCILSM-NEXT: sw zero, 12(a0)
+; RV32IXQCILSM-NEXT: qc.setwmi zero, 2, 0(a0)
+; RV32IXQCILSM-NEXT: qc.setwmi zero, 2, 8(a0)
; RV32IXQCILSM-NEXT: ret
entry:
tail call void @llvm.memset.p0.i32(ptr align 4 @arr1, i8 0, i32 16, i1 false)
@@ -689,14 +681,10 @@ define void @test9() nounwind {
; RV32IXQCILSM: # %bb.0: # %entry
; RV32IXQCILSM-NEXT: lui a0, %hi(arr1)
; RV32IXQCILSM-NEXT: addi a0, a0, %lo(arr1)
-; RV32IXQCILSM-NEXT: sw zero, 16(a0)
-; RV32IXQCILSM-NEXT: sw zero, 20(a0)
-; RV32IXQCILSM-NEXT: sw zero, 24(a0)
-; RV32IXQCILSM-NEXT: sw zero, 28(a0)
-; RV32IXQCILSM-NEXT: sw zero, 0(a0)
-; RV32IXQCILSM-NEXT: sw zero, 4(a0)
-; RV32IXQCILSM-NEXT: sw zero, 8(a0)
-; RV32IXQCILSM-NEXT: sw zero, 12(a0)
+; RV32IXQCILSM-NEXT: qc.setwmi zero, 2, 16(a0)
+; RV32IXQCILSM-NEXT: qc.setwmi zero, 2, 24(a0)
+; RV32IXQCILSM-NEXT: qc.setwmi zero, 2, 0(a0)
+; RV32IXQCILSM-NEXT: qc.setwmi zero, 2, 8(a0)
; RV32IXQCILSM-NEXT: ret
entry:
tail call void @llvm.memset.p0.i32(ptr align 4 @arr1, i8 0, i32 32, i1 false)
More information about the llvm-commits
mailing list