Index: src/ia32/lithium-codegen-ia32.cc |
=================================================================== |
--- src/ia32/lithium-codegen-ia32.cc (revision 7551) |
+++ src/ia32/lithium-codegen-ia32.cc (working copy) |
@@ -795,6 +795,7 @@ |
__ bind(&done); |
} else { |
LOperand* right = instr->InputAt(1); |
+ NearLabel done, remainder_eq_dividend, slow, do_subtraction, both_positive; |
Søren Thygesen Gjesse
2011/04/27 14:11:43
Please set up Register variables for left as well:
|
ASSERT(ToRegister(instr->InputAt(0)).is(eax)); |
ASSERT(ToRegister(instr->result()).is(edx)); |
@@ -808,6 +809,45 @@ |
DeoptimizeIf(zero, instr->environment()); |
} |
+ __ test(eax, Operand(eax)); |
+ __ j(zero, &remainder_eq_dividend); |
+ __ j(sign, &slow); |
+ |
+ __ test(right_reg, Operand(right_reg)); |
+ __ j(not_sign, &both_positive); |
+ // The sign of the divisor doesn't matter. |
+ __ neg(right_reg); |
+ |
+ __ bind(&both_positive); |
+ // If the dividend is smaller than the nonnegative |
+ // divisor, the dividend is the result. |
+ __ cmp(eax, Operand(right_reg)); |
+ __ j(less, &remainder_eq_dividend); |
+ |
+ // Check if the divisor is a PowerOfTwo integer. |
+ Register scratch = ToRegister(instr->TempAt(0)); |
+ __ mov(scratch, right_reg); |
+ __ sub(Operand(scratch), Immediate(1)); |
+ __ test(scratch, Operand(right_reg)); |
+ __ j(not_zero, &do_subtraction); |
+ __ and_(eax, Operand(scratch)); |
+ __ jmp(&remainder_eq_dividend); |
+ |
+ __ bind(&do_subtraction); |
+ const int kUnfolds = 3; |
+ // Try a few subtractions of the dividend. |
+ __ mov(scratch, eax); |
+ for (int i = 0; i < kUnfolds; i++) { |
+ // Reduce the dividend by the divisor. |
+ __ sub(eax, Operand(right_reg)); |
+ // Check if the dividend is less than the divisor. |
+ __ cmp(eax, Operand(right_reg)); |
+ __ j(less, &remainder_eq_dividend); |
+ } |
+ __ mov(eax, scratch); |
+ |
+ // Slow case, using idiv instruction. |
+ __ bind(&slow); |
// Sign extend to edx. |
__ cdq(); |
@@ -830,6 +870,12 @@ |
} else { |
__ idiv(right_reg); |
} |
+ __ jmp(&done); |
+ |
+ __ bind(&remainder_eq_dividend); |
+ __ mov(edx, eax); |
+ |
+ __ bind(&done); |
} |
} |