Commit 481502da authored by ahaas's avatar ahaas Committed by Commit bot

[turbofan] Introduce new operators Float32SubPreserveNan and Float64SubPreserveNan for wasm.

The operators are needed because the wasm spec requires that nan bits are preserved.

R=titzer@chromium.org

Review-Url: https://codereview.chromium.org/1973493003
Cr-Commit-Position: refs/heads/master@{#36212}
parent 51169f0c
......@@ -1205,6 +1205,35 @@ void InstructionSelector::VisitFloat64Add(Node* node) {
VisitRRR(this, kArmVaddF64, node);
}
namespace {
void VisitFloat32SubHelper(InstructionSelector* selector, Node* node) {
ArmOperandGenerator g(selector);
Float32BinopMatcher m(node);
if (m.right().IsFloat32Mul() && selector->CanCover(node, m.right().node())) {
Float32BinopMatcher mright(m.right().node());
selector->Emit(kArmVmlsF32, g.DefineSameAsFirst(node),
g.UseRegister(m.left().node()),
g.UseRegister(mright.left().node()),
g.UseRegister(mright.right().node()));
return;
}
VisitRRR(selector, kArmVsubF32, node);
}
void VisitFloat64SubHelper(InstructionSelector* selector, Node* node) {
ArmOperandGenerator g(selector);
Float64BinopMatcher m(node);
if (m.right().IsFloat64Mul() && selector->CanCover(node, m.right().node())) {
Float64BinopMatcher mright(m.right().node());
selector->Emit(kArmVmlsF64, g.DefineSameAsFirst(node),
g.UseRegister(m.left().node()),
g.UseRegister(mright.left().node()),
g.UseRegister(mright.right().node()));
return;
}
VisitRRR(selector, kArmVsubF64, node);
}
} // namespace
void InstructionSelector::VisitFloat32Sub(Node* node) {
ArmOperandGenerator g(this);
......@@ -1214,16 +1243,12 @@ void InstructionSelector::VisitFloat32Sub(Node* node) {
g.UseRegister(m.right().node()));
return;
}
if (m.right().IsFloat32Mul() && CanCover(node, m.right().node())) {
Float32BinopMatcher mright(m.right().node());
Emit(kArmVmlsF32, g.DefineSameAsFirst(node), g.UseRegister(m.left().node()),
g.UseRegister(mright.left().node()),
g.UseRegister(mright.right().node()));
return;
}
VisitRRR(this, kArmVsubF32, node);
VisitFloat32SubHelper(this, node);
}
void InstructionSelector::VisitFloat32SubPreserveNan(Node* node) {
VisitFloat32SubHelper(this, node);
}
void InstructionSelector::VisitFloat64Sub(Node* node) {
ArmOperandGenerator g(this);
......@@ -1245,16 +1270,12 @@ void InstructionSelector::VisitFloat64Sub(Node* node) {
g.UseRegister(m.right().node()));
return;
}
if (m.right().IsFloat64Mul() && CanCover(node, m.right().node())) {
Float64BinopMatcher mright(m.right().node());
Emit(kArmVmlsF64, g.DefineSameAsFirst(node), g.UseRegister(m.left().node()),
g.UseRegister(mright.left().node()),
g.UseRegister(mright.right().node()));
return;
}
VisitRRR(this, kArmVsubF64, node);
VisitFloat64SubHelper(this, node);
}
void InstructionSelector::VisitFloat64SubPreserveNan(Node* node) {
VisitFloat64SubHelper(this, node);
}
void InstructionSelector::VisitFloat32Mul(Node* node) {
VisitRRR(this, kArmVmulF32, node);
......
......@@ -1520,6 +1520,9 @@ void InstructionSelector::VisitFloat32Sub(Node* node) {
VisitRRR(this, kArm64Float32Sub, node);
}
void InstructionSelector::VisitFloat32SubPreserveNan(Node* node) {
VisitRRR(this, kArm64Float32Sub, node);
}
void InstructionSelector::VisitFloat64Sub(Node* node) {
Arm64OperandGenerator g(this);
......@@ -1544,6 +1547,9 @@ void InstructionSelector::VisitFloat64Sub(Node* node) {
VisitRRR(this, kArm64Float64Sub, node);
}
void InstructionSelector::VisitFloat64SubPreserveNan(Node* node) {
VisitRRR(this, kArm64Float64Sub, node);
}
void InstructionSelector::VisitFloat32Mul(Node* node) {
VisitRRR(this, kArm64Float32Mul, node);
......
......@@ -919,6 +919,9 @@ void InstructionSelector::VisitFloat32Sub(Node* node) {
VisitRROFloat(this, node, kAVXFloat32Sub, kSSEFloat32Sub);
}
void InstructionSelector::VisitFloat32SubPreserveNan(Node* node) {
VisitRROFloat(this, node, kAVXFloat32Sub, kSSEFloat32Sub);
}
void InstructionSelector::VisitFloat64Sub(Node* node) {
IA32OperandGenerator g(this);
......@@ -943,6 +946,9 @@ void InstructionSelector::VisitFloat64Sub(Node* node) {
VisitRROFloat(this, node, kAVXFloat64Sub, kSSEFloat64Sub);
}
void InstructionSelector::VisitFloat64SubPreserveNan(Node* node) {
VisitRROFloat(this, node, kAVXFloat64Sub, kSSEFloat64Sub);
}
void InstructionSelector::VisitFloat32Mul(Node* node) {
VisitRROFloat(this, node, kAVXFloat32Mul, kSSEFloat32Mul);
......
......@@ -1075,6 +1075,8 @@ void InstructionSelector::VisitNode(Node* node) {
return MarkAsFloat32(node), VisitFloat32Add(node);
case IrOpcode::kFloat32Sub:
return MarkAsFloat32(node), VisitFloat32Sub(node);
case IrOpcode::kFloat32SubPreserveNan:
return MarkAsFloat32(node), VisitFloat32SubPreserveNan(node);
case IrOpcode::kFloat32Mul:
return MarkAsFloat32(node), VisitFloat32Mul(node);
case IrOpcode::kFloat32Div:
......@@ -1097,6 +1099,8 @@ void InstructionSelector::VisitNode(Node* node) {
return MarkAsFloat64(node), VisitFloat64Add(node);
case IrOpcode::kFloat64Sub:
return MarkAsFloat64(node), VisitFloat64Sub(node);
case IrOpcode::kFloat64SubPreserveNan:
return MarkAsFloat64(node), VisitFloat64SubPreserveNan(node);
case IrOpcode::kFloat64Mul:
return MarkAsFloat64(node), VisitFloat64Mul(node);
case IrOpcode::kFloat64Div:
......
......@@ -149,12 +149,14 @@ MachineRepresentation AtomicStoreRepresentationOf(Operator const* op) {
V(Float32Abs, Operator::kNoProperties, 1, 0, 1) \
V(Float32Add, Operator::kCommutative, 2, 0, 1) \
V(Float32Sub, Operator::kNoProperties, 2, 0, 1) \
V(Float32SubPreserveNan, Operator::kNoProperties, 2, 0, 1) \
V(Float32Mul, Operator::kCommutative, 2, 0, 1) \
V(Float32Div, Operator::kNoProperties, 2, 0, 1) \
V(Float32Sqrt, Operator::kNoProperties, 1, 0, 1) \
V(Float64Abs, Operator::kNoProperties, 1, 0, 1) \
V(Float64Add, Operator::kCommutative, 2, 0, 1) \
V(Float64Sub, Operator::kNoProperties, 2, 0, 1) \
V(Float64SubPreserveNan, Operator::kNoProperties, 2, 0, 1) \
V(Float64Mul, Operator::kCommutative, 2, 0, 1) \
V(Float64Div, Operator::kNoProperties, 2, 0, 1) \
V(Float64Mod, Operator::kNoProperties, 2, 0, 1) \
......
......@@ -245,6 +245,7 @@ class MachineOperatorBuilder final : public ZoneObject {
// (single-precision).
const Operator* Float32Add();
const Operator* Float32Sub();
const Operator* Float32SubPreserveNan();
const Operator* Float32Mul();
const Operator* Float32Div();
const Operator* Float32Sqrt();
......@@ -253,6 +254,7 @@ class MachineOperatorBuilder final : public ZoneObject {
// (double-precision).
const Operator* Float64Add();
const Operator* Float64Sub();
const Operator* Float64SubPreserveNan();
const Operator* Float64Mul();
const Operator* Float64Div();
const Operator* Float64Mod();
......
......@@ -754,6 +754,9 @@ void InstructionSelector::VisitFloat32Sub(Node* node) {
VisitRRR(this, kMipsSubS, node);
}
void InstructionSelector::VisitFloat32SubPreserveNan(Node* node) {
VisitRRR(this, kMipsSubS, node);
}
void InstructionSelector::VisitFloat64Sub(Node* node) {
MipsOperandGenerator g(this);
......@@ -773,6 +776,9 @@ void InstructionSelector::VisitFloat64Sub(Node* node) {
VisitRRR(this, kMipsSubD, node);
}
void InstructionSelector::VisitFloat64SubPreserveNan(Node* node) {
VisitRRR(this, kMipsSubD, node);
}
void InstructionSelector::VisitFloat32Mul(Node* node) {
VisitRRR(this, kMipsMulS, node);
......
......@@ -1159,6 +1159,9 @@ void InstructionSelector::VisitFloat32Sub(Node* node) {
VisitRRR(this, kMips64SubS, node);
}
void InstructionSelector::VisitFloat32SubPreserveNan(Node* node) {
VisitRRR(this, kMips64SubS, node);
}
void InstructionSelector::VisitFloat64Sub(Node* node) {
Mips64OperandGenerator g(this);
......@@ -1178,6 +1181,9 @@ void InstructionSelector::VisitFloat64Sub(Node* node) {
VisitRRR(this, kMips64SubD, node);
}
void InstructionSelector::VisitFloat64SubPreserveNan(Node* node) {
VisitRRR(this, kMips64SubD, node);
}
void InstructionSelector::VisitFloat32Mul(Node* node) {
VisitRRR(this, kMips64MulS, node);
......
......@@ -317,6 +317,7 @@
V(BitcastInt64ToFloat64) \
V(Float32Add) \
V(Float32Sub) \
V(Float32SubPreserveNan) \
V(Float32Mul) \
V(Float32Div) \
V(Float32Max) \
......@@ -326,6 +327,7 @@
V(Float32RoundDown) \
V(Float64Add) \
V(Float64Sub) \
V(Float64SubPreserveNan) \
V(Float64Mul) \
V(Float64Div) \
V(Float64Mod) \
......
......@@ -1226,6 +1226,10 @@ void InstructionSelector::VisitFloat32Sub(Node* node) {
VisitRRR(this, kPPC_SubDouble | MiscField::encode(1), node);
}
void InstructionSelector::VisitFloat32SubPreserveNan(Node* node) {
PPCOperandGenerator g(this);
VisitRRR(this, kPPC_SubDouble | MiscField::encode(1), node);
}
void InstructionSelector::VisitFloat64Sub(Node* node) {
// TODO(mbrandy): detect multiply-subtract
......@@ -1252,6 +1256,9 @@ void InstructionSelector::VisitFloat64Sub(Node* node) {
VisitRRR(this, kPPC_SubDouble, node);
}
void InstructionSelector::VisitFloat64SubPreserveNan(Node* node) {
VisitRRR(this, kPPC_SubDouble, node);
}
void InstructionSelector::VisitFloat32Mul(Node* node) {
VisitRRR(this, kPPC_MulDouble | MiscField::encode(1), node);
......
......@@ -399,6 +399,9 @@ class RawMachineAssembler {
Node* Float32Sub(Node* a, Node* b) {
return AddNode(machine()->Float32Sub(), a, b);
}
Node* Float32SubPreserveNan(Node* a, Node* b) {
return AddNode(machine()->Float32SubPreserveNan(), a, b);
}
Node* Float32Mul(Node* a, Node* b) {
return AddNode(machine()->Float32Mul(), a, b);
}
......@@ -437,6 +440,9 @@ class RawMachineAssembler {
Node* Float64Sub(Node* a, Node* b) {
return AddNode(machine()->Float64Sub(), a, b);
}
Node* Float64SubPreserveNan(Node* a, Node* b) {
return AddNode(machine()->Float64SubPreserveNan(), a, b);
}
Node* Float64Mul(Node* a, Node* b) {
return AddNode(machine()->Float64Mul(), a, b);
}
......
......@@ -1117,6 +1117,11 @@ void InstructionSelector::VisitFloat32Sub(Node* node) {
VisitRRR(this, kS390_SubFloat, node);
}
void InstructionSelector::VisitFloat32SubPreserveNan(Node* node) {
S390OperandGenerator g(this);
VisitRRR(this, kS390_SubFloat, node);
}
void InstructionSelector::VisitFloat64Sub(Node* node) {
// TODO(mbrandy): detect multiply-subtract
S390OperandGenerator g(this);
......@@ -1142,6 +1147,10 @@ void InstructionSelector::VisitFloat64Sub(Node* node) {
VisitRRR(this, kS390_SubDouble, node);
}
void InstructionSelector::VisitFloat64SubPreserveNan(Node* node) {
VisitRRR(this, kS390_SubDouble, node);
}
void InstructionSelector::VisitFloat32Mul(Node* node) {
VisitRRR(this, kS390_MulFloat, node);
}
......
......@@ -2343,6 +2343,9 @@ Type* Typer::Visitor::TypeFloat32Add(Node* node) { return Type::Number(); }
Type* Typer::Visitor::TypeFloat32Sub(Node* node) { return Type::Number(); }
Type* Typer::Visitor::TypeFloat32SubPreserveNan(Node* node) {
return Type::Number();
}
Type* Typer::Visitor::TypeFloat32Mul(Node* node) { return Type::Number(); }
......@@ -2383,6 +2386,9 @@ Type* Typer::Visitor::TypeFloat64Add(Node* node) { return Type::Number(); }
Type* Typer::Visitor::TypeFloat64Sub(Node* node) { return Type::Number(); }
Type* Typer::Visitor::TypeFloat64SubPreserveNan(Node* node) {
return Type::Number();
}
Type* Typer::Visitor::TypeFloat64Mul(Node* node) { return Type::Number(); }
......
......@@ -951,6 +951,7 @@ void Verifier::Visitor::Check(Node* node) {
case IrOpcode::kUint64LessThanOrEqual:
case IrOpcode::kFloat32Add:
case IrOpcode::kFloat32Sub:
case IrOpcode::kFloat32SubPreserveNan:
case IrOpcode::kFloat32Mul:
case IrOpcode::kFloat32Div:
case IrOpcode::kFloat32Max:
......@@ -962,6 +963,7 @@ void Verifier::Visitor::Check(Node* node) {
case IrOpcode::kFloat32LessThanOrEqual:
case IrOpcode::kFloat64Add:
case IrOpcode::kFloat64Sub:
case IrOpcode::kFloat64SubPreserveNan:
case IrOpcode::kFloat64Mul:
case IrOpcode::kFloat64Div:
case IrOpcode::kFloat64Mod:
......
......@@ -538,7 +538,7 @@ Node* WasmGraphBuilder::Binop(wasm::WasmOpcode opcode, Node* left, Node* right,
op = m->Float32Add();
break;
case wasm::kExprF32Sub:
op = m->Float32Sub();
op = m->Float32SubPreserveNan();
break;
case wasm::kExprF32Mul:
op = m->Float32Mul();
......@@ -569,7 +569,7 @@ Node* WasmGraphBuilder::Binop(wasm::WasmOpcode opcode, Node* left, Node* right,
op = m->Float64Add();
break;
case wasm::kExprF64Sub:
op = m->Float64Sub();
op = m->Float64SubPreserveNan();
break;
case wasm::kExprF64Mul:
op = m->Float64Mul();
......
......@@ -1252,6 +1252,9 @@ void InstructionSelector::VisitFloat32Sub(Node* node) {
VisitFloatBinop(this, node, kAVXFloat32Sub, kSSEFloat32Sub);
}
void InstructionSelector::VisitFloat32SubPreserveNan(Node* node) {
VisitFloatBinop(this, node, kAVXFloat32Sub, kSSEFloat32Sub);
}
void InstructionSelector::VisitFloat32Mul(Node* node) {
VisitFloatBinop(this, node, kAVXFloat32Mul, kSSEFloat32Mul);
......@@ -1311,6 +1314,9 @@ void InstructionSelector::VisitFloat64Sub(Node* node) {
VisitFloatBinop(this, node, kAVXFloat64Sub, kSSEFloat64Sub);
}
void InstructionSelector::VisitFloat64SubPreserveNan(Node* node) {
VisitFloatBinop(this, node, kAVXFloat64Sub, kSSEFloat64Sub);
}
void InstructionSelector::VisitFloat64Mul(Node* node) {
VisitFloatBinop(this, node, kAVXFloat64Mul, kSSEFloat64Mul);
......
......@@ -897,6 +897,12 @@ void InstructionSelector::VisitFloat32Sub(Node* node) {
Emit(kX87Float32Sub, g.DefineAsFixed(node, stX_0), 0, nullptr);
}
void InstructionSelector::VisitFloat32SubPreserveNan(Node* node) {
X87OperandGenerator g(this);
Emit(kX87PushFloat32, g.NoOutput(), g.Use(node->InputAt(0)));
Emit(kX87PushFloat32, g.NoOutput(), g.Use(node->InputAt(1)));
Emit(kX87Float32Sub, g.DefineAsFixed(node, stX_0), 0, nullptr);
}
void InstructionSelector::VisitFloat64Sub(Node* node) {
X87OperandGenerator g(this);
......@@ -905,6 +911,13 @@ void InstructionSelector::VisitFloat64Sub(Node* node) {
Emit(kX87Float64Sub, g.DefineAsFixed(node, stX_0), 0, nullptr);
}
void InstructionSelector::VisitFloat64SubPreserveNan(Node* node) {
X87OperandGenerator g(this);
Emit(kX87PushFloat64, g.NoOutput(), g.Use(node->InputAt(0)));
Emit(kX87PushFloat64, g.NoOutput(), g.Use(node->InputAt(1)));
Emit(kX87Float64Sub, g.DefineAsFixed(node, stX_0), 0, nullptr);
}
void InstructionSelector::VisitFloat32Mul(Node* node) {
X87OperandGenerator g(this);
......
......@@ -581,6 +581,21 @@ TEST(Run_WasmFloat32Neg) {
}
}
TEST(Run_WasmFloat32SubMinusZero) {
WasmRunner<float> r(MachineType::Float32());
BUILD(r, WASM_F32_SUB(WASM_F32(-0.0), WASM_GET_LOCAL(0)));
CHECK_EQ(0x7fe00000, bit_cast<uint32_t>(r.Call(bit_cast<float>(0x7fa00000))));
}
TEST(Run_WasmFloat64SubMinusZero) {
WasmRunner<double> r(MachineType::Float64());
BUILD(r, WASM_F64_SUB(WASM_F64(-0.0), WASM_GET_LOCAL(0)));
CHECK_EQ(0x7ff8123456789abc,
bit_cast<uint64_t>(r.Call(bit_cast<double>(0x7ff0123456789abc))));
}
TEST(Run_WasmFloat64Neg) {
WasmRunner<double> r(MachineType::Float64());
BUILD(r, WASM_F64_NEG(WASM_GET_LOCAL(0)));
......
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