[wasm] Fixed FxxNeg for inputs of NaN.

The new implementation also changes the sign bit if the input is NaN.
(https://github.com/WebAssembly/v8-native-prototype/issues/99)

R=bradnelson@chromium.org

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

Cr-Commit-Position: refs/heads/master@{#32894}
This commit is contained in:
ahaas 2015-12-16 03:44:46 -08:00 committed by Commit bot
parent 13412d6693
commit 7ae140fe91
3 changed files with 42 additions and 14 deletions

View File

@ -664,8 +664,7 @@ Node* WasmGraphBuilder::Unop(wasm::WasmOpcode opcode, Node* input) {
op = m->Float32Abs();
break;
case wasm::kExprF32Neg:
op = m->Float32Mul();
return graph()->NewNode(op, jsgraph()->Float32Constant(-1), input);
return BuildF32Neg(input);
case wasm::kExprF32Sqrt:
op = m->Float32Sqrt();
break;
@ -673,8 +672,7 @@ Node* WasmGraphBuilder::Unop(wasm::WasmOpcode opcode, Node* input) {
op = m->Float64Abs();
break;
case wasm::kExprF64Neg:
op = m->Float64Mul();
return graph()->NewNode(op, jsgraph()->Float64Constant(-1), input);
return BuildF64Neg(input);
case wasm::kExprF64Sqrt:
op = m->Float64Sqrt();
break;
@ -980,6 +978,36 @@ Node* WasmGraphBuilder::Unreachable() {
}
Node* WasmGraphBuilder::BuildF32Neg(Node* input) {
Node* result =
Unop(wasm::kExprF32ReinterpretI32,
Binop(wasm::kExprI32Xor, Unop(wasm::kExprI32ReinterpretF32, input),
jsgraph()->Int32Constant(0x80000000)));
return result;
}
Node* WasmGraphBuilder::BuildF64Neg(Node* input) {
#if WASM_64
Node* result =
Unop(wasm::kExprF64ReinterpretI64,
Binop(wasm::kExprI64Xor, Unop(wasm::kExprI64ReinterpretF64, input),
jsgraph()->Int64Constant(0x8000000000000000)));
return result;
#else
MachineOperatorBuilder* m = jsgraph()->machine();
Node* old_high_word = graph()->NewNode(m->Float64ExtractHighWord32(), input);
Node* new_high_word = Binop(wasm::kExprI32Xor, old_high_word,
jsgraph()->Int32Constant(0x80000000));
return graph()->NewNode(m->Float64InsertHighWord32(), input, new_high_word);
#endif
}
Node* WasmGraphBuilder::BuildF32CopySign(Node* left, Node* right) {
Node* result = Unop(
wasm::kExprF32ReinterpretI32,

View File

@ -162,6 +162,8 @@ class WasmGraphBuilder {
void BoundsCheckMem(MachineType memtype, Node* index, uint32_t offset);
Node* BuildWasmCall(wasm::FunctionSig* sig, Node** args);
Node* BuildF32Neg(Node* input);
Node* BuildF64Neg(Node* input);
Node* BuildF32CopySign(Node* left, Node* right);
Node* BuildF64CopySign(Node* left, Node* right);
Node* BuildF32Min(Node* left, Node* right);

View File

@ -1157,11 +1157,10 @@ TEST(Run_WasmFloat32Neg) {
WasmRunner<float> r(MachineType::Float32());
BUILD(r, WASM_F32_NEG(WASM_GET_LOCAL(0)));
FOR_FLOAT32_INPUTS(i) { CheckFloatEq(-(*i), r.Call(*i)); }
// The difference between +0 and -0 matters here.
CHECK_EQ(bit_cast<uint32_t>(-0.0f), bit_cast<uint32_t>(r.Call(0.0f)));
CHECK_EQ(bit_cast<uint32_t>(0.0f), bit_cast<uint32_t>(r.Call(-0.0f)));
FOR_FLOAT32_INPUTS(i) {
CHECK_EQ(0x80000000,
bit_cast<uint32_t>(*i) ^ bit_cast<uint32_t>(r.Call(*i)));
}
}
@ -1169,11 +1168,10 @@ TEST(Run_WasmFloat64Neg) {
WasmRunner<double> r(MachineType::Float64());
BUILD(r, WASM_F64_NEG(WASM_GET_LOCAL(0)));
FOR_FLOAT64_INPUTS(i) { CheckDoubleEq(-(*i), r.Call(*i)); }
// The difference between +0 and -0 matters here.
CHECK_EQ(bit_cast<uint64_t>(-0.0), bit_cast<uint64_t>(r.Call(0.0)));
CHECK_EQ(bit_cast<uint64_t>(0.0), bit_cast<uint64_t>(r.Call(-0.0)));
FOR_FLOAT64_INPUTS(i) {
CHECK_EQ(0x8000000000000000,
bit_cast<uint64_t>(*i) ^ bit_cast<uint64_t>(r.Call(*i)));
}
}