Chromium Code Reviews| 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 5750 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5761 cp.Transform(); | 5761 cp.Transform(); |
| 5762 } | 5762 } |
| 5763 | 5763 |
| 5764 | 5764 |
| 5765 void ConstantPropagator::OptimizeBranches(FlowGraph* graph) { | 5765 void ConstantPropagator::OptimizeBranches(FlowGraph* graph) { |
| 5766 GrowableArray<BlockEntryInstr*> ignored; | 5766 GrowableArray<BlockEntryInstr*> ignored; |
| 5767 ConstantPropagator cp(graph, ignored); | 5767 ConstantPropagator cp(graph, ignored); |
| 5768 cp.Analyze(); | 5768 cp.Analyze(); |
| 5769 cp.VisitBranches(); | 5769 cp.VisitBranches(); |
| 5770 cp.Transform(); | 5770 cp.Transform(); |
| 5771 cp.EliminateRedundantBranches(); | |
| 5772 } | 5771 } |
| 5773 | 5772 |
| 5774 | 5773 |
| 5775 void ConstantPropagator::SetReachable(BlockEntryInstr* block) { | 5774 void ConstantPropagator::SetReachable(BlockEntryInstr* block) { |
| 5776 if (!reachable_->Contains(block->preorder_number())) { | 5775 if (!reachable_->Contains(block->preorder_number())) { |
| 5777 reachable_->Add(block->preorder_number()); | 5776 reachable_->Add(block->preorder_number()); |
| 5778 block_worklist_.Add(block); | 5777 block_worklist_.Add(block); |
| 5779 } | 5778 } |
| 5780 } | 5779 } |
| 5781 | 5780 |
| (...skipping 1062 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6844 } else { | 6843 } else { |
| 6845 // No new information: Assume both targets are reachable. | 6844 // No new information: Assume both targets are reachable. |
| 6846 SetReachable(branch->true_successor()); | 6845 SetReachable(branch->true_successor()); |
| 6847 SetReachable(branch->false_successor()); | 6846 SetReachable(branch->false_successor()); |
| 6848 } | 6847 } |
| 6849 } | 6848 } |
| 6850 } | 6849 } |
| 6851 } | 6850 } |
| 6852 | 6851 |
| 6853 | 6852 |
| 6854 // Traverses a chain of empty blocks and returns the first reachable non-empty | |
| 6855 // block. Empty blocks are added to the supplied bit vector. | |
| 6856 static BlockEntryInstr* FindFirstNonEmptySuccessor( | |
| 6857 TargetEntryInstr* block, | |
| 6858 BitVector* empty_blocks) { | |
| 6859 BlockEntryInstr* current = block; | |
| 6860 while (current->IsEmptyBlock()) { | |
|
Florian Schneider
2013/09/30 14:58:00
There is a bug: I need to check for (#predecessors
| |
| 6861 empty_blocks->Add(current->preorder_number()); | |
| 6862 current = current->next()->AsGoto()->successor(); | |
| 6863 } | |
| 6864 return current; | |
| 6865 } | |
| 6866 | |
| 6867 | |
| 6868 void ConstantPropagator::EliminateRedundantBranches() { | |
| 6869 // Canonicalize branches that have no side-effects and where true- and | |
| 6870 // false-targets are the same. | |
| 6871 BitVector* empty_blocks = new BitVector(graph_->preorder().length()); | |
| 6872 for (BlockIterator b = graph_->postorder_iterator(); | |
| 6873 !b.Done(); | |
| 6874 b.Advance()) { | |
| 6875 BlockEntryInstr* block = b.Current(); | |
| 6876 BranchInstr* branch = block->last_instruction()->AsBranch(); | |
| 6877 empty_blocks->Clear(); | |
| 6878 if ((branch != NULL) && branch->Effects().IsNone()) { | |
| 6879 ASSERT(branch->previous() != NULL); // Not already eliminated. | |
| 6880 BlockEntryInstr* if_true = | |
| 6881 FindFirstNonEmptySuccessor(branch->true_successor(), empty_blocks); | |
| 6882 BlockEntryInstr* if_false = | |
| 6883 FindFirstNonEmptySuccessor(branch->false_successor(), empty_blocks); | |
| 6884 if (if_true == if_false) { | |
| 6885 // Replace the branch with a jump to the common successor. | |
| 6886 // Drop the comparison, which does not have side effects | |
| 6887 JoinEntryInstr* join = if_true->AsJoinEntry(); | |
| 6888 if (join->phis() == NULL) { | |
| 6889 GotoInstr* jump = new GotoInstr(if_true->AsJoinEntry()); | |
| 6890 jump->InheritDeoptTarget(branch); | |
| 6891 | |
| 6892 Instruction* previous = branch->previous(); | |
| 6893 branch->set_previous(NULL); | |
| 6894 previous->LinkTo(jump); | |
| 6895 | |
| 6896 // Remove uses from branch and all the empty blocks that | |
| 6897 // are now unreachable. | |
| 6898 branch->UnuseAllInputs(); | |
| 6899 for (BitVector::Iterator it(empty_blocks); !it.Done(); it.Advance()) { | |
| 6900 BlockEntryInstr* empty_block = graph_->preorder()[it.Current()]; | |
| 6901 empty_block->ClearAllInstructions(); | |
| 6902 } | |
| 6903 | |
| 6904 if (FLAG_trace_constant_propagation) { | |
| 6905 OS::Print("Eliminated branch in B%"Pd" common target B%"Pd"\n", | |
| 6906 block->block_id(), join->block_id()); | |
| 6907 } | |
| 6908 } | |
| 6909 } | |
| 6910 } | |
| 6911 } | |
| 6912 | |
| 6913 graph_->DiscoverBlocks(); | |
| 6914 GrowableArray<BitVector*> dominance_frontier; | |
| 6915 graph_->ComputeDominators(&dominance_frontier); | |
| 6916 } | |
| 6917 | |
| 6918 | |
| 6919 void ConstantPropagator::Transform() { | 6853 void ConstantPropagator::Transform() { |
| 6920 if (FLAG_trace_constant_propagation) { | 6854 if (FLAG_trace_constant_propagation) { |
| 6921 OS::Print("\n==== Before constant propagation ====\n"); | 6855 OS::Print("\n==== Before constant propagation ====\n"); |
| 6922 FlowGraphPrinter printer(*graph_); | 6856 FlowGraphPrinter printer(*graph_); |
| 6923 printer.PrintBlocks(); | 6857 printer.PrintBlocks(); |
| 6924 } | 6858 } |
| 6925 | 6859 |
| 6926 GrowableArray<PhiInstr*> redundant_phis(10); | 6860 GrowableArray<PhiInstr*> redundant_phis(10); |
| 6927 | 6861 |
| 6928 // We will recompute dominators, block ordering, block ids, block last | 6862 // We will recompute dominators, block ordering, block ids, block last |
| 6929 // instructions, previous pointers, predecessors, etc. after eliminating | 6863 // instructions, previous pointers, predecessors, etc. after eliminating |
| 6930 // unreachable code. We do not maintain those properties during the | 6864 // unreachable code. We do not maintain those properties during the |
| 6931 // transformation. | 6865 // transformation. |
| 6932 for (BlockIterator b = graph_->reverse_postorder_iterator(); | 6866 for (BlockIterator b = graph_->reverse_postorder_iterator(); |
| 6933 !b.Done(); | 6867 !b.Done(); |
| 6934 b.Advance()) { | 6868 b.Advance()) { |
| 6935 BlockEntryInstr* block = b.Current(); | 6869 BlockEntryInstr* block = b.Current(); |
| 6870 JoinEntryInstr* join = block->AsJoinEntry(); | |
| 6936 if (!reachable_->Contains(block->preorder_number())) { | 6871 if (!reachable_->Contains(block->preorder_number())) { |
| 6937 if (FLAG_trace_constant_propagation) { | 6872 if (FLAG_trace_constant_propagation) { |
| 6938 OS::Print("Unreachable B%" Pd "\n", block->block_id()); | 6873 OS::Print("Unreachable B%" Pd "\n", block->block_id()); |
| 6939 } | 6874 } |
| 6940 // Remove all uses in unreachable blocks. | 6875 // Remove all uses in unreachable blocks. |
| 6941 block->ClearAllInstructions(); | 6876 if (join != NULL) { |
| 6877 for (PhiIterator it(join); !it.Done(); it.Advance()) { | |
| 6878 it.Current()->UnuseAllInputs(); | |
| 6879 } | |
| 6880 } | |
| 6881 block->UnuseAllInputs(); | |
| 6882 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { | |
| 6883 it.Current()->UnuseAllInputs(); | |
| 6884 } | |
| 6942 continue; | 6885 continue; |
| 6943 } | 6886 } |
| 6944 | 6887 |
| 6945 JoinEntryInstr* join = block->AsJoinEntry(); | |
| 6946 if (join != NULL) { | 6888 if (join != NULL) { |
| 6947 // Remove phi inputs corresponding to unreachable predecessor blocks. | 6889 // Remove phi inputs corresponding to unreachable predecessor blocks. |
| 6948 // Predecessors will be recomputed (in block id order) after removing | 6890 // Predecessors will be recomputed (in block id order) after removing |
| 6949 // unreachable code so we merely have to keep the phi inputs in order. | 6891 // unreachable code so we merely have to keep the phi inputs in order. |
| 6950 ZoneGrowableArray<PhiInstr*>* phis = join->phis(); | 6892 ZoneGrowableArray<PhiInstr*>* phis = join->phis(); |
| 6951 if ((phis != NULL) && !phis->is_empty()) { | 6893 if ((phis != NULL) && !phis->is_empty()) { |
| 6952 intptr_t pred_count = join->PredecessorCount(); | 6894 intptr_t pred_count = join->PredecessorCount(); |
| 6953 intptr_t live_count = 0; | 6895 intptr_t live_count = 0; |
| 6954 for (intptr_t pred_idx = 0; pred_idx < pred_count; ++pred_idx) { | 6896 for (intptr_t pred_idx = 0; pred_idx < pred_count; ++pred_idx) { |
| 6955 if (reachable_->Contains( | 6897 if (reachable_->Contains( |
| (...skipping 737 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7693 } | 7635 } |
| 7694 | 7636 |
| 7695 // Insert materializations at environment uses. | 7637 // Insert materializations at environment uses. |
| 7696 for (intptr_t i = 0; i < exits.length(); i++) { | 7638 for (intptr_t i = 0; i < exits.length(); i++) { |
| 7697 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *fields); | 7639 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *fields); |
| 7698 } | 7640 } |
| 7699 } | 7641 } |
| 7700 | 7642 |
| 7701 | 7643 |
| 7702 } // namespace dart | 7644 } // namespace dart |
| OLD | NEW |