OLD | NEW |
---|---|
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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/cha.h" | 7 #include "vm/cha.h" |
8 #include "vm/flow_graph_builder.h" | 8 #include "vm/flow_graph_builder.h" |
9 #include "vm/hash_map.h" | 9 #include "vm/hash_map.h" |
10 #include "vm/il_printer.h" | 10 #include "vm/il_printer.h" |
11 #include "vm/object_store.h" | 11 #include "vm/object_store.h" |
12 #include "vm/parser.h" | 12 #include "vm/parser.h" |
13 #include "vm/scopes.h" | 13 #include "vm/scopes.h" |
14 #include "vm/symbols.h" | 14 #include "vm/symbols.h" |
15 | 15 |
16 namespace dart { | 16 namespace dart { |
17 | 17 |
18 DECLARE_FLAG(bool, eliminate_type_checks); | 18 DECLARE_FLAG(bool, eliminate_type_checks); |
19 DECLARE_FLAG(bool, enable_type_checks); | 19 DECLARE_FLAG(bool, enable_type_checks); |
20 DEFINE_FLAG(bool, trace_optimization, false, "Print optimization details."); | 20 DEFINE_FLAG(bool, trace_optimization, false, "Print optimization details."); |
21 DECLARE_FLAG(bool, trace_type_check_elimination); | 21 DECLARE_FLAG(bool, trace_type_check_elimination); |
22 DEFINE_FLAG(bool, use_cha, true, "Use class hierarchy analysis."); | 22 DEFINE_FLAG(bool, use_cha, true, "Use class hierarchy analysis."); |
23 DEFINE_FLAG(bool, use_unboxed_doubles, true, "Try unboxing double values."); | |
23 | 24 |
24 void FlowGraphOptimizer::ApplyICData() { | 25 void FlowGraphOptimizer::ApplyICData() { |
25 VisitBlocks(); | 26 VisitBlocks(); |
26 } | 27 } |
27 | 28 |
28 | 29 |
29 void FlowGraphOptimizer::OptimizeComputations() { | 30 void FlowGraphOptimizer::OptimizeComputations() { |
30 for (intptr_t i = 0; i < block_order_.length(); ++i) { | 31 for (intptr_t i = 0; i < block_order_.length(); ++i) { |
31 BlockEntryInstr* entry = block_order_[i]; | 32 BlockEntryInstr* entry = block_order_[i]; |
32 entry->Accept(this); | 33 entry->Accept(this); |
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
242 instr->set_computation(array_op); | 243 instr->set_computation(array_op); |
243 RemovePushArguments(comp); | 244 RemovePushArguments(comp); |
244 return true; | 245 return true; |
245 } | 246 } |
246 default: | 247 default: |
247 return false; | 248 return false; |
248 } | 249 } |
249 } | 250 } |
250 | 251 |
251 | 252 |
253 Value* FlowGraphOptimizer::InsertBefore(Instruction* instr, | |
254 Computation* comp, | |
255 Environment* env) { | |
256 BindInstr* bind = new BindInstr(BindInstr::kUsed, comp); | |
257 bind->set_env(env->Clone()); | |
Florian Schneider
2012/08/24 11:09:28
Use Environment::Copy?
Vyacheslav Egorov (Google)
2012/08/24 13:23:01
Done.
| |
258 bind->set_ssa_temp_index(flow_graph_->alloc_ssa_temp_index()); | |
259 | |
260 bind->InsertBefore(instr); | |
261 | |
262 return new UseVal(bind); | |
263 } | |
264 | |
265 | |
266 BindInstr* FlowGraphOptimizer::InsertAfter(Instruction* instr, | |
267 Computation* comp) { | |
268 BindInstr* bind = new BindInstr(BindInstr::kUsed, comp); | |
269 bind->set_ssa_temp_index(flow_graph_->alloc_ssa_temp_index()); | |
270 | |
271 Instruction* next = instr->next(); | |
272 instr->set_next(bind); | |
273 bind->set_previous(instr); | |
274 bind->set_next(next); | |
275 next->set_previous(bind); | |
276 | |
277 return bind; | |
278 } | |
279 | |
280 | |
252 bool FlowGraphOptimizer::TryReplaceWithBinaryOp(BindInstr* instr, | 281 bool FlowGraphOptimizer::TryReplaceWithBinaryOp(BindInstr* instr, |
253 InstanceCallComp* comp, | 282 InstanceCallComp* comp, |
254 Token::Kind op_kind) { | 283 Token::Kind op_kind) { |
255 intptr_t operands_type = kIllegalCid; | 284 intptr_t operands_type = kIllegalCid; |
256 ASSERT(comp->HasICData()); | 285 ASSERT(comp->HasICData()); |
257 const ICData& ic_data = *comp->ic_data(); | 286 const ICData& ic_data = *comp->ic_data(); |
258 switch (op_kind) { | 287 switch (op_kind) { |
259 case Token::kADD: | 288 case Token::kADD: |
260 case Token::kSUB: | 289 case Token::kSUB: |
261 case Token::kMUL: | 290 case Token::kMUL: |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
293 } else { | 322 } else { |
294 return false; | 323 return false; |
295 } | 324 } |
296 break; | 325 break; |
297 default: | 326 default: |
298 UNREACHABLE(); | 327 UNREACHABLE(); |
299 }; | 328 }; |
300 | 329 |
301 ASSERT(comp->ArgumentCount() == 2); | 330 ASSERT(comp->ArgumentCount() == 2); |
302 if (operands_type == kDoubleCid) { | 331 if (operands_type == kDoubleCid) { |
303 BinaryDoubleOpComp* double_bin_op = new BinaryDoubleOpComp(op_kind, comp); | 332 if (FLAG_use_unboxed_doubles) { |
304 double_bin_op->set_ic_data(comp->ic_data()); | 333 Value* left = comp->ArgumentAt(0)->value(); |
305 instr->set_computation(double_bin_op); | 334 Value* right = comp->ArgumentAt(1)->value(); |
335 | |
336 CheckEitherNonSmiComp* check = | |
337 new CheckEitherNonSmiComp(left, right, comp); | |
338 BindInstr* check_instr = new BindInstr(BindInstr::kUnused, check); | |
339 check_instr->set_env(instr->env()); | |
340 check_instr->InsertBefore(instr); | |
341 | |
342 Value* unbox_left = | |
343 InsertBefore(instr, new UnboxDoubleComp(left, comp), instr->env()); | |
Florian Schneider
2012/08/24 11:09:28
Since left and right are used multiple times now,
Vyacheslav Egorov (Google)
2012/08/24 13:23:01
Done.
| |
344 Value* unbox_right = | |
345 InsertBefore(instr, new UnboxDoubleComp(right, comp), instr->env()); | |
346 UnboxedDoubleBinaryOpComp* double_bin_op = | |
347 new UnboxedDoubleBinaryOpComp(op_kind, comp, unbox_left, unbox_right); | |
348 double_bin_op->set_ic_data(comp->ic_data()); | |
349 instr->set_computation(double_bin_op); | |
350 if (instr->is_used()) { | |
351 UseVal* use_val = new UseVal(instr); | |
352 BindInstr* bind = InsertAfter(instr, new BoxDoubleComp(use_val, comp)); | |
353 instr->ReplaceUsesWith(bind); | |
354 use_val->SetDefinition(instr); | |
355 } | |
356 RemovePushArguments(comp); | |
357 } else { | |
358 BinaryDoubleOpComp* double_bin_op = new BinaryDoubleOpComp(op_kind, comp); | |
359 double_bin_op->set_ic_data(comp->ic_data()); | |
360 instr->set_computation(double_bin_op); | |
361 } | |
306 } else if (operands_type == kMintCid) { | 362 } else if (operands_type == kMintCid) { |
307 Value* left = comp->ArgumentAt(0)->value(); | 363 Value* left = comp->ArgumentAt(0)->value(); |
308 Value* right = comp->ArgumentAt(1)->value(); | 364 Value* right = comp->ArgumentAt(1)->value(); |
309 BinaryMintOpComp* bin_op = new BinaryMintOpComp(op_kind, | 365 BinaryMintOpComp* bin_op = new BinaryMintOpComp(op_kind, |
310 comp, | 366 comp, |
311 left, | 367 left, |
312 right); | 368 right); |
313 bin_op->set_ic_data(comp->ic_data()); | 369 bin_op->set_ic_data(comp->ic_data()); |
314 instr->set_computation(bin_op); | 370 instr->set_computation(bin_op); |
315 RemovePushArguments(comp); | 371 RemovePushArguments(comp); |
(...skipping 637 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
953 OS::Print("Replacing v%d with v%d\n", | 1009 OS::Print("Replacing v%d with v%d\n", |
954 instr->ssa_temp_index(), | 1010 instr->ssa_temp_index(), |
955 result->ssa_temp_index()); | 1011 result->ssa_temp_index()); |
956 } | 1012 } |
957 } | 1013 } |
958 } | 1014 } |
959 } | 1015 } |
960 | 1016 |
961 | 1017 |
962 } // namespace dart | 1018 } // namespace dart |
OLD | NEW |