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/all-nodes.h" | 9 #include "src/compiler/all-nodes.h" |
10 #include "src/compiler/common-operator.h" | 10 #include "src/compiler/common-operator.h" |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
134 for (Edge edge : node->input_edges()) { | 134 for (Edge edge : node->input_edges()) { |
135 if (edge.to() == self) node->ReplaceInput(edge.index(), node); | 135 if (edge.to() == self) node->ReplaceInput(edge.index(), node); |
136 } | 136 } |
137 return node; | 137 return node; |
138 } | 138 } |
139 | 139 |
140 const Operator* op(int count, bool effect) { | 140 const Operator* op(int count, bool effect) { |
141 return effect ? common.EffectPhi(count) : common.Phi(kMachAnyTagged, count); | 141 return effect ? common.EffectPhi(count) : common.Phi(kMachAnyTagged, count); |
142 } | 142 } |
143 | 143 |
144 void Trim() { ControlReducer::TrimGraph(main_zone(), &jsgraph); } | |
145 | |
146 void ReduceGraph() { ControlReducer::ReduceGraph(main_zone(), &jsgraph); } | 144 void ReduceGraph() { ControlReducer::ReduceGraph(main_zone(), &jsgraph); } |
147 | 145 |
148 // Checks one-step reduction of a phi. | 146 // Checks one-step reduction of a phi. |
149 void ReducePhi(Node* expect, Node* phi) { | 147 void ReducePhi(Node* expect, Node* phi) { |
150 Node* result = ControlReducer::ReducePhiForTesting(&jsgraph, phi); | 148 Node* result = ControlReducer::ReducePhiForTesting(&jsgraph, phi); |
151 CHECK_EQ(expect, result); | 149 CHECK_EQ(expect, result); |
152 ReducePhiIterative(expect, phi); // iterative should give the same result. | 150 ReducePhiIterative(expect, phi); // iterative should give the same result. |
153 } | 151 } |
154 | 152 |
155 // Checks one-step reduction of a phi. | 153 // Checks one-step reduction of a phi. |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
304 CHECK_EQ(3, d.phi->InputCount()); | 302 CHECK_EQ(3, d.phi->InputCount()); |
305 CHECK_EQ(d.merge, d.phi->InputAt(2)); | 303 CHECK_EQ(d.merge, d.phi->InputAt(2)); |
306 } else { | 304 } else { |
307 Check(d.phi); | 305 Check(d.phi); |
308 } | 306 } |
309 } | 307 } |
310 } | 308 } |
311 }; | 309 }; |
312 | 310 |
313 | 311 |
314 TEST(Trim1_live) { | |
315 ControlReducerTester T; | |
316 CHECK(IsUsedBy(T.start, T.p0)); | |
317 T.graph.SetEnd(T.p0); | |
318 T.Trim(); | |
319 CHECK(IsUsedBy(T.start, T.p0)); | |
320 CheckInputs(T.p0, T.start); | |
321 } | |
322 | |
323 | |
324 TEST(Trim1_dead) { | |
325 ControlReducerTester T; | |
326 CHECK(IsUsedBy(T.start, T.p0)); | |
327 T.Trim(); | |
328 CHECK(!IsUsedBy(T.start, T.p0)); | |
329 CHECK(!T.p0->InputAt(0)); | |
330 } | |
331 | |
332 | |
333 TEST(Trim2_live) { | |
334 ControlReducerTester T; | |
335 Node* phi = | |
336 T.graph.NewNode(T.common.Phi(kMachAnyTagged, 2), T.one, T.half, T.start); | |
337 CHECK(IsUsedBy(T.one, phi)); | |
338 CHECK(IsUsedBy(T.half, phi)); | |
339 CHECK(IsUsedBy(T.start, phi)); | |
340 T.graph.SetEnd(phi); | |
341 T.Trim(); | |
342 CHECK(IsUsedBy(T.one, phi)); | |
343 CHECK(IsUsedBy(T.half, phi)); | |
344 CHECK(IsUsedBy(T.start, phi)); | |
345 CheckInputs(phi, T.one, T.half, T.start); | |
346 } | |
347 | |
348 | |
349 TEST(Trim2_dead) { | |
350 ControlReducerTester T; | |
351 Node* phi = | |
352 T.graph.NewNode(T.common.Phi(kMachAnyTagged, 2), T.one, T.half, T.start); | |
353 CHECK(IsUsedBy(T.one, phi)); | |
354 CHECK(IsUsedBy(T.half, phi)); | |
355 CHECK(IsUsedBy(T.start, phi)); | |
356 T.Trim(); | |
357 CHECK(!IsUsedBy(T.one, phi)); | |
358 CHECK(!IsUsedBy(T.half, phi)); | |
359 CHECK(!IsUsedBy(T.start, phi)); | |
360 CHECK(!phi->InputAt(0)); | |
361 CHECK(!phi->InputAt(1)); | |
362 CHECK(!phi->InputAt(2)); | |
363 } | |
364 | |
365 | |
366 TEST(Trim_chain1) { | |
367 ControlReducerTester T; | |
368 const int kDepth = 15; | |
369 Node* live[kDepth]; | |
370 Node* dead[kDepth]; | |
371 Node* end = T.start; | |
372 for (int i = 0; i < kDepth; i++) { | |
373 live[i] = end = T.graph.NewNode(T.common.Merge(1), end); | |
374 dead[i] = T.graph.NewNode(T.common.Merge(1), end); | |
375 } | |
376 // end -> live[last] -> live[last-1] -> ... -> start | |
377 // dead[last] ^ dead[last-1] ^ ... ^ | |
378 T.graph.SetEnd(end); | |
379 T.Trim(); | |
380 for (int i = 0; i < kDepth; i++) { | |
381 CHECK(!IsUsedBy(live[i], dead[i])); | |
382 CHECK(!dead[i]->InputAt(0)); | |
383 CHECK_EQ(i == 0 ? T.start : live[i - 1], live[i]->InputAt(0)); | |
384 } | |
385 } | |
386 | |
387 | |
388 TEST(Trim_chain2) { | |
389 ControlReducerTester T; | |
390 const int kDepth = 15; | |
391 Node* live[kDepth]; | |
392 Node* dead[kDepth]; | |
393 Node* l = T.start; | |
394 Node* d = T.start; | |
395 for (int i = 0; i < kDepth; i++) { | |
396 live[i] = l = T.graph.NewNode(T.common.Merge(1), l); | |
397 dead[i] = d = T.graph.NewNode(T.common.Merge(1), d); | |
398 } | |
399 // end -> live[last] -> live[last-1] -> ... -> start | |
400 // dead[last] -> dead[last-1] -> ... -> start | |
401 T.graph.SetEnd(l); | |
402 T.Trim(); | |
403 CHECK(!IsUsedBy(T.start, dead[0])); | |
404 for (int i = 0; i < kDepth; i++) { | |
405 CHECK_EQ(i == 0 ? NULL : dead[i - 1], dead[i]->InputAt(0)); | |
406 CHECK_EQ(i == 0 ? T.start : live[i - 1], live[i]->InputAt(0)); | |
407 } | |
408 } | |
409 | |
410 | |
411 TEST(Trim_cycle1) { | |
412 ControlReducerTester T; | |
413 Node* loop = T.graph.NewNode(T.common.Loop(1), T.start, T.start); | |
414 loop->ReplaceInput(1, loop); | |
415 Node* end = T.graph.NewNode(T.common.End(1), loop); | |
416 T.graph.SetEnd(end); | |
417 | |
418 CHECK(IsUsedBy(T.start, loop)); | |
419 CHECK(IsUsedBy(loop, end)); | |
420 CHECK(IsUsedBy(loop, loop)); | |
421 | |
422 T.Trim(); | |
423 | |
424 // nothing should have happened to the loop itself. | |
425 CHECK(IsUsedBy(T.start, loop)); | |
426 CHECK(IsUsedBy(loop, end)); | |
427 CHECK(IsUsedBy(loop, loop)); | |
428 CheckInputs(loop, T.start, loop); | |
429 CheckInputs(end, loop); | |
430 } | |
431 | |
432 | |
433 TEST(Trim_cycle2) { | |
434 ControlReducerTester T; | |
435 Node* loop = T.graph.NewNode(T.common.Loop(2), T.start, T.start); | |
436 loop->ReplaceInput(1, loop); | |
437 Node* end = T.graph.NewNode(T.common.End(1), loop); | |
438 Node* phi = | |
439 T.graph.NewNode(T.common.Phi(kMachAnyTagged, 2), T.one, T.half, loop); | |
440 T.graph.SetEnd(end); | |
441 | |
442 CHECK(IsUsedBy(T.start, loop)); | |
443 CHECK(IsUsedBy(loop, end)); | |
444 CHECK(IsUsedBy(loop, loop)); | |
445 CHECK(IsUsedBy(loop, phi)); | |
446 CHECK(IsUsedBy(T.one, phi)); | |
447 CHECK(IsUsedBy(T.half, phi)); | |
448 | |
449 T.Trim(); | |
450 | |
451 // nothing should have happened to the loop itself. | |
452 CHECK(IsUsedBy(T.start, loop)); | |
453 CHECK(IsUsedBy(loop, end)); | |
454 CHECK(IsUsedBy(loop, loop)); | |
455 CheckInputs(loop, T.start, loop); | |
456 CheckInputs(end, loop); | |
457 | |
458 // phi should have been trimmed away. | |
459 CHECK(!IsUsedBy(loop, phi)); | |
460 CHECK(!IsUsedBy(T.one, phi)); | |
461 CHECK(!IsUsedBy(T.half, phi)); | |
462 CHECK(!phi->InputAt(0)); | |
463 CHECK(!phi->InputAt(1)); | |
464 CHECK(!phi->InputAt(2)); | |
465 } | |
466 | |
467 | |
468 void CheckTrimConstant(ControlReducerTester* T, Node* k) { | |
469 Node* phi = T->graph.NewNode(T->common.Phi(kMachInt32, 1), k, T->start); | |
470 CHECK(IsUsedBy(k, phi)); | |
471 T->Trim(); | |
472 CHECK(!IsUsedBy(k, phi)); | |
473 CHECK(!phi->InputAt(0)); | |
474 CHECK(!phi->InputAt(1)); | |
475 } | |
476 | |
477 | |
478 TEST(Trim_constants) { | |
479 ControlReducerTester T; | |
480 int32_t int32_constants[] = { | |
481 0, -1, -2, 2, 2, 3, 3, 4, 4, 5, 5, 4, 5, 6, 6, 7, 8, 7, 8, 9, | |
482 0, -11, -12, 12, 12, 13, 13, 14, 14, 15, 15, 14, 15, 6, 6, 7, 8, 7, 8, 9}; | |
483 | |
484 for (size_t i = 0; i < arraysize(int32_constants); i++) { | |
485 CheckTrimConstant(&T, T.jsgraph.Int32Constant(int32_constants[i])); | |
486 CheckTrimConstant(&T, T.jsgraph.Float64Constant(int32_constants[i])); | |
487 CheckTrimConstant(&T, T.jsgraph.Constant(int32_constants[i])); | |
488 } | |
489 | |
490 Node* other_constants[] = { | |
491 T.jsgraph.UndefinedConstant(), T.jsgraph.TheHoleConstant(), | |
492 T.jsgraph.TrueConstant(), T.jsgraph.FalseConstant(), | |
493 T.jsgraph.NullConstant(), T.jsgraph.ZeroConstant(), | |
494 T.jsgraph.OneConstant(), T.jsgraph.NaNConstant(), | |
495 T.jsgraph.Constant(21), T.jsgraph.Constant(22.2)}; | |
496 | |
497 for (size_t i = 0; i < arraysize(other_constants); i++) { | |
498 CheckTrimConstant(&T, other_constants[i]); | |
499 } | |
500 } | |
501 | |
502 | |
503 TEST(Trim_EmptyFrameState1) { | |
504 ControlReducerTester T; | |
505 | |
506 Node* node = T.jsgraph.EmptyFrameState(); | |
507 T.Trim(); | |
508 | |
509 for (Node* input : node->inputs()) { | |
510 CHECK_NOT_NULL(input); | |
511 } | |
512 } | |
513 | |
514 | |
515 TEST(Trim_EmptyFrameState2) { | |
516 ControlReducerTester T; | |
517 CheckTrimConstant(&T, T.jsgraph.EmptyFrameState()); | |
518 } | |
519 | |
520 | |
521 TEST(CReducePhi1) { | 312 TEST(CReducePhi1) { |
522 ControlReducerTester R; | 313 ControlReducerTester R; |
523 | 314 |
524 R.ReducePhi(R.leaf[0], R.Phi(R.leaf[0])); | 315 R.ReducePhi(R.leaf[0], R.Phi(R.leaf[0])); |
525 R.ReducePhi(R.leaf[1], R.Phi(R.leaf[1])); | 316 R.ReducePhi(R.leaf[1], R.Phi(R.leaf[1])); |
526 R.ReducePhi(R.leaf[2], R.Phi(R.leaf[2])); | 317 R.ReducePhi(R.leaf[2], R.Phi(R.leaf[2])); |
527 R.ReducePhi(R.leaf[3], R.Phi(R.leaf[3])); | 318 R.ReducePhi(R.leaf[3], R.Phi(R.leaf[3])); |
528 } | 319 } |
529 | 320 |
530 | 321 |
(...skipping 1084 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1615 | 1406 |
1616 R.ReduceGraph(); // d1 gets folded true. | 1407 R.ReduceGraph(); // d1 gets folded true. |
1617 | 1408 |
1618 CheckInputs(ret, y2, R.start, R.start); | 1409 CheckInputs(ret, y2, R.start, R.start); |
1619 | 1410 |
1620 DeadChecker dead(&R.graph); | 1411 DeadChecker dead(&R.graph); |
1621 dead.Check(d1); | 1412 dead.Check(d1); |
1622 dead.Check(d2); | 1413 dead.Check(d2); |
1623 dead.Check(d3); | 1414 dead.Check(d3); |
1624 } | 1415 } |
OLD | NEW |