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

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

Issue 10832180: Eliminate phis that do not reach any non-environment uses. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: address Kevin's comment Created 8 years, 4 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_builder.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) 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_builder.h" 5 #include "vm/flow_graph_builder.h"
6 6
7 #include "vm/ast_printer.h" 7 #include "vm/ast_printer.h"
8 #include "vm/bit_vector.h" 8 #include "vm/bit_vector.h"
9 #include "vm/code_descriptors.h" 9 #include "vm/code_descriptors.h"
10 #include "vm/dart_entry.h" 10 #include "vm/dart_entry.h"
(...skipping 2324 matching lines...) Expand 10 before | Expand all | Expand 10 after
2335 } 2335 }
2336 } 2336 }
2337 } 2337 }
2338 2338
2339 if (for_optimized && use_ssa) { 2339 if (for_optimized && use_ssa) {
2340 GrowableArray<BitVector*> dominance_frontier; 2340 GrowableArray<BitVector*> dominance_frontier;
2341 ComputeDominators(&preorder_block_entries_, &parent, &dominance_frontier); 2341 ComputeDominators(&preorder_block_entries_, &parent, &dominance_frontier);
2342 InsertPhis(preorder_block_entries_, 2342 InsertPhis(preorder_block_entries_,
2343 assigned_vars, 2343 assigned_vars,
2344 dominance_frontier); 2344 dominance_frontier);
2345 Rename(); 2345
2346 GrowableArray<PhiInstr*> live_phis;
2347
2348 // Rename uses to reference inserted phis where appropriate.
2349 // Collect phis that reach a non-environment use.
2350 Rename(&live_phis);
2351
2352 // Propagate alive mark transitively from alive phis.
2353 MarkLivePhis(&live_phis);
2346 } 2354 }
2347 if (FLAG_print_flow_graph || (Dart::flow_graph_writer() != NULL)) { 2355 if (FLAG_print_flow_graph || (Dart::flow_graph_writer() != NULL)) {
2348 intptr_t length = postorder_block_entries_.length(); 2356 intptr_t length = postorder_block_entries_.length();
2349 GrowableArray<BlockEntryInstr*> reverse_postorder(length); 2357 GrowableArray<BlockEntryInstr*> reverse_postorder(length);
2350 for (intptr_t i = length - 1; i >= 0; --i) { 2358 for (intptr_t i = length - 1; i >= 0; --i) {
2351 reverse_postorder.Add(postorder_block_entries_[i]); 2359 reverse_postorder.Add(postorder_block_entries_[i]);
2352 } 2360 }
2353 if (FLAG_print_flow_graph) { 2361 if (FLAG_print_flow_graph) {
2354 // Print flow graph to stdout. 2362 // Print flow graph to stdout.
2355 FlowGraphPrinter printer(function, reverse_postorder); 2363 FlowGraphPrinter printer(function, reverse_postorder);
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after
2536 work[index] = var_index; 2544 work[index] = var_index;
2537 worklist.Add(block); 2545 worklist.Add(block);
2538 } 2546 }
2539 } 2547 }
2540 } 2548 }
2541 } 2549 }
2542 } 2550 }
2543 } 2551 }
2544 2552
2545 2553
2546 void FlowGraphBuilder::Rename() { 2554 void FlowGraphBuilder::Rename(GrowableArray<PhiInstr*>* live_phis) {
2547 // TODO(fschneider): Support catch-entry. 2555 // TODO(fschneider): Support catch-entry.
2548 if (graph_entry_->SuccessorCount() > 1) { 2556 if (graph_entry_->SuccessorCount() > 1) {
2549 Bailout("Catch-entry support in SSA."); 2557 Bailout("Catch-entry support in SSA.");
2550 } 2558 }
2551 2559
2552 // Initialize start environment. 2560 // Initialize start environment.
2553 GrowableArray<Value*> start_env(variable_count()); 2561 GrowableArray<Value*> start_env(variable_count());
2554 for (intptr_t i = 0; i < parameter_count(); ++i) { 2562 for (intptr_t i = 0; i < parameter_count(); ++i) {
2555 ParameterInstr* param = new ParameterInstr(i); 2563 ParameterInstr* param = new ParameterInstr(i);
2556 param->set_ssa_temp_index(alloc_ssa_temp_index()); // New SSA temp. 2564 param->set_ssa_temp_index(alloc_ssa_temp_index()); // New SSA temp.
2557 start_env.Add(new UseVal(param)); 2565 start_env.Add(new UseVal(param));
2558 } 2566 }
2559 2567
2560 // All locals are initialized with #null. 2568 // All locals are initialized with #null.
2561 Value* null_value = new ConstantVal(Object::ZoneHandle()); 2569 Value* null_value = new ConstantVal(Object::ZoneHandle());
2562 while (start_env.length() < variable_count()) { 2570 while (start_env.length() < variable_count()) {
2563 start_env.Add(null_value); 2571 start_env.Add(null_value);
2564 } 2572 }
2565 graph_entry_->set_start_env( 2573 graph_entry_->set_start_env(
2566 new Environment(start_env, non_copied_parameter_count_)); 2574 new Environment(start_env, non_copied_parameter_count_));
2567 2575
2568 BlockEntryInstr* normal_entry = graph_entry_->SuccessorAt(0); 2576 BlockEntryInstr* normal_entry = graph_entry_->SuccessorAt(0);
2569 ASSERT(normal_entry != NULL); // Must have entry. 2577 ASSERT(normal_entry != NULL); // Must have entry.
2570 GrowableArray<Value*> env(variable_count()); 2578 GrowableArray<Value*> env(variable_count());
2571 env.AddArray(start_env); 2579 env.AddArray(start_env);
2572 RenameRecursive(normal_entry, &env); 2580 RenameRecursive(normal_entry, &env, live_phis);
2573 } 2581 }
2574 2582
2575 2583
2576 // Helper to a copy a value iff it is a UseVal. 2584 // Helper to a copy a value iff it is a UseVal.
2577 static Value* CopyValue(Value* value) { 2585 static Value* CopyValue(Value* value) {
2578 return value->IsUse() 2586 return value->IsUse()
2579 ? new UseVal(value->AsUse()->definition()) 2587 ? new UseVal(value->AsUse()->definition())
2580 : value; 2588 : value;
2581 } 2589 }
2582 2590
2583 2591
2584 void FlowGraphBuilder::RenameRecursive(BlockEntryInstr* block_entry, 2592 void FlowGraphBuilder::RenameRecursive(BlockEntryInstr* block_entry,
2585 GrowableArray<Value*>* env) { 2593 GrowableArray<Value*>* env,
2594 GrowableArray<PhiInstr*>* live_phis) {
2586 // 1. Process phis first. 2595 // 1. Process phis first.
2587 if (block_entry->IsJoinEntry()) { 2596 if (block_entry->IsJoinEntry()) {
2588 JoinEntryInstr* join = block_entry->AsJoinEntry(); 2597 JoinEntryInstr* join = block_entry->AsJoinEntry();
2589 if (join->phis() != NULL) { 2598 if (join->phis() != NULL) {
2590 for (intptr_t i = 0; i < join->phis()->length(); ++i) { 2599 for (intptr_t i = 0; i < join->phis()->length(); ++i) {
2591 PhiInstr* phi = (*join->phis())[i]; 2600 PhiInstr* phi = (*join->phis())[i];
2592 if (phi != NULL) { 2601 if (phi != NULL) {
2593 (*env)[i] = new UseVal(phi); 2602 (*env)[i] = new UseVal(phi);
2594 phi->set_ssa_temp_index(alloc_ssa_temp_index()); // New SSA temp. 2603 phi->set_ssa_temp_index(alloc_ssa_temp_index()); // New SSA temp.
2595 } 2604 }
2596 } 2605 }
2597 } 2606 }
2598 } 2607 }
2599 2608
2600 // 2. Process normal instructions. 2609 // 2. Process normal instructions.
2601 for (ForwardInstructionIterator it(block_entry); !it.Done(); it.Advance()) { 2610 for (ForwardInstructionIterator it(block_entry); !it.Done(); it.Advance()) {
2602 Instruction* current = it.Current(); 2611 Instruction* current = it.Current();
2603 // Attach current environment to the instruction. First, each instruction 2612 // Attach current environment to the instruction. First, each instruction
2604 // gets a full copy of the environment. Later we optimize this by 2613 // gets a full copy of the environment. Later we optimize this by
2605 // eliminating unnecessary environments. 2614 // eliminating unnecessary environments.
2606 current->set_env(new Environment(*env, non_copied_parameter_count_)); 2615 current->set_env(new Environment(*env, non_copied_parameter_count_));
2607 2616
2608 // 2a. Handle uses: 2617 // 2a. Handle uses:
2609 // Update expression stack environment for each use. 2618 // Update expression stack environment for each use.
2610 // For each use of a LoadLocal or StoreLocal: Replace it with the value 2619 // For each use of a LoadLocal or StoreLocal: Replace it with the value
2611 // from the environment. 2620 // from the environment.
2612 for (intptr_t i = 0; i < current->InputCount(); ++i) { 2621 for (intptr_t i = current->InputCount() - 1; i >= 0; --i) {
2613 Value* v = current->InputAt(i); 2622 Value* v = current->InputAt(i);
2614 if (!v->IsUse()) continue; 2623 if (!v->IsUse()) continue;
2615 // Update expression stack. 2624 // Update expression stack.
2616 ASSERT(env->length() > variable_count()); 2625 ASSERT(env->length() > variable_count());
2626
2627 Value* input_value = env->Last();
2628 ASSERT(input_value->IsUse());
2617 env->RemoveLast(); 2629 env->RemoveLast();
2630
2618 BindInstr* as_bind = v->AsUse()->definition()->AsBind(); 2631 BindInstr* as_bind = v->AsUse()->definition()->AsBind();
2619 if ((as_bind != NULL) && as_bind->computation()->IsLoadLocal()) { 2632 if ((as_bind != NULL) &&
2620 Computation* comp = as_bind->computation(); 2633 (as_bind->computation()->IsLoadLocal() ||
2621 intptr_t index = comp->AsLoadLocal()->local().BitIndexIn( 2634 as_bind->computation()->IsStoreLocal())) {
2622 non_copied_parameter_count_); 2635 current->SetInputAt(i, CopyValue(input_value));
2623 current->SetInputAt(i, CopyValue((*env)[index]));
2624 }
2625 if ((as_bind != NULL) && as_bind->computation()->IsStoreLocal()) {
2626 // For each use of a StoreLocal: Replace it with the value from the
2627 // environment.
2628 Computation* comp = as_bind->computation();
2629 intptr_t index = comp->AsStoreLocal()->local().BitIndexIn(
2630 non_copied_parameter_count_);
2631 current->SetInputAt(i, CopyValue((*env)[index]));
2632 } 2636 }
2633 } 2637 }
2634 2638
2635 // Drop pushed arguments for calls. 2639 // Drop pushed arguments for calls.
2636 for (intptr_t j = 0; j < current->ArgumentCount(); j++) { 2640 for (intptr_t j = 0; j < current->ArgumentCount(); j++) {
2637 env->RemoveLast(); 2641 env->RemoveLast();
2638 } 2642 }
2639 2643
2640 // 2b. Handle LoadLocal and StoreLocal. 2644 // 2b. Handle LoadLocal and StoreLocal.
2641 // For each LoadLocal: Remove it from the graph. 2645 // For each LoadLocal: Remove it from the graph.
2642 // For each StoreLocal: Remove it from the graph and update the environment. 2646 // For each StoreLocal: Remove it from the graph and update the environment.
2643 BindInstr* bind = current->AsBind(); 2647 BindInstr* bind = current->AsBind();
2644 if (bind != NULL) { 2648 if (bind != NULL) {
2645 LoadLocalComp* load = bind->computation()->AsLoadLocal(); 2649 LoadLocalComp* load = bind->computation()->AsLoadLocal();
2646 StoreLocalComp* store = bind->computation()->AsStoreLocal(); 2650 StoreLocalComp* store = bind->computation()->AsStoreLocal();
2647 if ((load != NULL) || (store != NULL)) { 2651 if ((load != NULL) || (store != NULL)) {
2648 intptr_t index; 2652 intptr_t index;
2649 if (store != NULL) { 2653 if (store != NULL) {
2650 index = store->local().BitIndexIn(non_copied_parameter_count_); 2654 index = store->local().BitIndexIn(non_copied_parameter_count_);
2651 // Update renaming environment. 2655 // Update renaming environment.
2652 (*env)[index] = store->value(); 2656 (*env)[index] = store->value();
2653 } else { 2657 } else {
2654 // The graph construction ensures we do not have an unused LoadLocal 2658 // The graph construction ensures we do not have an unused LoadLocal
2655 // computation. 2659 // computation.
2656 ASSERT(bind->is_used()); 2660 ASSERT(bind->is_used());
2657 index = load->local().BitIndexIn(non_copied_parameter_count_); 2661 index = load->local().BitIndexIn(non_copied_parameter_count_);
2662
2663 Value* value = (*env)[index];
2664 if (value->IsUse()) {
2665 PhiInstr* phi = value->AsUse()->definition()->AsPhi();
2666 if ((phi != NULL) && !phi->is_alive()) {
2667 phi->mark_alive();
2668 live_phis->Add(phi);
2669 }
2670 }
2658 } 2671 }
2659 // Update expression stack and remove from graph. 2672 // Update expression stack and remove from graph.
2660 if (bind->is_used()) { 2673 if (bind->is_used()) {
2661 env->Add(CopyValue((*env)[index])); 2674 env->Add(CopyValue((*env)[index]));
2662 } 2675 }
2663 it.RemoveCurrentFromGraph(); 2676 it.RemoveCurrentFromGraph();
2664 } else { 2677 } else {
2665 // Not a load or store. 2678 // Not a load or store.
2666 if (bind->is_used()) { 2679 if (bind->is_used()) {
2667 // Assign fresh SSA temporary and update expression stack. 2680 // Assign fresh SSA temporary and update expression stack.
2668 bind->set_ssa_temp_index(alloc_ssa_temp_index()); 2681 bind->set_ssa_temp_index(alloc_ssa_temp_index());
2669 env->Add(new UseVal(bind)); 2682 env->Add(new UseVal(bind));
2670 } 2683 }
2671 } 2684 }
2672 } 2685 }
2673 2686
2674 // 2c. Handle pushed argument. 2687 // 2c. Handle pushed argument.
2675 PushArgumentInstr* push = current->AsPushArgument(); 2688 PushArgumentInstr* push = current->AsPushArgument();
2676 if (push != NULL) { 2689 if (push != NULL) {
2677 env->Add(push->value()); 2690 env->Add(push->value());
2678 } 2691 }
2679 } 2692 }
2680 2693
2681 // 3. Process dominated blocks. 2694 // 3. Process dominated blocks.
2682 for (intptr_t i = 0; i < block_entry->dominated_blocks().length(); ++i) { 2695 for (intptr_t i = 0; i < block_entry->dominated_blocks().length(); ++i) {
2683 BlockEntryInstr* block = block_entry->dominated_blocks()[i]; 2696 BlockEntryInstr* block = block_entry->dominated_blocks()[i];
2684 GrowableArray<Value*> new_env(env->length()); 2697 GrowableArray<Value*> new_env(env->length());
2685 new_env.AddArray(*env); 2698 new_env.AddArray(*env);
2686 RenameRecursive(block, &new_env); 2699 RenameRecursive(block, &new_env, live_phis);
2687 } 2700 }
2688 2701
2689 // 4. Process successor block. We have edge-split form, so that only blocks 2702 // 4. Process successor block. We have edge-split form, so that only blocks
2690 // with one successor can have a join block as successor. 2703 // with one successor can have a join block as successor.
2691 if ((block_entry->last_instruction()->SuccessorCount() == 1) && 2704 if ((block_entry->last_instruction()->SuccessorCount() == 1) &&
2692 block_entry->last_instruction()->SuccessorAt(0)->IsJoinEntry()) { 2705 block_entry->last_instruction()->SuccessorAt(0)->IsJoinEntry()) {
2693 JoinEntryInstr* successor = 2706 JoinEntryInstr* successor =
2694 block_entry->last_instruction()->SuccessorAt(0)->AsJoinEntry(); 2707 block_entry->last_instruction()->SuccessorAt(0)->AsJoinEntry();
2695 intptr_t pred_index = successor->IndexOfPredecessor(block_entry); 2708 intptr_t pred_index = successor->IndexOfPredecessor(block_entry);
2696 ASSERT(pred_index >= 0); 2709 ASSERT(pred_index >= 0);
2697 if (successor->phis() != NULL) { 2710 if (successor->phis() != NULL) {
2698 for (intptr_t i = 0; i < successor->phis()->length(); ++i) { 2711 for (intptr_t i = 0; i < successor->phis()->length(); ++i) {
2699 PhiInstr* phi = (*successor->phis())[i]; 2712 PhiInstr* phi = (*successor->phis())[i];
2700 if (phi != NULL) { 2713 if (phi != NULL) {
2701 // Rename input operand and make a copy if it is a UseVal. 2714 // Rename input operand and make a copy if it is a UseVal.
2702 Value* new_val = (*env)[i]->IsUse() 2715 Value* new_val = (*env)[i]->IsUse()
2703 ? new UseVal((*env)[i]->AsUse()->definition()) 2716 ? new UseVal((*env)[i]->AsUse()->definition())
2704 : (*env)[i]; 2717 : (*env)[i];
2705 phi->SetInputAt(pred_index, new_val); 2718 phi->SetInputAt(pred_index, new_val);
2706 } 2719 }
2707 } 2720 }
2708 } 2721 }
2709 } 2722 }
2710 } 2723 }
2711 2724
2712 2725
2726 void FlowGraphBuilder::MarkLivePhis(GrowableArray<PhiInstr*>* live_phis) {
2727 while (!live_phis->is_empty()) {
2728 PhiInstr* phi = live_phis->Last();
2729 live_phis->RemoveLast();
2730 for (intptr_t i = 0; i < phi->InputCount(); i++) {
2731 Value* val = phi->InputAt(i);
2732 if (!val->IsUse()) continue;
2733 PhiInstr* used_phi = val->AsUse()->definition()->AsPhi();
2734 if ((used_phi != NULL) && !used_phi->is_alive()) {
2735 used_phi->mark_alive();
2736 live_phis->Add(used_phi);
2737 }
2738 }
2739 }
2740 }
2741
2713 void FlowGraphBuilder::Bailout(const char* reason) { 2742 void FlowGraphBuilder::Bailout(const char* reason) {
2714 const char* kFormat = "FlowGraphBuilder Bailout: %s %s"; 2743 const char* kFormat = "FlowGraphBuilder Bailout: %s %s";
2715 const char* function_name = parsed_function_.function().ToCString(); 2744 const char* function_name = parsed_function_.function().ToCString();
2716 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1; 2745 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1;
2717 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len); 2746 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
2718 OS::SNPrint(chars, len, kFormat, function_name, reason); 2747 OS::SNPrint(chars, len, kFormat, function_name, reason);
2719 const Error& error = Error::Handle( 2748 const Error& error = Error::Handle(
2720 LanguageError::New(String::Handle(String::New(chars)))); 2749 LanguageError::New(String::Handle(String::New(chars))));
2721 Isolate::Current()->long_jump_base()->Jump(1, error); 2750 Isolate::Current()->long_jump_base()->Jump(1, error);
2722 } 2751 }
2723 2752
2724 2753
2725 } // namespace dart 2754 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_builder.h ('k') | runtime/vm/intermediate_language.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698