Skip to content

Commit 2edd897

Browse files
NuriAmariNuri Amari
andauthored
Make WriteIndexesThinBackend multi threaded (#109847)
We've noticed that for large builds executing thin-link can take on the order of 10s of minutes. We are only using a single thread to write the sharded indices and import files for each input bitcode file. While we need to ensure the index file produced lists modules in a deterministic order, that doesn't prevent us from executing the rest of the work in parallel. In this change we use a thread pool to execute as much of the backend's work as possible in parallel. In local testing on a machine with 80 cores, this change makes a thin-link for ~100,000 input files run in ~2 minutes. Without this change it takes upwards of 10 minutes. --------- Co-authored-by: Nuri Amari <[email protected]>
1 parent 2fe1f84 commit 2edd897

File tree

15 files changed

+94
-61
lines changed

15 files changed

+94
-61
lines changed

lld/COFF/LTO.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ BitcodeCompiler::BitcodeCompiler(COFFLinkerContext &c) : ctx(c) {
118118
if (ctx.config.thinLTOIndexOnly) {
119119
auto OnIndexWrite = [&](StringRef S) { thinIndices.erase(S); };
120120
backend = lto::createWriteIndexesThinBackend(
121+
llvm::hardware_concurrency(ctx.config.thinLTOJobs),
121122
std::string(ctx.config.thinLTOPrefixReplaceOld),
122123
std::string(ctx.config.thinLTOPrefixReplaceNew),
123124
std::string(ctx.config.thinLTOPrefixReplaceNativeObject),

lld/ELF/LTO.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ BitcodeCompiler::BitcodeCompiler(Ctx &ctx) : ctx(ctx) {
179179
auto onIndexWrite = [&](StringRef s) { thinIndices.erase(s); };
180180
if (ctx.arg.thinLTOIndexOnly) {
181181
backend = lto::createWriteIndexesThinBackend(
182+
llvm::hardware_concurrency(ctx.arg.thinLTOJobs),
182183
std::string(ctx.arg.thinLTOPrefixReplaceOld),
183184
std::string(ctx.arg.thinLTOPrefixReplaceNew),
184185
std::string(ctx.arg.thinLTOPrefixReplaceNativeObject),

lld/MachO/LTO.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ BitcodeCompiler::BitcodeCompiler() {
8787
auto onIndexWrite = [&](StringRef S) { thinIndices.erase(S); };
8888
if (config->thinLTOIndexOnly) {
8989
backend = lto::createWriteIndexesThinBackend(
90+
llvm::hardware_concurrency(config->thinLTOJobs),
9091
std::string(config->thinLTOPrefixReplaceOld),
9192
std::string(config->thinLTOPrefixReplaceNew),
9293
std::string(config->thinLTOPrefixReplaceNativeObject),

lld/test/COFF/thinlto-emit-imports.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
; RUN: not lld-link -entry:main -thinlto-index-only \
3636
; RUN: -thinlto-emit-imports-files %t1.obj %t2.obj %t3.obj \
3737
; RUN: -out:%t4.exe 2>&1 | FileCheck -DMSG=%errc_EACCES %s --check-prefix=ERR
38-
; ERR: cannot open {{.*}}3.obj.imports: [[MSG]]
38+
; ERR: 'cannot open {{.*}}3.obj.imports': [[MSG]]
3939

4040
; Ensure lld doesn't generate import files when thinlto-index-only is not enabled
4141
; RUN: rm -f %t1.obj.imports

lld/test/ELF/lto/thinlto-cant-write-index.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
; RUN: chmod u-w %t2.o.thinlto.bc
1111
; RUN: not ld.lld --plugin-opt=thinlto-index-only -shared %t1.o %t2.o -o /dev/null 2>&1 | FileCheck -DMSG=%errc_EACCES %s
1212
; RUN: chmod u+w %t2.o.thinlto.bc
13-
; CHECK: cannot open {{.*}}2.o.thinlto.bc: [[MSG]]
13+
; CHECK: 'cannot open {{.*}}2.o.thinlto.bc': [[MSG]]
1414

1515
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
1616
target triple = "x86_64-unknown-linux-gnu"

lld/test/ELF/lto/thinlto-emit-imports.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
; RUN: touch %t3.o.imports
1111
; RUN: chmod 400 %t3.o.imports
1212
; RUN: not ld.lld --plugin-opt=thinlto-index-only --plugin-opt=thinlto-emit-imports-files -shared %t1.o %t2.o %t3.o -o /dev/null 2>&1 | FileCheck -DMSG=%errc_EACCES %s --check-prefix=ERR
13-
; ERR: cannot open {{.*}}3.o.imports: [[MSG]]
13+
; ERR: 'cannot open {{.*}}3.o.imports': [[MSG]]
1414

1515
; RUN: rm -f %t1.o.imports %t2.o.imports rm -f %t3.o.imports
1616
; RUN: ld.lld --plugin-opt=thinlto-emit-imports-files -shared %t1.o %t2.o %t3.o -o %t4

lld/test/MachO/thinlto-emit-imports.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
; RUN: chmod 400 %t3.o.imports
3434
; RUN: not %lld --thinlto-index-only --thinlto-emit-imports-files -dylib %t1.o %t2.o %t3.o -o /dev/null 2>&1 \
3535
; RUN: | FileCheck -DMSG=%errc_EACCES %s --check-prefix=ERR
36-
; ERR: cannot open {{.*}}3.o.imports: [[MSG]]
36+
; ERR: 'cannot open {{.*}}3.o.imports': [[MSG]]
3737

3838
; Ensure lld doesn't generate import files when thinlto-index-only is not enabled
3939
; RUN: rm -f %t1.o.imports

llvm/include/llvm/LTO/LTO.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,8 @@ ThinBackend createInProcessThinBackend(ThreadPoolStrategy Parallelism,
231231
/// the objects with NativeObjectPrefix instead of NewPrefix. OnWrite is
232232
/// callback which receives module identifier and notifies LTO user that index
233233
/// file for the module (and optionally imports file) was created.
234-
ThinBackend createWriteIndexesThinBackend(std::string OldPrefix,
234+
ThinBackend createWriteIndexesThinBackend(ThreadPoolStrategy Parallelism,
235+
std::string OldPrefix,
235236
std::string NewPrefix,
236237
std::string NativeObjectPrefix,
237238
bool ShouldEmitImportsFiles,

llvm/include/llvm/Support/Threading.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,18 @@ constexpr bool llvm_is_multithreaded() { return LLVM_ENABLE_THREADS; }
188188
return S;
189189
}
190190

191+
/// Like hardware_concurrency() above, but builds a strategy
192+
/// based on the rules described for get_threadpool_strategy().
193+
/// If \p Num is invalid, returns a default strategy where one thread per
194+
/// hardware core is used.
195+
inline ThreadPoolStrategy hardware_concurrency(StringRef Num) {
196+
std::optional<ThreadPoolStrategy> S =
197+
get_threadpool_strategy(Num, hardware_concurrency());
198+
if (S)
199+
return *S;
200+
return hardware_concurrency();
201+
}
202+
191203
/// Returns an optimal thread strategy to execute specified amount of tasks.
192204
/// This strategy should prevent us from creating too many threads if we
193205
/// occasionaly have an unexpectedly small amount of tasks.

llvm/include/llvm/Transforms/IPO/FunctionImport.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -417,9 +417,9 @@ void gatherImportedSummariesForModule(
417417
GVSummaryPtrSet &DecSummaries);
418418

419419
/// Emit into \p OutputFilename the files module \p ModulePath will import from.
420-
std::error_code
421-
EmitImportsFiles(StringRef ModulePath, StringRef OutputFilename,
422-
const ModuleToSummariesForIndexTy &ModuleToSummariesForIndex);
420+
Error EmitImportsFiles(
421+
StringRef ModulePath, StringRef OutputFilename,
422+
const ModuleToSummariesForIndexTy &ModuleToSummariesForIndex);
423423

424424
/// Based on the information recorded in the summaries during global
425425
/// summary-based analysis:

llvm/lib/LTO/LTO.cpp

Lines changed: 61 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1376,15 +1376,20 @@ class lto::ThinBackendProc {
13761376
const DenseMap<StringRef, GVSummaryMapTy> &ModuleToDefinedGVSummaries;
13771377
lto::IndexWriteCallback OnWrite;
13781378
bool ShouldEmitImportsFiles;
1379+
DefaultThreadPool BackendThreadPool;
1380+
std::optional<Error> Err;
1381+
std::mutex ErrMu;
13791382

13801383
public:
13811384
ThinBackendProc(
13821385
const Config &Conf, ModuleSummaryIndex &CombinedIndex,
13831386
const DenseMap<StringRef, GVSummaryMapTy> &ModuleToDefinedGVSummaries,
1384-
lto::IndexWriteCallback OnWrite, bool ShouldEmitImportsFiles)
1387+
lto::IndexWriteCallback OnWrite, bool ShouldEmitImportsFiles,
1388+
ThreadPoolStrategy ThinLTOParallelism)
13851389
: Conf(Conf), CombinedIndex(CombinedIndex),
13861390
ModuleToDefinedGVSummaries(ModuleToDefinedGVSummaries),
1387-
OnWrite(OnWrite), ShouldEmitImportsFiles(ShouldEmitImportsFiles) {}
1391+
OnWrite(OnWrite), ShouldEmitImportsFiles(ShouldEmitImportsFiles),
1392+
BackendThreadPool(ThinLTOParallelism) {}
13881393

13891394
virtual ~ThinBackendProc() = default;
13901395
virtual Error start(
@@ -1393,13 +1398,19 @@ class lto::ThinBackendProc {
13931398
const FunctionImporter::ExportSetTy &ExportList,
13941399
const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes> &ResolvedODR,
13951400
MapVector<StringRef, BitcodeModule> &ModuleMap) = 0;
1396-
virtual Error wait() = 0;
1397-
virtual unsigned getThreadCount() = 0;
1401+
Error wait() {
1402+
BackendThreadPool.wait();
1403+
if (Err)
1404+
return std::move(*Err);
1405+
return Error::success();
1406+
}
1407+
unsigned getThreadCount() { return BackendThreadPool.getMaxConcurrency(); }
1408+
virtual bool isSensitiveToInputOrder() { return false; }
13981409

13991410
// Write sharded indices and (optionally) imports to disk
14001411
Error emitFiles(const FunctionImporter::ImportMapTy &ImportList,
14011412
llvm::StringRef ModulePath,
1402-
const std::string &NewModulePath) {
1413+
const std::string &NewModulePath) const {
14031414
ModuleToSummariesForIndexTy ModuleToSummariesForIndex;
14041415
GVSummaryPtrSet DeclarationSummaries;
14051416

@@ -1411,32 +1422,29 @@ class lto::ThinBackendProc {
14111422
raw_fd_ostream OS(NewModulePath + ".thinlto.bc", EC,
14121423
sys::fs::OpenFlags::OF_None);
14131424
if (EC)
1414-
return errorCodeToError(EC);
1425+
return createFileError("cannot open " + NewModulePath + ".thinlto.bc",
1426+
EC);
14151427

14161428
writeIndexToFile(CombinedIndex, OS, &ModuleToSummariesForIndex,
14171429
&DeclarationSummaries);
14181430

14191431
if (ShouldEmitImportsFiles) {
1420-
EC = EmitImportsFiles(ModulePath, NewModulePath + ".imports",
1421-
ModuleToSummariesForIndex);
1422-
if (EC)
1423-
return errorCodeToError(EC);
1432+
Error ImportFilesError = EmitImportsFiles(
1433+
ModulePath, NewModulePath + ".imports", ModuleToSummariesForIndex);
1434+
if (ImportFilesError)
1435+
return ImportFilesError;
14241436
}
14251437
return Error::success();
14261438
}
14271439
};
14281440

14291441
namespace {
14301442
class InProcessThinBackend : public ThinBackendProc {
1431-
DefaultThreadPool BackendThreadPool;
14321443
AddStreamFn AddStream;
14331444
FileCache Cache;
14341445
DenseSet<GlobalValue::GUID> CfiFunctionDefs;
14351446
DenseSet<GlobalValue::GUID> CfiFunctionDecls;
14361447

1437-
std::optional<Error> Err;
1438-
std::mutex ErrMu;
1439-
14401448
bool ShouldEmitIndexFiles;
14411449

14421450
public:
@@ -1447,9 +1455,9 @@ class InProcessThinBackend : public ThinBackendProc {
14471455
AddStreamFn AddStream, FileCache Cache, lto::IndexWriteCallback OnWrite,
14481456
bool ShouldEmitIndexFiles, bool ShouldEmitImportsFiles)
14491457
: ThinBackendProc(Conf, CombinedIndex, ModuleToDefinedGVSummaries,
1450-
OnWrite, ShouldEmitImportsFiles),
1451-
BackendThreadPool(ThinLTOParallelism), AddStream(std::move(AddStream)),
1452-
Cache(std::move(Cache)), ShouldEmitIndexFiles(ShouldEmitIndexFiles) {
1458+
OnWrite, ShouldEmitImportsFiles, ThinLTOParallelism),
1459+
AddStream(std::move(AddStream)), Cache(std::move(Cache)),
1460+
ShouldEmitIndexFiles(ShouldEmitIndexFiles) {
14531461
for (auto &Name : CombinedIndex.cfiFunctionDefs())
14541462
CfiFunctionDefs.insert(
14551463
GlobalValue::getGUID(GlobalValue::dropLLVMManglingEscape(Name)));
@@ -1546,18 +1554,6 @@ class InProcessThinBackend : public ThinBackendProc {
15461554
OnWrite(std::string(ModulePath));
15471555
return Error::success();
15481556
}
1549-
1550-
Error wait() override {
1551-
BackendThreadPool.wait();
1552-
if (Err)
1553-
return std::move(*Err);
1554-
else
1555-
return Error::success();
1556-
}
1557-
1558-
unsigned getThreadCount() override {
1559-
return BackendThreadPool.getMaxConcurrency();
1560-
}
15611557
};
15621558
} // end anonymous namespace
15631559

@@ -1618,12 +1614,13 @@ class WriteIndexesThinBackend : public ThinBackendProc {
16181614
public:
16191615
WriteIndexesThinBackend(
16201616
const Config &Conf, ModuleSummaryIndex &CombinedIndex,
1617+
ThreadPoolStrategy ThinLTOParallelism,
16211618
const DenseMap<StringRef, GVSummaryMapTy> &ModuleToDefinedGVSummaries,
16221619
std::string OldPrefix, std::string NewPrefix,
16231620
std::string NativeObjectPrefix, bool ShouldEmitImportsFiles,
16241621
raw_fd_ostream *LinkedObjectsFile, lto::IndexWriteCallback OnWrite)
16251622
: ThinBackendProc(Conf, CombinedIndex, ModuleToDefinedGVSummaries,
1626-
OnWrite, ShouldEmitImportsFiles),
1623+
OnWrite, ShouldEmitImportsFiles, ThinLTOParallelism),
16271624
OldPrefix(OldPrefix), NewPrefix(NewPrefix),
16281625
NativeObjectPrefix(NativeObjectPrefix),
16291626
LinkedObjectsFile(LinkedObjectsFile) {}
@@ -1635,9 +1632,11 @@ class WriteIndexesThinBackend : public ThinBackendProc {
16351632
const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes> &ResolvedODR,
16361633
MapVector<StringRef, BitcodeModule> &ModuleMap) override {
16371634
StringRef ModulePath = BM.getModuleIdentifier();
1638-
std::string NewModulePath =
1639-
getThinLTOOutputFile(ModulePath, OldPrefix, NewPrefix);
16401635

1636+
// The contents of this file may be used as input to a native link, and must
1637+
// therefore contain the processed modules in a determinstic order that
1638+
// match the order they are provided on the command line. For that reason,
1639+
// we cannot include this in the asynchronously executed lambda below.
16411640
if (LinkedObjectsFile) {
16421641
std::string ObjectPrefix =
16431642
NativeObjectPrefix.empty() ? NewPrefix : NativeObjectPrefix;
@@ -1646,33 +1645,49 @@ class WriteIndexesThinBackend : public ThinBackendProc {
16461645
*LinkedObjectsFile << LinkedObjectsFilePath << '\n';
16471646
}
16481647

1649-
if (auto E = emitFiles(ImportList, ModulePath, NewModulePath))
1650-
return E;
1648+
BackendThreadPool.async(
1649+
[this](const StringRef ModulePath,
1650+
const FunctionImporter::ImportMapTy &ImportList,
1651+
const std::string &OldPrefix, const std::string &NewPrefix) {
1652+
std::string NewModulePath =
1653+
getThinLTOOutputFile(ModulePath, OldPrefix, NewPrefix);
1654+
auto E = emitFiles(ImportList, ModulePath, NewModulePath);
1655+
if (E) {
1656+
std::unique_lock<std::mutex> L(ErrMu);
1657+
if (Err)
1658+
Err = joinErrors(std::move(*Err), std::move(E));
1659+
else
1660+
Err = std::move(E);
1661+
return;
1662+
}
1663+
},
1664+
ModulePath, ImportList, OldPrefix, NewPrefix);
16511665

16521666
if (OnWrite)
16531667
OnWrite(std::string(ModulePath));
16541668
return Error::success();
16551669
}
16561670

1657-
Error wait() override { return Error::success(); }
1658-
1659-
// WriteIndexesThinBackend should always return 1 to prevent module
1660-
// re-ordering and avoid non-determinism in the final link.
1661-
unsigned getThreadCount() override { return 1; }
1671+
bool isSensitiveToInputOrder() override {
1672+
// The order which modules are written to LinkedObjectsFile should be
1673+
// deterministic and match the order they are passed on the command line.
1674+
return true;
1675+
}
16621676
};
16631677
} // end anonymous namespace
16641678

16651679
ThinBackend lto::createWriteIndexesThinBackend(
1666-
std::string OldPrefix, std::string NewPrefix,
1667-
std::string NativeObjectPrefix, bool ShouldEmitImportsFiles,
1668-
raw_fd_ostream *LinkedObjectsFile, IndexWriteCallback OnWrite) {
1680+
ThreadPoolStrategy Parallelism, std::string OldPrefix,
1681+
std::string NewPrefix, std::string NativeObjectPrefix,
1682+
bool ShouldEmitImportsFiles, raw_fd_ostream *LinkedObjectsFile,
1683+
IndexWriteCallback OnWrite) {
16691684
return
16701685
[=](const Config &Conf, ModuleSummaryIndex &CombinedIndex,
16711686
const DenseMap<StringRef, GVSummaryMapTy> &ModuleToDefinedGVSummaries,
16721687
AddStreamFn AddStream, FileCache Cache) {
16731688
return std::make_unique<WriteIndexesThinBackend>(
1674-
Conf, CombinedIndex, ModuleToDefinedGVSummaries, OldPrefix,
1675-
NewPrefix, NativeObjectPrefix, ShouldEmitImportsFiles,
1689+
Conf, CombinedIndex, Parallelism, ModuleToDefinedGVSummaries,
1690+
OldPrefix, NewPrefix, NativeObjectPrefix, ShouldEmitImportsFiles,
16761691
LinkedObjectsFile, OnWrite);
16771692
};
16781693
}
@@ -1854,7 +1869,8 @@ Error LTO::runThinLTO(AddStreamFn AddStream, FileCache Cache,
18541869
ResolvedODR[Mod.first], ThinLTO.ModuleMap);
18551870
};
18561871

1857-
if (BackendProcess->getThreadCount() == 1) {
1872+
if (BackendProcess->getThreadCount() == 1 ||
1873+
BackendProcess->isSensitiveToInputOrder()) {
18581874
// Process the modules in the order they were provided on the
18591875
// command-line. It is important for this codepath to be used for
18601876
// WriteIndexesThinBackend, to ensure the emitted LinkedObjectsFile lists

llvm/lib/LTO/ThinLTOCodeGenerator.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -837,9 +837,8 @@ void ThinLTOCodeGenerator::emitImports(Module &TheModule, StringRef OutputName,
837837
ModuleIdentifier, ModuleToDefinedGVSummaries,
838838
ImportLists[ModuleIdentifier], ModuleToSummariesForIndex, DecSummaries);
839839

840-
std::error_code EC;
841-
if ((EC = EmitImportsFiles(ModuleIdentifier, OutputName,
842-
ModuleToSummariesForIndex)))
840+
if (Error EC = EmitImportsFiles(ModuleIdentifier, OutputName,
841+
ModuleToSummariesForIndex))
843842
report_fatal_error(Twine("Failed to open ") + OutputName +
844843
" to save imports lists\n");
845844
}

llvm/lib/Transforms/IPO/FunctionImport.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1553,20 +1553,21 @@ void llvm::gatherImportedSummariesForModule(
15531553
}
15541554

15551555
/// Emit the files \p ModulePath will import from into \p OutputFilename.
1556-
std::error_code llvm::EmitImportsFiles(
1556+
Error llvm::EmitImportsFiles(
15571557
StringRef ModulePath, StringRef OutputFilename,
15581558
const ModuleToSummariesForIndexTy &ModuleToSummariesForIndex) {
15591559
std::error_code EC;
15601560
raw_fd_ostream ImportsOS(OutputFilename, EC, sys::fs::OpenFlags::OF_Text);
15611561
if (EC)
1562-
return EC;
1562+
return createFileError("cannot open " + OutputFilename,
1563+
errorCodeToError(EC));
15631564
for (const auto &ILI : ModuleToSummariesForIndex)
15641565
// The ModuleToSummariesForIndex map includes an entry for the current
15651566
// Module (needed for writing out the index files). We don't want to
15661567
// include it in the imports file, however, so filter it out.
15671568
if (ILI.first != ModulePath)
15681569
ImportsOS << ILI.first << "\n";
1569-
return std::error_code();
1570+
return Error::success();
15701571
}
15711572

15721573
bool llvm::convertToDeclaration(GlobalValue &GV) {

llvm/tools/gold/gold-plugin.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -899,7 +899,7 @@ static std::unique_ptr<LTO> createLTO(IndexWriteCallback OnIndexWrite,
899899
std::string OldPrefix, NewPrefix;
900900
getThinLTOOldAndNewPrefix(OldPrefix, NewPrefix);
901901
Backend = createWriteIndexesThinBackend(
902-
OldPrefix, NewPrefix,
902+
llvm::hardware_concurrency(options::Parallelism) OldPrefix, NewPrefix,
903903
// TODO: Add support for optional native object path in
904904
// thinlto_prefix_replace option to match lld.
905905
/*NativeObjectPrefix=*/"", options::thinlto_emit_imports_files,

llvm/tools/llvm-lto2/llvm-lto2.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,8 @@ static int run(int argc, char **argv) {
346346

347347
ThinBackend Backend;
348348
if (ThinLTODistributedIndexes)
349-
Backend = createWriteIndexesThinBackend(/*OldPrefix=*/"",
349+
Backend = createWriteIndexesThinBackend(llvm::hardware_concurrency(Threads),
350+
/*OldPrefix=*/"",
350351
/*NewPrefix=*/"",
351352
/*NativeObjectPrefix=*/"",
352353
ThinLTOEmitImports,

0 commit comments

Comments
 (0)