| Index: src/arm/lithium-codegen-arm.cc
|
| ===================================================================
|
| --- src/arm/lithium-codegen-arm.cc (revision 7286)
|
| +++ src/arm/lithium-codegen-arm.cc (working copy)
|
| @@ -802,7 +802,7 @@
|
| if (divisor < 0) divisor = -divisor;
|
|
|
| Label positive_dividend, done;
|
| - __ tst(dividend, Operand(dividend));
|
| + __ cmp(dividend, Operand(0));
|
| __ b(pl, &positive_dividend);
|
| __ rsb(dividend, dividend, Operand(0));
|
| __ and_(dividend, dividend, Operand(divisor - 1));
|
| @@ -817,55 +817,67 @@
|
| return;
|
| }
|
|
|
| - class DeferredModI: public LDeferredCode {
|
| - public:
|
| - DeferredModI(LCodeGen* codegen, LModI* instr)
|
| - : LDeferredCode(codegen), instr_(instr) { }
|
| - virtual void Generate() {
|
| - codegen()->DoDeferredBinaryOpStub(instr_, Token::MOD);
|
| - }
|
| - private:
|
| - LModI* instr_;
|
| - };
|
| // These registers hold untagged 32 bit values.
|
| Register left = ToRegister(instr->InputAt(0));
|
| Register right = ToRegister(instr->InputAt(1));
|
| Register result = ToRegister(instr->result());
|
| +
|
| Register scratch = scratch0();
|
| + Register scratch2 = ToRegister(instr->TempAt(0));
|
| + DwVfpRegister dividend = ToDoubleRegister(instr->TempAt(1));
|
| + DwVfpRegister divisor = ToDoubleRegister(instr->TempAt(2));
|
| + DwVfpRegister quotient = double_scratch0();
|
|
|
| - Label deoptimize, done;
|
| + ASSERT(result.is(left));
|
| +
|
| + ASSERT(!dividend.is(divisor));
|
| + ASSERT(!dividend.is(quotient));
|
| + ASSERT(!divisor.is(quotient));
|
| + ASSERT(!scratch.is(left));
|
| + ASSERT(!scratch.is(right));
|
| + ASSERT(!scratch.is(result));
|
| +
|
| + Label done, vfp_modulo, both_positive, right_negative;
|
| +
|
| // Check for x % 0.
|
| if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) {
|
| - __ tst(right, Operand(right));
|
| - __ b(eq, &deoptimize);
|
| + __ cmp(right, Operand(0));
|
| + DeoptimizeIf(eq, instr->environment());
|
| }
|
|
|
| - // Check for (0 % -x) that will produce negative zero.
|
| - if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
|
| - Label ok;
|
| - __ tst(left, Operand(left));
|
| - __ b(ne, &ok);
|
| - __ tst(right, Operand(right));
|
| - __ b(pl, &ok);
|
| - __ b(al, &deoptimize);
|
| - __ bind(&ok);
|
| - }
|
| + // (0 % x) must yield 0 (if x is finite, which is the case here).
|
| + __ cmp(left, Operand(0));
|
| + __ b(eq, &done);
|
| + // Preload right in a vfp register.
|
| + __ vmov(divisor.low(), right);
|
| + __ b(lt, &vfp_modulo);
|
|
|
| - // Try a few common cases before using the stub.
|
| - Label call_stub;
|
| + __ cmp(left, Operand(right));
|
| + __ b(lt, &done);
|
| +
|
| + // Check for (positive) power of two on the right hand side.
|
| + __ JumpIfNotPowerOfTwoOrZeroAndNeg(right,
|
| + scratch,
|
| + &right_negative,
|
| + &both_positive);
|
| + // Perform modulo operation (scratch contains right - 1).
|
| + __ and_(result, scratch, Operand(left));
|
| + __ b(&done);
|
| +
|
| + __ bind(&right_negative);
|
| + // Negate right. The sign of the divisor does not matter.
|
| + __ rsb(right, right, Operand(0));
|
| +
|
| + __ bind(&both_positive);
|
| const int kUnfolds = 3;
|
| - // Skip if either side is negative.
|
| - __ cmp(left, Operand(0));
|
| - __ cmp(right, Operand(0), NegateCondition(mi));
|
| - __ b(mi, &call_stub);
|
| // If the right hand side is smaller than the (nonnegative)
|
| - // left hand side, it is the result. Else try a few subtractions
|
| - // of the left hand side.
|
| + // left hand side, the left hand side is the result.
|
| + // Else try a few subtractions of the left hand side.
|
| __ mov(scratch, left);
|
| for (int i = 0; i < kUnfolds; i++) {
|
| // Check if the left hand side is less or equal than the
|
| // the right hand side.
|
| - __ cmp(scratch, right);
|
| + __ cmp(scratch, Operand(right));
|
| __ mov(result, scratch, LeaveCC, lt);
|
| __ b(lt, &done);
|
| // If not, reduce the left hand side by the right hand
|
| @@ -873,29 +885,45 @@
|
| if (i < kUnfolds - 1) __ sub(scratch, scratch, right);
|
| }
|
|
|
| - // Check for power of two on the right hand side.
|
| - __ JumpIfNotPowerOfTwoOrZero(right, scratch, &call_stub);
|
| - // Perform modulo operation (scratch contains right - 1).
|
| - __ and_(result, scratch, Operand(left));
|
| - __ b(&done);
|
| + __ bind(&vfp_modulo);
|
| + // Load the arguments in VFP registers.
|
| + // The divisor value is preloaded before. Be careful that 'right' is only live
|
| + // on entry.
|
| + __ vmov(dividend.low(), left);
|
| + // From here on don't use right as it may have been reallocated (for example
|
| + // to scratch2).
|
| + right = no_reg;
|
|
|
| - __ bind(&call_stub);
|
| - // Call the stub. The numbers in r0 and r1 have
|
| - // to be tagged to Smis. If that is not possible, deoptimize.
|
| - DeferredModI* deferred = new DeferredModI(this, instr);
|
| - __ TrySmiTag(left, &deoptimize, scratch);
|
| - __ TrySmiTag(right, &deoptimize, scratch);
|
| + __ vcvt_f64_s32(dividend, dividend.low());
|
| + __ vcvt_f64_s32(divisor, divisor.low());
|
|
|
| - __ b(al, deferred->entry());
|
| - __ bind(deferred->exit());
|
| + // We do not care about the sign of the divisor.
|
| + __ vabs(divisor, divisor);
|
| + // Compute the quotient and round it to a 32bit integer.
|
| + __ vdiv(quotient, dividend, divisor);
|
| + __ vcvt_s32_f64(quotient.low(), quotient);
|
| + __ vcvt_f64_s32(quotient, quotient.low());
|
|
|
| - // If the result in r0 is a Smi, untag it, else deoptimize.
|
| - __ JumpIfNotSmi(result, &deoptimize);
|
| - __ SmiUntag(result);
|
| + // Compute the remainder in result.
|
| + DwVfpRegister double_scratch = dividend;
|
| + __ vmul(double_scratch, divisor, quotient);
|
| + __ vcvt_s32_f64(double_scratch.low(), double_scratch);
|
| + __ vmov(scratch, double_scratch.low());
|
|
|
| - __ b(al, &done);
|
| - __ bind(&deoptimize);
|
| - DeoptimizeIf(al, instr->environment());
|
| + if (!instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
|
| + __ sub(result, left, scratch);
|
| + } else {
|
| + Label ok;
|
| + // Check for -0.
|
| + __ sub(scratch2, left, scratch, SetCC);
|
| + __ b(ne, &ok);
|
| + __ cmp(left, Operand(0));
|
| + DeoptimizeIf(mi, instr->environment());
|
| + __ bind(&ok);
|
| + // Load the result and we are done.
|
| + __ mov(result, scratch2);
|
| + }
|
| +
|
| __ bind(&done);
|
| }
|
|
|
| @@ -919,16 +947,16 @@
|
|
|
| // Check for x / 0.
|
| if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) {
|
| - __ tst(right, right);
|
| + __ cmp(right, Operand(0));
|
| DeoptimizeIf(eq, instr->environment());
|
| }
|
|
|
| // Check for (0 / -x) that will produce negative zero.
|
| if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
|
| Label left_not_zero;
|
| - __ tst(left, Operand(left));
|
| + __ cmp(left, Operand(0));
|
| __ b(ne, &left_not_zero);
|
| - __ tst(right, Operand(right));
|
| + __ cmp(right, Operand(0));
|
| DeoptimizeIf(mi, instr->environment());
|
| __ bind(&left_not_zero);
|
| }
|
| @@ -1035,7 +1063,7 @@
|
| if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
|
| // Bail out if the result is supposed to be negative zero.
|
| Label done;
|
| - __ tst(left, Operand(left));
|
| + __ cmp(left, Operand(0));
|
| __ b(ne, &done);
|
| if (instr->InputAt(1)->IsConstantOperand()) {
|
| if (ToInteger32(LConstantOperand::cast(instr->InputAt(1))) <= 0) {
|
| @@ -1900,8 +1928,7 @@
|
| InstanceofStub stub(InstanceofStub::kArgsInRegisters);
|
| CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
|
|
|
| - Label true_value, done;
|
| - __ tst(r0, r0);
|
| + __ cmp(r0, Operand(0));
|
| __ mov(r0, Operand(factory()->false_value()), LeaveCC, ne);
|
| __ mov(r0, Operand(factory()->true_value()), LeaveCC, eq);
|
| }
|
| @@ -1916,7 +1943,7 @@
|
|
|
| InstanceofStub stub(InstanceofStub::kArgsInRegisters);
|
| CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
|
| - __ tst(r0, Operand(r0));
|
| + __ cmp(r0, Operand(0));
|
| EmitBranch(true_block, false_block, eq);
|
| }
|
|
|
| @@ -2406,7 +2433,7 @@
|
| // stack.
|
| Label invoke, loop;
|
| // length is a small non-negative integer, due to the test above.
|
| - __ tst(length, Operand(length));
|
| + __ cmp(length, Operand(0));
|
| __ b(eq, &invoke);
|
| __ bind(&loop);
|
| __ ldr(scratch, MemOperand(elements, length, LSL, 2));
|
| @@ -2642,14 +2669,16 @@
|
| // Move the result back to general purpose register r0.
|
| __ vmov(result, single_scratch);
|
|
|
| - // Test for -0.
|
| - Label done;
|
| - __ cmp(result, Operand(0));
|
| - __ b(ne, &done);
|
| - __ vmov(scratch1, input.high());
|
| - __ tst(scratch1, Operand(HeapNumber::kSignMask));
|
| - DeoptimizeIf(ne, instr->environment());
|
| - __ bind(&done);
|
| + if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
|
| + // Test for -0.
|
| + Label done;
|
| + __ cmp(result, Operand(0));
|
| + __ b(ne, &done);
|
| + __ vmov(scratch1, input.high());
|
| + __ tst(scratch1, Operand(HeapNumber::kSignMask));
|
| + DeoptimizeIf(ne, instr->environment());
|
| + __ bind(&done);
|
| + }
|
| }
|
|
|
|
|
| @@ -2666,14 +2695,16 @@
|
| DeoptimizeIf(ne, instr->environment());
|
| __ vmov(result, double_scratch0().low());
|
|
|
| - // Test for -0.
|
| - Label done;
|
| - __ cmp(result, Operand(0));
|
| - __ b(ne, &done);
|
| - __ vmov(scratch1, input.high());
|
| - __ tst(scratch1, Operand(HeapNumber::kSignMask));
|
| - DeoptimizeIf(ne, instr->environment());
|
| - __ bind(&done);
|
| + if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
|
| + // Test for -0.
|
| + Label done;
|
| + __ cmp(result, Operand(0));
|
| + __ b(ne, &done);
|
| + __ vmov(scratch1, input.high());
|
| + __ tst(scratch1, Operand(HeapNumber::kSignMask));
|
| + DeoptimizeIf(ne, instr->environment());
|
| + __ bind(&done);
|
| + }
|
| }
|
|
|
|
|
|
|