diff options
author | Evgeny Stupachenko <evstupac@gmail.com> | 2016-08-24 23:01:33 +0000 |
---|---|---|
committer | Evgeny Stupachenko <evstupac@gmail.com> | 2016-08-24 23:01:33 +0000 |
commit | d7f9c3564a76fe827cce4f8d9849b001b9b915f6 (patch) | |
tree | df90c4ac7f2219caa0d5fb3e170a45790b562324 /llvm/lib/Analysis/ValueTracking.cpp | |
parent | b6cd5121b76d6ac2899412a2d0da5a9d5eb39c76 (diff) | |
download | llvm-d7f9c3564a76fe827cce4f8d9849b001b9b915f6.zip llvm-d7f9c3564a76fe827cce4f8d9849b001b9b915f6.tar.gz llvm-d7f9c3564a76fe827cce4f8d9849b001b9b915f6.tar.bz2 |
The patch improves ValueTracking on left shift with nsw flag.
Summary:
The patch fixes PR28946.
Reviewers: majnemer, sanjoy
Differential Revision: http://reviews.llvm.org/D23296
From: Li Huang
llvm-svn: 279684
Diffstat (limited to 'llvm/lib/Analysis/ValueTracking.cpp')
-rw-r--r-- | llvm/lib/Analysis/ValueTracking.cpp | 28 |
1 files changed, 23 insertions, 5 deletions
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index 7f62a26..e3ac4bb 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -795,6 +795,14 @@ static void computeKnownBitsFromShiftOperator( computeKnownBits(I->getOperand(0), KnownZero, KnownOne, Depth + 1, Q); KnownZero = KZF(KnownZero, ShiftAmt); KnownOne = KOF(KnownOne, ShiftAmt); + // If there is conflict between KnownZero and KnownOne, this must be an + // overflowing left shift, so the shift result is undefined. Clear KnownZero + // and KnownOne bits so that other code could propagate this undef. + if ((KnownZero & KnownOne) != 0) { + KnownZero.clearAllBits(); + KnownOne.clearAllBits(); + } + return; } @@ -1065,13 +1073,23 @@ static void computeKnownBitsFromOperator(const Operator *I, APInt &KnownZero, } case Instruction::Shl: { // (shl X, C1) & C2 == 0 iff (X & C2 >>u C1) == 0 - auto KZF = [BitWidth](const APInt &KnownZero, unsigned ShiftAmt) { - return (KnownZero << ShiftAmt) | - APInt::getLowBitsSet(BitWidth, ShiftAmt); // Low bits known 0. + bool NSW = cast<OverflowingBinaryOperator>(I)->hasNoSignedWrap(); + auto KZF = [BitWidth, NSW](const APInt &KnownZero, unsigned ShiftAmt) { + APInt KZResult = + (KnownZero << ShiftAmt) | + APInt::getLowBitsSet(BitWidth, ShiftAmt); // Low bits known 0. + // If this shift has "nsw" keyword, then the result is either a poison + // value or has the same sign bit as the first operand. + if (NSW && KnownZero.isNegative()) + KZResult.setBit(BitWidth - 1); + return KZResult; }; - auto KOF = [BitWidth](const APInt &KnownOne, unsigned ShiftAmt) { - return KnownOne << ShiftAmt; + auto KOF = [BitWidth, NSW](const APInt &KnownOne, unsigned ShiftAmt) { + APInt KOResult = KnownOne << ShiftAmt; + if (NSW && KnownOne.isNegative()) + KOResult.setBit(BitWidth - 1); + return KOResult; }; computeKnownBitsFromShiftOperator(I, KnownZero, KnownOne, |