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

Reid Spencer reid at x10sys.com
Wed Mar 7 17:46:56 PST 2007



Changes in directory llvm/lib/Transforms/Scalar:

InstructionCombining.cpp updated: 1.648 -> 1.649
---
Log message:

For PR1205: http://llvm.org/PR1205 :
Add a new ComputeMaskedBits function that is APIntified. We'll slowly
convert things over to use this version. When its all done, we'll remove
the existing version.


---
Diffs of the changes:  (+206 -1)

 InstructionCombining.cpp |  207 ++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 206 insertions(+), 1 deletion(-)


Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp
diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.648 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.649
--- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.648	Mon Mar  5 17:36:13 2007
+++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp	Wed Mar  7 19:46:38 2007
@@ -568,9 +568,214 @@
 
 /// ComputeMaskedBits - Determine which of the bits specified in Mask are
 /// known to be either zero or one and return them in the KnownZero/KnownOne
+/// bit sets.  This code only analyzes bits in Mask, in order to short-circuit
+/// processing.
+/// NOTE: we cannot consider 'undef' to be "IsZero" here.  The problem is that
+/// we cannot optimize based on the assumption that it is zero without changing
+/// it to be an explicit zero.  If we don't change it to zero, other code could
+/// optimized based on the contradictory assumption that it is non-zero.
+/// Because instcombine aggressively folds operations with undef args anyway,
+/// this won't lose us code quality.
+static void ComputeMaskedBits(Value *V, APInt Mask, APInt& KnownZero, 
+                              APInt& KnownOne, unsigned Depth = 0) {
+  uint32_t BitWidth = Mask.getBitWidth();
+  assert(KnownZero.getBitWidth() == BitWidth && 
+         KnownOne.getBitWidth() == BitWidth &&
+         "Mask, KnownOne and KnownZero should have same BitWidth");
+  if (ConstantInt *CI = dyn_cast<ConstantInt>(V)) {
+    // We know all of the bits for a constant!
+    APInt Tmp(CI->getValue());
+    Tmp.zextOrTrunc(BitWidth);
+    KnownOne = Tmp & Mask;
+    KnownZero = ~KnownOne & Mask;
+    return;
+  }
+
+  KnownZero.clear(); KnownOne.clear();   // Don't know anything.
+  if (Depth == 6 || Mask == 0)
+    return;  // Limit search depth.
+
+  Instruction *I = dyn_cast<Instruction>(V);
+  if (!I) return;
+
+  APInt KnownZero2(KnownZero), KnownOne2(KnownOne);
+  Mask &= APInt::getAllOnesValue(
+    cast<IntegerType>(V->getType())->getBitWidth()).zextOrTrunc(BitWidth);
+  
+  switch (I->getOpcode()) {
+  case Instruction::And:
+    // If either the LHS or the RHS are Zero, the result is zero.
+    ComputeMaskedBits(I->getOperand(1), Mask, KnownZero, KnownOne, Depth+1);
+    Mask &= ~KnownZero;
+    ComputeMaskedBits(I->getOperand(0), Mask, KnownZero2, KnownOne2, Depth+1);
+    assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); 
+    assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?"); 
+    
+    // Output known-1 bits are only known if set in both the LHS & RHS.
+    KnownOne &= KnownOne2;
+    // Output known-0 are known to be clear if zero in either the LHS | RHS.
+    KnownZero |= KnownZero2;
+    return;
+  case Instruction::Or:
+    ComputeMaskedBits(I->getOperand(1), Mask, KnownZero, KnownOne, Depth+1);
+    Mask &= ~KnownOne;
+    ComputeMaskedBits(I->getOperand(0), Mask, KnownZero2, KnownOne2, Depth+1);
+    assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); 
+    assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?"); 
+    
+    // Output known-0 bits are only known if clear in both the LHS & RHS.
+    KnownZero &= KnownZero2;
+    // Output known-1 are known to be set if set in either the LHS | RHS.
+    KnownOne |= KnownOne2;
+    return;
+  case Instruction::Xor: {
+    ComputeMaskedBits(I->getOperand(1), Mask, KnownZero, KnownOne, Depth+1);
+    ComputeMaskedBits(I->getOperand(0), Mask, KnownZero2, KnownOne2, Depth+1);
+    assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); 
+    assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?"); 
+    
+    // Output known-0 bits are known if clear or set in both the LHS & RHS.
+    APInt KnownZeroOut = (KnownZero & KnownZero2) | (KnownOne & KnownOne2);
+    // Output known-1 are known to be set if set in only one of the LHS, RHS.
+    KnownOne = (KnownZero & KnownOne2) | (KnownOne & KnownZero2);
+    KnownZero = KnownZeroOut;
+    return;
+  }
+  case Instruction::Select:
+    ComputeMaskedBits(I->getOperand(2), Mask, KnownZero, KnownOne, Depth+1);
+    ComputeMaskedBits(I->getOperand(1), Mask, KnownZero2, KnownOne2, Depth+1);
+    assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); 
+    assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?"); 
+
+    // Only known if known in both the LHS and RHS.
+    KnownOne &= KnownOne2;
+    KnownZero &= KnownZero2;
+    return;
+  case Instruction::FPTrunc:
+  case Instruction::FPExt:
+  case Instruction::FPToUI:
+  case Instruction::FPToSI:
+  case Instruction::SIToFP:
+  case Instruction::PtrToInt:
+  case Instruction::UIToFP:
+  case Instruction::IntToPtr:
+    return; // Can't work with floating point or pointers
+  case Instruction::Trunc: 
+    // All these have integer operands
+    ComputeMaskedBits(I->getOperand(0), Mask, KnownZero, KnownOne, Depth+1);
+    return;
+  case Instruction::BitCast: {
+    const Type *SrcTy = I->getOperand(0)->getType();
+    if (SrcTy->isInteger()) {
+      ComputeMaskedBits(I->getOperand(0), Mask, KnownZero, KnownOne, Depth+1);
+      return;
+    }
+    break;
+  }
+  case Instruction::ZExt:  {
+    // Compute the bits in the result that are not present in the input.
+    const IntegerType *SrcTy = cast<IntegerType>(I->getOperand(0)->getType());
+    APInt NotIn(~SrcTy->getMask());
+    APInt NewBits = APInt::getAllOnesValue(BitWidth) & 
+                    NotIn.zext(BitWidth);
+      
+    Mask &= ~NotIn;
+    ComputeMaskedBits(I->getOperand(0), Mask, KnownZero, KnownOne, Depth+1);
+    assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); 
+    // The top bits are known to be zero.
+    KnownZero |= NewBits;
+    return;
+  }
+  case Instruction::SExt: {
+    // Compute the bits in the result that are not present in the input.
+    const IntegerType *SrcTy = cast<IntegerType>(I->getOperand(0)->getType());
+    APInt NotIn(~SrcTy->getMask());
+    APInt NewBits = APInt::getAllOnesValue(BitWidth) & 
+                    NotIn.zext(BitWidth);
+      
+    Mask &= ~NotIn;
+    ComputeMaskedBits(I->getOperand(0), Mask, KnownZero, KnownOne, Depth+1);
+    assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); 
+
+    // If the sign bit of the input is known set or clear, then we know the
+    // top bits of the result.
+    APInt InSignBit(APInt::getSignedMinValue(SrcTy->getBitWidth()));
+    InSignBit.zextOrTrunc(BitWidth);
+    if ((KnownZero & InSignBit) != 0) {          // Input sign bit known zero
+      KnownZero |= NewBits;
+      KnownOne &= ~NewBits;
+    } else if ((KnownOne & InSignBit) != 0) {    // Input sign bit known set
+      KnownOne |= NewBits;
+      KnownZero &= ~NewBits;
+    } else {                              // Input sign bit unknown
+      KnownZero &= ~NewBits;
+      KnownOne &= ~NewBits;
+    }
+    return;
+  }
+  case Instruction::Shl:
+    // (shl X, C1) & C2 == 0   iff   (X & C2 >>u C1) == 0
+    if (ConstantInt *SA = dyn_cast<ConstantInt>(I->getOperand(1))) {
+      uint64_t ShiftAmt = SA->getZExtValue();
+      Mask = APIntOps::lshr(Mask, ShiftAmt);
+      ComputeMaskedBits(I->getOperand(0), Mask, KnownZero, KnownOne, Depth+1);
+      assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); 
+      KnownZero = APIntOps::shl(KnownZero, ShiftAmt);
+      KnownOne  = APIntOps::shl(KnownOne, ShiftAmt);
+      KnownZero |= APInt(BitWidth, 1ULL).shl(ShiftAmt)-1;  // low bits known zero.
+      return;
+    }
+    break;
+  case Instruction::LShr:
+    // (ushr X, C1) & C2 == 0   iff  (-1 >> C1) & C2 == 0
+    if (ConstantInt *SA = dyn_cast<ConstantInt>(I->getOperand(1))) {
+      // Compute the new bits that are at the top now.
+      uint64_t ShiftAmt = SA->getZExtValue();
+      APInt HighBits(APInt::getAllOnesValue(BitWidth).shl(BitWidth-ShiftAmt));
+      
+      // Unsigned shift right.
+      Mask = APIntOps::shl(Mask, ShiftAmt);
+      ComputeMaskedBits(I->getOperand(0), Mask, KnownZero,KnownOne,Depth+1);
+      assert((KnownZero & KnownOne) == 0&&"Bits known to be one AND zero?"); 
+      KnownZero = APIntOps::lshr(KnownZero, ShiftAmt);
+      KnownOne  = APIntOps::lshr(KnownOne, ShiftAmt);
+      KnownZero |= HighBits;  // high bits known zero.
+      return;
+    }
+    break;
+  case Instruction::AShr:
+    // (ushr X, C1) & C2 == 0   iff  (-1 >> C1) & C2 == 0
+    if (ConstantInt *SA = dyn_cast<ConstantInt>(I->getOperand(1))) {
+      // Compute the new bits that are at the top now.
+      uint64_t ShiftAmt = SA->getZExtValue();
+      APInt HighBits(APInt::getAllOnesValue(BitWidth).shl(BitWidth-ShiftAmt));
+      
+      // Signed shift right.
+      Mask = APIntOps::shl(Mask, ShiftAmt);
+      ComputeMaskedBits(I->getOperand(0), Mask, KnownZero,KnownOne,Depth+1);
+      assert((KnownZero & KnownOne) == 0&&"Bits known to be one AND zero?"); 
+      KnownZero = APIntOps::lshr(KnownZero, ShiftAmt);
+      KnownOne  = APIntOps::lshr(KnownOne, ShiftAmt);
+        
+      // Handle the sign bits and adjust to where it is now in the mask.
+      APInt SignBit = APInt::getSignedMinValue(BitWidth).lshr(ShiftAmt);
+        
+      if ((KnownZero & SignBit) != 0) {       // New bits are known zero.
+        KnownZero |= HighBits;
+      } else if ((KnownOne & SignBit) != 0) { // New bits are known one.
+        KnownOne |= HighBits;
+      }
+      return;
+    }
+    break;
+  }
+}
+
+/// ComputeMaskedBits - Determine which of the bits specified in Mask are
+/// known to be either zero or one and return them in the KnownZero/KnownOne
 /// bitsets.  This code only analyzes bits in Mask, in order to short-circuit
 /// processing.
-static void ComputeMaskedBits(Value *V, uint64_t Mask, uint64_t &KnownZero,
+static void ComputeMaskedBits(Value *V, uint64_t Mask, uint64_t &KnownZero, 
                               uint64_t &KnownOne, unsigned Depth = 0) {
   // Note, we cannot consider 'undef' to be "IsZero" here.  The problem is that
   // we cannot optimize based on the assumption that it is zero without changing






More information about the llvm-commits mailing list