| OLD | NEW |
| 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 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 110 call->deopt_id(), | 110 call->deopt_id(), |
| 111 class_ids.length())); | 111 class_ids.length())); |
| 112 ic_data.AddReceiverCheck(class_ids[0], function); | 112 ic_data.AddReceiverCheck(class_ids[0], function); |
| 113 call->set_ic_data(&ic_data); | 113 call->set_ic_data(&ic_data); |
| 114 return true; | 114 return true; |
| 115 } | 115 } |
| 116 return false; | 116 return false; |
| 117 } | 117 } |
| 118 | 118 |
| 119 | 119 |
| 120 static void EnsureSSATempIndex(FlowGraph* graph, |
| 121 Definition* defn, |
| 122 Definition* replacement) { |
| 123 if ((replacement->ssa_temp_index() == -1) && |
| 124 (defn->ssa_temp_index() != -1)) { |
| 125 replacement->set_ssa_temp_index(graph->alloc_ssa_temp_index()); |
| 126 } |
| 127 } |
| 128 |
| 129 |
| 120 static void ReplaceCurrentInstruction(ForwardInstructionIterator* it, | 130 static void ReplaceCurrentInstruction(ForwardInstructionIterator* it, |
| 121 Instruction* current, | 131 Instruction* current, |
| 122 Instruction* replacement) { | 132 Instruction* replacement, |
| 133 FlowGraph* graph) { |
| 123 if ((replacement != NULL) && current->IsDefinition()) { | 134 if ((replacement != NULL) && current->IsDefinition()) { |
| 124 Definition* current_defn = current->AsDefinition(); | 135 Definition* current_defn = current->AsDefinition(); |
| 125 Definition* replacement_defn = replacement->AsDefinition(); | 136 Definition* replacement_defn = replacement->AsDefinition(); |
| 126 ASSERT(replacement_defn != NULL); | 137 ASSERT(replacement_defn != NULL); |
| 127 current_defn->ReplaceUsesWith(replacement_defn); | 138 current_defn->ReplaceUsesWith(replacement_defn); |
| 139 EnsureSSATempIndex(graph, current_defn, replacement_defn); |
| 128 | 140 |
| 129 if (FLAG_trace_optimization) { | 141 if (FLAG_trace_optimization) { |
| 130 OS::Print("Replacing v%"Pd" with v%"Pd"\n", | 142 OS::Print("Replacing v%"Pd" with v%"Pd"\n", |
| 131 current_defn->ssa_temp_index(), | 143 current_defn->ssa_temp_index(), |
| 132 replacement_defn->ssa_temp_index()); | 144 replacement_defn->ssa_temp_index()); |
| 133 } | 145 } |
| 134 } else if (FLAG_trace_optimization) { | 146 } else if (FLAG_trace_optimization) { |
| 135 ASSERT(!current->IsDefinition() || | 147 ASSERT(!current->IsDefinition() || |
| 136 ((current->AsDefinition()->input_use_list() == NULL) && | 148 ((current->AsDefinition()->input_use_list() == NULL) && |
| 137 (current->AsDefinition()->env_use_list() == NULL))); | 149 (current->AsDefinition()->env_use_list() == NULL))); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 150 for (intptr_t i = 0; i < block_order_.length(); ++i) { | 162 for (intptr_t i = 0; i < block_order_.length(); ++i) { |
| 151 BlockEntryInstr* entry = block_order_[i]; | 163 BlockEntryInstr* entry = block_order_[i]; |
| 152 entry->Accept(this); | 164 entry->Accept(this); |
| 153 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) { | 165 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) { |
| 154 Instruction* current = it.Current(); | 166 Instruction* current = it.Current(); |
| 155 Instruction* replacement = current->Canonicalize(this); | 167 Instruction* replacement = current->Canonicalize(this); |
| 156 if (replacement != current) { | 168 if (replacement != current) { |
| 157 // For non-definitions Canonicalize should return either NULL or | 169 // For non-definitions Canonicalize should return either NULL or |
| 158 // this. | 170 // this. |
| 159 ASSERT((replacement == NULL) || current->IsDefinition()); | 171 ASSERT((replacement == NULL) || current->IsDefinition()); |
| 160 ReplaceCurrentInstruction(&it, current, replacement); | 172 ReplaceCurrentInstruction(&it, current, replacement, flow_graph_); |
| 161 } | 173 } |
| 162 } | 174 } |
| 163 } | 175 } |
| 164 } | 176 } |
| 165 | 177 |
| 166 | 178 |
| 167 void FlowGraphOptimizer::InsertConversion(Representation from, | 179 void FlowGraphOptimizer::InsertConversion(Representation from, |
| 168 Representation to, | 180 Representation to, |
| 169 Instruction* instr, | 181 Instruction* instr, |
| 170 Value* use, | 182 Value* use, |
| (...skipping 2927 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3098 Definition* defn = instr->AsDefinition(); | 3110 Definition* defn = instr->AsDefinition(); |
| 3099 if ((defn == NULL) || !IsLoadEliminationCandidate(defn)) { | 3111 if ((defn == NULL) || !IsLoadEliminationCandidate(defn)) { |
| 3100 continue; | 3112 continue; |
| 3101 } | 3113 } |
| 3102 | 3114 |
| 3103 const intptr_t expr_id = defn->expr_id(); | 3115 const intptr_t expr_id = defn->expr_id(); |
| 3104 if (gen->Contains(expr_id)) { | 3116 if (gen->Contains(expr_id)) { |
| 3105 // This is a locally redundant load. | 3117 // This is a locally redundant load. |
| 3106 ASSERT((out_values != NULL) && ((*out_values)[expr_id] != NULL)); | 3118 ASSERT((out_values != NULL) && ((*out_values)[expr_id] != NULL)); |
| 3107 | 3119 |
| 3120 Definition* replacement = (*out_values)[expr_id]; |
| 3121 EnsureSSATempIndex(graph_, defn, replacement); |
| 3108 if (FLAG_trace_optimization) { | 3122 if (FLAG_trace_optimization) { |
| 3109 OS::Print("Replacing load v%"Pd" with v%"Pd"\n", | 3123 OS::Print("Replacing load v%"Pd" with v%"Pd"\n", |
| 3110 defn->ssa_temp_index(), | 3124 defn->ssa_temp_index(), |
| 3111 (*out_values)[expr_id]->ssa_temp_index()); | 3125 replacement->ssa_temp_index()); |
| 3112 } | 3126 } |
| 3113 | 3127 |
| 3114 defn->ReplaceUsesWith((*out_values)[expr_id]); | 3128 defn->ReplaceUsesWith(replacement); |
| 3115 instr_it.RemoveCurrentFromGraph(); | 3129 instr_it.RemoveCurrentFromGraph(); |
| 3116 continue; | 3130 continue; |
| 3117 } else if (!kill->Contains(expr_id)) { | 3131 } else if (!kill->Contains(expr_id)) { |
| 3118 // This is an exposed load: it is the first representative of a | 3132 // This is an exposed load: it is the first representative of a |
| 3119 // given expression id and it is not killed on the path from | 3133 // given expression id and it is not killed on the path from |
| 3120 // the block entry. | 3134 // the block entry. |
| 3121 if (exposed_values == NULL) { | 3135 if (exposed_values == NULL) { |
| 3122 static const intptr_t kMaxExposedValuesInitialSize = 5; | 3136 static const intptr_t kMaxExposedValuesInitialSize = 5; |
| 3123 exposed_values = new ZoneGrowableArray<Definition*>( | 3137 exposed_values = new ZoneGrowableArray<Definition*>( |
| 3124 Utils::Minimum(kMaxExposedValuesInitialSize, max_expr_id_)); | 3138 Utils::Minimum(kMaxExposedValuesInitialSize, max_expr_id_)); |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3306 Definition* replacement = MergeIncomingValues(block, load->expr_id()); | 3320 Definition* replacement = MergeIncomingValues(block, load->expr_id()); |
| 3307 | 3321 |
| 3308 // Sets of outgoing values are not linked into use lists so | 3322 // Sets of outgoing values are not linked into use lists so |
| 3309 // they might contain values that were replace and removed | 3323 // they might contain values that were replace and removed |
| 3310 // from the graph by this iteration. | 3324 // from the graph by this iteration. |
| 3311 // To prevent using them we additionally mark definitions themselves | 3325 // To prevent using them we additionally mark definitions themselves |
| 3312 // as replaced and store a pointer to the replacement. | 3326 // as replaced and store a pointer to the replacement. |
| 3313 replacement = replacement->Replacement(); | 3327 replacement = replacement->Replacement(); |
| 3314 | 3328 |
| 3315 if (load != replacement) { | 3329 if (load != replacement) { |
| 3330 EnsureSSATempIndex(graph_, load, replacement); |
| 3331 |
| 3316 if (FLAG_trace_optimization) { | 3332 if (FLAG_trace_optimization) { |
| 3317 OS::Print("Replacing load v%"Pd" with v%"Pd"\n", | 3333 OS::Print("Replacing load v%"Pd" with v%"Pd"\n", |
| 3318 load->ssa_temp_index(), | 3334 load->ssa_temp_index(), |
| 3319 replacement->ssa_temp_index()); | 3335 replacement->ssa_temp_index()); |
| 3320 } | 3336 } |
| 3321 | 3337 |
| 3322 load->ReplaceUsesWith(replacement); | 3338 load->ReplaceUsesWith(replacement); |
| 3323 load->RemoveFromGraph(); | 3339 load->RemoveFromGraph(); |
| 3324 load->SetReplacement(replacement); | 3340 load->SetReplacement(replacement); |
| 3325 } | 3341 } |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3442 DirectChainedHashMap<LoadKeyValueTrait> map; | 3458 DirectChainedHashMap<LoadKeyValueTrait> map; |
| 3443 const intptr_t max_expr_id = | 3459 const intptr_t max_expr_id = |
| 3444 NumberLoadExpressions(graph, &map, &kill_by_offs); | 3460 NumberLoadExpressions(graph, &map, &kill_by_offs); |
| 3445 if (max_expr_id > 0) { | 3461 if (max_expr_id > 0) { |
| 3446 LoadOptimizer load_optimizer(graph, max_expr_id, &map, kill_by_offs); | 3462 LoadOptimizer load_optimizer(graph, max_expr_id, &map, kill_by_offs); |
| 3447 load_optimizer.Optimize(); | 3463 load_optimizer.Optimize(); |
| 3448 } | 3464 } |
| 3449 } | 3465 } |
| 3450 | 3466 |
| 3451 DirectChainedHashMap<PointerKeyValueTrait<Instruction> > map; | 3467 DirectChainedHashMap<PointerKeyValueTrait<Instruction> > map; |
| 3452 changed = OptimizeRecursive(graph->graph_entry(), &map) || changed; | 3468 changed = OptimizeRecursive(graph, graph->graph_entry(), &map) || changed; |
| 3453 | 3469 |
| 3454 return changed; | 3470 return changed; |
| 3455 } | 3471 } |
| 3456 | 3472 |
| 3457 | 3473 |
| 3458 bool DominatorBasedCSE::OptimizeRecursive( | 3474 bool DominatorBasedCSE::OptimizeRecursive( |
| 3475 FlowGraph* graph, |
| 3459 BlockEntryInstr* block, | 3476 BlockEntryInstr* block, |
| 3460 DirectChainedHashMap<PointerKeyValueTrait<Instruction> >* map) { | 3477 DirectChainedHashMap<PointerKeyValueTrait<Instruction> >* map) { |
| 3461 bool changed = false; | 3478 bool changed = false; |
| 3462 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { | 3479 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { |
| 3463 Instruction* current = it.Current(); | 3480 Instruction* current = it.Current(); |
| 3464 if (current->AffectedBySideEffect()) continue; | 3481 if (current->AffectedBySideEffect()) continue; |
| 3465 Instruction* replacement = map->Lookup(current); | 3482 Instruction* replacement = map->Lookup(current); |
| 3466 if (replacement == NULL) { | 3483 if (replacement == NULL) { |
| 3467 map->Insert(current); | 3484 map->Insert(current); |
| 3468 continue; | 3485 continue; |
| 3469 } | 3486 } |
| 3470 // Replace current with lookup result. | 3487 // Replace current with lookup result. |
| 3471 ReplaceCurrentInstruction(&it, current, replacement); | 3488 ReplaceCurrentInstruction(&it, current, replacement, graph); |
| 3472 changed = true; | 3489 changed = true; |
| 3473 } | 3490 } |
| 3474 | 3491 |
| 3475 // Process children in the dominator tree recursively. | 3492 // Process children in the dominator tree recursively. |
| 3476 intptr_t num_children = block->dominated_blocks().length(); | 3493 intptr_t num_children = block->dominated_blocks().length(); |
| 3477 for (intptr_t i = 0; i < num_children; ++i) { | 3494 for (intptr_t i = 0; i < num_children; ++i) { |
| 3478 BlockEntryInstr* child = block->dominated_blocks()[i]; | 3495 BlockEntryInstr* child = block->dominated_blocks()[i]; |
| 3479 if (i < num_children - 1) { | 3496 if (i < num_children - 1) { |
| 3480 // Copy map. | 3497 // Copy map. |
| 3481 DirectChainedHashMap<PointerKeyValueTrait<Instruction> > child_map(*map); | 3498 DirectChainedHashMap<PointerKeyValueTrait<Instruction> > child_map(*map); |
| 3482 changed = OptimizeRecursive(child, &child_map) || changed; | 3499 changed = OptimizeRecursive(graph, child, &child_map) || changed; |
| 3483 } else { | 3500 } else { |
| 3484 // Reuse map for the last child. | 3501 // Reuse map for the last child. |
| 3485 changed = OptimizeRecursive(child, map) || changed; | 3502 changed = OptimizeRecursive(graph, child, map) || changed; |
| 3486 } | 3503 } |
| 3487 } | 3504 } |
| 3488 return changed; | 3505 return changed; |
| 3489 } | 3506 } |
| 3490 | 3507 |
| 3491 | 3508 |
| 3492 ConstantPropagator::ConstantPropagator( | 3509 ConstantPropagator::ConstantPropagator( |
| 3493 FlowGraph* graph, | 3510 FlowGraph* graph, |
| 3494 const GrowableArray<BlockEntryInstr*>& ignored) | 3511 const GrowableArray<BlockEntryInstr*>& ignored) |
| 3495 : FlowGraphVisitor(ignored), | 3512 : FlowGraphVisitor(ignored), |
| (...skipping 837 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4333 | 4350 |
| 4334 if (FLAG_trace_constant_propagation) { | 4351 if (FLAG_trace_constant_propagation) { |
| 4335 OS::Print("\n==== After constant propagation ====\n"); | 4352 OS::Print("\n==== After constant propagation ====\n"); |
| 4336 FlowGraphPrinter printer(*graph_); | 4353 FlowGraphPrinter printer(*graph_); |
| 4337 printer.PrintBlocks(); | 4354 printer.PrintBlocks(); |
| 4338 } | 4355 } |
| 4339 } | 4356 } |
| 4340 | 4357 |
| 4341 | 4358 |
| 4342 } // namespace dart | 4359 } // namespace dart |
| OLD | NEW |