Files
swift-mirror/unittests/SIL/PartitionUtilsTest.cpp

250 lines
9.1 KiB
C++

#include "gtest/gtest.h"
#include "swift/SILOptimizer/Utils/PartitionUtils.h"
using namespace swift;
// this test tests that if a series of merges is split between two partitions
// p1 and p2, but also applied in its entirety to p3, then joining p1 and p2
// yields p3
TEST(PartitionUtilsTest, TestMergeAndJoin) {
Partition p1;
Partition p2;
Partition p3;
p1.apply(PartitionOp::AssignFresh(Element(0)));
p1.apply(PartitionOp::AssignFresh(Element(1)));
p1.apply(PartitionOp::AssignFresh(Element(2)));
p1.apply(PartitionOp::AssignFresh(Element(3)));
p2.apply(PartitionOp::AssignFresh(Element(5)));
p2.apply(PartitionOp::AssignFresh(Element(6)));
p2.apply(PartitionOp::AssignFresh(Element(7)));
p2.apply(PartitionOp::AssignFresh(Element(0)));
p3.apply(PartitionOp::AssignFresh(Element(2)));
p3.apply(PartitionOp::AssignFresh(Element(3)));
p3.apply(PartitionOp::AssignFresh(Element(4)));
p3.apply(PartitionOp::AssignFresh(Element(5)));
EXPECT_FALSE(Partition::equals(p1, p2));
EXPECT_FALSE(Partition::equals(p2, p3));
EXPECT_FALSE(Partition::equals(p1, p3));
p1.apply(PartitionOp::AssignFresh(Element(4)));
p1.apply(PartitionOp::AssignFresh(Element(5)));
p1.apply(PartitionOp::AssignFresh(Element(6)));
p1.apply(PartitionOp::AssignFresh(Element(7)));
p1.apply(PartitionOp::AssignFresh(Element(8)));
p2.apply(PartitionOp::AssignFresh(Element(1)));
p2.apply(PartitionOp::AssignFresh(Element(2)));
p2.apply(PartitionOp::AssignFresh(Element(3)));
p2.apply(PartitionOp::AssignFresh(Element(4)));
p2.apply(PartitionOp::AssignFresh(Element(8)));
p3.apply(PartitionOp::AssignFresh(Element(6)));
p3.apply(PartitionOp::AssignFresh(Element(7)));
p3.apply(PartitionOp::AssignFresh(Element(0)));
p3.apply(PartitionOp::AssignFresh(Element(1)));
p3.apply(PartitionOp::AssignFresh(Element(8)));
EXPECT_TRUE(Partition::equals(p1, p2));
EXPECT_TRUE(Partition::equals(p2, p3));
EXPECT_TRUE(Partition::equals(p1, p3));
auto expect_join_eq = [&]() {
Partition joined = Partition::join(p1, p2);
EXPECT_TRUE(Partition::equals(p3, joined));
};
auto apply_to_p1_and_p3 = [&](PartitionOp op) {
p1.apply(op);
p3.apply(op);
expect_join_eq();
};
auto apply_to_p2_and_p3 = [&](PartitionOp op) {
p2.apply(op);
p3.apply(op);
expect_join_eq();
};
apply_to_p1_and_p3(PartitionOp::Merge(Element(1), Element(2)));
apply_to_p2_and_p3(PartitionOp::Merge(Element(7), Element(8)));
apply_to_p1_and_p3(PartitionOp::Merge(Element(2), Element(7)));
apply_to_p2_and_p3(PartitionOp::Merge(Element(1), Element(3)));
apply_to_p1_and_p3(PartitionOp::Merge(Element(3), Element(4)));
EXPECT_FALSE(Partition::equals(p1, p2));
EXPECT_FALSE(Partition::equals(p2, p3));
EXPECT_FALSE(Partition::equals(p1, p3));
apply_to_p2_and_p3(PartitionOp::Merge(Element(2), Element(5)));
apply_to_p1_and_p3(PartitionOp::Merge(Element(5), Element(6)));
apply_to_p2_and_p3(PartitionOp::Merge(Element(1), Element(6)));
apply_to_p1_and_p3(PartitionOp::Merge(Element(2), Element(6)));
apply_to_p2_and_p3(PartitionOp::Merge(Element(3), Element(7)));
apply_to_p1_and_p3(PartitionOp::Merge(Element(7), Element(8)));
}
// This test tests the semantics of assignment
TEST(PartitionUtilsTest, TestAssign) {
Partition p1;
Partition p2;
Partition p3;
p1.apply(PartitionOp::AssignFresh(Element(0)));
p1.apply(PartitionOp::AssignFresh(Element(1)));
p1.apply(PartitionOp::AssignFresh(Element(2)));
p1.apply(PartitionOp::AssignFresh(Element(3)));
p2.apply(PartitionOp::AssignFresh(Element(0)));
p2.apply(PartitionOp::AssignFresh(Element(1)));
p2.apply(PartitionOp::AssignFresh(Element(2)));
p2.apply(PartitionOp::AssignFresh(Element(3)));
p3.apply(PartitionOp::AssignFresh(Element(0)));
p3.apply(PartitionOp::AssignFresh(Element(1)));
p3.apply(PartitionOp::AssignFresh(Element(2)));
p3.apply(PartitionOp::AssignFresh(Element(3)));
//expected: p1: ((Element(0)) (Element(1)) (Element(2)) (Element(3))), p2: ((Element(0)) (Element(1)) (Element(2)) (Element(3))), p3: ((Element(0)) (Element(1)) (Element(2)) (Element(3)))
EXPECT_TRUE(Partition::equals(p1, p2));
EXPECT_TRUE(Partition::equals(p2, p3));
EXPECT_TRUE(Partition::equals(p1, p3));
p1.apply(PartitionOp::Assign(Element(0), Element(1)));
p2.apply(PartitionOp::Assign(Element(1), Element(0)));
p3.apply(PartitionOp::Assign(Element(2), Element(1)));
//expected: p1: ((0 1) (Element(2)) (Element(3))), p2: ((0 1) (Element(2)) (Element(3))), p3: ((Element(0)) (1 2) (Element(3)))
EXPECT_TRUE(Partition::equals(p1, p2));
EXPECT_FALSE(Partition::equals(p2, p3));
EXPECT_FALSE(Partition::equals(p1, p3));
p1.apply(PartitionOp::Assign(Element(2), Element(0)));
p2.apply(PartitionOp::Assign(Element(2), Element(1)));
p3.apply(PartitionOp::Assign(Element(0), Element(2)));
//expected: p1: ((0 1 2) (Element(3))), p2: ((0 1 2) (Element(3))), p3: ((0 1 2) (Element(3)))
EXPECT_TRUE(Partition::equals(p1, p2));
EXPECT_TRUE(Partition::equals(p2, p3));
EXPECT_TRUE(Partition::equals(p1, p3));
p1.apply(PartitionOp::Assign(Element(0), Element(3)));
p2.apply(PartitionOp::Assign(Element(1), Element(3)));
p3.apply(PartitionOp::Assign(Element(2), Element(3)));
//expected: p1: ((1 2) (0 3)), p2: ((0 2) (1 3)), p3: ((0 1) (2 3))
EXPECT_FALSE(Partition::equals(p1, p2));
EXPECT_FALSE(Partition::equals(p2, p3));
EXPECT_FALSE(Partition::equals(p1, p3));
p1.apply(PartitionOp::Assign(Element(1), Element(0)));
p2.apply(PartitionOp::Assign(Element(2), Element(1)));
p3.apply(PartitionOp::Assign(Element(0), Element(2)));
//expected: p1: ((Element(2)) (0 1 3)), p2: ((Element(0)) (1 2 3)), p3: ((Element(1)) (0 2 3))
EXPECT_FALSE(Partition::equals(p1, p2));
EXPECT_FALSE(Partition::equals(p2, p3));
EXPECT_FALSE(Partition::equals(p1, p3));
p1.apply(PartitionOp::Assign(Element(2), Element(3)));
p2.apply(PartitionOp::Assign(Element(0), Element(3)));
p3.apply(PartitionOp::Assign(Element(1), Element(3)));
//expected: p1: ((0 1 2 3)), p2: ((0 1 2 3)), p3: ((0 1 2 3))
EXPECT_TRUE(Partition::equals(p1, p2));
EXPECT_TRUE(Partition::equals(p2, p3));
EXPECT_TRUE(Partition::equals(p1, p3));
}
// This test tests that consumption consumes entire regions as expected
TEST(PartitionUtilsTest, TestConsumeAndRequire) {
Partition p;
p.apply(PartitionOp::AssignFresh(Element(0)));
p.apply(PartitionOp::AssignFresh(Element(1)));
p.apply(PartitionOp::AssignFresh(Element(2)));
p.apply(PartitionOp::AssignFresh(Element(3)));
p.apply(PartitionOp::AssignFresh(Element(4)));
p.apply(PartitionOp::AssignFresh(Element(5)));
p.apply(PartitionOp::AssignFresh(Element(6)));
p.apply(PartitionOp::AssignFresh(Element(7)));
p.apply(PartitionOp::AssignFresh(Element(8)));
p.apply(PartitionOp::AssignFresh(Element(9)));
p.apply(PartitionOp::AssignFresh(Element(10)));
p.apply(PartitionOp::AssignFresh(Element(11)));
p.apply(PartitionOp::Assign(Element(1), Element(0)));
p.apply(PartitionOp::Assign(Element(2), Element(1)));
p.apply(PartitionOp::Assign(Element(4), Element(3)));
p.apply(PartitionOp::Assign(Element(5), Element(4)));
p.apply(PartitionOp::Assign(Element(7), Element(6)));
p.apply(PartitionOp::Assign(Element(9), Element(8)));
//expected: p: ((0 1 2) (3 4 5) (6 7) (8 9) (Element(10)) (Element(11)))
p.apply(PartitionOp::Consume(Element(2)));
p.apply(PartitionOp::Consume(Element(7)));
p.apply(PartitionOp::Consume(Element(10)));
// expected: p: ({0 1 2 6 7 10} (3 4 5) (8 9) (Element(11)))
auto never_called = [](const PartitionOp &, unsigned) {
EXPECT_TRUE(false);
};
int times_called = 0;
int expected_times_called = 0;
auto increment_times_called = [&](const PartitionOp &, unsigned) {
times_called++;
};
auto get_increment_times_called = [&]() {
expected_times_called++;
return increment_times_called;
};
p.apply(PartitionOp::Require(Element(0)), get_increment_times_called());
p.apply(PartitionOp::Require(Element(1)), get_increment_times_called());
p.apply(PartitionOp::Require(Element(2)), get_increment_times_called());
p.apply(PartitionOp::Require(Element(3)), never_called);
p.apply(PartitionOp::Require(Element(4)), never_called);
p.apply(PartitionOp::Require(Element(5)), never_called);
p.apply(PartitionOp::Require(Element(6)), get_increment_times_called());
p.apply(PartitionOp::Require(Element(7)), get_increment_times_called());
p.apply(PartitionOp::Require(Element(8)), never_called);
p.apply(PartitionOp::Require(Element(9)), never_called);
p.apply(PartitionOp::Require(Element(10)), get_increment_times_called());
p.apply(PartitionOp::Require(Element(11)), never_called);
EXPECT_TRUE(times_called == expected_times_called);
}
// This test tests that the copy constructor is usable to create fresh
// copies of partitions
TEST(PartitionUtilsTest, TestCopyConstructor) {
Partition p1;
p1.apply(PartitionOp::AssignFresh(Element(0)));
Partition p2 = p1;
p1.apply(PartitionOp::Consume(Element(0)));
bool failure = false;
p1.apply(PartitionOp::Require(Element(0)), [&](const PartitionOp &, unsigned) {
failure = true;
});
EXPECT_TRUE(failure);
p2.apply(PartitionOp::Require(Element(0)), [](const PartitionOp &, unsigned) {
EXPECT_TRUE(false);
});
}