aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib
diff options
context:
space:
mode:
authorAnna Thomas <anna@azul.com>2021-09-20 16:37:38 -0400
committerAnna Thomas <anna@azul.com>2021-09-21 10:04:04 -0400
commit69921f6f4558a2c5c8e48c5b12d83a65127bfecc (patch)
treefefff8aef5347a6e94b7fd4ca7739748f437224c /llvm/lib
parentee31ad0ab5f7d443b0bd582582a3524dcf7f13f0 (diff)
downloadllvm-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.cpp12
-rw-r--r--llvm/lib/Transforms/InstCombine/InstructionCombining.cpp29
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