Index: include/llvm/Bitcode/LLVMBitCodes.h
===================================================================
--- include/llvm/Bitcode/LLVMBitCodes.h
+++ include/llvm/Bitcode/LLVMBitCodes.h
@@ -210,6 +210,10 @@
   FS_COMBINED_PROFILE = 5,
   // COMBINED_GLOBALVAR_INIT_REFS: [modid, linkage, n x valueid]
   FS_COMBINED_GLOBALVAR_INIT_REFS = 6,
+  // ALIAS: [valueid, linkage, valueid]
+  FS_ALIAS = 7,
+  // ALIAS: [modid, linkage, offset]
+  FS_COMBINED_ALIAS = 8,
 };
 
 enum MetadataCodes {
Index: include/llvm/IR/ModuleSummaryIndex.h
===================================================================
--- include/llvm/IR/ModuleSummaryIndex.h
+++ include/llvm/IR/ModuleSummaryIndex.h
@@ -92,7 +92,7 @@
 class GlobalValueSummary {
 public:
   /// \brief Sububclass discriminator (for dyn_cast<> et al.)
-  enum SummaryKind { FunctionKind, GlobalVarKind };
+  enum SummaryKind { AliasKind, FunctionKind, GlobalVarKind };
 
 private:
   /// Kind of summary for use in dyn_cast<> et al.
@@ -168,6 +168,32 @@
   const std::vector<ValueInfo> &refs() const { return RefEdgeList; }
 };
 
+/// \brief Alias summary information.
+class AliasSummary : public GlobalValueSummary {
+  GlobalValueSummary *AliaseeSummary;
+
+public:
+  /// Summary constructors.
+  AliasSummary(GlobalValue::LinkageTypes Linkage)
+      : GlobalValueSummary(AliasKind, Linkage) {}
+
+  /// Check if this is an alias summary.
+  static bool classof(const GlobalValueSummary *GVS) {
+    return GVS->getSummaryKind() == AliasKind;
+  }
+
+  void setAliasee(GlobalValueSummary *Aliasee) { AliaseeSummary = Aliasee; }
+
+  const GlobalValueSummary &getAliasee() const {
+    return const_cast<AliasSummary *>(this)->getAliasee();
+  }
+
+  GlobalValueSummary &getAliasee() {
+    assert(AliaseeSummary && "Unexpected missing aliasee summary");
+    return *AliaseeSummary;
+  }
+};
+
 /// \brief Function summary information to aid decisions and implementation of
 /// importing.
 class FunctionSummary : public GlobalValueSummary {
Index: lib/Bitcode/Reader/BitcodeReader.cpp
===================================================================
--- lib/Bitcode/Reader/BitcodeReader.cpp
+++ lib/Bitcode/Reader/BitcodeReader.cpp
@@ -5836,6 +5836,33 @@
       Info->setSummary(std::move(FS));
       break;
     }
+    // FS_ALIAS: [valueid, linkage, valueid]
+    case bitc::FS_ALIAS: {
+      unsigned ValueID = Record[0];
+      uint64_t RawLinkage = Record[1];
+      unsigned AliaseeID = Record[2];
+      std::unique_ptr<AliasSummary> AS =
+          llvm::make_unique<AliasSummary>(getDecodedLinkage(RawLinkage));
+      // The module path string ref set in the summary must be owned by the
+      // index's module string table. Since we don't have a module path
+      // string table section in the per-module index, we create a single
+      // module path string table entry with an empty (0) ID to take
+      // ownership.
+      AS->setModulePath(
+          TheIndex->addModulePath(Buffer->getBufferIdentifier(), 0)->first());
+
+      GlobalValue::GUID AliaseeGUID = getGUIDFromValueId(AliaseeID);
+      auto *AliaseeInfo = TheIndex->getGlobalValueInfo(AliaseeGUID);
+      if (!AliaseeInfo->summary())
+        return error("Alias expects aliasee summary to be parsed");
+      AS->setAliasee(AliaseeInfo->summary());
+
+      GlobalValue::GUID GUID = getGUIDFromValueId(ValueID);
+      auto *Info = TheIndex->getGlobalValueInfo(GUID);
+      assert(!Info->summary() && "Expected a single summary per VST entry");
+      Info->setSummary(std::move(AS));
+      break;
+    }
     // FS_PERMODULE_GLOBALVAR_INIT_REFS: [valueid, linkage, n x valueid]
     case bitc::FS_PERMODULE_GLOBALVAR_INIT_REFS: {
       unsigned ValueID = Record[0];
@@ -5894,6 +5921,26 @@
       Combined = true;
       break;
     }
+    // FS_COMBINED_ALIAS: [modid, linkage, offset]
+    case bitc::FS_COMBINED_ALIAS: {
+      uint64_t ModuleId = Record[0];
+      uint64_t RawLinkage = Record[1];
+      uint64_t AliaseeSummaryOffset = Record[2];
+      std::unique_ptr<AliasSummary> AS =
+          llvm::make_unique<AliasSummary>(getDecodedLinkage(RawLinkage));
+      AS->setModulePath(ModuleIdMap[ModuleId]);
+
+      auto *AliaseeInfo = getInfoFromSummaryOffset(AliaseeSummaryOffset);
+      if (!AliaseeInfo->summary())
+        return error("Alias expects aliasee summary to be parsed");
+      AS->setAliasee(AliaseeInfo->summary());
+
+      auto *Info = getInfoFromSummaryOffset(CurRecordBit);
+      assert(!Info->summary() && "Expected a single summary per VST entry");
+      Info->setSummary(std::move(AS));
+      Combined = true;
+      break;
+    }
     // FS_COMBINED_GLOBALVAR_INIT_REFS: [modid, linkage, n x valueid]
     case bitc::FS_COMBINED_GLOBALVAR_INIT_REFS: {
       uint64_t ModuleId = Record[0];
Index: lib/Bitcode/Writer/BitcodeWriter.cpp
===================================================================
--- lib/Bitcode/Writer/BitcodeWriter.cpp
+++ lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -2910,6 +2910,14 @@
   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.
@@ -2928,20 +2936,6 @@
         FSCallsAbbrev, FSCallsProfileAbbrev, Stream, F);
   }
 
-  for (const GlobalAlias &A : M->aliases()) {
-    if (!A.getBaseObject())
-      continue;
-    const Function *F = dyn_cast<Function>(A.getBaseObject());
-    if (!F || F->isDeclaration())
-      continue;
-
-    auto *Info = Index.getGlobalValueInfo(A);
-    WritePerModuleFunctionSummaryRecord(
-        NameVals, Info,
-        VE.getValueID(M->getValueSymbolTable().lookup(A.getName())), VE,
-        FSCallsAbbrev, FSCallsProfileAbbrev, Stream, *F);
-  }
-
   // Capture references from GlobalVariable initializers, which are outside
   // of a function scope.
   for (const GlobalVariable &G : M->globals())
@@ -2951,12 +2945,23 @@
       WriteModuleLevelReferences(*GV, Index, VE, NameVals, FSModRefsAbbrev,
                                  Stream);
 
+  for (const GlobalAlias &A : M->aliases()) {
+    auto *Aliasee = A.getBaseObject();
+    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();
 }
 
 /// Emit the combined summary section into the combined index file.
 static void WriteCombinedGlobalValueSummary(
-    const ModuleSummaryIndex &I, BitstreamWriter &Stream,
+    const ModuleSummaryIndex &Index, BitstreamWriter &Stream,
     std::map<GlobalValue::GUID, unsigned> &GUIDToValueIdMap,
     unsigned GlobalValueId) {
   Stream.EnterSubblock(bitc::GLOBALVAL_SUMMARY_BLOCK_ID, 3);
@@ -2994,14 +2999,34 @@
   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));   // valueid
+  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 : I) {
+  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(I.getModuleId(VS->modulePath()));
+        NameVals.push_back(Index.getModuleId(VS->modulePath()));
         NameVals.push_back(getEncodedLinkage(VS->linkage()));
         for (auto &RI : VS->refs()) {
           const auto &VMI = GUIDToValueIdMap.find(RI.getId());
@@ -3021,6 +3046,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,
@@ -3030,7 +3057,7 @@
       }
 
       auto *FS = cast<FunctionSummary>(S);
-      NameVals.push_back(I.getModuleId(FS->modulePath()));
+      NameVals.push_back(Index.getModuleId(FS->modulePath()));
       NameVals.push_back(getEncodedLinkage(FS->linkage()));
       NameVals.push_back(FS->instCount());
       NameVals.push_back(FS->refs().size());
@@ -3072,6 +3099,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);
@@ -3084,6 +3113,25 @@
     }
   }
 
+  for (auto GVI : Aliases) {
+    AliasSummary *AS = cast<AliasSummary>(GVI->summary());
+    NameVals.push_back(Index.getModuleId(AS->modulePath()));
+    NameVals.push_back(getEncodedLinkage(AS->linkage()));
+    auto AliaseeID = SummaryToOffsetMap[&AS->getAliasee()];
+    assert(AliaseeID);
+    NameVals.push_back(AliaseeID);
+
+    // 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();
+    continue;
+  }
+
   Stream.ExitBlock();
 }
 
Index: lib/Transforms/IPO/FunctionImport.cpp
===================================================================
--- lib/Transforms/IPO/FunctionImport.cpp
+++ lib/Transforms/IPO/FunctionImport.cpp
@@ -79,13 +79,16 @@
 ///   number of source modules parsed/linked.
 /// - One that has PGO data attached.
 /// - [insert you fancy metric here]
-static const FunctionSummary *
+static const GlobalValueSummary *
 selectCallee(const GlobalValueInfoList &CalleeInfoList, unsigned Threshold) {
   auto It = llvm::find_if(
       CalleeInfoList, [&](const std::unique_ptr<GlobalValueInfo> &GlobInfo) {
         assert(GlobInfo->summary() &&
                "We should not have a Global Info without summary");
-        auto *Summary = cast<FunctionSummary>(GlobInfo->summary());
+        auto *GVSummary = GlobInfo->summary();
+        if (auto *AS = dyn_cast<AliasSummary>(GVSummary))
+          GVSummary = &AS->getAliasee();
+        auto *Summary = cast<FunctionSummary>(GVSummary);
 
         if (GlobalValue::isWeakAnyLinkage(Summary->linkage()))
           return false;
@@ -98,14 +101,14 @@
   if (It == CalleeInfoList.end())
     return nullptr;
 
-  return cast<FunctionSummary>((*It)->summary());
+  return cast<GlobalValueSummary>((*It)->summary());
 }
 
 /// Return the summary for the function \p GUID that fits the \p Threshold, or
 /// null if there's no match.
-static const FunctionSummary *selectCallee(GlobalValue::GUID GUID,
-                                           unsigned Threshold,
-                                           const ModuleSummaryIndex &Index) {
+static const GlobalValueSummary *selectCallee(GlobalValue::GUID GUID,
+                                              unsigned Threshold,
+                                              const ModuleSummaryIndex &Index) {
   auto CalleeInfoList = Index.findGlobalValueInfoList(GUID);
   if (CalleeInfoList == Index.end()) {
     return nullptr; // This function does not have a summary
@@ -140,7 +143,7 @@
 static void computeImportForFunction(
     StringRef ModulePath, const FunctionSummary &Summary,
     const ModuleSummaryIndex &Index, unsigned Threshold,
-    const std::map<GlobalValue::GUID, FunctionSummary *> &DefinedFunctions,
+    const std::map<GlobalValue::GUID, GlobalValueSummary *> &DefinedFunctions,
     SmallVectorImpl<EdgeInfo> &Worklist,
     FunctionImporter::ImportMapTy &ImportsForModule,
     StringMap<FunctionImporter::ExportSetTy> &ExportLists) {
@@ -158,11 +161,19 @@
       DEBUG(dbgs() << "ignored! No qualifying callee with summary found.\n");
       continue;
     }
-    assert(CalleeSummary->instCount() <= Threshold &&
+    // "Resolve" the summary, traversing alias,
+    const FunctionSummary *ResolvedCalleeSummary;
+    if (isa<AliasSummary>(CalleeSummary))
+      ResolvedCalleeSummary = cast<FunctionSummary>(
+          &cast<AliasSummary>(CalleeSummary)->getAliasee());
+    else
+      ResolvedCalleeSummary = cast<FunctionSummary>(CalleeSummary);
+
+    assert(ResolvedCalleeSummary->instCount() <= Threshold &&
            "selectCallee() didn't honor the threshold");
 
     auto &ProcessedThreshold =
-        ImportsForModule[CalleeSummary->modulePath()][GUID];
+        ImportsForModule[ResolvedCalleeSummary->modulePath()][GUID];
     /// Since the traversal of the call graph is DFS, we can revisit a function
     /// a second time with a higher threshold. In this case, it is added back to
     /// the worklist with the new threshold.
@@ -175,24 +186,24 @@
     ProcessedThreshold = Threshold;
 
     // Make exports in the source module.
-    auto ExportModulePath = CalleeSummary->modulePath();
+    auto ExportModulePath = ResolvedCalleeSummary->modulePath();
     auto ExportList = ExportLists[ExportModulePath];
     ExportList.insert(GUID);
     // Mark all functions and globals referenced by this function as exported to
     // the outside if they are defined in the same source module.
-    for (auto &Edge : CalleeSummary->calls()) {
+    for (auto &Edge : ResolvedCalleeSummary->calls()) {
       auto CalleeGUID = Edge.first.getId();
       if (isGlobalExported(Index, ExportModulePath, CalleeGUID))
         ExportList.insert(CalleeGUID);
     }
-    for (auto &Ref : CalleeSummary->refs()) {
+    for (auto &Ref : ResolvedCalleeSummary->refs()) {
       auto GUID = Ref.getId();
       if (isGlobalExported(Index, ExportModulePath, GUID))
         ExportList.insert(GUID);
     }
 
     // Insert the newly imported function to the worklist.
-    Worklist.push_back(std::make_pair(CalleeSummary, Threshold));
+    Worklist.push_back(std::make_pair(ResolvedCalleeSummary, Threshold));
   }
 }
 
@@ -201,7 +212,7 @@
 /// another module (that may require promotion).
 static void ComputeImportForModule(
     StringRef ModulePath,
-    const std::map<GlobalValue::GUID, FunctionSummary *> &DefinedFunctions,
+    const std::map<GlobalValue::GUID, GlobalValueSummary *> &DefinedFunctions,
     const ModuleSummaryIndex &Index,
     FunctionImporter::ImportMapTy &ImportsForModule,
     StringMap<FunctionImporter::ExportSetTy> &ExportLists) {
@@ -213,8 +224,11 @@
   // module
   for (auto &FuncInfo : DefinedFunctions) {
     auto *Summary = FuncInfo.second;
+    if (auto *AS = dyn_cast<AliasSummary>(Summary))
+      Summary = &AS->getAliasee();
+    auto *FuncSummary = cast<FunctionSummary>(Summary);
     DEBUG(dbgs() << "Initalize import for " << FuncInfo.first << "\n");
-    computeImportForFunction(ModulePath, *Summary, Index, ImportInstrLimit,
+    computeImportForFunction(ModulePath, *FuncSummary, Index, ImportInstrLimit,
                              DefinedFunctions, Worklist, ImportsForModule,
                              ExportLists);
   }
@@ -245,16 +259,20 @@
 
   // Collect for each module the list of function it defines.
   // GUID -> Summary
-  StringMap<std::map<GlobalValue::GUID, FunctionSummary *>>
+  StringMap<std::map<GlobalValue::GUID, GlobalValueSummary *>>
       Module2FunctionInfoMap(ModuleCount);
 
   for (auto &GlobalList : Index) {
     auto GUID = GlobalList.first;
     for (auto &GlobInfo : GlobalList.second) {
-      auto *Summary = dyn_cast_or_null<FunctionSummary>(GlobInfo->summary());
-      if (!Summary)
+      auto *Summary = GlobInfo->summary();
+      if (isa<GlobalVarSummary>(Summary))
         /// Ignore global variable, focus on functions
         continue;
+      if (auto *AS = dyn_cast<AliasSummary>(Summary))
+        if (isa<GlobalVarSummary>(&AS->getAliasee()))
+          /// Ignore alias to global variable, focus on functions
+          continue;
       DEBUG(dbgs() << "Adding definition: Module '" << Summary->modulePath()
                    << "' defines '" << GUID << "'\n");
       Module2FunctionInfoMap[Summary->modulePath()][GUID] = Summary;
@@ -333,7 +351,7 @@
         GlobalsToImport.insert(&GV);
       }
     }
-    for (auto &GV : SrcModule->aliases()) {
+    for (auto &GV : SrcModule->globals()) {
       if (!GV.hasName())
         continue;
       auto GUID = GV.getGUID();
@@ -342,18 +360,11 @@
                    << GV.getName() << " from " << SrcModule->getSourceFileName()
                    << "\n");
       if (Import) {
-        // Alias can't point to "available_externally". However when we import
-        // linkOnceODR the linkage does not change. So we import the alias
-        // and aliasee only in this case.
-        const GlobalObject *GO = GV.getBaseObject();
-        if (!GO->hasLinkOnceODRLinkage())
-          continue;
         GV.materialize();
         GlobalsToImport.insert(&GV);
-        GlobalsToImport.insert(GO);
       }
     }
-    for (auto &GV : SrcModule->globals()) {
+    for (auto &GV : SrcModule->aliases()) {
       if (!GV.hasName())
         continue;
       auto GUID = GV.getGUID();
@@ -362,6 +373,17 @@
                    << GV.getName() << " from " << SrcModule->getSourceFileName()
                    << "\n");
       if (Import) {
+        GlobalObject *GO = GV.getBaseObject();
+        if (!GO->hasLinkOnceODRLinkage())
+          continue;
+#ifndef NDEBUG
+        if (!GlobalsToImport.count(GO))
+          DEBUG(dbgs() << " alias triggers importing aliasee " << GO->getGUID()
+                       << " " << GO->getName() << " from "
+                       << SrcModule->getSourceFileName() << "\n");
+#endif
+        GO->materialize();
+        GlobalsToImport.insert(GO);
         GV.materialize();
         GlobalsToImport.insert(&GV);
       }
@@ -439,9 +461,7 @@
   static char ID;
 
   /// Specify pass name for debug output
-  const char *getPassName() const override {
-    return "Function Importing";
-  }
+  const char *getPassName() const override { return "Function Importing"; }
 
   explicit FunctionImportPass(const ModuleSummaryIndex *Index = nullptr)
       : ModulePass(ID), Index(Index) {}
Index: test/Bitcode/Inputs/thinlto-alias.ll
===================================================================
--- /dev/null
+++ test/Bitcode/Inputs/thinlto-alias.ll
@@ -0,0 +1,13 @@
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+
+
+@analias = alias void (...), bitcast (void ()* @aliasee to void (...)*)
+
+; Function Attrs: nounwind uwtable
+define void @aliasee() #0 {
+entry:
+    ret void
+}
+
Index: test/Bitcode/thinlto-alias.ll
===================================================================
--- /dev/null
+++ test/Bitcode/thinlto-alias.ll
@@ -0,0 +1,45 @@
+; Test to check the callgraph in summary
+; RUN: llvm-as -module-summary %s -o %t.o
+; RUN: llvm-bcanalyzer -dump %t.o | FileCheck %s
+; RUN: llvm-as -module-summary %p/Inputs/thinlto-alias.ll -o %t2.o
+; RUN: llvm-lto -thinlto -o %t3 %t.o %t2.o
+; RUN: llvm-bcanalyzer -dump %t3.thinlto.bc | FileCheck %s --check-prefix=COMBINED
+
+; CHECK:       <GLOBALVAL_SUMMARY_BLOCK
+; See if the call to func is registered, using the expected callsite count
+; and value id matching the subsequent value symbol table.
+; CHECK-NEXT:    <PERMODULE {{.*}} op4=[[FUNCID:[0-9]+]] op5=1/>
+; CHECK-NEXT:  </GLOBALVAL_SUMMARY_BLOCK>
+; CHECK-NEXT:  <VALUE_SYMTAB
+; CHECK-NEXT:    <FNENTRY {{.*}} record string = 'main'
+; External function analias should have entry with value id FUNCID
+; CHECK-NEXT:    <ENTRY {{.*}} op0=[[FUNCID]] {{.*}} record string = 'analias'
+; CHECK-NEXT:  </VALUE_SYMTAB>
+
+; COMBINED:       <GLOBALVAL_SUMMARY_BLOCK
+; See if the call to analias is registered, using the expected callsite count
+; and value id matching the subsequent value symbol table.
+; COMBINED-NEXT:    <COMBINED {{.*}} op4=[[ALIASID:[0-9]+]] op5=1/>
+; Followed by the alias and aliasee
+; COMBINED-NEXT:    <COMBINED {{.*}}
+; COMBINED-NEXT:    <COMBINED_ALIAS  {{.*}} op2=[[ALIASEEOFFSET:[0-9]+]]
+; COMBINED-NEXT:  </GLOBALVAL_SUMMARY_BLOCK
+; COMBINED-NEXT:  <VALUE_SYMTAB
+; Entry for function func should have entry with value id ALIASID
+; COMBINED-NEXT:    <COMBINED_GVDEFENTRY {{.*}} op0=[[ALIASID]] {{.*}} op2=-5751648690987223394/>
+; COMBINED-NEXT:    <COMBINED_GVDEFENTRY
+; COMBINED-NEXT:    <COMBINED_GVDEFENTRY  {{.*}} op1=[[ALIASEEOFFSET]] op2=-1039159065113703048/>
+; COMBINED-NEXT:  </VALUE_SYMTAB>
+
+; ModuleID = 'thinlto-function-summary-callgraph.ll'
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; Function Attrs: nounwind uwtable
+define i32 @main() {
+entry:
+    call void (...) @analias()
+    ret i32 0
+}
+
+declare void @analias(...)
Index: test/Bitcode/thinlto-function-summary.ll
===================================================================
--- test/Bitcode/thinlto-function-summary.ll
+++ test/Bitcode/thinlto-function-summary.ll
@@ -7,7 +7,7 @@
 ; BC: <GLOBALVAL_SUMMARY_BLOCK
 ; BC-NEXT: <PERMODULE {{.*}} op0=1 op1=0
 ; BC-NEXT: <PERMODULE {{.*}} op0=2 op1=0
-; BC-NEXT: <PERMODULE {{.*}} op0=4 op1=3
+; BC-NEXT: <ALIAS {{.*}} op0=4 op1=0 op2=3
 ; BC-NEXT: </GLOBALVAL_SUMMARY_BLOCK
 ; BC-NEXT: <VALUE_SYMTAB
 ; BC-NEXT: <FNENTRY {{.*}} op0=1 {{.*}}> record string = 'foo'
Index: tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp
===================================================================
--- tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp
+++ tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp
@@ -308,6 +308,8 @@
       STRINGIFY_CODE(FS, COMBINED)
       STRINGIFY_CODE(FS, COMBINED_PROFILE)
       STRINGIFY_CODE(FS, COMBINED_GLOBALVAR_INIT_REFS)
+      STRINGIFY_CODE(FS, ALIAS)
+      STRINGIFY_CODE(FS, COMBINED_ALIAS)
     }
   case bitc::METADATA_ATTACHMENT_ID:
     switch(CodeID) {