llvm.org GIT mirror llvm / 70c3a1b
[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 index-based WPD will be sent as a follow-on. 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@351453 91177308-0d34-0410-b5e6-96231b3b80d8 Teresa Johnson 1 year, 9 months ago
14 changed file(s) with 723 addition(s) and 28 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).
266267 // TYPE_ID: [typeid, kind, bitwidth, align, size, bitmask, inlinebits,
267268 // n x (typeid, kind, name, numrba,
268269 // numrba x (numarg, numarg x arg, kind, info, byte, bit))]
269270 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,
270285 };
271286
272287 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
668674 /// Global variable summary information to aid decisions and
669675 /// implementation of importing.
670676 ///
672678 /// modified during the program run or not. This affects ThinLTO
673679 /// internalization
674680 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
675686 public:
676687 struct GVarFlags {
677688 GVarFlags(bool ReadOnly = false) : ReadOnly(ReadOnly) {}
692703 GVarFlags varflags() const { return VarFlags; }
693704 void setReadOnly(bool RO) { VarFlags.ReadOnly = RO; }
694705 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 }
695717 };
696718
697719 struct TypeTestResolution {
790812 using TypeIdSummaryMapTy =
791813 std::multimap>;
792814
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
793823 /// Class to hold module path string table and global value map,
794824 /// and encapsulate methods for operating on them.
795825 class ModuleSummaryIndex {
802832 ModulePathStringTableTy ModulePathStringTable;
803833
804834 /// Mapping from type identifier GUIDs to type identifier and its summary
805 /// information.
835 /// information. Produced by thin link.
806836 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;
807842
808843 /// Mapping from original ID to GUID. If original ID can map to multiple
809844 /// GUIDs, it will be mapped to 0.
11621197 return nullptr;
11631198 }
11641199
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
11651221 /// Collect for the given module the list of functions it defines
11661222 /// (GUID -> Summary).
11671223 void collectDefinedFunctionsForModule(StringRef ModulePath,
405405 Index.addGlobalValueSummary(F, std::move(FuncSummary));
406406 }
407407
408 static void
409 computeVariableSummary(ModuleSummaryIndex &Index, const GlobalVariable &V,
410 DenseSet &CantBePromoted) {
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) {
411500 SetVector RefEdges;
412501 SmallPtrSet Visited;
413502 bool HasBlockAddress = findRefEdges(Index, &V, RefEdges, Visited);
414503 bool NonRenamableLocal = isNonRenamableLocal(V);
415504 GlobalValueSummary::GVFlags Flags(V.getLinkage(), NonRenamableLocal,
416505 /* 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 }
417521
418522 // Don't mark variables we won't be able to internalize as read-only.
419523 GlobalVarSummary::GVarFlags VarFlags(
425529 CantBePromoted.insert(V.getGUID());
426530 if (HasBlockAddress)
427531 GVarSummary->setNotEligibleToImport();
532 if (!VTableFuncs.empty())
533 GVarSummary->setVTableFuncs(VTableFuncs);
428534 Index.addGlobalValueSummary(V, std::move(GVarSummary));
429535 }
430536
567673
568674 // Compute summaries for all variables defined in module, and save in the
569675 // index.
676 SmallVector Types;
570677 for (const GlobalVariable &G : M.globals()) {
571678 if (G.isDeclaration())
572679 continue;
573 computeVariableSummary(Index, G, CantBePromoted);
680 computeVariableSummary(Index, G, CantBePromoted, M, Types);
574681 }
575682
576683 // 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);
751753 KEYWORD(aliasee);
752754 KEYWORD(refs);
753755 KEYWORD(typeIdInfo);
760762 KEYWORD(offset);
761763 KEYWORD(args);
762764 KEYWORD(typeid);
765 KEYWORD(typeidMetadata);
763766 KEYWORD(summary);
764767 KEYWORD(typeTestRes);
765768 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);
823826 break;
824827 default:
825828 return Error(Lex.getLoc(), "unexpected summary kind");
72567259 return false;
72577260 }
72587261
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
72597346 /// TypeTestResolution
72607347 /// ::= 'typeTestRes' ':' '(' 'kind' ':'
72617348 /// ( 'unsat' | 'byteArray' | 'inline' | 'single' | 'allOnes' ) ','
77637850 /*Live=*/false, /*IsLocal=*/false);
77647851 GlobalVarSummary::GVarFlags GVarFlags(/*ReadOnly*/ false);
77657852 std::vector Refs;
7853 VTableFuncList VTableFuncs;
77667854 if (ParseToken(lltok::colon, "expected ':' here") ||
77677855 ParseToken(lltok::lparen, "expected '(' here") ||
77687856 ParseModuleReference(ModulePath) ||
77717859 ParseGVarFlags(GVarFlags))
77727860 return true;
77737861
7774 // Parse optional refs field
7775 if (EatIfPresent(lltok::comma)) {
7776 if (ParseOptionalRefs(Refs))
7777 return true;
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 }
77787876 }
77797877
77807878 if (ParseToken(lltok::rparen, "expected ')' here"))
77847882 llvm::make_unique(GVFlags, GVarFlags, std::move(Refs));
77857883
77867884 GS->setModulePath(ModulePath);
7885 GS->setVTableFuncs(std::move(VTableFuncs));
77877886
77887887 AddGlobalValueToIndex(Name, GUID, (GlobalValue::LinkageTypes)GVFlags.Linkage,
77897888 ID, std::move(GS));
80018100 return false;
80028101 }
80038102
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
80048164 /// OptionalRefs
80058165 /// := 'refs' ':' '(' GVReference [',' GVReference]* ')'
80068166 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);
371372 bool ParseOptionalRefs(std::vector &Refs);
372373 bool ParseTypeIdEntry(unsigned ID);
373374 bool ParseTypeIdSummary(TypeIdSummary &TIS);
375 bool ParseTypeIdMetadataEntry(unsigned ID);
374376 bool ParseTypeTestResolution(TypeTestResolution &TTRes);
375377 bool ParseOptionalWpdResolutions(
376378 std::map &WPDResMap);
378378 kw_critical,
379379 kw_relbf,
380380 kw_variable,
381 kw_vTableFuncs,
382 kw_virtFunc,
381383 kw_aliasee,
382384 kw_refs,
383385 kw_typeIdInfo,
390392 kw_offset,
391393 kw_args,
392394 kw_typeid,
395 kw_typeidMetadata,
393396 kw_summary,
394397 kw_typeTestRes,
395398 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);
750753
751754 std::pair
752755 getValueInfoFromValueId(unsigned ValueId);
52235226 parseWholeProgramDevirtResolution(Record, Strtab, Slot, TypeId);
52245227 }
52255228
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
52265247 static void setImmutableRefs(std::vector &Refs, unsigned Count) {
52275248 // Read-only refs are in the end of the refs list.
52285249 for (unsigned RefNo = Refs.size() - Count; RefNo < Refs.size(); ++RefNo)
54405461 TheIndex.addGlobalValueSummary(GUID.first, std::move(FS));
54415462 break;
54425463 }
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 }
54435492 // FS_COMBINED: [valueid, modid, flags, instcount, fflags, numrefs,
54445493 // numrefs x valueid, n x (valueid)]
54455494 // FS_COMBINED_PROFILE: [valueid, modid, flags, instcount, fflags, numrefs,
56095658 case bitc::FS_TYPE_ID:
56105659 parseTypeIdSummaryRecord(Record, Strtab, TheIndex);
56115660 break;
5661
5662 case bitc::FS_TYPE_ID_METADATA:
5663 parseTypeIdMetadataSummaryRecord(Record);
5664 break;
56125665 }
56135666 }
56145667 llvm_unreachable("Exit infinite loop");
214214 const Function &F);
215215 void writeModuleLevelReferences(const GlobalVariable &V,
216216 SmallVector &NameVals,
217 unsigned FSModRefsAbbrev);
217 unsigned FSModRefsAbbrev,
218 unsigned FSModVTableRefsAbbrev);
218219
219220 void assignValueId(GlobalValue::GUID ValGUID) {
220221 GUIDToValueIdMap[ValGUID] = ++GlobalValueId;
35273528 W.second);
35283529 }
35293530
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
35303543 // Helper to emit a single function summary record.
35313544 void ModuleBitcodeWriterBase::writePerModuleFunctionSummaryRecord(
35323545 SmallVector &NameVals, GlobalValueSummary *Summary,
35713584 // and emit them in a summary record.
35723585 void ModuleBitcodeWriterBase::writeModuleLevelReferences(
35733586 const GlobalVariable &V, SmallVector &NameVals,
3574 unsigned FSModRefsAbbrev) {
3587 unsigned FSModRefsAbbrev, unsigned FSModVTableRefsAbbrev) {
35753588 auto VI = Index->getValueInfo(V.getGUID());
35763589 if (!VI || VI.getSummaryList().empty()) {
35773590 // Only declarations should not have a summary (a declaration might however
35853598 NameVals.push_back(getEncodedGVSummaryFlags(VS->flags()));
35863599 NameVals.push_back(getEncodedGVarFlags(VS->varflags()));
35873600
3601 auto VTableFuncs = VS->vTableFuncs();
3602 if (!VTableFuncs.empty())
3603 NameVals.push_back(VS->refs().size());
3604
35883605 unsigned SizeBeforeRefs = NameVals.size();
35893606 for (auto &RI : VS->refs())
35903607 NameVals.push_back(VE.getValueID(RI.getValue()));
35923609 // been initialized from a DenseSet.
35933610 llvm::sort(NameVals.begin() + SizeBeforeRefs, NameVals.end());
35943611
3595 Stream.EmitRecord(bitc::FS_PERMODULE_GLOBALVAR_INIT_REFS, NameVals,
3596 FSModRefsAbbrev);
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);
35973626 NameVals.clear();
35983627 }
35993628
36743703 Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));
36753704 unsigned FSModRefsAbbrev = Stream.EmitAbbrev(std::move(Abbv));
36763705
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
36773717 // Abbrev for FS_ALIAS.
36783718 Abbv = std::make_shared();
36793719 Abbv->Add(BitCodeAbbrevOp(bitc::FS_ALIAS));
37063746 // Capture references from GlobalVariable initializers, which are outside
37073747 // of a function scope.
37083748 for (const GlobalVariable &G : M.globals())
3709 writeModuleLevelReferences(G, NameVals, FSModRefsAbbrev);
3749 writeModuleLevelReferences(G, NameVals, FSModRefsAbbrev,
3750 FSModVTableRefsAbbrev);
37103751
37113752 for (const GlobalAlias &A : M.aliases()) {
37123753 auto *Aliasee = A.getBaseObject();
37223763 NameVals.push_back(AliaseeId);
37233764 Stream.EmitRecord(bitc::FS_ALIAS, NameVals, FSAliasAbbrev);
37243765 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 }
37253776 }
37263777
37273778 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
10401043 ST_DEBUG("end processIndex!\n");
10411044 }
10421045
23922395 void printGlobalVarSummary(const GlobalVarSummary *GS);
23932396 void printFunctionSummary(const FunctionSummary *FS);
23942397 void printTypeIdSummary(const TypeIdSummary &TIS);
2398 void printTypeIdMetadataSummary(const TypeIdGVInfo &TI);
23952399 void printTypeTestResolution(const TypeTestResolution &TTRes);
23962400 void printArgs(const std::vector &Args);
23972401 void printWPDRes(const WholeProgramDevirtResolution &WPDRes);
26942698 printTypeIdSummary(TidIter->second.second);
26952699 Out << ") ; guid = " << TidIter->first << "\n";
26962700 }
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 }
26972710 }
26982711
26992712 static const char *
27712784 printWPDRes(WPDRes.second);
27722785 Out << ")";
27732786 }
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());
27742799 Out << ")";
27752800 }
27762801 Out << ")";
28452870
28462871 void AssemblyWriter::printGlobalVarSummary(const GlobalVarSummary *GS) {
28472872 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 }
28482886 }
28492887
28502888 static std::string getLinkageName(GlobalValue::LinkageTypes LT) {
417417 }
418418 }
419419
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.
420 // Check if the LTO Unit splitting has been enabled.
421 bool enableSplitLTOUnit(Module &M) {
424422 bool EnableSplitLTOUnit = false;
425423 if (auto *MD = mdconst::extract_or_null(
426424 M.getModuleFlag("EnableSplitLTOUnit")))
427425 EnableSplitLTOUnit = MD->getZExtValue();
428 if (!EnableSplitLTOUnit)
429 return false;
430
431 // Module only needs to be split if it contains type metadata.
426 return EnableSplitLTOUnit;
427 }
428
429 // Returns whether this module needs to be split because it uses type metadata.
430 bool hasTypeMetadata(Module &M) {
432431 for (auto &GO : M.global_objects()) {
433432 if (GO.hasMetadata(LLVMContext::MD_type))
434433 return true;
435434 }
436
437435 return false;
438436 }
439437
440438 void writeThinLTOBitcode(raw_ostream &OS, raw_ostream *ThinLinkOS,
441439 function_ref AARGetter,
442440 Module &M, const ModuleSummaryIndex *Index) {
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.
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.
448469
449470 // Save the module hash produced for the full bitcode, which will
450471 // 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), 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 ; 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)
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) {