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

Side by Side Diff: runtime/vm/intermediate_language_mips.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_ia32.cc ('k') | runtime/vm/intermediate_language_test.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_MIPS. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_MIPS.
6 #if defined(TARGET_ARCH_MIPS) 6 #if defined(TARGET_ARCH_MIPS)
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 2464 matching lines...) Expand 10 before | Expand all | Expand 10 after
2475 } 2475 }
2476 2476
2477 default: 2477 default:
2478 UNREACHABLE(); 2478 UNREACHABLE();
2479 break; 2479 break;
2480 } 2480 }
2481 return; 2481 return;
2482 } 2482 }
2483 2483
2484 Register right = locs()->in(1).reg(); 2484 Register right = locs()->in(1).reg();
2485 Range* right_range = this->right()->definition()->range();
2485 switch (op_kind()) { 2486 switch (op_kind()) {
2486 case Token::kADD: { 2487 case Token::kADD: {
2487 if (deopt == NULL) { 2488 if (deopt == NULL) {
2488 __ addu(result, left, right); 2489 __ addu(result, left, right);
2489 } else { 2490 } else {
2490 Register temp = locs()->temp(0).reg(); 2491 Register temp = locs()->temp(0).reg();
2491 __ AdduDetectOverflow(result, left, right, CMPRES1, temp); 2492 __ AdduDetectOverflow(result, left, right, CMPRES1, temp);
2492 __ bltz(CMPRES1, deopt); 2493 __ bltz(CMPRES1, deopt);
2493 } 2494 }
2494 break; 2495 break;
(...skipping 29 matching lines...) Expand all
2524 // No overflow check. 2525 // No overflow check.
2525 __ or_(result, left, right); 2526 __ or_(result, left, right);
2526 break; 2527 break;
2527 } 2528 }
2528 case Token::kBIT_XOR: { 2529 case Token::kBIT_XOR: {
2529 // No overflow check. 2530 // No overflow check.
2530 __ xor_(result, left, right); 2531 __ xor_(result, left, right);
2531 break; 2532 break;
2532 } 2533 }
2533 case Token::kTRUNCDIV: { 2534 case Token::kTRUNCDIV: {
2534 // Handle divide by zero in runtime. 2535 if ((right_range == NULL) || right_range->Overlaps(0, 0)) {
2535 __ beq(right, ZR, deopt); 2536 // Handle divide by zero in runtime.
2537 __ beq(right, ZR, deopt);
2538 }
2536 Register temp = locs()->temp(0).reg(); 2539 Register temp = locs()->temp(0).reg();
2537 __ sra(temp, left, kSmiTagSize); // SmiUntag left into temp. 2540 __ sra(temp, left, kSmiTagSize); // SmiUntag left into temp.
2538 __ sra(TMP, right, kSmiTagSize); // SmiUntag right into TMP. 2541 __ sra(TMP, right, kSmiTagSize); // SmiUntag right into TMP.
2539 __ div(temp, TMP); 2542 __ div(temp, TMP);
2540 __ mflo(result); 2543 __ mflo(result);
2541 // Check the corner case of dividing the 'MIN_SMI' with -1, in which 2544 // Check the corner case of dividing the 'MIN_SMI' with -1, in which
2542 // case we cannot tag the result. 2545 // case we cannot tag the result.
2543 __ BranchEqual(result, 0x40000000, deopt); 2546 __ BranchEqual(result, 0x40000000, deopt);
2544 __ SmiTag(result); 2547 __ SmiTag(result);
2545 break; 2548 break;
2546 } 2549 }
2547 case Token::kMOD: { 2550 case Token::kMOD: {
2548 // Handle divide by zero in runtime. 2551 if ((right_range == NULL) || right_range->Overlaps(0, 0)) {
2549 __ beq(right, ZR, deopt); 2552 // Handle divide by zero in runtime.
2553 __ beq(right, ZR, deopt);
2554 }
2550 Register temp = locs()->temp(0).reg(); 2555 Register temp = locs()->temp(0).reg();
2551 __ sra(temp, left, kSmiTagSize); // SmiUntag left into temp. 2556 __ sra(temp, left, kSmiTagSize); // SmiUntag left into temp.
2552 __ sra(TMP, right, kSmiTagSize); // SmiUntag right into TMP. 2557 __ sra(TMP, right, kSmiTagSize); // SmiUntag right into TMP.
2553 __ div(temp, TMP); 2558 __ div(temp, TMP);
2554 __ mfhi(result); 2559 __ mfhi(result);
2555 // res = left % right; 2560 // res = left % right;
2556 // if (res < 0) { 2561 // if (res < 0) {
2557 // if (right < 0) { 2562 // if (right < 0) {
2558 // res = res - right; 2563 // res = res - right;
2559 // } else { 2564 // } else {
2560 // res = res + right; 2565 // res = res + right;
2561 // } 2566 // }
2562 // } 2567 // }
2563 Label done, subtract; 2568 Label done;
2564 __ bgez(result, &done); 2569 __ bgez(result, &done);
2565 __ bltz(right, &subtract); 2570 if ((right_range == NULL) || right_range->Overlaps(-1, 1)) {
2566 __ addu(result, result, TMP); 2571 Label subtract;
2567 __ b(&done); 2572 __ bltz(right, &subtract);
2568 __ Bind(&subtract); 2573 __ addu(result, result, TMP);
2569 __ subu(result, result, TMP); 2574 __ b(&done);
2575 __ Bind(&subtract);
2576 __ subu(result, result, TMP);
2577 } else if (right_range->IsWithin(0, RangeBoundary::kPlusInfinity)) {
2578 // Right is positive.
2579 __ addu(result, result, TMP);
2580 } else {
2581 // Right is negative.
2582 __ subu(result, result, TMP);
2583 }
2570 __ Bind(&done); 2584 __ Bind(&done);
2571 __ SmiTag(result); 2585 __ SmiTag(result);
2572 break; 2586 break;
2573 } 2587 }
2574 case Token::kSHR: { 2588 case Token::kSHR: {
2575 Register temp = locs()->temp(0).reg(); 2589 Register temp = locs()->temp(0).reg();
2576 if (CanDeoptimize()) { 2590 if (CanDeoptimize()) {
2577 __ bltz(right, deopt); 2591 __ bltz(right, deopt);
2578 } 2592 }
2579 __ sra(temp, right, kSmiTagSize); // SmiUntag right into temp. 2593 __ sra(temp, right, kSmiTagSize); // SmiUntag right into temp.
2580 // sra operation masks the count to 5 bits. 2594 // sra operation masks the count to 5 bits.
2581 const intptr_t kCountLimit = 0x1F; 2595 const intptr_t kCountLimit = 0x1F;
2582 Range* right_range = this->right()->definition()->range();
2583 if ((right_range == NULL) || 2596 if ((right_range == NULL) ||
2584 !right_range->IsWithin(RangeBoundary::kMinusInfinity, kCountLimit)) { 2597 !right_range->IsWithin(RangeBoundary::kMinusInfinity, kCountLimit)) {
2585 Label ok; 2598 Label ok;
2586 __ BranchSignedLessEqual(temp, kCountLimit, &ok); 2599 __ BranchSignedLessEqual(temp, kCountLimit, &ok);
2587 __ LoadImmediate(temp, kCountLimit); 2600 __ LoadImmediate(temp, kCountLimit);
2588 __ Bind(&ok); 2601 __ Bind(&ok);
2589 } 2602 }
2590 2603
2591 __ sra(CMPRES1, left, kSmiTagSize); // SmiUntag left into CMPRES1. 2604 __ sra(CMPRES1, left, kSmiTagSize); // SmiUntag left into CMPRES1.
2592 __ srav(result, CMPRES1, temp); 2605 __ srav(result, CMPRES1, temp);
(...skipping 831 matching lines...) Expand 10 before | Expand all | Expand 10 after
3424 if (CanDeoptimize()) { 3437 if (CanDeoptimize()) {
3425 deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinarySmiOp); 3438 deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinarySmiOp);
3426 } 3439 }
3427 if (kind() == MergedMathInstr::kTruncDivMod) { 3440 if (kind() == MergedMathInstr::kTruncDivMod) {
3428 Register left = locs()->in(0).reg(); 3441 Register left = locs()->in(0).reg();
3429 Register right = locs()->in(1).reg(); 3442 Register right = locs()->in(1).reg();
3430 Register result = locs()->out().reg(); 3443 Register result = locs()->out().reg();
3431 Register temp = locs()->temp(0).reg(); 3444 Register temp = locs()->temp(0).reg();
3432 Register result_div = locs()->temp(1).reg(); 3445 Register result_div = locs()->temp(1).reg();
3433 Register result_mod = locs()->temp(2).reg(); 3446 Register result_mod = locs()->temp(2).reg();
3434 // Handle divide by zero in runtime. 3447 Range* right_range = InputAt(1)->definition()->range();
3435 __ beq(right, ZR, deopt); 3448 if ((right_range == NULL) || right_range->Overlaps(0, 0)) {
3449 // Handle divide by zero in runtime.
3450 __ beq(right, ZR, deopt);
3451 }
3436 __ sra(temp, left, kSmiTagSize); // SmiUntag left into temp. 3452 __ sra(temp, left, kSmiTagSize); // SmiUntag left into temp.
3437 __ sra(TMP, right, kSmiTagSize); // SmiUntag right into TMP. 3453 __ sra(TMP, right, kSmiTagSize); // SmiUntag right into TMP.
3438 __ div(temp, TMP); 3454 __ div(temp, TMP);
3439 __ mflo(result_div); 3455 __ mflo(result_div);
3440 __ mfhi(result_mod); 3456 __ mfhi(result_mod);
3441 // Check the corner case of dividing the 'MIN_SMI' with -1, in which 3457 // Check the corner case of dividing the 'MIN_SMI' with -1, in which
3442 // case we cannot tag the result. 3458 // case we cannot tag the result.
3443 __ BranchEqual(result_div, 0x40000000, deopt); 3459 __ BranchEqual(result_div, 0x40000000, deopt);
3444 // res = left % right; 3460 // res = left % right;
3445 // if (res < 0) { 3461 // if (res < 0) {
3446 // if (right < 0) { 3462 // if (right < 0) {
3447 // res = res - right; 3463 // res = res - right;
3448 // } else { 3464 // } else {
3449 // res = res + right; 3465 // res = res + right;
3450 // } 3466 // }
3451 // } 3467 // }
3452 Label done, subtract; 3468 Label done;
3453 __ bgez(result_mod, &done); 3469 __ bgez(result_mod, &done);
3454 __ bltz(right, &subtract); 3470 if ((right_range == NULL) || right_range->Overlaps(-1, 1)) {
3455 __ addu(result_mod, result_mod, TMP); 3471 Label subtract;
3456 __ b(&done); 3472 __ bltz(right, &subtract);
3457 __ Bind(&subtract); 3473 __ addu(result_mod, result_mod, TMP);
3458 __ subu(result_mod, result_mod, TMP); 3474 __ b(&done);
3475 __ Bind(&subtract);
3476 __ subu(result_mod, result_mod, TMP);
3477 } else if (right_range->IsWithin(0, RangeBoundary::kPlusInfinity)) {
3478 // Right is positive.
3479 __ addu(result_mod, result_mod, TMP);
3480 } else {
3481 // Right is negative.
3482 __ subu(result_mod, result_mod, TMP);
3483 }
3459 __ Bind(&done); 3484 __ Bind(&done);
3460 3485
3461 __ SmiTag(result_div); 3486 __ SmiTag(result_div);
3462 __ SmiTag(result_mod); 3487 __ SmiTag(result_mod);
3463 __ LoadObject(result, Array::ZoneHandle(Array::New(2, Heap::kOld))); 3488 __ LoadObject(result, Array::ZoneHandle(Array::New(2, Heap::kOld)));
3464 // Note that index is expected smi-tagged, (i.e, times 2) for all arrays. 3489 // Note that index is expected smi-tagged, (i.e, times 2) for all arrays.
3465 // [0]: divide resut, [1]: mod result. 3490 // [0]: divide resut, [1]: mod result.
3466 __ LoadImmediate(temp, 3491 __ LoadImmediate(temp,
3467 FlowGraphCompiler::DataOffsetFor(kArrayCid) - kHeapObjectTag); 3492 FlowGraphCompiler::DataOffsetFor(kArrayCid) - kHeapObjectTag);
3468 __ addu(temp, result, temp); 3493 __ addu(temp, result, temp);
(...skipping 500 matching lines...) Expand 10 before | Expand all | Expand 10 after
3969 compiler->GenerateCall(token_pos(), 3994 compiler->GenerateCall(token_pos(),
3970 &label, 3995 &label,
3971 PcDescriptors::kOther, 3996 PcDescriptors::kOther,
3972 locs()); 3997 locs());
3973 __ Drop(2); // Discard type arguments and receiver. 3998 __ Drop(2); // Discard type arguments and receiver.
3974 } 3999 }
3975 4000
3976 } // namespace dart 4001 } // namespace dart
3977 4002
3978 #endif // defined TARGET_ARCH_MIPS 4003 #endif // defined TARGET_ARCH_MIPS
OLDNEW
« no previous file with comments | « runtime/vm/intermediate_language_ia32.cc ('k') | runtime/vm/intermediate_language_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698