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" |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
47 OS::Print("Removing v%d.\n", instr->ssa_temp_index()); | 47 OS::Print("Removing v%d.\n", instr->ssa_temp_index()); |
48 } | 48 } |
49 it.RemoveCurrentFromGraph(); | 49 it.RemoveCurrentFromGraph(); |
50 } | 50 } |
51 } | 51 } |
52 } | 52 } |
53 } | 53 } |
54 } | 54 } |
55 | 55 |
56 | 56 |
| 57 static Computation* CreateConversion(Representation from, |
| 58 Representation to, |
| 59 Definition* def, |
| 60 Instruction* deopt_target) { |
| 61 if ((from == kUnboxedDouble) && (to == kTagged)) { |
| 62 return new BoxDoubleComp(new Value(def), NULL); |
| 63 } else if ((from == kTagged) && (to == kUnboxedDouble)) { |
| 64 const intptr_t deopt_id = (deopt_target != NULL) ? |
| 65 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; |
| 66 ASSERT((deopt_target != NULL) || (def->GetPropagatedCid() == kDoubleCid)); |
| 67 return new UnboxDoubleComp(new Value(def), deopt_id); |
| 68 } else { |
| 69 UNREACHABLE(); |
| 70 return NULL; |
| 71 } |
| 72 } |
| 73 |
| 74 |
| 75 void FlowGraphOptimizer::InsertConversionsFor(Definition* def) { |
| 76 const Representation from_rep = def->representation(); |
| 77 |
| 78 for (Value* use = def->input_use_list(); |
| 79 use != NULL; |
| 80 use = use->next_use()) { |
| 81 const Representation to_rep = |
| 82 use->instruction()->RequiredInputRepresentation(use->use_index()); |
| 83 if (from_rep == to_rep) { |
| 84 continue; |
| 85 } |
| 86 |
| 87 Instruction* deopt_target = NULL; |
| 88 Instruction* instr = use->instruction(); |
| 89 if (instr->IsPhi()) { |
| 90 if (!instr->AsPhi()->is_alive()) continue; |
| 91 |
| 92 // For phis conversions have to be inserted in the predecessor. |
| 93 const BlockEntryInstr* pred = |
| 94 instr->AsPhi()->block()->PredecessorAt(use->use_index()); |
| 95 instr = pred->last_instruction(); |
| 96 } else { |
| 97 deopt_target = instr; |
| 98 } |
| 99 |
| 100 BindInstr* converted = InsertBefore( |
| 101 instr, |
| 102 CreateConversion(from_rep, to_rep, def, deopt_target), |
| 103 use->instruction()->env(), |
| 104 BindInstr::kUsed); |
| 105 |
| 106 use->set_definition(converted); |
| 107 } |
| 108 } |
| 109 |
| 110 void FlowGraphOptimizer::SelectRepresentations() { |
| 111 // Convervatively unbox all phis that were proven to be of type Double. |
| 112 for (intptr_t i = 0; i < block_order_.length(); ++i) { |
| 113 JoinEntryInstr* join_entry = block_order_[i]->AsJoinEntry(); |
| 114 if (join_entry == NULL) continue; |
| 115 |
| 116 if (join_entry->phis() != NULL) { |
| 117 for (intptr_t i = 0; i < join_entry->phis()->length(); ++i) { |
| 118 PhiInstr* phi = (*join_entry->phis())[i]; |
| 119 if ((phi != NULL) && (phi->GetPropagatedCid() == kDoubleCid)) { |
| 120 phi->set_representation(kUnboxedDouble); |
| 121 } |
| 122 } |
| 123 } |
| 124 } |
| 125 |
| 126 // Process all instructions and insert conversions where needed. |
| 127 GraphEntryInstr* graph_entry = block_order_[0]->AsGraphEntry(); |
| 128 |
| 129 // Visit incoming parameters. |
| 130 for (intptr_t i = 0; i < graph_entry->start_env()->values().length(); i++) { |
| 131 Value* val = graph_entry->start_env()->values()[i]; |
| 132 InsertConversionsFor(val->definition()); |
| 133 } |
| 134 |
| 135 for (intptr_t i = 0; i < block_order_.length(); ++i) { |
| 136 BlockEntryInstr* entry = block_order_[i]; |
| 137 |
| 138 JoinEntryInstr* join_entry = entry->AsJoinEntry(); |
| 139 if ((join_entry != NULL) && (join_entry->phis() != NULL)) { |
| 140 for (intptr_t i = 0; i < join_entry->phis()->length(); ++i) { |
| 141 PhiInstr* phi = (*join_entry->phis())[i]; |
| 142 if ((phi != NULL) && (phi->is_alive())) { |
| 143 InsertConversionsFor(phi); |
| 144 } |
| 145 } |
| 146 } |
| 147 |
| 148 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) { |
| 149 Definition* def = it.Current()->AsDefinition(); |
| 150 if (def != NULL) { |
| 151 InsertConversionsFor(def); |
| 152 } |
| 153 } |
| 154 } |
| 155 } |
| 156 |
| 157 |
57 static bool ICDataHasReceiverClassId(const ICData& ic_data, intptr_t class_id) { | 158 static bool ICDataHasReceiverClassId(const ICData& ic_data, intptr_t class_id) { |
58 ASSERT(ic_data.num_args_tested() > 0); | 159 ASSERT(ic_data.num_args_tested() > 0); |
59 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { | 160 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { |
60 const intptr_t test_class_id = ic_data.GetReceiverClassIdAt(i); | 161 const intptr_t test_class_id = ic_data.GetReceiverClassIdAt(i); |
61 if (test_class_id == class_id) { | 162 if (test_class_id == class_id) { |
62 return true; | 163 return true; |
63 } | 164 } |
64 } | 165 } |
65 return false; | 166 return false; |
66 } | 167 } |
(...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
334 | 435 |
335 ASSERT(comp->ArgumentCount() == 2); | 436 ASSERT(comp->ArgumentCount() == 2); |
336 if (operands_type == kDoubleCid) { | 437 if (operands_type == kDoubleCid) { |
337 if (FLAG_use_unboxed_doubles) { | 438 if (FLAG_use_unboxed_doubles) { |
338 Value* left = comp->ArgumentAt(0)->value(); | 439 Value* left = comp->ArgumentAt(0)->value(); |
339 Value* right = comp->ArgumentAt(1)->value(); | 440 Value* right = comp->ArgumentAt(1)->value(); |
340 | 441 |
341 // Check that either left or right are not a smi. Result or a | 442 // Check that either left or right are not a smi. Result or a |
342 // binary operation with two smis is a smi not a double. | 443 // binary operation with two smis is a smi not a double. |
343 InsertBefore(instr, | 444 InsertBefore(instr, |
344 new CheckEitherNonSmiComp(left, right, comp), | 445 new CheckEitherNonSmiComp(left->Copy(), |
| 446 right->Copy(), |
| 447 comp), |
345 instr->env(), | 448 instr->env(), |
346 BindInstr::kUnused); | 449 BindInstr::kUnused); |
347 | 450 |
348 // Unbox operands. | |
349 BindInstr* unbox_left = InsertBefore( | |
350 instr, | |
351 new UnboxDoubleComp(left->Copy(), comp), | |
352 instr->env(), | |
353 BindInstr::kUsed); | |
354 BindInstr* unbox_right = InsertBefore( | |
355 instr, | |
356 new UnboxDoubleComp(right->Copy(), comp), | |
357 instr->env(), | |
358 BindInstr::kUsed); | |
359 | |
360 UnboxedDoubleBinaryOpComp* double_bin_op = | 451 UnboxedDoubleBinaryOpComp* double_bin_op = |
361 new UnboxedDoubleBinaryOpComp(op_kind, | 452 new UnboxedDoubleBinaryOpComp(op_kind, |
362 new Value(unbox_left), | 453 left->Copy(), |
363 new Value(unbox_right)); | 454 right->Copy(), |
| 455 comp); |
364 double_bin_op->set_ic_data(comp->ic_data()); | 456 double_bin_op->set_ic_data(comp->ic_data()); |
365 instr->set_computation(double_bin_op); | 457 instr->set_computation(double_bin_op); |
366 | 458 |
367 if (instr->is_used()) { | |
368 // Box result. | |
369 Value* value = new Value(instr); | |
370 BindInstr* bind = InsertAfter(instr, | |
371 new BoxDoubleComp(value, comp), | |
372 NULL, | |
373 BindInstr::kUsed); | |
374 instr->ReplaceUsesWith(bind); | |
375 } | |
376 | |
377 RemovePushArguments(comp); | 459 RemovePushArguments(comp); |
378 } else { | 460 } else { |
379 BinaryDoubleOpComp* double_bin_op = new BinaryDoubleOpComp(op_kind, comp); | 461 BinaryDoubleOpComp* double_bin_op = new BinaryDoubleOpComp(op_kind, comp); |
380 double_bin_op->set_ic_data(comp->ic_data()); | 462 double_bin_op->set_ic_data(comp->ic_data()); |
381 instr->set_computation(double_bin_op); | 463 instr->set_computation(double_bin_op); |
382 } | 464 } |
383 } else if (operands_type == kMintCid) { | 465 } else if (operands_type == kMintCid) { |
384 Value* left = comp->ArgumentAt(0)->value(); | 466 Value* left = comp->ArgumentAt(0)->value(); |
385 Value* right = comp->ArgumentAt(1)->value(); | 467 Value* right = comp->ArgumentAt(1)->value(); |
386 BinaryMintOpComp* bin_op = new BinaryMintOpComp(op_kind, | 468 BinaryMintOpComp* bin_op = new BinaryMintOpComp(op_kind, |
(...skipping 679 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1066 DirectChainedHashMap<BindInstr*> child_map(*map); // Copy map. | 1148 DirectChainedHashMap<BindInstr*> child_map(*map); // Copy map. |
1067 OptimizeRecursive(child, &child_map); | 1149 OptimizeRecursive(child, &child_map); |
1068 } else { | 1150 } else { |
1069 OptimizeRecursive(child, map); // Reuse map for the last child. | 1151 OptimizeRecursive(child, map); // Reuse map for the last child. |
1070 } | 1152 } |
1071 } | 1153 } |
1072 } | 1154 } |
1073 | 1155 |
1074 | 1156 |
1075 } // namespace dart | 1157 } // namespace dart |
OLD | NEW |