[llvm] [ValueTracking] Skip incoming values that are the same as the phi in `isGuaranteedNotToBeUndefOrPoison` (PR #130111)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Mar 6 06:26:31 PST 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-analysis
Author: DianQK (DianQK)
<details>
<summary>Changes</summary>
Fixes #<!-- -->130110.
If the incoming value is PHI itself, we can skip this. If we can guarantee that the other incoming values are neither undef nor poison, then we can also guarantee that the value isn't either. If we cannot guarantee that, it makes no sense in calculating it.
---
Full diff: https://github.com/llvm/llvm-project/pull/130111.diff
2 Files Affected:
- (modified) llvm/lib/Analysis/ValueTracking.cpp (+2)
- (added) llvm/test/Analysis/ValueTracking/phi-self.ll (+145)
``````````diff
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index e3e026f7979da..9b098bcb28bcc 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -7824,6 +7824,8 @@ static bool isGuaranteedNotToBeUndefOrPoison(
unsigned Num = PN->getNumIncomingValues();
bool IsWellDefined = true;
for (unsigned i = 0; i < Num; ++i) {
+ if (PN == PN->getIncomingValue(i))
+ continue;
auto *TI = PN->getIncomingBlock(i)->getTerminator();
if (!isGuaranteedNotToBeUndefOrPoison(PN->getIncomingValue(i), AC, TI,
DT, Depth + 1, Kind)) {
diff --git a/llvm/test/Analysis/ValueTracking/phi-self.ll b/llvm/test/Analysis/ValueTracking/phi-self.ll
new file mode 100644
index 0000000000000..095a16983ce21
--- /dev/null
+++ b/llvm/test/Analysis/ValueTracking/phi-self.ll
@@ -0,0 +1,145 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt -S -passes=instsimplify < %s | FileCheck %s
+
+; Test `%r` can be replaced by `%nonpoison`.
+
+define i64 @other_noundef() {
+; CHECK-LABEL: define i64 @other_noundef() {
+; CHECK-NEXT: [[START:.*]]:
+; CHECK-NEXT: br label %[[LOOP:.*]]
+; CHECK: [[LOOP]]:
+; CHECK-NEXT: [[R:%.*]] = phi i64 [ [[R]], %[[BB0:.*]] ], [ [[R]], %[[BB1:.*]] ], [ [[R]], %[[BB2:.*]] ], [ [[R]], %[[BB:.*]] ], [ [[I:%.*]], %[[BACK_TO_LOOP:.*]] ], [ 0, %[[START]] ]
+; CHECK-NEXT: [[I]] = call i64 @opaque()
+; CHECK-NEXT: switch i64 [[I]], label %[[EXIT0:.*]] [
+; CHECK-NEXT: i64 -1, label %[[EXIT1:.*]]
+; CHECK-NEXT: i64 2, label %[[BACK_TO_LOOP]]
+; CHECK-NEXT: i64 0, label %[[BB]]
+; CHECK-NEXT: ]
+; CHECK: [[EXIT0]]:
+; CHECK-NEXT: br label %[[EXIT1]]
+; CHECK: [[EXIT1]]:
+; CHECK-NEXT: ret i64 [[R]]
+; CHECK: [[BACK_TO_LOOP]]:
+; CHECK-NEXT: br label %[[LOOP]]
+; CHECK: [[BB]]:
+; CHECK-NEXT: switch i64 [[R]], label %[[LOOP]] [
+; CHECK-NEXT: i64 0, label %[[BB0]]
+; CHECK-NEXT: i64 1, label %[[BB1]]
+; CHECK-NEXT: i64 2, label %[[BB2]]
+; CHECK-NEXT: ]
+; CHECK: [[BB0]]:
+; CHECK-NEXT: br label %[[LOOP]]
+; CHECK: [[BB1]]:
+; CHECK-NEXT: br label %[[LOOP]]
+; CHECK: [[BB2]]:
+; CHECK-NEXT: br label %[[LOOP]]
+;
+start:
+ br label %loop
+
+loop: ; preds = %bb2, %bb1, %bb0, %bb, %back_to_loop, %start
+ %nonpoison = phi i64 [ %nonpoison, %bb0 ], [ %nonpoison, %bb1 ], [ %nonpoison, %bb2 ], [ %nonpoison, %bb ], [ %i, %back_to_loop ], [ 0, %start ]
+ %i = call i64 @opaque()
+ switch i64 %i, label %exit0 [
+ i64 -1, label %exit1
+ i64 2, label %back_to_loop
+ i64 0, label %bb
+ ]
+
+exit0: ; preds = %loop
+ br label %exit1
+
+exit1: ; preds = %exit0, %loop
+ %r = phi i64 [ %nonpoison, %loop ], [ undef, %exit0 ]
+ ret i64 %r
+
+back_to_loop: ; preds = %loop
+ br label %loop
+
+bb: ; preds = %loop
+ switch i64 %nonpoison, label %loop [
+ i64 0, label %bb0
+ i64 1, label %bb1
+ i64 2, label %bb2
+ ]
+
+bb0: ; preds = %bb
+ br label %loop
+
+bb1: ; preds = %bb
+ br label %loop
+
+bb2: ; preds = %bb
+ br label %loop
+}
+
+define i64 @other_poison() {
+; CHECK-LABEL: define i64 @other_poison() {
+; CHECK-NEXT: [[START:.*:]]
+; CHECK-NEXT: br label %[[LOOP:.*]]
+; CHECK: [[LOOP]]:
+; CHECK-NEXT: [[I:%.*]] = call i64 @opaque()
+; CHECK-NEXT: switch i64 [[I]], label %[[EXIT0:.*]] [
+; CHECK-NEXT: i64 -1, label %[[EXIT1:.*]]
+; CHECK-NEXT: i64 2, label %[[BACK_TO_LOOP:.*]]
+; CHECK-NEXT: i64 0, label %[[BB:.*]]
+; CHECK-NEXT: ]
+; CHECK: [[EXIT0]]:
+; CHECK-NEXT: br label %[[EXIT1]]
+; CHECK: [[EXIT1]]:
+; CHECK-NEXT: ret i64 0
+; CHECK: [[BACK_TO_LOOP]]:
+; CHECK-NEXT: br label %[[LOOP]]
+; CHECK: [[BB]]:
+; CHECK-NEXT: switch i64 0, label %[[LOOP]] [
+; CHECK-NEXT: i64 0, label %[[BB0:.*]]
+; CHECK-NEXT: i64 1, label %[[BB1:.*]]
+; CHECK-NEXT: i64 2, label %[[BB2:.*]]
+; CHECK-NEXT: ]
+; CHECK: [[BB0]]:
+; CHECK-NEXT: br label %[[LOOP]]
+; CHECK: [[BB1]]:
+; CHECK-NEXT: br label %[[LOOP]]
+; CHECK: [[BB2]]:
+; CHECK-NEXT: br label %[[LOOP]]
+;
+start:
+ br label %loop
+
+loop: ; preds = %bb2, %bb1, %bb0, %bb, %back_to_loop, %start
+ %maypoison = phi i64 [ %maypoison, %bb0 ], [ %maypoison, %bb1 ], [ %maypoison, %bb2 ], [ %maypoison, %bb ], [ poison, %back_to_loop ], [ 0, %start ]
+ %i = call i64 @opaque()
+ switch i64 %i, label %exit0 [
+ i64 -1, label %exit1
+ i64 2, label %back_to_loop
+ i64 0, label %bb
+ ]
+
+exit0: ; preds = %loop
+ br label %exit1
+
+exit1: ; preds = %exit0, %loop
+ %r = phi i64 [ %maypoison, %loop ], [ undef, %exit0 ]
+ ret i64 %r
+
+back_to_loop: ; preds = %loop
+ br label %loop
+
+bb: ; preds = %loop
+ switch i64 %maypoison, label %loop [
+ i64 0, label %bb0
+ i64 1, label %bb1
+ i64 2, label %bb2
+ ]
+
+bb0: ; preds = %bb
+ br label %loop
+
+bb1: ; preds = %bb
+ br label %loop
+
+bb2: ; preds = %bb
+ br label %loop
+}
+
+declare i64 @opaque()
``````````
</details>
https://github.com/llvm/llvm-project/pull/130111
More information about the llvm-commits
mailing list