[Mlir-commits] [mlir] Reland [mlir][tools] Introduce tblgen-to-irdl tool (PR #70121)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Tue Oct 24 13:47:44 PDT 2023


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-mlir-core

Author: Kunwar Grover (Groverkss)

<details>
<summary>Changes</summary>

This patch relands the reverted commit https://github.com/llvm/llvm-project/commit/e6e9beb977555c84fb16ffdd8dca8649c7d3091d after fixing the sanitizer issue.

---
Full diff: https://github.com/llvm/llvm-project/pull/70121.diff


6 Files Affected:

- (modified) mlir/test/CMakeLists.txt (+1) 
- (added) mlir/test/tblgen-to-irdl/CMathDialect.td (+56) 
- (modified) mlir/tools/CMakeLists.txt (+1) 
- (added) mlir/tools/tblgen-to-irdl/CMakeLists.txt (+20) 
- (added) mlir/tools/tblgen-to-irdl/OpDefinitionsGen.cpp (+155) 
- (added) mlir/tools/tblgen-to-irdl/tblgen-to-irdl.cpp (+27) 


``````````diff
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); }

``````````

</details>


https://github.com/llvm/llvm-project/pull/70121


More information about the Mlir-commits mailing list