Commit 003b2622 authored by Richard Stotz's avatar Richard Stotz Committed by Commit Bot

[wasm][liftoff][x64] Add saturated conversion float->int64

Bug: v8:10520
Change-Id: Iad8d35e58b766a9e4d3013f90fd4d7fb68708fa7
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2201577
Commit-Queue: Richard Stotz <rstz@chromium.org>
Reviewed-by: 's avatarAndreas Haas <ahaas@chromium.org>
Cr-Commit-Position: refs/heads/master@{#67866}
parent e0246541
...@@ -1923,6 +1923,18 @@ bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode, ...@@ -1923,6 +1923,18 @@ bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode,
case kExprI32UConvertSatF64: case kExprI32UConvertSatF64:
bailout(kNonTrappingFloatToInt, "kExprI32UConvertSatF64"); bailout(kNonTrappingFloatToInt, "kExprI32UConvertSatF64");
return true; return true;
case kExprI64SConvertSatF32:
bailout(kNonTrappingFloatToInt, "kExprI64SConvertSatF32");
return true;
case kExprI64UConvertSatF32:
bailout(kNonTrappingFloatToInt, "kExprI64UConvertSatF32");
return true;
case kExprI64SConvertSatF64:
bailout(kNonTrappingFloatToInt, "kExprI64SConvertSatF64");
return true;
case kExprI64UConvertSatF64:
bailout(kNonTrappingFloatToInt, "kExprI64UConvertSatF64");
return true;
case kExprI32ReinterpretF32: case kExprI32ReinterpretF32:
vmov(dst.gp(), liftoff::GetFloatRegister(src.fp())); vmov(dst.gp(), liftoff::GetFloatRegister(src.fp()));
return true; return true;
......
...@@ -970,6 +970,18 @@ bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode, ...@@ -970,6 +970,18 @@ bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode,
case kExprI32UConvertSatF64: case kExprI32UConvertSatF64:
bailout(kNonTrappingFloatToInt, "kExprI32UConvertSatF64"); bailout(kNonTrappingFloatToInt, "kExprI32UConvertSatF64");
return true; return true;
case kExprI64SConvertSatF32:
bailout(kNonTrappingFloatToInt, "kExprI64SConvertSatF32");
return true;
case kExprI64UConvertSatF32:
bailout(kNonTrappingFloatToInt, "kExprI64UConvertSatF32");
return true;
case kExprI64SConvertSatF64:
bailout(kNonTrappingFloatToInt, "kExprI64SConvertSatF64");
return true;
case kExprI64UConvertSatF64:
bailout(kNonTrappingFloatToInt, "kExprI64UConvertSatF64");
return true;
case kExprI32ReinterpretF32: case kExprI32ReinterpretF32:
Fmov(dst.gp().W(), src.fp().S()); Fmov(dst.gp().W(), src.fp().S());
return true; return true;
......
...@@ -1703,6 +1703,18 @@ bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode, ...@@ -1703,6 +1703,18 @@ bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode,
case kExprI32UConvertSatF64: case kExprI32UConvertSatF64:
bailout(kNonTrappingFloatToInt, "kExprI32UConvertSatF64"); bailout(kNonTrappingFloatToInt, "kExprI32UConvertSatF64");
return true; return true;
case kExprI64SConvertSatF32:
bailout(kNonTrappingFloatToInt, "kExprI64SConvertSatF32");
return true;
case kExprI64UConvertSatF32:
bailout(kNonTrappingFloatToInt, "kExprI64UConvertSatF32");
return true;
case kExprI64SConvertSatF64:
bailout(kNonTrappingFloatToInt, "kExprI64SConvertSatF64");
return true;
case kExprI64UConvertSatF64:
bailout(kNonTrappingFloatToInt, "kExprI64UConvertSatF64");
return true;
case kExprI32ReinterpretF32: case kExprI32ReinterpretF32:
Movd(dst.gp(), src.fp()); Movd(dst.gp(), src.fp());
return true; return true;
......
...@@ -1093,10 +1093,10 @@ class LiftoffCompiler { ...@@ -1093,10 +1093,10 @@ class LiftoffCompiler {
CASE_TYPE_CONVERSION(I32UConvertSatF32, I32, F32, nullptr, kNoTrap) CASE_TYPE_CONVERSION(I32UConvertSatF32, I32, F32, nullptr, kNoTrap)
CASE_TYPE_CONVERSION(I32SConvertSatF64, I32, F64, nullptr, kNoTrap) CASE_TYPE_CONVERSION(I32SConvertSatF64, I32, F64, nullptr, kNoTrap)
CASE_TYPE_CONVERSION(I32UConvertSatF64, I32, F64, nullptr, kNoTrap) CASE_TYPE_CONVERSION(I32UConvertSatF64, I32, F64, nullptr, kNoTrap)
case kExprI64SConvertSatF32: CASE_TYPE_CONVERSION(I64SConvertSatF32, I64, F32, nullptr, kNoTrap)
case kExprI64UConvertSatF32: CASE_TYPE_CONVERSION(I64UConvertSatF32, I64, F32, nullptr, kNoTrap)
case kExprI64SConvertSatF64: CASE_TYPE_CONVERSION(I64SConvertSatF64, I64, F64, nullptr, kNoTrap)
case kExprI64UConvertSatF64: CASE_TYPE_CONVERSION(I64UConvertSatF64, I64, F64, nullptr, kNoTrap)
return unsupported(decoder, kNonTrappingFloatToInt, return unsupported(decoder, kNonTrappingFloatToInt,
WasmOpcodes::OpcodeName(opcode)); WasmOpcodes::OpcodeName(opcode));
default: default:
......
...@@ -1281,6 +1281,18 @@ bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode, ...@@ -1281,6 +1281,18 @@ bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode,
case kExprI32UConvertSatF64: case kExprI32UConvertSatF64:
bailout(kNonTrappingFloatToInt, "kExprI32UConvertSatF64"); bailout(kNonTrappingFloatToInt, "kExprI32UConvertSatF64");
return true; return true;
case kExprI64SConvertSatF32:
bailout(kNonTrappingFloatToInt, "kExprI64SConvertSatF32");
return true;
case kExprI64UConvertSatF32:
bailout(kNonTrappingFloatToInt, "kExprI64UConvertSatF32");
return true;
case kExprI64SConvertSatF64:
bailout(kNonTrappingFloatToInt, "kExprI64SConvertSatF64");
return true;
case kExprI64UConvertSatF64:
bailout(kNonTrappingFloatToInt, "kExprI64UConvertSatF64");
return true;
case kExprI32ReinterpretF32: case kExprI32ReinterpretF32:
mfc1(dst.gp(), src.fp()); mfc1(dst.gp(), src.fp());
return true; return true;
......
...@@ -1189,6 +1189,18 @@ bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode, ...@@ -1189,6 +1189,18 @@ bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode,
case kExprI32UConvertSatF64: case kExprI32UConvertSatF64:
bailout(kNonTrappingFloatToInt, "kExprI32UConvertSatF64"); bailout(kNonTrappingFloatToInt, "kExprI32UConvertSatF64");
return true; return true;
case kExprI64SConvertSatF32:
bailout(kNonTrappingFloatToInt, "kExprI64SConvertSatF32");
return true;
case kExprI64UConvertSatF32:
bailout(kNonTrappingFloatToInt, "kExprI64UConvertSatF32");
return true;
case kExprI64SConvertSatF64:
bailout(kNonTrappingFloatToInt, "kExprI64SConvertSatF64");
return true;
case kExprI64UConvertSatF64:
bailout(kNonTrappingFloatToInt, "kExprI64UConvertSatF64");
return true;
default: default:
return false; return false;
} }
......
...@@ -1697,7 +1697,7 @@ inline bool EmitSatTruncateFloatToInt(LiftoffAssembler* assm, Register dst, ...@@ -1697,7 +1697,7 @@ inline bool EmitSatTruncateFloatToInt(LiftoffAssembler* assm, Register dst,
Label done; Label done;
Label not_nan; Label not_nan;
Label src_pos; Label src_positive;
DoubleRegister rounded = kScratchDoubleReg; DoubleRegister rounded = kScratchDoubleReg;
DoubleRegister converted_back = kScratchDoubleReg2; DoubleRegister converted_back = kScratchDoubleReg2;
...@@ -1728,19 +1728,78 @@ inline bool EmitSatTruncateFloatToInt(LiftoffAssembler* assm, Register dst, ...@@ -1728,19 +1728,78 @@ inline bool EmitSatTruncateFloatToInt(LiftoffAssembler* assm, Register dst,
__ xorpd(zero_reg, zero_reg); __ xorpd(zero_reg, zero_reg);
// if out-of-bounds, check if src is positive
if (std::is_same<double, src_type>::value) { // f64 if (std::is_same<double, src_type>::value) { // f64
__ Ucomisd(src, kScratchDoubleReg); __ Ucomisd(src, zero_reg);
} else { // f32 } else { // f32
__ Ucomiss(src, kScratchDoubleReg); __ Ucomiss(src, zero_reg);
}
__ j(above, &src_positive);
if (std::is_same<int32_t, dst_type>::value ||
std::is_same<uint32_t, dst_type>::value) { // i32
__ movl(
dst,
Immediate(static_cast<int32_t>(std::numeric_limits<dst_type>::min())));
} else if (std::is_same<int64_t, dst_type>::value) { // i64s
__ movq(dst, Immediate64(std::numeric_limits<dst_type>::min()));
} else {
UNREACHABLE();
} }
__ j(above, &src_pos);
__ movl(dst, Immediate(std::numeric_limits<dst_type>::min()));
__ jmp(&done); __ jmp(&done);
__ bind(&src_pos); __ bind(&src_positive);
if (std::is_same<int32_t, dst_type>::value ||
std::is_same<uint32_t, dst_type>::value) { // i32
__ movl(
dst,
Immediate(static_cast<int32_t>(std::numeric_limits<dst_type>::max())));
} else if (std::is_same<int64_t, dst_type>::value) { // i64s
__ movq(dst, Immediate64(std::numeric_limits<dst_type>::max()));
} else {
UNREACHABLE();
}
__ bind(&done);
return true;
}
template <typename src_type>
inline bool EmitSatTruncateFloatToUInt64(LiftoffAssembler* assm, Register dst,
DoubleRegister src) {
if (!CpuFeatures::IsSupported(SSE4_1)) {
__ bailout(kMissingCPUFeature, "no SSE4.1");
return true;
}
CpuFeatureScope feature(assm, SSE4_1);
Label done;
Label neg_or_nan;
Label overflow;
__ movl(dst, Immediate(std::numeric_limits<dst_type>::max())); DoubleRegister zero_reg = kScratchDoubleReg;
__ xorpd(zero_reg, zero_reg);
if (std::is_same<double, src_type>::value) { // f64
__ Ucomisd(src, zero_reg);
} else { // f32
__ Ucomiss(src, zero_reg);
}
// Check if NaN
__ j(parity_even, &neg_or_nan);
__ j(below, &neg_or_nan);
if (std::is_same<double, src_type>::value) { // f64
__ Cvttsd2uiq(dst, src, &overflow);
} else { // f32
__ Cvttss2uiq(dst, src, &overflow);
}
__ jmp(&done);
__ bind(&neg_or_nan);
__ movq(dst, zero_reg);
__ jmp(&done);
__ bind(&overflow);
__ movq(dst, Immediate64(std::numeric_limits<uint64_t>::max()));
__ bind(&done); __ bind(&done);
return true; return true;
} }
...@@ -1800,6 +1859,20 @@ bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode, ...@@ -1800,6 +1859,20 @@ bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode,
Cvttsd2uiq(dst.gp(), src.fp(), trap); Cvttsd2uiq(dst.gp(), src.fp(), trap);
return true; return true;
} }
case kExprI64SConvertSatF32:
return liftoff::EmitSatTruncateFloatToInt<int64_t, float>(this, dst.gp(),
src.fp());
case kExprI64UConvertSatF32: {
return liftoff::EmitSatTruncateFloatToUInt64<float>(this, dst.gp(),
src.fp());
}
case kExprI64SConvertSatF64:
return liftoff::EmitSatTruncateFloatToInt<int64_t, double>(this, dst.gp(),
src.fp());
case kExprI64UConvertSatF64: {
return liftoff::EmitSatTruncateFloatToUInt64<double>(this, dst.gp(),
src.fp());
}
case kExprI64UConvertI32: case kExprI64UConvertI32:
AssertZeroExtended(src.gp()); AssertZeroExtended(src.gp());
if (dst.gp() != src.gp()) movl(dst.gp(), src.gp()); if (dst.gp() != src.gp()) movl(dst.gp(), src.gp());
......
...@@ -790,6 +790,10 @@ void WasmGenerator::Generate<ValueType::kI32>(DataRange* data) { ...@@ -790,6 +790,10 @@ void WasmGenerator::Generate<ValueType::kI32>(DataRange* data) {
&WasmGenerator::op<kExprI32UConvertSatF32, ValueType::kF32>, &WasmGenerator::op<kExprI32UConvertSatF32, ValueType::kF32>,
&WasmGenerator::op<kExprI32SConvertSatF64, ValueType::kF64>, &WasmGenerator::op<kExprI32SConvertSatF64, ValueType::kF64>,
&WasmGenerator::op<kExprI32UConvertSatF64, ValueType::kF64>, &WasmGenerator::op<kExprI32UConvertSatF64, ValueType::kF64>,
&WasmGenerator::op<kExprI64SConvertSatF32, ValueType::kF32>,
&WasmGenerator::op<kExprI64UConvertSatF32, ValueType::kF32>,
&WasmGenerator::op<kExprI64SConvertSatF64, ValueType::kF64>,
&WasmGenerator::op<kExprI64UConvertSatF64, ValueType::kF64>,
&WasmGenerator::block<ValueType::kI32>, &WasmGenerator::block<ValueType::kI32>,
&WasmGenerator::loop<ValueType::kI32>, &WasmGenerator::loop<ValueType::kI32>,
......
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