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.empty())
47 if (arrayCstAttr.isSplat()) {
49 arrayCstAttr.getSplatValue<APInt>()));
53 std::optional<ConstantIntRanges>
result;
54 for (
const APInt &val : arrayCstAttr) {
59 setResultRange(getResult(), *
result);
68void arith::AddIOp::inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,
71 getOverflowFlags())));
78void arith::SubIOp::inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,
81 getOverflowFlags())));
88void arith::MulIOp::inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,
91 getOverflowFlags())));
98void arith::DivUIOp::inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,
100 setResultRange(getResult(),
inferDivU(argRanges));
107void arith::DivSIOp::inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,
109 setResultRange(getResult(),
inferDivS(argRanges));
116void arith::CeilDivUIOp::inferResultRanges(
117 ArrayRef<ConstantIntRanges> argRanges,
SetIntRangeFn setResultRange) {
125void arith::CeilDivSIOp::inferResultRanges(
126 ArrayRef<ConstantIntRanges> argRanges,
SetIntRangeFn setResultRange) {
134void arith::FloorDivSIOp::inferResultRanges(
135 ArrayRef<ConstantIntRanges> argRanges,
SetIntRangeFn setResultRange) {
143void arith::RemUIOp::inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,
145 setResultRange(getResult(),
inferRemU(argRanges));
152void arith::RemSIOp::inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,
154 setResultRange(getResult(),
inferRemS(argRanges));
161void arith::AndIOp::inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,
163 setResultRange(getResult(),
inferAnd(argRanges));
170void arith::OrIOp::inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,
172 setResultRange(getResult(),
inferOr(argRanges));
179void arith::XOrIOp::inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,
181 setResultRange(getResult(),
inferXor(argRanges));
188void arith::MaxSIOp::inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,
190 setResultRange(getResult(),
inferMaxS(argRanges));
197void arith::MaxUIOp::inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,
199 setResultRange(getResult(),
inferMaxU(argRanges));
206void arith::MinSIOp::inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,
208 setResultRange(getResult(),
inferMinS(argRanges));
215void arith::MinUIOp::inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,
217 setResultRange(getResult(),
inferMinU(argRanges));
224void arith::ExtUIOp::inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,
228 setResultRange(getResult(),
extUIRange(argRanges[0], destWidth));
235void arith::ExtSIOp::inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,
239 setResultRange(getResult(),
extSIRange(argRanges[0], destWidth));
246void arith::TruncIOp::inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,
250 setResultRange(getResult(),
truncRange(argRanges[0], destWidth));
257void arith::IndexCastOp::inferResultRanges(
258 ArrayRef<ConstantIntRanges> argRanges,
SetIntRangeFn setResultRange) {
259 Type sourceType = getOperand().getType();
260 Type destType = getResult().getType();
264 if (srcWidth < destWidth)
265 setResultRange(getResult(),
extSIRange(argRanges[0], destWidth));
266 else if (srcWidth > destWidth)
267 setResultRange(getResult(),
truncRange(argRanges[0], destWidth));
269 setResultRange(getResult(), argRanges[0]);
276void arith::IndexCastUIOp::inferResultRanges(
277 ArrayRef<ConstantIntRanges> argRanges,
SetIntRangeFn setResultRange) {
278 Type sourceType = getOperand().getType();
279 Type destType = getResult().getType();
283 if (srcWidth < destWidth)
284 setResultRange(getResult(),
extUIRange(argRanges[0], destWidth));
285 else if (srcWidth > destWidth)
286 setResultRange(getResult(),
truncRange(argRanges[0], destWidth));
288 setResultRange(getResult(), argRanges[0]);
295void arith::CmpIOp::inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,
297 arith::CmpIPredicate arithPred = getPredicate();
299 const ConstantIntRanges &
lhs = argRanges[0], &
rhs = argRanges[1];
301 APInt
min = APInt::getZero(1);
302 APInt
max = APInt::getAllOnes(1);
305 if (truthValue.has_value() && *truthValue)
307 else if (truthValue.has_value() && !(*truthValue))
317void arith::SelectOp::inferResultRangesFromOptional(
318 ArrayRef<IntegerValueRange> argRanges,
SetIntLatticeFn setResultRange) {
319 std::optional<APInt> mbCondVal =
320 argRanges[0].isUninitialized()
322 : argRanges[0].getValue().getConstantValue();
324 const IntegerValueRange &trueCase = argRanges[1];
325 const IntegerValueRange &falseCase = argRanges[2];
328 if (mbCondVal->isZero())
329 setResultRange(getResult(), falseCase);
331 setResultRange(getResult(), trueCase);
347void arith::ShLIOp::inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,
350 getOverflowFlags())));
357void arith::ShRUIOp::inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,
359 setResultRange(getResult(),
inferShrU(argRanges));
366void arith::ShRSIOp::inferResultRanges(ArrayRef<ConstantIntRanges> argRanges,
368 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.
bool isUninitialized() const
Whether the range is uninitialized.
static IntegerValueRange getMaxRange(Value value)
Create a maximal range ([0, uint_max(t)] / [int_min(t), int_max(t)]) range that is used to mark the v...
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.