| 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 2458 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |