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

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

Issue 11280232: Implement better side effect tracking for load-to-load forwarding. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years 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 | « no previous file | no next file » | 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 2758 matching lines...) Expand 10 before | Expand all | Expand 10 after
2769 2769
2770 static bool IsLoadEliminationCandidate(Definition* def) { 2770 static bool IsLoadEliminationCandidate(Definition* def) {
2771 // Immutable loads (not affected by side effects) are handled 2771 // Immutable loads (not affected by side effects) are handled
2772 // in the DominatorBasedCSE pass. 2772 // in the DominatorBasedCSE pass.
2773 // TODO(fschneider): Extend to other load instructions. 2773 // TODO(fschneider): Extend to other load instructions.
2774 return (def->IsLoadField() && def->AffectedBySideEffect()) 2774 return (def->IsLoadField() && def->AffectedBySideEffect())
2775 || def->IsLoadIndexed(); 2775 || def->IsLoadIndexed();
2776 } 2776 }
2777 2777
2778 2778
2779 static intptr_t NumberLoadExpressions(FlowGraph* graph) { 2779 static intptr_t ComputeLoadOffsetInWords(Definition* defn) {
2780 if (defn->IsLoadIndexed()) {
2781 // We are assuming that LoadField is never used to load the first word.
2782 return 0;
2783 }
2784
2785 LoadFieldInstr* load_field = defn->AsLoadField();
2786 if (load_field != NULL) {
2787 const intptr_t idx = load_field->offset_in_bytes() / kWordSize;
2788 ASSERT(idx > 0);
2789 return idx;
2790 }
2791
2792 UNREACHABLE();
2793 return 0;
2794 }
2795
2796
2797 static bool IsInterferingStore(Instruction* instr,
2798 intptr_t* offset_in_words) {
2799 if (instr->IsStoreIndexed()) {
2800 // We are assuming that LoadField is never used to load the first word.
2801 *offset_in_words = 0;
2802 return true;
2803 }
2804
2805 StoreInstanceFieldInstr* store_instance_field = instr->AsStoreInstanceField();
2806 if (store_instance_field != NULL) {
2807 ASSERT(store_instance_field->field().Offset() != 0);
2808 *offset_in_words = store_instance_field->field().Offset() / kWordSize;
2809 return true;
2810 }
2811
2812 StoreVMFieldInstr* store_vm_field = instr->AsStoreVMField();
2813 if (store_vm_field != NULL) {
2814 ASSERT(store_vm_field->offset_in_bytes() != 0);
2815 *offset_in_words = store_vm_field->offset_in_bytes() / kWordSize;
2816 return true;
2817 }
2818
2819 return false;
2820 }
2821
2822
2823 static intptr_t NumberLoadExpressions(
2824 FlowGraph* graph,
2825 GrowableArray<BitVector*>* kill_by_offs) {
2780 DirectChainedHashMap<PointerKeyValueTrait<Definition> > map; 2826 DirectChainedHashMap<PointerKeyValueTrait<Definition> > map;
2781 intptr_t expr_id = 0; 2827 intptr_t expr_id = 0;
2828
2829 // Loads representing different expression ids will be collected and
2830 // used to build per offset kill sets.
2831 GrowableArray<Definition*> loads(10);
2832
2782 for (BlockIterator it = graph->reverse_postorder_iterator(); 2833 for (BlockIterator it = graph->reverse_postorder_iterator();
2783 !it.Done(); 2834 !it.Done();
2784 it.Advance()) { 2835 it.Advance()) {
2785 BlockEntryInstr* block = it.Current(); 2836 BlockEntryInstr* block = it.Current();
2786 for (ForwardInstructionIterator instr_it(block); 2837 for (ForwardInstructionIterator instr_it(block);
2787 !instr_it.Done(); 2838 !instr_it.Done();
2788 instr_it.Advance()) { 2839 instr_it.Advance()) {
2789 Definition* defn = instr_it.Current()->AsDefinition(); 2840 Definition* defn = instr_it.Current()->AsDefinition();
2790 if ((defn == NULL) || !IsLoadEliminationCandidate(defn)) { 2841 if ((defn == NULL) || !IsLoadEliminationCandidate(defn)) {
2791 continue; 2842 continue;
2792 } 2843 }
2793 Definition* result = map.Lookup(defn); 2844 Definition* result = map.Lookup(defn);
2794 if (result == NULL) { 2845 if (result == NULL) {
2795 map.Insert(defn); 2846 map.Insert(defn);
2796 defn->set_expr_id(expr_id++); 2847 defn->set_expr_id(expr_id++);
2848 loads.Add(defn);
2797 } else { 2849 } else {
2798 defn->set_expr_id(result->expr_id()); 2850 defn->set_expr_id(result->expr_id());
2799 } 2851 }
2800 } 2852 }
2801 } 2853 }
2854
2855 // Build per offset kill sets. Any store interferes only with loads from
2856 // the same offset.
2857 for (intptr_t i = 0; i < loads.length(); i++) {
2858 Definition* defn = loads[i];
2859
2860 const intptr_t offset_in_words = ComputeLoadOffsetInWords(defn);
2861 while (kill_by_offs->length() <= offset_in_words) {
2862 kill_by_offs->Add(NULL);
2863 }
2864 if ((*kill_by_offs)[offset_in_words] == NULL) {
2865 (*kill_by_offs)[offset_in_words] = new BitVector(expr_id);
2866 }
2867 (*kill_by_offs)[offset_in_words]->Add(defn->expr_id());
2868 }
2869
2870
2802 return expr_id; 2871 return expr_id;
2803 } 2872 }
2804 2873
2805 2874
2806 static void ComputeAvailableLoads( 2875 static void ComputeAvailableLoads(
2807 FlowGraph* graph, 2876 FlowGraph* graph,
2808 intptr_t max_expr_id, 2877 intptr_t max_expr_id,
2809 const GrowableArray<BitVector*>& avail_in) { 2878 const GrowableArray<BitVector*>& avail_in,
2879 const GrowableArray<BitVector*>& kill_by_offs) {
2810 // Initialize gen-, kill-, out-sets. 2880 // Initialize gen-, kill-, out-sets.
2811 intptr_t num_blocks = graph->preorder().length(); 2881 intptr_t num_blocks = graph->preorder().length();
2812 GrowableArray<BitVector*> avail_out(num_blocks); 2882 GrowableArray<BitVector*> avail_out(num_blocks);
2813 GrowableArray<BitVector*> avail_gen(num_blocks); 2883 GrowableArray<BitVector*> avail_gen(num_blocks);
2814 GrowableArray<BitVector*> avail_kill(num_blocks); 2884 GrowableArray<BitVector*> avail_kill(num_blocks);
2815 for (intptr_t i = 0; i < num_blocks; i++) { 2885 for (intptr_t i = 0; i < num_blocks; i++) {
2816 avail_out.Add(new BitVector(max_expr_id)); 2886 avail_out.Add(new BitVector(max_expr_id));
2817 avail_gen.Add(new BitVector(max_expr_id)); 2887 avail_gen.Add(new BitVector(max_expr_id));
2818 avail_kill.Add(new BitVector(max_expr_id)); 2888 avail_kill.Add(new BitVector(max_expr_id));
2819 } 2889 }
2820 2890
2821 for (BlockIterator block_it = graph->reverse_postorder_iterator(); 2891 for (BlockIterator block_it = graph->reverse_postorder_iterator();
2822 !block_it.Done(); 2892 !block_it.Done();
2823 block_it.Advance()) { 2893 block_it.Advance()) {
2824 BlockEntryInstr* block = block_it.Current(); 2894 BlockEntryInstr* block = block_it.Current();
2825 intptr_t preorder_number = block->preorder_number(); 2895 intptr_t preorder_number = block->preorder_number();
2826 for (BackwardInstructionIterator instr_it(block); 2896 for (BackwardInstructionIterator instr_it(block);
2827 !instr_it.Done(); 2897 !instr_it.Done();
2828 instr_it.Advance()) { 2898 instr_it.Advance()) {
2829 Instruction* instr = instr_it.Current(); 2899 Instruction* instr = instr_it.Current();
2830 if (instr->HasSideEffect()) { 2900
2901 intptr_t offset_in_words = 0;
2902 if (IsInterferingStore(instr, &offset_in_words)) {
2903 if ((offset_in_words < kill_by_offs.length()) &&
2904 (kill_by_offs[offset_in_words] != NULL)) {
2905 avail_kill[preorder_number]->AddAll(kill_by_offs[offset_in_words]);
2906 }
2907 } else if (instr->HasSideEffect()) {
2831 avail_kill[preorder_number]->SetAll(); 2908 avail_kill[preorder_number]->SetAll();
2832 break; 2909 break;
2833 } 2910 }
2834 Definition* defn = instr_it.Current()->AsDefinition(); 2911 Definition* defn = instr_it.Current()->AsDefinition();
2835 if ((defn == NULL) || !IsLoadEliminationCandidate(defn)) { 2912 if ((defn == NULL) || !IsLoadEliminationCandidate(defn)) {
2836 continue; 2913 continue;
2837 } 2914 }
2838 avail_gen[preorder_number]->Add(defn->expr_id()); 2915
2916 const intptr_t expr_id = defn->expr_id();
2917 if (!avail_kill[preorder_number]->Contains(expr_id)) {
2918 avail_gen[preorder_number]->Add(expr_id);
2919 }
2839 } 2920 }
2840 avail_out[preorder_number]->CopyFrom(avail_gen[preorder_number]); 2921 avail_out[preorder_number]->CopyFrom(avail_gen[preorder_number]);
2841 } 2922 }
2842 2923
2843 BitVector* temp = new BitVector(avail_in[0]->length()); 2924 BitVector* temp = new BitVector(avail_in[0]->length());
2844 2925
2845 bool changed = true; 2926 bool changed = true;
2846 while (changed) { 2927 while (changed) {
2847 changed = false; 2928 changed = false;
2848 2929
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
2880 if (block_out->KillAndAdd(block_kill, block_gen)) changed = true; 2961 if (block_out->KillAndAdd(block_kill, block_gen)) changed = true;
2881 } 2962 }
2882 } 2963 }
2883 } 2964 }
2884 } 2965 }
2885 2966
2886 2967
2887 static bool OptimizeLoads( 2968 static bool OptimizeLoads(
2888 BlockEntryInstr* block, 2969 BlockEntryInstr* block,
2889 GrowableArray<Definition*>* definitions, 2970 GrowableArray<Definition*>* definitions,
2890 const GrowableArray<BitVector*>& avail_in) { 2971 const GrowableArray<BitVector*>& avail_in,
2972 const GrowableArray<BitVector*>& kill_by_offs) {
2891 // TODO(fschneider): Factor out code shared with the existing CSE pass. 2973 // TODO(fschneider): Factor out code shared with the existing CSE pass.
2892 2974
2893 // Delete loads that are killed (not available) at the entry. 2975 // Delete loads that are killed (not available) at the entry.
2894 intptr_t pre_num = block->preorder_number(); 2976 intptr_t pre_num = block->preorder_number();
2895 ASSERT(avail_in[pre_num]->length() == definitions->length()); 2977 ASSERT(avail_in[pre_num]->length() == definitions->length());
2896 for (intptr_t i = 0; i < avail_in[pre_num]->length(); i++) { 2978 for (intptr_t i = 0; i < avail_in[pre_num]->length(); i++) {
2897 if (!avail_in[pre_num]->Contains(i)) { 2979 if (!avail_in[pre_num]->Contains(i)) {
2898 (*definitions)[i] = NULL; 2980 (*definitions)[i] = NULL;
2899 } 2981 }
2900 } 2982 }
2901 2983
2902 bool changed = false; 2984 bool changed = false;
2903 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { 2985 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
2904 Instruction* instr = it.Current(); 2986 Instruction* instr = it.Current();
2905 if (instr->HasSideEffect()) { 2987
2988 intptr_t offset_in_words = 0;
2989 if (IsInterferingStore(instr, &offset_in_words)) {
2990 if ((offset_in_words < kill_by_offs.length()) &&
2991 (kill_by_offs[offset_in_words] != NULL)) {
2992 for (BitVector::Iterator it(kill_by_offs[offset_in_words]);
2993 !it.Done();
2994 it.Advance()) {
2995 (*definitions)[it.Current()] = NULL;
2996 }
2997 }
Florian Schneider 2012/11/29 13:42:48 Maybe continue already here since IsInterferingSto
2998 } else if (instr->HasSideEffect()) {
2906 // Handle local side effects by clearing current definitions. 2999 // Handle local side effects by clearing current definitions.
2907 for (intptr_t i = 0; i < definitions->length(); i++) { 3000 for (intptr_t i = 0; i < definitions->length(); i++) {
2908 (*definitions)[i] = NULL; 3001 (*definitions)[i] = NULL;
2909 } 3002 }
2910 continue; 3003 continue;
2911 } 3004 }
2912 Definition* defn = instr->AsDefinition(); 3005 Definition* defn = instr->AsDefinition();
2913 if ((defn == NULL) || !IsLoadEliminationCandidate(defn)) { 3006 if ((defn == NULL) || !IsLoadEliminationCandidate(defn)) {
2914 continue; 3007 continue;
2915 } 3008 }
(...skipping 14 matching lines...) Expand all
2930 } 3023 }
2931 } 3024 }
2932 3025
2933 // Process children in the dominator tree recursively. 3026 // Process children in the dominator tree recursively.
2934 intptr_t num_children = block->dominated_blocks().length(); 3027 intptr_t num_children = block->dominated_blocks().length();
2935 for (intptr_t i = 0; i < num_children; ++i) { 3028 for (intptr_t i = 0; i < num_children; ++i) {
2936 BlockEntryInstr* child = block->dominated_blocks()[i]; 3029 BlockEntryInstr* child = block->dominated_blocks()[i];
2937 if (i < num_children - 1) { 3030 if (i < num_children - 1) {
2938 GrowableArray<Definition*> child_defs(definitions->length()); 3031 GrowableArray<Definition*> child_defs(definitions->length());
2939 child_defs.AddArray(*definitions); 3032 child_defs.AddArray(*definitions);
2940 changed = OptimizeLoads(child, &child_defs, avail_in) || changed; 3033 changed = OptimizeLoads(child, &child_defs, avail_in, kill_by_offs) ||
3034 changed;
2941 } else { 3035 } else {
2942 changed = OptimizeLoads(child, definitions, avail_in) || changed; 3036 changed = OptimizeLoads(child, definitions, avail_in, kill_by_offs) ||
3037 changed;
2943 } 3038 }
2944 } 3039 }
2945 return changed; 3040 return changed;
2946 } 3041 }
2947 3042
2948 3043
2949 bool DominatorBasedCSE::Optimize(FlowGraph* graph) { 3044 bool DominatorBasedCSE::Optimize(FlowGraph* graph) {
2950 bool changed = false; 3045 bool changed = false;
2951 if (FLAG_load_cse) { 3046 if (FLAG_load_cse) {
2952 intptr_t max_expr_id = NumberLoadExpressions(graph); 3047 GrowableArray<BitVector*> kill_by_offs(10);
3048 intptr_t max_expr_id = NumberLoadExpressions(graph, &kill_by_offs);
2953 if (max_expr_id > 0) { 3049 if (max_expr_id > 0) {
2954 intptr_t num_blocks = graph->preorder().length(); 3050 intptr_t num_blocks = graph->preorder().length();
2955 GrowableArray<BitVector*> avail_in(num_blocks); 3051 GrowableArray<BitVector*> avail_in(num_blocks);
2956 for (intptr_t i = 0; i < num_blocks; i++) { 3052 for (intptr_t i = 0; i < num_blocks; i++) {
2957 avail_in.Add(new BitVector(max_expr_id)); 3053 avail_in.Add(new BitVector(max_expr_id));
2958 } 3054 }
2959 3055
2960 ComputeAvailableLoads(graph, max_expr_id, avail_in); 3056 ComputeAvailableLoads(graph, max_expr_id, avail_in, kill_by_offs);
2961 3057
2962 GrowableArray<Definition*> definitions(max_expr_id); 3058 GrowableArray<Definition*> definitions(max_expr_id);
2963 for (intptr_t j = 0; j < max_expr_id ; j++) { 3059 for (intptr_t j = 0; j < max_expr_id ; j++) {
2964 definitions.Add(NULL); 3060 definitions.Add(NULL);
2965 } 3061 }
2966 changed = OptimizeLoads(graph->graph_entry(), &definitions, avail_in); 3062 changed = OptimizeLoads(
3063 graph->graph_entry(), &definitions, avail_in, kill_by_offs);
2967 } 3064 }
2968 } 3065 }
2969 3066
2970 DirectChainedHashMap<PointerKeyValueTrait<Instruction> > map; 3067 DirectChainedHashMap<PointerKeyValueTrait<Instruction> > map;
2971 changed = OptimizeRecursive(graph->graph_entry(), &map) || changed; 3068 changed = OptimizeRecursive(graph->graph_entry(), &map) || changed;
2972 3069
2973 return changed; 3070 return changed;
2974 } 3071 }
2975 3072
2976 3073
(...skipping 824 matching lines...) Expand 10 before | Expand all | Expand 10 after
3801 3898
3802 if (FLAG_trace_constant_propagation) { 3899 if (FLAG_trace_constant_propagation) {
3803 OS::Print("\n==== After constant propagation ====\n"); 3900 OS::Print("\n==== After constant propagation ====\n");
3804 FlowGraphPrinter printer(*graph_); 3901 FlowGraphPrinter printer(*graph_);
3805 printer.PrintBlocks(); 3902 printer.PrintBlocks();
3806 } 3903 }
3807 } 3904 }
3808 3905
3809 3906
3810 } // namespace dart 3907 } // namespace dart
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698