From: Dan Gohman Date: Sun, 24 May 2009 18:02:35 +0000 (+0000) Subject: When the low bits of one operand of an add are zero, that number X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=3925043af0ecf1f0a6158c5007c1186797a252cb;p=oota-llvm.git When the low bits of one operand of an add are zero, that number of low bits of the other operand are preserved in the output. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@72365 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Analysis/ValueTracking.cpp b/lib/Analysis/ValueTracking.cpp index 3c21e2039c1..29ff8aa4f4d 100644 --- a/lib/Analysis/ValueTracking.cpp +++ b/lib/Analysis/ValueTracking.cpp @@ -343,22 +343,43 @@ void llvm::ComputeMaskedBits(Value *V, const APInt &Mask, } // fall through case Instruction::Add: { - // Output known-0 bits are known if clear or set in both the low clear bits - // common to both LHS & RHS. For example, 8+(X<<3) is known to have the - // low 3 bits clear. - APInt Mask2 = APInt::getLowBitsSet(BitWidth, Mask.countTrailingOnes()); - ComputeMaskedBits(I->getOperand(0), Mask2, KnownZero2, KnownOne2, TD, + // If one of the operands has trailing zeros, than the bits that the + // other operand has in those bit positions will be preserved in the + // result. For an add, this works with either operand. For a subtract, + // this only works if the known zeros are in the right operand. + APInt LHSKnownZero(BitWidth, 0), LHSKnownOne(BitWidth, 0); + APInt Mask2 = APInt::getLowBitsSet(BitWidth, + BitWidth - Mask.countLeadingZeros()); + ComputeMaskedBits(I->getOperand(0), Mask2, LHSKnownZero, LHSKnownOne, TD, Depth+1); - assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?"); - unsigned KnownZeroOut = KnownZero2.countTrailingOnes(); + assert((LHSKnownZero & LHSKnownOne) == 0 && + "Bits known to be one AND zero?"); + unsigned LHSKnownZeroOut = LHSKnownZero.countTrailingOnes(); ComputeMaskedBits(I->getOperand(1), Mask2, KnownZero2, KnownOne2, TD, Depth+1); assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?"); - KnownZeroOut = std::min(KnownZeroOut, - KnownZero2.countTrailingOnes()); + unsigned RHSKnownZeroOut = KnownZero2.countTrailingOnes(); - KnownZero |= APInt::getLowBitsSet(BitWidth, KnownZeroOut); + // Determine which operand has more trailing zeros, and use that + // many bits from the other operand. + if (LHSKnownZeroOut > RHSKnownZeroOut) { + if (getOpcode(I) == Instruction::Add) { + APInt Mask = APInt::getLowBitsSet(BitWidth, LHSKnownZeroOut); + KnownZero |= KnownZero2 & Mask; + KnownOne |= KnownOne2 & Mask; + } else { + // If the known zeros are in the left operand for a subtract, + // fall back to the minimum known zeros in both operands. + KnownZero |= APInt::getLowBitsSet(BitWidth, + std::min(LHSKnownZeroOut, + RHSKnownZeroOut)); + } + } else if (RHSKnownZeroOut >= LHSKnownZeroOut) { + APInt Mask = APInt::getLowBitsSet(BitWidth, RHSKnownZeroOut); + KnownZero |= LHSKnownZero & Mask; + KnownOne |= LHSKnownOne & Mask; + } return; } case Instruction::SRem: