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

Chris Lattner lattner at cs.uiuc.edu
Fri Sep 19 12:18:02 PDT 2003


Changes in directory llvm/lib/Transforms/Scalar:

InstructionCombining.cpp updated: 1.120 -> 1.121

---
Log message:

pull a large nested conditional out into its own function


---
Diffs of the changes:

Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp
diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.120 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.121
--- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.120	Fri Sep 19 10:35:42 2003
+++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp	Fri Sep 19 12:17:26 2003
@@ -135,6 +135,9 @@
     // SimplifyCommutative - This performs a few simplifications for commutative
     // operators...
     bool SimplifyCommutative(BinaryOperator &I);
+
+    Instruction *OptAndOp(Instruction *Op, ConstantIntegral *OpRHS,
+                          ConstantIntegral *AndRHS, BinaryOperator &TheAnd);
   };
 
   RegisterOpt<InstCombiner> X("instcombine", "Combine redundant instructions");
@@ -716,6 +719,89 @@
 };
 
 
+// OptAndOp - This handles expressions of the form ((val OP C1) & C2).  Where
+// the Op parameter is 'OP', OpRHS is 'C1', and AndRHS is 'C2'.  Op is
+// guaranteed to be either a shift instruction or a binary operator.
+Instruction *InstCombiner::OptAndOp(Instruction *Op,
+                                    ConstantIntegral *OpRHS,
+                                    ConstantIntegral *AndRHS,
+                                    BinaryOperator &TheAnd) {
+  Value *X = Op->getOperand(0);
+  switch (Op->getOpcode()) {
+  case Instruction::Xor:
+    if ((*AndRHS & *OpRHS)->isNullValue()) {
+      // (X ^ C1) & C2 --> (X & C2) iff (C1&C2) == 0
+      return BinaryOperator::create(Instruction::And, X, AndRHS);
+    } else if (Op->use_size() == 1) {
+      // (X ^ C1) & C2 --> (X & C2) ^ (C1&C2)
+      std::string OpName = Op->getName(); Op->setName("");
+      Instruction *And = BinaryOperator::create(Instruction::And,
+                                                X, AndRHS, OpName);
+      InsertNewInstBefore(And, TheAnd);
+      return BinaryOperator::create(Instruction::Xor, And, *AndRHS & *OpRHS);
+    }
+    break;
+  case Instruction::Or:
+    // (X | C1) & C2 --> X & C2 iff C1 & C1 == 0
+    if ((*AndRHS & *OpRHS)->isNullValue())
+      return BinaryOperator::create(Instruction::And, X, AndRHS);
+    else {
+      Constant *Together = *AndRHS & *OpRHS;
+      if (Together == AndRHS) // (X | C) & C --> C
+        return ReplaceInstUsesWith(TheAnd, AndRHS);
+      
+      if (Op->use_size() == 1 && Together != OpRHS) {
+        // (X | C1) & C2 --> (X | (C1&C2)) & C2
+        std::string Op0Name = Op->getName(); Op->setName("");
+        Instruction *Or = BinaryOperator::create(Instruction::Or, X,
+                                                 Together, Op0Name);
+        InsertNewInstBefore(Or, TheAnd);
+        return BinaryOperator::create(Instruction::And, Or, AndRHS);
+      }
+    }
+    break;
+  case Instruction::Add:
+    if (Op->use_size() == 1) {
+      // Adding a one to a single bit bit-field should be turned into an XOR
+      // of the bit.  First thing to check is to see if this AND is with a
+      // single bit constant.
+      unsigned long long AndRHSV = cast<ConstantInt>(AndRHS)->getRawValue();
+
+      // Clear bits that are not part of the constant.
+      AndRHSV &= (1ULL << AndRHS->getType()->getPrimitiveSize()*8)-1;
+
+      // If there is only one bit set...
+      if ((AndRHSV & (AndRHSV-1)) == 0) {
+        // Ok, at this point, we know that we are masking the result of the
+        // ADD down to exactly one bit.  If the constant we are adding has
+        // no bits set below this bit, then we can eliminate the ADD.
+        unsigned long long AddRHS = cast<ConstantInt>(OpRHS)->getRawValue();
+            
+        // Check to see if any bits below the one bit set in AndRHSV are set.
+        if ((AddRHS & (AndRHSV-1)) == 0) {
+          // If not, the only thing that can effect the output of the AND is
+          // the bit specified by AndRHSV.  If that bit is set, the effect of
+          // the XOR is to toggle the bit.  If it is clear, then the ADD has
+          // no effect.
+          if ((AddRHS & AndRHSV) == 0) { // Bit is not set, noop
+            TheAnd.setOperand(0, X);
+            return &TheAnd;
+          } else {
+            std::string Name = Op->getName(); Op->setName("");
+            // Pull the XOR out of the AND.
+            Instruction *NewAnd =
+              BinaryOperator::create(Instruction::And, X, AndRHS, Name);
+            InsertNewInstBefore(NewAnd, TheAnd);
+            return BinaryOperator::create(Instruction::Xor, NewAnd, AndRHS);
+          }
+        }
+      }
+    }
+    break;
+  }
+  return 0;
+}
+
 
 Instruction *InstCombiner::visitAnd(BinaryOperator &I) {
   bool Changed = SimplifyCommutative(I);
@@ -730,78 +816,13 @@
     if (RHS->isAllOnesValue())
       return ReplaceInstUsesWith(I, Op0);
 
-    if (BinaryOperator *Op0I = dyn_cast<BinaryOperator>(Op0)) {
+    // Optimize a variety of ((val OP C1) & C2) combinations...
+    if (isa<BinaryOperator>(Op0) || isa<ShiftInst>(Op0)) {
+      Instruction *Op0I = cast<Instruction>(Op0);
       Value *X = Op0I->getOperand(0);
       if (ConstantInt *Op0CI = dyn_cast<ConstantInt>(Op0I->getOperand(1)))
-        if (Op0I->getOpcode() == Instruction::Xor) {
-          if ((*RHS & *Op0CI)->isNullValue()) {
-            // (X ^ C1) & C2 --> (X & C2) iff (C1&C2) == 0
-            return BinaryOperator::create(Instruction::And, X, RHS);
-          } else if (isOnlyUse(Op0)) {
-            // (X ^ C1) & C2 --> (X & C2) ^ (C1&C2)
-            std::string Op0Name = Op0I->getName(); Op0I->setName("");
-            Instruction *And = BinaryOperator::create(Instruction::And,
-                                                      X, RHS, Op0Name);
-            InsertNewInstBefore(And, I);
-            return BinaryOperator::create(Instruction::Xor, And, *RHS & *Op0CI);
-          }
-        } else if (Op0I->getOpcode() == Instruction::Or) {
-          // (X | C1) & C2 --> X & C2 iff C1 & C1 == 0
-          if ((*RHS & *Op0CI)->isNullValue())
-            return BinaryOperator::create(Instruction::And, X, RHS);
-
-          Constant *Together = *RHS & *Op0CI;
-          if (Together == RHS) // (X | C) & C --> C
-            return ReplaceInstUsesWith(I, RHS);
-
-          if (isOnlyUse(Op0)) {
-            if (Together != Op0CI) {
-              // (X | C1) & C2 --> (X | (C1&C2)) & C2
-              std::string Op0Name = Op0I->getName(); Op0I->setName("");
-              Instruction *Or = BinaryOperator::create(Instruction::Or, X,
-                                                       Together, Op0Name);
-              InsertNewInstBefore(Or, I);
-              return BinaryOperator::create(Instruction::And, Or, RHS);
-            }
-          }
-        } else if (Op0I->getOpcode() == Instruction::Add &&
-                   Op0I->use_size() == 1) {
-          // Adding a one to a single bit bit-field should be turned into an XOR
-          // of the bit.  First thing to check is to see if this AND is with a
-          // single bit constant.
-          unsigned long long AndRHS = cast<ConstantInt>(RHS)->getRawValue();
-
-          // Clear bits that are not part of the constant.
-          AndRHS &= (1ULL << RHS->getType()->getPrimitiveSize()*8)-1;
-
-          // If there is only one bit set...
-          if ((AndRHS & (AndRHS-1)) == 0) {
-            // Ok, at this point, we know that we are masking the result of the
-            // ADD down to exactly one bit.  If the constant we are adding has
-            // no bits set below this bit, then we can eliminate the ADD.
-            unsigned long long AddRHS = cast<ConstantInt>(Op0CI)->getRawValue();
-            
-            // Check to see if any bits below the one bit set in AndRHS are set.
-            if ((AddRHS & (AndRHS-1)) == 0) {
-              // If not, the only thing that can effect the output of the AND is
-              // the bit specified by AndRHS.  If that bit is set, the effect of
-              // the XOR is to toggle the bit.  If it is clear, then the ADD has
-              // no effect.
-              if ((AddRHS & AndRHS) == 0) { // Bit is not set, noop
-                I.setOperand(0, Op0I->getOperand(0));
-                return &I;
-              } else {
-                std::string Name = Op0I->getName(); Op0I->setName("");
-                // Pull the XOR out of the AND.
-                Instruction *NewAnd =
-                  BinaryOperator::create(Instruction::And, Op0I->getOperand(0),
-                                         RHS, Name);
-                InsertNewInstBefore(NewAnd, I);
-                return BinaryOperator::create(Instruction::Xor, NewAnd, RHS);
-              }
-            }
-          }
-        }
+        if (Instruction *Res = OptAndOp(Op0I, Op0CI, RHS, I))
+          return Res;
     }
   }
 





More information about the llvm-commits mailing list