Index: test/cctest/compiler/test-loop-analysis.cc |
diff --git a/test/cctest/compiler/test-loop-analysis.cc b/test/cctest/compiler/test-loop-analysis.cc |
index 8ce1e803539119ff6beed99fad285c2c552dc4ab..3a8614412d3f31fe4617a9cf99d83eeb2fb04d95 100644 |
--- a/test/cctest/compiler/test-loop-analysis.cc |
+++ b/test/cctest/compiler/test-loop-analysis.cc |
@@ -146,6 +146,7 @@ class LoopFinderTester : HandleAndZoneScope { |
} |
CHECK_EQ(body_count, static_cast<int>(loop->BodySize())); |
+ // TODO(turbofan): O(n^2) set equivalence in this test. |
for (int i = 0; i < body_count; i++) { |
// Each body node should be contained in the loop. |
CHECK(tree->Contains(loop, body[i])); |
@@ -154,7 +155,6 @@ class LoopFinderTester : HandleAndZoneScope { |
} |
void CheckRangeContains(NodeRange range, Node* node) { |
- // O(n) ftw. |
CHECK_NE(range.end(), std::find(range.begin(), range.end(), node)); |
} |
@@ -178,6 +178,8 @@ class LoopFinderTester : HandleAndZoneScope { |
} |
} |
} |
+ |
+ Zone* zone() { return main_zone(); } |
}; |
@@ -839,7 +841,7 @@ void RunEdgeMatrix3(int c1a, int c1b, int c1c, // line break |
// Runs all combinations with a fixed {i}. |
-void RunEdgeMatrix3_i(int i) { |
+static void RunEdgeMatrix3_i(int i) { |
for (int a = 0; a < 1; a++) { |
for (int b = 0; b < 1; b++) { |
for (int c = 0; c < 4; c++) { |
@@ -877,3 +879,99 @@ TEST(LaEdgeMatrix3_4) { RunEdgeMatrix3_i(4); } |
TEST(LaEdgeMatrix3_5) { RunEdgeMatrix3_i(5); } |
+ |
+ |
+static void RunManyChainedLoops_i(int count) { |
+ LoopFinderTester t; |
+ Node** nodes = t.zone()->NewArray<Node*>(count * 4); |
+ Node* k11 = t.jsgraph.Int32Constant(11); |
+ Node* k12 = t.jsgraph.Int32Constant(12); |
+ Node* last = t.start; |
+ |
+ // Build loops. |
+ for (int i = 0; i < count; i++) { |
+ Node* loop = t.graph.NewNode(t.common.Loop(2), last, t.start); |
+ Node* phi = t.graph.NewNode(t.common.Phi(kMachInt32, 2), k11, k12, loop); |
+ Node* branch = t.graph.NewNode(t.common.Branch(), phi, loop); |
+ Node* if_true = t.graph.NewNode(t.common.IfTrue(), branch); |
+ Node* exit = t.graph.NewNode(t.common.IfFalse(), branch); |
+ loop->ReplaceInput(1, if_true); |
+ |
+ nodes[i * 4 + 0] = loop; |
+ nodes[i * 4 + 1] = phi; |
+ nodes[i * 4 + 2] = branch; |
+ nodes[i * 4 + 3] = if_true; |
+ |
+ last = exit; |
+ } |
+ |
+ Node* ret = t.graph.NewNode(t.common.Return(), t.p0, t.start, last); |
+ t.graph.SetEnd(ret); |
+ |
+ // Verify loops. |
+ for (int i = 0; i < count; i++) { |
+ t.CheckLoop(nodes + i * 4, 2, nodes + i * 4 + 2, 2); |
+ } |
+} |
+ |
+ |
+static void RunManyNestedLoops_i(int count) { |
+ LoopFinderTester t; |
+ Node** nodes = t.zone()->NewArray<Node*>(count * 5); |
+ Node* k11 = t.jsgraph.Int32Constant(11); |
+ Node* k12 = t.jsgraph.Int32Constant(12); |
+ Node* outer = nullptr; |
+ Node* entry = t.start; |
+ |
+ // Build loops. |
+ for (int i = 0; i < count; i++) { |
+ Node* loop = t.graph.NewNode(t.common.Loop(2), entry, t.start); |
+ Node* phi = t.graph.NewNode(t.common.Phi(kMachInt32, 2), k11, k12, loop); |
+ Node* branch = t.graph.NewNode(t.common.Branch(), phi, loop); |
+ Node* if_true = t.graph.NewNode(t.common.IfTrue(), branch); |
+ Node* exit = t.graph.NewNode(t.common.IfFalse(), branch); |
+ |
+ nodes[i * 5 + 0] = exit; // outside |
+ nodes[i * 5 + 1] = loop; // header |
+ nodes[i * 5 + 2] = phi; // header |
+ nodes[i * 5 + 3] = branch; // body |
+ nodes[i * 5 + 4] = if_true; // body |
+ |
+ if (outer != nullptr) { |
+ // inner loop. |
+ outer->ReplaceInput(1, exit); |
+ } else { |
+ // outer loop. |
+ Node* ret = t.graph.NewNode(t.common.Return(), t.p0, t.start, exit); |
+ t.graph.SetEnd(ret); |
+ } |
+ outer = loop; |
+ entry = if_true; |
+ } |
+ outer->ReplaceInput(1, entry); // innermost loop. |
+ |
+ // Verify loops. |
+ for (int i = 0; i < count; i++) { |
+ int k = i * 5; |
+ t.CheckLoop(nodes + k + 1, 2, nodes + k + 3, count * 5 - k - 3); |
+ } |
+} |
+ |
+ |
+TEST(LaManyChained_30) { RunManyChainedLoops_i(30); } |
+TEST(LaManyChained_31) { RunManyChainedLoops_i(31); } |
+TEST(LaManyChained_32) { RunManyChainedLoops_i(32); } |
+TEST(LaManyChained_33) { RunManyChainedLoops_i(33); } |
+TEST(LaManyChained_34) { RunManyChainedLoops_i(34); } |
+TEST(LaManyChained_62) { RunManyChainedLoops_i(62); } |
+TEST(LaManyChained_63) { RunManyChainedLoops_i(63); } |
+TEST(LaManyChained_64) { RunManyChainedLoops_i(64); } |
+ |
+TEST(LaManyNested_30) { RunManyNestedLoops_i(30); } |
+TEST(LaManyNested_31) { RunManyNestedLoops_i(31); } |
+TEST(LaManyNested_32) { RunManyNestedLoops_i(32); } |
+TEST(LaManyNested_33) { RunManyNestedLoops_i(33); } |
+TEST(LaManyNested_34) { RunManyNestedLoops_i(34); } |
+TEST(LaManyNested_62) { RunManyNestedLoops_i(62); } |
+TEST(LaManyNested_63) { RunManyNestedLoops_i(63); } |
+TEST(LaManyNested_64) { RunManyNestedLoops_i(64); } |