OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 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/codegen.h" | 5 #include "src/codegen.h" |
6 #include "src/compiler/all-nodes.h" | 6 #include "src/compiler/all-nodes.h" |
7 #include "src/compiler/common-operator.h" | 7 #include "src/compiler/common-operator.h" |
8 #include "src/compiler/diamond.h" | 8 #include "src/compiler/diamond.h" |
9 #include "src/compiler/graph.h" | 9 #include "src/compiler/graph.h" |
10 #include "src/compiler/js-graph.h" | 10 #include "src/compiler/js-graph.h" |
(...skipping 352 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
363 TEST(Deconstruct_osr_nested1) { | 363 TEST(Deconstruct_osr_nested1) { |
364 OsrDeconstructorTester T(1); | 364 OsrDeconstructorTester T(1); |
365 | 365 |
366 While outer(T, T.p0, false); | 366 While outer(T, T.p0, false); |
367 While inner(T, T.p0, true); | 367 While inner(T, T.p0, true); |
368 inner.Nest(outer); | 368 inner.Nest(outer); |
369 | 369 |
370 Node* outer_phi = outer.Phi(T.p0, T.p0, nullptr); | 370 Node* outer_phi = outer.Phi(T.p0, T.p0, nullptr); |
371 outer.branch->ReplaceInput(0, outer_phi); | 371 outer.branch->ReplaceInput(0, outer_phi); |
372 | 372 |
373 Node* osr_phi = inner.Phi(T.jsgraph.OneConstant(), T.osr_values[0], | 373 Node* osr_phi = inner.Phi(T.jsgraph.TrueConstant(), T.osr_values[0], |
374 T.jsgraph.ZeroConstant()); | 374 T.jsgraph.FalseConstant()); |
375 inner.branch->ReplaceInput(0, osr_phi); | 375 inner.branch->ReplaceInput(0, osr_phi); |
376 outer_phi->ReplaceInput(1, osr_phi); | 376 outer_phi->ReplaceInput(1, osr_phi); |
377 | 377 |
378 Node* ret = | 378 Node* ret = |
379 T.graph.NewNode(T.common.Return(), outer_phi, T.start, outer.exit); | 379 T.graph.NewNode(T.common.Return(), outer_phi, T.start, outer.exit); |
380 Node* end = T.graph.NewNode(T.common.End(1), ret); | 380 Node* end = T.graph.NewNode(T.common.End(1), ret); |
381 T.graph.SetEnd(end); | 381 T.graph.SetEnd(end); |
382 | 382 |
383 T.DeconstructOsr(); | 383 T.DeconstructOsr(); |
384 | 384 |
385 // Check structure of deconstructed graph. | 385 // Check structure of deconstructed graph. |
386 // Check inner OSR loop is directly connected to start. | 386 // Check inner OSR loop is directly connected to start. |
387 CheckInputs(inner.loop, T.start, inner.if_true); | 387 CheckInputs(inner.loop, T.start, inner.if_true); |
388 CheckInputs(osr_phi, T.osr_values[0], T.jsgraph.ZeroConstant(), inner.loop); | 388 CheckInputs(osr_phi, T.osr_values[0], T.jsgraph.FalseConstant(), inner.loop); |
389 | 389 |
390 // Check control transfer to copy of outer loop. | 390 // Check control transfer to copy of outer loop. |
391 Node* new_outer_loop = FindSuccessor(inner.exit, IrOpcode::kLoop); | 391 Node* new_outer_loop = FindSuccessor(inner.exit, IrOpcode::kLoop); |
392 Node* new_outer_phi = FindSuccessor(new_outer_loop, IrOpcode::kPhi); | 392 Node* new_outer_phi = FindSuccessor(new_outer_loop, IrOpcode::kPhi); |
393 CHECK_NE(new_outer_loop, outer.loop); | 393 CHECK_NE(new_outer_loop, outer.loop); |
394 CHECK_NE(new_outer_phi, outer_phi); | 394 CHECK_NE(new_outer_phi, outer_phi); |
395 | 395 |
396 CheckInputs(new_outer_loop, inner.exit, new_outer_loop->InputAt(1)); | 396 CheckInputs(new_outer_loop, inner.exit, new_outer_loop->InputAt(1)); |
397 | 397 |
398 // Check structure of outer loop. | 398 // Check structure of outer loop. |
399 Node* new_outer_branch = FindSuccessor(new_outer_loop, IrOpcode::kBranch); | 399 Node* new_outer_branch = FindSuccessor(new_outer_loop, IrOpcode::kBranch); |
400 CHECK_NE(new_outer_branch, outer.branch); | 400 CHECK_NE(new_outer_branch, outer.branch); |
401 CheckInputs(new_outer_branch, new_outer_phi, new_outer_loop); | 401 CheckInputs(new_outer_branch, new_outer_phi, new_outer_loop); |
402 Node* new_outer_exit = FindSuccessor(new_outer_branch, IrOpcode::kIfFalse); | 402 Node* new_outer_exit = FindSuccessor(new_outer_branch, IrOpcode::kIfFalse); |
403 Node* new_outer_if_true = FindSuccessor(new_outer_branch, IrOpcode::kIfTrue); | 403 Node* new_outer_if_true = FindSuccessor(new_outer_branch, IrOpcode::kIfTrue); |
404 | 404 |
405 // Check structure of return. | 405 // Check structure of return. |
406 end = T.graph.end(); | 406 end = T.graph.end(); |
407 Node* new_ret = end->InputAt(0); | 407 Node* new_ret = end->InputAt(0); |
408 CHECK_EQ(IrOpcode::kReturn, new_ret->opcode()); | 408 CHECK_EQ(IrOpcode::kReturn, new_ret->opcode()); |
409 CheckInputs(new_ret, new_outer_phi, T.start, new_outer_exit); | 409 CheckInputs(new_ret, new_outer_phi, T.start, new_outer_exit); |
410 | 410 |
411 // Check structure of inner loop. | 411 // Check structure of inner loop. |
412 Node* new_inner_loop = FindSuccessor(new_outer_if_true, IrOpcode::kLoop); | 412 Node* new_inner_loop = FindSuccessor(new_outer_if_true, IrOpcode::kLoop); |
413 Node* new_inner_phi = FindSuccessor(new_inner_loop, IrOpcode::kPhi); | 413 Node* new_inner_phi = FindSuccessor(new_inner_loop, IrOpcode::kPhi); |
414 | 414 |
415 CheckInputs(new_inner_phi, T.jsgraph.OneConstant(), T.jsgraph.ZeroConstant(), | 415 CheckInputs(new_inner_phi, T.jsgraph.TrueConstant(), |
416 new_inner_loop); | 416 T.jsgraph.FalseConstant(), new_inner_loop); |
417 CheckInputs(new_outer_phi, osr_phi, new_inner_phi, new_outer_loop); | 417 CheckInputs(new_outer_phi, osr_phi, new_inner_phi, new_outer_loop); |
418 } | 418 } |
419 | 419 |
420 | 420 |
421 TEST(Deconstruct_osr_nested2) { | 421 TEST(Deconstruct_osr_nested2) { |
422 OsrDeconstructorTester T(1); | 422 OsrDeconstructorTester T(1); |
423 | 423 |
424 // Test multiple backedge outer loop. | 424 // Test multiple backedge outer loop. |
425 While outer(T, T.p0, false, 2); | 425 While outer(T, T.p0, false, 2); |
426 While inner(T, T.p0, true); | 426 While inner(T, T.p0, true); |
427 inner.Nest(outer); | 427 inner.Nest(outer); |
428 | 428 |
429 Node* outer_phi = outer.Phi(T.p0, T.p0, T.p0); | 429 Node* outer_phi = outer.Phi(T.p0, T.p0, T.p0); |
430 outer.branch->ReplaceInput(0, outer_phi); | 430 outer.branch->ReplaceInput(0, outer_phi); |
431 | 431 |
432 Node* osr_phi = inner.Phi(T.jsgraph.OneConstant(), T.osr_values[0], | 432 Node* osr_phi = inner.Phi(T.jsgraph.TrueConstant(), T.osr_values[0], |
433 T.jsgraph.ZeroConstant()); | 433 T.jsgraph.FalseConstant()); |
434 inner.branch->ReplaceInput(0, osr_phi); | 434 inner.branch->ReplaceInput(0, osr_phi); |
435 outer_phi->ReplaceInput(1, osr_phi); | 435 outer_phi->ReplaceInput(1, osr_phi); |
436 outer_phi->ReplaceInput(2, T.jsgraph.ZeroConstant()); | 436 outer_phi->ReplaceInput(2, T.jsgraph.FalseConstant()); |
437 | 437 |
438 Node* x_branch = T.graph.NewNode(T.common.Branch(), osr_phi, inner.exit); | 438 Node* x_branch = T.graph.NewNode(T.common.Branch(), osr_phi, inner.exit); |
439 Node* x_true = T.graph.NewNode(T.common.IfTrue(), x_branch); | 439 Node* x_true = T.graph.NewNode(T.common.IfTrue(), x_branch); |
440 Node* x_false = T.graph.NewNode(T.common.IfFalse(), x_branch); | 440 Node* x_false = T.graph.NewNode(T.common.IfFalse(), x_branch); |
441 | 441 |
442 outer.loop->ReplaceInput(1, x_true); | 442 outer.loop->ReplaceInput(1, x_true); |
443 outer.loop->ReplaceInput(2, x_false); | 443 outer.loop->ReplaceInput(2, x_false); |
444 | 444 |
445 Node* ret = | 445 Node* ret = |
446 T.graph.NewNode(T.common.Return(), outer_phi, T.start, outer.exit); | 446 T.graph.NewNode(T.common.Return(), outer_phi, T.start, outer.exit); |
447 Node* end = T.graph.NewNode(T.common.End(1), ret); | 447 Node* end = T.graph.NewNode(T.common.End(1), ret); |
448 T.graph.SetEnd(end); | 448 T.graph.SetEnd(end); |
449 | 449 |
450 T.DeconstructOsr(); | 450 T.DeconstructOsr(); |
451 | 451 |
452 // Check structure of deconstructed graph. | 452 // Check structure of deconstructed graph. |
453 // Check inner OSR loop is directly connected to start. | 453 // Check inner OSR loop is directly connected to start. |
454 CheckInputs(inner.loop, T.start, inner.if_true); | 454 CheckInputs(inner.loop, T.start, inner.if_true); |
455 CheckInputs(osr_phi, T.osr_values[0], T.jsgraph.ZeroConstant(), inner.loop); | 455 CheckInputs(osr_phi, T.osr_values[0], T.jsgraph.FalseConstant(), inner.loop); |
456 | 456 |
457 // Check control transfer to copy of outer loop. | 457 // Check control transfer to copy of outer loop. |
458 Node* new_merge = FindSuccessor(x_true, IrOpcode::kMerge); | 458 Node* new_merge = FindSuccessor(x_true, IrOpcode::kMerge); |
459 CHECK_EQ(new_merge, FindSuccessor(x_false, IrOpcode::kMerge)); | 459 CHECK_EQ(new_merge, FindSuccessor(x_false, IrOpcode::kMerge)); |
460 CheckInputs(new_merge, x_true, x_false); | 460 CheckInputs(new_merge, x_true, x_false); |
461 | 461 |
462 Node* new_outer_loop = FindSuccessor(new_merge, IrOpcode::kLoop); | 462 Node* new_outer_loop = FindSuccessor(new_merge, IrOpcode::kLoop); |
463 Node* new_outer_phi = FindSuccessor(new_outer_loop, IrOpcode::kPhi); | 463 Node* new_outer_phi = FindSuccessor(new_outer_loop, IrOpcode::kPhi); |
464 CHECK_NE(new_outer_loop, outer.loop); | 464 CHECK_NE(new_outer_loop, outer.loop); |
465 CHECK_NE(new_outer_phi, outer_phi); | 465 CHECK_NE(new_outer_phi, outer_phi); |
466 | 466 |
467 Node* new_entry_phi = FindSuccessor(new_merge, IrOpcode::kPhi); | 467 Node* new_entry_phi = FindSuccessor(new_merge, IrOpcode::kPhi); |
468 CheckInputs(new_entry_phi, osr_phi, T.jsgraph.ZeroConstant(), new_merge); | 468 CheckInputs(new_entry_phi, osr_phi, T.jsgraph.FalseConstant(), new_merge); |
469 | 469 |
470 CHECK_EQ(new_merge, new_outer_loop->InputAt(0)); | 470 CHECK_EQ(new_merge, new_outer_loop->InputAt(0)); |
471 | 471 |
472 // Check structure of outer loop. | 472 // Check structure of outer loop. |
473 Node* new_outer_branch = FindSuccessor(new_outer_loop, IrOpcode::kBranch); | 473 Node* new_outer_branch = FindSuccessor(new_outer_loop, IrOpcode::kBranch); |
474 CHECK_NE(new_outer_branch, outer.branch); | 474 CHECK_NE(new_outer_branch, outer.branch); |
475 CheckInputs(new_outer_branch, new_outer_phi, new_outer_loop); | 475 CheckInputs(new_outer_branch, new_outer_phi, new_outer_loop); |
476 Node* new_outer_exit = FindSuccessor(new_outer_branch, IrOpcode::kIfFalse); | 476 Node* new_outer_exit = FindSuccessor(new_outer_branch, IrOpcode::kIfFalse); |
477 Node* new_outer_if_true = FindSuccessor(new_outer_branch, IrOpcode::kIfTrue); | 477 Node* new_outer_if_true = FindSuccessor(new_outer_branch, IrOpcode::kIfTrue); |
478 | 478 |
479 // Check structure of return. | 479 // Check structure of return. |
480 end = T.graph.end(); | 480 end = T.graph.end(); |
481 Node* new_ret = end->InputAt(0); | 481 Node* new_ret = end->InputAt(0); |
482 CHECK_EQ(IrOpcode::kReturn, new_ret->opcode()); | 482 CHECK_EQ(IrOpcode::kReturn, new_ret->opcode()); |
483 CheckInputs(new_ret, new_outer_phi, T.start, new_outer_exit); | 483 CheckInputs(new_ret, new_outer_phi, T.start, new_outer_exit); |
484 | 484 |
485 // Check structure of inner loop. | 485 // Check structure of inner loop. |
486 Node* new_inner_loop = FindSuccessor(new_outer_if_true, IrOpcode::kLoop); | 486 Node* new_inner_loop = FindSuccessor(new_outer_if_true, IrOpcode::kLoop); |
487 Node* new_inner_phi = FindSuccessor(new_inner_loop, IrOpcode::kPhi); | 487 Node* new_inner_phi = FindSuccessor(new_inner_loop, IrOpcode::kPhi); |
488 | 488 |
489 CheckInputs(new_inner_phi, T.jsgraph.OneConstant(), T.jsgraph.ZeroConstant(), | 489 CheckInputs(new_inner_phi, T.jsgraph.TrueConstant(), |
490 new_inner_loop); | 490 T.jsgraph.FalseConstant(), new_inner_loop); |
491 CheckInputs(new_outer_phi, new_entry_phi, new_inner_phi, | 491 CheckInputs(new_outer_phi, new_entry_phi, new_inner_phi, |
492 T.jsgraph.ZeroConstant(), new_outer_loop); | 492 T.jsgraph.FalseConstant(), new_outer_loop); |
493 } | 493 } |
494 | 494 |
495 | 495 |
496 Node* MakeCounter(JSGraph* jsgraph, Node* start, Node* loop) { | 496 Node* MakeCounter(JSGraph* jsgraph, Node* start, Node* loop) { |
497 int count = loop->InputCount(); | 497 int count = loop->InputCount(); |
498 NodeVector tmp_inputs(jsgraph->graph()->zone()); | 498 NodeVector tmp_inputs(jsgraph->graph()->zone()); |
499 for (int i = 0; i < count; i++) { | 499 for (int i = 0; i < count; i++) { |
500 tmp_inputs.push_back(start); | 500 tmp_inputs.push_back(start); |
501 } | 501 } |
502 tmp_inputs.push_back(loop); | 502 tmp_inputs.push_back(loop); |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
586 | 586 |
587 Node* new_loop0_phi = new_ret->InputAt(0); | 587 Node* new_loop0_phi = new_ret->InputAt(0); |
588 CHECK_EQ(IrOpcode::kPhi, new_loop0_phi->opcode()); | 588 CHECK_EQ(IrOpcode::kPhi, new_loop0_phi->opcode()); |
589 CHECK_EQ(new_loop0_loop, NodeProperties::GetControlInput(new_loop0_phi)); | 589 CHECK_EQ(new_loop0_loop, NodeProperties::GetControlInput(new_loop0_phi)); |
590 CHECK_EQ(new_loop0_phi, FindSuccessor(new_loop0_loop, IrOpcode::kPhi)); | 590 CHECK_EQ(new_loop0_phi, FindSuccessor(new_loop0_loop, IrOpcode::kPhi)); |
591 | 591 |
592 // Check that the return returns the phi from the OSR loop and control | 592 // Check that the return returns the phi from the OSR loop and control |
593 // depends on the copy of the outer loop0. | 593 // depends on the copy of the outer loop0. |
594 CheckInputs(new_ret, new_loop0_phi, T.graph.start(), new_loop0_exit); | 594 CheckInputs(new_ret, new_loop0_phi, T.graph.start(), new_loop0_exit); |
595 } | 595 } |
OLD | NEW |