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.h253
1 files changed, 207 insertions, 46 deletions
diff --git a/include/llvm/IR/ModuleSummaryIndex.h b/include/llvm/IR/ModuleSummaryIndex.h
index a1acee494475..aacf8cfc089f 100644
--- a/include/llvm/IR/ModuleSummaryIndex.h
+++ b/include/llvm/IR/ModuleSummaryIndex.h
@@ -1,9 +1,8 @@
//===- llvm/ModuleSummaryIndex.h - Module Summary Index ---------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -120,7 +119,7 @@ class GlobalValueSummary;
using GlobalValueSummaryList = std::vector<std::unique_ptr<GlobalValueSummary>>;
-struct GlobalValueSummaryInfo {
+struct LLVM_ALIGNAS(8) GlobalValueSummaryInfo {
union NameOrGV {
NameOrGV(bool HaveGVs) {
if (HaveGVs)
@@ -163,7 +162,8 @@ using GlobalValueSummaryMapTy =
/// Struct that holds a reference to a particular GUID in a global value
/// summary.
struct ValueInfo {
- PointerIntPair<const GlobalValueSummaryMapTy::value_type *, 2, int>
+ enum Flags { HaveGV = 1, ReadOnly = 2, WriteOnly = 4 };
+ PointerIntPair<const GlobalValueSummaryMapTy::value_type *, 3, int>
RefAndFlags;
ValueInfo() = default;
@@ -189,15 +189,42 @@ struct ValueInfo {
: getRef()->second.U.Name;
}
- bool haveGVs() const { return RefAndFlags.getInt() & 0x1; }
- bool isReadOnly() const { return RefAndFlags.getInt() & 0x2; }
- void setReadOnly() { RefAndFlags.setInt(RefAndFlags.getInt() | 0x2); }
+ bool haveGVs() const { return RefAndFlags.getInt() & HaveGV; }
+ bool isReadOnly() const {
+ assert(isValidAccessSpecifier());
+ return RefAndFlags.getInt() & ReadOnly;
+ }
+ bool isWriteOnly() const {
+ assert(isValidAccessSpecifier());
+ return RefAndFlags.getInt() & WriteOnly;
+ }
+ unsigned getAccessSpecifier() const {
+ assert(isValidAccessSpecifier());
+ return RefAndFlags.getInt() & (ReadOnly | WriteOnly);
+ }
+ bool isValidAccessSpecifier() const {
+ unsigned BadAccessMask = ReadOnly | WriteOnly;
+ return (RefAndFlags.getInt() & BadAccessMask) != BadAccessMask;
+ }
+ void setReadOnly() {
+ // We expect ro/wo attribute to set only once during
+ // ValueInfo lifetime.
+ assert(getAccessSpecifier() == 0);
+ RefAndFlags.setInt(RefAndFlags.getInt() | ReadOnly);
+ }
+ void setWriteOnly() {
+ assert(getAccessSpecifier() == 0);
+ RefAndFlags.setInt(RefAndFlags.getInt() | WriteOnly);
+ }
const GlobalValueSummaryMapTy::value_type *getRef() const {
return RefAndFlags.getPointer();
}
bool isDSOLocal() const;
+
+ /// Checks if all copies are eligible for auto-hiding (have flag set).
+ bool canAutoHide() const;
};
inline raw_ostream &operator<<(raw_ostream &OS, const ValueInfo &VI) {
@@ -280,11 +307,23 @@ public:
/// within the same linkage unit.
unsigned DSOLocal : 1;
+ /// In the per-module summary, indicates that the global value is
+ /// linkonce_odr and global unnamed addr (so eligible for auto-hiding
+ /// via hidden visibility). In the combined summary, indicates that the
+ /// prevailing linkonce_odr copy can be auto-hidden via hidden visibility
+ /// when it is upgraded to weak_odr in the backend. This is legal when
+ /// all copies are eligible for auto-hiding (i.e. all copies were
+ /// linkonce_odr global unnamed addr. If any copy is not (e.g. it was
+ /// originally weak_odr, we cannot auto-hide the prevailing copy as it
+ /// means the symbol was externally visible.
+ unsigned CanAutoHide : 1;
+
/// Convenience Constructors
explicit GVFlags(GlobalValue::LinkageTypes Linkage,
- bool NotEligibleToImport, bool Live, bool IsLocal)
+ bool NotEligibleToImport, bool Live, bool IsLocal,
+ bool CanAutoHide)
: Linkage(Linkage), NotEligibleToImport(NotEligibleToImport),
- Live(Live), DSOLocal(IsLocal) {}
+ Live(Live), DSOLocal(IsLocal), CanAutoHide(CanAutoHide) {}
};
private:
@@ -365,6 +404,10 @@ public:
bool isDSOLocal() const { return Flags.DSOLocal; }
+ void setCanAutoHide(bool CanAutoHide) { Flags.CanAutoHide = CanAutoHide; }
+
+ bool canAutoHide() const { return Flags.CanAutoHide; }
+
/// Flag that this global value cannot be imported.
void setNotEligibleToImport() { Flags.NotEligibleToImport = true; }
@@ -381,25 +424,35 @@ public:
/// Alias summary information.
class AliasSummary : public GlobalValueSummary {
+ ValueInfo AliaseeValueInfo;
+
+ /// This is the Aliasee in the same module as alias (could get from VI, trades
+ /// memory for time). Note that this pointer may be null (and the value info
+ /// empty) when we have a distributed index where the alias is being imported
+ /// (as a copy of the aliasee), but the aliasee is not.
GlobalValueSummary *AliaseeSummary;
- // AliaseeGUID is only set and accessed when we are building a combined index
- // via the BitcodeReader.
- GlobalValue::GUID AliaseeGUID;
public:
AliasSummary(GVFlags Flags)
: GlobalValueSummary(AliasKind, Flags, ArrayRef<ValueInfo>{}),
- AliaseeSummary(nullptr), AliaseeGUID(0) {}
+ AliaseeSummary(nullptr) {}
/// Check if this is an alias summary.
static bool classof(const GlobalValueSummary *GVS) {
return GVS->getSummaryKind() == AliasKind;
}
- void setAliasee(GlobalValueSummary *Aliasee) { AliaseeSummary = Aliasee; }
- void setAliaseeGUID(GlobalValue::GUID GUID) { AliaseeGUID = GUID; }
+ void setAliasee(ValueInfo &AliaseeVI, GlobalValueSummary *Aliasee) {
+ AliaseeValueInfo = AliaseeVI;
+ AliaseeSummary = Aliasee;
+ }
- bool hasAliasee() const { return !!AliaseeSummary; }
+ bool hasAliasee() const {
+ assert(!!AliaseeSummary == (AliaseeValueInfo &&
+ !AliaseeValueInfo.getSummaryList().empty()) &&
+ "Expect to have both aliasee summary and summary list or neither");
+ return !!AliaseeSummary;
+ }
const GlobalValueSummary &getAliasee() const {
assert(AliaseeSummary && "Unexpected missing aliasee summary");
@@ -410,10 +463,13 @@ 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;
+ ValueInfo getAliaseeVI() const {
+ assert(AliaseeValueInfo && "Unexpected missing aliasee");
+ return AliaseeValueInfo;
+ }
+ GlobalValue::GUID getAliaseeGUID() const {
+ assert(AliaseeValueInfo && "Unexpected missing aliasee");
+ return AliaseeValueInfo.getGUID();
}
};
@@ -500,7 +556,8 @@ public:
return FunctionSummary(
FunctionSummary::GVFlags(
GlobalValue::LinkageTypes::AvailableExternallyLinkage,
- /*NotEligibleToImport=*/true, /*Live=*/true, /*IsLocal=*/false),
+ /*NotEligibleToImport=*/true, /*Live=*/true, /*IsLocal=*/false,
+ /*CanAutoHide=*/false),
/*InsCount=*/0, FunctionSummary::FFlags{}, /*EntryCount=*/0,
std::vector<ValueInfo>(), std::move(Edges),
std::vector<GlobalValue::GUID>(),
@@ -552,8 +609,8 @@ public:
std::move(TypeTestAssumeConstVCalls),
std::move(TypeCheckedLoadConstVCalls)});
}
- // Gets the number of immutable refs in RefEdgeList
- unsigned immutableRefCount() const;
+ // Gets the number of readonly and writeonly refs in RefEdgeList
+ std::pair<unsigned, unsigned> specialRefCounts() const;
/// Check if this is a function summary.
static bool classof(const GlobalValueSummary *GVS) {
@@ -666,18 +723,43 @@ template <> struct DenseMapInfo<FunctionSummary::ConstVCall> {
}
};
+/// The ValueInfo and offset for a function within a vtable definition
+/// initializer array.
+struct VirtFuncOffset {
+ VirtFuncOffset(ValueInfo VI, uint64_t Offset)
+ : FuncVI(VI), VTableOffset(Offset) {}
+
+ ValueInfo FuncVI;
+ uint64_t VTableOffset;
+};
+/// List of functions referenced by a particular vtable definition.
+using VTableFuncList = std::vector<VirtFuncOffset>;
+
/// Global variable summary information to aid decisions and
/// implementation of importing.
///
-/// Global variable summary has extra flag, telling if it is
-/// modified during the program run or not. This affects ThinLTO
-/// internalization
+/// Global variable summary has two extra flag, telling if it is
+/// readonly or writeonly. Both readonly and writeonly variables
+/// can be optimized in the backed: readonly variables can be
+/// const-folded, while writeonly vars can be completely eliminated
+/// together with corresponding stores. We let both things happen
+/// by means of internalizing such variables after ThinLTO import.
class GlobalVarSummary : public GlobalValueSummary {
+private:
+ /// For vtable definitions this holds the list of functions and
+ /// their corresponding offsets within the initializer array.
+ std::unique_ptr<VTableFuncList> VTableFuncs;
+
public:
struct GVarFlags {
- GVarFlags(bool ReadOnly = false) : ReadOnly(ReadOnly) {}
-
- unsigned ReadOnly : 1;
+ GVarFlags(bool ReadOnly, bool WriteOnly)
+ : MaybeReadOnly(ReadOnly), MaybeWriteOnly(WriteOnly) {}
+
+ // In permodule summaries both MaybeReadOnly and MaybeWriteOnly
+ // bits are set, because attribute propagation occurs later on
+ // thin link phase.
+ unsigned MaybeReadOnly : 1;
+ unsigned MaybeWriteOnly : 1;
} VarFlags;
GlobalVarSummary(GVFlags Flags, GVarFlags VarFlags,
@@ -691,8 +773,21 @@ public:
}
GVarFlags varflags() const { return VarFlags; }
- void setReadOnly(bool RO) { VarFlags.ReadOnly = RO; }
- bool isReadOnly() const { return VarFlags.ReadOnly; }
+ void setReadOnly(bool RO) { VarFlags.MaybeReadOnly = RO; }
+ void setWriteOnly(bool WO) { VarFlags.MaybeWriteOnly = WO; }
+ bool maybeReadOnly() const { return VarFlags.MaybeReadOnly; }
+ bool maybeWriteOnly() const { return VarFlags.MaybeWriteOnly; }
+
+ void setVTableFuncs(VTableFuncList Funcs) {
+ assert(!VTableFuncs);
+ VTableFuncs = llvm::make_unique<VTableFuncList>(std::move(Funcs));
+ }
+
+ ArrayRef<VirtFuncOffset> vTableFuncs() const {
+ if (VTableFuncs)
+ return *VTableFuncs;
+ return {};
+ }
};
struct TypeTestResolution {
@@ -791,6 +886,29 @@ using GVSummaryMapTy = DenseMap<GlobalValue::GUID, GlobalValueSummary *>;
using TypeIdSummaryMapTy =
std::multimap<GlobalValue::GUID, std::pair<std::string, TypeIdSummary>>;
+/// The following data structures summarize type metadata information.
+/// For type metadata overview see https://llvm.org/docs/TypeMetadata.html.
+/// Each type metadata includes both the type identifier and the offset of
+/// the address point of the type (the address held by objects of that type
+/// which may not be the beginning of the virtual table). Vtable definitions
+/// are decorated with type metadata for the types they are compatible with.
+///
+/// Holds information about vtable definitions decorated with type metadata:
+/// the vtable definition value and its address point offset in a type
+/// identifier metadata it is decorated (compatible) with.
+struct TypeIdOffsetVtableInfo {
+ TypeIdOffsetVtableInfo(uint64_t Offset, ValueInfo VI)
+ : AddressPointOffset(Offset), VTableVI(VI) {}
+
+ uint64_t AddressPointOffset;
+ ValueInfo VTableVI;
+};
+/// List of vtable definitions decorated by a particular type identifier,
+/// and their corresponding offsets in that type identifier's metadata.
+/// Note that each type identifier may be compatible with multiple vtables, due
+/// to inheritance, which is why this is a vector.
+using TypeIdCompatibleVtableInfo = std::vector<TypeIdOffsetVtableInfo>;
+
/// Class to hold module path string table and global value map,
/// and encapsulate methods for operating on them.
class ModuleSummaryIndex {
@@ -803,9 +921,15 @@ private:
ModulePathStringTableTy ModulePathStringTable;
/// Mapping from type identifier GUIDs to type identifier and its summary
- /// information.
+ /// information. Produced by thin link.
TypeIdSummaryMapTy TypeIdMap;
+ /// Mapping from type identifier to information about vtables decorated
+ /// with that type identifier's metadata. Produced by per module summary
+ /// analysis and consumed by thin link. For more information, see description
+ /// above where TypeIdCompatibleVtableInfo is defined.
+ std::map<std::string, TypeIdCompatibleVtableInfo> TypeIdCompatibleVtableMap;
+
/// Mapping from original ID to GUID. If original ID can map to multiple
/// GUIDs, it will be mapped to 0.
std::map<GlobalValue::GUID, GlobalValue::GUID> OidGuidMap;
@@ -1044,24 +1168,30 @@ public:
OidGuidMap[OrigGUID] = ValueGUID;
}
- /// Find the summary for global \p GUID in module \p ModuleId, or nullptr if
+ /// Find the summary for ValueInfo \p VI in module \p ModuleId, or nullptr if
/// not found.
- GlobalValueSummary *findSummaryInModule(GlobalValue::GUID ValueGUID,
- StringRef ModuleId) const {
- auto CalleeInfo = getValueInfo(ValueGUID);
- if (!CalleeInfo) {
- return nullptr; // This function does not have a summary
- }
+ GlobalValueSummary *findSummaryInModule(ValueInfo VI, StringRef ModuleId) const {
+ auto SummaryList = VI.getSummaryList();
auto Summary =
- llvm::find_if(CalleeInfo.getSummaryList(),
+ llvm::find_if(SummaryList,
[&](const std::unique_ptr<GlobalValueSummary> &Summary) {
return Summary->modulePath() == ModuleId;
});
- if (Summary == CalleeInfo.getSummaryList().end())
+ if (Summary == SummaryList.end())
return nullptr;
return Summary->get();
}
+ /// Find the summary for global \p GUID in module \p ModuleId, or nullptr if
+ /// not found.
+ GlobalValueSummary *findSummaryInModule(GlobalValue::GUID ValueGUID,
+ StringRef ModuleId) const {
+ auto CalleeInfo = getValueInfo(ValueGUID);
+ if (!CalleeInfo)
+ return nullptr; // This function does not have a summary
+ return findSummaryInModule(CalleeInfo, ModuleId);
+ }
+
/// Returns the first GlobalValueSummary for \p GV, asserting that there
/// is only one if \p PerModuleIndex.
GlobalValueSummary *getGlobalValueSummary(const GlobalValue &GV,
@@ -1163,6 +1293,29 @@ public:
return nullptr;
}
+ const std::map<std::string, TypeIdCompatibleVtableInfo> &
+ typeIdCompatibleVtableMap() const {
+ return TypeIdCompatibleVtableMap;
+ }
+
+ /// Return an existing or new TypeIdCompatibleVtableMap entry for \p TypeId.
+ /// This accessor can mutate the map and therefore should not be used in
+ /// the ThinLTO backends.
+ TypeIdCompatibleVtableInfo &
+ getOrInsertTypeIdCompatibleVtableSummary(StringRef TypeId) {
+ return TypeIdCompatibleVtableMap[TypeId];
+ }
+
+ /// For the given \p TypeId, this returns the TypeIdCompatibleVtableMap
+ /// entry if present in the summary map. This may be used when importing.
+ Optional<TypeIdCompatibleVtableInfo>
+ getTypeIdCompatibleVtableSummary(StringRef TypeId) const {
+ auto I = TypeIdCompatibleVtableMap.find(TypeId);
+ if (I == TypeIdCompatibleVtableMap.end())
+ return None;
+ return I->second;
+ }
+
/// Collect for the given module the list of functions it defines
/// (GUID -> Summary).
void collectDefinedFunctionsForModule(StringRef ModulePath,
@@ -1170,8 +1323,16 @@ public:
/// Collect for each module the list of Summaries it defines (GUID ->
/// Summary).
- void collectDefinedGVSummariesPerModule(
- StringMap<GVSummaryMapTy> &ModuleToDefinedGVSummaries) const;
+ template <class Map>
+ void
+ collectDefinedGVSummariesPerModule(Map &ModuleToDefinedGVSummaries) const {
+ for (auto &GlobalList : *this) {
+ auto GUID = GlobalList.first;
+ for (auto &Summary : GlobalList.second.SummaryList) {
+ ModuleToDefinedGVSummaries[Summary->modulePath()][GUID] = Summary.get();
+ }
+ }
+ }
/// Print to an output stream.
void print(raw_ostream &OS, bool IsForDebug = false) const;
@@ -1186,7 +1347,7 @@ public:
void dumpSCCs(raw_ostream &OS);
/// Analyze index and detect unmodified globals
- void propagateConstants(const DenseSet<GlobalValue::GUID> &PreservedSymbols);
+ void propagateAttributes(const DenseSet<GlobalValue::GUID> &PreservedSymbols);
};
/// GraphTraits definition to build SCC for the index