OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/compiler/access-builder.h" | 7 #include "src/compiler/access-builder.h" |
8 #include "src/compiler/common-operator.h" | 8 #include "src/compiler/common-operator.h" |
9 #include "src/compiler/graph.h" | 9 #include "src/compiler/graph.h" |
10 #include "src/compiler/graph-visualizer.h" | 10 #include "src/compiler/graph-visualizer.h" |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
139 CHECK_NE(NULL, loop); | 139 CHECK_NE(NULL, loop); |
140 | 140 |
141 CHECK(header_count == static_cast<int>(loop->HeaderSize())); | 141 CHECK(header_count == static_cast<int>(loop->HeaderSize())); |
142 for (int i = 0; i < header_count; i++) { | 142 for (int i = 0; i < header_count; i++) { |
143 // Each header node should be in the loop. | 143 // Each header node should be in the loop. |
144 CHECK_EQ(loop, tree->ContainingLoop(header[i])); | 144 CHECK_EQ(loop, tree->ContainingLoop(header[i])); |
145 CheckRangeContains(tree->HeaderNodes(loop), header[i]); | 145 CheckRangeContains(tree->HeaderNodes(loop), header[i]); |
146 } | 146 } |
147 | 147 |
148 CHECK_EQ(body_count, static_cast<int>(loop->BodySize())); | 148 CHECK_EQ(body_count, static_cast<int>(loop->BodySize())); |
| 149 // TODO(turbofan): O(n^2) set equivalence in this test. |
149 for (int i = 0; i < body_count; i++) { | 150 for (int i = 0; i < body_count; i++) { |
150 // Each body node should be contained in the loop. | 151 // Each body node should be contained in the loop. |
151 CHECK(tree->Contains(loop, body[i])); | 152 CHECK(tree->Contains(loop, body[i])); |
152 CheckRangeContains(tree->BodyNodes(loop), body[i]); | 153 CheckRangeContains(tree->BodyNodes(loop), body[i]); |
153 } | 154 } |
154 } | 155 } |
155 | 156 |
156 void CheckRangeContains(NodeRange range, Node* node) { | 157 void CheckRangeContains(NodeRange range, Node* node) { |
157 // O(n) ftw. | |
158 CHECK_NE(range.end(), std::find(range.begin(), range.end(), node)); | 158 CHECK_NE(range.end(), std::find(range.begin(), range.end(), node)); |
159 } | 159 } |
160 | 160 |
161 void CheckNestedLoops(Node** chain, int chain_count) { | 161 void CheckNestedLoops(Node** chain, int chain_count) { |
162 LoopTree* tree = GetLoopTree(); | 162 LoopTree* tree = GetLoopTree(); |
163 for (int i = 0; i < chain_count; i++) { | 163 for (int i = 0; i < chain_count; i++) { |
164 Node* header = chain[i]; | 164 Node* header = chain[i]; |
165 // Each header should be in a loop. | 165 // Each header should be in a loop. |
166 LoopTree::Loop* loop = tree->ContainingLoop(header); | 166 LoopTree::Loop* loop = tree->ContainingLoop(header); |
167 CHECK_NE(NULL, loop); | 167 CHECK_NE(NULL, loop); |
168 // Check parentage. | 168 // Check parentage. |
169 LoopTree::Loop* parent = | 169 LoopTree::Loop* parent = |
170 i == 0 ? NULL : tree->ContainingLoop(chain[i - 1]); | 170 i == 0 ? NULL : tree->ContainingLoop(chain[i - 1]); |
171 CHECK_EQ(parent, loop->parent()); | 171 CHECK_EQ(parent, loop->parent()); |
172 for (int j = i - 1; j >= 0; j--) { | 172 for (int j = i - 1; j >= 0; j--) { |
173 // This loop should be nested inside all the outer loops. | 173 // This loop should be nested inside all the outer loops. |
174 Node* outer_header = chain[j]; | 174 Node* outer_header = chain[j]; |
175 LoopTree::Loop* outer = tree->ContainingLoop(outer_header); | 175 LoopTree::Loop* outer = tree->ContainingLoop(outer_header); |
176 CHECK(tree->Contains(outer, header)); | 176 CHECK(tree->Contains(outer, header)); |
177 CHECK(!tree->Contains(loop, outer_header)); | 177 CHECK(!tree->Contains(loop, outer_header)); |
178 } | 178 } |
179 } | 179 } |
180 } | 180 } |
| 181 |
| 182 Zone* zone() { return main_zone(); } |
181 }; | 183 }; |
182 | 184 |
183 | 185 |
184 struct While { | 186 struct While { |
185 LoopFinderTester& t; | 187 LoopFinderTester& t; |
186 Node* branch; | 188 Node* branch; |
187 Node* if_true; | 189 Node* if_true; |
188 Node* exit; | 190 Node* exit; |
189 Node* loop; | 191 Node* loop; |
190 | 192 |
(...skipping 641 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
832 phi3, cond3, branch3, if_true3}; | 834 phi3, cond3, branch3, if_true3}; |
833 t.CheckLoop(header2, 2, body2, 9); | 835 t.CheckLoop(header2, 2, body2, 9); |
834 | 836 |
835 Node* header3[] = {loop3, phi3}; | 837 Node* header3[] = {loop3, phi3}; |
836 Node* body3[] = {cond3, branch3, if_true3}; | 838 Node* body3[] = {cond3, branch3, if_true3}; |
837 t.CheckLoop(header3, 2, body3, 3); | 839 t.CheckLoop(header3, 2, body3, 3); |
838 } | 840 } |
839 | 841 |
840 | 842 |
841 // Runs all combinations with a fixed {i}. | 843 // Runs all combinations with a fixed {i}. |
842 void RunEdgeMatrix3_i(int i) { | 844 static void RunEdgeMatrix3_i(int i) { |
843 for (int a = 0; a < 1; a++) { | 845 for (int a = 0; a < 1; a++) { |
844 for (int b = 0; b < 1; b++) { | 846 for (int b = 0; b < 1; b++) { |
845 for (int c = 0; c < 4; c++) { | 847 for (int c = 0; c < 4; c++) { |
846 for (int d = 0; d < 3; d++) { | 848 for (int d = 0; d < 3; d++) { |
847 for (int e = 0; e < 3; e++) { | 849 for (int e = 0; e < 3; e++) { |
848 for (int f = 0; f < 6; f++) { | 850 for (int f = 0; f < 6; f++) { |
849 for (int g = 0; g < 5; g++) { | 851 for (int g = 0; g < 5; g++) { |
850 for (int h = 0; h < 5; h++) { | 852 for (int h = 0; h < 5; h++) { |
851 RunEdgeMatrix3(a, b, c, d, e, f, g, h, i); | 853 RunEdgeMatrix3(a, b, c, d, e, f, g, h, i); |
852 } | 854 } |
(...skipping 17 matching lines...) Expand all Loading... |
870 TEST(LaEdgeMatrix3_2) { RunEdgeMatrix3_i(2); } | 872 TEST(LaEdgeMatrix3_2) { RunEdgeMatrix3_i(2); } |
871 | 873 |
872 | 874 |
873 TEST(LaEdgeMatrix3_3) { RunEdgeMatrix3_i(3); } | 875 TEST(LaEdgeMatrix3_3) { RunEdgeMatrix3_i(3); } |
874 | 876 |
875 | 877 |
876 TEST(LaEdgeMatrix3_4) { RunEdgeMatrix3_i(4); } | 878 TEST(LaEdgeMatrix3_4) { RunEdgeMatrix3_i(4); } |
877 | 879 |
878 | 880 |
879 TEST(LaEdgeMatrix3_5) { RunEdgeMatrix3_i(5); } | 881 TEST(LaEdgeMatrix3_5) { RunEdgeMatrix3_i(5); } |
| 882 |
| 883 |
| 884 static void RunManyChainedLoops_i(int count) { |
| 885 LoopFinderTester t; |
| 886 Node** nodes = t.zone()->NewArray<Node*>(count * 4); |
| 887 Node* k11 = t.jsgraph.Int32Constant(11); |
| 888 Node* k12 = t.jsgraph.Int32Constant(12); |
| 889 Node* last = t.start; |
| 890 |
| 891 // Build loops. |
| 892 for (int i = 0; i < count; i++) { |
| 893 Node* loop = t.graph.NewNode(t.common.Loop(2), last, t.start); |
| 894 Node* phi = t.graph.NewNode(t.common.Phi(kMachInt32, 2), k11, k12, loop); |
| 895 Node* branch = t.graph.NewNode(t.common.Branch(), phi, loop); |
| 896 Node* if_true = t.graph.NewNode(t.common.IfTrue(), branch); |
| 897 Node* exit = t.graph.NewNode(t.common.IfFalse(), branch); |
| 898 loop->ReplaceInput(1, if_true); |
| 899 |
| 900 nodes[i * 4 + 0] = loop; |
| 901 nodes[i * 4 + 1] = phi; |
| 902 nodes[i * 4 + 2] = branch; |
| 903 nodes[i * 4 + 3] = if_true; |
| 904 |
| 905 last = exit; |
| 906 } |
| 907 |
| 908 Node* ret = t.graph.NewNode(t.common.Return(), t.p0, t.start, last); |
| 909 t.graph.SetEnd(ret); |
| 910 |
| 911 // Verify loops. |
| 912 for (int i = 0; i < count; i++) { |
| 913 t.CheckLoop(nodes + i * 4, 2, nodes + i * 4 + 2, 2); |
| 914 } |
| 915 } |
| 916 |
| 917 |
| 918 static void RunManyNestedLoops_i(int count) { |
| 919 LoopFinderTester t; |
| 920 Node** nodes = t.zone()->NewArray<Node*>(count * 5); |
| 921 Node* k11 = t.jsgraph.Int32Constant(11); |
| 922 Node* k12 = t.jsgraph.Int32Constant(12); |
| 923 Node* outer = nullptr; |
| 924 Node* entry = t.start; |
| 925 |
| 926 // Build loops. |
| 927 for (int i = 0; i < count; i++) { |
| 928 Node* loop = t.graph.NewNode(t.common.Loop(2), entry, t.start); |
| 929 Node* phi = t.graph.NewNode(t.common.Phi(kMachInt32, 2), k11, k12, loop); |
| 930 Node* branch = t.graph.NewNode(t.common.Branch(), phi, loop); |
| 931 Node* if_true = t.graph.NewNode(t.common.IfTrue(), branch); |
| 932 Node* exit = t.graph.NewNode(t.common.IfFalse(), branch); |
| 933 |
| 934 nodes[i * 5 + 0] = exit; // outside |
| 935 nodes[i * 5 + 1] = loop; // header |
| 936 nodes[i * 5 + 2] = phi; // header |
| 937 nodes[i * 5 + 3] = branch; // body |
| 938 nodes[i * 5 + 4] = if_true; // body |
| 939 |
| 940 if (outer != nullptr) { |
| 941 // inner loop. |
| 942 outer->ReplaceInput(1, exit); |
| 943 } else { |
| 944 // outer loop. |
| 945 Node* ret = t.graph.NewNode(t.common.Return(), t.p0, t.start, exit); |
| 946 t.graph.SetEnd(ret); |
| 947 } |
| 948 outer = loop; |
| 949 entry = if_true; |
| 950 } |
| 951 outer->ReplaceInput(1, entry); // innermost loop. |
| 952 |
| 953 // Verify loops. |
| 954 for (int i = 0; i < count; i++) { |
| 955 int k = i * 5; |
| 956 t.CheckLoop(nodes + k + 1, 2, nodes + k + 3, count * 5 - k - 3); |
| 957 } |
| 958 } |
| 959 |
| 960 |
| 961 TEST(LaManyChained_30) { RunManyChainedLoops_i(30); } |
| 962 TEST(LaManyChained_31) { RunManyChainedLoops_i(31); } |
| 963 TEST(LaManyChained_32) { RunManyChainedLoops_i(32); } |
| 964 TEST(LaManyChained_33) { RunManyChainedLoops_i(33); } |
| 965 TEST(LaManyChained_34) { RunManyChainedLoops_i(34); } |
| 966 TEST(LaManyChained_62) { RunManyChainedLoops_i(62); } |
| 967 TEST(LaManyChained_63) { RunManyChainedLoops_i(63); } |
| 968 TEST(LaManyChained_64) { RunManyChainedLoops_i(64); } |
| 969 |
| 970 TEST(LaManyNested_30) { RunManyNestedLoops_i(30); } |
| 971 TEST(LaManyNested_31) { RunManyNestedLoops_i(31); } |
| 972 TEST(LaManyNested_32) { RunManyNestedLoops_i(32); } |
| 973 TEST(LaManyNested_33) { RunManyNestedLoops_i(33); } |
| 974 TEST(LaManyNested_34) { RunManyNestedLoops_i(34); } |
| 975 TEST(LaManyNested_62) { RunManyNestedLoops_i(62); } |
| 976 TEST(LaManyNested_63) { RunManyNestedLoops_i(63); } |
| 977 TEST(LaManyNested_64) { RunManyNestedLoops_i(64); } |
OLD | NEW |