| OLD | NEW | 
 | (Empty) | 
|     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 |  | 
|     3 // found in the LICENSE file. |  | 
|     4  |  | 
|     5 #include "src/v8.h" |  | 
|     6 #include "test/cctest/cctest.h" |  | 
|     7  |  | 
|     8 #include "src/base/bits.h" |  | 
|     9 #include "src/compiler/all-nodes.h" |  | 
|    10 #include "src/compiler/common-operator.h" |  | 
|    11 #include "src/compiler/control-reducer.h" |  | 
|    12 #include "src/compiler/graph.h" |  | 
|    13 #include "src/compiler/js-graph.h" |  | 
|    14 #include "src/compiler/node-properties.h" |  | 
|    15  |  | 
|    16 using namespace v8::internal; |  | 
|    17 using namespace v8::internal::compiler; |  | 
|    18  |  | 
|    19 static const size_t kNumLeafs = 4; |  | 
|    20  |  | 
|    21 enum Decision { kFalse, kUnknown, kTrue }; |  | 
|    22  |  | 
|    23 // TODO(titzer): convert this whole file into unit tests. |  | 
|    24  |  | 
|    25 static int CheckInputs(Node* node, Node* i0 = NULL, Node* i1 = NULL, |  | 
|    26                        Node* i2 = NULL) { |  | 
|    27   int count = 3; |  | 
|    28   if (i2 == NULL) count = 2; |  | 
|    29   if (i1 == NULL) count = 1; |  | 
|    30   if (i0 == NULL) count = 0; |  | 
|    31   CHECK_EQ(count, node->InputCount()); |  | 
|    32   if (i0 != NULL) CHECK_EQ(i0, node->InputAt(0)); |  | 
|    33   if (i1 != NULL) CHECK_EQ(i1, node->InputAt(1)); |  | 
|    34   if (i2 != NULL) CHECK_EQ(i2, node->InputAt(2)); |  | 
|    35   return count; |  | 
|    36 } |  | 
|    37  |  | 
|    38  |  | 
|    39 static int CheckMerge(Node* node, Node* i0 = NULL, Node* i1 = NULL, |  | 
|    40                       Node* i2 = NULL) { |  | 
|    41   CHECK_EQ(IrOpcode::kMerge, node->opcode()); |  | 
|    42   int count = CheckInputs(node, i0, i1, i2); |  | 
|    43   CHECK_EQ(count, node->op()->ControlInputCount()); |  | 
|    44   return count; |  | 
|    45 } |  | 
|    46  |  | 
|    47  |  | 
|    48 static int CheckLoop(Node* node, Node* i0 = NULL, Node* i1 = NULL, |  | 
|    49                      Node* i2 = NULL) { |  | 
|    50   CHECK_EQ(IrOpcode::kLoop, node->opcode()); |  | 
|    51   int count = CheckInputs(node, i0, i1, i2); |  | 
|    52   CHECK_EQ(count, node->op()->ControlInputCount()); |  | 
|    53   return count; |  | 
|    54 } |  | 
|    55  |  | 
|    56  |  | 
|    57 bool IsUsedBy(Node* a, Node* b) { |  | 
|    58   auto const uses = a->uses(); |  | 
|    59   return std::find(uses.begin(), uses.end(), b) != uses.end(); |  | 
|    60 } |  | 
|    61  |  | 
|    62  |  | 
|    63 // A helper for all tests dealing with ControlTester. |  | 
|    64 class ControlReducerTester : HandleAndZoneScope { |  | 
|    65  public: |  | 
|    66   ControlReducerTester() |  | 
|    67       : isolate(main_isolate()), |  | 
|    68         common(main_zone()), |  | 
|    69         graph(main_zone()), |  | 
|    70         jsgraph(main_isolate(), &graph, &common, NULL, NULL), |  | 
|    71         start(graph.NewNode(common.Start(1))), |  | 
|    72         end(graph.NewNode(common.End(1), start)), |  | 
|    73         p0(graph.NewNode(common.Parameter(0), start)), |  | 
|    74         zero(jsgraph.Int32Constant(0)), |  | 
|    75         one(jsgraph.OneConstant()), |  | 
|    76         half(jsgraph.Constant(0.5)), |  | 
|    77         self(graph.NewNode(common.Int32Constant(0xaabbccdd))), |  | 
|    78         dead(graph.NewNode(common.DeadControl())) { |  | 
|    79     graph.SetEnd(end); |  | 
|    80     graph.SetStart(start); |  | 
|    81     leaf[0] = zero; |  | 
|    82     leaf[1] = one; |  | 
|    83     leaf[2] = half; |  | 
|    84     leaf[3] = p0; |  | 
|    85   } |  | 
|    86  |  | 
|    87   Isolate* isolate; |  | 
|    88   CommonOperatorBuilder common; |  | 
|    89   Graph graph; |  | 
|    90   JSGraph jsgraph; |  | 
|    91   Node* start; |  | 
|    92   Node* end; |  | 
|    93   Node* p0; |  | 
|    94   Node* zero; |  | 
|    95   Node* one; |  | 
|    96   Node* half; |  | 
|    97   Node* self; |  | 
|    98   Node* dead; |  | 
|    99   Node* leaf[kNumLeafs]; |  | 
|   100  |  | 
|   101   Node* Phi(Node* a) { |  | 
|   102     return SetSelfReferences(graph.NewNode(op(1, false), a, start)); |  | 
|   103   } |  | 
|   104  |  | 
|   105   Node* Phi(Node* a, Node* b) { |  | 
|   106     return SetSelfReferences(graph.NewNode(op(2, false), a, b, start)); |  | 
|   107   } |  | 
|   108  |  | 
|   109   Node* Phi(Node* a, Node* b, Node* c) { |  | 
|   110     return SetSelfReferences(graph.NewNode(op(3, false), a, b, c, start)); |  | 
|   111   } |  | 
|   112  |  | 
|   113   Node* Phi(Node* a, Node* b, Node* c, Node* d) { |  | 
|   114     return SetSelfReferences(graph.NewNode(op(4, false), a, b, c, d, start)); |  | 
|   115   } |  | 
|   116  |  | 
|   117   Node* EffectPhi(Node* a) { |  | 
|   118     return SetSelfReferences(graph.NewNode(op(1, true), a, start)); |  | 
|   119   } |  | 
|   120  |  | 
|   121   Node* EffectPhi(Node* a, Node* b) { |  | 
|   122     return SetSelfReferences(graph.NewNode(op(2, true), a, b, start)); |  | 
|   123   } |  | 
|   124  |  | 
|   125   Node* EffectPhi(Node* a, Node* b, Node* c) { |  | 
|   126     return SetSelfReferences(graph.NewNode(op(3, true), a, b, c, start)); |  | 
|   127   } |  | 
|   128  |  | 
|   129   Node* EffectPhi(Node* a, Node* b, Node* c, Node* d) { |  | 
|   130     return SetSelfReferences(graph.NewNode(op(4, true), a, b, c, d, start)); |  | 
|   131   } |  | 
|   132  |  | 
|   133   Node* SetSelfReferences(Node* node) { |  | 
|   134     for (Edge edge : node->input_edges()) { |  | 
|   135       if (edge.to() == self) node->ReplaceInput(edge.index(), node); |  | 
|   136     } |  | 
|   137     return node; |  | 
|   138   } |  | 
|   139  |  | 
|   140   const Operator* op(int count, bool effect) { |  | 
|   141     return effect ? common.EffectPhi(count) : common.Phi(kMachAnyTagged, count); |  | 
|   142   } |  | 
|   143  |  | 
|   144   void ReduceGraph() { ControlReducer::ReduceGraph(main_zone(), &jsgraph); } |  | 
|   145  |  | 
|   146   void ReduceMerge(Node* expect, Node* merge) { |  | 
|   147     Node* result = ControlReducer::ReduceMerge(&jsgraph, merge); |  | 
|   148     CHECK_EQ(expect, result); |  | 
|   149   } |  | 
|   150  |  | 
|   151   void ReduceMergeIterative(Node* expect, Node* merge) { |  | 
|   152     p0->ReplaceInput(0, start);  // hack: parameters may be trimmed. |  | 
|   153     Node* end = graph.NewNode(common.End(1), merge); |  | 
|   154     graph.SetEnd(end); |  | 
|   155     ReduceGraph(); |  | 
|   156     CheckInputs(end, expect); |  | 
|   157   } |  | 
|   158  |  | 
|   159   void ReduceBranch(Decision expected, Node* branch) { |  | 
|   160     Node* control = branch->InputAt(1); |  | 
|   161     for (Node* use : branch->uses()) { |  | 
|   162       if (use->opcode() == IrOpcode::kIfTrue) { |  | 
|   163         Node* result = ControlReducer::ReduceIfNodeForTesting(&jsgraph, use); |  | 
|   164         if (expected == kTrue) CHECK_EQ(control, result); |  | 
|   165         if (expected == kFalse) { |  | 
|   166           CHECK_EQ(IrOpcode::kDeadControl, result->opcode()); |  | 
|   167         } |  | 
|   168         if (expected == kUnknown) CHECK_EQ(use, result); |  | 
|   169       } else if (use->opcode() == IrOpcode::kIfFalse) { |  | 
|   170         Node* result = ControlReducer::ReduceIfNodeForTesting(&jsgraph, use); |  | 
|   171         if (expected == kFalse) CHECK_EQ(control, result); |  | 
|   172         if (expected == kTrue) { |  | 
|   173           CHECK_EQ(IrOpcode::kDeadControl, result->opcode()); |  | 
|   174         } |  | 
|   175         if (expected == kUnknown) CHECK_EQ(use, result); |  | 
|   176       } else { |  | 
|   177         UNREACHABLE(); |  | 
|   178       } |  | 
|   179     } |  | 
|   180   } |  | 
|   181  |  | 
|   182   Node* Return(Node* val, Node* effect, Node* control) { |  | 
|   183     Node* ret = graph.NewNode(common.Return(), val, effect, control); |  | 
|   184     end->ReplaceInput(0, ret); |  | 
|   185     return ret; |  | 
|   186   } |  | 
|   187 }; |  | 
|   188  |  | 
|   189  |  | 
|   190 struct Branch { |  | 
|   191   Node* branch; |  | 
|   192   Node* if_true; |  | 
|   193   Node* if_false; |  | 
|   194  |  | 
|   195   Branch(ControlReducerTester& R, Node* cond, Node* control = NULL) { |  | 
|   196     if (control == NULL) control = R.start; |  | 
|   197     branch = R.graph.NewNode(R.common.Branch(), cond, control); |  | 
|   198     if_true = R.graph.NewNode(R.common.IfTrue(), branch); |  | 
|   199     if_false = R.graph.NewNode(R.common.IfFalse(), branch); |  | 
|   200   } |  | 
|   201 }; |  | 
|   202  |  | 
|   203  |  | 
|   204 // TODO(titzer): use the diamonds from src/compiler/diamond.h here. |  | 
|   205 struct Diamond { |  | 
|   206   Node* branch; |  | 
|   207   Node* if_true; |  | 
|   208   Node* if_false; |  | 
|   209   Node* merge; |  | 
|   210   Node* phi; |  | 
|   211  |  | 
|   212   Diamond(ControlReducerTester& R, Node* cond) { |  | 
|   213     branch = R.graph.NewNode(R.common.Branch(), cond, R.start); |  | 
|   214     if_true = R.graph.NewNode(R.common.IfTrue(), branch); |  | 
|   215     if_false = R.graph.NewNode(R.common.IfFalse(), branch); |  | 
|   216     merge = R.graph.NewNode(R.common.Merge(2), if_true, if_false); |  | 
|   217     phi = NULL; |  | 
|   218   } |  | 
|   219  |  | 
|   220   Diamond(ControlReducerTester& R, Node* cond, Node* tv, Node* fv) { |  | 
|   221     branch = R.graph.NewNode(R.common.Branch(), cond, R.start); |  | 
|   222     if_true = R.graph.NewNode(R.common.IfTrue(), branch); |  | 
|   223     if_false = R.graph.NewNode(R.common.IfFalse(), branch); |  | 
|   224     merge = R.graph.NewNode(R.common.Merge(2), if_true, if_false); |  | 
|   225     phi = R.graph.NewNode(R.common.Phi(kMachAnyTagged, 2), tv, fv, merge); |  | 
|   226   } |  | 
|   227  |  | 
|   228   void chain(Diamond& that) { branch->ReplaceInput(1, that.merge); } |  | 
|   229  |  | 
|   230   // Nest {this} into either the if_true or if_false branch of {that}. |  | 
|   231   void nest(Diamond& that, bool if_true) { |  | 
|   232     if (if_true) { |  | 
|   233       branch->ReplaceInput(1, that.if_true); |  | 
|   234       that.merge->ReplaceInput(0, merge); |  | 
|   235     } else { |  | 
|   236       branch->ReplaceInput(1, that.if_false); |  | 
|   237       that.merge->ReplaceInput(1, merge); |  | 
|   238     } |  | 
|   239   } |  | 
|   240 }; |  | 
|   241  |  | 
|   242  |  | 
|   243 struct While { |  | 
|   244   Node* branch; |  | 
|   245   Node* if_true; |  | 
|   246   Node* exit; |  | 
|   247   Node* loop; |  | 
|   248  |  | 
|   249   While(ControlReducerTester& R, Node* cond) { |  | 
|   250     loop = R.graph.NewNode(R.common.Loop(2), R.start, R.start); |  | 
|   251     branch = R.graph.NewNode(R.common.Branch(), cond, loop); |  | 
|   252     if_true = R.graph.NewNode(R.common.IfTrue(), branch); |  | 
|   253     exit = R.graph.NewNode(R.common.IfFalse(), branch); |  | 
|   254     loop->ReplaceInput(1, if_true); |  | 
|   255   } |  | 
|   256  |  | 
|   257   void chain(Node* control) { loop->ReplaceInput(0, control); } |  | 
|   258 }; |  | 
|   259  |  | 
|   260  |  | 
|   261 // Helper for checking that nodes are *not* reachable from end. |  | 
|   262 struct DeadChecker { |  | 
|   263   Zone zone; |  | 
|   264   AllNodes nodes; |  | 
|   265   explicit DeadChecker(Graph* graph) : zone(), nodes(&zone, graph) {} |  | 
|   266  |  | 
|   267   void Check(Node* node) { CHECK(!nodes.IsLive(node)); } |  | 
|   268  |  | 
|   269   void Check(Diamond& d) { |  | 
|   270     Check(d.branch); |  | 
|   271     Check(d.if_true); |  | 
|   272     Check(d.if_false); |  | 
|   273     Check(d.merge); |  | 
|   274     if (d.phi != NULL) Check(d.phi); |  | 
|   275   } |  | 
|   276  |  | 
|   277   void CheckLive(Diamond& d, bool live_phi = true) { |  | 
|   278     CheckInputs(d.merge, d.if_true, d.if_false); |  | 
|   279     CheckInputs(d.if_true, d.branch); |  | 
|   280     CheckInputs(d.if_false, d.branch); |  | 
|   281     if (d.phi != NULL) { |  | 
|   282       if (live_phi) { |  | 
|   283         CHECK_EQ(3, d.phi->InputCount()); |  | 
|   284         CHECK_EQ(d.merge, d.phi->InputAt(2)); |  | 
|   285       } else { |  | 
|   286         Check(d.phi); |  | 
|   287       } |  | 
|   288     } |  | 
|   289   } |  | 
|   290 }; |  | 
|   291  |  | 
|   292  |  | 
|   293 TEST(CMergeReduce_simple1) { |  | 
|   294   ControlReducerTester R; |  | 
|   295  |  | 
|   296   Node* merge = R.graph.NewNode(R.common.Merge(1), R.start); |  | 
|   297   R.ReduceMerge(R.start, merge); |  | 
|   298 } |  | 
|   299  |  | 
|   300  |  | 
|   301 TEST(CMergeReduce_simple2) { |  | 
|   302   ControlReducerTester R; |  | 
|   303  |  | 
|   304   Node* merge1 = R.graph.NewNode(R.common.Merge(1), R.start); |  | 
|   305   Node* merge2 = R.graph.NewNode(R.common.Merge(1), merge1); |  | 
|   306   R.ReduceMerge(merge1, merge2); |  | 
|   307   R.ReduceMergeIterative(R.start, merge2); |  | 
|   308 } |  | 
|   309  |  | 
|   310  |  | 
|   311 TEST(CMergeReduce_none1) { |  | 
|   312   ControlReducerTester R; |  | 
|   313  |  | 
|   314   Node* merge = R.graph.NewNode(R.common.Merge(2), R.start, R.start); |  | 
|   315   R.ReduceMerge(merge, merge); |  | 
|   316 } |  | 
|   317  |  | 
|   318  |  | 
|   319 TEST(CMergeReduce_none2) { |  | 
|   320   ControlReducerTester R; |  | 
|   321  |  | 
|   322   Node* t1 = R.graph.NewNode(R.common.IfTrue(), R.start); |  | 
|   323   Node* t2 = R.graph.NewNode(R.common.IfTrue(), R.start); |  | 
|   324   Node* merge = R.graph.NewNode(R.common.Merge(2), t1, t2); |  | 
|   325   R.ReduceMerge(merge, merge); |  | 
|   326 } |  | 
|   327  |  | 
|   328  |  | 
|   329 TEST(CMergeReduce_self3) { |  | 
|   330   ControlReducerTester R; |  | 
|   331  |  | 
|   332   Node* merge = |  | 
|   333       R.SetSelfReferences(R.graph.NewNode(R.common.Merge(2), R.start, R.self)); |  | 
|   334   R.ReduceMerge(merge, merge); |  | 
|   335 } |  | 
|   336  |  | 
|   337  |  | 
|   338 TEST(CMergeReduce_dead1) { |  | 
|   339   ControlReducerTester R; |  | 
|   340  |  | 
|   341   Node* merge = R.graph.NewNode(R.common.Merge(2), R.start, R.dead); |  | 
|   342   R.ReduceMerge(R.start, merge); |  | 
|   343 } |  | 
|   344  |  | 
|   345  |  | 
|   346 TEST(CMergeReduce_dead2) { |  | 
|   347   ControlReducerTester R; |  | 
|   348  |  | 
|   349   Node* merge1 = R.graph.NewNode(R.common.Merge(1), R.start); |  | 
|   350   Node* merge2 = R.graph.NewNode(R.common.Merge(2), merge1, R.dead); |  | 
|   351   R.ReduceMerge(merge1, merge2); |  | 
|   352   R.ReduceMergeIterative(R.start, merge2); |  | 
|   353 } |  | 
|   354  |  | 
|   355  |  | 
|   356 TEST(CMergeReduce_dead_rm1a) { |  | 
|   357   ControlReducerTester R; |  | 
|   358  |  | 
|   359   for (int i = 0; i < 3; i++) { |  | 
|   360     Node* merge = R.graph.NewNode(R.common.Merge(3), R.start, R.start, R.start); |  | 
|   361     merge->ReplaceInput(i, R.dead); |  | 
|   362     R.ReduceMerge(merge, merge); |  | 
|   363     CheckMerge(merge, R.start, R.start); |  | 
|   364   } |  | 
|   365 } |  | 
|   366  |  | 
|   367  |  | 
|   368 TEST(CMergeReduce_dead_rm1b) { |  | 
|   369   ControlReducerTester R; |  | 
|   370  |  | 
|   371   Node* t = R.graph.NewNode(R.common.IfTrue(), R.start); |  | 
|   372   Node* f = R.graph.NewNode(R.common.IfTrue(), R.start); |  | 
|   373   for (int i = 0; i < 2; i++) { |  | 
|   374     for (int j = i + 1; j < 3; j++) { |  | 
|   375       Node* merge = R.graph.NewNode(R.common.Merge(3), R.dead, R.dead, R.dead); |  | 
|   376       merge->ReplaceInput(i, t); |  | 
|   377       merge->ReplaceInput(j, f); |  | 
|   378       R.ReduceMerge(merge, merge); |  | 
|   379       CheckMerge(merge, t, f); |  | 
|   380     } |  | 
|   381   } |  | 
|   382 } |  | 
|   383  |  | 
|   384  |  | 
|   385 TEST(CMergeReduce_dead_rm2) { |  | 
|   386   ControlReducerTester R; |  | 
|   387  |  | 
|   388   for (int i = 0; i < 3; i++) { |  | 
|   389     Node* merge = R.graph.NewNode(R.common.Merge(3), R.dead, R.dead, R.dead); |  | 
|   390     merge->ReplaceInput(i, R.start); |  | 
|   391     R.ReduceMerge(R.start, merge); |  | 
|   392   } |  | 
|   393 } |  | 
|   394  |  | 
|   395  |  | 
|   396 TEST(CLoopReduce_dead_rm1) { |  | 
|   397   ControlReducerTester R; |  | 
|   398  |  | 
|   399   for (int i = 0; i < 3; i++) { |  | 
|   400     Node* loop = R.graph.NewNode(R.common.Loop(3), R.dead, R.start, R.start); |  | 
|   401     R.ReduceMerge(loop, loop); |  | 
|   402     CheckLoop(loop, R.start, R.start); |  | 
|   403   } |  | 
|   404 } |  | 
|   405  |  | 
|   406  |  | 
|   407 TEST(CMergeReduce_edit_phi1) { |  | 
|   408   ControlReducerTester R; |  | 
|   409  |  | 
|   410   for (int i = 0; i < 3; i++) { |  | 
|   411     Node* merge = R.graph.NewNode(R.common.Merge(3), R.start, R.start, R.start); |  | 
|   412     merge->ReplaceInput(i, R.dead); |  | 
|   413     Node* phi = R.graph.NewNode(R.common.Phi(kMachAnyTagged, 3), R.leaf[0], |  | 
|   414                                 R.leaf[1], R.leaf[2], merge); |  | 
|   415     R.ReduceMerge(merge, merge); |  | 
|   416     CHECK_EQ(IrOpcode::kPhi, phi->opcode()); |  | 
|   417     CHECK_EQ(2, phi->op()->ValueInputCount()); |  | 
|   418     CHECK_EQ(3, phi->InputCount()); |  | 
|   419     CHECK_EQ(R.leaf[i < 1 ? 1 : 0], phi->InputAt(0)); |  | 
|   420     CHECK_EQ(R.leaf[i < 2 ? 2 : 1], phi->InputAt(1)); |  | 
|   421     CHECK_EQ(merge, phi->InputAt(2)); |  | 
|   422   } |  | 
|   423 } |  | 
|   424  |  | 
|   425  |  | 
|   426 TEST(CMergeReduce_edit_effect_phi1) { |  | 
|   427   ControlReducerTester R; |  | 
|   428  |  | 
|   429   for (int i = 0; i < 3; i++) { |  | 
|   430     Node* merge = R.graph.NewNode(R.common.Merge(3), R.start, R.start, R.start); |  | 
|   431     merge->ReplaceInput(i, R.dead); |  | 
|   432     Node* phi = R.graph.NewNode(R.common.EffectPhi(3), R.leaf[0], R.leaf[1], |  | 
|   433                                 R.leaf[2], merge); |  | 
|   434     R.ReduceMerge(merge, merge); |  | 
|   435     CHECK_EQ(IrOpcode::kEffectPhi, phi->opcode()); |  | 
|   436     CHECK_EQ(0, phi->op()->ValueInputCount()); |  | 
|   437     CHECK_EQ(2, phi->op()->EffectInputCount()); |  | 
|   438     CHECK_EQ(3, phi->InputCount()); |  | 
|   439     CHECK_EQ(R.leaf[i < 1 ? 1 : 0], phi->InputAt(0)); |  | 
|   440     CHECK_EQ(R.leaf[i < 2 ? 2 : 1], phi->InputAt(1)); |  | 
|   441     CHECK_EQ(merge, phi->InputAt(2)); |  | 
|   442   } |  | 
|   443 } |  | 
|   444  |  | 
|   445  |  | 
|   446 static const int kSelectorSize = 4; |  | 
|   447  |  | 
|   448 // Helper to select K of N nodes according to a mask, useful for the test below. |  | 
|   449 struct Selector { |  | 
|   450   int mask; |  | 
|   451   int count; |  | 
|   452   explicit Selector(int m) { |  | 
|   453     mask = m; |  | 
|   454     count = v8::base::bits::CountPopulation32(m); |  | 
|   455   } |  | 
|   456   bool is_selected(int i) { return (mask & (1 << i)) != 0; } |  | 
|   457   void CheckNode(Node* node, IrOpcode::Value opcode, Node** inputs, |  | 
|   458                  Node* control) { |  | 
|   459     CHECK_EQ(opcode, node->opcode()); |  | 
|   460     CHECK_EQ(count + (control != NULL ? 1 : 0), node->InputCount()); |  | 
|   461     int index = 0; |  | 
|   462     for (int i = 0; i < kSelectorSize; i++) { |  | 
|   463       if (mask & (1 << i)) { |  | 
|   464         CHECK_EQ(inputs[i], node->InputAt(index++)); |  | 
|   465       } |  | 
|   466     } |  | 
|   467     CHECK_EQ(count, index); |  | 
|   468     if (control != NULL) CHECK_EQ(control, node->InputAt(index++)); |  | 
|   469   } |  | 
|   470   int single_index() { |  | 
|   471     CHECK_EQ(1, count); |  | 
|   472     return WhichPowerOf2(mask); |  | 
|   473   } |  | 
|   474 }; |  | 
|   475  |  | 
|   476  |  | 
|   477 TEST(CMergeReduce_exhaustive_4) { |  | 
|   478   ControlReducerTester R; |  | 
|   479   Node* controls[] = { |  | 
|   480       R.graph.NewNode(R.common.Start(1)), R.graph.NewNode(R.common.Start(2)), |  | 
|   481       R.graph.NewNode(R.common.Start(3)), R.graph.NewNode(R.common.Start(4))}; |  | 
|   482   Node* values[] = {R.jsgraph.Int32Constant(11), R.jsgraph.Int32Constant(22), |  | 
|   483                     R.jsgraph.Int32Constant(33), R.jsgraph.Int32Constant(44)}; |  | 
|   484   Node* effects[] = { |  | 
|   485       R.jsgraph.Float64Constant(123.4), R.jsgraph.Float64Constant(223.4), |  | 
|   486       R.jsgraph.Float64Constant(323.4), R.jsgraph.Float64Constant(423.4)}; |  | 
|   487  |  | 
|   488   for (int mask = 0; mask < (1 << (kSelectorSize - 1)); mask++) { |  | 
|   489     // Reduce a single merge with a given mask. |  | 
|   490     Node* merge = R.graph.NewNode(R.common.Merge(4), controls[0], controls[1], |  | 
|   491                                   controls[2], controls[3]); |  | 
|   492     Node* phi = R.graph.NewNode(R.common.Phi(kMachAnyTagged, 4), values[0], |  | 
|   493                                 values[1], values[2], values[3], merge); |  | 
|   494     Node* ephi = R.graph.NewNode(R.common.EffectPhi(4), effects[0], effects[1], |  | 
|   495                                  effects[2], effects[3], merge); |  | 
|   496  |  | 
|   497     Node* phi_use = |  | 
|   498         R.graph.NewNode(R.common.Phi(kMachAnyTagged, 1), phi, R.start); |  | 
|   499     Node* ephi_use = R.graph.NewNode(R.common.EffectPhi(1), ephi, R.start); |  | 
|   500  |  | 
|   501     Selector selector(mask); |  | 
|   502  |  | 
|   503     for (int i = 0; i < kSelectorSize; i++) {  // set up dead merge inputs. |  | 
|   504       if (!selector.is_selected(i)) merge->ReplaceInput(i, R.dead); |  | 
|   505     } |  | 
|   506  |  | 
|   507     Node* result = ControlReducer::ReduceMerge(&R.jsgraph, merge); |  | 
|   508  |  | 
|   509     int count = selector.count; |  | 
|   510     if (count == 0) { |  | 
|   511       // result should be dead. |  | 
|   512       CHECK_EQ(IrOpcode::kDeadControl, result->opcode()); |  | 
|   513     } else if (count == 1) { |  | 
|   514       // merge should be replaced with one of the controls. |  | 
|   515       CHECK_EQ(controls[selector.single_index()], result); |  | 
|   516       // Phis should have been directly replaced. |  | 
|   517       CHECK_EQ(values[selector.single_index()], phi_use->InputAt(0)); |  | 
|   518       CHECK_EQ(effects[selector.single_index()], ephi_use->InputAt(0)); |  | 
|   519     } else { |  | 
|   520       // Otherwise, nodes should be edited in place. |  | 
|   521       CHECK_EQ(merge, result); |  | 
|   522       selector.CheckNode(merge, IrOpcode::kMerge, controls, NULL); |  | 
|   523       selector.CheckNode(phi, IrOpcode::kPhi, values, merge); |  | 
|   524       selector.CheckNode(ephi, IrOpcode::kEffectPhi, effects, merge); |  | 
|   525       CHECK_EQ(phi, phi_use->InputAt(0)); |  | 
|   526       CHECK_EQ(ephi, ephi_use->InputAt(0)); |  | 
|   527       CHECK_EQ(count, phi->op()->ValueInputCount()); |  | 
|   528       CHECK_EQ(count + 1, phi->InputCount()); |  | 
|   529       CHECK_EQ(count, ephi->op()->EffectInputCount()); |  | 
|   530       CHECK_EQ(count + 1, ephi->InputCount()); |  | 
|   531     } |  | 
|   532   } |  | 
|   533 } |  | 
|   534  |  | 
|   535  |  | 
|   536 TEST(CMergeReduce_edit_many_phis1) { |  | 
|   537   ControlReducerTester R; |  | 
|   538  |  | 
|   539   const int kPhiCount = 10; |  | 
|   540   Node* phis[kPhiCount]; |  | 
|   541  |  | 
|   542   for (int i = 0; i < 3; i++) { |  | 
|   543     Node* merge = R.graph.NewNode(R.common.Merge(3), R.start, R.start, R.start); |  | 
|   544     merge->ReplaceInput(i, R.dead); |  | 
|   545     for (int j = 0; j < kPhiCount; j++) { |  | 
|   546       phis[j] = R.graph.NewNode(R.common.Phi(kMachAnyTagged, 3), R.leaf[0], |  | 
|   547                                 R.leaf[1], R.leaf[2], merge); |  | 
|   548     } |  | 
|   549     R.ReduceMerge(merge, merge); |  | 
|   550     for (int j = 0; j < kPhiCount; j++) { |  | 
|   551       Node* phi = phis[j]; |  | 
|   552       CHECK_EQ(IrOpcode::kPhi, phi->opcode()); |  | 
|   553       CHECK_EQ(2, phi->op()->ValueInputCount()); |  | 
|   554       CHECK_EQ(3, phi->InputCount()); |  | 
|   555       CHECK_EQ(R.leaf[i < 1 ? 1 : 0], phi->InputAt(0)); |  | 
|   556       CHECK_EQ(R.leaf[i < 2 ? 2 : 1], phi->InputAt(1)); |  | 
|   557       CHECK_EQ(merge, phi->InputAt(2)); |  | 
|   558     } |  | 
|   559   } |  | 
|   560 } |  | 
|   561  |  | 
|   562  |  | 
|   563 TEST(CMergeReduce_simple_chain1) { |  | 
|   564   ControlReducerTester R; |  | 
|   565   for (int i = 0; i < 5; i++) { |  | 
|   566     Node* merge = R.graph.NewNode(R.common.Merge(1), R.start); |  | 
|   567     for (int j = 0; j < i; j++) { |  | 
|   568       merge = R.graph.NewNode(R.common.Merge(1), merge); |  | 
|   569     } |  | 
|   570     R.ReduceMergeIterative(R.start, merge); |  | 
|   571   } |  | 
|   572 } |  | 
|   573  |  | 
|   574  |  | 
|   575 TEST(CMergeReduce_dead_chain1) { |  | 
|   576   ControlReducerTester R; |  | 
|   577   for (int i = 0; i < 5; i++) { |  | 
|   578     Node* merge = R.graph.NewNode(R.common.Merge(1), R.dead); |  | 
|   579     for (int j = 0; j < i; j++) { |  | 
|   580       merge = R.graph.NewNode(R.common.Merge(1), merge); |  | 
|   581     } |  | 
|   582     Node* end = R.graph.NewNode(R.common.End(1), merge); |  | 
|   583     R.graph.SetEnd(end); |  | 
|   584     R.ReduceGraph(); |  | 
|   585     CHECK(merge->IsDead()); |  | 
|   586     CHECK(!end->InputAt(0));  // end dies. |  | 
|   587   } |  | 
|   588 } |  | 
|   589  |  | 
|   590  |  | 
|   591 TEST(CMergeReduce_dead_chain2) { |  | 
|   592   ControlReducerTester R; |  | 
|   593   for (int i = 0; i < 5; i++) { |  | 
|   594     Node* merge = R.graph.NewNode(R.common.Merge(1), R.start); |  | 
|   595     for (int j = 0; j < i; j++) { |  | 
|   596       merge = R.graph.NewNode(R.common.Merge(2), merge, R.dead); |  | 
|   597     } |  | 
|   598     R.ReduceMergeIterative(R.start, merge); |  | 
|   599   } |  | 
|   600 } |  | 
|   601  |  | 
|   602  |  | 
|   603 TEST(CBranchReduce_none1) { |  | 
|   604   ControlReducerTester R; |  | 
|   605   Diamond d(R, R.p0); |  | 
|   606   R.ReduceBranch(kUnknown, d.branch); |  | 
|   607 } |  | 
|   608  |  | 
|   609  |  | 
|   610 TEST(CBranchReduce_none2) { |  | 
|   611   ControlReducerTester R; |  | 
|   612   Diamond d1(R, R.p0); |  | 
|   613   Diamond d2(R, R.p0); |  | 
|   614   d2.chain(d1); |  | 
|   615   R.ReduceBranch(kUnknown, d2.branch); |  | 
|   616 } |  | 
|   617  |  | 
|   618  |  | 
|   619 TEST(CBranchReduce_true) { |  | 
|   620   ControlReducerTester R; |  | 
|   621   Node* true_values[] = {R.jsgraph.Int32Constant(2), |  | 
|   622                          R.jsgraph.Int64Constant(0x7fffffff), |  | 
|   623                          R.jsgraph.TrueConstant()}; |  | 
|   624   for (size_t i = 0; i < arraysize(true_values); i++) { |  | 
|   625     Diamond d(R, true_values[i]); |  | 
|   626     R.ReduceBranch(kTrue, d.branch); |  | 
|   627   } |  | 
|   628 } |  | 
|   629  |  | 
|   630  |  | 
|   631 TEST(CBranchReduce_false) { |  | 
|   632   ControlReducerTester R; |  | 
|   633   Node* false_values[] = {R.jsgraph.Int32Constant(0), |  | 
|   634                           R.jsgraph.Int64Constant(0), |  | 
|   635                           R.jsgraph.FalseConstant()}; |  | 
|   636   for (size_t i = 0; i < arraysize(false_values); i++) { |  | 
|   637     Diamond d(R, false_values[i]); |  | 
|   638     R.ReduceBranch(kFalse, d.branch); |  | 
|   639   } |  | 
|   640 } |  | 
|   641  |  | 
|   642  |  | 
|   643 TEST(CDiamondReduce_true) { |  | 
|   644   ControlReducerTester R; |  | 
|   645   Diamond d1(R, R.jsgraph.TrueConstant()); |  | 
|   646   R.ReduceMergeIterative(R.start, d1.merge); |  | 
|   647 } |  | 
|   648  |  | 
|   649  |  | 
|   650 TEST(CDiamondReduce_false) { |  | 
|   651   ControlReducerTester R; |  | 
|   652   Diamond d2(R, R.jsgraph.FalseConstant()); |  | 
|   653   R.ReduceMergeIterative(R.start, d2.merge); |  | 
|   654 } |  | 
|   655  |  | 
|   656  |  | 
|   657 TEST(CChainedDiamondsReduce_true_false) { |  | 
|   658   ControlReducerTester R; |  | 
|   659   Diamond d1(R, R.jsgraph.TrueConstant()); |  | 
|   660   Diamond d2(R, R.jsgraph.FalseConstant()); |  | 
|   661   d2.chain(d1); |  | 
|   662  |  | 
|   663   R.ReduceMergeIterative(R.start, d2.merge); |  | 
|   664 } |  | 
|   665  |  | 
|   666  |  | 
|   667 TEST(CChainedDiamondsReduce_x_false) { |  | 
|   668   ControlReducerTester R; |  | 
|   669   Diamond d1(R, R.p0); |  | 
|   670   Diamond d2(R, R.jsgraph.FalseConstant()); |  | 
|   671   d2.chain(d1); |  | 
|   672  |  | 
|   673   R.ReduceMergeIterative(R.start, d2.merge); |  | 
|   674 } |  | 
|   675  |  | 
|   676  |  | 
|   677 TEST(CChainedDiamondsReduce_false_x) { |  | 
|   678   ControlReducerTester R; |  | 
|   679   Diamond d1(R, R.zero); |  | 
|   680   Diamond d2(R, R.p0); |  | 
|   681   d2.chain(d1); |  | 
|   682  |  | 
|   683   R.ReduceMergeIterative(R.start, d2.merge); |  | 
|   684 } |  | 
|   685  |  | 
|   686  |  | 
|   687 TEST(CChainedDiamondsReduce_phi1) { |  | 
|   688   ControlReducerTester R; |  | 
|   689   Diamond d1(R, R.zero, R.one, R.zero);  // foldable branch, phi. |  | 
|   690   Diamond d2(R, d1.phi); |  | 
|   691   d2.chain(d1); |  | 
|   692  |  | 
|   693   R.ReduceMergeIterative(R.start, d2.merge); |  | 
|   694 } |  | 
|   695  |  | 
|   696  |  | 
|   697 TEST(CNestedDiamondsReduce_true_true_false) { |  | 
|   698   ControlReducerTester R; |  | 
|   699   Diamond d1(R, R.jsgraph.TrueConstant()); |  | 
|   700   Diamond d2(R, R.jsgraph.FalseConstant()); |  | 
|   701   d2.nest(d1, true); |  | 
|   702  |  | 
|   703   R.ReduceMergeIterative(R.start, d1.merge); |  | 
|   704 } |  | 
|   705  |  | 
|   706  |  | 
|   707 TEST(CNestedDiamondsReduce_false_true_false) { |  | 
|   708   ControlReducerTester R; |  | 
|   709   Diamond d1(R, R.jsgraph.TrueConstant()); |  | 
|   710   Diamond d2(R, R.jsgraph.FalseConstant()); |  | 
|   711   d2.nest(d1, false); |  | 
|   712  |  | 
|   713   R.ReduceMergeIterative(R.start, d1.merge); |  | 
|   714 } |  | 
|   715  |  | 
|   716  |  | 
|   717 TEST(CNestedDiamonds_xyz) { |  | 
|   718   ControlReducerTester R; |  | 
|   719  |  | 
|   720   for (int a = 0; a < 2; a++) { |  | 
|   721     for (int b = 0; b < 2; b++) { |  | 
|   722       for (int c = 0; c < 2; c++) { |  | 
|   723         Diamond d1(R, R.jsgraph.Int32Constant(a)); |  | 
|   724         Diamond d2(R, R.jsgraph.Int32Constant(b)); |  | 
|   725         d2.nest(d1, c); |  | 
|   726  |  | 
|   727         R.ReduceMergeIterative(R.start, d1.merge); |  | 
|   728       } |  | 
|   729     } |  | 
|   730   } |  | 
|   731 } |  | 
|   732  |  | 
|   733  |  | 
|   734 TEST(CUnusedDiamond1) { |  | 
|   735   ControlReducerTester R; |  | 
|   736   // if (p0) { } else { } |  | 
|   737   Node* branch = R.graph.NewNode(R.common.Branch(), R.p0, R.start); |  | 
|   738   Node* if_true = R.graph.NewNode(R.common.IfTrue(), branch); |  | 
|   739   Node* if_false = R.graph.NewNode(R.common.IfFalse(), branch); |  | 
|   740   Node* merge = R.graph.NewNode(R.common.Merge(2), if_true, if_false); |  | 
|   741   R.ReduceMergeIterative(R.start, merge); |  | 
|   742 } |  | 
|   743  |  | 
|   744  |  | 
|   745 TEST(CUnusedDiamond2) { |  | 
|   746   ControlReducerTester R; |  | 
|   747   // if (p0) { } else { } |  | 
|   748   Node* branch = R.graph.NewNode(R.common.Branch(), R.p0, R.start); |  | 
|   749   Node* if_true = R.graph.NewNode(R.common.IfTrue(), branch); |  | 
|   750   Node* if_false = R.graph.NewNode(R.common.IfFalse(), branch); |  | 
|   751   Node* merge = R.graph.NewNode(R.common.Merge(2), if_false, if_true); |  | 
|   752   R.ReduceMergeIterative(R.start, merge); |  | 
|   753 } |  | 
|   754  |  | 
|   755  |  | 
|   756 TEST(CDeadLoop1) { |  | 
|   757   ControlReducerTester R; |  | 
|   758  |  | 
|   759   While w(R, R.p0); |  | 
|   760   Diamond d(R, R.zero); |  | 
|   761   // if (0) { while (p0) ; } else { } |  | 
|   762   w.branch->ReplaceInput(1, d.if_true); |  | 
|   763   d.merge->ReplaceInput(0, w.exit); |  | 
|   764  |  | 
|   765   R.ReduceMergeIterative(R.start, d.merge); |  | 
|   766  |  | 
|   767   DeadChecker dead(&R.graph); |  | 
|   768   dead.Check(d); |  | 
|   769   dead.Check(w.loop); |  | 
|   770 } |  | 
|   771  |  | 
|   772  |  | 
|   773 TEST(Return1) { |  | 
|   774   ControlReducerTester R; |  | 
|   775   Node* ret = R.Return(R.one, R.start, R.start); |  | 
|   776   R.ReduceGraph(); |  | 
|   777   CheckInputs(R.graph.end(), ret); |  | 
|   778   CheckInputs(ret, R.one, R.start, R.start); |  | 
|   779 } |  | 
|   780  |  | 
|   781  |  | 
|   782 TEST(Return2) { |  | 
|   783   ControlReducerTester R; |  | 
|   784   Diamond d(R, R.jsgraph.TrueConstant()); |  | 
|   785   Node* ret = R.Return(R.half, R.start, d.merge); |  | 
|   786   R.ReduceGraph(); |  | 
|   787  |  | 
|   788   DeadChecker dead(&R.graph); |  | 
|   789   dead.Check(d.branch); |  | 
|   790   dead.Check(d.if_true); |  | 
|   791   dead.Check(d.if_false); |  | 
|   792   dead.Check(d.merge); |  | 
|   793  |  | 
|   794   CheckInputs(R.graph.end(), ret); |  | 
|   795   CheckInputs(ret, R.half, R.start, R.start); |  | 
|   796 } |  | 
|   797  |  | 
|   798  |  | 
|   799 TEST(Return_true1) { |  | 
|   800   ControlReducerTester R; |  | 
|   801   Diamond d(R, R.jsgraph.TrueConstant(), R.half, R.zero); |  | 
|   802   Node* ret = R.Return(d.phi, R.start, d.merge); |  | 
|   803   R.ReduceGraph(); |  | 
|   804  |  | 
|   805   DeadChecker dead(&R.graph); |  | 
|   806   dead.Check(d.branch); |  | 
|   807   dead.Check(d.if_true); |  | 
|   808   dead.Check(d.if_false); |  | 
|   809   dead.Check(d.merge); |  | 
|   810   dead.Check(d.phi); |  | 
|   811  |  | 
|   812   CheckInputs(R.graph.end(), ret); |  | 
|   813   CheckInputs(ret, R.half, R.start, R.start); |  | 
|   814 } |  | 
|   815  |  | 
|   816  |  | 
|   817 TEST(Return_false1) { |  | 
|   818   ControlReducerTester R; |  | 
|   819   Diamond d(R, R.jsgraph.FalseConstant(), R.one, R.half); |  | 
|   820   Node* ret = R.Return(d.phi, R.start, d.merge); |  | 
|   821   R.ReduceGraph(); |  | 
|   822  |  | 
|   823   DeadChecker dead(&R.graph); |  | 
|   824   dead.Check(d.branch); |  | 
|   825   dead.Check(d.if_true); |  | 
|   826   dead.Check(d.if_false); |  | 
|   827   dead.Check(d.merge); |  | 
|   828   dead.Check(d.phi); |  | 
|   829  |  | 
|   830   CheckInputs(R.graph.end(), ret); |  | 
|   831   CheckInputs(ret, R.half, R.start, R.start); |  | 
|   832 } |  | 
|   833  |  | 
|   834  |  | 
|   835 TEST(Return_effect1) { |  | 
|   836   ControlReducerTester R; |  | 
|   837   Diamond d(R, R.jsgraph.TrueConstant()); |  | 
|   838   Node* e1 = R.jsgraph.Float64Constant(-100.1); |  | 
|   839   Node* e2 = R.jsgraph.Float64Constant(+100.1); |  | 
|   840   Node* effect = R.graph.NewNode(R.common.EffectPhi(2), e1, e2, d.merge); |  | 
|   841   Node* ret = R.Return(R.p0, effect, d.merge); |  | 
|   842   R.ReduceGraph(); |  | 
|   843  |  | 
|   844   DeadChecker dead(&R.graph); |  | 
|   845   dead.Check(d); |  | 
|   846   dead.Check(effect); |  | 
|   847  |  | 
|   848   CheckInputs(R.graph.end(), ret); |  | 
|   849   CheckInputs(ret, R.p0, e1, R.start); |  | 
|   850 } |  | 
|   851  |  | 
|   852  |  | 
|   853 TEST(Return_nested_diamonds1) { |  | 
|   854   ControlReducerTester R; |  | 
|   855   Diamond d2(R, R.p0, R.one, R.zero); |  | 
|   856   Diamond d3(R, R.p0, R.one, R.zero); |  | 
|   857   Diamond d1(R, R.p0, d2.phi, d3.phi); |  | 
|   858  |  | 
|   859   d2.nest(d1, true); |  | 
|   860   d3.nest(d1, false); |  | 
|   861  |  | 
|   862   Node* ret = R.Return(d1.phi, R.start, d1.merge); |  | 
|   863  |  | 
|   864   R.ReduceGraph();  // nothing should happen. |  | 
|   865  |  | 
|   866   CheckInputs(ret, d1.phi, R.start, d1.merge); |  | 
|   867   CheckInputs(d1.phi, d2.phi, d3.phi, d1.merge); |  | 
|   868   CheckInputs(d1.merge, d2.merge, d3.merge); |  | 
|   869  |  | 
|   870   DeadChecker dead(&R.graph); |  | 
|   871   dead.CheckLive(d2); |  | 
|   872   dead.CheckLive(d3); |  | 
|   873 } |  | 
|   874  |  | 
|   875  |  | 
|   876 TEST(Return_nested_diamonds1_dead1) { |  | 
|   877   ControlReducerTester R; |  | 
|   878   Diamond d2(R, R.p0);  // dead diamond |  | 
|   879   Diamond d3(R, R.p0, R.one, R.zero); |  | 
|   880   Diamond d1(R, R.p0, R.one, d3.phi); |  | 
|   881  |  | 
|   882   d2.nest(d1, true); |  | 
|   883   d3.nest(d1, false); |  | 
|   884  |  | 
|   885   Node* ret = R.Return(d1.phi, R.start, d1.merge); |  | 
|   886  |  | 
|   887   R.ReduceGraph(); |  | 
|   888  |  | 
|   889   CheckInputs(ret, d1.phi, R.start, d1.merge); |  | 
|   890   CheckInputs(d1.phi, R.one, d3.phi, d1.merge); |  | 
|   891   CheckInputs(d1.merge, d1.if_true, d3.merge); |  | 
|   892  |  | 
|   893   DeadChecker dead(&R.graph); |  | 
|   894   dead.Check(d2);  // d2 was a dead diamond. |  | 
|   895   dead.CheckLive(d3); |  | 
|   896 } |  | 
|   897  |  | 
|   898  |  | 
|   899 TEST(Return_nested_diamonds1_dead2) { |  | 
|   900   ControlReducerTester R; |  | 
|   901   Diamond d2(R, R.p0);  // dead diamond |  | 
|   902   Diamond d3(R, R.p0);  // dead diamond |  | 
|   903   Diamond d1(R, R.p0, R.one, R.zero); |  | 
|   904  |  | 
|   905   d2.nest(d1, true); |  | 
|   906   d3.nest(d1, false); |  | 
|   907  |  | 
|   908   Node* ret = R.Return(d1.phi, R.start, d1.merge); |  | 
|   909  |  | 
|   910   R.ReduceGraph(); |  | 
|   911  |  | 
|   912   CheckInputs(ret, d1.phi, R.start, d1.merge); |  | 
|   913   CheckInputs(d1.phi, R.one, R.zero, d1.merge); |  | 
|   914   CheckInputs(d1.merge, d1.if_true, d1.if_false); |  | 
|   915  |  | 
|   916   DeadChecker dead(&R.graph); |  | 
|   917   dead.Check(d2); |  | 
|   918   dead.Check(d3); |  | 
|   919 } |  | 
|   920  |  | 
|   921  |  | 
|   922 TEST(Return_nested_diamonds_true1) { |  | 
|   923   ControlReducerTester R; |  | 
|   924   Diamond d2(R, R.p0, R.one, R.zero); |  | 
|   925   Diamond d1(R, R.jsgraph.TrueConstant(), d2.phi, R.zero); |  | 
|   926   Diamond d3(R, R.p0); |  | 
|   927  |  | 
|   928   d2.nest(d1, true); |  | 
|   929   d3.nest(d1, false); |  | 
|   930  |  | 
|   931   Node* ret = R.Return(d1.phi, R.start, d1.merge); |  | 
|   932  |  | 
|   933   R.ReduceGraph();  // d1 gets folded true. |  | 
|   934  |  | 
|   935   CheckInputs(ret, d2.phi, R.start, d2.merge); |  | 
|   936   CheckInputs(d2.branch, R.p0, R.start); |  | 
|   937  |  | 
|   938   DeadChecker dead(&R.graph); |  | 
|   939   dead.Check(d1); |  | 
|   940   dead.CheckLive(d2); |  | 
|   941   dead.Check(d3); |  | 
|   942 } |  | 
|   943  |  | 
|   944  |  | 
|   945 TEST(Return_nested_diamonds_false1) { |  | 
|   946   ControlReducerTester R; |  | 
|   947   Diamond d3(R, R.p0, R.one, R.zero); |  | 
|   948   Diamond d1(R, R.zero, R.one, d3.phi); |  | 
|   949   Diamond d2(R, R.p0); |  | 
|   950  |  | 
|   951   d2.nest(d1, true); |  | 
|   952   d3.nest(d1, false); |  | 
|   953  |  | 
|   954   Node* ret = R.Return(d1.phi, R.start, d1.merge); |  | 
|   955  |  | 
|   956   R.ReduceGraph();  // d1 gets folded false. |  | 
|   957  |  | 
|   958   CheckInputs(ret, d3.phi, R.start, d3.merge); |  | 
|   959   CheckInputs(d3.branch, R.p0, R.start); |  | 
|   960  |  | 
|   961   DeadChecker dead(&R.graph); |  | 
|   962   dead.Check(d1); |  | 
|   963   dead.Check(d2); |  | 
|   964   dead.CheckLive(d3); |  | 
|   965 } |  | 
|   966  |  | 
|   967  |  | 
|   968 TEST(Return_nested_diamonds_true_true1) { |  | 
|   969   ControlReducerTester R; |  | 
|   970   Diamond d1(R, R.jsgraph.TrueConstant(), R.one, R.zero); |  | 
|   971   Diamond d2(R, R.jsgraph.TrueConstant()); |  | 
|   972   Diamond d3(R, R.p0); |  | 
|   973  |  | 
|   974   d2.nest(d1, true); |  | 
|   975   d3.nest(d1, false); |  | 
|   976  |  | 
|   977   Node* ret = R.Return(d1.phi, R.start, d1.merge); |  | 
|   978  |  | 
|   979   R.ReduceGraph();  // d1 and d2 both get folded true. |  | 
|   980  |  | 
|   981   CheckInputs(ret, R.one, R.start, R.start); |  | 
|   982  |  | 
|   983   DeadChecker dead(&R.graph); |  | 
|   984   dead.Check(d1); |  | 
|   985   dead.Check(d2); |  | 
|   986   dead.Check(d3); |  | 
|   987 } |  | 
|   988  |  | 
|   989  |  | 
|   990 TEST(Return_nested_diamonds_true_false1) { |  | 
|   991   ControlReducerTester R; |  | 
|   992   Diamond d1(R, R.jsgraph.TrueConstant(), R.one, R.zero); |  | 
|   993   Diamond d2(R, R.jsgraph.FalseConstant()); |  | 
|   994   Diamond d3(R, R.p0); |  | 
|   995  |  | 
|   996   d2.nest(d1, true); |  | 
|   997   d3.nest(d1, false); |  | 
|   998  |  | 
|   999   Node* ret = R.Return(d1.phi, R.start, d1.merge); |  | 
|  1000  |  | 
|  1001   R.ReduceGraph();  // d1 gets folded true and d2 gets folded false. |  | 
|  1002  |  | 
|  1003   CheckInputs(ret, R.one, R.start, R.start); |  | 
|  1004  |  | 
|  1005   DeadChecker dead(&R.graph); |  | 
|  1006   dead.Check(d1); |  | 
|  1007   dead.Check(d2); |  | 
|  1008   dead.Check(d3); |  | 
|  1009 } |  | 
|  1010  |  | 
|  1011  |  | 
|  1012 TEST(Return_nested_diamonds2) { |  | 
|  1013   ControlReducerTester R; |  | 
|  1014   Node* x2 = R.jsgraph.Float64Constant(11.1); |  | 
|  1015   Node* y2 = R.jsgraph.Float64Constant(22.2); |  | 
|  1016   Node* x3 = R.jsgraph.Float64Constant(33.3); |  | 
|  1017   Node* y3 = R.jsgraph.Float64Constant(44.4); |  | 
|  1018  |  | 
|  1019   Diamond d2(R, R.p0, x2, y2); |  | 
|  1020   Diamond d3(R, R.p0, x3, y3); |  | 
|  1021   Diamond d1(R, R.p0, d2.phi, d3.phi); |  | 
|  1022  |  | 
|  1023   d2.nest(d1, true); |  | 
|  1024   d3.nest(d1, false); |  | 
|  1025  |  | 
|  1026   Node* ret = R.Return(d1.phi, R.start, d1.merge); |  | 
|  1027  |  | 
|  1028   R.ReduceGraph();  // nothing should happen. |  | 
|  1029  |  | 
|  1030   CheckInputs(ret, d1.phi, R.start, d1.merge); |  | 
|  1031   CheckInputs(d1.phi, d2.phi, d3.phi, d1.merge); |  | 
|  1032   CheckInputs(d1.merge, d2.merge, d3.merge); |  | 
|  1033  |  | 
|  1034   DeadChecker dead(&R.graph); |  | 
|  1035   dead.CheckLive(d2); |  | 
|  1036   dead.CheckLive(d3); |  | 
|  1037 } |  | 
|  1038  |  | 
|  1039  |  | 
|  1040 TEST(Return_nested_diamonds_true2) { |  | 
|  1041   ControlReducerTester R; |  | 
|  1042   Node* x2 = R.jsgraph.Float64Constant(11.1); |  | 
|  1043   Node* y2 = R.jsgraph.Float64Constant(22.2); |  | 
|  1044   Node* x3 = R.jsgraph.Float64Constant(33.3); |  | 
|  1045   Node* y3 = R.jsgraph.Float64Constant(44.4); |  | 
|  1046  |  | 
|  1047   Diamond d2(R, R.p0, x2, y2); |  | 
|  1048   Diamond d3(R, R.p0, x3, y3); |  | 
|  1049   Diamond d1(R, R.jsgraph.TrueConstant(), d2.phi, d3.phi); |  | 
|  1050  |  | 
|  1051   d2.nest(d1, true); |  | 
|  1052   d3.nest(d1, false); |  | 
|  1053  |  | 
|  1054   Node* ret = R.Return(d1.phi, R.start, d1.merge); |  | 
|  1055  |  | 
|  1056   R.ReduceGraph();  // d1 gets folded true. |  | 
|  1057  |  | 
|  1058   CheckInputs(ret, d2.phi, R.start, d2.merge); |  | 
|  1059   CheckInputs(d2.branch, R.p0, R.start); |  | 
|  1060  |  | 
|  1061   DeadChecker dead(&R.graph); |  | 
|  1062   dead.Check(d1); |  | 
|  1063   dead.CheckLive(d2); |  | 
|  1064   dead.Check(d3); |  | 
|  1065 } |  | 
|  1066  |  | 
|  1067  |  | 
|  1068 TEST(Return_nested_diamonds_true_true2) { |  | 
|  1069   ControlReducerTester R; |  | 
|  1070   Node* x2 = R.jsgraph.Float64Constant(11.1); |  | 
|  1071   Node* y2 = R.jsgraph.Float64Constant(22.2); |  | 
|  1072   Node* x3 = R.jsgraph.Float64Constant(33.3); |  | 
|  1073   Node* y3 = R.jsgraph.Float64Constant(44.4); |  | 
|  1074  |  | 
|  1075   Diamond d2(R, R.jsgraph.TrueConstant(), x2, y2); |  | 
|  1076   Diamond d3(R, R.p0, x3, y3); |  | 
|  1077   Diamond d1(R, R.jsgraph.TrueConstant(), d2.phi, d3.phi); |  | 
|  1078  |  | 
|  1079   d2.nest(d1, true); |  | 
|  1080   d3.nest(d1, false); |  | 
|  1081  |  | 
|  1082   Node* ret = R.Return(d1.phi, R.start, d1.merge); |  | 
|  1083  |  | 
|  1084   R.ReduceGraph();  // d1 gets folded true. |  | 
|  1085  |  | 
|  1086   CheckInputs(ret, x2, R.start, R.start); |  | 
|  1087  |  | 
|  1088   DeadChecker dead(&R.graph); |  | 
|  1089   dead.Check(d1); |  | 
|  1090   dead.Check(d2); |  | 
|  1091   dead.Check(d3); |  | 
|  1092 } |  | 
|  1093  |  | 
|  1094  |  | 
|  1095 TEST(Return_nested_diamonds_true_false2) { |  | 
|  1096   ControlReducerTester R; |  | 
|  1097   Node* x2 = R.jsgraph.Float64Constant(11.1); |  | 
|  1098   Node* y2 = R.jsgraph.Float64Constant(22.2); |  | 
|  1099   Node* x3 = R.jsgraph.Float64Constant(33.3); |  | 
|  1100   Node* y3 = R.jsgraph.Float64Constant(44.4); |  | 
|  1101  |  | 
|  1102   Diamond d2(R, R.jsgraph.FalseConstant(), x2, y2); |  | 
|  1103   Diamond d3(R, R.p0, x3, y3); |  | 
|  1104   Diamond d1(R, R.jsgraph.TrueConstant(), d2.phi, d3.phi); |  | 
|  1105  |  | 
|  1106   d2.nest(d1, true); |  | 
|  1107   d3.nest(d1, false); |  | 
|  1108  |  | 
|  1109   Node* ret = R.Return(d1.phi, R.start, d1.merge); |  | 
|  1110  |  | 
|  1111   R.ReduceGraph();  // d1 gets folded true. |  | 
|  1112  |  | 
|  1113   CheckInputs(ret, y2, R.start, R.start); |  | 
|  1114  |  | 
|  1115   DeadChecker dead(&R.graph); |  | 
|  1116   dead.Check(d1); |  | 
|  1117   dead.Check(d2); |  | 
|  1118   dead.Check(d3); |  | 
|  1119 } |  | 
| OLD | NEW |