https://github.com/andykaylor updated https://github.com/llvm/llvm-project/pull/127835
>From 4f69f1700f9f982e9271157c5b870eda71e0c0f2 Mon Sep 17 00:00:00 2001 From: Andy Kaylor <akay...@nvidia.com> Date: Fri, 14 Feb 2025 17:30:54 -0800 Subject: [PATCH 1/6] [CIR] Initial implementation of lowering CIR to MLIR Add support for lowering CIR to MLIR and emitting an MLIR text file. Lowering of global pointers is not yet supported. --- clang/include/clang/CIR/CIRGenerator.h | 1 + .../clang/CIR/FrontendAction/CIRGenAction.h | 8 + clang/include/clang/CIR/LowerToLLVM.h | 4 + clang/include/clang/Driver/Options.td | 2 + .../include/clang/Frontend/FrontendOptions.h | 3 + clang/lib/CIR/FrontendAction/CIRGenAction.cpp | 17 ++ clang/lib/CIR/FrontendAction/CMakeLists.txt | 1 + clang/lib/CIR/Lowering/CMakeLists.txt | 1 + .../CIR/Lowering/ThroughMLIR/CMakeLists.txt | 16 ++ .../Lowering/ThroughMLIR/LowerCIRToMLIR.cpp | 201 ++++++++++++++++++ clang/lib/Frontend/CompilerInvocation.cpp | 2 + .../ExecuteCompilerInvocation.cpp | 6 + .../CIR/Lowering/ThroughMLIR/global-ptrs.cpp | 29 +++ .../test/CIR/Lowering/ThroughMLIR/global.cpp | 79 +++++++ 14 files changed, 370 insertions(+) create mode 100644 clang/lib/CIR/Lowering/ThroughMLIR/CMakeLists.txt create mode 100644 clang/lib/CIR/Lowering/ThroughMLIR/LowerCIRToMLIR.cpp create mode 100644 clang/test/CIR/Lowering/ThroughMLIR/global-ptrs.cpp create mode 100644 clang/test/CIR/Lowering/ThroughMLIR/global.cpp diff --git a/clang/include/clang/CIR/CIRGenerator.h b/clang/include/clang/CIR/CIRGenerator.h index 414eba80b88b8..76b662c68615c 100644 --- a/clang/include/clang/CIR/CIRGenerator.h +++ b/clang/include/clang/CIR/CIRGenerator.h @@ -55,6 +55,7 @@ class CIRGenerator : public clang::ASTConsumer { void Initialize(clang::ASTContext &astContext) override; bool HandleTopLevelDecl(clang::DeclGroupRef group) override; mlir::ModuleOp getModule() const; + mlir::MLIRContext &getContext() { return *mlirContext; } }; } // namespace cir diff --git a/clang/include/clang/CIR/FrontendAction/CIRGenAction.h b/clang/include/clang/CIR/FrontendAction/CIRGenAction.h index 99495f4718c5f..1ffffac1719c4 100644 --- a/clang/include/clang/CIR/FrontendAction/CIRGenAction.h +++ b/clang/include/clang/CIR/FrontendAction/CIRGenAction.h @@ -29,6 +29,7 @@ class CIRGenAction : public clang::ASTFrontendAction { EmitCIR, EmitLLVM, EmitBC, + EmitMLIR, EmitObj, }; @@ -59,6 +60,13 @@ class EmitCIRAction : public CIRGenAction { EmitCIRAction(mlir::MLIRContext *MLIRCtx = nullptr); }; +class EmitMLIRAction : public CIRGenAction { + virtual void anchor(); + +public: + EmitMLIRAction(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 6e1b0270fcd2b..e780a5a747730 100644 --- a/clang/include/clang/CIR/LowerToLLVM.h +++ b/clang/include/clang/CIR/LowerToLLVM.h @@ -20,6 +20,7 @@ class Module; } // namespace llvm namespace mlir { +class MLIRContext; class ModuleOp; } // namespace mlir @@ -30,6 +31,9 @@ std::unique_ptr<llvm::Module> lowerDirectlyFromCIRToLLVMIR(mlir::ModuleOp mlirModule, llvm::LLVMContext &llvmCtx); } // namespace direct + +mlir::ModuleOp lowerFromCIRToMLIR(mlir::ModuleOp mlirModule, + mlir::MLIRContext &mlirCtx); } // namespace cir #endif // CLANG_CIR_LOWERTOLLVM_H diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index d0414aba35209..02cabdbcee861 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2987,6 +2987,8 @@ defm clangir : BoolFOption<"clangir", BothFlags<[], [ClangOption, CC1Option], "">>; def emit_cir : Flag<["-"], "emit-cir">, Visibility<[ClangOption, CC1Option]>, Group<Action_Group>, HelpText<"Build ASTs and then lower to ClangIR">; +def emit_cir_mlir : Flag<["-"], "emit-cir-mlir">, Visibility<[CC1Option]>, Group<Action_Group>, + HelpText<"Build ASTs and then lower through ClangIR to MLIR, emit the .milr file">; /// ClangIR-specific options - END def flto_EQ : Joined<["-"], "flto=">, diff --git a/clang/include/clang/Frontend/FrontendOptions.h b/clang/include/clang/Frontend/FrontendOptions.h index 99b2d9a98ed1f..e15ce247d1e6e 100644 --- a/clang/include/clang/Frontend/FrontendOptions.h +++ b/clang/include/clang/Frontend/FrontendOptions.h @@ -68,6 +68,9 @@ enum ActionKind { /// Emit a .cir file EmitCIR, + /// Emit a .mlir file + EmitMLIR, + /// Emit a .ll file. EmitLLVM, diff --git a/clang/lib/CIR/FrontendAction/CIRGenAction.cpp b/clang/lib/CIR/FrontendAction/CIRGenAction.cpp index 0f686a36b982b..74f795e7e3307 100644 --- a/clang/lib/CIR/FrontendAction/CIRGenAction.cpp +++ b/clang/lib/CIR/FrontendAction/CIRGenAction.cpp @@ -24,6 +24,7 @@ static BackendAction getBackendActionFromOutputType(CIRGenAction::OutputType Action) { switch (Action) { case CIRGenAction::OutputType::EmitCIR: + case CIRGenAction::OutputType::EmitMLIR: assert(false && "Unsupported output type for getBackendActionFromOutputType!"); break; // Unreachable, but fall through to report that @@ -82,6 +83,7 @@ class CIRGenConsumer : public clang::ASTConsumer { void HandleTranslationUnit(ASTContext &C) override { Gen->HandleTranslationUnit(C); mlir::ModuleOp MlirModule = Gen->getModule(); + mlir::MLIRContext &MlirCtx = Gen->getContext(); switch (Action) { case CIRGenAction::OutputType::EmitCIR: if (OutputStream && MlirModule) { @@ -90,6 +92,15 @@ class CIRGenConsumer : public clang::ASTConsumer { MlirModule->print(*OutputStream, Flags); } break; + case CIRGenAction::OutputType::EmitMLIR: { + auto LoweredMlirModule = lowerFromCIRToMLIR(MlirModule, MlirCtx); + assert(OutputStream && "No output stream when lowering to MLIR!"); + // FIXME: we cannot roundtrip prettyForm=true right now. + mlir::OpPrintingFlags Flags; + Flags.enableDebugInfo(/*enable=*/true, /*prettyForm=*/false); + LoweredMlirModule->print(*OutputStream, Flags); + break; + } case CIRGenAction::OutputType::EmitLLVM: case CIRGenAction::OutputType::EmitBC: case CIRGenAction::OutputType::EmitObj: @@ -124,6 +135,8 @@ getOutputStream(CompilerInstance &CI, StringRef InFile, return CI.createDefaultOutputFile(false, InFile, "s"); case CIRGenAction::OutputType::EmitCIR: return CI.createDefaultOutputFile(false, InFile, "cir"); + case CIRGenAction::OutputType::EmitMLIR: + return CI.createDefaultOutputFile(false, InFile, "mlir"); case CIRGenAction::OutputType::EmitLLVM: return CI.createDefaultOutputFile(false, InFile, "ll"); case CIRGenAction::OutputType::EmitBC: @@ -155,6 +168,10 @@ void EmitCIRAction::anchor() {} EmitCIRAction::EmitCIRAction(mlir::MLIRContext *MLIRCtx) : CIRGenAction(OutputType::EmitCIR, MLIRCtx) {} +void EmitMLIRAction::anchor() {} +EmitMLIRAction::EmitMLIRAction(mlir::MLIRContext *MLIRCtx) + : CIRGenAction(OutputType::EmitMLIR, MLIRCtx) {} + void EmitLLVMAction::anchor() {} EmitLLVMAction::EmitLLVMAction(mlir::MLIRContext *MLIRCtx) : CIRGenAction(OutputType::EmitLLVM, MLIRCtx) {} diff --git a/clang/lib/CIR/FrontendAction/CMakeLists.txt b/clang/lib/CIR/FrontendAction/CMakeLists.txt index 6d5a8758468f6..859349e650d7e 100644 --- a/clang/lib/CIR/FrontendAction/CMakeLists.txt +++ b/clang/lib/CIR/FrontendAction/CMakeLists.txt @@ -17,6 +17,7 @@ add_clang_library(clangCIRFrontendAction clangFrontend clangCIR clangCIRLoweringDirectToLLVM + clangCIRLoweringThroughMLIR clangCodeGen MLIRCIR MLIRIR diff --git a/clang/lib/CIR/Lowering/CMakeLists.txt b/clang/lib/CIR/Lowering/CMakeLists.txt index 95c304ded9183..f720e597ecb0f 100644 --- a/clang/lib/CIR/Lowering/CMakeLists.txt +++ b/clang/lib/CIR/Lowering/CMakeLists.txt @@ -1 +1,2 @@ add_subdirectory(DirectToLLVM) +add_subdirectory(ThroughMLIR) diff --git a/clang/lib/CIR/Lowering/ThroughMLIR/CMakeLists.txt b/clang/lib/CIR/Lowering/ThroughMLIR/CMakeLists.txt new file mode 100644 index 0000000000000..81fc9703ff0ae --- /dev/null +++ b/clang/lib/CIR/Lowering/ThroughMLIR/CMakeLists.txt @@ -0,0 +1,16 @@ +set(LLVM_LINK_COMPONENTS + Core + Support + ) + +get_property(dialect_libs GLOBAL PROPERTY MLIR_DIALECT_LIBS) + +add_clang_library(clangCIRLoweringThroughMLIR + LowerCIRToMLIR.cpp + + DEPENDS + LINK_LIBS + MLIRIR + ${dialect_libs} + MLIRCIR +) diff --git a/clang/lib/CIR/Lowering/ThroughMLIR/LowerCIRToMLIR.cpp b/clang/lib/CIR/Lowering/ThroughMLIR/LowerCIRToMLIR.cpp new file mode 100644 index 0000000000000..53ec01a22f781 --- /dev/null +++ b/clang/lib/CIR/Lowering/ThroughMLIR/LowerCIRToMLIR.cpp @@ -0,0 +1,201 @@ +//====- LowerCIRToMLIR.cpp - Lowering from CIR to MLIR --------------------===// +// +// 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 implements lowering of CIR operations to MLIR. +// +//===----------------------------------------------------------------------===// + +#include "mlir/Dialect/MemRef/IR/MemRef.h" +#include "mlir/IR/BuiltinDialect.h" +#include "mlir/Pass/Pass.h" +#include "mlir/Pass/PassManager.h" +#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/MissingFeatures.h" +#include "llvm/ADT/TypeSwitch.h" +#include "llvm/Support/TimeProfiler.h" + +using namespace cir; +using namespace llvm; + +namespace cir { + +struct ConvertCIRToMLIRPass + : public mlir::PassWrapper<ConvertCIRToMLIRPass, + mlir::OperationPass<mlir::ModuleOp>> { + void getDependentDialects(mlir::DialectRegistry ®istry) const override { + registry.insert<mlir::BuiltinDialect, mlir::memref::MemRefDialect>(); + } + void runOnOperation() final; + + StringRef getDescription() const override { + return "Convert the CIR dialect module to MLIR standard dialects"; + } + + StringRef getArgument() const override { return "cir-to-mlir"; } +}; + +class CIRGlobalOpLowering : public mlir::OpConversionPattern<cir::GlobalOp> { +public: + using OpConversionPattern<cir::GlobalOp>::OpConversionPattern; + mlir::LogicalResult + matchAndRewrite(cir::GlobalOp op, OpAdaptor adaptor, + mlir::ConversionPatternRewriter &rewriter) const override { + auto moduleOp = op->getParentOfType<mlir::ModuleOp>(); + if (!moduleOp) + return mlir::failure(); + + mlir::OpBuilder b(moduleOp.getContext()); + + const auto cirSymType = op.getSymType(); + assert(!cir::MissingFeatures::convertTypeForMemory()); + auto convertedType = getTypeConverter()->convertType(cirSymType); + if (!convertedType) + return mlir::failure(); + auto memrefType = dyn_cast<mlir::MemRefType>(convertedType); + if (!memrefType) + memrefType = mlir::MemRefType::get({}, convertedType); + // Add an optional alignment to the global memref. + assert(!cir::MissingFeatures::opGlobalAlignment()); + mlir::IntegerAttr memrefAlignment = mlir::IntegerAttr(); + // Add an optional initial value to the global memref. + mlir::Attribute initialValue = mlir::Attribute(); + std::optional<mlir::Attribute> init = op.getInitialValue(); + if (init.has_value()) { + initialValue = + llvm::TypeSwitch<mlir::Attribute, mlir::Attribute>(init.value()) + .Case<cir::IntAttr>([&](cir::IntAttr attr) { + auto rtt = mlir::RankedTensorType::get({}, convertedType); + return mlir::DenseIntElementsAttr::get(rtt, attr.getValue()); + }) + .Case<cir::FPAttr>([&](cir::FPAttr attr) { + auto rtt = mlir::RankedTensorType::get({}, convertedType); + return mlir::DenseFPElementsAttr::get(rtt, attr.getValue()); + }) + .Default([&](mlir::Attribute attr) { + llvm_unreachable("GlobalOp lowering with initial value is not " + "fully supported yet"); + return mlir::Attribute(); + }); + } + + // Add symbol visibility + assert(!cir::MissingFeatures::opGlobalLinkage()); + std::string symVisibility = "public"; + + assert(!cir::MissingFeatures::opGlobalConstant()); + bool isConstant = false; + + rewriter.replaceOpWithNewOp<mlir::memref::GlobalOp>( + op, b.getStringAttr(op.getSymName()), + /*sym_visibility=*/b.getStringAttr(symVisibility), + /*type=*/memrefType, initialValue, + /*constant=*/isConstant, + /*alignment=*/memrefAlignment); + + return mlir::success(); + } +}; + +void populateCIRToMLIRConversionPatterns(mlir::RewritePatternSet &patterns, + mlir::TypeConverter &converter) { + patterns.add<CIRGlobalOpLowering>(converter, patterns.getContext()); +} + +static mlir::TypeConverter prepareTypeConverter() { + mlir::TypeConverter converter; + converter.addConversion([&](cir::PointerType type) -> mlir::Type { + assert(!cir::MissingFeatures::convertTypeForMemory()); + mlir::Type ty = converter.convertType(type.getPointee()); + // FIXME: The pointee type might not be converted (e.g. struct) + if (!ty) + return nullptr; + return mlir::MemRefType::get({}, ty); + }); + converter.addConversion( + [&](mlir::IntegerType type) -> mlir::Type { return type; }); + converter.addConversion( + [&](mlir::FloatType type) -> mlir::Type { return type; }); + converter.addConversion([&](cir::VoidType type) -> mlir::Type { return {}; }); + converter.addConversion([&](cir::IntType type) -> mlir::Type { + // arith dialect ops doesn't take signed integer -- drop cir sign here + return mlir::IntegerType::get( + type.getContext(), type.getWidth(), + mlir::IntegerType::SignednessSemantics::Signless); + }); + converter.addConversion([&](cir::SingleType type) -> mlir::Type { + return mlir::Float32Type::get(type.getContext()); + }); + converter.addConversion([&](cir::DoubleType type) -> mlir::Type { + return mlir::Float64Type::get(type.getContext()); + }); + converter.addConversion([&](cir::FP80Type type) -> mlir::Type { + return mlir::Float80Type::get(type.getContext()); + }); + converter.addConversion([&](cir::LongDoubleType type) -> mlir::Type { + return converter.convertType(type.getUnderlying()); + }); + converter.addConversion([&](cir::FP128Type type) -> mlir::Type { + return mlir::Float128Type::get(type.getContext()); + }); + converter.addConversion([&](cir::FP16Type type) -> mlir::Type { + return mlir::Float16Type::get(type.getContext()); + }); + converter.addConversion([&](cir::BF16Type type) -> mlir::Type { + return mlir::BFloat16Type::get(type.getContext()); + }); + + return converter; +} + +void ConvertCIRToMLIRPass::runOnOperation() { + auto module = getOperation(); + + auto converter = prepareTypeConverter(); + + mlir::RewritePatternSet patterns(&getContext()); + + populateCIRToMLIRConversionPatterns(patterns, converter); + + mlir::ConversionTarget target(getContext()); + target.addLegalOp<mlir::ModuleOp>(); + target.addLegalDialect<mlir::memref::MemRefDialect>(); + target.addIllegalDialect<cir::CIRDialect>(); + + if (failed(applyPartialConversion(module, target, std::move(patterns)))) + signalPassFailure(); +} + +std::unique_ptr<mlir::Pass> createConvertCIRToMLIRPass() { + return std::make_unique<ConvertCIRToMLIRPass>(); +} + +mlir::ModuleOp lowerFromCIRToMLIR(mlir::ModuleOp mlirModule, + mlir::MLIRContext &mlirCtx) { + llvm::TimeTraceScope scope("Lower CIR To MLIR"); + + mlir::PassManager pm(&mlirCtx); + + pm.addPass(createConvertCIRToMLIRPass()); + + auto result = !mlir::failed(pm.run(mlirModule)); + if (!result) + llvm::report_fatal_error( + "The pass manager failed to lower CIR to MLIR standard dialects!"); + + // Now that we ran all the lowering passes, verify the final output. + if (mlirModule.verify().failed()) + llvm::report_fatal_error( + "Verification of the final MLIR in standard dialects failed!"); + + return mlirModule; +} + +} // namespace cir diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 4eb743acf327f..58fdad192056f 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -2740,6 +2740,7 @@ static const auto &getFrontendActionTable() { {frontend::EmitAssembly, OPT_S}, {frontend::EmitBC, OPT_emit_llvm_bc}, {frontend::EmitCIR, OPT_emit_cir}, + {frontend::EmitMLIR, OPT_emit_cir_mlir}, {frontend::EmitHTML, OPT_emit_html}, {frontend::EmitLLVM, OPT_emit_llvm}, {frontend::EmitLLVMOnly, OPT_emit_llvm_only}, @@ -4631,6 +4632,7 @@ static bool isStrictlyPreprocessorAction(frontend::ActionKind Action) { case frontend::EmitAssembly: case frontend::EmitBC: case frontend::EmitCIR: + case frontend::EmitMLIR: case frontend::EmitHTML: case frontend::EmitLLVM: case frontend::EmitLLVMOnly: diff --git a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp index bb3bb0aac78bf..ec0949c2b6941 100644 --- a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp +++ b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp @@ -79,6 +79,12 @@ CreateFrontendBaseAction(CompilerInstance &CI) { return std::make_unique<cir::EmitCIRAction>(); #else llvm_unreachable("CIR suppport not built into clang"); +#endif + case EmitMLIR: +#if CLANG_ENABLE_CIR + return std::make_unique<cir::EmitMLIRAction>(); +#else + llvm_unreachable("CIR suppport not built into clang"); #endif case EmitHTML: return std::make_unique<HTMLPrintAction>(); case EmitLLVM: { diff --git a/clang/test/CIR/Lowering/ThroughMLIR/global-ptrs.cpp b/clang/test/CIR/Lowering/ThroughMLIR/global-ptrs.cpp new file mode 100644 index 0000000000000..ada6a17896dfa --- /dev/null +++ b/clang/test/CIR/Lowering/ThroughMLIR/global-ptrs.cpp @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir-mlir %s -o %t.mlir +// RUN: FileCheck --input-file=%t.mlir %s + +// XFAIL: * + +// Note: This is here to track the failed lowering of global pointers. When +// this test starts passing, the checks should be updated with more +// specifics. + +void *vp; +// CHECK: memref.global "public" @vp + +int *ip = 0; +// CHECK: memref.global "public" @ip + +double *dp; +// CHECK: memref.global "public" @dp + +char **cpp; +// CHECK: memref.global "public" @cpp + +void (*fp)(); +// CHECK: memref.global "public" @fp + +int (*fpii)(int) = 0; +// CHECK: memref.global "public" @fpii + +void (*fpvar)(int, ...); +// CHECK: memref.global "public" @fpvar diff --git a/clang/test/CIR/Lowering/ThroughMLIR/global.cpp b/clang/test/CIR/Lowering/ThroughMLIR/global.cpp new file mode 100644 index 0000000000000..4515d68aa177d --- /dev/null +++ b/clang/test/CIR/Lowering/ThroughMLIR/global.cpp @@ -0,0 +1,79 @@ +// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir-mlir %s -o %t.mlir +// RUN: FileCheck --input-file=%t.mlir %s + +char c; +// CHECK: memref.global "public" @c : memref<i8> + +signed char sc; +// CHECK: memref.global "public" @sc : memref<i8> + +unsigned char uc; +// CHECK: memref.global "public" @uc : memref<i8> + +short ss; +// CHECK: memref.global "public" @ss : memref<i16> + +unsigned short us = 100; +// CHECK: memref.global "public" @us : memref<i16> = dense<100> + +int si = 42; +// CHECK: memref.global "public" @si : memref<i32> = dense<42> + +unsigned ui; +// CHECK: memref.global "public" @ui : memref<i32> + +long sl; +// CHECK: memref.global "public" @sl : memref<i64> + +unsigned long ul; +// CHECK: memref.global "public" @ul : memref<i64> + +long long sll; +// CHECK: memref.global "public" @sll : memref<i64> + +unsigned long long ull = 123456; +// CHECK: memref.global "public" @ull : memref<i64> = dense<123456> + +__int128 s128; +// CHECK: memref.global "public" @s128 : memref<i128> + +unsigned __int128 u128; +// CHECK: memref.global "public" @u128 : memref<i128> + +wchar_t wc; +// CHECK: memref.global "public" @wc : memref<i32> + +char8_t c8; +// CHECK: memref.global "public" @c8 : memref<i8> + +char16_t c16; +// CHECK: memref.global "public" @c16 : memref<i16> + +char32_t c32; +// CHECK: memref.global "public" @c32 : memref<i32> + +_BitInt(20) sb20; +// CHECK: memref.global "public" @sb20 : memref<i20> + +unsigned _BitInt(48) ub48; +// CHECK: memref.global "public" @ub48 : memref<i48> + +_Float16 f16; +// CHECK: memref.global "public" @f16 : memref<f16> + +__bf16 bf16; +// CHECK: memref.global "public" @bf16 : memref<bf16> + +float f; +// CHECK: memref.global "public" @f : memref<f32> + +double d = 1.25; +// CHECK: memref.global "public" @d : memref<f64> = dense<1.250000e+00> + +long double ld; +// CHECK: memref.global "public" @ld : memref<f80> + +__float128 f128; +// CHECK: memref.global "public" @f128 : memref<f128> + +// FIXME: Add global pointers when they can be lowered to MLIR >From 0a3d748439a9722e7cae15121433cf72cc6b2bd4 Mon Sep 17 00:00:00 2001 From: Andy Kaylor <akay...@nvidia.com> Date: Wed, 19 Feb 2025 14:22:04 -0800 Subject: [PATCH 2/6] Change cl option to -emit-core-mlir, change getContext to getMLIRContext() --- clang/include/clang/CIR/CIRGenerator.h | 2 +- clang/include/clang/Driver/Options.td | 4 ++-- clang/include/clang/Frontend/FrontendOptions.h | 2 +- clang/lib/CIR/FrontendAction/CIRGenAction.cpp | 2 +- clang/lib/Frontend/CompilerInvocation.cpp | 4 ++-- clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp | 2 +- clang/test/CIR/Lowering/ThroughMLIR/global-ptrs.cpp | 2 +- clang/test/CIR/Lowering/ThroughMLIR/global.cpp | 2 +- 8 files changed, 10 insertions(+), 10 deletions(-) diff --git a/clang/include/clang/CIR/CIRGenerator.h b/clang/include/clang/CIR/CIRGenerator.h index 76b662c68615c..1b519ebeab27e 100644 --- a/clang/include/clang/CIR/CIRGenerator.h +++ b/clang/include/clang/CIR/CIRGenerator.h @@ -55,7 +55,7 @@ class CIRGenerator : public clang::ASTConsumer { void Initialize(clang::ASTContext &astContext) override; bool HandleTopLevelDecl(clang::DeclGroupRef group) override; mlir::ModuleOp getModule() const; - mlir::MLIRContext &getContext() { return *mlirContext; } + mlir::MLIRContext &getMLIRContext() { return *mlirContext; } }; } // namespace cir diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 02cabdbcee861..fe65c5393fe3e 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2987,8 +2987,8 @@ defm clangir : BoolFOption<"clangir", BothFlags<[], [ClangOption, CC1Option], "">>; def emit_cir : Flag<["-"], "emit-cir">, Visibility<[ClangOption, CC1Option]>, Group<Action_Group>, HelpText<"Build ASTs and then lower to ClangIR">; -def emit_cir_mlir : Flag<["-"], "emit-cir-mlir">, Visibility<[CC1Option]>, Group<Action_Group>, - HelpText<"Build ASTs and then lower through ClangIR to MLIR, emit the .milr file">; +def emit_core_mlir : Flag<["-"], "emit-core-mlir">, Visibility<[CC1Option]>, Group<Action_Group>, + HelpText<"Build ASTs and then lower through ClangIR to core MLIR dialects, emit the .milr file">; /// ClangIR-specific options - END def flto_EQ : Joined<["-"], "flto=">, diff --git a/clang/include/clang/Frontend/FrontendOptions.h b/clang/include/clang/Frontend/FrontendOptions.h index e15ce247d1e6e..9d647726e020b 100644 --- a/clang/include/clang/Frontend/FrontendOptions.h +++ b/clang/include/clang/Frontend/FrontendOptions.h @@ -69,7 +69,7 @@ enum ActionKind { EmitCIR, /// Emit a .mlir file - EmitMLIR, + EmitCoreMLIR, /// Emit a .ll file. EmitLLVM, diff --git a/clang/lib/CIR/FrontendAction/CIRGenAction.cpp b/clang/lib/CIR/FrontendAction/CIRGenAction.cpp index 74f795e7e3307..b61e680662701 100644 --- a/clang/lib/CIR/FrontendAction/CIRGenAction.cpp +++ b/clang/lib/CIR/FrontendAction/CIRGenAction.cpp @@ -83,7 +83,7 @@ class CIRGenConsumer : public clang::ASTConsumer { void HandleTranslationUnit(ASTContext &C) override { Gen->HandleTranslationUnit(C); mlir::ModuleOp MlirModule = Gen->getModule(); - mlir::MLIRContext &MlirCtx = Gen->getContext(); + mlir::MLIRContext &MlirCtx = Gen->getMLIRContext(); switch (Action) { case CIRGenAction::OutputType::EmitCIR: if (OutputStream && MlirModule) { diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 58fdad192056f..224825f3939d3 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -2740,7 +2740,7 @@ static const auto &getFrontendActionTable() { {frontend::EmitAssembly, OPT_S}, {frontend::EmitBC, OPT_emit_llvm_bc}, {frontend::EmitCIR, OPT_emit_cir}, - {frontend::EmitMLIR, OPT_emit_cir_mlir}, + {frontend::EmitCoreMLIR, OPT_emit_core_mlir}, {frontend::EmitHTML, OPT_emit_html}, {frontend::EmitLLVM, OPT_emit_llvm}, {frontend::EmitLLVMOnly, OPT_emit_llvm_only}, @@ -4632,7 +4632,7 @@ static bool isStrictlyPreprocessorAction(frontend::ActionKind Action) { case frontend::EmitAssembly: case frontend::EmitBC: case frontend::EmitCIR: - case frontend::EmitMLIR: + case frontend::EmitCoreMLIR: case frontend::EmitHTML: case frontend::EmitLLVM: case frontend::EmitLLVMOnly: diff --git a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp index ec0949c2b6941..5f354c8ab8631 100644 --- a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp +++ b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp @@ -80,7 +80,7 @@ CreateFrontendBaseAction(CompilerInstance &CI) { #else llvm_unreachable("CIR suppport not built into clang"); #endif - case EmitMLIR: + case EmitCoreMLIR: #if CLANG_ENABLE_CIR return std::make_unique<cir::EmitMLIRAction>(); #else diff --git a/clang/test/CIR/Lowering/ThroughMLIR/global-ptrs.cpp b/clang/test/CIR/Lowering/ThroughMLIR/global-ptrs.cpp index ada6a17896dfa..2eb359c6b56b6 100644 --- a/clang/test/CIR/Lowering/ThroughMLIR/global-ptrs.cpp +++ b/clang/test/CIR/Lowering/ThroughMLIR/global-ptrs.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir-mlir %s -o %t.mlir +// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-core-mlir %s -o %t.mlir // RUN: FileCheck --input-file=%t.mlir %s // XFAIL: * diff --git a/clang/test/CIR/Lowering/ThroughMLIR/global.cpp b/clang/test/CIR/Lowering/ThroughMLIR/global.cpp index 4515d68aa177d..4a6ae8640c95b 100644 --- a/clang/test/CIR/Lowering/ThroughMLIR/global.cpp +++ b/clang/test/CIR/Lowering/ThroughMLIR/global.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir-mlir %s -o %t.mlir +// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-core-mlir %s -o %t.mlir // RUN: FileCheck --input-file=%t.mlir %s char c; >From 2419c153bafaf3c663f5a2fa9ce031345c84b288 Mon Sep 17 00:00:00 2001 From: Andy Kaylor <akay...@nvidia.com> Date: Thu, 20 Feb 2025 13:57:14 -0800 Subject: [PATCH 3/6] Fix autos, add const getMLIRContext() --- clang/include/clang/CIR/CIRGenerator.h | 1 + clang/lib/CIR/FrontendAction/CIRGenAction.cpp | 3 ++- .../lib/CIR/Lowering/ThroughMLIR/LowerCIRToMLIR.cpp | 12 ++++++------ 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/clang/include/clang/CIR/CIRGenerator.h b/clang/include/clang/CIR/CIRGenerator.h index 1b519ebeab27e..f167ade4d578d 100644 --- a/clang/include/clang/CIR/CIRGenerator.h +++ b/clang/include/clang/CIR/CIRGenerator.h @@ -56,6 +56,7 @@ class CIRGenerator : public clang::ASTConsumer { bool HandleTopLevelDecl(clang::DeclGroupRef group) override; mlir::ModuleOp getModule() const; mlir::MLIRContext &getMLIRContext() { return *mlirContext; } + const mlir::MLIRContext &getMLIRContext() const { return *mlirContext; } }; } // namespace cir diff --git a/clang/lib/CIR/FrontendAction/CIRGenAction.cpp b/clang/lib/CIR/FrontendAction/CIRGenAction.cpp index b61e680662701..7bbe321b1d2e8 100644 --- a/clang/lib/CIR/FrontendAction/CIRGenAction.cpp +++ b/clang/lib/CIR/FrontendAction/CIRGenAction.cpp @@ -93,7 +93,8 @@ class CIRGenConsumer : public clang::ASTConsumer { } break; case CIRGenAction::OutputType::EmitMLIR: { - auto LoweredMlirModule = lowerFromCIRToMLIR(MlirModule, MlirCtx); + mlir::ModuleOp LoweredMlirModule = + lowerFromCIRToMLIR(MlirModule, MlirCtx); assert(OutputStream && "No output stream when lowering to MLIR!"); // FIXME: we cannot roundtrip prettyForm=true right now. mlir::OpPrintingFlags Flags; diff --git a/clang/lib/CIR/Lowering/ThroughMLIR/LowerCIRToMLIR.cpp b/clang/lib/CIR/Lowering/ThroughMLIR/LowerCIRToMLIR.cpp index 53ec01a22f781..3f3b7f2440350 100644 --- a/clang/lib/CIR/Lowering/ThroughMLIR/LowerCIRToMLIR.cpp +++ b/clang/lib/CIR/Lowering/ThroughMLIR/LowerCIRToMLIR.cpp @@ -48,15 +48,15 @@ class CIRGlobalOpLowering : public mlir::OpConversionPattern<cir::GlobalOp> { mlir::LogicalResult matchAndRewrite(cir::GlobalOp op, OpAdaptor adaptor, mlir::ConversionPatternRewriter &rewriter) const override { - auto moduleOp = op->getParentOfType<mlir::ModuleOp>(); + mlir::ModuleOp moduleOp = op->getParentOfType<mlir::ModuleOp>(); if (!moduleOp) return mlir::failure(); mlir::OpBuilder b(moduleOp.getContext()); - const auto cirSymType = op.getSymType(); + const mlir::Type cirSymType = op.getSymType(); assert(!cir::MissingFeatures::convertTypeForMemory()); - auto convertedType = getTypeConverter()->convertType(cirSymType); + mlir::Type convertedType = getTypeConverter()->convertType(cirSymType); if (!convertedType) return mlir::failure(); auto memrefType = dyn_cast<mlir::MemRefType>(convertedType); @@ -156,9 +156,9 @@ static mlir::TypeConverter prepareTypeConverter() { } void ConvertCIRToMLIRPass::runOnOperation() { - auto module = getOperation(); + mlir::ModuleOp module = getOperation(); - auto converter = prepareTypeConverter(); + mlir::TypeConverter converter = prepareTypeConverter(); mlir::RewritePatternSet patterns(&getContext()); @@ -185,7 +185,7 @@ mlir::ModuleOp lowerFromCIRToMLIR(mlir::ModuleOp mlirModule, pm.addPass(createConvertCIRToMLIRPass()); - auto result = !mlir::failed(pm.run(mlirModule)); + bool result = !mlir::failed(pm.run(mlirModule)); if (!result) llvm::report_fatal_error( "The pass manager failed to lower CIR to MLIR standard dialects!"); >From ecb6a80a0784adbf7115a9c3adc8ed06ae77003f Mon Sep 17 00:00:00 2001 From: Andy Kaylor <akay...@nvidia.com> Date: Fri, 21 Feb 2025 11:58:50 -0800 Subject: [PATCH 4/6] Use -emit-mlir=[core|cir] command-line options --- clang/include/clang/Driver/Options.td | 9 ++++-- .../include/clang/Frontend/FrontendOptions.h | 6 +++- clang/lib/CIR/FrontendAction/CIRGenAction.cpp | 30 +++++++++++-------- clang/lib/Frontend/CompilerInvocation.cpp | 11 +++++-- .../ExecuteCompilerInvocation.cpp | 2 +- .../CIR/Lowering/ThroughMLIR/global-ptrs.cpp | 2 +- .../test/CIR/Lowering/ThroughMLIR/global.cpp | 2 +- clang/test/CIR/global-var-simple.cpp | 4 +-- clang/test/CIR/hello.c | 6 ++++ 9 files changed, 50 insertions(+), 22 deletions(-) create mode 100644 clang/test/CIR/hello.c diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index fe65c5393fe3e..cfd903e7caf50 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2987,8 +2987,13 @@ defm clangir : BoolFOption<"clangir", BothFlags<[], [ClangOption, CC1Option], "">>; def emit_cir : Flag<["-"], "emit-cir">, Visibility<[ClangOption, CC1Option]>, Group<Action_Group>, HelpText<"Build ASTs and then lower to ClangIR">; -def emit_core_mlir : Flag<["-"], "emit-core-mlir">, Visibility<[CC1Option]>, Group<Action_Group>, - HelpText<"Build ASTs and then lower through ClangIR to core MLIR dialects, emit the .milr file">; +def emit_mlir_EQ : Joined<["-"], "emit-mlir=">, Visibility<[CC1Option]>, Group<Action_Group>, + HelpText<"Build ASTs and then generate/lower to the selected MLIR dialect, emit the .mlir or .cir file. " + "Allowed values are `core` for MLIR core dialects and `cir` for ClangIR">, + Values<"core,cir">, + NormalizedValuesScope<"clang::frontend">, + NormalizedValues<["MLIR_Core", "MLIR_CIR"]>, + MarshallingInfoEnum<FrontendOpts<"MLIRTargetDialect">, "MLIR_CIR">; /// ClangIR-specific options - END def flto_EQ : Joined<["-"], "flto=">, diff --git a/clang/include/clang/Frontend/FrontendOptions.h b/clang/include/clang/Frontend/FrontendOptions.h index 9d647726e020b..62094a0d2abac 100644 --- a/clang/include/clang/Frontend/FrontendOptions.h +++ b/clang/include/clang/Frontend/FrontendOptions.h @@ -69,7 +69,7 @@ enum ActionKind { EmitCIR, /// Emit a .mlir file - EmitCoreMLIR, + EmitMLIR, /// Emit a .ll file. EmitLLVM, @@ -151,6 +151,8 @@ enum ActionKind { PrintDependencyDirectivesSourceMinimizerOutput }; +enum MLIRDialectKind { MLIR_CIR, MLIR_Core }; + } // namespace frontend /// The kind of a file that we've been handed as an input. @@ -420,6 +422,8 @@ class FrontendOptions { /// Specifies the output format of the AST. ASTDumpOutputFormat ASTDumpFormat = ADOF_Default; + frontend::MLIRDialectKind MLIRTargetDialect = frontend::MLIR_CIR; + /// The input kind, either specified via -x argument or deduced from the input /// file name. InputKind DashX; diff --git a/clang/lib/CIR/FrontendAction/CIRGenAction.cpp b/clang/lib/CIR/FrontendAction/CIRGenAction.cpp index 7bbe321b1d2e8..16b32ed62ae5a 100644 --- a/clang/lib/CIR/FrontendAction/CIRGenAction.cpp +++ b/clang/lib/CIR/FrontendAction/CIRGenAction.cpp @@ -13,6 +13,7 @@ #include "clang/CIR/LowerToLLVM.h" #include "clang/CodeGen/BackendUtil.h" #include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendOptions.h" #include "llvm/IR/Module.h" using namespace cir; @@ -86,21 +87,26 @@ class CIRGenConsumer : public clang::ASTConsumer { mlir::MLIRContext &MlirCtx = Gen->getMLIRContext(); switch (Action) { case CIRGenAction::OutputType::EmitCIR: - if (OutputStream && MlirModule) { + assert(CI.getFrontendOpts().MLIRTargetDialect == frontend::MLIR_CIR); + case CIRGenAction::OutputType::EmitMLIR: { + switch (CI.getFrontendOpts().MLIRTargetDialect) { + case frontend::MLIR_CIR: + if (OutputStream && MlirModule) { + mlir::OpPrintingFlags Flags; + Flags.enableDebugInfo(/*enable=*/true, /*prettyForm=*/false); + MlirModule->print(*OutputStream, Flags); + } + break; + case frontend::MLIR_Core: + mlir::ModuleOp LoweredMlirModule = + lowerFromCIRToMLIR(MlirModule, MlirCtx); + assert(OutputStream && "No output stream when lowering to MLIR!"); + // FIXME: we cannot roundtrip prettyForm=true right now. mlir::OpPrintingFlags Flags; Flags.enableDebugInfo(/*enable=*/true, /*prettyForm=*/false); - MlirModule->print(*OutputStream, Flags); + LoweredMlirModule->print(*OutputStream, Flags); + break; } - break; - case CIRGenAction::OutputType::EmitMLIR: { - mlir::ModuleOp LoweredMlirModule = - lowerFromCIRToMLIR(MlirModule, MlirCtx); - assert(OutputStream && "No output stream when lowering to MLIR!"); - // FIXME: we cannot roundtrip prettyForm=true right now. - mlir::OpPrintingFlags Flags; - Flags.enableDebugInfo(/*enable=*/true, /*prettyForm=*/false); - LoweredMlirModule->print(*OutputStream, Flags); - break; } case CIRGenAction::OutputType::EmitLLVM: case CIRGenAction::OutputType::EmitBC: diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 224825f3939d3..fc52e3516f7d1 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -2740,7 +2740,7 @@ static const auto &getFrontendActionTable() { {frontend::EmitAssembly, OPT_S}, {frontend::EmitBC, OPT_emit_llvm_bc}, {frontend::EmitCIR, OPT_emit_cir}, - {frontend::EmitCoreMLIR, OPT_emit_core_mlir}, + {frontend::EmitMLIR, OPT_emit_mlir_EQ}, {frontend::EmitHTML, OPT_emit_html}, {frontend::EmitLLVM, OPT_emit_llvm}, {frontend::EmitLLVMOnly, OPT_emit_llvm_only}, @@ -2857,6 +2857,13 @@ static void GenerateFrontendArgs(const FrontendOptions &Opts, }; } + if (Opts.ProgramAction == frontend::EmitMLIR) { + GenerateProgramAction = [&]() { + if (Opts.MLIRTargetDialect == frontend::MLIR_CIR) + GenerateArg(Consumer, OPT_emit_cir); + }; + } + GenerateProgramAction(); for (const auto &PluginArgs : Opts.PluginArgs) { @@ -4632,7 +4639,7 @@ static bool isStrictlyPreprocessorAction(frontend::ActionKind Action) { case frontend::EmitAssembly: case frontend::EmitBC: case frontend::EmitCIR: - case frontend::EmitCoreMLIR: + case frontend::EmitMLIR: case frontend::EmitHTML: case frontend::EmitLLVM: case frontend::EmitLLVMOnly: diff --git a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp index 5f354c8ab8631..ec0949c2b6941 100644 --- a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp +++ b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp @@ -80,7 +80,7 @@ CreateFrontendBaseAction(CompilerInstance &CI) { #else llvm_unreachable("CIR suppport not built into clang"); #endif - case EmitCoreMLIR: + case EmitMLIR: #if CLANG_ENABLE_CIR return std::make_unique<cir::EmitMLIRAction>(); #else diff --git a/clang/test/CIR/Lowering/ThroughMLIR/global-ptrs.cpp b/clang/test/CIR/Lowering/ThroughMLIR/global-ptrs.cpp index 2eb359c6b56b6..16a81c1a3afa0 100644 --- a/clang/test/CIR/Lowering/ThroughMLIR/global-ptrs.cpp +++ b/clang/test/CIR/Lowering/ThroughMLIR/global-ptrs.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-core-mlir %s -o %t.mlir +// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-mlir=core %s -o %t.mlir // RUN: FileCheck --input-file=%t.mlir %s // XFAIL: * diff --git a/clang/test/CIR/Lowering/ThroughMLIR/global.cpp b/clang/test/CIR/Lowering/ThroughMLIR/global.cpp index 4a6ae8640c95b..e8e68ec8259c6 100644 --- a/clang/test/CIR/Lowering/ThroughMLIR/global.cpp +++ b/clang/test/CIR/Lowering/ThroughMLIR/global.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-core-mlir %s -o %t.mlir +// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-mlir=core %s -o %t.mlir // RUN: FileCheck --input-file=%t.mlir %s char c; diff --git a/clang/test/CIR/global-var-simple.cpp b/clang/test/CIR/global-var-simple.cpp index f18f00fd6bd13..2ede420107126 100644 --- a/clang/test/CIR/global-var-simple.cpp +++ b/clang/test/CIR/global-var-simple.cpp @@ -1,5 +1,5 @@ -// Global variables of scalar typees with initial values -// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o - | FileCheck %s +// Global variables of scalar types with initial values +// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-mlir=cir %s -o - | FileCheck %s char c; // CHECK: cir.global external @c : !cir.int<s, 8> diff --git a/clang/test/CIR/hello.c b/clang/test/CIR/hello.c new file mode 100644 index 0000000000000..023e9e00e1cbd --- /dev/null +++ b/clang/test/CIR/hello.c @@ -0,0 +1,6 @@ +// Smoke test for ClangIR code generation +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-mlir=cir %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o - | FileCheck %s + +void foo() {} +// CHECK: cir.func @foo >From 3f6a570ecaf9fc9bb687ece297e8c9e26e0ebbae Mon Sep 17 00:00:00 2001 From: Andy Kaylor <akay...@nvidia.com> Date: Thu, 6 Mar 2025 17:51:30 -0800 Subject: [PATCH 5/6] Update to realign with incubator changes --- .../clang/CIR/FrontendAction/CIRGenAction.h | 10 +---- clang/include/clang/Driver/Options.td | 13 ++++--- clang/include/clang/Driver/Types.def | 2 +- .../include/clang/Frontend/FrontendOptions.h | 7 +--- clang/lib/CIR/FrontendAction/CIRGenAction.cpp | 39 ++++++++----------- clang/lib/Driver/Driver.cpp | 4 +- clang/lib/Driver/ToolChains/Clang.cpp | 9 +++-- clang/lib/Frontend/CompilerInvocation.cpp | 8 ++-- .../ExecuteCompilerInvocation.cpp | 8 +--- 9 files changed, 39 insertions(+), 61 deletions(-) diff --git a/clang/include/clang/CIR/FrontendAction/CIRGenAction.h b/clang/include/clang/CIR/FrontendAction/CIRGenAction.h index 1ffffac1719c4..c1932727abc57 100644 --- a/clang/include/clang/CIR/FrontendAction/CIRGenAction.h +++ b/clang/include/clang/CIR/FrontendAction/CIRGenAction.h @@ -26,10 +26,9 @@ class CIRGenAction : public clang::ASTFrontendAction { public: enum class OutputType { EmitAssembly, - EmitCIR, + EmitMLIR, EmitLLVM, EmitBC, - EmitMLIR, EmitObj, }; @@ -53,13 +52,6 @@ class CIRGenAction : public clang::ASTFrontendAction { OutputType Action; }; -class EmitCIRAction : public CIRGenAction { - virtual void anchor(); - -public: - EmitCIRAction(mlir::MLIRContext *MLIRCtx = nullptr); -}; - class EmitMLIRAction : public CIRGenAction { virtual void anchor(); diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index cfd903e7caf50..72188fb9b0a3b 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2985,15 +2985,16 @@ defm clangir : BoolFOption<"clangir", PosFlag<SetTrue, [], [ClangOption, CC1Option], "Use the ClangIR pipeline to compile">, NegFlag<SetFalse, [], [ClangOption, CC1Option], "Use the AST -> LLVM pipeline to compile">, BothFlags<[], [ClangOption, CC1Option], "">>; -def emit_cir : Flag<["-"], "emit-cir">, Visibility<[ClangOption, CC1Option]>, - Group<Action_Group>, HelpText<"Build ASTs and then lower to ClangIR">; -def emit_mlir_EQ : Joined<["-"], "emit-mlir=">, Visibility<[CC1Option]>, Group<Action_Group>, - HelpText<"Build ASTs and then generate/lower to the selected MLIR dialect, emit the .mlir or .cir file. " +def emit_mlir_EQ : Joined<["-"], "emit-mlir=">, Visibility<[ClangOption, CC1Option]>, Group<Action_Group>, + HelpText<"Build ASTs and then generate/lower to the selected MLIR dialect, emit the .mlir file. " "Allowed values are `core` for MLIR core dialects and `cir` for ClangIR">, Values<"core,cir">, NormalizedValuesScope<"clang::frontend">, - NormalizedValues<["MLIR_Core", "MLIR_CIR"]>, - MarshallingInfoEnum<FrontendOpts<"MLIRTargetDialect">, "MLIR_CIR">; + NormalizedValues<["MLIR_CORE", "MLIR_CIR"]>, + MarshallingInfoEnum<FrontendOpts<"MLIRTargetDialect">, "MLIR_CORE">; +def emit_cir : Flag<["-"], "emit-cir">, Visibility<[ClangOption, CC1Option]>, + Group<Action_Group>, Alias<emit_mlir_EQ>, AliasArgs<["cir"]>, + HelpText<"Build ASTs and then lower to ClangIR">; /// ClangIR-specific options - END def flto_EQ : Joined<["-"], "flto=">, diff --git a/clang/include/clang/Driver/Types.def b/clang/include/clang/Driver/Types.def index 214c5e7a789f9..10bcbc5538702 100644 --- a/clang/include/clang/Driver/Types.def +++ b/clang/include/clang/Driver/Types.def @@ -99,7 +99,7 @@ TYPE("ir", LLVM_BC, INVALID, "bc", phases TYPE("lto-ir", LTO_IR, INVALID, "s", phases::Compile, phases::Backend, phases::Assemble, phases::Link) TYPE("lto-bc", LTO_BC, INVALID, "o", phases::Compile, phases::Backend, phases::Assemble, phases::Link) -TYPE("cir", CIR, INVALID, "cir", phases::Compile, phases::Backend, phases::Assemble, phases::Link) +TYPE("mlir", MLIR, INVALID, "mlir", phases::Compile, phases::Backend, phases::Assemble, phases::Link) // Misc. TYPE("ast", AST, INVALID, "ast", phases::Compile, phases::Backend, phases::Assemble, phases::Link) TYPE("ifs", IFS, INVALID, "ifs", phases::IfsMerge) diff --git a/clang/include/clang/Frontend/FrontendOptions.h b/clang/include/clang/Frontend/FrontendOptions.h index 62094a0d2abac..34cbe2faed84a 100644 --- a/clang/include/clang/Frontend/FrontendOptions.h +++ b/clang/include/clang/Frontend/FrontendOptions.h @@ -65,9 +65,6 @@ enum ActionKind { /// Translate input source into HTML. EmitHTML, - /// Emit a .cir file - EmitCIR, - /// Emit a .mlir file EmitMLIR, @@ -151,7 +148,7 @@ enum ActionKind { PrintDependencyDirectivesSourceMinimizerOutput }; -enum MLIRDialectKind { MLIR_CIR, MLIR_Core }; +enum MLIRDialectKind { MLIR_CORE, MLIR_CIR }; } // namespace frontend @@ -422,7 +419,7 @@ class FrontendOptions { /// Specifies the output format of the AST. ASTDumpOutputFormat ASTDumpFormat = ADOF_Default; - frontend::MLIRDialectKind MLIRTargetDialect = frontend::MLIR_CIR; + frontend::MLIRDialectKind MLIRTargetDialect; /// The input kind, either specified via -x argument or deduced from the input /// file name. diff --git a/clang/lib/CIR/FrontendAction/CIRGenAction.cpp b/clang/lib/CIR/FrontendAction/CIRGenAction.cpp index 16b32ed62ae5a..d01e6dcae4e6c 100644 --- a/clang/lib/CIR/FrontendAction/CIRGenAction.cpp +++ b/clang/lib/CIR/FrontendAction/CIRGenAction.cpp @@ -24,7 +24,6 @@ namespace cir { static BackendAction getBackendActionFromOutputType(CIRGenAction::OutputType Action) { switch (Action) { - case CIRGenAction::OutputType::EmitCIR: case CIRGenAction::OutputType::EmitMLIR: assert(false && "Unsupported output type for getBackendActionFromOutputType!"); @@ -85,28 +84,28 @@ class CIRGenConsumer : public clang::ASTConsumer { Gen->HandleTranslationUnit(C); mlir::ModuleOp MlirModule = Gen->getModule(); mlir::MLIRContext &MlirCtx = Gen->getMLIRContext(); + + auto emitMLIR = [&](mlir::Operation *MlirMod) { + assert(MlirMod && + "MLIR module does not exist, but lowering did not fail?"); + assert(OutputStream && "Missing output stream when emitting MLIR!"); + // FIXME: we cannot roundtrip prettyForm=true right now. + mlir::OpPrintingFlags Flags; + Flags.enableDebugInfo(/*enable=*/true, /*prettyForm=*/false); + MlirMod->print(*OutputStream, Flags); + }; + switch (Action) { - case CIRGenAction::OutputType::EmitCIR: - assert(CI.getFrontendOpts().MLIRTargetDialect == frontend::MLIR_CIR); case CIRGenAction::OutputType::EmitMLIR: { switch (CI.getFrontendOpts().MLIRTargetDialect) { - case frontend::MLIR_CIR: - if (OutputStream && MlirModule) { - mlir::OpPrintingFlags Flags; - Flags.enableDebugInfo(/*enable=*/true, /*prettyForm=*/false); - MlirModule->print(*OutputStream, Flags); - } + case frontend::MLIR_CORE: + emitMLIR(lowerFromCIRToMLIR(MlirModule, MlirCtx)); break; - case frontend::MLIR_Core: - mlir::ModuleOp LoweredMlirModule = - lowerFromCIRToMLIR(MlirModule, MlirCtx); - assert(OutputStream && "No output stream when lowering to MLIR!"); - // FIXME: we cannot roundtrip prettyForm=true right now. - mlir::OpPrintingFlags Flags; - Flags.enableDebugInfo(/*enable=*/true, /*prettyForm=*/false); - LoweredMlirModule->print(*OutputStream, Flags); + case frontend::MLIR_CIR: + emitMLIR(MlirModule); break; } + break; } case CIRGenAction::OutputType::EmitLLVM: case CIRGenAction::OutputType::EmitBC: @@ -140,8 +139,6 @@ getOutputStream(CompilerInstance &CI, StringRef InFile, switch (Action) { case CIRGenAction::OutputType::EmitAssembly: return CI.createDefaultOutputFile(false, InFile, "s"); - case CIRGenAction::OutputType::EmitCIR: - return CI.createDefaultOutputFile(false, InFile, "cir"); case CIRGenAction::OutputType::EmitMLIR: return CI.createDefaultOutputFile(false, InFile, "mlir"); case CIRGenAction::OutputType::EmitLLVM: @@ -171,10 +168,6 @@ void EmitAssemblyAction::anchor() {} EmitAssemblyAction::EmitAssemblyAction(mlir::MLIRContext *MLIRCtx) : CIRGenAction(OutputType::EmitAssembly, MLIRCtx) {} -void EmitCIRAction::anchor() {} -EmitCIRAction::EmitCIRAction(mlir::MLIRContext *MLIRCtx) - : CIRGenAction(OutputType::EmitCIR, MLIRCtx) {} - void EmitMLIRAction::anchor() {} EmitMLIRAction::EmitMLIRAction(mlir::MLIRContext *MLIRCtx) : CIRGenAction(OutputType::EmitMLIR, MLIRCtx) {} diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index eca96c1cce7f7..76a6b5dc895c4 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -5130,8 +5130,8 @@ Action *Driver::ConstructPhaseAction( return C.MakeAction<AnalyzeJobAction>(Input, types::TY_Plist); if (Args.hasArg(options::OPT_emit_ast)) return C.MakeAction<CompileJobAction>(Input, types::TY_AST); - if (Args.hasArg(options::OPT_emit_cir)) - return C.MakeAction<CompileJobAction>(Input, types::TY_CIR); + if (Args.hasArg(options::OPT_emit_mlir_EQ)) + return C.MakeAction<CompileJobAction>(Input, types::TY_MLIR); if (Args.hasArg(options::OPT_module_file_info)) return C.MakeAction<CompileJobAction>(Input, types::TY_ModuleFile); if (Args.hasArg(options::OPT_verify_pch)) diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 4ebbd241d2f0b..c6d9096f3f06d 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -5215,7 +5215,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } } - if (Args.hasArg(options::OPT_fclangir)) + if (Args.hasArg(options::OPT_fclangir) || + Args.hasArg(options::OPT_emit_mlir_EQ)) CmdArgs.push_back("-fclangir"); if (IsOpenMPDevice) { @@ -5384,8 +5385,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } else if (JA.getType() == types::TY_RewrittenLegacyObjC) { CmdArgs.push_back("-rewrite-objc"); rewriteKind = RK_Fragile; - } else if (JA.getType() == types::TY_CIR) { - CmdArgs.push_back("-emit-cir"); + } else if (JA.getType() == types::TY_MLIR) { + CmdArgs.push_back(Args.MakeArgString( + Twine("-emit-mlir=") + + Args.getLastArgValue(options::OPT_emit_mlir_EQ))); } else { assert(JA.getType() == types::TY_PP_Asm && "Unexpected output type!"); } diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index fc52e3516f7d1..81f94a78f81b0 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -2739,7 +2739,6 @@ static const auto &getFrontendActionTable() { {frontend::DumpTokens, OPT_dump_tokens}, {frontend::EmitAssembly, OPT_S}, {frontend::EmitBC, OPT_emit_llvm_bc}, - {frontend::EmitCIR, OPT_emit_cir}, {frontend::EmitMLIR, OPT_emit_mlir_EQ}, {frontend::EmitHTML, OPT_emit_html}, {frontend::EmitLLVM, OPT_emit_llvm}, @@ -2859,8 +2858,8 @@ static void GenerateFrontendArgs(const FrontendOptions &Opts, if (Opts.ProgramAction == frontend::EmitMLIR) { GenerateProgramAction = [&]() { - if (Opts.MLIRTargetDialect == frontend::MLIR_CIR) - GenerateArg(Consumer, OPT_emit_cir); + if (Opts.MLIRTargetDialect == frontend::MLIR_CORE) + GenerateArg(Consumer, OPT_emit_mlir_EQ, "core"); }; } @@ -3110,7 +3109,7 @@ static bool ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, if (Opts.ProgramAction != frontend::GenerateModule && Opts.IsSystemModule) Diags.Report(diag::err_drv_argument_only_allowed_with) << "-fsystem-module" << "-emit-module"; - if (Args.hasArg(OPT_fclangir) || Args.hasArg(OPT_emit_cir)) + if (Args.hasArg(OPT_fclangir) || Args.hasArg(OPT_emit_mlir_EQ)) Opts.UseClangIRPipeline = true; if (Args.hasArg(OPT_aux_target_cpu)) @@ -4638,7 +4637,6 @@ static bool isStrictlyPreprocessorAction(frontend::ActionKind Action) { case frontend::ASTView: case frontend::EmitAssembly: case frontend::EmitBC: - case frontend::EmitCIR: case frontend::EmitMLIR: case frontend::EmitHTML: case frontend::EmitLLVM: diff --git a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp index ec0949c2b6941..5b09df7dda712 100644 --- a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp +++ b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp @@ -48,7 +48,7 @@ CreateFrontendBaseAction(CompilerInstance &CI) { unsigned UseCIR = CI.getFrontendOpts().UseClangIRPipeline; frontend::ActionKind Act = CI.getFrontendOpts().ProgramAction; - bool EmitsCIR = Act == EmitCIR; + bool EmitsCIR = Act == EmitMLIR; if (!UseCIR && EmitsCIR) llvm::report_fatal_error("-emit-cir and only valid when using -fclangir"); @@ -74,12 +74,6 @@ CreateFrontendBaseAction(CompilerInstance &CI) { return std::make_unique<cir::EmitBCAction>(); #endif return std::make_unique<EmitBCAction>(); - case EmitCIR: -#if CLANG_ENABLE_CIR - return std::make_unique<cir::EmitCIRAction>(); -#else - llvm_unreachable("CIR suppport not built into clang"); -#endif case EmitMLIR: #if CLANG_ENABLE_CIR return std::make_unique<cir::EmitMLIRAction>(); >From 55607cde9987b33adad9cc635c9e5b9f049df875 Mon Sep 17 00:00:00 2001 From: Andy Kaylor <akay...@nvidia.com> Date: Thu, 6 Mar 2025 18:28:43 -0800 Subject: [PATCH 6/6] Update to fix issues after rebase --- clang/include/clang/CIR/MissingFeatures.h | 2 +- .../Lowering/ThroughMLIR/LowerCIRToMLIR.cpp | 24 +++++++++++++++---- clang/test/CIR/hello.c | 6 ----- 3 files changed, 20 insertions(+), 12 deletions(-) delete mode 100644 clang/test/CIR/hello.c diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h index 6f845b7689e51..e80799a182ff5 100644 --- a/clang/include/clang/CIR/MissingFeatures.h +++ b/clang/include/clang/CIR/MissingFeatures.h @@ -35,7 +35,7 @@ struct MissingFeatures { static bool opGlobalThreadLocal() { return false; } static bool opGlobalConstant() { return false; } static bool opGlobalAlignment() { return false; } - + static bool opGlobalMlirLinkage() { return false; } static bool supportIFuncAttr() { return false; } static bool supportVisibility() { return false; } static bool supportComdat() { return false; } diff --git a/clang/lib/CIR/Lowering/ThroughMLIR/LowerCIRToMLIR.cpp b/clang/lib/CIR/Lowering/ThroughMLIR/LowerCIRToMLIR.cpp index 3f3b7f2440350..b1475f41dc843 100644 --- a/clang/lib/CIR/Lowering/ThroughMLIR/LowerCIRToMLIR.cpp +++ b/clang/lib/CIR/Lowering/ThroughMLIR/LowerCIRToMLIR.cpp @@ -42,6 +42,21 @@ struct ConvertCIRToMLIRPass StringRef getArgument() const override { return "cir-to-mlir"; } }; +/// Given a type convertor and a data layout, convert the given type to a type +/// that is suitable for memory operations. For example, this can be used to +/// lower cir.bool accesses to i8. +static mlir::Type convertTypeForMemory(const mlir::TypeConverter &converter, + mlir::Type type) { + // TODO(cir): Handle other types similarly to clang's codegen + // convertTypeForMemory + if (isa<cir::BoolType>(type)) { + // TODO: Use datalayout to get the size of bool + return mlir::IntegerType::get(type.getContext(), 8); + } + + return converter.convertType(type); +} + class CIRGlobalOpLowering : public mlir::OpConversionPattern<cir::GlobalOp> { public: using OpConversionPattern<cir::GlobalOp>::OpConversionPattern; @@ -55,8 +70,8 @@ class CIRGlobalOpLowering : public mlir::OpConversionPattern<cir::GlobalOp> { mlir::OpBuilder b(moduleOp.getContext()); const mlir::Type cirSymType = op.getSymType(); - assert(!cir::MissingFeatures::convertTypeForMemory()); - mlir::Type convertedType = getTypeConverter()->convertType(cirSymType); + mlir::Type convertedType = + convertTypeForMemory(*getTypeConverter(), cirSymType); if (!convertedType) return mlir::failure(); auto memrefType = dyn_cast<mlir::MemRefType>(convertedType); @@ -87,7 +102,7 @@ class CIRGlobalOpLowering : public mlir::OpConversionPattern<cir::GlobalOp> { } // Add symbol visibility - assert(!cir::MissingFeatures::opGlobalLinkage()); + assert(!cir::MissingFeatures::opGlobalMlirLinkage()); std::string symVisibility = "public"; assert(!cir::MissingFeatures::opGlobalConstant()); @@ -112,8 +127,7 @@ void populateCIRToMLIRConversionPatterns(mlir::RewritePatternSet &patterns, static mlir::TypeConverter prepareTypeConverter() { mlir::TypeConverter converter; converter.addConversion([&](cir::PointerType type) -> mlir::Type { - assert(!cir::MissingFeatures::convertTypeForMemory()); - mlir::Type ty = converter.convertType(type.getPointee()); + mlir::Type ty = convertTypeForMemory(converter, type.getPointee()); // FIXME: The pointee type might not be converted (e.g. struct) if (!ty) return nullptr; diff --git a/clang/test/CIR/hello.c b/clang/test/CIR/hello.c deleted file mode 100644 index 023e9e00e1cbd..0000000000000 --- a/clang/test/CIR/hello.c +++ /dev/null @@ -1,6 +0,0 @@ -// Smoke test for ClangIR code generation -// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-mlir=cir %s -o - | FileCheck %s -// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o - | FileCheck %s - -void foo() {} -// CHECK: cir.func @foo _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits