Skip to content

Commit e553425

Browse files
authored
[Codegen][Tuner] attr verifier for tuning specs (#19486)
This PR is relevant to task in #19214: add [a discardable attr verifier](https://mlir.llvm.org/docs/DefiningDialects/#discardable-attribute-verification) for entry points iree_codegen.tuning_spec_entrypoint --------- Signed-off-by: Bangtian Liu <liubangtian@gmail.com>
1 parent 3614f69 commit e553425

File tree

7 files changed

+120
-31
lines changed

7 files changed

+120
-31
lines changed

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

+7-29
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "mlir/IR/BuiltinAttributes.h"
1919
#include "mlir/IR/BuiltinOps.h"
2020
#include "mlir/IR/Location.h"
21+
#include "mlir/IR/Verifier.h"
2122

2223
#define DEBUG_TYPE "iree-codegen-link-tuning-specs"
2324
#define DBGS() (llvm::dbgs() << "[" DEBUG_TYPE "]: ")
@@ -53,35 +54,14 @@ static SmallVector<NamedSequenceOp> findTuningSpecs(ModuleOp module) {
5354
});
5455
}
5556

56-
// Returns true iff the entrypoint has the following signature:
57-
// ```
58-
// transform.named_sequence @name(%arg0: !transform.any_op) ->
59-
// (!transform.any_op)
60-
// ```
61-
static LogicalResult validateTuningSpec(NamedSequenceOp op) {
62-
ArrayRef<Type> resTypes = op.getFunctionType().getResults();
63-
if (resTypes.size() != 1 || !isa<transform::AnyOpType>(resTypes[0])) {
64-
return op.emitWarning()
65-
<< "Tuning spec entry point expected to return any_op";
66-
}
67-
68-
ArrayRef<Type> argTypes = op.getArgumentTypes();
69-
if (argTypes.size() != 1 || !isa<transform::AnyOpType>(argTypes[0])) {
70-
return op.emitWarning() << "Tuning spec entry point expected to have a "
71-
"single any_op argument";
72-
}
73-
74-
return success();
75-
}
76-
7757
static bool consumesInputOp(NamedSequenceOp op) {
7858
if (op.getArgAttr(0, kArgConsumedAttrName)) {
7959
return true;
8060
}
8161
return false;
8262
}
8363

84-
static NamedSequenceOp
64+
static FailureOr<NamedSequenceOp>
8565
emitLinkedTuningSpec(ModuleOp module, ArrayRef<NamedSequenceOp> specsToLink) {
8666
OpBuilder builder(module->getContext());
8767
builder.setInsertionPointToEnd(module.getBody());
@@ -144,6 +124,11 @@ emitLinkedTuningSpec(ModuleOp module, ArrayRef<NamedSequenceOp> specsToLink) {
144124
}
145125

146126
builder.create<transform::YieldOp>(loc, operand);
127+
128+
if (failed(mlir::verify(module))) {
129+
return module.emitError("Linked tuning spec failed to verify");
130+
}
131+
147132
return newSpec;
148133
}
149134

@@ -169,13 +154,6 @@ FailureOr<NamedSequenceOp> linkTuningSpecs(ModuleOp module) {
169154
llvm::append_range(tuningSpecs, findTuningSpecs(nested));
170155
}
171156

172-
for (NamedSequenceOp spec : tuningSpecs) {
173-
LDBG("Found tuning spec: " << spec.getSymName());
174-
if (failed(validateTuningSpec(spec))) {
175-
return failure();
176-
}
177-
}
178-
179157
size_t numConsumedSpecs = llvm::count_if(tuningSpecs, consumesInputOp);
180158
if (numConsumedSpecs > 0 && numConsumedSpecs != tuningSpecs.size()) {
181159
LDBG("Only " << numConsumedSpecs << " tuning specs out of "

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

+14-2
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "mlir/IR/BuiltinTypeInterfaces.h"
2828
#include "mlir/IR/Location.h"
2929
#include "mlir/IR/OwningOpRef.h"
30+
#include "mlir/IR/Verifier.h"
3031
#include "mlir/Support/FileUtilities.h"
3132

3233
#define DEBUG_TYPE "iree-codegen-materialize-tuning-specs"
@@ -138,8 +139,19 @@ getDefaultTuningSpec(ModuleOp module,
138139

139140
// Load the library through the codegen dialect so that we cache the parsed
140141
// module.
141-
return dialect.getOrParseTransformLibraryModule(defaultTuningSpecName,
142-
*defaultTuningSpecSource);
142+
FailureOr<ModuleOp> defaultTransformLibrary =
143+
dialect.getOrParseTransformLibraryModule(defaultTuningSpecName,
144+
*defaultTuningSpecSource);
145+
146+
#ifndef NDEBUG
147+
if (succeeded(defaultTransformLibrary) &&
148+
failed(mlir::verify(*defaultTransformLibrary)))
149+
return (*defaultTransformLibrary).emitError()
150+
<< "Default tuning spec " << defaultTuningSpecName
151+
<< " failed to verify";
152+
#endif
153+
154+
return defaultTransformLibrary;
143155
}
144156

145157
static FailureOr<DenseElementsAttr>

compiler/src/iree/compiler/Codegen/Common/test/BUILD.bazel

+1
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ iree_lit_test_suite(
9696
"vector_layout_analysis.mlir",
9797
"vectorize_memref_copy.mlir",
9898
"vectorize_tensor_pad.mlir",
99+
"verify_tuning_specs.mlir",
99100
"verify_workgroup_distribution.mlir",
100101
"vmvx_materialize_encoding.mlir",
101102
],

compiler/src/iree/compiler/Codegen/Common/test/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ iree_lit_test_suite(
9292
"vector_layout_analysis.mlir"
9393
"vectorize_memref_copy.mlir"
9494
"vectorize_tensor_pad.mlir"
95+
"verify_tuning_specs.mlir"
9596
"verify_workgroup_distribution.mlir"
9697
"vmvx_materialize_encoding.mlir"
9798
TOOLS
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// RUN: iree-opt --verify-diagnostics --split-input-file %s
2+
3+
module @foo_module attributes { transform.with_named_sequence } {
4+
func.func @baz(%arg0: i32) -> () {
5+
return
6+
}
7+
transform.named_sequence @bar(%arg0: !transform.any_op {transform.readonly}) -> !transform.any_op
8+
attributes { iree_codegen.something } {
9+
transform.yield %arg0 : !transform.any_op
10+
}
11+
// expected-error @+1{{'iree_codegen.tuning_spec_entrypoint' attribute must be a UnitAttr}}
12+
transform.named_sequence @foo(%arg0: !transform.any_op {transform.readonly}) -> !transform.any_op
13+
attributes { iree_codegen.tuning_spec_entrypoint = "foo" } {
14+
transform.yield %arg0 : !transform.any_op
15+
}
16+
}
17+
18+
// -----
19+
20+
module @foo_module attributes { transform.with_named_sequence } {
21+
// expected-error @+1{{Tuning spec entry point expected to have a single any_op argument}}
22+
transform.named_sequence @foo(%arg0: !transform.any_op {transform.readonly}, %arg1: !transform.any_op {transform.readonly}) -> !transform.any_op
23+
attributes { iree_codegen.tuning_spec_entrypoint } {
24+
transform.yield %arg0 : !transform.any_op
25+
}
26+
}
27+
28+
// -----
29+
30+
module @foo_module attributes { transform.with_named_sequence } {
31+
// expected-error @+1{{Tuning spec entry point expected to have a single any_op argument}}
32+
transform.named_sequence @foo(%arg0: i32) -> !transform.any_op
33+
attributes { iree_codegen.tuning_spec_entrypoint } {}
34+
}
35+
36+
// -----
37+
38+
module @foo_module attributes { transform.with_named_sequence } {
39+
// expected-error @+1{{Tuning spec entry point expected to return any_op}}
40+
transform.named_sequence @foo(%arg0: !transform.any_op {transform.readonly}) -> i32
41+
attributes { iree_codegen.tuning_spec_entrypoint } {
42+
%0 = arith.constant 0 : i32
43+
transform.yield %0 : i32
44+
}
45+
}
46+
47+
// -----
48+
49+
module @foo_module attributes { transform.with_named_sequence } {
50+
// expected-error @+1{{Tuning spec entry point expected to return any_op}}
51+
transform.named_sequence @foo(%arg0: !transform.any_op {transform.readonly})
52+
attributes { iree_codegen.tuning_spec_entrypoint } {}
53+
}

compiler/src/iree/compiler/Codegen/Dialect/Codegen/IR/IREECodegenDialect.cpp

+43
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "iree/compiler/Codegen/Dialect/Codegen/IR/IREECodegenDialect.cpp.inc"
1111
#include "iree/compiler/Codegen/Dialect/Codegen/IR/IREECodegenOps.h"
1212
#include "iree/compiler/Codegen/Dialect/Codegen/IR/UKernelOps.h"
13+
#include "mlir/Dialect/Transform/IR/TransformOps.h"
1314
#include "mlir/IR/DialectImplementation.h"
1415

1516
namespace mlir::iree_compiler::IREE::Codegen {
@@ -45,4 +46,46 @@ void IREECodegenDialect::initialize() {
4546
>();
4647
}
4748

49+
LogicalResult
50+
IREECodegenDialect::verifyOperationAttribute(Operation *op,
51+
NamedAttribute attribute) {
52+
StringRef symbol = attribute.getName().strref();
53+
Attribute attr = attribute.getValue();
54+
55+
// This function verifies the validity of a specific operation attribute.
56+
// - If the attribute's name matches `kTuningSpecEntrypointAttrName`
57+
// ("iree_codegen.tuning_spec_entrypoint"):
58+
// 1. The attribute value must be a UnitAttr.
59+
// 2. If the operation is a transform::NamedSequenceOp:
60+
// - The operation's function signature must satisfy the following:
61+
// a. It must have exactly one result type, and the result must be of
62+
// type `transform::AnyOpType`.
63+
// b. It must have exactly one argument type, and the argument must be
64+
// of type `transform::AnyOpType`.
65+
66+
if (symbol != kTuningSpecEntrypointAttrName)
67+
return success();
68+
69+
if (!isa<UnitAttr>(attr)) {
70+
return op->emitError("'") << symbol << "' attribute must be a UnitAttr";
71+
}
72+
73+
if (auto namedSeqOp = dyn_cast<transform::NamedSequenceOp>(op)) {
74+
ArrayRef<Type> resTypes = namedSeqOp.getFunctionType().getResults();
75+
if (resTypes.size() != 1 || !isa<transform::AnyOpType>(resTypes[0])) {
76+
return namedSeqOp.emitError()
77+
<< "Tuning spec entry point expected to return any_op";
78+
}
79+
80+
ArrayRef<Type> argTypes = namedSeqOp.getArgumentTypes();
81+
if (argTypes.size() != 1 || !isa<transform::AnyOpType>(argTypes[0])) {
82+
return namedSeqOp.emitError()
83+
<< "Tuning spec entry point expected to have a "
84+
"single any_op argument";
85+
}
86+
}
87+
88+
return success();
89+
}
90+
4891
} // namespace mlir::iree_compiler::IREE::Codegen

compiler/src/iree/compiler/Codegen/Dialect/Codegen/IR/IREECodegenDialect.td

+1
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ def IREECodegen_Dialect : Dialect {
6868
std::mutex libraryMutex;
6969
}];
7070
let useDefaultAttributePrinterParser = 1;
71+
let hasOperationAttrVerify = 1;
7172
}
7273

7374
def AnyRankedTensorOrMemRefType : AnyTypeOf<[AnyRankedTensor, AnyMemRef]>;

0 commit comments

Comments
 (0)