15#define DEBUG_TYPE "int-range-analysis"
24 if (bitEnumContainsAny(flags, arith::IntegerOverflowFlags::nsw))
26 if (bitEnumContainsAny(flags, arith::IntegerOverflowFlags::nuw))
37 if (
auto scalarCstAttr = llvm::dyn_cast_or_null<IntegerAttr>(getValue())) {
38 const APInt &value = scalarCstAttr.getValue();
42 if (
auto arrayCstAttr =
43 llvm::dyn_cast_or_null<DenseIntElementsAttr>(getValue())) {
44 if (arrayCstAttr.isSplat()) {
46 arrayCstAttr.getSplatValue<APInt>()));
50 std::optional<ConstantIntRanges>
result;
51 for (
const APInt &val : arrayCstAttr) {
56 assert(
result &&
"Zero-sized vectors are not allowed");
57 setResultRange(getResult(), *
result);
66void arith::AddIOp::inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,
69 getOverflowFlags())));
76void arith::SubIOp::inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,
79 getOverflowFlags())));
86void arith::MulIOp::inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,
89 getOverflowFlags())));
96void arith::DivUIOp::inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,
98 setResultRange(getResult(),
inferDivU(argRanges));
105void arith::DivSIOp::inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,
107 setResultRange(getResult(),
inferDivS(argRanges));
114void arith::CeilDivUIOp::inferResultRanges(
115 ArrayRef<ConstantIntRanges> argRanges,
SetIntRangeFn setResultRange) {
123void arith::CeilDivSIOp::inferResultRanges(
124 ArrayRef<ConstantIntRanges> argRanges,
SetIntRangeFn setResultRange) {
132void arith::FloorDivSIOp::inferResultRanges(
133 ArrayRef<ConstantIntRanges> argRanges,
SetIntRangeFn setResultRange) {
141void arith::RemUIOp::inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,
143 setResultRange(getResult(),
inferRemU(argRanges));
150void arith::RemSIOp::inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,
152 setResultRange(getResult(),
inferRemS(argRanges));
159void arith::AndIOp::inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,
161 setResultRange(getResult(),
inferAnd(argRanges));
168void arith::OrIOp::inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,
170 setResultRange(getResult(),
inferOr(argRanges));
177void arith::XOrIOp::inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,
179 setResultRange(getResult(),
inferXor(argRanges));
186void arith::MaxSIOp::inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,
188 setResultRange(getResult(),
inferMaxS(argRanges));
195void arith::MaxUIOp::inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,
197 setResultRange(getResult(),
inferMaxU(argRanges));
204void arith::MinSIOp::inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,
206 setResultRange(getResult(),
inferMinS(argRanges));
213void arith::MinUIOp::inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,
215 setResultRange(getResult(),
inferMinU(argRanges));
222void arith::ExtUIOp::inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,
226 setResultRange(getResult(),
extUIRange(argRanges[0], destWidth));
233void arith::ExtSIOp::inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,
237 setResultRange(getResult(),
extSIRange(argRanges[0], destWidth));
244void arith::TruncIOp::inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,
248 setResultRange(getResult(),
truncRange(argRanges[0], destWidth));
255void arith::IndexCastOp::inferResultRanges(
256 ArrayRef<ConstantIntRanges> argRanges,
SetIntRangeFn setResultRange) {
257 Type sourceType = getOperand().getType();
258 Type destType = getResult().getType();
262 if (srcWidth < destWidth)
263 setResultRange(getResult(),
extSIRange(argRanges[0], destWidth));
264 else if (srcWidth > destWidth)
265 setResultRange(getResult(),
truncRange(argRanges[0], destWidth));
267 setResultRange(getResult(), argRanges[0]);
274void arith::IndexCastUIOp::inferResultRanges(
275 ArrayRef<ConstantIntRanges> argRanges,
SetIntRangeFn setResultRange) {
276 Type sourceType = getOperand().getType();
277 Type destType = getResult().getType();
281 if (srcWidth < destWidth)
282 setResultRange(getResult(),
extUIRange(argRanges[0], destWidth));
283 else if (srcWidth > destWidth)
284 setResultRange(getResult(),
truncRange(argRanges[0], destWidth));
286 setResultRange(getResult(), argRanges[0]);
293void arith::CmpIOp::inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,
295 arith::CmpIPredicate arithPred = getPredicate();
297 const ConstantIntRanges &
lhs = argRanges[0], &
rhs = argRanges[1];
299 APInt
min = APInt::getZero(1);
300 APInt
max = APInt::getAllOnes(1);
303 if (truthValue.has_value() && *truthValue)
305 else if (truthValue.has_value() && !(*truthValue))
315void arith::SelectOp::inferResultRangesFromOptional(
316 ArrayRef<IntegerValueRange> argRanges,
SetIntLatticeFn setResultRange) {
317 std::optional<APInt> mbCondVal =
318 argRanges[0].isUninitialized()
320 : argRanges[0].getValue().getConstantValue();
322 const IntegerValueRange &trueCase = argRanges[1];
323 const IntegerValueRange &falseCase = argRanges[2];
326 if (mbCondVal->isZero())
327 setResultRange(getResult(), falseCase);
329 setResultRange(getResult(), trueCase);
339void arith::ShLIOp::inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,
342 getOverflowFlags())));
349void arith::ShRUIOp::inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,
351 setResultRange(getResult(),
inferShrU(argRanges));
358void arith::ShRSIOp::inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,
360 setResultRange(getResult(),
inferShrS(argRanges));
static intrange::OverflowFlags convertArithOverflowFlags(arith::IntegerOverflowFlags flags)
static Value max(ImplicitLocOpBuilder &builder, Value value, Value bound)
static Value min(ImplicitLocOpBuilder &builder, Value value, Value bound)
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.
static IntegerValueRange join(const IntegerValueRange &lhs, const IntegerValueRange &rhs)
Compute the least upper bound of two ranges.
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.
llvm::function_ref< void(Value, const ConstantIntRanges &)> SetIntRangeFn
The type of the setResultRanges callback provided to ops implementing InferIntRangeInterface.
llvm::function_ref< void(Value, const IntegerValueRange &)> SetIntLatticeFn
Similar to SetIntRangeFn, but operating on IntegerValueRange lattice values.
Type getType(OpFoldResult ofr)
Returns the int type of the integer in ofr.