| 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 3220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3231 if (pre_header == NULL) continue; | 3231 if (pre_header == NULL) continue; |
| 3232 | 3232 |
| 3233 for (BitVector::Iterator loop_it(header->loop_info()); | 3233 for (BitVector::Iterator loop_it(header->loop_info()); |
| 3234 !loop_it.Done(); | 3234 !loop_it.Done(); |
| 3235 loop_it.Advance()) { | 3235 loop_it.Advance()) { |
| 3236 BlockEntryInstr* block = flow_graph()->preorder()[loop_it.Current()]; | 3236 BlockEntryInstr* block = flow_graph()->preorder()[loop_it.Current()]; |
| 3237 for (ForwardInstructionIterator it(block); | 3237 for (ForwardInstructionIterator it(block); |
| 3238 !it.Done(); | 3238 !it.Done(); |
| 3239 it.Advance()) { | 3239 it.Advance()) { |
| 3240 Instruction* current = it.Current(); | 3240 Instruction* current = it.Current(); |
| 3241 if (!current->IsPushArgument() && | 3241 if (current->AllowsCSE() && |
| 3242 current->AllowsCSE() && | |
| 3243 flow_graph()->block_effects()->CanBeMovedTo(current, pre_header)) { | 3242 flow_graph()->block_effects()->CanBeMovedTo(current, pre_header)) { |
| 3244 bool inputs_loop_invariant = true; | 3243 bool inputs_loop_invariant = true; |
| 3245 for (int i = 0; i < current->InputCount(); ++i) { | 3244 for (int i = 0; i < current->InputCount(); ++i) { |
| 3246 Definition* input_def = current->InputAt(i)->definition(); | 3245 Definition* input_def = current->InputAt(i)->definition(); |
| 3247 if (!input_def->GetBlock()->Dominates(pre_header)) { | 3246 if (!input_def->GetBlock()->Dominates(pre_header)) { |
| 3248 inputs_loop_invariant = false; | 3247 inputs_loop_invariant = false; |
| 3249 break; | 3248 break; |
| 3250 } | 3249 } |
| 3251 } | 3250 } |
| 3252 if (inputs_loop_invariant && | 3251 if (inputs_loop_invariant && |
| (...skipping 1270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4523 if (reachable_->Contains( | 4522 if (reachable_->Contains( |
| 4524 block->PredecessorAt(pred_idx)->preorder_number())) { | 4523 block->PredecessorAt(pred_idx)->preorder_number())) { |
| 4525 Join(&value, | 4524 Join(&value, |
| 4526 instr->InputAt(pred_idx)->definition()->constant_value()); | 4525 instr->InputAt(pred_idx)->definition()->constant_value()); |
| 4527 } | 4526 } |
| 4528 } | 4527 } |
| 4529 SetValue(instr, value); | 4528 SetValue(instr, value); |
| 4530 } | 4529 } |
| 4531 | 4530 |
| 4532 | 4531 |
| 4532 void ConstantPropagator::VisitRedefinition(RedefinitionInstr* instr) { |
| 4533 SetValue(instr, instr->value()->definition()->constant_value()); |
| 4534 } |
| 4535 |
| 4536 |
| 4533 void ConstantPropagator::VisitParameter(ParameterInstr* instr) { | 4537 void ConstantPropagator::VisitParameter(ParameterInstr* instr) { |
| 4534 SetValue(instr, non_constant_); | 4538 SetValue(instr, non_constant_); |
| 4535 } | 4539 } |
| 4536 | 4540 |
| 4537 | 4541 |
| 4538 void ConstantPropagator::VisitPushArgument(PushArgumentInstr* instr) { | 4542 void ConstantPropagator::VisitPushArgument(PushArgumentInstr* instr) { |
| 4539 SetValue(instr, instr->value()->definition()->constant_value()); | 4543 SetValue(instr, instr->value()->definition()->constant_value()); |
| 4540 } | 4544 } |
| 4541 | 4545 |
| 4542 | 4546 |
| (...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4797 AllocateObjectWithBoundsCheckInstr* instr) { | 4801 AllocateObjectWithBoundsCheckInstr* instr) { |
| 4798 SetValue(instr, non_constant_); | 4802 SetValue(instr, non_constant_); |
| 4799 } | 4803 } |
| 4800 | 4804 |
| 4801 | 4805 |
| 4802 void ConstantPropagator::VisitLoadUntagged(LoadUntaggedInstr* instr) { | 4806 void ConstantPropagator::VisitLoadUntagged(LoadUntaggedInstr* instr) { |
| 4803 SetValue(instr, non_constant_); | 4807 SetValue(instr, non_constant_); |
| 4804 } | 4808 } |
| 4805 | 4809 |
| 4806 | 4810 |
| 4811 void ConstantPropagator::VisitLoadClassId(LoadClassIdInstr* instr) { |
| 4812 SetValue(instr, non_constant_); |
| 4813 } |
| 4814 |
| 4815 |
| 4807 void ConstantPropagator::VisitLoadField(LoadFieldInstr* instr) { | 4816 void ConstantPropagator::VisitLoadField(LoadFieldInstr* instr) { |
| 4808 if ((instr->recognized_kind() == MethodRecognizer::kObjectArrayLength) && | 4817 if ((instr->recognized_kind() == MethodRecognizer::kObjectArrayLength) && |
| 4809 (instr->instance()->definition()->IsCreateArray())) { | 4818 (instr->instance()->definition()->IsCreateArray())) { |
| 4810 const intptr_t length = | 4819 const intptr_t length = |
| 4811 instr->instance()->definition()->AsCreateArray()->num_elements(); | 4820 instr->instance()->definition()->AsCreateArray()->num_elements(); |
| 4812 const Object& result = Smi::ZoneHandle(Smi::New(length)); | 4821 const Object& result = Smi::ZoneHandle(Smi::New(length)); |
| 4813 SetValue(instr, result); | 4822 SetValue(instr, result); |
| 4814 return; | 4823 return; |
| 4815 } | 4824 } |
| 4816 | 4825 |
| (...skipping 754 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5571 | 5580 |
| 5572 // Insert a copy of the constant in all the predecessors. | 5581 // Insert a copy of the constant in all the predecessors. |
| 5573 ConstantInstr* new_constant = CloneConstant(flow_graph, constant); | 5582 ConstantInstr* new_constant = CloneConstant(flow_graph, constant); |
| 5574 new_constant->InsertBefore(old_goto); | 5583 new_constant->InsertBefore(old_goto); |
| 5575 | 5584 |
| 5576 // Replace the goto in each predecessor with a rewritten branch, | 5585 // Replace the goto in each predecessor with a rewritten branch, |
| 5577 // rewritten to use the corresponding phi input instead of the phi. | 5586 // rewritten to use the corresponding phi input instead of the phi. |
| 5578 Value* new_left = phi->InputAt(i)->Copy(); | 5587 Value* new_left = phi->InputAt(i)->Copy(); |
| 5579 Value* new_right = new Value(new_constant); | 5588 Value* new_right = new Value(new_constant); |
| 5580 BranchInstr* new_branch = CloneBranch(branch, new_left, new_right); | 5589 BranchInstr* new_branch = CloneBranch(branch, new_left, new_right); |
| 5581 new_branch->InheritDeoptTarget(old_goto); | 5590 if (branch->env() == NULL) { |
| 5591 new_branch->InheritDeoptTarget(old_goto); |
| 5592 } else { |
| 5593 // Take the environment from the branch if it has one. |
| 5594 new_branch->InheritDeoptTarget(branch); |
| 5595 // InheritDeoptTarget gave the new branch's comparison the same |
| 5596 // deopt id that it gave the new branch. The id should be the |
| 5597 // deopt id of the original comparison. |
| 5598 new_branch->comparison()->SetDeoptId(comparison->GetDeoptId()); |
| 5599 // The phi and constant can be used in the branch's environment. |
| 5600 // Rename such uses. |
| 5601 for (Environment::DeepIterator it(new_branch->env()); |
| 5602 !it.Done(); |
| 5603 it.Advance()) { |
| 5604 Value* use = it.CurrentValue(); |
| 5605 Definition* replacement = NULL; |
| 5606 if (use->definition() == phi) { |
| 5607 replacement = phi->InputAt(i)->definition(); |
| 5608 } else if (use->definition() == constant) { |
| 5609 replacement = new_constant; |
| 5610 } |
| 5611 if (replacement != NULL) { |
| 5612 use->RemoveFromUseList(); |
| 5613 use->set_definition(replacement); |
| 5614 replacement->AddEnvUse(use); |
| 5615 } |
| 5616 } |
| 5617 } |
| 5618 |
| 5582 new_branch->InsertBefore(old_goto); | 5619 new_branch->InsertBefore(old_goto); |
| 5583 new_branch->set_next(NULL); // Detaching the goto from the graph. | 5620 new_branch->set_next(NULL); // Detaching the goto from the graph. |
| 5584 old_goto->UnuseAllInputs(); | 5621 old_goto->UnuseAllInputs(); |
| 5585 | 5622 |
| 5586 // Update the predecessor block. We may have created another | 5623 // Update the predecessor block. We may have created another |
| 5587 // instance of the pattern so add it to the worklist if necessary. | 5624 // instance of the pattern so add it to the worklist if necessary. |
| 5588 BlockEntryInstr* branch_block = new_branch->GetBlock(); | 5625 BlockEntryInstr* branch_block = new_branch->GetBlock(); |
| 5589 branch_block->set_last_instruction(new_branch); | 5626 branch_block->set_last_instruction(new_branch); |
| 5590 if (branch_block->IsJoinEntry()) worklist.Add(branch_block); | 5627 if (branch_block->IsJoinEntry()) worklist.Add(branch_block); |
| 5591 | 5628 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 5609 GotoInstr* goto_false = new GotoInstr(join_false); | 5646 GotoInstr* goto_false = new GotoInstr(join_false); |
| 5610 goto_false->InheritDeoptTarget(join_false); | 5647 goto_false->InheritDeoptTarget(join_false); |
| 5611 false_target->LinkTo(goto_false); | 5648 false_target->LinkTo(goto_false); |
| 5612 false_target->set_last_instruction(goto_false); | 5649 false_target->set_last_instruction(goto_false); |
| 5613 } | 5650 } |
| 5614 // When all predecessors have been rewritten, the original block is | 5651 // When all predecessors have been rewritten, the original block is |
| 5615 // unreachable from the graph. | 5652 // unreachable from the graph. |
| 5616 phi->UnuseAllInputs(); | 5653 phi->UnuseAllInputs(); |
| 5617 branch->UnuseAllInputs(); | 5654 branch->UnuseAllInputs(); |
| 5618 block->UnuseAllInputs(); | 5655 block->UnuseAllInputs(); |
| 5656 ASSERT(!phi->HasUses()); |
| 5657 ASSERT(!constant->HasUses()); |
| 5619 } | 5658 } |
| 5620 } | 5659 } |
| 5621 | 5660 |
| 5622 if (changed) { | 5661 if (changed) { |
| 5623 // We may have changed the block order and the dominator tree. | 5662 // We may have changed the block order and the dominator tree. |
| 5624 flow_graph->DiscoverBlocks(); | 5663 flow_graph->DiscoverBlocks(); |
| 5625 GrowableArray<BitVector*> dominance_frontier; | 5664 GrowableArray<BitVector*> dominance_frontier; |
| 5626 flow_graph->ComputeDominators(&dominance_frontier); | 5665 flow_graph->ComputeDominators(&dominance_frontier); |
| 5627 } | 5666 } |
| 5628 } | 5667 } |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5751 if (changed) { | 5790 if (changed) { |
| 5752 // We may have changed the block order and the dominator tree. | 5791 // We may have changed the block order and the dominator tree. |
| 5753 flow_graph->DiscoverBlocks(); | 5792 flow_graph->DiscoverBlocks(); |
| 5754 GrowableArray<BitVector*> dominance_frontier; | 5793 GrowableArray<BitVector*> dominance_frontier; |
| 5755 flow_graph->ComputeDominators(&dominance_frontier); | 5794 flow_graph->ComputeDominators(&dominance_frontier); |
| 5756 } | 5795 } |
| 5757 } | 5796 } |
| 5758 | 5797 |
| 5759 | 5798 |
| 5760 } // namespace dart | 5799 } // namespace dart |
| OLD | NEW |