Commit 2358a5be authored by ahaas's avatar ahaas Committed by Commit bot

[turbofan] Fixed a bug in TryTruncateFloatXXToInt64 with INT64_MIN.

On x64 and arm64 TryTruncateFloatXXToInt64 incorrectly failed when the
input was INT64_MIN.

R=bradnelson@chromium.org, mstarzinger@chromium.org, v8-arm-ports@googlegroups.com

Review URL: https://codereview.chromium.org/1526293002

Cr-Commit-Position: refs/heads/master@{#32908}
parent ba1d9af8
......@@ -1041,20 +1041,30 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
case kArm64Float32ToInt64:
__ Fcvtzs(i.OutputRegister64(), i.InputFloat32Register(0));
if (i.OutputCount() > 1) {
__ Mov(i.OutputRegister(1), 1);
Label done;
__ Cmp(i.OutputRegister(0), 1);
__ Ccmp(i.OutputRegister(0), -1, VFlag, vc);
__ Fccmp(i.InputFloat32Register(0), i.InputFloat32Register(0), VFlag,
vc);
__ Cset(i.OutputRegister(1), vc);
__ B(vc, &done);
__ Fcmp(i.InputFloat32Register(0), static_cast<float>(INT64_MIN));
__ Cset(i.OutputRegister(1), eq);
__ Bind(&done);
}
break;
case kArm64Float64ToInt64:
__ Fcvtzs(i.OutputRegister(0), i.InputDoubleRegister(0));
if (i.OutputCount() > 1) {
__ Mov(i.OutputRegister(1), 1);
Label done;
__ Cmp(i.OutputRegister(0), 1);
__ Ccmp(i.OutputRegister(0), -1, VFlag, vc);
__ Fccmp(i.InputDoubleRegister(0), i.InputDoubleRegister(0), VFlag, vc);
__ Cset(i.OutputRegister(1), vc);
__ B(vc, &done);
__ Fcmp(i.InputDoubleRegister(0), static_cast<double>(INT64_MIN));
__ Cset(i.OutputRegister(1), eq);
__ Bind(&done);
}
break;
case kArm64Float32ToUint64:
......
......@@ -1053,8 +1053,26 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
__ Cvttss2siq(i.OutputRegister(), i.InputOperand(0));
}
if (instr->OutputCount() > 1) {
__ Set(i.OutputRegister(1), 0x8000000000000000);
__ subq(i.OutputRegister(1), i.OutputRegister(0));
__ Set(i.OutputRegister(1), 1);
Label done;
Label fail;
__ Move(kScratchDoubleReg, static_cast<float>(INT64_MIN));
if (instr->InputAt(0)->IsDoubleRegister()) {
__ Ucomiss(kScratchDoubleReg, i.InputDoubleRegister(0));
} else {
__ Ucomiss(kScratchDoubleReg, i.InputOperand(0));
}
// If the input is NaN, then the conversion fails.
__ j(parity_even, &fail);
// If the input is INT64_MIN, then the conversion succeeds.
__ j(equal, &done);
__ cmpq(i.OutputRegister(0), Immediate(1));
// If the conversion results in INT64_MIN, but the input was not
// INT64_MIN, then the conversion fails.
__ j(no_overflow, &done);
__ bind(&fail);
__ Set(i.OutputRegister(1), 0);
__ bind(&done);
}
break;
case kSSEFloat64ToInt64:
......@@ -1064,8 +1082,26 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
__ Cvttsd2siq(i.OutputRegister(0), i.InputOperand(0));
}
if (instr->OutputCount() > 1) {
__ Set(i.OutputRegister(1), 0x8000000000000000);
__ subq(i.OutputRegister(1), i.OutputRegister(0));
__ Set(i.OutputRegister(1), 1);
Label done;
Label fail;
__ Move(kScratchDoubleReg, static_cast<double>(INT64_MIN));
if (instr->InputAt(0)->IsDoubleRegister()) {
__ Ucomisd(kScratchDoubleReg, i.InputDoubleRegister(0));
} else {
__ Ucomisd(kScratchDoubleReg, i.InputOperand(0));
}
// If the input is NaN, then the conversion fails.
__ j(parity_even, &fail);
// If the input is INT64_MIN, then the conversion succeeds.
__ j(equal, &done);
__ cmpq(i.OutputRegister(0), Immediate(1));
// If the conversion results in INT64_MIN, but the input was not
// INT64_MIN, then the conversion fails.
__ j(no_overflow, &done);
__ bind(&fail);
__ Set(i.OutputRegister(1), 0);
__ bind(&done);
}
break;
case kSSEFloat32ToUint64: {
......
......@@ -5465,7 +5465,8 @@ TEST(RunTryTruncateFloat32ToInt64WithoutCheck) {
FOR_INT64_INPUTS(i) {
float input = static_cast<float>(*i);
if (input < 9223372036854775808.0 && input > -9223372036854775809.0) {
if (input < static_cast<float>(INT64_MAX) &&
input >= static_cast<float>(INT64_MIN)) {
CHECK_EQ(static_cast<int64_t>(input), m.Call(input));
}
}
......@@ -5482,7 +5483,8 @@ TEST(RunTryTruncateFloat32ToInt64WithCheck) {
m.Return(val);
FOR_FLOAT32_INPUTS(i) {
if (*i < 9223372036854775808.0 && *i > -9223372036854775809.0) {
if (*i < static_cast<float>(INT64_MAX) &&
*i >= static_cast<float>(INT64_MIN)) {
CHECK_EQ(static_cast<int64_t>(*i), m.Call(*i));
CHECK_NE(0, success);
} else {
......@@ -5514,7 +5516,8 @@ TEST(RunTryTruncateFloat64ToInt64WithCheck) {
m.Return(val);
FOR_FLOAT64_INPUTS(i) {
if (*i < 9223372036854775808.0 && *i > -9223372036854775809.0) {
if (*i < static_cast<double>(INT64_MAX) &&
*i >= static_cast<double>(INT64_MIN)) {
// Conversions within this range should succeed.
CHECK_EQ(static_cast<int64_t>(*i), m.Call(*i));
CHECK_NE(0, success);
......
This diff is collapsed.
......@@ -3378,7 +3378,8 @@ TEST(Run_Wasm_I64SConvertF32) {
BUILD(r, WASM_I64_SCONVERT_F32(WASM_GET_LOCAL(0)));
FOR_FLOAT32_INPUTS(i) {
if (*i < 9223372036854775808.0 && *i > -9223372036854775809.0) {
if (*i < static_cast<float>(INT64_MAX) &&
*i >= static_cast<float>(INT64_MIN)) {
CHECK_EQ(static_cast<int64_t>(*i), r.Call(*i));
} else {
CHECK_TRAP64(r.Call(*i));
......@@ -3392,7 +3393,8 @@ TEST(Run_Wasm_I64SConvertF64) {
BUILD(r, WASM_I64_SCONVERT_F64(WASM_GET_LOCAL(0)));
FOR_FLOAT64_INPUTS(i) {
if (*i < 9223372036854775808.0 && *i > -9223372036854775809.0) {
if (*i < static_cast<double>(INT64_MAX) &&
*i >= static_cast<double>(INT64_MIN)) {
CHECK_EQ(static_cast<int64_t>(*i), r.Call(*i));
} else {
CHECK_TRAP64(r.Call(*i));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment