aboutsummaryrefslogtreecommitdiff
path: root/include/llvm/IR/ModuleSummaryIndex.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/llvm/IR/ModuleSummaryIndex.h')
-rw-r--r--include/llvm/IR/ModuleSummaryIndex.h187
1 files changed, 151 insertions, 36 deletions
diff --git a/include/llvm/IR/ModuleSummaryIndex.h b/include/llvm/IR/ModuleSummaryIndex.h
index fdf3d4b5f1ce..a1acee494475 100644
--- a/include/llvm/IR/ModuleSummaryIndex.h
+++ b/include/llvm/IR/ModuleSummaryIndex.h
@@ -23,6 +23,7 @@
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/TinyPtrVector.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/Allocator.h"
@@ -99,6 +100,22 @@ struct CalleeInfo {
}
};
+inline const char *getHotnessName(CalleeInfo::HotnessType HT) {
+ switch (HT) {
+ case CalleeInfo::HotnessType::Unknown:
+ return "unknown";
+ case CalleeInfo::HotnessType::Cold:
+ return "cold";
+ case CalleeInfo::HotnessType::None:
+ return "none";
+ case CalleeInfo::HotnessType::Hot:
+ return "hot";
+ case CalleeInfo::HotnessType::Critical:
+ return "critical";
+ }
+ llvm_unreachable("invalid hotness");
+}
+
class GlobalValueSummary;
using GlobalValueSummaryList = std::vector<std::unique_ptr<GlobalValueSummary>>;
@@ -146,13 +163,13 @@ using GlobalValueSummaryMapTy =
/// Struct that holds a reference to a particular GUID in a global value
/// summary.
struct ValueInfo {
- PointerIntPair<const GlobalValueSummaryMapTy::value_type *, 1, bool>
- RefAndFlag;
+ PointerIntPair<const GlobalValueSummaryMapTy::value_type *, 2, int>
+ RefAndFlags;
ValueInfo() = default;
ValueInfo(bool HaveGVs, const GlobalValueSummaryMapTy::value_type *R) {
- RefAndFlag.setPointer(R);
- RefAndFlag.setInt(HaveGVs);
+ RefAndFlags.setPointer(R);
+ RefAndFlags.setInt(HaveGVs);
}
operator bool() const { return getRef(); }
@@ -172,10 +189,12 @@ struct ValueInfo {
: getRef()->second.U.Name;
}
- bool haveGVs() const { return RefAndFlag.getInt(); }
+ bool haveGVs() const { return RefAndFlags.getInt() & 0x1; }
+ bool isReadOnly() const { return RefAndFlags.getInt() & 0x2; }
+ void setReadOnly() { RefAndFlags.setInt(RefAndFlags.getInt() | 0x2); }
const GlobalValueSummaryMapTy::value_type *getRef() const {
- return RefAndFlag.getPointer();
+ return RefAndFlags.getPointer();
}
bool isDSOLocal() const;
@@ -391,6 +410,7 @@ public:
return const_cast<GlobalValueSummary &>(
static_cast<const AliasSummary *>(this)->getAliasee());
}
+ bool hasAliaseeGUID() const { return AliaseeGUID != 0; }
const GlobalValue::GUID &getAliaseeGUID() const {
assert(AliaseeGUID && "Unexpected missing aliasee GUID");
return AliaseeGUID;
@@ -460,13 +480,17 @@ public:
TypeCheckedLoadConstVCalls;
};
- /// Function attribute flags. Used to track if a function accesses memory,
- /// recurses or aliases.
+ /// Flags specific to function summaries.
struct FFlags {
+ // Function attribute flags. Used to track if a function accesses memory,
+ // recurses or aliases.
unsigned ReadNone : 1;
unsigned ReadOnly : 1;
unsigned NoRecurse : 1;
unsigned ReturnDoesNotAlias : 1;
+
+ // Indicate if the global value cannot be inlined.
+ unsigned NoInline : 1;
};
/// Create an empty FunctionSummary (with specified call edges).
@@ -477,8 +501,9 @@ public:
FunctionSummary::GVFlags(
GlobalValue::LinkageTypes::AvailableExternallyLinkage,
/*NotEligibleToImport=*/true, /*Live=*/true, /*IsLocal=*/false),
- 0, FunctionSummary::FFlags{}, std::vector<ValueInfo>(),
- std::move(Edges), std::vector<GlobalValue::GUID>(),
+ /*InsCount=*/0, FunctionSummary::FFlags{}, /*EntryCount=*/0,
+ std::vector<ValueInfo>(), std::move(Edges),
+ std::vector<GlobalValue::GUID>(),
std::vector<FunctionSummary::VFuncId>(),
std::vector<FunctionSummary::VFuncId>(),
std::vector<FunctionSummary::ConstVCall>(),
@@ -493,10 +518,14 @@ private:
/// during the initial compile step when the summary index is first built.
unsigned InstCount;
- /// Function attribute flags. Used to track if a function accesses memory,
- /// recurses or aliases.
+ /// Function summary specific flags.
FFlags FunFlags;
+ /// The synthesized entry count of the function.
+ /// This is only populated during ThinLink phase and remains unused while
+ /// generating per-module summaries.
+ uint64_t EntryCount = 0;
+
/// List of <CalleeValueInfo, CalleeInfo> call edge pairs from this function.
std::vector<EdgeTy> CallGraphEdgeList;
@@ -504,14 +533,15 @@ private:
public:
FunctionSummary(GVFlags Flags, unsigned NumInsts, FFlags FunFlags,
- std::vector<ValueInfo> Refs, std::vector<EdgeTy> CGEdges,
+ uint64_t EntryCount, std::vector<ValueInfo> Refs,
+ std::vector<EdgeTy> CGEdges,
std::vector<GlobalValue::GUID> TypeTests,
std::vector<VFuncId> TypeTestAssumeVCalls,
std::vector<VFuncId> TypeCheckedLoadVCalls,
std::vector<ConstVCall> TypeTestAssumeConstVCalls,
std::vector<ConstVCall> TypeCheckedLoadConstVCalls)
: GlobalValueSummary(FunctionKind, Flags, std::move(Refs)),
- InstCount(NumInsts), FunFlags(FunFlags),
+ InstCount(NumInsts), FunFlags(FunFlags), EntryCount(EntryCount),
CallGraphEdgeList(std::move(CGEdges)) {
if (!TypeTests.empty() || !TypeTestAssumeVCalls.empty() ||
!TypeCheckedLoadVCalls.empty() || !TypeTestAssumeConstVCalls.empty() ||
@@ -522,18 +552,26 @@ public:
std::move(TypeTestAssumeConstVCalls),
std::move(TypeCheckedLoadConstVCalls)});
}
+ // Gets the number of immutable refs in RefEdgeList
+ unsigned immutableRefCount() const;
/// Check if this is a function summary.
static bool classof(const GlobalValueSummary *GVS) {
return GVS->getSummaryKind() == FunctionKind;
}
- /// Get function attribute flags.
+ /// Get function summary flags.
FFlags fflags() const { return FunFlags; }
/// Get the instruction count recorded for this function.
unsigned instCount() const { return InstCount; }
+ /// Get the synthetic entry count for this function.
+ uint64_t entryCount() const { return EntryCount; }
+
+ /// Set the synthetic entry count for this function.
+ void setEntryCount(uint64_t EC) { EntryCount = EC; }
+
/// Return the list of <CalleeValueInfo, CalleeInfo> pairs.
ArrayRef<EdgeTy> calls() const { return CallGraphEdgeList; }
@@ -631,19 +669,30 @@ template <> struct DenseMapInfo<FunctionSummary::ConstVCall> {
/// Global variable summary information to aid decisions and
/// implementation of importing.
///
-/// Currently this doesn't add anything to the base \p GlobalValueSummary,
-/// but is a placeholder as additional info may be added to the summary
-/// for variables.
+/// Global variable summary has extra flag, telling if it is
+/// modified during the program run or not. This affects ThinLTO
+/// internalization
class GlobalVarSummary : public GlobalValueSummary {
-
public:
- GlobalVarSummary(GVFlags Flags, std::vector<ValueInfo> Refs)
- : GlobalValueSummary(GlobalVarKind, Flags, std::move(Refs)) {}
+ struct GVarFlags {
+ GVarFlags(bool ReadOnly = false) : ReadOnly(ReadOnly) {}
+
+ unsigned ReadOnly : 1;
+ } VarFlags;
+
+ GlobalVarSummary(GVFlags Flags, GVarFlags VarFlags,
+ std::vector<ValueInfo> Refs)
+ : GlobalValueSummary(GlobalVarKind, Flags, std::move(Refs)),
+ VarFlags(VarFlags) {}
/// Check if this is a global variable summary.
static bool classof(const GlobalValueSummary *GVS) {
return GVS->getSummaryKind() == GlobalVarKind;
}
+
+ GVarFlags varflags() const { return VarFlags; }
+ void setReadOnly(bool RO) { VarFlags.ReadOnly = RO; }
+ bool isReadOnly() const { return VarFlags.ReadOnly; }
};
struct TypeTestResolution {
@@ -737,6 +786,11 @@ using ModulePathStringTableTy = StringMap<std::pair<uint64_t, ModuleHash>>;
/// a particular module, and provide efficient access to their summary.
using GVSummaryMapTy = DenseMap<GlobalValue::GUID, GlobalValueSummary *>;
+/// Map of a type GUID to type id string and summary (multimap used
+/// in case of GUID conflicts).
+using TypeIdSummaryMapTy =
+ std::multimap<GlobalValue::GUID, std::pair<std::string, TypeIdSummary>>;
+
/// Class to hold module path string table and global value map,
/// and encapsulate methods for operating on them.
class ModuleSummaryIndex {
@@ -748,9 +802,9 @@ private:
/// Holds strings for combined index, mapping to the corresponding module ID.
ModulePathStringTableTy ModulePathStringTable;
- /// Mapping from type identifiers to summary information for that type
- /// identifier.
- std::map<std::string, TypeIdSummary> TypeIdMap;
+ /// Mapping from type identifier GUIDs to type identifier and its summary
+ /// information.
+ TypeIdSummaryMapTy TypeIdMap;
/// Mapping from original ID to GUID. If original ID can map to multiple
/// GUIDs, it will be mapped to 0.
@@ -761,6 +815,9 @@ private:
/// considered live.
bool WithGlobalValueDeadStripping = false;
+ /// Indicates that summary-based synthetic entry count propagation has run
+ bool HasSyntheticEntryCounts = false;
+
/// Indicates that distributed backend should skip compilation of the
/// module. Flag is suppose to be set by distributed ThinLTO indexing
/// when it detected that the module is not needed during the final
@@ -774,6 +831,13 @@ private:
/// union.
bool HaveGVs;
+ // True if the index was created for a module compiled with -fsplit-lto-unit.
+ bool EnableSplitLTOUnit;
+
+ // True if some of the modules were compiled with -fsplit-lto-unit and
+ // some were not. Set when the combined index is created during the thin link.
+ bool PartiallySplitLTOUnits = false;
+
std::set<std::string> CfiFunctionDefs;
std::set<std::string> CfiFunctionDecls;
@@ -793,7 +857,9 @@ private:
public:
// See HaveGVs variable comment.
- ModuleSummaryIndex(bool HaveGVs) : HaveGVs(HaveGVs), Saver(Alloc) {}
+ ModuleSummaryIndex(bool HaveGVs, bool EnableSplitLTOUnit = false)
+ : HaveGVs(HaveGVs), EnableSplitLTOUnit(EnableSplitLTOUnit), Saver(Alloc) {
+ }
bool haveGVs() const { return HaveGVs; }
@@ -873,6 +939,9 @@ public:
WithGlobalValueDeadStripping = true;
}
+ bool hasSyntheticEntryCounts() const { return HasSyntheticEntryCounts; }
+ void setHasSyntheticEntryCounts() { HasSyntheticEntryCounts = true; }
+
bool skipModuleByDistributedBackend() const {
return SkipModuleByDistributedBackend;
}
@@ -880,6 +949,12 @@ public:
SkipModuleByDistributedBackend = true;
}
+ bool enableSplitLTOUnit() const { return EnableSplitLTOUnit; }
+ void setEnableSplitLTOUnit() { EnableSplitLTOUnit = true; }
+
+ bool partiallySplitLTOUnits() const { return PartiallySplitLTOUnits; }
+ void setPartiallySplitLTOUnits() { PartiallySplitLTOUnits = true; }
+
bool isGlobalValueLive(const GlobalValueSummary *GVS) const {
return !WithGlobalValueDeadStripping || GVS->isLive();
}
@@ -905,7 +980,7 @@ public:
// Save a string in the Index. Use before passing Name to
// getOrInsertValueInfo when the string isn't owned elsewhere (e.g. on the
// module's Strtab).
- StringRef saveString(std::string String) { return Saver.save(String); }
+ StringRef saveString(StringRef String) { return Saver.save(String); }
/// Return a ValueInfo for \p GUID setting value \p Name.
ValueInfo getOrInsertValueInfo(GlobalValue::GUID GUID, StringRef Name) {
@@ -1063,23 +1138,29 @@ public:
return ModulePathStringTable.count(M.getModuleIdentifier());
}
- const std::map<std::string, TypeIdSummary> &typeIds() const {
- return TypeIdMap;
- }
+ const TypeIdSummaryMapTy &typeIds() const { return TypeIdMap; }
- /// This accessor should only be used when exporting because it can mutate the
- /// map.
+ /// Return an existing or new TypeIdSummary entry for \p TypeId.
+ /// This accessor can mutate the map and therefore should not be used in
+ /// the ThinLTO backends.
TypeIdSummary &getOrInsertTypeIdSummary(StringRef TypeId) {
- return TypeIdMap[TypeId];
+ auto TidIter = TypeIdMap.equal_range(GlobalValue::getGUID(TypeId));
+ for (auto It = TidIter.first; It != TidIter.second; ++It)
+ if (It->second.first == TypeId)
+ return It->second.second;
+ auto It = TypeIdMap.insert(
+ {GlobalValue::getGUID(TypeId), {TypeId, TypeIdSummary()}});
+ return It->second.second;
}
/// This returns either a pointer to the type id summary (if present in the
/// summary map) or null (if not present). This may be used when importing.
const TypeIdSummary *getTypeIdSummary(StringRef TypeId) const {
- auto I = TypeIdMap.find(TypeId);
- if (I == TypeIdMap.end())
- return nullptr;
- return &I->second;
+ auto TidIter = TypeIdMap.equal_range(GlobalValue::getGUID(TypeId));
+ for (auto It = TidIter.first; It != TidIter.second; ++It)
+ if (It->second.first == TypeId)
+ return &It->second.second;
+ return nullptr;
}
/// Collect for the given module the list of functions it defines
@@ -1103,11 +1184,15 @@ public:
/// Print out strongly connected components for debugging.
void dumpSCCs(raw_ostream &OS);
+
+ /// Analyze index and detect unmodified globals
+ void propagateConstants(const DenseSet<GlobalValue::GUID> &PreservedSymbols);
};
/// GraphTraits definition to build SCC for the index
template <> struct GraphTraits<ValueInfo> {
typedef ValueInfo NodeRef;
+ using EdgeRef = FunctionSummary::EdgeTy &;
static NodeRef valueInfoFromEdge(FunctionSummary::EdgeTy &P) {
return P.first;
@@ -1116,6 +1201,8 @@ template <> struct GraphTraits<ValueInfo> {
mapped_iterator<std::vector<FunctionSummary::EdgeTy>::iterator,
decltype(&valueInfoFromEdge)>;
+ using ChildEdgeIteratorType = std::vector<FunctionSummary::EdgeTy>::iterator;
+
static NodeRef getEntryNode(ValueInfo V) { return V; }
static ChildIteratorType child_begin(NodeRef N) {
@@ -1137,6 +1224,26 @@ template <> struct GraphTraits<ValueInfo> {
cast<FunctionSummary>(N.getSummaryList().front()->getBaseObject());
return ChildIteratorType(F->CallGraphEdgeList.end(), &valueInfoFromEdge);
}
+
+ static ChildEdgeIteratorType child_edge_begin(NodeRef N) {
+ if (!N.getSummaryList().size()) // handle external function
+ return FunctionSummary::ExternalNode.CallGraphEdgeList.begin();
+
+ FunctionSummary *F =
+ cast<FunctionSummary>(N.getSummaryList().front()->getBaseObject());
+ return F->CallGraphEdgeList.begin();
+ }
+
+ static ChildEdgeIteratorType child_edge_end(NodeRef N) {
+ if (!N.getSummaryList().size()) // handle external function
+ return FunctionSummary::ExternalNode.CallGraphEdgeList.end();
+
+ FunctionSummary *F =
+ cast<FunctionSummary>(N.getSummaryList().front()->getBaseObject());
+ return F->CallGraphEdgeList.end();
+ }
+
+ static NodeRef edge_dest(EdgeRef E) { return E.first; }
};
template <>
@@ -1152,6 +1259,14 @@ struct GraphTraits<ModuleSummaryIndex *> : public GraphTraits<ValueInfo> {
}
};
+static inline bool canImportGlobalVar(GlobalValueSummary *S) {
+ assert(isa<GlobalVarSummary>(S->getBaseObject()));
+
+ // We don't import GV with references, because it can result
+ // in promotion of local variables in the source module.
+ return !GlobalValue::isInterposableLinkage(S->linkage()) &&
+ !S->notEligibleToImport() && S->refs().empty();
+}
} // end namespace llvm
#endif // LLVM_IR_MODULESUMMARYINDEX_H