1 // Copyright 2013 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 <functional>
6
7 #include "src/compiler/graph.h"
8 #include "src/compiler/node.h"
9 #include "src/compiler/operator.h"
10 #include "test/cctest/cctest.h"
11
12 namespace v8 {
13 namespace internal {
14 namespace compiler {
15
16 #define NONE reinterpret_cast<Node*>(1)
17
18 static Operator dummy_operator0(IrOpcode::kParameter, Operator::kNoWrite,
19 "dummy", 0, 0, 0, 1, 0, 0);
20 static Operator dummy_operator1(IrOpcode::kParameter, Operator::kNoWrite,
21 "dummy", 1, 0, 0, 1, 0, 0);
22 static Operator dummy_operator2(IrOpcode::kParameter, Operator::kNoWrite,
23 "dummy", 2, 0, 0, 1, 0, 0);
24 static Operator dummy_operator3(IrOpcode::kParameter, Operator::kNoWrite,
25 "dummy", 3, 0, 0, 1, 0, 0);
26
27 #define CHECK_USES(node, ...) \
28 do { \
29 Node* __array[] = {__VA_ARGS__}; \
30 int __size = \
31 __array[0] != NONE ? static_cast<int>(arraysize(__array)) : 0; \
32 CheckUseChain(node, __array, __size); \
33 } while (false)
34
35
36 namespace {
37
38 typedef std::multiset<Node*, std::less<Node*>> NodeMSet;
39
40
CheckUseChain(Node * node,Node ** uses,int use_count)41 void CheckUseChain(Node* node, Node** uses, int use_count) {
42 // Check ownership.
43 if (use_count == 1) CHECK(node->OwnedBy(uses[0]));
44 if (use_count > 1) {
45 for (int i = 0; i < use_count; i++) {
46 CHECK(!node->OwnedBy(uses[i]));
47 }
48 }
49
50 // Check the self-reported use count.
51 CHECK_EQ(use_count, node->UseCount());
52
53 // Build the expectation set.
54 NodeMSet expect_set;
55 for (int i = 0; i < use_count; i++) {
56 expect_set.insert(uses[i]);
57 }
58
59 {
60 // Check that iterating over the uses gives the right counts.
61 NodeMSet use_set;
62 for (auto use : node->uses()) {
63 use_set.insert(use);
64 }
65 CHECK(expect_set == use_set);
66 }
67
68 {
69 // Check that iterating over the use edges gives the right counts,
70 // input indices, from(), and to() pointers.
71 NodeMSet use_set;
72 for (auto edge : node->use_edges()) {
73 CHECK_EQ(node, edge.to());
74 CHECK_EQ(node, edge.from()->InputAt(edge.index()));
75 use_set.insert(edge.from());
76 }
77 CHECK(expect_set == use_set);
78 }
79
80 {
81 // Check the use nodes actually have the node as inputs.
82 for (Node* use : node->uses()) {
83 size_t count = 0;
84 for (Node* input : use->inputs()) {
85 if (input == node) count++;
86 }
87 CHECK_EQ(count, expect_set.count(use));
88 }
89 }
90 }
91
92
CheckInputs(Node * node,Node ** inputs,int input_count)93 void CheckInputs(Node* node, Node** inputs, int input_count) {
94 CHECK_EQ(input_count, node->InputCount());
95 // Check InputAt().
96 for (int i = 0; i < static_cast<int>(input_count); i++) {
97 CHECK_EQ(inputs[i], node->InputAt(i));
98 }
99
100 // Check input iterator.
101 int index = 0;
102 for (Node* input : node->inputs()) {
103 CHECK_EQ(inputs[index], input);
104 index++;
105 }
106
107 // Check use lists of inputs.
108 for (int i = 0; i < static_cast<int>(input_count); i++) {
109 Node* input = inputs[i];
110 if (!input) continue; // skip null inputs
111 bool found = false;
112 // Check regular use list.
113 for (Node* use : input->uses()) {
114 if (use == node) {
115 found = true;
116 break;
117 }
118 }
119 CHECK(found);
120 int count = 0;
121 // Check use edge list.
122 for (auto edge : input->use_edges()) {
123 if (edge.from() == node && edge.to() == input && edge.index() == i) {
124 count++;
125 }
126 }
127 CHECK_EQ(1, count);
128 }
129 }
130
131 } // namespace
132
133
134 #define CHECK_INPUTS(node, ...) \
135 do { \
136 Node* __array[] = {__VA_ARGS__}; \
137 int __size = \
138 __array[0] != NONE ? static_cast<int>(arraysize(__array)) : 0; \
139 CheckInputs(node, __array, __size); \
140 } while (false)
141
142
TEST(NodeUseIteratorReplaceUses)143 TEST(NodeUseIteratorReplaceUses) {
144 Zone zone;
145 Graph graph(&zone);
146 Node* n0 = graph.NewNode(&dummy_operator0);
147 Node* n1 = graph.NewNode(&dummy_operator1, n0);
148 Node* n2 = graph.NewNode(&dummy_operator1, n0);
149 Node* n3 = graph.NewNode(&dummy_operator0);
150
151 CHECK_USES(n0, n1, n2);
152
153 CHECK_INPUTS(n1, n0);
154 CHECK_INPUTS(n2, n0);
155
156 n0->ReplaceUses(n3);
157
158 CHECK_USES(n0, NONE);
159 CHECK_USES(n1, NONE);
160 CHECK_USES(n2, NONE);
161 CHECK_USES(n3, n1, n2);
162
163 CHECK_INPUTS(n1, n3);
164 CHECK_INPUTS(n2, n3);
165 }
166
167
TEST(NodeUseIteratorReplaceUsesSelf)168 TEST(NodeUseIteratorReplaceUsesSelf) {
169 Zone zone;
170 Graph graph(&zone);
171 Node* n0 = graph.NewNode(&dummy_operator0);
172 Node* n1 = graph.NewNode(&dummy_operator1, n0);
173
174 CHECK_USES(n0, n1);
175 CHECK_USES(n1, NONE);
176
177 n1->ReplaceInput(0, n1); // Create self-reference.
178
179 CHECK_USES(n0, NONE);
180 CHECK_USES(n1, n1);
181
182 Node* n2 = graph.NewNode(&dummy_operator0);
183
184 n1->ReplaceUses(n2);
185
186 CHECK_USES(n0, NONE);
187 CHECK_USES(n1, NONE);
188 CHECK_USES(n2, n1);
189 }
190
191
TEST(ReplaceInput)192 TEST(ReplaceInput) {
193 Zone zone;
194 Graph graph(&zone);
195 Node* n0 = graph.NewNode(&dummy_operator0);
196 Node* n1 = graph.NewNode(&dummy_operator0);
197 Node* n2 = graph.NewNode(&dummy_operator0);
198 Node* n3 = graph.NewNode(&dummy_operator3, n0, n1, n2);
199 Node* n4 = graph.NewNode(&dummy_operator0);
200
201 CHECK_USES(n0, n3);
202 CHECK_USES(n1, n3);
203 CHECK_USES(n2, n3);
204 CHECK_USES(n3, NONE);
205 CHECK_USES(n4, NONE);
206
207 CHECK_INPUTS(n3, n0, n1, n2);
208
209 n3->ReplaceInput(1, n4);
210
211 CHECK_USES(n1, NONE);
212 CHECK_USES(n4, n3);
213
214 CHECK_INPUTS(n3, n0, n4, n2);
215 }
216
217
TEST(OwnedBy)218 TEST(OwnedBy) {
219 Zone zone;
220 Graph graph(&zone);
221
222 {
223 Node* n0 = graph.NewNode(&dummy_operator0);
224 Node* n1 = graph.NewNode(&dummy_operator0);
225
226 CHECK(!n0->OwnedBy(n1));
227 CHECK(!n1->OwnedBy(n0));
228
229 Node* n2 = graph.NewNode(&dummy_operator1, n0);
230 CHECK(n0->OwnedBy(n2));
231 CHECK(!n2->OwnedBy(n0));
232
233 Node* n3 = graph.NewNode(&dummy_operator1, n0);
234 CHECK(!n0->OwnedBy(n2));
235 CHECK(!n0->OwnedBy(n3));
236 CHECK(!n2->OwnedBy(n0));
237 CHECK(!n3->OwnedBy(n0));
238 }
239
240 {
241 Node* n0 = graph.NewNode(&dummy_operator0);
242 Node* n1 = graph.NewNode(&dummy_operator1, n0);
243 CHECK(n0->OwnedBy(n1));
244 CHECK(!n1->OwnedBy(n0));
245 Node* n2 = graph.NewNode(&dummy_operator1, n0);
246 CHECK(!n0->OwnedBy(n1));
247 CHECK(!n0->OwnedBy(n2));
248 CHECK(!n1->OwnedBy(n0));
249 CHECK(!n1->OwnedBy(n2));
250 CHECK(!n2->OwnedBy(n0));
251 CHECK(!n2->OwnedBy(n1));
252
253 Node* n3 = graph.NewNode(&dummy_operator0);
254 n2->ReplaceInput(0, n3);
255
256 CHECK(n0->OwnedBy(n1));
257 CHECK(!n1->OwnedBy(n0));
258 CHECK(!n1->OwnedBy(n0));
259 CHECK(!n1->OwnedBy(n2));
260 CHECK(!n2->OwnedBy(n0));
261 CHECK(!n2->OwnedBy(n1));
262 CHECK(n3->OwnedBy(n2));
263 CHECK(!n2->OwnedBy(n3));
264 }
265 }
266
267
TEST(Uses)268 TEST(Uses) {
269 Zone zone;
270 Graph graph(&zone);
271
272 Node* n0 = graph.NewNode(&dummy_operator0);
273 Node* n1 = graph.NewNode(&dummy_operator1, n0);
274
275 CHECK_USES(n0, n1);
276 CHECK_USES(n1, NONE);
277
278 Node* n2 = graph.NewNode(&dummy_operator1, n0);
279
280 CHECK_USES(n0, n1, n2);
281 CHECK_USES(n2, NONE);
282
283 Node* n3 = graph.NewNode(&dummy_operator1, n0);
284
285 CHECK_USES(n0, n1, n2, n3);
286 CHECK_USES(n3, NONE);
287 }
288
289
TEST(Inputs)290 TEST(Inputs) {
291 Zone zone;
292 Graph graph(&zone);
293
294 Node* n0 = graph.NewNode(&dummy_operator0);
295 Node* n1 = graph.NewNode(&dummy_operator1, n0);
296 Node* n2 = graph.NewNode(&dummy_operator1, n0);
297 Node* n3 = graph.NewNode(&dummy_operator3, n0, n1, n2);
298
299 CHECK_INPUTS(n3, n0, n1, n2);
300
301 Node* n4 = graph.NewNode(&dummy_operator3, n0, n1, n2);
302 n3->AppendInput(graph.zone(), n4);
303
304 CHECK_INPUTS(n3, n0, n1, n2, n4);
305 CHECK_USES(n4, n3);
306
307 n3->AppendInput(graph.zone(), n4);
308
309 CHECK_INPUTS(n3, n0, n1, n2, n4, n4);
310 CHECK_USES(n4, n3, n3);
311
312 Node* n5 = graph.NewNode(&dummy_operator1, n4);
313
314 CHECK_USES(n4, n3, n3, n5);
315 }
316
317
TEST(RemoveInput)318 TEST(RemoveInput) {
319 Zone zone;
320 Graph graph(&zone);
321
322 Node* n0 = graph.NewNode(&dummy_operator0);
323 Node* n1 = graph.NewNode(&dummy_operator1, n0);
324 Node* n2 = graph.NewNode(&dummy_operator2, n0, n1);
325
326 CHECK_INPUTS(n0, NONE);
327 CHECK_INPUTS(n1, n0);
328 CHECK_INPUTS(n2, n0, n1);
329 CHECK_USES(n0, n1, n2);
330
331 n1->RemoveInput(0);
332 CHECK_INPUTS(n1, NONE);
333 CHECK_USES(n0, n2);
334
335 n2->RemoveInput(0);
336 CHECK_INPUTS(n2, n1);
337 CHECK_USES(n0, NONE);
338 CHECK_USES(n1, n2);
339
340 n2->RemoveInput(0);
341 CHECK_INPUTS(n2, NONE);
342 CHECK_USES(n0, NONE);
343 CHECK_USES(n1, NONE);
344 CHECK_USES(n2, NONE);
345 }
346
347
TEST(AppendInputsAndIterator)348 TEST(AppendInputsAndIterator) {
349 Zone zone;
350 Graph graph(&zone);
351
352 Node* n0 = graph.NewNode(&dummy_operator0);
353 Node* n1 = graph.NewNode(&dummy_operator1, n0);
354 Node* n2 = graph.NewNode(&dummy_operator2, n0, n1);
355
356 CHECK_INPUTS(n0, NONE);
357 CHECK_INPUTS(n1, n0);
358 CHECK_INPUTS(n2, n0, n1);
359 CHECK_USES(n0, n1, n2);
360
361 Node* n3 = graph.NewNode(&dummy_operator0);
362
363 n2->AppendInput(graph.zone(), n3);
364
365 CHECK_INPUTS(n2, n0, n1, n3);
366 CHECK_USES(n3, n2);
367 }
368
369
TEST(NullInputsSimple)370 TEST(NullInputsSimple) {
371 Zone zone;
372 Graph graph(&zone);
373
374 Node* n0 = graph.NewNode(&dummy_operator0);
375 Node* n1 = graph.NewNode(&dummy_operator1, n0);
376 Node* n2 = graph.NewNode(&dummy_operator2, n0, n1);
377
378 CHECK_INPUTS(n0, NONE);
379 CHECK_INPUTS(n1, n0);
380 CHECK_INPUTS(n2, n0, n1);
381 CHECK_USES(n0, n1, n2);
382
383 n2->ReplaceInput(0, nullptr);
384
385 CHECK_INPUTS(n2, NULL, n1);
386
387 CHECK_USES(n0, n1);
388
389 n2->ReplaceInput(1, nullptr);
390
391 CHECK_INPUTS(n2, NULL, NULL);
392
393 CHECK_USES(n1, NONE);
394 }
395
396
TEST(NullInputsAppended)397 TEST(NullInputsAppended) {
398 Zone zone;
399 Graph graph(&zone);
400
401 Node* n0 = graph.NewNode(&dummy_operator0);
402 Node* n1 = graph.NewNode(&dummy_operator1, n0);
403 Node* n2 = graph.NewNode(&dummy_operator1, n0);
404 Node* n3 = graph.NewNode(&dummy_operator1, n0);
405 n3->AppendInput(graph.zone(), n1);
406 n3->AppendInput(graph.zone(), n2);
407
408 CHECK_INPUTS(n3, n0, n1, n2);
409 CHECK_USES(n0, n1, n2, n3);
410 CHECK_USES(n1, n3);
411 CHECK_USES(n2, n3);
412
413 n3->ReplaceInput(1, NULL);
414 CHECK_USES(n1, NONE);
415
416 CHECK_INPUTS(n3, n0, NULL, n2);
417 }
418
419
TEST(ReplaceUsesFromAppendedInputs)420 TEST(ReplaceUsesFromAppendedInputs) {
421 Zone zone;
422 Graph graph(&zone);
423
424 Node* n0 = graph.NewNode(&dummy_operator0);
425 Node* n1 = graph.NewNode(&dummy_operator1, n0);
426 Node* n2 = graph.NewNode(&dummy_operator1, n0);
427 Node* n3 = graph.NewNode(&dummy_operator0);
428
429 CHECK_INPUTS(n2, n0);
430
431 n2->AppendInput(graph.zone(), n1);
432 CHECK_INPUTS(n2, n0, n1);
433 CHECK_USES(n1, n2);
434
435 n2->AppendInput(graph.zone(), n0);
436 CHECK_INPUTS(n2, n0, n1, n0);
437 CHECK_USES(n1, n2);
438 CHECK_USES(n0, n2, n1, n2);
439
440 n0->ReplaceUses(n3);
441
442 CHECK_USES(n0, NONE);
443 CHECK_INPUTS(n2, n3, n1, n3);
444 CHECK_USES(n3, n2, n1, n2);
445 }
446
447
TEST(ReplaceInputMultipleUses)448 TEST(ReplaceInputMultipleUses) {
449 Zone zone;
450 Graph graph(&zone);
451
452 Node* n0 = graph.NewNode(&dummy_operator0);
453 Node* n1 = graph.NewNode(&dummy_operator0);
454 Node* n2 = graph.NewNode(&dummy_operator1, n0);
455 n2->ReplaceInput(0, n1);
456 CHECK_EQ(0, n0->UseCount());
457 CHECK_EQ(1, n1->UseCount());
458
459 Node* n3 = graph.NewNode(&dummy_operator1, n0);
460 n3->ReplaceInput(0, n1);
461 CHECK_EQ(0, n0->UseCount());
462 CHECK_EQ(2, n1->UseCount());
463 }
464
465
TEST(TrimInputCountInline)466 TEST(TrimInputCountInline) {
467 Zone zone;
468 Graph graph(&zone);
469
470 {
471 Node* n0 = graph.NewNode(&dummy_operator0);
472 Node* n1 = graph.NewNode(&dummy_operator1, n0);
473 n1->TrimInputCount(1);
474 CHECK_INPUTS(n1, n0);
475 CHECK_USES(n0, n1);
476 }
477
478 {
479 Node* n0 = graph.NewNode(&dummy_operator0);
480 Node* n1 = graph.NewNode(&dummy_operator1, n0);
481 n1->TrimInputCount(0);
482 CHECK_INPUTS(n1, NONE);
483 CHECK_USES(n0, NONE);
484 }
485
486 {
487 Node* n0 = graph.NewNode(&dummy_operator0);
488 Node* n1 = graph.NewNode(&dummy_operator0);
489 Node* n2 = graph.NewNode(&dummy_operator2, n0, n1);
490 n2->TrimInputCount(2);
491 CHECK_INPUTS(n2, n0, n1);
492 CHECK_USES(n0, n2);
493 CHECK_USES(n1, n2);
494 }
495
496 {
497 Node* n0 = graph.NewNode(&dummy_operator0);
498 Node* n1 = graph.NewNode(&dummy_operator0);
499 Node* n2 = graph.NewNode(&dummy_operator2, n0, n1);
500 n2->TrimInputCount(1);
501 CHECK_INPUTS(n2, n0);
502 CHECK_USES(n0, n2);
503 CHECK_USES(n1, NONE);
504 }
505
506 {
507 Node* n0 = graph.NewNode(&dummy_operator0);
508 Node* n1 = graph.NewNode(&dummy_operator0);
509 Node* n2 = graph.NewNode(&dummy_operator2, n0, n1);
510 n2->TrimInputCount(0);
511 CHECK_INPUTS(n2, NONE);
512 CHECK_USES(n0, NONE);
513 CHECK_USES(n1, NONE);
514 }
515
516 {
517 Node* n0 = graph.NewNode(&dummy_operator0);
518 Node* n2 = graph.NewNode(&dummy_operator2, n0, n0);
519 n2->TrimInputCount(1);
520 CHECK_INPUTS(n2, n0);
521 CHECK_USES(n0, n2);
522 }
523
524 {
525 Node* n0 = graph.NewNode(&dummy_operator0);
526 Node* n2 = graph.NewNode(&dummy_operator2, n0, n0);
527 n2->TrimInputCount(0);
528 CHECK_INPUTS(n2, NONE);
529 CHECK_USES(n0, NONE);
530 }
531 }
532
533
TEST(TrimInputCountOutOfLine1)534 TEST(TrimInputCountOutOfLine1) {
535 Zone zone;
536 Graph graph(&zone);
537
538 {
539 Node* n0 = graph.NewNode(&dummy_operator0);
540 Node* n1 = graph.NewNode(&dummy_operator0);
541 n1->AppendInput(graph.zone(), n0);
542 CHECK_INPUTS(n1, n0);
543 CHECK_USES(n0, n1);
544
545 n1->TrimInputCount(1);
546 CHECK_INPUTS(n1, n0);
547 CHECK_USES(n0, n1);
548 }
549
550 {
551 Node* n0 = graph.NewNode(&dummy_operator0);
552 Node* n1 = graph.NewNode(&dummy_operator0);
553 n1->AppendInput(graph.zone(), n0);
554 CHECK_EQ(1, n1->InputCount());
555 n1->TrimInputCount(0);
556 CHECK_EQ(0, n1->InputCount());
557 CHECK_EQ(0, n0->UseCount());
558 }
559
560 {
561 Node* n0 = graph.NewNode(&dummy_operator0);
562 Node* n1 = graph.NewNode(&dummy_operator0);
563 Node* n2 = graph.NewNode(&dummy_operator0);
564 n2->AppendInput(graph.zone(), n0);
565 n2->AppendInput(graph.zone(), n1);
566 CHECK_INPUTS(n2, n0, n1);
567 n2->TrimInputCount(2);
568 CHECK_INPUTS(n2, n0, n1);
569 CHECK_USES(n0, n2);
570 CHECK_USES(n1, n2);
571 CHECK_USES(n2, NONE);
572 }
573
574 {
575 Node* n0 = graph.NewNode(&dummy_operator0);
576 Node* n1 = graph.NewNode(&dummy_operator0);
577 Node* n2 = graph.NewNode(&dummy_operator0);
578 n2->AppendInput(graph.zone(), n0);
579 n2->AppendInput(graph.zone(), n1);
580 CHECK_INPUTS(n2, n0, n1);
581 n2->TrimInputCount(1);
582 CHECK_INPUTS(n2, n0);
583 CHECK_USES(n0, n2);
584 CHECK_USES(n1, NONE);
585 CHECK_USES(n2, NONE);
586 }
587
588 {
589 Node* n0 = graph.NewNode(&dummy_operator0);
590 Node* n1 = graph.NewNode(&dummy_operator0);
591 Node* n2 = graph.NewNode(&dummy_operator0);
592 n2->AppendInput(graph.zone(), n0);
593 n2->AppendInput(graph.zone(), n1);
594 CHECK_INPUTS(n2, n0, n1);
595 n2->TrimInputCount(0);
596 CHECK_INPUTS(n2, NONE);
597 CHECK_USES(n0, NONE);
598 CHECK_USES(n1, NONE);
599 CHECK_USES(n2, NONE);
600 }
601
602 {
603 Node* n0 = graph.NewNode(&dummy_operator0);
604 Node* n2 = graph.NewNode(&dummy_operator0);
605 n2->AppendInput(graph.zone(), n0);
606 n2->AppendInput(graph.zone(), n0);
607 CHECK_INPUTS(n2, n0, n0);
608 CHECK_USES(n0, n2, n2);
609 n2->TrimInputCount(1);
610 CHECK_INPUTS(n2, n0);
611 CHECK_USES(n0, n2);
612 }
613
614 {
615 Node* n0 = graph.NewNode(&dummy_operator0);
616 Node* n2 = graph.NewNode(&dummy_operator0);
617 n2->AppendInput(graph.zone(), n0);
618 n2->AppendInput(graph.zone(), n0);
619 CHECK_INPUTS(n2, n0, n0);
620 CHECK_USES(n0, n2, n2);
621 n2->TrimInputCount(0);
622 CHECK_INPUTS(n2, NONE);
623 CHECK_USES(n0, NONE);
624 }
625 }
626
627
TEST(TrimInputCountOutOfLine2)628 TEST(TrimInputCountOutOfLine2) {
629 Zone zone;
630 Graph graph(&zone);
631
632 {
633 Node* n0 = graph.NewNode(&dummy_operator0);
634 Node* n1 = graph.NewNode(&dummy_operator0);
635 Node* n2 = graph.NewNode(&dummy_operator1, n0);
636 n2->AppendInput(graph.zone(), n1);
637 CHECK_INPUTS(n2, n0, n1);
638 n2->TrimInputCount(2);
639 CHECK_INPUTS(n2, n0, n1);
640 CHECK_USES(n0, n2);
641 CHECK_USES(n1, n2);
642 CHECK_USES(n2, NONE);
643 }
644
645 {
646 Node* n0 = graph.NewNode(&dummy_operator0);
647 Node* n1 = graph.NewNode(&dummy_operator0);
648 Node* n2 = graph.NewNode(&dummy_operator1, n0);
649 n2->AppendInput(graph.zone(), n1);
650 CHECK_INPUTS(n2, n0, n1);
651 n2->TrimInputCount(1);
652 CHECK_INPUTS(n2, n0);
653 CHECK_USES(n0, n2);
654 CHECK_USES(n1, NONE);
655 CHECK_USES(n2, NONE);
656 }
657
658 {
659 Node* n0 = graph.NewNode(&dummy_operator0);
660 Node* n1 = graph.NewNode(&dummy_operator0);
661 Node* n2 = graph.NewNode(&dummy_operator1, n0);
662 n2->AppendInput(graph.zone(), n1);
663 CHECK_INPUTS(n2, n0, n1);
664 n2->TrimInputCount(0);
665 CHECK_INPUTS(n2, NONE);
666 CHECK_USES(n0, NONE);
667 CHECK_USES(n1, NONE);
668 CHECK_USES(n2, NONE);
669 }
670
671 {
672 Node* n0 = graph.NewNode(&dummy_operator0);
673 Node* n2 = graph.NewNode(&dummy_operator1, n0);
674 n2->AppendInput(graph.zone(), n0);
675 CHECK_INPUTS(n2, n0, n0);
676 CHECK_USES(n0, n2, n2);
677 n2->TrimInputCount(1);
678 CHECK_INPUTS(n2, n0);
679 CHECK_USES(n0, n2);
680 CHECK_USES(n2, NONE);
681 }
682
683 {
684 Node* n0 = graph.NewNode(&dummy_operator0);
685 Node* n2 = graph.NewNode(&dummy_operator1, n0);
686 n2->AppendInput(graph.zone(), n0);
687 CHECK_EQ(2, n2->InputCount());
688 CHECK_EQ(2, n0->UseCount());
689 n2->TrimInputCount(0);
690 CHECK_EQ(0, n2->InputCount());
691 CHECK_EQ(0, n0->UseCount());
692 CHECK_EQ(0, n2->UseCount());
693 }
694 }
695
696
TEST(NullAllInputs)697 TEST(NullAllInputs) {
698 Zone zone;
699 Graph graph(&zone);
700
701 for (int i = 0; i < 2; i++) {
702 Node* n0 = graph.NewNode(&dummy_operator0);
703 Node* n1 = graph.NewNode(&dummy_operator1, n0);
704 Node* n2;
705 if (i == 0) {
706 n2 = graph.NewNode(&dummy_operator2, n0, n1);
707 CHECK_INPUTS(n2, n0, n1);
708 } else {
709 n2 = graph.NewNode(&dummy_operator1, n0);
710 CHECK_INPUTS(n2, n0);
711 n2->AppendInput(graph.zone(), n1); // with out-of-line input.
712 CHECK_INPUTS(n2, n0, n1);
713 }
714
715 n0->NullAllInputs();
716 CHECK_INPUTS(n0, NONE);
717
718 CHECK_USES(n0, n1, n2);
719 n1->NullAllInputs();
720 CHECK_INPUTS(n1, NULL);
721 CHECK_INPUTS(n2, n0, n1);
722 CHECK_USES(n0, n2);
723
724 n2->NullAllInputs();
725 CHECK_INPUTS(n1, NULL);
726 CHECK_INPUTS(n2, NULL, NULL);
727 CHECK_USES(n0, NONE);
728 }
729
730 {
731 Node* n0 = graph.NewNode(&dummy_operator0);
732 Node* n1 = graph.NewNode(&dummy_operator1, n0);
733 n1->ReplaceInput(0, n1); // self-reference.
734
735 CHECK_INPUTS(n0, NONE);
736 CHECK_INPUTS(n1, n1);
737 CHECK_USES(n0, NONE);
738 CHECK_USES(n1, n1);
739 n1->NullAllInputs();
740
741 CHECK_INPUTS(n0, NONE);
742 CHECK_INPUTS(n1, NULL);
743 CHECK_USES(n0, NONE);
744 CHECK_USES(n1, NONE);
745 }
746 }
747
748
TEST(AppendAndTrim)749 TEST(AppendAndTrim) {
750 Zone zone;
751 Graph graph(&zone);
752
753 Node* nodes[] = {
754 graph.NewNode(&dummy_operator0), graph.NewNode(&dummy_operator0),
755 graph.NewNode(&dummy_operator0), graph.NewNode(&dummy_operator0),
756 graph.NewNode(&dummy_operator0)};
757
758 int max = static_cast<int>(arraysize(nodes));
759
760 Node* last = graph.NewNode(&dummy_operator0);
761
762 for (int i = 0; i < max; i++) {
763 last->AppendInput(graph.zone(), nodes[i]);
764 CheckInputs(last, nodes, i + 1);
765
766 for (int j = 0; j < max; j++) {
767 if (j <= i) CHECK_USES(nodes[j], last);
768 if (j > i) CHECK_USES(nodes[j], NONE);
769 }
770
771 CHECK_USES(last, NONE);
772 }
773
774 for (int i = max; i >= 0; i--) {
775 last->TrimInputCount(i);
776 CheckInputs(last, nodes, i);
777
778 for (int j = 0; j < i; j++) {
779 if (j < i) CHECK_USES(nodes[j], last);
780 if (j >= i) CHECK_USES(nodes[j], NONE);
781 }
782
783 CHECK_USES(last, NONE);
784 }
785 }
786
787 } // namespace compiler
788 } // namespace internal
789 } // namespace v8
790