diff --git a/llvm/lib/Transforms/Scalar/NewGVN.cpp b/llvm/lib/Transforms/Scalar/NewGVN.cpp --- a/llvm/lib/Transforms/Scalar/NewGVN.cpp +++ b/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"); diff --git a/llvm/test/Transforms/NewGVN/cycle_poison.ll b/llvm/test/Transforms/NewGVN/cycle_poison.ll new file mode 100644 --- /dev/null +++ b/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 +}