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 
21 class CommonOperatorReducerTest : public GraphTest {
22  public:
CommonOperatorReducerTest(int num_parameters=1)23   explicit CommonOperatorReducerTest(int num_parameters = 1)
24       : GraphTest(num_parameters), machine_(zone()), simplified_(zone()) {}
~CommonOperatorReducerTest()25   ~CommonOperatorReducerTest() override {}
26 
27  protected:
Reduce(AdvancedReducer::Editor * editor,Node * node,MachineOperatorBuilder::Flags flags=MachineOperatorBuilder::kNoFlags)28   Reduction Reduce(
29       AdvancedReducer::Editor* editor, Node* node,
30       MachineOperatorBuilder::Flags flags = MachineOperatorBuilder::kNoFlags) {
31     MachineOperatorBuilder machine(zone(), MachineType::PointerRepresentation(),
32                                    flags);
33     CommonOperatorReducer reducer(editor, graph(), common(), &machine);
34     return reducer.Reduce(node);
35   }
36 
Reduce(Node * node,MachineOperatorBuilder::Flags flags=MachineOperatorBuilder::kNoFlags)37   Reduction Reduce(Node* node, MachineOperatorBuilder::Flags flags =
38                                    MachineOperatorBuilder::kNoFlags) {
39     StrictMock<MockAdvancedReducerEditor> editor;
40     return Reduce(&editor, node, flags);
41   }
42 
machine()43   MachineOperatorBuilder* machine() { return &machine_; }
simplified()44   SimplifiedOperatorBuilder* simplified() { return &simplified_; }
45 
46  private:
47   MachineOperatorBuilder machine_;
48   SimplifiedOperatorBuilder simplified_;
49 };
50 
51 
52 namespace {
53 
54 const BranchHint kBranchHints[] = {BranchHint::kNone, BranchHint::kFalse,
55                                    BranchHint::kTrue};
56 
57 
58 const MachineRepresentation kMachineRepresentations[] = {
59     MachineRepresentation::kBit,     MachineRepresentation::kWord8,
60     MachineRepresentation::kWord16,  MachineRepresentation::kWord32,
61     MachineRepresentation::kWord64,  MachineRepresentation::kFloat32,
62     MachineRepresentation::kFloat64, MachineRepresentation::kTagged};
63 
64 
65 const Operator kOp0(0, Operator::kNoProperties, "Op0", 0, 0, 0, 1, 1, 0);
66 
67 }  // namespace
68 
69 
70 // -----------------------------------------------------------------------------
71 // Branch
72 
73 
TEST_F(CommonOperatorReducerTest,BranchWithInt32ZeroConstant)74 TEST_F(CommonOperatorReducerTest, BranchWithInt32ZeroConstant) {
75   TRACED_FOREACH(BranchHint, hint, kBranchHints) {
76     Node* const control = graph()->start();
77     Node* const branch =
78         graph()->NewNode(common()->Branch(hint), Int32Constant(0), control);
79     Node* const if_true = graph()->NewNode(common()->IfTrue(), branch);
80     Node* const if_false = graph()->NewNode(common()->IfFalse(), branch);
81     StrictMock<MockAdvancedReducerEditor> editor;
82     EXPECT_CALL(editor, Replace(if_true, IsDead()));
83     EXPECT_CALL(editor, Replace(if_false, control));
84     Reduction const r = Reduce(&editor, branch);
85     ASSERT_TRUE(r.Changed());
86     EXPECT_THAT(r.replacement(), IsDead());
87   }
88 }
89 
90 
TEST_F(CommonOperatorReducerTest,BranchWithInt32OneConstant)91 TEST_F(CommonOperatorReducerTest, BranchWithInt32OneConstant) {
92   TRACED_FOREACH(BranchHint, hint, kBranchHints) {
93     Node* const control = graph()->start();
94     Node* const branch =
95         graph()->NewNode(common()->Branch(hint), Int32Constant(1), control);
96     Node* const if_true = graph()->NewNode(common()->IfTrue(), branch);
97     Node* const if_false = graph()->NewNode(common()->IfFalse(), branch);
98     StrictMock<MockAdvancedReducerEditor> editor;
99     EXPECT_CALL(editor, Replace(if_true, control));
100     EXPECT_CALL(editor, Replace(if_false, IsDead()));
101     Reduction const r = Reduce(&editor, branch);
102     ASSERT_TRUE(r.Changed());
103     EXPECT_THAT(r.replacement(), IsDead());
104   }
105 }
106 
107 
TEST_F(CommonOperatorReducerTest,BranchWithInt64ZeroConstant)108 TEST_F(CommonOperatorReducerTest, BranchWithInt64ZeroConstant) {
109   TRACED_FOREACH(BranchHint, hint, kBranchHints) {
110     Node* const control = graph()->start();
111     Node* const branch =
112         graph()->NewNode(common()->Branch(hint), Int64Constant(0), control);
113     Node* const if_true = graph()->NewNode(common()->IfTrue(), branch);
114     Node* const if_false = graph()->NewNode(common()->IfFalse(), branch);
115     StrictMock<MockAdvancedReducerEditor> editor;
116     EXPECT_CALL(editor, Replace(if_true, IsDead()));
117     EXPECT_CALL(editor, Replace(if_false, control));
118     Reduction const r = Reduce(&editor, branch);
119     ASSERT_TRUE(r.Changed());
120     EXPECT_THAT(r.replacement(), IsDead());
121   }
122 }
123 
124 
TEST_F(CommonOperatorReducerTest,BranchWithInt64OneConstant)125 TEST_F(CommonOperatorReducerTest, BranchWithInt64OneConstant) {
126   TRACED_FOREACH(BranchHint, hint, kBranchHints) {
127     Node* const control = graph()->start();
128     Node* const branch =
129         graph()->NewNode(common()->Branch(hint), Int64Constant(1), control);
130     Node* const if_true = graph()->NewNode(common()->IfTrue(), branch);
131     Node* const if_false = graph()->NewNode(common()->IfFalse(), branch);
132     StrictMock<MockAdvancedReducerEditor> editor;
133     EXPECT_CALL(editor, Replace(if_true, control));
134     EXPECT_CALL(editor, Replace(if_false, IsDead()));
135     Reduction const r = Reduce(&editor, branch);
136     ASSERT_TRUE(r.Changed());
137     EXPECT_THAT(r.replacement(), IsDead());
138   }
139 }
140 
141 
TEST_F(CommonOperatorReducerTest,BranchWithFalseConstant)142 TEST_F(CommonOperatorReducerTest, BranchWithFalseConstant) {
143   TRACED_FOREACH(BranchHint, hint, kBranchHints) {
144     Node* const control = graph()->start();
145     Node* const branch =
146         graph()->NewNode(common()->Branch(hint), FalseConstant(), control);
147     Node* const if_true = graph()->NewNode(common()->IfTrue(), branch);
148     Node* const if_false = graph()->NewNode(common()->IfFalse(), branch);
149     StrictMock<MockAdvancedReducerEditor> editor;
150     EXPECT_CALL(editor, Replace(if_true, IsDead()));
151     EXPECT_CALL(editor, Replace(if_false, control));
152     Reduction const r = Reduce(&editor, branch);
153     ASSERT_TRUE(r.Changed());
154     EXPECT_THAT(r.replacement(), IsDead());
155   }
156 }
157 
158 
TEST_F(CommonOperatorReducerTest,BranchWithTrueConstant)159 TEST_F(CommonOperatorReducerTest, BranchWithTrueConstant) {
160   TRACED_FOREACH(BranchHint, hint, kBranchHints) {
161     Node* const control = graph()->start();
162     Node* const branch =
163         graph()->NewNode(common()->Branch(hint), TrueConstant(), control);
164     Node* const if_true = graph()->NewNode(common()->IfTrue(), branch);
165     Node* const if_false = graph()->NewNode(common()->IfFalse(), branch);
166     StrictMock<MockAdvancedReducerEditor> editor;
167     EXPECT_CALL(editor, Replace(if_true, control));
168     EXPECT_CALL(editor, Replace(if_false, IsDead()));
169     Reduction const r = Reduce(&editor, branch);
170     ASSERT_TRUE(r.Changed());
171     EXPECT_THAT(r.replacement(), IsDead());
172   }
173 }
174 
175 
TEST_F(CommonOperatorReducerTest,BranchWithBooleanNot)176 TEST_F(CommonOperatorReducerTest, BranchWithBooleanNot) {
177   Node* const value = Parameter(0);
178   TRACED_FOREACH(BranchHint, hint, kBranchHints) {
179     Node* const control = graph()->start();
180     Node* const branch = graph()->NewNode(
181         common()->Branch(hint),
182         graph()->NewNode(simplified()->BooleanNot(), value), control);
183     Node* const if_true = graph()->NewNode(common()->IfTrue(), branch);
184     Node* const if_false = graph()->NewNode(common()->IfFalse(), branch);
185     Reduction const r = Reduce(branch);
186     ASSERT_TRUE(r.Changed());
187     EXPECT_EQ(branch, r.replacement());
188     EXPECT_THAT(branch, IsBranch(value, control));
189     EXPECT_THAT(if_false, IsIfTrue(branch));
190     EXPECT_THAT(if_true, IsIfFalse(branch));
191     EXPECT_EQ(NegateBranchHint(hint), BranchHintOf(branch->op()));
192   }
193 }
194 
195 
196 // -----------------------------------------------------------------------------
197 // Merge
198 
199 
TEST_F(CommonOperatorReducerTest,MergeOfUnusedDiamond0)200 TEST_F(CommonOperatorReducerTest, MergeOfUnusedDiamond0) {
201   Node* const value = Parameter(0);
202   Node* const control = graph()->start();
203   Node* const branch = graph()->NewNode(common()->Branch(), value, control);
204   Node* const if_true = graph()->NewNode(common()->IfTrue(), branch);
205   Node* const if_false = graph()->NewNode(common()->IfFalse(), branch);
206   Reduction const r =
207       Reduce(graph()->NewNode(common()->Merge(2), if_true, if_false));
208   ASSERT_TRUE(r.Changed());
209   EXPECT_EQ(control, r.replacement());
210   EXPECT_THAT(branch, IsDead());
211 }
212 
213 
TEST_F(CommonOperatorReducerTest,MergeOfUnusedDiamond1)214 TEST_F(CommonOperatorReducerTest, MergeOfUnusedDiamond1) {
215   Node* const value = Parameter(0);
216   Node* const control = graph()->start();
217   Node* const branch = graph()->NewNode(common()->Branch(), value, control);
218   Node* const if_true = graph()->NewNode(common()->IfTrue(), branch);
219   Node* const if_false = graph()->NewNode(common()->IfFalse(), branch);
220   Reduction const r =
221       Reduce(graph()->NewNode(common()->Merge(2), if_false, if_true));
222   ASSERT_TRUE(r.Changed());
223   EXPECT_EQ(control, r.replacement());
224   EXPECT_THAT(branch, IsDead());
225 }
226 
227 
228 // -----------------------------------------------------------------------------
229 // EffectPhi
230 
231 
TEST_F(CommonOperatorReducerTest,EffectPhiWithMerge)232 TEST_F(CommonOperatorReducerTest, EffectPhiWithMerge) {
233   const int kMaxInputs = 64;
234   Node* inputs[kMaxInputs];
235   Node* const input = graph()->NewNode(&kOp0);
236   TRACED_FORRANGE(int, input_count, 2, kMaxInputs - 1) {
237     int const value_input_count = input_count - 1;
238     for (int i = 0; i < value_input_count; ++i) {
239       inputs[i] = graph()->start();
240     }
241     Node* const merge = graph()->NewNode(common()->Merge(value_input_count),
242                                          value_input_count, inputs);
243     for (int i = 0; i < value_input_count; ++i) {
244       inputs[i] = input;
245     }
246     inputs[value_input_count] = merge;
247     StrictMock<MockAdvancedReducerEditor> editor;
248     EXPECT_CALL(editor, Revisit(merge));
249     Reduction r =
250         Reduce(&editor, graph()->NewNode(common()->EffectPhi(value_input_count),
251                                          input_count, inputs));
252     ASSERT_TRUE(r.Changed());
253     EXPECT_EQ(input, r.replacement());
254   }
255 }
256 
257 
TEST_F(CommonOperatorReducerTest,EffectPhiWithLoop)258 TEST_F(CommonOperatorReducerTest, EffectPhiWithLoop) {
259   Node* const e0 = graph()->NewNode(&kOp0);
260   Node* const loop =
261       graph()->NewNode(common()->Loop(2), graph()->start(), graph()->start());
262   loop->ReplaceInput(1, loop);
263   Node* const ephi = graph()->NewNode(common()->EffectPhi(2), e0, e0, loop);
264   ephi->ReplaceInput(1, ephi);
265   StrictMock<MockAdvancedReducerEditor> editor;
266   EXPECT_CALL(editor, Revisit(loop));
267   Reduction const r = Reduce(&editor, ephi);
268   ASSERT_TRUE(r.Changed());
269   EXPECT_EQ(e0, r.replacement());
270 }
271 
272 
273 // -----------------------------------------------------------------------------
274 // Phi
275 
276 
TEST_F(CommonOperatorReducerTest,PhiWithMerge)277 TEST_F(CommonOperatorReducerTest, PhiWithMerge) {
278   const int kMaxInputs = 64;
279   Node* inputs[kMaxInputs];
280   Node* const input = graph()->NewNode(&kOp0);
281   TRACED_FORRANGE(int, input_count, 2, kMaxInputs - 1) {
282     int const value_input_count = input_count - 1;
283     TRACED_FOREACH(MachineRepresentation, rep, kMachineRepresentations) {
284       for (int i = 0; i < value_input_count; ++i) {
285         inputs[i] = graph()->start();
286       }
287       Node* const merge = graph()->NewNode(common()->Merge(value_input_count),
288                                            value_input_count, inputs);
289       for (int i = 0; i < value_input_count; ++i) {
290         inputs[i] = input;
291       }
292       inputs[value_input_count] = merge;
293       StrictMock<MockAdvancedReducerEditor> editor;
294       EXPECT_CALL(editor, Revisit(merge));
295       Reduction r = Reduce(
296           &editor, graph()->NewNode(common()->Phi(rep, value_input_count),
297                                     input_count, inputs));
298       ASSERT_TRUE(r.Changed());
299       EXPECT_EQ(input, r.replacement());
300     }
301   }
302 }
303 
304 
TEST_F(CommonOperatorReducerTest,PhiWithLoop)305 TEST_F(CommonOperatorReducerTest, PhiWithLoop) {
306   Node* const p0 = Parameter(0);
307   Node* const loop =
308       graph()->NewNode(common()->Loop(2), graph()->start(), graph()->start());
309   loop->ReplaceInput(1, loop);
310   Node* const phi = graph()->NewNode(
311       common()->Phi(MachineRepresentation::kTagged, 2), p0, p0, loop);
312   phi->ReplaceInput(1, phi);
313   StrictMock<MockAdvancedReducerEditor> editor;
314   EXPECT_CALL(editor, Revisit(loop));
315   Reduction const r = Reduce(&editor, phi);
316   ASSERT_TRUE(r.Changed());
317   EXPECT_EQ(p0, r.replacement());
318 }
319 
320 
TEST_F(CommonOperatorReducerTest,PhiToFloat32Abs)321 TEST_F(CommonOperatorReducerTest, PhiToFloat32Abs) {
322   Node* p0 = Parameter(0);
323   Node* c0 = Float32Constant(0.0);
324   Node* check = graph()->NewNode(machine()->Float32LessThan(), c0, p0);
325   Node* branch = graph()->NewNode(common()->Branch(), check, graph()->start());
326   Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
327   Node* vtrue = p0;
328   Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
329   Node* vfalse = graph()->NewNode(machine()->Float32Sub(), c0, p0);
330   Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
331   Node* phi = graph()->NewNode(
332       common()->Phi(MachineRepresentation::kFloat32, 2), vtrue, vfalse, merge);
333   StrictMock<MockAdvancedReducerEditor> editor;
334   EXPECT_CALL(editor, Revisit(merge));
335   Reduction r = Reduce(&editor, phi);
336   ASSERT_TRUE(r.Changed());
337   EXPECT_THAT(r.replacement(), IsFloat32Abs(p0));
338 }
339 
340 
TEST_F(CommonOperatorReducerTest,PhiToFloat64Abs)341 TEST_F(CommonOperatorReducerTest, PhiToFloat64Abs) {
342   Node* p0 = Parameter(0);
343   Node* c0 = Float64Constant(0.0);
344   Node* check = graph()->NewNode(machine()->Float64LessThan(), c0, p0);
345   Node* branch = graph()->NewNode(common()->Branch(), check, graph()->start());
346   Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
347   Node* vtrue = p0;
348   Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
349   Node* vfalse = graph()->NewNode(machine()->Float64Sub(), c0, p0);
350   Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
351   Node* phi = graph()->NewNode(
352       common()->Phi(MachineRepresentation::kFloat64, 2), vtrue, vfalse, merge);
353   StrictMock<MockAdvancedReducerEditor> editor;
354   EXPECT_CALL(editor, Revisit(merge));
355   Reduction r = Reduce(&editor, phi);
356   ASSERT_TRUE(r.Changed());
357   EXPECT_THAT(r.replacement(), IsFloat64Abs(p0));
358 }
359 
360 
TEST_F(CommonOperatorReducerTest,PhiToFloat32Max)361 TEST_F(CommonOperatorReducerTest, PhiToFloat32Max) {
362   Node* p0 = Parameter(0);
363   Node* p1 = Parameter(1);
364   Node* check = graph()->NewNode(machine()->Float32LessThan(), p0, p1);
365   Node* branch = graph()->NewNode(common()->Branch(), check, graph()->start());
366   Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
367   Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
368   Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
369   Node* phi = graph()->NewNode(
370       common()->Phi(MachineRepresentation::kFloat32, 2), p1, p0, merge);
371   StrictMock<MockAdvancedReducerEditor> editor;
372   EXPECT_CALL(editor, Revisit(merge));
373   Reduction r = Reduce(&editor, phi, MachineOperatorBuilder::kFloat32Max);
374   ASSERT_TRUE(r.Changed());
375   EXPECT_THAT(r.replacement(), IsFloat32Max(p1, p0));
376 }
377 
378 
TEST_F(CommonOperatorReducerTest,PhiToFloat64Max)379 TEST_F(CommonOperatorReducerTest, PhiToFloat64Max) {
380   Node* p0 = Parameter(0);
381   Node* p1 = Parameter(1);
382   Node* check = graph()->NewNode(machine()->Float64LessThan(), p0, p1);
383   Node* branch = graph()->NewNode(common()->Branch(), check, graph()->start());
384   Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
385   Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
386   Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
387   Node* phi = graph()->NewNode(
388       common()->Phi(MachineRepresentation::kFloat64, 2), p1, p0, merge);
389   StrictMock<MockAdvancedReducerEditor> editor;
390   EXPECT_CALL(editor, Revisit(merge));
391   Reduction r = Reduce(&editor, phi, MachineOperatorBuilder::kFloat64Max);
392   ASSERT_TRUE(r.Changed());
393   EXPECT_THAT(r.replacement(), IsFloat64Max(p1, p0));
394 }
395 
396 
TEST_F(CommonOperatorReducerTest,PhiToFloat32Min)397 TEST_F(CommonOperatorReducerTest, PhiToFloat32Min) {
398   Node* p0 = Parameter(0);
399   Node* p1 = Parameter(1);
400   Node* check = graph()->NewNode(machine()->Float32LessThan(), p0, p1);
401   Node* branch = graph()->NewNode(common()->Branch(), check, graph()->start());
402   Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
403   Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
404   Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
405   Node* phi = graph()->NewNode(
406       common()->Phi(MachineRepresentation::kFloat32, 2), p0, p1, merge);
407   StrictMock<MockAdvancedReducerEditor> editor;
408   EXPECT_CALL(editor, Revisit(merge));
409   Reduction r = Reduce(&editor, phi, MachineOperatorBuilder::kFloat32Min);
410   ASSERT_TRUE(r.Changed());
411   EXPECT_THAT(r.replacement(), IsFloat32Min(p0, p1));
412 }
413 
414 
TEST_F(CommonOperatorReducerTest,PhiToFloat64Min)415 TEST_F(CommonOperatorReducerTest, PhiToFloat64Min) {
416   Node* p0 = Parameter(0);
417   Node* p1 = Parameter(1);
418   Node* check = graph()->NewNode(machine()->Float64LessThan(), p0, p1);
419   Node* branch = graph()->NewNode(common()->Branch(), check, graph()->start());
420   Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
421   Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
422   Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
423   Node* phi = graph()->NewNode(
424       common()->Phi(MachineRepresentation::kFloat64, 2), p0, p1, merge);
425   StrictMock<MockAdvancedReducerEditor> editor;
426   EXPECT_CALL(editor, Revisit(merge));
427   Reduction r = Reduce(&editor, phi, MachineOperatorBuilder::kFloat64Min);
428   ASSERT_TRUE(r.Changed());
429   EXPECT_THAT(r.replacement(), IsFloat64Min(p0, p1));
430 }
431 
432 
433 // -----------------------------------------------------------------------------
434 // Return
435 
436 
TEST_F(CommonOperatorReducerTest,ReturnWithPhiAndEffectPhiAndMerge)437 TEST_F(CommonOperatorReducerTest, ReturnWithPhiAndEffectPhiAndMerge) {
438   Node* cond = Parameter(2);
439   Node* branch = graph()->NewNode(common()->Branch(), cond, graph()->start());
440   Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
441   Node* etrue = graph()->start();
442   Node* vtrue = Parameter(0);
443   Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
444   Node* efalse = graph()->start();
445   Node* vfalse = Parameter(1);
446   Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
447   Node* ephi = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, merge);
448   Node* phi = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
449                                vtrue, vfalse, merge);
450   Node* ret = graph()->NewNode(common()->Return(), phi, ephi, merge);
451   graph()->SetEnd(graph()->NewNode(common()->End(1), ret));
452   StrictMock<MockAdvancedReducerEditor> editor;
453   EXPECT_CALL(editor, Replace(merge, IsDead()));
454   Reduction const r = Reduce(&editor, ret);
455   ASSERT_TRUE(r.Changed());
456   EXPECT_THAT(r.replacement(), IsDead());
457   EXPECT_THAT(graph()->end(), IsEnd(ret, IsReturn(vtrue, etrue, if_true),
458                                     IsReturn(vfalse, efalse, if_false)));
459 }
460 
461 
462 // -----------------------------------------------------------------------------
463 // Select
464 
465 
TEST_F(CommonOperatorReducerTest,SelectWithSameThenAndElse)466 TEST_F(CommonOperatorReducerTest, SelectWithSameThenAndElse) {
467   Node* const input = graph()->NewNode(&kOp0);
468   TRACED_FOREACH(BranchHint, hint, kBranchHints) {
469     TRACED_FOREACH(MachineRepresentation, rep, kMachineRepresentations) {
470       Reduction r = Reduce(
471           graph()->NewNode(common()->Select(rep, hint), input, input, input));
472       ASSERT_TRUE(r.Changed());
473       EXPECT_EQ(input, r.replacement());
474     }
475   }
476 }
477 
478 
TEST_F(CommonOperatorReducerTest,SelectWithInt32ZeroConstant)479 TEST_F(CommonOperatorReducerTest, SelectWithInt32ZeroConstant) {
480   Node* p0 = Parameter(0);
481   Node* p1 = Parameter(1);
482   Node* select =
483       graph()->NewNode(common()->Select(MachineRepresentation::kTagged),
484                        Int32Constant(0), p0, p1);
485   Reduction r = Reduce(select);
486   ASSERT_TRUE(r.Changed());
487   EXPECT_EQ(p1, r.replacement());
488 }
489 
490 
TEST_F(CommonOperatorReducerTest,SelectWithInt32OneConstant)491 TEST_F(CommonOperatorReducerTest, SelectWithInt32OneConstant) {
492   Node* p0 = Parameter(0);
493   Node* p1 = Parameter(1);
494   Node* select =
495       graph()->NewNode(common()->Select(MachineRepresentation::kTagged),
496                        Int32Constant(1), p0, p1);
497   Reduction r = Reduce(select);
498   ASSERT_TRUE(r.Changed());
499   EXPECT_EQ(p0, r.replacement());
500 }
501 
502 
TEST_F(CommonOperatorReducerTest,SelectWithInt64ZeroConstant)503 TEST_F(CommonOperatorReducerTest, SelectWithInt64ZeroConstant) {
504   Node* p0 = Parameter(0);
505   Node* p1 = Parameter(1);
506   Node* select =
507       graph()->NewNode(common()->Select(MachineRepresentation::kTagged),
508                        Int64Constant(0), p0, p1);
509   Reduction r = Reduce(select);
510   ASSERT_TRUE(r.Changed());
511   EXPECT_EQ(p1, r.replacement());
512 }
513 
514 
TEST_F(CommonOperatorReducerTest,SelectWithInt64OneConstant)515 TEST_F(CommonOperatorReducerTest, SelectWithInt64OneConstant) {
516   Node* p0 = Parameter(0);
517   Node* p1 = Parameter(1);
518   Node* select =
519       graph()->NewNode(common()->Select(MachineRepresentation::kTagged),
520                        Int64Constant(1), p0, p1);
521   Reduction r = Reduce(select);
522   ASSERT_TRUE(r.Changed());
523   EXPECT_EQ(p0, r.replacement());
524 }
525 
526 
TEST_F(CommonOperatorReducerTest,SelectWithFalseConstant)527 TEST_F(CommonOperatorReducerTest, SelectWithFalseConstant) {
528   Node* p0 = Parameter(0);
529   Node* p1 = Parameter(1);
530   Node* select =
531       graph()->NewNode(common()->Select(MachineRepresentation::kTagged),
532                        FalseConstant(), p0, p1);
533   Reduction r = Reduce(select);
534   ASSERT_TRUE(r.Changed());
535   EXPECT_EQ(p1, r.replacement());
536 }
537 
538 
TEST_F(CommonOperatorReducerTest,SelectWithTrueConstant)539 TEST_F(CommonOperatorReducerTest, SelectWithTrueConstant) {
540   Node* p0 = Parameter(0);
541   Node* p1 = Parameter(1);
542   Node* select = graph()->NewNode(
543       common()->Select(MachineRepresentation::kTagged), TrueConstant(), p0, p1);
544   Reduction r = Reduce(select);
545   ASSERT_TRUE(r.Changed());
546   EXPECT_EQ(p0, r.replacement());
547 }
548 
549 
TEST_F(CommonOperatorReducerTest,SelectToFloat32Abs)550 TEST_F(CommonOperatorReducerTest, SelectToFloat32Abs) {
551   Node* p0 = Parameter(0);
552   Node* c0 = Float32Constant(0.0);
553   Node* check = graph()->NewNode(machine()->Float32LessThan(), c0, p0);
554   Node* select =
555       graph()->NewNode(common()->Select(MachineRepresentation::kFloat32), check,
556                        p0, graph()->NewNode(machine()->Float32Sub(), c0, p0));
557   Reduction r = Reduce(select);
558   ASSERT_TRUE(r.Changed());
559   EXPECT_THAT(r.replacement(), IsFloat32Abs(p0));
560 }
561 
562 
TEST_F(CommonOperatorReducerTest,SelectToFloat64Abs)563 TEST_F(CommonOperatorReducerTest, SelectToFloat64Abs) {
564   Node* p0 = Parameter(0);
565   Node* c0 = Float64Constant(0.0);
566   Node* check = graph()->NewNode(machine()->Float64LessThan(), c0, p0);
567   Node* select =
568       graph()->NewNode(common()->Select(MachineRepresentation::kFloat64), check,
569                        p0, graph()->NewNode(machine()->Float64Sub(), c0, p0));
570   Reduction r = Reduce(select);
571   ASSERT_TRUE(r.Changed());
572   EXPECT_THAT(r.replacement(), IsFloat64Abs(p0));
573 }
574 
575 
TEST_F(CommonOperatorReducerTest,SelectToFloat32Max)576 TEST_F(CommonOperatorReducerTest, SelectToFloat32Max) {
577   Node* p0 = Parameter(0);
578   Node* p1 = Parameter(1);
579   Node* check = graph()->NewNode(machine()->Float32LessThan(), p0, p1);
580   Node* select = graph()->NewNode(
581       common()->Select(MachineRepresentation::kFloat32), check, p1, p0);
582   Reduction r = Reduce(select, MachineOperatorBuilder::kFloat32Max);
583   ASSERT_TRUE(r.Changed());
584   EXPECT_THAT(r.replacement(), IsFloat32Max(p1, p0));
585 }
586 
587 
TEST_F(CommonOperatorReducerTest,SelectToFloat64Max)588 TEST_F(CommonOperatorReducerTest, SelectToFloat64Max) {
589   Node* p0 = Parameter(0);
590   Node* p1 = Parameter(1);
591   Node* check = graph()->NewNode(machine()->Float64LessThan(), p0, p1);
592   Node* select = graph()->NewNode(
593       common()->Select(MachineRepresentation::kFloat64), check, p1, p0);
594   Reduction r = Reduce(select, MachineOperatorBuilder::kFloat64Max);
595   ASSERT_TRUE(r.Changed());
596   EXPECT_THAT(r.replacement(), IsFloat64Max(p1, p0));
597 }
598 
599 
TEST_F(CommonOperatorReducerTest,SelectToFloat32Min)600 TEST_F(CommonOperatorReducerTest, SelectToFloat32Min) {
601   Node* p0 = Parameter(0);
602   Node* p1 = Parameter(1);
603   Node* check = graph()->NewNode(machine()->Float32LessThan(), p0, p1);
604   Node* select = graph()->NewNode(
605       common()->Select(MachineRepresentation::kFloat32), check, p0, p1);
606   Reduction r = Reduce(select, MachineOperatorBuilder::kFloat32Min);
607   ASSERT_TRUE(r.Changed());
608   EXPECT_THAT(r.replacement(), IsFloat32Min(p0, p1));
609 }
610 
611 
TEST_F(CommonOperatorReducerTest,SelectToFloat64Min)612 TEST_F(CommonOperatorReducerTest, SelectToFloat64Min) {
613   Node* p0 = Parameter(0);
614   Node* p1 = Parameter(1);
615   Node* check = graph()->NewNode(machine()->Float64LessThan(), p0, p1);
616   Node* select = graph()->NewNode(
617       common()->Select(MachineRepresentation::kFloat64), check, p0, p1);
618   Reduction r = Reduce(select, MachineOperatorBuilder::kFloat64Min);
619   ASSERT_TRUE(r.Changed());
620   EXPECT_THAT(r.replacement(), IsFloat64Min(p0, p1));
621 }
622 
623 }  // namespace compiler
624 }  // namespace internal
625 }  // namespace v8
626