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

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
« no previous file with comments | « src/compiler/scheduler.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 // TODO(titzer): convert this whole file into unit tests.
21
22 static int CheckInputs(Node* node, Node* i0 = NULL, Node* i1 = NULL,
23 Node* i2 = NULL) {
24 int count = 3;
25 if (i2 == NULL) count = 2;
26 if (i1 == NULL) count = 1;
27 if (i0 == NULL) count = 0;
28 CHECK_EQ(count, node->InputCount());
29 if (i0 != NULL) CHECK_EQ(i0, node->InputAt(0));
30 if (i1 != NULL) CHECK_EQ(i1, node->InputAt(1));
31 if (i2 != NULL) CHECK_EQ(i2, node->InputAt(2));
32 return count;
33 }
34
35
36 static int CheckMerge(Node* node, Node* i0 = NULL, Node* i1 = NULL,
37 Node* i2 = NULL) {
38 CHECK_EQ(IrOpcode::kMerge, node->opcode());
39 int count = CheckInputs(node, i0, i1, i2);
40 CHECK_EQ(count, OperatorProperties::GetControlInputCount(node->op()));
41 return count;
42 }
43
44
45 static int CheckLoop(Node* node, Node* i0 = NULL, Node* i1 = NULL,
46 Node* i2 = NULL) {
47 CHECK_EQ(IrOpcode::kLoop, node->opcode());
48 int count = CheckInputs(node, i0, i1, i2);
49 CHECK_EQ(count, OperatorProperties::GetControlInputCount(node->op()));
50 return count;
51 }
52
53
54 bool IsUsedBy(Node* a, Node* b) {
55 for (UseIter i = a->uses().begin(); i != a->uses().end(); ++i) {
56 if (b == *i) return true;
57 }
58 return false;
59 }
60
61
62 // A helper for all tests dealing with ControlTester.
63 class ControlReducerTester : HandleAndZoneScope {
17 public: 64 public:
18 CTrimTester() 65 ControlReducerTester()
19 : isolate(main_isolate()), 66 : isolate(main_isolate()),
20 common(main_zone()), 67 common(main_zone()),
21 graph(main_zone()), 68 graph(main_zone()),
22 jsgraph(&graph, &common, NULL, NULL), 69 jsgraph(&graph, &common, NULL, NULL),
23 start(graph.NewNode(common.Start(1))), 70 start(graph.NewNode(common.Start(1))),
71 end(graph.NewNode(common.End(), start)),
24 p0(graph.NewNode(common.Parameter(0), start)), 72 p0(graph.NewNode(common.Parameter(0), start)),
73 zero(jsgraph.Int32Constant(0)),
25 one(jsgraph.OneConstant()), 74 one(jsgraph.OneConstant()),
26 half(jsgraph.Constant(0.5)) { 75 half(jsgraph.Constant(0.5)),
27 graph.SetEnd(start); 76 self(graph.NewNode(common.Int32Constant(0xaabbccdd))),
77 dead(graph.NewNode(common.Dead())) {
78 graph.SetEnd(end);
28 graph.SetStart(start); 79 graph.SetStart(start);
80 leaf[0] = zero;
81 leaf[1] = one;
82 leaf[2] = half;
83 leaf[3] = p0;
29 } 84 }
30 85
31 Isolate* isolate; 86 Isolate* isolate;
32 CommonOperatorBuilder common; 87 CommonOperatorBuilder common;
33 Graph graph; 88 Graph graph;
34 JSGraph jsgraph; 89 JSGraph jsgraph;
35 Node* start; 90 Node* start;
91 Node* end;
36 Node* p0; 92 Node* p0;
93 Node* zero;
37 Node* one; 94 Node* one;
38 Node* half; 95 Node* half;
96 Node* self;
97 Node* dead;
98 Node* leaf[kNumLeafs];
99
100 Node* Phi(Node* a) {
101 return SetSelfReferences(graph.NewNode(op(1, false), a, start));
102 }
103
104 Node* Phi(Node* a, Node* b) {
105 return SetSelfReferences(graph.NewNode(op(2, false), a, b, start));
106 }
107
108 Node* Phi(Node* a, Node* b, Node* c) {
109 return SetSelfReferences(graph.NewNode(op(3, false), a, b, c, start));
110 }
111
112 Node* Phi(Node* a, Node* b, Node* c, Node* d) {
113 return SetSelfReferences(graph.NewNode(op(4, false), a, b, c, d, start));
114 }
115
116 Node* EffectPhi(Node* a) {
117 return SetSelfReferences(graph.NewNode(op(1, true), a, start));
118 }
119
120 Node* EffectPhi(Node* a, Node* b) {
121 return SetSelfReferences(graph.NewNode(op(2, true), a, b, start));
122 }
123
124 Node* EffectPhi(Node* a, Node* b, Node* c) {
125 return SetSelfReferences(graph.NewNode(op(3, true), a, b, c, start));
126 }
127
128 Node* EffectPhi(Node* a, Node* b, Node* c, Node* d) {
129 return SetSelfReferences(graph.NewNode(op(4, true), a, b, c, d, start));
130 }
131
132 Node* SetSelfReferences(Node* node) {
133 Node::Inputs inputs = node->inputs();
134 for (Node::Inputs::iterator iter(inputs.begin()); iter != inputs.end();
135 ++iter) {
136 Node* input = *iter;
137 if (input == self) node->ReplaceInput(iter.index(), node);
138 }
139 return node;
140 }
141
142 const Operator* op(int count, bool effect) {
143 return effect ? common.EffectPhi(count) : common.Phi(kMachAnyTagged, count);
144 }
39 145
40 void Trim() { ControlReducer::TrimGraph(main_zone(), &jsgraph); } 146 void Trim() { ControlReducer::TrimGraph(main_zone(), &jsgraph); }
147
148 void ReduceGraph() {
149 ControlReducer::ReduceGraph(main_zone(), &jsgraph, &common);
150 }
151
152 // Checks one-step reduction of a phi.
153 void ReducePhi(Node* expect, Node* phi) {
154 Node* result = ControlReducer::ReducePhiForTesting(&jsgraph, &common, phi);
155 CHECK_EQ(expect, result);
156 ReducePhiIterative(expect, phi); // iterative should give the same result.
157 }
158
159 void ReducePhiIterative(Node* expect, Node* phi) {
160 p0->ReplaceInput(0, start); // hack: parameters may be trimmed.
161 Node* ret = graph.NewNode(common.Return(), phi, start, start);
162 Node* end = graph.NewNode(common.End(), ret);
163 graph.SetEnd(end);
164 ControlReducer::ReduceGraph(main_zone(), &jsgraph, &common);
165 CheckInputs(end, ret);
166 CheckInputs(ret, expect, start, start);
167 }
168
169 void ReduceMerge(Node* expect, Node* merge) {
170 Node* result =
171 ControlReducer::ReduceMergeForTesting(&jsgraph, &common, merge);
172 CHECK_EQ(expect, result);
173 }
174
175 void ReduceMergeIterative(Node* expect, Node* merge) {
176 p0->ReplaceInput(0, start); // hack: parameters may be trimmed.
177 Node* end = graph.NewNode(common.End(), merge);
178 graph.SetEnd(end);
179 ReduceGraph();
180 CheckInputs(end, expect);
181 }
182
183 void ReduceBranch(Node* expect, Node* branch) {
184 Node* result =
185 ControlReducer::ReduceBranchForTesting(&jsgraph, &common, branch);
186 CHECK_EQ(expect, result);
187 }
188
189 Node* Return(Node* val, Node* effect, Node* control) {
190 Node* ret = graph.NewNode(common.Return(), val, effect, control);
191 end->ReplaceInput(0, ret);
192 return ret;
193 }
41 }; 194 };
42 195
43 196
44 bool IsUsedBy(Node* a, Node* b) {
45 for (UseIter i = a->uses().begin(); i != a->uses().end(); ++i) {
46 if (b == *i) return true;
47 }
48 return false;
49 }
50
51
52 TEST(Trim1_live) { 197 TEST(Trim1_live) {
53 CTrimTester T; 198 ControlReducerTester T;
54 CHECK(IsUsedBy(T.start, T.p0)); 199 CHECK(IsUsedBy(T.start, T.p0));
55 T.graph.SetEnd(T.p0); 200 T.graph.SetEnd(T.p0);
56 T.Trim(); 201 T.Trim();
57 CHECK(IsUsedBy(T.start, T.p0)); 202 CHECK(IsUsedBy(T.start, T.p0));
58 CHECK_EQ(T.start, T.p0->InputAt(0)); 203 CheckInputs(T.p0, T.start);
59 } 204 }
60 205
61 206
62 TEST(Trim1_dead) { 207 TEST(Trim1_dead) {
63 CTrimTester T; 208 ControlReducerTester T;
64 CHECK(IsUsedBy(T.start, T.p0)); 209 CHECK(IsUsedBy(T.start, T.p0));
65 T.Trim(); 210 T.Trim();
66 CHECK(!IsUsedBy(T.start, T.p0)); 211 CHECK(!IsUsedBy(T.start, T.p0));
67 CHECK_EQ(NULL, T.p0->InputAt(0)); 212 CHECK_EQ(NULL, T.p0->InputAt(0));
68 } 213 }
69 214
70 215
71 TEST(Trim2_live) { 216 TEST(Trim2_live) {
72 CTrimTester T; 217 ControlReducerTester T;
73 Node* phi = 218 Node* phi =
74 T.graph.NewNode(T.common.Phi(kMachAnyTagged, 2), T.one, T.half, T.start); 219 T.graph.NewNode(T.common.Phi(kMachAnyTagged, 2), T.one, T.half, T.start);
75 CHECK(IsUsedBy(T.one, phi)); 220 CHECK(IsUsedBy(T.one, phi));
76 CHECK(IsUsedBy(T.half, phi)); 221 CHECK(IsUsedBy(T.half, phi));
77 CHECK(IsUsedBy(T.start, phi)); 222 CHECK(IsUsedBy(T.start, phi));
78 T.graph.SetEnd(phi); 223 T.graph.SetEnd(phi);
79 T.Trim(); 224 T.Trim();
80 CHECK(IsUsedBy(T.one, phi)); 225 CHECK(IsUsedBy(T.one, phi));
81 CHECK(IsUsedBy(T.half, phi)); 226 CHECK(IsUsedBy(T.half, phi));
82 CHECK(IsUsedBy(T.start, phi)); 227 CHECK(IsUsedBy(T.start, phi));
83 CHECK_EQ(T.one, phi->InputAt(0)); 228 CheckInputs(phi, T.one, T.half, T.start);
84 CHECK_EQ(T.half, phi->InputAt(1));
85 CHECK_EQ(T.start, phi->InputAt(2));
86 } 229 }
87 230
88 231
89 TEST(Trim2_dead) { 232 TEST(Trim2_dead) {
90 CTrimTester T; 233 ControlReducerTester T;
91 Node* phi = 234 Node* phi =
92 T.graph.NewNode(T.common.Phi(kMachAnyTagged, 2), T.one, T.half, T.start); 235 T.graph.NewNode(T.common.Phi(kMachAnyTagged, 2), T.one, T.half, T.start);
93 CHECK(IsUsedBy(T.one, phi)); 236 CHECK(IsUsedBy(T.one, phi));
94 CHECK(IsUsedBy(T.half, phi)); 237 CHECK(IsUsedBy(T.half, phi));
95 CHECK(IsUsedBy(T.start, phi)); 238 CHECK(IsUsedBy(T.start, phi));
96 T.Trim(); 239 T.Trim();
97 CHECK(!IsUsedBy(T.one, phi)); 240 CHECK(!IsUsedBy(T.one, phi));
98 CHECK(!IsUsedBy(T.half, phi)); 241 CHECK(!IsUsedBy(T.half, phi));
99 CHECK(!IsUsedBy(T.start, phi)); 242 CHECK(!IsUsedBy(T.start, phi));
100 CHECK_EQ(NULL, phi->InputAt(0)); 243 CHECK_EQ(NULL, phi->InputAt(0));
101 CHECK_EQ(NULL, phi->InputAt(1)); 244 CHECK_EQ(NULL, phi->InputAt(1));
102 CHECK_EQ(NULL, phi->InputAt(2)); 245 CHECK_EQ(NULL, phi->InputAt(2));
103 } 246 }
104 247
105 248
106 TEST(Trim_chain1) { 249 TEST(Trim_chain1) {
107 CTrimTester T; 250 ControlReducerTester T;
108 const int kDepth = 15; 251 const int kDepth = 15;
109 Node* live[kDepth]; 252 Node* live[kDepth];
110 Node* dead[kDepth]; 253 Node* dead[kDepth];
111 Node* end = T.start; 254 Node* end = T.start;
112 for (int i = 0; i < kDepth; i++) { 255 for (int i = 0; i < kDepth; i++) {
113 live[i] = end = T.graph.NewNode(T.common.Merge(1), end); 256 live[i] = end = T.graph.NewNode(T.common.Merge(1), end);
114 dead[i] = T.graph.NewNode(T.common.Merge(1), end); 257 dead[i] = T.graph.NewNode(T.common.Merge(1), end);
115 } 258 }
116 // end -> live[last] -> live[last-1] -> ... -> start 259 // end -> live[last] -> live[last-1] -> ... -> start
117 // dead[last] ^ dead[last-1] ^ ... ^ 260 // dead[last] ^ dead[last-1] ^ ... ^
118 T.graph.SetEnd(end); 261 T.graph.SetEnd(end);
119 T.Trim(); 262 T.Trim();
120 for (int i = 0; i < kDepth; i++) { 263 for (int i = 0; i < kDepth; i++) {
121 CHECK(!IsUsedBy(live[i], dead[i])); 264 CHECK(!IsUsedBy(live[i], dead[i]));
122 CHECK_EQ(NULL, dead[i]->InputAt(0)); 265 CHECK_EQ(NULL, dead[i]->InputAt(0));
123 CHECK_EQ(i == 0 ? T.start : live[i - 1], live[i]->InputAt(0)); 266 CHECK_EQ(i == 0 ? T.start : live[i - 1], live[i]->InputAt(0));
124 } 267 }
125 } 268 }
126 269
127 270
128 TEST(Trim_chain2) { 271 TEST(Trim_chain2) {
129 CTrimTester T; 272 ControlReducerTester T;
130 const int kDepth = 15; 273 const int kDepth = 15;
131 Node* live[kDepth]; 274 Node* live[kDepth];
132 Node* dead[kDepth]; 275 Node* dead[kDepth];
133 Node* l = T.start; 276 Node* l = T.start;
134 Node* d = T.start; 277 Node* d = T.start;
135 for (int i = 0; i < kDepth; i++) { 278 for (int i = 0; i < kDepth; i++) {
136 live[i] = l = T.graph.NewNode(T.common.Merge(1), l); 279 live[i] = l = T.graph.NewNode(T.common.Merge(1), l);
137 dead[i] = d = T.graph.NewNode(T.common.Merge(1), d); 280 dead[i] = d = T.graph.NewNode(T.common.Merge(1), d);
138 } 281 }
139 // end -> live[last] -> live[last-1] -> ... -> start 282 // end -> live[last] -> live[last-1] -> ... -> start
140 // dead[last] -> dead[last-1] -> ... -> start 283 // dead[last] -> dead[last-1] -> ... -> start
141 T.graph.SetEnd(l); 284 T.graph.SetEnd(l);
142 T.Trim(); 285 T.Trim();
143 CHECK(!IsUsedBy(T.start, dead[0])); 286 CHECK(!IsUsedBy(T.start, dead[0]));
144 for (int i = 0; i < kDepth; i++) { 287 for (int i = 0; i < kDepth; i++) {
145 CHECK_EQ(i == 0 ? NULL : dead[i - 1], dead[i]->InputAt(0)); 288 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)); 289 CHECK_EQ(i == 0 ? T.start : live[i - 1], live[i]->InputAt(0));
147 } 290 }
148 } 291 }
149 292
150 293
151 TEST(Trim_cycle1) { 294 TEST(Trim_cycle1) {
152 CTrimTester T; 295 ControlReducerTester T;
153 Node* loop = T.graph.NewNode(T.common.Loop(1), T.start, T.start); 296 Node* loop = T.graph.NewNode(T.common.Loop(1), T.start, T.start);
154 loop->ReplaceInput(1, loop); 297 loop->ReplaceInput(1, loop);
155 Node* end = T.graph.NewNode(T.common.End(), loop); 298 Node* end = T.graph.NewNode(T.common.End(), loop);
156 T.graph.SetEnd(end); 299 T.graph.SetEnd(end);
157 300
158 CHECK(IsUsedBy(T.start, loop)); 301 CHECK(IsUsedBy(T.start, loop));
159 CHECK(IsUsedBy(loop, end)); 302 CHECK(IsUsedBy(loop, end));
160 CHECK(IsUsedBy(loop, loop)); 303 CHECK(IsUsedBy(loop, loop));
161 304
162 T.Trim(); 305 T.Trim();
163 306
164 // nothing should have happened to the loop itself. 307 // nothing should have happened to the loop itself.
165 CHECK(IsUsedBy(T.start, loop)); 308 CHECK(IsUsedBy(T.start, loop));
166 CHECK(IsUsedBy(loop, end)); 309 CHECK(IsUsedBy(loop, end));
167 CHECK(IsUsedBy(loop, loop)); 310 CHECK(IsUsedBy(loop, loop));
168 CHECK_EQ(T.start, loop->InputAt(0)); 311 CheckInputs(loop, T.start, loop);
169 CHECK_EQ(loop, loop->InputAt(1)); 312 CheckInputs(end, loop);
170 CHECK_EQ(loop, end->InputAt(0));
171 } 313 }
172 314
173 315
174 TEST(Trim_cycle2) { 316 TEST(Trim_cycle2) {
175 CTrimTester T; 317 ControlReducerTester T;
176 Node* loop = T.graph.NewNode(T.common.Loop(2), T.start, T.start); 318 Node* loop = T.graph.NewNode(T.common.Loop(2), T.start, T.start);
177 loop->ReplaceInput(1, loop); 319 loop->ReplaceInput(1, loop);
178 Node* end = T.graph.NewNode(T.common.End(), loop); 320 Node* end = T.graph.NewNode(T.common.End(), loop);
179 Node* phi = 321 Node* phi =
180 T.graph.NewNode(T.common.Phi(kMachAnyTagged, 2), T.one, T.half, loop); 322 T.graph.NewNode(T.common.Phi(kMachAnyTagged, 2), T.one, T.half, loop);
181 T.graph.SetEnd(end); 323 T.graph.SetEnd(end);
182 324
183 CHECK(IsUsedBy(T.start, loop)); 325 CHECK(IsUsedBy(T.start, loop));
184 CHECK(IsUsedBy(loop, end)); 326 CHECK(IsUsedBy(loop, end));
185 CHECK(IsUsedBy(loop, loop)); 327 CHECK(IsUsedBy(loop, loop));
186 CHECK(IsUsedBy(loop, phi)); 328 CHECK(IsUsedBy(loop, phi));
187 CHECK(IsUsedBy(T.one, phi)); 329 CHECK(IsUsedBy(T.one, phi));
188 CHECK(IsUsedBy(T.half, phi)); 330 CHECK(IsUsedBy(T.half, phi));
189 331
190 T.Trim(); 332 T.Trim();
191 333
192 // nothing should have happened to the loop itself. 334 // nothing should have happened to the loop itself.
193 CHECK(IsUsedBy(T.start, loop)); 335 CHECK(IsUsedBy(T.start, loop));
194 CHECK(IsUsedBy(loop, end)); 336 CHECK(IsUsedBy(loop, end));
195 CHECK(IsUsedBy(loop, loop)); 337 CHECK(IsUsedBy(loop, loop));
196 CHECK_EQ(T.start, loop->InputAt(0)); 338 CheckInputs(loop, T.start, loop);
197 CHECK_EQ(loop, loop->InputAt(1)); 339 CheckInputs(end, loop);
198 CHECK_EQ(loop, end->InputAt(0));
199 340
200 // phi should have been trimmed away. 341 // phi should have been trimmed away.
201 CHECK(!IsUsedBy(loop, phi)); 342 CHECK(!IsUsedBy(loop, phi));
202 CHECK(!IsUsedBy(T.one, phi)); 343 CHECK(!IsUsedBy(T.one, phi));
203 CHECK(!IsUsedBy(T.half, phi)); 344 CHECK(!IsUsedBy(T.half, phi));
204 CHECK_EQ(NULL, phi->InputAt(0)); 345 CHECK_EQ(NULL, phi->InputAt(0));
205 CHECK_EQ(NULL, phi->InputAt(1)); 346 CHECK_EQ(NULL, phi->InputAt(1));
206 CHECK_EQ(NULL, phi->InputAt(2)); 347 CHECK_EQ(NULL, phi->InputAt(2));
207 } 348 }
208 349
209 350
210 void CheckTrimConstant(CTrimTester* T, Node* k) { 351 void CheckTrimConstant(ControlReducerTester* T, Node* k) {
211 Node* phi = T->graph.NewNode(T->common.Phi(kMachInt32, 1), k, T->start); 352 Node* phi = T->graph.NewNode(T->common.Phi(kMachInt32, 1), k, T->start);
212 CHECK(IsUsedBy(k, phi)); 353 CHECK(IsUsedBy(k, phi));
213 T->Trim(); 354 T->Trim();
214 CHECK(!IsUsedBy(k, phi)); 355 CHECK(!IsUsedBy(k, phi));
215 CHECK_EQ(NULL, phi->InputAt(0)); 356 CHECK_EQ(NULL, phi->InputAt(0));
216 CHECK_EQ(NULL, phi->InputAt(1)); 357 CHECK_EQ(NULL, phi->InputAt(1));
217 } 358 }
218 359
219 360
220 TEST(Trim_constants) { 361 TEST(Trim_constants) {
221 CTrimTester T; 362 ControlReducerTester T;
222 int32_t int32_constants[] = { 363 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, 364 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}; 365 0, -11, -12, 12, 12, 13, 13, 14, 14, 15, 15, 14, 15, 6, 6, 7, 8, 7, 8, 9};
225 366
226 for (size_t i = 0; i < arraysize(int32_constants); i++) { 367 for (size_t i = 0; i < arraysize(int32_constants); i++) {
227 CheckTrimConstant(&T, T.jsgraph.Int32Constant(int32_constants[i])); 368 CheckTrimConstant(&T, T.jsgraph.Int32Constant(int32_constants[i]));
228 CheckTrimConstant(&T, T.jsgraph.Float64Constant(int32_constants[i])); 369 CheckTrimConstant(&T, T.jsgraph.Float64Constant(int32_constants[i]));
229 CheckTrimConstant(&T, T.jsgraph.Constant(int32_constants[i])); 370 CheckTrimConstant(&T, T.jsgraph.Constant(int32_constants[i]));
230 } 371 }
231 372
232 Node* other_constants[] = { 373 Node* other_constants[] = {
233 T.jsgraph.UndefinedConstant(), T.jsgraph.TheHoleConstant(), 374 T.jsgraph.UndefinedConstant(), T.jsgraph.TheHoleConstant(),
234 T.jsgraph.TrueConstant(), T.jsgraph.FalseConstant(), 375 T.jsgraph.TrueConstant(), T.jsgraph.FalseConstant(),
235 T.jsgraph.NullConstant(), T.jsgraph.ZeroConstant(), 376 T.jsgraph.NullConstant(), T.jsgraph.ZeroConstant(),
236 T.jsgraph.OneConstant(), T.jsgraph.NaNConstant(), 377 T.jsgraph.OneConstant(), T.jsgraph.NaNConstant(),
237 T.jsgraph.Constant(21), T.jsgraph.Constant(22.2)}; 378 T.jsgraph.Constant(21), T.jsgraph.Constant(22.2)};
238 379
239 for (size_t i = 0; i < arraysize(other_constants); i++) { 380 for (size_t i = 0; i < arraysize(other_constants); i++) {
240 CheckTrimConstant(&T, other_constants[i]); 381 CheckTrimConstant(&T, other_constants[i]);
241 } 382 }
242 } 383 }
384
385
386 TEST(CReducePhi1) {
387 ControlReducerTester R;
388
389 R.ReducePhi(R.leaf[0], R.Phi(R.leaf[0]));
390 R.ReducePhi(R.leaf[1], R.Phi(R.leaf[1]));
391 R.ReducePhi(R.leaf[2], R.Phi(R.leaf[2]));
392 R.ReducePhi(R.leaf[3], R.Phi(R.leaf[3]));
393 }
394
395
396 TEST(CReducePhi1_dead) {
397 ControlReducerTester R;
398
399 R.ReducePhi(R.leaf[0], R.Phi(R.leaf[0], R.dead));
400 R.ReducePhi(R.leaf[1], R.Phi(R.leaf[1], R.dead));
401 R.ReducePhi(R.leaf[2], R.Phi(R.leaf[2], R.dead));
402 R.ReducePhi(R.leaf[3], R.Phi(R.leaf[3], R.dead));
403
404 R.ReducePhi(R.leaf[0], R.Phi(R.dead, R.leaf[0]));
405 R.ReducePhi(R.leaf[1], R.Phi(R.dead, R.leaf[1]));
406 R.ReducePhi(R.leaf[2], R.Phi(R.dead, R.leaf[2]));
407 R.ReducePhi(R.leaf[3], R.Phi(R.dead, R.leaf[3]));
408 }
409
410
411 TEST(CReducePhi1_dead2) {
412 ControlReducerTester R;
413
414 R.ReducePhi(R.leaf[0], R.Phi(R.leaf[0], R.dead, R.dead));
415 R.ReducePhi(R.leaf[0], R.Phi(R.dead, R.leaf[0], R.dead));
416 R.ReducePhi(R.leaf[0], R.Phi(R.dead, R.dead, R.leaf[0]));
417 }
418
419
420 TEST(CReducePhi2a) {
421 ControlReducerTester R;
422
423 for (size_t i = 0; i < kNumLeafs; i++) {
424 Node* a = R.leaf[i];
425 R.ReducePhi(a, R.Phi(a, a));
426 }
427 }
428
429
430 TEST(CReducePhi2b) {
431 ControlReducerTester R;
432
433 for (size_t i = 0; i < kNumLeafs; i++) {
434 Node* a = R.leaf[i];
435 R.ReducePhi(a, R.Phi(R.self, a));
436 R.ReducePhi(a, R.Phi(a, R.self));
437 }
438 }
439
440
441 TEST(CReducePhi2c) {
442 ControlReducerTester R;
443
444 for (size_t i = 1; i < kNumLeafs; i++) {
445 Node* a = R.leaf[i], *b = R.leaf[0];
446 Node* phi1 = R.Phi(b, a);
447 R.ReducePhi(phi1, phi1);
448
449 Node* phi2 = R.Phi(a, b);
450 R.ReducePhi(phi2, phi2);
451 }
452 }
453
454
455 TEST(CReducePhi2_dead) {
456 ControlReducerTester R;
457
458 for (size_t i = 0; i < kNumLeafs; i++) {
459 Node* a = R.leaf[i];
460 R.ReducePhi(a, R.Phi(a, a, R.dead));
461 R.ReducePhi(a, R.Phi(a, R.dead, a));
462 R.ReducePhi(a, R.Phi(R.dead, a, a));
463 }
464
465 for (size_t i = 0; i < kNumLeafs; i++) {
466 Node* a = R.leaf[i];
467 R.ReducePhi(a, R.Phi(R.self, a));
468 R.ReducePhi(a, R.Phi(a, R.self));
469 R.ReducePhi(a, R.Phi(R.self, a, R.dead));
470 R.ReducePhi(a, R.Phi(a, R.self, R.dead));
471 }
472
473 for (size_t i = 1; i < kNumLeafs; i++) {
474 Node* a = R.leaf[i], *b = R.leaf[0];
475 Node* phi1 = R.Phi(b, a, R.dead);
476 R.ReducePhi(phi1, phi1);
477
478 Node* phi2 = R.Phi(a, b, R.dead);
479 R.ReducePhi(phi2, phi2);
480 }
481 }
482
483
484 TEST(CReducePhi3) {
485 ControlReducerTester R;
486
487 for (size_t i = 0; i < kNumLeafs; i++) {
488 Node* a = R.leaf[i];
489 R.ReducePhi(a, R.Phi(a, a, a));
490 }
491
492 for (size_t i = 0; i < kNumLeafs; i++) {
493 Node* a = R.leaf[i];
494 R.ReducePhi(a, R.Phi(R.self, a, a));
495 R.ReducePhi(a, R.Phi(a, R.self, a));
496 R.ReducePhi(a, R.Phi(a, a, R.self));
497 }
498
499 for (size_t i = 1; i < kNumLeafs; i++) {
500 Node* a = R.leaf[i], *b = R.leaf[0];
501 Node* phi1 = R.Phi(b, a, a);
502 R.ReducePhi(phi1, phi1);
503
504 Node* phi2 = R.Phi(a, b, a);
505 R.ReducePhi(phi2, phi2);
506
507 Node* phi3 = R.Phi(a, a, b);
508 R.ReducePhi(phi3, phi3);
509 }
510 }
511
512
513 TEST(CReducePhi4) {
514 ControlReducerTester R;
515
516 for (size_t i = 0; i < kNumLeafs; i++) {
517 Node* a = R.leaf[i];
518 R.ReducePhi(a, R.Phi(a, a, a, a));
519 }
520
521 for (size_t i = 0; i < kNumLeafs; i++) {
522 Node* a = R.leaf[i];
523 R.ReducePhi(a, R.Phi(R.self, a, a, a));
524 R.ReducePhi(a, R.Phi(a, R.self, a, a));
525 R.ReducePhi(a, R.Phi(a, a, R.self, a));
526 R.ReducePhi(a, R.Phi(a, a, a, R.self));
527
528 R.ReducePhi(a, R.Phi(R.self, R.self, a, a));
529 R.ReducePhi(a, R.Phi(a, R.self, R.self, a));
530 R.ReducePhi(a, R.Phi(a, a, R.self, R.self));
531 R.ReducePhi(a, R.Phi(R.self, a, a, R.self));
532 }
533
534 for (size_t i = 1; i < kNumLeafs; i++) {
535 Node* a = R.leaf[i], *b = R.leaf[0];
536 Node* phi1 = R.Phi(b, a, a, a);
537 R.ReducePhi(phi1, phi1);
538
539 Node* phi2 = R.Phi(a, b, a, a);
540 R.ReducePhi(phi2, phi2);
541
542 Node* phi3 = R.Phi(a, a, b, a);
543 R.ReducePhi(phi3, phi3);
544
545 Node* phi4 = R.Phi(a, a, a, b);
546 R.ReducePhi(phi4, phi4);
547 }
548 }
549
550
551 TEST(CReducePhi_iterative1) {
552 ControlReducerTester R;
553
554 R.ReducePhiIterative(R.leaf[0], R.Phi(R.leaf[0], R.Phi(R.leaf[0])));
555 R.ReducePhiIterative(R.leaf[0], R.Phi(R.Phi(R.leaf[0]), R.leaf[0]));
556 }
557
558
559 TEST(CReducePhi_iterative2) {
560 ControlReducerTester R;
561
562 R.ReducePhiIterative(R.leaf[0], R.Phi(R.Phi(R.leaf[0]), R.Phi(R.leaf[0])));
563 }
564
565
566 TEST(CReducePhi_iterative3) {
567 ControlReducerTester R;
568
569 R.ReducePhiIterative(R.leaf[0],
570 R.Phi(R.leaf[0], R.Phi(R.leaf[0], R.leaf[0])));
571 R.ReducePhiIterative(R.leaf[0],
572 R.Phi(R.Phi(R.leaf[0], R.leaf[0]), R.leaf[0]));
573 }
574
575
576 TEST(CReducePhi_iterative4) {
577 ControlReducerTester R;
578
579 R.ReducePhiIterative(R.leaf[0], R.Phi(R.Phi(R.leaf[0], R.leaf[0]),
580 R.Phi(R.leaf[0], R.leaf[0])));
581
582 Node* p1 = R.Phi(R.leaf[0], R.leaf[0]);
583 R.ReducePhiIterative(R.leaf[0], R.Phi(p1, p1));
584
585 Node* p2 = R.Phi(R.leaf[0], R.leaf[0], R.leaf[0]);
586 R.ReducePhiIterative(R.leaf[0], R.Phi(p2, p2, p2));
587
588 Node* p3 = R.Phi(R.leaf[0], R.leaf[0], R.leaf[0]);
589 R.ReducePhiIterative(R.leaf[0], R.Phi(p3, p3, R.leaf[0]));
590 }
591
592
593 TEST(CReducePhi_iterative_self1) {
594 ControlReducerTester R;
595
596 R.ReducePhiIterative(R.leaf[0], R.Phi(R.leaf[0], R.Phi(R.leaf[0], R.self)));
597 R.ReducePhiIterative(R.leaf[0], R.Phi(R.Phi(R.leaf[0], R.self), R.leaf[0]));
598 }
599
600
601 TEST(CReducePhi_iterative_self2) {
602 ControlReducerTester R;
603
604 R.ReducePhiIterative(
605 R.leaf[0], R.Phi(R.Phi(R.leaf[0], R.self), R.Phi(R.leaf[0], R.self)));
606 R.ReducePhiIterative(
607 R.leaf[0], R.Phi(R.Phi(R.self, R.leaf[0]), R.Phi(R.self, R.leaf[0])));
608
609 Node* p1 = R.Phi(R.leaf[0], R.self);
610 R.ReducePhiIterative(R.leaf[0], R.Phi(p1, p1));
611
612 Node* p2 = R.Phi(R.self, R.leaf[0]);
613 R.ReducePhiIterative(R.leaf[0], R.Phi(p2, p2));
614 }
615
616
617 TEST(EReducePhi1) {
618 ControlReducerTester R;
619
620 R.ReducePhi(R.leaf[0], R.EffectPhi(R.leaf[0]));
621 R.ReducePhi(R.leaf[1], R.EffectPhi(R.leaf[1]));
622 R.ReducePhi(R.leaf[2], R.EffectPhi(R.leaf[2]));
623 R.ReducePhi(R.leaf[3], R.EffectPhi(R.leaf[3]));
624 }
625
626
627 TEST(EReducePhi1_dead) {
628 ControlReducerTester R;
629
630 R.ReducePhi(R.leaf[0], R.EffectPhi(R.leaf[0], R.dead));
631 R.ReducePhi(R.leaf[1], R.EffectPhi(R.leaf[1], R.dead));
632 R.ReducePhi(R.leaf[2], R.EffectPhi(R.leaf[2], R.dead));
633 R.ReducePhi(R.leaf[3], R.EffectPhi(R.leaf[3], R.dead));
634
635 R.ReducePhi(R.leaf[0], R.EffectPhi(R.dead, R.leaf[0]));
636 R.ReducePhi(R.leaf[1], R.EffectPhi(R.dead, R.leaf[1]));
637 R.ReducePhi(R.leaf[2], R.EffectPhi(R.dead, R.leaf[2]));
638 R.ReducePhi(R.leaf[3], R.EffectPhi(R.dead, R.leaf[3]));
639 }
640
641
642 TEST(EReducePhi1_dead2) {
643 ControlReducerTester R;
644
645 R.ReducePhi(R.leaf[0], R.EffectPhi(R.leaf[0], R.dead, R.dead));
646 R.ReducePhi(R.leaf[0], R.EffectPhi(R.dead, R.leaf[0], R.dead));
647 R.ReducePhi(R.leaf[0], R.EffectPhi(R.dead, R.dead, R.leaf[0]));
648 }
649
650
651 TEST(CMergeReduce_simple1) {
652 ControlReducerTester R;
653
654 Node* merge = R.graph.NewNode(R.common.Merge(1), R.start);
655 R.ReduceMerge(R.start, merge);
656 }
657
658
659 TEST(CMergeReduce_simple2) {
660 ControlReducerTester R;
661
662 Node* merge1 = R.graph.NewNode(R.common.Merge(1), R.start);
663 Node* merge2 = R.graph.NewNode(R.common.Merge(1), merge1);
664 R.ReduceMerge(merge1, merge2);
665 R.ReduceMergeIterative(R.start, merge2);
666 }
667
668
669 TEST(CMergeReduce_none1) {
670 ControlReducerTester R;
671
672 Node* merge = R.graph.NewNode(R.common.Merge(2), R.start, R.start);
673 R.ReduceMerge(merge, merge);
674 }
675
676
677 TEST(CMergeReduce_none2) {
678 ControlReducerTester R;
679
680 Node* t = R.graph.NewNode(R.common.IfTrue(), R.start);
681 Node* f = R.graph.NewNode(R.common.IfFalse(), R.start);
682 Node* merge = R.graph.NewNode(R.common.Merge(2), t, f);
683 R.ReduceMerge(merge, merge);
684 }
685
686
687 TEST(CMergeReduce_self3) {
688 ControlReducerTester R;
689
690 Node* merge =
691 R.SetSelfReferences(R.graph.NewNode(R.common.Merge(2), R.start, R.self));
692 R.ReduceMerge(merge, merge);
693 }
694
695
696 TEST(CMergeReduce_dead1) {
697 ControlReducerTester R;
698
699 Node* merge = R.graph.NewNode(R.common.Merge(2), R.start, R.dead);
700 R.ReduceMerge(R.start, merge);
701 }
702
703
704 TEST(CMergeReduce_dead2) {
705 ControlReducerTester R;
706
707 Node* merge1 = R.graph.NewNode(R.common.Merge(1), R.start);
708 Node* merge2 = R.graph.NewNode(R.common.Merge(2), merge1, R.dead);
709 R.ReduceMerge(merge1, merge2);
710 R.ReduceMergeIterative(R.start, merge2);
711 }
712
713
714 TEST(CMergeReduce_dead_rm1a) {
715 ControlReducerTester R;
716
717 for (int i = 0; i < 3; i++) {
718 Node* merge = R.graph.NewNode(R.common.Merge(3), R.start, R.start, R.start);
719 merge->ReplaceInput(i, R.dead);
720 R.ReduceMerge(merge, merge);
721 CheckMerge(merge, R.start, R.start);
722 }
723 }
724
725
726 TEST(CMergeReduce_dead_rm1b) {
727 ControlReducerTester R;
728
729 Node* t = R.graph.NewNode(R.common.IfTrue(), R.start);
730 Node* f = R.graph.NewNode(R.common.IfFalse(), R.start);
731 for (int i = 0; i < 2; i++) {
732 Node* merge = R.graph.NewNode(R.common.Merge(3), R.dead, R.dead, R.dead);
733 for (int j = i + 1; j < 3; j++) {
734 merge->ReplaceInput(i, t);
735 merge->ReplaceInput(j, f);
736 R.ReduceMerge(merge, merge);
737 CheckMerge(merge, t, f);
738 }
739 }
740 }
741
742
743 TEST(CMergeReduce_dead_rm2) {
744 ControlReducerTester R;
745
746 for (int i = 0; i < 3; i++) {
747 Node* merge = R.graph.NewNode(R.common.Merge(3), R.dead, R.dead, R.dead);
748 merge->ReplaceInput(i, R.start);
749 R.ReduceMerge(R.start, merge);
750 }
751 }
752
753
754 TEST(CLoopReduce_dead_rm1) {
755 ControlReducerTester R;
756
757 for (int i = 0; i < 3; i++) {
758 Node* loop = R.graph.NewNode(R.common.Loop(3), R.dead, R.start, R.start);
759 R.ReduceMerge(loop, loop);
760 CheckLoop(loop, R.start, R.start);
761 }
762 }
763
764
765 TEST(CMergeReduce_edit_phi1) {
766 ControlReducerTester R;
767
768 for (int i = 0; i < 3; i++) {
769 Node* merge = R.graph.NewNode(R.common.Merge(3), R.start, R.start, R.start);
770 merge->ReplaceInput(i, R.dead);
771 Node* phi = R.graph.NewNode(R.common.Phi(kMachAnyTagged, 3), R.leaf[0],
772 R.leaf[1], R.leaf[2], merge);
773 R.ReduceMerge(merge, merge);
774 CHECK_EQ(IrOpcode::kPhi, phi->opcode());
775 CHECK_EQ(2, phi->op()->InputCount());
776 CHECK_EQ(3, phi->InputCount());
777 CHECK_EQ(R.leaf[i < 1 ? 1 : 0], phi->InputAt(0));
778 CHECK_EQ(R.leaf[i < 2 ? 2 : 1], phi->InputAt(1));
779 CHECK_EQ(merge, phi->InputAt(2));
780 }
781 }
782
783
784 TEST(CMergeReduce_edit_effect_phi1) {
785 ControlReducerTester R;
786
787 for (int i = 0; i < 3; i++) {
788 Node* merge = R.graph.NewNode(R.common.Merge(3), R.start, R.start, R.start);
789 merge->ReplaceInput(i, R.dead);
790 Node* phi = R.graph.NewNode(R.common.EffectPhi(3), R.leaf[0], R.leaf[1],
791 R.leaf[2], merge);
792 R.ReduceMerge(merge, merge);
793 CHECK_EQ(IrOpcode::kEffectPhi, phi->opcode());
794 CHECK_EQ(0, phi->op()->InputCount());
795 CHECK_EQ(2, OperatorProperties::GetEffectInputCount(phi->op()));
796 CHECK_EQ(3, phi->InputCount());
797 CHECK_EQ(R.leaf[i < 1 ? 1 : 0], phi->InputAt(0));
798 CHECK_EQ(R.leaf[i < 2 ? 2 : 1], phi->InputAt(1));
799 CHECK_EQ(merge, phi->InputAt(2));
800 }
801 }
802
803
804 static const int kSelectorSize = 4;
805
806 // Helper to select K of N nodes according to a mask, useful for the test below.
807 struct Selector {
808 int mask;
809 int count;
810 explicit Selector(int m) {
811 mask = m;
812 count = v8::base::bits::CountPopulation32(m);
813 }
814 bool is_selected(int i) { return (mask & (1 << i)) != 0; }
815 void CheckNode(Node* node, IrOpcode::Value opcode, Node** inputs,
816 Node* control) {
817 CHECK_EQ(opcode, node->opcode());
818 CHECK_EQ(count + (control != NULL ? 1 : 0), node->InputCount());
819 int index = 0;
820 for (int i = 0; i < kSelectorSize; i++) {
821 if (mask & (1 << i)) {
822 CHECK_EQ(inputs[i], node->InputAt(index++));
823 }
824 }
825 CHECK_EQ(count, index);
826 if (control != NULL) CHECK_EQ(control, node->InputAt(index++));
827 }
828 int single_index() {
829 CHECK_EQ(1, count);
830 return WhichPowerOf2(mask);
831 }
832 };
833
834
835 TEST(CMergeReduce_exhaustive_4) {
836 ControlReducerTester R;
837 Node* controls[] = {
838 R.graph.NewNode(R.common.Start(1)), R.graph.NewNode(R.common.Start(2)),
839 R.graph.NewNode(R.common.Start(3)), R.graph.NewNode(R.common.Start(4))};
840 Node* values[] = {R.jsgraph.Int32Constant(11), R.jsgraph.Int32Constant(22),
841 R.jsgraph.Int32Constant(33), R.jsgraph.Int32Constant(44)};
842 Node* effects[] = {
843 R.jsgraph.Float64Constant(123.4), R.jsgraph.Float64Constant(223.4),
844 R.jsgraph.Float64Constant(323.4), R.jsgraph.Float64Constant(423.4)};
845
846 for (int mask = 0; mask < (1 << (kSelectorSize - 1)); mask++) {
847 // Reduce a single merge with a given mask.
848 Node* merge = R.graph.NewNode(R.common.Merge(4), controls[0], controls[1],
849 controls[2], controls[3]);
850 Node* phi = R.graph.NewNode(R.common.Phi(kMachAnyTagged, 4), values[0],
851 values[1], values[2], values[3], merge);
852 Node* ephi = R.graph.NewNode(R.common.EffectPhi(4), effects[0], effects[1],
853 effects[2], effects[3], merge);
854
855 Node* phi_use =
856 R.graph.NewNode(R.common.Phi(kMachAnyTagged, 1), phi, R.start);
857 Node* ephi_use = R.graph.NewNode(R.common.EffectPhi(1), ephi, R.start);
858
859 Selector selector(mask);
860
861 for (int i = 0; i < kSelectorSize; i++) { // set up dead merge inputs.
862 if (!selector.is_selected(i)) merge->ReplaceInput(i, R.dead);
863 }
864
865 Node* result =
866 ControlReducer::ReduceMergeForTesting(&R.jsgraph, &R.common, merge);
867
868 int count = selector.count;
869 if (count == 0) {
870 // result should be dead.
871 CHECK_EQ(IrOpcode::kDead, result->opcode());
872 } else if (count == 1) {
873 // merge should be replaced with one of the controls.
874 CHECK_EQ(controls[selector.single_index()], result);
875 // Phis should have been directly replaced.
876 CHECK_EQ(values[selector.single_index()], phi_use->InputAt(0));
877 CHECK_EQ(effects[selector.single_index()], ephi_use->InputAt(0));
878 } else {
879 // Otherwise, nodes should be edited in place.
880 CHECK_EQ(merge, result);
881 selector.CheckNode(merge, IrOpcode::kMerge, controls, NULL);
882 selector.CheckNode(phi, IrOpcode::kPhi, values, merge);
883 selector.CheckNode(ephi, IrOpcode::kEffectPhi, effects, merge);
884 CHECK_EQ(phi, phi_use->InputAt(0));
885 CHECK_EQ(ephi, ephi_use->InputAt(0));
886 CHECK_EQ(count, phi->op()->InputCount());
887 CHECK_EQ(count + 1, phi->InputCount());
888 CHECK_EQ(count, OperatorProperties::GetEffectInputCount(ephi->op()));
889 CHECK_EQ(count + 1, ephi->InputCount());
890 }
891 }
892 }
893
894
895 TEST(CMergeReduce_edit_many_phis1) {
896 ControlReducerTester R;
897
898 const int kPhiCount = 10;
899 Node* phis[kPhiCount];
900
901 for (int i = 0; i < 3; i++) {
902 Node* merge = R.graph.NewNode(R.common.Merge(3), R.start, R.start, R.start);
903 merge->ReplaceInput(i, R.dead);
904 for (int j = 0; j < kPhiCount; j++) {
905 phis[j] = R.graph.NewNode(R.common.Phi(kMachAnyTagged, 3), R.leaf[0],
906 R.leaf[1], R.leaf[2], merge);
907 }
908 R.ReduceMerge(merge, merge);
909 for (int j = 0; j < kPhiCount; j++) {
910 Node* phi = phis[j];
911 CHECK_EQ(IrOpcode::kPhi, phi->opcode());
912 CHECK_EQ(2, phi->op()->InputCount());
913 CHECK_EQ(3, phi->InputCount());
914 CHECK_EQ(R.leaf[i < 1 ? 1 : 0], phi->InputAt(0));
915 CHECK_EQ(R.leaf[i < 2 ? 2 : 1], phi->InputAt(1));
916 CHECK_EQ(merge, phi->InputAt(2));
917 }
918 }
919 }
920
921
922 TEST(CMergeReduce_simple_chain1) {
923 ControlReducerTester R;
924 for (int i = 0; i < 5; i++) {
925 Node* merge = R.graph.NewNode(R.common.Merge(1), R.start);
926 for (int j = 0; j < i; j++) {
927 merge = R.graph.NewNode(R.common.Merge(1), merge);
928 }
929 R.ReduceMergeIterative(R.start, merge);
930 }
931 }
932
933
934 TEST(CMergeReduce_dead_chain1) {
935 ControlReducerTester R;
936 for (int i = 0; i < 5; i++) {
937 Node* merge = R.graph.NewNode(R.common.Merge(1), R.dead);
938 for (int j = 0; j < i; j++) {
939 merge = R.graph.NewNode(R.common.Merge(1), merge);
940 }
941 Node* end = R.graph.NewNode(R.common.End(), merge);
942 R.graph.SetEnd(end);
943 R.ReduceGraph();
944 CHECK(merge->IsDead());
945 CHECK_EQ(NULL, end->InputAt(0)); // end dies.
946 }
947 }
948
949
950 TEST(CMergeReduce_dead_chain2) {
951 ControlReducerTester R;
952 for (int i = 0; i < 5; i++) {
953 Node* merge = R.graph.NewNode(R.common.Merge(1), R.start);
954 for (int j = 0; j < i; j++) {
955 merge = R.graph.NewNode(R.common.Merge(2), merge, R.dead);
956 }
957 R.ReduceMergeIterative(R.start, merge);
958 }
959 }
960
961
962 struct Branch {
963 Node* branch;
964 Node* if_true;
965 Node* if_false;
966
967 Branch(ControlReducerTester& R, Node* cond, Node* control = NULL) {
968 if (control == NULL) control = R.start;
969 branch = R.graph.NewNode(R.common.Branch(), cond, control);
970 if_true = R.graph.NewNode(R.common.IfTrue(), branch);
971 if_false = R.graph.NewNode(R.common.IfFalse(), branch);
972 }
973 };
974
975
976 struct Diamond {
977 Node* branch;
978 Node* if_true;
979 Node* if_false;
980 Node* merge;
981 Node* phi;
982
983 Diamond(ControlReducerTester& R, Node* cond) {
984 branch = R.graph.NewNode(R.common.Branch(), cond, R.start);
985 if_true = R.graph.NewNode(R.common.IfTrue(), branch);
986 if_false = R.graph.NewNode(R.common.IfFalse(), branch);
987 merge = R.graph.NewNode(R.common.Merge(2), if_true, if_false);
988 phi = NULL;
989 }
990
991 Diamond(ControlReducerTester& R, Node* cond, Node* tv, Node* fv) {
992 branch = R.graph.NewNode(R.common.Branch(), cond, R.start);
993 if_true = R.graph.NewNode(R.common.IfTrue(), branch);
994 if_false = R.graph.NewNode(R.common.IfFalse(), branch);
995 merge = R.graph.NewNode(R.common.Merge(2), if_true, if_false);
996 phi = R.graph.NewNode(R.common.Phi(kMachAnyTagged, 2), tv, fv, merge);
997 }
998
999 void chain(Diamond& that) { branch->ReplaceInput(1, that.merge); }
1000
1001 // Nest {this} into either the if_true or if_false branch of {that}.
1002 void nest(Diamond& that, bool if_true) {
1003 if (if_true) {
1004 branch->ReplaceInput(1, that.if_true);
1005 that.merge->ReplaceInput(0, merge);
1006 } else {
1007 branch->ReplaceInput(1, that.if_false);
1008 that.merge->ReplaceInput(1, merge);
1009 }
1010 }
1011 };
1012
1013
1014 struct While {
1015 Node* branch;
1016 Node* if_true;
1017 Node* exit;
1018 Node* loop;
1019
1020 While(ControlReducerTester& R, Node* cond) {
1021 loop = R.graph.NewNode(R.common.Loop(2), R.start, R.start);
1022 branch = R.graph.NewNode(R.common.Branch(), cond, loop);
1023 if_true = R.graph.NewNode(R.common.IfTrue(), branch);
1024 exit = R.graph.NewNode(R.common.IfFalse(), branch);
1025 loop->ReplaceInput(1, if_true);
1026 }
1027
1028 void chain(Node* control) { loop->ReplaceInput(0, control); }
1029 };
1030
1031
1032 TEST(CBranchReduce_none1) {
1033 ControlReducerTester R;
1034 Diamond d(R, R.p0);
1035 R.ReduceBranch(d.branch, d.branch);
1036 }
1037
1038
1039 TEST(CBranchReduce_none2) {
1040 ControlReducerTester R;
1041 Diamond d1(R, R.p0);
1042 Diamond d2(R, R.p0);
1043 d2.chain(d1);
1044 R.ReduceBranch(d2.branch, d2.branch);
1045 }
1046
1047
1048 TEST(CBranchReduce_true) {
1049 ControlReducerTester R;
1050 Node* true_values[] = {
1051 R.one, R.jsgraph.Int32Constant(2),
1052 R.jsgraph.Int32Constant(0x7fffffff), R.jsgraph.Constant(1.0),
1053 R.jsgraph.Constant(22.1), R.jsgraph.TrueConstant()};
1054
1055 for (size_t i = 0; i < arraysize(true_values); i++) {
1056 Diamond d(R, true_values[i]);
1057 Node* true_use = R.graph.NewNode(R.common.Merge(1), d.if_true);
1058 Node* false_use = R.graph.NewNode(R.common.Merge(1), d.if_false);
1059 R.ReduceBranch(R.start, d.branch);
1060 CHECK_EQ(R.start, true_use->InputAt(0));
1061 CHECK_EQ(IrOpcode::kDead, false_use->InputAt(0)->opcode());
1062 CHECK(d.if_true->IsDead()); // replaced
1063 CHECK(d.if_false->IsDead()); // replaced
1064 }
1065 }
1066
1067
1068 TEST(CBranchReduce_false) {
1069 ControlReducerTester R;
1070 Node* false_values[] = {R.zero, R.jsgraph.Constant(0.0),
1071 R.jsgraph.Constant(-0.0), R.jsgraph.FalseConstant()};
1072
1073 for (size_t i = 0; i < arraysize(false_values); i++) {
1074 Diamond d(R, false_values[i]);
1075 Node* true_use = R.graph.NewNode(R.common.Merge(1), d.if_true);
1076 Node* false_use = R.graph.NewNode(R.common.Merge(1), d.if_false);
1077 R.ReduceBranch(R.start, d.branch);
1078 CHECK_EQ(R.start, false_use->InputAt(0));
1079 CHECK_EQ(IrOpcode::kDead, true_use->InputAt(0)->opcode());
1080 CHECK(d.if_true->IsDead()); // replaced
1081 CHECK(d.if_false->IsDead()); // replaced
1082 }
1083 }
1084
1085
1086 TEST(CDiamondReduce_true) {
1087 ControlReducerTester R;
1088 Diamond d1(R, R.one);
1089 R.ReduceMergeIterative(R.start, d1.merge);
1090 }
1091
1092
1093 TEST(CDiamondReduce_false) {
1094 ControlReducerTester R;
1095 Diamond d2(R, R.zero);
1096 R.ReduceMergeIterative(R.start, d2.merge);
1097 }
1098
1099
1100 TEST(CChainedDiamondsReduce_true_false) {
1101 ControlReducerTester R;
1102 Diamond d1(R, R.one);
1103 Diamond d2(R, R.zero);
1104 d2.chain(d1);
1105
1106 R.ReduceMergeIterative(R.start, d2.merge);
1107 }
1108
1109
1110 TEST(CChainedDiamondsReduce_x_false) {
1111 ControlReducerTester R;
1112 Diamond d1(R, R.p0);
1113 Diamond d2(R, R.zero);
1114 d2.chain(d1);
1115
1116 R.ReduceMergeIterative(d1.merge, d2.merge);
1117 }
1118
1119
1120 TEST(CChainedDiamondsReduce_false_x) {
1121 ControlReducerTester R;
1122 Diamond d1(R, R.zero);
1123 Diamond d2(R, R.p0);
1124 d2.chain(d1);
1125
1126 R.ReduceMergeIterative(d2.merge, d2.merge);
1127 CheckInputs(d2.branch, R.p0, R.start);
1128 }
1129
1130
1131 TEST(CChainedDiamondsReduce_phi1) {
1132 ControlReducerTester R;
1133 Diamond d1(R, R.zero, R.one, R.zero); // foldable branch, phi.
1134 Diamond d2(R, d1.phi);
1135 d2.chain(d1);
1136
1137 R.ReduceMergeIterative(R.start, d2.merge);
1138 }
1139
1140
1141 TEST(CChainedDiamondsReduce_phi2) {
1142 ControlReducerTester R;
1143 Diamond d1(R, R.p0, R.one, R.one); // redundant phi.
1144 Diamond d2(R, d1.phi);
1145 d2.chain(d1);
1146
1147 R.ReduceMergeIterative(d1.merge, d2.merge);
1148 }
1149
1150
1151 TEST(CNestedDiamondsReduce_true_true_false) {
1152 ControlReducerTester R;
1153 Diamond d1(R, R.one);
1154 Diamond d2(R, R.zero);
1155 d2.nest(d1, true);
1156
1157 R.ReduceMergeIterative(R.start, d1.merge);
1158 }
1159
1160
1161 TEST(CNestedDiamondsReduce_false_true_false) {
1162 ControlReducerTester R;
1163 Diamond d1(R, R.one);
1164 Diamond d2(R, R.zero);
1165 d2.nest(d1, false);
1166
1167 R.ReduceMergeIterative(R.start, d1.merge);
1168 }
1169
1170
1171 TEST(CNestedDiamonds_xyz) {
1172 ControlReducerTester R;
1173
1174 for (int a = 0; a < 2; a++) {
1175 for (int b = 0; b < 2; b++) {
1176 for (int c = 0; c < 2; c++) {
1177 Diamond d1(R, R.jsgraph.Int32Constant(a));
1178 Diamond d2(R, R.jsgraph.Int32Constant(b));
1179 d2.nest(d1, c);
1180
1181 R.ReduceMergeIterative(R.start, d1.merge);
1182 }
1183 }
1184 }
1185 }
1186
1187
1188 TEST(CDeadLoop1) {
1189 ControlReducerTester R;
1190
1191 Node* loop = R.graph.NewNode(R.common.Loop(1), R.start);
1192 Branch b(R, R.p0, loop);
1193 loop->ReplaceInput(0, b.if_true); // loop is not connected to start.
1194 Node* merge = R.graph.NewNode(R.common.Merge(2), R.start, b.if_false);
1195 R.ReduceMergeIterative(R.start, merge);
1196 CHECK(b.if_true->IsDead());
1197 CHECK(b.if_false->IsDead());
1198 }
1199
1200
1201 TEST(CDeadLoop2) {
1202 ControlReducerTester R;
1203
1204 While w(R, R.p0);
1205 Diamond d(R, R.zero);
1206 // if (0) { while (p0) ; } else { }
1207 w.branch->ReplaceInput(1, d.if_true);
1208 d.merge->ReplaceInput(0, w.exit);
1209
1210 R.ReduceMergeIterative(R.start, d.merge);
1211 CHECK(d.if_true->IsDead());
1212 CHECK(d.if_false->IsDead());
1213 }
1214
1215
1216 TEST(CNonTermLoop1) {
1217 ControlReducerTester R;
1218 Node* loop =
1219 R.SetSelfReferences(R.graph.NewNode(R.common.Loop(2), R.start, R.self));
1220 R.ReduceGraph();
1221 Node* end = R.graph.end();
1222 CheckLoop(loop, R.start, loop);
1223 Node* merge = end->InputAt(0);
1224 CheckMerge(merge, R.start, loop);
1225 }
1226
1227
1228 TEST(CNonTermLoop2) {
1229 ControlReducerTester R;
1230 Diamond d(R, R.p0);
1231 Node* loop = R.SetSelfReferences(
1232 R.graph.NewNode(R.common.Loop(2), d.if_false, R.self));
1233 d.merge->ReplaceInput(1, R.dead);
1234 Node* end = R.graph.end();
1235 end->ReplaceInput(0, d.merge);
1236 R.ReduceGraph();
1237 CHECK_EQ(end, R.graph.end());
1238 CheckLoop(loop, d.if_false, loop);
1239 Node* merge = end->InputAt(0);
1240 CheckMerge(merge, d.if_true, loop);
1241 }
1242
1243
1244 TEST(NonTermLoop3) {
1245 ControlReducerTester R;
1246 Node* loop = R.graph.NewNode(R.common.Loop(2), R.start, R.start);
1247 Branch b(R, R.one, loop);
1248 loop->ReplaceInput(1, b.if_true);
1249 Node* end = R.graph.end();
1250 end->ReplaceInput(0, b.if_false);
1251
1252 R.ReduceGraph();
1253
1254 CHECK_EQ(end, R.graph.end());
1255 CheckInputs(end, loop);
1256 CheckInputs(loop, R.start, loop);
1257 }
1258
1259
1260 TEST(CNonTermLoop_terminate1) {
1261 ControlReducerTester R;
1262 Node* loop = R.graph.NewNode(R.common.Loop(2), R.start, R.start);
1263 Node* effect = R.SetSelfReferences(
1264 R.graph.NewNode(R.common.EffectPhi(2), R.start, R.self, loop));
1265 Branch b(R, R.one, loop);
1266 loop->ReplaceInput(1, b.if_true);
1267 Node* end = R.graph.end();
1268 end->ReplaceInput(0, b.if_false);
1269
1270 R.ReduceGraph();
1271
1272 CHECK_EQ(end, R.graph.end());
1273 CheckLoop(loop, R.start, loop);
1274 Node* terminate = end->InputAt(0);
1275 CHECK_EQ(IrOpcode::kTerminate, terminate->opcode());
1276 CHECK_EQ(2, terminate->InputCount());
1277 CHECK_EQ(1, OperatorProperties::GetEffectInputCount(terminate->op()));
1278 CHECK_EQ(1, OperatorProperties::GetControlInputCount(terminate->op()));
1279 CheckInputs(terminate, effect, loop);
1280 }
1281
1282
1283 TEST(CNonTermLoop_terminate2) {
1284 ControlReducerTester R;
1285 Node* loop = R.graph.NewNode(R.common.Loop(2), R.start, R.start);
1286 Node* effect1 = R.SetSelfReferences(
1287 R.graph.NewNode(R.common.EffectPhi(2), R.start, R.self, loop));
1288 Node* effect2 = R.SetSelfReferences(
1289 R.graph.NewNode(R.common.EffectPhi(2), R.start, R.self, loop));
1290 Branch b(R, R.one, loop);
1291 loop->ReplaceInput(1, b.if_true);
1292 Node* end = R.graph.end();
1293 end->ReplaceInput(0, b.if_false);
1294
1295 R.ReduceGraph();
1296
1297 CheckLoop(loop, R.start, loop);
1298 CHECK_EQ(end, R.graph.end());
1299 Node* terminate = end->InputAt(0);
1300 CHECK_EQ(IrOpcode::kTerminate, terminate->opcode());
1301 CHECK_EQ(3, terminate->InputCount());
1302 CHECK_EQ(2, OperatorProperties::GetEffectInputCount(terminate->op()));
1303 CHECK_EQ(1, OperatorProperties::GetControlInputCount(terminate->op()));
1304 Node* e0 = terminate->InputAt(0);
1305 Node* e1 = terminate->InputAt(1);
1306 CHECK(e0 == effect1 || e1 == effect1);
1307 CHECK(e0 == effect2 || e1 == effect2);
1308 CHECK_EQ(loop, terminate->InputAt(2));
1309 }
1310
1311
1312 TEST(CNonTermLoop_terminate_m1) {
1313 ControlReducerTester R;
1314 Node* loop =
1315 R.SetSelfReferences(R.graph.NewNode(R.common.Loop(2), R.start, R.self));
1316 Node* effect = R.SetSelfReferences(
1317 R.graph.NewNode(R.common.EffectPhi(2), R.start, R.self, loop));
1318 R.ReduceGraph();
1319 Node* end = R.graph.end();
1320 CHECK_EQ(R.start, loop->InputAt(0));
1321 CHECK_EQ(loop, loop->InputAt(1));
1322 Node* merge = end->InputAt(0);
1323 CHECK_EQ(IrOpcode::kMerge, merge->opcode());
1324 CHECK_EQ(2, merge->InputCount());
1325 CHECK_EQ(2, OperatorProperties::GetControlInputCount(merge->op()));
1326 CHECK_EQ(R.start, merge->InputAt(0));
1327
1328 Node* terminate = merge->InputAt(1);
1329 CHECK_EQ(IrOpcode::kTerminate, terminate->opcode());
1330 CHECK_EQ(2, terminate->InputCount());
1331 CHECK_EQ(1, OperatorProperties::GetEffectInputCount(terminate->op()));
1332 CHECK_EQ(1, OperatorProperties::GetControlInputCount(terminate->op()));
1333 CHECK_EQ(effect, terminate->InputAt(0));
1334 CHECK_EQ(loop, terminate->InputAt(1));
1335 }
1336
1337
1338 TEST(CNonTermLoop_big1) {
1339 ControlReducerTester R;
1340 Branch b1(R, R.p0);
1341 Node* rt = R.graph.NewNode(R.common.Return(), R.one, R.start, b1.if_true);
1342
1343 Branch b2(R, R.p0, b1.if_false);
1344 Node* rf = R.graph.NewNode(R.common.Return(), R.zero, R.start, b2.if_true);
1345 Node* loop = R.SetSelfReferences(
1346 R.graph.NewNode(R.common.Loop(2), b2.if_false, R.self));
1347 Node* merge = R.graph.NewNode(R.common.Merge(2), rt, rf);
1348 R.end->ReplaceInput(0, merge);
1349
1350 R.ReduceGraph();
1351
1352 CheckInputs(R.end, merge);
1353 CheckInputs(merge, rt, rf, loop);
1354 CheckInputs(loop, b2.if_false, loop);
1355 }
1356
1357
1358 TEST(CNonTermLoop_big2) {
1359 ControlReducerTester R;
1360 Branch b1(R, R.p0);
1361 Node* rt = R.graph.NewNode(R.common.Return(), R.one, R.start, b1.if_true);
1362
1363 Branch b2(R, R.zero, b1.if_false);
1364 Node* rf = R.graph.NewNode(R.common.Return(), R.zero, R.start, b2.if_true);
1365 Node* loop = R.SetSelfReferences(
1366 R.graph.NewNode(R.common.Loop(2), b2.if_false, R.self));
1367 Node* merge = R.graph.NewNode(R.common.Merge(2), rt, rf);
1368 R.end->ReplaceInput(0, merge);
1369
1370 R.ReduceGraph();
1371
1372 Node* new_merge = R.end->InputAt(0); // old merge was reduced.
1373 CHECK_NE(merge, new_merge);
1374 CheckInputs(new_merge, rt, loop);
1375 CheckInputs(loop, b1.if_false, loop);
1376 CHECK(merge->IsDead());
1377 CHECK(rf->IsDead());
1378 CHECK(b2.if_true->IsDead());
1379 }
1380
1381
1382 TEST(Return1) {
1383 ControlReducerTester R;
1384 Node* ret = R.Return(R.one, R.start, R.start);
1385 R.ReduceGraph();
1386 CheckInputs(R.graph.end(), ret);
1387 CheckInputs(ret, R.one, R.start, R.start);
1388 }
1389
1390
1391 TEST(Return2) {
1392 ControlReducerTester R;
1393 Diamond d(R, R.one);
1394 Node* ret = R.Return(R.half, R.start, d.merge);
1395 R.ReduceGraph();
1396 CHECK(d.branch->IsDead());
1397 CHECK(d.if_true->IsDead());
1398 CHECK(d.if_false->IsDead());
1399 CHECK(d.merge->IsDead());
1400
1401 CheckInputs(R.graph.end(), ret);
1402 CheckInputs(ret, R.half, R.start, R.start);
1403 }
1404
1405
1406 TEST(Return_true1) {
1407 ControlReducerTester R;
1408 Diamond d(R, R.one, R.half, R.zero);
1409 Node* ret = R.Return(d.phi, R.start, d.merge);
1410 R.ReduceGraph();
1411 CHECK(d.branch->IsDead());
1412 CHECK(d.if_true->IsDead());
1413 CHECK(d.if_false->IsDead());
1414 CHECK(d.merge->IsDead());
1415 CHECK(d.phi->IsDead());
1416
1417 CheckInputs(R.graph.end(), ret);
1418 CheckInputs(ret, R.half, R.start, R.start);
1419 }
1420
1421
1422 TEST(Return_false1) {
1423 ControlReducerTester R;
1424 Diamond d(R, R.zero, R.one, R.half);
1425 Node* ret = R.Return(d.phi, R.start, d.merge);
1426 R.ReduceGraph();
1427 CHECK(d.branch->IsDead());
1428 CHECK(d.if_true->IsDead());
1429 CHECK(d.if_false->IsDead());
1430 CHECK(d.merge->IsDead());
1431 CHECK(d.phi->IsDead());
1432
1433 CheckInputs(R.graph.end(), ret);
1434 CheckInputs(ret, R.half, R.start, R.start);
1435 }
1436
1437
1438 void CheckDeadDiamond(Diamond& d) {
1439 CHECK(d.branch->IsDead());
1440 CHECK(d.if_true->IsDead());
1441 CHECK(d.if_false->IsDead());
1442 CHECK(d.merge->IsDead());
1443 if (d.phi != NULL) CHECK(d.phi->IsDead());
1444 }
1445
1446
1447 void CheckLiveDiamond(Diamond& d, bool live_phi = true) {
1448 CheckInputs(d.merge, d.if_true, d.if_false);
1449 CheckInputs(d.if_true, d.branch);
1450 CheckInputs(d.if_false, d.branch);
1451 if (d.phi != NULL) {
1452 if (live_phi) {
1453 CHECK_EQ(3, d.phi->InputCount());
1454 CHECK_EQ(d.merge, d.phi->InputAt(2));
1455 } else {
1456 CHECK(d.phi->IsDead());
1457 }
1458 }
1459 }
1460
1461
1462 TEST(Return_effect1) {
1463 ControlReducerTester R;
1464 Diamond d(R, R.one);
1465 Node* e1 = R.jsgraph.Float64Constant(-100.1);
1466 Node* e2 = R.jsgraph.Float64Constant(+100.1);
1467 Node* effect = R.graph.NewNode(R.common.EffectPhi(2), e1, e2, d.merge);
1468 Node* ret = R.Return(R.p0, effect, d.merge);
1469 R.ReduceGraph();
1470 CheckDeadDiamond(d);
1471 CHECK(effect->IsDead());
1472
1473 CheckInputs(R.graph.end(), ret);
1474 CheckInputs(ret, R.p0, e1, R.start);
1475 }
1476
1477
1478 TEST(Return_nested_diamonds1) {
1479 ControlReducerTester R;
1480 Diamond d1(R, R.p0, R.one, R.zero);
1481 Diamond d2(R, R.p0);
1482 Diamond d3(R, R.p0);
1483
1484 d2.nest(d1, true);
1485 d3.nest(d1, false);
1486
1487 Node* ret = R.Return(d1.phi, R.start, d1.merge);
1488
1489 R.ReduceGraph(); // nothing should happen.
1490
1491 CheckInputs(ret, d1.phi, R.start, d1.merge);
1492 CheckInputs(d1.phi, R.one, R.zero, d1.merge);
1493 CheckInputs(d1.merge, d2.merge, d3.merge);
1494 CheckLiveDiamond(d2);
1495 CheckLiveDiamond(d3);
1496 }
1497
1498
1499 TEST(Return_nested_diamonds_true1) {
1500 ControlReducerTester R;
1501 Diamond d1(R, R.one, R.one, R.zero);
1502 Diamond d2(R, R.p0);
1503 Diamond d3(R, R.p0);
1504
1505 d2.nest(d1, true);
1506 d3.nest(d1, false);
1507
1508 Node* ret = R.Return(d1.phi, R.start, d1.merge);
1509
1510 R.ReduceGraph(); // d1 gets folded true.
1511
1512 CheckInputs(ret, R.one, R.start, d2.merge);
1513 CheckInputs(d2.branch, R.p0, R.start);
1514 CheckDeadDiamond(d1);
1515 CheckLiveDiamond(d2);
1516 CheckDeadDiamond(d3);
1517 }
1518
1519
1520 TEST(Return_nested_diamonds_false1) {
1521 ControlReducerTester R;
1522 Diamond d1(R, R.zero, R.one, R.zero);
1523 Diamond d2(R, R.p0);
1524 Diamond d3(R, R.p0);
1525
1526 d2.nest(d1, true);
1527 d3.nest(d1, false);
1528
1529 Node* ret = R.Return(d1.phi, R.start, d1.merge);
1530
1531 R.ReduceGraph(); // d1 gets folded false.
1532
1533 CheckInputs(ret, R.zero, R.start, d3.merge);
1534 CheckInputs(d3.branch, R.p0, R.start);
1535 CheckDeadDiamond(d1);
1536 CheckDeadDiamond(d2);
1537 CheckLiveDiamond(d3);
1538 }
1539
1540
1541 TEST(Return_nested_diamonds_true_true1) {
1542 ControlReducerTester R;
1543 Diamond d1(R, R.one, R.one, R.zero);
1544 Diamond d2(R, R.one);
1545 Diamond d3(R, R.p0);
1546
1547 d2.nest(d1, true);
1548 d3.nest(d1, false);
1549
1550 Node* ret = R.Return(d1.phi, R.start, d1.merge);
1551
1552 R.ReduceGraph(); // d1 and d2 both get folded true.
1553
1554 CheckInputs(ret, R.one, R.start, R.start);
1555 CheckDeadDiamond(d1);
1556 CheckDeadDiamond(d2);
1557 CheckDeadDiamond(d3);
1558 }
1559
1560
1561 TEST(Return_nested_diamonds_true_false1) {
1562 ControlReducerTester R;
1563 Diamond d1(R, R.one, R.one, R.zero);
1564 Diamond d2(R, R.zero);
1565 Diamond d3(R, R.p0);
1566
1567 d2.nest(d1, true);
1568 d3.nest(d1, false);
1569
1570 Node* ret = R.Return(d1.phi, R.start, d1.merge);
1571
1572 R.ReduceGraph(); // d1 gets folded true and d2 gets folded false.
1573
1574 CheckInputs(ret, R.one, R.start, R.start);
1575 CheckDeadDiamond(d1);
1576 CheckDeadDiamond(d2);
1577 CheckDeadDiamond(d3);
1578 }
1579
1580
1581 TEST(Return_nested_diamonds2) {
1582 ControlReducerTester R;
1583 Node* x2 = R.jsgraph.Float64Constant(11.1);
1584 Node* y2 = R.jsgraph.Float64Constant(22.2);
1585 Node* x3 = R.jsgraph.Float64Constant(33.3);
1586 Node* y3 = R.jsgraph.Float64Constant(44.4);
1587
1588 Diamond d2(R, R.p0, x2, y2);
1589 Diamond d3(R, R.p0, x3, y3);
1590 Diamond d1(R, R.p0, d2.phi, d3.phi);
1591
1592 d2.nest(d1, true);
1593 d3.nest(d1, false);
1594
1595 Node* ret = R.Return(d1.phi, R.start, d1.merge);
1596
1597 R.ReduceGraph(); // nothing should happen.
1598
1599 CheckInputs(ret, d1.phi, R.start, d1.merge);
1600 CheckInputs(d1.phi, d2.phi, d3.phi, d1.merge);
1601 CheckInputs(d1.merge, d2.merge, d3.merge);
1602 CheckLiveDiamond(d2);
1603 CheckLiveDiamond(d3);
1604 }
1605
1606
1607 TEST(Return_nested_diamonds_true2) {
1608 ControlReducerTester R;
1609 Node* x2 = R.jsgraph.Float64Constant(11.1);
1610 Node* y2 = R.jsgraph.Float64Constant(22.2);
1611 Node* x3 = R.jsgraph.Float64Constant(33.3);
1612 Node* y3 = R.jsgraph.Float64Constant(44.4);
1613
1614 Diamond d2(R, R.p0, x2, y2);
1615 Diamond d3(R, R.p0, x3, y3);
1616 Diamond d1(R, R.one, d2.phi, d3.phi);
1617
1618 d2.nest(d1, true);
1619 d3.nest(d1, false);
1620
1621 Node* ret = R.Return(d1.phi, R.start, d1.merge);
1622
1623 R.ReduceGraph(); // d1 gets folded true.
1624
1625 CheckInputs(ret, d2.phi, R.start, d2.merge);
1626 CheckInputs(d2.branch, R.p0, R.start);
1627 CheckDeadDiamond(d1);
1628 CheckLiveDiamond(d2);
1629 CheckDeadDiamond(d3);
1630 }
1631
1632
1633 TEST(Return_nested_diamonds_true_true2) {
1634 ControlReducerTester R;
1635 Node* x2 = R.jsgraph.Float64Constant(11.1);
1636 Node* y2 = R.jsgraph.Float64Constant(22.2);
1637 Node* x3 = R.jsgraph.Float64Constant(33.3);
1638 Node* y3 = R.jsgraph.Float64Constant(44.4);
1639
1640 Diamond d2(R, R.one, x2, y2);
1641 Diamond d3(R, R.p0, x3, y3);
1642 Diamond d1(R, R.one, d2.phi, d3.phi);
1643
1644 d2.nest(d1, true);
1645 d3.nest(d1, false);
1646
1647 Node* ret = R.Return(d1.phi, R.start, d1.merge);
1648
1649 R.ReduceGraph(); // d1 gets folded true.
1650
1651 CheckInputs(ret, x2, R.start, R.start);
1652 CheckDeadDiamond(d1);
1653 CheckDeadDiamond(d2);
1654 CheckDeadDiamond(d3);
1655 }
1656
1657
1658 TEST(Return_nested_diamonds_true_false2) {
1659 ControlReducerTester R;
1660 Node* x2 = R.jsgraph.Float64Constant(11.1);
1661 Node* y2 = R.jsgraph.Float64Constant(22.2);
1662 Node* x3 = R.jsgraph.Float64Constant(33.3);
1663 Node* y3 = R.jsgraph.Float64Constant(44.4);
1664
1665 Diamond d2(R, R.zero, x2, y2);
1666 Diamond d3(R, R.p0, x3, y3);
1667 Diamond d1(R, R.one, d2.phi, d3.phi);
1668
1669 d2.nest(d1, true);
1670 d3.nest(d1, false);
1671
1672 Node* ret = R.Return(d1.phi, R.start, d1.merge);
1673
1674 R.ReduceGraph(); // d1 gets folded true.
1675
1676 CheckInputs(ret, y2, R.start, R.start);
1677 CheckDeadDiamond(d1);
1678 CheckDeadDiamond(d2);
1679 CheckDeadDiamond(d3);
1680 }
OLDNEW
« no previous file with comments | « src/compiler/scheduler.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698