From f1e9ec2e1281acf06b9abad100ed6b054d9ae9d4 Mon Sep 17 00:00:00 2001 From: "svenpanne@chromium.org" Date: Mon, 29 Apr 2013 13:45:34 +0000 Subject: [PATCH] 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 --- src/arm/lithium-codegen-arm.cc | 47 ++++++++++------------------------------ src/ia32/lithium-codegen-ia32.cc | 17 ++------------- src/x64/lithium-codegen-x64.cc | 17 ++------------- 3 files changed, 16 insertions(+), 65 deletions(-) diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc index 4f55f8c..dfacf4c 100644 --- a/src/arm/lithium-codegen-arm.cc +++ b/src/arm/lithium-codegen-arm.cc @@ -1165,14 +1165,14 @@ void LCodeGen::DoModI(LModI* instr) { Register result = ToRegister(instr->result()); Label done; - 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()); - } + if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { + __ cmp(right, Operand::Zero()); + DeoptimizeIf(eq, instr->environment()); + } + if (CpuFeatures::IsSupported(SUDIV)) { + CpuFeatureScope scope(masm(), SUDIV); // 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' diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc index 91549a2..4318f31 100644 --- a/src/ia32/lithium-codegen-ia32.cc +++ b/src/ia32/lithium-codegen-ia32.cc @@ -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); diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc index 4b99c68..bd928e2 100644 --- a/src/x64/lithium-codegen-x64.cc +++ b/src/x64/lithium-codegen-x64.cc @@ -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); -- 2.7.4