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/cpu.h" | 9 #include "vm/cpu.h" |
10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
(...skipping 1181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1192 Definition** last) { | 1192 Definition** last) { |
1193 intptr_t array_cid = MethodKindToCid(kind); | 1193 intptr_t array_cid = MethodKindToCid(kind); |
1194 ASSERT(array_cid != kIllegalCid); | 1194 ASSERT(array_cid != kIllegalCid); |
1195 | 1195 |
1196 Definition* array = receiver; | 1196 Definition* array = receiver; |
1197 Definition* index = call->ArgumentAt(1); | 1197 Definition* index = call->ArgumentAt(1); |
1198 Definition* stored_value = call->ArgumentAt(2); | 1198 Definition* stored_value = call->ArgumentAt(2); |
1199 | 1199 |
1200 *entry = new(Z) TargetEntryInstr(flow_graph()->allocate_block_id(), | 1200 *entry = new(Z) TargetEntryInstr(flow_graph()->allocate_block_id(), |
1201 call->GetBlock()->try_index()); | 1201 call->GetBlock()->try_index()); |
1202 (*entry)->InheritDeoptTarget(I, call); | 1202 (*entry)->InheritDeoptTarget(Z, call); |
1203 Instruction* cursor = *entry; | 1203 Instruction* cursor = *entry; |
1204 if (I->TypeChecksEnabled()) { | 1204 if (I->TypeChecksEnabled()) { |
1205 // Only type check for the value. A type check for the index is not | 1205 // Only type check for the value. A type check for the index is not |
1206 // needed here because we insert a deoptimizing smi-check for the case | 1206 // needed here because we insert a deoptimizing smi-check for the case |
1207 // the index is not a smi. | 1207 // the index is not a smi. |
1208 const AbstractType& value_type = | 1208 const AbstractType& value_type = |
1209 AbstractType::ZoneHandle(Z, target.ParameterTypeAt(2)); | 1209 AbstractType::ZoneHandle(Z, target.ParameterTypeAt(2)); |
1210 Definition* instantiator = NULL; | 1210 Definition* instantiator = NULL; |
1211 Definition* type_args = NULL; | 1211 Definition* type_args = NULL; |
1212 switch (array_cid) { | 1212 switch (array_cid) { |
(...skipping 461 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1674 Definition* receiver, | 1674 Definition* receiver, |
1675 TargetEntryInstr** entry, | 1675 TargetEntryInstr** entry, |
1676 Definition** last) { | 1676 Definition** last) { |
1677 intptr_t array_cid = MethodKindToCid(kind); | 1677 intptr_t array_cid = MethodKindToCid(kind); |
1678 ASSERT(array_cid != kIllegalCid); | 1678 ASSERT(array_cid != kIllegalCid); |
1679 | 1679 |
1680 Definition* array = receiver; | 1680 Definition* array = receiver; |
1681 Definition* index = call->ArgumentAt(1); | 1681 Definition* index = call->ArgumentAt(1); |
1682 *entry = new(Z) TargetEntryInstr(flow_graph()->allocate_block_id(), | 1682 *entry = new(Z) TargetEntryInstr(flow_graph()->allocate_block_id(), |
1683 call->GetBlock()->try_index()); | 1683 call->GetBlock()->try_index()); |
1684 (*entry)->InheritDeoptTarget(I, call); | 1684 (*entry)->InheritDeoptTarget(Z, call); |
1685 Instruction* cursor = *entry; | 1685 Instruction* cursor = *entry; |
1686 | 1686 |
1687 array_cid = PrepareInlineIndexedOp(call, | 1687 array_cid = PrepareInlineIndexedOp(call, |
1688 array_cid, | 1688 array_cid, |
1689 &array, | 1689 &array, |
1690 index, | 1690 index, |
1691 &cursor); | 1691 &cursor); |
1692 | 1692 |
1693 intptr_t deopt_id = Isolate::kNoDeoptId; | 1693 intptr_t deopt_id = Isolate::kNoDeoptId; |
1694 if ((array_cid == kTypedDataInt32ArrayCid) || | 1694 if ((array_cid == kTypedDataInt32ArrayCid) || |
(...skipping 1036 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2731 // TODO(johnmccutchan): Handle external strings in PrepareInlineStringIndexOp. | 2731 // TODO(johnmccutchan): Handle external strings in PrepareInlineStringIndexOp. |
2732 if (RawObject::IsExternalStringClassId(cid)) { | 2732 if (RawObject::IsExternalStringClassId(cid)) { |
2733 return false; | 2733 return false; |
2734 } | 2734 } |
2735 | 2735 |
2736 Definition* str = call->ArgumentAt(0); | 2736 Definition* str = call->ArgumentAt(0); |
2737 Definition* index = call->ArgumentAt(1); | 2737 Definition* index = call->ArgumentAt(1); |
2738 | 2738 |
2739 *entry = new(Z) TargetEntryInstr(flow_graph()->allocate_block_id(), | 2739 *entry = new(Z) TargetEntryInstr(flow_graph()->allocate_block_id(), |
2740 call->GetBlock()->try_index()); | 2740 call->GetBlock()->try_index()); |
2741 (*entry)->InheritDeoptTarget(I, call); | 2741 (*entry)->InheritDeoptTarget(Z, call); |
2742 | 2742 |
2743 *last = PrepareInlineStringIndexOp(call, cid, str, index, *entry); | 2743 *last = PrepareInlineStringIndexOp(call, cid, str, index, *entry); |
2744 | 2744 |
2745 return true; | 2745 return true; |
2746 } | 2746 } |
2747 | 2747 |
2748 | 2748 |
2749 bool FlowGraphOptimizer::InlineStringBaseCharAt( | 2749 bool FlowGraphOptimizer::InlineStringBaseCharAt( |
2750 Instruction* call, | 2750 Instruction* call, |
2751 intptr_t cid, | 2751 intptr_t cid, |
2752 TargetEntryInstr** entry, | 2752 TargetEntryInstr** entry, |
2753 Definition** last) { | 2753 Definition** last) { |
2754 // TODO(johnmccutchan): Handle external strings in PrepareInlineStringIndexOp. | 2754 // TODO(johnmccutchan): Handle external strings in PrepareInlineStringIndexOp. |
2755 if (RawObject::IsExternalStringClassId(cid) || cid != kOneByteStringCid) { | 2755 if (RawObject::IsExternalStringClassId(cid) || cid != kOneByteStringCid) { |
2756 return false; | 2756 return false; |
2757 } | 2757 } |
2758 Definition* str = call->ArgumentAt(0); | 2758 Definition* str = call->ArgumentAt(0); |
2759 Definition* index = call->ArgumentAt(1); | 2759 Definition* index = call->ArgumentAt(1); |
2760 | 2760 |
2761 *entry = new(Z) TargetEntryInstr(flow_graph()->allocate_block_id(), | 2761 *entry = new(Z) TargetEntryInstr(flow_graph()->allocate_block_id(), |
2762 call->GetBlock()->try_index()); | 2762 call->GetBlock()->try_index()); |
2763 (*entry)->InheritDeoptTarget(I, call); | 2763 (*entry)->InheritDeoptTarget(Z, call); |
2764 | 2764 |
2765 *last = PrepareInlineStringIndexOp(call, cid, str, index, *entry); | 2765 *last = PrepareInlineStringIndexOp(call, cid, str, index, *entry); |
2766 | 2766 |
2767 StringFromCharCodeInstr* char_at = new(Z) StringFromCharCodeInstr( | 2767 StringFromCharCodeInstr* char_at = new(Z) StringFromCharCodeInstr( |
2768 new(Z) Value(*last), cid); | 2768 new(Z) Value(*last), cid); |
2769 | 2769 |
2770 flow_graph()->AppendTo(*last, char_at, NULL, FlowGraph::kValue); | 2770 flow_graph()->AppendTo(*last, char_at, NULL, FlowGraph::kValue); |
2771 *last = char_at; | 2771 *last = char_at; |
2772 | 2772 |
2773 return true; | 2773 return true; |
2774 } | 2774 } |
2775 | 2775 |
2776 | 2776 |
2777 bool FlowGraphOptimizer::InlineDoubleOp( | 2777 bool FlowGraphOptimizer::InlineDoubleOp( |
2778 Token::Kind op_kind, | 2778 Token::Kind op_kind, |
2779 Instruction* call, | 2779 Instruction* call, |
2780 TargetEntryInstr** entry, | 2780 TargetEntryInstr** entry, |
2781 Definition** last) { | 2781 Definition** last) { |
2782 Definition* left = call->ArgumentAt(0); | 2782 Definition* left = call->ArgumentAt(0); |
2783 Definition* right = call->ArgumentAt(1); | 2783 Definition* right = call->ArgumentAt(1); |
2784 | 2784 |
2785 *entry = new(Z) TargetEntryInstr(flow_graph()->allocate_block_id(), | 2785 *entry = new(Z) TargetEntryInstr(flow_graph()->allocate_block_id(), |
2786 call->GetBlock()->try_index()); | 2786 call->GetBlock()->try_index()); |
2787 (*entry)->InheritDeoptTarget(I, call); | 2787 (*entry)->InheritDeoptTarget(Z, call); |
2788 // Arguments are checked. No need for class check. | 2788 // Arguments are checked. No need for class check. |
2789 BinaryDoubleOpInstr* double_bin_op = | 2789 BinaryDoubleOpInstr* double_bin_op = |
2790 new(Z) BinaryDoubleOpInstr(op_kind, | 2790 new(Z) BinaryDoubleOpInstr(op_kind, |
2791 new(Z) Value(left), | 2791 new(Z) Value(left), |
2792 new(Z) Value(right), | 2792 new(Z) Value(right), |
2793 call->deopt_id(), call->token_pos()); | 2793 call->deopt_id(), call->token_pos()); |
2794 flow_graph()->AppendTo(*entry, double_bin_op, call->env(), FlowGraph::kValue); | 2794 flow_graph()->AppendTo(*entry, double_bin_op, call->env(), FlowGraph::kValue); |
2795 *last = double_bin_op; | 2795 *last = double_bin_op; |
2796 | 2796 |
2797 return true; | 2797 return true; |
(...skipping 749 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3547 intptr_t array_cid, | 3547 intptr_t array_cid, |
3548 intptr_t view_cid, | 3548 intptr_t view_cid, |
3549 const ICData& ic_data, | 3549 const ICData& ic_data, |
3550 TargetEntryInstr** entry, | 3550 TargetEntryInstr** entry, |
3551 Definition** last) { | 3551 Definition** last) { |
3552 ASSERT(array_cid != kIllegalCid); | 3552 ASSERT(array_cid != kIllegalCid); |
3553 Definition* array = receiver; | 3553 Definition* array = receiver; |
3554 Definition* index = call->ArgumentAt(1); | 3554 Definition* index = call->ArgumentAt(1); |
3555 *entry = new(Z) TargetEntryInstr(flow_graph()->allocate_block_id(), | 3555 *entry = new(Z) TargetEntryInstr(flow_graph()->allocate_block_id(), |
3556 call->GetBlock()->try_index()); | 3556 call->GetBlock()->try_index()); |
3557 (*entry)->InheritDeoptTarget(I, call); | 3557 (*entry)->InheritDeoptTarget(Z, call); |
3558 Instruction* cursor = *entry; | 3558 Instruction* cursor = *entry; |
3559 | 3559 |
3560 array_cid = PrepareInlineByteArrayBaseOp(call, | 3560 array_cid = PrepareInlineByteArrayBaseOp(call, |
3561 array_cid, | 3561 array_cid, |
3562 view_cid, | 3562 view_cid, |
3563 &array, | 3563 &array, |
3564 index, | 3564 index, |
3565 &cursor); | 3565 &cursor); |
3566 | 3566 |
3567 intptr_t deopt_id = Isolate::kNoDeoptId; | 3567 intptr_t deopt_id = Isolate::kNoDeoptId; |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3600 intptr_t array_cid, | 3600 intptr_t array_cid, |
3601 intptr_t view_cid, | 3601 intptr_t view_cid, |
3602 const ICData& ic_data, | 3602 const ICData& ic_data, |
3603 TargetEntryInstr** entry, | 3603 TargetEntryInstr** entry, |
3604 Definition** last) { | 3604 Definition** last) { |
3605 ASSERT(array_cid != kIllegalCid); | 3605 ASSERT(array_cid != kIllegalCid); |
3606 Definition* array = receiver; | 3606 Definition* array = receiver; |
3607 Definition* index = call->ArgumentAt(1); | 3607 Definition* index = call->ArgumentAt(1); |
3608 *entry = new(Z) TargetEntryInstr(flow_graph()->allocate_block_id(), | 3608 *entry = new(Z) TargetEntryInstr(flow_graph()->allocate_block_id(), |
3609 call->GetBlock()->try_index()); | 3609 call->GetBlock()->try_index()); |
3610 (*entry)->InheritDeoptTarget(I, call); | 3610 (*entry)->InheritDeoptTarget(Z, call); |
3611 Instruction* cursor = *entry; | 3611 Instruction* cursor = *entry; |
3612 | 3612 |
3613 array_cid = PrepareInlineByteArrayBaseOp(call, | 3613 array_cid = PrepareInlineByteArrayBaseOp(call, |
3614 array_cid, | 3614 array_cid, |
3615 view_cid, | 3615 view_cid, |
3616 &array, | 3616 &array, |
3617 index, | 3617 index, |
3618 &cursor); | 3618 &cursor); |
3619 | 3619 |
3620 // Extract the instance call so we can use the function_name in the stored | 3620 // Extract the instance call so we can use the function_name in the stored |
(...skipping 1249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4870 } | 4870 } |
4871 } | 4871 } |
4872 } | 4872 } |
4873 } | 4873 } |
4874 for (intptr_t j = 0; j < idefs->length(); ++j) { | 4874 for (intptr_t j = 0; j < idefs->length(); ++j) { |
4875 if (cdefs[j] != NULL && cdefs[j]->IsConstant()) { | 4875 if (cdefs[j] != NULL && cdefs[j]->IsConstant()) { |
4876 // TODO(fschneider): Use constants from the constant pool. | 4876 // TODO(fschneider): Use constants from the constant pool. |
4877 Definition* old = (*idefs)[j]; | 4877 Definition* old = (*idefs)[j]; |
4878 ConstantInstr* orig = cdefs[j]->AsConstant(); | 4878 ConstantInstr* orig = cdefs[j]->AsConstant(); |
4879 ConstantInstr* copy = | 4879 ConstantInstr* copy = |
4880 new(flow_graph->isolate()) ConstantInstr(orig->value()); | 4880 new(flow_graph->zone()) ConstantInstr(orig->value()); |
4881 copy->set_ssa_temp_index(flow_graph->alloc_ssa_temp_index()); | 4881 copy->set_ssa_temp_index(flow_graph->alloc_ssa_temp_index()); |
4882 old->ReplaceUsesWith(copy); | 4882 old->ReplaceUsesWith(copy); |
4883 (*idefs)[j] = copy; | 4883 (*idefs)[j] = copy; |
4884 } | 4884 } |
4885 } | 4885 } |
4886 } | 4886 } |
4887 } | 4887 } |
4888 | 4888 |
4889 | 4889 |
4890 LICM::LICM(FlowGraph* flow_graph) : flow_graph_(flow_graph) { | 4890 LICM::LICM(FlowGraph* flow_graph) : flow_graph_(flow_graph) { |
(...skipping 730 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5621 return wrapped; | 5621 return wrapped; |
5622 } | 5622 } |
5623 | 5623 |
5624 | 5624 |
5625 // Correspondence between places connected through outgoing phi moves on the | 5625 // Correspondence between places connected through outgoing phi moves on the |
5626 // edge that targets join. | 5626 // edge that targets join. |
5627 class PhiPlaceMoves : public ZoneAllocated { | 5627 class PhiPlaceMoves : public ZoneAllocated { |
5628 public: | 5628 public: |
5629 // Record a move from the place with id |from| to the place with id |to| at | 5629 // Record a move from the place with id |from| to the place with id |to| at |
5630 // the given block. | 5630 // the given block. |
5631 void CreateOutgoingMove(Isolate* isolate, | 5631 void CreateOutgoingMove(Zone* zone, |
5632 BlockEntryInstr* block, intptr_t from, intptr_t to) { | 5632 BlockEntryInstr* block, intptr_t from, intptr_t to) { |
5633 const intptr_t block_num = block->preorder_number(); | 5633 const intptr_t block_num = block->preorder_number(); |
5634 while (moves_.length() <= block_num) { | 5634 while (moves_.length() <= block_num) { |
5635 moves_.Add(NULL); | 5635 moves_.Add(NULL); |
5636 } | 5636 } |
5637 | 5637 |
5638 if (moves_[block_num] == NULL) { | 5638 if (moves_[block_num] == NULL) { |
5639 moves_[block_num] = new(isolate) ZoneGrowableArray<Move>(5); | 5639 moves_[block_num] = new(zone) ZoneGrowableArray<Move>(5); |
5640 } | 5640 } |
5641 | 5641 |
5642 moves_[block_num]->Add(Move(from, to)); | 5642 moves_[block_num]->Add(Move(from, to)); |
5643 } | 5643 } |
5644 | 5644 |
5645 class Move { | 5645 class Move { |
5646 public: | 5646 public: |
5647 Move(intptr_t from, intptr_t to) : from_(from), to_(to) { } | 5647 Move(intptr_t from, intptr_t to) : from_(from), to_(to) { } |
5648 | 5648 |
5649 intptr_t from() const { return from_; } | 5649 intptr_t from() const { return from_; } |
(...skipping 547 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6197 | 6197 |
6198 | 6198 |
6199 // For each place that depends on a phi ensure that equivalent places | 6199 // For each place that depends on a phi ensure that equivalent places |
6200 // corresponding to phi input are numbered and record outgoing phi moves | 6200 // corresponding to phi input are numbered and record outgoing phi moves |
6201 // for each block which establish correspondence between phi dependent place | 6201 // for each block which establish correspondence between phi dependent place |
6202 // and phi input's place that is flowing in. | 6202 // and phi input's place that is flowing in. |
6203 static PhiPlaceMoves* ComputePhiMoves( | 6203 static PhiPlaceMoves* ComputePhiMoves( |
6204 DirectChainedHashMap<PointerKeyValueTrait<Place> >* map, | 6204 DirectChainedHashMap<PointerKeyValueTrait<Place> >* map, |
6205 ZoneGrowableArray<Place*>* places) { | 6205 ZoneGrowableArray<Place*>* places) { |
6206 Thread* thread = Thread::Current(); | 6206 Thread* thread = Thread::Current(); |
6207 Isolate* isolate = thread->isolate(); | |
6208 Zone* zone = thread->zone(); | 6207 Zone* zone = thread->zone(); |
6209 PhiPlaceMoves* phi_moves = new(zone) PhiPlaceMoves(); | 6208 PhiPlaceMoves* phi_moves = new(zone) PhiPlaceMoves(); |
6210 | 6209 |
6211 for (intptr_t i = 0; i < places->length(); i++) { | 6210 for (intptr_t i = 0; i < places->length(); i++) { |
6212 Place* place = (*places)[i]; | 6211 Place* place = (*places)[i]; |
6213 | 6212 |
6214 if (IsPhiDependentPlace(place)) { | 6213 if (IsPhiDependentPlace(place)) { |
6215 PhiInstr* phi = place->instance()->AsPhi(); | 6214 PhiInstr* phi = place->instance()->AsPhi(); |
6216 BlockEntryInstr* block = phi->GetBlock(); | 6215 BlockEntryInstr* block = phi->GetBlock(); |
6217 | 6216 |
6218 if (FLAG_trace_optimization) { | 6217 if (FLAG_trace_optimization) { |
6219 ISL_Print("phi dependent place %s\n", place->ToCString()); | 6218 ISL_Print("phi dependent place %s\n", place->ToCString()); |
6220 } | 6219 } |
6221 | 6220 |
6222 Place input_place(*place); | 6221 Place input_place(*place); |
6223 for (intptr_t j = 0; j < phi->InputCount(); j++) { | 6222 for (intptr_t j = 0; j < phi->InputCount(); j++) { |
6224 input_place.set_instance(phi->InputAt(j)->definition()); | 6223 input_place.set_instance(phi->InputAt(j)->definition()); |
6225 | 6224 |
6226 Place* result = map->Lookup(&input_place); | 6225 Place* result = map->Lookup(&input_place); |
6227 if (result == NULL) { | 6226 if (result == NULL) { |
6228 result = Place::Wrap(zone, input_place, places->length()); | 6227 result = Place::Wrap(zone, input_place, places->length()); |
6229 map->Insert(result); | 6228 map->Insert(result); |
6230 places->Add(result); | 6229 places->Add(result); |
6231 if (FLAG_trace_optimization) { | 6230 if (FLAG_trace_optimization) { |
6232 ISL_Print(" adding place %s as %" Pd "\n", | 6231 ISL_Print(" adding place %s as %" Pd "\n", |
6233 result->ToCString(), | 6232 result->ToCString(), |
6234 result->id()); | 6233 result->id()); |
6235 } | 6234 } |
6236 } | 6235 } |
6237 phi_moves->CreateOutgoingMove(isolate, | 6236 phi_moves->CreateOutgoingMove(zone, |
6238 block->PredecessorAt(j), | 6237 block->PredecessorAt(j), |
6239 result->id(), | 6238 result->id(), |
6240 place->id()); | 6239 place->id()); |
6241 } | 6240 } |
6242 } | 6241 } |
6243 } | 6242 } |
6244 | 6243 |
6245 return phi_moves; | 6244 return phi_moves; |
6246 } | 6245 } |
6247 | 6246 |
(...skipping 1439 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7687 (right == NULL) ? NULL : right->definition()->AsConstant(); | 7686 (right == NULL) ? NULL : right->definition()->AsConstant(); |
7688 return (phi != NULL) && | 7687 return (phi != NULL) && |
7689 (constant != NULL) && | 7688 (constant != NULL) && |
7690 (phi->GetBlock() == block) && | 7689 (phi->GetBlock() == block) && |
7691 PhiHasSingleUse(phi, left) && | 7690 PhiHasSingleUse(phi, left) && |
7692 (block->next() == branch) && | 7691 (block->next() == branch) && |
7693 (block->phis()->length() == 1); | 7692 (block->phis()->length() == 1); |
7694 } | 7693 } |
7695 | 7694 |
7696 | 7695 |
7697 JoinEntryInstr* BranchSimplifier::ToJoinEntry(Isolate* isolate, | 7696 JoinEntryInstr* BranchSimplifier::ToJoinEntry(Zone* zone, |
7698 TargetEntryInstr* target) { | 7697 TargetEntryInstr* target) { |
7699 // Convert a target block into a join block. Branches will be duplicated | 7698 // Convert a target block into a join block. Branches will be duplicated |
7700 // so the former true and false targets become joins of the control flows | 7699 // so the former true and false targets become joins of the control flows |
7701 // from all the duplicated branches. | 7700 // from all the duplicated branches. |
7702 JoinEntryInstr* join = | 7701 JoinEntryInstr* join = |
7703 new(isolate) JoinEntryInstr(target->block_id(), target->try_index()); | 7702 new(zone) JoinEntryInstr(target->block_id(), target->try_index()); |
7704 join->InheritDeoptTarget(isolate, target); | 7703 join->InheritDeoptTarget(zone, target); |
7705 join->LinkTo(target->next()); | 7704 join->LinkTo(target->next()); |
7706 join->set_last_instruction(target->last_instruction()); | 7705 join->set_last_instruction(target->last_instruction()); |
7707 target->UnuseAllInputs(); | 7706 target->UnuseAllInputs(); |
7708 return join; | 7707 return join; |
7709 } | 7708 } |
7710 | 7709 |
7711 | 7710 |
7712 BranchInstr* BranchSimplifier::CloneBranch(Isolate* isolate, | 7711 BranchInstr* BranchSimplifier::CloneBranch(Zone* zone, |
7713 BranchInstr* branch, | 7712 BranchInstr* branch, |
7714 Value* new_left, | 7713 Value* new_left, |
7715 Value* new_right) { | 7714 Value* new_right) { |
7716 ComparisonInstr* comparison = branch->comparison(); | 7715 ComparisonInstr* comparison = branch->comparison(); |
7717 ComparisonInstr* new_comparison = | 7716 ComparisonInstr* new_comparison = |
7718 comparison->CopyWithNewOperands(new_left, new_right); | 7717 comparison->CopyWithNewOperands(new_left, new_right); |
7719 BranchInstr* new_branch = new(isolate) BranchInstr(new_comparison); | 7718 BranchInstr* new_branch = new(zone) BranchInstr(new_comparison); |
7720 new_branch->set_is_checked(branch->is_checked()); | 7719 new_branch->set_is_checked(branch->is_checked()); |
7721 return new_branch; | 7720 return new_branch; |
7722 } | 7721 } |
7723 | 7722 |
7724 | 7723 |
7725 void BranchSimplifier::Simplify(FlowGraph* flow_graph) { | 7724 void BranchSimplifier::Simplify(FlowGraph* flow_graph) { |
7726 // Optimize some branches that test the value of a phi. When it is safe | 7725 // Optimize some branches that test the value of a phi. When it is safe |
7727 // to do so, push the branch to each of the predecessor blocks. This is | 7726 // to do so, push the branch to each of the predecessor blocks. This is |
7728 // an optimization when (a) it can avoid materializing a boolean object at | 7727 // an optimization when (a) it can avoid materializing a boolean object at |
7729 // the phi only to test its value, and (b) it can expose opportunities for | 7728 // the phi only to test its value, and (b) it can expose opportunities for |
7730 // constant propagation and unreachable code elimination. This | 7729 // constant propagation and unreachable code elimination. This |
7731 // optimization is intended to run after inlining which creates | 7730 // optimization is intended to run after inlining which creates |
7732 // opportunities for optimization (a) and before constant folding which | 7731 // opportunities for optimization (a) and before constant folding which |
7733 // can perform optimization (b). | 7732 // can perform optimization (b). |
7734 | 7733 |
7735 // Begin with a worklist of join blocks ending in branches. They are | 7734 // Begin with a worklist of join blocks ending in branches. They are |
7736 // candidates for the pattern below. | 7735 // candidates for the pattern below. |
7737 Isolate* isolate = flow_graph->isolate(); | 7736 Zone* zone = flow_graph->zone(); |
7738 const GrowableArray<BlockEntryInstr*>& postorder = flow_graph->postorder(); | 7737 const GrowableArray<BlockEntryInstr*>& postorder = flow_graph->postorder(); |
7739 GrowableArray<BlockEntryInstr*> worklist(postorder.length()); | 7738 GrowableArray<BlockEntryInstr*> worklist(postorder.length()); |
7740 for (BlockIterator it(postorder); !it.Done(); it.Advance()) { | 7739 for (BlockIterator it(postorder); !it.Done(); it.Advance()) { |
7741 BlockEntryInstr* block = it.Current(); | 7740 BlockEntryInstr* block = it.Current(); |
7742 if (block->IsJoinEntry() && block->last_instruction()->IsBranch()) { | 7741 if (block->IsJoinEntry() && block->last_instruction()->IsBranch()) { |
7743 worklist.Add(block); | 7742 worklist.Add(block); |
7744 } | 7743 } |
7745 } | 7744 } |
7746 | 7745 |
7747 // Rewrite until no more instance of the pattern exists. | 7746 // Rewrite until no more instance of the pattern exists. |
(...skipping 10 matching lines...) Expand all Loading... |
7758 // predecessors. Convert the true and false target blocks into join | 7757 // predecessors. Convert the true and false target blocks into join |
7759 // blocks to join the control flows from all of the true | 7758 // blocks to join the control flows from all of the true |
7760 // (respectively, false) targets of the copied branches. | 7759 // (respectively, false) targets of the copied branches. |
7761 // | 7760 // |
7762 // The converted join block will have no phis, so it cannot be another | 7761 // The converted join block will have no phis, so it cannot be another |
7763 // instance of the pattern. There is thus no need to add it to the | 7762 // instance of the pattern. There is thus no need to add it to the |
7764 // worklist. | 7763 // worklist. |
7765 BranchInstr* branch = block->last_instruction()->AsBranch(); | 7764 BranchInstr* branch = block->last_instruction()->AsBranch(); |
7766 ASSERT(branch != NULL); | 7765 ASSERT(branch != NULL); |
7767 JoinEntryInstr* join_true = | 7766 JoinEntryInstr* join_true = |
7768 ToJoinEntry(isolate, branch->true_successor()); | 7767 ToJoinEntry(zone, branch->true_successor()); |
7769 JoinEntryInstr* join_false = | 7768 JoinEntryInstr* join_false = |
7770 ToJoinEntry(isolate, branch->false_successor()); | 7769 ToJoinEntry(zone, branch->false_successor()); |
7771 | 7770 |
7772 ComparisonInstr* comparison = branch->comparison(); | 7771 ComparisonInstr* comparison = branch->comparison(); |
7773 PhiInstr* phi = comparison->left()->definition()->AsPhi(); | 7772 PhiInstr* phi = comparison->left()->definition()->AsPhi(); |
7774 ConstantInstr* constant = comparison->right()->definition()->AsConstant(); | 7773 ConstantInstr* constant = comparison->right()->definition()->AsConstant(); |
7775 ASSERT(constant != NULL); | 7774 ASSERT(constant != NULL); |
7776 // Copy the constant and branch and push it to all the predecessors. | 7775 // Copy the constant and branch and push it to all the predecessors. |
7777 for (intptr_t i = 0, count = block->PredecessorCount(); i < count; ++i) { | 7776 for (intptr_t i = 0, count = block->PredecessorCount(); i < count; ++i) { |
7778 GotoInstr* old_goto = | 7777 GotoInstr* old_goto = |
7779 block->PredecessorAt(i)->last_instruction()->AsGoto(); | 7778 block->PredecessorAt(i)->last_instruction()->AsGoto(); |
7780 ASSERT(old_goto != NULL); | 7779 ASSERT(old_goto != NULL); |
7781 | 7780 |
7782 // Replace the goto in each predecessor with a rewritten branch, | 7781 // Replace the goto in each predecessor with a rewritten branch, |
7783 // rewritten to use the corresponding phi input instead of the phi. | 7782 // rewritten to use the corresponding phi input instead of the phi. |
7784 Value* new_left = phi->InputAt(i)->Copy(isolate); | 7783 Value* new_left = phi->InputAt(i)->Copy(zone); |
7785 Value* new_right = new(isolate) Value(constant); | 7784 Value* new_right = new(zone) Value(constant); |
7786 BranchInstr* new_branch = | 7785 BranchInstr* new_branch = |
7787 CloneBranch(isolate, branch, new_left, new_right); | 7786 CloneBranch(zone, branch, new_left, new_right); |
7788 if (branch->env() == NULL) { | 7787 if (branch->env() == NULL) { |
7789 new_branch->InheritDeoptTarget(isolate, old_goto); | 7788 new_branch->InheritDeoptTarget(zone, old_goto); |
7790 } else { | 7789 } else { |
7791 // Take the environment from the branch if it has one. | 7790 // Take the environment from the branch if it has one. |
7792 new_branch->InheritDeoptTarget(isolate, branch); | 7791 new_branch->InheritDeoptTarget(zone, branch); |
7793 // InheritDeoptTarget gave the new branch's comparison the same | 7792 // InheritDeoptTarget gave the new branch's comparison the same |
7794 // deopt id that it gave the new branch. The id should be the | 7793 // deopt id that it gave the new branch. The id should be the |
7795 // deopt id of the original comparison. | 7794 // deopt id of the original comparison. |
7796 new_branch->comparison()->SetDeoptId(*comparison); | 7795 new_branch->comparison()->SetDeoptId(*comparison); |
7797 // The phi can be used in the branch's environment. Rename such | 7796 // The phi can be used in the branch's environment. Rename such |
7798 // uses. | 7797 // uses. |
7799 for (Environment::DeepIterator it(new_branch->env()); | 7798 for (Environment::DeepIterator it(new_branch->env()); |
7800 !it.Done(); | 7799 !it.Done(); |
7801 it.Advance()) { | 7800 it.Advance()) { |
7802 Value* use = it.CurrentValue(); | 7801 Value* use = it.CurrentValue(); |
(...skipping 12 matching lines...) Expand all Loading... |
7815 | 7814 |
7816 // Update the predecessor block. We may have created another | 7815 // Update the predecessor block. We may have created another |
7817 // instance of the pattern so add it to the worklist if necessary. | 7816 // instance of the pattern so add it to the worklist if necessary. |
7818 BlockEntryInstr* branch_block = new_branch->GetBlock(); | 7817 BlockEntryInstr* branch_block = new_branch->GetBlock(); |
7819 branch_block->set_last_instruction(new_branch); | 7818 branch_block->set_last_instruction(new_branch); |
7820 if (branch_block->IsJoinEntry()) worklist.Add(branch_block); | 7819 if (branch_block->IsJoinEntry()) worklist.Add(branch_block); |
7821 | 7820 |
7822 // Connect the branch to the true and false joins, via empty target | 7821 // Connect the branch to the true and false joins, via empty target |
7823 // blocks. | 7822 // blocks. |
7824 TargetEntryInstr* true_target = | 7823 TargetEntryInstr* true_target = |
7825 new(isolate) TargetEntryInstr(flow_graph->max_block_id() + 1, | 7824 new(zone) TargetEntryInstr(flow_graph->max_block_id() + 1, |
7826 block->try_index()); | 7825 block->try_index()); |
7827 true_target->InheritDeoptTarget(isolate, join_true); | 7826 true_target->InheritDeoptTarget(zone, join_true); |
7828 TargetEntryInstr* false_target = | 7827 TargetEntryInstr* false_target = |
7829 new(isolate) TargetEntryInstr(flow_graph->max_block_id() + 2, | 7828 new(zone) TargetEntryInstr(flow_graph->max_block_id() + 2, |
7830 block->try_index()); | 7829 block->try_index()); |
7831 false_target->InheritDeoptTarget(isolate, join_false); | 7830 false_target->InheritDeoptTarget(zone, join_false); |
7832 flow_graph->set_max_block_id(flow_graph->max_block_id() + 2); | 7831 flow_graph->set_max_block_id(flow_graph->max_block_id() + 2); |
7833 *new_branch->true_successor_address() = true_target; | 7832 *new_branch->true_successor_address() = true_target; |
7834 *new_branch->false_successor_address() = false_target; | 7833 *new_branch->false_successor_address() = false_target; |
7835 GotoInstr* goto_true = new(isolate) GotoInstr(join_true); | 7834 GotoInstr* goto_true = new(zone) GotoInstr(join_true); |
7836 goto_true->InheritDeoptTarget(isolate, join_true); | 7835 goto_true->InheritDeoptTarget(zone, join_true); |
7837 true_target->LinkTo(goto_true); | 7836 true_target->LinkTo(goto_true); |
7838 true_target->set_last_instruction(goto_true); | 7837 true_target->set_last_instruction(goto_true); |
7839 GotoInstr* goto_false = new(isolate) GotoInstr(join_false); | 7838 GotoInstr* goto_false = new(zone) GotoInstr(join_false); |
7840 goto_false->InheritDeoptTarget(isolate, join_false); | 7839 goto_false->InheritDeoptTarget(zone, join_false); |
7841 false_target->LinkTo(goto_false); | 7840 false_target->LinkTo(goto_false); |
7842 false_target->set_last_instruction(goto_false); | 7841 false_target->set_last_instruction(goto_false); |
7843 } | 7842 } |
7844 // When all predecessors have been rewritten, the original block is | 7843 // When all predecessors have been rewritten, the original block is |
7845 // unreachable from the graph. | 7844 // unreachable from the graph. |
7846 phi->UnuseAllInputs(); | 7845 phi->UnuseAllInputs(); |
7847 branch->UnuseAllInputs(); | 7846 branch->UnuseAllInputs(); |
7848 block->UnuseAllInputs(); | 7847 block->UnuseAllInputs(); |
7849 ASSERT(!phi->HasUses()); | 7848 ASSERT(!phi->HasUses()); |
7850 } | 7849 } |
(...skipping 23 matching lines...) Expand all Loading... |
7874 | 7873 |
7875 if ((block->next() == instr) && | 7874 if ((block->next() == instr) && |
7876 (instr->next() == block->last_instruction())) { | 7875 (instr->next() == block->last_instruction())) { |
7877 before->previous()->LinkTo(instr); | 7876 before->previous()->LinkTo(instr); |
7878 instr->LinkTo(before); | 7877 instr->LinkTo(before); |
7879 } | 7878 } |
7880 } | 7879 } |
7881 | 7880 |
7882 | 7881 |
7883 void IfConverter::Simplify(FlowGraph* flow_graph) { | 7882 void IfConverter::Simplify(FlowGraph* flow_graph) { |
7884 Isolate* isolate = flow_graph->isolate(); | 7883 Zone* zone = flow_graph->zone(); |
7885 bool changed = false; | 7884 bool changed = false; |
7886 | 7885 |
7887 const GrowableArray<BlockEntryInstr*>& postorder = flow_graph->postorder(); | 7886 const GrowableArray<BlockEntryInstr*>& postorder = flow_graph->postorder(); |
7888 for (BlockIterator it(postorder); !it.Done(); it.Advance()) { | 7887 for (BlockIterator it(postorder); !it.Done(); it.Advance()) { |
7889 BlockEntryInstr* block = it.Current(); | 7888 BlockEntryInstr* block = it.Current(); |
7890 JoinEntryInstr* join = block->AsJoinEntry(); | 7889 JoinEntryInstr* join = block->AsJoinEntry(); |
7891 | 7890 |
7892 // Detect diamond control flow pattern which materializes a value depending | 7891 // Detect diamond control flow pattern which materializes a value depending |
7893 // on the result of the comparison: | 7892 // on the result of the comparison: |
7894 // | 7893 // |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7929 | 7928 |
7930 // Check if the platform supports efficient branchless IfThenElseInstr | 7929 // Check if the platform supports efficient branchless IfThenElseInstr |
7931 // for the given combination of comparison and values flowing from | 7930 // for the given combination of comparison and values flowing from |
7932 // false and true paths. | 7931 // false and true paths. |
7933 if (IfThenElseInstr::Supports(comparison, v1, v2)) { | 7932 if (IfThenElseInstr::Supports(comparison, v1, v2)) { |
7934 Value* if_true = (pred1 == branch->true_successor()) ? v1 : v2; | 7933 Value* if_true = (pred1 == branch->true_successor()) ? v1 : v2; |
7935 Value* if_false = (pred2 == branch->true_successor()) ? v1 : v2; | 7934 Value* if_false = (pred2 == branch->true_successor()) ? v1 : v2; |
7936 | 7935 |
7937 ComparisonInstr* new_comparison = | 7936 ComparisonInstr* new_comparison = |
7938 comparison->CopyWithNewOperands( | 7937 comparison->CopyWithNewOperands( |
7939 comparison->left()->Copy(isolate), | 7938 comparison->left()->Copy(zone), |
7940 comparison->right()->Copy(isolate)); | 7939 comparison->right()->Copy(zone)); |
7941 IfThenElseInstr* if_then_else = new(isolate) IfThenElseInstr( | 7940 IfThenElseInstr* if_then_else = new(zone) IfThenElseInstr( |
7942 new_comparison, | 7941 new_comparison, |
7943 if_true->Copy(isolate), | 7942 if_true->Copy(zone), |
7944 if_false->Copy(isolate)); | 7943 if_false->Copy(zone)); |
7945 flow_graph->InsertBefore(branch, | 7944 flow_graph->InsertBefore(branch, |
7946 if_then_else, | 7945 if_then_else, |
7947 NULL, | 7946 NULL, |
7948 FlowGraph::kValue); | 7947 FlowGraph::kValue); |
7949 | 7948 |
7950 phi->ReplaceUsesWith(if_then_else); | 7949 phi->ReplaceUsesWith(if_then_else); |
7951 | 7950 |
7952 // Connect IfThenElseInstr to the first instruction in the merge block | 7951 // Connect IfThenElseInstr to the first instruction in the merge block |
7953 // effectively eliminating diamond control flow. | 7952 // effectively eliminating diamond control flow. |
7954 // Current block as well as pred1 and pred2 blocks are no longer in | 7953 // Current block as well as pred1 and pred2 blocks are no longer in |
(...skipping 655 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8610 | 8609 |
8611 // Insert materializations at environment uses. | 8610 // Insert materializations at environment uses. |
8612 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { | 8611 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { |
8613 CreateMaterializationAt( | 8612 CreateMaterializationAt( |
8614 exits_collector_.exits()[i], alloc, *slots); | 8613 exits_collector_.exits()[i], alloc, *slots); |
8615 } | 8614 } |
8616 } | 8615 } |
8617 | 8616 |
8618 | 8617 |
8619 } // namespace dart | 8618 } // namespace dart |
OLD | NEW |