MLIR  20.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 
15 
16 using namespace mlir;
17 using namespace mlir::affine;
18 
19 FailureOr<OpFoldResult> mlir::affine::reifyValueBound(
22  ValueBoundsConstraintSet::StopConditionFn stopCondition, bool closedUB) {
23  // Compute bound.
24  AffineMap boundMap;
25  ValueDimList mapOperands;
27  boundMap, mapOperands, type, var, stopCondition, closedUB)))
28  return failure();
29 
30  // Reify bound.
31  return affine::materializeComputedBound(b, loc, boundMap, mapOperands);
32 }
33 
35  OpBuilder &b, Location loc, AffineMap boundMap,
36  ArrayRef<std::pair<Value, std::optional<int64_t>>> mapOperands) {
37  // Materialize tensor.dim/memref.dim ops.
38  SmallVector<Value> operands;
39  for (auto valueDim : mapOperands) {
40  Value value = valueDim.first;
41  std::optional<int64_t> dim = valueDim.second;
42 
43  if (!dim.has_value()) {
44  // This is an index-typed value.
45  assert(value.getType().isIndex() && "expected index type");
46  operands.push_back(value);
47  continue;
48  }
49 
50  assert(cast<ShapedType>(value.getType()).isDynamicDim(*dim) &&
51  "expected dynamic dim");
52  if (isa<RankedTensorType>(value.getType())) {
53  // A tensor dimension is used: generate a tensor.dim.
54  operands.push_back(b.create<tensor::DimOp>(loc, value, *dim));
55  } else if (isa<MemRefType>(value.getType())) {
56  // A memref dimension is used: generate a memref.dim.
57  operands.push_back(b.create<memref::DimOp>(loc, value, *dim));
58  } else {
59  llvm_unreachable("cannot generate DimOp for unsupported shaped type");
60  }
61  }
62 
63  // Simplify and return bound.
64  affine::canonicalizeMapAndOperands(&boundMap, &operands);
65  // Check for special cases where no affine.apply op is needed.
66  if (boundMap.isSingleConstant()) {
67  // Bound is a constant: return an IntegerAttr.
68  return static_cast<OpFoldResult>(
70  }
71  // No affine.apply op is needed if the bound is a single SSA value.
72  if (auto expr = dyn_cast<AffineDimExpr>(boundMap.getResult(0)))
73  return static_cast<OpFoldResult>(operands[expr.getPosition()]);
74  if (auto expr = dyn_cast<AffineSymbolExpr>(boundMap.getResult(0)))
75  return static_cast<OpFoldResult>(
76  operands[expr.getPosition() + boundMap.getNumDims()]);
77  // General case: build affine.apply op.
78  return static_cast<OpFoldResult>(
79  b.create<affine::AffineApplyOp>(loc, boundMap, operands).getResult());
80 }
81 
83  OpBuilder &b, Location loc, presburger::BoundType type, Value value,
84  int64_t dim, ValueBoundsConstraintSet::StopConditionFn stopCondition,
85  bool closedUB) {
86  auto reifyToOperands = [&](Value v, std::optional<int64_t> d,
88  // We are trying to reify a bound for `value` in terms of the owning op's
89  // operands. Construct a stop condition that evaluates to "true" for any SSA
90  // value except for `value`. I.e., the bound will be computed in terms of
91  // any SSA values except for `value`. The first such values are operands of
92  // the owner of `value`.
93  return v != value;
94  };
95  return reifyValueBound(b, loc, type, {value, dim},
96  stopCondition ? stopCondition : reifyToOperands,
97  closedUB);
98 }
99 
100 FailureOr<OpFoldResult> mlir::affine::reifyIndexValueBound(
101  OpBuilder &b, Location loc, presburger::BoundType type, Value value,
102  ValueBoundsConstraintSet::StopConditionFn stopCondition, bool closedUB) {
103  auto reifyToOperands = [&](Value v, std::optional<int64_t> d,
104  ValueBoundsConstraintSet &cstr) {
105  return v != value;
106  };
107  return reifyValueBound(b, loc, type, value,
108  stopCondition ? stopCondition : reifyToOperands,
109  closedUB);
110 }
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.
Definition: AffineMap.cpp:381
bool isSingleConstant() const
Returns true if this affine map is a single result constant function.
Definition: AffineMap.cpp:373
unsigned getNumDims() const
Definition: AffineMap.cpp:394
AffineExpr getResult(unsigned idx) const
Definition: AffineMap.cpp:411
IntegerAttr getIndexAttr(int64_t value)
Definition: Builders.cpp:148
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition: Location.h:66
This class helps build Operations.
Definition: Builders.h:216
Operation * create(const OperationState &state)
Creates an operation given the fields represented as an OperationState.
Definition: Builders.cpp:497
This class represents a single result from folding an operation.
Definition: OpDefinition.h:268
bool isIndex() const
Definition: Types.cpp:64
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, bool closedUB=false)
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:129
FailureOr< OpFoldResult > reifyValueBound(OpBuilder &b, Location loc, presburger::BoundType type, const ValueBoundsConstraintSet::Variable &var, ValueBoundsConstraintSet::StopConditionFn stopCondition, bool closedUB=false)
Reify a bound for the given variable in terms of SSA values for which stopCondition is met.
FailureOr< OpFoldResult > reifyIndexValueBound(OpBuilder &b, Location loc, presburger::BoundType type, Value value, ValueBoundsConstraintSet::StopConditionFn stopCondition=nullptr, bool closedUB=false)
Reify a bound for the given index-typed value in terms of SSA values for which stopCondition is met.
void canonicalizeMapAndOperands(AffineMap *map, SmallVectorImpl< Value > *operands)
Modifies both map and operands in-place so as to:
Definition: AffineOps.cpp:1435
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.
FailureOr< OpFoldResult > reifyShapedValueDimBound(OpBuilder &b, Location loc, presburger::BoundType type, Value value, int64_t dim, ValueBoundsConstraintSet::StopConditionFn stopCondition=nullptr, bool closedUB=false)
Reify a bound for the specified dimension of the given shaped value in terms of SSA values for which ...
BoundType
The type of bound: equal, lower bound or upper bound.
Include the generated interface declarations.
SmallVector< std::pair< Value, std::optional< int64_t > >> ValueDimList