diff options
author | Nikita Popov <nikita.ppv@gmail.com> | 2019-02-28 08:11:20 +0000 |
---|---|---|
committer | Nikita Popov <nikita.ppv@gmail.com> | 2019-02-28 08:11:20 +0000 |
commit | 6c57395fb438881018e0897f09f2137dc8dbd111 (patch) | |
tree | 35f8da1b04f4e77d6e0271036c0f69911566b212 /llvm/lib/Analysis/ValueTracking.cpp | |
parent | 6ca7398a1e9481c950d60f2200b297fd9c2d67a7 (diff) | |
download | llvm-6c57395fb438881018e0897f09f2137dc8dbd111.zip llvm-6c57395fb438881018e0897f09f2137dc8dbd111.tar.gz llvm-6c57395fb438881018e0897f09f2137dc8dbd111.tar.bz2 |
[ValueTracking] More accurate unsigned add overflow detection
Part of D58593.
Compute precise overflow conditions based on all known bits, rather
than just the sign bits. Unsigned a + b overflows iff a > ~b, and we
can determine whether this always/never happens based on the minimal
and maximal values achievable for a and ~b subject to the known bits
constraint.
llvm-svn: 355072
Diffstat (limited to 'llvm/lib/Analysis/ValueTracking.cpp')
-rw-r--r-- | llvm/lib/Analysis/ValueTracking.cpp | 24 |
1 files changed, 10 insertions, 14 deletions
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index deb2fb9..80a08e2 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -4044,21 +4044,17 @@ OverflowResult llvm::computeOverflowForUnsignedAdd( bool UseInstrInfo) { KnownBits LHSKnown = computeKnownBits(LHS, DL, /*Depth=*/0, AC, CxtI, DT, nullptr, UseInstrInfo); - if (LHSKnown.isNonNegative() || LHSKnown.isNegative()) { - KnownBits RHSKnown = computeKnownBits(RHS, DL, /*Depth=*/0, AC, CxtI, DT, - nullptr, UseInstrInfo); - - if (LHSKnown.isNegative() && RHSKnown.isNegative()) { - // The sign bit is set in both cases: this MUST overflow. - return OverflowResult::AlwaysOverflows; - } - - if (LHSKnown.isNonNegative() && RHSKnown.isNonNegative()) { - // The sign bit is clear in both cases: this CANNOT overflow. - return OverflowResult::NeverOverflows; - } - } + KnownBits RHSKnown = computeKnownBits(RHS, DL, /*Depth=*/0, AC, CxtI, DT, + nullptr, UseInstrInfo); + // a + b overflows iff a > ~b. Determine whether this is never/always true + // based on the min/max values achievable under the known bits constraint. + APInt MinLHS = LHSKnown.One, MaxLHS = ~LHSKnown.Zero; + APInt MinInvRHS = RHSKnown.Zero, MaxInvRHS = ~RHSKnown.One; + if (MaxLHS.ule(MinInvRHS)) + return OverflowResult::NeverOverflows; + if (MinLHS.ugt(MaxInvRHS)) + return OverflowResult::AlwaysOverflows; return OverflowResult::MayOverflow; } |