From 3af1d49fd6f744b29165fc75f2f24c9a3e9d43b1 Mon Sep 17 00:00:00 2001 From: Robert Konicar Date: Fri, 7 Feb 2025 15:22:38 +0100 Subject: [PATCH] [CIR] Add option to emit MLIR in LLVM dialect. --- .../clang/CIR/FrontendAction/CIRGenAction.h | 8 +++++ clang/include/clang/CIR/LowerToLLVM.h | 10 +++++-- clang/include/clang/CIR/LowerToMLIR.h | 6 ++++ clang/include/clang/Driver/Options.td | 2 ++ .../include/clang/Frontend/FrontendOptions.h | 3 ++ clang/lib/CIR/FrontendAction/CIRGenAction.cpp | 29 +++++++++++++++---- .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 24 +++++++++++---- .../Lowering/ThroughMLIR/LowerCIRToMLIR.cpp | 25 ++++++++++++---- clang/lib/Frontend/CompilerInvocation.cpp | 2 ++ .../ExecuteCompilerInvocation.cpp | 2 ++ 10 files changed, 93 insertions(+), 18 deletions(-) diff --git a/clang/include/clang/CIR/FrontendAction/CIRGenAction.h b/clang/include/clang/CIR/FrontendAction/CIRGenAction.h index 6618fbc54261..92f40231ac19 100644 --- a/clang/include/clang/CIR/FrontendAction/CIRGenAction.h +++ b/clang/include/clang/CIR/FrontendAction/CIRGenAction.h @@ -37,6 +37,7 @@ class CIRGenAction : public clang::ASTFrontendAction { EmitLLVM, EmitBC, EmitMLIR, + EmitMLIRLLVM, EmitObj, None }; @@ -101,6 +102,13 @@ class EmitMLIRAction : public CIRGenAction { EmitMLIRAction(mlir::MLIRContext *mlirCtx = nullptr); }; +class EmitMLIRLLVMAction : public CIRGenAction { + virtual void anchor(); + +public: + EmitMLIRLLVMAction(mlir::MLIRContext *mlirCtx = nullptr); +}; + class EmitLLVMAction : public CIRGenAction { virtual void anchor(); diff --git a/clang/include/clang/CIR/LowerToLLVM.h b/clang/include/clang/CIR/LowerToLLVM.h index 2992163196e7..dfa4e59b5e1c 100644 --- a/clang/include/clang/CIR/LowerToLLVM.h +++ b/clang/include/clang/CIR/LowerToLLVM.h @@ -29,13 +29,19 @@ class ModuleOp; namespace cir { namespace direct { +mlir::ModuleOp lowerDirectlyFromCIRToLLVMDialect(mlir::ModuleOp theModule, + bool disableVerifier = false, + bool disableCCLowering = false, + bool disableDebugInfo = false); + +// Lower directly from pristine CIR to LLVMIR. std::unique_ptr lowerDirectlyFromCIRToLLVMIR( mlir::ModuleOp theModule, llvm::LLVMContext &llvmCtx, bool disableVerifier = false, bool disableCCLowering = false, bool disableDebugInfo = false); -} -// Lower directly from pristine CIR to LLVMIR. +} // namespace direct + std::unique_ptr lowerFromCIRToMLIRToLLVMIR(mlir::ModuleOp theModule, std::unique_ptr mlirCtx, diff --git a/clang/include/clang/CIR/LowerToMLIR.h b/clang/include/clang/CIR/LowerToMLIR.h index 567deb7abc7d..1ddced958cee 100644 --- a/clang/include/clang/CIR/LowerToMLIR.h +++ b/clang/include/clang/CIR/LowerToMLIR.h @@ -12,10 +12,16 @@ #ifndef CLANG_CIR_LOWERTOMLIR_H #define CLANG_CIR_LOWERTOMLIR_H +#include "mlir/Transforms/DialectConversion.h" + namespace cir { void populateCIRLoopToSCFConversionPatterns(mlir::RewritePatternSet &patterns, mlir::TypeConverter &converter); + +mlir::ModuleOp +lowerFromCIRToMLIRToLLVMDialect(mlir::ModuleOp theModule, + mlir::MLIRContext *mlirCtx = nullptr); } // namespace cir #endif // CLANG_CIR_LOWERTOMLIR_H_ diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 3bd0fce9ab29..e59eb377b1af 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -3121,6 +3121,8 @@ def emit_cir_flat : Flag<["-"], "emit-cir-flat">, Visibility<[ClangOption, CC1Op Group, HelpText<"Similar to -emit-cir but also lowers structured CFG into basic blocks.">; def emit_mlir : Flag<["-"], "emit-mlir">, Visibility<[CC1Option]>, Group, HelpText<"Build ASTs and then lower through ClangIR to MLIR, emit the .milr file">; +def emit_mlir_llvm : Flag<["-"], "emit-mlir-llvm">, Visibility<[CC1Option]>, Group, + HelpText<"Build ASTs and then lower through ClangIR to MLIR LLVM Dialect, emit the .mlir file">; /// ClangIR-specific options - END def flto : Flag<["-"], "flto">, diff --git a/clang/include/clang/Frontend/FrontendOptions.h b/clang/include/clang/Frontend/FrontendOptions.h index c20744b49136..9eb60621dceb 100644 --- a/clang/include/clang/Frontend/FrontendOptions.h +++ b/clang/include/clang/Frontend/FrontendOptions.h @@ -77,6 +77,9 @@ enum ActionKind { /// Emit a .mlir file EmitMLIR, + /// Emit an .mlir file with LLVM dialect + EmitMLIRLLVM, + /// Emit a .ll file. EmitLLVM, diff --git a/clang/lib/CIR/FrontendAction/CIRGenAction.cpp b/clang/lib/CIR/FrontendAction/CIRGenAction.cpp index 5cb81e89388f..1cc808f02ed9 100644 --- a/clang/lib/CIR/FrontendAction/CIRGenAction.cpp +++ b/clang/lib/CIR/FrontendAction/CIRGenAction.cpp @@ -26,6 +26,7 @@ #include "clang/CIR/CIRToCIRPasses.h" #include "clang/CIR/Dialect/IR/CIRDialect.h" #include "clang/CIR/LowerToLLVM.h" +#include "clang/CIR/LowerToMLIR.h" #include "clang/CIR/Passes.h" #include "clang/CodeGen/BackendUtil.h" #include "clang/CodeGen/ModuleBuilder.h" @@ -260,6 +261,14 @@ class CIRGenConsumer : public clang::ASTConsumer { } } + auto printMlirModule = [&](mlir::ModuleOp root) { + assert(outputStream && "Why are we here without an output stream?"); + // FIXME: we cannot roundtrip prettyForm=true right now. + mlir::OpPrintingFlags flags; + flags.enableDebugInfo(/*enable=*/true, /*prettyForm=*/false); + root->print(*outputStream, flags); + }; + switch (action) { case CIRGenAction::OutputType::EmitCIR: case CIRGenAction::OutputType::EmitCIRFlat: @@ -274,11 +283,15 @@ class CIRGenConsumer : public clang::ASTConsumer { break; case CIRGenAction::OutputType::EmitMLIR: { auto loweredMlirModule = lowerFromCIRToMLIR(mlirMod, mlirCtx.get()); - assert(outputStream && "Why are we here without an output stream?"); - // FIXME: we cannot roundtrip prettyForm=true right now. - mlir::OpPrintingFlags flags; - flags.enableDebugInfo(/*enable=*/true, /*prettyForm=*/false); - loweredMlirModule->print(*outputStream, flags); + printMlirModule(loweredMlirModule); + break; + } + case CIRGenAction::OutputType::EmitMLIRLLVM: { + auto loweredMlirModule = + feOptions.ClangIRDirectLowering + ? direct::lowerDirectlyFromCIRToLLVMDialect(mlirMod) + : lowerFromCIRToMLIRToLLVMDialect(mlirMod); + printMlirModule(loweredMlirModule); break; } case CIRGenAction::OutputType::EmitLLVM: @@ -362,6 +375,8 @@ getOutputStream(CompilerInstance &ci, StringRef inFile, return ci.createDefaultOutputFile(false, inFile, "cir"); case CIRGenAction::OutputType::EmitMLIR: return ci.createDefaultOutputFile(false, inFile, "mlir"); + case CIRGenAction::OutputType::EmitMLIRLLVM: + return ci.createDefaultOutputFile(false, inFile, "mlir"); case CIRGenAction::OutputType::EmitLLVM: return ci.createDefaultOutputFile(false, inFile, "ll"); case CIRGenAction::OutputType::EmitBC: @@ -472,6 +487,10 @@ void EmitMLIRAction::anchor() {} EmitMLIRAction::EmitMLIRAction(mlir::MLIRContext *_MLIRContext) : CIRGenAction(OutputType::EmitMLIR, _MLIRContext) {} +void EmitMLIRLLVMAction::anchor() {} +EmitMLIRLLVMAction::EmitMLIRLLVMAction(mlir::MLIRContext *_MLIRContext) + : CIRGenAction(OutputType::EmitMLIRLLVM, _MLIRContext) {} + void EmitLLVMAction::anchor() {} EmitLLVMAction::EmitLLVMAction(mlir::MLIRContext *_MLIRContext) : CIRGenAction(OutputType::EmitLLVM, _MLIRContext) {} diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index 0331122f35d2..b3aad00aadd5 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -4689,11 +4689,11 @@ void populateCIRToLLVMPasses(mlir::OpPassManager &pm, bool useCCLowering) { extern void registerCIRDialectTranslation(mlir::MLIRContext &context); -std::unique_ptr -lowerDirectlyFromCIRToLLVMIR(mlir::ModuleOp theModule, LLVMContext &llvmCtx, - bool disableVerifier, bool disableCCLowering, - bool disableDebugInfo) { - llvm::TimeTraceScope scope("lower from CIR to LLVM directly"); +mlir::ModuleOp lowerDirectlyFromCIRToLLVMDialect(mlir::ModuleOp theModule, + bool disableVerifier, + bool disableCCLowering, + bool disableDebugInfo) { + llvm::TimeTraceScope scope("lower from CIR to LLVM Dialect"); mlir::MLIRContext *mlirCtx = theModule.getContext(); mlir::PassManager pm(mlirCtx); @@ -4722,6 +4722,20 @@ lowerDirectlyFromCIRToLLVMIR(mlir::ModuleOp theModule, LLVMContext &llvmCtx, if (theModule.verify().failed()) report_fatal_error("Verification of the final LLVMIR dialect failed!"); + return theModule; +} + +std::unique_ptr +lowerDirectlyFromCIRToLLVMIR(mlir::ModuleOp theModule, LLVMContext &llvmCtx, + bool disableVerifier, bool disableCCLowering, + bool disableDebugInfo) { + llvm::TimeTraceScope scope("lower from CIR to LLVM directly"); + + lowerDirectlyFromCIRToLLVMDialect(theModule, disableVerifier, + disableCCLowering, disableDebugInfo); + + mlir::MLIRContext *mlirCtx = theModule.getContext(); + mlir::registerBuiltinDialectTranslation(*mlirCtx); mlir::registerLLVMDialectTranslation(*mlirCtx); mlir::registerOpenMPDialectTranslation(*mlirCtx); diff --git a/clang/lib/CIR/Lowering/ThroughMLIR/LowerCIRToMLIR.cpp b/clang/lib/CIR/Lowering/ThroughMLIR/LowerCIRToMLIR.cpp index 8a3e6227b072..75c905299bdb 100644 --- a/clang/lib/CIR/Lowering/ThroughMLIR/LowerCIRToMLIR.cpp +++ b/clang/lib/CIR/Lowering/ThroughMLIR/LowerCIRToMLIR.cpp @@ -47,6 +47,7 @@ #include "mlir/Transforms/DialectConversion.h" #include "clang/CIR/Dialect/IR/CIRDialect.h" #include "clang/CIR/Dialect/IR/CIRTypes.h" +#include "clang/CIR/LowerToLLVM.h" #include "clang/CIR/LowerToMLIR.h" #include "clang/CIR/LoweringHelpers.h" #include "clang/CIR/Passes.h" @@ -1458,13 +1459,14 @@ void ConvertCIRToMLIRPass::runOnOperation() { signalPassFailure(); } -std::unique_ptr -lowerFromCIRToMLIRToLLVMIR(mlir::ModuleOp theModule, - std::unique_ptr mlirCtx, - LLVMContext &llvmCtx) { - llvm::TimeTraceScope scope("Lower from CIR to MLIR To LLVM"); +mlir::ModuleOp lowerFromCIRToMLIRToLLVMDialect(mlir::ModuleOp theModule, + mlir::MLIRContext *mlirCtx) { + llvm::TimeTraceScope scope("Lower from CIR to MLIR To LLVM Dialect"); + if (!mlirCtx) { + mlirCtx = theModule.getContext(); + } - mlir::PassManager pm(mlirCtx.get()); + mlir::PassManager pm(mlirCtx); pm.addPass(createConvertCIRToMLIRPass()); pm.addPass(createConvertMLIRToLLVMPass()); @@ -1478,6 +1480,17 @@ lowerFromCIRToMLIRToLLVMIR(mlir::ModuleOp theModule, if (theModule.verify().failed()) report_fatal_error("Verification of the final LLVMIR dialect failed!"); + return theModule; +} + +std::unique_ptr +lowerFromCIRToMLIRToLLVMIR(mlir::ModuleOp theModule, + std::unique_ptr mlirCtx, + LLVMContext &llvmCtx) { + llvm::TimeTraceScope scope("Lower from CIR to MLIR To LLVM"); + + lowerFromCIRToMLIRToLLVMDialect(theModule, mlirCtx.get()); + mlir::registerBuiltinDialectTranslation(*mlirCtx); mlir::registerLLVMDialectTranslation(*mlirCtx); mlir::registerOpenMPDialectTranslation(*mlirCtx); diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index a505b5412448..b044eafe5ab9 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -2738,6 +2738,7 @@ static const auto &getFrontendActionTable() { {frontend::EmitCIRFlat, OPT_emit_cir_flat}, {frontend::EmitCIROnly, OPT_emit_cir_only}, {frontend::EmitMLIR, OPT_emit_mlir}, + {frontend::EmitMLIRLLVM, OPT_emit_mlir_llvm}, {frontend::EmitHTML, OPT_emit_html}, {frontend::EmitLLVM, OPT_emit_llvm}, {frontend::EmitLLVMOnly, OPT_emit_llvm_only}, @@ -4669,6 +4670,7 @@ static bool isStrictlyPreprocessorAction(frontend::ActionKind Action) { case frontend::EmitCIRFlat: case frontend::EmitCIROnly: case frontend::EmitMLIR: + case frontend::EmitMLIRLLVM: case frontend::EmitHTML: case frontend::EmitLLVM: case frontend::EmitLLVMOnly: diff --git a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp index 4a54d90a6591..7524a87b09fd 100644 --- a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp +++ b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp @@ -99,6 +99,8 @@ CreateFrontendBaseAction(CompilerInstance &CI) { return std::make_unique(); case EmitMLIR: return std::make_unique(); + case EmitMLIRLLVM: + return std::make_unique(); #else case EmitCIR: case EmitCIRFlat: