Index: src/compiler/scheduler.cc |
diff --git a/src/compiler/scheduler.cc b/src/compiler/scheduler.cc |
index c0f05c506f71fc754decd589ae10bfbdc04b9e80..a75a9ef0e47f1f9ddf4fa8dc509b0f6bb93b31e2 100644 |
--- a/src/compiler/scheduler.cc |
+++ b/src/compiler/scheduler.cc |
@@ -562,15 +562,26 @@ class SpecialRPONumberer { |
BasicBlockVector* final_order = schedule_->rpo_order(); |
order->Serialize(final_order); |
- // Compute the correct loop header for every block and set the correct loop |
- // ends. |
+ // Compute the correct loop headers and set the correct loop ends. |
LoopInfo* current_loop = NULL; |
BasicBlock* current_header = NULL; |
int loop_depth = 0; |
for (BasicBlockVectorIter i = final_order->begin(); i != final_order->end(); |
++i) { |
BasicBlock* current = *i; |
+ |
+ // Finish the previous loop(s) if we just exited them. |
+ while (current_header != NULL && |
+ current->rpo_number() >= current_header->loop_end()) { |
+ DCHECK(current_header->IsLoopHeader()); |
+ DCHECK(current_loop != NULL); |
+ current_loop = current_loop->prev; |
+ current_header = current_loop == NULL ? NULL : current_loop->header; |
+ --loop_depth; |
+ } |
current->set_loop_header(current_header); |
+ |
+ // Push a new loop onto the stack if this loop is a loop header. |
if (current->IsLoopHeader()) { |
loop_depth++; |
current_loop = &loops[current->loop_end()]; |
@@ -581,17 +592,10 @@ class SpecialRPONumberer { |
current_header = current_loop->header; |
Trace("B%d is a loop header, increment loop depth to %d\n", |
current->id().ToInt(), loop_depth); |
- } else { |
- while (current_header != NULL && |
- current->rpo_number() >= current_header->loop_end()) { |
- DCHECK(current_header->IsLoopHeader()); |
- DCHECK(current_loop != NULL); |
- current_loop = current_loop->prev; |
- current_header = current_loop == NULL ? NULL : current_loop->header; |
- --loop_depth; |
- } |
} |
+ |
current->set_loop_depth(loop_depth); |
+ |
if (current->loop_header() == NULL) { |
Trace("B%d is not in a loop (depth == %d)\n", current->id().ToInt(), |
current->loop_depth()); |
@@ -756,6 +760,12 @@ class SpecialRPONumberer { |
os << " range: [" << block->rpo_number() << ", " << block->loop_end() |
<< ")"; |
} |
+ if (block->loop_header() != NULL) { |
+ os << " header: B" << block->loop_header()->id(); |
+ } |
+ if (block->loop_depth() > 0) { |
+ os << " depth: " << block->loop_depth(); |
+ } |
os << "\n"; |
} |
} |
@@ -775,6 +785,7 @@ class SpecialRPONumberer { |
DCHECK(header->loop_end() >= 0); |
DCHECK(header->loop_end() <= static_cast<int>(order->size())); |
DCHECK(header->loop_end() > header->rpo_number()); |
+ DCHECK(header->loop_header() != header); |
// Verify the start ... end list relationship. |
int links = 0; |
@@ -1074,31 +1085,29 @@ class ScheduleLateNodeVisitor { |
// Hoist nodes out of loops if possible. Nodes can be hoisted iteratively |
// into enclosing loop pre-headers until they would preceed their |
// ScheduleEarly position. |
- BasicBlock* hoist_block = block; |
+ BasicBlock* hoist_block = GetPreHeader(block); |
while (hoist_block != NULL && hoist_block->rpo_number() >= min_rpo) { |
- if (hoist_block->loop_depth() < block->loop_depth()) { |
- block = hoist_block; |
- Trace(" hoisting #%d:%s to block %d\n", node->id(), |
- node->op()->mnemonic(), block->id().ToInt()); |
- } |
- // Try to hoist to the pre-header of the loop header. |
- hoist_block = hoist_block->loop_header(); |
- if (hoist_block != NULL) { |
- BasicBlock* pre_header = hoist_block->dominator(); |
- DCHECK(pre_header == NULL || |
- *hoist_block->predecessors_begin() == pre_header); |
- Trace( |
- " hoist to pre-header B%d of loop header B%d, depth would be %d\n", |
- pre_header->id().ToInt(), hoist_block->id().ToInt(), |
- pre_header->loop_depth()); |
- hoist_block = pre_header; |
- } |
+ Trace(" hoisting #%d:%s to block %d\n", node->id(), |
+ node->op()->mnemonic(), hoist_block->id().ToInt()); |
+ DCHECK_LT(hoist_block->loop_depth(), block->loop_depth()); |
+ block = hoist_block; |
+ hoist_block = GetPreHeader(hoist_block); |
} |
ScheduleNode(block, node); |
} |
private: |
+ 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* GetCommonDominatorOfUses(Node* node) { |
BasicBlock* block = NULL; |
Node::Uses uses = node->uses(); |