ThinLTO: Make aliases explicit in the summary

To be able to work accurately on the reference graph when taking
decision about internalizing, promoting, renaming, etc. We need
to have the alias information explicit.

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

From: Mehdi Amini <mehdi.amini@apple.com>
llvm-svn: 266517
diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
index 0d10282..45f5da8 100644
--- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -2925,16 +2925,24 @@
   Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));
   unsigned FSModRefsAbbrev = Stream.EmitAbbrev(Abbv);
 
+  // Abbrev for FS_ALIAS.
+  Abbv = new BitCodeAbbrev();
+  Abbv->Add(BitCodeAbbrevOp(bitc::FS_ALIAS));
+  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));   // valueid
+  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 5)); // linkage
+  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));   // valueid
+  unsigned FSAliasAbbrev = Stream.EmitAbbrev(Abbv);
+
   SmallVector<uint64_t, 64> NameVals;
   // Iterate over the list of functions instead of the Index to
   // ensure the ordering is stable.
   for (const Function &F : *M) {
     if (F.isDeclaration())
       continue;
-    // Skip anonymous functions. We will emit a function summary for
-    // any aliases below.
+    // Summary emission does not support anonymous functions, they have to
+    // renamed using the anonymous function renaming pass.
     if (!F.hasName())
-      continue;
+      report_fatal_error("Unexpected anonymous function when writing summary");
 
     auto *Info = Index.getGlobalValueInfo(F);
     WritePerModuleFunctionSummaryRecord(
@@ -2948,6 +2956,20 @@
   for (const GlobalVariable &G : M->globals())
     WriteModuleLevelReferences(G, Index, VE, NameVals, FSModRefsAbbrev, Stream);
 
+  for (const GlobalAlias &A : M->aliases()) {
+    auto *Aliasee = A.getBaseObject();
+    if (!Aliasee->hasName())
+      // Nameless function don't have an entry in the summary, skip it.
+      continue;
+    auto AliasId = VE.getValueID(&A);
+    auto AliaseeId = VE.getValueID(Aliasee);
+    NameVals.push_back(AliasId);
+    NameVals.push_back(getEncodedLinkage(A.getLinkage()));
+    NameVals.push_back(AliaseeId);
+    Stream.EmitRecord(bitc::FS_ALIAS, NameVals, FSAliasAbbrev);
+    NameVals.clear();
+  }
+
   Stream.ExitBlock();
 }
 
@@ -2991,11 +3013,31 @@
   Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));
   unsigned FSModRefsAbbrev = Stream.EmitAbbrev(Abbv);
 
+  // Abbrev for FS_COMBINED_ALIAS.
+  Abbv = new BitCodeAbbrev();
+  Abbv->Add(BitCodeAbbrevOp(bitc::FS_COMBINED_ALIAS));
+  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));   // modid
+  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 5)); // linkage
+  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));   // offset
+  unsigned FSAliasAbbrev = Stream.EmitAbbrev(Abbv);
+
+  // The aliases are emitted as a post-pass, and will point to the summary
+  // offset id of the aliasee. For this purpose we need to be able to get back
+  // from the summary to the offset
+  SmallVector<GlobalValueInfo *, 64> Aliases;
+  DenseMap<const GlobalValueSummary *, uint64_t> SummaryToOffsetMap;
+
   SmallVector<uint64_t, 64> NameVals;
   for (const auto &FII : Index) {
     for (auto &FI : FII.second) {
       GlobalValueSummary *S = FI->summary();
       assert(S);
+      if (isa<AliasSummary>(S)) {
+        // Will process aliases as a post-pass because the reader wants all
+        // global to be loaded first.
+        Aliases.push_back(FI.get());
+        continue;
+      }
 
       if (auto *VS = dyn_cast<GlobalVarSummary>(S)) {
         NameVals.push_back(Index.getModuleId(VS->modulePath()));
@@ -3018,6 +3060,8 @@
         // reader will invoke readRecord after the abbrev id read.
         FI->setBitcodeIndex(Stream.GetCurrentBitNo() +
                             Stream.GetAbbrevIDWidth());
+        // Store temporarily the offset in the map for a possible alias.
+        SummaryToOffsetMap[S] = FI->bitcodeIndex();
 
         // Emit the finished record.
         Stream.EmitRecord(bitc::FS_COMBINED_GLOBALVAR_INIT_REFS, NameVals,
@@ -3069,6 +3113,8 @@
       // in the VST entry. Add the current code size since the
       // reader will invoke readRecord after the abbrev id read.
       FI->setBitcodeIndex(Stream.GetCurrentBitNo() + Stream.GetAbbrevIDWidth());
+      // Store temporarily the offset in the map for a possible alias.
+      SummaryToOffsetMap[S] = FI->bitcodeIndex();
 
       unsigned FSAbbrev =
           (HasProfileData ? FSCallsProfileAbbrev : FSCallsAbbrev);
@@ -3081,6 +3127,24 @@
     }
   }
 
+  for (auto GVI : Aliases) {
+    AliasSummary *AS = cast<AliasSummary>(GVI->summary());
+    NameVals.push_back(Index.getModuleId(AS->modulePath()));
+    NameVals.push_back(getEncodedLinkage(AS->linkage()));
+    auto AliaseeOffset = SummaryToOffsetMap[&AS->getAliasee()];
+    assert(AliaseeOffset);
+    NameVals.push_back(AliaseeOffset);
+
+    // Record the starting offset of this summary entry for use
+    // in the VST entry. Add the current code size since the
+    // reader will invoke readRecord after the abbrev id read.
+    GVI->setBitcodeIndex(Stream.GetCurrentBitNo() + Stream.GetAbbrevIDWidth());
+
+    // Emit the finished record.
+    Stream.EmitRecord(bitc::FS_COMBINED_ALIAS, NameVals, FSAliasAbbrev);
+    NameVals.clear();
+  }
+
   Stream.ExitBlock();
 }