| Index: runtime/vm/intermediate_language_x64.cc
|
| diff --git a/runtime/vm/intermediate_language_x64.cc b/runtime/vm/intermediate_language_x64.cc
|
| index 930ace149f1a5932f7b5b079eedd06f45c075df2..1980d5502c0adee039e5f3615f6eaca42bee87dd 100644
|
| --- a/runtime/vm/intermediate_language_x64.cc
|
| +++ b/runtime/vm/intermediate_language_x64.cc
|
| @@ -2760,7 +2760,7 @@ static void EmitSmiShiftLeft(FlowGraphCompiler* compiler,
|
|
|
| // Right (locs.in(1)) is not constant.
|
| Register right = locs.in(1).reg();
|
| - Range* right_range = shift_left->right()->definition()->range();
|
| + Range* right_range = shift_left->right_range();
|
| if (shift_left->left()->BindsToConstant() && shift_left->can_overflow()) {
|
| // TODO(srdjan): Implement code below for is_truncating().
|
| // If left is constant, we know the maximal allowed size for right.
|
| @@ -3360,7 +3360,6 @@ void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|
|
| // if locs()->in(1).IsRegister.
|
| Register right = locs()->in(1).reg();
|
| - Range* right_range = this->right()->definition()->range();
|
| switch (op_kind()) {
|
| case Token::kADD: {
|
| __ addq(left, right);
|
| @@ -3401,7 +3400,7 @@ void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
| ASSERT((right != RDX) && (right != RAX));
|
| ASSERT(temp == RDX);
|
| ASSERT(result == RAX);
|
| - if ((right_range == NULL) || right_range->Overlaps(0, 0)) {
|
| + if (RangeUtils::CanBeZero(right_range())) {
|
| // Handle divide by zero in runtime.
|
| __ testq(right, right);
|
| __ j(ZERO, deopt);
|
| @@ -3448,7 +3447,7 @@ void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
| ASSERT((right != RDX) && (right != RAX));
|
| ASSERT(temp == RAX);
|
| ASSERT(result == RDX);
|
| - if ((right_range == NULL) || right_range->Overlaps(0, 0)) {
|
| + if (RangeUtils::CanBeZero(right_range())) {
|
| // Handle divide by zero in runtime.
|
| __ testq(right, right);
|
| __ j(ZERO, deopt);
|
| @@ -3493,7 +3492,7 @@ void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
| __ cmpq(result, Immediate(0));
|
| __ j(GREATER_EQUAL, &all_done, Assembler::kNearJump);
|
| // Result is negative, adjust it.
|
| - if ((right_range == NULL) || right_range->Overlaps(-1, 1)) {
|
| + if (RangeUtils::Overlaps(right_range(), -1, 1)) {
|
| Label subtract;
|
| __ cmpq(right, Immediate(0));
|
| __ j(LESS, &subtract, Assembler::kNearJump);
|
| @@ -3501,7 +3500,7 @@ void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
| __ jmp(&all_done, Assembler::kNearJump);
|
| __ Bind(&subtract);
|
| __ subq(result, right);
|
| - } else if (right_range->IsPositive()) {
|
| + } else if (right_range()->IsPositive()) {
|
| // Right is positive.
|
| __ addq(result, right);
|
| } else {
|
| @@ -3520,8 +3519,7 @@ void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
| __ SmiUntag(right);
|
| // sarq operation masks the count to 6 bits.
|
| const intptr_t kCountLimit = 0x3F;
|
| - if ((right_range == NULL) ||
|
| - !right_range->OnlyLessThanOrEqualTo(kCountLimit)) {
|
| + if (!RangeUtils::OnlyLessThanOrEqualTo(right_range(), kCountLimit)) {
|
| __ CompareImmediate(right, Immediate(kCountLimit));
|
| Label count_ok;
|
| __ j(LESS, &count_ok, Assembler::kNearJump);
|
| @@ -5668,119 +5666,108 @@ void ExtractNthOutputInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
| }
|
|
|
|
|
| -LocationSummary* MergedMathInstr::MakeLocationSummary(Zone* zone,
|
| - bool opt) const {
|
| - if (kind() == MergedMathInstr::kTruncDivMod) {
|
| - const intptr_t kNumInputs = 2;
|
| - const intptr_t kNumTemps = 0;
|
| - LocationSummary* summary = new (zone)
|
| - LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
|
| - // Both inputs must be writable because they will be untagged.
|
| - summary->set_in(0, Location::RegisterLocation(RAX));
|
| - summary->set_in(1, Location::WritableRegister());
|
| - summary->set_out(0, Location::Pair(Location::RegisterLocation(RAX),
|
| - Location::RegisterLocation(RDX)));
|
| - return summary;
|
| - }
|
| - UNIMPLEMENTED();
|
| - return NULL;
|
| +LocationSummary* TruncDivModInstr::MakeLocationSummary(Zone* zone,
|
| + bool opt) const {
|
| + const intptr_t kNumInputs = 2;
|
| + const intptr_t kNumTemps = 0;
|
| + LocationSummary* summary = new (zone)
|
| + LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
|
| + // Both inputs must be writable because they will be untagged.
|
| + summary->set_in(0, Location::RegisterLocation(RAX));
|
| + summary->set_in(1, Location::WritableRegister());
|
| + summary->set_out(0, Location::Pair(Location::RegisterLocation(RAX),
|
| + Location::RegisterLocation(RDX)));
|
| + return summary;
|
| }
|
|
|
|
|
| -void MergedMathInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
| - Label* deopt = NULL;
|
| - if (CanDeoptimize()) {
|
| - deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp);
|
| - }
|
| - if (kind() == MergedMathInstr::kTruncDivMod) {
|
| - Register left = locs()->in(0).reg();
|
| - Register right = locs()->in(1).reg();
|
| - ASSERT(locs()->out(0).IsPairLocation());
|
| - PairLocation* pair = locs()->out(0).AsPairLocation();
|
| - Register result1 = pair->At(0).reg();
|
| - Register result2 = pair->At(1).reg();
|
| - Label not_32bit, done;
|
| - Register temp = RDX;
|
| - ASSERT(left == RAX);
|
| - ASSERT((right != RDX) && (right != RAX));
|
| - ASSERT(result1 == RAX);
|
| - ASSERT(result2 == RDX);
|
| - Range* right_range = InputAt(1)->definition()->range();
|
| - if ((right_range == NULL) || right_range->Overlaps(0, 0)) {
|
| - // Handle divide by zero in runtime.
|
| - __ testq(right, right);
|
| - __ j(ZERO, deopt);
|
| - }
|
| - // Check if both operands fit into 32bits as idiv with 64bit operands
|
| - // requires twice as many cycles and has much higher latency.
|
| - // We are checking this before untagging them to avoid corner case
|
| - // dividing INT_MAX by -1 that raises exception because quotient is
|
| - // too large for 32bit register.
|
| - __ movsxd(temp, left);
|
| - __ cmpq(temp, left);
|
| - __ j(NOT_EQUAL, ¬_32bit);
|
| - __ movsxd(temp, right);
|
| - __ cmpq(temp, right);
|
| - __ j(NOT_EQUAL, ¬_32bit);
|
| -
|
| - // Both operands are 31bit smis. Divide using 32bit idiv.
|
| - __ SmiUntag(left);
|
| - __ SmiUntag(right);
|
| - __ cdq();
|
| - __ idivl(right);
|
| - __ movsxd(RAX, RAX);
|
| - __ movsxd(RDX, RDX);
|
| - __ jmp(&done);
|
| -
|
| - // Divide using 64bit idiv.
|
| - __ Bind(¬_32bit);
|
| - __ SmiUntag(left);
|
| - __ SmiUntag(right);
|
| - __ cqo(); // Sign extend RAX -> RDX:RAX.
|
| - __ idivq(right); // RAX: quotient, RDX: remainder.
|
| - // Check the corner case of dividing the 'MIN_SMI' with -1, in which
|
| - // case we cannot tag the result.
|
| - __ CompareImmediate(RAX, Immediate(0x4000000000000000));
|
| - __ j(EQUAL, deopt);
|
| - __ Bind(&done);
|
| +void TruncDivModInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
| + ASSERT(CanDeoptimize());
|
| + Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp);
|
| + Register left = locs()->in(0).reg();
|
| + Register right = locs()->in(1).reg();
|
| + ASSERT(locs()->out(0).IsPairLocation());
|
| + PairLocation* pair = locs()->out(0).AsPairLocation();
|
| + Register result1 = pair->At(0).reg();
|
| + Register result2 = pair->At(1).reg();
|
| + Label not_32bit, done;
|
| + Register temp = RDX;
|
| + ASSERT(left == RAX);
|
| + ASSERT((right != RDX) && (right != RAX));
|
| + ASSERT(result1 == RAX);
|
| + ASSERT(result2 == RDX);
|
| + if (RangeUtils::CanBeZero(divisor_range())) {
|
| + // Handle divide by zero in runtime.
|
| + __ testq(right, right);
|
| + __ j(ZERO, deopt);
|
| + }
|
| + // Check if both operands fit into 32bits as idiv with 64bit operands
|
| + // requires twice as many cycles and has much higher latency.
|
| + // We are checking this before untagging them to avoid corner case
|
| + // dividing INT_MAX by -1 that raises exception because quotient is
|
| + // too large for 32bit register.
|
| + __ movsxd(temp, left);
|
| + __ cmpq(temp, left);
|
| + __ j(NOT_EQUAL, ¬_32bit);
|
| + __ movsxd(temp, right);
|
| + __ cmpq(temp, right);
|
| + __ j(NOT_EQUAL, ¬_32bit);
|
| +
|
| + // Both operands are 31bit smis. Divide using 32bit idiv.
|
| + __ SmiUntag(left);
|
| + __ SmiUntag(right);
|
| + __ cdq();
|
| + __ idivl(right);
|
| + __ movsxd(RAX, RAX);
|
| + __ movsxd(RDX, RDX);
|
| + __ jmp(&done);
|
|
|
| - // Modulo correction (RDX).
|
| - // res = left % right;
|
| - // if (res < 0) {
|
| - // if (right < 0) {
|
| - // res = res - right;
|
| - // } else {
|
| - // res = res + right;
|
| - // }
|
| - // }
|
| - Label all_done;
|
| - __ cmpq(RDX, Immediate(0));
|
| - __ j(GREATER_EQUAL, &all_done, Assembler::kNearJump);
|
| - // Result is negative, adjust it.
|
| - if ((right_range == NULL) || right_range->Overlaps(-1, 1)) {
|
| - Label subtract;
|
| - __ cmpq(right, Immediate(0));
|
| - __ j(LESS, &subtract, Assembler::kNearJump);
|
| - __ addq(RDX, right);
|
| - __ jmp(&all_done, Assembler::kNearJump);
|
| - __ Bind(&subtract);
|
| - __ subq(RDX, right);
|
| - } else if (right_range->IsPositive()) {
|
| - // Right is positive.
|
| - __ addq(RDX, right);
|
| - } else {
|
| - // Right is negative.
|
| - __ subq(RDX, right);
|
| - }
|
| - __ Bind(&all_done);
|
| + // Divide using 64bit idiv.
|
| + __ Bind(¬_32bit);
|
| + __ SmiUntag(left);
|
| + __ SmiUntag(right);
|
| + __ cqo(); // Sign extend RAX -> RDX:RAX.
|
| + __ idivq(right); // RAX: quotient, RDX: remainder.
|
| + // Check the corner case of dividing the 'MIN_SMI' with -1, in which
|
| + // case we cannot tag the result.
|
| + __ CompareImmediate(RAX, Immediate(0x4000000000000000));
|
| + __ j(EQUAL, deopt);
|
| + __ Bind(&done);
|
|
|
| - __ SmiTag(RAX);
|
| - __ SmiTag(RDX);
|
| - // Note that the result of an integer division/modulo of two
|
| - // in-range arguments, cannot create out-of-range result.
|
| - return;
|
| + // Modulo correction (RDX).
|
| + // res = left % right;
|
| + // if (res < 0) {
|
| + // if (right < 0) {
|
| + // res = res - right;
|
| + // } else {
|
| + // res = res + right;
|
| + // }
|
| + // }
|
| + Label all_done;
|
| + __ cmpq(RDX, Immediate(0));
|
| + __ j(GREATER_EQUAL, &all_done, Assembler::kNearJump);
|
| + // Result is negative, adjust it.
|
| + if ((divisor_range() == NULL) || divisor_range()->Overlaps(-1, 1)) {
|
| + Label subtract;
|
| + __ cmpq(right, Immediate(0));
|
| + __ j(LESS, &subtract, Assembler::kNearJump);
|
| + __ addq(RDX, right);
|
| + __ jmp(&all_done, Assembler::kNearJump);
|
| + __ Bind(&subtract);
|
| + __ subq(RDX, right);
|
| + } else if (divisor_range()->IsPositive()) {
|
| + // Right is positive.
|
| + __ addq(RDX, right);
|
| + } else {
|
| + // Right is negative.
|
| + __ subq(RDX, right);
|
| }
|
| - UNIMPLEMENTED();
|
| + __ Bind(&all_done);
|
| +
|
| + __ SmiTag(RAX);
|
| + __ SmiTag(RDX);
|
| + // Note that the result of an integer division/modulo of two
|
| + // in-range arguments, cannot create out-of-range result.
|
| }
|
|
|
|
|
| @@ -6126,14 +6113,6 @@ void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
| }
|
|
|
|
|
| -static const intptr_t kMintShiftCountLimit = 63;
|
| -
|
| -bool ShiftMintOpInstr::has_shift_count_check() const {
|
| - return !RangeUtils::IsWithin(right()->definition()->range(), 0,
|
| - kMintShiftCountLimit);
|
| -}
|
| -
|
| -
|
| LocationSummary* ShiftMintOpInstr::MakeLocationSummary(Zone* zone,
|
| bool opt) const {
|
| const intptr_t kNumInputs = 2;
|
|
|