From ec44f7452c612e30b74bdae8f398dbb979d4ebd1 Mon Sep 17 00:00:00 2001 From: Groverkss Date: Mon, 24 Jul 2023 01:18:32 +0530 Subject: [PATCH 1/3] Add tblgen-to-irdl tool --- mlir/test/CMakeLists.txt | 1 + mlir/test/tblgen-to-irdl/CMathDialect.td | 56 +++++++ mlir/tools/CMakeLists.txt | 1 + mlir/tools/tblgen-to-irdl/CMakeLists.txt | 20 +++ .../tools/tblgen-to-irdl/OpDefinitionsGen.cpp | 141 ++++++++++++++++++ mlir/tools/tblgen-to-irdl/tblgen-to-irdl.cpp | 27 ++++ 6 files changed, 246 insertions(+) create mode 100644 mlir/test/tblgen-to-irdl/CMathDialect.td create mode 100644 mlir/tools/tblgen-to-irdl/CMakeLists.txt create mode 100644 mlir/tools/tblgen-to-irdl/OpDefinitionsGen.cpp create mode 100644 mlir/tools/tblgen-to-irdl/tblgen-to-irdl.cpp diff --git a/mlir/test/CMakeLists.txt b/mlir/test/CMakeLists.txt index bf143d036c2f6..04bfa1ade655e 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 0000000000000..57ae8afbba5ee --- /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 traits = []> +: TypeDef { + let mnemonic = typeMnemonic; +} + +class CMath_Op traits = []> + : Op; + +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($_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($_self))" +// CHECK-NEXT: %1 = irdl.c_pred "(::llvm::isa($_self))" +// CHECK-NEXT: %2 = irdl.c_pred "(::llvm::isa($_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($_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 e9a1e4d625172..895a103061d30 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 0000000000000..a6621cb98ac6b --- /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 0000000000000..af342947bb28e --- /dev/null +++ b/mlir/tools/tblgen-to-irdl/OpDefinitionsGen.cpp @@ -0,0 +1,141 @@ +//===- 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 + 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( + 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( + UnknownLoc::get(ctx), StringAttr::get(ctx, opName)); + + // Add the block in the region. + Block &opBlock = op.getBody().emplaceBlock(); + OpBuilder consBuilder = OpBuilder::atBlockBegin(&opBlock); + + // Extract operands of the operation. + SmallVector operands; + for (const NamedTypeConstraint &namedCons : tblgenOp.getOperands()) { + auto operand = createConstraint(consBuilder, namedCons); + operands.push_back(operand); + } + + // Extract results of the operation. + SmallVector results; + for (const NamedTypeConstraint &namedCons : tblgenOp.getResults()) { + auto result = createConstraint(consBuilder, namedCons); + results.push_back(result); + } + + // Create the operands and results operations. + consBuilder.create(UnknownLoc::get(ctx), operands); + consBuilder.create(UnknownLoc::get(ctx), results); + + return op; +} + +static irdl::DialectOp createIRDLDialect(OpBuilder &builder) { + MLIRContext *ctx = builder.getContext(); + return builder.create(UnknownLoc::get(ctx), + StringAttr::get(ctx, selectedDialect)); +} + +static std::vector +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(); + OpBuilder builder(&ctx); + + // Create a module op and set it as the insertion point. + ModuleOp module = builder.create(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 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 0000000000000..092ec2ebe81a6 --- /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); } From 29ed2c50ed4292420aec1614e764ae646acd0fd2 Mon Sep 17 00:00:00 2001 From: Groverkss Date: Thu, 27 Jul 2023 23:08:43 +0530 Subject: [PATCH 2/3] [mlir][tools] Introduce tblgen-to-irdl tool 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 --- mlir/tools/tblgen-to-irdl/OpDefinitionsGen.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mlir/tools/tblgen-to-irdl/OpDefinitionsGen.cpp b/mlir/tools/tblgen-to-irdl/OpDefinitionsGen.cpp index af342947bb28e..5f899ee242c04 100644 --- a/mlir/tools/tblgen-to-irdl/OpDefinitionsGen.cpp +++ b/mlir/tools/tblgen-to-irdl/OpDefinitionsGen.cpp @@ -73,6 +73,8 @@ irdl::OperationOp createIRDLOperation(OpBuilder &builder, // Extract operands of the operation. SmallVector operands; for (const NamedTypeConstraint &namedCons : tblgenOp.getOperands()) { + assert(namedCons.isVariableLength() && + "Variable length operands not supported yet"); auto operand = createConstraint(consBuilder, namedCons); operands.push_back(operand); } @@ -80,6 +82,8 @@ irdl::OperationOp createIRDLOperation(OpBuilder &builder, // Extract results of the operation. SmallVector results; for (const NamedTypeConstraint &namedCons : tblgenOp.getResults()) { + assert(namedCons.isVariableLength() && + "Variable length operands not supported yet"); auto result = createConstraint(consBuilder, namedCons); results.push_back(result); } From 46d317edf479ca33976c5299fe1a10bac968761a Mon Sep 17 00:00:00 2001 From: Groverkss Date: Thu, 14 Sep 2023 19:45:53 +0530 Subject: [PATCH 3/3] Rebase and account for variadicity --- .../tools/tblgen-to-irdl/OpDefinitionsGen.cpp | 48 +++++++++++-------- 1 file changed, 29 insertions(+), 19 deletions(-) diff --git a/mlir/tools/tblgen-to-irdl/OpDefinitionsGen.cpp b/mlir/tools/tblgen-to-irdl/OpDefinitionsGen.cpp index 5f899ee242c04..2323127d7afd6 100644 --- a/mlir/tools/tblgen-to-irdl/OpDefinitionsGen.cpp +++ b/mlir/tools/tblgen-to-irdl/OpDefinitionsGen.cpp @@ -70,27 +70,37 @@ irdl::OperationOp createIRDLOperation(OpBuilder &builder, Block &opBlock = op.getBody().emplaceBlock(); OpBuilder consBuilder = OpBuilder::atBlockBegin(&opBlock); - // Extract operands of the operation. - SmallVector operands; - for (const NamedTypeConstraint &namedCons : tblgenOp.getOperands()) { - assert(namedCons.isVariableLength() && - "Variable length operands not supported yet"); - auto operand = createConstraint(consBuilder, namedCons); - operands.push_back(operand); - } - - // Extract results of the operation. - SmallVector results; - for (const NamedTypeConstraint &namedCons : tblgenOp.getResults()) { - assert(namedCons.isVariableLength() && - "Variable length operands not supported yet"); - auto result = createConstraint(consBuilder, namedCons); - results.push_back(result); - } + auto getValues = [&](tblgen::Operator::const_value_range namedCons) { + SmallVector operands; + SmallVector 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::Variadicity::optional); + else if (namedCons.isVariadic()) + var = consBuilder.getAttr( + irdl::Variadicity::variadic); + else + var = consBuilder.getAttr( + 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(UnknownLoc::get(ctx), operands); - consBuilder.create(UnknownLoc::get(ctx), results); + consBuilder.create(UnknownLoc::get(ctx), operands, + operandVariadicity); + consBuilder.create(UnknownLoc::get(ctx), results, + resultVariadicity); return op; }