MLIR  18.0.0git
ReifyValueBounds.cpp
Go to the documentation of this file.
1 //===- ReifyValueBounds.cpp --- Reify value bounds with arith 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::arith;
18 
19 /// Build Arith IR for the given affine map and its operands.
21  ValueRange operands) {
22  assert(map.getNumResults() == 1 && "multiple results not supported yet");
23  std::function<Value(AffineExpr)> buildExpr = [&](AffineExpr e) -> Value {
24  switch (e.getKind()) {
26  return b.create<ConstantIndexOp>(loc,
27  cast<AffineConstantExpr>(e).getValue());
29  return operands[cast<AffineDimExpr>(e).getPosition()];
31  return operands[cast<AffineSymbolExpr>(e).getPosition() +
32  map.getNumDims()];
33  case AffineExprKind::Add: {
34  auto binaryExpr = cast<AffineBinaryOpExpr>(e);
35  return b.create<AddIOp>(loc, buildExpr(binaryExpr.getLHS()),
36  buildExpr(binaryExpr.getRHS()));
37  }
38  case AffineExprKind::Mul: {
39  auto binaryExpr = cast<AffineBinaryOpExpr>(e);
40  return b.create<MulIOp>(loc, buildExpr(binaryExpr.getLHS()),
41  buildExpr(binaryExpr.getRHS()));
42  }
44  auto binaryExpr = cast<AffineBinaryOpExpr>(e);
45  return b.create<DivSIOp>(loc, buildExpr(binaryExpr.getLHS()),
46  buildExpr(binaryExpr.getRHS()));
47  }
49  auto binaryExpr = cast<AffineBinaryOpExpr>(e);
50  return b.create<CeilDivSIOp>(loc, buildExpr(binaryExpr.getLHS()),
51  buildExpr(binaryExpr.getRHS()));
52  }
53  case AffineExprKind::Mod: {
54  auto binaryExpr = cast<AffineBinaryOpExpr>(e);
55  return b.create<RemSIOp>(loc, buildExpr(binaryExpr.getLHS()),
56  buildExpr(binaryExpr.getRHS()));
57  }
58  }
59  llvm_unreachable("unsupported AffineExpr kind");
60  };
61  return buildExpr(map.getResult(0));
62 }
63 
66  Value value, std::optional<int64_t> dim,
68  bool closedUB) {
69  // Compute bound.
70  AffineMap boundMap;
71  ValueDimList mapOperands;
73  boundMap, mapOperands, type, value, dim, stopCondition, closedUB)))
74  return failure();
75 
76  // Materialize tensor.dim/memref.dim ops.
77  SmallVector<Value> operands;
78  for (auto valueDim : mapOperands) {
79  Value value = valueDim.first;
80  std::optional<int64_t> dim = valueDim.second;
81 
82  if (!dim.has_value()) {
83  // This is an index-typed value.
84  assert(value.getType().isIndex() && "expected index type");
85  operands.push_back(value);
86  continue;
87  }
88 
89  assert(cast<ShapedType>(value.getType()).isDynamicDim(*dim) &&
90  "expected dynamic dim");
91  if (isa<RankedTensorType>(value.getType())) {
92  // A tensor dimension is used: generate a tensor.dim.
93  operands.push_back(b.create<tensor::DimOp>(loc, value, *dim));
94  } else if (isa<MemRefType>(value.getType())) {
95  // A memref dimension is used: generate a memref.dim.
96  operands.push_back(b.create<memref::DimOp>(loc, value, *dim));
97  } else {
98  llvm_unreachable("cannot generate DimOp for unsupported shaped type");
99  }
100  }
101 
102  // Check for special cases where no arith ops are needed.
103  if (boundMap.isSingleConstant()) {
104  // Bound is a constant: return an IntegerAttr.
105  return static_cast<OpFoldResult>(
106  b.getIndexAttr(boundMap.getSingleConstantResult()));
107  }
108  // No arith ops are needed if the bound is a single SSA value.
109  if (auto expr = dyn_cast<AffineDimExpr>(boundMap.getResult(0)))
110  return static_cast<OpFoldResult>(operands[expr.getPosition()]);
111  if (auto expr = dyn_cast<AffineSymbolExpr>(boundMap.getResult(0)))
112  return static_cast<OpFoldResult>(
113  operands[expr.getPosition() + boundMap.getNumDims()]);
114  // General case: build Arith ops.
115  return static_cast<OpFoldResult>(buildArithValue(b, loc, boundMap, operands));
116 }
117 
119  OpBuilder &b, Location loc, presburger::BoundType type, Value value,
120  int64_t dim, ValueBoundsConstraintSet::StopConditionFn stopCondition,
121  bool closedUB) {
122  auto reifyToOperands = [&](Value v, std::optional<int64_t> d) {
123  // We are trying to reify a bound for `value` in terms of the owning op's
124  // operands. Construct a stop condition that evaluates to "true" for any SSA
125  // value expect for `value`. I.e., the bound will be computed in terms of
126  // any SSA values expect for `value`. The first such values are operands of
127  // the owner of `value`.
128  return v != value;
129  };
130  return reifyValueBound(b, loc, type, value, dim,
131  stopCondition ? stopCondition : reifyToOperands,
132  closedUB);
133 }
134 
136  OpBuilder &b, Location loc, presburger::BoundType type, Value value,
137  ValueBoundsConstraintSet::StopConditionFn stopCondition, bool closedUB) {
138  auto reifyToOperands = [&](Value v, std::optional<int64_t> d) {
139  return v != value;
140  };
141  return reifyValueBound(b, loc, type, value, /*dim=*/std::nullopt,
142  stopCondition ? stopCondition : reifyToOperands,
143  closedUB);
144 }
static FailureOr< OpFoldResult > reifyValueBound(OpBuilder &b, Location loc, presburger::BoundType type, Value value, std::optional< int64_t > dim, ValueBoundsConstraintSet::StopConditionFn stopCondition, bool closedUB)
static Value buildArithValue(OpBuilder &b, Location loc, AffineMap map, ValueRange operands)
Build Arith IR for the given affine map and its operands.
Base type for affine expression.
Definition: AffineExpr.h:68
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
unsigned getNumResults() const
Definition: AffineMap.cpp:382
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 provides an abstraction over the different types of ranges over Values.
Definition: ValueRange.h:378
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
Specialization of arith.constant op that returns an integer of index type.
Definition: Arith.h:90
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.
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
@ CeilDiv
RHS of ceildiv is always a constant or a symbolic expression.
@ Mul
RHS of mul is always a constant or a symbolic expression.
@ Mod
RHS of mod is always a constant or a symbolic expression with a positive value.
@ DimId
Dimensional identifier.
@ FloorDiv
RHS of floordiv is always a constant or a symbolic expression.
@ Constant
Constant integer.
@ SymbolId
Symbolic identifier.
bool failed(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a failure value.
Definition: LogicalResult.h:72