[llvm] [SpeculativeExecution] Drop poison-generating flags when hoisting instructions (PR #225377)

via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 22 04:52:43 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-transforms

Author: Adrian Kuegel (akuegel)

<details>
<summary>Changes</summary>

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.

Assisted-by: Gemini

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


2 Files Affected:

- (modified) llvm/lib/Transforms/Scalar/SpeculativeExecution.cpp (+1) 
- (modified) llvm/test/Transforms/SpeculativeExecution/spec.ll (+20) 


``````````diff
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
+}
+

``````````

</details>


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


More information about the llvm-commits mailing list