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

Chris Lattner clattner at apple.com
Sat Mar 24 00:04:27 PDT 2007


>
> Add an APInt version of SimplifyDemandedBits.
>
> Patch by Zhou Sheng.

Commenting on the version from mainline, comments preceeded with ***'s:


static void ComputeMaskedBits(Value *V, APInt Mask, APInt& KnownZero,
*** Mask should be passed by const&.


bool InstCombiner::SimplifyDemandedBits(Value *V, APInt DemandedMask,
*** Plz pass APInt's by const&, not by-value.
                                         APInt& KnownZero, APInt&  
KnownOne,
                                         unsigned Depth) {

...

   Instruction *I = dyn_cast<Instruction>(V);
   if (!I) return false;        // Only analyze instructions.

   DemandedMask &= APInt::getAllOnesValue(BitWidth);
*** This &= is dead.

   APInt LHSKnownZero(BitWidth, 0), LHSKnownOne(BitWidth, 0);
   APInt &RHSKnownZero = KnownZero, &RHSKnownOne = KnownOne;
*** What is the point of the RHSKnownZero/RHSKnownOne references, plz  
drop them.

   switch (I->getOpcode()) {
...
   case Instruction::Trunc: {
     uint32_t truncBf =
       cast<IntegerType>(I->getOperand(0)->getType())->getBitWidth();
     if (SimplifyDemandedBits(I->getOperand(0), DemandedMask.zext 
(truncBf),
         RHSKnownZero.zext(truncBf), RHSKnownOne.zext(truncBf), Depth 
+1))
*** Plz move the calls to zext out of line.
       return true;
     DemandedMask.trunc(BitWidth);
     RHSKnownZero.trunc(BitWidth);
     RHSKnownOne.trunc(BitWidth);
     assert((RHSKnownZero & RHSKnownOne) == 0 &&
            "Bits known to be one AND zero?");
     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 NewBits(APInt::getAllOnesValue(BitWidth).shl(SrcTy- 
 >getBitWidth()));
*** This idiom occurs in many places, it should be a new  
APInt::getHighBitsSet(width,numbits) method.

     DemandedMask &= SrcTy->getMask().zext(BitWidth);
*** This should truncate DemandedMask then 'and' it.

     uint32_t zextBf = SrcTy->getBitWidth();
     if (SimplifyDemandedBits(I->getOperand(0), DemandedMask.trunc 
(zextBf),
           RHSKnownZero.trunc(zextBf), RHSKnownOne.trunc(zextBf),  
Depth+1))
*** Truncs out of line plz.
       return true;
   }
   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 NewBits(APInt::getAllOnesValue(BitWidth).shl(SrcTy- 
 >getBitWidth()));
*** Should use APInt::getHighBitsSet.

     // Get the sign bit for the source type
     APInt InSignBit(APInt::getSignBit(SrcTy->getPrimitiveSizeInBits 
()));
     InSignBit.zext(BitWidth);
     APInt InputDemandedBits = DemandedMask &
                               SrcTy->getMask().zext(BitWidth);
*** The getMask().zext stuff should get 'APInt::getLowBitsSet(...)'.
..
     uint32_t sextBf = SrcTy->getBitWidth();
     if (SimplifyDemandedBits(I->getOperand(0),  
InputDemandedBits.trunc(sextBf),
           RHSKnownZero.trunc(sextBf), RHSKnownOne.trunc(sextBf),  
Depth+1))
*** Plz don't nest the trunc calls.
       return true;

   case Instruction::Add: {
...
       // If the top bit of the output is demanded, demand everything  
from the
       // input.  Otherwise, we demand all the input bits except NLZ  
top bits.
       APInt InDemandedBits(APInt::getAllOnesValue(BitWidth).lshr(NLZ));
*** Should be APInt::getLowBitsSet.

...
       bool CarryIn = false;
       APInt CarryBits(BitWidth, 0);
       const uint64_t *LHSKnownZeroRawVal = LHSKnownZero.getRawData(),
                      *RHSRawVal = RHSVal.getRawData();
       for (uint32_t i = 0; i != RHSVal.getNumWords(); ++i) {
         uint64_t AddVal = ~LHSKnownZeroRawVal[i] + RHSRawVal[i],
                  XorVal = ~LHSKnownZeroRawVal[i] ^ RHSRawVal[i];
         uint64_t WordCarryBits = AddVal ^ XorVal + CarryIn;
         if (AddVal < RHSRawVal[i])
           CarryIn = true;
         else
           CarryIn = false;
         CarryBits.setWordToValue(i, WordCarryBits);
       }
*** Why aren't you doing this in terms of APInt operations?
...
       // If the high-bits of this ADD are not demanded, then it does  
not demand
       // the high bits of its LHS or RHS.
       if ((DemandedMask & APInt::getSignBit(BitWidth)) == 0) {
*** This seems like it should be: "if (DemandedMask[BitWidth-1] == 0)  
{".  Likewise in other places, grep for getSignBit to find them.
         // Right fill the mask of bits for this ADD to demand the most
         // significant bit and all those below it.
         APInt DemandedFromOps = APInt::getAllOnesValue(BitWidth).lshr 
(NLZ);
*** Use APInt::getLowBitsSet.

...

   case Instruction::Sub:
     // If the high-bits of this SUB are not demanded, then it does  
not demand
     // the high bits of its LHS or RHS.
     if ((DemandedMask & APInt::getSignBit(BitWidth)) == 0) {
*** Use operator[]
       // Right fill the mask of bits for this SUB to demand the most
       // significant bit and all those below it.
       unsigned NLZ = DemandedMask.countLeadingZeros();
       APInt DemandedFromOps(APInt::getAllOnesValue(BitWidth).lshr 
(NLZ));
*** Use getLowBitsSet.


   case Instruction::Shl:
     if (ConstantInt *SA = dyn_cast<ConstantInt>(I->getOperand(1))) {
       uint64_t ShiftAmt = SA->getZExtValue();
       if (SimplifyDemandedBits(I->getOperand(0), DemandedMask.lshr 
(ShiftAmt),
*** Don't nest the lshr call, it makes it VERY easy to miss.
                                RHSKnownZero, RHSKnownOne, Depth+1))
         return true;
...
       // low bits known zero.
       if (ShiftAmt)
         RHSKnownZero |= APInt::getAllOnesValue(ShiftAmt).zextOrCopy 
(BitWidth);
*** getLowBitsSet.  If this is the only use of zextOrCopy, remove it.


   case Instruction::LShr:
     // For a logical shift right
     if (ConstantInt *SA = dyn_cast<ConstantInt>(I->getOperand(1))) {
       unsigned ShiftAmt = SA->getZExtValue();

       APInt TypeMask(APInt::getAllOnesValue(BitWidth));
       // Unsigned shift right.
       if (SimplifyDemandedBits(I->getOperand(0),
                               (DemandedMask.shl(ShiftAmt)) & TypeMask,
*** The & is dead, move the shl out of line plz.
                                RHSKnownZero, RHSKnownOne, Depth+1))
         return true;
       assert((RHSKnownZero & RHSKnownOne) == 0 &&
              "Bits known to be one AND zero?");
       RHSKnownZero &= TypeMask;
       RHSKnownOne  &= TypeMask;
*** These &='s are dead.
       RHSKnownZero = APIntOps::lshr(RHSKnownZero, ShiftAmt);
       RHSKnownOne  = APIntOps::lshr(RHSKnownOne, ShiftAmt);
       if (ShiftAmt) {
         // Compute the new bits that are at the top now.
         APInt HighBits(APInt::getAllOnesValue(BitWidth).shl(
                          BitWidth - ShiftAmt));
*** Should use APInt::getHighBitsSet.
...


   case Instruction::AShr:
*** Many of the same comments about LShr apply here.
...
       // Handle the sign bits.
       APInt SignBit(APInt::getSignBit(BitWidth));
       // Adjust to where it is now in the mask.
       SignBit = APIntOps::lshr(SignBit, ShiftAmt);

       // If the input sign bit is known to be zero, or if none of  
the top bits
       // are demanded, turn this into an unsigned shift right.
       if ((RHSKnownZero & SignBit) != 0 ||

*** All this logic playing with Sign bit should be eliminated and  
replace with use of RHSKnownZero[] and RHSKnownOne[] (down below).


static void ComputeUnsignedMinMaxValuesFromKnownBits(const Type *Ty,
                                                      const APInt&  
KnownZero,
                                                      const APInt&  
KnownOne,
                                                      APInt& Min,
                                                      APInt& Max) {
   uint32_t BitWidth = cast<IntegerType>(Ty)->getBitWidth();
   assert(KnownZero.getBitWidth() == BitWidth &&
          KnownOne.getBitWidth() == BitWidth &&
          Min.getBitWidth() == BitWidth && Max.getBitWidth() &&
          "Ty, KnownZero, KnownOne and Min, Max must have equal  
bitwidth.");
   APInt TypeBits(APInt::getAllOnesValue(BitWidth));
   APInt UnknownBits = ~(KnownZero|KnownOne) & TypeBits;
*** TypeBits and the & are dead.

   // 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;
}


static void ComputeSignedMinMaxValuesFromKnownBits(const Type *Ty,
                                                    const APInt&  
KnownZero,
                                                    const APInt&  
KnownOne,
                                                    APInt& Min,  
APInt& Max) {
   uint32_t BitWidth = cast<IntegerType>(Ty)->getBitWidth();
   assert(KnownZero.getBitWidth() == BitWidth &&
          KnownOne.getBitWidth() == BitWidth &&
          Min.getBitWidth() == BitWidth && Max.getBitWidth() ==  
BitWidth &&
          "Ty, KnownZero, KnownOne and Min, Max must have equal  
bitwidth.");
   APInt TypeBits(APInt::getAllOnesValue(BitWidth));
   APInt UnknownBits = ~(KnownZero|KnownOne) & TypeBits;
*** TypeBits and the & are dead.

   APInt SignBit(APInt::getSignBit(BitWidth));
*** Eliminate SignBit (and its uses) in favor of using UnknownBIts 
[BitWidth-1] and Min[BitWidth-1] = 1, etc.

   // 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) != 0) { // Sign bit is unknown
     Min |= SignBit;
     Max &= ~SignBit;
   }
}

static bool ShrinkDemandedConstant(Instruction *I, unsigned OpNo,
                                    APInt Demanded) {
*** Pass Demanded by const&.
   assert(I && "No instruction?");
   assert(OpNo < I->getNumOperands() && "Operand index too large");

   // If the operand is not a constant integer, nothing to do.
   ConstantInt *OpC = dyn_cast<ConstantInt>(I->getOperand(OpNo));
   if (!OpC) return false;

   // If there are no bits set that aren't demanded, nothing to do.
   Demanded.zextOrTrunc(OpC->getValue().getBitWidth());
*** This zextOrTrunc is dead.
   if ((~Demanded & OpC->getValue()) == 0)
     return false;

   // This instruction is producing bits that are not demanded.  
Shrink the RHS.
   Demanded &= OpC->getValue();
   I->setOperand(OpNo, ConstantInt::get(Demanded));
   return true;
}

Overall, nice job,

-Chris



More information about the llvm-commits mailing list