Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 3 additions & 7 deletions clang/include/clang/CodeGen/BackendUtil.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,9 @@ class FileSystem;
} // namespace llvm

namespace clang {
class CompilerInstance;
class DiagnosticsEngine;
class HeaderSearchOptions;
class CodeGenOptions;
class TargetOptions;
class LangOptions;
class BackendConsumer;

enum BackendAction {
Expand All @@ -41,10 +39,8 @@ enum BackendAction {
Backend_EmitObj ///< Emit native object files
};

void EmitBackendOutput(DiagnosticsEngine &Diags, const HeaderSearchOptions &,
const CodeGenOptions &CGOpts, const TargetOptions &TOpts,
const LangOptions &LOpts, StringRef TDesc,
llvm::Module *M, BackendAction Action,
void emitBackendOutput(CompilerInstance &CI, StringRef TDesc, llvm::Module *M,
BackendAction Action,
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
std::unique_ptr<raw_pwrite_stream> OS,
BackendConsumer *BC = nullptr);
Expand Down
4 changes: 3 additions & 1 deletion clang/include/clang/Frontend/CompilerInstance.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ class CompilerInstance : public ModuleLoader {
std::unique_ptr<Sema> TheSema;

/// The frontend timer group.
std::unique_ptr<llvm::TimerGroup> FrontendTimerGroup;
std::unique_ptr<llvm::TimerGroup> timerGroup;

/// The frontend timer.
std::unique_ptr<llvm::Timer> FrontendTimer;
Expand Down Expand Up @@ -630,6 +630,8 @@ class CompilerInstance : public ModuleLoader {
/// @name Frontend timer
/// @{

llvm::TimerGroup &getTimerGroup() const { return *timerGroup; }

bool hasFrontendTimer() const { return (bool)FrontendTimer; }

llvm::Timer &getFrontendTimer() const {
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/CodeGen/BackendConsumer.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ class BackendConsumer : public ASTConsumer {
using LinkModule = CodeGenAction::LinkModule;

virtual void anchor();
CompilerInstance &CI;
DiagnosticsEngine &Diags;
const HeaderSearchOptions &HeaderSearchOpts;
const CodeGenOptions &CodeGenOpts;
const TargetOptions &TargetOpts;
const LangOptions &LangOpts;
Expand Down Expand Up @@ -70,7 +70,7 @@ class BackendConsumer : public ASTConsumer {
llvm::Module *CurLinkModule = nullptr;

public:
BackendConsumer(const CompilerInstance &CI, BackendAction Action,
BackendConsumer(CompilerInstance &CI, BackendAction Action,
IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
llvm::LLVMContext &C, SmallVector<LinkModule, 4> LinkModules,
StringRef InFile, std::unique_ptr<raw_pwrite_stream> OS,
Expand Down
44 changes: 29 additions & 15 deletions clang/lib/CodeGen/BackendUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Frontend/Utils.h"
#include "clang/Lex/HeaderSearchOptions.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Analysis/GlobalsModRef.h"
Expand Down Expand Up @@ -137,8 +138,6 @@ class EmitAssemblyHelper {
llvm::Module *TheModule;
IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS;

Timer CodeGenerationTime;

std::unique_ptr<raw_pwrite_stream> OS;

Triple TargetTriple;
Expand Down Expand Up @@ -211,7 +210,6 @@ class EmitAssemblyHelper {
IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS)
: Diags(_Diags), HSOpts(HeaderSearchOpts), CodeGenOpts(CGOpts),
TargetOpts(TOpts), LangOpts(LOpts), TheModule(M), VFS(std::move(VFS)),
CodeGenerationTime("codegen", "Code Generation Time"),
TargetTriple(TheModule->getTargetTriple()) {}

~EmitAssemblyHelper() {
Expand All @@ -222,8 +220,8 @@ class EmitAssemblyHelper {
std::unique_ptr<TargetMachine> TM;

// Emit output using the new pass manager for the optimization pipeline.
void EmitAssembly(BackendAction Action, std::unique_ptr<raw_pwrite_stream> OS,
BackendConsumer *BC);
void emitAssembly(const CompilerInstance &CI, BackendAction Action,
std::unique_ptr<raw_pwrite_stream> OS, BackendConsumer *BC);
};
} // namespace

Expand Down Expand Up @@ -1212,10 +1210,10 @@ void EmitAssemblyHelper::RunCodegenPipeline(
}
}

void EmitAssemblyHelper::EmitAssembly(BackendAction Action,
void EmitAssemblyHelper::emitAssembly(const CompilerInstance &CI,
BackendAction Action,
std::unique_ptr<raw_pwrite_stream> OS,
BackendConsumer *BC) {
TimeRegion Region(CodeGenOpts.TimePasses ? &CodeGenerationTime : nullptr);
setCommandLineOpts(CodeGenOpts);

bool RequiresCodeGen = actionRequiresCodeGen(Action);
Expand Down Expand Up @@ -1346,14 +1344,30 @@ static void runThinLTOBackend(
}
}

void clang::EmitBackendOutput(
DiagnosticsEngine &Diags, const HeaderSearchOptions &HeaderOpts,
const CodeGenOptions &CGOpts, const clang::TargetOptions &TOpts,
const LangOptions &LOpts, StringRef TDesc, llvm::Module *M,
BackendAction Action, IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
std::unique_ptr<raw_pwrite_stream> OS, BackendConsumer *BC) {

void clang::emitBackendOutput(CompilerInstance &CI, StringRef TDesc,
llvm::Module *M, BackendAction Action,
IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
std::unique_ptr<raw_pwrite_stream> OS,
BackendConsumer *BC) {
llvm::TimeTraceScope TimeScope("Backend");
Copy link
Collaborator

Choose a reason for hiding this comment

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

I hope there is a way to unify those two timers, at least the scope of them.

DiagnosticsEngine &Diags = CI.getDiagnostics();
const auto &HeaderOpts = CI.getHeaderSearchOpts();
const auto &CGOpts = CI.getCodeGenOpts();
const auto &TOpts = CI.getTargetOpts();
const auto &LOpts = CI.getLangOpts();

Timer timer;
if (CGOpts.TimePasses) {
CI.getFrontendTimer().stopTimer();
Copy link
Collaborator

Choose a reason for hiding this comment

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

This stopTimer() is a bit suspicious. Where is the start timer? There are assertions to make sure that start/stop is balanced. I also believe you can enter this function without ever doing frontend?

Copy link
Member Author

@MaskRay MaskRay Jan 9, 2025

Choose a reason for hiding this comment

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

"Clang front-end" has a TimeRegion in clang/lib/Frontend/FrontendAction.cpp.

This PR repurposes the "Clang front-end timer" (which included backend time) to remove the backend part. If we don't stop "Clang front-end" here, "Clang front-end" and "Backend" in the same group would double count the time... After this PR, "Clang front-end" is more like preprocessing, lexing, parsing, and semantic analysis.

I recalled another complaint https://aras-p.info/blog/2019/01/12/Investigating-compile-times-and-Clang-ftime-report/

“Clang front-end time report” seems to be time for “everything”, not just the frontend (Clang frontend, LLVM backend, and whatever else it did).

Copy link
Collaborator

Choose a reason for hiding this comment

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

I see. I like the proposed time breakdown. This deserves a release note I think?

timer.init("backend", "Backend", CI.getTimerGroup());
timer.startTimer();
}
auto _ = llvm::make_scope_exit([&] {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Just use llvm::TimeRegion?

Copy link
Member Author

Choose a reason for hiding this comment

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

emitBackendOutput is a subset of clang/lib/Frontend/FrontendAction.cpp:1074 llvm::TimeRegion Timer(CI.getFrontendTimer()). We have to start getFrontendTimer() after Backend stops (required by TimeRegion).

Since we both stop a timer and start a timer, I resort to a make_scope_exit.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Is it better to relocate the Frontend Timer TimeRegion instead of doing a stop and start here? I am not sure if frontend should count the time after backend (even if it isn't much time).

Copy link
Member Author

Choose a reason for hiding this comment

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

This is difficult.... Parsing and codegen are interleaved in clang.ParseAST calls BackendConsumer::HandleTopLevelDecl and BackendConsumer::HandleTranslationUnit (call stack, which do code generation.

I've introduced yieldTo and changed the timers. Updated the description.

if (!CGOpts.TimePasses)
return;
timer.stopTimer();
CI.getFrontendTimer().startTimer();
});

std::unique_ptr<llvm::Module> EmptyModule;
if (!CGOpts.ThinLTOIndexFile.empty()) {
Expand Down Expand Up @@ -1394,7 +1408,7 @@ void clang::EmitBackendOutput(
}

EmitAssemblyHelper AsmHelper(Diags, HeaderOpts, CGOpts, TOpts, LOpts, M, VFS);
AsmHelper.EmitAssembly(Action, std::move(OS), BC);
AsmHelper.emitAssembly(CI, Action, std::move(OS), BC);

// Verify clang's TargetInfo DataLayout against the LLVM TargetMachine's
// DataLayout.
Expand Down
69 changes: 35 additions & 34 deletions clang/lib/CodeGen/CodeGenAction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,23 +105,26 @@ static void reportOptRecordError(Error E, DiagnosticsEngine &Diags,
});
}

BackendConsumer::BackendConsumer(
const CompilerInstance &CI, BackendAction Action,
IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS, LLVMContext &C,
SmallVector<LinkModule, 4> LinkModules, StringRef InFile,
std::unique_ptr<raw_pwrite_stream> OS, CoverageSourceInfo *CoverageInfo,
llvm::Module *CurLinkModule)
: Diags(CI.getDiagnostics()), HeaderSearchOpts(CI.getHeaderSearchOpts()),
CodeGenOpts(CI.getCodeGenOpts()), TargetOpts(CI.getTargetOpts()),
LangOpts(CI.getLangOpts()), AsmOutStream(std::move(OS)), FS(VFS),
LLVMIRGeneration("irgen", "LLVM IR Generation Time"), Action(Action),
BackendConsumer::BackendConsumer(CompilerInstance &CI, BackendAction Action,
IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
LLVMContext &C,
SmallVector<LinkModule, 4> LinkModules,
StringRef InFile,
std::unique_ptr<raw_pwrite_stream> OS,
CoverageSourceInfo *CoverageInfo,
llvm::Module *CurLinkModule)
: CI(CI), Diags(CI.getDiagnostics()), CodeGenOpts(CI.getCodeGenOpts()),
TargetOpts(CI.getTargetOpts()), LangOpts(CI.getLangOpts()),
AsmOutStream(std::move(OS)), FS(VFS), Action(Action),
Gen(CreateLLVMCodeGen(Diags, InFile, std::move(VFS),
CI.getHeaderSearchOpts(), CI.getPreprocessorOpts(),
CI.getCodeGenOpts(), C, CoverageInfo)),
LinkModules(std::move(LinkModules)), CurLinkModule(CurLinkModule) {
TimerIsEnabled = CodeGenOpts.TimePasses;
llvm::TimePassesIsEnabled = CodeGenOpts.TimePasses;
llvm::TimePassesPerRun = CodeGenOpts.TimePassesPerRun;
if (CodeGenOpts.TimePasses)
LLVMIRGeneration.init("irgen", "LLVM IR Generation", CI.getTimerGroup());
}

llvm::Module* BackendConsumer::getModule() const {
Expand Down Expand Up @@ -160,18 +163,16 @@ bool BackendConsumer::HandleTopLevelDecl(DeclGroupRef D) {
"LLVM IR generation of declaration");

// Recurse.
if (TimerIsEnabled) {
LLVMIRGenerationRefCount += 1;
if (LLVMIRGenerationRefCount == 1)
LLVMIRGeneration.startTimer();
if (TimerIsEnabled && !LLVMIRGenerationRefCount++) {
CI.getFrontendTimer().stopTimer();
LLVMIRGeneration.startTimer();
}

Gen->HandleTopLevelDecl(D);

if (TimerIsEnabled) {
LLVMIRGenerationRefCount -= 1;
if (LLVMIRGenerationRefCount == 0)
LLVMIRGeneration.stopTimer();
if (TimerIsEnabled && !--LLVMIRGenerationRefCount) {
LLVMIRGeneration.stopTimer();
CI.getFrontendTimer().startTimer();
}

return true;
Expand All @@ -181,13 +182,17 @@ void BackendConsumer::HandleInlineFunctionDefinition(FunctionDecl *D) {
PrettyStackTraceDecl CrashInfo(D, SourceLocation(),
Context->getSourceManager(),
"LLVM IR generation of inline function");
if (TimerIsEnabled)
if (TimerIsEnabled) {
CI.getFrontendTimer().stopTimer();
LLVMIRGeneration.startTimer();
}

Gen->HandleInlineFunctionDefinition(D);

if (TimerIsEnabled)
if (TimerIsEnabled) {
LLVMIRGeneration.stopTimer();
CI.getFrontendTimer().startTimer();
}
}

void BackendConsumer::HandleInterestingDecl(DeclGroupRef D) {
Expand Down Expand Up @@ -237,18 +242,16 @@ void BackendConsumer::HandleTranslationUnit(ASTContext &C) {
{
llvm::TimeTraceScope TimeScope("Frontend");
PrettyStackTraceString CrashInfo("Per-file LLVM IR generation");
if (TimerIsEnabled) {
LLVMIRGenerationRefCount += 1;
if (LLVMIRGenerationRefCount == 1)
LLVMIRGeneration.startTimer();
if (TimerIsEnabled && !LLVMIRGenerationRefCount++) {
CI.getFrontendTimer().stopTimer();
LLVMIRGeneration.startTimer();
}

Gen->HandleTranslationUnit(C);

if (TimerIsEnabled) {
LLVMIRGenerationRefCount -= 1;
if (LLVMIRGenerationRefCount == 0)
LLVMIRGeneration.stopTimer();
if (TimerIsEnabled && !--LLVMIRGenerationRefCount) {
LLVMIRGeneration.stopTimer();
CI.getFrontendTimer().startTimer();
}

IRGenFinished = true;
Expand Down Expand Up @@ -321,8 +324,7 @@ void BackendConsumer::HandleTranslationUnit(ASTContext &C) {

EmbedBitcode(getModule(), CodeGenOpts, llvm::MemoryBufferRef());

EmitBackendOutput(Diags, HeaderSearchOpts, CodeGenOpts, TargetOpts, LangOpts,
C.getTargetInfo().getDataLayoutString(), getModule(),
emitBackendOutput(CI, C.getTargetInfo().getDataLayoutString(), getModule(),
Action, FS, std::move(AsmOutStream), this);

Ctx.setDiagnosticHandler(std::move(OldDiagnosticHandler));
Expand Down Expand Up @@ -1183,10 +1185,9 @@ void CodeGenAction::ExecuteAction() {
std::unique_ptr<llvm::ToolOutputFile> OptRecordFile =
std::move(*OptRecordFileOrErr);

EmitBackendOutput(
Diagnostics, CI.getHeaderSearchOpts(), CodeGenOpts, TargetOpts,
CI.getLangOpts(), CI.getTarget().getDataLayoutString(), TheModule.get(),
BA, CI.getFileManager().getVirtualFileSystemPtr(), std::move(OS));
emitBackendOutput(CI, CI.getTarget().getDataLayoutString(), TheModule.get(),
BA, CI.getFileManager().getVirtualFileSystemPtr(),
std::move(OS));
if (OptRecordFile)
OptRecordFile->keep();
}
Expand Down
15 changes: 7 additions & 8 deletions clang/lib/CodeGen/ObjectFilePCHContainerWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ using namespace clang;

namespace {
class PCHContainerGenerator : public ASTConsumer {
CompilerInstance &CI;
DiagnosticsEngine &Diags;
const std::string MainFileName;
const std::string OutputFileName;
Expand Down Expand Up @@ -139,7 +140,7 @@ class PCHContainerGenerator : public ASTConsumer {
const std::string &OutputFileName,
std::unique_ptr<raw_pwrite_stream> OS,
std::shared_ptr<PCHBuffer> Buffer)
: Diags(CI.getDiagnostics()), MainFileName(MainFileName),
: CI(CI), Diags(CI.getDiagnostics()), MainFileName(MainFileName),
OutputFileName(OutputFileName), Ctx(nullptr),
MMap(CI.getPreprocessor().getHeaderSearchInfo().getModuleMap()),
FS(&CI.getVirtualFileSystem()),
Expand Down Expand Up @@ -317,19 +318,17 @@ class PCHContainerGenerator : public ASTConsumer {
LLVM_DEBUG({
// Print the IR for the PCH container to the debug output.
llvm::SmallString<0> Buffer;
clang::EmitBackendOutput(
Diags, HeaderSearchOpts, CodeGenOpts, TargetOpts, LangOpts,
Ctx.getTargetInfo().getDataLayoutString(), M.get(),
clang::emitBackendOutput(
CI, Ctx.getTargetInfo().getDataLayoutString(), M.get(),
BackendAction::Backend_EmitLL, FS,
std::make_unique<llvm::raw_svector_ostream>(Buffer));
llvm::dbgs() << Buffer;
});

// Use the LLVM backend to emit the pch container.
clang::EmitBackendOutput(Diags, HeaderSearchOpts, CodeGenOpts, TargetOpts,
LangOpts,
Ctx.getTargetInfo().getDataLayoutString(), M.get(),
BackendAction::Backend_EmitObj, FS, std::move(OS));
clang::emitBackendOutput(CI, Ctx.getTargetInfo().getDataLayoutString(),
M.get(), BackendAction::Backend_EmitObj, FS,
std::move(OS));

// Free the memory for the temporary buffer.
llvm::SmallVector<char, 0> Empty;
Expand Down
23 changes: 10 additions & 13 deletions clang/lib/Frontend/CompilerInstance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -722,11 +722,9 @@ void CompilerInstance::createCodeCompletionConsumer() {
}

void CompilerInstance::createFrontendTimer() {
FrontendTimerGroup.reset(
new llvm::TimerGroup("frontend", "Clang front-end time report"));
timerGroup.reset(new llvm::TimerGroup("clang", "Clang time report"));
FrontendTimer.reset(
new llvm::Timer("frontend", "Clang front-end timer",
*FrontendTimerGroup));
new llvm::Timer("frontend", "Clang front-end", *timerGroup));
}

CodeCompleteConsumer *
Expand Down Expand Up @@ -1726,10 +1724,9 @@ void CompilerInstance::createASTReader() {
const FrontendOptions &FEOpts = getFrontendOpts();
std::unique_ptr<llvm::Timer> ReadTimer;

if (FrontendTimerGroup)
if (timerGroup)
ReadTimer = std::make_unique<llvm::Timer>("reading_modules",
"Reading modules",
*FrontendTimerGroup);
"Reading modules", *timerGroup);
TheASTReader = new ASTReader(
getPreprocessor(), getModuleCache(), &getASTContext(),
getPCHContainerReader(), getFrontendOpts().ModuleFileExtensions,
Expand Down Expand Up @@ -1758,10 +1755,10 @@ void CompilerInstance::createASTReader() {
bool CompilerInstance::loadModuleFile(
StringRef FileName, serialization::ModuleFile *&LoadedModuleFile) {
llvm::Timer Timer;
if (FrontendTimerGroup)
if (timerGroup)
Timer.init("preloading." + FileName.str(), "Preloading " + FileName.str(),
*FrontendTimerGroup);
llvm::TimeRegion TimeLoading(FrontendTimerGroup ? &Timer : nullptr);
*timerGroup);
llvm::TimeRegion TimeLoading(timerGroup ? &Timer : nullptr);

// If we don't already have an ASTReader, create one now.
if (!TheASTReader)
Expand Down Expand Up @@ -1892,10 +1889,10 @@ ModuleLoadResult CompilerInstance::findOrCompileModuleAndReadAST(

// Time how long it takes to load the module.
llvm::Timer Timer;
if (FrontendTimerGroup)
if (timerGroup)
Timer.init("loading." + ModuleFilename, "Loading " + ModuleFilename,
*FrontendTimerGroup);
llvm::TimeRegion TimeLoading(FrontendTimerGroup ? &Timer : nullptr);
*timerGroup);
llvm::TimeRegion TimeLoading(timerGroup ? &Timer : nullptr);
llvm::TimeTraceScope TimeScope("Module Load", ModuleName);

// Try to load the module file. If we are not trying to load from the
Expand Down
Loading
Loading