OLD | NEW |
---|---|
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/compiler/scheduler.h" | 5 #include "src/compiler/scheduler.h" |
6 | 6 |
7 #include "src/bit-vector.h" | 7 #include "src/bit-vector.h" |
8 #include "src/compiler/common-operator.h" | 8 #include "src/compiler/common-operator.h" |
9 #include "src/compiler/control-equivalence.h" | 9 #include "src/compiler/control-equivalence.h" |
10 #include "src/compiler/graph.h" | 10 #include "src/compiler/graph.h" |
(...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
279 } | 279 } |
280 } | 280 } |
281 DCHECK(component_entry_); | 281 DCHECK(component_entry_); |
282 | 282 |
283 for (NodeVector::iterator i = control_.begin(); i != control_.end(); ++i) { | 283 for (NodeVector::iterator i = control_.begin(); i != control_.end(); ++i) { |
284 ConnectBlocks(*i); // Connect block to its predecessor/successors. | 284 ConnectBlocks(*i); // Connect block to its predecessor/successors. |
285 } | 285 } |
286 } | 286 } |
287 | 287 |
288 private: | 288 private: |
289 // TODO(mstarzinger): Only for Scheduler::FuseFloatingControl. | 289 friend class ScheduleLateNodeVisitor; |
290 friend class Scheduler; | 290 friend class Scheduler; |
291 | 291 |
292 void FixNode(BasicBlock* block, Node* node) { | 292 void FixNode(BasicBlock* block, Node* node) { |
293 schedule_->AddNode(block, node); | 293 schedule_->AddNode(block, node); |
294 scheduler_->UpdatePlacement(node, Scheduler::kFixed); | 294 scheduler_->UpdatePlacement(node, Scheduler::kFixed); |
295 } | 295 } |
296 | 296 |
297 void Queue(Node* node) { | 297 void Queue(Node* node) { |
298 // Mark the connected control nodes as they are queued. | 298 // Mark the connected control nodes as they are queued. |
299 if (!queued_.Get(node)) { | 299 if (!queued_.Get(node)) { |
(...skipping 13 matching lines...) Expand all Loading... | |
313 FixNode(schedule_->start(), node); | 313 FixNode(schedule_->start(), node); |
314 break; | 314 break; |
315 case IrOpcode::kLoop: | 315 case IrOpcode::kLoop: |
316 case IrOpcode::kMerge: | 316 case IrOpcode::kMerge: |
317 BuildBlockForNode(node); | 317 BuildBlockForNode(node); |
318 break; | 318 break; |
319 case IrOpcode::kBranch: | 319 case IrOpcode::kBranch: |
320 case IrOpcode::kSwitch: | 320 case IrOpcode::kSwitch: |
321 BuildBlocksForSuccessors(node); | 321 BuildBlocksForSuccessors(node); |
322 break; | 322 break; |
323 case IrOpcode::kCall: | |
324 if (!IsExceptionalCall(node)) break; | |
325 BuildBlocksForSuccessors(node); | |
326 break; | |
323 default: | 327 default: |
324 break; | 328 break; |
325 } | 329 } |
326 } | 330 } |
327 | 331 |
328 void ConnectBlocks(Node* node) { | 332 void ConnectBlocks(Node* node) { |
329 switch (node->opcode()) { | 333 switch (node->opcode()) { |
330 case IrOpcode::kLoop: | 334 case IrOpcode::kLoop: |
331 case IrOpcode::kMerge: | 335 case IrOpcode::kMerge: |
332 ConnectMerge(node); | 336 ConnectMerge(node); |
333 break; | 337 break; |
334 case IrOpcode::kBranch: | 338 case IrOpcode::kBranch: |
335 scheduler_->UpdatePlacement(node, Scheduler::kFixed); | 339 scheduler_->UpdatePlacement(node, Scheduler::kFixed); |
336 ConnectBranch(node); | 340 ConnectBranch(node); |
337 break; | 341 break; |
338 case IrOpcode::kSwitch: | 342 case IrOpcode::kSwitch: |
339 scheduler_->UpdatePlacement(node, Scheduler::kFixed); | 343 scheduler_->UpdatePlacement(node, Scheduler::kFixed); |
340 ConnectSwitch(node); | 344 ConnectSwitch(node); |
341 break; | 345 break; |
342 case IrOpcode::kReturn: | 346 case IrOpcode::kReturn: |
343 scheduler_->UpdatePlacement(node, Scheduler::kFixed); | 347 scheduler_->UpdatePlacement(node, Scheduler::kFixed); |
344 ConnectReturn(node); | 348 ConnectReturn(node); |
345 break; | 349 break; |
346 case IrOpcode::kThrow: | 350 case IrOpcode::kThrow: |
347 scheduler_->UpdatePlacement(node, Scheduler::kFixed); | 351 scheduler_->UpdatePlacement(node, Scheduler::kFixed); |
348 ConnectThrow(node); | 352 ConnectThrow(node); |
349 break; | 353 break; |
354 case IrOpcode::kCall: | |
355 if (!IsExceptionalCall(node)) break; | |
356 scheduler_->UpdatePlacement(node, Scheduler::kFixed); | |
357 ConnectCall(node); | |
358 break; | |
350 default: | 359 default: |
351 break; | 360 break; |
352 } | 361 } |
353 } | 362 } |
354 | 363 |
355 BasicBlock* BuildBlockForNode(Node* node) { | 364 BasicBlock* BuildBlockForNode(Node* node) { |
356 BasicBlock* block = schedule_->block(node); | 365 BasicBlock* block = schedule_->block(node); |
357 if (block == NULL) { | 366 if (block == NULL) { |
358 block = schedule_->NewBasicBlock(); | 367 block = schedule_->NewBasicBlock(); |
359 Trace("Create block B%d for #%d:%s\n", block->id().ToInt(), node->id(), | 368 Trace("Create block B%d for #%d:%s\n", block->id().ToInt(), node->id(), |
360 node->op()->mnemonic()); | 369 node->op()->mnemonic()); |
361 FixNode(block, node); | 370 FixNode(block, node); |
362 } | 371 } |
363 return block; | 372 return block; |
364 } | 373 } |
365 | 374 |
366 void BuildBlocksForSuccessors(Node* node) { | 375 void BuildBlocksForSuccessors(Node* node) { |
367 size_t const successor_count = node->op()->ControlOutputCount(); | 376 size_t const successor_count = node->op()->ControlOutputCount(); |
368 Node** successors = zone_->NewArray<Node*>(successor_count); | 377 Node** successors = zone_->NewArray<Node*>(successor_count); |
369 CollectSuccessorProjections(node, successors, successor_count); | 378 CollectSuccessorProjections(node, successors, successor_count); |
370 for (size_t index = 0; index < successor_count; ++index) { | 379 for (size_t index = 0; index < successor_count; ++index) { |
371 BuildBlockForNode(successors[index]); | 380 BuildBlockForNode(successors[index]); |
372 } | 381 } |
373 } | 382 } |
374 | 383 |
375 // Collect the branch-related projections from a node, such as IfTrue, | 384 // Collect the branch-related projections from a node, such as IfTrue, |
376 // IfFalse, and Case. | 385 // IfFalse, IfException, IfSuccess, and Case. |
377 void CollectSuccessorProjections(Node* node, Node** successors, | 386 void CollectSuccessorProjections(Node* node, Node** successors, |
378 size_t successor_count) { | 387 size_t successor_count) { |
379 #ifdef DEBUG | 388 #ifdef DEBUG |
380 DCHECK_EQ(static_cast<int>(successor_count), node->UseCount()); | 389 DCHECK_LE(static_cast<int>(successor_count), node->UseCount()); |
381 std::memset(successors, 0, sizeof(*successors) * successor_count); | 390 std::memset(successors, 0, sizeof(*successors) * successor_count); |
382 #endif | 391 #endif |
383 for (Node* const use : node->uses()) { | 392 for (Node* const use : node->uses()) { |
384 size_t index; | 393 size_t index; |
385 switch (use->opcode()) { | 394 switch (use->opcode()) { |
386 default: | |
387 UNREACHABLE(); | |
388 // Fall through. | |
389 case IrOpcode::kIfTrue: | 395 case IrOpcode::kIfTrue: |
390 DCHECK_EQ(IrOpcode::kBranch, node->opcode()); | 396 DCHECK_EQ(IrOpcode::kBranch, node->opcode()); |
391 index = 0; | 397 index = 0; |
392 break; | 398 break; |
393 case IrOpcode::kIfFalse: | 399 case IrOpcode::kIfFalse: |
394 DCHECK_EQ(IrOpcode::kBranch, node->opcode()); | 400 DCHECK_EQ(IrOpcode::kBranch, node->opcode()); |
395 index = 1; | 401 index = 1; |
396 break; | 402 break; |
403 case IrOpcode::kIfException: | |
404 DCHECK_EQ(IrOpcode::kCall, node->opcode()); | |
405 index = 1; | |
406 break; | |
407 case IrOpcode::kIfSuccess: | |
408 DCHECK_EQ(IrOpcode::kCall, node->opcode()); | |
409 index = 0; | |
410 break; | |
397 case IrOpcode::kCase: | 411 case IrOpcode::kCase: |
398 DCHECK_EQ(IrOpcode::kSwitch, node->opcode()); | 412 DCHECK_EQ(IrOpcode::kSwitch, node->opcode()); |
399 index = CaseIndexOf(use->op()); | 413 index = CaseIndexOf(use->op()); |
400 break; | 414 break; |
415 default: | |
416 continue; | |
401 } | 417 } |
402 DCHECK_LT(index, successor_count); | 418 DCHECK_LT(index, successor_count); |
403 DCHECK(successors[index] == nullptr); | 419 DCHECK(successors[index] == nullptr); |
404 successors[index] = use; | 420 successors[index] = use; |
405 } | 421 } |
406 #ifdef DEBUG | 422 #ifdef DEBUG |
407 for (size_t index = 0; index < successor_count; ++index) { | 423 for (size_t index = 0; index < successor_count; ++index) { |
408 DCHECK_NOT_NULL(successors[index]); | 424 DCHECK_NOT_NULL(successors[index]); |
409 } | 425 } |
410 #endif | 426 #endif |
411 } | 427 } |
412 | 428 |
413 void CollectSuccessorBlocks(Node* node, BasicBlock** successor_blocks, | 429 void CollectSuccessorBlocks(Node* node, BasicBlock** successor_blocks, |
414 size_t successor_count) { | 430 size_t successor_count) { |
415 Node** successors = reinterpret_cast<Node**>(successor_blocks); | 431 Node** successors = reinterpret_cast<Node**>(successor_blocks); |
416 CollectSuccessorProjections(node, successors, successor_count); | 432 CollectSuccessorProjections(node, successors, successor_count); |
417 for (size_t index = 0; index < successor_count; ++index) { | 433 for (size_t index = 0; index < successor_count; ++index) { |
418 successor_blocks[index] = schedule_->block(successors[index]); | 434 successor_blocks[index] = schedule_->block(successors[index]); |
419 } | 435 } |
420 } | 436 } |
421 | 437 |
438 BasicBlock* FindPredecessorBlock(Node* node) { | |
439 BasicBlock* predecessor_block = nullptr; | |
440 while (predecessor_block == nullptr) { | |
Benedikt Meurer
2015/02/17 05:58:49
The condition is redundant; can be while(true) ins
Michael Starzinger
2015/02/17 10:12:06
Done.
| |
441 predecessor_block = schedule_->block(node); | |
442 if (predecessor_block != nullptr) break; | |
443 node = NodeProperties::GetControlInput(node); | |
444 } | |
445 return predecessor_block; | |
446 } | |
447 | |
448 void ConnectCall(Node* call) { | |
449 BasicBlock* successor_blocks[2]; | |
450 CollectSuccessorBlocks(call, successor_blocks, arraysize(successor_blocks)); | |
451 | |
452 // Consider the exception continuation to be deferred. | |
453 successor_blocks[1]->set_deferred(true); | |
454 | |
455 Node* call_control = NodeProperties::GetControlInput(call); | |
456 BasicBlock* call_block = FindPredecessorBlock(call_control); | |
457 TraceConnect(call, call_block, successor_blocks[0]); | |
458 TraceConnect(call, call_block, successor_blocks[1]); | |
459 schedule_->AddCall(call_block, call, successor_blocks[0], | |
460 successor_blocks[1]); | |
461 } | |
462 | |
422 void ConnectBranch(Node* branch) { | 463 void ConnectBranch(Node* branch) { |
423 BasicBlock* successor_blocks[2]; | 464 BasicBlock* successor_blocks[2]; |
424 CollectSuccessorBlocks(branch, successor_blocks, | 465 CollectSuccessorBlocks(branch, successor_blocks, |
425 arraysize(successor_blocks)); | 466 arraysize(successor_blocks)); |
426 | 467 |
427 // Consider branch hints. | 468 // Consider branch hints. |
428 switch (BranchHintOf(branch->op())) { | 469 switch (BranchHintOf(branch->op())) { |
429 case BranchHint::kNone: | 470 case BranchHint::kNone: |
430 break; | 471 break; |
431 case BranchHint::kTrue: | 472 case BranchHint::kTrue: |
432 successor_blocks[1]->set_deferred(true); | 473 successor_blocks[1]->set_deferred(true); |
433 break; | 474 break; |
434 case BranchHint::kFalse: | 475 case BranchHint::kFalse: |
435 successor_blocks[0]->set_deferred(true); | 476 successor_blocks[0]->set_deferred(true); |
436 break; | 477 break; |
437 } | 478 } |
438 | 479 |
439 if (branch == component_entry_) { | 480 if (branch == component_entry_) { |
440 TraceConnect(branch, component_start_, successor_blocks[0]); | 481 TraceConnect(branch, component_start_, successor_blocks[0]); |
441 TraceConnect(branch, component_start_, successor_blocks[1]); | 482 TraceConnect(branch, component_start_, successor_blocks[1]); |
442 schedule_->InsertBranch(component_start_, component_end_, branch, | 483 schedule_->InsertBranch(component_start_, component_end_, branch, |
443 successor_blocks[0], successor_blocks[1]); | 484 successor_blocks[0], successor_blocks[1]); |
444 } else { | 485 } else { |
445 Node* branch_block_node = NodeProperties::GetControlInput(branch); | 486 Node* branch_control = NodeProperties::GetControlInput(branch); |
446 BasicBlock* branch_block = schedule_->block(branch_block_node); | 487 BasicBlock* branch_block = FindPredecessorBlock(branch_control); |
447 DCHECK_NOT_NULL(branch_block); | |
448 | |
449 TraceConnect(branch, branch_block, successor_blocks[0]); | 488 TraceConnect(branch, branch_block, successor_blocks[0]); |
450 TraceConnect(branch, branch_block, successor_blocks[1]); | 489 TraceConnect(branch, branch_block, successor_blocks[1]); |
451 schedule_->AddBranch(branch_block, branch, successor_blocks[0], | 490 schedule_->AddBranch(branch_block, branch, successor_blocks[0], |
452 successor_blocks[1]); | 491 successor_blocks[1]); |
453 } | 492 } |
454 } | 493 } |
455 | 494 |
456 void ConnectSwitch(Node* sw) { | 495 void ConnectSwitch(Node* sw) { |
457 size_t const successor_count = sw->op()->ControlOutputCount(); | 496 size_t const successor_count = sw->op()->ControlOutputCount(); |
458 BasicBlock** successor_blocks = | 497 BasicBlock** successor_blocks = |
459 zone_->NewArray<BasicBlock*>(successor_count); | 498 zone_->NewArray<BasicBlock*>(successor_count); |
460 CollectSuccessorBlocks(sw, successor_blocks, successor_count); | 499 CollectSuccessorBlocks(sw, successor_blocks, successor_count); |
461 | 500 |
462 if (sw == component_entry_) { | 501 if (sw == component_entry_) { |
463 for (size_t index = 0; index < successor_count; ++index) { | 502 for (size_t index = 0; index < successor_count; ++index) { |
464 TraceConnect(sw, component_start_, successor_blocks[index]); | 503 TraceConnect(sw, component_start_, successor_blocks[index]); |
465 } | 504 } |
466 schedule_->InsertSwitch(component_start_, component_end_, sw, | 505 schedule_->InsertSwitch(component_start_, component_end_, sw, |
467 successor_blocks, successor_count); | 506 successor_blocks, successor_count); |
468 } else { | 507 } else { |
469 Node* sw_block_node = NodeProperties::GetControlInput(sw); | 508 Node* switch_control = NodeProperties::GetControlInput(sw); |
470 BasicBlock* sw_block = schedule_->block(sw_block_node); | 509 BasicBlock* switch_block = FindPredecessorBlock(switch_control); |
471 DCHECK_NOT_NULL(sw_block); | |
472 | |
473 for (size_t index = 0; index < successor_count; ++index) { | 510 for (size_t index = 0; index < successor_count; ++index) { |
474 TraceConnect(sw, sw_block, successor_blocks[index]); | 511 TraceConnect(sw, switch_block, successor_blocks[index]); |
475 } | 512 } |
476 schedule_->AddSwitch(sw_block, sw, successor_blocks, successor_count); | 513 schedule_->AddSwitch(switch_block, sw, successor_blocks, successor_count); |
477 } | 514 } |
478 } | 515 } |
479 | 516 |
480 void ConnectMerge(Node* merge) { | 517 void ConnectMerge(Node* merge) { |
481 // Don't connect the special merge at the end to its predecessors. | 518 // Don't connect the special merge at the end to its predecessors. |
482 if (IsFinalMerge(merge)) return; | 519 if (IsFinalMerge(merge)) return; |
483 | 520 |
484 BasicBlock* block = schedule_->block(merge); | 521 BasicBlock* block = schedule_->block(merge); |
485 DCHECK_NOT_NULL(block); | 522 DCHECK_NOT_NULL(block); |
486 // For all of the merge's control inputs, add a goto at the end to the | 523 // For all of the merge's control inputs, add a goto at the end to the |
487 // merge's basic block. | 524 // merge's basic block. |
488 for (Node* const input : merge->inputs()) { | 525 for (Node* const input : merge->inputs()) { |
489 BasicBlock* predecessor_block = schedule_->block(input); | 526 BasicBlock* predecessor_block = FindPredecessorBlock(input); |
490 TraceConnect(merge, predecessor_block, block); | 527 TraceConnect(merge, predecessor_block, block); |
491 schedule_->AddGoto(predecessor_block, block); | 528 schedule_->AddGoto(predecessor_block, block); |
492 } | 529 } |
493 } | 530 } |
494 | 531 |
495 void ConnectReturn(Node* ret) { | 532 void ConnectReturn(Node* ret) { |
496 Node* return_block_node = NodeProperties::GetControlInput(ret); | 533 Node* return_control = NodeProperties::GetControlInput(ret); |
497 BasicBlock* return_block = schedule_->block(return_block_node); | 534 BasicBlock* return_block = FindPredecessorBlock(return_control); |
498 TraceConnect(ret, return_block, NULL); | 535 TraceConnect(ret, return_block, NULL); |
499 schedule_->AddReturn(return_block, ret); | 536 schedule_->AddReturn(return_block, ret); |
500 } | 537 } |
501 | 538 |
502 void ConnectThrow(Node* thr) { | 539 void ConnectThrow(Node* thr) { |
503 Node* throw_block_node = NodeProperties::GetControlInput(thr); | 540 Node* throw_control = NodeProperties::GetControlInput(thr); |
504 BasicBlock* throw_block = schedule_->block(throw_block_node); | 541 BasicBlock* throw_block = FindPredecessorBlock(throw_control); |
505 TraceConnect(thr, throw_block, NULL); | 542 TraceConnect(thr, throw_block, NULL); |
506 schedule_->AddThrow(throw_block, thr); | 543 schedule_->AddThrow(throw_block, thr); |
507 } | 544 } |
508 | 545 |
509 void TraceConnect(Node* node, BasicBlock* block, BasicBlock* succ) { | 546 void TraceConnect(Node* node, BasicBlock* block, BasicBlock* succ) { |
510 DCHECK_NOT_NULL(block); | 547 DCHECK_NOT_NULL(block); |
511 if (succ == NULL) { | 548 if (succ == NULL) { |
512 Trace("Connect #%d:%s, B%d -> end\n", node->id(), node->op()->mnemonic(), | 549 Trace("Connect #%d:%s, B%d -> end\n", node->id(), node->op()->mnemonic(), |
513 block->id().ToInt()); | 550 block->id().ToInt()); |
514 } else { | 551 } else { |
515 Trace("Connect #%d:%s, B%d -> B%d\n", node->id(), node->op()->mnemonic(), | 552 Trace("Connect #%d:%s, B%d -> B%d\n", node->id(), node->op()->mnemonic(), |
516 block->id().ToInt(), succ->id().ToInt()); | 553 block->id().ToInt(), succ->id().ToInt()); |
517 } | 554 } |
518 } | 555 } |
519 | 556 |
557 bool IsExceptionalCall(Node* node) { | |
558 for (Node* const use : node->uses()) { | |
559 if (use->opcode() == IrOpcode::kIfException) return true; | |
560 } | |
561 return false; | |
562 } | |
563 | |
520 bool IsFinalMerge(Node* node) { | 564 bool IsFinalMerge(Node* node) { |
521 return (node->opcode() == IrOpcode::kMerge && | 565 return (node->opcode() == IrOpcode::kMerge && |
522 node == scheduler_->graph_->end()->InputAt(0)); | 566 node == scheduler_->graph_->end()->InputAt(0)); |
523 } | 567 } |
524 | 568 |
525 bool IsSingleEntrySingleExitRegion(Node* entry, Node* exit) const { | 569 bool IsSingleEntrySingleExitRegion(Node* entry, Node* exit) const { |
526 size_t entry_class = scheduler_->equivalence_->ClassOf(entry); | 570 size_t entry_class = scheduler_->equivalence_->ClassOf(entry); |
527 size_t exit_class = scheduler_->equivalence_->ClassOf(exit); | 571 size_t exit_class = scheduler_->equivalence_->ClassOf(exit); |
528 return entry != exit && entry_class == exit_class; | 572 return entry != exit && entry_class == exit_class; |
529 } | 573 } |
(...skipping 825 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1355 block = hoist_block; | 1399 block = hoist_block; |
1356 hoist_block = GetPreHeader(hoist_block); | 1400 hoist_block = GetPreHeader(hoist_block); |
1357 } while (hoist_block && | 1401 } while (hoist_block && |
1358 hoist_block->dominator_depth() >= min_block->dominator_depth()); | 1402 hoist_block->dominator_depth() >= min_block->dominator_depth()); |
1359 } else if (scheduler_->flags_ & Scheduler::kSplitNodes) { | 1403 } else if (scheduler_->flags_ & Scheduler::kSplitNodes) { |
1360 // Split the {node} if beneficial and return the new {block} for it. | 1404 // Split the {node} if beneficial and return the new {block} for it. |
1361 block = SplitNode(block, node); | 1405 block = SplitNode(block, node); |
1362 } | 1406 } |
1363 | 1407 |
1364 // Schedule the node or a floating control structure. | 1408 // Schedule the node or a floating control structure. |
1365 if (NodeProperties::IsControl(node)) { | 1409 if (IrOpcode::IsMergeOpcode(node->opcode())) { |
1366 ScheduleFloatingControl(block, node); | 1410 ScheduleFloatingControl(block, node); |
1367 } else { | 1411 } else { |
1368 ScheduleNode(block, node); | 1412 ScheduleNode(block, node); |
1369 } | 1413 } |
1370 } | 1414 } |
1371 | 1415 |
1372 // Mark {block} and push its non-marked predecessor on the marking queue. | 1416 // Mark {block} and push its non-marked predecessor on the marking queue. |
1373 void MarkBlock(BasicBlock* block) { | 1417 void MarkBlock(BasicBlock* block) { |
1374 DCHECK_LT(block->id().ToSize(), marked_.size()); | 1418 DCHECK_LT(block->id().ToSize(), marked_.size()); |
1375 marked_[block->id().ToSize()] = true; | 1419 marked_[block->id().ToSize()] = true; |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1479 for (Edge edge : node->use_edges()) { | 1523 for (Edge edge : node->use_edges()) { |
1480 BasicBlock* use_block = GetBlockForUse(edge); | 1524 BasicBlock* use_block = GetBlockForUse(edge); |
1481 block = block == NULL ? use_block : use_block == NULL | 1525 block = block == NULL ? use_block : use_block == NULL |
1482 ? block | 1526 ? block |
1483 : BasicBlock::GetCommonDominator( | 1527 : BasicBlock::GetCommonDominator( |
1484 block, use_block); | 1528 block, use_block); |
1485 } | 1529 } |
1486 return block; | 1530 return block; |
1487 } | 1531 } |
1488 | 1532 |
1533 BasicBlock* FindPredecessorBlock(Node* node) { | |
1534 return scheduler_->control_flow_builder_->FindPredecessorBlock(node); | |
1535 } | |
1536 | |
1489 BasicBlock* GetBlockForUse(Edge edge) { | 1537 BasicBlock* GetBlockForUse(Edge edge) { |
1490 Node* use = edge.from(); | 1538 Node* use = edge.from(); |
1491 IrOpcode::Value opcode = use->opcode(); | 1539 if (IrOpcode::IsPhiOpcode(use->opcode())) { |
1492 if (IrOpcode::IsPhiOpcode(opcode)) { | |
1493 // If the use is from a coupled (i.e. floating) phi, compute the common | 1540 // If the use is from a coupled (i.e. floating) phi, compute the common |
1494 // dominator of its uses. This will not recurse more than one level. | 1541 // dominator of its uses. This will not recurse more than one level. |
1495 if (scheduler_->GetPlacement(use) == Scheduler::kCoupled) { | 1542 if (scheduler_->GetPlacement(use) == Scheduler::kCoupled) { |
1496 Trace(" inspecting uses of coupled #%d:%s\n", use->id(), | 1543 Trace(" inspecting uses of coupled #%d:%s\n", use->id(), |
1497 use->op()->mnemonic()); | 1544 use->op()->mnemonic()); |
1498 DCHECK_EQ(edge.to(), NodeProperties::GetControlInput(use)); | 1545 DCHECK_EQ(edge.to(), NodeProperties::GetControlInput(use)); |
1499 return GetCommonDominatorOfUses(use); | 1546 return GetCommonDominatorOfUses(use); |
1500 } | 1547 } |
1501 // If the use is from a fixed (i.e. non-floating) phi, use the block | 1548 // If the use is from a fixed (i.e. non-floating) phi, we use the |
1502 // of the corresponding control input to the merge. | 1549 // predecessor block of the corresponding control input to the merge. |
1503 if (scheduler_->GetPlacement(use) == Scheduler::kFixed) { | 1550 if (scheduler_->GetPlacement(use) == Scheduler::kFixed) { |
1504 Trace(" input@%d into a fixed phi #%d:%s\n", edge.index(), use->id(), | 1551 Trace(" input@%d into a fixed phi #%d:%s\n", edge.index(), use->id(), |
1505 use->op()->mnemonic()); | 1552 use->op()->mnemonic()); |
1506 Node* merge = NodeProperties::GetControlInput(use, 0); | 1553 Node* merge = NodeProperties::GetControlInput(use, 0); |
1507 opcode = merge->opcode(); | 1554 DCHECK(IrOpcode::IsMergeOpcode(merge->opcode())); |
1508 DCHECK(opcode == IrOpcode::kMerge || opcode == IrOpcode::kLoop); | 1555 Node* input = NodeProperties::GetControlInput(merge, edge.index()); |
1509 use = NodeProperties::GetControlInput(merge, edge.index()); | 1556 return FindPredecessorBlock(input); |
1557 } | |
1558 } else if (IrOpcode::IsMergeOpcode(use->opcode())) { | |
1559 // If the use is from a fixed (i.e. non-floating) merge, we use the | |
1560 // predecessor block of the current input to the merge. | |
1561 if (scheduler_->GetPlacement(use) == Scheduler::kFixed) { | |
1562 Trace(" input@%d into a fixed merge #%d:%s\n", edge.index(), use->id(), | |
1563 use->op()->mnemonic()); | |
1564 return FindPredecessorBlock(edge.to()); | |
1510 } | 1565 } |
1511 } | 1566 } |
1512 BasicBlock* result = schedule_->block(use); | 1567 BasicBlock* result = schedule_->block(use); |
1513 if (result == NULL) return NULL; | 1568 if (result == NULL) return NULL; |
1514 Trace(" must dominate use #%d:%s in B%d\n", use->id(), | 1569 Trace(" must dominate use #%d:%s in B%d\n", use->id(), |
1515 use->op()->mnemonic(), result->id().ToInt()); | 1570 use->op()->mnemonic(), result->id().ToInt()); |
1516 return result; | 1571 return result; |
1517 } | 1572 } |
1518 | 1573 |
1519 void ScheduleFloatingControl(BasicBlock* block, Node* node) { | 1574 void ScheduleFloatingControl(BasicBlock* block, Node* node) { |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1648 for (Node* const node : *nodes) { | 1703 for (Node* const node : *nodes) { |
1649 schedule_->SetBlockForNode(to, node); | 1704 schedule_->SetBlockForNode(to, node); |
1650 scheduled_nodes_[to->id().ToSize()].push_back(node); | 1705 scheduled_nodes_[to->id().ToSize()].push_back(node); |
1651 } | 1706 } |
1652 nodes->clear(); | 1707 nodes->clear(); |
1653 } | 1708 } |
1654 | 1709 |
1655 } // namespace compiler | 1710 } // namespace compiler |
1656 } // namespace internal | 1711 } // namespace internal |
1657 } // namespace v8 | 1712 } // namespace v8 |
OLD | NEW |