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

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: addressed comments 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 16 matching lines...) Expand all
2516 Range* constraint_range = new Range( 2522 Range* constraint_range = new Range(
2517 RangeBoundary::FromConstant(0), 2523 RangeBoundary::FromConstant(0),
2518 RangeBoundary::FromDefinition(length, -1)); 2524 RangeBoundary::FromDefinition(length, -1));
2519 InsertConstraintFor(defn, constraint_range, check); 2525 InsertConstraintFor(defn, constraint_range, check);
2520 } 2526 }
2521 2527
2522 2528
2523 void RangeAnalysis::InsertConstraints() { 2529 void RangeAnalysis::InsertConstraints() {
2524 for (intptr_t i = 0; i < smi_checks_.length(); i++) { 2530 for (intptr_t i = 0; i < smi_checks_.length(); i++) {
2525 CheckSmiInstr* check = smi_checks_[i]; 2531 CheckSmiInstr* check = smi_checks_[i];
2526 ConstraintInstr* constraint = 2532 InsertConstraintFor(check->value()->definition(), Range::Unknown(), check);
2527 InsertConstraintFor(check->value()->definition(),
2528 Range::Unknown(),
2529 check);
2530 if (constraint != NULL) {
2531 InsertConstraintsFor(constraint); // Constrain uses further.
2532 }
2533 } 2533 }
2534 2534
2535 for (intptr_t i = 0; i < smi_values_.length(); i++) { 2535 for (intptr_t i = 0; i < smi_values_.length(); i++) {
2536 InsertConstraintsFor(smi_values_[i]); 2536 InsertConstraintsFor(smi_values_[i]);
2537 } 2537 }
2538
2539 for (intptr_t i = 0; i < constraints_.length(); i++) {
2540 InsertConstraintsFor(constraints_[i]);
2541 }
2538 } 2542 }
2539 2543
2540 2544
2541 void RangeAnalysis::ResetWorklist() { 2545 void RangeAnalysis::ResetWorklist() {
2542 if (marked_defns_ == NULL) { 2546 if (marked_defns_ == NULL) {
2543 marked_defns_ = new BitVector(flow_graph_->current_ssa_temp_index()); 2547 marked_defns_ = new BitVector(flow_graph_->current_ssa_temp_index());
2544 } else { 2548 } else {
2545 marked_defns_->Clear(); 2549 marked_defns_->Clear();
2546 } 2550 }
2547 worklist_.Clear(); 2551 worklist_.Clear();
(...skipping 1064 matching lines...) Expand 10 before | Expand all | Expand 10 after
3612 3616
3613 3617
3614 void ConstantPropagator::Optimize(FlowGraph* graph) { 3618 void ConstantPropagator::Optimize(FlowGraph* graph) {
3615 GrowableArray<BlockEntryInstr*> ignored; 3619 GrowableArray<BlockEntryInstr*> ignored;
3616 ConstantPropagator cp(graph, ignored); 3620 ConstantPropagator cp(graph, ignored);
3617 cp.Analyze(); 3621 cp.Analyze();
3618 cp.Transform(); 3622 cp.Transform();
3619 } 3623 }
3620 3624
3621 3625
3626 void ConstantPropagator::OptimizeBranches(FlowGraph* graph) {
3627 GrowableArray<BlockEntryInstr*> ignored;
3628 ConstantPropagator cp(graph, ignored);
3629 cp.VisitBranches();
3630 cp.Transform();
3631 }
3632
3633
3622 void ConstantPropagator::SetReachable(BlockEntryInstr* block) { 3634 void ConstantPropagator::SetReachable(BlockEntryInstr* block) {
3623 if (!reachable_->Contains(block->preorder_number())) { 3635 if (!reachable_->Contains(block->preorder_number())) {
3624 reachable_->Add(block->preorder_number()); 3636 reachable_->Add(block->preorder_number());
3625 block_worklist_.Add(block); 3637 block_worklist_.Add(block);
3626 } 3638 }
3627 } 3639 }
3628 3640
3629 3641
3630 void ConstantPropagator::SetValue(Definition* definition, const Object& value) { 3642 void ConstantPropagator::SetValue(Definition* definition, const Object& value) {
3631 // We would like to assert we only go up (toward non-constant) in the lattice. 3643 // 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(); 4342 use = use->next_use();
4331 } 4343 }
4332 } else { 4344 } else {
4333 BlockEntryInstr* block = block_worklist_.RemoveLast(); 4345 BlockEntryInstr* block = block_worklist_.RemoveLast();
4334 block->Accept(this); 4346 block->Accept(this);
4335 } 4347 }
4336 } 4348 }
4337 } 4349 }
4338 4350
4339 4351
4352 void ConstantPropagator::VisitBranches() {
4353 GraphEntryInstr* entry = graph_->graph_entry();
4354 reachable_->Add(entry->preorder_number());
4355 // TODO(fschneider): Handle CatchEntry.
4356 reachable_->Add(entry->normal_entry()->preorder_number());
4357 block_worklist_.Add(entry->normal_entry());
4358
4359 while (!block_worklist_.is_empty()) {
4360 BlockEntryInstr* block = block_worklist_.RemoveLast();
4361 Instruction* last = block->last_instruction();
4362 if (last->IsGoto()) {
4363 SetReachable(last->AsGoto()->successor());
4364 } else if (last->IsBranch()) {
4365 BranchInstr* branch = last->AsBranch();
4366 // The current block must be reachable.
4367 ASSERT(reachable_->Contains(branch->GetBlock()->preorder_number()));
4368 if (branch->constant_target() != NULL) {
4369 // Found constant target computed by range analysis.
4370 if (branch->constant_target() == branch->true_successor()) {
4371 SetReachable(branch->true_successor());
4372 } else {
4373 ASSERT(branch->constant_target() == branch->false_successor());
4374 SetReachable(branch->false_successor());
4375 }
4376 } else {
4377 // No new information: Assume both targets are reachable.
4378 SetReachable(branch->true_successor());
4379 SetReachable(branch->false_successor());
4380 }
4381 }
4382 }
4383 }
4384
4385
4340 void ConstantPropagator::Transform() { 4386 void ConstantPropagator::Transform() {
4341 if (FLAG_trace_constant_propagation) { 4387 if (FLAG_trace_constant_propagation) {
4342 OS::Print("\n==== Before constant propagation ====\n"); 4388 OS::Print("\n==== Before constant propagation ====\n");
4343 FlowGraphPrinter printer(*graph_); 4389 FlowGraphPrinter printer(*graph_);
4344 printer.PrintBlocks(); 4390 printer.PrintBlocks();
4345 } 4391 }
4346 4392
4347 GrowableArray<PhiInstr*> redundant_phis(10); 4393 GrowableArray<PhiInstr*> redundant_phis(10);
4348 4394
4349 // We will recompute dominators, block ordering, block ids, block last 4395 // 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) { 4715 if (changed) {
4670 // We may have changed the block order and the dominator tree. 4716 // We may have changed the block order and the dominator tree.
4671 flow_graph->DiscoverBlocks(); 4717 flow_graph->DiscoverBlocks();
4672 GrowableArray<BitVector*> dominance_frontier; 4718 GrowableArray<BitVector*> dominance_frontier;
4673 flow_graph->ComputeDominators(&dominance_frontier); 4719 flow_graph->ComputeDominators(&dominance_frontier);
4674 } 4720 }
4675 } 4721 }
4676 4722
4677 4723
4678 } // namespace dart 4724 } // 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