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

Chris Lattner lattner at cs.uiuc.edu
Sat Feb 11 18:08:08 PST 2006



Changes in directory llvm/lib/Transforms/Scalar:

InstructionCombining.cpp updated: 1.429 -> 1.430
---
Log message:

Three changes:
1. Teach GetConstantInType to handle boolean constants.
2. Teach instcombine to fold (compare X, CST) when X has known 0/1 bits.
   Testcase here: set.ll:test22
3. Improve the "(X >> c1) & C2 == 0" folding code to allow a noop cast 
   between the shift and and.  More aggressive bitfolding for other reasons
   was turning signed shr's into unsigned shr's, leaving the noop cast in
   the way.


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

 InstructionCombining.cpp |  141 +++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 135 insertions(+), 6 deletions(-)


Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp
diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.429 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.430
--- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.429	Sat Feb 11 03:31:47 2006
+++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp	Sat Feb 11 20:07:56 2006
@@ -410,9 +410,11 @@
 
 /// GetConstantInType - Return a ConstantInt with the specified type and value.
 ///
-static ConstantInt *GetConstantInType(const Type *Ty, uint64_t Val) {
+static ConstantIntegral *GetConstantInType(const Type *Ty, uint64_t Val) {
   if (Ty->isUnsigned())
     return ConstantUInt::get(Ty, Val);
+  else if (Ty->getTypeID() == Type::BoolTyID)
+    return ConstantBool::get(Val);
   int64_t SVal = Val;
   SVal <<= 64-Ty->getPrimitiveSizeInBits();
   SVal >>= 64-Ty->getPrimitiveSizeInBits();
@@ -619,6 +621,52 @@
   return true;
 }
 
+// ComputeSignedMinMaxValuesFromKnownBits - Given a signed integer type and a 
+// set of known zero and one bits, compute the maximum and minimum values that
+// could have the specified known zero and known one bits, returning them in
+// min/max.
+static void ComputeSignedMinMaxValuesFromKnownBits(const Type *Ty,
+                                                   uint64_t KnownZero,
+                                                   uint64_t KnownOne,
+                                                   int64_t &Min, int64_t &Max) {
+  uint64_t TypeBits = Ty->getIntegralTypeMask();
+  uint64_t UnknownBits = ~(KnownZero|KnownOne) & TypeBits;
+
+  uint64_t SignBit = 1ULL << (Ty->getPrimitiveSizeInBits()-1);
+  
+  // The minimum value is when all unknown bits are zeros, EXCEPT for the sign
+  // bit if it is unknown.
+  Min = KnownOne;
+  Max = KnownOne|UnknownBits;
+  
+  if (SignBit & UnknownBits) { // Sign bit is unknown
+    Min |= SignBit;
+    Max &= ~SignBit;
+  }
+  
+  // Sign extend the min/max values.
+  int ShAmt = 64-Ty->getPrimitiveSizeInBits();
+  Min = (Min << ShAmt) >> ShAmt;
+  Max = (Max << ShAmt) >> ShAmt;
+}
+
+// ComputeUnsignedMinMaxValuesFromKnownBits - Given an unsigned integer type and
+// a set of known zero and one bits, compute the maximum and minimum values that
+// could have the specified known zero and known one bits, returning them in
+// min/max.
+static void ComputeUnsignedMinMaxValuesFromKnownBits(const Type *Ty,
+                                                     uint64_t KnownZero,
+                                                     uint64_t KnownOne,
+                                                     uint64_t &Min,
+                                                     uint64_t &Max) {
+  uint64_t TypeBits = Ty->getIntegralTypeMask();
+  uint64_t UnknownBits = ~(KnownZero|KnownOne) & TypeBits;
+  
+  // The minimum value is when the unknown bits are all zeros.
+  Min = KnownOne;
+  // The maximum value is when the unknown bits are all ones.
+  Max = KnownOne|UnknownBits;
+}
 
 
 /// SimplifyDemandedBits - Look at V.  At this point, we know that only the
@@ -3264,6 +3312,69 @@
     if (I.getOpcode() == Instruction::SetGE)
       return BinaryOperator::createSetGT(Op0, SubOne(CI));
 
+    
+    // See if we can fold the comparison based on bits known to be zero or one
+    // in the input.
+    uint64_t KnownZero, KnownOne;
+    if (SimplifyDemandedBits(Op0, Ty->getIntegralTypeMask(),
+                             KnownZero, KnownOne, 0))
+      return &I;
+        
+    // Given the known and unknown bits, compute a range that the LHS could be
+    // in.
+    if (KnownOne | KnownZero) {
+      if (Ty->isUnsigned()) {   // Unsigned comparison.
+        uint64_t Min, Max;
+        uint64_t RHSVal = CI->getZExtValue();
+        ComputeUnsignedMinMaxValuesFromKnownBits(Ty, KnownZero, KnownOne,
+                                                 Min, Max);
+        switch (I.getOpcode()) {  // LE/GE have been folded already.
+        default: assert(0 && "Unknown setcc opcode!");
+        case Instruction::SetEQ:
+          if (Max < RHSVal || Min > RHSVal)
+            return ReplaceInstUsesWith(I, ConstantBool::False);
+          break;
+        case Instruction::SetNE:
+          if (Max < RHSVal || Min > RHSVal)
+            return ReplaceInstUsesWith(I, ConstantBool::True);
+          break;
+        case Instruction::SetLT:
+          if (Max < RHSVal) return ReplaceInstUsesWith(I, ConstantBool::True);
+          if (Min > RHSVal) return ReplaceInstUsesWith(I, ConstantBool::False);
+          break;
+        case Instruction::SetGT:
+          if (Min > RHSVal) return ReplaceInstUsesWith(I, ConstantBool::True);
+          if (Max < RHSVal) return ReplaceInstUsesWith(I, ConstantBool::False);
+          break;
+        }
+      } else {              // Signed comparison.
+        int64_t Min, Max;
+        int64_t RHSVal = CI->getSExtValue();
+        ComputeSignedMinMaxValuesFromKnownBits(Ty, KnownZero, KnownOne,
+                                               Min, Max);
+        switch (I.getOpcode()) {  // LE/GE have been folded already.
+        default: assert(0 && "Unknown setcc opcode!");
+        case Instruction::SetEQ:
+          if (Max < RHSVal || Min > RHSVal)
+            return ReplaceInstUsesWith(I, ConstantBool::False);
+          break;
+        case Instruction::SetNE:
+          if (Max < RHSVal || Min > RHSVal)
+            return ReplaceInstUsesWith(I, ConstantBool::True);
+          break;
+        case Instruction::SetLT:
+          if (Max < RHSVal) return ReplaceInstUsesWith(I, ConstantBool::True);
+          if (Min > RHSVal) return ReplaceInstUsesWith(I, ConstantBool::False);
+          break;
+        case Instruction::SetGT:
+          if (Min > RHSVal) return ReplaceInstUsesWith(I, ConstantBool::True);
+          if (Max < RHSVal) return ReplaceInstUsesWith(I, ConstantBool::False);
+          break;
+        }
+      }
+    }
+          
+    
     if (Instruction *LHSI = dyn_cast<Instruction>(Op0))
       switch (LHSI->getOpcode()) {
       case Instruction::And:
@@ -3274,17 +3385,28 @@
           // happens a LOT in code produced by the C front-end, for bitfield
           // access.
           ShiftInst *Shift = dyn_cast<ShiftInst>(LHSI->getOperand(0));
+          ConstantInt *AndCST = cast<ConstantInt>(LHSI->getOperand(1));
+
+          // Check to see if there is a noop-cast between the shift and the and.
+          if (!Shift) {
+            if (CastInst *CI = dyn_cast<CastInst>(LHSI->getOperand(0)))
+              if (CI->getOperand(0)->getType()->isIntegral() &&
+                  CI->getOperand(0)->getType()->getPrimitiveSizeInBits() ==
+                     CI->getType()->getPrimitiveSizeInBits())
+                Shift = dyn_cast<ShiftInst>(CI->getOperand(0));
+          }
+          
           ConstantUInt *ShAmt;
           ShAmt = Shift ? dyn_cast<ConstantUInt>(Shift->getOperand(1)) : 0;
-          ConstantInt *AndCST = cast<ConstantInt>(LHSI->getOperand(1));
-          const Type *Ty = LHSI->getType();
+          const Type *Ty = Shift ? Shift->getType() : 0;  // Type of the shift.
+          const Type *AndTy = AndCST->getType();          // Type of the and.
 
           // We can fold this as long as we can't shift unknown bits
           // into the mask.  This can only happen with signed shift
           // rights, as they sign-extend.
           if (ShAmt) {
             bool CanFold = Shift->getOpcode() != Instruction::Shr ||
-                           Shift->getType()->isUnsigned();
+                           Ty->isUnsigned();
             if (!CanFold) {
               // To test for the bad case of the signed shr, see if any
               // of the bits shifted in could be tested after the mask.
@@ -3293,7 +3415,8 @@
 
               Constant *OShAmt = ConstantUInt::get(Type::UByteTy, ShAmtVal);
               Constant *ShVal =
-                ConstantExpr::getShl(ConstantInt::getAllOnesValue(Ty), OShAmt);
+                ConstantExpr::getShl(ConstantInt::getAllOnesValue(AndTy), 
+                                     OShAmt);
               if (ConstantExpr::getAnd(ShVal, AndCST)->isNullValue())
                 CanFold = true;
             }
@@ -3323,7 +3446,13 @@
                 else
                   NewAndCST = ConstantExpr::getShl(AndCST, ShAmt);
                 LHSI->setOperand(1, NewAndCST);
-                LHSI->setOperand(0, Shift->getOperand(0));
+                if (AndTy == Ty) 
+                  LHSI->setOperand(0, Shift->getOperand(0));
+                else {
+                  Value *NewCast = InsertCastBefore(Shift->getOperand(0), AndTy,
+                                                    *Shift);
+                  LHSI->setOperand(0, NewCast);
+                }
                 WorkList.push_back(Shift); // Shift is dead.
                 AddUsesToWorkList(I);
                 return &I;






More information about the llvm-commits mailing list