@@ -1376,15 +1376,20 @@ class lto::ThinBackendProc {
1376
1376
const DenseMap<StringRef, GVSummaryMapTy> &ModuleToDefinedGVSummaries;
1377
1377
lto::IndexWriteCallback OnWrite;
1378
1378
bool ShouldEmitImportsFiles;
1379
+ DefaultThreadPool BackendThreadPool;
1380
+ std::optional<Error> Err;
1381
+ std::mutex ErrMu;
1379
1382
1380
1383
public:
1381
1384
ThinBackendProc (
1382
1385
const Config &Conf, ModuleSummaryIndex &CombinedIndex,
1383
1386
const DenseMap<StringRef, GVSummaryMapTy> &ModuleToDefinedGVSummaries,
1384
- lto::IndexWriteCallback OnWrite, bool ShouldEmitImportsFiles)
1387
+ lto::IndexWriteCallback OnWrite, bool ShouldEmitImportsFiles,
1388
+ ThreadPoolStrategy ThinLTOParallelism)
1385
1389
: Conf(Conf), CombinedIndex(CombinedIndex),
1386
1390
ModuleToDefinedGVSummaries (ModuleToDefinedGVSummaries),
1387
- OnWrite(OnWrite), ShouldEmitImportsFiles(ShouldEmitImportsFiles) {}
1391
+ OnWrite(OnWrite), ShouldEmitImportsFiles(ShouldEmitImportsFiles),
1392
+ BackendThreadPool(ThinLTOParallelism) {}
1388
1393
1389
1394
virtual ~ThinBackendProc () = default ;
1390
1395
virtual Error start (
@@ -1393,13 +1398,19 @@ class lto::ThinBackendProc {
1393
1398
const FunctionImporter::ExportSetTy &ExportList,
1394
1399
const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes> &ResolvedODR,
1395
1400
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 ; }
1398
1409
1399
1410
// Write sharded indices and (optionally) imports to disk
1400
1411
Error emitFiles (const FunctionImporter::ImportMapTy &ImportList,
1401
1412
llvm::StringRef ModulePath,
1402
- const std::string &NewModulePath) {
1413
+ const std::string &NewModulePath) const {
1403
1414
ModuleToSummariesForIndexTy ModuleToSummariesForIndex;
1404
1415
GVSummaryPtrSet DeclarationSummaries;
1405
1416
@@ -1411,32 +1422,29 @@ class lto::ThinBackendProc {
1411
1422
raw_fd_ostream OS (NewModulePath + " .thinlto.bc" , EC,
1412
1423
sys::fs::OpenFlags::OF_None);
1413
1424
if (EC)
1414
- return errorCodeToError (EC);
1425
+ return createFileError (" cannot open " + NewModulePath + " .thinlto.bc" ,
1426
+ EC);
1415
1427
1416
1428
writeIndexToFile (CombinedIndex, OS, &ModuleToSummariesForIndex,
1417
1429
&DeclarationSummaries);
1418
1430
1419
1431
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 ;
1424
1436
}
1425
1437
return Error::success ();
1426
1438
}
1427
1439
};
1428
1440
1429
1441
namespace {
1430
1442
class InProcessThinBackend : public ThinBackendProc {
1431
- DefaultThreadPool BackendThreadPool;
1432
1443
AddStreamFn AddStream;
1433
1444
FileCache Cache;
1434
1445
DenseSet<GlobalValue::GUID> CfiFunctionDefs;
1435
1446
DenseSet<GlobalValue::GUID> CfiFunctionDecls;
1436
1447
1437
- std::optional<Error> Err;
1438
- std::mutex ErrMu;
1439
-
1440
1448
bool ShouldEmitIndexFiles;
1441
1449
1442
1450
public:
@@ -1447,9 +1455,9 @@ class InProcessThinBackend : public ThinBackendProc {
1447
1455
AddStreamFn AddStream, FileCache Cache, lto::IndexWriteCallback OnWrite,
1448
1456
bool ShouldEmitIndexFiles, bool ShouldEmitImportsFiles)
1449
1457
: 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) {
1453
1461
for (auto &Name : CombinedIndex.cfiFunctionDefs ())
1454
1462
CfiFunctionDefs.insert (
1455
1463
GlobalValue::getGUID (GlobalValue::dropLLVMManglingEscape (Name)));
@@ -1546,18 +1554,6 @@ class InProcessThinBackend : public ThinBackendProc {
1546
1554
OnWrite (std::string (ModulePath));
1547
1555
return Error::success ();
1548
1556
}
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
- }
1561
1557
};
1562
1558
} // end anonymous namespace
1563
1559
@@ -1618,12 +1614,13 @@ class WriteIndexesThinBackend : public ThinBackendProc {
1618
1614
public:
1619
1615
WriteIndexesThinBackend (
1620
1616
const Config &Conf, ModuleSummaryIndex &CombinedIndex,
1617
+ ThreadPoolStrategy ThinLTOParallelism,
1621
1618
const DenseMap<StringRef, GVSummaryMapTy> &ModuleToDefinedGVSummaries,
1622
1619
std::string OldPrefix, std::string NewPrefix,
1623
1620
std::string NativeObjectPrefix, bool ShouldEmitImportsFiles,
1624
1621
raw_fd_ostream *LinkedObjectsFile, lto::IndexWriteCallback OnWrite)
1625
1622
: ThinBackendProc(Conf, CombinedIndex, ModuleToDefinedGVSummaries,
1626
- OnWrite, ShouldEmitImportsFiles),
1623
+ OnWrite, ShouldEmitImportsFiles, ThinLTOParallelism ),
1627
1624
OldPrefix (OldPrefix), NewPrefix(NewPrefix),
1628
1625
NativeObjectPrefix(NativeObjectPrefix),
1629
1626
LinkedObjectsFile(LinkedObjectsFile) {}
@@ -1635,9 +1632,11 @@ class WriteIndexesThinBackend : public ThinBackendProc {
1635
1632
const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes> &ResolvedODR,
1636
1633
MapVector<StringRef, BitcodeModule> &ModuleMap) override {
1637
1634
StringRef ModulePath = BM.getModuleIdentifier ();
1638
- std::string NewModulePath =
1639
- getThinLTOOutputFile (ModulePath, OldPrefix, NewPrefix);
1640
1635
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.
1641
1640
if (LinkedObjectsFile) {
1642
1641
std::string ObjectPrefix =
1643
1642
NativeObjectPrefix.empty () ? NewPrefix : NativeObjectPrefix;
@@ -1646,33 +1645,49 @@ class WriteIndexesThinBackend : public ThinBackendProc {
1646
1645
*LinkedObjectsFile << LinkedObjectsFilePath << ' \n ' ;
1647
1646
}
1648
1647
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);
1651
1665
1652
1666
if (OnWrite)
1653
1667
OnWrite (std::string (ModulePath));
1654
1668
return Error::success ();
1655
1669
}
1656
1670
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
+ }
1662
1676
};
1663
1677
} // end anonymous namespace
1664
1678
1665
1679
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) {
1669
1684
return
1670
1685
[=](const Config &Conf, ModuleSummaryIndex &CombinedIndex,
1671
1686
const DenseMap<StringRef, GVSummaryMapTy> &ModuleToDefinedGVSummaries,
1672
1687
AddStreamFn AddStream, FileCache Cache) {
1673
1688
return std::make_unique<WriteIndexesThinBackend>(
1674
- Conf, CombinedIndex, ModuleToDefinedGVSummaries, OldPrefix ,
1675
- NewPrefix, NativeObjectPrefix, ShouldEmitImportsFiles,
1689
+ Conf, CombinedIndex, Parallelism, ModuleToDefinedGVSummaries ,
1690
+ OldPrefix, NewPrefix, NativeObjectPrefix, ShouldEmitImportsFiles,
1676
1691
LinkedObjectsFile, OnWrite);
1677
1692
};
1678
1693
}
@@ -1854,7 +1869,8 @@ Error LTO::runThinLTO(AddStreamFn AddStream, FileCache Cache,
1854
1869
ResolvedODR[Mod.first ], ThinLTO.ModuleMap );
1855
1870
};
1856
1871
1857
- if (BackendProcess->getThreadCount () == 1 ) {
1872
+ if (BackendProcess->getThreadCount () == 1 ||
1873
+ BackendProcess->isSensitiveToInputOrder ()) {
1858
1874
// Process the modules in the order they were provided on the
1859
1875
// command-line. It is important for this codepath to be used for
1860
1876
// WriteIndexesThinBackend, to ensure the emitted LinkedObjectsFile lists
0 commit comments