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,
+ // COMBINED_ALIAS: [modid, linkage, offset]
+ FS_COMBINED_ALIAS = 8,
};
enum MetadataCodes {
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.
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 {
/// (GUID -> Summary).
void collectDefinedFunctionsForModule(
StringRef ModulePath,
- std::map<GlobalValue::GUID, FunctionSummary *> &FunctionInfoMap) const;
+ std::map<GlobalValue::GUID, GlobalValueSummary *> &FunctionInfoMap) const;
};
} // End llvm namespace
Info->setSummary(std::move(FS));
break;
}
+ // FS_ALIAS: [valueid, linkage, valueid]
+ // Aliases must be emitted (and parsed) after all FS_PERMODULE entries, as
+ // they expect all aliasee summaries to be available.
+ 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];
Combined = true;
break;
}
+ // FS_COMBINED_ALIAS: [modid, linkage, offset]
+ // Aliases must be emitted (and parsed) after all FS_PERMODULE entries, as
+ // they expect all aliasee summaries to be available.
+ 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];
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.
+ // We shouldn't have any anonymous functions as they are not supported in
+ // ThinLTO and should be renamed.
if (!F.hasName())
- continue;
+ report_fatal_error("Unexpected anonymous function when writing summary");
auto *Info = Index.getGlobalValueInfo(F);
WritePerModuleFunctionSummaryRecord(
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();
}
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()));
// 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,
// 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);
}
}
+ 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();
}
// (GUID -> Summary).
void ModuleSummaryIndex::collectDefinedFunctionsForModule(
StringRef ModulePath,
- std::map<GlobalValue::GUID, FunctionSummary *> &FunctionInfoMap) const {
+ std::map<GlobalValue::GUID, GlobalValueSummary *> &FunctionInfoMap) const {
for (auto &GlobalList : *this) {
auto GUID = GlobalList.first;
for (auto &GlobInfo : GlobalList.second) {
/// 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;
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
static void computeImportForFunction(
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 = nullptr) {
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];
+ auto ExportModulePath = ResolvedCalleeSummary->modulePath();
+ auto &ProcessedThreshold = ImportsForModule[ExportModulePath][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.
ProcessedThreshold = Threshold;
// Make exports in the source module.
- auto ExportModulePath = CalleeSummary->modulePath();
if (ExportLists) {
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.getGUID();
if (isGlobalExported(Index, ExportModulePath, CalleeGUID))
ExportList.insert(CalleeGUID);
}
- for (auto &Ref : CalleeSummary->refs()) {
+ for (auto &Ref : ResolvedCalleeSummary->refs()) {
auto GUID = Ref.getGUID();
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));
}
}
/// as well as the list of "exports", i.e. the list of symbols referenced from
/// another module (that may require promotion).
static void ComputeImportForModule(
- const std::map<GlobalValue::GUID, FunctionSummary *> &DefinedFunctions,
+ const std::map<GlobalValue::GUID, GlobalValueSummary *> &DefinedFunctions,
const ModuleSummaryIndex &Index,
FunctionImporter::ImportMapTy &ImportsForModule,
StringMap<FunctionImporter::ExportSetTy> *ExportLists = nullptr) {
// 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(*Summary, Index, ImportInstrLimit,
+ computeImportForFunction(*FuncSummary, Index, ImportInstrLimit,
DefinedFunctions, Worklist, ImportsForModule,
ExportLists);
}
// 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;
// Collect the list of functions this module defines.
// GUID -> Summary
- std::map<GlobalValue::GUID, FunctionSummary *> FunctionInfoMap;
+ std::map<GlobalValue::GUID, GlobalValueSummary *> FunctionInfoMap;
Index.collectDefinedFunctionsForModule(ModulePath, FunctionInfoMap);
// Compute the import list for this module.
GlobalsToImport.insert(&GV);
}
}
- for (auto &GV : SrcModule->aliases()) {
+ for (auto &GV : SrcModule->globals()) {
if (!GV.hasName())
continue;
auto GUID = GV.getGUID();
<< 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();
<< 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.
+ 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);
}
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) {}
--- /dev/null
+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
+}
+
--- /dev/null
+; Test to check the callgraph in summary
+; RUN: opt -module-summary %s -o %t.o
+; RUN: llvm-bcanalyzer -dump %t.o | FileCheck %s
+; RUN: opt -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(...)
-; RUN: opt -module-summary < %s | llvm-bcanalyzer -dump | FileCheck %s -check-prefix=BC
+; RUN: opt -name-anon-functions -module-summary < %s | llvm-bcanalyzer -dump | FileCheck %s -check-prefix=BC
; Check for summary block/records.
; Check the value ids in the summary entries against the
; BC: <GLOBALVAL_SUMMARY_BLOCK
; BC-NEXT: <PERMODULE {{.*}} op0=1 op1=0
; BC-NEXT: <PERMODULE {{.*}} op0=2 op1=0
-; BC-NEXT: </GLOBALVAL_SUMMARY_BLOCK
+; BC: </GLOBALVAL_SUMMARY_BLOCK
; BC-NEXT: <VALUE_SYMTAB
-; BC-NEXT: <FNENTRY {{.*}} op0=1 {{.*}}> record string = 'foo'
+; BC: <FNENTRY {{.*}} op0=1 {{.*}}> record string = 'foo'
; BC-NEXT: <FNENTRY {{.*}} op0=2 {{.*}}> record string = 'bar'
; BC-NEXT: <FNENTRY {{.*}} op0=4 {{.*}}> record string = 'f'
-; RUN: opt -module-summary < %s | llvm-dis | FileCheck %s
+; RUN: opt -name-anon-functions -module-summary < %s | llvm-dis | FileCheck %s
; Check that this round-trips correctly.
; ModuleID = '<stdin>'
; INSTLIM5-DAG: declare hidden void @funcwithpersonality.llvm.{{.*}}()
; INSTLIMDEF-DAG: Import globalfunc2
-; INSTLIMDEF-DAG: 9 function-import - Number of functions imported
+; INSTLIMDEF-DAG: 11 function-import - Number of functions imported
; The actual GUID values will depend on path to test.
; GUID-DAG: GUID {{.*}} is weakalias
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) {