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

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
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 2373 matching lines...) Expand 10 before | Expand all | Expand 10 after
2384 break; 2384 break;
2385 } 2385 }
2386 if (FLAG_throw_on_javascript_int_overflow) { 2386 if (FLAG_throw_on_javascript_int_overflow) {
2387 EmitJavascriptOverflowCheck(compiler, range(), deopt, result); 2387 EmitJavascriptOverflowCheck(compiler, range(), deopt, result);
2388 } 2388 }
2389 return; 2389 return;
2390 } // locs()->in(1).IsStackSlot(). 2390 } // locs()->in(1).IsStackSlot().
2391 2391
2392 // if locs()->in(1).IsRegister. 2392 // if locs()->in(1).IsRegister.
2393 Register right = locs()->in(1).reg(); 2393 Register right = locs()->in(1).reg();
2394 Range* right_range = this->right()->definition()->range();
2394 switch (op_kind()) { 2395 switch (op_kind()) {
2395 case Token::kADD: { 2396 case Token::kADD: {
2396 __ addq(left, right); 2397 __ addq(left, right);
2397 if (deopt != NULL) __ j(OVERFLOW, deopt); 2398 if (deopt != NULL) __ j(OVERFLOW, deopt);
2398 break; 2399 break;
2399 } 2400 }
2400 case Token::kSUB: { 2401 case Token::kSUB: {
2401 __ subq(left, right); 2402 __ subq(left, right);
2402 if (deopt != NULL) __ j(OVERFLOW, deopt); 2403 if (deopt != NULL) __ j(OVERFLOW, deopt);
2403 break; 2404 break;
(...skipping 20 matching lines...) Expand all
2424 break; 2425 break;
2425 } 2426 }
2426 case Token::kTRUNCDIV: { 2427 case Token::kTRUNCDIV: {
2427 Label not_32bit, done; 2428 Label not_32bit, done;
2428 2429
2429 Register temp = locs()->temp(0).reg(); 2430 Register temp = locs()->temp(0).reg();
2430 ASSERT(left == RAX); 2431 ASSERT(left == RAX);
2431 ASSERT((right != RDX) && (right != RAX)); 2432 ASSERT((right != RDX) && (right != RAX));
2432 ASSERT(temp == RDX); 2433 ASSERT(temp == RDX);
2433 ASSERT(result == RAX); 2434 ASSERT(result == RAX);
2434 2435 if ((right_range == NULL) || right_range->IsWithin(0, 0)) {
2435 // Handle divide by zero in runtime. 2436 // Handle divide by zero in runtime.
2436 __ testq(right, right); 2437 __ testq(right, right);
2437 __ j(ZERO, deopt); 2438 __ j(ZERO, deopt);
2438 2439 }
2439 // Check if both operands fit into 32bits as idiv with 64bit operands 2440 // Check if both operands fit into 32bits as idiv with 64bit operands
2440 // requires twice as many cycles and has much higher latency. 2441 // requires twice as many cycles and has much higher latency.
2441 // We are checking this before untagging them to avoid corner case 2442 // We are checking this before untagging them to avoid corner case
2442 // dividing INT_MAX by -1 that raises exception because quotient is 2443 // dividing INT_MAX by -1 that raises exception because quotient is
2443 // too large for 32bit register. 2444 // too large for 32bit register.
2444 __ movsxd(temp, left); 2445 __ movsxd(temp, left);
2445 __ cmpq(temp, left); 2446 __ cmpq(temp, left);
2446 __ j(NOT_EQUAL, &not_32bit); 2447 __ j(NOT_EQUAL, &not_32bit);
2447 __ movsxd(temp, right); 2448 __ movsxd(temp, right);
2448 __ cmpq(temp, right); 2449 __ cmpq(temp, right);
(...skipping 22 matching lines...) Expand all
2471 break; 2472 break;
2472 } 2473 }
2473 case Token::kMOD: { 2474 case Token::kMOD: {
2474 Label not_32bit, div_done; 2475 Label not_32bit, div_done;
2475 2476
2476 Register temp = locs()->temp(0).reg(); 2477 Register temp = locs()->temp(0).reg();
2477 ASSERT(left == RDX); 2478 ASSERT(left == RDX);
2478 ASSERT((right != RDX) && (right != RAX)); 2479 ASSERT((right != RDX) && (right != RAX));
2479 ASSERT(temp == RAX); 2480 ASSERT(temp == RAX);
2480 ASSERT(result == RDX); 2481 ASSERT(result == RDX);
2481 // Handle divide by zero in runtime. 2482 if ((right_range == NULL) || right_range->IsWithin(0, 0)) {
2482 __ testq(right, right); 2483 // Handle divide by zero in runtime.
2483 __ j(ZERO, deopt); 2484 __ testq(right, right);
2485 __ j(ZERO, deopt);
2486 }
2484 // Check if both operands fit into 32bits as idiv with 64bit operands 2487 // Check if both operands fit into 32bits as idiv with 64bit operands
2485 // requires twice as many cycles and has much higher latency. 2488 // requires twice as many cycles and has much higher latency.
2486 // We are checking this before untagging them to avoid corner case 2489 // We are checking this before untagging them to avoid corner case
2487 // dividing INT_MAX by -1 that raises exception because quotient is 2490 // dividing INT_MAX by -1 that raises exception because quotient is
2488 // too large for 32bit register. 2491 // too large for 32bit register.
2489 __ movsxd(temp, left); 2492 __ movsxd(temp, left);
2490 __ cmpq(temp, left); 2493 __ cmpq(temp, left);
2491 __ j(NOT_EQUAL, &not_32bit); 2494 __ j(NOT_EQUAL, &not_32bit);
2492 __ movsxd(temp, right); 2495 __ movsxd(temp, right);
2493 __ cmpq(temp, right); 2496 __ cmpq(temp, right);
(...skipping 16 matching lines...) Expand all
2510 __ idivq(right); // RAX: quotient, RDX: remainder. 2513 __ idivq(right); // RAX: quotient, RDX: remainder.
2511 __ Bind(&div_done); 2514 __ Bind(&div_done);
2512 // res = left % right; 2515 // res = left % right;
2513 // if (res < 0) { 2516 // if (res < 0) {
2514 // if (right < 0) { 2517 // if (right < 0) {
2515 // res = res - right; 2518 // res = res - right;
2516 // } else { 2519 // } else {
2517 // res = res + right; 2520 // res = res + right;
2518 // } 2521 // }
2519 // } 2522 // }
2520 Label subtract, all_done; 2523 Label all_done;
2521 __ cmpq(result, Immediate(0)); 2524 __ cmpq(result, Immediate(0));
2522 __ j(GREATER_EQUAL, &all_done, Assembler::kNearJump); 2525 __ j(GREATER_EQUAL, &all_done, Assembler::kNearJump);
2523 // Result is negative, adjust it. 2526 // Result is negative, adjust it.
2524 __ cmpq(right, Immediate(0)); 2527 if ((right_range == NULL) || right_range->IsWithin(-1, 1)) {
2525 __ j(LESS, &subtract, Assembler::kNearJump); 2528 Label subtract;
2526 __ addq(result, right); 2529 __ cmpq(right, Immediate(0));
2527 __ jmp(&all_done, Assembler::kNearJump); 2530 __ j(LESS, &subtract, Assembler::kNearJump);
2528 __ Bind(&subtract); 2531 __ addq(result, right);
2529 __ subq(result, right); 2532 __ jmp(&all_done, Assembler::kNearJump);
2533 __ Bind(&subtract);
2534 __ subq(result, right);
2535 } else if (right_range->IsWithin(0, RangeBoundary::kPlusInfinity)) {
2536 // Right is positive.
2537 __ addq(result, right);
2538 } else {
2539 // Right is negative.
2540 __ subq(result, right);
2541 }
2530 __ Bind(&all_done); 2542 __ Bind(&all_done);
2531 __ SmiTag(result); 2543 __ SmiTag(result);
2532 break; 2544 break;
2533 } 2545 }
2534 case Token::kSHR: { 2546 case Token::kSHR: {
2535 if (CanDeoptimize()) { 2547 if (CanDeoptimize()) {
2536 __ CompareImmediate(right, Immediate(0), PP); 2548 __ CompareImmediate(right, Immediate(0), PP);
2537 __ j(LESS, deopt); 2549 __ j(LESS, deopt);
2538 } 2550 }
2539 __ SmiUntag(right); 2551 __ SmiUntag(right);
2540 // sarq operation masks the count to 6 bits. 2552 // sarq operation masks the count to 6 bits.
2541 const intptr_t kCountLimit = 0x3F; 2553 const intptr_t kCountLimit = 0x3F;
2542 Range* right_range = this->right()->definition()->range();
2543 if ((right_range == NULL) || 2554 if ((right_range == NULL) ||
2544 !right_range->IsWithin(RangeBoundary::kMinusInfinity, kCountLimit)) { 2555 !right_range->IsWithin(RangeBoundary::kMinusInfinity, kCountLimit)) {
2545 __ CompareImmediate(right, Immediate(kCountLimit), PP); 2556 __ CompareImmediate(right, Immediate(kCountLimit), PP);
2546 Label count_ok; 2557 Label count_ok;
2547 __ j(LESS, &count_ok, Assembler::kNearJump); 2558 __ j(LESS, &count_ok, Assembler::kNearJump);
2548 __ LoadImmediate(right, Immediate(kCountLimit), PP); 2559 __ LoadImmediate(right, Immediate(kCountLimit), PP);
2549 __ Bind(&count_ok); 2560 __ Bind(&count_ok);
2550 } 2561 }
2551 ASSERT(right == RCX); // Count must be in RCX 2562 ASSERT(right == RCX); // Count must be in RCX
2552 __ SmiUntag(left); 2563 __ SmiUntag(left);
(...skipping 1516 matching lines...) Expand 10 before | Expand all | Expand 10 after
4069 if (kind() == MergedMathInstr::kTruncDivMod) { 4080 if (kind() == MergedMathInstr::kTruncDivMod) {
4070 Register left = locs()->in(0).reg(); 4081 Register left = locs()->in(0).reg();
4071 Register right = locs()->in(1).reg(); 4082 Register right = locs()->in(1).reg();
4072 Register result = locs()->out().reg(); 4083 Register result = locs()->out().reg();
4073 Label not_32bit, done; 4084 Label not_32bit, done;
4074 Register temp = locs()->temp(0).reg(); 4085 Register temp = locs()->temp(0).reg();
4075 ASSERT(left == RAX); 4086 ASSERT(left == RAX);
4076 ASSERT((right != RDX) && (right != RAX)); 4087 ASSERT((right != RDX) && (right != RAX));
4077 ASSERT(temp == RDX); 4088 ASSERT(temp == RDX);
4078 ASSERT((result != RDX) && (result != RAX)); 4089 ASSERT((result != RDX) && (result != RAX));
4079 // Handle divide by zero in runtime. 4090
4080 __ testq(right, right); 4091 Range* right_range = InputAt(1)->definition()->range();
4081 __ j(ZERO, deopt); 4092 if ((right_range == NULL) || right_range->IsWithin(0, 0)) {
4093 // Handle divide by zero in runtime.
4094 __ testq(right, right);
4095 __ j(ZERO, deopt);
4096 }
4082 // Check if both operands fit into 32bits as idiv with 64bit operands 4097 // Check if both operands fit into 32bits as idiv with 64bit operands
4083 // requires twice as many cycles and has much higher latency. 4098 // requires twice as many cycles and has much higher latency.
4084 // We are checking this before untagging them to avoid corner case 4099 // We are checking this before untagging them to avoid corner case
4085 // dividing INT_MAX by -1 that raises exception because quotient is 4100 // dividing INT_MAX by -1 that raises exception because quotient is
4086 // too large for 32bit register. 4101 // too large for 32bit register.
4087 __ movsxd(temp, left); 4102 __ movsxd(temp, left);
4088 __ cmpq(temp, left); 4103 __ cmpq(temp, left);
4089 __ j(NOT_EQUAL, &not_32bit); 4104 __ j(NOT_EQUAL, &not_32bit);
4090 __ movsxd(temp, right); 4105 __ movsxd(temp, right);
4091 __ cmpq(temp, right); 4106 __ cmpq(temp, right);
(...skipping 22 matching lines...) Expand all
4114 4129
4115 // Modulo correction (RDX). 4130 // Modulo correction (RDX).
4116 // res = left % right; 4131 // res = left % right;
4117 // if (res < 0) { 4132 // if (res < 0) {
4118 // if (right < 0) { 4133 // if (right < 0) {
4119 // res = res - right; 4134 // res = res - right;
4120 // } else { 4135 // } else {
4121 // res = res + right; 4136 // res = res + right;
4122 // } 4137 // }
4123 // } 4138 // }
4124 Label subtract, all_done; 4139 Label all_done;
4125 __ cmpq(RDX, Immediate(0)); 4140 __ cmpq(RDX, Immediate(0));
4126 __ j(GREATER_EQUAL, &all_done, Assembler::kNearJump); 4141 __ j(GREATER_EQUAL, &all_done, Assembler::kNearJump);
4127 // Result is negative, adjust it. 4142 // Result is negative, adjust it.
4128 __ cmpq(right, Immediate(0)); 4143 if ((right_range == NULL) || right_range->IsWithin(-1, 1)) {
4129 __ j(LESS, &subtract, Assembler::kNearJump); 4144 Label subtract;
4130 __ addq(RDX, right); 4145 __ cmpq(right, Immediate(0));
4131 __ jmp(&all_done, Assembler::kNearJump); 4146 __ j(LESS, &subtract, Assembler::kNearJump);
4132 __ Bind(&subtract); 4147 __ addq(RDX, right);
4133 __ subq(RDX, right); 4148 __ jmp(&all_done, Assembler::kNearJump);
4149 __ Bind(&subtract);
4150 __ subq(RDX, right);
4151 } else if (right_range->IsWithin(0, RangeBoundary::kPlusInfinity)) {
4152 // Right is positive.
4153 __ addq(RDX, right);
4154 } else {
4155 // Right is negative.
4156 __ subq(RDX, right);
4157 }
4134 __ Bind(&all_done); 4158 __ Bind(&all_done);
4135 __ SmiTag(result); 4159 __ SmiTag(result);
4136 4160
4137 __ LoadObject(result, Array::ZoneHandle(Array::New(2, Heap::kOld)), PP); 4161 __ LoadObject(result, Array::ZoneHandle(Array::New(2, Heap::kOld)), PP);
4138 const intptr_t index_scale = FlowGraphCompiler::ElementSizeFor(kArrayCid); 4162 const intptr_t index_scale = FlowGraphCompiler::ElementSizeFor(kArrayCid);
4139 Address trunc_div_address( 4163 Address trunc_div_address(
4140 FlowGraphCompiler::ElementAddressForIntIndex(kArrayCid, 4164 FlowGraphCompiler::ElementAddressForIntIndex(kArrayCid,
4141 index_scale, 4165 index_scale,
4142 result, 4166 result,
4143 0)); 4167 0));
(...skipping 545 matching lines...) Expand 10 before | Expand all | Expand 10 after
4689 PcDescriptors::kOther, 4713 PcDescriptors::kOther,
4690 locs()); 4714 locs());
4691 __ Drop(2); // Discard type arguments and receiver. 4715 __ Drop(2); // Discard type arguments and receiver.
4692 } 4716 }
4693 4717
4694 } // namespace dart 4718 } // namespace dart
4695 4719
4696 #undef __ 4720 #undef __
4697 4721
4698 #endif // defined TARGET_ARCH_X64 4722 #endif // defined TARGET_ARCH_X64
OLDNEW
« runtime/vm/intermediate_language_ia32.cc ('K') | « runtime/vm/intermediate_language_mips.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698