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");
609LTO::RegularLTOState::RegularLTOState(
unsigned ParallelCodeGenParallelismLevel,
611 : ParallelCodeGenParallelismLevel(ParallelCodeGenParallelismLevel),
612 Ctx(Conf), CombinedModule(
std::make_unique<
Module>(
"ld-temp.o", Ctx)),
613 Mover(
std::make_unique<
IRMover>(*CombinedModule)) {}
615LTO::ThinLTOState::ThinLTOState(
ThinBackend BackendParam)
616 : Backend(
std::
move(BackendParam)), CombinedIndex(
false) {
617 if (!Backend.isValid())
623 unsigned ParallelCodeGenParallelismLevel,
LTOKind LTOMode)
625 RegularLTO(ParallelCodeGenParallelismLevel, this->Conf),
631 Alloc = std::make_unique<BumpPtrAllocator>();
632 GlobalResolutionSymbolSaver = std::make_unique<llvm::StringSaver>(*Alloc);
643 unsigned Partition,
bool InSummary) {
645 auto *ResI = Res.
begin();
646 auto *ResE = Res.
end();
654 if (GlobalResolutionSymbolSaver && !GlobalResolutions->contains(SymbolName))
655 SymbolName = GlobalResolutionSymbolSaver->save(SymbolName);
657 auto &GlobalRes = (*GlobalResolutions)[SymbolName];
658 GlobalRes.UnnamedAddr &= Sym.isUnnamedAddr();
660 assert(!GlobalRes.Prevailing &&
661 "Multiple prevailing defs are not allowed");
662 GlobalRes.Prevailing =
true;
663 GlobalRes.IRName = std::string(Sym.getIRName());
664 }
else if (!GlobalRes.Prevailing && GlobalRes.IRName.empty()) {
671 GlobalRes.IRName = std::string(Sym.getIRName());
685 if (GlobalRes.IRName != Sym.getIRName()) {
686 GlobalRes.Partition = GlobalResolution::External;
687 GlobalRes.VisibleOutsideSummary =
true;
695 (GlobalRes.Partition != GlobalResolution::Unknown &&
696 GlobalRes.Partition != Partition)) {
697 GlobalRes.Partition = GlobalResolution::External;
700 GlobalRes.Partition = Partition;
704 GlobalRes.VisibleOutsideSummary |=
711void LTO::releaseGlobalResolutionsMemory() {
713 GlobalResolutions.reset();
715 GlobalResolutionSymbolSaver.reset();
723 auto ResI = Res.
begin();
728 OS <<
"-r=" << Path <<
',' << Sym.getName() <<
',';
746 assert(!CalledGetMaxTasks);
752 InputFile *
Input = (*InputOrErr).get();
754 if (Conf.ResolutionFile)
757 if (RegularLTO.CombinedModule->getTargetTriple().empty()) {
759 RegularLTO.CombinedModule->setTargetTriple(InputTriple);
765 for (
unsigned I = 0;
I !=
Input->Mods.size(); ++
I) {
766 if (
auto Err = addModule(*
Input, InputRes,
I, Res).moveInto(Res))
782 if (EnableSplitLTOUnit) {
786 if (*EnableSplitLTOUnit != LTOInfo->EnableSplitLTOUnit)
789 EnableSplitLTOUnit = LTOInfo->EnableSplitLTOUnit;
794 !LTOInfo->UnifiedLTO)
796 "unified LTO compilation must use "
797 "compatible bitcode modules (use -funified-lto)",
807 Input.IsThinLTO = IsThinLTO;
809 auto ModSyms =
Input.module_symbols(ModI);
810 addModuleToGlobalRes(ModSyms, Res,
811 IsThinLTO ? ThinLTO.ModuleMap.
size() + 1 : 0,
812 LTOInfo->HasSummary);
815 return addThinLTO(BM, ModSyms, Res);
817 RegularLTO.EmptyCombinedModule =
false;
818 auto ModOrErr = addRegularLTO(
Input, InputRes, BM, ModSyms, Res);
820 return ModOrErr.takeError();
821 Res = ModOrErr->second;
823 if (!LTOInfo->HasSummary) {
824 if (
Error Err = linkRegularLTO(std::move(ModOrErr->first),
834 RegularLTO.ModsWithSummaries.push_back(std::move(ModOrErr->first));
850 std::set<const Comdat *> &NonPrevailingComdats) {
855 if (!NonPrevailingComdats.count(
C))
865 GO->setComdat(
nullptr);
872 std::pair<LTO::RegularLTOState::AddedModule, ArrayRef<SymbolResolution>>>
876 llvm::TimeTraceScope timeScope(
"LTO add regular LTO");
878 Expected<std::unique_ptr<Module>> MOrErr =
884 Mod.M = std::move(*MOrErr);
886 if (
Error Err =
M.materializeMetadata())
887 return std::move(Err);
893 if (NamedMDNode *CfiFunctionsMD =
M.getNamedMetadata(
"cfi.functions"))
894 M.eraseNamedMetadata(CfiFunctionsMD);
895 }
else if (NamedMDNode *AliasesMD =
M.getNamedMetadata(
"aliases")) {
898 DenseSet<StringRef> Prevailing;
900 if (
R.Prevailing && !
I.getIRName().empty())
901 Prevailing.
insert(
I.getIRName());
902 std::vector<MDNode *> AliasGroups;
903 for (MDNode *AliasGroup : AliasesMD->operands()) {
904 std::vector<Metadata *> Aliases;
905 for (
Metadata *Alias : AliasGroup->operands()) {
908 Aliases.push_back(Alias);
910 if (Aliases.size() > 1)
911 AliasGroups.push_back(
MDTuple::get(RegularLTO.Ctx, Aliases));
913 AliasesMD->clearOperands();
914 for (MDNode *
G : AliasGroups)
915 AliasesMD->addOperand(
G);
920 ModuleSymbolTable SymTab;
923 for (GlobalVariable &GV :
M.globals())
924 if (GV.hasAppendingLinkage())
925 Mod.Keep.push_back(&GV);
927 DenseSet<GlobalObject *> AliasedGlobals;
928 for (
auto &GA :
M.aliases())
929 if (GlobalObject *GO = GA.getAliaseeObject())
930 AliasedGlobals.
insert(GO);
939 auto MsymI = SymTab.
symbols().begin(), MsymE = SymTab.
symbols().end();
941 while (MsymI != MsymE) {
951 std::set<const Comdat *> NonPrevailingComdats;
952 SmallSet<StringRef, 2> NonPrevailingAsmSymbols;
953 for (
const InputFile::Symbol &Sym : Syms) {
963 if (Sym.isUndefined())
965 Mod.Keep.push_back(GV);
969 if (
R.LinkerRedefined)
977 (GV->hasLinkOnceODRLinkage() || GV->hasWeakODRLinkage() ||
978 GV->hasAvailableExternallyLinkage()) &&
985 Mod.Keep.push_back(GV);
988 NonPrevailingComdats.insert(GV->getComdat());
993 if (
R.FinalDefinitionInLinkageUnit) {
994 GV->setDSOLocal(
true);
995 if (GV->hasDLLImportStorageClass())
997 DefaultStorageClass);
999 }
else if (
auto *AS =
1003 NonPrevailingAsmSymbols.
insert(AS->first);
1011 if (Sym.isCommon()) {
1014 auto &CommonRes = RegularLTO.Commons[std::string(Sym.getIRName())];
1015 CommonRes.Size = std::max(CommonRes.Size, Sym.getCommonSize());
1016 if (uint32_t SymAlignValue = Sym.getCommonAlignment()) {
1017 CommonRes.Alignment =
1018 std::max(
Align(SymAlignValue), CommonRes.Alignment);
1020 CommonRes.Prevailing |=
R.Prevailing;
1024 if (!
M.getComdatSymbolTable().empty())
1025 for (GlobalValue &GV :
M.global_values())
1030 if (!
M.getModuleInlineAsm().empty()) {
1031 std::string NewIA =
".lto_discard";
1032 if (!NonPrevailingAsmSymbols.
empty()) {
1035 M, [&](StringRef Name, StringRef Alias) {
1036 if (!NonPrevailingAsmSymbols.
count(Alias))
1037 NonPrevailingAsmSymbols.
erase(Name);
1039 NewIA +=
" " +
llvm::join(NonPrevailingAsmSymbols,
", ");
1042 M.setModuleInlineAsm(NewIA +
M.getModuleInlineAsm());
1046 return std::make_pair(std::move(
Mod), Res);
1049Error LTO::linkRegularLTO(RegularLTOState::AddedModule
Mod,
1050 bool LivenessFromIndex) {
1051 llvm::TimeTraceScope timeScope(
"LTO link regular LTO");
1052 std::vector<GlobalValue *>
Keep;
1053 for (GlobalValue *GV :
Mod.Keep) {
1054 if (LivenessFromIndex && !ThinLTO.CombinedIndex.isGUIDLive(GV->
getGUID())) {
1056 if (DiagnosticOutputFile) {
1057 if (
Error Err =
F->materialize())
1059 OptimizationRemarkEmitter ORE(
F,
nullptr);
1060 ORE.emit(OptimizationRemark(
DEBUG_TYPE,
"deadfunction",
F)
1062 <<
" not added to the combined module ");
1075 GlobalValue *CombinedGV =
1076 RegularLTO.CombinedModule->getNamedValue(GV->
getName());
1083 return RegularLTO.Mover->move(std::move(
Mod.M),
Keep,
nullptr,
1088Expected<ArrayRef<SymbolResolution>>
1091 llvm::TimeTraceScope timeScope(
"LTO add thin LTO");
1094 for (
const InputFile::Symbol &Sym : Syms) {
1098 if (!Sym.getIRName().empty() &&
R.Prevailing) {
1102 ThinLTO.setPrevailingModuleForGUID(GUID, BMID);
1108 return ThinLTO.isPrevailingModuleForGUID(GUID, BMID);
1113 for (
const InputFile::Symbol &Sym : Syms) {
1117 if (!Sym.getIRName().empty() &&
1118 (
R.Prevailing ||
R.FinalDefinitionInLinkageUnit)) {
1123 assert(ThinLTO.isPrevailingModuleForGUID(GUID, BMID));
1129 if (
R.LinkerRedefined)
1130 if (
auto S = ThinLTO.CombinedIndex.findSummaryInModule(GUID, BMID))
1136 if (
R.FinalDefinitionInLinkageUnit) {
1137 if (
auto S = ThinLTO.CombinedIndex.findSummaryInModule(GUID, BMID)) {
1138 S->setDSOLocal(
true);
1144 if (!ThinLTO.ModuleMap.insert({BMID, BM}).second)
1146 "Expected at most one ThinLTO module per bitcode file",
1149 if (!Conf.ThinLTOModulesToCompile.empty()) {
1150 if (!ThinLTO.ModulesToCompile)
1151 ThinLTO.ModulesToCompile = ModuleMapType();
1154 for (
const std::string &Name : Conf.ThinLTOModulesToCompile) {
1155 if (BMID.contains(Name)) {
1156 ThinLTO.ModulesToCompile->insert({BMID, BM});
1157 LLVM_DEBUG(
dbgs() <<
"[ThinLTO] Selecting " << BMID <<
" to compile\n");
1167 CalledGetMaxTasks =
true;
1168 auto ModuleCount = ThinLTO.ModulesToCompile ? ThinLTO.ModulesToCompile->size()
1169 : ThinLTO.ModuleMap.size();
1170 return RegularLTO.ParallelCodeGenParallelismLevel + ModuleCount;
1175Error LTO::checkPartiallySplit() {
1179 const Module *Combined = RegularLTO.CombinedModule.get();
1185 Combined, Intrinsic::type_checked_load_relative);
1189 if ((TypeTestFunc && !TypeTestFunc->
use_empty()) ||
1190 (TypeCheckedLoadFunc && !TypeCheckedLoadFunc->
use_empty()) ||
1191 (TypeCheckedLoadRelativeFunc &&
1192 !TypeCheckedLoadRelativeFunc->
use_empty()))
1194 "inconsistent LTO Unit splitting (recompile with -fsplit-lto-unit)",
1199 for (
auto &
P : ThinLTO.CombinedIndex) {
1200 for (
auto &S :
P.second.getSummaryList()) {
1204 if (!FS->type_test_assume_vcalls().empty() ||
1205 !FS->type_checked_load_vcalls().empty() ||
1206 !FS->type_test_assume_const_vcalls().empty() ||
1207 !FS->type_checked_load_const_vcalls().empty() ||
1208 !FS->type_tests().empty())
1210 "inconsistent LTO Unit splitting (recompile with -fsplit-lto-unit)",
1224 for (
auto &Res : *GlobalResolutions) {
1227 if (Res.second.IRName.
empty())
1233 if (Res.second.VisibleOutsideSummary && Res.second.Prevailing)
1234 GUIDPreservedSymbols.
insert(GUID);
1236 if (Res.second.ExportDynamic)
1237 DynamicExportSymbols.insert(GUID);
1239 GUIDPrevailingResolutions[GUID] =
1244 auto It = GUIDPrevailingResolutions.
find(
G);
1245 if (It == GUIDPrevailingResolutions.
end())
1250 isPrevailing, Conf.OptLevel > 0);
1254 if (!StatsFileOrErr)
1255 return StatsFileOrErr.takeError();
1256 std::unique_ptr<ToolOutputFile> StatsFile = std::move(StatsFileOrErr.get());
1264 ThinLTO.CombinedIndex.setWithSupportsHotColdNew();
1266 Error Result = runRegularLTO(AddStream);
1270 Result = runThinLTO(AddStream, Cache, GUIDPreservedSymbols);
1280 LLVMContext &CombinedCtx = RegularLTO.CombinedModule->getContext();
1287 return DiagFileOrErr.takeError();
1288 DiagnosticOutputFile = std::move(*DiagFileOrErr);
1294 for (
auto &M : RegularLTO.ModsWithSummaries)
1295 if (
Error Err = linkRegularLTO(std::move(M),
true))
1303 if (
Error Err = checkPartiallySplit())
1308 const DataLayout &
DL = RegularLTO.CombinedModule->getDataLayout();
1309 for (
auto &
I : RegularLTO.Commons) {
1310 if (!
I.second.Prevailing)
1313 GlobalVariable *OldGV = RegularLTO.CombinedModule->getNamedGlobal(
I.first);
1314 if (OldGV &&
DL.getTypeAllocSize(OldGV->
getValueType()) ==
I.second.Size) {
1322 auto *GV =
new GlobalVariable(*RegularLTO.CombinedModule, Ty,
false,
1325 GV->setAlignment(
I.second.Alignment);
1335 bool WholeProgramVisibilityEnabledInLTO =
1336 Conf.HasWholeProgramVisibility &&
1339 (!Conf.ValidateAllVtablesHaveTypeInfos || Conf.AllVtablesHaveTypeInfos);
1343 auto IsVisibleToRegularObj = [&](StringRef
name) {
1344 auto It = GlobalResolutions->find(
name);
1345 return (It == GlobalResolutions->end() ||
1346 It->second.VisibleOutsideSummary || !It->second.Prevailing);
1352 *RegularLTO.CombinedModule, WholeProgramVisibilityEnabledInLTO,
1353 DynamicExportSymbols, Conf.ValidateAllVtablesHaveTypeInfos,
1354 IsVisibleToRegularObj);
1356 WholeProgramVisibilityEnabledInLTO);
1358 if (Conf.PreOptModuleHook &&
1359 !Conf.PreOptModuleHook(0, *RegularLTO.CombinedModule))
1362 if (!Conf.CodeGenOnly) {
1363 for (
const auto &R : *GlobalResolutions) {
1365 RegularLTO.CombinedModule->getNamedValue(
R.second.IRName);
1366 if (!
R.second.isPrevailingIRSymbol())
1368 if (
R.second.Partition != 0 &&
1369 R.second.Partition != GlobalResolution::External)
1397 if (Conf.PostInternalizeModuleHook &&
1398 !Conf.PostInternalizeModuleHook(0, *RegularLTO.CombinedModule))
1402 if (!RegularLTO.EmptyCombinedModule || Conf.AlwaysEmitRegularLTOObj) {
1404 backend(Conf, AddStream, RegularLTO.ParallelCodeGenParallelismLevel,
1405 *RegularLTO.CombinedModule, ThinLTO.CombinedIndex))
1422 return LibcallSymbols;
1427 const std::string &NewModulePath)
const {
1428 return emitFiles(ImportList, ModulePath, NewModulePath,
1429 NewModulePath +
".thinlto.bc",
1435 const std::string &NewModulePath,
StringRef SummaryPath,
1436 std::optional<std::reference_wrapper<ImportsFilesContainer>> ImportsFiles)
1443 ImportList, ModuleToSummariesForIndex,
1444 DeclarationSummaries);
1451 &DeclarationSummaries);
1455 ModulePath, NewModulePath +
".imports", ModuleToSummariesForIndex);
1456 if (ImportsFilesError)
1457 return ImportsFilesError;
1463 ModulePath, ModuleToSummariesForIndex,
1464 [&](
StringRef M) { ImportsFiles->get().push_back(M.str()); });
1477 bool ShouldEmitIndexFiles;
1484 bool ShouldEmitIndexFiles,
bool ShouldEmitImportsFiles,
1487 OnWrite, ShouldEmitImportsFiles, ThinLTOParallelism),
1488 AddStream(
std::
move(AddStream)),
1489 ShouldEmitIndexFiles(ShouldEmitIndexFiles) {
1499class InProcessThinBackend :
public CGThinBackend {
1504 InProcessThinBackend(
1509 bool ShouldEmitIndexFiles,
bool ShouldEmitImportsFiles)
1510 : CGThinBackend(Conf, CombinedIndex, ModuleToDefinedGVSummaries,
1511 AddStream, OnWrite, ShouldEmitIndexFiles,
1512 ShouldEmitImportsFiles, ThinLTOParallelism),
1515 virtual Error runThinLTOBackendThread(
1516 AddStreamFn AddStream, FileCache Cache,
unsigned Task, BitcodeModule BM,
1517 ModuleSummaryIndex &CombinedIndex,
1518 const FunctionImporter::ImportMapTy &ImportList,
1520 const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes> &ResolvedODR,
1522 MapVector<StringRef, BitcodeModule> &ModuleMap) {
1524 llvm::TimeTraceScope timeScope(
"Run ThinLTO backend thread (in-process)",
1526 auto RunThinBackend = [&](
AddStreamFn AddStream) {
1527 LTOLLVMContext BackendContext(Conf);
1528 Expected<std::unique_ptr<Module>> MOrErr = BM.
parseModule(BackendContext);
1532 return thinBackend(Conf, Task, AddStream, **MOrErr, CombinedIndex,
1533 ImportList, DefinedGlobals, &ModuleMap,
1536 if (ShouldEmitIndexFiles) {
1537 if (
auto E = emitFiles(ImportList, ModuleID, ModuleID.str()))
1543 [](uint32_t V) { return V == 0; }))
1546 return RunThinBackend(AddStream);
1550 Conf, CombinedIndex, ModuleID, ImportList, ExportList, ResolvedODR,
1551 DefinedGlobals, CfiFunctionDefs, CfiFunctionDecls);
1552 Expected<AddStreamFn> CacheAddStreamOrErr = Cache(Task,
Key, ModuleID);
1555 AddStreamFn &CacheAddStream = *CacheAddStreamOrErr;
1557 return RunThinBackend(CacheAddStream);
1563 unsigned Task, BitcodeModule BM,
1564 const FunctionImporter::ImportMapTy &ImportList,
1566 const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes> &ResolvedODR,
1567 MapVector<StringRef, BitcodeModule> &ModuleMap)
override {
1569 assert(ModuleToDefinedGVSummaries.
count(ModulePath));
1571 ModuleToDefinedGVSummaries.
find(ModulePath)->second;
1572 BackendThreadPool.async(
1573 [=](BitcodeModule BM, ModuleSummaryIndex &CombinedIndex,
1574 const FunctionImporter::ImportMapTy &ImportList,
1576 const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes>
1579 MapVector<StringRef, BitcodeModule> &ModuleMap) {
1583 Error E = runThinLTOBackendThread(
1584 AddStream, Cache, Task, BM, CombinedIndex, ImportList, ExportList,
1585 ResolvedODR, DefinedGlobals, ModuleMap);
1587 std::unique_lock<std::mutex>
L(ErrMu);
1596 BM, std::ref(CombinedIndex), std::ref(ImportList), std::ref(ExportList),
1597 std::ref(ResolvedODR), std::ref(DefinedGlobals), std::ref(ModuleMap));
1600 OnWrite(std::string(ModulePath));
1610class FirstRoundThinBackend :
public InProcessThinBackend {
1615 FirstRoundThinBackend(
1616 const Config &Conf, ModuleSummaryIndex &CombinedIndex,
1617 ThreadPoolStrategy ThinLTOParallelism,
1618 const DenseMap<StringRef, GVSummaryMapTy> &ModuleToDefinedGVSummaries,
1621 : InProcessThinBackend(Conf, CombinedIndex, ThinLTOParallelism,
1622 ModuleToDefinedGVSummaries, std::
move(CGAddStream),
1623 std::
move(CGCache), nullptr,
1626 IRAddStream(std::
move(IRAddStream)), IRCache(std::
move(IRCache)) {}
1628 Error runThinLTOBackendThread(
1629 AddStreamFn CGAddStream, FileCache CGCache,
unsigned Task,
1630 BitcodeModule BM, ModuleSummaryIndex &CombinedIndex,
1631 const FunctionImporter::ImportMapTy &ImportList,
1633 const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes> &ResolvedODR,
1635 MapVector<StringRef, BitcodeModule> &ModuleMap)
override {
1637 llvm::TimeTraceScope timeScope(
"Run ThinLTO backend thread (first round)",
1639 auto RunThinBackend = [&](
AddStreamFn CGAddStream,
1641 LTOLLVMContext BackendContext(Conf);
1642 Expected<std::unique_ptr<Module>> MOrErr = BM.
parseModule(BackendContext);
1646 return thinBackend(Conf, Task, CGAddStream, **MOrErr, CombinedIndex,
1647 ImportList, DefinedGlobals, &ModuleMap,
1653 if (ShouldEmitIndexFiles) {
1654 if (
auto E = emitFiles(ImportList, ModuleID, ModuleID.str()))
1659 "Both caches for CG and IR should have matching availability");
1662 [](uint32_t V) { return V == 0; }))
1665 return RunThinBackend(CGAddStream, IRAddStream);
1669 Conf, CombinedIndex, ModuleID, ImportList, ExportList, ResolvedODR,
1670 DefinedGlobals, CfiFunctionDefs, CfiFunctionDecls);
1671 Expected<AddStreamFn> CacheCGAddStreamOrErr =
1672 CGCache(Task, CGKey, ModuleID);
1675 AddStreamFn &CacheCGAddStream = *CacheCGAddStreamOrErr;
1679 Expected<AddStreamFn> CacheIRAddStreamOrErr =
1680 IRCache(Task, IRKey, ModuleID);
1683 AddStreamFn &CacheIRAddStream = *CacheIRAddStreamOrErr;
1689 if (CacheCGAddStream || CacheIRAddStream) {
1692 return RunThinBackend(CacheCGAddStream ? CacheCGAddStream : CGAddStream,
1693 CacheIRAddStream ? CacheIRAddStream : IRAddStream);
1705class SecondRoundThinBackend :
public InProcessThinBackend {
1706 std::unique_ptr<SmallVector<StringRef>> IRFiles;
1710 SecondRoundThinBackend(
1711 const Config &Conf, ModuleSummaryIndex &CombinedIndex,
1712 ThreadPoolStrategy ThinLTOParallelism,
1713 const DenseMap<StringRef, GVSummaryMapTy> &ModuleToDefinedGVSummaries,
1717 : InProcessThinBackend(Conf, CombinedIndex, ThinLTOParallelism,
1718 ModuleToDefinedGVSummaries, std::
move(AddStream),
1723 IRFiles(std::
move(IRFiles)), CombinedCGDataHash(CombinedCGDataHash) {}
1725 Error runThinLTOBackendThread(
1726 AddStreamFn AddStream, FileCache Cache,
unsigned Task, BitcodeModule BM,
1727 ModuleSummaryIndex &CombinedIndex,
1728 const FunctionImporter::ImportMapTy &ImportList,
1730 const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes> &ResolvedODR,
1732 MapVector<StringRef, BitcodeModule> &ModuleMap)
override {
1734 llvm::TimeTraceScope timeScope(
"Run ThinLTO backend thread (second round)",
1736 auto RunThinBackend = [&](
AddStreamFn AddStream) {
1737 LTOLLVMContext BackendContext(Conf);
1738 std::unique_ptr<Module> LoadedModule =
1741 return thinBackend(Conf, Task, AddStream, *LoadedModule, CombinedIndex,
1742 ImportList, DefinedGlobals, &ModuleMap,
1747 [](uint32_t V) { return V == 0; }))
1750 return RunThinBackend(AddStream);
1755 Conf, CombinedIndex, ModuleID, ImportList, ExportList, ResolvedODR,
1756 DefinedGlobals, CfiFunctionDefs, CfiFunctionDecls);
1758 std::to_string(CombinedCGDataHash));
1759 Expected<AddStreamFn> CacheAddStreamOrErr = Cache(Task,
Key, ModuleID);
1762 AddStreamFn &CacheAddStream = *CacheAddStreamOrErr;
1764 if (CacheAddStream) {
1767 return RunThinBackend(CacheAddStream);
1777 bool ShouldEmitIndexFiles,
1778 bool ShouldEmitImportsFiles) {
1783 return std::make_unique<InProcessThinBackend>(
1784 Conf, CombinedIndex, Parallelism, ModuleToDefinedGVSummaries,
1785 AddStream, Cache, OnWrite, ShouldEmitIndexFiles,
1786 ShouldEmitImportsFiles);
1812 return std::string(Path);
1816 if (!ParentPath.
empty()) {
1819 llvm::errs() <<
"warning: could not create directory '" << ParentPath
1820 <<
"': " << EC.message() <<
'\n';
1822 return std::string(NewPath);
1827 std::string OldPrefix, NewPrefix, NativeObjectPrefix;
1831 WriteIndexesThinBackend(
1835 std::string OldPrefix, std::string NewPrefix,
1836 std::string NativeObjectPrefix,
bool ShouldEmitImportsFiles,
1839 OnWrite, ShouldEmitImportsFiles, ThinLTOParallelism),
1840 OldPrefix(OldPrefix), NewPrefix(NewPrefix),
1841 NativeObjectPrefix(NativeObjectPrefix),
1842 LinkedObjectsFile(LinkedObjectsFile) {}
1848 const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes> &ResolvedODR,
1856 if (LinkedObjectsFile) {
1857 std::string ObjectPrefix =
1858 NativeObjectPrefix.empty() ? NewPrefix : NativeObjectPrefix;
1859 std::string LinkedObjectsFilePath =
1861 *LinkedObjectsFile << LinkedObjectsFilePath <<
'\n';
1864 BackendThreadPool.async(
1865 [
this](
const StringRef ModulePath,
1866 const FunctionImporter::ImportMapTy &ImportList,
1867 const std::string &OldPrefix,
const std::string &NewPrefix) {
1868 std::string NewModulePath =
1870 auto E = emitFiles(ImportList, ModulePath, NewModulePath);
1872 std::unique_lock<std::mutex>
L(ErrMu);
1880 ModulePath, ImportList, OldPrefix, NewPrefix);
1883 OnWrite(std::string(ModulePath));
1887 bool isSensitiveToInputOrder()
override {
1897 std::string NewPrefix, std::string NativeObjectPrefix,
1904 return std::make_unique<WriteIndexesThinBackend>(
1905 Conf, CombinedIndex, Parallelism, ModuleToDefinedGVSummaries,
1906 OldPrefix, NewPrefix, NativeObjectPrefix, ShouldEmitImportsFiles,
1907 LinkedObjectsFile, OnWrite);
1922 if (ThinLTO.ModuleMap.
empty())
1925 if (ThinLTO.ModulesToCompile && ThinLTO.ModulesToCompile->empty()) {
1926 llvm::errs() <<
"warning: [ThinLTO] No module compiled\n";
1930 if (Conf.CombinedIndexHook &&
1931 !Conf.CombinedIndexHook(ThinLTO.CombinedIndex, GUIDPreservedSymbols))
1936 DenseMap<StringRef, GVSummaryMapTy> ModuleToDefinedGVSummaries(
1937 ThinLTO.ModuleMap.size());
1938 ThinLTO.CombinedIndex.collectDefinedGVSummariesPerModule(
1939 ModuleToDefinedGVSummaries);
1947 for (
auto &
Mod : ThinLTO.ModuleMap)
1948 if (!ModuleToDefinedGVSummaries.
count(
Mod.first))
1951 FunctionImporter::ImportListsTy ImportLists(ThinLTO.ModuleMap.size());
1952 DenseMap<StringRef, FunctionImporter::ExportSetTy> ExportLists(
1953 ThinLTO.ModuleMap.size());
1954 StringMap<std::map<GlobalValue::GUID, GlobalValue::LinkageTypes>> ResolvedODR;
1957 ThinLTO.CombinedIndex.dumpSCCs(
outs());
1959 std::set<GlobalValue::GUID> ExportedGUIDs;
1961 bool WholeProgramVisibilityEnabledInLTO =
1962 Conf.HasWholeProgramVisibility &&
1965 (!Conf.ValidateAllVtablesHaveTypeInfos || Conf.AllVtablesHaveTypeInfos);
1967 ThinLTO.CombinedIndex.setWithWholeProgramVisibility();
1972 DenseSet<GlobalValue::GUID> VisibleToRegularObjSymbols;
1973 if (WholeProgramVisibilityEnabledInLTO &&
1974 Conf.ValidateAllVtablesHaveTypeInfos) {
1977 auto IsVisibleToRegularObj = [&](StringRef
name) {
1978 auto It = GlobalResolutions->find(
name);
1979 return (It == GlobalResolutions->end() ||
1980 It->second.VisibleOutsideSummary || !It->second.Prevailing);
1984 VisibleToRegularObjSymbols,
1985 IsVisibleToRegularObj);
1991 ThinLTO.CombinedIndex, WholeProgramVisibilityEnabledInLTO,
1992 DynamicExportSymbols, VisibleToRegularObjSymbols);
1997 std::map<ValueInfo, std::vector<VTableSlotSummary>> LocalWPDTargetsMap;
1999 LocalWPDTargetsMap);
2002 return ThinLTO.isPrevailingModuleForGUID(GUID, S->modulePath());
2005 MemProfContextDisambiguation ContextDisambiguation;
2006 ContextDisambiguation.
run(ThinLTO.CombinedIndex, isPrevailing);
2013 for (
auto &Res : *GlobalResolutions) {
2016 if (Res.second.Partition != GlobalResolution::External ||
2017 !Res.second.isPrevailingIRSymbol())
2022 if (ThinLTO.CombinedIndex.isGUIDLive(GUID))
2023 ExportedGUIDs.insert(GUID);
2030 releaseGlobalResolutionsMemory();
2032 if (Conf.OptLevel > 0)
2034 isPrevailing, ImportLists, ExportLists);
2038 auto &Defs = ThinLTO.CombinedIndex.cfiFunctionDefs();
2039 ExportedGUIDs.insert(Defs.guid_begin(), Defs.guid_end());
2040 auto &Decls = ThinLTO.CombinedIndex.cfiFunctionDecls();
2041 ExportedGUIDs.insert(Decls.guid_begin(), Decls.guid_end());
2043 auto isExported = [&](StringRef ModuleIdentifier, ValueInfo
VI) {
2044 const auto &ExportList = ExportLists.
find(ModuleIdentifier);
2045 return (ExportList != ExportLists.end() && ExportList->second.
count(VI)) ||
2046 ExportedGUIDs.count(
VI.getGUID());
2052 LocalWPDTargetsMap);
2057 auto recordNewLinkage = [&](StringRef ModuleIdentifier,
2060 ResolvedODR[ModuleIdentifier][
GUID] = NewLinkage;
2063 recordNewLinkage, GUIDPreservedSymbols);
2072 TimeTraceScopeExit.release();
2075 ThinLTO.ModulesToCompile ? *ThinLTO.ModulesToCompile : ThinLTO.ModuleMap;
2077 auto RunBackends = [&](ThinBackendProc *BackendProcess) ->
Error {
2078 auto ProcessOneModule = [&](
int I) ->
Error {
2082 return BackendProcess->start(
2083 RegularLTO.ParallelCodeGenParallelismLevel +
I,
Mod.second,
2084 ImportLists[
Mod.first], ExportLists[
Mod.first],
2085 ResolvedODR[
Mod.first], ThinLTO.ModuleMap);
2088 BackendProcess->setup(ModuleMap.
size(),
2089 RegularLTO.ParallelCodeGenParallelismLevel,
2090 RegularLTO.CombinedModule->getTargetTriple());
2092 if (BackendProcess->getThreadCount() == 1 ||
2093 BackendProcess->isSensitiveToInputOrder()) {
2099 for (
int I = 0,
E = ModuleMap.
size();
I !=
E; ++
I)
2100 if (
Error E = ProcessOneModule(
I))
2107 std::vector<BitcodeModule *> ModulesVec;
2108 ModulesVec.reserve(ModuleMap.
size());
2109 for (
auto &
Mod : ModuleMap)
2110 ModulesVec.push_back(&
Mod.second);
2112 if (
Error E = ProcessOneModule(
I))
2115 return BackendProcess->wait();
2119 std::unique_ptr<ThinBackendProc> BackendProc =
2120 ThinLTO.Backend(Conf, ThinLTO.CombinedIndex, ModuleToDefinedGVSummaries,
2122 return RunBackends(BackendProc.get());
2130 LLVM_DEBUG(
dbgs() <<
"[TwoRounds] Initializing ThinLTO two-codegen rounds\n");
2133 auto Parallelism = ThinLTO.Backend.getParallelism();
2136 cgdata::StreamCacheData CG(MaxTasks, Cache,
"CG"),
IR(MaxTasks, Cache,
"IR");
2141 LLVM_DEBUG(
dbgs() <<
"[TwoRounds] Running the first round of codegen\n");
2142 auto FirstRoundLTO = std::make_unique<FirstRoundThinBackend>(
2143 Conf, ThinLTO.CombinedIndex, Parallelism, ModuleToDefinedGVSummaries,
2144 CG.AddStream, CG.Cache,
IR.AddStream,
IR.Cache);
2145 if (
Error E = RunBackends(FirstRoundLTO.get()))
2150 if (
Error E = CombinedHashOrErr.takeError())
2152 auto CombinedHash = *CombinedHashOrErr;
2153 LLVM_DEBUG(
dbgs() <<
"[TwoRounds] CGData hash: " << CombinedHash <<
"\n");
2157 LLVM_DEBUG(
dbgs() <<
"[TwoRounds] Running the second round of codegen\n");
2158 auto SecondRoundLTO = std::make_unique<SecondRoundThinBackend>(
2159 Conf, ThinLTO.CombinedIndex, Parallelism, ModuleToDefinedGVSummaries,
2160 AddStream, Cache,
IR.getResult(), CombinedHash);
2161 return RunBackends(SecondRoundLTO.get());
2171 if (!Filename.empty() &&
Count != -1)
2179 if (
Error E = ResultOrErr.takeError())
2180 return std::move(E);
2183 (*ResultOrErr)->keep();
2191 if (StatsFilename.
empty())
2202 return std::move(StatsFile);
2210 std::vector<int> ModulesOrdering(Seq.begin(), Seq.end());
2211 llvm::sort(ModulesOrdering, [&](
int LeftIndex,
int RightIndex) {
2212 auto LSize = R[LeftIndex]->getBuffer().size();
2213 auto RSize = R[RightIndex]->getBuffer().size();
2214 return LSize > RSize;
2216 return ModulesOrdering;
2226class OutOfProcessThinBackend :
public CGThinBackend {
2232 SString LinkerOutputFile;
2234 SString DistributorPath;
2237 SString RemoteCompiler;
2246 std::atomic<size_t> CachedJobs{0};
2251 StringRef NativeObjectPath;
2252 StringRef SummaryIndexPath;
2254 std::string CacheKey;
2256 bool Cached =
false;
2265 unsigned ThinLTOTaskOffset;
2268 llvm::Triple Triple;
2274 OutOfProcessThinBackend(
2275 const Config &Conf, ModuleSummaryIndex &CombinedIndex,
2276 ThreadPoolStrategy ThinLTOParallelism,
2277 const DenseMap<StringRef, GVSummaryMapTy> &ModuleToDefinedGVSummaries,
2279 bool ShouldEmitIndexFiles,
bool ShouldEmitImportsFiles,
2280 StringRef LinkerOutputFile, StringRef Distributor,
2284 : CGThinBackend(Conf, CombinedIndex, ModuleToDefinedGVSummaries,
2285 AddStream, OnWrite, ShouldEmitIndexFiles,
2286 ShouldEmitImportsFiles, ThinLTOParallelism),
2287 LinkerOutputFile(LinkerOutputFile), DistributorPath(Distributor),
2288 DistributorArgs(DistributorArgs), RemoteCompiler(RemoteCompiler),
2289 RemoteCompilerPrependArgs(RemoteCompilerPrependArgs),
2290 RemoteCompilerArgs(RemoteCompilerArgs), SaveTemps(SaveTemps),
2291 Cache(std::
move(CacheFn)) {}
2293 void setup(
unsigned ThinLTONumTasks,
unsigned ThinLTOTaskOffset,
2294 llvm::Triple Triple)
override {
2296 Jobs.
resize((
size_t)ThinLTONumTasks);
2297 this->ThinLTOTaskOffset = ThinLTOTaskOffset;
2298 this->Triple = Triple;
2299 this->Conf.
Dtlto = 1;
2302 virtual Error runThinLTOBackendThread(
2303 Job &J,
const FunctionImporter::ImportMapTy &ImportList,
2305 const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes>
2308 TimeTraceScope TimeScope(
"Emit individual index for DTLTO",
2309 J.SummaryIndexPath);
2310 if (
auto E = emitFiles(ImportList, J.ModuleID, J.ModuleID.str(),
2311 J.SummaryIndexPath, J.ImportsFiles))
2317 [](uint32_t V) { return V == 0; }))
2322 TimeTraceScope TimeScope(
"Check cache for DTLTO", J.SummaryIndexPath);
2324 ModuleToDefinedGVSummaries.
find(J.ModuleID)->second;
2328 ExportList, ResolvedODR, DefinedGlobals,
2329 CfiFunctionDefs, CfiFunctionDecls);
2332 auto CacheAddStreamExp = Cache(J.Task, J.CacheKey, J.ModuleID);
2333 if (
Error Err = CacheAddStreamExp.takeError())
2338 if (!CacheAddStream) {
2340 CachedJobs.fetch_add(1);
2345 J.CacheAddStream = std::move(CacheAddStream);
2351 unsigned Task, BitcodeModule BM,
2352 const FunctionImporter::ImportMapTy &ImportList,
2354 const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes> &ResolvedODR,
2355 MapVector<StringRef, BitcodeModule> &ModuleMap)
override {
2361 itostr(Task) +
"." + UID +
".native.o");
2363 Job &J = Jobs[Task - ThinLTOTaskOffset];
2366 Saver.
save(ObjFilePath.str()),
2367 Saver.
save(ObjFilePath.str() +
".thinlto.bc"),
2376 if (!ShouldEmitIndexFiles)
2380 assert(ModuleToDefinedGVSummaries.
count(ModulePath));
2384 BackendThreadPool.async(
2385 [=](Job &J,
const FunctionImporter::ImportMapTy &ImportList,
2387 const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes>
2392 "Emit individual index and check cache for DTLTO");
2394 runThinLTOBackendThread(J, ImportList, ExportList, ResolvedODR);
2396 std::unique_lock<std::mutex>
L(ErrMu);
2405 std::ref(J), std::ref(ImportList), std::ref(ExportList),
2406 std::ref(ResolvedODR));
2420 void buildCommonRemoteCompilerOptions() {
2421 const lto::Config &
C = Conf;
2422 auto &
Ops = CodegenOptions;
2426 if (
C.Options.EmitAddrsig)
2427 Ops.push_back(
"-faddrsig");
2428 if (
C.Options.FunctionSections)
2429 Ops.push_back(
"-ffunction-sections");
2430 if (
C.Options.DataSections)
2431 Ops.push_back(
"-fdata-sections");
2436 Ops.push_back(
"-fpic");
2440 if (!
C.PGOWarnMismatch) {
2441 Ops.push_back(
"-mllvm");
2442 Ops.push_back(
"-no-pgo-warn-mismatch");
2447 if (!
C.SampleProfile.empty()) {
2449 Saver.
save(
"-fprofile-sample-use=" + Twine(
C.SampleProfile)));
2450 CommonInputs.
insert(
C.SampleProfile);
2454 Ops.push_back(
"-Wno-unused-command-line-argument");
2457 if (!RemoteCompilerArgs.
empty())
2458 for (
auto &a : RemoteCompilerArgs)
2464 bool emitDistributorJson(StringRef DistributorJson) {
2467 raw_fd_ostream OS(DistributorJson, EC);
2471 json::OStream JOS(OS);
2474 JOS.attributeObject(
"common", [&]() {
2475 JOS.attribute(
"linker_output", LinkerOutputFile);
2477 JOS.attributeArray(
"args", [&]() {
2478 JOS.value(RemoteCompiler);
2481 if (!RemoteCompilerPrependArgs.
empty())
2482 for (
auto &
A : RemoteCompilerPrependArgs)
2487 JOS.value(Saver.
save(
"--target=" + Triple.
str()));
2489 for (
const auto &
A : CodegenOptions)
2493 JOS.attribute(
"inputs",
Array(CommonInputs));
2497 JOS.attributeArray(
"jobs", [&]() {
2498 for (
const auto &J : Jobs) {
2506 SmallVector<StringRef, 1> Outputs;
2509 JOS.attributeArray(
"args", [&]() {
2510 JOS.value(J.ModuleID);
2514 Saver.
save(
"-fthinlto-index=" + Twine(J.SummaryIndexPath)));
2518 JOS.value(J.NativeObjectPath);
2526 JOS.attribute(
"inputs",
Array(Inputs));
2528 JOS.attribute(
"outputs",
Array(Outputs));
2537 void removeFile(StringRef FileName) {
2539 if (EC && EC != std::make_error_code(std::errc::no_such_file_or_directory))
2540 errs() <<
"warning: could not remove the file '" << FileName
2541 <<
"': " <<
EC.message() <<
"\n";
2544 Error wait()
override {
2547 BackendThreadPool.wait();
2549 return std::move(*Err);
2552 llvm::TimeTraceScope TimeScope(
"Remove DTLTO temporary files");
2554 for (
auto &Job : Jobs) {
2555 removeFile(Job.NativeObjectPath);
2556 if (!ShouldEmitIndexFiles)
2557 removeFile(Job.SummaryIndexPath);
2561 const StringRef BCError =
"DTLTO backend compilation: ";
2563 buildCommonRemoteCompilerOptions();
2567 llvm::TimeTraceScope TimeScope(
"Emit DTLTO JSON");
2569 UID +
".dist-file.json");
2573 if (!emitDistributorJson(JsonFile))
2575 BCError +
"failed to generate distributor JSON script: " + JsonFile,
2580 removeFile(JsonFile);
2584 llvm::TimeTraceScope TimeScope(
"Execute DTLTO distributor",
2587 if (CachedJobs.load() < Jobs.size()) {
2590 Args.push_back(JsonFile);
2597 BCError +
"distributor execution failed" +
2598 (!ErrMsg.empty() ?
": " + ErrMsg + Twine(
".") : Twine(
".")),
2605 llvm::TimeTraceScope FilesScope(
"Add DTLTO files to the link");
2606 for (
auto &Job : Jobs) {
2607 if (!Job.CacheKey.empty() && Job.Cached) {
2613 auto ObjFileMbOrErr =
2616 if (std::error_code EC = ObjFileMbOrErr.getError())
2618 BCError +
"cannot open native object file: " +
2619 Job.NativeObjectPath +
": " +
EC.message(),
2622 MemoryBufferRef ObjFileMbRef = ObjFileMbOrErr->get()->getMemBufferRef();
2626 assert(Job.CacheAddStream);
2628 auto CachedFileStreamOrErr =
2629 Job.CacheAddStream(Job.Task, Job.ModuleID);
2630 if (!CachedFileStreamOrErr)
2632 CachedFileStreamOrErr.takeError(),
2634 "Cannot get a cache file stream: %s",
2635 Job.NativeObjectPath.data()));
2637 auto &CacheStream = *(CachedFileStreamOrErr->get());
2638 *(CacheStream.OS) << ObjFileMbRef.
getBuffer();
2639 if (
Error Err = CacheStream.commit())
2642 auto StreamOrErr = AddStream(Job.Task, Job.ModuleID);
2643 if (
Error Err = StreamOrErr.takeError())
2645 auto &Stream = *StreamOrErr->get();
2647 if (
Error Err = Stream.commit())
2659 bool ShouldEmitIndexFiles,
bool ShouldEmitImportsFiles,
2668 return std::make_unique<OutOfProcessThinBackend>(
2669 Conf, CombinedIndex, Parallelism, ModuleToDefinedGVSummaries,
2670 AddStream, Cache, OnWrite, ShouldEmitIndexFiles,
2671 ShouldEmitImportsFiles, LinkerOutputFile, Distributor,
2672 DistributorArgs, RemoteCompiler, RemoteCompilerPrependArgs,
2673 RemoteCompilerArgs, SaveTemps);