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

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

Issue 261823005: Optimize conditional branches that have same true/false targets. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 7 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/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
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
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
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
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