| Index: src/compiler/schedule.cc
|
| diff --git a/src/compiler/schedule.cc b/src/compiler/schedule.cc
|
| index 08e078ef5ac89654445c78e33a7a03451a3e7cf2..6bd1a17be0603476585442eaea760ce2b1ad3eb4 100644
|
| --- a/src/compiler/schedule.cc
|
| +++ b/src/compiler/schedule.cc
|
| @@ -315,41 +315,87 @@ void Schedule::InsertSwitch(BasicBlock* block, BasicBlock* end, Node* sw,
|
| SetControlInput(block, sw);
|
| }
|
|
|
| -void Schedule::EnsureSplitEdgeForm() {
|
| +void Schedule::EnsureCFGWellFormedness() {
|
| // Make a copy of all the blocks for the iteration, since adding the split
|
| // edges will allocate new blocks.
|
| BasicBlockVector all_blocks_copy(all_blocks_);
|
|
|
| // Insert missing split edge blocks.
|
| for (auto block : all_blocks_copy) {
|
| - if (block->PredecessorCount() > 1 && block != end_) {
|
| - for (auto current_pred = block->predecessors().begin();
|
| - current_pred != block->predecessors().end(); ++current_pred) {
|
| - BasicBlock* pred = *current_pred;
|
| - if (pred->SuccessorCount() > 1) {
|
| - // Found a predecessor block with multiple successors.
|
| - BasicBlock* split_edge_block = NewBasicBlock();
|
| - split_edge_block->set_control(BasicBlock::kGoto);
|
| - split_edge_block->successors().push_back(block);
|
| - split_edge_block->predecessors().push_back(pred);
|
| - split_edge_block->set_deferred(pred->deferred());
|
| - *current_pred = split_edge_block;
|
| - // Find a corresponding successor in the previous block, replace it
|
| - // with the split edge block... but only do it once, since we only
|
| - // replace the previous blocks in the current block one at a time.
|
| - for (auto successor = pred->successors().begin();
|
| - successor != pred->successors().end(); ++successor) {
|
| - if (*successor == block) {
|
| - *successor = split_edge_block;
|
| - break;
|
| - }
|
| - }
|
| + if (block->PredecessorCount() > 1) {
|
| + if (block != end_) {
|
| + EnsureSplitEdgeForm(block);
|
| + }
|
| + if (block->deferred()) {
|
| + EnsureDeferredCodeSingleEntryPoint(block);
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| +void Schedule::EnsureSplitEdgeForm(BasicBlock* block) {
|
| + DCHECK(block->PredecessorCount() > 1 && block != end_);
|
| + for (auto current_pred = block->predecessors().begin();
|
| + current_pred != block->predecessors().end(); ++current_pred) {
|
| + BasicBlock* pred = *current_pred;
|
| + if (pred->SuccessorCount() > 1) {
|
| + // Found a predecessor block with multiple successors.
|
| + BasicBlock* split_edge_block = NewBasicBlock();
|
| + split_edge_block->set_control(BasicBlock::kGoto);
|
| + split_edge_block->successors().push_back(block);
|
| + split_edge_block->predecessors().push_back(pred);
|
| + split_edge_block->set_deferred(pred->deferred());
|
| + *current_pred = split_edge_block;
|
| + // Find a corresponding successor in the previous block, replace it
|
| + // with the split edge block... but only do it once, since we only
|
| + // replace the previous blocks in the current block one at a time.
|
| + for (auto successor = pred->successors().begin();
|
| + successor != pred->successors().end(); ++successor) {
|
| + if (*successor == block) {
|
| + *successor = split_edge_block;
|
| + break;
|
| }
|
| }
|
| }
|
| }
|
| }
|
|
|
| +void Schedule::EnsureDeferredCodeSingleEntryPoint(BasicBlock* block) {
|
| + // If a deferred block has multiple predecessors, they have to
|
| + // all be deferred. Otherwise, we can run into a situation where a range
|
| + // that spills only in deferred blocks inserts its spill in the block, but
|
| + // other ranges need moves inserted by ResolveControlFlow in the predecessors,
|
| + // which may clobber the register of this range.
|
| + // To ensure that, when a deferred block has multiple predecessors, and some
|
| + // are not deferred, we add a non-deferred block to collect all such edges.
|
| +
|
| + DCHECK(block->deferred() && block->PredecessorCount() > 1);
|
| + bool all_deferred = true;
|
| + for (auto current_pred = block->predecessors().begin();
|
| + current_pred != block->predecessors().end(); ++current_pred) {
|
| + BasicBlock* pred = *current_pred;
|
| + if (!pred->deferred()) {
|
| + all_deferred = false;
|
| + break;
|
| + }
|
| + }
|
| +
|
| + if (all_deferred) return;
|
| + BasicBlock* merger = NewBasicBlock();
|
| + merger->set_control(BasicBlock::kGoto);
|
| + merger->successors().push_back(block);
|
| + for (auto current_pred = block->predecessors().begin();
|
| + current_pred != block->predecessors().end(); ++current_pred) {
|
| + BasicBlock* pred = *current_pred;
|
| + merger->predecessors().push_back(pred);
|
| + pred->successors().clear();
|
| + pred->successors().push_back(merger);
|
| + }
|
| + merger->set_deferred(false);
|
| + block->predecessors().clear();
|
| + block->predecessors().push_back(merger);
|
| +}
|
| +
|
| void Schedule::PropagateDeferredMark() {
|
| // Push forward the deferred block marks through newly inserted blocks and
|
| // other improperly marked blocks until a fixed point is reached.
|
|
|