Home | History | Annotate | Download | only in IR
      1 //===- ConstantRange.h - Represent a range ----------------------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // Represent a range of possible values that may occur when the program is run
     11 // for an integral value.  This keeps track of a lower and upper bound for the
     12 // constant, which MAY wrap around the end of the numeric range.  To do this, it
     13 // keeps track of a [lower, upper) bound, which specifies an interval just like
     14 // STL iterators.  When used with boolean values, the following are important
     15 // ranges: :
     16 //
     17 //  [F, F) = {}     = Empty set
     18 //  [T, F) = {T}
     19 //  [F, T) = {F}
     20 //  [T, T) = {F, T} = Full set
     21 //
     22 // The other integral ranges use min/max values for special range values. For
     23 // example, for 8-bit types, it uses:
     24 // [0, 0)     = {}       = Empty set
     25 // [255, 255) = {0..255} = Full Set
     26 //
     27 // Note that ConstantRange can be used to represent either signed or
     28 // unsigned ranges.
     29 //
     30 //===----------------------------------------------------------------------===//
     31 
     32 #ifndef LLVM_IR_CONSTANTRANGE_H
     33 #define LLVM_IR_CONSTANTRANGE_H
     34 
     35 #include "llvm/ADT/APInt.h"
     36 #include "llvm/IR/InstrTypes.h"
     37 #include "llvm/Support/DataTypes.h"
     38 
     39 namespace llvm {
     40 
     41 /// This class represents a range of values.
     42 ///
     43 class ConstantRange {
     44   APInt Lower, Upper;
     45 
     46   // If we have move semantics, pass APInts by value and move them into place.
     47   typedef APInt APIntMoveTy;
     48 
     49 public:
     50   /// Initialize a full (the default) or empty set for the specified bit width.
     51   ///
     52   explicit ConstantRange(uint32_t BitWidth, bool isFullSet = true);
     53 
     54   /// Initialize a range to hold the single specified value.
     55   ///
     56   ConstantRange(APIntMoveTy Value);
     57 
     58   /// @brief Initialize a range of values explicitly. This will assert out if
     59   /// Lower==Upper and Lower != Min or Max value for its type. It will also
     60   /// assert out if the two APInt's are not the same bit width.
     61   ConstantRange(APIntMoveTy Lower, APIntMoveTy Upper);
     62 
     63   /// Produce the smallest range such that all values that may satisfy the given
     64   /// predicate with any value contained within Other is contained in the
     65   /// returned range.  Formally, this returns a superset of
     66   /// 'union over all y in Other . { x : icmp op x y is true }'.  If the exact
     67   /// answer is not representable as a ConstantRange, the return value will be a
     68   /// proper superset of the above.
     69   ///
     70   /// Example: Pred = ult and Other = i8 [2, 5) returns Result = [0, 4)
     71   static ConstantRange makeAllowedICmpRegion(CmpInst::Predicate Pred,
     72                                              const ConstantRange &Other);
     73 
     74   /// Produce the largest range such that all values in the returned range
     75   /// satisfy the given predicate with all values contained within Other.
     76   /// Formally, this returns a subset of
     77   /// 'intersection over all y in Other . { x : icmp op x y is true }'.  If the
     78   /// exact answer is not representable as a ConstantRange, the return value
     79   /// will be a proper subset of the above.
     80   ///
     81   /// Example: Pred = ult and Other = i8 [2, 5) returns [0, 2)
     82   static ConstantRange makeSatisfyingICmpRegion(CmpInst::Predicate Pred,
     83                                                 const ConstantRange &Other);
     84 
     85   /// Return the largest range containing all X such that "X BinOpC C" does not
     86   /// wrap (overflow).
     87   ///
     88   /// Example:
     89   ///  typedef OverflowingBinaryOperator OBO;
     90   ///  makeNoWrapRegion(Add, i8 1, OBO::NoSignedWrap) == [-128, 127)
     91   ///  makeNoWrapRegion(Add, i8 1, OBO::NoUnsignedWrap) == [0, -1)
     92   ///  makeNoWrapRegion(Add, i8 0, OBO::NoUnsignedWrap) == Full Set
     93   static ConstantRange makeNoWrapRegion(Instruction::BinaryOps BinOp,
     94                                         const APInt &C, unsigned NoWrapKind);
     95 
     96   /// Return the lower value for this range.
     97   ///
     98   const APInt &getLower() const { return Lower; }
     99 
    100   /// Return the upper value for this range.
    101   ///
    102   const APInt &getUpper() const { return Upper; }
    103 
    104   /// Get the bit width of this ConstantRange.
    105   ///
    106   uint32_t getBitWidth() const { return Lower.getBitWidth(); }
    107 
    108   /// Return true if this set contains all of the elements possible
    109   /// for this data-type.
    110   ///
    111   bool isFullSet() const;
    112 
    113   /// Return true if this set contains no members.
    114   ///
    115   bool isEmptySet() const;
    116 
    117   /// Return true if this set wraps around the top of the range.
    118   /// For example: [100, 8).
    119   ///
    120   bool isWrappedSet() const;
    121 
    122   /// Return true if this set wraps around the INT_MIN of
    123   /// its bitwidth. For example: i8 [120, 140).
    124   ///
    125   bool isSignWrappedSet() const;
    126 
    127   /// Return true if the specified value is in the set.
    128   ///
    129   bool contains(const APInt &Val) const;
    130 
    131   /// Return true if the other range is a subset of this one.
    132   ///
    133   bool contains(const ConstantRange &CR) const;
    134 
    135   /// If this set contains a single element, return it, otherwise return null.
    136   ///
    137   const APInt *getSingleElement() const {
    138     if (Upper == Lower + 1)
    139       return &Lower;
    140     return nullptr;
    141   }
    142 
    143   /// Return true if this set contains exactly one member.
    144   ///
    145   bool isSingleElement() const { return getSingleElement() != nullptr; }
    146 
    147   /// Return the number of elements in this set.
    148   ///
    149   APInt getSetSize() const;
    150 
    151   /// Return the largest unsigned value contained in the ConstantRange.
    152   ///
    153   APInt getUnsignedMax() const;
    154 
    155   /// Return the smallest unsigned value contained in the ConstantRange.
    156   ///
    157   APInt getUnsignedMin() const;
    158 
    159   /// Return the largest signed value contained in the ConstantRange.
    160   ///
    161   APInt getSignedMax() const;
    162 
    163   /// Return the smallest signed value contained in the ConstantRange.
    164   ///
    165   APInt getSignedMin() const;
    166 
    167   /// Return true if this range is equal to another range.
    168   ///
    169   bool operator==(const ConstantRange &CR) const {
    170     return Lower == CR.Lower && Upper == CR.Upper;
    171   }
    172   bool operator!=(const ConstantRange &CR) const {
    173     return !operator==(CR);
    174   }
    175 
    176   /// Subtract the specified constant from the endpoints of this constant range.
    177   ConstantRange subtract(const APInt &CI) const;
    178 
    179   /// \brief Subtract the specified range from this range (aka relative
    180   /// complement of the sets).
    181   ConstantRange difference(const ConstantRange &CR) const;
    182 
    183   /// Return the range that results from the intersection of
    184   /// this range with another range.  The resultant range is guaranteed to
    185   /// include all elements contained in both input ranges, and to have the
    186   /// smallest possible set size that does so.  Because there may be two
    187   /// intersections with the same set size, A.intersectWith(B) might not
    188   /// be equal to B.intersectWith(A).
    189   ///
    190   ConstantRange intersectWith(const ConstantRange &CR) const;
    191 
    192   /// Return the range that results from the union of this range
    193   /// with another range.  The resultant range is guaranteed to include the
    194   /// elements of both sets, but may contain more.  For example, [3, 9) union
    195   /// [12,15) is [3, 15), which includes 9, 10, and 11, which were not included
    196   /// in either set before.
    197   ///
    198   ConstantRange unionWith(const ConstantRange &CR) const;
    199 
    200   /// Return a new range in the specified integer type, which must
    201   /// be strictly larger than the current type.  The returned range will
    202   /// correspond to the possible range of values if the source range had been
    203   /// zero extended to BitWidth.
    204   ConstantRange zeroExtend(uint32_t BitWidth) const;
    205 
    206   /// Return a new range in the specified integer type, which must
    207   /// be strictly larger than the current type.  The returned range will
    208   /// correspond to the possible range of values if the source range had been
    209   /// sign extended to BitWidth.
    210   ConstantRange signExtend(uint32_t BitWidth) const;
    211 
    212   /// Return a new range in the specified integer type, which must be
    213   /// strictly smaller than the current type.  The returned range will
    214   /// correspond to the possible range of values if the source range had been
    215   /// truncated to the specified type.
    216   ConstantRange truncate(uint32_t BitWidth) const;
    217 
    218   /// Make this range have the bit width given by \p BitWidth. The
    219   /// value is zero extended, truncated, or left alone to make it that width.
    220   ConstantRange zextOrTrunc(uint32_t BitWidth) const;
    221 
    222   /// Make this range have the bit width given by \p BitWidth. The
    223   /// value is sign extended, truncated, or left alone to make it that width.
    224   ConstantRange sextOrTrunc(uint32_t BitWidth) const;
    225 
    226   /// Return a new range representing the possible values resulting
    227   /// from an addition of a value in this range and a value in \p Other.
    228   ConstantRange add(const ConstantRange &Other) const;
    229 
    230   /// Return a new range representing the possible values resulting
    231   /// from a subtraction of a value in this range and a value in \p Other.
    232   ConstantRange sub(const ConstantRange &Other) const;
    233 
    234   /// Return a new range representing the possible values resulting
    235   /// from a multiplication of a value in this range and a value in \p Other,
    236   /// treating both this and \p Other as unsigned ranges.
    237   ConstantRange multiply(const ConstantRange &Other) const;
    238 
    239   /// Return a new range representing the possible values resulting
    240   /// from a signed maximum of a value in this range and a value in \p Other.
    241   ConstantRange smax(const ConstantRange &Other) const;
    242 
    243   /// Return a new range representing the possible values resulting
    244   /// from an unsigned maximum of a value in this range and a value in \p Other.
    245   ConstantRange umax(const ConstantRange &Other) const;
    246 
    247   /// Return a new range representing the possible values resulting
    248   /// from an unsigned division of a value in this range and a value in
    249   /// \p Other.
    250   ConstantRange udiv(const ConstantRange &Other) const;
    251 
    252   /// Return a new range representing the possible values resulting
    253   /// from a binary-and of a value in this range by a value in \p Other.
    254   ConstantRange binaryAnd(const ConstantRange &Other) const;
    255 
    256   /// Return a new range representing the possible values resulting
    257   /// from a binary-or of a value in this range by a value in \p Other.
    258   ConstantRange binaryOr(const ConstantRange &Other) const;
    259 
    260   /// Return a new range representing the possible values resulting
    261   /// from a left shift of a value in this range by a value in \p Other.
    262   /// TODO: This isn't fully implemented yet.
    263   ConstantRange shl(const ConstantRange &Other) const;
    264 
    265   /// Return a new range representing the possible values resulting from a
    266   /// logical right shift of a value in this range and a value in \p Other.
    267   ConstantRange lshr(const ConstantRange &Other) const;
    268 
    269   /// Return a new range that is the logical not of the current set.
    270   ///
    271   ConstantRange inverse() const;
    272 
    273   /// Print out the bounds to a stream.
    274   ///
    275   void print(raw_ostream &OS) const;
    276 
    277   /// Allow printing from a debugger easily.
    278   ///
    279   void dump() const;
    280 };
    281 
    282 inline raw_ostream &operator<<(raw_ostream &OS, const ConstantRange &CR) {
    283   CR.print(OS);
    284   return OS;
    285 }
    286 
    287 } // End llvm namespace
    288 
    289 #endif
    290