Index: llvm/lib/Transforms/Utils/Local.cpp =================================================================== --- llvm/lib/Transforms/Utils/Local.cpp +++ llvm/lib/Transforms/Utils/Local.cpp @@ -2694,8 +2694,19 @@ DominatorTree &DT, const BasicBlock *BB) { auto ProperlyDominates = [&DT](const BasicBlock *BB, const Use &U) { - auto *I = cast(U.getUser())->getParent(); - return DT.properlyDominates(BB, I); + Instruction *UserInst = cast(U.getUser()); + PHINode *PN = dyn_cast(UserInst); + // A phi use using a value from a block is dominated by the end of that + // block. Note that the phi's parent block may not be. + if (PN && PN->getIncomingBlock(U) == BB) + return true; + + const BasicBlock *UseBB; + if (PN) + UseBB = PN->getIncomingBlock(U); + else + UseBB = UserInst->getParent(); + return DT.properlyDominates(BB, UseBB); }; return ::replaceDominatedUsesWith(From, To, BB, ProperlyDominates); } Index: llvm/test/Transforms/GVN/phi.ll =================================================================== --- llvm/test/Transforms/GVN/phi.ll +++ llvm/test/Transforms/GVN/phi.ll @@ -39,7 +39,7 @@ ; CHECK: untaken: ; CHECK-NEXT: br label [[MERGE]] ; CHECK: merge: -; CHECK-NEXT: [[PHI1:%.*]] = phi i64 [ [[A]], [[TAKEN]] ], [ [[B:%.*]], [[UNTAKEN]] ] +; CHECK-NEXT: [[PHI1:%.*]] = phi i64 [ 0, [[TAKEN]] ], [ [[B:%.*]], [[UNTAKEN]] ] ; CHECK-NEXT: [[PHI2:%.*]] = phi i64 [ 0, [[TAKEN]] ], [ [[B]], [[UNTAKEN]] ] ; CHECK-NEXT: [[RET:%.*]] = sub i64 [[PHI1]], [[PHI2]] ; CHECK-NEXT: ret i64 [[RET]] @@ -131,3 +131,80 @@ %ret = sub i64 %phi4, %phi3 ret i64 %ret } + +define i64 @test5(i1 %c, i64 %a) { +; CHECK-LABEL: @test5( +; CHECK-NEXT: br i1 [[C:%.*]], label [[TAKEN:%.*]], label [[UNTAKEN:%.*]] +; CHECK: taken: +; CHECK-NEXT: [[ASSUMPTION:%.*]] = icmp eq i64 [[A:%.*]], 0 +; CHECK-NEXT: call void @llvm.assume(i1 [[ASSUMPTION]]) +; CHECK-NEXT: br label [[MERGE:%.*]] +; CHECK: untaken: +; CHECK-NEXT: br label [[MERGE]] +; CHECK: merge: +; CHECK-NEXT: ret i64 0 +; + br i1 %c, label %taken, label %untaken +taken: + %assumption = icmp eq i64 %a, 0 + call void @llvm.assume(i1 %assumption) + br label %merge +untaken: + br label %merge +merge: + %phi = phi i64 [%a, %taken], [0, %untaken] + ret i64 %phi +} + +define i64 @test6(i1 %c, i64 %a) { +; CHECK-LABEL: @test6( +; CHECK-NEXT: br i1 [[C:%.*]], label [[TAKEN:%.*]], label [[UNTAKEN:%.*]] +; CHECK: taken: +; CHECK-NEXT: [[ASSUMPTION:%.*]] = icmp eq i64 [[A:%.*]], 0 +; CHECK-NEXT: call void @llvm.assume(i1 [[ASSUMPTION]]) +; CHECK-NEXT: br label [[MERGE:%.*]] +; CHECK: untaken: +; CHECK-NEXT: br label [[MERGE]] +; CHECK: merge: +; CHECK-NEXT: ret i64 0 +; + br i1 %c, label %taken, label %untaken +taken: + %assumption = icmp eq i64 %a, 0 + call void @llvm.assume(i1 %assumption) + br label %next +next: + br label %merge +untaken: + br label %merge +merge: + %phi = phi i64 [%a, %next], [0, %untaken] + ret i64 %phi +} + +; negative test, phi use is NOT dominated by assume +define i64 @test7(i1 %c, i64 %a) { +; CHECK-LABEL: @test7( +; CHECK-NEXT: br i1 [[C:%.*]], label [[TAKEN:%.*]], label [[UNTAKEN:%.*]] +; CHECK: taken: +; CHECK-NEXT: [[ASSUMPTION:%.*]] = icmp eq i64 [[A:%.*]], 0 +; CHECK-NEXT: call void @llvm.assume(i1 [[ASSUMPTION]]) +; CHECK-NEXT: br label [[MERGE:%.*]] +; CHECK: untaken: +; CHECK-NEXT: br label [[MERGE]] +; CHECK: merge: +; CHECK-NEXT: ret i64 [[A]] +; + br i1 %c, label %taken, label %untaken +taken: + %assumption = icmp eq i64 %a, 0 + call void @llvm.assume(i1 %assumption) + br label %merge +untaken: + br label %merge +merge: + br label %next +next: + %phi = phi i64 [%a, %merge] + ret i64 %phi +}