llvm.org GIT mirror llvm / 7a71aab
[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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@364960 91177308-0d34-0410-b5e6-96231b3b80d8 Teresa Johnson a month ago
14 changed file(s) with 767 addition(s) and 27 deletion(s). Raw diff Collapse all Expand all
262262 // Index-wide flags
263263 FS_FLAGS = 20,
264264 // Maps type identifier to summary information for that type identifier.
265 // Produced by the thin link (only lives in combined index).
265266 // TYPE_ID: [typeid, kind, bitwidth, align, size, bitmask, inlinebits,
266267 // n x (typeid, kind, name, numrba,
267268 // numrba x (numarg, numarg x arg, kind, info, byte, bit))]
268269 FS_TYPE_ID = 21,
270 // For background see overview at https://llvm.org/docs/TypeMetadata.html.
271 // The type metadata includes both the type identifier and the offset of
272 // the address point of the type (the address held by objects of that type
273 // which may not be the beginning of the virtual table). Vtable definitions
274 // are decorated with type metadata for the types they are compatible with.
275 //
276 // Maps type identifier to summary information for that type identifier
277 // computed from type metadata: the valueid of each vtable definition
278 // decorated with a type metadata for that identifier, and the offset from
279 // the corresponding type metadata.
280 // Exists in the per-module summary to provide information to thin link
281 // for index-based whole program devirtualization.
282 // TYPE_ID_METADATA: [typeid, n x (valueid, offset)]
283 FS_TYPE_ID_METADATA = 22,
284 // Summarizes vtable definition for use in index-based whole program
285 // devirtualization during the thin link.
286 // PERMODULE_VTABLE_GLOBALVAR_INIT_REFS: [valueid, flags, varflags,
287 // numrefs, numrefs x valueid,
288 // n x (valueid, offset)]
289 FS_PERMODULE_VTABLE_GLOBALVAR_INIT_REFS = 23,
269290 };
270291
271292 enum MetadataCodes {
697697 }
698698 };
699699
700 /// The ValueInfo and offset for a function within a vtable definition
701 /// initializer array.
702 struct VirtFuncOffset {
703 VirtFuncOffset(ValueInfo VI, uint64_t Offset)
704 : FuncVI(VI), VTableOffset(Offset) {}
705
706 ValueInfo FuncVI;
707 uint64_t VTableOffset;
708 };
709 /// List of functions referenced by a particular vtable definition.
710 using VTableFuncList = std::vector;
711
700712 /// Global variable summary information to aid decisions and
701713 /// implementation of importing.
702714 ///
704716 /// modified during the program run or not. This affects ThinLTO
705717 /// internalization
706718 class GlobalVarSummary : public GlobalValueSummary {
719 private:
720 /// For vtable definitions this holds the list of functions and
721 /// their corresponding offsets within the initializer array.
722 std::unique_ptr VTableFuncs;
723
707724 public:
708725 struct GVarFlags {
709726 GVarFlags(bool ReadOnly = false) : ReadOnly(ReadOnly) {}
724741 GVarFlags varflags() const { return VarFlags; }
725742 void setReadOnly(bool RO) { VarFlags.ReadOnly = RO; }
726743 bool isReadOnly() const { return VarFlags.ReadOnly; }
744
745 void setVTableFuncs(VTableFuncList Funcs) {
746 assert(!VTableFuncs);
747 VTableFuncs = llvm::make_unique(std::move(Funcs));
748 }
749
750 ArrayRef vTableFuncs() const {
751 if (VTableFuncs)
752 return *VTableFuncs;
753 return {};
754 }
727755 };
728756
729757 struct TypeTestResolution {
822850 using TypeIdSummaryMapTy =
823851 std::multimap>;
824852
853 /// The following data structures summarize type metadata information.
854 /// For type metadata overview see https://llvm.org/docs/TypeMetadata.html.
855 /// Each type metadata includes both the type identifier and the offset of
856 /// the address point of the type (the address held by objects of that type
857 /// which may not be the beginning of the virtual table). Vtable definitions
858 /// are decorated with type metadata for the types they are compatible with.
859 ///
860 /// Holds information about vtable definitions decorated with type metadata:
861 /// the vtable definition value and its address point offset in a type
862 /// identifier metadata it is decorated (compatible) with.
863 struct TypeIdOffsetVtableInfo {
864 TypeIdOffsetVtableInfo(uint64_t Offset, ValueInfo VI)
865 : AddressPointOffset(Offset), VTableVI(VI) {}
866
867 uint64_t AddressPointOffset;
868 ValueInfo VTableVI;
869 };
870 /// List of vtable definitions decorated by a particular type identifier,
871 /// and their corresponding offsets in that type identifier's metadata.
872 /// Note that each type identifier may be compatible with multiple vtables, due
873 /// to inheritance, which is why this is a vector.
874 using TypeIdCompatibleVtableInfo = std::vector;
875
825876 /// Class to hold module path string table and global value map,
826877 /// and encapsulate methods for operating on them.
827878 class ModuleSummaryIndex {
834885 ModulePathStringTableTy ModulePathStringTable;
835886
836887 /// Mapping from type identifier GUIDs to type identifier and its summary
837 /// information.
888 /// information. Produced by thin link.
838889 TypeIdSummaryMapTy TypeIdMap;
890
891 /// Mapping from type identifier to information about vtables decorated
892 /// with that type identifier's metadata. Produced by per module summary
893 /// analysis and consumed by thin link. For more information, see description
894 /// above where TypeIdCompatibleVtableInfo is defined.
895 std::map TypeIdCompatibleVtableMap;
839896
840897 /// Mapping from original ID to GUID. If original ID can map to multiple
841898 /// GUIDs, it will be mapped to 0.
12001257 return nullptr;
12011258 }
12021259
1260 const std::map &
1261 typeIdCompatibleVtableMap() const {
1262 return TypeIdCompatibleVtableMap;
1263 }
1264
1265 /// Return an existing or new TypeIdCompatibleVtableMap entry for \p TypeId.
1266 /// This accessor can mutate the map and therefore should not be used in
1267 /// the ThinLTO backends.
1268 TypeIdCompatibleVtableInfo &
1269 getOrInsertTypeIdCompatibleVtableSummary(StringRef TypeId) {
1270 return TypeIdCompatibleVtableMap[TypeId];
1271 }
1272
1273 /// For the given \p TypeId, this returns the TypeIdCompatibleVtableMap
1274 /// entry if present in the summary map. This may be used when importing.
1275 Optional
1276 getTypeIdCompatibleVtableSummary(StringRef TypeId) const {
1277 auto I = TypeIdCompatibleVtableMap.find(TypeId);
1278 if (I == TypeIdCompatibleVtableMap.end())
1279 return None;
1280 return I->second;
1281 }
1282
12031283 /// Collect for the given module the list of functions it defines
12041284 /// (GUID -> Summary).
12051285 void collectDefinedFunctionsForModule(StringRef ModulePath,
410410 Index.addGlobalValueSummary(F, std::move(FuncSummary));
411411 }
412412
413 /// Find function pointers referenced within the given vtable initializer
414 /// (or subset of an initializer) \p I. The starting offset of \p I within
415 /// the vtable initializer is \p StartingOffset. Any discovered function
416 /// pointers are added to \p VTableFuncs along with their cumulative offset
417 /// within the initializer.
418 static void findFuncPointers(const Constant *I, uint64_t StartingOffset,
419 const Module &M, ModuleSummaryIndex &Index,
420 VTableFuncList &VTableFuncs) {
421 // First check if this is a function pointer.
422 if (I->getType()->isPointerTy()) {
423 auto Fn = dyn_cast(I->stripPointerCasts());
424 // We can disregard __cxa_pure_virtual as a possible call target, as
425 // calls to pure virtuals are UB.
426 if (Fn && Fn->getName() != "__cxa_pure_virtual")
427 VTableFuncs.push_back({Index.getOrInsertValueInfo(Fn), StartingOffset});
428 return;
429 }
430
431 // Walk through the elements in the constant struct or array and recursively
432 // look for virtual function pointers.
433 const DataLayout &DL = M.getDataLayout();
434 if (auto *C = dyn_cast(I)) {
435 StructType *STy = dyn_cast(C->getType());
436 assert(STy);
437 const StructLayout *SL = DL.getStructLayout(C->getType());
438
439 for (StructType::element_iterator EB = STy->element_begin(), EI = EB,
440 EE = STy->element_end();
441 EI != EE; ++EI) {
442 auto Offset = SL->getElementOffset(EI - EB);
443 unsigned Op = SL->getElementContainingOffset(Offset);
444 findFuncPointers(cast(I->getOperand(Op)),
445 StartingOffset + Offset, M, Index, VTableFuncs);
446 }
447 } else if (auto *C = dyn_cast(I)) {
448 ArrayType *ATy = C->getType();
449 Type *EltTy = ATy->getElementType();
450 uint64_t EltSize = DL.getTypeAllocSize(EltTy);
451 for (unsigned i = 0, e = ATy->getNumElements(); i != e; ++i) {
452 findFuncPointers(cast(I->getOperand(i)),
453 StartingOffset + i * EltSize, M, Index, VTableFuncs);
454 }
455 }
456 }
457
458 // Identify the function pointers referenced by vtable definition \p V.
459 static void computeVTableFuncs(ModuleSummaryIndex &Index,
460 const GlobalVariable &V, const Module &M,
461 VTableFuncList &VTableFuncs) {
462 if (!V.isConstant())
463 return;
464
465 findFuncPointers(V.getInitializer(), /*StartingOffset=*/0, M, Index,
466 VTableFuncs);
467
468 #ifndef NDEBUG
469 // Validate that the VTableFuncs list is ordered by offset.
470 uint64_t PrevOffset = 0;
471 for (auto &P : VTableFuncs) {
472 // The findVFuncPointers traversal should have encountered the
473 // functions in offset order. We need to use ">=" since PrevOffset
474 // starts at 0.
475 assert(P.VTableOffset >= PrevOffset);
476 PrevOffset = P.VTableOffset;
477 }
478 #endif
479 }
480
481 /// Record vtable definition \p V for each type metadata it references.
413482 static void
414 computeVariableSummary(ModuleSummaryIndex &Index, const GlobalVariable &V,
415 DenseSet &CantBePromoted) {
483 recordTypeIdCompatibleVtableReferences(ModuleSummaryIndex &Index,
484 const GlobalVariable &V,
485 SmallVectorImpl &Types) {
486 for (MDNode *Type : Types) {
487 auto TypeID = Type->getOperand(1).get();
488
489 uint64_t Offset =
490 cast(
491 cast(Type->getOperand(0))->getValue())
492 ->getZExtValue();
493
494 if (auto *TypeId = dyn_cast(TypeID))
495 Index.getOrInsertTypeIdCompatibleVtableSummary(TypeId->getString())
496 .push_back({Offset, Index.getOrInsertValueInfo(&V)});
497 }
498 }
499
500 static void computeVariableSummary(ModuleSummaryIndex &Index,
501 const GlobalVariable &V,
502 DenseSet &CantBePromoted,
503 const Module &M,
504 SmallVectorImpl &Types) {
416505 SetVector RefEdges;
417506 SmallPtrSet Visited;
418507 bool HasBlockAddress = findRefEdges(Index, &V, RefEdges, Visited);
420509 GlobalValueSummary::GVFlags Flags(V.getLinkage(), NonRenamableLocal,
421510 /* Live = */ false, V.isDSOLocal(),
422511 V.hasLinkOnceODRLinkage() && V.hasGlobalUnnamedAddr());
512
513 VTableFuncList VTableFuncs;
514 // If splitting is not enabled, then we compute the summary information
515 // necessary for index-based whole program devirtualization.
516 if (!Index.enableSplitLTOUnit()) {
517 Types.clear();
518 V.getMetadata(LLVMContext::MD_type, Types);
519 if (!Types.empty()) {
520 // Identify the function pointers referenced by this vtable definition.
521 computeVTableFuncs(Index, V, M, VTableFuncs);
522
523 // Record this vtable definition for each type metadata it references.
524 recordTypeIdCompatibleVtableReferences(Index, V, Types);
525 }
526 }
423527
424528 // Don't mark variables we won't be able to internalize as read-only.
425529 GlobalVarSummary::GVarFlags VarFlags(
431535 CantBePromoted.insert(V.getGUID());
432536 if (HasBlockAddress)
433537 GVarSummary->setNotEligibleToImport();
538 if (!VTableFuncs.empty())
539 GVarSummary->setVTableFuncs(VTableFuncs);
434540 Index.addGlobalValueSummary(V, std::move(GVarSummary));
435541 }
436542
577683
578684 // Compute summaries for all variables defined in module, and save in the
579685 // index.
686 SmallVector Types;
580687 for (const GlobalVariable &G : M.globals()) {
581688 if (G.isDeclaration())
582689 continue;
583 computeVariableSummary(Index, G, CantBePromoted);
690 computeVariableSummary(Index, G, CantBePromoted, M, Types);
584691 }
585692
586693 // Compute summaries for all aliases defined in module, and save in the
751751 KEYWORD(critical);
752752 KEYWORD(relbf);
753753 KEYWORD(variable);
754 KEYWORD(vTableFuncs);
755 KEYWORD(virtFunc);
754756 KEYWORD(aliasee);
755757 KEYWORD(refs);
756758 KEYWORD(typeIdInfo);
763765 KEYWORD(offset);
764766 KEYWORD(args);
765767 KEYWORD(typeid);
768 KEYWORD(typeidCompatibleVTable);
766769 KEYWORD(summary);
767770 KEYWORD(typeTestRes);
768771 KEYWORD(kind);
830830 break;
831831 case lltok::kw_typeid:
832832 result = ParseTypeIdEntry(SummaryID);
833 break;
834 case lltok::kw_typeidCompatibleVTable:
835 result = ParseTypeIdCompatibleVtableEntry(SummaryID);
833836 break;
834837 default:
835838 result = Error(Lex.getLoc(), "unexpected summary kind");
74857488 return false;
74867489 }
74877490
7491 static ValueInfo EmptyVI =
7492 ValueInfo(false, (GlobalValueSummaryMapTy::value_type *)-8);
7493
7494 /// TypeIdCompatibleVtableEntry
7495 /// ::= 'typeidCompatibleVTable' ':' '(' 'name' ':' STRINGCONSTANT ','
7496 /// TypeIdCompatibleVtableInfo
7497 /// ')'
7498 bool LLParser::ParseTypeIdCompatibleVtableEntry(unsigned ID) {
7499 assert(Lex.getKind() == lltok::kw_typeidCompatibleVTable);
7500 Lex.Lex();
7501
7502 std::string Name;
7503 if (ParseToken(lltok::colon, "expected ':' here") ||
7504 ParseToken(lltok::lparen, "expected '(' here") ||
7505 ParseToken(lltok::kw_name, "expected 'name' here") ||
7506 ParseToken(lltok::colon, "expected ':' here") ||
7507 ParseStringConstant(Name))
7508 return true;
7509
7510 TypeIdCompatibleVtableInfo &TI =
7511 Index->getOrInsertTypeIdCompatibleVtableSummary(Name);
7512 if (ParseToken(lltok::comma, "expected ',' here") ||
7513 ParseToken(lltok::kw_summary, "expected 'summary' here") ||
7514 ParseToken(lltok::colon, "expected ':' here") ||
7515 ParseToken(lltok::lparen, "expected '(' here"))
7516 return true;
7517
7518 IdToIndexMapType IdToIndexMap;
7519 // Parse each call edge
7520 do {
7521 uint64_t Offset;
7522 if (ParseToken(lltok::lparen, "expected '(' here") ||
7523 ParseToken(lltok::kw_offset, "expected 'offset' here") ||
7524 ParseToken(lltok::colon, "expected ':' here") || ParseUInt64(Offset) ||
7525 ParseToken(lltok::comma, "expected ',' here"))
7526 return true;
7527
7528 LocTy Loc = Lex.getLoc();
7529 unsigned GVId;
7530 ValueInfo VI;
7531 if (ParseGVReference(VI, GVId))
7532 return true;
7533
7534 // Keep track of the TypeIdCompatibleVtableInfo array index needing a
7535 // forward reference. We will save the location of the ValueInfo needing an
7536 // update, but can only do so once the std::vector is finalized.
7537 if (VI == EmptyVI)
7538 IdToIndexMap[GVId].push_back(std::make_pair(TI.size(), Loc));
7539 TI.push_back({Offset, VI});
7540
7541 if (ParseToken(lltok::rparen, "expected ')' in call"))
7542 return true;
7543 } while (EatIfPresent(lltok::comma));
7544
7545 // Now that the TI vector is finalized, it is safe to save the locations
7546 // of any forward GV references that need updating later.
7547 for (auto I : IdToIndexMap) {
7548 for (auto P : I.second) {
7549 assert(TI[P.first].VTableVI == EmptyVI &&
7550 "Forward referenced ValueInfo expected to be empty");
7551 auto FwdRef = ForwardRefValueInfos.insert(std::make_pair(
7552 I.first, std::vector>()));
7553 FwdRef.first->second.push_back(
7554 std::make_pair(&TI[P.first].VTableVI, P.second));
7555 }
7556 }
7557
7558 if (ParseToken(lltok::rparen, "expected ')' here") ||
7559 ParseToken(lltok::rparen, "expected ')' here"))
7560 return true;
7561
7562 // Check if this ID was forward referenced, and if so, update the
7563 // corresponding GUIDs.
7564 auto FwdRefTIDs = ForwardRefTypeIds.find(ID);
7565 if (FwdRefTIDs != ForwardRefTypeIds.end()) {
7566 for (auto TIDRef : FwdRefTIDs->second) {
7567 assert(!*TIDRef.first &&
7568 "Forward referenced type id GUID expected to be 0");
7569 *TIDRef.first = GlobalValue::getGUID(Name);
7570 }
7571 ForwardRefTypeIds.erase(FwdRefTIDs);
7572 }
7573
7574 return false;
7575 }
7576
74887577 /// TypeTestResolution
74897578 /// ::= 'typeTestRes' ':' '(' 'kind' ':'
74907579 /// ( 'unsat' | 'byteArray' | 'inline' | 'single' | 'allOnes' ) ','
79938082 /*Live=*/false, /*IsLocal=*/false, /*CanAutoHide=*/false);
79948083 GlobalVarSummary::GVarFlags GVarFlags(/*ReadOnly*/ false);
79958084 std::vector Refs;
8085 VTableFuncList VTableFuncs;
79968086 if (ParseToken(lltok::colon, "expected ':' here") ||
79978087 ParseToken(lltok::lparen, "expected '(' here") ||
79988088 ParseModuleReference(ModulePath) ||
80018091 ParseGVarFlags(GVarFlags))
80028092 return true;
80038093
8004 // Parse optional refs field
8005 if (EatIfPresent(lltok::comma)) {
8006 if (ParseOptionalRefs(Refs))
8007 return true;
8094 // Parse optional fields
8095 while (EatIfPresent(lltok::comma)) {
8096 switch (Lex.getKind()) {
8097 case lltok::kw_vTableFuncs:
8098 if (ParseOptionalVTableFuncs(VTableFuncs))
8099 return true;
8100 break;
8101 case lltok::kw_refs:
8102 if (ParseOptionalRefs(Refs))
8103 return true;
8104 break;
8105 default:
8106 return Error(Lex.getLoc(), "expected optional variable summary field");
8107 }
80088108 }
80098109
80108110 if (ParseToken(lltok::rparen, "expected ')' here"))
80148114 llvm::make_unique(GVFlags, GVarFlags, std::move(Refs));
80158115
80168116 GS->setModulePath(ModulePath);
8117 GS->setVTableFuncs(std::move(VTableFuncs));
80178118
80188119 AddGlobalValueToIndex(Name, GUID, (GlobalValue::LinkageTypes)GVFlags.Linkage,
80198120 ID, std::move(GS));
82318332 return Error(Lex.getLoc(), "invalid call edge hotness");
82328333 }
82338334 Lex.Lex();
8335 return false;
8336 }
8337
8338 /// OptionalVTableFuncs
8339 /// := 'vTableFuncs' ':' '(' VTableFunc [',' VTableFunc]* ')'
8340 /// VTableFunc ::= '(' 'virtFunc' ':' GVReference ',' 'offset' ':' UInt64 ')'
8341 bool LLParser::ParseOptionalVTableFuncs(VTableFuncList &VTableFuncs) {
8342 assert(Lex.getKind() == lltok::kw_vTableFuncs);
8343 Lex.Lex();
8344
8345 if (ParseToken(lltok::colon, "expected ':' in vTableFuncs") |
8346 ParseToken(lltok::lparen, "expected '(' in vTableFuncs"))
8347 return true;
8348
8349 IdToIndexMapType IdToIndexMap;
8350 // Parse each virtual function pair
8351 do {
8352 ValueInfo VI;
8353 if (ParseToken(lltok::lparen, "expected '(' in vTableFunc") ||
8354 ParseToken(lltok::kw_virtFunc, "expected 'callee' in vTableFunc") ||
8355 ParseToken(lltok::colon, "expected ':'"))
8356 return true;
8357
8358 LocTy Loc = Lex.getLoc();
8359 unsigned GVId;
8360 if (ParseGVReference(VI, GVId))
8361 return true;
8362
8363 uint64_t Offset;
8364 if (ParseToken(lltok::comma, "expected comma") ||
8365 ParseToken(lltok::kw_offset, "expected offset") ||
8366 ParseToken(lltok::colon, "expected ':'") || ParseUInt64(Offset))
8367 return true;
8368
8369 // Keep track of the VTableFuncs array index needing a forward reference.
8370 // We will save the location of the ValueInfo needing an update, but
8371 // can only do so once the std::vector is finalized.
8372 if (VI == EmptyVI)
8373 IdToIndexMap[GVId].push_back(std::make_pair(VTableFuncs.size(), Loc));
8374 VTableFuncs.push_back({VI, Offset});
8375
8376 if (ParseToken(lltok::rparen, "expected ')' in vTableFunc"))
8377 return true;
8378 } while (EatIfPresent(lltok::comma));
8379
8380 // Now that the VTableFuncs vector is finalized, it is safe to save the
8381 // locations of any forward GV references that need updating later.
8382 for (auto I : IdToIndexMap) {
8383 for (auto P : I.second) {
8384 assert(VTableFuncs[P.first].FuncVI == EmptyVI &&
8385 "Forward referenced ValueInfo expected to be empty");
8386 auto FwdRef = ForwardRefValueInfos.insert(std::make_pair(
8387 I.first, std::vector>()));
8388 FwdRef.first->second.push_back(
8389 std::make_pair(&VTableFuncs[P.first].FuncVI, P.second));
8390 }
8391 }
8392
8393 if (ParseToken(lltok::rparen, "expected ')' in vTableFuncs"))
8394 return true;
8395
82348396 return false;
82358397 }
82368398
368368 IdToIndexMapType &IdToIndexMap, unsigned Index);
369369 bool ParseVFuncId(FunctionSummary::VFuncId &VFuncId,
370370 IdToIndexMapType &IdToIndexMap, unsigned Index);
371 bool ParseOptionalVTableFuncs(VTableFuncList &VTableFuncs);
371372 bool ParseOptionalRefs(std::vector &Refs);
372373 bool ParseTypeIdEntry(unsigned ID);
373374 bool ParseTypeIdSummary(TypeIdSummary &TIS);
375 bool ParseTypeIdCompatibleVtableEntry(unsigned ID);
374376 bool ParseTypeTestResolution(TypeTestResolution &TTRes);
375377 bool ParseOptionalWpdResolutions(
376378 std::map &WPDResMap);
382382 kw_critical,
383383 kw_relbf,
384384 kw_variable,
385 kw_vTableFuncs,
386 kw_virtFunc,
385387 kw_aliasee,
386388 kw_refs,
387389 kw_typeIdInfo,
394396 kw_offset,
395397 kw_args,
396398 kw_typeid,
399 kw_typeidCompatibleVTable,
397400 kw_summary,
398401 kw_typeTestRes,
399402 kw_kind,
827827 bool HasRelBF);
828828 Error parseEntireSummary(unsigned ID);
829829 Error parseModuleStringTable();
830 void parseTypeIdCompatibleVtableSummaryRecord(ArrayRef Record);
831 void parseTypeIdCompatibleVtableInfo(ArrayRef Record, size_t &Slot,
832 TypeIdCompatibleVtableInfo &TypeId);
830833
831834 std::pair
832835 getValueInfoFromValueId(unsigned ValueId);
56565659 parseWholeProgramDevirtResolution(Record, Strtab, Slot, TypeId);
56575660 }
56585661
5662 void ModuleSummaryIndexBitcodeReader::parseTypeIdCompatibleVtableInfo(
5663 ArrayRef Record, size_t &Slot,
5664 TypeIdCompatibleVtableInfo &TypeId) {
5665 uint64_t Offset = Record[Slot++];
5666 ValueInfo Callee = getValueInfoFromValueId(Record[Slot++]).first;
5667 TypeId.push_back({Offset, Callee});
5668 }
5669
5670 void ModuleSummaryIndexBitcodeReader::parseTypeIdCompatibleVtableSummaryRecord(
5671 ArrayRef Record) {
5672 size_t Slot = 0;
5673 TypeIdCompatibleVtableInfo &TypeId =
5674 TheIndex.getOrInsertTypeIdCompatibleVtableSummary(
5675 {Strtab.data() + Record[Slot],
5676 static_cast(Record[Slot + 1])});
5677 Slot += 2;
5678
5679 while (Slot < Record.size())
5680 parseTypeIdCompatibleVtableInfo(Record, Slot, TypeId);
5681 }
5682
56595683 static void setImmutableRefs(std::vector &Refs, unsigned Count) {
56605684 // Read-only refs are in the end of the refs list.
56615685 for (unsigned RefNo = Refs.size() - Count; RefNo < Refs.size(); ++RefNo)
58825906 TheIndex.addGlobalValueSummary(GUID.first, std::move(FS));
58835907 break;
58845908 }
5909 // FS_PERMODULE_VTABLE_GLOBALVAR_INIT_REFS: [valueid, flags, varflags,
5910 // numrefs, numrefs x valueid,
5911 // n x (valueid, offset)]
5912 case bitc::FS_PERMODULE_VTABLE_GLOBALVAR_INIT_REFS: {
5913 unsigned ValueID = Record[0];
5914 uint64_t RawFlags = Record[1];
5915 GlobalVarSummary::GVarFlags GVF = getDecodedGVarFlags(Record[2]);
5916 unsigned NumRefs = Record[3];
5917 unsigned RefListStartIndex = 4;
5918 unsigned VTableListStartIndex = RefListStartIndex + NumRefs;
5919 auto Flags = getDecodedGVSummaryFlags(RawFlags, Version);
5920 std::vector Refs = makeRefList(
5921 ArrayRef(Record).slice(RefListStartIndex, NumRefs));
5922 VTableFuncList VTableFuncs;
5923 for (unsigned I = VTableListStartIndex, E = Record.size(); I != E; ++I) {
5924 ValueInfo Callee = getValueInfoFromValueId(Record[I]).first;
5925 uint64_t Offset = Record[++I];
5926 VTableFuncs.push_back({Callee, Offset});
5927 }
5928 auto VS =
5929 llvm::make_unique(Flags, GVF, std::move(Refs));
5930 VS->setModulePath(getThisModule()->first());
5931 VS->setVTableFuncs(VTableFuncs);
5932 auto GUID = getValueInfoFromValueId(ValueID);
5933 VS->setOriginalName(GUID.second);
5934 TheIndex.addGlobalValueSummary(GUID.first, std::move(VS));
5935 break;
5936 }
58855937 // FS_COMBINED: [valueid, modid, flags, instcount, fflags, numrefs,
58865938 // numrefs x valueid, n x (valueid)]
58875939 // FS_COMBINED_PROFILE: [valueid, modid, flags, instcount, fflags, numrefs,
60486100 case bitc::FS_TYPE_ID:
60496101 parseTypeIdSummaryRecord(Record, Strtab, TheIndex);
60506102 break;
6103
6104 case bitc::FS_TYPE_ID_METADATA:
6105 parseTypeIdCompatibleVtableSummaryRecord(Record);
6106 break;
60516107 }
60526108 }
60536109 llvm_unreachable("Exit infinite loop");
213213 const Function &F);
214214 void writeModuleLevelReferences(const GlobalVariable &V,
215215 SmallVector &NameVals,
216 unsigned FSModRefsAbbrev);
216 unsigned FSModRefsAbbrev,
217 unsigned FSModVTableRefsAbbrev);
217218
218219 void assignValueId(GlobalValue::GUID ValGUID) {
219220 GUIDToValueIdMap[ValGUID] = ++GlobalValueId;
36043605 W.second);
36053606 }
36063607
3608 static void writeTypeIdCompatibleVtableSummaryRecord(
3609 SmallVector &NameVals, StringTableBuilder &StrtabBuilder,
3610 const std::string &Id, const TypeIdCompatibleVtableInfo &Summary,
3611 ValueEnumerator &VE) {
3612 NameVals.push_back(StrtabBuilder.add(Id));
3613 NameVals.push_back(Id.size());
3614
3615 for (auto &P : Summary) {
3616 NameVals.push_back(P.AddressPointOffset);
3617 NameVals.push_back(VE.getValueID(P.VTableVI.getValue()));
3618 }
3619 }
3620
36073621 // Helper to emit a single function summary record.
36083622 void ModuleBitcodeWriterBase::writePerModuleFunctionSummaryRecord(
36093623 SmallVector &NameVals, GlobalValueSummary *Summary,
36483662 // and emit them in a summary record.
36493663 void ModuleBitcodeWriterBase::writeModuleLevelReferences(
36503664 const GlobalVariable &V, SmallVector &NameVals,
3651 unsigned FSModRefsAbbrev) {
3665 unsigned FSModRefsAbbrev, unsigned FSModVTableRefsAbbrev) {
36523666 auto VI = Index->getValueInfo(V.getGUID());
36533667 if (!VI || VI.getSummaryList().empty()) {
36543668 // Only declarations should not have a summary (a declaration might however
36623676 NameVals.push_back(getEncodedGVSummaryFlags(VS->flags()));
36633677 NameVals.push_back(getEncodedGVarFlags(VS->varflags()));
36643678
3679 auto VTableFuncs = VS->vTableFuncs();
3680 if (!VTableFuncs.empty())
3681 NameVals.push_back(VS->refs().size());
3682
36653683 unsigned SizeBeforeRefs = NameVals.size();
36663684 for (auto &RI : VS->refs())
36673685 NameVals.push_back(VE.getValueID(RI.getValue()));
36693687 // been initialized from a DenseSet.
36703688 llvm::sort(NameVals.begin() + SizeBeforeRefs, NameVals.end());
36713689
3672 Stream.EmitRecord(bitc::FS_PERMODULE_GLOBALVAR_INIT_REFS, NameVals,
3673 FSModRefsAbbrev);
3690 if (!VTableFuncs.empty()) {
3691 // VTableFuncs pairs should already be sorted by offset.
3692 for (auto &P : VTableFuncs) {
3693 NameVals.push_back(VE.getValueID(P.FuncVI.getValue()));
3694 NameVals.push_back(P.VTableOffset);
3695 }
3696 }
3697
3698 if (VTableFuncs.empty())
3699 Stream.EmitRecord(bitc::FS_PERMODULE_GLOBALVAR_INIT_REFS, NameVals,
3700 FSModRefsAbbrev);
3701 else
3702 Stream.EmitRecord(bitc::FS_PERMODULE_VTABLE_GLOBALVAR_INIT_REFS, NameVals,
3703 FSModVTableRefsAbbrev);
36743704 NameVals.clear();
36753705 }
36763706
37513781 Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));
37523782 unsigned FSModRefsAbbrev = Stream.EmitAbbrev(std::move(Abbv));
37533783
3784 // Abbrev for FS_PERMODULE_VTABLE_GLOBALVAR_INIT_REFS.
3785 Abbv = std::make_shared();
3786 Abbv->Add(BitCodeAbbrevOp(bitc::FS_PERMODULE_VTABLE_GLOBALVAR_INIT_REFS));
3787 Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // valueid
3788 Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // flags
3789 Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 4)); // numrefs
3790 // numrefs x valueid, n x (valueid , offset)
3791 Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
3792 Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));
3793 unsigned FSModVTableRefsAbbrev = Stream.EmitAbbrev(std::move(Abbv));
3794
37543795 // Abbrev for FS_ALIAS.
37553796 Abbv = std::make_shared();
37563797 Abbv->Add(BitCodeAbbrevOp(bitc::FS_ALIAS));
37583799 Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // flags
37593800 Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // valueid
37603801 unsigned FSAliasAbbrev = Stream.EmitAbbrev(std::move(Abbv));
3802
3803 // Abbrev for FS_TYPE_ID_METADATA
3804 Abbv = std::make_shared();
3805 Abbv->Add(BitCodeAbbrevOp(bitc::FS_TYPE_ID_METADATA));
3806 Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // typeid strtab index
3807 Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // typeid length
3808 // n x (valueid , offset)
3809 Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
3810 Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));
3811 unsigned TypeIdCompatibleVtableAbbrev = Stream.EmitAbbrev(std::move(Abbv));
37613812
37623813 SmallVector NameVals;
37633814 // Iterate over the list of functions instead of the Index to
37833834 // Capture references from GlobalVariable initializers, which are outside
37843835 // of a function scope.
37853836 for (const GlobalVariable &G : M.globals())
3786 writeModuleLevelReferences(G, NameVals, FSModRefsAbbrev);
3837 writeModuleLevelReferences(G, NameVals, FSModRefsAbbrev,
3838 FSModVTableRefsAbbrev);
37873839
37883840 for (const GlobalAlias &A : M.aliases()) {
37893841 auto *Aliasee = A.getBaseObject();
37993851 NameVals.push_back(AliaseeId);
38003852 Stream.EmitRecord(bitc::FS_ALIAS, NameVals, FSAliasAbbrev);
38013853 NameVals.clear();
3854 }
3855
3856 if (!Index->typeIdCompatibleVtableMap().empty()) {
3857 for (auto &S : Index->typeIdCompatibleVtableMap()) {
3858 writeTypeIdCompatibleVtableSummaryRecord(NameVals, StrtabBuilder, S.first,
3859 S.second, VE);
3860 Stream.EmitRecord(bitc::FS_TYPE_ID_METADATA, NameVals,
3861 TypeIdCompatibleVtableAbbrev);
3862 NameVals.clear();
3863 }
38023864 }
38033865
38043866 Stream.ExitBlock();
10361036 TidIter != TheIndex->typeIds().end(); TidIter++)
10371037 CreateTypeIdSlot(TidIter->second.first);
10381038
1039 for (auto &TId : TheIndex->typeIdCompatibleVtableMap())
1040 CreateGUIDSlot(GlobalValue::getGUID(TId.first));
1041
10391042 ST_DEBUG("end processIndex!\n");
10401043 }
10411044
24092412 void printGlobalVarSummary(const GlobalVarSummary *GS);
24102413 void printFunctionSummary(const FunctionSummary *FS);
24112414 void printTypeIdSummary(const TypeIdSummary &TIS);
2415 void printTypeIdCompatibleVtableSummary(const TypeIdCompatibleVtableInfo &TI);
24122416 void printTypeTestResolution(const TypeTestResolution &TTRes);
24132417 void printArgs(const std::vector &Args);
24142418 void printWPDRes(const WholeProgramDevirtResolution &WPDRes);
27112715 printTypeIdSummary(TidIter->second.second);
27122716 Out << ") ; guid = " << TidIter->first << "\n";
27132717 }
2718
2719 // Print the TypeIdCompatibleVtableMap entries.
2720 for (auto &TId : TheIndex->typeIdCompatibleVtableMap()) {
2721 auto GUID = GlobalValue::getGUID(TId.first);
2722 Out << "^" << Machine.getGUIDSlot(GUID)
2723 << " = typeidCompatibleVTable: (name: \"" << TId.first << "\"";
2724 printTypeIdCompatibleVtableSummary(TId.second);
2725 Out << ") ; guid = " << GUID << "\n";
2726 }
27142727 }
27152728
27162729 static const char *
27882801 printWPDRes(WPDRes.second);
27892802 Out << ")";
27902803 }
2804 Out << ")";
2805 }
2806 Out << ")";
2807 }
2808
2809 void AssemblyWriter::printTypeIdCompatibleVtableSummary(
2810 const TypeIdCompatibleVtableInfo &TI) {
2811 Out << ", summary: (";
2812 FieldSeparator FS;
2813 for (auto &P : TI) {
2814 Out << FS;
2815 Out << "(offset: " << P.AddressPointOffset << ", ";
2816 Out << "^" << Machine.getGUIDSlot(P.VTableVI.getGUID());
27912817 Out << ")";
27922818 }
27932819 Out << ")";
28622888
28632889 void AssemblyWriter::printGlobalVarSummary(const GlobalVarSummary *GS) {
28642890 Out << ", varFlags: (readonly: " << GS->VarFlags.ReadOnly << ")";
2891
2892 auto VTableFuncs = GS->vTableFuncs();
2893 if (!VTableFuncs.empty()) {
2894 Out << ", vTableFuncs: (";
2895 FieldSeparator FS;
2896 for (auto &P : VTableFuncs) {
2897 Out << FS;
2898 Out << "(virtFunc: ^" << Machine.getGUIDSlot(P.FuncVI.getGUID())
2899 << ", offset: " << P.VTableOffset;
2900 Out << ")";
2901 }
2902 Out << ")";
2903 }
28652904 }
28662905
28672906 static std::string getLinkageName(GlobalValue::LinkageTypes LT) {
416416 }
417417 }
418418
419 // Returns whether this module needs to be split because splitting is
420 // enabled and it uses type metadata.
421 bool requiresSplit(Module &M) {
422 // First check if the LTO Unit splitting has been enabled.
419 // Check if the LTO Unit splitting has been enabled.
420 bool enableSplitLTOUnit(Module &M) {
423421 bool EnableSplitLTOUnit = false;
424422 if (auto *MD = mdconst::extract_or_null(
425423 M.getModuleFlag("EnableSplitLTOUnit")))
426424 EnableSplitLTOUnit = MD->getZExtValue();
427 if (!EnableSplitLTOUnit)
428 return false;
429
430 // Module only needs to be split if it contains type metadata.
425 return EnableSplitLTOUnit;
426 }
427
428 // Returns whether this module needs to be split because it uses type metadata.
429 bool hasTypeMetadata(Module &M) {
431430 for (auto &GO : M.global_objects()) {
432431 if (GO.hasMetadata(LLVMContext::MD_type))
433432 return true;
434433 }
435
436434 return false;
437435 }
438436
439437 void writeThinLTOBitcode(raw_ostream &OS, raw_ostream *ThinLinkOS,
440438 function_ref AARGetter,
441439 Module &M, const ModuleSummaryIndex *Index) {
442 // Split module if splitting is enabled and it contains any type metadata.
443 if (requiresSplit(M))
444 return splitAndWriteThinLTOBitcode(OS, ThinLinkOS, AARGetter, M);
445
446 // Otherwise we can just write it out as a regular module.
440 std::unique_ptr NewIndex = nullptr;
441 // See if this module has any type metadata. If so, we try to split it
442 // or at least promote type ids to enable WPD.
443 if (hasTypeMetadata(M)) {
444 if (enableSplitLTOUnit(M))
445 return splitAndWriteThinLTOBitcode(OS, ThinLinkOS, AARGetter, M);
446 // Promote type ids as needed for index-based WPD.
447 std::string ModuleId = getUniqueModuleId(&M);
448 if (!ModuleId.empty()) {
449 promoteTypeIds(M, ModuleId);
450 // Need to rebuild the index so that it contains type metadata
451 // for the newly promoted type ids.
452 // FIXME: Probably should not bother building the index at all
453 // in the caller of writeThinLTOBitcode (which does so via the
454 // ModuleSummaryIndexAnalysis pass), since we have to rebuild it
455 // anyway whenever there is type metadata (here or in
456 // splitAndWriteThinLTOBitcode). Just always build it once via the
457 // buildModuleSummaryIndex when Module(s) are ready.
458 ProfileSummaryInfo PSI(M);
459 NewIndex = llvm::make_unique(
460 buildModuleSummaryIndex(M, nullptr, &PSI));
461 Index = NewIndex.get();
462 }
463 }
464
465 // Write it out as an unsplit ThinLTO module.
447466
448467 // Save the module hash produced for the full bitcode, which will
449468 // be used in the backends, and use that in the minimized bitcode
0 ; 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, canAutoHide: 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, canAutoHide: 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 = typeidCompatibleVTable: (name: "_ZTS1A", summary: ((offset: 16, ^2), (offset: 16, ^4))) ; guid = 7004155349499253778
36 ^7 = typeidCompatibleVTable: (name: "_ZTS1B", summary: ((offset: 16, ^2))) ; guid = 6203814149063363976
37 ^8 = typeidCompatibleVTable: (name: "_ZTS1C", summary: ((offset: 16, ^4))) ; guid = 1884921850105019584
0 ; 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=typeidCompatibleVTable
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=typeidCompatibleVTable
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: typeidCompatibleVTable: (name: "_ZTS1A", summary: ((offset: 16, [[B]]), (offset: 16, [[C]])))
30 ; NOENABLESPLITFLAG-DAG: typeidCompatibleVTable: (name: "_ZTS1B", summary: ((offset: 16, [[B]])))
31 ; NOENABLESPLITFLAG-DAG: typeidCompatibleVTable: (name: "_ZTS1C", summary: ((offset: 16, [[C]])))
32 ; Type Id on _ZTV1D should have been promoted
33 ; NOENABLESPLITFLAG-DAG: typeidCompatibleVTable: (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)
319320 STRINGIFY_CODE(FS, COMBINED)
320321 STRINGIFY_CODE(FS, COMBINED_PROFILE)
321322 STRINGIFY_CODE(FS, COMBINED_GLOBALVAR_INIT_REFS)
333334 STRINGIFY_CODE(FS, CFI_FUNCTION_DEFS)
334335 STRINGIFY_CODE(FS, CFI_FUNCTION_DECLS)
335336 STRINGIFY_CODE(FS, TYPE_ID)
337 STRINGIFY_CODE(FS, TYPE_ID_METADATA)
336338 }
337339 case bitc::METADATA_ATTACHMENT_ID:
338340 switch(CodeID) {