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

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

Issue 11234002: Enable redundancy elimination for array loads. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 1 month 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) 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/flow_graph_compiler.h" 10 #include "vm/flow_graph_compiler.h"
(...skipping 2456 matching lines...) Expand 10 before | Expand all | Expand 10 after
2467 TryHoistCheckSmiThroughPhi( 2467 TryHoistCheckSmiThroughPhi(
2468 &it, header, pre_header, current->AsCheckSmi()); 2468 &it, header, pre_header, current->AsCheckSmi());
2469 } 2469 }
2470 } 2470 }
2471 } 2471 }
2472 } 2472 }
2473 } 2473 }
2474 } 2474 }
2475 2475
2476 2476
2477 static bool IsLoadEliminationCandidate(Definition* def) {
2478 // Immutable loads (not affected by side effects) are handled
2479 // in the DominatorBasedCSE pass.
2480 // TODO(fschneider): Extend to other load instructions.
2481 return (def->IsLoadField() && def->AffectedBySideEffect())
2482 || def->IsLoadIndexed();
2483 }
2484
2485
2477 static intptr_t NumberLoadExpressions(FlowGraph* graph) { 2486 static intptr_t NumberLoadExpressions(FlowGraph* graph) {
2478 DirectChainedHashMap<Definition*> map; 2487 DirectChainedHashMap<Definition*> map;
2479 intptr_t expr_id = 0; 2488 intptr_t expr_id = 0;
2480 for (BlockIterator it = graph->reverse_postorder_iterator(); 2489 for (BlockIterator it = graph->reverse_postorder_iterator();
2481 !it.Done(); 2490 !it.Done();
2482 it.Advance()) { 2491 it.Advance()) {
2483 BlockEntryInstr* block = it.Current(); 2492 BlockEntryInstr* block = it.Current();
2484 for (ForwardInstructionIterator instr_it(block); 2493 for (ForwardInstructionIterator instr_it(block);
2485 !instr_it.Done(); 2494 !instr_it.Done();
2486 instr_it.Advance()) { 2495 instr_it.Advance()) {
2487 Definition* defn = instr_it.Current()->AsDefinition(); 2496 Definition* defn = instr_it.Current()->AsDefinition();
2488 if ((defn == NULL) || 2497 if ((defn == NULL) || !IsLoadEliminationCandidate(defn)) {
2489 !defn->IsLoadField() ||
2490 !defn->AffectedBySideEffect()) {
2491 // TODO(fschneider): Extend to other load instructions.
2492 continue; 2498 continue;
2493 } 2499 }
2494 Definition* result = map.Lookup(defn); 2500 Definition* result = map.Lookup(defn);
2495 if (result == NULL) { 2501 if (result == NULL) {
2496 map.Insert(defn); 2502 map.Insert(defn);
2497 defn->set_expr_id(expr_id++); 2503 defn->set_expr_id(expr_id++);
2498 } else { 2504 } else {
2499 defn->set_expr_id(result->expr_id()); 2505 defn->set_expr_id(result->expr_id());
2500 } 2506 }
2501 } 2507 }
(...skipping 24 matching lines...) Expand all
2526 intptr_t preorder_number = block->preorder_number(); 2532 intptr_t preorder_number = block->preorder_number();
2527 for (BackwardInstructionIterator instr_it(block); 2533 for (BackwardInstructionIterator instr_it(block);
2528 !instr_it.Done(); 2534 !instr_it.Done();
2529 instr_it.Advance()) { 2535 instr_it.Advance()) {
2530 Instruction* instr = instr_it.Current(); 2536 Instruction* instr = instr_it.Current();
2531 if (instr->HasSideEffect()) { 2537 if (instr->HasSideEffect()) {
2532 avail_kill[preorder_number]->SetAll(); 2538 avail_kill[preorder_number]->SetAll();
2533 break; 2539 break;
2534 } 2540 }
2535 Definition* defn = instr_it.Current()->AsDefinition(); 2541 Definition* defn = instr_it.Current()->AsDefinition();
2536 if ((defn == NULL) || 2542 if ((defn == NULL) || !IsLoadEliminationCandidate(defn)) {
2537 !defn->IsLoadField() ||
2538 !defn->AffectedBySideEffect()) {
2539 // TODO(fschneider): Extend to other load instructions.
2540 continue; 2543 continue;
2541 } 2544 }
2542 avail_gen[preorder_number]->Add(defn->expr_id()); 2545 avail_gen[preorder_number]->Add(defn->expr_id());
2543 } 2546 }
2544 avail_out[preorder_number]->CopyFrom(avail_gen[preorder_number]); 2547 avail_out[preorder_number]->CopyFrom(avail_gen[preorder_number]);
2545 } 2548 }
2546 2549
2547 BitVector* temp = new BitVector(avail_in[0]->length()); 2550 BitVector* temp = new BitVector(avail_in[0]->length());
2548 2551
2549 bool changed = true; 2552 bool changed = true;
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
2581 } 2584 }
2582 if (!temp->Equals(*block_in)) { 2585 if (!temp->Equals(*block_in)) {
2583 block_in->CopyFrom(temp); 2586 block_in->CopyFrom(temp);
2584 if (block_out->KillAndAdd(block_kill, block_gen)) changed = true; 2587 if (block_out->KillAndAdd(block_kill, block_gen)) changed = true;
2585 } 2588 }
2586 } 2589 }
2587 } 2590 }
2588 } 2591 }
2589 2592
2590 2593
2591 static void OptimizeLoads( 2594 static bool OptimizeLoads(
2592 BlockEntryInstr* block, 2595 BlockEntryInstr* block,
2593 GrowableArray<Definition*>* definitions, 2596 GrowableArray<Definition*>* definitions,
2594 const GrowableArray<BitVector*>& avail_in) { 2597 const GrowableArray<BitVector*>& avail_in) {
2595 // TODO(fschneider): Factor out code shared with the existing CSE pass. 2598 // TODO(fschneider): Factor out code shared with the existing CSE pass.
2596 2599
2597 // Delete loads that are killed (not available) at the entry. 2600 // Delete loads that are killed (not available) at the entry.
2598 intptr_t pre_num = block->preorder_number(); 2601 intptr_t pre_num = block->preorder_number();
2599 ASSERT(avail_in[pre_num]->length() == definitions->length()); 2602 ASSERT(avail_in[pre_num]->length() == definitions->length());
2600 for (intptr_t i = 0; i < avail_in[pre_num]->length(); i++) { 2603 for (intptr_t i = 0; i < avail_in[pre_num]->length(); i++) {
2601 if (!avail_in[pre_num]->Contains(i)) { 2604 if (!avail_in[pre_num]->Contains(i)) {
2602 (*definitions)[i] = NULL; 2605 (*definitions)[i] = NULL;
2603 } 2606 }
2604 } 2607 }
2605 2608
2609 bool changed = false;
2606 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { 2610 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
2607 Instruction* instr = it.Current(); 2611 Instruction* instr = it.Current();
2608 if (instr->HasSideEffect()) { 2612 if (instr->HasSideEffect()) {
2609 // Handle local side effects by clearing current definitions. 2613 // Handle local side effects by clearing current definitions.
2610 for (intptr_t i = 0; i < definitions->length(); i++) { 2614 for (intptr_t i = 0; i < definitions->length(); i++) {
2611 (*definitions)[i] = NULL; 2615 (*definitions)[i] = NULL;
2612 } 2616 }
2613 continue; 2617 continue;
2614 } 2618 }
2615 Definition* defn = instr->AsDefinition(); 2619 Definition* defn = instr->AsDefinition();
2616 if ((defn == NULL) || 2620 if ((defn == NULL) || !IsLoadEliminationCandidate(defn)) {
2617 !defn->IsLoadField() ||
2618 !defn->AffectedBySideEffect()) {
2619 // Immutable loads are handled in normal CSE.
2620 // TODO(fschneider): Extend to other load instructions.
2621 continue; 2621 continue;
2622 } 2622 }
2623 Definition* result = (*definitions)[defn->expr_id()]; 2623 Definition* result = (*definitions)[defn->expr_id()];
2624 if (result == NULL) { 2624 if (result == NULL) {
2625 (*definitions)[defn->expr_id()] = defn; 2625 (*definitions)[defn->expr_id()] = defn;
2626 continue; 2626 continue;
2627 } 2627 }
2628 2628
2629 // Replace current with lookup result. 2629 // Replace current with lookup result.
2630 defn->ReplaceUsesWith(result); 2630 defn->ReplaceUsesWith(result);
2631 it.RemoveCurrentFromGraph(); 2631 it.RemoveCurrentFromGraph();
2632 changed = true;
2632 if (FLAG_trace_optimization) { 2633 if (FLAG_trace_optimization) {
2633 OS::Print("Replacing load v%"Pd" with v%"Pd"\n", 2634 OS::Print("Replacing load v%"Pd" with v%"Pd"\n",
2634 defn->ssa_temp_index(), 2635 defn->ssa_temp_index(),
2635 result->ssa_temp_index()); 2636 result->ssa_temp_index());
2636 } 2637 }
2637 } 2638 }
2638 2639
2639 // Process children in the dominator tree recursively. 2640 // Process children in the dominator tree recursively.
2640 intptr_t num_children = block->dominated_blocks().length(); 2641 intptr_t num_children = block->dominated_blocks().length();
2641 for (intptr_t i = 0; i < num_children; ++i) { 2642 for (intptr_t i = 0; i < num_children; ++i) {
2642 BlockEntryInstr* child = block->dominated_blocks()[i]; 2643 BlockEntryInstr* child = block->dominated_blocks()[i];
2643 if (i < num_children - 1) { 2644 if (i < num_children - 1) {
2644 GrowableArray<Definition*> child_defs(definitions->length()); 2645 GrowableArray<Definition*> child_defs(definitions->length());
2645 child_defs.AddArray(*definitions); 2646 child_defs.AddArray(*definitions);
2646 OptimizeLoads(child, &child_defs, avail_in); 2647 changed = OptimizeLoads(child, &child_defs, avail_in) || changed;
2647 } else { 2648 } else {
2648 OptimizeLoads(child, definitions, avail_in); 2649 changed = OptimizeLoads(child, definitions, avail_in) || changed;
2649 } 2650 }
2650 } 2651 }
2652 return changed;
2651 } 2653 }
2652 2654
2653 2655
2654 void DominatorBasedCSE::Optimize(FlowGraph* graph) { 2656 bool DominatorBasedCSE::Optimize(FlowGraph* graph) {
2657 bool changed = false;
2655 if (FLAG_load_cse) { 2658 if (FLAG_load_cse) {
2656 intptr_t max_expr_id = NumberLoadExpressions(graph); 2659 intptr_t max_expr_id = NumberLoadExpressions(graph);
2657 if (max_expr_id > 0) { 2660 if (max_expr_id > 0) {
2658 intptr_t num_blocks = graph->preorder().length(); 2661 intptr_t num_blocks = graph->preorder().length();
2659 GrowableArray<BitVector*> avail_in(num_blocks); 2662 GrowableArray<BitVector*> avail_in(num_blocks);
2660 for (intptr_t i = 0; i < num_blocks; i++) { 2663 for (intptr_t i = 0; i < num_blocks; i++) {
2661 avail_in.Add(new BitVector(max_expr_id)); 2664 avail_in.Add(new BitVector(max_expr_id));
2662 } 2665 }
2663 2666
2664 ComputeAvailableLoads(graph, max_expr_id, avail_in); 2667 ComputeAvailableLoads(graph, max_expr_id, avail_in);
2665 2668
2666 GrowableArray<Definition*> definitions(max_expr_id); 2669 GrowableArray<Definition*> definitions(max_expr_id);
2667 for (intptr_t j = 0; j < max_expr_id ; j++) { 2670 for (intptr_t j = 0; j < max_expr_id ; j++) {
2668 definitions.Add(NULL); 2671 definitions.Add(NULL);
2669 } 2672 }
2670 2673 changed = OptimizeLoads(graph->graph_entry(), &definitions, avail_in);
2671 OptimizeLoads(graph->graph_entry(), &definitions, avail_in);
2672 } 2674 }
2673 } 2675 }
2674 2676
2675 DirectChainedHashMap<Instruction*> map; 2677 DirectChainedHashMap<Instruction*> map;
2676 OptimizeRecursive(graph->graph_entry(), &map); 2678 changed = OptimizeRecursive(graph->graph_entry(), &map) || changed;
2679
2680 return changed;
2677 } 2681 }
2678 2682
2679 2683
2680 void DominatorBasedCSE::OptimizeRecursive( 2684 bool DominatorBasedCSE::OptimizeRecursive(
2681 BlockEntryInstr* block, 2685 BlockEntryInstr* block,
2682 DirectChainedHashMap<Instruction*>* map) { 2686 DirectChainedHashMap<Instruction*>* map) {
2687 bool changed = false;
2683 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { 2688 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
2684 Instruction* current = it.Current(); 2689 Instruction* current = it.Current();
2685 if (current->AffectedBySideEffect()) continue; 2690 if (current->AffectedBySideEffect()) continue;
2686 Instruction* replacement = map->Lookup(current); 2691 Instruction* replacement = map->Lookup(current);
2687 if (replacement == NULL) { 2692 if (replacement == NULL) {
2688 map->Insert(current); 2693 map->Insert(current);
2689 continue; 2694 continue;
2690 } 2695 }
2691 // Replace current with lookup result. 2696 // Replace current with lookup result.
2692 ReplaceCurrentInstruction(&it, current, replacement); 2697 ReplaceCurrentInstruction(&it, current, replacement);
2698 changed = true;
2693 } 2699 }
2694 2700
2695 // Process children in the dominator tree recursively. 2701 // Process children in the dominator tree recursively.
2696 intptr_t num_children = block->dominated_blocks().length(); 2702 intptr_t num_children = block->dominated_blocks().length();
2697 for (intptr_t i = 0; i < num_children; ++i) { 2703 for (intptr_t i = 0; i < num_children; ++i) {
2698 BlockEntryInstr* child = block->dominated_blocks()[i]; 2704 BlockEntryInstr* child = block->dominated_blocks()[i];
2699 if (i < num_children - 1) { 2705 if (i < num_children - 1) {
2700 DirectChainedHashMap<Instruction*> child_map(*map); // Copy map. 2706 DirectChainedHashMap<Instruction*> child_map(*map); // Copy map.
2701 OptimizeRecursive(child, &child_map); 2707 changed = OptimizeRecursive(child, &child_map) || changed;
2702 } else { 2708 } else {
2703 OptimizeRecursive(child, map); // Reuse map for the last child. 2709 // Reuse map for the last child.
2710 changed = OptimizeRecursive(child, map) || changed;
2704 } 2711 }
2705 } 2712 }
2713 return changed;
2706 } 2714 }
2707 2715
2708 2716
2709 ConstantPropagator::ConstantPropagator( 2717 ConstantPropagator::ConstantPropagator(
2710 FlowGraph* graph, 2718 FlowGraph* graph,
2711 const GrowableArray<BlockEntryInstr*>& ignored) 2719 const GrowableArray<BlockEntryInstr*>& ignored)
2712 : FlowGraphVisitor(ignored), 2720 : FlowGraphVisitor(ignored),
2713 graph_(graph), 2721 graph_(graph),
2714 unknown_(Object::ZoneHandle(Object::transition_sentinel())), 2722 unknown_(Object::ZoneHandle(Object::transition_sentinel())),
2715 non_constant_(Object::ZoneHandle(Object::sentinel())), 2723 non_constant_(Object::ZoneHandle(Object::sentinel())),
(...skipping 747 matching lines...) Expand 10 before | Expand all | Expand 10 after
3463 3471
3464 if (FLAG_trace_constant_propagation) { 3472 if (FLAG_trace_constant_propagation) {
3465 OS::Print("\n==== After constant propagation ====\n"); 3473 OS::Print("\n==== After constant propagation ====\n");
3466 FlowGraphPrinter printer(*graph_); 3474 FlowGraphPrinter printer(*graph_);
3467 printer.PrintBlocks(); 3475 printer.PrintBlocks();
3468 } 3476 }
3469 } 3477 }
3470 3478
3471 3479
3472 } // namespace dart 3480 } // 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