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

Side by Side Diff: test/cctest/compiler/test-control-reducer.cc

Issue 665223006: Implement control reducer, which reduces branches and phis together in a single fixpoint. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 2 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 | Annotate | Revision Log
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/v8.h" 5 #include "src/v8.h"
6 #include "test/cctest/cctest.h" 6 #include "test/cctest/cctest.h"
7 7
8 #include "src/base/bits.h"
8 #include "src/compiler/common-operator.h" 9 #include "src/compiler/common-operator.h"
9 #include "src/compiler/control-reducer.h" 10 #include "src/compiler/control-reducer.h"
10 #include "src/compiler/graph-inl.h" 11 #include "src/compiler/graph-inl.h"
11 #include "src/compiler/js-graph.h" 12 #include "src/compiler/js-graph.h"
13 #include "src/compiler/node-properties-inl.h"
12 14
13 using namespace v8::internal; 15 using namespace v8::internal;
14 using namespace v8::internal::compiler; 16 using namespace v8::internal::compiler;
15 17
16 class CTrimTester : HandleAndZoneScope { 18 static const size_t kNumLeafs = 4;
19
20 // A helper for all tests dealing with ControlTester.
21 class ControlReducerTester : HandleAndZoneScope {
17 public: 22 public:
18 CTrimTester() 23 ControlReducerTester()
19 : isolate(main_isolate()), 24 : isolate(main_isolate()),
20 common(main_zone()), 25 common(main_zone()),
21 graph(main_zone()), 26 graph(main_zone()),
22 jsgraph(&graph, &common, NULL, NULL), 27 jsgraph(&graph, &common, NULL, NULL),
23 start(graph.NewNode(common.Start(1))), 28 start(graph.NewNode(common.Start(1))),
29 end(graph.NewNode(common.End(), start)),
24 p0(graph.NewNode(common.Parameter(0), start)), 30 p0(graph.NewNode(common.Parameter(0), start)),
31 zero(jsgraph.Int32Constant(0)),
25 one(jsgraph.OneConstant()), 32 one(jsgraph.OneConstant()),
26 half(jsgraph.Constant(0.5)) { 33 half(jsgraph.Constant(0.5)),
27 graph.SetEnd(start); 34 self(graph.NewNode(common.Int32Constant(0xaabbccdd))),
35 dead(graph.NewNode(common.Dead())) {
36 graph.SetEnd(end);
28 graph.SetStart(start); 37 graph.SetStart(start);
38 leaf[0] = zero;
39 leaf[1] = one;
40 leaf[2] = half;
41 leaf[3] = p0;
29 } 42 }
30 43
31 Isolate* isolate; 44 Isolate* isolate;
32 CommonOperatorBuilder common; 45 CommonOperatorBuilder common;
33 Graph graph; 46 Graph graph;
34 JSGraph jsgraph; 47 JSGraph jsgraph;
35 Node* start; 48 Node* start;
49 Node* end;
36 Node* p0; 50 Node* p0;
51 Node* zero;
37 Node* one; 52 Node* one;
38 Node* half; 53 Node* half;
54 Node* self;
55 Node* dead;
56 Node* leaf[kNumLeafs];
57
58 Node* Phi(Node* a) {
59 return SetSelfReferences(graph.NewNode(op(1, false), a, start));
60 }
61
62 Node* Phi(Node* a, Node* b) {
63 return SetSelfReferences(graph.NewNode(op(2, false), a, b, start));
64 }
65
66 Node* Phi(Node* a, Node* b, Node* c) {
67 return SetSelfReferences(graph.NewNode(op(3, false), a, b, c, start));
68 }
69
70 Node* Phi(Node* a, Node* b, Node* c, Node* d) {
71 return SetSelfReferences(graph.NewNode(op(4, false), a, b, c, d, start));
72 }
73
74 Node* EffectPhi(Node* a) {
75 return SetSelfReferences(graph.NewNode(op(1, true), a, start));
76 }
77
78 Node* EffectPhi(Node* a, Node* b) {
79 return SetSelfReferences(graph.NewNode(op(2, true), a, b, start));
80 }
81
82 Node* EffectPhi(Node* a, Node* b, Node* c) {
83 return SetSelfReferences(graph.NewNode(op(3, true), a, b, c, start));
84 }
85
86 Node* EffectPhi(Node* a, Node* b, Node* c, Node* d) {
87 return SetSelfReferences(graph.NewNode(op(4, true), a, b, c, d, start));
88 }
89
90 Node* SetSelfReferences(Node* node) {
91 Node::Inputs inputs = node->inputs();
92 for (Node::Inputs::iterator iter(inputs.begin()); iter != inputs.end();
93 ++iter) {
94 Node* input = *iter;
95 if (input == self) node->ReplaceInput(iter.index(), node);
96 }
97 return node;
98 }
99
100 const Operator* op(int count, bool effect) {
101 return effect ? common.EffectPhi(count) : common.Phi(kMachAnyTagged, count);
102 }
39 103
40 void Trim() { ControlReducer::TrimGraph(main_zone(), &jsgraph); } 104 void Trim() { ControlReducer::TrimGraph(main_zone(), &jsgraph); }
105
106 // Checks one-step reduction of a phi.
107 void ReducePhi(Node* expect, Node* phi) {
108 Node* result = ControlReducer::ReducePhiForTesting(&jsgraph, &common, phi);
109 CHECK_EQ(expect, result);
110 ReducePhiIterative(expect, phi); // iterative should give the same result.
111 }
112
113 void ReducePhiIterative(Node* expect, Node* phi) {
114 p0->ReplaceInput(0, start); // hack: parameters may be trimmed.
115 Node* ret = graph.NewNode(common.Return(), phi, start);
116 Node* end = graph.NewNode(common.End(), ret);
117 graph.SetEnd(end);
118 ControlReducer::ReduceGraph(main_zone(), &jsgraph, &common);
119 CHECK_EQ(expect, ret->InputAt(0));
120 }
121
122 void ReduceMerge(Node* expect, Node* merge) {
123 Node* result =
124 ControlReducer::ReduceMergeForTesting(&jsgraph, &common, merge);
125 CHECK_EQ(expect, result);
126 }
127
128 void ReduceMergeIterative(Node* expect, Node* merge) {
129 p0->ReplaceInput(0, start); // hack: parameters may be trimmed.
130 Node* end = graph.NewNode(common.End(), merge);
131 graph.SetEnd(end);
132 ControlReducer::ReduceGraph(main_zone(), &jsgraph, &common);
133 CHECK_EQ(expect, end->InputAt(0));
134 }
135
136 void ReduceBranch(Node* expect, Node* branch) {
137 Node* result =
138 ControlReducer::ReduceBranchForTesting(&jsgraph, &common, branch);
139 CHECK_EQ(expect, result);
140 }
41 }; 141 };
42 142
43 143
44 bool IsUsedBy(Node* a, Node* b) { 144 bool IsUsedBy(Node* a, Node* b) {
45 for (UseIter i = a->uses().begin(); i != a->uses().end(); ++i) { 145 for (UseIter i = a->uses().begin(); i != a->uses().end(); ++i) {
46 if (b == *i) return true; 146 if (b == *i) return true;
47 } 147 }
48 return false; 148 return false;
49 } 149 }
50 150
51 151
52 TEST(Trim1_live) { 152 TEST(Trim1_live) {
53 CTrimTester T; 153 ControlReducerTester T;
54 CHECK(IsUsedBy(T.start, T.p0)); 154 CHECK(IsUsedBy(T.start, T.p0));
55 T.graph.SetEnd(T.p0); 155 T.graph.SetEnd(T.p0);
56 T.Trim(); 156 T.Trim();
57 CHECK(IsUsedBy(T.start, T.p0)); 157 CHECK(IsUsedBy(T.start, T.p0));
58 CHECK_EQ(T.start, T.p0->InputAt(0)); 158 CHECK_EQ(T.start, T.p0->InputAt(0));
59 } 159 }
60 160
61 161
62 TEST(Trim1_dead) { 162 TEST(Trim1_dead) {
63 CTrimTester T; 163 ControlReducerTester T;
64 CHECK(IsUsedBy(T.start, T.p0)); 164 CHECK(IsUsedBy(T.start, T.p0));
65 T.Trim(); 165 T.Trim();
66 CHECK(!IsUsedBy(T.start, T.p0)); 166 CHECK(!IsUsedBy(T.start, T.p0));
67 CHECK_EQ(NULL, T.p0->InputAt(0)); 167 CHECK_EQ(NULL, T.p0->InputAt(0));
68 } 168 }
69 169
70 170
71 TEST(Trim2_live) { 171 TEST(Trim2_live) {
72 CTrimTester T; 172 ControlReducerTester T;
73 Node* phi = 173 Node* phi =
74 T.graph.NewNode(T.common.Phi(kMachAnyTagged, 2), T.one, T.half, T.start); 174 T.graph.NewNode(T.common.Phi(kMachAnyTagged, 2), T.one, T.half, T.start);
75 CHECK(IsUsedBy(T.one, phi)); 175 CHECK(IsUsedBy(T.one, phi));
76 CHECK(IsUsedBy(T.half, phi)); 176 CHECK(IsUsedBy(T.half, phi));
77 CHECK(IsUsedBy(T.start, phi)); 177 CHECK(IsUsedBy(T.start, phi));
78 T.graph.SetEnd(phi); 178 T.graph.SetEnd(phi);
79 T.Trim(); 179 T.Trim();
80 CHECK(IsUsedBy(T.one, phi)); 180 CHECK(IsUsedBy(T.one, phi));
81 CHECK(IsUsedBy(T.half, phi)); 181 CHECK(IsUsedBy(T.half, phi));
82 CHECK(IsUsedBy(T.start, phi)); 182 CHECK(IsUsedBy(T.start, phi));
83 CHECK_EQ(T.one, phi->InputAt(0)); 183 CHECK_EQ(T.one, phi->InputAt(0));
84 CHECK_EQ(T.half, phi->InputAt(1)); 184 CHECK_EQ(T.half, phi->InputAt(1));
85 CHECK_EQ(T.start, phi->InputAt(2)); 185 CHECK_EQ(T.start, phi->InputAt(2));
86 } 186 }
87 187
88 188
89 TEST(Trim2_dead) { 189 TEST(Trim2_dead) {
90 CTrimTester T; 190 ControlReducerTester T;
91 Node* phi = 191 Node* phi =
92 T.graph.NewNode(T.common.Phi(kMachAnyTagged, 2), T.one, T.half, T.start); 192 T.graph.NewNode(T.common.Phi(kMachAnyTagged, 2), T.one, T.half, T.start);
93 CHECK(IsUsedBy(T.one, phi)); 193 CHECK(IsUsedBy(T.one, phi));
94 CHECK(IsUsedBy(T.half, phi)); 194 CHECK(IsUsedBy(T.half, phi));
95 CHECK(IsUsedBy(T.start, phi)); 195 CHECK(IsUsedBy(T.start, phi));
96 T.Trim(); 196 T.Trim();
97 CHECK(!IsUsedBy(T.one, phi)); 197 CHECK(!IsUsedBy(T.one, phi));
98 CHECK(!IsUsedBy(T.half, phi)); 198 CHECK(!IsUsedBy(T.half, phi));
99 CHECK(!IsUsedBy(T.start, phi)); 199 CHECK(!IsUsedBy(T.start, phi));
100 CHECK_EQ(NULL, phi->InputAt(0)); 200 CHECK_EQ(NULL, phi->InputAt(0));
101 CHECK_EQ(NULL, phi->InputAt(1)); 201 CHECK_EQ(NULL, phi->InputAt(1));
102 CHECK_EQ(NULL, phi->InputAt(2)); 202 CHECK_EQ(NULL, phi->InputAt(2));
103 } 203 }
104 204
105 205
106 TEST(Trim_chain1) { 206 TEST(Trim_chain1) {
107 CTrimTester T; 207 ControlReducerTester T;
108 const int kDepth = 15; 208 const int kDepth = 15;
109 Node* live[kDepth]; 209 Node* live[kDepth];
110 Node* dead[kDepth]; 210 Node* dead[kDepth];
111 Node* end = T.start; 211 Node* end = T.start;
112 for (int i = 0; i < kDepth; i++) { 212 for (int i = 0; i < kDepth; i++) {
113 live[i] = end = T.graph.NewNode(T.common.Merge(1), end); 213 live[i] = end = T.graph.NewNode(T.common.Merge(1), end);
114 dead[i] = T.graph.NewNode(T.common.Merge(1), end); 214 dead[i] = T.graph.NewNode(T.common.Merge(1), end);
115 } 215 }
116 // end -> live[last] -> live[last-1] -> ... -> start 216 // end -> live[last] -> live[last-1] -> ... -> start
117 // dead[last] ^ dead[last-1] ^ ... ^ 217 // dead[last] ^ dead[last-1] ^ ... ^
118 T.graph.SetEnd(end); 218 T.graph.SetEnd(end);
119 T.Trim(); 219 T.Trim();
120 for (int i = 0; i < kDepth; i++) { 220 for (int i = 0; i < kDepth; i++) {
121 CHECK(!IsUsedBy(live[i], dead[i])); 221 CHECK(!IsUsedBy(live[i], dead[i]));
122 CHECK_EQ(NULL, dead[i]->InputAt(0)); 222 CHECK_EQ(NULL, dead[i]->InputAt(0));
123 CHECK_EQ(i == 0 ? T.start : live[i - 1], live[i]->InputAt(0)); 223 CHECK_EQ(i == 0 ? T.start : live[i - 1], live[i]->InputAt(0));
124 } 224 }
125 } 225 }
126 226
127 227
128 TEST(Trim_chain2) { 228 TEST(Trim_chain2) {
129 CTrimTester T; 229 ControlReducerTester T;
130 const int kDepth = 15; 230 const int kDepth = 15;
131 Node* live[kDepth]; 231 Node* live[kDepth];
132 Node* dead[kDepth]; 232 Node* dead[kDepth];
133 Node* l = T.start; 233 Node* l = T.start;
134 Node* d = T.start; 234 Node* d = T.start;
135 for (int i = 0; i < kDepth; i++) { 235 for (int i = 0; i < kDepth; i++) {
136 live[i] = l = T.graph.NewNode(T.common.Merge(1), l); 236 live[i] = l = T.graph.NewNode(T.common.Merge(1), l);
137 dead[i] = d = T.graph.NewNode(T.common.Merge(1), d); 237 dead[i] = d = T.graph.NewNode(T.common.Merge(1), d);
138 } 238 }
139 // end -> live[last] -> live[last-1] -> ... -> start 239 // end -> live[last] -> live[last-1] -> ... -> start
140 // dead[last] -> dead[last-1] -> ... -> start 240 // dead[last] -> dead[last-1] -> ... -> start
141 T.graph.SetEnd(l); 241 T.graph.SetEnd(l);
142 T.Trim(); 242 T.Trim();
143 CHECK(!IsUsedBy(T.start, dead[0])); 243 CHECK(!IsUsedBy(T.start, dead[0]));
144 for (int i = 0; i < kDepth; i++) { 244 for (int i = 0; i < kDepth; i++) {
145 CHECK_EQ(i == 0 ? NULL : dead[i - 1], dead[i]->InputAt(0)); 245 CHECK_EQ(i == 0 ? NULL : dead[i - 1], dead[i]->InputAt(0));
146 CHECK_EQ(i == 0 ? T.start : live[i - 1], live[i]->InputAt(0)); 246 CHECK_EQ(i == 0 ? T.start : live[i - 1], live[i]->InputAt(0));
147 } 247 }
148 } 248 }
149 249
150 250
151 TEST(Trim_cycle1) { 251 TEST(Trim_cycle1) {
152 CTrimTester T; 252 ControlReducerTester T;
153 Node* loop = T.graph.NewNode(T.common.Loop(1), T.start, T.start); 253 Node* loop = T.graph.NewNode(T.common.Loop(1), T.start, T.start);
154 loop->ReplaceInput(1, loop); 254 loop->ReplaceInput(1, loop);
155 Node* end = T.graph.NewNode(T.common.End(), loop); 255 Node* end = T.graph.NewNode(T.common.End(), loop);
156 T.graph.SetEnd(end); 256 T.graph.SetEnd(end);
157 257
158 CHECK(IsUsedBy(T.start, loop)); 258 CHECK(IsUsedBy(T.start, loop));
159 CHECK(IsUsedBy(loop, end)); 259 CHECK(IsUsedBy(loop, end));
160 CHECK(IsUsedBy(loop, loop)); 260 CHECK(IsUsedBy(loop, loop));
161 261
162 T.Trim(); 262 T.Trim();
163 263
164 // nothing should have happened to the loop itself. 264 // nothing should have happened to the loop itself.
165 CHECK(IsUsedBy(T.start, loop)); 265 CHECK(IsUsedBy(T.start, loop));
166 CHECK(IsUsedBy(loop, end)); 266 CHECK(IsUsedBy(loop, end));
167 CHECK(IsUsedBy(loop, loop)); 267 CHECK(IsUsedBy(loop, loop));
168 CHECK_EQ(T.start, loop->InputAt(0)); 268 CHECK_EQ(T.start, loop->InputAt(0));
169 CHECK_EQ(loop, loop->InputAt(1)); 269 CHECK_EQ(loop, loop->InputAt(1));
170 CHECK_EQ(loop, end->InputAt(0)); 270 CHECK_EQ(loop, end->InputAt(0));
171 } 271 }
172 272
173 273
174 TEST(Trim_cycle2) { 274 TEST(Trim_cycle2) {
175 CTrimTester T; 275 ControlReducerTester T;
176 Node* loop = T.graph.NewNode(T.common.Loop(2), T.start, T.start); 276 Node* loop = T.graph.NewNode(T.common.Loop(2), T.start, T.start);
177 loop->ReplaceInput(1, loop); 277 loop->ReplaceInput(1, loop);
178 Node* end = T.graph.NewNode(T.common.End(), loop); 278 Node* end = T.graph.NewNode(T.common.End(), loop);
179 Node* phi = 279 Node* phi =
180 T.graph.NewNode(T.common.Phi(kMachAnyTagged, 2), T.one, T.half, loop); 280 T.graph.NewNode(T.common.Phi(kMachAnyTagged, 2), T.one, T.half, loop);
181 T.graph.SetEnd(end); 281 T.graph.SetEnd(end);
182 282
183 CHECK(IsUsedBy(T.start, loop)); 283 CHECK(IsUsedBy(T.start, loop));
184 CHECK(IsUsedBy(loop, end)); 284 CHECK(IsUsedBy(loop, end));
185 CHECK(IsUsedBy(loop, loop)); 285 CHECK(IsUsedBy(loop, loop));
(...skipping 14 matching lines...) Expand all
200 // phi should have been trimmed away. 300 // phi should have been trimmed away.
201 CHECK(!IsUsedBy(loop, phi)); 301 CHECK(!IsUsedBy(loop, phi));
202 CHECK(!IsUsedBy(T.one, phi)); 302 CHECK(!IsUsedBy(T.one, phi));
203 CHECK(!IsUsedBy(T.half, phi)); 303 CHECK(!IsUsedBy(T.half, phi));
204 CHECK_EQ(NULL, phi->InputAt(0)); 304 CHECK_EQ(NULL, phi->InputAt(0));
205 CHECK_EQ(NULL, phi->InputAt(1)); 305 CHECK_EQ(NULL, phi->InputAt(1));
206 CHECK_EQ(NULL, phi->InputAt(2)); 306 CHECK_EQ(NULL, phi->InputAt(2));
207 } 307 }
208 308
209 309
210 void CheckTrimConstant(CTrimTester* T, Node* k) { 310 void CheckTrimConstant(ControlReducerTester* T, Node* k) {
211 Node* phi = T->graph.NewNode(T->common.Phi(kMachInt32, 1), k, T->start); 311 Node* phi = T->graph.NewNode(T->common.Phi(kMachInt32, 1), k, T->start);
212 CHECK(IsUsedBy(k, phi)); 312 CHECK(IsUsedBy(k, phi));
213 T->Trim(); 313 T->Trim();
214 CHECK(!IsUsedBy(k, phi)); 314 CHECK(!IsUsedBy(k, phi));
215 CHECK_EQ(NULL, phi->InputAt(0)); 315 CHECK_EQ(NULL, phi->InputAt(0));
216 CHECK_EQ(NULL, phi->InputAt(1)); 316 CHECK_EQ(NULL, phi->InputAt(1));
217 } 317 }
218 318
219 319
220 TEST(Trim_constants) { 320 TEST(Trim_constants) {
221 CTrimTester T; 321 ControlReducerTester T;
222 int32_t int32_constants[] = { 322 int32_t int32_constants[] = {
223 0, -1, -2, 2, 2, 3, 3, 4, 4, 5, 5, 4, 5, 6, 6, 7, 8, 7, 8, 9, 323 0, -1, -2, 2, 2, 3, 3, 4, 4, 5, 5, 4, 5, 6, 6, 7, 8, 7, 8, 9,
224 0, -11, -12, 12, 12, 13, 13, 14, 14, 15, 15, 14, 15, 6, 6, 7, 8, 7, 8, 9}; 324 0, -11, -12, 12, 12, 13, 13, 14, 14, 15, 15, 14, 15, 6, 6, 7, 8, 7, 8, 9};
225 325
226 for (size_t i = 0; i < arraysize(int32_constants); i++) { 326 for (size_t i = 0; i < arraysize(int32_constants); i++) {
227 CheckTrimConstant(&T, T.jsgraph.Int32Constant(int32_constants[i])); 327 CheckTrimConstant(&T, T.jsgraph.Int32Constant(int32_constants[i]));
228 CheckTrimConstant(&T, T.jsgraph.Float64Constant(int32_constants[i])); 328 CheckTrimConstant(&T, T.jsgraph.Float64Constant(int32_constants[i]));
229 CheckTrimConstant(&T, T.jsgraph.Constant(int32_constants[i])); 329 CheckTrimConstant(&T, T.jsgraph.Constant(int32_constants[i]));
230 } 330 }
231 331
232 Node* other_constants[] = { 332 Node* other_constants[] = {
233 T.jsgraph.UndefinedConstant(), T.jsgraph.TheHoleConstant(), 333 T.jsgraph.UndefinedConstant(), T.jsgraph.TheHoleConstant(),
234 T.jsgraph.TrueConstant(), T.jsgraph.FalseConstant(), 334 T.jsgraph.TrueConstant(), T.jsgraph.FalseConstant(),
235 T.jsgraph.NullConstant(), T.jsgraph.ZeroConstant(), 335 T.jsgraph.NullConstant(), T.jsgraph.ZeroConstant(),
236 T.jsgraph.OneConstant(), T.jsgraph.NaNConstant(), 336 T.jsgraph.OneConstant(), T.jsgraph.NaNConstant(),
237 T.jsgraph.Constant(21), T.jsgraph.Constant(22.2)}; 337 T.jsgraph.Constant(21), T.jsgraph.Constant(22.2)};
238 338
239 for (size_t i = 0; i < arraysize(other_constants); i++) { 339 for (size_t i = 0; i < arraysize(other_constants); i++) {
240 CheckTrimConstant(&T, other_constants[i]); 340 CheckTrimConstant(&T, other_constants[i]);
241 } 341 }
242 } 342 }
343
344
345 TEST(CReducePhi1) {
346 ControlReducerTester R;
347
348 R.ReducePhi(R.leaf[0], R.Phi(R.leaf[0]));
349 R.ReducePhi(R.leaf[1], R.Phi(R.leaf[1]));
350 R.ReducePhi(R.leaf[2], R.Phi(R.leaf[2]));
351 R.ReducePhi(R.leaf[3], R.Phi(R.leaf[3]));
352 }
353
354
355 TEST(CReducePhi1_dead) {
356 ControlReducerTester R;
357
358 R.ReducePhi(R.leaf[0], R.Phi(R.leaf[0], R.dead));
359 R.ReducePhi(R.leaf[1], R.Phi(R.leaf[1], R.dead));
360 R.ReducePhi(R.leaf[2], R.Phi(R.leaf[2], R.dead));
361 R.ReducePhi(R.leaf[3], R.Phi(R.leaf[3], R.dead));
362
363 R.ReducePhi(R.leaf[0], R.Phi(R.dead, R.leaf[0]));
364 R.ReducePhi(R.leaf[1], R.Phi(R.dead, R.leaf[1]));
365 R.ReducePhi(R.leaf[2], R.Phi(R.dead, R.leaf[2]));
366 R.ReducePhi(R.leaf[3], R.Phi(R.dead, R.leaf[3]));
367 }
368
369
370 TEST(CReducePhi1_dead2) {
371 ControlReducerTester R;
372
373 R.ReducePhi(R.leaf[0], R.Phi(R.leaf[0], R.dead, R.dead));
374 R.ReducePhi(R.leaf[0], R.Phi(R.dead, R.leaf[0], R.dead));
375 R.ReducePhi(R.leaf[0], R.Phi(R.dead, R.dead, R.leaf[0]));
376 }
377
378
379 TEST(CReducePhi2a) {
380 ControlReducerTester R;
381
382 for (size_t i = 0; i < kNumLeafs; i++) {
383 Node* a = R.leaf[i];
384 R.ReducePhi(a, R.Phi(a, a));
385 }
386 }
387
388
389 TEST(CReducePhi2b) {
390 ControlReducerTester R;
391
392 for (size_t i = 0; i < kNumLeafs; i++) {
393 Node* a = R.leaf[i];
394 R.ReducePhi(a, R.Phi(R.self, a));
395 R.ReducePhi(a, R.Phi(a, R.self));
396 }
397 }
398
399
400 TEST(CReducePhi2c) {
401 ControlReducerTester R;
402
403 for (size_t i = 1; i < kNumLeafs; i++) {
404 Node* a = R.leaf[i], *b = R.leaf[0];
405 Node* phi1 = R.Phi(b, a);
406 R.ReducePhi(phi1, phi1);
407
408 Node* phi2 = R.Phi(a, b);
409 R.ReducePhi(phi2, phi2);
410 }
411 }
412
413
414 TEST(CReducePhi2_dead) {
415 ControlReducerTester R;
416
417 for (size_t i = 0; i < kNumLeafs; i++) {
418 Node* a = R.leaf[i];
419 R.ReducePhi(a, R.Phi(a, a, R.dead));
420 R.ReducePhi(a, R.Phi(a, R.dead, a));
421 R.ReducePhi(a, R.Phi(R.dead, a, a));
422 }
423
424 for (size_t i = 0; i < kNumLeafs; i++) {
425 Node* a = R.leaf[i];
426 R.ReducePhi(a, R.Phi(R.self, a));
427 R.ReducePhi(a, R.Phi(a, R.self));
428 R.ReducePhi(a, R.Phi(R.self, a, R.dead));
429 R.ReducePhi(a, R.Phi(a, R.self, R.dead));
430 }
431
432 for (size_t i = 1; i < kNumLeafs; i++) {
433 Node* a = R.leaf[i], *b = R.leaf[0];
434 Node* phi1 = R.Phi(b, a, R.dead);
435 R.ReducePhi(phi1, phi1);
436
437 Node* phi2 = R.Phi(a, b, R.dead);
438 R.ReducePhi(phi2, phi2);
439 }
440 }
441
442
443 TEST(CReducePhi3) {
444 ControlReducerTester R;
445
446 for (size_t i = 0; i < kNumLeafs; i++) {
447 Node* a = R.leaf[i];
448 R.ReducePhi(a, R.Phi(a, a, a));
449 }
450
451 for (size_t i = 0; i < kNumLeafs; i++) {
452 Node* a = R.leaf[i];
453 R.ReducePhi(a, R.Phi(R.self, a, a));
454 R.ReducePhi(a, R.Phi(a, R.self, a));
455 R.ReducePhi(a, R.Phi(a, a, R.self));
456 }
457
458 for (size_t i = 1; i < kNumLeafs; i++) {
459 Node* a = R.leaf[i], *b = R.leaf[0];
460 Node* phi1 = R.Phi(b, a, a);
461 R.ReducePhi(phi1, phi1);
462
463 Node* phi2 = R.Phi(a, b, a);
464 R.ReducePhi(phi2, phi2);
465
466 Node* phi3 = R.Phi(a, a, b);
467 R.ReducePhi(phi3, phi3);
468 }
469 }
470
471
472 TEST(CReducePhi4) {
473 ControlReducerTester R;
474
475 for (size_t i = 0; i < kNumLeafs; i++) {
476 Node* a = R.leaf[i];
477 R.ReducePhi(a, R.Phi(a, a, a, a));
478 }
479
480 for (size_t i = 0; i < kNumLeafs; i++) {
481 Node* a = R.leaf[i];
482 R.ReducePhi(a, R.Phi(R.self, a, a, a));
483 R.ReducePhi(a, R.Phi(a, R.self, a, a));
484 R.ReducePhi(a, R.Phi(a, a, R.self, a));
485 R.ReducePhi(a, R.Phi(a, a, a, R.self));
486
487 R.ReducePhi(a, R.Phi(R.self, R.self, a, a));
488 R.ReducePhi(a, R.Phi(a, R.self, R.self, a));
489 R.ReducePhi(a, R.Phi(a, a, R.self, R.self));
490 R.ReducePhi(a, R.Phi(R.self, a, a, R.self));
491 }
492
493 for (size_t i = 1; i < kNumLeafs; i++) {
494 Node* a = R.leaf[i], *b = R.leaf[0];
495 Node* phi1 = R.Phi(b, a, a, a);
496 R.ReducePhi(phi1, phi1);
497
498 Node* phi2 = R.Phi(a, b, a, a);
499 R.ReducePhi(phi2, phi2);
500
501 Node* phi3 = R.Phi(a, a, b, a);
502 R.ReducePhi(phi3, phi3);
503
504 Node* phi4 = R.Phi(a, a, a, b);
505 R.ReducePhi(phi4, phi4);
506 }
507 }
508
509
510 TEST(CReducePhi_iterative1) {
511 ControlReducerTester R;
512
513 R.ReducePhiIterative(R.leaf[0], R.Phi(R.leaf[0], R.Phi(R.leaf[0])));
514 R.ReducePhiIterative(R.leaf[0], R.Phi(R.Phi(R.leaf[0]), R.leaf[0]));
515 }
516
517
518 TEST(CReducePhi_iterative2) {
519 ControlReducerTester R;
520
521 R.ReducePhiIterative(R.leaf[0], R.Phi(R.Phi(R.leaf[0]), R.Phi(R.leaf[0])));
522 }
523
524
525 TEST(CReducePhi_iterative3) {
526 ControlReducerTester R;
527
528 R.ReducePhiIterative(R.leaf[0],
529 R.Phi(R.leaf[0], R.Phi(R.leaf[0], R.leaf[0])));
530 R.ReducePhiIterative(R.leaf[0],
531 R.Phi(R.Phi(R.leaf[0], R.leaf[0]), R.leaf[0]));
532 }
533
534
535 TEST(CReducePhi_iterative4) {
536 ControlReducerTester R;
537
538 R.ReducePhiIterative(R.leaf[0], R.Phi(R.Phi(R.leaf[0], R.leaf[0]),
539 R.Phi(R.leaf[0], R.leaf[0])));
540
541 Node* p1 = R.Phi(R.leaf[0], R.leaf[0]);
542 R.ReducePhiIterative(R.leaf[0], R.Phi(p1, p1));
543
544 Node* p2 = R.Phi(R.leaf[0], R.leaf[0], R.leaf[0]);
545 R.ReducePhiIterative(R.leaf[0], R.Phi(p2, p2, p2));
546
547 Node* p3 = R.Phi(R.leaf[0], R.leaf[0], R.leaf[0]);
548 R.ReducePhiIterative(R.leaf[0], R.Phi(p3, p3, R.leaf[0]));
549 }
550
551
552 TEST(CReducePhi_iterative_self1) {
553 ControlReducerTester R;
554
555 R.ReducePhiIterative(R.leaf[0], R.Phi(R.leaf[0], R.Phi(R.leaf[0], R.self)));
556 R.ReducePhiIterative(R.leaf[0], R.Phi(R.Phi(R.leaf[0], R.self), R.leaf[0]));
557 }
558
559
560 TEST(CReducePhi_iterative_self2) {
561 ControlReducerTester R;
562
563 R.ReducePhiIterative(
564 R.leaf[0], R.Phi(R.Phi(R.leaf[0], R.self), R.Phi(R.leaf[0], R.self)));
565 R.ReducePhiIterative(
566 R.leaf[0], R.Phi(R.Phi(R.self, R.leaf[0]), R.Phi(R.self, R.leaf[0])));
567
568 Node* p1 = R.Phi(R.leaf[0], R.self);
569 R.ReducePhiIterative(R.leaf[0], R.Phi(p1, p1));
570
571 Node* p2 = R.Phi(R.self, R.leaf[0]);
572 R.ReducePhiIterative(R.leaf[0], R.Phi(p2, p2));
573 }
574
575
576 TEST(EReducePhi1) {
577 ControlReducerTester R;
578
579 R.ReducePhi(R.leaf[0], R.EffectPhi(R.leaf[0]));
580 R.ReducePhi(R.leaf[1], R.EffectPhi(R.leaf[1]));
581 R.ReducePhi(R.leaf[2], R.EffectPhi(R.leaf[2]));
582 R.ReducePhi(R.leaf[3], R.EffectPhi(R.leaf[3]));
583 }
584
585
586 TEST(EReducePhi1_dead) {
587 ControlReducerTester R;
588
589 R.ReducePhi(R.leaf[0], R.EffectPhi(R.leaf[0], R.dead));
590 R.ReducePhi(R.leaf[1], R.EffectPhi(R.leaf[1], R.dead));
591 R.ReducePhi(R.leaf[2], R.EffectPhi(R.leaf[2], R.dead));
592 R.ReducePhi(R.leaf[3], R.EffectPhi(R.leaf[3], R.dead));
593
594 R.ReducePhi(R.leaf[0], R.EffectPhi(R.dead, R.leaf[0]));
595 R.ReducePhi(R.leaf[1], R.EffectPhi(R.dead, R.leaf[1]));
596 R.ReducePhi(R.leaf[2], R.EffectPhi(R.dead, R.leaf[2]));
597 R.ReducePhi(R.leaf[3], R.EffectPhi(R.dead, R.leaf[3]));
598 }
599
600
601 TEST(EReducePhi1_dead2) {
602 ControlReducerTester R;
603
604 R.ReducePhi(R.leaf[0], R.EffectPhi(R.leaf[0], R.dead, R.dead));
605 R.ReducePhi(R.leaf[0], R.EffectPhi(R.dead, R.leaf[0], R.dead));
606 R.ReducePhi(R.leaf[0], R.EffectPhi(R.dead, R.dead, R.leaf[0]));
607 }
608
609
610 TEST(CMergeReduce_simple1) {
611 ControlReducerTester R;
612
613 Node* merge = R.graph.NewNode(R.common.Merge(1), R.start);
614 R.ReduceMerge(R.start, merge);
615 }
616
617
618 TEST(CMergeReduce_simple2) {
619 ControlReducerTester R;
620
621 Node* merge1 = R.graph.NewNode(R.common.Merge(1), R.start);
622 Node* merge2 = R.graph.NewNode(R.common.Merge(1), merge1);
623 R.ReduceMerge(merge1, merge2);
624 R.ReduceMergeIterative(R.start, merge2);
625 }
626
627
628 TEST(CMergeReduce_none1) {
629 ControlReducerTester R;
630
631 Node* merge = R.graph.NewNode(R.common.Merge(2), R.start, R.start);
632 R.ReduceMerge(merge, merge);
633 }
634
635
636 TEST(CMergeReduce_none2) {
637 ControlReducerTester R;
638
639 Node* t = R.graph.NewNode(R.common.IfTrue(), R.start);
640 Node* f = R.graph.NewNode(R.common.IfFalse(), R.start);
641 Node* merge = R.graph.NewNode(R.common.Merge(2), t, f);
642 R.ReduceMerge(merge, merge);
643 }
644
645
646 TEST(CMergeReduce_self3) {
647 ControlReducerTester R;
648
649 Node* merge =
650 R.SetSelfReferences(R.graph.NewNode(R.common.Merge(2), R.start, R.self));
651 R.ReduceMerge(merge, merge);
652 }
653
654
655 TEST(CMergeReduce_dead1) {
656 ControlReducerTester R;
657
658 Node* merge = R.graph.NewNode(R.common.Merge(2), R.start, R.dead);
659 R.ReduceMerge(R.start, merge);
660 }
661
662
663 TEST(CMergeReduce_dead2) {
664 ControlReducerTester R;
665
666 Node* merge1 = R.graph.NewNode(R.common.Merge(1), R.start);
667 Node* merge2 = R.graph.NewNode(R.common.Merge(2), merge1, R.dead);
668 R.ReduceMerge(merge1, merge2);
669 R.ReduceMergeIterative(R.start, merge2);
670 }
671
672
673 TEST(CMergeReduce_dead_rm1a) {
674 ControlReducerTester R;
675
676 for (int i = 0; i < 3; i++) {
677 Node* merge = R.graph.NewNode(R.common.Merge(3), R.start, R.start, R.start);
678 merge->ReplaceInput(i, R.dead);
679 R.ReduceMerge(merge, merge);
680 CHECK_EQ(IrOpcode::kMerge, merge->opcode());
681 CHECK_EQ(2, OpParameter<int32_t>(merge->op()));
682 CHECK_EQ(2, merge->InputCount());
683 CHECK_EQ(R.start, merge->InputAt(0));
684 CHECK_EQ(R.start, merge->InputAt(1));
685 }
686 }
687
688
689 TEST(CMergeReduce_dead_rm1b) {
690 ControlReducerTester R;
691
692 Node* t = R.graph.NewNode(R.common.IfTrue(), R.start);
693 Node* f = R.graph.NewNode(R.common.IfFalse(), R.start);
694 for (int i = 0; i < 2; i++) {
695 Node* merge = R.graph.NewNode(R.common.Merge(3), R.dead, R.dead, R.dead);
696 for (int j = i + 1; j < 3; j++) {
697 merge->ReplaceInput(i, t);
698 merge->ReplaceInput(j, f);
699 R.ReduceMerge(merge, merge);
700 CHECK_EQ(IrOpcode::kMerge, merge->opcode());
701 CHECK_EQ(2, OpParameter<int32_t>(merge->op()));
702 CHECK_EQ(2, merge->InputCount());
703 CHECK_EQ(t, merge->InputAt(0));
704 CHECK_EQ(f, merge->InputAt(1));
705 }
706 }
707 }
708
709
710 TEST(CMergeReduce_dead_rm2) {
711 ControlReducerTester R;
712
713 for (int i = 0; i < 3; i++) {
714 Node* merge = R.graph.NewNode(R.common.Merge(3), R.dead, R.dead, R.dead);
715 merge->ReplaceInput(i, R.start);
716 R.ReduceMerge(R.start, merge);
717 }
718 }
719
720
721 TEST(CLoopReduce_dead_rm1) {
722 ControlReducerTester R;
723
724 for (int i = 0; i < 3; i++) {
725 Node* loop = R.graph.NewNode(R.common.Loop(3), R.dead, R.start, R.start);
726 R.ReduceMerge(loop, loop);
727 CHECK_EQ(IrOpcode::kLoop, loop->opcode());
728 CHECK_EQ(2, OpParameter<int32_t>(loop->op()));
729 CHECK_EQ(2, loop->InputCount());
730 CHECK_EQ(R.start, loop->InputAt(0));
731 CHECK_EQ(R.start, loop->InputAt(1));
732 }
733 }
734
735
736 TEST(CMergeReduce_edit_phi1) {
737 ControlReducerTester R;
738
739 for (int i = 0; i < 3; i++) {
740 Node* merge = R.graph.NewNode(R.common.Merge(3), R.start, R.start, R.start);
741 merge->ReplaceInput(i, R.dead);
742 Node* phi = R.graph.NewNode(R.common.Phi(kMachAnyTagged, 3), R.leaf[0],
743 R.leaf[1], R.leaf[2], merge);
744 R.ReduceMerge(merge, merge);
745 CHECK_EQ(IrOpcode::kPhi, phi->opcode());
746 CHECK_EQ(2, phi->op()->InputCount());
747 CHECK_EQ(3, phi->InputCount());
748 CHECK_EQ(R.leaf[i < 1 ? 1 : 0], phi->InputAt(0));
749 CHECK_EQ(R.leaf[i < 2 ? 2 : 1], phi->InputAt(1));
750 CHECK_EQ(merge, phi->InputAt(2));
751 }
752 }
753
754
755 TEST(CMergeReduce_edit_effect_phi1) {
756 ControlReducerTester R;
757
758 for (int i = 0; i < 3; i++) {
759 Node* merge = R.graph.NewNode(R.common.Merge(3), R.start, R.start, R.start);
760 merge->ReplaceInput(i, R.dead);
761 Node* phi = R.graph.NewNode(R.common.EffectPhi(3), R.leaf[0], R.leaf[1],
762 R.leaf[2], merge);
763 R.ReduceMerge(merge, merge);
764 CHECK_EQ(IrOpcode::kEffectPhi, phi->opcode());
765 CHECK_EQ(0, phi->op()->InputCount());
766 CHECK_EQ(2, OperatorProperties::GetEffectInputCount(phi->op()));
767 CHECK_EQ(3, phi->InputCount());
768 CHECK_EQ(R.leaf[i < 1 ? 1 : 0], phi->InputAt(0));
769 CHECK_EQ(R.leaf[i < 2 ? 2 : 1], phi->InputAt(1));
770 CHECK_EQ(merge, phi->InputAt(2));
771 }
772 }
773
774
775 TEST(CMergeReduce_exhaustive_4) {
776 ControlReducerTester R;
777 Node* control[] = {
778 R.graph.NewNode(R.common.Start(1)), R.graph.NewNode(R.common.Start(2)),
779 R.graph.NewNode(R.common.Start(3)), R.graph.NewNode(R.common.Start(4))};
780 Node* values[] = {R.jsgraph.Int32Constant(11), R.jsgraph.Int32Constant(22),
781 R.jsgraph.Int32Constant(33), R.jsgraph.Int32Constant(44)};
782 Node* effects[] = {
783 R.graph.NewNode(R.common.Start(5)), R.graph.NewNode(R.common.Start(6)),
784 R.graph.NewNode(R.common.Start(7)), R.graph.NewNode(R.common.Start(8))};
785
786 for (int p = 0; p < 16; p++) {
787 int a = p & 1, b = p & 2, c = p & 4, d = p & 8;
788 Node* merge = R.graph.NewNode(R.common.Merge(4), control[0], control[1],
789 control[2], control[3]);
790
791 if (!a) merge->ReplaceInput(0, R.dead);
792 if (!b) merge->ReplaceInput(1, R.dead);
793 if (!c) merge->ReplaceInput(2, R.dead);
794 if (!d) merge->ReplaceInput(3, R.dead);
795 Node* phi = R.graph.NewNode(R.common.Phi(kMachAnyTagged, 4), values[0],
796 values[1], values[2], values[3], merge);
797 Node* effect = R.graph.NewNode(R.common.EffectPhi(4), effects[0],
798 effects[1], effects[2], effects[3], merge);
799
800 int count = v8::base::bits::CountPopulation32(p);
801 if (count == 0) {
802 // result should be dead.
803 Node* r =
804 ControlReducer::ReduceMergeForTesting(&R.jsgraph, &R.common, merge);
805 CHECK_EQ(IrOpcode::kDead, r->opcode());
806 } else if (count == 1) {
807 // result should be one of the controls.
808 Node* expect = control[WhichPowerOf2(p)];
809 R.ReduceMerge(expect, merge);
810 } else {
811 // merge should be edited.
812 R.ReduceMerge(merge, merge);
813 CHECK_EQ(count, merge->InputCount());
814 CHECK_EQ(count, OperatorProperties::GetControlInputCount(merge->op()));
815
816 CHECK_EQ(IrOpcode::kPhi, phi->opcode());
817 CHECK_EQ(count, phi->op()->InputCount());
818 CHECK_EQ(count + 1, phi->InputCount());
819
820 CHECK_EQ(IrOpcode::kEffectPhi, effect->opcode());
821 CHECK_EQ(0, effect->op()->InputCount());
822 CHECK_EQ(count, OperatorProperties::GetEffectInputCount(effect->op()));
823 CHECK_EQ(count + 1, effect->InputCount());
824 }
825 }
826 }
827
828
829 TEST(CMergeReduce_edit_many_phis1) {
830 ControlReducerTester R;
831
832 const int kPhiCount = 10;
833 Node* phis[kPhiCount];
834
835 for (int i = 0; i < 3; i++) {
836 Node* merge = R.graph.NewNode(R.common.Merge(3), R.start, R.start, R.start);
837 merge->ReplaceInput(i, R.dead);
838 for (int j = 0; j < kPhiCount; j++) {
839 phis[j] = R.graph.NewNode(R.common.Phi(kMachAnyTagged, 3), R.leaf[0],
840 R.leaf[1], R.leaf[2], merge);
841 }
842 R.ReduceMerge(merge, merge);
843 for (int j = 0; j < kPhiCount; j++) {
844 Node* phi = phis[j];
845 CHECK_EQ(IrOpcode::kPhi, phi->opcode());
846 CHECK_EQ(2, phi->op()->InputCount());
847 CHECK_EQ(3, phi->InputCount());
848 CHECK_EQ(R.leaf[i < 1 ? 1 : 0], phi->InputAt(0));
849 CHECK_EQ(R.leaf[i < 2 ? 2 : 1], phi->InputAt(1));
850 CHECK_EQ(merge, phi->InputAt(2));
851 }
852 }
853 }
854
855
856 TEST(CMergeReduce_simple_chain1) {
857 ControlReducerTester R;
858 for (int i = 0; i < 5; i++) {
859 Node* merge = R.graph.NewNode(R.common.Merge(1), R.start);
860 for (int j = 0; j < i; j++) {
861 merge = R.graph.NewNode(R.common.Merge(1), merge);
862 }
863 R.ReduceMergeIterative(R.start, merge);
864 }
865 }
866
867
868 TEST(CMergeReduce_dead_chain1) {
869 ControlReducerTester R;
870 for (int i = 0; i < 5; i++) {
871 Node* merge = R.graph.NewNode(R.common.Merge(1), R.dead);
872 for (int j = 0; j < i; j++) {
873 merge = R.graph.NewNode(R.common.Merge(1), merge);
874 }
875 // TODO(titzer): the NULL is because end gets killed. Check for dead
876 // properly.
877 R.ReduceMergeIterative(NULL, merge);
878 }
879 }
880
881
882 TEST(CMergeReduce_dead_chain2) {
883 ControlReducerTester R;
884 for (int i = 0; i < 5; i++) {
885 Node* merge = R.graph.NewNode(R.common.Merge(1), R.start);
886 for (int j = 0; j < i; j++) {
887 merge = R.graph.NewNode(R.common.Merge(2), merge, R.dead);
888 }
889 R.ReduceMergeIterative(R.start, merge);
890 }
891 }
892
893
894 struct Diamond {
895 Node* branch;
896 Node* if_true;
897 Node* if_false;
898 Node* merge;
899 Node* phi;
900
901 Diamond(ControlReducerTester& R, Node* cond) {
902 branch = R.graph.NewNode(R.common.Branch(), cond, R.start);
903 if_true = R.graph.NewNode(R.common.IfTrue(), branch);
904 if_false = R.graph.NewNode(R.common.IfFalse(), branch);
905 merge = R.graph.NewNode(R.common.Merge(2), if_true, if_false);
906 phi = NULL;
907 }
908
909 Diamond(ControlReducerTester& R, Node* cond, Node* tv, Node* fv) {
910 branch = R.graph.NewNode(R.common.Branch(), cond, R.start);
911 if_true = R.graph.NewNode(R.common.IfTrue(), branch);
912 if_false = R.graph.NewNode(R.common.IfFalse(), branch);
913 merge = R.graph.NewNode(R.common.Merge(2), if_true, if_false);
914 phi = R.graph.NewNode(R.common.Phi(kMachAnyTagged, 2), tv, fv, merge);
915 }
916
917 void chain(Diamond& that) { branch->ReplaceInput(1, that.merge); }
918
919 void nest(Diamond& that, bool if_true) {
920 if (if_true) {
921 branch->ReplaceInput(1, that.if_true);
922 that.merge->ReplaceInput(0, merge);
923 } else {
924 branch->ReplaceInput(1, that.if_false);
925 that.merge->ReplaceInput(1, merge);
926 }
927 }
928 };
929
930
931 struct While {
932 Node* branch;
933 Node* if_true;
934 Node* exit;
935 Node* loop;
936
937 While(ControlReducerTester& R, Node* cond) {
938 loop = R.graph.NewNode(R.common.Loop(2), R.start, R.start);
939 branch = R.graph.NewNode(R.common.Branch(), cond, loop);
940 if_true = R.graph.NewNode(R.common.IfTrue(), branch);
941 exit = R.graph.NewNode(R.common.IfFalse(), branch);
942 loop->ReplaceInput(1, if_true);
943 }
944
945 void chain(Node* control) { loop->ReplaceInput(0, control); }
946 };
947
948
949 TEST(CBranchReduce_none1) {
950 ControlReducerTester R;
951 Diamond d(R, R.p0);
952 R.ReduceBranch(d.branch, d.branch);
953 }
954
955
956 TEST(CBranchReduce_none2) {
957 ControlReducerTester R;
958 Diamond d1(R, R.p0);
959 Diamond d2(R, R.p0);
960 d2.chain(d1);
961 R.ReduceBranch(d2.branch, d2.branch);
962 }
963
964
965 TEST(CBranchReduce_true) {
966 ControlReducerTester R;
967 Node* true_values[] = {
968 R.one, R.jsgraph.Int32Constant(2),
969 R.jsgraph.Int32Constant(0x7fffffff), R.jsgraph.Constant(1.0),
970 R.jsgraph.Constant(22.1), R.jsgraph.TrueConstant()};
971
972 for (size_t i = 0; i < arraysize(true_values); i++) {
973 Diamond d(R, true_values[i]);
974 Node* true_use = R.graph.NewNode(R.common.Merge(1), d.if_true);
975 Node* false_use = R.graph.NewNode(R.common.Merge(1), d.if_false);
976 R.ReduceBranch(R.start, d.branch);
977 CHECK_EQ(R.start, true_use->InputAt(0));
978 CHECK_EQ(IrOpcode::kDead, false_use->InputAt(0)->opcode());
979 CHECK(d.if_true->IsDead()); // replaced
980 CHECK(d.if_false->IsDead()); // replaced
981 }
982 }
983
984
985 TEST(CBranchReduce_false) {
986 ControlReducerTester R;
987 Node* false_values[] = {R.zero, R.jsgraph.Constant(0.0),
988 R.jsgraph.Constant(-0.0), R.jsgraph.FalseConstant()};
989
990 for (size_t i = 0; i < arraysize(false_values); i++) {
991 Diamond d(R, false_values[i]);
992 Node* true_use = R.graph.NewNode(R.common.Merge(1), d.if_true);
993 Node* false_use = R.graph.NewNode(R.common.Merge(1), d.if_false);
994 R.ReduceBranch(R.start, d.branch);
995 CHECK_EQ(R.start, false_use->InputAt(0));
996 CHECK_EQ(IrOpcode::kDead, true_use->InputAt(0)->opcode());
997 CHECK(d.if_true->IsDead()); // replaced
998 CHECK(d.if_false->IsDead()); // replaced
999 }
1000 }
1001
1002
1003 TEST(CDiamondReduce_true) {
1004 ControlReducerTester R;
1005 Diamond d1(R, R.one);
1006 R.ReduceMergeIterative(R.start, d1.merge);
1007 }
1008
1009
1010 TEST(CDiamondReduce_false) {
1011 ControlReducerTester R;
1012 Diamond d2(R, R.zero);
1013 R.ReduceMergeIterative(R.start, d2.merge);
1014 }
1015
1016
1017 TEST(CChainedDiamondsReduce_true_false) {
1018 ControlReducerTester R;
1019 Diamond d1(R, R.one);
1020 Diamond d2(R, R.zero);
1021 d2.chain(d1);
1022
1023 R.ReduceMergeIterative(R.start, d2.merge);
1024 }
1025
1026
1027 TEST(CChainedDiamondsReduce_x_false) {
1028 ControlReducerTester R;
1029 Diamond d1(R, R.p0);
1030 Diamond d2(R, R.zero);
1031 d2.chain(d1);
1032
1033 R.ReduceMergeIterative(d1.merge, d2.merge);
1034 }
1035
1036
1037 TEST(CChainedDiamondsReduce_false_x) {
1038 ControlReducerTester R;
1039 Diamond d1(R, R.zero);
1040 Diamond d2(R, R.p0);
1041 d2.chain(d1);
1042
1043 R.ReduceMergeIterative(d2.merge, d2.merge);
1044 CHECK_EQ(R.start, d2.branch->InputAt(1));
1045 }
1046
1047
1048 TEST(CChainedDiamondsReduce_phi1) {
1049 ControlReducerTester R;
1050 Diamond d1(R, R.zero, R.one, R.zero); // foldable branch, phi.
1051 Diamond d2(R, d1.phi);
1052 d2.chain(d1);
1053
1054 R.ReduceMergeIterative(R.start, d2.merge);
1055 }
1056
1057
1058 TEST(CChainedDiamondsReduce_phi2) {
1059 ControlReducerTester R;
1060 Diamond d1(R, R.p0, R.one, R.one); // redundant phi.
1061 Diamond d2(R, d1.phi);
1062 d2.chain(d1);
1063
1064 R.ReduceMergeIterative(d1.merge, d2.merge);
1065 }
1066
1067
1068 TEST(CNestedDiamondsReduce_true_true_false) {
1069 ControlReducerTester R;
1070 Diamond d1(R, R.one);
1071 Diamond d2(R, R.zero);
1072 d2.nest(d1, true);
1073
1074 R.ReduceMergeIterative(R.start, d1.merge);
1075 }
1076
1077
1078 TEST(CNestedDiamondsReduce_false_true_false) {
1079 ControlReducerTester R;
1080 Diamond d1(R, R.one);
1081 Diamond d2(R, R.zero);
1082 d2.nest(d1, false);
1083
1084 R.ReduceMergeIterative(R.start, d1.merge);
1085 }
1086
1087
1088 TEST(CNestedDiamonds_xyz) {
1089 ControlReducerTester R;
1090
1091 for (int a = 0; a < 2; a++) {
1092 for (int b = 0; b < 2; b++) {
1093 for (int c = 0; c < 2; c++) {
1094 Diamond d1(R, R.jsgraph.Int32Constant(a));
1095 Diamond d2(R, R.jsgraph.Int32Constant(b));
1096 d2.nest(d1, c);
1097
1098 R.ReduceMergeIterative(R.start, d1.merge);
1099 }
1100 }
1101 }
1102 }
1103
1104
1105 TEST(CDeadLoop1) {
1106 ControlReducerTester R;
1107
1108 Node* loop = R.graph.NewNode(R.common.Loop(1), R.start);
1109 Node* branch = R.graph.NewNode(R.common.Branch(), R.p0, loop);
1110 Node* if_true = R.graph.NewNode(R.common.IfTrue(), branch);
1111 Node* if_false = R.graph.NewNode(R.common.IfFalse(), branch);
1112 loop->ReplaceInput(0, if_true); // loop is not connected to start (i.e. dead)
1113 Node* merge = R.graph.NewNode(R.common.Merge(2), R.start, if_false);
1114 R.ReduceMergeIterative(R.start, merge);
1115 CHECK_EQ(NULL, if_true->InputAt(0));
1116 CHECK_EQ(NULL, if_false->InputAt(0));
1117 }
1118
1119
1120 TEST(CDeadLoop2) {
1121 ControlReducerTester R;
1122
1123 While w(R, R.p0);
1124 Diamond d(R, R.zero);
1125 // if (0) { while (p0) ; } else { }
1126 w.branch->ReplaceInput(1, d.if_true);
1127 d.merge->ReplaceInput(0, w.exit);
1128
1129 R.ReduceMergeIterative(R.start, d.merge);
1130 CHECK_EQ(NULL, d.if_true->InputAt(0));
1131 CHECK_EQ(NULL, d.if_false->InputAt(0));
1132 }
1133
1134
1135 TEST(CNonTermLoop1) {
1136 ControlReducerTester R;
1137 Node* loop =
1138 R.SetSelfReferences(R.graph.NewNode(R.common.Loop(1), R.start, R.self));
1139 ControlReducer::ReduceGraph(R.graph.zone(), &R.jsgraph, &R.common);
1140 Node* end = R.graph.end();
1141 CHECK_EQ(R.start, loop->InputAt(0));
1142 CHECK_EQ(loop, loop->InputAt(1));
1143 Node* merge = end->InputAt(0);
1144 CHECK_EQ(IrOpcode::kMerge, merge->opcode());
1145 CHECK_EQ(2, merge->InputCount());
1146 CHECK_EQ(2, OperatorProperties::GetControlInputCount(merge->op()));
1147 CHECK_EQ(R.start, merge->InputAt(0));
1148 CHECK_EQ(loop, merge->InputAt(1));
1149 }
1150
1151
1152 TEST(CNonTermLoop2) {}
OLDNEW
« src/compiler/control-reducer.cc ('K') | « src/compiler/control-reducer.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698