13 #include "llvm/Support/Debug.h"
16 #define DEBUG_TYPE "int-range-analysis"
25 if (bitEnumContainsAny(flags, arith::IntegerOverflowFlags::nsw))
27 if (bitEnumContainsAny(flags, arith::IntegerOverflowFlags::nuw))
38 if (
auto scalarCstAttr = llvm::dyn_cast_or_null<IntegerAttr>(getValue())) {
39 const APInt &value = scalarCstAttr.getValue();
43 if (
auto arrayCstAttr =
44 llvm::dyn_cast_or_null<DenseIntElementsAttr>(getValue())) {
45 if (arrayCstAttr.isSplat()) {
47 arrayCstAttr.getSplatValue<APInt>()));
51 std::optional<ConstantIntRanges> result;
52 for (
const APInt &val : arrayCstAttr) {
54 result = (result ? result->rangeUnion(range) : range);
57 assert(result &&
"Zero-sized vectors are not allowed");
58 setResultRange(getResult(), *result);
70 getOverflowFlags())));
80 getOverflowFlags())));
90 getOverflowFlags())));
99 setResultRange(getResult(),
inferDivU(argRanges));
108 setResultRange(getResult(),
inferDivS(argRanges));
115 void arith::CeilDivUIOp::inferResultRanges(
124 void arith::CeilDivSIOp::inferResultRanges(
133 void arith::FloorDivSIOp::inferResultRanges(
144 setResultRange(getResult(),
inferRemU(argRanges));
153 setResultRange(getResult(),
inferRemS(argRanges));
162 setResultRange(getResult(),
inferAnd(argRanges));
171 setResultRange(getResult(),
inferOr(argRanges));
180 setResultRange(getResult(),
inferXor(argRanges));
189 setResultRange(getResult(),
inferMaxS(argRanges));
198 setResultRange(getResult(),
inferMaxU(argRanges));
207 setResultRange(getResult(),
inferMinS(argRanges));
216 setResultRange(getResult(),
inferMinU(argRanges));
227 setResultRange(getResult(),
extUIRange(argRanges[0], destWidth));
238 setResultRange(getResult(),
extSIRange(argRanges[0], destWidth));
249 setResultRange(getResult(),
truncRange(argRanges[0], destWidth));
256 void arith::IndexCastOp::inferResultRanges(
258 Type sourceType = getOperand().getType();
259 Type destType = getResult().getType();
263 if (srcWidth < destWidth)
264 setResultRange(getResult(),
extSIRange(argRanges[0], destWidth));
265 else if (srcWidth > destWidth)
266 setResultRange(getResult(),
truncRange(argRanges[0], destWidth));
268 setResultRange(getResult(), argRanges[0]);
275 void arith::IndexCastUIOp::inferResultRanges(
277 Type sourceType = getOperand().getType();
278 Type destType = getResult().getType();
282 if (srcWidth < destWidth)
283 setResultRange(getResult(),
extUIRange(argRanges[0], destWidth));
284 else if (srcWidth > destWidth)
285 setResultRange(getResult(),
truncRange(argRanges[0], destWidth));
287 setResultRange(getResult(), argRanges[0]);
296 arith::CmpIPredicate arithPred = getPredicate();
301 APInt
max = APInt::getAllOnes(1);
304 if (truthValue.has_value() && *truthValue)
306 else if (truthValue.has_value() && !(*truthValue))
316 void arith::SelectOp::inferResultRangesFromOptional(
318 std::optional<APInt> mbCondVal =
319 argRanges[0].isUninitialized()
321 : argRanges[0].getValue().getConstantValue();
327 if (mbCondVal->isZero())
328 setResultRange(getResult(), falseCase);
330 setResultRange(getResult(), trueCase);
343 getOverflowFlags())));
352 setResultRange(getResult(),
inferShrU(argRanges));
361 setResultRange(getResult(),
inferShrS(argRanges));
static intrange::OverflowFlags convertArithOverflowFlags(arith::IntegerOverflowFlags flags)
static Value getZero(OpBuilder &b, Location loc, Type elementType)
Get zero value for an element type.
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 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...
static unsigned getStorageBitwidth(Type type)
Return the bitwidth that should be used for integer ranges describing type.
This lattice value represents the integer range of an SSA value.
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...
ConstantIntRanges inferAnd(ArrayRef< ConstantIntRanges > argRanges)
ConstantIntRanges inferShl(ArrayRef< ConstantIntRanges > argRanges, OverflowFlags ovfFlags=OverflowFlags::None)
ConstantIntRanges inferShrS(ArrayRef< ConstantIntRanges > argRanges)
ConstantIntRanges extSIRange(const ConstantIntRanges &range, unsigned destWidth)
Use the signed values in range to sign-extend it to destWidth.
std::optional< bool > evaluatePred(CmpPredicate pred, const ConstantIntRanges &lhs, const ConstantIntRanges &rhs)
Returns a boolean value if pred is statically true or false for anypossible inputs falling within lhs...
ConstantIntRanges inferMinS(ArrayRef< ConstantIntRanges > argRanges)
ConstantIntRanges inferMaxU(ArrayRef< ConstantIntRanges > argRanges)
ConstantIntRanges inferRemS(ArrayRef< ConstantIntRanges > argRanges)
CmpPredicate
Copy of the enum from arith and index to allow the common integer range infrastructure to not depend ...
ConstantIntRanges inferOr(ArrayRef< ConstantIntRanges > argRanges)
ConstantIntRanges inferSub(ArrayRef< ConstantIntRanges > argRanges, OverflowFlags ovfFlags=OverflowFlags::None)
ConstantIntRanges inferAdd(ArrayRef< ConstantIntRanges > argRanges, OverflowFlags ovfFlags=OverflowFlags::None)
ConstantIntRanges truncRange(const ConstantIntRanges &range, unsigned destWidth)
Truncate range to destWidth bits, taking care to handle cases such as the truncation of [255,...
ConstantIntRanges inferDivU(ArrayRef< ConstantIntRanges > argRanges)
ConstantIntRanges inferCeilDivS(ArrayRef< ConstantIntRanges > argRanges)
ConstantIntRanges inferMinU(ArrayRef< ConstantIntRanges > argRanges)
ConstantIntRanges inferMul(ArrayRef< ConstantIntRanges > argRanges, OverflowFlags ovfFlags=OverflowFlags::None)
ConstantIntRanges inferXor(ArrayRef< ConstantIntRanges > argRanges)
ConstantIntRanges inferDivS(ArrayRef< ConstantIntRanges > argRanges)
ConstantIntRanges inferShrU(ArrayRef< ConstantIntRanges > argRanges)
ConstantIntRanges inferRemU(ArrayRef< ConstantIntRanges > argRanges)
ConstantIntRanges inferFloorDivS(ArrayRef< ConstantIntRanges > argRanges)
ConstantIntRanges inferCeilDivU(ArrayRef< ConstantIntRanges > argRanges)
ConstantIntRanges extUIRange(const ConstantIntRanges &range, unsigned destWidth)
Use the unsigned values in range to zero-extend it to destWidth.
ConstantIntRanges inferMaxS(ArrayRef< ConstantIntRanges > argRanges)
Include the generated interface declarations.
Type getType(OpFoldResult ofr)
Returns the int type of the integer in ofr.