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

Side by Side Diff: runtime/vm/intermediate_language_arm64.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_arm.cc ('k') | runtime/vm/intermediate_language_dbc.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) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, 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_ARM64. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM64.
6 #if defined(TARGET_ARCH_ARM64) 6 #if defined(TARGET_ARCH_ARM64)
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 2777 matching lines...) Expand 10 before | Expand all | Expand 10 after
2788 __ cmp(left, Operand(TMP, ASR, value)); 2788 __ cmp(left, Operand(TMP, ASR, value));
2789 __ b(deopt, NE); // Overflow. 2789 __ b(deopt, NE); // Overflow.
2790 } 2790 }
2791 // Shift for result now we know there is no overflow. 2791 // Shift for result now we know there is no overflow.
2792 __ LslImmediate(result, left, value); 2792 __ LslImmediate(result, left, value);
2793 return; 2793 return;
2794 } 2794 }
2795 2795
2796 // Right (locs.in(1)) is not constant. 2796 // Right (locs.in(1)) is not constant.
2797 const Register right = locs.in(1).reg(); 2797 const Register right = locs.in(1).reg();
2798 Range* right_range = shift_left->right()->definition()->range(); 2798 Range* right_range = shift_left->right_range();
2799 if (shift_left->left()->BindsToConstant() && shift_left->can_overflow()) { 2799 if (shift_left->left()->BindsToConstant() && shift_left->can_overflow()) {
2800 // TODO(srdjan): Implement code below for is_truncating(). 2800 // TODO(srdjan): Implement code below for is_truncating().
2801 // If left is constant, we know the maximal allowed size for right. 2801 // If left is constant, we know the maximal allowed size for right.
2802 const Object& obj = shift_left->left()->BoundConstant(); 2802 const Object& obj = shift_left->left()->BoundConstant();
2803 if (obj.IsSmi()) { 2803 if (obj.IsSmi()) {
2804 const intptr_t left_int = Smi::Cast(obj).Value(); 2804 const intptr_t left_int = Smi::Cast(obj).Value();
2805 if (left_int == 0) { 2805 if (left_int == 0) {
2806 __ CompareRegisters(right, ZR); 2806 __ CompareRegisters(right, ZR);
2807 __ b(deopt, MI); 2807 __ b(deopt, MI);
2808 __ mov(result, ZR); 2808 __ mov(result, ZR);
(...skipping 10 matching lines...) Expand all
2819 __ SmiUntag(TMP, right); 2819 __ SmiUntag(TMP, right);
2820 __ lslv(result, left, TMP); 2820 __ lslv(result, left, TMP);
2821 } 2821 }
2822 return; 2822 return;
2823 } 2823 }
2824 2824
2825 const bool right_needs_check = 2825 const bool right_needs_check =
2826 !RangeUtils::IsWithin(right_range, 0, (Smi::kBits - 1)); 2826 !RangeUtils::IsWithin(right_range, 0, (Smi::kBits - 1));
2827 if (!shift_left->can_overflow()) { 2827 if (!shift_left->can_overflow()) {
2828 if (right_needs_check) { 2828 if (right_needs_check) {
2829 const bool right_may_be_negative = 2829 if (!RangeUtils::IsPositive(right_range)) {
2830 (right_range == NULL) || !right_range->IsPositive();
2831 if (right_may_be_negative) {
2832 ASSERT(shift_left->CanDeoptimize()); 2830 ASSERT(shift_left->CanDeoptimize());
2833 __ CompareRegisters(right, ZR); 2831 __ CompareRegisters(right, ZR);
2834 __ b(deopt, MI); 2832 __ b(deopt, MI);
2835 } 2833 }
2836 2834
2837 __ CompareImmediate(right, 2835 __ CompareImmediate(right,
2838 reinterpret_cast<int64_t>(Smi::New(Smi::kBits))); 2836 reinterpret_cast<int64_t>(Smi::New(Smi::kBits)));
2839 __ csel(result, ZR, result, CS); 2837 __ csel(result, ZR, result, CS);
2840 __ SmiUntag(TMP, right); 2838 __ SmiUntag(TMP, right);
2841 __ lslv(TMP, left, TMP); 2839 __ lslv(TMP, left, TMP);
(...skipping 429 matching lines...) Expand 10 before | Expand all | Expand 10 after
3271 break; 3269 break;
3272 } 3270 }
3273 default: 3271 default:
3274 UNREACHABLE(); 3272 UNREACHABLE();
3275 break; 3273 break;
3276 } 3274 }
3277 return; 3275 return;
3278 } 3276 }
3279 3277
3280 const Register right = locs()->in(1).reg(); 3278 const Register right = locs()->in(1).reg();
3281 Range* right_range = this->right()->definition()->range();
3282 switch (op_kind()) { 3279 switch (op_kind()) {
3283 case Token::kADD: { 3280 case Token::kADD: {
3284 if (deopt == NULL) { 3281 if (deopt == NULL) {
3285 __ add(result, left, Operand(right)); 3282 __ add(result, left, Operand(right));
3286 } else { 3283 } else {
3287 __ adds(result, left, Operand(right)); 3284 __ adds(result, left, Operand(right));
3288 __ b(deopt, VS); 3285 __ b(deopt, VS);
3289 } 3286 }
3290 break; 3287 break;
3291 } 3288 }
(...skipping 28 matching lines...) Expand all
3320 // No overflow check. 3317 // No overflow check.
3321 __ orr(result, left, Operand(right)); 3318 __ orr(result, left, Operand(right));
3322 break; 3319 break;
3323 } 3320 }
3324 case Token::kBIT_XOR: { 3321 case Token::kBIT_XOR: {
3325 // No overflow check. 3322 // No overflow check.
3326 __ eor(result, left, Operand(right)); 3323 __ eor(result, left, Operand(right));
3327 break; 3324 break;
3328 } 3325 }
3329 case Token::kTRUNCDIV: { 3326 case Token::kTRUNCDIV: {
3330 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { 3327 if (RangeUtils::CanBeZero(right_range())) {
3331 // Handle divide by zero in runtime. 3328 // Handle divide by zero in runtime.
3332 __ CompareRegisters(right, ZR); 3329 __ CompareRegisters(right, ZR);
3333 __ b(deopt, EQ); 3330 __ b(deopt, EQ);
3334 } 3331 }
3335 const Register temp = TMP2; 3332 const Register temp = TMP2;
3336 __ SmiUntag(temp, left); 3333 __ SmiUntag(temp, left);
3337 __ SmiUntag(TMP, right); 3334 __ SmiUntag(TMP, right);
3338 3335
3339 __ sdiv(result, temp, TMP); 3336 __ sdiv(result, temp, TMP);
3340 3337
3341 // Check the corner case of dividing the 'MIN_SMI' with -1, in which 3338 // Check the corner case of dividing the 'MIN_SMI' with -1, in which
3342 // case we cannot tag the result. 3339 // case we cannot tag the result.
3343 __ CompareImmediate(result, 0x4000000000000000LL); 3340 __ CompareImmediate(result, 0x4000000000000000LL);
3344 __ b(deopt, EQ); 3341 __ b(deopt, EQ);
3345 __ SmiTag(result); 3342 __ SmiTag(result);
3346 break; 3343 break;
3347 } 3344 }
3348 case Token::kMOD: { 3345 case Token::kMOD: {
3349 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { 3346 if (RangeUtils::CanBeZero(right_range())) {
3350 // Handle divide by zero in runtime. 3347 // Handle divide by zero in runtime.
3351 __ CompareRegisters(right, ZR); 3348 __ CompareRegisters(right, ZR);
3352 __ b(deopt, EQ); 3349 __ b(deopt, EQ);
3353 } 3350 }
3354 const Register temp = TMP2; 3351 const Register temp = TMP2;
3355 __ SmiUntag(temp, left); 3352 __ SmiUntag(temp, left);
3356 __ SmiUntag(TMP, right); 3353 __ SmiUntag(TMP, right);
3357 3354
3358 __ sdiv(result, temp, TMP); 3355 __ sdiv(result, temp, TMP);
3359 3356
(...skipping 20 matching lines...) Expand all
3380 break; 3377 break;
3381 } 3378 }
3382 case Token::kSHR: { 3379 case Token::kSHR: {
3383 if (CanDeoptimize()) { 3380 if (CanDeoptimize()) {
3384 __ CompareRegisters(right, ZR); 3381 __ CompareRegisters(right, ZR);
3385 __ b(deopt, LT); 3382 __ b(deopt, LT);
3386 } 3383 }
3387 __ SmiUntag(TMP, right); 3384 __ SmiUntag(TMP, right);
3388 // sarl operation masks the count to 6 bits. 3385 // sarl operation masks the count to 6 bits.
3389 const intptr_t kCountLimit = 0x3F; 3386 const intptr_t kCountLimit = 0x3F;
3390 if ((right_range == NULL) || 3387 if (!RangeUtils::OnlyLessThanOrEqualTo(right_range(), kCountLimit)) {
3391 !right_range->OnlyLessThanOrEqualTo(kCountLimit)) {
3392 __ LoadImmediate(TMP2, kCountLimit); 3388 __ LoadImmediate(TMP2, kCountLimit);
3393 __ CompareRegisters(TMP, TMP2); 3389 __ CompareRegisters(TMP, TMP2);
3394 __ csel(TMP, TMP2, TMP, GT); 3390 __ csel(TMP, TMP2, TMP, GT);
3395 } 3391 }
3396 const Register temp = locs()->temp(0).reg(); 3392 const Register temp = locs()->temp(0).reg();
3397 __ SmiUntag(temp, left); 3393 __ SmiUntag(temp, left);
3398 __ asrv(result, temp, TMP); 3394 __ asrv(result, temp, TMP);
3399 __ SmiTag(result); 3395 __ SmiTag(result);
3400 break; 3396 break;
3401 } 3397 }
(...skipping 1973 matching lines...) Expand 10 before | Expand all | Expand 10 after
5375 __ fmovdd(out, in); 5371 __ fmovdd(out, in);
5376 } else { 5372 } else {
5377 ASSERT(representation() == kTagged); 5373 ASSERT(representation() == kTagged);
5378 const Register out = locs()->out(0).reg(); 5374 const Register out = locs()->out(0).reg();
5379 const Register in = in_loc.reg(); 5375 const Register in = in_loc.reg();
5380 __ mov(out, in); 5376 __ mov(out, in);
5381 } 5377 }
5382 } 5378 }
5383 5379
5384 5380
5385 LocationSummary* MergedMathInstr::MakeLocationSummary(Zone* zone, 5381 LocationSummary* TruncDivModInstr::MakeLocationSummary(Zone* zone,
5386 bool opt) const { 5382 bool opt) const {
5387 if (kind() == MergedMathInstr::kTruncDivMod) { 5383 const intptr_t kNumInputs = 2;
5388 const intptr_t kNumInputs = 2; 5384 const intptr_t kNumTemps = 0;
5389 const intptr_t kNumTemps = 0; 5385 LocationSummary* summary = new (zone)
5390 LocationSummary* summary = new (zone) 5386 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
5391 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 5387 summary->set_in(0, Location::RequiresRegister());
5392 summary->set_in(0, Location::RequiresRegister()); 5388 summary->set_in(1, Location::RequiresRegister());
5393 summary->set_in(1, Location::RequiresRegister()); 5389 // Output is a pair of registers.
5394 // Output is a pair of registers. 5390 summary->set_out(0, Location::Pair(Location::RequiresRegister(),
5395 summary->set_out(0, Location::Pair(Location::RequiresRegister(), 5391 Location::RequiresRegister()));
5396 Location::RequiresRegister())); 5392 return summary;
5397 return summary;
5398 }
5399 UNIMPLEMENTED();
5400 return NULL;
5401 } 5393 }
5402 5394
5403 5395
5404 void MergedMathInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5396 void TruncDivModInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5405 Label* deopt = NULL; 5397 ASSERT(CanDeoptimize());
5406 if (CanDeoptimize()) { 5398 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp);
5407 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp); 5399 const Register left = locs()->in(0).reg();
5400 const Register right = locs()->in(1).reg();
5401 ASSERT(locs()->out(0).IsPairLocation());
5402 const PairLocation* pair = locs()->out(0).AsPairLocation();
5403 const Register result_div = pair->At(0).reg();
5404 const Register result_mod = pair->At(1).reg();
5405 if (RangeUtils::CanBeZero(divisor_range())) {
5406 // Handle divide by zero in runtime.
5407 __ CompareRegisters(right, ZR);
5408 __ b(deopt, EQ);
5408 } 5409 }
5409 if (kind() == MergedMathInstr::kTruncDivMod) {
5410 const Register left = locs()->in(0).reg();
5411 const Register right = locs()->in(1).reg();
5412 ASSERT(locs()->out(0).IsPairLocation());
5413 const PairLocation* pair = locs()->out(0).AsPairLocation();
5414 const Register result_div = pair->At(0).reg();
5415 const Register result_mod = pair->At(1).reg();
5416 const Range* right_range = InputAt(1)->definition()->range();
5417 if ((right_range == NULL) || right_range->Overlaps(0, 0)) {
5418 // Handle divide by zero in runtime.
5419 __ CompareRegisters(right, ZR);
5420 __ b(deopt, EQ);
5421 }
5422 5410
5423 __ SmiUntag(result_mod, left); 5411 __ SmiUntag(result_mod, left);
5424 __ SmiUntag(TMP, right); 5412 __ SmiUntag(TMP, right);
5425 5413
5426 __ sdiv(result_div, result_mod, TMP); 5414 __ sdiv(result_div, result_mod, TMP);
5427 5415
5428 // Check the corner case of dividing the 'MIN_SMI' with -1, in which 5416 // Check the corner case of dividing the 'MIN_SMI' with -1, in which
5429 // case we cannot tag the result. 5417 // case we cannot tag the result.
5430 __ CompareImmediate(result_div, 0x4000000000000000); 5418 __ CompareImmediate(result_div, 0x4000000000000000);
5431 __ b(deopt, EQ); 5419 __ b(deopt, EQ);
5432 // result_mod <- left - right * result_div. 5420 // result_mod <- left - right * result_div.
5433 __ msub(result_mod, TMP, result_div, result_mod); 5421 __ msub(result_mod, TMP, result_div, result_mod);
5434 __ SmiTag(result_div); 5422 __ SmiTag(result_div);
5435 __ SmiTag(result_mod); 5423 __ SmiTag(result_mod);
5436 // Correct MOD result: 5424 // Correct MOD result:
5437 // res = left % right; 5425 // res = left % right;
5438 // if (res < 0) { 5426 // if (res < 0) {
5439 // if (right < 0) { 5427 // if (right < 0) {
5440 // res = res - right; 5428 // res = res - right;
5441 // } else { 5429 // } else {
5442 // res = res + right; 5430 // res = res + right;
5443 // } 5431 // }
5444 // } 5432 // }
5445 Label done; 5433 Label done;
5446 __ CompareRegisters(result_mod, ZR); 5434 __ CompareRegisters(result_mod, ZR);
5447 __ b(&done, GE); 5435 __ b(&done, GE);
5448 // Result is negative, adjust it. 5436 // Result is negative, adjust it.
5449 __ CompareRegisters(right, ZR); 5437 __ CompareRegisters(right, ZR);
5450 __ sub(TMP2, result_mod, Operand(right)); 5438 __ sub(TMP2, result_mod, Operand(right));
5451 __ add(TMP, result_mod, Operand(right)); 5439 __ add(TMP, result_mod, Operand(right));
5452 __ csel(result_mod, TMP, TMP2, GE); 5440 __ csel(result_mod, TMP, TMP2, GE);
5453 __ Bind(&done); 5441 __ Bind(&done);
5454 return;
5455 }
5456 UNIMPLEMENTED();
5457 } 5442 }
5458 5443
5459 5444
5460 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary( 5445 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary(
5461 Zone* zone, 5446 Zone* zone,
5462 bool opt) const { 5447 bool opt) const {
5463 return MakeCallSummary(zone); 5448 return MakeCallSummary(zone);
5464 } 5449 }
5465 5450
5466 5451
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after
5725 UNIMPLEMENTED(); 5710 UNIMPLEMENTED();
5726 return NULL; 5711 return NULL;
5727 } 5712 }
5728 5713
5729 5714
5730 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5715 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5731 UNIMPLEMENTED(); 5716 UNIMPLEMENTED();
5732 } 5717 }
5733 5718
5734 5719
5735 bool ShiftMintOpInstr::has_shift_count_check() const {
5736 UNREACHABLE();
5737 return false;
5738 }
5739
5740
5741 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(Zone* zone, 5720 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(Zone* zone,
5742 bool opt) const { 5721 bool opt) const {
5743 UNIMPLEMENTED(); 5722 UNIMPLEMENTED();
5744 return NULL; 5723 return NULL;
5745 } 5724 }
5746 5725
5747 5726
5748 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5727 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5749 UNIMPLEMENTED(); 5728 UNIMPLEMENTED();
5750 } 5729 }
(...skipping 339 matching lines...) Expand 10 before | Expand all | Expand 10 after
6090 compiler->GenerateRuntimeCall(TokenPosition::kNoSource, deopt_id(), 6069 compiler->GenerateRuntimeCall(TokenPosition::kNoSource, deopt_id(),
6091 kGrowRegExpStackRuntimeEntry, 1, locs()); 6070 kGrowRegExpStackRuntimeEntry, 1, locs());
6092 __ Drop(1); 6071 __ Drop(1);
6093 __ Pop(result); 6072 __ Pop(result);
6094 } 6073 }
6095 6074
6096 6075
6097 } // namespace dart 6076 } // namespace dart
6098 6077
6099 #endif // defined TARGET_ARCH_ARM64 6078 #endif // defined TARGET_ARCH_ARM64
OLDNEW
« no previous file with comments | « runtime/vm/intermediate_language_arm.cc ('k') | runtime/vm/intermediate_language_dbc.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698