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

Chris Lattner lattner at cs.uiuc.edu
Fri Apr 9 14:06:04 PDT 2004


Changes in directory llvm/lib/Transforms/Scalar:

InstructionCombining.cpp updated: 1.183 -> 1.184

---
Log message:

Fold binary operators with a constant operand into select instructions
that have a constant operand.  This implements
add.ll:test19, shift.ll:test15*, and others that are not tested


---
Diffs of the changes:  (+94 -15)

Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp
diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.183 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.184
--- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.183	Fri Apr  9 13:19:44 2004
+++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp	Fri Apr  9 14:05:30 2004
@@ -489,7 +489,50 @@
   }
 };
 
+static Value *FoldOperationIntoSelectOperand(Instruction &BI, Value *SO,
+                                             InstCombiner *IC) {
+  // Figure out if the constant is the left or the right argument.
+  bool ConstIsRHS = isa<Constant>(BI.getOperand(1));
+  Constant *ConstOperand = cast<Constant>(BI.getOperand(ConstIsRHS));
+
+  if (Constant *SOC = dyn_cast<Constant>(SO)) {
+    if (ConstIsRHS)
+      return ConstantExpr::get(BI.getOpcode(), SOC, ConstOperand);
+    return ConstantExpr::get(BI.getOpcode(), ConstOperand, SOC);
+  }
+
+  Value *Op0 = SO, *Op1 = ConstOperand;
+  if (!ConstIsRHS)
+    std::swap(Op0, Op1);
+  Instruction *New;
+  if (BinaryOperator *BO = dyn_cast<BinaryOperator>(&BI))
+    New = BinaryOperator::create(BO->getOpcode(), Op0, Op1);
+  else if (ShiftInst *SI = dyn_cast<ShiftInst>(&BI))
+    New = new ShiftInst(SI->getOpcode(), Op0, Op1);
+  else
+    assert(0 && "Unknown binary instruction type!");
+  return IC->InsertNewInstBefore(New, BI);
+}
+
+// FoldBinOpIntoSelect - Given an instruction with a select as one operand and a
+// constant as the other operand, try to fold the binary operator into the
+// select arguments.
+static Instruction *FoldBinOpIntoSelect(Instruction &BI, SelectInst *SI,
+                                        InstCombiner *IC) {
+  // Don't modify shared select instructions
+  if (!SI->hasOneUse()) return 0;
+  Value *TV = SI->getOperand(1);
+  Value *FV = SI->getOperand(2);
+
+  if (isa<Constant>(TV) || isa<Constant>(FV)) {
+    Value *SelectTrueVal = FoldOperationIntoSelectOperand(BI, TV, IC);
+    Value *SelectFalseVal = FoldOperationIntoSelectOperand(BI, FV, IC);
 
+    return new SelectInst(SI->getCondition(), SelectTrueVal,
+                          SelectFalseVal);
+  }
+  return 0;
+}
 
 Instruction *InstCombiner::visitAdd(BinaryOperator &I) {
   bool Changed = SimplifyCommutative(I);
@@ -547,6 +590,11 @@
                                     CRHS, ConstantInt::get(I.getType(), 1)),
                                           ILHS->getOperand(0));
         break;
+      case Instruction::Select:
+        // Try to fold constant add into select arguments.
+        if (Instruction *R = FoldBinOpIntoSelect(I,cast<SelectInst>(ILHS),this))
+          return R;
+
       default: break;
       }
     }
@@ -632,6 +680,11 @@
             }
           }
     }
+
+    // Try to fold constant sub into select arguments.
+    if (SelectInst *SI = dyn_cast<SelectInst>(Op1))
+      if (Instruction *R = FoldBinOpIntoSelect(I, SI, this))
+        return R;
   }
 
   if (BinaryOperator *Op1I = dyn_cast<BinaryOperator>(Op1))
@@ -740,6 +793,11 @@
       if (Op1F->getValue() == 1.0)
         return ReplaceInstUsesWith(I, Op0);  // Eliminate 'mul double %X, 1.0'
     }
+
+    // Try to fold constant mul into select arguments.
+    if (SelectInst *SI = dyn_cast<SelectInst>(Op0))
+      if (Instruction *R = FoldBinOpIntoSelect(I, SI, this))
+        return R;
   }
 
   if (Value *Op0v = dyn_castNegVal(Op0))     // -X * -Y = X*Y
@@ -1093,6 +1151,11 @@
         if (Instruction *Res = OptAndOp(Op0I, Op0CI, RHS, I))
           return Res;
     }
+
+    // Try to fold constant and into select arguments.
+    if (SelectInst *SI = dyn_cast<SelectInst>(Op0))
+      if (Instruction *R = FoldBinOpIntoSelect(I, SI, this))
+        return R;
   }
 
   Value *Op0NotVal = dyn_castNotVal(Op0);
@@ -1158,6 +1221,11 @@
                                               NotConstant(RHS)));
         }
     }
+
+    // Try to fold constant and into select arguments.
+    if (SelectInst *SI = dyn_cast<SelectInst>(Op0))
+      if (Instruction *R = FoldBinOpIntoSelect(I, SI, this))
+        return R;
   }
 
   // (A & C1)|(A & C2) == A & (C1|C2)
@@ -1268,6 +1336,11 @@
         default: break;
         }
     }
+
+    // Try to fold constant and into select arguments.
+    if (SelectInst *SI = dyn_cast<SelectInst>(Op0))
+      if (Instruction *R = FoldBinOpIntoSelect(I, SI, this))
+        return R;
   }
 
   if (Value *X = dyn_castNotVal(Op0))   // ~A ^ A == -1
@@ -1668,6 +1741,12 @@
       if (CSI->isAllOnesValue())
         return ReplaceInstUsesWith(I, CSI);
 
+  // Try to fold constant and into select arguments.
+  if (isa<Constant>(Op0))
+    if (SelectInst *SI = dyn_cast<SelectInst>(Op1))
+      if (Instruction *R = FoldBinOpIntoSelect(I, SI, this))
+        return R;
+
   if (ConstantUInt *CUI = dyn_cast<ConstantUInt>(Op1)) {
     // shl uint X, 32 = 0 and shr ubyte Y, 9 = 0, ... just don't eliminate shr
     // of a signed value.
@@ -1689,6 +1768,10 @@
           return BinaryOperator::create(Instruction::Mul, BO->getOperand(0),
                                 ConstantExpr::get(Instruction::Shl, BOOp, CUI));
     
+    // Try to fold constant and into select arguments.
+    if (SelectInst *SI = dyn_cast<SelectInst>(Op0))
+      if (Instruction *R = FoldBinOpIntoSelect(I, SI, this))
+        return R;
 
     // If the operand is an bitwise operator with a constant RHS, and the
     // shift is the only use, we can pull it out of the shift.
@@ -2052,22 +2135,18 @@
       }
     }
 
-  // Selecting between two constants?
-  if (Constant *TrueValC = dyn_cast<Constant>(TrueVal))
-    if (Constant *FalseValC = dyn_cast<Constant>(FalseVal)) {
-      if (SI.getType()->isInteger()) {
-        // select C, 1, 0 -> cast C to int
-        if (FalseValC->isNullValue() && isa<ConstantInt>(TrueValC) &&
-            cast<ConstantInt>(TrueValC)->getRawValue() == 1) {
-          return new CastInst(CondVal, SI.getType());
-        } else if (TrueValC->isNullValue() && isa<ConstantInt>(FalseValC) &&
-                   cast<ConstantInt>(FalseValC)->getRawValue() == 1) {
-          // select C, 0, 1 -> cast !C to int
-          Value *NotCond =
-            InsertNewInstBefore(BinaryOperator::createNot(CondVal,
+  // Selecting between two integer constants?
+  if (ConstantInt *TrueValC = dyn_cast<ConstantInt>(TrueVal))
+    if (ConstantInt *FalseValC = dyn_cast<ConstantInt>(FalseVal)) {
+      // select C, 1, 0 -> cast C to int
+      if (FalseValC->isNullValue() && TrueValC->getRawValue() == 1) {
+        return new CastInst(CondVal, SI.getType());
+      } else if (TrueValC->isNullValue() && FalseValC->getRawValue() == 1) {
+        // select C, 0, 1 -> cast !C to int
+        Value *NotCond =
+          InsertNewInstBefore(BinaryOperator::createNot(CondVal,
                                                "not."+CondVal->getName()), SI);
-          return new CastInst(NotCond, SI.getType());
-        }
+        return new CastInst(NotCond, SI.getType());
       }
     }
   





More information about the llvm-commits mailing list