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

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

Issue 10939036: A simpler scheme for garbage collection of ureachable phi inputs. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Fix bug when multiple predecessors are unreachable. Created 8 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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/flow_graph_builder.h" 9 #include "vm/flow_graph_builder.h"
10 #include "vm/hash_map.h" 10 #include "vm/hash_map.h"
(...skipping 2367 matching lines...) Expand 10 before | Expand all | Expand 10 after
2378 // instructions, previous pointers, predecessors, etc. after eliminating 2378 // instructions, previous pointers, predecessors, etc. after eliminating
2379 // unreachable code. We do not maintain those properties during the 2379 // unreachable code. We do not maintain those properties during the
2380 // transformation. 2380 // transformation.
2381 for (BlockIterator b = graph_->reverse_postorder_iterator(); 2381 for (BlockIterator b = graph_->reverse_postorder_iterator();
2382 !b.Done(); 2382 !b.Done();
2383 b.Advance()) { 2383 b.Advance()) {
2384 BlockEntryInstr* block = b.Current(); 2384 BlockEntryInstr* block = b.Current();
2385 if (!reachable_->Contains(block->preorder_number())) { 2385 if (!reachable_->Contains(block->preorder_number())) {
2386 continue; 2386 continue;
2387 } 2387 }
2388
2389 JoinEntryInstr* join = block->AsJoinEntry();
2390 if (join != NULL) {
2391 // Remove phi inputs corresponding to unreachable predecessor blocks.
2392 // Predecessors will be recomputed (in block id order) after removing
2393 // unreachable code so we merely have to keep the phi inputs in order.
2394 ZoneGrowableArray<PhiInstr*>* phis = join->phis();
2395 if (phis != NULL) {
2396 intptr_t pred_count = join->PredecessorCount();
2397 intptr_t live_count = 0;
2398 for (intptr_t pred_idx = 0; pred_idx < pred_count; ++pred_idx) {
2399 if (reachable_->Contains(
2400 join->PredecessorAt(pred_idx)->preorder_number())) {
2401 if (live_count < pred_idx) {
2402 for (intptr_t phi_idx = 0; phi_idx < phis->length(); ++phi_idx) {
2403 PhiInstr* phi = (*phis)[phi_idx];
2404 if (phi == NULL) continue;
2405 phi->inputs_[live_count] = phi->inputs_[pred_idx];
2406 }
2407 }
2408 ++live_count;
2409 }
2410 }
2411 if (live_count < pred_count) {
2412 for (intptr_t phi_idx = 0; phi_idx < phis->length(); ++phi_idx) {
2413 PhiInstr* phi = (*phis)[phi_idx];
2414 if (phi == NULL) continue;
2415 phi->inputs_.TruncateTo(live_count);
2416 }
2417 }
2418 }
2419 }
2420
2388 for (ForwardInstructionIterator i(block); !i.Done(); i.Advance()) { 2421 for (ForwardInstructionIterator i(block); !i.Done(); i.Advance()) {
2389 Definition* defn = i.Current()->AsDefinition(); 2422 Definition* defn = i.Current()->AsDefinition();
2390 BranchInstr* branch = i.Current()->AsBranch(); 2423 BranchInstr* branch = i.Current()->AsBranch();
2391 if (defn != NULL) { 2424 if (defn != NULL) {
2392 if (IsConstant(defn->constant_value())) { 2425 if (IsConstant(defn->constant_value())) {
2393 if (!defn->IsConstant() && 2426 if (!defn->IsConstant() &&
2394 !defn->IsPushArgument() && 2427 !defn->IsPushArgument() &&
2395 !defn->IsStoreLocal() && 2428 !defn->IsStoreLocal() &&
2396 !defn->IsStoreIndexed() && 2429 !defn->IsStoreIndexed() &&
2397 !defn->IsStoreInstanceField() && 2430 !defn->IsStoreInstanceField() &&
2398 !defn->IsStoreStaticField() && 2431 !defn->IsStoreStaticField() &&
2399 !defn->IsStoreVMField()) { 2432 !defn->IsStoreVMField()) {
2400 // TODO(kmillikin): propagate constants to replace instructions 2433 // TODO(kmillikin): propagate constants to replace instructions
2401 // without side effects. 2434 // without side effects.
2402 } 2435 }
2403 } 2436 }
2404 } else if (branch != NULL) { 2437 } else if (branch != NULL) {
2405 TargetEntryInstr* if_true = branch->true_successor(); 2438 TargetEntryInstr* if_true = branch->true_successor();
2406 TargetEntryInstr* if_false = branch->false_successor(); 2439 TargetEntryInstr* if_false = branch->false_successor();
2407 JoinEntryInstr* join = NULL; 2440 JoinEntryInstr* join = NULL;
2408 Instruction* next = NULL; 2441 Instruction* next = NULL;
2409 2442
2410 if (!reachable_->Contains(if_true->preorder_number())) { 2443 if (!reachable_->Contains(if_true->preorder_number())) {
2411 ASSERT(reachable_->Contains(if_false->preorder_number())); 2444 ASSERT(reachable_->Contains(if_false->preorder_number()));
2412 ASSERT(branch->comparison()->IsStrictCompare()); 2445 ASSERT(branch->comparison()->IsStrictCompare());
2413 ASSERT(if_false->parallel_move() == NULL); 2446 ASSERT(if_false->parallel_move() == NULL);
2414 ASSERT(if_false->loop_info() == NULL); 2447 ASSERT(if_false->loop_info() == NULL);
2415 join = new JoinEntryInstr(if_false->try_index()); 2448 join =
2449 new JoinEntryInstr(if_false->block_id(), if_false->try_index());
2416 next = if_false->next(); 2450 next = if_false->next();
2417 } else if (!reachable_->Contains(if_false->preorder_number())) { 2451 } else if (!reachable_->Contains(if_false->preorder_number())) {
2418 ASSERT(branch->comparison()->IsStrictCompare()); 2452 ASSERT(branch->comparison()->IsStrictCompare());
2419 ASSERT(if_true->parallel_move() == NULL); 2453 ASSERT(if_true->parallel_move() == NULL);
2420 ASSERT(if_true->loop_info() == NULL); 2454 ASSERT(if_true->loop_info() == NULL);
2421 join = new JoinEntryInstr(if_true->try_index()); 2455 join = new JoinEntryInstr(if_true->block_id(), if_true->try_index());
2422 next = if_true->next(); 2456 next = if_true->next();
2423 } 2457 }
2424 2458
2425 if (join != NULL) { 2459 if (join != NULL) {
2426 // Replace the branch with a jump to the reachable successor. 2460 // Replace the branch with a jump to the reachable successor.
2427 // Drop the comparison, which does not have side effects as long 2461 // Drop the comparison, which does not have side effects as long
2428 // as it is a strict compare (the only one we can determine is 2462 // as it is a strict compare (the only one we can determine is
2429 // constant with the current analysis). 2463 // constant with the current analysis).
2430 GotoInstr* jump = new GotoInstr(join); 2464 GotoInstr* jump = new GotoInstr(join);
2431 // Removing the branch from the graph will leave the iterator in a 2465 // Removing the branch from the graph will leave the iterator in a
2432 // state where current is detached from the graph. Since current 2466 // state where current is detached from the graph. Since current
2433 // has no successors and neither does its replacement, that's 2467 // has no successors and neither does its replacement, that's
2434 // safe. 2468 // safe.
2435 Instruction* previous = branch->previous(); 2469 Instruction* previous = branch->previous();
2436 branch->set_previous(NULL); 2470 branch->set_previous(NULL);
2437 previous->set_next(jump); 2471 previous->set_next(jump);
2438 // Replace the false target entry with the new join entry. We will 2472 // Replace the false target entry with the new join entry. We will
2439 // recompute the dominators after this pass. 2473 // recompute the dominators after this pass.
2440 join->set_next(next); 2474 join->set_next(next);
2441 } 2475 }
2442 } 2476 }
2443 } 2477 }
2444 } 2478 }
2445 graph_->DiscoverBlocks(); 2479 graph_->DiscoverBlocks();
2446 GrowableArray<BitVector*> dominance_frontier; 2480 GrowableArray<BitVector*> dominance_frontier;
2447 graph_->ComputeDominators(&dominance_frontier); 2481 graph_->ComputeDominators(&dominance_frontier);
2448
2449 // Garbage collect phi inputs corresponding to unreachable predecessors.
2450 // This is required because we assume that predecessor and phi indexes
2451 // align. Note that this does not necessarily eliminate all useless phis
2452 // (e.g., it does not eliminate phis that were originally inserted solely
2453 // due to an assignment on the now-unreachable path).
2454 for (BlockIterator it = graph_->reverse_postorder_iterator();
2455 !it.Done();
2456 it.Advance()) {
2457 JoinEntryInstr* join = it.Current()->AsJoinEntry();
2458 if (join != NULL) join->EliminateUnreachablePhiInputs();
2459 }
2460
2461 graph_->ComputeUseLists(); 2482 graph_->ComputeUseLists();
2462 } 2483 }
2463 2484
2464 2485
2465 } // namespace dart 2486 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698