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

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

Issue 300003015: Reduce register pressure on ARM, ARM64, and MIPS. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 6 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
« no previous file with comments | « runtime/vm/disassembler_arm64.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 // 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_ARM. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM.
6 #if defined(TARGET_ARCH_ARM) 6 #if defined(TARGET_ARCH_ARM)
7 7
8 #include "vm/intermediate_language.h" 8 #include "vm/intermediate_language.h"
9 9
10 #include "vm/cpu.h" 10 #include "vm/cpu.h"
(...skipping 1433 matching lines...) Expand 10 before | Expand all | Expand 10 after
1444 : Location::RegisterOrConstant(value())); 1444 : Location::RegisterOrConstant(value()));
1445 break; 1445 break;
1446 case kExternalTypedDataUint8ArrayCid: 1446 case kExternalTypedDataUint8ArrayCid:
1447 case kExternalTypedDataUint8ClampedArrayCid: 1447 case kExternalTypedDataUint8ClampedArrayCid:
1448 case kTypedDataInt8ArrayCid: 1448 case kTypedDataInt8ArrayCid:
1449 case kTypedDataUint8ArrayCid: 1449 case kTypedDataUint8ArrayCid:
1450 case kTypedDataUint8ClampedArrayCid: 1450 case kTypedDataUint8ClampedArrayCid:
1451 case kOneByteStringCid: 1451 case kOneByteStringCid:
1452 case kTypedDataInt16ArrayCid: 1452 case kTypedDataInt16ArrayCid:
1453 case kTypedDataUint16ArrayCid: 1453 case kTypedDataUint16ArrayCid:
1454 locs->set_in(2, Location::WritableRegister()); 1454 locs->set_in(2, Location::RequiresRegister());
1455 break; 1455 break;
1456 case kTypedDataInt32ArrayCid: 1456 case kTypedDataInt32ArrayCid:
1457 case kTypedDataUint32ArrayCid: 1457 case kTypedDataUint32ArrayCid:
1458 // For smis, use a writable register because the value must be untagged 1458 // Smis are untagged in TMP register. Mints are stored in register pairs.
1459 // before storing. Mints are stored in register pairs.
1460 if (value()->IsSmiValue()) { 1459 if (value()->IsSmiValue()) {
1461 locs->set_in(2, Location::WritableRegister()); 1460 locs->set_in(2, Location::RequiresRegister());
1462 } else { 1461 } else {
1463 // We only move the lower 32-bits so we don't care where the high bits 1462 // We only move the lower 32-bits so we don't care where the high bits
1464 // are located. 1463 // are located.
1465 locs->set_in(2, Location::Pair(Location::RequiresRegister(), 1464 locs->set_in(2, Location::Pair(Location::RequiresRegister(),
1466 Location::Any())); 1465 Location::Any()));
1467 } 1466 }
1468 break; 1467 break;
1469 case kTypedDataFloat32ArrayCid: 1468 case kTypedDataFloat32ArrayCid:
1470 // Need low register (<= Q7). 1469 // Need low register (<= Q7).
1471 locs->set_in(2, Location::FpuRegisterLocation(Q7)); 1470 locs->set_in(2, Location::FpuRegisterLocation(Q7));
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
1513 case kTypedDataInt8ArrayCid: 1512 case kTypedDataInt8ArrayCid:
1514 case kTypedDataUint8ArrayCid: 1513 case kTypedDataUint8ArrayCid:
1515 case kExternalTypedDataUint8ArrayCid: 1514 case kExternalTypedDataUint8ArrayCid:
1516 case kOneByteStringCid: { 1515 case kOneByteStringCid: {
1517 if (locs()->in(2).IsConstant()) { 1516 if (locs()->in(2).IsConstant()) {
1518 const Smi& constant = Smi::Cast(locs()->in(2).constant()); 1517 const Smi& constant = Smi::Cast(locs()->in(2).constant());
1519 __ LoadImmediate(IP, static_cast<int8_t>(constant.Value())); 1518 __ LoadImmediate(IP, static_cast<int8_t>(constant.Value()));
1520 __ strb(IP, element_address); 1519 __ strb(IP, element_address);
1521 } else { 1520 } else {
1522 const Register value = locs()->in(2).reg(); 1521 const Register value = locs()->in(2).reg();
1523 __ SmiUntag(value); 1522 __ SmiUntag(IP, value);
1524 __ strb(value, element_address); 1523 __ strb(IP, element_address);
1525 } 1524 }
1526 break; 1525 break;
1527 } 1526 }
1528 case kTypedDataUint8ClampedArrayCid: 1527 case kTypedDataUint8ClampedArrayCid:
1529 case kExternalTypedDataUint8ClampedArrayCid: { 1528 case kExternalTypedDataUint8ClampedArrayCid: {
1530 if (locs()->in(2).IsConstant()) { 1529 if (locs()->in(2).IsConstant()) {
1531 const Smi& constant = Smi::Cast(locs()->in(2).constant()); 1530 const Smi& constant = Smi::Cast(locs()->in(2).constant());
1532 intptr_t value = constant.Value(); 1531 intptr_t value = constant.Value();
1533 // Clamp to 0x0 or 0xFF respectively. 1532 // Clamp to 0x0 or 0xFF respectively.
1534 if (value > 0xFF) { 1533 if (value > 0xFF) {
1535 value = 0xFF; 1534 value = 0xFF;
1536 } else if (value < 0) { 1535 } else if (value < 0) {
1537 value = 0; 1536 value = 0;
1538 } 1537 }
1539 __ LoadImmediate(IP, static_cast<int8_t>(value)); 1538 __ LoadImmediate(IP, static_cast<int8_t>(value));
1540 __ strb(IP, element_address); 1539 __ strb(IP, element_address);
1541 } else { 1540 } else {
1542 const Register value = locs()->in(2).reg(); 1541 const Register value = locs()->in(2).reg();
1543 Label store_value; 1542 __ LoadImmediate(IP, 0x1FE); // Smi 0xFF.
1544 __ SmiUntag(value); 1543 __ cmp(value, Operand(IP)); // Compare Smi value and smi 0xFF.
1545 __ cmp(value, Operand(0xFF));
1546 // Clamp to 0x00 or 0xFF respectively. 1544 // Clamp to 0x00 or 0xFF respectively.
1547 __ b(&store_value, LS); 1545 __ mov(IP, Operand(0), LE); // IP = value <= 0x1FE ? 0 : 0x1FE.
1548 __ mov(value, Operand(0x00), LE); 1546 __ mov(IP, Operand(value), LS); // IP = value in range ? value : IP.
1549 __ mov(value, Operand(0xFF), GT); 1547 __ SmiUntag(IP);
1550 __ Bind(&store_value); 1548 __ strb(IP, element_address);
1551 __ strb(value, element_address);
1552 } 1549 }
1553 break; 1550 break;
1554 } 1551 }
1555 case kTypedDataInt16ArrayCid: 1552 case kTypedDataInt16ArrayCid:
1556 case kTypedDataUint16ArrayCid: { 1553 case kTypedDataUint16ArrayCid: {
1557 const Register value = locs()->in(2).reg(); 1554 const Register value = locs()->in(2).reg();
1558 __ SmiUntag(value); 1555 __ SmiUntag(IP, value);
1559 __ strh(value, element_address); 1556 __ strh(IP, element_address);
1560 break; 1557 break;
1561 } 1558 }
1562 case kTypedDataInt32ArrayCid: 1559 case kTypedDataInt32ArrayCid:
1563 case kTypedDataUint32ArrayCid: { 1560 case kTypedDataUint32ArrayCid: {
1564 if (value()->IsSmiValue()) { 1561 if (value()->IsSmiValue()) {
1565 ASSERT(RequiredInputRepresentation(2) == kTagged); 1562 ASSERT(RequiredInputRepresentation(2) == kTagged);
1566 const Register value = locs()->in(2).reg(); 1563 const Register value = locs()->in(2).reg();
1567 __ SmiUntag(value); 1564 __ SmiUntag(IP, value);
1568 __ str(value, element_address); 1565 __ str(IP, element_address);
1569 } else { 1566 } else {
1570 ASSERT(RequiredInputRepresentation(2) == kUnboxedMint); 1567 ASSERT(RequiredInputRepresentation(2) == kUnboxedMint);
1571 PairLocation* value_pair = locs()->in(2).AsPairLocation(); 1568 PairLocation* value_pair = locs()->in(2).AsPairLocation();
1572 Register value1 = value_pair->At(0).reg(); 1569 Register value1 = value_pair->At(0).reg();
1573 __ str(value1, element_address); 1570 __ str(value1, element_address);
1574 } 1571 }
1575 break; 1572 break;
1576 } 1573 }
1577 case kTypedDataFloat32ArrayCid: { 1574 case kTypedDataFloat32ArrayCid: {
1578 const SRegister value_reg = 1575 const SRegister value_reg =
(...skipping 1403 matching lines...) Expand 10 before | Expand all | Expand 10 after
2982 return; 2979 return;
2983 } 2980 }
2984 const intptr_t max_right = kSmiBits - Utils::HighestBit(left_int); 2981 const intptr_t max_right = kSmiBits - Utils::HighestBit(left_int);
2985 const bool right_needs_check = 2982 const bool right_needs_check =
2986 (right_range == NULL) || 2983 (right_range == NULL) ||
2987 !right_range->IsWithin(0, max_right - 1); 2984 !right_range->IsWithin(0, max_right - 1);
2988 if (right_needs_check) { 2985 if (right_needs_check) {
2989 __ cmp(right, Operand(reinterpret_cast<int32_t>(Smi::New(max_right)))); 2986 __ cmp(right, Operand(reinterpret_cast<int32_t>(Smi::New(max_right))));
2990 __ b(deopt, CS); 2987 __ b(deopt, CS);
2991 } 2988 }
2992 __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP. 2989 __ SmiUntag(IP, right);
2993 __ Lsl(result, left, IP); 2990 __ Lsl(result, left, IP);
2994 } 2991 }
2995 return; 2992 return;
2996 } 2993 }
2997 2994
2998 const bool right_needs_check = 2995 const bool right_needs_check =
2999 (right_range == NULL) || !right_range->IsWithin(0, (Smi::kBits - 1)); 2996 (right_range == NULL) || !right_range->IsWithin(0, (Smi::kBits - 1));
3000 if (is_truncating) { 2997 if (is_truncating) {
3001 if (right_needs_check) { 2998 if (right_needs_check) {
3002 const bool right_may_be_negative = 2999 const bool right_may_be_negative =
3003 (right_range == NULL) || 3000 (right_range == NULL) ||
3004 !right_range->IsWithin(0, RangeBoundary::kPlusInfinity); 3001 !right_range->IsWithin(0, RangeBoundary::kPlusInfinity);
3005 if (right_may_be_negative) { 3002 if (right_may_be_negative) {
3006 ASSERT(shift_left->CanDeoptimize()); 3003 ASSERT(shift_left->CanDeoptimize());
3007 __ cmp(right, Operand(0)); 3004 __ cmp(right, Operand(0));
3008 __ b(deopt, MI); 3005 __ b(deopt, MI);
3009 } 3006 }
3010 3007
3011 __ cmp(right, Operand(reinterpret_cast<int32_t>(Smi::New(Smi::kBits)))); 3008 __ cmp(right, Operand(reinterpret_cast<int32_t>(Smi::New(Smi::kBits))));
3012 __ mov(result, Operand(0), CS); 3009 __ mov(result, Operand(0), CS);
3013 __ Asr(IP, right, kSmiTagSize, CC); // SmiUntag right into IP if CC. 3010 __ SmiUntag(IP, right, CC); // SmiUntag right into IP if CC.
3014 __ Lsl(result, left, IP, CC); 3011 __ Lsl(result, left, IP, CC);
3015 } else { 3012 } else {
3016 __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP. 3013 __ SmiUntag(IP, right);
3017 __ Lsl(result, left, IP); 3014 __ Lsl(result, left, IP);
3018 } 3015 }
3019 } else { 3016 } else {
3020 if (right_needs_check) { 3017 if (right_needs_check) {
3021 ASSERT(shift_left->CanDeoptimize()); 3018 ASSERT(shift_left->CanDeoptimize());
3022 __ cmp(right, Operand(reinterpret_cast<int32_t>(Smi::New(Smi::kBits)))); 3019 __ cmp(right, Operand(reinterpret_cast<int32_t>(Smi::New(Smi::kBits))));
3023 __ b(deopt, CS); 3020 __ b(deopt, CS);
3024 } 3021 }
3025 // Left is not a constant. 3022 // Left is not a constant.
3026 // Check if count too large for handling it inlined. 3023 // Check if count too large for handling it inlined.
3027 __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP. 3024 __ SmiUntag(IP, right);
3028 // Overflow test (preserve left, right, and IP); 3025 // Overflow test (preserve left, right, and IP);
3029 const Register temp = locs.temp(0).reg(); 3026 const Register temp = locs.temp(0).reg();
3030 __ Lsl(temp, left, IP); 3027 __ Lsl(temp, left, IP);
3031 __ cmp(left, Operand(temp, ASR, IP)); 3028 __ cmp(left, Operand(temp, ASR, IP));
3032 __ b(deopt, NE); // Overflow. 3029 __ b(deopt, NE); // Overflow.
3033 // Shift for result now we know there is no overflow. 3030 // Shift for result now we know there is no overflow.
3034 __ Lsl(result, left, IP); 3031 __ Lsl(result, left, IP);
3035 } 3032 }
3036 } 3033 }
3037 3034
(...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after
3268 case Token::kSUB: { 3265 case Token::kSUB: {
3269 if (deopt == NULL) { 3266 if (deopt == NULL) {
3270 __ sub(result, left, Operand(right)); 3267 __ sub(result, left, Operand(right));
3271 } else { 3268 } else {
3272 __ subs(result, left, Operand(right)); 3269 __ subs(result, left, Operand(right));
3273 __ b(deopt, VS); 3270 __ b(deopt, VS);
3274 } 3271 }
3275 break; 3272 break;
3276 } 3273 }
3277 case Token::kMUL: { 3274 case Token::kMUL: {
3278 __ Asr(IP, left, kSmiTagSize); // SmiUntag left into IP. 3275 __ SmiUntag(IP, left);
3279 if (deopt == NULL) { 3276 if (deopt == NULL) {
3280 __ mul(result, IP, right); 3277 __ mul(result, IP, right);
3281 } else { 3278 } else {
3282 if (TargetCPUFeatures::arm_version() == ARMv7) { 3279 if (TargetCPUFeatures::arm_version() == ARMv7) {
3283 __ smull(result, IP, IP, right); 3280 __ smull(result, IP, IP, right);
3284 // IP: result bits 32..63. 3281 // IP: result bits 32..63.
3285 __ cmp(IP, Operand(result, ASR, 31)); 3282 __ cmp(IP, Operand(result, ASR, 31));
3286 __ b(deopt, NE); 3283 __ b(deopt, NE);
3287 } else { 3284 } else {
3288 const QRegister qtmp = locs()->temp(0).fpu_reg(); 3285 const QRegister qtmp = locs()->temp(0).fpu_reg();
(...skipping 21 matching lines...) Expand all
3310 break; 3307 break;
3311 } 3308 }
3312 case Token::kTRUNCDIV: { 3309 case Token::kTRUNCDIV: {
3313 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { 3310 if ((right_range == NULL) || right_range->Overlaps(0, 0)) {
3314 // Handle divide by zero in runtime. 3311 // Handle divide by zero in runtime.
3315 __ cmp(right, Operand(0)); 3312 __ cmp(right, Operand(0));
3316 __ b(deopt, EQ); 3313 __ b(deopt, EQ);
3317 } 3314 }
3318 const Register temp = locs()->temp(0).reg(); 3315 const Register temp = locs()->temp(0).reg();
3319 const DRegister dtemp = EvenDRegisterOf(locs()->temp(1).fpu_reg()); 3316 const DRegister dtemp = EvenDRegisterOf(locs()->temp(1).fpu_reg());
3320 __ Asr(temp, left, kSmiTagSize); // SmiUntag left into temp. 3317 __ SmiUntag(temp, left);
3321 __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP. 3318 __ SmiUntag(IP, right);
3322 3319
3323 __ IntegerDivide(result, temp, IP, dtemp, DTMP); 3320 __ IntegerDivide(result, temp, IP, dtemp, DTMP);
3324 3321
3325 // Check the corner case of dividing the 'MIN_SMI' with -1, in which 3322 // Check the corner case of dividing the 'MIN_SMI' with -1, in which
3326 // case we cannot tag the result. 3323 // case we cannot tag the result.
3327 __ CompareImmediate(result, 0x40000000); 3324 __ CompareImmediate(result, 0x40000000);
3328 __ b(deopt, EQ); 3325 __ b(deopt, EQ);
3329 __ SmiTag(result); 3326 __ SmiTag(result);
3330 break; 3327 break;
3331 } 3328 }
3332 case Token::kMOD: { 3329 case Token::kMOD: {
3333 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { 3330 if ((right_range == NULL) || right_range->Overlaps(0, 0)) {
3334 // Handle divide by zero in runtime. 3331 // Handle divide by zero in runtime.
3335 __ cmp(right, Operand(0)); 3332 __ cmp(right, Operand(0));
3336 __ b(deopt, EQ); 3333 __ b(deopt, EQ);
3337 } 3334 }
3338 const Register temp = locs()->temp(0).reg(); 3335 const Register temp = locs()->temp(0).reg();
3339 const DRegister dtemp = EvenDRegisterOf(locs()->temp(1).fpu_reg()); 3336 const DRegister dtemp = EvenDRegisterOf(locs()->temp(1).fpu_reg());
3340 __ Asr(temp, left, kSmiTagSize); // SmiUntag left into temp. 3337 __ SmiUntag(temp, left);
3341 __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP. 3338 __ SmiUntag(IP, right);
3342 3339
3343 __ IntegerDivide(result, temp, IP, dtemp, DTMP); 3340 __ IntegerDivide(result, temp, IP, dtemp, DTMP);
3344 3341
3345 __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP. 3342 __ SmiUntag(IP, right);
3346 __ mls(result, IP, result, temp); // result <- left - right * result 3343 __ mls(result, IP, result, temp); // result <- left - right * result
3347 __ SmiTag(result); 3344 __ SmiTag(result);
3348 // res = left % right; 3345 // res = left % right;
3349 // if (res < 0) { 3346 // if (res < 0) {
3350 // if (right < 0) { 3347 // if (right < 0) {
3351 // res = res - right; 3348 // res = res - right;
3352 // } else { 3349 // } else {
3353 // res = res + right; 3350 // res = res + right;
3354 // } 3351 // }
3355 // } 3352 // }
3356 Label done; 3353 Label done;
3357 __ cmp(result, Operand(0)); 3354 __ cmp(result, Operand(0));
3358 __ b(&done, GE); 3355 __ b(&done, GE);
3359 // Result is negative, adjust it. 3356 // Result is negative, adjust it.
3360 __ cmp(right, Operand(0)); 3357 __ cmp(right, Operand(0));
3361 __ sub(result, result, Operand(right), LT); 3358 __ sub(result, result, Operand(right), LT);
3362 __ add(result, result, Operand(right), GE); 3359 __ add(result, result, Operand(right), GE);
3363 __ Bind(&done); 3360 __ Bind(&done);
3364 break; 3361 break;
3365 } 3362 }
3366 case Token::kSHR: { 3363 case Token::kSHR: {
3367 if (CanDeoptimize()) { 3364 if (CanDeoptimize()) {
3368 __ CompareImmediate(right, 0); 3365 __ CompareImmediate(right, 0);
3369 __ b(deopt, LT); 3366 __ b(deopt, LT);
3370 } 3367 }
3371 __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP. 3368 __ SmiUntag(IP, right);
3372 // sarl operation masks the count to 5 bits. 3369 // sarl operation masks the count to 5 bits.
3373 const intptr_t kCountLimit = 0x1F; 3370 const intptr_t kCountLimit = 0x1F;
3374 if ((right_range == NULL) || 3371 if ((right_range == NULL) ||
3375 !right_range->IsWithin(RangeBoundary::kMinusInfinity, kCountLimit)) { 3372 !right_range->IsWithin(RangeBoundary::kMinusInfinity, kCountLimit)) {
3376 __ CompareImmediate(IP, kCountLimit); 3373 __ CompareImmediate(IP, kCountLimit);
3377 __ LoadImmediate(IP, kCountLimit, GT); 3374 __ LoadImmediate(IP, kCountLimit, GT);
3378 } 3375 }
3379 const Register temp = locs()->temp(0).reg(); 3376 const Register temp = locs()->temp(0).reg();
3380 __ Asr(temp, left, kSmiTagSize); // SmiUntag left into temp. 3377 __ SmiUntag(temp, left);
3381 __ Asr(result, temp, IP); 3378 __ Asr(result, temp, IP);
3382 __ SmiTag(result); 3379 __ SmiTag(result);
3383 break; 3380 break;
3384 } 3381 }
3385 case Token::kDIV: { 3382 case Token::kDIV: {
3386 // Dispatches to 'Double./'. 3383 // Dispatches to 'Double./'.
3387 // TODO(srdjan): Implement as conversion to double and double division. 3384 // TODO(srdjan): Implement as conversion to double and double division.
3388 UNREACHABLE(); 3385 UNREACHABLE();
3389 break; 3386 break;
3390 } 3387 }
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
3467 __ Bind(slow_path->exit_label()); 3464 __ Bind(slow_path->exit_label());
3468 __ StoreDToOffset(value, out_reg, Double::value_offset() - kHeapObjectTag); 3465 __ StoreDToOffset(value, out_reg, Double::value_offset() - kHeapObjectTag);
3469 } 3466 }
3470 3467
3471 3468
3472 LocationSummary* UnboxDoubleInstr::MakeLocationSummary(Isolate* isolate, 3469 LocationSummary* UnboxDoubleInstr::MakeLocationSummary(Isolate* isolate,
3473 bool opt) const { 3470 bool opt) const {
3474 const intptr_t kNumInputs = 1; 3471 const intptr_t kNumInputs = 1;
3475 const intptr_t value_cid = value()->Type()->ToCid(); 3472 const intptr_t value_cid = value()->Type()->ToCid();
3476 const bool needs_temp = ((value_cid != kSmiCid) && (value_cid != kDoubleCid)); 3473 const bool needs_temp = ((value_cid != kSmiCid) && (value_cid != kDoubleCid));
3477 const bool needs_writable_input = (value_cid == kSmiCid);
3478 const intptr_t kNumTemps = needs_temp ? 1 : 0; 3474 const intptr_t kNumTemps = needs_temp ? 1 : 0;
3479 LocationSummary* summary = new(isolate) LocationSummary( 3475 LocationSummary* summary = new(isolate) LocationSummary(
3480 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); 3476 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
3481 summary->set_in(0, needs_writable_input 3477 summary->set_in(0, Location::RequiresRegister());
3482 ? Location::WritableRegister()
3483 : Location::RequiresRegister());
3484 if (needs_temp) summary->set_temp(0, Location::RequiresRegister()); 3478 if (needs_temp) summary->set_temp(0, Location::RequiresRegister());
3485 summary->set_out(0, Location::RequiresFpuRegister()); 3479 summary->set_out(0, Location::RequiresFpuRegister());
3486 return summary; 3480 return summary;
3487 } 3481 }
3488 3482
3489 3483
3490 void UnboxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3484 void UnboxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3491 CompileType* value_type = value()->Type(); 3485 CompileType* value_type = value()->Type();
3492 const intptr_t value_cid = value_type->ToCid(); 3486 const intptr_t value_cid = value_type->ToCid();
3493 const Register value = locs()->in(0).reg(); 3487 const Register value = locs()->in(0).reg();
3494 const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg()); 3488 const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg());
3495 3489
3496 if (value_cid == kDoubleCid) { 3490 if (value_cid == kDoubleCid) {
3497 __ LoadDFromOffset(result, value, Double::value_offset() - kHeapObjectTag); 3491 __ LoadDFromOffset(result, value, Double::value_offset() - kHeapObjectTag);
3498 } else if (value_cid == kSmiCid) { 3492 } else if (value_cid == kSmiCid) {
3499 __ SmiUntag(value); // Untag input before conversion. 3493 __ SmiUntag(IP, value);
3500 __ vmovsr(STMP, value); 3494 __ vmovsr(STMP, IP);
3501 __ vcvtdi(result, STMP); 3495 __ vcvtdi(result, STMP);
3502 } else { 3496 } else {
3503 Label* deopt = compiler->AddDeoptStub(deopt_id_, 3497 Label* deopt = compiler->AddDeoptStub(deopt_id_,
3504 ICData::kDeoptBinaryDoubleOp); 3498 ICData::kDeoptBinaryDoubleOp);
3505 const Register temp = locs()->temp(0).reg(); 3499 const Register temp = locs()->temp(0).reg();
3506 if (value_type->is_nullable() && 3500 if (value_type->is_nullable() &&
3507 (value_type->ToNullableCid() == kDoubleCid)) { 3501 (value_type->ToNullableCid() == kDoubleCid)) {
3508 __ CompareImmediate(value, reinterpret_cast<intptr_t>(Object::null())); 3502 __ CompareImmediate(value, reinterpret_cast<intptr_t>(Object::null()));
3509 __ b(deopt, EQ); 3503 __ b(deopt, EQ);
3510 // It must be double now. 3504 // It must be double now.
3511 __ LoadDFromOffset(result, value, 3505 __ LoadDFromOffset(result, value,
3512 Double::value_offset() - kHeapObjectTag); 3506 Double::value_offset() - kHeapObjectTag);
3513 } else { 3507 } else {
3514 Label is_smi, done; 3508 Label is_smi, done;
3515 __ tst(value, Operand(kSmiTagMask)); 3509 __ tst(value, Operand(kSmiTagMask));
3516 __ b(&is_smi, EQ); 3510 __ b(&is_smi, EQ);
3517 __ CompareClassId(value, kDoubleCid, temp); 3511 __ CompareClassId(value, kDoubleCid, temp);
3518 __ b(deopt, NE); 3512 __ b(deopt, NE);
3519 __ LoadDFromOffset(result, value, 3513 __ LoadDFromOffset(result, value,
3520 Double::value_offset() - kHeapObjectTag); 3514 Double::value_offset() - kHeapObjectTag);
3521 __ b(&done); 3515 __ b(&done);
3522 __ Bind(&is_smi); 3516 __ Bind(&is_smi);
3523 // TODO(regis): Why do we preserve value here but not above? 3517 __ SmiUntag(IP, value);
3524 __ mov(IP, Operand(value, ASR, 1)); // Copy and untag.
3525 __ vmovsr(STMP, IP); 3518 __ vmovsr(STMP, IP);
3526 __ vcvtdi(result, STMP); 3519 __ vcvtdi(result, STMP);
3527 __ Bind(&done); 3520 __ Bind(&done);
3528 } 3521 }
3529 } 3522 }
3530 } 3523 }
3531 3524
3532 3525
3533 LocationSummary* BoxFloat32x4Instr::MakeLocationSummary(Isolate* isolate, 3526 LocationSummary* BoxFloat32x4Instr::MakeLocationSummary(Isolate* isolate,
3534 bool opt) const { 3527 bool opt) const {
(...skipping 1591 matching lines...) Expand 10 before | Expand all | Expand 10 after
5126 __ vnegd(result, value); 5119 __ vnegd(result, value);
5127 } 5120 }
5128 5121
5129 5122
5130 LocationSummary* SmiToDoubleInstr::MakeLocationSummary(Isolate* isolate, 5123 LocationSummary* SmiToDoubleInstr::MakeLocationSummary(Isolate* isolate,
5131 bool opt) const { 5124 bool opt) const {
5132 const intptr_t kNumInputs = 1; 5125 const intptr_t kNumInputs = 1;
5133 const intptr_t kNumTemps = 0; 5126 const intptr_t kNumTemps = 0;
5134 LocationSummary* result = new(isolate) LocationSummary( 5127 LocationSummary* result = new(isolate) LocationSummary(
5135 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); 5128 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
5136 result->set_in(0, Location::WritableRegister()); 5129 result->set_in(0, Location::RequiresRegister());
5137 result->set_out(0, Location::RequiresFpuRegister()); 5130 result->set_out(0, Location::RequiresFpuRegister());
5138 return result; 5131 return result;
5139 } 5132 }
5140 5133
5141 5134
5142 void SmiToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5135 void SmiToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5143 const Register value = locs()->in(0).reg(); 5136 const Register value = locs()->in(0).reg();
5144 const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg()); 5137 const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg());
5145 __ SmiUntag(value); 5138 __ SmiUntag(IP, value);
5146 __ vmovsr(STMP, value); 5139 __ vmovsr(STMP, IP);
5147 __ vcvtdi(result, STMP); 5140 __ vcvtdi(result, STMP);
5148 } 5141 }
5149 5142
5150 5143
5151 LocationSummary* DoubleToIntegerInstr::MakeLocationSummary(Isolate* isolate, 5144 LocationSummary* DoubleToIntegerInstr::MakeLocationSummary(Isolate* isolate,
5152 bool opt) const { 5145 bool opt) const {
5153 const intptr_t kNumInputs = 1; 5146 const intptr_t kNumInputs = 1;
5154 const intptr_t kNumTemps = 0; 5147 const intptr_t kNumTemps = 0;
5155 LocationSummary* result = new(isolate) LocationSummary( 5148 LocationSummary* result = new(isolate) LocationSummary(
5156 isolate, kNumInputs, kNumTemps, LocationSummary::kCall); 5149 isolate, kNumInputs, kNumTemps, LocationSummary::kCall);
(...skipping 398 matching lines...) Expand 10 before | Expand all | Expand 10 after
5555 const Register result_mod = pair->At(1).reg(); 5548 const Register result_mod = pair->At(1).reg();
5556 Range* right_range = InputAt(1)->definition()->range(); 5549 Range* right_range = InputAt(1)->definition()->range();
5557 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { 5550 if ((right_range == NULL) || right_range->Overlaps(0, 0)) {
5558 // Handle divide by zero in runtime. 5551 // Handle divide by zero in runtime.
5559 __ cmp(right, Operand(0)); 5552 __ cmp(right, Operand(0));
5560 __ b(deopt, EQ); 5553 __ b(deopt, EQ);
5561 } 5554 }
5562 const Register temp = locs()->temp(0).reg(); 5555 const Register temp = locs()->temp(0).reg();
5563 const DRegister dtemp = EvenDRegisterOf(locs()->temp(1).fpu_reg()); 5556 const DRegister dtemp = EvenDRegisterOf(locs()->temp(1).fpu_reg());
5564 5557
5565 __ Asr(temp, left, kSmiTagSize); // SmiUntag left into temp. 5558 __ SmiUntag(temp, left);
5566 __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP. 5559 __ SmiUntag(IP, right);
5567 5560
5568 __ IntegerDivide(result_div, temp, IP, dtemp, DTMP); 5561 __ IntegerDivide(result_div, temp, IP, dtemp, DTMP);
5569 5562
5570 // Check the corner case of dividing the 'MIN_SMI' with -1, in which 5563 // Check the corner case of dividing the 'MIN_SMI' with -1, in which
5571 // case we cannot tag the result. 5564 // case we cannot tag the result.
5572 __ CompareImmediate(result_div, 0x40000000); 5565 __ CompareImmediate(result_div, 0x40000000);
5573 __ b(deopt, EQ); 5566 __ b(deopt, EQ);
5574 __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP. 5567 __ SmiUntag(IP, right);
5575 // result_mod <- left - right * result_div. 5568 // result_mod <- left - right * result_div.
5576 __ mls(result_mod, IP, result_div, temp); 5569 __ mls(result_mod, IP, result_div, temp);
5577 __ SmiTag(result_div); 5570 __ SmiTag(result_div);
5578 __ SmiTag(result_mod); 5571 __ SmiTag(result_mod);
5579 // Correct MOD result: 5572 // Correct MOD result:
5580 // res = left % right; 5573 // res = left % right;
5581 // if (res < 0) { 5574 // if (res < 0) {
5582 // if (right < 0) { 5575 // if (right < 0) {
5583 // res = res - right; 5576 // res = res - right;
5584 // } else { 5577 // } else {
(...skipping 817 matching lines...) Expand 10 before | Expand all | Expand 10 after
6402 compiler->GenerateCall(token_pos(), 6395 compiler->GenerateCall(token_pos(),
6403 &label, 6396 &label,
6404 PcDescriptors::kOther, 6397 PcDescriptors::kOther,
6405 locs()); 6398 locs());
6406 __ Drop(ArgumentCount()); // Discard arguments. 6399 __ Drop(ArgumentCount()); // Discard arguments.
6407 } 6400 }
6408 6401
6409 } // namespace dart 6402 } // namespace dart
6410 6403
6411 #endif // defined TARGET_ARCH_ARM 6404 #endif // defined TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « runtime/vm/disassembler_arm64.cc ('k') | runtime/vm/intermediate_language_arm64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698