mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-25 20:23:11 +01:00
IR: Function summary representation for type tests.
Each function summary has an attached list of type identifier GUIDs. The idea is that during the regular LTO phase we would match these GUIDs to type identifiers defined by the regular LTO module and store the resolutions in a top-level "type identifier summary" (which will be implemented separately). Differential Revision: https://reviews.llvm.org/D27967 llvm-svn: 290280
This commit is contained in:
parent
d114d43c64
commit
5ce602306f
@ -213,6 +213,8 @@ enum GlobalValueSummarySymtabCodes {
|
|||||||
FS_COMBINED_ORIGINAL_NAME = 9,
|
FS_COMBINED_ORIGINAL_NAME = 9,
|
||||||
// VERSION of the summary, bumped when adding flags for instance.
|
// VERSION of the summary, bumped when adding flags for instance.
|
||||||
FS_VERSION = 10,
|
FS_VERSION = 10,
|
||||||
|
// The list of llvm.type.test type identifiers used by the following function.
|
||||||
|
FS_TYPE_TESTS = 11,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum MetadataCodes {
|
enum MetadataCodes {
|
||||||
|
@ -284,12 +284,17 @@ private:
|
|||||||
/// List of <CalleeValueInfo, CalleeInfo> call edge pairs from this function.
|
/// List of <CalleeValueInfo, CalleeInfo> call edge pairs from this function.
|
||||||
std::vector<EdgeTy> CallGraphEdgeList;
|
std::vector<EdgeTy> CallGraphEdgeList;
|
||||||
|
|
||||||
|
/// List of type identifiers used by this function, represented as GUIDs.
|
||||||
|
std::vector<GlobalValue::GUID> TypeIdList;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// Summary constructors.
|
/// Summary constructors.
|
||||||
FunctionSummary(GVFlags Flags, unsigned NumInsts, std::vector<ValueInfo> Refs,
|
FunctionSummary(GVFlags Flags, unsigned NumInsts, std::vector<ValueInfo> Refs,
|
||||||
std::vector<EdgeTy> CGEdges)
|
std::vector<EdgeTy> CGEdges,
|
||||||
|
std::vector<GlobalValue::GUID> TypeIds)
|
||||||
: GlobalValueSummary(FunctionKind, Flags, std::move(Refs)),
|
: GlobalValueSummary(FunctionKind, Flags, std::move(Refs)),
|
||||||
InstCount(NumInsts), CallGraphEdgeList(std::move(CGEdges)) {}
|
InstCount(NumInsts), CallGraphEdgeList(std::move(CGEdges)),
|
||||||
|
TypeIdList(std::move(TypeIds)) {}
|
||||||
|
|
||||||
/// Check if this is a function summary.
|
/// Check if this is a function summary.
|
||||||
static bool classof(const GlobalValueSummary *GVS) {
|
static bool classof(const GlobalValueSummary *GVS) {
|
||||||
@ -301,6 +306,9 @@ public:
|
|||||||
|
|
||||||
/// Return the list of <CalleeValueInfo, CalleeInfo> pairs.
|
/// Return the list of <CalleeValueInfo, CalleeInfo> pairs.
|
||||||
ArrayRef<EdgeTy> calls() const { return CallGraphEdgeList; }
|
ArrayRef<EdgeTy> calls() const { return CallGraphEdgeList; }
|
||||||
|
|
||||||
|
/// Returns the list of type identifiers used by this function.
|
||||||
|
ArrayRef<GlobalValue::GUID> type_tests() const { return TypeIdList; }
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief Global variable summary information to aid decisions and
|
/// \brief Global variable summary information to aid decisions and
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include "llvm/Analysis/IndirectCallPromotionAnalysis.h"
|
#include "llvm/Analysis/IndirectCallPromotionAnalysis.h"
|
||||||
#include "llvm/Analysis/LoopInfo.h"
|
#include "llvm/Analysis/LoopInfo.h"
|
||||||
#include "llvm/Analysis/ProfileSummaryInfo.h"
|
#include "llvm/Analysis/ProfileSummaryInfo.h"
|
||||||
|
#include "llvm/Analysis/TypeMetadataUtils.h"
|
||||||
#include "llvm/IR/CallSite.h"
|
#include "llvm/IR/CallSite.h"
|
||||||
#include "llvm/IR/Dominators.h"
|
#include "llvm/IR/Dominators.h"
|
||||||
#include "llvm/IR/InstIterator.h"
|
#include "llvm/IR/InstIterator.h"
|
||||||
@ -92,6 +93,7 @@ static void computeFunctionSummary(ModuleSummaryIndex &Index, const Module &M,
|
|||||||
// counts for all static calls to a given callee.
|
// counts for all static calls to a given callee.
|
||||||
MapVector<ValueInfo, CalleeInfo> CallGraphEdges;
|
MapVector<ValueInfo, CalleeInfo> CallGraphEdges;
|
||||||
SetVector<ValueInfo> RefEdges;
|
SetVector<ValueInfo> RefEdges;
|
||||||
|
SetVector<GlobalValue::GUID> TypeTests;
|
||||||
ICallPromotionAnalysis ICallAnalysis;
|
ICallPromotionAnalysis ICallAnalysis;
|
||||||
|
|
||||||
bool HasInlineAsmMaybeReferencingInternal = false;
|
bool HasInlineAsmMaybeReferencingInternal = false;
|
||||||
@ -123,11 +125,29 @@ static void computeFunctionSummary(ModuleSummaryIndex &Index, const Module &M,
|
|||||||
assert(!CalledFunction && "Expected null called function in callsite for alias");
|
assert(!CalledFunction && "Expected null called function in callsite for alias");
|
||||||
CalledFunction = dyn_cast<Function>(GA->getBaseObject());
|
CalledFunction = dyn_cast<Function>(GA->getBaseObject());
|
||||||
}
|
}
|
||||||
// Check if this is a direct call to a known function.
|
// Check if this is a direct call to a known function or a known
|
||||||
|
// intrinsic, or an indirect call with profile data.
|
||||||
if (CalledFunction) {
|
if (CalledFunction) {
|
||||||
// Skip intrinsics.
|
if (CalledFunction->isIntrinsic()) {
|
||||||
if (CalledFunction->isIntrinsic())
|
if (CalledFunction->getIntrinsicID() != Intrinsic::type_test)
|
||||||
continue;
|
continue;
|
||||||
|
// Produce a summary from type.test intrinsics. We only summarize
|
||||||
|
// type.test intrinsics that are used other than by an llvm.assume
|
||||||
|
// intrinsic. Intrinsics that are assumed are relevant only to the
|
||||||
|
// devirtualization pass, not the type test lowering pass.
|
||||||
|
bool HasNonAssumeUses = llvm::any_of(CI->uses(), [](const Use &CIU) {
|
||||||
|
auto *AssumeCI = dyn_cast<CallInst>(CIU.getUser());
|
||||||
|
if (!AssumeCI)
|
||||||
|
return true;
|
||||||
|
Function *F = AssumeCI->getCalledFunction();
|
||||||
|
return !F || F->getIntrinsicID() != Intrinsic::assume;
|
||||||
|
});
|
||||||
|
if (HasNonAssumeUses) {
|
||||||
|
auto *TypeMDVal = cast<MetadataAsValue>(CI->getArgOperand(1));
|
||||||
|
if (auto *TypeId = dyn_cast<MDString>(TypeMDVal->getMetadata()))
|
||||||
|
TypeTests.insert(GlobalValue::getGUID(TypeId->getString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
// We should have named any anonymous globals
|
// We should have named any anonymous globals
|
||||||
assert(CalledFunction->hasName());
|
assert(CalledFunction->hasName());
|
||||||
auto ScaledCount = BFI ? BFI->getBlockProfileCount(&BB) : None;
|
auto ScaledCount = BFI ? BFI->getBlockProfileCount(&BB) : None;
|
||||||
@ -160,7 +180,8 @@ static void computeFunctionSummary(ModuleSummaryIndex &Index, const Module &M,
|
|||||||
|
|
||||||
GlobalValueSummary::GVFlags Flags(F);
|
GlobalValueSummary::GVFlags Flags(F);
|
||||||
auto FuncSummary = llvm::make_unique<FunctionSummary>(
|
auto FuncSummary = llvm::make_unique<FunctionSummary>(
|
||||||
Flags, NumInsts, RefEdges.takeVector(), CallGraphEdges.takeVector());
|
Flags, NumInsts, RefEdges.takeVector(), CallGraphEdges.takeVector(),
|
||||||
|
TypeTests.takeVector());
|
||||||
if (HasInlineAsmMaybeReferencingInternal)
|
if (HasInlineAsmMaybeReferencingInternal)
|
||||||
FuncSummary->setHasInlineAsmMaybeReferencingInternal();
|
FuncSummary->setHasInlineAsmMaybeReferencingInternal();
|
||||||
Index.addGlobalValueSummary(F.getName(), std::move(FuncSummary));
|
Index.addGlobalValueSummary(F.getName(), std::move(FuncSummary));
|
||||||
@ -280,7 +301,8 @@ ModuleSummaryIndex llvm::buildModuleSummaryIndex(
|
|||||||
std::unique_ptr<FunctionSummary> Summary =
|
std::unique_ptr<FunctionSummary> Summary =
|
||||||
llvm::make_unique<FunctionSummary>(
|
llvm::make_unique<FunctionSummary>(
|
||||||
GVFlags, 0, ArrayRef<ValueInfo>{},
|
GVFlags, 0, ArrayRef<ValueInfo>{},
|
||||||
ArrayRef<FunctionSummary::EdgeTy>{});
|
ArrayRef<FunctionSummary::EdgeTy>{},
|
||||||
|
ArrayRef<GlobalValue::GUID>{});
|
||||||
Summary->setNoRename();
|
Summary->setNoRename();
|
||||||
Index.addGlobalValueSummary(Name, std::move(Summary));
|
Index.addGlobalValueSummary(Name, std::move(Summary));
|
||||||
} else {
|
} else {
|
||||||
|
@ -4847,6 +4847,7 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(
|
|||||||
// "OriginalName" attachement.
|
// "OriginalName" attachement.
|
||||||
GlobalValueSummary *LastSeenSummary = nullptr;
|
GlobalValueSummary *LastSeenSummary = nullptr;
|
||||||
bool Combined = false;
|
bool Combined = false;
|
||||||
|
std::vector<GlobalValue::GUID> PendingTypeTests;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
|
BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
|
||||||
@ -4912,7 +4913,8 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(
|
|||||||
ArrayRef<uint64_t>(Record).slice(CallGraphEdgeStartIndex),
|
ArrayRef<uint64_t>(Record).slice(CallGraphEdgeStartIndex),
|
||||||
IsOldProfileFormat, HasProfile);
|
IsOldProfileFormat, HasProfile);
|
||||||
auto FS = llvm::make_unique<FunctionSummary>(
|
auto FS = llvm::make_unique<FunctionSummary>(
|
||||||
Flags, InstCount, std::move(Refs), std::move(Calls));
|
Flags, InstCount, std::move(Refs), std::move(Calls),
|
||||||
|
std::move(PendingTypeTests));
|
||||||
auto GUID = getGUIDFromValueId(ValueID);
|
auto GUID = getGUIDFromValueId(ValueID);
|
||||||
FS->setModulePath(TheIndex.addModulePath(ModulePath, 0)->first());
|
FS->setModulePath(TheIndex.addModulePath(ModulePath, 0)->first());
|
||||||
FS->setOriginalName(GUID.second);
|
FS->setOriginalName(GUID.second);
|
||||||
@ -4985,7 +4987,8 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(
|
|||||||
IsOldProfileFormat, HasProfile);
|
IsOldProfileFormat, HasProfile);
|
||||||
GlobalValue::GUID GUID = getGUIDFromValueId(ValueID).first;
|
GlobalValue::GUID GUID = getGUIDFromValueId(ValueID).first;
|
||||||
auto FS = llvm::make_unique<FunctionSummary>(
|
auto FS = llvm::make_unique<FunctionSummary>(
|
||||||
Flags, InstCount, std::move(Refs), std::move(Edges));
|
Flags, InstCount, std::move(Refs), std::move(Edges),
|
||||||
|
std::move(PendingTypeTests));
|
||||||
LastSeenSummary = FS.get();
|
LastSeenSummary = FS.get();
|
||||||
FS->setModulePath(ModuleIdMap[ModuleId]);
|
FS->setModulePath(ModuleIdMap[ModuleId]);
|
||||||
TheIndex.addGlobalValueSummary(GUID, std::move(FS));
|
TheIndex.addGlobalValueSummary(GUID, std::move(FS));
|
||||||
@ -5041,6 +5044,13 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(
|
|||||||
LastSeenSummary->setOriginalName(OriginalName);
|
LastSeenSummary->setOriginalName(OriginalName);
|
||||||
// Reset the LastSeenSummary
|
// Reset the LastSeenSummary
|
||||||
LastSeenSummary = nullptr;
|
LastSeenSummary = nullptr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case bitc::FS_TYPE_TESTS: {
|
||||||
|
assert(PendingTypeTests.empty());
|
||||||
|
PendingTypeTests.insert(PendingTypeTests.end(), Record.begin(),
|
||||||
|
Record.end());
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3286,6 +3286,9 @@ void ModuleBitcodeWriter::writePerModuleFunctionSummaryRecord(
|
|||||||
NameVals.push_back(ValueID);
|
NameVals.push_back(ValueID);
|
||||||
|
|
||||||
FunctionSummary *FS = cast<FunctionSummary>(Summary);
|
FunctionSummary *FS = cast<FunctionSummary>(Summary);
|
||||||
|
if (!FS->type_tests().empty())
|
||||||
|
Stream.EmitRecord(bitc::FS_TYPE_TESTS, FS->type_tests());
|
||||||
|
|
||||||
NameVals.push_back(getEncodedGVSummaryFlags(FS->flags()));
|
NameVals.push_back(getEncodedGVSummaryFlags(FS->flags()));
|
||||||
NameVals.push_back(FS->instCount());
|
NameVals.push_back(FS->instCount());
|
||||||
NameVals.push_back(FS->refs().size());
|
NameVals.push_back(FS->refs().size());
|
||||||
@ -3544,6 +3547,9 @@ void IndexBitcodeWriter::writeCombinedGlobalValueSummary() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto *FS = cast<FunctionSummary>(S);
|
auto *FS = cast<FunctionSummary>(S);
|
||||||
|
if (!FS->type_tests().empty())
|
||||||
|
Stream.EmitRecord(bitc::FS_TYPE_TESTS, FS->type_tests());
|
||||||
|
|
||||||
NameVals.push_back(ValueId);
|
NameVals.push_back(ValueId);
|
||||||
NameVals.push_back(Index.getModuleId(FS->modulePath()));
|
NameVals.push_back(Index.getModuleId(FS->modulePath()));
|
||||||
NameVals.push_back(getEncodedGVSummaryFlags(FS->flags()));
|
NameVals.push_back(getEncodedGVSummaryFlags(FS->flags()));
|
||||||
|
30
test/Bitcode/thinlto-type-tests.ll
Normal file
30
test/Bitcode/thinlto-type-tests.ll
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
; RUN: opt -module-summary %s -o %t.o
|
||||||
|
; RUN: llvm-bcanalyzer -dump %t.o | FileCheck %s
|
||||||
|
; RUN: llvm-lto -thinlto -o %t2 %t.o
|
||||||
|
; RUN: llvm-bcanalyzer -dump %t2.thinlto.bc | FileCheck --check-prefix=COMBINED %s
|
||||||
|
|
||||||
|
; COMBINED: <TYPE_TESTS op0=-2012135647395072713/>
|
||||||
|
; COMBINED: <TYPE_TESTS op0=6699318081062747564 op1=-2012135647395072713/>
|
||||||
|
; COMBINED: <TYPE_TESTS op0=6699318081062747564/>
|
||||||
|
|
||||||
|
; CHECK: <TYPE_TESTS op0=6699318081062747564/>
|
||||||
|
define i1 @f() {
|
||||||
|
%p = call i1 @llvm.type.test(i8* null, metadata !"foo")
|
||||||
|
ret i1 %p
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK: <TYPE_TESTS op0=6699318081062747564 op1=-2012135647395072713/>
|
||||||
|
define i1 @g() {
|
||||||
|
%p = call i1 @llvm.type.test(i8* null, metadata !"foo")
|
||||||
|
%q = call i1 @llvm.type.test(i8* null, metadata !"bar")
|
||||||
|
%pq = and i1 %p, %q
|
||||||
|
ret i1 %pq
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK: <TYPE_TESTS op0=-2012135647395072713/>
|
||||||
|
define i1 @h() {
|
||||||
|
%p = call i1 @llvm.type.test(i8* null, metadata !"bar")
|
||||||
|
ret i1 %p
|
||||||
|
}
|
||||||
|
|
||||||
|
declare i1 @llvm.type.test(i8*, metadata) nounwind readnone
|
13
test/Bitcode/thinlto-unused-type-tests.ll
Normal file
13
test/Bitcode/thinlto-unused-type-tests.ll
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
; RUN: opt -module-summary %s -o %t.o
|
||||||
|
; RUN: llvm-bcanalyzer -dump %t.o | FileCheck %s
|
||||||
|
|
||||||
|
; CHECK-NOT: <TYPE_TESTS
|
||||||
|
define void @f() {
|
||||||
|
%p = call i1 @llvm.type.test(i8* null, metadata !"foo")
|
||||||
|
%q = call i1 @llvm.type.test(i8* null, metadata !"bar")
|
||||||
|
call void @llvm.assume(i1 %q)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare i1 @llvm.type.test(i8*, metadata) nounwind readnone
|
||||||
|
declare void @llvm.assume(i1)
|
@ -311,6 +311,7 @@ static const char *GetCodeName(unsigned CodeID, unsigned BlockID,
|
|||||||
STRINGIFY_CODE(FS, COMBINED_ALIAS)
|
STRINGIFY_CODE(FS, COMBINED_ALIAS)
|
||||||
STRINGIFY_CODE(FS, COMBINED_ORIGINAL_NAME)
|
STRINGIFY_CODE(FS, COMBINED_ORIGINAL_NAME)
|
||||||
STRINGIFY_CODE(FS, VERSION)
|
STRINGIFY_CODE(FS, VERSION)
|
||||||
|
STRINGIFY_CODE(FS, TYPE_TESTS)
|
||||||
}
|
}
|
||||||
case bitc::METADATA_ATTACHMENT_ID:
|
case bitc::METADATA_ATTACHMENT_ID:
|
||||||
switch(CodeID) {
|
switch(CodeID) {
|
||||||
|
Loading…
Reference in New Issue
Block a user