[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:
ahaas 2016-01-20 07:43:03 -08:00 committed by Commit bot
parent d48feaccf2
commit a910cb4006
3 changed files with 78 additions and 11 deletions

View File

@ -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.

View File

@ -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);

View File

@ -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)));