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#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.
27class ConstantIntRanges {
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`.
88 ConstantIntRanges rangeUnion(const ConstantIntRanges &other) const;
89
90 /// Returns the intersection (computed separately for signed and unsigned
91 /// bounds) of this range and `other`.
92 ConstantIntRanges intersection(const ConstantIntRanges &other) const;
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
99 friend raw_ostream &operator<<(raw_ostream &os,
100 const ConstantIntRanges &range);
101
102private:
103 APInt uminVal, umaxVal, sminVal, smaxVal;
104};
105
106raw_ostream &operator<<(raw_ostream &, const ConstantIntRanges &);
107
108/// The type of the `setResultRanges` callback provided to ops implementing
109/// InferIntRangeInterface. It should be called once for each integer result
110/// value and be passed the ConstantIntRanges corresponding to that value.
111using SetIntRangeFn = function_ref<void(Value, const ConstantIntRanges &)>;
112} // end namespace mlir
113
114#include "mlir/Interfaces/InferIntRangeInterface.h.inc"
115
116#endif // MLIR_INTERFACES_INFERINTRANGEINTERFACE_H
117

source code of mlir/include/mlir/Interfaces/InferIntRangeInterface.h