ARM: Use division instructions in lithium and stubs
BUG=none TEST=Added to test/mjsunit/math-floor-of-div.js, math-floor-of-div-nosudiv.js Review URL: https://codereview.chromium.org/11316105 Patch from Martyn Capewell <m.m.capewell@googlemail.com>. git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@13257 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
a3f16f8e65
commit
653a66f527
@ -2441,33 +2441,112 @@ void BinaryOpStub_GenerateSmiSmiOperation(MacroAssembler* masm,
|
|||||||
// We fall through here if we multiplied a negative number with 0, because
|
// We fall through here if we multiplied a negative number with 0, because
|
||||||
// that would mean we should produce -0.
|
// that would mean we should produce -0.
|
||||||
break;
|
break;
|
||||||
case Token::DIV:
|
case Token::DIV: {
|
||||||
|
Label div_with_sdiv;
|
||||||
|
|
||||||
|
// Check for 0 divisor.
|
||||||
|
__ cmp(right, Operand(0));
|
||||||
|
__ b(eq, ¬_smi_result);
|
||||||
|
|
||||||
// Check for power of two on the right hand side.
|
// Check for power of two on the right hand side.
|
||||||
__ JumpIfNotPowerOfTwoOrZero(right, scratch1, ¬_smi_result);
|
__ sub(scratch1, right, Operand(1));
|
||||||
// Check for positive and no remainder (scratch1 contains right - 1).
|
__ tst(scratch1, right);
|
||||||
__ orr(scratch2, scratch1, Operand(0x80000000u));
|
if (CpuFeatures::IsSupported(SUDIV)) {
|
||||||
__ tst(left, scratch2);
|
__ b(ne, &div_with_sdiv);
|
||||||
__ b(ne, ¬_smi_result);
|
// Check for no remainder.
|
||||||
|
__ tst(left, scratch1);
|
||||||
|
__ b(ne, ¬_smi_result);
|
||||||
|
// Check for positive left hand side.
|
||||||
|
__ cmp(left, Operand(0));
|
||||||
|
__ b(mi, &div_with_sdiv);
|
||||||
|
} else {
|
||||||
|
__ b(ne, ¬_smi_result);
|
||||||
|
// Check for positive and no remainder.
|
||||||
|
__ orr(scratch2, scratch1, Operand(0x80000000u));
|
||||||
|
__ tst(left, scratch2);
|
||||||
|
__ b(ne, ¬_smi_result);
|
||||||
|
}
|
||||||
|
|
||||||
// Perform division by shifting.
|
// Perform division by shifting.
|
||||||
__ CountLeadingZeros(scratch1, scratch1, scratch2);
|
__ CountLeadingZeros(scratch1, scratch1, scratch2);
|
||||||
__ rsb(scratch1, scratch1, Operand(31));
|
__ rsb(scratch1, scratch1, Operand(31));
|
||||||
__ mov(right, Operand(left, LSR, scratch1));
|
__ mov(right, Operand(left, LSR, scratch1));
|
||||||
__ Ret();
|
__ Ret();
|
||||||
|
|
||||||
|
if (CpuFeatures::IsSupported(SUDIV)) {
|
||||||
|
Label result_not_zero;
|
||||||
|
|
||||||
|
__ bind(&div_with_sdiv);
|
||||||
|
// Do division.
|
||||||
|
__ sdiv(scratch1, left, right);
|
||||||
|
// Check that the remainder is zero.
|
||||||
|
__ mls(scratch2, scratch1, right, left);
|
||||||
|
__ cmp(scratch2, Operand(0));
|
||||||
|
__ b(ne, ¬_smi_result);
|
||||||
|
// Check for negative zero result.
|
||||||
|
__ cmp(scratch1, Operand(0));
|
||||||
|
__ b(ne, &result_not_zero);
|
||||||
|
__ cmp(right, Operand(0));
|
||||||
|
__ b(lt, ¬_smi_result);
|
||||||
|
__ bind(&result_not_zero);
|
||||||
|
// Check for the corner case of dividing the most negative smi by -1.
|
||||||
|
__ cmp(scratch1, Operand(0x40000000));
|
||||||
|
__ b(eq, ¬_smi_result);
|
||||||
|
// Tag and return the result.
|
||||||
|
__ SmiTag(right, scratch1);
|
||||||
|
__ Ret();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case Token::MOD:
|
}
|
||||||
// Check for two positive smis.
|
case Token::MOD: {
|
||||||
__ orr(scratch1, left, Operand(right));
|
Label modulo_with_sdiv;
|
||||||
__ tst(scratch1, Operand(0x80000000u | kSmiTagMask));
|
|
||||||
__ b(ne, ¬_smi_result);
|
|
||||||
|
|
||||||
// Check for power of two on the right hand side.
|
if (CpuFeatures::IsSupported(SUDIV)) {
|
||||||
__ JumpIfNotPowerOfTwoOrZero(right, scratch1, ¬_smi_result);
|
// Check for x % 0.
|
||||||
|
__ cmp(right, Operand(0));
|
||||||
|
__ b(eq, ¬_smi_result);
|
||||||
|
|
||||||
// Perform modulus by masking.
|
// Check for two positive smis.
|
||||||
|
__ orr(scratch1, left, Operand(right));
|
||||||
|
__ tst(scratch1, Operand(0x80000000u));
|
||||||
|
__ b(ne, &modulo_with_sdiv);
|
||||||
|
|
||||||
|
// Check for power of two on the right hand side.
|
||||||
|
__ sub(scratch1, right, Operand(1));
|
||||||
|
__ tst(scratch1, right);
|
||||||
|
__ b(ne, &modulo_with_sdiv);
|
||||||
|
} else {
|
||||||
|
// Check for two positive smis.
|
||||||
|
__ orr(scratch1, left, Operand(right));
|
||||||
|
__ tst(scratch1, Operand(0x80000000u));
|
||||||
|
__ b(ne, ¬_smi_result);
|
||||||
|
|
||||||
|
// Check for power of two on the right hand side.
|
||||||
|
__ JumpIfNotPowerOfTwoOrZero(right, scratch1, ¬_smi_result);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform modulus by masking (scratch1 contains right - 1).
|
||||||
__ and_(right, left, Operand(scratch1));
|
__ and_(right, left, Operand(scratch1));
|
||||||
__ Ret();
|
__ Ret();
|
||||||
|
|
||||||
|
if (CpuFeatures::IsSupported(SUDIV)) {
|
||||||
|
__ bind(&modulo_with_sdiv);
|
||||||
|
__ mov(scratch2, right);
|
||||||
|
// Perform modulus with sdiv and mls.
|
||||||
|
__ sdiv(scratch1, left, right);
|
||||||
|
__ mls(right, scratch1, right, left);
|
||||||
|
// Return if the result is not 0.
|
||||||
|
__ cmp(right, Operand(0));
|
||||||
|
__ Ret(ne);
|
||||||
|
// The result is 0, check for -0 case.
|
||||||
|
__ cmp(left, Operand(0));
|
||||||
|
__ Ret(pl);
|
||||||
|
// This is a -0 case, restore the value of right.
|
||||||
|
__ mov(right, scratch2);
|
||||||
|
// We fall through here to not_smi_result to produce -0.
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case Token::BIT_OR:
|
case Token::BIT_OR:
|
||||||
__ orr(right, left, Operand(right));
|
__ orr(right, left, Operand(right));
|
||||||
__ Ret();
|
__ Ret();
|
||||||
|
@ -1241,31 +1241,43 @@ HValue* LChunkBuilder::SimplifiedDividendForMathFloorOfDiv(HValue* dividend) {
|
|||||||
|
|
||||||
|
|
||||||
HValue* LChunkBuilder::SimplifiedDivisorForMathFloorOfDiv(HValue* divisor) {
|
HValue* LChunkBuilder::SimplifiedDivisorForMathFloorOfDiv(HValue* divisor) {
|
||||||
// Only optimize when we have magic numbers for the divisor.
|
if (CpuFeatures::IsSupported(SUDIV)) {
|
||||||
// The standard integer division routine is usually slower than transitionning
|
// A value with an integer representation does not need to be transformed.
|
||||||
// to VFP.
|
if (divisor->representation().IsInteger32()) {
|
||||||
if (divisor->IsConstant() &&
|
return divisor;
|
||||||
HConstant::cast(divisor)->HasInteger32Value()) {
|
// A change from an integer32 can be replaced by the integer32 value.
|
||||||
|
} else if (divisor->IsChange() &&
|
||||||
|
HChange::cast(divisor)->from().IsInteger32()) {
|
||||||
|
return HChange::cast(divisor)->value();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (divisor->IsConstant() && HConstant::cast(divisor)->HasInteger32Value()) {
|
||||||
HConstant* constant_val = HConstant::cast(divisor);
|
HConstant* constant_val = HConstant::cast(divisor);
|
||||||
int32_t int32_val = constant_val->Integer32Value();
|
int32_t int32_val = constant_val->Integer32Value();
|
||||||
if (LChunkBuilder::HasMagicNumberForDivisor(int32_val)) {
|
if (LChunkBuilder::HasMagicNumberForDivisor(int32_val) ||
|
||||||
|
CpuFeatures::IsSupported(SUDIV)) {
|
||||||
return constant_val->CopyToRepresentation(Representation::Integer32(),
|
return constant_val->CopyToRepresentation(Representation::Integer32(),
|
||||||
divisor->block()->zone());
|
divisor->block()->zone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) {
|
LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) {
|
||||||
HValue* right = instr->right();
|
HValue* right = instr->right();
|
||||||
LOperand* dividend = UseRegister(instr->left());
|
LOperand* dividend = UseRegister(instr->left());
|
||||||
LOperand* divisor = UseRegisterOrConstant(right);
|
LOperand* divisor = CpuFeatures::IsSupported(SUDIV)
|
||||||
LOperand* remainder = TempRegister();
|
? UseRegister(right)
|
||||||
ASSERT(right->IsConstant() &&
|
: UseOrConstant(right);
|
||||||
HConstant::cast(right)->HasInteger32Value() &&
|
LOperand* remainder = TempRegister();
|
||||||
HasMagicNumberForDivisor(HConstant::cast(right)->Integer32Value()));
|
ASSERT(CpuFeatures::IsSupported(SUDIV) ||
|
||||||
return AssignEnvironment(DefineAsRegister(
|
(right->IsConstant() &&
|
||||||
|
HConstant::cast(right)->HasInteger32Value() &&
|
||||||
|
HasMagicNumberForDivisor(HConstant::cast(right)->Integer32Value())));
|
||||||
|
return AssignEnvironment(DefineAsRegister(
|
||||||
new(zone()) LMathFloorOfDiv(dividend, divisor, remainder)));
|
new(zone()) LMathFloorOfDiv(dividend, divisor, remainder)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1433,25 +1433,68 @@ void LCodeGen::DoMathFloorOfDiv(LMathFloorOfDiv* instr) {
|
|||||||
const Register remainder = ToRegister(instr->temp());
|
const Register remainder = ToRegister(instr->temp());
|
||||||
const Register scratch = scratch0();
|
const Register scratch = scratch0();
|
||||||
|
|
||||||
// We only optimize this for division by constants, because the standard
|
if (!CpuFeatures::IsSupported(SUDIV)) {
|
||||||
// integer division routine is usually slower than transitionning to VFP.
|
// If the CPU doesn't support sdiv instruction, we only optimize when we
|
||||||
// This could be optimized on processors with SDIV available.
|
// have magic numbers for the divisor. The standard integer division routine
|
||||||
ASSERT(instr->right()->IsConstantOperand());
|
// is usually slower than transitionning to VFP.
|
||||||
int32_t divisor = ToInteger32(LConstantOperand::cast(instr->right()));
|
ASSERT(instr->right()->IsConstantOperand());
|
||||||
if (divisor < 0) {
|
int32_t divisor = ToInteger32(LConstantOperand::cast(instr->right()));
|
||||||
__ cmp(left, Operand(0));
|
ASSERT(LChunkBuilder::HasMagicNumberForDivisor(divisor));
|
||||||
|
if (divisor < 0) {
|
||||||
|
__ cmp(left, Operand(0));
|
||||||
|
DeoptimizeIf(eq, instr->environment());
|
||||||
|
}
|
||||||
|
EmitSignedIntegerDivisionByConstant(result,
|
||||||
|
left,
|
||||||
|
divisor,
|
||||||
|
remainder,
|
||||||
|
scratch,
|
||||||
|
instr->environment());
|
||||||
|
// We performed a truncating division. Correct the result if necessary.
|
||||||
|
__ cmp(remainder, Operand(0));
|
||||||
|
__ teq(remainder, Operand(divisor), ne);
|
||||||
|
__ sub(result, result, Operand(1), LeaveCC, mi);
|
||||||
|
} else {
|
||||||
|
CpuFeatures::Scope scope(SUDIV);
|
||||||
|
const Register right = ToRegister(instr->right());
|
||||||
|
|
||||||
|
// Check for x / 0.
|
||||||
|
__ cmp(right, Operand(0));
|
||||||
DeoptimizeIf(eq, instr->environment());
|
DeoptimizeIf(eq, instr->environment());
|
||||||
|
|
||||||
|
// Check for (kMinInt / -1).
|
||||||
|
if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
|
||||||
|
Label left_not_min_int;
|
||||||
|
__ cmp(left, Operand(kMinInt));
|
||||||
|
__ b(ne, &left_not_min_int);
|
||||||
|
__ cmp(right, Operand(-1));
|
||||||
|
DeoptimizeIf(eq, instr->environment());
|
||||||
|
__ bind(&left_not_min_int);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for (0 / -x) that will produce negative zero.
|
||||||
|
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
|
||||||
|
__ cmp(right, Operand(0));
|
||||||
|
__ cmp(left, Operand(0), mi);
|
||||||
|
// "right" can't be null because the code would have already been
|
||||||
|
// deoptimized. The Z flag is set only if (right < 0) and (left == 0).
|
||||||
|
// In this case we need to deoptimize to produce a -0.
|
||||||
|
DeoptimizeIf(eq, instr->environment());
|
||||||
|
}
|
||||||
|
|
||||||
|
Label done;
|
||||||
|
__ sdiv(result, left, right);
|
||||||
|
// If both operands have the same sign then we are done.
|
||||||
|
__ eor(remainder, left, Operand(right), SetCC);
|
||||||
|
__ b(pl, &done);
|
||||||
|
|
||||||
|
// Check if the result needs to be corrected.
|
||||||
|
__ mls(remainder, result, right, left);
|
||||||
|
__ cmp(remainder, Operand(0));
|
||||||
|
__ sub(result, result, Operand(1), LeaveCC, ne);
|
||||||
|
|
||||||
|
__ bind(&done);
|
||||||
}
|
}
|
||||||
EmitSignedIntegerDivisionByConstant(result,
|
|
||||||
left,
|
|
||||||
divisor,
|
|
||||||
remainder,
|
|
||||||
scratch,
|
|
||||||
instr->environment());
|
|
||||||
// We operated a truncating division. Correct the result if necessary.
|
|
||||||
__ cmp(remainder, Operand(0));
|
|
||||||
__ teq(remainder, Operand(divisor), ne);
|
|
||||||
__ sub(result, result, Operand(1), LeaveCC, mi);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
230
test/mjsunit/math-floor-of-div-nosudiv.js
Normal file
230
test/mjsunit/math-floor-of-div-nosudiv.js
Normal file
@ -0,0 +1,230 @@
|
|||||||
|
// Copyright 2012 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 --nouse_inlining --noenable_sudiv
|
||||||
|
|
||||||
|
// Use this function as reference. Make sure it is not inlined.
|
||||||
|
function div(a, b) {
|
||||||
|
return a / b;
|
||||||
|
}
|
||||||
|
|
||||||
|
var limit = 0x1000000;
|
||||||
|
var exhaustive_limit = 100;
|
||||||
|
var step = 10;
|
||||||
|
var values = [0x10000001,
|
||||||
|
0x12345678,
|
||||||
|
-0x789abcdf, // 0x87654321
|
||||||
|
0x01234567,
|
||||||
|
0x76543210,
|
||||||
|
-0x80000000, // 0x80000000
|
||||||
|
0x7fffffff,
|
||||||
|
-0x0fffffff, // 0xf0000001
|
||||||
|
0x00000010,
|
||||||
|
-0x01000000 // 0xff000000
|
||||||
|
];
|
||||||
|
|
||||||
|
function test_div() {
|
||||||
|
var c = 0;
|
||||||
|
for (var k = 0; k <= limit; k++) {
|
||||||
|
if (k > exhaustive_limit) { c += step; k += c; }
|
||||||
|
assertEquals(Math.floor(div(k, 1)), Math.floor(k / 1));
|
||||||
|
assertEquals(Math.floor(div(k, -1)), Math.floor(k / -1));
|
||||||
|
assertEquals(Math.floor(div(k, 2)), Math.floor(k / 2));
|
||||||
|
assertEquals(Math.floor(div(k, -2)), Math.floor(k / -2));
|
||||||
|
assertEquals(Math.floor(div(k, 3)), Math.floor(k / 3));
|
||||||
|
assertEquals(Math.floor(div(k, -3)), Math.floor(k / -3));
|
||||||
|
assertEquals(Math.floor(div(k, 4)), Math.floor(k / 4));
|
||||||
|
assertEquals(Math.floor(div(k, -4)), Math.floor(k / -4));
|
||||||
|
assertEquals(Math.floor(div(k, 5)), Math.floor(k / 5));
|
||||||
|
assertEquals(Math.floor(div(k, -5)), Math.floor(k / -5));
|
||||||
|
assertEquals(Math.floor(div(k, 6)), Math.floor(k / 6));
|
||||||
|
assertEquals(Math.floor(div(k, -6)), Math.floor(k / -6));
|
||||||
|
assertEquals(Math.floor(div(k, 7)), Math.floor(k / 7));
|
||||||
|
assertEquals(Math.floor(div(k, -7)), Math.floor(k / -7));
|
||||||
|
assertEquals(Math.floor(div(k, 8)), Math.floor(k / 8));
|
||||||
|
assertEquals(Math.floor(div(k, -8)), Math.floor(k / -8));
|
||||||
|
assertEquals(Math.floor(div(k, 9)), Math.floor(k / 9));
|
||||||
|
assertEquals(Math.floor(div(k, -9)), Math.floor(k / -9));
|
||||||
|
assertEquals(Math.floor(div(k, 10)), Math.floor(k / 10));
|
||||||
|
assertEquals(Math.floor(div(k, -10)), Math.floor(k / -10));
|
||||||
|
assertEquals(Math.floor(div(k, 11)), Math.floor(k / 11));
|
||||||
|
assertEquals(Math.floor(div(k, -11)), Math.floor(k / -11));
|
||||||
|
assertEquals(Math.floor(div(k, 12)), Math.floor(k / 12));
|
||||||
|
assertEquals(Math.floor(div(k, -12)), Math.floor(k / -12));
|
||||||
|
assertEquals(Math.floor(div(k, 13)), Math.floor(k / 13));
|
||||||
|
assertEquals(Math.floor(div(k, -13)), Math.floor(k / -13));
|
||||||
|
assertEquals(Math.floor(div(k, 14)), Math.floor(k / 14));
|
||||||
|
assertEquals(Math.floor(div(k, -14)), Math.floor(k / -14));
|
||||||
|
assertEquals(Math.floor(div(k, 15)), Math.floor(k / 15));
|
||||||
|
assertEquals(Math.floor(div(k, -15)), Math.floor(k / -15));
|
||||||
|
assertEquals(Math.floor(div(k, 16)), Math.floor(k / 16));
|
||||||
|
assertEquals(Math.floor(div(k, -16)), Math.floor(k / -16));
|
||||||
|
assertEquals(Math.floor(div(k, 17)), Math.floor(k / 17));
|
||||||
|
assertEquals(Math.floor(div(k, -17)), Math.floor(k / -17));
|
||||||
|
assertEquals(Math.floor(div(k, 18)), Math.floor(k / 18));
|
||||||
|
assertEquals(Math.floor(div(k, -18)), Math.floor(k / -18));
|
||||||
|
assertEquals(Math.floor(div(k, 19)), Math.floor(k / 19));
|
||||||
|
assertEquals(Math.floor(div(k, -19)), Math.floor(k / -19));
|
||||||
|
assertEquals(Math.floor(div(k, 20)), Math.floor(k / 20));
|
||||||
|
assertEquals(Math.floor(div(k, -20)), Math.floor(k / -20));
|
||||||
|
assertEquals(Math.floor(div(k, 21)), Math.floor(k / 21));
|
||||||
|
assertEquals(Math.floor(div(k, -21)), Math.floor(k / -21));
|
||||||
|
assertEquals(Math.floor(div(k, 22)), Math.floor(k / 22));
|
||||||
|
assertEquals(Math.floor(div(k, -22)), Math.floor(k / -22));
|
||||||
|
assertEquals(Math.floor(div(k, 23)), Math.floor(k / 23));
|
||||||
|
assertEquals(Math.floor(div(k, -23)), Math.floor(k / -23));
|
||||||
|
assertEquals(Math.floor(div(k, 24)), Math.floor(k / 24));
|
||||||
|
assertEquals(Math.floor(div(k, -24)), Math.floor(k / -24));
|
||||||
|
assertEquals(Math.floor(div(k, 25)), Math.floor(k / 25));
|
||||||
|
assertEquals(Math.floor(div(k, -25)), Math.floor(k / -25));
|
||||||
|
assertEquals(Math.floor(div(k, 125)), Math.floor(k / 125));
|
||||||
|
assertEquals(Math.floor(div(k, -125)), Math.floor(k / -125));
|
||||||
|
assertEquals(Math.floor(div(k, 625)), Math.floor(k / 625));
|
||||||
|
assertEquals(Math.floor(div(k, -625)), Math.floor(k / -625));
|
||||||
|
}
|
||||||
|
c = 0;
|
||||||
|
for (var k = 0; k <= limit; k++) {
|
||||||
|
if (k > exhaustive_limit) { c += step; k += c; }
|
||||||
|
assertEquals(Math.floor(div(-k, 1)), Math.floor(-k / 1));
|
||||||
|
assertEquals(Math.floor(div(-k, -1)), Math.floor(-k / -1));
|
||||||
|
assertEquals(Math.floor(div(-k, 2)), Math.floor(-k / 2));
|
||||||
|
assertEquals(Math.floor(div(-k, -2)), Math.floor(-k / -2));
|
||||||
|
assertEquals(Math.floor(div(-k, 3)), Math.floor(-k / 3));
|
||||||
|
assertEquals(Math.floor(div(-k, -3)), Math.floor(-k / -3));
|
||||||
|
assertEquals(Math.floor(div(-k, 4)), Math.floor(-k / 4));
|
||||||
|
assertEquals(Math.floor(div(-k, -4)), Math.floor(-k / -4));
|
||||||
|
assertEquals(Math.floor(div(-k, 5)), Math.floor(-k / 5));
|
||||||
|
assertEquals(Math.floor(div(-k, -5)), Math.floor(-k / -5));
|
||||||
|
assertEquals(Math.floor(div(-k, 6)), Math.floor(-k / 6));
|
||||||
|
assertEquals(Math.floor(div(-k, -6)), Math.floor(-k / -6));
|
||||||
|
assertEquals(Math.floor(div(-k, 7)), Math.floor(-k / 7));
|
||||||
|
assertEquals(Math.floor(div(-k, -7)), Math.floor(-k / -7));
|
||||||
|
assertEquals(Math.floor(div(-k, 8)), Math.floor(-k / 8));
|
||||||
|
assertEquals(Math.floor(div(-k, -8)), Math.floor(-k / -8));
|
||||||
|
assertEquals(Math.floor(div(-k, 9)), Math.floor(-k / 9));
|
||||||
|
assertEquals(Math.floor(div(-k, -9)), Math.floor(-k / -9));
|
||||||
|
assertEquals(Math.floor(div(-k, 10)), Math.floor(-k / 10));
|
||||||
|
assertEquals(Math.floor(div(-k, -10)), Math.floor(-k / -10));
|
||||||
|
assertEquals(Math.floor(div(-k, 11)), Math.floor(-k / 11));
|
||||||
|
assertEquals(Math.floor(div(-k, -11)), Math.floor(-k / -11));
|
||||||
|
assertEquals(Math.floor(div(-k, 12)), Math.floor(-k / 12));
|
||||||
|
assertEquals(Math.floor(div(-k, -12)), Math.floor(-k / -12));
|
||||||
|
assertEquals(Math.floor(div(-k, 13)), Math.floor(-k / 13));
|
||||||
|
assertEquals(Math.floor(div(-k, -13)), Math.floor(-k / -13));
|
||||||
|
assertEquals(Math.floor(div(-k, 14)), Math.floor(-k / 14));
|
||||||
|
assertEquals(Math.floor(div(-k, -14)), Math.floor(-k / -14));
|
||||||
|
assertEquals(Math.floor(div(-k, 15)), Math.floor(-k / 15));
|
||||||
|
assertEquals(Math.floor(div(-k, -15)), Math.floor(-k / -15));
|
||||||
|
assertEquals(Math.floor(div(-k, 16)), Math.floor(-k / 16));
|
||||||
|
assertEquals(Math.floor(div(-k, -16)), Math.floor(-k / -16));
|
||||||
|
assertEquals(Math.floor(div(-k, 17)), Math.floor(-k / 17));
|
||||||
|
assertEquals(Math.floor(div(-k, -17)), Math.floor(-k / -17));
|
||||||
|
assertEquals(Math.floor(div(-k, 18)), Math.floor(-k / 18));
|
||||||
|
assertEquals(Math.floor(div(-k, -18)), Math.floor(-k / -18));
|
||||||
|
assertEquals(Math.floor(div(-k, 19)), Math.floor(-k / 19));
|
||||||
|
assertEquals(Math.floor(div(-k, -19)), Math.floor(-k / -19));
|
||||||
|
assertEquals(Math.floor(div(-k, 20)), Math.floor(-k / 20));
|
||||||
|
assertEquals(Math.floor(div(-k, -20)), Math.floor(-k / -20));
|
||||||
|
assertEquals(Math.floor(div(-k, 21)), Math.floor(-k / 21));
|
||||||
|
assertEquals(Math.floor(div(-k, -21)), Math.floor(-k / -21));
|
||||||
|
assertEquals(Math.floor(div(-k, 22)), Math.floor(-k / 22));
|
||||||
|
assertEquals(Math.floor(div(-k, -22)), Math.floor(-k / -22));
|
||||||
|
assertEquals(Math.floor(div(-k, 23)), Math.floor(-k / 23));
|
||||||
|
assertEquals(Math.floor(div(-k, -23)), Math.floor(-k / -23));
|
||||||
|
assertEquals(Math.floor(div(-k, 24)), Math.floor(-k / 24));
|
||||||
|
assertEquals(Math.floor(div(-k, -24)), Math.floor(-k / -24));
|
||||||
|
assertEquals(Math.floor(div(-k, 25)), Math.floor(-k / 25));
|
||||||
|
assertEquals(Math.floor(div(-k, -25)), Math.floor(-k / -25));
|
||||||
|
assertEquals(Math.floor(div(-k, 125)), Math.floor(-k / 125));
|
||||||
|
assertEquals(Math.floor(div(-k, -125)), Math.floor(-k / -125));
|
||||||
|
assertEquals(Math.floor(div(-k, 625)), Math.floor(-k / 625));
|
||||||
|
assertEquals(Math.floor(div(-k, -625)), Math.floor(-k / -625));
|
||||||
|
}
|
||||||
|
// Test for edge cases.
|
||||||
|
// Use (values[key] | 0) to force the integer type.
|
||||||
|
for (var i = 0; i < values.length; i++) {
|
||||||
|
for (var j = 0; j < values.length; j++) {
|
||||||
|
assertEquals(Math.floor(div((values[i] | 0), (values[j] | 0))),
|
||||||
|
Math.floor((values[i] | 0) / (values[j] | 0)));
|
||||||
|
assertEquals(Math.floor(div(-(values[i] | 0), (values[j] | 0))),
|
||||||
|
Math.floor(-(values[i] | 0) / (values[j] | 0)));
|
||||||
|
assertEquals(Math.floor(div((values[i] | 0), -(values[j] | 0))),
|
||||||
|
Math.floor((values[i] | 0) / -(values[j] | 0)));
|
||||||
|
assertEquals(Math.floor(div(-(values[i] | 0), -(values[j] | 0))),
|
||||||
|
Math.floor(-(values[i] | 0) / -(values[j] | 0)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test_div();
|
||||||
|
%OptimizeFunctionOnNextCall(test_div);
|
||||||
|
test_div();
|
||||||
|
|
||||||
|
// Test for negative zero, overflow and division by 0.
|
||||||
|
// Separate the tests to prevent deoptimizations from making the other optimized
|
||||||
|
// test unreachable.
|
||||||
|
|
||||||
|
function IsNegativeZero(x) {
|
||||||
|
assertTrue(x == 0); // Is 0 or -0.
|
||||||
|
var y = 1 / x;
|
||||||
|
assertFalse(isFinite(y));
|
||||||
|
return y < 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_div_deopt_minus_zero() {
|
||||||
|
var zero_in_array = [0];
|
||||||
|
for (var i = 0; i < 2; ++i) {
|
||||||
|
assertTrue(IsNegativeZero(Math.floor((zero_in_array[0] | 0) / -1)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_div_deopt_overflow() {
|
||||||
|
// We box the value in an array to avoid constant propagation.
|
||||||
|
var min_int_in_array = [-2147483648];
|
||||||
|
for (var i = 0; i < 2; ++i) {
|
||||||
|
// We use '| 0' to force the representation to int32.
|
||||||
|
assertEquals(-min_int_in_array[0],
|
||||||
|
Math.floor((min_int_in_array[0] | 0) / -1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_div_deopt_div_by_zero() {
|
||||||
|
for (var i = 0; i < 2; ++i) {
|
||||||
|
assertEquals(div(i, 0),
|
||||||
|
Math.floor(i / 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test_div_deopt_minus_zero();
|
||||||
|
test_div_deopt_overflow();
|
||||||
|
test_div_deopt_div_by_zero();
|
||||||
|
%OptimizeFunctionOnNextCall(test_div_deopt_minus_zero);
|
||||||
|
%OptimizeFunctionOnNextCall(test_div_deopt_overflow);
|
||||||
|
%OptimizeFunctionOnNextCall(test_div_deopt_div_by_zero);
|
||||||
|
test_div_deopt_minus_zero();
|
||||||
|
test_div_deopt_overflow();
|
||||||
|
test_div_deopt_div_by_zero();
|
@ -25,7 +25,7 @@
|
|||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
// Flags: --allow-natives-syntax --nouse_inlining
|
// Flags: --allow-natives-syntax --nouse_inlining --enable_sudiv
|
||||||
|
|
||||||
// Use this function as reference. Make sure it is not inlined.
|
// Use this function as reference. Make sure it is not inlined.
|
||||||
function div(a, b) {
|
function div(a, b) {
|
||||||
@ -184,7 +184,7 @@ test_div();
|
|||||||
%OptimizeFunctionOnNextCall(test_div);
|
%OptimizeFunctionOnNextCall(test_div);
|
||||||
test_div();
|
test_div();
|
||||||
|
|
||||||
// Test for negative zero and overflow.
|
// Test for negative zero, overflow and division by 0.
|
||||||
// Separate the tests to prevent deoptimizations from making the other optimized
|
// Separate the tests to prevent deoptimizations from making the other optimized
|
||||||
// test unreachable.
|
// test unreachable.
|
||||||
|
|
||||||
@ -197,20 +197,34 @@ function IsNegativeZero(x) {
|
|||||||
|
|
||||||
function test_div_deopt_minus_zero() {
|
function test_div_deopt_minus_zero() {
|
||||||
var zero_in_array = [0];
|
var zero_in_array = [0];
|
||||||
assertTrue(IsNegativeZero(Math.floor((zero_in_array[0] | 0) / -1)));
|
for (var i = 0; i < 2; ++i) {
|
||||||
|
assertTrue(IsNegativeZero(Math.floor((zero_in_array[0] | 0) / -1)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_div_deopt_overflow() {
|
function test_div_deopt_overflow() {
|
||||||
// We box the value in an array to avoid constant propagation.
|
// We box the value in an array to avoid constant propagation.
|
||||||
var min_int_in_array = [-2147483648];
|
var min_int_in_array = [-2147483648];
|
||||||
// We use '| 0' to force the representation to int32.
|
for (var i = 0; i < 2; ++i) {
|
||||||
assertEquals(-min_int_in_array[0],
|
// We use '| 0' to force the representation to int32.
|
||||||
Math.floor((min_int_in_array[0] | 0) / -1));
|
assertEquals(-min_int_in_array[0],
|
||||||
|
Math.floor((min_int_in_array[0] | 0) / -1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_div_deopt_div_by_zero() {
|
||||||
|
for (var i = 0; i < 2; ++i) {
|
||||||
|
assertEquals(div(i, 0),
|
||||||
|
Math.floor(i / 0));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
test_div_deopt_minus_zero();
|
test_div_deopt_minus_zero();
|
||||||
test_div_deopt_overflow();
|
test_div_deopt_overflow();
|
||||||
|
test_div_deopt_div_by_zero();
|
||||||
%OptimizeFunctionOnNextCall(test_div_deopt_minus_zero);
|
%OptimizeFunctionOnNextCall(test_div_deopt_minus_zero);
|
||||||
%OptimizeFunctionOnNextCall(test_div_deopt_overflow);
|
%OptimizeFunctionOnNextCall(test_div_deopt_overflow);
|
||||||
|
%OptimizeFunctionOnNextCall(test_div_deopt_div_by_zero);
|
||||||
test_div_deopt_minus_zero();
|
test_div_deopt_minus_zero();
|
||||||
test_div_deopt_overflow();
|
test_div_deopt_overflow();
|
||||||
|
test_div_deopt_div_by_zero();
|
||||||
|
@ -76,6 +76,10 @@ regress/regress-crbug-160010: PASS, SKIP if $mode == debug
|
|||||||
d8-os: PASS, SKIP if ($isolates || $arch == android_arm || $arch == android_ia32)
|
d8-os: PASS, SKIP if ($isolates || $arch == android_arm || $arch == android_ia32)
|
||||||
tools/tickprocessor: PASS, SKIP if ($arch == android_arm || $arch == android_ia32)
|
tools/tickprocessor: PASS, SKIP if ($arch == android_arm || $arch == android_ia32)
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
# This test is the same as math-floor-of-div for non ARM architectures.
|
||||||
|
math-floor-of-div-nosudiv: PASS, SKIP if ($arch != arm && $arch != android_arm)
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
[ $arch == arm || $arch == android_arm ]
|
[ $arch == arm || $arch == android_arm ]
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user