|
@@ -69,9 +69,27 @@ class GlobalValueSummary;
|
|
using GlobalValueSummaryList = std::vector<std::unique_ptr<GlobalValueSummary>>;
|
|
using GlobalValueSummaryList = std::vector<std::unique_ptr<GlobalValueSummary>>;
|
|
|
|
|
|
struct GlobalValueSummaryInfo {
|
|
struct GlobalValueSummaryInfo {
|
|
- /// The GlobalValue corresponding to this summary. This is only used in
|
|
|
|
- /// per-module summaries.
|
|
|
|
- const GlobalValue *GV = nullptr;
|
|
|
|
|
|
+ union NameOrGV {
|
|
|
|
+ NameOrGV(bool IsAnalysis) {
|
|
|
|
+ if (IsAnalysis)
|
|
|
|
+ GV = nullptr;
|
|
|
|
+ else
|
|
|
|
+ Name = "";
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /// The GlobalValue corresponding to this summary. This is only used in
|
|
|
|
+ /// per-module summaries, when module analysis is being run.
|
|
|
|
+ const GlobalValue *GV;
|
|
|
|
+
|
|
|
|
+ /// Summary string representation. This StringRef points to BC module
|
|
|
|
+ /// string table and is valid until module data is stored in memory.
|
|
|
|
+ /// This is guaranteed to happen until runThinLTOBackend function is
|
|
|
|
+ /// called, so it is safe to use this field during thin link. This field
|
|
|
|
+ /// is only valid if summary index was loaded from BC file.
|
|
|
|
+ StringRef Name;
|
|
|
|
+ } U;
|
|
|
|
+
|
|
|
|
+ GlobalValueSummaryInfo(bool IsAnalysis) : U(IsAnalysis) {}
|
|
|
|
|
|
/// List of global value summary structures for a particular value held
|
|
/// List of global value summary structures for a particular value held
|
|
/// in the GlobalValueMap. Requires a vector in the case of multiple
|
|
/// in the GlobalValueMap. Requires a vector in the case of multiple
|
|
@@ -91,32 +109,60 @@ using GlobalValueSummaryMapTy =
|
|
/// Struct that holds a reference to a particular GUID in a global value
|
|
/// Struct that holds a reference to a particular GUID in a global value
|
|
/// summary.
|
|
/// summary.
|
|
struct ValueInfo {
|
|
struct ValueInfo {
|
|
- const GlobalValueSummaryMapTy::value_type *Ref = nullptr;
|
|
|
|
|
|
+ PointerIntPair<const GlobalValueSummaryMapTy::value_type *, 1, bool>
|
|
|
|
+ RefAndFlag;
|
|
|
|
|
|
ValueInfo() = default;
|
|
ValueInfo() = default;
|
|
- ValueInfo(const GlobalValueSummaryMapTy::value_type *Ref) : Ref(Ref) {}
|
|
|
|
|
|
+ ValueInfo(bool IsAnalysis, const GlobalValueSummaryMapTy::value_type *R) {
|
|
|
|
+ RefAndFlag.setPointer(R);
|
|
|
|
+ RefAndFlag.setInt(IsAnalysis);
|
|
|
|
+ }
|
|
|
|
|
|
- operator bool() const { return Ref; }
|
|
|
|
|
|
+ operator bool() const { return getRef(); }
|
|
|
|
|
|
- GlobalValue::GUID getGUID() const { return Ref->first; }
|
|
|
|
- const GlobalValue *getValue() const { return Ref->second.GV; }
|
|
|
|
|
|
+ GlobalValue::GUID getGUID() const { return getRef()->first; }
|
|
|
|
+ const GlobalValue *getValue() const {
|
|
|
|
+ assert(isFromAnalysis());
|
|
|
|
+ return getRef()->second.U.GV;
|
|
|
|
+ }
|
|
|
|
|
|
ArrayRef<std::unique_ptr<GlobalValueSummary>> getSummaryList() const {
|
|
ArrayRef<std::unique_ptr<GlobalValueSummary>> getSummaryList() const {
|
|
- return Ref->second.SummaryList;
|
|
|
|
|
|
+ return getRef()->second.SummaryList;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ StringRef name() const {
|
|
|
|
+ return isFromAnalysis() ? getRef()->second.U.GV->getName()
|
|
|
|
+ : getRef()->second.U.Name;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ bool isFromAnalysis() const { return RefAndFlag.getInt(); }
|
|
|
|
+
|
|
|
|
+ const GlobalValueSummaryMapTy::value_type *getRef() const {
|
|
|
|
+ return RefAndFlag.getPointer();
|
|
}
|
|
}
|
|
};
|
|
};
|
|
|
|
|
|
template <> struct DenseMapInfo<ValueInfo> {
|
|
template <> struct DenseMapInfo<ValueInfo> {
|
|
static inline ValueInfo getEmptyKey() {
|
|
static inline ValueInfo getEmptyKey() {
|
|
- return ValueInfo((GlobalValueSummaryMapTy::value_type *)-1);
|
|
|
|
|
|
+ return ValueInfo(false, (GlobalValueSummaryMapTy::value_type *)-8);
|
|
}
|
|
}
|
|
|
|
|
|
static inline ValueInfo getTombstoneKey() {
|
|
static inline ValueInfo getTombstoneKey() {
|
|
- return ValueInfo((GlobalValueSummaryMapTy::value_type *)-2);
|
|
|
|
|
|
+ return ValueInfo(false, (GlobalValueSummaryMapTy::value_type *)-16);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ static inline bool isSpecialKey(ValueInfo V) {
|
|
|
|
+ return V == getTombstoneKey() || V == getEmptyKey();
|
|
}
|
|
}
|
|
|
|
|
|
- static bool isEqual(ValueInfo L, ValueInfo R) { return L.Ref == R.Ref; }
|
|
|
|
- static unsigned getHashValue(ValueInfo I) { return (uintptr_t)I.Ref; }
|
|
|
|
|
|
+ static bool isEqual(ValueInfo L, ValueInfo R) {
|
|
|
|
+ // We are not supposed to mix ValueInfo(s) with different analysis flag
|
|
|
|
+ // in a same container.
|
|
|
|
+ assert(isSpecialKey(L) || isSpecialKey(R) ||
|
|
|
|
+ (L.isFromAnalysis() == R.isFromAnalysis()));
|
|
|
|
+ return L.getRef() == R.getRef();
|
|
|
|
+ }
|
|
|
|
+ static unsigned getHashValue(ValueInfo I) { return (uintptr_t)I.getRef(); }
|
|
};
|
|
};
|
|
|
|
|
|
/// \brief Function and variable summary information to aid decisions and
|
|
/// \brief Function and variable summary information to aid decisions and
|
|
@@ -619,6 +665,11 @@ private:
|
|
/// considered live.
|
|
/// considered live.
|
|
bool WithGlobalValueDeadStripping = false;
|
|
bool WithGlobalValueDeadStripping = false;
|
|
|
|
|
|
|
|
+ /// If true then we're performing analysis of IR module, filling summary
|
|
|
|
+ /// accordingly. The value of 'false' means we're reading summary from
|
|
|
|
+ /// BC or YAML source. Affects the type of value stored in NameOrGV union
|
|
|
|
+ bool IsAnalysis;
|
|
|
|
+
|
|
std::set<std::string> CfiFunctionDefs;
|
|
std::set<std::string> CfiFunctionDefs;
|
|
std::set<std::string> CfiFunctionDecls;
|
|
std::set<std::string> CfiFunctionDecls;
|
|
|
|
|
|
@@ -627,10 +678,16 @@ private:
|
|
|
|
|
|
GlobalValueSummaryMapTy::value_type *
|
|
GlobalValueSummaryMapTy::value_type *
|
|
getOrInsertValuePtr(GlobalValue::GUID GUID) {
|
|
getOrInsertValuePtr(GlobalValue::GUID GUID) {
|
|
- return &*GlobalValueMap.emplace(GUID, GlobalValueSummaryInfo{}).first;
|
|
|
|
|
|
+ return &*GlobalValueMap.emplace(GUID, GlobalValueSummaryInfo(IsAnalysis)).first;
|
|
}
|
|
}
|
|
|
|
|
|
public:
|
|
public:
|
|
|
|
+ // See IsAnalysis variable comment.
|
|
|
|
+ ModuleSummaryIndex(bool IsPerformingAnalysis)
|
|
|
|
+ : IsAnalysis(IsPerformingAnalysis) {}
|
|
|
|
+
|
|
|
|
+ bool isPerformingAnalysis() const { return IsAnalysis; }
|
|
|
|
+
|
|
gvsummary_iterator begin() { return GlobalValueMap.begin(); }
|
|
gvsummary_iterator begin() { return GlobalValueMap.begin(); }
|
|
const_gvsummary_iterator begin() const { return GlobalValueMap.begin(); }
|
|
const_gvsummary_iterator begin() const { return GlobalValueMap.begin(); }
|
|
gvsummary_iterator end() { return GlobalValueMap.end(); }
|
|
gvsummary_iterator end() { return GlobalValueMap.end(); }
|
|
@@ -652,19 +709,28 @@ public:
|
|
/// Return a ValueInfo for GUID if it exists, otherwise return ValueInfo().
|
|
/// Return a ValueInfo for GUID if it exists, otherwise return ValueInfo().
|
|
ValueInfo getValueInfo(GlobalValue::GUID GUID) const {
|
|
ValueInfo getValueInfo(GlobalValue::GUID GUID) const {
|
|
auto I = GlobalValueMap.find(GUID);
|
|
auto I = GlobalValueMap.find(GUID);
|
|
- return ValueInfo(I == GlobalValueMap.end() ? nullptr : &*I);
|
|
|
|
|
|
+ return ValueInfo(IsAnalysis, I == GlobalValueMap.end() ? nullptr : &*I);
|
|
}
|
|
}
|
|
|
|
|
|
/// Return a ValueInfo for \p GUID.
|
|
/// Return a ValueInfo for \p GUID.
|
|
ValueInfo getOrInsertValueInfo(GlobalValue::GUID GUID) {
|
|
ValueInfo getOrInsertValueInfo(GlobalValue::GUID GUID) {
|
|
- return ValueInfo(getOrInsertValuePtr(GUID));
|
|
|
|
|
|
+ return ValueInfo(IsAnalysis, getOrInsertValuePtr(GUID));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /// Return a ValueInfo for \p GUID setting value \p Name.
|
|
|
|
+ ValueInfo getOrInsertValueInfo(GlobalValue::GUID GUID, StringRef Name) {
|
|
|
|
+ assert(!IsAnalysis);
|
|
|
|
+ auto VP = getOrInsertValuePtr(GUID);
|
|
|
|
+ VP->second.U.Name = Name;
|
|
|
|
+ return ValueInfo(IsAnalysis, VP);
|
|
}
|
|
}
|
|
|
|
|
|
/// Return a ValueInfo for \p GV and mark it as belonging to GV.
|
|
/// Return a ValueInfo for \p GV and mark it as belonging to GV.
|
|
ValueInfo getOrInsertValueInfo(const GlobalValue *GV) {
|
|
ValueInfo getOrInsertValueInfo(const GlobalValue *GV) {
|
|
|
|
+ assert(IsAnalysis);
|
|
auto VP = getOrInsertValuePtr(GV->getGUID());
|
|
auto VP = getOrInsertValuePtr(GV->getGUID());
|
|
- VP->second.GV = GV;
|
|
|
|
- return ValueInfo(VP);
|
|
|
|
|
|
+ VP->second.U.GV = GV;
|
|
|
|
+ return ValueInfo(IsAnalysis, VP);
|
|
}
|
|
}
|
|
|
|
|
|
/// Return the GUID for \p OriginalId in the OidGuidMap.
|
|
/// Return the GUID for \p OriginalId in the OidGuidMap.
|
|
@@ -692,7 +758,7 @@ public:
|
|
addOriginalName(VI.getGUID(), Summary->getOriginalName());
|
|
addOriginalName(VI.getGUID(), Summary->getOriginalName());
|
|
// Here we have a notionally const VI, but the value it points to is owned
|
|
// Here we have a notionally const VI, but the value it points to is owned
|
|
// by the non-const *this.
|
|
// by the non-const *this.
|
|
- const_cast<GlobalValueSummaryMapTy::value_type *>(VI.Ref)
|
|
|
|
|
|
+ const_cast<GlobalValueSummaryMapTy::value_type *>(VI.getRef())
|
|
->second.SummaryList.push_back(std::move(Summary));
|
|
->second.SummaryList.push_back(std::move(Summary));
|
|
}
|
|
}
|
|
|
|
|
|
@@ -823,6 +889,9 @@ public:
|
|
/// Summary).
|
|
/// Summary).
|
|
void collectDefinedGVSummariesPerModule(
|
|
void collectDefinedGVSummariesPerModule(
|
|
StringMap<GVSummaryMapTy> &ModuleToDefinedGVSummaries) const;
|
|
StringMap<GVSummaryMapTy> &ModuleToDefinedGVSummaries) const;
|
|
|
|
+
|
|
|
|
+ /// Export summary to dot file for GraphViz.
|
|
|
|
+ void exportToDot(raw_ostream& OS) const;
|
|
};
|
|
};
|
|
|
|
|
|
} // end namespace llvm
|
|
} // end namespace llvm
|