[llvm] 69921f6 - [InstCombine] Improve TryToSinkInstruction with multiple uses
Anna Thomas via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 21 07:04:36 PDT 2021
Author: Anna Thomas
Date: 2021-09-21T10:04:04-04:00
New Revision: 69921f6f4558a2c5c8e48c5b12d83a65127bfecc
URL: https://github.com/llvm/llvm-project/commit/69921f6f4558a2c5c8e48c5b12d83a65127bfecc
DIFF: https://github.com/llvm/llvm-project/commit/69921f6f4558a2c5c8e48c5b12d83a65127bfecc.diff
LOG: [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
Added:
Modified:
llvm/include/llvm/IR/Value.h
llvm/lib/IR/Value.cpp
llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
llvm/test/Transforms/InstCombine/icmp-mul-zext.ll
llvm/test/Transforms/InstCombine/sink_instruction.ll
llvm/test/Transforms/SLPVectorizer/X86/blending-shuffle-inseltpoison.ll
llvm/test/Transforms/SLPVectorizer/X86/blending-shuffle.ll
Removed:
################################################################################
diff --git a/llvm/include/llvm/IR/Value.h b/llvm/include/llvm/IR/Value.h
index d19c5af87fb7d..253c97c3b5e33 100644
--- a/llvm/include/llvm/IR/Value.h
+++ b/llvm/include/llvm/IR/Value.h
@@ -459,6 +459,13 @@ class Value {
return const_cast<Value *>(this)->getSingleUndroppableUse();
}
+ /// Return true if there is exactly one unique user of this value that cannot be
+ /// dropped (that user can have multiple uses of this value).
+ User *getUniqueUndroppableUser();
+ const User *getUniqueUndroppableUser() const {
+ return const_cast<Value *>(this)->getUniqueUndroppableUser();
+ }
+
/// Return true if there this value.
///
/// This is specialized because it is a common request and does not require
diff --git a/llvm/lib/IR/Value.cpp b/llvm/lib/IR/Value.cpp
index a13380b51b21c..0f11bf6106bd5 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 6ba4e1cba2c79..249915bceebb2 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
diff erent 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
diff --git a/llvm/test/Transforms/InstCombine/icmp-mul-zext.ll b/llvm/test/Transforms/InstCombine/icmp-mul-zext.ll
index 9b4d9947d1619..e70d070b79df0 100644
--- a/llvm/test/Transforms/InstCombine/icmp-mul-zext.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-mul-zext.ll
@@ -56,9 +56,9 @@ lor.end:
define void @PR33765(i8 %beth) {
; CHECK-LABEL: @PR33765(
-; CHECK-NEXT: [[CONV:%.*]] = zext i8 [[BETH:%.*]] to i32
; CHECK-NEXT: br i1 false, label [[IF_THEN9:%.*]], label [[IF_THEN9]]
; CHECK: if.then9:
+; CHECK-NEXT: [[CONV:%.*]] = zext i8 [[BETH:%.*]] to i32
; CHECK-NEXT: [[MUL:%.*]] = mul nuw nsw i32 [[CONV]], [[CONV]]
; CHECK-NEXT: [[TINKY:%.*]] = load i16, i16* @glob, align 2
; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[MUL]] to i16
diff --git a/llvm/test/Transforms/InstCombine/sink_instruction.ll b/llvm/test/Transforms/InstCombine/sink_instruction.ll
index 4ac00571bc3c1..a9aba3164d3eb 100644
--- a/llvm/test/Transforms/InstCombine/sink_instruction.ll
+++ b/llvm/test/Transforms/InstCombine/sink_instruction.ll
@@ -114,13 +114,13 @@ sw.epilog: ; preds = %entry, %sw.bb
}
declare i32 @foo(i32, i32)
-; TODO: Two uses in a single user. We can still sink the instruction (tmp.9).
+; Two uses in a single user. We can still sink the instruction (tmp.9).
define i32 @test4(i32 %A, i32 %B, i1 %C) {
; CHECK-LABEL: @test4(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[TMP_9:%.*]] = add i32 [[B:%.*]], [[A:%.*]]
; CHECK-NEXT: br i1 [[C:%.*]], label [[THEN:%.*]], label [[ENDIF:%.*]]
; CHECK: then:
+; CHECK-NEXT: [[TMP_9:%.*]] = add i32 [[B:%.*]], [[A:%.*]]
; CHECK-NEXT: [[RES:%.*]] = call i32 @foo(i32 [[TMP_9]], i32 [[TMP_9]])
; CHECK-NEXT: ret i32 [[RES]]
; CHECK: endif:
@@ -175,16 +175,16 @@ sw.epilog: ; preds = %entry, %sw.bb
ret i32 %sum.0
}
-; TODO: Multiple uses but from same BB. We can sink.
+; Multiple uses but from same BB. We can sink.
define i32 @test6(i32* nocapture readonly %P, i32 %i, i1 %cond) {
; CHECK-LABEL: @test6(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[IDXPROM:%.*]] = sext i32 [[I:%.*]] to i64
-; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[P:%.*]], i64 [[IDXPROM]]
-; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[ARRAYIDX]], align 4
; CHECK-NEXT: [[ADD:%.*]] = shl nsw i32 [[I]], 1
; CHECK-NEXT: br label [[DISPATCHBB:%.*]]
; CHECK: dispatchBB:
+; CHECK-NEXT: [[IDXPROM:%.*]] = sext i32 [[I:%.*]] to i64
+; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[P:%.*]], i64 [[IDXPROM]]
+; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[ARRAYIDX]], align 4
; CHECK-NEXT: switch i32 [[I]], label [[SW_BB:%.*]] [
; CHECK-NEXT: i32 5, label [[SW_EPILOG:%.*]]
; CHECK-NEXT: i32 2, label [[SW_EPILOG]]
diff --git a/llvm/test/Transforms/SLPVectorizer/X86/blending-shuffle-inseltpoison.ll b/llvm/test/Transforms/SLPVectorizer/X86/blending-shuffle-inseltpoison.ll
index 1c806c6b1f736..f23eb38d48057 100644
--- a/llvm/test/Transforms/SLPVectorizer/X86/blending-shuffle-inseltpoison.ll
+++ b/llvm/test/Transforms/SLPVectorizer/X86/blending-shuffle-inseltpoison.ll
@@ -139,9 +139,9 @@ define i8 @k(<4 x i8> %x) {
define i8 @k_bb(<4 x i8> %x) {
; CHECK-LABEL: @k_bb(
-; CHECK-NEXT: [[X0:%.*]] = extractelement <4 x i8> [[X:%.*]], i32 0
; CHECK-NEXT: br label [[BB1:%.*]]
; CHECK: bb1:
+; CHECK-NEXT: [[X0:%.*]] = extractelement <4 x i8> [[X:%.*]], i32 0
; CHECK-NEXT: [[X3:%.*]] = extractelement <4 x i8> [[X]], i32 3
; CHECK-NEXT: [[X1:%.*]] = extractelement <4 x i8> [[X]], i32 1
; CHECK-NEXT: [[X2:%.*]] = extractelement <4 x i8> [[X]], i32 2
diff --git a/llvm/test/Transforms/SLPVectorizer/X86/blending-shuffle.ll b/llvm/test/Transforms/SLPVectorizer/X86/blending-shuffle.ll
index 0fcc096773dd2..6bbfb53014ce6 100644
--- a/llvm/test/Transforms/SLPVectorizer/X86/blending-shuffle.ll
+++ b/llvm/test/Transforms/SLPVectorizer/X86/blending-shuffle.ll
@@ -139,9 +139,9 @@ define i8 @k(<4 x i8> %x) {
define i8 @k_bb(<4 x i8> %x) {
; CHECK-LABEL: @k_bb(
-; CHECK-NEXT: [[X0:%.*]] = extractelement <4 x i8> [[X:%.*]], i32 0
; CHECK-NEXT: br label [[BB1:%.*]]
; CHECK: bb1:
+; CHECK-NEXT: [[X0:%.*]] = extractelement <4 x i8> [[X:%.*]], i32 0
; CHECK-NEXT: [[X3:%.*]] = extractelement <4 x i8> [[X]], i32 3
; CHECK-NEXT: [[X1:%.*]] = extractelement <4 x i8> [[X]], i32 1
; CHECK-NEXT: [[X2:%.*]] = extractelement <4 x i8> [[X]], i32 2
More information about the llvm-commits
mailing list