1 //===- InferIntRangeInterface.h - Integer Range Inference --*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file contains definitions of the integer range inference interface
10 // defined in `InferIntRange.td`
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef MLIR_INTERFACES_INFERINTRANGEINTERFACE_H
15 #define MLIR_INTERFACES_INFERINTRANGEINTERFACE_H
16 
17 #include "mlir/IR/OpDefinition.h"
18 
19 namespace mlir {
20 /// A set of arbitrary-precision integers representing bounds on a given integer
21 /// value. These bounds are inclusive on both ends, so
22 /// bounds of [4, 5] mean 4 <= x <= 5. Separate bounds are tracked for
23 /// the unsigned and signed interpretations of values in order to enable more
24 /// precice inference of the interplay between operations with signed and
25 /// unsigned semantics.
26 class ConstantIntRanges {
27 public:
28   /// Bound umin <= (unsigned)x <= umax and smin <= signed(x) <= smax.
29   /// Non-integer values should be bounded by APInts of bitwidth 0.
ConstantIntRanges(const APInt & umin,const APInt & umax,const APInt & smin,const APInt & smax)30   ConstantIntRanges(const APInt &umin, const APInt &umax, const APInt &smin,
31                     const APInt &smax)
32       : uminVal(umin), umaxVal(umax), sminVal(smin), smaxVal(smax) {
33     assert(uminVal.getBitWidth() == umaxVal.getBitWidth() &&
34            umaxVal.getBitWidth() == sminVal.getBitWidth() &&
35            sminVal.getBitWidth() == smaxVal.getBitWidth() &&
36            "All bounds in the ranges must have the same bitwidth");
37   }
38 
39   bool operator==(const ConstantIntRanges &other) const;
40 
41   /// The minimum value of an integer when it is interpreted as unsigned.
42   const APInt &umin() const;
43 
44   /// The maximum value of an integer when it is interpreted as unsigned.
45   const APInt &umax() const;
46 
47   /// The minimum value of an integer when it is interpreted as signed.
48   const APInt &smin() const;
49 
50   /// The maximum value of an integer when it is interpreted as signed.
51   const APInt &smax() const;
52 
53   /// Return the bitwidth that should be used for integer ranges describing
54   /// `type`. For concrete integer types, this is their bitwidth, for `index`,
55   /// this is the internal storage bitwidth of `index` attributes, and for
56   /// non-integer types this is 0.
57   static unsigned getStorageBitwidth(Type type);
58 
59   /// Create a `ConstantIntRanges` with the maximum bounds for the width
60   /// `bitwidth`, that is - [0, uint_max(width)]/[sint_min(width),
61   /// sint_max(width)].
62   static ConstantIntRanges maxRange(unsigned bitwidth);
63 
64   /// Create a `ConstantIntRanges` with a constant value - that is, with the
65   /// bounds [value, value] for both its signed interpretations.
66   static ConstantIntRanges constant(const APInt &value);
67 
68   /// Create a `ConstantIntRanges` whose minimum is `min` and maximum is `max`
69   /// with `isSigned` specifying if the min and max should be interpreted as
70   /// signed or unsigned.
71   static ConstantIntRanges range(const APInt &min, const APInt &max,
72                                  bool isSigned);
73 
74   /// Create an `ConstantIntRanges` with the signed minimum and maximum equal
75   /// to `smin` and `smax`, where the unsigned bounds are constructed from the
76   /// signed ones if they correspond to a contigious range of bit patterns when
77   /// viewed as unsigned values and are left at [0, int_max()] otherwise.
78   static ConstantIntRanges fromSigned(const APInt &smin, const APInt &smax);
79 
80   /// Create an `ConstantIntRanges` with the unsigned minimum and maximum equal
81   /// to `umin` and `umax` and the signed part equal to `umin` and `umax`
82   /// unless the sign bit changes between the minimum and maximum.
83   static ConstantIntRanges fromUnsigned(const APInt &umin, const APInt &umax);
84 
85   /// Returns the union (computed separately for signed and unsigned bounds)
86   /// of this range and `other`.
87   ConstantIntRanges rangeUnion(const ConstantIntRanges &other) const;
88 
89   /// Returns the intersection (computed separately for signed and unsigned
90   /// bounds) of this range and `other`.
91   ConstantIntRanges intersection(const ConstantIntRanges &other) const;
92 
93   /// If either the signed or unsigned interpretations of the range
94   /// indicate that the value it bounds is a constant, return that constant
95   /// value.
96   Optional<APInt> getConstantValue() const;
97 
98   friend raw_ostream &operator<<(raw_ostream &os,
99                                  const ConstantIntRanges &range);
100 
101 private:
102   APInt uminVal, umaxVal, sminVal, smaxVal;
103 };
104 
105 /// The type of the `setResultRanges` callback provided to ops implementing
106 /// InferIntRangeInterface. It should be called once for each integer result
107 /// value and be passed the ConstantIntRanges corresponding to that value.
108 using SetIntRangeFn = function_ref<void(Value, const ConstantIntRanges &)>;
109 } // end namespace mlir
110 
111 #include "mlir/Interfaces/InferIntRangeInterface.h.inc"
112 
113 #endif // MLIR_INTERFACES_INFERINTRANGEINTERFACE_H
114