}
};
-class GlobalValueSummary;
-
-typedef std::vector<std::unique_ptr<GlobalValueSummary>> GlobalValueSummaryList;
-
-struct GlobalValueSummaryInfo {
- /// The GlobalValue corresponding to this summary. This is only used in
- /// per-module summaries.
- const GlobalValue *GV = nullptr;
-
- /// List of global value summary structures for a particular value held
- /// in the GlobalValueMap. Requires a vector in the case of multiple
- /// COMDAT values of the same name.
- GlobalValueSummaryList SummaryList;
-};
-
-/// Map from global value GUID to corresponding summary structures. Use a
-/// std::map rather than a DenseMap so that pointers to the map's value_type
-/// (which are used by ValueInfo) are not invalidated by insertion. Also it will
-/// likely incur less overhead, as the value type is not very small and the size
-/// of the map is unknown, resulting in inefficiencies due to repeated
-/// insertions and resizing.
-typedef std::map<GlobalValue::GUID, GlobalValueSummaryInfo>
- GlobalValueSummaryMapTy;
-
-/// Struct that holds a reference to a particular GUID in a global value
-/// summary.
+/// 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 {
- const GlobalValueSummaryMapTy::value_type *Ref = nullptr;
- ValueInfo() = default;
- ValueInfo(const GlobalValueSummaryMapTy::value_type *Ref) : Ref(Ref) {}
- operator bool() const { return Ref; }
+ /// The value representation used in this instance.
+ enum ValueInfoKind {
+ VI_GUID,
+ VI_Value,
+ };
- GlobalValue::GUID getGUID() const { return Ref->first; }
- const GlobalValue *getValue() const { return Ref->second.GV; }
- ArrayRef<std::unique_ptr<GlobalValueSummary>> getSummaryList() const {
- return Ref->second.SummaryList;
- }
+ /// Union of the two possible value types.
+ union ValueUnion {
+ GlobalValue::GUID Id;
+ const GlobalValue *GV;
+ ValueUnion(GlobalValue::GUID Id) : Id(Id) {}
+ ValueUnion(const GlobalValue *GV) : GV(GV) {}
+ };
+
+ /// The value being represented.
+ ValueUnion TheValue;
+ /// The value representation.
+ ValueInfoKind Kind;
+ /// Constructor for a GUID value
+ ValueInfo(GlobalValue::GUID Id = 0) : TheValue(Id), Kind(VI_GUID) {}
+ /// 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 GlobalValue* value
+ const GlobalValue *getValue() const {
+ assert(Kind == VI_Value && "Not a Value type");
+ return TheValue.GV;
+ }
+ bool isGUID() const { return Kind == VI_GUID; }
};
template <> struct DenseMapInfo<ValueInfo> {
- static inline ValueInfo getEmptyKey() {
- return ValueInfo((GlobalValueSummaryMapTy::value_type *)-1);
- }
+ static inline ValueInfo getEmptyKey() { return ValueInfo((GlobalValue *)-1); }
static inline ValueInfo getTombstoneKey() {
- return ValueInfo((GlobalValueSummaryMapTy::value_type *)-2);
+ 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();
}
- static bool isEqual(ValueInfo L, ValueInfo R) { return L.Ref == R.Ref; }
- static unsigned getHashValue(ValueInfo I) { return (uintptr_t)I.Ref; }
};
/// \brief Function and variable summary information to aid decisions and
/// 160 bits SHA1
typedef std::array<uint32_t, 5> ModuleHash;
+/// List of global value summary structures for a particular value held
+/// in the GlobalValueMap. Requires a vector in the case of multiple
+/// COMDAT values of the same name.
+typedef std::vector<std::unique_ptr<GlobalValueSummary>> GlobalValueSummaryList;
+
+/// Map from global value GUID to corresponding summary structures.
+/// Use a std::map rather than a DenseMap since it will likely incur
+/// less overhead, as the value type is not very small and the size
+/// of the map is unknown, resulting in inefficiencies due to repeated
+/// insertions and resizing.
+typedef std::map<GlobalValue::GUID, GlobalValueSummaryList>
+ GlobalValueSummaryMapTy;
+
/// Type used for iterating through the global value summary map.
typedef GlobalValueSummaryMapTy::const_iterator const_gvsummary_iterator;
typedef GlobalValueSummaryMapTy::iterator gvsummary_iterator;
// YAML I/O support.
friend yaml::MappingTraits<ModuleSummaryIndex>;
- GlobalValueSummaryMapTy::value_type *
- getOrInsertValuePtr(GlobalValue::GUID GUID) {
- return &*GlobalValueMap.emplace(GUID, GlobalValueSummaryInfo{}).first;
- }
-
public:
gvsummary_iterator begin() { return GlobalValueMap.begin(); }
const_gvsummary_iterator begin() const { return GlobalValueMap.begin(); }
const_gvsummary_iterator end() const { return GlobalValueMap.end(); }
size_t size() const { return GlobalValueMap.size(); }
- /// Return a ValueInfo for GUID if it exists, otherwise return ValueInfo().
- ValueInfo getValueInfo(GlobalValue::GUID GUID) const {
- auto I = GlobalValueMap.find(GUID);
- return ValueInfo(I == GlobalValueMap.end() ? nullptr : &*I);
+ /// Get the list of global value summary objects for a given value name.
+ const GlobalValueSummaryList &getGlobalValueSummaryList(StringRef ValueName) {
+ return GlobalValueMap[GlobalValue::getGUID(ValueName)];
}
- /// Return a ValueInfo for \p GUID.
- ValueInfo getOrInsertValueInfo(GlobalValue::GUID GUID) {
- return ValueInfo(getOrInsertValuePtr(GUID));
+ /// Get the list of global value summary objects for a given value name.
+ const const_gvsummary_iterator
+ findGlobalValueSummaryList(StringRef ValueName) const {
+ return GlobalValueMap.find(GlobalValue::getGUID(ValueName));
}
- /// Return a ValueInfo for \p GV and mark it as belonging to GV.
- ValueInfo getOrInsertValueInfo(const GlobalValue *GV) {
- auto VP = getOrInsertValuePtr(GV->getGUID());
- VP->second.GV = GV;
- return ValueInfo(VP);
+ /// Get the list of global value summary objects for a given value GUID.
+ const const_gvsummary_iterator
+ findGlobalValueSummaryList(GlobalValue::GUID ValueGUID) const {
+ return GlobalValueMap.find(ValueGUID);
}
/// Return the GUID for \p OriginalId in the OidGuidMap.
/// Add a global value summary for a value of the given name.
void addGlobalValueSummary(StringRef ValueName,
std::unique_ptr<GlobalValueSummary> Summary) {
- addGlobalValueSummary(getOrInsertValueInfo(GlobalValue::getGUID(ValueName)),
- std::move(Summary));
+ addOriginalName(GlobalValue::getGUID(ValueName),
+ Summary->getOriginalName());
+ GlobalValueMap[GlobalValue::getGUID(ValueName)].push_back(
+ std::move(Summary));
}
- /// Add a global value summary for the given ValueInfo.
- void addGlobalValueSummary(ValueInfo VI,
+ /// Add a global value summary for a value of the given GUID.
+ void addGlobalValueSummary(GlobalValue::GUID ValueGUID,
std::unique_ptr<GlobalValueSummary> Summary) {
- addOriginalName(VI.getGUID(), Summary->getOriginalName());
- // Here we have a notionally const VI, but the value it points to is owned
- // by the non-const *this.
- const_cast<GlobalValueSummaryMapTy::value_type *>(VI.Ref)
- ->second.SummaryList.push_back(std::move(Summary));
+ addOriginalName(ValueGUID, Summary->getOriginalName());
+ GlobalValueMap[ValueGUID].push_back(std::move(Summary));
}
/// Add an original name for the value of the given GUID.
/// not found.
GlobalValueSummary *findSummaryInModule(GlobalValue::GUID ValueGUID,
StringRef ModuleId) const {
- auto CalleeInfo = getValueInfo(ValueGUID);
- if (!CalleeInfo) {
+ auto CalleeInfoList = findGlobalValueSummaryList(ValueGUID);
+ if (CalleeInfoList == end()) {
return nullptr; // This function does not have a summary
}
auto Summary =
- llvm::find_if(CalleeInfo.getSummaryList(),
+ llvm::find_if(CalleeInfoList->second,
[&](const std::unique_ptr<GlobalValueSummary> &Summary) {
return Summary->modulePath() == ModuleId;
});
- if (Summary == CalleeInfo.getSummaryList().end())
+ if (Summary == CalleeInfoList->second.end())
return nullptr;
return Summary->get();
}
for (auto &FSum : FSums) {
GlobalValueSummary::GVFlags GVFlags(GlobalValue::ExternalLinkage, false,
false);
- Elem.SummaryList.push_back(llvm::make_unique<FunctionSummary>(
+ Elem.push_back(llvm::make_unique<FunctionSummary>(
GVFlags, 0, ArrayRef<ValueInfo>{},
ArrayRef<FunctionSummary::EdgeTy>{}, std::move(FSum.TypeTests),
std::move(FSum.TypeTestAssumeVCalls),
static void output(IO &io, GlobalValueSummaryMapTy &V) {
for (auto &P : V) {
std::vector<FunctionSummaryYaml> FSums;
- for (auto &Sum : P.second.SummaryList) {
+ for (auto &Sum : P.second) {
if (auto *FSum = dyn_cast<FunctionSummary>(Sum.get()))
FSums.push_back(FunctionSummaryYaml{
FSum->type_tests(), FSum->type_test_assume_vcalls(),
// 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(ModuleSummaryIndex &Index, const User *CurUser,
- SetVector<ValueInfo> &RefEdges,
+static void findRefEdges(const User *CurUser, SetVector<ValueInfo> &RefEdges,
SmallPtrSet<const User *, 8> &Visited) {
SmallVector<const User *, 32> Worklist;
Worklist.push_back(CurUser);
// 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(Index.getOrInsertValueInfo(GV));
+ RefEdges.insert(GV);
continue;
}
Worklist.push_back(Operand);
if (isa<DbgInfoIntrinsic>(I))
continue;
++NumInsts;
- findRefEdges(Index, &I, RefEdges, Visited);
+ findRefEdges(&I, RefEdges, Visited);
auto CS = ImmutableCallSite(&I);
if (!CS)
continue;
// to record the call edge to the alias in that case. Eventually
// an alias summary will be created to associate the alias and
// aliasee.
- CallGraphEdges[Index.getOrInsertValueInfo(
- cast<GlobalValue>(CalledValue))]
- .updateHotness(Hotness);
+ CallGraphEdges[cast<GlobalValue>(CalledValue)].updateHotness(Hotness);
} else {
// Skip inline assembly calls.
if (CI && CI->isInlineAsm())
ICallAnalysis.getPromotionCandidatesForInstruction(
&I, NumVals, TotalCount, NumCandidates);
for (auto &Candidate : CandidateProfileData)
- CallGraphEdges[Index.getOrInsertValueInfo(Candidate.Value)]
- .updateHotness(getHotness(Candidate.Count, PSI));
+ CallGraphEdges[Candidate.Value].updateHotness(
+ getHotness(Candidate.Count, PSI));
}
}
// Explicit add hot edges to enforce importing for designated GUIDs for
// sample PGO, to enable the same inlines as the profiled optimized binary.
for (auto &I : F.getImportGUIDs())
- CallGraphEdges[Index.getOrInsertValueInfo(I)].updateHotness(
- CalleeInfo::HotnessType::Hot);
+ CallGraphEdges[I].updateHotness(CalleeInfo::HotnessType::Hot);
bool NonRenamableLocal = isNonRenamableLocal(F);
bool NotEligibleForImport =
DenseSet<GlobalValue::GUID> &CantBePromoted) {
SetVector<ValueInfo> RefEdges;
SmallPtrSet<const User *, 8> Visited;
- findRefEdges(Index, &V, RefEdges, Visited);
+ findRefEdges(&V, RefEdges, Visited);
bool NonRenamableLocal = isNonRenamableLocal(V);
GlobalValueSummary::GVFlags Flags(V.getLinkage(), NonRenamableLocal,
/* LiveRoot = */ false);
// Set LiveRoot flag on entries matching the given value name.
static void setLiveRoot(ModuleSummaryIndex &Index, StringRef Name) {
- if (ValueInfo VI = Index.getValueInfo(GlobalValue::getGUID(Name)))
- for (auto &Summary : VI.getSummaryList())
- Summary->setLiveRoot();
+ auto SummaryList =
+ Index.findGlobalValueSummaryList(GlobalValue::getGUID(Name));
+ if (SummaryList == Index.end())
+ return;
+ for (auto &Summary : SummaryList->second)
+ Summary->setLiveRoot();
}
ModuleSummaryIndex llvm::buildModuleSummaryIndex(
}
for (auto &GlobalList : Index) {
- // Ignore entries for references that are undefined in the current module.
- if (GlobalList.second.SummaryList.empty())
- continue;
-
- assert(GlobalList.second.SummaryList.size() == 1 &&
+ assert(GlobalList.second.size() == 1 &&
"Expected module's index to have one summary per GUID");
- auto &Summary = GlobalList.second.SummaryList[0];
+ auto &Summary = GlobalList.second[0];
bool AllRefsCanBeExternallyReferenced =
llvm::all_of(Summary->refs(), [&](const ValueInfo &VI) {
- return !CantBePromoted.count(VI.getGUID());
+ return !CantBePromoted.count(VI.getValue()->getGUID());
});
if (!AllRefsCanBeExternallyReferenced) {
Summary->setNotEligibleToImport();
if (auto *FuncSummary = dyn_cast<FunctionSummary>(Summary.get())) {
bool AllCallsCanBeExternallyReferenced = llvm::all_of(
FuncSummary->calls(), [&](const FunctionSummary::EdgeTy &Edge) {
- return !CantBePromoted.count(Edge.first.getGUID());
+ auto GUID = Edge.first.isGUID() ? Edge.first.getGUID()
+ : Edge.first.getValue()->getGUID();
+ return !CantBePromoted.count(GUID);
});
if (!AllCallsCanBeExternallyReferenced)
Summary->setNotEligibleToImport();
/// Used to enable on-demand parsing of the VST.
uint64_t VSTOffset = 0;
- // Map to save ValueId to ValueInfo association that was recorded in the
+ // Map to save ValueId to GUID association that was recorded in the
// ValueSymbolTable. It is used after the VST is parsed to convert
// call graph edges read from the function summary from referencing
- // callees by their ValueId to using the ValueInfo instead, which is how
+ // callees by their ValueId to using the GUID instead, which is how
// they are recorded in the summary index being built.
- // We save a GUID which refers to the same global as the ValueInfo, but
- // ignoring the linkage, i.e. for values other than local linkage they are
- // identical.
- DenseMap<unsigned, std::pair<ValueInfo, GlobalValue::GUID>>
- ValueIdToValueInfoMap;
+ // We save a second GUID which is the same as the first one, but ignoring the
+ // linkage, i.e. for value other than local linkage they are identical.
+ DenseMap<unsigned, std::pair<GlobalValue::GUID, GlobalValue::GUID>>
+ ValueIdToCallGraphGUIDMap;
/// Map populated during module path string table parsing, from the
/// module ID to a string reference owned by the index's module
Error parseEntireSummary();
Error parseModuleStringTable();
- std::pair<ValueInfo, GlobalValue::GUID>
- getValueInfoFromValueId(unsigned ValueId);
+ std::pair<GlobalValue::GUID, GlobalValue::GUID>
+ getGUIDFromValueId(unsigned ValueId);
ModulePathStringTableTy::iterator addThisModulePath();
};
return TheIndex.addModulePath(ModulePath, ModuleId);
}
-std::pair<ValueInfo, GlobalValue::GUID>
-ModuleSummaryIndexBitcodeReader::getValueInfoFromValueId(unsigned ValueId) {
- auto VGI = ValueIdToValueInfoMap[ValueId];
- assert(VGI.first);
- return VGI;
+std::pair<GlobalValue::GUID, GlobalValue::GUID>
+ModuleSummaryIndexBitcodeReader::getGUIDFromValueId(unsigned ValueId) {
+ auto VGI = ValueIdToCallGraphGUIDMap.find(ValueId);
+ assert(VGI != ValueIdToCallGraphGUIDMap.end());
+ return VGI->second;
}
void ModuleSummaryIndexBitcodeReader::setValueGUID(
if (PrintSummaryGUIDs)
dbgs() << "GUID " << ValueGUID << "(" << OriginalNameID << ") is "
<< ValueName << "\n";
- ValueIdToValueInfoMap[ValueID] =
- std::make_pair(TheIndex.getOrInsertValueInfo(ValueGUID), OriginalNameID);
+ ValueIdToCallGraphGUIDMap[ValueID] =
+ std::make_pair(ValueGUID, OriginalNameID);
}
// Specialized value symbol table parser used when reading module index
GlobalValue::GUID RefGUID = Record[1];
// The "original name", which is the second value of the pair will be
// overriden later by a FS_COMBINED_ORIGINAL_NAME in the combined index.
- ValueIdToValueInfoMap[ValueID] =
- std::make_pair(TheIndex.getOrInsertValueInfo(RefGUID), RefGUID);
+ ValueIdToCallGraphGUIDMap[ValueID] = std::make_pair(RefGUID, RefGUID);
break;
}
}
std::vector<ValueInfo> Ret;
Ret.reserve(Record.size());
for (uint64_t RefValueId : Record)
- Ret.push_back(getValueInfoFromValueId(RefValueId).first);
+ Ret.push_back(getGUIDFromValueId(RefValueId).first);
return Ret;
}
Ret.reserve(Record.size());
for (unsigned I = 0, E = Record.size(); I != E; ++I) {
CalleeInfo::HotnessType Hotness = CalleeInfo::HotnessType::Unknown;
- ValueInfo Callee = getValueInfoFromValueId(Record[I]).first;
+ 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{Callee, CalleeInfo{Hotness}});
+ Ret.push_back(FunctionSummary::EdgeTy{CalleeGUID, CalleeInfo{Hotness}});
}
return Ret;
}
case bitc::FS_VALUE_GUID: { // [valueid, refguid]
uint64_t ValueID = Record[0];
GlobalValue::GUID RefGUID = Record[1];
- ValueIdToValueInfoMap[ValueID] =
- std::make_pair(TheIndex.getOrInsertValueInfo(RefGUID), RefGUID);
+ ValueIdToCallGraphGUIDMap[ValueID] = std::make_pair(RefGUID, RefGUID);
break;
}
// FS_PERMODULE: [valueid, flags, instcount, numrefs, numrefs x valueid,
PendingTypeCheckedLoadVCalls.clear();
PendingTypeTestAssumeConstVCalls.clear();
PendingTypeCheckedLoadConstVCalls.clear();
- auto VIAndOriginalGUID = getValueInfoFromValueId(ValueID);
+ auto GUID = getGUIDFromValueId(ValueID);
FS->setModulePath(addThisModulePath()->first());
- FS->setOriginalName(VIAndOriginalGUID.second);
- TheIndex.addGlobalValueSummary(VIAndOriginalGUID.first, std::move(FS));
+ FS->setOriginalName(GUID.second);
+ TheIndex.addGlobalValueSummary(GUID.first, std::move(FS));
break;
}
// FS_ALIAS: [valueid, flags, valueid]
// ownership.
AS->setModulePath(addThisModulePath()->first());
- GlobalValue::GUID AliaseeGUID =
- getValueInfoFromValueId(AliaseeID).first.getGUID();
+ GlobalValue::GUID AliaseeGUID = getGUIDFromValueId(AliaseeID).first;
auto AliaseeInModule =
TheIndex.findSummaryInModule(AliaseeGUID, ModulePath);
if (!AliaseeInModule)
return error("Alias expects aliasee summary to be parsed");
AS->setAliasee(AliaseeInModule);
- auto GUID = getValueInfoFromValueId(ValueID);
+ auto GUID = getGUIDFromValueId(ValueID);
AS->setOriginalName(GUID.second);
TheIndex.addGlobalValueSummary(GUID.first, std::move(AS));
break;
makeRefList(ArrayRef<uint64_t>(Record).slice(2));
auto FS = llvm::make_unique<GlobalVarSummary>(Flags, std::move(Refs));
FS->setModulePath(addThisModulePath()->first());
- auto GUID = getValueInfoFromValueId(ValueID);
+ auto GUID = getGUIDFromValueId(ValueID);
FS->setOriginalName(GUID.second);
TheIndex.addGlobalValueSummary(GUID.first, std::move(FS));
break;
std::vector<FunctionSummary::EdgeTy> Edges = makeCallList(
ArrayRef<uint64_t>(Record).slice(CallGraphEdgeStartIndex),
IsOldProfileFormat, HasProfile);
- ValueInfo VI = getValueInfoFromValueId(ValueID).first;
+ GlobalValue::GUID GUID = getGUIDFromValueId(ValueID).first;
auto FS = llvm::make_unique<FunctionSummary>(
Flags, InstCount, std::move(Refs), std::move(Edges),
std::move(PendingTypeTests), std::move(PendingTypeTestAssumeVCalls),
PendingTypeTestAssumeConstVCalls.clear();
PendingTypeCheckedLoadConstVCalls.clear();
LastSeenSummary = FS.get();
- LastSeenGUID = VI.getGUID();
+ LastSeenGUID = GUID;
FS->setModulePath(ModuleIdMap[ModuleId]);
- TheIndex.addGlobalValueSummary(VI, std::move(FS));
+ TheIndex.addGlobalValueSummary(GUID, std::move(FS));
break;
}
// FS_COMBINED_ALIAS: [valueid, modid, flags, valueid]
LastSeenSummary = AS.get();
AS->setModulePath(ModuleIdMap[ModuleId]);
- auto AliaseeGUID =
- getValueInfoFromValueId(AliaseeValueId).first.getGUID();
+ auto AliaseeGUID = getGUIDFromValueId(AliaseeValueId).first;
auto AliaseeInModule =
TheIndex.findSummaryInModule(AliaseeGUID, AS->modulePath());
if (!AliaseeInModule)
return error("Alias expects aliasee summary to be parsed");
AS->setAliasee(AliaseeInModule);
- ValueInfo VI = getValueInfoFromValueId(ValueID).first;
- LastSeenGUID = VI.getGUID();
- TheIndex.addGlobalValueSummary(VI, std::move(AS));
+ GlobalValue::GUID GUID = getGUIDFromValueId(ValueID).first;
+ LastSeenGUID = GUID;
+ TheIndex.addGlobalValueSummary(GUID, std::move(AS));
break;
}
// FS_COMBINED_GLOBALVAR_INIT_REFS: [valueid, modid, flags, n x valueid]
auto FS = llvm::make_unique<GlobalVarSummary>(Flags, std::move(Refs));
LastSeenSummary = FS.get();
FS->setModulePath(ModuleIdMap[ModuleId]);
- ValueInfo VI = getValueInfoFromValueId(ValueID).first;
- LastSeenGUID = VI.getGUID();
- TheIndex.addGlobalValueSummary(VI, std::move(FS));
+ GlobalValue::GUID GUID = getGUIDFromValueId(ValueID).first;
+ LastSeenGUID = GUID;
+ TheIndex.addGlobalValueSummary(GUID, std::move(FS));
break;
}
// FS_COMBINED_ORIGINAL_NAME: [original_name]
return;
for (const auto &GUIDSummaryLists : *Index)
// Examine all summaries for this GUID.
- for (auto &Summary : GUIDSummaryLists.second.SummaryList)
+ for (auto &Summary : GUIDSummaryLists.second)
if (auto FS = dyn_cast<FunctionSummary>(Summary.get()))
// For each call in the function summary, see if the call
// is to a GUID (which means it is for an indirect call,
// otherwise we would have a Value for it). If so, synthesize
// a value id.
for (auto &CallEdge : FS->calls())
- if (!CallEdge.first.getValue())
+ if (CallEdge.first.isGUID())
assignValueId(CallEdge.first.getGUID());
}
}
// Helper to get the valueId for the type of value recorded in VI.
unsigned getValueId(ValueInfo VI) {
- if (!VI.getValue())
+ if (VI.isGUID())
return getValueId(VI.getGUID());
return VE.getValueID(VI.getValue());
}
Callback(Summary);
} else {
for (auto &Summaries : Index)
- for (auto &Summary : Summaries.second.SummaryList)
+ for (auto &Summary : Summaries.second)
Callback({Summaries.first, Summary.get()});
}
}
void ModuleBitcodeWriter::writeModuleLevelReferences(
const GlobalVariable &V, SmallVector<uint64_t, 64> &NameVals,
unsigned FSModRefsAbbrev) {
- auto VI = Index->getValueInfo(GlobalValue::getGUID(V.getName()));
- if (!VI || VI.getSummaryList().empty()) {
+ auto Summaries =
+ Index->findGlobalValueSummaryList(GlobalValue::getGUID(V.getName()));
+ if (Summaries == Index->end()) {
// Only declarations should not have a summary (a declaration might however
// have a summary if the def was in module level asm).
assert(V.isDeclaration());
return;
}
- auto *Summary = VI.getSummaryList()[0].get();
+ auto *Summary = Summaries->second.front().get();
NameVals.push_back(VE.getValueID(&V));
GlobalVarSummary *VS = cast<GlobalVarSummary>(Summary);
NameVals.push_back(getEncodedGVSummaryFlags(VS->flags()));
if (!F.hasName())
report_fatal_error("Unexpected anonymous function when writing summary");
- ValueInfo VI = Index->getValueInfo(GlobalValue::getGUID(F.getName()));
- if (!VI || VI.getSummaryList().empty()) {
+ auto Summaries =
+ Index->findGlobalValueSummaryList(GlobalValue::getGUID(F.getName()));
+ if (Summaries == Index->end()) {
// Only declarations should not have a summary (a declaration might
// however have a summary if the def was in module level asm).
assert(F.isDeclaration());
continue;
}
- auto *Summary = VI.getSummaryList()[0].get();
+ auto *Summary = Summaries->second.front().get();
writePerModuleFunctionSummaryRecord(NameVals, Summary, VE.getValueID(&F),
FSCallsAbbrev, FSCallsProfileAbbrev, F);
}
StringRef ModulePath, GVSummaryMapTy &GVSummaryMap) const {
for (auto &GlobalList : *this) {
auto GUID = GlobalList.first;
- for (auto &GlobSummary : GlobalList.second.SummaryList) {
+ for (auto &GlobSummary : GlobalList.second) {
auto *Summary = dyn_cast_or_null<FunctionSummary>(GlobSummary.get());
if (!Summary)
// Ignore global variable, focus on functions
StringMap<GVSummaryMapTy> &ModuleToDefinedGVSummaries) const {
for (auto &GlobalList : *this) {
auto GUID = GlobalList.first;
- for (auto &Summary : GlobalList.second.SummaryList) {
+ for (auto &Summary : GlobalList.second) {
ModuleToDefinedGVSummaries[Summary->modulePath()][GUID] = Summary.get();
}
}
GlobalValueSummary *
ModuleSummaryIndex::getGlobalValueSummary(uint64_t ValueGUID,
bool PerModuleIndex) const {
- auto VI = getValueInfo(ValueGUID);
- assert(VI && "GlobalValue not found in index");
- assert((!PerModuleIndex || VI.getSummaryList().size() == 1) &&
+ auto SummaryList = findGlobalValueSummaryList(ValueGUID);
+ assert(SummaryList != end() && "GlobalValue not found in index");
+ assert((!PerModuleIndex || SummaryList->second.size() == 1) &&
"Expected a single entry per global value in per-module index");
- auto &Summary = VI.getSummaryList()[0];
+ auto &Summary = SummaryList->second[0];
return Summary.get();
}
// when needed.
DenseSet<GlobalValueSummary *> GlobalInvolvedWithAlias;
for (auto &I : Index)
- for (auto &S : I.second.SummaryList)
+ for (auto &S : I.second)
if (auto AS = dyn_cast<AliasSummary>(S.get()))
GlobalInvolvedWithAlias.insert(&AS->getAliasee());
for (auto &I : Index)
- thinLTOResolveWeakForLinkerGUID(I.second.SummaryList, I.first,
- GlobalInvolvedWithAlias, isPrevailing,
- recordNewLinkage);
+ thinLTOResolveWeakForLinkerGUID(I.second, I.first, GlobalInvolvedWithAlias,
+ isPrevailing, recordNewLinkage);
}
static void thinLTOInternalizeAndPromoteGUID(
ModuleSummaryIndex &Index,
function_ref<bool(StringRef, GlobalValue::GUID)> isExported) {
for (auto &I : Index)
- thinLTOInternalizeAndPromoteGUID(I.second.SummaryList, I.first, isExported);
+ thinLTOInternalizeAndPromoteGUID(I.second, I.first, isExported);
}
// Requires a destructor for std::vector<InputModule>.
};
for (auto &I : Index) {
- if (HasMultipleCopies(I.second.SummaryList))
- PrevailingCopy[I.first] =
- getFirstDefinitionForLinker(I.second.SummaryList);
+ if (HasMultipleCopies(I.second))
+ PrevailingCopy[I.first] = getFirstDefinitionForLinker(I.second);
}
}
/// - [insert you fancy metric here]
static const GlobalValueSummary *
selectCallee(const ModuleSummaryIndex &Index,
- ArrayRef<std::unique_ptr<GlobalValueSummary>> CalleeSummaryList,
+ const GlobalValueSummaryList &CalleeSummaryList,
unsigned Threshold, StringRef CallerModulePath) {
auto It = llvm::find_if(
CalleeSummaryList,
return cast<GlobalValueSummary>(It->get());
}
+/// Return the summary for the function \p GUID that fits the \p Threshold, or
+/// null if there's no match.
+static const GlobalValueSummary *selectCallee(GlobalValue::GUID GUID,
+ unsigned Threshold,
+ const ModuleSummaryIndex &Index,
+ StringRef CallerModulePath) {
+ auto CalleeSummaryList = Index.findGlobalValueSummaryList(GUID);
+ if (CalleeSummaryList == Index.end())
+ return nullptr; // This function does not have a summary
+ return selectCallee(Index, CalleeSummaryList->second, Threshold,
+ CallerModulePath);
+}
+
using EdgeInfo = std::tuple<const FunctionSummary *, unsigned /* Threshold */,
GlobalValue::GUID>;
FunctionImporter::ImportMapTy &ImportList,
StringMap<FunctionImporter::ExportSetTy> *ExportLists = nullptr) {
for (auto &Edge : Summary.calls()) {
- ValueInfo VI = Edge.first;
- DEBUG(dbgs() << " edge -> " << VI.getGUID() << " Threshold:" << Threshold
- << "\n");
+ auto GUID = Edge.first.getGUID();
+ DEBUG(dbgs() << " edge -> " << GUID << " Threshold:" << Threshold << "\n");
- if (VI.getSummaryList().empty()) {
+ if (Index.findGlobalValueSummaryList(GUID) == Index.end()) {
// For SamplePGO, the indirect call targets for local functions will
// have its original name annotated in profile. We try to find the
// corresponding PGOFuncName as the GUID.
- auto GUID = Index.getGUIDFromOriginalID(VI.getGUID());
+ GUID = Index.getGUIDFromOriginalID(GUID);
if (GUID == 0)
continue;
- VI = Index.getValueInfo(GUID);
- if (!VI)
- continue;
}
- if (DefinedGVSummaries.count(VI.getGUID())) {
+ if (DefinedGVSummaries.count(GUID)) {
DEBUG(dbgs() << "ignored! Target already in destination module.\n");
continue;
}
const auto NewThreshold =
Threshold * GetBonusMultiplier(Edge.second.Hotness);
- auto *CalleeSummary = selectCallee(Index, VI.getSummaryList(), NewThreshold,
- Summary.modulePath());
+ auto *CalleeSummary =
+ selectCallee(GUID, NewThreshold, Index, Summary.modulePath());
if (!CalleeSummary) {
DEBUG(dbgs() << "ignored! No qualifying callee with summary found.\n");
continue;
const auto AdjThreshold = GetAdjustedThreshold(Threshold, IsHotCallsite);
auto ExportModulePath = ResolvedCalleeSummary->modulePath();
- auto &ProcessedThreshold = ImportList[ExportModulePath][VI.getGUID()];
+ auto &ProcessedThreshold = ImportList[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.
// Make exports in the source module.
if (ExportLists) {
auto &ExportList = (*ExportLists)[ExportModulePath];
- ExportList.insert(VI.getGUID());
+ ExportList.insert(GUID);
if (!PreviouslyImported) {
// This is the first time this function was exported from its source
// module, so mark all functions and globals it references as exported
}
// Insert the newly imported function to the worklist.
- Worklist.emplace_back(ResolvedCalleeSummary, AdjThreshold, VI.getGUID());
+ Worklist.emplace_back(ResolvedCalleeSummary, AdjThreshold, GUID);
}
}
if (GUIDPreservedSymbols.empty())
// Don't do anything when nothing is live, this is friendly with tests.
return DenseSet<GlobalValue::GUID>();
- DenseSet<ValueInfo> LiveSymbols;
- SmallVector<ValueInfo, 128> Worklist;
- Worklist.reserve(GUIDPreservedSymbols.size() * 2);
- for (auto GUID : GUIDPreservedSymbols) {
- ValueInfo VI = Index.getValueInfo(GUID);
- if (!VI)
- continue;
- DEBUG(dbgs() << "Live root: " << VI.getGUID() << "\n");
- LiveSymbols.insert(VI);
- Worklist.push_back(VI);
+ DenseSet<GlobalValue::GUID> LiveSymbols = GUIDPreservedSymbols;
+ SmallVector<GlobalValue::GUID, 128> Worklist;
+ Worklist.reserve(LiveSymbols.size() * 2);
+ for (auto GUID : LiveSymbols) {
+ DEBUG(dbgs() << "Live root: " << GUID << "\n");
+ Worklist.push_back(GUID);
}
// Add values flagged in the index as live roots to the worklist.
for (const auto &Entry : Index) {
bool IsLiveRoot = llvm::any_of(
- Entry.second.SummaryList,
+ Entry.second,
[&](const std::unique_ptr<llvm::GlobalValueSummary> &Summary) {
return Summary->liveRoot();
});
if (!IsLiveRoot)
continue;
DEBUG(dbgs() << "Live root (summary): " << Entry.first << "\n");
- Worklist.push_back(ValueInfo(&Entry));
+ Worklist.push_back(Entry.first);
}
while (!Worklist.empty()) {
- auto VI = Worklist.pop_back_val();
+ auto GUID = Worklist.pop_back_val();
+ auto It = Index.findGlobalValueSummaryList(GUID);
+ if (It == Index.end()) {
+ DEBUG(dbgs() << "Not in index: " << GUID << "\n");
+ continue;
+ }
// FIXME: we should only make the prevailing copy live here
- for (auto &Summary : VI.getSummaryList()) {
+ for (auto &Summary : It->second) {
for (auto Ref : Summary->refs()) {
- if (LiveSymbols.insert(Ref).second) {
- DEBUG(dbgs() << "Marking live (ref): " << Ref.getGUID() << "\n");
- Worklist.push_back(Ref);
+ auto RefGUID = Ref.getGUID();
+ if (LiveSymbols.insert(RefGUID).second) {
+ DEBUG(dbgs() << "Marking live (ref): " << RefGUID << "\n");
+ Worklist.push_back(RefGUID);
}
}
if (auto *FS = dyn_cast<FunctionSummary>(Summary.get())) {
for (auto Call : FS->calls()) {
- if (LiveSymbols.insert(Call.first).second) {
- DEBUG(dbgs() << "Marking live (call): " << Call.first.getGUID()
- << "\n");
- Worklist.push_back(Call.first);
+ auto CallGUID = Call.first.getGUID();
+ if (LiveSymbols.insert(CallGUID).second) {
+ DEBUG(dbgs() << "Marking live (call): " << CallGUID << "\n");
+ Worklist.push_back(CallGUID);
}
}
}
if (auto *AS = dyn_cast<AliasSummary>(Summary.get())) {
auto AliaseeGUID = AS->getAliasee().getOriginalName();
- ValueInfo AliaseeVI = Index.getValueInfo(AliaseeGUID);
- if (AliaseeVI && LiveSymbols.insert(AliaseeVI).second) {
+ if (LiveSymbols.insert(AliaseeGUID).second) {
DEBUG(dbgs() << "Marking live (alias): " << AliaseeGUID << "\n");
- Worklist.push_back(AliaseeVI);
+ Worklist.push_back(AliaseeGUID);
}
}
}
DeadSymbols.reserve(
std::min(Index.size(), Index.size() - LiveSymbols.size()));
for (auto &Entry : Index) {
- if (!LiveSymbols.count(ValueInfo(&Entry))) {
- DEBUG(dbgs() << "Marking dead: " << Entry.first << "\n");
- DeadSymbols.insert(Entry.first);
+ auto GUID = Entry.first;
+ if (!LiveSymbols.count(GUID)) {
+ DEBUG(dbgs() << "Marking dead: " << GUID << "\n");
+ DeadSymbols.insert(GUID);
}
}
DEBUG(dbgs() << LiveSymbols.size() << " symbols Live, and "
// is only enabled when testing importing via the 'opt' tool, which does
// not do the ThinLink that would normally determine what values to promote.
for (auto &I : *Index) {
- for (auto &S : I.second.SummaryList) {
+ for (auto &S : I.second) {
if (GlobalValue::isLocalLinkage(S->linkage()))
S->setLinkage(GlobalValue::ExternalLinkage);
}
}
for (auto &P : *ExportSummary) {
- for (auto &S : P.second.SummaryList) {
+ for (auto &S : P.second) {
auto *FS = dyn_cast<FunctionSummary>(S.get());
if (!FS)
continue;
}
for (auto &P : *ExportSummary) {
- for (auto &S : P.second.SummaryList) {
+ for (auto &S : P.second) {
auto *FS = dyn_cast<FunctionSummary>(S.get());
if (!FS)
continue;
// does not do the ThinLink that would normally determine what values to
// promote.
for (auto &I : *Index) {
- for (auto &S : I.second.SummaryList) {
+ for (auto &S : I.second) {
if (GlobalValue::isLocalLinkage(S->linkage()))
S->setLinkage(GlobalValue::ExternalLinkage);
}
unsigned Calls = 0, Refs = 0, Functions = 0, Alias = 0, Globals = 0;
for (auto &Summaries : *Index) {
- for (auto &Summary : Summaries.second.SummaryList) {
+ for (auto &Summary : Summaries.second) {
Refs += Summary->refs().size();
if (auto *FuncSummary = dyn_cast<FunctionSummary>(Summary.get())) {
Functions++;