[llvm] [SpeculativeExecution] Drop poison-generating flags when hoisting instructions (PR #225377)
Adrian Kuegel via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 22 05:45:51 PDT 2026
https://github.com/akuegel updated https://github.com/llvm/llvm-project/pull/225377
>From 8392a8a9018304a8c1a4f6530ea1da4cb285b798 Mon Sep 17 00:00:00 2001
From: Adrian Kuegel <akuegel at google.com>
Date: Tue, 22 Sep 2026 11:43:21 +0000
Subject: [PATCH 1/2] [SpeculativeExecution] Drop poison-generating flags when
hoisting instructions
When SpeculativeExecutionPass::considerHoistingFromTo hoists instructions
out of a conditionally executed basic block into a dominating block, any
poison-generating flags (such as `disjoint`, `nsw`, `nuw`, `exact`, or
`inbounds`) that were inferred under the branch condition may no longer
hold in the dominating block.
For example, `InstCombine` can fold `add i32 %x, -2` to `or disjoint i32 %x, -2`
inside an `if (%x < 2)` block. If `SpeculativeExecutionPass` hoists the
`or disjoint` above `if (%x < 2)` without dropping `disjoint`, subsequent
passes such as `NaryReassociate` (via `ScalarEvolution`) or `EarlyCSE`
treat the hoisted `or disjoint %x, -2` as equivalent to `add %x, -2` in
other blocks where `%x >= 2`, causing a miscompilation.
Call `dropPoisonGeneratingFlags()` on hoisted instructions.
---
.../Scalar/SpeculativeExecution.cpp | 1 +
.../Transforms/SpeculativeExecution/spec.ll | 20 +++++++++++++++++++
2 files changed, 21 insertions(+)
diff --git a/llvm/lib/Transforms/Scalar/SpeculativeExecution.cpp b/llvm/lib/Transforms/Scalar/SpeculativeExecution.cpp
index 0a2a3f8a495bf..2dcabaf7644fa 100644
--- a/llvm/lib/Transforms/Scalar/SpeculativeExecution.cpp
+++ b/llvm/lib/Transforms/Scalar/SpeculativeExecution.cpp
@@ -320,6 +320,7 @@ bool SpeculativeExecutionPass::considerHoistingFromTo(
if (!NotHoisted.count(&*Current)) {
Current->moveBefore(ToBlock.getTerminator()->getIterator());
Current->dropLocation();
+ Current->dropPoisonGeneratingFlags();
}
}
return true;
diff --git a/llvm/test/Transforms/SpeculativeExecution/spec.ll b/llvm/test/Transforms/SpeculativeExecution/spec.ll
index 9f409eb059f43..95c6306f04b5a 100644
--- a/llvm/test/Transforms/SpeculativeExecution/spec.ll
+++ b/llvm/test/Transforms/SpeculativeExecution/spec.ll
@@ -193,3 +193,23 @@ a:
b:
ret void
}
+
+; Drop poison-generating flags when hoisting.
+define void @dropPoisonFlags(i32 %val, ptr %p) {
+; CHECK-LABEL: @dropPoisonFlags(
+; CHECK-NEXT: %or = or i32 %val, -2{{$}}
+; CHECK-NEXT: %add = add i32 %or, 1{{$}}
+; CHECK-NEXT: %gep = getelementptr i8, ptr %p, i32 %add{{$}}
+; CHECK-NEXT: br i1 true
+ br i1 true, label %a, label %b
+; CHECK: a:
+a:
+ %or = or disjoint i32 %val, -2
+ %add = add nuw nsw i32 %or, 1
+ %gep = getelementptr inbounds i8, ptr %p, i32 %add
+ br label %b
+; CHECK: b:
+b:
+ ret void
+}
+
>From b7fbf4c8a90654b107a56cf4306bf61205053aa0 Mon Sep 17 00:00:00 2001
From: Adrian Kuegel <akuegel at google.com>
Date: Tue, 22 Sep 2026 12:44:37 +0000
Subject: [PATCH 2/2] Update spec-calls.ll for dropped is_zero_poison flag
---
llvm/test/Transforms/SpeculativeExecution/spec-calls.ll | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/test/Transforms/SpeculativeExecution/spec-calls.ll b/llvm/test/Transforms/SpeculativeExecution/spec-calls.ll
index 3a4ddf530a805..ed2ed53b2aedb 100644
--- a/llvm/test/Transforms/SpeculativeExecution/spec-calls.ll
+++ b/llvm/test/Transforms/SpeculativeExecution/spec-calls.ll
@@ -30,7 +30,7 @@ b:
define void @ifThen_ctlz() {
; CHECK-LABEL: define void @ifThen_ctlz() {
-; CHECK-NEXT: [[X:%.*]] = call i32 @llvm.ctlz.i32(i32 0, i1 true)
+; CHECK-NEXT: [[X:%.*]] = call i32 @llvm.ctlz.i32(i32 0, i1 false)
; CHECK-NEXT: br i1 true, label %[[A:.*]], label %[[B:.*]]
; CHECK: [[A]]:
; CHECK-NEXT: br label %[[B]]
More information about the llvm-commits
mailing list