#ifndef LLVM_SUPPORT_KNOWNBITS_H
#define LLVM_SUPPORT_KNOWNBITS_H
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/Optional.h"
namespace llvm {
struct KnownBits {
APInt Zero;
APInt One;
private:
KnownBits(APInt Zero, APInt One)
: Zero(std::move(Zero)), One(std::move(One)) {}
public:
KnownBits() = default;
KnownBits(unsigned BitWidth) : Zero(BitWidth, 0), One(BitWidth, 0) {}
unsigned getBitWidth() const {
assert(Zero.getBitWidth() == One.getBitWidth() &&
"Zero and One should have the same width!");
return Zero.getBitWidth();
}
bool hasConflict() const { return Zero.intersects(One); }
bool isConstant() const {
assert(!hasConflict() && "KnownBits conflict!");
return Zero.countPopulation() + One.countPopulation() == getBitWidth();
}
const APInt &getConstant() const {
assert(isConstant() && "Can only get value when all bits are known");
return One;
}
bool isUnknown() const { return Zero.isZero() && One.isZero(); }
void resetAll() {
Zero.clearAllBits();
One.clearAllBits();
}
bool isZero() const {
assert(!hasConflict() && "KnownBits conflict!");
return Zero.isAllOnes();
}
bool isAllOnes() const {
assert(!hasConflict() && "KnownBits conflict!");
return One.isAllOnes();
}
void setAllZero() {
Zero.setAllBits();
One.clearAllBits();
}
void setAllOnes() {
Zero.clearAllBits();
One.setAllBits();
}
bool isNegative() const { return One.isSignBitSet(); }
bool isNonNegative() const { return Zero.isSignBitSet(); }
bool isNonZero() const { return !One.isZero(); }
bool isStrictlyPositive() const {
return Zero.isSignBitSet() && !One.isZero();
}
void makeNegative() {
One.setSignBit();
}
void makeNonNegative() {
Zero.setSignBit();
}
APInt getMinValue() const {
return One;
}
APInt getSignedMinValue() const {
APInt Min = One;
if (Zero.isSignBitClear())
Min.setSignBit();
return Min;
}
APInt getMaxValue() const {
return ~Zero;
}
APInt getSignedMaxValue() const {
APInt Max = ~Zero;
if (One.isSignBitClear())
Max.clearSignBit();
return Max;
}
KnownBits trunc(unsigned BitWidth) const {
return KnownBits(Zero.trunc(BitWidth), One.trunc(BitWidth));
}
KnownBits anyext(unsigned BitWidth) const {
return KnownBits(Zero.zext(BitWidth), One.zext(BitWidth));
}
KnownBits zext(unsigned BitWidth) const {
unsigned OldBitWidth = getBitWidth();
APInt NewZero = Zero.zext(BitWidth);
NewZero.setBitsFrom(OldBitWidth);
return KnownBits(NewZero, One.zext(BitWidth));
}
KnownBits sext(unsigned BitWidth) const {
return KnownBits(Zero.sext(BitWidth), One.sext(BitWidth));
}
KnownBits anyextOrTrunc(unsigned BitWidth) const {
if (BitWidth > getBitWidth())
return anyext(BitWidth);
if (BitWidth < getBitWidth())
return trunc(BitWidth);
return *this;
}
KnownBits zextOrTrunc(unsigned BitWidth) const {
if (BitWidth > getBitWidth())
return zext(BitWidth);
if (BitWidth < getBitWidth())
return trunc(BitWidth);
return *this;
}
KnownBits sextOrTrunc(unsigned BitWidth) const {
if (BitWidth > getBitWidth())
return sext(BitWidth);
if (BitWidth < getBitWidth())
return trunc(BitWidth);
return *this;
}
KnownBits sextInReg(unsigned SrcBitWidth) const;
void insertBits(const KnownBits &SubBits, unsigned BitPosition) {
Zero.insertBits(SubBits.Zero, BitPosition);
One.insertBits(SubBits.One, BitPosition);
}
KnownBits extractBits(unsigned NumBits, unsigned BitPosition) const {
return KnownBits(Zero.extractBits(NumBits, BitPosition),
One.extractBits(NumBits, BitPosition));
}
KnownBits makeGE(const APInt &Val) const;
unsigned countMinTrailingZeros() const {
return Zero.countTrailingOnes();
}
unsigned countMinTrailingOnes() const {
return One.countTrailingOnes();
}
unsigned countMinLeadingZeros() const {
return Zero.countLeadingOnes();
}
unsigned countMinLeadingOnes() const {
return One.countLeadingOnes();
}
unsigned countMinSignBits() const {
if (isNonNegative())
return countMinLeadingZeros();
if (isNegative())
return countMinLeadingOnes();
return 1;
}
unsigned countMaxSignificantBits() const {
return getBitWidth() - countMinSignBits() + 1;
}
unsigned countMaxTrailingZeros() const {
return One.countTrailingZeros();
}
unsigned countMaxTrailingOnes() const {
return Zero.countTrailingZeros();
}
unsigned countMaxLeadingZeros() const {
return One.countLeadingZeros();
}
unsigned countMaxLeadingOnes() const {
return Zero.countLeadingZeros();
}
unsigned countMinPopulation() const {
return One.countPopulation();
}
unsigned countMaxPopulation() const {
return getBitWidth() - Zero.countPopulation();
}
unsigned countMaxActiveBits() const {
return getBitWidth() - countMinLeadingZeros();
}
static KnownBits makeConstant(const APInt &C) {
return KnownBits(~C, C);
}
static KnownBits commonBits(const KnownBits &LHS, const KnownBits &RHS) {
return KnownBits(LHS.Zero & RHS.Zero, LHS.One & RHS.One);
}
static bool haveNoCommonBitsSet(const KnownBits &LHS, const KnownBits &RHS) {
return (LHS.Zero | RHS.Zero).isAllOnes();
}
static KnownBits computeForAddCarry(
const KnownBits &LHS, const KnownBits &RHS, const KnownBits &Carry);
static KnownBits computeForAddSub(bool Add, bool NSW, const KnownBits &LHS,
KnownBits RHS);
static KnownBits mul(const KnownBits &LHS, const KnownBits &RHS,
bool NoUndefSelfMultiply = false);
static KnownBits mulhs(const KnownBits &LHS, const KnownBits &RHS);
static KnownBits mulhu(const KnownBits &LHS, const KnownBits &RHS);
static KnownBits udiv(const KnownBits &LHS, const KnownBits &RHS);
static KnownBits urem(const KnownBits &LHS, const KnownBits &RHS);
static KnownBits srem(const KnownBits &LHS, const KnownBits &RHS);
static KnownBits umax(const KnownBits &LHS, const KnownBits &RHS);
static KnownBits umin(const KnownBits &LHS, const KnownBits &RHS);
static KnownBits smax(const KnownBits &LHS, const KnownBits &RHS);
static KnownBits smin(const KnownBits &LHS, const KnownBits &RHS);
static KnownBits shl(const KnownBits &LHS, const KnownBits &RHS);
static KnownBits lshr(const KnownBits &LHS, const KnownBits &RHS);
static KnownBits ashr(const KnownBits &LHS, const KnownBits &RHS);
static Optional<bool> eq(const KnownBits &LHS, const KnownBits &RHS);
static Optional<bool> ne(const KnownBits &LHS, const KnownBits &RHS);
static Optional<bool> ugt(const KnownBits &LHS, const KnownBits &RHS);
static Optional<bool> uge(const KnownBits &LHS, const KnownBits &RHS);
static Optional<bool> ult(const KnownBits &LHS, const KnownBits &RHS);
static Optional<bool> ule(const KnownBits &LHS, const KnownBits &RHS);
static Optional<bool> sgt(const KnownBits &LHS, const KnownBits &RHS);
static Optional<bool> sge(const KnownBits &LHS, const KnownBits &RHS);
static Optional<bool> slt(const KnownBits &LHS, const KnownBits &RHS);
static Optional<bool> sle(const KnownBits &LHS, const KnownBits &RHS);
KnownBits &operator&=(const KnownBits &RHS);
KnownBits &operator|=(const KnownBits &RHS);
KnownBits &operator^=(const KnownBits &RHS);
KnownBits abs(bool IntMinIsPoison = false) const;
KnownBits byteSwap() {
return KnownBits(Zero.byteSwap(), One.byteSwap());
}
KnownBits reverseBits() {
return KnownBits(Zero.reverseBits(), One.reverseBits());
}
bool operator==(const KnownBits &Other) const {
return Zero == Other.Zero && One == Other.One;
}
bool operator!=(const KnownBits &Other) const { return !(*this == Other); }
void print(raw_ostream &OS) const;
void dump() const;
};
inline KnownBits operator&(KnownBits LHS, const KnownBits &RHS) {
LHS &= RHS;
return LHS;
}
inline KnownBits operator&(const KnownBits &LHS, KnownBits &&RHS) {
RHS &= LHS;
return std::move(RHS);
}
inline KnownBits operator|(KnownBits LHS, const KnownBits &RHS) {
LHS |= RHS;
return LHS;
}
inline KnownBits operator|(const KnownBits &LHS, KnownBits &&RHS) {
RHS |= LHS;
return std::move(RHS);
}
inline KnownBits operator^(KnownBits LHS, const KnownBits &RHS) {
LHS ^= RHS;
return LHS;
}
inline KnownBits operator^(const KnownBits &LHS, KnownBits &&RHS) {
RHS ^= LHS;
return std::move(RHS);
}
}
#endif