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

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

Issue 10956013: Reapply "A simpler scheme for garbage collection of ureachable phi inputs." (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: 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 1910 matching lines...) Expand 10 before | Expand all | Expand 10 after
1921 } 1921 }
1922 1922
1923 1923
1924 void ConstantPropagator::VisitGoto(GotoInstr* instr) { 1924 void ConstantPropagator::VisitGoto(GotoInstr* instr) {
1925 SetReachable(instr->successor()); 1925 SetReachable(instr->successor());
1926 } 1926 }
1927 1927
1928 1928
1929 void ConstantPropagator::VisitBranch(BranchInstr* instr) { 1929 void ConstantPropagator::VisitBranch(BranchInstr* instr) {
1930 instr->comparison()->Accept(this); 1930 instr->comparison()->Accept(this);
1931 const Object& value = instr->comparison()->constant_value(); 1931
1932 if (IsNonConstant(value)) { 1932 // The successors may be reachable, but only if this instruction is. (We
Kevin Millikin (Google) 2012/09/20 13:48:17 And look here.
1933 SetReachable(instr->true_successor()); 1933 // might be analyzing it because the constant value of one of its inputs
1934 SetReachable(instr->false_successor()); 1934 // has changed.)
1935 } else if (value.raw() == Bool::True()) { 1935 BlockEntryInstr* entry = NULL;
Vyacheslav Egorov (Google) 2012/09/21 14:48:05 ->GetBlock() instead of custom loop
1936 SetReachable(instr->true_successor()); 1936 Instruction* prev = instr->previous();
1937 } else if (!IsUnknown(value)) { // Any other constant. 1937 while ((entry = prev->AsBlockEntry()) == NULL) {
1938 SetReachable(instr->false_successor()); 1938 prev = prev->previous();
1939 }
1940 if (reachable_->Contains(entry->preorder_number())) {
1941 const Object& value = instr->comparison()->constant_value();
1942 if (IsNonConstant(value)) {
1943 SetReachable(instr->true_successor());
1944 SetReachable(instr->false_successor());
1945 } else if (value.raw() == Bool::True()) {
1946 SetReachable(instr->true_successor());
1947 } else if (!IsUnknown(value)) { // Any other constant.
1948 SetReachable(instr->false_successor());
1949 }
1939 } 1950 }
1940 } 1951 }
1941 1952
1942 1953
1943 // -------------------------------------------------------------------------- 1954 // --------------------------------------------------------------------------
1944 // Analysis of definitions. Compute the constant value. If it has changed 1955 // Analysis of definitions. Compute the constant value. If it has changed
1945 // and the definition has input uses, add the definition to the definition 1956 // and the definition has input uses, add the definition to the definition
1946 // worklist so that the used can be processed. 1957 // worklist so that the used can be processed.
1947 void ConstantPropagator::VisitPhi(PhiInstr* instr) { 1958 void ConstantPropagator::VisitPhi(PhiInstr* instr) {
1948 // Compute the join over all the reachable predecessor values. 1959 // Compute the join over all the reachable predecessor values.
(...skipping 428 matching lines...) Expand 10 before | Expand all | Expand 10 after
2377 // instructions, previous pointers, predecessors, etc. after eliminating 2388 // instructions, previous pointers, predecessors, etc. after eliminating
2378 // unreachable code. We do not maintain those properties during the 2389 // unreachable code. We do not maintain those properties during the
2379 // transformation. 2390 // transformation.
2380 for (BlockIterator b = graph_->reverse_postorder_iterator(); 2391 for (BlockIterator b = graph_->reverse_postorder_iterator();
2381 !b.Done(); 2392 !b.Done();
2382 b.Advance()) { 2393 b.Advance()) {
2383 BlockEntryInstr* block = b.Current(); 2394 BlockEntryInstr* block = b.Current();
2384 if (!reachable_->Contains(block->preorder_number())) { 2395 if (!reachable_->Contains(block->preorder_number())) {
2385 continue; 2396 continue;
2386 } 2397 }
2398
2399 JoinEntryInstr* join = block->AsJoinEntry();
2400 if (join != NULL) {
2401 // Remove phi inputs corresponding to unreachable predecessor blocks.
2402 // Predecessors will be recomputed (in block id order) after removing
2403 // unreachable code so we merely have to keep the phi inputs in order.
2404 ZoneGrowableArray<PhiInstr*>* phis = join->phis();
2405 if (phis != NULL) {
2406 intptr_t pred_count = join->PredecessorCount();
2407 intptr_t live_count = 0;
2408 for (intptr_t pred_idx = 0; pred_idx < pred_count; ++pred_idx) {
2409 if (reachable_->Contains(
2410 join->PredecessorAt(pred_idx)->preorder_number())) {
2411 if (live_count < pred_idx) {
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_[live_count] = phi->inputs_[pred_idx];
2416 }
2417 }
2418 ++live_count;
2419 }
2420 }
2421 if (live_count < pred_count) {
2422 for (intptr_t phi_idx = 0; phi_idx < phis->length(); ++phi_idx) {
2423 PhiInstr* phi = (*phis)[phi_idx];
2424 if (phi == NULL) continue;
2425 phi->inputs_.TruncateTo(live_count);
2426 }
2427 }
2428 }
2429 }
2430
2387 for (ForwardInstructionIterator i(block); !i.Done(); i.Advance()) { 2431 for (ForwardInstructionIterator i(block); !i.Done(); i.Advance()) {
2388 Definition* defn = i.Current()->AsDefinition(); 2432 Definition* defn = i.Current()->AsDefinition();
2389 BranchInstr* branch = i.Current()->AsBranch(); 2433 BranchInstr* branch = i.Current()->AsBranch();
2390 if (defn != NULL) { 2434 if (defn != NULL) {
2391 if (IsConstant(defn->constant_value())) { 2435 if (IsConstant(defn->constant_value())) {
2392 if (!defn->IsConstant() && 2436 if (!defn->IsConstant() &&
2393 !defn->IsPushArgument() && 2437 !defn->IsPushArgument() &&
2394 !defn->IsStoreLocal() && 2438 !defn->IsStoreLocal() &&
2395 !defn->IsStoreIndexed() && 2439 !defn->IsStoreIndexed() &&
2396 !defn->IsStoreInstanceField() && 2440 !defn->IsStoreInstanceField() &&
2397 !defn->IsStoreStaticField() && 2441 !defn->IsStoreStaticField() &&
2398 !defn->IsStoreVMField()) { 2442 !defn->IsStoreVMField()) {
2399 // TODO(kmillikin): propagate constants to replace instructions 2443 // TODO(kmillikin): propagate constants to replace instructions
2400 // without side effects. 2444 // without side effects.
2401 } 2445 }
2402 } 2446 }
2403 } else if (branch != NULL) { 2447 } else if (branch != NULL) {
2404 TargetEntryInstr* if_true = branch->true_successor(); 2448 TargetEntryInstr* if_true = branch->true_successor();
2405 TargetEntryInstr* if_false = branch->false_successor(); 2449 TargetEntryInstr* if_false = branch->false_successor();
2406 JoinEntryInstr* join = NULL; 2450 JoinEntryInstr* join = NULL;
2407 Instruction* next = NULL; 2451 Instruction* next = NULL;
2408 2452
2409 if (!reachable_->Contains(if_true->preorder_number())) { 2453 if (!reachable_->Contains(if_true->preorder_number())) {
2410 ASSERT(reachable_->Contains(if_false->preorder_number())); 2454 ASSERT(reachable_->Contains(if_false->preorder_number()));
2411 ASSERT(branch->comparison()->IsStrictCompare()); 2455 ASSERT(branch->comparison()->IsStrictCompare());
2412 ASSERT(if_false->parallel_move() == NULL); 2456 ASSERT(if_false->parallel_move() == NULL);
2413 ASSERT(if_false->loop_info() == NULL); 2457 ASSERT(if_false->loop_info() == NULL);
2414 join = new JoinEntryInstr(if_false->try_index()); 2458 join =
2459 new JoinEntryInstr(if_false->block_id(), if_false->try_index());
2415 next = if_false->next(); 2460 next = if_false->next();
2416 } else if (!reachable_->Contains(if_false->preorder_number())) { 2461 } else if (!reachable_->Contains(if_false->preorder_number())) {
2417 ASSERT(branch->comparison()->IsStrictCompare()); 2462 ASSERT(branch->comparison()->IsStrictCompare());
2418 ASSERT(if_true->parallel_move() == NULL); 2463 ASSERT(if_true->parallel_move() == NULL);
2419 ASSERT(if_true->loop_info() == NULL); 2464 ASSERT(if_true->loop_info() == NULL);
2420 join = new JoinEntryInstr(if_true->try_index()); 2465 join = new JoinEntryInstr(if_true->block_id(), if_true->try_index());
2421 next = if_true->next(); 2466 next = if_true->next();
2422 } 2467 }
2423 2468
2424 if (join != NULL) { 2469 if (join != NULL) {
2425 // Replace the branch with a jump to the reachable successor. 2470 // Replace the branch with a jump to the reachable successor.
2426 // Drop the comparison, which does not have side effects as long 2471 // Drop the comparison, which does not have side effects as long
2427 // as it is a strict compare (the only one we can determine is 2472 // as it is a strict compare (the only one we can determine is
2428 // constant with the current analysis). 2473 // constant with the current analysis).
2429 GotoInstr* jump = new GotoInstr(join); 2474 GotoInstr* jump = new GotoInstr(join);
2430 // Removing the branch from the graph will leave the iterator in a 2475 // Removing the branch from the graph will leave the iterator in a
2431 // state where current is detached from the graph. Since current 2476 // state where current is detached from the graph. Since current
2432 // has no successors and neither does its replacement, that's 2477 // has no successors and neither does its replacement, that's
2433 // safe. 2478 // safe.
2434 Instruction* previous = branch->previous(); 2479 Instruction* previous = branch->previous();
2435 branch->set_previous(NULL); 2480 branch->set_previous(NULL);
2436 previous->set_next(jump); 2481 previous->set_next(jump);
2437 // Replace the false target entry with the new join entry. We will 2482 // Replace the false target entry with the new join entry. We will
2438 // recompute the dominators after this pass. 2483 // recompute the dominators after this pass.
2439 join->set_next(next); 2484 join->set_next(next);
2440 } 2485 }
2441 } 2486 }
2442 } 2487 }
2443 } 2488 }
2444 graph_->DiscoverBlocks(); 2489 graph_->DiscoverBlocks();
2445 GrowableArray<BitVector*> dominance_frontier; 2490 GrowableArray<BitVector*> dominance_frontier;
2446 graph_->ComputeDominators(&dominance_frontier); 2491 graph_->ComputeDominators(&dominance_frontier);
2447
2448 // Garbage collect phi inputs corresponding to unreachable predecessors.
2449 // This is required because we assume that predecessor and phi indexes
2450 // align. Note that this does not necessarily eliminate all useless phis
2451 // (e.g., it does not eliminate phis that were originally inserted solely
2452 // due to an assignment on the now-unreachable path).
2453 for (BlockIterator it = graph_->reverse_postorder_iterator();
2454 !it.Done();
2455 it.Advance()) {
2456 JoinEntryInstr* join = it.Current()->AsJoinEntry();
2457 if (join != NULL) join->EliminateUnreachablePhiInputs();
2458 }
2459
2460 graph_->ComputeUseLists(); 2492 graph_->ComputeUseLists();
2461 } 2493 }
2462 2494
2463 2495
2464 } // namespace dart 2496 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698