| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 3328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3339 // Host CheckSmi instruction and make this phi smi one. | 3339 // Host CheckSmi instruction and make this phi smi one. |
| 3340 Hoist(it, pre_header, current); | 3340 Hoist(it, pre_header, current); |
| 3341 | 3341 |
| 3342 // Replace value we are checking with phi's input. | 3342 // Replace value we are checking with phi's input. |
| 3343 current->value()->BindTo(phi->InputAt(non_smi_input)->definition()); | 3343 current->value()->BindTo(phi->InputAt(non_smi_input)->definition()); |
| 3344 | 3344 |
| 3345 phi->UpdateType(CompileType::FromCid(kSmiCid)); | 3345 phi->UpdateType(CompileType::FromCid(kSmiCid)); |
| 3346 } | 3346 } |
| 3347 | 3347 |
| 3348 | 3348 |
| 3349 static bool IsLoopInvariantLoad(ZoneGrowableArray<BitVector*>* sets, |
| 3350 intptr_t loop_header_index, |
| 3351 Instruction* instr) { |
| 3352 return (sets != NULL) && |
| 3353 instr->HasExprId() && |
| 3354 ((*sets)[loop_header_index] != NULL) && |
| 3355 (*sets)[loop_header_index]->Contains(instr->expr_id()); |
| 3356 } |
| 3357 |
| 3358 |
| 3349 void LICM::Optimize() { | 3359 void LICM::Optimize() { |
| 3350 GrowableArray<BlockEntryInstr*> loop_headers; | 3360 const ZoneGrowableArray<BlockEntryInstr*>& loop_headers = |
| 3351 flow_graph()->ComputeLoops(&loop_headers); | 3361 flow_graph()->loop_headers(); |
| 3362 |
| 3363 ZoneGrowableArray<BitVector*>* loop_invariant_loads = |
| 3364 flow_graph()->loop_invariant_loads(); |
| 3365 |
| 3366 BlockEffects* block_effects = flow_graph()->block_effects(); |
| 3352 | 3367 |
| 3353 for (intptr_t i = 0; i < loop_headers.length(); ++i) { | 3368 for (intptr_t i = 0; i < loop_headers.length(); ++i) { |
| 3354 BlockEntryInstr* header = loop_headers[i]; | 3369 BlockEntryInstr* header = loop_headers[i]; |
| 3355 // Skip loop that don't have a pre-header block. | 3370 // Skip loop that don't have a pre-header block. |
| 3356 BlockEntryInstr* pre_header = FindPreHeader(header); | 3371 BlockEntryInstr* pre_header = FindPreHeader(header); |
| 3357 if (pre_header == NULL) continue; | 3372 if (pre_header == NULL) continue; |
| 3358 | 3373 |
| 3359 for (BitVector::Iterator loop_it(header->loop_info()); | 3374 for (BitVector::Iterator loop_it(header->loop_info()); |
| 3360 !loop_it.Done(); | 3375 !loop_it.Done(); |
| 3361 loop_it.Advance()) { | 3376 loop_it.Advance()) { |
| 3362 BlockEntryInstr* block = flow_graph()->preorder()[loop_it.Current()]; | 3377 BlockEntryInstr* block = flow_graph()->preorder()[loop_it.Current()]; |
| 3363 for (ForwardInstructionIterator it(block); | 3378 for (ForwardInstructionIterator it(block); |
| 3364 !it.Done(); | 3379 !it.Done(); |
| 3365 it.Advance()) { | 3380 it.Advance()) { |
| 3366 Instruction* current = it.Current(); | 3381 Instruction* current = it.Current(); |
| 3367 if (current->AllowsCSE() && | 3382 if ((current->AllowsCSE() && |
| 3368 flow_graph()->block_effects()->CanBeMovedTo(current, pre_header)) { | 3383 block_effects->CanBeMovedTo(current, pre_header)) || |
| 3384 IsLoopInvariantLoad(loop_invariant_loads, i, current)) { |
| 3369 bool inputs_loop_invariant = true; | 3385 bool inputs_loop_invariant = true; |
| 3370 for (int i = 0; i < current->InputCount(); ++i) { | 3386 for (int i = 0; i < current->InputCount(); ++i) { |
| 3371 Definition* input_def = current->InputAt(i)->definition(); | 3387 Definition* input_def = current->InputAt(i)->definition(); |
| 3372 if (!input_def->GetBlock()->Dominates(pre_header)) { | 3388 if (!input_def->GetBlock()->Dominates(pre_header)) { |
| 3373 inputs_loop_invariant = false; | 3389 inputs_loop_invariant = false; |
| 3374 break; | 3390 break; |
| 3375 } | 3391 } |
| 3376 } | 3392 } |
| 3377 if (inputs_loop_invariant && | 3393 if (inputs_loop_invariant && |
| 3378 !current->IsAssertAssignable() && | 3394 !current->IsAssertAssignable() && |
| (...skipping 505 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3884 continue; | 3900 continue; |
| 3885 } | 3901 } |
| 3886 Definition* result = map->Lookup(defn); | 3902 Definition* result = map->Lookup(defn); |
| 3887 if (result == NULL) { | 3903 if (result == NULL) { |
| 3888 map->Insert(defn); | 3904 map->Insert(defn); |
| 3889 defn->set_expr_id(expr_id++); | 3905 defn->set_expr_id(expr_id++); |
| 3890 loads.Add(defn); | 3906 loads.Add(defn); |
| 3891 } else { | 3907 } else { |
| 3892 defn->set_expr_id(result->expr_id()); | 3908 defn->set_expr_id(result->expr_id()); |
| 3893 } | 3909 } |
| 3910 |
| 3911 if (FLAG_trace_optimization) { |
| 3912 OS::Print("load v%"Pd" is numbered as %"Pd"\n", |
| 3913 defn->ssa_temp_index(), |
| 3914 defn->expr_id()); |
| 3915 } |
| 3894 } | 3916 } |
| 3895 } | 3917 } |
| 3896 | 3918 |
| 3897 // Build aliasing sets mapping aliases to loads. | 3919 // Build aliasing sets mapping aliases to loads. |
| 3898 AliasedSet* aliased_set = new AliasedSet(expr_id); | 3920 AliasedSet* aliased_set = new AliasedSet(expr_id); |
| 3899 for (intptr_t i = 0; i < loads.length(); i++) { | 3921 for (intptr_t i = 0; i < loads.length(); i++) { |
| 3900 Definition* defn = loads[i]; | 3922 Definition* defn = loads[i]; |
| 3901 aliased_set->AddRepresentative(defn); | 3923 aliased_set->AddRepresentative(defn); |
| 3902 } | 3924 } |
| 3903 return aliased_set; | 3925 return aliased_set; |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3949 LoadOptimizer load_optimizer(graph, aliased_set, &map); | 3971 LoadOptimizer load_optimizer(graph, aliased_set, &map); |
| 3950 return load_optimizer.Optimize(); | 3972 return load_optimizer.Optimize(); |
| 3951 } | 3973 } |
| 3952 return false; | 3974 return false; |
| 3953 } | 3975 } |
| 3954 | 3976 |
| 3955 private: | 3977 private: |
| 3956 bool Optimize() { | 3978 bool Optimize() { |
| 3957 ComputeInitialSets(); | 3979 ComputeInitialSets(); |
| 3958 ComputeOutValues(); | 3980 ComputeOutValues(); |
| 3981 if (graph_->is_licm_allowed()) { |
| 3982 MarkLoopInvariantLoads(); |
| 3983 } |
| 3959 ForwardLoads(); | 3984 ForwardLoads(); |
| 3960 EmitPhis(); | 3985 EmitPhis(); |
| 3961 return forwarded_; | 3986 return forwarded_; |
| 3962 } | 3987 } |
| 3963 | 3988 |
| 3964 // Compute sets of loads generated and killed by each block. | 3989 // Compute sets of loads generated and killed by each block. |
| 3965 // Additionally compute upwards exposed and generated loads for each block. | 3990 // Additionally compute upwards exposed and generated loads for each block. |
| 3966 // Exposed loads are those that can be replaced if a corresponding | 3991 // Exposed loads are those that can be replaced if a corresponding |
| 3967 // reaching load will be found. | 3992 // reaching load will be found. |
| 3968 // Loads that are locally redundant will be replaced as we go through | 3993 // Loads that are locally redundant will be replaced as we go through |
| (...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4204 block_in->Print(); | 4229 block_in->Print(); |
| 4205 block_out->Print(); | 4230 block_out->Print(); |
| 4206 block_kill->Print(); | 4231 block_kill->Print(); |
| 4207 block_gen->Print(); | 4232 block_gen->Print(); |
| 4208 OS::Print("\n"); | 4233 OS::Print("\n"); |
| 4209 } | 4234 } |
| 4210 } | 4235 } |
| 4211 } | 4236 } |
| 4212 } | 4237 } |
| 4213 | 4238 |
| 4239 void MarkLoopInvariantLoads() { |
| 4240 const ZoneGrowableArray<BlockEntryInstr*>& loop_headers = |
| 4241 graph_->loop_headers(); |
| 4242 |
| 4243 ZoneGrowableArray<BitVector*>* invariant_loads = |
| 4244 new ZoneGrowableArray<BitVector*>(loop_headers.length()); |
| 4245 |
| 4246 for (intptr_t i = 0; i < loop_headers.length(); i++) { |
| 4247 BlockEntryInstr* header = loop_headers[i]; |
| 4248 BlockEntryInstr* pre_header = FindPreHeader(header); |
| 4249 if (pre_header == NULL) { |
| 4250 invariant_loads->Add(NULL); |
| 4251 continue; |
| 4252 } |
| 4253 |
| 4254 BitVector* loop_gen = new BitVector(aliased_set_->max_expr_id()); |
| 4255 for (BitVector::Iterator loop_it(header->loop_info()); |
| 4256 !loop_it.Done(); |
| 4257 loop_it.Advance()) { |
| 4258 const intptr_t preorder_number = loop_it.Current(); |
| 4259 loop_gen->AddAll(gen_[preorder_number]); |
| 4260 } |
| 4261 |
| 4262 for (BitVector::Iterator loop_it(header->loop_info()); |
| 4263 !loop_it.Done(); |
| 4264 loop_it.Advance()) { |
| 4265 const intptr_t preorder_number = loop_it.Current(); |
| 4266 loop_gen->RemoveAll(kill_[preorder_number]); |
| 4267 } |
| 4268 |
| 4269 if (FLAG_trace_optimization) { |
| 4270 for (BitVector::Iterator it(loop_gen); !it.Done(); it.Advance()) { |
| 4271 OS::Print("load %"Pd" is loop invariant for B%"Pd"\n", |
| 4272 it.Current(), |
| 4273 header->block_id()); |
| 4274 } |
| 4275 } |
| 4276 |
| 4277 invariant_loads->Add(loop_gen); |
| 4278 } |
| 4279 |
| 4280 graph_->set_loop_invariant_loads(invariant_loads); |
| 4281 } |
| 4282 |
| 4214 // Compute incoming value for the given expression id. | 4283 // Compute incoming value for the given expression id. |
| 4215 // Will create a phi if different values are incoming from multiple | 4284 // Will create a phi if different values are incoming from multiple |
| 4216 // predecessors. | 4285 // predecessors. |
| 4217 Definition* MergeIncomingValues(BlockEntryInstr* block, intptr_t expr_id) { | 4286 Definition* MergeIncomingValues(BlockEntryInstr* block, intptr_t expr_id) { |
| 4218 // First check if the same value is coming in from all predecessors. | 4287 // First check if the same value is coming in from all predecessors. |
| 4219 Definition* incoming = NULL; | 4288 Definition* incoming = NULL; |
| 4220 for (intptr_t i = 0; i < block->PredecessorCount(); i++) { | 4289 for (intptr_t i = 0; i < block->PredecessorCount(); i++) { |
| 4221 BlockEntryInstr* pred = block->PredecessorAt(i); | 4290 BlockEntryInstr* pred = block->PredecessorAt(i); |
| 4222 ZoneGrowableArray<Definition*>* pred_out_values = | 4291 ZoneGrowableArray<Definition*>* pred_out_values = |
| 4223 out_values_[pred->preorder_number()]; | 4292 out_values_[pred->preorder_number()]; |
| (...skipping 2034 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6258 | 6327 |
| 6259 // Insert materializations at environment uses. | 6328 // Insert materializations at environment uses. |
| 6260 const Class& cls = Class::Handle(alloc->constructor().Owner()); | 6329 const Class& cls = Class::Handle(alloc->constructor().Owner()); |
| 6261 for (intptr_t i = 0; i < exits.length(); i++) { | 6330 for (intptr_t i = 0; i < exits.length(); i++) { |
| 6262 CreateMaterializationAt(exits[i], alloc, cls, *fields); | 6331 CreateMaterializationAt(exits[i], alloc, cls, *fields); |
| 6263 } | 6332 } |
| 6264 } | 6333 } |
| 6265 | 6334 |
| 6266 | 6335 |
| 6267 } // namespace dart | 6336 } // namespace dart |
| OLD | NEW |