Do not use repeated subtractions in mod-i, it hurts performance in general.
ARM only: Check for -0 only when really necessary. Tiny code de-duplication. R=jkummerow@chromium.org Review URL: https://codereview.chromium.org/14499011 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@14479 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
0c63e8d698
commit
f1e9ec2e12
@ -1165,14 +1165,14 @@ void LCodeGen::DoModI(LModI* instr) {
|
||||
Register result = ToRegister(instr->result());
|
||||
Label done;
|
||||
|
||||
// Check for x % 0.
|
||||
if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) {
|
||||
__ cmp(right, Operand::Zero());
|
||||
DeoptimizeIf(eq, instr->environment());
|
||||
}
|
||||
|
||||
if (CpuFeatures::IsSupported(SUDIV)) {
|
||||
CpuFeatureScope scope(masm(), SUDIV);
|
||||
// Check for x % 0.
|
||||
if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) {
|
||||
__ cmp(right, Operand::Zero());
|
||||
DeoptimizeIf(eq, instr->environment());
|
||||
}
|
||||
|
||||
// Check for (kMinInt % -1).
|
||||
if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
|
||||
Label left_not_min_int;
|
||||
@ -1189,12 +1189,12 @@ void LCodeGen::DoModI(LModI* instr) {
|
||||
|
||||
__ sdiv(result, left, right);
|
||||
__ mls(result, result, right, left);
|
||||
__ cmp(result, Operand::Zero());
|
||||
__ b(ne, &done);
|
||||
|
||||
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
|
||||
__ cmp(left, Operand::Zero());
|
||||
DeoptimizeIf(lt, instr->environment());
|
||||
__ cmp(result, Operand::Zero());
|
||||
__ b(ne, &done);
|
||||
__ cmp(left, Operand::Zero());
|
||||
DeoptimizeIf(lt, instr->environment());
|
||||
}
|
||||
} else {
|
||||
Register scratch = scratch0();
|
||||
@ -1210,13 +1210,7 @@ void LCodeGen::DoModI(LModI* instr) {
|
||||
ASSERT(!scratch.is(right));
|
||||
ASSERT(!scratch.is(result));
|
||||
|
||||
Label vfp_modulo, both_positive, right_negative;
|
||||
|
||||
// Check for x % 0.
|
||||
if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) {
|
||||
__ cmp(right, Operand::Zero());
|
||||
DeoptimizeIf(eq, instr->environment());
|
||||
}
|
||||
Label vfp_modulo, right_negative;
|
||||
|
||||
__ Move(result, left);
|
||||
|
||||
@ -1234,7 +1228,7 @@ void LCodeGen::DoModI(LModI* instr) {
|
||||
__ JumpIfNotPowerOfTwoOrZeroAndNeg(right,
|
||||
scratch,
|
||||
&right_negative,
|
||||
&both_positive);
|
||||
&vfp_modulo);
|
||||
// Perform modulo operation (scratch contains right - 1).
|
||||
__ and_(result, scratch, Operand(left));
|
||||
__ b(&done);
|
||||
@ -1243,23 +1237,6 @@ void LCodeGen::DoModI(LModI* instr) {
|
||||
// Negate right. The sign of the divisor does not matter.
|
||||
__ rsb(right, right, Operand::Zero());
|
||||
|
||||
__ bind(&both_positive);
|
||||
const int kUnfolds = 3;
|
||||
// If the right hand side is smaller than the (nonnegative)
|
||||
// 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, Operand(right));
|
||||
__ mov(result, scratch, LeaveCC, lt);
|
||||
__ b(lt, &done);
|
||||
// If not, reduce the left hand side by the right hand
|
||||
// side and check again.
|
||||
if (i < kUnfolds - 1) __ sub(scratch, scratch, right);
|
||||
}
|
||||
|
||||
__ bind(&vfp_modulo);
|
||||
// Load the arguments in VFP registers.
|
||||
// The divisor value is preloaded before. Be careful that 'right'
|
||||
|
@ -1234,7 +1234,7 @@ void LCodeGen::DoModI(LModI* instr) {
|
||||
__ and_(dividend, divisor - 1);
|
||||
__ bind(&done);
|
||||
} else {
|
||||
Label done, remainder_eq_dividend, slow, do_subtraction, both_positive;
|
||||
Label done, remainder_eq_dividend, slow, both_positive;
|
||||
Register left_reg = ToRegister(instr->left());
|
||||
Register right_reg = ToRegister(instr->right());
|
||||
Register result_reg = ToRegister(instr->result());
|
||||
@ -1270,23 +1270,10 @@ void LCodeGen::DoModI(LModI* instr) {
|
||||
__ mov(scratch, right_reg);
|
||||
__ sub(Operand(scratch), Immediate(1));
|
||||
__ test(scratch, Operand(right_reg));
|
||||
__ j(not_zero, &do_subtraction, Label::kNear);
|
||||
__ j(not_zero, &slow, Label::kNear);
|
||||
__ and_(left_reg, Operand(scratch));
|
||||
__ jmp(&remainder_eq_dividend, Label::kNear);
|
||||
|
||||
__ bind(&do_subtraction);
|
||||
const int kUnfolds = 3;
|
||||
// Try a few subtractions of the dividend.
|
||||
__ mov(scratch, left_reg);
|
||||
for (int i = 0; i < kUnfolds; i++) {
|
||||
// Reduce the dividend by the divisor.
|
||||
__ sub(left_reg, Operand(right_reg));
|
||||
// Check if the dividend is less than the divisor.
|
||||
__ cmp(left_reg, Operand(right_reg));
|
||||
__ j(less, &remainder_eq_dividend, Label::kNear);
|
||||
}
|
||||
__ mov(left_reg, scratch);
|
||||
|
||||
// Slow case, using idiv instruction.
|
||||
__ bind(&slow);
|
||||
|
||||
|
@ -1037,7 +1037,7 @@ void LCodeGen::DoModI(LModI* instr) {
|
||||
__ andl(dividend, Immediate(divisor - 1));
|
||||
__ bind(&done);
|
||||
} else {
|
||||
Label done, remainder_eq_dividend, slow, do_subtraction, both_positive;
|
||||
Label done, remainder_eq_dividend, slow, both_positive;
|
||||
Register left_reg = ToRegister(instr->left());
|
||||
Register right_reg = ToRegister(instr->right());
|
||||
Register result_reg = ToRegister(instr->result());
|
||||
@ -1073,23 +1073,10 @@ void LCodeGen::DoModI(LModI* instr) {
|
||||
__ movl(scratch, right_reg);
|
||||
__ subl(scratch, Immediate(1));
|
||||
__ testl(scratch, right_reg);
|
||||
__ j(not_zero, &do_subtraction, Label::kNear);
|
||||
__ j(not_zero, &slow, Label::kNear);
|
||||
__ andl(left_reg, scratch);
|
||||
__ jmp(&remainder_eq_dividend, Label::kNear);
|
||||
|
||||
__ bind(&do_subtraction);
|
||||
const int kUnfolds = 3;
|
||||
// Try a few subtractions of the dividend.
|
||||
__ movl(scratch, left_reg);
|
||||
for (int i = 0; i < kUnfolds; i++) {
|
||||
// Reduce the dividend by the divisor.
|
||||
__ subl(left_reg, right_reg);
|
||||
// Check if the dividend is less than the divisor.
|
||||
__ cmpl(left_reg, right_reg);
|
||||
__ j(less, &remainder_eq_dividend, Label::kNear);
|
||||
}
|
||||
__ movl(left_reg, scratch);
|
||||
|
||||
// Slow case, using idiv instruction.
|
||||
__ bind(&slow);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user