Skip to content

Commit

Permalink
[CIR][Passes] Add CallConvLowering pass skeleton (llvm#642)
Browse files Browse the repository at this point in the history
This patch adds a new CallConvLowering pass that aims to lower the
calling conventions of the functions in the module. It also includes a
new Clang command line option to enable it. Also, it is considered a
part of the lowering prepare set of passes, as it is unlikely to be used
elsewhere in the pipeline.

Since this will be dealing with ABI/Target-specific information, it
requires AST info. For this reason, it can only be executed through the
clang driver or cc1 tool for now as CIR does not encode AST info.

This pass is disabled by default and can be enabled by passing the flag
`-fclangir-call-conv-lowering`. Once this pass is more mature, it should
be enabled by default as a required step to lower to LLVM Dialect.
  • Loading branch information
sitio-couto authored and lanza committed Oct 12, 2024
1 parent d0aabe7 commit 966a733
Show file tree
Hide file tree
Showing 12 changed files with 119 additions and 3 deletions.
2 changes: 1 addition & 1 deletion clang/include/clang/CIR/CIRToCIRPasses.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ mlir::LogicalResult runCIRToCIRPasses(
llvm::StringRef lifetimeOpts, bool enableIdiomRecognizer,
llvm::StringRef idiomRecognizerOpts, bool enableLibOpt,
llvm::StringRef libOptOpts, std::string &passOptParsingFailure,
bool flattenCIR, bool emitMLIR);
bool flattenCIR, bool emitMLIR, bool enableCallConvLowering);

} // namespace cir

Expand Down
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 @@ -38,6 +38,9 @@ std::unique_ptr<Pass> createLibOptPass(clang::ASTContext *astCtx);
std::unique_ptr<Pass> createFlattenCFGPass();
std::unique_ptr<Pass> createGotoSolverPass();

/// Create a pass to lower ABI-independent function definitions/calls.
std::unique_ptr<Pass> createCallConvLoweringPass();

void populateCIRPreLoweringPasses(mlir::OpPassManager &pm);

//===----------------------------------------------------------------------===//
Expand Down
11 changes: 11 additions & 0 deletions clang/include/clang/CIR/Dialect/Passes.td
Original file line number Diff line number Diff line change
Expand Up @@ -149,4 +149,15 @@ def LibOpt : Pass<"cir-lib-opt"> {
];
}

def CallConvLowering : Pass<"cir-call-conv-lowering"> {
let summary = "Handle calling conventions for CIR functions";
let description = [{
This pass lowers CIR function definitions and calls according to the
calling conventions for the target architecture. This pass is necessary
to properly lower CIR functions to LLVM IR.
}];
let constructor = "mlir::createCallConvLoweringPass()";
let dependentDialects = ["mlir::cir::CIRDialect"];
}

#endif // MLIR_DIALECT_CIR_PASSES
4 changes: 4 additions & 0 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -3037,6 +3037,10 @@ def fclangir_lib_opt : Flag<["-"], "fclangir-lib-opt">,
Visibility<[ClangOption, CC1Option]>, Group<f_Group>,
Alias<fclangir_lib_opt_EQ>,
HelpText<"Enable C/C++ library based optimizations">;
def fclangir_call_conv_lowering : Flag<["-"], "fclangir-call-conv-lowering">,
Visibility<[ClangOption, CC1Option]>, Group<f_Group>,
HelpText<"Enable ClangIR calling convention lowering">,
MarshallingInfoFlag<FrontendOpts<"ClangIREnableCallConvLowering">>;

def clangir_disable_passes : Flag<["-"], "clangir-disable-passes">,
Visibility<[ClangOption, CC1Option]>,
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 @@ -448,6 +448,9 @@ class FrontendOptions {
// Enable Clang IR library optimizations
unsigned ClangIRLibOpt : 1;

// Enable Clang IR call conv lowering pass.
unsigned ClangIREnableCallConvLowering : 1;

CodeCompleteOptions CodeCompleteOpts;

/// Specifies the output format of the AST.
Expand Down
8 changes: 7 additions & 1 deletion clang/lib/CIR/CodeGen/CIRPasses.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ mlir::LogicalResult runCIRToCIRPasses(
llvm::StringRef lifetimeOpts, bool enableIdiomRecognizer,
llvm::StringRef idiomRecognizerOpts, bool enableLibOpt,
llvm::StringRef libOptOpts, std::string &passOptParsingFailure,
bool flattenCIR, bool emitMLIR) {
bool flattenCIR, bool emitMLIR, bool enableCallConvLowering) {
mlir::PassManager pm(mlirCtx);
pm.addPass(mlir::createMergeCleanupsPass());

Expand Down Expand Up @@ -64,6 +64,12 @@ mlir::LogicalResult runCIRToCIRPasses(
}

pm.addPass(mlir::createLoweringPreparePass(&astCtx));

// FIXME(cir): This pass should run by default, but it is lacking support for
// several code bits. Once it's more mature, we should fix this.
if (enableCallConvLowering)
pm.addPass(mlir::createCallConvLoweringPass());

if (flattenCIR)
mlir::populateCIRPreLoweringPasses(pm);

Expand Down
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 @@ -11,6 +11,7 @@ add_clang_library(MLIRCIRTransforms
FlattenCFG.cpp
GotoSolver.cpp
SCFPrepare.cpp
CallConvLowering.cpp

DEPENDS
MLIRCIRPassIncGen
Expand Down
76 changes: 76 additions & 0 deletions clang/lib/CIR/Dialect/Transforms/CallConvLowering.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
//===- CallConvLowering.cpp - Rewrites functions according to call convs --===//
//
// 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
//
//===----------------------------------------------------------------------===//

#include "mlir/IR/PatternMatch.h"
#include "mlir/Pass/Pass.h"
#include "mlir/Transforms/GreedyPatternRewriteDriver.h"
#include "clang/CIR/Dialect/IR/CIRDialect.h"

#define GEN_PASS_DEF_CALLCONVLOWERING
#include "clang/CIR/Dialect/Passes.h.inc"

namespace mlir {
namespace cir {

//===----------------------------------------------------------------------===//
// Rewrite Patterns
//===----------------------------------------------------------------------===//

struct CallConvLoweringPattern : public OpRewritePattern<FuncOp> {
using OpRewritePattern<FuncOp>::OpRewritePattern;

LogicalResult matchAndRewrite(FuncOp op,
PatternRewriter &rewriter) const final {
if (!op.getAst())
return op.emitError("function has no AST information");
return success();
}
};

//===----------------------------------------------------------------------===//
// Pass
//===----------------------------------------------------------------------===//

struct CallConvLoweringPass
: ::impl::CallConvLoweringBase<CallConvLoweringPass> {
using CallConvLoweringBase::CallConvLoweringBase;

void runOnOperation() override;
StringRef getArgument() const override { return "cir-call-conv-lowering"; };
};

void populateCallConvLoweringPassPatterns(RewritePatternSet &patterns) {
patterns.add<CallConvLoweringPattern>(patterns.getContext());
}

void CallConvLoweringPass::runOnOperation() {

// Collect rewrite patterns.
RewritePatternSet patterns(&getContext());
populateCallConvLoweringPassPatterns(patterns);

// Collect operations to be considered by the pass.
SmallVector<Operation *, 16> ops;
getOperation()->walk([&](FuncOp op) { ops.push_back(op); });

// Configure rewrite to ignore new ops created during the pass.
GreedyRewriteConfig config;
config.strictMode = GreedyRewriteStrictness::ExistingOps;

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

} // namespace cir

std::unique_ptr<Pass> createCallConvLoweringPass() {
return std::make_unique<cir::CallConvLoweringPass>();
}

} // namespace mlir
3 changes: 2 additions & 1 deletion clang/lib/CIR/FrontendAction/CIRGenAction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,8 @@ class CIRGenConsumer : public clang::ASTConsumer {
feOptions.ClangIRIdiomRecognizer, idiomRecognizerOpts,
feOptions.ClangIRLibOpt, libOptOpts, passOptParsingFailure,
action == CIRGenAction::OutputType::EmitCIRFlat,
action == CIRGenAction::OutputType::EmitMLIR)
action == CIRGenAction::OutputType::EmitMLIR,
feOptions.ClangIREnableCallConvLowering)
.failed()) {
if (!passOptParsingFailure.empty())
diagnosticsEngine.Report(diag::err_drv_cir_pass_opt_parsing)
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Driver/ToolChains/Clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5150,6 +5150,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT_clangir_disable_passes))
CmdArgs.push_back("-clangir-disable-passes");

if (Args.hasArg(options::OPT_fclangir_call_conv_lowering))
CmdArgs.push_back("-fclangir-call-conv-lowering");

// ClangIR lib opt requires idiom recognizer.
if (Args.hasArg(options::OPT_fclangir_lib_opt,
options::OPT_fclangir_lib_opt_EQ)) {
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3056,6 +3056,9 @@ static bool ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
if (Args.hasArg(OPT_clangir_verify_diagnostics))
Opts.ClangIRVerifyDiags = true;

if (Args.hasArg(OPT_fclangir_call_conv_lowering))
Opts.ClangIREnableCallConvLowering = true;

if (const Arg *A = Args.getLastArg(OPT_fclangir_lifetime_check,
OPT_fclangir_lifetime_check_EQ)) {
Opts.ClangIRLifetimeCheck = true;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -fclangir-call-conv-lowering -emit-cir -mmlir --mlir-print-ir-after=cir-call-conv-lowering %s -o %t.cir
// RUN: FileCheck --input-file=%t.cir %s

// Just check if the pass is called for now.
// CHECK: module

0 comments on commit 966a733

Please sign in to comment.