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

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

Issue 14682020: Optimize functions containing try-catch. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: addressed Srdjan's comments Created 7 years, 7 months 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
OLDNEW
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"
11 #include "vm/hash_map.h" 11 #include "vm/hash_map.h"
12 #include "vm/il_printer.h" 12 #include "vm/il_printer.h"
13 #include "vm/intermediate_language.h" 13 #include "vm/intermediate_language.h"
14 #include "vm/object_store.h" 14 #include "vm/object_store.h"
15 #include "vm/parser.h" 15 #include "vm/parser.h"
16 #include "vm/resolver.h" 16 #include "vm/resolver.h"
17 #include "vm/scopes.h" 17 #include "vm/scopes.h"
18 #include "vm/stack_frame.h"
18 #include "vm/symbols.h" 19 #include "vm/symbols.h"
19 20
20 namespace dart { 21 namespace dart {
21 22
22 DEFINE_FLAG(bool, array_bounds_check_elimination, true, 23 DEFINE_FLAG(bool, array_bounds_check_elimination, true,
23 "Eliminate redundant bounds checks."); 24 "Eliminate redundant bounds checks.");
24 DEFINE_FLAG(bool, load_cse, true, "Use redundant load elimination."); 25 DEFINE_FLAG(bool, load_cse, true, "Use redundant load elimination.");
25 DEFINE_FLAG(int, max_polymorphic_checks, 4, 26 DEFINE_FLAG(int, max_polymorphic_checks, 4,
26 "Maximum number of polymorphic check, otherwise it is megamorphic."); 27 "Maximum number of polymorphic check, otherwise it is megamorphic.");
27 DEFINE_FLAG(bool, remove_redundant_phis, true, "Remove redundant phis."); 28 DEFINE_FLAG(bool, remove_redundant_phis, true, "Remove redundant phis.");
(...skipping 422 matching lines...) Expand 10 before | Expand all | Expand 10 after
450 BlockEntryInstr* entry = block_order_[i]; 451 BlockEntryInstr* entry = block_order_[i];
451 JoinEntryInstr* join_entry = entry->AsJoinEntry(); 452 JoinEntryInstr* join_entry = entry->AsJoinEntry();
452 if (join_entry != NULL) { 453 if (join_entry != NULL) {
453 for (PhiIterator it(join_entry); !it.Done(); it.Advance()) { 454 for (PhiIterator it(join_entry); !it.Done(); it.Advance()) {
454 PhiInstr* phi = it.Current(); 455 PhiInstr* phi = it.Current();
455 ASSERT(phi != NULL); 456 ASSERT(phi != NULL);
456 ASSERT(phi->is_alive()); 457 ASSERT(phi->is_alive());
457 InsertConversionsFor(phi); 458 InsertConversionsFor(phi);
458 } 459 }
459 } 460 }
461 CatchBlockEntryInstr* catch_entry = entry->AsCatchBlockEntry();
462 if (catch_entry != NULL) {
463 for (intptr_t i = 0;
464 i < catch_entry->initial_definitions()->length();
465 i++) {
466 InsertConversionsFor((*catch_entry->initial_definitions())[i]);
467 }
468 }
460 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) { 469 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) {
461 Definition* def = it.Current()->AsDefinition(); 470 Definition* def = it.Current()->AsDefinition();
462 if (def != NULL) { 471 if (def != NULL) {
463 InsertConversionsFor(def); 472 InsertConversionsFor(def);
464 } 473 }
465 } 474 }
466 } 475 }
467 } 476 }
468 477
469 478
(...skipping 2201 matching lines...) Expand 10 before | Expand all | Expand 10 after
2671 2680
2672 2681
2673 void RangeAnalysis::Analyze() { 2682 void RangeAnalysis::Analyze() {
2674 CollectSmiValues(); 2683 CollectSmiValues();
2675 InsertConstraints(); 2684 InsertConstraints();
2676 InferRanges(); 2685 InferRanges();
2677 RemoveConstraints(); 2686 RemoveConstraints();
2678 } 2687 }
2679 2688
2680 2689
2681 void RangeAnalysis::CollectSmiValues() { 2690 void RangeAnalysis::CollectSmiValues() {
Kevin Millikin (Google) 2013/05/08 11:42:00 Note that this function does not handle smi consta
Florian Schneider 2013/05/08 17:10:55 Good catch. Done.
2682 for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator(); 2691 for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator();
2683 !block_it.Done(); 2692 !block_it.Done();
2684 block_it.Advance()) { 2693 block_it.Advance()) {
2685 BlockEntryInstr* block = block_it.Current(); 2694 BlockEntryInstr* block = block_it.Current();
2686 for (ForwardInstructionIterator instr_it(block); 2695 for (ForwardInstructionIterator instr_it(block);
2687 !instr_it.Done(); 2696 !instr_it.Done();
2688 instr_it.Advance()) { 2697 instr_it.Advance()) {
2689 Instruction* current = instr_it.Current(); 2698 Instruction* current = instr_it.Current();
2690 Definition* defn = current->AsDefinition(); 2699 Definition* defn = current->AsDefinition();
2691 if (defn != NULL) { 2700 if (defn != NULL) {
(...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after
3042 case kUnknown: 3051 case kUnknown:
3043 case kBoth: 3052 case kBoth:
3044 return Range::Unknown(); 3053 return Range::Unknown();
3045 } 3054 }
3046 3055
3047 UNREACHABLE(); 3056 UNREACHABLE();
3048 return NULL; 3057 return NULL;
3049 } 3058 }
3050 3059
3051 3060
3052 void RangeAnalysis::InferRangesRecursive(BlockEntryInstr* block) { 3061 void RangeAnalysis::InferRangesRecursive(BlockEntryInstr* block) {
Kevin Millikin (Google) 2013/05/08 11:42:00 Note that this function does not infer ranges for
Florian Schneider 2013/05/08 17:10:55 Done.
3053 JoinEntryInstr* join = block->AsJoinEntry(); 3062 JoinEntryInstr* join = block->AsJoinEntry();
3054 if (join != NULL) { 3063 if (join != NULL) {
3055 const bool is_loop_header = (join->loop_info() != NULL); 3064 const bool is_loop_header = (join->loop_info() != NULL);
3056 for (PhiIterator it(join); !it.Done(); it.Advance()) { 3065 for (PhiIterator it(join); !it.Done(); it.Advance()) {
3057 PhiInstr* phi = it.Current(); 3066 PhiInstr* phi = it.Current();
3058 if (smi_definitions_->Contains(phi->ssa_temp_index())) { 3067 if (smi_definitions_->Contains(phi->ssa_temp_index())) {
3059 if (is_loop_header) { 3068 if (is_loop_header) {
3060 // Try recognizing simple induction variables. 3069 // Try recognizing simple induction variables.
3061 Range* range = InferInductionVariableRange(join, phi); 3070 Range* range = InferInductionVariableRange(join, phi);
3062 if (range != NULL) { 3071 if (range != NULL) {
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
3129 } 3138 }
3130 } 3139 }
3131 3140
3132 3141
3133 void FlowGraphOptimizer::InferSmiRanges() { 3142 void FlowGraphOptimizer::InferSmiRanges() {
3134 RangeAnalysis range_analysis(flow_graph_); 3143 RangeAnalysis range_analysis(flow_graph_);
3135 range_analysis.Analyze(); 3144 range_analysis.Analyze();
3136 } 3145 }
3137 3146
3138 3147
3148 void FlowGraphOptimizer::AnalyzeTryCatch() {
Kevin Millikin (Google) 2013/05/08 11:42:00 Doesn't need to be in the FlowGraphOptimizer, whic
Florian Schneider 2013/05/08 17:10:55 Done.
3149 // For every catch-block: Iterate over all call instructions inside the
3150 // corresponding try-block and figure out for each environment value if it
3151 // is the same constant at all calls. If yes, replace the initial definition
3152 // at the catch-entry with this constant.
3153 const GrowableArray<CatchBlockEntryInstr*>& catch_entries =
3154 flow_graph_->graph_entry()->catch_entries();
3155 intptr_t nncp = flow_graph_->num_non_copied_params();
Kevin Millikin (Google) 2013/05/08 11:42:00 intptr_t base = kFirstLocalSlotIndex + flow_graph_
Florian Schneider 2013/05/08 17:10:55 Done.
3156 for (intptr_t catch_idx = 0;
3157 catch_idx < catch_entries.length();
3158 ++catch_idx) {
3159 CatchBlockEntryInstr* cb = catch_entries[catch_idx];
3160 CatchEntryInstr* catch_entry = cb->next()->AsCatchEntry();
3161 intptr_t ex_idx =
Kevin Millikin (Google) 2013/05/08 11:42:00 intptr_t ex_idx = base - catch_entry->exception_va
Florian Schneider 2013/05/08 17:10:55 Done.
3162 kFirstLocalSlotIndex - catch_entry->exception_var().index() + nncp;
3163 intptr_t st_idx =
3164 kFirstLocalSlotIndex - catch_entry->stacktrace_var().index() + nncp;
3165 GrowableArray<Definition*>* idefs = cb->initial_definitions();
3166 GrowableArray<Definition*> cdefs(idefs->length());
3167 cdefs.AddArray(*idefs);
3168
3169 for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator();
Kevin Millikin (Google) 2013/05/08 11:42:00 This is doing constant analysis with the lattice:
Florian Schneider 2013/05/08 17:10:55 Done.
3170 !block_it.Done();
3171 block_it.Advance()) {
3172 BlockEntryInstr* block = block_it.Current();
3173 if (block->try_index() == cb->catch_try_index()) {
3174 for (ForwardInstructionIterator instr_it(block);
3175 !instr_it.Done();
3176 instr_it.Advance()) {
3177 Instruction* current = instr_it.Current();
3178 if (current->MayThrow()) {
3179 Environment* env = current->env();
3180 for (intptr_t env_idx = 0; env_idx < cdefs.length(); ++env_idx) {
3181 if (cdefs[env_idx] != NULL &&
3182 cdefs[env_idx]->IsParameter() &&
3183 cdefs[env_idx]->AsParameter()->index() != ex_idx &&
Kevin Millikin (Google) 2013/05/08 11:42:00 The intent is that ex_idx and st_idx are not const
Florian Schneider 2013/05/08 17:10:55 Done.
3184 cdefs[env_idx]->AsParameter()->index() != st_idx &&
3185 env->ValueAt(env_idx)->definition()->IsConstant()) {
Kevin Millikin (Google) 2013/05/08 11:42:00 I guess you can write this as env->ValueAt(env_idx
Florian Schneider 2013/05/08 17:10:55 Done.
3186 cdefs[env_idx] = env->ValueAt(env_idx)->definition();
3187 }
3188 if (cdefs[env_idx] != env->ValueAt(env_idx)->definition()) {
3189 cdefs[env_idx] = NULL;
3190 }
3191 }
3192 }
3193 }
3194 }
3195 }
3196 for (intptr_t j = 0; j < idefs->length(); ++j) {
3197 if (cdefs[j] != NULL && cdefs[j]->IsConstant()) {
3198 Definition* old = (*idefs)[j];
3199 ConstantInstr* orig = cdefs[j]->AsConstant();
3200 ConstantInstr* copy = new ConstantInstr(orig->value());
Kevin Millikin (Google) 2013/05/08 11:42:00 Note that all constants are pooled now. I think y
Florian Schneider 2013/05/08 17:10:55 Yes. It should and make the code much simpler here
3201 copy->set_ssa_temp_index(flow_graph_->alloc_ssa_temp_index());
3202 old->ReplaceUsesWith(copy);
3203 (*idefs)[j] = copy;
3204 }
3205 }
3206 }
3207 }
3208
3209
3139 static BlockEntryInstr* FindPreHeader(BlockEntryInstr* header) { 3210 static BlockEntryInstr* FindPreHeader(BlockEntryInstr* header) {
3140 for (intptr_t j = 0; j < header->PredecessorCount(); ++j) { 3211 for (intptr_t j = 0; j < header->PredecessorCount(); ++j) {
3141 BlockEntryInstr* candidate = header->PredecessorAt(j); 3212 BlockEntryInstr* candidate = header->PredecessorAt(j);
3142 if (header->dominator() == candidate) { 3213 if (header->dominator() == candidate) {
3143 return candidate; 3214 return candidate;
3144 } 3215 }
3145 } 3216 }
3146 return NULL; 3217 return NULL;
3147 } 3218 }
3148 3219
(...skipping 1242 matching lines...) Expand 10 before | Expand all | Expand 10 after
4391 // -------------------------------------------------------------------------- 4462 // --------------------------------------------------------------------------
4392 // Analysis of blocks. Called at most once per block. The block is already 4463 // Analysis of blocks. Called at most once per block. The block is already
4393 // marked as reachable. All instructions in the block are analyzed. 4464 // marked as reachable. All instructions in the block are analyzed.
4394 void ConstantPropagator::VisitGraphEntry(GraphEntryInstr* block) { 4465 void ConstantPropagator::VisitGraphEntry(GraphEntryInstr* block) {
4395 const GrowableArray<Definition*>& defs = *block->initial_definitions(); 4466 const GrowableArray<Definition*>& defs = *block->initial_definitions();
4396 for (intptr_t i = 0; i < defs.length(); ++i) { 4467 for (intptr_t i = 0; i < defs.length(); ++i) {
4397 defs[i]->Accept(this); 4468 defs[i]->Accept(this);
4398 } 4469 }
4399 ASSERT(ForwardInstructionIterator(block).Done()); 4470 ASSERT(ForwardInstructionIterator(block).Done());
4400 4471
4401 SetReachable(block->normal_entry()); 4472 for (intptr_t i = 0; i < block->SuccessorCount(); ++i) {
4473 SetReachable(block->SuccessorAt(i));
Kevin Millikin (Google) 2013/05/08 11:42:00 Hmm, this is a poor approximation. Can you add a
Florian Schneider 2013/05/08 17:10:55 Done.
4474 }
4402 } 4475 }
4403 4476
4404 4477
4405 void ConstantPropagator::VisitJoinEntry(JoinEntryInstr* block) { 4478 void ConstantPropagator::VisitJoinEntry(JoinEntryInstr* block) {
4406 // Phis are visited when visiting Goto at a predecessor. See VisitGoto. 4479 // Phis are visited when visiting Goto at a predecessor. See VisitGoto.
4407 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { 4480 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
4408 it.Current()->Accept(this); 4481 it.Current()->Accept(this);
4409 } 4482 }
4410 } 4483 }
4411 4484
4412 4485
4413 void ConstantPropagator::VisitTargetEntry(TargetEntryInstr* block) { 4486 void ConstantPropagator::VisitTargetEntry(TargetEntryInstr* block) {
4414 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { 4487 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
4415 it.Current()->Accept(this); 4488 it.Current()->Accept(this);
4416 } 4489 }
4417 } 4490 }
4418 4491
4419 4492
4420 void ConstantPropagator::VisitCatchBlockEntry(CatchBlockEntryInstr* block) { 4493 void ConstantPropagator::VisitCatchBlockEntry(CatchBlockEntryInstr* block) {
4494 const GrowableArray<Definition*>& defs = *block->initial_definitions();
4495 for (intptr_t i = 0; i < defs.length(); ++i) {
4496 defs[i]->Accept(this);
4497 }
4421 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { 4498 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
4422 it.Current()->Accept(this); 4499 it.Current()->Accept(this);
4423 } 4500 }
4424 } 4501 }
4425 4502
4426 4503
4427 void ConstantPropagator::VisitParallelMove(ParallelMoveInstr* instr) { 4504 void ConstantPropagator::VisitParallelMove(ParallelMoveInstr* instr) {
4428 // Parallel moves have not yet been inserted in the graph. 4505 // Parallel moves have not yet been inserted in the graph.
4429 UNREACHABLE(); 4506 UNREACHABLE();
4430 } 4507 }
(...skipping 786 matching lines...) Expand 10 before | Expand all | Expand 10 after
5217 BlockEntryInstr* block = block_worklist_.RemoveLast(); 5294 BlockEntryInstr* block = block_worklist_.RemoveLast();
5218 block->Accept(this); 5295 block->Accept(this);
5219 } 5296 }
5220 } 5297 }
5221 } 5298 }
5222 5299
5223 5300
5224 void ConstantPropagator::VisitBranches() { 5301 void ConstantPropagator::VisitBranches() {
5225 GraphEntryInstr* entry = graph_->graph_entry(); 5302 GraphEntryInstr* entry = graph_->graph_entry();
5226 reachable_->Add(entry->preorder_number()); 5303 reachable_->Add(entry->preorder_number());
5227 // TODO(fschneider): Handle CatchEntry. 5304 block_worklist_.Add(entry);
5228 reachable_->Add(entry->normal_entry()->preorder_number());
5229 block_worklist_.Add(entry->normal_entry());
5230 5305
5231 while (!block_worklist_.is_empty()) { 5306 while (!block_worklist_.is_empty()) {
5232 BlockEntryInstr* block = block_worklist_.RemoveLast(); 5307 BlockEntryInstr* block = block_worklist_.RemoveLast();
5308 if (block->IsGraphEntry()) {
5309 for (intptr_t i = 0; i < block->SuccessorCount(); ++i) {
5310 SetReachable(block->SuccessorAt(i));
5311 }
5312 continue;
5313 }
5233 Instruction* last = block->last_instruction(); 5314 Instruction* last = block->last_instruction();
5234 if (last->IsGoto()) { 5315 if (last->IsGoto()) {
5235 SetReachable(last->AsGoto()->successor()); 5316 SetReachable(last->AsGoto()->successor());
5236 } else if (last->IsBranch()) { 5317 } else if (last->IsBranch()) {
5237 BranchInstr* branch = last->AsBranch(); 5318 BranchInstr* branch = last->AsBranch();
5238 // The current block must be reachable. 5319 // The current block must be reachable.
5239 ASSERT(reachable_->Contains(branch->GetBlock()->preorder_number())); 5320 ASSERT(reachable_->Contains(branch->GetBlock()->preorder_number()));
5240 if (branch->constant_target() != NULL) { 5321 if (branch->constant_target() != NULL) {
5241 // Found constant target computed by range analysis. 5322 // Found constant target computed by range analysis.
5242 if (branch->constant_target() == branch->true_successor()) { 5323 if (branch->constant_target() == branch->true_successor()) {
(...skipping 547 matching lines...) Expand 10 before | Expand all | Expand 10 after
5790 if (changed) { 5871 if (changed) {
5791 // We may have changed the block order and the dominator tree. 5872 // We may have changed the block order and the dominator tree.
5792 flow_graph->DiscoverBlocks(); 5873 flow_graph->DiscoverBlocks();
5793 GrowableArray<BitVector*> dominance_frontier; 5874 GrowableArray<BitVector*> dominance_frontier;
5794 flow_graph->ComputeDominators(&dominance_frontier); 5875 flow_graph->ComputeDominators(&dominance_frontier);
5795 } 5876 }
5796 } 5877 }
5797 5878
5798 5879
5799 } // namespace dart 5880 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698