Mercurial > hg > CbC > CbC_llvm
view llvm/unittests/CodeGen/SchedBoundary.cpp @ 252:1f2b6ac9f198 llvm-original
LLVM16-1
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 18 Aug 2023 09:04:13 +0900 |
parents | |
children |
line wrap: on
line source
#include "llvm/CodeGen/MachineScheduler.h" #include "gtest/gtest.h" using namespace llvm; #ifndef NDEBUG TEST(ResourceSegmentsDeath, OverwriteOnRight) { auto X = ResourceSegments({{10, 20}}); EXPECT_DEATH(X.add({15, 30}), "A resource is being overwritten"); } TEST(ResourceSegmentsDeath, OverwriteOnLeft) { auto X = ResourceSegments({{10, 20}}); EXPECT_DEATH(X.add({5, 11}), "A resource is being overwritten"); ; } TEST(ResourceSegmentsDeath, FullOverwrite) { auto X = ResourceSegments({{10, 20}}); EXPECT_DEATH(X.add({15, 18}), "A resource is being overwritten"); } TEST(ResourceSegmentsDeath, ZeroSizeIntervalsNotAllowed) { auto X = ResourceSegments({{10, 20}}); EXPECT_DEATH(X.add({20, 30}, 0), "0-size interval history has no use."); } #endif // NDEBUG TEST(ResourceSegments, ConsecutiveLeftNoOverlap) { auto X = ResourceSegments({{10, 20}}); X.add({7, 9}); EXPECT_EQ(X, ResourceSegments({{7, 9}, {10, 20}})); } TEST(ResourceSegments, ConsecutiveLeftWithOverlap) { auto X = ResourceSegments({{10, 20}}); X.add({7, 10}); EXPECT_EQ(X, ResourceSegments({{7, 20}})); } TEST(ResourceSegments, ConsecutiveRightNoOverlap) { auto X = ResourceSegments({{10, 20}}); X.add({21, 22}); EXPECT_EQ(X, ResourceSegments({{10, 20}, {21, 22}})); } TEST(ResourceSegments, ConsecutiveRightWithOverlap) { auto X = ResourceSegments({{10, 20}}); X.add({20, 22}); EXPECT_EQ(X, ResourceSegments({{10, 22}})); } TEST(ResourceSegments, Disjoint) { auto X = ResourceSegments({{10, 20}}); X.add({22, 23}); EXPECT_EQ(X, ResourceSegments({{10, 20}, {22, 23}})); } TEST(ResourceSegments, SortAfterAdd) { auto X = ResourceSegments({{10, 20}, {3, 4}}); X.add({6, 8}); EXPECT_EQ(X, ResourceSegments({{3, 4}, {6, 8}, {10, 20}})); } TEST(ResourceSegments, AddWithCutOff) { auto X = ResourceSegments({{1, 2}, {3, 4}}); X.add({6, 8}, 2); EXPECT_EQ(X, ResourceSegments({{3, 4}, {6, 8}})); } TEST(ResourceSegments, add_01) { auto X = ResourceSegments({{10, 20}, {30, 40}}); X.add({21, 29}); EXPECT_EQ(X, ResourceSegments({{10, 20}, {21, 29}, {30, 40}})); } TEST(ResourceSegments, add_02) { auto X = ResourceSegments({{10, 20}, {30, 40}}); X.add({22, 29}); EXPECT_EQ(X, ResourceSegments({{10, 20}, {22, 29}, {30, 40}})); X.add({29, 30}); EXPECT_EQ(X, ResourceSegments({{10, 20}, {22, 40}})); } #ifndef NDEBUG TEST(ResourceSegmentsDeath, add_empty) { auto X = ResourceSegments({{10, 20}, {30, 40}}); EXPECT_DEATH(X.add({22, 22}), "Cannot add empty resource usage"); } #endif TEST(ResourceSegments, sort_two) { EXPECT_EQ(ResourceSegments({{30, 40}, {10, 28}}), ResourceSegments({{10, 28}, {30, 40}})); } TEST(ResourceSegments, sort_three) { EXPECT_EQ(ResourceSegments({{30, 40}, {71, 200}, {10, 29}}), ResourceSegments({{10, 29}, {30, 40}, {71, 200}})); } TEST(ResourceSegments, merge_two) { EXPECT_EQ(ResourceSegments({{10, 33}, {30, 40}}), ResourceSegments({{10, 40}})); EXPECT_EQ(ResourceSegments({{10, 30}, {30, 40}}), ResourceSegments({{10, 40}})); // Cycle 29 is resource free, so the interval is disjoint. EXPECT_EQ(ResourceSegments({{10, 29}, {30, 40}}), ResourceSegments({{10, 29}, {30, 40}})); } TEST(ResourceSegments, merge_three) { EXPECT_EQ(ResourceSegments({{10, 29}, {30, 40}, {71, 200}}), ResourceSegments({{10, 29}, {30, 40}, {71, 200}})); EXPECT_EQ(ResourceSegments({{10, 29}, {30, 40}, {41, 200}}), ResourceSegments({{10, 29}, {30, 40}, {41, 200}})); EXPECT_EQ(ResourceSegments({{10, 30}, {30, 40}, {40, 200}}), ResourceSegments({{10, 200}})); EXPECT_EQ(ResourceSegments({{10, 28}, {30, 71}, {71, 200}}), ResourceSegments({{10, 28}, {30, 200}})); } //////////////////////////////////////////////////////////////////////////////// // Intersection TEST(ResourceSegments, intersects) { // no intersect EXPECT_FALSE(ResourceSegments::intersects({0, 1}, {3, 4})); EXPECT_FALSE(ResourceSegments::intersects({3, 4}, {0, 1})); EXPECT_FALSE(ResourceSegments::intersects({0, 3}, {3, 4})); EXPECT_FALSE(ResourceSegments::intersects({3, 4}, {0, 3})); // Share one boundary EXPECT_TRUE(ResourceSegments::intersects({5, 6}, {5, 10})); EXPECT_TRUE(ResourceSegments::intersects({5, 10}, {5, 6})); // full intersect EXPECT_TRUE(ResourceSegments::intersects({1, 2}, {0, 3})); EXPECT_TRUE(ResourceSegments::intersects({1, 2}, {0, 2})); EXPECT_TRUE(ResourceSegments::intersects({0, 3}, {1, 2})); EXPECT_TRUE(ResourceSegments::intersects({0, 2}, {1, 2})); // right intersect EXPECT_TRUE(ResourceSegments::intersects({2, 4}, {0, 3})); EXPECT_TRUE(ResourceSegments::intersects({0, 3}, {2, 4})); // left intersect EXPECT_TRUE(ResourceSegments::intersects({2, 4}, {3, 5})); EXPECT_TRUE(ResourceSegments::intersects({3, 5}, {2, 4})); } //////////////////////////////////////////////////////////////////////////////// // TOP-DOWN getFirstAvailableAt TEST(ResourceSegments, getFirstAvailableAtFromTop_oneCycle) { auto X = ResourceSegments({{2, 5}}); // 0 1 2 3 4 5 6 7 // Res X X X // ...X... EXPECT_EQ(X.getFirstAvailableAtFromTop(0, 0, 1), 0U); EXPECT_EQ(X.getFirstAvailableAtFromTop(1, 0, 1), 1U); // Skip to five when hitting cycle 2 EXPECT_EQ(X.getFirstAvailableAtFromTop(2, 0, 1), 5U); } TEST(ResourceSegments, getFirstAvailableAtFromTop_twoCycles) { auto X = ResourceSegments({{4, 5}}); // 0 1 2 3 4 5 6 7 // Res X // ...X X.... EXPECT_EQ(X.getFirstAvailableAtFromTop(0, 0, 2), 0U); EXPECT_EQ(X.getFirstAvailableAtFromTop(1, 0, 2), 1U); EXPECT_EQ(X.getFirstAvailableAtFromTop(2, 0, 2), 2U); // Skip to cycle 5 EXPECT_EQ(X.getFirstAvailableAtFromTop(3, 0, 2), 5U); } TEST(ResourceSegments, getFirstAvailableAtFromTop_twoCycles_Shifted) { auto X = ResourceSegments({{4, 5}}); // 0 1 2 3 4 5 6 7 // Res X // ...c X X... EXPECT_EQ(X.getFirstAvailableAtFromTop(0, 1, 3), 0U); EXPECT_EQ(X.getFirstAvailableAtFromTop(1, 1, 3), 1U); // Skip to cycle 4 EXPECT_EQ(X.getFirstAvailableAtFromTop(2, 1, 3), 4U); // Stay con cycle 4 // 0 1 2 3 4 5 6 7 // Res X // ...c X X... EXPECT_EQ(X.getFirstAvailableAtFromTop(3, 1, 3), 4U); // EXPECT_EQ(X.getFirstAvailableAtFromTop(4, 1, 3), 4U); EXPECT_EQ(X.getFirstAvailableAtFromTop(5, 1, 3), 5U); } TEST(ResourceSegments, getFirstAvailableAtFromTop_twoCycles_Shifted_withGap) { auto X = ResourceSegments({{4, 5}, {7, 9}}); // 0 1 2 3 4 5 6 7 8 9 // Res X X X // c X X EXPECT_EQ(X.getFirstAvailableAtFromTop(1, 1, 3), 1U); // 0 1 2 3 4 5 6 7 8 9 // Res X X X // c X X --> moves to 4 EXPECT_EQ(X.getFirstAvailableAtFromTop(2, 1, 3), 4U); // 0 1 2 3 4 5 6 7 8 9 // Res X X X // c X X --> moves to 4 EXPECT_EQ(X.getFirstAvailableAtFromTop(3, 1, 3), 4U); // 0 1 2 3 4 5 6 7 8 9 // Res X X X // c X X --> stays on 4 EXPECT_EQ(X.getFirstAvailableAtFromTop(4, 1, 3), 4U); // 0 1 2 3 4 5 6 7 8 9 // Res X X X // c X X --> skips to 8 EXPECT_EQ(X.getFirstAvailableAtFromTop(5, 1, 3), 8U); } TEST(ResourceSegments, getFirstAvailableAtFromTop_basic) { auto X = ResourceSegments({{5, 10}, {30, 40}}); EXPECT_EQ(X.getFirstAvailableAtFromTop(0, 3, 4), 0U); EXPECT_EQ(X.getFirstAvailableAtFromTop(1, 3, 4), 1U); EXPECT_EQ(X.getFirstAvailableAtFromTop(2, 3, 4), 7U); EXPECT_EQ(X.getFirstAvailableAtFromTop(3, 3, 4), 7U); EXPECT_EQ(X.getFirstAvailableAtFromTop(4, 3, 4), 7U); EXPECT_EQ(X.getFirstAvailableAtFromTop(5, 3, 4), 7U); EXPECT_EQ(X.getFirstAvailableAtFromTop(6, 3, 4), 7U); EXPECT_EQ(X.getFirstAvailableAtFromTop(7, 3, 4), 7U); // Check the empty range between the two intervals of X. EXPECT_EQ(X.getFirstAvailableAtFromTop(15, 3, 4), 15U); // Overlap the second interval. EXPECT_EQ(X.getFirstAvailableAtFromTop(28, 3, 4), 37U); } TEST(ResourceSegments, getFirstAvailableAtFromTop_advanced) { auto X = ResourceSegments({{3, 6}, {7, 9}, {11, 14}, {30, 33}}); EXPECT_EQ(X.getFirstAvailableAtFromTop(2, 4, 5), 2U); EXPECT_EQ(X.getFirstAvailableAtFromTop(2, 3, 4), 3U); // Can schedule at 7U because the interval [14, 19[ does not // overlap any of the intervals in X. EXPECT_EQ(X.getFirstAvailableAtFromTop(1, 7, 12), 7U); } //////////////////////////////////////////////////////////////////////////////// // BOTTOM-UP getFirstAvailableAt TEST(ResourceSegments, getFirstAvailableAtFromBottom) { // Scheduling cycles move to the left... // // 41 40 39 ... 31 30 29 ... 21 20 19 ... 11 10 9 8 7 6 ... 1 0 // Res X X X X X X X X // X X X X X X // Time (relative to instruction execution) 0 1 2 3 4 5 auto X = ResourceSegments({{10, 20}, {30, 40}}); // .. but time (instruction cycle) moves to the right. Therefore, it // is always possible to llocate a resource to the right of 0 if 0 // is not taken, because the right side of the scheduling cycles is // empty. EXPECT_EQ(X.getFirstAvailableAtFromBottom(0, 0, 1), 0U); EXPECT_EQ(X.getFirstAvailableAtFromBottom(0, 0, 9), 0U); EXPECT_EQ(X.getFirstAvailableAtFromBottom(0, 0, 10), 0U); EXPECT_EQ(X.getFirstAvailableAtFromBottom(0, 0, 20), 0U); EXPECT_EQ(X.getFirstAvailableAtFromBottom(0, 0, 21), 0U); EXPECT_EQ(X.getFirstAvailableAtFromBottom(0, 0, 22), 0U); EXPECT_EQ(X.getFirstAvailableAtFromBottom(0, 0, 29), 0U); EXPECT_EQ(X.getFirstAvailableAtFromBottom(0, 0, 30), 0U); } TEST(ResourceSegments, getFirstAvailableAtFromBottom_01) { auto X = ResourceSegments({{3, 7}}); // 10 9 8 7 6 5 4 3 2 1 0 // X X X X // ...X... <- one cycle resource placement EXPECT_EQ(X.getFirstAvailableAtFromBottom(0, 0, 1), 0U); EXPECT_EQ(X.getFirstAvailableAtFromBottom(1, 0, 1), 1U); EXPECT_EQ(X.getFirstAvailableAtFromBottom(2, 0, 1), 2U); // Skip to 7 EXPECT_EQ(X.getFirstAvailableAtFromBottom(3, 0, 1), 7U); } TEST(ResourceSegments, getFirstAvailableAtFromBottom_02) { auto X = ResourceSegments({{3, 7}}); // 10 9 8 7 6 5 4 3 2 1 0 // X X X X // ...X X... <- two cycles resource placement EXPECT_EQ(X.getFirstAvailableAtFromBottom(0, 0, 2), 0U); EXPECT_EQ(X.getFirstAvailableAtFromBottom(1, 0, 2), 1U); EXPECT_EQ(X.getFirstAvailableAtFromBottom(2, 0, 2), 2U); // skip to 8 EXPECT_EQ(X.getFirstAvailableAtFromBottom(3, 0, 2), 8U); } TEST(ResourceSegments, getFirstAvailableAtFromBottom_02_shifted) { auto X = ResourceSegments({{3, 7}}); // 10 9 8 7 6 5 4 3 2 1 0 // X X X X // c X X <- two cycles resource placement but shifted by 1 // 0 1 2 <- cycles relative to the execution of the // instruction EXPECT_EQ(X.getFirstAvailableAtFromBottom(0, 1, 3), 0U); EXPECT_EQ(X.getFirstAvailableAtFromBottom(1, 1, 3), 1U); EXPECT_EQ(X.getFirstAvailableAtFromBottom(2, 1, 3), 2U); EXPECT_EQ(X.getFirstAvailableAtFromBottom(3, 1, 3), 3U); // 10 9 8 7 6 5 4 3 2 1 0 // X X X X // c X X -> skip to 9 // 0 1 2 EXPECT_EQ(X.getFirstAvailableAtFromBottom(4, 1, 3), 9U); EXPECT_EQ(X.getFirstAvailableAtFromBottom(5, 1, 3), 9U); EXPECT_EQ(X.getFirstAvailableAtFromBottom(6, 1, 3), 9U); EXPECT_EQ(X.getFirstAvailableAtFromBottom(7, 1, 3), 9U); // 10 9 8 7 6 5 4 3 2 1 0 // X X X X // c X X <- skip to 9 // 0 1 2 EXPECT_EQ(X.getFirstAvailableAtFromBottom(8, 1, 3), 9U); // 10 9 8 7 6 5 4 3 2 1 0 // X X X X // c X X // 0 1 2 EXPECT_EQ(X.getFirstAvailableAtFromBottom(9, 1, 3), 9U); // 10 9 8 7 6 5 4 3 2 1 0 // X X X X // c X X // 0 1 2 EXPECT_EQ(X.getFirstAvailableAtFromBottom(10, 1, 3), 10U); } TEST(ResourceSegments, getFirstAvailableAtFromBottom_03) { auto X = ResourceSegments({{1, 2}, {3, 7}}); // 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 // X X X X X // X EXPECT_EQ(X.getFirstAvailableAtFromBottom(0, 0, 1), 0U); // 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 // X X X X X // X EXPECT_EQ(X.getFirstAvailableAtFromBottom(1, 0, 1), 2U); // 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 // X X X X X // X EXPECT_EQ(X.getFirstAvailableAtFromBottom(2, 0, 1), 2U); // 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 // X X X X X // X X X X X EXPECT_EQ(X.getFirstAvailableAtFromBottom(2, 0, 5), 11U); EXPECT_EQ(X.getFirstAvailableAtFromBottom(3, 0, 5), 11U); EXPECT_EQ(X.getFirstAvailableAtFromBottom(5, 0, 5), 11U); EXPECT_EQ(X.getFirstAvailableAtFromBottom(11, 0, 5), 11U); // 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 // X X X X X // X X X X X EXPECT_EQ(X.getFirstAvailableAtFromBottom(12, 0, 5), 12U); } TEST(ResourceSegments, getFirstAvailableAtFromBottom_03_shifted) { // 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 -1 -2 -3 // X X X X X X X X auto X = ResourceSegments({{-3, -1}, {1, 2}, {3, 7}, {9, 10}}); EXPECT_EQ(X.getFirstAvailableAtFromBottom(0, 1, 2), 0U); EXPECT_EQ(X.getFirstAvailableAtFromBottom(0, 0, 2), 0U); // 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 -1 -2 -3 // X X X X X X X X // X X X -> skip to cycle 12 EXPECT_EQ(X.getFirstAvailableAtFromBottom(0, 0, 3), 12U); // 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 -1 -2 -3 // X X X X X X X X // X X EXPECT_EQ(X.getFirstAvailableAtFromBottom(0, 1, 3), 1U); EXPECT_EQ(X.getFirstAvailableAtFromBottom(0, 1, 4), 13U); EXPECT_EQ(X.getFirstAvailableAtFromBottom(12, 1, 4), 13U); // 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 -1 -2 -3 // X X X X X X X X // c X X X EXPECT_EQ(X.getFirstAvailableAtFromBottom(13, 1, 4), 13U); // 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 -1 -2 -3 // X X X X X X X X // X X EXPECT_EQ(X.getFirstAvailableAtFromBottom(1, 1, 3), 1U); // 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 -1 -2 -3 // X X X X X X X X // C X X 0 -> skip to cycle 9 EXPECT_EQ(X.getFirstAvailableAtFromBottom(2, 1, 3), 9U); // 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 -1 -2 -3 // X X X X X X X X // C C X X X X X -> skip to cycle 16 EXPECT_EQ(X.getFirstAvailableAtFromBottom(3, 2, 7), 16U); } TEST(ResourceSegments, getFirstAvailableAtFromBottom_empty) { // Empty resource usage can accept schediling at any cycle auto X = ResourceSegments(); EXPECT_EQ(X.getFirstAvailableAtFromBottom(0, 0, 1), 0U); EXPECT_EQ(X.getFirstAvailableAtFromBottom(17, 1, 22), 17U); }