diff --git a/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h b/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h --- a/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h +++ b/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h @@ -53,9 +53,11 @@ T translator(m); translator.llvmModule = std::move(llvmModule); + translator.postLLVMModuleCreation(); translator.convertGlobals(); if (failed(translator.convertFunctions())) return nullptr; + translator.postLLVMTranslation(); return std::move(translator.llvmModule); } @@ -74,6 +76,8 @@ } virtual ~ModuleTranslation() {} + virtual void postLLVMModuleCreation() {} + virtual void postLLVMTranslation() {} virtual LogicalResult convertOperation(Operation &op, llvm::IRBuilder<> &builder); static std::unique_ptr prepareLLVMModule(Operation *m); @@ -94,14 +98,15 @@ llvm::Constant *getLLVMConstant(llvm::Type *llvmType, Attribute attr, Location loc); - // Original and translated module. + // Original module. Operation *mlirModule; - std::unique_ptr llvmModule; // Mappings between llvm.mlir.global definitions and corresponding globals. DenseMap globalsMapping; protected: + // Translated module. + std::unique_ptr llvmModule; // Mappings between original and translated values, used for lookups. llvm::StringMap functionMapping; DenseMap valueMapping; diff --git a/mlir/include/mlir/Target/OpenMPLLVMIR.h b/mlir/include/mlir/Target/OpenMPLLVMIR.h new file mode 100644 --- /dev/null +++ b/mlir/include/mlir/Target/OpenMPLLVMIR.h @@ -0,0 +1,36 @@ +//===- OpenMPLLVMIR.h - MLIR (w OpenMP) to LLVM IR conversion -*- C++ ---*-===// +// +// Part of the MLIR 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 declares the entry point for the MLIR (with OpenMP) to LLVM IR +// conversion. +// +//===----------------------------------------------------------------------===// + +#ifndef MLIR_TARGET_OPENMPLLVMIR_H +#define MLIR_TARGET_OPENMPLLVMIR_H + +#include + +// Forward-declare LLVM classes. +namespace llvm { +class Module; +} // namespace llvm + +namespace mlir { +class Operation; + +/// Convert the given LLVM-module-like operation containing OpenMP into LLVM IR. +/// This conversion requires the registration of the LLVM IR dialect and will +/// extract the LLVM context from the registered LLVM IR dialect. In case of +/// error, report it to the error handler registered with the MLIR context, if +/// any (obtained from the MLIR module), and return `nullptr`. +std::unique_ptr translateModuleToOpenMPLLVMIR(Operation *m); + +} // namespace mlir + +#endif // MLIR_TARGET_OPENMPLLVMIR_H diff --git a/mlir/lib/Target/CMakeLists.txt b/mlir/lib/Target/CMakeLists.txt --- a/mlir/lib/Target/CMakeLists.txt +++ b/mlir/lib/Target/CMakeLists.txt @@ -47,3 +47,15 @@ MLIRROCDLIR MLIRTargetLLVMIRModuleTranslation ) +add_llvm_library(MLIRTargetOPENMPLLVMIR + LLVMIR/ConvertToOpenMPLLVMIR.cpp + + ADDITIONAL_HEADER_DIRS + ${MLIR_MAIN_INCLUDE_DIR}/mlir/Target/LLVMIR + ) +target_link_libraries(MLIRTargetOPENMPLLVMIR + MLIRIR + MLIRLLVMIR + MLIROpenMP + MLIRTargetLLVMIRModuleTranslation + ) diff --git a/mlir/lib/Target/LLVMIR/ConvertToOpenMPLLVMIR.cpp b/mlir/lib/Target/LLVMIR/ConvertToOpenMPLLVMIR.cpp new file mode 100644 --- /dev/null +++ b/mlir/lib/Target/LLVMIR/ConvertToOpenMPLLVMIR.cpp @@ -0,0 +1,82 @@ +//===- ConvertToNVVMIR.cpp - MLIR to LLVM IR conversion -------------------===// +// +// Part of the MLIR 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 LLVM + NVVM dialects and +// LLVM IR with NVVM intrinsics and metadata. +// +//===----------------------------------------------------------------------===// + +#include "mlir/Target/OpenMPLLVMIR.h" + +#include "mlir/Dialect/LLVMIR/LLVMDialect.h" +#include "mlir/Dialect/OpenMP/OpenMPDialect.h" +#include "mlir/IR/Module.h" +#include "mlir/Target/LLVMIR/ModuleTranslation.h" +#include "mlir/Translation.h" + +#include "llvm/ADT/StringRef.h" +#include "llvm/IR/Module.h" +#include "llvm/Support/ToolOutputFile.h" +#include "llvm/Frontend/OpenMP/OMPIRBuilder.h" + +using namespace mlir; + +namespace { +class ModuleTranslation : public LLVM::ModuleTranslation { + +public: + explicit ModuleTranslation(Operation *module) + : LLVM::ModuleTranslation(module) { + } + ~ModuleTranslation() override {} + + void postLLVMModuleCreation() override { + OMPBuilder = new llvm::OpenMPIRBuilder(*llvmModule); + OMPBuilder->initialize(); + } + + void postLLVMTranslation() override { + if (OMPBuilder) + delete OMPBuilder; + } + +protected: + LogicalResult convertOperation(Operation &opInst, + llvm::IRBuilder<> &builder) override { + + if (auto barrierOp = dyn_cast(opInst)) { + llvm::OpenMPIRBuilder::LocationDescription Loc({builder.saveIP()}); + OMPBuilder->CreateBarrier(Loc, llvm::omp::OMPD_barrier); + return success(); + } + + return LLVM::ModuleTranslation::convertOperation(opInst, builder); + } + +private: + llvm::OpenMPIRBuilder *OMPBuilder; +}; +} // namespace + +std::unique_ptr mlir::translateModuleToOpenMPLLVMIR(Operation *m) { + ModuleTranslation translation(m); + auto llvmModule = + LLVM::ModuleTranslation::translateModule(m); + + return llvmModule; +} + +static TranslateFromMLIRRegistration + registration("mlir-to-openmpllvmir", [](ModuleOp module, raw_ostream &output) { + auto llvmModule = mlir::translateModuleToOpenMPLLVMIR(module); + if (!llvmModule) + return failure(); + + llvmModule->print(output, nullptr); + return success(); + }); diff --git a/mlir/test/Target/openmp-llvm.mlir b/mlir/test/Target/openmp-llvm.mlir new file mode 100644 --- /dev/null +++ b/mlir/test/Target/openmp-llvm.mlir @@ -0,0 +1,11 @@ +// RUN: mlir-translate -mlir-to-openmpllvmir %s | FileCheck %s + +// CHECK-LABEL: define void @empty() { +// CHECK: [[OMP_THREAD:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* @{{[0-9]+}}) +// CHECK-NEXT: call void @__kmpc_barrier(%struct.ident_t* @{{[0-9]+}}, i32 [[OMP_THREAD]]) +// CHECK-NEXT: ret void +// CHECK-NEXT: } +llvm.func @empty() { + omp.barrier + llvm.return +} diff --git a/mlir/tools/mlir-translate/CMakeLists.txt b/mlir/tools/mlir-translate/CMakeLists.txt --- a/mlir/tools/mlir-translate/CMakeLists.txt +++ b/mlir/tools/mlir-translate/CMakeLists.txt @@ -6,8 +6,10 @@ MLIRTargetLLVMIR MLIRTargetNVVMIR MLIRTargetROCDLIR + MLIRTargetOPENMPLLVMIR MLIRTranslation MLIRSupport + LLVMFrontendOpenMP ) add_llvm_executable(mlir-translate mlir-translate.cpp