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