diff --git a/src/compiler/machine-operator-reducer.cc b/src/compiler/machine-operator-reducer.cc index c3e45a1b25..9b0c2b2f34 100644 --- a/src/compiler/machine-operator-reducer.cc +++ b/src/compiler/machine-operator-reducer.cc @@ -75,7 +75,9 @@ Node* MachineOperatorReducer::Int32Add(Node* lhs, Node* rhs) { Node* MachineOperatorReducer::Int32Sub(Node* lhs, Node* rhs) { - return graph()->NewNode(machine()->Int32Sub(), lhs, rhs); + Node* const node = graph()->NewNode(machine()->Int32Sub(), lhs, rhs); + Reduction const reduction = ReduceInt32Sub(node); + return reduction.Changed() ? reduction.replacement() : node; } @@ -216,16 +218,8 @@ Reduction MachineOperatorReducer::Reduce(Node* node) { } case IrOpcode::kInt32Add: return ReduceInt32Add(node); - case IrOpcode::kInt32Sub: { - Int32BinopMatcher m(node); - if (m.right().Is(0)) return Replace(m.left().node()); // x - 0 => x - if (m.IsFoldable()) { // K - K => K - return ReplaceInt32(static_cast(m.left().Value()) - - static_cast(m.right().Value())); - } - if (m.LeftEqualsRight()) return ReplaceInt32(0); // x - x => 0 - break; - } + case IrOpcode::kInt32Sub: + return ReduceInt32Sub(node); case IrOpcode::kInt32Mul: { Int32BinopMatcher m(node); if (m.right().Is(0)) return Replace(m.right().node()); // x * 0 => 0 @@ -475,6 +469,25 @@ Reduction MachineOperatorReducer::ReduceInt32Add(Node* node) { } +Reduction MachineOperatorReducer::ReduceInt32Sub(Node* node) { + DCHECK_EQ(IrOpcode::kInt32Sub, node->opcode()); + Int32BinopMatcher m(node); + if (m.right().Is(0)) return Replace(m.left().node()); // x - 0 => x + if (m.IsFoldable()) { // K - K => K + return ReplaceInt32(static_cast(m.left().Value()) - + static_cast(m.right().Value())); + } + if (m.LeftEqualsRight()) return ReplaceInt32(0); // x - x => 0 + if (m.right().HasValue()) { // x - K => x + -K + node->set_op(machine()->Int32Add()); + node->ReplaceInput(1, Int32Constant(-m.right().Value())); + Reduction const reduction = ReduceInt32Add(node); + return reduction.Changed() ? reduction : Changed(node); + } + return NoChange(); +} + + Reduction MachineOperatorReducer::ReduceInt32Div(Node* node) { Int32BinopMatcher m(node); if (m.left().Is(0)) return Replace(m.left().node()); // 0 / x => 0 diff --git a/src/compiler/machine-operator-reducer.h b/src/compiler/machine-operator-reducer.h index 8200abbf95..9e02ffde72 100644 --- a/src/compiler/machine-operator-reducer.h +++ b/src/compiler/machine-operator-reducer.h @@ -65,6 +65,7 @@ class MachineOperatorReducer FINAL : public Reducer { } Reduction ReduceInt32Add(Node* node); + Reduction ReduceInt32Sub(Node* node); Reduction ReduceInt32Div(Node* node); Reduction ReduceUint32Div(Node* node); Reduction ReduceInt32Mod(Node* node); diff --git a/test/unittests/compiler/machine-operator-reducer-unittest.cc b/test/unittests/compiler/machine-operator-reducer-unittest.cc index 6fdba35f58..41e69f0a83 100644 --- a/test/unittests/compiler/machine-operator-reducer-unittest.cc +++ b/test/unittests/compiler/machine-operator-reducer-unittest.cc @@ -841,6 +841,25 @@ TEST_F(MachineOperatorReducerTest, Word32ShlWithWord32Shr) { } +// ----------------------------------------------------------------------------- +// Int32Sub + + +TEST_F(MachineOperatorReducerTest, Int32SubWithConstant) { + Node* const p0 = Parameter(0); + TRACED_FOREACH(int32_t, k, kInt32Values) { + Reduction const r = + Reduce(graph()->NewNode(machine()->Int32Sub(), p0, Int32Constant(k))); + ASSERT_TRUE(r.Changed()); + if (k == 0) { + EXPECT_EQ(p0, r.replacement()); + } else { + EXPECT_THAT(r.replacement(), IsInt32Add(p0, IsInt32Constant(-k))); + } + } +} + + // ----------------------------------------------------------------------------- // Int32Div