[PATCH] D145223: [InstCombine] Combine binary operator of two phi node

luxufan via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Fri Mar 3 00:57:50 PST 2023


StephenFan created this revision.
StephenFan added reviewers: nikic, spatel.
Herald added a subscriber: hiraditya.
Herald added a project: All.
StephenFan requested review of this revision.
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

Combine binary operator of two phi node if there is at least one
specific constant value in phi0 and phi1's incoming values for each
same incoming block and this specific constant value can be used
to do optimization for specific binary operator.
For example:

  %phi0 = phi i32 [0, %bb0], [%i, %bb1]
  %phi1 = phi i32 [%j, %bb0], [0, %bb1]
  %add = add i32 %phi0, %phi1
  ==>
  %add = phi i32 [%j, %bb0], [%i, %bb1]

Fixes: https://github.com/llvm/llvm-project/issues/61137


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D145223

Files:
  llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
  llvm/test/Transforms/InstCombine/add.ll


Index: llvm/test/Transforms/InstCombine/add.ll
===================================================================
--- llvm/test/Transforms/InstCombine/add.ll
+++ llvm/test/Transforms/InstCombine/add.ll
@@ -2952,9 +2952,7 @@
 ; CHECK:       if.then:
 ; CHECK-NEXT:    br label [[IF_END]]
 ; CHECK:       if.end:
-; CHECK-NEXT:    [[X:%.*]] = phi i32 [ 0, [[IF_THEN]] ], [ [[J:%.*]], [[ENTRY:%.*]] ]
-; CHECK-NEXT:    [[Y:%.*]] = phi i32 [ [[I:%.*]], [[IF_THEN]] ], [ 0, [[ENTRY]] ]
-; CHECK-NEXT:    [[ADD:%.*]] = add i32 [[Y]], [[X]]
+; CHECK-NEXT:    [[ADD:%.*]] = phi i32 [ [[I:%.*]], [[IF_THEN]] ], [ [[J:%.*]], [[ENTRY:%.*]] ]
 ; CHECK-NEXT:    ret i32 [[ADD]]
 ;
 entry:
Index: llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
===================================================================
--- llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -1294,7 +1294,7 @@
   auto *Phi0 = dyn_cast<PHINode>(BO.getOperand(0));
   auto *Phi1 = dyn_cast<PHINode>(BO.getOperand(1));
   if (!Phi0 || !Phi1 || !Phi0->hasOneUse() || !Phi1->hasOneUse() ||
-      Phi0->getNumOperands() != 2 || Phi1->getNumOperands() != 2)
+      Phi0->getNumOperands() != Phi1->getNumOperands())
     return nullptr;
 
   // TODO: Remove the restriction for binop being in the same block as the phis.
@@ -1302,6 +1302,47 @@
       BO.getParent() != Phi1->getParent())
     return nullptr;
 
+  // Fold if there is at least one specific constant values in phi0 or phi1's
+  // incoming value that comes from the same block and this specific constant
+  // value can be used to do optimization for specific binary operator.
+  // For example:
+  // %phi0 = phi i32 [0, %bb0], [%i, %bb1]
+  // %phi1 = phi i32 [%j, %bb0], [0, %bb1]
+  // %add = add i32 %phi0, %phi1
+  // ==>
+  // %add = phi i32 [%j, %bb0], [%i, %bb1]
+  // TODO: Support other binary operators
+  if (BO.getOpcode() == Instruction::Add) {
+    llvm::SmallVector<Value *, 4> NewIncomingValues;
+    if (all_of(llvm::zip(Phi0->operands(), Phi1->operands()),
+               [&](std::tuple<llvm::Use &, llvm::Use &> T) {
+                 auto &Phi0Use = std::get<0>(T);
+                 auto &Phi1Use = std::get<1>(T);
+                 if (Phi0->getIncomingBlock(Phi0Use) !=
+                     Phi1->getIncomingBlock(Phi1Use))
+                   return false;
+                 if (match(Phi0Use.get(), m_Zero()))
+                   NewIncomingValues.push_back(Phi1Use.get());
+                 else if (match(Phi1Use.get(), m_Zero()))
+                   NewIncomingValues.push_back(Phi0Use.get());
+                 else
+                   return false;
+                 return true;
+               })) {
+      PHINode *NewPhi =
+          PHINode::Create(Phi0->getType(), Phi0->getNumOperands());
+      assert(NewIncomingValues.size() == Phi0->getNumOperands() &&
+             "The number of collected incoming values should equal the number "
+             "of the original PHINode operands!");
+      for (unsigned I = 0; I < Phi0->getNumOperands(); I++)
+        NewPhi->addIncoming(NewIncomingValues[I], Phi0->getIncomingBlock(I));
+      return NewPhi;
+    }
+  }
+
+  if (Phi0->getNumOperands() != 2 || Phi1->getNumOperands() != 2)
+    return nullptr;
+
   // Match a pair of incoming constants for one of the predecessor blocks.
   BasicBlock *ConstBB, *OtherBB;
   Constant *C0, *C1;


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D145223.502074.patch
Type: text/x-patch
Size: 3430 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20230303/bdb3c5cf/attachment.bin>


More information about the llvm-commits mailing list