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

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

Issue 61123003: Inline integer modulo operation. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 1 month 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/intermediate_language_mips.cc ('k') | no next file » | 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_X64. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64.
6 #if defined(TARGET_ARCH_X64) 6 #if defined(TARGET_ARCH_X64)
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 2184 matching lines...) Expand 10 before | Expand all | Expand 10 after
2195 2195
2196 2196
2197 LocationSummary* BinarySmiOpInstr::MakeLocationSummary() const { 2197 LocationSummary* BinarySmiOpInstr::MakeLocationSummary() const {
2198 const intptr_t kNumInputs = 2; 2198 const intptr_t kNumInputs = 2;
2199 2199
2200 ConstantInstr* right_constant = right()->definition()->AsConstant(); 2200 ConstantInstr* right_constant = right()->definition()->AsConstant();
2201 if ((right_constant != NULL) && 2201 if ((right_constant != NULL) &&
2202 (op_kind() != Token::kTRUNCDIV) && 2202 (op_kind() != Token::kTRUNCDIV) &&
2203 (op_kind() != Token::kSHL) && 2203 (op_kind() != Token::kSHL) &&
2204 (op_kind() != Token::kMUL) && 2204 (op_kind() != Token::kMUL) &&
2205 (op_kind() != Token::kMOD) &&
2205 CanBeImmediate(right_constant->value())) { 2206 CanBeImmediate(right_constant->value())) {
2206 const intptr_t kNumTemps = 0; 2207 const intptr_t kNumTemps = 0;
2207 LocationSummary* summary = 2208 LocationSummary* summary =
2208 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 2209 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
2209 summary->set_in(0, Location::RequiresRegister()); 2210 summary->set_in(0, Location::RequiresRegister());
2210 summary->set_in(1, Location::Constant(right_constant->value())); 2211 summary->set_in(1, Location::Constant(right_constant->value()));
2211 summary->set_out(Location::SameAsFirstInput()); 2212 summary->set_out(Location::SameAsFirstInput());
2212 return summary; 2213 return summary;
2213 } 2214 }
2214 2215
2215 if (op_kind() == Token::kTRUNCDIV) { 2216 if (op_kind() == Token::kTRUNCDIV) {
2216 const intptr_t kNumTemps = 1; 2217 const intptr_t kNumTemps = 1;
2217 LocationSummary* summary = 2218 LocationSummary* summary =
2218 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 2219 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
2219 if (RightIsPowerOfTwoConstant()) { 2220 if (RightIsPowerOfTwoConstant()) {
2220 summary->set_in(0, Location::RequiresRegister()); 2221 summary->set_in(0, Location::RequiresRegister());
2221 ConstantInstr* right_constant = right()->definition()->AsConstant(); 2222 ConstantInstr* right_constant = right()->definition()->AsConstant();
2222 summary->set_in(1, Location::Constant(right_constant->value())); 2223 summary->set_in(1, Location::Constant(right_constant->value()));
2223 summary->set_temp(0, Location::RequiresRegister()); 2224 summary->set_temp(0, Location::RequiresRegister());
2224 summary->set_out(Location::SameAsFirstInput()); 2225 summary->set_out(Location::SameAsFirstInput());
2225 } else { 2226 } else {
2226 // Both inputs must be writable because they will be untagged. 2227 // Both inputs must be writable because they will be untagged.
2227 summary->set_in(0, Location::RegisterLocation(RAX)); 2228 summary->set_in(0, Location::RegisterLocation(RAX));
2228 summary->set_in(1, Location::WritableRegister()); 2229 summary->set_in(1, Location::WritableRegister());
2229 summary->set_out(Location::SameAsFirstInput()); 2230 summary->set_out(Location::SameAsFirstInput());
2230 // Will be used for sign extension and division. 2231 // Will be used for sign extension and division.
2231 summary->set_temp(0, Location::RegisterLocation(RDX)); 2232 summary->set_temp(0, Location::RegisterLocation(RDX));
2232 } 2233 }
2233 return summary; 2234 return summary;
2235 } else if (op_kind() == Token::kMOD) {
2236 const intptr_t kNumTemps = 1;
2237 LocationSummary* summary =
2238 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
2239 // Both inputs must be writable because they will be untagged.
2240 summary->set_in(0, Location::RegisterLocation(RDX));
2241 summary->set_in(1, Location::WritableRegister());
2242 summary->set_out(Location::SameAsFirstInput());
2243 // Will be used for sign extension and division.
2244 summary->set_temp(0, Location::RegisterLocation(RAX));
2245 return summary;
2234 } else if (op_kind() == Token::kSHR) { 2246 } else if (op_kind() == Token::kSHR) {
2235 const intptr_t kNumTemps = 0; 2247 const intptr_t kNumTemps = 0;
2236 LocationSummary* summary = 2248 LocationSummary* summary =
2237 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 2249 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
2238 summary->set_in(0, Location::RequiresRegister()); 2250 summary->set_in(0, Location::RequiresRegister());
2239 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), RCX)); 2251 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), RCX));
2240 summary->set_out(Location::SameAsFirstInput()); 2252 summary->set_out(Location::SameAsFirstInput());
2241 return summary; 2253 return summary;
2242 } else if (op_kind() == Token::kSHL) { 2254 } else if (op_kind() == Token::kSHL) {
2243 const intptr_t kNumTemps = 0; 2255 const intptr_t kNumTemps = 0;
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after
2508 __ cqo(); // Sign extend RAX -> RDX:RAX. 2520 __ cqo(); // Sign extend RAX -> RDX:RAX.
2509 __ idivq(right); // RAX: quotient, RDX: remainder. 2521 __ idivq(right); // RAX: quotient, RDX: remainder.
2510 // Check the corner case of dividing the 'MIN_SMI' with -1, in which 2522 // Check the corner case of dividing the 'MIN_SMI' with -1, in which
2511 // case we cannot tag the result. 2523 // case we cannot tag the result.
2512 __ CompareImmediate(result, Immediate(0x4000000000000000), PP); 2524 __ CompareImmediate(result, Immediate(0x4000000000000000), PP);
2513 __ j(EQUAL, deopt); 2525 __ j(EQUAL, deopt);
2514 __ Bind(&done); 2526 __ Bind(&done);
2515 __ SmiTag(result); 2527 __ SmiTag(result);
2516 break; 2528 break;
2517 } 2529 }
2530 case Token::kMOD: {
2531 Label not_32bit, div_done;
2532
2533 Register temp = locs()->temp(0).reg();
2534 ASSERT(left == RDX);
2535 ASSERT((right != RDX) && (right != RAX));
2536 ASSERT(temp == RAX);
2537 ASSERT(result == RDX);
2538 // Handle divide by zero in runtime.
2539 __ testq(right, right);
2540 __ j(ZERO, deopt);
2541 // Check if both operands fit into 32bits as idiv with 64bit operands
2542 // requires twice as many cycles and has much higher latency.
2543 // We are checking this before untagging them to avoid corner case
2544 // dividing INT_MAX by -1 that raises exception because quotient is
2545 // too large for 32bit register.
2546 __ movsxd(temp, left);
2547 __ cmpq(temp, left);
2548 __ j(NOT_EQUAL, &not_32bit);
2549 __ movsxd(temp, right);
2550 __ cmpq(temp, right);
2551 __ j(NOT_EQUAL, &not_32bit);
2552 // Both operands are 31bit smis. Divide using 32bit idiv.
2553 __ SmiUntag(left);
2554 __ SmiUntag(right);
2555 __ movq(RAX, RDX);
2556 __ cdq();
2557 __ idivl(right);
2558 __ movsxd(result, result);
2559 __ jmp(&div_done);
2560
2561 // Divide using 64bit idiv.
2562 __ Bind(&not_32bit);
2563 __ SmiUntag(left);
2564 __ SmiUntag(right);
2565 __ movq(RAX, RDX);
2566 __ cqo(); // Sign extend RAX -> RDX:RAX.
2567 __ idivq(right); // RAX: quotient, RDX: remainder.
2568 __ Bind(&div_done);
2569 // res = left % right;
2570 // if (res < 0) {
2571 // if (right < 0) {
2572 // res = res - right;
2573 // } else {
2574 // res = res + right;
2575 // }
2576 // }
2577 Label subtract, all_done;
2578 __ cmpq(result, Immediate(0));
2579 __ j(GREATER_EQUAL, &all_done, Assembler::kNearJump);
2580 // Result is negative, adjust it.
2581 __ cmpq(right, Immediate(0));
2582 __ j(LESS, &subtract, Assembler::kNearJump);
2583 __ addq(result, right);
2584 __ jmp(&all_done, Assembler::kNearJump);
2585 __ Bind(&subtract);
2586 __ subq(result, right);
2587 __ Bind(&all_done);
2588 __ SmiTag(result);
2589 break;
2590 }
2518 case Token::kSHR: { 2591 case Token::kSHR: {
2519 if (CanDeoptimize()) { 2592 if (CanDeoptimize()) {
2520 __ CompareImmediate(right, Immediate(0), PP); 2593 __ CompareImmediate(right, Immediate(0), PP);
2521 __ j(LESS, deopt); 2594 __ j(LESS, deopt);
2522 } 2595 }
2523 __ SmiUntag(right); 2596 __ SmiUntag(right);
2524 // sarq operation masks the count to 6 bits. 2597 // sarq operation masks the count to 6 bits.
2525 const intptr_t kCountLimit = 0x3F; 2598 const intptr_t kCountLimit = 0x3F;
2526 Range* right_range = this->right()->definition()->range(); 2599 Range* right_range = this->right()->definition()->range();
2527 if ((right_range == NULL) || 2600 if ((right_range == NULL) ||
2528 !right_range->IsWithin(RangeBoundary::kMinusInfinity, kCountLimit)) { 2601 !right_range->IsWithin(RangeBoundary::kMinusInfinity, kCountLimit)) {
2529 __ CompareImmediate(right, Immediate(kCountLimit), PP); 2602 __ CompareImmediate(right, Immediate(kCountLimit), PP);
2530 Label count_ok; 2603 Label count_ok;
2531 __ j(LESS, &count_ok, Assembler::kNearJump); 2604 __ j(LESS, &count_ok, Assembler::kNearJump);
2532 __ LoadImmediate(right, Immediate(kCountLimit), PP); 2605 __ LoadImmediate(right, Immediate(kCountLimit), PP);
2533 __ Bind(&count_ok); 2606 __ Bind(&count_ok);
2534 } 2607 }
2535 ASSERT(right == RCX); // Count must be in RCX 2608 ASSERT(right == RCX); // Count must be in RCX
2536 __ SmiUntag(left); 2609 __ SmiUntag(left);
2537 __ sarq(left, right); 2610 __ sarq(left, right);
2538 __ SmiTag(left); 2611 __ SmiTag(left);
2539 break; 2612 break;
2540 } 2613 }
2541 case Token::kDIV: { 2614 case Token::kDIV: {
2542 // Dispatches to 'Double./'. 2615 // Dispatches to 'Double./'.
2543 // TODO(srdjan): Implement as conversion to double and double division. 2616 // TODO(srdjan): Implement as conversion to double and double division.
2544 UNREACHABLE(); 2617 UNREACHABLE();
2545 break; 2618 break;
2546 } 2619 }
2547 case Token::kMOD: {
2548 // TODO(srdjan): Implement.
2549 UNREACHABLE();
2550 break;
2551 }
2552 case Token::kOR: 2620 case Token::kOR:
2553 case Token::kAND: { 2621 case Token::kAND: {
2554 // Flow graph builder has dissected this operation to guarantee correct 2622 // Flow graph builder has dissected this operation to guarantee correct
2555 // behavior (short-circuit evaluation). 2623 // behavior (short-circuit evaluation).
2556 UNREACHABLE(); 2624 UNREACHABLE();
2557 break; 2625 break;
2558 } 2626 }
2559 default: 2627 default:
2560 UNREACHABLE(); 2628 UNREACHABLE();
2561 break; 2629 break;
(...skipping 2016 matching lines...) Expand 10 before | Expand all | Expand 10 after
4578 PcDescriptors::kOther, 4646 PcDescriptors::kOther,
4579 locs()); 4647 locs());
4580 __ Drop(2); // Discard type arguments and receiver. 4648 __ Drop(2); // Discard type arguments and receiver.
4581 } 4649 }
4582 4650
4583 } // namespace dart 4651 } // namespace dart
4584 4652
4585 #undef __ 4653 #undef __
4586 4654
4587 #endif // defined TARGET_ARCH_X64 4655 #endif // defined TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « runtime/vm/intermediate_language_mips.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698