diff --git a/llvm/include/llvm/IR/Constant.h b/llvm/include/llvm/IR/Constant.h --- a/llvm/include/llvm/IR/Constant.h +++ b/llvm/include/llvm/IR/Constant.h @@ -204,6 +204,12 @@ /// Constant::removeDeadConstantUsers, but doesn't remove dead constants. bool hasOneLiveUse() const; + /// Return true if the constant has exactly one live use. + /// + /// This returns the same result as calling Value::use_empty after + /// Constant::removeDeadConstantUsers, but doesn't remove dead constants. + bool hasZeroLiveUses() const; + const Constant *stripPointerCasts() const { return cast(Value::stripPointerCasts()); } @@ -244,6 +250,8 @@ /// Determine what potential relocations may be needed by this constant. PossibleRelocationsTy getRelocationInfo() const; + + bool hasNLiveUses(unsigned N) const; }; } // end namespace llvm diff --git a/llvm/lib/Analysis/LazyCallGraph.cpp b/llvm/lib/Analysis/LazyCallGraph.cpp --- a/llvm/lib/Analysis/LazyCallGraph.cpp +++ b/llvm/lib/Analysis/LazyCallGraph.cpp @@ -1503,7 +1503,7 @@ void LazyCallGraph::removeDeadFunction(Function &F) { // FIXME: This is unnecessarily restrictive. We should be able to remove // functions which recursively call themselves. - assert(F.use_empty() && + assert(F.hasZeroLiveUses() && "This routine should only be called on trivially dead functions!"); // We shouldn't remove library functions as they are never really dead while diff --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp --- a/llvm/lib/IR/Constants.cpp +++ b/llvm/lib/IR/Constants.cpp @@ -779,18 +779,22 @@ } } -bool Constant::hasOneLiveUse() const { +bool Constant::hasOneLiveUse() const { return hasNLiveUses(1); } + +bool Constant::hasZeroLiveUses() const { return hasNLiveUses(0); } + +bool Constant::hasNLiveUses(unsigned N) const { unsigned NumUses = 0; - for (const Use &use : uses()) { - const Constant *User = dyn_cast(use.getUser()); + for (const Use &U : uses()) { + const Constant *User = dyn_cast(U.getUser()); if (!User || !constantIsDead(User, /* RemoveDeadUsers= */ false)) { ++NumUses; - if (NumUses > 1) + if (NumUses > N) return false; } } - return NumUses == 1; + return NumUses == N; } Constant *Constant::replaceUndefsWith(Constant *C, Constant *Replacement) { diff --git a/llvm/lib/Transforms/IPO/Inliner.cpp b/llvm/lib/Transforms/IPO/Inliner.cpp --- a/llvm/lib/Transforms/IPO/Inliner.cpp +++ b/llvm/lib/Transforms/IPO/Inliner.cpp @@ -946,10 +946,7 @@ // discardable functions with comdats are checked later on. bool CalleeWasDeleted = false; if (Callee.isDiscardableIfUnused()) { - // To check this we also need to nuke any dead constant uses (perhaps - // made dead by this operation on other functions). - Callee.removeDeadConstantUsers(); - if (Callee.use_empty() && !CG.isLibFunction(Callee)) { + if (Callee.hasZeroLiveUses() && !CG.isLibFunction(Callee)) { if (Callee.hasLocalLinkage() || !Callee.hasComdat()) { Calls->erase_if([&](const std::pair &Call) { return Call.first->getCaller() == &Callee;