[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