[llvm] [RISCV] Merge zeroing stores into wider LMUL vector stores (PR #223908)

via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 15 21:05:30 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-risc-v

Author: Pengcheng Wang (wangpc-pp)

<details>
<summary>Changes</summary>

memset lowers to LMUL1 vector stores (v2i64 for e64) that we rely on
store merging to widen. `storeOfVectorConstantIsCheap` counted the
number of MemVT-sized stores, so a v2i64 MemVT needed 4 stores before
merging kicked in, leaving two VL=2 m1 stores for a 32B zero region.

Use the total element count for zeroing stores so two v2i64 stores
merge into one VL=4 e64 m2 store.

Partially fixes #<!-- -->223906

Assisted-by: TRAE CLI (Opus 4.8)


---
Full diff: https://github.com/llvm/llvm-project/pull/223908.diff


4 Files Affected:

- (modified) llvm/lib/Target/RISCV/RISCVISelLowering.h (+10-2) 
- (modified) llvm/test/CodeGen/RISCV/rvv/memset-inline.ll (+16-34) 
- (modified) llvm/test/CodeGen/RISCV/rvv/pr83017.ll (+3-5) 
- (modified) llvm/test/CodeGen/RISCV/rvv/pr90559.ll (+4-6) 


``````````diff
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.h b/llvm/lib/Target/RISCV/RISCVISelLowering.h
index a7f5a1304863e..661e2f041236b 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.h
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.h
@@ -217,8 +217,16 @@ class RISCVTargetLowering : public TargetLowering {
 
   bool storeOfVectorConstantIsCheap(bool IsZero, EVT MemVT, unsigned NumElem,
                                     unsigned AddrSpace) const override {
-    // If we can replace 4 or more scalar stores, there will be a reduction
-    // in instructions even after we add a vector constant load.
+    // A zero splat is free to materialize, so merging is a win once it
+    // covers 4 or more elements.  MemVT may already be a vector, since
+    // memset lowers to LMUL1 stores that we want to merge into a larger
+    // LMUL, so use the total element count.
+    unsigned NumMemElts = MemVT.isVector() ? MemVT.getVectorNumElements() : 1;
+    if (IsZero)
+      return NumElem * NumMemElts >= 4;
+
+    // Non-zero vector constants aren't always cheap to materialize; only
+    // merge when replacing 4 or more scalar stores.
     return NumElem >= 4;
   }
 
diff --git a/llvm/test/CodeGen/RISCV/rvv/memset-inline.ll b/llvm/test/CodeGen/RISCV/rvv/memset-inline.ll
index 0417b36fd9db5..d3e8de8b1730e 100644
--- a/llvm/test/CodeGen/RISCV/rvv/memset-inline.ll
+++ b/llvm/test/CodeGen/RISCV/rvv/memset-inline.ll
@@ -501,38 +501,32 @@ define void @memset_zero_16(ptr %a) nounwind {
 define void @memset_zero_32(ptr %a) nounwind {
 ; RV32-LABEL: memset_zero_32:
 ; RV32:       # %bb.0:
-; RV32-NEXT:    vsetivli zero, 16, e8, m1, ta, ma
+; RV32-NEXT:    li a1, 32
+; RV32-NEXT:    vsetvli zero, a1, e8, m2, ta, ma
 ; RV32-NEXT:    vmv.v.i v8, 0
-; RV32-NEXT:    addi a1, a0, 16
 ; RV32-NEXT:    vse8.v v8, (a0)
-; RV32-NEXT:    vse8.v v8, (a1)
 ; RV32-NEXT:    ret
 ;
 ; RV64-LABEL: memset_zero_32:
 ; RV64:       # %bb.0:
-; RV64-NEXT:    vsetivli zero, 16, e8, m1, ta, ma
+; RV64-NEXT:    li a1, 32
+; RV64-NEXT:    vsetvli zero, a1, e8, m2, ta, ma
 ; RV64-NEXT:    vmv.v.i v8, 0
-; RV64-NEXT:    addi a1, a0, 16
 ; RV64-NEXT:    vse8.v v8, (a0)
-; RV64-NEXT:    vse8.v v8, (a1)
 ; RV64-NEXT:    ret
 ;
 ; RV32-FAST-LABEL: memset_zero_32:
 ; RV32-FAST:       # %bb.0:
-; RV32-FAST-NEXT:    vsetivli zero, 2, e64, m1, ta, ma
+; RV32-FAST-NEXT:    vsetivli zero, 4, e64, m2, ta, ma
 ; RV32-FAST-NEXT:    vmv.v.i v8, 0
-; RV32-FAST-NEXT:    addi a1, a0, 16
 ; RV32-FAST-NEXT:    vse64.v v8, (a0)
-; RV32-FAST-NEXT:    vse64.v v8, (a1)
 ; RV32-FAST-NEXT:    ret
 ;
 ; RV64-FAST-LABEL: memset_zero_32:
 ; RV64-FAST:       # %bb.0:
-; RV64-FAST-NEXT:    vsetivli zero, 2, e64, m1, ta, ma
+; RV64-FAST-NEXT:    vsetivli zero, 4, e64, m2, ta, ma
 ; RV64-FAST-NEXT:    vmv.v.i v8, 0
-; RV64-FAST-NEXT:    addi a1, a0, 16
 ; RV64-FAST-NEXT:    vse64.v v8, (a0)
-; RV64-FAST-NEXT:    vse64.v v8, (a1)
 ; RV64-FAST-NEXT:    ret
   tail call void @llvm.memset.inline.p0.i64(ptr %a, i8 0, i64 32, i1 0)
   ret void
@@ -638,20 +632,16 @@ define void @aligned_memset_zero_16(ptr %a) nounwind {
 define void @aligned_memset_zero_32(ptr %a) nounwind {
 ; RV32-BOTH-LABEL: aligned_memset_zero_32:
 ; RV32-BOTH:       # %bb.0:
-; RV32-BOTH-NEXT:    vsetivli zero, 2, e64, m1, ta, ma
+; RV32-BOTH-NEXT:    vsetivli zero, 4, e64, m2, ta, ma
 ; RV32-BOTH-NEXT:    vmv.v.i v8, 0
-; RV32-BOTH-NEXT:    addi a1, a0, 16
 ; RV32-BOTH-NEXT:    vse64.v v8, (a0)
-; RV32-BOTH-NEXT:    vse64.v v8, (a1)
 ; RV32-BOTH-NEXT:    ret
 ;
 ; RV64-BOTH-LABEL: aligned_memset_zero_32:
 ; RV64-BOTH:       # %bb.0:
-; RV64-BOTH-NEXT:    vsetivli zero, 2, e64, m1, ta, ma
+; RV64-BOTH-NEXT:    vsetivli zero, 4, e64, m2, ta, ma
 ; RV64-BOTH-NEXT:    vmv.v.i v8, 0
-; RV64-BOTH-NEXT:    addi a1, a0, 16
 ; RV64-BOTH-NEXT:    vse64.v v8, (a0)
-; RV64-BOTH-NEXT:    vse64.v v8, (a1)
 ; RV64-BOTH-NEXT:    ret
   tail call void @llvm.memset.inline.p0.i64(ptr align 32 %a, i8 0, i64 32, i1 0)
   ret void
@@ -698,31 +688,23 @@ define void @aligned_memset_zero_66(ptr %a) nounwind {
 define void @aligned_memset_zero_96(ptr %a) nounwind {
 ; RV32-BOTH-LABEL: aligned_memset_zero_96:
 ; RV32-BOTH:       # %bb.0:
-; RV32-BOTH-NEXT:    vsetivli zero, 2, e64, m1, ta, ma
-; RV32-BOTH-NEXT:    vmv.v.i v12, 0
 ; RV32-BOTH-NEXT:    vsetivli zero, 8, e64, m4, ta, ma
 ; RV32-BOTH-NEXT:    vmv.v.i v8, 0
-; RV32-BOTH-NEXT:    addi a1, a0, 80
-; RV32-BOTH-NEXT:    vsetivli zero, 2, e64, m1, ta, ma
-; RV32-BOTH-NEXT:    vse64.v v12, (a1)
-; RV32-BOTH-NEXT:    addi a1, a0, 64
-; RV32-BOTH-NEXT:    vse64.v v12, (a1)
-; RV32-BOTH-NEXT:    vsetivli zero, 8, e64, m4, ta, ma
+; RV32-BOTH-NEXT:    vse64.v v8, (a0)
+; RV32-BOTH-NEXT:    vsetivli zero, 4, e64, m2, ta, ma
+; RV32-BOTH-NEXT:    vmv.v.i v8, 0
+; RV32-BOTH-NEXT:    addi a0, a0, 64
 ; RV32-BOTH-NEXT:    vse64.v v8, (a0)
 ; RV32-BOTH-NEXT:    ret
 ;
 ; RV64-BOTH-LABEL: aligned_memset_zero_96:
 ; RV64-BOTH:       # %bb.0:
-; RV64-BOTH-NEXT:    vsetivli zero, 2, e64, m1, ta, ma
-; RV64-BOTH-NEXT:    vmv.v.i v12, 0
 ; RV64-BOTH-NEXT:    vsetivli zero, 8, e64, m4, ta, ma
 ; RV64-BOTH-NEXT:    vmv.v.i v8, 0
-; RV64-BOTH-NEXT:    addi a1, a0, 80
-; RV64-BOTH-NEXT:    vsetivli zero, 2, e64, m1, ta, ma
-; RV64-BOTH-NEXT:    vse64.v v12, (a1)
-; RV64-BOTH-NEXT:    addi a1, a0, 64
-; RV64-BOTH-NEXT:    vse64.v v12, (a1)
-; RV64-BOTH-NEXT:    vsetivli zero, 8, e64, m4, ta, ma
+; RV64-BOTH-NEXT:    vse64.v v8, (a0)
+; RV64-BOTH-NEXT:    vsetivli zero, 4, e64, m2, ta, ma
+; RV64-BOTH-NEXT:    vmv.v.i v8, 0
+; RV64-BOTH-NEXT:    addi a0, a0, 64
 ; RV64-BOTH-NEXT:    vse64.v v8, (a0)
 ; RV64-BOTH-NEXT:    ret
   tail call void @llvm.memset.inline.p0.i64(ptr align 64 %a, i8 0, i64 96, i1 0)
diff --git a/llvm/test/CodeGen/RISCV/rvv/pr83017.ll b/llvm/test/CodeGen/RISCV/rvv/pr83017.ll
index fc509deb63236..47124ee314e19 100644
--- a/llvm/test/CodeGen/RISCV/rvv/pr83017.ll
+++ b/llvm/test/CodeGen/RISCV/rvv/pr83017.ll
@@ -30,15 +30,13 @@
 define void @aliasing(ptr %p) {
 ; CHECK-LABEL: aliasing:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    vsetivli zero, 16, e8, m1, ta, ma
+; CHECK-NEXT:    vsetvli a1, zero, e8, m2, ta, ma
 ; CHECK-NEXT:    vmv.v.i v12, 0
 ; CHECK-NEXT:    vsetvli a1, zero, e8, m4, ta, ma
 ; CHECK-NEXT:    vmv.v.i v8, 0
-; CHECK-NEXT:    addi a1, a0, 80
-; CHECK-NEXT:    lw a2, 84(a0)
-; CHECK-NEXT:    vs1r.v v12, (a1)
 ; CHECK-NEXT:    addi a1, a0, 64
-; CHECK-NEXT:    vs1r.v v12, (a1)
+; CHECK-NEXT:    lw a2, 84(a0)
+; CHECK-NEXT:    vs2r.v v12, (a1)
 ; CHECK-NEXT:    vs4r.v v8, (a0)
 ; CHECK-NEXT:    sw a2, 84(a0)
 ; CHECK-NEXT:    ret
diff --git a/llvm/test/CodeGen/RISCV/rvv/pr90559.ll b/llvm/test/CodeGen/RISCV/rvv/pr90559.ll
index 1632244abafbc..818bdb800ca60 100644
--- a/llvm/test/CodeGen/RISCV/rvv/pr90559.ll
+++ b/llvm/test/CodeGen/RISCV/rvv/pr90559.ll
@@ -27,17 +27,15 @@
 define void @f(ptr %p) vscale_range(2,2) {
 ; CHECK-LABEL: f:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    vsetivli zero, 16, e8, m1, ta, ma
+; CHECK-NEXT:    vsetvli a1, zero, e8, m2, ta, ma
 ; CHECK-NEXT:    vmv.v.i v12, 0
 ; CHECK-NEXT:    vsetvli a1, zero, e8, m4, ta, ma
 ; CHECK-NEXT:    vmv.v.i v8, 0
-; CHECK-NEXT:    addi a1, a0, 80
-; CHECK-NEXT:    lw a2, 84(a0)
-; CHECK-NEXT:    vs1r.v v12, (a1)
 ; CHECK-NEXT:    addi a1, a0, 64
-; CHECK-NEXT:    vs1r.v v12, (a1)
-; CHECK-NEXT:    sw a2, 84(a0)
+; CHECK-NEXT:    lw a2, 84(a0)
+; CHECK-NEXT:    vs2r.v v12, (a1)
 ; CHECK-NEXT:    vs4r.v v8, (a0)
+; CHECK-NEXT:    sw a2, 84(a0)
 ; CHECK-NEXT:    ret
   %q = getelementptr inbounds i8, ptr %p, i64 84
   %x = load i32, ptr %q

``````````

</details>


https://github.com/llvm/llvm-project/pull/223908


More information about the llvm-commits mailing list