[Mlir-commits] [mlir] merge code for llvm.emit_c_interface into convertFuncOpToLLVMFuncOp (PR #92986)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Tue May 21 20:08:36 PDT 2024


https://github.com/fengxie created https://github.com/llvm/llvm-project/pull/92986

In today's repo, attribute `llvm.emit_c_interface` of func op is handled outside of `mlir::convertFuncOpToLLVMFuncOp` in `FuncOpConversion` pattern. In some cases, `FuncOpConversion` can't be directly re-used, but we still want to re-use the code to emit c interface for `llvm.emit_c_interface`.

This PR
* move the code to generate c with "llvm.emit_c_interface" interface into `mlir::convertFuncOpToLLVMFuncOp` to be able to re-use it.
* added unit test to verify c interface for jit can be generated correctly.



>From 2287e3622aa8971161e1d94453467fa15afd54af Mon Sep 17 00:00:00 2001
From: Fung Xie <ftse at nvidia.com>
Date: Wed, 22 May 2024 10:59:37 +0800
Subject: [PATCH 1/2] merge code for llvm.emit_c_interface into
 convertFuncOpToLLVMFuncOp

---
 mlir/lib/Conversion/FuncToLLVM/FuncToLLVM.cpp | 40 ++++++------
 .../test/Transforms/test-convert-func-op.mlir | 12 ++++
 .../lib/Conversion/FuncToLLVM/CMakeLists.txt  |  1 +
 .../FuncToLLVM/TestConvertFuncOp.cpp          | 62 +++++++++++++++++++
 mlir/tools/mlir-opt/mlir-opt.cpp              |  2 +
 5 files changed, 97 insertions(+), 20 deletions(-)
 create mode 100644 mlir/test/Transforms/test-convert-func-op.mlir
 create mode 100644 mlir/test/lib/Conversion/FuncToLLVM/TestConvertFuncOp.cpp

diff --git a/mlir/lib/Conversion/FuncToLLVM/FuncToLLVM.cpp b/mlir/lib/Conversion/FuncToLLVM/FuncToLLVM.cpp
index 53b44aa3241bb..202bbd6fd17ab 100644
--- a/mlir/lib/Conversion/FuncToLLVM/FuncToLLVM.cpp
+++ b/mlir/lib/Conversion/FuncToLLVM/FuncToLLVM.cpp
@@ -449,6 +449,26 @@ mlir::convertFuncOpToLLVMFuncOp(FunctionOpInterface funcOp,
                                        "region types conversion failed");
   }
 
+  if (!shouldUseBarePtrCallConv(funcOp, &converter)) {
+    if (funcOp->getAttrOfType<UnitAttr>(
+            LLVM::LLVMDialect::getEmitCWrapperAttrName())) {
+      if (newFuncOp.isVarArg())
+        return funcOp.emitError("C interface for variadic functions is not "
+                                "supported yet.");
+
+      if (newFuncOp.isExternal())
+        wrapExternalFunction(rewriter, funcOp->getLoc(), converter, funcOp,
+                             newFuncOp);
+      else
+        wrapForExternalCallers(rewriter, funcOp->getLoc(), converter, funcOp,
+                               newFuncOp);
+    }
+  } else {
+    modifyFuncOpToUseBarePtrCallingConv(
+        rewriter, funcOp->getLoc(), converter, newFuncOp,
+        llvm::cast<FunctionType>(funcOp.getFunctionType()).getInputs());
+  }
+
   return newFuncOp;
 }
 
@@ -484,26 +504,6 @@ struct FuncOpConversion : public FuncOpConversionBase {
     if (failed(newFuncOp))
       return rewriter.notifyMatchFailure(funcOp, "Could not convert funcop");
 
-    if (!shouldUseBarePtrCallConv(funcOp, this->getTypeConverter())) {
-      if (funcOp->getAttrOfType<UnitAttr>(
-              LLVM::LLVMDialect::getEmitCWrapperAttrName())) {
-        if (newFuncOp->isVarArg())
-          return funcOp->emitError("C interface for variadic functions is not "
-                                   "supported yet.");
-
-        if (newFuncOp->isExternal())
-          wrapExternalFunction(rewriter, funcOp->getLoc(), *getTypeConverter(),
-                               funcOp, *newFuncOp);
-        else
-          wrapForExternalCallers(rewriter, funcOp->getLoc(),
-                                 *getTypeConverter(), funcOp, *newFuncOp);
-      }
-    } else {
-      modifyFuncOpToUseBarePtrCallingConv(rewriter, funcOp->getLoc(),
-                                          *getTypeConverter(), *newFuncOp,
-                                          funcOp.getFunctionType().getInputs());
-    }
-
     rewriter.eraseOp(funcOp);
     return success();
   }
diff --git a/mlir/test/Transforms/test-convert-func-op.mlir b/mlir/test/Transforms/test-convert-func-op.mlir
new file mode 100644
index 0000000000000..6e96703cda578
--- /dev/null
+++ b/mlir/test/Transforms/test-convert-func-op.mlir
@@ -0,0 +1,12 @@
+// RUN: mlir-opt %s -test-convert-func-op | FileCheck %s
+
+// CHECK-LABEL: llvm.func @add
+func.func @add(%arg0: i32, %arg1: i32) -> i32 attributes { llvm.emit_c_interface } {
+  %res = arith.addi %arg0, %arg1 : i32
+  return %res : i32
+}
+// CHECK-LABEL: llvm.func @_mlir_ciface_add
+// CHECK-SAME: [[ARG0:%[a-zA-Z0-9_]+]]: i32
+// CHECK-SAME: [[ARG1:%[a-zA-Z0-9_]+]]: i32
+// CHECK-NEXT: [[RES:%.*]] = llvm.call @add([[ARG0]], [[ARG1]])
+// CHECK-NEXT: llvm.return [[RES]]
diff --git a/mlir/test/lib/Conversion/FuncToLLVM/CMakeLists.txt b/mlir/test/lib/Conversion/FuncToLLVM/CMakeLists.txt
index 45ba62d839d36..d3dbc94a99bc7 100644
--- a/mlir/test/lib/Conversion/FuncToLLVM/CMakeLists.txt
+++ b/mlir/test/lib/Conversion/FuncToLLVM/CMakeLists.txt
@@ -1,6 +1,7 @@
 # Exclude tests from libMLIR.so
 add_mlir_library(MLIRTestFuncToLLVM
   TestConvertCallOp.cpp
+  TestConvertFuncOp.cpp
 
   EXCLUDE_FROM_LIBMLIR
 
diff --git a/mlir/test/lib/Conversion/FuncToLLVM/TestConvertFuncOp.cpp b/mlir/test/lib/Conversion/FuncToLLVM/TestConvertFuncOp.cpp
new file mode 100644
index 0000000000000..a801cf6528621
--- /dev/null
+++ b/mlir/test/lib/Conversion/FuncToLLVM/TestConvertFuncOp.cpp
@@ -0,0 +1,62 @@
+//===- TestConvertCallOp.cpp - Test LLVM Conversion of Func CallOp --------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "TestDialect.h"
+#include "TestOps.h"
+#include "TestTypes.h"
+#include "mlir/Conversion/FuncToLLVM/ConvertFuncToLLVM.h"
+#include "mlir/Conversion/LLVMCommon/Pattern.h"
+#include "mlir/Dialect/Func/IR/FuncOps.h"
+#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
+#include "mlir/Pass/Pass.h"
+
+using namespace mlir;
+
+namespace {
+
+struct TestConvertFuncOp
+    : public PassWrapper<TestConvertFuncOp, OperationPass<ModuleOp>> {
+  MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestConvertFuncOp)
+
+  void getDependentDialects(DialectRegistry &registry) const final {
+    registry.insert<LLVM::LLVMDialect>();
+  }
+  [[nodiscard]] StringRef getArgument() const final { return "test-convert-func-op"; }
+  [[nodiscard]] StringRef getDescription() const final {
+    return "Tests conversion of `func.func` to `llvm.func` for different attributes"
+           ;
+  }
+
+  void runOnOperation() override {
+    ModuleOp m = getOperation();
+
+    LowerToLLVMOptions options(m.getContext());
+
+    // Populate type conversions.
+    LLVMTypeConverter typeConverter(m.getContext(), options);
+
+    // Populate patterns.
+    RewritePatternSet patterns(m.getContext());
+    populateFuncToLLVMConversionPatterns(typeConverter, patterns);
+
+    // Set target.
+    ConversionTarget target(getContext());
+    target.addLegalDialect<LLVM::LLVMDialect>();
+    target.addIllegalDialect<func::FuncDialect>();
+
+    if (failed(applyPartialConversion(m, target, std::move(patterns))))
+      signalPassFailure();
+  }
+};
+
+} // namespace
+
+
+namespace mlir::test {
+void registerConvertFuncOpPass() { PassRegistration<TestConvertFuncOp>(); }
+} // namespace mlir::test
diff --git a/mlir/tools/mlir-opt/mlir-opt.cpp b/mlir/tools/mlir-opt/mlir-opt.cpp
index 1dfc5d178b614..0e8b161d51345 100644
--- a/mlir/tools/mlir-opt/mlir-opt.cpp
+++ b/mlir/tools/mlir-opt/mlir-opt.cpp
@@ -71,6 +71,7 @@ namespace test {
 void registerTestCompositePass();
 void registerCommutativityUtils();
 void registerConvertCallOpPass();
+void registerConvertFuncOpPass();
 void registerInliner();
 void registerMemRefBoundCheck();
 void registerPatternsTestPass();
@@ -199,6 +200,7 @@ void registerTestPasses() {
   mlir::test::registerTestCompositePass();
   mlir::test::registerCommutativityUtils();
   mlir::test::registerConvertCallOpPass();
+  mlir::test::registerConvertFuncOpPass();
   mlir::test::registerInliner();
   mlir::test::registerMemRefBoundCheck();
   mlir::test::registerPatternsTestPass();

>From 319ef33ca5dcd26e77ca479b622e81fc5db6effb Mon Sep 17 00:00:00 2001
From: Fung Xie <ftse at nvidia.com>
Date: Wed, 22 May 2024 11:08:01 +0800
Subject: [PATCH 2/2] fixed comments and remove un-used headers

---
 .../Conversion/FuncToLLVM/TestConvertFuncOp.cpp    | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/mlir/test/lib/Conversion/FuncToLLVM/TestConvertFuncOp.cpp b/mlir/test/lib/Conversion/FuncToLLVM/TestConvertFuncOp.cpp
index a801cf6528621..87fbf2dd15917 100644
--- a/mlir/test/lib/Conversion/FuncToLLVM/TestConvertFuncOp.cpp
+++ b/mlir/test/lib/Conversion/FuncToLLVM/TestConvertFuncOp.cpp
@@ -1,4 +1,4 @@
-//===- TestConvertCallOp.cpp - Test LLVM Conversion of Func CallOp --------===//
+//===- TestConvertFuncOp.cpp - Test LLVM Conversion of Func FuncOp --------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -7,8 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "TestDialect.h"
-#include "TestOps.h"
-#include "TestTypes.h"
+
 #include "mlir/Conversion/FuncToLLVM/ConvertFuncToLLVM.h"
 #include "mlir/Conversion/LLVMCommon/Pattern.h"
 #include "mlir/Dialect/Func/IR/FuncOps.h"
@@ -26,10 +25,12 @@ struct TestConvertFuncOp
   void getDependentDialects(DialectRegistry &registry) const final {
     registry.insert<LLVM::LLVMDialect>();
   }
-  [[nodiscard]] StringRef getArgument() const final { return "test-convert-func-op"; }
+  [[nodiscard]] StringRef getArgument() const final {
+    return "test-convert-func-op";
+  }
   [[nodiscard]] StringRef getDescription() const final {
-    return "Tests conversion of `func.func` to `llvm.func` for different attributes"
-           ;
+    return "Tests conversion of `func.func` to `llvm.func` for different "
+           "attributes";
   }
 
   void runOnOperation() override {
@@ -56,7 +57,6 @@ struct TestConvertFuncOp
 
 } // namespace
 
-
 namespace mlir::test {
 void registerConvertFuncOpPass() { PassRegistration<TestConvertFuncOp>(); }
 } // namespace mlir::test



More information about the Mlir-commits mailing list