Skip to content

Commit ab7664c

Browse files
authored
[mlir][integer-range-analysis] expose helpers in header and fix ConstantIntRange print (llvm#127888)
1 parent f5b311e commit ab7664c

File tree

4 files changed

+39
-28
lines changed

4 files changed

+39
-28
lines changed

mlir/include/mlir/Analysis/DataFlow/IntegerRangeAnalysis.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,18 @@ class IntegerRangeAnalysis
7171
unsigned firstIndex) override;
7272
};
7373

74+
/// Succeeds if an op can be converted to its unsigned equivalent without
75+
/// changing its semantics. This is the case when none of its openands or
76+
/// results can be below 0 when analyzed from a signed perspective.
77+
LogicalResult staticallyNonNegative(DataFlowSolver &solver, Operation *op);
78+
79+
/// Succeeds when a value is statically non-negative in that it has a lower
80+
/// bound on its value (if it is treated as signed) and that bound is
81+
/// non-negative.
82+
/// Note, the results of this query may not be accurate for `index` if you plan
83+
/// to use a non-64-bit index.
84+
LogicalResult staticallyNonNegative(DataFlowSolver &solver, Value v);
85+
7486
} // end namespace dataflow
7587
} // end namespace mlir
7688

mlir/lib/Analysis/DataFlow/IntegerRangeAnalysis.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,24 @@
3737
using namespace mlir;
3838
using namespace mlir::dataflow;
3939

40+
namespace mlir::dataflow {
41+
LogicalResult staticallyNonNegative(DataFlowSolver &solver, Value v) {
42+
auto *result = solver.lookupState<IntegerValueRangeLattice>(v);
43+
if (!result || result->getValue().isUninitialized())
44+
return failure();
45+
const ConstantIntRanges &range = result->getValue().getValue();
46+
return success(range.smin().isNonNegative());
47+
}
48+
49+
LogicalResult staticallyNonNegative(DataFlowSolver &solver, Operation *op) {
50+
auto nonNegativePred = [&solver](Value v) -> bool {
51+
return succeeded(staticallyNonNegative(solver, v));
52+
};
53+
return success(llvm::all_of(op->getOperands(), nonNegativePred) &&
54+
llvm::all_of(op->getResults(), nonNegativePred));
55+
}
56+
} // namespace mlir::dataflow
57+
4058
void IntegerValueRangeLattice::onUpdate(DataFlowSolver *solver) const {
4159
Lattice::onUpdate(solver);
4260

mlir/lib/Dialect/Arith/Transforms/UnsignedWhenEquivalent.cpp

Lines changed: 4 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -27,32 +27,6 @@ using namespace mlir;
2727
using namespace mlir::arith;
2828
using namespace mlir::dataflow;
2929

30-
/// Succeeds when a value is statically non-negative in that it has a lower
31-
/// bound on its value (if it is treated as signed) and that bound is
32-
/// non-negative.
33-
// TODO: IntegerRangeAnalysis internally assumes index is 64bit and this pattern
34-
// relies on this. These transformations may not be valid for 32bit index,
35-
// need more investigation.
36-
static LogicalResult staticallyNonNegative(DataFlowSolver &solver, Value v) {
37-
auto *result = solver.lookupState<IntegerValueRangeLattice>(v);
38-
if (!result || result->getValue().isUninitialized())
39-
return failure();
40-
const ConstantIntRanges &range = result->getValue().getValue();
41-
return success(range.smin().isNonNegative());
42-
}
43-
44-
/// Succeeds if an op can be converted to its unsigned equivalent without
45-
/// changing its semantics. This is the case when none of its openands or
46-
/// results can be below 0 when analyzed from a signed perspective.
47-
static LogicalResult staticallyNonNegative(DataFlowSolver &solver,
48-
Operation *op) {
49-
auto nonNegativePred = [&solver](Value v) -> bool {
50-
return succeeded(staticallyNonNegative(solver, v));
51-
};
52-
return success(llvm::all_of(op->getOperands(), nonNegativePred) &&
53-
llvm::all_of(op->getResults(), nonNegativePred));
54-
}
55-
5630
/// Succeeds when the comparison predicate is a signed operation and all the
5731
/// operands are non-negative, indicating that the cmpi operation `op` can have
5832
/// its predicate changed to an unsigned equivalent.
@@ -103,6 +77,10 @@ class DataFlowListener : public RewriterBase::Listener {
10377
DataFlowSolver &s;
10478
};
10579

80+
// TODO: IntegerRangeAnalysis internally assumes index is 64bit and this pattern
81+
// (via staticallyNonNegative) relies on this. These transformations may not be
82+
// valid for 32bit index, need more investigation.
83+
10684
template <typename Signed, typename Unsigned>
10785
struct ConvertOpToUnsigned final : OpRewritePattern<Signed> {
10886
ConvertOpToUnsigned(MLIRContext *context, DataFlowSolver &s)

mlir/lib/Interfaces/InferIntRangeInterface.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,11 @@ std::optional<APInt> ConstantIntRanges::getConstantValue() const {
125125
}
126126

127127
raw_ostream &mlir::operator<<(raw_ostream &os, const ConstantIntRanges &range) {
128-
return os << "unsigned : [" << range.umin() << ", " << range.umax()
129-
<< "] signed : [" << range.smin() << ", " << range.smax() << "]";
128+
os << "unsigned : [";
129+
range.umin().print(os, /*isSigned*/ false);
130+
os << ", ";
131+
range.umax().print(os, /*isSigned*/ false);
132+
return os << "] signed : [" << range.smin() << ", " << range.smax() << "]";
130133
}
131134

132135
IntegerValueRange IntegerValueRange::getMaxRange(Value value) {

0 commit comments

Comments
 (0)