diff --git a/llvm/include/llvm/IR/Dominators.h b/llvm/include/llvm/IR/Dominators.h --- a/llvm/include/llvm/IR/Dominators.h +++ b/llvm/include/llvm/IR/Dominators.h @@ -165,6 +165,9 @@ // Ensure base-class overloads are visible. using Base::dominates; + /// Return true if the (end of the) basic block BB dominates the use U. + bool dominates(const BasicBlock *BB, const Use &U) const; + /// Return true if value Def dominates use U, in the sense that Def is /// available at U, and could be substituted as the used value without /// violating the SSA dominance requirement. diff --git a/llvm/lib/IR/Dominators.cpp b/llvm/lib/IR/Dominators.cpp --- a/llvm/lib/IR/Dominators.cpp +++ b/llvm/lib/IR/Dominators.cpp @@ -112,6 +112,16 @@ PAC.preservedSet()); } +bool DominatorTree::dominates(const BasicBlock *BB, const Use &U) const { + Instruction *UserInst = cast(U.getUser()); + if (auto *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. + return dominates(BB, PN->getIncomingBlock(U)); + else + return properlyDominates(BB, UserInst->getParent()); +} + // dominates - Return true if Def dominates a use in User. This performs // the special checks necessary if Def and User are in the same basic block. // Note that Def doesn't dominate a use in Def itself! diff --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp --- a/llvm/lib/Transforms/Utils/Local.cpp +++ b/llvm/lib/Transforms/Utils/Local.cpp @@ -2683,11 +2683,10 @@ unsigned llvm::replaceDominatedUsesWith(Value *From, Value *To, 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); + auto Dominates = [&DT](const BasicBlock *BB, const Use &U) { + return DT.dominates(BB, U); }; - return ::replaceDominatedUsesWith(From, To, BB, ProperlyDominates); + return ::replaceDominatedUsesWith(From, To, BB, Dominates); } bool llvm::callsGCLeafFunction(const CallBase *Call, diff --git a/llvm/test/Transforms/GVN/phi.ll b/llvm/test/Transforms/GVN/phi.ll --- a/llvm/test/Transforms/GVN/phi.ll +++ b/llvm/test/Transforms/GVN/phi.ll @@ -37,10 +37,8 @@ ; CHECK: untaken: ; CHECK-NEXT: br label [[MERGE]] ; CHECK: merge: -; CHECK-NEXT: [[PHI1:%.*]] = phi i64 [ [[A]], [[TAKEN]] ], [ [[B:%.*]], [[UNTAKEN]] ] -; CHECK-NEXT: [[PHI2:%.*]] = phi i64 [ 0, [[TAKEN]] ], [ [[B]], [[UNTAKEN]] ] -; CHECK-NEXT: [[RET:%.*]] = sub i64 [[PHI1]], [[PHI2]] -; CHECK-NEXT: ret i64 [[RET]] +; CHECK-NEXT: [[PHI1:%.*]] = phi i64 [ 0, [[TAKEN]] ], [ [[B:%.*]], [[UNTAKEN]] ] +; CHECK-NEXT: ret i64 0 ; br i1 %c, label %taken, label %untaken taken: @@ -134,8 +132,7 @@ ; CHECK: untaken: ; CHECK-NEXT: br label [[MERGE]] ; CHECK: merge: -; CHECK-NEXT: [[PHI:%.*]] = phi i64 [ [[A]], [[TAKEN]] ], [ 0, [[UNTAKEN]] ] -; CHECK-NEXT: ret i64 [[PHI]] +; CHECK-NEXT: ret i64 0 ; br i1 %c, label %taken, label %untaken taken: @@ -159,8 +156,7 @@ ; CHECK: untaken: ; CHECK-NEXT: br label [[MERGE]] ; CHECK: merge: -; CHECK-NEXT: [[PHI:%.*]] = phi i64 [ [[A]], [[TAKEN]] ], [ 0, [[UNTAKEN]] ] -; CHECK-NEXT: ret i64 [[PHI]] +; CHECK-NEXT: ret i64 0 ; br i1 %c, label %taken, label %untaken taken: