Commit 612bad1d authored by georgia.kouveli's avatar georgia.kouveli Committed by Commit bot

[arm] [arm64] Add optional operators Float32Neg and Float64Neg.

Adding optional operators for FNeg for WebAssembly, as the current implementation was significantly suboptimal for ARM.

Review-Url: https://codereview.chromium.org/2011303002
Cr-Commit-Position: refs/heads/master@{#36544}
parent 8c31bd81
......@@ -1440,6 +1440,13 @@ void InstructionSelector::VisitFloat64RoundTiesEven(Node* node) {
VisitRR(this, kArmVrintnF64, node);
}
void InstructionSelector::VisitFloat32Neg(Node* node) {
VisitRR(this, kArmVnegF32, node);
}
void InstructionSelector::VisitFloat64Neg(Node* node) {
VisitRR(this, kArmVnegF64, node);
}
void InstructionSelector::EmitPrepareArguments(
ZoneVector<PushParameter>* arguments, const CallDescriptor* descriptor,
......@@ -1963,7 +1970,9 @@ InstructionSelector::SupportedMachineOperatorFlags() {
MachineOperatorBuilder::kFloat32Min |
MachineOperatorBuilder::kFloat32Max |
MachineOperatorBuilder::kFloat64Min |
MachineOperatorBuilder::kFloat64Max;
MachineOperatorBuilder::kFloat64Max |
MachineOperatorBuilder::kFloat32Neg |
MachineOperatorBuilder::kFloat64Neg;
}
return flags;
}
......
......@@ -1183,6 +1183,9 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
case kArm64Float32Abs:
__ Fabs(i.OutputFloat32Register(), i.InputFloat32Register(0));
break;
case kArm64Float32Neg:
__ Fneg(i.OutputFloat32Register(), i.InputFloat32Register(0));
break;
case kArm64Float32Sqrt:
__ Fsqrt(i.OutputFloat32Register(), i.InputFloat32Register(0));
break;
......
......@@ -91,6 +91,7 @@ namespace compiler {
V(Arm64Float32Max) \
V(Arm64Float32Min) \
V(Arm64Float32Abs) \
V(Arm64Float32Neg) \
V(Arm64Float32Sqrt) \
V(Arm64Float32RoundDown) \
V(Arm64Float64Cmp) \
......
......@@ -85,6 +85,7 @@ int InstructionScheduler::GetTargetInstructionFlags(
case kArm64Float32Max:
case kArm64Float32Min:
case kArm64Float32Abs:
case kArm64Float32Neg:
case kArm64Float32Sqrt:
case kArm64Float32RoundDown:
case kArm64Float64Cmp:
......@@ -291,6 +292,7 @@ int InstructionScheduler::GetInstructionLatency(const Instruction* instr) {
case kArm64Float32Abs:
case kArm64Float32Cmp:
case kArm64Float32Neg:
case kArm64Float64Abs:
case kArm64Float64Cmp:
case kArm64Float64Neg:
......
......@@ -1720,6 +1720,13 @@ void InstructionSelector::VisitFloat64RoundTiesEven(Node* node) {
VisitRR(this, kArm64Float64RoundTiesEven, node);
}
void InstructionSelector::VisitFloat32Neg(Node* node) {
VisitRR(this, kArm64Float32Neg, node);
}
void InstructionSelector::VisitFloat64Neg(Node* node) {
VisitRR(this, kArm64Float64Neg, node);
}
void InstructionSelector::EmitPrepareArguments(
ZoneVector<PushParameter>* arguments, const CallDescriptor* descriptor,
......@@ -2414,7 +2421,9 @@ InstructionSelector::SupportedMachineOperatorFlags() {
MachineOperatorBuilder::kInt32DivIsSafe |
MachineOperatorBuilder::kUint32DivIsSafe |
MachineOperatorBuilder::kWord32ReverseBits |
MachineOperatorBuilder::kWord64ReverseBits;
MachineOperatorBuilder::kWord64ReverseBits |
MachineOperatorBuilder::kFloat32Neg |
MachineOperatorBuilder::kFloat64Neg;
}
// static
......
......@@ -1069,6 +1069,9 @@ void InstructionSelector::VisitFloat64RoundTiesEven(Node* node) {
VisitRR(this, node, kSSEFloat64Round | MiscField::encode(kRoundToNearest));
}
void InstructionSelector::VisitFloat32Neg(Node* node) { UNREACHABLE(); }
void InstructionSelector::VisitFloat64Neg(Node* node) { UNREACHABLE(); }
void InstructionSelector::EmitPrepareArguments(
ZoneVector<PushParameter>* arguments, const CallDescriptor* descriptor,
......
......@@ -1084,6 +1084,8 @@ void InstructionSelector::VisitNode(Node* node) {
return MarkAsFloat32(node), VisitFloat32Sub(node);
case IrOpcode::kFloat32SubPreserveNan:
return MarkAsFloat32(node), VisitFloat32SubPreserveNan(node);
case IrOpcode::kFloat32Neg:
return MarkAsFloat32(node), VisitFloat32Neg(node);
case IrOpcode::kFloat32Mul:
return MarkAsFloat32(node), VisitFloat32Mul(node);
case IrOpcode::kFloat32Div:
......@@ -1108,6 +1110,8 @@ void InstructionSelector::VisitNode(Node* node) {
return MarkAsFloat64(node), VisitFloat64Sub(node);
case IrOpcode::kFloat64SubPreserveNan:
return MarkAsFloat64(node), VisitFloat64SubPreserveNan(node);
case IrOpcode::kFloat64Neg:
return MarkAsFloat64(node), VisitFloat64Neg(node);
case IrOpcode::kFloat64Mul:
return MarkAsFloat64(node), VisitFloat64Mul(node);
case IrOpcode::kFloat64Div:
......
......@@ -372,7 +372,9 @@ MachineRepresentation AtomicStoreRepresentationOf(Operator const* op) {
V(Float64RoundTruncate, Operator::kNoProperties, 1, 0, 1) \
V(Float64RoundTiesAway, Operator::kNoProperties, 1, 0, 1) \
V(Float32RoundTiesEven, Operator::kNoProperties, 1, 0, 1) \
V(Float64RoundTiesEven, Operator::kNoProperties, 1, 0, 1)
V(Float64RoundTiesEven, Operator::kNoProperties, 1, 0, 1) \
V(Float32Neg, Operator::kNoProperties, 1, 0, 1) \
V(Float64Neg, Operator::kNoProperties, 1, 0, 1)
#define MACHINE_TYPE_LIST(V) \
V(Float32) \
......
......@@ -113,13 +113,15 @@ class MachineOperatorBuilder final : public ZoneObject {
kWord64Popcnt = 1u << 19,
kWord32ReverseBits = 1u << 20,
kWord64ReverseBits = 1u << 21,
kAllOptionalOps = kFloat32Max | kFloat32Min | kFloat64Max | kFloat64Min |
kFloat32RoundDown | kFloat64RoundDown | kFloat32RoundUp |
kFloat64RoundUp | kFloat32RoundTruncate |
kFloat64RoundTruncate | kFloat64RoundTiesAway |
kFloat32RoundTiesEven | kFloat64RoundTiesEven |
kWord32Ctz | kWord64Ctz | kWord32Popcnt | kWord64Popcnt |
kWord32ReverseBits | kWord64ReverseBits
kFloat32Neg = 1u << 22,
kFloat64Neg = 1u << 23,
kAllOptionalOps =
kFloat32Max | kFloat32Min | kFloat64Max | kFloat64Min |
kFloat32RoundDown | kFloat64RoundDown | kFloat32RoundUp |
kFloat64RoundUp | kFloat32RoundTruncate | kFloat64RoundTruncate |
kFloat64RoundTiesAway | kFloat32RoundTiesEven | kFloat64RoundTiesEven |
kWord32Ctz | kWord64Ctz | kWord32Popcnt | kWord64Popcnt |
kWord32ReverseBits | kWord64ReverseBits | kFloat32Neg | kFloat64Neg
};
typedef base::Flags<Flag, unsigned> Flags;
......@@ -361,6 +363,10 @@ class MachineOperatorBuilder final : public ZoneObject {
const OptionalOperator Float32RoundTiesEven();
const OptionalOperator Float64RoundTiesEven();
// Floating point neg.
const OptionalOperator Float32Neg();
const OptionalOperator Float64Neg();
// Floating point bit representation.
const Operator* Float64ExtractLowWord32();
const Operator* Float64ExtractHighWord32();
......
......@@ -931,6 +931,9 @@ void InstructionSelector::VisitFloat64RoundTiesEven(Node* node) {
VisitRR(this, kMipsFloat64RoundTiesEven, node);
}
void InstructionSelector::VisitFloat32Neg(Node* node) { UNREACHABLE(); }
void InstructionSelector::VisitFloat64Neg(Node* node) { UNREACHABLE(); }
void InstructionSelector::EmitPrepareArguments(
ZoneVector<PushParameter>* arguments, const CallDescriptor* descriptor,
......
......@@ -1337,6 +1337,9 @@ void InstructionSelector::VisitFloat64RoundTiesEven(Node* node) {
VisitRR(this, kMips64Float64RoundTiesEven, node);
}
void InstructionSelector::VisitFloat32Neg(Node* node) { UNREACHABLE(); }
void InstructionSelector::VisitFloat64Neg(Node* node) { UNREACHABLE(); }
void InstructionSelector::EmitPrepareArguments(
ZoneVector<PushParameter>* arguments, const CallDescriptor* descriptor,
......
......@@ -323,6 +323,7 @@
V(Float32Add) \
V(Float32Sub) \
V(Float32SubPreserveNan) \
V(Float32Neg) \
V(Float32Mul) \
V(Float32Div) \
V(Float32Max) \
......@@ -333,6 +334,7 @@
V(Float64Add) \
V(Float64Sub) \
V(Float64SubPreserveNan) \
V(Float64Neg) \
V(Float64Mul) \
V(Float64Div) \
V(Float64Mod) \
......
......@@ -1365,6 +1365,9 @@ void InstructionSelector::VisitFloat64RoundTiesEven(Node* node) {
UNREACHABLE();
}
void InstructionSelector::VisitFloat32Neg(Node* node) { UNREACHABLE(); }
void InstructionSelector::VisitFloat64Neg(Node* node) { UNREACHABLE(); }
void InstructionSelector::VisitInt32AddWithOverflow(Node* node) {
if (Node* ovf = NodeProperties::FindProjection(node, 1)) {
......
......@@ -1235,6 +1235,10 @@ void InstructionSelector::VisitFloat64RoundTiesEven(Node* node) {
UNREACHABLE();
}
void InstructionSelector::VisitFloat32Neg(Node* node) { UNREACHABLE(); }
void InstructionSelector::VisitFloat64Neg(Node* node) { UNREACHABLE(); }
void InstructionSelector::VisitInt32AddWithOverflow(Node* node) {
if (Node* ovf = NodeProperties::FindProjection(node, 1)) {
FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf);
......
......@@ -2363,6 +2363,8 @@ Type* Typer::Visitor::TypeFloat32SubPreserveNan(Node* node) {
return Type::Number();
}
Type* Typer::Visitor::TypeFloat32Neg(Node* node) { return Type::Number(); }
Type* Typer::Visitor::TypeFloat32Mul(Node* node) { return Type::Number(); }
......@@ -2406,6 +2408,8 @@ Type* Typer::Visitor::TypeFloat64SubPreserveNan(Node* node) {
return Type::Number();
}
Type* Typer::Visitor::TypeFloat64Neg(Node* node) { return Type::Number(); }
Type* Typer::Visitor::TypeFloat64Mul(Node* node) { return Type::Number(); }
......
......@@ -977,6 +977,7 @@ void Verifier::Visitor::Check(Node* node) {
case IrOpcode::kFloat32Add:
case IrOpcode::kFloat32Sub:
case IrOpcode::kFloat32SubPreserveNan:
case IrOpcode::kFloat32Neg:
case IrOpcode::kFloat32Mul:
case IrOpcode::kFloat32Div:
case IrOpcode::kFloat32Max:
......@@ -989,6 +990,7 @@ void Verifier::Visitor::Check(Node* node) {
case IrOpcode::kFloat64Add:
case IrOpcode::kFloat64Sub:
case IrOpcode::kFloat64SubPreserveNan:
case IrOpcode::kFloat64Neg:
case IrOpcode::kFloat64Mul:
case IrOpcode::kFloat64Div:
case IrOpcode::kFloat64Mod:
......
......@@ -645,16 +645,28 @@ Node* WasmGraphBuilder::Unop(wasm::WasmOpcode opcode, Node* input,
case wasm::kExprF32Abs:
op = m->Float32Abs();
break;
case wasm::kExprF32Neg:
return BuildF32Neg(input);
case wasm::kExprF32Neg: {
if (m->Float32Neg().IsSupported()) {
op = m->Float32Neg().op();
break;
} else {
return BuildF32Neg(input);
}
}
case wasm::kExprF32Sqrt:
op = m->Float32Sqrt();
break;
case wasm::kExprF64Abs:
op = m->Float64Abs();
break;
case wasm::kExprF64Neg:
return BuildF64Neg(input);
case wasm::kExprF64Neg: {
if (m->Float64Neg().IsSupported()) {
op = m->Float64Neg().op();
break;
} else {
return BuildF64Neg(input);
}
}
case wasm::kExprF64Sqrt:
op = m->Float64Sqrt();
break;
......
......@@ -1405,6 +1405,9 @@ void InstructionSelector::VisitFloat64RoundTiesEven(Node* node) {
VisitRR(this, node, kSSEFloat64Round | MiscField::encode(kRoundToNearest));
}
void InstructionSelector::VisitFloat32Neg(Node* node) { UNREACHABLE(); }
void InstructionSelector::VisitFloat64Neg(Node* node) { UNREACHABLE(); }
void InstructionSelector::EmitPrepareArguments(
ZoneVector<PushParameter>* arguments, const CallDescriptor* descriptor,
......
......@@ -1084,6 +1084,9 @@ void InstructionSelector::VisitFloat64RoundTiesEven(Node* node) {
g.UseFixed(node, stX_0), g.Use(node->InputAt(0)));
}
void InstructionSelector::VisitFloat32Neg(Node* node) { UNREACHABLE(); }
void InstructionSelector::VisitFloat64Neg(Node* node) { UNREACHABLE(); }
void InstructionSelector::EmitPrepareArguments(
ZoneVector<PushParameter>* arguments, const CallDescriptor* descriptor,
......
......@@ -3568,6 +3568,12 @@ TEST(RunFloat32Sub) {
}
}
TEST(RunFloat32Neg) {
BufferedRawMachineAssemblerTester<float> m(MachineType::Float32());
if (!m.machine()->Float32Neg().IsSupported()) return;
m.Return(m.AddNode(m.machine()->Float32Neg().op(), m.Parameter(0)));
FOR_FLOAT32_INPUTS(i) { CHECK_FLOAT_EQ(-0.0f - *i, m.Call(*i)); }
}
TEST(RunFloat32Mul) {
BufferedRawMachineAssemblerTester<float> m(MachineType::Float32(),
......@@ -3612,6 +3618,12 @@ TEST(RunFloat64Sub) {
}
}
TEST(RunFloat64Neg) {
BufferedRawMachineAssemblerTester<double> m(MachineType::Float64());
if (!m.machine()->Float64Neg().IsSupported()) return;
m.Return(m.AddNode(m.machine()->Float64Neg().op(), m.Parameter(0)));
FOR_FLOAT64_INPUTS(i) { CHECK_FLOAT_EQ(-0.0 - *i, m.Call(*i)); }
}
TEST(RunFloat64Mul) {
BufferedRawMachineAssemblerTester<double> m(MachineType::Float64(),
......
......@@ -3059,6 +3059,36 @@ TEST_F(InstructionSelectorTest, Float64Min) {
EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
}
TEST_F(InstructionSelectorTest, Float32Neg) {
StreamBuilder m(this, MachineType::Float32(), MachineType::Float32());
Node* const p0 = m.Parameter(0);
// Don't use m.Float32Neg() as that generates an explicit sub.
Node* const n = m.AddNode(m.machine()->Float32Neg().op(), m.Parameter(0));
m.Return(n);
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
EXPECT_EQ(kArmVnegF32, s[0]->arch_opcode());
ASSERT_EQ(1U, s[0]->InputCount());
EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
ASSERT_EQ(1U, s[0]->OutputCount());
EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
}
TEST_F(InstructionSelectorTest, Float64Neg) {
StreamBuilder m(this, MachineType::Float64(), MachineType::Float64());
Node* const p0 = m.Parameter(0);
// Don't use m.Float64Neg() as that generates an explicit sub.
Node* const n = m.AddNode(m.machine()->Float64Neg().op(), m.Parameter(0));
m.Return(n);
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
EXPECT_EQ(kArmVnegF64, s[0]->arch_opcode());
ASSERT_EQ(1U, s[0]->InputCount());
EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
ASSERT_EQ(1U, s[0]->OutputCount());
EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
}
} // namespace compiler
} // namespace internal
} // namespace v8
......@@ -3574,6 +3574,36 @@ TEST_F(InstructionSelectorTest, Float64Min) {
EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
}
TEST_F(InstructionSelectorTest, Float32Neg) {
StreamBuilder m(this, MachineType::Float32(), MachineType::Float32());
Node* const p0 = m.Parameter(0);
// Don't use m.Float32Neg() as that generates an explicit sub.
Node* const n = m.AddNode(m.machine()->Float32Neg().op(), m.Parameter(0));
m.Return(n);
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
EXPECT_EQ(kArm64Float32Neg, s[0]->arch_opcode());
ASSERT_EQ(1U, s[0]->InputCount());
EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
ASSERT_EQ(1U, s[0]->OutputCount());
EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
}
TEST_F(InstructionSelectorTest, Float64Neg) {
StreamBuilder m(this, MachineType::Float64(), MachineType::Float64());
Node* const p0 = m.Parameter(0);
// Don't use m.Float64Neg() as that generates an explicit sub.
Node* const n = m.AddNode(m.machine()->Float64Neg().op(), m.Parameter(0));
m.Return(n);
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
EXPECT_EQ(kArm64Float64Neg, s[0]->arch_opcode());
ASSERT_EQ(1U, s[0]->InputCount());
EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
ASSERT_EQ(1U, s[0]->OutputCount());
EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
}
} // namespace compiler
} // namespace internal
} // namespace v8
......@@ -327,6 +327,8 @@ const OptionalOperatorEntry kOptionalOperators[] = {
OPTIONAL_ENTRY(Float64RoundDown, 1, 0, 1), // --
OPTIONAL_ENTRY(Float64RoundTruncate, 1, 0, 1), // --
OPTIONAL_ENTRY(Float64RoundTiesAway, 1, 0, 1), // --
OPTIONAL_ENTRY(Float32Neg, 1, 0, 1), // --
OPTIONAL_ENTRY(Float64Neg, 1, 0, 1), // --
#undef OPTIONAL_ENTRY
};
} // namespace
......
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