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/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 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
141 | 141 |
142 void FlowGraphOptimizer::SelectRepresentations() { | 142 void FlowGraphOptimizer::SelectRepresentations() { |
143 // Convervatively unbox all phis that were proven to be of type Double. | 143 // Convervatively unbox all phis that were proven to be of type Double. |
144 for (intptr_t i = 0; i < block_order_.length(); ++i) { | 144 for (intptr_t i = 0; i < block_order_.length(); ++i) { |
145 JoinEntryInstr* join_entry = block_order_[i]->AsJoinEntry(); | 145 JoinEntryInstr* join_entry = block_order_[i]->AsJoinEntry(); |
146 if (join_entry == NULL) continue; | 146 if (join_entry == NULL) continue; |
147 | 147 |
148 if (join_entry->phis() != NULL) { | 148 if (join_entry->phis() != NULL) { |
149 for (intptr_t i = 0; i < join_entry->phis()->length(); ++i) { | 149 for (intptr_t i = 0; i < join_entry->phis()->length(); ++i) { |
150 PhiInstr* phi = (*join_entry->phis())[i]; | 150 PhiInstr* phi = (*join_entry->phis())[i]; |
151 if ((phi != NULL) && (phi->GetPropagatedCid() == kDoubleCid)) { | 151 if (phi == NULL) continue; |
| 152 if (phi->GetPropagatedCid() == kDoubleCid) { |
152 phi->set_representation(kUnboxedDouble); | 153 phi->set_representation(kUnboxedDouble); |
153 } | 154 } |
154 } | 155 } |
155 } | 156 } |
156 } | 157 } |
157 | 158 |
158 // Process all instructions and insert conversions where needed. | 159 // Process all instructions and insert conversions where needed. |
159 GraphEntryInstr* graph_entry = block_order_[0]->AsGraphEntry(); | 160 GraphEntryInstr* graph_entry = block_order_[0]->AsGraphEntry(); |
160 | 161 |
161 // Visit incoming parameters and constants. | 162 // Visit incoming parameters and constants. |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
261 if (ic_data.NumberOfChecks() == 1) { | 262 if (ic_data.NumberOfChecks() == 1) { |
262 return ICDataHasReceiverClassId(ic_data, kSmiCid) | 263 return ICDataHasReceiverClassId(ic_data, kSmiCid) |
263 || ICDataHasReceiverClassId(ic_data, kMintCid); | 264 || ICDataHasReceiverClassId(ic_data, kMintCid); |
264 } | 265 } |
265 return (ic_data.NumberOfChecks() == 2) | 266 return (ic_data.NumberOfChecks() == 2) |
266 && ICDataHasReceiverClassId(ic_data, kSmiCid) | 267 && ICDataHasReceiverClassId(ic_data, kSmiCid) |
267 && ICDataHasReceiverClassId(ic_data, kMintCid); | 268 && ICDataHasReceiverClassId(ic_data, kMintCid); |
268 } | 269 } |
269 | 270 |
270 | 271 |
271 static bool HasOnlyTwoSmi(const ICData& ic_data) { | 272 static bool HasOnlyTwoSmis(const ICData& ic_data) { |
272 return (ic_data.NumberOfChecks() == 1) && | 273 return (ic_data.NumberOfChecks() == 1) && |
273 ICDataHasReceiverArgumentClassIds(ic_data, kSmiCid, kSmiCid); | 274 ICDataHasReceiverArgumentClassIds(ic_data, kSmiCid, kSmiCid); |
274 } | 275 } |
275 | 276 |
276 | 277 |
277 // Returns false if the ICData contains anything other than the 4 combinations | 278 // Returns false if the ICData contains anything other than the 4 combinations |
278 // of Mint and Smi for the receiver and argument classes. | 279 // of Mint and Smi for the receiver and argument classes. |
279 static bool HasTwoMintOrSmi(const ICData& ic_data) { | 280 static bool HasTwoMintOrSmi(const ICData& ic_data) { |
280 GrowableArray<intptr_t> class_ids(2); | 281 GrowableArray<intptr_t> class_ids(2); |
281 class_ids.Add(kSmiCid); | 282 class_ids.Add(kSmiCid); |
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
467 | 468 |
468 | 469 |
469 bool FlowGraphOptimizer::TryReplaceWithBinaryOp(InstanceCallInstr* call, | 470 bool FlowGraphOptimizer::TryReplaceWithBinaryOp(InstanceCallInstr* call, |
470 Token::Kind op_kind) { | 471 Token::Kind op_kind) { |
471 intptr_t operands_type = kIllegalCid; | 472 intptr_t operands_type = kIllegalCid; |
472 ASSERT(call->HasICData()); | 473 ASSERT(call->HasICData()); |
473 const ICData& ic_data = *call->ic_data(); | 474 const ICData& ic_data = *call->ic_data(); |
474 switch (op_kind) { | 475 switch (op_kind) { |
475 case Token::kADD: | 476 case Token::kADD: |
476 case Token::kSUB: | 477 case Token::kSUB: |
477 if (HasOnlyTwoSmi(ic_data)) { | 478 if (HasOnlyTwoSmis(ic_data)) { |
478 operands_type = kSmiCid; | 479 operands_type = kSmiCid; |
479 } else if (HasTwoMintOrSmi(ic_data) && | 480 } else if (HasTwoMintOrSmi(ic_data) && |
480 FlowGraphCompiler::SupportsUnboxedMints()) { | 481 FlowGraphCompiler::SupportsUnboxedMints()) { |
481 operands_type = kMintCid; | 482 operands_type = kMintCid; |
482 } else if (ShouldSpecializeForDouble(ic_data)) { | 483 } else if (ShouldSpecializeForDouble(ic_data)) { |
483 operands_type = kDoubleCid; | 484 operands_type = kDoubleCid; |
484 } else { | 485 } else { |
485 return false; | 486 return false; |
486 } | 487 } |
487 break; | 488 break; |
488 case Token::kMUL: | 489 case Token::kMUL: |
489 if (HasOnlyTwoSmi(ic_data)) { | 490 if (HasOnlyTwoSmis(ic_data)) { |
490 operands_type = kSmiCid; | 491 operands_type = kSmiCid; |
491 } else if (ShouldSpecializeForDouble(ic_data)) { | 492 } else if (ShouldSpecializeForDouble(ic_data)) { |
492 operands_type = kDoubleCid; | 493 operands_type = kDoubleCid; |
493 } else { | 494 } else { |
494 return false; | 495 return false; |
495 } | 496 } |
496 break; | 497 break; |
497 case Token::kDIV: | 498 case Token::kDIV: |
498 if (ShouldSpecializeForDouble(ic_data)) { | 499 if (ShouldSpecializeForDouble(ic_data)) { |
499 operands_type = kDoubleCid; | 500 operands_type = kDoubleCid; |
500 } else { | 501 } else { |
501 return false; | 502 return false; |
502 } | 503 } |
503 break; | 504 break; |
504 case Token::kMOD: | 505 case Token::kMOD: |
505 if (HasOnlyTwoSmi(ic_data)) { | 506 if (HasOnlyTwoSmis(ic_data)) { |
506 operands_type = kSmiCid; | 507 operands_type = kSmiCid; |
507 } else { | 508 } else { |
508 return false; | 509 return false; |
509 } | 510 } |
510 break; | 511 break; |
511 case Token::kBIT_AND: | 512 case Token::kBIT_AND: |
512 case Token::kBIT_OR: | 513 case Token::kBIT_OR: |
513 case Token::kBIT_XOR: | 514 case Token::kBIT_XOR: |
514 if (HasOnlyTwoSmi(ic_data)) { | 515 if (HasOnlyTwoSmis(ic_data)) { |
515 operands_type = kSmiCid; | 516 operands_type = kSmiCid; |
516 } else if (HasTwoMintOrSmi(ic_data) && | 517 } else if (HasTwoMintOrSmi(ic_data) && |
517 FlowGraphCompiler::SupportsUnboxedMints()) { | 518 FlowGraphCompiler::SupportsUnboxedMints()) { |
518 operands_type = kMintCid; | 519 operands_type = kMintCid; |
519 } else { | 520 } else { |
520 return false; | 521 return false; |
521 } | 522 } |
522 break; | 523 break; |
| 524 case Token::kSHR: |
| 525 if (HasOnlyTwoSmis(ic_data)) { |
| 526 operands_type = kSmiCid; |
| 527 } else if (HasTwoMintOrSmi(ic_data) && |
| 528 FlowGraphCompiler::SupportsUnboxedMints()) { |
| 529 operands_type = kMintCid; |
| 530 } else { |
| 531 return false; |
| 532 } |
| 533 break; |
523 case Token::kTRUNCDIV: | 534 case Token::kTRUNCDIV: |
524 case Token::kSHR: | |
525 case Token::kSHL: | 535 case Token::kSHL: |
526 if (HasOnlyTwoSmi(ic_data)) { | 536 if (HasOnlyTwoSmis(ic_data)) { |
527 operands_type = kSmiCid; | 537 operands_type = kSmiCid; |
528 } else { | 538 } else { |
529 return false; | 539 return false; |
530 } | 540 } |
531 break; | 541 break; |
532 default: | 542 default: |
533 UNREACHABLE(); | 543 UNREACHABLE(); |
534 }; | 544 }; |
535 | 545 |
536 ASSERT(call->ArgumentCount() == 2); | 546 ASSERT(call->ArgumentCount() == 2); |
(...skipping 10 matching lines...) Expand all Loading... |
547 call->env(), | 557 call->env(), |
548 Definition::kEffect); | 558 Definition::kEffect); |
549 | 559 |
550 BinaryDoubleOpInstr* double_bin_op = | 560 BinaryDoubleOpInstr* double_bin_op = |
551 new BinaryDoubleOpInstr(op_kind, left->Copy(), right->Copy(), call); | 561 new BinaryDoubleOpInstr(op_kind, left->Copy(), right->Copy(), call); |
552 call->ReplaceWith(double_bin_op, current_iterator()); | 562 call->ReplaceWith(double_bin_op, current_iterator()); |
553 RemovePushArguments(call); | 563 RemovePushArguments(call); |
554 } else if (operands_type == kMintCid) { | 564 } else if (operands_type == kMintCid) { |
555 Value* left = call->ArgumentAt(0)->value(); | 565 Value* left = call->ArgumentAt(0)->value(); |
556 Value* right = call->ArgumentAt(1)->value(); | 566 Value* right = call->ArgumentAt(1)->value(); |
557 BinaryMintOpInstr* bin_op = | 567 if (op_kind == Token::kSHR) { |
558 new BinaryMintOpInstr(op_kind, left, right, call); | 568 ShiftMintOpInstr* shift_op = |
559 call->ReplaceWith(bin_op, current_iterator()); | 569 new ShiftMintOpInstr(op_kind, left, right, call); |
| 570 call->ReplaceWith(shift_op, current_iterator()); |
| 571 } else { |
| 572 BinaryMintOpInstr* bin_op = |
| 573 new BinaryMintOpInstr(op_kind, left, right, call); |
| 574 call->ReplaceWith(bin_op, current_iterator()); |
| 575 } |
560 RemovePushArguments(call); | 576 RemovePushArguments(call); |
561 } else if (op_kind == Token::kMOD) { | 577 } else if (op_kind == Token::kMOD) { |
562 // TODO(vegorov): implement fast path code for modulo. | 578 // TODO(vegorov): implement fast path code for modulo. |
563 ASSERT(operands_type == kSmiCid); | 579 ASSERT(operands_type == kSmiCid); |
564 if (!call->ArgumentAt(1)->value()->BindsToConstant()) return false; | 580 if (!call->ArgumentAt(1)->value()->BindsToConstant()) return false; |
565 const Object& obj = call->ArgumentAt(1)->value()->BoundConstant(); | 581 const Object& obj = call->ArgumentAt(1)->value()->BoundConstant(); |
566 if (!obj.IsSmi()) return false; | 582 if (!obj.IsSmi()) return false; |
567 const intptr_t value = Smi::Cast(obj).Value(); | 583 const intptr_t value = Smi::Cast(obj).Value(); |
568 if ((value > 0) && Utils::IsPowerOfTwo(value)) { | 584 if ((value > 0) && Utils::IsPowerOfTwo(value)) { |
569 Value* left = call->ArgumentAt(0)->value(); | 585 Value* left = call->ArgumentAt(0)->value(); |
(...skipping 465 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1035 RelationalOpInstr* comp, | 1051 RelationalOpInstr* comp, |
1036 Instruction* instr) { | 1052 Instruction* instr) { |
1037 if (!comp->HasICData()) return; | 1053 if (!comp->HasICData()) return; |
1038 | 1054 |
1039 const ICData& ic_data = *comp->ic_data(); | 1055 const ICData& ic_data = *comp->ic_data(); |
1040 if (ic_data.NumberOfChecks() == 0) return; | 1056 if (ic_data.NumberOfChecks() == 0) return; |
1041 // TODO(srdjan): Add multiple receiver type support. | 1057 // TODO(srdjan): Add multiple receiver type support. |
1042 if (ic_data.NumberOfChecks() != 1) return; | 1058 if (ic_data.NumberOfChecks() != 1) return; |
1043 ASSERT(ic_data.HasOneTarget()); | 1059 ASSERT(ic_data.HasOneTarget()); |
1044 | 1060 |
1045 if (HasOnlyTwoSmi(ic_data)) { | 1061 if (HasOnlyTwoSmis(ic_data)) { |
1046 optimizer->InsertBefore( | 1062 optimizer->InsertBefore( |
1047 instr, | 1063 instr, |
1048 new CheckSmiInstr(comp->left()->Copy(), comp->deopt_id()), | 1064 new CheckSmiInstr(comp->left()->Copy(), comp->deopt_id()), |
1049 instr->env(), | 1065 instr->env(), |
1050 Definition::kEffect); | 1066 Definition::kEffect); |
1051 optimizer->InsertBefore( | 1067 optimizer->InsertBefore( |
1052 instr, | 1068 instr, |
1053 new CheckSmiInstr(comp->right()->Copy(), comp->deopt_id()), | 1069 new CheckSmiInstr(comp->right()->Copy(), comp->deopt_id()), |
1054 instr->env(), | 1070 instr->env(), |
1055 Definition::kEffect); | 1071 Definition::kEffect); |
(...skipping 1920 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2976 } | 2992 } |
2977 | 2993 |
2978 | 2994 |
2979 void ConstantPropagator::VisitBinaryMintOp( | 2995 void ConstantPropagator::VisitBinaryMintOp( |
2980 BinaryMintOpInstr* instr) { | 2996 BinaryMintOpInstr* instr) { |
2981 // TODO(kmillikin): Handle binary operations. | 2997 // TODO(kmillikin): Handle binary operations. |
2982 SetValue(instr, non_constant_); | 2998 SetValue(instr, non_constant_); |
2983 } | 2999 } |
2984 | 3000 |
2985 | 3001 |
| 3002 void ConstantPropagator::VisitShiftMintOp( |
| 3003 ShiftMintOpInstr* instr) { |
| 3004 // TODO(kmillikin): Handle shift operations. |
| 3005 SetValue(instr, non_constant_); |
| 3006 } |
| 3007 |
| 3008 |
2986 void ConstantPropagator::VisitUnaryMintOp( | 3009 void ConstantPropagator::VisitUnaryMintOp( |
2987 UnaryMintOpInstr* instr) { | 3010 UnaryMintOpInstr* instr) { |
2988 // TODO(kmillikin): Handle unary operations. | 3011 // TODO(kmillikin): Handle unary operations. |
2989 SetValue(instr, non_constant_); | 3012 SetValue(instr, non_constant_); |
2990 } | 3013 } |
2991 | 3014 |
2992 | 3015 |
2993 void ConstantPropagator::VisitUnarySmiOp(UnarySmiOpInstr* instr) { | 3016 void ConstantPropagator::VisitUnarySmiOp(UnarySmiOpInstr* instr) { |
2994 const Object& value = instr->value()->definition()->constant_value(); | 3017 const Object& value = instr->value()->definition()->constant_value(); |
2995 if (IsNonConstant(value)) { | 3018 if (IsNonConstant(value)) { |
(...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3226 | 3249 |
3227 if (FLAG_trace_constant_propagation) { | 3250 if (FLAG_trace_constant_propagation) { |
3228 OS::Print("\n==== After constant propagation ====\n"); | 3251 OS::Print("\n==== After constant propagation ====\n"); |
3229 FlowGraphPrinter printer(*graph_); | 3252 FlowGraphPrinter printer(*graph_); |
3230 printer.PrintBlocks(); | 3253 printer.PrintBlocks(); |
3231 } | 3254 } |
3232 } | 3255 } |
3233 | 3256 |
3234 | 3257 |
3235 } // namespace dart | 3258 } // namespace dart |
OLD | NEW |