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/compiler.h" | 9 #include "vm/compiler.h" |
10 #include "vm/cpu.h" | 10 #include "vm/cpu.h" |
(...skipping 619 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
630 Instruction* replacement, | 630 Instruction* replacement, |
631 FlowGraph* graph) { | 631 FlowGraph* graph) { |
632 Definition* current_defn = current->AsDefinition(); | 632 Definition* current_defn = current->AsDefinition(); |
633 if ((replacement != NULL) && (current_defn != NULL)) { | 633 if ((replacement != NULL) && (current_defn != NULL)) { |
634 Definition* replacement_defn = replacement->AsDefinition(); | 634 Definition* replacement_defn = replacement->AsDefinition(); |
635 ASSERT(replacement_defn != NULL); | 635 ASSERT(replacement_defn != NULL); |
636 current_defn->ReplaceUsesWith(replacement_defn); | 636 current_defn->ReplaceUsesWith(replacement_defn); |
637 EnsureSSATempIndex(graph, current_defn, replacement_defn); | 637 EnsureSSATempIndex(graph, current_defn, replacement_defn); |
638 | 638 |
639 if (FLAG_trace_optimization) { | 639 if (FLAG_trace_optimization) { |
640 ISL_Print("Replacing v%" Pd " with v%" Pd "\n", | 640 THR_Print("Replacing v%" Pd " with v%" Pd "\n", |
641 current_defn->ssa_temp_index(), | 641 current_defn->ssa_temp_index(), |
642 replacement_defn->ssa_temp_index()); | 642 replacement_defn->ssa_temp_index()); |
643 } | 643 } |
644 } else if (FLAG_trace_optimization) { | 644 } else if (FLAG_trace_optimization) { |
645 if (current_defn == NULL) { | 645 if (current_defn == NULL) { |
646 ISL_Print("Removing %s\n", current->DebugName()); | 646 THR_Print("Removing %s\n", current->DebugName()); |
647 } else { | 647 } else { |
648 ASSERT(!current_defn->HasUses()); | 648 ASSERT(!current_defn->HasUses()); |
649 ISL_Print("Removing v%" Pd ".\n", current_defn->ssa_temp_index()); | 649 THR_Print("Removing v%" Pd ".\n", current_defn->ssa_temp_index()); |
650 } | 650 } |
651 } | 651 } |
652 iterator->RemoveCurrentFromGraph(); | 652 iterator->RemoveCurrentFromGraph(); |
653 } | 653 } |
654 | 654 |
655 | 655 |
656 bool FlowGraphOptimizer::Canonicalize() { | 656 bool FlowGraphOptimizer::Canonicalize() { |
657 bool changed = false; | 657 bool changed = false; |
658 for (intptr_t i = 0; i < block_order_.length(); ++i) { | 658 for (intptr_t i = 0; i < block_order_.length(); ++i) { |
659 BlockEntryInstr* entry = block_order_[i]; | 659 BlockEntryInstr* entry = block_order_[i]; |
(...skipping 1670 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2330 const Function& function = flow_graph_->function(); | 2330 const Function& function = flow_graph_->function(); |
2331 if (function.IsDynamicFunction() && | 2331 if (function.IsDynamicFunction() && |
2332 callee_receiver->IsParameter() && | 2332 callee_receiver->IsParameter() && |
2333 (callee_receiver->AsParameter()->index() == 0)) { | 2333 (callee_receiver->AsParameter()->index() == 0)) { |
2334 const String& name = (kind == RawFunction::kMethodExtractor) | 2334 const String& name = (kind == RawFunction::kMethodExtractor) |
2335 ? String::Handle(Z, Field::NameFromGetter(call->function_name())) | 2335 ? String::Handle(Z, Field::NameFromGetter(call->function_name())) |
2336 : call->function_name(); | 2336 : call->function_name(); |
2337 const Class& cls = Class::Handle(Z, function.Owner()); | 2337 const Class& cls = Class::Handle(Z, function.Owner()); |
2338 if (!thread()->cha()->HasOverride(cls, name)) { | 2338 if (!thread()->cha()->HasOverride(cls, name)) { |
2339 if (FLAG_trace_cha) { | 2339 if (FLAG_trace_cha) { |
2340 ISL_Print(" **(CHA) Instance call needs no check, " | 2340 THR_Print(" **(CHA) Instance call needs no check, " |
2341 "no overrides of '%s' '%s'\n", | 2341 "no overrides of '%s' '%s'\n", |
2342 name.ToCString(), cls.ToCString()); | 2342 name.ToCString(), cls.ToCString()); |
2343 } | 2343 } |
2344 thread()->cha()->AddToLeafClasses(cls); | 2344 thread()->cha()->AddToLeafClasses(cls); |
2345 return false; | 2345 return false; |
2346 } | 2346 } |
2347 } | 2347 } |
2348 return true; | 2348 return true; |
2349 } | 2349 } |
2350 | 2350 |
(...skipping 1678 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4029 if (CHA::IsImplemented(type_class)) return false; | 4029 if (CHA::IsImplemented(type_class)) return false; |
4030 // Check if there are subclasses. | 4030 // Check if there are subclasses. |
4031 if (CHA::HasSubclasses(type_class)) { | 4031 if (CHA::HasSubclasses(type_class)) { |
4032 return false; | 4032 return false; |
4033 } | 4033 } |
4034 | 4034 |
4035 // Private classes cannot be subclassed by later loaded libs. | 4035 // Private classes cannot be subclassed by later loaded libs. |
4036 if (!type_class.IsPrivate()) { | 4036 if (!type_class.IsPrivate()) { |
4037 if (FLAG_use_cha_deopt) { | 4037 if (FLAG_use_cha_deopt) { |
4038 if (FLAG_trace_cha) { | 4038 if (FLAG_trace_cha) { |
4039 ISL_Print(" **(CHA) Typecheck as class equality since no " | 4039 THR_Print(" **(CHA) Typecheck as class equality since no " |
4040 "subclasses: %s\n", | 4040 "subclasses: %s\n", |
4041 type_class.ToCString()); | 4041 type_class.ToCString()); |
4042 } | 4042 } |
4043 thread()->cha()->AddToLeafClasses(type_class); | 4043 thread()->cha()->AddToLeafClasses(type_class); |
4044 } else { | 4044 } else { |
4045 return false; | 4045 return false; |
4046 } | 4046 } |
4047 } | 4047 } |
4048 const intptr_t num_type_args = type_class.NumTypeArguments(); | 4048 const intptr_t num_type_args = type_class.NumTypeArguments(); |
4049 if (num_type_args > 0) { | 4049 if (num_type_args > 0) { |
(...skipping 563 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4613 if (field.is_double_initialized()) { | 4613 if (field.is_double_initialized()) { |
4614 unboxed_field = true; | 4614 unboxed_field = true; |
4615 } else if ((setter.usage_counter() > 0) && | 4615 } else if ((setter.usage_counter() > 0) && |
4616 ((FLAG_getter_setter_ratio * setter.usage_counter()) >= | 4616 ((FLAG_getter_setter_ratio * setter.usage_counter()) >= |
4617 getter.usage_counter())) { | 4617 getter.usage_counter())) { |
4618 unboxed_field = true; | 4618 unboxed_field = true; |
4619 } | 4619 } |
4620 } | 4620 } |
4621 if (!unboxed_field) { | 4621 if (!unboxed_field) { |
4622 if (FLAG_trace_optimization || FLAG_trace_field_guards) { | 4622 if (FLAG_trace_optimization || FLAG_trace_field_guards) { |
4623 ISL_Print("Disabling unboxing of %s\n", field.ToCString()); | 4623 THR_Print("Disabling unboxing of %s\n", field.ToCString()); |
4624 if (!setter.IsNull()) { | 4624 if (!setter.IsNull()) { |
4625 OS::Print(" setter usage count: %" Pd "\n", setter.usage_counter()); | 4625 OS::Print(" setter usage count: %" Pd "\n", setter.usage_counter()); |
4626 } | 4626 } |
4627 if (!getter.IsNull()) { | 4627 if (!getter.IsNull()) { |
4628 OS::Print(" getter usage count: %" Pd "\n", getter.usage_counter()); | 4628 OS::Print(" getter usage count: %" Pd "\n", getter.usage_counter()); |
4629 } | 4629 } |
4630 } | 4630 } |
4631 field.set_is_unboxing_candidate(false); | 4631 field.set_is_unboxing_candidate(false); |
4632 field.DeoptimizeDependentCode(); | 4632 field.DeoptimizeDependentCode(); |
4633 } else { | 4633 } else { |
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4842 | 4842 |
4843 // Worklist used to collect dependency graph. | 4843 // Worklist used to collect dependency graph. |
4844 DefinitionWorklist worklist(flow_graph_, candidates.length()); | 4844 DefinitionWorklist worklist(flow_graph_, candidates.length()); |
4845 for (intptr_t i = 0; i < candidates.length(); i++) { | 4845 for (intptr_t i = 0; i < candidates.length(); i++) { |
4846 BinarySmiOpInstr* op = candidates[i]; | 4846 BinarySmiOpInstr* op = candidates[i]; |
4847 if (op->WasEliminated() || processed->Contains(op->ssa_temp_index())) { | 4847 if (op->WasEliminated() || processed->Contains(op->ssa_temp_index())) { |
4848 continue; | 4848 continue; |
4849 } | 4849 } |
4850 | 4850 |
4851 if (FLAG_trace_smi_widening) { | 4851 if (FLAG_trace_smi_widening) { |
4852 ISL_Print("analysing candidate: %s\n", op->ToCString()); | 4852 THR_Print("analysing candidate: %s\n", op->ToCString()); |
4853 } | 4853 } |
4854 worklist.Clear(); | 4854 worklist.Clear(); |
4855 worklist.Add(op); | 4855 worklist.Add(op); |
4856 | 4856 |
4857 // Collect dependency graph. Note: more items are added to worklist | 4857 // Collect dependency graph. Note: more items are added to worklist |
4858 // inside this loop. | 4858 // inside this loop. |
4859 intptr_t gain = 0; | 4859 intptr_t gain = 0; |
4860 for (intptr_t j = 0; j < worklist.definitions().length(); j++) { | 4860 for (intptr_t j = 0; j < worklist.definitions().length(); j++) { |
4861 Definition* defn = worklist.definitions()[j]; | 4861 Definition* defn = worklist.definitions()[j]; |
4862 | 4862 |
4863 if (FLAG_trace_smi_widening) { | 4863 if (FLAG_trace_smi_widening) { |
4864 ISL_Print("> %s\n", defn->ToCString()); | 4864 THR_Print("> %s\n", defn->ToCString()); |
4865 } | 4865 } |
4866 | 4866 |
4867 if (defn->IsBinarySmiOp() && | 4867 if (defn->IsBinarySmiOp() && |
4868 BenefitsFromWidening(defn->AsBinarySmiOp())) { | 4868 BenefitsFromWidening(defn->AsBinarySmiOp())) { |
4869 gain++; | 4869 gain++; |
4870 if (FLAG_trace_smi_widening) { | 4870 if (FLAG_trace_smi_widening) { |
4871 ISL_Print("^ [%" Pd "] (o) %s\n", gain, defn->ToCString()); | 4871 THR_Print("^ [%" Pd "] (o) %s\n", gain, defn->ToCString()); |
4872 } | 4872 } |
4873 } | 4873 } |
4874 | 4874 |
4875 const intptr_t defn_loop = loops[defn->GetBlock()->preorder_number()]; | 4875 const intptr_t defn_loop = loops[defn->GetBlock()->preorder_number()]; |
4876 | 4876 |
4877 // Process all inputs. | 4877 // Process all inputs. |
4878 for (intptr_t k = 0; k < defn->InputCount(); k++) { | 4878 for (intptr_t k = 0; k < defn->InputCount(); k++) { |
4879 Definition* input = defn->InputAt(k)->definition(); | 4879 Definition* input = defn->InputAt(k)->definition(); |
4880 if (input->IsBinarySmiOp() && | 4880 if (input->IsBinarySmiOp() && |
4881 CanBeWidened(input->AsBinarySmiOp())) { | 4881 CanBeWidened(input->AsBinarySmiOp())) { |
4882 worklist.Add(input); | 4882 worklist.Add(input); |
4883 } else if (input->IsPhi() && (input->Type()->ToCid() == kSmiCid)) { | 4883 } else if (input->IsPhi() && (input->Type()->ToCid() == kSmiCid)) { |
4884 worklist.Add(input); | 4884 worklist.Add(input); |
4885 } else if (input->IsBinaryMintOp()) { | 4885 } else if (input->IsBinaryMintOp()) { |
4886 // Mint operation produces untagged result. We avoid tagging. | 4886 // Mint operation produces untagged result. We avoid tagging. |
4887 gain++; | 4887 gain++; |
4888 if (FLAG_trace_smi_widening) { | 4888 if (FLAG_trace_smi_widening) { |
4889 ISL_Print("^ [%" Pd "] (i) %s\n", gain, input->ToCString()); | 4889 THR_Print("^ [%" Pd "] (i) %s\n", gain, input->ToCString()); |
4890 } | 4890 } |
4891 } else if (defn_loop == loops[input->GetBlock()->preorder_number()] && | 4891 } else if (defn_loop == loops[input->GetBlock()->preorder_number()] && |
4892 (input->Type()->ToCid() == kSmiCid)) { | 4892 (input->Type()->ToCid() == kSmiCid)) { |
4893 // Input comes from the same loop, is known to be smi and requires | 4893 // Input comes from the same loop, is known to be smi and requires |
4894 // untagging. | 4894 // untagging. |
4895 // TODO(vegorov) this heuristic assumes that values that are not | 4895 // TODO(vegorov) this heuristic assumes that values that are not |
4896 // known to be smi have to be checked and this check can be | 4896 // known to be smi have to be checked and this check can be |
4897 // coalesced with untagging. Start coalescing them. | 4897 // coalesced with untagging. Start coalescing them. |
4898 gain--; | 4898 gain--; |
4899 if (FLAG_trace_smi_widening) { | 4899 if (FLAG_trace_smi_widening) { |
4900 ISL_Print("v [%" Pd "] (i) %s\n", gain, input->ToCString()); | 4900 THR_Print("v [%" Pd "] (i) %s\n", gain, input->ToCString()); |
4901 } | 4901 } |
4902 } | 4902 } |
4903 } | 4903 } |
4904 | 4904 |
4905 // Process all uses. | 4905 // Process all uses. |
4906 for (Value* use = defn->input_use_list(); | 4906 for (Value* use = defn->input_use_list(); |
4907 use != NULL; | 4907 use != NULL; |
4908 use = use->next_use()) { | 4908 use = use->next_use()) { |
4909 Instruction* instr = use->instruction(); | 4909 Instruction* instr = use->instruction(); |
4910 Definition* use_defn = instr->AsDefinition(); | 4910 Definition* use_defn = instr->AsDefinition(); |
4911 if (use_defn == NULL) { | 4911 if (use_defn == NULL) { |
4912 // We assume that tagging before returning or pushing argument costs | 4912 // We assume that tagging before returning or pushing argument costs |
4913 // very little compared to the cost of the return/call itself. | 4913 // very little compared to the cost of the return/call itself. |
4914 if (!instr->IsReturn() && !instr->IsPushArgument()) { | 4914 if (!instr->IsReturn() && !instr->IsPushArgument()) { |
4915 gain--; | 4915 gain--; |
4916 if (FLAG_trace_smi_widening) { | 4916 if (FLAG_trace_smi_widening) { |
4917 ISL_Print("v [%" Pd "] (u) %s\n", | 4917 THR_Print("v [%" Pd "] (u) %s\n", |
4918 gain, | 4918 gain, |
4919 use->instruction()->ToCString()); | 4919 use->instruction()->ToCString()); |
4920 } | 4920 } |
4921 } | 4921 } |
4922 continue; | 4922 continue; |
4923 } else if (use_defn->IsBinarySmiOp() && | 4923 } else if (use_defn->IsBinarySmiOp() && |
4924 CanBeWidened(use_defn->AsBinarySmiOp())) { | 4924 CanBeWidened(use_defn->AsBinarySmiOp())) { |
4925 worklist.Add(use_defn); | 4925 worklist.Add(use_defn); |
4926 } else if (use_defn->IsPhi() && | 4926 } else if (use_defn->IsPhi() && |
4927 use_defn->AsPhi()->Type()->ToCid() == kSmiCid) { | 4927 use_defn->AsPhi()->Type()->ToCid() == kSmiCid) { |
4928 worklist.Add(use_defn); | 4928 worklist.Add(use_defn); |
4929 } else if (use_defn->IsBinaryMintOp()) { | 4929 } else if (use_defn->IsBinaryMintOp()) { |
4930 // BinaryMintOp requires untagging of its inputs. | 4930 // BinaryMintOp requires untagging of its inputs. |
4931 // Converting kUnboxedInt32 to kUnboxedMint is essentially zero cost | 4931 // Converting kUnboxedInt32 to kUnboxedMint is essentially zero cost |
4932 // sign extension operation. | 4932 // sign extension operation. |
4933 gain++; | 4933 gain++; |
4934 if (FLAG_trace_smi_widening) { | 4934 if (FLAG_trace_smi_widening) { |
4935 ISL_Print("^ [%" Pd "] (u) %s\n", | 4935 THR_Print("^ [%" Pd "] (u) %s\n", |
4936 gain, | 4936 gain, |
4937 use->instruction()->ToCString()); | 4937 use->instruction()->ToCString()); |
4938 } | 4938 } |
4939 } else if (defn_loop == loops[instr->GetBlock()->preorder_number()]) { | 4939 } else if (defn_loop == loops[instr->GetBlock()->preorder_number()]) { |
4940 gain--; | 4940 gain--; |
4941 if (FLAG_trace_smi_widening) { | 4941 if (FLAG_trace_smi_widening) { |
4942 ISL_Print("v [%" Pd "] (u) %s\n", | 4942 THR_Print("v [%" Pd "] (u) %s\n", |
4943 gain, | 4943 gain, |
4944 use->instruction()->ToCString()); | 4944 use->instruction()->ToCString()); |
4945 } | 4945 } |
4946 } | 4946 } |
4947 } | 4947 } |
4948 } | 4948 } |
4949 | 4949 |
4950 processed->AddAll(worklist.contains_vector()); | 4950 processed->AddAll(worklist.contains_vector()); |
4951 | 4951 |
4952 if (FLAG_trace_smi_widening) { | 4952 if (FLAG_trace_smi_widening) { |
4953 ISL_Print("~ %s gain %" Pd "\n", op->ToCString(), gain); | 4953 THR_Print("~ %s gain %" Pd "\n", op->ToCString(), gain); |
4954 } | 4954 } |
4955 | 4955 |
4956 if (gain > 0) { | 4956 if (gain > 0) { |
4957 // We have positive gain from widening. Convert all BinarySmiOpInstr into | 4957 // We have positive gain from widening. Convert all BinarySmiOpInstr into |
4958 // BinaryInt32OpInstr and set representation of all phis to kUnboxedInt32. | 4958 // BinaryInt32OpInstr and set representation of all phis to kUnboxedInt32. |
4959 for (intptr_t j = 0; j < worklist.definitions().length(); j++) { | 4959 for (intptr_t j = 0; j < worklist.definitions().length(); j++) { |
4960 Definition* defn = worklist.definitions()[j]; | 4960 Definition* defn = worklist.definitions()[j]; |
4961 ASSERT(defn->IsPhi() || defn->IsBinarySmiOp()); | 4961 ASSERT(defn->IsPhi() || defn->IsBinarySmiOp()); |
4962 | 4962 |
4963 if (defn->IsBinarySmiOp()) { | 4963 if (defn->IsBinarySmiOp()) { |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5071 if (current->IsCheckClass()) { | 5071 if (current->IsCheckClass()) { |
5072 current->AsCheckClass()->set_licm_hoisted(true); | 5072 current->AsCheckClass()->set_licm_hoisted(true); |
5073 } else if (current->IsCheckSmi()) { | 5073 } else if (current->IsCheckSmi()) { |
5074 current->AsCheckSmi()->set_licm_hoisted(true); | 5074 current->AsCheckSmi()->set_licm_hoisted(true); |
5075 } else if (current->IsCheckEitherNonSmi()) { | 5075 } else if (current->IsCheckEitherNonSmi()) { |
5076 current->AsCheckEitherNonSmi()->set_licm_hoisted(true); | 5076 current->AsCheckEitherNonSmi()->set_licm_hoisted(true); |
5077 } else if (current->IsCheckArrayBound()) { | 5077 } else if (current->IsCheckArrayBound()) { |
5078 current->AsCheckArrayBound()->set_licm_hoisted(true); | 5078 current->AsCheckArrayBound()->set_licm_hoisted(true); |
5079 } | 5079 } |
5080 if (FLAG_trace_optimization) { | 5080 if (FLAG_trace_optimization) { |
5081 ISL_Print("Hoisting instruction %s:%" Pd " from B%" Pd " to B%" Pd "\n", | 5081 THR_Print("Hoisting instruction %s:%" Pd " from B%" Pd " to B%" Pd "\n", |
5082 current->DebugName(), | 5082 current->DebugName(), |
5083 current->GetDeoptId(), | 5083 current->GetDeoptId(), |
5084 current->GetBlock()->block_id(), | 5084 current->GetBlock()->block_id(), |
5085 pre_header->block_id()); | 5085 pre_header->block_id()); |
5086 } | 5086 } |
5087 // Move the instruction out of the loop. | 5087 // Move the instruction out of the loop. |
5088 current->RemoveEnvironment(); | 5088 current->RemoveEnvironment(); |
5089 if (it != NULL) { | 5089 if (it != NULL) { |
5090 it->RemoveCurrentFromGraph(); | 5090 it->RemoveCurrentFromGraph(); |
5091 } else { | 5091 } else { |
(...skipping 796 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5888 Place* LookupCanonical(Place* place) const { | 5888 Place* LookupCanonical(Place* place) const { |
5889 return places_map_->Lookup(place); | 5889 return places_map_->Lookup(place); |
5890 } | 5890 } |
5891 | 5891 |
5892 void PrintSet(BitVector* set) { | 5892 void PrintSet(BitVector* set) { |
5893 bool comma = false; | 5893 bool comma = false; |
5894 for (BitVector::Iterator it(set); | 5894 for (BitVector::Iterator it(set); |
5895 !it.Done(); | 5895 !it.Done(); |
5896 it.Advance()) { | 5896 it.Advance()) { |
5897 if (comma) { | 5897 if (comma) { |
5898 ISL_Print(", "); | 5898 THR_Print(", "); |
5899 } | 5899 } |
5900 ISL_Print("%s", places_[it.Current()]->ToCString()); | 5900 THR_Print("%s", places_[it.Current()]->ToCString()); |
5901 comma = true; | 5901 comma = true; |
5902 } | 5902 } |
5903 } | 5903 } |
5904 | 5904 |
5905 const PhiPlaceMoves* phi_moves() const { return phi_moves_; } | 5905 const PhiPlaceMoves* phi_moves() const { return phi_moves_; } |
5906 | 5906 |
5907 void RollbackAliasedIdentites() { | 5907 void RollbackAliasedIdentites() { |
5908 for (intptr_t i = 0; i < identity_rollback_.length(); ++i) { | 5908 for (intptr_t i = 0; i < identity_rollback_.length(); ++i) { |
5909 identity_rollback_[i]->SetIdentity(AliasIdentity::Unknown()); | 5909 identity_rollback_[i]->SetIdentity(AliasIdentity::Unknown()); |
5910 } | 5910 } |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5985 | 5985 |
5986 void ComputeKillSets() { | 5986 void ComputeKillSets() { |
5987 for (intptr_t i = 0; i < aliases_.length(); ++i) { | 5987 for (intptr_t i = 0; i < aliases_.length(); ++i) { |
5988 const Place* alias = aliases_[i]; | 5988 const Place* alias = aliases_[i]; |
5989 // Add all representatives to the kill set. | 5989 // Add all representatives to the kill set. |
5990 AddAllRepresentatives(alias->id(), alias->id()); | 5990 AddAllRepresentatives(alias->id(), alias->id()); |
5991 ComputeKillSet(alias); | 5991 ComputeKillSet(alias); |
5992 } | 5992 } |
5993 | 5993 |
5994 if (FLAG_trace_load_optimization) { | 5994 if (FLAG_trace_load_optimization) { |
5995 ISL_Print("Aliases KILL sets:\n"); | 5995 THR_Print("Aliases KILL sets:\n"); |
5996 for (intptr_t i = 0; i < aliases_.length(); ++i) { | 5996 for (intptr_t i = 0; i < aliases_.length(); ++i) { |
5997 const Place* alias = aliases_[i]; | 5997 const Place* alias = aliases_[i]; |
5998 BitVector* kill = GetKilledSet(alias->id()); | 5998 BitVector* kill = GetKilledSet(alias->id()); |
5999 | 5999 |
6000 ISL_Print("%s: ", alias->ToCString()); | 6000 THR_Print("%s: ", alias->ToCString()); |
6001 if (kill != NULL) { | 6001 if (kill != NULL) { |
6002 PrintSet(kill); | 6002 PrintSet(kill); |
6003 } | 6003 } |
6004 ISL_Print("\n"); | 6004 THR_Print("\n"); |
6005 } | 6005 } |
6006 } | 6006 } |
6007 } | 6007 } |
6008 | 6008 |
6009 void InsertAlias(const Place* alias) { | 6009 void InsertAlias(const Place* alias) { |
6010 aliases_map_.Insert(alias); | 6010 aliases_map_.Insert(alias); |
6011 aliases_.Add(alias); | 6011 aliases_.Add(alias); |
6012 } | 6012 } |
6013 | 6013 |
6014 const Place* CanonicalizeAlias(const Place& alias) { | 6014 const Place* CanonicalizeAlias(const Place& alias) { |
(...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6381 PhiPlaceMoves* phi_moves = new(zone) PhiPlaceMoves(); | 6381 PhiPlaceMoves* phi_moves = new(zone) PhiPlaceMoves(); |
6382 | 6382 |
6383 for (intptr_t i = 0; i < places->length(); i++) { | 6383 for (intptr_t i = 0; i < places->length(); i++) { |
6384 Place* place = (*places)[i]; | 6384 Place* place = (*places)[i]; |
6385 | 6385 |
6386 if (IsPhiDependentPlace(place)) { | 6386 if (IsPhiDependentPlace(place)) { |
6387 PhiInstr* phi = place->instance()->AsPhi(); | 6387 PhiInstr* phi = place->instance()->AsPhi(); |
6388 BlockEntryInstr* block = phi->GetBlock(); | 6388 BlockEntryInstr* block = phi->GetBlock(); |
6389 | 6389 |
6390 if (FLAG_trace_optimization) { | 6390 if (FLAG_trace_optimization) { |
6391 ISL_Print("phi dependent place %s\n", place->ToCString()); | 6391 THR_Print("phi dependent place %s\n", place->ToCString()); |
6392 } | 6392 } |
6393 | 6393 |
6394 Place input_place(*place); | 6394 Place input_place(*place); |
6395 for (intptr_t j = 0; j < phi->InputCount(); j++) { | 6395 for (intptr_t j = 0; j < phi->InputCount(); j++) { |
6396 input_place.set_instance(phi->InputAt(j)->definition()); | 6396 input_place.set_instance(phi->InputAt(j)->definition()); |
6397 | 6397 |
6398 Place* result = map->Lookup(&input_place); | 6398 Place* result = map->Lookup(&input_place); |
6399 if (result == NULL) { | 6399 if (result == NULL) { |
6400 result = Place::Wrap(zone, input_place, places->length()); | 6400 result = Place::Wrap(zone, input_place, places->length()); |
6401 map->Insert(result); | 6401 map->Insert(result); |
6402 places->Add(result); | 6402 places->Add(result); |
6403 if (FLAG_trace_optimization) { | 6403 if (FLAG_trace_optimization) { |
6404 ISL_Print(" adding place %s as %" Pd "\n", | 6404 THR_Print(" adding place %s as %" Pd "\n", |
6405 result->ToCString(), | 6405 result->ToCString(), |
6406 result->id()); | 6406 result->id()); |
6407 } | 6407 } |
6408 } | 6408 } |
6409 phi_moves->CreateOutgoingMove(zone, | 6409 phi_moves->CreateOutgoingMove(zone, |
6410 block->PredecessorAt(j), | 6410 block->PredecessorAt(j), |
6411 result->id(), | 6411 result->id(), |
6412 place->id()); | 6412 place->id()); |
6413 } | 6413 } |
6414 } | 6414 } |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6450 continue; | 6450 continue; |
6451 } | 6451 } |
6452 | 6452 |
6453 Place* result = map->Lookup(&place); | 6453 Place* result = map->Lookup(&place); |
6454 if (result == NULL) { | 6454 if (result == NULL) { |
6455 result = Place::Wrap(zone, place, places->length()); | 6455 result = Place::Wrap(zone, place, places->length()); |
6456 map->Insert(result); | 6456 map->Insert(result); |
6457 places->Add(result); | 6457 places->Add(result); |
6458 | 6458 |
6459 if (FLAG_trace_optimization) { | 6459 if (FLAG_trace_optimization) { |
6460 ISL_Print("numbering %s as %" Pd "\n", | 6460 THR_Print("numbering %s as %" Pd "\n", |
6461 result->ToCString(), | 6461 result->ToCString(), |
6462 result->id()); | 6462 result->id()); |
6463 } | 6463 } |
6464 } | 6464 } |
6465 | 6465 |
6466 instr->set_place_id(result->id()); | 6466 instr->set_place_id(result->id()); |
6467 } | 6467 } |
6468 } | 6468 } |
6469 | 6469 |
6470 if ((mode == kOptimizeLoads) && !has_loads) { | 6470 if ((mode == kOptimizeLoads) && !has_loads) { |
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6719 } | 6719 } |
6720 | 6720 |
6721 const intptr_t place_id = defn->place_id(); | 6721 const intptr_t place_id = defn->place_id(); |
6722 if (gen->Contains(place_id)) { | 6722 if (gen->Contains(place_id)) { |
6723 // This is a locally redundant load. | 6723 // This is a locally redundant load. |
6724 ASSERT((out_values != NULL) && ((*out_values)[place_id] != NULL)); | 6724 ASSERT((out_values != NULL) && ((*out_values)[place_id] != NULL)); |
6725 | 6725 |
6726 Definition* replacement = (*out_values)[place_id]; | 6726 Definition* replacement = (*out_values)[place_id]; |
6727 EnsureSSATempIndex(graph_, defn, replacement); | 6727 EnsureSSATempIndex(graph_, defn, replacement); |
6728 if (FLAG_trace_optimization) { | 6728 if (FLAG_trace_optimization) { |
6729 ISL_Print("Replacing load v%" Pd " with v%" Pd "\n", | 6729 THR_Print("Replacing load v%" Pd " with v%" Pd "\n", |
6730 defn->ssa_temp_index(), | 6730 defn->ssa_temp_index(), |
6731 replacement->ssa_temp_index()); | 6731 replacement->ssa_temp_index()); |
6732 } | 6732 } |
6733 | 6733 |
6734 defn->ReplaceUsesWith(replacement); | 6734 defn->ReplaceUsesWith(replacement); |
6735 instr_it.RemoveCurrentFromGraph(); | 6735 instr_it.RemoveCurrentFromGraph(); |
6736 forwarded_ = true; | 6736 forwarded_ = true; |
6737 continue; | 6737 continue; |
6738 } else if (!kill->Contains(place_id)) { | 6738 } else if (!kill->Contains(place_id)) { |
6739 // This is an exposed load: it is the first representative of a | 6739 // 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... |
6927 for (intptr_t i = 0; i < phi_moves->length(); i++) { | 6927 for (intptr_t i = 0; i < phi_moves->length(); i++) { |
6928 const intptr_t from = (*phi_moves)[i].from(); | 6928 const intptr_t from = (*phi_moves)[i].from(); |
6929 const intptr_t to = (*phi_moves)[i].to(); | 6929 const intptr_t to = (*phi_moves)[i].to(); |
6930 if (from == to) continue; | 6930 if (from == to) continue; |
6931 | 6931 |
6932 (*block_out_values)[to] = (*temp_forwarded_values)[to]; | 6932 (*block_out_values)[to] = (*temp_forwarded_values)[to]; |
6933 } | 6933 } |
6934 } | 6934 } |
6935 | 6935 |
6936 if (FLAG_trace_load_optimization) { | 6936 if (FLAG_trace_load_optimization) { |
6937 ISL_Print("B%" Pd "\n", block->block_id()); | 6937 THR_Print("B%" Pd "\n", block->block_id()); |
6938 ISL_Print(" IN: "); | 6938 THR_Print(" IN: "); |
6939 aliased_set_->PrintSet(in_[preorder_number]); | 6939 aliased_set_->PrintSet(in_[preorder_number]); |
6940 ISL_Print("\n"); | 6940 THR_Print("\n"); |
6941 | 6941 |
6942 ISL_Print(" KILL: "); | 6942 THR_Print(" KILL: "); |
6943 aliased_set_->PrintSet(kill_[preorder_number]); | 6943 aliased_set_->PrintSet(kill_[preorder_number]); |
6944 ISL_Print("\n"); | 6944 THR_Print("\n"); |
6945 | 6945 |
6946 ISL_Print(" OUT: "); | 6946 THR_Print(" OUT: "); |
6947 aliased_set_->PrintSet(out_[preorder_number]); | 6947 aliased_set_->PrintSet(out_[preorder_number]); |
6948 ISL_Print("\n"); | 6948 THR_Print("\n"); |
6949 } | 6949 } |
6950 } | 6950 } |
6951 | 6951 |
6952 // All blocks were visited. Fill pending phis with inputs | 6952 // All blocks were visited. Fill pending phis with inputs |
6953 // that flow on back edges. | 6953 // that flow on back edges. |
6954 for (intptr_t i = 0; i < pending_phis.length(); i++) { | 6954 for (intptr_t i = 0; i < pending_phis.length(); i++) { |
6955 FillPhiInputs(pending_phis[i]); | 6955 FillPhiInputs(pending_phis[i]); |
6956 } | 6956 } |
6957 } | 6957 } |
6958 | 6958 |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6991 | 6991 |
6992 for (BitVector::Iterator loop_it(header->loop_info()); | 6992 for (BitVector::Iterator loop_it(header->loop_info()); |
6993 !loop_it.Done(); | 6993 !loop_it.Done(); |
6994 loop_it.Advance()) { | 6994 loop_it.Advance()) { |
6995 const intptr_t preorder_number = loop_it.Current(); | 6995 const intptr_t preorder_number = loop_it.Current(); |
6996 loop_gen->RemoveAll(kill_[preorder_number]); | 6996 loop_gen->RemoveAll(kill_[preorder_number]); |
6997 } | 6997 } |
6998 | 6998 |
6999 if (FLAG_trace_optimization) { | 6999 if (FLAG_trace_optimization) { |
7000 for (BitVector::Iterator it(loop_gen); !it.Done(); it.Advance()) { | 7000 for (BitVector::Iterator it(loop_gen); !it.Done(); it.Advance()) { |
7001 ISL_Print("place %s is loop invariant for B%" Pd "\n", | 7001 THR_Print("place %s is loop invariant for B%" Pd "\n", |
7002 aliased_set_->places()[it.Current()]->ToCString(), | 7002 aliased_set_->places()[it.Current()]->ToCString(), |
7003 header->block_id()); | 7003 header->block_id()); |
7004 } | 7004 } |
7005 } | 7005 } |
7006 | 7006 |
7007 invariant_loads->Add(loop_gen); | 7007 invariant_loads->Add(loop_gen); |
7008 } | 7008 } |
7009 | 7009 |
7010 graph_->set_loop_invariant_loads(invariant_loads); | 7010 graph_->set_loop_invariant_loads(invariant_loads); |
7011 } | 7011 } |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7062 Definition* replacement = (*pred_out_values)[place_id]->Replacement(); | 7062 Definition* replacement = (*pred_out_values)[place_id]->Replacement(); |
7063 Value* input = new(Z) Value(replacement); | 7063 Value* input = new(Z) Value(replacement); |
7064 phi->SetInputAt(i, input); | 7064 phi->SetInputAt(i, input); |
7065 replacement->AddInputUse(input); | 7065 replacement->AddInputUse(input); |
7066 } | 7066 } |
7067 | 7067 |
7068 phi->set_ssa_temp_index(graph_->alloc_ssa_temp_index()); | 7068 phi->set_ssa_temp_index(graph_->alloc_ssa_temp_index()); |
7069 phis_.Add(phi); // Postpone phi insertion until after load forwarding. | 7069 phis_.Add(phi); // Postpone phi insertion until after load forwarding. |
7070 | 7070 |
7071 if (FLAG_trace_load_optimization) { | 7071 if (FLAG_trace_load_optimization) { |
7072 ISL_Print("created pending phi %s for %s at B%" Pd "\n", | 7072 THR_Print("created pending phi %s for %s at B%" Pd "\n", |
7073 phi->ToCString(), | 7073 phi->ToCString(), |
7074 aliased_set_->places()[place_id]->ToCString(), | 7074 aliased_set_->places()[place_id]->ToCString(), |
7075 block->block_id()); | 7075 block->block_id()); |
7076 } | 7076 } |
7077 } | 7077 } |
7078 | 7078 |
7079 // Iterate over basic blocks and replace exposed loads with incoming | 7079 // Iterate over basic blocks and replace exposed loads with incoming |
7080 // values. | 7080 // values. |
7081 void ForwardLoads() { | 7081 void ForwardLoads() { |
7082 for (BlockIterator block_it = graph_->reverse_postorder_iterator(); | 7082 for (BlockIterator block_it = graph_->reverse_postorder_iterator(); |
(...skipping 18 matching lines...) Expand all Loading... |
7101 // they might contain values that were replace and removed | 7101 // they might contain values that were replace and removed |
7102 // from the graph by this iteration. | 7102 // from the graph by this iteration. |
7103 // To prevent using them we additionally mark definitions themselves | 7103 // To prevent using them we additionally mark definitions themselves |
7104 // as replaced and store a pointer to the replacement. | 7104 // as replaced and store a pointer to the replacement. |
7105 replacement = replacement->Replacement(); | 7105 replacement = replacement->Replacement(); |
7106 | 7106 |
7107 if (load != replacement) { | 7107 if (load != replacement) { |
7108 EnsureSSATempIndex(graph_, load, replacement); | 7108 EnsureSSATempIndex(graph_, load, replacement); |
7109 | 7109 |
7110 if (FLAG_trace_optimization) { | 7110 if (FLAG_trace_optimization) { |
7111 ISL_Print("Replacing load v%" Pd " with v%" Pd "\n", | 7111 THR_Print("Replacing load v%" Pd " with v%" Pd "\n", |
7112 load->ssa_temp_index(), | 7112 load->ssa_temp_index(), |
7113 replacement->ssa_temp_index()); | 7113 replacement->ssa_temp_index()); |
7114 } | 7114 } |
7115 | 7115 |
7116 load->ReplaceUsesWith(replacement); | 7116 load->ReplaceUsesWith(replacement); |
7117 load->RemoveFromGraph(); | 7117 load->RemoveFromGraph(); |
7118 load->SetReplacement(replacement); | 7118 load->SetReplacement(replacement); |
7119 forwarded_ = true; | 7119 forwarded_ = true; |
7120 } | 7120 } |
7121 } | 7121 } |
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7290 if (!a->IsPhi()) { | 7290 if (!a->IsPhi()) { |
7291 if (Dominates(a, b)) { | 7291 if (Dominates(a, b)) { |
7292 Definition* t = a; | 7292 Definition* t = a; |
7293 a = b; | 7293 a = b; |
7294 b = t; | 7294 b = t; |
7295 } | 7295 } |
7296 ASSERT(Dominates(b, a)); | 7296 ASSERT(Dominates(b, a)); |
7297 } | 7297 } |
7298 | 7298 |
7299 if (FLAG_trace_load_optimization) { | 7299 if (FLAG_trace_load_optimization) { |
7300 ISL_Print("Replacing %s with congruent %s\n", | 7300 THR_Print("Replacing %s with congruent %s\n", |
7301 a->ToCString(), | 7301 a->ToCString(), |
7302 b->ToCString()); | 7302 b->ToCString()); |
7303 } | 7303 } |
7304 | 7304 |
7305 a->ReplaceUsesWith(b); | 7305 a->ReplaceUsesWith(b); |
7306 if (a->IsPhi()) { | 7306 if (a->IsPhi()) { |
7307 // We might be replacing a phi introduced by the load forwarding | 7307 // We might be replacing a phi introduced by the load forwarding |
7308 // that is not inserted in the graph yet. | 7308 // that is not inserted in the graph yet. |
7309 ASSERT(b->IsPhi()); | 7309 ASSERT(b->IsPhi()); |
7310 PhiInstr* phi_a = a->AsPhi(); | 7310 PhiInstr* phi_a = a->AsPhi(); |
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7496 // Loads/stores of final fields do not participate. | 7496 // Loads/stores of final fields do not participate. |
7497 continue; | 7497 continue; |
7498 } | 7498 } |
7499 | 7499 |
7500 // Handle stores. | 7500 // Handle stores. |
7501 if (is_store) { | 7501 if (is_store) { |
7502 if (kill->Contains(instr->place_id())) { | 7502 if (kill->Contains(instr->place_id())) { |
7503 if (!live_in->Contains(instr->place_id()) && | 7503 if (!live_in->Contains(instr->place_id()) && |
7504 CanEliminateStore(instr)) { | 7504 CanEliminateStore(instr)) { |
7505 if (FLAG_trace_optimization) { | 7505 if (FLAG_trace_optimization) { |
7506 ISL_Print( | 7506 THR_Print( |
7507 "Removing dead store to place %" Pd " in block B%" Pd "\n", | 7507 "Removing dead store to place %" Pd " in block B%" Pd "\n", |
7508 instr->place_id(), block->block_id()); | 7508 instr->place_id(), block->block_id()); |
7509 } | 7509 } |
7510 instr_it.RemoveCurrentFromGraph(); | 7510 instr_it.RemoveCurrentFromGraph(); |
7511 } | 7511 } |
7512 } else if (!live_in->Contains(instr->place_id())) { | 7512 } else if (!live_in->Contains(instr->place_id())) { |
7513 // Mark this store as down-ward exposed: They are the only | 7513 // Mark this store as down-ward exposed: They are the only |
7514 // candidates for the global store elimination. | 7514 // candidates for the global store elimination. |
7515 if (exposed_stores == NULL) { | 7515 if (exposed_stores == NULL) { |
7516 const intptr_t kMaxExposedStoresInitialSize = 5; | 7516 const intptr_t kMaxExposedStoresInitialSize = 5; |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7549 if ((defn != NULL) && IsLoadEliminationCandidate(defn)) { | 7549 if ((defn != NULL) && IsLoadEliminationCandidate(defn)) { |
7550 const intptr_t alias = aliased_set_->LookupAliasId(place.ToAlias()); | 7550 const intptr_t alias = aliased_set_->LookupAliasId(place.ToAlias()); |
7551 live_in->AddAll(aliased_set_->GetKilledSet(alias)); | 7551 live_in->AddAll(aliased_set_->GetKilledSet(alias)); |
7552 continue; | 7552 continue; |
7553 } | 7553 } |
7554 } | 7554 } |
7555 exposed_stores_[postorder_number] = exposed_stores; | 7555 exposed_stores_[postorder_number] = exposed_stores; |
7556 } | 7556 } |
7557 if (FLAG_trace_load_optimization) { | 7557 if (FLAG_trace_load_optimization) { |
7558 Dump(); | 7558 Dump(); |
7559 ISL_Print("---\n"); | 7559 THR_Print("---\n"); |
7560 } | 7560 } |
7561 } | 7561 } |
7562 | 7562 |
7563 void EliminateDeadStores() { | 7563 void EliminateDeadStores() { |
7564 // Iteration order does not matter here. | 7564 // Iteration order does not matter here. |
7565 for (BlockIterator block_it = graph_->postorder_iterator(); | 7565 for (BlockIterator block_it = graph_->postorder_iterator(); |
7566 !block_it.Done(); | 7566 !block_it.Done(); |
7567 block_it.Advance()) { | 7567 block_it.Advance()) { |
7568 BlockEntryInstr* block = block_it.Current(); | 7568 BlockEntryInstr* block = block_it.Current(); |
7569 const intptr_t postorder_number = block->postorder_number(); | 7569 const intptr_t postorder_number = block->postorder_number(); |
(...skipping 13 matching lines...) Expand all Loading... |
7583 ASSERT(!is_load && is_store); | 7583 ASSERT(!is_load && is_store); |
7584 if (place.IsFinalField()) { | 7584 if (place.IsFinalField()) { |
7585 // Final field do not participate in dead store elimination. | 7585 // Final field do not participate in dead store elimination. |
7586 continue; | 7586 continue; |
7587 } | 7587 } |
7588 // Eliminate a downward exposed store if the corresponding place is not | 7588 // Eliminate a downward exposed store if the corresponding place is not |
7589 // in live-out. | 7589 // in live-out. |
7590 if (!live_out->Contains(instr->place_id()) && | 7590 if (!live_out->Contains(instr->place_id()) && |
7591 CanEliminateStore(instr)) { | 7591 CanEliminateStore(instr)) { |
7592 if (FLAG_trace_optimization) { | 7592 if (FLAG_trace_optimization) { |
7593 ISL_Print("Removing dead store to place %" Pd " block B%" Pd "\n", | 7593 THR_Print("Removing dead store to place %" Pd " block B%" Pd "\n", |
7594 instr->place_id(), block->block_id()); | 7594 instr->place_id(), block->block_id()); |
7595 } | 7595 } |
7596 instr->RemoveFromGraph(/* ignored */ false); | 7596 instr->RemoveFromGraph(/* ignored */ false); |
7597 } | 7597 } |
7598 } | 7598 } |
7599 } | 7599 } |
7600 } | 7600 } |
7601 | 7601 |
7602 FlowGraph* graph_; | 7602 FlowGraph* graph_; |
7603 DirectChainedHashMap<PointerKeyValueTrait<Place> >* map_; | 7603 DirectChainedHashMap<PointerKeyValueTrait<Place> >* map_; |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7677 // Eliminate dead phis and compact the phis_ array of the block. | 7677 // Eliminate dead phis and compact the phis_ array of the block. |
7678 intptr_t to_index = 0; | 7678 intptr_t to_index = 0; |
7679 for (intptr_t i = 0; i < join->phis_->length(); ++i) { | 7679 for (intptr_t i = 0; i < join->phis_->length(); ++i) { |
7680 PhiInstr* phi = (*join->phis_)[i]; | 7680 PhiInstr* phi = (*join->phis_)[i]; |
7681 if (phi != NULL) { | 7681 if (phi != NULL) { |
7682 if (!phi->is_alive()) { | 7682 if (!phi->is_alive()) { |
7683 phi->ReplaceUsesWith(flow_graph->constant_null()); | 7683 phi->ReplaceUsesWith(flow_graph->constant_null()); |
7684 phi->UnuseAllInputs(); | 7684 phi->UnuseAllInputs(); |
7685 (*join->phis_)[i] = NULL; | 7685 (*join->phis_)[i] = NULL; |
7686 if (FLAG_trace_optimization) { | 7686 if (FLAG_trace_optimization) { |
7687 ISL_Print("Removing dead phi v%" Pd "\n", phi->ssa_temp_index()); | 7687 THR_Print("Removing dead phi v%" Pd "\n", phi->ssa_temp_index()); |
7688 } | 7688 } |
7689 } else if (phi->IsRedundant()) { | 7689 } else if (phi->IsRedundant()) { |
7690 phi->ReplaceUsesWith(phi->InputAt(0)->definition()); | 7690 phi->ReplaceUsesWith(phi->InputAt(0)->definition()); |
7691 phi->UnuseAllInputs(); | 7691 phi->UnuseAllInputs(); |
7692 (*join->phis_)[i] = NULL; | 7692 (*join->phis_)[i] = NULL; |
7693 if (FLAG_trace_optimization) { | 7693 if (FLAG_trace_optimization) { |
7694 ISL_Print("Removing redundant phi v%" Pd "\n", | 7694 THR_Print("Removing redundant phi v%" Pd "\n", |
7695 phi->ssa_temp_index()); | 7695 phi->ssa_temp_index()); |
7696 } | 7696 } |
7697 } else { | 7697 } else { |
7698 (*join->phis_)[to_index++] = phi; | 7698 (*join->phis_)[to_index++] = phi; |
7699 } | 7699 } |
7700 } | 7700 } |
7701 } | 7701 } |
7702 if (to_index == 0) { | 7702 if (to_index == 0) { |
7703 join->phis_ = NULL; | 7703 join->phis_ = NULL; |
7704 } else { | 7704 } else { |
(...skipping 522 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8227 // deoptimization exit. So candidate should only be used in StoreInstanceField | 8227 // deoptimization exit. So candidate should only be used in StoreInstanceField |
8228 // instructions that write into fields of the allocated object. | 8228 // instructions that write into fields of the allocated object. |
8229 // We do not support materialization of the object that has type arguments. | 8229 // We do not support materialization of the object that has type arguments. |
8230 static bool IsAllocationSinkingCandidate(Definition* alloc, | 8230 static bool IsAllocationSinkingCandidate(Definition* alloc, |
8231 SafeUseCheck check_type) { | 8231 SafeUseCheck check_type) { |
8232 for (Value* use = alloc->input_use_list(); | 8232 for (Value* use = alloc->input_use_list(); |
8233 use != NULL; | 8233 use != NULL; |
8234 use = use->next_use()) { | 8234 use = use->next_use()) { |
8235 if (!IsSafeUse(use, check_type)) { | 8235 if (!IsSafeUse(use, check_type)) { |
8236 if (FLAG_trace_optimization) { | 8236 if (FLAG_trace_optimization) { |
8237 ISL_Print("use of %s at %s is unsafe for allocation sinking\n", | 8237 THR_Print("use of %s at %s is unsafe for allocation sinking\n", |
8238 alloc->ToCString(), | 8238 alloc->ToCString(), |
8239 use->instruction()->ToCString()); | 8239 use->instruction()->ToCString()); |
8240 } | 8240 } |
8241 return false; | 8241 return false; |
8242 } | 8242 } |
8243 } | 8243 } |
8244 | 8244 |
8245 return true; | 8245 return true; |
8246 } | 8246 } |
8247 | 8247 |
8248 | 8248 |
8249 // If the given use is a store into an object then return an object we are | 8249 // If the given use is a store into an object then return an object we are |
8250 // storing into. | 8250 // storing into. |
8251 static Definition* StoreInto(Value* use) { | 8251 static Definition* StoreInto(Value* use) { |
8252 StoreInstanceFieldInstr* store = use->instruction()->AsStoreInstanceField(); | 8252 StoreInstanceFieldInstr* store = use->instruction()->AsStoreInstanceField(); |
8253 if (store != NULL) { | 8253 if (store != NULL) { |
8254 return store->instance()->definition(); | 8254 return store->instance()->definition(); |
8255 } | 8255 } |
8256 | 8256 |
8257 return NULL; | 8257 return NULL; |
8258 } | 8258 } |
8259 | 8259 |
8260 | 8260 |
8261 // Remove the given allocation from the graph. It is not observable. | 8261 // Remove the given allocation from the graph. It is not observable. |
8262 // If deoptimization occurs the object will be materialized. | 8262 // If deoptimization occurs the object will be materialized. |
8263 void AllocationSinking::EliminateAllocation(Definition* alloc) { | 8263 void AllocationSinking::EliminateAllocation(Definition* alloc) { |
8264 ASSERT(IsAllocationSinkingCandidate(alloc, kStrictCheck)); | 8264 ASSERT(IsAllocationSinkingCandidate(alloc, kStrictCheck)); |
8265 | 8265 |
8266 if (FLAG_trace_optimization) { | 8266 if (FLAG_trace_optimization) { |
8267 ISL_Print("removing allocation from the graph: v%" Pd "\n", | 8267 THR_Print("removing allocation from the graph: v%" Pd "\n", |
8268 alloc->ssa_temp_index()); | 8268 alloc->ssa_temp_index()); |
8269 } | 8269 } |
8270 | 8270 |
8271 // As an allocation sinking candidate it is only used in stores to its own | 8271 // As an allocation sinking candidate it is only used in stores to its own |
8272 // fields. Remove these stores. | 8272 // fields. Remove these stores. |
8273 for (Value* use = alloc->input_use_list(); | 8273 for (Value* use = alloc->input_use_list(); |
8274 use != NULL; | 8274 use != NULL; |
8275 use = alloc->input_use_list()) { | 8275 use = alloc->input_use_list()) { |
8276 use->instruction()->RemoveFromGraph(); | 8276 use->instruction()->RemoveFromGraph(); |
8277 } | 8277 } |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8338 } | 8338 } |
8339 } | 8339 } |
8340 } while (changed); | 8340 } while (changed); |
8341 | 8341 |
8342 // Shrink the list of candidates removing all unmarked ones. | 8342 // Shrink the list of candidates removing all unmarked ones. |
8343 intptr_t j = 0; | 8343 intptr_t j = 0; |
8344 for (intptr_t i = 0; i < candidates_.length(); i++) { | 8344 for (intptr_t i = 0; i < candidates_.length(); i++) { |
8345 Definition* alloc = candidates_[i]; | 8345 Definition* alloc = candidates_[i]; |
8346 if (alloc->Identity().IsAllocationSinkingCandidate()) { | 8346 if (alloc->Identity().IsAllocationSinkingCandidate()) { |
8347 if (FLAG_trace_optimization) { | 8347 if (FLAG_trace_optimization) { |
8348 ISL_Print("discovered allocation sinking candidate: v%" Pd "\n", | 8348 THR_Print("discovered allocation sinking candidate: v%" Pd "\n", |
8349 alloc->ssa_temp_index()); | 8349 alloc->ssa_temp_index()); |
8350 } | 8350 } |
8351 | 8351 |
8352 if (j != i) { | 8352 if (j != i) { |
8353 candidates_[j] = alloc; | 8353 candidates_[j] = alloc; |
8354 } | 8354 } |
8355 j++; | 8355 j++; |
8356 } | 8356 } |
8357 } | 8357 } |
8358 candidates_.TruncateTo(j); | 8358 candidates_.TruncateTo(j); |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8433 } | 8433 } |
8434 } | 8434 } |
8435 } while (changed); | 8435 } while (changed); |
8436 | 8436 |
8437 // Remove all failed candidates from the candidates list. | 8437 // Remove all failed candidates from the candidates list. |
8438 intptr_t j = 0; | 8438 intptr_t j = 0; |
8439 for (intptr_t i = 0; i < candidates_.length(); i++) { | 8439 for (intptr_t i = 0; i < candidates_.length(); i++) { |
8440 Definition* alloc = candidates_[i]; | 8440 Definition* alloc = candidates_[i]; |
8441 if (!alloc->Identity().IsAllocationSinkingCandidate()) { | 8441 if (!alloc->Identity().IsAllocationSinkingCandidate()) { |
8442 if (FLAG_trace_optimization) { | 8442 if (FLAG_trace_optimization) { |
8443 ISL_Print("allocation v%" Pd " can't be eliminated\n", | 8443 THR_Print("allocation v%" Pd " can't be eliminated\n", |
8444 alloc->ssa_temp_index()); | 8444 alloc->ssa_temp_index()); |
8445 } | 8445 } |
8446 | 8446 |
8447 #ifdef DEBUG | 8447 #ifdef DEBUG |
8448 for (Value* use = alloc->env_use_list(); | 8448 for (Value* use = alloc->env_use_list(); |
8449 use != NULL; | 8449 use != NULL; |
8450 use = use->next_use()) { | 8450 use = use->next_use()) { |
8451 ASSERT(use->instruction()->IsMaterializeObject()); | 8451 ASSERT(use->instruction()->IsMaterializeObject()); |
8452 } | 8452 } |
8453 #endif | 8453 #endif |
(...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8782 | 8782 |
8783 // Insert materializations at environment uses. | 8783 // Insert materializations at environment uses. |
8784 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { | 8784 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { |
8785 CreateMaterializationAt( | 8785 CreateMaterializationAt( |
8786 exits_collector_.exits()[i], alloc, *slots); | 8786 exits_collector_.exits()[i], alloc, *slots); |
8787 } | 8787 } |
8788 } | 8788 } |
8789 | 8789 |
8790 | 8790 |
8791 } // namespace dart | 8791 } // namespace dart |
OLD | NEW |