[llvm] [SLSR] Defer removal of poison-generating annotations if not executed (PR #217093)

via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 18 10:53:38 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-transforms

Author: Nick Riasanovsky (njriasan)

<details>
<summary>Changes</summary>

Defer removal of poison-generating annotations in SLSR until the selected rewrite is actually executed.

Previously, candidate discovery could remove annotations such as nuw and nsw even when the rewrite was later skipped by a debug counter. The pass now retains the annotations during candidate analysis and removes them only after committing to a rewrite.

The debug-counter test now verifies both behaviors:

- Skipped rewrites preserve poison-generating annotations.
- Executed rewrites remove annotations required for safe basis reuse.

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


2 Files Affected:

- (modified) llvm/lib/Transforms/Scalar/StraightLineStrengthReduce.cpp (+7-9) 
- (modified) llvm/test/Other/debugcounter-slsr.ll (+35-25) 


``````````diff
diff --git a/llvm/lib/Transforms/Scalar/StraightLineStrengthReduce.cpp b/llvm/lib/Transforms/Scalar/StraightLineStrengthReduce.cpp
index 8826127dd7ae3..deed6160b2056 100644
--- a/llvm/lib/Transforms/Scalar/StraightLineStrengthReduce.cpp
+++ b/llvm/lib/Transforms/Scalar/StraightLineStrengthReduce.cpp
@@ -217,8 +217,8 @@ class StraightLineStrengthReduce {
     // Points to (Y - X) that will be used to rewrite this candidate.
     Value *Delta = nullptr;
 
-    // List of instructions we need to drop poison generating annotations from.
-    // This is used so we can defer dropping until the candidate is evaluated.
+    // List of instructions whose poison-generating annotations must be dropped
+    // if this candidate is used as the basis of an executed rewrite.
     SmallVector<Instruction *> DropList;
 
     /// Cost model: Evaluate the computational efficiency of the candidate.
@@ -760,11 +760,6 @@ bool StraightLineStrengthReduce::candidatePredicate(Candidate *Basis,
       !C.isProfitableRewrite(*Delta, Candidate::IndexDelta))
     return false;
 
-  // If there is a Delta that we can reuse Basis to rewrite C, clean up
-  // previously collected poison generating instructions.
-  for (Instruction *I : Basis->DropList)
-    I->dropPoisonGeneratingAnnotations();
-
   // Record delta if none has been found yet, or the new delta is
   // a constant that is better than the existing delta.
   if (!C.Delta || isa<ConstantInt>(Delta)) {
@@ -1050,8 +1045,8 @@ void StraightLineStrengthReduce::allocateCandidatesAndFindBasis(
   RewriteCandidates[C.Ins].push_back(&Candidates.back());
   // Only add to the dict if this instruction is safe to reuse as a basis. By
   // doing this early we avoid calling canReuseInstruction repeatedly for the
-  // same instruction. The DropList is stored on the Candidate so
-  // candidatePredicate can drop the flags when a rewrite is being done.
+  // same instruction. The DropList is stored on the Candidate so the flags can
+  // be dropped only if this candidate is used by an executed rewrite.
   if (!EnablePoisonReuseGuard ||
       SE->canReuseInstruction(SE->getSCEV(I), I, Candidates.back().DropList)) {
     CandidateDict.add(Candidates.back());
@@ -1304,6 +1299,9 @@ void StraightLineStrengthReduce::rewriteCandidate(const Candidate &C) {
   assert(C.Delta && C.CandidateKind == Basis.CandidateKind &&
          C.hasValidDelta(Basis));
 
+  for (Instruction *I : Basis.DropList)
+    I->dropPoisonGeneratingAnnotations();
+
   IRBuilder<> Builder(C.Ins);
   Value *Bump = emitBump(Basis, C, Builder, DL);
   Value *Reduced = nullptr; // equivalent to but weaker than C.Ins
diff --git a/llvm/test/Other/debugcounter-slsr.ll b/llvm/test/Other/debugcounter-slsr.ll
index 0e24f493c3bc8..27abd033814b5 100644
--- a/llvm/test/Other/debugcounter-slsr.ll
+++ b/llvm/test/Other/debugcounter-slsr.ll
@@ -1,25 +1,35 @@
-; RUN: opt -passes=slsr -S -debug-counter=slsr-counter=1  < %s | FileCheck %s
-
-; Test that, with debug counters on, we will skip the first slsr opportunity.
-
-define void @stride_is_2s(i32 %b, i32 %s) {
-; CHECK-LABEL: @stride_is_2s(
-; CHECK-NEXT: %s2 = shl i32 %s, 1
-; CHECK-NEXT: %t1 = add i32 %b, %s2
-; CHECK-NEXT: call void @foo(i32 %t1)
-; CHECK-NEXT: %s4 = shl i32 %s, 2
-; CHECK-NEXT: %t2 = add i32 %b, %s4
-; CHECK-NEXT: call void @foo(i32 %t2)
-; CHECK-NEXT: ret void
-;
-  %s2 = shl i32 %s, 1
-  %t1 = add i32 %b, %s2
-  call void @foo(i32 %t1)
-  %s4 = shl i32 %s, 2
-  %t2 = add i32 %b, %s4
-  call void @foo(i32 %t2)
-  ret void
-}
-
-declare void @foo(i32)
-
+; RUN: opt -passes=slsr -S -debug-counter=slsr-counter=1 < %s | FileCheck %s --check-prefix=SKIP
+; RUN: opt -passes=slsr -S < %s | FileCheck %s --check-prefix=EXEC
+
+; Test that poison-generating annotations are dropped only when an SLSR
+; opportunity is executed.
+
+define void @stride_is_2s(i32 %b, i32 %s) {
+; SKIP-LABEL: @stride_is_2s(
+; SKIP-NEXT: %s2 = shl nuw nsw i32 %s, 1
+; SKIP-NEXT: %t1 = add nuw nsw i32 %b, %s2
+; SKIP-NEXT: call void @foo(i32 %t1)
+; SKIP-NEXT: %s4 = shl i32 %s, 2
+; SKIP-NEXT: %t2 = add i32 %b, %s4
+; SKIP-NEXT: call void @foo(i32 %t2)
+; SKIP-NEXT: ret void
+;
+; EXEC-LABEL: @stride_is_2s(
+; EXEC-NEXT: %s2 = shl i32 %s, 1
+; EXEC-NEXT: %t1 = add i32 %b, %s2
+; EXEC-NEXT: call void @foo(i32 %t1)
+; EXEC-NEXT: [[BUMP:%.*]] = shl i32 %s, 1
+; EXEC-NEXT: %t2 = add i32 %t1, [[BUMP]]
+; EXEC-NEXT: call void @foo(i32 %t2)
+; EXEC-NEXT: ret void
+;
+  %s2 = shl nuw nsw i32 %s, 1
+  %t1 = add nuw nsw i32 %b, %s2
+  call void @foo(i32 %t1)
+  %s4 = shl i32 %s, 2
+  %t2 = add i32 %b, %s4
+  call void @foo(i32 %t2)
+  ret void
+}
+
+declare void @foo(i32)

``````````

</details>


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


More information about the llvm-commits mailing list