MLIR  18.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 
21  Value value, std::optional<int64_t> dim,
23  bool closedUB) {
24  // Compute bound.
25  AffineMap boundMap;
26  ValueDimList mapOperands;
28  boundMap, mapOperands, type, value, dim, stopCondition, closedUB)))
29  return failure();
30 
31  // Reify bound.
32  return affine::materializeComputedBound(b, loc, boundMap, mapOperands);
33 }
34 
36  OpBuilder &b, Location loc, AffineMap boundMap,
37  ArrayRef<std::pair<Value, std::optional<int64_t>>> mapOperands) {
38  // Materialize tensor.dim/memref.dim ops.
39  SmallVector<Value> operands;
40  for (auto valueDim : mapOperands) {
41  Value value = valueDim.first;
42  std::optional<int64_t> dim = valueDim.second;
43 
44  if (!dim.has_value()) {
45  // This is an index-typed value.
46  assert(value.getType().isIndex() && "expected index type");
47  operands.push_back(value);
48  continue;
49  }
50 
51  assert(cast<ShapedType>(value.getType()).isDynamicDim(*dim) &&
52  "expected dynamic dim");
53  if (isa<RankedTensorType>(value.getType())) {
54  // A tensor dimension is used: generate a tensor.dim.
55  operands.push_back(b.create<tensor::DimOp>(loc, value, *dim));
56  } else if (isa<MemRefType>(value.getType())) {
57  // A memref dimension is used: generate a memref.dim.
58  operands.push_back(b.create<memref::DimOp>(loc, value, *dim));
59  } else {
60  llvm_unreachable("cannot generate DimOp for unsupported shaped type");
61  }
62  }
63 
64  // Simplify and return bound.
65  affine::canonicalizeMapAndOperands(&boundMap, &operands);
66  // Check for special cases where no affine.apply op is needed.
67  if (boundMap.isSingleConstant()) {
68  // Bound is a constant: return an IntegerAttr.
69  return static_cast<OpFoldResult>(
71  }
72  // No affine.apply op is needed if the bound is a single SSA value.
73  if (auto expr = dyn_cast<AffineDimExpr>(boundMap.getResult(0)))
74  return static_cast<OpFoldResult>(operands[expr.getPosition()]);
75  if (auto expr = dyn_cast<AffineSymbolExpr>(boundMap.getResult(0)))
76  return static_cast<OpFoldResult>(
77  operands[expr.getPosition() + boundMap.getNumDims()]);
78  // General case: build affine.apply op.
79  return static_cast<OpFoldResult>(
80  b.create<affine::AffineApplyOp>(loc, boundMap, operands).getResult());
81 }
82 
84  OpBuilder &b, Location loc, presburger::BoundType type, Value value,
85  int64_t dim, ValueBoundsConstraintSet::StopConditionFn stopCondition,
86  bool closedUB) {
87  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 
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  return v != value;
105  };
106  return reifyValueBound(b, loc, type, value, /*dim=*/std::nullopt,
107  stopCondition ? stopCondition : reifyToOperands,
108  closedUB);
109 }
static FailureOr< OpFoldResult > reifyValueBound(OpBuilder &b, Location loc, presburger::BoundType type, Value value, std::optional< int64_t > dim, ValueBoundsConstraintSet::StopConditionFn stopCondition, bool closedUB)
A multi-dimensional affine map Affine map's are immutable like Type's, and they are uniqued.
Definition: AffineMap.h:47
int64_t getSingleConstantResult() const
Returns the constant result of this map.
Definition: AffineMap.cpp:361
bool isSingleConstant() const
Returns true if this affine map is a single result constant function.
Definition: AffineMap.cpp:351
unsigned getNumDims() const
Definition: AffineMap.cpp:374
AffineExpr getResult(unsigned idx) const
Definition: AffineMap.cpp:391
IntegerAttr getIndexAttr(int64_t value)
Definition: Builders.cpp:124
This class provides support for representing a failure result, or a valid value of type T.
Definition: LogicalResult.h:78
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition: Location.h:63
This class helps build Operations.
Definition: Builders.h:206
Operation * create(const OperationState &state)
Creates an operation given the fields represented as an OperationState.
Definition: Builders.cpp:446
This class represents a single result from folding an operation.
Definition: OpDefinition.h:266
bool isIndex() const
Definition: Types.cpp:56
static LogicalResult computeBound(AffineMap &resultMap, ValueDimList &mapOperands, presburger::BoundType type, Value value, std::optional< int64_t > dim, StopConditionFn stopCondition, bool closedUB=false)
Compute a bound for the given index-typed value or shape dimension size.
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:125
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:1411
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.
LogicalResult failure(bool isFailure=true)
Utility function to generate a LogicalResult.
Definition: LogicalResult.h:62
bool failed(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a failure value.
Definition: LogicalResult.h:72