From e8cb930dbb9cf362b5175793203a72e0496e6154 Mon Sep 17 00:00:00 2001 From: Teresa Johnson Date: Thu, 17 Jan 2019 16:05:04 +0000 Subject: [PATCH] Revert "[ThinLTO] Add summary entries for index-based WPD" Mistaken commit of something still under review! This reverts commit r351453. llvm-svn: 351455 --- include/llvm/Bitcode/LLVMBitCodes.h | 15 -- include/llvm/IR/ModuleSummaryIndex.h | 58 +------ lib/Analysis/ModuleSummaryAnalysis.cpp | 115 +------------- lib/AsmParser/LLLexer.cpp | 3 - lib/AsmParser/LLParser.cpp | 168 +------------------- lib/AsmParser/LLParser.h | 2 - lib/AsmParser/LLToken.h | 3 - lib/Bitcode/Reader/BitcodeReader.cpp | 53 ------ lib/Bitcode/Writer/BitcodeWriter.cpp | 61 +------ lib/IR/AsmWriter.cpp | 38 ----- lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp | 45 ++---- test/Assembler/thinlto-vtable-summary.ll | 38 ----- test/ThinLTO/X86/devirt.ll | 146 ----------------- tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp | 2 - 14 files changed, 26 insertions(+), 721 deletions(-) delete mode 100644 test/Assembler/thinlto-vtable-summary.ll delete mode 100644 test/ThinLTO/X86/devirt.ll diff --git a/include/llvm/Bitcode/LLVMBitCodes.h b/include/llvm/Bitcode/LLVMBitCodes.h index 1e601aa5390..f0d11e9c168 100644 --- a/include/llvm/Bitcode/LLVMBitCodes.h +++ b/include/llvm/Bitcode/LLVMBitCodes.h @@ -264,25 +264,10 @@ 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, - // 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 { diff --git a/include/llvm/IR/ModuleSummaryIndex.h b/include/llvm/IR/ModuleSummaryIndex.h index 41c12cdee93..a1acee49447 100644 --- a/include/llvm/IR/ModuleSummaryIndex.h +++ b/include/llvm/IR/ModuleSummaryIndex.h @@ -666,12 +666,6 @@ template <> struct DenseMapInfo { } }; -/// Pair of function ValueInfo and offset within a vtable definition -/// initializer array. -using VirtFuncOffsetPair = std::pair; -/// List of functions referenced by a particular vtable definition. -using VTableFuncList = std::vector; - /// Global variable summary information to aid decisions and /// implementation of importing. /// @@ -679,11 +673,6 @@ using VTableFuncList = std::vector; /// 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 VTableFuncs; - public: struct GVarFlags { GVarFlags(bool ReadOnly = false) : ReadOnly(ReadOnly) {} @@ -704,17 +693,6 @@ 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(std::move(Funcs)); - } - - ArrayRef vTableFuncs() const { - if (VTableFuncs) - return *VTableFuncs; - return {}; - } }; struct TypeTestResolution { @@ -813,14 +791,6 @@ using GVSummaryMapTy = DenseMap; using TypeIdSummaryMapTy = std::multimap>; -/// Holds information about vtable definitions decorated with type metadata: -/// the vtable definition value and its offset in the corresponding type -/// metadata. -using TypeIdOffsetGVPair = std::pair; -/// List of vtable definitions decorated by the same type id metadata, -/// and their corresponding offsets in the type id metadata. -using TypeIdGVInfo = std::vector; - /// Class to hold module path string table and global value map, /// and encapsulate methods for operating on them. class ModuleSummaryIndex { @@ -833,14 +803,9 @@ private: ModulePathStringTableTy ModulePathStringTable; /// Mapping from type identifier GUIDs to type identifier and its summary - /// information. Produced by thin link. + /// information. 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. - std::map TypeIdMetadataMap; - /// Mapping from original ID to GUID. If original ID can map to multiple /// GUIDs, it will be mapped to 0. std::map OidGuidMap; @@ -1198,27 +1163,6 @@ public: return nullptr; } - const std::map &typeIdMetadataMap() const { - return TypeIdMetadataMap; - } - - /// Return an existing or new TypeIdMetadataMap entry for \p TypeId. - /// This accessor can mutate the map and therefore should not be used in - /// the ThinLTO backends. - TypeIdGVInfo &getOrInsertTypeIdMetadataSummary(StringRef TypeId) { - return TypeIdMetadataMap[TypeId]; - } - - /// For the given \p TypeId, this returns either a pointer to the - /// TypeIdMetadataMap entry (if present in the summary map) or null - /// (if not present). This may be used when importing. - const TypeIdGVInfo *getTypeIdMetadataSummary(StringRef TypeId) const { - auto I = TypeIdMetadataMap.find(TypeId); - if (I == TypeIdMetadataMap.end()) - return nullptr; - return &I->second; - } - /// Collect for the given module the list of functions it defines /// (GUID -> Summary). void collectDefinedFunctionsForModule(StringRef ModulePath, diff --git a/lib/Analysis/ModuleSummaryAnalysis.cpp b/lib/Analysis/ModuleSummaryAnalysis.cpp index af3d97a03cd..87f76d43bb1 100644 --- a/lib/Analysis/ModuleSummaryAnalysis.cpp +++ b/lib/Analysis/ModuleSummaryAnalysis.cpp @@ -406,98 +406,9 @@ static void computeFunctionSummary(ModuleSummaryIndex &Index, const Module &M, 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(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( - std::make_pair(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(I)) { - StructType *STy = dyn_cast(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(I->getOperand(Op)), - StartingOffset + Offset, M, Index, VTableFuncs); - } - } else if (auto *C = dyn_cast(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(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.second >= PrevOffset); - PrevOffset = P.second; - } -#endif -} - -/// Record vtable definition \p V for each type metadata it references. -static void recordTypeIdMetadataReferences(ModuleSummaryIndex &Index, - const GlobalVariable &V, - SmallVectorImpl &Types) { - for (MDNode *Type : Types) { - auto TypeID = Type->getOperand(1).get(); - - uint64_t Offset = - cast( - cast(Type->getOperand(0))->getValue()) - ->getZExtValue(); - - if (auto *TypeId = dyn_cast(TypeID)) - Index.getOrInsertTypeIdMetadataSummary(TypeId->getString()) - .push_back({Offset, Index.getOrInsertValueInfo(&V)}); - } -} - -static void computeVariableSummary(ModuleSummaryIndex &Index, - const GlobalVariable &V, - DenseSet &CantBePromoted, - const Module &M, - SmallVectorImpl &Types) { +static void +computeVariableSummary(ModuleSummaryIndex &Index, const GlobalVariable &V, + DenseSet &CantBePromoted) { SetVector RefEdges; SmallPtrSet Visited; bool HasBlockAddress = findRefEdges(Index, &V, RefEdges, Visited); @@ -505,21 +416,6 @@ static void computeVariableSummary(ModuleSummaryIndex &Index, GlobalValueSummary::GVFlags Flags(V.getLinkage(), NonRenamableLocal, /* Live = */ false, V.isDSOLocal()); - 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. - recordTypeIdMetadataReferences(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() && @@ -530,8 +426,6 @@ static void computeVariableSummary(ModuleSummaryIndex &Index, CantBePromoted.insert(V.getGUID()); if (HasBlockAddress) GVarSummary->setNotEligibleToImport(); - if (!VTableFuncs.empty()) - GVarSummary->setVTableFuncs(VTableFuncs); Index.addGlobalValueSummary(V, std::move(GVarSummary)); } @@ -674,11 +568,10 @@ ModuleSummaryIndex llvm::buildModuleSummaryIndex( // Compute summaries for all variables defined in module, and save in the // index. - SmallVector Types; for (const GlobalVariable &G : M.globals()) { if (G.isDeclaration()) continue; - computeVariableSummary(Index, G, CantBePromoted, M, Types); + computeVariableSummary(Index, G, CantBePromoted); } // Compute summaries for all aliases defined in module, and save in the diff --git a/lib/AsmParser/LLLexer.cpp b/lib/AsmParser/LLLexer.cpp index f5246d5480b..eab7ec81953 100644 --- a/lib/AsmParser/LLLexer.cpp +++ b/lib/AsmParser/LLLexer.cpp @@ -749,8 +749,6 @@ lltok::Kind LLLexer::LexIdentifier() { KEYWORD(critical); KEYWORD(relbf); KEYWORD(variable); - KEYWORD(vTableFuncs); - KEYWORD(virtFunc); KEYWORD(aliasee); KEYWORD(refs); KEYWORD(typeIdInfo); @@ -763,7 +761,6 @@ lltok::Kind LLLexer::LexIdentifier() { KEYWORD(offset); KEYWORD(args); KEYWORD(typeid); - KEYWORD(typeidMetadata); KEYWORD(summary); KEYWORD(typeTestRes); KEYWORD(kind); diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp index 5ef171fe965..816bb4e9401 100644 --- a/lib/AsmParser/LLParser.cpp +++ b/lib/AsmParser/LLParser.cpp @@ -822,9 +822,6 @@ bool LLParser::ParseSummaryEntry() { case lltok::kw_typeid: return ParseTypeIdEntry(SummaryID); break; - case lltok::kw_typeidMetadata: - return ParseTypeIdMetadataEntry(SummaryID); - break; default: return Error(Lex.getLoc(), "unexpected summary kind"); } @@ -7260,90 +7257,6 @@ bool LLParser::ParseTypeIdSummary(TypeIdSummary &TIS) { return false; } -static ValueInfo EmptyVI = - ValueInfo(false, (GlobalValueSummaryMapTy::value_type *)-8); - -/// TypeIdMetadataEntry -/// ::= 'typeidMetadata' ':' '(' 'name' ':' STRINGCONSTANT ',' TypeIdGVInfo -/// ')' -bool LLParser::ParseTypeIdMetadataEntry(unsigned ID) { - assert(Lex.getKind() == lltok::kw_typeidMetadata); - 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; - - TypeIdGVInfo &TI = Index->getOrInsertTypeIdMetadataSummary(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 TypeIdGVInfo 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].second == EmptyVI && - "Forward referenced ValueInfo expected to be empty"); - auto FwdRef = ForwardRefValueInfos.insert(std::make_pair( - I.first, std::vector>())); - FwdRef.first->second.push_back( - std::make_pair(&TI[P.first].second, 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' ) ',' @@ -7851,7 +7764,6 @@ bool LLParser::ParseVariableSummary(std::string Name, GlobalValue::GUID GUID, /*Live=*/false, /*IsLocal=*/false); GlobalVarSummary::GVarFlags GVarFlags(/*ReadOnly*/ false); std::vector Refs; - VTableFuncList VTableFuncs; if (ParseToken(lltok::colon, "expected ':' here") || ParseToken(lltok::lparen, "expected '(' here") || ParseModuleReference(ModulePath) || @@ -7860,20 +7772,10 @@ bool LLParser::ParseVariableSummary(std::string Name, GlobalValue::GUID GUID, ParseGVarFlags(GVarFlags)) 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"); - } + // Parse optional refs field + if (EatIfPresent(lltok::comma)) { + if (ParseOptionalRefs(Refs)) + return true; } if (ParseToken(lltok::rparen, "expected ')' here")) @@ -7883,7 +7785,6 @@ bool LLParser::ParseVariableSummary(std::string Name, GlobalValue::GUID GUID, llvm::make_unique(GVFlags, GVarFlags, std::move(Refs)); GS->setModulePath(ModulePath); - GS->setVTableFuncs(std::move(VTableFuncs)); AddGlobalValueToIndex(Name, GUID, (GlobalValue::LinkageTypes)GVFlags.Linkage, ID, std::move(GS)); @@ -8101,67 +8002,6 @@ bool LLParser::ParseHotness(CalleeInfo::HotnessType &Hotness) { 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(std::make_pair(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].first == EmptyVI && - "Forward referenced ValueInfo expected to be empty"); - auto FwdRef = ForwardRefValueInfos.insert(std::make_pair( - I.first, std::vector>())); - FwdRef.first->second.push_back( - std::make_pair(&VTableFuncs[P.first].first, P.second)); - } - } - - if (ParseToken(lltok::rparen, "expected ')' in vTableFuncs")) - return true; - - return false; -} - /// OptionalRefs /// := 'refs' ':' '(' GVReference [',' GVReference]* ')' bool LLParser::ParseOptionalRefs(std::vector &Refs) { diff --git a/lib/AsmParser/LLParser.h b/lib/AsmParser/LLParser.h index 272f1ac68a8..5a0fc297265 100644 --- a/lib/AsmParser/LLParser.h +++ b/lib/AsmParser/LLParser.h @@ -369,11 +369,9 @@ namespace llvm { IdToIndexMapType &IdToIndexMap, unsigned Index); bool ParseVFuncId(FunctionSummary::VFuncId &VFuncId, IdToIndexMapType &IdToIndexMap, unsigned Index); - bool ParseOptionalVTableFuncs(VTableFuncList &VTableFuncs); bool ParseOptionalRefs(std::vector &Refs); bool ParseTypeIdEntry(unsigned ID); bool ParseTypeIdSummary(TypeIdSummary &TIS); - bool ParseTypeIdMetadataEntry(unsigned ID); bool ParseTypeTestResolution(TypeTestResolution &TTRes); bool ParseOptionalWpdResolutions( std::map &WPDResMap); diff --git a/lib/AsmParser/LLToken.h b/lib/AsmParser/LLToken.h index 13e574241a0..c2e2795a946 100644 --- a/lib/AsmParser/LLToken.h +++ b/lib/AsmParser/LLToken.h @@ -379,8 +379,6 @@ enum Kind { kw_critical, kw_relbf, kw_variable, - kw_vTableFuncs, - kw_virtFunc, kw_aliasee, kw_refs, kw_typeIdInfo, @@ -393,7 +391,6 @@ enum Kind { kw_offset, kw_args, kw_typeid, - kw_typeidMetadata, kw_summary, kw_typeTestRes, kw_kind, diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp index 78504cc64e2..fe051e7a912 100644 --- a/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/lib/Bitcode/Reader/BitcodeReader.cpp @@ -748,9 +748,6 @@ private: bool HasRelBF); Error parseEntireSummary(unsigned ID); Error parseModuleStringTable(); - void parseTypeIdMetadataSummaryRecord(ArrayRef Record); - void parseTypeIdGVInfo(ArrayRef Record, size_t &Slot, - TypeIdGVInfo &TypeId); std::pair getValueInfoFromValueId(unsigned ValueId); @@ -5227,24 +5224,6 @@ static void parseTypeIdSummaryRecord(ArrayRef Record, parseWholeProgramDevirtResolution(Record, Strtab, Slot, TypeId); } -void ModuleSummaryIndexBitcodeReader::parseTypeIdGVInfo( - ArrayRef Record, size_t &Slot, TypeIdGVInfo &TypeId) { - uint64_t Offset = Record[Slot++]; - ValueInfo Callee = getValueInfoFromValueId(Record[Slot++]).first; - TypeId.push_back({Offset, Callee}); -} - -void ModuleSummaryIndexBitcodeReader::parseTypeIdMetadataSummaryRecord( - ArrayRef Record) { - size_t Slot = 0; - TypeIdGVInfo &TypeId = TheIndex.getOrInsertTypeIdMetadataSummary( - {Strtab.data() + Record[Slot], static_cast(Record[Slot + 1])}); - Slot += 2; - - while (Slot < Record.size()) - parseTypeIdGVInfo(Record, Slot, TypeId); -} - static void setImmutableRefs(std::vector &Refs, unsigned Count) { // Read-only refs are in the end of the refs list. for (unsigned RefNo = Refs.size() - Count; RefNo < Refs.size(); ++RefNo) @@ -5462,34 +5441,6 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(unsigned ID) { 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 Refs = makeRefList( - ArrayRef(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(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, @@ -5659,10 +5610,6 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(unsigned ID) { case bitc::FS_TYPE_ID: parseTypeIdSummaryRecord(Record, Strtab, TheIndex); break; - - case bitc::FS_TYPE_ID_METADATA: - parseTypeIdMetadataSummaryRecord(Record); - break; } } llvm_unreachable("Exit infinite loop"); diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp index 56656c74906..ba4f932e2e6 100644 --- a/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -215,8 +215,7 @@ private: const Function &F); void writeModuleLevelReferences(const GlobalVariable &V, SmallVector &NameVals, - unsigned FSModRefsAbbrev, - unsigned FSModVTableRefsAbbrev); + unsigned FSModRefsAbbrev); void assignValueId(GlobalValue::GUID ValGUID) { GUIDToValueIdMap[ValGUID] = ++GlobalValueId; @@ -3529,18 +3528,6 @@ static void writeTypeIdSummaryRecord(SmallVector &NameVals, W.second); } -static void writeTypeIdMetadataSummaryRecord( - SmallVector &NameVals, StringTableBuilder &StrtabBuilder, - const std::string &Id, const TypeIdGVInfo &Summary, ValueEnumerator &VE) { - NameVals.push_back(StrtabBuilder.add(Id)); - NameVals.push_back(Id.size()); - - for (auto &P : Summary) { - NameVals.push_back(P.first); - NameVals.push_back(VE.getValueID(P.second.getValue())); - } -} - // Helper to emit a single function summary record. void ModuleBitcodeWriterBase::writePerModuleFunctionSummaryRecord( SmallVector &NameVals, GlobalValueSummary *Summary, @@ -3585,7 +3572,7 @@ void ModuleBitcodeWriterBase::writePerModuleFunctionSummaryRecord( // and emit them in a summary record. void ModuleBitcodeWriterBase::writeModuleLevelReferences( const GlobalVariable &V, SmallVector &NameVals, - unsigned FSModRefsAbbrev, unsigned FSModVTableRefsAbbrev) { + unsigned FSModRefsAbbrev) { auto VI = Index->getValueInfo(V.getGUID()); if (!VI || VI.getSummaryList().empty()) { // Only declarations should not have a summary (a declaration might however @@ -3599,10 +3586,6 @@ void ModuleBitcodeWriterBase::writeModuleLevelReferences( 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())); @@ -3610,20 +3593,8 @@ void ModuleBitcodeWriterBase::writeModuleLevelReferences( // been initialized from a DenseSet. llvm::sort(NameVals.begin() + SizeBeforeRefs, NameVals.end()); - if (!VTableFuncs.empty()) { - // VTableFuncs pairs should already be sorted by offset. - for (auto &P : VTableFuncs) { - NameVals.push_back(VE.getValueID(P.first.getValue())); - NameVals.push_back(P.second); - } - } - - 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); + Stream.EmitRecord(bitc::FS_PERMODULE_GLOBALVAR_INIT_REFS, NameVals, + FSModRefsAbbrev); NameVals.clear(); } @@ -3704,17 +3675,6 @@ void ModuleBitcodeWriterBase::writePerModuleGlobalValueSummary() { 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(); - 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(); Abbv->Add(BitCodeAbbrevOp(bitc::FS_ALIAS)); @@ -3747,8 +3707,7 @@ void ModuleBitcodeWriterBase::writePerModuleGlobalValueSummary() { // Capture references from GlobalVariable initializers, which are outside // of a function scope. for (const GlobalVariable &G : M.globals()) - writeModuleLevelReferences(G, NameVals, FSModRefsAbbrev, - FSModVTableRefsAbbrev); + writeModuleLevelReferences(G, NameVals, FSModRefsAbbrev); for (const GlobalAlias &A : M.aliases()) { auto *Aliasee = A.getBaseObject(); @@ -3766,16 +3725,6 @@ void ModuleBitcodeWriterBase::writePerModuleGlobalValueSummary() { NameVals.clear(); } - if (!Index->typeIdMetadataMap().empty()) { - SmallVector NameVals; - for (auto &S : Index->typeIdMetadataMap()) { - writeTypeIdMetadataSummaryRecord(NameVals, StrtabBuilder, S.first, - S.second, VE); - Stream.EmitRecord(bitc::FS_TYPE_ID_METADATA, NameVals); - NameVals.clear(); - } - } - Stream.ExitBlock(); } diff --git a/lib/IR/AsmWriter.cpp b/lib/IR/AsmWriter.cpp index e431deb86f4..a5dc623e1a3 100644 --- a/lib/IR/AsmWriter.cpp +++ b/lib/IR/AsmWriter.cpp @@ -1038,9 +1038,6 @@ void SlotTracker::processIndex() { TidIter != TheIndex->typeIds().end(); TidIter++) CreateTypeIdSlot(TidIter->second.first); - for (auto &TId : TheIndex->typeIdMetadataMap()) - CreateGUIDSlot(GlobalValue::getGUID(TId.first)); - ST_DEBUG("end processIndex!\n"); } @@ -2396,7 +2393,6 @@ public: void printGlobalVarSummary(const GlobalVarSummary *GS); void printFunctionSummary(const FunctionSummary *FS); void printTypeIdSummary(const TypeIdSummary &TIS); - void printTypeIdMetadataSummary(const TypeIdGVInfo &TI); void printTypeTestResolution(const TypeTestResolution &TTRes); void printArgs(const std::vector &Args); void printWPDRes(const WholeProgramDevirtResolution &WPDRes); @@ -2699,15 +2695,6 @@ void AssemblyWriter::printModuleSummaryIndex() { printTypeIdSummary(TidIter->second.second); Out << ") ; guid = " << TidIter->first << "\n"; } - - // Print the TypeIdMetadataMap entries. - for (auto &TId : TheIndex->typeIdMetadataMap()) { - auto GUID = GlobalValue::getGUID(TId.first); - Out << "^" << Machine.getGUIDSlot(GUID) << " = typeidMetadata: (name: \"" - << TId.first << "\""; - printTypeIdMetadataSummary(TId.second); - Out << ") ; guid = " << GUID << "\n"; - } } static const char * @@ -2790,18 +2777,6 @@ void AssemblyWriter::printTypeIdSummary(const TypeIdSummary &TIS) { Out << ")"; } -void AssemblyWriter::printTypeIdMetadataSummary(const TypeIdGVInfo &TI) { - Out << ", summary: ("; - FieldSeparator FS; - for (auto &P : TI) { - Out << FS; - Out << "(offset: " << P.first << ", "; - Out << "^" << Machine.getGUIDSlot(P.second.getGUID()); - Out << ")"; - } - Out << ")"; -} - void AssemblyWriter::printArgs(const std::vector &Args) { Out << "args: ("; FieldSeparator FS; @@ -2871,19 +2846,6 @@ void AssemblyWriter::printAliasSummary(const AliasSummary *AS) { 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.first.getGUID()) - << ", offset: " << P.second; - Out << ")"; - } - Out << ")"; - } } static std::string getLinkageName(GlobalValue::LinkageTypes LT) { diff --git a/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp b/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp index 88b45e03492..510ecb516dc 100644 --- a/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp +++ b/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp @@ -418,55 +418,34 @@ void splitAndWriteThinLTOBitcode( } } -// Check if the LTO Unit splitting has been enabled. -bool enableSplitLTOUnit(Module &M) { +// 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. bool EnableSplitLTOUnit = false; if (auto *MD = mdconst::extract_or_null( M.getModuleFlag("EnableSplitLTOUnit"))) EnableSplitLTOUnit = MD->getZExtValue(); - return EnableSplitLTOUnit; -} + if (!EnableSplitLTOUnit) + return false; -// Returns whether this module needs to be split because it uses type metadata. -bool hasTypeMetadata(Module &M) { + // Module only needs to be split if it contains type metadata. 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 AARGetter, Module &M, const ModuleSummaryIndex *Index) { - std::unique_ptr 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); - else { - // 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( - buildModuleSummaryIndex(M, nullptr, &PSI)); - Index = NewIndex.get(); - } - } - } + // Split module if splitting is enabled and it contains any type metadata. + if (requiresSplit(M)) + return splitAndWriteThinLTOBitcode(OS, ThinLinkOS, AARGetter, M); - // Write it out as an unsplit ThinLTO module. + // Otherwise we can just write it out as a regular module. // Save the module hash produced for the full bitcode, which will // be used in the backends, and use that in the minimized bitcode diff --git a/test/Assembler/thinlto-vtable-summary.ll b/test/Assembler/thinlto-vtable-summary.ll deleted file mode 100644 index 2c07cb8435f..00000000000 --- a/test/Assembler/thinlto-vtable-summary.ll +++ /dev/null @@ -1,38 +0,0 @@ -; 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 } - -@_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 -@_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: "", 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), 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), varFlags: (readonly: 0), vTableFuncs: ((virtFunc: ^5, offset: 16), (virtFunc: ^1, offset: 24)), refs: (^1, ^5)))) ; guid = 13624023785555846296 -^5 = gv: (name: "_ZN1C1fEi") ; guid = 14876272565662207556 -^6 = typeidMetadata: (name: "_ZTS1A", summary: ((offset: 16, ^2), (offset: 16, ^4))) ; guid = 7004155349499253778 -^7 = typeidMetadata: (name: "_ZTS1B", summary: ((offset: 16, ^2))) ; guid = 6203814149063363976 -^8 = typeidMetadata: (name: "_ZTS1C", summary: ((offset: 16, ^4))) ; guid = 1884921850105019584 diff --git a/test/ThinLTO/X86/devirt.ll b/test/ThinLTO/X86/devirt.ll deleted file mode 100644 index 5d067f83926..00000000000 --- a/test/ThinLTO/X86/devirt.ll +++ /dev/null @@ -1,146 +0,0 @@ -; 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=typeidMetadata -; 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=typeidMetadata -; 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: typeidMetadata: (name: "_ZTS1A", summary: ((offset: 16, [[B]]), (offset: 16, [[C]]))) -; NOENABLESPLITFLAG-DAG: typeidMetadata: (name: "_ZTS1B", summary: ((offset: 16, [[B]]))) -; NOENABLESPLITFLAG-DAG: typeidMetadata: (name: "_ZTS1C", summary: ((offset: 16, [[C]]))) -; Type Id on _ZTV1D should have been promoted -; NOENABLESPLITFLAG-DAG: typeidMetadata: (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 (...)** } - -@_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 -@_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 -@_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 !{} diff --git a/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp b/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp index a841d535cfa..789a666cb41 100644 --- a/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp +++ b/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp @@ -317,7 +317,6 @@ static const char *GetCodeName(unsigned CodeID, unsigned BlockID, 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) @@ -335,7 +334,6 @@ static const char *GetCodeName(unsigned CodeID, unsigned BlockID, 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) {