LTO: Hash type identifier resolutions for LowerTypeTests.

Differential Revision: https://reviews.llvm.org/D30553

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@297513 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Peter Collingbourne 2017-03-10 21:35:17 +00:00
parent 966981992e
commit a354228e67
5 changed files with 109 additions and 11 deletions

View File

@ -663,6 +663,10 @@ public:
return ModulePathStringTable.count(M.getModuleIdentifier());
}
const std::map<std::string, TypeIdSummary> &typeIds() const {
return TypeIdMap;
}
TypeIdSummary &getTypeIdSummary(StringRef TypeId) {
return TypeIdMap[TypeId];
}

View File

@ -50,6 +50,12 @@ using namespace object;
#define DEBUG_TYPE "lto"
// 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.
@ -58,7 +64,8 @@ static void computeCacheKey(
StringRef ModuleID, const FunctionImporter::ImportMapTy &ImportList,
const FunctionImporter::ExportSetTy &ExportList,
const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes> &ResolvedODR,
const GVSummaryMapTy &DefinedGlobals) {
const GVSummaryMapTy &DefinedGlobals,
const TypeIdSummariesByGuidTy &TypeIdSummariesByGuid) {
// Compute the unique hash for this entry.
// This is based on the current compiler version, the module itself, the
// export list, the hash for every single module in the import list, the
@ -144,12 +151,52 @@ static void computeCacheKey(
sizeof(GlobalValue::LinkageTypes)));
}
std::set<GlobalValue::GUID> UsedTypeIds;
auto AddUsedTypeIds = [&](GlobalValueSummary *GS) {
auto *FS = dyn_cast_or_null<FunctionSummary>(GS);
if (!FS)
return;
for (auto &TT : FS->type_tests())
UsedTypeIds.insert(TT);
for (auto &TT : FS->type_test_assume_vcalls())
UsedTypeIds.insert(TT.GUID);
for (auto &TT : FS->type_checked_load_vcalls())
UsedTypeIds.insert(TT.GUID);
for (auto &TT : FS->type_test_assume_const_vcalls())
UsedTypeIds.insert(TT.VFunc.GUID);
for (auto &TT : FS->type_checked_load_const_vcalls())
UsedTypeIds.insert(TT.VFunc.GUID);
};
// Include the hash for the linkage type to reflect internalization and weak
// resolution.
// resolution, and collect any used type identifier resolutions.
for (auto &GS : DefinedGlobals) {
GlobalValue::LinkageTypes Linkage = GS.second->linkage();
Hasher.update(
ArrayRef<uint8_t>((const uint8_t *)&Linkage, sizeof(Linkage)));
AddUsedTypeIds(GS.second);
}
// Imported functions may introduce new uses of type identifier resolutions,
// so we need to collect their used resolutions as well.
for (auto &ImpM : ImportList)
for (auto &ImpF : ImpM.second)
AddUsedTypeIds(Index.findSummaryInModule(ImpF.first, ImpM.first()));
auto AddTypeIdSummary = [&](StringRef TId, const TypeIdSummary &S) {
AddString(TId);
AddUnsigned(S.TTRes.TheKind);
AddUnsigned(S.TTRes.SizeM1BitWidth);
};
// 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);
}
if (!Conf.SampleProfile.empty()) {
@ -702,6 +749,7 @@ class InProcessThinBackend : public ThinBackendProc {
ThreadPool BackendThreadPool;
AddStreamFn AddStream;
NativeObjectCache Cache;
TypeIdSummariesByGuidTy TypeIdSummariesByGuid;
Optional<Error> Err;
std::mutex ErrMu;
@ -714,7 +762,14 @@ public:
AddStreamFn AddStream, NativeObjectCache Cache)
: ThinBackendProc(Conf, CombinedIndex, ModuleToDefinedGVSummaries),
BackendThreadPool(ThinLTOParallelismLevel),
AddStream(std::move(AddStream)), Cache(std::move(Cache)) {}
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);
}
Error runThinLTOBackendThread(
AddStreamFn AddStream, NativeObjectCache Cache, unsigned Task,
@ -723,7 +778,8 @@ public:
const FunctionImporter::ExportSetTy &ExportList,
const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes> &ResolvedODR,
const GVSummaryMapTy &DefinedGlobals,
MapVector<StringRef, BitcodeModule> &ModuleMap) {
MapVector<StringRef, BitcodeModule> &ModuleMap,
const TypeIdSummariesByGuidTy &TypeIdSummariesByGuid) {
auto RunThinBackend = [&](AddStreamFn AddStream) {
LTOLLVMContext BackendContext(Conf);
Expected<std::unique_ptr<Module>> MOrErr = BM.parseModule(BackendContext);
@ -746,7 +802,7 @@ public:
SmallString<40> Key;
// The module may be cached, this helps handling it.
computeCacheKey(Key, Conf, CombinedIndex, ModuleID, ImportList, ExportList,
ResolvedODR, DefinedGlobals);
ResolvedODR, DefinedGlobals, TypeIdSummariesByGuid);
if (AddStreamFn CacheAddStream = Cache(Task, Key))
return RunThinBackend(CacheAddStream);
@ -770,10 +826,11 @@ public:
const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes>
&ResolvedODR,
const GVSummaryMapTy &DefinedGlobals,
MapVector<StringRef, BitcodeModule> &ModuleMap) {
MapVector<StringRef, BitcodeModule> &ModuleMap,
const TypeIdSummariesByGuidTy &TypeIdSummariesByGuid) {
Error E = runThinLTOBackendThread(
AddStream, Cache, Task, BM, CombinedIndex, ImportList,
ExportList, ResolvedODR, DefinedGlobals, ModuleMap);
AddStream, Cache, Task, BM, CombinedIndex, ImportList, ExportList,
ResolvedODR, DefinedGlobals, ModuleMap, TypeIdSummariesByGuid);
if (E) {
std::unique_lock<std::mutex> L(ErrMu);
if (Err)
@ -782,9 +839,9 @@ public:
Err = std::move(E);
}
},
BM, std::ref(CombinedIndex), std::ref(ImportList),
std::ref(ExportList), std::ref(ResolvedODR), std::ref(DefinedGlobals),
std::ref(ModuleMap));
BM, std::ref(CombinedIndex), std::ref(ImportList), std::ref(ExportList),
std::ref(ResolvedODR), std::ref(DefinedGlobals), std::ref(ModuleMap),
std::ref(TypeIdSummariesByGuid));
return Error::success();
}

View File

@ -0,0 +1,9 @@
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
define i1 @importf1(i8* %p) {
%x = call i1 @f1(i8* %p)
ret i1 %x
}
declare i1 @f1(i8* %p)

View File

@ -0,0 +1,6 @@
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
@vt1 = constant i32 0, !type !0
!0 = !{i32 0, !"typeid1"}

View File

@ -0,0 +1,22 @@
; RUN: opt -module-hash -module-summary %s -o %t.bc
; RUN: opt -module-hash -module-summary %S/Inputs/cache-typeid-resolutions-import.ll -o %t-import.bc
; RUN: llvm-as -o %t1.bc %S/Inputs/cache-typeid-resolutions1.ll
; Two resolutions for typeid1: Unsat, Single
; where both t and t-import are sensitive to typeid1's resolution
; so 4 distinct objects in total.
; RUN: rm -rf %t.cache
; RUN: llvm-lto2 -o %t.o %t.bc %t-import.bc -cache-dir %t.cache -r=%t.bc,f1,plx -r=%t-import.bc,importf1,plx -r=%t-import.bc,f1,lx
; RUN: llvm-lto2 -o %t.o %t.bc %t-import.bc %t1.bc -cache-dir %t.cache -r=%t.bc,f1,plx -r=%t-import.bc,importf1,plx -r=%t-import.bc,f1,lx -r=%t1.bc,vt1,plx
; RUN: ls %t.cache | count 4
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
define i1 @f1(i8* %p) {
%x = call i1 @llvm.type.test(i8* %p, metadata !"typeid1")
ret i1 %x
}
declare i1 @llvm.type.test(i8*, metadata)