Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[CIR] Introduce a flattening pass #516

Merged
merged 16 commits into from
Apr 3, 2024
15 changes: 9 additions & 6 deletions clang/include/clang/CIR/CIRToCIRPasses.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,15 @@ class ModuleOp;
namespace cir {

// Run set of cleanup/prepare/etc passes CIR <-> CIR.
mlir::LogicalResult runCIRToCIRPasses(
mlir::ModuleOp theModule, mlir::MLIRContext *mlirCtx,
clang::ASTContext &astCtx, bool enableVerifier, bool enableLifetime,
llvm::StringRef lifetimeOpts, bool enableIdiomRecognizer,
llvm::StringRef idiomRecognizerOpts, bool enableLibOpt,
llvm::StringRef libOptOpts, std::string &passOptParsingFailure);
mlir::LogicalResult
runCIRToCIRPasses(mlir::ModuleOp theModule, mlir::MLIRContext *mlirCtx,
clang::ASTContext &astCtx, bool enableVerifier,
bool enableLifetime, llvm::StringRef lifetimeOpts,
bool enableIdiomRecognizer,
llvm::StringRef idiomRecognizerOpts, bool enableLibOpt,
llvm::StringRef libOptOpts,
std::string &passOptParsingFailure, bool flattenCIR);

} // namespace cir

#endif // CLANG_CIR_CIRTOCIRPASSES_H_
3 changes: 3 additions & 0 deletions clang/include/clang/CIR/Dialect/Passes.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ std::unique_ptr<Pass> createIdiomRecognizerPass();
std::unique_ptr<Pass> createIdiomRecognizerPass(clang::ASTContext *astCtx);
std::unique_ptr<Pass> createLibOptPass();
std::unique_ptr<Pass> createLibOptPass(clang::ASTContext *astCtx);
std::unique_ptr<Pass> createFlattenCFGPass();

void populateCIRPreLoweringPasses(mlir::OpPassManager &pm);

//===----------------------------------------------------------------------===//
// Registration
Expand Down
14 changes: 14 additions & 0 deletions clang/include/clang/CIR/Dialect/Passes.td
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,20 @@ def LoweringPrepare : Pass<"cir-lowering-prepare"> {
let dependentDialects = ["cir::CIRDialect"];
}

def FlattenCFG : Pass<"cir-flatten-cfg"> {
let summary = "Produces flatten cfg";
let description = [{
This pass transforms CIR and inline all the nested regions. Thus,
the next post condtions are met after the pass applied:
- there is not any nested region in a function body
- all the blocks in a function belong to the parent region
In other words, this pass removes such CIR operations like IfOp, LoopOp,
ScopeOp and etc. and produces a flat CIR.
}];
let constructor = "mlir::createFlattenCFGPass()";
let dependentDialects = ["cir::CIRDialect"];
}

def IdiomRecognizer : Pass<"cir-idiom-recognizer"> {
let summary = "Raise calls to C/C++ libraries to CIR operations";
let description = [{
Expand Down
4 changes: 4 additions & 0 deletions clang/include/clang/CIR/Passes.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ std::unique_ptr<mlir::Pass> createConvertCIRToMLIRPass();
namespace direct {
/// Create a pass that fully lowers CIR to the LLVMIR dialect.
std::unique_ptr<mlir::Pass> createConvertCIRToLLVMPass();

/// Adds passes that fully lower CIR to the LLVMIR dialect.
void populateCIRToLLVMPasses(mlir::OpPassManager &pm);

} // namespace direct
} // end namespace cir

Expand Down
8 changes: 8 additions & 0 deletions clang/include/clang/CIRFrontendAction/CIRGenAction.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class CIRGenAction : public clang::ASTFrontendAction {
enum class OutputType {
EmitAssembly,
EmitCIR,
EmitCIRFlat,
EmitLLVM,
EmitMLIR,
EmitObj,
Expand Down Expand Up @@ -77,6 +78,13 @@ class EmitCIRAction : public CIRGenAction {
EmitCIRAction(mlir::MLIRContext *mlirCtx = nullptr);
};

class EmitCIRFlatAction : public CIRGenAction {
virtual void anchor();

public:
EmitCIRFlatAction(mlir::MLIRContext *mlirCtx = nullptr);
};

class EmitCIROnlyAction : public CIRGenAction {
virtual void anchor();

Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -2926,6 +2926,8 @@ defm clangir_direct_lowering : BoolFOption<"clangir-direct-lowering",

def emit_cir : Flag<["-"], "emit-cir">, Visibility<[ClangOption, CC1Option]>,
Group<Action_Group>, HelpText<"Build ASTs and then lower to ClangIR, emit the .cir file">;
def emit_cir_flat : Flag<["-"], "emit-cir-flat">, Visibility<[ClangOption, CC1Option]>,
Group<Action_Group>, HelpText<"Similar to -emit-cir but also lowers structured CFG into basic blocks.">;
def emit_mlir : Flag<["-"], "emit-mlir">, Visibility<[CC1Option]>, Group<Action_Group>,
HelpText<"Build ASTs and then lower through ClangIR to MLIR, emit the .milr file">;
/// ClangIR-specific options - END
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Driver/Types.def
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ TYPE("lto-ir", LTO_IR, INVALID, "s", phases
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("cir-flat", CIR_FLAT, INVALID, "cir", phases::Compile, phases::Backend, phases::Assemble, phases::Link)
TYPE("mlir", MLIR, INVALID, "mlir", phases::Compile, phases::Backend, phases::Assemble, phases::Link)

// Misc.
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/Frontend/FrontendOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ enum ActionKind {
/// Emit a .cir file
EmitCIR,

/// Emit a .cir file with flat ClangIR
EmitCIRFlat,

/// Generate CIR, bud don't emit anything.
EmitCIROnly,

Expand Down
26 changes: 20 additions & 6 deletions clang/lib/CIR/CodeGen/CIRPasses.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,14 @@
#include "mlir/Pass/PassManager.h"

namespace cir {
mlir::LogicalResult runCIRToCIRPasses(
mlir::ModuleOp theModule, mlir::MLIRContext *mlirCtx,
clang::ASTContext &astCtx, bool enableVerifier, bool enableLifetime,
llvm::StringRef lifetimeOpts, bool enableIdiomRecognizer,
llvm::StringRef idiomRecognizerOpts, bool enableLibOpt,
llvm::StringRef libOptOpts, std::string &passOptParsingFailure) {
mlir::LogicalResult
runCIRToCIRPasses(mlir::ModuleOp theModule, mlir::MLIRContext *mlirCtx,
clang::ASTContext &astCtx, bool enableVerifier,
bool enableLifetime, llvm::StringRef lifetimeOpts,
bool enableIdiomRecognizer,
llvm::StringRef idiomRecognizerOpts, bool enableLibOpt,
llvm::StringRef libOptOpts,
std::string &passOptParsingFailure, bool flattenCIR) {
mlir::PassManager pm(mlirCtx);
pm.addPass(mlir::createMergeCleanupsPass());

Expand Down Expand Up @@ -55,6 +57,8 @@ mlir::LogicalResult runCIRToCIRPasses(
}

pm.addPass(mlir::createLoweringPreparePass(&astCtx));
if (flattenCIR)
mlir::populateCIRPreLoweringPasses(pm);

// FIXME: once CIRCodenAction fixes emission other than CIR we
// need to run this right before dialect emission.
Expand All @@ -63,4 +67,14 @@ mlir::LogicalResult runCIRToCIRPasses(
(void)mlir::applyPassManagerCLOptions(pm);
return pm.run(theModule);
}

} // namespace cir

namespace mlir {

void populateCIRPreLoweringPasses(OpPassManager &pm) {
pm.addPass(createFlattenCFGPass());
// add other passes here
}

} // namespace mlir
1 change: 1 addition & 0 deletions clang/lib/CIR/Dialect/Transforms/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ add_clang_library(MLIRCIRTransforms
IdiomRecognizer.cpp
LibOpt.cpp
StdHelpers.cpp
FlattenCFG.cpp

DEPENDS
MLIRCIRPassIncGen
Expand Down
60 changes: 60 additions & 0 deletions clang/lib/CIR/Dialect/Transforms/FlattenCFG.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
//====- FlattenCFG.cpp - Flatten CIR CFG ----------------------------------===//
//
// 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 pass that inlines CIR operations regions into the parent
// function region.
//
//===----------------------------------------------------------------------===//
#include "PassDetail.h"
#include "mlir/Dialect/Func/IR/FuncOps.h"
#include "mlir/IR/PatternMatch.h"
#include "mlir/Support/LogicalResult.h"
#include "mlir/Transforms/DialectConversion.h"
#include "mlir/Transforms/GreedyPatternRewriteDriver.h"
#include "clang/CIR/Dialect/IR/CIRDialect.h"
#include "clang/CIR/Dialect/Passes.h"

using namespace mlir;
using namespace mlir::cir;

namespace {

struct FlattenCFGPass : public FlattenCFGBase<FlattenCFGPass> {

FlattenCFGPass() = default;
void runOnOperation() override;
};

void populateFlattenCFGPatterns(RewritePatternSet &patterns) {
// TODO: add patterns here
}

void FlattenCFGPass::runOnOperation() {
RewritePatternSet patterns(&getContext());
populateFlattenCFGPatterns(patterns);

// Collect operations to apply patterns.
SmallVector<Operation *, 16> ops;
getOperation()->walk<mlir::WalkOrder::PostOrder>([&](Operation *op) {
// TODO: push back operations here
});

// Apply patterns.
if (applyOpPatternsAndFold(ops, std::move(patterns)).failed())
signalPassFailure();
}

} // namespace

namespace mlir {

std::unique_ptr<Pass> createFlattenCFGPass() {
return std::make_unique<FlattenCFGPass>();
}

} // namespace mlir
10 changes: 9 additions & 1 deletion clang/lib/CIR/FrontendAction/CIRGenAction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,8 @@ class CIRGenConsumer : public clang::ASTConsumer {
mlirMod, mlirCtx.get(), C, !feOptions.ClangIRDisableCIRVerifier,
feOptions.ClangIRLifetimeCheck, lifetimeOpts,
feOptions.ClangIRIdiomRecognizer, idiomRecognizerOpts,
feOptions.ClangIRLibOpt, libOptOpts, passOptParsingFailure)
feOptions.ClangIRLibOpt, libOptOpts, passOptParsingFailure,
action == CIRGenAction::OutputType::EmitCIRFlat)
.failed()) {
if (!passOptParsingFailure.empty())
diagnosticsEngine.Report(diag::err_drv_cir_pass_opt_parsing)
Expand Down Expand Up @@ -233,6 +234,7 @@ class CIRGenConsumer : public clang::ASTConsumer {

switch (action) {
case CIRGenAction::OutputType::EmitCIR:
case CIRGenAction::OutputType::EmitCIRFlat:
if (outputStream && mlirMod) {
// Emit remaining defaulted C++ methods
if (!feOptions.ClangIRDisableEmitCXXDefault)
Expand Down Expand Up @@ -353,6 +355,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::EmitCIRFlat:
return ci.createDefaultOutputFile(false, inFile, "cir");
case CIRGenAction::OutputType::EmitMLIR:
return ci.createDefaultOutputFile(false, inFile, "mlir");
case CIRGenAction::OutputType::EmitLLVM:
Expand Down Expand Up @@ -446,6 +450,10 @@ void EmitCIRAction::anchor() {}
EmitCIRAction::EmitCIRAction(mlir::MLIRContext *_MLIRContext)
: CIRGenAction(OutputType::EmitCIR, _MLIRContext) {}

void EmitCIRFlatAction::anchor() {}
EmitCIRFlatAction::EmitCIRFlatAction(mlir::MLIRContext *_MLIRContext)
: CIRGenAction(OutputType::EmitCIRFlat, _MLIRContext) {}

void EmitCIROnlyAction::anchor() {}
EmitCIROnlyAction::EmitCIROnlyAction(mlir::MLIRContext *_MLIRContext)
: CIRGenAction(OutputType::None, _MLIRContext) {}
Expand Down
1 change: 1 addition & 0 deletions clang/lib/CIR/Lowering/DirectToLLVM/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ add_clang_library(clangCIRLoweringDirectToLLVM
${dialect_libs}
MLIRCIR
MLIRAnalysis
MLIRCIRTransforms
MLIRIR
MLIRParser
MLIRSideEffectInterfaces
Expand Down
13 changes: 10 additions & 3 deletions clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
#include "clang/CIR/Dialect/IR/CIRDialect.h"
#include "clang/CIR/Dialect/IR/CIROpsEnums.h"
#include "clang/CIR/Dialect/IR/CIRTypes.h"
#include "clang/CIR/Dialect/Passes.h"
#include "clang/CIR/Passes.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/ArrayRef.h"
Expand Down Expand Up @@ -916,7 +917,9 @@ struct ConvertCIRToLLVMPass
}
void runOnOperation() final;

virtual StringRef getArgument() const override { return "cir-to-llvm"; }
virtual StringRef getArgument() const override {
return "cir-to-llvm-internal";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what does internal means? I don't understand why this needs to be renamed.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

internal here is a hint that this pass can't be run with any CIR input like it was before. Now the pre requirement is our new cir-flatten-cfg pass. I would deprecate createConvertCIRToLLVMPass of even remove it from the interface, but it;s up to you to decide.
And the pass need to be renamed since we register a pipeline in cir-opt with the same name - in order to guarantee any cir input is stiil valid as it was earlier - i.e. that first it will be processed by cir-flatten-cfg pass and then will go to the lowering.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would deprecate createConvertCIRToLLVMPass of even remove it from the interface, but it;s up to you to decide.

I'm down for simplifying and unifying as much as possible, but can you address it in a follow up PR.

internal here is a hint that this pass can't be run with any CIR input like it was before. Now the pre requirement is our new cir-flatten-cfg pass

Perhaps it should be named cir-flat-to-llvm, or something like that.

Since it would be wrong to run cir-flat-to-llvm without running cir-flatten-cfg, we should make cir-flat-to-llvm pass to require cir-flatten-cfg pass to be run before.

Seems like all the changes for this comment should be addressed together in another PR.

}
};

class CIRCallLowering : public mlir::OpConversionPattern<mlir::cir::CallOp> {
Expand Down Expand Up @@ -2968,15 +2971,19 @@ std::unique_ptr<mlir::Pass> createConvertCIRToLLVMPass() {
return std::make_unique<ConvertCIRToLLVMPass>();
}

void populateCIRToLLVMPasses(mlir::OpPassManager &pm) {
populateCIRPreLoweringPasses(pm);
pm.addPass(createConvertCIRToLLVMPass());
}

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

std::unique_ptr<llvm::Module>
lowerDirectlyFromCIRToLLVMIR(mlir::ModuleOp theModule, LLVMContext &llvmCtx,
bool disableVerifier) {
mlir::MLIRContext *mlirCtx = theModule.getContext();
mlir::PassManager pm(mlirCtx);

pm.addPass(createConvertCIRToLLVMPass());
populateCIRToLLVMPasses(pm);

// This is necessary to have line tables emitted and basic
// debugger working. In the future we will add proper debug information
Expand Down
6 changes: 4 additions & 2 deletions clang/lib/Driver/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,7 @@ phases::ID Driver::getFinalPhase(const DerivedArgList &DAL,
(PhaseArg = DAL.getLastArg(options::OPT__migrate)) ||
(PhaseArg = DAL.getLastArg(options::OPT__analyze)) ||
(PhaseArg = DAL.getLastArg(options::OPT_emit_cir)) ||
(PhaseArg = DAL.getLastArg(options::OPT_emit_cir_flat)) ||
(PhaseArg = DAL.getLastArg(options::OPT_emit_ast))) {
FinalPhase = phases::Compile;

Expand Down Expand Up @@ -4785,9 +4786,10 @@ Action *Driver::ConstructPhaseAction(
return C.MakeAction<MigrateJobAction>(Input, types::TY_Remap);
if (Args.hasArg(options::OPT_emit_ast))
return C.MakeAction<CompileJobAction>(Input, types::TY_AST);
if (Args.hasArg(options::OPT_emit_cir)) {
if (Args.hasArg(options::OPT_emit_cir))
return C.MakeAction<CompileJobAction>(Input, types::TY_CIR);
}
if (Args.hasArg(options::OPT_emit_cir_flat))
return C.MakeAction<CompileJobAction>(Input, types::TY_CIR_FLAT);
if (Args.hasArg(options::OPT_module_file_info))
return C.MakeAction<CompileJobAction>(Input, types::TY_ModuleFile);
if (Args.hasArg(options::OPT_verify_pch))
Expand Down
5 changes: 4 additions & 1 deletion clang/lib/Driver/ToolChains/Clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4910,7 +4910,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}

if (Args.hasArg(options::OPT_fclangir_enable) ||
Args.hasArg(options::OPT_emit_cir))
Args.hasArg(options::OPT_emit_cir) ||
Args.hasArg(options::OPT_emit_cir_flat))
CmdArgs.push_back("-fclangir-enable");

if (Args.hasArg(options::OPT_fclangir_direct_lowering))
Expand Down Expand Up @@ -5052,6 +5053,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-emit-llvm");
} else if (JA.getType() == types::TY_CIR) {
CmdArgs.push_back("-emit-cir");
} else if (JA.getType() == types::TY_CIR_FLAT) {
CmdArgs.push_back("-emit-cir-flat");
} else if (JA.getType() == types::TY_LLVM_BC ||
JA.getType() == types::TY_LTO_BC) {
// Emit textual llvm IR for AMDGPU offloading for -emit-llvm -S
Expand Down
5 changes: 4 additions & 1 deletion clang/lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2552,6 +2552,7 @@ static const auto &getFrontendActionTable() {
{frontend::EmitAssembly, OPT_S},
{frontend::EmitBC, OPT_emit_llvm_bc},
{frontend::EmitCIR, OPT_emit_cir},
{frontend::EmitCIRFlat, OPT_emit_cir_flat},
{frontend::EmitCIROnly, OPT_emit_cir_only},
{frontend::EmitMLIR, OPT_emit_mlir},
{frontend::EmitHTML, OPT_emit_html},
Expand Down Expand Up @@ -2907,7 +2908,8 @@ 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_enable) || Args.hasArg(OPT_emit_cir))
if (Args.hasArg(OPT_fclangir_enable) || Args.hasArg(OPT_emit_cir) ||
Args.hasArg(OPT_emit_cir_flat))
Opts.UseClangIRPipeline = true;

if (Args.hasArg(OPT_fclangir_direct_lowering))
Expand Down Expand Up @@ -4383,6 +4385,7 @@ static bool isStrictlyPreprocessorAction(frontend::ActionKind Action) {
case frontend::EmitAssembly:
case frontend::EmitBC:
case frontend::EmitCIR:
case frontend::EmitCIRFlat:
case frontend::EmitCIROnly:
case frontend::EmitMLIR:
case frontend::EmitHTML:
Expand Down
Loading
Loading