Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(180)

Side by Side Diff: test/cctest/compiler/test-control-reducer.cc

Issue 1193833002: [turbofan] Proper dead code elimination as regular reducer. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Renamed DeadControl to Dead. Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « test/cctest/cctest.gyp ('k') | test/cctest/compiler/test-loop-analysis.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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 }
OLDNEW
« no previous file with comments | « test/cctest/cctest.gyp ('k') | test/cctest/compiler/test-loop-analysis.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698