Skip to content

Commit 22bd691

Browse files
ChuanqiXu9lanza
authored andcommitted
Recommit [CIR][Pipeline] Support -fclangir-analysis-only (llvm#832)
Reland llvm#638 This was reverted due to llvm#655. I tried to address the problem in the newest commit. The changes of the PR since the last landed one includes: - Move the definition of `cir::CIRGenConsumer` to `clang/include/clang/CIRFrontendAction/CIRGenConsumer.h`, and leave its `HandleTranslationUnit` interface is left empty. So that `cir::CIRGenConsumer` won't need to depend on CodeGen any more. - Change the old definition of `cir::CIRGenConsumer` in `clang/lib/CIR/FrontendAction/CIRGenAction.cpp` and to `CIRLoweringConsumer`, inherited from `cir::CIRGenConsumer`, which implements the original `HandleTranslationUnit` interface. I feel this may improve the readability more even without my original patch.
1 parent b981867 commit 22bd691

File tree

11 files changed

+163
-3
lines changed

11 files changed

+163
-3
lines changed

clang/include/clang/CIRFrontendAction/CIRGenAction.h

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#ifndef LLVM_CLANG_CIR_CIRGENACTION_H
1010
#define LLVM_CLANG_CIR_CIRGENACTION_H
1111

12+
#include "clang/CodeGen/CodeGenAction.h"
1213
#include "clang/Frontend/FrontendAction.h"
1314
#include <memory>
1415

@@ -128,6 +129,60 @@ class EmitObjAction : public CIRGenAction {
128129
EmitObjAction(mlir::MLIRContext *mlirCtx = nullptr);
129130
};
130131

132+
// Used for -fclangir-analysis-only: use CIR analysis but still use original LLVM codegen path
133+
class AnalysisOnlyActionBase : public clang::CodeGenAction {
134+
virtual void anchor();
135+
136+
protected:
137+
std::unique_ptr<clang::ASTConsumer>
138+
CreateASTConsumer(clang::CompilerInstance &CI,
139+
llvm::StringRef InFile) override;
140+
141+
AnalysisOnlyActionBase(unsigned _Act,
142+
llvm::LLVMContext *_VMContext = nullptr);
143+
};
144+
145+
class AnalysisOnlyAndEmitAssemblyAction : public AnalysisOnlyActionBase {
146+
virtual void anchor() override;
147+
148+
public:
149+
AnalysisOnlyAndEmitAssemblyAction(llvm::LLVMContext *_VMContext = nullptr);
150+
};
151+
152+
class AnalysisOnlyAndEmitBCAction : public AnalysisOnlyActionBase {
153+
virtual void anchor() override;
154+
155+
public:
156+
AnalysisOnlyAndEmitBCAction(llvm::LLVMContext *_VMContext = nullptr);
157+
};
158+
159+
class AnalysisOnlyAndEmitLLVMAction : public AnalysisOnlyActionBase {
160+
virtual void anchor() override;
161+
162+
public:
163+
AnalysisOnlyAndEmitLLVMAction(llvm::LLVMContext *_VMContext = nullptr);
164+
};
165+
166+
class AnalysisOnlyAndEmitLLVMOnlyAction : public AnalysisOnlyActionBase {
167+
virtual void anchor() override;
168+
169+
public:
170+
AnalysisOnlyAndEmitLLVMOnlyAction(llvm::LLVMContext *_VMContext = nullptr);
171+
};
172+
173+
class AnalysisOnlyAndEmitCodeGenOnlyAction : public AnalysisOnlyActionBase {
174+
virtual void anchor() override;
175+
176+
public:
177+
AnalysisOnlyAndEmitCodeGenOnlyAction(llvm::LLVMContext *_VMContext = nullptr);
178+
};
179+
180+
class AnalysisOnlyAndEmitObjAction : public AnalysisOnlyActionBase {
181+
virtual void anchor() override;
182+
183+
public:
184+
AnalysisOnlyAndEmitObjAction(llvm::LLVMContext *_VMContext = nullptr);
185+
};
131186
} // namespace cir
132187

133188
#endif

clang/include/clang/CIRFrontendAction/CIRGenConsumer.h

Whitespace-only changes.

clang/include/clang/Driver/Options.td

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3066,6 +3066,11 @@ defm clangir_direct_lowering : BoolFOption<"clangir-direct-lowering",
30663066
FrontendOpts<"ClangIRDirectLowering">, DefaultTrue,
30673067
PosFlag<SetTrue, [], [ClangOption, CC1Option], "Lower directly from ClangIR to LLVM">,
30683068
NegFlag<SetFalse, [], [ClangOption, CC1Option], "Lower through MLIR to LLVM">>;
3069+
defm clangir_analysis_only : BoolFOption<"clangir-analysis-only",
3070+
FrontendOpts<"ClangIRAnalysisOnly">, DefaultFalse,
3071+
PosFlag<SetTrue, [], [ClangOption, CC1Option],
3072+
"Enable CIR analysis but keep traditional LLVM codegen (not through CIR)">,
3073+
NegFlag<SetFalse, [], [ClangOption, CC1Option], "">>;
30693074

30703075
def emit_cir : Flag<["-"], "emit-cir">, Visibility<[CC1Option]>,
30713076
Group<Action_Group>, HelpText<"Build ASTs and then lower to ClangIR, emit the .cir file">;

clang/include/clang/Frontend/FrontendOptions.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -454,6 +454,10 @@ class FrontendOptions {
454454
// Enable Clang IR mem2reg pass on the flat CIR.
455455
unsigned ClangIREnableMem2Reg : 1;
456456

457+
// Enable Clang IR analysis only pipeline that uses tranditional code gen
458+
// pipeline.
459+
unsigned ClangIRAnalysisOnly : 1;
460+
457461
CodeCompleteOptions CodeCompleteOpts;
458462

459463
/// Specifies the output format of the AST.
@@ -653,7 +657,8 @@ class FrontendOptions {
653657
ClangIRDisablePasses(false), ClangIRDisableCIRVerifier(false),
654658
ClangIRDisableEmitCXXDefault(false), ClangIRLifetimeCheck(false),
655659
ClangIRIdiomRecognizer(false), ClangIRLibOpt(false),
656-
TimeTraceGranularity(500), TimeTraceVerbose(false) {}
660+
ClangIRAnalysisOnly(false), TimeTraceGranularity(500),
661+
TimeTraceVerbose(false) {}
657662

658663
/// getInputKindForExtension - Return the appropriate input kind for a file
659664
/// extension. For example, "c" would return Language::C.

clang/lib/CIR/FrontendAction/CIRGenAction.cpp

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "clang/Driver/DriverDiagnostic.h"
3333
#include "clang/Frontend/CompilerInstance.h"
3434
#include "clang/Frontend/FrontendDiagnostic.h"
35+
#include "clang/Frontend/MultiplexConsumer.h"
3536
#include "clang/Lex/Preprocessor.h"
3637
#include "llvm/Bitcode/BitcodeReader.h"
3738
#include "llvm/IR/DebugInfo.h"
@@ -439,6 +440,7 @@ void CIRGenAction::ExecuteAction() {
439440
llvmModule->print(*outstream, nullptr);
440441
}
441442

443+
namespace cir {
442444
void EmitAssemblyAction::anchor() {}
443445
EmitAssemblyAction::EmitAssemblyAction(mlir::MLIRContext *_MLIRContext)
444446
: CIRGenAction(OutputType::EmitAssembly, _MLIRContext) {}
@@ -470,3 +472,52 @@ EmitBCAction::EmitBCAction(mlir::MLIRContext *_MLIRContext)
470472
void EmitObjAction::anchor() {}
471473
EmitObjAction::EmitObjAction(mlir::MLIRContext *_MLIRContext)
472474
: CIRGenAction(OutputType::EmitObj, _MLIRContext) {}
475+
} // namespace cir
476+
477+
// Used for -fclangir-analysis-only: use CIR analysis but still use original LLVM codegen path
478+
void AnalysisOnlyActionBase::anchor() {}
479+
AnalysisOnlyActionBase::AnalysisOnlyActionBase(unsigned _Act,
480+
llvm::LLVMContext *_VMContext)
481+
: clang::CodeGenAction(_Act, _VMContext) {}
482+
483+
std::unique_ptr<ASTConsumer>
484+
AnalysisOnlyActionBase::CreateASTConsumer(clang::CompilerInstance &ci,
485+
llvm::StringRef inFile) {
486+
std::vector<std::unique_ptr<ASTConsumer>> Consumers;
487+
Consumers.push_back(clang::CodeGenAction::CreateASTConsumer(ci, inFile));
488+
Consumers.push_back(std::make_unique<cir::CIRGenConsumer>(
489+
CIRGenAction::OutputType::None, ci.getDiagnostics(),
490+
&ci.getVirtualFileSystem(), ci.getHeaderSearchOpts(), ci.getCodeGenOpts(),
491+
ci.getTargetOpts(), ci.getLangOpts(), ci.getFrontendOpts(), nullptr));
492+
return std::make_unique<MultiplexConsumer>(std::move(Consumers));
493+
}
494+
495+
void AnalysisOnlyAndEmitAssemblyAction::anchor() {}
496+
AnalysisOnlyAndEmitAssemblyAction::AnalysisOnlyAndEmitAssemblyAction(
497+
llvm::LLVMContext *_VMContext)
498+
: AnalysisOnlyActionBase(Backend_EmitAssembly, _VMContext) {}
499+
500+
void AnalysisOnlyAndEmitBCAction::anchor() {}
501+
AnalysisOnlyAndEmitBCAction::AnalysisOnlyAndEmitBCAction(
502+
llvm::LLVMContext *_VMContext)
503+
: AnalysisOnlyActionBase(Backend_EmitBC, _VMContext) {}
504+
505+
void AnalysisOnlyAndEmitLLVMAction::anchor() {}
506+
AnalysisOnlyAndEmitLLVMAction::AnalysisOnlyAndEmitLLVMAction(
507+
llvm::LLVMContext *_VMContext)
508+
: AnalysisOnlyActionBase(Backend_EmitLL, _VMContext) {}
509+
510+
void AnalysisOnlyAndEmitLLVMOnlyAction::anchor() {}
511+
AnalysisOnlyAndEmitLLVMOnlyAction::AnalysisOnlyAndEmitLLVMOnlyAction(
512+
llvm::LLVMContext *_VMContext)
513+
: AnalysisOnlyActionBase(Backend_EmitNothing, _VMContext) {}
514+
515+
void AnalysisOnlyAndEmitCodeGenOnlyAction::anchor() {}
516+
AnalysisOnlyAndEmitCodeGenOnlyAction::AnalysisOnlyAndEmitCodeGenOnlyAction(
517+
llvm::LLVMContext *_VMContext)
518+
: AnalysisOnlyActionBase(Backend_EmitMCNull, _VMContext) {}
519+
520+
void AnalysisOnlyAndEmitObjAction::anchor() {}
521+
AnalysisOnlyAndEmitObjAction::AnalysisOnlyAndEmitObjAction(
522+
llvm::LLVMContext *_VMContext)
523+
: AnalysisOnlyActionBase(Backend_EmitObj, _VMContext) {}

clang/lib/Driver/ToolChains/Clang.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5164,6 +5164,15 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
51645164
CmdArgs.push_back("-fclangir-idiom-recognizer");
51655165
}
51665166

5167+
if (Args.hasArg(options::OPT_fclangir_analysis_only)) {
5168+
CmdArgs.push_back("-fclangir-analysis-only");
5169+
5170+
// TODO: We should pass some default analysis configuration here.
5171+
5172+
// TODO2: Should we emit some diagnostics if the configurations conflict
5173+
// with each other?
5174+
}
5175+
51675176
if (IsOpenMPDevice) {
51685177
// We have to pass the triple of the host if compiling for an OpenMP device.
51695178
std::string NormalizedTriple =

clang/lib/Frontend/CompilerInvocation.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3059,6 +3059,9 @@ static bool ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
30593059
if (Args.hasArg(OPT_fclangir_call_conv_lowering))
30603060
Opts.ClangIREnableCallConvLowering = true;
30613061

3062+
if (Args.hasArg(OPT_fclangir_analysis_only))
3063+
Opts.ClangIRAnalysisOnly = true;
3064+
30623065
if (const Arg *A = Args.getLastArg(OPT_fclangir_lifetime_check,
30633066
OPT_fclangir_lifetime_check_EQ)) {
30643067
Opts.ClangIRLifetimeCheck = true;

clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ CreateFrontendBaseAction(CompilerInstance &CI) {
5353

5454
auto UseCIR = CI.getFrontendOpts().UseClangIRPipeline;
5555
auto Act = CI.getFrontendOpts().ProgramAction;
56+
auto CIRAnalysisOnly = CI.getFrontendOpts().ClangIRAnalysisOnly;
5657
auto EmitsCIR = Act == EmitCIR || Act == EmitCIRFlat || Act == EmitCIROnly;
5758

5859
if (!UseCIR && EmitsCIR)
@@ -76,12 +77,16 @@ CreateFrontendBaseAction(CompilerInstance &CI) {
7677
#if CLANG_ENABLE_CIR
7778
if (UseCIR)
7879
return std::make_unique<::cir::EmitAssemblyAction>();
80+
if (CIRAnalysisOnly)
81+
return std::make_unique<::cir::AnalysisOnlyAndEmitAssemblyAction>();
7982
#endif
8083
return std::make_unique<EmitAssemblyAction>();
8184
case EmitBC: {
8285
#if CLANG_ENABLE_CIR
8386
if (UseCIR)
8487
return std::make_unique<::cir::EmitBCAction>();
88+
if (CIRAnalysisOnly)
89+
return std::make_unique<::cir::AnalysisOnlyAndEmitBCAction>();
8590
#endif
8691
return std::make_unique<EmitBCAction>();
8792
}
@@ -102,15 +107,31 @@ CreateFrontendBaseAction(CompilerInstance &CI) {
102107
#if CLANG_ENABLE_CIR
103108
if (UseCIR)
104109
return std::make_unique<::cir::EmitLLVMAction>();
110+
if (CIRAnalysisOnly)
111+
return std::make_unique<::cir::AnalysisOnlyAndEmitLLVMAction>();
105112
#endif
106113
return std::make_unique<EmitLLVMAction>();
107114
}
108-
case EmitLLVMOnly: return std::make_unique<EmitLLVMOnlyAction>();
109-
case EmitCodeGenOnly: return std::make_unique<EmitCodeGenOnlyAction>();
115+
case EmitLLVMOnly: {
116+
#if CLANG_ENABLE_CIR
117+
if (CIRAnalysisOnly)
118+
return std::make_unique<::cir::AnalysisOnlyAndEmitLLVMOnlyAction>();
119+
#endif
120+
return std::make_unique<EmitLLVMOnlyAction>();
121+
}
122+
case EmitCodeGenOnly: {
123+
#if CLANG_ENABLE_CIR
124+
if (CIRAnalysisOnly)
125+
return std::make_unique<::cir::AnalysisOnlyAndEmitLLVMOnlyAction>();
126+
#endif
127+
return std::make_unique<EmitCodeGenOnlyAction>();
128+
}
110129
case EmitObj: {
111130
#if CLANG_ENABLE_CIR
112131
if (UseCIR)
113132
return std::make_unique<::cir::EmitObjAction>();
133+
if (CIRAnalysisOnly)
134+
return std::make_unique<::cir::AnalysisOnlyAndEmitObjAction>();
114135
#endif
115136
return std::make_unique<EmitObjAction>();
116137
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// Check `-fclangir-analysis-only` would generate code correctly.
2+
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir-analysis-only -std=c++20 \
3+
// RUN: -O2 -emit-llvm %s -o - | FileCheck %s
4+
5+
extern "C" void foo() {}
6+
7+
// CHECK: define{{.*}} @foo(
8+

clang/test/CIR/Transforms/lifetime-check-agg.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -mconstructor-aliases -fclangir -clangir-disable-emit-cxx-default -fclangir-lifetime-check="history=all;remarks=all" -clangir-verify-diagnostics -emit-cir %s -o %t.cir
2+
// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -mconstructor-aliases -fclangir-analysis-only -fclangir-lifetime-check="history=all;remarks=all" %s -clangir-verify-diagnostics -emit-obj -o /dev/null
23

34
typedef enum SType {
45
INFO_ENUM_0 = 9,

0 commit comments

Comments
 (0)