Commit 29737301 authored by titzer's avatar titzer Committed by Commit bot

[wasm] Introduce custom asm.js bytecodes for double->int conversions.

R=ahaas@chromium.org,bradnelson@chromium.org
BUG=

Review-Url: https://codereview.chromium.org/1971693002
Cr-Commit-Position: refs/heads/master@{#36164}
parent 6e15433d
......@@ -662,6 +662,10 @@ Node* WasmGraphBuilder::Unop(wasm::WasmOpcode opcode, Node* input,
return BuildI32SConvertF64(input, position);
case wasm::kExprI32UConvertF64:
return BuildI32UConvertF64(input, position);
case wasm::kExprI32AsmjsSConvertF64:
return BuildI32AsmjsSConvertF64(input);
case wasm::kExprI32AsmjsUConvertF64:
return BuildI32AsmjsUConvertF64(input);
case wasm::kExprF32ConvertF64:
op = m->TruncateFloat64ToFloat32();
break;
......@@ -681,6 +685,10 @@ Node* WasmGraphBuilder::Unop(wasm::WasmOpcode opcode, Node* input,
return BuildI32SConvertF32(input, position);
case wasm::kExprI32UConvertF32:
return BuildI32UConvertF32(input, position);
case wasm::kExprI32AsmjsSConvertF32:
return BuildI32AsmjsSConvertF32(input);
case wasm::kExprI32AsmjsUConvertF32:
return BuildI32AsmjsUConvertF32(input);
case wasm::kExprF64ConvertF32:
op = m->ChangeFloat32ToFloat64();
break;
......@@ -1129,12 +1137,6 @@ Node* WasmGraphBuilder::BuildF64Max(Node* left, Node* right) {
Node* WasmGraphBuilder::BuildI32SConvertF32(Node* input,
wasm::WasmCodePosition position) {
MachineOperatorBuilder* m = jsgraph()->machine();
if (module_ && module_->asm_js()) {
// asm.js must use the wacky JS semantics.
input = graph()->NewNode(m->ChangeFloat32ToFloat64(), input);
return graph()->NewNode(m->TruncateFloat64ToWord32(), input);
}
// Truncation of the input value is needed for the overflow check later.
Node* trunc = Unop(wasm::kExprF32Trunc, input);
Node* result = graph()->NewNode(m->TruncateFloat32ToInt32(), trunc);
......@@ -1151,10 +1153,6 @@ Node* WasmGraphBuilder::BuildI32SConvertF32(Node* input,
Node* WasmGraphBuilder::BuildI32SConvertF64(Node* input,
wasm::WasmCodePosition position) {
MachineOperatorBuilder* m = jsgraph()->machine();
if (module_ && module_->asm_js()) {
// asm.js must use the wacky JS semantics.
return graph()->NewNode(m->TruncateFloat64ToWord32(), input);
}
// Truncation of the input value is needed for the overflow check later.
Node* trunc = Unop(wasm::kExprF64Trunc, input);
Node* result = graph()->NewNode(m->ChangeFloat64ToInt32(), trunc);
......@@ -1171,12 +1169,6 @@ Node* WasmGraphBuilder::BuildI32SConvertF64(Node* input,
Node* WasmGraphBuilder::BuildI32UConvertF32(Node* input,
wasm::WasmCodePosition position) {
MachineOperatorBuilder* m = jsgraph()->machine();
if (module_ && module_->asm_js()) {
// asm.js must use the wacky JS semantics.
input = graph()->NewNode(m->ChangeFloat32ToFloat64(), input);
return graph()->NewNode(m->TruncateFloat64ToWord32(), input);
}
// Truncation of the input value is needed for the overflow check later.
Node* trunc = Unop(wasm::kExprF32Trunc, input);
Node* result = graph()->NewNode(m->TruncateFloat32ToUint32(), trunc);
......@@ -1193,10 +1185,6 @@ Node* WasmGraphBuilder::BuildI32UConvertF32(Node* input,
Node* WasmGraphBuilder::BuildI32UConvertF64(Node* input,
wasm::WasmCodePosition position) {
MachineOperatorBuilder* m = jsgraph()->machine();
if (module_ && module_->asm_js()) {
// asm.js must use the wacky JS semantics.
return graph()->NewNode(m->TruncateFloat64ToWord32(), input);
}
// Truncation of the input value is needed for the overflow check later.
Node* trunc = Unop(wasm::kExprF64Trunc, input);
Node* result = graph()->NewNode(m->TruncateFloat64ToUint32(), trunc);
......@@ -1210,6 +1198,32 @@ Node* WasmGraphBuilder::BuildI32UConvertF64(Node* input,
return result;
}
Node* WasmGraphBuilder::BuildI32AsmjsSConvertF32(Node* input) {
MachineOperatorBuilder* m = jsgraph()->machine();
// asm.js must use the wacky JS semantics.
input = graph()->NewNode(m->ChangeFloat32ToFloat64(), input);
return graph()->NewNode(m->TruncateFloat64ToWord32(), input);
}
Node* WasmGraphBuilder::BuildI32AsmjsSConvertF64(Node* input) {
MachineOperatorBuilder* m = jsgraph()->machine();
// asm.js must use the wacky JS semantics.
return graph()->NewNode(m->TruncateFloat64ToWord32(), input);
}
Node* WasmGraphBuilder::BuildI32AsmjsUConvertF32(Node* input) {
MachineOperatorBuilder* m = jsgraph()->machine();
// asm.js must use the wacky JS semantics.
input = graph()->NewNode(m->ChangeFloat32ToFloat64(), input);
return graph()->NewNode(m->TruncateFloat64ToWord32(), input);
}
Node* WasmGraphBuilder::BuildI32AsmjsUConvertF64(Node* input) {
MachineOperatorBuilder* m = jsgraph()->machine();
// asm.js must use the wacky JS semantics.
return graph()->NewNode(m->TruncateFloat64ToWord32(), input);
}
Node* WasmGraphBuilder::BuildBitCountingCall(Node* input, ExternalReference ref,
MachineRepresentation input_type) {
Node* stack_slot_param =
......
......@@ -267,11 +267,6 @@ class WasmGraphBuilder {
Node* BuildI32DivU(Node* left, Node* right, wasm::WasmCodePosition position);
Node* BuildI32RemU(Node* left, Node* right, wasm::WasmCodePosition position);
Node* BuildI32AsmjsDivS(Node* left, Node* right);
Node* BuildI32AsmjsRemS(Node* left, Node* right);
Node* BuildI32AsmjsDivU(Node* left, Node* right);
Node* BuildI32AsmjsRemU(Node* left, Node* right);
Node* BuildI64DivS(Node* left, Node* right, wasm::WasmCodePosition position);
Node* BuildI64RemS(Node* left, Node* right, wasm::WasmCodePosition position);
Node* BuildI64DivU(Node* left, Node* right, wasm::WasmCodePosition position);
......@@ -296,6 +291,16 @@ class WasmGraphBuilder {
Node* BuildLoadHeapNumberValue(Node* value, Node* control);
Node* BuildHeapNumberValueIndexConstant();
// Asm.js specific functionality.
Node* BuildI32AsmjsSConvertF32(Node* input);
Node* BuildI32AsmjsSConvertF64(Node* input);
Node* BuildI32AsmjsUConvertF32(Node* input);
Node* BuildI32AsmjsUConvertF64(Node* input);
Node* BuildI32AsmjsDivS(Node* left, Node* right);
Node* BuildI32AsmjsRemS(Node* left, Node* right);
Node* BuildI32AsmjsDivU(Node* left, Node* right);
Node* BuildI32AsmjsRemU(Node* left, Node* right);
Node** Realloc(Node** buffer, size_t old_count, size_t new_count) {
Node** buf = Buffer(new_count);
if (buf != buffer) memcpy(buf, buffer, old_count * sizeof(Node*));
......
......@@ -1437,9 +1437,9 @@ class AsmWasmBuilderImpl : public AstVisitor {
RECURSE(Visit(GetLeft(expr)));
TypeIndex type = TypeIndexOf(GetLeft(expr));
if (type == kFloat32) {
current_function_builder_->Emit(kExprI32SConvertF32);
current_function_builder_->Emit(kExprI32AsmjsSConvertF32);
} else if (type == kFloat64) {
current_function_builder_->Emit(kExprI32SConvertF64);
current_function_builder_->Emit(kExprI32AsmjsSConvertF64);
} else {
UNREACHABLE();
}
......
......@@ -260,7 +260,11 @@ const WasmCodePosition kNoCodePosition = -1;
V(I32AsmjsDivS, 0xd0, i_ii) \
V(I32AsmjsDivU, 0xd1, i_ii) \
V(I32AsmjsRemS, 0xd2, i_ii) \
V(I32AsmjsRemU, 0xd3, i_ii)
V(I32AsmjsRemU, 0xd3, i_ii) \
V(I32AsmjsSConvertF32, 0xe0, i_f) \
V(I32AsmjsUConvertF32, 0xe1, i_f) \
V(I32AsmjsSConvertF64, 0xe2, i_d) \
V(I32AsmjsUConvertF64, 0xe3, i_d)
/* TODO(titzer): introduce compatibility opcodes for these asm.js ops \
V(I32AsmjsLoad8S, 0xd4, i_i) \ \
......@@ -275,10 +279,6 @@ V(I32AsmjsStore16, 0xdc, i_i) \ \
V(I32AsmjsStore, 0xdd, i_ii) \ \
V(F32AsmjsStore, 0xde, i_if) \ \
V(F64AsmjsStore, 0xdf, i_id) \ \
V(I32SAsmjsConvertF32, 0xe0, i_f) \ \
V(I32UAsmjsConvertF32, 0xe1, i_f) \ \
V(I32SAsmjsConvertF64, 0xe2, i_d) \ \
V(I32SAsmjsConvertF64, 0xe3, i_d) \
*/
// All opcodes.
......
......@@ -70,6 +70,46 @@ TEST(Run_WASM_Int32AsmjsRemU) {
CHECK_EQ(kMin, r.Call(kMin, -1));
}
TEST(Run_Wasm_I32AsmjsSConvertF32) {
WasmRunner<int32_t> r(MachineType::Float32());
BUILD(r, WASM_UNOP(kExprI32AsmjsSConvertF32, WASM_GET_LOCAL(0)));
FOR_FLOAT32_INPUTS(i) {
int32_t expected = DoubleToInt32(*i);
CHECK_EQ(expected, r.Call(*i));
}
}
TEST(Run_Wasm_I32AsmjsSConvertF64) {
WasmRunner<int32_t> r(MachineType::Float64());
BUILD(r, WASM_UNOP(kExprI32AsmjsSConvertF64, WASM_GET_LOCAL(0)));
FOR_FLOAT64_INPUTS(i) {
int32_t expected = DoubleToInt32(*i);
CHECK_EQ(expected, r.Call(*i));
}
}
TEST(Run_Wasm_I32AsmjsUConvertF32) {
WasmRunner<uint32_t> r(MachineType::Float32());
BUILD(r, WASM_UNOP(kExprI32AsmjsUConvertF32, WASM_GET_LOCAL(0)));
FOR_FLOAT32_INPUTS(i) {
uint32_t expected = DoubleToUint32(*i);
CHECK_EQ(expected, r.Call(*i));
}
}
TEST(Run_Wasm_I32AsmjsUConvertF64) {
WasmRunner<uint32_t> r(MachineType::Float64());
BUILD(r, WASM_UNOP(kExprI32AsmjsUConvertF64, WASM_GET_LOCAL(0)));
FOR_FLOAT64_INPUTS(i) {
uint32_t expected = DoubleToUint32(*i);
CHECK_EQ(expected, r.Call(*i));
}
}
TEST(Run_Wasm_LoadMemI32_oob_asm) {
TestingModule module;
module.origin = kAsmJsOrigin;
......
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