[Mlir-commits] [mlir] 0b8c636 - [MLIR] Move builtin.module LLVM IR translation to before nested operations

Sergio Afonso llvmlistbot at llvm.org
Fri Sep 1 09:09:47 PDT 2023


Author: Sergio Afonso
Date: 2023-09-01T17:09:25+01:00
New Revision: 0b8c636211b89ba721f060d30290e8a1992879b7

URL: https://github.com/llvm/llvm-project/commit/0b8c636211b89ba721f060d30290e8a1992879b7
DIFF: https://github.com/llvm/llvm-project/commit/0b8c636211b89ba721f060d30290e8a1992879b7.diff

LOG: [MLIR] Move builtin.module LLVM IR translation to before nested operations

This patch moves the call for translating an MLIR module to LLVM IR to the
beginning of the translation process. This enables the use of dialect
attributes attached to `builtin.module` operations and the `amendOperation()`
flow to initialize dialect-specific global configuration before translating
the contents of the module.

Currently, this patch does not impact the generated IR on its own. Testing
infrastructure to allow translating the Test dialect to LLVM IR is added, so
that it can be checked that the current behavior is not broken in the future.

Differential Revision: https://reviews.llvm.org/D158278

Added: 
    mlir/test/Target/LLVMIR/test.mlir
    mlir/test/lib/Dialect/Test/TestToLLVMIRTranslation.cpp

Modified: 
    mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
    mlir/test/lib/Dialect/Test/CMakeLists.txt
    mlir/tools/mlir-translate/mlir-translate.cpp

Removed: 
    


################################################################################
diff  --git a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
index 8b38cf761273f96..ce9bf2fbe35a1a1 100644
--- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
@@ -1377,6 +1377,15 @@ mlir::translateModuleToLLVMIR(Operation *module, llvm::LLVMContext &llvmContext,
   LLVM::ensureDistinctSuccessors(module);
 
   ModuleTranslation translator(module, std::move(llvmModule));
+  llvm::IRBuilder<> llvmBuilder(llvmContext);
+
+  // Convert module before functions and operations inside, so dialect
+  // attributes can be used to change dialect-specific global configurations via
+  // `amendOperation()`. These configurations can then influence the translation
+  // of operations afterwards.
+  if (failed(translator.convertOperation(*module, llvmBuilder)))
+    return nullptr;
+
   if (failed(translator.convertComdats()))
     return nullptr;
   if (failed(translator.convertFunctionSignatures()))
@@ -1387,7 +1396,6 @@ mlir::translateModuleToLLVMIR(Operation *module, llvm::LLVMContext &llvmContext,
     return nullptr;
 
   // Convert other top-level operations if possible.
-  llvm::IRBuilder<> llvmBuilder(llvmContext);
   for (Operation &o : getModuleBody(module).getOperations()) {
     if (!isa<LLVM::LLVMFuncOp, LLVM::GlobalOp, LLVM::GlobalCtorsOp,
              LLVM::GlobalDtorsOp, LLVM::ComdatOp>(&o) &&
@@ -1403,10 +1411,6 @@ mlir::translateModuleToLLVMIR(Operation *module, llvm::LLVMContext &llvmContext,
   if (failed(translator.convertFunctions()))
     return nullptr;
 
-  // Convert module itself.
-  if (failed(translator.convertOperation(*module, llvmBuilder)))
-    return nullptr;
-
   if (llvm::verifyModule(*translator.llvmModule, &llvm::errs()))
     return nullptr;
 

diff  --git a/mlir/test/Target/LLVMIR/test.mlir b/mlir/test/Target/LLVMIR/test.mlir
new file mode 100644
index 000000000000000..f48738f44f44b4f
--- /dev/null
+++ b/mlir/test/Target/LLVMIR/test.mlir
@@ -0,0 +1,18 @@
+// RUN: mlir-translate -test-to-llvmir -split-input-file %s | FileCheck %s
+
+module {
+  "test.symbol"() <{sym_name = "foo"}> : () -> ()
+}
+
+// CHECK-NOT: @sym_from_attr
+// CHECK: @foo = external global i32
+// CHECK-NOT: @sym_from_attr
+
+// -----
+
+// Make sure that the module attribute is processed before its body, so that the
+// `test.symbol` that is created as a result of the `test.discardable_mod_attr`
+// attribute is later picked up and translated to LLVM IR.
+module attributes {test.discardable_mod_attr = true} {}
+
+// CHECK: @sym_from_attr = external global i32

diff  --git a/mlir/test/lib/Dialect/Test/CMakeLists.txt b/mlir/test/lib/Dialect/Test/CMakeLists.txt
index a185cc38b820142..e4cbbdadb992e03 100644
--- a/mlir/test/lib/Dialect/Test/CMakeLists.txt
+++ b/mlir/test/lib/Dialect/Test/CMakeLists.txt
@@ -2,6 +2,7 @@ set(LLVM_OPTIONAL_SOURCES
   TestDialect.cpp
   TestPatterns.cpp
   TestTraits.cpp
+  TestToLLVMIRTranslation.cpp
 )
 
 set(LLVM_TARGET_DEFINITIONS TestInterfaces.td)
@@ -83,4 +84,19 @@ add_mlir_library(MLIRTestDialect
   MLIRTensorDialect
   MLIRTransformUtils
   MLIRTransforms
-)
+  )
+
+add_mlir_translation_library(MLIRTestToLLVMIRTranslation
+  TestToLLVMIRTranslation.cpp
+
+  LINK_COMPONENTS
+  Core
+
+  LINK_LIBS PUBLIC
+  MLIRIR
+  MLIRLLVMDialect
+  MLIRTestDialect
+  MLIRSupport
+  MLIRBuiltinToLLVMIRTranslation
+  MLIRLLVMToLLVMIRTranslation
+  )

diff  --git a/mlir/test/lib/Dialect/Test/TestToLLVMIRTranslation.cpp b/mlir/test/lib/Dialect/Test/TestToLLVMIRTranslation.cpp
new file mode 100644
index 000000000000000..7110d999c8f8ae2
--- /dev/null
+++ b/mlir/test/lib/Dialect/Test/TestToLLVMIRTranslation.cpp
@@ -0,0 +1,124 @@
+//===- TestToLLVMIRTranslation.cpp - Translate Test dialect to LLVM IR ----===//
+//
+// 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 implements a translation between the MLIR Test dialect and LLVM IR.
+//
+//===----------------------------------------------------------------------===//
+
+#include "TestDialect.h"
+#include "mlir/IR/Builders.h"
+#include "mlir/IR/BuiltinAttributes.h"
+#include "mlir/IR/BuiltinOps.h"
+#include "mlir/Target/LLVMIR/Dialect/Builtin/BuiltinToLLVMIRTranslation.h"
+#include "mlir/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.h"
+#include "mlir/Target/LLVMIR/LLVMTranslationInterface.h"
+#include "mlir/Target/LLVMIR/ModuleTranslation.h"
+#include "mlir/Tools/mlir-translate/Translation.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/TypeSwitch.h"
+
+using namespace mlir;
+
+namespace {
+
+class TestDialectLLVMIRTranslationInterface
+    : public LLVMTranslationDialectInterface {
+public:
+  using LLVMTranslationDialectInterface::LLVMTranslationDialectInterface;
+
+  LogicalResult
+  amendOperation(Operation *op, NamedAttribute attribute,
+                 LLVM::ModuleTranslation &moduleTranslation) const final;
+
+  LogicalResult
+  convertOperation(Operation *op, llvm::IRBuilderBase &builder,
+                   LLVM::ModuleTranslation &moduleTranslation) const final;
+};
+
+} // namespace
+
+LogicalResult TestDialectLLVMIRTranslationInterface::amendOperation(
+    Operation *op, NamedAttribute attribute,
+    LLVM::ModuleTranslation &moduleTranslation) const {
+  return llvm::StringSwitch<llvm::function_ref<LogicalResult(Attribute)>>(
+             attribute.getName())
+      // The `test.discardable_mod_attr` attribute, if present and set to
+      // `true`, results in the addition of a `test.symbol` in the module it is
+      // attached to with name "sym_from_attr".
+      .Case("test.discardable_mod_attr",
+            [&](Attribute attr) {
+              if (!isa<ModuleOp>(op)) {
+                op->emitOpError("attribute 'test.discardable_mod_attr' only "
+                                "supported in modules");
+                return failure();
+              }
+
+              bool createSymbol = false;
+              if (auto boolAttr = attr.dyn_cast<BoolAttr>())
+                createSymbol = boolAttr.getValue();
+
+              if (createSymbol) {
+                OpBuilder builder(op->getRegion(0));
+                builder.create<test::SymbolOp>(
+                    op->getLoc(),
+                    StringAttr::get(op->getContext(), "sym_from_attr"),
+                    /*sym_visibility=*/nullptr);
+              }
+
+              return success();
+            })
+      .Default([](Attribute) {
+        // Skip other discardable dialect attributes.
+        return success();
+      })(attribute.getValue());
+}
+
+LogicalResult TestDialectLLVMIRTranslationInterface::convertOperation(
+    Operation *op, llvm::IRBuilderBase &builder,
+    LLVM::ModuleTranslation &moduleTranslation) const {
+  return llvm::TypeSwitch<Operation *, LogicalResult>(op)
+      // `test.symbol`s are translated into global integers in LLVM IR, with a
+      // name equal to the symbol they are translated from.
+      .Case([&](test::SymbolOp symOp) {
+        llvm::Module *mod = moduleTranslation.getLLVMModule();
+        llvm::IntegerType *i32Type =
+            llvm::IntegerType::get(moduleTranslation.getLLVMContext(), 32);
+        mod->getOrInsertGlobal(symOp.getSymName(), i32Type);
+        return success();
+      })
+      .Default([&](Operation *) {
+        return op->emitOpError("unsupported translation of test operation");
+      });
+}
+
+namespace mlir {
+
+void registerTestToLLVMIR() {
+  TranslateFromMLIRRegistration registration(
+      "test-to-llvmir", "test dialect to LLVM IR",
+      [](Operation *op, raw_ostream &output) {
+        llvm::LLVMContext llvmContext;
+        auto llvmModule = translateModuleToLLVMIR(op, llvmContext);
+        if (!llvmModule)
+          return failure();
+
+        llvmModule->print(output, nullptr);
+        return success();
+      },
+      [](DialectRegistry &registry) {
+        registry.insert<test::TestDialect>();
+        registerBuiltinDialectTranslation(registry);
+        registerLLVMDialectTranslation(registry);
+        registry.addExtension(
+            +[](MLIRContext *ctx, test::TestDialect *dialect) {
+              dialect->addInterfaces<TestDialectLLVMIRTranslationInterface>();
+            });
+      });
+}
+
+} // namespace mlir

diff  --git a/mlir/tools/mlir-translate/mlir-translate.cpp b/mlir/tools/mlir-translate/mlir-translate.cpp
index f39bf5894a417bb..4f9661c058c2d34 100644
--- a/mlir/tools/mlir-translate/mlir-translate.cpp
+++ b/mlir/tools/mlir-translate/mlir-translate.cpp
@@ -21,11 +21,17 @@ namespace mlir {
 // Defined in the test directory, no public header.
 void registerTestRoundtripSPIRV();
 void registerTestRoundtripDebugSPIRV();
+#ifdef MLIR_INCLUDE_TESTS
+void registerTestToLLVMIR();
+#endif
 } // namespace mlir
 
 static void registerTestTranslations() {
   registerTestRoundtripSPIRV();
   registerTestRoundtripDebugSPIRV();
+#ifdef MLIR_INCLUDE_TESTS
+  registerTestToLLVMIR();
+#endif
 }
 
 int main(int argc, char **argv) {


        


More information about the Mlir-commits mailing list