llvm.org GIT mirror llvm / 5b5290a
Revert "[ThinLTO] Add summary entries for index-based WPD" Mistaken commit of something still under review! This reverts commit r351453. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@351455 91177308-0d34-0410-b5e6-96231b3b80d8 Teresa Johnson 1 year, 9 months ago
14 changed file(s) with 28 addition(s) and 723 deletion(s). Raw diff Collapse all Expand all
263263 // Index-wide flags
264264 FS_FLAGS = 20,
265265 // Maps type identifier to summary information for that type identifier.
266 // Produced by the thin link (only lives in combined index).
267266 // TYPE_ID: [typeid, kind, bitwidth, align, size, bitmask, inlinebits,
268267 // n x (typeid, kind, name, numrba,
269268 // numrba x (numarg, numarg x arg, kind, info, byte, bit))]
270269 FS_TYPE_ID = 21,
271 // Maps type identifier to summary information for that type identifier
272 // computed from type metadata: the valueid of each vtable definition
273 // decorated with a type metadata for that identifier, and the offset from
274 // the corresponding type metadata.
275 // Exists in the per-module summary to provide information to thin link
276 // for index-based whole program devirtualization.
277 // TYPE_ID_METADATA: [typeid, n x (valueid, offset)]
278 FS_TYPE_ID_METADATA = 22,
279 // Summarizes vtable definition for use in index-based whole program
280 // devirtualization during the thin link.
281 // PERMODULE_VTABLE_GLOBALVAR_INIT_REFS: [valueid, flags, varflags,
282 // numrefs, numrefs x valueid,
283 // n x (valueid, offset)]
284 FS_PERMODULE_VTABLE_GLOBALVAR_INIT_REFS = 23,
285270 };
286271
287272 enum MetadataCodes {
665665 }
666666 };
667667
668 /// Pair of function ValueInfo and offset within a vtable definition
669 /// initializer array.
670 using VirtFuncOffsetPair = std::pair;
671 /// List of functions referenced by a particular vtable definition.
672 using VTableFuncList = std::vector;
673
674668 /// Global variable summary information to aid decisions and
675669 /// implementation of importing.
676670 ///
678672 /// modified during the program run or not. This affects ThinLTO
679673 /// internalization
680674 class GlobalVarSummary : public GlobalValueSummary {
681 private:
682 /// For vtable definitions this holds the list of functions and
683 /// their corresponding offsets within the initializer array.
684 std::unique_ptr VTableFuncs;
685
686675 public:
687676 struct GVarFlags {
688677 GVarFlags(bool ReadOnly = false) : ReadOnly(ReadOnly) {}
703692 GVarFlags varflags() const { return VarFlags; }
704693 void setReadOnly(bool RO) { VarFlags.ReadOnly = RO; }
705694 bool isReadOnly() const { return VarFlags.ReadOnly; }
706
707 void setVTableFuncs(VTableFuncList Funcs) {
708 assert(!VTableFuncs);
709 VTableFuncs = llvm::make_unique(std::move(Funcs));
710 }
711
712 ArrayRef vTableFuncs() const {
713 if (VTableFuncs)
714 return *VTableFuncs;
715 return {};
716 }
717695 };
718696
719697 struct TypeTestResolution {
812790 using TypeIdSummaryMapTy =
813791 std::multimap>;
814792
815 /// Holds information about vtable definitions decorated with type metadata:
816 /// the vtable definition value and its offset in the corresponding type
817 /// metadata.
818 using TypeIdOffsetGVPair = std::pair;
819 /// List of vtable definitions decorated by the same type id metadata,
820 /// and their corresponding offsets in the type id metadata.
821 using TypeIdGVInfo = std::vector;
822
823793 /// Class to hold module path string table and global value map,
824794 /// and encapsulate methods for operating on them.
825795 class ModuleSummaryIndex {
832802 ModulePathStringTableTy ModulePathStringTable;
833803
834804 /// Mapping from type identifier GUIDs to type identifier and its summary
835 /// information. Produced by thin link.
805 /// information.
836806 TypeIdSummaryMapTy TypeIdMap;
837
838 /// Mapping from type identifier to information about vtables decorated
839 /// with that type identifier's metadata. Produced by per module summary
840 /// analysis and consumed by thin link.
841 std::map TypeIdMetadataMap;
842807
843808 /// Mapping from original ID to GUID. If original ID can map to multiple
844809 /// GUIDs, it will be mapped to 0.
11971162 return nullptr;
11981163 }
11991164
1200 const std::map &typeIdMetadataMap() const {
1201 return TypeIdMetadataMap;
1202 }
1203
1204 /// Return an existing or new TypeIdMetadataMap entry for \p TypeId.
1205 /// This accessor can mutate the map and therefore should not be used in
1206 /// the ThinLTO backends.
1207 TypeIdGVInfo &getOrInsertTypeIdMetadataSummary(StringRef TypeId) {
1208 return TypeIdMetadataMap[TypeId];
1209 }
1210
1211 /// For the given \p TypeId, this returns either a pointer to the
1212 /// TypeIdMetadataMap entry (if present in the summary map) or null
1213 /// (if not present). This may be used when importing.
1214 const TypeIdGVInfo *getTypeIdMetadataSummary(StringRef TypeId) const {
1215 auto I = TypeIdMetadataMap.find(TypeId);
1216 if (I == TypeIdMetadataMap.end())
1217 return nullptr;
1218 return &I->second;
1219 }
1220
12211165 /// Collect for the given module the list of functions it defines
12221166 /// (GUID -> Summary).
12231167 void collectDefinedFunctionsForModule(StringRef ModulePath,
405405 Index.addGlobalValueSummary(F, std::move(FuncSummary));
406406 }
407407
408 /// Find function pointers referenced within the given vtable initializer
409 /// (or subset of an initializer) \p I. The starting offset of \p I within
410 /// the vtable initializer is \p StartingOffset. Any discovered function
411 /// pointers are added to \p VTableFuncs along with their cumulative offset
412 /// within the initializer.
413 static void findFuncPointers(const Constant *I, uint64_t StartingOffset,
414 const Module &M, ModuleSummaryIndex &Index,
415 VTableFuncList &VTableFuncs) {
416 // First check if this is a function pointer.
417 if (I->getType()->isPointerTy()) {
418 auto Fn = dyn_cast(I->stripPointerCasts());
419 // We can disregard __cxa_pure_virtual as a possible call target, as
420 // calls to pure virtuals are UB.
421 if (Fn && Fn->getName() != "__cxa_pure_virtual")
422 VTableFuncs.push_back(
423 std::make_pair(Index.getOrInsertValueInfo(Fn), StartingOffset));
424 return;
425 }
426
427 // Walk through the elements in the constant struct or array and recursively
428 // look for virtual function pointers.
429 const DataLayout &DL = M.getDataLayout();
430 if (auto *C = dyn_cast(I)) {
431 StructType *STy = dyn_cast(C->getType());
432 assert(STy);
433 const StructLayout *SL = DL.getStructLayout(C->getType());
434
435 for (StructType::element_iterator EB = STy->element_begin(), EI = EB,
436 EE = STy->element_end();
437 EI != EE; ++EI) {
438 auto Offset = SL->getElementOffset(EI - EB);
439 unsigned Op = SL->getElementContainingOffset(Offset);
440 findFuncPointers(cast(I->getOperand(Op)),
441 StartingOffset + Offset, M, Index, VTableFuncs);
442 }
443 } else if (auto *C = dyn_cast(I)) {
444 ArrayType *ATy = C->getType();
445 Type *EltTy = ATy->getElementType();
446 uint64_t EltSize = DL.getTypeAllocSize(EltTy);
447 for (unsigned i = 0, e = ATy->getNumElements(); i != e; ++i) {
448 findFuncPointers(cast(I->getOperand(i)),
449 StartingOffset + i * EltSize, M, Index, VTableFuncs);
450 }
451 }
452 }
453
454 // Identify the function pointers referenced by vtable definition \p V.
455 static void computeVTableFuncs(ModuleSummaryIndex &Index,
456 const GlobalVariable &V, const Module &M,
457 VTableFuncList &VTableFuncs) {
458 if (!V.isConstant())
459 return;
460
461 findFuncPointers(V.getInitializer(), /*StartingOffset=*/0, M, Index,
462 VTableFuncs);
463
464 #ifndef NDEBUG
465 // Validate that the VTableFuncs list is ordered by offset.
466 uint64_t PrevOffset = 0;
467 for (auto &P : VTableFuncs) {
468 // The findVFuncPointers traversal should have encountered the
469 // functions in offset order. We need to use ">=" since PrevOffset
470 // starts at 0.
471 assert(P.second >= PrevOffset);
472 PrevOffset = P.second;
473 }
474 #endif
475 }
476
477 /// Record vtable definition \p V for each type metadata it references.
478 static void recordTypeIdMetadataReferences(ModuleSummaryIndex &Index,
479 const GlobalVariable &V,
480 SmallVectorImpl &Types) {
481 for (MDNode *Type : Types) {
482 auto TypeID = Type->getOperand(1).get();
483
484 uint64_t Offset =
485 cast(
486 cast(Type->getOperand(0))->getValue())
487 ->getZExtValue();
488
489 if (auto *TypeId = dyn_cast(TypeID))
490 Index.getOrInsertTypeIdMetadataSummary(TypeId->getString())
491 .push_back({Offset, Index.getOrInsertValueInfo(&V)});
492 }
493 }
494
495 static void computeVariableSummary(ModuleSummaryIndex &Index,
496 const GlobalVariable &V,
497 DenseSet &CantBePromoted,
498 const Module &M,
499 SmallVectorImpl &Types) {
408 static void
409 computeVariableSummary(ModuleSummaryIndex &Index, const GlobalVariable &V,
410 DenseSet &CantBePromoted) {
500411 SetVector RefEdges;
501412 SmallPtrSet Visited;
502413 bool HasBlockAddress = findRefEdges(Index, &V, RefEdges, Visited);
503414 bool NonRenamableLocal = isNonRenamableLocal(V);
504415 GlobalValueSummary::GVFlags Flags(V.getLinkage(), NonRenamableLocal,
505416 /* Live = */ false, V.isDSOLocal());
506
507 VTableFuncList VTableFuncs;
508 // If splitting is not enabled, then we compute the summary information
509 // necessary for index-based whole program devirtualization.
510 if (!Index.enableSplitLTOUnit()) {
511 Types.clear();
512 V.getMetadata(LLVMContext::MD_type, Types);
513 if (!Types.empty()) {
514 // Identify the function pointers referenced by this vtable definition.
515 computeVTableFuncs(Index, V, M, VTableFuncs);
516
517 // Record this vtable definition for each type metadata it references.
518 recordTypeIdMetadataReferences(Index, V, Types);
519 }
520 }
521417
522418 // Don't mark variables we won't be able to internalize as read-only.
523419 GlobalVarSummary::GVarFlags VarFlags(
529425 CantBePromoted.insert(V.getGUID());
530426 if (HasBlockAddress)
531427 GVarSummary->setNotEligibleToImport();
532 if (!VTableFuncs.empty())
533 GVarSummary->setVTableFuncs(VTableFuncs);
534428 Index.addGlobalValueSummary(V, std::move(GVarSummary));
535429 }
536430
673567
674568 // Compute summaries for all variables defined in module, and save in the
675569 // index.
676 SmallVector Types;
677570 for (const GlobalVariable &G : M.globals()) {
678571 if (G.isDeclaration())
679572 continue;
680 computeVariableSummary(Index, G, CantBePromoted, M, Types);
573 computeVariableSummary(Index, G, CantBePromoted);
681574 }
682575
683576 // Compute summaries for all aliases defined in module, and save in the
748748 KEYWORD(critical);
749749 KEYWORD(relbf);
750750 KEYWORD(variable);
751 KEYWORD(vTableFuncs);
752 KEYWORD(virtFunc);
753751 KEYWORD(aliasee);
754752 KEYWORD(refs);
755753 KEYWORD(typeIdInfo);
762760 KEYWORD(offset);
763761 KEYWORD(args);
764762 KEYWORD(typeid);
765 KEYWORD(typeidMetadata);
766763 KEYWORD(summary);
767764 KEYWORD(typeTestRes);
768765 KEYWORD(kind);
820820 return ParseModuleEntry(SummaryID);
821821 case lltok::kw_typeid:
822822 return ParseTypeIdEntry(SummaryID);
823 break;
824 case lltok::kw_typeidMetadata:
825 return ParseTypeIdMetadataEntry(SummaryID);
826823 break;
827824 default:
828825 return Error(Lex.getLoc(), "unexpected summary kind");
72597256 return false;
72607257 }
72617258
7262 static ValueInfo EmptyVI =
7263 ValueInfo(false, (GlobalValueSummaryMapTy::value_type *)-8);
7264
7265 /// TypeIdMetadataEntry
7266 /// ::= 'typeidMetadata' ':' '(' 'name' ':' STRINGCONSTANT ',' TypeIdGVInfo
7267 /// ')'
7268 bool LLParser::ParseTypeIdMetadataEntry(unsigned ID) {
7269 assert(Lex.getKind() == lltok::kw_typeidMetadata);
7270 Lex.Lex();
7271
7272 std::string Name;
7273 if (ParseToken(lltok::colon, "expected ':' here") ||
7274 ParseToken(lltok::lparen, "expected '(' here") ||
7275 ParseToken(lltok::kw_name, "expected 'name' here") ||
7276 ParseToken(lltok::colon, "expected ':' here") ||
7277 ParseStringConstant(Name))
7278 return true;
7279
7280 TypeIdGVInfo &TI = Index->getOrInsertTypeIdMetadataSummary(Name);
7281 if (ParseToken(lltok::comma, "expected ',' here") ||
7282 ParseToken(lltok::kw_summary, "expected 'summary' here") ||
7283 ParseToken(lltok::colon, "expected ':' here") ||
7284 ParseToken(lltok::lparen, "expected '(' here"))
7285 return true;
7286
7287 IdToIndexMapType IdToIndexMap;
7288 // Parse each call edge
7289 do {
7290 uint64_t Offset;
7291 if (ParseToken(lltok::lparen, "expected '(' here") ||
7292 ParseToken(lltok::kw_offset, "expected 'offset' here") ||
7293 ParseToken(lltok::colon, "expected ':' here") || ParseUInt64(Offset) ||
7294 ParseToken(lltok::comma, "expected ',' here"))
7295 return true;
7296
7297 LocTy Loc = Lex.getLoc();
7298 unsigned GVId;
7299 ValueInfo VI;
7300 if (ParseGVReference(VI, GVId))
7301 return true;
7302
7303 // Keep track of the TypeIdGVInfo array index needing a forward reference.
7304 // We will save the location of the ValueInfo needing an update, but
7305 // can only do so once the std::vector is finalized.
7306 if (VI == EmptyVI)
7307 IdToIndexMap[GVId].push_back(std::make_pair(TI.size(), Loc));
7308 TI.push_back({Offset, VI});
7309
7310 if (ParseToken(lltok::rparen, "expected ')' in call"))
7311 return true;
7312 } while (EatIfPresent(lltok::comma));
7313
7314 // Now that the TI vector is finalized, it is safe to save the locations
7315 // of any forward GV references that need updating later.
7316 for (auto I : IdToIndexMap) {
7317 for (auto P : I.second) {
7318 assert(TI[P.first].second == EmptyVI &&
7319 "Forward referenced ValueInfo expected to be empty");
7320 auto FwdRef = ForwardRefValueInfos.insert(std::make_pair(
7321 I.first, std::vector>()));
7322 FwdRef.first->second.push_back(
7323 std::make_pair(&TI[P.first].second, P.second));
7324 }
7325 }
7326
7327 if (ParseToken(lltok::rparen, "expected ')' here") ||
7328 ParseToken(lltok::rparen, "expected ')' here"))
7329 return true;
7330
7331 // Check if this ID was forward referenced, and if so, update the
7332 // corresponding GUIDs.
7333 auto FwdRefTIDs = ForwardRefTypeIds.find(ID);
7334 if (FwdRefTIDs != ForwardRefTypeIds.end()) {
7335 for (auto TIDRef : FwdRefTIDs->second) {
7336 assert(!*TIDRef.first &&
7337 "Forward referenced type id GUID expected to be 0");
7338 *TIDRef.first = GlobalValue::getGUID(Name);
7339 }
7340 ForwardRefTypeIds.erase(FwdRefTIDs);
7341 }
7342
7343 return false;
7344 }
7345
73467259 /// TypeTestResolution
73477260 /// ::= 'typeTestRes' ':' '(' 'kind' ':'
73487261 /// ( 'unsat' | 'byteArray' | 'inline' | 'single' | 'allOnes' ) ','
78507763 /*Live=*/false, /*IsLocal=*/false);
78517764 GlobalVarSummary::GVarFlags GVarFlags(/*ReadOnly*/ false);
78527765 std::vector Refs;
7853 VTableFuncList VTableFuncs;
78547766 if (ParseToken(lltok::colon, "expected ':' here") ||
78557767 ParseToken(lltok::lparen, "expected '(' here") ||
78567768 ParseModuleReference(ModulePath) ||
78597771 ParseGVarFlags(GVarFlags))
78607772 return true;
78617773
7862 // Parse optional fields
7863 while (EatIfPresent(lltok::comma)) {
7864 switch (Lex.getKind()) {
7865 case lltok::kw_vTableFuncs:
7866 if (ParseOptionalVTableFuncs(VTableFuncs))
7867 return true;
7868 break;
7869 case lltok::kw_refs:
7870 if (ParseOptionalRefs(Refs))
7871 return true;
7872 break;
7873 default:
7874 return Error(Lex.getLoc(), "expected optional variable summary field");
7875 }
7774 // Parse optional refs field
7775 if (EatIfPresent(lltok::comma)) {
7776 if (ParseOptionalRefs(Refs))
7777 return true;
78767778 }
78777779
78787780 if (ParseToken(lltok::rparen, "expected ')' here"))
78827784 llvm::make_unique(GVFlags, GVarFlags, std::move(Refs));
78837785
78847786 GS->setModulePath(ModulePath);
7885 GS->setVTableFuncs(std::move(VTableFuncs));
78867787
78877788 AddGlobalValueToIndex(Name, GUID, (GlobalValue::LinkageTypes)GVFlags.Linkage,
78887789 ID, std::move(GS));
81008001 return false;
81018002 }
81028003
8103 /// OptionalVTableFuncs
8104 /// := 'vTableFuncs' ':' '(' VTableFunc [',' VTableFunc]* ')'
8105 /// VTableFunc ::= '(' 'virtFunc' ':' GVReference ',' 'offset' ':' UInt64 ')'
8106 bool LLParser::ParseOptionalVTableFuncs(VTableFuncList &VTableFuncs) {
8107 assert(Lex.getKind() == lltok::kw_vTableFuncs);
8108 Lex.Lex();
8109
8110 if (ParseToken(lltok::colon, "expected ':' in vTableFuncs") |
8111 ParseToken(lltok::lparen, "expected '(' in vTableFuncs"))
8112 return true;
8113
8114 IdToIndexMapType IdToIndexMap;
8115 // Parse each virtual function pair
8116 do {
8117 ValueInfo VI;
8118 if (ParseToken(lltok::lparen, "expected '(' in vTableFunc") ||
8119 ParseToken(lltok::kw_virtFunc, "expected 'callee' in vTableFunc") ||
8120 ParseToken(lltok::colon, "expected ':'"))
8121 return true;
8122
8123 LocTy Loc = Lex.getLoc();
8124 unsigned GVId;
8125 if (ParseGVReference(VI, GVId))
8126 return true;
8127
8128 uint64_t Offset;
8129 if (ParseToken(lltok::comma, "expected comma") ||
8130 ParseToken(lltok::kw_offset, "expected offset") ||
8131 ParseToken(lltok::colon, "expected ':'") || ParseUInt64(Offset))
8132 return true;
8133
8134 // Keep track of the VTableFuncs array index needing a forward reference.
8135 // We will save the location of the ValueInfo needing an update, but
8136 // can only do so once the std::vector is finalized.
8137 if (VI == EmptyVI)
8138 IdToIndexMap[GVId].push_back(std::make_pair(VTableFuncs.size(), Loc));
8139 VTableFuncs.push_back(std::make_pair(VI, Offset));
8140
8141 if (ParseToken(lltok::rparen, "expected ')' in vTableFunc"))
8142 return true;
8143 } while (EatIfPresent(lltok::comma));
8144
8145 // Now that the VTableFuncs vector is finalized, it is safe to save the
8146 // locations of any forward GV references that need updating later.
8147 for (auto I : IdToIndexMap) {
8148 for (auto P : I.second) {
8149 assert(VTableFuncs[P.first].first == EmptyVI &&
8150 "Forward referenced ValueInfo expected to be empty");
8151 auto FwdRef = ForwardRefValueInfos.insert(std::make_pair(
8152 I.first, std::vector>()));
8153 FwdRef.first->second.push_back(
8154 std::make_pair(&VTableFuncs[P.first].first, P.second));
8155 }
8156 }
8157
8158 if (ParseToken(lltok::rparen, "expected ')' in vTableFuncs"))
8159 return true;
8160
8161 return false;
8162 }
8163
81648004 /// OptionalRefs
81658005 /// := 'refs' ':' '(' GVReference [',' GVReference]* ')'
81668006 bool LLParser::ParseOptionalRefs(std::vector &Refs) {
368368 IdToIndexMapType &IdToIndexMap, unsigned Index);
369369 bool ParseVFuncId(FunctionSummary::VFuncId &VFuncId,
370370 IdToIndexMapType &IdToIndexMap, unsigned Index);
371 bool ParseOptionalVTableFuncs(VTableFuncList &VTableFuncs);
372371 bool ParseOptionalRefs(std::vector &Refs);
373372 bool ParseTypeIdEntry(unsigned ID);
374373 bool ParseTypeIdSummary(TypeIdSummary &TIS);
375 bool ParseTypeIdMetadataEntry(unsigned ID);
376374 bool ParseTypeTestResolution(TypeTestResolution &TTRes);
377375 bool ParseOptionalWpdResolutions(
378376 std::map &WPDResMap);
378378 kw_critical,
379379 kw_relbf,
380380 kw_variable,
381 kw_vTableFuncs,
382 kw_virtFunc,
383381 kw_aliasee,
384382 kw_refs,
385383 kw_typeIdInfo,
392390 kw_offset,
393391 kw_args,
394392 kw_typeid,
395 kw_typeidMetadata,
396393 kw_summary,
397394 kw_typeTestRes,
398395 kw_kind,
747747 bool HasRelBF);
748748 Error parseEntireSummary(unsigned ID);
749749 Error parseModuleStringTable();
750 void parseTypeIdMetadataSummaryRecord(ArrayRef Record);
751 void parseTypeIdGVInfo(ArrayRef Record, size_t &Slot,
752 TypeIdGVInfo &TypeId);
753750
754751 std::pair
755752 getValueInfoFromValueId(unsigned ValueId);
52265223 parseWholeProgramDevirtResolution(Record, Strtab, Slot, TypeId);
52275224 }
52285225
5229 void ModuleSummaryIndexBitcodeReader::parseTypeIdGVInfo(
5230 ArrayRef Record, size_t &Slot, TypeIdGVInfo &TypeId) {
5231 uint64_t Offset = Record[Slot++];
5232 ValueInfo Callee = getValueInfoFromValueId(Record[Slot++]).first;
5233 TypeId.push_back({Offset, Callee});
5234 }
5235
5236 void ModuleSummaryIndexBitcodeReader::parseTypeIdMetadataSummaryRecord(
5237 ArrayRef Record) {
5238 size_t Slot = 0;
5239 TypeIdGVInfo &TypeId = TheIndex.getOrInsertTypeIdMetadataSummary(
5240 {Strtab.data() + Record[Slot], static_cast(Record[Slot + 1])});
5241 Slot += 2;
5242
5243 while (Slot < Record.size())
5244 parseTypeIdGVInfo(Record, Slot, TypeId);
5245 }
5246
52475226 static void setImmutableRefs(std::vector &Refs, unsigned Count) {
52485227 // Read-only refs are in the end of the refs list.
52495228 for (unsigned RefNo = Refs.size() - Count; RefNo < Refs.size(); ++RefNo)
54615440 TheIndex.addGlobalValueSummary(GUID.first, std::move(FS));
54625441 break;
54635442 }
5464 // FS_PERMODULE_VTABLE_GLOBALVAR_INIT_REFS: [valueid, flags, varflags,
5465 // numrefs, numrefs x valueid,
5466 // n x (valueid, offset)]
5467 case bitc::FS_PERMODULE_VTABLE_GLOBALVAR_INIT_REFS: {
5468 unsigned ValueID = Record[0];
5469 uint64_t RawFlags = Record[1];
5470 GlobalVarSummary::GVarFlags GVF = getDecodedGVarFlags(Record[2]);
5471 unsigned NumRefs = Record[3];
5472 unsigned RefListStartIndex = 4;
5473 unsigned VTableListStartIndex = RefListStartIndex + NumRefs;
5474 auto Flags = getDecodedGVSummaryFlags(RawFlags, Version);
5475 std::vector Refs = makeRefList(
5476 ArrayRef(Record).slice(RefListStartIndex, NumRefs));
5477 VTableFuncList VTableFuncs;
5478 for (unsigned I = VTableListStartIndex, E = Record.size(); I != E; ++I) {
5479 ValueInfo Callee = getValueInfoFromValueId(Record[I]).first;
5480 uint64_t Offset = Record[++I];
5481 VTableFuncs.push_back({Callee, Offset});
5482 }
5483 auto VS =
5484 llvm::make_unique(Flags, GVF, std::move(Refs));
5485 VS->setModulePath(getThisModule()->first());
5486 VS->setVTableFuncs(VTableFuncs);
5487 auto GUID = getValueInfoFromValueId(ValueID);
5488 VS->setOriginalName(GUID.second);
5489 TheIndex.addGlobalValueSummary(GUID.first, std::move(VS));
5490 break;
5491 }
54925443 // FS_COMBINED: [valueid, modid, flags, instcount, fflags, numrefs,
54935444 // numrefs x valueid, n x (valueid)]
54945445 // FS_COMBINED_PROFILE: [valueid, modid, flags, instcount, fflags, numrefs,
56585609 case bitc::FS_TYPE_ID:
56595610 parseTypeIdSummaryRecord(Record, Strtab, TheIndex);
56605611 break;
5661
5662 case bitc::FS_TYPE_ID_METADATA:
5663 parseTypeIdMetadataSummaryRecord(Record);
5664 break;
56655612 }
56665613 }
56675614 llvm_unreachable("Exit infinite loop");
214214 const Function &F);
215215 void writeModuleLevelReferences(const GlobalVariable &V,
216216 SmallVector &NameVals,
217 unsigned FSModRefsAbbrev,
218 unsigned FSModVTableRefsAbbrev);
217 unsigned FSModRefsAbbrev);
219218
220219 void assignValueId(GlobalValue::GUID ValGUID) {
221220 GUIDToValueIdMap[ValGUID] = ++GlobalValueId;
35283527 W.second);
35293528 }
35303529
3531 static void writeTypeIdMetadataSummaryRecord(
3532 SmallVector &NameVals, StringTableBuilder &StrtabBuilder,
3533 const std::string &Id, const TypeIdGVInfo &Summary, ValueEnumerator &VE) {
3534 NameVals.push_back(StrtabBuilder.add(Id));
3535 NameVals.push_back(Id.size());
3536
3537 for (auto &P : Summary) {
3538 NameVals.push_back(P.first);
3539 NameVals.push_back(VE.getValueID(P.second.getValue()));
3540 }
3541 }
3542
35433530 // Helper to emit a single function summary record.
35443531 void ModuleBitcodeWriterBase::writePerModuleFunctionSummaryRecord(
35453532 SmallVector &NameVals, GlobalValueSummary *Summary,
35843571 // and emit them in a summary record.
35853572 void ModuleBitcodeWriterBase::writeModuleLevelReferences(
35863573 const GlobalVariable &V, SmallVector &NameVals,
3587 unsigned FSModRefsAbbrev, unsigned FSModVTableRefsAbbrev) {
3574 unsigned FSModRefsAbbrev) {
35883575 auto VI = Index->getValueInfo(V.getGUID());
35893576 if (!VI || VI.getSummaryList().empty()) {
35903577 // Only declarations should not have a summary (a declaration might however
35983585 NameVals.push_back(getEncodedGVSummaryFlags(VS->flags()));
35993586 NameVals.push_back(getEncodedGVarFlags(VS->varflags()));
36003587
3601 auto VTableFuncs = VS->vTableFuncs();
3602 if (!VTableFuncs.empty())
3603 NameVals.push_back(VS->refs().size());
3604
36053588 unsigned SizeBeforeRefs = NameVals.size();
36063589 for (auto &RI : VS->refs())
36073590 NameVals.push_back(VE.getValueID(RI.getValue()));
36093592 // been initialized from a DenseSet.
36103593 llvm::sort(NameVals.begin() + SizeBeforeRefs, NameVals.end());
36113594
3612 if (!VTableFuncs.empty()) {
3613 // VTableFuncs pairs should already be sorted by offset.
3614 for (auto &P : VTableFuncs) {
3615 NameVals.push_back(VE.getValueID(P.first.getValue()));
3616 NameVals.push_back(P.second);
3617 }
3618 }
3619
3620 if (VTableFuncs.empty())
3621 Stream.EmitRecord(bitc::FS_PERMODULE_GLOBALVAR_INIT_REFS, NameVals,
3622 FSModRefsAbbrev);
3623 else
3624 Stream.EmitRecord(bitc::FS_PERMODULE_VTABLE_GLOBALVAR_INIT_REFS, NameVals,
3625 FSModVTableRefsAbbrev);
3595 Stream.EmitRecord(bitc::FS_PERMODULE_GLOBALVAR_INIT_REFS, NameVals,
3596 FSModRefsAbbrev);
36263597 NameVals.clear();
36273598 }
36283599
37033674 Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));
37043675 unsigned FSModRefsAbbrev = Stream.EmitAbbrev(std::move(Abbv));
37053676
3706 // Abbrev for FS_PERMODULE_VTABLE_GLOBALVAR_INIT_REFS.
3707 Abbv = std::make_shared();
3708 Abbv->Add(BitCodeAbbrevOp(bitc::FS_PERMODULE_VTABLE_GLOBALVAR_INIT_REFS));
3709 Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // valueid
3710 Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // flags
3711 Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 4)); // numrefs
3712 // numrefs x valueid, n x (valueid , offset)
3713 Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
3714 Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));
3715 unsigned FSModVTableRefsAbbrev = Stream.EmitAbbrev(std::move(Abbv));
3716
37173677 // Abbrev for FS_ALIAS.
37183678 Abbv = std::make_shared();
37193679 Abbv->Add(BitCodeAbbrevOp(bitc::FS_ALIAS));
37463706 // Capture references from GlobalVariable initializers, which are outside
37473707 // of a function scope.
37483708 for (const GlobalVariable &G : M.globals())
3749 writeModuleLevelReferences(G, NameVals, FSModRefsAbbrev,
3750 FSModVTableRefsAbbrev);
3709 writeModuleLevelReferences(G, NameVals, FSModRefsAbbrev);
37513710
37523711 for (const GlobalAlias &A : M.aliases()) {
37533712 auto *Aliasee = A.getBaseObject();
37633722 NameVals.push_back(AliaseeId);
37643723 Stream.EmitRecord(bitc::FS_ALIAS, NameVals, FSAliasAbbrev);
37653724 NameVals.clear();
3766 }
3767
3768 if (!Index->typeIdMetadataMap().empty()) {
3769 SmallVector NameVals;
3770 for (auto &S : Index->typeIdMetadataMap()) {
3771 writeTypeIdMetadataSummaryRecord(NameVals, StrtabBuilder, S.first,
3772 S.second, VE);
3773 Stream.EmitRecord(bitc::FS_TYPE_ID_METADATA, NameVals);
3774 NameVals.clear();
3775 }
37763725 }
37773726
37783727 Stream.ExitBlock();
10371037 TidIter != TheIndex->typeIds().end(); TidIter++)
10381038 CreateTypeIdSlot(TidIter->second.first);
10391039
1040 for (auto &TId : TheIndex->typeIdMetadataMap())
1041 CreateGUIDSlot(GlobalValue::getGUID(TId.first));
1042
10431040 ST_DEBUG("end processIndex!\n");
10441041 }
10451042
23952392 void printGlobalVarSummary(const GlobalVarSummary *GS);
23962393 void printFunctionSummary(const FunctionSummary *FS);
23972394 void printTypeIdSummary(const TypeIdSummary &TIS);
2398 void printTypeIdMetadataSummary(const TypeIdGVInfo &TI);
23992395 void printTypeTestResolution(const TypeTestResolution &TTRes);
24002396 void printArgs(const std::vector &Args);
24012397 void printWPDRes(const WholeProgramDevirtResolution &WPDRes);
26982694 printTypeIdSummary(TidIter->second.second);
26992695 Out << ") ; guid = " << TidIter->first << "\n";
27002696 }
2701
2702 // Print the TypeIdMetadataMap entries.
2703 for (auto &TId : TheIndex->typeIdMetadataMap()) {
2704 auto GUID = GlobalValue::getGUID(TId.first);
2705 Out << "^" << Machine.getGUIDSlot(GUID) << " = typeidMetadata: (name: \""
2706 << TId.first << "\"";
2707 printTypeIdMetadataSummary(TId.second);
2708 Out << ") ; guid = " << GUID << "\n";
2709 }
27102697 }
27112698
27122699 static const char *
27842771 printWPDRes(WPDRes.second);
27852772 Out << ")";
27862773 }
2787 Out << ")";
2788 }
2789 Out << ")";
2790 }
2791
2792 void AssemblyWriter::printTypeIdMetadataSummary(const TypeIdGVInfo &TI) {
2793 Out << ", summary: (";
2794 FieldSeparator FS;
2795 for (auto &P : TI) {
2796 Out << FS;
2797 Out << "(offset: " << P.first << ", ";
2798 Out << "^" << Machine.getGUIDSlot(P.second.getGUID());
27992774 Out << ")";
28002775 }
28012776 Out << ")";
28702845
28712846 void AssemblyWriter::printGlobalVarSummary(const GlobalVarSummary *GS) {
28722847 Out << ", varFlags: (readonly: " << GS->VarFlags.ReadOnly << ")";
2873
2874 auto VTableFuncs = GS->vTableFuncs();
2875 if (!VTableFuncs.empty()) {
2876 Out << ", vTableFuncs: (";
2877 FieldSeparator FS;
2878 for (auto &P : VTableFuncs) {
2879 Out << FS;
2880 Out << "(virtFunc: ^" << Machine.getGUIDSlot(P.first.getGUID())
2881 << ", offset: " << P.second;
2882 Out << ")";
2883 }
2884 Out << ")";
2885 }
28862848 }
28872849
28882850 static std::string getLinkageName(GlobalValue::LinkageTypes LT) {
417417 }
418418 }
419419
420 // Check if the LTO Unit splitting has been enabled.
421 bool enableSplitLTOUnit(Module &M) {
420 // Returns whether this module needs to be split because splitting is
421 // enabled and it uses type metadata.
422 bool requiresSplit(Module &M) {
423 // First check if the LTO Unit splitting has been enabled.
422424 bool EnableSplitLTOUnit = false;
423425 if (auto *MD = mdconst::extract_or_null(
424426 M.getModuleFlag("EnableSplitLTOUnit")))
425427 EnableSplitLTOUnit = MD->getZExtValue();
426 return EnableSplitLTOUnit;
427 }
428
429 // Returns whether this module needs to be split because it uses type metadata.
430 bool hasTypeMetadata(Module &M) {
428 if (!EnableSplitLTOUnit)
429 return false;
430
431 // Module only needs to be split if it contains type metadata.
431432 for (auto &GO : M.global_objects()) {
432433 if (GO.hasMetadata(LLVMContext::MD_type))
433434 return true;
434435 }
436
435437 return false;
436438 }
437439
438440 void writeThinLTOBitcode(raw_ostream &OS, raw_ostream *ThinLinkOS,
439441 function_ref AARGetter,
440442 Module &M, const ModuleSummaryIndex *Index) {
441 std::unique_ptr NewIndex = nullptr;
442 // See if this module has any type metadata. If so, we try to split it
443 // or at least promote type ids to enable WPD.
444 if (hasTypeMetadata(M)) {
445 if (enableSplitLTOUnit(M))
446 return splitAndWriteThinLTOBitcode(OS, ThinLinkOS, AARGetter, M);
447 else {
448 // Promote type ids as needed for index-based WPD.
449 std::string ModuleId = getUniqueModuleId(&M);
450 if (!ModuleId.empty()) {
451 promoteTypeIds(M, ModuleId);
452 // Need to rebuild the index so that it contains type metadata
453 // for the newly promoted type ids.
454 // FIXME: Probably should not bother building the index at all
455 // in the caller of writeThinLTOBitcode (which does so via the
456 // ModuleSummaryIndexAnalysis pass), since we have to rebuild it
457 // anyway whenever there is type metadata (here or in
458 // splitAndWriteThinLTOBitcode). Just always build it once via the
459 // buildModuleSummaryIndex when Module(s) are ready.
460 ProfileSummaryInfo PSI(M);
461 NewIndex = llvm::make_unique(
462 buildModuleSummaryIndex(M, nullptr, &PSI));
463 Index = NewIndex.get();
464 }
465 }
466 }
467
468 // Write it out as an unsplit ThinLTO module.
443 // Split module if splitting is enabled and it contains any type metadata.
444 if (requiresSplit(M))
445 return splitAndWriteThinLTOBitcode(OS, ThinLinkOS, AARGetter, M);
446
447 // Otherwise we can just write it out as a regular module.
469448
470449 // Save the module hash produced for the full bitcode, which will
471450 // be used in the backends, and use that in the minimized bitcode
+0
-38
test/Assembler/thinlto-vtable-summary.ll less more
None ; Test summary parsing of index-based WPD related summary fields
1 ; RUN: llvm-as %s -o - | llvm-dis -o %t.ll
2 ; RUN: grep "^\^" %s >%t2
3 ; RUN: grep "^\^" %t.ll >%t3
4 ; Expect that the summary information is the same after round-trip through
5 ; llvm-as and llvm-dis.
6 ; RUN: diff %t2 %t3
7
8 source_filename = "thinlto-vtable-summary.ll"
9 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
10 target triple = "x86_64-grtev4-linux-gnu"
11
12 %struct.A = type { i32 (...)** }
13 %struct.B = type { %struct.A }
14 %struct.C = type { %struct.A }
15
16 @_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
17 @_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
18
19 declare i32 @_ZN1B1fEi(%struct.B*, i32)
20
21 declare i32 @_ZN1A1nEi(%struct.A*, i32)
22
23 declare i32 @_ZN1C1fEi(%struct.C*, i32)
24
25 !0 = !{i64 16, !"_ZTS1A"}
26 !1 = !{i64 16, !"_ZTS1B"}
27 !2 = !{i64 16, !"_ZTS1C"}
28
29 ^0 = module: (path: "", hash: (0, 0, 0, 0, 0))
30 ^1 = gv: (name: "_ZN1A1nEi") ; guid = 1621563287929432257
31 ^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
32 ^3 = gv: (name: "_ZN1B1fEi") ; guid = 7162046368816414394
33 ^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
34 ^5 = gv: (name: "_ZN1C1fEi") ; guid = 14876272565662207556
35 ^6 = typeidMetadata: (name: "_ZTS1A", summary: ((offset: 16, ^2), (offset: 16, ^4))) ; guid = 7004155349499253778
36 ^7 = typeidMetadata: (name: "_ZTS1B", summary: ((offset: 16, ^2))) ; guid = 6203814149063363976
37 ^8 = typeidMetadata: (name: "_ZTS1C", summary: ((offset: 16, ^4))) ; guid = 1884921850105019584
+0
-146
test/ThinLTO/X86/devirt.ll less more
None ; REQUIRES: x86-registered-target
1
2 ; Test devirtualization through the thin link and backend.
3
4 ; Generate split module with summary for hybrid Thin/Regular LTO WPD.
5 ; RUN: opt -thinlto-bc -thinlto-split-lto-unit -o %t.o %s
6
7 ; Check that we have module flag showing splitting enabled, and that we don't
8 ; generate summary information needed for index-based WPD.
9 ; RUN: llvm-modextract -b -n=0 %t.o -o %t.o.0
10 ; RUN: llvm-dis -o - %t.o.0 | FileCheck %s --check-prefix=ENABLESPLITFLAG --implicit-check-not=vTableFuncs --implicit-check-not=typeidMetadata
11 ; RUN: llvm-modextract -b -n=1 %t.o -o %t.o.1
12 ; RUN: llvm-dis -o - %t.o.1 | FileCheck %s --check-prefix=ENABLESPLITFLAG --implicit-check-not=vTableFuncs --implicit-check-not=typeidMetadata
13 ; ENABLESPLITFLAG: !{i32 1, !"EnableSplitLTOUnit", i32 1}
14
15 ; Generate unsplit module with summary for ThinLTO index-based WPD.
16 ; RUN: opt -thinlto-bc -o %t2.o %s
17
18 ; Check that we don't have module flag when splitting not enabled for ThinLTO,
19 ; and that we generate summary information needed for index-based WPD.
20 ; RUN: llvm-dis -o - %t2.o | FileCheck %s --check-prefix=NOENABLESPLITFLAG
21 ; NOENABLESPLITFLAG-DAG: !{i32 1, !"EnableSplitLTOUnit", i32 0}
22 ; NOENABLESPLITFLAG-DAG: [[An:\^[0-9]+]] = gv: (name: "_ZN1A1nEi")
23 ; NOENABLESPLITFLAG-DAG: [[Bf:\^[0-9]+]] = gv: (name: "_ZN1B1fEi")
24 ; NOENABLESPLITFLAG-DAG: [[Cf:\^[0-9]+]] = gv: (name: "_ZN1C1fEi")
25 ; NOENABLESPLITFLAG-DAG: [[Dm:\^[0-9]+]] = gv: (name: "_ZN1D1mEi")
26 ; NOENABLESPLITFLAG-DAG: [[B:\^[0-9]+]] = gv: (name: "_ZTV1B", {{.*}} vTableFuncs: ((virtFunc: [[Bf]], offset: 16), (virtFunc: [[An]], offset: 24)), refs: ([[Bf]], [[An]])
27 ; NOENABLESPLITFLAG-DAG: [[C:\^[0-9]+]] = gv: (name: "_ZTV1C", {{.*}} vTableFuncs: ((virtFunc: [[Cf]], offset: 16), (virtFunc: [[An]], offset: 24)), refs: ([[An]], [[Cf]])
28 ; NOENABLESPLITFLAG-DAG: [[D:\^[0-9]+]] = gv: (name: "_ZTV1D", {{.*}} vTableFuncs: ((virtFunc: [[Dm]], offset: 16)), refs: ([[Dm]])
29 ; NOENABLESPLITFLAG-DAG: typeidMetadata: (name: "_ZTS1A", summary: ((offset: 16, [[B]]), (offset: 16, [[C]])))
30 ; NOENABLESPLITFLAG-DAG: typeidMetadata: (name: "_ZTS1B", summary: ((offset: 16, [[B]])))
31 ; NOENABLESPLITFLAG-DAG: typeidMetadata: (name: "_ZTS1C", summary: ((offset: 16, [[C]])))
32 ; Type Id on _ZTV1D should have been promoted
33 ; NOENABLESPLITFLAG-DAG: typeidMetadata: (name: "1${{.*}}", summary: ((offset: 16, [[D]])))
34
35 ; TODO: Test index-based WPD one %t2.o once implemented.
36
37 ; Legacy PM
38 ; RUN: llvm-lto2 run %t.o -save-temps -pass-remarks=. \
39 ; RUN: -o %t3 \
40 ; RUN: -r=%t.o,test,px \
41 ; RUN: -r=%t.o,_ZN1A1nEi,p \
42 ; RUN: -r=%t.o,_ZN1B1fEi,p \
43 ; RUN: -r=%t.o,_ZN1C1fEi,p \
44 ; RUN: -r=%t.o,_ZN1D1mEi,p \
45 ; RUN: -r=%t.o,_ZTV1B, \
46 ; RUN: -r=%t.o,_ZTV1C, \
47 ; RUN: -r=%t.o,_ZTV1D, \
48 ; RUN: -r=%t.o,_ZN1A1nEi, \
49 ; RUN: -r=%t.o,_ZN1B1fEi, \
50 ; RUN: -r=%t.o,_ZN1C1fEi, \
51 ; RUN: -r=%t.o,_ZN1D1mEi, \
52 ; RUN: -r=%t.o,_ZTV1B,px \
53 ; RUN: -r=%t.o,_ZTV1C,px \
54 ; RUN: -r=%t.o,_ZTV1D,px 2>&1 | FileCheck %s --check-prefix=REMARK
55 ; RUN: llvm-dis %t3.1.4.opt.bc -o - | FileCheck %s --check-prefix=CHECK-IR
56
57 ; New PM
58 ; RUN: llvm-lto2 run %t.o -save-temps -use-new-pm -pass-remarks=. \
59 ; RUN: -o %t3 \
60 ; RUN: -r=%t.o,test,px \
61 ; RUN: -r=%t.o,_ZN1A1nEi,p \
62 ; RUN: -r=%t.o,_ZN1B1fEi,p \
63 ; RUN: -r=%t.o,_ZN1C1fEi,p \
64 ; RUN: -r=%t.o,_ZN1D1mEi,p \
65 ; RUN: -r=%t.o,_ZTV1B, \
66 ; RUN: -r=%t.o,_ZTV1C, \
67 ; RUN: -r=%t.o,_ZTV1D, \
68 ; RUN: -r=%t.o,_ZN1A1nEi, \
69 ; RUN: -r=%t.o,_ZN1B1fEi, \
70 ; RUN: -r=%t.o,_ZN1C1fEi, \
71 ; RUN: -r=%t.o,_ZN1D1mEi, \
72 ; RUN: -r=%t.o,_ZTV1B,px \
73 ; RUN: -r=%t.o,_ZTV1C,px \
74 ; RUN: -r=%t.o,_ZTV1D,px 2>&1 | FileCheck %s --check-prefix=REMARK
75 ; RUN: llvm-dis %t3.1.4.opt.bc -o - | FileCheck %s --check-prefix=CHECK-IR
76
77 ; REMARK-DAG: single-impl: devirtualized a call to _ZN1A1nEi
78 ; REMARK-DAG: single-impl: devirtualized a call to _ZN1D1mEi
79
80 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
81 target triple = "x86_64-grtev4-linux-gnu"
82
83 %struct.A = type { i32 (...)** }
84 %struct.B = type { %struct.A }
85 %struct.C = type { %struct.A }
86 %struct.D = type { i32 (...)** }
87
88 @_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
89 @_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
90 @_ZTV1D = constant { [3 x i8*] } { [3 x i8*] [i8* null, i8* undef, i8* bitcast (i32 (%struct.D*, i32)* @_ZN1D1mEi to i8*)] }, !type !3
91
92
93 ; CHECK-IR-LABEL: define i32 @test
94 define i32 @test(%struct.A* %obj, %struct.D* %obj2, i32 %a) {
95 entry:
96 %0 = bitcast %struct.A* %obj to i8***
97 %vtable = load i8**, i8*** %0
98 %1 = bitcast i8** %vtable to i8*
99 %p = call i1 @llvm.type.test(i8* %1, metadata !"_ZTS1A")
100 call void @llvm.assume(i1 %p)
101 %fptrptr = getelementptr i8*, i8** %vtable, i32 1
102 %2 = bitcast i8** %fptrptr to i32 (%struct.A*, i32)**
103 %fptr1 = load i32 (%struct.A*, i32)*, i32 (%struct.A*, i32)** %2, align 8
104
105 ; Check that the call was devirtualized.
106 ; CHECK-IR: %call = tail call i32 @_ZN1A1nEi
107 %call = tail call i32 %fptr1(%struct.A* nonnull %obj, i32 %a)
108
109 %3 = bitcast i8** %vtable to i32 (%struct.A*, i32)**
110 %fptr22 = load i32 (%struct.A*, i32)*, i32 (%struct.A*, i32)** %3, align 8
111
112 ; We still have to call it as virtual.
113 ; CHECK-IR: %call3 = tail call i32 %fptr22
114 %call3 = tail call i32 %fptr22(%struct.A* nonnull %obj, i32 %call)
115
116 %4 = bitcast %struct.D* %obj2 to i8***
117 %vtable2 = load i8**, i8*** %4
118 %5 = bitcast i8** %vtable2 to i8*
119 %p2 = call i1 @llvm.type.test(i8* %5, metadata !4)
120 call void @llvm.assume(i1 %p2)
121
122 %6 = bitcast i8** %vtable2 to i32 (%struct.D*, i32)**
123 %fptr33 = load i32 (%struct.D*, i32)*, i32 (%struct.D*, i32)** %6, align 8
124
125 ; Check that the call was devirtualized.
126 ; CHECK-IR: %call4 = tail call i32 @_ZN1D1mEi
127 %call4 = tail call i32 %fptr33(%struct.D* nonnull %obj2, i32 %call3)
128 ret i32 %call4
129 }
130 ; CHECK-IR-LABEL: ret i32
131 ; CHECK-IR-LABEL: }
132
133 declare i1 @llvm.type.test(i8*, metadata)
134 declare void @llvm.assume(i1)
135
136 declare i32 @_ZN1B1fEi(%struct.B* %this, i32 %a)
137 declare i32 @_ZN1A1nEi(%struct.A* %this, i32 %a)
138 declare i32 @_ZN1C1fEi(%struct.C* %this, i32 %a)
139 declare i32 @_ZN1D1mEi(%struct.D* %this, i32 %a)
140
141 !0 = !{i64 16, !"_ZTS1A"}
142 !1 = !{i64 16, !"_ZTS1B"}
143 !2 = !{i64 16, !"_ZTS1C"}
144 !3 = !{i64 16, !4}
145 !4 = distinct !{}
316316 STRINGIFY_CODE(FS, PERMODULE_PROFILE)
317317 STRINGIFY_CODE(FS, PERMODULE_RELBF)
318318 STRINGIFY_CODE(FS, PERMODULE_GLOBALVAR_INIT_REFS)
319 STRINGIFY_CODE(FS, PERMODULE_VTABLE_GLOBALVAR_INIT_REFS)
320319 STRINGIFY_CODE(FS, COMBINED)
321320 STRINGIFY_CODE(FS, COMBINED_PROFILE)
322321 STRINGIFY_CODE(FS, COMBINED_GLOBALVAR_INIT_REFS)
334333 STRINGIFY_CODE(FS, CFI_FUNCTION_DEFS)
335334 STRINGIFY_CODE(FS, CFI_FUNCTION_DECLS)
336335 STRINGIFY_CODE(FS, TYPE_ID)
337 STRINGIFY_CODE(FS, TYPE_ID_METADATA)
338336 }
339337 case bitc::METADATA_ATTACHMENT_ID:
340338 switch(CodeID) {