diff options
Diffstat (limited to 'include/llvm/IR/ModuleSummaryIndex.h')
-rw-r--r-- | include/llvm/IR/ModuleSummaryIndex.h | 222 |
1 files changed, 211 insertions, 11 deletions
diff --git a/include/llvm/IR/ModuleSummaryIndex.h b/include/llvm/IR/ModuleSummaryIndex.h index 83c4ae011216..09f6c1897009 100644 --- a/include/llvm/IR/ModuleSummaryIndex.h +++ b/include/llvm/IR/ModuleSummaryIndex.h @@ -162,7 +162,7 @@ private: protected: /// GlobalValueSummary constructor. GlobalValueSummary(SummaryKind K, GVFlags Flags, std::vector<ValueInfo> Refs) - : Kind(K), Flags(Flags), RefEdgeList(std::move(Refs)) {} + : Kind(K), Flags(Flags), OriginalName(0), RefEdgeList(std::move(Refs)) {} public: virtual ~GlobalValueSummary() = default; @@ -233,12 +233,13 @@ public: void setAliasee(GlobalValueSummary *Aliasee) { AliaseeSummary = Aliasee; } const GlobalValueSummary &getAliasee() const { - return const_cast<AliasSummary *>(this)->getAliasee(); + assert(AliaseeSummary && "Unexpected missing aliasee summary"); + return *AliaseeSummary; } GlobalValueSummary &getAliasee() { - assert(AliaseeSummary && "Unexpected missing aliasee summary"); - return *AliaseeSummary; + return const_cast<GlobalValueSummary &>( + static_cast<const AliasSummary *>(this)->getAliasee()); } }; @@ -249,6 +250,23 @@ public: /// <CalleeValueInfo, CalleeInfo> call edge pair. typedef std::pair<ValueInfo, CalleeInfo> EdgeTy; + /// An "identifier" for a virtual function. This contains the type identifier + /// represented as a GUID and the offset from the address point to the virtual + /// function pointer, where "address point" is as defined in the Itanium ABI: + /// https://mentorembedded.github.io/cxx-abi/abi.html#vtable-general + struct VFuncId { + GlobalValue::GUID GUID; + uint64_t Offset; + }; + + /// A specification for a virtual function call with all constant integer + /// arguments. This is used to perform virtual constant propagation on the + /// summary. + struct ConstVCall { + VFuncId VFunc; + std::vector<uint64_t> Args; + }; + private: /// Number of instructions (ignoring debug instructions, e.g.) computed /// during the initial compile step when the summary index is first built. @@ -257,17 +275,47 @@ private: /// List of <CalleeValueInfo, CalleeInfo> call edge pairs from this function. std::vector<EdgeTy> CallGraphEdgeList; - /// List of type identifiers used by this function, represented as GUIDs. - std::vector<GlobalValue::GUID> TypeIdList; + /// All type identifier related information. Because these fields are + /// relatively uncommon we only allocate space for them if necessary. + struct TypeIdInfo { + /// List of type identifiers used by this function in llvm.type.test + /// intrinsics other than by an llvm.assume intrinsic, represented as GUIDs. + std::vector<GlobalValue::GUID> TypeTests; + + /// List of virtual calls made by this function using (respectively) + /// llvm.assume(llvm.type.test) or llvm.type.checked.load intrinsics that do + /// not have all constant integer arguments. + std::vector<VFuncId> TypeTestAssumeVCalls, TypeCheckedLoadVCalls; + + /// List of virtual calls made by this function using (respectively) + /// llvm.assume(llvm.type.test) or llvm.type.checked.load intrinsics with + /// all constant integer arguments. + std::vector<ConstVCall> TypeTestAssumeConstVCalls, + TypeCheckedLoadConstVCalls; + }; + + std::unique_ptr<TypeIdInfo> TIdInfo; public: /// Summary constructors. FunctionSummary(GVFlags Flags, unsigned NumInsts, std::vector<ValueInfo> Refs, std::vector<EdgeTy> CGEdges, - std::vector<GlobalValue::GUID> TypeIds) + 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), CallGraphEdgeList(std::move(CGEdges)), - TypeIdList(std::move(TypeIds)) {} + InstCount(NumInsts), CallGraphEdgeList(std::move(CGEdges)) { + if (!TypeTests.empty() || !TypeTestAssumeVCalls.empty() || + !TypeCheckedLoadVCalls.empty() || !TypeTestAssumeConstVCalls.empty() || + !TypeCheckedLoadConstVCalls.empty()) + TIdInfo = llvm::make_unique<TypeIdInfo>(TypeIdInfo{ + std::move(TypeTests), std::move(TypeTestAssumeVCalls), + std::move(TypeCheckedLoadVCalls), + std::move(TypeTestAssumeConstVCalls), + std::move(TypeCheckedLoadConstVCalls)}); + } /// Check if this is a function summary. static bool classof(const GlobalValueSummary *GVS) { @@ -280,8 +328,85 @@ public: /// Return the list of <CalleeValueInfo, CalleeInfo> pairs. ArrayRef<EdgeTy> calls() const { return CallGraphEdgeList; } - /// Returns the list of type identifiers used by this function. - ArrayRef<GlobalValue::GUID> type_tests() const { return TypeIdList; } + /// Returns the list of type identifiers used by this function in + /// llvm.type.test intrinsics other than by an llvm.assume intrinsic, + /// represented as GUIDs. + ArrayRef<GlobalValue::GUID> type_tests() const { + if (TIdInfo) + return TIdInfo->TypeTests; + return {}; + } + + /// Returns the list of virtual calls made by this function using + /// llvm.assume(llvm.type.test) intrinsics that do not have all constant + /// integer arguments. + ArrayRef<VFuncId> type_test_assume_vcalls() const { + if (TIdInfo) + return TIdInfo->TypeTestAssumeVCalls; + return {}; + } + + /// Returns the list of virtual calls made by this function using + /// llvm.type.checked.load intrinsics that do not have all constant integer + /// arguments. + ArrayRef<VFuncId> type_checked_load_vcalls() const { + if (TIdInfo) + return TIdInfo->TypeCheckedLoadVCalls; + return {}; + } + + /// Returns the list of virtual calls made by this function using + /// llvm.assume(llvm.type.test) intrinsics with all constant integer + /// arguments. + ArrayRef<ConstVCall> type_test_assume_const_vcalls() const { + if (TIdInfo) + return TIdInfo->TypeTestAssumeConstVCalls; + return {}; + } + + /// Returns the list of virtual calls made by this function using + /// llvm.type.checked.load intrinsics with all constant integer arguments. + ArrayRef<ConstVCall> type_checked_load_const_vcalls() const { + if (TIdInfo) + return TIdInfo->TypeCheckedLoadConstVCalls; + return {}; + } + + /// Add a type test to the summary. This is used by WholeProgramDevirt if we + /// were unable to devirtualize a checked call. + void addTypeTest(GlobalValue::GUID Guid) { + if (!TIdInfo) + TIdInfo = llvm::make_unique<TypeIdInfo>(); + TIdInfo->TypeTests.push_back(Guid); + } +}; + +template <> struct DenseMapInfo<FunctionSummary::VFuncId> { + static FunctionSummary::VFuncId getEmptyKey() { return {0, uint64_t(-1)}; } + static FunctionSummary::VFuncId getTombstoneKey() { + return {0, uint64_t(-2)}; + } + static bool isEqual(FunctionSummary::VFuncId L, FunctionSummary::VFuncId R) { + return L.GUID == R.GUID && L.Offset == R.Offset; + } + static unsigned getHashValue(FunctionSummary::VFuncId I) { return I.GUID; } +}; + +template <> struct DenseMapInfo<FunctionSummary::ConstVCall> { + static FunctionSummary::ConstVCall getEmptyKey() { + return {{0, uint64_t(-1)}, {}}; + } + static FunctionSummary::ConstVCall getTombstoneKey() { + return {{0, uint64_t(-2)}, {}}; + } + static bool isEqual(FunctionSummary::ConstVCall L, + FunctionSummary::ConstVCall R) { + return DenseMapInfo<FunctionSummary::VFuncId>::isEqual(L.VFunc, R.VFunc) && + L.Args == R.Args; + } + static unsigned getHashValue(FunctionSummary::ConstVCall I) { + return I.VFunc.GUID; + } }; /// \brief Global variable summary information to aid decisions and @@ -323,8 +448,40 @@ struct TypeTestResolution { unsigned SizeM1BitWidth = 0; }; +struct WholeProgramDevirtResolution { + enum Kind { + Indir, ///< Just do a regular virtual call + SingleImpl, ///< Single implementation devirtualization + } TheKind = Indir; + + std::string SingleImplName; + + struct ByArg { + enum Kind { + Indir, ///< Just do a regular virtual call + UniformRetVal, ///< Uniform return value optimization + UniqueRetVal, ///< Unique return value optimization + VirtualConstProp, ///< Virtual constant propagation + } TheKind = Indir; + + /// Additional information for the resolution: + /// - UniformRetVal: the uniform return value. + /// - UniqueRetVal: the return value associated with the unique vtable (0 or + /// 1). + uint64_t Info = 0; + }; + + /// Resolutions for calls with all constant integer arguments (excluding the + /// first argument, "this"), where the key is the argument vector. + std::map<std::vector<uint64_t>, ByArg> ResByArg; +}; + struct TypeIdSummary { TypeTestResolution TTRes; + + /// Mapping from byte offset to whole-program devirt resolution for that + /// (typeid, byte offset) pair. + std::map<uint64_t, WholeProgramDevirtResolution> WPDRes; }; /// 160 bits SHA1 @@ -372,6 +529,10 @@ private: // FIXME: Add bitcode read/write support for this field. std::map<std::string, TypeIdSummary> TypeIdMap; + /// 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; + // YAML I/O support. friend yaml::MappingTraits<ModuleSummaryIndex>; @@ -399,9 +560,17 @@ public: return GlobalValueMap.find(ValueGUID); } + /// Return the GUID for \p OriginalId in the OidGuidMap. + GlobalValue::GUID getGUIDFromOriginalID(GlobalValue::GUID OriginalID) const { + const auto I = OidGuidMap.find(OriginalID); + return I == OidGuidMap.end() ? 0 : I->second; + } + /// Add a global value summary for a value of the given name. void addGlobalValueSummary(StringRef ValueName, std::unique_ptr<GlobalValueSummary> Summary) { + addOriginalName(GlobalValue::getGUID(ValueName), + Summary->getOriginalName()); GlobalValueMap[GlobalValue::getGUID(ValueName)].push_back( std::move(Summary)); } @@ -409,9 +578,21 @@ public: /// Add a global value summary for a value of the given GUID. void addGlobalValueSummary(GlobalValue::GUID ValueGUID, std::unique_ptr<GlobalValueSummary> Summary) { + addOriginalName(ValueGUID, Summary->getOriginalName()); GlobalValueMap[ValueGUID].push_back(std::move(Summary)); } + /// Add an original name for the value of the given GUID. + void addOriginalName(GlobalValue::GUID ValueGUID, + GlobalValue::GUID OrigGUID) { + if (OrigGUID == 0 || ValueGUID == OrigGUID) + return; + if (OidGuidMap.count(OrigGUID) && OidGuidMap[OrigGUID] != ValueGUID) + OidGuidMap[OrigGUID] = 0; + else + OidGuidMap[OrigGUID] = ValueGUID; + } + /// Find the summary for global \p GUID in module \p ModuleId, or nullptr if /// not found. GlobalValueSummary *findSummaryInModule(GlobalValue::GUID ValueGUID, @@ -507,6 +688,25 @@ public: return ModulePathStringTable.count(M.getModuleIdentifier()); } + const std::map<std::string, TypeIdSummary> &typeIds() const { + return TypeIdMap; + } + + /// This accessor should only be used when exporting because it can mutate the + /// map. + TypeIdSummary &getOrInsertTypeIdSummary(StringRef TypeId) { + return TypeIdMap[TypeId]; + } + + /// 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; + } + /// Remove entries in the GlobalValueMap that have empty summaries due to the /// eager nature of map entry creation during VST parsing. These would /// also be suppressed during combined index generation in mergeFrom(), |