mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 12:41:49 +01: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:
parent
57b0c16d3c
commit
2f92680aa3
@ -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(); }
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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) {
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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() {
|
||||
|
@ -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));
|
||||
|
@ -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>
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user