Chromium Code Reviews| 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/flow_graph_builder.h" | 9 #include "vm/flow_graph_builder.h" |
| 10 #include "vm/flow_graph_compiler.h" | 10 #include "vm/flow_graph_compiler.h" |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 160 | 160 |
| 161 const bool with_checks = false; | 161 const bool with_checks = false; |
| 162 PolymorphicInstanceCallInstr* specialized = | 162 PolymorphicInstanceCallInstr* specialized = |
| 163 new PolymorphicInstanceCallInstr(call->instance_call(), | 163 new PolymorphicInstanceCallInstr(call->instance_call(), |
| 164 ic_data, | 164 ic_data, |
| 165 with_checks); | 165 with_checks); |
| 166 call->ReplaceWith(specialized, current_iterator()); | 166 call->ReplaceWith(specialized, current_iterator()); |
| 167 } | 167 } |
| 168 | 168 |
| 169 | 169 |
| 170 static BinarySmiOpInstr* AsSmiLeftShiftInstruction(Value* v) { | |
| 171 BinarySmiOpInstr* instr = v->definition()->AsBinarySmiOp(); | |
| 172 if ((instr != NULL) && (instr->op_kind() == Token::kSHL)) { | |
| 173 return instr; | |
| 174 } | |
| 175 return NULL; | |
| 176 } | |
| 177 | |
| 178 | |
| 179 Value* AsPositiveSmiConstValue(Value* v) { | |
| 180 if (v->BindsToConstant() && v->BoundConstant().IsSmi()) { | |
| 181 if (Smi::Cast(v->BoundConstant()).Value() >= 0) { | |
| 182 return v; | |
| 183 } | |
| 184 } | |
| 185 return NULL; | |
| 186 } | |
| 187 | |
| 188 | |
| 189 void FlowGraphOptimizer::OptimizeLeftShiftBitAndSmiOp( | |
|
Kevin Millikin (Google)
2013/02/21 12:44:35
I also think this kind of function is clearer if i
srdjan
2013/02/21 21:55:31
Done.
| |
| 190 Definition* bit_and_instr, | |
| 191 Value* left, | |
| 192 Value* right) { | |
| 193 // Check for pattern, smi_left_shift value must be single-use. | |
| 194 BinarySmiOpInstr* smi_left_shift = NULL; | |
| 195 Value* smi_const = AsPositiveSmiConstValue(left); | |
| 196 if (smi_const == NULL) { | |
| 197 smi_const = AsPositiveSmiConstValue(right); | |
| 198 if (left->IsSingleUse() && (smi_const != NULL)) { | |
| 199 smi_left_shift = AsSmiLeftShiftInstruction(left); | |
| 200 } | |
| 201 } else if (right->IsSingleUse()) { | |
| 202 smi_left_shift = AsSmiLeftShiftInstruction(right); | |
| 203 } | |
| 204 if ((smi_left_shift == NULL) || (smi_const == NULL)) { | |
| 205 // Not the pattern '(mint,smi)-bit-and with smi-left-shift and smi-const'. | |
| 206 return; | |
| 207 } | |
| 208 // TODO(srdjan): If done post inlining, we must check environment uses. | |
| 209 if (bit_and_instr->IsBinarySmiOp()) { | |
| 210 smi_left_shift->set_is_truncating(true); | |
| 211 } else { | |
| 212 ASSERT(bit_and_instr->IsBinaryMintOp()); | |
| 213 smi_left_shift->set_is_truncating(true); | |
| 214 // Replace Mint op with Smi op. | |
| 215 BinarySmiOpInstr* smi_op = new BinarySmiOpInstr( | |
| 216 Token::kBIT_AND, | |
| 217 bit_and_instr->AsBinaryMintOp()->instance_call(), | |
| 218 left->Copy(), | |
| 219 right->Copy()); | |
| 220 bit_and_instr->ReplaceWith(smi_op, current_iterator()); | |
| 221 } | |
| 222 } | |
| 223 | |
| 224 | |
| 225 // Optimize (a << b) & c pattern: if c is a positive smi, then the | |
| 226 // shift can be a truncating Smi shift and result is always Smi. | |
| 227 void FlowGraphOptimizer::TryOptimizeLeftShiftWithBitAndPattern() { | |
| 228 ASSERT(current_iterator_ == NULL); | |
| 229 for (intptr_t i = 0; i < block_order_.length(); ++i) { | |
| 230 BlockEntryInstr* entry = block_order_[i]; | |
| 231 ForwardInstructionIterator it(entry); | |
| 232 current_iterator_ = ⁢ | |
| 233 for (; !it.Done(); it.Advance()) { | |
| 234 if (it.Current()->IsBinarySmiOp()) { | |
| 235 BinarySmiOpInstr* binop = it.Current()->AsBinarySmiOp(); | |
| 236 if (binop->op_kind() == Token::kBIT_AND) { | |
| 237 OptimizeLeftShiftBitAndSmiOp(binop, binop->left(), binop->right()); | |
| 238 } | |
| 239 } else if (it.Current()->IsBinaryMintOp()) { | |
| 240 BinaryMintOpInstr* mintop = it.Current()->AsBinaryMintOp(); | |
| 241 if (mintop->op_kind() == Token::kBIT_AND) { | |
| 242 OptimizeLeftShiftBitAndSmiOp(mintop, mintop->left(), mintop->right()); | |
| 243 } | |
| 244 } | |
| 245 } | |
| 246 current_iterator_ = NULL; | |
| 247 } | |
| 248 } | |
| 249 | |
| 250 | |
| 170 static void EnsureSSATempIndex(FlowGraph* graph, | 251 static void EnsureSSATempIndex(FlowGraph* graph, |
| 171 Definition* defn, | 252 Definition* defn, |
| 172 Definition* replacement) { | 253 Definition* replacement) { |
| 173 if ((replacement->ssa_temp_index() == -1) && | 254 if ((replacement->ssa_temp_index() == -1) && |
| 174 (defn->ssa_temp_index() != -1)) { | 255 (defn->ssa_temp_index() != -1)) { |
| 175 replacement->set_ssa_temp_index(graph->alloc_ssa_temp_index()); | 256 replacement->set_ssa_temp_index(graph->alloc_ssa_temp_index()); |
| 176 } | 257 } |
| 177 } | 258 } |
| 178 | 259 |
| 179 | 260 |
| (...skipping 767 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 947 InsertBefore(call, constant, NULL, Definition::kValue); | 1028 InsertBefore(call, constant, NULL, Definition::kValue); |
| 948 BinarySmiOpInstr* bin_op = | 1029 BinarySmiOpInstr* bin_op = |
| 949 new BinarySmiOpInstr(Token::kBIT_AND, call, | 1030 new BinarySmiOpInstr(Token::kBIT_AND, call, |
| 950 new Value(left), | 1031 new Value(left), |
| 951 new Value(constant)); | 1032 new Value(constant)); |
| 952 ReplaceCall(call, bin_op); | 1033 ReplaceCall(call, bin_op); |
| 953 } else { | 1034 } else { |
| 954 ASSERT(operands_type == kSmiCid); | 1035 ASSERT(operands_type == kSmiCid); |
| 955 // Insert two smi checks and attach a copy of the original | 1036 // Insert two smi checks and attach a copy of the original |
| 956 // environment because the smi operation can still deoptimize. | 1037 // environment because the smi operation can still deoptimize. |
| 957 InsertBefore(call, | 1038 if (left->Type()->ToCid() != kSmiCid) { |
|
Vyacheslav Egorov (Google)
2013/02/21 14:45:50
I suggest to create a method that inserts a check:
srdjan
2013/02/21 21:55:31
Done.
| |
| 958 new CheckSmiInstr(new Value(left), call->deopt_id()), | 1039 InsertBefore(call, |
| 959 call->env(), | 1040 new CheckSmiInstr(new Value(left), call->deopt_id()), |
| 960 Definition::kEffect); | 1041 call->env(), |
| 961 InsertBefore(call, | 1042 Definition::kEffect); |
| 962 new CheckSmiInstr(new Value(right), call->deopt_id()), | 1043 } |
| 963 call->env(), | 1044 if (right->Type()->ToCid() != kSmiCid) { |
| 964 Definition::kEffect); | 1045 InsertBefore(call, |
| 1046 new CheckSmiInstr(new Value(right), call->deopt_id()), | |
| 1047 call->env(), | |
| 1048 Definition::kEffect); | |
| 1049 } | |
| 965 if (left->IsConstant() && | 1050 if (left->IsConstant() && |
| 966 ((op_kind == Token::kADD) || (op_kind == Token::kMUL))) { | 1051 ((op_kind == Token::kADD) || (op_kind == Token::kMUL))) { |
| 967 // Constant should be on the right side. | 1052 // Constant should be on the right side. |
| 968 Definition* temp = left; | 1053 Definition* temp = left; |
| 969 left = right; | 1054 left = right; |
| 970 right = temp; | 1055 right = temp; |
| 971 } | 1056 } |
| 972 BinarySmiOpInstr* bin_op = | 1057 BinarySmiOpInstr* bin_op = |
| 973 new BinarySmiOpInstr(op_kind, call, new Value(left), new Value(right)); | 1058 new BinarySmiOpInstr(op_kind, call, new Value(left), new Value(right)); |
| 974 ReplaceCall(call, bin_op); | 1059 ReplaceCall(call, bin_op); |
| (...skipping 3211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4186 | 4271 |
| 4187 if (FLAG_trace_constant_propagation) { | 4272 if (FLAG_trace_constant_propagation) { |
| 4188 OS::Print("\n==== After constant propagation ====\n"); | 4273 OS::Print("\n==== After constant propagation ====\n"); |
| 4189 FlowGraphPrinter printer(*graph_); | 4274 FlowGraphPrinter printer(*graph_); |
| 4190 printer.PrintBlocks(); | 4275 printer.PrintBlocks(); |
| 4191 } | 4276 } |
| 4192 } | 4277 } |
| 4193 | 4278 |
| 4194 | 4279 |
| 4195 } // namespace dart | 4280 } // namespace dart |
| OLD | NEW |