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

Chris Lattner lattner at cs.uiuc.edu
Tue Feb 18 13:29:01 PST 2003


Changes in directory llvm/lib/Transforms/Scalar:

InstructionCombining.cpp updated: 1.67 -> 1.68

---
Log message:

Add a variety of new transformations:
  * A & ~A == 0
  * A / (2^c) == A >> c  if unsigned
  * 0 / A == 0
  * 1.0 * A == A
  * A * (2^c) == A << c
  * A ^ ~A == -1
  * A | ~A == -1
  * 0 % X = 0
  * A % (2^c) == A & (c-1) if unsigned
  * A - (A & B) == A & ~B
  * -1 - A == ~A



---
Diffs of the changes:

Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp
diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.67 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.68
--- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.67	Thu Dec  5 16:41:53 2002
+++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp	Tue Feb 18 13:28:33 2003
@@ -123,22 +123,27 @@
 // instruction if the LHS is a constant zero (which is the 'negate' form).
 //
 static inline Value *dyn_castNegInst(Value *V) {
-  Instruction *I = dyn_cast<Instruction>(V);
-  if (!I || I->getOpcode() != Instruction::Sub) return 0;
-
-  if (I->getOperand(0) == Constant::getNullValue(I->getType()))
-    return I->getOperand(1);
-  return 0;
+  return BinaryOperator::isNeg(V) ?
+    BinaryOperator::getNegArgument(cast<BinaryOperator>(V)) : 0;
 }
 
 static inline Value *dyn_castNotInst(Value *V) {
-  Instruction *I = dyn_cast<Instruction>(V);
-  if (!I || I->getOpcode() != Instruction::Xor) return 0;
+  return BinaryOperator::isNot(V) ?
+    BinaryOperator::getNotArgument(cast<BinaryOperator>(V)) : 0;
+}
 
-  if (ConstantIntegral *CI = dyn_cast<ConstantIntegral>(I->getOperand(1)))
-    if (CI->isAllOnesValue())
-      return I->getOperand(0);
-  return 0;
+
+// Log2 - Calculate the log base 2 for the specified value if it is exactly a
+// power of 2.
+static unsigned Log2(uint64_t Val) {
+  assert(Val > 1 && "Values 0 and 1 should be handled elsewhere!");
+  unsigned Count = 0;
+  while (Val != 1) {
+    if (Val & 1) return 0;    // Multiple bits set?
+    Val >>= 1;
+    ++Count;
+  }
+  return Count;
 }
 
 Instruction *InstCombiner::visitAdd(BinaryOperator &I) {
@@ -197,56 +202,119 @@
   if (Value *V = dyn_castNegInst(Op1))
     return BinaryOperator::create(Instruction::Add, Op0, V);
 
-  // Replace (x - (y - z)) with (x + (z - y)) if the (y - z) subexpression is
-  // not used by anyone else...
-  //
+  // Replace (-1 - A) with (~A)...
+  if (ConstantInt *C = dyn_cast<ConstantInt>(Op0))
+    if (C->isAllOnesValue())
+      return BinaryOperator::createNot(Op1);
+
   if (BinaryOperator *Op1I = dyn_cast<BinaryOperator>(Op1))
-    if (Op1I->use_size() == 1 && Op1I->getOpcode() == Instruction::Sub) {
-      // Swap the two operands of the subexpr...
-      Value *IIOp0 = Op1I->getOperand(0), *IIOp1 = Op1I->getOperand(1);
-      Op1I->setOperand(0, IIOp1);
-      Op1I->setOperand(1, IIOp0);
+    if (Op1I->use_size() == 1) {
+      // Replace (x - (y - z)) with (x + (z - y)) if the (y - z) subexpression
+      // is not used by anyone else...
+      //
+      if (Op1I->getOpcode() == Instruction::Sub) {
+        // Swap the two operands of the subexpr...
+        Value *IIOp0 = Op1I->getOperand(0), *IIOp1 = Op1I->getOperand(1);
+        Op1I->setOperand(0, IIOp1);
+        Op1I->setOperand(1, IIOp0);
+        
+        // Create the new top level add instruction...
+        return BinaryOperator::create(Instruction::Add, Op0, Op1);
+      }
+
+      // Replace (A - (A & B)) with (A & ~B) if this is the only use of (A&B)...
+      //
+      if (Op1I->getOpcode() == Instruction::And &&
+          (Op1I->getOperand(0) == Op0 || Op1I->getOperand(1) == Op0)) {
+        Value *OtherOp = Op1I->getOperand(Op1I->getOperand(0) == Op0);
 
-      // Create the new top level add instruction...
-      return BinaryOperator::create(Instruction::Add, Op0, Op1);
+        Instruction *NewNot = BinaryOperator::createNot(OtherOp, "B.not", &I);
+        return BinaryOperator::create(Instruction::And, Op0, NewNot);
+      }
     }
+
   return 0;
 }
 
 Instruction *InstCombiner::visitMul(BinaryOperator &I) {
   bool Changed = SimplifyBinOp(I);
-  Value *Op1 = I.getOperand(0);
+  Value *Op0 = I.getOperand(0);
 
   // Simplify mul instructions with a constant RHS...
-  if (Constant *Op2 = dyn_cast<Constant>(I.getOperand(1))) {
-    if (I.getType()->isInteger() && cast<ConstantInt>(Op2)->equalsInt(1))
-      return ReplaceInstUsesWith(I, Op1);  // Eliminate 'mul int %X, 1'
-
-    if (I.getType()->isInteger() && cast<ConstantInt>(Op2)->equalsInt(2))
-      // Convert 'mul int %X, 2' to 'add int %X, %X'
-      return BinaryOperator::create(Instruction::Add, Op1, Op1, I.getName());
+  if (Constant *Op1 = dyn_cast<Constant>(I.getOperand(1))) {
+    if (ConstantInt *CI = dyn_cast<ConstantInt>(Op1)) {
+      const Type *Ty = CI->getType();
+      uint64_t Val = Ty->isSigned() ?
+                          (uint64_t)cast<ConstantSInt>(CI)->getValue() : 
+                                    cast<ConstantUInt>(CI)->getValue();
+      switch (Val) {
+      case 0:
+        return ReplaceInstUsesWith(I, Op1);  // Eliminate 'mul double %X, 0'
+      case 1:
+        return ReplaceInstUsesWith(I, Op0);  // Eliminate 'mul int %X, 1'
+      case 2:                     // Convert 'mul int %X, 2' to 'add int %X, %X'
+        return BinaryOperator::create(Instruction::Add, Op0, Op0, I.getName());
+      }
 
-    if (Op2->isNullValue())
-      return ReplaceInstUsesWith(I, Op2);  // Eliminate 'mul int %X, 0'
+      if (uint64_t C = Log2(Val))            // Replace X*(2^C) with X << C
+        return new ShiftInst(Instruction::Shl, Op0,
+                             ConstantUInt::get(Type::UByteTy, C));
+    } else {
+      ConstantFP *Op1F = cast<ConstantFP>(Op1);
+      if (Op1F->isNullValue())
+        return ReplaceInstUsesWith(I, Op1);
+
+      // "In IEEE floating point, x*1 is not equivalent to x for nans.  However,
+      // ANSI says we can drop signals, so we can do this anyway." (from GCC)
+      if (Op1F->getValue() == 1.0)
+        return ReplaceInstUsesWith(I, Op0);  // Eliminate 'mul double %X, 1.0'
+    }
   }
 
   return Changed ? &I : 0;
 }
 
-
 Instruction *InstCombiner::visitDiv(BinaryOperator &I) {
   // div X, 1 == X
-  if (ConstantInt *RHS = dyn_cast<ConstantInt>(I.getOperand(1)))
+  if (ConstantInt *RHS = dyn_cast<ConstantInt>(I.getOperand(1))) {
     if (RHS->equalsInt(1))
       return ReplaceInstUsesWith(I, I.getOperand(0));
+
+    // Check to see if this is an unsigned division with an exact power of 2,
+    // if so, convert to a right shift.
+    if (ConstantUInt *C = dyn_cast<ConstantUInt>(RHS))
+      if (uint64_t Val = C->getValue())    // Don't break X / 0
+        if (uint64_t C = Log2(Val))
+          return new ShiftInst(Instruction::Shr, I.getOperand(0),
+                               ConstantUInt::get(Type::UByteTy, C));
+  }
+
+  // 0 / X == 0, we don't need to preserve faults!
+  if (ConstantInt *LHS = dyn_cast<ConstantInt>(I.getOperand(0)))
+    if (LHS->equalsInt(0))
+      return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
+
   return 0;
 }
 
 
 Instruction *InstCombiner::visitRem(BinaryOperator &I) {
-  // rem X, 1 == 0
-  if (ConstantInt *RHS = dyn_cast<ConstantInt>(I.getOperand(1)))
-    if (RHS->equalsInt(1))
+  if (ConstantInt *RHS = dyn_cast<ConstantInt>(I.getOperand(1))) {
+    if (RHS->equalsInt(1))  // X % 1 == 0
+      return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
+
+    // Check to see if this is an unsigned remainder with an exact power of 2,
+    // if so, convert to a bitwise and.
+    if (ConstantUInt *C = dyn_cast<ConstantUInt>(RHS))
+      if (uint64_t Val = C->getValue())    // Don't break X % 0 (divide by zero)
+        if (Log2(Val))
+          return BinaryOperator::create(Instruction::And, I.getOperand(0),
+                                        ConstantUInt::get(I.getType(), Val-1));
+  }
+
+  // 0 % X == 0, we don't need to preserve faults!
+  if (ConstantInt *LHS = dyn_cast<ConstantInt>(I.getOperand(0)))
+    if (LHS->equalsInt(0))
       return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
 
   return 0;
@@ -299,15 +367,19 @@
     if (RHS->isAllOnesValue())
       return ReplaceInstUsesWith(I, Op0);
 
-  // and (not A), (not B) == not (or A, B)
-  if (Op0->use_size() == 1 && Op1->use_size() == 1)
-    if (Value *A = dyn_castNotInst(Op0))
-      if (Value *B = dyn_castNotInst(Op1)) {
-        Instruction *Or = BinaryOperator::create(Instruction::Or, A, B,
-                                                 I.getName()+".demorgan");
-        InsertNewInstBefore(Or, I);
-        return BinaryOperator::createNot(Or, I.getName());
-      }
+  Value *Op0NotVal = dyn_castNotInst(Op0);
+  Value *Op1NotVal = dyn_castNotInst(Op1);
+
+  // (~A & ~B) == (~(A | B)) - Demorgan's Law
+  if (Op0->use_size() == 1 && Op1->use_size() == 1 && Op0NotVal && Op1NotVal) {
+    Instruction *Or = BinaryOperator::create(Instruction::Or, Op0NotVal,
+                                             Op1NotVal,I.getName()+".demorgan",
+                                             &I);
+    return BinaryOperator::createNot(Or);
+  }
+
+  if (Op0NotVal == Op1 || Op1NotVal == Op0)  // A & ~A  == ~A & A == 0
+    return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
 
   return Changed ? &I : 0;
 }
@@ -327,6 +399,16 @@
     if (RHS->isAllOnesValue())
       return ReplaceInstUsesWith(I, Op1);
 
+  if (Value *X = dyn_castNotInst(Op0))   // ~A | A == -1
+    if (X == Op1)
+      return ReplaceInstUsesWith(I, 
+                            ConstantIntegral::getAllOnesValue(I.getType()));
+
+  if (Value *X = dyn_castNotInst(Op1))   // A | ~A == -1
+    if (X == Op0)
+      return ReplaceInstUsesWith(I, 
+                            ConstantIntegral::getAllOnesValue(I.getType()));
+
   return Changed ? &I : 0;
 }
 
@@ -359,6 +441,16 @@
     }
   }
 
+  if (Value *X = dyn_castNotInst(Op0))   // ~A ^ A == -1
+    if (X == Op1)
+      return ReplaceInstUsesWith(I,
+                                ConstantIntegral::getAllOnesValue(I.getType()));
+
+  if (Value *X = dyn_castNotInst(Op1))   // A ^ ~A == -1
+    if (X == Op0)
+      return ReplaceInstUsesWith(I,
+                                ConstantIntegral::getAllOnesValue(I.getType()));
+
   return Changed ? &I : 0;
 }
 
@@ -501,7 +593,7 @@
     // Check to see if we are shifting left by 1.  If so, turn it into an add
     // instruction.
     if (I.getOpcode() == Instruction::Shl && CUI->equalsInt(1))
-      // Convert 'shl int %X, 2' to 'add int %X, %X'
+      // Convert 'shl int %X, 1' to 'add int %X, %X'
       return BinaryOperator::create(Instruction::Add, Op0, Op0, I.getName());
 
   }





More information about the llvm-commits mailing list