MLIR 22.0.0git
InferIntRangeInterface.h
Go to the documentation of this file.
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
18#include <optional>
19
20namespace mlir {
21/// A set of arbitrary-precision integers representing bounds on a given integer
22/// value. These bounds are inclusive on both ends, so
23/// bounds of [4, 5] mean 4 <= x <= 5. Separate bounds are tracked for
24/// the unsigned and signed interpretations of values in order to enable more
25/// precice inference of the interplay between operations with signed and
26/// unsigned semantics.
28public:
29 /// Bound umin <= (unsigned)x <= umax and smin <= signed(x) <= smax.
30 /// Non-integer values should be bounded by APInts of bitwidth 0.
31 ConstantIntRanges(const APInt &umin, const APInt &umax, const APInt &smin,
32 const APInt &smax)
33 : uminVal(umin), umaxVal(umax), sminVal(smin), smaxVal(smax) {
34 assert(uminVal.getBitWidth() == umaxVal.getBitWidth() &&
35 umaxVal.getBitWidth() == sminVal.getBitWidth() &&
36 sminVal.getBitWidth() == smaxVal.getBitWidth() &&
37 "All bounds in the ranges must have the same bitwidth");
38 }
39
40 bool operator==(const ConstantIntRanges &other) const;
41
42 /// The minimum value of an integer when it is interpreted as unsigned.
43 const APInt &umin() const;
44
45 /// The maximum value of an integer when it is interpreted as unsigned.
46 const APInt &umax() const;
47
48 /// The minimum value of an integer when it is interpreted as signed.
49 const APInt &smin() const;
50
51 /// The maximum value of an integer when it is interpreted as signed.
52 const APInt &smax() const;
53
54 /// Return the bitwidth that should be used for integer ranges describing
55 /// `type`. For concrete integer types, this is their bitwidth, for `index`,
56 /// this is the internal storage bitwidth of `index` attributes, and for
57 /// non-integer types this is 0.
58 static unsigned getStorageBitwidth(Type type);
59
60 /// Create a `ConstantIntRanges` with the maximum bounds for the width
61 /// `bitwidth`, that is - [0, uint_max(width)]/[sint_min(width),
62 /// sint_max(width)].
63 static ConstantIntRanges maxRange(unsigned bitwidth);
64
65 /// Create a `ConstantIntRanges` with a constant value - that is, with the
66 /// bounds [value, value] for both its signed interpretations.
67 static ConstantIntRanges constant(const APInt &value);
68
69 /// Create a `ConstantIntRanges` whose minimum is `min` and maximum is `max`
70 /// with `isSigned` specifying if the min and max should be interpreted as
71 /// signed or unsigned.
72 static ConstantIntRanges range(const APInt &min, const APInt &max,
73 bool isSigned);
74
75 /// Create an `ConstantIntRanges` with the signed minimum and maximum equal
76 /// to `smin` and `smax`, where the unsigned bounds are constructed from the
77 /// signed ones if they correspond to a contigious range of bit patterns when
78 /// viewed as unsigned values and are left at [0, int_max()] otherwise.
79 static ConstantIntRanges fromSigned(const APInt &smin, const APInt &smax);
80
81 /// Create an `ConstantIntRanges` with the unsigned minimum and maximum equal
82 /// to `umin` and `umax` and the signed part equal to `umin` and `umax`
83 /// unless the sign bit changes between the minimum and maximum.
84 static ConstantIntRanges fromUnsigned(const APInt &umin, const APInt &umax);
85
86 /// Returns the union (computed separately for signed and unsigned bounds)
87 /// of this range and `other`.
89
90 /// Returns the intersection (computed separately for signed and unsigned
91 /// bounds) of this range and `other`.
93
94 /// If either the signed or unsigned interpretations of the range
95 /// indicate that the value it bounds is a constant, return that constant
96 /// value.
97 std::optional<APInt> getConstantValue() const;
98
100 const ConstantIntRanges &range);
101
102private:
103 APInt uminVal, umaxVal, sminVal, smaxVal;
104};
105
107
108/// This lattice value represents the integer range of an SSA value.
110public:
111 /// Create a maximal range ([0, uint_max(t)] / [int_min(t), int_max(t)])
112 /// range that is used to mark the value as unable to be analyzed further,
113 /// where `t` is the type of `value`.
114 static IntegerValueRange getMaxRange(Value value);
115
116 /// Create an integer value range lattice value.
117 IntegerValueRange(ConstantIntRanges value) : value(std::move(value)) {}
118
119 /// Create an integer value range lattice value.
121 std::optional<ConstantIntRanges> value = std::nullopt)
122 : value(std::move(value)) {}
123
124 /// Whether the range is uninitialized. This happens when the state hasn't
125 /// been set during the analysis.
126 bool isUninitialized() const { return !value.has_value(); }
127
128 /// Get the known integer value range.
130 assert(!isUninitialized());
131 return *value;
132 }
133
134 /// Compare two ranges.
135 bool operator==(const IntegerValueRange &rhs) const {
136 return value == rhs.value;
137 }
138
139 /// Compute the least upper bound of two ranges.
141 const IntegerValueRange &rhs) {
142 if (lhs.isUninitialized())
143 return rhs;
144 if (rhs.isUninitialized())
145 return lhs;
146 return IntegerValueRange{lhs.getValue().rangeUnion(rhs.getValue())};
147 }
148
149 /// Print the integer value range.
150 void print(raw_ostream &os) const { os << value; }
151
152private:
153 /// The known integer value range.
154 std::optional<ConstantIntRanges> value;
155};
156
157raw_ostream &operator<<(raw_ostream &, const IntegerValueRange &);
158
159/// The type of the `setResultRanges` callback provided to ops implementing
160/// InferIntRangeInterface. It should be called once for each integer result
161/// value and be passed the ConstantIntRanges corresponding to that value.
164
165/// Similar to SetIntRangeFn, but operating on IntegerValueRange lattice values.
166/// This is the `setResultRanges` callback for the IntegerValueRange based
167/// interface method.
170
171/// Helper callback type to get the integer range of a value.
173
174/// Helper function to collect the integer range values of an array of op fold
175/// results.
177 GetIntRangeFn getIntRange,
178 int32_t indexBitwidth);
179
180class InferIntRangeInterface;
181
183/// Default implementation of `inferResultRanges` which dispatches to the
184/// `inferResultRangesFromOptional`.
185void defaultInferResultRanges(InferIntRangeInterface interface,
187 SetIntLatticeFn setResultRanges);
188
189/// Default implementation of `inferResultRangesFromOptional` which dispatches
190/// to the `inferResultRanges`.
191void defaultInferResultRangesFromOptional(InferIntRangeInterface interface,
193 SetIntRangeFn setResultRanges);
194} // end namespace intrange::detail
195} // end namespace mlir
196
197#include "mlir/Interfaces/InferIntRangeInterface.h.inc"
198
199#endif // MLIR_INTERFACES_INFERINTRANGEINTERFACE_H
lhs
static Value max(ImplicitLocOpBuilder &builder, Value value, Value bound)
static Value min(ImplicitLocOpBuilder &builder, Value value, Value bound)
A set of arbitrary-precision integers representing bounds on a given integer value.
static ConstantIntRanges maxRange(unsigned bitwidth)
Create a ConstantIntRanges with the maximum bounds for the width bitwidth, that is - [0,...
ConstantIntRanges(const APInt &umin, const APInt &umax, const APInt &smin, const APInt &smax)
Bound umin <= (unsigned)x <= umax and smin <= signed(x) <= smax.
friend raw_ostream & operator<<(raw_ostream &os, const ConstantIntRanges &range)
const APInt & smax() const
The maximum value of an integer when it is interpreted as signed.
static ConstantIntRanges constant(const APInt &value)
Create a ConstantIntRanges with a constant value - that is, with the bounds [value,...
static ConstantIntRanges fromUnsigned(const APInt &umin, const APInt &umax)
Create an ConstantIntRanges with the unsigned minimum and maximum equal to umin and umax and the sign...
const APInt & smin() const
The minimum value of an integer when it is interpreted as signed.
static ConstantIntRanges range(const APInt &min, const APInt &max, bool isSigned)
Create a ConstantIntRanges whose minimum is min and maximum is max with isSigned specifying if the mi...
ConstantIntRanges intersection(const ConstantIntRanges &other) const
Returns the intersection (computed separately for signed and unsigned bounds) of this range and other...
static ConstantIntRanges fromSigned(const APInt &smin, const APInt &smax)
Create an ConstantIntRanges with the signed minimum and maximum equal to smin and smax,...
static unsigned getStorageBitwidth(Type type)
Return the bitwidth that should be used for integer ranges describing type.
std::optional< APInt > getConstantValue() const
If either the signed or unsigned interpretations of the range indicate that the value it bounds is a ...
const APInt & umax() const
The maximum value of an integer when it is interpreted as unsigned.
const APInt & umin() const
The minimum value of an integer when it is interpreted as unsigned.
ConstantIntRanges rangeUnion(const ConstantIntRanges &other) const
Returns the union (computed separately for signed and unsigned bounds) of this range and other.
bool operator==(const ConstantIntRanges &other) const
This lattice value represents the integer range of an SSA value.
IntegerValueRange(ConstantIntRanges value)
Create an integer value range lattice value.
void print(raw_ostream &os) const
Print the integer value range.
const ConstantIntRanges & getValue() const
Get the known integer value range.
IntegerValueRange(std::optional< ConstantIntRanges > value=std::nullopt)
Create an integer value range lattice value.
bool isUninitialized() const
Whether the range is uninitialized.
static IntegerValueRange getMaxRange(Value value)
Create a maximal range ([0, uint_max(t)] / [int_min(t), int_max(t)]) range that is used to mark the v...
bool operator==(const IntegerValueRange &rhs) const
Compare two ranges.
static IntegerValueRange join(const IntegerValueRange &lhs, const IntegerValueRange &rhs)
Compute the least upper bound of two ranges.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition Types.h:74
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition Value.h:96
void defaultInferResultRanges(InferIntRangeInterface interface, ArrayRef< IntegerValueRange > argRanges, SetIntLatticeFn setResultRanges)
Default implementation of inferResultRanges which dispatches to the inferResultRangesFromOptional.
void defaultInferResultRangesFromOptional(InferIntRangeInterface interface, ArrayRef< ConstantIntRanges > argRanges, SetIntRangeFn setResultRanges)
Default implementation of inferResultRangesFromOptional which dispatches to the inferResultRanges.
Include the generated interface declarations.
llvm::function_ref< void(Value, const ConstantIntRanges &)> SetIntRangeFn
The type of the setResultRanges callback provided to ops implementing InferIntRangeInterface.
raw_ostream & operator<<(raw_ostream &os, const AliasResult &result)
llvm::function_ref< void(Value, const IntegerValueRange &)> SetIntLatticeFn
Similar to SetIntRangeFn, but operating on IntegerValueRange lattice values.
SmallVector< IntegerValueRange > getIntValueRanges(ArrayRef< OpFoldResult > values, GetIntRangeFn getIntRange, int32_t indexBitwidth)
Helper function to collect the integer range values of an array of op fold results.
llvm::function_ref< Fn > function_ref
Definition LLVM.h:152
function_ref< IntegerValueRange(Value)> GetIntRangeFn
Helper callback type to get the integer range of a value.