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