MLIR 23.0.0git
ReifyValueBounds.cpp
Go to the documentation of this file.
1//===- ReifyValueBounds.cpp --- Reify value bounds with affine ops ------*-===//
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
10
16
17using namespace mlir;
18using namespace mlir::affine;
19
20FailureOr<OpFoldResult> mlir::affine::reifyValueBound(
25 // Compute bound.
26 AffineMap boundMap;
27 ValueDimList mapOperands;
29 boundMap, mapOperands, type, var, stopCondition, options)))
30 return failure();
31
32 // Reify bound.
33 return affine::materializeComputedBound(b, loc, boundMap, mapOperands);
34}
35
37 OpBuilder &b, Location loc, AffineMap boundMap,
38 ArrayRef<std::pair<Value, std::optional<int64_t>>> mapOperands) {
39 // Materialize tensor.dim/memref.dim ops.
40 SmallVector<Value> operands;
41 for (auto valueDim : mapOperands) {
42 Value value = valueDim.first;
43 std::optional<int64_t> dim = valueDim.second;
44
45 if (!dim.has_value()) {
46 // This is an index-typed/integer-typed value.
47 assert(
48 (value.getType().isIndex() || value.getType().isSignlessInteger()) &&
49 "expected index or signless integer type");
50 if (value.getType().isSignlessInteger())
51 value = arith::IndexCastOp::create(b, loc, b.getIndexType(), value);
52 operands.push_back(value);
53 continue;
54 }
55
56 assert(cast<ShapedType>(value.getType()).isDynamicDim(*dim) &&
57 "expected dynamic dim");
58 if (isa<RankedTensorType>(value.getType())) {
59 // A tensor dimension is used: generate a tensor.dim.
60 operands.push_back(tensor::DimOp::create(b, loc, value, *dim));
61 } else if (isa<MemRefType>(value.getType())) {
62 // A memref dimension is used: generate a memref.dim.
63 operands.push_back(memref::DimOp::create(b, loc, value, *dim));
64 } else {
65 llvm_unreachable("cannot generate DimOp for unsupported shaped type");
66 }
67 }
68
69 // Simplify and return bound.
70 affine::canonicalizeMapAndOperands(&boundMap, &operands);
71 // Check for special cases where no affine.apply op is needed.
72 if (boundMap.isSingleConstant()) {
73 // Bound is a constant: return an IntegerAttr.
74 return static_cast<OpFoldResult>(
75 b.getIndexAttr(boundMap.getSingleConstantResult()));
76 }
77 // No affine.apply op is needed if the bound is a single SSA value.
78 if (auto expr = dyn_cast<AffineDimExpr>(boundMap.getResult(0)))
79 return static_cast<OpFoldResult>(operands[expr.getPosition()]);
80 if (auto expr = dyn_cast<AffineSymbolExpr>(boundMap.getResult(0)))
81 return static_cast<OpFoldResult>(
82 operands[expr.getPosition() + boundMap.getNumDims()]);
83 // General case: build affine.apply op.
84 return static_cast<OpFoldResult>(
85 affine::AffineApplyOp::create(b, loc, boundMap, operands).getResult());
86}
87
92 auto reifyToOperands = [&](Value v, std::optional<int64_t> d,
94 // We are trying to reify a bound for `value` in terms of the owning op's
95 // operands. Construct a stop condition that evaluates to "true" for any SSA
96 // value except for `value`. I.e., the bound will be computed in terms of
97 // any SSA values except for `value`. The first such values are operands of
98 // the owner of `value`.
99 return v != value;
100 };
101 return reifyValueBound(b, loc, type, {value, dim},
102 stopCondition ? stopCondition : reifyToOperands,
103 options);
104}
105
110 auto reifyToOperands = [&](Value v, std::optional<int64_t> d,
112 return v != value;
113 };
114 return reifyValueBound(b, loc, type, value,
115 stopCondition ? stopCondition : reifyToOperands,
116 options);
117}
b
Return true if permutation is a valid permutation of the outer_dims_perm (case OuterOrInnerPerm::Oute...
static llvm::ManagedStatic< PassManagerOptions > options
A multi-dimensional affine map Affine map's are immutable like Type's, and they are uniqued.
Definition AffineMap.h:46
int64_t getSingleConstantResult() const
Returns the constant result of this map.
bool isSingleConstant() const
Returns true if this affine map is a single result constant function.
unsigned getNumDims() const
AffineExpr getResult(unsigned idx) const
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition Location.h:76
This class helps build Operations.
Definition Builders.h:209
This class represents a single result from folding an operation.
bool isSignlessInteger() const
Return true if this is a signless integer type (with the specified width).
Definition Types.cpp:66
bool isIndex() const
Definition Types.cpp:56
A variable that can be added to the constraint set as a "column".
A helper class to be used with ValueBoundsOpInterface.
static LogicalResult computeBound(AffineMap &resultMap, ValueDimList &mapOperands, presburger::BoundType type, const Variable &var, StopConditionFn stopCondition, ValueBoundsOptions options={})
Compute a bound for the given variable.
std::function< bool( Value, std::optional< int64_t >, ValueBoundsConstraintSet &cstr)> StopConditionFn
The stop condition when traversing the backward slice of a shaped value/ index-type value.
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition Value.h:96
Type getType() const
Return the type of this value.
Definition Value.h:105
FailureOr< OpFoldResult > reifyValueBound(OpBuilder &b, Location loc, presburger::BoundType type, const ValueBoundsConstraintSet::Variable &var, ValueBoundsConstraintSet::StopConditionFn stopCondition, ValueBoundsOptions options={})
Reify a bound for the given variable in terms of SSA values for which stopCondition is met.
FailureOr< OpFoldResult > reifyShapedValueDimBound(OpBuilder &b, Location loc, presburger::BoundType type, Value value, int64_t dim, ValueBoundsConstraintSet::StopConditionFn stopCondition=nullptr, ValueBoundsOptions options={})
Reify a bound for the specified dimension of the given shaped value in terms of SSA values for which ...
void canonicalizeMapAndOperands(AffineMap *map, SmallVectorImpl< Value > *operands)
Modifies both map and operands in-place so as to:
FailureOr< OpFoldResult > reifyIndexValueBound(OpBuilder &b, Location loc, presburger::BoundType type, Value value, ValueBoundsConstraintSet::StopConditionFn stopCondition=nullptr, ValueBoundsOptions options={})
Reify a bound for the given index-typed value in terms of SSA values for which stopCondition is met.
OpFoldResult materializeComputedBound(OpBuilder &b, Location loc, AffineMap boundMap, ArrayRef< std::pair< Value, std::optional< int64_t > > > mapOperands)
Materialize an already computed bound with Affine dialect ops.
BoundType
The type of bound: equal, lower bound or upper bound.
Include the generated interface declarations.
SmallVector< std::pair< Value, std::optional< int64_t > >, 2 > ValueDimList
Options that control value bound computation.