| // 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 |