123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478 |
- #pragma once
- #ifdef __GNUC__
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wunused-parameter"
- #endif
- //===- 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
- #ifdef __GNUC__
- #pragma GCC diagnostic pop
- #endif
|