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

Unified 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: Created 7 years, 3 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 side-by-side diff with in-line comments
Download patch
Index: runtime/vm/flow_graph_optimizer.cc
===================================================================
--- runtime/vm/flow_graph_optimizer.cc (revision 27294)
+++ runtime/vm/flow_graph_optimizer.cc (working copy)
@@ -6698,6 +6698,84 @@
}
+static bool IsEmpty(BlockEntryInstr* block) {
+ return block->next()->IsGoto()
Kevin Millikin (Google) 2013/09/27 11:03:43 I swear we have exactly this same function somewhe
Florian Schneider 2013/09/30 12:19:23 We have one that deals with blocks after translate
Kevin Millikin (Google) 2013/09/30 12:27:41 Nah, it's not necessary.
+ && (!block->IsJoinEntry() || (block->AsJoinEntry()->phis() == NULL));
+}
+
+
+// Traverses a chain of empty blocks and return the first
srdjan 2013/09/27 15:44:11 Why only 60 chars per line? s/return/returns/
Florian Schneider 2013/09/30 12:19:23 Done.
+// reachable non-empty block. Empty blocks are added to
+// the supplied bit vector.
+static BlockEntryInstr* FindFirstNonEmptySuccessor(
+ TargetEntryInstr* block,
+ BitVector* empty_blocks) {
+ BlockEntryInstr* current = block;
+ while (IsEmpty(current)) {
+ empty_blocks->Add(current->preorder_number());
+ current = current->next()->AsGoto()->successor();
+ }
+ return current;
+}
+
+void ConstantPropagator::RemoveRedundantBranches(FlowGraph* graph) {
+ GrowableArray<BlockEntryInstr*> ignored;
+ ConstantPropagator cp(graph, ignored);
+ cp.EliminateRedundantBranches();
+}
+
+
+void ConstantPropagator::EliminateRedundantBranches() {
+ // Canonicalize branches that have no side-effects and
+ // where true- and false-target are the same.
srdjan 2013/09/27 15:44:11 s/target/targets/
Florian Schneider 2013/09/30 12:19:23 Done.
+ BitVector* empty_blocks = new BitVector(graph_->preorder().length());
+ for (BlockIterator b = graph_->postorder_iterator();
+ !b.Done();
+ b.Advance()) {
+ BlockEntryInstr* block = b.Current();
+ BranchInstr* branch = block->last_instruction()->AsBranch();
+ empty_blocks->Clear();
+ if ((branch != NULL) && branch->Effects().IsNone()) {
+ ASSERT(branch->previous() != NULL); // Not already eliminated.
+ BlockEntryInstr* if_true =
+ FindFirstNonEmptySuccessor(branch->true_successor(), empty_blocks);
+ BlockEntryInstr* if_false =
+ FindFirstNonEmptySuccessor(branch->false_successor(), empty_blocks);
+ if (if_true == if_false) {
+ // Replace the branch with a jump to the common successor.
+ // Drop the comparison, which does not have side effects
+ JoinEntryInstr* join = if_true->AsJoinEntry();
+ if (join->phis() == NULL) {
+ GotoInstr* jump = new GotoInstr(if_true->AsJoinEntry());
+ jump->InheritDeoptTarget(branch);
+
+ Instruction* previous = branch->previous();
+ branch->set_previous(NULL);
+ previous->LinkTo(jump);
+
+ // Remove uses from branch and all the empty blocks that
+ // are now unreachable.
+ branch->UnuseAllInputs();
+ for (BitVector::Iterator it(empty_blocks); !it.Done(); it.Advance()) {
+ BlockEntryInstr* empty_block = graph_->preorder()[it.Current()];
+ empty_block->UnuseAllInstructions();
+ }
+
+ if (FLAG_trace_constant_propagation) {
+ OS::Print("Eliminated branch in B%"Pd" common target B%"Pd"\n",
+ block->block_id(), join->block_id());
+ }
+ }
+ }
+ }
+ }
+
+ graph_->DiscoverBlocks();
+ GrowableArray<BitVector*> dominance_frontier;
+ graph_->ComputeDominators(&dominance_frontier);
+}
+
+
void ConstantPropagator::Transform() {
if (FLAG_trace_constant_propagation) {
OS::Print("\n==== Before constant propagation ====\n");
@@ -6715,24 +6793,16 @@
!b.Done();
b.Advance()) {
BlockEntryInstr* block = b.Current();
- JoinEntryInstr* join = block->AsJoinEntry();
if (!reachable_->Contains(block->preorder_number())) {
if (FLAG_trace_constant_propagation) {
OS::Print("Unreachable B%" Pd "\n", block->block_id());
}
// Remove all uses in unreachable blocks.
- if (join != NULL) {
- for (PhiIterator it(join); !it.Done(); it.Advance()) {
- it.Current()->UnuseAllInputs();
- }
- }
- block->UnuseAllInputs();
- for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
- it.Current()->UnuseAllInputs();
- }
+ block->UnuseAllInstructions();
continue;
}
+ JoinEntryInstr* join = block->AsJoinEntry();
if (join != NULL) {
// Remove phi inputs corresponding to unreachable predecessor blocks.
// Predecessors will be recomputed (in block id order) after removing

Powered by Google App Engine
This is Rietveld 408576698