diff options
author | Craig Topper <craig.topper@intel.com> | 2017-08-08 16:29:35 +0000 |
---|---|---|
committer | Craig Topper <craig.topper@intel.com> | 2017-08-08 16:29:35 +0000 |
commit | b498a23f0e757e50e504b5b9591e69e605f4fc12 (patch) | |
tree | 017d7f34206b5d285afc56086f9a38f0f64aadfe /llvm/lib/Support/KnownBits.cpp | |
parent | 5a497136be8397ae18c5a83da064fb6b4f682aa3 (diff) | |
download | bcm5719-llvm-b498a23f0e757e50e504b5b9591e69e605f4fc12.tar.gz bcm5719-llvm-b498a23f0e757e50e504b5b9591e69e605f4fc12.zip |
[KnownBits][ValueTracking] Move the math for calculating known bits for add/sub into a static method in KnownBits object
I want to reuse this code in SimplifyDemandedBits handling of Add/Sub. This will make that easier.
Wonder if we should use it in SelectionDAG's computeKnownBits too.
Differential Revision: https://reviews.llvm.org/D36433
llvm-svn: 310378
Diffstat (limited to 'llvm/lib/Support/KnownBits.cpp')
-rw-r--r-- | llvm/lib/Support/KnownBits.cpp | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/llvm/lib/Support/KnownBits.cpp b/llvm/lib/Support/KnownBits.cpp new file mode 100644 index 00000000000..ac790ebed35 --- /dev/null +++ b/llvm/lib/Support/KnownBits.cpp @@ -0,0 +1,65 @@ +//===-- KnownBits.cpp - Stores known zeros/ones ---------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains a class for representing known zeros and ones used by +// computeKnownBits. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/KnownBits.h" + +using namespace llvm; + +KnownBits KnownBits::computeForAddSub(bool Add, bool NSW, + const KnownBits &LHS, KnownBits RHS) { + // Carry in a 1 for a subtract, rather than 0. + bool CarryIn = false; + if (!Add) { + // Sum = LHS + ~RHS + 1 + std::swap(RHS.Zero, RHS.One); + CarryIn = true; + } + + APInt PossibleSumZero = ~LHS.Zero + ~RHS.Zero + CarryIn; + APInt PossibleSumOne = LHS.One + RHS.One + CarryIn; + + // Compute known bits of the carry. + APInt CarryKnownZero = ~(PossibleSumZero ^ LHS.Zero ^ RHS.Zero); + APInt CarryKnownOne = PossibleSumOne ^ LHS.One ^ RHS.One; + + // Compute set of known bits (where all three relevant bits are known). + APInt LHSKnownUnion = LHS.Zero | LHS.One; + APInt RHSKnownUnion = RHS.Zero | RHS.One; + APInt CarryKnownUnion = std::move(CarryKnownZero) | CarryKnownOne; + APInt Known = std::move(LHSKnownUnion) & RHSKnownUnion & CarryKnownUnion; + + assert((PossibleSumZero & Known) == (PossibleSumOne & Known) && + "known bits of sum differ"); + + // Compute known bits of the result. + KnownBits KnownOut; + KnownOut.Zero = ~std::move(PossibleSumZero) & Known; + KnownOut.One = std::move(PossibleSumOne) & Known; + + // Are we still trying to solve for the sign bit? + if (!Known.isSignBitSet()) { + if (NSW) { + // Adding two non-negative numbers, or subtracting a negative number from + // a non-negative one, can't wrap into negative. + if (LHS.isNonNegative() && RHS.isNonNegative()) + KnownOut.makeNonNegative(); + // Adding two negative numbers, or subtracting a non-negative number from + // a negative one, can't wrap into non-negative. + else if (LHS.isNegative() && RHS.isNegative()) + KnownOut.makeNegative(); + } + } + + return KnownOut; +} |