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

Side by Side Diff: runtime/vm/intermediate_language_arm.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.cc ('k') | runtime/vm/intermediate_language_arm64.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 1
2 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 2 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
3 // for details. All rights reserved. Use of this source code is governed by a 3 // for details. All rights reserved. Use of this source code is governed by a
4 // BSD-style license that can be found in the LICENSE file. 4 // BSD-style license that can be found in the LICENSE file.
5 5
6 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM. 6 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM.
7 #if defined(TARGET_ARCH_ARM) 7 #if defined(TARGET_ARCH_ARM)
8 8
9 #include "vm/intermediate_language.h" 9 #include "vm/intermediate_language.h"
10 10
(...skipping 3053 matching lines...) Expand 10 before | Expand all | Expand 10 after
3064 __ cmp(left, Operand(IP, ASR, value)); 3064 __ cmp(left, Operand(IP, ASR, value));
3065 __ b(deopt, NE); // Overflow. 3065 __ b(deopt, NE); // Overflow.
3066 } 3066 }
3067 // Shift for result now we know there is no overflow. 3067 // Shift for result now we know there is no overflow.
3068 __ Lsl(result, left, Operand(value)); 3068 __ Lsl(result, left, Operand(value));
3069 return; 3069 return;
3070 } 3070 }
3071 3071
3072 // Right (locs.in(1)) is not constant. 3072 // Right (locs.in(1)) is not constant.
3073 const Register right = locs.in(1).reg(); 3073 const Register right = locs.in(1).reg();
3074 Range* right_range = shift_left->right()->definition()->range(); 3074 Range* right_range = shift_left->right_range();
3075 if (shift_left->left()->BindsToConstant() && shift_left->can_overflow()) { 3075 if (shift_left->left()->BindsToConstant() && shift_left->can_overflow()) {
3076 // TODO(srdjan): Implement code below for is_truncating(). 3076 // TODO(srdjan): Implement code below for is_truncating().
3077 // If left is constant, we know the maximal allowed size for right. 3077 // If left is constant, we know the maximal allowed size for right.
3078 const Object& obj = shift_left->left()->BoundConstant(); 3078 const Object& obj = shift_left->left()->BoundConstant();
3079 if (obj.IsSmi()) { 3079 if (obj.IsSmi()) {
3080 const intptr_t left_int = Smi::Cast(obj).Value(); 3080 const intptr_t left_int = Smi::Cast(obj).Value();
3081 if (left_int == 0) { 3081 if (left_int == 0) {
3082 __ cmp(right, Operand(0)); 3082 __ cmp(right, Operand(0));
3083 __ b(deopt, MI); 3083 __ b(deopt, MI);
3084 __ mov(result, Operand(0)); 3084 __ mov(result, Operand(0));
3085 return; 3085 return;
3086 } 3086 }
3087 const intptr_t max_right = kSmiBits - Utils::HighestBit(left_int); 3087 const intptr_t max_right = kSmiBits - Utils::HighestBit(left_int);
3088 const bool right_needs_check = 3088 const bool right_needs_check =
3089 !RangeUtils::IsWithin(right_range, 0, max_right - 1); 3089 !RangeUtils::IsWithin(right_range, 0, max_right - 1);
3090 if (right_needs_check) { 3090 if (right_needs_check) {
3091 __ cmp(right, Operand(reinterpret_cast<int32_t>(Smi::New(max_right)))); 3091 __ cmp(right, Operand(reinterpret_cast<int32_t>(Smi::New(max_right))));
3092 __ b(deopt, CS); 3092 __ b(deopt, CS);
3093 } 3093 }
3094 __ SmiUntag(IP, right); 3094 __ SmiUntag(IP, right);
3095 __ Lsl(result, left, IP); 3095 __ Lsl(result, left, IP);
3096 } 3096 }
3097 return; 3097 return;
3098 } 3098 }
3099 3099
3100 const bool right_needs_check = 3100 const bool right_needs_check =
3101 !RangeUtils::IsWithin(right_range, 0, (Smi::kBits - 1)); 3101 !RangeUtils::IsWithin(right_range, 0, (Smi::kBits - 1));
3102 if (!shift_left->can_overflow()) { 3102 if (!shift_left->can_overflow()) {
3103 if (right_needs_check) { 3103 if (right_needs_check) {
3104 const bool right_may_be_negative = 3104 if (!RangeUtils::IsPositive(right_range)) {
3105 (right_range == NULL) || !right_range->IsPositive();
3106 if (right_may_be_negative) {
3107 ASSERT(shift_left->CanDeoptimize()); 3105 ASSERT(shift_left->CanDeoptimize());
3108 __ cmp(right, Operand(0)); 3106 __ cmp(right, Operand(0));
3109 __ b(deopt, MI); 3107 __ b(deopt, MI);
3110 } 3108 }
3111 3109
3112 __ cmp(right, Operand(reinterpret_cast<int32_t>(Smi::New(Smi::kBits)))); 3110 __ cmp(right, Operand(reinterpret_cast<int32_t>(Smi::New(Smi::kBits))));
3113 __ mov(result, Operand(0), CS); 3111 __ mov(result, Operand(0), CS);
3114 __ SmiUntag(IP, right, CC); // SmiUntag right into IP if CC. 3112 __ SmiUntag(IP, right, CC); // SmiUntag right into IP if CC.
3115 __ Lsl(result, left, IP, CC); 3113 __ Lsl(result, left, IP, CC);
3116 } else { 3114 } else {
(...skipping 458 matching lines...) Expand 10 before | Expand all | Expand 10 after
3575 } 3573 }
3576 3574
3577 default: 3575 default:
3578 UNREACHABLE(); 3576 UNREACHABLE();
3579 break; 3577 break;
3580 } 3578 }
3581 return; 3579 return;
3582 } 3580 }
3583 3581
3584 const Register right = locs()->in(1).reg(); 3582 const Register right = locs()->in(1).reg();
3585 Range* right_range = this->right()->definition()->range();
3586 switch (op_kind()) { 3583 switch (op_kind()) {
3587 case Token::kADD: { 3584 case Token::kADD: {
3588 if (deopt == NULL) { 3585 if (deopt == NULL) {
3589 __ add(result, left, Operand(right)); 3586 __ add(result, left, Operand(right));
3590 } else { 3587 } else {
3591 __ adds(result, left, Operand(right)); 3588 __ adds(result, left, Operand(right));
3592 __ b(deopt, VS); 3589 __ b(deopt, VS);
3593 } 3590 }
3594 break; 3591 break;
3595 } 3592 }
(...skipping 28 matching lines...) Expand all
3624 __ orr(result, left, Operand(right)); 3621 __ orr(result, left, Operand(right));
3625 break; 3622 break;
3626 } 3623 }
3627 case Token::kBIT_XOR: { 3624 case Token::kBIT_XOR: {
3628 // No overflow check. 3625 // No overflow check.
3629 __ eor(result, left, Operand(right)); 3626 __ eor(result, left, Operand(right));
3630 break; 3627 break;
3631 } 3628 }
3632 case Token::kTRUNCDIV: { 3629 case Token::kTRUNCDIV: {
3633 ASSERT(TargetCPUFeatures::can_divide()); 3630 ASSERT(TargetCPUFeatures::can_divide());
3634 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { 3631 if (RangeUtils::CanBeZero(right_range())) {
3635 // Handle divide by zero in runtime. 3632 // Handle divide by zero in runtime.
3636 __ cmp(right, Operand(0)); 3633 __ cmp(right, Operand(0));
3637 __ b(deopt, EQ); 3634 __ b(deopt, EQ);
3638 } 3635 }
3639 const Register temp = locs()->temp(0).reg(); 3636 const Register temp = locs()->temp(0).reg();
3640 const DRegister dtemp = EvenDRegisterOf(locs()->temp(1).fpu_reg()); 3637 const DRegister dtemp = EvenDRegisterOf(locs()->temp(1).fpu_reg());
3641 __ SmiUntag(temp, left); 3638 __ SmiUntag(temp, left);
3642 __ SmiUntag(IP, right); 3639 __ SmiUntag(IP, right);
3643 __ IntegerDivide(result, temp, IP, dtemp, DTMP); 3640 __ IntegerDivide(result, temp, IP, dtemp, DTMP);
3644 3641
3645 // Check the corner case of dividing the 'MIN_SMI' with -1, in which 3642 // Check the corner case of dividing the 'MIN_SMI' with -1, in which
3646 // case we cannot tag the result. 3643 // case we cannot tag the result.
3647 __ CompareImmediate(result, 0x40000000); 3644 __ CompareImmediate(result, 0x40000000);
3648 __ b(deopt, EQ); 3645 __ b(deopt, EQ);
3649 __ SmiTag(result); 3646 __ SmiTag(result);
3650 break; 3647 break;
3651 } 3648 }
3652 case Token::kMOD: { 3649 case Token::kMOD: {
3653 ASSERT(TargetCPUFeatures::can_divide()); 3650 ASSERT(TargetCPUFeatures::can_divide());
3654 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { 3651 if (RangeUtils::CanBeZero(right_range())) {
3655 // Handle divide by zero in runtime. 3652 // Handle divide by zero in runtime.
3656 __ cmp(right, Operand(0)); 3653 __ cmp(right, Operand(0));
3657 __ b(deopt, EQ); 3654 __ b(deopt, EQ);
3658 } 3655 }
3659 const Register temp = locs()->temp(0).reg(); 3656 const Register temp = locs()->temp(0).reg();
3660 const DRegister dtemp = EvenDRegisterOf(locs()->temp(1).fpu_reg()); 3657 const DRegister dtemp = EvenDRegisterOf(locs()->temp(1).fpu_reg());
3661 __ SmiUntag(temp, left); 3658 __ SmiUntag(temp, left);
3662 __ SmiUntag(IP, right); 3659 __ SmiUntag(IP, right);
3663 __ IntegerDivide(result, temp, IP, dtemp, DTMP); 3660 __ IntegerDivide(result, temp, IP, dtemp, DTMP);
3664 __ SmiUntag(IP, right); 3661 __ SmiUntag(IP, right);
(...skipping 18 matching lines...) Expand all
3683 break; 3680 break;
3684 } 3681 }
3685 case Token::kSHR: { 3682 case Token::kSHR: {
3686 if (CanDeoptimize()) { 3683 if (CanDeoptimize()) {
3687 __ CompareImmediate(right, 0); 3684 __ CompareImmediate(right, 0);
3688 __ b(deopt, LT); 3685 __ b(deopt, LT);
3689 } 3686 }
3690 __ SmiUntag(IP, right); 3687 __ SmiUntag(IP, right);
3691 // sarl operation masks the count to 5 bits. 3688 // sarl operation masks the count to 5 bits.
3692 const intptr_t kCountLimit = 0x1F; 3689 const intptr_t kCountLimit = 0x1F;
3693 if ((right_range == NULL) || 3690 if (!RangeUtils::OnlyLessThanOrEqualTo(right_range(), kCountLimit)) {
3694 !right_range->OnlyLessThanOrEqualTo(kCountLimit)) {
3695 __ CompareImmediate(IP, kCountLimit); 3691 __ CompareImmediate(IP, kCountLimit);
3696 __ LoadImmediate(IP, kCountLimit, GT); 3692 __ LoadImmediate(IP, kCountLimit, GT);
3697 } 3693 }
3698 const Register temp = locs()->temp(0).reg(); 3694 const Register temp = locs()->temp(0).reg();
3699 __ SmiUntag(temp, left); 3695 __ SmiUntag(temp, left);
3700 __ Asr(result, temp, IP); 3696 __ Asr(result, temp, IP);
3701 __ SmiTag(result); 3697 __ SmiTag(result);
3702 break; 3698 break;
3703 } 3699 }
3704 case Token::kDIV: { 3700 case Token::kDIV: {
(...skipping 2491 matching lines...) Expand 10 before | Expand all | Expand 10 after
6196 __ vmovq(out, in); 6192 __ vmovq(out, in);
6197 } else { 6193 } else {
6198 ASSERT(representation() == kTagged); 6194 ASSERT(representation() == kTagged);
6199 const Register out = locs()->out(0).reg(); 6195 const Register out = locs()->out(0).reg();
6200 const Register in = in_loc.reg(); 6196 const Register in = in_loc.reg();
6201 __ mov(out, Operand(in)); 6197 __ mov(out, Operand(in));
6202 } 6198 }
6203 } 6199 }
6204 6200
6205 6201
6206 LocationSummary* MergedMathInstr::MakeLocationSummary(Zone* zone, 6202 LocationSummary* TruncDivModInstr::MakeLocationSummary(Zone* zone,
6207 bool opt) const { 6203 bool opt) const {
6208 if (kind() == MergedMathInstr::kTruncDivMod) { 6204 const intptr_t kNumInputs = 2;
6209 const intptr_t kNumInputs = 2; 6205 const intptr_t kNumTemps = 2;
6210 const intptr_t kNumTemps = 2; 6206 LocationSummary* summary = new (zone)
6211 LocationSummary* summary = new (zone) 6207 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
6212 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 6208 summary->set_in(0, Location::RequiresRegister());
6213 summary->set_in(0, Location::RequiresRegister()); 6209 summary->set_in(1, Location::RequiresRegister());
6214 summary->set_in(1, Location::RequiresRegister()); 6210 summary->set_temp(0, Location::RequiresRegister());
6215 summary->set_temp(0, Location::RequiresRegister()); 6211 summary->set_temp(1, Location::RequiresFpuRegister());
6216 summary->set_temp(1, Location::RequiresFpuRegister()); 6212 // Output is a pair of registers.
6217 // Output is a pair of registers. 6213 summary->set_out(0, Location::Pair(Location::RequiresRegister(),
6218 summary->set_out(0, Location::Pair(Location::RequiresRegister(), 6214 Location::RequiresRegister()));
6219 Location::RequiresRegister())); 6215 return summary;
6220 return summary;
6221 }
6222 UNIMPLEMENTED();
6223 return NULL;
6224 } 6216 }
6225 6217
6226 6218
6227 void MergedMathInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 6219 void TruncDivModInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
6228 Label* deopt = NULL; 6220 ASSERT(CanDeoptimize());
6229 if (CanDeoptimize()) { 6221 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp);
6230 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp); 6222
6223 ASSERT(TargetCPUFeatures::can_divide());
6224 const Register left = locs()->in(0).reg();
6225 const Register right = locs()->in(1).reg();
6226 ASSERT(locs()->out(0).IsPairLocation());
6227 PairLocation* pair = locs()->out(0).AsPairLocation();
6228 const Register result_div = pair->At(0).reg();
6229 const Register result_mod = pair->At(1).reg();
6230 if (RangeUtils::CanBeZero(divisor_range())) {
6231 // Handle divide by zero in runtime.
6232 __ cmp(right, Operand(0));
6233 __ b(deopt, EQ);
6231 } 6234 }
6232 if (kind() == MergedMathInstr::kTruncDivMod) { 6235 const Register temp = locs()->temp(0).reg();
6233 ASSERT(TargetCPUFeatures::can_divide()); 6236 const DRegister dtemp = EvenDRegisterOf(locs()->temp(1).fpu_reg());
6234 const Register left = locs()->in(0).reg(); 6237 __ SmiUntag(temp, left);
6235 const Register right = locs()->in(1).reg(); 6238 __ SmiUntag(IP, right);
6236 ASSERT(locs()->out(0).IsPairLocation()); 6239 __ IntegerDivide(result_div, temp, IP, dtemp, DTMP);
6237 PairLocation* pair = locs()->out(0).AsPairLocation();
6238 const Register result_div = pair->At(0).reg();
6239 const Register result_mod = pair->At(1).reg();
6240 Range* right_range = InputAt(1)->definition()->range();
6241 if ((right_range == NULL) || right_range->Overlaps(0, 0)) {
6242 // Handle divide by zero in runtime.
6243 __ cmp(right, Operand(0));
6244 __ b(deopt, EQ);
6245 }
6246 const Register temp = locs()->temp(0).reg();
6247 const DRegister dtemp = EvenDRegisterOf(locs()->temp(1).fpu_reg());
6248 __ SmiUntag(temp, left);
6249 __ SmiUntag(IP, right);
6250 __ IntegerDivide(result_div, temp, IP, dtemp, DTMP);
6251 6240
6252 // Check the corner case of dividing the 'MIN_SMI' with -1, in which 6241 // Check the corner case of dividing the 'MIN_SMI' with -1, in which
6253 // case we cannot tag the result. 6242 // case we cannot tag the result.
6254 __ CompareImmediate(result_div, 0x40000000); 6243 __ CompareImmediate(result_div, 0x40000000);
6255 __ b(deopt, EQ); 6244 __ b(deopt, EQ);
6256 __ SmiUntag(IP, right); 6245 __ SmiUntag(IP, right);
6257 // result_mod <- left - right * result_div. 6246 // result_mod <- left - right * result_div.
6258 __ mls(result_mod, IP, result_div, temp); 6247 __ mls(result_mod, IP, result_div, temp);
6259 __ SmiTag(result_div); 6248 __ SmiTag(result_div);
6260 __ SmiTag(result_mod); 6249 __ SmiTag(result_mod);
6261 // Correct MOD result: 6250 // Correct MOD result:
6262 // res = left % right; 6251 // res = left % right;
6263 // if (res < 0) { 6252 // if (res < 0) {
6264 // if (right < 0) { 6253 // if (right < 0) {
6265 // res = res - right; 6254 // res = res - right;
6266 // } else { 6255 // } else {
6267 // res = res + right; 6256 // res = res + right;
6268 // } 6257 // }
6269 // } 6258 // }
6270 Label done; 6259 Label done;
6271 __ cmp(result_mod, Operand(0)); 6260 __ cmp(result_mod, Operand(0));
6272 __ b(&done, GE); 6261 __ b(&done, GE);
6273 // Result is negative, adjust it. 6262 // Result is negative, adjust it.
6274 __ cmp(right, Operand(0)); 6263 __ cmp(right, Operand(0));
6275 __ sub(result_mod, result_mod, Operand(right), LT); 6264 __ sub(result_mod, result_mod, Operand(right), LT);
6276 __ add(result_mod, result_mod, Operand(right), GE); 6265 __ add(result_mod, result_mod, Operand(right), GE);
6277 __ Bind(&done); 6266 __ Bind(&done);
6278
6279 return;
6280 }
6281 UNIMPLEMENTED();
6282 } 6267 }
6283 6268
6284 6269
6285 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary( 6270 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary(
6286 Zone* zone, 6271 Zone* zone,
6287 bool opt) const { 6272 bool opt) const {
6288 return MakeCallSummary(zone); 6273 return MakeCallSummary(zone);
6289 } 6274 }
6290 6275
6291 6276
(...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after
6626 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 6611 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
6627 summary->set_in(0, Location::Pair(Location::RequiresRegister(), 6612 summary->set_in(0, Location::Pair(Location::RequiresRegister(),
6628 Location::RequiresRegister())); 6613 Location::RequiresRegister()));
6629 summary->set_in(1, Location::WritableRegisterOrSmiConstant(right())); 6614 summary->set_in(1, Location::WritableRegisterOrSmiConstant(right()));
6630 summary->set_out(0, Location::Pair(Location::RequiresRegister(), 6615 summary->set_out(0, Location::Pair(Location::RequiresRegister(),
6631 Location::RequiresRegister())); 6616 Location::RequiresRegister()));
6632 return summary; 6617 return summary;
6633 } 6618 }
6634 6619
6635 6620
6636 static const intptr_t kMintShiftCountLimit = 63;
6637
6638 bool ShiftMintOpInstr::has_shift_count_check() const {
6639 return !RangeUtils::IsWithin(right()->definition()->range(), 0,
6640 kMintShiftCountLimit);
6641 }
6642
6643
6644 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 6621 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
6645 PairLocation* left_pair = locs()->in(0).AsPairLocation(); 6622 PairLocation* left_pair = locs()->in(0).AsPairLocation();
6646 Register left_lo = left_pair->At(0).reg(); 6623 Register left_lo = left_pair->At(0).reg();
6647 Register left_hi = left_pair->At(1).reg(); 6624 Register left_hi = left_pair->At(1).reg();
6648 PairLocation* out_pair = locs()->out(0).AsPairLocation(); 6625 PairLocation* out_pair = locs()->out(0).AsPairLocation();
6649 Register out_lo = out_pair->At(0).reg(); 6626 Register out_lo = out_pair->At(0).reg();
6650 Register out_hi = out_pair->At(1).reg(); 6627 Register out_hi = out_pair->At(1).reg();
6651 6628
6652 Label* deopt = NULL; 6629 Label* deopt = NULL;
6653 if (CanDeoptimize()) { 6630 if (CanDeoptimize()) {
(...skipping 615 matching lines...) Expand 10 before | Expand all | Expand 10 after
7269 compiler->GenerateRuntimeCall(TokenPosition::kNoSource, deopt_id(), 7246 compiler->GenerateRuntimeCall(TokenPosition::kNoSource, deopt_id(),
7270 kGrowRegExpStackRuntimeEntry, 1, locs()); 7247 kGrowRegExpStackRuntimeEntry, 1, locs());
7271 __ Drop(1); 7248 __ Drop(1);
7272 __ Pop(result); 7249 __ Pop(result);
7273 } 7250 }
7274 7251
7275 7252
7276 } // namespace dart 7253 } // namespace dart
7277 7254
7278 #endif // defined TARGET_ARCH_ARM 7255 #endif // defined TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « runtime/vm/intermediate_language.cc ('k') | runtime/vm/intermediate_language_arm64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698