From 6587d6dd55e5e118d301dc3466444b5b6cd60f27 Mon Sep 17 00:00:00 2001 From: Michael Kruse Date: Sat, 26 Mar 2016 23:32:57 +0000 Subject: [PATCH] [Verifier] Reject PHIs using defs from own block. Reject the following IR as malformed (assuming that %entry, %next are not in a loop): next: %y = phi i32 [ 0, %entry ] %x = phi i32 [ %y, %entry ] Such PHI nodes came up in PR26718. While there was no consensus on whether or not this is valid IR, most opinions on that bug and in a discussion on the llvm-dev mailing list tended towards a "strict interpretation" (term by Joseph Tremoulet) of PHI node uses. Also, the language reference explicitly states that "the use of each incoming value is deemed to occur on the edge from the corresponding predecessor block to the current block" and `DominatorTree::dominates(Instruction*, Use&)` uses this definition as well. For the code mentioned in PR15384, clang does not compile to such PHIs (anymore?). The test case still hangs when replacing `%tmp6` with `%tmp` in revisions before r176366 (where PR15384 has been fixed). The occurrence of %tmp6 therefore was probably unintentional. Its value is not used except in other PHIs. Reviewers: majnemer, reames, JosephTremoulet, bkramer, grosser, jdoerfert, kparzysz, sanjoy Differential Revision: http://reviews.llvm.org/D18443 llvm-svn: 264528 --- lib/IR/Verifier.cpp | 8 +++++++- test/Transforms/LoopVectorize/phi-hang.ll | 2 +- test/Verifier/dominates.ll | 13 +++++++++++++ 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/lib/IR/Verifier.cpp b/lib/IR/Verifier.cpp index 9d9fe7d376d..0cd24633499 100644 --- a/lib/IR/Verifier.cpp +++ b/lib/IR/Verifier.cpp @@ -3397,8 +3397,14 @@ void Verifier::verifyDominatesUse(Instruction &I, unsigned i) { return; } + // Quick check whether the def has already been encountered in the same block. + // PHI nodes are not checked to prevent accepting preceeding PHIs, because PHI + // uses are defined to happen on the incoming edge, not at the instruction. + if (!isa(I) && InstsInThisBlock.count(Op)) + return; + const Use &U = I.getOperandUse(i); - Assert(InstsInThisBlock.count(Op) || DT.dominates(Op, U), + Assert(DT.dominates(Op, U), "Instruction does not dominate all uses!", Op, &I); } diff --git a/test/Transforms/LoopVectorize/phi-hang.ll b/test/Transforms/LoopVectorize/phi-hang.ll index bbce239afa7..eb1aaeffde8 100644 --- a/test/Transforms/LoopVectorize/phi-hang.ll +++ b/test/Transforms/LoopVectorize/phi-hang.ll @@ -18,7 +18,7 @@ bb4: ; preds = %bb3 bb5: ; preds = %bb4, %bb1 %tmp6 = phi i32 [ 0, %bb4 ], [ %tmp, %bb1 ] - %tmp7 = phi i32 [ 0, %bb4 ], [ %tmp6, %bb1 ] + %tmp7 = phi i32 [ 0, %bb4 ], [ %tmp, %bb1 ] %tmp8 = phi i32 [ 0, %bb4 ], [ %tmp, %bb1 ] %tmp9 = add nsw i32 %tmp2, 1 %tmp10 = icmp eq i32 %tmp9, 0 diff --git a/test/Verifier/dominates.ll b/test/Verifier/dominates.ll index c5424bbede3..6b0c67f7a2b 100644 --- a/test/Verifier/dominates.ll +++ b/test/Verifier/dominates.ll @@ -55,3 +55,16 @@ bb1: ; CHECK-NEXT: %y1 = add i32 %x, 1 ; CHECK-NEXT: %y3 = phi i32 [ %y1, %bb0 ] } + +define void @f5() { +entry: + br label %next + +next: + %y = phi i32 [ 0, %entry ] + %x = phi i32 [ %y, %entry ] + ret void +; CHECK: Instruction does not dominate all uses! +; CHECK-NEXT: %y = phi i32 [ 0, %entry ] +; CHECK-NEXT: %x = phi i32 [ %y, %entry ] +}