[MLIR] Convert DialectReductionPatternInterface using ODS (#180640)
This PR converts `DialectReductionPatternInterface` using ODS. It also introduces a new Interface Method class: `PureVirtualInterfaceMethod` which creates the method as pure virtual.
This commit is contained in:
parent
f530c161a7
commit
f46c2c46d1
9 changed files with 133 additions and 49 deletions
|
|
@ -85,6 +85,11 @@ class StaticInterfaceMethod<string desc, string retTy, string methodName,
|
|||
: InterfaceMethod<desc, retTy, methodName, args, methodBody,
|
||||
defaultImplementation>;
|
||||
|
||||
// This class represents a pure virtual interface method.
|
||||
class PureVirtualInterfaceMethod<string desc, string retTy, string methodName,
|
||||
dag args = (ins)>
|
||||
: InterfaceMethod<desc, retTy, methodName, args>;
|
||||
|
||||
// This class represents a interface method declaration.
|
||||
class InterfaceMethodDeclaration<string desc, string retTy, string methodName,
|
||||
dag args = (ins)>
|
||||
|
|
|
|||
|
|
@ -2,4 +2,8 @@ set(LLVM_TARGET_DEFINITIONS Passes.td)
|
|||
mlir_tablegen(Passes.h.inc -gen-pass-decls -name Reducer)
|
||||
add_mlir_generic_tablegen_target(MLIRReducerIncGen)
|
||||
|
||||
set(LLVM_TARGET_DEFINITIONS DialectReductionPatternInterface.td)
|
||||
mlir_tablegen(DialectReductionPatternInterface.h.inc -gen-dialect-interface-decls)
|
||||
add_mlir_generic_tablegen_target(MLIRDialectReductionPatternInterfaceIncGen)
|
||||
|
||||
add_mlir_doc(Passes ReducerPasses ./ -gen-pass-doc)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,59 @@
|
|||
#ifndef MLIR_INTERFACES_DIALECTREDUCTIONPATTERNINTERFACE
|
||||
#define MLIR_INTERFACES_DIALECTREDUCTIONPATTERNINTERFACE
|
||||
|
||||
include "mlir/IR/Interfaces.td"
|
||||
|
||||
def DialectReductionPatternInterface : DialectInterface<"DialectReductionPatternInterface"> {
|
||||
let description = [{
|
||||
This is used to report the reduction patterns for a Dialect. While using
|
||||
mlir-reduce to reduce a module, we may want to transform certain cases into
|
||||
simpler forms by applying certain rewrite patterns. Implement the
|
||||
`populateReductionPatterns` to report those patterns by adding them to the
|
||||
RewritePatternSet.
|
||||
|
||||
Example:
|
||||
MyDialectReductionPattern::populateReductionPatterns(
|
||||
RewritePatternSet &patterns) {
|
||||
patterns.add<TensorOpReduction>(patterns.getContext());
|
||||
}
|
||||
|
||||
For DRR, mlir-tblgen will generate a helper function
|
||||
`populateWithGenerated` which has the same signature therefore you can
|
||||
delegate to the helper function as well.
|
||||
|
||||
Example:
|
||||
MyDialectReductionPattern::populateReductionPatterns(
|
||||
RewritePatternSet &patterns) {
|
||||
// Include the autogen file somewhere above.
|
||||
populateWithGenerated(patterns);
|
||||
}
|
||||
}];
|
||||
let cppNamespace = "::mlir";
|
||||
|
||||
let methods = [
|
||||
PureVirtualInterfaceMethod<[{
|
||||
Patterns provided here are intended to transform operations from a complex
|
||||
form to a simpler form, without breaking the semantics of the program
|
||||
being reduced. For example, you may want to replace the
|
||||
tensor<?xindex> with a known rank and type, e.g. tensor<1xi32>, or
|
||||
replacing an operation with a constant.
|
||||
}],
|
||||
"void", "populateReductionPatterns",
|
||||
(ins "::mlir::RewritePatternSet &":$patterns)
|
||||
>,
|
||||
InterfaceMethod<[{
|
||||
This method extends `populateReductionPatterns` by allowing reduction
|
||||
patterns to use a `Tester` instance. Some reduction patterns may need to
|
||||
run tester to determine whether certain transformations preserve the
|
||||
"interesting" behavior of the program. This is mostly useful when pattern
|
||||
should choose between multiple modifications.
|
||||
}],
|
||||
"void", "populateReductionPatternsWithTester",
|
||||
(ins "::mlir::RewritePatternSet &":$patterns, "::mlir::Tester &":$tester),
|
||||
[{}]
|
||||
>
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -13,52 +13,9 @@
|
|||
#include "mlir/Reducer/Tester.h"
|
||||
|
||||
namespace mlir {
|
||||
|
||||
class RewritePatternSet;
|
||||
|
||||
/// This is used to report the reduction patterns for a Dialect. While using
|
||||
/// mlir-reduce to reduce a module, we may want to transform certain cases into
|
||||
/// simpler forms by applying certain rewrite patterns. Implement the
|
||||
/// `populateReductionPatterns` to report those patterns by adding them to the
|
||||
/// RewritePatternSet.
|
||||
///
|
||||
/// Example:
|
||||
/// MyDialectReductionPattern::populateReductionPatterns(
|
||||
/// RewritePatternSet &patterns) {
|
||||
/// patterns.add<TensorOpReduction>(patterns.getContext());
|
||||
/// }
|
||||
///
|
||||
/// For DRR, mlir-tblgen will generate a helper function
|
||||
/// `populateWithGenerated` which has the same signature therefore you can
|
||||
/// delegate to the helper function as well.
|
||||
///
|
||||
/// Example:
|
||||
/// MyDialectReductionPattern::populateReductionPatterns(
|
||||
/// RewritePatternSet &patterns) {
|
||||
/// // Include the autogen file somewhere above.
|
||||
/// populateWithGenerated(patterns);
|
||||
/// }
|
||||
class DialectReductionPatternInterface
|
||||
: public DialectInterface::Base<DialectReductionPatternInterface> {
|
||||
public:
|
||||
/// Patterns provided here are intended to transform operations from a complex
|
||||
/// form to a simpler form, without breaking the semantics of the program
|
||||
/// being reduced. For example, you may want to replace the
|
||||
/// tensor<?xindex> with a known rank and type, e.g. tensor<1xi32>, or
|
||||
/// replacing an operation with a constant.
|
||||
virtual void populateReductionPatterns(RewritePatternSet &patterns) const = 0;
|
||||
|
||||
/// This method extends `populateReductionPatterns` by allowing reduction
|
||||
/// patterns to use a `Tester` instance. Some reduction patterns may need to
|
||||
/// run tester to determine whether certain transformations preserve the
|
||||
/// "interesting" behavior of the program. This is mostly useful when pattern
|
||||
/// should choose between multiple modifications.
|
||||
virtual void populateReductionPatternsWithTester(RewritePatternSet &patterns,
|
||||
Tester &tester) const {}
|
||||
|
||||
protected:
|
||||
DialectReductionPatternInterface(Dialect *dialect) : Base(dialect) {}
|
||||
};
|
||||
} // namespace mlir
|
||||
|
||||
#include "mlir/Reducer/DialectReductionPatternInterface.h.inc"
|
||||
|
||||
#endif // MLIR_REDUCER_REDUCTIONPATTERNINTERFACE_H
|
||||
|
|
|
|||
|
|
@ -47,6 +47,9 @@ public:
|
|||
// Return if this method is static.
|
||||
bool isStatic() const;
|
||||
|
||||
// Return if the method is a pure virtual one.
|
||||
bool isPureVirtual() const;
|
||||
|
||||
// Return if the method is only a declaration.
|
||||
bool isDeclaration() const;
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ add_mlir_library(MLIRReduce
|
|||
|
||||
DEPENDS
|
||||
MLIRReducerIncGen
|
||||
MLIRDialectReductionPatternInterfaceIncGen
|
||||
)
|
||||
|
||||
mlir_check_all_link_libraries(MLIRReduce)
|
||||
|
|
|
|||
|
|
@ -52,6 +52,11 @@ bool InterfaceMethod::isStatic() const {
|
|||
return def->isSubClassOf("StaticInterfaceMethod");
|
||||
}
|
||||
|
||||
// Return if the method is a pure virtual one.
|
||||
bool InterfaceMethod::isPureVirtual() const {
|
||||
return def->isSubClassOf("PureVirtualInterfaceMethod");
|
||||
}
|
||||
|
||||
// Return if the method is only a declaration.
|
||||
bool InterfaceMethod::isDeclaration() const {
|
||||
return def->isSubClassOf("InterfaceMethodDeclaration");
|
||||
|
|
|
|||
|
|
@ -22,9 +22,9 @@ def NoDefaultMethod : DialectInterface<"NoDefaultMethod"> {
|
|||
|
||||
// DECL: class NoDefaultMethod : public {{.*}}DialectInterface::Base<NoDefaultMethod>
|
||||
// DECL: public:
|
||||
// DECL: NoDefaultMethod(::mlir::Dialect *dialect) : Base(dialect) {}
|
||||
// DECL: virtual bool isExampleDialect() const {}
|
||||
// DECL: virtual unsigned supportSecondMethod(::mlir::Type type) const {}
|
||||
// DECL: NoDefaultMethod(::mlir::Dialect *dialect) : Base(dialect) {}
|
||||
|
||||
def WithDefaultMethodInterface : DialectInterface<"WithDefaultMethodInterface"> {
|
||||
let description = [{
|
||||
|
|
@ -73,3 +73,24 @@ def OnlyDeclarationInterfaceWithExtraDecls : DialectInterface<"OnlyDeclarationIn
|
|||
// DECL: class OnlyDeclarationInterfaceWithExtraDecls : public {{.*}}DialectInterface::Base<OnlyDeclarationInterfaceWithExtraDecls>
|
||||
// DECL: virtual void exampleMethodDeclaration(::mlir::Type type) const;
|
||||
// DECL: using DeclType = int;
|
||||
|
||||
def PureVirtualInterface : DialectInterface<"PureVirtualInterface"> {
|
||||
let description = [{
|
||||
This is an example dialect interface with pure virtual methods.
|
||||
}];
|
||||
|
||||
let cppNamespace = "::mlir::example";
|
||||
|
||||
let methods = [
|
||||
PureVirtualInterfaceMethod<
|
||||
"Check if it's an example dialect", "bool", "isExampleDialect",
|
||||
(ins)
|
||||
>
|
||||
];
|
||||
}
|
||||
|
||||
// DECL: class PureVirtualInterface : public {{.*}}DialectInterface::Base<PureVirtualInterface>
|
||||
// DECL: public:
|
||||
// DECL: virtual bool isExampleDialect() const = 0;
|
||||
// DECL: protected:
|
||||
// DECL-NEXT: PureVirtualInterface(::mlir::Dialect *dialect) : Base(dialect) {}
|
||||
|
|
|
|||
|
|
@ -113,6 +113,11 @@ static void emitInterfaceMethodsDef(const DialectInterface &interface,
|
|||
continue;
|
||||
}
|
||||
|
||||
if (method.isPureVirtual()) {
|
||||
ios << " = 0;\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
// if it is not a method declaration, then it's a normal interface method.
|
||||
ios << " {";
|
||||
|
||||
|
|
@ -126,6 +131,27 @@ static void emitInterfaceMethodsDef(const DialectInterface &interface,
|
|||
}
|
||||
}
|
||||
|
||||
static void emitConstructor(const DialectInterface &interface,
|
||||
raw_ostream &os) {
|
||||
|
||||
raw_indented_ostream ios(os);
|
||||
|
||||
// We consider a constructor protected if interface has at least one pure
|
||||
// virtual method
|
||||
auto hasProtectedConstructor =
|
||||
llvm::any_of(interface.getMethods(), [](const InterfaceMethod &method) {
|
||||
return method.isPureVirtual();
|
||||
});
|
||||
|
||||
ios.indent(0);
|
||||
if (hasProtectedConstructor)
|
||||
ios << "protected:\n";
|
||||
|
||||
ios.indent(2);
|
||||
ios << llvm::formatv("{0}(::mlir::Dialect *dialect) : Base(dialect) {{}\n",
|
||||
interface.getName());
|
||||
}
|
||||
|
||||
void DialectInterfaceGenerator::emitInterfaceDecl(
|
||||
const DialectInterface &interface) {
|
||||
llvm::NamespaceEmitter ns(os, interface.getCppNamespace());
|
||||
|
|
@ -135,9 +161,8 @@ void DialectInterfaceGenerator::emitInterfaceDecl(
|
|||
|
||||
// Emit the main interface class declaration.
|
||||
os << llvm::formatv(
|
||||
"class {0} : public ::mlir::DialectInterface::Base<{0}> {\n"
|
||||
"public:\n"
|
||||
" {0}(::mlir::Dialect *dialect) : Base(dialect) {{}\n",
|
||||
"class {0} : public ::mlir::DialectInterface::Base<{0}> {{\n"
|
||||
"public:\n",
|
||||
interface.getName());
|
||||
|
||||
emitInterfaceMethodsDef(interface, os);
|
||||
|
|
@ -151,6 +176,10 @@ void DialectInterfaceGenerator::emitInterfaceDecl(
|
|||
ios << "\n";
|
||||
}
|
||||
|
||||
os << "\n";
|
||||
|
||||
emitConstructor(interface, os);
|
||||
|
||||
os << "};\n";
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue