Commit 73bf6079 authored by Richard Stotz's avatar Richard Stotz Committed by Commit Bot

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

We implement the conversions via C functions (external references)
because 64-bit conversions are difficult to implement on ia32 and
would not be significantly faster.

Bug: v8:10520
Change-Id: I3573d30bf6b3d558f708c7e0273f027c30a1a771
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2202988
Commit-Queue: Richard Stotz <rstz@chromium.org>
Reviewed-by: 's avatarClemens Backes <clemensb@chromium.org>
Reviewed-by: 's avatarAndreas Haas <ahaas@chromium.org>
Cr-Commit-Position: refs/heads/master@{#67883}
parent 3cc981cb
......@@ -277,6 +277,14 @@ FUNCTION_REFERENCE(wasm_float32_to_int64, wasm::float32_to_int64_wrapper)
FUNCTION_REFERENCE(wasm_float32_to_uint64, wasm::float32_to_uint64_wrapper)
FUNCTION_REFERENCE(wasm_float64_to_int64, wasm::float64_to_int64_wrapper)
FUNCTION_REFERENCE(wasm_float64_to_uint64, wasm::float64_to_uint64_wrapper)
FUNCTION_REFERENCE(wasm_float32_to_int64_sat,
wasm::float32_to_int64_sat_wrapper)
FUNCTION_REFERENCE(wasm_float32_to_uint64_sat,
wasm::float32_to_uint64_sat_wrapper)
FUNCTION_REFERENCE(wasm_float64_to_int64_sat,
wasm::float64_to_int64_sat_wrapper)
FUNCTION_REFERENCE(wasm_float64_to_uint64_sat,
wasm::float64_to_uint64_sat_wrapper)
FUNCTION_REFERENCE(wasm_int64_div, wasm::int64_div_wrapper)
FUNCTION_REFERENCE(wasm_int64_mod, wasm::int64_mod_wrapper)
FUNCTION_REFERENCE(wasm_uint64_div, wasm::uint64_div_wrapper)
......
......@@ -181,9 +181,13 @@ class StatsCounter;
V(wasm_f64_trunc, "wasm::f64_trunc_wrapper") \
V(wasm_float32_to_int64, "wasm::float32_to_int64_wrapper") \
V(wasm_float32_to_uint64, "wasm::float32_to_uint64_wrapper") \
V(wasm_float32_to_int64_sat, "wasm::float32_to_int64_sat_wrapper") \
V(wasm_float32_to_uint64_sat, "wasm::float32_to_uint64_sat_wrapper") \
V(wasm_float64_pow, "wasm::float64_pow") \
V(wasm_float64_to_int64, "wasm::float64_to_int64_wrapper") \
V(wasm_float64_to_uint64, "wasm::float64_to_uint64_wrapper") \
V(wasm_float64_to_int64_sat, "wasm::float64_to_int64_sat_wrapper") \
V(wasm_float64_to_uint64_sat, "wasm::float64_to_uint64_sat_wrapper") \
V(wasm_int64_div, "wasm::int64_div") \
V(wasm_int64_mod, "wasm::int64_mod") \
V(wasm_int64_to_float32, "wasm::int64_to_float32_wrapper") \
......
......@@ -1769,18 +1769,6 @@ bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode,
case kExprI32UConvertSatF64:
return liftoff::EmitSatTruncateFloatToInt<uint32_t, double>(
this, dst.gp(), src.fp());
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:
Movd(dst.gp(), src.fp());
return true;
......
......@@ -1093,10 +1093,18 @@ class LiftoffCompiler {
CASE_TYPE_CONVERSION(I32UConvertSatF32, I32, F32, nullptr, kNoTrap)
CASE_TYPE_CONVERSION(I32SConvertSatF64, I32, F64, nullptr, kNoTrap)
CASE_TYPE_CONVERSION(I32UConvertSatF64, I32, F64, nullptr, kNoTrap)
CASE_TYPE_CONVERSION(I64SConvertSatF32, I64, F32, nullptr, kNoTrap)
CASE_TYPE_CONVERSION(I64UConvertSatF32, I64, F32, nullptr, kNoTrap)
CASE_TYPE_CONVERSION(I64SConvertSatF64, I64, F64, nullptr, kNoTrap)
CASE_TYPE_CONVERSION(I64UConvertSatF64, I64, F64, nullptr, kNoTrap)
CASE_TYPE_CONVERSION(I64SConvertSatF32, I64, F32,
&ExternalReference::wasm_float32_to_int64_sat,
kNoTrap)
CASE_TYPE_CONVERSION(I64UConvertSatF32, I64, F32,
&ExternalReference::wasm_float32_to_uint64_sat,
kNoTrap)
CASE_TYPE_CONVERSION(I64SConvertSatF64, I64, F64,
&ExternalReference::wasm_float64_to_int64_sat,
kNoTrap)
CASE_TYPE_CONVERSION(I64UConvertSatF64, I64, F64,
&ExternalReference::wasm_float64_to_uint64_sat,
kNoTrap)
return unsupported(decoder, kNonTrappingFloatToInt,
WasmOpcodes::OpcodeName(opcode));
default:
......
......@@ -230,6 +230,82 @@ int32_t float64_to_uint64_wrapper(Address data) {
return 0;
}
void float32_to_int64_sat_wrapper(Address data) {
float input = ReadUnalignedValue<float>(data);
// We use "<" here to check the upper bound because of rounding problems: With
// "<=" some inputs would be considered within int64 range which are actually
// not within int64 range.
if (input < static_cast<float>(std::numeric_limits<int64_t>::max()) &&
input >= static_cast<float>(std::numeric_limits<int64_t>::min())) {
WriteUnalignedValue<int64_t>(data, static_cast<int64_t>(input));
return;
}
if (std::isnan(input)) {
WriteUnalignedValue<int64_t>(data, 0);
return;
}
if (input < 0.0) {
WriteUnalignedValue<int64_t>(data, std::numeric_limits<int64_t>::min());
return;
}
WriteUnalignedValue<int64_t>(data, std::numeric_limits<int64_t>::max());
}
void float32_to_uint64_sat_wrapper(Address data) {
float input = ReadUnalignedValue<float>(data);
// We use "<" here to check the upper bound because of rounding problems: With
// "<=" some inputs would be considered within uint64 range which are actually
// not within uint64 range.
if (input < static_cast<float>(std::numeric_limits<uint64_t>::max()) &&
input >= 0.0) {
WriteUnalignedValue<uint64_t>(data, static_cast<uint64_t>(input));
return;
}
if (input >= std::numeric_limits<uint64_t>::max()) {
WriteUnalignedValue<uint64_t>(data, std::numeric_limits<uint64_t>::max());
return;
}
WriteUnalignedValue<uint64_t>(data, 0);
}
void float64_to_int64_sat_wrapper(Address data) {
double input = ReadUnalignedValue<double>(data);
// We use "<" here to check the upper bound because of rounding problems: With
// "<=" some inputs would be considered within int64 range which are actually
// not within int64 range.
if (input < static_cast<double>(std::numeric_limits<int64_t>::max()) &&
input >= static_cast<double>(std::numeric_limits<int64_t>::min())) {
WriteUnalignedValue<int64_t>(data, static_cast<int64_t>(input));
return;
}
if (std::isnan(input)) {
WriteUnalignedValue<int64_t>(data, 0);
return;
}
if (input < 0.0) {
WriteUnalignedValue<int64_t>(data, std::numeric_limits<int64_t>::min());
return;
}
WriteUnalignedValue<int64_t>(data, std::numeric_limits<int64_t>::max());
}
void float64_to_uint64_sat_wrapper(Address data) {
double input = ReadUnalignedValue<double>(data);
// We use "<" here to check the upper bound because of rounding problems: With
// "<=" some inputs would be considered within int64 range which are actually
// not within int64 range.
if (input < static_cast<double>(std::numeric_limits<uint64_t>::max()) &&
input >= 0.0) {
WriteUnalignedValue<uint64_t>(data, static_cast<uint64_t>(input));
return;
}
if (input >= std::numeric_limits<uint64_t>::max()) {
WriteUnalignedValue<uint64_t>(data, std::numeric_limits<uint64_t>::max());
return;
}
WriteUnalignedValue<uint64_t>(data, 0);
}
int32_t int64_div_wrapper(Address data) {
int64_t dividend = ReadUnalignedValue<int64_t>(data);
int64_t divisor = ReadUnalignedValue<int64_t>(data + sizeof(dividend));
......
......@@ -45,6 +45,14 @@ V8_EXPORT_PRIVATE int32_t float64_to_int64_wrapper(Address data);
V8_EXPORT_PRIVATE int32_t float64_to_uint64_wrapper(Address data);
V8_EXPORT_PRIVATE void float32_to_int64_sat_wrapper(Address data);
V8_EXPORT_PRIVATE void float32_to_uint64_sat_wrapper(Address data);
V8_EXPORT_PRIVATE void float64_to_int64_sat_wrapper(Address data);
V8_EXPORT_PRIVATE void float64_to_uint64_sat_wrapper(Address data);
V8_EXPORT_PRIVATE int32_t int64_div_wrapper(Address data);
V8_EXPORT_PRIVATE int32_t int64_mod_wrapper(Address data);
......
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