diff options
Diffstat (limited to 'llvm/include/llvm/IR/ModuleSummaryIndex.h')
-rw-r--r-- | llvm/include/llvm/IR/ModuleSummaryIndex.h | 150 |
1 files changed, 127 insertions, 23 deletions
diff --git a/llvm/include/llvm/IR/ModuleSummaryIndex.h b/llvm/include/llvm/IR/ModuleSummaryIndex.h index aa4054c8409e..12a829b14e36 100644 --- a/llvm/include/llvm/IR/ModuleSummaryIndex.h +++ b/llvm/include/llvm/IR/ModuleSummaryIndex.h @@ -23,6 +23,7 @@ #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/TinyPtrVector.h" +#include "llvm/IR/ConstantRange.h" #include "llvm/IR/GlobalValue.h" #include "llvm/IR/Module.h" #include "llvm/Support/Allocator.h" @@ -552,6 +553,41 @@ public: unsigned AlwaysInline : 1; }; + /// Describes the uses of a parameter by the function. + struct ParamAccess { + static constexpr uint32_t RangeWidth = 64; + + /// Describes the use of a value in a call instruction, specifying the + /// call's target, the value's parameter number, and the possible range of + /// offsets from the beginning of the value that are passed. + struct Call { + uint64_t ParamNo = 0; + GlobalValue::GUID Callee = 0; + ConstantRange Offsets{/*BitWidth=*/RangeWidth, /*isFullSet=*/true}; + + Call() = default; + Call(uint64_t ParamNo, GlobalValue::GUID Callee, + const ConstantRange &Offsets) + : ParamNo(ParamNo), Callee(Callee), Offsets(Offsets) {} + }; + + uint64_t ParamNo = 0; + /// The range contains byte offsets from the parameter pointer which + /// accessed by the function. In the per-module summary, it only includes + /// accesses made by the function instructions. In the combined summary, it + /// also includes accesses by nested function calls. + ConstantRange Use{/*BitWidth=*/RangeWidth, /*isFullSet=*/true}; + /// In the per-module summary, it summarizes the byte offset applied to each + /// pointer parameter before passing to each corresponding callee. + /// In the combined summary, it's empty and information is propagated by + /// inter-procedural analysis and applied to the Use field. + std::vector<Call> Calls; + + ParamAccess() = default; + ParamAccess(uint64_t ParamNo, const ConstantRange &Use) + : ParamNo(ParamNo), Use(Use) {} + }; + /// Create an empty FunctionSummary (with specified call edges). /// Used to represent external nodes and the dummy root node. static FunctionSummary @@ -567,7 +603,8 @@ public: std::vector<FunctionSummary::VFuncId>(), std::vector<FunctionSummary::VFuncId>(), std::vector<FunctionSummary::ConstVCall>(), - std::vector<FunctionSummary::ConstVCall>()); + std::vector<FunctionSummary::ConstVCall>(), + std::vector<FunctionSummary::ParamAccess>()); } /// A dummy node to reference external functions that aren't in the index @@ -591,6 +628,10 @@ private: std::unique_ptr<TypeIdInfo> TIdInfo; + /// Uses for every parameter to this function. + using ParamAccessesTy = std::vector<ParamAccess>; + std::unique_ptr<ParamAccessesTy> ParamAccesses; + public: FunctionSummary(GVFlags Flags, unsigned NumInsts, FFlags FunFlags, uint64_t EntryCount, std::vector<ValueInfo> Refs, @@ -599,18 +640,21 @@ public: std::vector<VFuncId> TypeTestAssumeVCalls, std::vector<VFuncId> TypeCheckedLoadVCalls, std::vector<ConstVCall> TypeTestAssumeConstVCalls, - std::vector<ConstVCall> TypeCheckedLoadConstVCalls) + std::vector<ConstVCall> TypeCheckedLoadConstVCalls, + std::vector<ParamAccess> Params) : GlobalValueSummary(FunctionKind, Flags, std::move(Refs)), InstCount(NumInsts), FunFlags(FunFlags), EntryCount(EntryCount), CallGraphEdgeList(std::move(CGEdges)) { if (!TypeTests.empty() || !TypeTestAssumeVCalls.empty() || !TypeCheckedLoadVCalls.empty() || !TypeTestAssumeConstVCalls.empty() || !TypeCheckedLoadConstVCalls.empty()) - TIdInfo = std::make_unique<TypeIdInfo>(TypeIdInfo{ - std::move(TypeTests), std::move(TypeTestAssumeVCalls), - std::move(TypeCheckedLoadVCalls), - std::move(TypeTestAssumeConstVCalls), - std::move(TypeCheckedLoadConstVCalls)}); + TIdInfo = std::make_unique<TypeIdInfo>( + TypeIdInfo{std::move(TypeTests), std::move(TypeTestAssumeVCalls), + std::move(TypeCheckedLoadVCalls), + std::move(TypeTestAssumeConstVCalls), + std::move(TypeCheckedLoadConstVCalls)}); + if (!Params.empty()) + ParamAccesses = std::make_unique<ParamAccessesTy>(std::move(Params)); } // Gets the number of readonly and writeonly refs in RefEdgeList std::pair<unsigned, unsigned> specialRefCounts() const; @@ -681,6 +725,23 @@ public: return {}; } + /// Returns the list of known uses of pointer parameters. + ArrayRef<ParamAccess> paramAccesses() const { + if (ParamAccesses) + return *ParamAccesses; + return {}; + } + + /// Sets the list of known uses of pointer parameters. + void setParamAccesses(std::vector<ParamAccess> NewParams) { + if (NewParams.empty()) + ParamAccesses.reset(); + else if (ParamAccesses) + *ParamAccesses = std::move(NewParams); + else + ParamAccesses = std::make_unique<ParamAccessesTy>(std::move(NewParams)); + } + /// 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) { @@ -757,14 +818,33 @@ private: public: struct GVarFlags { - 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. + GVarFlags(bool ReadOnly, bool WriteOnly, bool Constant, + GlobalObject::VCallVisibility Vis) + : MaybeReadOnly(ReadOnly), MaybeWriteOnly(WriteOnly), + Constant(Constant), VCallVisibility(Vis) {} + + // If true indicates that this global variable might be accessed + // purely by non-volatile load instructions. This in turn means + // it can be internalized in source and destination modules during + // thin LTO import because it neither modified nor its address + // is taken. unsigned MaybeReadOnly : 1; + // If true indicates that variable is possibly only written to, so + // its value isn't loaded and its address isn't taken anywhere. + // False, when 'Constant' attribute is set. unsigned MaybeWriteOnly : 1; + // Indicates that value is a compile-time constant. Global variable + // can be 'Constant' while not being 'ReadOnly' on several occasions: + // - it is volatile, (e.g mapped device address) + // - its address is taken, meaning that unlike 'ReadOnly' vars we can't + // internalize it. + // Constant variables are always imported thus giving compiler an + // opportunity to make some extra optimizations. Readonly constants + // are also internalized. + unsigned Constant : 1; + // Set from metadata on vtable definitions during the module summary + // analysis. + unsigned VCallVisibility : 2; } VarFlags; GlobalVarSummary(GVFlags Flags, GVarFlags VarFlags, @@ -782,6 +862,13 @@ public: void setWriteOnly(bool WO) { VarFlags.MaybeWriteOnly = WO; } bool maybeReadOnly() const { return VarFlags.MaybeReadOnly; } bool maybeWriteOnly() const { return VarFlags.MaybeWriteOnly; } + bool isConstant() const { return VarFlags.Constant; } + void setVCallVisibility(GlobalObject::VCallVisibility Vis) { + VarFlags.VCallVisibility = Vis; + } + GlobalObject::VCallVisibility getVCallVisibility() const { + return (GlobalObject::VCallVisibility)VarFlags.VCallVisibility; + } void setVTableFuncs(VTableFuncList Funcs) { assert(!VTableFuncs); @@ -807,7 +894,8 @@ struct TypeTestResolution { Single, ///< Single element (last example in "Short Inline Bit Vectors") AllOnes, ///< All-ones bit vector ("Eliminating Bit Vector Checks for /// All-Ones Bit Vectors") - } TheKind = Unsat; + Unknown, ///< Unknown (analysis not performed, don't lower) + } TheKind = Unknown; /// Range of size-1 expressed as a bit width. For example, if the size is in /// range [1,256], this number will be 8. This helps generate the most compact @@ -933,7 +1021,8 @@ private: /// 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; + std::map<std::string, TypeIdCompatibleVtableInfo, std::less<>> + TypeIdCompatibleVtableMap; /// Mapping from original ID to GUID. If original ID can map to multiple /// GUIDs, it will be mapped to 0. @@ -980,6 +1069,10 @@ private: StringSaver Saver; BumpPtrAllocator Alloc; + // The total number of basic blocks in the module in the per-module summary or + // the total number of basic blocks in the LTO unit in the combined index. + uint64_t BlockCount; + // YAML I/O support. friend yaml::MappingTraits<ModuleSummaryIndex>; @@ -992,18 +1085,30 @@ private: public: // See HaveGVs variable comment. ModuleSummaryIndex(bool HaveGVs, bool EnableSplitLTOUnit = false) - : HaveGVs(HaveGVs), EnableSplitLTOUnit(EnableSplitLTOUnit), Saver(Alloc) { - } + : HaveGVs(HaveGVs), EnableSplitLTOUnit(EnableSplitLTOUnit), Saver(Alloc), + BlockCount(0) {} // Current version for the module summary in bitcode files. // The BitcodeSummaryVersion should be bumped whenever we introduce changes // in the way some record are interpreted, like flags for instance. // Note that incrementing this may require changes in both BitcodeReader.cpp // and BitcodeWriter.cpp. - static constexpr uint64_t BitcodeSummaryVersion = 8; + static constexpr uint64_t BitcodeSummaryVersion = 9; + + // Regular LTO module name for ASM writer + static constexpr const char *getRegularLTOModuleName() { + return "[Regular LTO]"; + } bool haveGVs() const { return HaveGVs; } + uint64_t getFlags() const; + void setFlags(uint64_t Flags); + + uint64_t getBlockCount() const { return BlockCount; } + void addBlockCount(uint64_t C) { BlockCount += C; } + void setBlockCount(uint64_t C) { BlockCount = C; } + gvsummary_iterator begin() { return GlobalValueMap.begin(); } const_gvsummary_iterator begin() const { return GlobalValueMap.begin(); } gvsummary_iterator end() { return GlobalValueMap.end(); } @@ -1264,7 +1369,7 @@ public: NewName += ".llvm."; NewName += utostr((uint64_t(ModHash[0]) << 32) | ModHash[1]); // Take the first 64 bits - return NewName.str(); + return std::string(NewName.str()); } /// Helper to obtain the unpromoted name for a global value (or the original @@ -1310,7 +1415,7 @@ public: if (It->second.first == TypeId) return It->second.second; auto It = TypeIdMap.insert( - {GlobalValue::getGUID(TypeId), {TypeId, TypeIdSummary()}}); + {GlobalValue::getGUID(TypeId), {std::string(TypeId), TypeIdSummary()}}); return It->second.second; } @@ -1330,8 +1435,7 @@ public: TypeId)); } - const std::map<std::string, TypeIdCompatibleVtableInfo> & - typeIdCompatibleVtableMap() const { + const auto &typeIdCompatibleVtableMap() const { return TypeIdCompatibleVtableMap; } @@ -1340,7 +1444,7 @@ public: /// the ThinLTO backends. TypeIdCompatibleVtableInfo & getOrInsertTypeIdCompatibleVtableSummary(StringRef TypeId) { - return TypeIdCompatibleVtableMap[TypeId]; + return TypeIdCompatibleVtableMap[std::string(TypeId)]; } /// For the given \p TypeId, this returns the TypeIdCompatibleVtableMap |