diff --git a/lib/Transforms/Scalar/GVN.cpp b/lib/Transforms/Scalar/GVN.cpp index 37e970b8b61..dc13edff255 100644 --- a/lib/Transforms/Scalar/GVN.cpp +++ b/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/test/Transforms/GVN/condprop.ll b/test/Transforms/GVN/condprop.ll index b22675b47cc..9c28955801f 100644 --- a/test/Transforms/GVN/condprop.ll +++ b/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 +}