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

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

Issue 11568011: Implement store 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 2811 matching lines...) Expand 10 before | Expand all | Expand 10 after
2822 if (store_vm_field != NULL) { 2822 if (store_vm_field != NULL) {
2823 ASSERT(store_vm_field->offset_in_bytes() != 0); 2823 ASSERT(store_vm_field->offset_in_bytes() != 0);
2824 *offset_in_words = store_vm_field->offset_in_bytes() / kWordSize; 2824 *offset_in_words = store_vm_field->offset_in_bytes() / kWordSize;
2825 return true; 2825 return true;
2826 } 2826 }
2827 2827
2828 return false; 2828 return false;
2829 } 2829 }
2830 2830
2831 2831
2832 static Definition* GetStoredValue(Instruction* instr) {
2833 if (instr->IsStoreIndexed()) {
2834 return instr->AsStoreIndexed()->value()->definition();
2835 }
2836
2837 StoreInstanceFieldInstr* store_instance_field = instr->AsStoreInstanceField();
2838 if (store_instance_field != NULL) {
2839 return store_instance_field->value()->definition();
2840 }
2841
2842 StoreVMFieldInstr* store_vm_field = instr->AsStoreVMField();
2843 if (store_vm_field != NULL) {
2844 return store_vm_field->value()->definition();
2845 }
2846
2847 UNREACHABLE(); // Should only be called for supported store instructions.
2848 return NULL;
2849 }
2850
2851
2852 // KeyValueTrait used for numbering of loads. Allows to lookup loads
2853 // corresponding to stores.
2854 class LoadKeyValueTrait {
2855 public:
2856 typedef Definition* Value;
2857 typedef Definition* Key;
2858 typedef Definition* Pair;
2859
2860 static Key KeyOf(Pair kv) {
2861 return kv;
2862 }
2863
2864 static Value ValueOf(Pair kv) {
2865 return kv;
2866 }
2867
2868 static inline intptr_t Hashcode(Key key) {
2869 intptr_t object = 0;
2870 intptr_t location = 0;
2871
2872 if (key->IsLoadIndexed()) {
2873 LoadIndexedInstr* load_indexed = key->AsLoadIndexed();
2874 object = load_indexed->array()->definition()->ssa_temp_index();
2875 location = load_indexed->index()->definition()->ssa_temp_index();
2876 } else if (key->IsStoreIndexed()) {
2877 StoreIndexedInstr* store_indexed = key->AsStoreIndexed();
2878 object = store_indexed->array()->definition()->ssa_temp_index();
2879 location = store_indexed->index()->definition()->ssa_temp_index();
2880 } else if (key->IsLoadField()) {
2881 LoadFieldInstr* load_field = key->AsLoadField();
2882 object = load_field->value()->definition()->ssa_temp_index();
2883 location = load_field->offset_in_bytes();
2884 } else if (key->IsStoreInstanceField()) {
2885 StoreInstanceFieldInstr* store_field = key->AsStoreInstanceField();
2886 object = store_field->instance()->definition()->ssa_temp_index();
2887 location = store_field->field().Offset();
2888 } else if (key->IsStoreVMField()) {
2889 StoreVMFieldInstr* store_field = key->AsStoreVMField();
2890 object = store_field->dest()->definition()->ssa_temp_index();
2891 location = store_field->offset_in_bytes();
2892 }
2893
2894 return object * 31 + location;
2895 }
2896
2897 static inline bool IsKeyEqual(Pair kv, Key key) {
2898 if (kv->Equals(key)) return true;
2899
2900 if (kv->IsLoadIndexed()) {
2901 if (key->IsStoreIndexed()) {
2902 LoadIndexedInstr* load_indexed = kv->AsLoadIndexed();
2903 StoreIndexedInstr* store_indexed = key->AsStoreIndexed();
2904 return load_indexed->array()->Equals(store_indexed->array()) &&
2905 load_indexed->index()->Equals(store_indexed->index());
2906 }
2907 return false;
2908 }
2909
2910 ASSERT(kv->IsLoadField());
2911 LoadFieldInstr* load_field = kv->AsLoadField();
2912 if (key->IsStoreVMField()) {
2913 StoreVMFieldInstr* store_field = key->AsStoreVMField();
2914 return load_field->value()->Equals(store_field->dest()) &&
2915 (load_field->offset_in_bytes() == store_field->offset_in_bytes());
2916 } else if (key->IsStoreInstanceField()) {
2917 StoreInstanceFieldInstr* store_field = key->AsStoreInstanceField();
2918 return load_field->value()->Equals(store_field->instance()) &&
2919 (load_field->offset_in_bytes() == store_field->field().Offset());
2920 }
2921
2922 return false;
2923 }
2924 };
2925
2926
2832 static intptr_t NumberLoadExpressions( 2927 static intptr_t NumberLoadExpressions(
2833 FlowGraph* graph, 2928 FlowGraph* graph,
2929 DirectChainedHashMap<LoadKeyValueTrait>* map,
2834 GrowableArray<BitVector*>* kill_by_offs) { 2930 GrowableArray<BitVector*>* kill_by_offs) {
2835 DirectChainedHashMap<PointerKeyValueTrait<Definition> > map;
2836 intptr_t expr_id = 0; 2931 intptr_t expr_id = 0;
2837 2932
2838 // Loads representing different expression ids will be collected and 2933 // Loads representing different expression ids will be collected and
2839 // used to build per offset kill sets. 2934 // used to build per offset kill sets.
2840 GrowableArray<Definition*> loads(10); 2935 GrowableArray<Definition*> loads(10);
2841 2936
2842 for (BlockIterator it = graph->reverse_postorder_iterator(); 2937 for (BlockIterator it = graph->reverse_postorder_iterator();
2843 !it.Done(); 2938 !it.Done();
2844 it.Advance()) { 2939 it.Advance()) {
2845 BlockEntryInstr* block = it.Current(); 2940 BlockEntryInstr* block = it.Current();
2846 for (ForwardInstructionIterator instr_it(block); 2941 for (ForwardInstructionIterator instr_it(block);
2847 !instr_it.Done(); 2942 !instr_it.Done();
2848 instr_it.Advance()) { 2943 instr_it.Advance()) {
2849 Definition* defn = instr_it.Current()->AsDefinition(); 2944 Definition* defn = instr_it.Current()->AsDefinition();
2850 if ((defn == NULL) || !IsLoadEliminationCandidate(defn)) { 2945 if ((defn == NULL) || !IsLoadEliminationCandidate(defn)) {
2851 continue; 2946 continue;
2852 } 2947 }
2853 Definition* result = map.Lookup(defn); 2948 Definition* result = map->Lookup(defn);
2854 if (result == NULL) { 2949 if (result == NULL) {
2855 map.Insert(defn); 2950 map->Insert(defn);
2856 defn->set_expr_id(expr_id++); 2951 defn->set_expr_id(expr_id++);
2857 loads.Add(defn); 2952 loads.Add(defn);
2858 } else { 2953 } else {
2859 defn->set_expr_id(result->expr_id()); 2954 defn->set_expr_id(result->expr_id());
2860 } 2955 }
2861 } 2956 }
2862 } 2957 }
2863 2958
2864 // Build per offset kill sets. Any store interferes only with loads from 2959 // Build per offset kill sets. Any store interferes only with loads from
2865 // the same offset. 2960 // the same offset.
2866 for (intptr_t i = 0; i < loads.length(); i++) { 2961 for (intptr_t i = 0; i < loads.length(); i++) {
2867 Definition* defn = loads[i]; 2962 Definition* defn = loads[i];
2868 2963
2869 const intptr_t offset_in_words = ComputeLoadOffsetInWords(defn); 2964 const intptr_t offset_in_words = ComputeLoadOffsetInWords(defn);
2870 while (kill_by_offs->length() <= offset_in_words) { 2965 while (kill_by_offs->length() <= offset_in_words) {
2871 kill_by_offs->Add(NULL); 2966 kill_by_offs->Add(NULL);
2872 } 2967 }
2873 if ((*kill_by_offs)[offset_in_words] == NULL) { 2968 if ((*kill_by_offs)[offset_in_words] == NULL) {
2874 (*kill_by_offs)[offset_in_words] = new BitVector(expr_id); 2969 (*kill_by_offs)[offset_in_words] = new BitVector(expr_id);
2875 } 2970 }
2876 (*kill_by_offs)[offset_in_words]->Add(defn->expr_id()); 2971 (*kill_by_offs)[offset_in_words]->Add(defn->expr_id());
2877 } 2972 }
2878 2973
2879
2880 return expr_id; 2974 return expr_id;
2881 } 2975 }
2882 2976
2883 2977
2884 class LoadOptimizer : public ValueObject { 2978 class LoadOptimizer : public ValueObject {
2885 public: 2979 public:
2886 LoadOptimizer(FlowGraph* graph, 2980 LoadOptimizer(FlowGraph* graph,
2887 intptr_t max_expr_id, 2981 intptr_t max_expr_id,
2982 DirectChainedHashMap<LoadKeyValueTrait>* map,
2888 const GrowableArray<BitVector*>& kill_by_offset) 2983 const GrowableArray<BitVector*>& kill_by_offset)
2889 : graph_(graph), 2984 : graph_(graph),
2985 map_(map),
2890 max_expr_id_(max_expr_id), 2986 max_expr_id_(max_expr_id),
2891 kill_by_offset_(kill_by_offset), 2987 kill_by_offset_(kill_by_offset),
2892 in_(graph_->preorder().length()), 2988 in_(graph_->preorder().length()),
2893 out_(graph_->preorder().length()), 2989 out_(graph_->preorder().length()),
2894 gen_(graph_->preorder().length()), 2990 gen_(graph_->preorder().length()),
2895 kill_(graph_->preorder().length()), 2991 kill_(graph_->preorder().length()),
2896 exposed_values_(graph_->preorder().length()), 2992 exposed_values_(graph_->preorder().length()),
2897 out_values_(graph_->preorder().length()), 2993 out_values_(graph_->preorder().length()),
2898 phis_(5), 2994 phis_(5),
2899 worklist_(5), 2995 worklist_(5),
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
2945 intptr_t offset_in_words = 0; 3041 intptr_t offset_in_words = 0;
2946 if (IsInterferingStore(instr, &offset_in_words)) { 3042 if (IsInterferingStore(instr, &offset_in_words)) {
2947 // Interfering stores kill only loads from the same offset. 3043 // Interfering stores kill only loads from the same offset.
2948 if ((offset_in_words < kill_by_offset_.length()) && 3044 if ((offset_in_words < kill_by_offset_.length()) &&
2949 (kill_by_offset_[offset_in_words] != NULL)) { 3045 (kill_by_offset_[offset_in_words] != NULL)) {
2950 kill->AddAll(kill_by_offset_[offset_in_words]); 3046 kill->AddAll(kill_by_offset_[offset_in_words]);
2951 // There is no need to clear out_values when clearing GEN set 3047 // There is no need to clear out_values when clearing GEN set
2952 // because only those values that are in the GEN set 3048 // because only those values that are in the GEN set
2953 // will ever be used. 3049 // will ever be used.
2954 gen->RemoveAll(kill_by_offset_[offset_in_words]); 3050 gen->RemoveAll(kill_by_offset_[offset_in_words]);
3051
3052 Definition* load = map_->Lookup(instr->AsDefinition());
3053 if (load != NULL) {
3054 // Store has a corresponding numbered load. Try forwarding
3055 // stored value to it.
3056 gen->Add(load->expr_id());
3057 if (out_values == NULL) out_values = CreateBlockOutValues();
3058 (*out_values)[load->expr_id()] = GetStoredValue(instr);
3059 }
2955 } 3060 }
2956 ASSERT(instr->IsDefinition() && 3061 ASSERT(instr->IsDefinition() &&
2957 !IsLoadEliminationCandidate(instr->AsDefinition())); 3062 !IsLoadEliminationCandidate(instr->AsDefinition()));
2958 continue; 3063 continue;
2959 } 3064 }
2960 3065
2961 // Other instructions with side effects kill all loads. 3066 // Other instructions with side effects kill all loads.
2962 if (instr->HasSideEffect()) { 3067 if (instr->HasSideEffect()) {
2963 kill->SetAll(); 3068 kill->SetAll();
2964 // There is no need to clear out_values when clearing GEN set 3069 // There is no need to clear out_values when clearing GEN set
(...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after
3267 ZoneGrowableArray<Definition*>* CreateBlockOutValues() { 3372 ZoneGrowableArray<Definition*>* CreateBlockOutValues() {
3268 ZoneGrowableArray<Definition*>* out = 3373 ZoneGrowableArray<Definition*>* out =
3269 new ZoneGrowableArray<Definition*>(max_expr_id_); 3374 new ZoneGrowableArray<Definition*>(max_expr_id_);
3270 for (intptr_t i = 0; i < max_expr_id_; i++) { 3375 for (intptr_t i = 0; i < max_expr_id_; i++) {
3271 out->Add(NULL); 3376 out->Add(NULL);
3272 } 3377 }
3273 return out; 3378 return out;
3274 } 3379 }
3275 3380
3276 FlowGraph* graph_; 3381 FlowGraph* graph_;
3382 DirectChainedHashMap<LoadKeyValueTrait>* map_;
3277 const intptr_t max_expr_id_; 3383 const intptr_t max_expr_id_;
3278 3384
3279 // Mapping between field offsets in words and expression ids of loads from 3385 // Mapping between field offsets in words and expression ids of loads from
3280 // that offset. 3386 // that offset.
3281 const GrowableArray<BitVector*>& kill_by_offset_; 3387 const GrowableArray<BitVector*>& kill_by_offset_;
3282 3388
3283 // Per block sets of expression ids for loads that are: incoming (available 3389 // Per block sets of expression ids for loads that are: incoming (available
3284 // on the entry), outgoing (available on the exit), generated and killed. 3390 // on the entry), outgoing (available on the exit), generated and killed.
3285 GrowableArray<BitVector*> in_; 3391 GrowableArray<BitVector*> in_;
3286 GrowableArray<BitVector*> out_; 3392 GrowableArray<BitVector*> out_;
(...skipping 17 matching lines...) Expand all
3304 BitVector* in_worklist_; 3410 BitVector* in_worklist_;
3305 3411
3306 DISALLOW_COPY_AND_ASSIGN(LoadOptimizer); 3412 DISALLOW_COPY_AND_ASSIGN(LoadOptimizer);
3307 }; 3413 };
3308 3414
3309 3415
3310 bool DominatorBasedCSE::Optimize(FlowGraph* graph) { 3416 bool DominatorBasedCSE::Optimize(FlowGraph* graph) {
3311 bool changed = false; 3417 bool changed = false;
3312 if (FLAG_load_cse) { 3418 if (FLAG_load_cse) {
3313 GrowableArray<BitVector*> kill_by_offs(10); 3419 GrowableArray<BitVector*> kill_by_offs(10);
3314 const intptr_t max_expr_id = NumberLoadExpressions(graph, &kill_by_offs); 3420 DirectChainedHashMap<LoadKeyValueTrait> map;
3421 const intptr_t max_expr_id =
3422 NumberLoadExpressions(graph, &map, &kill_by_offs);
3315 if (max_expr_id > 0) { 3423 if (max_expr_id > 0) {
3316 LoadOptimizer load_optimizer(graph, max_expr_id, kill_by_offs); 3424 LoadOptimizer load_optimizer(graph, max_expr_id, &map, kill_by_offs);
3317 load_optimizer.Optimize(); 3425 load_optimizer.Optimize();
3318 } 3426 }
3319 } 3427 }
3320 3428
3321 DirectChainedHashMap<PointerKeyValueTrait<Instruction> > map; 3429 DirectChainedHashMap<PointerKeyValueTrait<Instruction> > map;
3322 changed = OptimizeRecursive(graph->graph_entry(), &map) || changed; 3430 changed = OptimizeRecursive(graph->graph_entry(), &map) || changed;
3323 3431
3324 return changed; 3432 return changed;
3325 } 3433 }
3326 3434
(...skipping 834 matching lines...) Expand 10 before | Expand all | Expand 10 after
4161 4269
4162 if (FLAG_trace_constant_propagation) { 4270 if (FLAG_trace_constant_propagation) {
4163 OS::Print("\n==== After constant propagation ====\n"); 4271 OS::Print("\n==== After constant propagation ====\n");
4164 FlowGraphPrinter printer(*graph_); 4272 FlowGraphPrinter printer(*graph_);
4165 printer.PrintBlocks(); 4273 printer.PrintBlocks();
4166 } 4274 }
4167 } 4275 }
4168 4276
4169 4277
4170 } // namespace dart 4278 } // 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