From 4d928e7dffb79938438de7b1264c338ae1a8d697 Mon Sep 17 00:00:00 2001 From: Duncan Sands Date: Sun, 4 Mar 2012 13:25:19 +0000 Subject: [PATCH] Nick pointed out on IRC that GVN's propagateEquality wasn't propagating equalities into phi node operands for which the equality is known to hold in the incoming basic block. That's because replaceAllDominatedUsesWith wasn't handling phi nodes correctly in general (that this didn't give wrong results was just luck: the specific way GVN uses replaceAllDominatedUsesWith precluded wrong changes to phi nodes). llvm-svn: 152006 --- llvm/lib/Transforms/Scalar/GVN.cpp | 12 +++++++++++- llvm/test/Transforms/GVN/condprop.ll | 17 +++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/llvm/lib/Transforms/Scalar/GVN.cpp b/llvm/lib/Transforms/Scalar/GVN.cpp index 37e970b8b614..dc13edff2555 100644 --- a/llvm/lib/Transforms/Scalar/GVN.cpp +++ b/llvm/lib/Transforms/Scalar/GVN.cpp @@ -1953,7 +1953,17 @@ unsigned GVN::replaceAllDominatedUsesWith(Value *From, Value *To, for (Value::use_iterator UI = From->use_begin(), UE = From->use_end(); UI != UE; ) { Use &U = (UI++).getUse(); - if (DT->dominates(Root, cast(U.getUser())->getParent())) { + + // If From occurs as a phi node operand then the use implicitly lives in the + // corresponding incoming block. Otherwise it is the block containing the + // user that must be dominated by Root. + BasicBlock *UsingBlock; + if (PHINode *PN = dyn_cast(U.getUser())) + UsingBlock = PN->getIncomingBlock(U); + else + UsingBlock = cast(U.getUser())->getParent(); + + if (DT->dominates(Root, UsingBlock)) { U.set(To); ++Count; } diff --git a/llvm/test/Transforms/GVN/condprop.ll b/llvm/test/Transforms/GVN/condprop.ll index b22675b47cc0..9c28955801f7 100644 --- a/llvm/test/Transforms/GVN/condprop.ll +++ b/llvm/test/Transforms/GVN/condprop.ll @@ -232,3 +232,20 @@ cond_true2: next2: ret i32 0 } + +; CHECK: @test12 +define i32 @test12(i32 %x) { + %cmp = icmp eq i32 %x, 0 + br i1 %cmp, label %cond_true, label %cond_false + +cond_true: + br label %ret + +cond_false: + br label %ret + +ret: + %res = phi i32 [ %x, %cond_true ], [ %x, %cond_false ] +; CHECK: %res = phi i32 [ 0, %cond_true ], [ %x, %cond_false ] + ret i32 %res +}