diff options
Diffstat (limited to 'unittests')
-rw-r--r-- | unittests/Analysis/ProfileSummaryInfoTest.cpp | 6 | ||||
-rw-r--r-- | unittests/Analysis/TargetLibraryInfoTest.cpp | 46 | ||||
-rw-r--r-- | unittests/DebugInfo/CMakeLists.txt | 2 | ||||
-rw-r--r-- | unittests/DebugInfo/CodeView/CMakeLists.txt | 11 | ||||
-rw-r--r-- | unittests/DebugInfo/CodeView/ErrorChecking.h | 61 | ||||
-rw-r--r-- | unittests/DebugInfo/CodeView/RandomAccessVisitorTest.cpp | 353 | ||||
-rw-r--r-- | unittests/ExecutionEngine/Orc/ObjectTransformLayerTest.cpp | 2 | ||||
-rw-r--r-- | unittests/ExecutionEngine/Orc/OrcTestCommon.h | 2 | ||||
-rw-r--r-- | unittests/ExecutionEngine/Orc/RTDyldObjectLinkingLayerTest.cpp | 29 | ||||
-rw-r--r-- | unittests/IR/ConstantRangeTest.cpp | 9 | ||||
-rw-r--r-- | unittests/IR/InstructionsTest.cpp | 7 | ||||
-rw-r--r-- | unittests/IR/TypeBuilderTest.cpp | 30 | ||||
-rw-r--r-- | unittests/Support/CMakeLists.txt | 1 | ||||
-rw-r--r-- | unittests/Support/DynamicLibrary/DynamicLibraryTest.cpp | 4 | ||||
-rw-r--r-- | unittests/Support/ParallelTest.cpp | 53 | ||||
-rw-r--r-- | unittests/Support/Path.cpp | 2 | ||||
-rw-r--r-- | unittests/Transforms/Utils/Cloning.cpp | 65 |
17 files changed, 619 insertions, 64 deletions
diff --git a/unittests/Analysis/ProfileSummaryInfoTest.cpp b/unittests/Analysis/ProfileSummaryInfoTest.cpp index 0b4b1de28053b..3454474f0376d 100644 --- a/unittests/Analysis/ProfileSummaryInfoTest.cpp +++ b/unittests/Analysis/ProfileSummaryInfoTest.cpp @@ -162,6 +162,12 @@ TEST_F(ProfileSummaryInfoTest, InstrProf) { EXPECT_TRUE(PSI.isHotCallSite(CS1, &BFI)); EXPECT_FALSE(PSI.isHotCallSite(CS2, &BFI)); + + // Test that adding an MD_prof metadata with a hot count on CS2 does not + // change its hotness as it has no effect in instrumented profiling. + MDBuilder MDB(M->getContext()); + CI2->setMetadata(llvm::LLVMContext::MD_prof, MDB.createBranchWeights({400})); + EXPECT_FALSE(PSI.isHotCallSite(CS2, &BFI)); } TEST_F(ProfileSummaryInfoTest, SampleProf) { diff --git a/unittests/Analysis/TargetLibraryInfoTest.cpp b/unittests/Analysis/TargetLibraryInfoTest.cpp index 44c141d6a1e9f..9d852cf0301b9 100644 --- a/unittests/Analysis/TargetLibraryInfoTest.cpp +++ b/unittests/Analysis/TargetLibraryInfoTest.cpp @@ -470,6 +470,52 @@ TEST_F(TargetLibraryInfoTest, ValidProto) { "declare i32 @isascii(i32)\n" "declare i32 @isdigit(i32)\n" "declare i32 @toascii(i32)\n" + + // These functions were extracted from math-finite.h which provides + // functions similar to those in math.h, but optimized for handling + // finite values only. + "declare double @__acos_finite(double)\n" + "declare float @__acosf_finite(float)\n" + "declare x86_fp80 @__acosl_finite(x86_fp80)\n" + "declare double @__acosh_finite(double)\n" + "declare float @__acoshf_finite(float)\n" + "declare x86_fp80 @__acoshl_finite(x86_fp80)\n" + "declare double @__asin_finite(double)\n" + "declare float @__asinf_finite(float)\n" + "declare x86_fp80 @__asinl_finite(x86_fp80)\n" + "declare double @__atan2_finite(double, double)\n" + "declare float @__atan2f_finite(float, float)\n" + "declare x86_fp80 @__atan2l_finite(x86_fp80, x86_fp80)\n" + "declare double @__atanh_finite(double)\n" + "declare float @__atanhf_finite(float)\n" + "declare x86_fp80 @__atanhl_finite(x86_fp80)\n" + "declare double @__cosh_finite(double)\n" + "declare float @__coshf_finite(float)\n" + "declare x86_fp80 @__coshl_finite(x86_fp80)\n" + "declare double @__exp10_finite(double)\n" + "declare float @__exp10f_finite(float)\n" + "declare x86_fp80 @__exp10l_finite(x86_fp80)\n" + "declare double @__exp2_finite(double)\n" + "declare float @__exp2f_finite(float)\n" + "declare x86_fp80 @__exp2l_finite(x86_fp80)\n" + "declare double @__exp_finite(double)\n" + "declare float @__expf_finite(float)\n" + "declare x86_fp80 @__expl_finite(x86_fp80)\n" + "declare double @__log10_finite(double)\n" + "declare float @__log10f_finite(float)\n" + "declare x86_fp80 @__log10l_finite(x86_fp80)\n" + "declare double @__log2_finite(double)\n" + "declare float @__log2f_finite(float)\n" + "declare x86_fp80 @__log2l_finite(x86_fp80)\n" + "declare double @__log_finite(double)\n" + "declare float @__logf_finite(float)\n" + "declare x86_fp80 @__logl_finite(x86_fp80)\n" + "declare double @__pow_finite(double, double)\n" + "declare float @__powf_finite(float, float)\n" + "declare x86_fp80 @__powl_finite(x86_fp80, x86_fp80)\n" + "declare double @__sinh_finite(double)\n" + "declare float @__sinhf_finite(float)\n" + "declare x86_fp80 @__sinhl_finite(x86_fp80)\n" ); for (unsigned FI = 0; FI != LibFunc::NumLibFuncs; ++FI) { diff --git a/unittests/DebugInfo/CMakeLists.txt b/unittests/DebugInfo/CMakeLists.txt index dae472bafdd71..e38fff58cae6a 100644 --- a/unittests/DebugInfo/CMakeLists.txt +++ b/unittests/DebugInfo/CMakeLists.txt @@ -1,3 +1,3 @@ - +add_subdirectory(CodeView) add_subdirectory(DWARF) add_subdirectory(PDB) diff --git a/unittests/DebugInfo/CodeView/CMakeLists.txt b/unittests/DebugInfo/CodeView/CMakeLists.txt new file mode 100644 index 0000000000000..854182c4efb41 --- /dev/null +++ b/unittests/DebugInfo/CodeView/CMakeLists.txt @@ -0,0 +1,11 @@ +set(LLVM_LINK_COMPONENTS + DebugInfoCodeView + ) + +set(DebugInfoCodeViewSources + RandomAccessVisitorTest.cpp + ) + +add_llvm_unittest(DebugInfoCodeViewTests + ${DebugInfoCodeViewSources} + ) diff --git a/unittests/DebugInfo/CodeView/ErrorChecking.h b/unittests/DebugInfo/CodeView/ErrorChecking.h new file mode 100644 index 0000000000000..09310883bf588 --- /dev/null +++ b/unittests/DebugInfo/CodeView/ErrorChecking.h @@ -0,0 +1,61 @@ +//===- ErrorChecking.h - Helpers for verifying llvm::Errors -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_UNITTESTS_DEBUGINFO_CODEVIEW_ERRORCHECKING_H +#define LLVM_UNITTESTS_DEBUGINFO_CODEVIEW_ERRORCHECKING_H + +#define EXPECT_NO_ERROR(Err) \ + { \ + auto E = Err; \ + EXPECT_FALSE(static_cast<bool>(E)); \ + if (E) \ + consumeError(std::move(E)); \ + } + +#define EXPECT_ERROR(Err) \ + { \ + auto E = Err; \ + EXPECT_TRUE(static_cast<bool>(E)); \ + if (E) \ + consumeError(std::move(E)); \ + } + +#define EXPECT_EXPECTED(Exp) \ + { \ + auto E = Exp.takeError(); \ + EXPECT_FALSE(static_cast<bool>(E)); \ + if (E) { \ + consumeError(std::move(E)); \ + return; \ + } \ + } + +#define EXPECT_EXPECTED_EQ(Val, Exp) \ + { \ + auto Result = Exp; \ + auto E = Result.takeError(); \ + EXPECT_FALSE(static_cast<bool>(E)); \ + if (E) { \ + consumeError(std::move(E)); \ + return; \ + } \ + EXPECT_EQ(Val, *Result); \ + } + +#define EXPECT_UNEXPECTED(Exp) \ + { \ + auto E = Exp.takeError(); \ + EXPECT_TRUE(static_cast<bool>(E)); \ + if (E) { \ + consumeError(std::move(E)); \ + return; \ + } \ + } + +#endif diff --git a/unittests/DebugInfo/CodeView/RandomAccessVisitorTest.cpp b/unittests/DebugInfo/CodeView/RandomAccessVisitorTest.cpp new file mode 100644 index 0000000000000..fedb5978da816 --- /dev/null +++ b/unittests/DebugInfo/CodeView/RandomAccessVisitorTest.cpp @@ -0,0 +1,353 @@ +//===- llvm/unittest/DebugInfo/CodeView/RandomAccessVisitorTest.cpp -------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ErrorChecking.h" + +#include "llvm/ADT/SmallBitVector.h" +#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" +#include "llvm/DebugInfo/CodeView/RandomAccessTypeVisitor.h" +#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/DebugInfo/CodeView/TypeRecordMapping.h" +#include "llvm/DebugInfo/CodeView/TypeSerializer.h" +#include "llvm/DebugInfo/CodeView/TypeServerHandler.h" +#include "llvm/DebugInfo/CodeView/TypeTableBuilder.h" +#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h" +#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h" +#include "llvm/DebugInfo/PDB/Native/RawTypes.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/BinaryItemStream.h" +#include "llvm/Support/Error.h" + +#include "gtest/gtest.h" + +using namespace llvm; +using namespace llvm::codeview; +using namespace llvm::pdb; + +namespace llvm { +namespace codeview { +inline bool operator==(const ArrayRecord &R1, const ArrayRecord &R2) { + if (R1.ElementType != R2.ElementType) + return false; + if (R1.IndexType != R2.IndexType) + return false; + if (R1.Name != R2.Name) + return false; + if (R1.Size != R2.Size) + return false; + return true; +} +inline bool operator!=(const ArrayRecord &R1, const ArrayRecord &R2) { + return !(R1 == R2); +} + +inline bool operator==(const CVType &R1, const CVType &R2) { + if (R1.Type != R2.Type) + return false; + if (R1.RecordData != R2.RecordData) + return false; + return true; +} +inline bool operator!=(const CVType &R1, const CVType &R2) { + return !(R1 == R2); +} +} +} + +namespace llvm { +template <> struct BinaryItemTraits<CVType> { + static size_t length(const CVType &Item) { return Item.length(); } + static ArrayRef<uint8_t> bytes(const CVType &Item) { return Item.data(); } +}; +} + +namespace { + +class MockCallbacks : public TypeVisitorCallbacks { +public: + virtual Error visitTypeBegin(CVType &CVR, TypeIndex Index) { + Indices.push_back(Index); + return Error::success(); + } + virtual Error visitKnownRecord(CVType &CVR, ArrayRecord &AR) { + VisitedRecords.push_back(AR); + RawRecords.push_back(CVR); + return Error::success(); + } + + uint32_t count() const { + assert(Indices.size() == RawRecords.size()); + assert(Indices.size() == VisitedRecords.size()); + return Indices.size(); + } + std::vector<TypeIndex> Indices; + std::vector<CVType> RawRecords; + std::vector<ArrayRecord> VisitedRecords; +}; + +class RandomAccessVisitorTest : public testing::Test { +public: + RandomAccessVisitorTest() {} + + static void SetUpTestCase() { + GlobalState = llvm::make_unique<GlobalTestState>(); + + TypeTableBuilder Builder(GlobalState->Allocator); + + uint32_t Offset = 0; + for (int I = 0; I < 11; ++I) { + ArrayRecord AR(TypeRecordKind::Array); + AR.ElementType = TypeIndex::Int32(); + AR.IndexType = TypeIndex::UInt32(); + AR.Size = I; + std::string Name; + raw_string_ostream Stream(Name); + Stream << "Array [" << I << "]"; + AR.Name = GlobalState->Strings.save(Stream.str()); + GlobalState->Records.push_back(AR); + GlobalState->Indices.push_back(Builder.writeKnownType(AR)); + + CVType Type(TypeLeafKind::LF_ARRAY, Builder.records().back()); + GlobalState->TypeVector.push_back(Type); + + GlobalState->AllOffsets.push_back( + {GlobalState->Indices.back(), ulittle32_t(Offset)}); + Offset += Type.length(); + } + + GlobalState->ItemStream.setItems(GlobalState->TypeVector); + GlobalState->TypeArray = VarStreamArray<CVType>(GlobalState->ItemStream); + } + + static void TearDownTestCase() { GlobalState.reset(); } + + void SetUp() override { + TestState = llvm::make_unique<PerTestState>(); + + TestState->Pipeline.addCallbackToPipeline(TestState->Deserializer); + TestState->Pipeline.addCallbackToPipeline(TestState->Callbacks); + } + + void TearDown() override { TestState.reset(); } + +protected: + bool ValidateDatabaseRecord(const RandomAccessTypeVisitor &Visitor, + uint32_t Index) { + TypeIndex TI = TypeIndex::fromArrayIndex(Index); + if (!Visitor.database().contains(TI)) + return false; + if (GlobalState->TypeVector[Index] != Visitor.database().getTypeRecord(TI)) + return false; + return true; + } + + bool ValidateVisitedRecord(uint32_t VisitationOrder, + uint32_t GlobalArrayIndex) { + TypeIndex TI = TypeIndex::fromArrayIndex(GlobalArrayIndex); + if (TI != TestState->Callbacks.Indices[VisitationOrder]) + return false; + + if (GlobalState->TypeVector[TI.toArrayIndex()] != + TestState->Callbacks.RawRecords[VisitationOrder]) + return false; + + if (GlobalState->Records[TI.toArrayIndex()] != + TestState->Callbacks.VisitedRecords[VisitationOrder]) + return false; + + return true; + } + + struct GlobalTestState { + GlobalTestState() : Strings(Allocator), ItemStream(llvm::support::little) {} + + BumpPtrAllocator Allocator; + StringSaver Strings; + + std::vector<ArrayRecord> Records; + std::vector<TypeIndex> Indices; + std::vector<TypeIndexOffset> AllOffsets; + std::vector<CVType> TypeVector; + BinaryItemStream<CVType> ItemStream; + VarStreamArray<CVType> TypeArray; + + MutableBinaryByteStream Stream; + }; + + struct PerTestState { + FixedStreamArray<TypeIndexOffset> Offsets; + + TypeVisitorCallbackPipeline Pipeline; + TypeDeserializer Deserializer; + MockCallbacks Callbacks; + }; + + FixedStreamArray<TypeIndexOffset> + createPartialOffsets(MutableBinaryByteStream &Storage, + std::initializer_list<uint32_t> Indices) { + + uint32_t Count = Indices.size(); + uint32_t Size = Count * sizeof(TypeIndexOffset); + uint8_t *Buffer = GlobalState->Allocator.Allocate<uint8_t>(Size); + MutableArrayRef<uint8_t> Bytes(Buffer, Size); + Storage = MutableBinaryByteStream(Bytes, support::little); + BinaryStreamWriter Writer(Storage); + for (const auto I : Indices) + consumeError(Writer.writeObject(GlobalState->AllOffsets[I])); + + BinaryStreamReader Reader(Storage); + FixedStreamArray<TypeIndexOffset> Result; + consumeError(Reader.readArray(Result, Count)); + return Result; + } + + static std::unique_ptr<GlobalTestState> GlobalState; + std::unique_ptr<PerTestState> TestState; +}; + +std::unique_ptr<RandomAccessVisitorTest::GlobalTestState> + RandomAccessVisitorTest::GlobalState; +} + +TEST_F(RandomAccessVisitorTest, MultipleVisits) { + TestState->Offsets = createPartialOffsets(GlobalState->Stream, {0, 8}); + RandomAccessTypeVisitor Visitor(GlobalState->TypeArray, + GlobalState->TypeVector.size(), + TestState->Offsets); + + std::vector<uint32_t> IndicesToVisit = {5, 5, 5}; + + for (uint32_t I : IndicesToVisit) { + TypeIndex TI = TypeIndex::fromArrayIndex(I); + EXPECT_NO_ERROR(Visitor.visitTypeIndex(TI, TestState->Pipeline)); + } + + // [0,8) should be present + EXPECT_EQ(8u, Visitor.database().size()); + for (uint32_t I = 0; I < 8; ++I) + EXPECT_TRUE(ValidateDatabaseRecord(Visitor, I)); + + // 5, 5, 5 + EXPECT_EQ(3u, TestState->Callbacks.count()); + for (auto I : enumerate(IndicesToVisit)) + EXPECT_TRUE(ValidateVisitedRecord(I.index(), I.value())); +} + +TEST_F(RandomAccessVisitorTest, DescendingWithinChunk) { + // Visit multiple items from the same "chunk" in reverse order. In this + // example, it's 7 then 4 then 2. At the end, all records from 0 to 7 should + // be known by the database, but only 2, 4, and 7 should have been visited. + TestState->Offsets = createPartialOffsets(GlobalState->Stream, {0, 8}); + + std::vector<uint32_t> IndicesToVisit = {7, 4, 2}; + + RandomAccessTypeVisitor Visitor(GlobalState->TypeArray, + GlobalState->TypeVector.size(), + TestState->Offsets); + + for (uint32_t I : IndicesToVisit) { + TypeIndex TI = TypeIndex::fromArrayIndex(I); + EXPECT_NO_ERROR(Visitor.visitTypeIndex(TI, TestState->Pipeline)); + } + + // [0, 7] + EXPECT_EQ(8u, Visitor.database().size()); + for (uint32_t I = 0; I < 8; ++I) + EXPECT_TRUE(ValidateDatabaseRecord(Visitor, I)); + + // 2, 4, 7 + EXPECT_EQ(3u, TestState->Callbacks.count()); + for (auto I : enumerate(IndicesToVisit)) + EXPECT_TRUE(ValidateVisitedRecord(I.index(), I.value())); +} + +TEST_F(RandomAccessVisitorTest, AscendingWithinChunk) { + // * Visit multiple items from the same chunk in ascending order, ensuring + // that intermediate items are not visited. In the below example, it's + // 5 -> 6 -> 7 which come from the [4,8) chunk. + TestState->Offsets = createPartialOffsets(GlobalState->Stream, {0, 8}); + + std::vector<uint32_t> IndicesToVisit = {2, 4, 7}; + + RandomAccessTypeVisitor Visitor(GlobalState->TypeArray, + GlobalState->TypeVector.size(), + TestState->Offsets); + + for (uint32_t I : IndicesToVisit) { + TypeIndex TI = TypeIndex::fromArrayIndex(I); + EXPECT_NO_ERROR(Visitor.visitTypeIndex(TI, TestState->Pipeline)); + } + + // [0, 7] + EXPECT_EQ(8u, Visitor.database().size()); + for (uint32_t I = 0; I < 8; ++I) + EXPECT_TRUE(ValidateDatabaseRecord(Visitor, I)); + + // 2, 4, 7 + EXPECT_EQ(3u, TestState->Callbacks.count()); + for (auto &I : enumerate(IndicesToVisit)) + EXPECT_TRUE(ValidateVisitedRecord(I.index(), I.value())); +} + +TEST_F(RandomAccessVisitorTest, StopPrematurelyInChunk) { + // * Don't visit the last item in one chunk, ensuring that visitation stops + // at the record you specify, and the chunk is only partially visited. + // In the below example, this is tested by visiting 0 and 1 but not 2, + // all from the [0,3) chunk. + TestState->Offsets = createPartialOffsets(GlobalState->Stream, {0, 8}); + + std::vector<uint32_t> IndicesToVisit = {0, 1, 2}; + + RandomAccessTypeVisitor Visitor(GlobalState->TypeArray, + GlobalState->TypeVector.size(), + TestState->Offsets); + + for (uint32_t I : IndicesToVisit) { + TypeIndex TI = TypeIndex::fromArrayIndex(I); + EXPECT_NO_ERROR(Visitor.visitTypeIndex(TI, TestState->Pipeline)); + } + + // [0, 8) should be visited. + EXPECT_EQ(8u, Visitor.database().size()); + for (uint32_t I = 0; I < 8; ++I) + EXPECT_TRUE(ValidateDatabaseRecord(Visitor, I)); + + // [0, 2] + EXPECT_EQ(3u, TestState->Callbacks.count()); + for (auto I : enumerate(IndicesToVisit)) + EXPECT_TRUE(ValidateVisitedRecord(I.index(), I.value())); +} + +TEST_F(RandomAccessVisitorTest, InnerChunk) { + // Test that when a request comes from a chunk in the middle of the partial + // offsets array, that items from surrounding chunks are not visited or + // added to the database. + TestState->Offsets = createPartialOffsets(GlobalState->Stream, {0, 4, 9}); + + std::vector<uint32_t> IndicesToVisit = {5, 7}; + + RandomAccessTypeVisitor Visitor(GlobalState->TypeArray, + GlobalState->TypeVector.size(), + TestState->Offsets); + + for (uint32_t I : IndicesToVisit) { + TypeIndex TI = TypeIndex::fromArrayIndex(I); + EXPECT_NO_ERROR(Visitor.visitTypeIndex(TI, TestState->Pipeline)); + } + + // [4, 9) + EXPECT_EQ(5u, Visitor.database().size()); + for (uint32_t I = 4; I < 9; ++I) + EXPECT_TRUE(ValidateDatabaseRecord(Visitor, I)); + + // 5, 7 + EXPECT_EQ(2u, TestState->Callbacks.count()); + for (auto &I : enumerate(IndicesToVisit)) + EXPECT_TRUE(ValidateVisitedRecord(I.index(), I.value())); +} diff --git a/unittests/ExecutionEngine/Orc/ObjectTransformLayerTest.cpp b/unittests/ExecutionEngine/Orc/ObjectTransformLayerTest.cpp index 96214a368dce0..362c143c54ef4 100644 --- a/unittests/ExecutionEngine/Orc/ObjectTransformLayerTest.cpp +++ b/unittests/ExecutionEngine/Orc/ObjectTransformLayerTest.cpp @@ -304,7 +304,7 @@ TEST(ObjectTransformLayerTest, Main) { return nullptr; } void registerEHFrames(uint8_t *, uint64_t, size_t) override {} - void deregisterEHFrames(uint8_t *, uint64_t, size_t) override {} + void deregisterEHFrames() override {} bool finalizeMemory(std::string *) override { return false; } }; diff --git a/unittests/ExecutionEngine/Orc/OrcTestCommon.h b/unittests/ExecutionEngine/Orc/OrcTestCommon.h index 7fb26634c7a7a..dff72c6b9d575 100644 --- a/unittests/ExecutionEngine/Orc/OrcTestCommon.h +++ b/unittests/ExecutionEngine/Orc/OrcTestCommon.h @@ -101,7 +101,7 @@ class TypeBuilder<DummyStruct, XCompile> { public: static StructType *get(LLVMContext &Context) { return StructType::get( - TypeBuilder<types::i<32>[256], XCompile>::get(Context), nullptr); + TypeBuilder<types::i<32>[256], XCompile>::get(Context)); } }; diff --git a/unittests/ExecutionEngine/Orc/RTDyldObjectLinkingLayerTest.cpp b/unittests/ExecutionEngine/Orc/RTDyldObjectLinkingLayerTest.cpp index de99c022fb9dc..c13a75a5cbfe9 100644 --- a/unittests/ExecutionEngine/Orc/RTDyldObjectLinkingLayerTest.cpp +++ b/unittests/ExecutionEngine/Orc/RTDyldObjectLinkingLayerTest.cpp @@ -90,7 +90,8 @@ TEST(RTDyldObjectLinkingLayerTest, TestSetProcessAllSections) { Objs.push_back(OwningObj.getBinary()); bool DebugSectionSeen = false; - SectionMemoryManagerWrapper SMMW(DebugSectionSeen); + auto SMMW = + std::make_shared<SectionMemoryManagerWrapper>(DebugSectionSeen); auto Resolver = createLambdaResolver( [](const std::string &Name) { @@ -102,7 +103,7 @@ TEST(RTDyldObjectLinkingLayerTest, TestSetProcessAllSections) { { // Test with ProcessAllSections = false (the default). - auto H = ObjLayer.addObjectSet(Objs, &SMMW, &*Resolver); + auto H = ObjLayer.addObjectSet(Objs, SMMW, &*Resolver); ObjLayer.emitAndFinalize(H); EXPECT_EQ(DebugSectionSeen, false) << "Unexpected debug info section"; @@ -112,7 +113,7 @@ TEST(RTDyldObjectLinkingLayerTest, TestSetProcessAllSections) { { // Test with ProcessAllSections = true. ObjLayer.setProcessAllSections(true); - auto H = ObjLayer.addObjectSet(Objs, &SMMW, &*Resolver); + auto H = ObjLayer.addObjectSet(Objs, SMMW, &*Resolver); ObjLayer.emitAndFinalize(H); EXPECT_EQ(DebugSectionSeen, true) << "Expected debug info section not seen"; @@ -178,14 +179,15 @@ TEST_F(RTDyldObjectLinkingLayerExecutionTest, NoDuplicateFinalization) { return JITSymbol(nullptr); }); - SectionMemoryManagerWrapper SMMW; - ObjLayer.addObjectSet(std::move(Obj1Set), &SMMW, &*Resolver); - auto H = ObjLayer.addObjectSet(std::move(Obj2Set), &SMMW, &*Resolver); + auto SMMW = std::make_shared<SectionMemoryManagerWrapper>(); + ObjLayer.addObjectSet(std::move(Obj1Set), SMMW, &*Resolver); + auto H = ObjLayer.addObjectSet(std::move(Obj2Set), SMMW, &*Resolver); ObjLayer.emitAndFinalize(H); - + ObjLayer.removeObjectSet(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) + EXPECT_EQ(SMMW->FinalizationCount, 1) << "Extra call to finalize"; } @@ -238,14 +240,15 @@ TEST_F(RTDyldObjectLinkingLayerExecutionTest, NoPrematureAllocation) { std::vector<object::ObjectFile*> Obj2Set; Obj2Set.push_back(Obj2.getBinary()); - SectionMemoryManagerWrapper SMMW; + auto SMMW = std::make_shared<SectionMemoryManagerWrapper>(); NullResolver NR; - auto H = ObjLayer.addObjectSet(std::move(Obj1Set), &SMMW, &NR); - ObjLayer.addObjectSet(std::move(Obj2Set), &SMMW, &NR); + auto H = ObjLayer.addObjectSet(std::move(Obj1Set), SMMW, &NR); + ObjLayer.addObjectSet(std::move(Obj2Set), SMMW, &NR); ObjLayer.emitAndFinalize(H); - + ObjLayer.removeObjectSet(H); + // Only one call to needsToReserveAllocationSpace should have been made. - EXPECT_EQ(SMMW.NeedsToReserveAllocationSpaceCount, 1) + EXPECT_EQ(SMMW->NeedsToReserveAllocationSpaceCount, 1) << "More than one call to needsToReserveAllocationSpace " "(multiple unrelated objects loaded prior to finalization)"; } diff --git a/unittests/IR/ConstantRangeTest.cpp b/unittests/IR/ConstantRangeTest.cpp index b22f82154f403..c6c9bf6d6b503 100644 --- a/unittests/IR/ConstantRangeTest.cpp +++ b/unittests/IR/ConstantRangeTest.cpp @@ -443,6 +443,11 @@ TEST_F(ConstantRangeTest, Multiply) { EXPECT_EQ(ConstantRange(APInt(8, 254), APInt(8, 255)).multiply( ConstantRange(APInt(8, 2), APInt(8, 4))), ConstantRange(APInt(8, 250), APInt(8, 253))); + + // TODO: This should be return [-2, 0] + EXPECT_EQ(ConstantRange(APInt(8, -2)).multiply( + ConstantRange(APInt(8, 0), APInt(8, 2))), + ConstantRange(APInt(8, -2), APInt(8, 1))); } TEST_F(ConstantRangeTest, UMax) { @@ -703,13 +708,13 @@ TEST(ConstantRange, MakeGuaranteedNoWrapRegion) { Instruction::Add, ConstantRange(32, /* isFullSet = */ true), OBO::NoUnsignedWrap); EXPECT_TRUE(NUWForAllValues.isSingleElement() && - NSWForAllValues.getSingleElement()->isMinValue()); + NUWForAllValues.getSingleElement()->isMinValue()); auto NUWAndNSWForAllValues = ConstantRange::makeGuaranteedNoWrapRegion( Instruction::Add, ConstantRange(32, /* isFullSet = */ true), OBO::NoUnsignedWrap | OBO::NoSignedWrap); EXPECT_TRUE(NUWAndNSWForAllValues.isSingleElement() && - NSWForAllValues.getSingleElement()->isMinValue()); + NUWAndNSWForAllValues.getSingleElement()->isMinValue()); ConstantRange OneToFive(APInt(32, 1), APInt(32, 6)); EXPECT_EQ(ConstantRange::makeGuaranteedNoWrapRegion( diff --git a/unittests/IR/InstructionsTest.cpp b/unittests/IR/InstructionsTest.cpp index 7c75aaec17539..b8d398c5cc388 100644 --- a/unittests/IR/InstructionsTest.cpp +++ b/unittests/IR/InstructionsTest.cpp @@ -21,6 +21,7 @@ #include "llvm/IR/Module.h" #include "llvm/IR/NoFolder.h" #include "llvm/IR/Operator.h" +#include "gmock/gmock-matchers.h" #include "gtest/gtest.h" #include <memory> @@ -740,5 +741,11 @@ TEST(InstructionsTest, SwitchInst) { EXPECT_EQ(BB1.get(), Handle.getCaseSuccessor()); } +TEST(InstructionsTest, CommuteShuffleMask) { + SmallVector<int, 16> Indices({-1, 0, 7}); + ShuffleVectorInst::commuteShuffleMask(Indices, 4); + EXPECT_THAT(Indices, testing::ContainerEq(ArrayRef<int>({-1, 4, 3}))); +} + } // end anonymous namespace } // end namespace llvm diff --git a/unittests/IR/TypeBuilderTest.cpp b/unittests/IR/TypeBuilderTest.cpp index f2dccac001a4b..9ba776543d944 100644 --- a/unittests/IR/TypeBuilderTest.cpp +++ b/unittests/IR/TypeBuilderTest.cpp @@ -264,23 +264,21 @@ namespace { TEST(TypeBuilderTest, Extensions) { LLVMContext Context; - EXPECT_EQ(PointerType::getUnqual(StructType::get( - TypeBuilder<int, false>::get(Context), - TypeBuilder<int *, false>::get(Context), - TypeBuilder<void *[], false>::get(Context), (void *)nullptr)), + EXPECT_EQ(PointerType::getUnqual( + StructType::get(TypeBuilder<int, false>::get(Context), + TypeBuilder<int *, false>::get(Context), + TypeBuilder<void *[], false>::get(Context))), (TypeBuilder<MyType *, false>::get(Context))); - EXPECT_EQ( - PointerType::getUnqual(StructType::get( - TypeBuilder<types::i<32>, false>::get(Context), - TypeBuilder<types::i<32> *, false>::get(Context), - TypeBuilder<types::i<8> *[], false>::get(Context), (void *)nullptr)), - (TypeBuilder<MyPortableType *, false>::get(Context))); - EXPECT_EQ( - PointerType::getUnqual(StructType::get( - TypeBuilder<types::i<32>, false>::get(Context), - TypeBuilder<types::i<32> *, false>::get(Context), - TypeBuilder<types::i<8> *[], false>::get(Context), (void *)nullptr)), - (TypeBuilder<MyPortableType *, true>::get(Context))); + EXPECT_EQ(PointerType::getUnqual(StructType::get( + TypeBuilder<types::i<32>, false>::get(Context), + TypeBuilder<types::i<32> *, false>::get(Context), + TypeBuilder<types::i<8> *[], false>::get(Context))), + (TypeBuilder<MyPortableType *, false>::get(Context))); + EXPECT_EQ(PointerType::getUnqual(StructType::get( + TypeBuilder<types::i<32>, false>::get(Context), + TypeBuilder<types::i<32> *, false>::get(Context), + TypeBuilder<types::i<8> *[], false>::get(Context))), + (TypeBuilder<MyPortableType *, true>::get(Context))); } } // anonymous namespace diff --git a/unittests/Support/CMakeLists.txt b/unittests/Support/CMakeLists.txt index 1f677100dcef3..f8d3c1c9a8c77 100644 --- a/unittests/Support/CMakeLists.txt +++ b/unittests/Support/CMakeLists.txt @@ -36,6 +36,7 @@ add_llvm_unittest(SupportTests MemoryBufferTest.cpp MemoryTest.cpp NativeFormatTests.cpp + ParallelTest.cpp Path.cpp ProcessTest.cpp ProgramTest.cpp diff --git a/unittests/Support/DynamicLibrary/DynamicLibraryTest.cpp b/unittests/Support/DynamicLibrary/DynamicLibraryTest.cpp index d46eadc9a0460..0674a91282a1a 100644 --- a/unittests/Support/DynamicLibrary/DynamicLibraryTest.cpp +++ b/unittests/Support/DynamicLibrary/DynamicLibraryTest.cpp @@ -23,8 +23,10 @@ using namespace llvm::sys; extern "C" PIPSQUEAK_EXPORT const char *TestA() { return "ProcessCall"; } std::string LibPath() { + const std::vector<testing::internal::string>& Argvs = testing::internal::GetArgvs(); + const char *Argv0 = Argvs.size() > 0 ? Argvs[0].c_str() : "DynamicLibraryTests"; void *Ptr = (void*)(intptr_t)TestA; - std::string Path = fs::getMainExecutable("DynamicLibraryTests", Ptr); + std::string Path = fs::getMainExecutable(Argv0, Ptr); llvm::SmallString<256> Buf(path::parent_path(Path)); path::append(Buf, "PipSqueak.so"); return Buf.str(); diff --git a/unittests/Support/ParallelTest.cpp b/unittests/Support/ParallelTest.cpp new file mode 100644 index 0000000000000..d734e0dd8586a --- /dev/null +++ b/unittests/Support/ParallelTest.cpp @@ -0,0 +1,53 @@ +//===- llvm/unittest/Support/ParallelTest.cpp -----------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief Parallel.h unit tests. +/// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/Parallel.h" +#include "gtest/gtest.h" +#include <array> +#include <random> + +uint32_t array[1024 * 1024]; + +using namespace llvm; + +// Tests below are hanging up on mingw. Investigating. +#if !defined(__MINGW32__) + +TEST(Parallel, sort) { + std::mt19937 randEngine; + std::uniform_int_distribution<uint32_t> dist; + + for (auto &i : array) + i = dist(randEngine); + + sort(parallel::par, std::begin(array), std::end(array)); + ASSERT_TRUE(std::is_sorted(std::begin(array), std::end(array))); +} + +TEST(Parallel, parallel_for) { + // We need to test the case with a TaskSize > 1. We are white-box testing + // here. The TaskSize is calculated as (End - Begin) / 1024 at the time of + // writing. + uint32_t range[2050]; + std::fill(range, range + 2050, 1); + for_each_n(parallel::par, 0, 2049, [&range](size_t I) { ++range[I]; }); + + uint32_t expected[2049]; + std::fill(expected, expected + 2049, 2); + ASSERT_TRUE(std::equal(range, range + 2049, expected)); + // Check that we don't write past the end of the requested range. + ASSERT_EQ(range[2049], 1u); +} + +#endif diff --git a/unittests/Support/Path.cpp b/unittests/Support/Path.cpp index 426aff47c7462..a4bdcb5c79a27 100644 --- a/unittests/Support/Path.cpp +++ b/unittests/Support/Path.cpp @@ -1047,7 +1047,7 @@ TEST_F(FileSystemTest, MD5) { SmallString<64> TempPath; ASSERT_NO_ERROR(fs::createTemporaryFile("prefix", "temp", FD, TempPath)); StringRef Data("abcdefghijklmnopqrstuvwxyz"); - write(FD, Data.data(), Data.size()); + ASSERT_EQ(write(FD, Data.data(), Data.size()), static_cast<ssize_t>(Data.size())); lseek(FD, 0, SEEK_SET); auto Hash = fs::md5_contents(FD); ::close(FD); diff --git a/unittests/Transforms/Utils/Cloning.cpp b/unittests/Transforms/Utils/Cloning.cpp index 2f4ee8636530d..83f146dca704a 100644 --- a/unittests/Transforms/Utils/Cloning.cpp +++ b/unittests/Transforms/Utils/Cloning.cpp @@ -296,7 +296,6 @@ protected: Value* AllocaContent = IBuilder.getInt32(1); Instruction* Store = IBuilder.CreateStore(AllocaContent, Alloca); IBuilder.SetCurrentDebugLocation(DebugLoc::get(5, 2, Subprogram)); - Instruction* Terminator = IBuilder.CreateRetVoid(); // Create a local variable around the alloca auto *IntType = DBuilder.createBasicType("int", 32, dwarf::DW_ATE_signed); @@ -306,12 +305,25 @@ protected: auto *DL = DILocation::get(Subprogram->getContext(), 5, 0, Subprogram); DBuilder.insertDeclare(Alloca, Variable, E, DL, Store); DBuilder.insertDbgValueIntrinsic(AllocaContent, 0, Variable, E, DL, - Terminator); - // Finalize the debug info + Entry); + // Also create an inlined variable. + auto *InlinedSP = + DBuilder.createFunction(CU, "inlined", "inlined", File, 8, FuncType, + true, true, 9, DINode::FlagZero, false); + auto *InlinedVar = + DBuilder.createAutoVariable(InlinedSP, "inlined", File, 5, IntType, true); + auto *Scope = DBuilder.createLexicalBlock( + DBuilder.createLexicalBlockFile(InlinedSP, File), File, 1, 1); + auto InlinedDL = + DebugLoc::get(9, 4, Scope, DebugLoc::get(5, 2, Subprogram)); + IBuilder.SetCurrentDebugLocation(InlinedDL); + DBuilder.insertDeclare(Alloca, InlinedVar, E, InlinedDL, Store); + IBuilder.CreateStore(IBuilder.getInt32(2), Alloca); + // Finalize the debug info. DBuilder.finalize(); + IBuilder.CreateRetVoid(); - - // Create another, empty, compile unit + // Create another, empty, compile unit. DIBuilder DBuilder2(*M); DBuilder2.createCompileUnit(dwarf::DW_LANG_C99, DBuilder.createFile("extra.c", "/file/dir"), @@ -345,15 +357,8 @@ TEST_F(CloneFunc, NewFunctionCreated) { // function, while the original subprogram still points to the old one. TEST_F(CloneFunc, Subprogram) { EXPECT_FALSE(verifyModule(*M)); - - unsigned SubprogramCount = Finder->subprogram_count(); - EXPECT_EQ(1U, SubprogramCount); - - auto Iter = Finder->subprograms().begin(); - auto *Sub = cast<DISubprogram>(*Iter); - - EXPECT_TRUE(Sub == OldFunc->getSubprogram()); - EXPECT_TRUE(Sub == NewFunc->getSubprogram()); + EXPECT_EQ(3U, Finder->subprogram_count()); + EXPECT_NE(NewFunc->getSubprogram(), OldFunc->getSubprogram()); } // Test that instructions in the old function still belong to it in the @@ -380,8 +385,8 @@ TEST_F(CloneFunc, InstructionOwnership) { EXPECT_EQ(OldDL.getCol(), NewDL.getCol()); // But that they belong to different functions - auto *OldSubprogram = cast<DISubprogram>(OldDL.getScope()); - auto *NewSubprogram = cast<DISubprogram>(NewDL.getScope()); + auto *OldSubprogram = cast<DISubprogram>(OldDL.getInlinedAtScope()); + auto *NewSubprogram = cast<DISubprogram>(NewDL.getInlinedAtScope()); EXPECT_EQ(OldFunc->getSubprogram(), OldSubprogram); EXPECT_EQ(NewFunc->getSubprogram(), NewSubprogram); } @@ -416,22 +421,26 @@ TEST_F(CloneFunc, DebugIntrinsics) { EXPECT_EQ(NewFunc, cast<AllocaInst>(NewIntrin->getAddress())-> getParent()->getParent()); - // Old variable must belong to the old function - EXPECT_EQ(OldFunc->getSubprogram(), - cast<DISubprogram>(OldIntrin->getVariable()->getScope())); - // New variable must belong to the New function - EXPECT_EQ(NewFunc->getSubprogram(), - cast<DISubprogram>(NewIntrin->getVariable()->getScope())); + if (!OldIntrin->getDebugLoc()->getInlinedAt()) { + // Old variable must belong to the old function. + EXPECT_EQ(OldFunc->getSubprogram(), + cast<DISubprogram>(OldIntrin->getVariable()->getScope())); + // New variable must belong to the new function. + EXPECT_EQ(NewFunc->getSubprogram(), + cast<DISubprogram>(NewIntrin->getVariable()->getScope())); + } } else if (DbgValueInst* OldIntrin = dyn_cast<DbgValueInst>(&OldI)) { DbgValueInst* NewIntrin = dyn_cast<DbgValueInst>(&NewI); EXPECT_TRUE(NewIntrin); - // Old variable must belong to the old function - EXPECT_EQ(OldFunc->getSubprogram(), - cast<DISubprogram>(OldIntrin->getVariable()->getScope())); - // New variable must belong to the New function - EXPECT_EQ(NewFunc->getSubprogram(), - cast<DISubprogram>(NewIntrin->getVariable()->getScope())); + if (!OldIntrin->getDebugLoc()->getInlinedAt()) { + // Old variable must belong to the old function. + EXPECT_EQ(OldFunc->getSubprogram(), + cast<DISubprogram>(OldIntrin->getVariable()->getScope())); + // New variable must belong to the new function. + EXPECT_EQ(NewFunc->getSubprogram(), + cast<DISubprogram>(NewIntrin->getVariable()->getScope())); + } } ++OldIter; |