OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/flow_graph_optimizer.h" | 5 #include "vm/flow_graph_optimizer.h" |
6 | 6 |
7 #include "vm/bit_vector.h" | 7 #include "vm/bit_vector.h" |
8 #include "vm/cha.h" | 8 #include "vm/cha.h" |
9 #include "vm/cpu.h" | 9 #include "vm/cpu.h" |
10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
(...skipping 7151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7162 cp.Transform(); | 7162 cp.Transform(); |
7163 } | 7163 } |
7164 | 7164 |
7165 | 7165 |
7166 void ConstantPropagator::OptimizeBranches(FlowGraph* graph) { | 7166 void ConstantPropagator::OptimizeBranches(FlowGraph* graph) { |
7167 GrowableArray<BlockEntryInstr*> ignored; | 7167 GrowableArray<BlockEntryInstr*> ignored; |
7168 ConstantPropagator cp(graph, ignored); | 7168 ConstantPropagator cp(graph, ignored); |
7169 cp.Analyze(); | 7169 cp.Analyze(); |
7170 cp.VisitBranches(); | 7170 cp.VisitBranches(); |
7171 cp.Transform(); | 7171 cp.Transform(); |
| 7172 cp.EliminateRedundantBranches(); |
7172 } | 7173 } |
7173 | 7174 |
7174 | 7175 |
7175 void ConstantPropagator::SetReachable(BlockEntryInstr* block) { | 7176 void ConstantPropagator::SetReachable(BlockEntryInstr* block) { |
7176 if (!reachable_->Contains(block->preorder_number())) { | 7177 if (!reachable_->Contains(block->preorder_number())) { |
7177 reachable_->Add(block->preorder_number()); | 7178 reachable_->Add(block->preorder_number()); |
7178 block_worklist_.Add(block); | 7179 block_worklist_.Add(block); |
7179 } | 7180 } |
7180 } | 7181 } |
7181 | 7182 |
(...skipping 1254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8436 } else { | 8437 } else { |
8437 // No new information: Assume both targets are reachable. | 8438 // No new information: Assume both targets are reachable. |
8438 SetReachable(branch->true_successor()); | 8439 SetReachable(branch->true_successor()); |
8439 SetReachable(branch->false_successor()); | 8440 SetReachable(branch->false_successor()); |
8440 } | 8441 } |
8441 } | 8442 } |
8442 } | 8443 } |
8443 } | 8444 } |
8444 | 8445 |
8445 | 8446 |
| 8447 static bool IsEmptyBlock(BlockEntryInstr* block) { |
| 8448 return block->next()->IsGoto() && |
| 8449 (!block->IsJoinEntry() || (block->AsJoinEntry()->phis() == NULL)); |
| 8450 } |
| 8451 |
| 8452 |
| 8453 // Traverses a chain of empty blocks and returns the first reachable non-empty |
| 8454 // block that is not dominated by the start block. The empty blocks are added |
| 8455 // to the supplied bit vector. |
| 8456 static BlockEntryInstr* FindFirstNonEmptySuccessor( |
| 8457 TargetEntryInstr* block, |
| 8458 BitVector* empty_blocks) { |
| 8459 BlockEntryInstr* current = block; |
| 8460 while (IsEmptyBlock(current) && block->Dominates(current)) { |
| 8461 ASSERT(!block->IsJoinEntry() || (block->AsJoinEntry()->phis() == NULL)); |
| 8462 empty_blocks->Add(current->preorder_number()); |
| 8463 current = current->next()->AsGoto()->successor(); |
| 8464 } |
| 8465 return current; |
| 8466 } |
| 8467 |
| 8468 |
| 8469 void ConstantPropagator::EliminateRedundantBranches() { |
| 8470 // Canonicalize branches that have no side-effects and where true- and |
| 8471 // false-targets are the same. |
| 8472 bool changed = false; |
| 8473 BitVector* empty_blocks = new BitVector(graph_->preorder().length()); |
| 8474 for (BlockIterator b = graph_->postorder_iterator(); |
| 8475 !b.Done(); |
| 8476 b.Advance()) { |
| 8477 BlockEntryInstr* block = b.Current(); |
| 8478 BranchInstr* branch = block->last_instruction()->AsBranch(); |
| 8479 empty_blocks->Clear(); |
| 8480 if ((branch != NULL) && branch->Effects().IsNone()) { |
| 8481 ASSERT(branch->previous() != NULL); // Not already eliminated. |
| 8482 BlockEntryInstr* if_true = |
| 8483 FindFirstNonEmptySuccessor(branch->true_successor(), empty_blocks); |
| 8484 BlockEntryInstr* if_false = |
| 8485 FindFirstNonEmptySuccessor(branch->false_successor(), empty_blocks); |
| 8486 if (if_true == if_false) { |
| 8487 // Replace the branch with a jump to the common successor. |
| 8488 // Drop the comparison, which does not have side effects |
| 8489 JoinEntryInstr* join = if_true->AsJoinEntry(); |
| 8490 if (join->phis() == NULL) { |
| 8491 GotoInstr* jump = new GotoInstr(if_true->AsJoinEntry()); |
| 8492 jump->InheritDeoptTarget(branch); |
| 8493 |
| 8494 Instruction* previous = branch->previous(); |
| 8495 branch->set_previous(NULL); |
| 8496 previous->LinkTo(jump); |
| 8497 |
| 8498 // Remove uses from branch and all the empty blocks that |
| 8499 // are now unreachable. |
| 8500 branch->UnuseAllInputs(); |
| 8501 for (BitVector::Iterator it(empty_blocks); !it.Done(); it.Advance()) { |
| 8502 BlockEntryInstr* empty_block = graph_->preorder()[it.Current()]; |
| 8503 empty_block->ClearAllInstructions(); |
| 8504 } |
| 8505 |
| 8506 changed = true; |
| 8507 |
| 8508 if (FLAG_trace_constant_propagation) { |
| 8509 OS::Print("Eliminated branch in B%"Pd" common target B%"Pd"\n", |
| 8510 block->block_id(), join->block_id()); |
| 8511 } |
| 8512 } |
| 8513 } |
| 8514 } |
| 8515 } |
| 8516 |
| 8517 if (changed) { |
| 8518 graph_->DiscoverBlocks(); |
| 8519 // TODO(fschneider): Update dominator tree in place instead of recomputing. |
| 8520 GrowableArray<BitVector*> dominance_frontier; |
| 8521 graph_->ComputeDominators(&dominance_frontier); |
| 8522 } |
| 8523 } |
| 8524 |
| 8525 |
8446 void ConstantPropagator::Transform() { | 8526 void ConstantPropagator::Transform() { |
8447 if (FLAG_trace_constant_propagation) { | 8527 if (FLAG_trace_constant_propagation) { |
8448 OS::Print("\n==== Before constant propagation ====\n"); | 8528 OS::Print("\n==== Before constant propagation ====\n"); |
8449 FlowGraphPrinter printer(*graph_); | 8529 FlowGraphPrinter printer(*graph_); |
8450 printer.PrintBlocks(); | 8530 printer.PrintBlocks(); |
8451 } | 8531 } |
8452 | 8532 |
8453 GrowableArray<PhiInstr*> redundant_phis(10); | 8533 GrowableArray<PhiInstr*> redundant_phis(10); |
8454 | 8534 |
8455 // We will recompute dominators, block ordering, block ids, block last | 8535 // We will recompute dominators, block ordering, block ids, block last |
8456 // instructions, previous pointers, predecessors, etc. after eliminating | 8536 // instructions, previous pointers, predecessors, etc. after eliminating |
8457 // unreachable code. We do not maintain those properties during the | 8537 // unreachable code. We do not maintain those properties during the |
8458 // transformation. | 8538 // transformation. |
8459 for (BlockIterator b = graph_->reverse_postorder_iterator(); | 8539 for (BlockIterator b = graph_->reverse_postorder_iterator(); |
8460 !b.Done(); | 8540 !b.Done(); |
8461 b.Advance()) { | 8541 b.Advance()) { |
8462 BlockEntryInstr* block = b.Current(); | 8542 BlockEntryInstr* block = b.Current(); |
8463 JoinEntryInstr* join = block->AsJoinEntry(); | |
8464 if (!reachable_->Contains(block->preorder_number())) { | 8543 if (!reachable_->Contains(block->preorder_number())) { |
8465 if (FLAG_trace_constant_propagation) { | 8544 if (FLAG_trace_constant_propagation) { |
8466 OS::Print("Unreachable B%" Pd "\n", block->block_id()); | 8545 OS::Print("Unreachable B%" Pd "\n", block->block_id()); |
8467 } | 8546 } |
8468 // Remove all uses in unreachable blocks. | 8547 // Remove all uses in unreachable blocks. |
8469 if (join != NULL) { | 8548 block->ClearAllInstructions(); |
8470 for (PhiIterator it(join); !it.Done(); it.Advance()) { | |
8471 it.Current()->UnuseAllInputs(); | |
8472 } | |
8473 } | |
8474 block->UnuseAllInputs(); | |
8475 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { | |
8476 it.Current()->UnuseAllInputs(); | |
8477 } | |
8478 continue; | 8549 continue; |
8479 } | 8550 } |
8480 | 8551 |
| 8552 JoinEntryInstr* join = block->AsJoinEntry(); |
8481 if (join != NULL) { | 8553 if (join != NULL) { |
8482 // Remove phi inputs corresponding to unreachable predecessor blocks. | 8554 // Remove phi inputs corresponding to unreachable predecessor blocks. |
8483 // Predecessors will be recomputed (in block id order) after removing | 8555 // Predecessors will be recomputed (in block id order) after removing |
8484 // unreachable code so we merely have to keep the phi inputs in order. | 8556 // unreachable code so we merely have to keep the phi inputs in order. |
8485 ZoneGrowableArray<PhiInstr*>* phis = join->phis(); | 8557 ZoneGrowableArray<PhiInstr*>* phis = join->phis(); |
8486 if ((phis != NULL) && !phis->is_empty()) { | 8558 if ((phis != NULL) && !phis->is_empty()) { |
8487 intptr_t pred_count = join->PredecessorCount(); | 8559 intptr_t pred_count = join->PredecessorCount(); |
8488 intptr_t live_count = 0; | 8560 intptr_t live_count = 0; |
8489 for (intptr_t pred_idx = 0; pred_idx < pred_count; ++pred_idx) { | 8561 for (intptr_t pred_idx = 0; pred_idx < pred_count; ++pred_idx) { |
8490 if (reachable_->Contains( | 8562 if (reachable_->Contains( |
(...skipping 713 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9204 } | 9276 } |
9205 | 9277 |
9206 // Insert materializations at environment uses. | 9278 // Insert materializations at environment uses. |
9207 for (intptr_t i = 0; i < exits.length(); i++) { | 9279 for (intptr_t i = 0; i < exits.length(); i++) { |
9208 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *slots); | 9280 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *slots); |
9209 } | 9281 } |
9210 } | 9282 } |
9211 | 9283 |
9212 | 9284 |
9213 } // namespace dart | 9285 } // namespace dart |
OLD | NEW |