1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-18 18:42:46 +02:00

[ThinLTO] Add FunctionAttrs to ThinLTO index

Adds function attributes to index: ReadNone, ReadOnly, NoRecurse, NoAlias. This attributes will be used for future ThinLTO optimizations that will propagate function attributes across modules.

llvm-svn: 310061
This commit is contained in:
Charles Saternos 2017-08-04 16:00:58 +00:00
parent 0e224c7256
commit 81929b6bb0
14 changed files with 142 additions and 44 deletions

View File

@ -25,6 +25,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/Module.h"
#include "llvm/Transforms/IPO/FunctionAttrs.h"
#include <algorithm>
#include <array>
#include <cassert>
@ -287,11 +288,24 @@ public:
std::vector<uint64_t> Args;
};
/// Function attribute flags. Used to track if a function accesses memory,
/// recurses or aliases.
struct FFlags {
unsigned ReadNone : 1;
unsigned ReadOnly : 1;
unsigned NoRecurse : 1;
unsigned ReturnDoesNotAlias : 1;
};
private:
/// Number of instructions (ignoring debug instructions, e.g.) computed
/// during the initial compile step when the summary index is first built.
unsigned InstCount;
/// Function attribute flags. Used to track if a function accesses memory,
/// recurses or aliases.
FFlags FunFlags;
/// List of <CalleeValueInfo, CalleeInfo> call edge pairs from this function.
std::vector<EdgeTy> CallGraphEdgeList;
@ -317,15 +331,16 @@ private:
std::unique_ptr<TypeIdInfo> TIdInfo;
public:
FunctionSummary(GVFlags Flags, unsigned NumInsts, std::vector<ValueInfo> Refs,
std::vector<EdgeTy> CGEdges,
FunctionSummary(GVFlags Flags, unsigned NumInsts, FFlags FunFlags,
std::vector<ValueInfo> Refs, std::vector<EdgeTy> CGEdges,
std::vector<GlobalValue::GUID> TypeTests,
std::vector<VFuncId> TypeTestAssumeVCalls,
std::vector<VFuncId> TypeCheckedLoadVCalls,
std::vector<ConstVCall> TypeTestAssumeConstVCalls,
std::vector<ConstVCall> TypeCheckedLoadConstVCalls)
: GlobalValueSummary(FunctionKind, Flags, std::move(Refs)),
InstCount(NumInsts), CallGraphEdgeList(std::move(CGEdges)) {
InstCount(NumInsts), FunFlags(FunFlags),
CallGraphEdgeList(std::move(CGEdges)) {
if (!TypeTests.empty() || !TypeTestAssumeVCalls.empty() ||
!TypeCheckedLoadVCalls.empty() || !TypeTestAssumeConstVCalls.empty() ||
!TypeCheckedLoadConstVCalls.empty())
@ -341,6 +356,9 @@ public:
return GVS->getSummaryKind() == FunctionKind;
}
/// Get function attribute flags.
FFlags &fflags() { return FunFlags; }
/// Get the instruction count recorded for this function.
unsigned instCount() const { return InstCount; }

View File

@ -206,8 +206,9 @@ template <> struct CustomMappingTraits<GlobalValueSummaryMapTy> {
GlobalValueSummary::GVFlags(
static_cast<GlobalValue::LinkageTypes>(FSum.Linkage),
FSum.NotEligibleToImport, FSum.Live),
0, ArrayRef<ValueInfo>{}, ArrayRef<FunctionSummary::EdgeTy>{},
std::move(FSum.TypeTests), std::move(FSum.TypeTestAssumeVCalls),
0, FunctionSummary::FFlags{}, ArrayRef<ValueInfo>{},
ArrayRef<FunctionSummary::EdgeTy>{}, std::move(FSum.TypeTests),
std::move(FSum.TypeTestAssumeVCalls),
std::move(FSum.TypeCheckedLoadVCalls),
std::move(FSum.TypeTestAssumeConstVCalls),
std::move(FSum.TypeCheckedLoadConstVCalls)));

View File

@ -276,10 +276,16 @@ computeFunctionSummary(ModuleSummaryIndex &Index, const Module &M,
F.isVarArg();
GlobalValueSummary::GVFlags Flags(F.getLinkage(), NotEligibleForImport,
/* Live = */ false);
FunctionSummary::FFlags FunFlags{
F.hasFnAttribute(Attribute::ReadNone),
F.hasFnAttribute(Attribute::ReadOnly),
F.hasFnAttribute(Attribute::NoRecurse),
F.returnDoesNotAlias(),
};
auto FuncSummary = llvm::make_unique<FunctionSummary>(
Flags, NumInsts, RefEdges.takeVector(), CallGraphEdges.takeVector(),
TypeTests.takeVector(), TypeTestAssumeVCalls.takeVector(),
TypeCheckedLoadVCalls.takeVector(),
Flags, NumInsts, FunFlags, RefEdges.takeVector(),
CallGraphEdges.takeVector(), TypeTests.takeVector(),
TypeTestAssumeVCalls.takeVector(), TypeCheckedLoadVCalls.takeVector(),
TypeTestAssumeConstVCalls.takeVector(),
TypeCheckedLoadConstVCalls.takeVector());
if (NonRenamableLocal)
@ -427,11 +433,16 @@ ModuleSummaryIndex llvm::buildModuleSummaryIndex(
/* Live = */ true);
CantBePromoted.insert(GlobalValue::getGUID(Name));
// Create the appropriate summary type.
if (isa<Function>(GV)) {
if (Function *F = dyn_cast<Function>(GV)) {
std::unique_ptr<FunctionSummary> Summary =
llvm::make_unique<FunctionSummary>(
GVFlags, 0, ArrayRef<ValueInfo>{},
ArrayRef<FunctionSummary::EdgeTy>{},
GVFlags, 0,
FunctionSummary::FFlags{
F->hasFnAttribute(Attribute::ReadNone),
F->hasFnAttribute(Attribute::ReadOnly),
F->hasFnAttribute(Attribute::NoRecurse),
F->returnDoesNotAlias()},
ArrayRef<ValueInfo>{}, ArrayRef<FunctionSummary::EdgeTy>{},
ArrayRef<GlobalValue::GUID>{},
ArrayRef<FunctionSummary::VFuncId>{},
ArrayRef<FunctionSummary::VFuncId>{},

View File

@ -860,6 +860,15 @@ static GlobalValue::LinkageTypes getDecodedLinkage(unsigned Val) {
}
}
static FunctionSummary::FFlags getDecodedFFlags(uint64_t RawFlags) {
FunctionSummary::FFlags Flags;
Flags.ReadNone = RawFlags & 0x1;
Flags.ReadOnly = (RawFlags >> 1) & 0x1;
Flags.NoRecurse = (RawFlags >> 2) & 0x1;
Flags.ReturnDoesNotAlias = (RawFlags >> 3) & 0x1;
return Flags;
}
/// Decode the flags for GlobalValue in the summary.
static GlobalValueSummary::GVFlags getDecodedGVSummaryFlags(uint64_t RawFlags,
uint64_t Version) {
@ -5036,9 +5045,9 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(unsigned ID) {
}
const uint64_t Version = Record[0];
const bool IsOldProfileFormat = Version == 1;
if (Version < 1 || Version > 3)
if (Version < 1 || Version > 4)
return error("Invalid summary version " + Twine(Version) +
", 1, 2 or 3 expected");
", 1, 2, 3 or 4 expected");
Record.clear();
// Keep around the last seen summary to be used when we see an optional
@ -5088,9 +5097,9 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(unsigned ID) {
std::make_pair(TheIndex.getOrInsertValueInfo(RefGUID), RefGUID);
break;
}
// FS_PERMODULE: [valueid, flags, instcount, numrefs, numrefs x valueid,
// n x (valueid)]
// FS_PERMODULE_PROFILE: [valueid, flags, instcount, numrefs,
// FS_PERMODULE: [valueid, flags, instcount, fflags, numrefs,
// numrefs x valueid, n x (valueid)]
// FS_PERMODULE_PROFILE: [valueid, flags, instcount, fflags, numrefs,
// numrefs x valueid,
// n x (valueid, hotness)]
case bitc::FS_PERMODULE:
@ -5098,14 +5107,21 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(unsigned ID) {
unsigned ValueID = Record[0];
uint64_t RawFlags = Record[1];
unsigned InstCount = Record[2];
uint64_t RawFunFlags = 0;
unsigned NumRefs = Record[3];
int RefListStartIndex = 4;
if (Version >= 4) {
RawFunFlags = Record[3];
NumRefs = Record[4];
RefListStartIndex = 5;
}
auto Flags = getDecodedGVSummaryFlags(RawFlags, Version);
// 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.
static int RefListStartIndex = 4;
int CallGraphEdgeStartIndex = RefListStartIndex + NumRefs;
assert(Record.size() >= RefListStartIndex + NumRefs &&
"Record size inconsistent with number of references");
@ -5116,8 +5132,9 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(unsigned ID) {
ArrayRef<uint64_t>(Record).slice(CallGraphEdgeStartIndex),
IsOldProfileFormat, HasProfile);
auto FS = llvm::make_unique<FunctionSummary>(
Flags, InstCount, std::move(Refs), std::move(Calls),
std::move(PendingTypeTests), std::move(PendingTypeTestAssumeVCalls),
Flags, InstCount, getDecodedFFlags(RawFunFlags), std::move(Refs),
std::move(Calls), std::move(PendingTypeTests),
std::move(PendingTypeTestAssumeVCalls),
std::move(PendingTypeCheckedLoadVCalls),
std::move(PendingTypeTestAssumeConstVCalls),
std::move(PendingTypeCheckedLoadConstVCalls));
@ -5176,9 +5193,9 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(unsigned ID) {
TheIndex.addGlobalValueSummary(GUID.first, std::move(FS));
break;
}
// FS_COMBINED: [valueid, modid, flags, instcount, numrefs,
// FS_COMBINED: [valueid, modid, flags, instcount, fflags, numrefs,
// numrefs x valueid, n x (valueid)]
// FS_COMBINED_PROFILE: [valueid, modid, flags, instcount, numrefs,
// FS_COMBINED_PROFILE: [valueid, modid, flags, instcount, fflags, numrefs,
// numrefs x valueid, n x (valueid, hotness)]
case bitc::FS_COMBINED:
case bitc::FS_COMBINED_PROFILE: {
@ -5186,9 +5203,17 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(unsigned ID) {
uint64_t ModuleId = Record[1];
uint64_t RawFlags = Record[2];
unsigned InstCount = Record[3];
uint64_t RawFunFlags = 0;
unsigned NumRefs = Record[4];
int RefListStartIndex = 5;
if (Version >= 4) {
RawFunFlags = Record[4];
NumRefs = Record[5];
RefListStartIndex = 6;
}
auto Flags = getDecodedGVSummaryFlags(RawFlags, Version);
static int RefListStartIndex = 5;
int CallGraphEdgeStartIndex = RefListStartIndex + NumRefs;
assert(Record.size() >= RefListStartIndex + NumRefs &&
"Record size inconsistent with number of references");
@ -5200,8 +5225,9 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(unsigned ID) {
IsOldProfileFormat, HasProfile);
ValueInfo VI = getValueInfoFromValueId(ValueID).first;
auto FS = llvm::make_unique<FunctionSummary>(
Flags, InstCount, std::move(Refs), std::move(Edges),
std::move(PendingTypeTests), std::move(PendingTypeTestAssumeVCalls),
Flags, InstCount, getDecodedFFlags(RawFunFlags), std::move(Refs),
std::move(Edges), std::move(PendingTypeTests),
std::move(PendingTypeTestAssumeVCalls),
std::move(PendingTypeCheckedLoadVCalls),
std::move(PendingTypeTestAssumeConstVCalls),
std::move(PendingTypeCheckedLoadConstVCalls));

View File

@ -895,6 +895,15 @@ static unsigned getEncodedLinkage(const GlobalValue &GV) {
return getEncodedLinkage(GV.getLinkage());
}
static uint64_t getEncodedFFlags(FunctionSummary::FFlags Flags) {
uint64_t RawFlags = 0;
RawFlags |= Flags.ReadNone;
RawFlags |= (Flags.ReadOnly << 1);
RawFlags |= (Flags.NoRecurse << 2);
RawFlags |= (Flags.ReturnDoesNotAlias << 3);
return RawFlags;
}
// Decode the flags for GlobalValue in the summary
static uint64_t getEncodedGVSummaryFlags(GlobalValueSummary::GVFlags Flags) {
uint64_t RawFlags = 0;
@ -1703,7 +1712,7 @@ void ModuleBitcodeWriter::writeDIGlobalVariableExpression(
Record.push_back(N->isDistinct());
Record.push_back(VE.getMetadataOrNullID(N->getVariable()));
Record.push_back(VE.getMetadataOrNullID(N->getExpression()));
Stream.EmitRecord(bitc::METADATA_GLOBAL_VAR_EXPR, Record, Abbrev);
Record.clear();
}
@ -3293,6 +3302,7 @@ void ModuleBitcodeWriterBase::writePerModuleFunctionSummaryRecord(
NameVals.push_back(getEncodedGVSummaryFlags(FS->flags()));
NameVals.push_back(FS->instCount());
NameVals.push_back(getEncodedFFlags(FS->fflags()));
NameVals.push_back(FS->refs().size());
for (auto &RI : FS->refs())
@ -3346,7 +3356,7 @@ void ModuleBitcodeWriterBase::writeModuleLevelReferences(
// Current version for the summary.
// This is bumped whenever we introduce changes in the way some record are
// interpreted, like flags for instance.
static const uint64_t INDEX_VERSION = 3;
static const uint64_t INDEX_VERSION = 4;
/// Emit the per-module summary section alongside the rest of
/// the module's bitcode.
@ -3379,6 +3389,7 @@ void ModuleBitcodeWriterBase::writePerModuleGlobalValueSummary() {
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // valueid
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // flags
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // instcount
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 4)); // fflags
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 4)); // numrefs
// numrefs x valueid, n x (valueid)
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
@ -3391,6 +3402,7 @@ void ModuleBitcodeWriterBase::writePerModuleGlobalValueSummary() {
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // valueid
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // flags
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // instcount
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 4)); // fflags
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 4)); // numrefs
// numrefs x valueid, n x (valueid, hotness)
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
@ -3476,6 +3488,7 @@ void IndexBitcodeWriter::writeCombinedGlobalValueSummary() {
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // modid
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // flags
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // instcount
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 4)); // fflags
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 4)); // numrefs
// numrefs x valueid, n x (valueid)
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
@ -3489,6 +3502,7 @@ void IndexBitcodeWriter::writeCombinedGlobalValueSummary() {
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // modid
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // flags
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // instcount
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 4)); // fflags
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 4)); // numrefs
// numrefs x valueid, n x (valueid, hotness)
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
@ -3574,6 +3588,7 @@ void IndexBitcodeWriter::writeCombinedGlobalValueSummary() {
NameVals.push_back(Index.getModuleId(FS->modulePath()));
NameVals.push_back(getEncodedGVSummaryFlags(FS->flags()));
NameVals.push_back(FS->instCount());
NameVals.push_back(getEncodedFFlags(FS->fflags()));
// Fill in below
NameVals.push_back(0);
@ -3585,7 +3600,7 @@ void IndexBitcodeWriter::writeCombinedGlobalValueSummary() {
NameVals.push_back(*RefValueId);
Count++;
}
NameVals[4] = Count;
NameVals[5] = Count;
bool HasProfileData = false;
for (auto &EI : FS->calls()) {

View File

@ -2,7 +2,7 @@
; RUN: opt -module-summary %s -o - | llvm-bcanalyzer -dump | FileCheck %s
; CHECK: <GLOBALVAL_SUMMARY_BLOCK
; CHECK: <VERSION op0=3/>
; CHECK: <VERSION op0=4/>

View File

@ -14,7 +14,7 @@
; CHECK-NEXT: <VERSION
; See if the call to func is registered.
; The value id 1 matches the second FUNCTION record above.
; CHECK-NEXT: <PERMODULE {{.*}} op4=1/>
; CHECK-NEXT: <PERMODULE {{.*}} op5=1/>
; CHECK-NEXT: </GLOBALVAL_SUMMARY_BLOCK>
; CHECK: <STRTAB_BLOCK
@ -26,7 +26,7 @@
; COMBINED-NEXT: <VALUE_GUID op0=[[ALIASID:[0-9]+]] op1=-5751648690987223394/>
; COMBINED-NEXT: <VALUE_GUID
; COMBINED-NEXT: <VALUE_GUID op0=[[ALIASEEID:[0-9]+]] op1=-1039159065113703048/>
; COMBINED-NEXT: <COMBINED {{.*}} op5=[[ALIASID]]/>
; COMBINED-NEXT: <COMBINED {{.*}} op6=[[ALIASID]]/>
; COMBINED-NEXT: <COMBINED {{.*}}
; COMBINED-NEXT: <COMBINED_ALIAS {{.*}} op3=[[ALIASEEID]]
; COMBINED-NEXT: </GLOBALVAL_SUMMARY_BLOCK

View File

@ -4,7 +4,7 @@
; CHECK: <GLOBALVAL_SUMMARY_BLOCK
; CHECK-NEXT: <VERSION
; CHECK-NEXT: <PERMODULE {{.*}} op3=0 op4=[[ALIASID:[0-9]+]]/>
; CHECK-NEXT: <PERMODULE {{.*}} op4=0 op5=[[ALIASID:[0-9]+]]/>
; CHECK-NEXT: <PERMODULE {{.*}} op0=[[ALIASEEID:[0-9]+]]
; CHECK-NEXT: <ALIAS {{.*}} op0=[[ALIASID]] {{.*}} op2=[[ALIASEEID]]/>
; CHECK-NEXT: </GLOBALVAL_SUMMARY_BLOCK>

View File

@ -17,7 +17,7 @@
; CHECK: <GLOBALVAL_SUMMARY_BLOCK
; CHECK-NEXT: <VERSION
; See if the call to func is registered, using the expected hotness type.
; CHECK-NEXT: <PERMODULE_PROFILE {{.*}} op4=1 op5=2/>
; CHECK-NEXT: <PERMODULE_PROFILE {{.*}} op5=1 op6=2/>
; CHECK-NEXT: </GLOBALVAL_SUMMARY_BLOCK>
; CHECK: <STRTAB_BLOCK
; CHECK-NEXT: blob data = 'mainfunc{{.*}}'
@ -29,7 +29,7 @@
; COMBINED-NEXT: <COMBINED
; See if the call to func is registered, using the expected hotness type.
; op6=2 which is hotnessType::None.
; COMBINED-NEXT: <COMBINED_PROFILE {{.*}} op5=[[FUNCID]] op6=2/>
; COMBINED-NEXT: <COMBINED_PROFILE {{.*}} op6=[[FUNCID]] op7=2/>
; COMBINED-NEXT: </GLOBALVAL_SUMMARY_BLOCK>
; ModuleID = 'thinlto-function-summary-callgraph.ll'

View File

@ -29,7 +29,7 @@
; CHECK-NEXT: <VERSION
; CHECK-NEXT: <VALUE_GUID op0=25 op1=123/>
; op4=hot1 op6=cold op8=hot2 op10=hot4 op12=none1 op14=hot3 op16=none2 op18=none3 op20=123
; CHECK-NEXT: <PERMODULE_PROFILE {{.*}} op4=1 op5=3 op6=5 op7=1 op8=2 op9=3 op10=4 op11=1 op12=6 op13=2 op14=3 op15=3 op16=7 op17=2 op18=8 op19=2 op20=25 op21=4/>
; CHECK-NEXT: <PERMODULE_PROFILE {{.*}} op5=1 op6=3 op7=5 op8=1 op9=2 op10=3 op11=4 op12=1 op13=6 op14=2 op15=3 op16=3 op17=7 op18=2 op19=8 op20=2 op21=25 op22=4/>
; CHECK-NEXT: </GLOBALVAL_SUMMARY_BLOCK>
; CHECK: <STRTAB_BLOCK
@ -51,7 +51,7 @@
; COMBINED-NEXT: <COMBINED abbrevid=
; COMBINED-NEXT: <COMBINED abbrevid=
; COMBINED-NEXT: <COMBINED abbrevid=
; COMBINED-NEXT: <COMBINED_PROFILE {{.*}} op5=[[HOT1:.*]] op6=3 op7=[[COLD:.*]] op8=1 op9=[[HOT2:.*]] op10=3 op11=[[NONE1:.*]] op12=2 op13=[[HOT3:.*]] op14=3 op15=[[NONE2:.*]] op16=2 op17=[[NONE3:.*]] op18=2/>
; COMBINED-NEXT: <COMBINED_PROFILE {{.*}} op6=[[HOT1:.*]] op7=3 op8=[[COLD:.*]] op9=1 op10=[[HOT2:.*]] op11=3 op12=[[NONE1:.*]] op13=2 op14=[[HOT3:.*]] op15=3 op16=[[NONE2:.*]] op17=2 op18=[[NONE3:.*]] op19=2/>
; COMBINED_NEXT: <COMBINED abbrevid=
; COMBINED_NEXT: </GLOBALVAL_SUMMARY_BLOCK>

View File

@ -31,7 +31,7 @@
; CHECK-NEXT: <VERSION
; CHECK-NEXT: <VALUE_GUID op0=26 op1=123/>
; op4=none1 op6=hot1 op8=cold1 op10=none2 op12=hot2 op14=cold2 op16=none3 op18=hot3 op20=cold3 op22=123
; CHECK-NEXT: <PERMODULE_PROFILE {{.*}} op4=7 op5=0 op6=1 op7=3 op8=4 op9=1 op10=8 op11=0 op12=2 op13=3 op14=5 op15=1 op16=9 op17=0 op18=3 op19=3 op20=6 op21=1 op22=26 op23=4/>
; CHECK-NEXT: <PERMODULE_PROFILE {{.*}} op5=7 op6=0 op7=1 op8=3 op9=4 op10=1 op11=8 op12=0 op13=2 op14=3 op15=5 op16=1 op17=9 op18=0 op19=3 op20=3 op21=6 op22=1 op23=26 op24=4/>
; CHECK-NEXT: </GLOBALVAL_SUMMARY_BLOCK>
; CHECK: <STRTAB_BLOCK
@ -57,7 +57,7 @@
; COMBINED-NEXT: <COMBINED abbrevid=
; COMBINED-NEXT: <COMBINED abbrevid=
; COMBINED-NEXT: <COMBINED abbrevid=
; COMBINED-NEXT: <COMBINED_PROFILE {{.*}} op5=[[NONE1:.*]] op6=0 op7=[[HOT1:.*]] op8=3 op9=[[COLD1:.*]] op10=1 op11=[[NONE2:.*]] op12=0 op13=[[HOT2:.*]] op14=3 op15=[[COLD2:.*]] op16=1 op17=[[NONE3:.*]] op18=0 op19=[[HOT3:.*]] op20=3 op21=[[COLD3:.*]] op22=1/>
; COMBINED-NEXT: <COMBINED_PROFILE {{.*}} op6=[[NONE1:.*]] op7=0 op8=[[HOT1:.*]] op9=3 op10=[[COLD1:.*]] op11=1 op12=[[NONE2:.*]] op13=0 op14=[[HOT2:.*]] op15=3 op16=[[COLD2:.*]] op17=1 op18=[[NONE3:.*]] op19=0 op20=[[HOT3:.*]] op21=3 op22=[[COLD3:.*]] op23=1/>
; COMBINED_NEXT: <COMBINED abbrevid=
; COMBINED_NEXT: </GLOBALVAL_SUMMARY_BLOCK>

View File

@ -18,7 +18,7 @@
; CHECK: <GLOBALVAL_SUMMARY_BLOCK
; CHECK-NEXT: <VERSION
; See if the call to func is registered.
; CHECK-NEXT: <PERMODULE {{.*}} op3=1
; CHECK-NEXT: <PERMODULE {{.*}} op4=1
; CHECK-NEXT: </GLOBALVAL_SUMMARY_BLOCK>
; CHECK: <STRTAB_BLOCK
; CHECK-NEXT: blob data = 'undefinedglobmainfunc{{.*}}'
@ -32,7 +32,7 @@
; COMBINED-NEXT: <VALUE_GUID
; COMBINED-NEXT: <COMBINED
; See if the call to func is registered.
; COMBINED-NEXT: <COMBINED {{.*}} op5=[[FUNCID]]/>
; COMBINED-NEXT: <COMBINED {{.*}} op6=[[FUNCID]]/>
; COMBINED-NEXT: </GLOBALVAL_SUMMARY_BLOCK>
; ModuleID = 'thinlto-function-summary-callgraph.ll'

View File

@ -0,0 +1,27 @@
; RUN: opt -module-summary %s -o %t.o
; RUN: llvm-bcanalyzer -dump %t.o | FileCheck %s
; CHECK: <GLOBALVAL_SUMMARY_BLOCK
; ensure @f is marked readnone
; CHECK: <PERMODULE {{.*}} op0=0 {{.*}} op3=1
; ensure @g is marked readonly
; CHECK: <PERMODULE {{.*}} op0=1 {{.*}} op3=2
; ensure @h is marked norecurse
; CHECK: <PERMODULE {{.*}} op0=2 {{.*}} op3=4
; ensure @i is marked returndoesnotalias
; CHECK: <PERMODULE {{.*}} op0=3 {{.*}} op3=8
define void @f() readnone {
ret void
}
define void @g() readonly {
ret void
}
define void @h() norecurse {
ret void
}
define noalias i8* @i() {
%r = alloca i8
ret i8* %r
}

View File

@ -38,24 +38,24 @@
; CHECK: <GLOBALVAL_SUMMARY_BLOCK
; Function main contains call to func, as well as address reference to func:
; op0=main op4=func op5=func
; CHECK-DAG: <PERMODULE {{.*}} op0=11 op1=0 {{.*}} op3=1 op4=2 op5=2/>
; CHECK-DAG: <PERMODULE {{.*}} op0=11 op1=0 {{.*}} op4=1 op5=2 op6=2/>
; Function W contains a call to func3 as well as a reference to globalvar:
; op0=W op4=globalvar op5=func3
; CHECK-DAG: <PERMODULE {{.*}} op0=6 op1=5 {{.*}} op3=1 op4=1 op5=5/>
; CHECK-DAG: <PERMODULE {{.*}} op0=6 op1=5 {{.*}} op4=1 op5=1 op6=5/>
; Function X contains call to foo, as well as address reference to foo
; which is in the same instruction as the call:
; op0=X op4=foo op5=foo
; CHECK-DAG: <PERMODULE {{.*}} op0=7 op1=1 {{.*}} op3=1 op4=4 op5=4/>
; CHECK-DAG: <PERMODULE {{.*}} op0=7 op1=1 {{.*}} op4=1 op5=4 op6=4/>
; Function Y contains call to func2, and ensures we don't incorrectly add
; a reference to it when reached while earlier analyzing the phi using its
; return value:
; op0=Y op4=func2
; CHECK-DAG: <PERMODULE {{.*}} op0=8 op1=8 {{.*}} op3=0 op4=3/>
; CHECK-DAG: <PERMODULE {{.*}} op0=8 op1=8 {{.*}} op4=0 op5=3/>
; Function Z contains call to func2, and ensures we don't incorrectly add
; a reference to it when reached while analyzing subsequent use of its return
; value:
; op0=Z op4=func2
; CHECK-DAG: <PERMODULE {{.*}} op0=9 op1=3 {{.*}} op3=0 op4=3/>
; CHECK-DAG: <PERMODULE {{.*}} op0=9 op1=3 {{.*}} op4=0 op5=3/>
; Variable bar initialization contains address reference to func:
; op0=bar op2=func
; CHECK-DAG: <PERMODULE_GLOBALVAR_INIT_REFS {{.*}} op0=0 op1=0 op2=2/>