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,12 +165,21 @@ // Ensure base-class overloads are visible. using Base::dominates; - /// Return true if Def dominates a use in User. + /// 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. /// - /// 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! - bool dominates(const Instruction *Def, const Use &U) const; - bool dominates(const Instruction *Def, const Instruction *User) const; + /// In particular, it is worth noting that: + /// * Non-instruction Defs dominate everything. + /// * Def does not dominate a use in Def itself (outside of degenerate cases + /// like unreachable code or trivial phi cycles). + /// * Invoke/callbr Defs only dominate uses in their default destination. + bool dominates(const Value *Def, const Use &U) const; + /// Return true if value Def dominates all possible uses inside instruction + /// User. Same comments as for the Use-based API apply. + bool dominates(const Value *Def, const Instruction *User) const; + // Does not accept Value to avoid ambiguity with dominance checks between + // two basic blocks. bool dominates(const Instruction *Def, const BasicBlock *BB) const; /// Return true if an edge dominates a use. 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 @@ -115,8 +115,14 @@ // 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! -bool DominatorTree::dominates(const Instruction *Def, +bool DominatorTree::dominates(const Value *DefV, const Instruction *User) const { + const Instruction *Def = dyn_cast(DefV); + if (!Def) { + assert(!isa(DefV) && "Should not be called with basic blocks"); + return true; // Arguments, constants, globals dominate everything. + } + const BasicBlock *UseBB = User->getParent(); const BasicBlock *DefBB = Def->getParent(); @@ -250,7 +256,13 @@ return dominates(BBE, UseBB); } -bool DominatorTree::dominates(const Instruction *Def, const Use &U) const { +bool DominatorTree::dominates(const Value *DefV, const Use &U) const { + const Instruction *Def = dyn_cast(DefV); + if (!Def) { + assert(!isa(DefV) && "Should not be called with basic blocks"); + return true; // Arguments, constants, globals dominate everything. + } + Instruction *UserInst = cast(U.getUser()); const BasicBlock *DefBB = Def->getParent(); diff --git a/llvm/unittests/IR/DominatorTreeTest.cpp b/llvm/unittests/IR/DominatorTreeTest.cpp --- a/llvm/unittests/IR/DominatorTreeTest.cpp +++ b/llvm/unittests/IR/DominatorTreeTest.cpp @@ -1071,3 +1071,32 @@ EXPECT_TRUE(DT->dominates(E23, E23)); }); } + +TEST(DominatorTree, ValueDomination) { + StringRef ModuleString = R"( + @foo = global i8 0 + define i8 @f(i8 %arg) { + ret i8 %arg + } + )"; + + LLVMContext Context; + std::unique_ptr M = makeLLVMModule(Context, ModuleString); + + runWithDomTree(*M, "f", + [&](Function &F, DominatorTree *DT, PostDominatorTree *PDT) { + Argument *A = F.getArg(0); + GlobalValue *G = M->getNamedValue("foo"); + Constant *C = ConstantInt::getNullValue(Type::getInt8Ty(Context)); + + Instruction *I = F.getEntryBlock().getTerminator(); + EXPECT_TRUE(DT->dominates(A, I)); + EXPECT_TRUE(DT->dominates(G, I)); + EXPECT_TRUE(DT->dominates(C, I)); + + const Use &U = I->getOperandUse(0); + EXPECT_TRUE(DT->dominates(A, U)); + EXPECT_TRUE(DT->dominates(G, U)); + EXPECT_TRUE(DT->dominates(C, U)); + }); +}