summaryrefslogtreecommitdiffstats
path: root/llvm
diff options
context:
space:
mode:
Diffstat (limited to 'llvm')
-rw-r--r--llvm/include/llvm/Bitcode/LLVMBitCodes.h2
-rw-r--r--llvm/include/llvm/IR/ModuleSummaryIndex.h12
-rw-r--r--llvm/lib/Analysis/ModuleSummaryAnalysis.cpp34
-rw-r--r--llvm/lib/Bitcode/Reader/BitcodeReader.cpp14
-rw-r--r--llvm/lib/Bitcode/Writer/BitcodeWriter.cpp6
-rw-r--r--llvm/test/Bitcode/thinlto-type-tests.ll30
-rw-r--r--llvm/test/Bitcode/thinlto-unused-type-tests.ll13
-rw-r--r--llvm/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp1
8 files changed, 102 insertions, 10 deletions
diff --git a/llvm/include/llvm/Bitcode/LLVMBitCodes.h b/llvm/include/llvm/Bitcode/LLVMBitCodes.h
index 32a7fa8b7f2..86d378df784 100644
--- a/llvm/include/llvm/Bitcode/LLVMBitCodes.h
+++ b/llvm/include/llvm/Bitcode/LLVMBitCodes.h
@@ -213,6 +213,8 @@ enum GlobalValueSummarySymtabCodes {
FS_COMBINED_ORIGINAL_NAME = 9,
// VERSION of the summary, bumped when adding flags for instance.
FS_VERSION = 10,
+ // The list of llvm.type.test type identifiers used by the following function.
+ FS_TYPE_TESTS = 11,
};
enum MetadataCodes {
diff --git a/llvm/include/llvm/IR/ModuleSummaryIndex.h b/llvm/include/llvm/IR/ModuleSummaryIndex.h
index c2977fd0972..53df1bdb40c 100644
--- a/llvm/include/llvm/IR/ModuleSummaryIndex.h
+++ b/llvm/include/llvm/IR/ModuleSummaryIndex.h
@@ -284,12 +284,17 @@ private:
/// List of <CalleeValueInfo, CalleeInfo> call edge pairs from this function.
std::vector<EdgeTy> CallGraphEdgeList;
+ /// List of type identifiers used by this function, represented as GUIDs.
+ std::vector<GlobalValue::GUID> TypeIdList;
+
public:
/// Summary constructors.
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)),
- InstCount(NumInsts), CallGraphEdgeList(std::move(CGEdges)) {}
+ InstCount(NumInsts), CallGraphEdgeList(std::move(CGEdges)),
+ TypeIdList(std::move(TypeIds)) {}
/// Check if this is a function summary.
static bool classof(const GlobalValueSummary *GVS) {
@@ -301,6 +306,9 @@ public:
/// Return the list of <CalleeValueInfo, CalleeInfo> pairs.
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
diff --git a/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp b/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp
index d5ceb18b951..cc256f9c829 100644
--- a/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp
+++ b/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp
@@ -22,6 +22,7 @@
#include "llvm/Analysis/IndirectCallPromotionAnalysis.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/ProfileSummaryInfo.h"
+#include "llvm/Analysis/TypeMetadataUtils.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/Dominators.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.
MapVector<ValueInfo, CalleeInfo> CallGraphEdges;
SetVector<ValueInfo> RefEdges;
+ SetVector<GlobalValue::GUID> TypeTests;
ICallPromotionAnalysis ICallAnalysis;
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");
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) {
- // Skip intrinsics.
- if (CalledFunction->isIntrinsic())
- continue;
+ if (CalledFunction->isIntrinsic()) {
+ if (CalledFunction->getIntrinsicID() != Intrinsic::type_test)
+ 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
assert(CalledFunction->hasName());
auto ScaledCount = BFI ? BFI->getBlockProfileCount(&BB) : None;
@@ -160,7 +180,8 @@ static void computeFunctionSummary(ModuleSummaryIndex &Index, const Module &M,
GlobalValueSummary::GVFlags Flags(F);
auto FuncSummary = llvm::make_unique<FunctionSummary>(
- Flags, NumInsts, RefEdges.takeVector(), CallGraphEdges.takeVector());
+ Flags, NumInsts, RefEdges.takeVector(), CallGraphEdges.takeVector(),
+ TypeTests.takeVector());
if (HasInlineAsmMaybeReferencingInternal)
FuncSummary->setHasInlineAsmMaybeReferencingInternal();
Index.addGlobalValueSummary(F.getName(), std::move(FuncSummary));
@@ -280,7 +301,8 @@ ModuleSummaryIndex llvm::buildModuleSummaryIndex(
std::unique_ptr<FunctionSummary> Summary =
llvm::make_unique<FunctionSummary>(
GVFlags, 0, ArrayRef<ValueInfo>{},
- ArrayRef<FunctionSummary::EdgeTy>{});
+ ArrayRef<FunctionSummary::EdgeTy>{},
+ ArrayRef<GlobalValue::GUID>{});
Summary->setNoRename();
Index.addGlobalValueSummary(Name, std::move(Summary));
} else {
diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
index b719313bbf4..55f2af65255 100644
--- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -4847,6 +4847,7 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(
// "OriginalName" attachement.
GlobalValueSummary *LastSeenSummary = nullptr;
bool Combined = false;
+ std::vector<GlobalValue::GUID> PendingTypeTests;
while (true) {
BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
@@ -4912,7 +4913,8 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(
ArrayRef<uint64_t>(Record).slice(CallGraphEdgeStartIndex),
IsOldProfileFormat, HasProfile);
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);
FS->setModulePath(TheIndex.addModulePath(ModulePath, 0)->first());
FS->setOriginalName(GUID.second);
@@ -4985,7 +4987,8 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(
IsOldProfileFormat, HasProfile);
GlobalValue::GUID GUID = getGUIDFromValueId(ValueID).first;
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();
FS->setModulePath(ModuleIdMap[ModuleId]);
TheIndex.addGlobalValueSummary(GUID, std::move(FS));
@@ -5041,6 +5044,13 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(
LastSeenSummary->setOriginalName(OriginalName);
// Reset the LastSeenSummary
LastSeenSummary = nullptr;
+ break;
+ }
+ case bitc::FS_TYPE_TESTS: {
+ assert(PendingTypeTests.empty());
+ PendingTypeTests.insert(PendingTypeTests.end(), Record.begin(),
+ Record.end());
+ break;
}
}
}
diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
index 7984292cb0c..d2abf7cb39a 100644
--- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -3286,6 +3286,9 @@ void ModuleBitcodeWriter::writePerModuleFunctionSummaryRecord(
NameVals.push_back(ValueID);
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(FS->instCount());
NameVals.push_back(FS->refs().size());
@@ -3544,6 +3547,9 @@ void IndexBitcodeWriter::writeCombinedGlobalValueSummary() {
}
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(Index.getModuleId(FS->modulePath()));
NameVals.push_back(getEncodedGVSummaryFlags(FS->flags()));
diff --git a/llvm/test/Bitcode/thinlto-type-tests.ll b/llvm/test/Bitcode/thinlto-type-tests.ll
new file mode 100644
index 00000000000..4281fbba196
--- /dev/null
+++ b/llvm/test/Bitcode/thinlto-type-tests.ll
@@ -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
diff --git a/llvm/test/Bitcode/thinlto-unused-type-tests.ll b/llvm/test/Bitcode/thinlto-unused-type-tests.ll
new file mode 100644
index 00000000000..c2c5dd2f9a3
--- /dev/null
+++ b/llvm/test/Bitcode/thinlto-unused-type-tests.ll
@@ -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)
diff --git a/llvm/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp b/llvm/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp
index d866201723a..e494343bf87 100644
--- a/llvm/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp
+++ b/llvm/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp
@@ -311,6 +311,7 @@ static const char *GetCodeName(unsigned CodeID, unsigned BlockID,
STRINGIFY_CODE(FS, COMBINED_ALIAS)
STRINGIFY_CODE(FS, COMBINED_ORIGINAL_NAME)
STRINGIFY_CODE(FS, VERSION)
+ STRINGIFY_CODE(FS, TYPE_TESTS)
}
case bitc::METADATA_ATTACHMENT_ID:
switch(CodeID) {
OpenPOWER on IntegriCloud