Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(196)

Side by Side Diff: test/unittests/compiler/graph-reducer-unittest.cc

Issue 1122423003: [turbofan] Add support for advanced reducers. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Make windows happy. Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 the V8 project authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/compiler/graph.h" 5 #include "src/compiler/graph.h"
6 #include "src/compiler/graph-reducer.h"
7 #include "src/compiler/node.h" 6 #include "src/compiler/node.h"
8 #include "src/compiler/operator.h" 7 #include "src/compiler/operator.h"
8 #include "test/unittests/compiler/graph-reducer-unittest.h"
9 #include "test/unittests/test-utils.h" 9 #include "test/unittests/test-utils.h"
10 #include "testing/gmock/include/gmock/gmock.h"
11 10
12 using testing::_; 11 using testing::_;
13 using testing::DefaultValue; 12 using testing::DefaultValue;
14 using testing::Return; 13 using testing::Return;
15 using testing::Sequence; 14 using testing::Sequence;
16 using testing::StrictMock; 15 using testing::StrictMock;
17 16
18 namespace v8 { 17 namespace v8 {
19 namespace internal { 18 namespace internal {
20 namespace compiler { 19 namespace compiler {
(...skipping 27 matching lines...) Expand all
48 static TestOperator kOpC0(kOpcodeC0, Operator::kNoWrite, "opc0", 0, 0); 47 static TestOperator kOpC0(kOpcodeC0, Operator::kNoWrite, "opc0", 0, 0);
49 static TestOperator kOpC1(kOpcodeC1, Operator::kNoWrite, "opc1", 1, 0); 48 static TestOperator kOpC1(kOpcodeC1, Operator::kNoWrite, "opc1", 1, 0);
50 static TestOperator kOpC2(kOpcodeC2, Operator::kNoWrite, "opc2", 2, 0); 49 static TestOperator kOpC2(kOpcodeC2, Operator::kNoWrite, "opc2", 2, 0);
51 50
52 struct MockReducer : public Reducer { 51 struct MockReducer : public Reducer {
53 MOCK_METHOD1(Reduce, Reduction(Node*)); 52 MOCK_METHOD1(Reduce, Reduction(Node*));
54 }; 53 };
55 54
56 55
57 // Replaces all "A" operators with "B" operators without creating new nodes. 56 // Replaces all "A" operators with "B" operators without creating new nodes.
58 class InPlaceABReducer : public Reducer { 57 class InPlaceABReducer final : public Reducer {
59 public: 58 public:
60 virtual Reduction Reduce(Node* node) { 59 Reduction Reduce(Node* node) final {
61 switch (node->op()->opcode()) { 60 switch (node->op()->opcode()) {
62 case kOpcodeA0: 61 case kOpcodeA0:
63 EXPECT_EQ(0, node->InputCount()); 62 EXPECT_EQ(0, node->InputCount());
64 node->set_op(&kOpB0); 63 node->set_op(&kOpB0);
65 return Replace(node); 64 return Replace(node);
66 case kOpcodeA1: 65 case kOpcodeA1:
67 EXPECT_EQ(1, node->InputCount()); 66 EXPECT_EQ(1, node->InputCount());
68 node->set_op(&kOpB1); 67 node->set_op(&kOpB1);
69 return Replace(node); 68 return Replace(node);
70 case kOpcodeA2: 69 case kOpcodeA2:
71 EXPECT_EQ(2, node->InputCount()); 70 EXPECT_EQ(2, node->InputCount());
72 node->set_op(&kOpB2); 71 node->set_op(&kOpB2);
73 return Replace(node); 72 return Replace(node);
74 } 73 }
75 return NoChange(); 74 return NoChange();
76 } 75 }
77 }; 76 };
78 77
79 78
80 // Replaces all "A" operators with "B" operators by allocating new nodes. 79 // Replaces all "A" operators with "B" operators by allocating new nodes.
81 class NewABReducer : public Reducer { 80 class NewABReducer final : public Reducer {
82 public: 81 public:
83 explicit NewABReducer(Graph* graph) : graph_(graph) {} 82 explicit NewABReducer(Graph* graph) : graph_(graph) {}
84 virtual Reduction Reduce(Node* node) { 83
84 Reduction Reduce(Node* node) final {
85 switch (node->op()->opcode()) { 85 switch (node->op()->opcode()) {
86 case kOpcodeA0: 86 case kOpcodeA0:
87 EXPECT_EQ(0, node->InputCount()); 87 EXPECT_EQ(0, node->InputCount());
88 return Replace(graph_->NewNode(&kOpB0)); 88 return Replace(graph_->NewNode(&kOpB0));
89 case kOpcodeA1: 89 case kOpcodeA1:
90 EXPECT_EQ(1, node->InputCount()); 90 EXPECT_EQ(1, node->InputCount());
91 return Replace(graph_->NewNode(&kOpB1, node->InputAt(0))); 91 return Replace(graph_->NewNode(&kOpB1, node->InputAt(0)));
92 case kOpcodeA2: 92 case kOpcodeA2:
93 EXPECT_EQ(2, node->InputCount()); 93 EXPECT_EQ(2, node->InputCount());
94 return Replace( 94 return Replace(
95 graph_->NewNode(&kOpB2, node->InputAt(0), node->InputAt(1))); 95 graph_->NewNode(&kOpB2, node->InputAt(0), node->InputAt(1)));
96 } 96 }
97 return NoChange(); 97 return NoChange();
98 } 98 }
99 Graph* graph_; 99
100 private:
101 Graph* const graph_;
100 }; 102 };
101 103
102 104
103 // Wraps all "kOpA0" nodes in "kOpB1" operators by allocating new nodes. 105 // Wraps all "kOpA0" nodes in "kOpB1" operators by allocating new nodes.
104 class A0Wrapper final : public Reducer { 106 class A0Wrapper final : public Reducer {
105 public: 107 public:
106 explicit A0Wrapper(Graph* graph) : graph_(graph) {} 108 explicit A0Wrapper(Graph* graph) : graph_(graph) {}
107 virtual Reduction Reduce(Node* node) override { 109
110 Reduction Reduce(Node* node) final {
108 switch (node->op()->opcode()) { 111 switch (node->op()->opcode()) {
109 case kOpcodeA0: 112 case kOpcodeA0:
110 EXPECT_EQ(0, node->InputCount()); 113 EXPECT_EQ(0, node->InputCount());
111 return Replace(graph_->NewNode(&kOpB1, node)); 114 return Replace(graph_->NewNode(&kOpB1, node));
112 } 115 }
113 return NoChange(); 116 return NoChange();
114 } 117 }
115 Graph* graph_; 118
119 private:
120 Graph* const graph_;
116 }; 121 };
117 122
118 123
119 // Wraps all "kOpB0" nodes in two "kOpC1" operators by allocating new nodes. 124 // Wraps all "kOpB0" nodes in two "kOpC1" operators by allocating new nodes.
120 class B0Wrapper final : public Reducer { 125 class B0Wrapper final : public Reducer {
121 public: 126 public:
122 explicit B0Wrapper(Graph* graph) : graph_(graph) {} 127 explicit B0Wrapper(Graph* graph) : graph_(graph) {}
123 virtual Reduction Reduce(Node* node) override { 128
129 Reduction Reduce(Node* node) final {
124 switch (node->op()->opcode()) { 130 switch (node->op()->opcode()) {
125 case kOpcodeB0: 131 case kOpcodeB0:
126 EXPECT_EQ(0, node->InputCount()); 132 EXPECT_EQ(0, node->InputCount());
127 return Replace(graph_->NewNode(&kOpC1, graph_->NewNode(&kOpC1, node))); 133 return Replace(graph_->NewNode(&kOpC1, graph_->NewNode(&kOpC1, node)));
128 } 134 }
129 return NoChange(); 135 return NoChange();
130 } 136 }
131 Graph* graph_; 137
138 private:
139 Graph* const graph_;
132 }; 140 };
133 141
134 142
135 // Replaces all "kOpA1" nodes with the first input. 143 // Replaces all "kOpA1" nodes with the first input.
136 class A1Forwarder : public Reducer { 144 class A1Forwarder final : public Reducer {
137 virtual Reduction Reduce(Node* node) { 145 public:
146 Reduction Reduce(Node* node) final {
138 switch (node->op()->opcode()) { 147 switch (node->op()->opcode()) {
139 case kOpcodeA1: 148 case kOpcodeA1:
140 EXPECT_EQ(1, node->InputCount()); 149 EXPECT_EQ(1, node->InputCount());
141 return Replace(node->InputAt(0)); 150 return Replace(node->InputAt(0));
142 } 151 }
143 return NoChange(); 152 return NoChange();
144 } 153 }
145 }; 154 };
146 155
147 156
148 // Replaces all "kOpB1" nodes with the first input. 157 // Replaces all "kOpB1" nodes with the first input.
149 class B1Forwarder : public Reducer { 158 class B1Forwarder final : public Reducer {
150 virtual Reduction Reduce(Node* node) { 159 public:
160 Reduction Reduce(Node* node) final {
151 switch (node->op()->opcode()) { 161 switch (node->op()->opcode()) {
152 case kOpcodeB1: 162 case kOpcodeB1:
153 EXPECT_EQ(1, node->InputCount()); 163 EXPECT_EQ(1, node->InputCount());
154 return Replace(node->InputAt(0)); 164 return Replace(node->InputAt(0));
155 } 165 }
156 return NoChange(); 166 return NoChange();
157 } 167 }
158 }; 168 };
159 169
160 170
161 // Replaces all "B" operators with "C" operators without creating new nodes. 171 // Replaces all "B" operators with "C" operators without creating new nodes.
162 class InPlaceBCReducer : public Reducer { 172 class InPlaceBCReducer final : public Reducer {
163 public: 173 public:
164 virtual Reduction Reduce(Node* node) { 174 Reduction Reduce(Node* node) final {
165 switch (node->op()->opcode()) { 175 switch (node->op()->opcode()) {
166 case kOpcodeB0: 176 case kOpcodeB0:
167 EXPECT_EQ(0, node->InputCount()); 177 EXPECT_EQ(0, node->InputCount());
168 node->set_op(&kOpC0); 178 node->set_op(&kOpC0);
169 return Replace(node); 179 return Replace(node);
170 case kOpcodeB1: 180 case kOpcodeB1:
171 EXPECT_EQ(1, node->InputCount()); 181 EXPECT_EQ(1, node->InputCount());
172 node->set_op(&kOpC1); 182 node->set_op(&kOpC1);
173 return Replace(node); 183 return Replace(node);
174 case kOpcodeB2: 184 case kOpcodeB2:
175 EXPECT_EQ(2, node->InputCount()); 185 EXPECT_EQ(2, node->InputCount());
176 node->set_op(&kOpC2); 186 node->set_op(&kOpC2);
177 return Replace(node); 187 return Replace(node);
178 } 188 }
179 return NoChange(); 189 return NoChange();
180 } 190 }
181 }; 191 };
182 192
183 193
184 // Swaps the inputs to "kOp2A" and "kOp2B" nodes based on ids. 194 // Swaps the inputs to "kOp2A" and "kOp2B" nodes based on ids.
185 class AB2Sorter : public Reducer { 195 class AB2Sorter final : public Reducer {
186 virtual Reduction Reduce(Node* node) { 196 public:
197 Reduction Reduce(Node* node) final {
187 switch (node->op()->opcode()) { 198 switch (node->op()->opcode()) {
188 case kOpcodeA2: 199 case kOpcodeA2:
189 case kOpcodeB2: 200 case kOpcodeB2:
190 EXPECT_EQ(2, node->InputCount()); 201 EXPECT_EQ(2, node->InputCount());
191 Node* x = node->InputAt(0); 202 Node* x = node->InputAt(0);
192 Node* y = node->InputAt(1); 203 Node* y = node->InputAt(1);
193 if (x->id() > y->id()) { 204 if (x->id() > y->id()) {
194 node->ReplaceInput(0, y); 205 node->ReplaceInput(0, y);
195 node->ReplaceInput(1, x); 206 node->ReplaceInput(1, x);
196 return Replace(node); 207 return Replace(node);
197 } 208 }
198 } 209 }
199 return NoChange(); 210 return NoChange();
200 } 211 }
201 }; 212 };
202 213
203
204 } // namespace 214 } // namespace
205 215
206 216
207 class GraphReducerTest : public TestWithZone { 217 class GraphReducerTest : public TestWithZone {
208 public: 218 public:
209 GraphReducerTest() : graph_(zone()) {} 219 GraphReducerTest() : graph_(zone()) {}
210 220
211 static void SetUpTestCase() { 221 static void SetUpTestCase() {
212 TestWithZone::SetUpTestCase(); 222 TestWithZone::SetUpTestCase();
213 DefaultValue<Reduction>::Set(Reducer::NoChange()); 223 DefaultValue<Reduction>::Set(Reducer::NoChange());
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
261 reducer.ReduceGraph(); 271 reducer.ReduceGraph();
262 } 272 }
263 273
264 Graph* graph() { return &graph_; } 274 Graph* graph() { return &graph_; }
265 275
266 private: 276 private:
267 Graph graph_; 277 Graph graph_;
268 }; 278 };
269 279
270 280
281 TEST_F(GraphReducerTest, AddReducerSetsObserver) {
282 StrictMock<MockReducer> r;
283 GraphReducer gr(graph(), zone());
284 gr.AddReducer(&r);
285 EXPECT_EQ(&gr, r.observer());
286 }
287
288
289 TEST_F(GraphReducerTest, DestructorResetsObserver) {
290 StrictMock<MockReducer> r;
291 {
292 GraphReducer gr(graph(), zone());
293 gr.AddReducer(&r);
294 }
295 EXPECT_EQ(nullptr, r.observer());
296 }
297
298
271 TEST_F(GraphReducerTest, NodeIsDeadAfterReplace) { 299 TEST_F(GraphReducerTest, NodeIsDeadAfterReplace) {
272 StrictMock<MockReducer> r; 300 StrictMock<MockReducer> r;
273 Node* node0 = graph()->NewNode(&kOpA0); 301 Node* node0 = graph()->NewNode(&kOpA0);
274 Node* node1 = graph()->NewNode(&kOpA1, node0); 302 Node* node1 = graph()->NewNode(&kOpA1, node0);
275 Node* node2 = graph()->NewNode(&kOpA1, node0); 303 Node* node2 = graph()->NewNode(&kOpA1, node0);
276 EXPECT_CALL(r, Reduce(node0)).WillOnce(Return(Reducer::NoChange())); 304 EXPECT_CALL(r, Reduce(node0)).WillOnce(Return(Reducer::NoChange()));
277 EXPECT_CALL(r, Reduce(node1)).WillOnce(Return(Reducer::Replace(node2))); 305 EXPECT_CALL(r, Reduce(node1)).WillOnce(Return(Reducer::Replace(node2)));
278 ReduceNode(node1, &r); 306 ReduceNode(node1, &r);
279 EXPECT_FALSE(node0->IsDead()); 307 EXPECT_FALSE(node0->IsDead());
280 EXPECT_TRUE(node1->IsDead()); 308 EXPECT_TRUE(node1->IsDead());
(...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after
566 EXPECT_EQ(&kOpA0, n1->op()); 594 EXPECT_EQ(&kOpA0, n1->op());
567 EXPECT_EQ(&kOpA1, n2->op()); 595 EXPECT_EQ(&kOpA1, n2->op());
568 EXPECT_EQ(&kOpA1, n3->op()); 596 EXPECT_EQ(&kOpA1, n3->op());
569 EXPECT_EQ(&kOpA2, end->op()); 597 EXPECT_EQ(&kOpA2, end->op());
570 EXPECT_EQ(end, graph()->end()); 598 EXPECT_EQ(end, graph()->end());
571 EXPECT_LE(end->InputAt(0)->id(), end->InputAt(1)->id()); 599 EXPECT_LE(end->InputAt(0)->id(), end->InputAt(1)->id());
572 } 600 }
573 } 601 }
574 602
575 603
604 namespace {
605
576 // Generate a node graph with the given permutations. 606 // Generate a node graph with the given permutations.
577 void GenDAG(Graph* graph, int* p3, int* p2, int* p1) { 607 void GenDAG(Graph* graph, int* p3, int* p2, int* p1) {
578 Node* level4 = graph->NewNode(&kOpA0); 608 Node* level4 = graph->NewNode(&kOpA0);
579 Node* level3[] = {graph->NewNode(&kOpA1, level4), 609 Node* level3[] = {graph->NewNode(&kOpA1, level4),
580 graph->NewNode(&kOpA1, level4)}; 610 graph->NewNode(&kOpA1, level4)};
581 611
582 Node* level2[] = {graph->NewNode(&kOpA1, level3[p3[0]]), 612 Node* level2[] = {graph->NewNode(&kOpA1, level3[p3[0]]),
583 graph->NewNode(&kOpA1, level3[p3[1]]), 613 graph->NewNode(&kOpA1, level3[p3[1]]),
584 graph->NewNode(&kOpA1, level3[p3[0]]), 614 graph->NewNode(&kOpA1, level3[p3[0]]),
585 graph->NewNode(&kOpA1, level3[p3[1]])}; 615 graph->NewNode(&kOpA1, level3[p3[1]])};
586 616
587 Node* level1[] = {graph->NewNode(&kOpA2, level2[p2[0]], level2[p2[1]]), 617 Node* level1[] = {graph->NewNode(&kOpA2, level2[p2[0]], level2[p2[1]]),
588 graph->NewNode(&kOpA2, level2[p2[2]], level2[p2[3]])}; 618 graph->NewNode(&kOpA2, level2[p2[2]], level2[p2[3]])};
589 619
590 Node* end = graph->NewNode(&kOpA2, level1[p1[0]], level1[p1[1]]); 620 Node* end = graph->NewNode(&kOpA2, level1[p1[0]], level1[p1[1]]);
591 graph->SetEnd(end); 621 graph->SetEnd(end);
592 } 622 }
593 623
624 } // namespace
625
594 626
595 TEST_F(GraphReducerTest, SortForwardReduce) { 627 TEST_F(GraphReducerTest, SortForwardReduce) {
596 // Tests combined reductions on a series of DAGs. 628 // Tests combined reductions on a series of DAGs.
597 for (int j = 0; j < 2; j++) { 629 for (int j = 0; j < 2; j++) {
598 int p3[] = {j, 1 - j}; 630 int p3[] = {j, 1 - j};
599 for (int m = 0; m < 2; m++) { 631 for (int m = 0; m < 2; m++) {
600 int p1[] = {m, 1 - m}; 632 int p1[] = {m, 1 - m};
601 for (int k = 0; k < 24; k++) { // All permutations of 0, 1, 2, 3 633 for (int k = 0; k < 24; k++) { // All permutations of 0, 1, 2, 3
602 int p2[] = {-1, -1, -1, -1}; 634 int p2[] = {-1, -1, -1, -1};
603 int n = k; 635 int n = k;
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
660 } 692 }
661 693
662 EXPECT_EQ(before, graph()->NodeCount()); 694 EXPECT_EQ(before, graph()->NodeCount());
663 EXPECT_EQ(&kOpC0, n1->op()); 695 EXPECT_EQ(&kOpC0, n1->op());
664 EXPECT_EQ(&kOpC1, end->op()); 696 EXPECT_EQ(&kOpC1, end->op());
665 EXPECT_EQ(n1, end->InputAt(0)); 697 EXPECT_EQ(n1, end->InputAt(0));
666 } 698 }
667 } 699 }
668 } 700 }
669 701
670
671 } // namespace compiler 702 } // namespace compiler
672 } // namespace internal 703 } // namespace internal
673 } // namespace v8 704 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698