MLIR 23.0.0git
IntegerRangeAnalysis.h
Go to the documentation of this file.
1//===-IntegerRangeAnalysis.h - Integer range analysis -----------*- 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 declares the dataflow analysis class for integer range inference
10// so that it can be used in transformations over the `arith` dialect such as
11// branch elimination or signed->unsigned rewriting.
12//
13// One can also implement InferIntRangeInterface on ops in custom dialects,
14// and then use this analysis to propagate ranges with custom semantics.
15//
16//===----------------------------------------------------------------------===//
17
18#ifndef MLIR_ANALYSIS_DATAFLOW_INTEGERANGEANALYSIS_H
19#define MLIR_ANALYSIS_DATAFLOW_INTEGERANGEANALYSIS_H
20
23
24namespace mlir {
25class RewriterBase;
26namespace dataflow {
27
28/// This lattice element represents the integer value range of an SSA value.
29///
30/// `join` overrides the base behaviour to apply per-state widening: once
31/// the lattice has absorbed enough strictly-increasing merges the range is
32/// forced to its max as a sound over-approximation. This is the sole
33/// convergence guarantee for `IntegerRangeAnalysis` on loop-carried
34/// values; without it, `scf.while` loops with dynamic bounds and nested
35/// region ops can keep the solver ratcheting a loop-carried range by +1
36/// per worklist visit for up to 2^31 iterations on i32. The budget is
37/// sized to be much larger than realistic merge counts on naturally
38/// bounded accumulators (e.g. `arith.minsi`/`arith.andi`-clamped iter
39/// args) so the analysis still converges to a tight range on those.
40///
41/// Note that only the `(const AbstractSparseLattice &)` overload is
42/// overridden, so the widening fires only at framework merge sites
43/// (block-arg / region-successor / callable-arg joins) —
44/// transfer-function updates that go through the non-virtual
45/// `join(const ValueT &)` overload are unaffected.
46class IntegerValueRangeLattice : public Lattice<IntegerValueRange> {
47public:
48 using Lattice::Lattice;
49 // The override below would otherwise hide the inherited
50 // `join(const ValueT &)` overload that callers (e.g. transfer functions)
51 // rely on for direct-value joins.
52 using Lattice::join;
53
55
56private:
57 /// Per-state merge-site change counter. Drives the widening budget in
58 /// `join`.
59 unsigned mergeChangeCount = 0;
60};
61
62/// Integer range analysis determines the integer value range of SSA values
63/// using operations that define `InferIntRangeInterface` and also sets the
64/// range of iteration indices of loops with known bounds.
65///
66/// This analysis depends on DeadCodeAnalysis, and will be a silent no-op
67/// if DeadCodeAnalysis is not loaded in the same solver context.
69 : public SparseForwardDataFlowAnalysis<IntegerValueRangeLattice> {
70public:
72
73 /// At an entry point, we cannot reason about integer value ranges.
74 void setToEntryState(IntegerValueRangeLattice *lattice) override {
76 lattice->getAnchor())));
77 }
78
79 /// Visit an operation. Invoke the transfer function on each operation that
80 /// implements `InferIntRangeInterface`.
81 LogicalResult
85
86 /// Visit block arguments or operation results of an operation with region
87 /// control-flow for which values are not defined by region control-flow. This
88 /// function calls `InferIntRangeInterface` to provide values for block
89 /// arguments or tries to reduce the range on loop induction variables with
90 /// known bounds.
92 Operation *op, const RegionSuccessor &successor,
93 ValueRange nonSuccessorInputs,
94 ArrayRef<IntegerValueRangeLattice *> nonSuccessorInputLattices) override;
95};
96
97/// Succeeds if an op can be converted to its unsigned equivalent without
98/// changing its semantics. This is the case when none of its openands or
99/// results can be below 0 when analyzed from a signed perspective.
100LogicalResult staticallyNonNegative(DataFlowSolver &solver, Operation *op);
101
102/// Succeeds when a value is statically non-negative in that it has a lower
103/// bound on its value (if it is treated as signed) and that bound is
104/// non-negative.
105/// Note, the results of this query may not be accurate for `index` if you plan
106/// to use a non-64-bit index.
107LogicalResult staticallyNonNegative(DataFlowSolver &solver, Value v);
108
109LogicalResult maybeReplaceWithConstant(DataFlowSolver &solver,
110 RewriterBase &rewriter, Value value);
111
112} // end namespace dataflow
113} // end namespace mlir
114
115#endif // MLIR_ANALYSIS_DATAFLOW_INTEGERANGEANALYSIS_H
void propagateIfChanged(AnalysisState *state, ChangeResult changed)
Propagate an update to a state if it changed.
The general data-flow analysis solver.
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...
Operation is the basic unit of execution within MLIR.
Definition Operation.h:88
This class represents a successor of a region.
This class coordinates the application of a rewrite on a set of IR, providing a way for clients to tr...
This class provides an abstraction over the different types of ranges over Values.
Definition ValueRange.h:389
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition Value.h:96
Integer range analysis determines the integer value range of SSA values using operations that define ...
void setToEntryState(IntegerValueRangeLattice *lattice) override
At an entry point, we cannot reason about integer value ranges.
void visitNonControlFlowArguments(Operation *op, const RegionSuccessor &successor, ValueRange nonSuccessorInputs, ArrayRef< IntegerValueRangeLattice * > nonSuccessorInputLattices) override
Visit block arguments or operation results of an operation with region control-flow for which values ...
LogicalResult visitOperation(Operation *op, ArrayRef< const IntegerValueRangeLattice * > operands, ArrayRef< IntegerValueRangeLattice * > results) override
Visit an operation.
SparseForwardDataFlowAnalysis(DataFlowSolver &solver)
This lattice element represents the integer value range of an SSA value.
ChangeResult join(const AbstractSparseLattice &rhs) override
Join the information contained in 'rhs' into this lattice.
This class represents a lattice holding a specific value of type ValueT.
Value getAnchor() const
Return the value this lattice is located at.
ChangeResult join(const AbstractSparseLattice &rhs) override
Join the information contained in the 'rhs' lattice into this lattice.
SparseForwardDataFlowAnalysis(DataFlowSolver &solver)
LogicalResult staticallyNonNegative(DataFlowSolver &solver, Operation *op)
Succeeds if an op can be converted to its unsigned equivalent without changing its semantics.
LogicalResult maybeReplaceWithConstant(DataFlowSolver &solver, RewriterBase &rewriter, Value value)
Patterned after SCCP.
Include the generated interface declarations.
ChangeResult
A result type used to indicate if a change happened.