| 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 547 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 558 Instruction* replacement, | 558 Instruction* replacement, |
| 559 FlowGraph* graph) { | 559 FlowGraph* graph) { |
| 560 Definition* current_defn = current->AsDefinition(); | 560 Definition* current_defn = current->AsDefinition(); |
| 561 if ((replacement != NULL) && (current_defn != NULL)) { | 561 if ((replacement != NULL) && (current_defn != NULL)) { |
| 562 Definition* replacement_defn = replacement->AsDefinition(); | 562 Definition* replacement_defn = replacement->AsDefinition(); |
| 563 ASSERT(replacement_defn != NULL); | 563 ASSERT(replacement_defn != NULL); |
| 564 current_defn->ReplaceUsesWith(replacement_defn); | 564 current_defn->ReplaceUsesWith(replacement_defn); |
| 565 EnsureSSATempIndex(graph, current_defn, replacement_defn); | 565 EnsureSSATempIndex(graph, current_defn, replacement_defn); |
| 566 | 566 |
| 567 if (FLAG_trace_optimization) { | 567 if (FLAG_trace_optimization) { |
| 568 OS::Print("Replacing v%" Pd " with v%" Pd "\n", | 568 ISL_Print("Replacing v%" Pd " with v%" Pd "\n", |
| 569 current_defn->ssa_temp_index(), | 569 current_defn->ssa_temp_index(), |
| 570 replacement_defn->ssa_temp_index()); | 570 replacement_defn->ssa_temp_index()); |
| 571 } | 571 } |
| 572 } else if (FLAG_trace_optimization) { | 572 } else if (FLAG_trace_optimization) { |
| 573 if (current_defn == NULL) { | 573 if (current_defn == NULL) { |
| 574 OS::Print("Removing %s\n", current->DebugName()); | 574 ISL_Print("Removing %s\n", current->DebugName()); |
| 575 } else { | 575 } else { |
| 576 ASSERT(!current_defn->HasUses()); | 576 ASSERT(!current_defn->HasUses()); |
| 577 OS::Print("Removing v%" Pd ".\n", current_defn->ssa_temp_index()); | 577 ISL_Print("Removing v%" Pd ".\n", current_defn->ssa_temp_index()); |
| 578 } | 578 } |
| 579 } | 579 } |
| 580 iterator->RemoveCurrentFromGraph(); | 580 iterator->RemoveCurrentFromGraph(); |
| 581 } | 581 } |
| 582 | 582 |
| 583 | 583 |
| 584 bool FlowGraphOptimizer::Canonicalize() { | 584 bool FlowGraphOptimizer::Canonicalize() { |
| 585 bool changed = false; | 585 bool changed = false; |
| 586 for (intptr_t i = 0; i < block_order_.length(); ++i) { | 586 for (intptr_t i = 0; i < block_order_.length(); ++i) { |
| 587 BlockEntryInstr* entry = block_order_[i]; | 587 BlockEntryInstr* entry = block_order_[i]; |
| (...skipping 3844 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4432 Function::Handle(Z, owner.LookupGetterFunction(field_name)); | 4432 Function::Handle(Z, owner.LookupGetterFunction(field_name)); |
| 4433 const Function& setter = | 4433 const Function& setter = |
| 4434 Function::Handle(Z, owner.LookupSetterFunction(field_name)); | 4434 Function::Handle(Z, owner.LookupSetterFunction(field_name)); |
| 4435 bool result = !getter.IsNull() | 4435 bool result = !getter.IsNull() |
| 4436 && !setter.IsNull() | 4436 && !setter.IsNull() |
| 4437 && (setter.usage_counter() > 0) | 4437 && (setter.usage_counter() > 0) |
| 4438 && (FLAG_getter_setter_ratio * setter.usage_counter() >= | 4438 && (FLAG_getter_setter_ratio * setter.usage_counter() >= |
| 4439 getter.usage_counter()); | 4439 getter.usage_counter()); |
| 4440 if (!result) { | 4440 if (!result) { |
| 4441 if (FLAG_trace_optimization) { | 4441 if (FLAG_trace_optimization) { |
| 4442 OS::Print("Disabling unboxing of %s\n", field.ToCString()); | 4442 ISL_Print("Disabling unboxing of %s\n", field.ToCString()); |
| 4443 } | 4443 } |
| 4444 field.set_is_unboxing_candidate(false); | 4444 field.set_is_unboxing_candidate(false); |
| 4445 field.DeoptimizeDependentCode(); | 4445 field.DeoptimizeDependentCode(); |
| 4446 } else { | 4446 } else { |
| 4447 FlowGraph::AddToGuardedFields(flow_graph_->guarded_fields(), &field); | 4447 FlowGraph::AddToGuardedFields(flow_graph_->guarded_fields(), &field); |
| 4448 } | 4448 } |
| 4449 } | 4449 } |
| 4450 } | 4450 } |
| 4451 | 4451 |
| 4452 | 4452 |
| (...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4667 | 4667 |
| 4668 // Worklist used to collect dependency graph. | 4668 // Worklist used to collect dependency graph. |
| 4669 DefinitionWorklist worklist(flow_graph_, candidates.length()); | 4669 DefinitionWorklist worklist(flow_graph_, candidates.length()); |
| 4670 for (intptr_t i = 0; i < candidates.length(); i++) { | 4670 for (intptr_t i = 0; i < candidates.length(); i++) { |
| 4671 BinarySmiOpInstr* op = candidates[i]; | 4671 BinarySmiOpInstr* op = candidates[i]; |
| 4672 if (op->WasEliminated() || processed->Contains(op->ssa_temp_index())) { | 4672 if (op->WasEliminated() || processed->Contains(op->ssa_temp_index())) { |
| 4673 continue; | 4673 continue; |
| 4674 } | 4674 } |
| 4675 | 4675 |
| 4676 if (FLAG_trace_smi_widening) { | 4676 if (FLAG_trace_smi_widening) { |
| 4677 OS::Print("analysing candidate: %s\n", op->ToCString()); | 4677 ISL_Print("analysing candidate: %s\n", op->ToCString()); |
| 4678 } | 4678 } |
| 4679 worklist.Clear(); | 4679 worklist.Clear(); |
| 4680 worklist.Add(op); | 4680 worklist.Add(op); |
| 4681 | 4681 |
| 4682 // Collect dependency graph. Note: more items are added to worklist | 4682 // Collect dependency graph. Note: more items are added to worklist |
| 4683 // inside this loop. | 4683 // inside this loop. |
| 4684 intptr_t gain = 0; | 4684 intptr_t gain = 0; |
| 4685 for (intptr_t j = 0; j < worklist.definitions().length(); j++) { | 4685 for (intptr_t j = 0; j < worklist.definitions().length(); j++) { |
| 4686 Definition* defn = worklist.definitions()[j]; | 4686 Definition* defn = worklist.definitions()[j]; |
| 4687 | 4687 |
| 4688 if (FLAG_trace_smi_widening) { | 4688 if (FLAG_trace_smi_widening) { |
| 4689 OS::Print("> %s\n", defn->ToCString()); | 4689 ISL_Print("> %s\n", defn->ToCString()); |
| 4690 } | 4690 } |
| 4691 | 4691 |
| 4692 if (defn->IsBinarySmiOp() && | 4692 if (defn->IsBinarySmiOp() && |
| 4693 BenefitsFromWidening(defn->AsBinarySmiOp())) { | 4693 BenefitsFromWidening(defn->AsBinarySmiOp())) { |
| 4694 gain++; | 4694 gain++; |
| 4695 if (FLAG_trace_smi_widening) { | 4695 if (FLAG_trace_smi_widening) { |
| 4696 OS::Print("^ [%" Pd "] (o) %s\n", gain, defn->ToCString()); | 4696 ISL_Print("^ [%" Pd "] (o) %s\n", gain, defn->ToCString()); |
| 4697 } | 4697 } |
| 4698 } | 4698 } |
| 4699 | 4699 |
| 4700 const intptr_t defn_loop = loops[defn->GetBlock()->preorder_number()]; | 4700 const intptr_t defn_loop = loops[defn->GetBlock()->preorder_number()]; |
| 4701 | 4701 |
| 4702 // Process all inputs. | 4702 // Process all inputs. |
| 4703 for (intptr_t k = 0; k < defn->InputCount(); k++) { | 4703 for (intptr_t k = 0; k < defn->InputCount(); k++) { |
| 4704 Definition* input = defn->InputAt(k)->definition(); | 4704 Definition* input = defn->InputAt(k)->definition(); |
| 4705 if (input->IsBinarySmiOp() && | 4705 if (input->IsBinarySmiOp() && |
| 4706 CanBeWidened(input->AsBinarySmiOp())) { | 4706 CanBeWidened(input->AsBinarySmiOp())) { |
| 4707 worklist.Add(input); | 4707 worklist.Add(input); |
| 4708 } else if (input->IsPhi() && (input->Type()->ToCid() == kSmiCid)) { | 4708 } else if (input->IsPhi() && (input->Type()->ToCid() == kSmiCid)) { |
| 4709 worklist.Add(input); | 4709 worklist.Add(input); |
| 4710 } else if (input->IsBinaryMintOp()) { | 4710 } else if (input->IsBinaryMintOp()) { |
| 4711 // Mint operation produces untagged result. We avoid tagging. | 4711 // Mint operation produces untagged result. We avoid tagging. |
| 4712 gain++; | 4712 gain++; |
| 4713 if (FLAG_trace_smi_widening) { | 4713 if (FLAG_trace_smi_widening) { |
| 4714 OS::Print("^ [%" Pd "] (i) %s\n", gain, input->ToCString()); | 4714 ISL_Print("^ [%" Pd "] (i) %s\n", gain, input->ToCString()); |
| 4715 } | 4715 } |
| 4716 } else if (defn_loop == loops[input->GetBlock()->preorder_number()] && | 4716 } else if (defn_loop == loops[input->GetBlock()->preorder_number()] && |
| 4717 (input->Type()->ToCid() == kSmiCid)) { | 4717 (input->Type()->ToCid() == kSmiCid)) { |
| 4718 // Input comes from the same loop, is known to be smi and requires | 4718 // Input comes from the same loop, is known to be smi and requires |
| 4719 // untagging. | 4719 // untagging. |
| 4720 // TODO(vegorov) this heuristic assumes that values that are not | 4720 // TODO(vegorov) this heuristic assumes that values that are not |
| 4721 // known to be smi have to be checked and this check can be | 4721 // known to be smi have to be checked and this check can be |
| 4722 // coalesced with untagging. Start coalescing them. | 4722 // coalesced with untagging. Start coalescing them. |
| 4723 gain--; | 4723 gain--; |
| 4724 if (FLAG_trace_smi_widening) { | 4724 if (FLAG_trace_smi_widening) { |
| 4725 OS::Print("v [%" Pd "] (i) %s\n", gain, input->ToCString()); | 4725 ISL_Print("v [%" Pd "] (i) %s\n", gain, input->ToCString()); |
| 4726 } | 4726 } |
| 4727 } | 4727 } |
| 4728 } | 4728 } |
| 4729 | 4729 |
| 4730 // Process all uses. | 4730 // Process all uses. |
| 4731 for (Value* use = defn->input_use_list(); | 4731 for (Value* use = defn->input_use_list(); |
| 4732 use != NULL; | 4732 use != NULL; |
| 4733 use = use->next_use()) { | 4733 use = use->next_use()) { |
| 4734 Instruction* instr = use->instruction(); | 4734 Instruction* instr = use->instruction(); |
| 4735 Definition* use_defn = instr->AsDefinition(); | 4735 Definition* use_defn = instr->AsDefinition(); |
| 4736 if (use_defn == NULL) { | 4736 if (use_defn == NULL) { |
| 4737 // We assume that tagging before returning or pushing argument costs | 4737 // We assume that tagging before returning or pushing argument costs |
| 4738 // very little compared to the cost of the return/call itself. | 4738 // very little compared to the cost of the return/call itself. |
| 4739 if (!instr->IsReturn() && !instr->IsPushArgument()) { | 4739 if (!instr->IsReturn() && !instr->IsPushArgument()) { |
| 4740 gain--; | 4740 gain--; |
| 4741 if (FLAG_trace_smi_widening) { | 4741 if (FLAG_trace_smi_widening) { |
| 4742 OS::Print("v [%" Pd "] (u) %s\n", | 4742 ISL_Print("v [%" Pd "] (u) %s\n", |
| 4743 gain, | 4743 gain, |
| 4744 use->instruction()->ToCString()); | 4744 use->instruction()->ToCString()); |
| 4745 } | 4745 } |
| 4746 } | 4746 } |
| 4747 continue; | 4747 continue; |
| 4748 } else if (use_defn->IsBinarySmiOp() && | 4748 } else if (use_defn->IsBinarySmiOp() && |
| 4749 CanBeWidened(use_defn->AsBinarySmiOp())) { | 4749 CanBeWidened(use_defn->AsBinarySmiOp())) { |
| 4750 worklist.Add(use_defn); | 4750 worklist.Add(use_defn); |
| 4751 } else if (use_defn->IsPhi() && | 4751 } else if (use_defn->IsPhi() && |
| 4752 use_defn->AsPhi()->Type()->ToCid() == kSmiCid) { | 4752 use_defn->AsPhi()->Type()->ToCid() == kSmiCid) { |
| 4753 worklist.Add(use_defn); | 4753 worklist.Add(use_defn); |
| 4754 } else if (use_defn->IsBinaryMintOp()) { | 4754 } else if (use_defn->IsBinaryMintOp()) { |
| 4755 // BinaryMintOp requires untagging of its inputs. | 4755 // BinaryMintOp requires untagging of its inputs. |
| 4756 // Converting kUnboxedInt32 to kUnboxedMint is essentially zero cost | 4756 // Converting kUnboxedInt32 to kUnboxedMint is essentially zero cost |
| 4757 // sign extension operation. | 4757 // sign extension operation. |
| 4758 gain++; | 4758 gain++; |
| 4759 if (FLAG_trace_smi_widening) { | 4759 if (FLAG_trace_smi_widening) { |
| 4760 OS::Print("^ [%" Pd "] (u) %s\n", | 4760 ISL_Print("^ [%" Pd "] (u) %s\n", |
| 4761 gain, | 4761 gain, |
| 4762 use->instruction()->ToCString()); | 4762 use->instruction()->ToCString()); |
| 4763 } | 4763 } |
| 4764 } else if (defn_loop == loops[instr->GetBlock()->preorder_number()]) { | 4764 } else if (defn_loop == loops[instr->GetBlock()->preorder_number()]) { |
| 4765 gain--; | 4765 gain--; |
| 4766 if (FLAG_trace_smi_widening) { | 4766 if (FLAG_trace_smi_widening) { |
| 4767 OS::Print("v [%" Pd "] (u) %s\n", | 4767 ISL_Print("v [%" Pd "] (u) %s\n", |
| 4768 gain, | 4768 gain, |
| 4769 use->instruction()->ToCString()); | 4769 use->instruction()->ToCString()); |
| 4770 } | 4770 } |
| 4771 } | 4771 } |
| 4772 } | 4772 } |
| 4773 } | 4773 } |
| 4774 | 4774 |
| 4775 processed->AddAll(worklist.contains_vector()); | 4775 processed->AddAll(worklist.contains_vector()); |
| 4776 | 4776 |
| 4777 if (FLAG_trace_smi_widening) { | 4777 if (FLAG_trace_smi_widening) { |
| 4778 OS::Print("~ %s gain %" Pd "\n", op->ToCString(), gain); | 4778 ISL_Print("~ %s gain %" Pd "\n", op->ToCString(), gain); |
| 4779 } | 4779 } |
| 4780 | 4780 |
| 4781 if (gain > 0) { | 4781 if (gain > 0) { |
| 4782 // We have positive gain from widening. Convert all BinarySmiOpInstr into | 4782 // We have positive gain from widening. Convert all BinarySmiOpInstr into |
| 4783 // BinaryInt32OpInstr and set representation of all phis to kUnboxedInt32. | 4783 // BinaryInt32OpInstr and set representation of all phis to kUnboxedInt32. |
| 4784 for (intptr_t j = 0; j < worklist.definitions().length(); j++) { | 4784 for (intptr_t j = 0; j < worklist.definitions().length(); j++) { |
| 4785 Definition* defn = worklist.definitions()[j]; | 4785 Definition* defn = worklist.definitions()[j]; |
| 4786 ASSERT(defn->IsPhi() || defn->IsBinarySmiOp()); | 4786 ASSERT(defn->IsPhi() || defn->IsBinarySmiOp()); |
| 4787 | 4787 |
| 4788 if (defn->IsBinarySmiOp()) { | 4788 if (defn->IsBinarySmiOp()) { |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4896 if (current->IsCheckClass()) { | 4896 if (current->IsCheckClass()) { |
| 4897 current->AsCheckClass()->set_licm_hoisted(true); | 4897 current->AsCheckClass()->set_licm_hoisted(true); |
| 4898 } else if (current->IsCheckSmi()) { | 4898 } else if (current->IsCheckSmi()) { |
| 4899 current->AsCheckSmi()->set_licm_hoisted(true); | 4899 current->AsCheckSmi()->set_licm_hoisted(true); |
| 4900 } else if (current->IsCheckEitherNonSmi()) { | 4900 } else if (current->IsCheckEitherNonSmi()) { |
| 4901 current->AsCheckEitherNonSmi()->set_licm_hoisted(true); | 4901 current->AsCheckEitherNonSmi()->set_licm_hoisted(true); |
| 4902 } else if (current->IsCheckArrayBound()) { | 4902 } else if (current->IsCheckArrayBound()) { |
| 4903 current->AsCheckArrayBound()->set_licm_hoisted(true); | 4903 current->AsCheckArrayBound()->set_licm_hoisted(true); |
| 4904 } | 4904 } |
| 4905 if (FLAG_trace_optimization) { | 4905 if (FLAG_trace_optimization) { |
| 4906 OS::Print("Hoisting instruction %s:%" Pd " from B%" Pd " to B%" Pd "\n", | 4906 ISL_Print("Hoisting instruction %s:%" Pd " from B%" Pd " to B%" Pd "\n", |
| 4907 current->DebugName(), | 4907 current->DebugName(), |
| 4908 current->GetDeoptId(), | 4908 current->GetDeoptId(), |
| 4909 current->GetBlock()->block_id(), | 4909 current->GetBlock()->block_id(), |
| 4910 pre_header->block_id()); | 4910 pre_header->block_id()); |
| 4911 } | 4911 } |
| 4912 // Move the instruction out of the loop. | 4912 // Move the instruction out of the loop. |
| 4913 current->RemoveEnvironment(); | 4913 current->RemoveEnvironment(); |
| 4914 if (it != NULL) { | 4914 if (it != NULL) { |
| 4915 it->RemoveCurrentFromGraph(); | 4915 it->RemoveCurrentFromGraph(); |
| 4916 } else { | 4916 } else { |
| (...skipping 796 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5713 Place* LookupCanonical(Place* place) const { | 5713 Place* LookupCanonical(Place* place) const { |
| 5714 return places_map_->Lookup(place); | 5714 return places_map_->Lookup(place); |
| 5715 } | 5715 } |
| 5716 | 5716 |
| 5717 void PrintSet(BitVector* set) { | 5717 void PrintSet(BitVector* set) { |
| 5718 bool comma = false; | 5718 bool comma = false; |
| 5719 for (BitVector::Iterator it(set); | 5719 for (BitVector::Iterator it(set); |
| 5720 !it.Done(); | 5720 !it.Done(); |
| 5721 it.Advance()) { | 5721 it.Advance()) { |
| 5722 if (comma) { | 5722 if (comma) { |
| 5723 OS::Print(", "); | 5723 ISL_Print(", "); |
| 5724 } | 5724 } |
| 5725 OS::Print("%s", places_[it.Current()]->ToCString()); | 5725 ISL_Print("%s", places_[it.Current()]->ToCString()); |
| 5726 comma = true; | 5726 comma = true; |
| 5727 } | 5727 } |
| 5728 } | 5728 } |
| 5729 | 5729 |
| 5730 const PhiPlaceMoves* phi_moves() const { return phi_moves_; } | 5730 const PhiPlaceMoves* phi_moves() const { return phi_moves_; } |
| 5731 | 5731 |
| 5732 void RollbackAliasedIdentites() { | 5732 void RollbackAliasedIdentites() { |
| 5733 for (intptr_t i = 0; i < identity_rollback_.length(); ++i) { | 5733 for (intptr_t i = 0; i < identity_rollback_.length(); ++i) { |
| 5734 identity_rollback_[i]->SetIdentity(AliasIdentity::Unknown()); | 5734 identity_rollback_[i]->SetIdentity(AliasIdentity::Unknown()); |
| 5735 } | 5735 } |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5810 | 5810 |
| 5811 void ComputeKillSets() { | 5811 void ComputeKillSets() { |
| 5812 for (intptr_t i = 0; i < aliases_.length(); ++i) { | 5812 for (intptr_t i = 0; i < aliases_.length(); ++i) { |
| 5813 const Place* alias = aliases_[i]; | 5813 const Place* alias = aliases_[i]; |
| 5814 // Add all representatives to the kill set. | 5814 // Add all representatives to the kill set. |
| 5815 AddAllRepresentatives(alias->id(), alias->id()); | 5815 AddAllRepresentatives(alias->id(), alias->id()); |
| 5816 ComputeKillSet(alias); | 5816 ComputeKillSet(alias); |
| 5817 } | 5817 } |
| 5818 | 5818 |
| 5819 if (FLAG_trace_load_optimization) { | 5819 if (FLAG_trace_load_optimization) { |
| 5820 OS::Print("Aliases KILL sets:\n"); | 5820 ISL_Print("Aliases KILL sets:\n"); |
| 5821 for (intptr_t i = 0; i < aliases_.length(); ++i) { | 5821 for (intptr_t i = 0; i < aliases_.length(); ++i) { |
| 5822 const Place* alias = aliases_[i]; | 5822 const Place* alias = aliases_[i]; |
| 5823 BitVector* kill = GetKilledSet(alias->id()); | 5823 BitVector* kill = GetKilledSet(alias->id()); |
| 5824 | 5824 |
| 5825 OS::Print("%s: ", alias->ToCString()); | 5825 ISL_Print("%s: ", alias->ToCString()); |
| 5826 if (kill != NULL) { | 5826 if (kill != NULL) { |
| 5827 PrintSet(kill); | 5827 PrintSet(kill); |
| 5828 } | 5828 } |
| 5829 OS::Print("\n"); | 5829 ISL_Print("\n"); |
| 5830 } | 5830 } |
| 5831 } | 5831 } |
| 5832 } | 5832 } |
| 5833 | 5833 |
| 5834 void InsertAlias(const Place* alias) { | 5834 void InsertAlias(const Place* alias) { |
| 5835 aliases_map_.Insert(alias); | 5835 aliases_map_.Insert(alias); |
| 5836 aliases_.Add(alias); | 5836 aliases_.Add(alias); |
| 5837 } | 5837 } |
| 5838 | 5838 |
| 5839 const Place* CanonicalizeAlias(const Place& alias) { | 5839 const Place* CanonicalizeAlias(const Place& alias) { |
| (...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6207 PhiPlaceMoves* phi_moves = new(zone) PhiPlaceMoves(); | 6207 PhiPlaceMoves* phi_moves = new(zone) PhiPlaceMoves(); |
| 6208 | 6208 |
| 6209 for (intptr_t i = 0; i < places->length(); i++) { | 6209 for (intptr_t i = 0; i < places->length(); i++) { |
| 6210 Place* place = (*places)[i]; | 6210 Place* place = (*places)[i]; |
| 6211 | 6211 |
| 6212 if (IsPhiDependentPlace(place)) { | 6212 if (IsPhiDependentPlace(place)) { |
| 6213 PhiInstr* phi = place->instance()->AsPhi(); | 6213 PhiInstr* phi = place->instance()->AsPhi(); |
| 6214 BlockEntryInstr* block = phi->GetBlock(); | 6214 BlockEntryInstr* block = phi->GetBlock(); |
| 6215 | 6215 |
| 6216 if (FLAG_trace_optimization) { | 6216 if (FLAG_trace_optimization) { |
| 6217 OS::Print("phi dependent place %s\n", place->ToCString()); | 6217 ISL_Print("phi dependent place %s\n", place->ToCString()); |
| 6218 } | 6218 } |
| 6219 | 6219 |
| 6220 Place input_place(*place); | 6220 Place input_place(*place); |
| 6221 for (intptr_t j = 0; j < phi->InputCount(); j++) { | 6221 for (intptr_t j = 0; j < phi->InputCount(); j++) { |
| 6222 input_place.set_instance(phi->InputAt(j)->definition()); | 6222 input_place.set_instance(phi->InputAt(j)->definition()); |
| 6223 | 6223 |
| 6224 Place* result = map->Lookup(&input_place); | 6224 Place* result = map->Lookup(&input_place); |
| 6225 if (result == NULL) { | 6225 if (result == NULL) { |
| 6226 result = Place::Wrap(zone, input_place, places->length()); | 6226 result = Place::Wrap(zone, input_place, places->length()); |
| 6227 map->Insert(result); | 6227 map->Insert(result); |
| 6228 places->Add(result); | 6228 places->Add(result); |
| 6229 if (FLAG_trace_optimization) { | 6229 if (FLAG_trace_optimization) { |
| 6230 OS::Print(" adding place %s as %" Pd "\n", | 6230 ISL_Print(" adding place %s as %" Pd "\n", |
| 6231 result->ToCString(), | 6231 result->ToCString(), |
| 6232 result->id()); | 6232 result->id()); |
| 6233 } | 6233 } |
| 6234 } | 6234 } |
| 6235 phi_moves->CreateOutgoingMove(isolate, | 6235 phi_moves->CreateOutgoingMove(isolate, |
| 6236 block->PredecessorAt(j), | 6236 block->PredecessorAt(j), |
| 6237 result->id(), | 6237 result->id(), |
| 6238 place->id()); | 6238 place->id()); |
| 6239 } | 6239 } |
| 6240 } | 6240 } |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6276 continue; | 6276 continue; |
| 6277 } | 6277 } |
| 6278 | 6278 |
| 6279 Place* result = map->Lookup(&place); | 6279 Place* result = map->Lookup(&place); |
| 6280 if (result == NULL) { | 6280 if (result == NULL) { |
| 6281 result = Place::Wrap(zone, place, places->length()); | 6281 result = Place::Wrap(zone, place, places->length()); |
| 6282 map->Insert(result); | 6282 map->Insert(result); |
| 6283 places->Add(result); | 6283 places->Add(result); |
| 6284 | 6284 |
| 6285 if (FLAG_trace_optimization) { | 6285 if (FLAG_trace_optimization) { |
| 6286 OS::Print("numbering %s as %" Pd "\n", | 6286 ISL_Print("numbering %s as %" Pd "\n", |
| 6287 result->ToCString(), | 6287 result->ToCString(), |
| 6288 result->id()); | 6288 result->id()); |
| 6289 } | 6289 } |
| 6290 } | 6290 } |
| 6291 | 6291 |
| 6292 instr->set_place_id(result->id()); | 6292 instr->set_place_id(result->id()); |
| 6293 } | 6293 } |
| 6294 } | 6294 } |
| 6295 | 6295 |
| 6296 if ((mode == kOptimizeLoads) && !has_loads) { | 6296 if ((mode == kOptimizeLoads) && !has_loads) { |
| (...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6545 } | 6545 } |
| 6546 | 6546 |
| 6547 const intptr_t place_id = defn->place_id(); | 6547 const intptr_t place_id = defn->place_id(); |
| 6548 if (gen->Contains(place_id)) { | 6548 if (gen->Contains(place_id)) { |
| 6549 // This is a locally redundant load. | 6549 // This is a locally redundant load. |
| 6550 ASSERT((out_values != NULL) && ((*out_values)[place_id] != NULL)); | 6550 ASSERT((out_values != NULL) && ((*out_values)[place_id] != NULL)); |
| 6551 | 6551 |
| 6552 Definition* replacement = (*out_values)[place_id]; | 6552 Definition* replacement = (*out_values)[place_id]; |
| 6553 EnsureSSATempIndex(graph_, defn, replacement); | 6553 EnsureSSATempIndex(graph_, defn, replacement); |
| 6554 if (FLAG_trace_optimization) { | 6554 if (FLAG_trace_optimization) { |
| 6555 OS::Print("Replacing load v%" Pd " with v%" Pd "\n", | 6555 ISL_Print("Replacing load v%" Pd " with v%" Pd "\n", |
| 6556 defn->ssa_temp_index(), | 6556 defn->ssa_temp_index(), |
| 6557 replacement->ssa_temp_index()); | 6557 replacement->ssa_temp_index()); |
| 6558 } | 6558 } |
| 6559 | 6559 |
| 6560 defn->ReplaceUsesWith(replacement); | 6560 defn->ReplaceUsesWith(replacement); |
| 6561 instr_it.RemoveCurrentFromGraph(); | 6561 instr_it.RemoveCurrentFromGraph(); |
| 6562 forwarded_ = true; | 6562 forwarded_ = true; |
| 6563 continue; | 6563 continue; |
| 6564 } else if (!kill->Contains(place_id)) { | 6564 } else if (!kill->Contains(place_id)) { |
| 6565 // This is an exposed load: it is the first representative of a | 6565 // This is an exposed load: it is the first representative of a |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6753 for (intptr_t i = 0; i < phi_moves->length(); i++) { | 6753 for (intptr_t i = 0; i < phi_moves->length(); i++) { |
| 6754 const intptr_t from = (*phi_moves)[i].from(); | 6754 const intptr_t from = (*phi_moves)[i].from(); |
| 6755 const intptr_t to = (*phi_moves)[i].to(); | 6755 const intptr_t to = (*phi_moves)[i].to(); |
| 6756 if (from == to) continue; | 6756 if (from == to) continue; |
| 6757 | 6757 |
| 6758 (*block_out_values)[to] = (*temp_forwarded_values)[to]; | 6758 (*block_out_values)[to] = (*temp_forwarded_values)[to]; |
| 6759 } | 6759 } |
| 6760 } | 6760 } |
| 6761 | 6761 |
| 6762 if (FLAG_trace_load_optimization) { | 6762 if (FLAG_trace_load_optimization) { |
| 6763 OS::Print("B%" Pd "\n", block->block_id()); | 6763 ISL_Print("B%" Pd "\n", block->block_id()); |
| 6764 OS::Print(" IN: "); | 6764 ISL_Print(" IN: "); |
| 6765 aliased_set_->PrintSet(in_[preorder_number]); | 6765 aliased_set_->PrintSet(in_[preorder_number]); |
| 6766 OS::Print("\n"); | 6766 ISL_Print("\n"); |
| 6767 | 6767 |
| 6768 OS::Print(" KILL: "); | 6768 ISL_Print(" KILL: "); |
| 6769 aliased_set_->PrintSet(kill_[preorder_number]); | 6769 aliased_set_->PrintSet(kill_[preorder_number]); |
| 6770 OS::Print("\n"); | 6770 ISL_Print("\n"); |
| 6771 | 6771 |
| 6772 OS::Print(" OUT: "); | 6772 ISL_Print(" OUT: "); |
| 6773 aliased_set_->PrintSet(out_[preorder_number]); | 6773 aliased_set_->PrintSet(out_[preorder_number]); |
| 6774 OS::Print("\n"); | 6774 ISL_Print("\n"); |
| 6775 } | 6775 } |
| 6776 } | 6776 } |
| 6777 | 6777 |
| 6778 // All blocks were visited. Fill pending phis with inputs | 6778 // All blocks were visited. Fill pending phis with inputs |
| 6779 // that flow on back edges. | 6779 // that flow on back edges. |
| 6780 for (intptr_t i = 0; i < pending_phis.length(); i++) { | 6780 for (intptr_t i = 0; i < pending_phis.length(); i++) { |
| 6781 FillPhiInputs(pending_phis[i]); | 6781 FillPhiInputs(pending_phis[i]); |
| 6782 } | 6782 } |
| 6783 } | 6783 } |
| 6784 | 6784 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6817 | 6817 |
| 6818 for (BitVector::Iterator loop_it(header->loop_info()); | 6818 for (BitVector::Iterator loop_it(header->loop_info()); |
| 6819 !loop_it.Done(); | 6819 !loop_it.Done(); |
| 6820 loop_it.Advance()) { | 6820 loop_it.Advance()) { |
| 6821 const intptr_t preorder_number = loop_it.Current(); | 6821 const intptr_t preorder_number = loop_it.Current(); |
| 6822 loop_gen->RemoveAll(kill_[preorder_number]); | 6822 loop_gen->RemoveAll(kill_[preorder_number]); |
| 6823 } | 6823 } |
| 6824 | 6824 |
| 6825 if (FLAG_trace_optimization) { | 6825 if (FLAG_trace_optimization) { |
| 6826 for (BitVector::Iterator it(loop_gen); !it.Done(); it.Advance()) { | 6826 for (BitVector::Iterator it(loop_gen); !it.Done(); it.Advance()) { |
| 6827 OS::Print("place %s is loop invariant for B%" Pd "\n", | 6827 ISL_Print("place %s is loop invariant for B%" Pd "\n", |
| 6828 aliased_set_->places()[it.Current()]->ToCString(), | 6828 aliased_set_->places()[it.Current()]->ToCString(), |
| 6829 header->block_id()); | 6829 header->block_id()); |
| 6830 } | 6830 } |
| 6831 } | 6831 } |
| 6832 | 6832 |
| 6833 invariant_loads->Add(loop_gen); | 6833 invariant_loads->Add(loop_gen); |
| 6834 } | 6834 } |
| 6835 | 6835 |
| 6836 graph_->set_loop_invariant_loads(invariant_loads); | 6836 graph_->set_loop_invariant_loads(invariant_loads); |
| 6837 } | 6837 } |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6888 Definition* replacement = (*pred_out_values)[place_id]->Replacement(); | 6888 Definition* replacement = (*pred_out_values)[place_id]->Replacement(); |
| 6889 Value* input = new(Z) Value(replacement); | 6889 Value* input = new(Z) Value(replacement); |
| 6890 phi->SetInputAt(i, input); | 6890 phi->SetInputAt(i, input); |
| 6891 replacement->AddInputUse(input); | 6891 replacement->AddInputUse(input); |
| 6892 } | 6892 } |
| 6893 | 6893 |
| 6894 phi->set_ssa_temp_index(graph_->alloc_ssa_temp_index()); | 6894 phi->set_ssa_temp_index(graph_->alloc_ssa_temp_index()); |
| 6895 phis_.Add(phi); // Postpone phi insertion until after load forwarding. | 6895 phis_.Add(phi); // Postpone phi insertion until after load forwarding. |
| 6896 | 6896 |
| 6897 if (FLAG_trace_load_optimization) { | 6897 if (FLAG_trace_load_optimization) { |
| 6898 OS::Print("created pending phi %s for %s at B%" Pd "\n", | 6898 ISL_Print("created pending phi %s for %s at B%" Pd "\n", |
| 6899 phi->ToCString(), | 6899 phi->ToCString(), |
| 6900 aliased_set_->places()[place_id]->ToCString(), | 6900 aliased_set_->places()[place_id]->ToCString(), |
| 6901 block->block_id()); | 6901 block->block_id()); |
| 6902 } | 6902 } |
| 6903 } | 6903 } |
| 6904 | 6904 |
| 6905 // Iterate over basic blocks and replace exposed loads with incoming | 6905 // Iterate over basic blocks and replace exposed loads with incoming |
| 6906 // values. | 6906 // values. |
| 6907 void ForwardLoads() { | 6907 void ForwardLoads() { |
| 6908 for (BlockIterator block_it = graph_->reverse_postorder_iterator(); | 6908 for (BlockIterator block_it = graph_->reverse_postorder_iterator(); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 6927 // they might contain values that were replace and removed | 6927 // they might contain values that were replace and removed |
| 6928 // from the graph by this iteration. | 6928 // from the graph by this iteration. |
| 6929 // To prevent using them we additionally mark definitions themselves | 6929 // To prevent using them we additionally mark definitions themselves |
| 6930 // as replaced and store a pointer to the replacement. | 6930 // as replaced and store a pointer to the replacement. |
| 6931 replacement = replacement->Replacement(); | 6931 replacement = replacement->Replacement(); |
| 6932 | 6932 |
| 6933 if (load != replacement) { | 6933 if (load != replacement) { |
| 6934 EnsureSSATempIndex(graph_, load, replacement); | 6934 EnsureSSATempIndex(graph_, load, replacement); |
| 6935 | 6935 |
| 6936 if (FLAG_trace_optimization) { | 6936 if (FLAG_trace_optimization) { |
| 6937 OS::Print("Replacing load v%" Pd " with v%" Pd "\n", | 6937 ISL_Print("Replacing load v%" Pd " with v%" Pd "\n", |
| 6938 load->ssa_temp_index(), | 6938 load->ssa_temp_index(), |
| 6939 replacement->ssa_temp_index()); | 6939 replacement->ssa_temp_index()); |
| 6940 } | 6940 } |
| 6941 | 6941 |
| 6942 load->ReplaceUsesWith(replacement); | 6942 load->ReplaceUsesWith(replacement); |
| 6943 load->RemoveFromGraph(); | 6943 load->RemoveFromGraph(); |
| 6944 load->SetReplacement(replacement); | 6944 load->SetReplacement(replacement); |
| 6945 forwarded_ = true; | 6945 forwarded_ = true; |
| 6946 } | 6946 } |
| 6947 } | 6947 } |
| (...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7116 if (!a->IsPhi()) { | 7116 if (!a->IsPhi()) { |
| 7117 if (Dominates(a, b)) { | 7117 if (Dominates(a, b)) { |
| 7118 Definition* t = a; | 7118 Definition* t = a; |
| 7119 a = b; | 7119 a = b; |
| 7120 b = t; | 7120 b = t; |
| 7121 } | 7121 } |
| 7122 ASSERT(Dominates(b, a)); | 7122 ASSERT(Dominates(b, a)); |
| 7123 } | 7123 } |
| 7124 | 7124 |
| 7125 if (FLAG_trace_load_optimization) { | 7125 if (FLAG_trace_load_optimization) { |
| 7126 OS::Print("Replacing %s with congruent %s\n", | 7126 ISL_Print("Replacing %s with congruent %s\n", |
| 7127 a->ToCString(), | 7127 a->ToCString(), |
| 7128 b->ToCString()); | 7128 b->ToCString()); |
| 7129 } | 7129 } |
| 7130 | 7130 |
| 7131 a->ReplaceUsesWith(b); | 7131 a->ReplaceUsesWith(b); |
| 7132 if (a->IsPhi()) { | 7132 if (a->IsPhi()) { |
| 7133 // We might be replacing a phi introduced by the load forwarding | 7133 // We might be replacing a phi introduced by the load forwarding |
| 7134 // that is not inserted in the graph yet. | 7134 // that is not inserted in the graph yet. |
| 7135 ASSERT(b->IsPhi()); | 7135 ASSERT(b->IsPhi()); |
| 7136 PhiInstr* phi_a = a->AsPhi(); | 7136 PhiInstr* phi_a = a->AsPhi(); |
| (...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7322 // Loads/stores of final fields do not participate. | 7322 // Loads/stores of final fields do not participate. |
| 7323 continue; | 7323 continue; |
| 7324 } | 7324 } |
| 7325 | 7325 |
| 7326 // Handle stores. | 7326 // Handle stores. |
| 7327 if (is_store) { | 7327 if (is_store) { |
| 7328 if (kill->Contains(instr->place_id())) { | 7328 if (kill->Contains(instr->place_id())) { |
| 7329 if (!live_in->Contains(instr->place_id()) && | 7329 if (!live_in->Contains(instr->place_id()) && |
| 7330 CanEliminateStore(instr)) { | 7330 CanEliminateStore(instr)) { |
| 7331 if (FLAG_trace_optimization) { | 7331 if (FLAG_trace_optimization) { |
| 7332 OS::Print( | 7332 ISL_Print( |
| 7333 "Removing dead store to place %" Pd " in block B%" Pd "\n", | 7333 "Removing dead store to place %" Pd " in block B%" Pd "\n", |
| 7334 instr->place_id(), block->block_id()); | 7334 instr->place_id(), block->block_id()); |
| 7335 } | 7335 } |
| 7336 instr_it.RemoveCurrentFromGraph(); | 7336 instr_it.RemoveCurrentFromGraph(); |
| 7337 } | 7337 } |
| 7338 } else if (!live_in->Contains(instr->place_id())) { | 7338 } else if (!live_in->Contains(instr->place_id())) { |
| 7339 // Mark this store as down-ward exposed: They are the only | 7339 // Mark this store as down-ward exposed: They are the only |
| 7340 // candidates for the global store elimination. | 7340 // candidates for the global store elimination. |
| 7341 if (exposed_stores == NULL) { | 7341 if (exposed_stores == NULL) { |
| 7342 const intptr_t kMaxExposedStoresInitialSize = 5; | 7342 const intptr_t kMaxExposedStoresInitialSize = 5; |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7375 if ((defn != NULL) && IsLoadEliminationCandidate(defn)) { | 7375 if ((defn != NULL) && IsLoadEliminationCandidate(defn)) { |
| 7376 const intptr_t alias = aliased_set_->LookupAliasId(place.ToAlias()); | 7376 const intptr_t alias = aliased_set_->LookupAliasId(place.ToAlias()); |
| 7377 live_in->AddAll(aliased_set_->GetKilledSet(alias)); | 7377 live_in->AddAll(aliased_set_->GetKilledSet(alias)); |
| 7378 continue; | 7378 continue; |
| 7379 } | 7379 } |
| 7380 } | 7380 } |
| 7381 exposed_stores_[postorder_number] = exposed_stores; | 7381 exposed_stores_[postorder_number] = exposed_stores; |
| 7382 } | 7382 } |
| 7383 if (FLAG_trace_load_optimization) { | 7383 if (FLAG_trace_load_optimization) { |
| 7384 Dump(); | 7384 Dump(); |
| 7385 OS::Print("---\n"); | 7385 ISL_Print("---\n"); |
| 7386 } | 7386 } |
| 7387 } | 7387 } |
| 7388 | 7388 |
| 7389 void EliminateDeadStores() { | 7389 void EliminateDeadStores() { |
| 7390 // Iteration order does not matter here. | 7390 // Iteration order does not matter here. |
| 7391 for (BlockIterator block_it = graph_->postorder_iterator(); | 7391 for (BlockIterator block_it = graph_->postorder_iterator(); |
| 7392 !block_it.Done(); | 7392 !block_it.Done(); |
| 7393 block_it.Advance()) { | 7393 block_it.Advance()) { |
| 7394 BlockEntryInstr* block = block_it.Current(); | 7394 BlockEntryInstr* block = block_it.Current(); |
| 7395 const intptr_t postorder_number = block->postorder_number(); | 7395 const intptr_t postorder_number = block->postorder_number(); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 7409 ASSERT(!is_load && is_store); | 7409 ASSERT(!is_load && is_store); |
| 7410 if (place.IsFinalField()) { | 7410 if (place.IsFinalField()) { |
| 7411 // Final field do not participate in dead store elimination. | 7411 // Final field do not participate in dead store elimination. |
| 7412 continue; | 7412 continue; |
| 7413 } | 7413 } |
| 7414 // Eliminate a downward exposed store if the corresponding place is not | 7414 // Eliminate a downward exposed store if the corresponding place is not |
| 7415 // in live-out. | 7415 // in live-out. |
| 7416 if (!live_out->Contains(instr->place_id()) && | 7416 if (!live_out->Contains(instr->place_id()) && |
| 7417 CanEliminateStore(instr)) { | 7417 CanEliminateStore(instr)) { |
| 7418 if (FLAG_trace_optimization) { | 7418 if (FLAG_trace_optimization) { |
| 7419 OS::Print("Removing dead store to place %" Pd " block B%" Pd "\n", | 7419 ISL_Print("Removing dead store to place %" Pd " block B%" Pd "\n", |
| 7420 instr->place_id(), block->block_id()); | 7420 instr->place_id(), block->block_id()); |
| 7421 } | 7421 } |
| 7422 instr->RemoveFromGraph(/* ignored */ false); | 7422 instr->RemoveFromGraph(/* ignored */ false); |
| 7423 } | 7423 } |
| 7424 } | 7424 } |
| 7425 } | 7425 } |
| 7426 } | 7426 } |
| 7427 | 7427 |
| 7428 FlowGraph* graph_; | 7428 FlowGraph* graph_; |
| 7429 DirectChainedHashMap<PointerKeyValueTrait<Place> >* map_; | 7429 DirectChainedHashMap<PointerKeyValueTrait<Place> >* map_; |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7503 // Eliminate dead phis and compact the phis_ array of the block. | 7503 // Eliminate dead phis and compact the phis_ array of the block. |
| 7504 intptr_t to_index = 0; | 7504 intptr_t to_index = 0; |
| 7505 for (intptr_t i = 0; i < join->phis_->length(); ++i) { | 7505 for (intptr_t i = 0; i < join->phis_->length(); ++i) { |
| 7506 PhiInstr* phi = (*join->phis_)[i]; | 7506 PhiInstr* phi = (*join->phis_)[i]; |
| 7507 if (phi != NULL) { | 7507 if (phi != NULL) { |
| 7508 if (!phi->is_alive()) { | 7508 if (!phi->is_alive()) { |
| 7509 phi->ReplaceUsesWith(flow_graph->constant_null()); | 7509 phi->ReplaceUsesWith(flow_graph->constant_null()); |
| 7510 phi->UnuseAllInputs(); | 7510 phi->UnuseAllInputs(); |
| 7511 (*join->phis_)[i] = NULL; | 7511 (*join->phis_)[i] = NULL; |
| 7512 if (FLAG_trace_optimization) { | 7512 if (FLAG_trace_optimization) { |
| 7513 OS::Print("Removing dead phi v%" Pd "\n", phi->ssa_temp_index()); | 7513 ISL_Print("Removing dead phi v%" Pd "\n", phi->ssa_temp_index()); |
| 7514 } | 7514 } |
| 7515 } else if (phi->IsRedundant()) { | 7515 } else if (phi->IsRedundant()) { |
| 7516 phi->ReplaceUsesWith(phi->InputAt(0)->definition()); | 7516 phi->ReplaceUsesWith(phi->InputAt(0)->definition()); |
| 7517 phi->UnuseAllInputs(); | 7517 phi->UnuseAllInputs(); |
| 7518 (*join->phis_)[i] = NULL; | 7518 (*join->phis_)[i] = NULL; |
| 7519 if (FLAG_trace_optimization) { | 7519 if (FLAG_trace_optimization) { |
| 7520 OS::Print("Removing redundant phi v%" Pd "\n", | 7520 ISL_Print("Removing redundant phi v%" Pd "\n", |
| 7521 phi->ssa_temp_index()); | 7521 phi->ssa_temp_index()); |
| 7522 } | 7522 } |
| 7523 } else { | 7523 } else { |
| 7524 (*join->phis_)[to_index++] = phi; | 7524 (*join->phis_)[to_index++] = phi; |
| 7525 } | 7525 } |
| 7526 } | 7526 } |
| 7527 } | 7527 } |
| 7528 if (to_index == 0) { | 7528 if (to_index == 0) { |
| 7529 join->phis_ = NULL; | 7529 join->phis_ = NULL; |
| 7530 } else { | 7530 } else { |
| (...skipping 522 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8053 // deoptimization exit. So candidate should only be used in StoreInstanceField | 8053 // deoptimization exit. So candidate should only be used in StoreInstanceField |
| 8054 // instructions that write into fields of the allocated object. | 8054 // instructions that write into fields of the allocated object. |
| 8055 // We do not support materialization of the object that has type arguments. | 8055 // We do not support materialization of the object that has type arguments. |
| 8056 static bool IsAllocationSinkingCandidate(Definition* alloc, | 8056 static bool IsAllocationSinkingCandidate(Definition* alloc, |
| 8057 SafeUseCheck check_type) { | 8057 SafeUseCheck check_type) { |
| 8058 for (Value* use = alloc->input_use_list(); | 8058 for (Value* use = alloc->input_use_list(); |
| 8059 use != NULL; | 8059 use != NULL; |
| 8060 use = use->next_use()) { | 8060 use = use->next_use()) { |
| 8061 if (!IsSafeUse(use, check_type)) { | 8061 if (!IsSafeUse(use, check_type)) { |
| 8062 if (FLAG_trace_optimization) { | 8062 if (FLAG_trace_optimization) { |
| 8063 OS::Print("use of %s at %s is unsafe for allocation sinking\n", | 8063 ISL_Print("use of %s at %s is unsafe for allocation sinking\n", |
| 8064 alloc->ToCString(), | 8064 alloc->ToCString(), |
| 8065 use->instruction()->ToCString()); | 8065 use->instruction()->ToCString()); |
| 8066 } | 8066 } |
| 8067 return false; | 8067 return false; |
| 8068 } | 8068 } |
| 8069 } | 8069 } |
| 8070 | 8070 |
| 8071 return true; | 8071 return true; |
| 8072 } | 8072 } |
| 8073 | 8073 |
| 8074 | 8074 |
| 8075 // If the given use is a store into an object then return an object we are | 8075 // If the given use is a store into an object then return an object we are |
| 8076 // storing into. | 8076 // storing into. |
| 8077 static Definition* StoreInto(Value* use) { | 8077 static Definition* StoreInto(Value* use) { |
| 8078 StoreInstanceFieldInstr* store = use->instruction()->AsStoreInstanceField(); | 8078 StoreInstanceFieldInstr* store = use->instruction()->AsStoreInstanceField(); |
| 8079 if (store != NULL) { | 8079 if (store != NULL) { |
| 8080 return store->instance()->definition(); | 8080 return store->instance()->definition(); |
| 8081 } | 8081 } |
| 8082 | 8082 |
| 8083 return NULL; | 8083 return NULL; |
| 8084 } | 8084 } |
| 8085 | 8085 |
| 8086 | 8086 |
| 8087 // Remove the given allocation from the graph. It is not observable. | 8087 // Remove the given allocation from the graph. It is not observable. |
| 8088 // If deoptimization occurs the object will be materialized. | 8088 // If deoptimization occurs the object will be materialized. |
| 8089 void AllocationSinking::EliminateAllocation(Definition* alloc) { | 8089 void AllocationSinking::EliminateAllocation(Definition* alloc) { |
| 8090 ASSERT(IsAllocationSinkingCandidate(alloc, kStrictCheck)); | 8090 ASSERT(IsAllocationSinkingCandidate(alloc, kStrictCheck)); |
| 8091 | 8091 |
| 8092 if (FLAG_trace_optimization) { | 8092 if (FLAG_trace_optimization) { |
| 8093 OS::Print("removing allocation from the graph: v%" Pd "\n", | 8093 ISL_Print("removing allocation from the graph: v%" Pd "\n", |
| 8094 alloc->ssa_temp_index()); | 8094 alloc->ssa_temp_index()); |
| 8095 } | 8095 } |
| 8096 | 8096 |
| 8097 // As an allocation sinking candidate it is only used in stores to its own | 8097 // As an allocation sinking candidate it is only used in stores to its own |
| 8098 // fields. Remove these stores. | 8098 // fields. Remove these stores. |
| 8099 for (Value* use = alloc->input_use_list(); | 8099 for (Value* use = alloc->input_use_list(); |
| 8100 use != NULL; | 8100 use != NULL; |
| 8101 use = alloc->input_use_list()) { | 8101 use = alloc->input_use_list()) { |
| 8102 use->instruction()->RemoveFromGraph(); | 8102 use->instruction()->RemoveFromGraph(); |
| 8103 } | 8103 } |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8164 } | 8164 } |
| 8165 } | 8165 } |
| 8166 } while (changed); | 8166 } while (changed); |
| 8167 | 8167 |
| 8168 // Shrink the list of candidates removing all unmarked ones. | 8168 // Shrink the list of candidates removing all unmarked ones. |
| 8169 intptr_t j = 0; | 8169 intptr_t j = 0; |
| 8170 for (intptr_t i = 0; i < candidates_.length(); i++) { | 8170 for (intptr_t i = 0; i < candidates_.length(); i++) { |
| 8171 Definition* alloc = candidates_[i]; | 8171 Definition* alloc = candidates_[i]; |
| 8172 if (alloc->Identity().IsAllocationSinkingCandidate()) { | 8172 if (alloc->Identity().IsAllocationSinkingCandidate()) { |
| 8173 if (FLAG_trace_optimization) { | 8173 if (FLAG_trace_optimization) { |
| 8174 OS::Print("discovered allocation sinking candidate: v%" Pd "\n", | 8174 ISL_Print("discovered allocation sinking candidate: v%" Pd "\n", |
| 8175 alloc->ssa_temp_index()); | 8175 alloc->ssa_temp_index()); |
| 8176 } | 8176 } |
| 8177 | 8177 |
| 8178 if (j != i) { | 8178 if (j != i) { |
| 8179 candidates_[j] = alloc; | 8179 candidates_[j] = alloc; |
| 8180 } | 8180 } |
| 8181 j++; | 8181 j++; |
| 8182 } | 8182 } |
| 8183 } | 8183 } |
| 8184 candidates_.TruncateTo(j); | 8184 candidates_.TruncateTo(j); |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8259 } | 8259 } |
| 8260 } | 8260 } |
| 8261 } while (changed); | 8261 } while (changed); |
| 8262 | 8262 |
| 8263 // Remove all failed candidates from the candidates list. | 8263 // Remove all failed candidates from the candidates list. |
| 8264 intptr_t j = 0; | 8264 intptr_t j = 0; |
| 8265 for (intptr_t i = 0; i < candidates_.length(); i++) { | 8265 for (intptr_t i = 0; i < candidates_.length(); i++) { |
| 8266 Definition* alloc = candidates_[i]; | 8266 Definition* alloc = candidates_[i]; |
| 8267 if (!alloc->Identity().IsAllocationSinkingCandidate()) { | 8267 if (!alloc->Identity().IsAllocationSinkingCandidate()) { |
| 8268 if (FLAG_trace_optimization) { | 8268 if (FLAG_trace_optimization) { |
| 8269 OS::Print("allocation v%" Pd " can't be eliminated\n", | 8269 ISL_Print("allocation v%" Pd " can't be eliminated\n", |
| 8270 alloc->ssa_temp_index()); | 8270 alloc->ssa_temp_index()); |
| 8271 } | 8271 } |
| 8272 | 8272 |
| 8273 #ifdef DEBUG | 8273 #ifdef DEBUG |
| 8274 for (Value* use = alloc->env_use_list(); | 8274 for (Value* use = alloc->env_use_list(); |
| 8275 use != NULL; | 8275 use != NULL; |
| 8276 use = use->next_use()) { | 8276 use = use->next_use()) { |
| 8277 ASSERT(use->instruction()->IsMaterializeObject()); | 8277 ASSERT(use->instruction()->IsMaterializeObject()); |
| 8278 } | 8278 } |
| 8279 #endif | 8279 #endif |
| (...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8608 | 8608 |
| 8609 // Insert materializations at environment uses. | 8609 // Insert materializations at environment uses. |
| 8610 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { | 8610 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { |
| 8611 CreateMaterializationAt( | 8611 CreateMaterializationAt( |
| 8612 exits_collector_.exits()[i], alloc, *slots); | 8612 exits_collector_.exits()[i], alloc, *slots); |
| 8613 } | 8613 } |
| 8614 } | 8614 } |
| 8615 | 8615 |
| 8616 | 8616 |
| 8617 } // namespace dart | 8617 } // namespace dart |
| OLD | NEW |