[wasm] Implemented F32Trunc as a turbofan graph based on int32 instructions.
Platforms which do not provide rounding instructions (like x64 without sse4.1, arm before v8) fall back to this new soft float inplementation. BUG=575379 LOG=Y R=titzer@chromium.org Review URL: https://codereview.chromium.org/1611513003 Cr-Commit-Position: refs/heads/master@{#33412}
This commit is contained in:
parent
d48feaccf2
commit
a910cb4006
@ -756,11 +756,10 @@ Node* WasmGraphBuilder::Unop(wasm::WasmOpcode opcode, Node* input) {
|
||||
case wasm::kExprF32Trunc: {
|
||||
if (m->Float32RoundTruncate().IsSupported()) {
|
||||
op = m->Float32RoundTruncate().op();
|
||||
break;
|
||||
} else {
|
||||
op = UnsupportedOpcode(opcode);
|
||||
break;
|
||||
return BuildF32Trunc(input);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case wasm::kExprF32NearestInt: {
|
||||
if (m->Float32RoundTiesEven().IsSupported()) {
|
||||
@ -1365,6 +1364,73 @@ Node* WasmGraphBuilder::BuildI64Popcnt(Node* input) {
|
||||
}
|
||||
|
||||
|
||||
Node* WasmGraphBuilder::BuildF32Trunc(Node* input) {
|
||||
// int32_t int_input = bitftoi(input);
|
||||
// int32_t exponent = int_input & 0x7f800000;
|
||||
// if (exponent >= ((23 + 127) << 23)) {
|
||||
// if (input != input) {
|
||||
// return bititof(int_input | (1 << 22));
|
||||
// }
|
||||
// return input;
|
||||
// }
|
||||
// int32_t sign = int_input & 0x80000000;
|
||||
// if (exponent < (127 << 23)) {
|
||||
// return bititof(sign);
|
||||
// }
|
||||
// int32_t mantissa = int_input & 0x007fffff;
|
||||
// int32_t shift = (127 + 23) - (exponent >> 23);
|
||||
// int32_t new_mantissa = (mantissa >> shift) << shift;
|
||||
// int32_t result = new_mantissa | exponent | sign;
|
||||
// return bititof(result);
|
||||
|
||||
Node* int_input = Unop(wasm::kExprI32ReinterpretF32, input);
|
||||
Node* exponent =
|
||||
Binop(wasm::kExprI32And, int_input, jsgraph()->Int32Constant(0x7f800000));
|
||||
|
||||
Node* sign =
|
||||
Binop(wasm::kExprI32And, int_input, jsgraph()->Int32Constant(0x80000000));
|
||||
|
||||
Node* result_out_of_range = int_input;
|
||||
|
||||
Node* result_nan =
|
||||
Binop(wasm::kExprI32Ior, int_input, jsgraph()->Int32Constant(1 << 22));
|
||||
|
||||
Node* result_zero = sign;
|
||||
|
||||
Node* mantissa =
|
||||
Binop(wasm::kExprI32And, int_input, jsgraph()->Int32Constant(0x007fffff));
|
||||
Node* shift =
|
||||
Binop(wasm::kExprI32Sub, jsgraph()->Int32Constant(23 + 127),
|
||||
Binop(wasm::kExprI32ShrU, exponent, jsgraph()->Int32Constant(23)));
|
||||
Node* new_mantissa = Binop(wasm::kExprI32Shl,
|
||||
Binop(wasm::kExprI32ShrU, mantissa, shift), shift);
|
||||
Node* result_truncate =
|
||||
Binop(wasm::kExprI32Ior, Binop(wasm::kExprI32Ior, new_mantissa, exponent),
|
||||
sign);
|
||||
|
||||
Diamond is_zero(
|
||||
graph(), jsgraph()->common(),
|
||||
Binop(wasm::kExprI32LtU, exponent, jsgraph()->Int32Constant(127 << 23)));
|
||||
|
||||
Node* result_within_range =
|
||||
is_zero.Phi(wasm::kAstI32, result_zero, result_truncate);
|
||||
|
||||
Diamond input_nan(graph(), jsgraph()->common(),
|
||||
Binop(wasm::kExprF32Ne, input, input));
|
||||
Node* result_exponent_geq_23 =
|
||||
input_nan.Phi(wasm::kAstI32, result_nan, result_out_of_range);
|
||||
|
||||
Diamond exponent_geq_23(graph(), jsgraph()->common(),
|
||||
Binop(wasm::kExprI32GeU, exponent,
|
||||
jsgraph()->Int32Constant((23 + 127) << 23)));
|
||||
|
||||
Node* result = exponent_geq_23.Phi(wasm::kAstI32, result_exponent_geq_23,
|
||||
result_within_range);
|
||||
|
||||
return Unop(wasm::kExprF32ReinterpretI32, result);
|
||||
}
|
||||
|
||||
|
||||
Node* WasmGraphBuilder::BuildWasmCall(wasm::FunctionSig* sig, Node** args) {
|
||||
const size_t params = sig->parameter_count();
|
||||
const size_t extra = 2; // effect and control inputs.
|
||||
|
@ -176,6 +176,7 @@ class WasmGraphBuilder {
|
||||
Node* BuildI32Popcnt(Node* input);
|
||||
Node* BuildI64Ctz(Node* input);
|
||||
Node* BuildI64Popcnt(Node* input);
|
||||
Node* BuildF32Trunc(Node* input);
|
||||
|
||||
Node** Realloc(Node** buffer, size_t count) {
|
||||
Node** buf = Buffer(count);
|
||||
|
@ -2933,6 +2933,14 @@ TEST(Run_Wasm_MultipleCallIndirect) {
|
||||
}
|
||||
|
||||
|
||||
TEST(Run_Wasm_F32Trunc) {
|
||||
WasmRunner<float> r(MachineType::Float32());
|
||||
BUILD(r, WASM_F32_TRUNC(WASM_GET_LOCAL(0)));
|
||||
|
||||
FOR_FLOAT32_INPUTS(i) { CheckFloatEq(trunc(*i), r.Call(*i)); }
|
||||
}
|
||||
|
||||
|
||||
// TODO(titzer): Fix for nosee4 and re-enable.
|
||||
#if 0
|
||||
|
||||
@ -2952,14 +2960,6 @@ TEST(Run_Wasm_F32Ceil) {
|
||||
}
|
||||
|
||||
|
||||
TEST(Run_Wasm_F32Trunc) {
|
||||
WasmRunner<float> r(MachineType::Float32());
|
||||
BUILD(r, WASM_F32_TRUNC(WASM_GET_LOCAL(0)));
|
||||
|
||||
FOR_FLOAT32_INPUTS(i) { CheckFloatEq(trunc(*i), r.Call(*i)); }
|
||||
}
|
||||
|
||||
|
||||
TEST(Run_Wasm_F32NearestInt) {
|
||||
WasmRunner<float> r(MachineType::Float32());
|
||||
BUILD(r, WASM_F32_NEARESTINT(WASM_GET_LOCAL(0)));
|
||||
|
Loading…
Reference in New Issue
Block a user