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

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

Issue 13469013: Use range analysis to improve constant propagation. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 8 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
« no previous file with comments | « runtime/vm/flow_graph_optimizer.h ('k') | runtime/vm/intermediate_language.h » ('j') | 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) 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 2458 matching lines...) Expand 10 before | Expand all | Expand 10 after
2469 op_kind = FlipComparison(rel_op->kind()); 2469 op_kind = FlipComparison(rel_op->kind());
2470 } 2470 }
2471 2471
2472 // Constrain definition at the true successor. 2472 // Constrain definition at the true successor.
2473 ConstraintInstr* true_constraint = 2473 ConstraintInstr* true_constraint =
2474 InsertConstraintFor(defn, 2474 InsertConstraintFor(defn,
2475 ConstraintRange(op_kind, boundary), 2475 ConstraintRange(op_kind, boundary),
2476 branch->true_successor()); 2476 branch->true_successor());
2477 // Mark true_constraint an artificial use of boundary. This ensures 2477 // Mark true_constraint an artificial use of boundary. This ensures
2478 // that constraint's range is recalculated if boundary's range changes. 2478 // that constraint's range is recalculated if boundary's range changes.
2479 if (true_constraint != NULL) true_constraint->AddDependency(boundary); 2479 if (true_constraint != NULL) {
2480 true_constraint->AddDependency(boundary);
2481 true_constraint->set_target(branch->true_successor());
2482 }
2480 2483
2481 // Constrain definition with a negated condition at the false successor. 2484 // Constrain definition with a negated condition at the false successor.
2482 ConstraintInstr* false_constraint = 2485 ConstraintInstr* false_constraint =
2483 InsertConstraintFor( 2486 InsertConstraintFor(
2484 defn, 2487 defn,
2485 ConstraintRange(Token::NegateComparison(op_kind), boundary), 2488 ConstraintRange(Token::NegateComparison(op_kind), boundary),
2486 branch->false_successor()); 2489 branch->false_successor());
2487 // Mark false_constraint an artificial use of boundary. This ensures 2490 // Mark false_constraint an artificial use of boundary. This ensures
2488 // that constraint's range is recalculated if boundary's range changes. 2491 // that constraint's range is recalculated if boundary's range changes.
2489 if (false_constraint != NULL) false_constraint->AddDependency(boundary); 2492 if (false_constraint != NULL) {
2493 false_constraint->AddDependency(boundary);
2494 false_constraint->set_target(branch->false_successor());
2495 }
2490 } 2496 }
2491 } 2497 }
2492 2498
2493 void RangeAnalysis::InsertConstraintsFor(Definition* defn) { 2499 void RangeAnalysis::InsertConstraintsFor(Definition* defn) {
2494 for (Value* use = defn->input_use_list(); 2500 for (Value* use = defn->input_use_list();
2495 use != NULL; 2501 use != NULL;
2496 use = use->next_use()) { 2502 use = use->next_use()) {
2497 if (use->instruction()->IsBranch()) { 2503 if (use->instruction()->IsBranch()) {
2498 ConstrainValueAfterBranch(defn, use); 2504 ConstrainValueAfterBranch(defn, use);
2499 } else if (use->instruction()->IsCheckArrayBound()) { 2505 } else if (use->instruction()->IsCheckArrayBound()) {
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after
2697 } 2703 }
2698 2704
2699 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { 2705 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
2700 Instruction* current = it.Current(); 2706 Instruction* current = it.Current();
2701 2707
2702 Definition* defn = current->AsDefinition(); 2708 Definition* defn = current->AsDefinition();
2703 if ((defn != NULL) && 2709 if ((defn != NULL) &&
2704 (defn->ssa_temp_index() != -1) && 2710 (defn->ssa_temp_index() != -1) &&
2705 smi_definitions_->Contains(defn->ssa_temp_index())) { 2711 smi_definitions_->Contains(defn->ssa_temp_index())) {
2706 defn->InferRange(); 2712 defn->InferRange();
2713 // Mark branches that generate unsatisfiable constraints as constant.
Vyacheslav Egorov (Google) 2013/04/03 19:38:57 I wonder if this can be moved into the Constraint:
Florian Schneider 2013/04/04 11:49:15 Done.
2714 if (defn->IsConstraint()) {
2715 ConstraintInstr* constraint = defn->AsConstraint();
2716 if (constraint->target() != NULL &&
2717 constraint->range()->IsUnsatisfiable()) {
2718 BranchInstr* branch = constraint->target()->PredecessorAt(0)->
2719 last_instruction()->AsBranch();
2720 if (constraint->target() == branch->true_successor()) {
2721 // True unreachable.
2722 if (FLAG_trace_constant_propagation) {
2723 OS::Print("Range analysis: True unreachable (B%"Pd")\n",
2724 branch->true_successor()->block_id());
2725 }
2726 branch->set_constant_target(branch->false_successor());
2727 } else {
2728 ASSERT(constraint->target() == branch->false_successor());
2729 // False unreachable.
2730 if (FLAG_trace_constant_propagation) {
2731 OS::Print("Range analysis: False unreachable (B%"Pd")\n",
2732 branch->false_successor()->block_id());
2733 }
2734 branch->set_constant_target(branch->true_successor());
2735 }
2736 }
2737 }
2707 } else if (FLAG_array_bounds_check_elimination && 2738 } else if (FLAG_array_bounds_check_elimination &&
2708 current->IsCheckArrayBound()) { 2739 current->IsCheckArrayBound()) {
2709 CheckArrayBoundInstr* check = current->AsCheckArrayBound(); 2740 CheckArrayBoundInstr* check = current->AsCheckArrayBound();
2710 RangeBoundary array_length = 2741 RangeBoundary array_length =
2711 RangeBoundary::FromDefinition(check->length()->definition()); 2742 RangeBoundary::FromDefinition(check->length()->definition());
2712 if (check->IsRedundant(array_length)) { 2743 if (check->IsRedundant(array_length)) {
2713 it.RemoveCurrentFromGraph(); 2744 it.RemoveCurrentFromGraph();
2714 } 2745 }
2715 } 2746 }
2716 } 2747 }
(...skipping 895 matching lines...) Expand 10 before | Expand all | Expand 10 after
3612 3643
3613 3644
3614 void ConstantPropagator::Optimize(FlowGraph* graph) { 3645 void ConstantPropagator::Optimize(FlowGraph* graph) {
3615 GrowableArray<BlockEntryInstr*> ignored; 3646 GrowableArray<BlockEntryInstr*> ignored;
3616 ConstantPropagator cp(graph, ignored); 3647 ConstantPropagator cp(graph, ignored);
3617 cp.Analyze(); 3648 cp.Analyze();
3618 cp.Transform(); 3649 cp.Transform();
3619 } 3650 }
3620 3651
3621 3652
3653 void ConstantPropagator::OptimizeBranches(FlowGraph* graph) {
3654 GrowableArray<BlockEntryInstr*> ignored;
3655 ConstantPropagator cp(graph, ignored);
3656 cp.VisitBranches();
3657 cp.Transform();
3658 }
3659
3660
3622 void ConstantPropagator::SetReachable(BlockEntryInstr* block) { 3661 void ConstantPropagator::SetReachable(BlockEntryInstr* block) {
3623 if (!reachable_->Contains(block->preorder_number())) { 3662 if (!reachable_->Contains(block->preorder_number())) {
3624 reachable_->Add(block->preorder_number()); 3663 reachable_->Add(block->preorder_number());
3625 block_worklist_.Add(block); 3664 block_worklist_.Add(block);
3626 } 3665 }
3627 } 3666 }
3628 3667
3629 3668
3630 void ConstantPropagator::SetValue(Definition* definition, const Object& value) { 3669 void ConstantPropagator::SetValue(Definition* definition, const Object& value) {
3631 // We would like to assert we only go up (toward non-constant) in the lattice. 3670 // We would like to assert we only go up (toward non-constant) in the lattice.
(...skipping 698 matching lines...) Expand 10 before | Expand all | Expand 10 after
4330 use = use->next_use(); 4369 use = use->next_use();
4331 } 4370 }
4332 } else { 4371 } else {
4333 BlockEntryInstr* block = block_worklist_.RemoveLast(); 4372 BlockEntryInstr* block = block_worklist_.RemoveLast();
4334 block->Accept(this); 4373 block->Accept(this);
4335 } 4374 }
4336 } 4375 }
4337 } 4376 }
4338 4377
4339 4378
4379 void ConstantPropagator::VisitBranches() {
4380 GraphEntryInstr* entry = graph_->graph_entry();
4381 reachable_->Add(entry->preorder_number());
4382 // TODO(fschneider): Handle CatchEntry.
4383 reachable_->Add(entry->normal_entry()->preorder_number());
4384 block_worklist_.Add(entry->normal_entry());
4385
4386 while (!block_worklist_.is_empty()) {
4387 BlockEntryInstr* block = block_worklist_.RemoveLast();
4388 Instruction* last = block->last_instruction();
4389 if (last->IsGoto()) {
4390 SetReachable(last->AsGoto()->successor());
4391 } else if (last->IsBranch()) {
4392 BranchInstr* branch = last->AsBranch();
4393 // The current block must be reachable.
4394 ASSERT(reachable_->Contains(branch->GetBlock()->preorder_number()));
4395 if (branch->constant_target() != NULL) {
4396 // Found constant target computed by range analysis.
4397 if (branch->constant_target() == branch->true_successor()) {
4398 SetReachable(branch->true_successor());
4399 } else {
4400 ASSERT(branch->constant_target() == branch->false_successor());
4401 SetReachable(branch->false_successor());
4402 }
4403 } else {
4404 // No new information: Assume both targets are reachable.
4405 SetReachable(branch->true_successor());
4406 SetReachable(branch->false_successor());
4407 }
4408 }
4409 }
4410 }
4411
4412
4340 void ConstantPropagator::Transform() { 4413 void ConstantPropagator::Transform() {
4341 if (FLAG_trace_constant_propagation) { 4414 if (FLAG_trace_constant_propagation) {
4342 OS::Print("\n==== Before constant propagation ====\n"); 4415 OS::Print("\n==== Before constant propagation ====\n");
4343 FlowGraphPrinter printer(*graph_); 4416 FlowGraphPrinter printer(*graph_);
4344 printer.PrintBlocks(); 4417 printer.PrintBlocks();
4345 } 4418 }
4346 4419
4347 GrowableArray<PhiInstr*> redundant_phis(10); 4420 GrowableArray<PhiInstr*> redundant_phis(10);
4348 4421
4349 // We will recompute dominators, block ordering, block ids, block last 4422 // We will recompute dominators, block ordering, block ids, block last
(...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after
4669 if (changed) { 4742 if (changed) {
4670 // We may have changed the block order and the dominator tree. 4743 // We may have changed the block order and the dominator tree.
4671 flow_graph->DiscoverBlocks(); 4744 flow_graph->DiscoverBlocks();
4672 GrowableArray<BitVector*> dominance_frontier; 4745 GrowableArray<BitVector*> dominance_frontier;
4673 flow_graph->ComputeDominators(&dominance_frontier); 4746 flow_graph->ComputeDominators(&dominance_frontier);
4674 } 4747 }
4675 } 4748 }
4676 4749
4677 4750
4678 } // namespace dart 4751 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_optimizer.h ('k') | runtime/vm/intermediate_language.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698