[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:
parent
13412d6693
commit
7ae140fe91
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user