[llvm] r305482 - Apply summary-based dead stripping to regular LTO modules with summaries.

Peter Collingbourne via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 15 10:26:13 PDT 2017


Author: pcc
Date: Thu Jun 15 12:26:13 2017
New Revision: 305482

URL: http://llvm.org/viewvc/llvm-project?rev=305482&view=rev
Log:
Apply summary-based dead stripping to regular LTO modules with summaries.

If a regular LTO module has a summary index, then instead of linking
it into the combined regular LTO module right away, add it to the
combined summary index and associate it with a special module that
represents the combined regular LTO module.

Any such modules are linked during LTO::run(), at which time we use
the results of summary-based dead stripping to control whether to
link prevailing symbols.

Differential Revision: https://reviews.llvm.org/D33922

Added:
    llvm/trunk/test/LTO/Resolution/X86/Inputs/dead-strip-fulllto.ll
    llvm/trunk/test/LTO/Resolution/X86/dead-strip-fulllto.ll
Modified:
    llvm/trunk/include/llvm/Bitcode/BitcodeReader.h
    llvm/trunk/include/llvm/IR/ModuleSummaryIndex.h
    llvm/trunk/include/llvm/LTO/LTO.h
    llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp
    llvm/trunk/lib/IR/ModuleSummaryIndex.cpp
    llvm/trunk/lib/LTO/LTO.cpp
    llvm/trunk/lib/LTO/LTOModule.cpp

Modified: llvm/trunk/include/llvm/Bitcode/BitcodeReader.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Bitcode/BitcodeReader.h?rev=305482&r1=305481&r2=305482&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Bitcode/BitcodeReader.h (original)
+++ llvm/trunk/include/llvm/Bitcode/BitcodeReader.h Thu Jun 15 12:26:13 2017
@@ -42,6 +42,12 @@ namespace llvm {
 
   struct BitcodeFileContents;
 
+  /// Basic information extracted from a bitcode module to be used for LTO.
+  struct BitcodeLTOInfo {
+    bool IsThinLTO;
+    bool HasSummary;
+  };
+
   /// Represents a module in a bitcode file.
   class BitcodeModule {
     // This covers the identification (if present) and module blocks.
@@ -90,15 +96,17 @@ namespace llvm {
     /// Read the entire bitcode module and return it.
     Expected<std::unique_ptr<Module>> parseModule(LLVMContext &Context);
 
-    /// Check if the given bitcode buffer contains a summary block.
-    Expected<bool> hasSummary();
+    /// Returns information about the module to be used for LTO: whether to
+    /// compile with ThinLTO, and whether it has a summary.
+    Expected<BitcodeLTOInfo> getLTOInfo();
 
     /// Parse the specified bitcode buffer, returning the module summary index.
     Expected<std::unique_ptr<ModuleSummaryIndex>> getSummary();
 
     /// Parse the specified bitcode buffer and merge its module summary index
     /// into CombinedIndex.
-    Error readSummary(ModuleSummaryIndex &CombinedIndex, unsigned ModuleId);
+    Error readSummary(ModuleSummaryIndex &CombinedIndex, StringRef ModulePath,
+                      uint64_t ModuleId);
   };
 
   struct BitcodeFileContents {
@@ -147,8 +155,8 @@ namespace llvm {
   Expected<std::unique_ptr<Module>> parseBitcodeFile(MemoryBufferRef Buffer,
                                                      LLVMContext &Context);
 
-  /// Check if the given bitcode buffer contains a summary block.
-  Expected<bool> hasGlobalValueSummary(MemoryBufferRef Buffer);
+  /// Returns LTO information for the specified bitcode file.
+  Expected<BitcodeLTOInfo> getBitcodeLTOInfo(MemoryBufferRef Buffer);
 
   /// Parse the specified bitcode buffer, returning the module summary index.
   Expected<std::unique_ptr<ModuleSummaryIndex>>
@@ -157,7 +165,7 @@ namespace llvm {
   /// Parse the specified bitcode buffer and merge the index into CombinedIndex.
   Error readModuleSummaryIndex(MemoryBufferRef Buffer,
                                ModuleSummaryIndex &CombinedIndex,
-                               unsigned ModuleId);
+                               uint64_t ModuleId);
 
   /// Parse the module summary index out of an IR file and return the module
   /// summary index object if found, or an empty summary if not. If Path refers

Modified: llvm/trunk/include/llvm/IR/ModuleSummaryIndex.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/ModuleSummaryIndex.h?rev=305482&r1=305481&r2=305482&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/ModuleSummaryIndex.h (original)
+++ llvm/trunk/include/llvm/IR/ModuleSummaryIndex.h Thu Jun 15 12:26:13 2017
@@ -567,6 +567,7 @@ public:
   bool isGlobalValueLive(const GlobalValueSummary *GVS) const {
     return !WithGlobalValueDeadStripping || GVS->isLive();
   }
+  bool isGUIDLive(GlobalValue::GUID GUID) const;
 
   /// Return a ValueInfo for GUID if it exists, otherwise return ValueInfo().
   ValueInfo getValueInfo(GlobalValue::GUID GUID) const {

Modified: llvm/trunk/include/llvm/LTO/LTO.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/LTO/LTO.h?rev=305482&r1=305481&r2=305482&view=diff
==============================================================================
--- llvm/trunk/include/llvm/LTO/LTO.h (original)
+++ llvm/trunk/include/llvm/LTO/LTO.h Thu Jun 15 12:26:13 2017
@@ -281,6 +281,16 @@ private:
     bool HasModule = false;
     std::unique_ptr<Module> CombinedModule;
     std::unique_ptr<IRMover> Mover;
+
+    // This stores the information about a regular LTO module that we have added
+    // to the link. It will either be linked immediately (for modules without
+    // summaries) or after summary-based dead stripping (for modules with
+    // summaries).
+    struct AddedModule {
+      std::unique_ptr<Module> M;
+      std::vector<GlobalValue *> Keep;
+    };
+    std::vector<AddedModule> ModsWithSummaries;
   } RegularLTO;
 
   struct ThinLTOState {
@@ -303,9 +313,10 @@ private:
     /// The unmangled name of the global.
     std::string IRName;
 
-    /// Keep track if the symbol is visible outside of ThinLTO (i.e. in
-    /// either a regular object or the regular LTO partition).
-    bool VisibleOutsideThinLTO = false;
+    /// Keep track if the symbol is visible outside of a module with a summary
+    /// (i.e. in either a regular object or a regular LTO module without a
+    /// summary).
+    bool VisibleOutsideSummary = false;
 
     bool UnnamedAddr = true;
 
@@ -339,8 +350,9 @@ private:
   // Global mapping from mangled symbol names to resolutions.
   StringMap<GlobalResolution> GlobalResolutions;
 
-  void addSymbolToGlobalRes(const InputFile::Symbol &Sym, SymbolResolution Res,
-                            unsigned Partition);
+  void addModuleToGlobalRes(ArrayRef<InputFile::Symbol> Syms,
+                            ArrayRef<SymbolResolution> Res, unsigned Partition,
+                            bool InSummary);
 
   // These functions take a range of symbol resolutions [ResI, ResE) and consume
   // the resolutions used by a single input module by incrementing ResI. After
@@ -348,10 +360,13 @@ private:
   // the remaining modules in the InputFile.
   Error addModule(InputFile &Input, unsigned ModI,
                   const SymbolResolution *&ResI, const SymbolResolution *ResE);
-  Error addRegularLTO(BitcodeModule BM,
-                      ArrayRef<InputFile::Symbol> Syms,
-                      const SymbolResolution *&ResI,
-                      const SymbolResolution *ResE);
+
+  Expected<RegularLTOState::AddedModule>
+  addRegularLTO(BitcodeModule BM, ArrayRef<InputFile::Symbol> Syms,
+                const SymbolResolution *&ResI, const SymbolResolution *ResE);
+  Error linkRegularLTO(RegularLTOState::AddedModule Mod,
+                       bool LivenessFromIndex);
+
   Error addThinLTO(BitcodeModule BM, ArrayRef<InputFile::Symbol> Syms,
                    const SymbolResolution *&ResI, const SymbolResolution *ResE);
 

Modified: llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp?rev=305482&r1=305481&r2=305482&view=diff
==============================================================================
--- llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp (original)
+++ llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp Thu Jun 15 12:26:13 2017
@@ -733,7 +733,7 @@ private:
   std::vector<FunctionSummary::EdgeTy> makeCallList(ArrayRef<uint64_t> Record,
                                                     bool IsOldProfileFormat,
                                                     bool HasProfile);
-  Error parseEntireSummary();
+  Error parseEntireSummary(unsigned ID);
   Error parseModuleStringTable();
 
   std::pair<ValueInfo, GlobalValue::GUID>
@@ -4854,6 +4854,7 @@ Error ModuleSummaryIndexBitcodeReader::p
           return error("Invalid record");
         break;
       case bitc::GLOBALVAL_SUMMARY_BLOCK_ID:
+      case bitc::FULL_LTO_GLOBALVAL_SUMMARY_BLOCK_ID:
         assert(!SeenValueSymbolTable &&
                "Already read VST when parsing summary block?");
         // We might not have a VST if there were no values in the
@@ -4866,7 +4867,7 @@ Error ModuleSummaryIndexBitcodeReader::p
           SeenValueSymbolTable = true;
         }
         SeenGlobalValSummary = true;
-        if (Error Err = parseEntireSummary())
+        if (Error Err = parseEntireSummary(Entry.ID))
           return Err;
         break;
       case bitc::MODULE_STRTAB_BLOCK_ID:
@@ -4974,8 +4975,8 @@ std::vector<FunctionSummary::EdgeTy> Mod
 
 // Eagerly parse the entire summary block. This populates the GlobalValueSummary
 // objects in the index.
-Error ModuleSummaryIndexBitcodeReader::parseEntireSummary() {
-  if (Stream.EnterSubBlock(bitc::GLOBALVAL_SUMMARY_BLOCK_ID))
+Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(unsigned ID) {
+  if (Stream.EnterSubBlock(ID))
     return error("Invalid record");
   SmallVector<uint64_t, 64> Record;
 
@@ -5517,13 +5518,16 @@ BitcodeModule::getLazyModule(LLVMContext
 }
 
 // Parse the specified bitcode buffer and merge the index into CombinedIndex.
+// We don't use ModuleIdentifier here because the client may need to control the
+// module path used in the combined summary (e.g. when reading summaries for
+// regular LTO modules).
 Error BitcodeModule::readSummary(ModuleSummaryIndex &CombinedIndex,
-                                 unsigned ModuleId) {
+                                 StringRef ModulePath, uint64_t ModuleId) {
   BitstreamCursor Stream(Buffer);
   Stream.JumpToBit(ModuleBit);
 
   ModuleSummaryIndexBitcodeReader R(std::move(Stream), Strtab, CombinedIndex,
-                                    ModuleIdentifier, ModuleId);
+                                    ModulePath, ModuleId);
   return R.parseModule();
 }
 
@@ -5543,7 +5547,7 @@ Expected<std::unique_ptr<ModuleSummaryIn
 }
 
 // Check if the given bitcode buffer contains a global value summary block.
-Expected<bool> BitcodeModule::hasSummary() {
+Expected<BitcodeLTOInfo> BitcodeModule::getLTOInfo() {
   BitstreamCursor Stream(Buffer);
   Stream.JumpToBit(ModuleBit);
 
@@ -5557,11 +5561,14 @@ Expected<bool> BitcodeModule::hasSummary
     case BitstreamEntry::Error:
       return error("Malformed block");
     case BitstreamEntry::EndBlock:
-      return false;
+      return BitcodeLTOInfo{/*IsThinLTO=*/false, /*HasSummary=*/false};
 
     case BitstreamEntry::SubBlock:
       if (Entry.ID == bitc::GLOBALVAL_SUMMARY_BLOCK_ID)
-        return true;
+        return BitcodeLTOInfo{/*IsThinLTO=*/true, /*HasSummary=*/true};
+
+      if (Entry.ID == bitc::FULL_LTO_GLOBALVAL_SUMMARY_BLOCK_ID)
+        return BitcodeLTOInfo{/*IsThinLTO=*/false, /*HasSummary=*/true};
 
       // Ignore other sub-blocks.
       if (Stream.SkipBlock())
@@ -5648,12 +5655,12 @@ Expected<std::string> llvm::getBitcodePr
 
 Error llvm::readModuleSummaryIndex(MemoryBufferRef Buffer,
                                    ModuleSummaryIndex &CombinedIndex,
-                                   unsigned ModuleId) {
+                                   uint64_t ModuleId) {
   Expected<BitcodeModule> BM = getSingleModule(Buffer);
   if (!BM)
     return BM.takeError();
 
-  return BM->readSummary(CombinedIndex, ModuleId);
+  return BM->readSummary(CombinedIndex, BM->getModuleIdentifier(), ModuleId);
 }
 
 Expected<std::unique_ptr<ModuleSummaryIndex>>
@@ -5665,12 +5672,12 @@ llvm::getModuleSummaryIndex(MemoryBuffer
   return BM->getSummary();
 }
 
-Expected<bool> llvm::hasGlobalValueSummary(MemoryBufferRef Buffer) {
+Expected<BitcodeLTOInfo> llvm::getBitcodeLTOInfo(MemoryBufferRef Buffer) {
   Expected<BitcodeModule> BM = getSingleModule(Buffer);
   if (!BM)
     return BM.takeError();
 
-  return BM->hasSummary();
+  return BM->getLTOInfo();
 }
 
 Expected<std::unique_ptr<ModuleSummaryIndex>>

Modified: llvm/trunk/lib/IR/ModuleSummaryIndex.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/ModuleSummaryIndex.cpp?rev=305482&r1=305481&r2=305482&view=diff
==============================================================================
--- llvm/trunk/lib/IR/ModuleSummaryIndex.cpp (original)
+++ llvm/trunk/lib/IR/ModuleSummaryIndex.cpp Thu Jun 15 12:26:13 2017
@@ -56,3 +56,13 @@ ModuleSummaryIndex::getGlobalValueSummar
   auto &Summary = VI.getSummaryList()[0];
   return Summary.get();
 }
+
+bool ModuleSummaryIndex::isGUIDLive(GlobalValue::GUID GUID) const {
+  auto VI = getValueInfo(GUID);
+  if (!VI)
+    return false;
+  for (auto &I : VI.getSummaryList())
+    if (isGlobalValueLive(I.get()))
+      return true;
+  return false;
+}

Modified: llvm/trunk/lib/LTO/LTO.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/LTO/LTO.cpp?rev=305482&r1=305481&r2=305482&view=diff
==============================================================================
--- llvm/trunk/lib/LTO/LTO.cpp (original)
+++ llvm/trunk/lib/LTO/LTO.cpp Thu Jun 15 12:26:13 2017
@@ -364,31 +364,39 @@ LTO::LTO(Config Conf, ThinBackend Backen
 // Requires a destructor for MapVector<BitcodeModule>.
 LTO::~LTO() = default;
 
-// Add the given symbol to the GlobalResolutions map, and resolve its partition.
-void LTO::addSymbolToGlobalRes(const InputFile::Symbol &Sym,
-                               SymbolResolution Res, unsigned Partition) {
-  auto &GlobalRes = GlobalResolutions[Sym.getName()];
-  GlobalRes.UnnamedAddr &= Sym.isUnnamedAddr();
-  if (Res.Prevailing)
-    GlobalRes.IRName = Sym.getIRName();
-
-  // Set the partition to external if we know it is re-defined by the linker
-  // with -defsym or -wrap options, used elsewhere, e.g. it is visible to a
-  // regular object, is referenced from llvm.compiler_used, or was already
-  // recorded as being referenced from a different partition.
-  if (Res.LinkerRedefined || Res.VisibleToRegularObj || Sym.isUsed() ||
-      (GlobalRes.Partition != GlobalResolution::Unknown &&
-       GlobalRes.Partition != Partition)) {
-    GlobalRes.Partition = GlobalResolution::External;
-  } else
-    // First recorded reference, save the current partition.
-    GlobalRes.Partition = Partition;
-
-  // Flag as visible outside of ThinLTO if visible from a regular object or
-  // if this is a reference in the regular LTO partition.
-  GlobalRes.VisibleOutsideThinLTO |=
-      (Res.VisibleToRegularObj || Sym.isUsed() ||
-       Partition == GlobalResolution::RegularLTO);
+// Add the symbols in the given module to the GlobalResolutions map, and resolve
+// their partitions.
+void LTO::addModuleToGlobalRes(ArrayRef<InputFile::Symbol> Syms,
+                               ArrayRef<SymbolResolution> Res,
+                               unsigned Partition, bool InSummary) {
+  auto *ResI = Res.begin();
+  auto *ResE = Res.end();
+  for (const InputFile::Symbol &Sym : Syms) {
+    assert(ResI != ResE);
+    SymbolResolution Res = *ResI++;
+
+    auto &GlobalRes = GlobalResolutions[Sym.getName()];
+    GlobalRes.UnnamedAddr &= Sym.isUnnamedAddr();
+    if (Res.Prevailing)
+      GlobalRes.IRName = Sym.getIRName();
+
+    // Set the partition to external if we know it is re-defined by the linker
+    // with -defsym or -wrap options, used elsewhere, e.g. it is visible to a
+    // regular object, is referenced from llvm.compiler_used, or was already
+    // recorded as being referenced from a different partition.
+    if (Res.LinkerRedefined || Res.VisibleToRegularObj || Sym.isUsed() ||
+        (GlobalRes.Partition != GlobalResolution::Unknown &&
+         GlobalRes.Partition != Partition)) {
+      GlobalRes.Partition = GlobalResolution::External;
+    } else
+      // First recorded reference, save the current partition.
+      GlobalRes.Partition = Partition;
+
+    // Flag as visible outside of summary if visible from a regular object or
+    // from a module that does not have a summary.
+    GlobalRes.VisibleOutsideSummary |=
+        (Res.VisibleToRegularObj || Sym.isUsed() || !InSummary);
+  }
 }
 
 static void writeToResolutionFile(raw_ostream &OS, InputFile *Input,
@@ -434,46 +442,61 @@ Error LTO::add(std::unique_ptr<InputFile
 Error LTO::addModule(InputFile &Input, unsigned ModI,
                      const SymbolResolution *&ResI,
                      const SymbolResolution *ResE) {
-  Expected<bool> HasThinLTOSummary = Input.Mods[ModI].hasSummary();
-  if (!HasThinLTOSummary)
-    return HasThinLTOSummary.takeError();
+  Expected<BitcodeLTOInfo> LTOInfo = Input.Mods[ModI].getLTOInfo();
+  if (!LTOInfo)
+    return LTOInfo.takeError();
 
+  BitcodeModule BM = Input.Mods[ModI];
   auto ModSyms = Input.module_symbols(ModI);
-  if (*HasThinLTOSummary)
-    return addThinLTO(Input.Mods[ModI], ModSyms, ResI, ResE);
-  else
-    return addRegularLTO(Input.Mods[ModI], ModSyms, ResI, ResE);
+  addModuleToGlobalRes(ModSyms, {ResI, ResE},
+                       LTOInfo->IsThinLTO ? ThinLTO.ModuleMap.size() + 1 : 0,
+                       LTOInfo->HasSummary);
+
+  if (LTOInfo->IsThinLTO)
+    return addThinLTO(BM, ModSyms, ResI, ResE);
+
+  Expected<RegularLTOState::AddedModule> ModOrErr =
+      addRegularLTO(BM, ModSyms, ResI, ResE);
+  if (!ModOrErr)
+    return ModOrErr.takeError();
+
+  if (!LTOInfo->HasSummary)
+    return linkRegularLTO(std::move(*ModOrErr), /*LivenessFromIndex=*/false);
+
+  // Regular LTO module summaries are added to a dummy module that represents
+  // the combined regular LTO module.
+  if (Error Err = BM.readSummary(ThinLTO.CombinedIndex, "", -1ull))
+    return Err;
+  RegularLTO.ModsWithSummaries.push_back(std::move(*ModOrErr));
+  return Error::success();
 }
 
 // Add a regular LTO object to the link.
-Error LTO::addRegularLTO(BitcodeModule BM,
-                         ArrayRef<InputFile::Symbol> Syms,
-                         const SymbolResolution *&ResI,
-                         const SymbolResolution *ResE) {
-  if (!RegularLTO.CombinedModule) {
-    RegularLTO.CombinedModule =
-        llvm::make_unique<Module>("ld-temp.o", RegularLTO.Ctx);
-    RegularLTO.Mover = llvm::make_unique<IRMover>(*RegularLTO.CombinedModule);
-  }
+// The resulting module needs to be linked into the combined LTO module with
+// linkRegularLTO.
+Expected<LTO::RegularLTOState::AddedModule>
+LTO::addRegularLTO(BitcodeModule BM, ArrayRef<InputFile::Symbol> Syms,
+                   const SymbolResolution *&ResI,
+                   const SymbolResolution *ResE) {
+  RegularLTOState::AddedModule Mod;
   Expected<std::unique_ptr<Module>> MOrErr =
       BM.getLazyModule(RegularLTO.Ctx, /*ShouldLazyLoadMetadata*/ true,
                        /*IsImporting*/ false);
   if (!MOrErr)
     return MOrErr.takeError();
-
   Module &M = **MOrErr;
+  Mod.M = std::move(*MOrErr);
+
   if (Error Err = M.materializeMetadata())
-    return Err;
+    return std::move(Err);
   UpgradeDebugInfo(M);
 
   ModuleSymbolTable SymTab;
   SymTab.addModule(&M);
 
-  std::vector<GlobalValue *> Keep;
-
   for (GlobalVariable &GV : M.globals())
     if (GV.hasAppendingLinkage())
-      Keep.push_back(&GV);
+      Mod.Keep.push_back(&GV);
 
   DenseSet<GlobalObject *> AliasedGlobals;
   for (auto &GA : M.aliases())
@@ -502,7 +525,6 @@ Error LTO::addRegularLTO(BitcodeModule B
   for (const InputFile::Symbol &Sym : Syms) {
     assert(ResI != ResE);
     SymbolResolution Res = *ResI++;
-    addSymbolToGlobalRes(Sym, Res, 0);
 
     assert(MsymI != MsymE);
     ModuleSymbolTable::Symbol Msym = *MsymI++;
@@ -512,7 +534,7 @@ Error LTO::addRegularLTO(BitcodeModule B
       if (Res.Prevailing) {
         if (Sym.isUndefined())
           continue;
-        Keep.push_back(GV);
+        Mod.Keep.push_back(GV);
         // For symbols re-defined with linker -wrap and -defsym options,
         // set the linkage to weak to inhibit IPO. The linkage will be
         // restored by the linker.
@@ -527,17 +549,14 @@ Error LTO::addRegularLTO(BitcodeModule B
                  (GV->hasLinkOnceODRLinkage() || GV->hasWeakODRLinkage() ||
                   GV->hasAvailableExternallyLinkage()) &&
                  !AliasedGlobals.count(cast<GlobalObject>(GV))) {
-        // Either of the above three types of linkage indicates that the
+        // Any of the above three types of linkage indicates that the
         // chosen prevailing symbol will have the same semantics as this copy of
-        // the symbol, so we can link it with available_externally linkage. We
-        // only need to do this if the symbol is undefined.
-        GlobalValue *CombinedGV =
-            RegularLTO.CombinedModule->getNamedValue(GV->getName());
-        if (!CombinedGV || CombinedGV->isDeclaration()) {
-          Keep.push_back(GV);
-          GV->setLinkage(GlobalValue::AvailableExternallyLinkage);
-          cast<GlobalObject>(GV)->setComdat(nullptr);
-        }
+        // the symbol, so we may be able to link it with available_externally
+        // linkage. We will decide later whether to do that when we link this
+        // module (in linkRegularLTO), based on whether it is undefined.
+        Mod.Keep.push_back(GV);
+        GV->setLinkage(GlobalValue::AvailableExternallyLinkage);
+        cast<GlobalObject>(GV)->setComdat(nullptr);
       }
     }
     // Common resolution: collect the maximum size/alignment over all commons.
@@ -555,25 +574,54 @@ Error LTO::addRegularLTO(BitcodeModule B
     // FIXME: use proposed local attribute for FinalDefinitionInLinkageUnit.
   }
   assert(MsymI == MsymE);
+  return std::move(Mod);
+}
 
-  return RegularLTO.Mover->move(std::move(*MOrErr), Keep,
+Error LTO::linkRegularLTO(RegularLTOState::AddedModule Mod,
+                          bool LivenessFromIndex) {
+  if (!RegularLTO.CombinedModule) {
+    RegularLTO.CombinedModule =
+        llvm::make_unique<Module>("ld-temp.o", RegularLTO.Ctx);
+    RegularLTO.Mover = llvm::make_unique<IRMover>(*RegularLTO.CombinedModule);
+  }
+
+  std::vector<GlobalValue *> Keep;
+  for (GlobalValue *GV : Mod.Keep) {
+    if (LivenessFromIndex && !ThinLTO.CombinedIndex.isGUIDLive(GV->getGUID()))
+      continue;
+
+    if (!GV->hasAvailableExternallyLinkage()) {
+      Keep.push_back(GV);
+      continue;
+    }
+
+    // Only link available_externally definitions if we don't already have a
+    // definition.
+    GlobalValue *CombinedGV =
+        RegularLTO.CombinedModule->getNamedValue(GV->getName());
+    if (CombinedGV && !CombinedGV->isDeclaration())
+      continue;
+
+    Keep.push_back(GV);
+  }
+
+  return RegularLTO.Mover->move(std::move(Mod.M), Keep,
                                 [](GlobalValue &, IRMover::ValueAdder) {},
                                 /* IsPerformingImport */ false);
 }
 
-// Add a ThinLTO object to the link.
-Error LTO::addThinLTO(BitcodeModule BM,
-                      ArrayRef<InputFile::Symbol> Syms,
+// Add a ThinLTO module to the link.
+Error LTO::addThinLTO(BitcodeModule BM, ArrayRef<InputFile::Symbol> Syms,
                       const SymbolResolution *&ResI,
                       const SymbolResolution *ResE) {
   if (Error Err =
-          BM.readSummary(ThinLTO.CombinedIndex, ThinLTO.ModuleMap.size()))
+          BM.readSummary(ThinLTO.CombinedIndex, BM.getModuleIdentifier(),
+                         ThinLTO.ModuleMap.size()))
     return Err;
 
   for (const InputFile::Symbol &Sym : Syms) {
     assert(ResI != ResE);
     SymbolResolution Res = *ResI++;
-    addSymbolToGlobalRes(Sym, Res, ThinLTO.ModuleMap.size() + 1);
 
     if (Res.Prevailing) {
       if (!Sym.getIRName().empty()) {
@@ -601,7 +649,7 @@ Error LTO::run(AddStreamFn AddStream, Na
   // Compute "dead" symbols, we don't want to import/export these!
   DenseSet<GlobalValue::GUID> GUIDPreservedSymbols;
   for (auto &Res : GlobalResolutions) {
-    if (Res.second.VisibleOutsideThinLTO &&
+    if (Res.second.VisibleOutsideSummary &&
         // IRName will be defined if we have seen the prevailing copy of
         // this value. If not, no need to preserve any ThinLTO copies.
         !Res.second.IRName.empty())
@@ -614,7 +662,8 @@ Error LTO::run(AddStreamFn AddStream, Na
   // Save the status of having a regularLTO combined module, as
   // this is needed for generating the ThinLTO Task ID, and
   // the CombinedModule will be moved at the end of runRegularLTO.
-  bool HasRegularLTO = RegularLTO.CombinedModule != nullptr;
+  bool HasRegularLTO = RegularLTO.CombinedModule != nullptr ||
+                       !RegularLTO.ModsWithSummaries.empty();
   // Invoke regular LTO if there was a regular LTO module to start with.
   if (HasRegularLTO)
     if (auto E = runRegularLTO(AddStream))
@@ -623,6 +672,11 @@ Error LTO::run(AddStreamFn AddStream, Na
 }
 
 Error LTO::runRegularLTO(AddStreamFn AddStream) {
+  for (auto &M : RegularLTO.ModsWithSummaries)
+    if (Error Err = linkRegularLTO(std::move(M),
+                                   /*LivenessFromIndex=*/true))
+      return Err;
+
   // Make sure commons have the right size/alignment: we kept the largest from
   // all the prevailing when adding the inputs, and we apply it here.
   const DataLayout &DL = RegularLTO.CombinedModule->getDataLayout();
@@ -920,17 +974,6 @@ ThinBackend lto::createWriteIndexesThinB
   };
 }
 
-static bool IsLiveByGUID(const ModuleSummaryIndex &Index,
-                         GlobalValue::GUID GUID) {
-  auto VI = Index.getValueInfo(GUID);
-  if (!VI)
-    return false;
-  for (auto &I : VI.getSummaryList())
-    if (Index.isGlobalValueLive(I.get()))
-      return true;
-  return false;
-}
-
 Error LTO::runThinLTO(AddStreamFn AddStream, NativeObjectCache Cache,
                       bool HasRegularLTO) {
   if (ThinLTO.ModuleMap.empty())
@@ -979,7 +1022,7 @@ Error LTO::runThinLTO(AddStreamFn AddStr
       auto GUID = GlobalValue::getGUID(
           GlobalValue::dropLLVMManglingEscape(Res.second.IRName));
       // Mark exported unless index-based analysis determined it to be dead.
-      if (IsLiveByGUID(ThinLTO.CombinedIndex, GUID))
+      if (ThinLTO.CombinedIndex.isGUIDLive(GUID))
         ExportedGUIDs.insert(GUID);
     }
 

Modified: llvm/trunk/lib/LTO/LTOModule.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/LTO/LTOModule.cpp?rev=305482&r1=305481&r2=305482&view=diff
==============================================================================
--- llvm/trunk/lib/LTO/LTOModule.cpp (original)
+++ llvm/trunk/lib/LTO/LTOModule.cpp Thu Jun 15 12:26:13 2017
@@ -77,14 +77,12 @@ bool LTOModule::isBitcodeFile(StringRef
 }
 
 bool LTOModule::isThinLTO() {
-  // Right now the detection is only based on the summary presence. We may want
-  // to add a dedicated flag at some point.
-  Expected<bool> Result = hasGlobalValueSummary(MBRef);
+  Expected<BitcodeLTOInfo> Result = getBitcodeLTOInfo(MBRef);
   if (!Result) {
     logAllUnhandledErrors(Result.takeError(), errs(), "");
     return false;
   }
-  return *Result;
+  return Result->IsThinLTO;
 }
 
 bool LTOModule::isBitcodeForTarget(MemoryBuffer *Buffer,

Added: llvm/trunk/test/LTO/Resolution/X86/Inputs/dead-strip-fulllto.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/LTO/Resolution/X86/Inputs/dead-strip-fulllto.ll?rev=305482&view=auto
==============================================================================
--- llvm/trunk/test/LTO/Resolution/X86/Inputs/dead-strip-fulllto.ll (added)
+++ llvm/trunk/test/LTO/Resolution/X86/Inputs/dead-strip-fulllto.ll Thu Jun 15 12:26:13 2017
@@ -0,0 +1,16 @@
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @live1() {
+  call void @live2()
+  ret void
+}
+
+declare void @live2()
+
+define void @dead1() {
+  call void @dead2()
+  ret void
+}
+
+declare void @dead2()

Added: llvm/trunk/test/LTO/Resolution/X86/dead-strip-fulllto.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/LTO/Resolution/X86/dead-strip-fulllto.ll?rev=305482&view=auto
==============================================================================
--- llvm/trunk/test/LTO/Resolution/X86/dead-strip-fulllto.ll (added)
+++ llvm/trunk/test/LTO/Resolution/X86/dead-strip-fulllto.ll Thu Jun 15 12:26:13 2017
@@ -0,0 +1,37 @@
+; RUN: opt -module-summary -o %t %s
+; RUN: opt -module-summary -o %t2 %S/Inputs/dead-strip-fulllto.ll
+; RUN: llvm-lto2 run %t -r %t,main,px -r %t,live1,p -r %t,live2,p -r %t,dead2,p \
+; RUN:               %t2 -r %t2,live1,p -r %t2,live2, -r %t2,dead1,p -r %t2,dead2, \
+; RUN: -save-temps -o %t3
+; RUN: llvm-nm %t3.0 | FileCheck --check-prefix=FULL %s
+; RUN: llvm-nm %t3.1 | FileCheck --check-prefix=THIN %s
+
+; FULL-NOT: dead
+; FULL: U live1
+; FULL: T live2
+; FULL: T main
+
+; THIN-NOT: dead
+; THIN: T live1
+; THIN: U live2
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @main() {
+  call void @live1()
+  ret void
+}
+
+declare void @live1()
+
+define void @live2() {
+  ret void
+}
+
+define void @dead2() {
+  ret void
+}
+
+!0 = !{i32 1, !"ThinLTO", i32 0}
+!llvm.module.flags = !{ !0 }




More information about the llvm-commits mailing list