diff options
author | Erik Desjardins <erikdesjardinspublic@gmail.com> | 2021-10-07 08:14:56 -0700 |
---|---|---|
committer | Mircea Trofin <mtrofin@google.com> | 2021-10-07 08:33:25 -0700 |
commit | 11c8efd4db0fe58a2858459353cc5c0c41565ee5 (patch) | |
tree | 4e49db7776b879ecfea37b9035d5101b2da60f42 /llvm/lib/IR/Constants.cpp | |
parent | 3a5aa57c9b1c01c990700bfcedcebc14ef9a97dc (diff) | |
download | llvm-11c8efd4db0fe58a2858459353cc5c0c41565ee5.zip llvm-11c8efd4db0fe58a2858459353cc5c0c41565ee5.tar.gz llvm-11c8efd4db0fe58a2858459353cc5c0c41565ee5.tar.bz2 |
[Inline] Introduce Constant::hasOneLiveUse, use it instead of hasOneUse in inline cost model (PR51667)
Otherwise, inlining costs may be pessimized by dead constants.
Fixes https://bugs.llvm.org/show_bug.cgi?id=51667.
Reviewed By: mtrofin, aeubanks
Differential Revision: https://reviews.llvm.org/D109294
Diffstat (limited to 'llvm/lib/IR/Constants.cpp')
-rw-r--r-- | llvm/lib/IR/Constants.cpp | 54 |
1 files changed, 40 insertions, 14 deletions
diff --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp index 30a5cae..a7a1918 100644 --- a/llvm/lib/IR/Constants.cpp +++ b/llvm/lib/IR/Constants.cpp @@ -714,29 +714,41 @@ Constant::PossibleRelocationsTy Constant::getRelocationInfo() const { return Result; } -/// If the specified constantexpr is dead, remove it. This involves recursively -/// eliminating any dead users of the constantexpr. -static bool removeDeadUsersOfConstant(const Constant *C) { +/// Return true if the specified constantexpr is dead. This involves +/// recursively traversing users of the constantexpr. +/// If RemoveDeadUsers is true, also remove dead users at the same time. +static bool constantIsDead(const Constant *C, bool RemoveDeadUsers) { if (isa<GlobalValue>(C)) return false; // Cannot remove this - while (!C->use_empty()) { - const Constant *User = dyn_cast<Constant>(C->user_back()); + Value::const_user_iterator I = C->user_begin(), E = C->user_end(); + while (I != E) { + const Constant *User = dyn_cast<Constant>(*I); if (!User) return false; // Non-constant usage; - if (!removeDeadUsersOfConstant(User)) + if (!constantIsDead(User, RemoveDeadUsers)) return false; // Constant wasn't dead + + // Just removed User, so the iterator was invalidated. + // Since we return immediately upon finding a live user, we can always + // restart from user_begin(). + if (RemoveDeadUsers) + I = C->user_begin(); + else + ++I; } - // If C is only used by metadata, it should not be preserved but should have - // its uses replaced. - if (C->isUsedByMetadata()) { - const_cast<Constant *>(C)->replaceAllUsesWith( - UndefValue::get(C->getType())); + if (RemoveDeadUsers) { + // If C is only used by metadata, it should not be preserved but should + // have its uses replaced. + if (C->isUsedByMetadata()) { + const_cast<Constant *>(C)->replaceAllUsesWith( + UndefValue::get(C->getType())); + } + const_cast<Constant *>(C)->destroyConstant(); } - const_cast<Constant*>(C)->destroyConstant(); + return true; } - void Constant::removeDeadConstantUsers() const { Value::const_user_iterator I = user_begin(), E = user_end(); Value::const_user_iterator LastNonDeadUser = E; @@ -748,7 +760,7 @@ void Constant::removeDeadConstantUsers() const { continue; } - if (!removeDeadUsersOfConstant(User)) { + if (!constantIsDead(User, /* RemoveDeadUsers= */ true)) { // If the constant wasn't dead, remember that this was the last live use // and move on to the next constant. LastNonDeadUser = I; @@ -764,6 +776,20 @@ void Constant::removeDeadConstantUsers() const { } } +bool Constant::hasOneLiveUse() const { + unsigned NumUses = 0; + for (const Use &use : uses()) { + const Constant *User = dyn_cast<Constant>(use.getUser()); + if (!User || !constantIsDead(User, /* RemoveDeadUsers= */ false)) { + ++NumUses; + + if (NumUses > 1) + return false; + } + } + return NumUses == 1; +} + Constant *Constant::replaceUndefsWith(Constant *C, Constant *Replacement) { assert(C && Replacement && "Expected non-nullptr constant arguments"); Type *Ty = C->getType(); |