Path: blob/main/contrib/llvm-project/llvm/lib/Transforms/Utils/FunctionImportUtils.cpp
35271 views
//===- lib/Transforms/Utils/FunctionImportUtils.cpp - Importing utilities -===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file implements the FunctionImportGlobalProcessing class, used9// to perform the necessary global value handling for function importing.10//11//===----------------------------------------------------------------------===//1213#include "llvm/Transforms/Utils/FunctionImportUtils.h"14#include "llvm/Support/CommandLine.h"15using namespace llvm;1617/// Uses the "source_filename" instead of a Module hash ID for the suffix of18/// promoted locals during LTO. NOTE: This requires that the source filename19/// has a unique name / path to avoid name collisions.20static cl::opt<bool> UseSourceFilenameForPromotedLocals(21"use-source-filename-for-promoted-locals", cl::Hidden,22cl::desc("Uses the source file name instead of the Module hash. "23"This requires that the source filename has a unique name / "24"path to avoid name collisions."));2526/// Checks if we should import SGV as a definition, otherwise import as a27/// declaration.28bool FunctionImportGlobalProcessing::doImportAsDefinition(29const GlobalValue *SGV) {30if (!isPerformingImport())31return false;3233// Only import the globals requested for importing.34if (!GlobalsToImport->count(const_cast<GlobalValue *>(SGV)))35return false;3637assert(!isa<GlobalAlias>(SGV) &&38"Unexpected global alias in the import list.");3940// Otherwise yes.41return true;42}4344bool FunctionImportGlobalProcessing::shouldPromoteLocalToGlobal(45const GlobalValue *SGV, ValueInfo VI) {46assert(SGV->hasLocalLinkage());4748// Ifuncs and ifunc alias does not have summary.49if (isa<GlobalIFunc>(SGV) ||50(isa<GlobalAlias>(SGV) &&51isa<GlobalIFunc>(cast<GlobalAlias>(SGV)->getAliaseeObject())))52return false;5354// Both the imported references and the original local variable must55// be promoted.56if (!isPerformingImport() && !isModuleExporting())57return false;5859if (isPerformingImport()) {60assert((!GlobalsToImport->count(const_cast<GlobalValue *>(SGV)) ||61!isNonRenamableLocal(*SGV)) &&62"Attempting to promote non-renamable local");63// We don't know for sure yet if we are importing this value (as either64// a reference or a def), since we are simply walking all values in the65// module. But by necessity if we end up importing it and it is local,66// it must be promoted, so unconditionally promote all values in the67// importing module.68return true;69}7071// When exporting, consult the index. We can have more than one local72// with the same GUID, in the case of same-named locals in different but73// same-named source files that were compiled in their respective directories74// (so the source file name and resulting GUID is the same). Find the one75// in this module.76auto Summary = ImportIndex.findSummaryInModule(77VI, SGV->getParent()->getModuleIdentifier());78assert(Summary && "Missing summary for global value when exporting");79auto Linkage = Summary->linkage();80if (!GlobalValue::isLocalLinkage(Linkage)) {81assert(!isNonRenamableLocal(*SGV) &&82"Attempting to promote non-renamable local");83return true;84}8586return false;87}8889#ifndef NDEBUG90bool FunctionImportGlobalProcessing::isNonRenamableLocal(91const GlobalValue &GV) const {92if (!GV.hasLocalLinkage())93return false;94// This needs to stay in sync with the logic in buildModuleSummaryIndex.95if (GV.hasSection())96return true;97if (Used.count(const_cast<GlobalValue *>(&GV)))98return true;99return false;100}101#endif102103std::string104FunctionImportGlobalProcessing::getPromotedName(const GlobalValue *SGV) {105assert(SGV->hasLocalLinkage());106107// For locals that must be promoted to global scope, ensure that108// the promoted name uniquely identifies the copy in the original module,109// using the ID assigned during combined index creation.110if (UseSourceFilenameForPromotedLocals &&111!SGV->getParent()->getSourceFileName().empty()) {112SmallString<256> Suffix(SGV->getParent()->getSourceFileName());113std::replace_if(std::begin(Suffix), std::end(Suffix),114[&](char ch) { return !isAlnum(ch); }, '_');115return ModuleSummaryIndex::getGlobalNameForLocal(116SGV->getName(), Suffix);117}118119return ModuleSummaryIndex::getGlobalNameForLocal(120SGV->getName(),121ImportIndex.getModuleHash(SGV->getParent()->getModuleIdentifier()));122}123124GlobalValue::LinkageTypes125FunctionImportGlobalProcessing::getLinkage(const GlobalValue *SGV,126bool DoPromote) {127// Any local variable that is referenced by an exported function needs128// to be promoted to global scope. Since we don't currently know which129// functions reference which local variables/functions, we must treat130// all as potentially exported if this module is exporting anything.131if (isModuleExporting()) {132if (SGV->hasLocalLinkage() && DoPromote)133return GlobalValue::ExternalLinkage;134return SGV->getLinkage();135}136137// Otherwise, if we aren't importing, no linkage change is needed.138if (!isPerformingImport())139return SGV->getLinkage();140141switch (SGV->getLinkage()) {142case GlobalValue::LinkOnceODRLinkage:143case GlobalValue::ExternalLinkage:144// External and linkonce definitions are converted to available_externally145// definitions upon import, so that they are available for inlining146// and/or optimization, but are turned into declarations later147// during the EliminateAvailableExternally pass.148if (doImportAsDefinition(SGV) && !isa<GlobalAlias>(SGV))149return GlobalValue::AvailableExternallyLinkage;150// An imported external declaration stays external.151return SGV->getLinkage();152153case GlobalValue::AvailableExternallyLinkage:154// An imported available_externally definition converts155// to external if imported as a declaration.156if (!doImportAsDefinition(SGV))157return GlobalValue::ExternalLinkage;158// An imported available_externally declaration stays that way.159return SGV->getLinkage();160161case GlobalValue::LinkOnceAnyLinkage:162case GlobalValue::WeakAnyLinkage:163// Can't import linkonce_any/weak_any definitions correctly, or we might164// change the program semantics, since the linker will pick the first165// linkonce_any/weak_any definition and importing would change the order166// they are seen by the linker. The module linking caller needs to enforce167// this.168assert(!doImportAsDefinition(SGV));169// If imported as a declaration, it becomes external_weak.170return SGV->getLinkage();171172case GlobalValue::WeakODRLinkage:173// For weak_odr linkage, there is a guarantee that all copies will be174// equivalent, so the issue described above for weak_any does not exist,175// and the definition can be imported. It can be treated similarly176// to an imported externally visible global value.177if (doImportAsDefinition(SGV) && !isa<GlobalAlias>(SGV))178return GlobalValue::AvailableExternallyLinkage;179else180return GlobalValue::ExternalLinkage;181182case GlobalValue::AppendingLinkage:183// It would be incorrect to import an appending linkage variable,184// since it would cause global constructors/destructors to be185// executed multiple times. This should have already been handled186// by linkIfNeeded, and we will assert in shouldLinkFromSource187// if we try to import, so we simply return AppendingLinkage.188return GlobalValue::AppendingLinkage;189190case GlobalValue::InternalLinkage:191case GlobalValue::PrivateLinkage:192// If we are promoting the local to global scope, it is handled193// similarly to a normal externally visible global.194if (DoPromote) {195if (doImportAsDefinition(SGV) && !isa<GlobalAlias>(SGV))196return GlobalValue::AvailableExternallyLinkage;197else198return GlobalValue::ExternalLinkage;199}200// A non-promoted imported local definition stays local.201// The ThinLTO pass will eventually force-import their definitions.202return SGV->getLinkage();203204case GlobalValue::ExternalWeakLinkage:205// External weak doesn't apply to definitions, must be a declaration.206assert(!doImportAsDefinition(SGV));207// Linkage stays external_weak.208return SGV->getLinkage();209210case GlobalValue::CommonLinkage:211// Linkage stays common on definitions.212// The ThinLTO pass will eventually force-import their definitions.213return SGV->getLinkage();214}215216llvm_unreachable("unknown linkage type");217}218219void FunctionImportGlobalProcessing::processGlobalForThinLTO(GlobalValue &GV) {220221ValueInfo VI;222if (GV.hasName()) {223VI = ImportIndex.getValueInfo(GV.getGUID());224// Set synthetic function entry counts.225if (VI && ImportIndex.hasSyntheticEntryCounts()) {226if (Function *F = dyn_cast<Function>(&GV)) {227if (!F->isDeclaration()) {228for (const auto &S : VI.getSummaryList()) {229auto *FS = cast<FunctionSummary>(S->getBaseObject());230if (FS->modulePath() == M.getModuleIdentifier()) {231F->setEntryCount(Function::ProfileCount(FS->entryCount(),232Function::PCT_Synthetic));233break;234}235}236}237}238}239}240241// We should always have a ValueInfo (i.e. GV in index) for definitions when242// we are exporting, and also when importing that value.243assert(VI || GV.isDeclaration() ||244(isPerformingImport() && !doImportAsDefinition(&GV)));245246// Mark read/write-only variables which can be imported with specific247// attribute. We can't internalize them now because IRMover will fail248// to link variable definitions to their external declarations during249// ThinLTO import. We'll internalize read-only variables later, after250// import is finished. See internalizeGVsAfterImport.251//252// If global value dead stripping is not enabled in summary then253// propagateConstants hasn't been run. We can't internalize GV254// in such case.255if (!GV.isDeclaration() && VI && ImportIndex.withAttributePropagation()) {256if (GlobalVariable *V = dyn_cast<GlobalVariable>(&GV)) {257// We can have more than one local with the same GUID, in the case of258// same-named locals in different but same-named source files that were259// compiled in their respective directories (so the source file name260// and resulting GUID is the same). Find the one in this module.261// Handle the case where there is no summary found in this module. That262// can happen in the distributed ThinLTO backend, because the index only263// contains summaries from the source modules if they are being imported.264// We might have a non-null VI and get here even in that case if the name265// matches one in this module (e.g. weak or appending linkage).266auto *GVS = dyn_cast_or_null<GlobalVarSummary>(267ImportIndex.findSummaryInModule(VI, M.getModuleIdentifier()));268if (GVS &&269(ImportIndex.isReadOnly(GVS) || ImportIndex.isWriteOnly(GVS))) {270V->addAttribute("thinlto-internalize");271// Objects referenced by writeonly GV initializer should not be272// promoted, because there is no any kind of read access to them273// on behalf of this writeonly GV. To avoid promotion we convert274// GV initializer to 'zeroinitializer'. This effectively drops275// references in IR module (not in combined index), so we can276// ignore them when computing import. We do not export references277// of writeonly object. See computeImportForReferencedGlobals278if (ImportIndex.isWriteOnly(GVS))279V->setInitializer(Constant::getNullValue(V->getValueType()));280}281}282}283284if (GV.hasLocalLinkage() && shouldPromoteLocalToGlobal(&GV, VI)) {285// Save the original name string before we rename GV below.286auto Name = GV.getName().str();287GV.setName(getPromotedName(&GV));288GV.setLinkage(getLinkage(&GV, /* DoPromote */ true));289assert(!GV.hasLocalLinkage());290GV.setVisibility(GlobalValue::HiddenVisibility);291292// If we are renaming a COMDAT leader, ensure that we record the COMDAT293// for later renaming as well. This is required for COFF.294if (const auto *C = GV.getComdat())295if (C->getName() == Name)296RenamedComdats.try_emplace(C, M.getOrInsertComdat(GV.getName()));297} else298GV.setLinkage(getLinkage(&GV, /* DoPromote */ false));299300// When ClearDSOLocalOnDeclarations is true, clear dso_local if GV is301// converted to a declaration, to disable direct access. Don't do this if GV302// is implicitly dso_local due to a non-default visibility.303if (ClearDSOLocalOnDeclarations &&304(GV.isDeclarationForLinker() ||305(isPerformingImport() && !doImportAsDefinition(&GV))) &&306!GV.isImplicitDSOLocal()) {307GV.setDSOLocal(false);308} else if (VI && VI.isDSOLocal(ImportIndex.withDSOLocalPropagation())) {309// If all summaries are dso_local, symbol gets resolved to a known local310// definition.311GV.setDSOLocal(true);312if (GV.hasDLLImportStorageClass())313GV.setDLLStorageClass(GlobalValue::DefaultStorageClass);314}315316// Remove functions imported as available externally defs from comdats,317// as this is a declaration for the linker, and will be dropped eventually.318// It is illegal for comdats to contain declarations.319auto *GO = dyn_cast<GlobalObject>(&GV);320if (GO && GO->isDeclarationForLinker() && GO->hasComdat()) {321// The IRMover should not have placed any imported declarations in322// a comdat, so the only declaration that should be in a comdat323// at this point would be a definition imported as available_externally.324assert(GO->hasAvailableExternallyLinkage() &&325"Expected comdat on definition (possibly available external)");326GO->setComdat(nullptr);327}328}329330void FunctionImportGlobalProcessing::processGlobalsForThinLTO() {331for (GlobalVariable &GV : M.globals())332processGlobalForThinLTO(GV);333for (Function &SF : M)334processGlobalForThinLTO(SF);335for (GlobalAlias &GA : M.aliases())336processGlobalForThinLTO(GA);337338// Replace any COMDATS that required renaming (because the COMDAT leader was339// promoted and renamed).340if (!RenamedComdats.empty())341for (auto &GO : M.global_objects())342if (auto *C = GO.getComdat()) {343auto Replacement = RenamedComdats.find(C);344if (Replacement != RenamedComdats.end())345GO.setComdat(Replacement->second);346}347}348349bool FunctionImportGlobalProcessing::run() {350processGlobalsForThinLTO();351return false;352}353354bool llvm::renameModuleForThinLTO(Module &M, const ModuleSummaryIndex &Index,355bool ClearDSOLocalOnDeclarations,356SetVector<GlobalValue *> *GlobalsToImport) {357FunctionImportGlobalProcessing ThinLTOProcessing(M, Index, GlobalsToImport,358ClearDSOLocalOnDeclarations);359return ThinLTOProcessing.run();360}361362363