aboutsummaryrefslogtreecommitdiffstats
path: root/unittests
diff options
context:
space:
mode:
authorStephen Hines <srhines@google.com>2014-05-29 02:49:00 -0700
committerStephen Hines <srhines@google.com>2014-05-29 02:49:00 -0700
commitdce4a407a24b04eebc6a376f8e62b41aaa7b071f (patch)
treedcebc53f2b182f145a2e659393bf9a0472cedf23 /unittests
parent220b921aed042f9e520c26cffd8282a94c66c3d5 (diff)
downloadexternal_llvm-dce4a407a24b04eebc6a376f8e62b41aaa7b071f.zip
external_llvm-dce4a407a24b04eebc6a376f8e62b41aaa7b071f.tar.gz
external_llvm-dce4a407a24b04eebc6a376f8e62b41aaa7b071f.tar.bz2
Update LLVM for 3.5 rebase (r209712).
Change-Id: I149556c940fb7dc92d075273c87ff584f400941f
Diffstat (limited to 'unittests')
-rw-r--r--unittests/ADT/PointerUnionTest.cpp44
-rw-r--r--unittests/ADT/SCCIteratorTest.cpp2
-rw-r--r--unittests/ADT/SmallVectorTest.cpp63
-rw-r--r--unittests/ADT/StringMapTest.cpp88
-rw-r--r--unittests/ADT/StringRefTest.cpp1
-rw-r--r--unittests/Analysis/CMakeLists.txt2
-rw-r--r--unittests/Analysis/LazyCallGraphTest.cpp720
-rw-r--r--unittests/Analysis/MixedTBAATest.cpp77
-rw-r--r--unittests/Bitcode/BitReaderTest.cpp1
-rw-r--r--unittests/CMakeLists.txt1
-rw-r--r--unittests/CodeGen/DIEHashTest.cpp200
-rw-r--r--unittests/ExecutionEngine/JIT/IntelJITEventListenerTest.cpp2
-rw-r--r--unittests/ExecutionEngine/JIT/JITTest.cpp4
-rw-r--r--unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp27
-rw-r--r--unittests/IR/CMakeLists.txt1
-rw-r--r--unittests/IR/ConstantsTest.cpp28
-rw-r--r--unittests/IR/InstructionsTest.cpp33
-rw-r--r--unittests/IR/MDBuilderTest.cpp1
-rw-r--r--unittests/IR/UserTest.cpp96
-rw-r--r--unittests/IR/VerifierTest.cpp4
-rw-r--r--unittests/LineEditor/LineEditor.cpp1
-rw-r--r--unittests/Linker/LinkModulesTest.cpp39
-rw-r--r--unittests/Object/CMakeLists.txt1
-rw-r--r--unittests/Object/StringTableBuilderTest.cpp40
-rw-r--r--unittests/Option/OptionParsingTest.cpp20
-rw-r--r--unittests/Support/AllocatorTest.cpp58
-rw-r--r--unittests/Support/BlockFrequencyTest.cpp147
-rw-r--r--unittests/Support/BranchProbabilityTest.cpp282
-rw-r--r--unittests/Support/CMakeLists.txt4
-rw-r--r--unittests/Support/CompressionTest.cpp17
-rw-r--r--unittests/Support/FileOutputBufferTest.cpp9
-rw-r--r--unittests/Support/IteratorTest.cpp101
-rw-r--r--unittests/Support/MemoryBufferTest.cpp3
-rw-r--r--unittests/Support/YAMLIOTest.cpp48
-rw-r--r--unittests/Transforms/Utils/SpecialCaseList.cpp5
35 files changed, 1821 insertions, 349 deletions
diff --git a/unittests/ADT/PointerUnionTest.cpp b/unittests/ADT/PointerUnionTest.cpp
index 7eb7181..3bfb79c 100644
--- a/unittests/ADT/PointerUnionTest.cpp
+++ b/unittests/ADT/PointerUnionTest.cpp
@@ -13,22 +13,24 @@ using namespace llvm;
namespace {
-typedef PointerUnion<int*, float*> PU;
+typedef PointerUnion<int *, float *> PU;
-// Test fixture
-class PointerUnionTest : public testing::Test {
-};
+struct PointerUnionTest : public testing::Test {
+ float f;
+ int i;
-float f = 3.14f;
-int i = 42;
+ PU a, b, c, n;
-const PU a(&f);
-const PU b(&i);
-const PU n;
+ PointerUnionTest() : f(3.14f), i(42), a(&f), b(&i), c(&i), n() {}
+};
TEST_F(PointerUnionTest, Comparison) {
+ EXPECT_TRUE(a == a);
+ EXPECT_FALSE(a != a);
EXPECT_TRUE(a != b);
EXPECT_FALSE(a == b);
+ EXPECT_TRUE(b == c);
+ EXPECT_FALSE(b != c);
EXPECT_TRUE(b != n);
EXPECT_FALSE(b == n);
}
@@ -44,21 +46,27 @@ TEST_F(PointerUnionTest, Null) {
EXPECT_TRUE((bool)a);
EXPECT_TRUE((bool)b);
EXPECT_FALSE(n);
+
+ EXPECT_NE(n, b);
+ EXPECT_EQ(b, c);
+ b = nullptr;
+ EXPECT_EQ(n, b);
+ EXPECT_NE(b, c);
}
TEST_F(PointerUnionTest, Is) {
- EXPECT_FALSE(a.is<int*>());
- EXPECT_TRUE(a.is<float*>());
- EXPECT_TRUE(b.is<int*>());
- EXPECT_FALSE(b.is<float*>());
- EXPECT_TRUE(n.is<int*>());
- EXPECT_FALSE(n.is<float*>());
+ EXPECT_FALSE(a.is<int *>());
+ EXPECT_TRUE(a.is<float *>());
+ EXPECT_TRUE(b.is<int *>());
+ EXPECT_FALSE(b.is<float *>());
+ EXPECT_TRUE(n.is<int *>());
+ EXPECT_FALSE(n.is<float *>());
}
TEST_F(PointerUnionTest, Get) {
- EXPECT_EQ(a.get<float*>(), &f);
- EXPECT_EQ(b.get<int*>(), &i);
- EXPECT_EQ(n.get<int*>(), (int*)0);
+ EXPECT_EQ(a.get<float *>(), &f);
+ EXPECT_EQ(b.get<int *>(), &i);
+ EXPECT_EQ(n.get<int *>(), (int *)0);
}
} // end anonymous namespace
diff --git a/unittests/ADT/SCCIteratorTest.cpp b/unittests/ADT/SCCIteratorTest.cpp
index 92b4b31..8609732 100644
--- a/unittests/ADT/SCCIteratorTest.cpp
+++ b/unittests/ADT/SCCIteratorTest.cpp
@@ -277,7 +277,7 @@ TEST(SCCIteratorTest, AllSmallGraphs) {
GT::NodeSubset NodesInSomeSCC;
for (scc_iterator<GT> I = scc_begin(G), E = scc_end(G); I != E; ++I) {
- std::vector<GT::NodeType*> &SCC = *I;
+ const std::vector<GT::NodeType *> &SCC = *I;
// Get the nodes in this SCC as a NodeSubset rather than a vector.
GT::NodeSubset NodesInThisSCC;
diff --git a/unittests/ADT/SmallVectorTest.cpp b/unittests/ADT/SmallVectorTest.cpp
index 90c7982..58f5591 100644
--- a/unittests/ADT/SmallVectorTest.cpp
+++ b/unittests/ADT/SmallVectorTest.cpp
@@ -29,27 +29,43 @@ private:
static int numDestructorCalls;
static int numAssignmentCalls;
+ bool constructed;
int value;
public:
- Constructable() : value(0) {
+ Constructable() : constructed(true), value(0) {
++numConstructorCalls;
}
- Constructable(int val) : value(val) {
+ Constructable(int val) : constructed(true), value(val) {
++numConstructorCalls;
}
- Constructable(const Constructable & src) {
+ Constructable(const Constructable & src) : constructed(true) {
+ value = src.value;
+ ++numConstructorCalls;
+ }
+
+ Constructable(Constructable && src) : constructed(true) {
value = src.value;
++numConstructorCalls;
}
~Constructable() {
+ EXPECT_TRUE(constructed);
++numDestructorCalls;
+ constructed = false;
}
Constructable & operator=(const Constructable & src) {
+ EXPECT_TRUE(constructed);
+ value = src.value;
+ ++numAssignmentCalls;
+ return *this;
+ }
+
+ Constructable & operator=(Constructable && src) {
+ EXPECT_TRUE(constructed);
value = src.value;
++numAssignmentCalls;
return *this;
@@ -338,6 +354,36 @@ TYPED_TEST(SmallVectorTest, AssignTest) {
this->assertValuesInOrder(this->theVector, 2u, 77, 77);
}
+// Move-assign test
+TYPED_TEST(SmallVectorTest, MoveAssignTest) {
+ SCOPED_TRACE("MoveAssignTest");
+
+ // Set up our vector with a single element, but enough capacity for 4.
+ this->theVector.reserve(4);
+ this->theVector.push_back(Constructable(1));
+
+ // Set up the other vector with 2 elements.
+ this->otherVector.push_back(Constructable(2));
+ this->otherVector.push_back(Constructable(3));
+
+ // Move-assign from the other vector.
+ this->theVector = std::move(this->otherVector);
+
+ // Make sure we have the right result.
+ this->assertValuesInOrder(this->theVector, 2u, 2, 3);
+
+ // Make sure the # of constructor/destructor calls line up. There
+ // are two live objects after clearing the other vector.
+ this->otherVector.clear();
+ EXPECT_EQ(Constructable::getNumConstructorCalls()-2,
+ Constructable::getNumDestructorCalls());
+
+ // There shouldn't be any live objects any more.
+ this->theVector.clear();
+ EXPECT_EQ(Constructable::getNumConstructorCalls(),
+ Constructable::getNumDestructorCalls());
+}
+
// Erase a single element
TYPED_TEST(SmallVectorTest, EraseTest) {
SCOPED_TRACE("EraseTest");
@@ -455,13 +501,12 @@ TYPED_TEST(SmallVectorTest, DirectVectorTest) {
this->theVector.reserve(4);
EXPECT_LE(4u, this->theVector.capacity());
EXPECT_EQ(0, Constructable::getNumConstructorCalls());
- this->theVector.end()[0] = 1;
- this->theVector.end()[1] = 2;
- this->theVector.end()[2] = 3;
- this->theVector.end()[3] = 4;
- this->theVector.set_size(4);
+ this->theVector.push_back(1);
+ this->theVector.push_back(2);
+ this->theVector.push_back(3);
+ this->theVector.push_back(4);
EXPECT_EQ(4u, this->theVector.size());
- EXPECT_EQ(4, Constructable::getNumConstructorCalls());
+ EXPECT_EQ(8, Constructable::getNumConstructorCalls());
EXPECT_EQ(1, this->theVector[0].getValue());
EXPECT_EQ(2, this->theVector[1].getValue());
EXPECT_EQ(3, this->theVector[2].getValue());
diff --git a/unittests/ADT/StringMapTest.cpp b/unittests/ADT/StringMapTest.cpp
index b6d41bc..de18e07 100644
--- a/unittests/ADT/StringMapTest.cpp
+++ b/unittests/ADT/StringMapTest.cpp
@@ -218,4 +218,92 @@ TEST_F(StringMapTest, NonDefaultConstructable) {
ASSERT_EQ(iter->second.i, 123);
}
+struct MoveOnly {
+ int i;
+ MoveOnly(int i) : i(i) {}
+ MoveOnly(MoveOnly &&RHS) : i(RHS.i) {}
+ MoveOnly &operator=(MoveOnly &&RHS) {
+ i = RHS.i;
+ return *this;
+ }
+
+private:
+ MoveOnly(const MoveOnly &);
+ MoveOnly &operator=(const MoveOnly &);
+};
+
+TEST_F(StringMapTest, MoveOnlyKey) {
+ StringMap<MoveOnly> t;
+ t.GetOrCreateValue("Test", MoveOnly(42));
+ StringRef Key = "Test";
+ StringMapEntry<MoveOnly>::Create(Key.begin(), Key.end(), MoveOnly(42))
+ ->Destroy();
+}
+
+TEST_F(StringMapTest, MoveConstruct) {
+ StringMap<int> A;
+ A.GetOrCreateValue("x", 42);
+ StringMap<int> B = std::move(A);
+ ASSERT_EQ(A.size(), 0u);
+ ASSERT_EQ(B.size(), 1u);
+ ASSERT_EQ(B["x"], 42);
+ ASSERT_EQ(B.count("y"), 0u);
+}
+
+TEST_F(StringMapTest, MoveAssignment) {
+ StringMap<int> A;
+ A["x"] = 42;
+ StringMap<int> B;
+ B["y"] = 117;
+ A = std::move(B);
+ ASSERT_EQ(A.size(), 1u);
+ ASSERT_EQ(B.size(), 0u);
+ ASSERT_EQ(A["y"], 117);
+ ASSERT_EQ(B.count("x"), 0u);
+}
+
+struct Countable {
+ int &InstanceCount;
+ int Number;
+ Countable(int Number, int &InstanceCount)
+ : InstanceCount(InstanceCount), Number(Number) {
+ ++InstanceCount;
+ }
+ Countable(Countable &&C) : InstanceCount(C.InstanceCount), Number(C.Number) {
+ ++InstanceCount;
+ C.Number = -1;
+ }
+ Countable(const Countable &C)
+ : InstanceCount(C.InstanceCount), Number(C.Number) {
+ ++InstanceCount;
+ }
+ Countable &operator=(Countable C) {
+ Number = C.Number;
+ return *this;
+ }
+ ~Countable() { --InstanceCount; }
+};
+
+TEST_F(StringMapTest, MoveDtor) {
+ int InstanceCount = 0;
+ StringMap<Countable> A;
+ A.GetOrCreateValue("x", Countable(42, InstanceCount));
+ ASSERT_EQ(InstanceCount, 1);
+ auto I = A.find("x");
+ ASSERT_NE(I, A.end());
+ ASSERT_EQ(I->second.Number, 42);
+
+ StringMap<Countable> B;
+ B = std::move(A);
+ ASSERT_EQ(InstanceCount, 1);
+ ASSERT_TRUE(A.empty());
+ I = B.find("x");
+ ASSERT_NE(I, B.end());
+ ASSERT_EQ(I->second.Number, 42);
+
+ B = StringMap<Countable>();
+ ASSERT_EQ(InstanceCount, 0);
+ ASSERT_TRUE(B.empty());
+}
+
} // end anonymous namespace
diff --git a/unittests/ADT/StringRefTest.cpp b/unittests/ADT/StringRefTest.cpp
index c7fd9d0..d80179b 100644
--- a/unittests/ADT/StringRefTest.cpp
+++ b/unittests/ADT/StringRefTest.cpp
@@ -9,6 +9,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Hashing.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/Allocator.h"
diff --git a/unittests/Analysis/CMakeLists.txt b/unittests/Analysis/CMakeLists.txt
index d9f8c0c..8454860 100644
--- a/unittests/Analysis/CMakeLists.txt
+++ b/unittests/Analysis/CMakeLists.txt
@@ -7,5 +7,7 @@ set(LLVM_LINK_COMPONENTS
add_llvm_unittest(AnalysisTests
CFGTest.cpp
+ LazyCallGraphTest.cpp
ScalarEvolutionTest.cpp
+ MixedTBAATest.cpp
)
diff --git a/unittests/Analysis/LazyCallGraphTest.cpp b/unittests/Analysis/LazyCallGraphTest.cpp
new file mode 100644
index 0000000..d7c7045
--- /dev/null
+++ b/unittests/Analysis/LazyCallGraphTest.cpp
@@ -0,0 +1,720 @@
+//===- LazyCallGraphTest.cpp - Unit tests for the lazy CG analysis --------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Analysis/LazyCallGraph.h"
+#include "llvm/AsmParser/Parser.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/SourceMgr.h"
+#include "gtest/gtest.h"
+#include <memory>
+
+using namespace llvm;
+
+namespace {
+
+std::unique_ptr<Module> parseAssembly(const char *Assembly) {
+ auto M = make_unique<Module>("Module", getGlobalContext());
+
+ SMDiagnostic Error;
+ bool Parsed =
+ ParseAssemblyString(Assembly, M.get(), Error, M->getContext()) == M.get();
+
+ std::string ErrMsg;
+ raw_string_ostream OS(ErrMsg);
+ Error.print("", OS);
+
+ // A failure here means that the test itself is buggy.
+ if (!Parsed)
+ report_fatal_error(OS.str().c_str());
+
+ return M;
+}
+
+// IR forming a call graph with a diamond of triangle-shaped SCCs:
+//
+// d1
+// / \
+// d3--d2
+// / \
+// b1 c1
+// / \ / \
+// b3--b2 c3--c2
+// \ /
+// a1
+// / \
+// a3--a2
+//
+// All call edges go up between SCCs, and clockwise around the SCC.
+static const char DiamondOfTriangles[] =
+ "define void @a1() {\n"
+ "entry:\n"
+ " call void @a2()\n"
+ " call void @b2()\n"
+ " call void @c3()\n"
+ " ret void\n"
+ "}\n"
+ "define void @a2() {\n"
+ "entry:\n"
+ " call void @a3()\n"
+ " ret void\n"
+ "}\n"
+ "define void @a3() {\n"
+ "entry:\n"
+ " call void @a1()\n"
+ " ret void\n"
+ "}\n"
+ "define void @b1() {\n"
+ "entry:\n"
+ " call void @b2()\n"
+ " call void @d3()\n"
+ " ret void\n"
+ "}\n"
+ "define void @b2() {\n"
+ "entry:\n"
+ " call void @b3()\n"
+ " ret void\n"
+ "}\n"
+ "define void @b3() {\n"
+ "entry:\n"
+ " call void @b1()\n"
+ " ret void\n"
+ "}\n"
+ "define void @c1() {\n"
+ "entry:\n"
+ " call void @c2()\n"
+ " call void @d2()\n"
+ " ret void\n"
+ "}\n"
+ "define void @c2() {\n"
+ "entry:\n"
+ " call void @c3()\n"
+ " ret void\n"
+ "}\n"
+ "define void @c3() {\n"
+ "entry:\n"
+ " call void @c1()\n"
+ " ret void\n"
+ "}\n"
+ "define void @d1() {\n"
+ "entry:\n"
+ " call void @d2()\n"
+ " ret void\n"
+ "}\n"
+ "define void @d2() {\n"
+ "entry:\n"
+ " call void @d3()\n"
+ " ret void\n"
+ "}\n"
+ "define void @d3() {\n"
+ "entry:\n"
+ " call void @d1()\n"
+ " ret void\n"
+ "}\n";
+
+TEST(LazyCallGraphTest, BasicGraphFormation) {
+ std::unique_ptr<Module> M = parseAssembly(DiamondOfTriangles);
+ LazyCallGraph CG(*M);
+
+ // The order of the entry nodes should be stable w.r.t. the source order of
+ // the IR, and everything in our module is an entry node, so just directly
+ // build variables for each node.
+ auto I = CG.begin();
+ LazyCallGraph::Node &A1 = *I++;
+ EXPECT_EQ("a1", A1.getFunction().getName());
+ LazyCallGraph::Node &A2 = *I++;
+ EXPECT_EQ("a2", A2.getFunction().getName());
+ LazyCallGraph::Node &A3 = *I++;
+ EXPECT_EQ("a3", A3.getFunction().getName());
+ LazyCallGraph::Node &B1 = *I++;
+ EXPECT_EQ("b1", B1.getFunction().getName());
+ LazyCallGraph::Node &B2 = *I++;
+ EXPECT_EQ("b2", B2.getFunction().getName());
+ LazyCallGraph::Node &B3 = *I++;
+ EXPECT_EQ("b3", B3.getFunction().getName());
+ LazyCallGraph::Node &C1 = *I++;
+ EXPECT_EQ("c1", C1.getFunction().getName());
+ LazyCallGraph::Node &C2 = *I++;
+ EXPECT_EQ("c2", C2.getFunction().getName());
+ LazyCallGraph::Node &C3 = *I++;
+ EXPECT_EQ("c3", C3.getFunction().getName());
+ LazyCallGraph::Node &D1 = *I++;
+ EXPECT_EQ("d1", D1.getFunction().getName());
+ LazyCallGraph::Node &D2 = *I++;
+ EXPECT_EQ("d2", D2.getFunction().getName());
+ LazyCallGraph::Node &D3 = *I++;
+ EXPECT_EQ("d3", D3.getFunction().getName());
+ EXPECT_EQ(CG.end(), I);
+
+ // Build vectors and sort them for the rest of the assertions to make them
+ // independent of order.
+ std::vector<std::string> Nodes;
+
+ for (LazyCallGraph::Node &N : A1)
+ Nodes.push_back(N.getFunction().getName());
+ std::sort(Nodes.begin(), Nodes.end());
+ EXPECT_EQ("a2", Nodes[0]);
+ EXPECT_EQ("b2", Nodes[1]);
+ EXPECT_EQ("c3", Nodes[2]);
+ Nodes.clear();
+
+ EXPECT_EQ(A2.end(), std::next(A2.begin()));
+ EXPECT_EQ("a3", A2.begin()->getFunction().getName());
+ EXPECT_EQ(A3.end(), std::next(A3.begin()));
+ EXPECT_EQ("a1", A3.begin()->getFunction().getName());
+
+ for (LazyCallGraph::Node &N : B1)
+ Nodes.push_back(N.getFunction().getName());
+ std::sort(Nodes.begin(), Nodes.end());
+ EXPECT_EQ("b2", Nodes[0]);
+ EXPECT_EQ("d3", Nodes[1]);
+ Nodes.clear();
+
+ EXPECT_EQ(B2.end(), std::next(B2.begin()));
+ EXPECT_EQ("b3", B2.begin()->getFunction().getName());
+ EXPECT_EQ(B3.end(), std::next(B3.begin()));
+ EXPECT_EQ("b1", B3.begin()->getFunction().getName());
+
+ for (LazyCallGraph::Node &N : C1)
+ Nodes.push_back(N.getFunction().getName());
+ std::sort(Nodes.begin(), Nodes.end());
+ EXPECT_EQ("c2", Nodes[0]);
+ EXPECT_EQ("d2", Nodes[1]);
+ Nodes.clear();
+
+ EXPECT_EQ(C2.end(), std::next(C2.begin()));
+ EXPECT_EQ("c3", C2.begin()->getFunction().getName());
+ EXPECT_EQ(C3.end(), std::next(C3.begin()));
+ EXPECT_EQ("c1", C3.begin()->getFunction().getName());
+
+ EXPECT_EQ(D1.end(), std::next(D1.begin()));
+ EXPECT_EQ("d2", D1.begin()->getFunction().getName());
+ EXPECT_EQ(D2.end(), std::next(D2.begin()));
+ EXPECT_EQ("d3", D2.begin()->getFunction().getName());
+ EXPECT_EQ(D3.end(), std::next(D3.begin()));
+ EXPECT_EQ("d1", D3.begin()->getFunction().getName());
+
+ // Now lets look at the SCCs.
+ auto SCCI = CG.postorder_scc_begin();
+
+ LazyCallGraph::SCC &D = *SCCI++;
+ for (LazyCallGraph::Node *N : D)
+ Nodes.push_back(N->getFunction().getName());
+ std::sort(Nodes.begin(), Nodes.end());
+ EXPECT_EQ(3u, Nodes.size());
+ EXPECT_EQ("d1", Nodes[0]);
+ EXPECT_EQ("d2", Nodes[1]);
+ EXPECT_EQ("d3", Nodes[2]);
+ Nodes.clear();
+ EXPECT_FALSE(D.isParentOf(D));
+ EXPECT_FALSE(D.isChildOf(D));
+ EXPECT_FALSE(D.isAncestorOf(D));
+ EXPECT_FALSE(D.isDescendantOf(D));
+
+ LazyCallGraph::SCC &C = *SCCI++;
+ for (LazyCallGraph::Node *N : C)
+ Nodes.push_back(N->getFunction().getName());
+ std::sort(Nodes.begin(), Nodes.end());
+ EXPECT_EQ(3u, Nodes.size());
+ EXPECT_EQ("c1", Nodes[0]);
+ EXPECT_EQ("c2", Nodes[1]);
+ EXPECT_EQ("c3", Nodes[2]);
+ Nodes.clear();
+ EXPECT_TRUE(C.isParentOf(D));
+ EXPECT_FALSE(C.isChildOf(D));
+ EXPECT_TRUE(C.isAncestorOf(D));
+ EXPECT_FALSE(C.isDescendantOf(D));
+
+ LazyCallGraph::SCC &B = *SCCI++;
+ for (LazyCallGraph::Node *N : B)
+ Nodes.push_back(N->getFunction().getName());
+ std::sort(Nodes.begin(), Nodes.end());
+ EXPECT_EQ(3u, Nodes.size());
+ EXPECT_EQ("b1", Nodes[0]);
+ EXPECT_EQ("b2", Nodes[1]);
+ EXPECT_EQ("b3", Nodes[2]);
+ Nodes.clear();
+ EXPECT_TRUE(B.isParentOf(D));
+ EXPECT_FALSE(B.isChildOf(D));
+ EXPECT_TRUE(B.isAncestorOf(D));
+ EXPECT_FALSE(B.isDescendantOf(D));
+ EXPECT_FALSE(B.isAncestorOf(C));
+ EXPECT_FALSE(C.isAncestorOf(B));
+
+ LazyCallGraph::SCC &A = *SCCI++;
+ for (LazyCallGraph::Node *N : A)
+ Nodes.push_back(N->getFunction().getName());
+ std::sort(Nodes.begin(), Nodes.end());
+ EXPECT_EQ(3u, Nodes.size());
+ EXPECT_EQ("a1", Nodes[0]);
+ EXPECT_EQ("a2", Nodes[1]);
+ EXPECT_EQ("a3", Nodes[2]);
+ Nodes.clear();
+ EXPECT_TRUE(A.isParentOf(B));
+ EXPECT_TRUE(A.isParentOf(C));
+ EXPECT_FALSE(A.isParentOf(D));
+ EXPECT_TRUE(A.isAncestorOf(B));
+ EXPECT_TRUE(A.isAncestorOf(C));
+ EXPECT_TRUE(A.isAncestorOf(D));
+
+ EXPECT_EQ(CG.postorder_scc_end(), SCCI);
+}
+
+static Function &lookupFunction(Module &M, StringRef Name) {
+ for (Function &F : M)
+ if (F.getName() == Name)
+ return F;
+ report_fatal_error("Couldn't find function!");
+}
+
+TEST(LazyCallGraphTest, BasicGraphMutation) {
+ std::unique_ptr<Module> M = parseAssembly(
+ "define void @a() {\n"
+ "entry:\n"
+ " call void @b()\n"
+ " call void @c()\n"
+ " ret void\n"
+ "}\n"
+ "define void @b() {\n"
+ "entry:\n"
+ " ret void\n"
+ "}\n"
+ "define void @c() {\n"
+ "entry:\n"
+ " ret void\n"
+ "}\n");
+ LazyCallGraph CG(*M);
+
+ LazyCallGraph::Node &A = CG.get(lookupFunction(*M, "a"));
+ LazyCallGraph::Node &B = CG.get(lookupFunction(*M, "b"));
+ EXPECT_EQ(2, std::distance(A.begin(), A.end()));
+ EXPECT_EQ(0, std::distance(B.begin(), B.end()));
+
+ CG.insertEdge(B, lookupFunction(*M, "c"));
+ EXPECT_EQ(1, std::distance(B.begin(), B.end()));
+ LazyCallGraph::Node &C = *B.begin();
+ EXPECT_EQ(0, std::distance(C.begin(), C.end()));
+
+ CG.insertEdge(C, B.getFunction());
+ EXPECT_EQ(1, std::distance(C.begin(), C.end()));
+ EXPECT_EQ(&B, &*C.begin());
+
+ CG.insertEdge(C, C.getFunction());
+ EXPECT_EQ(2, std::distance(C.begin(), C.end()));
+ EXPECT_EQ(&B, &*C.begin());
+ EXPECT_EQ(&C, &*std::next(C.begin()));
+
+ CG.removeEdge(C, B.getFunction());
+ EXPECT_EQ(1, std::distance(C.begin(), C.end()));
+ EXPECT_EQ(&C, &*C.begin());
+
+ CG.removeEdge(C, C.getFunction());
+ EXPECT_EQ(0, std::distance(C.begin(), C.end()));
+
+ CG.removeEdge(B, C.getFunction());
+ EXPECT_EQ(0, std::distance(B.begin(), B.end()));
+}
+
+TEST(LazyCallGraphTest, MultiArmSCC) {
+ // Two interlocking cycles. The really useful thing about this SCC is that it
+ // will require Tarjan's DFS to backtrack and finish processing all of the
+ // children of each node in the SCC.
+ std::unique_ptr<Module> M = parseAssembly(
+ "define void @a() {\n"
+ "entry:\n"
+ " call void @b()\n"
+ " call void @d()\n"
+ " ret void\n"
+ "}\n"
+ "define void @b() {\n"
+ "entry:\n"
+ " call void @c()\n"
+ " ret void\n"
+ "}\n"
+ "define void @c() {\n"
+ "entry:\n"
+ " call void @a()\n"
+ " ret void\n"
+ "}\n"
+ "define void @d() {\n"
+ "entry:\n"
+ " call void @e()\n"
+ " ret void\n"
+ "}\n"
+ "define void @e() {\n"
+ "entry:\n"
+ " call void @a()\n"
+ " ret void\n"
+ "}\n");
+ LazyCallGraph CG(*M);
+
+ // Force the graph to be fully expanded.
+ auto SCCI = CG.postorder_scc_begin();
+ LazyCallGraph::SCC &SCC = *SCCI++;
+ EXPECT_EQ(CG.postorder_scc_end(), SCCI);
+
+ LazyCallGraph::Node &A = *CG.lookup(lookupFunction(*M, "a"));
+ LazyCallGraph::Node &B = *CG.lookup(lookupFunction(*M, "b"));
+ LazyCallGraph::Node &C = *CG.lookup(lookupFunction(*M, "c"));
+ LazyCallGraph::Node &D = *CG.lookup(lookupFunction(*M, "d"));
+ LazyCallGraph::Node &E = *CG.lookup(lookupFunction(*M, "e"));
+ EXPECT_EQ(&SCC, CG.lookupSCC(A));
+ EXPECT_EQ(&SCC, CG.lookupSCC(B));
+ EXPECT_EQ(&SCC, CG.lookupSCC(C));
+ EXPECT_EQ(&SCC, CG.lookupSCC(D));
+ EXPECT_EQ(&SCC, CG.lookupSCC(E));
+}
+
+TEST(LazyCallGraphTest, OutgoingSCCEdgeInsertion) {
+ std::unique_ptr<Module> M = parseAssembly(
+ "define void @a() {\n"
+ "entry:\n"
+ " call void @b()\n"
+ " call void @c()\n"
+ " ret void\n"
+ "}\n"
+ "define void @b() {\n"
+ "entry:\n"
+ " call void @d()\n"
+ " ret void\n"
+ "}\n"
+ "define void @c() {\n"
+ "entry:\n"
+ " call void @d()\n"
+ " ret void\n"
+ "}\n"
+ "define void @d() {\n"
+ "entry:\n"
+ " ret void\n"
+ "}\n");
+ LazyCallGraph CG(*M);
+
+ // Force the graph to be fully expanded.
+ for (LazyCallGraph::SCC &C : CG.postorder_sccs())
+ (void)C;
+
+ LazyCallGraph::Node &A = *CG.lookup(lookupFunction(*M, "a"));
+ LazyCallGraph::Node &B = *CG.lookup(lookupFunction(*M, "b"));
+ LazyCallGraph::Node &C = *CG.lookup(lookupFunction(*M, "c"));
+ LazyCallGraph::Node &D = *CG.lookup(lookupFunction(*M, "d"));
+ LazyCallGraph::SCC &AC = *CG.lookupSCC(A);
+ LazyCallGraph::SCC &BC = *CG.lookupSCC(B);
+ LazyCallGraph::SCC &CC = *CG.lookupSCC(C);
+ LazyCallGraph::SCC &DC = *CG.lookupSCC(D);
+ EXPECT_TRUE(AC.isAncestorOf(BC));
+ EXPECT_TRUE(AC.isAncestorOf(CC));
+ EXPECT_TRUE(AC.isAncestorOf(DC));
+ EXPECT_TRUE(DC.isDescendantOf(AC));
+ EXPECT_TRUE(DC.isDescendantOf(BC));
+ EXPECT_TRUE(DC.isDescendantOf(CC));
+
+ EXPECT_EQ(2, std::distance(A.begin(), A.end()));
+ AC.insertOutgoingEdge(A, D);
+ EXPECT_EQ(3, std::distance(A.begin(), A.end()));
+ EXPECT_TRUE(AC.isParentOf(DC));
+ EXPECT_EQ(&AC, CG.lookupSCC(A));
+ EXPECT_EQ(&BC, CG.lookupSCC(B));
+ EXPECT_EQ(&CC, CG.lookupSCC(C));
+ EXPECT_EQ(&DC, CG.lookupSCC(D));
+}
+
+TEST(LazyCallGraphTest, IncomingSCCEdgeInsertion) {
+ // We want to ensure we can add edges even across complex diamond graphs, so
+ // we use the diamond of triangles graph defined above. The ascii diagram is
+ // repeated here for easy reference.
+ //
+ // d1 |
+ // / \ |
+ // d3--d2 |
+ // / \ |
+ // b1 c1 |
+ // / \ / \ |
+ // b3--b2 c3--c2 |
+ // \ / |
+ // a1 |
+ // / \ |
+ // a3--a2 |
+ //
+ std::unique_ptr<Module> M = parseAssembly(DiamondOfTriangles);
+ LazyCallGraph CG(*M);
+
+ // Force the graph to be fully expanded.
+ for (LazyCallGraph::SCC &C : CG.postorder_sccs())
+ (void)C;
+
+ LazyCallGraph::Node &A1 = *CG.lookup(lookupFunction(*M, "a1"));
+ LazyCallGraph::Node &A2 = *CG.lookup(lookupFunction(*M, "a2"));
+ LazyCallGraph::Node &A3 = *CG.lookup(lookupFunction(*M, "a3"));
+ LazyCallGraph::Node &B1 = *CG.lookup(lookupFunction(*M, "b1"));
+ LazyCallGraph::Node &B2 = *CG.lookup(lookupFunction(*M, "b2"));
+ LazyCallGraph::Node &B3 = *CG.lookup(lookupFunction(*M, "b3"));
+ LazyCallGraph::Node &C1 = *CG.lookup(lookupFunction(*M, "c1"));
+ LazyCallGraph::Node &C2 = *CG.lookup(lookupFunction(*M, "c2"));
+ LazyCallGraph::Node &C3 = *CG.lookup(lookupFunction(*M, "c3"));
+ LazyCallGraph::Node &D1 = *CG.lookup(lookupFunction(*M, "d1"));
+ LazyCallGraph::Node &D2 = *CG.lookup(lookupFunction(*M, "d2"));
+ LazyCallGraph::Node &D3 = *CG.lookup(lookupFunction(*M, "d3"));
+ LazyCallGraph::SCC &AC = *CG.lookupSCC(A1);
+ LazyCallGraph::SCC &BC = *CG.lookupSCC(B1);
+ LazyCallGraph::SCC &CC = *CG.lookupSCC(C1);
+ LazyCallGraph::SCC &DC = *CG.lookupSCC(D1);
+ ASSERT_EQ(&AC, CG.lookupSCC(A2));
+ ASSERT_EQ(&AC, CG.lookupSCC(A3));
+ ASSERT_EQ(&BC, CG.lookupSCC(B2));
+ ASSERT_EQ(&BC, CG.lookupSCC(B3));
+ ASSERT_EQ(&CC, CG.lookupSCC(C2));
+ ASSERT_EQ(&CC, CG.lookupSCC(C3));
+ ASSERT_EQ(&DC, CG.lookupSCC(D2));
+ ASSERT_EQ(&DC, CG.lookupSCC(D3));
+ ASSERT_EQ(1, std::distance(D2.begin(), D2.end()));
+
+ // Add an edge to make the graph:
+ //
+ // d1 |
+ // / \ |
+ // d3--d2---. |
+ // / \ | |
+ // b1 c1 | |
+ // / \ / \ / |
+ // b3--b2 c3--c2 |
+ // \ / |
+ // a1 |
+ // / \ |
+ // a3--a2 |
+ CC.insertIncomingEdge(D2, C2);
+ // Make sure we connected the nodes.
+ EXPECT_EQ(2, std::distance(D2.begin(), D2.end()));
+
+ // Make sure we have the correct nodes in the SCC sets.
+ EXPECT_EQ(&AC, CG.lookupSCC(A1));
+ EXPECT_EQ(&AC, CG.lookupSCC(A2));
+ EXPECT_EQ(&AC, CG.lookupSCC(A3));
+ EXPECT_EQ(&BC, CG.lookupSCC(B1));
+ EXPECT_EQ(&BC, CG.lookupSCC(B2));
+ EXPECT_EQ(&BC, CG.lookupSCC(B3));
+ EXPECT_EQ(&CC, CG.lookupSCC(C1));
+ EXPECT_EQ(&CC, CG.lookupSCC(C2));
+ EXPECT_EQ(&CC, CG.lookupSCC(C3));
+ EXPECT_EQ(&CC, CG.lookupSCC(D1));
+ EXPECT_EQ(&CC, CG.lookupSCC(D2));
+ EXPECT_EQ(&CC, CG.lookupSCC(D3));
+
+ // And that ancestry tests have been updated.
+ EXPECT_TRUE(AC.isParentOf(BC));
+ EXPECT_TRUE(AC.isParentOf(CC));
+ EXPECT_FALSE(AC.isAncestorOf(DC));
+ EXPECT_FALSE(BC.isAncestorOf(DC));
+ EXPECT_FALSE(CC.isAncestorOf(DC));
+}
+
+TEST(LazyCallGraphTest, IncomingSCCEdgeInsertionMidTraversal) {
+ // This is the same fundamental test as the previous, but we perform it
+ // having only partially walked the SCCs of the graph.
+ std::unique_ptr<Module> M = parseAssembly(DiamondOfTriangles);
+ LazyCallGraph CG(*M);
+
+ // Walk the SCCs until we find the one containing 'c1'.
+ auto SCCI = CG.postorder_scc_begin(), SCCE = CG.postorder_scc_end();
+ ASSERT_NE(SCCI, SCCE);
+ LazyCallGraph::SCC &DC = *SCCI;
+ ASSERT_NE(&DC, nullptr);
+ ++SCCI;
+ ASSERT_NE(SCCI, SCCE);
+ LazyCallGraph::SCC &CC = *SCCI;
+ ASSERT_NE(&CC, nullptr);
+
+ ASSERT_EQ(nullptr, CG.lookup(lookupFunction(*M, "a1")));
+ ASSERT_EQ(nullptr, CG.lookup(lookupFunction(*M, "a2")));
+ ASSERT_EQ(nullptr, CG.lookup(lookupFunction(*M, "a3")));
+ ASSERT_EQ(nullptr, CG.lookup(lookupFunction(*M, "b1")));
+ ASSERT_EQ(nullptr, CG.lookup(lookupFunction(*M, "b2")));
+ ASSERT_EQ(nullptr, CG.lookup(lookupFunction(*M, "b3")));
+ LazyCallGraph::Node &C1 = *CG.lookup(lookupFunction(*M, "c1"));
+ LazyCallGraph::Node &C2 = *CG.lookup(lookupFunction(*M, "c2"));
+ LazyCallGraph::Node &C3 = *CG.lookup(lookupFunction(*M, "c3"));
+ LazyCallGraph::Node &D1 = *CG.lookup(lookupFunction(*M, "d1"));
+ LazyCallGraph::Node &D2 = *CG.lookup(lookupFunction(*M, "d2"));
+ LazyCallGraph::Node &D3 = *CG.lookup(lookupFunction(*M, "d3"));
+ ASSERT_EQ(&CC, CG.lookupSCC(C1));
+ ASSERT_EQ(&CC, CG.lookupSCC(C2));
+ ASSERT_EQ(&CC, CG.lookupSCC(C3));
+ ASSERT_EQ(&DC, CG.lookupSCC(D1));
+ ASSERT_EQ(&DC, CG.lookupSCC(D2));
+ ASSERT_EQ(&DC, CG.lookupSCC(D3));
+ ASSERT_EQ(1, std::distance(D2.begin(), D2.end()));
+
+ CC.insertIncomingEdge(D2, C2);
+ EXPECT_EQ(2, std::distance(D2.begin(), D2.end()));
+
+ // Make sure we have the correct nodes in the SCC sets.
+ EXPECT_EQ(&CC, CG.lookupSCC(C1));
+ EXPECT_EQ(&CC, CG.lookupSCC(C2));
+ EXPECT_EQ(&CC, CG.lookupSCC(C3));
+ EXPECT_EQ(&CC, CG.lookupSCC(D1));
+ EXPECT_EQ(&CC, CG.lookupSCC(D2));
+ EXPECT_EQ(&CC, CG.lookupSCC(D3));
+
+ // Check that we can form the last two SCCs now in a coherent way.
+ ++SCCI;
+ EXPECT_NE(SCCI, SCCE);
+ LazyCallGraph::SCC &BC = *SCCI;
+ EXPECT_NE(&BC, nullptr);
+ EXPECT_EQ(&BC, CG.lookupSCC(*CG.lookup(lookupFunction(*M, "b1"))));
+ EXPECT_EQ(&BC, CG.lookupSCC(*CG.lookup(lookupFunction(*M, "b2"))));
+ EXPECT_EQ(&BC, CG.lookupSCC(*CG.lookup(lookupFunction(*M, "b3"))));
+ ++SCCI;
+ EXPECT_NE(SCCI, SCCE);
+ LazyCallGraph::SCC &AC = *SCCI;
+ EXPECT_NE(&AC, nullptr);
+ EXPECT_EQ(&AC, CG.lookupSCC(*CG.lookup(lookupFunction(*M, "a1"))));
+ EXPECT_EQ(&AC, CG.lookupSCC(*CG.lookup(lookupFunction(*M, "a2"))));
+ EXPECT_EQ(&AC, CG.lookupSCC(*CG.lookup(lookupFunction(*M, "a3"))));
+ ++SCCI;
+ EXPECT_EQ(SCCI, SCCE);
+}
+
+TEST(LazyCallGraphTest, InterSCCEdgeRemoval) {
+ std::unique_ptr<Module> M = parseAssembly(
+ "define void @a() {\n"
+ "entry:\n"
+ " call void @b()\n"
+ " ret void\n"
+ "}\n"
+ "define void @b() {\n"
+ "entry:\n"
+ " ret void\n"
+ "}\n");
+ LazyCallGraph CG(*M);
+
+ // Force the graph to be fully expanded.
+ for (LazyCallGraph::SCC &C : CG.postorder_sccs())
+ (void)C;
+
+ LazyCallGraph::Node &A = *CG.lookup(lookupFunction(*M, "a"));
+ LazyCallGraph::Node &B = *CG.lookup(lookupFunction(*M, "b"));
+ LazyCallGraph::SCC &AC = *CG.lookupSCC(A);
+ LazyCallGraph::SCC &BC = *CG.lookupSCC(B);
+
+ EXPECT_EQ("b", A.begin()->getFunction().getName());
+ EXPECT_EQ(B.end(), B.begin());
+ EXPECT_EQ(&AC, &*BC.parent_begin());
+
+ AC.removeInterSCCEdge(A, B);
+
+ EXPECT_EQ(A.end(), A.begin());
+ EXPECT_EQ(B.end(), B.begin());
+ EXPECT_EQ(BC.parent_end(), BC.parent_begin());
+}
+
+TEST(LazyCallGraphTest, IntraSCCEdgeInsertion) {
+ std::unique_ptr<Module> M1 = parseAssembly(
+ "define void @a() {\n"
+ "entry:\n"
+ " call void @b()\n"
+ " ret void\n"
+ "}\n"
+ "define void @b() {\n"
+ "entry:\n"
+ " call void @c()\n"
+ " ret void\n"
+ "}\n"
+ "define void @c() {\n"
+ "entry:\n"
+ " call void @a()\n"
+ " ret void\n"
+ "}\n");
+ LazyCallGraph CG1(*M1);
+
+ // Force the graph to be fully expanded.
+ auto SCCI = CG1.postorder_scc_begin();
+ LazyCallGraph::SCC &SCC = *SCCI++;
+ EXPECT_EQ(CG1.postorder_scc_end(), SCCI);
+
+ LazyCallGraph::Node &A = *CG1.lookup(lookupFunction(*M1, "a"));
+ LazyCallGraph::Node &B = *CG1.lookup(lookupFunction(*M1, "b"));
+ LazyCallGraph::Node &C = *CG1.lookup(lookupFunction(*M1, "c"));
+ EXPECT_EQ(&SCC, CG1.lookupSCC(A));
+ EXPECT_EQ(&SCC, CG1.lookupSCC(B));
+ EXPECT_EQ(&SCC, CG1.lookupSCC(C));
+
+ // Insert an edge from 'a' to 'c'. Nothing changes about the SCCs.
+ SCC.insertIntraSCCEdge(A, C);
+ EXPECT_EQ(2, std::distance(A.begin(), A.end()));
+ EXPECT_EQ(&SCC, CG1.lookupSCC(A));
+ EXPECT_EQ(&SCC, CG1.lookupSCC(B));
+ EXPECT_EQ(&SCC, CG1.lookupSCC(C));
+
+ // Insert a self edge from 'a' back to 'a'.
+ SCC.insertIntraSCCEdge(A, A);
+ EXPECT_EQ(3, std::distance(A.begin(), A.end()));
+ EXPECT_EQ(&SCC, CG1.lookupSCC(A));
+ EXPECT_EQ(&SCC, CG1.lookupSCC(B));
+ EXPECT_EQ(&SCC, CG1.lookupSCC(C));
+}
+
+TEST(LazyCallGraphTest, IntraSCCEdgeRemoval) {
+ // A nice fully connected (including self-edges) SCC.
+ std::unique_ptr<Module> M1 = parseAssembly(
+ "define void @a() {\n"
+ "entry:\n"
+ " call void @a()\n"
+ " call void @b()\n"
+ " call void @c()\n"
+ " ret void\n"
+ "}\n"
+ "define void @b() {\n"
+ "entry:\n"
+ " call void @a()\n"
+ " call void @b()\n"
+ " call void @c()\n"
+ " ret void\n"
+ "}\n"
+ "define void @c() {\n"
+ "entry:\n"
+ " call void @a()\n"
+ " call void @b()\n"
+ " call void @c()\n"
+ " ret void\n"
+ "}\n");
+ LazyCallGraph CG1(*M1);
+
+ // Force the graph to be fully expanded.
+ auto SCCI = CG1.postorder_scc_begin();
+ LazyCallGraph::SCC &SCC = *SCCI++;
+ EXPECT_EQ(CG1.postorder_scc_end(), SCCI);
+
+ LazyCallGraph::Node &A = *CG1.lookup(lookupFunction(*M1, "a"));
+ LazyCallGraph::Node &B = *CG1.lookup(lookupFunction(*M1, "b"));
+ LazyCallGraph::Node &C = *CG1.lookup(lookupFunction(*M1, "c"));
+ EXPECT_EQ(&SCC, CG1.lookupSCC(A));
+ EXPECT_EQ(&SCC, CG1.lookupSCC(B));
+ EXPECT_EQ(&SCC, CG1.lookupSCC(C));
+
+ // Remove the edge from b -> a, which should leave the 3 functions still in
+ // a single connected component because of a -> b -> c -> a.
+ SmallVector<LazyCallGraph::SCC *, 1> NewSCCs = SCC.removeIntraSCCEdge(B, A);
+ EXPECT_EQ(0u, NewSCCs.size());
+ EXPECT_EQ(&SCC, CG1.lookupSCC(A));
+ EXPECT_EQ(&SCC, CG1.lookupSCC(B));
+ EXPECT_EQ(&SCC, CG1.lookupSCC(C));
+
+ // Remove the edge from c -> a, which should leave 'a' in the original SCC
+ // and form a new SCC for 'b' and 'c'.
+ NewSCCs = SCC.removeIntraSCCEdge(C, A);
+ EXPECT_EQ(1u, NewSCCs.size());
+ EXPECT_EQ(&SCC, CG1.lookupSCC(A));
+ EXPECT_EQ(1, std::distance(SCC.begin(), SCC.end()));
+ LazyCallGraph::SCC *SCC2 = CG1.lookupSCC(B);
+ EXPECT_EQ(SCC2, CG1.lookupSCC(C));
+ EXPECT_EQ(SCC2, NewSCCs[0]);
+}
+
+}
diff --git a/unittests/Analysis/MixedTBAATest.cpp b/unittests/Analysis/MixedTBAATest.cpp
new file mode 100644
index 0000000..2cf7c73
--- /dev/null
+++ b/unittests/Analysis/MixedTBAATest.cpp
@@ -0,0 +1,77 @@
+//===--- MixedTBAATest.cpp - Mixed TBAA unit tests ------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Analysis/Passes.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/MDBuilder.h"
+#include "llvm/IR/Module.h"
+#include "llvm/PassManager.h"
+#include "llvm/Support/CommandLine.h"
+#include "gtest/gtest.h"
+
+namespace llvm {
+namespace {
+
+class MixedTBAATest : public testing::Test {
+protected:
+ MixedTBAATest() : M("MixedTBAATest", C), MD(C) {}
+
+ LLVMContext C;
+ Module M;
+ MDBuilder MD;
+ PassManager PM;
+};
+
+TEST_F(MixedTBAATest, MixedTBAA) {
+ // Setup function.
+ FunctionType *FTy = FunctionType::get(Type::getVoidTy(C),
+ std::vector<Type *>(), false);
+ auto *F = cast<Function>(M.getOrInsertFunction("f", FTy));
+ auto *BB = BasicBlock::Create(C, "entry", F);
+ auto IntType = Type::getInt32Ty(C);
+ auto PtrType = Type::getInt32PtrTy(C);
+ auto *Value = ConstantInt::get(IntType, 42);
+ auto *Addr = ConstantPointerNull::get(PtrType);
+
+ auto *Store1 = new StoreInst(Value, Addr, BB);
+ auto *Store2 = new StoreInst(Value, Addr, BB);
+ ReturnInst::Create(C, 0, BB);
+
+ // New TBAA metadata
+ {
+ auto RootMD = MD.createTBAARoot("Simple C/C++ TBAA");
+ auto MD1 = MD.createTBAAScalarTypeNode("omnipotent char", RootMD);
+ auto MD2 = MD.createTBAAScalarTypeNode("int", MD1);
+ auto MD3 = MD.createTBAAStructTagNode(MD2, MD2, 0);
+ Store2->setMetadata(LLVMContext::MD_tbaa, MD3);
+ }
+
+ // Old TBAA metadata
+ {
+ auto RootMD = MD.createTBAARoot("Simple C/C++ TBAA");
+ auto MD1 = MD.createTBAANode("omnipotent char", RootMD);
+ auto MD2 = MD.createTBAANode("int", MD1);
+ Store1->setMetadata(LLVMContext::MD_tbaa, MD2);
+ }
+
+ // Run the TBAA eval pass on a mixture of path-aware and non-path-aware TBAA.
+ // The order of the metadata (path-aware vs non-path-aware) is important,
+ // because the AA eval pass only runs one test per store-pair.
+ const char* args[] = { "MixedTBAATest", "-evaluate-tbaa" };
+ cl::ParseCommandLineOptions(sizeof(args) / sizeof(const char*), args);
+ PM.add(createTypeBasedAliasAnalysisPass());
+ PM.add(createAAEvalPass());
+ PM.run(M);
+}
+
+} // end anonymous namspace
+} // end llvm namespace
+
diff --git a/unittests/Bitcode/BitReaderTest.cpp b/unittests/Bitcode/BitReaderTest.cpp
index ba03023..b6a3e9a 100644
--- a/unittests/Bitcode/BitReaderTest.cpp
+++ b/unittests/Bitcode/BitReaderTest.cpp
@@ -59,6 +59,7 @@ TEST(BitReaderTest, MaterializeFunctionsForBlockAddr) { // PR11677
std::unique_ptr<Module> m(ModuleOrErr.get());
PassManager passes;
passes.add(createVerifierPass());
+ passes.add(createDebugInfoVerifierPass());
passes.run(*m);
}
diff --git a/unittests/CMakeLists.txt b/unittests/CMakeLists.txt
index 9e2f60c..bbab2a1 100644
--- a/unittests/CMakeLists.txt
+++ b/unittests/CMakeLists.txt
@@ -19,6 +19,7 @@ add_subdirectory(DebugInfo)
add_subdirectory(ExecutionEngine)
add_subdirectory(IR)
add_subdirectory(LineEditor)
+add_subdirectory(Linker)
add_subdirectory(MC)
add_subdirectory(Object)
add_subdirectory(Option)
diff --git a/unittests/CodeGen/DIEHashTest.cpp b/unittests/CodeGen/DIEHashTest.cpp
index c874cef..04c5a8a 100644
--- a/unittests/CodeGen/DIEHashTest.cpp
+++ b/unittests/CodeGen/DIEHashTest.cpp
@@ -12,6 +12,7 @@
#include "llvm/Support/Debug.h"
#include "llvm/Support/Dwarf.h"
#include "llvm/Support/Format.h"
+#include "llvm/ADT/STLExtras.h"
#include "gtest/gtest.h"
using namespace llvm;
@@ -59,7 +60,7 @@ TEST(DIEHashTest, NamedType) {
TEST(DIEHashTest, NamespacedType) {
DIE CU(dwarf::DW_TAG_compile_unit);
- DIE *Space = new DIE(dwarf::DW_TAG_namespace);
+ auto Space = make_unique<DIE>(dwarf::DW_TAG_namespace);
DIEInteger One(1);
DIEString SpaceStr(&One, "space");
Space->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &SpaceStr);
@@ -67,15 +68,16 @@ TEST(DIEHashTest, NamespacedType) {
Space->addValue(dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present, &One);
// sibling?
- DIE *Foo = new DIE(dwarf::DW_TAG_structure_type);
+ auto Foo = make_unique<DIE>(dwarf::DW_TAG_structure_type);
DIEString FooStr(&One, "foo");
Foo->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr);
Foo->addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &One);
- Space->addChild(Foo);
- CU.addChild(Space);
+ DIE &N = *Foo;
+ Space->addChild(std::move(Foo));
+ CU.addChild(std::move(Space));
- uint64_t MD5Res = DIEHash().computeTypeSignature(*Foo);
+ uint64_t MD5Res = DIEHash().computeTypeSignature(N);
// The exact same hash GCC produces for this DIE.
ASSERT_EQ(0x7b80381fd17f1e33ULL, MD5Res);
@@ -87,15 +89,6 @@ TEST(DIEHashTest, TypeWithMember) {
DIEInteger Four(4);
Unnamed.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Four);
- DIE *Member = new DIE(dwarf::DW_TAG_member);
- DIEString MemberStr(&Four, "member");
- Member->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &MemberStr);
- DIEInteger Zero(0);
- Member->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1,
- &Zero);
-
- Unnamed.addChild(Member);
-
DIE Int(dwarf::DW_TAG_base_type);
DIEString IntStr(&Four, "int");
Int.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &IntStr);
@@ -103,9 +96,18 @@ TEST(DIEHashTest, TypeWithMember) {
DIEInteger Five(5);
Int.addValue(dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, &Five);
- DIEEntry IntRef(&Int);
+ DIEEntry IntRef(Int);
+
+ auto Member = make_unique<DIE>(dwarf::DW_TAG_member);
+ DIEString MemberStr(&Four, "member");
+ Member->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &MemberStr);
+ DIEInteger Zero(0);
+ Member->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1,
+ &Zero);
Member->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &IntRef);
+ Unnamed.addChild(std::move(Member));
+
uint64_t MD5Res = DIEHash().computeTypeSignature(Unnamed);
ASSERT_EQ(0x5646aa436b7e07c6ULL, MD5Res);
@@ -117,35 +119,35 @@ TEST(DIEHashTest, ReusedType) {
DIEInteger Eight(8);
Unnamed.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Eight);
- DIE *Mem1 = new DIE(dwarf::DW_TAG_member);
DIEInteger Four(4);
+ DIE Int(dwarf::DW_TAG_base_type);
+ DIEString IntStr(&Four, "int");
+ Int.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &IntStr);
+ Int.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Four);
+ DIEInteger Five(5);
+ Int.addValue(dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, &Five);
+
+ DIEEntry IntRef(Int);
+
+ auto Mem1 = make_unique<DIE>(dwarf::DW_TAG_member);
DIEString Mem1Str(&Four, "mem1");
Mem1->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &Mem1Str);
DIEInteger Zero(0);
Mem1->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1,
&Zero);
+ Mem1->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &IntRef);
- Unnamed.addChild(Mem1);
+ Unnamed.addChild(std::move(Mem1));
- DIE *Mem2 = new DIE(dwarf::DW_TAG_member);
+ auto Mem2 = make_unique<DIE>(dwarf::DW_TAG_member);
DIEString Mem2Str(&Four, "mem2");
Mem2->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &Mem2Str);
Mem2->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1,
&Four);
-
- Unnamed.addChild(Mem2);
-
- DIE Int(dwarf::DW_TAG_base_type);
- DIEString IntStr(&Four, "int");
- Int.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &IntStr);
- Int.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Four);
- DIEInteger Five(5);
- Int.addValue(dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, &Five);
-
- DIEEntry IntRef(&Int);
- Mem1->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &IntRef);
Mem2->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &IntRef);
+ Unnamed.addChild(std::move(Mem2));
+
uint64_t MD5Res = DIEHash().computeTypeSignature(Unnamed);
ASSERT_EQ(0x3a7dc3ed7b76b2f8ULL, MD5Res);
@@ -159,14 +161,14 @@ TEST(DIEHashTest, RecursiveType) {
DIEString FooStr(&One, "foo");
Foo.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr);
- DIE *Mem = new DIE(dwarf::DW_TAG_member);
+ auto Mem = make_unique<DIE>(dwarf::DW_TAG_member);
DIEString MemStr(&One, "mem");
Mem->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &MemStr);
- DIEEntry FooRef(&Foo);
+ DIEEntry FooRef(Foo);
Mem->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &FooRef);
// DW_AT_external and DW_AT_declaration are ignored anyway, so skip them.
- Foo.addChild(Mem);
+ Foo.addChild(std::move(Mem));
uint64_t MD5Res = DIEHash().computeTypeSignature(Foo);
@@ -181,7 +183,7 @@ TEST(DIEHashTest, Pointer) {
DIEString FooStr(&Eight, "foo");
Foo.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr);
- DIE *Mem = new DIE(dwarf::DW_TAG_member);
+ auto Mem = make_unique<DIE>(dwarf::DW_TAG_member);
DIEString MemStr(&Eight, "mem");
Mem->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &MemStr);
DIEInteger Zero(0);
@@ -189,13 +191,13 @@ TEST(DIEHashTest, Pointer) {
DIE FooPtr(dwarf::DW_TAG_pointer_type);
FooPtr.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Eight);
- DIEEntry FooRef(&Foo);
+ DIEEntry FooRef(Foo);
FooPtr.addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &FooRef);
- DIEEntry FooPtrRef(&FooPtr);
+ DIEEntry FooPtrRef(FooPtr);
Mem->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &FooPtrRef);
- Foo.addChild(Mem);
+ Foo.addChild(std::move(Mem));
uint64_t MD5Res = DIEHash().computeTypeSignature(Foo);
@@ -210,7 +212,7 @@ TEST(DIEHashTest, Reference) {
DIEString FooStr(&Eight, "foo");
Foo.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr);
- DIE *Mem = new DIE(dwarf::DW_TAG_member);
+ auto Mem = make_unique<DIE>(dwarf::DW_TAG_member);
DIEString MemStr(&Eight, "mem");
Mem->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &MemStr);
DIEInteger Zero(0);
@@ -218,17 +220,17 @@ TEST(DIEHashTest, Reference) {
DIE FooRef(dwarf::DW_TAG_reference_type);
FooRef.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Eight);
- DIEEntry FooEntry(&Foo);
+ DIEEntry FooEntry(Foo);
FooRef.addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &FooEntry);
DIE FooRefConst(dwarf::DW_TAG_const_type);
- DIEEntry FooRefRef(&FooRef);
+ DIEEntry FooRefRef(FooRef);
FooRefConst.addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &FooRefRef);
- DIEEntry FooRefConstRef(&FooRefConst);
+ DIEEntry FooRefConstRef(FooRefConst);
Mem->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &FooRefConstRef);
- Foo.addChild(Mem);
+ Foo.addChild(std::move(Mem));
uint64_t MD5Res = DIEHash().computeTypeSignature(Foo);
@@ -243,7 +245,7 @@ TEST(DIEHashTest, RValueReference) {
DIEString FooStr(&Eight, "foo");
Foo.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr);
- DIE *Mem = new DIE(dwarf::DW_TAG_member);
+ auto Mem = make_unique<DIE>(dwarf::DW_TAG_member);
DIEString MemStr(&Eight, "mem");
Mem->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &MemStr);
DIEInteger Zero(0);
@@ -251,17 +253,17 @@ TEST(DIEHashTest, RValueReference) {
DIE FooRef(dwarf::DW_TAG_rvalue_reference_type);
FooRef.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Eight);
- DIEEntry FooEntry(&Foo);
+ DIEEntry FooEntry(Foo);
FooRef.addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &FooEntry);
DIE FooRefConst(dwarf::DW_TAG_const_type);
- DIEEntry FooRefRef(&FooRef);
+ DIEEntry FooRefRef(FooRef);
FooRefConst.addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &FooRefRef);
- DIEEntry FooRefConstRef(&FooRefConst);
+ DIEEntry FooRefConstRef(FooRefConst);
Mem->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &FooRefConstRef);
- Foo.addChild(Mem);
+ Foo.addChild(std::move(Mem));
uint64_t MD5Res = DIEHash().computeTypeSignature(Foo);
@@ -276,22 +278,22 @@ TEST(DIEHashTest, PtrToMember) {
DIEString FooStr(&Eight, "foo");
Foo.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr);
- DIE *Mem = new DIE(dwarf::DW_TAG_member);
+ auto Mem = make_unique<DIE>(dwarf::DW_TAG_member);
DIEString MemStr(&Eight, "mem");
Mem->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &MemStr);
DIEInteger Zero(0);
Mem->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1, &Zero);
DIE PtrToFooMem(dwarf::DW_TAG_ptr_to_member_type);
- DIEEntry FooEntry(&Foo);
+ DIEEntry FooEntry(Foo);
PtrToFooMem.addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &FooEntry);
PtrToFooMem.addValue(dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4,
&FooEntry);
- DIEEntry PtrToFooMemRef(&PtrToFooMem);
+ DIEEntry PtrToFooMemRef(PtrToFooMem);
Mem->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &PtrToFooMemRef);
- Foo.addChild(Mem);
+ Foo.addChild(std::move(Mem));
uint64_t MD5Res = DIEHash().computeTypeSignature(Foo);
@@ -320,22 +322,22 @@ TEST(DIEHashTest, PtrToMemberDeclDefMatch) {
Foo.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Eight);
Foo.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr);
- DIE *Mem = new DIE(dwarf::DW_TAG_member);
+ auto Mem = make_unique<DIE>(dwarf::DW_TAG_member);
Mem->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &MemStr);
Mem->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1,
&Zero);
DIE PtrToFooMem(dwarf::DW_TAG_ptr_to_member_type);
- DIEEntry BarEntry(&Bar);
+ DIEEntry BarEntry(Bar);
PtrToFooMem.addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &BarEntry);
- DIEEntry FooEntry(&Foo);
+ DIEEntry FooEntry(Foo);
PtrToFooMem.addValue(dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4,
&FooEntry);
- DIEEntry PtrToFooMemRef(&PtrToFooMem);
+ DIEEntry PtrToFooMemRef(PtrToFooMem);
Mem->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &PtrToFooMemRef);
- Foo.addChild(Mem);
+ Foo.addChild(std::move(Mem));
MD5ResDecl = DIEHash().computeTypeSignature(Foo);
}
@@ -349,22 +351,22 @@ TEST(DIEHashTest, PtrToMemberDeclDefMatch) {
Foo.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Eight);
Foo.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr);
- DIE *Mem = new DIE(dwarf::DW_TAG_member);
+ auto Mem = make_unique<DIE>(dwarf::DW_TAG_member);
Mem->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &MemStr);
Mem->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1,
&Zero);
DIE PtrToFooMem(dwarf::DW_TAG_ptr_to_member_type);
- DIEEntry BarEntry(&Bar);
+ DIEEntry BarEntry(Bar);
PtrToFooMem.addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &BarEntry);
- DIEEntry FooEntry(&Foo);
+ DIEEntry FooEntry(Foo);
PtrToFooMem.addValue(dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4,
&FooEntry);
- DIEEntry PtrToFooMemRef(&PtrToFooMem);
+ DIEEntry PtrToFooMemRef(PtrToFooMem);
Mem->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &PtrToFooMemRef);
- Foo.addChild(Mem);
+ Foo.addChild(std::move(Mem));
MD5ResDef = DIEHash().computeTypeSignature(Foo);
}
@@ -393,21 +395,21 @@ TEST(DIEHashTest, PtrToMemberDeclDefMisMatch) {
Foo.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Eight);
Foo.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr);
- DIE *Mem = new DIE(dwarf::DW_TAG_member);
+ auto Mem = make_unique<DIE>(dwarf::DW_TAG_member);
Mem->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &MemStr);
Mem->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1,
&Zero);
DIE PtrToFooMem(dwarf::DW_TAG_ptr_to_member_type);
- DIEEntry BarEntry(&Bar);
+ DIEEntry BarEntry(Bar);
PtrToFooMem.addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &BarEntry);
PtrToFooMem.addValue(dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4,
&BarEntry);
- DIEEntry PtrToFooMemRef(&PtrToFooMem);
+ DIEEntry PtrToFooMemRef(PtrToFooMem);
Mem->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &PtrToFooMemRef);
- Foo.addChild(Mem);
+ Foo.addChild(std::move(Mem));
MD5ResDecl = DIEHash().computeTypeSignature(Foo);
}
@@ -421,21 +423,21 @@ TEST(DIEHashTest, PtrToMemberDeclDefMisMatch) {
Foo.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Eight);
Foo.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr);
- DIE *Mem = new DIE(dwarf::DW_TAG_member);
+ auto Mem = make_unique<DIE>(dwarf::DW_TAG_member);
Mem->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &MemStr);
Mem->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1,
&Zero);
DIE PtrToFooMem(dwarf::DW_TAG_ptr_to_member_type);
- DIEEntry BarEntry(&Bar);
+ DIEEntry BarEntry(Bar);
PtrToFooMem.addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &BarEntry);
PtrToFooMem.addValue(dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4,
&BarEntry);
- DIEEntry PtrToFooMemRef(&PtrToFooMem);
+ DIEEntry PtrToFooMemRef(PtrToFooMem);
Mem->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &PtrToFooMemRef);
- Foo.addChild(Mem);
+ Foo.addChild(std::move(Mem));
MD5ResDef = DIEHash().computeTypeSignature(Foo);
}
@@ -463,19 +465,19 @@ TEST(DIEHashTest, RefUnnamedType) {
Foo.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Eight);
Foo.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr);
- DIE *Mem = new DIE(dwarf::DW_TAG_member);
+ auto Mem = make_unique<DIE>(dwarf::DW_TAG_member);
Mem->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &MemStr);
Mem->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1, &Zero);
DIE UnnamedPtr(dwarf::DW_TAG_pointer_type);
UnnamedPtr.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Eight);
- DIEEntry UnnamedRef(&Unnamed);
+ DIEEntry UnnamedRef(Unnamed);
UnnamedPtr.addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &UnnamedRef);
- DIEEntry UnnamedPtrRef(&UnnamedPtr);
+ DIEEntry UnnamedPtrRef(UnnamedPtr);
Mem->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &UnnamedPtrRef);
- Foo.addChild(Mem);
+ Foo.addChild(std::move(Mem));
uint64_t MD5Res = DIEHash().computeTypeSignature(Foo);
@@ -488,12 +490,12 @@ TEST(DIEHashTest, NestedType) {
DIEInteger One(1);
Unnamed.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &One);
- DIE *Foo = new DIE(dwarf::DW_TAG_structure_type);
+ auto Foo = make_unique<DIE>(dwarf::DW_TAG_structure_type);
DIEString FooStr(&One, "foo");
Foo->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr);
Foo->addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &One);
- Unnamed.addChild(Foo);
+ Unnamed.addChild(std::move(Foo));
uint64_t MD5Res = DIEHash().computeTypeSignature(Unnamed);
@@ -507,11 +509,11 @@ TEST(DIEHashTest, MemberFunc) {
DIEInteger One(1);
Unnamed.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &One);
- DIE *Func = new DIE(dwarf::DW_TAG_subprogram);
+ auto Func = make_unique<DIE>(dwarf::DW_TAG_subprogram);
DIEString FuncStr(&One, "func");
Func->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FuncStr);
- Unnamed.addChild(Func);
+ Unnamed.addChild(std::move(Func));
uint64_t MD5Res = DIEHash().computeTypeSignature(Unnamed);
@@ -531,7 +533,7 @@ TEST(DIEHashTest, MemberFuncFlag) {
A.addValue(dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1, &One);
A.addValue(dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1, &One);
- DIE *Func = new DIE(dwarf::DW_TAG_subprogram);
+ auto Func = make_unique<DIE>(dwarf::DW_TAG_subprogram);
DIEString FuncStr(&One, "func");
DIEString FuncLinkage(&One, "_ZN1A4funcEv");
DIEInteger Two(2);
@@ -542,7 +544,7 @@ TEST(DIEHashTest, MemberFuncFlag) {
Func->addValue(dwarf::DW_AT_linkage_name, dwarf::DW_FORM_strp, &FuncLinkage);
Func->addValue(dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present, &One);
- A.addChild(Func);
+ A.addChild(std::move(Func));
uint64_t MD5Res = DIEHash().computeTypeSignature(A);
@@ -567,17 +569,17 @@ TEST(DIEHashTest, MemberSdata) {
DIEInteger Four(4);
DIEInteger Five(5);
DIEString FStr(&One, "int");
- DIE *IntTyDIE = new DIE(dwarf::DW_TAG_base_type);
- IntTyDIE->addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Four);
- IntTyDIE->addValue(dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, &Five);
- IntTyDIE->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FStr);
+ DIE IntTyDIE(dwarf::DW_TAG_base_type);
+ IntTyDIE.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Four);
+ IntTyDIE.addValue(dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, &Five);
+ IntTyDIE.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FStr);
DIEEntry IntTy(IntTyDIE);
- DIE *PITyDIE = new DIE(dwarf::DW_TAG_const_type);
+ auto PITyDIE = make_unique<DIE>(dwarf::DW_TAG_const_type);
PITyDIE->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &IntTy);
- DIEEntry PITy(PITyDIE);
- DIE *PI = new DIE(dwarf::DW_TAG_member);
+ DIEEntry PITy(*PITyDIE);
+ auto PI = make_unique<DIE>(dwarf::DW_TAG_member);
DIEString PIStr(&One, "PI");
DIEInteger Two(2);
DIEInteger NegThree(-3);
@@ -589,7 +591,7 @@ TEST(DIEHashTest, MemberSdata) {
PI->addValue(dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present, &One);
PI->addValue(dwarf::DW_AT_const_value, dwarf::DW_FORM_sdata, &NegThree);
- A.addChild(PI);
+ A.addChild(std::move(PI));
uint64_t MD5Res = DIEHash().computeTypeSignature(A);
ASSERT_EQ(0x9a216000dd3788a7ULL, MD5Res);
@@ -611,17 +613,17 @@ TEST(DIEHashTest, MemberBlock) {
DIEInteger Four(4);
DIEString FStr(&One, "float");
- DIE *FloatTyDIE = new DIE(dwarf::DW_TAG_base_type);
+ auto FloatTyDIE = make_unique<DIE>(dwarf::DW_TAG_base_type);
FloatTyDIE->addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Four);
FloatTyDIE->addValue(dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, &Four);
FloatTyDIE->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FStr);
- DIEEntry FloatTy(FloatTyDIE);
- DIE *PITyDIE = new DIE(dwarf::DW_TAG_const_type);
+ DIEEntry FloatTy(*FloatTyDIE);
+ auto PITyDIE = make_unique<DIE>(dwarf::DW_TAG_const_type);
PITyDIE->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &FloatTy);
- DIEEntry PITy(PITyDIE);
- DIE *PI = new DIE(dwarf::DW_TAG_member);
+ DIEEntry PITy(*PITyDIE);
+ auto PI = make_unique<DIE>(dwarf::DW_TAG_member);
DIEString PIStr(&One, "PI");
DIEInteger Two(2);
PI->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &PIStr);
@@ -631,20 +633,20 @@ TEST(DIEHashTest, MemberBlock) {
PI->addValue(dwarf::DW_AT_external, dwarf::DW_FORM_flag_present, &One);
PI->addValue(dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present, &One);
- DIEBlock *PIBlock = new DIEBlock();
+ DIEBlock PIBlock;
DIEInteger Blk1(0xc3);
DIEInteger Blk2(0xf5);
DIEInteger Blk3(0x48);
DIEInteger Blk4(0x40);
- PIBlock->addValue((dwarf::Attribute)0, dwarf::DW_FORM_data1, &Blk1);
- PIBlock->addValue((dwarf::Attribute)0, dwarf::DW_FORM_data1, &Blk2);
- PIBlock->addValue((dwarf::Attribute)0, dwarf::DW_FORM_data1, &Blk3);
- PIBlock->addValue((dwarf::Attribute)0, dwarf::DW_FORM_data1, &Blk4);
+ PIBlock.addValue((dwarf::Attribute)0, dwarf::DW_FORM_data1, &Blk1);
+ PIBlock.addValue((dwarf::Attribute)0, dwarf::DW_FORM_data1, &Blk2);
+ PIBlock.addValue((dwarf::Attribute)0, dwarf::DW_FORM_data1, &Blk3);
+ PIBlock.addValue((dwarf::Attribute)0, dwarf::DW_FORM_data1, &Blk4);
- PI->addValue(dwarf::DW_AT_const_value, dwarf::DW_FORM_block1, PIBlock);
+ PI->addValue(dwarf::DW_AT_const_value, dwarf::DW_FORM_block1, &PIBlock);
- A.addChild(PI);
+ A.addChild(std::move(PI));
uint64_t MD5Res = DIEHash().computeTypeSignature(A);
ASSERT_EQ(0x493af53ad3d3f651ULL, MD5Res);
diff --git a/unittests/ExecutionEngine/JIT/IntelJITEventListenerTest.cpp b/unittests/ExecutionEngine/JIT/IntelJITEventListenerTest.cpp
index d3f66a2..db90887 100644
--- a/unittests/ExecutionEngine/JIT/IntelJITEventListenerTest.cpp
+++ b/unittests/ExecutionEngine/JIT/IntelJITEventListenerTest.cpp
@@ -83,7 +83,7 @@ public:
EXPECT_TRUE(0 != MockWrapper);
Listener.reset(JITEventListener::createIntelJITEventListener(
- MockWrapper.take()));
+ MockWrapper.release()));
EXPECT_TRUE(0 != Listener);
EE->RegisterJITEventListener(Listener.get());
}
diff --git a/unittests/ExecutionEngine/JIT/JITTest.cpp b/unittests/ExecutionEngine/JIT/JITTest.cpp
index 9e65fee..f438286 100644
--- a/unittests/ExecutionEngine/JIT/JITTest.cpp
+++ b/unittests/ExecutionEngine/JIT/JITTest.cpp
@@ -114,8 +114,8 @@ public:
return Result;
}
int stubsAllocated;
- virtual uint8_t *allocateStub(const GlobalValue* F, unsigned StubSize,
- unsigned Alignment) {
+ uint8_t *allocateStub(const GlobalValue *F, unsigned StubSize,
+ unsigned Alignment) override {
stubsAllocated++;
return Base->allocateStub(F, StubSize, Alignment);
}
diff --git a/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp b/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp
index 3813d59..20d3f13 100644
--- a/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp
+++ b/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp
@@ -28,6 +28,7 @@ using namespace llvm;
static bool didCallAllocateCodeSection;
static bool didAllocateCompactUnwindSection;
+static bool didCallYield;
static uint8_t *roundTripAllocateCodeSection(void *object, uintptr_t size,
unsigned alignment,
@@ -64,6 +65,10 @@ static void roundTripDestroy(void *object) {
delete static_cast<SectionMemoryManager*>(object);
}
+static void yield(LLVMContextRef, void *) {
+ didCallYield = true;
+}
+
namespace {
// memory manager to test reserve allocation space callback
@@ -142,6 +147,7 @@ protected:
virtual void SetUp() {
didCallAllocateCodeSection = false;
didAllocateCompactUnwindSection = false;
+ didCallYield = false;
Module = 0;
Function = 0;
Engine = 0;
@@ -429,3 +435,24 @@ TEST_F(MCJITCAPITest, reserve_allocation_space) {
EXPECT_TRUE(MM->UsedCodeSize > 0);
EXPECT_TRUE(MM->UsedDataSizeRW > 0);
}
+
+TEST_F(MCJITCAPITest, yield) {
+ SKIP_UNSUPPORTED_PLATFORM;
+
+ buildSimpleFunction();
+ buildMCJITOptions();
+ buildMCJITEngine();
+ LLVMContextRef C = LLVMGetGlobalContext();
+ LLVMContextSetYieldCallback(C, yield, NULL);
+ buildAndRunPasses();
+
+ union {
+ void *raw;
+ int (*usable)();
+ } functionPointer;
+ functionPointer.raw = LLVMGetPointerToGlobal(Engine, Function);
+
+ EXPECT_EQ(42, functionPointer.usable());
+ EXPECT_TRUE(didCallYield);
+}
+
diff --git a/unittests/IR/CMakeLists.txt b/unittests/IR/CMakeLists.txt
index 7368a24..b439d59 100644
--- a/unittests/IR/CMakeLists.txt
+++ b/unittests/IR/CMakeLists.txt
@@ -21,6 +21,7 @@ set(IRSources
PatternMatch.cpp
TypeBuilderTest.cpp
TypesTest.cpp
+ UserTest.cpp
ValueHandleTest.cpp
ValueMapTest.cpp
ValueTest.cpp
diff --git a/unittests/IR/ConstantsTest.cpp b/unittests/IR/ConstantsTest.cpp
index b3aa810..c11729c 100644
--- a/unittests/IR/ConstantsTest.cpp
+++ b/unittests/IR/ConstantsTest.cpp
@@ -254,6 +254,34 @@ TEST(ConstantsTest, AsInstructionsTest) {
P6STR ", i32 1");
}
+#ifdef GTEST_HAS_DEATH_TEST
+#ifndef NDEBUG
+TEST(ConstantsTest, ReplaceWithConstantTest) {
+ std::unique_ptr<Module> M(new Module("MyModule", getGlobalContext()));
+
+ Type *Int32Ty = Type::getInt32Ty(getGlobalContext());
+ Constant *One = ConstantInt::get(Int32Ty, 1);
+
+ Constant *Global =
+ M->getOrInsertGlobal("dummy", PointerType::getUnqual(Int32Ty));
+ Constant *GEP = ConstantExpr::getGetElementPtr(Global, One);
+ EXPECT_DEATH(Global->replaceAllUsesWith(GEP),
+ "this->replaceAllUsesWith\\(expr\\(this\\)\\) is NOT valid!");
+}
+
+TEST(ConstantsTest, ReplaceInAliasTest) {
+ std::unique_ptr<Module> M(new Module("MyModule", getGlobalContext()));
+
+ Type *Int32Ty = Type::getInt32Ty(getGlobalContext());
+ auto *Global = cast<GlobalObject>(M->getOrInsertGlobal("dummy", Int32Ty));
+ auto *GA = GlobalAlias::create(GlobalValue::ExternalLinkage, "alias", Global);
+ EXPECT_DEATH(Global->replaceAllUsesWith(GA),
+ "replaceAliasUseWith cannot form an alias cycle");
+}
+
+#endif
+#endif
+
#undef CHECK
} // end anonymous namespace
diff --git a/unittests/IR/InstructionsTest.cpp b/unittests/IR/InstructionsTest.cpp
index e76afa8..336f5a2 100644
--- a/unittests/IR/InstructionsTest.cpp
+++ b/unittests/IR/InstructionsTest.cpp
@@ -483,6 +483,39 @@ TEST(InstructionsTest, isEliminableCastPair) {
}
+TEST(InstructionsTest, CloneCall) {
+ LLVMContext &C(getGlobalContext());
+ Type *Int32Ty = Type::getInt32Ty(C);
+ Type *ArgTys[] = {Int32Ty, Int32Ty, Int32Ty};
+ Type *FnTy = FunctionType::get(Int32Ty, ArgTys, /*isVarArg=*/false);
+ Value *Callee = Constant::getNullValue(FnTy->getPointerTo());
+ Value *Args[] = {
+ ConstantInt::get(Int32Ty, 1),
+ ConstantInt::get(Int32Ty, 2),
+ ConstantInt::get(Int32Ty, 3)
+ };
+ std::unique_ptr<CallInst> Call(CallInst::Create(Callee, Args, "result"));
+
+ // Test cloning the tail call kind.
+ CallInst::TailCallKind Kinds[] = {CallInst::TCK_None, CallInst::TCK_Tail,
+ CallInst::TCK_MustTail};
+ for (CallInst::TailCallKind TCK : Kinds) {
+ Call->setTailCallKind(TCK);
+ std::unique_ptr<CallInst> Clone(cast<CallInst>(Call->clone()));
+ EXPECT_EQ(Call->getTailCallKind(), Clone->getTailCallKind());
+ }
+ Call->setTailCallKind(CallInst::TCK_None);
+
+ // Test cloning an attribute.
+ {
+ AttrBuilder AB;
+ AB.addAttribute(Attribute::ReadOnly);
+ Call->setAttributes(AttributeSet::get(C, AttributeSet::FunctionIndex, AB));
+ std::unique_ptr<CallInst> Clone(cast<CallInst>(Call->clone()));
+ EXPECT_TRUE(Clone->onlyReadsMemory());
+ }
+}
+
} // end anonymous namespace
} // end namespace llvm
diff --git a/unittests/IR/MDBuilderTest.cpp b/unittests/IR/MDBuilderTest.cpp
index 665d559..c8b5a09 100644
--- a/unittests/IR/MDBuilderTest.cpp
+++ b/unittests/IR/MDBuilderTest.cpp
@@ -9,6 +9,7 @@
#include "llvm/IR/MDBuilder.h"
#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/Metadata.h"
#include "llvm/IR/Operator.h"
#include "gtest/gtest.h"
diff --git a/unittests/IR/UserTest.cpp b/unittests/IR/UserTest.cpp
new file mode 100644
index 0000000..9c0e7b2
--- /dev/null
+++ b/unittests/IR/UserTest.cpp
@@ -0,0 +1,96 @@
+//===- llvm/unittest/IR/UserTest.cpp - User unit tests --------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/AsmParser/Parser.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/User.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/Support/SourceMgr.h"
+#include "gtest/gtest.h"
+using namespace llvm;
+
+namespace {
+
+TEST(UserTest, ValueOpIteration) {
+ LLVMContext C;
+
+ const char *ModuleString = "define void @f(i32 %x, i32 %y) {\n"
+ "entry:\n"
+ " switch i32 undef, label %s0\n"
+ " [ i32 1, label %s1\n"
+ " i32 2, label %s2\n"
+ " i32 3, label %s3\n"
+ " i32 4, label %s4\n"
+ " i32 5, label %s5\n"
+ " i32 6, label %s6\n"
+ " i32 7, label %s7\n"
+ " i32 8, label %s8\n"
+ " i32 9, label %s9 ]\n"
+ "\n"
+ "s0:\n"
+ " br label %exit\n"
+ "s1:\n"
+ " br label %exit\n"
+ "s2:\n"
+ " br label %exit\n"
+ "s3:\n"
+ " br label %exit\n"
+ "s4:\n"
+ " br label %exit\n"
+ "s5:\n"
+ " br label %exit\n"
+ "s6:\n"
+ " br label %exit\n"
+ "s7:\n"
+ " br label %exit\n"
+ "s8:\n"
+ " br label %exit\n"
+ "s9:\n"
+ " br label %exit\n"
+ "\n"
+ "exit:\n"
+ " %phi = phi i32 [ 0, %s0 ], [ 1, %s1 ],\n"
+ " [ 2, %s2 ], [ 3, %s3 ],\n"
+ " [ 4, %s4 ], [ 5, %s5 ],\n"
+ " [ 6, %s6 ], [ 7, %s7 ],\n"
+ " [ 8, %s8 ], [ 9, %s9 ]\n"
+ " ret void\n"
+ "}\n";
+ SMDiagnostic Err;
+ Module *M = ParseAssemblyString(ModuleString, NULL, Err, C);
+
+ Function *F = M->getFunction("f");
+ BasicBlock &ExitBB = F->back();
+ PHINode &P = cast<PHINode>(ExitBB.front());
+ EXPECT_TRUE(P.value_op_begin() == P.value_op_begin());
+ EXPECT_FALSE(P.value_op_begin() == P.value_op_end());
+ EXPECT_TRUE(P.value_op_begin() != P.value_op_end());
+ EXPECT_FALSE(P.value_op_end() != P.value_op_end());
+ EXPECT_TRUE(P.value_op_begin() < P.value_op_end());
+ EXPECT_FALSE(P.value_op_begin() < P.value_op_begin());
+ EXPECT_TRUE(P.value_op_end() > P.value_op_begin());
+ EXPECT_FALSE(P.value_op_begin() > P.value_op_begin());
+ EXPECT_TRUE(P.value_op_begin() <= P.value_op_begin());
+ EXPECT_FALSE(P.value_op_end() <= P.value_op_begin());
+ EXPECT_TRUE(P.value_op_begin() >= P.value_op_begin());
+ EXPECT_FALSE(P.value_op_begin() >= P.value_op_end());
+ EXPECT_EQ(10, std::distance(P.value_op_begin(), P.value_op_end()));
+
+ User::value_op_iterator I = P.value_op_begin();
+ I += 3;
+ EXPECT_EQ(std::next(P.value_op_begin(), 3), I);
+ EXPECT_EQ(P.getOperand(3), *I);
+ I++;
+ EXPECT_EQ(P.getOperand(6), I[2]);
+ EXPECT_EQ(P.value_op_end(), (I - 2) + 8);
+}
+
+} // end anonymous namespace
diff --git a/unittests/IR/VerifierTest.cpp b/unittests/IR/VerifierTest.cpp
index 0a660a6..252bdd3 100644
--- a/unittests/IR/VerifierTest.cpp
+++ b/unittests/IR/VerifierTest.cpp
@@ -52,9 +52,7 @@ TEST(VerifierTest, AliasUnnamedAddr) {
GlobalVariable *Aliasee = new GlobalVariable(M, Ty, true,
GlobalValue::ExternalLinkage,
Init, "foo");
- GlobalAlias *GA = new GlobalAlias(Type::getInt8PtrTy(C),
- GlobalValue::ExternalLinkage,
- "bar", Aliasee, &M);
+ auto *GA = GlobalAlias::create(GlobalValue::ExternalLinkage, "bar", Aliasee);
GA->setUnnamedAddr(true);
std::string Error;
raw_string_ostream ErrorOS(Error);
diff --git a/unittests/LineEditor/LineEditor.cpp b/unittests/LineEditor/LineEditor.cpp
index cb115bd..26053c0 100644
--- a/unittests/LineEditor/LineEditor.cpp
+++ b/unittests/LineEditor/LineEditor.cpp
@@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/LineEditor/LineEditor.h"
+#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "gtest/gtest.h"
diff --git a/unittests/Linker/LinkModulesTest.cpp b/unittests/Linker/LinkModulesTest.cpp
index 7b40b9f..1d5db36 100644
--- a/unittests/Linker/LinkModulesTest.cpp
+++ b/unittests/Linker/LinkModulesTest.cpp
@@ -22,11 +22,9 @@ namespace {
class LinkModuleTest : public testing::Test {
protected:
virtual void SetUp() {
- LLVMContext &Ctx = getGlobalContext();
M.reset(new Module("MyModule", Ctx));
- FunctionType *FTy = FunctionType::get(Type::getInt8PtrTy(Ctx),
- Type::getInt32Ty(Ctx),
- false /*=isVarArg*/);
+ FunctionType *FTy = FunctionType::get(
+ Type::getInt8PtrTy(Ctx), Type::getInt32Ty(Ctx), false /*=isVarArg*/);
F = Function::Create(FTy, Function::ExternalLinkage, "ba_func", M.get());
F->setCallingConv(CallingConv::C);
@@ -38,12 +36,10 @@ protected:
ArrayType *AT = ArrayType::get(Type::getInt8PtrTy(Ctx), 3);
GV = new GlobalVariable(*M.get(), AT, false /*=isConstant*/,
- GlobalValue::InternalLinkage,
- 0, "switch.bas");
-
+ GlobalValue::InternalLinkage, 0, "switch.bas");
// Global Initializer
- std::vector<Constant*> Init;
+ std::vector<Constant *> Init;
Constant *SwitchCase1BA = BlockAddress::get(SwitchCase1BB);
Init.push_back(SwitchCase1BA);
@@ -51,17 +47,16 @@ protected:
Init.push_back(SwitchCase2BA);
ConstantInt *One = ConstantInt::get(Type::getInt32Ty(Ctx), 1);
- Constant *OnePtr = ConstantExpr::getCast(Instruction::IntToPtr,
- One, Type::getInt8PtrTy(Ctx));
+ Constant *OnePtr = ConstantExpr::getCast(Instruction::IntToPtr, One,
+ Type::getInt8PtrTy(Ctx));
Init.push_back(OnePtr);
GV->setInitializer(ConstantArray::get(AT, Init));
}
- virtual void TearDown() {
- M.reset();
- }
+ virtual void TearDown() { M.reset(); }
+ LLVMContext Ctx;
std::unique_ptr<Module> M;
Function *F;
GlobalVariable *GV;
@@ -72,10 +67,9 @@ protected:
};
TEST_F(LinkModuleTest, BlockAddress) {
- LLVMContext &Ctx = getGlobalContext();
IRBuilder<> Builder(EntryBB);
- std::vector<Value*> GEPIndices;
+ std::vector<Value *> GEPIndices;
GEPIndices.push_back(ConstantInt::get(Type::getInt32Ty(Ctx), 0));
GEPIndices.push_back(F->arg_begin());
@@ -93,7 +87,7 @@ TEST_F(LinkModuleTest, BlockAddress) {
Builder.SetInsertPoint(ExitBB);
Builder.CreateRet(ConstantPointerNull::get(Type::getInt8PtrTy(Ctx)));
- Module *LinkedModule = new Module("MyModuleLinked", getGlobalContext());
+ Module *LinkedModule = new Module("MyModuleLinked", Ctx);
Linker::LinkModules(LinkedModule, M.get(), Linker::PreserveSource, 0);
// Delete the original module.
@@ -117,7 +111,7 @@ TEST_F(LinkModuleTest, BlockAddress) {
LinkedModule->getFunction("ba_func"));
EXPECT_EQ(cast<BlockAddress>(Elem)->getBasicBlock()->getParent(),
LinkedModule->getFunction("ba_func"));
-
+
Elem = Init->getOperand(1);
ASSERT_TRUE(isa<BlockAddress>(Elem));
EXPECT_EQ(cast<BlockAddress>(Elem)->getFunction(),
@@ -129,11 +123,9 @@ TEST_F(LinkModuleTest, BlockAddress) {
}
TEST_F(LinkModuleTest, EmptyModule) {
- LLVMContext &Ctx = getGlobalContext();
Module *InternalM = new Module("InternalModule", Ctx);
- FunctionType *FTy = FunctionType::get(Type::getVoidTy(Ctx),
- Type::getInt8PtrTy(Ctx),
- false /*=isVarArgs*/);
+ FunctionType *FTy = FunctionType::get(
+ Type::getVoidTy(Ctx), Type::getInt8PtrTy(Ctx), false /*=isVarArgs*/);
F = Function::Create(FTy, Function::InternalLinkage, "bar", InternalM);
F->setCallingConv(CallingConv::C);
@@ -145,12 +137,11 @@ TEST_F(LinkModuleTest, EmptyModule) {
StructType *STy = StructType::create(Ctx, PointerType::get(FTy, 0));
GlobalVariable *GV =
- new GlobalVariable(*InternalM, STy, false /*=isConstant*/,
- GlobalValue::InternalLinkage, 0, "g");
+ new GlobalVariable(*InternalM, STy, false /*=isConstant*/,
+ GlobalValue::InternalLinkage, 0, "g");
GV->setInitializer(ConstantStruct::get(STy, F));
-
Module *EmptyM = new Module("EmptyModule1", Ctx);
Linker::LinkModules(EmptyM, InternalM, Linker::PreserveSource, 0);
diff --git a/unittests/Object/CMakeLists.txt b/unittests/Object/CMakeLists.txt
index 6dd66ce..580a894 100644
--- a/unittests/Object/CMakeLists.txt
+++ b/unittests/Object/CMakeLists.txt
@@ -4,5 +4,6 @@ set(LLVM_LINK_COMPONENTS
)
add_llvm_unittest(ObjectTests
+ StringTableBuilderTest.cpp
YAMLTest.cpp
)
diff --git a/unittests/Object/StringTableBuilderTest.cpp b/unittests/Object/StringTableBuilderTest.cpp
new file mode 100644
index 0000000..130eb4a
--- /dev/null
+++ b/unittests/Object/StringTableBuilderTest.cpp
@@ -0,0 +1,40 @@
+//===----------- StringTableBuilderTest.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/Object/StringTableBuilder.h"
+#include <string>
+
+using namespace llvm;
+
+namespace {
+
+TEST(StringTableBuilderTest, Basic) {
+ StringTableBuilder B;
+
+ B.add("foo");
+ B.add("bar");
+ B.add("foobar");
+
+ B.finalize();
+
+ std::string Expected;
+ Expected += '\x00';
+ Expected += "foobar";
+ Expected += '\x00';
+ Expected += "foo";
+ Expected += '\x00';
+
+ EXPECT_EQ(Expected, B.data());
+ EXPECT_EQ(1U, B.getOffset("foobar"));
+ EXPECT_EQ(4U, B.getOffset("bar"));
+ EXPECT_EQ(8U, B.getOffset("foo"));
+}
+
+}
diff --git a/unittests/Option/OptionParsingTest.cpp b/unittests/Option/OptionParsingTest.cpp
index 6beb286..aa32da3 100644
--- a/unittests/Option/OptionParsingTest.cpp
+++ b/unittests/Option/OptionParsingTest.cpp
@@ -68,7 +68,7 @@ TEST(Option, OptionParsing) {
TestOptTable T;
unsigned MAI, MAC;
std::unique_ptr<InputArgList> AL(
- T.ParseArgs(Args, array_endof(Args), MAI, MAC));
+ T.ParseArgs(std::begin(Args), std::end(Args), MAI, MAC));
// Check they all exist.
EXPECT_TRUE(AL->hasArg(OPT_A));
@@ -114,7 +114,7 @@ TEST(Option, ParseWithFlagExclusions) {
std::unique_ptr<InputArgList> AL;
// Exclude flag3 to avoid parsing as OPT_SLASH_C.
- AL.reset(T.ParseArgs(Args, array_endof(Args), MAI, MAC,
+ AL.reset(T.ParseArgs(std::begin(Args), std::end(Args), MAI, MAC,
/*FlagsToInclude=*/0,
/*FlagsToExclude=*/OptFlag3));
EXPECT_TRUE(AL->hasArg(OPT_A));
@@ -122,7 +122,7 @@ TEST(Option, ParseWithFlagExclusions) {
EXPECT_FALSE(AL->hasArg(OPT_SLASH_C));
// Exclude flag1 to avoid parsing as OPT_C.
- AL.reset(T.ParseArgs(Args, array_endof(Args), MAI, MAC,
+ AL.reset(T.ParseArgs(std::begin(Args), std::end(Args), MAI, MAC,
/*FlagsToInclude=*/0,
/*FlagsToExclude=*/OptFlag1));
EXPECT_TRUE(AL->hasArg(OPT_B));
@@ -130,7 +130,7 @@ TEST(Option, ParseWithFlagExclusions) {
EXPECT_TRUE(AL->hasArg(OPT_SLASH_C));
const char *NewArgs[] = { "/C", "foo", "--C=bar" };
- AL.reset(T.ParseArgs(NewArgs, array_endof(NewArgs), MAI, MAC));
+ AL.reset(T.ParseArgs(std::begin(NewArgs), std::end(NewArgs), MAI, MAC));
EXPECT_TRUE(AL->hasArg(OPT_SLASH_C));
EXPECT_TRUE(AL->hasArg(OPT_C));
EXPECT_EQ(AL->getLastArgValue(OPT_SLASH_C), "foo");
@@ -143,7 +143,7 @@ TEST(Option, ParseAliasInGroup) {
const char *MyArgs[] = { "-I" };
std::unique_ptr<InputArgList> AL(
- T.ParseArgs(MyArgs, array_endof(MyArgs), MAI, MAC));
+ T.ParseArgs(std::begin(MyArgs), std::end(MyArgs), MAI, MAC));
EXPECT_TRUE(AL->hasArg(OPT_H));
}
@@ -153,7 +153,7 @@ TEST(Option, AliasArgs) {
const char *MyArgs[] = { "-J", "-Joo" };
std::unique_ptr<InputArgList> AL(
- T.ParseArgs(MyArgs, array_endof(MyArgs), MAI, MAC));
+ T.ParseArgs(std::begin(MyArgs), std::end(MyArgs), MAI, MAC));
EXPECT_TRUE(AL->hasArg(OPT_B));
EXPECT_EQ(AL->getAllArgValues(OPT_B)[0], "foo");
EXPECT_EQ(AL->getAllArgValues(OPT_B)[1], "bar");
@@ -165,7 +165,7 @@ TEST(Option, IgnoreCase) {
const char *MyArgs[] = { "-a", "-joo" };
std::unique_ptr<InputArgList> AL(
- T.ParseArgs(MyArgs, array_endof(MyArgs), MAI, MAC));
+ T.ParseArgs(std::begin(MyArgs), std::end(MyArgs), MAI, MAC));
EXPECT_TRUE(AL->hasArg(OPT_A));
EXPECT_TRUE(AL->hasArg(OPT_B));
}
@@ -176,7 +176,7 @@ TEST(Option, DoNotIgnoreCase) {
const char *MyArgs[] = { "-a", "-joo" };
std::unique_ptr<InputArgList> AL(
- T.ParseArgs(MyArgs, array_endof(MyArgs), MAI, MAC));
+ T.ParseArgs(std::begin(MyArgs), std::end(MyArgs), MAI, MAC));
EXPECT_FALSE(AL->hasArg(OPT_A));
EXPECT_FALSE(AL->hasArg(OPT_B));
}
@@ -187,7 +187,7 @@ TEST(Option, SlurpEmpty) {
const char *MyArgs[] = { "-A", "-slurp" };
std::unique_ptr<InputArgList> AL(
- T.ParseArgs(MyArgs, array_endof(MyArgs), MAI, MAC));
+ T.ParseArgs(std::begin(MyArgs), std::end(MyArgs), MAI, MAC));
EXPECT_TRUE(AL->hasArg(OPT_A));
EXPECT_TRUE(AL->hasArg(OPT_Slurp));
EXPECT_EQ(AL->getAllArgValues(OPT_Slurp).size(), 0U);
@@ -199,7 +199,7 @@ TEST(Option, Slurp) {
const char *MyArgs[] = { "-A", "-slurp", "-B", "--", "foo" };
std::unique_ptr<InputArgList> AL(
- T.ParseArgs(MyArgs, array_endof(MyArgs), MAI, MAC));
+ T.ParseArgs(std::begin(MyArgs), std::end(MyArgs), MAI, MAC));
EXPECT_EQ(AL->size(), 2U);
EXPECT_TRUE(AL->hasArg(OPT_A));
EXPECT_FALSE(AL->hasArg(OPT_B));
diff --git a/unittests/Support/AllocatorTest.cpp b/unittests/Support/AllocatorTest.cpp
index bcf6bf1..0fc84c7 100644
--- a/unittests/Support/AllocatorTest.cpp
+++ b/unittests/Support/AllocatorTest.cpp
@@ -29,6 +29,21 @@ TEST(AllocatorTest, Basics) {
EXPECT_EQ(2, b[9]);
EXPECT_EQ(3, *c);
EXPECT_EQ(1U, Alloc.GetNumSlabs());
+
+ BumpPtrAllocator Alloc2 = std::move(Alloc);
+ EXPECT_EQ(0U, Alloc.GetNumSlabs());
+ EXPECT_EQ(1U, Alloc2.GetNumSlabs());
+
+ // Make sure the old pointers still work. These are especially interesting
+ // under ASan or Valgrind.
+ EXPECT_EQ(1, *a);
+ EXPECT_EQ(2, b[0]);
+ EXPECT_EQ(2, b[9]);
+ EXPECT_EQ(3, *c);
+
+ Alloc = std::move(Alloc2);
+ EXPECT_EQ(0U, Alloc2.GetNumSlabs());
+ EXPECT_EQ(1U, Alloc.GetNumSlabs());
}
// Allocate enough bytes to create three slabs.
@@ -84,7 +99,7 @@ TEST(AllocatorTest, TestOverflow) {
BumpPtrAllocator Alloc;
// Fill the slab right up until the end pointer.
- Alloc.Allocate(4096 - sizeof(MemSlab), 0);
+ Alloc.Allocate(4096, 0);
EXPECT_EQ(1U, Alloc.GetNumSlabs());
// If we don't allocate a new slab, then we will have overflowed.
@@ -102,49 +117,52 @@ TEST(AllocatorTest, TestSmallSlabSize) {
// Mock slab allocator that returns slabs aligned on 4096 bytes. There is no
// easy portable way to do this, so this is kind of a hack.
-class MockSlabAllocator : public SlabAllocator {
- MemSlab *LastSlab;
+class MockSlabAllocator {
+ static size_t LastSlabSize;
public:
- virtual ~MockSlabAllocator() { }
+ ~MockSlabAllocator() { }
- virtual MemSlab *Allocate(size_t Size) {
+ void *Allocate(size_t Size, size_t /*Alignment*/) {
// Allocate space for the alignment, the slab, and a void* that goes right
// before the slab.
size_t Alignment = 4096;
void *MemBase = malloc(Size + Alignment - 1 + sizeof(void*));
- // Make the slab.
- MemSlab *Slab = (MemSlab*)(((uintptr_t)MemBase+sizeof(void*)+Alignment-1) &
- ~(uintptr_t)(Alignment - 1));
- Slab->Size = Size;
- Slab->NextPtr = 0;
+ // Find the slab start.
+ void *Slab = alignPtr((char *)MemBase + sizeof(void *), Alignment);
// Hold a pointer to the base so we can free the whole malloced block.
((void**)Slab)[-1] = MemBase;
- LastSlab = Slab;
+ LastSlabSize = Size;
return Slab;
}
- virtual void Deallocate(MemSlab *Slab) {
+ void Deallocate(void *Slab, size_t Size) {
free(((void**)Slab)[-1]);
}
- MemSlab *GetLastSlab() {
- return LastSlab;
- }
+ static size_t GetLastSlabSize() { return LastSlabSize; }
};
+size_t MockSlabAllocator::LastSlabSize = 0;
+
// Allocate a large-ish block with a really large alignment so that the
// allocator will think that it has space, but after it does the alignment it
// will not.
TEST(AllocatorTest, TestBigAlignment) {
- MockSlabAllocator SlabAlloc;
- BumpPtrAllocator Alloc(SlabAlloc);
- uintptr_t Ptr = (uintptr_t)Alloc.Allocate(3000, 2048);
- MemSlab *Slab = SlabAlloc.GetLastSlab();
- EXPECT_LE(Ptr + 3000, ((uintptr_t)Slab) + Slab->Size);
+ BumpPtrAllocatorImpl<MockSlabAllocator> Alloc;
+
+ // First allocate a tiny bit to ensure we have to re-align things.
+ (void)Alloc.Allocate(1, 0);
+
+ // Now the big chunk with a big alignment.
+ (void)Alloc.Allocate(3000, 2048);
+
+ // We test that the last slab size is not the default 4096 byte slab, but
+ // rather a custom sized slab that is larger.
+ EXPECT_GT(MockSlabAllocator::GetLastSlabSize(), 4096u);
}
} // anonymous namespace
diff --git a/unittests/Support/BlockFrequencyTest.cpp b/unittests/Support/BlockFrequencyTest.cpp
index c318451..f6e3537 100644
--- a/unittests/Support/BlockFrequencyTest.cpp
+++ b/unittests/Support/BlockFrequencyTest.cpp
@@ -15,9 +15,8 @@ TEST(BlockFrequencyTest, OneToZero) {
EXPECT_EQ(Freq.getFrequency(), 0u);
Freq = BlockFrequency(1);
- uint32_t Remainder = Freq.scale(Prob);
+ Freq *= Prob;
EXPECT_EQ(Freq.getFrequency(), 0u);
- EXPECT_EQ(Remainder, UINT32_MAX - 1);
}
TEST(BlockFrequencyTest, OneToOne) {
@@ -27,9 +26,8 @@ TEST(BlockFrequencyTest, OneToOne) {
EXPECT_EQ(Freq.getFrequency(), 1u);
Freq = BlockFrequency(1);
- uint32_t Remainder = Freq.scale(Prob);
+ Freq *= Prob;
EXPECT_EQ(Freq.getFrequency(), 1u);
- EXPECT_EQ(Remainder, 0u);
}
TEST(BlockFrequencyTest, ThreeToOne) {
@@ -39,9 +37,8 @@ TEST(BlockFrequencyTest, ThreeToOne) {
EXPECT_EQ(Freq.getFrequency(), 1u);
Freq = BlockFrequency(3);
- uint32_t Remainder = Freq.scale(Prob);
+ Freq *= Prob;
EXPECT_EQ(Freq.getFrequency(), 1u);
- EXPECT_EQ(Remainder, 0u);
}
TEST(BlockFrequencyTest, MaxToHalfMax) {
@@ -51,9 +48,8 @@ TEST(BlockFrequencyTest, MaxToHalfMax) {
EXPECT_EQ(Freq.getFrequency(), 9223372034707292159ULL);
Freq = BlockFrequency(UINT64_MAX);
- uint32_t Remainder = Freq.scale(Prob);
+ Freq *= Prob;
EXPECT_EQ(Freq.getFrequency(), 9223372034707292159ULL);
- EXPECT_EQ(Remainder, 0u);
}
TEST(BlockFrequencyTest, BigToBig) {
@@ -65,9 +61,8 @@ TEST(BlockFrequencyTest, BigToBig) {
EXPECT_EQ(Freq.getFrequency(), Big);
Freq = BlockFrequency(Big);
- uint32_t Remainder = Freq.scale(Prob);
+ Freq *= Prob;
EXPECT_EQ(Freq.getFrequency(), Big);
- EXPECT_EQ(Remainder, 0u);
}
TEST(BlockFrequencyTest, MaxToMax) {
@@ -80,109 +75,8 @@ TEST(BlockFrequencyTest, MaxToMax) {
// value, we do not signal saturation if the result equals said value, but
// saturating does not occur.
Freq = BlockFrequency(UINT64_MAX);
- uint32_t Remainder = Freq.scale(Prob);
+ Freq *= Prob;
EXPECT_EQ(Freq.getFrequency(), UINT64_MAX);
- EXPECT_EQ(Remainder, 0u);
-}
-
-TEST(BlockFrequencyTest, ScaleResultRemainderTest) {
- struct {
- uint64_t Freq;
- uint32_t Prob[2];
- uint64_t ExpectedFreq;
- uint32_t ExpectedRemainder;
- } Tests[80] = {
- // Data for scaling that results in <= 64 bit division.
- { 0x1423e2a50ULL, { 0x64819521, 0x7765dd13 }, 0x10f418889ULL, 0x92b9d25 },
- { 0x35ef14ceULL, { 0x28ade3c7, 0x304532ae }, 0x2d73c33aULL, 0x2c0fd0b6 },
- { 0xd03dbfbe24ULL, { 0x790079, 0xe419f3 }, 0x6e776fc1fdULL, 0x4a06dd },
- { 0x21d67410bULL, { 0x302a9dc2, 0x3ddb4442 }, 0x1a5948fd6ULL, 0x265d1c2a },
- { 0x8664aeadULL, { 0x3d523513, 0x403523b1 }, 0x805a04cfULL, 0x324c27b8 },
- { 0x201db0cf4ULL, { 0x35112a7b, 0x79fc0c74 }, 0xdf8b07f6ULL, 0x490c1dc4 },
- { 0x13f1e4430aULL, { 0x21c92bf, 0x21e63aae }, 0x13e0cba15ULL, 0x1df47c30 },
- { 0x16c83229ULL, { 0x3793f66f, 0x53180dea }, 0xf3ce7b6ULL, 0x1d0c1b6b },
- { 0xc62415be8ULL, { 0x9cc4a63, 0x4327ae9b }, 0x1ce8b71caULL, 0x3f2c696a },
- { 0x6fac5e434ULL, { 0xe5f9170, 0x1115e10b }, 0x5df23dd4cULL, 0x4dafc7c },
- { 0x1929375f2ULL, { 0x3a851375, 0x76c08456 }, 0xc662b082ULL, 0x343589ee },
- { 0x243c89db6ULL, { 0x354ebfc0, 0x450ef197 }, 0x1bf8c1661ULL, 0x4948e49 },
- { 0x310e9b31aULL, { 0x1b1b8acf, 0x2d3629f0 }, 0x1d69c93f9ULL, 0x73e3b96 },
- { 0xa1fae921dULL, { 0xa7a098c, 0x10469f44 }, 0x684413d6cULL, 0x86a882c },
- { 0xc1582d957ULL, { 0x498e061, 0x59856bc }, 0x9edc5f4e7ULL, 0x29b0653 },
- { 0x57cfee75ULL, { 0x1d061dc3, 0x7c8bfc17 }, 0x1476a220ULL, 0x2383d33f },
- { 0x139220080ULL, { 0x294a6c71, 0x2a2b07c9 }, 0x1329e1c76ULL, 0x7aa5da },
- { 0x1665d353cULL, { 0x7080db5, 0xde0d75c }, 0xb590d9fbULL, 0x7ba8c38 },
- { 0xe8f14541ULL, { 0x5188e8b2, 0x736527ef }, 0xa4971be5ULL, 0x6b612167 },
- { 0x2f4775f29ULL, { 0x254ef0fe, 0x435fcf50 }, 0x1a2e449c1ULL, 0x28bbf5e },
- { 0x27b85d8d7ULL, { 0x304c8220, 0x5de678f2 }, 0x146e3bef9ULL, 0x4b27097e },
- { 0x1d362e36bULL, { 0x36c85b12, 0x37a66f55 }, 0x1cc19b8e6ULL, 0x688e828 },
- { 0x155fd48c7ULL, { 0xf5894d, 0x1256108 }, 0x11e383602ULL, 0x111f0cb },
- { 0xb5db2d15ULL, { 0x39bb26c5, 0x5bdcda3e }, 0x72499259ULL, 0x59c4939b },
- { 0x153990298ULL, { 0x48921c09, 0x706eb817 }, 0xdb3268e8ULL, 0x66bb8a80 },
- { 0x28a7c3ed7ULL, { 0x1f776fd7, 0x349f7a70 }, 0x184f73ae1ULL, 0x28910321 },
- { 0x724dbeabULL, { 0x1bd149f5, 0x253a085e }, 0x5569c0b3ULL, 0xff8e2ed },
- { 0xd8f0c513ULL, { 0x18c8cc4c, 0x1b72bad0 }, 0xc3e30643ULL, 0xd85e134 },
- { 0x17ce3dcbULL, { 0x1e4c6260, 0x233b359e }, 0x1478f4afULL, 0x49ea31e },
- { 0x1ce036ce0ULL, { 0x29e3c8af, 0x5318dd4a }, 0xe8e76196ULL, 0x11d5b9c4 },
- { 0x1473ae2aULL, { 0x29b897ba, 0x2be29378 }, 0x13718185ULL, 0x6f93b2c },
- { 0x1dd41aa68ULL, { 0x3d0a4441, 0x5a0e8f12 }, 0x1437b6bbfULL, 0x54b09ffa },
- { 0x1b49e4a53ULL, { 0x3430c1fe, 0x5a204aed }, 0xfcd6852fULL, 0x15ad6ed7 },
- { 0x217941b19ULL, { 0x12ced2bd, 0x21b68310 }, 0x12aca65b1ULL, 0x1b2a9565 },
- { 0xac6a4dc8ULL, { 0x3ed68da8, 0x6fdca34c }, 0x60da926dULL, 0x22ff53e4 },
- { 0x1c503a4e7ULL, { 0xfcbbd32, 0x11e48d17 }, 0x18fec7d38ULL, 0xa8aa816 },
- { 0x1c885855ULL, { 0x213e919d, 0x25941897 }, 0x193de743ULL, 0x4ea09c },
- { 0x29b9c168eULL, { 0x2b644aea, 0x45725ee7 }, 0x1a122e5d5ULL, 0xbee1099 },
- { 0x806a33f2ULL, { 0x30a80a23, 0x5063733a }, 0x4db9a264ULL, 0x1eaed76e },
- { 0x282afc96bULL, { 0x143ae554, 0x1a9863ff }, 0x1e8de5204ULL, 0x158d9020 },
- // Data for scaling that results in > 64 bit division.
- { 0x23ca5f2f672ca41cULL, { 0xecbc641, 0x111373f7 }, 0x1f0301e5e8295ab5ULL, 0xf627f79 },
- { 0x5e4f2468142265e3ULL, { 0x1ddf5837, 0x32189233 }, 0x383ca7ba9fdd2c8cULL, 0x1c8f33e1 },
- { 0x277a1a6f6b266bf6ULL, { 0x415d81a8, 0x61eb5e1e }, 0x1a5a3e1d41b30c0fULL, 0x29cde3ae },
- { 0x1bdbb49a237035cbULL, { 0xea5bf17, 0x1d25ffb3 }, 0xdffc51c53d44b93ULL, 0x5170574 },
- { 0x2bce6d29b64fb8ULL, { 0x3bfd5631, 0x7525c9bb }, 0x166ebedda7ac57ULL, 0x3026dfab },
- { 0x3a02116103df5013ULL, { 0x2ee18a83, 0x3299aea8 }, 0x35be8922ab1e2a84ULL, 0x298d9919 },
- { 0x7b5762390799b18cULL, { 0x12f8e5b9, 0x2563bcd4 }, 0x3e960077aca01209ULL, 0x93afeb8 },
- { 0x69cfd72537021579ULL, { 0x4c35f468, 0x6a40feee }, 0x4be4cb3848be98a3ULL, 0x4ff96b9e },
- { 0x49dfdf835120f1c1ULL, { 0x8cb3759, 0x559eb891 }, 0x79663f7120edadeULL, 0x51b1fb5b },
- { 0x74b5be5c27676381ULL, { 0x47e4c5e0, 0x7c7b19ff }, 0x4367d2dff36a1028ULL, 0x7a7b5608 },
- { 0x4f50f97075e7f431ULL, { 0x9a50a17, 0x11cd1185 }, 0x2af952b34c032df4ULL, 0xfddc6a3 },
- { 0x2f8b0d712e393be4ULL, { 0x1487e386, 0x15aa356e }, 0x2d0df36478a776aaULL, 0x14e2564c },
- { 0x224c1c75999d3deULL, { 0x3b2df0ea, 0x4523b100 }, 0x1d5b481d145f08aULL, 0x15145eec },
- { 0x2bcbcea22a399a76ULL, { 0x28b58212, 0x48dd013e }, 0x187814d084c47cabULL, 0x3a38ebe2 },
- { 0x1dbfca91257cb2d1ULL, { 0x1a8c04d9, 0x5e92502c }, 0x859cf7d00f77545ULL, 0x7431f4d },
- { 0x7f20039b57cda935ULL, { 0xeccf651, 0x323f476e }, 0x25720cd976461a77ULL, 0x202817a3 },
- { 0x40512c6a586aa087ULL, { 0x113b0423, 0x398c9eab }, 0x1341c03de8696a7eULL, 0x1e27284b },
- { 0x63d802693f050a11ULL, { 0xf50cdd6, 0xfce2a44 }, 0x60c0177bb5e46846ULL, 0xf7ad89e },
- { 0x2d956b422838de77ULL, { 0xb2d345b, 0x1321e557 }, 0x1aa0ed16b6aa5319ULL, 0xfe1a5ce },
- { 0x5a1cdf0c1657bc91ULL, { 0x1d77bb0c, 0x1f991ff1 }, 0x54097ee94ff87560ULL, 0x11c4a26c },
- { 0x3801b26d7e00176bULL, { 0xeed25da, 0x1a819d8b }, 0x1f89e96a3a639526ULL, 0xcd51e7c },
- { 0x37655e74338e1e45ULL, { 0x300e170a, 0x5a1595fe }, 0x1d8cfb55fddc0441ULL, 0x3df05434 },
- { 0x7b38703f2a84e6ULL, { 0x66d9053, 0xc79b6b9 }, 0x3f7d4c91774094ULL, 0x26d939e },
- { 0x2245063c0acb3215ULL, { 0x30ce2f5b, 0x610e7271 }, 0x113b916468389235ULL, 0x1b588512 },
- { 0x6bc195877b7b8a7eULL, { 0x392004aa, 0x4a24e60c }, 0x530594fb17db6ba5ULL, 0x35c0a5f0 },
- { 0x40a3fde23c7b43dbULL, { 0x4e712195, 0x6553e56e }, 0x320a799bc76a466aULL, 0x5e23a5eb },
- { 0x1d3dfc2866fbccbaULL, { 0x5075b517, 0x5fc42245 }, 0x18917f0061595bc3ULL, 0x3fcf4527 },
- { 0x19aeb14045a61121ULL, { 0x1bf6edec, 0x707e2f4b }, 0x6626672a070bcc7ULL, 0x3607801f },
- { 0x44ff90486c531e9fULL, { 0x66598a, 0x8a90dc }, 0x32f6f2b0525199b0ULL, 0x5ab576 },
- { 0x3f3e7121092c5bcbULL, { 0x1c754df7, 0x5951a1b9 }, 0x14267f50b7ef375dULL, 0x221220a8 },
- { 0x60e2dafb7e50a67eULL, { 0x4d96c66e, 0x65bd878d }, 0x49e31715ac393f8bULL, 0x4e97b195 },
- { 0x656286667e0e6e29ULL, { 0x9d971a2, 0xacda23b }, 0x5c6ee315ead6cb4fULL, 0x516f5bd },
- { 0x1114e0974255d507ULL, { 0x1c693, 0x2d6ff }, 0xaae42e4b35f6e60ULL, 0x8b65 },
- { 0x508c8baf3a70ff5aULL, { 0x3b26b779, 0x6ad78745 }, 0x2c98387636c4b365ULL, 0x11dc6a51 },
- { 0x5b47bc666bf1f9cfULL, { 0x10a87ed6, 0x187d358a }, 0x3e1767155848368bULL, 0xfb871c },
- { 0x50954e3744460395ULL, { 0x7a42263, 0xcdaa048 }, 0x2fe739f0aee1fee1ULL, 0xb8add57 },
- { 0x20020b406550dd8fULL, { 0x3318539, 0x42eead0 }, 0x186f326325fa346bULL, 0x10d3ae7 },
- { 0x5bcb0b872439ffd5ULL, { 0x6f61fb2, 0x9af7344 }, 0x41fa1e3bec3c1b30ULL, 0x4fee45a },
- { 0x7a670f365db87a53ULL, { 0x417e102, 0x3bb54c67 }, 0x8642a558304fd9eULL, 0x3b65f514 },
- { 0x1ef0db1e7bab1cd0ULL, { 0x2b60cf38, 0x4188f78f }, 0x147ae0d6226b2ee6ULL, 0x336b6106 }
- };
-
- for (unsigned i = 0; i < 80; i++) {
- BlockFrequency Freq(Tests[i].Freq);
- uint32_t Remainder = Freq.scale(BranchProbability(Tests[i].Prob[0],
- Tests[i].Prob[1]));
- EXPECT_EQ(Tests[i].ExpectedFreq, Freq.getFrequency());
- EXPECT_EQ(Tests[i].ExpectedRemainder, Remainder);
- }
}
TEST(BlockFrequency, Divide) {
@@ -208,35 +102,6 @@ TEST(BlockFrequencyTest, Saturate) {
EXPECT_EQ(33506781356485509ULL, Freq.getFrequency());
}
-TEST(BlockFrequencyTest, ProbabilityCompare) {
- BranchProbability A(4, 5);
- BranchProbability B(4U << 29, 5U << 29);
- BranchProbability C(3, 4);
-
- EXPECT_TRUE(A == B);
- EXPECT_FALSE(A != B);
- EXPECT_FALSE(A < B);
- EXPECT_FALSE(A > B);
- EXPECT_TRUE(A <= B);
- EXPECT_TRUE(A >= B);
-
- EXPECT_FALSE(B == C);
- EXPECT_TRUE(B != C);
- EXPECT_FALSE(B < C);
- EXPECT_TRUE(B > C);
- EXPECT_FALSE(B <= C);
- EXPECT_TRUE(B >= C);
-
- BranchProbability BigZero(0, UINT32_MAX);
- BranchProbability BigOne(UINT32_MAX, UINT32_MAX);
- EXPECT_FALSE(BigZero == BigOne);
- EXPECT_TRUE(BigZero != BigOne);
- EXPECT_TRUE(BigZero < BigOne);
- EXPECT_FALSE(BigZero > BigOne);
- EXPECT_TRUE(BigZero <= BigOne);
- EXPECT_FALSE(BigZero >= BigOne);
-}
-
TEST(BlockFrequencyTest, SaturatingRightShift) {
BlockFrequency Freq(0x10080ULL);
Freq >>= 2;
diff --git a/unittests/Support/BranchProbabilityTest.cpp b/unittests/Support/BranchProbabilityTest.cpp
new file mode 100644
index 0000000..bbd4d4e
--- /dev/null
+++ b/unittests/Support/BranchProbabilityTest.cpp
@@ -0,0 +1,282 @@
+//===- unittest/Support/BranchProbabilityTest.cpp - BranchProbability tests -=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/BranchProbability.h"
+#include "llvm/Support/raw_ostream.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace llvm {
+void PrintTo(const BranchProbability &P, ::std::ostream *os) {
+ *os << P.getNumerator() << "/" << P.getDenominator();
+}
+}
+namespace {
+
+typedef BranchProbability BP;
+TEST(BranchProbabilityTest, Accessors) {
+ EXPECT_EQ(1u, BP(1, 7).getNumerator());
+ EXPECT_EQ(7u, BP(1, 7).getDenominator());
+ EXPECT_EQ(0u, BP::getZero().getNumerator());
+ EXPECT_EQ(1u, BP::getZero().getDenominator());
+ EXPECT_EQ(1u, BP::getOne().getNumerator());
+ EXPECT_EQ(1u, BP::getOne().getDenominator());
+}
+
+TEST(BranchProbabilityTest, Operators) {
+ EXPECT_TRUE(BP(1, 7) < BP(2, 7));
+ EXPECT_TRUE(BP(1, 7) < BP(1, 4));
+ EXPECT_TRUE(BP(5, 7) < BP(3, 4));
+ EXPECT_FALSE(BP(1, 7) < BP(1, 7));
+ EXPECT_FALSE(BP(1, 7) < BP(2, 14));
+ EXPECT_FALSE(BP(4, 7) < BP(1, 2));
+ EXPECT_FALSE(BP(4, 7) < BP(3, 7));
+
+ EXPECT_FALSE(BP(1, 7) > BP(2, 7));
+ EXPECT_FALSE(BP(1, 7) > BP(1, 4));
+ EXPECT_FALSE(BP(5, 7) > BP(3, 4));
+ EXPECT_FALSE(BP(1, 7) > BP(1, 7));
+ EXPECT_FALSE(BP(1, 7) > BP(2, 14));
+ EXPECT_TRUE(BP(4, 7) > BP(1, 2));
+ EXPECT_TRUE(BP(4, 7) > BP(3, 7));
+
+ EXPECT_TRUE(BP(1, 7) <= BP(2, 7));
+ EXPECT_TRUE(BP(1, 7) <= BP(1, 4));
+ EXPECT_TRUE(BP(5, 7) <= BP(3, 4));
+ EXPECT_TRUE(BP(1, 7) <= BP(1, 7));
+ EXPECT_TRUE(BP(1, 7) <= BP(2, 14));
+ EXPECT_FALSE(BP(4, 7) <= BP(1, 2));
+ EXPECT_FALSE(BP(4, 7) <= BP(3, 7));
+
+ EXPECT_FALSE(BP(1, 7) >= BP(2, 7));
+ EXPECT_FALSE(BP(1, 7) >= BP(1, 4));
+ EXPECT_FALSE(BP(5, 7) >= BP(3, 4));
+ EXPECT_TRUE(BP(1, 7) >= BP(1, 7));
+ EXPECT_TRUE(BP(1, 7) >= BP(2, 14));
+ EXPECT_TRUE(BP(4, 7) >= BP(1, 2));
+ EXPECT_TRUE(BP(4, 7) >= BP(3, 7));
+
+ EXPECT_FALSE(BP(1, 7) == BP(2, 7));
+ EXPECT_FALSE(BP(1, 7) == BP(1, 4));
+ EXPECT_FALSE(BP(5, 7) == BP(3, 4));
+ EXPECT_TRUE(BP(1, 7) == BP(1, 7));
+ EXPECT_TRUE(BP(1, 7) == BP(2, 14));
+ EXPECT_FALSE(BP(4, 7) == BP(1, 2));
+ EXPECT_FALSE(BP(4, 7) == BP(3, 7));
+
+ EXPECT_TRUE(BP(1, 7) != BP(2, 7));
+ EXPECT_TRUE(BP(1, 7) != BP(1, 4));
+ EXPECT_TRUE(BP(5, 7) != BP(3, 4));
+ EXPECT_FALSE(BP(1, 7) != BP(1, 7));
+ EXPECT_FALSE(BP(1, 7) != BP(2, 14));
+ EXPECT_TRUE(BP(4, 7) != BP(1, 2));
+ EXPECT_TRUE(BP(4, 7) != BP(3, 7));
+}
+
+TEST(BranchProbabilityTest, MoreOperators) {
+ BP A(4, 5);
+ BP B(4U << 29, 5U << 29);
+ BP C(3, 4);
+
+ EXPECT_TRUE(A == B);
+ EXPECT_FALSE(A != B);
+ EXPECT_FALSE(A < B);
+ EXPECT_FALSE(A > B);
+ EXPECT_TRUE(A <= B);
+ EXPECT_TRUE(A >= B);
+
+ EXPECT_FALSE(B == C);
+ EXPECT_TRUE(B != C);
+ EXPECT_FALSE(B < C);
+ EXPECT_TRUE(B > C);
+ EXPECT_FALSE(B <= C);
+ EXPECT_TRUE(B >= C);
+
+ BP BigZero(0, UINT32_MAX);
+ BP BigOne(UINT32_MAX, UINT32_MAX);
+ EXPECT_FALSE(BigZero == BigOne);
+ EXPECT_TRUE(BigZero != BigOne);
+ EXPECT_TRUE(BigZero < BigOne);
+ EXPECT_FALSE(BigZero > BigOne);
+ EXPECT_TRUE(BigZero <= BigOne);
+ EXPECT_FALSE(BigZero >= BigOne);
+}
+
+TEST(BranchProbabilityTest, getCompl) {
+ EXPECT_EQ(BP(5, 7), BP(2, 7).getCompl());
+ EXPECT_EQ(BP(2, 7), BP(5, 7).getCompl());
+ EXPECT_EQ(BP::getZero(), BP(7, 7).getCompl());
+ EXPECT_EQ(BP::getOne(), BP(0, 7).getCompl());
+}
+
+TEST(BranchProbabilityTest, scale) {
+ // Multiply by 1.0.
+ EXPECT_EQ(UINT64_MAX, BP(1, 1).scale(UINT64_MAX));
+ EXPECT_EQ(UINT64_MAX, BP(7, 7).scale(UINT64_MAX));
+ EXPECT_EQ(UINT32_MAX, BP(1, 1).scale(UINT32_MAX));
+ EXPECT_EQ(UINT32_MAX, BP(7, 7).scale(UINT32_MAX));
+ EXPECT_EQ(0u, BP(1, 1).scale(0));
+ EXPECT_EQ(0u, BP(7, 7).scale(0));
+
+ // Multiply by 0.0.
+ EXPECT_EQ(0u, BP(0, 1).scale(UINT64_MAX));
+ EXPECT_EQ(0u, BP(0, 1).scale(UINT64_MAX));
+ EXPECT_EQ(0u, BP(0, 1).scale(0));
+
+ auto Two63 = UINT64_C(1) << 63;
+ auto Two31 = UINT64_C(1) << 31;
+
+ // Multiply by 0.5.
+ EXPECT_EQ(Two63 - 1, BP(1, 2).scale(UINT64_MAX));
+
+ // Big fractions.
+ EXPECT_EQ(1u, BP(Two31, UINT32_MAX).scale(2));
+ EXPECT_EQ(Two31, BP(Two31, UINT32_MAX).scale(Two31 * 2));
+ EXPECT_EQ(Two63 + Two31, BP(Two31, UINT32_MAX).scale(UINT64_MAX));
+
+ // High precision.
+ EXPECT_EQ(UINT64_C(9223372047592194055),
+ BP(Two31 + 1, UINT32_MAX - 2).scale(UINT64_MAX));
+}
+
+TEST(BranchProbabilityTest, scaleByInverse) {
+ // Divide by 1.0.
+ EXPECT_EQ(UINT64_MAX, BP(1, 1).scaleByInverse(UINT64_MAX));
+ EXPECT_EQ(UINT64_MAX, BP(7, 7).scaleByInverse(UINT64_MAX));
+ EXPECT_EQ(UINT32_MAX, BP(1, 1).scaleByInverse(UINT32_MAX));
+ EXPECT_EQ(UINT32_MAX, BP(7, 7).scaleByInverse(UINT32_MAX));
+ EXPECT_EQ(0u, BP(1, 1).scaleByInverse(0));
+ EXPECT_EQ(0u, BP(7, 7).scaleByInverse(0));
+
+ // Divide by something very small.
+ EXPECT_EQ(UINT64_MAX, BP(1, UINT32_MAX).scaleByInverse(UINT64_MAX));
+ EXPECT_EQ(uint64_t(UINT32_MAX) * UINT32_MAX,
+ BP(1, UINT32_MAX).scaleByInverse(UINT32_MAX));
+ EXPECT_EQ(UINT32_MAX, BP(1, UINT32_MAX).scaleByInverse(1));
+
+ auto Two63 = UINT64_C(1) << 63;
+ auto Two31 = UINT64_C(1) << 31;
+
+ // Divide by 0.5.
+ EXPECT_EQ(UINT64_MAX - 1, BP(1, 2).scaleByInverse(Two63 - 1));
+ EXPECT_EQ(UINT64_MAX, BP(1, 2).scaleByInverse(Two63));
+
+ // Big fractions.
+ EXPECT_EQ(1u, BP(Two31, UINT32_MAX).scaleByInverse(1));
+ EXPECT_EQ(2u, BP(Two31 - 1, UINT32_MAX).scaleByInverse(1));
+ EXPECT_EQ(Two31 * 2 - 1, BP(Two31, UINT32_MAX).scaleByInverse(Two31));
+ EXPECT_EQ(Two31 * 2 + 1, BP(Two31 - 1, UINT32_MAX).scaleByInverse(Two31));
+ EXPECT_EQ(UINT64_MAX, BP(Two31, UINT32_MAX).scaleByInverse(Two63 + Two31));
+
+ // High precision. The exact answers to these are close to the successors of
+ // the floor. If we were rounding, these would round up.
+ EXPECT_EQ(UINT64_C(18446744065119617030),
+ BP(Two31 + 2, UINT32_MAX - 2)
+ .scaleByInverse(UINT64_C(9223372047592194055)));
+ EXPECT_EQ(UINT64_C(18446744065119617026),
+ BP(Two31 + 1, UINT32_MAX).scaleByInverse(Two63 + Two31));
+}
+
+TEST(BranchProbabilityTest, scaleBruteForce) {
+ struct {
+ uint64_t Num;
+ uint32_t Prob[2];
+ uint64_t Result;
+ } Tests[] = {
+ // Data for scaling that results in <= 64 bit division.
+ { 0x1423e2a50ULL, { 0x64819521, 0x7765dd13 }, 0x10f418889ULL },
+ { 0x35ef14ceULL, { 0x28ade3c7, 0x304532ae }, 0x2d73c33aULL },
+ { 0xd03dbfbe24ULL, { 0x790079, 0xe419f3 }, 0x6e776fc1fdULL },
+ { 0x21d67410bULL, { 0x302a9dc2, 0x3ddb4442 }, 0x1a5948fd6ULL },
+ { 0x8664aeadULL, { 0x3d523513, 0x403523b1 }, 0x805a04cfULL },
+ { 0x201db0cf4ULL, { 0x35112a7b, 0x79fc0c74 }, 0xdf8b07f6ULL },
+ { 0x13f1e4430aULL, { 0x21c92bf, 0x21e63aae }, 0x13e0cba15ULL },
+ { 0x16c83229ULL, { 0x3793f66f, 0x53180dea }, 0xf3ce7b6ULL },
+ { 0xc62415be8ULL, { 0x9cc4a63, 0x4327ae9b }, 0x1ce8b71caULL },
+ { 0x6fac5e434ULL, { 0xe5f9170, 0x1115e10b }, 0x5df23dd4cULL },
+ { 0x1929375f2ULL, { 0x3a851375, 0x76c08456 }, 0xc662b082ULL },
+ { 0x243c89db6ULL, { 0x354ebfc0, 0x450ef197 }, 0x1bf8c1661ULL },
+ { 0x310e9b31aULL, { 0x1b1b8acf, 0x2d3629f0 }, 0x1d69c93f9ULL },
+ { 0xa1fae921dULL, { 0xa7a098c, 0x10469f44 }, 0x684413d6cULL },
+ { 0xc1582d957ULL, { 0x498e061, 0x59856bc }, 0x9edc5f4e7ULL },
+ { 0x57cfee75ULL, { 0x1d061dc3, 0x7c8bfc17 }, 0x1476a220ULL },
+ { 0x139220080ULL, { 0x294a6c71, 0x2a2b07c9 }, 0x1329e1c76ULL },
+ { 0x1665d353cULL, { 0x7080db5, 0xde0d75c }, 0xb590d9fbULL },
+ { 0xe8f14541ULL, { 0x5188e8b2, 0x736527ef }, 0xa4971be5ULL },
+ { 0x2f4775f29ULL, { 0x254ef0fe, 0x435fcf50 }, 0x1a2e449c1ULL },
+ { 0x27b85d8d7ULL, { 0x304c8220, 0x5de678f2 }, 0x146e3bef9ULL },
+ { 0x1d362e36bULL, { 0x36c85b12, 0x37a66f55 }, 0x1cc19b8e6ULL },
+ { 0x155fd48c7ULL, { 0xf5894d, 0x1256108 }, 0x11e383602ULL },
+ { 0xb5db2d15ULL, { 0x39bb26c5, 0x5bdcda3e }, 0x72499259ULL },
+ { 0x153990298ULL, { 0x48921c09, 0x706eb817 }, 0xdb3268e8ULL },
+ { 0x28a7c3ed7ULL, { 0x1f776fd7, 0x349f7a70 }, 0x184f73ae1ULL },
+ { 0x724dbeabULL, { 0x1bd149f5, 0x253a085e }, 0x5569c0b3ULL },
+ { 0xd8f0c513ULL, { 0x18c8cc4c, 0x1b72bad0 }, 0xc3e30643ULL },
+ { 0x17ce3dcbULL, { 0x1e4c6260, 0x233b359e }, 0x1478f4afULL },
+ { 0x1ce036ce0ULL, { 0x29e3c8af, 0x5318dd4a }, 0xe8e76196ULL },
+ { 0x1473ae2aULL, { 0x29b897ba, 0x2be29378 }, 0x13718185ULL },
+ { 0x1dd41aa68ULL, { 0x3d0a4441, 0x5a0e8f12 }, 0x1437b6bbfULL },
+ { 0x1b49e4a53ULL, { 0x3430c1fe, 0x5a204aed }, 0xfcd6852fULL },
+ { 0x217941b19ULL, { 0x12ced2bd, 0x21b68310 }, 0x12aca65b1ULL },
+ { 0xac6a4dc8ULL, { 0x3ed68da8, 0x6fdca34c }, 0x60da926dULL },
+ { 0x1c503a4e7ULL, { 0xfcbbd32, 0x11e48d17 }, 0x18fec7d38ULL },
+ { 0x1c885855ULL, { 0x213e919d, 0x25941897 }, 0x193de743ULL },
+ { 0x29b9c168eULL, { 0x2b644aea, 0x45725ee7 }, 0x1a122e5d5ULL },
+ { 0x806a33f2ULL, { 0x30a80a23, 0x5063733a }, 0x4db9a264ULL },
+ { 0x282afc96bULL, { 0x143ae554, 0x1a9863ff }, 0x1e8de5204ULL },
+ // Data for scaling that results in > 64 bit division.
+ { 0x23ca5f2f672ca41cULL, { 0xecbc641, 0x111373f7 }, 0x1f0301e5e8295ab5ULL },
+ { 0x5e4f2468142265e3ULL, { 0x1ddf5837, 0x32189233 }, 0x383ca7ba9fdd2c8cULL },
+ { 0x277a1a6f6b266bf6ULL, { 0x415d81a8, 0x61eb5e1e }, 0x1a5a3e1d41b30c0fULL },
+ { 0x1bdbb49a237035cbULL, { 0xea5bf17, 0x1d25ffb3 }, 0xdffc51c53d44b93ULL },
+ { 0x2bce6d29b64fb8ULL, { 0x3bfd5631, 0x7525c9bb }, 0x166ebedda7ac57ULL },
+ { 0x3a02116103df5013ULL, { 0x2ee18a83, 0x3299aea8 }, 0x35be8922ab1e2a84ULL },
+ { 0x7b5762390799b18cULL, { 0x12f8e5b9, 0x2563bcd4 }, 0x3e960077aca01209ULL },
+ { 0x69cfd72537021579ULL, { 0x4c35f468, 0x6a40feee }, 0x4be4cb3848be98a3ULL },
+ { 0x49dfdf835120f1c1ULL, { 0x8cb3759, 0x559eb891 }, 0x79663f7120edadeULL },
+ { 0x74b5be5c27676381ULL, { 0x47e4c5e0, 0x7c7b19ff }, 0x4367d2dff36a1028ULL },
+ { 0x4f50f97075e7f431ULL, { 0x9a50a17, 0x11cd1185 }, 0x2af952b34c032df4ULL },
+ { 0x2f8b0d712e393be4ULL, { 0x1487e386, 0x15aa356e }, 0x2d0df36478a776aaULL },
+ { 0x224c1c75999d3deULL, { 0x3b2df0ea, 0x4523b100 }, 0x1d5b481d145f08aULL },
+ { 0x2bcbcea22a399a76ULL, { 0x28b58212, 0x48dd013e }, 0x187814d084c47cabULL },
+ { 0x1dbfca91257cb2d1ULL, { 0x1a8c04d9, 0x5e92502c }, 0x859cf7d00f77545ULL },
+ { 0x7f20039b57cda935ULL, { 0xeccf651, 0x323f476e }, 0x25720cd976461a77ULL },
+ { 0x40512c6a586aa087ULL, { 0x113b0423, 0x398c9eab }, 0x1341c03de8696a7eULL },
+ { 0x63d802693f050a11ULL, { 0xf50cdd6, 0xfce2a44 }, 0x60c0177bb5e46846ULL },
+ { 0x2d956b422838de77ULL, { 0xb2d345b, 0x1321e557 }, 0x1aa0ed16b6aa5319ULL },
+ { 0x5a1cdf0c1657bc91ULL, { 0x1d77bb0c, 0x1f991ff1 }, 0x54097ee94ff87560ULL },
+ { 0x3801b26d7e00176bULL, { 0xeed25da, 0x1a819d8b }, 0x1f89e96a3a639526ULL },
+ { 0x37655e74338e1e45ULL, { 0x300e170a, 0x5a1595fe }, 0x1d8cfb55fddc0441ULL },
+ { 0x7b38703f2a84e6ULL, { 0x66d9053, 0xc79b6b9 }, 0x3f7d4c91774094ULL },
+ { 0x2245063c0acb3215ULL, { 0x30ce2f5b, 0x610e7271 }, 0x113b916468389235ULL },
+ { 0x6bc195877b7b8a7eULL, { 0x392004aa, 0x4a24e60c }, 0x530594fb17db6ba5ULL },
+ { 0x40a3fde23c7b43dbULL, { 0x4e712195, 0x6553e56e }, 0x320a799bc76a466aULL },
+ { 0x1d3dfc2866fbccbaULL, { 0x5075b517, 0x5fc42245 }, 0x18917f0061595bc3ULL },
+ { 0x19aeb14045a61121ULL, { 0x1bf6edec, 0x707e2f4b }, 0x6626672a070bcc7ULL },
+ { 0x44ff90486c531e9fULL, { 0x66598a, 0x8a90dc }, 0x32f6f2b0525199b0ULL },
+ { 0x3f3e7121092c5bcbULL, { 0x1c754df7, 0x5951a1b9 }, 0x14267f50b7ef375dULL },
+ { 0x60e2dafb7e50a67eULL, { 0x4d96c66e, 0x65bd878d }, 0x49e31715ac393f8bULL },
+ { 0x656286667e0e6e29ULL, { 0x9d971a2, 0xacda23b }, 0x5c6ee315ead6cb4fULL },
+ { 0x1114e0974255d507ULL, { 0x1c693, 0x2d6ff }, 0xaae42e4b35f6e60ULL },
+ { 0x508c8baf3a70ff5aULL, { 0x3b26b779, 0x6ad78745 }, 0x2c98387636c4b365ULL },
+ { 0x5b47bc666bf1f9cfULL, { 0x10a87ed6, 0x187d358a }, 0x3e1767155848368bULL },
+ { 0x50954e3744460395ULL, { 0x7a42263, 0xcdaa048 }, 0x2fe739f0aee1fee1ULL },
+ { 0x20020b406550dd8fULL, { 0x3318539, 0x42eead0 }, 0x186f326325fa346bULL },
+ { 0x5bcb0b872439ffd5ULL, { 0x6f61fb2, 0x9af7344 }, 0x41fa1e3bec3c1b30ULL },
+ { 0x7a670f365db87a53ULL, { 0x417e102, 0x3bb54c67 }, 0x8642a558304fd9eULL },
+ { 0x1ef0db1e7bab1cd0ULL, { 0x2b60cf38, 0x4188f78f }, 0x147ae0d6226b2ee6ULL }
+ };
+
+ for (const auto &T : Tests) {
+ EXPECT_EQ(T.Result, BP(T.Prob[0], T.Prob[1]).scale(T.Num));
+ }
+}
+
+}
diff --git a/unittests/Support/CMakeLists.txt b/unittests/Support/CMakeLists.txt
index 4afa4fd..0ea9310 100644
--- a/unittests/Support/CMakeLists.txt
+++ b/unittests/Support/CMakeLists.txt
@@ -7,6 +7,7 @@ add_llvm_unittest(SupportTests
AllocatorTest.cpp
ArrayRecyclerTest.cpp
BlockFrequencyTest.cpp
+ BranchProbabilityTest.cpp
Casting.cpp
CommandLineTest.cpp
CompressionTest.cpp
@@ -15,12 +16,13 @@ add_llvm_unittest(SupportTests
EndianTest.cpp
ErrorOrTest.cpp
FileOutputBufferTest.cpp
+ IteratorTest.cpp
LEB128Test.cpp
LineIteratorTest.cpp
LockFileManagerTest.cpp
+ MD5Test.cpp
ManagedStatic.cpp
MathExtrasTest.cpp
- MD5Test.cpp
MemoryBufferTest.cpp
MemoryTest.cpp
Path.cpp
diff --git a/unittests/Support/CompressionTest.cpp b/unittests/Support/CompressionTest.cpp
index db6a8bb..698ae3a 100644
--- a/unittests/Support/CompressionTest.cpp
+++ b/unittests/Support/CompressionTest.cpp
@@ -13,8 +13,8 @@
#include "llvm/Support/Compression.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/SmallString.h"
#include "llvm/Config/config.h"
-#include "llvm/Support/MemoryBuffer.h"
#include "gtest/gtest.h"
using namespace llvm;
@@ -24,20 +24,17 @@ namespace {
#if LLVM_ENABLE_ZLIB == 1 && HAVE_LIBZ
void TestZlibCompression(StringRef Input, zlib::CompressionLevel Level) {
- std::unique_ptr<MemoryBuffer> Compressed;
- std::unique_ptr<MemoryBuffer> Uncompressed;
+ SmallString<32> Compressed;
+ SmallString<32> Uncompressed;
EXPECT_EQ(zlib::StatusOK, zlib::compress(Input, Compressed, Level));
// Check that uncompressed buffer is the same as original.
- EXPECT_EQ(zlib::StatusOK, zlib::uncompress(Compressed->getBuffer(),
- Uncompressed, Input.size()));
- EXPECT_EQ(Input.size(), Uncompressed->getBufferSize());
- EXPECT_EQ(0,
- memcmp(Input.data(), Uncompressed->getBufferStart(), Input.size()));
+ EXPECT_EQ(zlib::StatusOK,
+ zlib::uncompress(Compressed, Uncompressed, Input.size()));
+ EXPECT_EQ(Input, Uncompressed);
if (Input.size() > 0) {
// Uncompression fails if expected length is too short.
EXPECT_EQ(zlib::StatusBufferTooShort,
- zlib::uncompress(Compressed->getBuffer(), Uncompressed,
- Input.size() - 1));
+ zlib::uncompress(Compressed, Uncompressed, Input.size() - 1));
}
}
diff --git a/unittests/Support/FileOutputBufferTest.cpp b/unittests/Support/FileOutputBufferTest.cpp
index 6d62999..0801f85 100644
--- a/unittests/Support/FileOutputBufferTest.cpp
+++ b/unittests/Support/FileOutputBufferTest.cpp
@@ -8,7 +8,6 @@
//===----------------------------------------------------------------------===//
#include "llvm/Support/FileOutputBuffer.h"
-#include "llvm/ADT/OwningPtr.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
@@ -38,7 +37,7 @@ TEST(FileOutputBuffer, Test) {
SmallString<128> File1(TestDirectory);
File1.append("/file1");
{
- OwningPtr<FileOutputBuffer> Buffer;
+ std::unique_ptr<FileOutputBuffer> Buffer;
ASSERT_NO_ERROR(FileOutputBuffer::create(File1, 8192, Buffer));
// Start buffer with special header.
memcpy(Buffer->getBufferStart(), "AABBCCDDEEFFGGHHIIJJ", 20);
@@ -62,7 +61,7 @@ TEST(FileOutputBuffer, Test) {
SmallString<128> File2(TestDirectory);
File2.append("/file2");
{
- OwningPtr<FileOutputBuffer> Buffer2;
+ std::unique_ptr<FileOutputBuffer> Buffer2;
ASSERT_NO_ERROR(FileOutputBuffer::create(File2, 8192, Buffer2));
// Fill buffer with special header.
memcpy(Buffer2->getBufferStart(), "AABBCCDDEEFFGGHHIIJJ", 20);
@@ -78,7 +77,7 @@ TEST(FileOutputBuffer, Test) {
SmallString<128> File3(TestDirectory);
File3.append("/file3");
{
- OwningPtr<FileOutputBuffer> Buffer;
+ std::unique_ptr<FileOutputBuffer> Buffer;
ASSERT_NO_ERROR(FileOutputBuffer::create(File3, 8192000, Buffer));
// Start buffer with special header.
memcpy(Buffer->getBufferStart(), "AABBCCDDEEFFGGHHIIJJ", 20);
@@ -102,7 +101,7 @@ TEST(FileOutputBuffer, Test) {
SmallString<128> File4(TestDirectory);
File4.append("/file4");
{
- OwningPtr<FileOutputBuffer> Buffer;
+ std::unique_ptr<FileOutputBuffer> Buffer;
ASSERT_NO_ERROR(FileOutputBuffer::create(File4, 8192, Buffer,
FileOutputBuffer::F_executable));
// Start buffer with special header.
diff --git a/unittests/Support/IteratorTest.cpp b/unittests/Support/IteratorTest.cpp
new file mode 100644
index 0000000..8384832
--- /dev/null
+++ b/unittests/Support/IteratorTest.cpp
@@ -0,0 +1,101 @@
+//===- IteratorTest.cpp - Unit tests for iterator utilities ---------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/iterator.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVector.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+TEST(PointeeIteratorTest, Basic) {
+ int arr[4] = { 1, 2, 3, 4 };
+ SmallVector<int *, 4> V;
+ V.push_back(&arr[0]);
+ V.push_back(&arr[1]);
+ V.push_back(&arr[2]);
+ V.push_back(&arr[3]);
+
+ typedef pointee_iterator<SmallVectorImpl<int *>::const_iterator> test_iterator;
+
+ test_iterator Begin, End;
+ Begin = V.begin();
+ End = test_iterator(V.end());
+
+ test_iterator I = Begin;
+ for (int i = 0; i < 4; ++i) {
+ EXPECT_EQ(*V[i], *I);
+
+ EXPECT_EQ(I, Begin + i);
+ EXPECT_EQ(I, std::next(Begin, i));
+ test_iterator J = Begin;
+ J += i;
+ EXPECT_EQ(I, J);
+ EXPECT_EQ(*V[i], Begin[i]);
+
+ EXPECT_NE(I, End);
+ EXPECT_GT(End, I);
+ EXPECT_LT(I, End);
+ EXPECT_GE(I, Begin);
+ EXPECT_LE(Begin, I);
+
+ EXPECT_EQ(i, I - Begin);
+ EXPECT_EQ(i, std::distance(Begin, I));
+ EXPECT_EQ(Begin, I - i);
+
+ test_iterator K = I++;
+ EXPECT_EQ(K, std::prev(I));
+ }
+ EXPECT_EQ(End, I);
+}
+
+TEST(PointeeIteratorTest, SmartPointer) {
+ SmallVector<std::unique_ptr<int>, 4> V;
+ V.push_back(make_unique<int>(1));
+ V.push_back(make_unique<int>(2));
+ V.push_back(make_unique<int>(3));
+ V.push_back(make_unique<int>(4));
+
+ typedef pointee_iterator<
+ SmallVectorImpl<std::unique_ptr<int>>::const_iterator> test_iterator;
+
+ test_iterator Begin, End;
+ Begin = V.begin();
+ End = test_iterator(V.end());
+
+ test_iterator I = Begin;
+ for (int i = 0; i < 4; ++i) {
+ EXPECT_EQ(*V[i], *I);
+
+ EXPECT_EQ(I, Begin + i);
+ EXPECT_EQ(I, std::next(Begin, i));
+ test_iterator J = Begin;
+ J += i;
+ EXPECT_EQ(I, J);
+ EXPECT_EQ(*V[i], Begin[i]);
+
+ EXPECT_NE(I, End);
+ EXPECT_GT(End, I);
+ EXPECT_LT(I, End);
+ EXPECT_GE(I, Begin);
+ EXPECT_LE(Begin, I);
+
+ EXPECT_EQ(i, I - Begin);
+ EXPECT_EQ(i, std::distance(Begin, I));
+ EXPECT_EQ(Begin, I - i);
+
+ test_iterator K = I++;
+ EXPECT_EQ(K, std::prev(I));
+ }
+ EXPECT_EQ(End, I);
+}
+
+} // anonymous namespace
diff --git a/unittests/Support/MemoryBufferTest.cpp b/unittests/Support/MemoryBufferTest.cpp
index 43b7e0d..6790d0c 100644
--- a/unittests/Support/MemoryBufferTest.cpp
+++ b/unittests/Support/MemoryBufferTest.cpp
@@ -12,7 +12,6 @@
//===----------------------------------------------------------------------===//
#include "llvm/Support/FileSystem.h"
-#include "llvm/ADT/OwningPtr.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
#include "gtest/gtest.h"
@@ -36,7 +35,7 @@ protected:
/// anew before using MemoryBuffer.
void testGetOpenFileSlice(bool Reopen);
- typedef OwningPtr<MemoryBuffer> OwningBuffer;
+ typedef std::unique_ptr<MemoryBuffer> OwningBuffer;
std::string data;
};
diff --git a/unittests/Support/YAMLIOTest.cpp b/unittests/Support/YAMLIOTest.cpp
index 52a8f6b..cf95532 100644
--- a/unittests/Support/YAMLIOTest.cpp
+++ b/unittests/Support/YAMLIOTest.cpp
@@ -302,11 +302,23 @@ struct StringTypes {
llvm::StringRef str3;
llvm::StringRef str4;
llvm::StringRef str5;
+ llvm::StringRef str6;
+ llvm::StringRef str7;
+ llvm::StringRef str8;
+ llvm::StringRef str9;
+ llvm::StringRef str10;
+ llvm::StringRef str11;
std::string stdstr1;
std::string stdstr2;
std::string stdstr3;
std::string stdstr4;
std::string stdstr5;
+ std::string stdstr6;
+ std::string stdstr7;
+ std::string stdstr8;
+ std::string stdstr9;
+ std::string stdstr10;
+ std::string stdstr11;
};
namespace llvm {
@@ -319,11 +331,23 @@ namespace yaml {
io.mapRequired("str3", st.str3);
io.mapRequired("str4", st.str4);
io.mapRequired("str5", st.str5);
+ io.mapRequired("str6", st.str6);
+ io.mapRequired("str7", st.str7);
+ io.mapRequired("str8", st.str8);
+ io.mapRequired("str9", st.str9);
+ io.mapRequired("str10", st.str10);
+ io.mapRequired("str11", st.str11);
io.mapRequired("stdstr1", st.stdstr1);
io.mapRequired("stdstr2", st.stdstr2);
io.mapRequired("stdstr3", st.stdstr3);
io.mapRequired("stdstr4", st.stdstr4);
io.mapRequired("stdstr5", st.stdstr5);
+ io.mapRequired("stdstr6", st.stdstr6);
+ io.mapRequired("stdstr7", st.stdstr7);
+ io.mapRequired("stdstr8", st.stdstr8);
+ io.mapRequired("stdstr9", st.stdstr9);
+ io.mapRequired("stdstr10", st.stdstr10);
+ io.mapRequired("stdstr11", st.stdstr11);
}
};
}
@@ -338,11 +362,23 @@ TEST(YAMLIO, TestReadWriteStringTypes) {
map.str3 = "`ccc";
map.str4 = "@ddd";
map.str5 = "";
+ map.str6 = "0000000004000000";
+ map.str7 = "true";
+ map.str8 = "FALSE";
+ map.str9 = "~";
+ map.str10 = "0.2e20";
+ map.str11 = "0x30";
map.stdstr1 = "'eee";
map.stdstr2 = "\"fff";
map.stdstr3 = "`ggg";
map.stdstr4 = "@hhh";
map.stdstr5 = "";
+ map.stdstr6 = "0000000004000000";
+ map.stdstr7 = "true";
+ map.stdstr8 = "FALSE";
+ map.stdstr9 = "~";
+ map.stdstr10 = "0.2e20";
+ map.stdstr11 = "0x30";
llvm::raw_string_ostream ostr(intermediate);
Output yout(ostr);
@@ -355,11 +391,18 @@ TEST(YAMLIO, TestReadWriteStringTypes) {
EXPECT_NE(llvm::StringRef::npos, flowOut.find("'`ccc'"));
EXPECT_NE(llvm::StringRef::npos, flowOut.find("'@ddd'"));
EXPECT_NE(llvm::StringRef::npos, flowOut.find("''\n"));
+ EXPECT_NE(llvm::StringRef::npos, flowOut.find("'0000000004000000'\n"));
+ EXPECT_NE(llvm::StringRef::npos, flowOut.find("'true'\n"));
+ EXPECT_NE(llvm::StringRef::npos, flowOut.find("'FALSE'\n"));
+ EXPECT_NE(llvm::StringRef::npos, flowOut.find("'~'\n"));
+ EXPECT_NE(llvm::StringRef::npos, flowOut.find("'0.2e20'\n"));
+ EXPECT_NE(llvm::StringRef::npos, flowOut.find("'0x30'\n"));
EXPECT_NE(std::string::npos, flowOut.find("'''eee"));
EXPECT_NE(std::string::npos, flowOut.find("'\"fff'"));
EXPECT_NE(std::string::npos, flowOut.find("'`ggg'"));
EXPECT_NE(std::string::npos, flowOut.find("'@hhh'"));
EXPECT_NE(std::string::npos, flowOut.find("''\n"));
+ EXPECT_NE(std::string::npos, flowOut.find("'0000000004000000'\n"));
{
Input yin(intermediate);
@@ -372,11 +415,13 @@ TEST(YAMLIO, TestReadWriteStringTypes) {
EXPECT_TRUE(map.str3.equals("`ccc"));
EXPECT_TRUE(map.str4.equals("@ddd"));
EXPECT_TRUE(map.str5.equals(""));
+ EXPECT_TRUE(map.str6.equals("0000000004000000"));
EXPECT_TRUE(map.stdstr1 == "'eee");
EXPECT_TRUE(map.stdstr2 == "\"fff");
EXPECT_TRUE(map.stdstr3 == "`ggg");
EXPECT_TRUE(map.stdstr4 == "@hhh");
EXPECT_TRUE(map.stdstr5 == "");
+ EXPECT_TRUE(map.stdstr6 == "0000000004000000");
}
}
@@ -602,6 +647,7 @@ namespace yaml {
return "malformed by";
}
}
+ static bool mustQuote(StringRef) { return true; }
};
}
}
@@ -663,6 +709,8 @@ namespace yaml {
value = n;
return StringRef();
}
+
+ static bool mustQuote(StringRef) { return false; }
};
}
}
diff --git a/unittests/Transforms/Utils/SpecialCaseList.cpp b/unittests/Transforms/Utils/SpecialCaseList.cpp
index 748834f..fd00687 100644
--- a/unittests/Transforms/Utils/SpecialCaseList.cpp
+++ b/unittests/Transforms/Utils/SpecialCaseList.cpp
@@ -34,9 +34,8 @@ protected:
M, ST, false, GlobalValue::ExternalLinkage, 0, Name);
}
- GlobalAlias *makeAlias(StringRef Name, GlobalValue *Aliasee) {
- return new GlobalAlias(Aliasee->getType(), GlobalValue::ExternalLinkage,
- Name, Aliasee, Aliasee->getParent());
+ GlobalAlias *makeAlias(StringRef Name, GlobalObject *Aliasee) {
+ return GlobalAlias::create(GlobalValue::ExternalLinkage, Name, Aliasee);
}
SpecialCaseList *makeSpecialCaseList(StringRef List, std::string &Error) {