diff --git a/src/compiler/wasm-compiler.cc b/src/compiler/wasm-compiler.cc index 21c6a67379..d838e01958 100644 --- a/src/compiler/wasm-compiler.cc +++ b/src/compiler/wasm-compiler.cc @@ -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. diff --git a/src/compiler/wasm-compiler.h b/src/compiler/wasm-compiler.h index 1a17a832e4..f0c54352f8 100644 --- a/src/compiler/wasm-compiler.h +++ b/src/compiler/wasm-compiler.h @@ -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); diff --git a/test/cctest/wasm/test-run-wasm.cc b/test/cctest/wasm/test-run-wasm.cc index 196aea4f57..4873f570b7 100644 --- a/test/cctest/wasm/test-run-wasm.cc +++ b/test/cctest/wasm/test-run-wasm.cc @@ -2933,6 +2933,14 @@ TEST(Run_Wasm_MultipleCallIndirect) { } +TEST(Run_Wasm_F32Trunc) { + WasmRunner 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 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 r(MachineType::Float32()); BUILD(r, WASM_F32_NEARESTINT(WASM_GET_LOCAL(0)));