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 53278 : static Operator dummy_operator0(IrOpcode::kParameter, Operator::kNoWrite,
20 26639 : "dummy", 0, 0, 0, 1, 0, 0);
21 53278 : static Operator dummy_operator1(IrOpcode::kParameter, Operator::kNoWrite,
22 26639 : "dummy", 1, 0, 0, 1, 0, 0);
23 53278 : static Operator dummy_operator2(IrOpcode::kParameter, Operator::kNoWrite,
24 26639 : "dummy", 2, 0, 0, 1, 0, 0);
25 53278 : static Operator dummy_operator3(IrOpcode::kParameter, Operator::kNoWrite,
26 26639 : "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 735 : void CheckUseChain(Node* node, Node** uses, int use_count) {
43 : // Check ownership.
44 1060 : if (use_count == 1) CHECK(node->OwnedBy(uses[0]));
45 735 : if (use_count > 1) {
46 475 : for (int i = 0; i < use_count; i++) {
47 390 : CHECK(!node->OwnedBy(uses[i]));
48 : }
49 : }
50 :
51 : // Check the self-reported use count.
52 735 : CHECK_EQ(use_count, node->UseCount());
53 :
54 : // Build the expectation set.
55 : NodeMSet expect_set;
56 1775 : for (int i = 0; i < use_count; i++) {
57 520 : expect_set.insert(uses[i]);
58 : }
59 :
60 : {
61 : // Check that iterating over the uses gives the right counts.
62 : NodeMSet use_set;
63 1775 : for (auto use : node->uses()) {
64 : use_set.insert(use);
65 : }
66 735 : 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 1255 : for (auto edge : node->use_edges()) {
74 520 : CHECK_EQ(node, edge.to());
75 520 : CHECK_EQ(node, edge.from()->InputAt(edge.index()));
76 1040 : use_set.insert(edge.from());
77 : }
78 735 : CHECK(expect_set == use_set);
79 : }
80 :
81 : {
82 : // Check the use nodes actually have the node as inputs.
83 1775 : for (Node* use : node->uses()) {
84 : size_t count = 0;
85 1770 : for (Node* input : use->inputs()) {
86 1250 : if (input == node) count++;
87 : }
88 520 : CHECK_EQ(count, expect_set.count(use));
89 : }
90 : }
91 735 : }
92 :
93 :
94 470 : void CheckInputs(Node* node, Node** inputs, int input_count) {
95 470 : CHECK_EQ(input_count, node->InputCount());
96 : // Check InputAt().
97 2250 : for (int i = 0; i < static_cast<int>(input_count); i++) {
98 890 : CHECK_EQ(inputs[i], node->InputAt(i));
99 : }
100 :
101 : // Check input iterator.
102 : int index = 0;
103 1360 : for (Node* input : node->inputs()) {
104 890 : CHECK_EQ(inputs[index], input);
105 890 : index++;
106 : }
107 :
108 : // Check use lists of inputs.
109 2250 : for (int i = 0; i < static_cast<int>(input_count); i++) {
110 890 : Node* input = inputs[i];
111 890 : if (!input) continue; // skip null inputs
112 : bool found = false;
113 : // Check regular use list.
114 850 : for (Node* use : input->uses()) {
115 850 : if (use == node) {
116 : found = true;
117 : break;
118 : }
119 : }
120 825 : CHECK(found);
121 : int count = 0;
122 : // Check use edge list.
123 2620 : for (auto edge : input->use_edges()) {
124 2860 : if (edge.from() == node && edge.to() == input && edge.index() == i) {
125 825 : count++;
126 : }
127 : }
128 825 : CHECK_EQ(1, count);
129 : }
130 470 : }
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 26644 : TEST(NodeUseIteratorReplaceUses) {
145 10 : v8::internal::AccountingAllocator allocator;
146 10 : Zone zone(&allocator, ZONE_NAME);
147 5 : 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 5 : CHECK_USES(n0, n1, n2);
154 :
155 5 : CHECK_INPUTS(n1, n0);
156 5 : CHECK_INPUTS(n2, n0);
157 :
158 5 : n0->ReplaceUses(n3);
159 :
160 5 : CHECK_USES(n0, NONE);
161 5 : CHECK_USES(n1, NONE);
162 5 : CHECK_USES(n2, NONE);
163 5 : CHECK_USES(n3, n1, n2);
164 :
165 5 : CHECK_INPUTS(n1, n3);
166 5 : CHECK_INPUTS(n2, n3);
167 5 : }
168 :
169 :
170 26644 : TEST(NodeUseIteratorReplaceUsesSelf) {
171 10 : v8::internal::AccountingAllocator allocator;
172 10 : Zone zone(&allocator, ZONE_NAME);
173 5 : Graph graph(&zone);
174 : Node* n0 = graph.NewNode(&dummy_operator0);
175 : Node* n1 = graph.NewNode(&dummy_operator1, n0);
176 :
177 5 : CHECK_USES(n0, n1);
178 5 : CHECK_USES(n1, NONE);
179 :
180 5 : n1->ReplaceInput(0, n1); // Create self-reference.
181 :
182 5 : CHECK_USES(n0, NONE);
183 5 : CHECK_USES(n1, n1);
184 :
185 : Node* n2 = graph.NewNode(&dummy_operator0);
186 :
187 5 : n1->ReplaceUses(n2);
188 :
189 5 : CHECK_USES(n0, NONE);
190 5 : CHECK_USES(n1, NONE);
191 5 : CHECK_USES(n2, n1);
192 5 : }
193 :
194 :
195 26644 : TEST(ReplaceInput) {
196 10 : v8::internal::AccountingAllocator allocator;
197 10 : Zone zone(&allocator, ZONE_NAME);
198 5 : 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 5 : CHECK_USES(n0, n3);
206 5 : CHECK_USES(n1, n3);
207 5 : CHECK_USES(n2, n3);
208 5 : CHECK_USES(n3, NONE);
209 5 : CHECK_USES(n4, NONE);
210 :
211 5 : CHECK_INPUTS(n3, n0, n1, n2);
212 :
213 5 : n3->ReplaceInput(1, n4);
214 :
215 5 : CHECK_USES(n1, NONE);
216 5 : CHECK_USES(n4, n3);
217 :
218 5 : CHECK_INPUTS(n3, n0, n4, n2);
219 5 : }
220 :
221 :
222 26644 : TEST(OwnedBy) {
223 10 : v8::internal::AccountingAllocator allocator;
224 10 : Zone zone(&allocator, ZONE_NAME);
225 5 : Graph graph(&zone);
226 :
227 : {
228 : Node* n0 = graph.NewNode(&dummy_operator0);
229 : Node* n1 = graph.NewNode(&dummy_operator0);
230 :
231 5 : CHECK(!n0->OwnedBy(n1));
232 5 : CHECK(!n1->OwnedBy(n0));
233 :
234 : Node* n2 = graph.NewNode(&dummy_operator1, n0);
235 5 : CHECK(n0->OwnedBy(n2));
236 5 : CHECK(!n2->OwnedBy(n0));
237 :
238 : Node* n3 = graph.NewNode(&dummy_operator1, n0);
239 5 : CHECK(!n0->OwnedBy(n2));
240 5 : CHECK(!n0->OwnedBy(n3));
241 5 : CHECK(!n2->OwnedBy(n0));
242 5 : CHECK(!n3->OwnedBy(n0));
243 : }
244 :
245 : {
246 : Node* n0 = graph.NewNode(&dummy_operator0);
247 : Node* n1 = graph.NewNode(&dummy_operator1, n0);
248 5 : CHECK(n0->OwnedBy(n1));
249 5 : CHECK(!n1->OwnedBy(n0));
250 : Node* n2 = graph.NewNode(&dummy_operator1, n0);
251 5 : CHECK(!n0->OwnedBy(n1));
252 5 : CHECK(!n0->OwnedBy(n2));
253 5 : CHECK(!n1->OwnedBy(n0));
254 5 : CHECK(!n1->OwnedBy(n2));
255 5 : CHECK(!n2->OwnedBy(n0));
256 5 : CHECK(!n2->OwnedBy(n1));
257 :
258 : Node* n3 = graph.NewNode(&dummy_operator0);
259 5 : n2->ReplaceInput(0, n3);
260 :
261 5 : CHECK(n0->OwnedBy(n1));
262 5 : CHECK(!n1->OwnedBy(n0));
263 5 : CHECK(!n1->OwnedBy(n0));
264 5 : CHECK(!n1->OwnedBy(n2));
265 5 : CHECK(!n2->OwnedBy(n0));
266 5 : CHECK(!n2->OwnedBy(n1));
267 5 : CHECK(n3->OwnedBy(n2));
268 5 : CHECK(!n2->OwnedBy(n3));
269 : }
270 5 : }
271 :
272 :
273 26644 : TEST(Uses) {
274 10 : v8::internal::AccountingAllocator allocator;
275 10 : Zone zone(&allocator, ZONE_NAME);
276 5 : Graph graph(&zone);
277 :
278 : Node* n0 = graph.NewNode(&dummy_operator0);
279 : Node* n1 = graph.NewNode(&dummy_operator1, n0);
280 :
281 5 : CHECK_USES(n0, n1);
282 5 : CHECK_USES(n1, NONE);
283 :
284 : Node* n2 = graph.NewNode(&dummy_operator1, n0);
285 :
286 5 : CHECK_USES(n0, n1, n2);
287 5 : CHECK_USES(n2, NONE);
288 :
289 : Node* n3 = graph.NewNode(&dummy_operator1, n0);
290 :
291 5 : CHECK_USES(n0, n1, n2, n3);
292 5 : CHECK_USES(n3, NONE);
293 5 : }
294 :
295 :
296 26644 : TEST(Inputs) {
297 10 : v8::internal::AccountingAllocator allocator;
298 10 : Zone zone(&allocator, ZONE_NAME);
299 5 : 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 5 : CHECK_INPUTS(n3, n0, n1, n2);
307 :
308 : Node* n4 = graph.NewNode(&dummy_operator3, n0, n1, n2);
309 5 : n3->AppendInput(graph.zone(), n4);
310 :
311 5 : CHECK_INPUTS(n3, n0, n1, n2, n4);
312 5 : CHECK_USES(n4, n3);
313 :
314 5 : n3->AppendInput(graph.zone(), n4);
315 :
316 5 : CHECK_INPUTS(n3, n0, n1, n2, n4, n4);
317 5 : CHECK_USES(n4, n3, n3);
318 :
319 : Node* n5 = graph.NewNode(&dummy_operator1, n4);
320 :
321 5 : CHECK_USES(n4, n3, n3, n5);
322 5 : }
323 :
324 26644 : TEST(InsertInputs) {
325 10 : v8::internal::AccountingAllocator allocator;
326 10 : Zone zone(&allocator, ZONE_NAME);
327 5 : 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 5 : node->InsertInputs(graph.zone(), 0, 1);
336 5 : node->ReplaceInput(0, n1);
337 5 : CHECK_INPUTS(node, n1, n0);
338 : }
339 : {
340 : Node* node = graph.NewNode(&dummy_operator1, n0);
341 5 : node->InsertInputs(graph.zone(), 0, 2);
342 5 : node->ReplaceInput(0, node);
343 5 : node->ReplaceInput(1, n2);
344 5 : CHECK_INPUTS(node, node, n2, n0);
345 : }
346 : {
347 : Node* node = graph.NewNode(&dummy_operator3, n0, n1, n2);
348 5 : node->InsertInputs(graph.zone(), 0, 1);
349 5 : node->ReplaceInput(0, node);
350 5 : CHECK_INPUTS(node, node, n0, n1, n2);
351 : }
352 : {
353 : Node* node = graph.NewNode(&dummy_operator3, n0, n1, n2);
354 5 : node->InsertInputs(graph.zone(), 1, 1);
355 5 : node->ReplaceInput(1, node);
356 5 : CHECK_INPUTS(node, n0, node, n1, n2);
357 : }
358 : {
359 : Node* node = graph.NewNode(&dummy_operator3, n0, n1, n2);
360 5 : node->InsertInputs(graph.zone(), 2, 1);
361 5 : node->ReplaceInput(2, node);
362 5 : CHECK_INPUTS(node, n0, n1, node, n2);
363 : }
364 : {
365 : Node* node = graph.NewNode(&dummy_operator3, n0, n1, n2);
366 5 : node->InsertInputs(graph.zone(), 2, 1);
367 5 : node->ReplaceInput(2, node);
368 5 : CHECK_INPUTS(node, n0, n1, node, n2);
369 : }
370 : {
371 : Node* node = graph.NewNode(&dummy_operator3, n0, n1, n2);
372 5 : node->InsertInputs(graph.zone(), 0, 4);
373 5 : node->ReplaceInput(0, node);
374 5 : node->ReplaceInput(1, node);
375 5 : node->ReplaceInput(2, node);
376 5 : node->ReplaceInput(3, node);
377 5 : CHECK_INPUTS(node, node, node, node, node, n0, n1, n2);
378 : }
379 : {
380 : Node* node = graph.NewNode(&dummy_operator3, n0, n1, n2);
381 5 : node->InsertInputs(graph.zone(), 1, 4);
382 5 : node->ReplaceInput(1, node);
383 5 : node->ReplaceInput(2, node);
384 5 : node->ReplaceInput(3, node);
385 5 : node->ReplaceInput(4, node);
386 5 : CHECK_INPUTS(node, n0, node, node, node, node, n1, n2);
387 : }
388 : {
389 : Node* node = graph.NewNode(&dummy_operator3, n0, n1, n2);
390 5 : node->InsertInputs(graph.zone(), 2, 4);
391 5 : node->ReplaceInput(2, node);
392 5 : node->ReplaceInput(3, node);
393 5 : node->ReplaceInput(4, node);
394 5 : node->ReplaceInput(5, node);
395 5 : CHECK_INPUTS(node, n0, n1, node, node, node, node, n2);
396 : }
397 5 : }
398 :
399 26644 : TEST(RemoveInput) {
400 10 : v8::internal::AccountingAllocator allocator;
401 10 : Zone zone(&allocator, ZONE_NAME);
402 5 : 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 5 : CHECK_INPUTS(n0, NONE);
409 5 : CHECK_INPUTS(n1, n0);
410 5 : CHECK_INPUTS(n2, n0, n1);
411 5 : CHECK_USES(n0, n1, n2);
412 :
413 5 : n1->RemoveInput(0);
414 5 : CHECK_INPUTS(n1, NONE);
415 5 : CHECK_USES(n0, n2);
416 :
417 5 : n2->RemoveInput(0);
418 5 : CHECK_INPUTS(n2, n1);
419 5 : CHECK_USES(n0, NONE);
420 5 : CHECK_USES(n1, n2);
421 :
422 5 : n2->RemoveInput(0);
423 5 : CHECK_INPUTS(n2, NONE);
424 5 : CHECK_USES(n0, NONE);
425 5 : CHECK_USES(n1, NONE);
426 5 : CHECK_USES(n2, NONE);
427 5 : }
428 :
429 :
430 26644 : TEST(AppendInputsAndIterator) {
431 10 : v8::internal::AccountingAllocator allocator;
432 10 : Zone zone(&allocator, ZONE_NAME);
433 5 : 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 5 : CHECK_INPUTS(n0, NONE);
440 5 : CHECK_INPUTS(n1, n0);
441 5 : CHECK_INPUTS(n2, n0, n1);
442 5 : CHECK_USES(n0, n1, n2);
443 :
444 : Node* n3 = graph.NewNode(&dummy_operator0);
445 :
446 5 : n2->AppendInput(graph.zone(), n3);
447 :
448 5 : CHECK_INPUTS(n2, n0, n1, n3);
449 5 : CHECK_USES(n3, n2);
450 5 : }
451 :
452 :
453 26644 : TEST(NullInputsSimple) {
454 10 : v8::internal::AccountingAllocator allocator;
455 10 : Zone zone(&allocator, ZONE_NAME);
456 5 : 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 5 : CHECK_INPUTS(n0, NONE);
463 5 : CHECK_INPUTS(n1, n0);
464 5 : CHECK_INPUTS(n2, n0, n1);
465 5 : CHECK_USES(n0, n1, n2);
466 :
467 5 : n2->ReplaceInput(0, nullptr);
468 :
469 5 : CHECK_INPUTS(n2, nullptr, n1);
470 :
471 5 : CHECK_USES(n0, n1);
472 :
473 5 : n2->ReplaceInput(1, nullptr);
474 :
475 5 : CHECK_INPUTS(n2, nullptr, nullptr);
476 :
477 5 : CHECK_USES(n1, NONE);
478 5 : }
479 :
480 :
481 26644 : TEST(NullInputsAppended) {
482 10 : v8::internal::AccountingAllocator allocator;
483 10 : Zone zone(&allocator, ZONE_NAME);
484 5 : 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 5 : n3->AppendInput(graph.zone(), n1);
491 5 : n3->AppendInput(graph.zone(), n2);
492 :
493 5 : CHECK_INPUTS(n3, n0, n1, n2);
494 5 : CHECK_USES(n0, n1, n2, n3);
495 5 : CHECK_USES(n1, n3);
496 5 : CHECK_USES(n2, n3);
497 :
498 5 : n3->ReplaceInput(1, nullptr);
499 5 : CHECK_USES(n1, NONE);
500 :
501 5 : CHECK_INPUTS(n3, n0, nullptr, n2);
502 5 : }
503 :
504 :
505 26644 : TEST(ReplaceUsesFromAppendedInputs) {
506 10 : v8::internal::AccountingAllocator allocator;
507 10 : Zone zone(&allocator, ZONE_NAME);
508 5 : 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 5 : CHECK_INPUTS(n2, n0);
516 :
517 5 : n2->AppendInput(graph.zone(), n1);
518 5 : CHECK_INPUTS(n2, n0, n1);
519 5 : CHECK_USES(n1, n2);
520 :
521 5 : n2->AppendInput(graph.zone(), n0);
522 5 : CHECK_INPUTS(n2, n0, n1, n0);
523 5 : CHECK_USES(n1, n2);
524 5 : CHECK_USES(n0, n2, n1, n2);
525 :
526 5 : n0->ReplaceUses(n3);
527 :
528 5 : CHECK_USES(n0, NONE);
529 5 : CHECK_INPUTS(n2, n3, n1, n3);
530 5 : CHECK_USES(n3, n2, n1, n2);
531 5 : }
532 :
533 :
534 26644 : TEST(ReplaceInputMultipleUses) {
535 10 : v8::internal::AccountingAllocator allocator;
536 10 : Zone zone(&allocator, ZONE_NAME);
537 5 : 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 5 : n2->ReplaceInput(0, n1);
543 5 : CHECK_EQ(0, n0->UseCount());
544 5 : CHECK_EQ(1, n1->UseCount());
545 :
546 : Node* n3 = graph.NewNode(&dummy_operator1, n0);
547 5 : n3->ReplaceInput(0, n1);
548 5 : CHECK_EQ(0, n0->UseCount());
549 5 : CHECK_EQ(2, n1->UseCount());
550 5 : }
551 :
552 :
553 26644 : TEST(TrimInputCountInline) {
554 10 : v8::internal::AccountingAllocator allocator;
555 10 : Zone zone(&allocator, ZONE_NAME);
556 5 : Graph graph(&zone);
557 :
558 : {
559 : Node* n0 = graph.NewNode(&dummy_operator0);
560 : Node* n1 = graph.NewNode(&dummy_operator1, n0);
561 5 : n1->TrimInputCount(1);
562 5 : CHECK_INPUTS(n1, n0);
563 5 : CHECK_USES(n0, n1);
564 : }
565 :
566 : {
567 : Node* n0 = graph.NewNode(&dummy_operator0);
568 : Node* n1 = graph.NewNode(&dummy_operator1, n0);
569 5 : n1->TrimInputCount(0);
570 5 : CHECK_INPUTS(n1, NONE);
571 5 : 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 5 : n2->TrimInputCount(2);
579 5 : CHECK_INPUTS(n2, n0, n1);
580 5 : CHECK_USES(n0, n2);
581 5 : 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 5 : n2->TrimInputCount(1);
589 5 : CHECK_INPUTS(n2, n0);
590 5 : CHECK_USES(n0, n2);
591 5 : 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 5 : n2->TrimInputCount(0);
599 5 : CHECK_INPUTS(n2, NONE);
600 5 : CHECK_USES(n0, NONE);
601 5 : CHECK_USES(n1, NONE);
602 : }
603 :
604 : {
605 : Node* n0 = graph.NewNode(&dummy_operator0);
606 : Node* n2 = graph.NewNode(&dummy_operator2, n0, n0);
607 5 : n2->TrimInputCount(1);
608 5 : CHECK_INPUTS(n2, n0);
609 5 : CHECK_USES(n0, n2);
610 : }
611 :
612 : {
613 : Node* n0 = graph.NewNode(&dummy_operator0);
614 : Node* n2 = graph.NewNode(&dummy_operator2, n0, n0);
615 5 : n2->TrimInputCount(0);
616 5 : CHECK_INPUTS(n2, NONE);
617 5 : CHECK_USES(n0, NONE);
618 : }
619 5 : }
620 :
621 :
622 26644 : TEST(TrimInputCountOutOfLine1) {
623 10 : v8::internal::AccountingAllocator allocator;
624 10 : Zone zone(&allocator, ZONE_NAME);
625 5 : Graph graph(&zone);
626 :
627 : {
628 : Node* n0 = graph.NewNode(&dummy_operator0);
629 : Node* n1 = graph.NewNode(&dummy_operator0);
630 5 : n1->AppendInput(graph.zone(), n0);
631 5 : CHECK_INPUTS(n1, n0);
632 5 : CHECK_USES(n0, n1);
633 :
634 5 : n1->TrimInputCount(1);
635 5 : CHECK_INPUTS(n1, n0);
636 5 : CHECK_USES(n0, n1);
637 : }
638 :
639 : {
640 : Node* n0 = graph.NewNode(&dummy_operator0);
641 : Node* n1 = graph.NewNode(&dummy_operator0);
642 5 : n1->AppendInput(graph.zone(), n0);
643 5 : CHECK_EQ(1, n1->InputCount());
644 5 : n1->TrimInputCount(0);
645 5 : CHECK_EQ(0, n1->InputCount());
646 5 : 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 5 : n2->AppendInput(graph.zone(), n0);
654 5 : n2->AppendInput(graph.zone(), n1);
655 5 : CHECK_INPUTS(n2, n0, n1);
656 5 : n2->TrimInputCount(2);
657 5 : CHECK_INPUTS(n2, n0, n1);
658 5 : CHECK_USES(n0, n2);
659 5 : CHECK_USES(n1, n2);
660 5 : 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 5 : n2->AppendInput(graph.zone(), n0);
668 5 : n2->AppendInput(graph.zone(), n1);
669 5 : CHECK_INPUTS(n2, n0, n1);
670 5 : n2->TrimInputCount(1);
671 5 : CHECK_INPUTS(n2, n0);
672 5 : CHECK_USES(n0, n2);
673 5 : CHECK_USES(n1, NONE);
674 5 : 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 5 : n2->AppendInput(graph.zone(), n0);
682 5 : n2->AppendInput(graph.zone(), n1);
683 5 : CHECK_INPUTS(n2, n0, n1);
684 5 : n2->TrimInputCount(0);
685 5 : CHECK_INPUTS(n2, NONE);
686 5 : CHECK_USES(n0, NONE);
687 5 : CHECK_USES(n1, NONE);
688 5 : CHECK_USES(n2, NONE);
689 : }
690 :
691 : {
692 : Node* n0 = graph.NewNode(&dummy_operator0);
693 : Node* n2 = graph.NewNode(&dummy_operator0);
694 5 : n2->AppendInput(graph.zone(), n0);
695 5 : n2->AppendInput(graph.zone(), n0);
696 5 : CHECK_INPUTS(n2, n0, n0);
697 5 : CHECK_USES(n0, n2, n2);
698 5 : n2->TrimInputCount(1);
699 5 : CHECK_INPUTS(n2, n0);
700 5 : CHECK_USES(n0, n2);
701 : }
702 :
703 : {
704 : Node* n0 = graph.NewNode(&dummy_operator0);
705 : Node* n2 = graph.NewNode(&dummy_operator0);
706 5 : n2->AppendInput(graph.zone(), n0);
707 5 : n2->AppendInput(graph.zone(), n0);
708 5 : CHECK_INPUTS(n2, n0, n0);
709 5 : CHECK_USES(n0, n2, n2);
710 5 : n2->TrimInputCount(0);
711 5 : CHECK_INPUTS(n2, NONE);
712 5 : CHECK_USES(n0, NONE);
713 : }
714 5 : }
715 :
716 :
717 26644 : TEST(TrimInputCountOutOfLine2) {
718 10 : v8::internal::AccountingAllocator allocator;
719 10 : Zone zone(&allocator, ZONE_NAME);
720 5 : 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 5 : n2->AppendInput(graph.zone(), n1);
727 5 : CHECK_INPUTS(n2, n0, n1);
728 5 : n2->TrimInputCount(2);
729 5 : CHECK_INPUTS(n2, n0, n1);
730 5 : CHECK_USES(n0, n2);
731 5 : CHECK_USES(n1, n2);
732 5 : 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 5 : n2->AppendInput(graph.zone(), n1);
740 5 : CHECK_INPUTS(n2, n0, n1);
741 5 : n2->TrimInputCount(1);
742 5 : CHECK_INPUTS(n2, n0);
743 5 : CHECK_USES(n0, n2);
744 5 : CHECK_USES(n1, NONE);
745 5 : 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 5 : n2->AppendInput(graph.zone(), n1);
753 5 : CHECK_INPUTS(n2, n0, n1);
754 5 : n2->TrimInputCount(0);
755 5 : CHECK_INPUTS(n2, NONE);
756 5 : CHECK_USES(n0, NONE);
757 5 : CHECK_USES(n1, NONE);
758 5 : CHECK_USES(n2, NONE);
759 : }
760 :
761 : {
762 : Node* n0 = graph.NewNode(&dummy_operator0);
763 : Node* n2 = graph.NewNode(&dummy_operator1, n0);
764 5 : n2->AppendInput(graph.zone(), n0);
765 5 : CHECK_INPUTS(n2, n0, n0);
766 5 : CHECK_USES(n0, n2, n2);
767 5 : n2->TrimInputCount(1);
768 5 : CHECK_INPUTS(n2, n0);
769 5 : CHECK_USES(n0, n2);
770 5 : CHECK_USES(n2, NONE);
771 : }
772 :
773 : {
774 : Node* n0 = graph.NewNode(&dummy_operator0);
775 : Node* n2 = graph.NewNode(&dummy_operator1, n0);
776 5 : n2->AppendInput(graph.zone(), n0);
777 5 : CHECK_EQ(2, n2->InputCount());
778 5 : CHECK_EQ(2, n0->UseCount());
779 5 : n2->TrimInputCount(0);
780 5 : CHECK_EQ(0, n2->InputCount());
781 5 : CHECK_EQ(0, n0->UseCount());
782 5 : CHECK_EQ(0, n2->UseCount());
783 : }
784 5 : }
785 :
786 :
787 26644 : TEST(NullAllInputs) {
788 10 : v8::internal::AccountingAllocator allocator;
789 10 : Zone zone(&allocator, ZONE_NAME);
790 5 : Graph graph(&zone);
791 :
792 25 : 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 10 : if (i == 0) {
797 : n2 = graph.NewNode(&dummy_operator2, n0, n1);
798 5 : CHECK_INPUTS(n2, n0, n1);
799 : } else {
800 : n2 = graph.NewNode(&dummy_operator1, n0);
801 5 : CHECK_INPUTS(n2, n0);
802 5 : n2->AppendInput(graph.zone(), n1); // with out-of-line input.
803 5 : CHECK_INPUTS(n2, n0, n1);
804 : }
805 :
806 10 : n0->NullAllInputs();
807 10 : CHECK_INPUTS(n0, NONE);
808 :
809 10 : CHECK_USES(n0, n1, n2);
810 10 : n1->NullAllInputs();
811 10 : CHECK_INPUTS(n1, nullptr);
812 10 : CHECK_INPUTS(n2, n0, n1);
813 10 : CHECK_USES(n0, n2);
814 :
815 10 : n2->NullAllInputs();
816 10 : CHECK_INPUTS(n1, nullptr);
817 10 : CHECK_INPUTS(n2, nullptr, nullptr);
818 10 : CHECK_USES(n0, NONE);
819 : }
820 :
821 : {
822 : Node* n0 = graph.NewNode(&dummy_operator0);
823 : Node* n1 = graph.NewNode(&dummy_operator1, n0);
824 5 : n1->ReplaceInput(0, n1); // self-reference.
825 :
826 5 : CHECK_INPUTS(n0, NONE);
827 5 : CHECK_INPUTS(n1, n1);
828 5 : CHECK_USES(n0, NONE);
829 5 : CHECK_USES(n1, n1);
830 5 : n1->NullAllInputs();
831 :
832 5 : CHECK_INPUTS(n0, NONE);
833 5 : CHECK_INPUTS(n1, nullptr);
834 5 : CHECK_USES(n0, NONE);
835 5 : CHECK_USES(n1, NONE);
836 : }
837 5 : }
838 :
839 :
840 26644 : TEST(AppendAndTrim) {
841 10 : v8::internal::AccountingAllocator allocator;
842 10 : Zone zone(&allocator, ZONE_NAME);
843 5 : 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 25 : graph.NewNode(&dummy_operator0)};
849 :
850 : int max = static_cast<int>(arraysize(nodes));
851 :
852 : Node* last = graph.NewNode(&dummy_operator0);
853 :
854 55 : for (int i = 0; i < max; i++) {
855 25 : last->AppendInput(graph.zone(), nodes[i]);
856 25 : CheckInputs(last, nodes, i + 1);
857 :
858 275 : for (int j = 0; j < max; j++) {
859 125 : if (j <= i) CHECK_USES(nodes[j], last);
860 125 : if (j > i) CHECK_USES(nodes[j], NONE);
861 : }
862 :
863 25 : CHECK_USES(last, NONE);
864 : }
865 :
866 65 : for (int i = max; i >= 0; i--) {
867 30 : last->TrimInputCount(i);
868 30 : CheckInputs(last, nodes, i);
869 :
870 180 : for (int j = 0; j < i; j++) {
871 75 : if (j < i) CHECK_USES(nodes[j], last);
872 75 : if (j >= i) CHECK_USES(nodes[j], NONE);
873 : }
874 :
875 30 : CHECK_USES(last, NONE);
876 : }
877 5 : }
878 :
879 : #undef NONE
880 : #undef CHECK_USES
881 : #undef CHECK_INPUTS
882 :
883 : } // namespace node
884 : } // namespace compiler
885 : } // namespace internal
886 79917 : } // namespace v8
|