Commit 2aed882f authored by Benedikt Meurer's avatar Benedikt Meurer

[arm] Fix recognition of VNEG.

TEST=mjsunit,unittests
R=svenpanne@chromium.org

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

Cr-Commit-Position: refs/heads/master@{#25513}
parent e04727e7
...@@ -854,16 +854,16 @@ void InstructionSelector::VisitTruncateFloat64ToFloat32(Node* node) { ...@@ -854,16 +854,16 @@ void InstructionSelector::VisitTruncateFloat64ToFloat32(Node* node) {
void InstructionSelector::VisitFloat64Add(Node* node) { void InstructionSelector::VisitFloat64Add(Node* node) {
ArmOperandGenerator g(this); ArmOperandGenerator g(this);
Int32BinopMatcher m(node); Float64BinopMatcher m(node);
if (m.left().IsFloat64Mul() && CanCover(node, m.left().node())) { if (m.left().IsFloat64Mul() && CanCover(node, m.left().node())) {
Int32BinopMatcher mleft(m.left().node()); Float64BinopMatcher mleft(m.left().node());
Emit(kArmVmlaF64, g.DefineSameAsFirst(node), Emit(kArmVmlaF64, g.DefineSameAsFirst(node),
g.UseRegister(m.right().node()), g.UseRegister(mleft.left().node()), g.UseRegister(m.right().node()), g.UseRegister(mleft.left().node()),
g.UseRegister(mleft.right().node())); g.UseRegister(mleft.right().node()));
return; return;
} }
if (m.right().IsFloat64Mul() && CanCover(node, m.right().node())) { if (m.right().IsFloat64Mul() && CanCover(node, m.right().node())) {
Int32BinopMatcher mright(m.right().node()); Float64BinopMatcher mright(m.right().node());
Emit(kArmVmlaF64, g.DefineSameAsFirst(node), g.UseRegister(m.left().node()), Emit(kArmVmlaF64, g.DefineSameAsFirst(node), g.UseRegister(m.left().node()),
g.UseRegister(mright.left().node()), g.UseRegister(mright.left().node()),
g.UseRegister(mright.right().node())); g.UseRegister(mright.right().node()));
...@@ -875,9 +875,14 @@ void InstructionSelector::VisitFloat64Add(Node* node) { ...@@ -875,9 +875,14 @@ void InstructionSelector::VisitFloat64Add(Node* node) {
void InstructionSelector::VisitFloat64Sub(Node* node) { void InstructionSelector::VisitFloat64Sub(Node* node) {
ArmOperandGenerator g(this); ArmOperandGenerator g(this);
Int32BinopMatcher m(node); Float64BinopMatcher m(node);
if (m.left().IsMinusZero()) {
Emit(kArmVnegF64, g.DefineAsRegister(node),
g.UseRegister(m.right().node()));
return;
}
if (m.right().IsFloat64Mul() && CanCover(node, m.right().node())) { if (m.right().IsFloat64Mul() && CanCover(node, m.right().node())) {
Int32BinopMatcher mright(m.right().node()); Float64BinopMatcher mright(m.right().node());
Emit(kArmVmlsF64, g.DefineSameAsFirst(node), g.UseRegister(m.left().node()), Emit(kArmVmlsF64, g.DefineSameAsFirst(node), g.UseRegister(m.left().node()),
g.UseRegister(mright.left().node()), g.UseRegister(mright.left().node()),
g.UseRegister(mright.right().node())); g.UseRegister(mright.right().node()));
...@@ -888,13 +893,7 @@ void InstructionSelector::VisitFloat64Sub(Node* node) { ...@@ -888,13 +893,7 @@ void InstructionSelector::VisitFloat64Sub(Node* node) {
void InstructionSelector::VisitFloat64Mul(Node* node) { void InstructionSelector::VisitFloat64Mul(Node* node) {
ArmOperandGenerator g(this); VisitRRRFloat64(this, kArmVmulF64, node);
Float64BinopMatcher m(node);
if (m.right().Is(-1.0)) {
Emit(kArmVnegF64, g.DefineAsRegister(node), g.UseRegister(m.left().node()));
} else {
VisitRRRFloat64(this, kArmVmulF64, node);
}
} }
......
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
#ifndef V8_COMPILER_NODE_MATCHERS_H_ #ifndef V8_COMPILER_NODE_MATCHERS_H_
#define V8_COMPILER_NODE_MATCHERS_H_ #define V8_COMPILER_NODE_MATCHERS_H_
#include <cmath>
#include "src/compiler/generic-node.h" #include "src/compiler/generic-node.h"
#include "src/compiler/generic-node-inl.h" #include "src/compiler/generic-node-inl.h"
#include "src/compiler/node.h" #include "src/compiler/node.h"
...@@ -104,6 +106,7 @@ template <typename T, IrOpcode::Value kOpcode> ...@@ -104,6 +106,7 @@ template <typename T, IrOpcode::Value kOpcode>
struct FloatMatcher FINAL : public ValueMatcher<T, kOpcode> { struct FloatMatcher FINAL : public ValueMatcher<T, kOpcode> {
explicit FloatMatcher(Node* node) : ValueMatcher<T, kOpcode>(node) {} explicit FloatMatcher(Node* node) : ValueMatcher<T, kOpcode>(node) {}
bool IsMinusZero() const { return this->Is(0.0) && signbit(this->Value()); }
bool IsNaN() const { return this->HasValue() && std::isnan(this->Value()); } bool IsNaN() const { return this->HasValue() && std::isnan(this->Value()); }
}; };
...@@ -167,6 +170,7 @@ typedef BinopMatcher<UintPtrMatcher, UintPtrMatcher> UintPtrBinopMatcher; ...@@ -167,6 +170,7 @@ typedef BinopMatcher<UintPtrMatcher, UintPtrMatcher> UintPtrBinopMatcher;
typedef BinopMatcher<Float64Matcher, Float64Matcher> Float64BinopMatcher; typedef BinopMatcher<Float64Matcher, Float64Matcher> Float64BinopMatcher;
typedef BinopMatcher<NumberMatcher, NumberMatcher> NumberBinopMatcher; typedef BinopMatcher<NumberMatcher, NumberMatcher> NumberBinopMatcher;
template <class BinopMatcher, IrOpcode::Value kAddOpcode, template <class BinopMatcher, IrOpcode::Value kAddOpcode,
IrOpcode::Value kMulOpcode, IrOpcode::Value kShiftOpcode> IrOpcode::Value kMulOpcode, IrOpcode::Value kShiftOpcode>
struct AddMatcher : public BinopMatcher { struct AddMatcher : public BinopMatcher {
......
...@@ -12,22 +12,32 @@ function Module(stdlib, foreign, heap) { ...@@ -12,22 +12,32 @@ function Module(stdlib, foreign, heap) {
i = +i; i = +i;
return +(-1 * i); return +(-1 * i);
} }
return { f1: f1, f2: f2 }; function f3(i) {
i = +i;
return +(-i);
}
return { f1: f1, f2: f2, f3: f3 };
} }
var m = Module(this, {}, new ArrayBuffer(64 * 1024)); var m = Module(this, {}, new ArrayBuffer(64 * 1024));
assertEquals(NaN, m.f1(NaN)); assertEquals(NaN, m.f1(NaN));
assertEquals(NaN, m.f2(NaN)); assertEquals(NaN, m.f2(NaN));
assertEquals(NaN, m.f3(NaN));
assertEquals(Infinity, 1 / m.f1(-0)); assertEquals(Infinity, 1 / m.f1(-0));
assertEquals(Infinity, 1 / m.f2(-0)); assertEquals(Infinity, 1 / m.f2(-0));
assertEquals(Infinity, 1 / m.f3(-0));
assertEquals(Infinity, m.f1(-Infinity)); assertEquals(Infinity, m.f1(-Infinity));
assertEquals(Infinity, m.f2(-Infinity)); assertEquals(Infinity, m.f2(-Infinity));
assertEquals(Infinity, m.f3(-Infinity));
assertEquals(-Infinity, 1 / m.f1(0)); assertEquals(-Infinity, 1 / m.f1(0));
assertEquals(-Infinity, 1 / m.f2(0)); assertEquals(-Infinity, 1 / m.f2(0));
assertEquals(-Infinity, 1 / m.f3(0));
assertEquals(-Infinity, m.f1(Infinity)); assertEquals(-Infinity, m.f1(Infinity));
assertEquals(-Infinity, m.f2(Infinity)); assertEquals(-Infinity, m.f2(Infinity));
assertEquals(-Infinity, m.f3(Infinity));
for (var i = -2147483648; i < 2147483648; i += 3999777) { for (var i = -2147483648; i < 2147483648; i += 3999777) {
assertEquals(-i, m.f1(i)); assertEquals(-i, m.f1(i));
assertEquals(-i, m.f2(i)); assertEquals(-i, m.f2(i));
assertEquals(-i, m.f3(i));
} }
...@@ -1482,6 +1482,21 @@ INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, ...@@ -1482,6 +1482,21 @@ INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
// Miscellaneous. // Miscellaneous.
TEST_F(InstructionSelectorTest, Float64SubWithMinusZero) {
StreamBuilder m(this, kMachFloat64, kMachFloat64);
Node* const p0 = m.Parameter(0);
Node* const n = m.Float64Sub(m.Float64Constant(-0.0), p0);
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()));
}
TEST_F(InstructionSelectorTest, Int32AddWithInt32Mul) { TEST_F(InstructionSelectorTest, Int32AddWithInt32Mul) {
{ {
StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32, kMachInt32); StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32, kMachInt32);
......
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