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