blob: c66e6d0a825a4eb09526577a7012b2619385faba [file] [edit]
// Copyright 2021 The IREE Authors
//
// Licensed under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#include "iree/compiler/Dialect/Stream/Conversion/PatternUtils.h"
#include "iree/compiler/Dialect/Flow/IR/FlowTypes.h"
#include "iree/compiler/Dialect/Stream/Analysis/Affinity.h"
#include "iree/compiler/Dialect/Stream/IR/StreamOps.h"
#include "iree/compiler/Dialect/Stream/IR/StreamTypes.h"
namespace mlir::iree_compiler {
TypedAttr convertAttributeToStream(TypedAttr attr) {
if (!attr) {
return {};
}
if (auto parameterAttr = dyn_cast<IREE::Flow::NamedParameterAttr>(attr)) {
return IREE::Stream::NamedParameterAttr::get(
attr.getContext(), parameterAttr.getType(), parameterAttr.getScope(),
parameterAttr.getKey(), parameterAttr.getConfig());
}
return attr;
}
IREE::Stream::AffinityAttr
tryLookupGlobalAffinity(Operation *op,
IREE::Stream::AffinityAnalysis *affinityAnalysis) {
return affinityAnalysis->lookupGlobalAffinity(op);
}
IREE::Stream::AffinityAttr
tryLookupExecutionAffinity(Operation *op,
IREE::Stream::AffinityAnalysis *affinityAnalysis) {
// Note: Operations using AffinityOpConversionPattern don't need to implement
// AffinityOpInterface. The analysis can handle any operation and will use
// operand/result affinities or fall back to defaults if needed.
return affinityAnalysis->lookupExecutionAffinity(op);
}
IREE::Stream::AffinityAttr
tryLookupResultAffinity(Value value,
IREE::Stream::AffinityAnalysis *affinityAnalysis) {
return affinityAnalysis->lookupResourceAffinity(value);
}
ConvertedTensor resolveTensorOperands(
Location loc, Value originalOperand, ValueRange convertedOperand,
IREE::Stream::AffinityAnalysis *affinityAnalysis, OpBuilder &builder) {
assert(convertedOperand.size() == 2 &&
"expected tensor operands to be converted to `!stream.resource<*>, "
"index`");
auto affinityAttr = affinityAnalysis->lookupResourceAffinity(originalOperand);
return {affinityAttr, convertedOperand[0], convertedOperand[1]};
}
ConvertedTensor transferTensorOperands(
Location loc, Value originalOperand, ValueRange convertedOperand,
IREE::Stream::AffinityAttr requiredAffinityAttr,
IREE::Stream::AffinityAnalysis *affinityAnalysis, OpBuilder &builder) {
assert(convertedOperand.size() == 2 &&
"expected tensor operands to be converted to `!stream.resource<*>, "
"index`");
Value resource = convertedOperand[0];
Value resourceSize = convertedOperand[1];
auto affinityAttr = affinityAnalysis->lookupResourceAffinity(originalOperand);
bool isBarrier =
isa_and_nonnull<IREE::Stream::AsyncBarrierOp>(resource.getDefiningOp());
if (affinityAttr != requiredAffinityAttr && !isBarrier) {
resource = IREE::Stream::AsyncTransferOp::create(
builder, loc, resource.getType(), resource, resourceSize, resourceSize,
affinityAttr, requiredAffinityAttr);
}
return {requiredAffinityAttr, resource, resourceSize};
}
void replaceOpWithMultiple(Operation *op,
ArrayRef<SmallVector<Value>> replacements,
ConversionPatternRewriter &rewriter) {
auto r = llvm::map_to_vector(
replacements, [](ArrayRef<Value> v) -> ValueRange { return v; });
rewriter.replaceOpWithMultiple(op, r);
}
void replaceOpWithMultiple(Operation *op, ValueRange resources,
ValueRange sizes,
ConversionPatternRewriter &rewriter) {
SmallVector<SmallVector<Value>> replacements = llvm::map_to_vector(
llvm::zip_equal(resources, sizes), [](auto it) -> SmallVector<Value> {
if (std::get<1>(it)) {
return {std::get<0>(it), std::get<1>(it)};
}
return {std::get<0>(it)};
});
replaceOpWithMultiple(op, replacements, rewriter);
}
} // namespace mlir::iree_compiler