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 18 matching lines...) Expand all Loading... |
29 if (i0 != NULL) CHECK_EQ(i0, node->InputAt(0)); | 29 if (i0 != NULL) CHECK_EQ(i0, node->InputAt(0)); |
30 if (i1 != NULL) CHECK_EQ(i1, node->InputAt(1)); | 30 if (i1 != NULL) CHECK_EQ(i1, node->InputAt(1)); |
31 if (i2 != NULL) CHECK_EQ(i2, node->InputAt(2)); | 31 if (i2 != NULL) CHECK_EQ(i2, node->InputAt(2)); |
32 if (i3 != NULL) CHECK_EQ(i3, node->InputAt(3)); | 32 if (i3 != NULL) CHECK_EQ(i3, node->InputAt(3)); |
33 return count; | 33 return count; |
34 } | 34 } |
35 | 35 |
36 | 36 |
37 static Operator kIntLt(IrOpcode::kInt32LessThan, Operator::kPure, | 37 static Operator kIntLt(IrOpcode::kInt32LessThan, Operator::kPure, |
38 "Int32LessThan", 2, 0, 0, 1, 0, 0); | 38 "Int32LessThan", 2, 0, 0, 1, 0, 0); |
| 39 static Operator kIntAdd(IrOpcode::kInt32Add, Operator::kPure, "Int32Add", 2, 0, |
| 40 0, 1, 0, 0); |
39 | 41 |
40 | 42 |
41 static const int kMaxOsrValues = 10; | 43 static const int kMaxOsrValues = 10; |
42 | 44 |
43 class OsrDeconstructorTester : public HandleAndZoneScope { | 45 class OsrDeconstructorTester : public HandleAndZoneScope { |
44 public: | 46 public: |
45 explicit OsrDeconstructorTester(int num_values) | 47 explicit OsrDeconstructorTester(int num_values) |
46 : isolate(main_isolate()), | 48 : isolate(main_isolate()), |
47 common(main_zone()), | 49 common(main_zone()), |
48 graph(main_zone()), | 50 graph(main_zone()), |
(...skipping 433 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
482 | 484 |
483 // Check structure of inner loop. | 485 // Check structure of inner loop. |
484 Node* new_inner_loop = FindSuccessor(new_outer_if_true, IrOpcode::kLoop); | 486 Node* new_inner_loop = FindSuccessor(new_outer_if_true, IrOpcode::kLoop); |
485 Node* new_inner_phi = FindSuccessor(new_inner_loop, IrOpcode::kPhi); | 487 Node* new_inner_phi = FindSuccessor(new_inner_loop, IrOpcode::kPhi); |
486 | 488 |
487 CheckInputs(new_inner_phi, T.jsgraph.OneConstant(), T.jsgraph.ZeroConstant(), | 489 CheckInputs(new_inner_phi, T.jsgraph.OneConstant(), T.jsgraph.ZeroConstant(), |
488 new_inner_loop); | 490 new_inner_loop); |
489 CheckInputs(new_outer_phi, new_entry_phi, new_inner_phi, | 491 CheckInputs(new_outer_phi, new_entry_phi, new_inner_phi, |
490 T.jsgraph.ZeroConstant(), new_outer_loop); | 492 T.jsgraph.ZeroConstant(), new_outer_loop); |
491 } | 493 } |
| 494 |
| 495 |
| 496 Node* MakeCounter(JSGraph* jsgraph, Node* start, Node* loop) { |
| 497 int count = loop->InputCount(); |
| 498 NodeVector tmp_inputs(jsgraph->graph()->zone()); |
| 499 for (int i = 0; i < count; i++) { |
| 500 tmp_inputs.push_back(start); |
| 501 } |
| 502 tmp_inputs.push_back(loop); |
| 503 |
| 504 Node* phi = jsgraph->graph()->NewNode( |
| 505 jsgraph->common()->Phi(kMachInt32, count), count + 1, &tmp_inputs[0]); |
| 506 Node* inc = jsgraph->graph()->NewNode(&kIntAdd, phi, jsgraph->OneConstant()); |
| 507 |
| 508 for (int i = 1; i < count; i++) { |
| 509 phi->ReplaceInput(i, inc); |
| 510 } |
| 511 return phi; |
| 512 } |
| 513 |
| 514 |
| 515 TEST(Deconstruct_osr_nested3) { |
| 516 OsrDeconstructorTester T(1); |
| 517 |
| 518 // outermost loop. |
| 519 While loop0(T, T.p0, false, 1); |
| 520 Node* loop0_cntr = MakeCounter(&T.jsgraph, T.p0, loop0.loop); |
| 521 loop0.branch->ReplaceInput(0, loop0_cntr); |
| 522 |
| 523 // middle loop. |
| 524 Node* loop1 = T.graph.NewNode(T.common.Loop(2), loop0.if_true, T.self); |
| 525 loop1->ReplaceInput(0, loop0.if_true); |
| 526 Node* loop1_phi = |
| 527 T.graph.NewNode(T.common.Phi(kMachAnyTagged, 2), loop0_cntr, loop0_cntr); |
| 528 |
| 529 // innermost (OSR) loop. |
| 530 While loop2(T, T.p0, true, 1); |
| 531 loop2.loop->ReplaceInput(0, loop1); |
| 532 |
| 533 Node* loop2_cntr = MakeCounter(&T.jsgraph, loop1_phi, loop2.loop); |
| 534 loop2_cntr->ReplaceInput(1, T.osr_values[0]); |
| 535 Node* osr_phi = loop2_cntr; |
| 536 Node* loop2_inc = loop2_cntr->InputAt(2); |
| 537 loop2.branch->ReplaceInput(0, loop2_cntr); |
| 538 |
| 539 loop1_phi->ReplaceInput(1, loop2_cntr); |
| 540 loop0_cntr->ReplaceInput(1, loop2_cntr); |
| 541 |
| 542 // Branch to either the outer or middle loop. |
| 543 Node* branch = T.graph.NewNode(T.common.Branch(), loop2_cntr, loop2.exit); |
| 544 Node* if_true = T.graph.NewNode(T.common.IfTrue(), branch); |
| 545 Node* if_false = T.graph.NewNode(T.common.IfFalse(), branch); |
| 546 |
| 547 loop0.loop->ReplaceInput(1, if_true); |
| 548 loop1->ReplaceInput(1, if_false); |
| 549 |
| 550 Node* ret = |
| 551 T.graph.NewNode(T.common.Return(), loop0_cntr, T.start, loop0.exit); |
| 552 Node* end = T.graph.NewNode(T.common.End(), ret); |
| 553 T.graph.SetEnd(end); |
| 554 |
| 555 T.DeconstructOsr(); |
| 556 |
| 557 // Check structure of deconstructed graph. |
| 558 // Check loop2 (OSR loop) is directly connected to start. |
| 559 CheckInputs(loop2.loop, T.start, loop2.if_true); |
| 560 CheckInputs(osr_phi, T.osr_values[0], loop2_inc, loop2.loop); |
| 561 CheckInputs(loop2.branch, osr_phi, loop2.loop); |
| 562 CheckInputs(loop2.if_true, loop2.branch); |
| 563 CheckInputs(loop2.exit, loop2.branch); |
| 564 CheckInputs(branch, osr_phi, loop2.exit); |
| 565 CheckInputs(if_true, branch); |
| 566 CheckInputs(if_false, branch); |
| 567 |
| 568 // Check structure of new_loop1. |
| 569 Node* new_loop1_loop = FindSuccessor(if_false, IrOpcode::kLoop); |
| 570 // TODO(titzer): check the internal copy of loop2. |
| 571 USE(new_loop1_loop); |
| 572 |
| 573 // Check structure of new_loop0. |
| 574 Node* new_loop0_loop_entry = FindSuccessor(if_true, IrOpcode::kMerge); |
| 575 Node* new_loop0_loop = FindSuccessor(new_loop0_loop_entry, IrOpcode::kLoop); |
| 576 // TODO(titzer): check the internal copies of loop1 and loop2. |
| 577 |
| 578 Node* new_loop0_branch = FindSuccessor(new_loop0_loop, IrOpcode::kBranch); |
| 579 Node* new_loop0_if_true = FindSuccessor(new_loop0_branch, IrOpcode::kIfTrue); |
| 580 Node* new_loop0_exit = FindSuccessor(new_loop0_branch, IrOpcode::kIfFalse); |
| 581 |
| 582 USE(new_loop0_if_true); |
| 583 |
| 584 Node* new_ret = T.graph.end()->InputAt(0); |
| 585 CHECK_EQ(IrOpcode::kReturn, new_ret->opcode()); |
| 586 |
| 587 Node* new_loop0_phi = new_ret->InputAt(0); |
| 588 CHECK_EQ(IrOpcode::kPhi, new_loop0_phi->opcode()); |
| 589 CHECK_EQ(new_loop0_loop, NodeProperties::GetControlInput(new_loop0_phi)); |
| 590 CHECK_EQ(new_loop0_phi, FindSuccessor(new_loop0_loop, IrOpcode::kPhi)); |
| 591 |
| 592 // Check that the return returns the phi from the OSR loop and control |
| 593 // depends on the copy of the outer loop0. |
| 594 CheckInputs(new_ret, new_loop0_phi, T.graph.start(), new_loop0_exit); |
| 595 } |
OLD | NEW |