From fd0c8391e70c147491bc9f0bf76a05d4e8c69207 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 9 Oct 2024 14:46:27 +0200 Subject: [PATCH] wip: adding --emit-spirv-mlir path --- clang/include/clang/CIR/LowerToSPIRV.h | 32 +++++++++++++++++++ clang/include/clang/CIR/Passes.h | 4 +++ .../clang/CIRFrontendAction/CIRGenAction.h | 8 +++++ clang/include/clang/Driver/Options.td | 2 ++ .../include/clang/Frontend/FrontendOptions.h | 3 ++ clang/lib/CIR/FrontendAction/CIRGenAction.cpp | 20 ++++++++++++ .../CIR/Lowering/ThroughMLIR/CMakeLists.txt | 1 + .../Lowering/ThroughMLIR/LowerMLIRToSPIRV.cpp | 25 +++++++++++++++ clang/lib/Frontend/CompilerInvocation.cpp | 1 + .../ExecuteCompilerInvocation.cpp | 3 +- 10 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 clang/include/clang/CIR/LowerToSPIRV.h create mode 100644 clang/lib/CIR/Lowering/ThroughMLIR/LowerMLIRToSPIRV.cpp diff --git a/clang/include/clang/CIR/LowerToSPIRV.h b/clang/include/clang/CIR/LowerToSPIRV.h new file mode 100644 index 000000000000..62b56a0edf8a --- /dev/null +++ b/clang/include/clang/CIR/LowerToSPIRV.h @@ -0,0 +1,32 @@ +//====- LowerToSPIRV.h- Lowering from CIR to LLVM -------------------------===// +// +// 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 file declares an interface for converting MLIR modules to SPIR-V +// +//===----------------------------------------------------------------------===// +#ifndef CLANG_CIR_LOWERTOSPIRV_H +#define CLANG_CIR_LOWERTOSPIRV_H + +#include "mlir/Dialect/SPIRV/IR/SPIRVOps.h" + +#include + +namespace llvm { +class LLVMContext; +class Module; +} // namespace llvm + +namespace mlir { +class MLIRContext; +class ModuleOp; + +spirv::ModuleOp lowerFromMLIRToSPIRV(mlir::ModuleOp theModule, + mlir::MLIRContext *mlirCtx); +} // namespace mlir + +#endif // CLANG_CIR_LOWERTOSPIRV_H diff --git a/clang/include/clang/CIR/Passes.h b/clang/include/clang/CIR/Passes.h index 6b1d2fdc75c4..d7359da5d105 100644 --- a/clang/include/clang/CIR/Passes.h +++ b/clang/include/clang/CIR/Passes.h @@ -22,9 +22,13 @@ namespace cir { /// `Std`, to the LLVM dialect for codegen. std::unique_ptr createConvertMLIRToLLVMPass(); +/// Create a pass for lowering from MLIR builtin dialects to the SPIRV dialect for codegen. +std::unique_ptr createConvertMLIRToSPIRVPass(); + /// Create a pass that fully lowers CIR to the MLIR in-tree dialects. std::unique_ptr createConvertCIRToMLIRPass(); + namespace direct { /// Create a pass that fully lowers CIR to the LLVMIR dialect. std::unique_ptr createConvertCIRToLLVMPass(); diff --git a/clang/include/clang/CIRFrontendAction/CIRGenAction.h b/clang/include/clang/CIRFrontendAction/CIRGenAction.h index 13c2a4381573..850ae5bf86fc 100644 --- a/clang/include/clang/CIRFrontendAction/CIRGenAction.h +++ b/clang/include/clang/CIRFrontendAction/CIRGenAction.h @@ -34,6 +34,7 @@ class CIRGenAction : public clang::ASTFrontendAction { EmitAssembly, EmitCIR, EmitCIRFlat, + EmitSPIRV, EmitLLVM, EmitBC, EmitMLIR, @@ -101,6 +102,13 @@ class EmitMLIRAction : public CIRGenAction { EmitMLIRAction(mlir::MLIRContext *mlirCtx = nullptr); }; +class EmitSPIRVAction : public CIRGenAction { + virtual void anchor(); + +public: + EmitSPIRVAction(mlir::MLIRContext *mlirCtx = nullptr); +}; + class EmitLLVMAction : public CIRGenAction { virtual void anchor(); diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index b423c42eda90..a57abd278090 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -3055,6 +3055,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_spirv_mlir : Flag<["-"], "emit-spirv-mlir">, Visibility<[CC1Option]>, Group, + HelpText<"Build ASTs and then lower through ClangIR to MLIR to SPIR-V, emit the .spv 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 b9e4d09df222..5ef3976b3fb4 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 a .spv file + EmitSPIRV, + /// Emit a .ll file. EmitLLVM, diff --git a/clang/lib/CIR/FrontendAction/CIRGenAction.cpp b/clang/lib/CIR/FrontendAction/CIRGenAction.cpp index 57be1a5e077d..73b272192d24 100644 --- a/clang/lib/CIR/FrontendAction/CIRGenAction.cpp +++ b/clang/lib/CIR/FrontendAction/CIRGenAction.cpp @@ -13,6 +13,7 @@ #include "mlir/IR/MLIRContext.h" #include "mlir/IR/OperationSupport.h" #include "mlir/Parser/Parser.h" +#include "mlir/Target/SPIRV/Serialization.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclCXX.h" @@ -26,6 +27,7 @@ #include "clang/CIR/CIRToCIRPasses.h" #include "clang/CIR/Dialect/IR/CIRDialect.h" #include "clang/CIR/LowerToLLVM.h" +#include "clang/CIR/LowerToSPIRV.h" #include "clang/CIR/Passes.h" #include "clang/CodeGen/BackendUtil.h" #include "clang/CodeGen/ModuleBuilder.h" @@ -278,6 +280,20 @@ class CIRGenConsumer : public clang::ASTConsumer { loweredMlirModule->print(*outputStream, flags); break; } + case CIRGenAction::OutputType::EmitSPIRV: { + auto loweredMlirModule = lowerFromCIRToMLIR(mlirMod, mlirCtx.get()); + auto spirvModule = ::mlir::lowerFromMLIRToSPIRV(loweredMlirModule, 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); + SmallVector words; + ::mlir::spirv::SerializationOptions options; + (void) ::mlir::spirv::serialize(spirvModule, words, options); + outputStream->write(reinterpret_cast(words.data()), words.size_in_bytes()); + break; + } case CIRGenAction::OutputType::EmitLLVM: case CIRGenAction::OutputType::EmitBC: case CIRGenAction::OutputType::EmitObj: @@ -464,6 +480,10 @@ void EmitMLIRAction::anchor() {} EmitMLIRAction::EmitMLIRAction(mlir::MLIRContext *_MLIRContext) : CIRGenAction(OutputType::EmitMLIR, _MLIRContext) {} +void EmitSPIRVAction::anchor() {} +EmitSPIRVAction::EmitSPIRVAction(mlir::MLIRContext *_MLIRContext) + : CIRGenAction(OutputType::EmitSPIRV, _MLIRContext) {} + void EmitLLVMAction::anchor() {} EmitLLVMAction::EmitLLVMAction(mlir::MLIRContext *_MLIRContext) : CIRGenAction(OutputType::EmitLLVM, _MLIRContext) {} diff --git a/clang/lib/CIR/Lowering/ThroughMLIR/CMakeLists.txt b/clang/lib/CIR/Lowering/ThroughMLIR/CMakeLists.txt index 33a74b9ddf8b..466c25e6cc9a 100644 --- a/clang/lib/CIR/Lowering/ThroughMLIR/CMakeLists.txt +++ b/clang/lib/CIR/Lowering/ThroughMLIR/CMakeLists.txt @@ -9,6 +9,7 @@ add_clang_library(clangCIRLoweringThroughMLIR LowerCIRLoopToSCF.cpp LowerCIRToMLIR.cpp LowerMLIRToLLVM.cpp + LowerMLIRToSPIRV.cpp DEPENDS MLIRCIROpsIncGen diff --git a/clang/lib/CIR/Lowering/ThroughMLIR/LowerMLIRToSPIRV.cpp b/clang/lib/CIR/Lowering/ThroughMLIR/LowerMLIRToSPIRV.cpp new file mode 100644 index 000000000000..055be910908c --- /dev/null +++ b/clang/lib/CIR/Lowering/ThroughMLIR/LowerMLIRToSPIRV.cpp @@ -0,0 +1,25 @@ +#include "mlir/IR/BuiltinOps.h" +#include "mlir/IR/MLIRContext.h" +#include "mlir/Pass/PassManager.h" +#include "clang/CIR/Passes.h" +#include "llvm/Support/TimeProfiler.h" + +#include "mlir/Dialect/SPIRV/Transforms/Passes.h" + +namespace mlir { + +mlir::ModuleOp lowerFromMLIRToSPIRV(mlir::ModuleOp theModule, + mlir::MLIRContext *mlirCtx) { + llvm::TimeTraceScope scope("Lower from MLIR to SPIR-V"); + + mlir::PassManager pm(mlirCtx); + + // TODO + //pm.addPass(cir::createConvertMLIRToSPIRVPass()); + + //auto result = !mlir::failed(pm.run(theModule)); + //if (!result) + // report_fatal_error("The pass manager failed to lower CIR to SPIRV dialect!"); +} + +} // namespace mlir \ No newline at end of file diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 534539d62282..3a1f4377a7da 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -2634,6 +2634,7 @@ static const auto &getFrontendActionTable() { {frontend::EmitCIRFlat, OPT_emit_cir_flat}, {frontend::EmitCIROnly, OPT_emit_cir_only}, {frontend::EmitMLIR, OPT_emit_mlir}, + {frontend::EmitSPIRV, OPT_emit_spirv_mlir}, {frontend::EmitHTML, OPT_emit_html}, {frontend::EmitLLVM, OPT_emit_llvm}, {frontend::EmitLLVMOnly, OPT_emit_llvm_only}, diff --git a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp index 40a96a38a8d5..d48548d87b7f 100644 --- a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp +++ b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp @@ -54,7 +54,7 @@ CreateFrontendBaseAction(CompilerInstance &CI) { auto UseCIR = CI.getFrontendOpts().UseClangIRPipeline; auto Act = CI.getFrontendOpts().ProgramAction; auto CIRAnalysisOnly = CI.getFrontendOpts().ClangIRAnalysisOnly; - auto EmitsCIR = Act == EmitCIR || Act == EmitCIRFlat || Act == EmitCIROnly; + auto EmitsCIR = Act == EmitCIR || Act == EmitCIRFlat || Act == EmitCIROnly || Act == EmitSPIRV; if (!UseCIR && EmitsCIR) llvm::report_fatal_error( @@ -96,6 +96,7 @@ CreateFrontendBaseAction(CompilerInstance &CI) { return std::make_unique<::cir::EmitCIRFlatAction>(); case EmitCIROnly: return std::make_unique<::cir::EmitCIROnlyAction>(); case EmitMLIR: return std::make_unique<::cir::EmitMLIRAction>(); + case EmitSPIRV: return std::make_unique<::cir::EmitSPIRVAction>(); #else case EmitCIR: case EmitCIRFlat: