mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
250 lines
9.1 KiB
C++
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);
|
|
});
|
|
}
|