diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2016-01-13 19:58:01 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2016-01-13 19:58:01 +0000 |
commit | 050e163ae8b4bb6eb252b59e2f8f36e68ae9239d (patch) | |
tree | 7376a0c71aad05d327e5b1dcbceb3311a10f9f29 /unittests | |
parent | 8a6c1c25bce0267ee4072bd7b786b921e8a66a35 (diff) | |
download | src-test2-050e163ae8b4bb6eb252b59e2f8f36e68ae9239d.tar.gz src-test2-050e163ae8b4bb6eb252b59e2f8f36e68ae9239d.zip |
Notes
Diffstat (limited to 'unittests')
-rw-r--r-- | unittests/ADT/CMakeLists.txt | 2 | ||||
-rw-r--r-- | unittests/ADT/PointerEmbeddedIntTest.cpp | 46 | ||||
-rw-r--r-- | unittests/ADT/PointerIntPairTest.cpp | 27 | ||||
-rw-r--r-- | unittests/ADT/PointerSumTypeTest.cpp | 113 | ||||
-rw-r--r-- | unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp | 5 | ||||
-rw-r--r-- | unittests/ExecutionEngine/Orc/CMakeLists.txt | 1 | ||||
-rw-r--r-- | unittests/ExecutionEngine/Orc/ObjectLinkingLayerTest.cpp | 82 | ||||
-rw-r--r-- | unittests/ExecutionEngine/Orc/OrcTestCommon.cpp | 6 | ||||
-rw-r--r-- | unittests/ExecutionEngine/Orc/OrcTestCommon.h | 2 | ||||
-rw-r--r-- | unittests/ExecutionEngine/Orc/RPCUtilsTest.cpp | 147 | ||||
-rw-r--r-- | unittests/IR/AsmWriterTest.cpp | 37 | ||||
-rw-r--r-- | unittests/IR/CMakeLists.txt | 1 | ||||
-rw-r--r-- | unittests/IR/IRBuilderTest.cpp | 16 | ||||
-rw-r--r-- | unittests/ProfileData/InstrProfTest.cpp | 140 | ||||
-rw-r--r-- | unittests/Support/MathExtrasTest.cpp | 54 |
15 files changed, 632 insertions, 47 deletions
diff --git a/unittests/ADT/CMakeLists.txt b/unittests/ADT/CMakeLists.txt index cb878c61b85f..bce1bf93a338 100644 --- a/unittests/ADT/CMakeLists.txt +++ b/unittests/ADT/CMakeLists.txt @@ -25,7 +25,9 @@ set(ADTSources MapVectorTest.cpp OptionalTest.cpp PackedVectorTest.cpp + PointerEmbeddedIntTest.cpp PointerIntPairTest.cpp + PointerSumTypeTest.cpp PointerUnionTest.cpp PostOrderIteratorTest.cpp RangeAdapterTest.cpp diff --git a/unittests/ADT/PointerEmbeddedIntTest.cpp b/unittests/ADT/PointerEmbeddedIntTest.cpp new file mode 100644 index 000000000000..b10365a2f618 --- /dev/null +++ b/unittests/ADT/PointerEmbeddedIntTest.cpp @@ -0,0 +1,46 @@ +//===- llvm/unittest/ADT/PointerEmbeddedIntTest.cpp -----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "gtest/gtest.h" +#include "llvm/ADT/PointerEmbeddedInt.h" +using namespace llvm; + +namespace { + +TEST(PointerEmbeddedIntTest, Basic) { + PointerEmbeddedInt<int, CHAR_BIT> I = 42, J = 43; + + EXPECT_EQ(42, I); + EXPECT_EQ(43, I + 1); + EXPECT_EQ(sizeof(uintptr_t) * CHAR_BIT - CHAR_BIT, + PointerLikeTypeTraits<decltype(I)>::NumLowBitsAvailable); + + EXPECT_FALSE(I == J); + EXPECT_TRUE(I != J); + EXPECT_TRUE(I < J); + EXPECT_FALSE(I > J); + EXPECT_TRUE(I <= J); + EXPECT_FALSE(I >= J); + + EXPECT_FALSE(I == 43); + EXPECT_TRUE(I != 43); + EXPECT_TRUE(I < 43); + EXPECT_FALSE(I > 43); + EXPECT_TRUE(I <= 43); + EXPECT_FALSE(I >= 43); + + EXPECT_FALSE(42 == J); + EXPECT_TRUE(42 != J); + EXPECT_TRUE(42 < J); + EXPECT_FALSE(42 > J); + EXPECT_TRUE(42 <= J); + EXPECT_FALSE(42 >= J); +} + +} // end anonymous namespace diff --git a/unittests/ADT/PointerIntPairTest.cpp b/unittests/ADT/PointerIntPairTest.cpp index e27a5823a51e..13680c78b9bb 100644 --- a/unittests/ADT/PointerIntPairTest.cpp +++ b/unittests/ADT/PointerIntPairTest.cpp @@ -35,6 +35,33 @@ TEST(PointerIntPairTest, GetSet) { Pair.setPointerAndInt(&s, 3U); EXPECT_EQ(&s, Pair.getPointer()); EXPECT_EQ(3U, Pair.getInt()); + + // Make sure that we can perform all of our operations on enum classes. + // + // The concern is that enum classes are only explicitly convertible to + // integers. This means that if we assume in PointerIntPair this, a + // compilation error will result. This group of tests exercises the enum class + // code to make sure that we do not run into such issues in the future. + enum class E : unsigned { + Case1, + Case2, + Case3, + }; + PointerIntPair<S *, 2, E> Pair2(&s, E::Case1); + EXPECT_EQ(&s, Pair2.getPointer()); + EXPECT_EQ(E::Case1, Pair2.getInt()); + + Pair2.setInt(E::Case2); + EXPECT_EQ(&s, Pair2.getPointer()); + EXPECT_EQ(E::Case2, Pair2.getInt()); + + Pair2.setPointer(nullptr); + EXPECT_EQ(nullptr, Pair2.getPointer()); + EXPECT_EQ(E::Case2, Pair2.getInt()); + + Pair2.setPointerAndInt(&s, E::Case3); + EXPECT_EQ(&s, Pair2.getPointer()); + EXPECT_EQ(E::Case3, Pair2.getInt()); } TEST(PointerIntPairTest, DefaultInitialize) { diff --git a/unittests/ADT/PointerSumTypeTest.cpp b/unittests/ADT/PointerSumTypeTest.cpp new file mode 100644 index 000000000000..75c88f7fee9f --- /dev/null +++ b/unittests/ADT/PointerSumTypeTest.cpp @@ -0,0 +1,113 @@ +//===- llvm/unittest/ADT/PointerSumTypeTest.cpp ---------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "gtest/gtest.h" +#include "llvm/ADT/PointerSumType.h" +using namespace llvm; + +namespace { + +struct PointerSumTypeTest : public testing::Test { + enum Kinds { Float, Int1, Int2 }; + float f; + int i1, i2; + + typedef PointerSumType<Kinds, PointerSumTypeMember<Float, float *>, + PointerSumTypeMember<Int1, int *>, + PointerSumTypeMember<Int2, int *>> + SumType; + SumType a, b, c, n; + + PointerSumTypeTest() + : f(3.14f), i1(42), i2(-1), a(SumType::create<Float>(&f)), + b(SumType::create<Int1>(&i1)), c(SumType::create<Int2>(&i2)), n() {} +}; + +TEST_F(PointerSumTypeTest, NullTest) { + EXPECT_TRUE(a); + EXPECT_TRUE(b); + EXPECT_TRUE(c); + EXPECT_FALSE(n); +} + +TEST_F(PointerSumTypeTest, GetTag) { + EXPECT_EQ(Float, a.getTag()); + EXPECT_EQ(Int1, b.getTag()); + EXPECT_EQ(Int2, c.getTag()); + EXPECT_EQ((Kinds)0, n.getTag()); +} + +TEST_F(PointerSumTypeTest, Is) { + EXPECT_TRUE(a.is<Float>()); + EXPECT_FALSE(a.is<Int1>()); + EXPECT_FALSE(a.is<Int2>()); + EXPECT_FALSE(b.is<Float>()); + EXPECT_TRUE(b.is<Int1>()); + EXPECT_FALSE(b.is<Int2>()); + EXPECT_FALSE(c.is<Float>()); + EXPECT_FALSE(c.is<Int1>()); + EXPECT_TRUE(c.is<Int2>()); +} + +TEST_F(PointerSumTypeTest, Get) { + EXPECT_EQ(&f, a.get<Float>()); + EXPECT_EQ(nullptr, a.get<Int1>()); + EXPECT_EQ(nullptr, a.get<Int2>()); + EXPECT_EQ(nullptr, b.get<Float>()); + EXPECT_EQ(&i1, b.get<Int1>()); + EXPECT_EQ(nullptr, b.get<Int2>()); + EXPECT_EQ(nullptr, c.get<Float>()); + EXPECT_EQ(nullptr, c.get<Int1>()); + EXPECT_EQ(&i2, c.get<Int2>()); + + // Note that we can use .get even on a null sum type. It just always produces + // a null pointer, even if one of the discriminants is null. + EXPECT_EQ(nullptr, n.get<Float>()); + EXPECT_EQ(nullptr, n.get<Int1>()); + EXPECT_EQ(nullptr, n.get<Int2>()); +} + +TEST_F(PointerSumTypeTest, Cast) { + EXPECT_EQ(&f, a.cast<Float>()); + EXPECT_EQ(&i1, b.cast<Int1>()); + EXPECT_EQ(&i2, c.cast<Int2>()); +} + +TEST_F(PointerSumTypeTest, Assignment) { + b = SumType::create<Int2>(&i2); + EXPECT_EQ(nullptr, b.get<Float>()); + EXPECT_EQ(nullptr, b.get<Int1>()); + EXPECT_EQ(&i2, b.get<Int2>()); + + b = SumType::create<Int2>(&i1); + EXPECT_EQ(nullptr, b.get<Float>()); + EXPECT_EQ(nullptr, b.get<Int1>()); + EXPECT_EQ(&i1, b.get<Int2>()); + + float Local = 1.616f; + b = SumType::create<Float>(&Local); + EXPECT_EQ(&Local, b.get<Float>()); + EXPECT_EQ(nullptr, b.get<Int1>()); + EXPECT_EQ(nullptr, b.get<Int2>()); + + n = SumType::create<Int1>(&i2); + EXPECT_TRUE(n); + EXPECT_EQ(nullptr, n.get<Float>()); + EXPECT_EQ(&i2, n.get<Int1>()); + EXPECT_EQ(nullptr, n.get<Int2>()); + + n = SumType::create<Float>(nullptr); + EXPECT_FALSE(n); + EXPECT_EQ(nullptr, n.get<Float>()); + EXPECT_EQ(nullptr, n.get<Int1>()); + EXPECT_EQ(nullptr, n.get<Int2>()); +} + + +} // end anonymous namespace diff --git a/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp b/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp index 7704e5a2f79a..c8c244d22ed1 100644 --- a/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp +++ b/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp @@ -88,8 +88,9 @@ public: bool needsToReserveAllocationSpace() override { return true; } - void reserveAllocationSpace(uintptr_t CodeSize, uintptr_t DataSizeRO, - uintptr_t DataSizeRW) override { + void reserveAllocationSpace(uintptr_t CodeSize, uint32_t CodeAlign, + uintptr_t DataSizeRO, uint32_t RODataAlign, + uintptr_t DataSizeRW, uint32_t RWDataAlign) override { ReservedCodeSize = CodeSize; ReservedDataSizeRO = DataSizeRO; ReservedDataSizeRW = DataSizeRW; diff --git a/unittests/ExecutionEngine/Orc/CMakeLists.txt b/unittests/ExecutionEngine/Orc/CMakeLists.txt index 74cc5b57015c..41fef24556b1 100644 --- a/unittests/ExecutionEngine/Orc/CMakeLists.txt +++ b/unittests/ExecutionEngine/Orc/CMakeLists.txt @@ -18,4 +18,5 @@ add_llvm_unittest(OrcJITTests ObjectTransformLayerTest.cpp OrcCAPITest.cpp OrcTestCommon.cpp + RPCUtilsTest.cpp ) diff --git a/unittests/ExecutionEngine/Orc/ObjectLinkingLayerTest.cpp b/unittests/ExecutionEngine/Orc/ObjectLinkingLayerTest.cpp index a37177c5d1db..59ee01f36010 100644 --- a/unittests/ExecutionEngine/Orc/ObjectLinkingLayerTest.cpp +++ b/unittests/ExecutionEngine/Orc/ObjectLinkingLayerTest.cpp @@ -7,6 +7,7 @@ // //===----------------------------------------------------------------------===// +#include "OrcTestCommon.h" #include "llvm/ExecutionEngine/ExecutionEngine.h" #include "llvm/ExecutionEngine/SectionMemoryManager.h" #include "llvm/ExecutionEngine/Orc/CompileUtils.h" @@ -21,6 +22,19 @@ using namespace llvm::orc; namespace { +class ObjectLinkingLayerExecutionTest : public testing::Test, + public OrcExecutionTest { +}; + +class SectionMemoryManagerWrapper : public SectionMemoryManager { +public: + int FinalizationCount = 0; + bool finalizeMemory(std::string *ErrMsg = 0) override { + ++FinalizationCount; + return SectionMemoryManager::finalizeMemory(ErrMsg); + } +}; + TEST(ObjectLinkingLayerTest, TestSetProcessAllSections) { class SectionMemoryManagerWrapper : public SectionMemoryManager { @@ -91,4 +105,72 @@ TEST(ObjectLinkingLayerTest, TestSetProcessAllSections) { } } + +TEST_F(ObjectLinkingLayerExecutionTest, NoDuplicateFinalization) { + + if (!TM) + return; + + ObjectLinkingLayer<> ObjLayer; + SimpleCompiler Compile(*TM); + + // Create a pair of modules that will trigger recursive finalization: + // Module 1: + // int bar() { return 42; } + // Module 2: + // int bar(); + // int foo() { return bar(); } + + ModuleBuilder MB1(getGlobalContext(), "", "dummy"); + { + MB1.getModule()->setDataLayout(TM->createDataLayout()); + Function *BarImpl = MB1.createFunctionDecl<int32_t(void)>("bar"); + BasicBlock *BarEntry = BasicBlock::Create(getGlobalContext(), "entry", + BarImpl); + IRBuilder<> Builder(BarEntry); + IntegerType *Int32Ty = IntegerType::get(getGlobalContext(), 32); + Value *FourtyTwo = ConstantInt::getSigned(Int32Ty, 42); + Builder.CreateRet(FourtyTwo); + } + + auto Obj1 = Compile(*MB1.getModule()); + std::vector<object::ObjectFile*> Obj1Set; + Obj1Set.push_back(Obj1.getBinary()); + + ModuleBuilder MB2(getGlobalContext(), "", "dummy"); + { + MB2.getModule()->setDataLayout(TM->createDataLayout()); + Function *BarDecl = MB2.createFunctionDecl<int32_t(void)>("bar"); + Function *FooImpl = MB2.createFunctionDecl<int32_t(void)>("foo"); + BasicBlock *FooEntry = BasicBlock::Create(getGlobalContext(), "entry", + FooImpl); + IRBuilder<> Builder(FooEntry); + Builder.CreateRet(Builder.CreateCall(BarDecl)); + } + auto Obj2 = Compile(*MB2.getModule()); + std::vector<object::ObjectFile*> Obj2Set; + Obj2Set.push_back(Obj2.getBinary()); + + auto Resolver = + createLambdaResolver( + [&](const std::string &Name) { + if (auto Sym = ObjLayer.findSymbol(Name, true)) + return RuntimeDyld::SymbolInfo(Sym.getAddress(), Sym.getFlags()); + return RuntimeDyld::SymbolInfo(nullptr); + }, + [](const std::string &Name) { + return RuntimeDyld::SymbolInfo(nullptr); + }); + + SectionMemoryManagerWrapper SMMW; + ObjLayer.addObjectSet(std::move(Obj1Set), &SMMW, &*Resolver); + auto H = ObjLayer.addObjectSet(std::move(Obj2Set), &SMMW, &*Resolver); + ObjLayer.emitAndFinalize(H); + + // Finalization of module 2 should trigger finalization of module 1. + // Verify that finalize on SMMW is only called once. + EXPECT_EQ(SMMW.FinalizationCount, 1) + << "Extra call to finalize"; +} + } diff --git a/unittests/ExecutionEngine/Orc/OrcTestCommon.cpp b/unittests/ExecutionEngine/Orc/OrcTestCommon.cpp index 1b5485d3b33b..17d1e9c9276e 100644 --- a/unittests/ExecutionEngine/Orc/OrcTestCommon.cpp +++ b/unittests/ExecutionEngine/Orc/OrcTestCommon.cpp @@ -19,7 +19,7 @@ bool OrcExecutionTest::NativeTargetInitialized = false; ModuleBuilder::ModuleBuilder(LLVMContext &Context, StringRef Triple, StringRef Name) - : M(new Module(Name, Context)), - Builder(Context) { - M->setTargetTriple(Triple); + : M(new Module(Name, Context)) { + if (Triple != "") + M->setTargetTriple(Triple); } diff --git a/unittests/ExecutionEngine/Orc/OrcTestCommon.h b/unittests/ExecutionEngine/Orc/OrcTestCommon.h index 15d9f54a37fc..f480e0789ae5 100644 --- a/unittests/ExecutionEngine/Orc/OrcTestCommon.h +++ b/unittests/ExecutionEngine/Orc/OrcTestCommon.h @@ -20,6 +20,7 @@ #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/IR/TypeBuilder.h" +#include "llvm/Object/ObjectFile.h" #include "llvm/ExecutionEngine/ExecutionEngine.h" #include "llvm/ExecutionEngine/Orc/JITSymbol.h" #include "llvm/Support/TargetSelect.h" @@ -74,7 +75,6 @@ public: private: std::unique_ptr<Module> M; - IRBuilder<> Builder; }; // Dummy struct type. diff --git a/unittests/ExecutionEngine/Orc/RPCUtilsTest.cpp b/unittests/ExecutionEngine/Orc/RPCUtilsTest.cpp new file mode 100644 index 000000000000..8215144a514d --- /dev/null +++ b/unittests/ExecutionEngine/Orc/RPCUtilsTest.cpp @@ -0,0 +1,147 @@ +//===----------- RPCUtilsTest.cpp - Unit tests the Orc RPC utils ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ExecutionEngine/Orc/RPCChannel.h" +#include "llvm/ExecutionEngine/Orc/RPCUtils.h" +#include "gtest/gtest.h" + +#include <queue> + +using namespace llvm; +using namespace llvm::orc; +using namespace llvm::orc::remote; + +class QueueChannel : public RPCChannel { +public: + QueueChannel(std::queue<char> &Queue) : Queue(Queue) {} + + std::error_code readBytes(char *Dst, unsigned Size) override { + while (Size--) { + *Dst++ = Queue.front(); + Queue.pop(); + } + return std::error_code(); + } + + std::error_code appendBytes(const char *Src, unsigned Size) override { + while (Size--) + Queue.push(*Src++); + return std::error_code(); + } + + std::error_code send() override { return std::error_code(); } + +private: + std::queue<char> &Queue; +}; + +class DummyRPC : public testing::Test, + public RPC<QueueChannel> { +public: + typedef Procedure<1, bool> Proc1; + typedef Procedure<2, int8_t, + uint8_t, + int16_t, + uint16_t, + int32_t, + uint32_t, + int64_t, + uint64_t, + bool, + std::string, + std::vector<int>> AllTheTypes; +}; + + +TEST_F(DummyRPC, TestBasic) { + std::queue<char> Queue; + QueueChannel C(Queue); + + { + // Make a call to Proc1. + auto EC = call<Proc1>(C, true); + EXPECT_FALSE(EC) << "Simple call over queue failed"; + } + + { + // Expect a call to Proc1. + auto EC = expect<Proc1>(C, + [&](bool &B) { + EXPECT_EQ(B, true) + << "Bool serialization broken"; + return std::error_code(); + }); + EXPECT_FALSE(EC) << "Simple expect over queue failed"; + } +} + +TEST_F(DummyRPC, TestSerialization) { + std::queue<char> Queue; + QueueChannel C(Queue); + + { + // Make a call to Proc1. + std::vector<int> v({42, 7}); + auto EC = call<AllTheTypes>(C, + -101, + 250, + -10000, + 10000, + -1000000000, + 1000000000, + -10000000000, + 10000000000, + true, + "foo", + v); + EXPECT_FALSE(EC) << "Big (serialization test) call over queue failed"; + } + + { + // Expect a call to Proc1. + auto EC = expect<AllTheTypes>(C, + [&](int8_t &s8, + uint8_t &u8, + int16_t &s16, + uint16_t &u16, + int32_t &s32, + uint32_t &u32, + int64_t &s64, + uint64_t &u64, + bool &b, + std::string &s, + std::vector<int> &v) { + + EXPECT_EQ(s8, -101) + << "int8_t serialization broken"; + EXPECT_EQ(u8, 250) + << "uint8_t serialization broken"; + EXPECT_EQ(s16, -10000) + << "int16_t serialization broken"; + EXPECT_EQ(u16, 10000) + << "uint16_t serialization broken"; + EXPECT_EQ(s32, -1000000000) + << "int32_t serialization broken"; + EXPECT_EQ(u32, 1000000000ULL) + << "uint32_t serialization broken"; + EXPECT_EQ(s64, -10000000000) + << "int64_t serialization broken"; + EXPECT_EQ(u64, 10000000000ULL) + << "uint64_t serialization broken"; + EXPECT_EQ(b, true) + << "bool serialization broken"; + EXPECT_EQ(s, "foo") + << "std::string serialization broken"; + EXPECT_EQ(v, std::vector<int>({42, 7})) + << "std::vector serialization broken"; + return std::error_code(); + }); + EXPECT_FALSE(EC) << "Big (serialization test) call over queue failed"; + } +} diff --git a/unittests/IR/AsmWriterTest.cpp b/unittests/IR/AsmWriterTest.cpp new file mode 100644 index 000000000000..c7e7bb5c9f0f --- /dev/null +++ b/unittests/IR/AsmWriterTest.cpp @@ -0,0 +1,37 @@ +//===- llvm/unittest/IR/AsmWriter.cpp - AsmWriter tests -------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/MDBuilder.h" +#include "llvm/IR/Module.h" +#include "gtest/gtest.h" + +using namespace llvm; + +namespace { + +TEST(AsmWriterTest, DebugPrintDetachedInstruction) { + + // PR24852: Ensure that an instruction can be printed even when it + // has metadata attached but no parent. + LLVMContext Ctx; + auto Ty = Type::getInt32Ty(Ctx); + auto Undef = UndefValue::get(Ty); + std::unique_ptr<BinaryOperator> Add(BinaryOperator::CreateAdd(Undef, Undef)); + Add->setMetadata( + "", MDNode::get(Ctx, {ConstantAsMetadata::get(ConstantInt::get(Ty, 1))})); + std::string S; + raw_string_ostream OS(S); + Add->print(OS); + std::size_t r = OS.str().find("<badref> = add i32 undef, undef, !<empty"); + EXPECT_TRUE(r != std::string::npos); +} + +} diff --git a/unittests/IR/CMakeLists.txt b/unittests/IR/CMakeLists.txt index e5a0fc981075..5aad8edc9134 100644 --- a/unittests/IR/CMakeLists.txt +++ b/unittests/IR/CMakeLists.txt @@ -6,6 +6,7 @@ set(LLVM_LINK_COMPONENTS ) set(IRSources + AsmWriterTest.cpp AttributesTest.cpp ConstantRangeTest.cpp ConstantsTest.cpp diff --git a/unittests/IR/IRBuilderTest.cpp b/unittests/IR/IRBuilderTest.cpp index 82565ccaebcf..bd0eae0399a4 100644 --- a/unittests/IR/IRBuilderTest.cpp +++ b/unittests/IR/IRBuilderTest.cpp @@ -142,13 +142,13 @@ TEST_F(IRBuilderTest, FastMathFlags) { EXPECT_FALSE(FAdd->hasNoNaNs()); FastMathFlags FMF; - Builder.SetFastMathFlags(FMF); + Builder.setFastMathFlags(FMF); F = Builder.CreateFAdd(F, F); EXPECT_FALSE(Builder.getFastMathFlags().any()); FMF.setUnsafeAlgebra(); - Builder.SetFastMathFlags(FMF); + Builder.setFastMathFlags(FMF); F = Builder.CreateFAdd(F, F); EXPECT_TRUE(Builder.getFastMathFlags().any()); @@ -179,7 +179,7 @@ TEST_F(IRBuilderTest, FastMathFlags) { FMF.clear(); FMF.setAllowReciprocal(); - Builder.SetFastMathFlags(FMF); + Builder.setFastMathFlags(FMF); F = Builder.CreateFDiv(F, F); EXPECT_TRUE(Builder.getFastMathFlags().any()); @@ -197,7 +197,7 @@ TEST_F(IRBuilderTest, FastMathFlags) { FMF.clear(); FMF.setAllowReciprocal(); - Builder.SetFastMathFlags(FMF); + Builder.setFastMathFlags(FMF); FC = Builder.CreateFCmpOEQ(F, F); EXPECT_TRUE(Builder.getFastMathFlags().any()); @@ -224,7 +224,7 @@ TEST_F(IRBuilderTest, FastMathFlags) { FMF.clear(); FMF.setNoNaNs(); - Builder.SetFastMathFlags(FMF); + Builder.setFastMathFlags(FMF); FCall = Builder.CreateCall(Callee, None); EXPECT_TRUE(Builder.getFastMathFlags().any()); @@ -309,14 +309,14 @@ TEST_F(IRBuilderTest, RAIIHelpersTest) { MDNode *FPMathA = MDB.createFPMath(0.01f); MDNode *FPMathB = MDB.createFPMath(0.1f); - Builder.SetDefaultFPMathTag(FPMathA); + Builder.setDefaultFPMathTag(FPMathA); { IRBuilder<>::FastMathFlagGuard Guard(Builder); FastMathFlags FMF; FMF.setAllowReciprocal(); - Builder.SetFastMathFlags(FMF); - Builder.SetDefaultFPMathTag(FPMathB); + Builder.setFastMathFlags(FMF); + Builder.setDefaultFPMathTag(FPMathB); EXPECT_TRUE(Builder.getFastMathFlags().allowReciprocal()); EXPECT_EQ(FPMathB, Builder.getDefaultFPMathTag()); } diff --git a/unittests/ProfileData/InstrProfTest.cpp b/unittests/ProfileData/InstrProfTest.cpp index 1ccc3ca5d695..51f52f2a0771 100644 --- a/unittests/ProfileData/InstrProfTest.cpp +++ b/unittests/ProfileData/InstrProfTest.cpp @@ -159,11 +159,57 @@ TEST_F(InstrProfTest, get_icall_data_read_write) { std::unique_ptr<InstrProfValueData[]> VD = R.get().getValueForSite(IPVK_IndirectCallTarget, 0); - // Now sort the target acording to frequency. - std::sort(&VD[0], &VD[3], - [](const InstrProfValueData &VD1, const InstrProfValueData &VD2) { - return VD1.Count > VD2.Count; - }); + + ASSERT_EQ(3U, VD[0].Count); + ASSERT_EQ(2U, VD[1].Count); + ASSERT_EQ(1U, VD[2].Count); + + ASSERT_EQ(StringRef((const char *)VD[0].Value, 7), StringRef("callee3")); + ASSERT_EQ(StringRef((const char *)VD[1].Value, 7), StringRef("callee2")); + ASSERT_EQ(StringRef((const char *)VD[2].Value, 7), StringRef("callee1")); +} + +TEST_F(InstrProfTest, get_icall_data_read_write_with_weight) { + InstrProfRecord Record1("caller", 0x1234, {1, 2}); + InstrProfRecord Record2("callee1", 0x1235, {3, 4}); + InstrProfRecord Record3("callee2", 0x1235, {3, 4}); + InstrProfRecord Record4("callee3", 0x1235, {3, 4}); + + // 4 value sites. + Record1.reserveSites(IPVK_IndirectCallTarget, 4); + InstrProfValueData VD0[] = {{(uint64_t) "callee1", 1}, + {(uint64_t) "callee2", 2}, + {(uint64_t) "callee3", 3}}; + Record1.addValueData(IPVK_IndirectCallTarget, 0, VD0, 3, nullptr); + // No value profile data at the second site. + Record1.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr); + InstrProfValueData VD2[] = {{(uint64_t) "callee1", 1}, + {(uint64_t) "callee2", 2}}; + Record1.addValueData(IPVK_IndirectCallTarget, 2, VD2, 2, nullptr); + InstrProfValueData VD3[] = {{(uint64_t) "callee1", 1}}; + Record1.addValueData(IPVK_IndirectCallTarget, 3, VD3, 1, nullptr); + + Writer.addRecord(std::move(Record1), 10); + Writer.addRecord(std::move(Record2)); + Writer.addRecord(std::move(Record3)); + Writer.addRecord(std::move(Record4)); + auto Profile = Writer.writeBuffer(); + readProfile(std::move(Profile)); + + ErrorOr<InstrProfRecord> R = Reader->getInstrProfRecord("caller", 0x1234); + ASSERT_TRUE(NoError(R.getError())); + ASSERT_EQ(4U, R.get().getNumValueSites(IPVK_IndirectCallTarget)); + ASSERT_EQ(3U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 0)); + ASSERT_EQ(0U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 1)); + ASSERT_EQ(2U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 2)); + ASSERT_EQ(1U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 3)); + + std::unique_ptr<InstrProfValueData[]> VD = + R.get().getValueForSite(IPVK_IndirectCallTarget, 0); + ASSERT_EQ(30U, VD[0].Count); + ASSERT_EQ(20U, VD[1].Count); + ASSERT_EQ(10U, VD[2].Count); + ASSERT_EQ(StringRef((const char *)VD[0].Value, 7), StringRef("callee3")); ASSERT_EQ(StringRef((const char *)VD[1].Value, 7), StringRef("callee2")); ASSERT_EQ(StringRef((const char *)VD[2].Value, 7), StringRef("callee1")); @@ -213,11 +259,6 @@ TEST_F(InstrProfTest, get_icall_data_read_write_big_endian) { std::unique_ptr<InstrProfValueData[]> VD = R.get().getValueForSite(IPVK_IndirectCallTarget, 0); - // Now sort the target acording to frequency. - std::sort(&VD[0], &VD[3], - [](const InstrProfValueData &VD1, const InstrProfValueData &VD2) { - return VD1.Count > VD2.Count; - }); ASSERT_EQ(StringRef((const char *)VD[0].Value, 7), StringRef("callee3")); ASSERT_EQ(StringRef((const char *)VD[1].Value, 7), StringRef("callee2")); ASSERT_EQ(StringRef((const char *)VD[2].Value, 7), StringRef("callee1")); @@ -249,12 +290,11 @@ TEST_F(InstrProfTest, get_icall_data_merge1) { {uint64_t(callee4), 4}}; Record11.addValueData(IPVK_IndirectCallTarget, 0, VD0, 4, nullptr); - // No valeu profile data at the second site. + // No value profile data at the second site. Record11.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr); - InstrProfValueData VD2[] = {{uint64_t(callee1), 1}, - {uint64_t(callee2), 2}, - {uint64_t(callee3), 3}}; + InstrProfValueData VD2[] = { + {uint64_t(callee1), 1}, {uint64_t(callee2), 2}, {uint64_t(callee3), 3}}; Record11.addValueData(IPVK_IndirectCallTarget, 2, VD2, 3, nullptr); InstrProfValueData VD3[] = {{uint64_t(callee1), 1}}; @@ -267,16 +307,14 @@ TEST_F(InstrProfTest, get_icall_data_merge1) { // A differnt record for the same caller. Record12.reserveSites(IPVK_IndirectCallTarget, 5); - InstrProfValueData VD02[] = {{uint64_t(callee2), 5}, - {uint64_t(callee3), 3}}; + InstrProfValueData VD02[] = {{uint64_t(callee2), 5}, {uint64_t(callee3), 3}}; Record12.addValueData(IPVK_IndirectCallTarget, 0, VD02, 2, nullptr); - // No valeu profile data at the second site. + // No value profile data at the second site. Record12.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr); - InstrProfValueData VD22[] = {{uint64_t(callee2), 1}, - {uint64_t(callee3), 3}, - {uint64_t(callee4), 4}}; + InstrProfValueData VD22[] = { + {uint64_t(callee2), 1}, {uint64_t(callee3), 3}, {uint64_t(callee4), 4}}; Record12.addValueData(IPVK_IndirectCallTarget, 2, VD22, 3, nullptr); Record12.addValueData(IPVK_IndirectCallTarget, 3, nullptr, 0, nullptr); @@ -309,11 +347,6 @@ TEST_F(InstrProfTest, get_icall_data_merge1) { std::unique_ptr<InstrProfValueData[]> VD = R.get().getValueForSite(IPVK_IndirectCallTarget, 0); - // Now sort the target acording to frequency. - std::sort(&VD[0], &VD[4], - [](const InstrProfValueData &VD1, const InstrProfValueData &VD2) { - return VD1.Count > VD2.Count; - }); ASSERT_EQ(StringRef((const char *)VD[0].Value, 7), StringRef("callee2")); ASSERT_EQ(7U, VD[0].Count); ASSERT_EQ(StringRef((const char *)VD[1].Value, 7), StringRef("callee3")); @@ -325,10 +358,6 @@ TEST_F(InstrProfTest, get_icall_data_merge1) { std::unique_ptr<InstrProfValueData[]> VD_2( R.get().getValueForSite(IPVK_IndirectCallTarget, 2)); - std::sort(&VD_2[0], &VD_2[4], - [](const InstrProfValueData &VD1, const InstrProfValueData &VD2) { - return VD1.Count > VD2.Count; - }); ASSERT_EQ(StringRef((const char *)VD_2[0].Value, 7), StringRef("callee3")); ASSERT_EQ(6U, VD_2[0].Count); ASSERT_EQ(StringRef((const char *)VD_2[1].Value, 7), StringRef("callee4")); @@ -345,10 +374,6 @@ TEST_F(InstrProfTest, get_icall_data_merge1) { std::unique_ptr<InstrProfValueData[]> VD_4( R.get().getValueForSite(IPVK_IndirectCallTarget, 4)); - std::sort(&VD_4[0], &VD_4[3], - [](const InstrProfValueData &VD1, const InstrProfValueData &VD2) { - return VD1.Count > VD2.Count; - }); ASSERT_EQ(StringRef((const char *)VD_4[0].Value, 7), StringRef("callee3")); ASSERT_EQ(6U, VD_4[0].Count); ASSERT_EQ(StringRef((const char *)VD_4[1].Value, 7), StringRef("callee2")); @@ -408,6 +433,55 @@ TEST_F(InstrProfTest, get_icall_data_merge1_saturation) { ASSERT_EQ(Max, VD[0].Count); } +// This test tests that when there are too many values +// for a given site, the merged results are properly +// truncated. +TEST_F(InstrProfTest, get_icall_data_merge_site_trunc) { + static const char caller[] = "caller"; + + InstrProfRecord Record11(caller, 0x1234, {1, 2}); + InstrProfRecord Record12(caller, 0x1234, {1, 2}); + + // 2 value sites. + Record11.reserveSites(IPVK_IndirectCallTarget, 2); + InstrProfValueData VD0[255]; + for (int I = 0; I < 255; I++) { + VD0[I].Value = 2 * I; + VD0[I].Count = 2 * I + 1000; + } + + Record11.addValueData(IPVK_IndirectCallTarget, 0, VD0, 255, nullptr); + Record11.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr); + + Record12.reserveSites(IPVK_IndirectCallTarget, 2); + InstrProfValueData VD1[255]; + for (int I = 0; I < 255; I++) { + VD1[I].Value = 2 * I + 1; + VD1[I].Count = 2 * I + 1001; + } + + Record12.addValueData(IPVK_IndirectCallTarget, 0, VD1, 255, nullptr); + Record12.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr); + + Writer.addRecord(std::move(Record11)); + // Merge profile data. + Writer.addRecord(std::move(Record12)); + + auto Profile = Writer.writeBuffer(); + readProfile(std::move(Profile)); + + ErrorOr<InstrProfRecord> R = Reader->getInstrProfRecord("caller", 0x1234); + ASSERT_TRUE(NoError(R.getError())); + std::unique_ptr<InstrProfValueData[]> VD( + R.get().getValueForSite(IPVK_IndirectCallTarget, 0)); + ASSERT_EQ(2U, R.get().getNumValueSites(IPVK_IndirectCallTarget)); + ASSERT_EQ(255U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 0)); + for (unsigned I = 0; I < 255; I++) { + ASSERT_EQ(VD[I].Value, 509 - I); + ASSERT_EQ(VD[I].Count, 1509 - I); + } +} + // Synthesize runtime value profile data. ValueProfNode Site1Values[5] = {{{uint64_t("callee1"), 400}, &Site1Values[1]}, {{uint64_t("callee2"), 1000}, &Site1Values[2]}, diff --git a/unittests/Support/MathExtrasTest.cpp b/unittests/Support/MathExtrasTest.cpp index 945d8322b259..97309f8d31f5 100644 --- a/unittests/Support/MathExtrasTest.cpp +++ b/unittests/Support/MathExtrasTest.cpp @@ -304,4 +304,58 @@ TEST(MathExtras, SaturatingMultiply) { SaturatingMultiplyTestHelper<uint64_t>(); } +template<typename T> +void SaturatingMultiplyAddTestHelper() +{ + const T Max = std::numeric_limits<T>::max(); + bool ResultOverflowed; + + // Test basic multiply-add. + EXPECT_EQ(T(16), SaturatingMultiplyAdd(T(2), T(3), T(10))); + EXPECT_EQ(T(16), SaturatingMultiplyAdd(T(2), T(3), T(10), &ResultOverflowed)); + EXPECT_FALSE(ResultOverflowed); + + // Test multiply overflows, add doesn't overflow + EXPECT_EQ(Max, SaturatingMultiplyAdd(Max, Max, T(0), &ResultOverflowed)); + EXPECT_TRUE(ResultOverflowed); + + // Test multiply doesn't overflow, add overflows + EXPECT_EQ(Max, SaturatingMultiplyAdd(T(1), T(1), Max, &ResultOverflowed)); + EXPECT_TRUE(ResultOverflowed); + + // Test multiply-add with Max as operand + EXPECT_EQ(Max, SaturatingMultiplyAdd(T(1), T(1), Max, &ResultOverflowed)); + EXPECT_TRUE(ResultOverflowed); + + EXPECT_EQ(Max, SaturatingMultiplyAdd(T(1), Max, T(1), &ResultOverflowed)); + EXPECT_TRUE(ResultOverflowed); + + EXPECT_EQ(Max, SaturatingMultiplyAdd(Max, Max, T(1), &ResultOverflowed)); + EXPECT_TRUE(ResultOverflowed); + + EXPECT_EQ(Max, SaturatingMultiplyAdd(Max, Max, Max, &ResultOverflowed)); + EXPECT_TRUE(ResultOverflowed); + + // Test multiply-add with 0 as operand + EXPECT_EQ(T(1), SaturatingMultiplyAdd(T(1), T(1), T(0), &ResultOverflowed)); + EXPECT_FALSE(ResultOverflowed); + + EXPECT_EQ(T(1), SaturatingMultiplyAdd(T(1), T(0), T(1), &ResultOverflowed)); + EXPECT_FALSE(ResultOverflowed); + + EXPECT_EQ(T(1), SaturatingMultiplyAdd(T(0), T(0), T(1), &ResultOverflowed)); + EXPECT_FALSE(ResultOverflowed); + + EXPECT_EQ(T(0), SaturatingMultiplyAdd(T(0), T(0), T(0), &ResultOverflowed)); + EXPECT_FALSE(ResultOverflowed); + +} + +TEST(MathExtras, SaturatingMultiplyAdd) { + SaturatingMultiplyAddTestHelper<uint8_t>(); + SaturatingMultiplyAddTestHelper<uint16_t>(); + SaturatingMultiplyAddTestHelper<uint32_t>(); + SaturatingMultiplyAddTestHelper<uint64_t>(); +} + } |