mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-28 16:11:29 +00:00
[mlir] Simplify ModuleTranslation for LLVM IR
A series of preceding patches changed the mechanism for translating MLIR to LLVM IR to use dialect interface with delayed registration. It is no longer necessary for specific dialects to derive from ModuleTranslation. Remove all virtual methods from ModuleTranslation and factor out the entry point to be a free function. Also perform some cleanups in ModuleTranslation internals. Depends On D96774 Reviewed By: nicolasvasilache Differential Revision: https://reviews.llvm.org/D96775
This commit is contained in:
parent
df45c18135
commit
ce8f10d6cb
@ -26,6 +26,7 @@
|
||||
#include "mlir/Pass/Pass.h"
|
||||
#include "mlir/Pass/PassManager.h"
|
||||
#include "mlir/Target/LLVMIR.h"
|
||||
#include "mlir/Target/LLVMIR/Export.h"
|
||||
#include "mlir/Transforms/Passes.h"
|
||||
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "mlir/Pass/Pass.h"
|
||||
#include "mlir/Pass/PassManager.h"
|
||||
#include "mlir/Target/LLVMIR.h"
|
||||
#include "mlir/Target/LLVMIR/Export.h"
|
||||
#include "mlir/Transforms/Passes.h"
|
||||
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
|
@ -19,7 +19,6 @@
|
||||
|
||||
// Forward-declare LLVM classes.
|
||||
namespace llvm {
|
||||
class LLVMContext;
|
||||
class Module;
|
||||
} // namespace llvm
|
||||
|
||||
@ -28,15 +27,6 @@ namespace mlir {
|
||||
class DialectRegistry;
|
||||
class OwningModuleRef;
|
||||
class MLIRContext;
|
||||
class Operation;
|
||||
|
||||
/// Convert the given MLIR module into LLVM IR. The LLVM context is extracted
|
||||
/// 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<llvm::Module>
|
||||
translateModuleToLLVMIR(Operation *op, llvm::LLVMContext &llvmContext,
|
||||
StringRef name = "LLVMDialectModule");
|
||||
|
||||
/// Convert the given LLVM module into MLIR's LLVM dialect. The LLVM context is
|
||||
/// extracted from the registered LLVM IR dialect. In case of error, report it
|
||||
|
32
mlir/include/mlir/Target/LLVMIR/Export.h
Normal file
32
mlir/include/mlir/Target/LLVMIR/Export.h
Normal file
@ -0,0 +1,32 @@
|
||||
//===- Export.h - MLIR to LLVM IR translation entry point -------*- 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef MLIR_TARGET_LLVMIR_EXPORT_H
|
||||
#define MLIR_TARGET_LLVMIR_EXPORT_H
|
||||
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include <memory>
|
||||
|
||||
namespace llvm {
|
||||
class LLVMContext;
|
||||
class Module;
|
||||
} // namespace llvm
|
||||
|
||||
namespace mlir {
|
||||
class Operation;
|
||||
|
||||
/// 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.
|
||||
std::unique_ptr<llvm::Module>
|
||||
translateModuleToLLVMIR(Operation *module, llvm::LLVMContext &llvmContext,
|
||||
llvm::StringRef name = "LLVMDialectModule");
|
||||
} // namespace mlir
|
||||
|
||||
#endif // MLIR_TARGET_LLVMIR_EXPORT_H
|
@ -14,27 +14,26 @@
|
||||
#ifndef MLIR_TARGET_LLVMIR_MODULETRANSLATION_H
|
||||
#define MLIR_TARGET_LLVMIR_MODULETRANSLATION_H
|
||||
|
||||
#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
|
||||
#include "mlir/Dialect/LLVMIR/Transforms/LegalizeForExport.h"
|
||||
#include "mlir/IR/Block.h"
|
||||
#include "mlir/IR/BuiltinOps.h"
|
||||
#include "mlir/IR/Operation.h"
|
||||
#include "mlir/IR/Value.h"
|
||||
#include "mlir/Target/LLVMIR/Export.h"
|
||||
#include "mlir/Target/LLVMIR/LLVMTranslationInterface.h"
|
||||
#include "mlir/Target/LLVMIR/TypeTranslation.h"
|
||||
|
||||
#include "llvm/ADT/SetVector.h"
|
||||
#include "llvm/Frontend/OpenMP/OMPIRBuilder.h"
|
||||
#include "llvm/IR/BasicBlock.h"
|
||||
#include "llvm/IR/Function.h"
|
||||
#include "llvm/IR/IRBuilder.h"
|
||||
#include "llvm/IR/MatrixBuilder.h"
|
||||
#include "llvm/IR/Value.h"
|
||||
|
||||
namespace llvm {
|
||||
class BasicBlock;
|
||||
class IRBuilderBase;
|
||||
class Function;
|
||||
class Value;
|
||||
} // namespace llvm
|
||||
|
||||
namespace mlir {
|
||||
class Attribute;
|
||||
class Block;
|
||||
class Location;
|
||||
class ModuleOp;
|
||||
class Operation;
|
||||
|
||||
namespace LLVM {
|
||||
|
||||
@ -50,35 +49,10 @@ class LLVMFuncOp;
|
||||
/// mappings in one class since the conversion of control flow operations
|
||||
/// needs to look up block and function mappings.
|
||||
class ModuleTranslation {
|
||||
friend std::unique_ptr<llvm::Module>
|
||||
mlir::translateModuleToLLVMIR(Operation *, llvm::LLVMContext &, StringRef);
|
||||
|
||||
public:
|
||||
template <typename T = ModuleTranslation>
|
||||
static std::unique_ptr<llvm::Module>
|
||||
translateModule(Operation *m, llvm::LLVMContext &llvmContext,
|
||||
StringRef name = "LLVMDialectModule") {
|
||||
if (!satisfiesLLVMModule(m))
|
||||
return nullptr;
|
||||
if (failed(checkSupportedModuleOps(m)))
|
||||
return nullptr;
|
||||
std::unique_ptr<llvm::Module> llvmModule =
|
||||
prepareLLVMModule(m, llvmContext, name);
|
||||
|
||||
LLVM::ensureDistinctSuccessors(m);
|
||||
|
||||
T translator(m, std::move(llvmModule));
|
||||
if (failed(translator.convertFunctionSignatures()))
|
||||
return nullptr;
|
||||
if (failed(translator.convertGlobals()))
|
||||
return nullptr;
|
||||
if (failed(translator.convertFunctions()))
|
||||
return nullptr;
|
||||
|
||||
return std::move(translator.llvmModule);
|
||||
}
|
||||
|
||||
/// A helper method to get the single Block in an operation honoring LLVM's
|
||||
/// module requirements.
|
||||
static Block &getModuleBody(Operation *m) { return m->getRegion(0).front(); }
|
||||
|
||||
/// Stores the mapping between a function name and its LLVM IR representation.
|
||||
void mapFunction(StringRef name, llvm::Function *func) {
|
||||
auto result = functionMapping.try_emplace(name, func);
|
||||
@ -175,31 +149,19 @@ public:
|
||||
/// PHI nodes are constructed for block arguments but are _not_ connected to
|
||||
/// the predecessors that may not exist yet.
|
||||
LogicalResult convertBlock(Block &bb, bool ignoreArguments,
|
||||
llvm::IRBuilder<> &builder);
|
||||
llvm::IRBuilderBase &builder);
|
||||
|
||||
/// Gets the named metadata in the LLVM IR module being constructed, creating
|
||||
/// it if it does not exist.
|
||||
llvm::NamedMDNode *getOrInsertNamedModuleMetadata(StringRef name);
|
||||
|
||||
protected:
|
||||
/// Translate the given MLIR module expressed in MLIR LLVM IR dialect into an
|
||||
/// LLVM IR module. The MLIR LLVM IR dialect holds a pointer to an
|
||||
/// LLVMContext, the LLVM IR module will be created in that context.
|
||||
private:
|
||||
ModuleTranslation(Operation *module,
|
||||
std::unique_ptr<llvm::Module> llvmModule);
|
||||
virtual ~ModuleTranslation();
|
||||
|
||||
virtual LogicalResult convertOperation(Operation &op,
|
||||
llvm::IRBuilder<> &builder);
|
||||
|
||||
static std::unique_ptr<llvm::Module>
|
||||
prepareLLVMModule(Operation *m, llvm::LLVMContext &llvmContext,
|
||||
StringRef name);
|
||||
|
||||
private:
|
||||
/// Check whether the module contains only supported ops directly in its body.
|
||||
static LogicalResult checkSupportedModuleOps(Operation *m);
|
||||
~ModuleTranslation();
|
||||
|
||||
/// Converts individual components.
|
||||
LogicalResult convertOperation(Operation &op, llvm::IRBuilderBase &builder);
|
||||
LogicalResult convertFunctionSignatures();
|
||||
LogicalResult convertFunctions();
|
||||
LogicalResult convertGlobals();
|
||||
@ -217,11 +179,6 @@ private:
|
||||
/// Builder for LLVM IR generation of OpenMP constructs.
|
||||
std::unique_ptr<llvm::OpenMPIRBuilder> ompBuilder;
|
||||
|
||||
/// Precomputed pointer to OpenMP dialect. Note this can be nullptr if the
|
||||
/// OpenMP dialect hasn't been loaded (it is always loaded if there are OpenMP
|
||||
/// operations in the module though).
|
||||
const Dialect *ompDialect;
|
||||
|
||||
/// Mappings between llvm.mlir.global definitions and corresponding globals.
|
||||
DenseMap<Operation *, llvm::GlobalValue *> globalsMapping;
|
||||
|
||||
|
@ -14,7 +14,7 @@
|
||||
#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
|
||||
#include "mlir/IR/BuiltinOps.h"
|
||||
#include "mlir/Support/FileUtilities.h"
|
||||
#include "mlir/Target/LLVMIR.h"
|
||||
#include "mlir/Target/LLVMIR/Export.h"
|
||||
|
||||
#include "llvm/ExecutionEngine/JITEventListener.h"
|
||||
#include "llvm/ExecutionEngine/ObjectCache.h"
|
||||
|
@ -35,18 +35,6 @@
|
||||
|
||||
using namespace mlir;
|
||||
|
||||
std::unique_ptr<llvm::Module>
|
||||
mlir::translateModuleToLLVMIR(Operation *op, llvm::LLVMContext &llvmContext,
|
||||
StringRef name) {
|
||||
auto llvmModule =
|
||||
LLVM::ModuleTranslation::translateModule<>(op, llvmContext, name);
|
||||
if (!llvmModule)
|
||||
emitError(op->getLoc(), "Fail to convert MLIR to LLVM IR");
|
||||
else if (verifyModule(*llvmModule))
|
||||
emitError(op->getLoc(), "LLVM IR fails to verify");
|
||||
return llvmModule;
|
||||
}
|
||||
|
||||
void mlir::registerLLVMDialectTranslation(DialectRegistry ®istry) {
|
||||
registry.insert<LLVM::LLVMDialect>();
|
||||
registry.addDialectInterface<LLVM::LLVMDialect,
|
||||
@ -71,8 +59,7 @@ void registerToLLVMIRTranslation() {
|
||||
"mlir-to-llvmir",
|
||||
[](ModuleOp module, raw_ostream &output) {
|
||||
llvm::LLVMContext llvmContext;
|
||||
auto llvmModule = LLVM::ModuleTranslation::translateModule<>(
|
||||
module, llvmContext, "LLVMDialectModule");
|
||||
auto llvmModule = translateModuleToLLVMIR(module, llvmContext);
|
||||
if (!llvmModule)
|
||||
return failure();
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "llvm/IR/IRBuilder.h"
|
||||
#include "llvm/IR/InlineAsm.h"
|
||||
#include "llvm/IR/MDBuilder.h"
|
||||
#include "llvm/IR/MatrixBuilder.h"
|
||||
#include "llvm/IR/Operator.h"
|
||||
|
||||
using namespace mlir;
|
||||
|
@ -58,14 +58,9 @@ static void convertOmpOpRegions(Region ®ion, StringRef blockName,
|
||||
sourceTerminator->setSuccessor(0, llvmBB);
|
||||
}
|
||||
|
||||
llvm::IRBuilder<>::InsertPointGuard guard(builder);
|
||||
if (failed(moduleTranslation.convertBlock(
|
||||
*bb, bb->isEntryBlock(),
|
||||
// TODO: this downcast should be removed after all of
|
||||
// ModuleTranslation migrated to using IRBuilderBase &; the cast is
|
||||
// safe in practice because the builder always comes from
|
||||
// ModuleTranslation itself that only uses this subclass.
|
||||
static_cast<llvm::IRBuilder<> &>(builder)))) {
|
||||
llvm::IRBuilderBase::InsertPointGuard guard(builder);
|
||||
if (failed(
|
||||
moduleTranslation.convertBlock(*bb, bb->isEntryBlock(), builder))) {
|
||||
bodyGenStatus = failure();
|
||||
return;
|
||||
}
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
#include "DebugTranslation.h"
|
||||
#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
|
||||
#include "mlir/Dialect/LLVMIR/Transforms/LegalizeForExport.h"
|
||||
#include "mlir/Dialect/OpenMP/OpenMPDialect.h"
|
||||
#include "mlir/IR/Attributes.h"
|
||||
#include "mlir/IR/BuiltinOps.h"
|
||||
@ -37,6 +38,7 @@
|
||||
#include "llvm/IR/LLVMContext.h"
|
||||
#include "llvm/IR/MDBuilder.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
#include "llvm/IR/Verifier.h"
|
||||
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
|
||||
#include "llvm/Transforms/Utils/Cloning.h"
|
||||
|
||||
@ -192,7 +194,6 @@ ModuleTranslation::ModuleTranslation(Operation *module,
|
||||
: mlirModule(module), llvmModule(std::move(llvmModule)),
|
||||
debugTranslation(
|
||||
std::make_unique<DebugTranslation>(module, *this->llvmModule)),
|
||||
ompDialect(module->getContext()->getLoadedDialect("omp")),
|
||||
typeTranslator(this->llvmModule->getContext()),
|
||||
iface(module->getContext()) {
|
||||
assert(satisfiesLLVMModule(mlirModule) &&
|
||||
@ -301,8 +302,9 @@ llvm::Value *mlir::LLVM::detail::createIntrinsicCall(
|
||||
|
||||
/// Given a single MLIR operation, create the corresponding LLVM IR operation
|
||||
/// using the `builder`.
|
||||
LogicalResult ModuleTranslation::convertOperation(Operation &opInst,
|
||||
llvm::IRBuilder<> &builder) {
|
||||
LogicalResult
|
||||
ModuleTranslation::convertOperation(Operation &opInst,
|
||||
llvm::IRBuilderBase &builder) {
|
||||
if (failed(iface.convertOperation(&opInst, builder, *this)))
|
||||
return opInst.emitError("unsupported or non-LLVM operation: ")
|
||||
<< opInst.getName();
|
||||
@ -318,7 +320,7 @@ LogicalResult ModuleTranslation::convertOperation(Operation &opInst,
|
||||
/// instructions at the end of the block and leaves `builder` in a state
|
||||
/// suitable for further insertion into the end of the block.
|
||||
LogicalResult ModuleTranslation::convertBlock(Block &bb, bool ignoreArguments,
|
||||
llvm::IRBuilder<> &builder) {
|
||||
llvm::IRBuilderBase &builder) {
|
||||
builder.SetInsertPoint(lookupBlock(&bb));
|
||||
auto *subprogram = builder.GetInsertBlock()->getParent()->getSubprogram();
|
||||
|
||||
@ -356,6 +358,12 @@ LogicalResult ModuleTranslation::convertBlock(Block &bb, bool ignoreArguments,
|
||||
return success();
|
||||
}
|
||||
|
||||
/// A helper method to get the single Block in an operation honoring LLVM's
|
||||
/// module requirements.
|
||||
static Block &getModuleBody(Operation *module) {
|
||||
return module->getRegion(0).front();
|
||||
}
|
||||
|
||||
/// Create named global variables that correspond to llvm.mlir.global
|
||||
/// definitions.
|
||||
LogicalResult ModuleTranslation::convertGlobals() {
|
||||
@ -582,7 +590,8 @@ LogicalResult ModuleTranslation::convertDialectAttributes(Operation *op) {
|
||||
return success();
|
||||
}
|
||||
|
||||
LogicalResult ModuleTranslation::checkSupportedModuleOps(Operation *m) {
|
||||
/// Check whether the module contains only supported ops directly in its body.
|
||||
static LogicalResult checkSupportedModuleOps(Operation *m) {
|
||||
for (Operation &o : getModuleBody(m).getOperations())
|
||||
if (!isa<LLVM::LLVMFuncOp, LLVM::GlobalOp>(&o) &&
|
||||
!o.hasTrait<OpTrait::IsTerminator>())
|
||||
@ -648,8 +657,9 @@ ModuleTranslation::getOrInsertNamedModuleMetadata(StringRef name) {
|
||||
return llvmModule->getOrInsertNamedMetadata(name);
|
||||
}
|
||||
|
||||
std::unique_ptr<llvm::Module> ModuleTranslation::prepareLLVMModule(
|
||||
Operation *m, llvm::LLVMContext &llvmContext, StringRef name) {
|
||||
static std::unique_ptr<llvm::Module>
|
||||
prepareLLVMModule(Operation *m, llvm::LLVMContext &llvmContext,
|
||||
StringRef name) {
|
||||
m->getContext()->getOrLoadDialect<LLVM::LLVMDialect>();
|
||||
auto llvmModule = std::make_unique<llvm::Module>(name, llvmContext);
|
||||
if (auto dataLayoutAttr =
|
||||
@ -669,3 +679,28 @@ std::unique_ptr<llvm::Module> ModuleTranslation::prepareLLVMModule(
|
||||
|
||||
return llvmModule;
|
||||
}
|
||||
|
||||
std::unique_ptr<llvm::Module>
|
||||
mlir::translateModuleToLLVMIR(Operation *module, llvm::LLVMContext &llvmContext,
|
||||
StringRef name) {
|
||||
if (!satisfiesLLVMModule(module))
|
||||
return nullptr;
|
||||
if (failed(checkSupportedModuleOps(module)))
|
||||
return nullptr;
|
||||
std::unique_ptr<llvm::Module> llvmModule =
|
||||
prepareLLVMModule(module, llvmContext, name);
|
||||
|
||||
LLVM::ensureDistinctSuccessors(module);
|
||||
|
||||
ModuleTranslation translator(module, std::move(llvmModule));
|
||||
if (failed(translator.convertFunctionSignatures()))
|
||||
return nullptr;
|
||||
if (failed(translator.convertGlobals()))
|
||||
return nullptr;
|
||||
if (failed(translator.convertFunctions()))
|
||||
return nullptr;
|
||||
if (llvm::verifyModule(*translator.llvmModule, &llvm::errs()))
|
||||
return nullptr;
|
||||
|
||||
return std::move(translator.llvmModule);
|
||||
}
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "mlir/Pass/PassManager.h"
|
||||
#include "mlir/Target/LLVMIR.h"
|
||||
#include "mlir/Target/LLVMIR/Dialect/NVVM/NVVMToLLVMIRTranslation.h"
|
||||
#include "mlir/Target/LLVMIR/Export.h"
|
||||
#include "llvm/Support/TargetSelect.h"
|
||||
|
||||
using namespace mlir;
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "mlir/Pass/PassManager.h"
|
||||
#include "mlir/Target/LLVMIR.h"
|
||||
#include "mlir/Target/LLVMIR/Dialect/ROCDL/ROCDLToLLVMIRTranslation.h"
|
||||
#include "mlir/Target/LLVMIR/Export.h"
|
||||
#include "llvm/Support/TargetSelect.h"
|
||||
|
||||
using namespace mlir;
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include "mlir/Pass/PassManager.h"
|
||||
#include "mlir/Target/LLVMIR.h"
|
||||
#include "mlir/Target/LLVMIR/Dialect/NVVM/NVVMToLLVMIRTranslation.h"
|
||||
#include "mlir/Target/LLVMIR/Export.h"
|
||||
#include "mlir/Transforms/DialectConversion.h"
|
||||
#include "mlir/Transforms/Passes.h"
|
||||
|
||||
|
@ -32,7 +32,7 @@
|
||||
#include "mlir/Support/FileUtilities.h"
|
||||
#include "mlir/Target/LLVMIR.h"
|
||||
#include "mlir/Target/LLVMIR/Dialect/ROCDL/ROCDLToLLVMIRTranslation.h"
|
||||
#include "mlir/Target/ROCDLIR.h"
|
||||
#include "mlir/Target/LLVMIR/Export.h"
|
||||
#include "mlir/Transforms/DialectConversion.h"
|
||||
#include "mlir/Transforms/Passes.h"
|
||||
#include "llvm/Support/ErrorOr.h"
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "mlir/Pass/Pass.h"
|
||||
#include "mlir/Pass/PassManager.h"
|
||||
#include "mlir/Target/LLVMIR.h"
|
||||
#include "mlir/Target/LLVMIR/Export.h"
|
||||
|
||||
#include "llvm/IR/LLVMContext.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
|
Loading…
Reference in New Issue
Block a user