Line data Source code
1 : // Copyright 2014 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #include "src/compiler/common-operator.h"
6 : #include "src/compiler/common-operator-reducer.h"
7 : #include "src/compiler/machine-operator.h"
8 : #include "src/compiler/operator.h"
9 : #include "src/compiler/simplified-operator.h"
10 : #include "src/machine-type.h"
11 : #include "test/unittests/compiler/graph-reducer-unittest.h"
12 : #include "test/unittests/compiler/graph-unittest.h"
13 : #include "test/unittests/compiler/node-test-utils.h"
14 :
15 : using testing::StrictMock;
16 :
17 : namespace v8 {
18 : namespace internal {
19 : namespace compiler {
20 : namespace common_operator_reducer_unittest {
21 :
22 : class CommonOperatorReducerTest : public GraphTest {
23 : public:
24 26 : explicit CommonOperatorReducerTest(int num_parameters = 1)
25 52 : : GraphTest(num_parameters), machine_(zone()), simplified_(zone()) {}
26 26 : ~CommonOperatorReducerTest() override = default;
27 :
28 : protected:
29 617 : Reduction Reduce(
30 : AdvancedReducer::Editor* editor, Node* node,
31 : MachineOperatorBuilder::Flags flags = MachineOperatorBuilder::kNoFlags) {
32 1234 : JSHeapBroker broker(isolate(), zone());
33 : MachineOperatorBuilder machine(zone(), MachineType::PointerRepresentation(),
34 617 : flags);
35 : CommonOperatorReducer reducer(editor, graph(), &broker, common(), &machine,
36 617 : zone());
37 1234 : return reducer.Reduce(node);
38 : }
39 :
40 38 : Reduction Reduce(Node* node, MachineOperatorBuilder::Flags flags =
41 : MachineOperatorBuilder::kNoFlags) {
42 38 : StrictMock<MockAdvancedReducerEditor> editor;
43 76 : return Reduce(&editor, node, flags);
44 : }
45 :
46 : MachineOperatorBuilder* machine() { return &machine_; }
47 : SimplifiedOperatorBuilder* simplified() { return &simplified_; }
48 :
49 : private:
50 : MachineOperatorBuilder machine_;
51 : SimplifiedOperatorBuilder simplified_;
52 : };
53 :
54 :
55 : namespace {
56 :
57 : const BranchHint kBranchHints[] = {BranchHint::kNone, BranchHint::kFalse,
58 : BranchHint::kTrue};
59 :
60 :
61 : const MachineRepresentation kMachineRepresentations[] = {
62 : MachineRepresentation::kBit, MachineRepresentation::kWord8,
63 : MachineRepresentation::kWord16, MachineRepresentation::kWord32,
64 : MachineRepresentation::kWord64, MachineRepresentation::kFloat32,
65 : MachineRepresentation::kFloat64, MachineRepresentation::kTagged};
66 :
67 :
68 3037 : const Operator kOp0(0, Operator::kNoProperties, "Op0", 0, 0, 0, 1, 1, 0);
69 :
70 : } // namespace
71 :
72 :
73 : // -----------------------------------------------------------------------------
74 : // Branch
75 :
76 :
77 15189 : TEST_F(CommonOperatorReducerTest, BranchWithInt32ZeroConstant) {
78 19 : TRACED_FOREACH(BranchHint, hint, kBranchHints) {
79 3 : Node* const control = graph()->start();
80 : Node* const branch =
81 3 : graph()->NewNode(common()->Branch(hint), Int32Constant(0), control);
82 3 : Node* const if_true = graph()->NewNode(common()->IfTrue(), branch);
83 3 : Node* const if_false = graph()->NewNode(common()->IfFalse(), branch);
84 3 : StrictMock<MockAdvancedReducerEditor> editor;
85 12 : EXPECT_CALL(editor, Replace(if_true, IsDead()));
86 12 : EXPECT_CALL(editor, Replace(if_false, control));
87 3 : Reduction const r = Reduce(&editor, branch);
88 4 : ASSERT_TRUE(r.Changed());
89 12 : EXPECT_THAT(r.replacement(), IsDead());
90 3 : }
91 : }
92 :
93 :
94 15189 : TEST_F(CommonOperatorReducerTest, BranchWithInt32OneConstant) {
95 19 : TRACED_FOREACH(BranchHint, hint, kBranchHints) {
96 3 : Node* const control = graph()->start();
97 : Node* const branch =
98 3 : graph()->NewNode(common()->Branch(hint), Int32Constant(1), control);
99 3 : Node* const if_true = graph()->NewNode(common()->IfTrue(), branch);
100 3 : Node* const if_false = graph()->NewNode(common()->IfFalse(), branch);
101 3 : StrictMock<MockAdvancedReducerEditor> editor;
102 12 : EXPECT_CALL(editor, Replace(if_true, control));
103 12 : EXPECT_CALL(editor, Replace(if_false, IsDead()));
104 3 : Reduction const r = Reduce(&editor, branch);
105 4 : ASSERT_TRUE(r.Changed());
106 12 : EXPECT_THAT(r.replacement(), IsDead());
107 3 : }
108 : }
109 :
110 :
111 15189 : TEST_F(CommonOperatorReducerTest, BranchWithFalseConstant) {
112 19 : TRACED_FOREACH(BranchHint, hint, kBranchHints) {
113 3 : Node* const control = graph()->start();
114 : Node* const branch =
115 3 : graph()->NewNode(common()->Branch(hint), FalseConstant(), control);
116 3 : Node* const if_true = graph()->NewNode(common()->IfTrue(), branch);
117 3 : Node* const if_false = graph()->NewNode(common()->IfFalse(), branch);
118 3 : StrictMock<MockAdvancedReducerEditor> editor;
119 12 : EXPECT_CALL(editor, Replace(if_true, IsDead()));
120 12 : EXPECT_CALL(editor, Replace(if_false, control));
121 3 : Reduction const r = Reduce(&editor, branch);
122 4 : ASSERT_TRUE(r.Changed());
123 12 : EXPECT_THAT(r.replacement(), IsDead());
124 3 : }
125 : }
126 :
127 :
128 15189 : TEST_F(CommonOperatorReducerTest, BranchWithTrueConstant) {
129 19 : TRACED_FOREACH(BranchHint, hint, kBranchHints) {
130 3 : Node* const control = graph()->start();
131 : Node* const branch =
132 3 : graph()->NewNode(common()->Branch(hint), TrueConstant(), control);
133 3 : Node* const if_true = graph()->NewNode(common()->IfTrue(), branch);
134 3 : Node* const if_false = graph()->NewNode(common()->IfFalse(), branch);
135 3 : StrictMock<MockAdvancedReducerEditor> editor;
136 12 : EXPECT_CALL(editor, Replace(if_true, control));
137 12 : EXPECT_CALL(editor, Replace(if_false, IsDead()));
138 3 : Reduction const r = Reduce(&editor, branch);
139 4 : ASSERT_TRUE(r.Changed());
140 12 : EXPECT_THAT(r.replacement(), IsDead());
141 3 : }
142 : }
143 :
144 :
145 15189 : TEST_F(CommonOperatorReducerTest, BranchWithBooleanNot) {
146 1 : Node* const value = Parameter(0);
147 19 : TRACED_FOREACH(BranchHint, hint, kBranchHints) {
148 3 : Node* const control = graph()->start();
149 : Node* const branch = graph()->NewNode(
150 : common()->Branch(hint),
151 9 : graph()->NewNode(simplified()->BooleanNot(), value), control);
152 9 : Node* const if_true = graph()->NewNode(common()->IfTrue(), branch);
153 6 : Node* const if_false = graph()->NewNode(common()->IfFalse(), branch);
154 3 : Reduction const r = Reduce(branch);
155 4 : ASSERT_TRUE(r.Changed());
156 6 : EXPECT_EQ(branch, r.replacement());
157 18 : EXPECT_THAT(branch, IsBranch(value, control));
158 15 : EXPECT_THAT(if_false, IsIfTrue(branch));
159 15 : EXPECT_THAT(if_true, IsIfFalse(branch));
160 9 : EXPECT_EQ(NegateBranchHint(hint), BranchHintOf(branch->op()));
161 3 : }
162 : }
163 :
164 15189 : TEST_F(CommonOperatorReducerTest, BranchWithSelect) {
165 1 : Node* const value = Parameter(0);
166 19 : TRACED_FOREACH(BranchHint, hint, kBranchHints) {
167 3 : Node* const control = graph()->start();
168 : Node* const branch = graph()->NewNode(
169 : common()->Branch(hint),
170 : graph()->NewNode(common()->Select(MachineRepresentation::kTagged),
171 : value, FalseConstant(), TrueConstant()),
172 9 : control);
173 9 : Node* const if_true = graph()->NewNode(common()->IfTrue(), branch);
174 6 : Node* const if_false = graph()->NewNode(common()->IfFalse(), branch);
175 3 : Reduction const r = Reduce(branch);
176 4 : ASSERT_TRUE(r.Changed());
177 6 : EXPECT_EQ(branch, r.replacement());
178 18 : EXPECT_THAT(branch, IsBranch(value, control));
179 15 : EXPECT_THAT(if_false, IsIfTrue(branch));
180 15 : EXPECT_THAT(if_true, IsIfFalse(branch));
181 9 : EXPECT_EQ(NegateBranchHint(hint), BranchHintOf(branch->op()));
182 3 : }
183 : }
184 :
185 : // -----------------------------------------------------------------------------
186 : // Merge
187 :
188 :
189 15189 : TEST_F(CommonOperatorReducerTest, MergeOfUnusedDiamond0) {
190 1 : Node* const value = Parameter(0);
191 1 : Node* const control = graph()->start();
192 2 : Node* const branch = graph()->NewNode(common()->Branch(), value, control);
193 1 : Node* const if_true = graph()->NewNode(common()->IfTrue(), branch);
194 1 : Node* const if_false = graph()->NewNode(common()->IfFalse(), branch);
195 : Reduction const r =
196 2 : Reduce(graph()->NewNode(common()->Merge(2), if_true, if_false));
197 2 : ASSERT_TRUE(r.Changed());
198 2 : EXPECT_EQ(control, r.replacement());
199 4 : EXPECT_THAT(branch, IsDead());
200 : }
201 :
202 :
203 15189 : TEST_F(CommonOperatorReducerTest, MergeOfUnusedDiamond1) {
204 1 : Node* const value = Parameter(0);
205 1 : Node* const control = graph()->start();
206 2 : Node* const branch = graph()->NewNode(common()->Branch(), value, control);
207 1 : Node* const if_true = graph()->NewNode(common()->IfTrue(), branch);
208 1 : Node* const if_false = graph()->NewNode(common()->IfFalse(), branch);
209 : Reduction const r =
210 2 : Reduce(graph()->NewNode(common()->Merge(2), if_false, if_true));
211 2 : ASSERT_TRUE(r.Changed());
212 2 : EXPECT_EQ(control, r.replacement());
213 4 : EXPECT_THAT(branch, IsDead());
214 : }
215 :
216 :
217 : // -----------------------------------------------------------------------------
218 : // EffectPhi
219 :
220 :
221 15189 : TEST_F(CommonOperatorReducerTest, EffectPhiWithMerge) {
222 : const int kMaxInputs = 64;
223 : Node* inputs[kMaxInputs];
224 2 : Node* const input = graph()->NewNode(&kOp0);
225 373 : TRACED_FORRANGE(int, input_count, 2, kMaxInputs - 1) {
226 62 : int const value_input_count = input_count - 1;
227 2015 : for (int i = 0; i < value_input_count; ++i) {
228 1953 : inputs[i] = graph()->start();
229 : }
230 : Node* const merge = graph()->NewNode(common()->Merge(value_input_count),
231 62 : value_input_count, inputs);
232 2015 : for (int i = 0; i < value_input_count; ++i) {
233 1953 : inputs[i] = input;
234 : }
235 62 : inputs[value_input_count] = merge;
236 62 : StrictMock<MockAdvancedReducerEditor> editor;
237 186 : EXPECT_CALL(editor, Revisit(merge));
238 : Reduction r =
239 : Reduce(&editor, graph()->NewNode(common()->EffectPhi(value_input_count),
240 62 : input_count, inputs));
241 63 : ASSERT_TRUE(r.Changed());
242 124 : EXPECT_EQ(input, r.replacement());
243 62 : }
244 : }
245 :
246 :
247 15189 : TEST_F(CommonOperatorReducerTest, EffectPhiWithLoop) {
248 2 : Node* const e0 = graph()->NewNode(&kOp0);
249 : Node* const loop =
250 1 : graph()->NewNode(common()->Loop(2), graph()->start(), graph()->start());
251 1 : loop->ReplaceInput(1, loop);
252 1 : Node* const ephi = graph()->NewNode(common()->EffectPhi(2), e0, e0, loop);
253 1 : ephi->ReplaceInput(1, ephi);
254 1 : StrictMock<MockAdvancedReducerEditor> editor;
255 3 : EXPECT_CALL(editor, Revisit(loop));
256 1 : Reduction const r = Reduce(&editor, ephi);
257 2 : ASSERT_TRUE(r.Changed());
258 2 : EXPECT_EQ(e0, r.replacement());
259 : }
260 :
261 :
262 : // -----------------------------------------------------------------------------
263 : // Phi
264 :
265 :
266 15189 : TEST_F(CommonOperatorReducerTest, PhiWithMerge) {
267 : const int kMaxInputs = 64;
268 : Node* inputs[kMaxInputs];
269 2 : Node* const input = graph()->NewNode(&kOp0);
270 373 : TRACED_FORRANGE(int, input_count, 2, kMaxInputs - 1) {
271 62 : int const value_input_count = input_count - 1;
272 3038 : TRACED_FOREACH(MachineRepresentation, rep, kMachineRepresentations) {
273 15624 : for (int i = 0; i < value_input_count; ++i) {
274 15624 : inputs[i] = graph()->start();
275 : }
276 : Node* const merge = graph()->NewNode(common()->Merge(value_input_count),
277 496 : value_input_count, inputs);
278 16120 : for (int i = 0; i < value_input_count; ++i) {
279 15624 : inputs[i] = input;
280 : }
281 496 : inputs[value_input_count] = merge;
282 496 : StrictMock<MockAdvancedReducerEditor> editor;
283 1488 : EXPECT_CALL(editor, Revisit(merge));
284 : Reduction r = Reduce(
285 : &editor, graph()->NewNode(common()->Phi(rep, value_input_count),
286 496 : input_count, inputs));
287 497 : ASSERT_TRUE(r.Changed());
288 992 : EXPECT_EQ(input, r.replacement());
289 496 : }
290 62 : }
291 : }
292 :
293 :
294 15189 : TEST_F(CommonOperatorReducerTest, PhiWithLoop) {
295 1 : Node* const p0 = Parameter(0);
296 : Node* const loop =
297 1 : graph()->NewNode(common()->Loop(2), graph()->start(), graph()->start());
298 1 : loop->ReplaceInput(1, loop);
299 : Node* const phi = graph()->NewNode(
300 1 : common()->Phi(MachineRepresentation::kTagged, 2), p0, p0, loop);
301 1 : phi->ReplaceInput(1, phi);
302 1 : StrictMock<MockAdvancedReducerEditor> editor;
303 3 : EXPECT_CALL(editor, Revisit(loop));
304 1 : Reduction const r = Reduce(&editor, phi);
305 2 : ASSERT_TRUE(r.Changed());
306 2 : EXPECT_EQ(p0, r.replacement());
307 : }
308 :
309 :
310 15189 : TEST_F(CommonOperatorReducerTest, PhiToFloat32Abs) {
311 1 : Node* p0 = Parameter(0);
312 1 : Node* c0 = Float32Constant(0.0);
313 1 : Node* check = graph()->NewNode(machine()->Float32LessThan(), c0, p0);
314 1 : Node* branch = graph()->NewNode(common()->Branch(), check, graph()->start());
315 1 : Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
316 : Node* vtrue = p0;
317 1 : Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
318 1 : Node* vfalse = graph()->NewNode(machine()->Float32Sub(), c0, p0);
319 1 : Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
320 : Node* phi = graph()->NewNode(
321 1 : common()->Phi(MachineRepresentation::kFloat32, 2), vtrue, vfalse, merge);
322 1 : StrictMock<MockAdvancedReducerEditor> editor;
323 3 : EXPECT_CALL(editor, Revisit(merge));
324 1 : Reduction r = Reduce(&editor, phi);
325 2 : ASSERT_TRUE(r.Changed());
326 5 : EXPECT_THAT(r.replacement(), IsFloat32Abs(p0));
327 : }
328 :
329 :
330 15189 : TEST_F(CommonOperatorReducerTest, PhiToFloat64Abs) {
331 1 : Node* p0 = Parameter(0);
332 1 : Node* c0 = Float64Constant(0.0);
333 1 : Node* check = graph()->NewNode(machine()->Float64LessThan(), c0, p0);
334 1 : Node* branch = graph()->NewNode(common()->Branch(), check, graph()->start());
335 1 : Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
336 : Node* vtrue = p0;
337 1 : Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
338 1 : Node* vfalse = graph()->NewNode(machine()->Float64Sub(), c0, p0);
339 1 : Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
340 : Node* phi = graph()->NewNode(
341 1 : common()->Phi(MachineRepresentation::kFloat64, 2), vtrue, vfalse, merge);
342 1 : StrictMock<MockAdvancedReducerEditor> editor;
343 3 : EXPECT_CALL(editor, Revisit(merge));
344 1 : Reduction r = Reduce(&editor, phi);
345 2 : ASSERT_TRUE(r.Changed());
346 5 : EXPECT_THAT(r.replacement(), IsFloat64Abs(p0));
347 : }
348 :
349 :
350 : // -----------------------------------------------------------------------------
351 : // Return
352 :
353 :
354 15189 : TEST_F(CommonOperatorReducerTest, ReturnWithPhiAndEffectPhiAndMerge) {
355 1 : Node* cond = Parameter(2);
356 1 : Node* branch = graph()->NewNode(common()->Branch(), cond, graph()->start());
357 1 : Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
358 1 : Node* etrue = graph()->start();
359 1 : Node* vtrue = Parameter(0);
360 1 : Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
361 1 : Node* efalse = graph()->start();
362 1 : Node* vfalse = Parameter(1);
363 1 : Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
364 1 : Node* ephi = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, merge);
365 : Node* phi = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
366 1 : vtrue, vfalse, merge);
367 :
368 1 : Node* zero = graph()->NewNode(common()->Int32Constant(0));
369 1 : Node* ret = graph()->NewNode(common()->Return(), zero, phi, ephi, merge);
370 1 : graph()->SetEnd(graph()->NewNode(common()->End(1), ret));
371 1 : StrictMock<MockAdvancedReducerEditor> editor;
372 4 : EXPECT_CALL(editor, Replace(merge, IsDead()));
373 1 : Reduction const r = Reduce(&editor, ret);
374 2 : ASSERT_TRUE(r.Changed());
375 4 : EXPECT_THAT(r.replacement(), IsDead());
376 13 : EXPECT_THAT(graph()->end(), IsEnd(ret, IsReturn(vtrue, etrue, if_true),
377 0 : IsReturn(vfalse, efalse, if_false)));
378 : }
379 :
380 15189 : TEST_F(CommonOperatorReducerTest, MultiReturnWithPhiAndEffectPhiAndMerge) {
381 1 : Node* cond = Parameter(2);
382 1 : Node* branch = graph()->NewNode(common()->Branch(), cond, graph()->start());
383 1 : Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
384 1 : Node* etrue = graph()->start();
385 1 : Node* vtrue1 = Parameter(0);
386 1 : Node* vtrue2 = Parameter(1);
387 1 : Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
388 1 : Node* efalse = graph()->start();
389 1 : Node* vfalse1 = Parameter(1);
390 1 : Node* vfalse2 = Parameter(0);
391 1 : Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
392 1 : Node* ephi = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, merge);
393 : Node* phi1 = graph()->NewNode(
394 1 : common()->Phi(MachineRepresentation::kTagged, 2), vtrue1, vfalse1, merge);
395 : Node* phi2 = graph()->NewNode(
396 1 : common()->Phi(MachineRepresentation::kTagged, 2), vtrue2, vfalse2, merge);
397 :
398 1 : Node* zero = graph()->NewNode(common()->Int32Constant(0));
399 : Node* ret =
400 1 : graph()->NewNode(common()->Return(2), zero, phi1, phi2, ephi, merge);
401 1 : graph()->SetEnd(graph()->NewNode(common()->End(1), ret));
402 1 : StrictMock<MockAdvancedReducerEditor> editor;
403 1 : Reduction const r = Reduce(&editor, ret);
404 : // For now a return with multiple return values should not be reduced.
405 3 : ASSERT_TRUE(!r.Changed());
406 : }
407 :
408 : // -----------------------------------------------------------------------------
409 : // Select
410 :
411 :
412 15189 : TEST_F(CommonOperatorReducerTest, SelectWithSameThenAndElse) {
413 2 : Node* const input = graph()->NewNode(&kOp0);
414 19 : TRACED_FOREACH(BranchHint, hint, kBranchHints) {
415 168 : TRACED_FOREACH(MachineRepresentation, rep, kMachineRepresentations) {
416 : Reduction r = Reduce(
417 48 : graph()->NewNode(common()->Select(rep, hint), input, input, input));
418 25 : ASSERT_TRUE(r.Changed());
419 48 : EXPECT_EQ(input, r.replacement());
420 24 : }
421 3 : }
422 : }
423 :
424 :
425 15189 : TEST_F(CommonOperatorReducerTest, SelectWithInt32ZeroConstant) {
426 1 : Node* p0 = Parameter(0);
427 1 : Node* p1 = Parameter(1);
428 : Node* select =
429 : graph()->NewNode(common()->Select(MachineRepresentation::kTagged),
430 1 : Int32Constant(0), p0, p1);
431 1 : Reduction r = Reduce(select);
432 2 : ASSERT_TRUE(r.Changed());
433 2 : EXPECT_EQ(p1, r.replacement());
434 : }
435 :
436 :
437 15189 : TEST_F(CommonOperatorReducerTest, SelectWithInt32OneConstant) {
438 1 : Node* p0 = Parameter(0);
439 1 : Node* p1 = Parameter(1);
440 : Node* select =
441 : graph()->NewNode(common()->Select(MachineRepresentation::kTagged),
442 1 : Int32Constant(1), p0, p1);
443 1 : Reduction r = Reduce(select);
444 2 : ASSERT_TRUE(r.Changed());
445 2 : EXPECT_EQ(p0, r.replacement());
446 : }
447 :
448 :
449 15189 : TEST_F(CommonOperatorReducerTest, SelectWithFalseConstant) {
450 1 : Node* p0 = Parameter(0);
451 1 : Node* p1 = Parameter(1);
452 : Node* select =
453 : graph()->NewNode(common()->Select(MachineRepresentation::kTagged),
454 1 : FalseConstant(), p0, p1);
455 1 : Reduction r = Reduce(select);
456 2 : ASSERT_TRUE(r.Changed());
457 2 : EXPECT_EQ(p1, r.replacement());
458 : }
459 :
460 :
461 15189 : TEST_F(CommonOperatorReducerTest, SelectWithTrueConstant) {
462 1 : Node* p0 = Parameter(0);
463 1 : Node* p1 = Parameter(1);
464 : Node* select = graph()->NewNode(
465 1 : common()->Select(MachineRepresentation::kTagged), TrueConstant(), p0, p1);
466 1 : Reduction r = Reduce(select);
467 2 : ASSERT_TRUE(r.Changed());
468 2 : EXPECT_EQ(p0, r.replacement());
469 : }
470 :
471 :
472 15189 : TEST_F(CommonOperatorReducerTest, SelectToFloat32Abs) {
473 1 : Node* p0 = Parameter(0);
474 1 : Node* c0 = Float32Constant(0.0);
475 1 : Node* check = graph()->NewNode(machine()->Float32LessThan(), c0, p0);
476 : Node* select =
477 : graph()->NewNode(common()->Select(MachineRepresentation::kFloat32), check,
478 2 : p0, graph()->NewNode(machine()->Float32Sub(), c0, p0));
479 1 : Reduction r = Reduce(select);
480 2 : ASSERT_TRUE(r.Changed());
481 5 : EXPECT_THAT(r.replacement(), IsFloat32Abs(p0));
482 : }
483 :
484 :
485 15189 : TEST_F(CommonOperatorReducerTest, SelectToFloat64Abs) {
486 1 : Node* p0 = Parameter(0);
487 1 : Node* c0 = Float64Constant(0.0);
488 1 : Node* check = graph()->NewNode(machine()->Float64LessThan(), c0, p0);
489 : Node* select =
490 : graph()->NewNode(common()->Select(MachineRepresentation::kFloat64), check,
491 2 : p0, graph()->NewNode(machine()->Float64Sub(), c0, p0));
492 1 : Reduction r = Reduce(select);
493 2 : ASSERT_TRUE(r.Changed());
494 5 : EXPECT_THAT(r.replacement(), IsFloat64Abs(p0));
495 : }
496 :
497 : // -----------------------------------------------------------------------------
498 : // Switch
499 :
500 15189 : TEST_F(CommonOperatorReducerTest, SwitchInputMatchesCaseWithDefault) {
501 1 : Node* const control = graph()->start();
502 :
503 1 : Node* sw = graph()->NewNode(common()->Switch(2), Int32Constant(1), control);
504 1 : Node* const if_1 = graph()->NewNode(common()->IfValue(1), sw);
505 1 : graph()->NewNode(common()->IfDefault(), sw);
506 :
507 1 : StrictMock<MockAdvancedReducerEditor> editor;
508 4 : EXPECT_CALL(editor, Replace(if_1, control));
509 1 : Reduction r = Reduce(&editor, sw);
510 2 : ASSERT_TRUE(r.Changed());
511 4 : EXPECT_THAT(r.replacement(), IsDead());
512 : }
513 :
514 15189 : TEST_F(CommonOperatorReducerTest, SwitchInputMatchesDefaultWithCase) {
515 1 : Node* const control = graph()->start();
516 :
517 1 : Node* sw = graph()->NewNode(common()->Switch(2), Int32Constant(0), control);
518 1 : graph()->NewNode(common()->IfValue(1), sw);
519 1 : Node* const if_default = graph()->NewNode(common()->IfDefault(), sw);
520 :
521 1 : StrictMock<MockAdvancedReducerEditor> editor;
522 4 : EXPECT_CALL(editor, Replace(if_default, control));
523 1 : Reduction r = Reduce(&editor, sw);
524 2 : ASSERT_TRUE(r.Changed());
525 4 : EXPECT_THAT(r.replacement(), IsDead());
526 : }
527 :
528 15189 : TEST_F(CommonOperatorReducerTest, SwitchInputMatchesCaseExtraCaseWithDefault) {
529 1 : Node* const control = graph()->start();
530 :
531 1 : Node* sw = graph()->NewNode(common()->Switch(3), Int32Constant(0), control);
532 1 : Node* const if_0 = graph()->NewNode(common()->IfValue(0), sw);
533 1 : graph()->NewNode(common()->IfValue(1), sw);
534 1 : graph()->NewNode(common()->IfDefault(), sw);
535 :
536 1 : StrictMock<MockAdvancedReducerEditor> editor;
537 4 : EXPECT_CALL(editor, Replace(if_0, control));
538 1 : Reduction r = Reduce(&editor, sw);
539 2 : ASSERT_TRUE(r.Changed());
540 4 : EXPECT_THAT(r.replacement(), IsDead());
541 : }
542 :
543 : } // namespace common_operator_reducer_unittest
544 : } // namespace compiler
545 : } // namespace internal
546 9111 : } // namespace v8
|