27#include "llvm/Config/llvm-config.h"
52#include "llvm/Support/VCSRevision.h"
66using namespace object;
68#define DEBUG_TYPE "lto"
74 cl::desc(
"Dump the SCCs in the ThinLTO index's callgraph"));
82 cl::desc(
"Enable global value internalization in LTO"));
86 cl::desc(
"Keep copies of symbols in LTO indexing"));
103 const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes> &ResolvedODR,
114 Hasher.
update(LLVM_VERSION_STRING);
116 Hasher.
update(LLVM_REVISION);
124 auto AddUnsigned = [&](
unsigned I) {
134 auto AddUint8 = [&](
const uint8_t I) {
158 AddUnsigned(
static_cast<int>(Conf.
CGOptLevel));
159 AddUnsigned(
static_cast<int>(Conf.
CGFileType));
169 auto ModHash = Index.getModuleHash(ModuleID);
174 std::vector<uint64_t> ExportsGUID;
175 ExportsGUID.reserve(ExportList.
size());
176 for (
const auto &VI : ExportList)
177 ExportsGUID.push_back(VI.getGUID());
181 for (
auto GUID : ExportsGUID)
186 auto Comp = [&](
const std::pair<StringRef, GlobalValue::GUID> &L,
187 const std::pair<StringRef, GlobalValue::GUID> &R) {
188 return std::make_pair(Index.getModule(L.first)->second, L.second) <
189 std::make_pair(Index.getModule(R.first)->second, R.second);
195 for (
const auto &[FromModule, GUID,
Type] : SortedImportList)
196 ++ModuleToNumImports[FromModule];
198 std::optional<StringRef> LastModule;
199 for (
const auto &[FromModule, GUID,
Type] : SortedImportList) {
200 if (LastModule != FromModule) {
204 LastModule = FromModule;
205 auto ModHash = Index.getModule(FromModule)->second;
207 AddUint64(ModuleToNumImports[FromModule]);
214 for (
auto &Entry : ResolvedODR) {
223 std::set<GlobalValue::GUID> UsedCfiDefs;
224 std::set<GlobalValue::GUID> UsedCfiDecls;
227 std::set<GlobalValue::GUID> UsedTypeIds;
230 if (CfiFunctionDefs.
contains(ValueGUID))
231 UsedCfiDefs.insert(ValueGUID);
232 if (CfiFunctionDecls.
contains(ValueGUID))
233 UsedCfiDecls.insert(ValueGUID);
238 AddUnsigned(GS->getVisibility());
239 AddUnsigned(GS->isLive());
240 AddUnsigned(GS->canAutoHide());
242 AddUnsigned(VI.isDSOLocal(Index.withDSOLocalPropagation()));
243 AddUsedCfiGlobal(VI.getGUID());
245 if (
auto *GVS = dyn_cast<GlobalVarSummary>(GS)) {
246 AddUnsigned(GVS->maybeReadOnly());
247 AddUnsigned(GVS->maybeWriteOnly());
249 if (
auto *FS = dyn_cast<FunctionSummary>(GS)) {
250 for (
auto &TT : FS->type_tests())
251 UsedTypeIds.insert(TT);
252 for (
auto &TT : FS->type_test_assume_vcalls())
253 UsedTypeIds.insert(TT.GUID);
254 for (
auto &TT : FS->type_checked_load_vcalls())
255 UsedTypeIds.insert(TT.GUID);
256 for (
auto &TT : FS->type_test_assume_const_vcalls())
257 UsedTypeIds.insert(TT.VFunc.GUID);
258 for (
auto &TT : FS->type_checked_load_const_vcalls())
259 UsedTypeIds.insert(TT.VFunc.GUID);
260 for (
auto &ET : FS->calls()) {
261 AddUnsigned(ET.first.isDSOLocal(Index.withDSOLocalPropagation()));
262 AddUsedCfiGlobal(ET.first.getGUID());
269 for (
auto &GS : DefinedGlobals) {
273 AddUsedCfiGlobal(GS.first);
274 AddUsedThings(GS.second);
279 for (
const auto &[FromModule, GUID,
Type] : SortedImportList) {
284 if (
auto *AS = dyn_cast_or_null<AliasSummary>(S))
285 AddUsedThings(AS->getBaseObject());
291 AddUnsigned(S.TTRes.TheKind);
292 AddUnsigned(S.TTRes.SizeM1BitWidth);
294 AddUint64(S.TTRes.AlignLog2);
295 AddUint64(S.TTRes.SizeM1);
296 AddUint64(S.TTRes.BitMask);
297 AddUint64(S.TTRes.InlineBits);
299 AddUint64(S.WPDRes.size());
300 for (
auto &WPD : S.WPDRes) {
301 AddUnsigned(WPD.first);
302 AddUnsigned(WPD.second.TheKind);
303 AddString(WPD.second.SingleImplName);
305 AddUint64(WPD.second.ResByArg.size());
306 for (
auto &ByArg : WPD.second.ResByArg) {
307 AddUint64(ByArg.first.size());
310 AddUnsigned(ByArg.second.TheKind);
311 AddUint64(ByArg.second.Info);
312 AddUnsigned(ByArg.second.Byte);
313 AddUnsigned(ByArg.second.Bit);
320 auto TidIter = Index.typeIds().equal_range(TId);
322 AddTypeIdSummary(
I.second.first,
I.second.second);
325 AddUnsigned(UsedCfiDefs.size());
326 for (
auto &V : UsedCfiDefs)
329 AddUnsigned(UsedCfiDecls.size());
330 for (
auto &V : UsedCfiDecls)
336 Hasher.
update(FileOrErr.get()->getBuffer());
341 Hasher.
update(FileOrErr.get()->getBuffer());
346 return toHex(Hasher.
result());
360 return toHex(Hasher.
result());
372 C.VisibilityScheme ==
Config::ELF ? VI.getELFVisibility()
374 for (
auto &S : VI.getSummaryList()) {
389 if (isPrevailing(VI.getGUID(), S.get())) {
402 S->setCanAutoHide(VI.canAutoHide() &&
403 !GUIDPreservedSymbols.
count(VI.getGUID()));
406 Visibility = S->getVisibility();
409 else if (!isa<AliasSummary>(S.get()) &&
410 !GlobalInvolvedWithAlias.
count(S.get()))
417 S->setVisibility(Visibility);
419 if (S->linkage() != OriginalLinkage)
420 recordNewLinkage(S->modulePath(), VI.getGUID(), S->linkage());
424 for (
auto &S : VI.getSummaryList()) {
429 S->setVisibility(Visibility);
451 for (
auto &
I : Index)
452 for (
auto &S :
I.second.SummaryList)
453 if (
auto AS = dyn_cast<AliasSummary>(S.get()))
454 GlobalInvolvedWithAlias.
insert(&AS->getAliasee());
456 for (
auto &
I : Index)
458 GlobalInvolvedWithAlias, isPrevailing,
459 recordNewLinkage, GUIDPreservedSymbols);
466 auto ExternallyVisibleCopies =
468 [](
const std::unique_ptr<GlobalValueSummary> &Summary) {
469 return !GlobalValue::isLocalLinkage(Summary->linkage());
472 for (
auto &S : VI.getSummaryList()) {
475 if (isExported(S->modulePath(), VI)) {
534 if (isPrevailing(VI.getGUID(), S.get()) && ExternallyVisibleCopies == 1)
546 for (
auto &
I : Index)
555 std::unique_ptr<InputFile> File(
new InputFile);
561 File->TargetTriple = FOrErr->TheReader.getTargetTriple();
562 File->SourceFileName = FOrErr->TheReader.getSourceFileName();
563 File->COFFLinkerOpts = FOrErr->TheReader.getCOFFLinkerOpts();
564 File->DependentLibraries = FOrErr->TheReader.getDependentLibraries();
565 File->ComdatTable = FOrErr->TheReader.getComdatTable();
567 for (
unsigned I = 0;
I != FOrErr->Mods.size(); ++
I) {
568 size_t Begin = File->Symbols.size();
570 FOrErr->TheReader.module_symbols(
I))
574 File->Symbols.push_back(
Sym);
575 File->ModuleSymIndices.push_back({Begin, File->Symbols.size()});
578 File->Mods = FOrErr->Mods;
579 File->Strtab = std::move(FOrErr->Strtab);
580 return std::move(File);
584 return Mods[0].getModuleIdentifier();
588 assert(Mods.size() == 1 &&
"Expect only one bitcode module");
592LTO::RegularLTOState::RegularLTOState(
unsigned ParallelCodeGenParallelismLevel,
594 : ParallelCodeGenParallelismLevel(ParallelCodeGenParallelismLevel),
595 Ctx(Conf), CombinedModule(
std::make_unique<
Module>(
"ld-temp.o", Ctx)),
596 Mover(
std::make_unique<
IRMover>(*CombinedModule)) {
600LTO::ThinLTOState::ThinLTOState(
ThinBackend BackendParam)
601 : Backend(
std::
move(BackendParam)), CombinedIndex(
false) {
602 if (!Backend.isValid())
608 unsigned ParallelCodeGenParallelismLevel,
LTOKind LTOMode)
610 RegularLTO(ParallelCodeGenParallelismLevel, this->Conf),
616 Alloc = std::make_unique<BumpPtrAllocator>();
617 GlobalResolutionSymbolSaver = std::make_unique<llvm::StringSaver>(*Alloc);
628 unsigned Partition,
bool InSummary) {
629 auto *ResI = Res.
begin();
630 auto *ResE = Res.
end();
632 const Triple TT(RegularLTO.CombinedModule->getTargetTriple());
639 if (GlobalResolutionSymbolSaver && !GlobalResolutions->contains(SymbolName))
640 SymbolName = GlobalResolutionSymbolSaver->save(SymbolName);
642 auto &GlobalRes = (*GlobalResolutions)[SymbolName];
643 GlobalRes.UnnamedAddr &=
Sym.isUnnamedAddr();
645 assert(!GlobalRes.Prevailing &&
646 "Multiple prevailing defs are not allowed");
647 GlobalRes.Prevailing =
true;
648 GlobalRes.IRName = std::string(
Sym.getIRName());
649 }
else if (!GlobalRes.Prevailing && GlobalRes.IRName.empty()) {
656 GlobalRes.IRName = std::string(
Sym.getIRName());
670 if (GlobalRes.IRName !=
Sym.getIRName()) {
671 GlobalRes.Partition = GlobalResolution::External;
672 GlobalRes.VisibleOutsideSummary =
true;
680 (GlobalRes.Partition != GlobalResolution::Unknown &&
681 GlobalRes.Partition != Partition)) {
682 GlobalRes.Partition = GlobalResolution::External;
685 GlobalRes.Partition = Partition;
689 GlobalRes.VisibleOutsideSummary |=
696void LTO::releaseGlobalResolutionsMemory() {
698 GlobalResolutions.reset();
700 GlobalResolutionSymbolSaver.reset();
708 auto ResI = Res.
begin();
713 OS <<
"-r=" << Path <<
',' <<
Sym.getName() <<
',';
730 assert(!CalledGetMaxTasks);
735 if (RegularLTO.CombinedModule->getTargetTriple().empty()) {
736 RegularLTO.CombinedModule->setTargetTriple(Input->getTargetTriple());
742 for (
unsigned I = 0;
I != Input->Mods.size(); ++
I)
743 if (
Error Err = addModule(*Input,
I, ResI, Res.
end()))
757 if (EnableSplitLTOUnit) {
761 if (*EnableSplitLTOUnit != LTOInfo->EnableSplitLTOUnit)
762 ThinLTO.CombinedIndex.setPartiallySplitLTOUnits();
764 EnableSplitLTOUnit = LTOInfo->EnableSplitLTOUnit;
769 !LTOInfo->UnifiedLTO)
770 return make_error<StringError>(
771 "unified LTO compilation must use "
772 "compatible bitcode modules (use -funified-lto)",
780 auto ModSyms = Input.module_symbols(ModI);
781 addModuleToGlobalRes(ModSyms, {ResI, ResE},
782 IsThinLTO ? ThinLTO.ModuleMap.size() + 1 : 0,
783 LTOInfo->HasSummary);
786 return addThinLTO(BM, ModSyms, ResI, ResE);
788 RegularLTO.EmptyCombinedModule =
false;
790 addRegularLTO(BM, ModSyms, ResI, ResE);
794 if (!LTOInfo->HasSummary)
795 return linkRegularLTO(std::move(*ModOrErr),
false);
801 RegularLTO.ModsWithSummaries.push_back(std::move(*ModOrErr));
817 std::set<const Comdat *> &NonPrevailingComdats) {
822 if (!NonPrevailingComdats.count(
C))
831 if (
auto GO = dyn_cast<GlobalObject>(&GV))
832 GO->setComdat(
nullptr);
842 RegularLTOState::AddedModule
Mod;
849 Mod.M = std::move(*MOrErr);
851 if (
Error Err =
M.materializeMetadata())
852 return std::move(Err);
859 if (
NamedMDNode *CfiFunctionsMD =
M.getNamedMetadata(
"cfi.functions"))
860 M.eraseNamedMetadata(CfiFunctionsMD);
868 if (GV.hasAppendingLinkage())
869 Mod.Keep.push_back(&GV);
872 for (
auto &GA :
M.aliases())
874 AliasedGlobals.
insert(GO);
883 auto MsymI = SymTab.
symbols().begin(), MsymE = SymTab.
symbols().end();
885 while (MsymI != MsymE) {
895 std::set<const Comdat *> NonPrevailingComdats;
905 if (
GlobalValue *GV = dyn_cast_if_present<GlobalValue *>(Msym)) {
907 if (
Sym.isUndefined())
909 Mod.Keep.push_back(GV);
920 }
else if (isa<GlobalObject>(GV) &&
921 (GV->hasLinkOnceODRLinkage() || GV->hasWeakODRLinkage() ||
922 GV->hasAvailableExternallyLinkage()) &&
923 !AliasedGlobals.
count(cast<GlobalObject>(GV))) {
929 Mod.Keep.push_back(GV);
932 NonPrevailingComdats.insert(GV->getComdat());
933 cast<GlobalObject>(GV)->setComdat(
nullptr);
938 GV->setDSOLocal(
true);
939 if (GV->hasDLLImportStorageClass())
941 DefaultStorageClass);
943 }
else if (
auto *AS =
944 dyn_cast_if_present<ModuleSymbolTable::AsmSymbol *>(Msym)) {
947 NonPrevailingAsmSymbols.
insert(AS->first);
955 if (
Sym.isCommon()) {
958 auto &CommonRes = RegularLTO.Commons[std::string(
Sym.getIRName())];
959 CommonRes.Size = std::max(CommonRes.Size,
Sym.getCommonSize());
960 if (
uint32_t SymAlignValue =
Sym.getCommonAlignment()) {
961 CommonRes.Alignment =
962 std::max(
Align(SymAlignValue), CommonRes.Alignment);
968 if (!
M.getComdatSymbolTable().empty())
974 if (!
M.getModuleInlineAsm().empty()) {
975 std::string NewIA =
".lto_discard";
976 if (!NonPrevailingAsmSymbols.
empty()) {
980 if (!NonPrevailingAsmSymbols.
count(Alias))
983 NewIA +=
" " + llvm::join(NonPrevailingAsmSymbols,
", ");
986 M.setModuleInlineAsm(NewIA +
M.getModuleInlineAsm());
990 return std::move(
Mod);
993Error LTO::linkRegularLTO(RegularLTOState::AddedModule
Mod,
994 bool LivenessFromIndex) {
995 std::vector<GlobalValue *>
Keep;
997 if (LivenessFromIndex && !ThinLTO.CombinedIndex.isGUIDLive(GV->
getGUID())) {
998 if (
Function *
F = dyn_cast<Function>(GV)) {
999 if (DiagnosticOutputFile) {
1000 if (
Error Err =
F->materialize())
1005 <<
" not added to the combined module ");
1019 RegularLTO.CombinedModule->getNamedValue(GV->
getName());
1026 return RegularLTO.Mover->move(std::move(
Mod.M),
Keep,
nullptr,
1039 if (!
Sym.getIRName().empty()) {
1050 return ThinLTO.PrevailingModuleForGUID[GUID] ==
1051 BM.getModuleIdentifier();
1060 if (!
Sym.getIRName().empty()) {
1064 assert(ThinLTO.PrevailingModuleForGUID[GUID] ==
1072 if (
auto S = ThinLTO.CombinedIndex.findSummaryInModule(
1080 if (
auto S = ThinLTO.CombinedIndex.findSummaryInModule(
1082 S->setDSOLocal(
true);
1088 if (!ThinLTO.ModuleMap.insert({BM.getModuleIdentifier(), BM}).second)
1089 return make_error<StringError>(
1090 "Expected at most one ThinLTO module per bitcode file",
1094 if (!ThinLTO.ModulesToCompile)
1095 ThinLTO.ModulesToCompile = ModuleMapType();
1102 <<
" to compile\n");
1111 CalledGetMaxTasks =
true;
1112 auto ModuleCount = ThinLTO.ModulesToCompile ? ThinLTO.ModulesToCompile->size()
1113 : ThinLTO.ModuleMap.size();
1114 return RegularLTO.ParallelCodeGenParallelismLevel + ModuleCount;
1119Error LTO::checkPartiallySplit() {
1120 if (!ThinLTO.CombinedIndex.partiallySplitLTOUnits())
1123 const Module *Combined = RegularLTO.CombinedModule.get();
1129 Combined, Intrinsic::type_checked_load_relative);
1133 if ((TypeTestFunc && !TypeTestFunc->
use_empty()) ||
1134 (TypeCheckedLoadFunc && !TypeCheckedLoadFunc->
use_empty()) ||
1135 (TypeCheckedLoadRelativeFunc &&
1136 !TypeCheckedLoadRelativeFunc->
use_empty()))
1137 return make_error<StringError>(
1138 "inconsistent LTO Unit splitting (recompile with -fsplit-lto-unit)",
1143 for (
auto &
P : ThinLTO.CombinedIndex) {
1144 for (
auto &S :
P.second.SummaryList) {
1145 auto *FS = dyn_cast<FunctionSummary>(S.get());
1148 if (!FS->type_test_assume_vcalls().empty() ||
1149 !FS->type_checked_load_vcalls().empty() ||
1150 !FS->type_test_assume_const_vcalls().empty() ||
1151 !FS->type_checked_load_const_vcalls().empty() ||
1152 !FS->type_tests().empty())
1153 return make_error<StringError>(
1154 "inconsistent LTO Unit splitting (recompile with -fsplit-lto-unit)",
1165 for (
auto &Res : *GlobalResolutions) {
1168 if (Res.second.IRName.empty())
1174 if (Res.second.VisibleOutsideSummary && Res.second.
Prevailing)
1175 GUIDPreservedSymbols.
insert(GUID);
1178 DynamicExportSymbols.insert(GUID);
1180 GUIDPrevailingResolutions[GUID] =
1185 auto It = GUIDPrevailingResolutions.
find(
G);
1186 if (It == GUIDPrevailingResolutions.
end())
1195 if (!StatsFileOrErr)
1196 return StatsFileOrErr.takeError();
1197 std::unique_ptr<ToolOutputFile> StatsFile = std::move(StatsFileOrErr.get());
1205 ThinLTO.CombinedIndex.setWithSupportsHotColdNew();
1207 Error Result = runRegularLTO(AddStream);
1211 Result = runThinLTO(AddStream, Cache, GUIDPreservedSymbols);
1221 if (Index.withSupportsHotColdNew())
1229 for (
auto &
F :
Mod) {
1230 for (
auto &BB :
F) {
1231 for (
auto &
I : BB) {
1232 auto *CI = dyn_cast<CallBase>(&
I);
1235 if (CI->hasFnAttr(
"memprof"))
1236 CI->removeFnAttr(
"memprof");
1243 CI->setMetadata(LLVMContext::MD_memprof,
nullptr);
1244 CI->setMetadata(LLVMContext::MD_callsite,
nullptr);
1258 return DiagFileOrErr.takeError();
1259 DiagnosticOutputFile = std::move(*DiagFileOrErr);
1263 for (
auto &M : RegularLTO.ModsWithSummaries)
1264 if (
Error Err = linkRegularLTO(std::move(M),
1272 if (
Error Err = checkPartiallySplit())
1277 const DataLayout &
DL = RegularLTO.CombinedModule->getDataLayout();
1278 for (
auto &
I : RegularLTO.Commons) {
1279 if (!
I.second.Prevailing)
1282 GlobalVariable *OldGV = RegularLTO.CombinedModule->getNamedGlobal(
I.first);
1283 if (OldGV &&
DL.getTypeAllocSize(OldGV->
getValueType()) ==
I.second.Size) {
1291 auto *GV =
new GlobalVariable(*RegularLTO.CombinedModule, Ty,
false,
1294 GV->setAlignment(
I.second.Alignment);
1306 bool WholeProgramVisibilityEnabledInLTO =
1315 auto It = GlobalResolutions->find(
name);
1316 return (It == GlobalResolutions->end() || It->second.VisibleOutsideSummary);
1322 *RegularLTO.CombinedModule, WholeProgramVisibilityEnabledInLTO,
1324 IsVisibleToRegularObj);
1326 WholeProgramVisibilityEnabledInLTO);
1333 for (
const auto &R : *GlobalResolutions) {
1335 RegularLTO.CombinedModule->getNamedValue(
R.second.IRName);
1336 if (!
R.second.isPrevailingIRSymbol())
1338 if (
R.second.Partition != 0 &&
1339 R.second.Partition != GlobalResolution::External)
1374 backend(Conf, AddStream, RegularLTO.ParallelCodeGenParallelismLevel,
1375 *RegularLTO.CombinedModule, ThinLTO.CombinedIndex))
1386 [](
const char *
Name) { return Name; });
1387 return LibcallSymbols;
1392 const std::string &NewModulePath)
const {
1398 ImportList, ModuleToSummariesForIndex,
1399 DeclarationSummaries);
1404 return createFileError(
"cannot open " + NewModulePath +
".thinlto.bc", EC);
1407 &DeclarationSummaries);
1411 ModulePath, NewModulePath +
".imports", ModuleToSummariesForIndex);
1412 if (ImportFilesError)
1413 return ImportFilesError;
1426 bool ShouldEmitIndexFiles;
1429 InProcessThinBackend(
1434 bool ShouldEmitIndexFiles,
bool ShouldEmitImportsFiles)
1436 OnWrite, ShouldEmitImportsFiles, ThinLTOParallelism),
1438 ShouldEmitIndexFiles(ShouldEmitIndexFiles) {
1447 virtual Error runThinLTOBackendThread(
1452 const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes> &ResolvedODR,
1455 auto RunThinBackend = [&](
AddStreamFn AddStream) {
1461 return thinBackend(Conf, Task, AddStream, **MOrErr, CombinedIndex,
1462 ImportList, DefinedGlobals, &ModuleMap,
1468 if (ShouldEmitIndexFiles) {
1469 if (
auto E = emitFiles(ImportList, ModuleID, ModuleID.str()))
1475 [](
uint32_t V) { return V == 0; }))
1478 return RunThinBackend(AddStream);
1482 Conf, CombinedIndex, ModuleID, ImportList, ExportList, ResolvedODR,
1483 DefinedGlobals, CfiFunctionDefs, CfiFunctionDecls);
1487 AddStreamFn &CacheAddStream = *CacheAddStreamOrErr;
1489 return RunThinBackend(CacheAddStream);
1498 const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes> &ResolvedODR,
1501 assert(ModuleToDefinedGVSummaries.
count(ModulePath));
1503 ModuleToDefinedGVSummaries.
find(ModulePath)->second;
1504 BackendThreadPool.async(
1508 const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes>
1515 Error E = runThinLTOBackendThread(
1516 AddStream, Cache, Task, BM, CombinedIndex, ImportList, ExportList,
1517 ResolvedODR, DefinedGlobals, ModuleMap);
1519 std::unique_lock<std::mutex>
L(ErrMu);
1528 BM, std::ref(CombinedIndex), std::ref(ImportList), std::ref(ExportList),
1529 std::ref(ResolvedODR), std::ref(DefinedGlobals), std::ref(ModuleMap));
1532 OnWrite(std::string(ModulePath));
1542class FirstRoundThinBackend :
public InProcessThinBackend {
1547 FirstRoundThinBackend(
1553 : InProcessThinBackend(Conf, CombinedIndex, ThinLTOParallelism,
1554 ModuleToDefinedGVSummaries,
std::
move(CGAddStream),
1558 IRAddStream(
std::
move(IRAddStream)), IRCache(
std::
move(IRCache)) {}
1560 Error runThinLTOBackendThread(
1565 const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes> &ResolvedODR,
1568 auto RunThinBackend = [&](
AddStreamFn CGAddStream,
1575 return thinBackend(Conf, Task, CGAddStream, **MOrErr, CombinedIndex,
1576 ImportList, DefinedGlobals, &ModuleMap,
1584 if (ShouldEmitIndexFiles) {
1585 if (
auto E = emitFiles(ImportList, ModuleID, ModuleID.str()))
1590 "Both caches for CG and IR should have matching availability");
1593 [](
uint32_t V) { return V == 0; }))
1596 return RunThinBackend(CGAddStream, IRAddStream);
1600 Conf, CombinedIndex, ModuleID, ImportList, ExportList, ResolvedODR,
1601 DefinedGlobals, CfiFunctionDefs, CfiFunctionDecls);
1603 CGCache(Task, CGKey, ModuleID);
1606 AddStreamFn &CacheCGAddStream = *CacheCGAddStreamOrErr;
1611 IRCache(Task, IRKey, ModuleID);
1614 AddStreamFn &CacheIRAddStream = *CacheIRAddStreamOrErr;
1620 if (CacheCGAddStream || CacheIRAddStream) {
1623 return RunThinBackend(CacheCGAddStream ? CacheCGAddStream : CGAddStream,
1624 CacheIRAddStream ? CacheIRAddStream : IRAddStream);
1636class SecondRoundThinBackend :
public InProcessThinBackend {
1637 std::unique_ptr<SmallVector<StringRef>> IRFiles;
1641 SecondRoundThinBackend(
1648 : InProcessThinBackend(Conf, CombinedIndex, ThinLTOParallelism,
1649 ModuleToDefinedGVSummaries,
std::
move(AddStream),
1654 IRFiles(
std::
move(IRFiles)), CombinedCGDataHash(CombinedCGDataHash) {}
1656 virtual Error runThinLTOBackendThread(
1661 const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes> &ResolvedODR,
1664 auto RunThinBackend = [&](
AddStreamFn AddStream) {
1666 std::unique_ptr<Module> LoadedModule =
1669 return thinBackend(Conf, Task, AddStream, *LoadedModule, CombinedIndex,
1670 ImportList, DefinedGlobals, &ModuleMap,
1677 [](
uint32_t V) { return V == 0; }))
1680 return RunThinBackend(AddStream);
1685 Conf, CombinedIndex, ModuleID, ImportList, ExportList, ResolvedODR,
1686 DefinedGlobals, CfiFunctionDefs, CfiFunctionDecls);
1688 std::to_string(CombinedCGDataHash));
1692 AddStreamFn &CacheAddStream = *CacheAddStreamOrErr;
1694 if (CacheAddStream) {
1697 return RunThinBackend(CacheAddStream);
1707 bool ShouldEmitIndexFiles,
1708 bool ShouldEmitImportsFiles) {
1713 return std::make_unique<InProcessThinBackend>(
1714 Conf, CombinedIndex, Parallelism, ModuleToDefinedGVSummaries,
1715 AddStream, Cache, OnWrite, ShouldEmitIndexFiles,
1716 ShouldEmitImportsFiles);
1742 return std::string(Path);
1746 if (!ParentPath.
empty()) {
1749 llvm::errs() <<
"warning: could not create directory '" << ParentPath
1750 <<
"': " << EC.message() <<
'\n';
1752 return std::string(NewPath);
1757 std::string OldPrefix, NewPrefix, NativeObjectPrefix;
1761 WriteIndexesThinBackend(
1765 std::string OldPrefix, std::string NewPrefix,
1766 std::string NativeObjectPrefix,
bool ShouldEmitImportsFiles,
1769 OnWrite, ShouldEmitImportsFiles, ThinLTOParallelism),
1770 OldPrefix(OldPrefix), NewPrefix(NewPrefix),
1771 NativeObjectPrefix(NativeObjectPrefix),
1772 LinkedObjectsFile(LinkedObjectsFile) {}
1778 const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes> &ResolvedODR,
1786 if (LinkedObjectsFile) {
1787 std::string ObjectPrefix =
1788 NativeObjectPrefix.
empty() ? NewPrefix : NativeObjectPrefix;
1789 std::string LinkedObjectsFilePath =
1791 *LinkedObjectsFile << LinkedObjectsFilePath <<
'\n';
1794 BackendThreadPool.async(
1797 const std::string &OldPrefix,
const std::string &NewPrefix) {
1798 std::string NewModulePath =
1800 auto E = emitFiles(ImportList, ModulePath, NewModulePath);
1802 std::unique_lock<std::mutex>
L(ErrMu);
1810 ModulePath, ImportList, OldPrefix, NewPrefix);
1813 OnWrite(std::string(ModulePath));
1817 bool isSensitiveToInputOrder()
override {
1827 std::string NewPrefix, std::string NativeObjectPrefix,
1834 return std::make_unique<WriteIndexesThinBackend>(
1835 Conf, CombinedIndex, Parallelism, ModuleToDefinedGVSummaries,
1836 OldPrefix, NewPrefix, NativeObjectPrefix, ShouldEmitImportsFiles,
1837 LinkedObjectsFile, OnWrite);
1845 ThinLTO.CombinedIndex.releaseTemporaryMemory();
1851 if (ThinLTO.ModuleMap.empty())
1854 if (ThinLTO.ModulesToCompile && ThinLTO.ModulesToCompile->empty()) {
1855 llvm::errs() <<
"warning: [ThinLTO] No module compiled\n";
1866 ThinLTO.ModuleMap.size());
1867 ThinLTO.CombinedIndex.collectDefinedGVSummariesPerModule(
1868 ModuleToDefinedGVSummaries);
1876 for (
auto &
Mod : ThinLTO.ModuleMap)
1877 if (!ModuleToDefinedGVSummaries.
count(
Mod.first))
1882 ThinLTO.ModuleMap.size());
1886 ThinLTO.CombinedIndex.dumpSCCs(
outs());
1888 std::set<GlobalValue::GUID> ExportedGUIDs;
1890 bool WholeProgramVisibilityEnabledInLTO =
1896 ThinLTO.CombinedIndex.setWithWholeProgramVisibility();
1902 if (WholeProgramVisibilityEnabledInLTO &&
1907 auto It = GlobalResolutions->
find(
name);
1908 return (It == GlobalResolutions->end() ||
1909 It->second.VisibleOutsideSummary);
1913 VisibleToRegularObjSymbols,
1914 IsVisibleToRegularObj);
1920 ThinLTO.CombinedIndex, WholeProgramVisibilityEnabledInLTO,
1921 DynamicExportSymbols, VisibleToRegularObjSymbols);
1926 std::map<ValueInfo, std::vector<VTableSlotSummary>> LocalWPDTargetsMap;
1928 LocalWPDTargetsMap);
1931 return ThinLTO.PrevailingModuleForGUID[
GUID] == S->modulePath();
1935 ContextDisambiguation.
run(ThinLTO.CombinedIndex, isPrevailing);
1942 for (
auto &Res : *GlobalResolutions) {
1945 if (Res.second.Partition != GlobalResolution::External ||
1946 !Res.second.isPrevailingIRSymbol())
1951 if (ThinLTO.CombinedIndex.isGUIDLive(GUID))
1952 ExportedGUIDs.insert(GUID);
1959 releaseGlobalResolutionsMemory();
1963 isPrevailing, ImportLists, ExportLists);
1967 for (
auto &Def : ThinLTO.CombinedIndex.cfiFunctionDefs())
1968 ExportedGUIDs.insert(
1970 for (
auto &Decl : ThinLTO.CombinedIndex.cfiFunctionDecls())
1971 ExportedGUIDs.insert(
1975 const auto &ExportList = ExportLists.
find(ModuleIdentifier);
1976 return (ExportList != ExportLists.end() && ExportList->second.
count(VI)) ||
1977 ExportedGUIDs.count(
VI.getGUID());
1983 LocalWPDTargetsMap);
1988 auto recordNewLinkage = [&](
StringRef ModuleIdentifier,
1991 ResolvedODR[ModuleIdentifier][
GUID] = NewLinkage;
1994 recordNewLinkage, GUIDPreservedSymbols);
2003 TimeTraceScopeExit.release();
2006 ThinLTO.ModulesToCompile ? *ThinLTO.ModulesToCompile : ThinLTO.ModuleMap;
2009 auto ProcessOneModule = [&](
int I) ->
Error {
2013 return BackendProcess->start(
2014 RegularLTO.ParallelCodeGenParallelismLevel +
I,
Mod.second,
2015 ImportLists[
Mod.first], ExportLists[
Mod.first],
2016 ResolvedODR[
Mod.first], ThinLTO.ModuleMap);
2019 if (BackendProcess->getThreadCount() == 1 ||
2020 BackendProcess->isSensitiveToInputOrder()) {
2026 for (
int I = 0, E = ModuleMap.
size();
I != E; ++
I)
2027 if (
Error E = ProcessOneModule(
I))
2034 std::vector<BitcodeModule *> ModulesVec;
2035 ModulesVec.reserve(ModuleMap.
size());
2036 for (
auto &
Mod : ModuleMap)
2037 ModulesVec.push_back(&
Mod.second);
2039 if (
Error E = ProcessOneModule(
I))
2042 return BackendProcess->wait();
2046 std::unique_ptr<ThinBackendProc> BackendProc =
2047 ThinLTO.Backend(Conf, ThinLTO.CombinedIndex, ModuleToDefinedGVSummaries,
2049 return RunBackends(BackendProc.get());
2057 LLVM_DEBUG(
dbgs() <<
"[TwoRounds] Initializing ThinLTO two-codegen rounds\n");
2060 auto Parallelism = ThinLTO.Backend.getParallelism();
2068 LLVM_DEBUG(
dbgs() <<
"[TwoRounds] Running the first round of codegen\n");
2069 auto FirstRoundLTO = std::make_unique<FirstRoundThinBackend>(
2070 Conf, ThinLTO.CombinedIndex, Parallelism, ModuleToDefinedGVSummaries,
2071 CG.AddStream, CG.Cache,
IR.AddStream,
IR.Cache);
2072 if (
Error E = RunBackends(FirstRoundLTO.get()))
2077 if (
Error E = CombinedHashOrErr.takeError())
2079 auto CombinedHash = *CombinedHashOrErr;
2080 LLVM_DEBUG(
dbgs() <<
"[TwoRounds] CGData hash: " << CombinedHash <<
"\n");
2084 LLVM_DEBUG(
dbgs() <<
"[TwoRounds] Running the second round of codegen\n");
2085 auto SecondRoundLTO = std::make_unique<SecondRoundThinBackend>(
2086 Conf, ThinLTO.CombinedIndex, Parallelism, ModuleToDefinedGVSummaries,
2087 AddStream, Cache,
IR.getResult(), CombinedHash);
2088 return RunBackends(SecondRoundLTO.get());
2098 if (!Filename.empty() && Count != -1)
2106 if (
Error E = ResultOrErr.takeError())
2107 return std::move(E);
2110 (*ResultOrErr)->keep();
2118 if (StatsFilename.
empty())
2129 return std::move(StatsFile);
2136 auto Seq = llvm::seq<int>(0, R.size());
2137 std::vector<int> ModulesOrdering(Seq.begin(), Seq.end());
2138 llvm::sort(ModulesOrdering, [&](
int LeftIndex,
int RightIndex) {
2139 auto LSize = R[LeftIndex]->getBuffer().
size();
2140 auto RSize = R[RightIndex]->getBuffer().
size();
2141 return LSize > RSize;
2143 return ModulesOrdering;
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
cl::opt< bool > CodeGenDataThinLTOTwoRounds("codegen-data-thinlto-two-rounds", cl::init(false), cl::Hidden, cl::desc("Enable two-round ThinLTO code generation. The first round " "emits codegen data, while the second round uses the emitted " "codegen data for further optimizations."))
static void writeToResolutionFile(raw_ostream &OS, InputFile *Input, ArrayRef< SymbolResolution > Res)
static void thinLTOResolvePrevailingGUID(const Config &C, ValueInfo VI, DenseSet< GlobalValueSummary * > &GlobalInvolvedWithAlias, function_ref< bool(GlobalValue::GUID, const GlobalValueSummary *)> isPrevailing, function_ref< void(StringRef, GlobalValue::GUID, GlobalValue::LinkageTypes)> recordNewLinkage, const DenseSet< GlobalValue::GUID > &GUIDPreservedSymbols)
static void handleNonPrevailingComdat(GlobalValue &GV, std::set< const Comdat * > &NonPrevailingComdats)
cl::opt< bool > CodeGenDataThinLTOTwoRounds
static cl::opt< bool > DumpThinCGSCCs("dump-thin-cg-sccs", cl::init(false), cl::Hidden, cl::desc("Dump the SCCs in the ThinLTO index's callgraph"))
static void thinLTOInternalizeAndPromoteGUID(ValueInfo VI, function_ref< bool(StringRef, ValueInfo)> isExported, function_ref< bool(GlobalValue::GUID, const GlobalValueSummary *)> isPrevailing)
cl::opt< bool > UseNewDbgInfoFormat
Legalize the Machine IR a function s Machine IR
llvm::cl::opt< bool > UseNewDbgInfoFormat
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the make_scope_exit function, which executes user-defined cleanup logic at scope ex...
This file defines the SmallSet class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
static ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
Represents a module in a bitcode file.
StringRef getModuleIdentifier() const
Error readSummary(ModuleSummaryIndex &CombinedIndex, StringRef ModulePath, std::function< bool(GlobalValue::GUID)> IsPrevailing=nullptr)
Parse the specified bitcode buffer and merge its module summary index into CombinedIndex.
Expected< std::unique_ptr< Module > > parseModule(LLVMContext &Context, ParserCallbacks Callbacks={})
Read the entire bitcode module and return it.
Expected< std::unique_ptr< Module > > getLazyModule(LLVMContext &Context, bool ShouldLazyLoadMetadata, bool IsImporting, ParserCallbacks Callbacks={})
Read the bitcode module and prepare for lazy deserialization of function bodies.
static ConstantAggregateZero * get(Type *Ty)
A parsed version of the target data layout string in and methods for querying it.
iterator find(const_arg_type_t< KeyT > Val)
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
Implements a dense probed hash-table based set.
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
Error takeError()
Take ownership of the stored error.
The map maintains the list of imports.
void setAlignment(Align Align)
Sets the alignment attribute of the GlobalObject.
Function and variable summary information to aid decisions and implementation of importing.
static bool isAppendingLinkage(LinkageTypes Linkage)
static bool isExternalWeakLinkage(LinkageTypes Linkage)
static bool isLocalLinkage(LinkageTypes Linkage)
bool isDeclaration() const
Return true if the primary definition of this global value is outside of the current translation unit...
void setUnnamedAddr(UnnamedAddr Val)
bool hasLocalLinkage() const
static StringRef dropLLVMManglingEscape(StringRef Name)
If the given string begins with the GlobalValue name mangling escape character '\1',...
const Comdat * getComdat() const
static bool isLinkOnceLinkage(LinkageTypes Linkage)
static GUID getGUID(StringRef GlobalName)
Return a 64-bit global unique ID constructed from global value name (i.e.
void setLinkage(LinkageTypes LT)
DLLStorageClassTypes
Storage classes of global values for PE targets.
GUID getGUID() const
Return a 64-bit global unique ID constructed from global value name (i.e.
const GlobalObject * getAliaseeObject() const
static bool isExternalLinkage(LinkageTypes Linkage)
VisibilityTypes
An enumeration for the kinds of visibility of global values.
@ DefaultVisibility
The GV is visible.
static LinkageTypes getWeakLinkage(bool ODR)
bool isWeakForLinker() const
bool hasAppendingLinkage() const
bool hasAvailableExternallyLinkage() const
std::string getGlobalIdentifier() const
Return the modified name for this global value suitable to be used as the key for a global lookup (e....
LinkageTypes
An enumeration for the kinds of linkage for global values.
@ CommonLinkage
Tentative definitions.
@ InternalLinkage
Rename collisions when linking (static functions).
@ ExternalLinkage
Externally visible function.
@ WeakAnyLinkage
Keep one copy of named function when linking (weak)
@ AvailableExternallyLinkage
Available for inspection, not emission.
DLLStorageClassTypes getDLLStorageClass() const
Type * getValueType() const
static bool isLinkOnceODRLinkage(LinkageTypes Linkage)
void eraseFromParent()
eraseFromParent - This method unlinks 'this' from the containing module and deletes it.
This is an important class for using LLVM in a threaded context.
This class implements a map that also provides access to all stored values in a deterministic order.
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFile(const Twine &Filename, bool IsText=false, bool RequiresNullTerminator=true, bool IsVolatile=false, std::optional< Align > Alignment=std::nullopt)
Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful,...
Class to hold module path string table and global value map, and encapsulate methods for operating on...
const ModuleHash & getModuleHash(const StringRef ModPath) const
Get the module SHA1 hash recorded for the given module path.
const StringMap< ModuleHash > & modulePaths() const
Table of modules, containing module hash and id.
std::set< std::string, std::less<> > & cfiFunctionDefs()
std::set< std::string, std::less<> > & cfiFunctionDecls()
void addModule(Module *M)
static void CollectAsmSymvers(const Module &M, function_ref< void(StringRef, StringRef)> AsmSymver)
Parse inline ASM and collect the symvers directives that are defined in the current module.
uint32_t getSymbolFlags(Symbol S) const
ArrayRef< Symbol > symbols() const
A Module instance is used to store all the information related to an LLVM module.
A discriminated union of two or more pointer types, with the discriminator in the low bit of the poin...
A class that wrap the SHA1 algorithm.
void update(ArrayRef< uint8_t > Data)
Digest more data.
std::array< uint8_t, 20 > result()
Return the current raw 160-bits SHA1 for the digested data since the last call to init().
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
size_type count(const T &V) const
count - Return 1 if the element is in the set, 0 otherwise.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
StringRef str() const
Explicit conversion to StringRef.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
A wrapper around a string literal that serves as a proxy for constructing global tables of StringRefs...
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
size_type count(StringRef Key) const
count - Return 1 if the element is in the map, 0 otherwise.
StringRef - Represent a constant reference to a string, i.e.
constexpr bool empty() const
empty - Check if the string is empty.
bool contains(StringRef Other) const
Return true if the given string is a substring of *this, and false otherwise.
MCTargetOptions MCOptions
Machine level options.
DebuggerKind DebuggerTuning
Which debugger to tune for.
unsigned FunctionSections
Emit functions into separate sections.
unsigned DataSections
Emit data into separate sections.
This tells how a thread pool will be used.
Triple - Helper class for working with autoconf configuration names.
bool isArm64e() const
Tests whether the target is the Apple "arm64e" AArch64 subarch.
ArchType getArch() const
Get the parsed architecture type of this triple.
bool isOSDarwin() const
Is this a "Darwin" OS (macOS, iOS, tvOS, watchOS, XROS, or DriverKit).
bool isOSBinFormatELF() const
Tests whether the OS uses the ELF binary format.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
static IntegerType * getInt8Ty(LLVMContext &C)
void setName(const Twine &Name)
Change the name of the value.
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
StringRef getName() const
Return a constant reference to the value's name.
void takeName(Value *V)
Transfer the name from V to this value.
std::pair< iterator, bool > insert(const ValueT &V)
iterator find(const_arg_type_t< ValueT > V)
bool contains(const_arg_type_t< ValueT > V) const
Check if the set contains the given element.
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
An efficient, type-erasing, non-owning reference to a callable.
Ephemeral symbols produced by Reader::symbols() and Reader::module_symbols().
LTO(Config Conf, ThinBackend Backend={}, unsigned ParallelCodeGenParallelismLevel=1, LTOKind LTOMode=LTOK_Default)
Create an LTO object.
Error add(std::unique_ptr< InputFile > Obj, ArrayRef< SymbolResolution > Res)
Add an input file to the LTO link, using the provided symbol resolutions.
static SmallVector< const char * > getRuntimeLibcallSymbols(const Triple &TT)
Static method that returns a list of libcall symbols that can be generated by LTO but might not be vi...
LTOKind
Unified LTO modes.
@ LTOK_UnifiedRegular
Regular LTO, with Unified LTO enabled.
@ LTOK_Default
Any LTO mode without Unified LTO. The default mode.
@ LTOK_UnifiedThin
ThinLTO, with Unified LTO enabled.
unsigned getMaxTasks() const
Returns an upper bound on the number of tasks that the client may expect.
Error run(AddStreamFn AddStream, FileCache Cache={})
Runs the LTO pipeline.
This class defines the interface to the ThinLTO backend.
Error emitFiles(const FunctionImporter::ImportMapTy &ImportList, llvm::StringRef ModulePath, const std::string &NewModulePath) const
bool ShouldEmitImportsFiles
const DenseMap< StringRef, GVSummaryMapTy > & ModuleToDefinedGVSummaries
ModuleSummaryIndex & CombinedIndex
A raw_ostream that writes to a file descriptor.
This class implements an extremely fast bulk output stream that can only output to a stream.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ C
The default llvm calling convention, compatible with C.
Function * getDeclarationIfExists(Module *M, ID id, ArrayRef< Type * > Tys, FunctionType *FT=nullptr)
This version supports overloaded intrinsics.
Expected< stable_hash > mergeCodeGenData(ArrayRef< StringRef > ObjectFiles)
Merge the codegen data from the scratch objects ObjectFiles from the first codegen round.
std::unique_ptr< Module > loadModuleForTwoRounds(BitcodeModule &OrigModule, unsigned Task, LLVMContext &Context, ArrayRef< StringRef > IRFiles)
Load the optimized bitcode module for the second codegen round.
initializer< Ty > init(const Ty &Val)
ThinBackend createInProcessThinBackend(ThreadPoolStrategy Parallelism, IndexWriteCallback OnWrite=nullptr, bool ShouldEmitIndexFiles=false, bool ShouldEmitImportsFiles=false)
This ThinBackend runs the individual backend jobs in-process.
std::string getThinLTOOutputFile(StringRef Path, StringRef OldPrefix, StringRef NewPrefix)
Given the original Path to an output file, replace any path prefix matching OldPrefix with NewPrefix.
std::function< void(const std::string &)> IndexWriteCallback
StringLiteral getThinLTODefaultCPU(const Triple &TheTriple)
Expected< std::unique_ptr< ToolOutputFile > > setupStatsFile(StringRef StatsFilename)
Setups the output file for saving statistics.
Error backend(const Config &C, AddStreamFn AddStream, unsigned ParallelCodeGenParallelismLevel, Module &M, ModuleSummaryIndex &CombinedIndex)
Runs a regular LTO backend.
ThinBackend createWriteIndexesThinBackend(ThreadPoolStrategy Parallelism, std::string OldPrefix, std::string NewPrefix, std::string NativeObjectPrefix, bool ShouldEmitImportsFiles, raw_fd_ostream *LinkedObjectsFile, IndexWriteCallback OnWrite)
This ThinBackend writes individual module indexes to files, instead of running the individual backend...
Error finalizeOptimizationRemarks(std::unique_ptr< ToolOutputFile > DiagOutputFile)
std::vector< int > generateModulesOrdering(ArrayRef< BitcodeModule * > R)
Produces a container ordering for optimal multi-threaded processing.
Expected< std::unique_ptr< ToolOutputFile > > setupLLVMOptimizationRemarks(LLVMContext &Context, StringRef RemarksFilename, StringRef RemarksPasses, StringRef RemarksFormat, bool RemarksWithHotness, std::optional< uint64_t > RemarksHotnessThreshold=0, int Count=-1)
Setup optimization remarks.
Error thinBackend(const Config &C, unsigned Task, AddStreamFn AddStream, Module &M, const ModuleSummaryIndex &CombinedIndex, const FunctionImporter::ImportMapTy &ImportList, const GVSummaryMapTy &DefinedGlobals, MapVector< StringRef, BitcodeModule > *ModuleMap, bool CodeGenOnly, AddStreamFn IRAddStream=nullptr, const std::vector< uint8_t > &CmdArgs=std::vector< uint8_t >())
Runs a ThinLTO backend.
void updateMemProfAttributes(Module &Mod, const ModuleSummaryIndex &Index)
Updates MemProf attributes (and metadata) based on whether the index has recorded that we are linking...
Expected< IRSymtabFile > readIRSymtab(MemoryBufferRef MBRef)
Reads a bitcode file, creating its irsymtab if necessary.
void write64le(void *P, uint64_t V)
void write32le(void *P, uint32_t V)
std::error_code create_directories(const Twine &path, bool IgnoreExisting=true, perms Perms=owner_all|group_all)
Create all the non-existent directories in path.
StringRef parent_path(StringRef path, Style style=Style::native)
Get parent path.
bool replace_path_prefix(SmallVectorImpl< char > &Path, StringRef OldPrefix, StringRef NewPrefix, Style style=Style::native)
Replace matching path prefix with another path.
This is an optimization pass for GlobalISel generic memory operations.
ThreadPoolStrategy heavyweight_hardware_concurrency(unsigned ThreadCount=0)
Returns a thread strategy for tasks requiring significant memory or other resources.
cl::opt< std::string > RemarksFormat("lto-pass-remarks-format", cl::desc("The format used for serializing remarks (default: YAML)"), cl::value_desc("format"), cl::init("yaml"))
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Error createFileError(const Twine &F, Error E)
Concatenate a source file path and/or name with an Error.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
detail::scope_exit< std::decay_t< Callable > > make_scope_exit(Callable &&F)
void generateParamAccessSummary(ModuleSummaryIndex &Index)
cl::opt< std::string > RemarksPasses("lto-pass-remarks-filter", cl::desc("Only record optimization remarks from passes whose " "names match the given regular expression"), cl::value_desc("regex"))
std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
raw_fd_ostream & outs()
This returns a reference to a raw_fd_ostream for standard output.
std::function< Expected< std::unique_ptr< CachedFileStream > >(unsigned Task, const Twine &ModuleName)> AddStreamFn
This type defines the callback to add a file that is generated on the fly.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
bool thinLTOPropagateFunctionAttrs(ModuleSummaryIndex &Index, function_ref< bool(GlobalValue::GUID, const GlobalValueSummary *)> isPrevailing)
Propagate function attributes for function summaries along the index's callgraph during thinlink.
OutputIt copy_if(R &&Range, OutputIt Out, UnaryPredicate P)
Provide wrappers to std::copy_if which take ranges instead of having to pass begin/end explicitly.
bool hasWholeProgramVisibility(bool WholeProgramVisibilityEnabledInLTO)
void writeIndexToFile(const ModuleSummaryIndex &Index, raw_ostream &Out, const ModuleToSummariesForIndexTy *ModuleToSummariesForIndex=nullptr, const GVSummaryPtrSet *DecSummaries=nullptr)
Write the specified module summary index to the given raw output stream, where it will be written in ...
void ComputeCrossModuleImport(const ModuleSummaryIndex &Index, const DenseMap< StringRef, GVSummaryMapTy > &ModuleToDefinedGVSummaries, function_ref< bool(GlobalValue::GUID, const GlobalValueSummary *)> isPrevailing, FunctionImporter::ImportListsTy &ImportLists, DenseMap< StringRef, FunctionImporter::ExportSetTy > &ExportLists)
Compute all the imports and exports for every module in the Index.
void EnableStatistics(bool DoPrintOnExit=true)
Enable the collection and printing of statistics.
void thinLTOInternalizeAndPromoteInIndex(ModuleSummaryIndex &Index, function_ref< bool(StringRef, ValueInfo)> isExported, function_ref< bool(GlobalValue::GUID, const GlobalValueSummary *)> isPrevailing)
Update the linkages in the given Index to mark exported values as external and non-exported values as...
void timeTraceProfilerInitialize(unsigned TimeTraceGranularity, StringRef ProcName, bool TimeTraceVerbose=false)
Initialize the time trace profiler.
void timeTraceProfilerFinishThread()
Finish a time trace profiler running on a worker thread.
std::string recomputeLTOCacheKey(const std::string &Key, StringRef ExtraID)
Recomputes the LTO cache key for a given key with an extra identifier.
Error joinErrors(Error E1, Error E2)
Concatenate errors.
void updatePublicTypeTestCalls(Module &M, bool WholeProgramVisibilityEnabledInLTO)
void getVisibleToRegularObjVtableGUIDs(ModuleSummaryIndex &Index, DenseSet< GlobalValue::GUID > &VisibleToRegularObjSymbols, function_ref< bool(StringRef)> IsVisibleToRegularObj)
Based on typeID string, get all associated vtable GUIDS that are visible to regular objects.
void sort(IteratorTy Start, IteratorTy End)
bool timeTraceProfilerEnabled()
Is the time trace profiler enabled, i.e. initialized?
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Expected< std::unique_ptr< ToolOutputFile > > setupLLVMOptimizationRemarks(LLVMContext &Context, StringRef RemarksFilename, StringRef RemarksPasses, StringRef RemarksFormat, bool RemarksWithHotness, std::optional< uint64_t > RemarksHotnessThreshold=0)
Setup optimization remarks that output to a file.
cl::opt< bool > EnableLTOInternalization
Enable global value internalization in LTO.
cl::opt< bool > RemarksWithHotness("lto-pass-remarks-with-hotness", cl::desc("With PGO, include profile count in optimization remarks"), cl::Hidden)
void timeTraceProfilerEnd()
Manually end the last time section.
cl::opt< std::string > RemarksFilename("lto-pass-remarks-output", cl::desc("Output filename for pass remarks"), cl::value_desc("filename"))
cl::opt< bool > SupportsHotColdNew
Indicate we are linking with an allocator that supports hot/cold operator new interfaces.
void updateIndexWPDForExports(ModuleSummaryIndex &Summary, function_ref< bool(StringRef, ValueInfo)> isExported, std::map< ValueInfo, std::vector< VTableSlotSummary > > &LocalWPDTargetsMap)
Call after cross-module importing to update the recorded single impl devirt target names for any loca...
void thinLTOResolvePrevailingInIndex(const lto::Config &C, ModuleSummaryIndex &Index, function_ref< bool(GlobalValue::GUID, const GlobalValueSummary *)> isPrevailing, function_ref< void(StringRef, GlobalValue::GUID, GlobalValue::LinkageTypes)> recordNewLinkage, const DenseSet< GlobalValue::GUID > &GUIDPreservedSymbols)
Resolve linkage for prevailing symbols in the Index.
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
@ Mod
The access may modify the value stored in memory.
cl::opt< bool > EnableMemProfContextDisambiguation
Enable MemProf context disambiguation for thin link.
void runWholeProgramDevirtOnIndex(ModuleSummaryIndex &Summary, std::set< GlobalValue::GUID > &ExportedGUIDs, std::map< ValueInfo, std::vector< VTableSlotSummary > > &LocalWPDTargetsMap)
Perform index-based whole program devirtualization on the Summary index.
std::unordered_set< GlobalValueSummary * > GVSummaryPtrSet
A set of global value summary pointers.
void gatherImportedSummariesForModule(StringRef ModulePath, const DenseMap< StringRef, GVSummaryMapTy > &ModuleToDefinedGVSummaries, const FunctionImporter::ImportMapTy &ImportList, ModuleToSummariesForIndexTy &ModuleToSummariesForIndex, GVSummaryPtrSet &DecSummaries)
Compute the set of summaries needed for a ThinLTO backend compilation of ModulePath.
std::map< std::string, GVSummaryMapTy, std::less<> > ModuleToSummariesForIndexTy
Map of a module name to the GUIDs and summaries we will import from that module.
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
auto count_if(R &&Range, UnaryPredicate P)
Wrapper function around std::count_if to count the number of times an element satisfying a given pred...
cl::opt< std::optional< uint64_t >, false, remarks::HotnessThresholdParser > RemarksHotnessThreshold("lto-pass-remarks-hotness-threshold", cl::desc("Minimum profile count required for an " "optimization remark to be output." " Use 'auto' to apply the threshold from profile summary."), cl::value_desc("uint or 'auto'"), cl::init(0), cl::Hidden)
std::string computeLTOCacheKey(const lto::Config &Conf, const ModuleSummaryIndex &Index, StringRef ModuleID, const FunctionImporter::ImportMapTy &ImportList, const FunctionImporter::ExportSetTy &ExportList, const std::map< GlobalValue::GUID, GlobalValue::LinkageTypes > &ResolvedODR, const GVSummaryMapTy &DefinedGlobals, const DenseSet< GlobalValue::GUID > &CfiFunctionDefs={}, const DenseSet< GlobalValue::GUID > &CfiFunctionDecls={})
Computes a unique hash for the Module considering the current list of export/import and other global ...
Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
static cl::opt< bool > LTOKeepSymbolCopies("lto-keep-symbol-copies", cl::init(false), cl::Hidden, cl::desc("Keep copies of symbols in LTO indexing"))
bool UpgradeDebugInfo(Module &M)
Check the debug info version number, if it is out-dated, drop the debug info.
void PrintStatisticsJSON(raw_ostream &OS)
Print statistics in JSON format.
void computeDeadSymbolsWithConstProp(ModuleSummaryIndex &Index, const DenseSet< GlobalValue::GUID > &GUIDPreservedSymbols, function_ref< PrevailingType(GlobalValue::GUID)> isPrevailing, bool ImportEnabled)
Compute dead symbols and run constant propagation in combined index after that.
Error EmitImportsFiles(StringRef ModulePath, StringRef OutputFilename, const ModuleToSummariesForIndexTy &ModuleToSummariesForIndex)
Emit into OutputFilename the files module ModulePath will import from.
@ Keep
No function return thunk.
void updateVCallVisibilityInModule(Module &M, bool WholeProgramVisibilityEnabledInLTO, const DenseSet< GlobalValue::GUID > &DynamicExportSymbols, bool ValidateAllVtablesHaveTypeInfos, function_ref< bool(StringRef)> IsVisibleToRegularObj)
If whole program visibility asserted, then upgrade all public vcall visibility metadata on vtable def...
TimeTraceProfilerEntry * timeTraceProfilerBegin(StringRef Name, StringRef Detail)
Manually begin a time section, with the given Name and Detail.
void updateVCallVisibilityInIndex(ModuleSummaryIndex &Index, bool WholeProgramVisibilityEnabledInLTO, const DenseSet< GlobalValue::GUID > &DynamicExportSymbols, const DenseSet< GlobalValue::GUID > &VisibleToRegularObjSymbols)
If whole program visibility asserted, then upgrade all public vcall visibility metadata on vtable def...
Implement std::hash so that hash_code can be used in STL containers.
This struct is a compact representation of a valid (non-zero power of two) alignment.
Used in the streaming interface as the general argument type.
This type represents a file cache system that manages caching of files.
A simple container for information about the supported runtime calls.
iterator_range< const char ** > getLibcallNames()
Struct that holds a reference to a particular GUID in a global value summary.
bool isFormatSpecific() const
bool HasWholeProgramVisibility
Asserts whether we can assume whole program visibility during the LTO link.
bool ValidateAllVtablesHaveTypeInfos
We're validating that all native vtables have corresponding type infos.
bool KeepSymbolNameCopies
If true, the LTO instance creates copies of the symbol names for LTO::run.
std::optional< uint64_t > RemarksHotnessThreshold
The minimum hotness value a diagnostic needs in order to be included in optimization diagnostics.
std::string StatsFile
Statistics output file path.
ModuleHookFn PreOptModuleHook
This module hook is called after linking (regular LTO) or loading (ThinLTO) the module,...
CombinedIndexHookFn CombinedIndexHook
std::optional< CodeModel::Model > CodeModel
bool CodeGenOnly
Disable entirely the optimizer, including importing for ThinLTO.
std::vector< std::string > MAttrs
std::vector< std::string > MllvmArgs
std::vector< std::string > ThinLTOModulesToCompile
Specific thinLTO modules to compile.
CodeGenOptLevel CGOptLevel
std::unique_ptr< raw_ostream > ResolutionFile
If this field is set, LTO will write input file paths and symbol resolutions here in llvm-lto2 comman...
std::string DefaultTriple
Setting this field will replace unspecified target triples in input files with this triple.
bool AlwaysEmitRegularLTOObj
Always emit a Regular LTO object even when it is empty because no Regular LTO modules were linked.
std::string DwoDir
The directory to store .dwo files.
std::string RemarksFilename
Optimization remarks file path.
VisScheme VisibilityScheme
Allows non-imported definitions to get the potentially more constraining visibility from the prevaili...
std::string OverrideTriple
Setting this field will replace target triples in input files with this triple.
std::string ProfileRemapping
Name remapping file for profile data.
bool AllVtablesHaveTypeInfos
If all native vtables have corresponding type infos, allow usage of RTTI to block devirtualization on...
bool TimeTraceEnabled
Time trace enabled.
std::string RemarksPasses
Optimization remarks pass filter.
std::string OptPipeline
If this field is set, the set of passes run in the middle-end optimizer will be the one specified by ...
ModuleHookFn PostInternalizeModuleHook
This hook is called after internalizing the module.
unsigned TimeTraceGranularity
Time trace granularity.
bool RemarksWithHotness
Whether to emit optimization remarks with hotness informations.
std::optional< Reloc::Model > RelocModel
CodeGenFileType CGFileType
bool Freestanding
Flag to indicate that the optimizer should not assume builtins are present on the target.
std::string SampleProfile
Sample PGO profile path.
std::string RemarksFormat
The format used for serializing remarks (default: YAML).
A derived class of LLVMContext that initializes itself according to a given Config object.
The resolution for a symbol.
unsigned FinalDefinitionInLinkageUnit
The definition of this symbol is unpreemptable at runtime and is known to be in this linkage unit.
unsigned ExportDynamic
The symbol was exported dynamically, and therefore could be referenced by a shared library not visibl...
unsigned Prevailing
The linker has chosen this definition of the symbol.
unsigned LinkerRedefined
Linker redefined version of the symbol which appeared in -wrap or -defsym linker option.
unsigned VisibleToRegularObj
The definition of this symbol is visible outside of the LTO unit.
This type defines the behavior following the thin-link phase during ThinLTO.