| Index: test/unittests/compiler/graph-reducer-unittest.cc | 
| diff --git a/test/unittests/compiler/graph-reducer-unittest.cc b/test/unittests/compiler/graph-reducer-unittest.cc | 
| index ea981ccaf3051778aeae25f8475d352428932372..d3e97975786d8c30cb9af5dd11dbb1f32dfd7b04 100644 | 
| --- a/test/unittests/compiler/graph-reducer-unittest.cc | 
| +++ b/test/unittests/compiler/graph-reducer-unittest.cc | 
| @@ -2,6 +2,7 @@ | 
| // Use of this source code is governed by a BSD-style license that can be | 
| // found in the LICENSE file. | 
|  | 
| +#include "src/compiler/common-operator.h" | 
| #include "src/compiler/graph.h" | 
| #include "src/compiler/node.h" | 
| #include "src/compiler/operator.h" | 
| @@ -10,9 +11,11 @@ | 
|  | 
| using testing::_; | 
| using testing::DefaultValue; | 
| +using testing::ElementsAre; | 
| using testing::Return; | 
| using testing::Sequence; | 
| using testing::StrictMock; | 
| +using testing::UnorderedElementsAre; | 
|  | 
| namespace v8 { | 
| namespace internal { | 
| @@ -264,6 +267,124 @@ TEST_F(AdvancedReducerTest, Revisit) { | 
| } | 
|  | 
|  | 
| +namespace { | 
| + | 
| +struct ReplaceWithValueReducer final : public AdvancedReducer { | 
| +  explicit ReplaceWithValueReducer(Editor* editor) : AdvancedReducer(editor) {} | 
| +  Reduction Reduce(Node* node) final { return NoChange(); } | 
| +  using AdvancedReducer::ReplaceWithValue; | 
| +}; | 
| + | 
| +const Operator kMockOperator(IrOpcode::kDead, Operator::kNoProperties, | 
| +                             "MockOperator", 0, 0, 0, 1, 0, 0); | 
| +const Operator kMockOpEffect(IrOpcode::kDead, Operator::kNoProperties, | 
| +                             "MockOpEffect", 0, 1, 0, 1, 1, 0); | 
| +const Operator kMockOpControl(IrOpcode::kDead, Operator::kNoProperties, | 
| +                              "MockOpControl", 0, 0, 1, 1, 0, 1); | 
| + | 
| +const IfExceptionHint kNoHint = IfExceptionHint::kLocallyCaught; | 
| + | 
| +}  // namespace | 
| + | 
| + | 
| +TEST_F(AdvancedReducerTest, ReplaceWithValue_ValueUse) { | 
| +  CommonOperatorBuilder common(zone()); | 
| +  Node* node = graph()->NewNode(&kMockOperator); | 
| +  Node* use_value = graph()->NewNode(common.Return(), node); | 
| +  Node* replacement = graph()->NewNode(&kMockOperator); | 
| +  GraphReducer graph_reducer(zone(), graph(), nullptr, nullptr); | 
| +  ReplaceWithValueReducer r(&graph_reducer); | 
| +  r.ReplaceWithValue(node, replacement); | 
| +  EXPECT_EQ(replacement, use_value->InputAt(0)); | 
| +  EXPECT_EQ(0, node->UseCount()); | 
| +  EXPECT_EQ(1, replacement->UseCount()); | 
| +  EXPECT_THAT(replacement->uses(), ElementsAre(use_value)); | 
| +} | 
| + | 
| + | 
| +TEST_F(AdvancedReducerTest, ReplaceWithValue_EffectUse) { | 
| +  CommonOperatorBuilder common(zone()); | 
| +  Node* start = graph()->NewNode(common.Start(1)); | 
| +  Node* node = graph()->NewNode(&kMockOpEffect, start); | 
| +  Node* use_effect = graph()->NewNode(common.EffectPhi(1), node); | 
| +  Node* replacement = graph()->NewNode(&kMockOperator); | 
| +  GraphReducer graph_reducer(zone(), graph(), nullptr, nullptr); | 
| +  ReplaceWithValueReducer r(&graph_reducer); | 
| +  r.ReplaceWithValue(node, replacement); | 
| +  EXPECT_EQ(start, use_effect->InputAt(0)); | 
| +  EXPECT_EQ(0, node->UseCount()); | 
| +  EXPECT_EQ(2, start->UseCount()); | 
| +  EXPECT_EQ(0, replacement->UseCount()); | 
| +  EXPECT_THAT(start->uses(), UnorderedElementsAre(use_effect, node)); | 
| +} | 
| + | 
| + | 
| +TEST_F(AdvancedReducerTest, ReplaceWithValue_ControlUse1) { | 
| +  CommonOperatorBuilder common(zone()); | 
| +  Node* start = graph()->NewNode(common.Start(1)); | 
| +  Node* node = graph()->NewNode(&kMockOpControl, start); | 
| +  Node* success = graph()->NewNode(common.IfSuccess(), node); | 
| +  Node* use_control = graph()->NewNode(common.Merge(1), success); | 
| +  Node* replacement = graph()->NewNode(&kMockOperator); | 
| +  GraphReducer graph_reducer(zone(), graph(), nullptr, nullptr); | 
| +  ReplaceWithValueReducer r(&graph_reducer); | 
| +  r.ReplaceWithValue(node, replacement); | 
| +  EXPECT_EQ(start, use_control->InputAt(0)); | 
| +  EXPECT_EQ(0, node->UseCount()); | 
| +  EXPECT_EQ(2, start->UseCount()); | 
| +  EXPECT_EQ(0, replacement->UseCount()); | 
| +  EXPECT_THAT(start->uses(), UnorderedElementsAre(use_control, node)); | 
| +} | 
| + | 
| + | 
| +TEST_F(AdvancedReducerTest, ReplaceWithValue_ControlUse2) { | 
| +  CommonOperatorBuilder common(zone()); | 
| +  Node* start = graph()->NewNode(common.Start(1)); | 
| +  Node* dead = graph()->NewNode(&kMockOperator); | 
| +  Node* node = graph()->NewNode(&kMockOpControl, start); | 
| +  Node* success = graph()->NewNode(common.IfSuccess(), node); | 
| +  Node* exception = graph()->NewNode(common.IfException(kNoHint), node); | 
| +  Node* use_control = graph()->NewNode(common.Merge(1), success); | 
| +  Node* use_exception_control = graph()->NewNode(common.Merge(1), exception); | 
| +  Node* replacement = graph()->NewNode(&kMockOperator); | 
| +  GraphReducer graph_reducer(zone(), graph(), nullptr, dead); | 
| +  ReplaceWithValueReducer r(&graph_reducer); | 
| +  r.ReplaceWithValue(node, replacement); | 
| +  EXPECT_EQ(start, use_control->InputAt(0)); | 
| +  EXPECT_EQ(dead, use_exception_control->InputAt(0)); | 
| +  EXPECT_EQ(0, node->UseCount()); | 
| +  EXPECT_EQ(2, start->UseCount()); | 
| +  EXPECT_EQ(1, dead->UseCount()); | 
| +  EXPECT_EQ(0, replacement->UseCount()); | 
| +  EXPECT_THAT(start->uses(), UnorderedElementsAre(use_control, node)); | 
| +  EXPECT_THAT(dead->uses(), ElementsAre(use_exception_control)); | 
| +} | 
| + | 
| + | 
| +TEST_F(AdvancedReducerTest, ReplaceWithValue_ControlUse3) { | 
| +  CommonOperatorBuilder common(zone()); | 
| +  Node* start = graph()->NewNode(common.Start(1)); | 
| +  Node* dead = graph()->NewNode(&kMockOperator); | 
| +  Node* node = graph()->NewNode(&kMockOpControl, start); | 
| +  Node* success = graph()->NewNode(common.IfSuccess(), node); | 
| +  Node* exception = graph()->NewNode(common.IfException(kNoHint), node); | 
| +  Node* use_control = graph()->NewNode(common.Merge(1), success); | 
| +  Node* use_exception_value = graph()->NewNode(common.Return(), exception); | 
| +  Node* replacement = graph()->NewNode(&kMockOperator); | 
| +  GraphReducer graph_reducer(zone(), graph(), dead, nullptr); | 
| +  ReplaceWithValueReducer r(&graph_reducer); | 
| +  r.ReplaceWithValue(node, replacement); | 
| +  EXPECT_EQ(start, use_control->InputAt(0)); | 
| +  EXPECT_EQ(dead, use_exception_value->InputAt(0)); | 
| +  EXPECT_EQ(0, node->UseCount()); | 
| +  EXPECT_EQ(2, start->UseCount()); | 
| +  EXPECT_EQ(1, dead->UseCount()); | 
| +  EXPECT_EQ(0, replacement->UseCount()); | 
| +  EXPECT_THAT(start->uses(), UnorderedElementsAre(use_control, node)); | 
| +  EXPECT_THAT(dead->uses(), ElementsAre(use_exception_value)); | 
| +} | 
| + | 
| + | 
| class GraphReducerTest : public TestWithZone { | 
| public: | 
| GraphReducerTest() : graph_(zone()) {} | 
| @@ -280,20 +401,20 @@ class GraphReducerTest : public TestWithZone { | 
|  | 
| protected: | 
| void ReduceNode(Node* node, Reducer* r) { | 
| -    GraphReducer reducer(graph(), zone()); | 
| +    GraphReducer reducer(zone(), graph()); | 
| reducer.AddReducer(r); | 
| reducer.ReduceNode(node); | 
| } | 
|  | 
| void ReduceNode(Node* node, Reducer* r1, Reducer* r2) { | 
| -    GraphReducer reducer(graph(), zone()); | 
| +    GraphReducer reducer(zone(), graph()); | 
| reducer.AddReducer(r1); | 
| reducer.AddReducer(r2); | 
| reducer.ReduceNode(node); | 
| } | 
|  | 
| void ReduceNode(Node* node, Reducer* r1, Reducer* r2, Reducer* r3) { | 
| -    GraphReducer reducer(graph(), zone()); | 
| +    GraphReducer reducer(zone(), graph()); | 
| reducer.AddReducer(r1); | 
| reducer.AddReducer(r2); | 
| reducer.AddReducer(r3); | 
| @@ -301,20 +422,20 @@ class GraphReducerTest : public TestWithZone { | 
| } | 
|  | 
| void ReduceGraph(Reducer* r1) { | 
| -    GraphReducer reducer(graph(), zone()); | 
| +    GraphReducer reducer(zone(), graph()); | 
| reducer.AddReducer(r1); | 
| reducer.ReduceGraph(); | 
| } | 
|  | 
| void ReduceGraph(Reducer* r1, Reducer* r2) { | 
| -    GraphReducer reducer(graph(), zone()); | 
| +    GraphReducer reducer(zone(), graph()); | 
| reducer.AddReducer(r1); | 
| reducer.AddReducer(r2); | 
| reducer.ReduceGraph(); | 
| } | 
|  | 
| void ReduceGraph(Reducer* r1, Reducer* r2, Reducer* r3) { | 
| -    GraphReducer reducer(graph(), zone()); | 
| +    GraphReducer reducer(zone(), graph()); | 
| reducer.AddReducer(r1); | 
| reducer.AddReducer(r2); | 
| reducer.AddReducer(r3); | 
|  |