//===- llvm/Support/KnownBits.h - Stores known zeros/ones -------*- C++ -*-===//
 
//
 
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 
// See https://llvm.org/LICENSE.txt for license information.
 
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 
//
 
//===----------------------------------------------------------------------===//
 
//
 
// This file contains a class for representing known zeros and ones used by
 
// computeKnownBits.
 
//
 
//===----------------------------------------------------------------------===//
 
 
 
#ifndef LLVM_SUPPORT_KNOWNBITS_H
 
#define LLVM_SUPPORT_KNOWNBITS_H
 
 
 
#include "llvm/ADT/APInt.h"
 
#include <optional>
 
 
 
namespace llvm {
 
 
 
// Struct for tracking the known zeros and ones of a value.
 
struct KnownBits {
 
  APInt Zero;
 
  APInt One;
 
 
 
private:
 
  // Internal constructor for creating a KnownBits from two APInts.
 
  KnownBits(APInt Zero, APInt One)
 
      : Zero(std::move(Zero)), One(std::move(One)) {}
 
 
 
public:
 
  // Default construct Zero and One.
 
  KnownBits() = default;
 
 
 
  /// Create a known bits object of BitWidth bits initialized to unknown.
 
  KnownBits(unsigned BitWidth) : Zero(BitWidth, 0), One(BitWidth, 0) {}
 
 
 
  /// Get the bit width of this value.
 
  unsigned getBitWidth() const {
 
    assert(Zero.getBitWidth() == One.getBitWidth() &&
 
           "Zero and One should have the same width!");
 
    return Zero.getBitWidth();
 
  }
 
 
 
  /// Returns true if there is conflicting information.
 
  bool hasConflict() const { return Zero.intersects(One); }
 
 
 
  /// Returns true if we know the value of all bits.
 
  bool isConstant() const {
 
    assert(!hasConflict() && "KnownBits conflict!");
 
    return Zero.countPopulation() + One.countPopulation() == getBitWidth();
 
  }
 
 
 
  /// Returns the value when all bits have a known value. This just returns One
 
  /// with a protective assertion.
 
  const APInt &getConstant() const {
 
    assert(isConstant() && "Can only get value when all bits are known");
 
    return One;
 
  }
 
 
 
  /// Returns true if we don't know any bits.
 
  bool isUnknown() const { return Zero.isZero() && One.isZero(); }
 
 
 
  /// Resets the known state of all bits.
 
  void resetAll() {
 
    Zero.clearAllBits();
 
    One.clearAllBits();
 
  }
 
 
 
  /// Returns true if value is all zero.
 
  bool isZero() const {
 
    assert(!hasConflict() && "KnownBits conflict!");
 
    return Zero.isAllOnes();
 
  }
 
 
 
  /// Returns true if value is all one bits.
 
  bool isAllOnes() const {
 
    assert(!hasConflict() && "KnownBits conflict!");
 
    return One.isAllOnes();
 
  }
 
 
 
  /// Make all bits known to be zero and discard any previous information.
 
  void setAllZero() {
 
    Zero.setAllBits();
 
    One.clearAllBits();
 
  }
 
 
 
  /// Make all bits known to be one and discard any previous information.
 
  void setAllOnes() {
 
    Zero.clearAllBits();
 
    One.setAllBits();
 
  }
 
 
 
  /// Returns true if this value is known to be negative.
 
  bool isNegative() const { return One.isSignBitSet(); }
 
 
 
  /// Returns true if this value is known to be non-negative.
 
  bool isNonNegative() const { return Zero.isSignBitSet(); }
 
 
 
  /// Returns true if this value is known to be non-zero.
 
  bool isNonZero() const { return !One.isZero(); }
 
 
 
  /// Returns true if this value is known to be positive.
 
  bool isStrictlyPositive() const {
 
    return Zero.isSignBitSet() && !One.isZero();
 
  }
 
 
 
  /// Make this value negative.
 
  void makeNegative() {
 
    One.setSignBit();
 
  }
 
 
 
  /// Make this value non-negative.
 
  void makeNonNegative() {
 
    Zero.setSignBit();
 
  }
 
 
 
  /// Return the minimal unsigned value possible given these KnownBits.
 
  APInt getMinValue() const {
 
    // Assume that all bits that aren't known-ones are zeros.
 
    return One;
 
  }
 
 
 
  /// Return the minimal signed value possible given these KnownBits.
 
  APInt getSignedMinValue() const {
 
    // Assume that all bits that aren't known-ones are zeros.
 
    APInt Min = One;
 
    // Sign bit is unknown.
 
    if (Zero.isSignBitClear())
 
      Min.setSignBit();
 
    return Min;
 
  }
 
 
 
  /// Return the maximal unsigned value possible given these KnownBits.
 
  APInt getMaxValue() const {
 
    // Assume that all bits that aren't known-zeros are ones.
 
    return ~Zero;
 
  }
 
 
 
  /// Return the maximal signed value possible given these KnownBits.
 
  APInt getSignedMaxValue() const {
 
    // Assume that all bits that aren't known-zeros are ones.
 
    APInt Max = ~Zero;
 
    // Sign bit is unknown.
 
    if (One.isSignBitClear())
 
      Max.clearSignBit();
 
    return Max;
 
  }
 
 
 
  /// Return known bits for a truncation of the value we're tracking.
 
  KnownBits trunc(unsigned BitWidth) const {
 
    return KnownBits(Zero.trunc(BitWidth), One.trunc(BitWidth));
 
  }
 
 
 
  /// Return known bits for an "any" extension of the value we're tracking,
 
  /// where we don't know anything about the extended bits.
 
  KnownBits anyext(unsigned BitWidth) const {
 
    return KnownBits(Zero.zext(BitWidth), One.zext(BitWidth));
 
  }
 
 
 
  /// Return known bits for a zero extension of the value we're tracking.
 
  KnownBits zext(unsigned BitWidth) const {
 
    unsigned OldBitWidth = getBitWidth();
 
    APInt NewZero = Zero.zext(BitWidth);
 
    NewZero.setBitsFrom(OldBitWidth);
 
    return KnownBits(NewZero, One.zext(BitWidth));
 
  }
 
 
 
  /// Return known bits for a sign extension of the value we're tracking.
 
  KnownBits sext(unsigned BitWidth) const {
 
    return KnownBits(Zero.sext(BitWidth), One.sext(BitWidth));
 
  }
 
 
 
  /// Return known bits for an "any" extension or truncation of the value we're
 
  /// tracking.
 
  KnownBits anyextOrTrunc(unsigned BitWidth) const {
 
    if (BitWidth > getBitWidth())
 
      return anyext(BitWidth);
 
    if (BitWidth < getBitWidth())
 
      return trunc(BitWidth);
 
    return *this;
 
  }
 
 
 
  /// Return known bits for a zero extension or truncation of the value we're
 
  /// tracking.
 
  KnownBits zextOrTrunc(unsigned BitWidth) const {
 
    if (BitWidth > getBitWidth())
 
      return zext(BitWidth);
 
    if (BitWidth < getBitWidth())
 
      return trunc(BitWidth);
 
    return *this;
 
  }
 
 
 
  /// Return known bits for a sign extension or truncation of the value we're
 
  /// tracking.
 
  KnownBits sextOrTrunc(unsigned BitWidth) const {
 
    if (BitWidth > getBitWidth())
 
      return sext(BitWidth);
 
    if (BitWidth < getBitWidth())
 
      return trunc(BitWidth);
 
    return *this;
 
  }
 
 
 
  /// Return known bits for a in-register sign extension of the value we're
 
  /// tracking.
 
  KnownBits sextInReg(unsigned SrcBitWidth) const;
 
 
 
  /// Insert the bits from a smaller known bits starting at bitPosition.
 
  void insertBits(const KnownBits &SubBits, unsigned BitPosition) {
 
    Zero.insertBits(SubBits.Zero, BitPosition);
 
    One.insertBits(SubBits.One, BitPosition);
 
  }
 
 
 
  /// Return a subset of the known bits from [bitPosition,bitPosition+numBits).
 
  KnownBits extractBits(unsigned NumBits, unsigned BitPosition) const {
 
    return KnownBits(Zero.extractBits(NumBits, BitPosition),
 
                     One.extractBits(NumBits, BitPosition));
 
  }
 
 
 
  /// Concatenate the bits from \p Lo onto the bottom of *this.  This is
 
  /// equivalent to:
 
  ///   (this->zext(NewWidth) << Lo.getBitWidth()) | Lo.zext(NewWidth)
 
  KnownBits concat(const KnownBits &Lo) const {
 
    return KnownBits(Zero.concat(Lo.Zero), One.concat(Lo.One));
 
  }
 
 
 
  /// Return KnownBits based on this, but updated given that the underlying
 
  /// value is known to be greater than or equal to Val.
 
  KnownBits makeGE(const APInt &Val) const;
 
 
 
  /// Returns the minimum number of trailing zero bits.
 
  unsigned countMinTrailingZeros() const {
 
    return Zero.countTrailingOnes();
 
  }
 
 
 
  /// Returns the minimum number of trailing one bits.
 
  unsigned countMinTrailingOnes() const {
 
    return One.countTrailingOnes();
 
  }
 
 
 
  /// Returns the minimum number of leading zero bits.
 
  unsigned countMinLeadingZeros() const {
 
    return Zero.countLeadingOnes();
 
  }
 
 
 
  /// Returns the minimum number of leading one bits.
 
  unsigned countMinLeadingOnes() const {
 
    return One.countLeadingOnes();
 
  }
 
 
 
  /// Returns the number of times the sign bit is replicated into the other
 
  /// bits.
 
  unsigned countMinSignBits() const {
 
    if (isNonNegative())
 
      return countMinLeadingZeros();
 
    if (isNegative())
 
      return countMinLeadingOnes();
 
    // Every value has at least 1 sign bit.
 
    return 1;
 
  }
 
 
 
  /// Returns the maximum number of bits needed to represent all possible
 
  /// signed values with these known bits. This is the inverse of the minimum
 
  /// number of known sign bits. Examples for bitwidth 5:
 
  /// 110?? --> 4
 
  /// 0000? --> 2
 
  unsigned countMaxSignificantBits() const {
 
    return getBitWidth() - countMinSignBits() + 1;
 
  }
 
 
 
  /// Returns the maximum number of trailing zero bits possible.
 
  unsigned countMaxTrailingZeros() const {
 
    return One.countTrailingZeros();
 
  }
 
 
 
  /// Returns the maximum number of trailing one bits possible.
 
  unsigned countMaxTrailingOnes() const {
 
    return Zero.countTrailingZeros();
 
  }
 
 
 
  /// Returns the maximum number of leading zero bits possible.
 
  unsigned countMaxLeadingZeros() const {
 
    return One.countLeadingZeros();
 
  }
 
 
 
  /// Returns the maximum number of leading one bits possible.
 
  unsigned countMaxLeadingOnes() const {
 
    return Zero.countLeadingZeros();
 
  }
 
 
 
  /// Returns the number of bits known to be one.
 
  unsigned countMinPopulation() const {
 
    return One.countPopulation();
 
  }
 
 
 
  /// Returns the maximum number of bits that could be one.
 
  unsigned countMaxPopulation() const {
 
    return getBitWidth() - Zero.countPopulation();
 
  }
 
 
 
  /// Returns the maximum number of bits needed to represent all possible
 
  /// unsigned values with these known bits. This is the inverse of the
 
  /// minimum number of leading zeros.
 
  unsigned countMaxActiveBits() const {
 
    return getBitWidth() - countMinLeadingZeros();
 
  }
 
 
 
  /// Create known bits from a known constant.
 
  static KnownBits makeConstant(const APInt &C) {
 
    return KnownBits(~C, C);
 
  }
 
 
 
  /// Compute known bits common to LHS and RHS.
 
  static KnownBits commonBits(const KnownBits &LHS, const KnownBits &RHS) {
 
    return KnownBits(LHS.Zero & RHS.Zero, LHS.One & RHS.One);
 
  }
 
 
 
  /// Return true if LHS and RHS have no common bits set.
 
  static bool haveNoCommonBitsSet(const KnownBits &LHS, const KnownBits &RHS) {
 
    return (LHS.Zero | RHS.Zero).isAllOnes();
 
  }
 
 
 
  /// Compute known bits resulting from adding LHS, RHS and a 1-bit Carry.
 
  static KnownBits computeForAddCarry(
 
      const KnownBits &LHS, const KnownBits &RHS, const KnownBits &Carry);
 
 
 
  /// Compute known bits resulting from adding LHS and RHS.
 
  static KnownBits computeForAddSub(bool Add, bool NSW, const KnownBits &LHS,
 
                                    KnownBits RHS);
 
 
 
  /// Compute known bits resulting from multiplying LHS and RHS.
 
  static KnownBits mul(const KnownBits &LHS, const KnownBits &RHS,
 
                       bool NoUndefSelfMultiply = false);
 
 
 
  /// Compute known bits from sign-extended multiply-hi.
 
  static KnownBits mulhs(const KnownBits &LHS, const KnownBits &RHS);
 
 
 
  /// Compute known bits from zero-extended multiply-hi.
 
  static KnownBits mulhu(const KnownBits &LHS, const KnownBits &RHS);
 
 
 
  /// Compute known bits for udiv(LHS, RHS).
 
  static KnownBits udiv(const KnownBits &LHS, const KnownBits &RHS);
 
 
 
  /// Compute known bits for urem(LHS, RHS).
 
  static KnownBits urem(const KnownBits &LHS, const KnownBits &RHS);
 
 
 
  /// Compute known bits for srem(LHS, RHS).
 
  static KnownBits srem(const KnownBits &LHS, const KnownBits &RHS);
 
 
 
  /// Compute known bits for umax(LHS, RHS).
 
  static KnownBits umax(const KnownBits &LHS, const KnownBits &RHS);
 
 
 
  /// Compute known bits for umin(LHS, RHS).
 
  static KnownBits umin(const KnownBits &LHS, const KnownBits &RHS);
 
 
 
  /// Compute known bits for smax(LHS, RHS).
 
  static KnownBits smax(const KnownBits &LHS, const KnownBits &RHS);
 
 
 
  /// Compute known bits for smin(LHS, RHS).
 
  static KnownBits smin(const KnownBits &LHS, const KnownBits &RHS);
 
 
 
  /// Compute known bits for shl(LHS, RHS).
 
  /// NOTE: RHS (shift amount) bitwidth doesn't need to be the same as LHS.
 
  static KnownBits shl(const KnownBits &LHS, const KnownBits &RHS);
 
 
 
  /// Compute known bits for lshr(LHS, RHS).
 
  /// NOTE: RHS (shift amount) bitwidth doesn't need to be the same as LHS.
 
  static KnownBits lshr(const KnownBits &LHS, const KnownBits &RHS);
 
 
 
  /// Compute known bits for ashr(LHS, RHS).
 
  /// NOTE: RHS (shift amount) bitwidth doesn't need to be the same as LHS.
 
  static KnownBits ashr(const KnownBits &LHS, const KnownBits &RHS);
 
 
 
  /// Determine if these known bits always give the same ICMP_EQ result.
 
  static std::optional<bool> eq(const KnownBits &LHS, const KnownBits &RHS);
 
 
 
  /// Determine if these known bits always give the same ICMP_NE result.
 
  static std::optional<bool> ne(const KnownBits &LHS, const KnownBits &RHS);
 
 
 
  /// Determine if these known bits always give the same ICMP_UGT result.
 
  static std::optional<bool> ugt(const KnownBits &LHS, const KnownBits &RHS);
 
 
 
  /// Determine if these known bits always give the same ICMP_UGE result.
 
  static std::optional<bool> uge(const KnownBits &LHS, const KnownBits &RHS);
 
 
 
  /// Determine if these known bits always give the same ICMP_ULT result.
 
  static std::optional<bool> ult(const KnownBits &LHS, const KnownBits &RHS);
 
 
 
  /// Determine if these known bits always give the same ICMP_ULE result.
 
  static std::optional<bool> ule(const KnownBits &LHS, const KnownBits &RHS);
 
 
 
  /// Determine if these known bits always give the same ICMP_SGT result.
 
  static std::optional<bool> sgt(const KnownBits &LHS, const KnownBits &RHS);
 
 
 
  /// Determine if these known bits always give the same ICMP_SGE result.
 
  static std::optional<bool> sge(const KnownBits &LHS, const KnownBits &RHS);
 
 
 
  /// Determine if these known bits always give the same ICMP_SLT result.
 
  static std::optional<bool> slt(const KnownBits &LHS, const KnownBits &RHS);
 
 
 
  /// Determine if these known bits always give the same ICMP_SLE result.
 
  static std::optional<bool> sle(const KnownBits &LHS, const KnownBits &RHS);
 
 
 
  /// Update known bits based on ANDing with RHS.
 
  KnownBits &operator&=(const KnownBits &RHS);
 
 
 
  /// Update known bits based on ORing with RHS.
 
  KnownBits &operator|=(const KnownBits &RHS);
 
 
 
  /// Update known bits based on XORing with RHS.
 
  KnownBits &operator^=(const KnownBits &RHS);
 
 
 
  /// Compute known bits for the absolute value.
 
  KnownBits abs(bool IntMinIsPoison = false) const;
 
 
 
  KnownBits byteSwap() const {
 
    return KnownBits(Zero.byteSwap(), One.byteSwap());
 
  }
 
 
 
  KnownBits reverseBits() const {
 
    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);
 
}
 
 
 
} // end namespace llvm
 
 
 
#endif