Skip to content

Commit 49f7c80

Browse files
authored
[CIR] Add option to emit MLIR in LLVM dialect. (#1316)
This PR adds the flag `-emit-mlir-llvm` to allow emitting of MLIR in the LLVM dialect (cc @xlauko who asked me to do this). I'm not sure if the naming of the flag is the best and maybe someone will have a better idea. Another solution would be to make the `-emit-mlir` flag have a value, that specifies the target dialect (CIR/MLIR std dialects/LLVM Dialect).
1 parent d9eeb83 commit 49f7c80

File tree

27 files changed

+215
-120
lines changed

27 files changed

+215
-120
lines changed

clang/include/clang/CIR/FrontendAction/CIRGenAction.h

+1-17
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,9 @@ class CIRGenAction : public clang::ASTFrontendAction {
3232
public:
3333
enum class OutputType {
3434
EmitAssembly,
35-
EmitCIR,
36-
EmitCIRFlat,
35+
EmitMLIR,
3736
EmitLLVM,
3837
EmitBC,
39-
EmitMLIR,
4038
EmitObj,
4139
None
4240
};
@@ -73,20 +71,6 @@ class CIRGenAction : public clang::ASTFrontendAction {
7371
OutputType action;
7472
};
7573

76-
class EmitCIRAction : public CIRGenAction {
77-
virtual void anchor();
78-
79-
public:
80-
EmitCIRAction(mlir::MLIRContext *mlirCtx = nullptr);
81-
};
82-
83-
class EmitCIRFlatAction : public CIRGenAction {
84-
virtual void anchor();
85-
86-
public:
87-
EmitCIRFlatAction(mlir::MLIRContext *mlirCtx = nullptr);
88-
};
89-
9074
class EmitCIROnlyAction : public CIRGenAction {
9175
virtual void anchor();
9276

clang/include/clang/CIR/LowerToLLVM.h

+8-2
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,19 @@ class ModuleOp;
2929
namespace cir {
3030

3131
namespace direct {
32+
mlir::ModuleOp lowerDirectlyFromCIRToLLVMDialect(mlir::ModuleOp theModule,
33+
bool disableVerifier = false,
34+
bool disableCCLowering = false,
35+
bool disableDebugInfo = false);
36+
37+
// Lower directly from pristine CIR to LLVMIR.
3238
std::unique_ptr<llvm::Module> lowerDirectlyFromCIRToLLVMIR(
3339
mlir::ModuleOp theModule, llvm::LLVMContext &llvmCtx,
3440
bool disableVerifier = false, bool disableCCLowering = false,
3541
bool disableDebugInfo = false);
36-
}
3742

38-
// Lower directly from pristine CIR to LLVMIR.
43+
} // namespace direct
44+
3945
std::unique_ptr<llvm::Module>
4046
lowerFromCIRToMLIRToLLVMIR(mlir::ModuleOp theModule,
4147
std::unique_ptr<mlir::MLIRContext> mlirCtx,

clang/include/clang/CIR/LowerToMLIR.h

+6
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,16 @@
1212
#ifndef CLANG_CIR_LOWERTOMLIR_H
1313
#define CLANG_CIR_LOWERTOMLIR_H
1414

15+
#include "mlir/Transforms/DialectConversion.h"
16+
1517
namespace cir {
1618

1719
void populateCIRLoopToSCFConversionPatterns(mlir::RewritePatternSet &patterns,
1820
mlir::TypeConverter &converter);
21+
22+
mlir::ModuleOp
23+
lowerFromCIRToMLIRToLLVMDialect(mlir::ModuleOp theModule,
24+
mlir::MLIRContext *mlirCtx = nullptr);
1925
} // namespace cir
2026

2127
#endif // CLANG_CIR_LOWERTOMLIR_H_

clang/include/clang/Driver/Options.td

+15-4
Original file line numberDiff line numberDiff line change
@@ -3113,14 +3113,25 @@ defm clangir_call_conv_lowering : BoolFOption<"clangir-call-conv-lowering",
31133113
NegFlag<SetFalse, [], [ClangOption, CC1Option], "Ignore calling convetion during lowering">,
31143114
BothFlags<[], [ClangOption, CC1Option], "">>;
31153115

3116+
def emit_mlir : Flag<["-"], "emit-mlir">, Visibility<[ClangOption]>, Group<Action_Group>,
3117+
HelpText<"Build ASTs and then lower through ClangIR to MLIR (standard dialects "
3118+
"when `-fno-clangir-direct-lowering` is used or the LLVM dialect when "
3119+
"`-fclangir-direct-lowering` is used), emit the .mlir file.">;
3120+
def emit_mlir_EQ : Joined<["-"], "emit-mlir=">, Visibility<[ClangOption, CC1Option]>, Group<Action_Group>,
3121+
HelpText<"Build ASTs and then lower through ClangIR to the selected MLIR dialect, emit the .mlir file. "
3122+
"Allowed values are `core` for MLIR standard dialects and `llvm` for the LLVM dialect.">,
3123+
Values<"core,llvm,cir,cir-flat">,
3124+
NormalizedValuesScope<"frontend">,
3125+
NormalizedValues<["MLIR_CORE", "MLIR_LLVM", "MLIR_CIR", "MLIR_CIR_FLAT"]>,
3126+
MarshallingInfoEnum<FrontendOpts<"MLIRTargetDialect">, "MLIR_CORE">;
31163127
def emit_cir : Flag<["-"], "emit-cir">, Visibility<[ClangOption, CC1Option]>,
3117-
Group<Action_Group>, HelpText<"Build ASTs and then lower to ClangIR, emit the .cir file">;
3128+
Group<Action_Group>, Alias<emit_mlir_EQ>, AliasArgs<["cir"]>,
3129+
HelpText<"Build ASTs and then lower to ClangIR, emit the .cir file">;
31183130
def emit_cir_only : Flag<["-"], "emit-cir-only">,
31193131
HelpText<"Build ASTs and convert to CIR, discarding output">;
31203132
def emit_cir_flat : Flag<["-"], "emit-cir-flat">, Visibility<[ClangOption, CC1Option]>,
3121-
Group<Action_Group>, HelpText<"Similar to -emit-cir but also lowers structured CFG into basic blocks.">;
3122-
def emit_mlir : Flag<["-"], "emit-mlir">, Visibility<[CC1Option]>, Group<Action_Group>,
3123-
HelpText<"Build ASTs and then lower through ClangIR to MLIR, emit the .milr file">;
3133+
Group<Action_Group>, Alias<emit_mlir_EQ>, AliasArgs<["cir-flat"]>,
3134+
HelpText<"Similar to -emit-cir but also lowers structured CFG into basic blocks.">;
31243135
/// ClangIR-specific options - END
31253136

31263137
def flto : Flag<["-"], "flto">,

clang/include/clang/Driver/Types.def

-2
Original file line numberDiff line numberDiff line change
@@ -99,8 +99,6 @@ TYPE("ir", LLVM_BC, INVALID, "bc", phases
9999
TYPE("lto-ir", LTO_IR, INVALID, "s", phases::Compile, phases::Backend, phases::Assemble, phases::Link)
100100
TYPE("lto-bc", LTO_BC, INVALID, "o", phases::Compile, phases::Backend, phases::Assemble, phases::Link)
101101

102-
TYPE("cir", CIR, INVALID, "cir", phases::Compile, phases::Backend, phases::Assemble, phases::Link)
103-
TYPE("cir-flat", CIR_FLAT, INVALID, "cir", phases::Compile, phases::Backend, phases::Assemble, phases::Link)
104102
TYPE("mlir", MLIR, INVALID, "mlir", phases::Compile, phases::Backend, phases::Assemble, phases::Link)
105103

106104
// Misc.

clang/include/clang/Frontend/FrontendOptions.h

+4-6
Original file line numberDiff line numberDiff line change
@@ -65,12 +65,6 @@ enum ActionKind {
6565
/// Translate input source into HTML.
6666
EmitHTML,
6767

68-
/// Emit a .cir file
69-
EmitCIR,
70-
71-
/// Emit a .cir file with flat ClangIR
72-
EmitCIRFlat,
73-
7468
/// Generate CIR, bud don't emit anything.
7569
EmitCIROnly,
7670

@@ -160,6 +154,8 @@ enum ActionKind {
160154
PrintDependencyDirectivesSourceMinimizerOutput
161155
};
162156

157+
enum MLIRDialectKind { MLIR_CORE, MLIR_LLVM, MLIR_CIR, MLIR_CIR_FLAT };
158+
163159
} // namespace frontend
164160

165161
/// The kind of a file that we've been handed as an input.
@@ -530,6 +526,8 @@ class FrontendOptions {
530526
std::string ClangIRIdiomRecognizerOpts;
531527
std::string ClangIRLibOptOpts;
532528

529+
frontend::MLIRDialectKind MLIRTargetDialect;
530+
533531
/// The input kind, either specified via -x argument or deduced from the input
534532
/// file name.
535533
InputKind DashX;

clang/lib/CIR/CodeGen/CIRPasses.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ mlir::LogicalResult runCIRToCIRPasses(
2828
llvm::StringRef lifetimeOpts, bool enableIdiomRecognizer,
2929
llvm::StringRef idiomRecognizerOpts, bool enableLibOpt,
3030
llvm::StringRef libOptOpts, std::string &passOptParsingFailure,
31-
bool enableCIRSimplify, bool flattenCIR, bool emitMLIR,
31+
bool enableCIRSimplify, bool flattenCIR, bool emitCore,
3232
bool enableCallConvLowering, bool enableMem2Reg) {
3333

3434
llvm::TimeTraceScope scope("CIR To CIR Passes");
@@ -81,7 +81,7 @@ mlir::LogicalResult runCIRToCIRPasses(
8181
if (enableMem2Reg)
8282
pm.addPass(mlir::createMem2Reg());
8383

84-
if (emitMLIR)
84+
if (emitCore)
8585
pm.addPass(mlir::createSCFPreparePass());
8686

8787
// FIXME: once CIRCodenAction fixes emission other than CIR we

clang/lib/CIR/FrontendAction/CIRGenAction.cpp

+42-33
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "clang/CIR/CIRToCIRPasses.h"
2727
#include "clang/CIR/Dialect/IR/CIRDialect.h"
2828
#include "clang/CIR/LowerToLLVM.h"
29+
#include "clang/CIR/LowerToMLIR.h"
2930
#include "clang/CIR/Passes.h"
3031
#include "clang/CodeGen/BackendUtil.h"
3132
#include "clang/CodeGen/ModuleBuilder.h"
@@ -201,8 +202,16 @@ class CIRGenConsumer : public clang::ASTConsumer {
201202
if (feOptions.ClangIRLibOpt)
202203
libOptOpts = sanitizePassOptions(feOptions.ClangIRLibOptOpts);
203204

204-
bool enableCCLowering = feOptions.ClangIRCallConvLowering &&
205-
action != CIRGenAction::OutputType::EmitCIR;
205+
bool enableCCLowering =
206+
feOptions.ClangIRCallConvLowering &&
207+
!(action == CIRGenAction::OutputType::EmitMLIR &&
208+
feOptions.MLIRTargetDialect == frontend::MLIR_CIR);
209+
bool flattenCIR =
210+
action == CIRGenAction::OutputType::EmitMLIR &&
211+
feOptions.MLIRTargetDialect == clang::frontend::MLIR_CIR_FLAT;
212+
213+
bool emitCore = action == CIRGenAction::OutputType::EmitMLIR &&
214+
feOptions.MLIRTargetDialect == clang::frontend::MLIR_CORE;
206215

207216
// Setup and run CIR pipeline.
208217
std::string passOptParsingFailure;
@@ -211,10 +220,8 @@ class CIRGenConsumer : public clang::ASTConsumer {
211220
feOptions.ClangIRLifetimeCheck, lifetimeOpts,
212221
feOptions.ClangIRIdiomRecognizer, idiomRecognizerOpts,
213222
feOptions.ClangIRLibOpt, libOptOpts, passOptParsingFailure,
214-
codeGenOptions.OptimizationLevel > 0,
215-
action == CIRGenAction::OutputType::EmitCIRFlat,
216-
action == CIRGenAction::OutputType::EmitMLIR, enableCCLowering,
217-
feOptions.ClangIREnableMem2Reg)
223+
codeGenOptions.OptimizationLevel > 0, flattenCIR, emitCore,
224+
enableCCLowering, feOptions.ClangIREnableMem2Reg)
218225
.failed()) {
219226
if (!passOptParsingFailure.empty())
220227
diagnosticsEngine.Report(diag::err_drv_cir_pass_opt_parsing)
@@ -260,25 +267,39 @@ class CIRGenConsumer : public clang::ASTConsumer {
260267
}
261268
}
262269

263-
switch (action) {
264-
case CIRGenAction::OutputType::EmitCIR:
265-
case CIRGenAction::OutputType::EmitCIRFlat:
266-
if (outputStream && mlirMod) {
267-
// FIXME: we cannot roundtrip prettyForm=true right now.
268-
mlir::OpPrintingFlags flags;
269-
flags.enableDebugInfo(/*enable=*/true, /*prettyForm=*/false);
270-
if (feOptions.ClangIRDisableCIRVerifier)
271-
flags.assumeVerified();
272-
mlirMod->print(*outputStream, flags);
273-
}
274-
break;
275-
case CIRGenAction::OutputType::EmitMLIR: {
276-
auto loweredMlirModule = lowerFromCIRToMLIR(mlirMod, mlirCtx.get());
270+
auto emitMLIR = [&](mlir::Operation *mlirMod, bool verify) {
271+
assert(mlirMod &&
272+
"MLIR module does not exist, but lowering did not fail?");
277273
assert(outputStream && "Why are we here without an output stream?");
278274
// FIXME: we cannot roundtrip prettyForm=true right now.
279275
mlir::OpPrintingFlags flags;
280276
flags.enableDebugInfo(/*enable=*/true, /*prettyForm=*/false);
281-
loweredMlirModule->print(*outputStream, flags);
277+
if (!verify)
278+
flags.assumeVerified();
279+
mlirMod->print(*outputStream, flags);
280+
};
281+
282+
switch (action) {
283+
case CIRGenAction::OutputType::EmitMLIR: {
284+
switch (feOptions.MLIRTargetDialect) {
285+
case clang::frontend::MLIR_CORE:
286+
// case for direct lowering is already checked in compiler invocation
287+
// no need to check here
288+
emitMLIR(lowerFromCIRToMLIR(mlirMod, mlirCtx.get()), false);
289+
break;
290+
case clang::frontend::MLIR_LLVM: {
291+
mlir::ModuleOp loweredMLIRModule =
292+
feOptions.ClangIRDirectLowering
293+
? direct::lowerDirectlyFromCIRToLLVMDialect(mlirMod)
294+
: lowerFromCIRToMLIRToLLVMDialect(mlirMod, mlirCtx.get());
295+
emitMLIR(loweredMLIRModule, false);
296+
break;
297+
}
298+
case clang::frontend::MLIR_CIR:
299+
case clang::frontend::MLIR_CIR_FLAT:
300+
emitMLIR(mlirMod, feOptions.ClangIRDisableCIRVerifier);
301+
break;
302+
}
282303
break;
283304
}
284305
case CIRGenAction::OutputType::EmitLLVM:
@@ -356,10 +377,6 @@ getOutputStream(CompilerInstance &ci, StringRef inFile,
356377
switch (action) {
357378
case CIRGenAction::OutputType::EmitAssembly:
358379
return ci.createDefaultOutputFile(false, inFile, "s");
359-
case CIRGenAction::OutputType::EmitCIR:
360-
return ci.createDefaultOutputFile(false, inFile, "cir");
361-
case CIRGenAction::OutputType::EmitCIRFlat:
362-
return ci.createDefaultOutputFile(false, inFile, "cir");
363380
case CIRGenAction::OutputType::EmitMLIR:
364381
return ci.createDefaultOutputFile(false, inFile, "mlir");
365382
case CIRGenAction::OutputType::EmitLLVM:
@@ -456,14 +473,6 @@ void EmitAssemblyAction::anchor() {}
456473
EmitAssemblyAction::EmitAssemblyAction(mlir::MLIRContext *_MLIRContext)
457474
: CIRGenAction(OutputType::EmitAssembly, _MLIRContext) {}
458475

459-
void EmitCIRAction::anchor() {}
460-
EmitCIRAction::EmitCIRAction(mlir::MLIRContext *_MLIRContext)
461-
: CIRGenAction(OutputType::EmitCIR, _MLIRContext) {}
462-
463-
void EmitCIRFlatAction::anchor() {}
464-
EmitCIRFlatAction::EmitCIRFlatAction(mlir::MLIRContext *_MLIRContext)
465-
: CIRGenAction(OutputType::EmitCIRFlat, _MLIRContext) {}
466-
467476
void EmitCIROnlyAction::anchor() {}
468477
EmitCIROnlyAction::EmitCIROnlyAction(mlir::MLIRContext *_MLIRContext)
469478
: CIRGenAction(OutputType::None, _MLIRContext) {}

clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp

+19-5
Original file line numberDiff line numberDiff line change
@@ -4789,11 +4789,11 @@ void populateCIRToLLVMPasses(mlir::OpPassManager &pm, bool useCCLowering) {
47894789

47904790
extern void registerCIRDialectTranslation(mlir::MLIRContext &context);
47914791

4792-
std::unique_ptr<llvm::Module>
4793-
lowerDirectlyFromCIRToLLVMIR(mlir::ModuleOp theModule, LLVMContext &llvmCtx,
4794-
bool disableVerifier, bool disableCCLowering,
4795-
bool disableDebugInfo) {
4796-
llvm::TimeTraceScope scope("lower from CIR to LLVM directly");
4792+
mlir::ModuleOp lowerDirectlyFromCIRToLLVMDialect(mlir::ModuleOp theModule,
4793+
bool disableVerifier,
4794+
bool disableCCLowering,
4795+
bool disableDebugInfo) {
4796+
llvm::TimeTraceScope scope("lower from CIR to LLVM Dialect");
47974797

47984798
mlir::MLIRContext *mlirCtx = theModule.getContext();
47994799
mlir::PassManager pm(mlirCtx);
@@ -4822,6 +4822,20 @@ lowerDirectlyFromCIRToLLVMIR(mlir::ModuleOp theModule, LLVMContext &llvmCtx,
48224822
if (theModule.verify().failed())
48234823
report_fatal_error("Verification of the final LLVMIR dialect failed!");
48244824

4825+
return theModule;
4826+
}
4827+
4828+
std::unique_ptr<llvm::Module>
4829+
lowerDirectlyFromCIRToLLVMIR(mlir::ModuleOp theModule, LLVMContext &llvmCtx,
4830+
bool disableVerifier, bool disableCCLowering,
4831+
bool disableDebugInfo) {
4832+
llvm::TimeTraceScope scope("lower from CIR to LLVM directly");
4833+
4834+
lowerDirectlyFromCIRToLLVMDialect(theModule, disableVerifier,
4835+
disableCCLowering, disableDebugInfo);
4836+
4837+
mlir::MLIRContext *mlirCtx = theModule.getContext();
4838+
48254839
mlir::registerBuiltinDialectTranslation(*mlirCtx);
48264840
mlir::registerLLVMDialectTranslation(*mlirCtx);
48274841
mlir::registerOpenMPDialectTranslation(*mlirCtx);

clang/lib/CIR/Lowering/ThroughMLIR/LowerCIRToMLIR.cpp

+19-6
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
#include "mlir/Transforms/DialectConversion.h"
4848
#include "clang/CIR/Dialect/IR/CIRDialect.h"
4949
#include "clang/CIR/Dialect/IR/CIRTypes.h"
50+
#include "clang/CIR/LowerToLLVM.h"
5051
#include "clang/CIR/LowerToMLIR.h"
5152
#include "clang/CIR/LoweringHelpers.h"
5253
#include "clang/CIR/Passes.h"
@@ -1465,13 +1466,14 @@ void ConvertCIRToMLIRPass::runOnOperation() {
14651466
signalPassFailure();
14661467
}
14671468

1468-
std::unique_ptr<llvm::Module>
1469-
lowerFromCIRToMLIRToLLVMIR(mlir::ModuleOp theModule,
1470-
std::unique_ptr<mlir::MLIRContext> mlirCtx,
1471-
LLVMContext &llvmCtx) {
1472-
llvm::TimeTraceScope scope("Lower from CIR to MLIR To LLVM");
1469+
mlir::ModuleOp lowerFromCIRToMLIRToLLVMDialect(mlir::ModuleOp theModule,
1470+
mlir::MLIRContext *mlirCtx) {
1471+
llvm::TimeTraceScope scope("Lower from CIR to MLIR To LLVM Dialect");
1472+
if (!mlirCtx) {
1473+
mlirCtx = theModule.getContext();
1474+
}
14731475

1474-
mlir::PassManager pm(mlirCtx.get());
1476+
mlir::PassManager pm(mlirCtx);
14751477

14761478
pm.addPass(createConvertCIRToMLIRPass());
14771479
pm.addPass(createConvertMLIRToLLVMPass());
@@ -1485,6 +1487,17 @@ lowerFromCIRToMLIRToLLVMIR(mlir::ModuleOp theModule,
14851487
if (theModule.verify().failed())
14861488
report_fatal_error("Verification of the final LLVMIR dialect failed!");
14871489

1490+
return theModule;
1491+
}
1492+
1493+
std::unique_ptr<llvm::Module>
1494+
lowerFromCIRToMLIRToLLVMIR(mlir::ModuleOp theModule,
1495+
std::unique_ptr<mlir::MLIRContext> mlirCtx,
1496+
LLVMContext &llvmCtx) {
1497+
llvm::TimeTraceScope scope("Lower from CIR to MLIR To LLVM");
1498+
1499+
lowerFromCIRToMLIRToLLVMDialect(theModule, mlirCtx.get());
1500+
14881501
mlir::registerBuiltinDialectTranslation(*mlirCtx);
14891502
mlir::registerLLVMDialectTranslation(*mlirCtx);
14901503
mlir::registerOpenMPDialectTranslation(*mlirCtx);

0 commit comments

Comments
 (0)