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