Skip to content

[mlir] Re-Add mlirTranslateModuleToLLVMIR to MLIR-C #73627

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 6 commits into from
Nov 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions mlir/include/mlir-c/Target/LLVMIR.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
//===-- LLVMIR.h - C Interface for MLIR LLVMIR Target -------------*- C -*-===//
//
// 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 header declares the C interface to target LLVMIR with MLIR.
//
//===----------------------------------------------------------------------===//

#ifndef MLIR_C_TARGET_LLVMIR_H
#define MLIR_C_TARGET_LLVMIR_H

#include "mlir-c/IR.h"
#include "mlir-c/Support.h"
#include "llvm-c/Support.h"

#ifdef __cplusplus
extern "C" {
#endif

/// Translate operation that satisfies LLVM dialect module requirements into an
/// LLVM IR module living in the given context. This translates operations from
/// any dilalect that has a registered implementation of
/// LLVMTranslationDialectInterface.
///
/// \returns the generated LLVM IR Module from the translated MLIR module, it is
/// owned by the caller.
MLIR_CAPI_EXPORTED LLVMModuleRef
mlirTranslateModuleToLLVMIR(MlirOperation module, LLVMContextRef context);

#ifdef __cplusplus
}
#endif

#endif // MLIR_C_TARGET_LLVMIR_H
2 changes: 1 addition & 1 deletion mlir/lib/CAPI/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ add_subdirectory(Interfaces)
add_subdirectory(IR)
add_subdirectory(RegisterEverything)
add_subdirectory(Transforms)
add_subdirectory(Target)

if(MLIR_ENABLE_EXECUTION_ENGINE)
add_subdirectory(ExecutionEngine)
Expand All @@ -36,4 +37,3 @@ if(MLIR_BUILD_MLIR_C_DYLIB)
endif()
endif()
endif()

12 changes: 12 additions & 0 deletions mlir/lib/CAPI/Target/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
add_mlir_upstream_c_api_library(MLIRCAPITarget
LLVMIR.cpp

LINK_COMPONENTS
Core

LINK_LIBS PUBLIC
MLIRToLLVMIRTranslationRegistration
MLIRCAPIIR
MLIRLLVMToLLVMIRTranslation
MLIRSupport
)
36 changes: 36 additions & 0 deletions mlir/lib/CAPI/Target/LLVMIR.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//===-- LLVMIR.h - C Interface for MLIR LLVMIR Target ---------------------===//
//
// 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 "mlir-c/Target/LLVMIR.h"
#include "llvm-c/Support.h"

#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include <memory>

#include "mlir/CAPI/IR.h"
#include "mlir/CAPI/Support.h"
#include "mlir/CAPI/Wrap.h"
#include "mlir/Target/LLVMIR/ModuleTranslation.h"

using namespace mlir;

LLVMModuleRef mlirTranslateModuleToLLVMIR(MlirOperation module,
LLVMContextRef context) {
Operation *moduleOp = unwrap(module);

llvm::LLVMContext *ctx = llvm::unwrap(context);

std::unique_ptr<llvm::Module> llvmModule =
mlir::translateModuleToLLVMIR(moduleOp, *ctx);

LLVMModuleRef moduleRef = llvm::wrap(llvmModule.release());

return moduleRef;
}
9 changes: 9 additions & 0 deletions mlir/test/CAPI/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -85,3 +85,12 @@ _add_capi_test_executable(mlir-capi-transform-test
MLIRCAPIRegisterEverything
MLIRCAPITransformDialect
)

_add_capi_test_executable(mlir-capi-translation-test
translation.c
LINK_LIBS PRIVATE
MLIRCAPIIR
MLIRCAPILLVM
MLIRCAPIRegisterEverything
MLIRCAPITarget
)
67 changes: 67 additions & 0 deletions mlir/test/CAPI/translation.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
//===- translation.c - Test MLIR Target translations ----------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

// RUN: mlir-capi-translation-test 2>&1 | FileCheck %s

#include "llvm-c/Core.h"
#include "llvm-c/Support.h"
#include "llvm-c/Types.h"

#include "mlir-c/BuiltinTypes.h"
#include "mlir-c/Dialect/LLVM.h"
#include "mlir-c/IR.h"
#include "mlir-c/RegisterEverything.h"
#include "mlir-c/Support.h"
#include "mlir-c/Target/LLVMIR.h"

#include <assert.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// CHECK-LABEL: testToLLVMIR()
static void testToLLVMIR(MlirContext ctx) {
fprintf(stderr, "testToLLVMIR()\n");
LLVMContextRef llvmCtx = LLVMContextCreate();

const char *moduleString = "llvm.func @add(%arg0: i64, %arg1: i64) -> i64 { \
%0 = llvm.add %arg0, %arg1 : i64 \
llvm.return %0 : i64 \
}";

mlirRegisterAllLLVMTranslations(ctx);

MlirModule module =
mlirModuleCreateParse(ctx, mlirStringRefCreateFromCString(moduleString));

MlirOperation operation = mlirModuleGetOperation(module);

LLVMModuleRef llvmModule = mlirTranslateModuleToLLVMIR(operation, llvmCtx);

// clang-format off
// CHECK: define i64 @add(i64 %[[arg1:.*]], i64 %[[arg2:.*]]) {
// CHECK-NEXT: %[[arg3:.*]] = add i64 %[[arg1]], %[[arg2]]
// CHECK-NEXT: ret i64 %[[arg3]]
// CHECK-NEXT: }
// clang-format on
LLVMDumpModule(llvmModule);

LLVMDisposeModule(llvmModule);
mlirModuleDestroy(module);
}

int main(void) {
MlirContext ctx = mlirContextCreate();
mlirDialectHandleRegisterDialect(mlirGetDialectHandle__llvm__(), ctx);
mlirContextGetOrLoadDialect(ctx, mlirStringRefCreateFromCString("llvm"));
testToLLVMIR(ctx);
mlirContextDestroy(ctx);
return 0;
}
9 changes: 5 additions & 4 deletions mlir/test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,10 @@ if (MLIR_INCLUDE_INTEGRATION_TESTS)
message(FATAL_ERROR "MLIR_INCLUDE_INTEGRATION_TESTS requires a native target")
endif()

# When the Integration tests are requested via the MLIR_INCLUDE_INTEGRATION_TESTS
# configuration flag, we automatically include sm80 tests when build for
# cuSparse when the configuration flag MLIR_ENABLE_CUDA_CUSPARSE is set and
# include sm80 lt tests when the MLIR_ENABLE_CUDA_CUSPARSELT is set in
# When the Integration tests are requested via the MLIR_INCLUDE_INTEGRATION_TESTS
# configuration flag, we automatically include sm80 tests when build for
# cuSparse when the configuration flag MLIR_ENABLE_CUDA_CUSPARSE is set and
# include sm80 lt tests when the MLIR_ENABLE_CUDA_CUSPARSELT is set in
# addition to those.
if (MLIR_ENABLE_CUDA_CUSPARSE)
set(MLIR_RUN_CUDA_SM80_TESTS ON)
Expand Down Expand Up @@ -101,6 +101,7 @@ set(MLIR_TEST_DEPENDS
mlir-capi-quant-test
mlir-capi-sparse-tensor-test
mlir-capi-transform-test
mlir-capi-translation-test
mlir-linalg-ods-yaml-gen
mlir-lsp-server
mlir-pdll-lsp-server
Expand Down
1 change: 1 addition & 0 deletions mlir/test/lit.cfg.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ def add_runtime(name):
"mlir-capi-quant-test",
"mlir-capi-sparse-tensor-test",
"mlir-capi-transform-test",
"mlir-capi-translation-test",
"mlir-cpu-runner",
add_runtime("mlir_runner_utils"),
add_runtime("mlir_c_runner_utils"),
Expand Down