[PATCH] D33074: InstCombine: Allow sinking instructions with more uses in the same block.

Kyle Butt via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Wed May 10 14:56:54 PDT 2017


iteratee created this revision.

Currently InstCombine will sink instructions that may be trivially sunk if they
have a single use. This patch relaxes this requirement to 4 or fewer uses, and
requires that they all be in the same basic block. The motivating case was an
instruction that was used by 2 extractvalue instructions, both in the same
block.


Repository:
  rL LLVM

https://reviews.llvm.org/D33074

Files:
  lib/Transforms/InstCombine/InstructionCombining.cpp


Index: lib/Transforms/InstCombine/InstructionCombining.cpp
===================================================================
--- lib/Transforms/InstCombine/InstructionCombining.cpp
+++ lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -2789,7 +2789,25 @@
 /// instruction past all of the instructions between it and the end of its
 /// block.
 static bool TryToSinkInstruction(Instruction *I, BasicBlock *DestBlock) {
-  assert(I->hasOneUse() && "Invariants didn't hold!");
+  // verify that all uses are in the same block.
+  DEBUG(
+      BasicBlock *UsersParent = nullptr;
+      int UseCount = 0;
+      for (const Use &U : I->uses()) {
+        if (++UseCount > 4)
+          llvm_unreachable("Instruction has too many uses to be sunk.");
+        Instruction *UserInst = cast<Instruction>(U.getUser());
+        BasicBlock *CurrentUserParent;
+        // Get the block the use occurs in.
+        if (PHINode *PN = dyn_cast<PHINode>(UserInst))
+          CurrentUserParent = PN->getIncomingBlock(U);
+        else
+          CurrentUserParent = UserInst->getParent();
+        if (UsersParent == nullptr)
+          UsersParent = CurrentUserParent;
+        else if (CurrentUserParent != UsersParent)
+          llvm_unreachable("Instruction has uses in different blocks.");
+      });
 
   // Cannot move control-flow-involving, volatile loads, vaarg, etc.
   if (isa<PHINode>(I) || I->isEHPad() || I->mayHaveSideEffects() ||
@@ -2879,32 +2897,51 @@
     }
 
     // See if we can trivially sink this instruction to a successor basic block.
-    if (I->hasOneUse()) {
-      BasicBlock *BB = I->getParent();
-      Instruction *UserInst = cast<Instruction>(*I->user_begin());
-      BasicBlock *UserParent;
-
+    // First see if we have a small number of uses, all in the same block.
+    bool UsesInOneBlock = false;
+    BasicBlock *UsersParent = nullptr;
+    int MaxUseCount = 4;
+
+    for (const Use &U : I->uses()) {
+      if (MaxUseCount <= 0) {
+        UsesInOneBlock = false;
+        break;
+      }
+      Instruction *UserInst = cast<Instruction>(U.getUser());
+      BasicBlock *CurrentUserParent;
       // Get the block the use occurs in.
       if (PHINode *PN = dyn_cast<PHINode>(UserInst))
-        UserParent = PN->getIncomingBlock(*I->use_begin());
+        CurrentUserParent = PN->getIncomingBlock(U);
       else
-        UserParent = UserInst->getParent();
+        CurrentUserParent = UserInst->getParent();
+      if (UsersParent == nullptr) {
+        UsersParent = CurrentUserParent;
+        UsesInOneBlock = true;
+      } else if (CurrentUserParent != UsersParent) {
+        UsesInOneBlock = false;
+        break;
+      }
+      --MaxUseCount;
+    }
+
+    if (UsesInOneBlock) {
+      BasicBlock *BB = I->getParent();
 
-      if (UserParent != BB) {
+      if (UsersParent != BB) {
         bool UserIsSuccessor = false;
         // See if the user is one of our successors.
         for (succ_iterator SI = succ_begin(BB), E = succ_end(BB); SI != E; ++SI)
-          if (*SI == UserParent) {
+          if (*SI == UsersParent) {
             UserIsSuccessor = true;
             break;
           }
 
         // If the user is one of our immediate successors, and if that successor
         // only has us as a predecessors (we'd have to split the critical edge
         // otherwise), we can keep going.
-        if (UserIsSuccessor && UserParent->getUniquePredecessor()) {
+        if (UserIsSuccessor && UsersParent->getUniquePredecessor()) {
           // Okay, the CFG is simple enough, try to sink this instruction.
-          if (TryToSinkInstruction(I, UserParent)) {
+          if (TryToSinkInstruction(I, UsersParent)) {
             DEBUG(dbgs() << "IC: Sink: " << *I << '\n');
             MadeIRChange = true;
             // We'll add uses of the sunk instruction below, but since sinking


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D33074.98537.patch
Type: text/x-patch
Size: 3859 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20170510/312056a8/attachment.bin>


More information about the llvm-commits mailing list