[PATCH] D151807: [InstCombine] Revisit user of newly one-use instructions
Nikita Popov via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Wed May 31 07:50:36 PDT 2023
nikic created this revision.
nikic added reviewers: goldstein.w.n, RKSimon, fhahn.
Herald added subscribers: StephenFan, hiraditya.
Herald added a project: All.
nikic requested review of this revision.
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.
Many folds in InstCombine are limited to one-use instructions. For that reason, if the use-count of an instruction drops to one, it makes sense to revisit that one user. This is one of the most common reasons why InstCombine fails to finish in a single iteration.
Doing this revisit actually slightly improves compile-time (http://llvm-compile-time-tracker.com/compare.php?from=97f0e7b06e6b76fd85fb81b8c12eba2255ff1742&to=fc740dee13f42a948b378d731e666d0a80d16061&stat=instructions:u), because we save an extra InstCombine iteration in enough cases to make a visible difference.
This is conceptually NFC, but not NFC in practice, because differences in worklist order can result in slightly different folding behavior.
https://reviews.llvm.org/D151807
Files:
llvm/include/llvm/Transforms/Utils/InstructionWorklist.h
llvm/lib/Transforms/InstCombine/InstCombineInternal.h
llvm/test/Other/print-debug-counter.ll
llvm/test/Transforms/InstCombine/or-shifted-masks.ll
Index: llvm/test/Transforms/InstCombine/or-shifted-masks.ll
===================================================================
--- llvm/test/Transforms/InstCombine/or-shifted-masks.ll
+++ llvm/test/Transforms/InstCombine/or-shifted-masks.ll
@@ -54,10 +54,13 @@
define i32 @multiuse1(i32 %x) {
; CHECK-LABEL: @multiuse1(
-; CHECK-NEXT: [[I21:%.*]] = shl i32 [[X:%.*]], 6
+; CHECK-NEXT: [[I:%.*]] = lshr i32 [[X:%.*]], 1
+; CHECK-NEXT: [[I3:%.*]] = and i32 [[I]], 1
+; CHECK-NEXT: [[I1:%.*]] = lshr i32 [[X]], 1
+; CHECK-NEXT: [[I5:%.*]] = and i32 [[I1]], 2
+; CHECK-NEXT: [[I21:%.*]] = shl i32 [[X]], 6
; CHECK-NEXT: [[I6:%.*]] = and i32 [[I21]], 384
-; CHECK-NEXT: [[I32:%.*]] = lshr i32 [[X]], 1
-; CHECK-NEXT: [[I7:%.*]] = and i32 [[I32]], 3
+; CHECK-NEXT: [[I7:%.*]] = or i32 [[I3]], [[I5]]
; CHECK-NEXT: [[I8:%.*]] = or i32 [[I7]], [[I6]]
; CHECK-NEXT: ret i32 [[I8]]
;
@@ -77,13 +80,15 @@
; CHECK-LABEL: @multiuse2(
; CHECK-NEXT: [[I:%.*]] = shl i32 [[X:%.*]], 1
; CHECK-NEXT: [[I2:%.*]] = and i32 [[I]], 12
-; CHECK-NEXT: [[I6:%.*]] = shl i32 [[X]], 8
-; CHECK-NEXT: [[I7:%.*]] = and i32 [[I6]], 24576
+; CHECK-NEXT: [[I3:%.*]] = shl i32 [[X]], 1
+; CHECK-NEXT: [[I5:%.*]] = and i32 [[I3]], 48
+; CHECK-NEXT: [[I6:%.*]] = and i32 [[X]], 96
+; CHECK-NEXT: [[I7:%.*]] = shl nuw nsw i32 [[I6]], 8
+; CHECK-NEXT: [[I8:%.*]] = shl nuw nsw i32 [[I6]], 1
; CHECK-NEXT: [[I14:%.*]] = shl i32 [[X]], 8
; CHECK-NEXT: [[I9:%.*]] = and i32 [[I14]], 7680
; CHECK-NEXT: [[I10:%.*]] = or i32 [[I7]], [[I9]]
-; CHECK-NEXT: [[I85:%.*]] = shl i32 [[X]], 1
-; CHECK-NEXT: [[I11:%.*]] = and i32 [[I85]], 240
+; CHECK-NEXT: [[I11:%.*]] = or i32 [[I8]], [[I5]]
; CHECK-NEXT: [[I12:%.*]] = or i32 [[I2]], [[I11]]
; CHECK-NEXT: [[I13:%.*]] = or i32 [[I10]], [[I12]]
; CHECK-NEXT: ret i32 [[I13]]
Index: llvm/test/Other/print-debug-counter.ll
===================================================================
--- llvm/test/Other/print-debug-counter.ll
+++ llvm/test/Other/print-debug-counter.ll
@@ -8,7 +8,7 @@
; CHECK: early-cse
; CHECK-SAME: {4,1,1}
; CHECK: instcombine-visit
-; CHECK-SAME: {12,0,-1}
+; CHECK-SAME: {13,0,-1}
; CHECK: newgvn-vn
; CHECK-SAME: {9,1,2}
define i32 @f1(i32 %a, i32 %b) {
Index: llvm/lib/Transforms/InstCombine/InstCombineInternal.h
===================================================================
--- llvm/lib/Transforms/InstCombine/InstCombineInternal.h
+++ llvm/lib/Transforms/InstCombine/InstCombineInternal.h
@@ -411,12 +411,11 @@
// Make sure that we reprocess all operands now that we reduced their
// use counts.
- for (Use &Operand : I.operands())
- if (auto *Inst = dyn_cast<Instruction>(Operand))
- Worklist.add(Inst);
-
+ SmallVector<Value *> Ops(I.operands());
Worklist.remove(&I);
I.eraseFromParent();
+ for (Value *Op : Ops)
+ Worklist.handleUseCountDecrement(Op);
MadeIRChange = true;
return nullptr; // Don't do anything with FI
}
Index: llvm/include/llvm/Transforms/Utils/InstructionWorklist.h
===================================================================
--- llvm/include/llvm/Transforms/Utils/InstructionWorklist.h
+++ llvm/include/llvm/Transforms/Utils/InstructionWorklist.h
@@ -108,6 +108,17 @@
push(cast<Instruction>(U));
}
+ /// Should be called *after* decrementing the use-count on V.
+ void handleUseCountDecrement(Value *V) {
+ if (auto *I = dyn_cast<Instruction>(V)) {
+ add(I);
+ // Many folds have one-use limitations. If there's only one use left,
+ // revisit that use.
+ if (I->hasOneUse())
+ add(cast<Instruction>(*I->user_begin()));
+ }
+ }
+
/// Check that the worklist is empty and nuke the backing store for the map.
void zap() {
assert(WorklistMap.empty() && "Worklist empty, but map not?");
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D151807.527040.patch
Type: text/x-patch
Size: 3911 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20230531/db25fd5d/attachment.bin>
More information about the llvm-commits
mailing list