Skip to content

Commit 4492dda

Browse files
authored
[DT] Add support for materializing func.func and func.return op. (#21582)
The revision implements the materialization pattern for `func.return` ops and a method that sets function signatures with converted types. If the type is not configured in the type converter, e.g., `!hal.buffer_view`, it uses the same type. The function signature is not updated with a pattern because the `MaterializeDeviceEncoding` pass is a `FunctionOpInterface` interface pass. It is a step towards #20825 --------- Signed-off-by: hanhanW <[email protected]>
1 parent 66b2f33 commit 4492dda

File tree

3 files changed

+59
-28
lines changed

3 files changed

+59
-28
lines changed

compiler/src/iree/compiler/Codegen/Common/MaterializeEncoding.cpp

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
#include "iree/compiler/Codegen/Common/Passes.h"
99
#include "iree/compiler/Codegen/Common/Transforms.h"
1010
#include "iree/compiler/Codegen/Dialect/CPU/IR/IREECPUDialect.h"
11-
#include "iree/compiler/Codegen/Dialect/CPU/IR/IREECPUTypes.h"
1211
#include "iree/compiler/Codegen/Dialect/Codegen/IR/IREECodegenAttrs.h"
1312
#include "iree/compiler/Codegen/Dialect/Codegen/IR/IREECodegenDialect.h"
1413
#include "iree/compiler/Codegen/Dialect/GPU/IR/IREEGPUAttrs.h"
@@ -44,6 +43,22 @@ using namespace IREE::Encoding;
4443

4544
namespace {
4645

46+
static void
47+
updateFuncSignature(FunctionOpInterface funcOp,
48+
const MaterializeEncodingTypeConverter &typeConverter) {
49+
// Do not convert the type if the type converter does not understand the
50+
// conversion. E.g., `!hal.buffer_view` type.
51+
auto convertType = [&](Type t) {
52+
Type newType = typeConverter.convertType(t);
53+
return newType ? newType : t;
54+
};
55+
SmallVector<Type> newInputs =
56+
llvm::map_to_vector(funcOp.getArgumentTypes(), convertType);
57+
SmallVector<Type> newResults =
58+
llvm::map_to_vector(funcOp.getResultTypes(), convertType);
59+
funcOp.setType(FunctionType::get(funcOp.getContext(), newInputs, newResults));
60+
}
61+
4762
static LogicalResult
4863
materializeFuncOpEncodings(FunctionOpInterface funcOp,
4964
IREE::HAL::ExecutableTargetAttr targetAttr,
@@ -113,9 +128,12 @@ materializeFuncOpEncodings(FunctionOpInterface funcOp,
113128
populateMaterializeEncodingPatterns(patterns, target, typeConverter);
114129

115130
if (failed(applyPartialConversion(funcOp, target, std::move(patterns)))) {
116-
funcOp.emitOpError("materialization failed");
117-
return failure();
131+
return funcOp.emitOpError("materialization failed");
118132
}
133+
134+
// The update is required for testing purposes, which results in fewer IRs.
135+
// We do not expect inputs and outputs from `funcOp` in practice.
136+
updateFuncSignature(funcOp, typeConverter);
119137
}
120138

121139
// Run patterns to fold pack/unpack ops with pad/extract_slice ops, resolve
@@ -146,8 +164,7 @@ materializeFuncOpEncodings(FunctionOpInterface funcOp,
146164
});
147165
memref::populateResolveRankedShapedTypeResultDimsPatterns(patterns);
148166
if (failed(applyPatternsGreedily(funcOp, std::move(patterns)))) {
149-
funcOp.emitOpError("folding patterns failed");
150-
return failure();
167+
return funcOp.emitOpError("folding patterns failed");
151168
}
152169

153170
IRRewriter rewriter(ctx);

compiler/src/iree/compiler/Codegen/Common/MaterializeEncodingPatterns.cpp

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,10 @@
1919
#include "iree/compiler/Dialect/Util/IR/UtilOps.h"
2020
#include "llvm/ADT/SmallVectorExtras.h"
2121
#include "llvm/Support/LogicalResult.h"
22-
#include "mlir/Dialect/Affine/IR/AffineOps.h"
2322
#include "mlir/Dialect/Arith/IR/Arith.h"
23+
#include "mlir/Dialect/Func/IR/FuncOps.h"
2424
#include "mlir/Dialect/Linalg/IR/Linalg.h"
2525
#include "mlir/Dialect/Linalg/Transforms/Transforms.h"
26-
#include "mlir/Dialect/MemRef/Transforms/Transforms.h"
2726
#include "mlir/Dialect/Tensor/IR/Tensor.h"
2827
#include "mlir/Dialect/Utils/IndexingUtils.h"
2928
#include "mlir/IR/BuiltinTypes.h"
@@ -878,6 +877,25 @@ class MaterializeContractionOp
878877
}
879878
};
880879

880+
static bool isRankedTensorTypeWithEncoding(Type type) {
881+
auto rankedTensorType = dyn_cast<RankedTensorType>(type);
882+
if (!rankedTensorType) {
883+
return false;
884+
}
885+
return rankedTensorType.getEncoding() ? true : false;
886+
}
887+
888+
struct MaterializeFuncReturnOp final
889+
: public OpConversionPattern<func::ReturnOp> {
890+
using OpConversionPattern<func::ReturnOp>::OpConversionPattern;
891+
LogicalResult
892+
matchAndRewrite(func::ReturnOp op, OpAdaptor adaptor,
893+
ConversionPatternRewriter &rewriter) const override {
894+
rewriter.replaceOpWithNewOp<func::ReturnOp>(op, adaptor.getOperands());
895+
return success();
896+
}
897+
};
898+
881899
} // namespace
882900

883901
void populateMaterializeEncodingPatterns(
@@ -913,6 +931,10 @@ void populateMaterializeEncodingPatterns(
913931
return true;
914932
return resultType == typeConverter.convertType(resultType);
915933
});
934+
target.addDynamicallyLegalOp<func::ReturnOp>([](func::ReturnOp returnOp) {
935+
return !llvm::any_of(returnOp.getOperandTypes(),
936+
isRankedTensorTypeWithEncoding);
937+
});
916938

917939
patterns.insert<MaterializeContractionOp, SetEncodingOpLoweringConversion,
918940
UnsetEncodingOpLoweringConversion,
@@ -922,7 +944,8 @@ void populateMaterializeEncodingPatterns(
922944
MaterializeOptimizationBarrierOp,
923945
MaterializeTensorExtDispatchTensorLoadOp,
924946
MaterializeTensorExtDispatchTensorStoreOp,
925-
MaterializeInterfaceBindingEncoding>(typeConverter, context);
947+
MaterializeInterfaceBindingEncoding, MaterializeFuncReturnOp>(
948+
typeConverter, context);
926949
};
927950

928951
} // namespace mlir::iree_compiler

compiler/src/iree/compiler/Codegen/Common/test/materialize_encoding_x86_64.mlir

Lines changed: 11 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,28 @@
11
// RUN: iree-opt --pass-pipeline="builtin.module(func.func(iree-codegen-materialize-device-encoding))" --split-input-file %s | FileCheck %s
22

3-
#pipeline_layout = #hal.pipeline.layout<bindings = [
4-
#hal.pipeline.binding<storage_buffer>,
5-
#hal.pipeline.binding<storage_buffer>
6-
]>
7-
#encoding = #iree_encoding.encoding<operand_index = 0, op_type = matmul, element_types = [bf16, bf16, bf16], user_indexing_maps = [affine_map<(d0, d1, d2) -> (d0, d2)>, affine_map<(d0, d1, d2) -> (d2, d1)>, affine_map<(d0, d1, d2) -> (d0, d1)>], iteration_sizes = [1, 1000, ?]>
8-
func.func @set_encoding_with_padding_semantics_bf16_x86_64_avx512f() attributes {
9-
hal.executable.target = #hal.executable.target<"llvm-cpu", "xyz", {target_triple="x86_64-xyz-xyz", cpu_features="+avx512f", iree.encoding.resolver = #iree_cpu.cpu_encoding_resolver<>}>
10-
}{
11-
%c0 = arith.constant 0 : index
12-
%0 = hal.interface.binding.subspan layout(#pipeline_layout) binding(0) alignment(64) offset(%c0) flags(ReadOnly) : !iree_tensor_ext.dispatch.tensor<readonly:tensor<1x1000xbf16>>
13-
%1 = hal.interface.binding.subspan layout(#pipeline_layout) binding(1) alignment(64) offset(%c0) : !iree_tensor_ext.dispatch.tensor<writeonly:tensor<1x1000xbf16, #encoding>>
14-
%2 = iree_tensor_ext.dispatch.tensor.load %0, offsets = [0, 0], sizes = [1, 1000], strides = [1, 1] : !iree_tensor_ext.dispatch.tensor<readonly:tensor<1x1000xbf16>> -> tensor<1x1000xbf16>
15-
%3 = iree_encoding.set_encoding %2 : tensor<1x1000xbf16> -> tensor<1x1000xbf16, #encoding>
16-
iree_tensor_ext.dispatch.tensor.store %3, %1, offsets = [0, 0], sizes = [1, 1000], strides = [1, 1] : tensor<1x1000xbf16, #encoding> -> !iree_tensor_ext.dispatch.tensor<writeonly:tensor<1x1000xbf16, #encoding>>
17-
return
3+
#map = affine_map<(d0, d1, d2) -> (d0, d2)>
4+
#map1 = affine_map<(d0, d1, d2) -> (d2, d1)>
5+
#map2 = affine_map<(d0, d1, d2) -> (d0, d1)>
6+
#encoding = #iree_encoding.encoding<operand_index = 0 : i64, op_type = matmul, element_types = [bf16, bf16, bf16], user_indexing_maps = [#map, #map1, #map2], iteration_sizes = [1, 1000, ?]>
7+
#executable_target = #hal.executable.target<"llvm-cpu", "xyz", {cpu_features = "+avx512f", iree.encoding.resolver = #iree_cpu.cpu_encoding_resolver<>, target_triple = "x86_64-xyz-xyz"}>
8+
func.func @set_encoding_with_padding_semantics_bf16_x86_64_avx512f(%arg0: tensor<1x1000xbf16>)
9+
-> tensor<1x1000xbf16, #encoding> attributes { hal.executable.target = #executable_target } {
10+
%0 = iree_encoding.set_encoding %arg0 : tensor<1x1000xbf16> -> tensor<1x1000xbf16, #encoding>
11+
return %0 : tensor<1x1000xbf16, #encoding>
1812
}
1913
// This tests that
2014
// 1. The padding value is created for linalg.pack ops.
2115
// 2. The inner tile sizes are less than or equal to values in iteration_sizes.
2216
// We could choose 128 when it is a narrow matrix.
2317
// CHECK-LABEL: func.func @set_encoding_with_padding_semantics_bf16_x86_64_avx512f
24-
// CHECK-DAG: %[[C0:.+]] = arith.constant 0 : index
25-
// CHECK-DAG: %[[IN_BINDING:.+]] = hal.interface.binding.subspan {{.+}} : !iree_tensor_ext.dispatch.tensor<readonly:tensor<1x1000xbf16>>
26-
// CHECK-DAG: %[[OUT_BINDING:.+]] = hal.interface.binding.subspan {{.+}} : !iree_tensor_ext.dispatch.tensor<writeonly:tensor<1x1000x1x1xbf16>>
27-
// CHECK: %[[SRC:.+]] = iree_tensor_ext.dispatch.tensor.load %[[IN_BINDING]]
18+
// CHECK-SAME: %[[SRC:[a-zA-Z0-9]+]]
2819
// CHECK-DAG: %[[INIT:.+]] = tensor.empty() : tensor<1x1000x1x1xbf16>
2920
// CHECK: %[[PACK:.+]] = linalg.pack %[[SRC]]
3021
// CHECK-SAME: outer_dims_perm = [0, 1]
3122
// CHECK-SAME: inner_dims_pos = [0, 1]
3223
// CHECK-SAME: inner_tiles = [1, 1]
3324
// CHECK-SAME: into %[[INIT]] : tensor<1x1000xbf16> -> tensor<1x1000x1x1xbf16>
34-
// CHECK: iree_tensor_ext.dispatch.tensor.store %[[PACK]], %[[OUT_BINDING]]
25+
// CHECK: return %[[PACK]]
3526

3627
// -----
3728

0 commit comments

Comments
 (0)