Skip to content

Commit 4ac4e52

Browse files
committed
[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, the API for retrieving undroppable user has been updated accordingly since in both usecases (Attributor and InstCombine), we seem to care about the user, rather than the use. Reviewed-By: nikic Differential Revision: https://reviews.llvm.org/D109700
1 parent 248e430 commit 4ac4e52

File tree

6 files changed

+40
-30
lines changed

6 files changed

+40
-30
lines changed

llvm/include/llvm/IR/Value.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -452,11 +452,11 @@ class Value {
452452
/// in the worst case, the whole use list of a value.
453453
bool hasOneUser() const;
454454

455-
/// Return true if there is exactly one use of this value that cannot be
456-
/// dropped.
457-
Use *getSingleUndroppableUse();
458-
const Use *getSingleUndroppableUse() const {
459-
return const_cast<Value *>(this)->getSingleUndroppableUse();
455+
/// Return true if there is exactly one unique user of this value that cannot be
456+
/// dropped (that user can have multiple uses of this value).
457+
User *getUniqueUndroppableUser();
458+
const User *getUniqueUndroppableUser() const {
459+
return const_cast<Value *>(this)->getUniqueUndroppableUser();
460460
}
461461

462462
/// Return true if there this value.

llvm/lib/IR/Value.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -164,13 +164,13 @@ bool Value::hasOneUser() const {
164164

165165
static bool isUnDroppableUser(const User *U) { return !U->isDroppable(); }
166166

167-
Use *Value::getSingleUndroppableUse() {
168-
Use *Result = nullptr;
169-
for (Use &U : uses()) {
170-
if (!U.getUser()->isDroppable()) {
171-
if (Result)
167+
User *Value::getUniqueUndroppableUser() {
168+
User *Result = nullptr;
169+
for (auto *U : users()) {
170+
if (!U->isDroppable()) {
171+
if (Result && Result != U)
172172
return nullptr;
173-
Result = &U;
173+
Result = U;
174174
}
175175
}
176176
return Result;

llvm/lib/Transforms/InstCombine/InstructionCombining.cpp

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3659,7 +3659,7 @@ Instruction *InstCombinerImpl::visitFreeze(FreezeInst &I) {
36593659
/// instruction past all of the instructions between it and the end of its
36603660
/// block.
36613661
static bool TryToSinkInstruction(Instruction *I, BasicBlock *DestBlock) {
3662-
assert(I->getSingleUndroppableUse() && "Invariants didn't hold!");
3662+
assert(I->getUniqueUndroppableUser() && "Invariants didn't hold!");
36633663
BasicBlock *SrcBlock = I->getParent();
36643664

36653665
// Cannot move control-flow-involving, volatile loads, vaarg, etc.
@@ -3818,18 +3818,27 @@ bool InstCombinerImpl::run() {
38183818
[this](Instruction *I) -> Optional<BasicBlock *> {
38193819
if (!EnableCodeSinking)
38203820
return None;
3821-
Use *SingleUse = I->getSingleUndroppableUse();
3822-
if (!SingleUse)
3821+
auto *UserInst = cast_or_null<Instruction>(I->getUniqueUndroppableUser());
3822+
if (!UserInst)
38233823
return None;
38243824

38253825
BasicBlock *BB = I->getParent();
3826-
Instruction *UserInst = cast<Instruction>(SingleUse->getUser());
3827-
BasicBlock *UserParent;
3828-
3829-
// Get the block the use occurs in.
3830-
if (PHINode *PN = dyn_cast<PHINode>(UserInst))
3831-
UserParent = PN->getIncomingBlock(*SingleUse);
3832-
else
3826+
BasicBlock *UserParent = nullptr;
3827+
3828+
// Special handling for Phi nodes - get the block the use occurs in.
3829+
if (PHINode *PN = dyn_cast<PHINode>(UserInst)) {
3830+
for (unsigned i = 0; i < PN->getNumIncomingValues(); i++) {
3831+
if (PN->getIncomingValue(i) == I) {
3832+
// Bail out if we have uses in different blocks. We don't do any
3833+
// sophisticated analysis (i.e finding NearestCommonDominator of these
3834+
// use blocks).
3835+
if (UserParent && UserParent != PN->getIncomingBlock(i))
3836+
return None;
3837+
UserParent = PN->getIncomingBlock(i);
3838+
}
3839+
}
3840+
assert(UserParent && "expected to find user block!");
3841+
} else
38333842
UserParent = UserInst->getParent();
38343843

38353844
// Try sinking to another block. If that block is unreachable, then do

llvm/lib/Transforms/Utils/AssumeBundleBuilder.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -161,8 +161,9 @@ struct AssumeBuilderState {
161161
if (wouldInstructionBeTriviallyDead(Inst)) {
162162
if (RK.WasOn->use_empty())
163163
return false;
164-
Use *SingleUse = RK.WasOn->getSingleUndroppableUse();
165-
if (SingleUse && SingleUse->getUser() == InstBeingModified)
164+
auto *UniqueUser =
165+
RK.WasOn->getUniqueUndroppableUser();
166+
if (UniqueUser == InstBeingModified)
166167
return false;
167168
}
168169
return true;

llvm/test/Transforms/InstCombine/icmp-mul-zext.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,9 @@ lor.end:
5656

5757
define void @PR33765(i8 %beth) {
5858
; CHECK-LABEL: @PR33765(
59-
; CHECK-NEXT: [[CONV:%.*]] = zext i8 [[BETH:%.*]] to i32
6059
; CHECK-NEXT: br i1 false, label [[IF_THEN9:%.*]], label [[IF_THEN9]]
6160
; CHECK: if.then9:
61+
; CHECK-NEXT: [[CONV:%.*]] = zext i8 [[BETH:%.*]] to i32
6262
; CHECK-NEXT: [[MUL:%.*]] = mul nuw nsw i32 [[CONV]], [[CONV]]
6363
; CHECK-NEXT: [[TINKY:%.*]] = load i16, i16* @glob, align 2
6464
; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[MUL]] to i16

llvm/test/Transforms/InstCombine/sink_instruction.ll

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -114,13 +114,13 @@ sw.epilog: ; preds = %entry, %sw.bb
114114
}
115115

116116
declare i32 @foo(i32, i32)
117-
; TODO: Two uses in a single user. We can still sink the instruction (tmp.9).
117+
; Two uses in a single user. We can still sink the instruction (tmp.9).
118118
define i32 @test4(i32 %A, i32 %B, i1 %C) {
119119
; CHECK-LABEL: @test4(
120120
; CHECK-NEXT: entry:
121-
; CHECK-NEXT: [[TMP_9:%.*]] = add i32 [[B:%.*]], [[A:%.*]]
122121
; CHECK-NEXT: br i1 [[C:%.*]], label [[THEN:%.*]], label [[ENDIF:%.*]]
123122
; CHECK: then:
123+
; CHECK-NEXT: [[TMP_9:%.*]] = add i32 [[B:%.*]], [[A:%.*]]
124124
; CHECK-NEXT: [[RES:%.*]] = call i32 @foo(i32 [[TMP_9]], i32 [[TMP_9]])
125125
; CHECK-NEXT: ret i32 [[RES]]
126126
; CHECK: endif:
@@ -175,16 +175,16 @@ sw.epilog: ; preds = %entry, %sw.bb
175175
ret i32 %sum.0
176176
}
177177

178-
; TODO: Multiple uses but from same BB. We can sink.
178+
; Multiple uses but from same BB. We can sink.
179179
define i32 @test6(i32* nocapture readonly %P, i32 %i, i1 %cond) {
180180
; CHECK-LABEL: @test6(
181181
; CHECK-NEXT: entry:
182-
; CHECK-NEXT: [[IDXPROM:%.*]] = sext i32 [[I:%.*]] to i64
183-
; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[P:%.*]], i64 [[IDXPROM]]
184-
; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[ARRAYIDX]], align 4
185182
; CHECK-NEXT: [[ADD:%.*]] = shl nsw i32 [[I]], 1
186183
; CHECK-NEXT: br label [[DISPATCHBB:%.*]]
187184
; CHECK: dispatchBB:
185+
; CHECK-NEXT: [[IDXPROM:%.*]] = sext i32 [[I:%.*]] to i64
186+
; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[P:%.*]], i64 [[IDXPROM]]
187+
; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[ARRAYIDX]], align 4
188188
; CHECK-NEXT: switch i32 [[I]], label [[SW_BB:%.*]] [
189189
; CHECK-NEXT: i32 5, label [[SW_EPILOG:%.*]]
190190
; CHECK-NEXT: i32 2, label [[SW_EPILOG]]

0 commit comments

Comments
 (0)