| 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/branch_optimizer.h" | 8 #include "vm/branch_optimizer.h" |
| 9 #include "vm/cha.h" | 9 #include "vm/cha.h" |
| 10 #include "vm/compiler.h" | 10 #include "vm/compiler.h" |
| (...skipping 4870 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4881 new(Z) BitVector(Z, flow_graph_->current_ssa_temp_index()); | 4881 new(Z) BitVector(Z, flow_graph_->current_ssa_temp_index()); |
| 4882 | 4882 |
| 4883 // Worklist used to collect dependency graph. | 4883 // Worklist used to collect dependency graph. |
| 4884 DefinitionWorklist worklist(flow_graph_, candidates.length()); | 4884 DefinitionWorklist worklist(flow_graph_, candidates.length()); |
| 4885 for (intptr_t i = 0; i < candidates.length(); i++) { | 4885 for (intptr_t i = 0; i < candidates.length(); i++) { |
| 4886 BinarySmiOpInstr* op = candidates[i]; | 4886 BinarySmiOpInstr* op = candidates[i]; |
| 4887 if (op->WasEliminated() || processed->Contains(op->ssa_temp_index())) { | 4887 if (op->WasEliminated() || processed->Contains(op->ssa_temp_index())) { |
| 4888 continue; | 4888 continue; |
| 4889 } | 4889 } |
| 4890 | 4890 |
| 4891 if (FLAG_trace_smi_widening) { | 4891 if (FLAG_support_il_printer && FLAG_trace_smi_widening) { |
| 4892 THR_Print("analysing candidate: %s\n", op->ToCString()); | 4892 THR_Print("analysing candidate: %s\n", op->ToCString()); |
| 4893 } | 4893 } |
| 4894 worklist.Clear(); | 4894 worklist.Clear(); |
| 4895 worklist.Add(op); | 4895 worklist.Add(op); |
| 4896 | 4896 |
| 4897 // Collect dependency graph. Note: more items are added to worklist | 4897 // Collect dependency graph. Note: more items are added to worklist |
| 4898 // inside this loop. | 4898 // inside this loop. |
| 4899 intptr_t gain = 0; | 4899 intptr_t gain = 0; |
| 4900 for (intptr_t j = 0; j < worklist.definitions().length(); j++) { | 4900 for (intptr_t j = 0; j < worklist.definitions().length(); j++) { |
| 4901 Definition* defn = worklist.definitions()[j]; | 4901 Definition* defn = worklist.definitions()[j]; |
| 4902 | 4902 |
| 4903 if (FLAG_trace_smi_widening) { | 4903 if (FLAG_support_il_printer && FLAG_trace_smi_widening) { |
| 4904 THR_Print("> %s\n", defn->ToCString()); | 4904 THR_Print("> %s\n", defn->ToCString()); |
| 4905 } | 4905 } |
| 4906 | 4906 |
| 4907 if (defn->IsBinarySmiOp() && | 4907 if (defn->IsBinarySmiOp() && |
| 4908 BenefitsFromWidening(defn->AsBinarySmiOp())) { | 4908 BenefitsFromWidening(defn->AsBinarySmiOp())) { |
| 4909 gain++; | 4909 gain++; |
| 4910 if (FLAG_trace_smi_widening) { | 4910 if (FLAG_support_il_printer && FLAG_trace_smi_widening) { |
| 4911 THR_Print("^ [%" Pd "] (o) %s\n", gain, defn->ToCString()); | 4911 THR_Print("^ [%" Pd "] (o) %s\n", gain, defn->ToCString()); |
| 4912 } | 4912 } |
| 4913 } | 4913 } |
| 4914 | 4914 |
| 4915 const intptr_t defn_loop = loops[defn->GetBlock()->preorder_number()]; | 4915 const intptr_t defn_loop = loops[defn->GetBlock()->preorder_number()]; |
| 4916 | 4916 |
| 4917 // Process all inputs. | 4917 // Process all inputs. |
| 4918 for (intptr_t k = 0; k < defn->InputCount(); k++) { | 4918 for (intptr_t k = 0; k < defn->InputCount(); k++) { |
| 4919 Definition* input = defn->InputAt(k)->definition(); | 4919 Definition* input = defn->InputAt(k)->definition(); |
| 4920 if (input->IsBinarySmiOp() && | 4920 if (input->IsBinarySmiOp() && |
| 4921 CanBeWidened(input->AsBinarySmiOp())) { | 4921 CanBeWidened(input->AsBinarySmiOp())) { |
| 4922 worklist.Add(input); | 4922 worklist.Add(input); |
| 4923 } else if (input->IsPhi() && (input->Type()->ToCid() == kSmiCid)) { | 4923 } else if (input->IsPhi() && (input->Type()->ToCid() == kSmiCid)) { |
| 4924 worklist.Add(input); | 4924 worklist.Add(input); |
| 4925 } else if (input->IsBinaryMintOp()) { | 4925 } else if (input->IsBinaryMintOp()) { |
| 4926 // Mint operation produces untagged result. We avoid tagging. | 4926 // Mint operation produces untagged result. We avoid tagging. |
| 4927 gain++; | 4927 gain++; |
| 4928 if (FLAG_trace_smi_widening) { | 4928 if (FLAG_support_il_printer && FLAG_trace_smi_widening) { |
| 4929 THR_Print("^ [%" Pd "] (i) %s\n", gain, input->ToCString()); | 4929 THR_Print("^ [%" Pd "] (i) %s\n", gain, input->ToCString()); |
| 4930 } | 4930 } |
| 4931 } else if (defn_loop == loops[input->GetBlock()->preorder_number()] && | 4931 } else if (defn_loop == loops[input->GetBlock()->preorder_number()] && |
| 4932 (input->Type()->ToCid() == kSmiCid)) { | 4932 (input->Type()->ToCid() == kSmiCid)) { |
| 4933 // Input comes from the same loop, is known to be smi and requires | 4933 // Input comes from the same loop, is known to be smi and requires |
| 4934 // untagging. | 4934 // untagging. |
| 4935 // TODO(vegorov) this heuristic assumes that values that are not | 4935 // TODO(vegorov) this heuristic assumes that values that are not |
| 4936 // known to be smi have to be checked and this check can be | 4936 // known to be smi have to be checked and this check can be |
| 4937 // coalesced with untagging. Start coalescing them. | 4937 // coalesced with untagging. Start coalescing them. |
| 4938 gain--; | 4938 gain--; |
| 4939 if (FLAG_trace_smi_widening) { | 4939 if (FLAG_support_il_printer && FLAG_trace_smi_widening) { |
| 4940 THR_Print("v [%" Pd "] (i) %s\n", gain, input->ToCString()); | 4940 THR_Print("v [%" Pd "] (i) %s\n", gain, input->ToCString()); |
| 4941 } | 4941 } |
| 4942 } | 4942 } |
| 4943 } | 4943 } |
| 4944 | 4944 |
| 4945 // Process all uses. | 4945 // Process all uses. |
| 4946 for (Value* use = defn->input_use_list(); | 4946 for (Value* use = defn->input_use_list(); |
| 4947 use != NULL; | 4947 use != NULL; |
| 4948 use = use->next_use()) { | 4948 use = use->next_use()) { |
| 4949 Instruction* instr = use->instruction(); | 4949 Instruction* instr = use->instruction(); |
| 4950 Definition* use_defn = instr->AsDefinition(); | 4950 Definition* use_defn = instr->AsDefinition(); |
| 4951 if (use_defn == NULL) { | 4951 if (use_defn == NULL) { |
| 4952 // We assume that tagging before returning or pushing argument costs | 4952 // We assume that tagging before returning or pushing argument costs |
| 4953 // very little compared to the cost of the return/call itself. | 4953 // very little compared to the cost of the return/call itself. |
| 4954 if (!instr->IsReturn() && !instr->IsPushArgument()) { | 4954 if (!instr->IsReturn() && !instr->IsPushArgument()) { |
| 4955 gain--; | 4955 gain--; |
| 4956 if (FLAG_trace_smi_widening) { | 4956 if (FLAG_support_il_printer && FLAG_trace_smi_widening) { |
| 4957 THR_Print("v [%" Pd "] (u) %s\n", | 4957 THR_Print("v [%" Pd "] (u) %s\n", |
| 4958 gain, | 4958 gain, |
| 4959 use->instruction()->ToCString()); | 4959 use->instruction()->ToCString()); |
| 4960 } | 4960 } |
| 4961 } | 4961 } |
| 4962 continue; | 4962 continue; |
| 4963 } else if (use_defn->IsBinarySmiOp() && | 4963 } else if (use_defn->IsBinarySmiOp() && |
| 4964 CanBeWidened(use_defn->AsBinarySmiOp())) { | 4964 CanBeWidened(use_defn->AsBinarySmiOp())) { |
| 4965 worklist.Add(use_defn); | 4965 worklist.Add(use_defn); |
| 4966 } else if (use_defn->IsPhi() && | 4966 } else if (use_defn->IsPhi() && |
| 4967 use_defn->AsPhi()->Type()->ToCid() == kSmiCid) { | 4967 use_defn->AsPhi()->Type()->ToCid() == kSmiCid) { |
| 4968 worklist.Add(use_defn); | 4968 worklist.Add(use_defn); |
| 4969 } else if (use_defn->IsBinaryMintOp()) { | 4969 } else if (use_defn->IsBinaryMintOp()) { |
| 4970 // BinaryMintOp requires untagging of its inputs. | 4970 // BinaryMintOp requires untagging of its inputs. |
| 4971 // Converting kUnboxedInt32 to kUnboxedMint is essentially zero cost | 4971 // Converting kUnboxedInt32 to kUnboxedMint is essentially zero cost |
| 4972 // sign extension operation. | 4972 // sign extension operation. |
| 4973 gain++; | 4973 gain++; |
| 4974 if (FLAG_trace_smi_widening) { | 4974 if (FLAG_support_il_printer && FLAG_trace_smi_widening) { |
| 4975 THR_Print("^ [%" Pd "] (u) %s\n", | 4975 THR_Print("^ [%" Pd "] (u) %s\n", |
| 4976 gain, | 4976 gain, |
| 4977 use->instruction()->ToCString()); | 4977 use->instruction()->ToCString()); |
| 4978 } | 4978 } |
| 4979 } else if (defn_loop == loops[instr->GetBlock()->preorder_number()]) { | 4979 } else if (defn_loop == loops[instr->GetBlock()->preorder_number()]) { |
| 4980 gain--; | 4980 gain--; |
| 4981 if (FLAG_trace_smi_widening) { | 4981 if (FLAG_support_il_printer && FLAG_trace_smi_widening) { |
| 4982 THR_Print("v [%" Pd "] (u) %s\n", | 4982 THR_Print("v [%" Pd "] (u) %s\n", |
| 4983 gain, | 4983 gain, |
| 4984 use->instruction()->ToCString()); | 4984 use->instruction()->ToCString()); |
| 4985 } | 4985 } |
| 4986 } | 4986 } |
| 4987 } | 4987 } |
| 4988 } | 4988 } |
| 4989 | 4989 |
| 4990 processed->AddAll(worklist.contains_vector()); | 4990 processed->AddAll(worklist.contains_vector()); |
| 4991 | 4991 |
| 4992 if (FLAG_trace_smi_widening) { | 4992 if (FLAG_support_il_printer && FLAG_trace_smi_widening) { |
| 4993 THR_Print("~ %s gain %" Pd "\n", op->ToCString(), gain); | 4993 THR_Print("~ %s gain %" Pd "\n", op->ToCString(), gain); |
| 4994 } | 4994 } |
| 4995 | 4995 |
| 4996 if (gain > 0) { | 4996 if (gain > 0) { |
| 4997 // We have positive gain from widening. Convert all BinarySmiOpInstr into | 4997 // We have positive gain from widening. Convert all BinarySmiOpInstr into |
| 4998 // BinaryInt32OpInstr and set representation of all phis to kUnboxedInt32. | 4998 // BinaryInt32OpInstr and set representation of all phis to kUnboxedInt32. |
| 4999 for (intptr_t j = 0; j < worklist.definitions().length(); j++) { | 4999 for (intptr_t j = 0; j < worklist.definitions().length(); j++) { |
| 5000 Definition* defn = worklist.definitions()[j]; | 5000 Definition* defn = worklist.definitions()[j]; |
| 5001 ASSERT(defn->IsPhi() || defn->IsBinarySmiOp()); | 5001 ASSERT(defn->IsPhi() || defn->IsBinarySmiOp()); |
| 5002 | 5002 |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5047 // the code for this instruction, however, leaving the environment | 5047 // the code for this instruction, however, leaving the environment |
| 5048 // changes code. | 5048 // changes code. |
| 5049 current->RemoveEnvironment(); | 5049 current->RemoveEnvironment(); |
| 5050 } | 5050 } |
| 5051 } | 5051 } |
| 5052 } | 5052 } |
| 5053 } | 5053 } |
| 5054 | 5054 |
| 5055 | 5055 |
| 5056 } // namespace dart | 5056 } // namespace dart |
| OLD | NEW |