| Index: src/compiler/scheduler.cc
|
| diff --git a/src/compiler/scheduler.cc b/src/compiler/scheduler.cc
|
| index 674b89ef66762d0b5ffa5c5b052e094d3ac0d290..3e7d353cb7bf8e675b177b10f79079a71d09d536 100644
|
| --- a/src/compiler/scheduler.cc
|
| +++ b/src/compiler/scheduler.cc
|
| @@ -587,7 +587,8 @@ class SpecialRPONumberer : public ZoneObject {
|
| loops_(zone),
|
| backedges_(zone),
|
| stack_(zone),
|
| - previous_block_count_(0) {}
|
| + previous_block_count_(0),
|
| + empty_(0, zone) {}
|
|
|
| // Computes the special reverse-post-order for the main control flow graph,
|
| // that is for the graph spanned between the schedule's start and end blocks.
|
| @@ -624,6 +625,14 @@ class SpecialRPONumberer : public ZoneObject {
|
| #endif
|
| }
|
|
|
| + const ZoneList<BasicBlock*>& GetOutgoingBlocks(BasicBlock* block) {
|
| + if (HasLoopNumber(block)) {
|
| + LoopInfo const& loop = loops_[GetLoopNumber(block)];
|
| + if (loop.outgoing) return *loop.outgoing;
|
| + }
|
| + return empty_;
|
| + }
|
| +
|
| private:
|
| typedef std::pair<BasicBlock*, size_t> Backedge;
|
|
|
| @@ -1046,6 +1055,7 @@ class SpecialRPONumberer : public ZoneObject {
|
| ZoneVector<Backedge> backedges_;
|
| ZoneVector<SpecialRPOStackFrame> stack_;
|
| size_t previous_block_count_;
|
| + ZoneList<BasicBlock*> const empty_;
|
| };
|
|
|
|
|
| @@ -1346,7 +1356,7 @@ class ScheduleLateNodeVisitor {
|
| // Hoist nodes out of loops if possible. Nodes can be hoisted iteratively
|
| // into enclosing loop pre-headers until they would preceed their schedule
|
| // early position.
|
| - BasicBlock* hoist_block = GetPreHeader(block);
|
| + BasicBlock* hoist_block = GetHoistBlock(block);
|
| if (hoist_block &&
|
| hoist_block->dominator_depth() >= min_block->dominator_depth()) {
|
| do {
|
| @@ -1354,7 +1364,7 @@ class ScheduleLateNodeVisitor {
|
| node->op()->mnemonic(), hoist_block->id().ToInt());
|
| DCHECK_LT(hoist_block->loop_depth(), block->loop_depth());
|
| block = hoist_block;
|
| - hoist_block = GetPreHeader(hoist_block);
|
| + hoist_block = GetHoistBlock(hoist_block);
|
| } while (hoist_block &&
|
| hoist_block->dominator_depth() >= min_block->dominator_depth());
|
| } else if (scheduler_->flags_ & Scheduler::kSplitNodes) {
|
| @@ -1465,14 +1475,23 @@ class ScheduleLateNodeVisitor {
|
| return block;
|
| }
|
|
|
| - BasicBlock* GetPreHeader(BasicBlock* block) {
|
| - if (block->IsLoopHeader()) {
|
| - return block->dominator();
|
| - } else if (block->loop_header() != NULL) {
|
| - return block->loop_header()->dominator();
|
| - } else {
|
| - return NULL;
|
| + BasicBlock* GetHoistBlock(BasicBlock* block) {
|
| + if (block->IsLoopHeader()) return block->dominator();
|
| + // We have to check to make sure that the {block} dominates all
|
| + // of the outgoing blocks. If it doesn't, then there is a path
|
| + // out of the loop which does not execute this {block}, so we
|
| + // can't hoist operations from this {block} out of the loop, as
|
| + // that would introduce additional computations.
|
| + if (BasicBlock* header_block = block->loop_header()) {
|
| + for (BasicBlock* outgoing_block :
|
| + scheduler_->special_rpo_->GetOutgoingBlocks(header_block)) {
|
| + if (BasicBlock::GetCommonDominator(block, outgoing_block) != block) {
|
| + return nullptr;
|
| + }
|
| + }
|
| + return header_block->dominator();
|
| }
|
| + return nullptr;
|
| }
|
|
|
| BasicBlock* GetCommonDominatorOfUses(Node* node) {
|
|
|