Commit d9cb130d authored by bmeurer's avatar bmeurer Committed by Commit bot

[turbofan] Strength reduction for Int32MulWithOverflow.

Add simple strength reduction for Int32MulWithOverflow to the
MachineOperatorReducer.

R=mvstanton@chromium.org

Review-Url: https://codereview.chromium.org/2139733003
Cr-Commit-Position: refs/heads/master@{#37751}
parent ac50c1ca
......@@ -235,6 +235,21 @@ Reduction MachineOperatorReducer::Reduce(Node* node) {
}
break;
}
case IrOpcode::kInt32MulWithOverflow: {
Int32BinopMatcher m(node);
if (m.right().Is(2)) {
node->ReplaceInput(1, m.left().node());
NodeProperties::ChangeOp(node, machine()->Int32AddWithOverflow());
return Changed(node);
}
if (m.right().Is(-1)) {
node->ReplaceInput(0, Int32Constant(0));
node->ReplaceInput(1, m.left().node());
NodeProperties::ChangeOp(node, machine()->Int32SubWithOverflow());
return Changed(node);
}
break;
}
case IrOpcode::kInt32Div:
return ReduceInt32Div(node);
case IrOpcode::kUint32Div:
......@@ -831,10 +846,10 @@ Reduction MachineOperatorReducer::ReduceProjection(size_t index, Node* node) {
int32_t val;
bool ovf = base::bits::SignedAddOverflow32(m.left().Value(),
m.right().Value(), &val);
return ReplaceInt32((index == 0) ? val : ovf);
return ReplaceInt32(index == 0 ? val : ovf);
}
if (m.right().Is(0)) {
return (index == 0) ? Replace(m.left().node()) : ReplaceInt32(0);
return Replace(index == 0 ? m.left().node() : m.right().node());
}
break;
}
......@@ -845,10 +860,27 @@ Reduction MachineOperatorReducer::ReduceProjection(size_t index, Node* node) {
int32_t val;
bool ovf = base::bits::SignedSubOverflow32(m.left().Value(),
m.right().Value(), &val);
return ReplaceInt32((index == 0) ? val : ovf);
return ReplaceInt32(index == 0 ? val : ovf);
}
if (m.right().Is(0)) {
return Replace(index == 0 ? m.left().node() : m.right().node());
}
break;
}
case IrOpcode::kInt32MulWithOverflow: {
DCHECK(index == 0 || index == 1);
Int32BinopMatcher m(node);
if (m.IsFoldable()) {
int32_t val;
bool ovf = base::bits::SignedMulOverflow32(m.left().Value(),
m.right().Value(), &val);
return ReplaceInt32(index == 0 ? val : ovf);
}
if (m.right().Is(0)) {
return (index == 0) ? Replace(m.left().node()) : ReplaceInt32(0);
return Replace(m.right().node());
}
if (m.right().Is(1)) {
return index == 0 ? Replace(m.left().node()) : ReplaceInt32(0);
}
break;
}
......
......@@ -1380,8 +1380,133 @@ TEST_F(MachineOperatorReducerTest, Int32SubWithOverflowWithConstant) {
// -----------------------------------------------------------------------------
// Uint32LessThan
// Int32MulWithOverflow
TEST_F(MachineOperatorReducerTest, Int32MulWithOverflowWithZero) {
Node* control = graph()->start();
Node* p0 = Parameter(0);
{
Node* mul = graph()->NewNode(machine()->Int32MulWithOverflow(),
Int32Constant(0), p0, control);
Reduction r =
Reduce(graph()->NewNode(common()->Projection(1), mul, control));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsInt32Constant(0));
r = Reduce(graph()->NewNode(common()->Projection(0), mul, control));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsInt32Constant(0));
}
{
Node* mul = graph()->NewNode(machine()->Int32MulWithOverflow(), p0,
Int32Constant(0), control);
Reduction r =
Reduce(graph()->NewNode(common()->Projection(1), mul, control));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsInt32Constant(0));
r = Reduce(graph()->NewNode(common()->Projection(0), mul, control));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsInt32Constant(0));
}
}
TEST_F(MachineOperatorReducerTest, Int32MulWithOverflowWithOne) {
Node* control = graph()->start();
Node* p0 = Parameter(0);
{
Node* mul = graph()->NewNode(machine()->Int32MulWithOverflow(),
Int32Constant(1), p0, control);
Reduction r =
Reduce(graph()->NewNode(common()->Projection(1), mul, control));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsInt32Constant(0));
r = Reduce(graph()->NewNode(common()->Projection(0), mul, control));
ASSERT_TRUE(r.Changed());
EXPECT_EQ(p0, r.replacement());
}
{
Node* mul = graph()->NewNode(machine()->Int32MulWithOverflow(), p0,
Int32Constant(1), control);
Reduction r =
Reduce(graph()->NewNode(common()->Projection(1), mul, control));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsInt32Constant(0));
r = Reduce(graph()->NewNode(common()->Projection(0), mul, control));
ASSERT_TRUE(r.Changed());
EXPECT_EQ(p0, r.replacement());
}
}
TEST_F(MachineOperatorReducerTest, Int32MulWithOverflowWithMinusOne) {
Node* control = graph()->start();
Node* p0 = Parameter(0);
{
Reduction r = Reduce(graph()->NewNode(machine()->Int32MulWithOverflow(),
Int32Constant(-1), p0, control));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(),
IsInt32SubWithOverflow(IsInt32Constant(0), p0));
}
{
Reduction r = Reduce(graph()->NewNode(machine()->Int32MulWithOverflow(), p0,
Int32Constant(-1), control));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(),
IsInt32SubWithOverflow(IsInt32Constant(0), p0));
}
}
TEST_F(MachineOperatorReducerTest, Int32MulWithOverflowWithTwo) {
Node* control = graph()->start();
Node* p0 = Parameter(0);
{
Reduction r = Reduce(graph()->NewNode(machine()->Int32MulWithOverflow(),
Int32Constant(2), p0, control));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsInt32AddWithOverflow(p0, p0));
}
{
Reduction r = Reduce(graph()->NewNode(machine()->Int32MulWithOverflow(), p0,
Int32Constant(2), control));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsInt32AddWithOverflow(p0, p0));
}
}
TEST_F(MachineOperatorReducerTest, Int32MulWithOverflowWithConstant) {
Node* control = graph()->start();
TRACED_FOREACH(int32_t, x, kInt32Values) {
TRACED_FOREACH(int32_t, y, kInt32Values) {
int32_t z;
Node* mul = graph()->NewNode(machine()->Int32MulWithOverflow(),
Int32Constant(x), Int32Constant(y), control);
Reduction r =
Reduce(graph()->NewNode(common()->Projection(1), mul, control));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(),
IsInt32Constant(base::bits::SignedMulOverflow32(x, y, &z)));
r = Reduce(graph()->NewNode(common()->Projection(0), mul, control));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsInt32Constant(z));
}
}
}
// -----------------------------------------------------------------------------
// Uint32LessThan
TEST_F(MachineOperatorReducerTest, Uint32LessThanWithWord32Sar) {
Node* const p0 = Parameter(0);
......
......@@ -2233,6 +2233,7 @@ IS_BINOP_MATCHER(Word64Sar)
IS_BINOP_MATCHER(Word64Shl)
IS_BINOP_MATCHER(Word64Equal)
IS_BINOP_MATCHER(Int32AddWithOverflow)
IS_BINOP_MATCHER(Int32SubWithOverflow)
IS_BINOP_MATCHER(Int32Add)
IS_BINOP_MATCHER(Int32Sub)
IS_BINOP_MATCHER(Int32Mul)
......
......@@ -339,6 +339,8 @@ Matcher<Node*> IsWord64Equal(const Matcher<Node*>& lhs_matcher,
const Matcher<Node*>& rhs_matcher);
Matcher<Node*> IsInt32AddWithOverflow(const Matcher<Node*>& lhs_matcher,
const Matcher<Node*>& rhs_matcher);
Matcher<Node*> IsInt32SubWithOverflow(const Matcher<Node*>& lhs_matcher,
const Matcher<Node*>& rhs_matcher);
Matcher<Node*> IsInt32Add(const Matcher<Node*>& lhs_matcher,
const Matcher<Node*>& rhs_matcher);
Matcher<Node*> IsInt32Sub(const Matcher<Node*>& lhs_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