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), |