Commit 5ae2d0e5 authored by martyn.capewell's avatar martyn.capewell Committed by Commit bot

[turbofan] Reduce some Float64 division to multiplication

For denominators that are powers of two, replace Float64 division with
multiplication by the reciprocal.

Additionally, replace division by -1 with negation, and multiplication by two
with addition.

BUG=

Review-Url: https://codereview.chromium.org/2347573002
Cr-Commit-Position: refs/heads/master@{#39478}
parent 7c05d8a4
......@@ -418,6 +418,11 @@ Reduction MachineOperatorReducer::Reduce(Node* node) {
if (m.IsFoldable()) { // K * K => K
return ReplaceFloat64(m.left().Value() * m.right().Value());
}
if (m.right().Is(2)) { // x * 2.0 => x + x
node->ReplaceInput(1, m.left().node());
NodeProperties::ChangeOp(node, machine()->Float64Add());
return Changed(node);
}
break;
}
case IrOpcode::kFloat64Div: {
......@@ -432,6 +437,19 @@ Reduction MachineOperatorReducer::Reduce(Node* node) {
if (m.IsFoldable()) { // K / K => K
return ReplaceFloat64(m.left().Value() / m.right().Value());
}
if (m.right().Is(-1)) { // x / -1.0 => -x
node->RemoveInput(1);
NodeProperties::ChangeOp(node, machine()->Float64Neg());
return Changed(node);
}
if (m.right().IsNormal() && m.right().IsPositiveOrNegativePowerOf2()) {
// All reciprocals of non-denormal powers of two can be represented
// exactly, so division by power of two can be reduced to
// multiplication by reciprocal, with the same result.
node->ReplaceInput(1, Float64Constant(1.0 / m.right().Value()));
NodeProperties::ChangeOp(node, machine()->Float64Mul());
return Changed(node);
}
break;
}
case IrOpcode::kFloat64Mod: {
......
......@@ -11,6 +11,7 @@
#include "src/assembler.h"
#include "src/compiler/node.h"
#include "src/compiler/operator.h"
#include "src/double.h"
namespace v8 {
namespace internal {
......@@ -161,6 +162,17 @@ struct FloatMatcher final : public ValueMatcher<T, kOpcode> {
bool IsNegative() const { return this->HasValue() && this->Value() < 0.0; }
bool IsNaN() const { return this->HasValue() && std::isnan(this->Value()); }
bool IsZero() const { return this->Is(0.0) && !std::signbit(this->Value()); }
bool IsNormal() const {
return this->HasValue() && std::isnormal(this->Value());
}
bool IsPositiveOrNegativePowerOf2() const {
if (!this->HasValue() || (this->Value() == 0.0)) {
return false;
}
Double value = Double(this->Value());
return !value.IsInfinite() &&
base::bits::IsPowerOfTwo64(value.Significand());
}
};
typedef FloatMatcher<float, IrOpcode::kFloat32Constant> Float32Matcher;
......
......@@ -1587,6 +1587,48 @@ TEST_F(MachineOperatorReducerTest, Float32SubMinusZeroMinusX) {
}
}
TEST_F(MachineOperatorReducerTest, Float64MulWithTwo) {
Node* const p0 = Parameter(0);
{
Reduction r = Reduce(
graph()->NewNode(machine()->Float64Mul(), Float64Constant(2.0), p0));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsFloat64Add(p0, p0));
}
{
Reduction r = Reduce(
graph()->NewNode(machine()->Float64Mul(), p0, Float64Constant(2.0)));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsFloat64Add(p0, p0));
}
}
// -----------------------------------------------------------------------------
// Float64Div
TEST_F(MachineOperatorReducerTest, Float64DivWithMinusOne) {
Node* const p0 = Parameter(0);
{
Reduction r = Reduce(
graph()->NewNode(machine()->Float64Div(), p0, Float64Constant(-1.0)));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsFloat64Neg(p0));
}
}
TEST_F(MachineOperatorReducerTest, Float64DivWithPowerOfTwo) {
Node* const p0 = Parameter(0);
TRACED_FORRANGE(uint64_t, exponent, 1, 0x7fe) {
Double divisor = Double(exponent << Double::kPhysicalSignificandSize);
if (divisor.value() == 1.0) continue; // Skip x / 1.0 => x.
Reduction r = Reduce(graph()->NewNode(machine()->Float64Div(), p0,
Float64Constant(divisor.value())));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(),
IsFloat64Mul(p0, IsFloat64Constant(1.0 / divisor.value())));
}
}
// -----------------------------------------------------------------------------
// Float64Acos
......
......@@ -2307,7 +2307,9 @@ IS_BINOP_MATCHER(Float32LessThan)
IS_BINOP_MATCHER(Float32LessThanOrEqual)
IS_BINOP_MATCHER(Float64Max)
IS_BINOP_MATCHER(Float64Min)
IS_BINOP_MATCHER(Float64Add)
IS_BINOP_MATCHER(Float64Sub)
IS_BINOP_MATCHER(Float64Mul)
IS_BINOP_MATCHER(Float64InsertLowWord32)
IS_BINOP_MATCHER(Float64InsertHighWord32)
#undef IS_BINOP_MATCHER
......
......@@ -407,8 +407,12 @@ Matcher<Node*> IsFloat64Max(const Matcher<Node*>& lhs_matcher,
const Matcher<Node*>& rhs_matcher);
Matcher<Node*> IsFloat64Min(const Matcher<Node*>& lhs_matcher,
const Matcher<Node*>& rhs_matcher);
Matcher<Node*> IsFloat64Add(const Matcher<Node*>& lhs_matcher,
const Matcher<Node*>& rhs_matcher);
Matcher<Node*> IsFloat64Sub(const Matcher<Node*>& lhs_matcher,
const Matcher<Node*>& rhs_matcher);
Matcher<Node*> IsFloat64Mul(const Matcher<Node*>& lhs_matcher,
const Matcher<Node*>& rhs_matcher);
Matcher<Node*> IsFloat64Abs(const Matcher<Node*>& input_matcher);
Matcher<Node*> IsFloat64Neg(const Matcher<Node*>& input_matcher);
Matcher<Node*> IsFloat64Sqrt(const Matcher<Node*>& input_matcher);
......
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