1274955Ssvnmir//===- ConstantRange.h - Represent a range ----------------------*- C++ -*-===//
2274955Ssvnmir//
3274955Ssvnmir//                     The LLVM Compiler Infrastructure
4274955Ssvnmir//
5274955Ssvnmir// This file is distributed under the University of Illinois Open Source
6274955Ssvnmir// License. See LICENSE.TXT for details.
7274955Ssvnmir//
8274955Ssvnmir//===----------------------------------------------------------------------===//
9274955Ssvnmir//
10274955Ssvnmir// Represent a range of possible values that may occur when the program is run
11274955Ssvnmir// for an integral value.  This keeps track of a lower and upper bound for the
12274955Ssvnmir// constant, which MAY wrap around the end of the numeric range.  To do this, it
13274955Ssvnmir// keeps track of a [lower, upper) bound, which specifies an interval just like
14274955Ssvnmir// STL iterators.  When used with boolean values, the following are important
15274955Ssvnmir// ranges: :
16274955Ssvnmir//
17274955Ssvnmir//  [F, F) = {}     = Empty set
18274955Ssvnmir//  [T, F) = {T}
19274955Ssvnmir//  [F, T) = {F}
20274955Ssvnmir//  [T, T) = {F, T} = Full set
21274955Ssvnmir//
22274955Ssvnmir// The other integral ranges use min/max values for special range values. For
23274955Ssvnmir// example, for 8-bit types, it uses:
24274955Ssvnmir// [0, 0)     = {}       = Empty set
25274955Ssvnmir// [255, 255) = {0..255} = Full Set
26274955Ssvnmir//
27274955Ssvnmir// Note that ConstantRange can be used to represent either signed or
28274955Ssvnmir// unsigned ranges.
29274955Ssvnmir//
30274955Ssvnmir//===----------------------------------------------------------------------===//
31274955Ssvnmir
32280031Sdim#ifndef LLVM_IR_CONSTANTRANGE_H
33280031Sdim#define LLVM_IR_CONSTANTRANGE_H
34274955Ssvnmir
35274955Ssvnmir#include "llvm/ADT/APInt.h"
36288943Sdim#include "llvm/IR/InstrTypes.h"
37274955Ssvnmir#include "llvm/Support/DataTypes.h"
38274955Ssvnmir
39274955Ssvnmirnamespace llvm {
40274955Ssvnmir
41280031Sdim/// This class represents a range of values.
42274955Ssvnmir///
43274955Ssvnmirclass ConstantRange {
44274955Ssvnmir  APInt Lower, Upper;
45274955Ssvnmir
46274955Ssvnmir  // If we have move semantics, pass APInts by value and move them into place.
47274955Ssvnmir  typedef APInt APIntMoveTy;
48274955Ssvnmir
49274955Ssvnmirpublic:
50274955Ssvnmir  /// Initialize a full (the default) or empty set for the specified bit width.
51274955Ssvnmir  ///
52274955Ssvnmir  explicit ConstantRange(uint32_t BitWidth, bool isFullSet = true);
53274955Ssvnmir
54274955Ssvnmir  /// Initialize a range to hold the single specified value.
55274955Ssvnmir  ///
56274955Ssvnmir  ConstantRange(APIntMoveTy Value);
57274955Ssvnmir
58274955Ssvnmir  /// @brief Initialize a range of values explicitly. This will assert out if
59274955Ssvnmir  /// Lower==Upper and Lower != Min or Max value for its type. It will also
60274955Ssvnmir  /// assert out if the two APInt's are not the same bit width.
61274955Ssvnmir  ConstantRange(APIntMoveTy Lower, APIntMoveTy Upper);
62274955Ssvnmir
63288943Sdim  /// Produce the smallest range such that all values that may satisfy the given
64288943Sdim  /// predicate with any value contained within Other is contained in the
65288943Sdim  /// returned range.  Formally, this returns a superset of
66288943Sdim  /// 'union over all y in Other . { x : icmp op x y is true }'.  If the exact
67288943Sdim  /// answer is not representable as a ConstantRange, the return value will be a
68288943Sdim  /// proper superset of the above.
69274955Ssvnmir  ///
70288943Sdim  /// Example: Pred = ult and Other = i8 [2, 5) returns Result = [0, 4)
71288943Sdim  static ConstantRange makeAllowedICmpRegion(CmpInst::Predicate Pred,
72288943Sdim                                             const ConstantRange &Other);
73274955Ssvnmir
74288943Sdim  /// Produce the largest range such that all values in the returned range
75288943Sdim  /// satisfy the given predicate with all values contained within Other.
76288943Sdim  /// Formally, this returns a subset of
77288943Sdim  /// 'intersection over all y in Other . { x : icmp op x y is true }'.  If the
78288943Sdim  /// exact answer is not representable as a ConstantRange, the return value
79288943Sdim  /// will be a proper subset of the above.
80288943Sdim  ///
81288943Sdim  /// Example: Pred = ult and Other = i8 [2, 5) returns [0, 2)
82288943Sdim  static ConstantRange makeSatisfyingICmpRegion(CmpInst::Predicate Pred,
83288943Sdim                                                const ConstantRange &Other);
84288943Sdim
85296417Sdim  /// Return the largest range containing all X such that "X BinOpC C" does not
86296417Sdim  /// wrap (overflow).
87296417Sdim  ///
88296417Sdim  /// Example:
89296417Sdim  ///  typedef OverflowingBinaryOperator OBO;
90296417Sdim  ///  makeNoWrapRegion(Add, i8 1, OBO::NoSignedWrap) == [-128, 127)
91296417Sdim  ///  makeNoWrapRegion(Add, i8 1, OBO::NoUnsignedWrap) == [0, -1)
92296417Sdim  ///  makeNoWrapRegion(Add, i8 0, OBO::NoUnsignedWrap) == Full Set
93296417Sdim  static ConstantRange makeNoWrapRegion(Instruction::BinaryOps BinOp,
94296417Sdim                                        const APInt &C, unsigned NoWrapKind);
95296417Sdim
96280031Sdim  /// Return the lower value for this range.
97274955Ssvnmir  ///
98274955Ssvnmir  const APInt &getLower() const { return Lower; }
99274955Ssvnmir
100280031Sdim  /// Return the upper value for this range.
101274955Ssvnmir  ///
102274955Ssvnmir  const APInt &getUpper() const { return Upper; }
103274955Ssvnmir
104280031Sdim  /// Get the bit width of this ConstantRange.
105274955Ssvnmir  ///
106274955Ssvnmir  uint32_t getBitWidth() const { return Lower.getBitWidth(); }
107274955Ssvnmir
108280031Sdim  /// Return true if this set contains all of the elements possible
109280031Sdim  /// for this data-type.
110274955Ssvnmir  ///
111274955Ssvnmir  bool isFullSet() const;
112274955Ssvnmir
113280031Sdim  /// Return true if this set contains no members.
114274955Ssvnmir  ///
115274955Ssvnmir  bool isEmptySet() const;
116274955Ssvnmir
117280031Sdim  /// Return true if this set wraps around the top of the range.
118280031Sdim  /// For example: [100, 8).
119274955Ssvnmir  ///
120274955Ssvnmir  bool isWrappedSet() const;
121274955Ssvnmir
122280031Sdim  /// Return true if this set wraps around the INT_MIN of
123280031Sdim  /// its bitwidth. For example: i8 [120, 140).
124274955Ssvnmir  ///
125274955Ssvnmir  bool isSignWrappedSet() const;
126274955Ssvnmir
127280031Sdim  /// Return true if the specified value is in the set.
128274955Ssvnmir  ///
129274955Ssvnmir  bool contains(const APInt &Val) const;
130274955Ssvnmir
131280031Sdim  /// Return true if the other range is a subset of this one.
132274955Ssvnmir  ///
133274955Ssvnmir  bool contains(const ConstantRange &CR) const;
134274955Ssvnmir
135280031Sdim  /// If this set contains a single element, return it, otherwise return null.
136274955Ssvnmir  ///
137274955Ssvnmir  const APInt *getSingleElement() const {
138274955Ssvnmir    if (Upper == Lower + 1)
139274955Ssvnmir      return &Lower;
140274955Ssvnmir    return nullptr;
141274955Ssvnmir  }
142274955Ssvnmir
143280031Sdim  /// Return true if this set contains exactly one member.
144274955Ssvnmir  ///
145274955Ssvnmir  bool isSingleElement() const { return getSingleElement() != nullptr; }
146274955Ssvnmir
147280031Sdim  /// Return the number of elements in this set.
148274955Ssvnmir  ///
149274955Ssvnmir  APInt getSetSize() const;
150274955Ssvnmir
151280031Sdim  /// Return the largest unsigned value contained in the ConstantRange.
152274955Ssvnmir  ///
153274955Ssvnmir  APInt getUnsignedMax() const;
154274955Ssvnmir
155280031Sdim  /// Return the smallest unsigned value contained in the ConstantRange.
156274955Ssvnmir  ///
157274955Ssvnmir  APInt getUnsignedMin() const;
158274955Ssvnmir
159280031Sdim  /// Return the largest signed value contained in the ConstantRange.
160274955Ssvnmir  ///
161274955Ssvnmir  APInt getSignedMax() const;
162274955Ssvnmir
163280031Sdim  /// Return the smallest signed value contained in the ConstantRange.
164274955Ssvnmir  ///
165274955Ssvnmir  APInt getSignedMin() const;
166274955Ssvnmir
167280031Sdim  /// Return true if this range is equal to another range.
168274955Ssvnmir  ///
169274955Ssvnmir  bool operator==(const ConstantRange &CR) const {
170274955Ssvnmir    return Lower == CR.Lower && Upper == CR.Upper;
171274955Ssvnmir  }
172274955Ssvnmir  bool operator!=(const ConstantRange &CR) const {
173274955Ssvnmir    return !operator==(CR);
174274955Ssvnmir  }
175274955Ssvnmir
176280031Sdim  /// Subtract the specified constant from the endpoints of this constant range.
177274955Ssvnmir  ConstantRange subtract(const APInt &CI) const;
178274955Ssvnmir
179274955Ssvnmir  /// \brief Subtract the specified range from this range (aka relative
180274955Ssvnmir  /// complement of the sets).
181274955Ssvnmir  ConstantRange difference(const ConstantRange &CR) const;
182274955Ssvnmir
183280031Sdim  /// Return the range that results from the intersection of
184274955Ssvnmir  /// this range with another range.  The resultant range is guaranteed to
185274955Ssvnmir  /// include all elements contained in both input ranges, and to have the
186274955Ssvnmir  /// smallest possible set size that does so.  Because there may be two
187274955Ssvnmir  /// intersections with the same set size, A.intersectWith(B) might not
188274955Ssvnmir  /// be equal to B.intersectWith(A).
189274955Ssvnmir  ///
190274955Ssvnmir  ConstantRange intersectWith(const ConstantRange &CR) const;
191274955Ssvnmir
192280031Sdim  /// Return the range that results from the union of this range
193274955Ssvnmir  /// with another range.  The resultant range is guaranteed to include the
194274955Ssvnmir  /// elements of both sets, but may contain more.  For example, [3, 9) union
195274955Ssvnmir  /// [12,15) is [3, 15), which includes 9, 10, and 11, which were not included
196274955Ssvnmir  /// in either set before.
197274955Ssvnmir  ///
198274955Ssvnmir  ConstantRange unionWith(const ConstantRange &CR) const;
199274955Ssvnmir
200280031Sdim  /// Return a new range in the specified integer type, which must
201274955Ssvnmir  /// be strictly larger than the current type.  The returned range will
202274955Ssvnmir  /// correspond to the possible range of values if the source range had been
203274955Ssvnmir  /// zero extended to BitWidth.
204274955Ssvnmir  ConstantRange zeroExtend(uint32_t BitWidth) const;
205274955Ssvnmir
206280031Sdim  /// Return a new range in the specified integer type, which must
207274955Ssvnmir  /// be strictly larger than the current type.  The returned range will
208274955Ssvnmir  /// correspond to the possible range of values if the source range had been
209274955Ssvnmir  /// sign extended to BitWidth.
210274955Ssvnmir  ConstantRange signExtend(uint32_t BitWidth) const;
211274955Ssvnmir
212280031Sdim  /// Return a new range in the specified integer type, which must be
213274955Ssvnmir  /// strictly smaller than the current type.  The returned range will
214274955Ssvnmir  /// correspond to the possible range of values if the source range had been
215274955Ssvnmir  /// truncated to the specified type.
216274955Ssvnmir  ConstantRange truncate(uint32_t BitWidth) const;
217274955Ssvnmir
218280031Sdim  /// Make this range have the bit width given by \p BitWidth. The
219274955Ssvnmir  /// value is zero extended, truncated, or left alone to make it that width.
220274955Ssvnmir  ConstantRange zextOrTrunc(uint32_t BitWidth) const;
221296417Sdim
222280031Sdim  /// Make this range have the bit width given by \p BitWidth. The
223274955Ssvnmir  /// value is sign extended, truncated, or left alone to make it that width.
224274955Ssvnmir  ConstantRange sextOrTrunc(uint32_t BitWidth) const;
225274955Ssvnmir
226280031Sdim  /// Return a new range representing the possible values resulting
227274955Ssvnmir  /// from an addition of a value in this range and a value in \p Other.
228274955Ssvnmir  ConstantRange add(const ConstantRange &Other) const;
229274955Ssvnmir
230280031Sdim  /// Return a new range representing the possible values resulting
231274955Ssvnmir  /// from a subtraction of a value in this range and a value in \p Other.
232274955Ssvnmir  ConstantRange sub(const ConstantRange &Other) const;
233274955Ssvnmir
234280031Sdim  /// Return a new range representing the possible values resulting
235288943Sdim  /// from a multiplication of a value in this range and a value in \p Other,
236288943Sdim  /// treating both this and \p Other as unsigned ranges.
237274955Ssvnmir  ConstantRange multiply(const ConstantRange &Other) const;
238274955Ssvnmir
239280031Sdim  /// Return a new range representing the possible values resulting
240274955Ssvnmir  /// from a signed maximum of a value in this range and a value in \p Other.
241274955Ssvnmir  ConstantRange smax(const ConstantRange &Other) const;
242274955Ssvnmir
243280031Sdim  /// Return a new range representing the possible values resulting
244274955Ssvnmir  /// from an unsigned maximum of a value in this range and a value in \p Other.
245274955Ssvnmir  ConstantRange umax(const ConstantRange &Other) const;
246274955Ssvnmir
247280031Sdim  /// Return a new range representing the possible values resulting
248274955Ssvnmir  /// from an unsigned division of a value in this range and a value in
249274955Ssvnmir  /// \p Other.
250274955Ssvnmir  ConstantRange udiv(const ConstantRange &Other) const;
251274955Ssvnmir
252280031Sdim  /// Return a new range representing the possible values resulting
253274955Ssvnmir  /// from a binary-and of a value in this range by a value in \p Other.
254274955Ssvnmir  ConstantRange binaryAnd(const ConstantRange &Other) const;
255274955Ssvnmir
256280031Sdim  /// Return a new range representing the possible values resulting
257274955Ssvnmir  /// from a binary-or of a value in this range by a value in \p Other.
258274955Ssvnmir  ConstantRange binaryOr(const ConstantRange &Other) const;
259274955Ssvnmir
260280031Sdim  /// Return a new range representing the possible values resulting
261274955Ssvnmir  /// from a left shift of a value in this range by a value in \p Other.
262274955Ssvnmir  /// TODO: This isn't fully implemented yet.
263274955Ssvnmir  ConstantRange shl(const ConstantRange &Other) const;
264274955Ssvnmir
265280031Sdim  /// Return a new range representing the possible values resulting from a
266280031Sdim  /// logical right shift of a value in this range and a value in \p Other.
267274955Ssvnmir  ConstantRange lshr(const ConstantRange &Other) const;
268274955Ssvnmir
269280031Sdim  /// Return a new range that is the logical not of the current set.
270274955Ssvnmir  ///
271274955Ssvnmir  ConstantRange inverse() const;
272296417Sdim
273280031Sdim  /// Print out the bounds to a stream.
274274955Ssvnmir  ///
275274955Ssvnmir  void print(raw_ostream &OS) const;
276274955Ssvnmir
277280031Sdim  /// Allow printing from a debugger easily.
278274955Ssvnmir  ///
279274955Ssvnmir  void dump() const;
280274955Ssvnmir};
281274955Ssvnmir
282274955Ssvnmirinline raw_ostream &operator<<(raw_ostream &OS, const ConstantRange &CR) {
283274955Ssvnmir  CR.print(OS);
284274955Ssvnmir  return OS;
285274955Ssvnmir}
286274955Ssvnmir
287274955Ssvnmir} // End llvm namespace
288274955Ssvnmir
289274955Ssvnmir#endif
290