diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc index 7f504ea4ad..d3ac5e0dfe 100644 --- a/src/arm/lithium-arm.cc +++ b/src/arm/lithium-arm.cc @@ -1373,9 +1373,8 @@ LInstruction* LChunkBuilder::DoDiv(HDiv* instr) { if (instr->HasPowerOf2Divisor()) { ASSERT(!instr->CheckFlag(HValue::kCanBeDivByZero)); LOperand* value = UseRegisterAtStart(instr->left()); - LDivI* div = - new(zone()) LDivI(value, UseOrConstant(instr->right()), NULL); - return AssignEnvironment(DefineSameAsFirst(div)); + LDivI* div = new(zone()) LDivI(value, UseConstant(instr->right()), NULL); + return AssignEnvironment(DefineAsRegister(div)); } LOperand* dividend = UseRegister(instr->left()); LOperand* divisor = UseRegister(instr->right()); diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc index b7fc3b6055..b01f840c63 100644 --- a/src/arm/lithium-codegen-arm.cc +++ b/src/arm/lithium-codegen-arm.cc @@ -1383,7 +1383,8 @@ void LCodeGen::EmitSignedIntegerDivisionByConstant( void LCodeGen::DoDivI(LDivI* instr) { if (instr->hydrogen()->HasPowerOf2Divisor()) { - Register dividend = ToRegister(instr->left()); + const Register dividend = ToRegister(instr->left()); + const Register result = ToRegister(instr->result()); int32_t divisor = instr->hydrogen()->right()->GetInteger32Constant(); int32_t test_value = 0; int32_t power = 0; @@ -1394,7 +1395,7 @@ void LCodeGen::DoDivI(LDivI* instr) { } else { // Check for (0 / -x) that will produce negative zero. if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { - __ tst(dividend, Operand(dividend)); + __ cmp(dividend, Operand::Zero()); DeoptimizeIf(eq, instr->environment()); } // Check for (kMinInt / -1). @@ -1409,20 +1410,26 @@ void LCodeGen::DoDivI(LDivI* instr) { if (test_value != 0) { if (instr->hydrogen()->CheckFlag( HInstruction::kAllUsesTruncatingToInt32)) { - __ cmp(dividend, Operand(0)); - __ rsb(dividend, dividend, Operand(0), LeaveCC, lt); - __ mov(dividend, Operand(dividend, ASR, power)); - if (divisor > 0) __ rsb(dividend, dividend, Operand(0), LeaveCC, lt); - if (divisor < 0) __ rsb(dividend, dividend, Operand(0), LeaveCC, gt); + __ sub(result, dividend, Operand::Zero(), SetCC); + __ rsb(result, result, Operand::Zero(), LeaveCC, lt); + __ mov(result, Operand(result, ASR, power)); + if (divisor > 0) __ rsb(result, result, Operand::Zero(), LeaveCC, lt); + if (divisor < 0) __ rsb(result, result, Operand::Zero(), LeaveCC, gt); return; // Don't fall through to "__ rsb" below. } else { // Deoptimize if remainder is not 0. __ tst(dividend, Operand(test_value)); DeoptimizeIf(ne, instr->environment()); - __ mov(dividend, Operand(dividend, ASR, power)); + __ mov(result, Operand(dividend, ASR, power)); + if (divisor < 0) __ rsb(result, result, Operand(0)); + } + } else { + if (divisor < 0) { + __ rsb(result, dividend, Operand(0)); + } else { + __ Move(result, dividend); } } - if (divisor < 0) __ rsb(dividend, dividend, Operand(0)); return; } @@ -1439,12 +1446,15 @@ void LCodeGen::DoDivI(LDivI* instr) { // Check for (0 / -x) that will produce negative zero. if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { - Label left_not_zero; + Label positive; + if (!instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { + // Do the test only if it hadn't be done above. + __ cmp(right, Operand::Zero()); + } + __ b(pl, &positive); __ cmp(left, Operand::Zero()); - __ b(ne, &left_not_zero); - __ cmp(right, Operand::Zero()); - DeoptimizeIf(mi, instr->environment()); - __ bind(&left_not_zero); + DeoptimizeIf(eq, instr->environment()); + __ bind(&positive); } // Check for (kMinInt / -1). diff --git a/test/mjsunit/lithium/DivI.js b/test/mjsunit/lithium/DivI.js new file mode 100644 index 0000000000..5420d8c8d0 --- /dev/null +++ b/test/mjsunit/lithium/DivI.js @@ -0,0 +1,57 @@ +// Copyright 2013 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Flags: --allow-natives-syntax --no-use-osr + +function foo(a, b) { + var result = a / 35; + result += 50 / b; + result += a / b; + result += a / -1; + result += a / 1; + result += a / 4; + result += a / -4; + return result / b; +} + +foo(700, 5); +var r1 = foo(700, 5); +%OptimizeFunctionOnNextCall(foo); +var r2 = foo(700, 5); + +assertEquals(r1, r2); + +function boo(value) { + return value / -1; +} + +// Test deoptimization of MinInt / -1. +assertEquals(2147483600, boo(-2147483600)); +assertEquals(2147483600, boo(-2147483600)); +%OptimizeFunctionOnNextCall(boo); +assertEquals(2147483600, boo(-2147483600)); +assertEquals(2147483648, boo(-2147483648));