| Index: src/compiler/wasm-compiler.cc
|
| diff --git a/src/compiler/wasm-compiler.cc b/src/compiler/wasm-compiler.cc
|
| index dd0dfe3873bca5de94a28196a0072b44184f0d85..69e51d77e5544ff89e21b1c3a4326a468bc89953 100644
|
| --- a/src/compiler/wasm-compiler.cc
|
| +++ b/src/compiler/wasm-compiler.cc
|
| @@ -742,57 +742,35 @@ Node* WasmGraphBuilder::Unop(wasm::WasmOpcode opcode, Node* input) {
|
| }
|
| }
|
| case wasm::kExprF32Floor: {
|
| - if (m->Float32RoundDown().IsSupported()) {
|
| - op = m->Float32RoundDown().op();
|
| - break;
|
| - } else {
|
| - op = UnsupportedOpcode(opcode);
|
| - break;
|
| - }
|
| + if (!m->Float32RoundDown().IsSupported()) return BuildF32Floor(input);
|
| + op = m->Float32RoundDown().op();
|
| + break;
|
| }
|
| case wasm::kExprF32Ceil: {
|
| - if (m->Float32RoundUp().IsSupported()) {
|
| - op = m->Float32RoundUp().op();
|
| - break;
|
| - } else {
|
| - op = UnsupportedOpcode(opcode);
|
| - break;
|
| - }
|
| + if (!m->Float32RoundUp().IsSupported()) return BuildF32Ceil(input);
|
| + op = m->Float32RoundUp().op();
|
| + break;
|
| }
|
| case wasm::kExprF32Trunc: {
|
| - if (m->Float32RoundTruncate().IsSupported()) {
|
| - op = m->Float32RoundTruncate().op();
|
| - } else {
|
| - return BuildF32Trunc(input);
|
| - }
|
| + if (!m->Float32RoundTruncate().IsSupported()) return BuildF32Trunc(input);
|
| + op = m->Float32RoundTruncate().op();
|
| break;
|
| }
|
| case wasm::kExprF32NearestInt: {
|
| - if (m->Float32RoundTiesEven().IsSupported()) {
|
| - op = m->Float32RoundTiesEven().op();
|
| - break;
|
| - } else {
|
| - op = UnsupportedOpcode(opcode);
|
| - break;
|
| - }
|
| + if (!m->Float32RoundTiesEven().IsSupported())
|
| + return BuildF32NearestInt(input);
|
| + op = m->Float32RoundTiesEven().op();
|
| + break;
|
| }
|
| case wasm::kExprF64Floor: {
|
| - if (m->Float64RoundDown().IsSupported()) {
|
| - op = m->Float64RoundDown().op();
|
| - break;
|
| - } else {
|
| - op = UnsupportedOpcode(opcode);
|
| - break;
|
| - }
|
| + if (!m->Float64RoundDown().IsSupported()) return BuildF64Floor(input);
|
| + op = m->Float64RoundDown().op();
|
| + break;
|
| }
|
| case wasm::kExprF64Ceil: {
|
| - if (m->Float64RoundUp().IsSupported()) {
|
| - op = m->Float64RoundUp().op();
|
| - break;
|
| - } else {
|
| - op = UnsupportedOpcode(opcode);
|
| - break;
|
| - }
|
| + if (!m->Float64RoundUp().IsSupported()) return BuildF64Ceil(input);
|
| + op = m->Float64RoundUp().op();
|
| + break;
|
| }
|
| case wasm::kExprF64Trunc: {
|
| if (!m->Float64RoundTruncate().IsSupported()) return BuildF64Trunc(input);
|
| @@ -800,13 +778,10 @@ Node* WasmGraphBuilder::Unop(wasm::WasmOpcode opcode, Node* input) {
|
| break;
|
| }
|
| case wasm::kExprF64NearestInt: {
|
| - if (m->Float64RoundTiesEven().IsSupported()) {
|
| - op = m->Float64RoundTiesEven().op();
|
| - break;
|
| - } else {
|
| - op = UnsupportedOpcode(opcode);
|
| - break;
|
| - }
|
| + if (!m->Float64RoundTiesEven().IsSupported())
|
| + return BuildF64NearestInt(input);
|
| + op = m->Float64RoundTiesEven().op();
|
| + break;
|
| }
|
|
|
| #if WASM_64
|
| @@ -1365,99 +1340,89 @@ Node* WasmGraphBuilder::BuildI64Popcnt(Node* input) {
|
| return result;
|
| }
|
|
|
| -
|
| 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);
|
| + MachineType type = MachineType::Float32();
|
| + ExternalReference ref =
|
| + ExternalReference::f32_trunc_wrapper_function(jsgraph()->isolate());
|
| + return BuildRoundingInstruction(input, ref, type);
|
| +}
|
| +
|
| +Node* WasmGraphBuilder::BuildF32Floor(Node* input) {
|
| + MachineType type = MachineType::Float32();
|
| + ExternalReference ref =
|
| + ExternalReference::f32_floor_wrapper_function(jsgraph()->isolate());
|
| + return BuildRoundingInstruction(input, ref, type);
|
| +}
|
| +
|
| +Node* WasmGraphBuilder::BuildF32Ceil(Node* input) {
|
| + MachineType type = MachineType::Float32();
|
| + ExternalReference ref =
|
| + ExternalReference::f32_ceil_wrapper_function(jsgraph()->isolate());
|
| + return BuildRoundingInstruction(input, ref, type);
|
| +}
|
| +
|
| +Node* WasmGraphBuilder::BuildF32NearestInt(Node* input) {
|
| + MachineType type = MachineType::Float32();
|
| + ExternalReference ref =
|
| + ExternalReference::f32_nearest_int_wrapper_function(jsgraph()->isolate());
|
| + return BuildRoundingInstruction(input, ref, type);
|
| }
|
|
|
| Node* WasmGraphBuilder::BuildF64Trunc(Node* input) {
|
| + MachineType type = MachineType::Float64();
|
| + ExternalReference ref =
|
| + ExternalReference::f64_trunc_wrapper_function(jsgraph()->isolate());
|
| + return BuildRoundingInstruction(input, ref, type);
|
| +}
|
| +
|
| +Node* WasmGraphBuilder::BuildF64Floor(Node* input) {
|
| + MachineType type = MachineType::Float64();
|
| + ExternalReference ref =
|
| + ExternalReference::f64_floor_wrapper_function(jsgraph()->isolate());
|
| + return BuildRoundingInstruction(input, ref, type);
|
| +}
|
| +
|
| +Node* WasmGraphBuilder::BuildF64Ceil(Node* input) {
|
| + MachineType type = MachineType::Float64();
|
| + ExternalReference ref =
|
| + ExternalReference::f64_ceil_wrapper_function(jsgraph()->isolate());
|
| + return BuildRoundingInstruction(input, ref, type);
|
| +}
|
| +
|
| +Node* WasmGraphBuilder::BuildF64NearestInt(Node* input) {
|
| + MachineType type = MachineType::Float64();
|
| + ExternalReference ref =
|
| + ExternalReference::f64_nearest_int_wrapper_function(jsgraph()->isolate());
|
| + return BuildRoundingInstruction(input, ref, type);
|
| +}
|
| +
|
| +Node* WasmGraphBuilder::BuildRoundingInstruction(Node* input,
|
| + ExternalReference ref,
|
| + MachineType type) {
|
| // We do truncation by calling a C function which calculates the truncation
|
| // for us. The input is passed to the C function as a double* to avoid double
|
| // parameters. For this we reserve a slot on the stack, store the parameter in
|
| // that slot, pass a pointer to the slot to the C function, and after calling
|
| // the C function we collect the return value from the stack slot.
|
|
|
| - Node* stack_slot_param = graph()->NewNode(
|
| - jsgraph()->machine()->StackSlot(MachineRepresentation::kFloat64));
|
| + Node* stack_slot_param =
|
| + graph()->NewNode(jsgraph()->machine()->StackSlot(type.representation()));
|
|
|
| const Operator* store_op = jsgraph()->machine()->Store(
|
| - StoreRepresentation(MachineRepresentation::kFloat64, kNoWriteBarrier));
|
| + StoreRepresentation(type.representation(), kNoWriteBarrier));
|
| *effect_ =
|
| graph()->NewNode(store_op, stack_slot_param, jsgraph()->Int32Constant(0),
|
| input, *effect_, *control_);
|
|
|
| Signature<MachineType>::Builder sig_builder(jsgraph()->zone(), 0, 1);
|
| sig_builder.AddParam(MachineType::Pointer());
|
| - Node* function = graph()->NewNode(jsgraph()->common()->ExternalConstant(
|
| - ExternalReference::trunc64_wrapper_function(jsgraph()->isolate())));
|
| + Node* function = graph()->NewNode(jsgraph()->common()->ExternalConstant(ref));
|
|
|
| Node* args[] = {function, stack_slot_param};
|
|
|
| BuildCCall(sig_builder.Build(), args);
|
|
|
| - const Operator* load_op = jsgraph()->machine()->Load(MachineType::Float64());
|
| + const Operator* load_op = jsgraph()->machine()->Load(type);
|
|
|
| Node* load =
|
| graph()->NewNode(load_op, stack_slot_param, jsgraph()->Int32Constant(0),
|
|
|