MLIR 23.0.0git
IndependenceTransforms.cpp
Go to the documentation of this file.
1//===- IndependenceTransforms.cpp - Make ops independent of values --------===//
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
16using namespace mlir;
17using namespace mlir::tensor;
18
19/// Make the given OpFoldResult independent of all independencies.
20static FailureOr<OpFoldResult> makeIndependent(OpBuilder &b, Location loc,
21 OpFoldResult ofr,
22 ValueRange independencies) {
23 if (isa<Attribute>(ofr))
24 return ofr;
25 Value value = cast<Value>(ofr);
26 AffineMap boundMap;
27 ValueDimList mapOperands;
29 boundMap, mapOperands, presburger::BoundType::UB, value,
30 independencies, ValueBoundsOptions{/*closedUB=*/true})))
31 return failure();
32 return mlir::affine::materializeComputedBound(b, loc, boundMap, mapOperands);
33}
34
35FailureOr<Value> tensor::buildIndependentOp(OpBuilder &b, tensor::PadOp padOp,
36 ValueRange independencies) {
38 b.setInsertionPoint(padOp);
39 Location loc = padOp.getLoc();
40
41 // Non-constant padding not supported.
42 Value constantPadding = padOp.getConstantPaddingValue();
43 if (!constantPadding)
44 return failure();
45
46 SmallVector<OpFoldResult> newMixedLow, newMixedHigh;
47 for (OpFoldResult ofr : padOp.getMixedLowPad()) {
48 auto ub = makeIndependent(b, loc, ofr, independencies);
49 if (failed(ub))
50 return failure();
51 newMixedLow.push_back(*ub);
52 }
53 for (OpFoldResult ofr : padOp.getMixedHighPad()) {
54 auto ub = makeIndependent(b, loc, ofr, independencies);
55 if (failed(ub))
56 return failure();
57 newMixedHigh.push_back(*ub);
58 }
59
60 // Return existing tensor::PadOp if nothing has changed.
61 if (llvm::equal(padOp.getMixedLowPad(), newMixedLow) &&
62 llvm::equal(padOp.getMixedHighPad(), newMixedHigh))
63 return padOp.getResult();
64
65 // Create a new tensor::PadOp.
66 auto newPadOp =
67 PadOp::create(b, loc, padOp.getResultType(), padOp.getSource(),
68 newMixedLow, newMixedHigh, constantPadding,
69 padOp.getNofold(), /*attrs=*/ArrayRef<NamedAttribute>{});
70
71 // Create a tensor::ExtractSliceOp.
72 // Reify the result sizes of the old tensor::PadOp.
73 ReifiedRankedShapedTypeDims reifiedSizes;
74 ReifyRankedShapedTypeOpInterface reifyShapedTypeInterface =
75 dyn_cast<ReifyRankedShapedTypeOpInterface>(padOp.getOperation());
76 if (failed(reifyShapedTypeInterface.reifyResultShapes(b, reifiedSizes)))
77 return failure();
78 SmallVector<OpFoldResult> offsets, sizes, strides;
79 for (int64_t i = 0, e = padOp.getResultType().getRank(); i < e; ++i) {
80 // offset = ub(low_padding) - low_padding
81 OpFoldResult prevLow = padOp.getMixedLowPad()[i];
82 if (isa<Attribute>(prevLow)) {
83 offsets.push_back(b.getIndexAttr(0));
84 } else {
85 offsets.push_back(
86 affine::AffineApplyOp::create(
87 b, loc, b.getAffineDimExpr(0) - b.getAffineDimExpr(1),
88 std::initializer_list<Value>{cast<Value>(newMixedLow[i]),
89 cast<Value>(prevLow)})
90 .getResult());
91 }
92 // size = reified result size
93 if (!padOp.getResultType().isDynamicDim(i)) {
94 sizes.push_back(b.getIndexAttr(padOp.getResultType().getDimSize(i)));
95 } else {
96 sizes.push_back(reifiedSizes[0][i]);
97 }
98 // stride = 1
99 strides.push_back(b.getIndexAttr(1));
100 }
101
102 return ExtractSliceOp::create(b, loc, newPadOp, offsets, sizes, strides)
103 .getResult();
104}
105
107 tensor::EmptyOp emptyOp,
108 ValueRange independencies) {
110 b.setInsertionPoint(emptyOp);
111 Location loc = emptyOp.getLoc();
112
114 for (OpFoldResult ofr : emptyOp.getMixedSizes()) {
115 auto ub = makeIndependent(b, loc, ofr, independencies);
116 if (failed(ub))
117 return failure();
118 newSizes.push_back(*ub);
119 }
120
121 // Return existing tensor::EmptyOp if nothing has changed.
122 if (llvm::equal(emptyOp.getMixedSizes(), newSizes))
123 return emptyOp.getResult();
124
125 // Create a new tensor::EmptyOp.
126 Value newEmptyOp =
127 EmptyOp::create(b, loc, newSizes, emptyOp.getType().getElementType());
128
129 // Create a tensor::ExtractSliceOp.
130 SmallVector<OpFoldResult> offsets(newSizes.size(), b.getIndexAttr(0));
131 SmallVector<OpFoldResult> strides(newSizes.size(), b.getIndexAttr(1));
132 return ExtractSliceOp::create(b, loc, newEmptyOp, offsets,
133 emptyOp.getMixedSizes(), strides)
134 .getResult();
135}
b
Return true if permutation is a valid permutation of the outer_dims_perm (case OuterOrInnerPerm::Oute...
static FailureOr< OpFoldResult > makeIndependent(OpBuilder &b, Location loc, OpFoldResult ofr, ValueRange independencies)
Make the given OpFoldResult independent of all independencies.
A multi-dimensional affine map Affine map's are immutable like Type's, and they are uniqued.
Definition AffineMap.h:46
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition Location.h:76
RAII guard to reset the insertion point of the builder when destroyed.
Definition Builders.h:350
This class helps build Operations.
Definition Builders.h:209
This class represents a single result from folding an operation.
static LogicalResult computeIndependentBound(AffineMap &resultMap, ValueDimList &mapOperands, presburger::BoundType type, const Variable &var, ValueRange independencies, ValueBoundsOptions options={})
Compute a bound in that is independent of all values in independencies.
This class provides an abstraction over the different types of ranges over Values.
Definition ValueRange.h:389
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition Value.h:96
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< Value > buildIndependentOp(OpBuilder &b, tensor::PadOp padOp, ValueRange independencies)
Build a new tensor::PadOp with low/high padding that is independent of all given independencies.
Include the generated interface declarations.
SmallVector< SmallVector< OpFoldResult > > ReifiedRankedShapedTypeDims
SmallVector< std::pair< Value, std::optional< int64_t > >, 2 > ValueDimList
Options that control value bound computation.