OLD | NEW |
| (Empty) |
1 // Copyright 2014 the V8 project authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "src/v8.h" | |
6 | |
7 #include "src/compiler/access-builder.h" | |
8 #include "src/compiler/common-operator.h" | |
9 #include "src/compiler/graph.h" | |
10 #include "src/compiler/graph-visualizer.h" | |
11 #include "src/compiler/js-operator.h" | |
12 #include "src/compiler/node.h" | |
13 #include "src/compiler/opcodes.h" | |
14 #include "src/compiler/operator.h" | |
15 #include "src/compiler/schedule.h" | |
16 #include "src/compiler/scheduler.h" | |
17 #include "src/compiler/simplified-operator.h" | |
18 #include "src/compiler/verifier.h" | |
19 #include "test/cctest/cctest.h" | |
20 | |
21 using namespace v8::internal; | |
22 using namespace v8::internal::compiler; | |
23 | |
24 Operator kIntAdd(IrOpcode::kInt32Add, Operator::kPure, "Int32Add", 2, 0, 0, 1, | |
25 0, 0); | |
26 | |
27 // TODO(titzer): pull RPO tests out to their own file. | |
28 static void CheckRPONumbers(BasicBlockVector* order, size_t expected, | |
29 bool loops_allowed) { | |
30 CHECK(expected == order->size()); | |
31 for (int i = 0; i < static_cast<int>(order->size()); i++) { | |
32 CHECK(order->at(i)->rpo_number() == i); | |
33 if (!loops_allowed) { | |
34 CHECK_EQ(NULL, order->at(i)->loop_end()); | |
35 CHECK_EQ(NULL, order->at(i)->loop_header()); | |
36 } | |
37 } | |
38 } | |
39 | |
40 | |
41 static void CheckLoop(BasicBlockVector* order, BasicBlock** blocks, | |
42 int body_size) { | |
43 BasicBlock* header = blocks[0]; | |
44 BasicBlock* end = header->loop_end(); | |
45 CHECK_NE(NULL, end); | |
46 CHECK_GT(end->rpo_number(), 0); | |
47 CHECK_EQ(body_size, end->rpo_number() - header->rpo_number()); | |
48 for (int i = 0; i < body_size; i++) { | |
49 CHECK_GE(blocks[i]->rpo_number(), header->rpo_number()); | |
50 CHECK_LT(blocks[i]->rpo_number(), end->rpo_number()); | |
51 CHECK(header->LoopContains(blocks[i])); | |
52 CHECK(header->IsLoopHeader() || blocks[i]->loop_header() == header); | |
53 } | |
54 if (header->rpo_number() > 0) { | |
55 CHECK_NE(order->at(header->rpo_number() - 1)->loop_header(), header); | |
56 } | |
57 if (end->rpo_number() < static_cast<int>(order->size())) { | |
58 CHECK_NE(order->at(end->rpo_number())->loop_header(), header); | |
59 } | |
60 } | |
61 | |
62 | |
63 struct TestLoop { | |
64 int count; | |
65 BasicBlock** nodes; | |
66 BasicBlock* header() { return nodes[0]; } | |
67 BasicBlock* last() { return nodes[count - 1]; } | |
68 ~TestLoop() { delete[] nodes; } | |
69 | |
70 void Check(BasicBlockVector* order) { CheckLoop(order, nodes, count); } | |
71 }; | |
72 | |
73 | |
74 static TestLoop* CreateLoop(Schedule* schedule, int count) { | |
75 TestLoop* loop = new TestLoop(); | |
76 loop->count = count; | |
77 loop->nodes = new BasicBlock* [count]; | |
78 for (int i = 0; i < count; i++) { | |
79 loop->nodes[i] = schedule->NewBasicBlock(); | |
80 if (i > 0) { | |
81 schedule->AddSuccessorForTesting(loop->nodes[i - 1], loop->nodes[i]); | |
82 } | |
83 } | |
84 schedule->AddSuccessorForTesting(loop->nodes[count - 1], loop->nodes[0]); | |
85 return loop; | |
86 } | |
87 | |
88 | |
89 static int GetScheduledNodeCount(const Schedule* schedule) { | |
90 size_t node_count = 0; | |
91 for (auto block : *schedule->rpo_order()) { | |
92 node_count += block->NodeCount(); | |
93 if (block->control() != BasicBlock::kNone) ++node_count; | |
94 } | |
95 return static_cast<int>(node_count); | |
96 } | |
97 | |
98 | |
99 static Schedule* ComputeAndVerifySchedule(int expected, Graph* graph) { | |
100 if (FLAG_trace_turbo) { | |
101 OFStream os(stdout); | |
102 os << AsDOT(*graph); | |
103 } | |
104 | |
105 Schedule* schedule = Scheduler::ComputeSchedule(graph->zone(), graph); | |
106 | |
107 if (FLAG_trace_turbo_scheduler) { | |
108 OFStream os(stdout); | |
109 os << *schedule << std::endl; | |
110 } | |
111 ScheduleVerifier::Run(schedule); | |
112 CHECK_EQ(expected, GetScheduledNodeCount(schedule)); | |
113 return schedule; | |
114 } | |
115 | |
116 | |
117 TEST(RPODegenerate1) { | |
118 HandleAndZoneScope scope; | |
119 Schedule schedule(scope.main_zone()); | |
120 | |
121 BasicBlockVector* order = | |
122 Scheduler::ComputeSpecialRPO(scope.main_zone(), &schedule); | |
123 CheckRPONumbers(order, 1, false); | |
124 CHECK_EQ(schedule.start(), order->at(0)); | |
125 } | |
126 | |
127 | |
128 TEST(RPODegenerate2) { | |
129 HandleAndZoneScope scope; | |
130 Schedule schedule(scope.main_zone()); | |
131 | |
132 schedule.AddGoto(schedule.start(), schedule.end()); | |
133 BasicBlockVector* order = | |
134 Scheduler::ComputeSpecialRPO(scope.main_zone(), &schedule); | |
135 CheckRPONumbers(order, 2, false); | |
136 CHECK_EQ(schedule.start(), order->at(0)); | |
137 CHECK_EQ(schedule.end(), order->at(1)); | |
138 } | |
139 | |
140 | |
141 TEST(RPOLine) { | |
142 HandleAndZoneScope scope; | |
143 | |
144 for (int i = 0; i < 10; i++) { | |
145 Schedule schedule(scope.main_zone()); | |
146 | |
147 BasicBlock* last = schedule.start(); | |
148 for (int j = 0; j < i; j++) { | |
149 BasicBlock* block = schedule.NewBasicBlock(); | |
150 block->set_deferred(i & 1); | |
151 schedule.AddGoto(last, block); | |
152 last = block; | |
153 } | |
154 BasicBlockVector* order = | |
155 Scheduler::ComputeSpecialRPO(scope.main_zone(), &schedule); | |
156 CheckRPONumbers(order, 1 + i, false); | |
157 | |
158 for (size_t i = 0; i < schedule.BasicBlockCount(); i++) { | |
159 BasicBlock* block = schedule.GetBlockById(BasicBlock::Id::FromSize(i)); | |
160 if (block->rpo_number() >= 0 && block->SuccessorCount() == 1) { | |
161 CHECK(block->rpo_number() + 1 == block->SuccessorAt(0)->rpo_number()); | |
162 } | |
163 } | |
164 } | |
165 } | |
166 | |
167 | |
168 TEST(RPOSelfLoop) { | |
169 HandleAndZoneScope scope; | |
170 Schedule schedule(scope.main_zone()); | |
171 schedule.AddSuccessorForTesting(schedule.start(), schedule.start()); | |
172 BasicBlockVector* order = | |
173 Scheduler::ComputeSpecialRPO(scope.main_zone(), &schedule); | |
174 CheckRPONumbers(order, 1, true); | |
175 BasicBlock* loop[] = {schedule.start()}; | |
176 CheckLoop(order, loop, 1); | |
177 } | |
178 | |
179 | |
180 TEST(RPOEntryLoop) { | |
181 HandleAndZoneScope scope; | |
182 Schedule schedule(scope.main_zone()); | |
183 BasicBlock* body = schedule.NewBasicBlock(); | |
184 schedule.AddSuccessorForTesting(schedule.start(), body); | |
185 schedule.AddSuccessorForTesting(body, schedule.start()); | |
186 BasicBlockVector* order = | |
187 Scheduler::ComputeSpecialRPO(scope.main_zone(), &schedule); | |
188 CheckRPONumbers(order, 2, true); | |
189 BasicBlock* loop[] = {schedule.start(), body}; | |
190 CheckLoop(order, loop, 2); | |
191 } | |
192 | |
193 | |
194 TEST(RPOEndLoop) { | |
195 HandleAndZoneScope scope; | |
196 Schedule schedule(scope.main_zone()); | |
197 SmartPointer<TestLoop> loop1(CreateLoop(&schedule, 2)); | |
198 schedule.AddSuccessorForTesting(schedule.start(), loop1->header()); | |
199 BasicBlockVector* order = | |
200 Scheduler::ComputeSpecialRPO(scope.main_zone(), &schedule); | |
201 CheckRPONumbers(order, 3, true); | |
202 loop1->Check(order); | |
203 } | |
204 | |
205 | |
206 TEST(RPOEndLoopNested) { | |
207 HandleAndZoneScope scope; | |
208 Schedule schedule(scope.main_zone()); | |
209 SmartPointer<TestLoop> loop1(CreateLoop(&schedule, 2)); | |
210 schedule.AddSuccessorForTesting(schedule.start(), loop1->header()); | |
211 schedule.AddSuccessorForTesting(loop1->last(), schedule.start()); | |
212 BasicBlockVector* order = | |
213 Scheduler::ComputeSpecialRPO(scope.main_zone(), &schedule); | |
214 CheckRPONumbers(order, 3, true); | |
215 loop1->Check(order); | |
216 } | |
217 | |
218 | |
219 TEST(RPODiamond) { | |
220 HandleAndZoneScope scope; | |
221 Schedule schedule(scope.main_zone()); | |
222 | |
223 BasicBlock* A = schedule.start(); | |
224 BasicBlock* B = schedule.NewBasicBlock(); | |
225 BasicBlock* C = schedule.NewBasicBlock(); | |
226 BasicBlock* D = schedule.end(); | |
227 | |
228 schedule.AddSuccessorForTesting(A, B); | |
229 schedule.AddSuccessorForTesting(A, C); | |
230 schedule.AddSuccessorForTesting(B, D); | |
231 schedule.AddSuccessorForTesting(C, D); | |
232 | |
233 BasicBlockVector* order = | |
234 Scheduler::ComputeSpecialRPO(scope.main_zone(), &schedule); | |
235 CheckRPONumbers(order, 4, false); | |
236 | |
237 CHECK_EQ(0, A->rpo_number()); | |
238 CHECK((B->rpo_number() == 1 && C->rpo_number() == 2) || | |
239 (B->rpo_number() == 2 && C->rpo_number() == 1)); | |
240 CHECK_EQ(3, D->rpo_number()); | |
241 } | |
242 | |
243 | |
244 TEST(RPOLoop1) { | |
245 HandleAndZoneScope scope; | |
246 Schedule schedule(scope.main_zone()); | |
247 | |
248 BasicBlock* A = schedule.start(); | |
249 BasicBlock* B = schedule.NewBasicBlock(); | |
250 BasicBlock* C = schedule.NewBasicBlock(); | |
251 BasicBlock* D = schedule.end(); | |
252 | |
253 schedule.AddSuccessorForTesting(A, B); | |
254 schedule.AddSuccessorForTesting(B, C); | |
255 schedule.AddSuccessorForTesting(C, B); | |
256 schedule.AddSuccessorForTesting(C, D); | |
257 | |
258 BasicBlockVector* order = | |
259 Scheduler::ComputeSpecialRPO(scope.main_zone(), &schedule); | |
260 CheckRPONumbers(order, 4, true); | |
261 BasicBlock* loop[] = {B, C}; | |
262 CheckLoop(order, loop, 2); | |
263 } | |
264 | |
265 | |
266 TEST(RPOLoop2) { | |
267 HandleAndZoneScope scope; | |
268 Schedule schedule(scope.main_zone()); | |
269 | |
270 BasicBlock* A = schedule.start(); | |
271 BasicBlock* B = schedule.NewBasicBlock(); | |
272 BasicBlock* C = schedule.NewBasicBlock(); | |
273 BasicBlock* D = schedule.end(); | |
274 | |
275 schedule.AddSuccessorForTesting(A, B); | |
276 schedule.AddSuccessorForTesting(B, C); | |
277 schedule.AddSuccessorForTesting(C, B); | |
278 schedule.AddSuccessorForTesting(B, D); | |
279 | |
280 BasicBlockVector* order = | |
281 Scheduler::ComputeSpecialRPO(scope.main_zone(), &schedule); | |
282 CheckRPONumbers(order, 4, true); | |
283 BasicBlock* loop[] = {B, C}; | |
284 CheckLoop(order, loop, 2); | |
285 } | |
286 | |
287 | |
288 TEST(RPOLoopN) { | |
289 HandleAndZoneScope scope; | |
290 | |
291 for (int i = 0; i < 11; i++) { | |
292 Schedule schedule(scope.main_zone()); | |
293 BasicBlock* A = schedule.start(); | |
294 BasicBlock* B = schedule.NewBasicBlock(); | |
295 BasicBlock* C = schedule.NewBasicBlock(); | |
296 BasicBlock* D = schedule.NewBasicBlock(); | |
297 BasicBlock* E = schedule.NewBasicBlock(); | |
298 BasicBlock* F = schedule.NewBasicBlock(); | |
299 BasicBlock* G = schedule.end(); | |
300 | |
301 schedule.AddSuccessorForTesting(A, B); | |
302 schedule.AddSuccessorForTesting(B, C); | |
303 schedule.AddSuccessorForTesting(C, D); | |
304 schedule.AddSuccessorForTesting(D, E); | |
305 schedule.AddSuccessorForTesting(E, F); | |
306 schedule.AddSuccessorForTesting(F, B); | |
307 schedule.AddSuccessorForTesting(B, G); | |
308 | |
309 // Throw in extra backedges from time to time. | |
310 if (i == 1) schedule.AddSuccessorForTesting(B, B); | |
311 if (i == 2) schedule.AddSuccessorForTesting(C, B); | |
312 if (i == 3) schedule.AddSuccessorForTesting(D, B); | |
313 if (i == 4) schedule.AddSuccessorForTesting(E, B); | |
314 if (i == 5) schedule.AddSuccessorForTesting(F, B); | |
315 | |
316 // Throw in extra loop exits from time to time. | |
317 if (i == 6) schedule.AddSuccessorForTesting(B, G); | |
318 if (i == 7) schedule.AddSuccessorForTesting(C, G); | |
319 if (i == 8) schedule.AddSuccessorForTesting(D, G); | |
320 if (i == 9) schedule.AddSuccessorForTesting(E, G); | |
321 if (i == 10) schedule.AddSuccessorForTesting(F, G); | |
322 | |
323 BasicBlockVector* order = | |
324 Scheduler::ComputeSpecialRPO(scope.main_zone(), &schedule); | |
325 CheckRPONumbers(order, 7, true); | |
326 BasicBlock* loop[] = {B, C, D, E, F}; | |
327 CheckLoop(order, loop, 5); | |
328 } | |
329 } | |
330 | |
331 | |
332 TEST(RPOLoopNest1) { | |
333 HandleAndZoneScope scope; | |
334 Schedule schedule(scope.main_zone()); | |
335 | |
336 BasicBlock* A = schedule.start(); | |
337 BasicBlock* B = schedule.NewBasicBlock(); | |
338 BasicBlock* C = schedule.NewBasicBlock(); | |
339 BasicBlock* D = schedule.NewBasicBlock(); | |
340 BasicBlock* E = schedule.NewBasicBlock(); | |
341 BasicBlock* F = schedule.end(); | |
342 | |
343 schedule.AddSuccessorForTesting(A, B); | |
344 schedule.AddSuccessorForTesting(B, C); | |
345 schedule.AddSuccessorForTesting(C, D); | |
346 schedule.AddSuccessorForTesting(D, C); | |
347 schedule.AddSuccessorForTesting(D, E); | |
348 schedule.AddSuccessorForTesting(E, B); | |
349 schedule.AddSuccessorForTesting(E, F); | |
350 | |
351 BasicBlockVector* order = | |
352 Scheduler::ComputeSpecialRPO(scope.main_zone(), &schedule); | |
353 CheckRPONumbers(order, 6, true); | |
354 BasicBlock* loop1[] = {B, C, D, E}; | |
355 CheckLoop(order, loop1, 4); | |
356 | |
357 BasicBlock* loop2[] = {C, D}; | |
358 CheckLoop(order, loop2, 2); | |
359 } | |
360 | |
361 | |
362 TEST(RPOLoopNest2) { | |
363 HandleAndZoneScope scope; | |
364 Schedule schedule(scope.main_zone()); | |
365 | |
366 BasicBlock* A = schedule.start(); | |
367 BasicBlock* B = schedule.NewBasicBlock(); | |
368 BasicBlock* C = schedule.NewBasicBlock(); | |
369 BasicBlock* D = schedule.NewBasicBlock(); | |
370 BasicBlock* E = schedule.NewBasicBlock(); | |
371 BasicBlock* F = schedule.NewBasicBlock(); | |
372 BasicBlock* G = schedule.NewBasicBlock(); | |
373 BasicBlock* H = schedule.end(); | |
374 | |
375 schedule.AddSuccessorForTesting(A, B); | |
376 schedule.AddSuccessorForTesting(B, C); | |
377 schedule.AddSuccessorForTesting(C, D); | |
378 schedule.AddSuccessorForTesting(D, E); | |
379 schedule.AddSuccessorForTesting(E, F); | |
380 schedule.AddSuccessorForTesting(F, G); | |
381 schedule.AddSuccessorForTesting(G, H); | |
382 | |
383 schedule.AddSuccessorForTesting(E, D); | |
384 schedule.AddSuccessorForTesting(F, C); | |
385 schedule.AddSuccessorForTesting(G, B); | |
386 | |
387 BasicBlockVector* order = | |
388 Scheduler::ComputeSpecialRPO(scope.main_zone(), &schedule); | |
389 CheckRPONumbers(order, 8, true); | |
390 BasicBlock* loop1[] = {B, C, D, E, F, G}; | |
391 CheckLoop(order, loop1, 6); | |
392 | |
393 BasicBlock* loop2[] = {C, D, E, F}; | |
394 CheckLoop(order, loop2, 4); | |
395 | |
396 BasicBlock* loop3[] = {D, E}; | |
397 CheckLoop(order, loop3, 2); | |
398 } | |
399 | |
400 | |
401 TEST(RPOLoopFollow1) { | |
402 HandleAndZoneScope scope; | |
403 Schedule schedule(scope.main_zone()); | |
404 | |
405 SmartPointer<TestLoop> loop1(CreateLoop(&schedule, 1)); | |
406 SmartPointer<TestLoop> loop2(CreateLoop(&schedule, 1)); | |
407 | |
408 BasicBlock* A = schedule.start(); | |
409 BasicBlock* E = schedule.end(); | |
410 | |
411 schedule.AddSuccessorForTesting(A, loop1->header()); | |
412 schedule.AddSuccessorForTesting(loop1->header(), loop2->header()); | |
413 schedule.AddSuccessorForTesting(loop2->last(), E); | |
414 | |
415 BasicBlockVector* order = | |
416 Scheduler::ComputeSpecialRPO(scope.main_zone(), &schedule); | |
417 | |
418 CHECK_EQ(static_cast<int>(schedule.BasicBlockCount()), | |
419 static_cast<int>(order->size())); | |
420 | |
421 loop1->Check(order); | |
422 loop2->Check(order); | |
423 } | |
424 | |
425 | |
426 TEST(RPOLoopFollow2) { | |
427 HandleAndZoneScope scope; | |
428 Schedule schedule(scope.main_zone()); | |
429 | |
430 SmartPointer<TestLoop> loop1(CreateLoop(&schedule, 1)); | |
431 SmartPointer<TestLoop> loop2(CreateLoop(&schedule, 1)); | |
432 | |
433 BasicBlock* A = schedule.start(); | |
434 BasicBlock* S = schedule.NewBasicBlock(); | |
435 BasicBlock* E = schedule.end(); | |
436 | |
437 schedule.AddSuccessorForTesting(A, loop1->header()); | |
438 schedule.AddSuccessorForTesting(loop1->header(), S); | |
439 schedule.AddSuccessorForTesting(S, loop2->header()); | |
440 schedule.AddSuccessorForTesting(loop2->last(), E); | |
441 | |
442 BasicBlockVector* order = | |
443 Scheduler::ComputeSpecialRPO(scope.main_zone(), &schedule); | |
444 | |
445 CHECK_EQ(static_cast<int>(schedule.BasicBlockCount()), | |
446 static_cast<int>(order->size())); | |
447 loop1->Check(order); | |
448 loop2->Check(order); | |
449 } | |
450 | |
451 | |
452 TEST(RPOLoopFollowN) { | |
453 HandleAndZoneScope scope; | |
454 | |
455 for (int size = 1; size < 5; size++) { | |
456 for (int exit = 0; exit < size; exit++) { | |
457 Schedule schedule(scope.main_zone()); | |
458 SmartPointer<TestLoop> loop1(CreateLoop(&schedule, size)); | |
459 SmartPointer<TestLoop> loop2(CreateLoop(&schedule, size)); | |
460 BasicBlock* A = schedule.start(); | |
461 BasicBlock* E = schedule.end(); | |
462 | |
463 schedule.AddSuccessorForTesting(A, loop1->header()); | |
464 schedule.AddSuccessorForTesting(loop1->nodes[exit], loop2->header()); | |
465 schedule.AddSuccessorForTesting(loop2->nodes[exit], E); | |
466 BasicBlockVector* order = | |
467 Scheduler::ComputeSpecialRPO(scope.main_zone(), &schedule); | |
468 | |
469 CHECK_EQ(static_cast<int>(schedule.BasicBlockCount()), | |
470 static_cast<int>(order->size())); | |
471 loop1->Check(order); | |
472 loop2->Check(order); | |
473 } | |
474 } | |
475 } | |
476 | |
477 | |
478 TEST(RPONestedLoopFollow1) { | |
479 HandleAndZoneScope scope; | |
480 Schedule schedule(scope.main_zone()); | |
481 | |
482 SmartPointer<TestLoop> loop1(CreateLoop(&schedule, 1)); | |
483 SmartPointer<TestLoop> loop2(CreateLoop(&schedule, 1)); | |
484 | |
485 BasicBlock* A = schedule.start(); | |
486 BasicBlock* B = schedule.NewBasicBlock(); | |
487 BasicBlock* C = schedule.NewBasicBlock(); | |
488 BasicBlock* E = schedule.end(); | |
489 | |
490 schedule.AddSuccessorForTesting(A, B); | |
491 schedule.AddSuccessorForTesting(B, loop1->header()); | |
492 schedule.AddSuccessorForTesting(loop1->header(), loop2->header()); | |
493 schedule.AddSuccessorForTesting(loop2->last(), C); | |
494 schedule.AddSuccessorForTesting(C, E); | |
495 schedule.AddSuccessorForTesting(C, B); | |
496 | |
497 BasicBlockVector* order = | |
498 Scheduler::ComputeSpecialRPO(scope.main_zone(), &schedule); | |
499 | |
500 CHECK_EQ(static_cast<int>(schedule.BasicBlockCount()), | |
501 static_cast<int>(order->size())); | |
502 loop1->Check(order); | |
503 loop2->Check(order); | |
504 | |
505 BasicBlock* loop3[] = {B, loop1->nodes[0], loop2->nodes[0], C}; | |
506 CheckLoop(order, loop3, 4); | |
507 } | |
508 | |
509 | |
510 TEST(RPOLoopBackedges1) { | |
511 HandleAndZoneScope scope; | |
512 | |
513 int size = 8; | |
514 for (int i = 0; i < size; i++) { | |
515 for (int j = 0; j < size; j++) { | |
516 Schedule schedule(scope.main_zone()); | |
517 BasicBlock* A = schedule.start(); | |
518 BasicBlock* E = schedule.end(); | |
519 | |
520 SmartPointer<TestLoop> loop1(CreateLoop(&schedule, size)); | |
521 schedule.AddSuccessorForTesting(A, loop1->header()); | |
522 schedule.AddSuccessorForTesting(loop1->last(), E); | |
523 | |
524 schedule.AddSuccessorForTesting(loop1->nodes[i], loop1->header()); | |
525 schedule.AddSuccessorForTesting(loop1->nodes[j], E); | |
526 | |
527 BasicBlockVector* order = | |
528 Scheduler::ComputeSpecialRPO(scope.main_zone(), &schedule); | |
529 CheckRPONumbers(order, schedule.BasicBlockCount(), true); | |
530 loop1->Check(order); | |
531 } | |
532 } | |
533 } | |
534 | |
535 | |
536 TEST(RPOLoopOutedges1) { | |
537 HandleAndZoneScope scope; | |
538 | |
539 int size = 8; | |
540 for (int i = 0; i < size; i++) { | |
541 for (int j = 0; j < size; j++) { | |
542 Schedule schedule(scope.main_zone()); | |
543 BasicBlock* A = schedule.start(); | |
544 BasicBlock* D = schedule.NewBasicBlock(); | |
545 BasicBlock* E = schedule.end(); | |
546 | |
547 SmartPointer<TestLoop> loop1(CreateLoop(&schedule, size)); | |
548 schedule.AddSuccessorForTesting(A, loop1->header()); | |
549 schedule.AddSuccessorForTesting(loop1->last(), E); | |
550 | |
551 schedule.AddSuccessorForTesting(loop1->nodes[i], loop1->header()); | |
552 schedule.AddSuccessorForTesting(loop1->nodes[j], D); | |
553 schedule.AddSuccessorForTesting(D, E); | |
554 | |
555 BasicBlockVector* order = | |
556 Scheduler::ComputeSpecialRPO(scope.main_zone(), &schedule); | |
557 CheckRPONumbers(order, schedule.BasicBlockCount(), true); | |
558 loop1->Check(order); | |
559 } | |
560 } | |
561 } | |
562 | |
563 | |
564 TEST(RPOLoopOutedges2) { | |
565 HandleAndZoneScope scope; | |
566 | |
567 int size = 8; | |
568 for (int i = 0; i < size; i++) { | |
569 Schedule schedule(scope.main_zone()); | |
570 BasicBlock* A = schedule.start(); | |
571 BasicBlock* E = schedule.end(); | |
572 | |
573 SmartPointer<TestLoop> loop1(CreateLoop(&schedule, size)); | |
574 schedule.AddSuccessorForTesting(A, loop1->header()); | |
575 schedule.AddSuccessorForTesting(loop1->last(), E); | |
576 | |
577 for (int j = 0; j < size; j++) { | |
578 BasicBlock* O = schedule.NewBasicBlock(); | |
579 schedule.AddSuccessorForTesting(loop1->nodes[j], O); | |
580 schedule.AddSuccessorForTesting(O, E); | |
581 } | |
582 | |
583 BasicBlockVector* order = | |
584 Scheduler::ComputeSpecialRPO(scope.main_zone(), &schedule); | |
585 CheckRPONumbers(order, schedule.BasicBlockCount(), true); | |
586 loop1->Check(order); | |
587 } | |
588 } | |
589 | |
590 | |
591 TEST(RPOLoopOutloops1) { | |
592 HandleAndZoneScope scope; | |
593 | |
594 int size = 8; | |
595 for (int i = 0; i < size; i++) { | |
596 Schedule schedule(scope.main_zone()); | |
597 BasicBlock* A = schedule.start(); | |
598 BasicBlock* E = schedule.end(); | |
599 SmartPointer<TestLoop> loop1(CreateLoop(&schedule, size)); | |
600 schedule.AddSuccessorForTesting(A, loop1->header()); | |
601 schedule.AddSuccessorForTesting(loop1->last(), E); | |
602 | |
603 TestLoop** loopN = new TestLoop* [size]; | |
604 for (int j = 0; j < size; j++) { | |
605 loopN[j] = CreateLoop(&schedule, 2); | |
606 schedule.AddSuccessorForTesting(loop1->nodes[j], loopN[j]->header()); | |
607 schedule.AddSuccessorForTesting(loopN[j]->last(), E); | |
608 } | |
609 | |
610 BasicBlockVector* order = | |
611 Scheduler::ComputeSpecialRPO(scope.main_zone(), &schedule); | |
612 CheckRPONumbers(order, schedule.BasicBlockCount(), true); | |
613 loop1->Check(order); | |
614 | |
615 for (int j = 0; j < size; j++) { | |
616 loopN[j]->Check(order); | |
617 delete loopN[j]; | |
618 } | |
619 delete[] loopN; | |
620 } | |
621 } | |
622 | |
623 | |
624 TEST(RPOLoopMultibackedge) { | |
625 HandleAndZoneScope scope; | |
626 Schedule schedule(scope.main_zone()); | |
627 | |
628 BasicBlock* A = schedule.start(); | |
629 BasicBlock* B = schedule.NewBasicBlock(); | |
630 BasicBlock* C = schedule.NewBasicBlock(); | |
631 BasicBlock* D = schedule.NewBasicBlock(); | |
632 BasicBlock* E = schedule.NewBasicBlock(); | |
633 | |
634 schedule.AddSuccessorForTesting(A, B); | |
635 schedule.AddSuccessorForTesting(B, C); | |
636 schedule.AddSuccessorForTesting(B, D); | |
637 schedule.AddSuccessorForTesting(B, E); | |
638 schedule.AddSuccessorForTesting(C, B); | |
639 schedule.AddSuccessorForTesting(D, B); | |
640 schedule.AddSuccessorForTesting(E, B); | |
641 | |
642 BasicBlockVector* order = | |
643 Scheduler::ComputeSpecialRPO(scope.main_zone(), &schedule); | |
644 CheckRPONumbers(order, 5, true); | |
645 | |
646 BasicBlock* loop1[] = {B, C, D, E}; | |
647 CheckLoop(order, loop1, 4); | |
648 } | |
649 | |
650 | |
651 TEST(BuildScheduleEmpty) { | |
652 HandleAndZoneScope scope; | |
653 Graph graph(scope.main_zone()); | |
654 CommonOperatorBuilder builder(scope.main_zone()); | |
655 graph.SetStart(graph.NewNode(builder.Start(0))); | |
656 graph.SetEnd(graph.NewNode(builder.End(), graph.start())); | |
657 | |
658 USE(Scheduler::ComputeSchedule(scope.main_zone(), &graph)); | |
659 } | |
660 | |
661 | |
662 TEST(BuildScheduleOneParameter) { | |
663 HandleAndZoneScope scope; | |
664 Graph graph(scope.main_zone()); | |
665 CommonOperatorBuilder builder(scope.main_zone()); | |
666 graph.SetStart(graph.NewNode(builder.Start(0))); | |
667 | |
668 Node* p1 = graph.NewNode(builder.Parameter(0), graph.start()); | |
669 Node* ret = graph.NewNode(builder.Return(), p1, graph.start(), graph.start()); | |
670 | |
671 graph.SetEnd(graph.NewNode(builder.End(), ret)); | |
672 | |
673 USE(Scheduler::ComputeSchedule(scope.main_zone(), &graph)); | |
674 } | |
675 | |
676 | |
677 TEST(BuildScheduleIfSplit) { | |
678 HandleAndZoneScope scope; | |
679 Graph graph(scope.main_zone()); | |
680 CommonOperatorBuilder builder(scope.main_zone()); | |
681 JSOperatorBuilder js_builder(scope.main_zone()); | |
682 graph.SetStart(graph.NewNode(builder.Start(3))); | |
683 | |
684 Node* p1 = graph.NewNode(builder.Parameter(0), graph.start()); | |
685 Node* p2 = graph.NewNode(builder.Parameter(1), graph.start()); | |
686 Node* p3 = graph.NewNode(builder.Parameter(2), graph.start()); | |
687 Node* p4 = graph.NewNode(builder.Parameter(3), graph.start()); | |
688 Node* p5 = graph.NewNode(builder.Parameter(4), graph.start()); | |
689 Node* cmp = graph.NewNode(js_builder.LessThanOrEqual(), p1, p2, p3, | |
690 graph.start(), graph.start()); | |
691 Node* branch = graph.NewNode(builder.Branch(), cmp, graph.start()); | |
692 Node* true_branch = graph.NewNode(builder.IfTrue(), branch); | |
693 Node* false_branch = graph.NewNode(builder.IfFalse(), branch); | |
694 | |
695 Node* ret1 = graph.NewNode(builder.Return(), p4, graph.start(), true_branch); | |
696 Node* ret2 = graph.NewNode(builder.Return(), p5, graph.start(), false_branch); | |
697 Node* merge = graph.NewNode(builder.Merge(2), ret1, ret2); | |
698 graph.SetEnd(graph.NewNode(builder.End(), merge)); | |
699 | |
700 ComputeAndVerifySchedule(13, &graph); | |
701 } | |
702 | |
703 | |
704 TEST(BuildScheduleIfSplitWithEffects) { | |
705 HandleAndZoneScope scope; | |
706 Isolate* isolate = scope.main_isolate(); | |
707 Graph graph(scope.main_zone()); | |
708 CommonOperatorBuilder common_builder(scope.main_zone()); | |
709 JSOperatorBuilder js_builder(scope.main_zone()); | |
710 const Operator* op; | |
711 | |
712 Handle<HeapObject> object = | |
713 Handle<HeapObject>(isolate->heap()->undefined_value(), isolate); | |
714 Unique<HeapObject> unique_constant = | |
715 Unique<HeapObject>::CreateUninitialized(object); | |
716 | |
717 // Manually transcripted code for: | |
718 // function turbo_fan_test(a, b, c, y) { | |
719 // if (a < b) { | |
720 // return a + b - c * c - a + y; | |
721 // } else { | |
722 // return c * c - a; | |
723 // } | |
724 // } | |
725 op = common_builder.Start(0); | |
726 Node* n0 = graph.NewNode(op); | |
727 USE(n0); | |
728 Node* nil = graph.NewNode(common_builder.Dead()); | |
729 op = common_builder.End(); | |
730 Node* n23 = graph.NewNode(op, nil); | |
731 USE(n23); | |
732 op = common_builder.Merge(2); | |
733 Node* n22 = graph.NewNode(op, nil, nil); | |
734 USE(n22); | |
735 op = common_builder.Return(); | |
736 Node* n16 = graph.NewNode(op, nil, nil, nil); | |
737 USE(n16); | |
738 op = js_builder.Add(); | |
739 Node* n15 = graph.NewNode(op, nil, nil, nil, nil, nil); | |
740 USE(n15); | |
741 op = js_builder.Subtract(); | |
742 Node* n14 = graph.NewNode(op, nil, nil, nil, nil, nil); | |
743 USE(n14); | |
744 op = js_builder.Subtract(); | |
745 Node* n13 = graph.NewNode(op, nil, nil, nil, nil, nil); | |
746 USE(n13); | |
747 op = js_builder.Add(); | |
748 Node* n11 = graph.NewNode(op, nil, nil, nil, nil, nil); | |
749 USE(n11); | |
750 op = common_builder.Parameter(0); | |
751 Node* n2 = graph.NewNode(op, n0); | |
752 USE(n2); | |
753 n11->ReplaceInput(0, n2); | |
754 op = common_builder.Parameter(0); | |
755 Node* n3 = graph.NewNode(op, n0); | |
756 USE(n3); | |
757 n11->ReplaceInput(1, n3); | |
758 op = common_builder.HeapConstant(unique_constant); | |
759 Node* n7 = graph.NewNode(op); | |
760 USE(n7); | |
761 n11->ReplaceInput(2, n7); | |
762 op = js_builder.LessThan(); | |
763 Node* n8 = graph.NewNode(op, nil, nil, nil, nil, nil); | |
764 USE(n8); | |
765 n8->ReplaceInput(0, n2); | |
766 n8->ReplaceInput(1, n3); | |
767 n8->ReplaceInput(2, n7); | |
768 n8->ReplaceInput(3, n0); | |
769 n8->ReplaceInput(4, n0); | |
770 n11->ReplaceInput(3, n8); | |
771 op = common_builder.IfTrue(); | |
772 Node* n10 = graph.NewNode(op, nil); | |
773 USE(n10); | |
774 op = common_builder.Branch(); | |
775 Node* n9 = graph.NewNode(op, nil, nil); | |
776 USE(n9); | |
777 n9->ReplaceInput(0, n8); | |
778 n9->ReplaceInput(1, n0); | |
779 n10->ReplaceInput(0, n9); | |
780 n11->ReplaceInput(4, n10); | |
781 n13->ReplaceInput(0, n11); | |
782 op = js_builder.Multiply(); | |
783 Node* n12 = graph.NewNode(op, nil, nil, nil, nil, nil); | |
784 USE(n12); | |
785 op = common_builder.Parameter(0); | |
786 Node* n4 = graph.NewNode(op, n0); | |
787 USE(n4); | |
788 n12->ReplaceInput(0, n4); | |
789 n12->ReplaceInput(1, n4); | |
790 n12->ReplaceInput(2, n7); | |
791 n12->ReplaceInput(3, n11); | |
792 n12->ReplaceInput(4, n10); | |
793 n13->ReplaceInput(1, n12); | |
794 n13->ReplaceInput(2, n7); | |
795 n13->ReplaceInput(3, n12); | |
796 n13->ReplaceInput(4, n10); | |
797 n14->ReplaceInput(0, n13); | |
798 n14->ReplaceInput(1, n2); | |
799 n14->ReplaceInput(2, n7); | |
800 n14->ReplaceInput(3, n13); | |
801 n14->ReplaceInput(4, n10); | |
802 n15->ReplaceInput(0, n14); | |
803 op = common_builder.Parameter(0); | |
804 Node* n5 = graph.NewNode(op, n0); | |
805 USE(n5); | |
806 n15->ReplaceInput(1, n5); | |
807 n15->ReplaceInput(2, n7); | |
808 n15->ReplaceInput(3, n14); | |
809 n15->ReplaceInput(4, n10); | |
810 n16->ReplaceInput(0, n15); | |
811 n16->ReplaceInput(1, n15); | |
812 n16->ReplaceInput(2, n10); | |
813 n22->ReplaceInput(0, n16); | |
814 op = common_builder.Return(); | |
815 Node* n21 = graph.NewNode(op, nil, nil, nil); | |
816 USE(n21); | |
817 op = js_builder.Subtract(); | |
818 Node* n20 = graph.NewNode(op, nil, nil, nil, nil, nil); | |
819 USE(n20); | |
820 op = js_builder.Multiply(); | |
821 Node* n19 = graph.NewNode(op, nil, nil, nil, nil, nil); | |
822 USE(n19); | |
823 n19->ReplaceInput(0, n4); | |
824 n19->ReplaceInput(1, n4); | |
825 n19->ReplaceInput(2, n7); | |
826 n19->ReplaceInput(3, n8); | |
827 op = common_builder.IfFalse(); | |
828 Node* n18 = graph.NewNode(op, nil); | |
829 USE(n18); | |
830 n18->ReplaceInput(0, n9); | |
831 n19->ReplaceInput(4, n18); | |
832 n20->ReplaceInput(0, n19); | |
833 n20->ReplaceInput(1, n2); | |
834 n20->ReplaceInput(2, n7); | |
835 n20->ReplaceInput(3, n19); | |
836 n20->ReplaceInput(4, n18); | |
837 n21->ReplaceInput(0, n20); | |
838 n21->ReplaceInput(1, n20); | |
839 n21->ReplaceInput(2, n18); | |
840 n22->ReplaceInput(1, n21); | |
841 n23->ReplaceInput(0, n22); | |
842 | |
843 graph.SetStart(n0); | |
844 graph.SetEnd(n23); | |
845 | |
846 ComputeAndVerifySchedule(20, &graph); | |
847 } | |
848 | |
849 | |
850 TEST(BuildScheduleSimpleLoop) { | |
851 HandleAndZoneScope scope; | |
852 Isolate* isolate = scope.main_isolate(); | |
853 Graph graph(scope.main_zone()); | |
854 CommonOperatorBuilder common_builder(scope.main_zone()); | |
855 JSOperatorBuilder js_builder(scope.main_zone()); | |
856 const Operator* op; | |
857 | |
858 Handle<HeapObject> object = | |
859 Handle<HeapObject>(isolate->heap()->undefined_value(), isolate); | |
860 Unique<HeapObject> unique_constant = | |
861 Unique<HeapObject>::CreateUninitialized(object); | |
862 | |
863 // Manually transcripted code for: | |
864 // function turbo_fan_test(a, b) { | |
865 // while (a < b) { | |
866 // a++; | |
867 // } | |
868 // return a; | |
869 // } | |
870 op = common_builder.Start(0); | |
871 Node* n0 = graph.NewNode(op); | |
872 USE(n0); | |
873 Node* nil = graph.NewNode(common_builder.Dead()); | |
874 op = common_builder.End(); | |
875 Node* n20 = graph.NewNode(op, nil); | |
876 USE(n20); | |
877 op = common_builder.Return(); | |
878 Node* n19 = graph.NewNode(op, nil, nil, nil); | |
879 USE(n19); | |
880 op = common_builder.Phi(kMachAnyTagged, 2); | |
881 Node* n8 = graph.NewNode(op, nil, nil, nil); | |
882 USE(n8); | |
883 op = common_builder.Parameter(0); | |
884 Node* n2 = graph.NewNode(op, n0); | |
885 USE(n2); | |
886 n8->ReplaceInput(0, n2); | |
887 op = js_builder.Add(); | |
888 Node* n18 = graph.NewNode(op, nil, nil, nil, nil, nil); | |
889 USE(n18); | |
890 op = js_builder.ToNumber(); | |
891 Node* n16 = graph.NewNode(op, nil, nil, nil, nil); | |
892 USE(n16); | |
893 n16->ReplaceInput(0, n8); | |
894 op = common_builder.HeapConstant(unique_constant); | |
895 Node* n5 = graph.NewNode(op); | |
896 USE(n5); | |
897 n16->ReplaceInput(1, n5); | |
898 op = js_builder.LessThan(); | |
899 Node* n12 = graph.NewNode(op, nil, nil, nil, nil, nil); | |
900 USE(n12); | |
901 n12->ReplaceInput(0, n8); | |
902 op = common_builder.Phi(kMachAnyTagged, 2); | |
903 Node* n9 = graph.NewNode(op, nil, nil, nil); | |
904 USE(n9); | |
905 op = common_builder.Parameter(0); | |
906 Node* n3 = graph.NewNode(op, n0); | |
907 USE(n3); | |
908 n9->ReplaceInput(0, n3); | |
909 n9->ReplaceInput(1, n9); | |
910 op = common_builder.Loop(2); | |
911 Node* n6 = graph.NewNode(op, nil, nil); | |
912 USE(n6); | |
913 n6->ReplaceInput(0, n0); | |
914 op = common_builder.IfTrue(); | |
915 Node* n14 = graph.NewNode(op, nil); | |
916 USE(n14); | |
917 op = common_builder.Branch(); | |
918 Node* n13 = graph.NewNode(op, nil, nil); | |
919 USE(n13); | |
920 n13->ReplaceInput(0, n12); | |
921 n13->ReplaceInput(1, n6); | |
922 n14->ReplaceInput(0, n13); | |
923 n6->ReplaceInput(1, n14); | |
924 n9->ReplaceInput(2, n6); | |
925 n12->ReplaceInput(1, n9); | |
926 n12->ReplaceInput(2, n5); | |
927 op = common_builder.Phi(kMachAnyTagged, 2); | |
928 Node* n10 = graph.NewNode(op, nil, nil, nil); | |
929 USE(n10); | |
930 n10->ReplaceInput(0, n0); | |
931 n10->ReplaceInput(1, n18); | |
932 n10->ReplaceInput(2, n6); | |
933 n12->ReplaceInput(3, n10); | |
934 n12->ReplaceInput(4, n6); | |
935 n16->ReplaceInput(2, n12); | |
936 n16->ReplaceInput(3, n14); | |
937 n18->ReplaceInput(0, n16); | |
938 op = common_builder.NumberConstant(0); | |
939 Node* n17 = graph.NewNode(op); | |
940 USE(n17); | |
941 n18->ReplaceInput(1, n17); | |
942 n18->ReplaceInput(2, n5); | |
943 n18->ReplaceInput(3, n16); | |
944 n18->ReplaceInput(4, n14); | |
945 n8->ReplaceInput(1, n18); | |
946 n8->ReplaceInput(2, n6); | |
947 n19->ReplaceInput(0, n8); | |
948 n19->ReplaceInput(1, n12); | |
949 op = common_builder.IfFalse(); | |
950 Node* n15 = graph.NewNode(op, nil); | |
951 USE(n15); | |
952 n15->ReplaceInput(0, n13); | |
953 n19->ReplaceInput(2, n15); | |
954 n20->ReplaceInput(0, n19); | |
955 | |
956 graph.SetStart(n0); | |
957 graph.SetEnd(n20); | |
958 | |
959 ComputeAndVerifySchedule(19, &graph); | |
960 } | |
961 | |
962 | |
963 TEST(BuildScheduleComplexLoops) { | |
964 HandleAndZoneScope scope; | |
965 Isolate* isolate = scope.main_isolate(); | |
966 Graph graph(scope.main_zone()); | |
967 CommonOperatorBuilder common_builder(scope.main_zone()); | |
968 JSOperatorBuilder js_builder(scope.main_zone()); | |
969 const Operator* op; | |
970 | |
971 Handle<HeapObject> object = | |
972 Handle<HeapObject>(isolate->heap()->undefined_value(), isolate); | |
973 Unique<HeapObject> unique_constant = | |
974 Unique<HeapObject>::CreateUninitialized(object); | |
975 | |
976 // Manually transcripted code for: | |
977 // function turbo_fan_test(a, b, c) { | |
978 // while (a < b) { | |
979 // a++; | |
980 // while (c < b) { | |
981 // c++; | |
982 // } | |
983 // } | |
984 // while (a < b) { | |
985 // a += 2; | |
986 // } | |
987 // return a; | |
988 // } | |
989 op = common_builder.Start(0); | |
990 Node* n0 = graph.NewNode(op); | |
991 USE(n0); | |
992 Node* nil = graph.NewNode(common_builder.Dead()); | |
993 op = common_builder.End(); | |
994 Node* n46 = graph.NewNode(op, nil); | |
995 USE(n46); | |
996 op = common_builder.Return(); | |
997 Node* n45 = graph.NewNode(op, nil, nil, nil); | |
998 USE(n45); | |
999 op = common_builder.Phi(kMachAnyTagged, 2); | |
1000 Node* n35 = graph.NewNode(op, nil, nil, nil); | |
1001 USE(n35); | |
1002 op = common_builder.Phi(kMachAnyTagged, 2); | |
1003 Node* n9 = graph.NewNode(op, nil, nil, nil); | |
1004 USE(n9); | |
1005 op = common_builder.Parameter(0); | |
1006 Node* n2 = graph.NewNode(op, n0); | |
1007 USE(n2); | |
1008 n9->ReplaceInput(0, n2); | |
1009 op = common_builder.Phi(kMachAnyTagged, 2); | |
1010 Node* n23 = graph.NewNode(op, nil, nil, nil); | |
1011 USE(n23); | |
1012 op = js_builder.Add(); | |
1013 Node* n20 = graph.NewNode(op, nil, nil, nil, nil, nil); | |
1014 USE(n20); | |
1015 op = js_builder.ToNumber(); | |
1016 Node* n18 = graph.NewNode(op, nil, nil, nil, nil); | |
1017 USE(n18); | |
1018 n18->ReplaceInput(0, n9); | |
1019 op = common_builder.HeapConstant(unique_constant); | |
1020 Node* n6 = graph.NewNode(op); | |
1021 USE(n6); | |
1022 n18->ReplaceInput(1, n6); | |
1023 op = js_builder.LessThan(); | |
1024 Node* n14 = graph.NewNode(op, nil, nil, nil, nil, nil); | |
1025 USE(n14); | |
1026 n14->ReplaceInput(0, n9); | |
1027 op = common_builder.Phi(kMachAnyTagged, 2); | |
1028 Node* n10 = graph.NewNode(op, nil, nil, nil); | |
1029 USE(n10); | |
1030 op = common_builder.Parameter(0); | |
1031 Node* n3 = graph.NewNode(op, n0); | |
1032 USE(n3); | |
1033 n10->ReplaceInput(0, n3); | |
1034 op = common_builder.Phi(kMachAnyTagged, 2); | |
1035 Node* n24 = graph.NewNode(op, nil, nil, nil); | |
1036 USE(n24); | |
1037 n24->ReplaceInput(0, n10); | |
1038 n24->ReplaceInput(1, n24); | |
1039 op = common_builder.Loop(2); | |
1040 Node* n21 = graph.NewNode(op, nil, nil); | |
1041 USE(n21); | |
1042 op = common_builder.IfTrue(); | |
1043 Node* n16 = graph.NewNode(op, nil); | |
1044 USE(n16); | |
1045 op = common_builder.Branch(); | |
1046 Node* n15 = graph.NewNode(op, nil, nil); | |
1047 USE(n15); | |
1048 n15->ReplaceInput(0, n14); | |
1049 op = common_builder.Loop(2); | |
1050 Node* n7 = graph.NewNode(op, nil, nil); | |
1051 USE(n7); | |
1052 n7->ReplaceInput(0, n0); | |
1053 op = common_builder.IfFalse(); | |
1054 Node* n30 = graph.NewNode(op, nil); | |
1055 USE(n30); | |
1056 op = common_builder.Branch(); | |
1057 Node* n28 = graph.NewNode(op, nil, nil); | |
1058 USE(n28); | |
1059 op = js_builder.LessThan(); | |
1060 Node* n27 = graph.NewNode(op, nil, nil, nil, nil, nil); | |
1061 USE(n27); | |
1062 op = common_builder.Phi(kMachAnyTagged, 2); | |
1063 Node* n25 = graph.NewNode(op, nil, nil, nil); | |
1064 USE(n25); | |
1065 op = common_builder.Phi(kMachAnyTagged, 2); | |
1066 Node* n11 = graph.NewNode(op, nil, nil, nil); | |
1067 USE(n11); | |
1068 op = common_builder.Parameter(0); | |
1069 Node* n4 = graph.NewNode(op, n0); | |
1070 USE(n4); | |
1071 n11->ReplaceInput(0, n4); | |
1072 n11->ReplaceInput(1, n25); | |
1073 n11->ReplaceInput(2, n7); | |
1074 n25->ReplaceInput(0, n11); | |
1075 op = js_builder.Add(); | |
1076 Node* n32 = graph.NewNode(op, nil, nil, nil, nil, nil); | |
1077 USE(n32); | |
1078 op = js_builder.ToNumber(); | |
1079 Node* n31 = graph.NewNode(op, nil, nil, nil, nil); | |
1080 USE(n31); | |
1081 n31->ReplaceInput(0, n25); | |
1082 n31->ReplaceInput(1, n6); | |
1083 n31->ReplaceInput(2, n27); | |
1084 op = common_builder.IfTrue(); | |
1085 Node* n29 = graph.NewNode(op, nil); | |
1086 USE(n29); | |
1087 n29->ReplaceInput(0, n28); | |
1088 n31->ReplaceInput(3, n29); | |
1089 n32->ReplaceInput(0, n31); | |
1090 op = common_builder.NumberConstant(0); | |
1091 Node* n19 = graph.NewNode(op); | |
1092 USE(n19); | |
1093 n32->ReplaceInput(1, n19); | |
1094 n32->ReplaceInput(2, n6); | |
1095 n32->ReplaceInput(3, n31); | |
1096 n32->ReplaceInput(4, n29); | |
1097 n25->ReplaceInput(1, n32); | |
1098 n25->ReplaceInput(2, n21); | |
1099 n27->ReplaceInput(0, n25); | |
1100 n27->ReplaceInput(1, n24); | |
1101 n27->ReplaceInput(2, n6); | |
1102 op = common_builder.Phi(kMachAnyTagged, 2); | |
1103 Node* n26 = graph.NewNode(op, nil, nil, nil); | |
1104 USE(n26); | |
1105 n26->ReplaceInput(0, n20); | |
1106 n26->ReplaceInput(1, n32); | |
1107 n26->ReplaceInput(2, n21); | |
1108 n27->ReplaceInput(3, n26); | |
1109 n27->ReplaceInput(4, n21); | |
1110 n28->ReplaceInput(0, n27); | |
1111 n28->ReplaceInput(1, n21); | |
1112 n30->ReplaceInput(0, n28); | |
1113 n7->ReplaceInput(1, n30); | |
1114 n15->ReplaceInput(1, n7); | |
1115 n16->ReplaceInput(0, n15); | |
1116 n21->ReplaceInput(0, n16); | |
1117 n21->ReplaceInput(1, n29); | |
1118 n24->ReplaceInput(2, n21); | |
1119 n10->ReplaceInput(1, n24); | |
1120 n10->ReplaceInput(2, n7); | |
1121 n14->ReplaceInput(1, n10); | |
1122 n14->ReplaceInput(2, n6); | |
1123 op = common_builder.Phi(kMachAnyTagged, 2); | |
1124 Node* n12 = graph.NewNode(op, nil, nil, nil); | |
1125 USE(n12); | |
1126 n12->ReplaceInput(0, n0); | |
1127 n12->ReplaceInput(1, n27); | |
1128 n12->ReplaceInput(2, n7); | |
1129 n14->ReplaceInput(3, n12); | |
1130 n14->ReplaceInput(4, n7); | |
1131 n18->ReplaceInput(2, n14); | |
1132 n18->ReplaceInput(3, n16); | |
1133 n20->ReplaceInput(0, n18); | |
1134 n20->ReplaceInput(1, n19); | |
1135 n20->ReplaceInput(2, n6); | |
1136 n20->ReplaceInput(3, n18); | |
1137 n20->ReplaceInput(4, n16); | |
1138 n23->ReplaceInput(0, n20); | |
1139 n23->ReplaceInput(1, n23); | |
1140 n23->ReplaceInput(2, n21); | |
1141 n9->ReplaceInput(1, n23); | |
1142 n9->ReplaceInput(2, n7); | |
1143 n35->ReplaceInput(0, n9); | |
1144 op = js_builder.Add(); | |
1145 Node* n44 = graph.NewNode(op, nil, nil, nil, nil, nil); | |
1146 USE(n44); | |
1147 n44->ReplaceInput(0, n35); | |
1148 op = common_builder.NumberConstant(0); | |
1149 Node* n43 = graph.NewNode(op); | |
1150 USE(n43); | |
1151 n44->ReplaceInput(1, n43); | |
1152 n44->ReplaceInput(2, n6); | |
1153 op = js_builder.LessThan(); | |
1154 Node* n39 = graph.NewNode(op, nil, nil, nil, nil, nil); | |
1155 USE(n39); | |
1156 n39->ReplaceInput(0, n35); | |
1157 op = common_builder.Phi(kMachAnyTagged, 2); | |
1158 Node* n36 = graph.NewNode(op, nil, nil, nil); | |
1159 USE(n36); | |
1160 n36->ReplaceInput(0, n10); | |
1161 n36->ReplaceInput(1, n36); | |
1162 op = common_builder.Loop(2); | |
1163 Node* n33 = graph.NewNode(op, nil, nil); | |
1164 USE(n33); | |
1165 op = common_builder.IfFalse(); | |
1166 Node* n17 = graph.NewNode(op, nil); | |
1167 USE(n17); | |
1168 n17->ReplaceInput(0, n15); | |
1169 n33->ReplaceInput(0, n17); | |
1170 op = common_builder.IfTrue(); | |
1171 Node* n41 = graph.NewNode(op, nil); | |
1172 USE(n41); | |
1173 op = common_builder.Branch(); | |
1174 Node* n40 = graph.NewNode(op, nil, nil); | |
1175 USE(n40); | |
1176 n40->ReplaceInput(0, n39); | |
1177 n40->ReplaceInput(1, n33); | |
1178 n41->ReplaceInput(0, n40); | |
1179 n33->ReplaceInput(1, n41); | |
1180 n36->ReplaceInput(2, n33); | |
1181 n39->ReplaceInput(1, n36); | |
1182 n39->ReplaceInput(2, n6); | |
1183 op = common_builder.Phi(kMachAnyTagged, 2); | |
1184 Node* n38 = graph.NewNode(op, nil, nil, nil); | |
1185 USE(n38); | |
1186 n38->ReplaceInput(0, n14); | |
1187 n38->ReplaceInput(1, n44); | |
1188 n38->ReplaceInput(2, n33); | |
1189 n39->ReplaceInput(3, n38); | |
1190 n39->ReplaceInput(4, n33); | |
1191 n44->ReplaceInput(3, n39); | |
1192 n44->ReplaceInput(4, n41); | |
1193 n35->ReplaceInput(1, n44); | |
1194 n35->ReplaceInput(2, n33); | |
1195 n45->ReplaceInput(0, n35); | |
1196 n45->ReplaceInput(1, n39); | |
1197 op = common_builder.IfFalse(); | |
1198 Node* n42 = graph.NewNode(op, nil); | |
1199 USE(n42); | |
1200 n42->ReplaceInput(0, n40); | |
1201 n45->ReplaceInput(2, n42); | |
1202 n46->ReplaceInput(0, n45); | |
1203 | |
1204 graph.SetStart(n0); | |
1205 graph.SetEnd(n46); | |
1206 | |
1207 ComputeAndVerifySchedule(46, &graph); | |
1208 } | |
1209 | |
1210 | |
1211 TEST(BuildScheduleBreakAndContinue) { | |
1212 HandleAndZoneScope scope; | |
1213 Isolate* isolate = scope.main_isolate(); | |
1214 Graph graph(scope.main_zone()); | |
1215 CommonOperatorBuilder common_builder(scope.main_zone()); | |
1216 JSOperatorBuilder js_builder(scope.main_zone()); | |
1217 const Operator* op; | |
1218 | |
1219 Handle<HeapObject> object = | |
1220 Handle<HeapObject>(isolate->heap()->undefined_value(), isolate); | |
1221 Unique<HeapObject> unique_constant = | |
1222 Unique<HeapObject>::CreateUninitialized(object); | |
1223 | |
1224 // Manually transcripted code for: | |
1225 // function turbo_fan_test(a, b, c) { | |
1226 // var d = 0; | |
1227 // while (a < b) { | |
1228 // a++; | |
1229 // while (c < b) { | |
1230 // c++; | |
1231 // if (d == 0) break; | |
1232 // a++; | |
1233 // } | |
1234 // if (a == 1) continue; | |
1235 // d++; | |
1236 // } | |
1237 // return a + d; | |
1238 // } | |
1239 op = common_builder.Start(0); | |
1240 Node* n0 = graph.NewNode(op); | |
1241 USE(n0); | |
1242 Node* nil = graph.NewNode(common_builder.Dead()); | |
1243 op = common_builder.End(); | |
1244 Node* n58 = graph.NewNode(op, nil); | |
1245 USE(n58); | |
1246 op = common_builder.Return(); | |
1247 Node* n57 = graph.NewNode(op, nil, nil, nil); | |
1248 USE(n57); | |
1249 op = js_builder.Add(); | |
1250 Node* n56 = graph.NewNode(op, nil, nil, nil, nil, nil); | |
1251 USE(n56); | |
1252 op = common_builder.Phi(kMachAnyTagged, 2); | |
1253 Node* n10 = graph.NewNode(op, nil, nil, nil); | |
1254 USE(n10); | |
1255 op = common_builder.Parameter(0); | |
1256 Node* n2 = graph.NewNode(op, n0); | |
1257 USE(n2); | |
1258 n10->ReplaceInput(0, n2); | |
1259 op = common_builder.Phi(kMachAnyTagged, 2); | |
1260 Node* n25 = graph.NewNode(op, nil, nil, nil); | |
1261 USE(n25); | |
1262 op = js_builder.Add(); | |
1263 Node* n22 = graph.NewNode(op, nil, nil, nil, nil, nil); | |
1264 USE(n22); | |
1265 op = js_builder.ToNumber(); | |
1266 Node* n20 = graph.NewNode(op, nil, nil, nil, nil); | |
1267 USE(n20); | |
1268 n20->ReplaceInput(0, n10); | |
1269 op = common_builder.HeapConstant(unique_constant); | |
1270 Node* n6 = graph.NewNode(op); | |
1271 USE(n6); | |
1272 n20->ReplaceInput(1, n6); | |
1273 op = js_builder.LessThan(); | |
1274 Node* n16 = graph.NewNode(op, nil, nil, nil, nil, nil); | |
1275 USE(n16); | |
1276 n16->ReplaceInput(0, n10); | |
1277 op = common_builder.Phi(kMachAnyTagged, 2); | |
1278 Node* n11 = graph.NewNode(op, nil, nil, nil); | |
1279 USE(n11); | |
1280 op = common_builder.Parameter(0); | |
1281 Node* n3 = graph.NewNode(op, n0); | |
1282 USE(n3); | |
1283 n11->ReplaceInput(0, n3); | |
1284 op = common_builder.Phi(kMachAnyTagged, 2); | |
1285 Node* n26 = graph.NewNode(op, nil, nil, nil); | |
1286 USE(n26); | |
1287 n26->ReplaceInput(0, n11); | |
1288 n26->ReplaceInput(1, n26); | |
1289 op = common_builder.Loop(2); | |
1290 Node* n23 = graph.NewNode(op, nil, nil); | |
1291 USE(n23); | |
1292 op = common_builder.IfTrue(); | |
1293 Node* n18 = graph.NewNode(op, nil); | |
1294 USE(n18); | |
1295 op = common_builder.Branch(); | |
1296 Node* n17 = graph.NewNode(op, nil, nil); | |
1297 USE(n17); | |
1298 n17->ReplaceInput(0, n16); | |
1299 op = common_builder.Loop(2); | |
1300 Node* n8 = graph.NewNode(op, nil, nil); | |
1301 USE(n8); | |
1302 n8->ReplaceInput(0, n0); | |
1303 op = common_builder.Merge(2); | |
1304 Node* n53 = graph.NewNode(op, nil, nil); | |
1305 USE(n53); | |
1306 op = common_builder.IfTrue(); | |
1307 Node* n49 = graph.NewNode(op, nil); | |
1308 USE(n49); | |
1309 op = common_builder.Branch(); | |
1310 Node* n48 = graph.NewNode(op, nil, nil); | |
1311 USE(n48); | |
1312 op = js_builder.Equal(); | |
1313 Node* n47 = graph.NewNode(op, nil, nil, nil, nil, nil); | |
1314 USE(n47); | |
1315 n47->ReplaceInput(0, n25); | |
1316 op = common_builder.NumberConstant(0); | |
1317 Node* n46 = graph.NewNode(op); | |
1318 USE(n46); | |
1319 n47->ReplaceInput(1, n46); | |
1320 n47->ReplaceInput(2, n6); | |
1321 op = common_builder.Phi(kMachAnyTagged, 2); | |
1322 Node* n42 = graph.NewNode(op, nil, nil, nil); | |
1323 USE(n42); | |
1324 op = js_builder.LessThan(); | |
1325 Node* n30 = graph.NewNode(op, nil, nil, nil, nil, nil); | |
1326 USE(n30); | |
1327 op = common_builder.Phi(kMachAnyTagged, 2); | |
1328 Node* n27 = graph.NewNode(op, nil, nil, nil); | |
1329 USE(n27); | |
1330 op = common_builder.Phi(kMachAnyTagged, 2); | |
1331 Node* n12 = graph.NewNode(op, nil, nil, nil); | |
1332 USE(n12); | |
1333 op = common_builder.Parameter(0); | |
1334 Node* n4 = graph.NewNode(op, n0); | |
1335 USE(n4); | |
1336 n12->ReplaceInput(0, n4); | |
1337 op = common_builder.Phi(kMachAnyTagged, 2); | |
1338 Node* n41 = graph.NewNode(op, nil, nil, nil); | |
1339 USE(n41); | |
1340 n41->ReplaceInput(0, n27); | |
1341 op = js_builder.Add(); | |
1342 Node* n35 = graph.NewNode(op, nil, nil, nil, nil, nil); | |
1343 USE(n35); | |
1344 op = js_builder.ToNumber(); | |
1345 Node* n34 = graph.NewNode(op, nil, nil, nil, nil); | |
1346 USE(n34); | |
1347 n34->ReplaceInput(0, n27); | |
1348 n34->ReplaceInput(1, n6); | |
1349 n34->ReplaceInput(2, n30); | |
1350 op = common_builder.IfTrue(); | |
1351 Node* n32 = graph.NewNode(op, nil); | |
1352 USE(n32); | |
1353 op = common_builder.Branch(); | |
1354 Node* n31 = graph.NewNode(op, nil, nil); | |
1355 USE(n31); | |
1356 n31->ReplaceInput(0, n30); | |
1357 n31->ReplaceInput(1, n23); | |
1358 n32->ReplaceInput(0, n31); | |
1359 n34->ReplaceInput(3, n32); | |
1360 n35->ReplaceInput(0, n34); | |
1361 op = common_builder.NumberConstant(0); | |
1362 Node* n21 = graph.NewNode(op); | |
1363 USE(n21); | |
1364 n35->ReplaceInput(1, n21); | |
1365 n35->ReplaceInput(2, n6); | |
1366 n35->ReplaceInput(3, n34); | |
1367 n35->ReplaceInput(4, n32); | |
1368 n41->ReplaceInput(1, n35); | |
1369 op = common_builder.Merge(2); | |
1370 Node* n40 = graph.NewNode(op, nil, nil); | |
1371 USE(n40); | |
1372 op = common_builder.IfFalse(); | |
1373 Node* n33 = graph.NewNode(op, nil); | |
1374 USE(n33); | |
1375 n33->ReplaceInput(0, n31); | |
1376 n40->ReplaceInput(0, n33); | |
1377 op = common_builder.IfTrue(); | |
1378 Node* n39 = graph.NewNode(op, nil); | |
1379 USE(n39); | |
1380 op = common_builder.Branch(); | |
1381 Node* n38 = graph.NewNode(op, nil, nil); | |
1382 USE(n38); | |
1383 op = js_builder.Equal(); | |
1384 Node* n37 = graph.NewNode(op, nil, nil, nil, nil, nil); | |
1385 USE(n37); | |
1386 op = common_builder.Phi(kMachAnyTagged, 2); | |
1387 Node* n28 = graph.NewNode(op, nil, nil, nil); | |
1388 USE(n28); | |
1389 op = common_builder.Phi(kMachAnyTagged, 2); | |
1390 Node* n13 = graph.NewNode(op, nil, nil, nil); | |
1391 USE(n13); | |
1392 op = common_builder.NumberConstant(0); | |
1393 Node* n7 = graph.NewNode(op); | |
1394 USE(n7); | |
1395 n13->ReplaceInput(0, n7); | |
1396 op = common_builder.Phi(kMachAnyTagged, 2); | |
1397 Node* n54 = graph.NewNode(op, nil, nil, nil); | |
1398 USE(n54); | |
1399 n54->ReplaceInput(0, n28); | |
1400 op = js_builder.Add(); | |
1401 Node* n52 = graph.NewNode(op, nil, nil, nil, nil, nil); | |
1402 USE(n52); | |
1403 op = js_builder.ToNumber(); | |
1404 Node* n51 = graph.NewNode(op, nil, nil, nil, nil); | |
1405 USE(n51); | |
1406 n51->ReplaceInput(0, n28); | |
1407 n51->ReplaceInput(1, n6); | |
1408 n51->ReplaceInput(2, n47); | |
1409 op = common_builder.IfFalse(); | |
1410 Node* n50 = graph.NewNode(op, nil); | |
1411 USE(n50); | |
1412 n50->ReplaceInput(0, n48); | |
1413 n51->ReplaceInput(3, n50); | |
1414 n52->ReplaceInput(0, n51); | |
1415 n52->ReplaceInput(1, n21); | |
1416 n52->ReplaceInput(2, n6); | |
1417 n52->ReplaceInput(3, n51); | |
1418 n52->ReplaceInput(4, n50); | |
1419 n54->ReplaceInput(1, n52); | |
1420 n54->ReplaceInput(2, n53); | |
1421 n13->ReplaceInput(1, n54); | |
1422 n13->ReplaceInput(2, n8); | |
1423 n28->ReplaceInput(0, n13); | |
1424 n28->ReplaceInput(1, n28); | |
1425 n28->ReplaceInput(2, n23); | |
1426 n37->ReplaceInput(0, n28); | |
1427 op = common_builder.NumberConstant(0); | |
1428 Node* n36 = graph.NewNode(op); | |
1429 USE(n36); | |
1430 n37->ReplaceInput(1, n36); | |
1431 n37->ReplaceInput(2, n6); | |
1432 n37->ReplaceInput(3, n35); | |
1433 n37->ReplaceInput(4, n32); | |
1434 n38->ReplaceInput(0, n37); | |
1435 n38->ReplaceInput(1, n32); | |
1436 n39->ReplaceInput(0, n38); | |
1437 n40->ReplaceInput(1, n39); | |
1438 n41->ReplaceInput(2, n40); | |
1439 n12->ReplaceInput(1, n41); | |
1440 n12->ReplaceInput(2, n8); | |
1441 n27->ReplaceInput(0, n12); | |
1442 n27->ReplaceInput(1, n35); | |
1443 n27->ReplaceInput(2, n23); | |
1444 n30->ReplaceInput(0, n27); | |
1445 n30->ReplaceInput(1, n26); | |
1446 n30->ReplaceInput(2, n6); | |
1447 op = common_builder.Phi(kMachAnyTagged, 2); | |
1448 Node* n29 = graph.NewNode(op, nil, nil, nil); | |
1449 USE(n29); | |
1450 n29->ReplaceInput(0, n22); | |
1451 op = js_builder.Add(); | |
1452 Node* n45 = graph.NewNode(op, nil, nil, nil, nil, nil); | |
1453 USE(n45); | |
1454 op = js_builder.ToNumber(); | |
1455 Node* n44 = graph.NewNode(op, nil, nil, nil, nil); | |
1456 USE(n44); | |
1457 n44->ReplaceInput(0, n25); | |
1458 n44->ReplaceInput(1, n6); | |
1459 n44->ReplaceInput(2, n37); | |
1460 op = common_builder.IfFalse(); | |
1461 Node* n43 = graph.NewNode(op, nil); | |
1462 USE(n43); | |
1463 n43->ReplaceInput(0, n38); | |
1464 n44->ReplaceInput(3, n43); | |
1465 n45->ReplaceInput(0, n44); | |
1466 n45->ReplaceInput(1, n21); | |
1467 n45->ReplaceInput(2, n6); | |
1468 n45->ReplaceInput(3, n44); | |
1469 n45->ReplaceInput(4, n43); | |
1470 n29->ReplaceInput(1, n45); | |
1471 n29->ReplaceInput(2, n23); | |
1472 n30->ReplaceInput(3, n29); | |
1473 n30->ReplaceInput(4, n23); | |
1474 n42->ReplaceInput(0, n30); | |
1475 n42->ReplaceInput(1, n37); | |
1476 n42->ReplaceInput(2, n40); | |
1477 n47->ReplaceInput(3, n42); | |
1478 n47->ReplaceInput(4, n40); | |
1479 n48->ReplaceInput(0, n47); | |
1480 n48->ReplaceInput(1, n40); | |
1481 n49->ReplaceInput(0, n48); | |
1482 n53->ReplaceInput(0, n49); | |
1483 n53->ReplaceInput(1, n50); | |
1484 n8->ReplaceInput(1, n53); | |
1485 n17->ReplaceInput(1, n8); | |
1486 n18->ReplaceInput(0, n17); | |
1487 n23->ReplaceInput(0, n18); | |
1488 n23->ReplaceInput(1, n43); | |
1489 n26->ReplaceInput(2, n23); | |
1490 n11->ReplaceInput(1, n26); | |
1491 n11->ReplaceInput(2, n8); | |
1492 n16->ReplaceInput(1, n11); | |
1493 n16->ReplaceInput(2, n6); | |
1494 op = common_builder.Phi(kMachAnyTagged, 2); | |
1495 Node* n14 = graph.NewNode(op, nil, nil, nil); | |
1496 USE(n14); | |
1497 n14->ReplaceInput(0, n0); | |
1498 op = common_builder.Phi(kMachAnyTagged, 2); | |
1499 Node* n55 = graph.NewNode(op, nil, nil, nil); | |
1500 USE(n55); | |
1501 n55->ReplaceInput(0, n47); | |
1502 n55->ReplaceInput(1, n52); | |
1503 n55->ReplaceInput(2, n53); | |
1504 n14->ReplaceInput(1, n55); | |
1505 n14->ReplaceInput(2, n8); | |
1506 n16->ReplaceInput(3, n14); | |
1507 n16->ReplaceInput(4, n8); | |
1508 n20->ReplaceInput(2, n16); | |
1509 n20->ReplaceInput(3, n18); | |
1510 n22->ReplaceInput(0, n20); | |
1511 n22->ReplaceInput(1, n21); | |
1512 n22->ReplaceInput(2, n6); | |
1513 n22->ReplaceInput(3, n20); | |
1514 n22->ReplaceInput(4, n18); | |
1515 n25->ReplaceInput(0, n22); | |
1516 n25->ReplaceInput(1, n45); | |
1517 n25->ReplaceInput(2, n23); | |
1518 n10->ReplaceInput(1, n25); | |
1519 n10->ReplaceInput(2, n8); | |
1520 n56->ReplaceInput(0, n10); | |
1521 n56->ReplaceInput(1, n13); | |
1522 n56->ReplaceInput(2, n6); | |
1523 n56->ReplaceInput(3, n16); | |
1524 op = common_builder.IfFalse(); | |
1525 Node* n19 = graph.NewNode(op, nil); | |
1526 USE(n19); | |
1527 n19->ReplaceInput(0, n17); | |
1528 n56->ReplaceInput(4, n19); | |
1529 n57->ReplaceInput(0, n56); | |
1530 n57->ReplaceInput(1, n56); | |
1531 n57->ReplaceInput(2, n19); | |
1532 n58->ReplaceInput(0, n57); | |
1533 | |
1534 graph.SetStart(n0); | |
1535 graph.SetEnd(n58); | |
1536 | |
1537 ComputeAndVerifySchedule(62, &graph); | |
1538 } | |
1539 | |
1540 | |
1541 TEST(BuildScheduleSimpleLoopWithCodeMotion) { | |
1542 HandleAndZoneScope scope; | |
1543 Isolate* isolate = scope.main_isolate(); | |
1544 Graph graph(scope.main_zone()); | |
1545 CommonOperatorBuilder common_builder(scope.main_zone()); | |
1546 JSOperatorBuilder js_builder(scope.main_zone()); | |
1547 const Operator* op; | |
1548 | |
1549 Handle<HeapObject> object = | |
1550 Handle<HeapObject>(isolate->heap()->undefined_value(), isolate); | |
1551 Unique<HeapObject> unique_constant = | |
1552 Unique<HeapObject>::CreateUninitialized(object); | |
1553 | |
1554 // Manually transcripted code for: | |
1555 // function turbo_fan_test(a, b, c) { | |
1556 // while (a < b) { | |
1557 // a += b + c; | |
1558 // } | |
1559 // return a; | |
1560 // } | |
1561 op = common_builder.Start(0); | |
1562 Node* n0 = graph.NewNode(op); | |
1563 USE(n0); | |
1564 Node* nil = graph.NewNode(common_builder.Dead()); | |
1565 op = common_builder.End(); | |
1566 Node* n22 = graph.NewNode(op, nil); | |
1567 USE(n22); | |
1568 op = common_builder.Return(); | |
1569 Node* n21 = graph.NewNode(op, nil, nil, nil); | |
1570 USE(n21); | |
1571 op = common_builder.Phi(kMachAnyTagged, 2); | |
1572 Node* n9 = graph.NewNode(op, nil, nil, nil); | |
1573 USE(n9); | |
1574 op = common_builder.Parameter(0); | |
1575 Node* n2 = graph.NewNode(op, n0); | |
1576 USE(n2); | |
1577 n9->ReplaceInput(0, n2); | |
1578 op = js_builder.Add(); | |
1579 Node* n20 = graph.NewNode(op, nil, nil, nil, nil, nil); | |
1580 USE(n20); | |
1581 n20->ReplaceInput(0, n9); | |
1582 op = &kIntAdd; | |
1583 Node* n19 = graph.NewNode(op, nil, nil); | |
1584 USE(n19); | |
1585 op = common_builder.Phi(kMachAnyTagged, 2); | |
1586 Node* n10 = graph.NewNode(op, nil, nil, nil); | |
1587 USE(n10); | |
1588 op = common_builder.Parameter(0); | |
1589 Node* n3 = graph.NewNode(op, n0); | |
1590 USE(n3); | |
1591 n10->ReplaceInput(0, n3); | |
1592 n10->ReplaceInput(1, n10); | |
1593 op = common_builder.Loop(2); | |
1594 Node* n7 = graph.NewNode(op, nil, nil); | |
1595 USE(n7); | |
1596 n7->ReplaceInput(0, n0); | |
1597 op = common_builder.IfTrue(); | |
1598 Node* n17 = graph.NewNode(op, nil); | |
1599 USE(n17); | |
1600 op = common_builder.Branch(); | |
1601 Node* n16 = graph.NewNode(op, nil, nil); | |
1602 USE(n16); | |
1603 op = js_builder.ToBoolean(); | |
1604 Node* n15 = graph.NewNode(op, nil, nil, nil, nil); | |
1605 USE(n15); | |
1606 op = js_builder.LessThan(); | |
1607 Node* n14 = graph.NewNode(op, nil, nil, nil, nil, nil); | |
1608 USE(n14); | |
1609 n14->ReplaceInput(0, n9); | |
1610 n14->ReplaceInput(1, n10); | |
1611 op = common_builder.HeapConstant(unique_constant); | |
1612 Node* n6 = graph.NewNode(op); | |
1613 USE(n6); | |
1614 n14->ReplaceInput(2, n6); | |
1615 op = common_builder.Phi(kMachAnyTagged, 2); | |
1616 Node* n12 = graph.NewNode(op, nil, nil, nil); | |
1617 USE(n12); | |
1618 n12->ReplaceInput(0, n0); | |
1619 n12->ReplaceInput(1, n20); | |
1620 n12->ReplaceInput(2, n7); | |
1621 n14->ReplaceInput(3, n12); | |
1622 n14->ReplaceInput(4, n7); | |
1623 n15->ReplaceInput(0, n14); | |
1624 n15->ReplaceInput(1, n6); | |
1625 n15->ReplaceInput(2, n14); | |
1626 n15->ReplaceInput(3, n7); | |
1627 n16->ReplaceInput(0, n15); | |
1628 n16->ReplaceInput(1, n7); | |
1629 n17->ReplaceInput(0, n16); | |
1630 n7->ReplaceInput(1, n17); | |
1631 n10->ReplaceInput(2, n7); | |
1632 n19->ReplaceInput(0, n2); | |
1633 op = common_builder.Phi(kMachAnyTagged, 2); | |
1634 Node* n11 = graph.NewNode(op, nil, nil, nil); | |
1635 USE(n11); | |
1636 op = common_builder.Parameter(0); | |
1637 Node* n4 = graph.NewNode(op, n0); | |
1638 USE(n4); | |
1639 n11->ReplaceInput(0, n4); | |
1640 n11->ReplaceInput(1, n11); | |
1641 n11->ReplaceInput(2, n7); | |
1642 n19->ReplaceInput(1, n3); | |
1643 n20->ReplaceInput(1, n19); | |
1644 n20->ReplaceInput(2, n6); | |
1645 n20->ReplaceInput(3, n19); | |
1646 n20->ReplaceInput(4, n17); | |
1647 n9->ReplaceInput(1, n20); | |
1648 n9->ReplaceInput(2, n7); | |
1649 n21->ReplaceInput(0, n9); | |
1650 n21->ReplaceInput(1, n15); | |
1651 op = common_builder.IfFalse(); | |
1652 Node* n18 = graph.NewNode(op, nil); | |
1653 USE(n18); | |
1654 n18->ReplaceInput(0, n16); | |
1655 n21->ReplaceInput(2, n18); | |
1656 n22->ReplaceInput(0, n21); | |
1657 | |
1658 graph.SetStart(n0); | |
1659 graph.SetEnd(n22); | |
1660 | |
1661 Schedule* schedule = ComputeAndVerifySchedule(19, &graph); | |
1662 // Make sure the integer-only add gets hoisted to a different block that the | |
1663 // JSAdd. | |
1664 CHECK(schedule->block(n19) != schedule->block(n20)); | |
1665 } | |
1666 | |
1667 | |
1668 #if V8_TURBOFAN_TARGET | |
1669 | |
1670 static Node* CreateDiamond(Graph* graph, CommonOperatorBuilder* common, | |
1671 Node* cond) { | |
1672 Node* tv = graph->NewNode(common->Int32Constant(6)); | |
1673 Node* fv = graph->NewNode(common->Int32Constant(7)); | |
1674 Node* br = graph->NewNode(common->Branch(), cond, graph->start()); | |
1675 Node* t = graph->NewNode(common->IfTrue(), br); | |
1676 Node* f = graph->NewNode(common->IfFalse(), br); | |
1677 Node* m = graph->NewNode(common->Merge(2), t, f); | |
1678 Node* phi = graph->NewNode(common->Phi(kMachAnyTagged, 2), tv, fv, m); | |
1679 return phi; | |
1680 } | |
1681 | |
1682 | |
1683 TEST(FloatingDiamond1) { | |
1684 HandleAndZoneScope scope; | |
1685 Graph graph(scope.main_zone()); | |
1686 CommonOperatorBuilder common(scope.main_zone()); | |
1687 | |
1688 Node* start = graph.NewNode(common.Start(1)); | |
1689 graph.SetStart(start); | |
1690 | |
1691 Node* p0 = graph.NewNode(common.Parameter(0), start); | |
1692 Node* d1 = CreateDiamond(&graph, &common, p0); | |
1693 Node* ret = graph.NewNode(common.Return(), d1, start, start); | |
1694 Node* end = graph.NewNode(common.End(), ret, start); | |
1695 | |
1696 graph.SetEnd(end); | |
1697 | |
1698 ComputeAndVerifySchedule(13, &graph); | |
1699 } | |
1700 | |
1701 | |
1702 TEST(FloatingDiamond2) { | |
1703 HandleAndZoneScope scope; | |
1704 Graph graph(scope.main_zone()); | |
1705 CommonOperatorBuilder common(scope.main_zone()); | |
1706 | |
1707 Node* start = graph.NewNode(common.Start(2)); | |
1708 graph.SetStart(start); | |
1709 | |
1710 Node* p0 = graph.NewNode(common.Parameter(0), start); | |
1711 Node* p1 = graph.NewNode(common.Parameter(1), start); | |
1712 Node* d1 = CreateDiamond(&graph, &common, p0); | |
1713 Node* d2 = CreateDiamond(&graph, &common, p1); | |
1714 Node* add = graph.NewNode(&kIntAdd, d1, d2); | |
1715 Node* ret = graph.NewNode(common.Return(), add, start, start); | |
1716 Node* end = graph.NewNode(common.End(), ret, start); | |
1717 | |
1718 graph.SetEnd(end); | |
1719 | |
1720 ComputeAndVerifySchedule(24, &graph); | |
1721 } | |
1722 | |
1723 | |
1724 TEST(FloatingDiamond3) { | |
1725 HandleAndZoneScope scope; | |
1726 Graph graph(scope.main_zone()); | |
1727 CommonOperatorBuilder common(scope.main_zone()); | |
1728 | |
1729 Node* start = graph.NewNode(common.Start(2)); | |
1730 graph.SetStart(start); | |
1731 | |
1732 Node* p0 = graph.NewNode(common.Parameter(0), start); | |
1733 Node* p1 = graph.NewNode(common.Parameter(1), start); | |
1734 Node* d1 = CreateDiamond(&graph, &common, p0); | |
1735 Node* d2 = CreateDiamond(&graph, &common, p1); | |
1736 Node* add = graph.NewNode(&kIntAdd, d1, d2); | |
1737 Node* d3 = CreateDiamond(&graph, &common, add); | |
1738 Node* ret = graph.NewNode(common.Return(), d3, start, start); | |
1739 Node* end = graph.NewNode(common.End(), ret, start); | |
1740 | |
1741 graph.SetEnd(end); | |
1742 | |
1743 ComputeAndVerifySchedule(33, &graph); | |
1744 } | |
1745 | |
1746 | |
1747 TEST(NestedFloatingDiamonds) { | |
1748 HandleAndZoneScope scope; | |
1749 Graph graph(scope.main_zone()); | |
1750 CommonOperatorBuilder common(scope.main_zone()); | |
1751 SimplifiedOperatorBuilder simplified(scope.main_zone()); | |
1752 | |
1753 Node* start = graph.NewNode(common.Start(2)); | |
1754 graph.SetStart(start); | |
1755 | |
1756 Node* p0 = graph.NewNode(common.Parameter(0), start); | |
1757 | |
1758 Node* fv = graph.NewNode(common.Int32Constant(7)); | |
1759 Node* br = graph.NewNode(common.Branch(), p0, graph.start()); | |
1760 Node* t = graph.NewNode(common.IfTrue(), br); | |
1761 Node* f = graph.NewNode(common.IfFalse(), br); | |
1762 | |
1763 Node* map = graph.NewNode( | |
1764 simplified.LoadElement(AccessBuilder::ForFixedArrayElement()), p0, p0, p0, | |
1765 start, f); | |
1766 Node* br1 = graph.NewNode(common.Branch(), map, graph.start()); | |
1767 Node* t1 = graph.NewNode(common.IfTrue(), br1); | |
1768 Node* f1 = graph.NewNode(common.IfFalse(), br1); | |
1769 Node* m1 = graph.NewNode(common.Merge(2), t1, f1); | |
1770 Node* ttrue = graph.NewNode(common.Int32Constant(1)); | |
1771 Node* ffalse = graph.NewNode(common.Int32Constant(0)); | |
1772 Node* phi1 = graph.NewNode(common.Phi(kMachAnyTagged, 2), ttrue, ffalse, m1); | |
1773 | |
1774 | |
1775 Node* m = graph.NewNode(common.Merge(2), t, f); | |
1776 Node* phi = graph.NewNode(common.Phi(kMachAnyTagged, 2), fv, phi1, m); | |
1777 Node* ephi1 = graph.NewNode(common.EffectPhi(2), start, map, m); | |
1778 | |
1779 Node* ret = graph.NewNode(common.Return(), phi, ephi1, start); | |
1780 Node* end = graph.NewNode(common.End(), ret, start); | |
1781 | |
1782 graph.SetEnd(end); | |
1783 | |
1784 ComputeAndVerifySchedule(23, &graph); | |
1785 } | |
1786 | |
1787 | |
1788 TEST(NestedFloatingDiamondWithChain) { | |
1789 HandleAndZoneScope scope; | |
1790 Graph graph(scope.main_zone()); | |
1791 CommonOperatorBuilder common(scope.main_zone()); | |
1792 | |
1793 Node* start = graph.NewNode(common.Start(2)); | |
1794 graph.SetStart(start); | |
1795 | |
1796 Node* p0 = graph.NewNode(common.Parameter(0), start); | |
1797 Node* p1 = graph.NewNode(common.Parameter(1), start); | |
1798 Node* c = graph.NewNode(common.Int32Constant(7)); | |
1799 | |
1800 Node* brA1 = graph.NewNode(common.Branch(), p0, graph.start()); | |
1801 Node* tA1 = graph.NewNode(common.IfTrue(), brA1); | |
1802 Node* fA1 = graph.NewNode(common.IfFalse(), brA1); | |
1803 Node* mA1 = graph.NewNode(common.Merge(2), tA1, fA1); | |
1804 Node* phiA1 = graph.NewNode(common.Phi(kMachAnyTagged, 2), p0, p1, mA1); | |
1805 | |
1806 Node* brB1 = graph.NewNode(common.Branch(), p1, graph.start()); | |
1807 Node* tB1 = graph.NewNode(common.IfTrue(), brB1); | |
1808 Node* fB1 = graph.NewNode(common.IfFalse(), brB1); | |
1809 Node* mB1 = graph.NewNode(common.Merge(2), tB1, fB1); | |
1810 Node* phiB1 = graph.NewNode(common.Phi(kMachAnyTagged, 2), p0, p1, mB1); | |
1811 | |
1812 Node* brA2 = graph.NewNode(common.Branch(), phiB1, mA1); | |
1813 Node* tA2 = graph.NewNode(common.IfTrue(), brA2); | |
1814 Node* fA2 = graph.NewNode(common.IfFalse(), brA2); | |
1815 Node* mA2 = graph.NewNode(common.Merge(2), tA2, fA2); | |
1816 Node* phiA2 = graph.NewNode(common.Phi(kMachAnyTagged, 2), phiB1, c, mA2); | |
1817 | |
1818 Node* brB2 = graph.NewNode(common.Branch(), phiA1, mB1); | |
1819 Node* tB2 = graph.NewNode(common.IfTrue(), brB2); | |
1820 Node* fB2 = graph.NewNode(common.IfFalse(), brB2); | |
1821 Node* mB2 = graph.NewNode(common.Merge(2), tB2, fB2); | |
1822 Node* phiB2 = graph.NewNode(common.Phi(kMachAnyTagged, 2), phiA1, c, mB2); | |
1823 | |
1824 Node* add = graph.NewNode(&kIntAdd, phiA2, phiB2); | |
1825 Node* ret = graph.NewNode(common.Return(), add, start, start); | |
1826 Node* end = graph.NewNode(common.End(), ret, start); | |
1827 | |
1828 graph.SetEnd(end); | |
1829 | |
1830 ComputeAndVerifySchedule(35, &graph); | |
1831 } | |
1832 | |
1833 | |
1834 TEST(NestedFloatingDiamondWithLoop) { | |
1835 HandleAndZoneScope scope; | |
1836 Graph graph(scope.main_zone()); | |
1837 CommonOperatorBuilder common(scope.main_zone()); | |
1838 | |
1839 Node* start = graph.NewNode(common.Start(2)); | |
1840 graph.SetStart(start); | |
1841 | |
1842 Node* p0 = graph.NewNode(common.Parameter(0), start); | |
1843 | |
1844 Node* fv = graph.NewNode(common.Int32Constant(7)); | |
1845 Node* br = graph.NewNode(common.Branch(), p0, graph.start()); | |
1846 Node* t = graph.NewNode(common.IfTrue(), br); | |
1847 Node* f = graph.NewNode(common.IfFalse(), br); | |
1848 | |
1849 Node* loop = graph.NewNode(common.Loop(2), f, start); | |
1850 Node* ind = graph.NewNode(common.Phi(kMachAnyTagged, 2), p0, p0, loop); | |
1851 | |
1852 Node* add = graph.NewNode(&kIntAdd, ind, fv); | |
1853 Node* br1 = graph.NewNode(common.Branch(), add, loop); | |
1854 Node* t1 = graph.NewNode(common.IfTrue(), br1); | |
1855 Node* f1 = graph.NewNode(common.IfFalse(), br1); | |
1856 | |
1857 loop->ReplaceInput(1, t1); // close loop. | |
1858 ind->ReplaceInput(1, ind); // close induction variable. | |
1859 | |
1860 Node* m = graph.NewNode(common.Merge(2), t, f1); | |
1861 Node* phi = graph.NewNode(common.Phi(kMachAnyTagged, 2), fv, ind, m); | |
1862 | |
1863 Node* ret = graph.NewNode(common.Return(), phi, start, start); | |
1864 Node* end = graph.NewNode(common.End(), ret, start); | |
1865 | |
1866 graph.SetEnd(end); | |
1867 | |
1868 ComputeAndVerifySchedule(20, &graph); | |
1869 } | |
1870 | |
1871 | |
1872 TEST(LoopedFloatingDiamond1) { | |
1873 HandleAndZoneScope scope; | |
1874 Graph graph(scope.main_zone()); | |
1875 CommonOperatorBuilder common(scope.main_zone()); | |
1876 | |
1877 Node* start = graph.NewNode(common.Start(2)); | |
1878 graph.SetStart(start); | |
1879 | |
1880 Node* p0 = graph.NewNode(common.Parameter(0), start); | |
1881 | |
1882 Node* c = graph.NewNode(common.Int32Constant(7)); | |
1883 Node* loop = graph.NewNode(common.Loop(2), start, start); | |
1884 Node* ind = graph.NewNode(common.Phi(kMachAnyTagged, 2), p0, p0, loop); | |
1885 Node* add = graph.NewNode(&kIntAdd, ind, c); | |
1886 | |
1887 Node* br = graph.NewNode(common.Branch(), add, loop); | |
1888 Node* t = graph.NewNode(common.IfTrue(), br); | |
1889 Node* f = graph.NewNode(common.IfFalse(), br); | |
1890 | |
1891 Node* br1 = graph.NewNode(common.Branch(), p0, graph.start()); | |
1892 Node* t1 = graph.NewNode(common.IfTrue(), br1); | |
1893 Node* f1 = graph.NewNode(common.IfFalse(), br1); | |
1894 Node* m1 = graph.NewNode(common.Merge(2), t1, f1); | |
1895 Node* phi1 = graph.NewNode(common.Phi(kMachAnyTagged, 2), add, p0, m1); | |
1896 | |
1897 loop->ReplaceInput(1, t); // close loop. | |
1898 ind->ReplaceInput(1, phi1); // close induction variable. | |
1899 | |
1900 Node* ret = graph.NewNode(common.Return(), ind, start, f); | |
1901 Node* end = graph.NewNode(common.End(), ret, f); | |
1902 | |
1903 graph.SetEnd(end); | |
1904 | |
1905 ComputeAndVerifySchedule(20, &graph); | |
1906 } | |
1907 | |
1908 | |
1909 TEST(LoopedFloatingDiamond2) { | |
1910 HandleAndZoneScope scope; | |
1911 Graph graph(scope.main_zone()); | |
1912 CommonOperatorBuilder common(scope.main_zone()); | |
1913 | |
1914 Node* start = graph.NewNode(common.Start(2)); | |
1915 graph.SetStart(start); | |
1916 | |
1917 Node* p0 = graph.NewNode(common.Parameter(0), start); | |
1918 | |
1919 Node* c = graph.NewNode(common.Int32Constant(7)); | |
1920 Node* loop = graph.NewNode(common.Loop(2), start, start); | |
1921 Node* ind = graph.NewNode(common.Phi(kMachAnyTagged, 2), p0, p0, loop); | |
1922 | |
1923 Node* br1 = graph.NewNode(common.Branch(), p0, graph.start()); | |
1924 Node* t1 = graph.NewNode(common.IfTrue(), br1); | |
1925 Node* f1 = graph.NewNode(common.IfFalse(), br1); | |
1926 Node* m1 = graph.NewNode(common.Merge(2), t1, f1); | |
1927 Node* phi1 = graph.NewNode(common.Phi(kMachAnyTagged, 2), c, ind, m1); | |
1928 | |
1929 Node* add = graph.NewNode(&kIntAdd, ind, phi1); | |
1930 | |
1931 Node* br = graph.NewNode(common.Branch(), add, loop); | |
1932 Node* t = graph.NewNode(common.IfTrue(), br); | |
1933 Node* f = graph.NewNode(common.IfFalse(), br); | |
1934 | |
1935 loop->ReplaceInput(1, t); // close loop. | |
1936 ind->ReplaceInput(1, add); // close induction variable. | |
1937 | |
1938 Node* ret = graph.NewNode(common.Return(), ind, start, f); | |
1939 Node* end = graph.NewNode(common.End(), ret, f); | |
1940 | |
1941 graph.SetEnd(end); | |
1942 | |
1943 ComputeAndVerifySchedule(20, &graph); | |
1944 } | |
1945 | |
1946 | |
1947 TEST(LoopedFloatingDiamond3) { | |
1948 HandleAndZoneScope scope; | |
1949 Graph graph(scope.main_zone()); | |
1950 CommonOperatorBuilder common(scope.main_zone()); | |
1951 | |
1952 Node* start = graph.NewNode(common.Start(2)); | |
1953 graph.SetStart(start); | |
1954 | |
1955 Node* p0 = graph.NewNode(common.Parameter(0), start); | |
1956 | |
1957 Node* c = graph.NewNode(common.Int32Constant(7)); | |
1958 Node* loop = graph.NewNode(common.Loop(2), start, start); | |
1959 Node* ind = graph.NewNode(common.Phi(kMachAnyTagged, 2), p0, p0, loop); | |
1960 | |
1961 Node* br1 = graph.NewNode(common.Branch(), p0, graph.start()); | |
1962 Node* t1 = graph.NewNode(common.IfTrue(), br1); | |
1963 Node* f1 = graph.NewNode(common.IfFalse(), br1); | |
1964 | |
1965 Node* loop1 = graph.NewNode(common.Loop(2), t1, start); | |
1966 Node* ind1 = graph.NewNode(common.Phi(kMachAnyTagged, 2), p0, p0, loop); | |
1967 | |
1968 Node* add1 = graph.NewNode(&kIntAdd, ind1, c); | |
1969 Node* br2 = graph.NewNode(common.Branch(), add1, loop1); | |
1970 Node* t2 = graph.NewNode(common.IfTrue(), br2); | |
1971 Node* f2 = graph.NewNode(common.IfFalse(), br2); | |
1972 | |
1973 loop1->ReplaceInput(1, t2); // close inner loop. | |
1974 ind1->ReplaceInput(1, ind1); // close inner induction variable. | |
1975 | |
1976 Node* m1 = graph.NewNode(common.Merge(2), f1, f2); | |
1977 Node* phi1 = graph.NewNode(common.Phi(kMachAnyTagged, 2), c, ind1, m1); | |
1978 | |
1979 Node* add = graph.NewNode(&kIntAdd, ind, phi1); | |
1980 | |
1981 Node* br = graph.NewNode(common.Branch(), add, loop); | |
1982 Node* t = graph.NewNode(common.IfTrue(), br); | |
1983 Node* f = graph.NewNode(common.IfFalse(), br); | |
1984 | |
1985 loop->ReplaceInput(1, t); // close loop. | |
1986 ind->ReplaceInput(1, add); // close induction variable. | |
1987 | |
1988 Node* ret = graph.NewNode(common.Return(), ind, start, f); | |
1989 Node* end = graph.NewNode(common.End(), ret, f); | |
1990 | |
1991 graph.SetEnd(end); | |
1992 | |
1993 ComputeAndVerifySchedule(28, &graph); | |
1994 } | |
1995 | |
1996 | |
1997 TEST(PhisPushedDownToDifferentBranches) { | |
1998 HandleAndZoneScope scope; | |
1999 Graph graph(scope.main_zone()); | |
2000 CommonOperatorBuilder common(scope.main_zone()); | |
2001 | |
2002 Node* start = graph.NewNode(common.Start(2)); | |
2003 graph.SetStart(start); | |
2004 | |
2005 Node* p0 = graph.NewNode(common.Parameter(0), start); | |
2006 Node* p1 = graph.NewNode(common.Parameter(1), start); | |
2007 | |
2008 Node* v1 = graph.NewNode(common.Int32Constant(1)); | |
2009 Node* v2 = graph.NewNode(common.Int32Constant(2)); | |
2010 Node* v3 = graph.NewNode(common.Int32Constant(3)); | |
2011 Node* v4 = graph.NewNode(common.Int32Constant(4)); | |
2012 Node* br = graph.NewNode(common.Branch(), p0, graph.start()); | |
2013 Node* t = graph.NewNode(common.IfTrue(), br); | |
2014 Node* f = graph.NewNode(common.IfFalse(), br); | |
2015 Node* m = graph.NewNode(common.Merge(2), t, f); | |
2016 Node* phi = graph.NewNode(common.Phi(kMachAnyTagged, 2), v1, v2, m); | |
2017 Node* phi2 = graph.NewNode(common.Phi(kMachAnyTagged, 2), v3, v4, m); | |
2018 | |
2019 Node* br2 = graph.NewNode(common.Branch(), p1, graph.start()); | |
2020 Node* t2 = graph.NewNode(common.IfTrue(), br2); | |
2021 Node* f2 = graph.NewNode(common.IfFalse(), br2); | |
2022 Node* m2 = graph.NewNode(common.Merge(2), t2, f2); | |
2023 Node* phi3 = graph.NewNode(common.Phi(kMachAnyTagged, 2), phi, phi2, m2); | |
2024 | |
2025 Node* ret = graph.NewNode(common.Return(), phi3, start, start); | |
2026 Node* end = graph.NewNode(common.End(), ret, start); | |
2027 | |
2028 graph.SetEnd(end); | |
2029 | |
2030 ComputeAndVerifySchedule(24, &graph); | |
2031 } | |
2032 | |
2033 | |
2034 TEST(BranchHintTrue) { | |
2035 HandleAndZoneScope scope; | |
2036 Graph graph(scope.main_zone()); | |
2037 CommonOperatorBuilder common(scope.main_zone()); | |
2038 | |
2039 Node* start = graph.NewNode(common.Start(1)); | |
2040 graph.SetStart(start); | |
2041 | |
2042 Node* p0 = graph.NewNode(common.Parameter(0), start); | |
2043 Node* tv = graph.NewNode(common.Int32Constant(6)); | |
2044 Node* fv = graph.NewNode(common.Int32Constant(7)); | |
2045 Node* br = graph.NewNode(common.Branch(BranchHint::kTrue), p0, start); | |
2046 Node* t = graph.NewNode(common.IfTrue(), br); | |
2047 Node* f = graph.NewNode(common.IfFalse(), br); | |
2048 Node* m = graph.NewNode(common.Merge(2), t, f); | |
2049 Node* phi = graph.NewNode(common.Phi(kMachAnyTagged, 2), tv, fv, m); | |
2050 Node* ret = graph.NewNode(common.Return(), phi, start, start); | |
2051 Node* end = graph.NewNode(common.End(), ret, start); | |
2052 | |
2053 graph.SetEnd(end); | |
2054 | |
2055 Schedule* schedule = ComputeAndVerifySchedule(13, &graph); | |
2056 // Make sure the false block is marked as deferred. | |
2057 CHECK(!schedule->block(t)->deferred()); | |
2058 CHECK(schedule->block(f)->deferred()); | |
2059 } | |
2060 | |
2061 | |
2062 TEST(BranchHintFalse) { | |
2063 HandleAndZoneScope scope; | |
2064 Graph graph(scope.main_zone()); | |
2065 CommonOperatorBuilder common(scope.main_zone()); | |
2066 | |
2067 Node* start = graph.NewNode(common.Start(1)); | |
2068 graph.SetStart(start); | |
2069 | |
2070 Node* p0 = graph.NewNode(common.Parameter(0), start); | |
2071 Node* tv = graph.NewNode(common.Int32Constant(6)); | |
2072 Node* fv = graph.NewNode(common.Int32Constant(7)); | |
2073 Node* br = graph.NewNode(common.Branch(BranchHint::kFalse), p0, start); | |
2074 Node* t = graph.NewNode(common.IfTrue(), br); | |
2075 Node* f = graph.NewNode(common.IfFalse(), br); | |
2076 Node* m = graph.NewNode(common.Merge(2), t, f); | |
2077 Node* phi = graph.NewNode(common.Phi(kMachAnyTagged, 2), tv, fv, m); | |
2078 Node* ret = graph.NewNode(common.Return(), phi, start, start); | |
2079 Node* end = graph.NewNode(common.End(), ret, start); | |
2080 | |
2081 graph.SetEnd(end); | |
2082 | |
2083 Schedule* schedule = ComputeAndVerifySchedule(13, &graph); | |
2084 // Make sure the true block is marked as deferred. | |
2085 CHECK(schedule->block(t)->deferred()); | |
2086 CHECK(!schedule->block(f)->deferred()); | |
2087 } | |
2088 | |
2089 | |
2090 TEST(ScheduleTerminate) { | |
2091 HandleAndZoneScope scope; | |
2092 Graph graph(scope.main_zone()); | |
2093 CommonOperatorBuilder common(scope.main_zone()); | |
2094 | |
2095 Node* start = graph.NewNode(common.Start(1)); | |
2096 graph.SetStart(start); | |
2097 | |
2098 Node* loop = graph.NewNode(common.Loop(2), start, start); | |
2099 loop->ReplaceInput(1, loop); // self loop, NTL. | |
2100 | |
2101 Node* effect = graph.NewNode(common.EffectPhi(1), start, loop); | |
2102 effect->ReplaceInput(0, effect); | |
2103 | |
2104 Node* terminate = graph.NewNode(common.Terminate(1), effect, loop); | |
2105 Node* end = graph.NewNode(common.End(), terminate); | |
2106 | |
2107 graph.SetEnd(end); | |
2108 | |
2109 Schedule* schedule = ComputeAndVerifySchedule(6, &graph); | |
2110 BasicBlock* block = schedule->block(loop); | |
2111 CHECK_NE(NULL, loop); | |
2112 CHECK_EQ(block, schedule->block(effect)); | |
2113 CHECK_GE(block->rpo_number(), 0); | |
2114 } | |
2115 | |
2116 #endif | |
OLD | NEW |