| 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 |