-
Notifications
You must be signed in to change notification settings - Fork 14.3k
Reland [mlir][tools] Introduce tblgen-to-irdl tool #70121
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This patch adds a new tool, tblgen-to-irdl, which is an IRDL backend to MLIR ODS. Currently, the tool only covers operation and dialect definitions and generates verifiers constraints as "irdl::CPred", which is the constraint as a C++ string. The tool currently does not support traits/interfaces/regions/variadics as they are not added in IRDL yet, so the generated definitions would not be correct for operations using them. Support for these things will be added as they are implemented in IRDL. This tool acts as a bridge to convert TableGen-defined dialects into IRDL definitions, making operation definitions more easily introspectable. This introspectablility allows for tools like fuzzers, mutators, and reducers to work on ODS definitions as a MLIR dialect instead of trying to navigate through TableGen. Differential Revision: https://reviews.llvm.org/D156469
@llvm/pr-subscribers-mlir @llvm/pr-subscribers-mlir-core Author: Kunwar Grover (Groverkss) ChangesThis patch relands the reverted commit e6e9beb after fixing the sanitizer issue. Full diff: https://github.com/llvm/llvm-project/pull/70121.diff 6 Files Affected:
diff --git a/mlir/test/CMakeLists.txt b/mlir/test/CMakeLists.txt
index bf143d036c2f66f..04bfa1ade655e04 100644
--- a/mlir/test/CMakeLists.txt
+++ b/mlir/test/CMakeLists.txt
@@ -108,6 +108,7 @@ set(MLIR_TEST_DEPENDS
mlir-tblgen
mlir-translate
tblgen-lsp-server
+ tblgen-to-irdl
)
# The native target may not be enabled, in this case we won't
diff --git a/mlir/test/tblgen-to-irdl/CMathDialect.td b/mlir/test/tblgen-to-irdl/CMathDialect.td
new file mode 100644
index 000000000000000..57ae8afbba5eeb3
--- /dev/null
+++ b/mlir/test/tblgen-to-irdl/CMathDialect.td
@@ -0,0 +1,56 @@
+// RUN: tblgen-to-irdl %s -I=%S/../../include --gen-dialect-irdl-defs --dialect=cmath | FileCheck %s
+
+include "mlir/IR/OpBase.td"
+include "mlir/IR/AttrTypeBase.td"
+
+// CHECK-LABEL: irdl.dialect @cmath {
+def CMath_Dialect : Dialect {
+ let name = "cmath";
+}
+
+class CMath_Type<string name, string typeMnemonic, list<Trait> traits = []>
+: TypeDef<CMath_Dialect, name, traits> {
+ let mnemonic = typeMnemonic;
+}
+
+class CMath_Op<string mnemonic, list<Trait> traits = []>
+ : Op<CMath_Dialect, mnemonic, traits>;
+
+def f32Orf64Type : Or<[CPred<"::llvm::isa<::mlir::F32>">,
+ CPred<"::llvm::isa<::mlir::F64>">]>;
+
+def CMath_ComplexType : CMath_Type<"ComplexType", "complex"> {
+ let parameters = (ins f32Orf64Type:$elementType);
+}
+
+// CHECK: irdl.operation @identity {
+// CHECK-NEXT: %0 = irdl.c_pred "(::llvm::isa<cmath::ComplexTypeType>($_self))"
+// CHECK-NEXT: irdl.operands()
+// CHECK-NEXT: irdl.results(%0)
+// CHECK-NEXT: }
+def CMath_IdentityOp : CMath_Op<"identity"> {
+ let results = (outs CMath_ComplexType:$out);
+}
+
+// CHECK: irdl.operation @mul {
+// CHECK-NEXT: %0 = irdl.c_pred "(::llvm::isa<cmath::ComplexTypeType>($_self))"
+// CHECK-NEXT: %1 = irdl.c_pred "(::llvm::isa<cmath::ComplexTypeType>($_self))"
+// CHECK-NEXT: %2 = irdl.c_pred "(::llvm::isa<cmath::ComplexTypeType>($_self))"
+// CHECK-NEXT: irdl.operands(%0, %1)
+// CHECK-NEXT: irdl.results(%2)
+// CHECK-NEXT: }
+def CMath_MulOp : CMath_Op<"mul"> {
+ let arguments = (ins CMath_ComplexType:$in1, CMath_ComplexType:$in2);
+ let results = (outs CMath_ComplexType:$out);
+}
+
+// CHECK: irdl.operation @norm {
+// CHECK-NEXT: %0 = irdl.c_pred "(true)"
+// CHECK-NEXT: %1 = irdl.c_pred "(::llvm::isa<cmath::ComplexTypeType>($_self))"
+// CHECK-NEXT: irdl.operands(%0)
+// CHECK-NEXT: irdl.results(%1)
+// CHECK-NEXT: }
+def CMath_NormOp : CMath_Op<"norm"> {
+ let arguments = (ins AnyType:$in);
+ let results = (outs CMath_ComplexType:$out);
+}
diff --git a/mlir/tools/CMakeLists.txt b/mlir/tools/CMakeLists.txt
index e9a1e4d6251722e..895a103061d3052 100644
--- a/mlir/tools/CMakeLists.txt
+++ b/mlir/tools/CMakeLists.txt
@@ -8,6 +8,7 @@ add_subdirectory(mlir-spirv-cpu-runner)
add_subdirectory(mlir-translate)
add_subdirectory(mlir-vulkan-runner)
add_subdirectory(tblgen-lsp-server)
+add_subdirectory(tblgen-to-irdl)
# mlir-cpu-runner requires ExecutionEngine.
if(MLIR_ENABLE_EXECUTION_ENGINE)
diff --git a/mlir/tools/tblgen-to-irdl/CMakeLists.txt b/mlir/tools/tblgen-to-irdl/CMakeLists.txt
new file mode 100644
index 000000000000000..a6621cb98ac6bdc
--- /dev/null
+++ b/mlir/tools/tblgen-to-irdl/CMakeLists.txt
@@ -0,0 +1,20 @@
+set(LLVM_LINK_COMPONENTS
+ TableGen
+)
+
+add_tablegen(tblgen-to-irdl MLIR
+ DESTINATION "${MLIR_TOOLS_INSTALL_DIR}"
+ EXPORT MLIR
+ tblgen-to-irdl.cpp
+ OpDefinitionsGen.cpp
+ )
+
+target_link_libraries(tblgen-to-irdl
+ PRIVATE
+ MLIRIR
+ MLIRIRDL
+ MLIRTblgenLib
+ MLIRSupport
+)
+
+mlir_check_all_link_libraries(tblgen-to-irdl)
diff --git a/mlir/tools/tblgen-to-irdl/OpDefinitionsGen.cpp b/mlir/tools/tblgen-to-irdl/OpDefinitionsGen.cpp
new file mode 100644
index 000000000000000..9b732aadfc02440
--- /dev/null
+++ b/mlir/tools/tblgen-to-irdl/OpDefinitionsGen.cpp
@@ -0,0 +1,155 @@
+//===- OpDefinitionsGen.cpp - IRDL op definitions generator ---------------===//
+//
+// Part of the LLVM Project, 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
+//
+//===----------------------------------------------------------------------===//
+//
+// OpDefinitionsGen uses the description of operations to generate IRDL
+// definitions for ops.
+//
+//===----------------------------------------------------------------------===//
+
+#include "mlir/Dialect/IRDL/IR/IRDL.h"
+#include "mlir/IR/Attributes.h"
+#include "mlir/IR/Builders.h"
+#include "mlir/IR/BuiltinOps.h"
+#include "mlir/IR/Diagnostics.h"
+#include "mlir/IR/Dialect.h"
+#include "mlir/IR/MLIRContext.h"
+#include "mlir/TableGen/AttrOrTypeDef.h"
+#include "mlir/TableGen/GenInfo.h"
+#include "mlir/TableGen/GenNameParser.h"
+#include "mlir/TableGen/Interfaces.h"
+#include "mlir/TableGen/Operator.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/InitLLVM.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/TableGen/Main.h"
+#include "llvm/TableGen/Record.h"
+#include "llvm/TableGen/TableGenBackend.h"
+
+using namespace llvm;
+using namespace mlir;
+using tblgen::NamedTypeConstraint;
+
+static llvm::cl::OptionCategory dialectGenCat("Options for -gen-irdl-dialect");
+llvm::cl::opt<std::string>
+ selectedDialect("dialect", llvm::cl::desc("The dialect to gen for"),
+ llvm::cl::cat(dialectGenCat), llvm::cl::Required);
+
+irdl::CPredOp createConstraint(OpBuilder &builder,
+ NamedTypeConstraint namedConstraint) {
+ MLIRContext *ctx = builder.getContext();
+ // Build the constraint as a string.
+ std::string constraint =
+ namedConstraint.constraint.getPredicate().getCondition();
+ // Build a CPredOp to match the C constraint built.
+ irdl::CPredOp op = builder.create<irdl::CPredOp>(
+ UnknownLoc::get(ctx), StringAttr::get(ctx, constraint));
+ return op;
+}
+
+/// Returns the name of the operation without the dialect prefix.
+static StringRef getOperatorName(tblgen::Operator &tblgenOp) {
+ StringRef opName = tblgenOp.getDef().getValueAsString("opName");
+ return opName;
+}
+
+/// Extract an operation to IRDL.
+irdl::OperationOp createIRDLOperation(OpBuilder &builder,
+ tblgen::Operator &tblgenOp) {
+ MLIRContext *ctx = builder.getContext();
+ StringRef opName = getOperatorName(tblgenOp);
+
+ irdl::OperationOp op = builder.create<irdl::OperationOp>(
+ UnknownLoc::get(ctx), StringAttr::get(ctx, opName));
+
+ // Add the block in the region.
+ Block &opBlock = op.getBody().emplaceBlock();
+ OpBuilder consBuilder = OpBuilder::atBlockBegin(&opBlock);
+
+ auto getValues = [&](tblgen::Operator::const_value_range namedCons) {
+ SmallVector<Value> operands;
+ SmallVector<irdl::VariadicityAttr> variadicity;
+ for (const NamedTypeConstraint &namedCons : namedCons) {
+ auto operand = createConstraint(consBuilder, namedCons);
+ operands.push_back(operand);
+
+ irdl::VariadicityAttr var;
+ if (namedCons.isOptional())
+ var = consBuilder.getAttr<irdl::VariadicityAttr>(
+ irdl::Variadicity::optional);
+ else if (namedCons.isVariadic())
+ var = consBuilder.getAttr<irdl::VariadicityAttr>(
+ irdl::Variadicity::variadic);
+ else
+ var = consBuilder.getAttr<irdl::VariadicityAttr>(
+ irdl::Variadicity::single);
+
+ variadicity.push_back(var);
+ }
+ return std::make_tuple(operands, variadicity);
+ };
+
+ auto [operands, operandVariadicity] = getValues(tblgenOp.getOperands());
+ auto [results, resultVariadicity] = getValues(tblgenOp.getResults());
+
+ // Create the operands and results operations.
+ consBuilder.create<irdl::OperandsOp>(UnknownLoc::get(ctx), operands,
+ operandVariadicity);
+ consBuilder.create<irdl::ResultsOp>(UnknownLoc::get(ctx), results,
+ resultVariadicity);
+
+ return op;
+}
+
+static irdl::DialectOp createIRDLDialect(OpBuilder &builder) {
+ MLIRContext *ctx = builder.getContext();
+ return builder.create<irdl::DialectOp>(UnknownLoc::get(ctx),
+ StringAttr::get(ctx, selectedDialect));
+}
+
+static std::vector<llvm::Record *>
+getOpDefinitions(const RecordKeeper &recordKeeper) {
+ if (!recordKeeper.getClass("Op"))
+ return {};
+ return recordKeeper.getAllDerivedDefinitions("Op");
+}
+
+static bool emitDialectIRDLDefs(const RecordKeeper &recordKeeper,
+ raw_ostream &os) {
+ // Initialize.
+ MLIRContext ctx;
+ ctx.getOrLoadDialect<irdl::IRDLDialect>();
+ OpBuilder builder(&ctx);
+
+ // Create a module op and set it as the insertion point.
+ OwningOpRef<ModuleOp> module = builder.create<ModuleOp>(UnknownLoc::get(&ctx));
+ builder = builder.atBlockBegin(module->getBody());
+ // Create the dialect and insert it.
+ irdl::DialectOp dialect = createIRDLDialect(builder);
+ // Set insertion point to start of DialectOp.
+ builder = builder.atBlockBegin(&dialect.getBody().emplaceBlock());
+
+ std::vector<Record *> defs = getOpDefinitions(recordKeeper);
+ for (auto *def : defs) {
+ tblgen::Operator tblgenOp(def);
+ if (tblgenOp.getDialectName() != selectedDialect)
+ continue;
+
+ createIRDLOperation(builder, tblgenOp);
+ }
+
+ // Print the module.
+ module->print(os);
+
+ return false;
+}
+
+static mlir::GenRegistration
+ genOpDefs("gen-dialect-irdl-defs", "Generate IRDL dialect definitions",
+ [](const RecordKeeper &records, raw_ostream &os) {
+ return emitDialectIRDLDefs(records, os);
+ });
diff --git a/mlir/tools/tblgen-to-irdl/tblgen-to-irdl.cpp b/mlir/tools/tblgen-to-irdl/tblgen-to-irdl.cpp
new file mode 100644
index 000000000000000..092ec2ebe81a682
--- /dev/null
+++ b/mlir/tools/tblgen-to-irdl/tblgen-to-irdl.cpp
@@ -0,0 +1,27 @@
+//===- mlir-tblgen.cpp - Top-Level TableGen implementation for MLIR -------===//
+//
+// Part of the LLVM Project, 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the main function for MLIR's TableGen IRDL backend.
+//
+//===----------------------------------------------------------------------===//
+
+#include "mlir/TableGen/GenInfo.h"
+#include "mlir/Tools/mlir-tblgen/MlirTblgenMain.h"
+#include "llvm/TableGen/Record.h"
+
+using namespace llvm;
+using namespace mlir;
+
+// Generator that prints records.
+GenRegistration printRecords("print-records", "Print all records to stdout",
+ [](const RecordKeeper &records, raw_ostream &os) {
+ os << records;
+ return false;
+ });
+
+int main(int argc, char **argv) { return MlirTblgenMain(argc, argv); }
|
math-fehr
approved these changes
Oct 24, 2023
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This patch relands the reverted commit e6e9beb after fixing the sanitizer issue.