[llvm] [VectorCombine] Handle frees and synchronization in single element stores (PR #216562)
via llvm-commits
llvm-commits at lists.llvm.org
Sun Aug 16 04:25:26 PDT 2026
https://github.com/ParkHanbum created https://github.com/llvm/llvm-project/pull/216562
foldSingleElementStore only checked whether intervening instructions modified
the stored memory. Calls that may free or synchronize could therefore make
scalarization incorrect.
Use willNotFreeBetween with the existing ModRef check and add a regression
test.
Fixes https://github.com/llvm/llvm-project/issues/216557
>From f832ecedf5152033fdac0e1beeb03c4758419e43 Mon Sep 17 00:00:00 2001
From: hanbeom <kese111 at gmail.com>
Date: Sun, 16 Aug 2026 20:06:47 +0900
Subject: [PATCH] [VectorCombine] Handle frees and synchronization in single
element stores
foldSingleElementStore only checked whether intervening instructions modified
the stored memory. Calls that may free or synchronize could therefore make
scalarization incorrect.
Use willNotFreeBetween with the existing ModRef check and add a regression
test.
---
.../Transforms/Vectorize/VectorCombine.cpp | 18 +++++++++++++--
.../VectorCombine/SPIRV/load-insert-store.ll | 2 +-
.../VectorCombine/load-insert-store.ll | 22 ++++++++++++++++++-
3 files changed, 38 insertions(+), 4 deletions(-)
diff --git a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp
index 7c6a87685e015..7e721dbcf6096 100644
--- a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp
+++ b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp
@@ -1844,6 +1844,20 @@ static bool isMemModifiedBetween(BasicBlock::iterator Begin,
});
}
+// Check if memory is modified, freed, or synchronized between two instrs in
+// the same BB.
+static bool isMemModifiedFreeSyncBetween(BasicBlock::iterator Begin,
+ BasicBlock::iterator End,
+ const MemoryLocation &Loc,
+ AAResults &AA) {
+ if (isMemModifiedBetween(Begin, End, Loc, AA))
+ return true;
+
+ // willNotFreeBetween expects instructions rather than iterators. An empty
+ // range cannot free or synchronize, so avoid dereferencing its end.
+ return Begin != End && !willNotFreeBetween(&*Begin, &*End);
+}
+
namespace {
/// Helper class to indicate whether a vector index can be safely scalarized and
/// if a freeze needs to be inserted.
@@ -1996,8 +2010,8 @@ bool VectorCombine::foldSingleElementStore(Instruction &I) {
SrcAddr != SI->getPointerOperand()->stripPointerCasts())
return false;
- if (isMemModifiedBetween(Load->getIterator(), SI->getIterator(),
- MemoryLocation::get(SI), AA))
+ if (isMemModifiedFreeSyncBetween(Load->getIterator(), SI->getIterator(),
+ MemoryLocation::get(SI), AA))
return false;
auto ScalarizableIdx =
canScalarizeAccess(VecTy, Idx, SQ.getWithInstruction(Load));
diff --git a/llvm/test/Transforms/VectorCombine/SPIRV/load-insert-store.ll b/llvm/test/Transforms/VectorCombine/SPIRV/load-insert-store.ll
index 6f4c80d5d89a6..b579922029247 100644
--- a/llvm/test/Transforms/VectorCombine/SPIRV/load-insert-store.ll
+++ b/llvm/test/Transforms/VectorCombine/SPIRV/load-insert-store.ll
@@ -800,7 +800,7 @@ entry:
declare void @foo()
declare void @maywrite(ptr)
-declare void @nowrite(ptr) readonly
+declare void @nowrite(ptr) readonly nofree
; To test if number of instructions in-between exceeds the limit (default 30),
; the combine will quit.
diff --git a/llvm/test/Transforms/VectorCombine/load-insert-store.ll b/llvm/test/Transforms/VectorCombine/load-insert-store.ll
index 897b113c197cf..b2f25adc15e0b 100644
--- a/llvm/test/Transforms/VectorCombine/load-insert-store.ll
+++ b/llvm/test/Transforms/VectorCombine/load-insert-store.ll
@@ -16,6 +16,26 @@ entry:
ret void
}
+declare void @may_synchronize() memory(none)
+
+define void @insert_store_across_synchronization(ptr %q, i32 %s) {
+; CHECK-LABEL: @insert_store_across_synchronization(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[V:%.*]] = load <4 x i32>, ptr [[Q:%.*]], align 16
+; CHECK-NEXT: call void @may_synchronize()
+; CHECK-NEXT: [[VECINS:%.*]] = insertelement <4 x i32> [[V]], i32 [[S:%.*]],
+; CHECK-SAME: i32 1
+; CHECK-NEXT: store <4 x i32> [[VECINS]], ptr [[Q]], align 16
+; CHECK-NEXT: ret void
+;
+entry:
+ %v = load <4 x i32>, ptr %q, align 16
+ call void @may_synchronize()
+ %vecins = insertelement <4 x i32> %v, i32 %s, i32 1
+ store <4 x i32> %vecins, ptr %q, align 16
+ ret void
+}
+
define void @insert_store_i16_align1(ptr %q, i16 zeroext %s) {
; CHECK-LABEL: @insert_store_i16_align1(
; CHECK-NEXT: entry:
@@ -762,7 +782,7 @@ entry:
declare void @foo()
declare void @maywrite(ptr)
-declare void @nowrite(ptr) readonly
+declare void @nowrite(ptr) readonly nofree
; To test if number of instructions in-between exceeds the limit (default 30),
; the combine will quit.
More information about the llvm-commits
mailing list