Skip to content

Commit 81800d1

Browse files
[CAS] Improve the cc1 flag round trip speed when CAS is used. NFCI
Delay initialize the inputs from CAS to after ParseArgs to speed up the performance of round tripping arguments. This will save the CAS initialization/destruction costs when round tripping cc1 arguments, which is often used to modify/update cc1 arguments. rdar://134363755
1 parent 9d45b9c commit 81800d1

File tree

5 files changed

+72
-66
lines changed

5 files changed

+72
-66
lines changed

clang/include/clang/Basic/DiagnosticDriverKinds.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -716,6 +716,8 @@ def err_drv_inputs_and_include_tree : Error<
716716
"passing input files is incompatible with '-fcas-include-tree'">;
717717
def err_drv_incompatible_option_include_tree : Error<
718718
"passing incompatible option '%0' with '-fcas-include-tree'">;
719+
def err_drv_include_tree_miss_input_kind : Error<
720+
"missing '-x' input kind when using '-fcas-include-tree'">;
719721

720722
def err_drv_invalid_directx_shader_module : Error<
721723
"invalid profile : %0">;

clang/include/clang/Frontend/CompilerInstance.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -824,6 +824,9 @@ class CompilerInstance : public ModuleLoader {
824824
bool RemoveFileOnSignal, bool UseTemporary,
825825
bool CreateMissingDirectories);
826826

827+
/// Initialize inputs from CAS.
828+
void initializeDelayedInputFileFromCAS();
829+
827830
public:
828831
std::unique_ptr<raw_pwrite_stream> createNullOutputFile();
829832

clang/lib/Frontend/CompilerInstance.cpp

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,10 @@ CompilerInstance::~CompilerInstance() {
8989
void CompilerInstance::setInvocation(
9090
std::shared_ptr<CompilerInvocation> Value) {
9191
Invocation = std::move(Value);
92+
93+
/// Initialize the input from CAS when setting the invocation to preserve
94+
/// the same behavior when perform all kinds of FrontendActions.
95+
initializeDelayedInputFileFromCAS();
9296
}
9397

9498
bool CompilerInstance::shouldBuildGlobalModuleIndex() const {
@@ -1000,6 +1004,57 @@ CompilerInstance::createOutputFile(StringRef OutputPath, bool Binary,
10001004
return nullptr;
10011005
}
10021006

1007+
void CompilerInstance::initializeDelayedInputFileFromCAS() {
1008+
auto &Opts = Invocation->getFrontendOpts();
1009+
// Return if no need to initialize or already initialized.
1010+
if (Opts.CASIncludeTreeID.empty() || !Opts.Inputs.empty())
1011+
return;
1012+
1013+
// If there is include tree, initialize the inputs from CAS.
1014+
auto reportError = [&](llvm::Error &&E) {
1015+
Diagnostics->Report(diag::err_fe_unable_to_load_include_tree)
1016+
<< Opts.CASIncludeTreeID << llvm::toString(std::move(E));
1017+
};
1018+
auto CAS = Invocation->getCASOpts().getOrCreateDatabases(*Diagnostics).first;
1019+
if (!CAS)
1020+
return;
1021+
auto ID = CAS->parseID(Opts.CASIncludeTreeID);
1022+
if (!ID)
1023+
return reportError(ID.takeError());
1024+
auto Object = CAS->getReference(*ID);
1025+
if (!Object)
1026+
return reportError(llvm::cas::ObjectStore::createUnknownObjectError(*ID));
1027+
auto Root = cas::IncludeTreeRoot::get(*CAS, *Object);
1028+
if (!Root)
1029+
return reportError(Root.takeError());
1030+
auto MainTree = Root->getMainFileTree();
1031+
if (!MainTree)
1032+
return reportError(MainTree.takeError());
1033+
auto BaseFile = MainTree->getBaseFile();
1034+
if (!BaseFile)
1035+
return reportError(BaseFile.takeError());
1036+
auto FilenameBlob = BaseFile->getFilename();
1037+
if (!FilenameBlob)
1038+
return reportError(FilenameBlob.takeError());
1039+
1040+
auto InputFilename = FilenameBlob->getData();
1041+
1042+
if (InputFilename != Module::getModuleInputBufferName()) {
1043+
Opts.Inputs.emplace_back(Root->getRef(), InputFilename, Opts.DashX,
1044+
/*isSystem=*/false);
1045+
} else {
1046+
assert(Opts.ProgramAction == frontend::GenerateModule);
1047+
1048+
auto Kind = Opts.DashX.withFormat(InputKind::Source);
1049+
auto Contents = BaseFile->getContents();
1050+
if (!Contents)
1051+
return reportError(Contents.takeError());
1052+
auto Buffer = llvm::MemoryBufferRef(Contents->getData(), InputFilename);
1053+
Opts.Inputs.emplace_back(Root->getRef(), Buffer, Kind,
1054+
(bool)Opts.IsSystemModule);
1055+
}
1056+
}
1057+
10031058
Expected<std::unique_ptr<llvm::raw_pwrite_stream>>
10041059
CompilerInstance::createOutputFileImpl(StringRef OutputPath, bool Binary,
10051060
bool RemoveFileOnSignal,
@@ -1127,6 +1182,8 @@ bool CompilerInstance::ExecuteAction(FrontendAction &Act) {
11271182
if (getFrontendOpts().ShowStats || !getFrontendOpts().StatsFile.empty())
11281183
llvm::EnableStatistics(false);
11291184

1185+
initializeDelayedInputFileFromCAS();
1186+
11301187
for (const FrontendInputFile &FIF : getFrontendOpts().Inputs) {
11311188
// Reset the ID tables if we are reusing the SourceManager and parsing
11321189
// regular files.

clang/lib/Frontend/CompilerInvocation.cpp

Lines changed: 9 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -3046,50 +3046,6 @@ static void GenerateFrontendArgs(const FrontendOptions &Opts,
30463046
Consumer(Input.getFile());
30473047
}
30483048

3049-
static void determineInputFromIncludeTree(
3050-
StringRef IncludeTreeID, CASOptions &CASOpts, DiagnosticsEngine &Diags,
3051-
std::optional<cas::IncludeTreeRoot> &IncludeTree,
3052-
std::optional<llvm::MemoryBufferRef> &Buffer, StringRef &InputFilename) {
3053-
assert(!IncludeTreeID.empty());
3054-
auto reportError = [&](llvm::Error &&E) {
3055-
Diags.Report(diag::err_fe_unable_to_load_include_tree)
3056-
<< IncludeTreeID << llvm::toString(std::move(E));
3057-
};
3058-
auto CAS = CASOpts.getOrCreateDatabases(Diags).first;
3059-
if (!CAS)
3060-
return;
3061-
auto ID = CAS->parseID(IncludeTreeID);
3062-
if (!ID)
3063-
return reportError(ID.takeError());
3064-
auto Object = CAS->getReference(*ID);
3065-
if (!Object)
3066-
return reportError(llvm::cas::ObjectStore::createUnknownObjectError(*ID));
3067-
auto Root = cas::IncludeTreeRoot::get(*CAS, *Object);
3068-
if (!Root)
3069-
return reportError(Root.takeError());
3070-
auto MainTree = Root->getMainFileTree();
3071-
if (!MainTree)
3072-
return reportError(MainTree.takeError());
3073-
auto BaseFile = MainTree->getBaseFile();
3074-
if (!BaseFile)
3075-
return reportError(BaseFile.takeError());
3076-
auto FilenameBlob = BaseFile->getFilename();
3077-
if (!FilenameBlob)
3078-
return reportError(FilenameBlob.takeError());
3079-
3080-
InputFilename = FilenameBlob->getData();
3081-
IncludeTree = *Root;
3082-
3083-
if (InputFilename != Module::getModuleInputBufferName())
3084-
return;
3085-
3086-
// Handle <module-include> buffer
3087-
auto Contents = BaseFile->getContents();
3088-
if (!Contents)
3089-
return reportError(Contents.takeError());
3090-
Buffer = llvm::MemoryBufferRef(Contents->getData(), InputFilename);
3091-
}
3092-
30933049
static bool ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
30943050
CASOptions &CASOpts, DiagnosticsEngine &Diags,
30953051
bool &IsHeaderFile) {
@@ -3308,17 +3264,18 @@ static bool ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
33083264
std::vector<std::string> Inputs = Args.getAllArgValues(OPT_INPUT);
33093265
Opts.Inputs.clear();
33103266

3311-
std::optional<cas::IncludeTreeRoot> Tree;
3312-
std::optional<llvm::MemoryBufferRef> TreeInputBuffer;
33133267
if (!Opts.CASIncludeTreeID.empty()) {
3314-
if (!Inputs.empty()) {
3268+
if (!Inputs.empty())
33153269
Diags.Report(diag::err_drv_inputs_and_include_tree);
3270+
3271+
if (DashX.isUnknown()) {
3272+
Diags.Report(diag::err_drv_include_tree_miss_input_kind);
3273+
DashX = Language::C; // set to default C to avoid crashing.
33163274
}
3317-
StringRef InputFilename;
3318-
determineInputFromIncludeTree(Opts.CASIncludeTreeID, CASOpts, Diags, Tree,
3319-
TreeInputBuffer, InputFilename);
3320-
if (!InputFilename.empty())
3321-
Inputs.push_back(InputFilename.str());
3275+
3276+
// Quit early as include tree will delay input initialization.
3277+
Opts.DashX = DashX;
3278+
return Diags.getNumErrors() == NumErrorsBefore;
33223279
}
33233280

33243281
if (Inputs.empty())
@@ -3353,20 +3310,6 @@ static bool ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
33533310
Opts.Inputs.emplace_back(std::move(Inputs[i]), IK, IsSystem);
33543311
}
33553312

3356-
if (Tree) {
3357-
FrontendInputFile &InputFile = Opts.Inputs.back();
3358-
if (TreeInputBuffer) {
3359-
// This is automatically set to modulemap when building a module; revert
3360-
// to a source file for the module includes buffer.
3361-
auto Kind = InputFile.getKind().withFormat(InputKind::Source);
3362-
InputFile = FrontendInputFile(Tree->getRef(), *TreeInputBuffer, Kind,
3363-
InputFile.isSystem());
3364-
} else {
3365-
InputFile = FrontendInputFile(Tree->getRef(), InputFile.getFile(),
3366-
InputFile.getKind(), InputFile.isSystem());
3367-
}
3368-
}
3369-
33703313
Opts.DashX = DashX;
33713314

33723315
return Diags.getNumErrors() == NumErrorsBefore;

clang/test/ClangScanDeps/modules-include-tree-api-notes.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
// RUN: -fcas-path %t/cas -fsyntax-only 2>&1 | \
5252
// RUN: FileCheck %s -check-prefix=INCOMPATIBLE
5353

54+
// INCOMPATIBLE: error: missing '-x' input kind when using '-fcas-include-tree'
5455
// INCOMPATIBLE: error: passing incompatible option '-fapinotes' with '-fcas-include-tree'
5556

5657
//--- cdb.json.template

0 commit comments

Comments
 (0)