/// Fixup WeakForLinker linkages in \p TheModule based on summary analysis. void llvm::thinLTOResolveWeakForLinkerModule( Module &TheModule, const GVSummaryMapTy &DefinedGlobals) { auto updateLinkage = [&](GlobalValue &GV) { if (!GlobalValue::isWeakForLinker(GV.getLinkage())) return; // See if the global summary analysis computed a new resolved linkage. const auto &GS = DefinedGlobals.find(GV.getGUID()); if (GS == DefinedGlobals.end()) return; auto NewLinkage = GS->second->linkage(); if (NewLinkage == GV.getLinkage()) return; DEBUG(dbgs() << "ODR fixing up linkage for `" << GV.getName() << "` from " << GV.getLinkage() << " to " << NewLinkage << "\n"); GV.setLinkage(NewLinkage); }; // Process functions and global now for (auto &GV : TheModule) updateLinkage(GV); for (auto &GV : TheModule.globals()) updateLinkage(GV); for (auto &GV : TheModule.aliases()) updateLinkage(GV); }
/// Fixup WeakForLinker linkages in \p TheModule based on summary analysis. void llvm::thinLTOResolveWeakForLinkerModule( Module &TheModule, const GVSummaryMapTy &DefinedGlobals) { auto updateLinkage = [&](GlobalValue &GV) { if (!GlobalValue::isWeakForLinker(GV.getLinkage())) return; // See if the global summary analysis computed a new resolved linkage. const auto &GS = DefinedGlobals.find(GV.getGUID()); if (GS == DefinedGlobals.end()) return; auto NewLinkage = GS->second->linkage(); if (NewLinkage == GV.getLinkage()) return; DEBUG(dbgs() << "ODR fixing up linkage for `" << GV.getName() << "` from " << GV.getLinkage() << " to " << NewLinkage << "\n"); GV.setLinkage(NewLinkage); // Remove functions converted to available_externally from comdats, // as this is a declaration for the linker, and will be dropped eventually. // It is illegal for comdats to contain declarations. auto *GO = dyn_cast_or_null<GlobalObject>(&GV); if (GO && GO->isDeclarationForLinker() && GO->hasComdat()) { assert(GO->hasAvailableExternallyLinkage() && "Expected comdat on definition (possibly available external)"); GO->setComdat(nullptr); } }; // Process functions and global now for (auto &GV : TheModule) updateLinkage(GV); for (auto &GV : TheModule.globals()) updateLinkage(GV); for (auto &GV : TheModule.aliases()) updateLinkage(GV); }
Error lto::thinBackend(Config &Conf, unsigned Task, AddStreamFn AddStream, Module &Mod, ModuleSummaryIndex &CombinedIndex, const FunctionImporter::ImportMapTy &ImportList, const GVSummaryMapTy &DefinedGlobals, MapVector<StringRef, MemoryBufferRef> &ModuleMap) { Expected<const Target *> TOrErr = initAndLookupTarget(Conf, Mod); if (!TOrErr) return TOrErr.takeError(); std::unique_ptr<TargetMachine> TM = createTargetMachine(Conf, Mod.getTargetTriple(), *TOrErr); handleAsmUndefinedRefs(Mod, *TM); if (Conf.CodeGenOnly) { codegen(Conf, TM.get(), AddStream, Task, Mod); return Error::success(); } if (Conf.PreOptModuleHook && !Conf.PreOptModuleHook(Task, Mod)) return Error::success(); renameModuleForThinLTO(Mod, CombinedIndex); thinLTOResolveWeakForLinkerModule(Mod, DefinedGlobals); if (Conf.PostPromoteModuleHook && !Conf.PostPromoteModuleHook(Task, Mod)) return Error::success(); if (!DefinedGlobals.empty()) thinLTOInternalizeModule(Mod, DefinedGlobals); if (Conf.PostInternalizeModuleHook && !Conf.PostInternalizeModuleHook(Task, Mod)) return Error::success(); auto ModuleLoader = [&](StringRef Identifier) { assert(Mod.getContext().isODRUniquingDebugTypes() && "ODR Type uniquing should be enabled on the context"); return std::move(getLazyBitcodeModule(ModuleMap[Identifier], Mod.getContext(), /*ShouldLazyLoadMetadata=*/true) .get()); }; FunctionImporter Importer(CombinedIndex, ModuleLoader); if (Error Err = Importer.importFunctions(Mod, ImportList).takeError()) return Err; if (Conf.PostImportModuleHook && !Conf.PostImportModuleHook(Task, Mod)) return Error::success(); if (!opt(Conf, TM.get(), Task, Mod, /*IsThinLto=*/true)) return Error::success(); codegen(Conf, TM.get(), AddStream, Task, Mod); return Error::success(); }
/// Run internalization on \p TheModule based on symmary analysis. void llvm::thinLTOInternalizeModule(Module &TheModule, const GVSummaryMapTy &DefinedGlobals) { // Parse inline ASM and collect the list of symbols that are not defined in // the current module. StringSet<> AsmUndefinedRefs; ModuleSymbolTable::CollectAsmSymbols( Triple(TheModule.getTargetTriple()), TheModule.getModuleInlineAsm(), [&AsmUndefinedRefs](StringRef Name, object::BasicSymbolRef::Flags Flags) { if (Flags & object::BasicSymbolRef::SF_Undefined) AsmUndefinedRefs.insert(Name); }); // Declare a callback for the internalize pass that will ask for every // candidate GlobalValue if it can be internalized or not. auto MustPreserveGV = [&](const GlobalValue &GV) -> bool { // Can't be internalized if referenced in inline asm. if (AsmUndefinedRefs.count(GV.getName())) return true; // Lookup the linkage recorded in the summaries during global analysis. const auto &GS = DefinedGlobals.find(GV.getGUID()); GlobalValue::LinkageTypes Linkage; if (GS == DefinedGlobals.end()) { // Must have been promoted (possibly conservatively). Find original // name so that we can access the correct summary and see if it can // be internalized again. // FIXME: Eventually we should control promotion instead of promoting // and internalizing again. StringRef OrigName = ModuleSummaryIndex::getOriginalNameBeforePromote(GV.getName()); std::string OrigId = GlobalValue::getGlobalIdentifier( OrigName, GlobalValue::InternalLinkage, TheModule.getSourceFileName()); const auto &GS = DefinedGlobals.find(GlobalValue::getGUID(OrigId)); if (GS == DefinedGlobals.end()) { // Also check the original non-promoted non-globalized name. In some // cases a preempted weak value is linked in as a local copy because // it is referenced by an alias (IRLinker::linkGlobalValueProto). // In that case, since it was originally not a local value, it was // recorded in the index using the original name. // FIXME: This may not be needed once PR27866 is fixed. const auto &GS = DefinedGlobals.find(GlobalValue::getGUID(OrigName)); assert(GS != DefinedGlobals.end()); Linkage = GS->second->linkage(); } else { Linkage = GS->second->linkage(); } } else Linkage = GS->second->linkage(); return !GlobalValue::isLocalLinkage(Linkage); }; // FIXME: See if we can just internalize directly here via linkage changes // based on the index, rather than invoking internalizeModule. llvm::internalizeModule(TheModule, MustPreserveGV); }