Skip to content

Commit 3509ead

Browse files
Cleanup ConvertToStream to accomodate llvm/llvm-project@3f136f7 (#19451)
The upstream change llvm/llvm-project@3f136f7 allows `ConvertToStream` to better handle the 1:N type conversion, specifically the type conversion of a `tensor<...>` to `!stream.resource<*>, index`. Now instead of trying to work around `builtin.unrealized_conversion_cast`s the conversion can get the converted values directly using the `OneToNAdaptor` and can also replace a `tensor<..>` directly with multiple values using the `ConversionPatternRewriter::replaceOpWithMultiple`. These changes are required to drop the revert of llvm/llvm-project#116470 in the IREE ToM. The change drops these reverts as well. Fixes #19448 --------- Signed-off-by: MaheshRavishankar <[email protected]>
1 parent 72d98bc commit 3509ead

File tree

10 files changed

+418
-362
lines changed

10 files changed

+418
-362
lines changed

compiler/src/iree/compiler/Dialect/Stream/Conversion/FlowToStream/Patterns.cpp

Lines changed: 200 additions & 141 deletions
Large diffs are not rendered by default.

compiler/src/iree/compiler/Dialect/Stream/Conversion/HALToStream/Patterns.cpp

Lines changed: 44 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,14 @@ namespace mlir::iree_compiler {
1616

1717
namespace {
1818

19+
/// Flatten the given value ranges into a single vector of values.
20+
static SmallVector<Value> flattenValues(ArrayRef<ValueRange> values) {
21+
SmallVector<Value> result;
22+
for (const auto &vals : values)
23+
llvm::append_range(result, vals);
24+
return result;
25+
}
26+
1927
// %1 = hal.tensor.import %0 : !hal.buffer_view -> tensor<4xf32>
2028
// ->
2129
// %1 = stream.tensor.import %0 : !hal.buffer_view ->
@@ -24,7 +32,7 @@ struct ConvertTensorImportOp
2432
: public AffinityOpConversionPattern<IREE::HAL::TensorImportOp> {
2533
using AffinityOpConversionPattern::AffinityOpConversionPattern;
2634
LogicalResult matchAndRewriteOnAffinity(
27-
IREE::HAL::TensorImportOp op, OpAdaptor adaptor,
35+
IREE::HAL::TensorImportOp op, OneToNOpAdaptor adaptor,
2836
IREE::Stream::AffinityAttr executionAffinityAttr,
2937
ConversionPatternRewriter &rewriter) const override {
3038
auto sourceType = op.getSource().getType();
@@ -42,9 +50,9 @@ struct ConvertTensorImportOp
4250
// mistake and it's better to know of a shape mismatch than just buffer
4351
// byte length difference.
4452
if (auto tensorType = llvm::dyn_cast<RankedTensorType>(targetType)) {
45-
if (failed(buildEncodingAssertions(op.getLoc(), adaptor.getSource(),
46-
op.getNameAttr(), tensorType,
47-
op.getTargetDims(), rewriter))) {
53+
if (failed(buildEncodingAssertions(
54+
op.getLoc(), adaptor.getSource().front(), op.getNameAttr(),
55+
tensorType, op.getTargetDims(), rewriter))) {
4856
return rewriter.notifyMatchFailure(op, "unsupported tensor type");
4957
}
5058
}
@@ -55,11 +63,12 @@ struct ConvertTensorImportOp
5563
IREE::Stream::Lifetime::External);
5664
Value resultSize = rewriter.create<IREE::Stream::TensorSizeOfOp>(
5765
op.getLoc(), rewriter.getIndexType(),
58-
TypeAttr::get(op.getTarget().getType()), adaptor.getTargetDims(),
59-
executionAffinityAttr);
66+
TypeAttr::get(op.getTarget().getType()),
67+
flattenValues(adaptor.getTargetDims()), executionAffinityAttr);
6068
Value resource = rewriter.create<IREE::Stream::TensorImportOp>(
61-
op.getLoc(), resultType, adaptor.getSource(), TypeAttr::get(targetType),
62-
adaptor.getTargetDims(), resultSize, executionAffinityAttr);
69+
op.getLoc(), resultType, adaptor.getSource().front(),
70+
TypeAttr::get(targetType), flattenValues(adaptor.getTargetDims()),
71+
resultSize, executionAffinityAttr);
6372

6473
// Await the fence, if needed. When not specified the resource is assumed to
6574
// be immediately available.
@@ -75,10 +84,11 @@ struct ConvertTensorImportOp
7584
}
7685

7786
auto unknownType = rewriter.getType<IREE::Stream::ResourceType>();
78-
rewriter.replaceOpWithNewOp<IREE::Stream::AsyncTransferOp>(
79-
op, unknownType, resource, resultSize, resultSize,
87+
Value newImport = rewriter.create<IREE::Stream::AsyncTransferOp>(
88+
op.getLoc(), unknownType, resource, resultSize, resultSize,
8089
/*source_affinity=*/executionAffinityAttr,
8190
/*target_affinity=*/executionAffinityAttr);
91+
rewriter.replaceOpWithMultiple(op, {{newImport, resultSize}});
8292
return success();
8393
}
8494

@@ -125,7 +135,7 @@ struct ConvertTensorExportOp
125135
: public AffinityOpConversionPattern<IREE::HAL::TensorExportOp> {
126136
using AffinityOpConversionPattern::AffinityOpConversionPattern;
127137
LogicalResult matchAndRewriteOnAffinity(
128-
IREE::HAL::TensorExportOp op, OpAdaptor adaptor,
138+
IREE::HAL::TensorExportOp op, OneToNOpAdaptor adaptor,
129139
IREE::Stream::AffinityAttr executionAffinityAttr,
130140
ConversionPatternRewriter &rewriter) const override {
131141
auto sourceType = op.getSourceEncoding();
@@ -136,12 +146,12 @@ struct ConvertTensorExportOp
136146
}
137147

138148
auto source =
139-
transferTensorOperand(op.getLoc(), op.getSource(), adaptor.getSource(),
140-
executionAffinityAttr, rewriter);
149+
transferTensorOperands(op.getLoc(), op.getSource(), adaptor.getSource(),
150+
executionAffinityAttr, rewriter);
141151

142152
// Exporting a produced value - transfer our source value to an externally
143153
// usable resource and directly export it. This will cause an allocation.
144-
auto exportSource = adaptor.getSource();
154+
Value exportSource = adaptor.getSource().front();
145155
auto externalType = rewriter.getType<IREE::Stream::ResourceType>(
146156
IREE::Stream::Lifetime::External);
147157
if (source.resource.getType() != externalType) {
@@ -154,7 +164,8 @@ struct ConvertTensorExportOp
154164
// Export (stream resource to buffer view).
155165
rewriter.replaceOpWithNewOp<IREE::Stream::TensorExportOp>(
156166
op, targetType, exportSource, TypeAttr::get(sourceType),
157-
adaptor.getSourceDims(), source.resourceSize, executionAffinityAttr);
167+
flattenValues(adaptor.getSourceDims()), source.resourceSize,
168+
executionAffinityAttr);
158169
return success();
159170
}
160171
};
@@ -174,19 +185,21 @@ struct ConvertTensorAliasOp
174185
: public AffinityOpConversionPattern<IREE::HAL::TensorAliasOp> {
175186
using AffinityOpConversionPattern::AffinityOpConversionPattern;
176187
LogicalResult matchAndRewriteOnAffinity(
177-
IREE::HAL::TensorAliasOp op, OpAdaptor adaptor,
188+
IREE::HAL::TensorAliasOp op, OneToNOpAdaptor adaptor,
178189
IREE::Stream::AffinityAttr executionAffinityAttr,
179190
ConversionPatternRewriter &rewriter) const override {
180191
auto sourceType = op.getSource().getType();
181192
auto source =
182-
transferTensorOperand(op.getLoc(), op.getSource(), adaptor.getSource(),
183-
executionAffinityAttr, rewriter);
193+
transferTensorOperands(op.getLoc(), op.getSource(), adaptor.getSource(),
194+
executionAffinityAttr, rewriter);
184195

185196
// Query the target storage buffer length; we will only populate up to
186197
// what is required for the output.
198+
SmallVector<Value> convertedSourceDims =
199+
flattenValues(adaptor.getSourceDims());
187200
Value storageSize = rewriter.create<IREE::Stream::TensorSizeOfOp>(
188201
op.getLoc(), rewriter.getIndexType(),
189-
TypeAttr::get(op.getSource().getType()), adaptor.getSourceDims(),
202+
TypeAttr::get(op.getSource().getType()), convertedSourceDims,
190203
executionAffinityAttr);
191204

192205
// Import the target storage as a resource that we can use as an update
@@ -195,8 +208,8 @@ struct ConvertTensorAliasOp
195208
auto externalType = rewriter.getType<IREE::Stream::ResourceType>(
196209
IREE::Stream::Lifetime::External);
197210
auto importOp = rewriter.create<IREE::Stream::TensorImportOp>(
198-
op.getLoc(), externalType, adaptor.getStorage(),
199-
TypeAttr::get(sourceType), adaptor.getSourceDims(), storageSize,
211+
op.getLoc(), externalType, adaptor.getStorage().front(),
212+
TypeAttr::get(sourceType), convertedSourceDims, storageSize,
200213
executionAffinityAttr);
201214

202215
// Await the fence, if needed. When not specified the storage is assumed to
@@ -235,7 +248,7 @@ struct ConvertTensorAliasOp
235248
op.getLoc(), source.resource.getType(), result, source.resourceSize,
236249
source.resourceSize, executionAffinityAttr, executionAffinityAttr);
237250
}
238-
rewriter.replaceOp(op, result);
251+
rewriter.replaceOpWithMultiple(op, {{result, source.resourceSize}});
239252

240253
return success();
241254
}
@@ -254,20 +267,22 @@ struct ConvertTensorBarrierOp
254267
: public AffinityAwareConversionPattern<IREE::HAL::TensorBarrierOp> {
255268
using AffinityAwareConversionPattern::AffinityAwareConversionPattern;
256269
LogicalResult
257-
matchAndRewrite(IREE::HAL::TensorBarrierOp op, OpAdaptor adaptor,
270+
matchAndRewrite(IREE::HAL::TensorBarrierOp op, OneToNOpAdaptor adaptor,
258271
ConversionPatternRewriter &rewriter) const override {
259272
auto timepointType = rewriter.getType<IREE::Stream::TimepointType>();
260273
IREE::Stream::AffinityAttr anyAffinityAttr;
261274
SmallVector<Value> signaledResources;
275+
SmallVector<Value> signaledResourceSizes;
262276
SmallVector<Value> signaledTimepoints;
263277
for (auto [sourceTensor, sourceResource] :
264278
llvm::zip_equal(op.getSources(), adaptor.getSources())) {
265-
auto source = resolveTensorOperand(op.getLoc(), sourceTensor,
266-
sourceResource, rewriter);
279+
auto source = resolveTensorOperands(op.getLoc(), sourceTensor,
280+
sourceResource, rewriter);
267281
auto barrierOp = rewriter.create<IREE::Stream::TimepointBarrierOp>(
268-
sourceResource.getLoc(), source.resource.getType(), timepointType,
269-
source.resource, source.resourceSize, source.affinity);
282+
sourceResource.front().getLoc(), source.resource.getType(),
283+
timepointType, source.resource, source.resourceSize, source.affinity);
270284
signaledResources.push_back(barrierOp.getResult());
285+
signaledResourceSizes.push_back(source.resourceSize);
271286
signaledTimepoints.push_back(barrierOp.getResultTimepoint());
272287

273288
// When joining from multiple affinities we need to pick one to perform
@@ -283,7 +298,8 @@ struct ConvertTensorBarrierOp
283298
rewriter.create<IREE::Stream::TimepointChainExternalOp>(
284299
op.getLoc(), joinedTimepoint, ValueRange{adaptor.getSignalFence()},
285300
anyAffinityAttr);
286-
rewriter.replaceOp(op, signaledResources);
301+
replaceOpWithMultiple(op, signaledResources, signaledResourceSizes,
302+
rewriter);
287303
return success();
288304
}
289305
};

compiler/src/iree/compiler/Dialect/Stream/Conversion/PatternUtils.cpp

Lines changed: 34 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -44,73 +44,25 @@ tryLookupResultAffinity(Value value,
4444
return affinityAnalysis->lookupResourceAffinity(value);
4545
}
4646

47-
static std::pair<Value, Value>
48-
resolveTensorOperand(Location loc, Value convertedOperand, OpBuilder &builder) {
49-
auto operandType = convertedOperand.getType();
50-
if (llvm::isa<IREE::Stream::ResourceType>(operandType)) {
51-
// Prior to https://reviews.llvm.org/D111620 this is the path we'd take;
52-
// the tensor operands would be remapped into their new resource types.
53-
// This is still possible during rewriting if we ourselves produce a new
54-
// resource type, but the automatic materialization will go down the
55-
// unrealized_conversion_cast path below.
56-
return std::make_pair(convertedOperand,
57-
builder.createOrFold<IREE::Stream::ResourceSizeOp>(
58-
loc, builder.getIndexType(), convertedOperand));
59-
} else if (auto castOp =
60-
convertedOperand
61-
.getDefiningOp<mlir::UnrealizedConversionCastOp>()) {
62-
// We only have a single tensor type conversion and it expands to (resource,
63-
// size) so that's all we look for here.
64-
assert(castOp.getNumOperands() == 2 && "expected (resource, size)");
65-
return std::make_pair(castOp.getOperand(0), castOp.getOperand(1));
66-
}
67-
assert(false &&
68-
"unexpected operand; expected either a IREE::Stream::ResourceType or "
69-
"the result of a mlir::UnrealizedConversionCastOp");
70-
return std::make_pair(Value{}, Value{});
71-
}
72-
73-
void expandResourceOperand(Location loc, Value operand,
74-
SmallVectorImpl<Value> &newOperands,
75-
OpBuilder &builder) {
76-
if (llvm::isa<TensorType>(operand.getType())) {
77-
auto [resource, resourceSize] = resolveTensorOperand(loc, operand, builder);
78-
newOperands.push_back(resource);
79-
newOperands.push_back(resourceSize);
80-
} else if (llvm::isa<IREE::Stream::ResourceType>(operand.getType())) {
81-
newOperands.push_back(operand);
82-
newOperands.push_back(
83-
builder.createOrFold<IREE::Stream::ResourceSizeOp>(loc, operand));
84-
} else {
85-
newOperands.push_back(operand);
86-
}
87-
}
88-
89-
SmallVector<Value> expandResourceOperands(Location loc, ValueRange operands,
90-
ConversionPatternRewriter &rewriter) {
91-
SmallVector<Value> expandedOperands;
92-
expandedOperands.reserve(operands.size());
93-
for (auto operand : operands) {
94-
expandResourceOperand(loc, operand, expandedOperands, rewriter);
95-
}
96-
return expandedOperands;
97-
}
98-
99-
ConvertedTensor resolveTensorOperand(
100-
Location loc, Value originalOperand, Value convertedOperand,
47+
ConvertedTensor resolveTensorOperands(
48+
Location loc, Value originalOperand, ValueRange convertedOperand,
10149
IREE::Stream::AffinityAnalysis *affinityAnalysis, OpBuilder &builder) {
102-
auto [resource, resourceSize] =
103-
resolveTensorOperand(loc, convertedOperand, builder);
50+
assert(convertedOperand.size() == 2 &&
51+
"expected tensor operands to be converted to `!stream.resource<*>, "
52+
"index`");
10453
auto affinityAttr = affinityAnalysis->lookupResourceAffinity(originalOperand);
105-
return {affinityAttr, resource, resourceSize};
54+
return {affinityAttr, convertedOperand[0], convertedOperand[1]};
10655
}
10756

108-
ConvertedTensor transferTensorOperand(
109-
Location loc, Value originalOperand, Value convertedOperand,
57+
ConvertedTensor transferTensorOperands(
58+
Location loc, Value originalOperand, ValueRange convertedOperand,
11059
IREE::Stream::AffinityAttr requiredAffinityAttr,
11160
IREE::Stream::AffinityAnalysis *affinityAnalysis, OpBuilder &builder) {
112-
auto [resource, resourceSize] =
113-
resolveTensorOperand(loc, convertedOperand, builder);
61+
assert(convertedOperand.size() == 2 &&
62+
"expected tensor operands to be converted to `!stream.resource<*>, "
63+
"index`");
64+
Value resource = convertedOperand[0];
65+
Value resourceSize = convertedOperand[1];
11466
auto affinityAttr = affinityAnalysis->lookupResourceAffinity(originalOperand);
11567
if (affinityAttr != requiredAffinityAttr) {
11668
resource = builder.create<IREE::Stream::AsyncTransferOp>(
@@ -120,4 +72,25 @@ ConvertedTensor transferTensorOperand(
12072
return {requiredAffinityAttr, resource, resourceSize};
12173
}
12274

75+
void replaceOpWithMultiple(Operation *op,
76+
ArrayRef<SmallVector<Value>> replacements,
77+
ConversionPatternRewriter &rewriter) {
78+
auto r = llvm::map_to_vector(
79+
replacements, [](ArrayRef<Value> v) -> ValueRange { return v; });
80+
rewriter.replaceOpWithMultiple(op, r);
81+
}
82+
83+
void replaceOpWithMultiple(Operation *op, ValueRange resources,
84+
ValueRange sizes,
85+
ConversionPatternRewriter &rewriter) {
86+
SmallVector<SmallVector<Value>> replacements = llvm::map_to_vector(
87+
llvm::zip_equal(resources, sizes), [](auto it) -> SmallVector<Value> {
88+
if (std::get<1>(it)) {
89+
return {std::get<0>(it), std::get<1>(it)};
90+
}
91+
return {std::get<0>(it)};
92+
});
93+
replaceOpWithMultiple(op, replacements, rewriter);
94+
}
95+
12396
} // namespace mlir::iree_compiler

compiler/src/iree/compiler/Dialect/Stream/Conversion/PatternUtils.h

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -42,18 +42,11 @@ struct ConvertedTensor {
4242
Value resourceSize;
4343
};
4444

45-
void expandResourceOperand(Location loc, Value convertedOperand,
46-
SmallVectorImpl<Value> &newOperands,
47-
OpBuilder &builder);
48-
SmallVector<Value> expandResourceOperands(Location loc,
49-
ValueRange convertedOperands,
50-
ConversionPatternRewriter &rewriter);
51-
52-
ConvertedTensor resolveTensorOperand(
53-
Location loc, Value originalOperand, Value convertedOperand,
45+
ConvertedTensor resolveTensorOperands(
46+
Location loc, Value originalOperand, ValueRange convertedOperand,
5447
IREE::Stream::AffinityAnalysis *affinityAnalysis, OpBuilder &builder);
55-
ConvertedTensor transferTensorOperand(
56-
Location loc, Value originalOperand, Value convertedOperand,
48+
ConvertedTensor transferTensorOperands(
49+
Location loc, Value originalOperand, ValueRange convertedOperand,
5750
IREE::Stream::AffinityAttr requiredAffinityAttr,
5851
IREE::Stream::AffinityAnalysis *affinityAnalysis, OpBuilder &builder);
5952

@@ -72,19 +65,19 @@ struct AffinityAwareConversionPattern : public OpConversionPattern<OpT> {
7265
}
7366

7467
protected:
75-
ConvertedTensor resolveTensorOperand(Location loc, Value originalOperand,
76-
Value convertedOperand,
77-
OpBuilder &builder) const {
78-
return mlir::iree_compiler::resolveTensorOperand(
68+
ConvertedTensor resolveTensorOperands(Location loc, Value originalOperand,
69+
ValueRange convertedOperand,
70+
OpBuilder &builder) const {
71+
return mlir::iree_compiler::resolveTensorOperands(
7972
loc, originalOperand, convertedOperand, affinityAnalysis, builder);
8073
}
8174

8275
ConvertedTensor
83-
transferTensorOperand(Location loc, Value originalOperand,
84-
Value convertedOperand,
85-
IREE::Stream::AffinityAttr requiredAffinityAttr,
86-
OpBuilder &builder) const {
87-
return mlir::iree_compiler::transferTensorOperand(
76+
transferTensorOperands(Location loc, Value originalOperand,
77+
ValueRange convertedOperand,
78+
IREE::Stream::AffinityAttr requiredAffinityAttr,
79+
OpBuilder &builder) const {
80+
return mlir::iree_compiler::transferTensorOperands(
8881
loc, originalOperand, convertedOperand, requiredAffinityAttr,
8982
affinityAnalysis, builder);
9083
}
@@ -110,13 +103,14 @@ struct AffinityOpConversionPattern
110103

111104
protected:
112105
virtual LogicalResult matchAndRewriteOnAffinity(
113-
OpT op, typename OpConversionPattern<OpT>::OpAdaptor adaptor,
106+
OpT op, typename OpConversionPattern<OpT>::OneToNOpAdaptor adaptor,
114107
IREE::Stream::AffinityAttr executionAffinityAttr,
115108
ConversionPatternRewriter &rewriter) const = 0;
116109

117110
private:
118111
LogicalResult
119-
matchAndRewrite(OpT op, typename OpConversionPattern<OpT>::OpAdaptor adaptor,
112+
matchAndRewrite(OpT op,
113+
typename OpConversionPattern<OpT>::OneToNOpAdaptor adaptor,
120114
ConversionPatternRewriter &rewriter) const override final {
121115
auto executionAffinityAttr =
122116
tryLookupExecutionAffinity(op, this->getAffinityAnalysis());
@@ -125,6 +119,13 @@ struct AffinityOpConversionPattern
125119
}
126120
};
127121

122+
void replaceOpWithMultiple(Operation *op,
123+
ArrayRef<SmallVector<Value>> replacements,
124+
ConversionPatternRewriter &rewriter);
125+
void replaceOpWithMultiple(Operation *op, ValueRange resources,
126+
ValueRange sizes,
127+
ConversionPatternRewriter &rewriter);
128+
128129
} // namespace mlir::iree_compiler
129130

130131
#endif // IREE_COMPILER_DIALECT_STREAM_CONVERSION_PATTERN_UTILS_H_

0 commit comments

Comments
 (0)