[llvm-branch-commits] [llvm] release/23.x: [RISCV] Don't move memory instructions across calls in isSafeToMove (#212236) (PR #212478)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Tue Jul 28 05:12:15 PDT 2026


https://github.com/llvmbot updated https://github.com/llvm/llvm-project/pull/212478

>From ab215190ab6350588b605c8ed564bc0119459d15 Mon Sep 17 00:00:00 2001
From: Pengcheng Wang <wangpengcheng.pp at bytedance.com>
Date: Tue, 28 Jul 2026 19:19:15 +0800
Subject: [PATCH] [RISCV] Don't move memory instructions across calls in
 isSafeToMove (#212236)

RISCVInstrInfo::isSafeToMove scans the instructions between From and To
to decide whether a memory instruction can be moved, but it only treated
mayStore() instructions as barriers. Calls on RISC-V are modeled with
isCall() and a register mask rather than mayStore(), so a load could be
moved across a call even though the callee may clobber the loaded
memory.

RISCVVectorPeephole::foldVMergeToMask uses this helper via ensureDominates()
to sink a load into a masked load when folding it into a vmerge, which
produced wrong code when the load was sunk past a call.

Instead of hand-rolling the barrier check, call MachineInstr::isSafeToMove
on each intervening instruction to populate SawStore. That is the same
helper used on From below, and it already treats calls (as well as PHIs
and ordered memory references) as stores.

This fixes #212226.

Assisted-by: TRAE CLI (DeepSeek V4 Pro)
(cherry picked from commit 840060f2f85c2d3f8ebe1c9304770d682e4141f6)
---
 llvm/lib/Target/RISCV/RISCVInstrInfo.cpp      |  5 ++--
 .../CodeGen/RISCV/rvv/vmerge-peephole.mir     | 24 +++++++++++++++++++
 2 files changed, 26 insertions(+), 3 deletions(-)

diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
index 6512dde8fde23..e36410fbcb593 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
@@ -5528,10 +5528,9 @@ bool RISCVInstrInfo::isSafeToMove(const MachineInstr &From,
       if (II->definesRegister(PhysReg, nullptr) ||
           II->readsRegister(PhysReg, nullptr))
         return false;
-    if (II->mayStore()) {
-      SawStore = true;
+    II->isSafeToMove(SawStore);
+    if (SawStore)
       break;
-    }
   }
   return From.isSafeToMove(SawStore);
 }
diff --git a/llvm/test/CodeGen/RISCV/rvv/vmerge-peephole.mir b/llvm/test/CodeGen/RISCV/rvv/vmerge-peephole.mir
index f7188c47f2a64..c06e0b5ee81be 100644
--- a/llvm/test/CodeGen/RISCV/rvv/vmerge-peephole.mir
+++ b/llvm/test/CodeGen/RISCV/rvv/vmerge-peephole.mir
@@ -284,3 +284,27 @@ body: |
     %avl:gprnox0 = ADDI $noreg, 1
     %z:vrnov0 = PseudoVMERGE_VVM_M1 $noreg, %false:vrnov0, %x:vrnov0, %mask, %avl, 5
 ...
+---
+# Negative test: don't fold the load into the vmerge if that would sink the
+# load past a call, since the callee may clobber the loaded memory.
+name: vle32_cant_sink_past_call
+tracksRegLiveness: true
+body: |
+  bb.0:
+    liveins: $x8, $v0
+    ; CHECK-LABEL: name: vle32_cant_sink_past_call
+    ; CHECK: liveins: $x8, $v0
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: %avl:gprnox0 = COPY $x8
+    ; CHECK-NEXT: %mask:vmv0 = COPY $v0
+    ; CHECK-NEXT: %x:vrnov0 = PseudoVLE32_V_M1 $noreg, $noreg, %avl /* vl */, 5 /* e32 */, 2 /* tu, ma */ :: (load unknown-size, align 1)
+    ; CHECK-NEXT: PseudoCALL target-flags(riscv-call) &foo, csr_ilp32d_lp64d, implicit-def dead $x1, implicit-def $x2
+    ; CHECK-NEXT: %false:vrnov0 = PseudoVMV_V_I_M1 $noreg, 0, %avl /* vl */, 5 /* e32 */, 0 /* tu, mu */
+    ; CHECK-NEXT: %y:vrnov0 = PseudoVMERGE_VVM_M1 $noreg, %false, %x, %mask, %avl /* vl */, 5 /* e32 */
+    %avl:gprnox0 = COPY $x8
+    %mask:vmv0 = COPY $v0
+    %x:vrnov0 = PseudoVLE32_V_M1 $noreg, $noreg, %avl, 5 /* e32 */, 2 /* tu, ma */ :: (load unknown-size)
+    PseudoCALL target-flags(riscv-call) &foo, csr_ilp32d_lp64d, implicit-def dead $x1, implicit-def $x2
+    %false:vrnov0 = PseudoVMV_V_I_M1 $noreg, 0, %avl, 5 /* e32 */, 0 /* tu, mu */
+    %y:vrnov0 = PseudoVMERGE_VVM_M1 $noreg, %false, %x, %mask, %avl, 5 /* e32 */
+...



More information about the llvm-branch-commits mailing list