Chromium Code Reviews| 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 |