brintos

brintos / llvm-project-archived public Read only

0
0
Text · 16.0 KiB · d31154f Raw
384 lines · cpp
1//===- lib/Transforms/Utils/FunctionImportUtils.cpp - Importing utilities -===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file implements the FunctionImportGlobalProcessing class, used10// to perform the necessary global value handling for function importing.11//12//===----------------------------------------------------------------------===//13 14#include "llvm/Transforms/Utils/FunctionImportUtils.h"15#include "llvm/Support/CommandLine.h"16#include "llvm/Support/TimeProfiler.h"17 18using namespace llvm;19 20namespace llvm {21 22/// Uses the "source_filename" instead of a Module hash ID for the suffix of23/// promoted locals during LTO. NOTE: This requires that the source filename24/// has a unique name / path to avoid name collisions.25static cl::opt<bool> UseSourceFilenameForPromotedLocals(26    "use-source-filename-for-promoted-locals", cl::Hidden,27    cl::desc("Uses the source file name instead of the Module hash. "28             "This requires that the source filename has a unique name / "29             "path to avoid name collisions."));30 31cl::list<GlobalValue::GUID> MoveSymbolGUID(32    "thinlto-move-symbols",33    cl::desc(34        "Move the symbols with the given name. This will delete these symbols "35        "wherever they are originally defined, and make sure their "36        "linkage is External where they are imported. It is meant to be "37        "used with the name of contextual profiling roots."),38    cl::Hidden);39 40} // end namespace llvm41 42FunctionImportGlobalProcessing::FunctionImportGlobalProcessing(43    Module &M, const ModuleSummaryIndex &Index,44    SetVector<GlobalValue *> *GlobalsToImport, bool ClearDSOLocalOnDeclarations)45    : M(M), ImportIndex(Index), GlobalsToImport(GlobalsToImport),46      ClearDSOLocalOnDeclarations(ClearDSOLocalOnDeclarations) {47  // If we have a ModuleSummaryIndex but no function to import,48  // then this is the primary module being compiled in a ThinLTO49  // backend compilation, and we need to see if it has functions that50  // may be exported to another backend compilation.51  if (!GlobalsToImport)52    HasExportedFunctions = ImportIndex.hasExportedFunctions(M);53 54#ifndef NDEBUG55  SmallVector<GlobalValue *, 4> Vec;56  // First collect those in the llvm.used set.57  collectUsedGlobalVariables(M, Vec, /*CompilerUsed=*/false);58  // Next collect those in the llvm.compiler.used set.59  collectUsedGlobalVariables(M, Vec, /*CompilerUsed=*/true);60  Used = {llvm::from_range, Vec};61#endif62  SymbolsToMove.insert_range(MoveSymbolGUID);63}64 65/// Checks if we should import SGV as a definition, otherwise import as a66/// declaration.67bool FunctionImportGlobalProcessing::doImportAsDefinition(68    const GlobalValue *SGV) {69  if (!isPerformingImport())70    return false;71 72  // Only import the globals requested for importing.73  if (!GlobalsToImport->count(const_cast<GlobalValue *>(SGV)))74    return false;75 76  assert(!isa<GlobalAlias>(SGV) &&77         "Unexpected global alias in the import list.");78 79  // Otherwise yes.80  return true;81}82 83bool FunctionImportGlobalProcessing::shouldPromoteLocalToGlobal(84    const GlobalValue *SGV, ValueInfo VI) {85  assert(SGV->hasLocalLinkage());86 87  // Ifuncs and ifunc alias does not have summary.88  if (isa<GlobalIFunc>(SGV) ||89      (isa<GlobalAlias>(SGV) &&90       isa<GlobalIFunc>(cast<GlobalAlias>(SGV)->getAliaseeObject())))91    return false;92 93  // Both the imported references and the original local variable must94  // be promoted.95  if (!isPerformingImport() && !isModuleExporting())96    return false;97 98  if (isPerformingImport()) {99    assert((!GlobalsToImport->count(const_cast<GlobalValue *>(SGV)) ||100            !isNonRenamableLocal(*SGV)) &&101           "Attempting to promote non-renamable local");102    // We don't know for sure yet if we are importing this value (as either103    // a reference or a def), since we are simply walking all values in the104    // module. But by necessity if we end up importing it and it is local,105    // it must be promoted, so unconditionally promote all values in the106    // importing module.107    return true;108  }109 110  // When exporting, consult the index. We can have more than one local111  // with the same GUID, in the case of same-named locals in different but112  // same-named source files that were compiled in their respective directories113  // (so the source file name and resulting GUID is the same). Find the one114  // in this module.115  auto Summary = ImportIndex.findSummaryInModule(116      VI, SGV->getParent()->getModuleIdentifier());117  assert(Summary && "Missing summary for global value when exporting");118  auto Linkage = Summary->linkage();119  if (!GlobalValue::isLocalLinkage(Linkage)) {120    assert(!isNonRenamableLocal(*SGV) &&121           "Attempting to promote non-renamable local");122    return true;123  }124 125  return false;126}127 128#ifndef NDEBUG129bool FunctionImportGlobalProcessing::isNonRenamableLocal(130    const GlobalValue &GV) const {131  if (!GV.hasLocalLinkage())132    return false;133  // This needs to stay in sync with the logic in buildModuleSummaryIndex.134  if (GV.hasSection())135    return true;136  if (Used.count(const_cast<GlobalValue *>(&GV)))137    return true;138  return false;139}140#endif141 142std::string143FunctionImportGlobalProcessing::getPromotedName(const GlobalValue *SGV) {144  assert(SGV->hasLocalLinkage());145 146  // For locals that must be promoted to global scope, ensure that147  // the promoted name uniquely identifies the copy in the original module,148  // using the ID assigned during combined index creation.149  if (UseSourceFilenameForPromotedLocals &&150      !SGV->getParent()->getSourceFileName().empty()) {151    SmallString<256> Suffix(SGV->getParent()->getSourceFileName());152    std::replace_if(std::begin(Suffix), std::end(Suffix),153                    [&](char ch) { return !isAlnum(ch); }, '_');154    return ModuleSummaryIndex::getGlobalNameForLocal(155        SGV->getName(), Suffix);156  }157 158  return ModuleSummaryIndex::getGlobalNameForLocal(159      SGV->getName(),160      ImportIndex.getModuleHash(SGV->getParent()->getModuleIdentifier()));161}162 163GlobalValue::LinkageTypes164FunctionImportGlobalProcessing::getLinkage(const GlobalValue *SGV,165                                           bool DoPromote) {166  // Any local variable that is referenced by an exported function needs167  // to be promoted to global scope. Since we don't currently know which168  // functions reference which local variables/functions, we must treat169  // all as potentially exported if this module is exporting anything.170  if (isModuleExporting()) {171    if (SGV->hasLocalLinkage() && DoPromote)172      return GlobalValue::ExternalLinkage;173    return SGV->getLinkage();174  }175 176  // Otherwise, if we aren't importing, no linkage change is needed.177  if (!isPerformingImport())178    return SGV->getLinkage();179 180  switch (SGV->getLinkage()) {181  case GlobalValue::LinkOnceODRLinkage:182  case GlobalValue::ExternalLinkage:183    // External and linkonce definitions are converted to available_externally184    // definitions upon import, so that they are available for inlining185    // and/or optimization, but are turned into declarations later186    // during the EliminateAvailableExternally pass.187    if (doImportAsDefinition(SGV) && !isa<GlobalAlias>(SGV))188      return SymbolsToMove.contains(SGV->getGUID())189                 ? GlobalValue::ExternalLinkage190                 : GlobalValue::AvailableExternallyLinkage;191    // An imported external declaration stays external.192    return SGV->getLinkage();193 194  case GlobalValue::AvailableExternallyLinkage:195    // An imported available_externally definition converts196    // to external if imported as a declaration.197    if (!doImportAsDefinition(SGV))198      return GlobalValue::ExternalLinkage;199    // An imported available_externally declaration stays that way.200    return SGV->getLinkage();201 202  case GlobalValue::LinkOnceAnyLinkage:203  case GlobalValue::WeakAnyLinkage:204    // Can't import linkonce_any/weak_any definitions correctly, or we might205    // change the program semantics, since the linker will pick the first206    // linkonce_any/weak_any definition and importing would change the order207    // they are seen by the linker. The module linking caller needs to enforce208    // this.209    assert(!doImportAsDefinition(SGV));210    // If imported as a declaration, it becomes external_weak.211    return SGV->getLinkage();212 213  case GlobalValue::WeakODRLinkage:214    // For weak_odr linkage, there is a guarantee that all copies will be215    // equivalent, so the issue described above for weak_any does not exist,216    // and the definition can be imported. It can be treated similarly217    // to an imported externally visible global value.218    if (doImportAsDefinition(SGV) && !isa<GlobalAlias>(SGV))219      return GlobalValue::AvailableExternallyLinkage;220    else221      return GlobalValue::ExternalLinkage;222 223  case GlobalValue::AppendingLinkage:224    // It would be incorrect to import an appending linkage variable,225    // since it would cause global constructors/destructors to be226    // executed multiple times. This should have already been handled227    // by linkIfNeeded, and we will assert in shouldLinkFromSource228    // if we try to import, so we simply return AppendingLinkage.229    return GlobalValue::AppendingLinkage;230 231  case GlobalValue::InternalLinkage:232  case GlobalValue::PrivateLinkage:233    // If we are promoting the local to global scope, it is handled234    // similarly to a normal externally visible global.235    if (DoPromote) {236      if (doImportAsDefinition(SGV) && !isa<GlobalAlias>(SGV))237        return GlobalValue::AvailableExternallyLinkage;238      else239        return GlobalValue::ExternalLinkage;240    }241    // A non-promoted imported local definition stays local.242    // The ThinLTO pass will eventually force-import their definitions.243    return SGV->getLinkage();244 245  case GlobalValue::ExternalWeakLinkage:246    // External weak doesn't apply to definitions, must be a declaration.247    assert(!doImportAsDefinition(SGV));248    // Linkage stays external_weak.249    return SGV->getLinkage();250 251  case GlobalValue::CommonLinkage:252    // Linkage stays common on definitions.253    // The ThinLTO pass will eventually force-import their definitions.254    return SGV->getLinkage();255  }256 257  llvm_unreachable("unknown linkage type");258}259 260void FunctionImportGlobalProcessing::processGlobalForThinLTO(GlobalValue &GV) {261 262  ValueInfo VI;263  if (GV.hasName())264    VI = ImportIndex.getValueInfo(GV.getGUID());265 266  // We should always have a ValueInfo (i.e. GV in index) for definitions when267  // we are exporting, and also when importing that value.268  assert(VI || GV.isDeclaration() ||269         (isPerformingImport() && !doImportAsDefinition(&GV)));270 271  // Mark read/write-only variables which can be imported with specific272  // attribute. We can't internalize them now because IRMover will fail273  // to link variable definitions to their external declarations during274  // ThinLTO import. We'll internalize read-only variables later, after275  // import is finished. See internalizeGVsAfterImport.276  //277  // If global value dead stripping is not enabled in summary then278  // propagateConstants hasn't been run. We can't internalize GV279  // in such case.280  if (!GV.isDeclaration() && VI && ImportIndex.withAttributePropagation()) {281    if (GlobalVariable *V = dyn_cast<GlobalVariable>(&GV)) {282      // We can have more than one local with the same GUID, in the case of283      // same-named locals in different but same-named source files that were284      // compiled in their respective directories (so the source file name285      // and resulting GUID is the same). Find the one in this module.286      // Handle the case where there is no summary found in this module. That287      // can happen in the distributed ThinLTO backend, because the index only288      // contains summaries from the source modules if they are being imported.289      // We might have a non-null VI and get here even in that case if the name290      // matches one in this module (e.g. weak or appending linkage).291      auto *GVS = dyn_cast_or_null<GlobalVarSummary>(292          ImportIndex.findSummaryInModule(VI, M.getModuleIdentifier()));293      if (GVS &&294          (ImportIndex.isReadOnly(GVS) || ImportIndex.isWriteOnly(GVS))) {295        V->addAttribute("thinlto-internalize");296        // Objects referenced by writeonly GV initializer should not be297        // promoted, because there is no any kind of read access to them298        // on behalf of this writeonly GV. To avoid promotion we convert299        // GV initializer to 'zeroinitializer'. This effectively drops300        // references in IR module (not in combined index), so we can301        // ignore them when computing import. We do not export references302        // of writeonly object. See computeImportForReferencedGlobals303        if (ImportIndex.isWriteOnly(GVS))304          V->setInitializer(Constant::getNullValue(V->getValueType()));305      }306    }307  }308 309  if (GV.hasLocalLinkage() && shouldPromoteLocalToGlobal(&GV, VI)) {310    // Save the original name string before we rename GV below.311    auto Name = GV.getName().str();312    GV.setName(getPromotedName(&GV));313    GV.setLinkage(getLinkage(&GV, /* DoPromote */ true));314    assert(!GV.hasLocalLinkage());315    GV.setVisibility(GlobalValue::HiddenVisibility);316 317    // If we are renaming a COMDAT leader, ensure that we record the COMDAT318    // for later renaming as well. This is required for COFF.319    if (const auto *C = GV.getComdat())320      if (C->getName() == Name)321        RenamedComdats.try_emplace(C, M.getOrInsertComdat(GV.getName()));322  } else323    GV.setLinkage(getLinkage(&GV, /* DoPromote */ false));324 325  // When ClearDSOLocalOnDeclarations is true, clear dso_local if GV is326  // converted to a declaration, to disable direct access. Don't do this if GV327  // is implicitly dso_local due to a non-default visibility.328  if (ClearDSOLocalOnDeclarations &&329      (GV.isDeclarationForLinker() ||330       (isPerformingImport() && !doImportAsDefinition(&GV))) &&331      !GV.isImplicitDSOLocal()) {332    GV.setDSOLocal(false);333  } else if (VI && VI.isDSOLocal(ImportIndex.withDSOLocalPropagation())) {334    // If all summaries are dso_local, symbol gets resolved to a known local335    // definition.336    GV.setDSOLocal(true);337    if (GV.hasDLLImportStorageClass())338      GV.setDLLStorageClass(GlobalValue::DefaultStorageClass);339  }340 341  // Remove functions imported as available externally defs from comdats,342  // as this is a declaration for the linker, and will be dropped eventually.343  // It is illegal for comdats to contain declarations.344  auto *GO = dyn_cast<GlobalObject>(&GV);345  if (GO && GO->isDeclarationForLinker() && GO->hasComdat()) {346    // The IRMover should not have placed any imported declarations in347    // a comdat, so the only declaration that should be in a comdat348    // at this point would be a definition imported as available_externally.349    assert(GO->hasAvailableExternallyLinkage() &&350           "Expected comdat on definition (possibly available external)");351    GO->setComdat(nullptr);352  }353}354 355void FunctionImportGlobalProcessing::processGlobalsForThinLTO() {356  for (GlobalVariable &GV : M.globals())357    processGlobalForThinLTO(GV);358  for (Function &SF : M)359    processGlobalForThinLTO(SF);360  for (GlobalAlias &GA : M.aliases())361    processGlobalForThinLTO(GA);362 363  // Replace any COMDATS that required renaming (because the COMDAT leader was364  // promoted and renamed).365  if (!RenamedComdats.empty())366    for (auto &GO : M.global_objects())367      if (auto *C = GO.getComdat()) {368        auto Replacement = RenamedComdats.find(C);369        if (Replacement != RenamedComdats.end())370          GO.setComdat(Replacement->second);371      }372}373 374void FunctionImportGlobalProcessing::run() { processGlobalsForThinLTO(); }375 376void llvm::renameModuleForThinLTO(Module &M, const ModuleSummaryIndex &Index,377                                  bool ClearDSOLocalOnDeclarations,378                                  SetVector<GlobalValue *> *GlobalsToImport) {379  llvm::TimeTraceScope timeScope("Rename module for ThinLTO");380  FunctionImportGlobalProcessing ThinLTOProcessing(M, Index, GlobalsToImport,381                                                   ClearDSOLocalOnDeclarations);382  ThinLTOProcessing.run();383}384