Nick pointed out on IRC that GVN's propagateEquality wasn't propagating
authorDuncan Sands <baldrick@free.fr>
Sun, 4 Mar 2012 13:25:19 +0000 (13:25 +0000)
committerDuncan Sands <baldrick@free.fr>
Sun, 4 Mar 2012 13:25:19 +0000 (13:25 +0000)
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).

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@152006 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/Scalar/GVN.cpp
test/Transforms/GVN/condprop.ll

index 37e970b8b6144a2fac181ad5be70693a07c39229..dc13edff2555cda456d51d4e85c914fcca5badd0 100644 (file)
@@ -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<Instruction>(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<PHINode>(U.getUser()))
+      UsingBlock = PN->getIncomingBlock(U);
+    else
+      UsingBlock = cast<Instruction>(U.getUser())->getParent();
+
+    if (DT->dominates(Root, UsingBlock)) {
       U.set(To);
       ++Count;
     }
index b22675b47cc0e0c292f68c5d6f101e258054e481..9c28955801f77deb2e87ff04c2b3973dfdfa823a 100644 (file)
@@ -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
+}