[llvm-branch-commits] [llvm] release/23.x: [RISCV] Avoid pre-RA Zilsd pairs with same src/dst registers (#215575) (PR #215602)

Douglas Yung via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Sat Aug 15 08:43:16 PDT 2026


https://github.com/dyung updated https://github.com/llvm/llvm-project/pull/215602

>From 4a94b37026f5b50bcdc7f4711f65a61816514e1d Mon Sep 17 00:00:00 2001
From: Sudharsan Veeravalli <svs at qti.qualcomm.com>
Date: Tue, 11 Aug 2026 21:28:46 +0530
Subject: [PATCH] [RISCV] Avoid pre-RA Zilsd pairs with same src/dst registers
 (#215575)

The pre-RA Zilsd optimizer previously allowed a special case for stores
where both source operands were the same vreg if that vreg was defined
by COPY $x0. This assumes register allocation will preserve the value as
x0, but that is not guaranteed. The vreg can be allocated to a normal
GPR, producing an invalid pair.

(cherry picked from commit 4ef2427b4c08fd28e4244c585ae0673711e4c0d6)
---
 llvm/lib/Target/RISCV/RISCVZilsdOptimizer.cpp | 16 +-----
 .../CodeGen/RISCV/zilsd-ldst-opt-prera.mir    |  3 +-
 llvm/test/CodeGen/RISCV/zilsd.ll              | 55 +++++++++++++++----
 3 files changed, 48 insertions(+), 26 deletions(-)

diff --git a/llvm/lib/Target/RISCV/RISCVZilsdOptimizer.cpp b/llvm/lib/Target/RISCV/RISCVZilsdOptimizer.cpp
index 54908b31f6299..1886ccc0b8186 100644
--- a/llvm/lib/Target/RISCV/RISCVZilsdOptimizer.cpp
+++ b/llvm/lib/Target/RISCV/RISCVZilsdOptimizer.cpp
@@ -212,22 +212,8 @@ bool RISCVPreAllocZilsdOpt::canFormLdSdPair(MachineInstr *MI0,
 
   // Check that the two destination/source registers are different for
   // load/store respectively.
-  // The only case two destinations/sources can be same is (x0, x0). This pass
-  // is run before register coalescer so it will be the form of:
-  //   %0 = COPY $x0
-  //   SW %0, %ptr
-  // instead of:
-  //   SW $x0, %ptr
-  Register FirstReg = MI0->getOperand(0).getReg();
-  Register SecondReg = MI1->getOperand(0).getReg();
-  if (FirstReg == SecondReg) {
-    const MachineInstr *FirstOpDefInst = MRI->getUniqueVRegDef(FirstReg);
-    if (FirstOpDefInst->isCopy() &&
-        FirstOpDefInst->getOperand(1).getReg() == RISCV::X0 &&
-        MRI->getRegClass(FirstReg)->contains(RISCV::X0))
-      return true;
+  if (MI0->getOperand(0).getReg() == MI1->getOperand(0).getReg())
     return false;
-  }
 
   return true;
 }
diff --git a/llvm/test/CodeGen/RISCV/zilsd-ldst-opt-prera.mir b/llvm/test/CodeGen/RISCV/zilsd-ldst-opt-prera.mir
index 490586430e9b2..09c0f5d00f786 100644
--- a/llvm/test/CodeGen/RISCV/zilsd-ldst-opt-prera.mir
+++ b/llvm/test/CodeGen/RISCV/zilsd-ldst-opt-prera.mir
@@ -363,7 +363,8 @@ body: |
     ; CHECK-4BYTE-NEXT: {{  $}}
     ; CHECK-4BYTE-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
     ; CHECK-4BYTE-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x0
-    ; CHECK-4BYTE-NEXT: PseudoSD_RV32_OPT [[COPY1]], [[COPY1]], [[COPY]], 0 :: (store (s32))
+    ; CHECK-4BYTE-NEXT: SW [[COPY1]], [[COPY]], 0 :: (store (s32))
+    ; CHECK-4BYTE-NEXT: SW [[COPY1]], [[COPY]], 4 :: (store (s32))
     ; CHECK-4BYTE-NEXT: PseudoRET
     %0:gpr = COPY $x10
     %1:gpr = COPY $x0
diff --git a/llvm/test/CodeGen/RISCV/zilsd.ll b/llvm/test/CodeGen/RISCV/zilsd.ll
index 40ef659a7ce6c..b2b71da3898a4 100644
--- a/llvm/test/CodeGen/RISCV/zilsd.ll
+++ b/llvm/test/CodeGen/RISCV/zilsd.ll
@@ -276,18 +276,53 @@ entry:
 }
 
 define void @basic_store_zero_combine(ptr %0, i32 %1, i32 %2) {
-; SLOW-LABEL: basic_store_zero_combine:
-; SLOW:       # %bb.0:
-; SLOW-NEXT:    sw zero, 0(a0)
-; SLOW-NEXT:    sw zero, 4(a0)
-; SLOW-NEXT:    ret
-;
-; FAST-LABEL: basic_store_zero_combine:
-; FAST:       # %bb.0:
-; FAST-NEXT:    sd zero, 0(a0)
-; FAST-NEXT:    ret
+; CHECK-LABEL: basic_store_zero_combine:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    sw zero, 0(a0)
+; CHECK-NEXT:    sw zero, 4(a0)
+; CHECK-NEXT:    ret
   store i32 0, ptr %0, align 4
   %4 = getelementptr inbounds i32, ptr %0, i32 1
   store i32 0, ptr %4, align 4
   ret void
 }
+
+declare void @llvm.memset.p0.i32(ptr, i8, i32, i1 immarg)
+
+define void @no_coalesce() #0 {
+; CHECK-LABEL: no_coalesce:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    li a1, 0
+; CHECK-NEXT:    li a0, 1
+; CHECK-NEXT:    j .LBB12_2
+; CHECK-NEXT:  .LBB12_1: # %crash
+; CHECK-NEXT:    # in Loop: Header=BB12_2 Depth=1
+; CHECK-NEXT:    sd a0, 0(zero)
+; CHECK-NEXT:    sw a1, 8(zero)
+; CHECK-NEXT:    sw a1, 0(zero)
+; CHECK-NEXT:    sw a1, 4(zero)
+; CHECK-NEXT:  .LBB12_2: # %loop
+; CHECK-NEXT:    # =>This Inner Loop Header: Depth=1
+; CHECK-NEXT:    bnez a1, .LBB12_1
+; CHECK-NEXT:  # %bb.3: # %loop
+; CHECK-NEXT:    # in Loop: Header=BB12_2 Depth=1
+; CHECK-NEXT:    beqz a1, .LBB12_2
+; CHECK-NEXT:  # %bb.4: # %exit
+; CHECK-NEXT:    ret
+entry:
+  br label %loop
+
+loop:
+  switch i8 0, label %loop [
+    i8 1, label %crash
+    i8 3, label %exit
+  ]
+
+crash:
+  store i64 1, ptr null, align 8
+  call void @llvm.memset.p0.i32(ptr null, i8 0, i32 12, i1 false)
+  br label %loop
+
+exit:
+  ret void
+}



More information about the llvm-branch-commits mailing list