[llvm-commits] CVS: llvm/lib/Transforms/Scalar/InstructionCombining.cpp

Chris Lattner lattner at cs.uiuc.edu
Sun Nov 14 11:13:35 PST 2004



Changes in directory llvm/lib/Transforms/Scalar:

InstructionCombining.cpp updated: 1.282 -> 1.283
---
Log message:

Implement instcombine/phi.ll:test6 - pulling operations through PHI nodes.

This exposes subsequent optimization possiblities and reduces code size.
This triggers 1423 times in spec.


---
Diffs of the changes:  (+85 -6)

Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp
diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.282 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.283
--- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.282	Sun Nov 14 01:33:16 2004
+++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp	Sun Nov 14 13:13:23 2004
@@ -29,7 +29,7 @@
 //    5. add X, X is represented as (X*2) => (X << 1)
 //    6. Multiplies with a power-of-two constant argument are transformed into
 //       shifts.
-//    N. This list is incomplete
+//   ... etc.
 //
 //===----------------------------------------------------------------------===//
 
@@ -205,6 +205,11 @@
     // (which is only possible if all operands to the PHI are constants).
     Instruction *FoldOpIntoPhi(Instruction &I);
 
+    // FoldPHIArgOpIntoPHI - If all operands to a PHI node are the same "unary"
+    // operator and they all are only used by the PHI, PHI together their
+    // inputs, and do the operation once, to the result of the PHI.
+    Instruction *FoldPHIArgOpIntoPHI(PHINode &PN);
+
     Instruction *OptAndOp(Instruction *Op, ConstantIntegral *OpRHS,
                           ConstantIntegral *AndRHS, BinaryOperator &TheAnd);
 
@@ -509,11 +514,13 @@
 /// is only possible if all operands to the PHI are constants).
 Instruction *InstCombiner::FoldOpIntoPhi(Instruction &I) {
   PHINode *PN = cast<PHINode>(I.getOperand(0));
-  if (!PN->hasOneUse()) return 0;
+  unsigned NumPHIValues = PN->getNumIncomingValues();
+  if (!PN->hasOneUse() || NumPHIValues == 0 ||
+      !isa<Constant>(PN->getIncomingValue(0))) return 0;
 
   // Check to see if all of the operands of the PHI are constants.  If not, we
   // cannot do the transformation.
-  for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i)
+  for (unsigned i = 1; i != NumPHIValues; ++i)
     if (!isa<Constant>(PN->getIncomingValue(i)))
       return 0;
 
@@ -526,7 +533,7 @@
   // Next, add all of the operands to the PHI.
   if (I.getNumOperands() == 2) {
     Constant *C = cast<Constant>(I.getOperand(1));
-    for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) {
+    for (unsigned i = 0; i != NumPHIValues; ++i) {
       Constant *InV = cast<Constant>(PN->getIncomingValue(i));
       NewPN->addIncoming(ConstantExpr::get(I.getOpcode(), InV, C),
                          PN->getIncomingBlock(i));
@@ -534,7 +541,7 @@
   } else {
     assert(isa<CastInst>(I) && "Unary op should be a cast!");
     const Type *RetTy = I.getType();
-    for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) {
+    for (unsigned i = 0; i != NumPHIValues; ++i) {
       Constant *InV = cast<Constant>(PN->getIncomingValue(i));
       NewPN->addIncoming(ConstantExpr::getCast(InV, RetTy),
                          PN->getIncomingBlock(i));
@@ -3408,6 +3415,63 @@
 }
 
 
+// FoldPHIArgOpIntoPHI - If all operands to a PHI node are the same "unary"
+// operator and they all are only used by the PHI, PHI together their
+// inputs, and do the operation once, to the result of the PHI.
+Instruction *InstCombiner::FoldPHIArgOpIntoPHI(PHINode &PN) {
+  Instruction *FirstInst = cast<Instruction>(PN.getIncomingValue(0));
+
+  // Scan the instruction, looking for input operations that can be folded away.
+  // If all input operands to the phi are the same instruction (e.g. a cast from
+  // the same type or "+42") we can pull the operation through the PHI, reducing
+  // code size and simplifying code.
+  Constant *ConstantOp = 0;
+  const Type *CastSrcTy = 0;
+  if (isa<CastInst>(FirstInst)) {
+    CastSrcTy = FirstInst->getOperand(0)->getType();
+  } else if (isa<BinaryOperator>(FirstInst) || isa<ShiftInst>(FirstInst)) {
+    // Can fold binop or shift if the RHS is a constant.
+    ConstantOp = dyn_cast<Constant>(FirstInst->getOperand(1));
+    if (ConstantOp == 0) return 0;
+  } else {
+    return 0;  // Cannot fold this operation.
+  }
+
+  // Check to see if all arguments are the same operation.
+  for (unsigned i = 1, e = PN.getNumIncomingValues(); i != e; ++i) {
+    if (!isa<Instruction>(PN.getIncomingValue(i))) return 0;
+    Instruction *I = cast<Instruction>(PN.getIncomingValue(i));
+    if (!I->hasOneUse() || I->getOpcode() != FirstInst->getOpcode())
+      return 0;
+    if (CastSrcTy) {
+      if (I->getOperand(0)->getType() != CastSrcTy)
+        return 0;  // Cast operation must match.
+    } else if (I->getOperand(1) != ConstantOp) {
+      return 0;
+    }
+  }
+
+  // Okay, they are all the same operation.  Create a new PHI node of the
+  // correct type, and PHI together all of the LHS's of the instructions.
+  PHINode *NewPN = new PHINode(FirstInst->getOperand(0)->getType(),
+                               PN.getName()+".in");
+  NewPN->op_reserve(PN.getNumOperands());
+  InsertNewInstBefore(NewPN, PN);
+
+  // Add all operands to the new PHI.
+  for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i)
+    NewPN->addIncoming(cast<Instruction>(PN.getIncomingValue(i))->getOperand(0),
+                       PN.getIncomingBlock(i));
+  
+  // Insert and return the new operation.
+  if (isa<CastInst>(FirstInst))
+    return new CastInst(NewPN, PN.getType());
+  else if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(FirstInst))
+    return BinaryOperator::create(BinOp->getOpcode(), NewPN, ConstantOp);
+  else
+    return new ShiftInst(cast<ShiftInst>(FirstInst)->getOpcode(),
+                         NewPN, ConstantOp);
+}
 
 // PHINode simplification
 //
@@ -3459,6 +3523,15 @@
           return &PN;                // PN is now dead!
         }
       }
+
+  // If all PHI operands are the same operation, pull them through the PHI,
+  // reducing code size.
+  if (isa<Instruction>(PN.getIncomingValue(0)) &&
+      PN.getIncomingValue(0)->hasOneUse())
+    if (Instruction *Result = FoldPHIArgOpIntoPHI(PN))
+      return Result;
+
+  
   return 0;
 }
 
@@ -4111,7 +4184,13 @@
 
         // Insert the new instruction into the basic block...
         BasicBlock *InstParent = I->getParent();
-        InstParent->getInstList().insert(I, Result);
+        BasicBlock::iterator InsertPos = I;
+
+        if (!isa<PHINode>(Result))        // If combining a PHI, don't insert
+          while (isa<PHINode>(InsertPos)) // middle of a block of PHIs.
+            ++InsertPos;
+
+        InstParent->getInstList().insert(InsertPos, Result);
 
         // Make sure that we reprocess all operands now that we reduced their
         // use counts.






More information about the llvm-commits mailing list