[PATCH] D158273: [NewGVN] Don't ignore poison in cyclic PHIs
Manuel Brito via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Fri Aug 18 05:57:57 PDT 2023
ManuelJBrito created this revision.
ManuelJBrito added reviewers: asbirlea, nlopes.
Herald added subscribers: kmitropoulou, hiraditya.
Herald added a project: All.
ManuelJBrito requested review of this revision.
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.
NewGVN gets stuck in a infinite loop for the following test case.
define void @foo() {
br label %1
1:
%2 = phi i32 [ %3, %1 ], [ undef, %0 ]
%3 = lshr i32 %2, 973496514
br label %1
With the following steps:
%2 -> undef (edge <%1, %1> is initially unreachable)
%3 -> 0 ; start of evaluation loop
%2 -> phi [0, undef]
%3 -> poison
%2 -> phi [poison, undef] -> undef
%3 -> 0
; repeat
The problem here is that poison and undef simplify differently and we have a cyclic dependency, so the value numbering never converges.
Not ignoring the poison breaks the cycle.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D158273
Files:
llvm/lib/Transforms/Scalar/NewGVN.cpp
llvm/test/Transforms/NewGVN/cycle_poison.ll
Index: llvm/test/Transforms/NewGVN/cycle_poison.ll
===================================================================
--- /dev/null
+++ llvm/test/Transforms/NewGVN/cycle_poison.ll
@@ -0,0 +1,17 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -passes=newgvn -S %s | FileCheck %s
+
+define void @foo() {
+; CHECK-LABEL: @foo(
+; CHECK-NEXT: br label [[TMP1:%.*]]
+; CHECK: 1:
+; CHECK-NEXT: [[TMP2:%.*]] = phi i32 [ poison, [[TMP1]] ], [ undef, [[TMP0:%.*]] ]
+; CHECK-NEXT: br label [[TMP1]]
+;
+ br label %1
+
+1: ; preds = %1, %0
+ %2 = phi i32 [ %3, %1 ], [ undef, %0 ]
+ %3 = lshr i32 %2, 973496514
+ br label %1
+}
Index: llvm/lib/Transforms/Scalar/NewGVN.cpp
===================================================================
--- llvm/lib/Transforms/Scalar/NewGVN.cpp
+++ llvm/lib/Transforms/Scalar/NewGVN.cpp
@@ -1756,9 +1756,15 @@
});
// If we are left with no operands, it's dead.
if (Filtered.empty()) {
- // If it has undef or poison at this point, it means there are no-non-undef
- // arguments, and thus, the value of the phi node must be undef.
if (HasUndef) {
+ // If we have undef and poison, we need to know if it's cycle
+ // free to ignore the poison. Otherwise we might get stuck in a evaluation
+ // loop.
+ if (HasBackedge && !OriginalOpsConstant && HasPoison && !isCycleFree(I))
+ return E;
+ // If it has undef or poison at this point, it means there are
+ // no-non-undef arguments, and thus, the value of the phi node must be
+ // undef.
LLVM_DEBUG(
dbgs() << "PHI Node " << *I
<< " has no non-undef arguments, valuing it as undef\n");
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D158273.551472.patch
Type: text/x-patch
Size: 1769 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20230818/9cf393ff/attachment.bin>
More information about the llvm-commits
mailing list