• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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