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

Side by Side Diff: runtime/vm/intermediate_language_ia32.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
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_IA32. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32.
6 #if defined(TARGET_ARCH_IA32) 6 #if defined(TARGET_ARCH_IA32)
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 2188 matching lines...) Expand 10 before | Expand all | Expand 10 after
2199 summary->set_out(Location::SameAsFirstInput()); 2199 summary->set_out(Location::SameAsFirstInput());
2200 } else { 2200 } else {
2201 // Both inputs must be writable because they will be untagged. 2201 // Both inputs must be writable because they will be untagged.
2202 summary->set_in(0, Location::RegisterLocation(EAX)); 2202 summary->set_in(0, Location::RegisterLocation(EAX));
2203 summary->set_in(1, Location::WritableRegister()); 2203 summary->set_in(1, Location::WritableRegister());
2204 summary->set_out(Location::SameAsFirstInput()); 2204 summary->set_out(Location::SameAsFirstInput());
2205 // Will be used for sign extension and division. 2205 // Will be used for sign extension and division.
2206 summary->set_temp(0, Location::RegisterLocation(EDX)); 2206 summary->set_temp(0, Location::RegisterLocation(EDX));
2207 } 2207 }
2208 return summary; 2208 return summary;
2209 } else if (op_kind() == Token::kMOD) {
2210 const intptr_t kNumTemps = 1;
2211 LocationSummary* summary =
2212 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
2213 // Both inputs must be writable because they will be untagged.
2214 summary->set_in(0, Location::RegisterLocation(EDX));
2215 summary->set_in(1, Location::WritableRegister());
2216 summary->set_out(Location::SameAsFirstInput());
2217 // Will be used for sign extension and division.
2218 summary->set_temp(0, Location::RegisterLocation(EAX));
2219 return summary;
2209 } else if (op_kind() == Token::kSHR) { 2220 } else if (op_kind() == Token::kSHR) {
2210 const intptr_t kNumTemps = 0; 2221 const intptr_t kNumTemps = 0;
2211 LocationSummary* summary = 2222 LocationSummary* summary =
2212 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 2223 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
2213 summary->set_in(0, Location::RequiresRegister()); 2224 summary->set_in(0, Location::RequiresRegister());
2214 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), ECX)); 2225 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), ECX));
2215 summary->set_out(Location::SameAsFirstInput()); 2226 summary->set_out(Location::SameAsFirstInput());
2216 return summary; 2227 return summary;
2217 } else if (op_kind() == Token::kSHL) { 2228 } else if (op_kind() == Token::kSHL) {
2218 const intptr_t kNumTemps = 0; 2229 const intptr_t kNumTemps = 0;
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after
2444 __ SmiUntag(right); 2455 __ SmiUntag(right);
2445 __ cdq(); // Sign extend EAX -> EDX:EAX. 2456 __ cdq(); // Sign extend EAX -> EDX:EAX.
2446 __ idivl(right); // EAX: quotient, EDX: remainder. 2457 __ idivl(right); // EAX: quotient, EDX: remainder.
2447 // Check the corner case of dividing the 'MIN_SMI' with -1, in which 2458 // Check the corner case of dividing the 'MIN_SMI' with -1, in which
2448 // case we cannot tag the result. 2459 // case we cannot tag the result.
2449 __ cmpl(result, Immediate(0x40000000)); 2460 __ cmpl(result, Immediate(0x40000000));
2450 __ j(EQUAL, deopt); 2461 __ j(EQUAL, deopt);
2451 __ SmiTag(result); 2462 __ SmiTag(result);
2452 break; 2463 break;
2453 } 2464 }
2465 case Token::kMOD: {
2466 // Handle divide by zero in runtime.
2467 __ testl(right, right);
2468 __ j(ZERO, deopt);
sra1 2013/11/07 00:50:23 This should be unnecessary in cases where right ==
srdjan 2013/11/07 05:26:52 Yes. I had the code in and have removed it in orde
sra1 2013/11/08 01:40:16 I see. The latency of idiv covers everything else
srdjan 2013/11/08 16:02:53 Yes, preliminary measurement show a big benefit of
2469 ASSERT(left == EDX);
2470 ASSERT((right != EDX) && (right != EAX));
2471 ASSERT(locs()->temp(0).reg() == EAX);
2472 ASSERT(result == EDX);
2473 __ SmiUntag(left);
2474 __ SmiUntag(right);
2475 __ movl(EAX, EDX);
2476 __ cdq(); // Sign extend EAX -> EDX:EAX.
2477 __ idivl(right); // EAX: quotient, EDX: remainder.
2478 // res = left % right;
2479 // if (res < 0) {
2480 // if (right < 0) {
2481 // res = res - right;
2482 // } else {
2483 // res = res + right;
2484 // }
2485 // }
2486 Label subtract, done;
2487 __ cmpl(result, Immediate(0));
2488 __ j(GREATER_EQUAL, &done, Assembler::kNearJump);
sra1 2013/11/07 00:50:23 You might be able to test whether this is necessar
srdjan 2013/11/07 05:26:52 Ditto. I have not used the val range, but the rang
2489 // Result is negative, adjust it.
2490 __ cmpl(right, Immediate(0));
2491 __ j(LESS, &subtract, Assembler::kNearJump);
2492 __ addl(result, right);
2493 __ jmp(&done, Assembler::kNearJump);
2494 __ Bind(&subtract);
2495 __ subl(result, right);
2496 __ Bind(&done);
2497 __ SmiTag(result);
2498 break;
2499 }
2454 case Token::kSHR: { 2500 case Token::kSHR: {
2455 if (CanDeoptimize()) { 2501 if (CanDeoptimize()) {
2456 __ cmpl(right, Immediate(0)); 2502 __ cmpl(right, Immediate(0));
2457 __ j(LESS, deopt); 2503 __ j(LESS, deopt);
2458 } 2504 }
2459 __ SmiUntag(right); 2505 __ SmiUntag(right);
2460 // sarl operation masks the count to 5 bits. 2506 // sarl operation masks the count to 5 bits.
2461 const intptr_t kCountLimit = 0x1F; 2507 const intptr_t kCountLimit = 0x1F;
2462 Range* right_range = this->right()->definition()->range(); 2508 Range* right_range = this->right()->definition()->range();
2463 if ((right_range == NULL) || 2509 if ((right_range == NULL) ||
2464 !right_range->IsWithin(RangeBoundary::kMinusInfinity, kCountLimit)) { 2510 !right_range->IsWithin(RangeBoundary::kMinusInfinity, kCountLimit)) {
2465 __ cmpl(right, Immediate(kCountLimit)); 2511 __ cmpl(right, Immediate(kCountLimit));
2466 Label count_ok; 2512 Label count_ok;
2467 __ j(LESS, &count_ok, Assembler::kNearJump); 2513 __ j(LESS, &count_ok, Assembler::kNearJump);
2468 __ movl(right, Immediate(kCountLimit)); 2514 __ movl(right, Immediate(kCountLimit));
2469 __ Bind(&count_ok); 2515 __ Bind(&count_ok);
2470 } 2516 }
2471 ASSERT(right == ECX); // Count must be in ECX 2517 ASSERT(right == ECX); // Count must be in ECX
2472 __ SmiUntag(left); 2518 __ SmiUntag(left);
2473 __ sarl(left, right); 2519 __ sarl(left, right);
2474 __ SmiTag(left); 2520 __ SmiTag(left);
2475 break; 2521 break;
2476 } 2522 }
2477 case Token::kDIV: { 2523 case Token::kDIV: {
2478 // Dispatches to 'Double./'. 2524 // Dispatches to 'Double./'.
2479 // TODO(srdjan): Implement as conversion to double and double division. 2525 // TODO(srdjan): Implement as conversion to double and double division.
2480 UNREACHABLE(); 2526 UNREACHABLE();
2481 break; 2527 break;
2482 } 2528 }
2483 case Token::kMOD: {
2484 // TODO(srdjan): Implement.
2485 UNREACHABLE();
2486 break;
2487 }
2488 case Token::kOR: 2529 case Token::kOR:
2489 case Token::kAND: { 2530 case Token::kAND: {
2490 // Flow graph builder has dissected this operation to guarantee correct 2531 // Flow graph builder has dissected this operation to guarantee correct
2491 // behavior (short-circuit evaluation). 2532 // behavior (short-circuit evaluation).
2492 UNREACHABLE(); 2533 UNREACHABLE();
2493 break; 2534 break;
2494 } 2535 }
2495 default: 2536 default:
2496 UNREACHABLE(); 2537 UNREACHABLE();
2497 break; 2538 break;
(...skipping 2423 matching lines...) Expand 10 before | Expand all | Expand 10 after
4921 PcDescriptors::kOther, 4962 PcDescriptors::kOther,
4922 locs()); 4963 locs());
4923 __ Drop(2); // Discard type arguments and receiver. 4964 __ Drop(2); // Discard type arguments and receiver.
4924 } 4965 }
4925 4966
4926 } // namespace dart 4967 } // namespace dart
4927 4968
4928 #undef __ 4969 #undef __
4929 4970
4930 #endif // defined TARGET_ARCH_IA32 4971 #endif // defined TARGET_ARCH_IA32
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698