1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-19 02:52:53 +02:00

IR: Eliminate non-determinism in the module summary analysis.

Also make the summary ref and call graph vectors immutable. This means
a smaller API surface and fewer places to audit for non-determinism.

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

llvm-svn: 290200
This commit is contained in:
Peter Collingbourne 2016-12-20 21:12:28 +00:00
parent 57b0c16d3c
commit 2f92680aa3
7 changed files with 132 additions and 172 deletions

View File

@ -42,7 +42,11 @@ public:
typedef typename VectorType::reverse_iterator reverse_iterator;
typedef typename VectorType::const_reverse_iterator const_reverse_iterator;
ArrayRef<value_type> getArrayRef() const { return Vector; }
/// Clear the MapVector and return the underlying vector.
VectorType takeVector() {
Map.clear();
return std::move(Vector);
}
size_type size() const { return Vector.size(); }

View File

@ -63,6 +63,12 @@ public:
ArrayRef<T> getArrayRef() const { return vector_; }
/// Clear the SetVector and return the underlying vector.
Vector takeVector() {
set_.clear();
return std::move(vector_);
}
/// \brief Determine if the SetVector is empty or not.
bool empty() const {
return vector_.empty();

View File

@ -41,8 +41,8 @@ struct CalleeInfo {
}
};
/// Struct to hold value either by GUID or Value*, depending on whether this
/// is a combined or per-module index, respectively.
/// Struct to hold value either by GUID or GlobalValue*. Values in combined
/// indexes as well as indirect calls are GUIDs, all others are GlobalValues.
struct ValueInfo {
/// The value representation used in this instance.
enum ValueInfoKind {
@ -53,9 +53,9 @@ struct ValueInfo {
/// Union of the two possible value types.
union ValueUnion {
GlobalValue::GUID Id;
const Value *V;
const GlobalValue *GV;
ValueUnion(GlobalValue::GUID Id) : Id(Id) {}
ValueUnion(const Value *V) : V(V) {}
ValueUnion(const GlobalValue *GV) : GV(GV) {}
};
/// The value being represented.
@ -64,21 +64,37 @@ struct ValueInfo {
ValueInfoKind Kind;
/// Constructor for a GUID value
ValueInfo(GlobalValue::GUID Id = 0) : TheValue(Id), Kind(VI_GUID) {}
/// Constructor for a Value* value
ValueInfo(const Value *V) : TheValue(V), Kind(VI_Value) {}
/// Constructor for a GlobalValue* value
ValueInfo(const GlobalValue *V) : TheValue(V), Kind(VI_Value) {}
/// Accessor for GUID value
GlobalValue::GUID getGUID() const {
assert(Kind == VI_GUID && "Not a GUID type");
return TheValue.Id;
}
/// Accessor for Value* value
const Value *getValue() const {
/// Accessor for GlobalValue* value
const GlobalValue *getValue() const {
assert(Kind == VI_Value && "Not a Value type");
return TheValue.V;
return TheValue.GV;
}
bool isGUID() const { return Kind == VI_GUID; }
};
template <> struct DenseMapInfo<ValueInfo> {
static inline ValueInfo getEmptyKey() { return ValueInfo((GlobalValue *)-1); }
static inline ValueInfo getTombstoneKey() {
return ValueInfo((GlobalValue *)-2);
}
static bool isEqual(ValueInfo L, ValueInfo R) {
if (L.isGUID() != R.isGUID())
return false;
return L.isGUID() ? (L.getGUID() == R.getGUID())
: (L.getValue() == R.getValue());
}
static unsigned getHashValue(ValueInfo I) {
return I.isGUID() ? I.getGUID() : (uintptr_t)I.getValue();
}
};
/// \brief Function and variable summary information to aid decisions and
/// implementation of importing.
class GlobalValueSummary {
@ -160,7 +176,8 @@ private:
protected:
/// GlobalValueSummary constructor.
GlobalValueSummary(SummaryKind K, GVFlags Flags) : Kind(K), Flags(Flags) {}
GlobalValueSummary(SummaryKind K, GVFlags Flags, std::vector<ValueInfo> Refs)
: Kind(K), Flags(Flags), RefEdgeList(std::move(Refs)) {}
public:
virtual ~GlobalValueSummary() = default;
@ -222,24 +239,8 @@ public:
Flags.HasInlineAsmMaybeReferencingInternal = true;
}
/// Record a reference from this global value to the global value identified
/// by \p RefGUID.
void addRefEdge(GlobalValue::GUID RefGUID) { RefEdgeList.push_back(RefGUID); }
/// Record a reference from this global value to the global value identified
/// by \p RefV.
void addRefEdge(const Value *RefV) { RefEdgeList.push_back(RefV); }
/// Record a reference from this global value to each global value identified
/// in \p RefEdges.
void addRefEdges(DenseSet<const Value *> &RefEdges) {
for (auto &RI : RefEdges)
addRefEdge(RI);
}
/// Return the list of values referenced by this global value definition.
std::vector<ValueInfo> &refs() { return RefEdgeList; }
const std::vector<ValueInfo> &refs() const { return RefEdgeList; }
ArrayRef<ValueInfo> refs() const { return RefEdgeList; }
};
/// \brief Alias summary information.
@ -248,7 +249,8 @@ class AliasSummary : public GlobalValueSummary {
public:
/// Summary constructors.
AliasSummary(GVFlags Flags) : GlobalValueSummary(AliasKind, Flags) {}
AliasSummary(GVFlags Flags, std::vector<ValueInfo> Refs)
: GlobalValueSummary(AliasKind, Flags, std::move(Refs)) {}
/// Check if this is an alias summary.
static bool classof(const GlobalValueSummary *GVS) {
@ -284,8 +286,10 @@ private:
public:
/// Summary constructors.
FunctionSummary(GVFlags Flags, unsigned NumInsts)
: GlobalValueSummary(FunctionKind, Flags), InstCount(NumInsts) {}
FunctionSummary(GVFlags Flags, unsigned NumInsts, std::vector<ValueInfo> Refs,
std::vector<EdgeTy> CGEdges)
: GlobalValueSummary(FunctionKind, Flags, std::move(Refs)),
InstCount(NumInsts), CallGraphEdgeList(std::move(CGEdges)) {}
/// Check if this is a function summary.
static bool classof(const GlobalValueSummary *GVS) {
@ -295,38 +299,8 @@ public:
/// Get the instruction count recorded for this function.
unsigned instCount() const { return InstCount; }
/// Record a call graph edge from this function to the function identified
/// by \p CalleeGUID, with \p CalleeInfo including the cumulative profile
/// count (across all calls from this function) or 0 if no PGO.
void addCallGraphEdge(GlobalValue::GUID CalleeGUID, CalleeInfo Info) {
CallGraphEdgeList.push_back(std::make_pair(CalleeGUID, Info));
}
/// Record a call graph edge from this function to each function GUID recorded
/// in \p CallGraphEdges.
void
addCallGraphEdges(DenseMap<GlobalValue::GUID, CalleeInfo> &CallGraphEdges) {
for (auto &EI : CallGraphEdges)
addCallGraphEdge(EI.first, EI.second);
}
/// Record a call graph edge from this function to the function identified
/// by \p CalleeV, with \p CalleeInfo including the cumulative profile
/// count (across all calls from this function) or 0 if no PGO.
void addCallGraphEdge(const Value *CalleeV, CalleeInfo Info) {
CallGraphEdgeList.push_back(std::make_pair(CalleeV, Info));
}
/// Record a call graph edge from this function to each function recorded
/// in \p CallGraphEdges.
void addCallGraphEdges(DenseMap<const Value *, CalleeInfo> &CallGraphEdges) {
for (auto &EI : CallGraphEdges)
addCallGraphEdge(EI.first, EI.second);
}
/// Return the list of <CalleeValueInfo, CalleeInfo> pairs.
std::vector<EdgeTy> &calls() { return CallGraphEdgeList; }
const std::vector<EdgeTy> &calls() const { return CallGraphEdgeList; }
ArrayRef<EdgeTy> calls() const { return CallGraphEdgeList; }
};
/// \brief Global variable summary information to aid decisions and
@ -339,7 +313,8 @@ class GlobalVarSummary : public GlobalValueSummary {
public:
/// Summary constructors.
GlobalVarSummary(GVFlags Flags) : GlobalValueSummary(GlobalVarKind, Flags) {}
GlobalVarSummary(GVFlags Flags, std::vector<ValueInfo> Refs)
: GlobalValueSummary(GlobalVarKind, Flags, std::move(Refs)) {}
/// Check if this is a global variable summary.
static bool classof(const GlobalValueSummary *GVS) {

View File

@ -13,6 +13,8 @@
//===----------------------------------------------------------------------===//
#include "llvm/Analysis/ModuleSummaryAnalysis.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Analysis/BlockFrequencyInfo.h"
#include "llvm/Analysis/BlockFrequencyInfoImpl.h"
@ -34,7 +36,7 @@ using namespace llvm;
// Walk through the operands of a given User via worklist iteration and populate
// the set of GlobalValue references encountered. Invoked either on an
// Instruction or a GlobalVariable (which walks its initializer).
static void findRefEdges(const User *CurUser, DenseSet<const Value *> &RefEdges,
static void findRefEdges(const User *CurUser, SetVector<ValueInfo> &RefEdges,
SmallPtrSet<const User *, 8> &Visited) {
SmallVector<const User *, 32> Worklist;
Worklist.push_back(CurUser);
@ -53,12 +55,12 @@ static void findRefEdges(const User *CurUser, DenseSet<const Value *> &RefEdges,
continue;
if (isa<BlockAddress>(Operand))
continue;
if (isa<GlobalValue>(Operand)) {
if (auto *GV = dyn_cast<GlobalValue>(Operand)) {
// We have a reference to a global value. This should be added to
// the reference set unless it is a callee. Callees are handled
// specially by WriteFunction and are added to a separate list.
if (!(CS && CS.isCallee(&OI)))
RefEdges.insert(Operand);
RefEdges.insert(GV);
continue;
}
Worklist.push_back(Operand);
@ -88,9 +90,8 @@ static void computeFunctionSummary(ModuleSummaryIndex &Index, const Module &M,
unsigned NumInsts = 0;
// Map from callee ValueId to profile count. Used to accumulate profile
// counts for all static calls to a given callee.
DenseMap<const Value *, CalleeInfo> CallGraphEdges;
DenseMap<GlobalValue::GUID, CalleeInfo> IndirectCallEdges;
DenseSet<const Value *> RefEdges;
MapVector<ValueInfo, CalleeInfo> CallGraphEdges;
SetVector<ValueInfo> RefEdges;
ICallPromotionAnalysis ICallAnalysis;
bool HasInlineAsmMaybeReferencingInternal = false;
@ -130,16 +131,14 @@ static void computeFunctionSummary(ModuleSummaryIndex &Index, const Module &M,
// We should have named any anonymous globals
assert(CalledFunction->hasName());
auto ScaledCount = BFI ? BFI->getBlockProfileCount(&BB) : None;
auto Hotness = ScaledCount ? getHotness(ScaledCount.getValue(), PSI)
: CalleeInfo::HotnessType::Unknown;
// Use the original CalledValue, in case it was an alias. We want
// to record the call edge to the alias in that case. Eventually
// an alias summary will be created to associate the alias and
// aliasee.
auto *CalleeId =
M.getValueSymbolTable().lookup(CalledValue->getName());
auto Hotness = ScaledCount ? getHotness(ScaledCount.getValue(), PSI)
: CalleeInfo::HotnessType::Unknown;
CallGraphEdges[CalleeId].updateHotness(Hotness);
CallGraphEdges[cast<GlobalValue>(CalledValue)].updateHotness(Hotness);
} else {
// Skip inline assembly calls.
if (CI && CI->isInlineAsm())
@ -154,17 +153,14 @@ static void computeFunctionSummary(ModuleSummaryIndex &Index, const Module &M,
ICallAnalysis.getPromotionCandidatesForInstruction(
&I, NumVals, TotalCount, NumCandidates);
for (auto &Candidate : CandidateProfileData)
IndirectCallEdges[Candidate.Value].updateHotness(
CallGraphEdges[Candidate.Value].updateHotness(
getHotness(Candidate.Count, PSI));
}
}
GlobalValueSummary::GVFlags Flags(F);
std::unique_ptr<FunctionSummary> FuncSummary =
llvm::make_unique<FunctionSummary>(Flags, NumInsts);
FuncSummary->addCallGraphEdges(CallGraphEdges);
FuncSummary->addCallGraphEdges(IndirectCallEdges);
FuncSummary->addRefEdges(RefEdges);
auto FuncSummary = llvm::make_unique<FunctionSummary>(
Flags, NumInsts, RefEdges.takeVector(), CallGraphEdges.takeVector());
if (HasInlineAsmMaybeReferencingInternal)
FuncSummary->setHasInlineAsmMaybeReferencingInternal();
Index.addGlobalValueSummary(F.getName(), std::move(FuncSummary));
@ -172,20 +168,19 @@ static void computeFunctionSummary(ModuleSummaryIndex &Index, const Module &M,
static void computeVariableSummary(ModuleSummaryIndex &Index,
const GlobalVariable &V) {
DenseSet<const Value *> RefEdges;
SetVector<ValueInfo> RefEdges;
SmallPtrSet<const User *, 8> Visited;
findRefEdges(&V, RefEdges, Visited);
GlobalValueSummary::GVFlags Flags(V);
std::unique_ptr<GlobalVarSummary> GVarSummary =
llvm::make_unique<GlobalVarSummary>(Flags);
GVarSummary->addRefEdges(RefEdges);
auto GVarSummary =
llvm::make_unique<GlobalVarSummary>(Flags, RefEdges.takeVector());
Index.addGlobalValueSummary(V.getName(), std::move(GVarSummary));
}
static void computeAliasSummary(ModuleSummaryIndex &Index,
const GlobalAlias &A) {
GlobalValueSummary::GVFlags Flags(A);
std::unique_ptr<AliasSummary> AS = llvm::make_unique<AliasSummary>(Flags);
auto AS = llvm::make_unique<AliasSummary>(Flags, ArrayRef<ValueInfo>{});
auto *Aliasee = A.getBaseObject();
auto *AliaseeSummary = Index.getGlobalValueSummary(*Aliasee);
assert(AliaseeSummary && "Alias expects aliasee summary to be parsed");
@ -283,12 +278,15 @@ ModuleSummaryIndex llvm::buildModuleSummaryIndex(
// Create the appropriate summary type.
if (isa<Function>(GV)) {
std::unique_ptr<FunctionSummary> Summary =
llvm::make_unique<FunctionSummary>(GVFlags, 0);
llvm::make_unique<FunctionSummary>(
GVFlags, 0, ArrayRef<ValueInfo>{},
ArrayRef<FunctionSummary::EdgeTy>{});
Summary->setNoRename();
Index.addGlobalValueSummary(Name, std::move(Summary));
} else {
std::unique_ptr<GlobalVarSummary> Summary =
llvm::make_unique<GlobalVarSummary>(GVFlags);
llvm::make_unique<GlobalVarSummary>(GVFlags,
ArrayRef<ValueInfo>{});
Summary->setNoRename();
Index.addGlobalValueSummary(Name, std::move(Summary));
}

View File

@ -668,14 +668,15 @@ private:
Error parseValueSymbolTable(
uint64_t Offset,
DenseMap<unsigned, GlobalValue::LinkageTypes> &ValueIdToLinkageMap);
std::vector<ValueInfo> makeRefList(ArrayRef<uint64_t> Record);
std::vector<FunctionSummary::EdgeTy> makeCallList(ArrayRef<uint64_t> Record,
bool IsOldProfileFormat,
bool HasProfile);
Error parseEntireSummary(StringRef ModulePath);
Error parseModuleStringTable();
std::pair<GlobalValue::GUID, GlobalValue::GUID>
std::pair<GlobalValue::GUID, GlobalValue::GUID>
getGUIDFromValueId(unsigned ValueId);
std::pair<GlobalValue::GUID, CalleeInfo::HotnessType>
readCallGraphEdge(const SmallVector<uint64_t, 64> &Record, unsigned int &I,
bool IsOldProfileFormat, bool HasProfile);
};
} // end anonymous namespace
@ -4792,6 +4793,33 @@ Error ModuleSummaryIndexBitcodeReader::parseModule(StringRef ModulePath) {
}
}
std::vector<ValueInfo>
ModuleSummaryIndexBitcodeReader::makeRefList(ArrayRef<uint64_t> Record) {
std::vector<ValueInfo> Ret;
Ret.reserve(Record.size());
for (uint64_t RefValueId : Record)
Ret.push_back(getGUIDFromValueId(RefValueId).first);
return Ret;
}
std::vector<FunctionSummary::EdgeTy> ModuleSummaryIndexBitcodeReader::makeCallList(
ArrayRef<uint64_t> Record, bool IsOldProfileFormat, bool HasProfile) {
std::vector<FunctionSummary::EdgeTy> Ret;
Ret.reserve(Record.size());
for (unsigned I = 0, E = Record.size(); I != E; ++I) {
CalleeInfo::HotnessType Hotness = CalleeInfo::HotnessType::Unknown;
GlobalValue::GUID CalleeGUID = getGUIDFromValueId(Record[I]).first;
if (IsOldProfileFormat) {
I += 1; // Skip old callsitecount field
if (HasProfile)
I += 1; // Skip old profilecount field
} else if (HasProfile)
Hotness = static_cast<CalleeInfo::HotnessType>(Record[++I]);
Ret.push_back(FunctionSummary::EdgeTy{CalleeGUID, CalleeInfo{Hotness}});
}
return Ret;
}
// Eagerly parse the entire summary block. This populates the GlobalValueSummary
// objects in the index.
Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(
@ -4868,33 +4896,25 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(
unsigned InstCount = Record[2];
unsigned NumRefs = Record[3];
auto Flags = getDecodedGVSummaryFlags(RawFlags, Version);
std::unique_ptr<FunctionSummary> FS =
llvm::make_unique<FunctionSummary>(Flags, InstCount);
// 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.
FS->setModulePath(TheIndex.addModulePath(ModulePath, 0)->first());
static int RefListStartIndex = 4;
int CallGraphEdgeStartIndex = RefListStartIndex + NumRefs;
assert(Record.size() >= RefListStartIndex + NumRefs &&
"Record size inconsistent with number of references");
for (unsigned I = 4, E = CallGraphEdgeStartIndex; I != E; ++I) {
unsigned RefValueId = Record[I];
GlobalValue::GUID RefGUID = getGUIDFromValueId(RefValueId).first;
FS->addRefEdge(RefGUID);
}
std::vector<ValueInfo> Refs = makeRefList(
ArrayRef<uint64_t>(Record).slice(RefListStartIndex, NumRefs));
bool HasProfile = (BitCode == bitc::FS_PERMODULE_PROFILE);
for (unsigned I = CallGraphEdgeStartIndex, E = Record.size(); I != E;
++I) {
CalleeInfo::HotnessType Hotness;
GlobalValue::GUID CalleeGUID;
std::tie(CalleeGUID, Hotness) =
readCallGraphEdge(Record, I, IsOldProfileFormat, HasProfile);
FS->addCallGraphEdge(CalleeGUID, CalleeInfo(Hotness));
}
std::vector<FunctionSummary::EdgeTy> Calls = makeCallList(
ArrayRef<uint64_t>(Record).slice(CallGraphEdgeStartIndex),
IsOldProfileFormat, HasProfile);
auto FS = llvm::make_unique<FunctionSummary>(
Flags, InstCount, std::move(Refs), std::move(Calls));
auto GUID = getGUIDFromValueId(ValueID);
FS->setModulePath(TheIndex.addModulePath(ModulePath, 0)->first());
FS->setOriginalName(GUID.second);
TheIndex.addGlobalValueSummary(GUID.first, std::move(FS));
break;
@ -4907,7 +4927,8 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(
uint64_t RawFlags = Record[1];
unsigned AliaseeID = Record[2];
auto Flags = getDecodedGVSummaryFlags(RawFlags, Version);
std::unique_ptr<AliasSummary> AS = llvm::make_unique<AliasSummary>(Flags);
auto AS =
llvm::make_unique<AliasSummary>(Flags, std::vector<ValueInfo>{});
// 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
@ -4931,14 +4952,10 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(
unsigned ValueID = Record[0];
uint64_t RawFlags = Record[1];
auto Flags = getDecodedGVSummaryFlags(RawFlags, Version);
std::unique_ptr<GlobalVarSummary> FS =
llvm::make_unique<GlobalVarSummary>(Flags);
std::vector<ValueInfo> Refs =
makeRefList(ArrayRef<uint64_t>(Record).slice(2));
auto FS = llvm::make_unique<GlobalVarSummary>(Flags, std::move(Refs));
FS->setModulePath(TheIndex.addModulePath(ModulePath, 0)->first());
for (unsigned I = 2, E = Record.size(); I != E; ++I) {
unsigned RefValueId = Record[I];
GlobalValue::GUID RefGUID = getGUIDFromValueId(RefValueId).first;
FS->addRefEdge(RefGUID);
}
auto GUID = getGUIDFromValueId(ValueID);
FS->setOriginalName(GUID.second);
TheIndex.addGlobalValueSummary(GUID.first, std::move(FS));
@ -4956,30 +4973,21 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(
unsigned InstCount = Record[3];
unsigned NumRefs = Record[4];
auto Flags = getDecodedGVSummaryFlags(RawFlags, Version);
std::unique_ptr<FunctionSummary> FS =
llvm::make_unique<FunctionSummary>(Flags, InstCount);
LastSeenSummary = FS.get();
FS->setModulePath(ModuleIdMap[ModuleId]);
static int RefListStartIndex = 5;
int CallGraphEdgeStartIndex = RefListStartIndex + NumRefs;
assert(Record.size() >= RefListStartIndex + NumRefs &&
"Record size inconsistent with number of references");
for (unsigned I = RefListStartIndex, E = CallGraphEdgeStartIndex; I != E;
++I) {
unsigned RefValueId = Record[I];
GlobalValue::GUID RefGUID = getGUIDFromValueId(RefValueId).first;
FS->addRefEdge(RefGUID);
}
std::vector<ValueInfo> Refs = makeRefList(
ArrayRef<uint64_t>(Record).slice(RefListStartIndex, NumRefs));
bool HasProfile = (BitCode == bitc::FS_COMBINED_PROFILE);
for (unsigned I = CallGraphEdgeStartIndex, E = Record.size(); I != E;
++I) {
CalleeInfo::HotnessType Hotness;
GlobalValue::GUID CalleeGUID;
std::tie(CalleeGUID, Hotness) =
readCallGraphEdge(Record, I, IsOldProfileFormat, HasProfile);
FS->addCallGraphEdge(CalleeGUID, CalleeInfo(Hotness));
}
std::vector<FunctionSummary::EdgeTy> Edges = makeCallList(
ArrayRef<uint64_t>(Record).slice(CallGraphEdgeStartIndex),
IsOldProfileFormat, HasProfile);
GlobalValue::GUID GUID = getGUIDFromValueId(ValueID).first;
auto FS = llvm::make_unique<FunctionSummary>(
Flags, InstCount, std::move(Refs), std::move(Edges));
LastSeenSummary = FS.get();
FS->setModulePath(ModuleIdMap[ModuleId]);
TheIndex.addGlobalValueSummary(GUID, std::move(FS));
Combined = true;
break;
@ -4993,7 +5001,7 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(
uint64_t RawFlags = Record[2];
unsigned AliaseeValueId = Record[3];
auto Flags = getDecodedGVSummaryFlags(RawFlags, Version);
std::unique_ptr<AliasSummary> AS = llvm::make_unique<AliasSummary>(Flags);
auto AS = llvm::make_unique<AliasSummary>(Flags, std::vector<ValueInfo>{});
LastSeenSummary = AS.get();
AS->setModulePath(ModuleIdMap[ModuleId]);
@ -5015,15 +5023,11 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(
uint64_t ModuleId = Record[1];
uint64_t RawFlags = Record[2];
auto Flags = getDecodedGVSummaryFlags(RawFlags, Version);
std::unique_ptr<GlobalVarSummary> FS =
llvm::make_unique<GlobalVarSummary>(Flags);
std::vector<ValueInfo> Refs =
makeRefList(ArrayRef<uint64_t>(Record).slice(3));
auto FS = llvm::make_unique<GlobalVarSummary>(Flags, std::move(Refs));
LastSeenSummary = FS.get();
FS->setModulePath(ModuleIdMap[ModuleId]);
for (unsigned I = 3, E = Record.size(); I != E; ++I) {
unsigned RefValueId = Record[I];
GlobalValue::GUID RefGUID = getGUIDFromValueId(RefValueId).first;
FS->addRefEdge(RefGUID);
}
GlobalValue::GUID GUID = getGUIDFromValueId(ValueID).first;
TheIndex.addGlobalValueSummary(GUID, std::move(FS));
Combined = true;
@ -5043,23 +5047,6 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(
llvm_unreachable("Exit infinite loop");
}
std::pair<GlobalValue::GUID, CalleeInfo::HotnessType>
ModuleSummaryIndexBitcodeReader::readCallGraphEdge(
const SmallVector<uint64_t, 64> &Record, unsigned int &I,
const bool IsOldProfileFormat, const bool HasProfile) {
auto Hotness = CalleeInfo::HotnessType::Unknown;
unsigned CalleeValueId = Record[I];
GlobalValue::GUID CalleeGUID = getGUIDFromValueId(CalleeValueId).first;
if (IsOldProfileFormat) {
I += 1; // Skip old callsitecount field
if (HasProfile)
I += 1; // Skip old profilecount field
} else if (HasProfile)
Hotness = static_cast<CalleeInfo::HotnessType>(Record[++I]);
return {CalleeGUID, Hotness};
}
// Parse the module string table block into the Index.
// This populates the ModulePathStringTable map in the index.
Error ModuleSummaryIndexBitcodeReader::parseModuleStringTable() {

View File

@ -3290,21 +3290,11 @@ void ModuleBitcodeWriter::writePerModuleFunctionSummaryRecord(
NameVals.push_back(FS->instCount());
NameVals.push_back(FS->refs().size());
unsigned SizeBeforeRefs = NameVals.size();
for (auto &RI : FS->refs())
NameVals.push_back(VE.getValueID(RI.getValue()));
// Sort the refs for determinism output, the vector returned by FS->refs() has
// been initialized from a DenseSet.
std::sort(NameVals.begin() + SizeBeforeRefs, NameVals.end());
std::vector<FunctionSummary::EdgeTy> Calls = FS->calls();
std::sort(Calls.begin(), Calls.end(),
[this](const FunctionSummary::EdgeTy &L,
const FunctionSummary::EdgeTy &R) {
return getValueId(L.first) < getValueId(R.first);
});
bool HasProfileData = F.getEntryCount().hasValue();
for (auto &ECI : Calls) {
for (auto &ECI : FS->calls()) {
NameVals.push_back(getValueId(ECI.first));
if (HasProfileData)
NameVals.push_back(static_cast<uint8_t>(ECI.second.Hotness));

View File

@ -10,7 +10,7 @@
; CHECK-NEXT: <VERSION
; See if the call to func is registered, using the expected callsite count
; and profile count, with value id matching the subsequent value symbol table.
; CHECK-NEXT: <PERMODULE_PROFILE {{.*}} op4=[[HOT1:.*]] op5=3 op6=[[HOT2:.*]] op7=3 op8=[[HOT3:.*]] op9=3 op10=[[COLD:.*]] op11=1 op12=[[NONE1:.*]] op13=2 op14=[[NONE2:.*]] op15=2 op16=[[NONE3:.*]] op17=2/>
; CHECK-NEXT: <PERMODULE_PROFILE {{.*}} op4=[[HOT1:.*]] op5=3 op6=[[COLD:.*]] op7=1 op8=[[HOT2:.*]] op9=3 op10=[[NONE1:.*]] op11=2 op12=[[HOT3:.*]] op13=3 op14=[[NONE2:.*]] op15=2 op16=[[NONE3:.*]] op17=2/>
; CHECK-NEXT: </GLOBALVAL_SUMMARY_BLOCK>
; CHECK-LABEL: <VALUE_SYMTAB
; CHECK-NEXT: <FNENTRY {{.*}} record string = 'hot_function
@ -31,7 +31,7 @@
; COMBINED-NEXT: <COMBINED abbrevid=
; COMBINED-NEXT: <COMBINED abbrevid=
; COMBINED-NEXT: <COMBINED abbrevid=
; COMBINED-NEXT: <COMBINED_PROFILE {{.*}} op5=[[HOT1:.*]] op6=3 op7=[[HOT2:.*]] op8=3 op9=[[HOT3:.*]] op10=3 op11=[[COLD:.*]] op12=1 op13=[[NONE1:.*]] op14=2 op15=[[NONE2:.*]] op16=2 op17=[[NONE3:.*]] op18=2/>
; 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 abbrevid=
; COMBINED_NEXT: </GLOBALVAL_SUMMARY_BLOCK>