Skip to content

Commit 53e5de6

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 06675fd commit 53e5de6

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
@@ -768,6 +768,8 @@ def err_drv_inputs_and_include_tree : Error<
768768
"passing input files is incompatible with '-fcas-include-tree'">;
769769
def err_drv_incompatible_option_include_tree : Error<
770770
"passing incompatible option '%0' with '-fcas-include-tree'">;
771+
def err_drv_include_tree_miss_input_kind : Error<
772+
"missing '-x' input kind when using '-fcas-include-tree'">;
771773

772774
def err_drv_invalid_directx_shader_module : Error<
773775
"invalid profile : %0">;

clang/include/clang/Frontend/CompilerInstance.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -866,6 +866,9 @@ class CompilerInstance : public ModuleLoader {
866866
bool RemoveFileOnSignal, bool UseTemporary,
867867
bool CreateMissingDirectories);
868868

869+
/// Initialize inputs from CAS.
870+
void initializeDelayedInputFileFromCAS();
871+
869872
public:
870873
std::unique_ptr<raw_pwrite_stream> createNullOutputFile();
871874

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 {
@@ -990,6 +994,57 @@ CompilerInstance::createOutputFile(StringRef OutputPath, bool Binary,
990994
return nullptr;
991995
}
992996

997+
void CompilerInstance::initializeDelayedInputFileFromCAS() {
998+
auto &Opts = Invocation->getFrontendOpts();
999+
// Return if no need to initialize or already initialized.
1000+
if (Opts.CASIncludeTreeID.empty() || !Opts.Inputs.empty())
1001+
return;
1002+
1003+
// If there is include tree, initialize the inputs from CAS.
1004+
auto reportError = [&](llvm::Error &&E) {
1005+
Diagnostics->Report(diag::err_fe_unable_to_load_include_tree)
1006+
<< Opts.CASIncludeTreeID << llvm::toString(std::move(E));
1007+
};
1008+
auto CAS = Invocation->getCASOpts().getOrCreateDatabases(*Diagnostics).first;
1009+
if (!CAS)
1010+
return;
1011+
auto ID = CAS->parseID(Opts.CASIncludeTreeID);
1012+
if (!ID)
1013+
return reportError(ID.takeError());
1014+
auto Object = CAS->getReference(*ID);
1015+
if (!Object)
1016+
return reportError(llvm::cas::ObjectStore::createUnknownObjectError(*ID));
1017+
auto Root = cas::IncludeTreeRoot::get(*CAS, *Object);
1018+
if (!Root)
1019+
return reportError(Root.takeError());
1020+
auto MainTree = Root->getMainFileTree();
1021+
if (!MainTree)
1022+
return reportError(MainTree.takeError());
1023+
auto BaseFile = MainTree->getBaseFile();
1024+
if (!BaseFile)
1025+
return reportError(BaseFile.takeError());
1026+
auto FilenameBlob = BaseFile->getFilename();
1027+
if (!FilenameBlob)
1028+
return reportError(FilenameBlob.takeError());
1029+
1030+
auto InputFilename = FilenameBlob->getData();
1031+
1032+
if (InputFilename != Module::getModuleInputBufferName()) {
1033+
Opts.Inputs.emplace_back(Root->getRef(), InputFilename, Opts.DashX,
1034+
/*isSystem=*/false);
1035+
} else {
1036+
assert(Opts.ProgramAction == frontend::GenerateModule);
1037+
1038+
auto Kind = Opts.DashX.withFormat(InputKind::Source);
1039+
auto Contents = BaseFile->getContents();
1040+
if (!Contents)
1041+
return reportError(Contents.takeError());
1042+
auto Buffer = llvm::MemoryBufferRef(Contents->getData(), InputFilename);
1043+
Opts.Inputs.emplace_back(Root->getRef(), Buffer, Kind,
1044+
(bool)Opts.IsSystemModule);
1045+
}
1046+
}
1047+
9931048
Expected<std::unique_ptr<llvm::raw_pwrite_stream>>
9941049
CompilerInstance::createOutputFileImpl(StringRef OutputPath, bool Binary,
9951050
bool RemoveFileOnSignal,
@@ -1122,6 +1177,8 @@ bool CompilerInstance::ExecuteAction(FrontendAction &Act) {
11221177
llvm::sort(getCodeGenOpts().TocDataVarsUserSpecified);
11231178
llvm::sort(getCodeGenOpts().NoTocDataVars);
11241179

1180+
initializeDelayedInputFileFromCAS();
1181+
11251182
for (const FrontendInputFile &FIF : getFrontendOpts().Inputs) {
11261183
// Reset the ID tables if we are reusing the SourceManager and parsing
11271184
// regular files.

clang/lib/Frontend/CompilerInvocation.cpp

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

3081-
static void determineInputFromIncludeTree(
3082-
StringRef IncludeTreeID, CASOptions &CASOpts, DiagnosticsEngine &Diags,
3083-
std::optional<cas::IncludeTreeRoot> &IncludeTree,
3084-
std::optional<llvm::MemoryBufferRef> &Buffer, StringRef &InputFilename) {
3085-
assert(!IncludeTreeID.empty());
3086-
auto reportError = [&](llvm::Error &&E) {
3087-
Diags.Report(diag::err_fe_unable_to_load_include_tree)
3088-
<< IncludeTreeID << llvm::toString(std::move(E));
3089-
};
3090-
auto CAS = CASOpts.getOrCreateDatabases(Diags).first;
3091-
if (!CAS)
3092-
return;
3093-
auto ID = CAS->parseID(IncludeTreeID);
3094-
if (!ID)
3095-
return reportError(ID.takeError());
3096-
auto Object = CAS->getReference(*ID);
3097-
if (!Object)
3098-
return reportError(llvm::cas::ObjectStore::createUnknownObjectError(*ID));
3099-
auto Root = cas::IncludeTreeRoot::get(*CAS, *Object);
3100-
if (!Root)
3101-
return reportError(Root.takeError());
3102-
auto MainTree = Root->getMainFileTree();
3103-
if (!MainTree)
3104-
return reportError(MainTree.takeError());
3105-
auto BaseFile = MainTree->getBaseFile();
3106-
if (!BaseFile)
3107-
return reportError(BaseFile.takeError());
3108-
auto FilenameBlob = BaseFile->getFilename();
3109-
if (!FilenameBlob)
3110-
return reportError(FilenameBlob.takeError());
3111-
3112-
InputFilename = FilenameBlob->getData();
3113-
IncludeTree = *Root;
3114-
3115-
if (InputFilename != Module::getModuleInputBufferName())
3116-
return;
3117-
3118-
// Handle <module-include> buffer
3119-
auto Contents = BaseFile->getContents();
3120-
if (!Contents)
3121-
return reportError(Contents.takeError());
3122-
Buffer = llvm::MemoryBufferRef(Contents->getData(), InputFilename);
3123-
}
3124-
31253081
static bool ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
31263082
CASOptions &CASOpts, DiagnosticsEngine &Diags,
31273083
bool &IsHeaderFile) {
@@ -3367,17 +3323,18 @@ static bool ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
33673323
std::vector<std::string> Inputs = Args.getAllArgValues(OPT_INPUT);
33683324
Opts.Inputs.clear();
33693325

3370-
std::optional<cas::IncludeTreeRoot> Tree;
3371-
std::optional<llvm::MemoryBufferRef> TreeInputBuffer;
33723326
if (!Opts.CASIncludeTreeID.empty()) {
3373-
if (!Inputs.empty()) {
3327+
if (!Inputs.empty())
33743328
Diags.Report(diag::err_drv_inputs_and_include_tree);
3329+
3330+
if (DashX.isUnknown()) {
3331+
Diags.Report(diag::err_drv_include_tree_miss_input_kind);
3332+
DashX = Language::C; // set to default C to avoid crashing.
33753333
}
3376-
StringRef InputFilename;
3377-
determineInputFromIncludeTree(Opts.CASIncludeTreeID, CASOpts, Diags, Tree,
3378-
TreeInputBuffer, InputFilename);
3379-
if (!InputFilename.empty())
3380-
Inputs.push_back(InputFilename.str());
3334+
3335+
// Quit early as include tree will delay input initialization.
3336+
Opts.DashX = DashX;
3337+
return Diags.getNumErrors() == NumErrorsBefore;
33813338
}
33823339

33833340
if (Inputs.empty())
@@ -3412,20 +3369,6 @@ static bool ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
34123369
Opts.Inputs.emplace_back(std::move(Inputs[i]), IK, IsSystem);
34133370
}
34143371

3415-
if (Tree) {
3416-
FrontendInputFile &InputFile = Opts.Inputs.back();
3417-
if (TreeInputBuffer) {
3418-
// This is automatically set to modulemap when building a module; revert
3419-
// to a source file for the module includes buffer.
3420-
auto Kind = InputFile.getKind().withFormat(InputKind::Source);
3421-
InputFile = FrontendInputFile(Tree->getRef(), *TreeInputBuffer, Kind,
3422-
InputFile.isSystem());
3423-
} else {
3424-
InputFile = FrontendInputFile(Tree->getRef(), InputFile.getFile(),
3425-
InputFile.getKind(), InputFile.isSystem());
3426-
}
3427-
}
3428-
34293372
Opts.DashX = DashX;
34303373

34313374
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)