| Index: test/cctest/compiler/test-osr.cc
|
| diff --git a/test/cctest/compiler/test-osr.cc b/test/cctest/compiler/test-osr.cc
|
| index 83e0fd0516221ad0bb6976c71d28f8df1a795b5d..d2171188f844e79984625c1d8dac9bfb3f24f709 100644
|
| --- a/test/cctest/compiler/test-osr.cc
|
| +++ b/test/cctest/compiler/test-osr.cc
|
| @@ -36,6 +36,8 @@ static int CheckInputs(Node* node, Node* i0 = NULL, Node* i1 = NULL,
|
|
|
| static Operator kIntLt(IrOpcode::kInt32LessThan, Operator::kPure,
|
| "Int32LessThan", 2, 0, 0, 1, 0, 0);
|
| +static Operator kIntAdd(IrOpcode::kInt32Add, Operator::kPure, "Int32Add", 2, 0,
|
| + 0, 1, 0, 0);
|
|
|
|
|
| static const int kMaxOsrValues = 10;
|
| @@ -489,3 +491,105 @@ TEST(Deconstruct_osr_nested2) {
|
| CheckInputs(new_outer_phi, new_entry_phi, new_inner_phi,
|
| T.jsgraph.ZeroConstant(), new_outer_loop);
|
| }
|
| +
|
| +
|
| +Node* MakeCounter(JSGraph* jsgraph, Node* start, Node* loop) {
|
| + int count = loop->InputCount();
|
| + NodeVector tmp_inputs(jsgraph->graph()->zone());
|
| + for (int i = 0; i < count; i++) {
|
| + tmp_inputs.push_back(start);
|
| + }
|
| + tmp_inputs.push_back(loop);
|
| +
|
| + Node* phi = jsgraph->graph()->NewNode(
|
| + jsgraph->common()->Phi(kMachInt32, count), count + 1, &tmp_inputs[0]);
|
| + Node* inc = jsgraph->graph()->NewNode(&kIntAdd, phi, jsgraph->OneConstant());
|
| +
|
| + for (int i = 1; i < count; i++) {
|
| + phi->ReplaceInput(i, inc);
|
| + }
|
| + return phi;
|
| +}
|
| +
|
| +
|
| +TEST(Deconstruct_osr_nested3) {
|
| + OsrDeconstructorTester T(1);
|
| +
|
| + // outermost loop.
|
| + While loop0(T, T.p0, false, 1);
|
| + Node* loop0_cntr = MakeCounter(&T.jsgraph, T.p0, loop0.loop);
|
| + loop0.branch->ReplaceInput(0, loop0_cntr);
|
| +
|
| + // middle loop.
|
| + Node* loop1 = T.graph.NewNode(T.common.Loop(2), loop0.if_true, T.self);
|
| + loop1->ReplaceInput(0, loop0.if_true);
|
| + Node* loop1_phi =
|
| + T.graph.NewNode(T.common.Phi(kMachAnyTagged, 2), loop0_cntr, loop0_cntr);
|
| +
|
| + // innermost (OSR) loop.
|
| + While loop2(T, T.p0, true, 1);
|
| + loop2.loop->ReplaceInput(0, loop1);
|
| +
|
| + Node* loop2_cntr = MakeCounter(&T.jsgraph, loop1_phi, loop2.loop);
|
| + loop2_cntr->ReplaceInput(1, T.osr_values[0]);
|
| + Node* osr_phi = loop2_cntr;
|
| + Node* loop2_inc = loop2_cntr->InputAt(2);
|
| + loop2.branch->ReplaceInput(0, loop2_cntr);
|
| +
|
| + loop1_phi->ReplaceInput(1, loop2_cntr);
|
| + loop0_cntr->ReplaceInput(1, loop2_cntr);
|
| +
|
| + // Branch to either the outer or middle loop.
|
| + Node* branch = T.graph.NewNode(T.common.Branch(), loop2_cntr, loop2.exit);
|
| + Node* if_true = T.graph.NewNode(T.common.IfTrue(), branch);
|
| + Node* if_false = T.graph.NewNode(T.common.IfFalse(), branch);
|
| +
|
| + loop0.loop->ReplaceInput(1, if_true);
|
| + loop1->ReplaceInput(1, if_false);
|
| +
|
| + Node* ret =
|
| + T.graph.NewNode(T.common.Return(), loop0_cntr, T.start, loop0.exit);
|
| + Node* end = T.graph.NewNode(T.common.End(), ret);
|
| + T.graph.SetEnd(end);
|
| +
|
| + T.DeconstructOsr();
|
| +
|
| + // Check structure of deconstructed graph.
|
| + // Check loop2 (OSR loop) is directly connected to start.
|
| + CheckInputs(loop2.loop, T.start, loop2.if_true);
|
| + CheckInputs(osr_phi, T.osr_values[0], loop2_inc, loop2.loop);
|
| + CheckInputs(loop2.branch, osr_phi, loop2.loop);
|
| + CheckInputs(loop2.if_true, loop2.branch);
|
| + CheckInputs(loop2.exit, loop2.branch);
|
| + CheckInputs(branch, osr_phi, loop2.exit);
|
| + CheckInputs(if_true, branch);
|
| + CheckInputs(if_false, branch);
|
| +
|
| + // Check structure of new_loop1.
|
| + Node* new_loop1_loop = FindSuccessor(if_false, IrOpcode::kLoop);
|
| + // TODO(titzer): check the internal copy of loop2.
|
| + USE(new_loop1_loop);
|
| +
|
| + // Check structure of new_loop0.
|
| + Node* new_loop0_loop_entry = FindSuccessor(if_true, IrOpcode::kMerge);
|
| + Node* new_loop0_loop = FindSuccessor(new_loop0_loop_entry, IrOpcode::kLoop);
|
| + // TODO(titzer): check the internal copies of loop1 and loop2.
|
| +
|
| + Node* new_loop0_branch = FindSuccessor(new_loop0_loop, IrOpcode::kBranch);
|
| + Node* new_loop0_if_true = FindSuccessor(new_loop0_branch, IrOpcode::kIfTrue);
|
| + Node* new_loop0_exit = FindSuccessor(new_loop0_branch, IrOpcode::kIfFalse);
|
| +
|
| + USE(new_loop0_if_true);
|
| +
|
| + Node* new_ret = T.graph.end()->InputAt(0);
|
| + CHECK_EQ(IrOpcode::kReturn, new_ret->opcode());
|
| +
|
| + Node* new_loop0_phi = new_ret->InputAt(0);
|
| + CHECK_EQ(IrOpcode::kPhi, new_loop0_phi->opcode());
|
| + CHECK_EQ(new_loop0_loop, NodeProperties::GetControlInput(new_loop0_phi));
|
| + CHECK_EQ(new_loop0_phi, FindSuccessor(new_loop0_loop, IrOpcode::kPhi));
|
| +
|
| + // Check that the return returns the phi from the OSR loop and control
|
| + // depends on the copy of the outer loop0.
|
| + CheckInputs(new_ret, new_loop0_phi, T.graph.start(), new_loop0_exit);
|
| +}
|
|
|