| 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 663 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 674 | 674 |
| 675 bool FlowGraphOptimizer::TryReplaceWithBinaryOp(InstanceCallInstr* call, | 675 bool FlowGraphOptimizer::TryReplaceWithBinaryOp(InstanceCallInstr* call, |
| 676 Token::Kind op_kind) { | 676 Token::Kind op_kind) { |
| 677 intptr_t operands_type = kIllegalCid; | 677 intptr_t operands_type = kIllegalCid; |
| 678 ASSERT(call->HasICData()); | 678 ASSERT(call->HasICData()); |
| 679 const ICData& ic_data = *call->ic_data(); | 679 const ICData& ic_data = *call->ic_data(); |
| 680 switch (op_kind) { | 680 switch (op_kind) { |
| 681 case Token::kADD: | 681 case Token::kADD: |
| 682 case Token::kSUB: | 682 case Token::kSUB: |
| 683 if (HasOnlyTwoSmis(ic_data)) { | 683 if (HasOnlyTwoSmis(ic_data)) { |
| 684 operands_type = kSmiCid; | 684 // Don't generate smi code if the IC data is marked because |
| 685 // of an overflow. |
| 686 operands_type = (ic_data.deopt_reason() == kDeoptBinarySmiOp) |
| 687 ? kMintCid |
| 688 : kSmiCid; |
| 685 } else if (HasTwoMintOrSmi(ic_data) && | 689 } else if (HasTwoMintOrSmi(ic_data) && |
| 686 FlowGraphCompiler::SupportsUnboxedMints()) { | 690 FlowGraphCompiler::SupportsUnboxedMints()) { |
| 691 // Don't generate mint code if the IC data is marked because of an |
| 692 // overflow. |
| 693 if (ic_data.deopt_reason() == kDeoptBinaryMintOp) return false; |
| 687 operands_type = kMintCid; | 694 operands_type = kMintCid; |
| 688 } else if (ShouldSpecializeForDouble(ic_data)) { | 695 } else if (ShouldSpecializeForDouble(ic_data)) { |
| 689 operands_type = kDoubleCid; | 696 operands_type = kDoubleCid; |
| 690 } else { | 697 } else { |
| 691 return false; | 698 return false; |
| 692 } | 699 } |
| 693 break; | 700 break; |
| 694 case Token::kMUL: | 701 case Token::kMUL: |
| 695 if (HasOnlyTwoSmis(ic_data)) { | 702 if (HasOnlyTwoSmis(ic_data)) { |
| 703 // Don't generate smi code if the IC data is marked because of an |
| 704 // overflow. |
| 705 // TODO(fschneider): Add unboxed mint multiplication. |
| 706 if (ic_data.deopt_reason() == kDeoptBinarySmiOp) return false; |
| 696 operands_type = kSmiCid; | 707 operands_type = kSmiCid; |
| 697 } else if (ShouldSpecializeForDouble(ic_data)) { | 708 } else if (ShouldSpecializeForDouble(ic_data)) { |
| 698 operands_type = kDoubleCid; | 709 operands_type = kDoubleCid; |
| 699 } else { | 710 } else { |
| 700 return false; | 711 return false; |
| 701 } | 712 } |
| 702 break; | 713 break; |
| 703 case Token::kDIV: | 714 case Token::kDIV: |
| 704 if (ShouldSpecializeForDouble(ic_data)) { | 715 if (ShouldSpecializeForDouble(ic_data)) { |
| 705 operands_type = kDoubleCid; | 716 operands_type = kDoubleCid; |
| 706 } else { | 717 } else { |
| 707 return false; | 718 return false; |
| 708 } | 719 } |
| 709 break; | 720 break; |
| 710 case Token::kMOD: | 721 case Token::kMOD: |
| 711 if (HasOnlyTwoSmis(ic_data)) { | 722 if (HasOnlyTwoSmis(ic_data)) { |
| 712 operands_type = kSmiCid; | 723 operands_type = kSmiCid; |
| 713 } else { | 724 } else { |
| 714 return false; | 725 return false; |
| 715 } | 726 } |
| 716 break; | 727 break; |
| 717 case Token::kBIT_AND: | 728 case Token::kBIT_AND: |
| 718 case Token::kBIT_OR: | 729 case Token::kBIT_OR: |
| 719 case Token::kBIT_XOR: | 730 case Token::kBIT_XOR: |
| 720 if (HasOnlyTwoSmis(ic_data)) { | 731 if (HasOnlyTwoSmis(ic_data)) { |
| 721 operands_type = kSmiCid; | 732 operands_type = kSmiCid; |
| 722 } else if (HasTwoMintOrSmi(ic_data) && | 733 } else if (HasTwoMintOrSmi(ic_data)) { |
| 723 FlowGraphCompiler::SupportsUnboxedMints()) { | |
| 724 operands_type = kMintCid; | 734 operands_type = kMintCid; |
| 725 } else { | 735 } else { |
| 726 return false; | 736 return false; |
| 727 } | 737 } |
| 728 break; | 738 break; |
| 729 case Token::kSHR: | 739 case Token::kSHR: |
| 730 case Token::kSHL: | 740 case Token::kSHL: |
| 731 if (HasOnlyTwoSmis(ic_data)) { | 741 if (HasOnlyTwoSmis(ic_data)) { |
| 732 operands_type = kSmiCid; | 742 // Left shift may overflow from smi into mint or big ints. |
| 733 } else if (FlowGraphCompiler::SupportsUnboxedMints() && | 743 // Don't generate smi code if the IC data is marked because |
| 734 HasTwoMintOrSmi(ic_data) && | 744 // of an overflow. |
| 745 if (ic_data.deopt_reason() == kDeoptShiftMintOp) return false; |
| 746 operands_type = (ic_data.deopt_reason() == kDeoptBinarySmiOp) |
| 747 ? kMintCid |
| 748 : kSmiCid; |
| 749 } else if (HasTwoMintOrSmi(ic_data) && |
| 735 HasOnlyOneSmi(ICData::Handle( | 750 HasOnlyOneSmi(ICData::Handle( |
| 736 ic_data.AsUnaryClassChecksForArgNr(1)))) { | 751 ic_data.AsUnaryClassChecksForArgNr(1)))) { |
| 752 // Don't generate mint code if the IC data is marked because of an |
| 753 // overflow. |
| 754 if (ic_data.deopt_reason() == kDeoptShiftMintOp) return false; |
| 737 // Check for smi/mint << smi or smi/mint >> smi. | 755 // Check for smi/mint << smi or smi/mint >> smi. |
| 738 operands_type = kMintCid; | 756 operands_type = kMintCid; |
| 739 } else { | 757 } else { |
| 740 return false; | 758 return false; |
| 741 } | 759 } |
| 742 break; | 760 break; |
| 743 case Token::kTRUNCDIV: | 761 case Token::kTRUNCDIV: |
| 744 if (HasOnlyTwoSmis(ic_data)) { | 762 if (HasOnlyTwoSmis(ic_data)) { |
| 763 if (ic_data.deopt_reason() == kDeoptBinarySmiOp) return false; |
| 745 operands_type = kSmiCid; | 764 operands_type = kSmiCid; |
| 746 } else { | 765 } else { |
| 747 return false; | 766 return false; |
| 748 } | 767 } |
| 749 break; | 768 break; |
| 750 default: | 769 default: |
| 751 UNREACHABLE(); | 770 UNREACHABLE(); |
| 752 }; | 771 }; |
| 753 | 772 |
| 754 ASSERT(call->ArgumentCount() == 2); | 773 ASSERT(call->ArgumentCount() == 2); |
| 755 if (operands_type == kDoubleCid) { | 774 if (operands_type == kDoubleCid) { |
| 756 Value* left = call->ArgumentAt(0)->value(); | 775 Value* left = call->ArgumentAt(0)->value(); |
| 757 Value* right = call->ArgumentAt(1)->value(); | 776 Value* right = call->ArgumentAt(1)->value(); |
| 758 | 777 |
| 759 // Check that either left or right are not a smi. Result or a | 778 // Check that either left or right are not a smi. Result or a |
| 760 // binary operation with two smis is a smi not a double. | 779 // binary operation with two smis is a smi not a double. |
| 761 InsertBefore(call, | 780 InsertBefore(call, |
| 762 new CheckEitherNonSmiInstr(left->Copy(), | 781 new CheckEitherNonSmiInstr(left->Copy(), |
| 763 right->Copy(), | 782 right->Copy(), |
| 764 call), | 783 call), |
| 765 call->env(), | 784 call->env(), |
| 766 Definition::kEffect); | 785 Definition::kEffect); |
| 767 | 786 |
| 768 BinaryDoubleOpInstr* double_bin_op = | 787 BinaryDoubleOpInstr* double_bin_op = |
| 769 new BinaryDoubleOpInstr(op_kind, left->Copy(), right->Copy(), call); | 788 new BinaryDoubleOpInstr(op_kind, left->Copy(), right->Copy(), call); |
| 770 call->ReplaceWith(double_bin_op, current_iterator()); | 789 call->ReplaceWith(double_bin_op, current_iterator()); |
| 771 RemovePushArguments(call); | 790 RemovePushArguments(call); |
| 772 } else if (operands_type == kMintCid) { | 791 } else if (operands_type == kMintCid) { |
| 792 if (!FlowGraphCompiler::SupportsUnboxedMints()) return false; |
| 773 Value* left = call->ArgumentAt(0)->value(); | 793 Value* left = call->ArgumentAt(0)->value(); |
| 774 Value* right = call->ArgumentAt(1)->value(); | 794 Value* right = call->ArgumentAt(1)->value(); |
| 775 if ((op_kind == Token::kSHR) || (op_kind == Token::kSHL)) { | 795 if ((op_kind == Token::kSHR) || (op_kind == Token::kSHL)) { |
| 776 ShiftMintOpInstr* shift_op = | 796 ShiftMintOpInstr* shift_op = |
| 777 new ShiftMintOpInstr(op_kind, left, right, call); | 797 new ShiftMintOpInstr(op_kind, left, right, call); |
| 778 call->ReplaceWith(shift_op, current_iterator()); | 798 call->ReplaceWith(shift_op, current_iterator()); |
| 779 } else { | 799 } else { |
| 780 BinaryMintOpInstr* bin_op = | 800 BinaryMintOpInstr* bin_op = |
| 781 new BinaryMintOpInstr(op_kind, left, right, call); | 801 new BinaryMintOpInstr(op_kind, left, right, call); |
| 782 call->ReplaceWith(bin_op, current_iterator()); | 802 call->ReplaceWith(bin_op, current_iterator()); |
| (...skipping 2930 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3713 | 3733 |
| 3714 if (FLAG_trace_constant_propagation) { | 3734 if (FLAG_trace_constant_propagation) { |
| 3715 OS::Print("\n==== After constant propagation ====\n"); | 3735 OS::Print("\n==== After constant propagation ====\n"); |
| 3716 FlowGraphPrinter printer(*graph_); | 3736 FlowGraphPrinter printer(*graph_); |
| 3717 printer.PrintBlocks(); | 3737 printer.PrintBlocks(); |
| 3718 } | 3738 } |
| 3719 } | 3739 } |
| 3720 | 3740 |
| 3721 | 3741 |
| 3722 } // namespace dart | 3742 } // namespace dart |
| OLD | NEW |