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

Side by Side Diff: runtime/vm/flow_graph_optimizer.cc

Issue 982873004: Thread/Isolate refactoring: new(Isolate) -> new(Zone) (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 5 years, 9 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/flow_graph_range_analysis.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/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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_optimizer.h ('k') | runtime/vm/flow_graph_range_analysis.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698