[llvm] r364960 - [ThinLTO] Add summary entries for index-based WPD
Teresa Johnson via llvm-commits
llvm-commits at lists.llvm.org
Wed Jul 3 08:12:45 PDT 2019
Fixed in r365047.
Thanks,
Teresa
On Wed, Jul 3, 2019 at 7:02 AM Mikael Holmén <mikael.holmen at ericsson.com>
wrote:
> Hi,
>
> On 2019-07-03 15:36, Teresa Johnson wrote:
> > Hi Mikael,
> >
> > Thanks for looking into this! Not sure why I had const in the return
> > type to start with, let me go ahead and remove it once I sanity check
> > that everything builds/runs with the change (including a follow-on patch
> > that makes use of this interface).
> >
>
> Sounds good!
>
> Thanks,
> Mikael
>
> > Teresa
> >
> > On Wed, Jul 3, 2019 at 12:39 AM Mikael Holmén
> > <mikael.holmen at ericsson.com <mailto:mikael.holmen at ericsson.com>> wrote:
> >
> >
> >
> > On 2019-07-03 08:39, Mikael Holmén via llvm-commits wrote:
> > > Hi Teresa,
> > >
> > > With this commit I start seeing warnings from gcc 7.4.0:
> > >
> > > In file included from ../include/llvm/ADT/STLExtras.h:19:0,
> > > from ../include/llvm/ADT/StringRef.h:12,
> > > from ../include/llvm/ADT/StringMap.h:16,
> > > from ../include/llvm/Support/Host.h:16,
> > > from ../include/llvm/ADT/Hashing.h:48,
> > > from ../include/llvm/ADT/ArrayRef.h:12,
> > > from ../include/llvm/ADT/APFloat.h:20,
> > > from ../lib/IR/AsmWriter.cpp:18:
> > > ../include/llvm/ADT/Optional.h: In instantiation of 'void
> > > llvm::optional_detail::OptionalStorage<T, <anonymous>
> > >::emplace(Args&&
> > > ...) [with Args = {const std::vector<llvm::TypeIdOffsetVtableInfo,
> > > std::allocator<llvm::TypeIdOffsetVtableInfo> >}; T = const
> > > std::vector<llvm::TypeIdOffsetVtableInfo>; bool <anonymous> =
> > false]':
> > > ../include/llvm/ADT/Optional.h:55:14: required from
> > > 'llvm::optional_detail::OptionalStorage<T, <anonymous>
> > > >::OptionalStorage(llvm::optional_detail::OptionalStorage<T,
> > > <anonymous> >&&) [with T = const
> > > std::vector<llvm::TypeIdOffsetVtableInfo>; bool <anonymous> =
> false]'
> > > ../include/llvm/ADT/Optional.h:228:3: required from here
> > > ../include/llvm/ADT/Optional.h:89:12: error: cast from type 'const
> > > std::vector<llvm::TypeIdOffsetVtableInfo>*' to type 'void*' casts
> > away
> > > qualifiers [-Werror=cast-qual]
> > > ::new ((void *)std::addressof(value))
> > T(std::forward<Args>(args)...);
> > > ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> > >
> > > Can you make any sense out of that with respect to your commit?
> > >
> >
> > It seems like it's the const in the return type in
> >
> > Optional<const TypeIdCompatibleVtableInfo>
> > getTypeIdCompatibleVtableSummary(StringRef TypeId) const {
> > auto I = TypeIdCompatibleVtableMap.find(TypeId);
> > if (I == TypeIdCompatibleVtableMap.end())
> > return None;
> > return I->second;
> > }
> >
> > that it complains that it casts away in
> >
> > template <class... Args> void emplace(Args &&... args) {
> > reset();
> > ::new ((void *)std::addressof(value))
> > T(std::forward<Args>(args)...);
> > hasVal = true;
> > }
> >
> > The warning goes away if I remove that const, but I've no idea what
> the
> > proper solution is.
> >
> > /Mikael
> >
> >
> > > Thanks,
> > > Mikael
> > >
> > > On 2019-07-02 21:38, Teresa Johnson via llvm-commits wrote:
> > >> Author: tejohnson
> > >> Date: Tue Jul 2 12:38:02 2019
> > >> New Revision: 364960
> > >>
> > >> URL: http://llvm.org/viewvc/llvm-project?rev=364960&view=rev
> > >> Log:
> > >> [ThinLTO] Add summary entries for index-based WPD
> > >>
> > >> Summary:
> > >> If LTOUnit splitting is disabled, the module summary analysis
> > computes
> > >> the summary information necessary to perform single
> implementation
> > >> devirtualization during the thin link with the index and no IR.
> The
> > >> information collected from the regular LTO IR in the current
> > hybrid WPD
> > >> algorithm is summarized, including:
> > >> 1) For vtable definitions, record the function pointers and
> > their offset
> > >> within the vtable initializer (subsumes the information
> > collected from
> > >> IR by tryFindVirtualCallTargets).
> > >> 2) A record for each type metadata summarizing the vtable
> > definitions
> > >> decorated with that metadata (subsumes the TypeIdentiferMap
> > collected
> > >> from IR).
> > >>
> > >> Also added are the necessary bitcode records, and the
> corresponding
> > >> assembly support.
> > >>
> > >> The follow-on index-based WPD patch is D55153.
> > >>
> > >> Depends on D53890.
> > >>
> > >> Reviewers: pcc
> > >>
> > >> Subscribers: mehdi_amini, Prazek, inglorion, eraman, steven_wu,
> > dexonsmith, arphaman, llvm-commits
> > >>
> > >> Differential Revision: https://reviews.llvm.org/D54815
> > >>
> > >> Added:
> > >> llvm/trunk/test/Assembler/thinlto-vtable-summary.ll
> > >> llvm/trunk/test/ThinLTO/X86/devirt.ll
> > >> Modified:
> > >> llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h
> > >> llvm/trunk/include/llvm/IR/ModuleSummaryIndex.h
> > >> llvm/trunk/lib/Analysis/ModuleSummaryAnalysis.cpp
> > >> llvm/trunk/lib/AsmParser/LLLexer.cpp
> > >> llvm/trunk/lib/AsmParser/LLParser.cpp
> > >> llvm/trunk/lib/AsmParser/LLParser.h
> > >> llvm/trunk/lib/AsmParser/LLToken.h
> > >> llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp
> > >> llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp
> > >> llvm/trunk/lib/IR/AsmWriter.cpp
> > >> llvm/trunk/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp
> > >> llvm/trunk/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp
> > >>
> > >> Modified: llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h
> > >> URL:
> >
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h?rev=364960&r1=364959&r2=364960&view=diff
> > >>
> >
> ==============================================================================
> > >> --- llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h (original)
> > >> +++ llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h Tue Jul 2
> > 12:38:02 2019
> > >> @@ -263,10 +263,31 @@ enum GlobalValueSummarySymtabCodes {
> > >> // Index-wide flags
> > >> FS_FLAGS = 20,
> > >> // Maps type identifier to summary information for that
> > type identifier.
> > >> + // Produced by the thin link (only lives in combined index).
> > >> // TYPE_ID: [typeid, kind, bitwidth, align, size, bitmask,
> > inlinebits,
> > >> // n x (typeid, kind, name, numrba,
> > >> // numrba x (numarg, numarg x arg, kind,
> > info, byte, bit))]
> > >> FS_TYPE_ID = 21,
> > >> + // For background see overview at
> > https://llvm.org/docs/TypeMetadata.html.
> > >> + // The 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.
> > >> + //
> > >> + // Maps type identifier to summary information for that type
> > identifier
> > >> + // computed from type metadata: the valueid of each vtable
> > definition
> > >> + // decorated with a type metadata for that identifier, and
> > the offset from
> > >> + // the corresponding type metadata.
> > >> + // Exists in the per-module summary to provide information to
> > thin link
> > >> + // for index-based whole program devirtualization.
> > >> + // TYPE_ID_METADATA: [typeid, n x (valueid, offset)]
> > >> + FS_TYPE_ID_METADATA = 22,
> > >> + // Summarizes vtable definition for use in index-based whole
> > program
> > >> + // devirtualization during the thin link.
> > >> + // PERMODULE_VTABLE_GLOBALVAR_INIT_REFS: [valueid, flags,
> > varflags,
> > >> + // numrefs, numrefs x
> > valueid,
> > >> + // n x (valueid,
> offset)]
> > >> + FS_PERMODULE_VTABLE_GLOBALVAR_INIT_REFS = 23,
> > >> };
> > >>
> > >> enum MetadataCodes {
> > >>
> > >> Modified: llvm/trunk/include/llvm/IR/ModuleSummaryIndex.h
> > >> URL:
> >
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/ModuleSummaryIndex.h?rev=364960&r1=364959&r2=364960&view=diff
> > >>
> >
> ==============================================================================
> > >> --- llvm/trunk/include/llvm/IR/ModuleSummaryIndex.h (original)
> > >> +++ llvm/trunk/include/llvm/IR/ModuleSummaryIndex.h Tue Jul 2
> > 12:38:02 2019
> > >> @@ -698,6 +698,18 @@ template <> struct DenseMapInfo<Function
> > >> }
> > >> };
> > >>
> > >> +/// 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.
> > >> ///
> > >> @@ -705,6 +717,11 @@ template <> struct DenseMapInfo<Function
> > >> /// modified during the program run or not. This affects
> ThinLTO
> > >> /// internalization
> > >> 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) {}
> > >> @@ -725,6 +742,17 @@ public:
> > >> GVarFlags varflags() const { return VarFlags; }
> > >> void setReadOnly(bool RO) { VarFlags.ReadOnly = RO; }
> > >> bool isReadOnly() const { return VarFlags.ReadOnly; }
> > >> +
> > >> + 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 {
> > >> @@ -823,6 +851,29 @@ using GVSummaryMapTy = DenseMap<GlobalVa
> > >> 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 {
> > >> @@ -835,9 +886,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;
> > >> @@ -1201,6 +1258,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<const 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,
> > >>
> > >> Modified: llvm/trunk/lib/Analysis/ModuleSummaryAnalysis.cpp
> > >> URL:
> >
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ModuleSummaryAnalysis.cpp?rev=364960&r1=364959&r2=364960&view=diff
> > >>
> >
> ==============================================================================
> > >> --- llvm/trunk/lib/Analysis/ModuleSummaryAnalysis.cpp (original)
> > >> +++ llvm/trunk/lib/Analysis/ModuleSummaryAnalysis.cpp Tue Jul 2
> > 12:38:02 2019
> > >> @@ -411,9 +411,98 @@ static void computeFunctionSummary(Modul
> > >> Index.addGlobalValueSummary(F, std::move(FuncSummary));
> > >> }
> > >>
> > >> +/// Find function pointers referenced within the given vtable
> > initializer
> > >> +/// (or subset of an initializer) \p I. The starting offset of
> > \p I within
> > >> +/// the vtable initializer is \p StartingOffset. Any discovered
> > function
> > >> +/// pointers are added to \p VTableFuncs along with their
> > cumulative offset
> > >> +/// within the initializer.
> > >> +static void findFuncPointers(const Constant *I, uint64_t
> > StartingOffset,
> > >> + const Module &M,
> > ModuleSummaryIndex &Index,
> > >> + VTableFuncList &VTableFuncs) {
> > >> + // First check if this is a function pointer.
> > >> + if (I->getType()->isPointerTy()) {
> > >> + auto Fn = dyn_cast<Function>(I->stripPointerCasts());
> > >> + // We can disregard __cxa_pure_virtual as a possible call
> > target, as
> > >> + // calls to pure virtuals are UB.
> > >> + if (Fn && Fn->getName() != "__cxa_pure_virtual")
> > >> + VTableFuncs.push_back({Index.getOrInsertValueInfo(Fn),
> > StartingOffset});
> > >> + return;
> > >> + }
> > >> +
> > >> + // Walk through the elements in the constant struct or array
> > and recursively
> > >> + // look for virtual function pointers.
> > >> + const DataLayout &DL = M.getDataLayout();
> > >> + if (auto *C = dyn_cast<ConstantStruct>(I)) {
> > >> + StructType *STy = dyn_cast<StructType>(C->getType());
> > >> + assert(STy);
> > >> + const StructLayout *SL = DL.getStructLayout(C->getType());
> > >> +
> > >> + for (StructType::element_iterator EB =
> > STy->element_begin(), EI = EB,
> > >> + EE = STy->element_end();
> > >> + EI != EE; ++EI) {
> > >> + auto Offset = SL->getElementOffset(EI - EB);
> > >> + unsigned Op = SL->getElementContainingOffset(Offset);
> > >> + findFuncPointers(cast<Constant>(I->getOperand(Op)),
> > >> + StartingOffset + Offset, M, Index,
> > VTableFuncs);
> > >> + }
> > >> + } else if (auto *C = dyn_cast<ConstantArray>(I)) {
> > >> + ArrayType *ATy = C->getType();
> > >> + Type *EltTy = ATy->getElementType();
> > >> + uint64_t EltSize = DL.getTypeAllocSize(EltTy);
> > >> + for (unsigned i = 0, e = ATy->getNumElements(); i != e;
> ++i) {
> > >> + findFuncPointers(cast<Constant>(I->getOperand(i)),
> > >> + StartingOffset + i * EltSize, M, Index,
> > VTableFuncs);
> > >> + }
> > >> + }
> > >> +}
> > >> +
> > >> +// Identify the function pointers referenced by vtable
> > definition \p V.
> > >> +static void computeVTableFuncs(ModuleSummaryIndex &Index,
> > >> + const GlobalVariable &V, const
> > Module &M,
> > >> + VTableFuncList &VTableFuncs) {
> > >> + if (!V.isConstant())
> > >> + return;
> > >> +
> > >> + findFuncPointers(V.getInitializer(), /*StartingOffset=*/0, M,
> > Index,
> > >> + VTableFuncs);
> > >> +
> > >> +#ifndef NDEBUG
> > >> + // Validate that the VTableFuncs list is ordered by offset.
> > >> + uint64_t PrevOffset = 0;
> > >> + for (auto &P : VTableFuncs) {
> > >> + // The findVFuncPointers traversal should have encountered
> the
> > >> + // functions in offset order. We need to use ">=" since
> > PrevOffset
> > >> + // starts at 0.
> > >> + assert(P.VTableOffset >= PrevOffset);
> > >> + PrevOffset = P.VTableOffset;
> > >> + }
> > >> +#endif
> > >> +}
> > >> +
> > >> +/// Record vtable definition \p V for each type metadata it
> > references.
> > >> static void
> > >> -computeVariableSummary(ModuleSummaryIndex &Index, const
> > GlobalVariable &V,
> > >> - DenseSet<GlobalValue::GUID>
> > &CantBePromoted) {
> > >> +recordTypeIdCompatibleVtableReferences(ModuleSummaryIndex
> &Index,
> > >> + const GlobalVariable &V,
> > >> + SmallVectorImpl<MDNode
> > *> &Types) {
> > >> + for (MDNode *Type : Types) {
> > >> + auto TypeID = Type->getOperand(1).get();
> > >> +
> > >> + uint64_t Offset =
> > >> + cast<ConstantInt>(
> > >> +
> > cast<ConstantAsMetadata>(Type->getOperand(0))->getValue())
> > >> + ->getZExtValue();
> > >> +
> > >> + if (auto *TypeId = dyn_cast<MDString>(TypeID))
> > >> +
> > Index.getOrInsertTypeIdCompatibleVtableSummary(TypeId->getString())
> > >> + .push_back({Offset, Index.getOrInsertValueInfo(&V)});
> > >> + }
> > >> +}
> > >> +
> > >> +static void computeVariableSummary(ModuleSummaryIndex &Index,
> > >> + const GlobalVariable &V,
> > >> + DenseSet<GlobalValue::GUID>
> > &CantBePromoted,
> > >> + const Module &M,
> > >> + SmallVectorImpl<MDNode *>
> > &Types) {
> > >> SetVector<ValueInfo> RefEdges;
> > >> SmallPtrSet<const User *, 8> Visited;
> > >> bool HasBlockAddress = findRefEdges(Index, &V, RefEdges,
> > Visited);
> > >> @@ -422,6 +511,21 @@ computeVariableSummary(ModuleSummaryInde
> > >> /* Live = */ false,
> > V.isDSOLocal(),
> > >> V.hasLinkOnceODRLinkage()
> > && V.hasGlobalUnnamedAddr());
> > >>
> > >> + VTableFuncList VTableFuncs;
> > >> + // If splitting is not enabled, then we compute the summary
> > information
> > >> + // necessary for index-based whole program devirtualization.
> > >> + if (!Index.enableSplitLTOUnit()) {
> > >> + Types.clear();
> > >> + V.getMetadata(LLVMContext::MD_type, Types);
> > >> + if (!Types.empty()) {
> > >> + // Identify the function pointers referenced by this
> > vtable definition.
> > >> + computeVTableFuncs(Index, V, M, VTableFuncs);
> > >> +
> > >> + // Record this vtable definition for each type metadata
> > it references.
> > >> + recordTypeIdCompatibleVtableReferences(Index, V, Types);
> > >> + }
> > >> + }
> > >> +
> > >> // Don't mark variables we won't be able to internalize as
> > read-only.
> > >> GlobalVarSummary::GVarFlags VarFlags(
> > >> !V.hasComdat() && !V.hasAppendingLinkage() &&
> > !V.isInterposable() &&
> > >> @@ -432,6 +536,8 @@ computeVariableSummary(ModuleSummaryInde
> > >> CantBePromoted.insert(V.getGUID());
> > >> if (HasBlockAddress)
> > >> GVarSummary->setNotEligibleToImport();
> > >> + if (!VTableFuncs.empty())
> > >> + GVarSummary->setVTableFuncs(VTableFuncs);
> > >> Index.addGlobalValueSummary(V, std::move(GVarSummary));
> > >> }
> > >>
> > >> @@ -578,10 +684,11 @@ ModuleSummaryIndex llvm::buildModuleSumm
> > >>
> > >> // Compute summaries for all variables defined in module,
> > and save in the
> > >> // index.
> > >> + SmallVector<MDNode *, 2> Types;
> > >> for (const GlobalVariable &G : M.globals()) {
> > >> if (G.isDeclaration())
> > >> continue;
> > >> - computeVariableSummary(Index, G, CantBePromoted);
> > >> + computeVariableSummary(Index, G, CantBePromoted, M, Types);
> > >> }
> > >>
> > >> // Compute summaries for all aliases defined in module, and
> > save in the
> > >>
> > >> Modified: llvm/trunk/lib/AsmParser/LLLexer.cpp
> > >> URL:
> >
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLLexer.cpp?rev=364960&r1=364959&r2=364960&view=diff
> > >>
> >
> ==============================================================================
> > >> --- llvm/trunk/lib/AsmParser/LLLexer.cpp (original)
> > >> +++ llvm/trunk/lib/AsmParser/LLLexer.cpp Tue Jul 2 12:38:02 2019
> > >> @@ -752,6 +752,8 @@ lltok::Kind LLLexer::LexIdentifier() {
> > >> KEYWORD(critical);
> > >> KEYWORD(relbf);
> > >> KEYWORD(variable);
> > >> + KEYWORD(vTableFuncs);
> > >> + KEYWORD(virtFunc);
> > >> KEYWORD(aliasee);
> > >> KEYWORD(refs);
> > >> KEYWORD(typeIdInfo);
> > >> @@ -764,6 +766,7 @@ lltok::Kind LLLexer::LexIdentifier() {
> > >> KEYWORD(offset);
> > >> KEYWORD(args);
> > >> KEYWORD(typeid);
> > >> + KEYWORD(typeidCompatibleVTable);
> > >> KEYWORD(summary);
> > >> KEYWORD(typeTestRes);
> > >> KEYWORD(kind);
> > >>
> > >> Modified: llvm/trunk/lib/AsmParser/LLParser.cpp
> > >> URL:
> >
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLParser.cpp?rev=364960&r1=364959&r2=364960&view=diff
> > >>
> >
> ==============================================================================
> > >> --- llvm/trunk/lib/AsmParser/LLParser.cpp (original)
> > >> +++ llvm/trunk/lib/AsmParser/LLParser.cpp Tue Jul 2 12:38:02
> 2019
> > >> @@ -832,6 +832,9 @@ bool LLParser::ParseSummaryEntry() {
> > >> case lltok::kw_typeid:
> > >> result = ParseTypeIdEntry(SummaryID);
> > >> break;
> > >> + case lltok::kw_typeidCompatibleVTable:
> > >> + result = ParseTypeIdCompatibleVtableEntry(SummaryID);
> > >> + break;
> > >> default:
> > >> result = Error(Lex.getLoc(), "unexpected summary kind");
> > >> break;
> > >> @@ -7486,6 +7489,92 @@ bool LLParser::ParseTypeIdSummary(TypeId
> > >> return false;
> > >> }
> > >>
> > >> +static ValueInfo EmptyVI =
> > >> + ValueInfo(false, (GlobalValueSummaryMapTy::value_type *)-8);
> > >> +
> > >> +/// TypeIdCompatibleVtableEntry
> > >> +/// ::= 'typeidCompatibleVTable' ':' '(' 'name' ':'
> > STRINGCONSTANT ','
> > >> +/// TypeIdCompatibleVtableInfo
> > >> +/// ')'
> > >> +bool LLParser::ParseTypeIdCompatibleVtableEntry(unsigned ID) {
> > >> + assert(Lex.getKind() == lltok::kw_typeidCompatibleVTable);
> > >> + Lex.Lex();
> > >> +
> > >> + std::string Name;
> > >> + if (ParseToken(lltok::colon, "expected ':' here") ||
> > >> + ParseToken(lltok::lparen, "expected '(' here") ||
> > >> + ParseToken(lltok::kw_name, "expected 'name' here") ||
> > >> + ParseToken(lltok::colon, "expected ':' here") ||
> > >> + ParseStringConstant(Name))
> > >> + return true;
> > >> +
> > >> + TypeIdCompatibleVtableInfo &TI =
> > >> + Index->getOrInsertTypeIdCompatibleVtableSummary(Name);
> > >> + if (ParseToken(lltok::comma, "expected ',' here") ||
> > >> + ParseToken(lltok::kw_summary, "expected 'summary' here")
> ||
> > >> + ParseToken(lltok::colon, "expected ':' here") ||
> > >> + ParseToken(lltok::lparen, "expected '(' here"))
> > >> + return true;
> > >> +
> > >> + IdToIndexMapType IdToIndexMap;
> > >> + // Parse each call edge
> > >> + do {
> > >> + uint64_t Offset;
> > >> + if (ParseToken(lltok::lparen, "expected '(' here") ||
> > >> + ParseToken(lltok::kw_offset, "expected 'offset' here")
> ||
> > >> + ParseToken(lltok::colon, "expected ':' here") ||
> > ParseUInt64(Offset) ||
> > >> + ParseToken(lltok::comma, "expected ',' here"))
> > >> + return true;
> > >> +
> > >> + LocTy Loc = Lex.getLoc();
> > >> + unsigned GVId;
> > >> + ValueInfo VI;
> > >> + if (ParseGVReference(VI, GVId))
> > >> + return true;
> > >> +
> > >> + // Keep track of the TypeIdCompatibleVtableInfo array index
> > needing a
> > >> + // forward reference. We will save the location of the
> > ValueInfo needing an
> > >> + // update, but can only do so once the std::vector is
> > finalized.
> > >> + if (VI == EmptyVI)
> > >> + IdToIndexMap[GVId].push_back(std::make_pair(TI.size(),
> Loc));
> > >> + TI.push_back({Offset, VI});
> > >> +
> > >> + if (ParseToken(lltok::rparen, "expected ')' in call"))
> > >> + return true;
> > >> + } while (EatIfPresent(lltok::comma));
> > >> +
> > >> + // Now that the TI vector is finalized, it is safe to save
> > the locations
> > >> + // of any forward GV references that need updating later.
> > >> + for (auto I : IdToIndexMap) {
> > >> + for (auto P : I.second) {
> > >> + assert(TI[P.first].VTableVI == EmptyVI &&
> > >> + "Forward referenced ValueInfo expected to be
> empty");
> > >> + auto FwdRef = ForwardRefValueInfos.insert(std::make_pair(
> > >> + I.first, std::vector<std::pair<ValueInfo *,
> LocTy>>()));
> > >> + FwdRef.first->second.push_back(
> > >> + std::make_pair(&TI[P.first].VTableVI, P.second));
> > >> + }
> > >> + }
> > >> +
> > >> + if (ParseToken(lltok::rparen, "expected ')' here") ||
> > >> + ParseToken(lltok::rparen, "expected ')' here"))
> > >> + return true;
> > >> +
> > >> + // Check if this ID was forward referenced, and if so, update
> the
> > >> + // corresponding GUIDs.
> > >> + auto FwdRefTIDs = ForwardRefTypeIds.find(ID);
> > >> + if (FwdRefTIDs != ForwardRefTypeIds.end()) {
> > >> + for (auto TIDRef : FwdRefTIDs->second) {
> > >> + assert(!*TIDRef.first &&
> > >> + "Forward referenced type id GUID expected to be
> 0");
> > >> + *TIDRef.first = GlobalValue::getGUID(Name);
> > >> + }
> > >> + ForwardRefTypeIds.erase(FwdRefTIDs);
> > >> + }
> > >> +
> > >> + return false;
> > >> +}
> > >> +
> > >> /// TypeTestResolution
> > >> /// ::= 'typeTestRes' ':' '(' 'kind' ':'
> > >> /// ( 'unsat' | 'byteArray' | 'inline' | 'single' |
> > 'allOnes' ) ','
> > >> @@ -7994,6 +8083,7 @@ bool LLParser::ParseVariableSummary(std:
> > >> /*Live=*/false, /*IsLocal=*/false,
> /*CanAutoHide=*/false);
> > >> GlobalVarSummary::GVarFlags GVarFlags(/*ReadOnly*/ false);
> > >> std::vector<ValueInfo> Refs;
> > >> + VTableFuncList VTableFuncs;
> > >> if (ParseToken(lltok::colon, "expected ':' here") ||
> > >> ParseToken(lltok::lparen, "expected '(' here") ||
> > >> ParseModuleReference(ModulePath) ||
> > >> @@ -8002,10 +8092,20 @@ bool LLParser::ParseVariableSummary(std:
> > >> ParseGVarFlags(GVarFlags))
> > >> return true;
> > >>
> > >> - // Parse optional refs field
> > >> - if (EatIfPresent(lltok::comma)) {
> > >> - if (ParseOptionalRefs(Refs))
> > >> - return true;
> > >> + // Parse optional fields
> > >> + while (EatIfPresent(lltok::comma)) {
> > >> + switch (Lex.getKind()) {
> > >> + case lltok::kw_vTableFuncs:
> > >> + if (ParseOptionalVTableFuncs(VTableFuncs))
> > >> + return true;
> > >> + break;
> > >> + case lltok::kw_refs:
> > >> + if (ParseOptionalRefs(Refs))
> > >> + return true;
> > >> + break;
> > >> + default:
> > >> + return Error(Lex.getLoc(), "expected optional variable
> > summary field");
> > >> + }
> > >> }
> > >>
> > >> if (ParseToken(lltok::rparen, "expected ')' here"))
> > >> @@ -8015,6 +8115,7 @@ bool LLParser::ParseVariableSummary(std:
> > >> llvm::make_unique<GlobalVarSummary>(GVFlags, GVarFlags,
> > std::move(Refs));
> > >>
> > >> GS->setModulePath(ModulePath);
> > >> + GS->setVTableFuncs(std::move(VTableFuncs));
> > >>
> > >> AddGlobalValueToIndex(Name, GUID,
> > (GlobalValue::LinkageTypes)GVFlags.Linkage,
> > >> ID, std::move(GS));
> > >> @@ -8235,6 +8336,67 @@ bool LLParser::ParseHotness(CalleeInfo::
> > >> return false;
> > >> }
> > >>
> > >> +/// OptionalVTableFuncs
> > >> +/// := 'vTableFuncs' ':' '(' VTableFunc [',' VTableFunc]* ')'
> > >> +/// VTableFunc ::= '(' 'virtFunc' ':' GVReference ',' 'offset'
> > ':' UInt64 ')'
> > >> +bool LLParser::ParseOptionalVTableFuncs(VTableFuncList
> > &VTableFuncs) {
> > >> + assert(Lex.getKind() == lltok::kw_vTableFuncs);
> > >> + Lex.Lex();
> > >> +
> > >> + if (ParseToken(lltok::colon, "expected ':' in vTableFuncs") |
> > >> + ParseToken(lltok::lparen, "expected '(' in vTableFuncs"))
> > >> + return true;
> > >> +
> > >> + IdToIndexMapType IdToIndexMap;
> > >> + // Parse each virtual function pair
> > >> + do {
> > >> + ValueInfo VI;
> > >> + if (ParseToken(lltok::lparen, "expected '(' in vTableFunc")
> ||
> > >> + ParseToken(lltok::kw_virtFunc, "expected 'callee' in
> > vTableFunc") ||
> > >> + ParseToken(lltok::colon, "expected ':'"))
> > >> + return true;
> > >> +
> > >> + LocTy Loc = Lex.getLoc();
> > >> + unsigned GVId;
> > >> + if (ParseGVReference(VI, GVId))
> > >> + return true;
> > >> +
> > >> + uint64_t Offset;
> > >> + if (ParseToken(lltok::comma, "expected comma") ||
> > >> + ParseToken(lltok::kw_offset, "expected offset") ||
> > >> + ParseToken(lltok::colon, "expected ':'") ||
> > ParseUInt64(Offset))
> > >> + return true;
> > >> +
> > >> + // Keep track of the VTableFuncs array index needing a
> > forward reference.
> > >> + // We will save the location of the ValueInfo needing an
> > update, but
> > >> + // can only do so once the std::vector is finalized.
> > >> + if (VI == EmptyVI)
> > >> +
> > IdToIndexMap[GVId].push_back(std::make_pair(VTableFuncs.size(),
> Loc));
> > >> + VTableFuncs.push_back({VI, Offset});
> > >> +
> > >> + if (ParseToken(lltok::rparen, "expected ')' in vTableFunc"))
> > >> + return true;
> > >> + } while (EatIfPresent(lltok::comma));
> > >> +
> > >> + // Now that the VTableFuncs vector is finalized, it is safe
> > to save the
> > >> + // locations of any forward GV references that need updating
> > later.
> > >> + for (auto I : IdToIndexMap) {
> > >> + for (auto P : I.second) {
> > >> + assert(VTableFuncs[P.first].FuncVI == EmptyVI &&
> > >> + "Forward referenced ValueInfo expected to be
> empty");
> > >> + auto FwdRef = ForwardRefValueInfos.insert(std::make_pair(
> > >> + I.first, std::vector<std::pair<ValueInfo *,
> LocTy>>()));
> > >> + FwdRef.first->second.push_back(
> > >> + std::make_pair(&VTableFuncs[P.first].FuncVI,
> P.second));
> > >> + }
> > >> + }
> > >> +
> > >> + if (ParseToken(lltok::rparen, "expected ')' in vTableFuncs"))
> > >> + return true;
> > >> +
> > >> + return false;
> > >> +}
> > >> +
> > >> /// OptionalRefs
> > >> /// := 'refs' ':' '(' GVReference [',' GVReference]* ')'
> > >> bool LLParser::ParseOptionalRefs(std::vector<ValueInfo>
> &Refs) {
> > >>
> > >> Modified: llvm/trunk/lib/AsmParser/LLParser.h
> > >> URL:
> >
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLParser.h?rev=364960&r1=364959&r2=364960&view=diff
> > >>
> >
> ==============================================================================
> > >> --- llvm/trunk/lib/AsmParser/LLParser.h (original)
> > >> +++ llvm/trunk/lib/AsmParser/LLParser.h Tue Jul 2 12:38:02 2019
> > >> @@ -369,9 +369,11 @@ namespace llvm {
> > >> IdToIndexMapType &IdToIndexMap,
> > unsigned Index);
> > >> bool ParseVFuncId(FunctionSummary::VFuncId &VFuncId,
> > >> IdToIndexMapType &IdToIndexMap,
> > unsigned Index);
> > >> + bool ParseOptionalVTableFuncs(VTableFuncList &VTableFuncs);
> > >> bool ParseOptionalRefs(std::vector<ValueInfo> &Refs);
> > >> bool ParseTypeIdEntry(unsigned ID);
> > >> bool ParseTypeIdSummary(TypeIdSummary &TIS);
> > >> + bool ParseTypeIdCompatibleVtableEntry(unsigned ID);
> > >> bool ParseTypeTestResolution(TypeTestResolution &TTRes);
> > >> bool ParseOptionalWpdResolutions(
> > >> std::map<uint64_t, WholeProgramDevirtResolution>
> > &WPDResMap);
> > >>
> > >> Modified: llvm/trunk/lib/AsmParser/LLToken.h
> > >> URL:
> >
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLToken.h?rev=364960&r1=364959&r2=364960&view=diff
> > >>
> >
> ==============================================================================
> > >> --- llvm/trunk/lib/AsmParser/LLToken.h (original)
> > >> +++ llvm/trunk/lib/AsmParser/LLToken.h Tue Jul 2 12:38:02 2019
> > >> @@ -383,6 +383,8 @@ enum Kind {
> > >> kw_critical,
> > >> kw_relbf,
> > >> kw_variable,
> > >> + kw_vTableFuncs,
> > >> + kw_virtFunc,
> > >> kw_aliasee,
> > >> kw_refs,
> > >> kw_typeIdInfo,
> > >> @@ -395,6 +397,7 @@ enum Kind {
> > >> kw_offset,
> > >> kw_args,
> > >> kw_typeid,
> > >> + kw_typeidCompatibleVTable,
> > >> kw_summary,
> > >> kw_typeTestRes,
> > >> kw_kind,
> > >>
> > >> Modified: llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp
> > >> URL:
> >
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp?rev=364960&r1=364959&r2=364960&view=diff
> > >>
> >
> ==============================================================================
> > >> --- llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp (original)
> > >> +++ llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp Tue Jul 2
> > 12:38:02 2019
> > >> @@ -828,6 +828,9 @@ private:
> > >> bool
> > HasRelBF);
> > >> Error parseEntireSummary(unsigned ID);
> > >> Error parseModuleStringTable();
> > >> + void
> > parseTypeIdCompatibleVtableSummaryRecord(ArrayRef<uint64_t> Record);
> > >> + void parseTypeIdCompatibleVtableInfo(ArrayRef<uint64_t>
> > Record, size_t &Slot,
> > >> +
> > TypeIdCompatibleVtableInfo &TypeId);
> > >>
> > >> std::pair<ValueInfo, GlobalValue::GUID>
> > >> getValueInfoFromValueId(unsigned ValueId);
> > >> @@ -5657,6 +5660,27 @@ static void parseTypeIdSummaryRecord(Arr
> > >> parseWholeProgramDevirtResolution(Record, Strtab, Slot,
> > TypeId);
> > >> }
> > >>
> > >> +void
> > ModuleSummaryIndexBitcodeReader::parseTypeIdCompatibleVtableInfo(
> > >> + ArrayRef<uint64_t> Record, size_t &Slot,
> > >> + TypeIdCompatibleVtableInfo &TypeId) {
> > >> + uint64_t Offset = Record[Slot++];
> > >> + ValueInfo Callee =
> getValueInfoFromValueId(Record[Slot++]).first;
> > >> + TypeId.push_back({Offset, Callee});
> > >> +}
> > >> +
> > >> +void
> >
> ModuleSummaryIndexBitcodeReader::parseTypeIdCompatibleVtableSummaryRecord(
> > >> + ArrayRef<uint64_t> Record) {
> > >> + size_t Slot = 0;
> > >> + TypeIdCompatibleVtableInfo &TypeId =
> > >> + TheIndex.getOrInsertTypeIdCompatibleVtableSummary(
> > >> + {Strtab.data() + Record[Slot],
> > >> + static_cast<size_t>(Record[Slot + 1])});
> > >> + Slot += 2;
> > >> +
> > >> + while (Slot < Record.size())
> > >> + parseTypeIdCompatibleVtableInfo(Record, Slot, TypeId);
> > >> +}
> > >> +
> > >> static void setImmutableRefs(std::vector<ValueInfo> &Refs,
> > unsigned Count) {
> > >> // Read-only refs are in the end of the refs list.
> > >> for (unsigned RefNo = Refs.size() - Count; RefNo <
> > Refs.size(); ++RefNo)
> > >> @@ -5883,6 +5907,34 @@ Error ModuleSummaryIndexBitcodeReader::p
> > >> TheIndex.addGlobalValueSummary(GUID.first,
> std::move(FS));
> > >> break;
> > >> }
> > >> + // FS_PERMODULE_VTABLE_GLOBALVAR_INIT_REFS: [valueid,
> > flags, varflags,
> > >> + // numrefs, numrefs x valueid,
> > >> + // n x (valueid, offset)]
> > >> + case bitc::FS_PERMODULE_VTABLE_GLOBALVAR_INIT_REFS: {
> > >> + unsigned ValueID = Record[0];
> > >> + uint64_t RawFlags = Record[1];
> > >> + GlobalVarSummary::GVarFlags GVF =
> > getDecodedGVarFlags(Record[2]);
> > >> + unsigned NumRefs = Record[3];
> > >> + unsigned RefListStartIndex = 4;
> > >> + unsigned VTableListStartIndex = RefListStartIndex +
> NumRefs;
> > >> + auto Flags = getDecodedGVSummaryFlags(RawFlags, Version);
> > >> + std::vector<ValueInfo> Refs = makeRefList(
> > >> + ArrayRef<uint64_t>(Record).slice(RefListStartIndex,
> > NumRefs));
> > >> + VTableFuncList VTableFuncs;
> > >> + for (unsigned I = VTableListStartIndex, E =
> > Record.size(); I != E; ++I) {
> > >> + ValueInfo Callee =
> > getValueInfoFromValueId(Record[I]).first;
> > >> + uint64_t Offset = Record[++I];
> > >> + VTableFuncs.push_back({Callee, Offset});
> > >> + }
> > >> + auto VS =
> > >> + llvm::make_unique<GlobalVarSummary>(Flags, GVF,
> > std::move(Refs));
> > >> + VS->setModulePath(getThisModule()->first());
> > >> + VS->setVTableFuncs(VTableFuncs);
> > >> + auto GUID = getValueInfoFromValueId(ValueID);
> > >> + VS->setOriginalName(GUID.second);
> > >> + TheIndex.addGlobalValueSummary(GUID.first, std::move(VS));
> > >> + break;
> > >> + }
> > >> // FS_COMBINED: [valueid, modid, flags, instcount,
> > fflags, numrefs,
> > >> // numrefs x valueid, n x (valueid)]
> > >> // FS_COMBINED_PROFILE: [valueid, modid, flags,
> > instcount, fflags, numrefs,
> > >> @@ -6049,6 +6101,10 @@ Error ModuleSummaryIndexBitcodeReader::p
> > >> case bitc::FS_TYPE_ID:
> > >> parseTypeIdSummaryRecord(Record, Strtab, TheIndex);
> > >> break;
> > >> +
> > >> + case bitc::FS_TYPE_ID_METADATA:
> > >> + parseTypeIdCompatibleVtableSummaryRecord(Record);
> > >> + break;
> > >> }
> > >> }
> > >> llvm_unreachable("Exit infinite loop");
> > >>
> > >> Modified: llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp
> > >> URL:
> >
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp?rev=364960&r1=364959&r2=364960&view=diff
> > >>
> >
> ==============================================================================
> > >> --- llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp (original)
> > >> +++ llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp Tue Jul 2
> > 12:38:02 2019
> > >> @@ -214,7 +214,8 @@ private:
> > >> const Function &F);
> > >> void writeModuleLevelReferences(const GlobalVariable &V,
> > >> SmallVector<uint64_t, 64>
> > &NameVals,
> > >> - unsigned FSModRefsAbbrev);
> > >> + unsigned FSModRefsAbbrev,
> > >> + unsigned
> FSModVTableRefsAbbrev);
> > >>
> > >> void assignValueId(GlobalValue::GUID ValGUID) {
> > >> GUIDToValueIdMap[ValGUID] = ++GlobalValueId;
> > >> @@ -3605,6 +3606,19 @@ static void writeTypeIdSummaryRecord(Sma
> > >> W.second);
> > >> }
> > >>
> > >> +static void writeTypeIdCompatibleVtableSummaryRecord(
> > >> + SmallVector<uint64_t, 64> &NameVals, StringTableBuilder
> > &StrtabBuilder,
> > >> + const std::string &Id, const TypeIdCompatibleVtableInfo
> > &Summary,
> > >> + ValueEnumerator &VE) {
> > >> + NameVals.push_back(StrtabBuilder.add(Id));
> > >> + NameVals.push_back(Id.size());
> > >> +
> > >> + for (auto &P : Summary) {
> > >> + NameVals.push_back(P.AddressPointOffset);
> > >> + NameVals.push_back(VE.getValueID(P.VTableVI.getValue()));
> > >> + }
> > >> +}
> > >> +
> > >> // Helper to emit a single function summary record.
> > >> void
> > ModuleBitcodeWriterBase::writePerModuleFunctionSummaryRecord(
> > >> SmallVector<uint64_t, 64> &NameVals, GlobalValueSummary
> > *Summary,
> > >> @@ -3649,7 +3663,7 @@ void ModuleBitcodeWriterBase::writePerMo
> > >> // and emit them in a summary record.
> > >> void ModuleBitcodeWriterBase::writeModuleLevelReferences(
> > >> const GlobalVariable &V, SmallVector<uint64_t, 64>
> &NameVals,
> > >> - unsigned FSModRefsAbbrev) {
> > >> + unsigned FSModRefsAbbrev, unsigned FSModVTableRefsAbbrev) {
> > >> auto VI = Index->getValueInfo(V.getGUID());
> > >> if (!VI || VI.getSummaryList().empty()) {
> > >> // Only declarations should not have a summary (a
> > declaration might however
> > >> @@ -3663,6 +3677,10 @@ void ModuleBitcodeWriterBase::writeModul
> > >> NameVals.push_back(getEncodedGVSummaryFlags(VS->flags()));
> > >> NameVals.push_back(getEncodedGVarFlags(VS->varflags()));
> > >>
> > >> + auto VTableFuncs = VS->vTableFuncs();
> > >> + if (!VTableFuncs.empty())
> > >> + NameVals.push_back(VS->refs().size());
> > >> +
> > >> unsigned SizeBeforeRefs = NameVals.size();
> > >> for (auto &RI : VS->refs())
> > >> NameVals.push_back(VE.getValueID(RI.getValue()));
> > >> @@ -3670,8 +3688,20 @@ void ModuleBitcodeWriterBase::writeModul
> > >> // been initialized from a DenseSet.
> > >> llvm::sort(NameVals.begin() + SizeBeforeRefs,
> NameVals.end());
> > >>
> > >> - Stream.EmitRecord(bitc::FS_PERMODULE_GLOBALVAR_INIT_REFS,
> > NameVals,
> > >> - FSModRefsAbbrev);
> > >> + if (!VTableFuncs.empty()) {
> > >> + // VTableFuncs pairs should already be sorted by offset.
> > >> + for (auto &P : VTableFuncs) {
> > >> + NameVals.push_back(VE.getValueID(P.FuncVI.getValue()));
> > >> + NameVals.push_back(P.VTableOffset);
> > >> + }
> > >> + }
> > >> +
> > >> + if (VTableFuncs.empty())
> > >> + Stream.EmitRecord(bitc::FS_PERMODULE_GLOBALVAR_INIT_REFS,
> > NameVals,
> > >> + FSModRefsAbbrev);
> > >> + else
> > >> +
> > Stream.EmitRecord(bitc::FS_PERMODULE_VTABLE_GLOBALVAR_INIT_REFS,
> > NameVals,
> > >> + FSModVTableRefsAbbrev);
> > >> NameVals.clear();
> > >> }
> > >>
> > >> @@ -3752,6 +3782,17 @@ void ModuleBitcodeWriterBase::writePerMo
> > >> Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));
> > >> unsigned FSModRefsAbbrev =
> Stream.EmitAbbrev(std::move(Abbv));
> > >>
> > >> + // Abbrev for FS_PERMODULE_VTABLE_GLOBALVAR_INIT_REFS.
> > >> + Abbv = std::make_shared<BitCodeAbbrev>();
> > >> +
> >
> Abbv->Add(BitCodeAbbrevOp(bitc::FS_PERMODULE_VTABLE_GLOBALVAR_INIT_REFS));
> > >> + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); //
> valueid
> > >> + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // flags
> > >> + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 4)); //
> numrefs
> > >> + // numrefs x valueid, n x (valueid , offset)
> > >> + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
> > >> + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));
> > >> + unsigned FSModVTableRefsAbbrev =
> > Stream.EmitAbbrev(std::move(Abbv));
> > >> +
> > >> // Abbrev for FS_ALIAS.
> > >> Abbv = std::make_shared<BitCodeAbbrev>();
> > >> Abbv->Add(BitCodeAbbrevOp(bitc::FS_ALIAS));
> > >> @@ -3760,6 +3801,16 @@ void ModuleBitcodeWriterBase::writePerMo
> > >> Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); //
> > valueid
> > >> unsigned FSAliasAbbrev = Stream.EmitAbbrev(std::move(Abbv));
> > >>
> > >> + // Abbrev for FS_TYPE_ID_METADATA
> > >> + Abbv = std::make_shared<BitCodeAbbrev>();
> > >> + Abbv->Add(BitCodeAbbrevOp(bitc::FS_TYPE_ID_METADATA));
> > >> + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); //
> > typeid strtab index
> > >> + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); //
> > typeid length
> > >> + // n x (valueid , offset)
> > >> + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
> > >> + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));
> > >> + unsigned TypeIdCompatibleVtableAbbrev =
> > Stream.EmitAbbrev(std::move(Abbv));
> > >> +
> > >> SmallVector<uint64_t, 64> NameVals;
> > >> // Iterate over the list of functions instead of the Index
> to
> > >> // ensure the ordering is stable.
> > >> @@ -3784,7 +3835,8 @@ void ModuleBitcodeWriterBase::writePerMo
> > >> // Capture references from GlobalVariable initializers,
> > which are outside
> > >> // of a function scope.
> > >> for (const GlobalVariable &G : M.globals())
> > >> - writeModuleLevelReferences(G, NameVals, FSModRefsAbbrev);
> > >> + writeModuleLevelReferences(G, NameVals, FSModRefsAbbrev,
> > >> + FSModVTableRefsAbbrev);
> > >>
> > >> for (const GlobalAlias &A : M.aliases()) {
> > >> auto *Aliasee = A.getBaseObject();
> > >> @@ -3802,6 +3854,16 @@ void ModuleBitcodeWriterBase::writePerMo
> > >> NameVals.clear();
> > >> }
> > >>
> > >> + if (!Index->typeIdCompatibleVtableMap().empty()) {
> > >> + for (auto &S : Index->typeIdCompatibleVtableMap()) {
> > >> + writeTypeIdCompatibleVtableSummaryRecord(NameVals,
> > StrtabBuilder, S.first,
> > >> + S.second, VE);
> > >> + Stream.EmitRecord(bitc::FS_TYPE_ID_METADATA, NameVals,
> > >> + TypeIdCompatibleVtableAbbrev);
> > >> + NameVals.clear();
> > >> + }
> > >> + }
> > >> +
> > >> Stream.ExitBlock();
> > >> }
> > >>
> > >>
> > >> Modified: llvm/trunk/lib/IR/AsmWriter.cpp
> > >> URL:
> >
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/AsmWriter.cpp?rev=364960&r1=364959&r2=364960&view=diff
> > >>
> >
> ==============================================================================
> > >> --- llvm/trunk/lib/IR/AsmWriter.cpp (original)
> > >> +++ llvm/trunk/lib/IR/AsmWriter.cpp Tue Jul 2 12:38:02 2019
> > >> @@ -1037,6 +1037,9 @@ void SlotTracker::processIndex() {
> > >> TidIter != TheIndex->typeIds().end(); TidIter++)
> > >> CreateTypeIdSlot(TidIter->second.first);
> > >>
> > >> + for (auto &TId : TheIndex->typeIdCompatibleVtableMap())
> > >> + CreateGUIDSlot(GlobalValue::getGUID(TId.first));
> > >> +
> > >> ST_DEBUG("end processIndex!\n");
> > >> }
> > >>
> > >> @@ -2410,6 +2413,7 @@ public:
> > >> void printGlobalVarSummary(const GlobalVarSummary *GS);
> > >> void printFunctionSummary(const FunctionSummary *FS);
> > >> void printTypeIdSummary(const TypeIdSummary &TIS);
> > >> + void printTypeIdCompatibleVtableSummary(const
> > TypeIdCompatibleVtableInfo &TI);
> > >> void printTypeTestResolution(const TypeTestResolution
> &TTRes);
> > >> void printArgs(const std::vector<uint64_t> &Args);
> > >> void printWPDRes(const WholeProgramDevirtResolution
> &WPDRes);
> > >> @@ -2712,6 +2716,15 @@ void AssemblyWriter::printModuleSummaryI
> > >> printTypeIdSummary(TidIter->second.second);
> > >> Out << ") ; guid = " << TidIter->first << "\n";
> > >> }
> > >> +
> > >> + // Print the TypeIdCompatibleVtableMap entries.
> > >> + for (auto &TId : TheIndex->typeIdCompatibleVtableMap()) {
> > >> + auto GUID = GlobalValue::getGUID(TId.first);
> > >> + Out << "^" << Machine.getGUIDSlot(GUID)
> > >> + << " = typeidCompatibleVTable: (name: \"" << TId.first
> > << "\"";
> > >> + printTypeIdCompatibleVtableSummary(TId.second);
> > >> + Out << ") ; guid = " << GUID << "\n";
> > >> + }
> > >> }
> > >>
> > >> static const char *
> > >> @@ -2794,6 +2807,19 @@ void AssemblyWriter::printTypeIdSummary(
> > >> Out << ")";
> > >> }
> > >>
> > >> +void AssemblyWriter::printTypeIdCompatibleVtableSummary(
> > >> + const TypeIdCompatibleVtableInfo &TI) {
> > >> + Out << ", summary: (";
> > >> + FieldSeparator FS;
> > >> + for (auto &P : TI) {
> > >> + Out << FS;
> > >> + Out << "(offset: " << P.AddressPointOffset << ", ";
> > >> + Out << "^" << Machine.getGUIDSlot(P.VTableVI.getGUID());
> > >> + Out << ")";
> > >> + }
> > >> + Out << ")";
> > >> +}
> > >> +
> > >> void AssemblyWriter::printArgs(const std::vector<uint64_t>
> > &Args) {
> > >> Out << "args: (";
> > >> FieldSeparator FS;
> > >> @@ -2863,6 +2889,19 @@ void AssemblyWriter::printAliasSummary(c
> > >>
> > >> void AssemblyWriter::printGlobalVarSummary(const
> > GlobalVarSummary *GS) {
> > >> Out << ", varFlags: (readonly: " << GS->VarFlags.ReadOnly
> > << ")";
> > >> +
> > >> + auto VTableFuncs = GS->vTableFuncs();
> > >> + if (!VTableFuncs.empty()) {
> > >> + Out << ", vTableFuncs: (";
> > >> + FieldSeparator FS;
> > >> + for (auto &P : VTableFuncs) {
> > >> + Out << FS;
> > >> + Out << "(virtFunc: ^" <<
> > Machine.getGUIDSlot(P.FuncVI.getGUID())
> > >> + << ", offset: " << P.VTableOffset;
> > >> + Out << ")";
> > >> + }
> > >> + Out << ")";
> > >> + }
> > >> }
> > >>
> > >> static std::string getLinkageName(GlobalValue::LinkageTypes
> LT) {
> > >>
> > >> Modified: llvm/trunk/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp
> > >> URL:
> >
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp?rev=364960&r1=364959&r2=364960&view=diff
> > >>
> >
> ==============================================================================
> > >> --- llvm/trunk/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp
> > (original)
> > >> +++ llvm/trunk/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp Tue
> > Jul 2 12:38:02 2019
> > >> @@ -417,34 +417,53 @@ void splitAndWriteThinLTOBitcode(
> > >> }
> > >> }
> > >>
> > >> -// Returns whether this module needs to be split because
> > splitting is
> > >> -// enabled and it uses type metadata.
> > >> -bool requiresSplit(Module &M) {
> > >> - // First check if the LTO Unit splitting has been enabled.
> > >> +// Check if the LTO Unit splitting has been enabled.
> > >> +bool enableSplitLTOUnit(Module &M) {
> > >> bool EnableSplitLTOUnit = false;
> > >> if (auto *MD = mdconst::extract_or_null<ConstantInt>(
> > >> M.getModuleFlag("EnableSplitLTOUnit")))
> > >> EnableSplitLTOUnit = MD->getZExtValue();
> > >> - if (!EnableSplitLTOUnit)
> > >> - return false;
> > >> + return EnableSplitLTOUnit;
> > >> +}
> > >>
> > >> - // Module only needs to be split if it contains type metadata.
> > >> +// Returns whether this module needs to be split because it
> > uses type metadata.
> > >> +bool hasTypeMetadata(Module &M) {
> > >> for (auto &GO : M.global_objects()) {
> > >> if (GO.hasMetadata(LLVMContext::MD_type))
> > >> return true;
> > >> }
> > >> -
> > >> return false;
> > >> }
> > >>
> > >> void writeThinLTOBitcode(raw_ostream &OS, raw_ostream
> > *ThinLinkOS,
> > >> function_ref<AAResults &(Function
> > &)> AARGetter,
> > >> Module &M, const ModuleSummaryIndex
> > *Index) {
> > >> - // Split module if splitting is enabled and it contains any
> > type metadata.
> > >> - if (requiresSplit(M))
> > >> - return splitAndWriteThinLTOBitcode(OS, ThinLinkOS,
> > AARGetter, M);
> > >> + std::unique_ptr<ModuleSummaryIndex> NewIndex = nullptr;
> > >> + // See if this module has any type metadata. If so, we try to
> > split it
> > >> + // or at least promote type ids to enable WPD.
> > >> + if (hasTypeMetadata(M)) {
> > >> + if (enableSplitLTOUnit(M))
> > >> + return splitAndWriteThinLTOBitcode(OS, ThinLinkOS,
> > AARGetter, M);
> > >> + // Promote type ids as needed for index-based WPD.
> > >> + std::string ModuleId = getUniqueModuleId(&M);
> > >> + if (!ModuleId.empty()) {
> > >> + promoteTypeIds(M, ModuleId);
> > >> + // Need to rebuild the index so that it contains type
> > metadata
> > >> + // for the newly promoted type ids.
> > >> + // FIXME: Probably should not bother building the index
> > at all
> > >> + // in the caller of writeThinLTOBitcode (which does so
> > via the
> > >> + // ModuleSummaryIndexAnalysis pass), since we have to
> > rebuild it
> > >> + // anyway whenever there is type metadata (here or in
> > >> + // splitAndWriteThinLTOBitcode). Just always build it
> > once via the
> > >> + // buildModuleSummaryIndex when Module(s) are ready.
> > >> + ProfileSummaryInfo PSI(M);
> > >> + NewIndex = llvm::make_unique<ModuleSummaryIndex>(
> > >> + buildModuleSummaryIndex(M, nullptr, &PSI));
> > >> + Index = NewIndex.get();
> > >> + }
> > >> + }
> > >>
> > >> - // Otherwise we can just write it out as a regular module.
> > >> + // Write it out as an unsplit ThinLTO module.
> > >>
> > >> // Save the module hash produced for the full bitcode,
> > which will
> > >> // be used in the backends, and use that in the minimized
> > bitcode
> > >>
> > >> Added: llvm/trunk/test/Assembler/thinlto-vtable-summary.ll
> > >> URL:
> >
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Assembler/thinlto-vtable-summary.ll?rev=364960&view=auto
> > >>
> >
> ==============================================================================
> > >> --- llvm/trunk/test/Assembler/thinlto-vtable-summary.ll (added)
> > >> +++ llvm/trunk/test/Assembler/thinlto-vtable-summary.ll Tue Jul
> > 2 12:38:02 2019
> > >> @@ -0,0 +1,38 @@
> > >> +; Test summary parsing of index-based WPD related summary fields
> > >> +; RUN: llvm-as %s -o - | llvm-dis -o %t.ll
> > >> +; RUN: grep "^\^" %s >%t2
> > >> +; RUN: grep "^\^" %t.ll >%t3
> > >> +; Expect that the summary information is the same after
> > round-trip through
> > >> +; llvm-as and llvm-dis.
> > >> +; RUN: diff %t2 %t3
> > >> +
> > >> +source_filename = "thinlto-vtable-summary.ll"
> > >> +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
> > >> +target triple = "x86_64-grtev4-linux-gnu"
> > >> +
> > >> +%struct.A = type { i32 (...)** }
> > >> +%struct.B = type { %struct.A }
> > >> +%struct.C = type { %struct.A }
> > >> +
> > >> + at _ZTV1B = constant { [4 x i8*] } { [4 x i8*] [i8* null, i8*
> > undef, i8* bitcast (i32 (%struct.B*, i32)* @_ZN1B1fEi to i8*), i8*
> > bitcast (i32 (%struct.A*, i32)* @_ZN1A1nEi to i8*)] }, !type !0,
> > !type !1
> > >> + at _ZTV1C = constant { [4 x i8*] } { [4 x i8*] [i8* null, i8*
> > undef, i8* bitcast (i32 (%struct.C*, i32)* @_ZN1C1fEi to i8*), i8*
> > bitcast (i32 (%struct.A*, i32)* @_ZN1A1nEi to i8*)] }, !type !0,
> > !type !2
> > >> +
> > >> +declare i32 @_ZN1B1fEi(%struct.B*, i32)
> > >> +
> > >> +declare i32 @_ZN1A1nEi(%struct.A*, i32)
> > >> +
> > >> +declare i32 @_ZN1C1fEi(%struct.C*, i32)
> > >> +
> > >> +!0 = !{i64 16, !"_ZTS1A"}
> > >> +!1 = !{i64 16, !"_ZTS1B"}
> > >> +!2 = !{i64 16, !"_ZTS1C"}
> > >> +
> > >> +^0 = module: (path: "<stdin>", hash: (0, 0, 0, 0, 0))
> > >> +^1 = gv: (name: "_ZN1A1nEi") ; guid = 1621563287929432257
> > >> +^2 = gv: (name: "_ZTV1B", summaries: (variable: (module: ^0,
> > flags: (linkage: external, notEligibleToImport: 0, live: 0,
> > dsoLocal: 0, canAutoHide: 0), varFlags: (readonly: 0), vTableFuncs:
> > ((virtFunc: ^3, offset: 16), (virtFunc: ^1, offset: 24)), refs: (^3,
> > ^1)))) ; guid = 5283576821522790367
> > >> +^3 = gv: (name: "_ZN1B1fEi") ; guid = 7162046368816414394
> > >> +^4 = gv: (name: "_ZTV1C", summaries: (variable: (module: ^0,
> > flags: (linkage: external, notEligibleToImport: 0, live: 0,
> > dsoLocal: 0, canAutoHide: 0), varFlags: (readonly: 0), vTableFuncs:
> > ((virtFunc: ^5, offset: 16), (virtFunc: ^1, offset: 24)), refs: (^1,
> > ^5)))) ; guid = 13624023785555846296
> > >> +^5 = gv: (name: "_ZN1C1fEi") ; guid = 14876272565662207556
> > >> +^6 = typeidCompatibleVTable: (name: "_ZTS1A", summary:
> > ((offset: 16, ^2), (offset: 16, ^4))) ; guid = 7004155349499253778
> > >> +^7 = typeidCompatibleVTable: (name: "_ZTS1B", summary:
> > ((offset: 16, ^2))) ; guid = 6203814149063363976
> > >> +^8 = typeidCompatibleVTable: (name: "_ZTS1C", summary:
> > ((offset: 16, ^4))) ; guid = 1884921850105019584
> > >>
> > >> Added: llvm/trunk/test/ThinLTO/X86/devirt.ll
> > >> URL:
> >
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/ThinLTO/X86/devirt.ll?rev=364960&view=auto
> > >>
> >
> ==============================================================================
> > >> --- llvm/trunk/test/ThinLTO/X86/devirt.ll (added)
> > >> +++ llvm/trunk/test/ThinLTO/X86/devirt.ll Tue Jul 2 12:38:02
> 2019
> > >> @@ -0,0 +1,146 @@
> > >> +; REQUIRES: x86-registered-target
> > >> +
> > >> +; Test devirtualization through the thin link and backend.
> > >> +
> > >> +; Generate split module with summary for hybrid Thin/Regular
> > LTO WPD.
> > >> +; RUN: opt -thinlto-bc -thinlto-split-lto-unit -o %t.o %s
> > >> +
> > >> +; Check that we have module flag showing splitting enabled, and
> > that we don't
> > >> +; generate summary information needed for index-based WPD.
> > >> +; RUN: llvm-modextract -b -n=0 %t.o -o %t.o.0
> > >> +; RUN: llvm-dis -o - %t.o.0 | FileCheck %s
> > --check-prefix=ENABLESPLITFLAG --implicit-check-not=vTableFuncs
> > --implicit-check-not=typeidCompatibleVTable
> > >> +; RUN: llvm-modextract -b -n=1 %t.o -o %t.o.1
> > >> +; RUN: llvm-dis -o - %t.o.1 | FileCheck %s
> > --check-prefix=ENABLESPLITFLAG --implicit-check-not=vTableFuncs
> > --implicit-check-not=typeidCompatibleVTable
> > >> +; ENABLESPLITFLAG: !{i32 1, !"EnableSplitLTOUnit", i32 1}
> > >> +
> > >> +; Generate unsplit module with summary for ThinLTO index-based
> WPD.
> > >> +; RUN: opt -thinlto-bc -o %t2.o %s
> > >> +
> > >> +; Check that we don't have module flag when splitting not
> > enabled for ThinLTO,
> > >> +; and that we generate summary information needed for
> > index-based WPD.
> > >> +; RUN: llvm-dis -o - %t2.o | FileCheck %s
> > --check-prefix=NOENABLESPLITFLAG
> > >> +; NOENABLESPLITFLAG-DAG: !{i32 1, !"EnableSplitLTOUnit", i32 0}
> > >> +; NOENABLESPLITFLAG-DAG: [[An:\^[0-9]+]] = gv: (name:
> "_ZN1A1nEi")
> > >> +; NOENABLESPLITFLAG-DAG: [[Bf:\^[0-9]+]] = gv: (name:
> "_ZN1B1fEi")
> > >> +; NOENABLESPLITFLAG-DAG: [[Cf:\^[0-9]+]] = gv: (name:
> "_ZN1C1fEi")
> > >> +; NOENABLESPLITFLAG-DAG: [[Dm:\^[0-9]+]] = gv: (name:
> "_ZN1D1mEi")
> > >> +; NOENABLESPLITFLAG-DAG: [[B:\^[0-9]+]] = gv: (name: "_ZTV1B",
> > {{.*}} vTableFuncs: ((virtFunc: [[Bf]], offset: 16), (virtFunc:
> > [[An]], offset: 24)), refs: ([[Bf]], [[An]])
> > >> +; NOENABLESPLITFLAG-DAG: [[C:\^[0-9]+]] = gv: (name: "_ZTV1C",
> > {{.*}} vTableFuncs: ((virtFunc: [[Cf]], offset: 16), (virtFunc:
> > [[An]], offset: 24)), refs: ([[An]], [[Cf]])
> > >> +; NOENABLESPLITFLAG-DAG: [[D:\^[0-9]+]] = gv: (name: "_ZTV1D",
> > {{.*}} vTableFuncs: ((virtFunc: [[Dm]], offset: 16)), refs: ([[Dm]])
> > >> +; NOENABLESPLITFLAG-DAG: typeidCompatibleVTable: (name:
> > "_ZTS1A", summary: ((offset: 16, [[B]]), (offset: 16, [[C]])))
> > >> +; NOENABLESPLITFLAG-DAG: typeidCompatibleVTable: (name:
> > "_ZTS1B", summary: ((offset: 16, [[B]])))
> > >> +; NOENABLESPLITFLAG-DAG: typeidCompatibleVTable: (name:
> > "_ZTS1C", summary: ((offset: 16, [[C]])))
> > >> +; Type Id on _ZTV1D should have been promoted
> > >> +; NOENABLESPLITFLAG-DAG: typeidCompatibleVTable: (name:
> > "1${{.*}}", summary: ((offset: 16, [[D]])))
> > >> +
> > >> +; TODO: Test index-based WPD one %t2.o once implemented.
> > >> +
> > >> +; Legacy PM
> > >> +; RUN: llvm-lto2 run %t.o -save-temps -pass-remarks=. \
> > >> +; RUN: -o %t3 \
> > >> +; RUN: -r=%t.o,test,px \
> > >> +; RUN: -r=%t.o,_ZN1A1nEi,p \
> > >> +; RUN: -r=%t.o,_ZN1B1fEi,p \
> > >> +; RUN: -r=%t.o,_ZN1C1fEi,p \
> > >> +; RUN: -r=%t.o,_ZN1D1mEi,p \
> > >> +; RUN: -r=%t.o,_ZTV1B, \
> > >> +; RUN: -r=%t.o,_ZTV1C, \
> > >> +; RUN: -r=%t.o,_ZTV1D, \
> > >> +; RUN: -r=%t.o,_ZN1A1nEi, \
> > >> +; RUN: -r=%t.o,_ZN1B1fEi, \
> > >> +; RUN: -r=%t.o,_ZN1C1fEi, \
> > >> +; RUN: -r=%t.o,_ZN1D1mEi, \
> > >> +; RUN: -r=%t.o,_ZTV1B,px \
> > >> +; RUN: -r=%t.o,_ZTV1C,px \
> > >> +; RUN: -r=%t.o,_ZTV1D,px 2>&1 | FileCheck %s
> > --check-prefix=REMARK
> > >> +; RUN: llvm-dis %t3.1.4.opt.bc -o - | FileCheck %s
> > --check-prefix=CHECK-IR
> > >> +
> > >> +; New PM
> > >> +; RUN: llvm-lto2 run %t.o -save-temps -use-new-pm
> -pass-remarks=. \
> > >> +; RUN: -o %t3 \
> > >> +; RUN: -r=%t.o,test,px \
> > >> +; RUN: -r=%t.o,_ZN1A1nEi,p \
> > >> +; RUN: -r=%t.o,_ZN1B1fEi,p \
> > >> +; RUN: -r=%t.o,_ZN1C1fEi,p \
> > >> +; RUN: -r=%t.o,_ZN1D1mEi,p \
> > >> +; RUN: -r=%t.o,_ZTV1B, \
> > >> +; RUN: -r=%t.o,_ZTV1C, \
> > >> +; RUN: -r=%t.o,_ZTV1D, \
> > >> +; RUN: -r=%t.o,_ZN1A1nEi, \
> > >> +; RUN: -r=%t.o,_ZN1B1fEi, \
> > >> +; RUN: -r=%t.o,_ZN1C1fEi, \
> > >> +; RUN: -r=%t.o,_ZN1D1mEi, \
> > >> +; RUN: -r=%t.o,_ZTV1B,px \
> > >> +; RUN: -r=%t.o,_ZTV1C,px \
> > >> +; RUN: -r=%t.o,_ZTV1D,px 2>&1 | FileCheck %s
> > --check-prefix=REMARK
> > >> +; RUN: llvm-dis %t3.1.4.opt.bc -o - | FileCheck %s
> > --check-prefix=CHECK-IR
> > >> +
> > >> +; REMARK-DAG: single-impl: devirtualized a call to _ZN1A1nEi
> > >> +; REMARK-DAG: single-impl: devirtualized a call to _ZN1D1mEi
> > >> +
> > >> +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
> > >> +target triple = "x86_64-grtev4-linux-gnu"
> > >> +
> > >> +%struct.A = type { i32 (...)** }
> > >> +%struct.B = type { %struct.A }
> > >> +%struct.C = type { %struct.A }
> > >> +%struct.D = type { i32 (...)** }
> > >> +
> > >> + at _ZTV1B = constant { [4 x i8*] } { [4 x i8*] [i8* null, i8*
> > undef, i8* bitcast (i32 (%struct.B*, i32)* @_ZN1B1fEi to i8*), i8*
> > bitcast (i32 (%struct.A*, i32)* @_ZN1A1nEi to i8*)] }, !type !0,
> > !type !1
> > >> + at _ZTV1C = constant { [4 x i8*] } { [4 x i8*] [i8* null, i8*
> > undef, i8* bitcast (i32 (%struct.C*, i32)* @_ZN1C1fEi to i8*), i8*
> > bitcast (i32 (%struct.A*, i32)* @_ZN1A1nEi to i8*)] }, !type !0,
> > !type !2
> > >> + at _ZTV1D = constant { [3 x i8*] } { [3 x i8*] [i8* null, i8*
> > undef, i8* bitcast (i32 (%struct.D*, i32)* @_ZN1D1mEi to i8*)] },
> > !type !3
> > >> +
> > >> +
> > >> +; CHECK-IR-LABEL: define i32 @test
> > >> +define i32 @test(%struct.A* %obj, %struct.D* %obj2, i32 %a) {
> > >> +entry:
> > >> + %0 = bitcast %struct.A* %obj to i8***
> > >> + %vtable = load i8**, i8*** %0
> > >> + %1 = bitcast i8** %vtable to i8*
> > >> + %p = call i1 @llvm.type.test(i8* %1, metadata !"_ZTS1A")
> > >> + call void @llvm.assume(i1 %p)
> > >> + %fptrptr = getelementptr i8*, i8** %vtable, i32 1
> > >> + %2 = bitcast i8** %fptrptr to i32 (%struct.A*, i32)**
> > >> + %fptr1 = load i32 (%struct.A*, i32)*, i32 (%struct.A*, i32)**
> > %2, align 8
> > >> +
> > >> + ; Check that the call was devirtualized.
> > >> + ; CHECK-IR: %call = tail call i32 @_ZN1A1nEi
> > >> + %call = tail call i32 %fptr1(%struct.A* nonnull %obj, i32 %a)
> > >> +
> > >> + %3 = bitcast i8** %vtable to i32 (%struct.A*, i32)**
> > >> + %fptr22 = load i32 (%struct.A*, i32)*, i32 (%struct.A*,
> > i32)** %3, align 8
> > >> +
> > >> + ; We still have to call it as virtual.
> > >> + ; CHECK-IR: %call3 = tail call i32 %fptr22
> > >> + %call3 = tail call i32 %fptr22(%struct.A* nonnull %obj, i32
> > %call)
> > >> +
> > >> + %4 = bitcast %struct.D* %obj2 to i8***
> > >> + %vtable2 = load i8**, i8*** %4
> > >> + %5 = bitcast i8** %vtable2 to i8*
> > >> + %p2 = call i1 @llvm.type.test(i8* %5, metadata !4)
> > >> + call void @llvm.assume(i1 %p2)
> > >> +
> > >> + %6 = bitcast i8** %vtable2 to i32 (%struct.D*, i32)**
> > >> + %fptr33 = load i32 (%struct.D*, i32)*, i32 (%struct.D*,
> > i32)** %6, align 8
> > >> +
> > >> + ; Check that the call was devirtualized.
> > >> + ; CHECK-IR: %call4 = tail call i32 @_ZN1D1mEi
> > >> + %call4 = tail call i32 %fptr33(%struct.D* nonnull %obj2, i32
> > %call3)
> > >> + ret i32 %call4
> > >> +}
> > >> +; CHECK-IR-LABEL: ret i32
> > >> +; CHECK-IR-LABEL: }
> > >> +
> > >> +declare i1 @llvm.type.test(i8*, metadata)
> > >> +declare void @llvm.assume(i1)
> > >> +
> > >> +declare i32 @_ZN1B1fEi(%struct.B* %this, i32 %a)
> > >> +declare i32 @_ZN1A1nEi(%struct.A* %this, i32 %a)
> > >> +declare i32 @_ZN1C1fEi(%struct.C* %this, i32 %a)
> > >> +declare i32 @_ZN1D1mEi(%struct.D* %this, i32 %a)
> > >> +
> > >> +!0 = !{i64 16, !"_ZTS1A"}
> > >> +!1 = !{i64 16, !"_ZTS1B"}
> > >> +!2 = !{i64 16, !"_ZTS1C"}
> > >> +!3 = !{i64 16, !4}
> > >> +!4 = distinct !{}
> > >>
> > >> Modified: llvm/trunk/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp
> > >> URL:
> >
> http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp?rev=364960&r1=364959&r2=364960&view=diff
> > >>
> >
> ==============================================================================
> > >> --- llvm/trunk/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp
> (original)
> > >> +++ llvm/trunk/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp Tue
> > Jul 2 12:38:02 2019
> > >> @@ -317,6 +317,7 @@ static const char *GetCodeName(unsigned
> > >> STRINGIFY_CODE(FS, PERMODULE_PROFILE)
> > >> STRINGIFY_CODE(FS, PERMODULE_RELBF)
> > >> STRINGIFY_CODE(FS, PERMODULE_GLOBALVAR_INIT_REFS)
> > >> + STRINGIFY_CODE(FS, PERMODULE_VTABLE_GLOBALVAR_INIT_REFS)
> > >> STRINGIFY_CODE(FS, COMBINED)
> > >> STRINGIFY_CODE(FS, COMBINED_PROFILE)
> > >> STRINGIFY_CODE(FS, COMBINED_GLOBALVAR_INIT_REFS)
> > >> @@ -334,6 +335,7 @@ static const char *GetCodeName(unsigned
> > >> STRINGIFY_CODE(FS, CFI_FUNCTION_DEFS)
> > >> STRINGIFY_CODE(FS, CFI_FUNCTION_DECLS)
> > >> STRINGIFY_CODE(FS, TYPE_ID)
> > >> + STRINGIFY_CODE(FS, TYPE_ID_METADATA)
> > >> }
> > >> case bitc::METADATA_ATTACHMENT_ID:
> > >> switch(CodeID) {
> > >>
> > >>
> > >> _______________________________________________
> > >> llvm-commits mailing list
> > >> llvm-commits at lists.llvm.org <mailto:llvm-commits at lists.llvm.org>
> > >> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
> > >>
> > > _______________________________________________
> > > llvm-commits mailing list
> > > llvm-commits at lists.llvm.org <mailto:llvm-commits at lists.llvm.org>
> > > https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
> > >
> >
> >
> >
> > --
> > Teresa Johnson | Software Engineer | tejohnson at google.com
> > <mailto:tejohnson at google.com> |
> >
>
>
--
Teresa Johnson | Software Engineer | tejohnson at google.com |
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20190703/0debe29f/attachment-0001.html>
More information about the llvm-commits
mailing list