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 #include "test/cctest/cctest.h" | 6 #include "test/cctest/cctest.h" |
7 | 7 |
8 #include "src/base/bits.h" | 8 #include "src/base/bits.h" |
9 #include "src/compiler/common-operator.h" | 9 #include "src/compiler/common-operator.h" |
10 #include "src/compiler/control-reducer.h" | 10 #include "src/compiler/control-reducer.h" |
11 #include "src/compiler/graph-inl.h" | 11 #include "src/compiler/graph-inl.h" |
12 #include "src/compiler/js-graph.h" | 12 #include "src/compiler/js-graph.h" |
13 #include "src/compiler/node-properties-inl.h" | 13 #include "src/compiler/node-properties-inl.h" |
14 | 14 |
15 using namespace v8::internal; | 15 using namespace v8::internal; |
16 using namespace v8::internal::compiler; | 16 using namespace v8::internal::compiler; |
17 | 17 |
18 static const size_t kNumLeafs = 4; | 18 static const size_t kNumLeafs = 4; |
19 | 19 |
| 20 enum Decision { kFalse, kUnknown, kTrue }; |
| 21 |
20 // TODO(titzer): convert this whole file into unit tests. | 22 // TODO(titzer): convert this whole file into unit tests. |
21 | 23 |
22 static int CheckInputs(Node* node, Node* i0 = NULL, Node* i1 = NULL, | 24 static int CheckInputs(Node* node, Node* i0 = NULL, Node* i1 = NULL, |
23 Node* i2 = NULL) { | 25 Node* i2 = NULL) { |
24 int count = 3; | 26 int count = 3; |
25 if (i2 == NULL) count = 2; | 27 if (i2 == NULL) count = 2; |
26 if (i1 == NULL) count = 1; | 28 if (i1 == NULL) count = 1; |
27 if (i0 == NULL) count = 0; | 29 if (i0 == NULL) count = 0; |
28 CHECK_EQ(count, node->InputCount()); | 30 CHECK_EQ(count, node->InputCount()); |
29 if (i0 != NULL) CHECK_EQ(i0, node->InputAt(0)); | 31 if (i0 != NULL) CHECK_EQ(i0, node->InputAt(0)); |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
168 } | 170 } |
169 | 171 |
170 void ReduceMergeIterative(Node* expect, Node* merge) { | 172 void ReduceMergeIterative(Node* expect, Node* merge) { |
171 p0->ReplaceInput(0, start); // hack: parameters may be trimmed. | 173 p0->ReplaceInput(0, start); // hack: parameters may be trimmed. |
172 Node* end = graph.NewNode(common.End(), merge); | 174 Node* end = graph.NewNode(common.End(), merge); |
173 graph.SetEnd(end); | 175 graph.SetEnd(end); |
174 ReduceGraph(); | 176 ReduceGraph(); |
175 CheckInputs(end, expect); | 177 CheckInputs(end, expect); |
176 } | 178 } |
177 | 179 |
178 void ReduceBranch(Node* expect, Node* branch) { | 180 void ReduceBranch(Decision expected, Node* branch) { |
179 Node* result = | 181 Node* control = branch->InputAt(1); |
180 ControlReducer::ReduceBranchForTesting(&jsgraph, &common, branch); | 182 for (Node* use : branch->uses()) { |
181 CHECK_EQ(expect, result); | 183 if (use->opcode() == IrOpcode::kIfTrue) { |
| 184 Node* result = |
| 185 ControlReducer::ReduceIfNodeForTesting(&jsgraph, &common, use); |
| 186 if (expected == kTrue) CHECK_EQ(control, result); |
| 187 if (expected == kFalse) CHECK_EQ(IrOpcode::kDead, result->opcode()); |
| 188 if (expected == kUnknown) CHECK_EQ(use, result); |
| 189 } else if (use->opcode() == IrOpcode::kIfFalse) { |
| 190 Node* result = |
| 191 ControlReducer::ReduceIfNodeForTesting(&jsgraph, &common, use); |
| 192 if (expected == kFalse) CHECK_EQ(control, result); |
| 193 if (expected == kTrue) CHECK_EQ(IrOpcode::kDead, result->opcode()); |
| 194 if (expected == kUnknown) CHECK_EQ(use, result); |
| 195 } else { |
| 196 UNREACHABLE(); |
| 197 } |
| 198 } |
182 } | 199 } |
183 | 200 |
184 Node* Return(Node* val, Node* effect, Node* control) { | 201 Node* Return(Node* val, Node* effect, Node* control) { |
185 Node* ret = graph.NewNode(common.Return(), val, effect, control); | 202 Node* ret = graph.NewNode(common.Return(), val, effect, control); |
186 end->ReplaceInput(0, ret); | 203 end->ReplaceInput(0, ret); |
187 return ret; | 204 return ret; |
188 } | 205 } |
189 }; | 206 }; |
190 | 207 |
191 | 208 |
(...skipping 829 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1021 loop->ReplaceInput(1, if_true); | 1038 loop->ReplaceInput(1, if_true); |
1022 } | 1039 } |
1023 | 1040 |
1024 void chain(Node* control) { loop->ReplaceInput(0, control); } | 1041 void chain(Node* control) { loop->ReplaceInput(0, control); } |
1025 }; | 1042 }; |
1026 | 1043 |
1027 | 1044 |
1028 TEST(CBranchReduce_none1) { | 1045 TEST(CBranchReduce_none1) { |
1029 ControlReducerTester R; | 1046 ControlReducerTester R; |
1030 Diamond d(R, R.p0); | 1047 Diamond d(R, R.p0); |
1031 R.ReduceBranch(d.branch, d.branch); | 1048 R.ReduceBranch(kUnknown, d.branch); |
1032 } | 1049 } |
1033 | 1050 |
1034 | 1051 |
1035 TEST(CBranchReduce_none2) { | 1052 TEST(CBranchReduce_none2) { |
1036 ControlReducerTester R; | 1053 ControlReducerTester R; |
1037 Diamond d1(R, R.p0); | 1054 Diamond d1(R, R.p0); |
1038 Diamond d2(R, R.p0); | 1055 Diamond d2(R, R.p0); |
1039 d2.chain(d1); | 1056 d2.chain(d1); |
1040 R.ReduceBranch(d2.branch, d2.branch); | 1057 R.ReduceBranch(kUnknown, d2.branch); |
1041 } | 1058 } |
1042 | 1059 |
1043 | 1060 |
1044 TEST(CBranchReduce_true) { | 1061 TEST(CBranchReduce_true) { |
1045 ControlReducerTester R; | 1062 ControlReducerTester R; |
1046 Node* true_values[] = { | 1063 Node* true_values[] = { |
1047 R.one, R.jsgraph.Int32Constant(2), | 1064 R.one, R.jsgraph.Int32Constant(2), |
1048 R.jsgraph.Int32Constant(0x7fffffff), R.jsgraph.Constant(1.0), | 1065 R.jsgraph.Int32Constant(0x7fffffff), R.jsgraph.Constant(1.0), |
1049 R.jsgraph.Constant(22.1), R.jsgraph.TrueConstant()}; | 1066 R.jsgraph.Constant(22.1), R.jsgraph.TrueConstant()}; |
1050 | 1067 |
1051 for (size_t i = 0; i < arraysize(true_values); i++) { | 1068 for (size_t i = 0; i < arraysize(true_values); i++) { |
1052 Diamond d(R, true_values[i]); | 1069 Diamond d(R, true_values[i]); |
1053 Node* true_use = R.graph.NewNode(R.common.Merge(1), d.if_true); | 1070 R.ReduceBranch(kTrue, d.branch); |
1054 Node* false_use = R.graph.NewNode(R.common.Merge(1), d.if_false); | |
1055 R.ReduceBranch(R.start, d.branch); | |
1056 CHECK_EQ(R.start, true_use->InputAt(0)); | |
1057 CHECK_EQ(IrOpcode::kDead, false_use->InputAt(0)->opcode()); | |
1058 CHECK(d.if_true->IsDead()); // replaced | |
1059 CHECK(d.if_false->IsDead()); // replaced | |
1060 } | 1071 } |
1061 } | 1072 } |
1062 | 1073 |
1063 | 1074 |
1064 TEST(CBranchReduce_false) { | 1075 TEST(CBranchReduce_false) { |
1065 ControlReducerTester R; | 1076 ControlReducerTester R; |
1066 Node* false_values[] = {R.zero, R.jsgraph.Constant(0.0), | 1077 Node* false_values[] = {R.zero, R.jsgraph.Constant(0.0), |
1067 R.jsgraph.Constant(-0.0), R.jsgraph.FalseConstant()}; | 1078 R.jsgraph.Constant(-0.0), R.jsgraph.FalseConstant()}; |
1068 | 1079 |
1069 for (size_t i = 0; i < arraysize(false_values); i++) { | 1080 for (size_t i = 0; i < arraysize(false_values); i++) { |
1070 Diamond d(R, false_values[i]); | 1081 Diamond d(R, false_values[i]); |
1071 Node* true_use = R.graph.NewNode(R.common.Merge(1), d.if_true); | 1082 R.ReduceBranch(kFalse, d.branch); |
1072 Node* false_use = R.graph.NewNode(R.common.Merge(1), d.if_false); | |
1073 R.ReduceBranch(R.start, d.branch); | |
1074 CHECK_EQ(R.start, false_use->InputAt(0)); | |
1075 CHECK_EQ(IrOpcode::kDead, true_use->InputAt(0)->opcode()); | |
1076 CHECK(d.if_true->IsDead()); // replaced | |
1077 CHECK(d.if_false->IsDead()); // replaced | |
1078 } | 1083 } |
1079 } | 1084 } |
1080 | 1085 |
1081 | 1086 |
1082 TEST(CDiamondReduce_true) { | 1087 TEST(CDiamondReduce_true) { |
1083 ControlReducerTester R; | 1088 ControlReducerTester R; |
1084 Diamond d1(R, R.one); | 1089 Diamond d1(R, R.one); |
1085 R.ReduceMergeIterative(R.start, d1.merge); | 1090 R.ReduceMergeIterative(R.start, d1.merge); |
1086 } | 1091 } |
1087 | 1092 |
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1349 CheckInputs(merge, rt, rf, loop); | 1354 CheckInputs(merge, rt, rf, loop); |
1350 CheckInputs(loop, b2.if_false, loop); | 1355 CheckInputs(loop, b2.if_false, loop); |
1351 } | 1356 } |
1352 | 1357 |
1353 | 1358 |
1354 TEST(CNonTermLoop_big2) { | 1359 TEST(CNonTermLoop_big2) { |
1355 ControlReducerTester R; | 1360 ControlReducerTester R; |
1356 Branch b1(R, R.p0); | 1361 Branch b1(R, R.p0); |
1357 Node* rt = R.graph.NewNode(R.common.Return(), R.one, R.start, b1.if_true); | 1362 Node* rt = R.graph.NewNode(R.common.Return(), R.one, R.start, b1.if_true); |
1358 | 1363 |
1359 Branch b2(R, R.zero, b1.if_false); | 1364 Node* loop = R.graph.NewNode(R.common.Loop(2), b1.if_false, R.start); |
| 1365 Branch b2(R, R.zero, loop); |
| 1366 loop->ReplaceInput(1, b2.if_false); |
1360 Node* rf = R.graph.NewNode(R.common.Return(), R.zero, R.start, b2.if_true); | 1367 Node* rf = R.graph.NewNode(R.common.Return(), R.zero, R.start, b2.if_true); |
1361 Node* loop = R.SetSelfReferences( | |
1362 R.graph.NewNode(R.common.Loop(2), b2.if_false, R.self)); | |
1363 Node* merge = R.graph.NewNode(R.common.Merge(2), rt, rf); | 1368 Node* merge = R.graph.NewNode(R.common.Merge(2), rt, rf); |
1364 R.end->ReplaceInput(0, merge); | 1369 R.end->ReplaceInput(0, merge); |
1365 | 1370 |
1366 R.ReduceGraph(); | 1371 R.ReduceGraph(); |
1367 | 1372 |
1368 Node* new_merge = R.end->InputAt(0); // old merge was reduced. | 1373 Node* new_merge = R.end->InputAt(0); // old merge was reduced. |
1369 CHECK_NE(merge, new_merge); | 1374 CHECK_NE(merge, new_merge); |
1370 CheckInputs(new_merge, rt, loop); | 1375 CheckInputs(new_merge, rt, loop); |
1371 CheckInputs(loop, b1.if_false, loop); | 1376 CheckInputs(loop, b1.if_false, loop); |
1372 CHECK(merge->IsDead()); | 1377 CHECK(merge->IsDead()); |
(...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1667 | 1672 |
1668 Node* ret = R.Return(d1.phi, R.start, d1.merge); | 1673 Node* ret = R.Return(d1.phi, R.start, d1.merge); |
1669 | 1674 |
1670 R.ReduceGraph(); // d1 gets folded true. | 1675 R.ReduceGraph(); // d1 gets folded true. |
1671 | 1676 |
1672 CheckInputs(ret, y2, R.start, R.start); | 1677 CheckInputs(ret, y2, R.start, R.start); |
1673 CheckDeadDiamond(d1); | 1678 CheckDeadDiamond(d1); |
1674 CheckDeadDiamond(d2); | 1679 CheckDeadDiamond(d2); |
1675 CheckDeadDiamond(d3); | 1680 CheckDeadDiamond(d3); |
1676 } | 1681 } |
OLD | NEW |