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

Chris Lattner lattner at cs.uiuc.edu
Tue Sep 28 14:48:15 PDT 2004



Changes in directory llvm/lib/Transforms/Scalar:

InstructionCombining.cpp updated: 1.253 -> 1.254
---
Log message:

Fold (and (setcc X, C1), (setcc X, C2))

This is important for several reasons:

1. Benchmarks have lots of code that looks like this (perlbmk in particular):

  %tmp.2.i = setne int %tmp.0.i, 128              ; <bool> [#uses=1]
  %tmp.6343 = seteq int %tmp.0.i, 1               ; <bool> [#uses=1]
  %tmp.63 = and bool %tmp.2.i, %tmp.6343          ; <bool> [#uses=1]

   we now fold away the setne, a clear improvement.

2. In the more important cases, such as (X >= 10) & (X < 20), we now produce
   smaller code: (X-10) < 10.

3. Perhaps the nicest effect of this patch is that it really helps out the
   code generators.  In particular, for a 'range test' like the above, 
   instead of generating this on X86 (the difference on PPC is even more 
   pronounced):

        cmp %EAX, 50
        setge %CL
        cmp %EAX, 100
        setl %AL
        and %CL, %AL
        cmp %CL, 0

   we now generate this:

        add %EAX, -50
        cmp %EAX, 50

   Furthermore, this causes setcc's to be folded into branches more often.

These combinations trigger dozens of times in the spec benchmarks, particularly
in 176.gcc, 186.crafty, 253.perlbmk, 254.gap, & 099.go.



---
Diffs of the changes:  (+121 -20)

Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp
diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.253 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.254
--- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.253	Tue Sep 28 13:22:15 2004
+++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp	Tue Sep 28 16:48:02 2004
@@ -137,7 +137,7 @@
     // InsertNewInstBefore - insert an instruction New before instruction Old
     // in the program.  Add the new instruction to the worklist.
     //
-    Value *InsertNewInstBefore(Instruction *New, Instruction &Old) {
+    Instruction *InsertNewInstBefore(Instruction *New, Instruction &Old) {
       assert(New && New->getParent() == 0 &&
              "New instruction already inserted into a basic block!");
       BasicBlock *BB = Old.getParent();
@@ -334,6 +334,22 @@
   return Count;
 }
 
+// AddOne, SubOne - Add or subtract a constant one from an integer constant...
+static Constant *AddOne(ConstantInt *C) {
+  return ConstantExpr::getAdd(C, ConstantInt::get(C->getType(), 1));
+}
+static Constant *SubOne(ConstantInt *C) {
+  return ConstantExpr::getSub(C, ConstantInt::get(C->getType(), 1));
+}
+
+// isTrueWhenEqual - Return true if the specified setcondinst instruction is
+// true when both operands are equal...
+//
+static bool isTrueWhenEqual(Instruction &I) {
+  return I.getOpcode() == Instruction::SetEQ ||
+         I.getOpcode() == Instruction::SetGE ||
+         I.getOpcode() == Instruction::SetLE;
+}
 
 /// AssociativeOpt - Perform an optimization on an associative operator.  This
 /// function is designed to check a chain of associative operators for a
@@ -1203,11 +1219,113 @@
     return BinaryOperator::createNot(Or);
   }
 
-  // (setcc1 A, B) & (setcc2 A, B) --> (setcc3 A, B)
-  if (SetCondInst *RHS = dyn_cast<SetCondInst>(I.getOperand(1)))
+  if (SetCondInst *RHS = dyn_cast<SetCondInst>(Op1)) {
+    // (setcc1 A, B) & (setcc2 A, B) --> (setcc3 A, B)
     if (Instruction *R = AssociativeOpt(I, FoldSetCCLogical(*this, RHS)))
       return R;
 
+    Value *LHSVal, *RHSVal;
+    ConstantInt *LHSCst, *RHSCst;
+    Instruction::BinaryOps LHSCC, RHSCC;
+    if (match(Op0, m_SetCond(LHSCC, m_Value(LHSVal), m_ConstantInt(LHSCst))))
+      if (match(RHS, m_SetCond(RHSCC, m_Value(RHSVal), m_ConstantInt(RHSCst))))
+        if (LHSVal == RHSVal &&    // Found (X setcc C1) & (X setcc C2)
+            // Set[GL]E X, CST is folded to Set[GL]T elsewhere.
+            LHSCC != Instruction::SetGE && LHSCC != Instruction::SetLE && 
+            RHSCC != Instruction::SetGE && RHSCC != Instruction::SetLE) {
+          // Ensure that the larger constant is on the RHS.
+          Constant *Cmp = ConstantExpr::getSetGT(LHSCst, RHSCst);
+          SetCondInst *LHS = cast<SetCondInst>(Op0);
+          if (cast<ConstantBool>(Cmp)->getValue()) {
+            std::swap(LHS, RHS);
+            std::swap(LHSCst, RHSCst);
+            std::swap(LHSCC, RHSCC);
+          }
+
+          // At this point, we know we have have two setcc instructions
+          // comparing a value against two constants and and'ing the result
+          // together.  Because of the above check, we know that we only have
+          // SetEQ, SetNE, SetLT, and SetGT here.  We also know (from the
+          // FoldSetCCLogical check above), that the two constants are not
+          // equal.
+          assert(LHSCst != RHSCst && "Compares not folded above?");
+
+          switch (LHSCC) {
+          default: assert(0 && "Unknown integer condition code!");
+          case Instruction::SetEQ:
+            switch (RHSCC) {
+            default: assert(0 && "Unknown integer condition code!");
+            case Instruction::SetEQ:  // (X == 13 & X == 15) -> false
+            case Instruction::SetGT:  // (X == 13 & X > 15)  -> false
+              return ReplaceInstUsesWith(I, ConstantBool::False);
+            case Instruction::SetNE:  // (X == 13 & X != 15) -> X == 13
+            case Instruction::SetLT:  // (X == 13 & X < 15)  -> X == 13
+              return ReplaceInstUsesWith(I, LHS);
+            }
+          case Instruction::SetNE:
+            switch (RHSCC) {
+            default: assert(0 && "Unknown integer condition code!");
+            case Instruction::SetLT:
+              if (LHSCst == SubOne(RHSCst)) // (X != 13 & X < 14) -> X < 13
+                return new SetCondInst(Instruction::SetLT, LHSVal, LHSCst);
+              break;                        // (X != 13 & X < 15) -> no change
+            case Instruction::SetEQ:        // (X != 13 & X == 15) -> X == 15
+            case Instruction::SetGT:        // (X != 13 & X > 15)  -> X > 15
+              return ReplaceInstUsesWith(I, RHS);
+            case Instruction::SetNE:
+              if (LHSCst == SubOne(RHSCst)) {// (X != 13 & X != 14) -> X-13 >u 1
+                Constant *AddCST = ConstantExpr::getNeg(LHSCst);
+                Instruction *Add = BinaryOperator::createAdd(LHSVal, AddCST,
+                                                      LHSVal->getName()+".off");
+                InsertNewInstBefore(Add, I);
+                const Type *UnsType = Add->getType()->getUnsignedVersion();
+                Value *OffsetVal = InsertCastBefore(Add, UnsType, I);
+                AddCST = ConstantExpr::getSub(RHSCst, LHSCst);
+                AddCST = ConstantExpr::getCast(AddCST, UnsType);
+                return new SetCondInst(Instruction::SetGT, OffsetVal, AddCST);
+              }
+              break;                        // (X != 13 & X != 15) -> no change
+            }
+            break;
+          case Instruction::SetLT:
+            switch (RHSCC) {
+            default: assert(0 && "Unknown integer condition code!");
+            case Instruction::SetEQ:  // (X < 13 & X == 15) -> false
+            case Instruction::SetGT:  // (X < 13 & X > 15)  -> false
+              return ReplaceInstUsesWith(I, ConstantBool::False);
+            case Instruction::SetNE:  // (X < 13 & X != 15) -> X < 13
+            case Instruction::SetLT:  // (X < 13 & X < 15) -> X < 13
+              return ReplaceInstUsesWith(I, LHS);
+            }
+          case Instruction::SetGT:
+            switch (RHSCC) {
+            default: assert(0 && "Unknown integer condition code!");
+            case Instruction::SetEQ:  // (X > 13 & X == 15) -> X > 13
+              return ReplaceInstUsesWith(I, LHS);
+            case Instruction::SetGT:  // (X > 13 & X > 15)  -> X > 15
+              return ReplaceInstUsesWith(I, RHS);
+            case Instruction::SetNE:
+              if (RHSCst == AddOne(LHSCst)) // (X > 13 & X != 14) -> X > 14
+                return new SetCondInst(Instruction::SetGT, LHSVal, RHSCst);
+              break;                        // (X > 13 & X != 15) -> no change
+            case Instruction::SetLT: { // (X > 13 & X < 15) -> (X-14) <u 1
+              Constant *AddCST = ConstantExpr::getNeg(AddOne(LHSCst));
+              Instruction *Add = BinaryOperator::createAdd(LHSVal, AddCST,
+                                                      LHSVal->getName()+".off");
+              InsertNewInstBefore(Add, I);
+              // Convert to unsigned for the comparison.
+              const Type *UnsType = Add->getType()->getUnsignedVersion();
+              Value *OffsetVal = InsertCastBefore(Add, UnsType, I);
+              AddCST = ConstantExpr::getAdd(AddCST, RHSCst);
+              AddCST = ConstantExpr::getCast(AddCST, UnsType);
+              return new SetCondInst(Instruction::SetLT, OffsetVal, AddCST);
+            }
+            break;
+            }
+          }
+        }
+  }
+
   return Changed ? &I : 0;
 }
 
@@ -1429,23 +1547,6 @@
   return Changed ? &I : 0;
 }
 
-// AddOne, SubOne - Add or subtract a constant one from an integer constant...
-static Constant *AddOne(ConstantInt *C) {
-  return ConstantExpr::getAdd(C, ConstantInt::get(C->getType(), 1));
-}
-static Constant *SubOne(ConstantInt *C) {
-  return ConstantExpr::getSub(C, ConstantInt::get(C->getType(), 1));
-}
-
-// isTrueWhenEqual - Return true if the specified setcondinst instruction is
-// true when both operands are equal...
-//
-static bool isTrueWhenEqual(Instruction &I) {
-  return I.getOpcode() == Instruction::SetEQ ||
-         I.getOpcode() == Instruction::SetGE ||
-         I.getOpcode() == Instruction::SetLE;
-}
-
 Instruction *InstCombiner::visitSetCondInst(BinaryOperator &I) {
   bool Changed = SimplifyCommutative(I);
   Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);






More information about the llvm-commits mailing list