| 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/dart_entry.h" | 9 #include "vm/dart_entry.h" |
| 10 #include "vm/flow_graph_builder.h" | 10 #include "vm/flow_graph_builder.h" |
| (...skipping 5604 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5615 cp.Transform(); | 5615 cp.Transform(); |
| 5616 } | 5616 } |
| 5617 | 5617 |
| 5618 | 5618 |
| 5619 void ConstantPropagator::OptimizeBranches(FlowGraph* graph) { | 5619 void ConstantPropagator::OptimizeBranches(FlowGraph* graph) { |
| 5620 GrowableArray<BlockEntryInstr*> ignored; | 5620 GrowableArray<BlockEntryInstr*> ignored; |
| 5621 ConstantPropagator cp(graph, ignored); | 5621 ConstantPropagator cp(graph, ignored); |
| 5622 cp.Analyze(); | 5622 cp.Analyze(); |
| 5623 cp.VisitBranches(); | 5623 cp.VisitBranches(); |
| 5624 cp.Transform(); | 5624 cp.Transform(); |
| 5625 cp.EliminateRedundantBranches(); |
| 5625 } | 5626 } |
| 5626 | 5627 |
| 5627 | 5628 |
| 5628 void ConstantPropagator::SetReachable(BlockEntryInstr* block) { | 5629 void ConstantPropagator::SetReachable(BlockEntryInstr* block) { |
| 5629 if (!reachable_->Contains(block->preorder_number())) { | 5630 if (!reachable_->Contains(block->preorder_number())) { |
| 5630 reachable_->Add(block->preorder_number()); | 5631 reachable_->Add(block->preorder_number()); |
| 5631 block_worklist_.Add(block); | 5632 block_worklist_.Add(block); |
| 5632 } | 5633 } |
| 5633 } | 5634 } |
| 5634 | 5635 |
| (...skipping 1056 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6691 } else { | 6692 } else { |
| 6692 // No new information: Assume both targets are reachable. | 6693 // No new information: Assume both targets are reachable. |
| 6693 SetReachable(branch->true_successor()); | 6694 SetReachable(branch->true_successor()); |
| 6694 SetReachable(branch->false_successor()); | 6695 SetReachable(branch->false_successor()); |
| 6695 } | 6696 } |
| 6696 } | 6697 } |
| 6697 } | 6698 } |
| 6698 } | 6699 } |
| 6699 | 6700 |
| 6700 | 6701 |
| 6702 // Traverses a chain of empty blocks and returns the first reachable non-empty |
| 6703 // block. Empty blocks are added to the supplied bit vector. |
| 6704 static BlockEntryInstr* FindFirstNonEmptySuccessor( |
| 6705 TargetEntryInstr* block, |
| 6706 BitVector* empty_blocks) { |
| 6707 BlockEntryInstr* current = block; |
| 6708 while (current->IsEmptyBlock()) { |
| 6709 empty_blocks->Add(current->preorder_number()); |
| 6710 current = current->next()->AsGoto()->successor(); |
| 6711 } |
| 6712 return current; |
| 6713 } |
| 6714 |
| 6715 |
| 6716 void ConstantPropagator::EliminateRedundantBranches() { |
| 6717 // Canonicalize branches that have no side-effects and where true- and |
| 6718 // false-targets are the same. |
| 6719 BitVector* empty_blocks = new BitVector(graph_->preorder().length()); |
| 6720 for (BlockIterator b = graph_->postorder_iterator(); |
| 6721 !b.Done(); |
| 6722 b.Advance()) { |
| 6723 BlockEntryInstr* block = b.Current(); |
| 6724 BranchInstr* branch = block->last_instruction()->AsBranch(); |
| 6725 empty_blocks->Clear(); |
| 6726 if ((branch != NULL) && branch->Effects().IsNone()) { |
| 6727 ASSERT(branch->previous() != NULL); // Not already eliminated. |
| 6728 BlockEntryInstr* if_true = |
| 6729 FindFirstNonEmptySuccessor(branch->true_successor(), empty_blocks); |
| 6730 BlockEntryInstr* if_false = |
| 6731 FindFirstNonEmptySuccessor(branch->false_successor(), empty_blocks); |
| 6732 if (if_true == if_false) { |
| 6733 // Replace the branch with a jump to the common successor. |
| 6734 // Drop the comparison, which does not have side effects |
| 6735 JoinEntryInstr* join = if_true->AsJoinEntry(); |
| 6736 if (join->phis() == NULL) { |
| 6737 GotoInstr* jump = new GotoInstr(if_true->AsJoinEntry()); |
| 6738 jump->InheritDeoptTarget(branch); |
| 6739 |
| 6740 Instruction* previous = branch->previous(); |
| 6741 branch->set_previous(NULL); |
| 6742 previous->LinkTo(jump); |
| 6743 |
| 6744 // Remove uses from branch and all the empty blocks that |
| 6745 // are now unreachable. |
| 6746 branch->UnuseAllInputs(); |
| 6747 for (BitVector::Iterator it(empty_blocks); !it.Done(); it.Advance()) { |
| 6748 BlockEntryInstr* empty_block = graph_->preorder()[it.Current()]; |
| 6749 empty_block->ClearAllInstructions(); |
| 6750 } |
| 6751 |
| 6752 if (FLAG_trace_constant_propagation) { |
| 6753 OS::Print("Eliminated branch in B%"Pd" common target B%"Pd"\n", |
| 6754 block->block_id(), join->block_id()); |
| 6755 } |
| 6756 } |
| 6757 } |
| 6758 } |
| 6759 } |
| 6760 |
| 6761 graph_->DiscoverBlocks(); |
| 6762 GrowableArray<BitVector*> dominance_frontier; |
| 6763 graph_->ComputeDominators(&dominance_frontier); |
| 6764 } |
| 6765 |
| 6766 |
| 6701 void ConstantPropagator::Transform() { | 6767 void ConstantPropagator::Transform() { |
| 6702 if (FLAG_trace_constant_propagation) { | 6768 if (FLAG_trace_constant_propagation) { |
| 6703 OS::Print("\n==== Before constant propagation ====\n"); | 6769 OS::Print("\n==== Before constant propagation ====\n"); |
| 6704 FlowGraphPrinter printer(*graph_); | 6770 FlowGraphPrinter printer(*graph_); |
| 6705 printer.PrintBlocks(); | 6771 printer.PrintBlocks(); |
| 6706 } | 6772 } |
| 6707 | 6773 |
| 6708 GrowableArray<PhiInstr*> redundant_phis(10); | 6774 GrowableArray<PhiInstr*> redundant_phis(10); |
| 6709 | 6775 |
| 6710 // We will recompute dominators, block ordering, block ids, block last | 6776 // We will recompute dominators, block ordering, block ids, block last |
| 6711 // instructions, previous pointers, predecessors, etc. after eliminating | 6777 // instructions, previous pointers, predecessors, etc. after eliminating |
| 6712 // unreachable code. We do not maintain those properties during the | 6778 // unreachable code. We do not maintain those properties during the |
| 6713 // transformation. | 6779 // transformation. |
| 6714 for (BlockIterator b = graph_->reverse_postorder_iterator(); | 6780 for (BlockIterator b = graph_->reverse_postorder_iterator(); |
| 6715 !b.Done(); | 6781 !b.Done(); |
| 6716 b.Advance()) { | 6782 b.Advance()) { |
| 6717 BlockEntryInstr* block = b.Current(); | 6783 BlockEntryInstr* block = b.Current(); |
| 6718 JoinEntryInstr* join = block->AsJoinEntry(); | |
| 6719 if (!reachable_->Contains(block->preorder_number())) { | 6784 if (!reachable_->Contains(block->preorder_number())) { |
| 6720 if (FLAG_trace_constant_propagation) { | 6785 if (FLAG_trace_constant_propagation) { |
| 6721 OS::Print("Unreachable B%" Pd "\n", block->block_id()); | 6786 OS::Print("Unreachable B%" Pd "\n", block->block_id()); |
| 6722 } | 6787 } |
| 6723 // Remove all uses in unreachable blocks. | 6788 // Remove all uses in unreachable blocks. |
| 6724 if (join != NULL) { | 6789 block->ClearAllInstructions(); |
| 6725 for (PhiIterator it(join); !it.Done(); it.Advance()) { | |
| 6726 it.Current()->UnuseAllInputs(); | |
| 6727 } | |
| 6728 } | |
| 6729 block->UnuseAllInputs(); | |
| 6730 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { | |
| 6731 it.Current()->UnuseAllInputs(); | |
| 6732 } | |
| 6733 continue; | 6790 continue; |
| 6734 } | 6791 } |
| 6735 | 6792 |
| 6793 JoinEntryInstr* join = block->AsJoinEntry(); |
| 6736 if (join != NULL) { | 6794 if (join != NULL) { |
| 6737 // Remove phi inputs corresponding to unreachable predecessor blocks. | 6795 // Remove phi inputs corresponding to unreachable predecessor blocks. |
| 6738 // Predecessors will be recomputed (in block id order) after removing | 6796 // Predecessors will be recomputed (in block id order) after removing |
| 6739 // unreachable code so we merely have to keep the phi inputs in order. | 6797 // unreachable code so we merely have to keep the phi inputs in order. |
| 6740 ZoneGrowableArray<PhiInstr*>* phis = join->phis(); | 6798 ZoneGrowableArray<PhiInstr*>* phis = join->phis(); |
| 6741 if ((phis != NULL) && !phis->is_empty()) { | 6799 if ((phis != NULL) && !phis->is_empty()) { |
| 6742 intptr_t pred_count = join->PredecessorCount(); | 6800 intptr_t pred_count = join->PredecessorCount(); |
| 6743 intptr_t live_count = 0; | 6801 intptr_t live_count = 0; |
| 6744 for (intptr_t pred_idx = 0; pred_idx < pred_count; ++pred_idx) { | 6802 for (intptr_t pred_idx = 0; pred_idx < pred_count; ++pred_idx) { |
| 6745 if (reachable_->Contains( | 6803 if (reachable_->Contains( |
| (...skipping 737 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7483 } | 7541 } |
| 7484 | 7542 |
| 7485 // Insert materializations at environment uses. | 7543 // Insert materializations at environment uses. |
| 7486 for (intptr_t i = 0; i < exits.length(); i++) { | 7544 for (intptr_t i = 0; i < exits.length(); i++) { |
| 7487 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *fields); | 7545 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *fields); |
| 7488 } | 7546 } |
| 7489 } | 7547 } |
| 7490 | 7548 |
| 7491 | 7549 |
| 7492 } // namespace dart | 7550 } // namespace dart |
| OLD | NEW |