1*95aff23eSKrzysztof Drewniak //===- InferIntRangeInterface.cpp - Integer range inference interface ---===// 2*95aff23eSKrzysztof Drewniak // 3*95aff23eSKrzysztof Drewniak // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*95aff23eSKrzysztof Drewniak // See https://llvm.org/LICENSE.txt for license information. 5*95aff23eSKrzysztof Drewniak // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*95aff23eSKrzysztof Drewniak // 7*95aff23eSKrzysztof Drewniak //===----------------------------------------------------------------------===// 8*95aff23eSKrzysztof Drewniak 9*95aff23eSKrzysztof Drewniak #include "mlir/Interfaces/InferIntRangeInterface.h" 10*95aff23eSKrzysztof Drewniak #include "mlir/IR/BuiltinTypes.h" 11*95aff23eSKrzysztof Drewniak #include "mlir/Interfaces/InferIntRangeInterface.cpp.inc" 12*95aff23eSKrzysztof Drewniak 13*95aff23eSKrzysztof Drewniak using namespace mlir; 14*95aff23eSKrzysztof Drewniak 15*95aff23eSKrzysztof Drewniak bool ConstantIntRanges::operator==(const ConstantIntRanges &other) const { 16*95aff23eSKrzysztof Drewniak return umin().getBitWidth() == other.umin().getBitWidth() && 17*95aff23eSKrzysztof Drewniak umin() == other.umin() && umax() == other.umax() && 18*95aff23eSKrzysztof Drewniak smin() == other.smin() && smax() == other.smax(); 19*95aff23eSKrzysztof Drewniak } 20*95aff23eSKrzysztof Drewniak 21*95aff23eSKrzysztof Drewniak const APInt &ConstantIntRanges::umin() const { return uminVal; } 22*95aff23eSKrzysztof Drewniak 23*95aff23eSKrzysztof Drewniak const APInt &ConstantIntRanges::umax() const { return umaxVal; } 24*95aff23eSKrzysztof Drewniak 25*95aff23eSKrzysztof Drewniak const APInt &ConstantIntRanges::smin() const { return sminVal; } 26*95aff23eSKrzysztof Drewniak 27*95aff23eSKrzysztof Drewniak const APInt &ConstantIntRanges::smax() const { return smaxVal; } 28*95aff23eSKrzysztof Drewniak 29*95aff23eSKrzysztof Drewniak unsigned ConstantIntRanges::getStorageBitwidth(Type type) { 30*95aff23eSKrzysztof Drewniak if (type.isIndex()) 31*95aff23eSKrzysztof Drewniak return IndexType::kInternalStorageBitWidth; 32*95aff23eSKrzysztof Drewniak if (auto integerType = type.dyn_cast<IntegerType>()) 33*95aff23eSKrzysztof Drewniak return integerType.getWidth(); 34*95aff23eSKrzysztof Drewniak // Non-integer types have their bounds stored in width 0 `APInt`s. 35*95aff23eSKrzysztof Drewniak return 0; 36*95aff23eSKrzysztof Drewniak } 37*95aff23eSKrzysztof Drewniak 38*95aff23eSKrzysztof Drewniak ConstantIntRanges ConstantIntRanges::range(const APInt &min, const APInt &max) { 39*95aff23eSKrzysztof Drewniak return {min, max, min, max}; 40*95aff23eSKrzysztof Drewniak } 41*95aff23eSKrzysztof Drewniak 42*95aff23eSKrzysztof Drewniak ConstantIntRanges ConstantIntRanges::fromSigned(const APInt &smin, 43*95aff23eSKrzysztof Drewniak const APInt &smax) { 44*95aff23eSKrzysztof Drewniak unsigned int width = smin.getBitWidth(); 45*95aff23eSKrzysztof Drewniak APInt umin, umax; 46*95aff23eSKrzysztof Drewniak if (smin.isNonNegative() == smax.isNonNegative()) { 47*95aff23eSKrzysztof Drewniak umin = smin.ult(smax) ? smin : smax; 48*95aff23eSKrzysztof Drewniak umax = smin.ugt(smax) ? smin : smax; 49*95aff23eSKrzysztof Drewniak } else { 50*95aff23eSKrzysztof Drewniak umin = APInt::getMinValue(width); 51*95aff23eSKrzysztof Drewniak umax = APInt::getMaxValue(width); 52*95aff23eSKrzysztof Drewniak } 53*95aff23eSKrzysztof Drewniak return {umin, umax, smin, smax}; 54*95aff23eSKrzysztof Drewniak } 55*95aff23eSKrzysztof Drewniak 56*95aff23eSKrzysztof Drewniak ConstantIntRanges ConstantIntRanges::fromUnsigned(const APInt &umin, 57*95aff23eSKrzysztof Drewniak const APInt &umax) { 58*95aff23eSKrzysztof Drewniak unsigned int width = umin.getBitWidth(); 59*95aff23eSKrzysztof Drewniak APInt smin, smax; 60*95aff23eSKrzysztof Drewniak if (umin.isNonNegative() == umax.isNonNegative()) { 61*95aff23eSKrzysztof Drewniak smin = umin.slt(umax) ? umin : umax; 62*95aff23eSKrzysztof Drewniak smax = umin.sgt(umax) ? umin : umax; 63*95aff23eSKrzysztof Drewniak } else { 64*95aff23eSKrzysztof Drewniak smin = APInt::getSignedMinValue(width); 65*95aff23eSKrzysztof Drewniak smax = APInt::getSignedMaxValue(width); 66*95aff23eSKrzysztof Drewniak } 67*95aff23eSKrzysztof Drewniak return {umin, umax, smin, smax}; 68*95aff23eSKrzysztof Drewniak } 69*95aff23eSKrzysztof Drewniak 70*95aff23eSKrzysztof Drewniak ConstantIntRanges 71*95aff23eSKrzysztof Drewniak ConstantIntRanges::rangeUnion(const ConstantIntRanges &other) const { 72*95aff23eSKrzysztof Drewniak // "Not an integer" poisons everything and also cannot be fed to comparison 73*95aff23eSKrzysztof Drewniak // operators. 74*95aff23eSKrzysztof Drewniak if (umin().getBitWidth() == 0) 75*95aff23eSKrzysztof Drewniak return *this; 76*95aff23eSKrzysztof Drewniak if (other.umin().getBitWidth() == 0) 77*95aff23eSKrzysztof Drewniak return other; 78*95aff23eSKrzysztof Drewniak 79*95aff23eSKrzysztof Drewniak const APInt &uminUnion = umin().ult(other.umin()) ? umin() : other.umin(); 80*95aff23eSKrzysztof Drewniak const APInt &umaxUnion = umax().ugt(other.umax()) ? umax() : other.umax(); 81*95aff23eSKrzysztof Drewniak const APInt &sminUnion = smin().slt(other.smin()) ? smin() : other.smin(); 82*95aff23eSKrzysztof Drewniak const APInt &smaxUnion = smax().sgt(other.smax()) ? smax() : other.smax(); 83*95aff23eSKrzysztof Drewniak 84*95aff23eSKrzysztof Drewniak return {uminUnion, umaxUnion, sminUnion, smaxUnion}; 85*95aff23eSKrzysztof Drewniak } 86*95aff23eSKrzysztof Drewniak 87*95aff23eSKrzysztof Drewniak Optional<APInt> ConstantIntRanges::getConstantValue() const { 88*95aff23eSKrzysztof Drewniak // Note: we need to exclude the trivially-equal width 0 values here. 89*95aff23eSKrzysztof Drewniak if (umin() == umax() && umin().getBitWidth() != 0) 90*95aff23eSKrzysztof Drewniak return umin(); 91*95aff23eSKrzysztof Drewniak if (smin() == smax() && smin().getBitWidth() != 0) 92*95aff23eSKrzysztof Drewniak return smin(); 93*95aff23eSKrzysztof Drewniak return None; 94*95aff23eSKrzysztof Drewniak } 95*95aff23eSKrzysztof Drewniak 96*95aff23eSKrzysztof Drewniak raw_ostream &mlir::operator<<(raw_ostream &os, const ConstantIntRanges &range) { 97*95aff23eSKrzysztof Drewniak return os << "unsigned : [" << range.umin() << ", " << range.umax() 98*95aff23eSKrzysztof Drewniak << "] signed : [" << range.smin() << ", " << range.smax() << "]"; 99*95aff23eSKrzysztof Drewniak } 100