Commit 3f4163cd authored by ahaas's avatar ahaas Committed by Commit bot

[wasm] Backoff implementation for F64Trunc using std::trunc.

R=titzer@chromium.org

Review URL: https://codereview.chromium.org/1638283004

Cr-Commit-Position: refs/heads/master@{#33670}
parent 7feaf896
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include "src/assembler.h" #include "src/assembler.h"
#include <math.h>
#include <cmath> #include <cmath>
#include "src/api.h" #include "src/api.h"
#include "src/base/cpu.h" #include "src/base/cpu.h"
...@@ -1131,6 +1132,12 @@ ExternalReference ExternalReference::compute_output_frames_function( ...@@ -1131,6 +1132,12 @@ ExternalReference ExternalReference::compute_output_frames_function(
Redirect(isolate, FUNCTION_ADDR(Deoptimizer::ComputeOutputFrames))); Redirect(isolate, FUNCTION_ADDR(Deoptimizer::ComputeOutputFrames)));
} }
static void trunc64_wrapper(double* param) { *param = trunc(*param); }
ExternalReference ExternalReference::trunc64_wrapper_function(
Isolate* isolate) {
return ExternalReference(Redirect(isolate, FUNCTION_ADDR(trunc64_wrapper)));
}
ExternalReference ExternalReference::log_enter_external_function( ExternalReference ExternalReference::log_enter_external_function(
Isolate* isolate) { Isolate* isolate) {
......
...@@ -913,6 +913,8 @@ class ExternalReference BASE_EMBEDDED { ...@@ -913,6 +913,8 @@ class ExternalReference BASE_EMBEDDED {
static ExternalReference new_deoptimizer_function(Isolate* isolate); static ExternalReference new_deoptimizer_function(Isolate* isolate);
static ExternalReference compute_output_frames_function(Isolate* isolate); static ExternalReference compute_output_frames_function(Isolate* isolate);
static ExternalReference trunc64_wrapper_function(Isolate* isolate);
// Log support. // Log support.
static ExternalReference log_enter_external_function(Isolate* isolate); static ExternalReference log_enter_external_function(Isolate* isolate);
static ExternalReference log_leave_external_function(Isolate* isolate); static ExternalReference log_leave_external_function(Isolate* isolate);
......
...@@ -795,13 +795,9 @@ Node* WasmGraphBuilder::Unop(wasm::WasmOpcode opcode, Node* input) { ...@@ -795,13 +795,9 @@ Node* WasmGraphBuilder::Unop(wasm::WasmOpcode opcode, Node* input) {
} }
} }
case wasm::kExprF64Trunc: { case wasm::kExprF64Trunc: {
if (m->Float64RoundTruncate().IsSupported()) { if (!m->Float64RoundTruncate().IsSupported()) return BuildF64Trunc(input);
op = m->Float64RoundTruncate().op(); op = m->Float64RoundTruncate().op();
break; break;
} else {
op = UnsupportedOpcode(opcode);
break;
}
} }
case wasm::kExprF64NearestInt: { case wasm::kExprF64NearestInt: {
if (m->Float64RoundTiesEven().IsSupported()) { if (m->Float64RoundTiesEven().IsSupported()) {
...@@ -1436,6 +1432,60 @@ Node* WasmGraphBuilder::BuildF32Trunc(Node* input) { ...@@ -1436,6 +1432,60 @@ Node* WasmGraphBuilder::BuildF32Trunc(Node* input) {
return Unop(wasm::kExprF32ReinterpretI32, result); return Unop(wasm::kExprF32ReinterpretI32, result);
} }
Node* WasmGraphBuilder::BuildF64Trunc(Node* input) {
// 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));
const Operator* store_op = jsgraph()->machine()->Store(
StoreRepresentation(MachineRepresentation::kFloat64, 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* args[] = {function, stack_slot_param};
BuildCCall(sig_builder.Build(), args);
const Operator* load_op = jsgraph()->machine()->Load(MachineType::Float64());
Node* load =
graph()->NewNode(load_op, stack_slot_param, jsgraph()->Int32Constant(0),
*effect_, *control_);
*effect_ = load;
return load;
}
Node* WasmGraphBuilder::BuildCCall(MachineSignature* sig, Node** args) {
const size_t params = sig->parameter_count();
const size_t extra = 2; // effect and control inputs.
const size_t count = 1 + params + extra;
// Reallocate the buffer to make space for extra inputs.
args = Realloc(args, count);
// Add effect and control inputs.
args[params + 1] = *effect_;
args[params + 2] = *control_;
CallDescriptor* desc =
Linkage::GetSimplifiedCDescriptor(jsgraph()->zone(), sig);
const Operator* op = jsgraph()->common()->Call(desc);
Node* call = graph()->NewNode(op, static_cast<int>(count), args);
*effect_ = call;
return call;
}
Node* WasmGraphBuilder::BuildWasmCall(wasm::FunctionSig* sig, Node** args) { Node* WasmGraphBuilder::BuildWasmCall(wasm::FunctionSig* sig, Node** args) {
const size_t params = sig->parameter_count(); const size_t params = sig->parameter_count();
......
...@@ -159,6 +159,7 @@ class WasmGraphBuilder { ...@@ -159,6 +159,7 @@ class WasmGraphBuilder {
Node* MemBuffer(uint32_t offset); Node* MemBuffer(uint32_t offset);
void BoundsCheckMem(MachineType memtype, Node* index, uint32_t offset); void BoundsCheckMem(MachineType memtype, Node* index, uint32_t offset);
Node* BuildCCall(MachineSignature* sig, Node** args);
Node* BuildWasmCall(wasm::FunctionSig* sig, Node** args); Node* BuildWasmCall(wasm::FunctionSig* sig, Node** args);
Node* BuildF32Neg(Node* input); Node* BuildF32Neg(Node* input);
Node* BuildF64Neg(Node* input); Node* BuildF64Neg(Node* input);
...@@ -177,6 +178,7 @@ class WasmGraphBuilder { ...@@ -177,6 +178,7 @@ class WasmGraphBuilder {
Node* BuildI64Ctz(Node* input); Node* BuildI64Ctz(Node* input);
Node* BuildI64Popcnt(Node* input); Node* BuildI64Popcnt(Node* input);
Node* BuildF32Trunc(Node* input); Node* BuildF32Trunc(Node* input);
Node* BuildF64Trunc(Node* input);
Node** Realloc(Node** buffer, size_t count) { Node** Realloc(Node** buffer, size_t count) {
Node** buf = Buffer(count); Node** buf = Buffer(count);
......
...@@ -264,6 +264,7 @@ CallDescriptor* ModuleEnv::GetWasmCallDescriptor(Zone* zone, ...@@ -264,6 +264,7 @@ CallDescriptor* ModuleEnv::GetWasmCallDescriptor(Zone* zone,
// The target for WASM calls is always a code object. // The target for WASM calls is always a code object.
MachineType target_type = MachineType::AnyTagged(); MachineType target_type = MachineType::AnyTagged();
LinkageLocation target_loc = LinkageLocation::ForAnyRegister(); LinkageLocation target_loc = LinkageLocation::ForAnyRegister();
return new (zone) CallDescriptor( // -- return new (zone) CallDescriptor( // --
CallDescriptor::kCallCodeObject, // kind CallDescriptor::kCallCodeObject, // kind
target_type, // target MachineType target_type, // target MachineType
......
...@@ -119,6 +119,8 @@ ExternalReferenceTable::ExternalReferenceTable(Isolate* isolate) { ...@@ -119,6 +119,8 @@ ExternalReferenceTable::ExternalReferenceTable(Isolate* isolate) {
"InvokeFunctionCallback"); "InvokeFunctionCallback");
Add(ExternalReference::invoke_accessor_getter_callback(isolate).address(), Add(ExternalReference::invoke_accessor_getter_callback(isolate).address(),
"InvokeAccessorGetterCallback"); "InvokeAccessorGetterCallback");
Add(ExternalReference::trunc64_wrapper_function(isolate).address(),
"trunc64_wrapper");
Add(ExternalReference::log_enter_external_function(isolate).address(), Add(ExternalReference::log_enter_external_function(isolate).address(),
"Logger::EnterExternal"); "Logger::EnterExternal");
Add(ExternalReference::log_leave_external_function(isolate).address(), Add(ExternalReference::log_leave_external_function(isolate).address(),
......
...@@ -5588,6 +5588,19 @@ TEST(RunCallCFunction8) { ...@@ -5588,6 +5588,19 @@ TEST(RunCallCFunction8) {
} }
#endif // USE_SIMULATOR #endif // USE_SIMULATOR
TEST(RunCallExternalReferenceF64Trunc) {
BufferedRawMachineAssemblerTester<double> m(MachineType::Float64());
Node* stack_slot = m.StackSlot(MachineRepresentation::kFloat64);
m.Store(MachineRepresentation::kFloat64, stack_slot, m.Parameter(0),
WriteBarrierKind::kNoWriteBarrier);
Node* function = m.ExternalConstant(
ExternalReference::trunc64_wrapper_function(m.isolate()));
m.CallCFunction1(MachineType::Pointer(), MachineType::Pointer(), function,
stack_slot);
m.Return(m.Load(MachineType::Float64(), stack_slot));
FOR_FLOAT64_INPUTS(i) { CheckDoubleEq(trunc(*i), m.Call(*i)); }
}
#if V8_TARGET_ARCH_64_BIT #if V8_TARGET_ARCH_64_BIT
// TODO(titzer): run int64 tests on all platforms when supported. // TODO(titzer): run int64 tests on all platforms when supported.
TEST(RunCheckedLoadInt64) { TEST(RunCheckedLoadInt64) {
......
...@@ -3006,14 +3006,6 @@ TEST(Run_Wasm_F64Ceil) { ...@@ -3006,14 +3006,6 @@ TEST(Run_Wasm_F64Ceil) {
} }
TEST(Run_Wasm_F64Trunc) {
WasmRunner<double> r(MachineType::Float64());
BUILD(r, WASM_F64_TRUNC(WASM_GET_LOCAL(0)));
FOR_FLOAT64_INPUTS(i) { CheckDoubleEq(trunc(*i), r.Call(*i)); }
}
TEST(Run_Wasm_F64NearestInt) { TEST(Run_Wasm_F64NearestInt) {
WasmRunner<double> r(MachineType::Float64()); WasmRunner<double> r(MachineType::Float64());
BUILD(r, WASM_F64_NEARESTINT(WASM_GET_LOCAL(0))); BUILD(r, WASM_F64_NEARESTINT(WASM_GET_LOCAL(0)));
...@@ -3023,6 +3015,12 @@ TEST(Run_Wasm_F64NearestInt) { ...@@ -3023,6 +3015,12 @@ TEST(Run_Wasm_F64NearestInt) {
#endif #endif
TEST(Run_Wasm_F64Trunc) {
WasmRunner<double> r(MachineType::Float64());
BUILD(r, WASM_F64_TRUNC(WASM_GET_LOCAL(0)));
FOR_FLOAT64_INPUTS(i) { CheckDoubleEq(trunc(*i), r.Call(*i)); }
}
TEST(Run_Wasm_F32Min) { TEST(Run_Wasm_F32Min) {
WasmRunner<float> r(MachineType::Float32(), MachineType::Float32()); WasmRunner<float> r(MachineType::Float32(), MachineType::Float32());
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment