[llvm] f7a977c - [InstCombine] Revisit user of newly one-use instructions

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Wed Jun 14 00:12:38 PDT 2023


Author: Nikita Popov
Date: 2023-06-14T09:12:30+02:00
New Revision: f7a977c7b3b4d8efebb92ed803585168df369831

URL: https://github.com/llvm/llvm-project/commit/f7a977c7b3b4d8efebb92ed803585168df369831
DIFF: https://github.com/llvm/llvm-project/commit/f7a977c7b3b4d8efebb92ed803585168df369831.diff

LOG: [InstCombine] Revisit user of newly one-use instructions

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, 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.

The regressed tests in or-shifted-masks.ll now require a sequence of
instcombine,early-cse,instcombine to fold fully. D152876 would make
these fold in a single instcombine run again.

Differential Revision: https://reviews.llvm.org/D151807

Added: 
    

Modified: 
    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

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/Transforms/Utils/InstructionWorklist.h b/llvm/include/llvm/Transforms/Utils/InstructionWorklist.h
index a318c2cd28bbd..c8f20636965e8 100644
--- a/llvm/include/llvm/Transforms/Utils/InstructionWorklist.h
+++ b/llvm/include/llvm/Transforms/Utils/InstructionWorklist.h
@@ -108,6 +108,17 @@ class InstructionWorklist {
       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?");

diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
index 1a9519f387977..88fbca2b13392 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
+++ b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
@@ -411,12 +411,11 @@ class LLVM_LIBRARY_VISIBILITY InstCombinerImpl final
 
     // 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
   }

diff  --git a/llvm/test/Other/print-debug-counter.ll b/llvm/test/Other/print-debug-counter.ll
index ac9882fe19c57..4b6e42570b315 100644
--- a/llvm/test/Other/print-debug-counter.ll
+++ b/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) {

diff  --git a/llvm/test/Transforms/InstCombine/or-shifted-masks.ll b/llvm/test/Transforms/InstCombine/or-shifted-masks.ll
index 5aa9112a5212a..e7a209a3f6c39 100644
--- a/llvm/test/Transforms/InstCombine/or-shifted-masks.ll
+++ b/llvm/test/Transforms/InstCombine/or-shifted-masks.ll
@@ -54,10 +54,13 @@ define i32 @or_and_shift_shift_and(i32 %x) {
 
 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]]
 ;
@@ -75,10 +78,16 @@ define i32 @multiuse1(i32 %x) {
 
 define i32 @multiuse2(i32 %x) {
 ; CHECK-LABEL: @multiuse2(
-; CHECK-NEXT:    [[TMP1:%.*]] = shl i32 [[X:%.*]], 8
+; CHECK-NEXT:    [[I:%.*]] = shl i32 [[X:%.*]], 1
+; CHECK-NEXT:    [[I2:%.*]] = and i32 [[I]], 12
+; CHECK-NEXT:    [[I3:%.*]] = shl i32 [[X]], 1
+; CHECK-NEXT:    [[I5:%.*]] = and i32 [[I3]], 48
+; CHECK-NEXT:    [[I6:%.*]] = shl i32 [[X]], 1
+; CHECK-NEXT:    [[I8:%.*]] = and i32 [[I6]], 192
+; CHECK-NEXT:    [[TMP1:%.*]] = shl i32 [[X]], 8
 ; CHECK-NEXT:    [[I10:%.*]] = and i32 [[TMP1]], 32256
-; CHECK-NEXT:    [[TMP2:%.*]] = shl i32 [[X]], 1
-; CHECK-NEXT:    [[I12:%.*]] = and i32 [[TMP2]], 252
+; 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]]
 ;
@@ -101,10 +110,13 @@ define i32 @multiuse2(i32 %x) {
 
 define i32 @multiuse3(i32 %x) {
 ; CHECK-LABEL: @multiuse3(
-; CHECK-NEXT:    [[TMP1:%.*]] = shl i32 [[X:%.*]], 6
+; CHECK-NEXT:    [[I:%.*]] = lshr i32 [[X:%.*]], 1
+; CHECK-NEXT:    [[I2:%.*]] = and i32 [[I]], 48
+; CHECK-NEXT:    [[TMP1:%.*]] = shl i32 [[X]], 6
 ; CHECK-NEXT:    [[I5:%.*]] = and i32 [[TMP1]], 8064
-; CHECK-NEXT:    [[TMP2:%.*]] = lshr i32 [[X]], 1
-; CHECK-NEXT:    [[I8:%.*]] = and i32 [[TMP2]], 63
+; CHECK-NEXT:    [[I6:%.*]] = lshr i32 [[X]], 1
+; CHECK-NEXT:    [[I7:%.*]] = and i32 [[I6]], 15
+; CHECK-NEXT:    [[I8:%.*]] = or i32 [[I2]], [[I7]]
 ; CHECK-NEXT:    [[I9:%.*]] = or i32 [[I8]], [[I5]]
 ; CHECK-NEXT:    ret i32 [[I9]]
 ;


        


More information about the llvm-commits mailing list