[llvm] r260395 - [ThinLTO] Move global processing from Linker to TransformUtils (NFC)

Teresa Johnson via llvm-commits llvm-commits at lists.llvm.org
Wed Feb 10 10:11:32 PST 2016


Author: tejohnson
Date: Wed Feb 10 12:11:31 2016
New Revision: 260395

URL: http://llvm.org/viewvc/llvm-project?rev=260395&view=rev
Log:
[ThinLTO] Move global processing from Linker to TransformUtils (NFC)

Summary:
As discussed on IRC, move the ThinLTOGlobalProcessing code out of
the linker, and into TransformUtils. The name of the class is changed
to FunctionImportGlobalProcessing.

Reviewers: joker.eph, rafael

Subscribers: joker.eph, llvm-commits

Differential Revision: http://reviews.llvm.org/D17081

Added:
    llvm/trunk/include/llvm/Transforms/Utils/FunctionImportUtils.h
    llvm/trunk/lib/Transforms/Utils/FunctionImportUtils.cpp
Modified:
    llvm/trunk/include/llvm/Linker/Linker.h
    llvm/trunk/lib/Linker/LinkModules.cpp
    llvm/trunk/lib/Transforms/IPO/FunctionImport.cpp
    llvm/trunk/lib/Transforms/Utils/CMakeLists.txt

Modified: llvm/trunk/include/llvm/Linker/Linker.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Linker/Linker.h?rev=260395&r1=260394&r2=260395&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Linker/Linker.h (original)
+++ llvm/trunk/include/llvm/Linker/Linker.h Wed Feb 10 12:11:31 2016
@@ -67,10 +67,6 @@ public:
                       DenseMap<unsigned, MDNode *> *ValIDToTempMDMap);
 };
 
-/// Perform in-place global value handling on the given Module for
-/// exported local functions renamed and promoted for ThinLTO.
-bool renameModuleForThinLTO(Module &M, const FunctionInfoIndex *Index);
-
 } // End llvm namespace
 
 #endif

Added: llvm/trunk/include/llvm/Transforms/Utils/FunctionImportUtils.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Utils/FunctionImportUtils.h?rev=260395&view=auto
==============================================================================
--- llvm/trunk/include/llvm/Transforms/Utils/FunctionImportUtils.h (added)
+++ llvm/trunk/include/llvm/Transforms/Utils/FunctionImportUtils.h Wed Feb 10 12:11:31 2016
@@ -0,0 +1,106 @@
+//===- FunctionImportUtils.h - Importing support utilities -----*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the FunctionImportGlobalProcessing class which is used
+// to perform the necessary global value handling for function importing.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_UTILS_FUNCTIONIMPORTUTILS_H
+#define LLVM_TRANSFORMS_UTILS_FUNCTIONIMPORTUTILS_H
+
+#include "llvm/ADT/SetVector.h"
+#include "llvm/IR/FunctionInfo.h"
+
+namespace llvm {
+class Module;
+
+/// Class to handle necessary GlobalValue changes required by ThinLTO
+/// function importing, including linkage changes and any necessary renaming.
+class FunctionImportGlobalProcessing {
+  /// The Module which we are exporting or importing functions from.
+  Module &M;
+
+  /// Function index passed in for function importing/exporting handling.
+  const FunctionInfoIndex *ImportIndex;
+
+  /// Functions to import from this module, all other functions will be
+  /// imported as declarations instead of definitions.
+  DenseSet<const GlobalValue *> *FunctionsToImport;
+
+  /// Set to true if the given FunctionInfoIndex contains any functions
+  /// from this source module, in which case we must conservatively assume
+  /// that any of its functions may be imported into another module
+  /// as part of a different backend compilation process.
+  bool HasExportedFunctions = false;
+
+  /// Populated during ThinLTO global processing with locals promoted
+  /// to global scope in an exporting module, which now need to be linked
+  /// in if calling from the ModuleLinker.
+  SetVector<GlobalValue *> NewExportedValues;
+
+  /// Check if we should promote the given local value to global scope.
+  bool doPromoteLocalToGlobal(const GlobalValue *SGV);
+
+  /// Helper methods to check if we are importing from or potentially
+  /// exporting from the current source module.
+  bool isPerformingImport() const { return FunctionsToImport != nullptr; }
+  bool isModuleExporting() const { return HasExportedFunctions; }
+
+  /// If we are importing from the source module, checks if we should
+  /// import SGV as a definition, otherwise import as a declaration.
+  bool doImportAsDefinition(const GlobalValue *SGV);
+
+  /// Get the name for SGV that should be used in the linked destination
+  /// module. Specifically, this handles the case where we need to rename
+  /// a local that is being promoted to global scope.
+  std::string getName(const GlobalValue *SGV);
+
+  /// Process globals so that they can be used in ThinLTO. This includes
+  /// promoting local variables so that they can be reference externally by
+  /// thin lto imported globals and converting strong external globals to
+  /// available_externally.
+  void processGlobalsForThinLTO();
+  void processGlobalForThinLTO(GlobalValue &GV);
+
+  /// Get the new linkage for SGV that should be used in the linked destination
+  /// module. Specifically, for ThinLTO importing or exporting it may need
+  /// to be adjusted.
+  GlobalValue::LinkageTypes getLinkage(const GlobalValue *SGV);
+
+public:
+  FunctionImportGlobalProcessing(
+      Module &M, const FunctionInfoIndex *Index,
+      DenseSet<const GlobalValue *> *FunctionsToImport = nullptr)
+      : M(M), ImportIndex(Index), FunctionsToImport(FunctionsToImport) {
+    // If we have a FunctionInfoIndex but no function to import,
+    // then this is the primary module being compiled in a ThinLTO
+    // backend compilation, and we need to see if it has functions that
+    // may be exported to another backend compilation.
+    if (!FunctionsToImport)
+      HasExportedFunctions = ImportIndex->hasExportedFunctions(M);
+  }
+
+  bool run();
+
+  static bool
+  doImportAsDefinition(const GlobalValue *SGV,
+                       DenseSet<const GlobalValue *> *FunctionsToImport);
+
+  /// Access the promoted globals that are now exported and need to be linked.
+  SetVector<GlobalValue *> &getNewExportedValues() { return NewExportedValues; }
+};
+
+/// Perform in-place global value handling on the given Module for
+/// exported local functions renamed and promoted for ThinLTO.
+bool renameModuleForThinLTO(Module &M, const FunctionInfoIndex *Index);
+
+} // End llvm namespace
+
+#endif

Modified: llvm/trunk/lib/Linker/LinkModules.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Linker/LinkModules.cpp?rev=260395&r1=260394&r2=260395&view=diff
==============================================================================
--- llvm/trunk/lib/Linker/LinkModules.cpp (original)
+++ llvm/trunk/lib/Linker/LinkModules.cpp Wed Feb 10 12:11:31 2016
@@ -11,13 +11,14 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "llvm/Linker/Linker.h"
 #include "LinkDiagnosticInfo.h"
 #include "llvm-c/Linker.h"
 #include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/StringSet.h"
 #include "llvm/IR/DiagnosticPrinter.h"
 #include "llvm/IR/LLVMContext.h"
+#include "llvm/Linker/Linker.h"
+#include "llvm/Transforms/Utils/FunctionImportUtils.h"
 using namespace llvm;
 
 namespace {
@@ -141,257 +142,13 @@ public:
 
   bool run();
 };
-
-/// Class to handle necessary GlobalValue changes required by ThinLTO including
-/// linkage changes and any necessary renaming.
-class ThinLTOGlobalProcessing {
-  /// The Module which we are exporting or importing functions from.
-  Module &M;
-
-  /// Function index passed in for function importing/exporting handling.
-  const FunctionInfoIndex *ImportIndex;
-
-  /// Functions to import from this module, all other functions will be
-  /// imported as declarations instead of definitions.
-  DenseSet<const GlobalValue *> *FunctionsToImport;
-
-  /// Set to true if the given FunctionInfoIndex contains any functions
-  /// from this source module, in which case we must conservatively assume
-  /// that any of its functions may be imported into another module
-  /// as part of a different backend compilation process.
-  bool HasExportedFunctions = false;
-
-  /// Populated during ThinLTO global processing with locals promoted
-  /// to global scope in an exporting module, which now need to be linked
-  /// in if calling from the ModuleLinker.
-  SetVector<GlobalValue *> NewExportedValues;
-
-  /// Check if we should promote the given local value to global scope.
-  bool doPromoteLocalToGlobal(const GlobalValue *SGV);
-
-  /// Helper methods to check if we are importing from or potentially
-  /// exporting from the current source module.
-  bool isPerformingImport() const { return FunctionsToImport != nullptr; }
-  bool isModuleExporting() const { return HasExportedFunctions; }
-
-  /// If we are importing from the source module, checks if we should
-  /// import SGV as a definition, otherwise import as a declaration.
-  bool doImportAsDefinition(const GlobalValue *SGV);
-
-  /// Get the name for SGV that should be used in the linked destination
-  /// module. Specifically, this handles the case where we need to rename
-  /// a local that is being promoted to global scope.
-  std::string getName(const GlobalValue *SGV);
-
-  /// Process globals so that they can be used in ThinLTO. This includes
-  /// promoting local variables so that they can be reference externally by
-  /// thin lto imported globals and converting strong external globals to
-  /// available_externally.
-  void processGlobalsForThinLTO();
-  void processGlobalForThinLTO(GlobalValue &GV);
-
-  /// Get the new linkage for SGV that should be used in the linked destination
-  /// module. Specifically, for ThinLTO importing or exporting it may need
-  /// to be adjusted.
-  GlobalValue::LinkageTypes getLinkage(const GlobalValue *SGV);
-
-public:
-  ThinLTOGlobalProcessing(
-      Module &M, const FunctionInfoIndex *Index,
-      DenseSet<const GlobalValue *> *FunctionsToImport = nullptr)
-      : M(M), ImportIndex(Index), FunctionsToImport(FunctionsToImport) {
-    // If we have a FunctionInfoIndex but no function to import,
-    // then this is the primary module being compiled in a ThinLTO
-    // backend compilation, and we need to see if it has functions that
-    // may be exported to another backend compilation.
-    if (!FunctionsToImport)
-      HasExportedFunctions = ImportIndex->hasExportedFunctions(M);
-  }
-
-  bool run();
-
-  /// Access the promoted globals that are now exported and need to be linked.
-  SetVector<GlobalValue *> &getNewExportedValues() { return NewExportedValues; }
-};
-}
-
-/// Checks if we should import SGV as a definition, otherwise import as a
-/// declaration.
-static bool
-doImportAsDefinitionImpl(const GlobalValue *SGV,
-                         DenseSet<const GlobalValue *> *FunctionsToImport) {
-  auto *GA = dyn_cast<GlobalAlias>(SGV);
-  if (GA) {
-    if (GA->hasWeakAnyLinkage())
-      return false;
-    const GlobalObject *GO = GA->getBaseObject();
-    if (!GO->hasLinkOnceODRLinkage())
-      return false;
-    return doImportAsDefinitionImpl(GO, FunctionsToImport);
-  }
-  // Always import GlobalVariable definitions, except for the special
-  // case of WeakAny which are imported as ExternalWeak declarations
-  // (see comments in ModuleLinker::getLinkage). The linkage changes
-  // described in ModuleLinker::getLinkage ensure the correct behavior (e.g.
-  // global variables with external linkage are transformed to
-  // available_externally definitions, which are ultimately turned into
-  // declarations after the EliminateAvailableExternally pass).
-  if (isa<GlobalVariable>(SGV) && !SGV->isDeclaration() &&
-      !SGV->hasWeakAnyLinkage())
-    return true;
-  // Only import the function requested for importing.
-  auto *SF = dyn_cast<Function>(SGV);
-  if (SF && FunctionsToImport->count(SF))
-    return true;
-  // Otherwise no.
-  return false;
-}
-
-bool ThinLTOGlobalProcessing::doImportAsDefinition(const GlobalValue *SGV) {
-  if (!isPerformingImport())
-    return false;
-  return doImportAsDefinitionImpl(SGV, FunctionsToImport);
 }
 
 bool ModuleLinker::doImportAsDefinition(const GlobalValue *SGV) {
   if (!isPerformingImport())
     return false;
-  return doImportAsDefinitionImpl(SGV, FunctionsToImport);
-}
-
-bool ThinLTOGlobalProcessing::doPromoteLocalToGlobal(const GlobalValue *SGV) {
-  assert(SGV->hasLocalLinkage());
-  // Both the imported references and the original local variable must
-  // be promoted.
-  if (!isPerformingImport() && !isModuleExporting())
-    return false;
-
-  // Local const variables never need to be promoted unless they are address
-  // taken. The imported uses can simply use the clone created in this module.
-  // For now we are conservative in determining which variables are not
-  // address taken by checking the unnamed addr flag. To be more aggressive,
-  // the address taken information must be checked earlier during parsing
-  // of the module and recorded in the function index for use when importing
-  // from that module.
-  auto *GVar = dyn_cast<GlobalVariable>(SGV);
-  if (GVar && GVar->isConstant() && GVar->hasUnnamedAddr())
-    return false;
-
-  // Eventually we only need to promote functions in the exporting module that
-  // are referenced by a potentially exported function (i.e. one that is in the
-  // function index).
-  return true;
-}
-
-std::string ThinLTOGlobalProcessing::getName(const GlobalValue *SGV) {
-  // For locals that must be promoted to global scope, ensure that
-  // the promoted name uniquely identifies the copy in the original module,
-  // using the ID assigned during combined index creation. When importing,
-  // we rename all locals (not just those that are promoted) in order to
-  // avoid naming conflicts between locals imported from different modules.
-  if (SGV->hasLocalLinkage() &&
-      (doPromoteLocalToGlobal(SGV) || isPerformingImport()))
-    return FunctionInfoIndex::getGlobalNameForLocal(
-        SGV->getName(),
-        ImportIndex->getModuleId(SGV->getParent()->getModuleIdentifier()));
-  return SGV->getName();
-}
-
-GlobalValue::LinkageTypes
-ThinLTOGlobalProcessing::getLinkage(const GlobalValue *SGV) {
-  // Any local variable that is referenced by an exported function needs
-  // to be promoted to global scope. Since we don't currently know which
-  // functions reference which local variables/functions, we must treat
-  // all as potentially exported if this module is exporting anything.
-  if (isModuleExporting()) {
-    if (SGV->hasLocalLinkage() && doPromoteLocalToGlobal(SGV))
-      return GlobalValue::ExternalLinkage;
-    return SGV->getLinkage();
-  }
-
-  // Otherwise, if we aren't importing, no linkage change is needed.
-  if (!isPerformingImport())
-    return SGV->getLinkage();
-
-  switch (SGV->getLinkage()) {
-  case GlobalValue::ExternalLinkage:
-    // External defnitions are converted to available_externally
-    // definitions upon import, so that they are available for inlining
-    // and/or optimization, but are turned into declarations later
-    // during the EliminateAvailableExternally pass.
-    if (doImportAsDefinition(SGV) && !dyn_cast<GlobalAlias>(SGV))
-      return GlobalValue::AvailableExternallyLinkage;
-    // An imported external declaration stays external.
-    return SGV->getLinkage();
-
-  case GlobalValue::AvailableExternallyLinkage:
-    // An imported available_externally definition converts
-    // to external if imported as a declaration.
-    if (!doImportAsDefinition(SGV))
-      return GlobalValue::ExternalLinkage;
-    // An imported available_externally declaration stays that way.
-    return SGV->getLinkage();
-
-  case GlobalValue::LinkOnceAnyLinkage:
-  case GlobalValue::LinkOnceODRLinkage:
-    // These both stay the same when importing the definition.
-    // The ThinLTO pass will eventually force-import their definitions.
-    return SGV->getLinkage();
-
-  case GlobalValue::WeakAnyLinkage:
-    // Can't import weak_any definitions correctly, or we might change the
-    // program semantics, since the linker will pick the first weak_any
-    // definition and importing would change the order they are seen by the
-    // linker. The module linking caller needs to enforce this.
-    assert(!doImportAsDefinition(SGV));
-    // If imported as a declaration, it becomes external_weak.
-    return GlobalValue::ExternalWeakLinkage;
-
-  case GlobalValue::WeakODRLinkage:
-    // For weak_odr linkage, there is a guarantee that all copies will be
-    // equivalent, so the issue described above for weak_any does not exist,
-    // and the definition can be imported. It can be treated similarly
-    // to an imported externally visible global value.
-    if (doImportAsDefinition(SGV) && !dyn_cast<GlobalAlias>(SGV))
-      return GlobalValue::AvailableExternallyLinkage;
-    else
-      return GlobalValue::ExternalLinkage;
-
-  case GlobalValue::AppendingLinkage:
-    // It would be incorrect to import an appending linkage variable,
-    // since it would cause global constructors/destructors to be
-    // executed multiple times. This should have already been handled
-    // by linkIfNeeded, and we will assert in shouldLinkFromSource
-    // if we try to import, so we simply return AppendingLinkage.
-    return GlobalValue::AppendingLinkage;
-
-  case GlobalValue::InternalLinkage:
-  case GlobalValue::PrivateLinkage:
-    // If we are promoting the local to global scope, it is handled
-    // similarly to a normal externally visible global.
-    if (doPromoteLocalToGlobal(SGV)) {
-      if (doImportAsDefinition(SGV) && !dyn_cast<GlobalAlias>(SGV))
-        return GlobalValue::AvailableExternallyLinkage;
-      else
-        return GlobalValue::ExternalLinkage;
-    }
-    // A non-promoted imported local definition stays local.
-    // The ThinLTO pass will eventually force-import their definitions.
-    return SGV->getLinkage();
-
-  case GlobalValue::ExternalWeakLinkage:
-    // External weak doesn't apply to definitions, must be a declaration.
-    assert(!doImportAsDefinition(SGV));
-    // Linkage stays external_weak.
-    return SGV->getLinkage();
-
-  case GlobalValue::CommonLinkage:
-    // Linkage stays common on definitions.
-    // The ThinLTO pass will eventually force-import their definitions.
-    return SGV->getLinkage();
-  }
-
-  llvm_unreachable("unknown linkage type");
+  return FunctionImportGlobalProcessing::doImportAsDefinition(
+      SGV, FunctionsToImport);
 }
 
 static GlobalValue::VisibilityTypes
@@ -713,46 +470,6 @@ void ModuleLinker::addLazyFor(GlobalValu
   }
 }
 
-void ThinLTOGlobalProcessing::processGlobalForThinLTO(GlobalValue &GV) {
-  if (GV.hasLocalLinkage() &&
-      (doPromoteLocalToGlobal(&GV) || isPerformingImport())) {
-    GV.setName(getName(&GV));
-    GV.setLinkage(getLinkage(&GV));
-    if (!GV.hasLocalLinkage())
-      GV.setVisibility(GlobalValue::HiddenVisibility);
-    if (isModuleExporting())
-      NewExportedValues.insert(&GV);
-  } else
-    GV.setLinkage(getLinkage(&GV));
-
-  // Remove functions imported as available externally defs 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()) {
-    // The IRMover should not have placed any imported declarations in
-    // a comdat, so the only declaration that should be in a comdat
-    // at this point would be a definition imported as available_externally.
-    assert(GO->hasAvailableExternallyLinkage() &&
-           "Expected comdat on definition (possibly available external)");
-    GO->setComdat(nullptr);
-  }
-}
-
-void ThinLTOGlobalProcessing::processGlobalsForThinLTO() {
-  for (GlobalVariable &GV : M.globals())
-    processGlobalForThinLTO(GV);
-  for (Function &SF : M)
-    processGlobalForThinLTO(SF);
-  for (GlobalAlias &GA : M.aliases())
-    processGlobalForThinLTO(GA);
-}
-
-bool ThinLTOGlobalProcessing::run() {
-  processGlobalsForThinLTO();
-  return false;
-}
-
 bool ModuleLinker::run() {
   for (const auto &SMEC : SrcM.getComdatSymbolTable()) {
     const Comdat &C = SMEC.getValue();
@@ -792,8 +509,8 @@ bool ModuleLinker::run() {
       return true;
 
   if (ImportIndex) {
-    ThinLTOGlobalProcessing ThinLTOProcessing(SrcM, ImportIndex,
-                                              FunctionsToImport);
+    FunctionImportGlobalProcessing ThinLTOProcessing(SrcM, ImportIndex,
+                                                     FunctionsToImport);
     if (ThinLTOProcessing.run())
       return true;
     for (auto *GV : ThinLTOProcessing.getNewExportedValues())
@@ -871,11 +588,6 @@ bool Linker::linkModules(Module &Dest, s
   return L.linkInModule(std::move(Src), Flags);
 }
 
-bool llvm::renameModuleForThinLTO(Module &M, const FunctionInfoIndex *Index) {
-  ThinLTOGlobalProcessing ThinLTOProcessing(M, Index);
-  return ThinLTOProcessing.run();
-}
-
 //===----------------------------------------------------------------------===//
 // C API.
 //===----------------------------------------------------------------------===//

Modified: llvm/trunk/lib/Transforms/IPO/FunctionImport.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/FunctionImport.cpp?rev=260395&r1=260394&r2=260395&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/IPO/FunctionImport.cpp (original)
+++ llvm/trunk/lib/Transforms/IPO/FunctionImport.cpp Wed Feb 10 12:11:31 2016
@@ -24,6 +24,7 @@
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/SourceMgr.h"
+#include "llvm/Transforms/Utils/FunctionImportUtils.h"
 
 #include <map>
 

Modified: llvm/trunk/lib/Transforms/Utils/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/CMakeLists.txt?rev=260395&r1=260394&r2=260395&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Utils/CMakeLists.txt (original)
+++ llvm/trunk/lib/Transforms/Utils/CMakeLists.txt Wed Feb 10 12:11:31 2016
@@ -13,6 +13,7 @@ add_llvm_library(LLVMTransformUtils
   DemoteRegToStack.cpp
   Evaluator.cpp
   FlattenCFG.cpp
+  FunctionImportUtils.cpp
   GlobalStatus.cpp
   InlineFunction.cpp
   InstructionNamer.cpp

Added: llvm/trunk/lib/Transforms/Utils/FunctionImportUtils.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/FunctionImportUtils.cpp?rev=260395&view=auto
==============================================================================
--- llvm/trunk/lib/Transforms/Utils/FunctionImportUtils.cpp (added)
+++ llvm/trunk/lib/Transforms/Utils/FunctionImportUtils.cpp Wed Feb 10 12:11:31 2016
@@ -0,0 +1,237 @@
+//===- lib/Transforms/Utils/FunctionImportUtils.cpp - Importing utilities -===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the FunctionImportGlobalProcessing class, used
+// to perform the necessary global value handling for function importing.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Transforms/Utils/FunctionImportUtils.h"
+using namespace llvm;
+
+/// Checks if we should import SGV as a definition, otherwise import as a
+/// declaration.
+bool FunctionImportGlobalProcessing::doImportAsDefinition(
+    const GlobalValue *SGV, DenseSet<const GlobalValue *> *FunctionsToImport) {
+  auto *GA = dyn_cast<GlobalAlias>(SGV);
+  if (GA) {
+    if (GA->hasWeakAnyLinkage())
+      return false;
+    const GlobalObject *GO = GA->getBaseObject();
+    if (!GO->hasLinkOnceODRLinkage())
+      return false;
+    return FunctionImportGlobalProcessing::doImportAsDefinition(
+        GO, FunctionsToImport);
+  }
+  // Always import GlobalVariable definitions, except for the special
+  // case of WeakAny which are imported as ExternalWeak declarations
+  // (see comments in FunctionImportGlobalProcessing::getLinkage). The linkage
+  // changes described in FunctionImportGlobalProcessing::getLinkage ensure the
+  // correct behavior (e.g. global variables with external linkage are
+  // transformed to available_externally definitions, which are ultimately
+  // turned into declarations after the EliminateAvailableExternally pass).
+  if (isa<GlobalVariable>(SGV) && !SGV->isDeclaration() &&
+      !SGV->hasWeakAnyLinkage())
+    return true;
+  // Only import the function requested for importing.
+  auto *SF = dyn_cast<Function>(SGV);
+  if (SF && FunctionsToImport->count(SF))
+    return true;
+  // Otherwise no.
+  return false;
+}
+
+bool FunctionImportGlobalProcessing::doImportAsDefinition(
+    const GlobalValue *SGV) {
+  if (!isPerformingImport())
+    return false;
+  return FunctionImportGlobalProcessing::doImportAsDefinition(
+      SGV, FunctionsToImport);
+}
+
+bool FunctionImportGlobalProcessing::doPromoteLocalToGlobal(
+    const GlobalValue *SGV) {
+  assert(SGV->hasLocalLinkage());
+  // Both the imported references and the original local variable must
+  // be promoted.
+  if (!isPerformingImport() && !isModuleExporting())
+    return false;
+
+  // Local const variables never need to be promoted unless they are address
+  // taken. The imported uses can simply use the clone created in this module.
+  // For now we are conservative in determining which variables are not
+  // address taken by checking the unnamed addr flag. To be more aggressive,
+  // the address taken information must be checked earlier during parsing
+  // of the module and recorded in the function index for use when importing
+  // from that module.
+  auto *GVar = dyn_cast<GlobalVariable>(SGV);
+  if (GVar && GVar->isConstant() && GVar->hasUnnamedAddr())
+    return false;
+
+  // Eventually we only need to promote functions in the exporting module that
+  // are referenced by a potentially exported function (i.e. one that is in the
+  // function index).
+  return true;
+}
+
+std::string FunctionImportGlobalProcessing::getName(const GlobalValue *SGV) {
+  // For locals that must be promoted to global scope, ensure that
+  // the promoted name uniquely identifies the copy in the original module,
+  // using the ID assigned during combined index creation. When importing,
+  // we rename all locals (not just those that are promoted) in order to
+  // avoid naming conflicts between locals imported from different modules.
+  if (SGV->hasLocalLinkage() &&
+      (doPromoteLocalToGlobal(SGV) || isPerformingImport()))
+    return FunctionInfoIndex::getGlobalNameForLocal(
+        SGV->getName(),
+        ImportIndex->getModuleId(SGV->getParent()->getModuleIdentifier()));
+  return SGV->getName();
+}
+
+GlobalValue::LinkageTypes
+FunctionImportGlobalProcessing::getLinkage(const GlobalValue *SGV) {
+  // Any local variable that is referenced by an exported function needs
+  // to be promoted to global scope. Since we don't currently know which
+  // functions reference which local variables/functions, we must treat
+  // all as potentially exported if this module is exporting anything.
+  if (isModuleExporting()) {
+    if (SGV->hasLocalLinkage() && doPromoteLocalToGlobal(SGV))
+      return GlobalValue::ExternalLinkage;
+    return SGV->getLinkage();
+  }
+
+  // Otherwise, if we aren't importing, no linkage change is needed.
+  if (!isPerformingImport())
+    return SGV->getLinkage();
+
+  switch (SGV->getLinkage()) {
+  case GlobalValue::ExternalLinkage:
+    // External defnitions are converted to available_externally
+    // definitions upon import, so that they are available for inlining
+    // and/or optimization, but are turned into declarations later
+    // during the EliminateAvailableExternally pass.
+    if (doImportAsDefinition(SGV) && !dyn_cast<GlobalAlias>(SGV))
+      return GlobalValue::AvailableExternallyLinkage;
+    // An imported external declaration stays external.
+    return SGV->getLinkage();
+
+  case GlobalValue::AvailableExternallyLinkage:
+    // An imported available_externally definition converts
+    // to external if imported as a declaration.
+    if (!doImportAsDefinition(SGV))
+      return GlobalValue::ExternalLinkage;
+    // An imported available_externally declaration stays that way.
+    return SGV->getLinkage();
+
+  case GlobalValue::LinkOnceAnyLinkage:
+  case GlobalValue::LinkOnceODRLinkage:
+    // These both stay the same when importing the definition.
+    // The ThinLTO pass will eventually force-import their definitions.
+    return SGV->getLinkage();
+
+  case GlobalValue::WeakAnyLinkage:
+    // Can't import weak_any definitions correctly, or we might change the
+    // program semantics, since the linker will pick the first weak_any
+    // definition and importing would change the order they are seen by the
+    // linker. The module linking caller needs to enforce this.
+    assert(!doImportAsDefinition(SGV));
+    // If imported as a declaration, it becomes external_weak.
+    return GlobalValue::ExternalWeakLinkage;
+
+  case GlobalValue::WeakODRLinkage:
+    // For weak_odr linkage, there is a guarantee that all copies will be
+    // equivalent, so the issue described above for weak_any does not exist,
+    // and the definition can be imported. It can be treated similarly
+    // to an imported externally visible global value.
+    if (doImportAsDefinition(SGV) && !dyn_cast<GlobalAlias>(SGV))
+      return GlobalValue::AvailableExternallyLinkage;
+    else
+      return GlobalValue::ExternalLinkage;
+
+  case GlobalValue::AppendingLinkage:
+    // It would be incorrect to import an appending linkage variable,
+    // since it would cause global constructors/destructors to be
+    // executed multiple times. This should have already been handled
+    // by linkIfNeeded, and we will assert in shouldLinkFromSource
+    // if we try to import, so we simply return AppendingLinkage.
+    return GlobalValue::AppendingLinkage;
+
+  case GlobalValue::InternalLinkage:
+  case GlobalValue::PrivateLinkage:
+    // If we are promoting the local to global scope, it is handled
+    // similarly to a normal externally visible global.
+    if (doPromoteLocalToGlobal(SGV)) {
+      if (doImportAsDefinition(SGV) && !dyn_cast<GlobalAlias>(SGV))
+        return GlobalValue::AvailableExternallyLinkage;
+      else
+        return GlobalValue::ExternalLinkage;
+    }
+    // A non-promoted imported local definition stays local.
+    // The ThinLTO pass will eventually force-import their definitions.
+    return SGV->getLinkage();
+
+  case GlobalValue::ExternalWeakLinkage:
+    // External weak doesn't apply to definitions, must be a declaration.
+    assert(!doImportAsDefinition(SGV));
+    // Linkage stays external_weak.
+    return SGV->getLinkage();
+
+  case GlobalValue::CommonLinkage:
+    // Linkage stays common on definitions.
+    // The ThinLTO pass will eventually force-import their definitions.
+    return SGV->getLinkage();
+  }
+
+  llvm_unreachable("unknown linkage type");
+}
+
+void FunctionImportGlobalProcessing::processGlobalForThinLTO(GlobalValue &GV) {
+  if (GV.hasLocalLinkage() &&
+      (doPromoteLocalToGlobal(&GV) || isPerformingImport())) {
+    GV.setName(getName(&GV));
+    GV.setLinkage(getLinkage(&GV));
+    if (!GV.hasLocalLinkage())
+      GV.setVisibility(GlobalValue::HiddenVisibility);
+    if (isModuleExporting())
+      NewExportedValues.insert(&GV);
+  } else
+    GV.setLinkage(getLinkage(&GV));
+
+  // Remove functions imported as available externally defs 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()) {
+    // The IRMover should not have placed any imported declarations in
+    // a comdat, so the only declaration that should be in a comdat
+    // at this point would be a definition imported as available_externally.
+    assert(GO->hasAvailableExternallyLinkage() &&
+           "Expected comdat on definition (possibly available external)");
+    GO->setComdat(nullptr);
+  }
+}
+
+void FunctionImportGlobalProcessing::processGlobalsForThinLTO() {
+  for (GlobalVariable &GV : M.globals())
+    processGlobalForThinLTO(GV);
+  for (Function &SF : M)
+    processGlobalForThinLTO(SF);
+  for (GlobalAlias &GA : M.aliases())
+    processGlobalForThinLTO(GA);
+}
+
+bool FunctionImportGlobalProcessing::run() {
+  processGlobalsForThinLTO();
+  return false;
+}
+
+bool llvm::renameModuleForThinLTO(Module &M, const FunctionInfoIndex *Index) {
+  FunctionImportGlobalProcessing ThinLTOProcessing(M, Index);
+  return ThinLTOProcessing.run();
+}




More information about the llvm-commits mailing list