Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(779)

Side by Side Diff: runtime/vm/intermediate_language_mips.cc

Issue 564843002: Initial steps towards cleaning up integer arithmetic IR. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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/globals.h" // Needed here to get TARGET_ARCH_MIPS. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_MIPS.
6 #if defined(TARGET_ARCH_MIPS) 6 #if defined(TARGET_ARCH_MIPS)
7 7
8 #include "vm/intermediate_language.h" 8 #include "vm/intermediate_language.h"
9 9
10 #include "vm/dart_entry.h" 10 #include "vm/dart_entry.h"
(...skipping 2611 matching lines...) Expand 10 before | Expand all | Expand 10 after
2622 } 2622 }
2623 if (compiler->ForceSlowPathForStackOverflow()) { 2623 if (compiler->ForceSlowPathForStackOverflow()) {
2624 __ b(slow_path->entry_label()); 2624 __ b(slow_path->entry_label());
2625 } 2625 }
2626 __ Bind(slow_path->exit_label()); 2626 __ Bind(slow_path->exit_label());
2627 } 2627 }
2628 2628
2629 2629
2630 static void EmitSmiShiftLeft(FlowGraphCompiler* compiler, 2630 static void EmitSmiShiftLeft(FlowGraphCompiler* compiler,
2631 BinarySmiOpInstr* shift_left) { 2631 BinarySmiOpInstr* shift_left) {
2632 const bool is_truncating = shift_left->IsTruncating();
2633 const LocationSummary& locs = *shift_left->locs(); 2632 const LocationSummary& locs = *shift_left->locs();
2634 Register left = locs.in(0).reg(); 2633 Register left = locs.in(0).reg();
2635 Register result = locs.out(0).reg(); 2634 Register result = locs.out(0).reg();
2636 Label* deopt = shift_left->CanDeoptimize() ? 2635 Label* deopt = shift_left->CanDeoptimize() ?
2637 compiler->AddDeoptStub(shift_left->deopt_id(), ICData::kDeoptBinarySmiOp) 2636 compiler->AddDeoptStub(shift_left->deopt_id(), ICData::kDeoptBinarySmiOp)
2638 : NULL; 2637 : NULL;
2639 2638
2640 __ TraceSimMsg("EmitSmiShiftLeft"); 2639 __ TraceSimMsg("EmitSmiShiftLeft");
2641 2640
2642 if (locs.in(1).IsConstant()) { 2641 if (locs.in(1).IsConstant()) {
2643 const Object& constant = locs.in(1).constant(); 2642 const Object& constant = locs.in(1).constant();
2644 ASSERT(constant.IsSmi()); 2643 ASSERT(constant.IsSmi());
2645 // Immediate shift operation takes 5 bits for the count. 2644 // Immediate shift operation takes 5 bits for the count.
2646 const intptr_t kCountLimit = 0x1F; 2645 const intptr_t kCountLimit = 0x1F;
2647 const intptr_t value = Smi::Cast(constant).Value(); 2646 const intptr_t value = Smi::Cast(constant).Value();
2648 if (value == 0) { 2647 ASSERT((0 < value) && (value < kCountLimit));
2649 if (result != left) { 2648 if (shift_left->can_overflow()) {
2650 __ mov(result, left); 2649 // Check for overflow (preserve left).
2651 } 2650 __ sll(TMP, left, value);
2652 } else if ((value < 0) || (value >= kCountLimit)) { 2651 __ sra(CMPRES1, TMP, value);
2653 // This condition may not be known earlier in some cases because 2652 __ bne(CMPRES1, left, deopt); // Overflow.
2654 // of constant propagation, inlining, etc.
2655 if ((value >= kCountLimit) && is_truncating) {
2656 __ mov(result, ZR);
2657 } else {
2658 // Result is Mint or exception.
2659 __ b(deopt);
2660 }
2661 } else {
2662 if (!is_truncating) {
2663 // Check for overflow (preserve left).
2664 __ sll(TMP, left, value);
2665 __ sra(CMPRES1, TMP, value);
2666 __ bne(CMPRES1, left, deopt); // Overflow.
2667 }
2668 // Shift for result now we know there is no overflow.
2669 __ sll(result, left, value);
2670 } 2653 }
2654 // Shift for result now we know there is no overflow.
2655 __ sll(result, left, value);
2671 return; 2656 return;
2672 } 2657 }
2673 2658
2674 // Right (locs.in(1)) is not constant. 2659 // Right (locs.in(1)) is not constant.
2675 Register right = locs.in(1).reg(); 2660 Register right = locs.in(1).reg();
2676 Range* right_range = shift_left->right()->definition()->range(); 2661 Range* right_range = shift_left->right()->definition()->range();
2677 if (shift_left->left()->BindsToConstant() && !is_truncating) { 2662 if (shift_left->left()->BindsToConstant() && shift_left->can_overflow()) {
2678 // TODO(srdjan): Implement code below for is_truncating(). 2663 // TODO(srdjan): Implement code below for is_truncating().
2679 // If left is constant, we know the maximal allowed size for right. 2664 // If left is constant, we know the maximal allowed size for right.
2680 const Object& obj = shift_left->left()->BoundConstant(); 2665 const Object& obj = shift_left->left()->BoundConstant();
2681 if (obj.IsSmi()) { 2666 if (obj.IsSmi()) {
2682 const intptr_t left_int = Smi::Cast(obj).Value(); 2667 const intptr_t left_int = Smi::Cast(obj).Value();
2683 if (left_int == 0) { 2668 if (left_int == 0) {
2684 __ bltz(right, deopt); 2669 __ bltz(right, deopt);
2685 __ mov(result, ZR); 2670 __ mov(result, ZR);
2686 return; 2671 return;
2687 } 2672 }
2688 const intptr_t max_right = kSmiBits - Utils::HighestBit(left_int); 2673 const intptr_t max_right = kSmiBits - Utils::HighestBit(left_int);
2689 const bool right_needs_check = 2674 const bool right_needs_check =
2690 !RangeUtils::IsWithin(right_range, 0, max_right - 1); 2675 !RangeUtils::IsWithin(right_range, 0, max_right - 1);
2691 if (right_needs_check) { 2676 if (right_needs_check) {
2692 __ BranchUnsignedGreaterEqual( 2677 __ BranchUnsignedGreaterEqual(
2693 right, reinterpret_cast<int32_t>(Smi::New(max_right)), deopt); 2678 right, reinterpret_cast<int32_t>(Smi::New(max_right)), deopt);
2694 } 2679 }
2695 __ SmiUntag(TMP, right); 2680 __ SmiUntag(TMP, right);
2696 __ sllv(result, left, TMP); 2681 __ sllv(result, left, TMP);
2697 } 2682 }
2698 return; 2683 return;
2699 } 2684 }
2700 2685
2701 const bool right_needs_check = 2686 const bool right_needs_check =
2702 !RangeUtils::IsWithin(right_range, 0, (Smi::kBits - 1)); 2687 !RangeUtils::IsWithin(right_range, 0, (Smi::kBits - 1));
2703 if (is_truncating) { 2688 if (!shift_left->can_overflow()) {
2704 if (right_needs_check) { 2689 if (right_needs_check) {
2705 const bool right_may_be_negative = 2690 const bool right_may_be_negative =
2706 (right_range == NULL) || !right_range->IsPositive(); 2691 (right_range == NULL) || !right_range->IsPositive();
2707 if (right_may_be_negative) { 2692 if (right_may_be_negative) {
2708 ASSERT(shift_left->CanDeoptimize()); 2693 ASSERT(shift_left->CanDeoptimize());
2709 __ bltz(right, deopt); 2694 __ bltz(right, deopt);
2710 } 2695 }
2711 Label done, is_not_zero; 2696 Label done, is_not_zero;
2712 2697
2713 __ sltiu(CMPRES1, 2698 __ sltiu(CMPRES1,
(...skipping 27 matching lines...) Expand all
2741 } 2726 }
2742 2727
2743 2728
2744 LocationSummary* BinarySmiOpInstr::MakeLocationSummary(Isolate* isolate, 2729 LocationSummary* BinarySmiOpInstr::MakeLocationSummary(Isolate* isolate,
2745 bool opt) const { 2730 bool opt) const {
2746 const intptr_t kNumInputs = 2; 2731 const intptr_t kNumInputs = 2;
2747 const intptr_t kNumTemps = 2732 const intptr_t kNumTemps =
2748 ((op_kind() == Token::kADD) || 2733 ((op_kind() == Token::kADD) ||
2749 (op_kind() == Token::kMOD) || 2734 (op_kind() == Token::kMOD) ||
2750 (op_kind() == Token::kTRUNCDIV) || 2735 (op_kind() == Token::kTRUNCDIV) ||
2751 (((op_kind() == Token::kSHL) && !IsTruncating()) || 2736 (((op_kind() == Token::kSHL) && can_overflow()) ||
2752 (op_kind() == Token::kSHR))) ? 1 : 0; 2737 (op_kind() == Token::kSHR))) ? 1 : 0;
2753 LocationSummary* summary = new(isolate) LocationSummary( 2738 LocationSummary* summary = new(isolate) LocationSummary(
2754 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); 2739 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
2755 if (op_kind() == Token::kTRUNCDIV) { 2740 if (op_kind() == Token::kTRUNCDIV) {
2756 summary->set_in(0, Location::RequiresRegister()); 2741 summary->set_in(0, Location::RequiresRegister());
2757 if (RightIsPowerOfTwoConstant()) { 2742 if (RightIsPowerOfTwoConstant()) {
2758 ConstantInstr* right_constant = right()->definition()->AsConstant(); 2743 ConstantInstr* right_constant = right()->definition()->AsConstant();
2759 summary->set_in(1, Location::Constant(right_constant)); 2744 summary->set_in(1, Location::Constant(right_constant));
2760 } else { 2745 } else {
2761 summary->set_in(1, Location::RequiresRegister()); 2746 summary->set_in(1, Location::RequiresRegister());
2762 } 2747 }
2763 summary->set_temp(0, Location::RequiresRegister()); 2748 summary->set_temp(0, Location::RequiresRegister());
2764 summary->set_out(0, Location::RequiresRegister()); 2749 summary->set_out(0, Location::RequiresRegister());
2765 return summary; 2750 return summary;
2766 } 2751 }
2767 if (op_kind() == Token::kMOD) { 2752 if (op_kind() == Token::kMOD) {
2768 summary->set_in(0, Location::RequiresRegister()); 2753 summary->set_in(0, Location::RequiresRegister());
2769 summary->set_in(1, Location::RequiresRegister()); 2754 summary->set_in(1, Location::RequiresRegister());
2770 summary->set_temp(0, Location::RequiresRegister()); 2755 summary->set_temp(0, Location::RequiresRegister());
2771 summary->set_out(0, Location::RequiresRegister()); 2756 summary->set_out(0, Location::RequiresRegister());
2772 return summary; 2757 return summary;
2773 } 2758 }
2774 summary->set_in(0, Location::RequiresRegister()); 2759 summary->set_in(0, Location::RequiresRegister());
2775 summary->set_in(1, Location::RegisterOrSmiConstant(right())); 2760 summary->set_in(1, Location::RegisterOrSmiConstant(right()));
2776 if (((op_kind() == Token::kSHL) && !IsTruncating()) || 2761 if (((op_kind() == Token::kSHL) && can_overflow()) ||
2777 (op_kind() == Token::kSHR)) { 2762 (op_kind() == Token::kSHR)) {
2778 summary->set_temp(0, Location::RequiresRegister()); 2763 summary->set_temp(0, Location::RequiresRegister());
2779 } else if (op_kind() == Token::kADD) { 2764 } else if (op_kind() == Token::kADD) {
2780 // Need an extra temp for the overflow detection code. 2765 // Need an extra temp for the overflow detection code.
2781 summary->set_temp(0, Location::RequiresRegister()); 2766 summary->set_temp(0, Location::RequiresRegister());
2782 } 2767 }
2783 // We make use of 3-operand instructions by not requiring result register 2768 // We make use of 3-operand instructions by not requiring result register
2784 // to be identical to first input register as on Intel. 2769 // to be identical to first input register as on Intel.
2785 summary->set_out(0, Location::RequiresRegister()); 2770 summary->set_out(0, Location::RequiresRegister());
2786 return summary; 2771 return summary;
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
2822 __ AddImmediate(result, left, -imm); 2807 __ AddImmediate(result, left, -imm);
2823 } else { 2808 } else {
2824 __ SubImmediateDetectOverflow(result, left, imm, CMPRES1); 2809 __ SubImmediateDetectOverflow(result, left, imm, CMPRES1);
2825 __ bltz(CMPRES1, deopt); 2810 __ bltz(CMPRES1, deopt);
2826 } 2811 }
2827 break; 2812 break;
2828 } 2813 }
2829 case Token::kMUL: { 2814 case Token::kMUL: {
2830 // Keep left value tagged and untag right value. 2815 // Keep left value tagged and untag right value.
2831 const intptr_t value = Smi::Cast(constant).Value(); 2816 const intptr_t value = Smi::Cast(constant).Value();
2832 if (deopt == NULL) { 2817 __ LoadImmediate(TMP, value);
2833 if (value == 2) { 2818 __ mult(left, TMP);
2834 __ sll(result, left, 1); 2819 __ mflo(result);
2835 } else { 2820 if (deopt != NULL) {
2836 __ LoadImmediate(TMP, value); 2821 __ mfhi(CMPRES2);
2837 __ mult(left, TMP);
2838 __ mflo(result);
2839 }
2840 } else {
2841 if (value == 2) {
2842 __ sra(CMPRES2, left, 31); // CMPRES2 = sign of left.
2843 __ sll(result, left, 1);
2844 } else {
2845 __ LoadImmediate(TMP, value);
2846 __ mult(left, TMP);
2847 __ mflo(result);
2848 __ mfhi(CMPRES2);
2849 }
2850 __ sra(CMPRES1, result, 31); 2822 __ sra(CMPRES1, result, 31);
2851 __ bne(CMPRES1, CMPRES2, deopt); 2823 __ bne(CMPRES1, CMPRES2, deopt);
2852 } 2824 }
2853 break; 2825 break;
2854 } 2826 }
2855 case Token::kTRUNCDIV: { 2827 case Token::kTRUNCDIV: {
2856 const intptr_t value = Smi::Cast(constant).Value(); 2828 const intptr_t value = Smi::Cast(constant).Value();
2857 if (value == 1) {
2858 if (result != left) {
2859 __ mov(result, left);
2860 }
2861 break;
2862 } else if (value == -1) {
2863 // Check the corner case of dividing the 'MIN_SMI' with -1, in which
2864 // case we cannot negate the result.
2865 __ BranchEqual(left, 0x80000000, deopt);
2866 __ subu(result, ZR, left);
2867 break;
2868 }
2869 ASSERT(Utils::IsPowerOfTwo(Utils::Abs(value))); 2829 ASSERT(Utils::IsPowerOfTwo(Utils::Abs(value)));
2870 const intptr_t shift_count = 2830 const intptr_t shift_count =
2871 Utils::ShiftForPowerOfTwo(Utils::Abs(value)) + kSmiTagSize; 2831 Utils::ShiftForPowerOfTwo(Utils::Abs(value)) + kSmiTagSize;
2872 ASSERT(kSmiTagSize == 1); 2832 ASSERT(kSmiTagSize == 1);
2873 __ sra(TMP, left, 31); 2833 __ sra(TMP, left, 31);
2874 ASSERT(shift_count > 1); // 1, -1 case handled above. 2834 ASSERT(shift_count > 1); // 1, -1 case handled above.
2875 Register temp = locs()->temp(0).reg(); 2835 Register temp = locs()->temp(0).reg();
2876 __ srl(TMP, TMP, 32 - shift_count); 2836 __ srl(TMP, TMP, 32 - shift_count);
2877 __ addu(temp, left, TMP); 2837 __ addu(temp, left, TMP);
2878 ASSERT(shift_count > 0); 2838 ASSERT(shift_count > 0);
(...skipping 30 matching lines...) Expand all
2909 __ xori(result, left, Immediate(imm)); 2869 __ xori(result, left, Immediate(imm));
2910 } else { 2870 } else {
2911 __ LoadImmediate(TMP, imm); 2871 __ LoadImmediate(TMP, imm);
2912 __ xor_(result, left, TMP); 2872 __ xor_(result, left, TMP);
2913 } 2873 }
2914 break; 2874 break;
2915 } 2875 }
2916 case Token::kSHR: { 2876 case Token::kSHR: {
2917 // sarl operation masks the count to 5 bits. 2877 // sarl operation masks the count to 5 bits.
2918 const intptr_t kCountLimit = 0x1F; 2878 const intptr_t kCountLimit = 0x1F;
2919 intptr_t value = Smi::Cast(constant).Value(); 2879 const intptr_t value = Smi::Cast(constant).Value();
2920
2921 __ TraceSimMsg("kSHR"); 2880 __ TraceSimMsg("kSHR");
2922 2881 __ sra(result, left, Utils::Minimum(value + kSmiTagSize, kCountLimit));
2923 if (value == 0) {
2924 // TODO(vegorov): should be handled outside.
2925 if (result != left) {
2926 __ mov(result, left);
2927 }
2928 break;
2929 } else if (value < 0) {
2930 // TODO(vegorov): should be handled outside.
2931 __ b(deopt);
2932 break;
2933 }
2934
2935 value = value + kSmiTagSize;
2936 if (value >= kCountLimit) {
2937 value = kCountLimit;
2938 }
2939
2940 __ sra(result, left, value);
2941 __ SmiTag(result); 2882 __ SmiTag(result);
2942 break; 2883 break;
2943 } 2884 }
2944 2885
2945 default: 2886 default:
2946 UNREACHABLE(); 2887 UNREACHABLE();
2947 break; 2888 break;
2948 } 2889 }
2949 return; 2890 return;
2950 } 2891 }
(...skipping 2045 matching lines...) Expand 10 before | Expand all | Expand 10 after
4996 compiler->GenerateCall(token_pos(), &label, stub_kind_, locs()); 4937 compiler->GenerateCall(token_pos(), &label, stub_kind_, locs());
4997 #if defined(DEBUG) 4938 #if defined(DEBUG)
4998 __ LoadImmediate(S4, kInvalidObjectPointer); 4939 __ LoadImmediate(S4, kInvalidObjectPointer);
4999 __ LoadImmediate(S5, kInvalidObjectPointer); 4940 __ LoadImmediate(S5, kInvalidObjectPointer);
5000 #endif 4941 #endif
5001 } 4942 }
5002 4943
5003 } // namespace dart 4944 } // namespace dart
5004 4945
5005 #endif // defined TARGET_ARCH_MIPS 4946 #endif // defined TARGET_ARCH_MIPS
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698