Index: llvm/trunk/include/llvm/Support/KnownBits.h =================================================================== --- llvm/trunk/include/llvm/Support/KnownBits.h +++ llvm/trunk/include/llvm/Support/KnownBits.h @@ -193,6 +193,10 @@ unsigned countMaxPopulation() const { return getBitWidth() - Zero.countPopulation(); } + + /// Compute known bits resulting from adding LHS and RHS. + static KnownBits computeForAddSub(bool Add, bool NSW, const KnownBits &LHS, + KnownBits RHS); }; } // end namespace llvm Index: llvm/trunk/lib/Analysis/ValueTracking.cpp =================================================================== --- llvm/trunk/lib/Analysis/ValueTracking.cpp +++ llvm/trunk/lib/Analysis/ValueTracking.cpp @@ -275,47 +275,7 @@ computeKnownBits(Op0, LHSKnown, Depth + 1, Q); computeKnownBits(Op1, Known2, Depth + 1, Q); - // Carry in a 1 for a subtract, rather than a 0. - uint64_t CarryIn = 0; - if (!Add) { - // Sum = LHS + ~RHS + 1 - std::swap(Known2.Zero, Known2.One); - CarryIn = 1; - } - - APInt PossibleSumZero = ~LHSKnown.Zero + ~Known2.Zero + CarryIn; - APInt PossibleSumOne = LHSKnown.One + Known2.One + CarryIn; - - // Compute known bits of the carry. - APInt CarryKnownZero = ~(PossibleSumZero ^ LHSKnown.Zero ^ Known2.Zero); - APInt CarryKnownOne = PossibleSumOne ^ LHSKnown.One ^ Known2.One; - - // Compute set of known bits (where all three relevant bits are known). - APInt LHSKnownUnion = LHSKnown.Zero | LHSKnown.One; - APInt RHSKnownUnion = Known2.Zero | Known2.One; - APInt CarryKnownUnion = CarryKnownZero | CarryKnownOne; - APInt Known = LHSKnownUnion & RHSKnownUnion & CarryKnownUnion; - - assert((PossibleSumZero & Known) == (PossibleSumOne & Known) && - "known bits of sum differ"); - - // Compute known bits of the result. - KnownOut.Zero = ~PossibleSumOne & Known; - KnownOut.One = 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 (LHSKnown.isNonNegative() && Known2.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 (LHSKnown.isNegative() && Known2.isNegative()) - KnownOut.makeNegative(); - } - } + KnownOut = KnownBits::computeForAddSub(Add, NSW, LHSKnown, Known2); } static void computeKnownBitsMul(const Value *Op0, const Value *Op1, bool NSW, Index: llvm/trunk/lib/Support/CMakeLists.txt =================================================================== --- llvm/trunk/lib/Support/CMakeLists.txt +++ llvm/trunk/lib/Support/CMakeLists.txt @@ -71,6 +71,7 @@ IntEqClasses.cpp IntervalMap.cpp JamCRC.cpp + KnownBits.cpp LEB128.cpp LineIterator.cpp Locale.cpp Index: llvm/trunk/lib/Support/KnownBits.cpp =================================================================== --- llvm/trunk/lib/Support/KnownBits.cpp +++ llvm/trunk/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; +}