Commit 36003d07 authored by titzer's avatar titzer Committed by Commit bot

[turbofan] Improve loop analysis to handle more than 32 loops.

R=mstarzinger@chromium.org
BUG=

Review URL: https://codereview.chromium.org/855653002

Cr-Commit-Position: refs/heads/master@{#26140}
parent 327d4a7c
This diff is collapsed.
...@@ -25,7 +25,7 @@ class LoopTree : public ZoneObject { ...@@ -25,7 +25,7 @@ class LoopTree : public ZoneObject {
: zone_(zone), : zone_(zone),
outer_loops_(zone), outer_loops_(zone),
all_loops_(zone), all_loops_(zone),
node_to_loop_num_(static_cast<int>(num_nodes), 0, zone), node_to_loop_num_(static_cast<int>(num_nodes), -1, zone),
loop_nodes_(zone) {} loop_nodes_(zone) {}
// Represents a loop in the tree of loops, including the header nodes, // Represents a loop in the tree of loops, including the header nodes,
...@@ -61,7 +61,7 @@ class LoopTree : public ZoneObject { ...@@ -61,7 +61,7 @@ class LoopTree : public ZoneObject {
Loop* ContainingLoop(Node* node) { Loop* ContainingLoop(Node* node) {
if (node->id() >= static_cast<int>(node_to_loop_num_.size())) if (node->id() >= static_cast<int>(node_to_loop_num_.size()))
return nullptr; return nullptr;
uint8_t num = node_to_loop_num_[node->id()]; int num = node_to_loop_num_[node->id()];
return num > 0 ? &all_loops_[num - 1] : nullptr; return num > 0 ? &all_loops_[num - 1] : nullptr;
} }
...@@ -116,8 +116,7 @@ class LoopTree : public ZoneObject { ...@@ -116,8 +116,7 @@ class LoopTree : public ZoneObject {
Zone* zone_; Zone* zone_;
ZoneVector<Loop*> outer_loops_; ZoneVector<Loop*> outer_loops_;
ZoneVector<Loop> all_loops_; ZoneVector<Loop> all_loops_;
// TODO(titzer): lift loop count restriction. ZoneVector<int> node_to_loop_num_;
ZoneVector<uint8_t> node_to_loop_num_;
ZoneVector<Node*> loop_nodes_; ZoneVector<Node*> loop_nodes_;
}; };
......
...@@ -146,6 +146,7 @@ class LoopFinderTester : HandleAndZoneScope { ...@@ -146,6 +146,7 @@ class LoopFinderTester : HandleAndZoneScope {
} }
CHECK_EQ(body_count, static_cast<int>(loop->BodySize())); 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++) { for (int i = 0; i < body_count; i++) {
// Each body node should be contained in the loop. // Each body node should be contained in the loop.
CHECK(tree->Contains(loop, body[i])); CHECK(tree->Contains(loop, body[i]));
...@@ -154,7 +155,6 @@ class LoopFinderTester : HandleAndZoneScope { ...@@ -154,7 +155,6 @@ class LoopFinderTester : HandleAndZoneScope {
} }
void CheckRangeContains(NodeRange range, Node* node) { void CheckRangeContains(NodeRange range, Node* node) {
// O(n) ftw.
CHECK_NE(range.end(), std::find(range.begin(), range.end(), node)); CHECK_NE(range.end(), std::find(range.begin(), range.end(), node));
} }
...@@ -178,6 +178,8 @@ class LoopFinderTester : HandleAndZoneScope { ...@@ -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 ...@@ -839,7 +841,7 @@ void RunEdgeMatrix3(int c1a, int c1b, int c1c, // line break
// Runs all combinations with a fixed {i}. // 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 a = 0; a < 1; a++) {
for (int b = 0; b < 1; b++) { for (int b = 0; b < 1; b++) {
for (int c = 0; c < 4; c++) { for (int c = 0; c < 4; c++) {
...@@ -877,3 +879,99 @@ TEST(LaEdgeMatrix3_4) { RunEdgeMatrix3_i(4); } ...@@ -877,3 +879,99 @@ TEST(LaEdgeMatrix3_4) { RunEdgeMatrix3_i(4); }
TEST(LaEdgeMatrix3_5) { RunEdgeMatrix3_i(5); } 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); }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment