Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(27)

Side by Side Diff: runtime/vm/flow_graph_optimizer.cc

Issue 23549020: Optimize conditional branches that have same true/false targets. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: addressed comments Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/flow_graph_optimizer.h ('k') | runtime/vm/intermediate_language.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_optimizer.h ('k') | runtime/vm/intermediate_language.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698