[llvm] r294981 - IR: Type ID summary extensions for WPD; thread summary into WPD pass.
Peter Collingbourne via llvm-commits
llvm-commits at lists.llvm.org
Mon Feb 13 11:26:19 PST 2017
Author: pcc
Date: Mon Feb 13 13:26:18 2017
New Revision: 294981
URL: http://llvm.org/viewvc/llvm-project?rev=294981&view=rev
Log:
IR: Type ID summary extensions for WPD; thread summary into WPD pass.
Make the whole thing testable by adding YAML I/O support for the WPD
summary information and adding some negative tests that exercise the
YAML support.
Differential Revision: https://reviews.llvm.org/D29782
Added:
llvm/trunk/test/Transforms/WholeProgramDevirt/Inputs/
llvm/trunk/test/Transforms/WholeProgramDevirt/Inputs/import-indir.yaml
llvm/trunk/test/Transforms/WholeProgramDevirt/export-nothing.ll
llvm/trunk/test/Transforms/WholeProgramDevirt/import-indir.ll
Modified:
llvm/trunk/include/llvm/IR/ModuleSummaryIndex.h
llvm/trunk/include/llvm/IR/ModuleSummaryIndexYAML.h
llvm/trunk/include/llvm/Transforms/IPO.h
llvm/trunk/lib/Transforms/IPO/PassManagerBuilder.cpp
llvm/trunk/lib/Transforms/IPO/WholeProgramDevirt.cpp
llvm/trunk/test/Transforms/LowerTypeTests/export-allones.ll
llvm/trunk/test/Transforms/LowerTypeTests/export-bytearray.ll
llvm/trunk/test/Transforms/LowerTypeTests/export-inline.ll
Modified: llvm/trunk/include/llvm/IR/ModuleSummaryIndex.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/ModuleSummaryIndex.h?rev=294981&r1=294980&r2=294981&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/ModuleSummaryIndex.h (original)
+++ llvm/trunk/include/llvm/IR/ModuleSummaryIndex.h Mon Feb 13 13:26:18 2017
@@ -439,8 +439,40 @@ struct TypeTestResolution {
unsigned SizeM1BitWidth = 0;
};
+struct WholeProgramDevirtResolution {
+ enum Kind {
+ Indir, ///< Just do a regular virtual call
+ SingleImpl, ///< Single implementation devirtualization
+ } TheKind = Indir;
+
+ std::string SingleImplName;
+
+ struct ByArg {
+ enum Kind {
+ Indir, ///< Just do a regular virtual call
+ UniformRetVal, ///< Uniform return value optimization
+ UniqueRetVal, ///< Unique return value optimization
+ VirtualConstProp, ///< Virtual constant propagation
+ } TheKind = Indir;
+
+ /// Additional information for the resolution:
+ /// - UniformRetVal: the uniform return value.
+ /// - UniqueRetVal: the return value associated with the unique vtable (0 or
+ /// 1).
+ uint64_t Info = 0;
+ };
+
+ /// Resolutions for calls with all constant integer arguments (excluding the
+ /// first argument, "this"), where the key is the argument vector.
+ std::map<std::vector<uint64_t>, ByArg> ResByArg;
+};
+
struct TypeIdSummary {
TypeTestResolution TTRes;
+
+ /// Mapping from byte offset to whole-program devirt resolution for that
+ /// (typeid, byte offset) pair.
+ std::map<uint64_t, WholeProgramDevirtResolution> WPDRes;
};
/// 160 bits SHA1
Modified: llvm/trunk/include/llvm/IR/ModuleSummaryIndexYAML.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/ModuleSummaryIndexYAML.h?rev=294981&r1=294980&r2=294981&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/ModuleSummaryIndexYAML.h (original)
+++ llvm/trunk/include/llvm/IR/ModuleSummaryIndexYAML.h Mon Feb 13 13:26:18 2017
@@ -33,14 +33,106 @@ template <> struct MappingTraits<TypeTes
}
};
+template <>
+struct ScalarEnumerationTraits<WholeProgramDevirtResolution::ByArg::Kind> {
+ static void enumeration(IO &io,
+ WholeProgramDevirtResolution::ByArg::Kind &value) {
+ io.enumCase(value, "Indir", WholeProgramDevirtResolution::ByArg::Indir);
+ io.enumCase(value, "UniformRetVal",
+ WholeProgramDevirtResolution::ByArg::UniformRetVal);
+ io.enumCase(value, "UniqueRetVal",
+ WholeProgramDevirtResolution::ByArg::UniqueRetVal);
+ io.enumCase(value, "VirtualConstProp",
+ WholeProgramDevirtResolution::ByArg::VirtualConstProp);
+ }
+};
+
+template <> struct MappingTraits<WholeProgramDevirtResolution::ByArg> {
+ static void mapping(IO &io, WholeProgramDevirtResolution::ByArg &res) {
+ io.mapOptional("Kind", res.TheKind);
+ io.mapOptional("Info", res.Info);
+ }
+};
+
+template <>
+struct CustomMappingTraits<
+ std::map<std::vector<uint64_t>, WholeProgramDevirtResolution::ByArg>> {
+ static void inputOne(
+ IO &io, StringRef Key,
+ std::map<std::vector<uint64_t>, WholeProgramDevirtResolution::ByArg> &V) {
+ std::vector<uint64_t> Args;
+ std::pair<StringRef, StringRef> P = {"", Key};
+ while (!P.second.empty()) {
+ P = P.second.split(',');
+ uint64_t Arg;
+ if (P.first.getAsInteger(0, Arg)) {
+ io.setError("key not an integer");
+ return;
+ }
+ Args.push_back(Arg);
+ }
+ io.mapRequired(Key.str().c_str(), V[Args]);
+ }
+ static void output(
+ IO &io,
+ std::map<std::vector<uint64_t>, WholeProgramDevirtResolution::ByArg> &V) {
+ for (auto &P : V) {
+ std::string Key;
+ for (uint64_t Arg : P.first) {
+ if (!Key.empty())
+ Key += ',';
+ Key += llvm::utostr(Arg);
+ }
+ io.mapRequired(Key.c_str(), P.second);
+ }
+ }
+};
+
+template <> struct ScalarEnumerationTraits<WholeProgramDevirtResolution::Kind> {
+ static void enumeration(IO &io, WholeProgramDevirtResolution::Kind &value) {
+ io.enumCase(value, "Indir", WholeProgramDevirtResolution::Indir);
+ io.enumCase(value, "SingleImpl", WholeProgramDevirtResolution::SingleImpl);
+ }
+};
+
+template <> struct MappingTraits<WholeProgramDevirtResolution> {
+ static void mapping(IO &io, WholeProgramDevirtResolution &res) {
+ io.mapOptional("Kind", res.TheKind);
+ io.mapOptional("SingleImplName", res.SingleImplName);
+ io.mapOptional("ResByArg", res.ResByArg);
+ }
+};
+
+template <>
+struct CustomMappingTraits<std::map<uint64_t, WholeProgramDevirtResolution>> {
+ static void inputOne(IO &io, StringRef Key,
+ std::map<uint64_t, WholeProgramDevirtResolution> &V) {
+ uint64_t KeyInt;
+ if (Key.getAsInteger(0, KeyInt)) {
+ io.setError("key not an integer");
+ return;
+ }
+ io.mapRequired(Key.str().c_str(), V[KeyInt]);
+ }
+ static void output(IO &io, std::map<uint64_t, WholeProgramDevirtResolution> &V) {
+ for (auto &P : V)
+ io.mapRequired(llvm::utostr(P.first).c_str(), P.second);
+ }
+};
+
template <> struct MappingTraits<TypeIdSummary> {
static void mapping(IO &io, TypeIdSummary& summary) {
io.mapOptional("TTRes", summary.TTRes);
+ io.mapOptional("WPDRes", summary.WPDRes);
}
};
struct FunctionSummaryYaml {
std::vector<uint64_t> TypeTests;
+ std::vector<FunctionSummary::VFuncId> TypeTestAssumeVCalls,
+ TypeCheckedLoadVCalls;
+ std::vector<FunctionSummary::ConstVCall> TypeTestAssumeConstVCalls,
+ TypeCheckedLoadConstVCalls;
};
} // End yaml namespace
@@ -51,9 +143,38 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(uint64_t)
namespace llvm {
namespace yaml {
+template <> struct MappingTraits<FunctionSummary::VFuncId> {
+ static void mapping(IO &io, FunctionSummary::VFuncId& id) {
+ io.mapOptional("GUID", id.GUID);
+ io.mapOptional("Offset", id.Offset);
+ }
+};
+
+template <> struct MappingTraits<FunctionSummary::ConstVCall> {
+ static void mapping(IO &io, FunctionSummary::ConstVCall& id) {
+ io.mapOptional("VFunc", id.VFunc);
+ io.mapOptional("Args", id.Args);
+ }
+};
+
+} // End yaml namespace
+} // End llvm namespace
+
+LLVM_YAML_IS_SEQUENCE_VECTOR(FunctionSummary::VFuncId)
+LLVM_YAML_IS_SEQUENCE_VECTOR(FunctionSummary::ConstVCall)
+
+namespace llvm {
+namespace yaml {
+
template <> struct MappingTraits<FunctionSummaryYaml> {
static void mapping(IO &io, FunctionSummaryYaml& summary) {
io.mapOptional("TypeTests", summary.TypeTests);
+ io.mapOptional("TypeTestAssumeVCalls", summary.TypeTestAssumeVCalls);
+ io.mapOptional("TypeCheckedLoadVCalls", summary.TypeCheckedLoadVCalls);
+ io.mapOptional("TypeTestAssumeConstVCalls",
+ summary.TypeTestAssumeConstVCalls);
+ io.mapOptional("TypeCheckedLoadConstVCalls",
+ summary.TypeCheckedLoadConstVCalls);
}
};
@@ -83,10 +204,10 @@ template <> struct CustomMappingTraits<G
Elem.push_back(llvm::make_unique<FunctionSummary>(
GVFlags, 0, ArrayRef<ValueInfo>{},
ArrayRef<FunctionSummary::EdgeTy>{}, std::move(FSum.TypeTests),
- ArrayRef<FunctionSummary::VFuncId>{},
- ArrayRef<FunctionSummary::VFuncId>{},
- ArrayRef<FunctionSummary::ConstVCall>{},
- ArrayRef<FunctionSummary::ConstVCall>{}));
+ std::move(FSum.TypeTestAssumeVCalls),
+ std::move(FSum.TypeCheckedLoadVCalls),
+ std::move(FSum.TypeTestAssumeConstVCalls),
+ std::move(FSum.TypeCheckedLoadConstVCalls)));
}
}
static void output(IO &io, GlobalValueSummaryMapTy &V) {
@@ -94,7 +215,11 @@ template <> struct CustomMappingTraits<G
std::vector<FunctionSummaryYaml> FSums;
for (auto &Sum : P.second) {
if (auto *FSum = dyn_cast<FunctionSummary>(Sum.get()))
- FSums.push_back(FunctionSummaryYaml{FSum->type_tests()});
+ FSums.push_back(FunctionSummaryYaml{
+ FSum->type_tests(), FSum->type_test_assume_vcalls(),
+ FSum->type_checked_load_vcalls(),
+ FSum->type_test_assume_const_vcalls(),
+ FSum->type_checked_load_const_vcalls()});
}
if (!FSums.empty())
io.mapRequired(llvm::utostr(P.first).c_str(), FSums);
Modified: llvm/trunk/include/llvm/Transforms/IPO.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/IPO.h?rev=294981&r1=294980&r2=294981&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Transforms/IPO.h (original)
+++ llvm/trunk/include/llvm/Transforms/IPO.h Mon Feb 13 13:26:18 2017
@@ -235,7 +235,8 @@ ModulePass *createCrossDSOCFIPass();
/// \brief This pass implements whole-program devirtualization using type
/// metadata.
-ModulePass *createWholeProgramDevirtPass();
+ModulePass *createWholeProgramDevirtPass(PassSummaryAction Action,
+ ModuleSummaryIndex *Index);
/// This pass splits globals into pieces for the benefit of whole-program
/// devirtualization and control-flow integrity.
Modified: llvm/trunk/lib/Transforms/IPO/PassManagerBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/PassManagerBuilder.cpp?rev=294981&r1=294980&r2=294981&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/IPO/PassManagerBuilder.cpp (original)
+++ llvm/trunk/lib/Transforms/IPO/PassManagerBuilder.cpp Mon Feb 13 13:26:18 2017
@@ -700,7 +700,8 @@ void PassManagerBuilder::addLTOOptimizat
PM.add(createGlobalSplitPass());
// Apply whole-program devirtualization and virtual constant propagation.
- PM.add(createWholeProgramDevirtPass());
+ PM.add(createWholeProgramDevirtPass(
+ Summary ? PassSummaryAction::Export : PassSummaryAction::None, Summary));
// That's all we need at opt level 1.
if (OptLevel == 1)
Modified: llvm/trunk/lib/Transforms/IPO/WholeProgramDevirt.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/WholeProgramDevirt.cpp?rev=294981&r1=294980&r2=294981&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/IPO/WholeProgramDevirt.cpp (original)
+++ llvm/trunk/lib/Transforms/IPO/WholeProgramDevirt.cpp Mon Feb 13 13:26:18 2017
@@ -54,10 +54,13 @@
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/Module.h"
+#include "llvm/IR/ModuleSummaryIndexYAML.h"
#include "llvm/Pass.h"
#include "llvm/PassRegistry.h"
#include "llvm/PassSupport.h"
#include "llvm/Support/Casting.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/Utils/Evaluator.h"
@@ -72,6 +75,26 @@ using namespace wholeprogramdevirt;
#define DEBUG_TYPE "wholeprogramdevirt"
+static cl::opt<PassSummaryAction> ClSummaryAction(
+ "wholeprogramdevirt-summary-action",
+ cl::desc("What to do with the summary when running this pass"),
+ cl::values(clEnumValN(PassSummaryAction::None, "none", "Do nothing"),
+ clEnumValN(PassSummaryAction::Import, "import",
+ "Import typeid resolutions from summary and globals"),
+ clEnumValN(PassSummaryAction::Export, "export",
+ "Export typeid resolutions to summary and globals")),
+ cl::Hidden);
+
+static cl::opt<std::string> ClReadSummary(
+ "wholeprogramdevirt-read-summary",
+ cl::desc("Read summary from given YAML file before running pass"),
+ cl::Hidden);
+
+static cl::opt<std::string> ClWriteSummary(
+ "wholeprogramdevirt-write-summary",
+ cl::desc("Write summary to given YAML file after running pass"),
+ cl::Hidden);
+
// Find the minimum offset that we may store a value of size Size bits at. If
// IsAfter is set, look for an offset before the object, otherwise look for an
// offset after the object.
@@ -261,6 +284,10 @@ struct VirtualCallSite {
struct DevirtModule {
Module &M;
+
+ PassSummaryAction Action;
+ ModuleSummaryIndex *Summary;
+
IntegerType *Int8Ty;
PointerType *Int8PtrTy;
IntegerType *Int32Ty;
@@ -279,8 +306,9 @@ struct DevirtModule {
// true.
std::map<CallInst *, unsigned> NumUnsafeUsesForTypeTest;
- DevirtModule(Module &M)
- : M(M), Int8Ty(Type::getInt8Ty(M.getContext())),
+ DevirtModule(Module &M, PassSummaryAction Action, ModuleSummaryIndex *Summary)
+ : M(M), Action(Action), Summary(Summary),
+ Int8Ty(Type::getInt8Ty(M.getContext())),
Int8PtrTy(Type::getInt8PtrTy(M.getContext())),
Int32Ty(Type::getInt32Ty(M.getContext())),
RemarksEnabled(areRemarksEnabled()) {}
@@ -315,20 +343,35 @@ struct DevirtModule {
void rebuildGlobal(VTableBits &B);
bool run();
+
+ // Lower the module using the action and summary passed as command line
+ // arguments. For testing purposes only.
+ static bool runForTesting(Module &M);
};
struct WholeProgramDevirt : public ModulePass {
static char ID;
- WholeProgramDevirt() : ModulePass(ID) {
+ bool UseCommandLine = false;
+
+ PassSummaryAction Action;
+ ModuleSummaryIndex *Summary;
+
+ WholeProgramDevirt() : ModulePass(ID), UseCommandLine(true) {
+ initializeWholeProgramDevirtPass(*PassRegistry::getPassRegistry());
+ }
+
+ WholeProgramDevirt(PassSummaryAction Action, ModuleSummaryIndex *Summary)
+ : ModulePass(ID), Action(Action), Summary(Summary) {
initializeWholeProgramDevirtPass(*PassRegistry::getPassRegistry());
}
bool runOnModule(Module &M) override {
if (skipModule(M))
return false;
-
- return DevirtModule(M).run();
+ if (UseCommandLine)
+ return DevirtModule::runForTesting(M);
+ return DevirtModule(M, Action, Summary).run();
}
};
@@ -338,17 +381,50 @@ INITIALIZE_PASS(WholeProgramDevirt, "who
"Whole program devirtualization", false, false)
char WholeProgramDevirt::ID = 0;
-ModulePass *llvm::createWholeProgramDevirtPass() {
- return new WholeProgramDevirt;
+ModulePass *llvm::createWholeProgramDevirtPass(PassSummaryAction Action,
+ ModuleSummaryIndex *Summary) {
+ return new WholeProgramDevirt(Action, Summary);
}
PreservedAnalyses WholeProgramDevirtPass::run(Module &M,
ModuleAnalysisManager &) {
- if (!DevirtModule(M).run())
+ if (!DevirtModule(M, PassSummaryAction::None, nullptr).run())
return PreservedAnalyses::all();
return PreservedAnalyses::none();
}
+bool DevirtModule::runForTesting(Module &M) {
+ ModuleSummaryIndex Summary;
+
+ // Handle the command-line summary arguments. This code is for testing
+ // purposes only, so we handle errors directly.
+ if (!ClReadSummary.empty()) {
+ ExitOnError ExitOnErr("-wholeprogramdevirt-read-summary: " + ClReadSummary +
+ ": ");
+ auto ReadSummaryFile =
+ ExitOnErr(errorOrToExpected(MemoryBuffer::getFile(ClReadSummary)));
+
+ yaml::Input In(ReadSummaryFile->getBuffer());
+ In >> Summary;
+ ExitOnErr(errorCodeToError(In.error()));
+ }
+
+ bool Changed = DevirtModule(M, ClSummaryAction, &Summary).run();
+
+ if (!ClWriteSummary.empty()) {
+ ExitOnError ExitOnErr(
+ "-wholeprogramdevirt-write-summary: " + ClWriteSummary + ": ");
+ std::error_code EC;
+ raw_fd_ostream OS(ClWriteSummary, EC, sys::fs::F_Text);
+ ExitOnErr(errorCodeToError(EC));
+
+ yaml::Output Out(OS);
+ Out << Summary;
+ }
+
+ return Changed;
+}
+
void DevirtModule::buildTypeIdentifierMap(
std::vector<VTableBits> &Bits,
DenseMap<Metadata *, std::set<TypeMemberInfo>> &TypeIdMap) {
Modified: llvm/trunk/test/Transforms/LowerTypeTests/export-allones.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LowerTypeTests/export-allones.ll?rev=294981&r1=294980&r2=294981&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/LowerTypeTests/export-allones.ll (original)
+++ llvm/trunk/test/Transforms/LowerTypeTests/export-allones.ll Mon Feb 13 13:26:18 2017
@@ -153,7 +153,9 @@
; SUMMARY-NEXT: TTRes:
; SUMMARY-NEXT: Kind: AllOnes
; SUMMARY-NEXT: SizeM1BitWidth: 7
+; SUMMARY-NEXT: WPDRes:
; SUMMARY-NEXT: typeid2:
; SUMMARY-NEXT: TTRes:
; SUMMARY-NEXT: Kind: AllOnes
; SUMMARY-NEXT: SizeM1BitWidth: 32
+; SUMMARY-NEXT: WPDRes:
Modified: llvm/trunk/test/Transforms/LowerTypeTests/export-bytearray.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LowerTypeTests/export-bytearray.ll?rev=294981&r1=294980&r2=294981&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/LowerTypeTests/export-bytearray.ll (original)
+++ llvm/trunk/test/Transforms/LowerTypeTests/export-bytearray.ll Mon Feb 13 13:26:18 2017
@@ -32,7 +32,9 @@
; SUMMARY-NEXT: TTRes:
; SUMMARY-NEXT: Kind: ByteArray
; SUMMARY-NEXT: SizeM1BitWidth: 7
+; SUMMARY-NEXT: WPDRes:
; SUMMARY-NEXT: typeid2:
; SUMMARY-NEXT: TTRes:
; SUMMARY-NEXT: Kind: ByteArray
; SUMMARY-NEXT: SizeM1BitWidth: 32
+; SUMMARY-NEXT: WPDRes:
Modified: llvm/trunk/test/Transforms/LowerTypeTests/export-inline.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LowerTypeTests/export-inline.ll?rev=294981&r1=294980&r2=294981&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/LowerTypeTests/export-inline.ll (original)
+++ llvm/trunk/test/Transforms/LowerTypeTests/export-inline.ll Mon Feb 13 13:26:18 2017
@@ -27,7 +27,9 @@
; SUMMARY-NEXT: TTRes:
; SUMMARY-NEXT: Kind: Inline
; SUMMARY-NEXT: SizeM1BitWidth: 5
+; SUMMARY-NEXT: WPDRes:
; SUMMARY-NEXT: typeid2:
; SUMMARY-NEXT: TTRes:
; SUMMARY-NEXT: Kind: Inline
; SUMMARY-NEXT: SizeM1BitWidth: 6
+; SUMMARY-NEXT: WPDRes:
Added: llvm/trunk/test/Transforms/WholeProgramDevirt/Inputs/import-indir.yaml
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/WholeProgramDevirt/Inputs/import-indir.yaml?rev=294981&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/WholeProgramDevirt/Inputs/import-indir.yaml (added)
+++ llvm/trunk/test/Transforms/WholeProgramDevirt/Inputs/import-indir.yaml Mon Feb 13 13:26:18 2017
@@ -0,0 +1,41 @@
+---
+GlobalValueMap:
+ 42:
+ - TypeTestAssumeVCalls:
+ - GUID: 123
+ Offset: 0
+ - GUID: 456
+ Offset: 4
+ TypeCheckedLoadVCalls:
+ - GUID: 789
+ Offset: 8
+ - GUID: 1234
+ Offset: 16
+ TypeTestAssumeConstVCalls:
+ - VFunc:
+ GUID: 123
+ Offset: 4
+ Args: [12, 24]
+ TypeCheckedLoadConstVCalls:
+ - VFunc:
+ GUID: 456
+ Offset: 8
+ Args: [24, 12]
+TypeIdMap:
+ typeid1:
+ WPDRes:
+ 0:
+ Kind: Indir
+ 4:
+ Kind: Indir
+ ResByArg:
+ "":
+ Kind: UniformRetVal
+ Info: 12
+ 12:
+ Kind: UniformRetVal
+ Info: 24
+ "12,24":
+ Kind: UniformRetVal
+ Info: 48
+...
Added: llvm/trunk/test/Transforms/WholeProgramDevirt/export-nothing.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/WholeProgramDevirt/export-nothing.ll?rev=294981&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/WholeProgramDevirt/export-nothing.ll (added)
+++ llvm/trunk/test/Transforms/WholeProgramDevirt/export-nothing.ll Mon Feb 13 13:26:18 2017
@@ -0,0 +1,7 @@
+; RUN: opt -wholeprogramdevirt -wholeprogramdevirt-summary-action=export -wholeprogramdevirt-write-summary=%t -o /dev/null %s
+; RUN: FileCheck %s < %t
+
+; CHECK: ---
+; CHECK-NEXT: GlobalValueMap:
+; CHECK-NEXT: TypeIdMap:
+; CHECK-NEXT: ...
Added: llvm/trunk/test/Transforms/WholeProgramDevirt/import-indir.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/WholeProgramDevirt/import-indir.ll?rev=294981&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/WholeProgramDevirt/import-indir.ll (added)
+++ llvm/trunk/test/Transforms/WholeProgramDevirt/import-indir.ll Mon Feb 13 13:26:18 2017
@@ -0,0 +1,99 @@
+; Test that we correctly import an indir resolution for type identifier "typeid1".
+; RUN: opt -S -wholeprogramdevirt -wholeprogramdevirt-summary-action=import -wholeprogramdevirt-read-summary=%S/Inputs/import-indir.yaml -wholeprogramdevirt-write-summary=%t < %s | FileCheck %s
+; RUN: FileCheck --check-prefix=SUMMARY %s < %t
+
+; SUMMARY: GlobalValueMap:
+; SUMMARY-NEXT: 42:
+; SUMMARY-NEXT: - TypeTests:
+; SUMMARY-NEXT: TypeTestAssumeVCalls:
+; SUMMARY-NEXT: - GUID: 123
+; SUMMARY-NEXT: Offset: 0
+; SUMMARY-NEXT: - GUID: 456
+; SUMMARY-NEXT: Offset: 4
+; SUMMARY-NEXT: TypeCheckedLoadVCalls:
+; SUMMARY-NEXT: - GUID: 789
+; SUMMARY-NEXT: Offset: 8
+; SUMMARY-NEXT: - GUID: 1234
+; SUMMARY-NEXT: Offset: 16
+; SUMMARY-NEXT: TypeTestAssumeConstVCalls:
+; SUMMARY-NEXT: - VFunc:
+; SUMMARY-NEXT: GUID: 123
+; SUMMARY-NEXT: Offset: 4
+; SUMMARY-NEXT: Args:
+; SUMMARY-NEXT: - 12
+; SUMMARY-NEXT: - 24
+; SUMMARY-NEXT: TypeCheckedLoadConstVCalls:
+; SUMMARY-NEXT: - VFunc:
+; SUMMARY-NEXT: GUID: 456
+; SUMMARY-NEXT: Offset: 8
+; SUMMARY-NEXT: Args:
+; SUMMARY-NEXT: - 24
+; SUMMARY-NEXT: - 12
+; SUMMARY-NEXT: TypeIdMap:
+; SUMMARY-NEXT: typeid1:
+; SUMMARY-NEXT: TTRes:
+; SUMMARY-NEXT: Kind: Unsat
+; SUMMARY-NEXT: SizeM1BitWidth: 0
+; SUMMARY-NEXT: WPDRes:
+; SUMMARY-NEXT: 0:
+; SUMMARY-NEXT: Kind: Indir
+; SUMMARY-NEXT: SingleImplName: ''
+; SUMMARY-NEXT: ResByArg:
+; SUMMARY-NEXT: 4:
+; SUMMARY-NEXT: Kind: Indir
+; SUMMARY-NEXT: SingleImplName: ''
+; SUMMARY-NEXT: ResByArg:
+; SUMMARY-NEXT: :
+; SUMMARY-NEXT: Kind: UniformRetVal
+; SUMMARY-NEXT: Info: 12
+; SUMMARY-NEXT: 12:
+; SUMMARY-NEXT: Kind: UniformRetVal
+; SUMMARY-NEXT: Info: 24
+; SUMMARY-NEXT: 12,24:
+; SUMMARY-NEXT: Kind: UniformRetVal
+; SUMMARY-NEXT: Info: 48
+
+target datalayout = "e-p:32:32"
+
+declare void @llvm.assume(i1)
+declare void @llvm.trap()
+declare {i8*, i1} @llvm.type.checked.load(i8*, i32, metadata)
+declare i1 @llvm.type.test(i8*, metadata)
+
+; CHECK: define i1 @f1
+define i1 @f1(i8* %obj) {
+ %vtableptr = bitcast i8* %obj to [1 x i8*]**
+ %vtable = load [1 x i8*]*, [1 x i8*]** %vtableptr
+ %vtablei8 = bitcast [1 x i8*]* %vtable to i8*
+ %p = call i1 @llvm.type.test(i8* %vtablei8, metadata !"typeid1")
+ call void @llvm.assume(i1 %p)
+ %fptrptr = getelementptr [1 x i8*], [1 x i8*]* %vtable, i32 0, i32 0
+ %fptr = load i8*, i8** %fptrptr
+ %fptr_casted = bitcast i8* %fptr to i1 (i8*, i32)*
+ ; CHECK: call i1 %
+ %result = call i1 %fptr_casted(i8* %obj, i32 5)
+ ret i1 %result
+}
+
+; CHECK: define i1 @f2
+define i1 @f2(i8* %obj) {
+ %vtableptr = bitcast i8* %obj to [1 x i8*]**
+ %vtable = load [1 x i8*]*, [1 x i8*]** %vtableptr
+ %vtablei8 = bitcast [1 x i8*]* %vtable to i8*
+ %pair = call {i8*, i1} @llvm.type.checked.load(i8* %vtablei8, i32 4, metadata !"typeid1")
+ %fptr = extractvalue {i8*, i1} %pair, 0
+ %p = extractvalue {i8*, i1} %pair, 1
+ ; CHECK: [[P:%.*]] = call i1 @llvm.type.test
+ ; CHECK: br i1 [[P]]
+ br i1 %p, label %cont, label %trap
+
+cont:
+ %fptr_casted = bitcast i8* %fptr to i1 (i8*, i32)*
+ ; CHECK: call i1 %
+ %result = call i1 %fptr_casted(i8* %obj, i32 undef)
+ ret i1 %result
+
+trap:
+ call void @llvm.trap()
+ unreachable
+}
More information about the llvm-commits
mailing list