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