[llvm-commits] CVS: llvm/lib/Transforms/Scalar/InstructionCombining.cpp
Chris Lattner
lattner at cs.uiuc.edu
Wed Feb 8 23:39:10 PST 2006
Changes in directory llvm/lib/Transforms/Scalar:
InstructionCombining.cpp updated: 1.426 -> 1.427
---
Log message:
Enhance MVIZ in three ways:
1. Teach it new tricks: in particular how to propagate through signed shr and sexts.
2. Teach it to return a bitset of known-1 and known-0 bits, instead of just zero.
3. Teach instcombine (AND X, C) to fold when we know all C bits of X.
This implements Regression/Transforms/InstCombine/bittest.ll, and allows
future things to be simplified.
---
Diffs of the changes: (+157 -55)
InstructionCombining.cpp | 212 ++++++++++++++++++++++++++++++++++-------------
1 files changed, 157 insertions(+), 55 deletions(-)
Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp
diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.426 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.427
--- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.426 Wed Feb 8 01:34:50 2006
+++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp Thu Feb 9 01:38:58 2006
@@ -406,88 +406,182 @@
ConstantInt::get(C->getType(), 1)));
}
-/// ComputeMaskedNonZeroBits - Determine which of the bits specified in Mask are
-/// not known to be zero and return them as a bitmask. The bits that we can
-/// guarantee to be zero are returned as zero bits in the result.
-static uint64_t ComputeMaskedNonZeroBits(Value *V, uint64_t Mask,
- unsigned Depth = 0) {
+/// 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,
+ 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
// 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.
- if (ConstantIntegral *CI = dyn_cast<ConstantIntegral>(V))
- return CI->getRawValue() & Mask;
+ if (ConstantIntegral *CI = dyn_cast<ConstantIntegral>(V)) {
+ // We know all of the bits for a constant!
+ KnownOne = CI->getZExtValue();
+ KnownZero = ~KnownOne & Mask;
+ return;
+ }
+
+ KnownZero = KnownOne = 0; // Don't know anything.
if (Depth == 6 || Mask == 0)
- return Mask; // Limit search depth.
-
+ return; // Limit search depth.
+
+ uint64_t KnownZero2, KnownOne2;
if (Instruction *I = dyn_cast<Instruction>(V)) {
switch (I->getOpcode()) {
case Instruction::And:
- // (X & C1) & C2 == 0 iff C1 & C2 == 0.
- if (ConstantIntegral *CI = dyn_cast<ConstantIntegral>(I->getOperand(1)))
- return ComputeMaskedNonZeroBits(I->getOperand(0),
- CI->getRawValue() & Mask, Depth+1);
- // If either the LHS or the RHS are MaskedValueIsZero, the result is zero.
- Mask = ComputeMaskedNonZeroBits(I->getOperand(1), Mask, Depth+1);
- Mask = ComputeMaskedNonZeroBits(I->getOperand(0), Mask, Depth+1);
- return Mask;
+ // 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:
- case Instruction::Xor:
- // Any non-zero bits in the LHS or RHS are potentially non-zero in the
- // result.
- return ComputeMaskedNonZeroBits(I->getOperand(1), Mask, Depth+1) |
- ComputeMaskedNonZeroBits(I->getOperand(0), Mask, Depth+1);
+ 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 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.
+ uint64_t 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:
- // Any non-zero bits in the T or F values are potentially non-zero in the
- // result.
- return ComputeMaskedNonZeroBits(I->getOperand(2), Mask, Depth+1) |
- ComputeMaskedNonZeroBits(I->getOperand(1), Mask, Depth+1);
+ 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::Cast: {
const Type *SrcTy = I->getOperand(0)->getType();
- if (SrcTy == Type::BoolTy)
- return ComputeMaskedNonZeroBits(I->getOperand(0), Mask & 1, Depth+1);
- if (!SrcTy->isInteger()) return Mask;
+ if (!SrcTy->isIntegral()) return;
- // (cast <ty> X to int) & C2 == 0 iff <ty> could not have contained C2.
- if (SrcTy->isUnsigned() || // Only handle zero ext/trunc/noop
- SrcTy->getPrimitiveSizeInBits() >=
- I->getType()->getPrimitiveSizeInBits()) {
- Mask &= SrcTy->getIntegralTypeMask();
- return ComputeMaskedNonZeroBits(I->getOperand(0), Mask, Depth+1);
+ // If this is an integer truncate or noop, just look in the input.
+ if (SrcTy->getPrimitiveSizeInBits() >=
+ I->getType()->getPrimitiveSizeInBits()) {
+ ComputeMaskedBits(I->getOperand(0), Mask, KnownZero, KnownOne, Depth+1);
+ return;
}
- // FIXME: handle sext casts.
- break;
+ // Sign or Zero extension. Compute the bits in the result that are not
+ // present in the input.
+ uint64_t NotIn = ~SrcTy->getIntegralTypeMask();
+ uint64_t NewBits = I->getType()->getIntegralTypeMask() & NotIn;
+
+ // Handle zero extension.
+ if (!SrcTy->isSigned()) {
+ Mask &= SrcTy->getIntegralTypeMask();
+ 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;
+ } else {
+ // Sign extension.
+ Mask &= SrcTy->getIntegralTypeMask();
+ 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.
+ uint64_t InSignBit = 1ULL << (SrcTy->getPrimitiveSizeInBits()-1);
+ if (KnownZero & InSignBit) { // Input sign bit known zero
+ KnownZero |= NewBits;
+ KnownOne &= ~NewBits;
+ } else if (KnownOne & InSignBit) { // 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 (ConstantUInt *SA = dyn_cast<ConstantUInt>(I->getOperand(1)))
- return ComputeMaskedNonZeroBits(I->getOperand(0),Mask >> SA->getValue(),
- Depth+1) << SA->getValue();
+ if (ConstantUInt *SA = dyn_cast<ConstantUInt>(I->getOperand(1))) {
+ Mask >> SA->getValue();
+ ComputeMaskedBits(I->getOperand(0), Mask, KnownZero, KnownOne, Depth+1);
+ assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
+ KnownZero <<= SA->getValue();
+ KnownOne <<= SA->getValue();
+ KnownZero |= (1ULL << SA->getValue())-1; // low bits known zero.
+ return;
+ }
break;
case Instruction::Shr:
// (ushr X, C1) & C2 == 0 iff (-1 >> C1) & C2 == 0
- if (ConstantUInt *SA = dyn_cast<ConstantUInt>(I->getOperand(1)))
- if (I->getType()->isUnsigned()) {
- Mask <<= SA->getValue();
- Mask &= I->getType()->getIntegralTypeMask();
- return ComputeMaskedNonZeroBits(I->getOperand(0), Mask, Depth+1)
- >> SA->getValue();
+ if (ConstantUInt *SA = dyn_cast<ConstantUInt>(I->getOperand(1))) {
+ // Compute the new bits that are at the top now.
+ uint64_t HighBits = (1ULL << SA->getValue())-1;
+ HighBits <<= I->getType()->getPrimitiveSizeInBits()-SA->getValue();
+
+ if (I->getType()->isUnsigned()) { // Unsigned shift right.
+ Mask << SA->getValue();
+ ComputeMaskedBits(I->getOperand(0), Mask, KnownZero,KnownOne,Depth+1);
+ assert((KnownZero & KnownOne) == 0&&"Bits known to be one AND zero?");
+ KnownZero >>= SA->getValue();
+ KnownOne >>= SA->getValue();
+ KnownZero |= HighBits; // high bits known zero.
+ } else {
+ Mask << SA->getValue();
+ ComputeMaskedBits(I->getOperand(0), Mask, KnownZero,KnownOne,Depth+1);
+ assert((KnownZero & KnownOne) == 0&&"Bits known to be one AND zero?");
+ KnownZero >>= SA->getValue();
+ KnownOne >>= SA->getValue();
+
+ // Handle the sign bits.
+ uint64_t SignBit = 1ULL << (I->getType()->getPrimitiveSizeInBits()-1);
+ SignBit >>= SA->getValue(); // Adjust to where it is now in the mask.
+
+ if (KnownZero & SignBit) { // New bits are known zero.
+ KnownZero |= HighBits;
+ } else if (KnownOne & SignBit) { // New bits are known one.
+ KnownOne |= HighBits;
+ }
}
+ return;
+ }
break;
}
}
-
- return Mask;
}
/// MaskedValueIsZero - Return true if 'V & Mask' is known to be zero. We use
/// this predicate to simplify operations downstream. Mask is known to be zero
/// for bits that V cannot have.
static bool MaskedValueIsZero(Value *V, uint64_t Mask, unsigned Depth = 0) {
- return ComputeMaskedNonZeroBits(V, Mask, Depth) == 0;
+ uint64_t KnownZero, KnownOne;
+ ComputeMaskedBits(V, Mask, KnownZero, KnownOne, Depth);
+ assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
+ return (KnownZero & Mask) == Mask;
}
/// SimplifyDemandedBits - Look at V. At this point, we know that only the Mask
@@ -879,8 +973,9 @@
}
if (Found) {
// This is a sign extend if the top bits are known zero.
- uint64_t Mask = XorLHS->getType()->getIntegralTypeMask();
+ uint64_t Mask = ~0ULL;
Mask <<= 64-(TySizeBits-Size);
+ Mask &= XorLHS->getType()->getIntegralTypeMask();
if (!MaskedValueIsZero(XorLHS, Mask))
Size = 0; // Not a sign ext, but can't be any others either.
goto FoundSExt;
@@ -1949,22 +2044,29 @@
// Figure out which of the input bits are not known to be zero, and which
// bits are known to be zero.
- uint64_t NonZeroBits = ComputeMaskedNonZeroBits(Op0, TypeMask);
- uint64_t ZeroBits = NonZeroBits^TypeMask;
+ uint64_t KnownZeroBits, KnownOneBits;
+ ComputeMaskedBits(Op0, TypeMask, KnownZeroBits, KnownOneBits);
// If the mask is not masking out any bits (i.e. all of the zeros in the
// mask are already known to be zero), there is no reason to do the and in
// the first place.
uint64_t NotAndRHS = AndRHSMask^TypeMask;
- if ((NotAndRHS & ZeroBits) == NotAndRHS)
+ if ((NotAndRHS & KnownZeroBits) == NotAndRHS)
return ReplaceInstUsesWith(I, Op0);
+ // If the AND'd bits are all known, turn this AND into a constant.
+ if ((AndRHSMask & (KnownOneBits|KnownZeroBits)) == AndRHSMask) {
+ Constant *NewRHS = ConstantUInt::get(Type::ULongTy,
+ AndRHSMask & KnownOneBits);
+ return ReplaceInstUsesWith(I, ConstantExpr::getCast(NewRHS, I.getType()));
+ }
+
// If the AND mask contains bits that are known zero, remove them. A
// special case is when there are no bits in common, in which case we
// implicitly turn this into an AND X, 0, which is later simplified into 0.
- if ((AndRHSMask & NonZeroBits) != AndRHSMask) {
+ if ((AndRHSMask & ~KnownZeroBits) != AndRHSMask) {
Constant *NewRHS =
- ConstantUInt::get(Type::ULongTy, AndRHSMask & NonZeroBits);
+ ConstantUInt::get(Type::ULongTy, AndRHSMask & ~KnownZeroBits);
I.setOperand(1, ConstantExpr::getCast(NewRHS, I.getType()));
return &I;
}
More information about the llvm-commits
mailing list