1// Copyright 2014 the V8 project authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "src/compiler/graph.h" 6#include "src/compiler/graph-reducer.h" 7#include "src/compiler/operator.h" 8#include "src/test/test-utils.h" 9#include "testing/gmock/include/gmock/gmock.h" 10 11using testing::_; 12using testing::DefaultValue; 13using testing::Return; 14using testing::Sequence; 15using testing::StrictMock; 16 17namespace v8 { 18namespace internal { 19namespace compiler { 20 21namespace { 22 23SimpleOperator OP0(0, Operator::kNoWrite, 0, 1, "op0"); 24SimpleOperator OP1(1, Operator::kNoProperties, 1, 1, "op1"); 25 26 27struct MockReducer : public Reducer { 28 MOCK_METHOD1(Reduce, Reduction(Node*)); 29}; 30 31} // namespace 32 33 34class GraphReducerTest : public TestWithZone { 35 public: 36 GraphReducerTest() : graph_(zone()) {} 37 38 static void SetUpTestCase() { 39 TestWithZone::SetUpTestCase(); 40 DefaultValue<Reduction>::Set(Reducer::NoChange()); 41 } 42 43 static void TearDownTestCase() { 44 DefaultValue<Reduction>::Clear(); 45 TestWithZone::TearDownTestCase(); 46 } 47 48 protected: 49 void ReduceNode(Node* node, Reducer* r) { 50 GraphReducer reducer(graph()); 51 reducer.AddReducer(r); 52 reducer.ReduceNode(node); 53 } 54 55 void ReduceNode(Node* node, Reducer* r1, Reducer* r2) { 56 GraphReducer reducer(graph()); 57 reducer.AddReducer(r1); 58 reducer.AddReducer(r2); 59 reducer.ReduceNode(node); 60 } 61 62 void ReduceNode(Node* node, Reducer* r1, Reducer* r2, Reducer* r3) { 63 GraphReducer reducer(graph()); 64 reducer.AddReducer(r1); 65 reducer.AddReducer(r2); 66 reducer.AddReducer(r3); 67 reducer.ReduceNode(node); 68 } 69 70 Graph* graph() { return &graph_; } 71 72 private: 73 Graph graph_; 74}; 75 76 77TEST_F(GraphReducerTest, NodeIsDeadAfterReplace) { 78 StrictMock<MockReducer> r; 79 Node* node0 = graph()->NewNode(&OP0); 80 Node* node1 = graph()->NewNode(&OP1, node0); 81 Node* node2 = graph()->NewNode(&OP1, node0); 82 EXPECT_CALL(r, Reduce(node1)).WillOnce(Return(Reducer::Replace(node2))); 83 ReduceNode(node1, &r); 84 EXPECT_FALSE(node0->IsDead()); 85 EXPECT_TRUE(node1->IsDead()); 86 EXPECT_FALSE(node2->IsDead()); 87} 88 89 90TEST_F(GraphReducerTest, ReduceOnceForEveryReducer) { 91 StrictMock<MockReducer> r1, r2; 92 Node* node0 = graph()->NewNode(&OP0); 93 EXPECT_CALL(r1, Reduce(node0)); 94 EXPECT_CALL(r2, Reduce(node0)); 95 ReduceNode(node0, &r1, &r2); 96} 97 98 99TEST_F(GraphReducerTest, ReduceAgainAfterChanged) { 100 Sequence s1, s2; 101 StrictMock<MockReducer> r1, r2, r3; 102 Node* node0 = graph()->NewNode(&OP0); 103 EXPECT_CALL(r1, Reduce(node0)); 104 EXPECT_CALL(r2, Reduce(node0)); 105 EXPECT_CALL(r3, Reduce(node0)).InSequence(s1, s2).WillOnce( 106 Return(Reducer::Changed(node0))); 107 EXPECT_CALL(r1, Reduce(node0)).InSequence(s1); 108 EXPECT_CALL(r2, Reduce(node0)).InSequence(s2); 109 ReduceNode(node0, &r1, &r2, &r3); 110} 111 112} // namespace compiler 113} // namespace internal 114} // namespace v8 115