| 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 |