378 C.VisibilityScheme ==
Config::ELF ? VI.getELFVisibility()
380 for (
auto &S : VI.getSummaryList()) {
395 if (isPrevailing(VI.getGUID(), S.get())) {
408 S->setCanAutoHide(VI.canAutoHide() &&
409 !GUIDPreservedSymbols.
count(VI.getGUID()));
412 Visibility = S->getVisibility();
426 S->setVisibility(Visibility);
428 if (S->linkage() != OriginalLinkage)
429 recordNewLinkage(S->modulePath(), VI.getGUID(), S->linkage());
433 for (
auto &S : VI.getSummaryList()) {
438 S->setVisibility(Visibility);
460 for (
auto &
I : Index)
461 for (
auto &S :
I.second.getSummaryList())
463 GlobalInvolvedWithAlias.
insert(&AS->getAliasee());
465 for (
auto &
I : Index)
467 GlobalInvolvedWithAlias, isPrevailing,
468 recordNewLinkage, GUIDPreservedSymbols);
479 const bool SingleExternallyVisibleCopy =
480 VI.getSummaryList().size() == 1 &&
483 for (
auto &S : VI.getSummaryList()) {
486 if (isExported(S->modulePath(), VI)) {
547 if (SingleExternallyVisibleCopy && isPrevailing(VI.getGUID(), S.get()))
559 assert(!Index.withInternalizeAndPromote());
560 for (
auto &
I : Index)
563 Index.setWithInternalizeAndPromote();
570 std::unique_ptr<InputFile> File(
new InputFile);
576 File->TargetTriple = FOrErr->TheReader.getTargetTriple();
577 File->SourceFileName = FOrErr->TheReader.getSourceFileName();
578 File->COFFLinkerOpts = FOrErr->TheReader.getCOFFLinkerOpts();
579 File->DependentLibraries = FOrErr->TheReader.getDependentLibraries();
580 File->ComdatTable = FOrErr->TheReader.getComdatTable();
584 for (
unsigned I = 0;
I != FOrErr->Mods.size(); ++
I) {
585 size_t Begin = File->Symbols.size();
587 FOrErr->TheReader.module_symbols(
I))
590 if (Sym.isGlobal() && !Sym.isFormatSpecific())
591 File->Symbols.push_back(Sym);
592 File->ModuleSymIndices.push_back({Begin, File->Symbols.size()});
595 File->Mods = FOrErr->Mods;
596 File->Strtab = std::move(FOrErr->Strtab);
597 return std::move(File);
601 return Mods[0].getModuleIdentifier();
605 assert(Mods.size() == 1 &&
"Expect only one bitcode module");
611LTO::RegularLTOState::RegularLTOState(
unsigned ParallelCodeGenParallelismLevel,
613 : ParallelCodeGenParallelismLevel(ParallelCodeGenParallelismLevel),
614 Ctx(Conf), CombinedModule(
std::make_unique<
Module>(
"ld-temp.o", Ctx)),
615 Mover(
std::make_unique<
IRMover>(*CombinedModule)) {}
617LTO::ThinLTOState::ThinLTOState(
ThinBackend BackendParam)
618 : Backend(
std::
move(BackendParam)), CombinedIndex(
false) {
619 if (!Backend.isValid())
625 unsigned ParallelCodeGenParallelismLevel,
LTOKind LTOMode)
627 RegularLTO(ParallelCodeGenParallelismLevel, this->Conf),
633 Alloc = std::make_unique<BumpPtrAllocator>();
634 GlobalResolutionSymbolSaver = std::make_unique<llvm::StringSaver>(*Alloc);
645 unsigned Partition,
bool InSummary) {
647 auto *ResI = Res.
begin();
648 auto *ResE = Res.
end();
656 if (GlobalResolutionSymbolSaver && !GlobalResolutions->contains(SymbolName))
657 SymbolName = GlobalResolutionSymbolSaver->save(SymbolName);
659 auto &GlobalRes = (*GlobalResolutions)[SymbolName];
660 GlobalRes.UnnamedAddr &= Sym.isUnnamedAddr();
662 assert(!GlobalRes.Prevailing &&
663 "Multiple prevailing defs are not allowed");
664 GlobalRes.Prevailing =
true;
665 GlobalRes.IRName = std::string(Sym.getIRName());
666 }
else if (!GlobalRes.Prevailing && GlobalRes.IRName.empty()) {
673 GlobalRes.IRName = std::string(Sym.getIRName());
687 if (GlobalRes.IRName != Sym.getIRName()) {
688 GlobalRes.Partition = GlobalResolution::External;
689 GlobalRes.VisibleOutsideSummary =
true;
697 (GlobalRes.Partition != GlobalResolution::Unknown &&
698 GlobalRes.Partition != Partition)) {
699 GlobalRes.Partition = GlobalResolution::External;
702 GlobalRes.Partition = Partition;
706 GlobalRes.VisibleOutsideSummary |=
713void LTO::releaseGlobalResolutionsMemory() {
715 GlobalResolutions.reset();
717 GlobalResolutionSymbolSaver.reset();
725 auto ResI = Res.
begin();
730 OS <<
"-r=" << Path <<
',' << Sym.getName() <<
',';
748 assert(!CalledGetMaxTasks);
754 InputFile *
Input = (*InputOrErr).get();
756 if (Conf.ResolutionFile)
759 if (RegularLTO.CombinedModule->getTargetTriple().empty()) {
761 RegularLTO.CombinedModule->setTargetTriple(InputTriple);
767 for (
unsigned I = 0;
I !=
Input->Mods.size(); ++
I) {
768 if (
auto Err = addModule(*
Input, InputRes,
I, Res).moveInto(Res))
784 if (EnableSplitLTOUnit) {
788 if (*EnableSplitLTOUnit != LTOInfo->EnableSplitLTOUnit)
791 EnableSplitLTOUnit = LTOInfo->EnableSplitLTOUnit;
796 !LTOInfo->UnifiedLTO)
798 "unified LTO compilation must use "
799 "compatible bitcode modules (use -funified-lto)",
809 Input.IsThinLTO |= IsThinLTO;
811 auto ModSyms =
Input.module_symbols(ModI);
812 addModuleToGlobalRes(ModSyms, Res,
813 IsThinLTO ? ThinLTO.ModuleMap.
size() + 1 : 0,
814 LTOInfo->HasSummary);
817 return addThinLTO(BM, ModSyms, Res);
819 RegularLTO.EmptyCombinedModule =
false;
820 auto ModOrErr = addRegularLTO(
Input, InputRes, BM, ModSyms, Res);
822 return ModOrErr.takeError();
823 Res = ModOrErr->second;
825 if (!LTOInfo->HasSummary) {
826 if (
Error Err = linkRegularLTO(std::move(ModOrErr->first),
836 RegularLTO.ModsWithSummaries.push_back(std::move(ModOrErr->first));
852 std::set<const Comdat *> &NonPrevailingComdats) {
857 if (!NonPrevailingComdats.count(
C))
867 GO->setComdat(
nullptr);
874 std::pair<LTO::RegularLTOState::AddedModule, ArrayRef<SymbolResolution>>>
878 llvm::TimeTraceScope timeScope(
"LTO add regular LTO");
880 Expected<std::unique_ptr<Module>> MOrErr =
886 Mod.M = std::move(*MOrErr);
888 if (
Error Err =
M.materializeMetadata())
889 return std::move(Err);
895 if (NamedMDNode *CfiFunctionsMD =
M.getNamedMetadata(
"cfi.functions"))
896 M.eraseNamedMetadata(CfiFunctionsMD);
897 }
else if (NamedMDNode *AliasesMD =
M.getNamedMetadata(
"aliases")) {
900 DenseSet<StringRef> Prevailing;
902 if (
R.Prevailing && !
I.getIRName().empty())
903 Prevailing.
insert(
I.getIRName());
904 std::vector<MDNode *> AliasGroups;
905 for (MDNode *AliasGroup : AliasesMD->operands()) {
906 std::vector<Metadata *> Aliases;
907 for (
Metadata *Alias : AliasGroup->operands()) {
910 Aliases.push_back(Alias);
912 if (Aliases.size() > 1)
913 AliasGroups.push_back(
MDTuple::get(RegularLTO.Ctx, Aliases));
915 AliasesMD->clearOperands();
916 for (MDNode *
G : AliasGroups)
917 AliasesMD->addOperand(
G);
922 ModuleSymbolTable SymTab;
925 for (GlobalVariable &GV :
M.globals())
926 if (GV.hasAppendingLinkage())
927 Mod.Keep.push_back(&GV);
929 DenseSet<GlobalObject *> AliasedGlobals;
930 for (
auto &GA :
M.aliases())
931 if (GlobalObject *GO = GA.getAliaseeObject())
932 AliasedGlobals.
insert(GO);
941 auto MsymI = SymTab.
symbols().begin(), MsymE = SymTab.
symbols().end();
943 while (MsymI != MsymE) {
953 std::set<const Comdat *> NonPrevailingComdats;
954 SmallSet<StringRef, 2> NonPrevailingAsmSymbols;
955 for (
const InputFile::Symbol &Sym : Syms) {
965 if (Sym.isUndefined())
967 Mod.Keep.push_back(GV);
971 if (
R.LinkerRedefined)
979 (GV->hasLinkOnceODRLinkage() || GV->hasWeakODRLinkage() ||
980 GV->hasAvailableExternallyLinkage()) &&
987 Mod.Keep.push_back(GV);
990 NonPrevailingComdats.insert(GV->getComdat());
995 if (
R.FinalDefinitionInLinkageUnit) {
996 GV->setDSOLocal(
true);
997 if (GV->hasDLLImportStorageClass())
999 DefaultStorageClass);
1001 }
else if (
auto *AS =
1005 NonPrevailingAsmSymbols.
insert(AS->first);
1013 if (Sym.isCommon()) {
1016 auto &CommonRes = RegularLTO.Commons[std::string(Sym.getIRName())];
1017 CommonRes.Size = std::max(CommonRes.Size, Sym.getCommonSize());
1018 if (uint32_t SymAlignValue = Sym.getCommonAlignment()) {
1019 CommonRes.Alignment =
1020 std::max(
Align(SymAlignValue), CommonRes.Alignment);
1022 CommonRes.Prevailing |=
R.Prevailing;
1026 if (!
M.getComdatSymbolTable().empty())
1027 for (GlobalValue &GV :
M.global_values())
1032 if (!
M.getModuleInlineAsm().empty()) {
1033 std::string NewIA =
".lto_discard";
1034 if (!NonPrevailingAsmSymbols.
empty()) {
1037 M, [&](StringRef Name, StringRef Alias) {
1038 if (!NonPrevailingAsmSymbols.
count(Alias))
1039 NonPrevailingAsmSymbols.
erase(Name);
1041 NewIA +=
" " +
llvm::join(NonPrevailingAsmSymbols,
", ");
1044 M.setModuleInlineAsm(NewIA +
M.getModuleInlineAsm());
1048 return std::make_pair(std::move(
Mod), Res);
1051Error LTO::linkRegularLTO(RegularLTOState::AddedModule
Mod,
1052 bool LivenessFromIndex) {
1053 llvm::TimeTraceScope timeScope(
"LTO link regular LTO");
1054 std::vector<GlobalValue *>
Keep;
1055 for (GlobalValue *GV :
Mod.Keep) {
1056 if (LivenessFromIndex && !ThinLTO.CombinedIndex.isGUIDLive(GV->
getGUID())) {
1058 if (DiagnosticOutputFile) {
1059 if (
Error Err =
F->materialize())
1061 OptimizationRemarkEmitter ORE(
F,
nullptr);
1062 ORE.emit(OptimizationRemark(
DEBUG_TYPE,
"deadfunction",
F)
1064 <<
" not added to the combined module ");
1077 GlobalValue *CombinedGV =
1078 RegularLTO.CombinedModule->getNamedValue(GV->
getName());
1085 return RegularLTO.Mover->move(std::move(
Mod.M),
Keep,
nullptr,
1090Expected<ArrayRef<SymbolResolution>>
1093 llvm::TimeTraceScope timeScope(
"LTO add thin LTO");
1096 for (
const InputFile::Symbol &Sym : Syms) {
1100 if (!Sym.getIRName().empty() &&
R.Prevailing) {
1104 ThinLTO.setPrevailingModuleForGUID(GUID, BMID);
1110 return ThinLTO.isPrevailingModuleForGUID(GUID, BMID);
1115 for (
const InputFile::Symbol &Sym : Syms) {
1119 if (!Sym.getIRName().empty() &&
1120 (
R.Prevailing ||
R.FinalDefinitionInLinkageUnit)) {
1125 assert(ThinLTO.isPrevailingModuleForGUID(GUID, BMID));
1131 if (
R.LinkerRedefined)
1132 if (
auto S = ThinLTO.CombinedIndex.findSummaryInModule(GUID, BMID))
1138 if (
R.FinalDefinitionInLinkageUnit) {
1139 if (
auto S = ThinLTO.CombinedIndex.findSummaryInModule(GUID, BMID)) {
1140 S->setDSOLocal(
true);
1146 if (!ThinLTO.ModuleMap.insert({BMID, BM}).second)
1148 "Expected at most one ThinLTO module per bitcode file",
1151 if (!Conf.ThinLTOModulesToCompile.empty()) {
1152 if (!ThinLTO.ModulesToCompile)
1153 ThinLTO.ModulesToCompile = ModuleMapType();
1156 for (
const std::string &Name : Conf.ThinLTOModulesToCompile) {
1157 if (BMID.contains(Name)) {
1158 ThinLTO.ModulesToCompile->insert({BMID, BM});
1159 LLVM_DEBUG(
dbgs() <<
"[ThinLTO] Selecting " << BMID <<
" to compile\n");
1169 CalledGetMaxTasks =
true;
1170 auto ModuleCount = ThinLTO.ModulesToCompile ? ThinLTO.ModulesToCompile->size()
1171 : ThinLTO.ModuleMap.size();
1172 return RegularLTO.ParallelCodeGenParallelismLevel + ModuleCount;
1177Error LTO::checkPartiallySplit() {
1181 const Module *Combined = RegularLTO.CombinedModule.get();
1187 Combined, Intrinsic::type_checked_load_relative);
1191 if ((TypeTestFunc && !TypeTestFunc->
use_empty()) ||
1192 (TypeCheckedLoadFunc && !TypeCheckedLoadFunc->
use_empty()) ||
1193 (TypeCheckedLoadRelativeFunc &&
1194 !TypeCheckedLoadRelativeFunc->
use_empty()))
1196 "inconsistent LTO Unit splitting (recompile with -fsplit-lto-unit)",
1201 for (
auto &
P : ThinLTO.CombinedIndex) {
1202 for (
auto &S :
P.second.getSummaryList()) {
1206 if (!FS->type_test_assume_vcalls().empty() ||
1207 !FS->type_checked_load_vcalls().empty() ||
1208 !FS->type_test_assume_const_vcalls().empty() ||
1209 !FS->type_checked_load_const_vcalls().empty() ||
1210 !FS->type_tests().empty())
1212 "inconsistent LTO Unit splitting (recompile with -fsplit-lto-unit)",
1226 for (
auto &Res : *GlobalResolutions) {
1229 if (Res.second.IRName.
empty())
1235 if (Res.second.VisibleOutsideSummary && Res.second.Prevailing)
1236 GUIDPreservedSymbols.
insert(GUID);
1238 if (Res.second.ExportDynamic)
1239 DynamicExportSymbols.insert(GUID);
1241 GUIDPrevailingResolutions[GUID] =
1246 auto It = GUIDPrevailingResolutions.
find(
G);
1247 if (It == GUIDPrevailingResolutions.
end())
1252 isPrevailing, Conf.OptLevel > 0);
1256 if (!StatsFileOrErr)
1257 return StatsFileOrErr.takeError();
1258 std::unique_ptr<ToolOutputFile> StatsFile = std::move(StatsFileOrErr.get());
1266 ThinLTO.CombinedIndex.setWithSupportsHotColdNew();
1268 Error Result = runRegularLTO(AddStream);
1272 Result = runThinLTO(AddStream, Cache, GUIDPreservedSymbols);
1282 LLVMContext &CombinedCtx = RegularLTO.CombinedModule->getContext();
1289 return DiagFileOrErr.takeError();
1290 DiagnosticOutputFile = std::move(*DiagFileOrErr);
1296 for (
auto &M : RegularLTO.ModsWithSummaries)
1297 if (
Error Err = linkRegularLTO(std::move(M),
true))
1305 if (
Error Err = checkPartiallySplit())
1310 const DataLayout &
DL = RegularLTO.CombinedModule->getDataLayout();
1311 for (
auto &
I : RegularLTO.Commons) {
1312 if (!
I.second.Prevailing)
1315 GlobalVariable *OldGV = RegularLTO.CombinedModule->getNamedGlobal(
I.first);
1316 if (OldGV &&
DL.getTypeAllocSize(OldGV->
getValueType()) ==
I.second.Size) {
1324 auto *GV =
new GlobalVariable(*RegularLTO.CombinedModule, Ty,
false,
1327 GV->setAlignment(
I.second.Alignment);
1337 bool WholeProgramVisibilityEnabledInLTO =
1338 Conf.HasWholeProgramVisibility &&
1341 (!Conf.ValidateAllVtablesHaveTypeInfos || Conf.AllVtablesHaveTypeInfos);
1345 auto IsVisibleToRegularObj = [&](StringRef
name) {
1346 auto It = GlobalResolutions->find(
name);
1347 return (It == GlobalResolutions->end() ||
1348 It->second.VisibleOutsideSummary || !It->second.Prevailing);
1354 *RegularLTO.CombinedModule, WholeProgramVisibilityEnabledInLTO,
1355 DynamicExportSymbols, Conf.ValidateAllVtablesHaveTypeInfos,
1356 IsVisibleToRegularObj);
1358 WholeProgramVisibilityEnabledInLTO);
1360 if (Conf.PreOptModuleHook &&
1361 !Conf.PreOptModuleHook(0, *RegularLTO.CombinedModule))
1364 if (!Conf.CodeGenOnly) {
1365 for (
const auto &R : *GlobalResolutions) {
1367 RegularLTO.CombinedModule->getNamedValue(
R.second.IRName);
1368 if (!
R.second.isPrevailingIRSymbol())
1370 if (
R.second.Partition != 0 &&
1371 R.second.Partition != GlobalResolution::External)
1399 if (Conf.PostInternalizeModuleHook &&
1400 !Conf.PostInternalizeModuleHook(0, *RegularLTO.CombinedModule))
1404 if (!RegularLTO.EmptyCombinedModule || Conf.AlwaysEmitRegularLTOObj) {
1406 backend(Conf, AddStream, RegularLTO.ParallelCodeGenParallelismLevel,
1407 *RegularLTO.CombinedModule, ThinLTO.CombinedIndex))
1424 return LibcallSymbols;
1429 const std::string &NewModulePath)
const {
1430 return emitFiles(ImportList, ModulePath, NewModulePath,
1431 NewModulePath +
".thinlto.bc",
1437 const std::string &NewModulePath,
StringRef SummaryPath,
1438 std::optional<std::reference_wrapper<ImportsFilesContainer>> ImportsFiles)
1445 ImportList, ModuleToSummariesForIndex,
1446 DeclarationSummaries);
1453 &DeclarationSummaries);
1457 ModulePath, NewModulePath +
".imports", ModuleToSummariesForIndex);
1458 if (ImportsFilesError)
1459 return ImportsFilesError;
1465 ModulePath, ModuleToSummariesForIndex,
1466 [&](
StringRef M) { ImportsFiles->get().push_back(M.str()); });
1479 bool ShouldEmitIndexFiles;
1486 bool ShouldEmitIndexFiles,
bool ShouldEmitImportsFiles,
1489 OnWrite, ShouldEmitImportsFiles, ThinLTOParallelism),
1490 AddStream(
std::
move(AddStream)),
1491 ShouldEmitIndexFiles(ShouldEmitIndexFiles) {
1501class InProcessThinBackend :
public CGThinBackend {
1506 InProcessThinBackend(
1511 bool ShouldEmitIndexFiles,
bool ShouldEmitImportsFiles)
1512 : CGThinBackend(Conf, CombinedIndex, ModuleToDefinedGVSummaries,
1513 AddStream, OnWrite, ShouldEmitIndexFiles,
1514 ShouldEmitImportsFiles, ThinLTOParallelism),
1517 virtual Error runThinLTOBackendThread(
1518 AddStreamFn AddStream, FileCache Cache,
unsigned Task, BitcodeModule BM,
1519 ModuleSummaryIndex &CombinedIndex,
1520 const FunctionImporter::ImportMapTy &ImportList,
1522 const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes> &ResolvedODR,
1524 MapVector<StringRef, BitcodeModule> &ModuleMap) {
1526 llvm::TimeTraceScope timeScope(
"Run ThinLTO backend thread (in-process)",
1528 auto RunThinBackend = [&](
AddStreamFn AddStream) {
1529 LTOLLVMContext BackendContext(Conf);
1530 Expected<std::unique_ptr<Module>> MOrErr = BM.
parseModule(BackendContext);
1534 return thinBackend(Conf, Task, AddStream, **MOrErr, CombinedIndex,
1535 ImportList, DefinedGlobals, &ModuleMap,
1538 if (ShouldEmitIndexFiles) {
1539 if (
auto E = emitFiles(ImportList, ModuleID, ModuleID.str()))
1545 [](uint32_t V) { return V == 0; }))
1548 return RunThinBackend(AddStream);
1552 Conf, CombinedIndex, ModuleID, ImportList, ExportList, ResolvedODR,
1553 DefinedGlobals, CfiFunctionDefs, CfiFunctionDecls);
1554 Expected<AddStreamFn> CacheAddStreamOrErr = Cache(Task,
Key, ModuleID);
1557 AddStreamFn &CacheAddStream = *CacheAddStreamOrErr;
1559 return RunThinBackend(CacheAddStream);
1565 unsigned Task, BitcodeModule BM,
1566 const FunctionImporter::ImportMapTy &ImportList,
1568 const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes> &ResolvedODR,
1569 MapVector<StringRef, BitcodeModule> &ModuleMap)
override {
1571 assert(ModuleToDefinedGVSummaries.
count(ModulePath));
1573 ModuleToDefinedGVSummaries.
find(ModulePath)->second;
1574 BackendThreadPool.async(
1575 [=](BitcodeModule BM, ModuleSummaryIndex &CombinedIndex,
1576 const FunctionImporter::ImportMapTy &ImportList,
1578 const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes>
1581 MapVector<StringRef, BitcodeModule> &ModuleMap) {
1585 Error E = runThinLTOBackendThread(
1586 AddStream, Cache, Task, BM, CombinedIndex, ImportList, ExportList,
1587 ResolvedODR, DefinedGlobals, ModuleMap);
1589 std::unique_lock<std::mutex>
L(ErrMu);
1598 BM, std::ref(CombinedIndex), std::ref(ImportList), std::ref(ExportList),
1599 std::ref(ResolvedODR), std::ref(DefinedGlobals), std::ref(ModuleMap));
1602 OnWrite(std::string(ModulePath));
1612class FirstRoundThinBackend :
public InProcessThinBackend {
1617 FirstRoundThinBackend(
1618 const Config &Conf, ModuleSummaryIndex &CombinedIndex,
1619 ThreadPoolStrategy ThinLTOParallelism,
1620 const DenseMap<StringRef, GVSummaryMapTy> &ModuleToDefinedGVSummaries,
1623 : InProcessThinBackend(Conf, CombinedIndex, ThinLTOParallelism,
1624 ModuleToDefinedGVSummaries, std::
move(CGAddStream),
1625 std::
move(CGCache), nullptr,
1628 IRAddStream(std::
move(IRAddStream)), IRCache(std::
move(IRCache)) {}
1630 Error runThinLTOBackendThread(
1631 AddStreamFn CGAddStream, FileCache CGCache,
unsigned Task,
1632 BitcodeModule BM, ModuleSummaryIndex &CombinedIndex,
1633 const FunctionImporter::ImportMapTy &ImportList,
1635 const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes> &ResolvedODR,
1637 MapVector<StringRef, BitcodeModule> &ModuleMap)
override {
1639 llvm::TimeTraceScope timeScope(
"Run ThinLTO backend thread (first round)",
1641 auto RunThinBackend = [&](
AddStreamFn CGAddStream,
1643 LTOLLVMContext BackendContext(Conf);
1644 Expected<std::unique_ptr<Module>> MOrErr = BM.
parseModule(BackendContext);
1648 return thinBackend(Conf, Task, CGAddStream, **MOrErr, CombinedIndex,
1649 ImportList, DefinedGlobals, &ModuleMap,
1655 if (ShouldEmitIndexFiles) {
1656 if (
auto E = emitFiles(ImportList, ModuleID, ModuleID.str()))
1661 "Both caches for CG and IR should have matching availability");
1664 [](uint32_t V) { return V == 0; }))
1667 return RunThinBackend(CGAddStream, IRAddStream);
1671 Conf, CombinedIndex, ModuleID, ImportList, ExportList, ResolvedODR,
1672 DefinedGlobals, CfiFunctionDefs, CfiFunctionDecls);
1673 Expected<AddStreamFn> CacheCGAddStreamOrErr =
1674 CGCache(Task, CGKey, ModuleID);
1677 AddStreamFn &CacheCGAddStream = *CacheCGAddStreamOrErr;
1681 Expected<AddStreamFn> CacheIRAddStreamOrErr =
1682 IRCache(Task, IRKey, ModuleID);
1685 AddStreamFn &CacheIRAddStream = *CacheIRAddStreamOrErr;
1691 if (CacheCGAddStream || CacheIRAddStream) {
1694 return RunThinBackend(CacheCGAddStream ? CacheCGAddStream : CGAddStream,
1695 CacheIRAddStream ? CacheIRAddStream : IRAddStream);
1707class SecondRoundThinBackend :
public InProcessThinBackend {
1708 std::unique_ptr<SmallVector<StringRef>> IRFiles;
1712 SecondRoundThinBackend(
1713 const Config &Conf, ModuleSummaryIndex &CombinedIndex,
1714 ThreadPoolStrategy ThinLTOParallelism,
1715 const DenseMap<StringRef, GVSummaryMapTy> &ModuleToDefinedGVSummaries,
1719 : InProcessThinBackend(Conf, CombinedIndex, ThinLTOParallelism,
1720 ModuleToDefinedGVSummaries, std::
move(AddStream),
1725 IRFiles(std::
move(IRFiles)), CombinedCGDataHash(CombinedCGDataHash) {}
1727 Error runThinLTOBackendThread(
1728 AddStreamFn AddStream, FileCache Cache,
unsigned Task, BitcodeModule BM,
1729 ModuleSummaryIndex &CombinedIndex,
1730 const FunctionImporter::ImportMapTy &ImportList,
1732 const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes> &ResolvedODR,
1734 MapVector<StringRef, BitcodeModule> &ModuleMap)
override {
1736 llvm::TimeTraceScope timeScope(
"Run ThinLTO backend thread (second round)",
1738 auto RunThinBackend = [&](
AddStreamFn AddStream) {
1739 LTOLLVMContext BackendContext(Conf);
1740 std::unique_ptr<Module> LoadedModule =
1743 return thinBackend(Conf, Task, AddStream, *LoadedModule, CombinedIndex,
1744 ImportList, DefinedGlobals, &ModuleMap,
1749 [](uint32_t V) { return V == 0; }))
1752 return RunThinBackend(AddStream);
1757 Conf, CombinedIndex, ModuleID, ImportList, ExportList, ResolvedODR,
1758 DefinedGlobals, CfiFunctionDefs, CfiFunctionDecls);
1760 std::to_string(CombinedCGDataHash));
1761 Expected<AddStreamFn> CacheAddStreamOrErr = Cache(Task,
Key, ModuleID);
1764 AddStreamFn &CacheAddStream = *CacheAddStreamOrErr;
1766 if (CacheAddStream) {
1769 return RunThinBackend(CacheAddStream);
1779 bool ShouldEmitIndexFiles,
1780 bool ShouldEmitImportsFiles) {
1785 return std::make_unique<InProcessThinBackend>(
1786 Conf, CombinedIndex, Parallelism, ModuleToDefinedGVSummaries,
1787 AddStream, Cache, OnWrite, ShouldEmitIndexFiles,
1788 ShouldEmitImportsFiles);
1814 return std::string(Path);
1818 if (!ParentPath.
empty()) {
1821 llvm::errs() <<
"warning: could not create directory '" << ParentPath
1822 <<
"': " << EC.message() <<
'\n';
1824 return std::string(NewPath);
1829 std::string OldPrefix, NewPrefix, NativeObjectPrefix;
1833 WriteIndexesThinBackend(
1837 std::string OldPrefix, std::string NewPrefix,
1838 std::string NativeObjectPrefix,
bool ShouldEmitImportsFiles,
1841 OnWrite, ShouldEmitImportsFiles, ThinLTOParallelism),
1842 OldPrefix(OldPrefix), NewPrefix(NewPrefix),
1843 NativeObjectPrefix(NativeObjectPrefix),
1844 LinkedObjectsFile(LinkedObjectsFile) {}
1850 const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes> &ResolvedODR,
1858 if (LinkedObjectsFile) {
1859 std::string ObjectPrefix =
1860 NativeObjectPrefix.empty() ? NewPrefix : NativeObjectPrefix;
1861 std::string LinkedObjectsFilePath =
1863 *LinkedObjectsFile << LinkedObjectsFilePath <<
'\n';
1866 BackendThreadPool.async(
1867 [
this](
const StringRef ModulePath,
1868 const FunctionImporter::ImportMapTy &ImportList,
1869 const std::string &OldPrefix,
const std::string &NewPrefix) {
1870 std::string NewModulePath =
1872 auto E = emitFiles(ImportList, ModulePath, NewModulePath);
1874 std::unique_lock<std::mutex>
L(ErrMu);
1882 ModulePath, ImportList, OldPrefix, NewPrefix);
1885 OnWrite(std::string(ModulePath));
1889 bool isSensitiveToInputOrder()
override {
1899 std::string NewPrefix, std::string NativeObjectPrefix,
1906 return std::make_unique<WriteIndexesThinBackend>(
1907 Conf, CombinedIndex, Parallelism, ModuleToDefinedGVSummaries,
1908 OldPrefix, NewPrefix, NativeObjectPrefix, ShouldEmitImportsFiles,
1909 LinkedObjectsFile, OnWrite);
1924 if (ThinLTO.ModuleMap.
empty())
1927 if (ThinLTO.ModulesToCompile && ThinLTO.ModulesToCompile->empty()) {
1928 llvm::errs() <<
"warning: [ThinLTO] No module compiled\n";
1932 if (Conf.CombinedIndexHook &&
1933 !Conf.CombinedIndexHook(ThinLTO.CombinedIndex, GUIDPreservedSymbols))
1938 DenseMap<StringRef, GVSummaryMapTy> ModuleToDefinedGVSummaries(
1939 ThinLTO.ModuleMap.size());
1940 ThinLTO.CombinedIndex.collectDefinedGVSummariesPerModule(
1941 ModuleToDefinedGVSummaries);
1949 for (
auto &
Mod : ThinLTO.ModuleMap)
1950 if (!ModuleToDefinedGVSummaries.
count(
Mod.first))
1953 FunctionImporter::ImportListsTy ImportLists(ThinLTO.ModuleMap.size());
1954 DenseMap<StringRef, FunctionImporter::ExportSetTy> ExportLists(
1955 ThinLTO.ModuleMap.size());
1956 StringMap<std::map<GlobalValue::GUID, GlobalValue::LinkageTypes>> ResolvedODR;
1959 ThinLTO.CombinedIndex.dumpSCCs(
outs());
1961 std::set<GlobalValue::GUID> ExportedGUIDs;
1963 bool WholeProgramVisibilityEnabledInLTO =
1964 Conf.HasWholeProgramVisibility &&
1967 (!Conf.ValidateAllVtablesHaveTypeInfos || Conf.AllVtablesHaveTypeInfos);
1969 ThinLTO.CombinedIndex.setWithWholeProgramVisibility();
1974 DenseSet<GlobalValue::GUID> VisibleToRegularObjSymbols;
1975 if (WholeProgramVisibilityEnabledInLTO &&
1976 Conf.ValidateAllVtablesHaveTypeInfos) {
1979 auto IsVisibleToRegularObj = [&](StringRef
name) {
1980 auto It = GlobalResolutions->find(
name);
1981 return (It == GlobalResolutions->end() ||
1982 It->second.VisibleOutsideSummary || !It->second.Prevailing);
1986 VisibleToRegularObjSymbols,
1987 IsVisibleToRegularObj);
1993 ThinLTO.CombinedIndex, WholeProgramVisibilityEnabledInLTO,
1994 DynamicExportSymbols, VisibleToRegularObjSymbols);
1999 std::map<ValueInfo, std::vector<VTableSlotSummary>> LocalWPDTargetsMap;
2001 LocalWPDTargetsMap);
2004 return ThinLTO.isPrevailingModuleForGUID(GUID, S->modulePath());
2007 MemProfContextDisambiguation ContextDisambiguation;
2008 ContextDisambiguation.
run(ThinLTO.CombinedIndex, isPrevailing);
2015 for (
auto &Res : *GlobalResolutions) {
2018 if (Res.second.Partition != GlobalResolution::External ||
2019 !Res.second.isPrevailingIRSymbol())
2024 if (ThinLTO.CombinedIndex.isGUIDLive(GUID))
2025 ExportedGUIDs.insert(GUID);
2032 releaseGlobalResolutionsMemory();
2034 if (Conf.OptLevel > 0)
2036 isPrevailing, ImportLists, ExportLists);
2040 auto &Defs = ThinLTO.CombinedIndex.cfiFunctionDefs();
2041 ExportedGUIDs.insert(Defs.guid_begin(), Defs.guid_end());
2042 auto &Decls = ThinLTO.CombinedIndex.cfiFunctionDecls();
2043 ExportedGUIDs.insert(Decls.guid_begin(), Decls.guid_end());
2045 auto isExported = [&](StringRef ModuleIdentifier, ValueInfo
VI) {
2046 const auto &ExportList = ExportLists.
find(ModuleIdentifier);
2047 return (ExportList != ExportLists.end() && ExportList->second.
count(VI)) ||
2048 ExportedGUIDs.count(
VI.getGUID());
2054 LocalWPDTargetsMap);
2059 auto recordNewLinkage = [&](StringRef ModuleIdentifier,
2062 ResolvedODR[ModuleIdentifier][
GUID] = NewLinkage;
2065 recordNewLinkage, GUIDPreservedSymbols);
2074 TimeTraceScopeExit.release();
2077 ThinLTO.ModulesToCompile ? *ThinLTO.ModulesToCompile : ThinLTO.ModuleMap;
2079 auto RunBackends = [&](ThinBackendProc *BackendProcess) ->
Error {
2080 auto ProcessOneModule = [&](
int I) ->
Error {
2084 return BackendProcess->start(
2085 RegularLTO.ParallelCodeGenParallelismLevel +
I,
Mod.second,
2086 ImportLists[
Mod.first], ExportLists[
Mod.first],
2087 ResolvedODR[
Mod.first], ThinLTO.ModuleMap);
2090 BackendProcess->setup(ModuleMap.
size(),
2091 RegularLTO.ParallelCodeGenParallelismLevel,
2092 RegularLTO.CombinedModule->getTargetTriple());
2094 if (BackendProcess->getThreadCount() == 1 ||
2095 BackendProcess->isSensitiveToInputOrder()) {
2101 for (
int I = 0,
E = ModuleMap.
size();
I !=
E; ++
I)
2102 if (
Error E = ProcessOneModule(
I))
2109 std::vector<BitcodeModule *> ModulesVec;
2110 ModulesVec.reserve(ModuleMap.
size());
2111 for (
auto &
Mod : ModuleMap)
2112 ModulesVec.push_back(&
Mod.second);
2114 if (
Error E = ProcessOneModule(
I))
2117 return BackendProcess->wait();
2121 std::unique_ptr<ThinBackendProc> BackendProc =
2122 ThinLTO.Backend(Conf, ThinLTO.CombinedIndex, ModuleToDefinedGVSummaries,
2124 return RunBackends(BackendProc.get());
2132 LLVM_DEBUG(
dbgs() <<
"[TwoRounds] Initializing ThinLTO two-codegen rounds\n");
2135 auto Parallelism = ThinLTO.Backend.getParallelism();
2138 cgdata::StreamCacheData CG(MaxTasks, Cache,
"CG"),
IR(MaxTasks, Cache,
"IR");
2143 LLVM_DEBUG(
dbgs() <<
"[TwoRounds] Running the first round of codegen\n");
2144 auto FirstRoundLTO = std::make_unique<FirstRoundThinBackend>(
2145 Conf, ThinLTO.CombinedIndex, Parallelism, ModuleToDefinedGVSummaries,
2146 CG.AddStream, CG.Cache,
IR.AddStream,
IR.Cache);
2147 if (
Error E = RunBackends(FirstRoundLTO.get()))
2152 if (
Error E = CombinedHashOrErr.takeError())
2154 auto CombinedHash = *CombinedHashOrErr;
2155 LLVM_DEBUG(
dbgs() <<
"[TwoRounds] CGData hash: " << CombinedHash <<
"\n");
2159 LLVM_DEBUG(
dbgs() <<
"[TwoRounds] Running the second round of codegen\n");
2160 auto SecondRoundLTO = std::make_unique<SecondRoundThinBackend>(
2161 Conf, ThinLTO.CombinedIndex, Parallelism, ModuleToDefinedGVSummaries,
2162 AddStream, Cache,
IR.getResult(), CombinedHash);
2163 return RunBackends(SecondRoundLTO.get());
2173 if (!Filename.empty() &&
Count != -1)
2181 if (
Error E = ResultOrErr.takeError())
2182 return std::move(E);
2185 (*ResultOrErr)->keep();
2193 if (StatsFilename.
empty())
2204 return std::move(StatsFile);
2212 std::vector<int> ModulesOrdering(Seq.begin(), Seq.end());
2213 llvm::sort(ModulesOrdering, [&](
int LeftIndex,
int RightIndex) {
2214 auto LSize = R[LeftIndex]->getBuffer().size();
2215 auto RSize = R[RightIndex]->getBuffer().size();
2216 return LSize > RSize;
2218 return ModulesOrdering;
2228class OutOfProcessThinBackend :
public CGThinBackend {
2234 SString LinkerOutputFile;
2236 SString DistributorPath;
2239 SString RemoteCompiler;
2248 std::atomic<size_t> CachedJobs{0};
2253 StringRef NativeObjectPath;
2254 StringRef SummaryIndexPath;
2256 std::string CacheKey;
2258 bool Cached =
false;
2267 unsigned ThinLTOTaskOffset;
2270 llvm::Triple Triple;
2276 OutOfProcessThinBackend(
2277 const Config &Conf, ModuleSummaryIndex &CombinedIndex,
2278 ThreadPoolStrategy ThinLTOParallelism,
2279 const DenseMap<StringRef, GVSummaryMapTy> &ModuleToDefinedGVSummaries,
2281 bool ShouldEmitIndexFiles,
bool ShouldEmitImportsFiles,
2282 StringRef LinkerOutputFile, StringRef Distributor,
2286 : CGThinBackend(Conf, CombinedIndex, ModuleToDefinedGVSummaries,
2287 AddStream, OnWrite, ShouldEmitIndexFiles,
2288 ShouldEmitImportsFiles, ThinLTOParallelism),
2289 LinkerOutputFile(LinkerOutputFile), DistributorPath(Distributor),
2290 DistributorArgs(DistributorArgs), RemoteCompiler(RemoteCompiler),
2291 RemoteCompilerPrependArgs(RemoteCompilerPrependArgs),
2292 RemoteCompilerArgs(RemoteCompilerArgs), SaveTemps(SaveTemps),
2293 Cache(std::
move(CacheFn)) {}
2295 void setup(
unsigned ThinLTONumTasks,
unsigned ThinLTOTaskOffset,
2296 llvm::Triple Triple)
override {
2298 Jobs.
resize((
size_t)ThinLTONumTasks);
2299 this->ThinLTOTaskOffset = ThinLTOTaskOffset;
2300 this->Triple = Triple;
2301 this->Conf.
Dtlto = 1;
2304 virtual Error runThinLTOBackendThread(
2305 Job &J,
const FunctionImporter::ImportMapTy &ImportList,
2307 const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes>
2310 TimeTraceScope TimeScope(
"Emit individual index for DTLTO",
2311 J.SummaryIndexPath);
2312 if (
auto E = emitFiles(ImportList, J.ModuleID, J.ModuleID.str(),
2313 J.SummaryIndexPath, J.ImportsFiles))
2319 [](uint32_t V) { return V == 0; }))
2324 TimeTraceScope TimeScope(
"Check cache for DTLTO", J.SummaryIndexPath);
2326 ModuleToDefinedGVSummaries.
find(J.ModuleID)->second;
2330 ExportList, ResolvedODR, DefinedGlobals,
2331 CfiFunctionDefs, CfiFunctionDecls);
2334 auto CacheAddStreamExp = Cache(J.Task, J.CacheKey, J.ModuleID);
2335 if (
Error Err = CacheAddStreamExp.takeError())
2340 if (!CacheAddStream) {
2342 CachedJobs.fetch_add(1);
2347 J.CacheAddStream = std::move(CacheAddStream);
2353 unsigned Task, BitcodeModule BM,
2354 const FunctionImporter::ImportMapTy &ImportList,
2356 const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes> &ResolvedODR,
2357 MapVector<StringRef, BitcodeModule> &ModuleMap)
override {
2363 itostr(Task) +
"." + UID +
".native.o");
2365 Job &J = Jobs[Task - ThinLTOTaskOffset];
2368 Saver.
save(ObjFilePath.str()),
2369 Saver.
save(ObjFilePath.str() +
".thinlto.bc"),
2378 if (!ShouldEmitIndexFiles)
2382 assert(ModuleToDefinedGVSummaries.
count(ModulePath));
2386 BackendThreadPool.async(
2387 [=](Job &J,
const FunctionImporter::ImportMapTy &ImportList,
2389 const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes>
2394 "Emit individual index and check cache for DTLTO");
2396 runThinLTOBackendThread(J, ImportList, ExportList, ResolvedODR);
2398 std::unique_lock<std::mutex>
L(ErrMu);
2407 std::ref(J), std::ref(ImportList), std::ref(ExportList),
2408 std::ref(ResolvedODR));
2422 void buildCommonRemoteCompilerOptions() {
2423 const lto::Config &
C = Conf;
2424 auto &
Ops = CodegenOptions;
2428 if (
C.Options.EmitAddrsig)
2429 Ops.push_back(
"-faddrsig");
2430 if (
C.Options.FunctionSections)
2431 Ops.push_back(
"-ffunction-sections");
2432 if (
C.Options.DataSections)
2433 Ops.push_back(
"-fdata-sections");
2438 Ops.push_back(
"-fpic");
2442 if (!
C.PGOWarnMismatch) {
2443 Ops.push_back(
"-mllvm");
2444 Ops.push_back(
"-no-pgo-warn-mismatch");
2449 if (!
C.SampleProfile.empty()) {
2451 Saver.
save(
"-fprofile-sample-use=" + Twine(
C.SampleProfile)));
2452 CommonInputs.
insert(
C.SampleProfile);
2456 Ops.push_back(
"-Wno-unused-command-line-argument");
2459 if (!RemoteCompilerArgs.
empty())
2460 for (
auto &a : RemoteCompilerArgs)
2466 bool emitDistributorJson(StringRef DistributorJson) {
2469 raw_fd_ostream OS(DistributorJson, EC);
2473 json::OStream JOS(OS);
2476 JOS.attributeObject(
"common", [&]() {
2477 JOS.attribute(
"linker_output", LinkerOutputFile);
2479 JOS.attributeArray(
"args", [&]() {
2480 JOS.value(RemoteCompiler);
2483 if (!RemoteCompilerPrependArgs.
empty())
2484 for (
auto &
A : RemoteCompilerPrependArgs)
2489 JOS.value(Saver.
save(
"--target=" + Triple.
str()));
2491 for (
const auto &
A : CodegenOptions)
2495 JOS.attribute(
"inputs",
Array(CommonInputs));
2499 JOS.attributeArray(
"jobs", [&]() {
2500 for (
const auto &J : Jobs) {
2508 SmallVector<StringRef, 1> Outputs;
2511 JOS.attributeArray(
"args", [&]() {
2512 JOS.value(J.ModuleID);
2516 Saver.
save(
"-fthinlto-index=" + Twine(J.SummaryIndexPath)));
2520 JOS.value(J.NativeObjectPath);
2528 JOS.attribute(
"inputs",
Array(Inputs));
2530 JOS.attribute(
"outputs",
Array(Outputs));
2539 void removeFile(StringRef FileName) {
2541 if (EC && EC != std::make_error_code(std::errc::no_such_file_or_directory))
2542 errs() <<
"warning: could not remove the file '" << FileName
2543 <<
"': " <<
EC.message() <<
"\n";
2546 Error wait()
override {
2549 BackendThreadPool.wait();
2551 return std::move(*Err);
2554 llvm::TimeTraceScope TimeScope(
"Remove DTLTO temporary files");
2556 for (
auto &Job : Jobs) {
2557 removeFile(Job.NativeObjectPath);
2558 if (!ShouldEmitIndexFiles)
2559 removeFile(Job.SummaryIndexPath);
2563 const StringRef BCError =
"DTLTO backend compilation: ";
2565 buildCommonRemoteCompilerOptions();
2569 llvm::TimeTraceScope TimeScope(
"Emit DTLTO JSON");
2571 UID +
".dist-file.json");
2575 if (!emitDistributorJson(JsonFile))
2577 BCError +
"failed to generate distributor JSON script: " + JsonFile,
2582 removeFile(JsonFile);
2586 llvm::TimeTraceScope TimeScope(
"Execute DTLTO distributor",
2589 if (CachedJobs.load() < Jobs.size()) {
2592 Args.push_back(JsonFile);
2599 BCError +
"distributor execution failed" +
2600 (!ErrMsg.empty() ?
": " + ErrMsg + Twine(
".") : Twine(
".")),
2607 llvm::TimeTraceScope FilesScope(
"Add DTLTO files to the link");
2608 for (
auto &Job : Jobs) {
2609 if (!Job.CacheKey.empty() && Job.Cached) {
2615 auto ObjFileMbOrErr =
2618 if (std::error_code EC = ObjFileMbOrErr.getError())
2620 BCError +
"cannot open native object file: " +
2621 Job.NativeObjectPath +
": " +
EC.message(),
2624 MemoryBufferRef ObjFileMbRef = ObjFileMbOrErr->get()->getMemBufferRef();
2628 assert(Job.CacheAddStream);
2630 auto CachedFileStreamOrErr =
2631 Job.CacheAddStream(Job.Task, Job.ModuleID);
2632 if (!CachedFileStreamOrErr)
2634 CachedFileStreamOrErr.takeError(),
2636 "Cannot get a cache file stream: %s",
2637 Job.NativeObjectPath.data()));
2639 auto &CacheStream = *(CachedFileStreamOrErr->get());
2640 *(CacheStream.OS) << ObjFileMbRef.
getBuffer();
2641 if (
Error Err = CacheStream.commit())
2644 auto StreamOrErr = AddStream(Job.Task, Job.ModuleID);
2645 if (
Error Err = StreamOrErr.takeError())
2647 auto &Stream = *StreamOrErr->get();
2649 if (
Error Err = Stream.commit())
2661 bool ShouldEmitIndexFiles,
bool ShouldEmitImportsFiles,
2670 return std::make_unique<OutOfProcessThinBackend>(
2671 Conf, CombinedIndex, Parallelism, ModuleToDefinedGVSummaries,
2672 AddStream, Cache, OnWrite, ShouldEmitIndexFiles,
2673 ShouldEmitImportsFiles, LinkerOutputFile, Distributor,
2674 DistributorArgs, RemoteCompiler, RemoteCompilerPrependArgs,
2675 RemoteCompilerArgs, SaveTemps);