forked from OSchip/llvm-project
[ThinLTO] Efficiency fix for writing type id records in per-module indexes
Summary: In D49565/r337503, the type id record writing was fixed so that only referenced type ids were emitted into each per-module index for ThinLTO distributed builds. However, this still left an efficiency issue: each per-module index checked all type ids for membership in the referenced set, yielding O(M*N) performance (M indexes and N type ids). Change the TypeIdMap in the summary to be indexed by GUID, to facilitate correlating with type identifier GUIDs referenced in the function summary TypeIdInfo structures. This allowed simplifying other places where a map from type id GUID to type id map entry was previously being used to aid this correlation. Also fix AsmWriter code to handle the rare case of type id GUID collision. For a large internal application, this reduced the thin link time by almost 15%. Reviewers: pcc, vitalybuka Subscribers: mehdi_amini, inglorion, steven_wu, dexonsmith, llvm-commits Differential Revision: https://reviews.llvm.org/D51330 llvm-svn: 343021
This commit is contained in:
parent
d2aab83fa6
commit
7fb39dfa7c
|
@ -23,6 +23,7 @@
|
|||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ADT/TinyPtrVector.h"
|
||||
#include "llvm/IR/GlobalValue.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
#include "llvm/Support/Allocator.h"
|
||||
|
@ -753,6 +754,11 @@ using ModulePathStringTableTy = StringMap<std::pair<uint64_t, ModuleHash>>;
|
|||
/// a particular module, and provide efficient access to their summary.
|
||||
using GVSummaryMapTy = DenseMap<GlobalValue::GUID, GlobalValueSummary *>;
|
||||
|
||||
/// Map of a type GUID to type id string and summary (multimap used
|
||||
/// in case of GUID conflicts).
|
||||
using TypeIdSummaryMapTy =
|
||||
std::multimap<GlobalValue::GUID, std::pair<std::string, TypeIdSummary>>;
|
||||
|
||||
/// Class to hold module path string table and global value map,
|
||||
/// and encapsulate methods for operating on them.
|
||||
class ModuleSummaryIndex {
|
||||
|
@ -764,9 +770,9 @@ private:
|
|||
/// Holds strings for combined index, mapping to the corresponding module ID.
|
||||
ModulePathStringTableTy ModulePathStringTable;
|
||||
|
||||
/// Mapping from type identifiers to summary information for that type
|
||||
/// identifier.
|
||||
std::map<std::string, TypeIdSummary> TypeIdMap;
|
||||
/// Mapping from type identifier GUIDs to type identifier and its summary
|
||||
/// information.
|
||||
TypeIdSummaryMapTy TypeIdMap;
|
||||
|
||||
/// Mapping from original ID to GUID. If original ID can map to multiple
|
||||
/// GUIDs, it will be mapped to 0.
|
||||
|
@ -1079,23 +1085,29 @@ public:
|
|||
return ModulePathStringTable.count(M.getModuleIdentifier());
|
||||
}
|
||||
|
||||
const std::map<std::string, TypeIdSummary> &typeIds() const {
|
||||
return TypeIdMap;
|
||||
}
|
||||
const TypeIdSummaryMapTy &typeIds() const { return TypeIdMap; }
|
||||
|
||||
/// This accessor should only be used when exporting because it can mutate the
|
||||
/// map.
|
||||
/// Return an existing or new TypeIdSummary entry for \p TypeId.
|
||||
/// This accessor can mutate the map and therefore should not be used in
|
||||
/// the ThinLTO backends.
|
||||
TypeIdSummary &getOrInsertTypeIdSummary(StringRef TypeId) {
|
||||
return TypeIdMap[TypeId];
|
||||
auto TidIter = TypeIdMap.equal_range(GlobalValue::getGUID(TypeId));
|
||||
for (auto It = TidIter.first; It != TidIter.second; ++It)
|
||||
if (It->second.first == TypeId)
|
||||
return It->second.second;
|
||||
auto It = TypeIdMap.insert(
|
||||
{GlobalValue::getGUID(TypeId), {TypeId, TypeIdSummary()}});
|
||||
return It->second.second;
|
||||
}
|
||||
|
||||
/// This returns either a pointer to the type id summary (if present in the
|
||||
/// summary map) or null (if not present). This may be used when importing.
|
||||
const TypeIdSummary *getTypeIdSummary(StringRef TypeId) const {
|
||||
auto I = TypeIdMap.find(TypeId);
|
||||
if (I == TypeIdMap.end())
|
||||
return nullptr;
|
||||
return &I->second;
|
||||
auto TidIter = TypeIdMap.equal_range(GlobalValue::getGUID(TypeId));
|
||||
for (auto It = TidIter.first; It != TidIter.second; ++It)
|
||||
if (It->second.first == TypeId)
|
||||
return &It->second.second;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// Collect for the given module the list of functions it defines
|
||||
|
|
|
@ -195,7 +195,6 @@ template <> struct MappingTraits<FunctionSummaryYaml> {
|
|||
} // End yaml namespace
|
||||
} // End llvm namespace
|
||||
|
||||
LLVM_YAML_IS_STRING_MAP(TypeIdSummary)
|
||||
LLVM_YAML_IS_SEQUENCE_VECTOR(FunctionSummaryYaml)
|
||||
|
||||
namespace llvm {
|
||||
|
@ -258,6 +257,18 @@ template <> struct CustomMappingTraits<GlobalValueSummaryMapTy> {
|
|||
}
|
||||
};
|
||||
|
||||
template <> struct CustomMappingTraits<TypeIdSummaryMapTy> {
|
||||
static void inputOne(IO &io, StringRef Key, TypeIdSummaryMapTy &V) {
|
||||
TypeIdSummary TId;
|
||||
io.mapRequired(Key.str().c_str(), TId);
|
||||
V.insert({GlobalValue::getGUID(Key), {Key, TId}});
|
||||
}
|
||||
static void output(IO &io, TypeIdSummaryMapTy &V) {
|
||||
for (auto TidIter = V.begin(); TidIter != V.end(); TidIter++)
|
||||
io.mapRequired(TidIter->second.first.c_str(), TidIter->second.second);
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct MappingTraits<ModuleSummaryIndex> {
|
||||
static void mapping(IO &io, ModuleSummaryIndex& index) {
|
||||
io.mapOptional("GlobalValueMap", index.GlobalValueMap);
|
||||
|
|
|
@ -3903,12 +3903,13 @@ void IndexBitcodeWriter::writeCombinedGlobalValueSummary() {
|
|||
NameVals.clear();
|
||||
}
|
||||
|
||||
if (!Index.typeIds().empty()) {
|
||||
for (auto &S : Index.typeIds()) {
|
||||
// Skip if not referenced in any GV summary within this index file.
|
||||
if (!ReferencedTypeIds.count(GlobalValue::getGUID(S.first)))
|
||||
continue;
|
||||
writeTypeIdSummaryRecord(NameVals, StrtabBuilder, S.first, S.second);
|
||||
// Walk the GUIDs that were referenced, and write the
|
||||
// corresponding type id records.
|
||||
for (auto &T : ReferencedTypeIds) {
|
||||
auto TidIter = Index.typeIds().equal_range(T);
|
||||
for (auto It = TidIter.first; It != TidIter.second; ++It) {
|
||||
writeTypeIdSummaryRecord(NameVals, StrtabBuilder, It->second.first,
|
||||
It->second.second);
|
||||
Stream.EmitRecord(bitc::FS_TYPE_ID, NameVals);
|
||||
NameVals.clear();
|
||||
}
|
||||
|
|
|
@ -705,6 +705,10 @@ private:
|
|||
DenseMap<GlobalValue::GUID, unsigned> GUIDMap;
|
||||
unsigned GUIDNext = 0;
|
||||
|
||||
/// TypeIdMap - The slot map for type ids used in the summary index.
|
||||
StringMap<unsigned> TypeIdMap;
|
||||
unsigned TypeIdNext = 0;
|
||||
|
||||
public:
|
||||
/// Construct from a module.
|
||||
///
|
||||
|
@ -736,6 +740,7 @@ public:
|
|||
int getAttributeGroupSlot(AttributeSet AS);
|
||||
int getModulePathSlot(StringRef Path);
|
||||
int getGUIDSlot(GlobalValue::GUID GUID);
|
||||
int getTypeIdSlot(StringRef Id);
|
||||
|
||||
/// If you'd like to deal with a function instead of just a module, use
|
||||
/// this method to get its data into the SlotTracker.
|
||||
|
@ -790,6 +795,7 @@ private:
|
|||
|
||||
inline void CreateModulePathSlot(StringRef Path);
|
||||
void CreateGUIDSlot(GlobalValue::GUID GUID);
|
||||
void CreateTypeIdSlot(StringRef Id);
|
||||
|
||||
/// Add all of the module level global variables (and their initializers)
|
||||
/// and function declarations, but not the contents of those functions.
|
||||
|
@ -1026,8 +1032,12 @@ void SlotTracker::processIndex() {
|
|||
for (auto &GlobalList : *TheIndex)
|
||||
CreateGUIDSlot(GlobalList.first);
|
||||
|
||||
for (auto &TId : TheIndex->typeIds())
|
||||
CreateGUIDSlot(GlobalValue::getGUID(TId.first));
|
||||
// Start numbering the TypeIds after the GUIDs.
|
||||
TypeIdNext = GUIDNext;
|
||||
|
||||
for (auto TidIter = TheIndex->typeIds().begin();
|
||||
TidIter != TheIndex->typeIds().end(); TidIter++)
|
||||
CreateTypeIdSlot(TidIter->second.first);
|
||||
|
||||
ST_DEBUG("end processIndex!\n");
|
||||
}
|
||||
|
@ -1133,6 +1143,15 @@ int SlotTracker::getGUIDSlot(GlobalValue::GUID GUID) {
|
|||
return I == GUIDMap.end() ? -1 : (int)I->second;
|
||||
}
|
||||
|
||||
int SlotTracker::getTypeIdSlot(StringRef Id) {
|
||||
// Check for uninitialized state and do lazy initialization.
|
||||
initializeIndexIfNeeded();
|
||||
|
||||
// Find the TypeId string in the map
|
||||
auto I = TypeIdMap.find(Id);
|
||||
return I == TypeIdMap.end() ? -1 : (int)I->second;
|
||||
}
|
||||
|
||||
/// CreateModuleSlot - Insert the specified GlobalValue* into the slot table.
|
||||
void SlotTracker::CreateModuleSlot(const GlobalValue *V) {
|
||||
assert(V && "Can't insert a null Value into SlotTracker!");
|
||||
|
@ -1203,6 +1222,11 @@ void SlotTracker::CreateGUIDSlot(GlobalValue::GUID GUID) {
|
|||
GUIDMap[GUID] = GUIDNext++;
|
||||
}
|
||||
|
||||
/// Create a new slot for the specified Id
|
||||
void SlotTracker::CreateTypeIdSlot(StringRef Id) {
|
||||
TypeIdMap[Id] = TypeIdNext++;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// AsmWriter Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -2656,12 +2680,12 @@ void AssemblyWriter::printModuleSummaryIndex() {
|
|||
}
|
||||
|
||||
// Print the TypeIdMap entries.
|
||||
for (auto &TId : TheIndex->typeIds()) {
|
||||
auto GUID = GlobalValue::getGUID(TId.first);
|
||||
Out << "^" << Machine.getGUIDSlot(GUID) << " = typeid: (name: \""
|
||||
<< TId.first << "\"";
|
||||
printTypeIdSummary(TId.second);
|
||||
Out << ") ; guid = " << GUID << "\n";
|
||||
for (auto TidIter = TheIndex->typeIds().begin();
|
||||
TidIter != TheIndex->typeIds().end(); TidIter++) {
|
||||
Out << "^" << Machine.getTypeIdSlot(TidIter->second.first)
|
||||
<< " = typeid: (name: \"" << TidIter->second.first << "\"";
|
||||
printTypeIdSummary(TidIter->second.second);
|
||||
Out << ") ; guid = " << TidIter->first << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2894,12 +2918,19 @@ void AssemblyWriter::printTypeIdInfo(
|
|||
Out << "typeTests: (";
|
||||
FieldSeparator FS;
|
||||
for (auto &GUID : TIDInfo.TypeTests) {
|
||||
Out << FS;
|
||||
auto Slot = Machine.getGUIDSlot(GUID);
|
||||
if (Slot != -1)
|
||||
Out << "^" << Slot;
|
||||
else
|
||||
auto TidIter = TheIndex->typeIds().equal_range(GUID);
|
||||
if (TidIter.first == TidIter.second) {
|
||||
Out << FS;
|
||||
Out << GUID;
|
||||
continue;
|
||||
}
|
||||
// Print all type id that correspond to this GUID.
|
||||
for (auto It = TidIter.first; It != TidIter.second; ++It) {
|
||||
Out << FS;
|
||||
auto Slot = Machine.getTypeIdSlot(It->second.first);
|
||||
assert(Slot != -1);
|
||||
Out << "^" << Slot;
|
||||
}
|
||||
}
|
||||
Out << ")";
|
||||
}
|
||||
|
@ -2925,14 +2956,25 @@ void AssemblyWriter::printTypeIdInfo(
|
|||
}
|
||||
|
||||
void AssemblyWriter::printVFuncId(const FunctionSummary::VFuncId VFId) {
|
||||
Out << "vFuncId: (";
|
||||
auto Slot = Machine.getGUIDSlot(VFId.GUID);
|
||||
if (Slot != -1)
|
||||
Out << "^" << Slot;
|
||||
else
|
||||
auto TidIter = TheIndex->typeIds().equal_range(VFId.GUID);
|
||||
if (TidIter.first == TidIter.second) {
|
||||
Out << "vFuncId: (";
|
||||
Out << "guid: " << VFId.GUID;
|
||||
Out << ", offset: " << VFId.Offset;
|
||||
Out << ")";
|
||||
Out << ", offset: " << VFId.Offset;
|
||||
Out << ")";
|
||||
return;
|
||||
}
|
||||
// Print all type id that correspond to this GUID.
|
||||
FieldSeparator FS;
|
||||
for (auto It = TidIter.first; It != TidIter.second; ++It) {
|
||||
Out << FS;
|
||||
Out << "vFuncId: (";
|
||||
auto Slot = Machine.getTypeIdSlot(It->second.first);
|
||||
assert(Slot != -1);
|
||||
Out << "^" << Slot;
|
||||
Out << ", offset: " << VFId.Offset;
|
||||
Out << ")";
|
||||
}
|
||||
}
|
||||
|
||||
void AssemblyWriter::printNonConstVCalls(
|
||||
|
|
|
@ -56,12 +56,6 @@ static cl::opt<bool>
|
|||
DumpThinCGSCCs("dump-thin-cg-sccs", cl::init(false), cl::Hidden,
|
||||
cl::desc("Dump the SCCs in the ThinLTO index's callgraph"));
|
||||
|
||||
// The values are (type identifier, summary) pairs.
|
||||
typedef DenseMap<
|
||||
GlobalValue::GUID,
|
||||
TinyPtrVector<const std::pair<const std::string, TypeIdSummary> *>>
|
||||
TypeIdSummariesByGuidTy;
|
||||
|
||||
// Returns a unique hash for the Module considering the current list of
|
||||
// export/import and other global analysis results.
|
||||
// The hash is produced in \p Key.
|
||||
|
@ -71,7 +65,6 @@ static void computeCacheKey(
|
|||
const FunctionImporter::ExportSetTy &ExportList,
|
||||
const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes> &ResolvedODR,
|
||||
const GVSummaryMapTy &DefinedGlobals,
|
||||
const TypeIdSummariesByGuidTy &TypeIdSummariesByGuid,
|
||||
const std::set<GlobalValue::GUID> &CfiFunctionDefs,
|
||||
const std::set<GlobalValue::GUID> &CfiFunctionDecls) {
|
||||
// Compute the unique hash for this entry.
|
||||
|
@ -255,10 +248,9 @@ static void computeCacheKey(
|
|||
|
||||
// Include the hash for all type identifiers used by this module.
|
||||
for (GlobalValue::GUID TId : UsedTypeIds) {
|
||||
auto SummariesI = TypeIdSummariesByGuid.find(TId);
|
||||
if (SummariesI != TypeIdSummariesByGuid.end())
|
||||
for (auto *Summary : SummariesI->second)
|
||||
AddTypeIdSummary(Summary->first, Summary->second);
|
||||
auto TidIter = Index.typeIds().equal_range(TId);
|
||||
for (auto It = TidIter.first; It != TidIter.second; ++It)
|
||||
AddTypeIdSummary(It->second.first, It->second.second);
|
||||
}
|
||||
|
||||
AddUnsigned(UsedCfiDefs.size());
|
||||
|
@ -917,7 +909,6 @@ class InProcessThinBackend : public ThinBackendProc {
|
|||
ThreadPool BackendThreadPool;
|
||||
AddStreamFn AddStream;
|
||||
NativeObjectCache Cache;
|
||||
TypeIdSummariesByGuidTy TypeIdSummariesByGuid;
|
||||
std::set<GlobalValue::GUID> CfiFunctionDefs;
|
||||
std::set<GlobalValue::GUID> CfiFunctionDecls;
|
||||
|
||||
|
@ -933,12 +924,6 @@ public:
|
|||
: ThinBackendProc(Conf, CombinedIndex, ModuleToDefinedGVSummaries),
|
||||
BackendThreadPool(ThinLTOParallelismLevel),
|
||||
AddStream(std::move(AddStream)), Cache(std::move(Cache)) {
|
||||
// Create a mapping from type identifier GUIDs to type identifier summaries.
|
||||
// This allows backends to use the type identifier GUIDs stored in the
|
||||
// function summaries to determine which type identifier summaries affect
|
||||
// each function without needing to compute GUIDs in each backend.
|
||||
for (auto &TId : CombinedIndex.typeIds())
|
||||
TypeIdSummariesByGuid[GlobalValue::getGUID(TId.first)].push_back(&TId);
|
||||
for (auto &Name : CombinedIndex.cfiFunctionDefs())
|
||||
CfiFunctionDefs.insert(
|
||||
GlobalValue::getGUID(GlobalValue::dropLLVMManglingEscape(Name)));
|
||||
|
@ -954,8 +939,7 @@ public:
|
|||
const FunctionImporter::ExportSetTy &ExportList,
|
||||
const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes> &ResolvedODR,
|
||||
const GVSummaryMapTy &DefinedGlobals,
|
||||
MapVector<StringRef, BitcodeModule> &ModuleMap,
|
||||
const TypeIdSummariesByGuidTy &TypeIdSummariesByGuid) {
|
||||
MapVector<StringRef, BitcodeModule> &ModuleMap) {
|
||||
auto RunThinBackend = [&](AddStreamFn AddStream) {
|
||||
LTOLLVMContext BackendContext(Conf);
|
||||
Expected<std::unique_ptr<Module>> MOrErr = BM.parseModule(BackendContext);
|
||||
|
@ -978,8 +962,8 @@ public:
|
|||
SmallString<40> Key;
|
||||
// The module may be cached, this helps handling it.
|
||||
computeCacheKey(Key, Conf, CombinedIndex, ModuleID, ImportList, ExportList,
|
||||
ResolvedODR, DefinedGlobals, TypeIdSummariesByGuid,
|
||||
CfiFunctionDefs, CfiFunctionDecls);
|
||||
ResolvedODR, DefinedGlobals, CfiFunctionDefs,
|
||||
CfiFunctionDecls);
|
||||
if (AddStreamFn CacheAddStream = Cache(Task, Key))
|
||||
return RunThinBackend(CacheAddStream);
|
||||
|
||||
|
@ -1003,11 +987,10 @@ public:
|
|||
const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes>
|
||||
&ResolvedODR,
|
||||
const GVSummaryMapTy &DefinedGlobals,
|
||||
MapVector<StringRef, BitcodeModule> &ModuleMap,
|
||||
const TypeIdSummariesByGuidTy &TypeIdSummariesByGuid) {
|
||||
MapVector<StringRef, BitcodeModule> &ModuleMap) {
|
||||
Error E = runThinLTOBackendThread(
|
||||
AddStream, Cache, Task, BM, CombinedIndex, ImportList, ExportList,
|
||||
ResolvedODR, DefinedGlobals, ModuleMap, TypeIdSummariesByGuid);
|
||||
ResolvedODR, DefinedGlobals, ModuleMap);
|
||||
if (E) {
|
||||
std::unique_lock<std::mutex> L(ErrMu);
|
||||
if (Err)
|
||||
|
@ -1017,8 +1000,7 @@ public:
|
|||
}
|
||||
},
|
||||
BM, std::ref(CombinedIndex), std::ref(ImportList), std::ref(ExportList),
|
||||
std::ref(ResolvedODR), std::ref(DefinedGlobals), std::ref(ModuleMap),
|
||||
std::ref(TypeIdSummariesByGuid));
|
||||
std::ref(ResolvedODR), std::ref(DefinedGlobals), std::ref(ModuleMap));
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
|
|
|
@ -54,13 +54,13 @@
|
|||
|
||||
; Test TypeId summaries:
|
||||
|
||||
; Test the AllOnes resolution, and all kinds of WholeProgramDevirtResolution
|
||||
; types, including all optional resolution by argument kinds.
|
||||
^24 = typeid: (name: "_ZTS1A", summary: (typeTestRes: (kind: allOnes, sizeM1BitWidth: 7), wpdResolutions: ((offset: 0, wpdRes: (kind: branchFunnel)), (offset: 8, wpdRes: (kind: singleImpl, singleImplName: "_ZN1A1nEi")), (offset: 16, wpdRes: (kind: indir, resByArg: (args: (1, 2), byArg: (kind: indir, byte: 2, bit: 3), args: (3), byArg: (kind: uniformRetVal, info: 1), args: (4), byArg: (kind: uniqueRetVal, info: 1), args: (5), byArg: (kind: virtualConstProp)))))))
|
||||
^24 = typeid: (name: "_ZTS1C", summary: (typeTestRes: (kind: single, sizeM1BitWidth: 0)))
|
||||
; Test TypeId with other optional fields (alignLog2/sizeM1/bitMask/inlineBits)
|
||||
^25 = typeid: (name: "_ZTS1B", summary: (typeTestRes: (kind: inline, sizeM1BitWidth: 0, alignLog2: 1, sizeM1: 2, bitMask: 3, inlineBits: 4)))
|
||||
; Test the AllOnes resolution, and all kinds of WholeProgramDevirtResolution
|
||||
; types, including all optional resolution by argument kinds.
|
||||
^26 = typeid: (name: "_ZTS1A", summary: (typeTestRes: (kind: allOnes, sizeM1BitWidth: 7), wpdResolutions: ((offset: 0, wpdRes: (kind: branchFunnel)), (offset: 8, wpdRes: (kind: singleImpl, singleImplName: "_ZN1A1nEi")), (offset: 16, wpdRes: (kind: indir, resByArg: (args: (1, 2), byArg: (kind: indir, byte: 2, bit: 3), args: (3), byArg: (kind: uniformRetVal, info: 1), args: (4), byArg: (kind: uniqueRetVal, info: 1), args: (5), byArg: (kind: virtualConstProp)))))))
|
||||
; Test the other kinds of type test resoultions
|
||||
^26 = typeid: (name: "_ZTS1C", summary: (typeTestRes: (kind: single, sizeM1BitWidth: 0)))
|
||||
^27 = typeid: (name: "_ZTS1D", summary: (typeTestRes: (kind: byteArray, sizeM1BitWidth: 0)))
|
||||
^28 = typeid: (name: "_ZTS1E", summary: (typeTestRes: (kind: unsat, sizeM1BitWidth: 0)))
|
||||
|
||||
|
@ -89,8 +89,8 @@
|
|||
; CHECK: ^21 = gv: (guid: 20, summaries: (function: (module: ^0, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 0), insts: 5, typeIdInfo: (typeCheckedLoadVCalls: (vFuncId: (^25, offset: 16))))))
|
||||
; CHECK: ^22 = gv: (guid: 21, summaries: (function: (module: ^0, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 0), insts: 15, typeIdInfo: (typeTestAssumeConstVCalls: ((vFuncId: (^27, offset: 16), args: (42)), (vFuncId: (^27, offset: 24)))))))
|
||||
; CHECK: ^23 = gv: (guid: 22, summaries: (function: (module: ^0, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 0), insts: 5, typeIdInfo: (typeCheckedLoadConstVCalls: ((vFuncId: (^28, offset: 16), args: (42)))))))
|
||||
; CHECK: ^24 = typeid: (name: "_ZTS1A", summary: (typeTestRes: (kind: allOnes, sizeM1BitWidth: 7), wpdResolutions: ((offset: 0, wpdRes: (kind: branchFunnel)), (offset: 8, wpdRes: (kind: singleImpl, singleImplName: "_ZN1A1nEi")), (offset: 16, wpdRes: (kind: indir, resByArg: (args: (1, 2), byArg: (kind: indir, byte: 2, bit: 3), args: (3), byArg: (kind: uniformRetVal, info: 1), args: (4), byArg: (kind: uniqueRetVal, info: 1), args: (5), byArg: (kind: virtualConstProp))))))) ; guid = 7004155349499253778
|
||||
; CHECK: ^24 = typeid: (name: "_ZTS1C", summary: (typeTestRes: (kind: single, sizeM1BitWidth: 0))) ; guid = 1884921850105019584
|
||||
; CHECK: ^25 = typeid: (name: "_ZTS1B", summary: (typeTestRes: (kind: inline, sizeM1BitWidth: 0, alignLog2: 1, sizeM1: 2, bitMask: 3, inlineBits: 4))) ; guid = 6203814149063363976
|
||||
; CHECK: ^26 = typeid: (name: "_ZTS1C", summary: (typeTestRes: (kind: single, sizeM1BitWidth: 0))) ; guid = 1884921850105019584
|
||||
; CHECK: ^26 = typeid: (name: "_ZTS1A", summary: (typeTestRes: (kind: allOnes, sizeM1BitWidth: 7), wpdResolutions: ((offset: 0, wpdRes: (kind: branchFunnel)), (offset: 8, wpdRes: (kind: singleImpl, singleImplName: "_ZN1A1nEi")), (offset: 16, wpdRes: (kind: indir, resByArg: (args: (1, 2), byArg: (kind: indir, byte: 2, bit: 3), args: (3), byArg: (kind: uniformRetVal, info: 1), args: (4), byArg: (kind: uniqueRetVal, info: 1), args: (5), byArg: (kind: virtualConstProp))))))) ; guid = 7004155349499253778
|
||||
; CHECK: ^27 = typeid: (name: "_ZTS1D", summary: (typeTestRes: (kind: byteArray, sizeM1BitWidth: 0))) ; guid = 9614786172484273522
|
||||
; CHECK: ^28 = typeid: (name: "_ZTS1E", summary: (typeTestRes: (kind: unsat, sizeM1BitWidth: 0))) ; guid = 17437243864166745132
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
; RUN: FileCheck --check-prefix=SUMMARY %s < %t
|
||||
|
||||
; SUMMARY: TypeIdMap:
|
||||
; SUMMARY-NEXT: typeid1:
|
||||
; SUMMARY-NEXT: typeid3:
|
||||
; SUMMARY-NEXT: TTRes:
|
||||
; SUMMARY-NEXT: Kind: Unsat
|
||||
; SUMMARY-NEXT: SizeM1BitWidth: 0
|
||||
|
@ -21,7 +21,20 @@
|
|||
; SUMMARY-NEXT: Kind: BranchFunnel
|
||||
; SUMMARY-NEXT: SingleImplName: ''
|
||||
; SUMMARY-NEXT: ResByArg:
|
||||
; SUMMARY-NEXT: typeid2:
|
||||
; SUMMARY-NEXT: typeid1:
|
||||
; SUMMARY-NEXT: TTRes:
|
||||
; SUMMARY-NEXT: Kind: Unsat
|
||||
; SUMMARY-NEXT: SizeM1BitWidth: 0
|
||||
; SUMMARY-NEXT: AlignLog2: 0
|
||||
; SUMMARY-NEXT: SizeM1: 0
|
||||
; SUMMARY-NEXT: BitMask: 0
|
||||
; SUMMARY-NEXT: InlineBits: 0
|
||||
; SUMMARY-NEXT: WPDRes:
|
||||
; SUMMARY-NEXT: 0:
|
||||
; SUMMARY-NEXT: Kind: BranchFunnel
|
||||
; SUMMARY-NEXT: SingleImplName: ''
|
||||
; SUMMARY-NEXT: ResByArg:
|
||||
; SUMMARY-NEXT: typeid2:
|
||||
; SUMMARY-NEXT: TTRes:
|
||||
; SUMMARY-NEXT: Kind: Unsat
|
||||
; SUMMARY-NEXT: SizeM1BitWidth: 0
|
||||
|
@ -34,19 +47,6 @@
|
|||
; SUMMARY-NEXT: Kind: Indir
|
||||
; SUMMARY-NEXT: SingleImplName: ''
|
||||
; SUMMARY-NEXT: ResByArg:
|
||||
; SUMMARY-NEXT: typeid3:
|
||||
; SUMMARY-NEXT: TTRes:
|
||||
; SUMMARY-NEXT: Kind: Unsat
|
||||
; SUMMARY-NEXT: SizeM1BitWidth: 0
|
||||
; SUMMARY-NEXT: AlignLog2: 0
|
||||
; SUMMARY-NEXT: SizeM1: 0
|
||||
; SUMMARY-NEXT: BitMask: 0
|
||||
; SUMMARY-NEXT: InlineBits: 0
|
||||
; SUMMARY-NEXT: WPDRes:
|
||||
; SUMMARY-NEXT: 0:
|
||||
; SUMMARY-NEXT: Kind: BranchFunnel
|
||||
; SUMMARY-NEXT: SingleImplName: ''
|
||||
; SUMMARY-NEXT: ResByArg:
|
||||
|
||||
target datalayout = "e-p:64:64"
|
||||
target triple = "x86_64-unknown-linux-gnu"
|
||||
|
|
|
@ -2,6 +2,19 @@
|
|||
; RUN: FileCheck --check-prefix=SUMMARY %s < %t
|
||||
|
||||
; SUMMARY: TypeIdMap:
|
||||
; SUMMARY-NEXT: typeid3:
|
||||
; SUMMARY-NEXT: TTRes:
|
||||
; SUMMARY-NEXT: Kind: Unsat
|
||||
; SUMMARY-NEXT: SizeM1BitWidth: 0
|
||||
; SUMMARY-NEXT: AlignLog2: 0
|
||||
; SUMMARY-NEXT: SizeM1: 0
|
||||
; SUMMARY-NEXT: BitMask: 0
|
||||
; SUMMARY-NEXT: InlineBits: 0
|
||||
; SUMMARY-NEXT: WPDRes:
|
||||
; SUMMARY-NEXT: 0:
|
||||
; SUMMARY-NEXT: Kind: SingleImpl
|
||||
; SUMMARY-NEXT: SingleImplName: 'vf3$merged'
|
||||
; SUMMARY-NEXT: ResByArg:
|
||||
; SUMMARY-NEXT: typeid1:
|
||||
; SUMMARY-NEXT: TTRes:
|
||||
; SUMMARY-NEXT: Kind: Unsat
|
||||
|
@ -28,19 +41,6 @@
|
|||
; SUMMARY-NEXT: Kind: SingleImpl
|
||||
; SUMMARY-NEXT: SingleImplName: vf2
|
||||
; SUMMARY-NEXT: ResByArg:
|
||||
; SUMMARY-NEXT: typeid3:
|
||||
; SUMMARY-NEXT: TTRes:
|
||||
; SUMMARY-NEXT: Kind: Unsat
|
||||
; SUMMARY-NEXT: SizeM1BitWidth: 0
|
||||
; SUMMARY-NEXT: AlignLog2: 0
|
||||
; SUMMARY-NEXT: SizeM1: 0
|
||||
; SUMMARY-NEXT: BitMask: 0
|
||||
; SUMMARY-NEXT: InlineBits: 0
|
||||
; SUMMARY-NEXT: WPDRes:
|
||||
; SUMMARY-NEXT: 0:
|
||||
; SUMMARY-NEXT: Kind: SingleImpl
|
||||
; SUMMARY-NEXT: SingleImplName: 'vf3$merged'
|
||||
; SUMMARY-NEXT: ResByArg:
|
||||
; SUMMARY-NEXT: typeid4:
|
||||
; SUMMARY-NEXT: TTRes:
|
||||
; SUMMARY-NEXT: Kind: Unsat
|
||||
|
|
Loading…
Reference in New Issue