diff options
author | Anna Thomas <anna@azul.com> | 2021-09-20 16:37:38 -0400 |
---|---|---|
committer | Anna Thomas <anna@azul.com> | 2021-09-21 10:04:04 -0400 |
commit | 69921f6f4558a2c5c8e48c5b12d83a65127bfecc (patch) | |
tree | fefff8aef5347a6e94b7fd4ca7739748f437224c /llvm/lib | |
parent | ee31ad0ab5f7d443b0bd582582a3524dcf7f13f0 (diff) | |
download | llvm-69921f6f4558a2c5c8e48c5b12d83a65127bfecc.zip llvm-69921f6f4558a2c5c8e48c5b12d83a65127bfecc.tar.gz llvm-69921f6f4558a2c5c8e48c5b12d83a65127bfecc.tar.bz2 |
[InstCombine] Improve TryToSinkInstruction with multiple uses
This patch allows sinking an instruction which can have multiple uses in a
single user. We were previously over-restrictive by looking for exactly one use,
rather than one user.
Also added an API for retrieving a unique undroppable user.
Reviewed By: nikic
Differential Revision: https://reviews.llvm.org/D109700
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/IR/Value.cpp | 12 | ||||
-rw-r--r-- | llvm/lib/Transforms/InstCombine/InstructionCombining.cpp | 29 |
2 files changed, 31 insertions, 10 deletions
diff --git a/llvm/lib/IR/Value.cpp b/llvm/lib/IR/Value.cpp index a13380b..0f11bf61 100644 --- a/llvm/lib/IR/Value.cpp +++ b/llvm/lib/IR/Value.cpp @@ -176,6 +176,18 @@ Use *Value::getSingleUndroppableUse() { return Result; } +User *Value::getUniqueUndroppableUser() { + User *Result = nullptr; + for (auto *U : users()) { + if (!U->isDroppable()) { + if (Result && Result != U) + return nullptr; + Result = U; + } + } + return Result; +} + bool Value::hasNUndroppableUses(unsigned int N) const { return hasNItems(user_begin(), user_end(), N, isUnDroppableUser); } diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp index 6ba4e1c..249915b 100644 --- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -3613,7 +3613,7 @@ Instruction *InstCombinerImpl::visitFreeze(FreezeInst &I) { /// instruction past all of the instructions between it and the end of its /// block. static bool TryToSinkInstruction(Instruction *I, BasicBlock *DestBlock) { - assert(I->getSingleUndroppableUse() && "Invariants didn't hold!"); + assert(I->getUniqueUndroppableUser() && "Invariants didn't hold!"); BasicBlock *SrcBlock = I->getParent(); // Cannot move control-flow-involving, volatile loads, vaarg, etc. @@ -3772,18 +3772,27 @@ bool InstCombinerImpl::run() { [this](Instruction *I) -> Optional<BasicBlock *> { if (!EnableCodeSinking) return None; - Use *SingleUse = I->getSingleUndroppableUse(); - if (!SingleUse) + auto *UserInst = cast_or_null<Instruction>(I->getUniqueUndroppableUser()); + if (!UserInst) return None; BasicBlock *BB = I->getParent(); - Instruction *UserInst = cast<Instruction>(SingleUse->getUser()); - BasicBlock *UserParent; - - // Get the block the use occurs in. - if (PHINode *PN = dyn_cast<PHINode>(UserInst)) - UserParent = PN->getIncomingBlock(*SingleUse); - else + BasicBlock *UserParent = nullptr; + + // Special handling for Phi nodes - get the block the use occurs in. + if (PHINode *PN = dyn_cast<PHINode>(UserInst)) { + for (unsigned i = 0; i < PN->getNumIncomingValues(); i++) { + if (PN->getIncomingValue(i) == I) { + // Bail out if we have uses in different blocks. We don't do any + // sophisticated analysis (i.e finding NearestCommonDominator of these + // use blocks). + if (UserParent && UserParent != PN->getIncomingBlock(i)) + return None; + UserParent = PN->getIncomingBlock(i); + } + } + assert(UserParent && "expected to find user block!"); + } else UserParent = UserInst->getParent(); // Try sinking to another block. If that block is unreachable, then do |