Commit 746cd5f8 authored by ahaas's avatar ahaas Committed by Commit bot

[wasm] Fixed FxxMin and FxxMax for cases where one operand is NaN.

R=titzer@chromium.org

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

Cr-Commit-Position: refs/heads/master@{#32811}
parent d671f427
......@@ -638,42 +638,14 @@ Node* WasmGraphBuilder::Binop(wasm::WasmOpcode opcode, Node* left,
op = m->Float64LessThanOrEqual();
std::swap(left, right);
break;
case wasm::kExprF32Min: {
if (m->Float32Min().IsSupported()) {
op = m->Float32Min().op();
break;
} else {
op = UnsupportedOpcode(opcode);
break;
}
}
case wasm::kExprF64Min: {
if (m->Float64Min().IsSupported()) {
op = m->Float64Min().op();
break;
} else {
op = UnsupportedOpcode(opcode);
break;
}
}
case wasm::kExprF32Max: {
if (m->Float32Max().IsSupported()) {
op = m->Float32Max().op();
break;
} else {
op = UnsupportedOpcode(opcode);
break;
}
}
case wasm::kExprF64Max: {
if (m->Float64Max().IsSupported()) {
op = m->Float64Max().op();
break;
} else {
op = UnsupportedOpcode(opcode);
break;
}
}
case wasm::kExprF32Min:
return BuildF32Min(left, right);
case wasm::kExprF64Min:
return BuildF64Min(left, right);
case wasm::kExprF32Max:
return BuildF32Max(left, right);
case wasm::kExprF64Max:
return BuildF64Max(left, right);
default:
op = UnsupportedOpcode(opcode);
}
......@@ -1050,6 +1022,74 @@ Node* WasmGraphBuilder::BuildF64CopySign(Node* left, Node* right) {
}
Node* WasmGraphBuilder::BuildF32Min(Node* left, Node* right) {
Diamond left_le_right(graph(), jsgraph()->common(),
Binop(wasm::kExprF32Le, left, right));
Diamond right_lt_left(graph(), jsgraph()->common(),
Binop(wasm::kExprF32Lt, right, left));
Diamond left_is_not_nan(graph(), jsgraph()->common(),
Binop(wasm::kExprF32Eq, left, left));
return left_le_right.Phi(
wasm::kAstF32, left,
right_lt_left.Phi(wasm::kAstF32, right,
left_is_not_nan.Phi(wasm::kAstF32, right, left)));
}
Node* WasmGraphBuilder::BuildF32Max(Node* left, Node* right) {
Diamond left_ge_right(graph(), jsgraph()->common(),
Binop(wasm::kExprF32Ge, left, right));
Diamond right_gt_left(graph(), jsgraph()->common(),
Binop(wasm::kExprF32Gt, right, left));
Diamond left_is_not_nan(graph(), jsgraph()->common(),
Binop(wasm::kExprF32Eq, left, left));
return left_ge_right.Phi(
wasm::kAstF32, left,
right_gt_left.Phi(wasm::kAstF32, right,
left_is_not_nan.Phi(wasm::kAstF32, right, left)));
}
Node* WasmGraphBuilder::BuildF64Min(Node* left, Node* right) {
Diamond left_le_right(graph(), jsgraph()->common(),
Binop(wasm::kExprF64Le, left, right));
Diamond right_lt_left(graph(), jsgraph()->common(),
Binop(wasm::kExprF64Lt, right, left));
Diamond left_is_not_nan(graph(), jsgraph()->common(),
Binop(wasm::kExprF64Eq, left, left));
return left_le_right.Phi(
wasm::kAstF64, left,
right_lt_left.Phi(wasm::kAstF64, right,
left_is_not_nan.Phi(wasm::kAstF64, right, left)));
}
Node* WasmGraphBuilder::BuildF64Max(Node* left, Node* right) {
Diamond left_ge_right(graph(), jsgraph()->common(),
Binop(wasm::kExprF64Ge, left, right));
Diamond right_gt_left(graph(), jsgraph()->common(),
Binop(wasm::kExprF64Lt, right, left));
Diamond left_is_not_nan(graph(), jsgraph()->common(),
Binop(wasm::kExprF64Eq, left, left));
return left_ge_right.Phi(
wasm::kAstF64, left,
right_gt_left.Phi(wasm::kAstF64, right,
left_is_not_nan.Phi(wasm::kAstF64, right, left)));
}
Node* WasmGraphBuilder::BuildI32Ctz(Node* input) {
//// Implement the following code as TF graph.
// value = value | (value << 1);
......
......@@ -164,6 +164,10 @@ class WasmGraphBuilder {
Node* BuildWasmCall(wasm::FunctionSig* sig, Node** args);
Node* BuildF32CopySign(Node* left, Node* right);
Node* BuildF64CopySign(Node* left, Node* right);
Node* BuildF32Min(Node* left, Node* right);
Node* BuildF32Max(Node* left, Node* right);
Node* BuildF64Min(Node* left, Node* right);
Node* BuildF64Max(Node* left, Node* right);
Node* BuildI32Ctz(Node* input);
Node* BuildI32Popcnt(Node* input);
Node* BuildI64Ctz(Node* input);
......
......@@ -3197,7 +3197,18 @@ TEST(Run_Wasm_F32Min) {
FOR_FLOAT32_INPUTS(i) {
FOR_FLOAT32_INPUTS(j) {
float expected = *i < *j ? *i : *j;
float expected;
if (*i < *j) {
expected = *i;
} else if (*j < *i) {
expected = *j;
} else if (*i != *i) {
// If *i or *j is NaN, then the result is NaN.
expected = *i;
} else {
expected = *j;
}
CheckFloatEq(expected, r.Call(*i, *j));
}
}
......@@ -3210,7 +3221,18 @@ TEST(Run_Wasm_F64Min) {
FOR_FLOAT64_INPUTS(i) {
FOR_FLOAT64_INPUTS(j) {
double expected = *i < *j ? *i : *j;
double expected;
if (*i < *j) {
expected = *i;
} else if (*j < *i) {
expected = *j;
} else if (*i != *i) {
// If *i or *j is NaN, then the result is NaN.
expected = *i;
} else {
expected = *j;
}
CheckDoubleEq(expected, r.Call(*i, *j));
}
}
......@@ -3223,7 +3245,18 @@ TEST(Run_Wasm_F32Max) {
FOR_FLOAT32_INPUTS(i) {
FOR_FLOAT32_INPUTS(j) {
float expected = *i > *j ? *i : *j;
float expected;
if (*i > *j) {
expected = *i;
} else if (*j > *i) {
expected = *j;
} else if (*i != *i) {
// If *i or *j is NaN, then the result is NaN.
expected = *i;
} else {
expected = *j;
}
CheckFloatEq(expected, r.Call(*i, *j));
}
}
......@@ -3236,7 +3269,18 @@ TEST(Run_Wasm_F64Max) {
FOR_FLOAT64_INPUTS(i) {
FOR_FLOAT64_INPUTS(j) {
double expected = *i > *j ? *i : *j;
double expected;
if (*i > *j) {
expected = *i;
} else if (*j > *i) {
expected = *j;
} else if (*i != *i) {
// If *i or *j is NaN, then the result is NaN.
expected = *i;
} else {
expected = *j;
}
CheckDoubleEq(expected, r.Call(*i, *j));
}
}
......
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