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

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

Issue 2891113002: Use same range info when emitting code and computing if instruction can deopt. (Closed)
Patch Set: Add a comment to the test Created 3 years, 7 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
« no previous file with comments | « runtime/vm/intermediate_language_ia32.cc ('k') | runtime/vm/intermediate_language_x64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/compiler.h" 10 #include "vm/compiler.h"
(...skipping 2915 matching lines...) Expand 10 before | Expand all | Expand 10 after
2926 __ sra(CMPRES1, TMP, value); 2926 __ sra(CMPRES1, TMP, value);
2927 __ bne(CMPRES1, left, deopt); // Overflow. 2927 __ bne(CMPRES1, left, deopt); // Overflow.
2928 } 2928 }
2929 // Shift for result now we know there is no overflow. 2929 // Shift for result now we know there is no overflow.
2930 __ sll(result, left, value); 2930 __ sll(result, left, value);
2931 return; 2931 return;
2932 } 2932 }
2933 2933
2934 // Right (locs.in(1)) is not constant. 2934 // Right (locs.in(1)) is not constant.
2935 Register right = locs.in(1).reg(); 2935 Register right = locs.in(1).reg();
2936 Range* right_range = shift_left->right()->definition()->range(); 2936 Range* right_range = shift_left->right_range();
2937 if (shift_left->left()->BindsToConstant() && shift_left->can_overflow()) { 2937 if (shift_left->left()->BindsToConstant() && shift_left->can_overflow()) {
2938 // TODO(srdjan): Implement code below for is_truncating(). 2938 // TODO(srdjan): Implement code below for is_truncating().
2939 // If left is constant, we know the maximal allowed size for right. 2939 // If left is constant, we know the maximal allowed size for right.
2940 const Object& obj = shift_left->left()->BoundConstant(); 2940 const Object& obj = shift_left->left()->BoundConstant();
2941 if (obj.IsSmi()) { 2941 if (obj.IsSmi()) {
2942 const intptr_t left_int = Smi::Cast(obj).Value(); 2942 const intptr_t left_int = Smi::Cast(obj).Value();
2943 if (left_int == 0) { 2943 if (left_int == 0) {
2944 __ bltz(right, deopt); 2944 __ bltz(right, deopt);
2945 __ mov(result, ZR); 2945 __ mov(result, ZR);
2946 return; 2946 return;
2947 } 2947 }
2948 const intptr_t max_right = kSmiBits - Utils::HighestBit(left_int); 2948 const intptr_t max_right = kSmiBits - Utils::HighestBit(left_int);
2949 const bool right_needs_check = 2949 const bool right_needs_check =
2950 !RangeUtils::IsWithin(right_range, 0, max_right - 1); 2950 !RangeUtils::IsWithin(right_range, 0, max_right - 1);
2951 if (right_needs_check) { 2951 if (right_needs_check) {
2952 const Immediate& max_right_imm = 2952 const Immediate& max_right_imm =
2953 Immediate(reinterpret_cast<int32_t>(Smi::New(max_right))); 2953 Immediate(reinterpret_cast<int32_t>(Smi::New(max_right)));
2954 __ BranchUnsignedGreaterEqual(right, max_right_imm, deopt); 2954 __ BranchUnsignedGreaterEqual(right, max_right_imm, deopt);
2955 } 2955 }
2956 __ SmiUntag(TMP, right); 2956 __ SmiUntag(TMP, right);
2957 __ sllv(result, left, TMP); 2957 __ sllv(result, left, TMP);
2958 } 2958 }
2959 return; 2959 return;
2960 } 2960 }
2961 2961
2962 const bool right_needs_check = 2962 const bool right_needs_check =
2963 !RangeUtils::IsWithin(right_range, 0, (Smi::kBits - 1)); 2963 !RangeUtils::IsWithin(right_range, 0, (Smi::kBits - 1));
2964 if (!shift_left->can_overflow()) { 2964 if (!shift_left->can_overflow()) {
2965 if (right_needs_check) { 2965 if (right_needs_check) {
2966 const bool right_may_be_negative = 2966 if (!RangeUtils::IsPositive(right_range)) {
2967 (right_range == NULL) || !right_range->IsPositive();
2968 if (right_may_be_negative) {
2969 ASSERT(shift_left->CanDeoptimize()); 2967 ASSERT(shift_left->CanDeoptimize());
2970 __ bltz(right, deopt); 2968 __ bltz(right, deopt);
2971 } 2969 }
2972 Label done, is_not_zero; 2970 Label done, is_not_zero;
2973 2971
2974 __ sltiu(CMPRES1, right, 2972 __ sltiu(CMPRES1, right,
2975 Immediate(reinterpret_cast<int32_t>(Smi::New(Smi::kBits)))); 2973 Immediate(reinterpret_cast<int32_t>(Smi::New(Smi::kBits))));
2976 __ movz(result, ZR, CMPRES1); // result = right >= kBits ? 0 : result. 2974 __ movz(result, ZR, CMPRES1); // result = right >= kBits ? 0 : result.
2977 __ sra(TMP, right, kSmiTagSize); 2975 __ sra(TMP, right, kSmiTagSize);
2978 __ sllv(TMP, left, TMP); 2976 __ sllv(TMP, left, TMP);
(...skipping 436 matching lines...) Expand 10 before | Expand all | Expand 10 after
3415 } 3413 }
3416 3414
3417 default: 3415 default:
3418 UNREACHABLE(); 3416 UNREACHABLE();
3419 break; 3417 break;
3420 } 3418 }
3421 return; 3419 return;
3422 } 3420 }
3423 3421
3424 Register right = locs()->in(1).reg(); 3422 Register right = locs()->in(1).reg();
3425 Range* right_range = this->right()->definition()->range();
3426 switch (op_kind()) { 3423 switch (op_kind()) {
3427 case Token::kADD: { 3424 case Token::kADD: {
3428 if (deopt == NULL) { 3425 if (deopt == NULL) {
3429 __ addu(result, left, right); 3426 __ addu(result, left, right);
3430 } else { 3427 } else {
3431 Register temp = locs()->temp(0).reg(); 3428 Register temp = locs()->temp(0).reg();
3432 __ AdduDetectOverflow(result, left, right, CMPRES1, temp); 3429 __ AdduDetectOverflow(result, left, right, CMPRES1, temp);
3433 __ bltz(CMPRES1, deopt); 3430 __ bltz(CMPRES1, deopt);
3434 } 3431 }
3435 break; 3432 break;
(...skipping 29 matching lines...) Expand all
3465 // No overflow check. 3462 // No overflow check.
3466 __ or_(result, left, right); 3463 __ or_(result, left, right);
3467 break; 3464 break;
3468 } 3465 }
3469 case Token::kBIT_XOR: { 3466 case Token::kBIT_XOR: {
3470 // No overflow check. 3467 // No overflow check.
3471 __ xor_(result, left, right); 3468 __ xor_(result, left, right);
3472 break; 3469 break;
3473 } 3470 }
3474 case Token::kTRUNCDIV: { 3471 case Token::kTRUNCDIV: {
3475 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { 3472 if (RangeUtils::CanBeZero(right_range())) {
3476 // Handle divide by zero in runtime. 3473 // Handle divide by zero in runtime.
3477 __ beq(right, ZR, deopt); 3474 __ beq(right, ZR, deopt);
3478 } 3475 }
3479 Register temp = locs()->temp(0).reg(); 3476 Register temp = locs()->temp(0).reg();
3480 __ SmiUntag(temp, left); 3477 __ SmiUntag(temp, left);
3481 __ SmiUntag(TMP, right); 3478 __ SmiUntag(TMP, right);
3482 __ div(temp, TMP); 3479 __ div(temp, TMP);
3483 __ mflo(result); 3480 __ mflo(result);
3484 // Check the corner case of dividing the 'MIN_SMI' with -1, in which 3481 // Check the corner case of dividing the 'MIN_SMI' with -1, in which
3485 // case we cannot tag the result. 3482 // case we cannot tag the result.
3486 __ BranchEqual(result, Immediate(0x40000000), deopt); 3483 __ BranchEqual(result, Immediate(0x40000000), deopt);
3487 __ SmiTag(result); 3484 __ SmiTag(result);
3488 break; 3485 break;
3489 } 3486 }
3490 case Token::kMOD: { 3487 case Token::kMOD: {
3491 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { 3488 if (RangeUtils::CanBeZero(right_range())) {
3492 // Handle divide by zero in runtime. 3489 // Handle divide by zero in runtime.
3493 __ beq(right, ZR, deopt); 3490 __ beq(right, ZR, deopt);
3494 } 3491 }
3495 Register temp = locs()->temp(0).reg(); 3492 Register temp = locs()->temp(0).reg();
3496 __ SmiUntag(temp, left); 3493 __ SmiUntag(temp, left);
3497 __ SmiUntag(TMP, right); 3494 __ SmiUntag(TMP, right);
3498 __ div(temp, TMP); 3495 __ div(temp, TMP);
3499 __ mfhi(result); 3496 __ mfhi(result);
3500 // res = left % right; 3497 // res = left % right;
3501 // if (res < 0) { 3498 // if (res < 0) {
3502 // if (right < 0) { 3499 // if (right < 0) {
3503 // res = res - right; 3500 // res = res - right;
3504 // } else { 3501 // } else {
3505 // res = res + right; 3502 // res = res + right;
3506 // } 3503 // }
3507 // } 3504 // }
3508 Label done; 3505 Label done;
3509 __ bgez(result, &done); 3506 __ bgez(result, &done);
3510 if ((right_range == NULL) || right_range->Overlaps(-1, 1)) { 3507 if (RangeUtils::Overlaps(right_range(), -1, 1)) {
3511 Label subtract; 3508 Label subtract;
3512 __ bltz(right, &subtract); 3509 __ bltz(right, &subtract);
3513 __ addu(result, result, TMP); 3510 __ addu(result, result, TMP);
3514 __ b(&done); 3511 __ b(&done);
3515 __ Bind(&subtract); 3512 __ Bind(&subtract);
3516 __ subu(result, result, TMP); 3513 __ subu(result, result, TMP);
3517 } else if (right_range->IsPositive()) { 3514 } else if (right_range()->IsPositive()) {
3518 // Right is positive. 3515 // Right is positive.
3519 __ addu(result, result, TMP); 3516 __ addu(result, result, TMP);
3520 } else { 3517 } else {
3521 // Right is negative. 3518 // Right is negative.
3522 __ subu(result, result, TMP); 3519 __ subu(result, result, TMP);
3523 } 3520 }
3524 __ Bind(&done); 3521 __ Bind(&done);
3525 __ SmiTag(result); 3522 __ SmiTag(result);
3526 break; 3523 break;
3527 } 3524 }
3528 case Token::kSHR: { 3525 case Token::kSHR: {
3529 Register temp = locs()->temp(0).reg(); 3526 Register temp = locs()->temp(0).reg();
3530 if (CanDeoptimize()) { 3527 if (CanDeoptimize()) {
3531 __ bltz(right, deopt); 3528 __ bltz(right, deopt);
3532 } 3529 }
3533 __ SmiUntag(temp, right); 3530 __ SmiUntag(temp, right);
3534 // sra operation masks the count to 5 bits. 3531 // sra operation masks the count to 5 bits.
3535 const intptr_t kCountLimit = 0x1F; 3532 const intptr_t kCountLimit = 0x1F;
3536 if ((right_range == NULL) || 3533 if (!RangeUtils::OnlyLessThanOrEqualTo(right_range(), kCountLimit)) {
3537 !right_range->OnlyLessThanOrEqualTo(kCountLimit)) {
3538 Label ok; 3534 Label ok;
3539 __ BranchSignedLessEqual(temp, Immediate(kCountLimit), &ok); 3535 __ BranchSignedLessEqual(temp, Immediate(kCountLimit), &ok);
3540 __ LoadImmediate(temp, kCountLimit); 3536 __ LoadImmediate(temp, kCountLimit);
3541 __ Bind(&ok); 3537 __ Bind(&ok);
3542 } 3538 }
3543 3539
3544 __ SmiUntag(CMPRES1, left); 3540 __ SmiUntag(CMPRES1, left);
3545 __ srav(result, CMPRES1, temp); 3541 __ srav(result, CMPRES1, temp);
3546 __ SmiTag(result); 3542 __ SmiTag(result);
3547 break; 3543 break;
(...skipping 1404 matching lines...) Expand 10 before | Expand all | Expand 10 after
4952 __ movd(out, in); 4948 __ movd(out, in);
4953 } else { 4949 } else {
4954 ASSERT(representation() == kTagged); 4950 ASSERT(representation() == kTagged);
4955 Register out = locs()->out(0).reg(); 4951 Register out = locs()->out(0).reg();
4956 Register in = in_loc.reg(); 4952 Register in = in_loc.reg();
4957 __ mov(out, in); 4953 __ mov(out, in);
4958 } 4954 }
4959 } 4955 }
4960 4956
4961 4957
4962 LocationSummary* MergedMathInstr::MakeLocationSummary(Zone* zone, 4958 LocationSummary* TruncDivModInstr::MakeLocationSummary(Zone* zone,
4963 bool opt) const { 4959 bool opt) const {
4964 if (kind() == MergedMathInstr::kTruncDivMod) { 4960 const intptr_t kNumInputs = 2;
4965 const intptr_t kNumInputs = 2; 4961 const intptr_t kNumTemps = 1;
4966 const intptr_t kNumTemps = 1; 4962 LocationSummary* summary = new (zone)
4967 LocationSummary* summary = new (zone) 4963 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
4968 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 4964 summary->set_in(0, Location::RequiresRegister());
4969 summary->set_in(0, Location::RequiresRegister()); 4965 summary->set_in(1, Location::RequiresRegister());
4970 summary->set_in(1, Location::RequiresRegister()); 4966 summary->set_temp(0, Location::RequiresRegister());
4971 summary->set_temp(0, Location::RequiresRegister()); 4967 // Output is a pair of registers.
4972 // Output is a pair of registers. 4968 summary->set_out(0, Location::Pair(Location::RequiresRegister(),
4973 summary->set_out(0, Location::Pair(Location::RequiresRegister(), 4969 Location::RequiresRegister()));
4974 Location::RequiresRegister())); 4970 return summary;
4975 return summary;
4976 }
4977 UNIMPLEMENTED();
4978 return NULL;
4979 } 4971 }
4980 4972
4981 4973
4982 void MergedMathInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 4974 void TruncDivModInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
4983 Label* deopt = NULL; 4975 ASSERT(CanDeoptimize());
4984 if (CanDeoptimize()) { 4976 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp);
4985 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp); 4977 Register left = locs()->in(0).reg();
4978 Register right = locs()->in(1).reg();
4979 Register temp = locs()->temp(0).reg();
4980 ASSERT(locs()->out(0).IsPairLocation());
4981 PairLocation* pair = locs()->out(0).AsPairLocation();
4982 Register result_div = pair->At(0).reg();
4983 Register result_mod = pair->At(1).reg();
4984 if (RangeUtils::CanBeZero(divisor_range())) {
4985 // Handle divide by zero in runtime.
4986 __ beq(right, ZR, deopt);
4986 } 4987 }
4987 if (kind() == MergedMathInstr::kTruncDivMod) { 4988 __ SmiUntag(temp, left);
4988 Register left = locs()->in(0).reg(); 4989 __ SmiUntag(TMP, right);
4989 Register right = locs()->in(1).reg(); 4990 __ div(temp, TMP);
4990 Register temp = locs()->temp(0).reg(); 4991 __ mflo(result_div);
4991 ASSERT(locs()->out(0).IsPairLocation()); 4992 __ mfhi(result_mod);
4992 PairLocation* pair = locs()->out(0).AsPairLocation(); 4993 // Check the corner case of dividing the 'MIN_SMI' with -1, in which
4993 Register result_div = pair->At(0).reg(); 4994 // case we cannot tag the result.
4994 Register result_mod = pair->At(1).reg(); 4995 __ BranchEqual(result_div, Immediate(0x40000000), deopt);
4995 Range* right_range = InputAt(1)->definition()->range(); 4996 // res = left % right;
4996 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { 4997 // if (res < 0) {
4997 // Handle divide by zero in runtime. 4998 // if (right < 0) {
4998 __ beq(right, ZR, deopt); 4999 // res = res - right;
4999 } 5000 // } else {
5000 __ SmiUntag(temp, left); 5001 // res = res + right;
5001 __ SmiUntag(TMP, right); 5002 // }
5002 __ div(temp, TMP); 5003 // }
5003 __ mflo(result_div); 5004 Label done;
5004 __ mfhi(result_mod); 5005 __ bgez(result_mod, &done);
5005 // Check the corner case of dividing the 'MIN_SMI' with -1, in which 5006 if (RangeUtils::Overlaps(divisor_range(), -1, 1)) {
5006 // case we cannot tag the result. 5007 Label subtract;
5007 __ BranchEqual(result_div, Immediate(0x40000000), deopt); 5008 __ bltz(right, &subtract);
5008 // res = left % right; 5009 __ addu(result_mod, result_mod, TMP);
5009 // if (res < 0) { 5010 __ b(&done);
5010 // if (right < 0) { 5011 __ Bind(&subtract);
5011 // res = res - right; 5012 __ subu(result_mod, result_mod, TMP);
5012 // } else { 5013 } else if (divisor_range()->IsPositive()) {
5013 // res = res + right; 5014 // Right is positive.
5014 // } 5015 __ addu(result_mod, result_mod, TMP);
5015 // } 5016 } else {
5016 Label done; 5017 // Right is negative.
5017 __ bgez(result_mod, &done); 5018 __ subu(result_mod, result_mod, TMP);
5018 if ((right_range == NULL) || right_range->Overlaps(-1, 1)) { 5019 }
5019 Label subtract; 5020 __ Bind(&done);
5020 __ bltz(right, &subtract);
5021 __ addu(result_mod, result_mod, TMP);
5022 __ b(&done);
5023 __ Bind(&subtract);
5024 __ subu(result_mod, result_mod, TMP);
5025 } else if (right_range->IsPositive()) {
5026 // Right is positive.
5027 __ addu(result_mod, result_mod, TMP);
5028 } else {
5029 // Right is negative.
5030 __ subu(result_mod, result_mod, TMP);
5031 }
5032 __ Bind(&done);
5033 5021
5034 __ SmiTag(result_div); 5022 __ SmiTag(result_div);
5035 __ SmiTag(result_mod); 5023 __ SmiTag(result_mod);
5036 return;
5037 }
5038 UNIMPLEMENTED();
5039 } 5024 }
5040 5025
5041 5026
5042 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary( 5027 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary(
5043 Zone* zone, 5028 Zone* zone,
5044 bool opt) const { 5029 bool opt) const {
5045 return MakeCallSummary(zone); 5030 return MakeCallSummary(zone);
5046 } 5031 }
5047 5032
5048 5033
(...skipping 352 matching lines...) Expand 10 before | Expand all | Expand 10 after
5401 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 5386 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
5402 summary->set_in(0, Location::Pair(Location::RequiresRegister(), 5387 summary->set_in(0, Location::Pair(Location::RequiresRegister(),
5403 Location::RequiresRegister())); 5388 Location::RequiresRegister()));
5404 summary->set_in(1, Location::WritableRegisterOrSmiConstant(right())); 5389 summary->set_in(1, Location::WritableRegisterOrSmiConstant(right()));
5405 summary->set_out(0, Location::Pair(Location::RequiresRegister(), 5390 summary->set_out(0, Location::Pair(Location::RequiresRegister(),
5406 Location::RequiresRegister())); 5391 Location::RequiresRegister()));
5407 return summary; 5392 return summary;
5408 } 5393 }
5409 5394
5410 5395
5411 static const intptr_t kMintShiftCountLimit = 63;
5412
5413 bool ShiftMintOpInstr::has_shift_count_check() const {
5414 return !RangeUtils::IsWithin(right()->definition()->range(), 0,
5415 kMintShiftCountLimit);
5416 }
5417
5418
5419 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5396 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5420 PairLocation* left_pair = locs()->in(0).AsPairLocation(); 5397 PairLocation* left_pair = locs()->in(0).AsPairLocation();
5421 Register left_lo = left_pair->At(0).reg(); 5398 Register left_lo = left_pair->At(0).reg();
5422 Register left_hi = left_pair->At(1).reg(); 5399 Register left_hi = left_pair->At(1).reg();
5423 PairLocation* out_pair = locs()->out(0).AsPairLocation(); 5400 PairLocation* out_pair = locs()->out(0).AsPairLocation();
5424 Register out_lo = out_pair->At(0).reg(); 5401 Register out_lo = out_pair->At(0).reg();
5425 Register out_hi = out_pair->At(1).reg(); 5402 Register out_hi = out_pair->At(1).reg();
5426 5403
5427 Label* deopt = NULL; 5404 Label* deopt = NULL;
5428 if (CanDeoptimize()) { 5405 if (CanDeoptimize()) {
(...skipping 659 matching lines...) Expand 10 before | Expand all | Expand 10 after
6088 compiler->GenerateRuntimeCall(TokenPosition::kNoSource, deopt_id(), 6065 compiler->GenerateRuntimeCall(TokenPosition::kNoSource, deopt_id(),
6089 kGrowRegExpStackRuntimeEntry, 1, locs()); 6066 kGrowRegExpStackRuntimeEntry, 1, locs());
6090 __ lw(result, Address(SP, 1 * kWordSize)); 6067 __ lw(result, Address(SP, 1 * kWordSize));
6091 __ addiu(SP, SP, Immediate(2 * kWordSize)); 6068 __ addiu(SP, SP, Immediate(2 * kWordSize));
6092 } 6069 }
6093 6070
6094 6071
6095 } // namespace dart 6072 } // namespace dart
6096 6073
6097 #endif // defined TARGET_ARCH_MIPS 6074 #endif // defined TARGET_ARCH_MIPS
OLDNEW
« no previous file with comments | « runtime/vm/intermediate_language_ia32.cc ('k') | runtime/vm/intermediate_language_x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698