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

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

Issue 81623003: Use range information to omit checks in TRUNCDIV/MOD operations. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years 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_test.cc ('k') | tests/language/modulo_test.dart » ('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_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 2358 matching lines...) Expand 10 before | Expand all | Expand 10 after
2369 break; 2369 break;
2370 } 2370 }
2371 if (FLAG_throw_on_javascript_int_overflow) { 2371 if (FLAG_throw_on_javascript_int_overflow) {
2372 EmitJavascriptOverflowCheck(compiler, range(), deopt, result); 2372 EmitJavascriptOverflowCheck(compiler, range(), deopt, result);
2373 } 2373 }
2374 return; 2374 return;
2375 } // locs()->in(1).IsStackSlot(). 2375 } // locs()->in(1).IsStackSlot().
2376 2376
2377 // if locs()->in(1).IsRegister. 2377 // if locs()->in(1).IsRegister.
2378 Register right = locs()->in(1).reg(); 2378 Register right = locs()->in(1).reg();
2379 Range* right_range = this->right()->definition()->range();
2379 switch (op_kind()) { 2380 switch (op_kind()) {
2380 case Token::kADD: { 2381 case Token::kADD: {
2381 __ addq(left, right); 2382 __ addq(left, right);
2382 if (deopt != NULL) __ j(OVERFLOW, deopt); 2383 if (deopt != NULL) __ j(OVERFLOW, deopt);
2383 break; 2384 break;
2384 } 2385 }
2385 case Token::kSUB: { 2386 case Token::kSUB: {
2386 __ subq(left, right); 2387 __ subq(left, right);
2387 if (deopt != NULL) __ j(OVERFLOW, deopt); 2388 if (deopt != NULL) __ j(OVERFLOW, deopt);
2388 break; 2389 break;
(...skipping 20 matching lines...) Expand all
2409 break; 2410 break;
2410 } 2411 }
2411 case Token::kTRUNCDIV: { 2412 case Token::kTRUNCDIV: {
2412 Label not_32bit, done; 2413 Label not_32bit, done;
2413 2414
2414 Register temp = locs()->temp(0).reg(); 2415 Register temp = locs()->temp(0).reg();
2415 ASSERT(left == RAX); 2416 ASSERT(left == RAX);
2416 ASSERT((right != RDX) && (right != RAX)); 2417 ASSERT((right != RDX) && (right != RAX));
2417 ASSERT(temp == RDX); 2418 ASSERT(temp == RDX);
2418 ASSERT(result == RAX); 2419 ASSERT(result == RAX);
2419 2420 if ((right_range == NULL) || right_range->Overlaps(0, 0)) {
2420 // Handle divide by zero in runtime. 2421 // Handle divide by zero in runtime.
2421 __ testq(right, right); 2422 __ testq(right, right);
2422 __ j(ZERO, deopt); 2423 __ j(ZERO, deopt);
2423 2424 }
2424 // Check if both operands fit into 32bits as idiv with 64bit operands 2425 // Check if both operands fit into 32bits as idiv with 64bit operands
2425 // requires twice as many cycles and has much higher latency. 2426 // requires twice as many cycles and has much higher latency.
2426 // We are checking this before untagging them to avoid corner case 2427 // We are checking this before untagging them to avoid corner case
2427 // dividing INT_MAX by -1 that raises exception because quotient is 2428 // dividing INT_MAX by -1 that raises exception because quotient is
2428 // too large for 32bit register. 2429 // too large for 32bit register.
2429 __ movsxd(temp, left); 2430 __ movsxd(temp, left);
2430 __ cmpq(temp, left); 2431 __ cmpq(temp, left);
2431 __ j(NOT_EQUAL, &not_32bit); 2432 __ j(NOT_EQUAL, &not_32bit);
2432 __ movsxd(temp, right); 2433 __ movsxd(temp, right);
2433 __ cmpq(temp, right); 2434 __ cmpq(temp, right);
(...skipping 22 matching lines...) Expand all
2456 break; 2457 break;
2457 } 2458 }
2458 case Token::kMOD: { 2459 case Token::kMOD: {
2459 Label not_32bit, div_done; 2460 Label not_32bit, div_done;
2460 2461
2461 Register temp = locs()->temp(0).reg(); 2462 Register temp = locs()->temp(0).reg();
2462 ASSERT(left == RDX); 2463 ASSERT(left == RDX);
2463 ASSERT((right != RDX) && (right != RAX)); 2464 ASSERT((right != RDX) && (right != RAX));
2464 ASSERT(temp == RAX); 2465 ASSERT(temp == RAX);
2465 ASSERT(result == RDX); 2466 ASSERT(result == RDX);
2466 // Handle divide by zero in runtime. 2467 if ((right_range == NULL) || right_range->Overlaps(0, 0)) {
2467 __ testq(right, right); 2468 // Handle divide by zero in runtime.
2468 __ j(ZERO, deopt); 2469 __ testq(right, right);
2470 __ j(ZERO, deopt);
2471 }
2469 // Check if both operands fit into 32bits as idiv with 64bit operands 2472 // Check if both operands fit into 32bits as idiv with 64bit operands
2470 // requires twice as many cycles and has much higher latency. 2473 // requires twice as many cycles and has much higher latency.
2471 // We are checking this before untagging them to avoid corner case 2474 // We are checking this before untagging them to avoid corner case
2472 // dividing INT_MAX by -1 that raises exception because quotient is 2475 // dividing INT_MAX by -1 that raises exception because quotient is
2473 // too large for 32bit register. 2476 // too large for 32bit register.
2474 __ movsxd(temp, left); 2477 __ movsxd(temp, left);
2475 __ cmpq(temp, left); 2478 __ cmpq(temp, left);
2476 __ j(NOT_EQUAL, &not_32bit); 2479 __ j(NOT_EQUAL, &not_32bit);
2477 __ movsxd(temp, right); 2480 __ movsxd(temp, right);
2478 __ cmpq(temp, right); 2481 __ cmpq(temp, right);
(...skipping 16 matching lines...) Expand all
2495 __ idivq(right); // RAX: quotient, RDX: remainder. 2498 __ idivq(right); // RAX: quotient, RDX: remainder.
2496 __ Bind(&div_done); 2499 __ Bind(&div_done);
2497 // res = left % right; 2500 // res = left % right;
2498 // if (res < 0) { 2501 // if (res < 0) {
2499 // if (right < 0) { 2502 // if (right < 0) {
2500 // res = res - right; 2503 // res = res - right;
2501 // } else { 2504 // } else {
2502 // res = res + right; 2505 // res = res + right;
2503 // } 2506 // }
2504 // } 2507 // }
2505 Label subtract, all_done; 2508 Label all_done;
2506 __ cmpq(result, Immediate(0)); 2509 __ cmpq(result, Immediate(0));
2507 __ j(GREATER_EQUAL, &all_done, Assembler::kNearJump); 2510 __ j(GREATER_EQUAL, &all_done, Assembler::kNearJump);
2508 // Result is negative, adjust it. 2511 // Result is negative, adjust it.
2509 __ cmpq(right, Immediate(0)); 2512 if ((right_range == NULL) || right_range->Overlaps(-1, 1)) {
2510 __ j(LESS, &subtract, Assembler::kNearJump); 2513 Label subtract;
2511 __ addq(result, right); 2514 __ cmpq(right, Immediate(0));
2512 __ jmp(&all_done, Assembler::kNearJump); 2515 __ j(LESS, &subtract, Assembler::kNearJump);
2513 __ Bind(&subtract); 2516 __ addq(result, right);
2514 __ subq(result, right); 2517 __ jmp(&all_done, Assembler::kNearJump);
2518 __ Bind(&subtract);
2519 __ subq(result, right);
2520 } else if (right_range->IsWithin(0, RangeBoundary::kPlusInfinity)) {
2521 // Right is positive.
2522 __ addq(result, right);
2523 } else {
2524 // Right is negative.
2525 __ subq(result, right);
2526 }
2515 __ Bind(&all_done); 2527 __ Bind(&all_done);
2516 __ SmiTag(result); 2528 __ SmiTag(result);
2517 break; 2529 break;
2518 } 2530 }
2519 case Token::kSHR: { 2531 case Token::kSHR: {
2520 if (CanDeoptimize()) { 2532 if (CanDeoptimize()) {
2521 __ CompareImmediate(right, Immediate(0), PP); 2533 __ CompareImmediate(right, Immediate(0), PP);
2522 __ j(LESS, deopt); 2534 __ j(LESS, deopt);
2523 } 2535 }
2524 __ SmiUntag(right); 2536 __ SmiUntag(right);
2525 // sarq operation masks the count to 6 bits. 2537 // sarq operation masks the count to 6 bits.
2526 const intptr_t kCountLimit = 0x3F; 2538 const intptr_t kCountLimit = 0x3F;
2527 Range* right_range = this->right()->definition()->range();
2528 if ((right_range == NULL) || 2539 if ((right_range == NULL) ||
2529 !right_range->IsWithin(RangeBoundary::kMinusInfinity, kCountLimit)) { 2540 !right_range->IsWithin(RangeBoundary::kMinusInfinity, kCountLimit)) {
2530 __ CompareImmediate(right, Immediate(kCountLimit), PP); 2541 __ CompareImmediate(right, Immediate(kCountLimit), PP);
2531 Label count_ok; 2542 Label count_ok;
2532 __ j(LESS, &count_ok, Assembler::kNearJump); 2543 __ j(LESS, &count_ok, Assembler::kNearJump);
2533 __ LoadImmediate(right, Immediate(kCountLimit), PP); 2544 __ LoadImmediate(right, Immediate(kCountLimit), PP);
2534 __ Bind(&count_ok); 2545 __ Bind(&count_ok);
2535 } 2546 }
2536 ASSERT(right == RCX); // Count must be in RCX 2547 ASSERT(right == RCX); // Count must be in RCX
2537 __ SmiUntag(left); 2548 __ SmiUntag(left);
(...skipping 1516 matching lines...) Expand 10 before | Expand all | Expand 10 after
4054 if (kind() == MergedMathInstr::kTruncDivMod) { 4065 if (kind() == MergedMathInstr::kTruncDivMod) {
4055 Register left = locs()->in(0).reg(); 4066 Register left = locs()->in(0).reg();
4056 Register right = locs()->in(1).reg(); 4067 Register right = locs()->in(1).reg();
4057 Register result = locs()->out().reg(); 4068 Register result = locs()->out().reg();
4058 Label not_32bit, done; 4069 Label not_32bit, done;
4059 Register temp = locs()->temp(0).reg(); 4070 Register temp = locs()->temp(0).reg();
4060 ASSERT(left == RAX); 4071 ASSERT(left == RAX);
4061 ASSERT((right != RDX) && (right != RAX)); 4072 ASSERT((right != RDX) && (right != RAX));
4062 ASSERT(temp == RDX); 4073 ASSERT(temp == RDX);
4063 ASSERT((result != RDX) && (result != RAX)); 4074 ASSERT((result != RDX) && (result != RAX));
4064 // Handle divide by zero in runtime. 4075
4065 __ testq(right, right); 4076 Range* right_range = InputAt(1)->definition()->range();
4066 __ j(ZERO, deopt); 4077 if ((right_range == NULL) || right_range->Overlaps(0, 0)) {
4078 // Handle divide by zero in runtime.
4079 __ testq(right, right);
4080 __ j(ZERO, deopt);
4081 }
4067 // Check if both operands fit into 32bits as idiv with 64bit operands 4082 // Check if both operands fit into 32bits as idiv with 64bit operands
4068 // requires twice as many cycles and has much higher latency. 4083 // requires twice as many cycles and has much higher latency.
4069 // We are checking this before untagging them to avoid corner case 4084 // We are checking this before untagging them to avoid corner case
4070 // dividing INT_MAX by -1 that raises exception because quotient is 4085 // dividing INT_MAX by -1 that raises exception because quotient is
4071 // too large for 32bit register. 4086 // too large for 32bit register.
4072 __ movsxd(temp, left); 4087 __ movsxd(temp, left);
4073 __ cmpq(temp, left); 4088 __ cmpq(temp, left);
4074 __ j(NOT_EQUAL, &not_32bit); 4089 __ j(NOT_EQUAL, &not_32bit);
4075 __ movsxd(temp, right); 4090 __ movsxd(temp, right);
4076 __ cmpq(temp, right); 4091 __ cmpq(temp, right);
(...skipping 22 matching lines...) Expand all
4099 4114
4100 // Modulo correction (RDX). 4115 // Modulo correction (RDX).
4101 // res = left % right; 4116 // res = left % right;
4102 // if (res < 0) { 4117 // if (res < 0) {
4103 // if (right < 0) { 4118 // if (right < 0) {
4104 // res = res - right; 4119 // res = res - right;
4105 // } else { 4120 // } else {
4106 // res = res + right; 4121 // res = res + right;
4107 // } 4122 // }
4108 // } 4123 // }
4109 Label subtract, all_done; 4124 Label all_done;
4110 __ cmpq(RDX, Immediate(0)); 4125 __ cmpq(RDX, Immediate(0));
4111 __ j(GREATER_EQUAL, &all_done, Assembler::kNearJump); 4126 __ j(GREATER_EQUAL, &all_done, Assembler::kNearJump);
4112 // Result is negative, adjust it. 4127 // Result is negative, adjust it.
4113 __ cmpq(right, Immediate(0)); 4128 if ((right_range == NULL) || right_range->Overlaps(-1, 1)) {
4114 __ j(LESS, &subtract, Assembler::kNearJump); 4129 Label subtract;
4115 __ addq(RDX, right); 4130 __ cmpq(right, Immediate(0));
4116 __ jmp(&all_done, Assembler::kNearJump); 4131 __ j(LESS, &subtract, Assembler::kNearJump);
4117 __ Bind(&subtract); 4132 __ addq(RDX, right);
4118 __ subq(RDX, right); 4133 __ jmp(&all_done, Assembler::kNearJump);
4134 __ Bind(&subtract);
4135 __ subq(RDX, right);
4136 } else if (right_range->IsWithin(0, RangeBoundary::kPlusInfinity)) {
4137 // Right is positive.
4138 __ addq(RDX, right);
4139 } else {
4140 // Right is negative.
4141 __ subq(RDX, right);
4142 }
4119 __ Bind(&all_done); 4143 __ Bind(&all_done);
4120 __ SmiTag(result); 4144 __ SmiTag(result);
4121 4145
4122 __ LoadObject(result, Array::ZoneHandle(Array::New(2, Heap::kOld)), PP); 4146 __ LoadObject(result, Array::ZoneHandle(Array::New(2, Heap::kOld)), PP);
4123 const intptr_t index_scale = FlowGraphCompiler::ElementSizeFor(kArrayCid); 4147 const intptr_t index_scale = FlowGraphCompiler::ElementSizeFor(kArrayCid);
4124 Address trunc_div_address( 4148 Address trunc_div_address(
4125 FlowGraphCompiler::ElementAddressForIntIndex(kArrayCid, 4149 FlowGraphCompiler::ElementAddressForIntIndex(kArrayCid,
4126 index_scale, 4150 index_scale,
4127 result, 4151 result,
4128 0)); 4152 0));
(...skipping 540 matching lines...) Expand 10 before | Expand all | Expand 10 after
4669 PcDescriptors::kOther, 4693 PcDescriptors::kOther,
4670 locs()); 4694 locs());
4671 __ Drop(2); // Discard type arguments and receiver. 4695 __ Drop(2); // Discard type arguments and receiver.
4672 } 4696 }
4673 4697
4674 } // namespace dart 4698 } // namespace dart
4675 4699
4676 #undef __ 4700 #undef __
4677 4701
4678 #endif // defined TARGET_ARCH_X64 4702 #endif // defined TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « runtime/vm/intermediate_language_test.cc ('k') | tests/language/modulo_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698