| 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 |