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

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

Powered by Google App Engine
This is Rietveld 408576698