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 <limits>
6
7#include "test/unittests/compiler/instruction-selector-unittest.h"
8
9namespace v8 {
10namespace internal {
11namespace compiler {
12
13namespace {
14
15typedef Node* (RawMachineAssembler::*Constructor)(Node*, Node*);
16
17
18// Data processing instructions.
19struct DPI {
20  Constructor constructor;
21  const char* constructor_name;
22  ArchOpcode arch_opcode;
23  ArchOpcode reverse_arch_opcode;
24  ArchOpcode test_arch_opcode;
25};
26
27
28std::ostream& operator<<(std::ostream& os, const DPI& dpi) {
29  return os << dpi.constructor_name;
30}
31
32
33const DPI kDPIs[] = {
34    {&RawMachineAssembler::Word32And, "Word32And", kArmAnd, kArmAnd, kArmTst},
35    {&RawMachineAssembler::Word32Or, "Word32Or", kArmOrr, kArmOrr, kArmOrr},
36    {&RawMachineAssembler::Word32Xor, "Word32Xor", kArmEor, kArmEor, kArmTeq},
37    {&RawMachineAssembler::Int32Add, "Int32Add", kArmAdd, kArmAdd, kArmCmn},
38    {&RawMachineAssembler::Int32Sub, "Int32Sub", kArmSub, kArmRsb, kArmCmp}};
39
40
41// Floating point arithmetic instructions.
42struct FAI {
43  Constructor constructor;
44  const char* constructor_name;
45  MachineType machine_type;
46  ArchOpcode arch_opcode;
47};
48
49
50std::ostream& operator<<(std::ostream& os, const FAI& fai) {
51  return os << fai.constructor_name;
52}
53
54
55const FAI kFAIs[] = {{&RawMachineAssembler::Float32Add, "Float32Add",
56                      MachineType::Float32(), kArmVaddF32},
57                     {&RawMachineAssembler::Float64Add, "Float64Add",
58                      MachineType::Float64(), kArmVaddF64},
59                     {&RawMachineAssembler::Float32Sub, "Float32Sub",
60                      MachineType::Float32(), kArmVsubF32},
61                     {&RawMachineAssembler::Float64Sub, "Float64Sub",
62                      MachineType::Float64(), kArmVsubF64},
63                     {&RawMachineAssembler::Float32Mul, "Float32Mul",
64                      MachineType::Float32(), kArmVmulF32},
65                     {&RawMachineAssembler::Float64Mul, "Float64Mul",
66                      MachineType::Float64(), kArmVmulF64},
67                     {&RawMachineAssembler::Float32Div, "Float32Div",
68                      MachineType::Float32(), kArmVdivF32},
69                     {&RawMachineAssembler::Float64Div, "Float64Div",
70                      MachineType::Float64(), kArmVdivF64}};
71
72
73// Data processing instructions with overflow.
74struct ODPI {
75  Constructor constructor;
76  const char* constructor_name;
77  ArchOpcode arch_opcode;
78  ArchOpcode reverse_arch_opcode;
79};
80
81
82std::ostream& operator<<(std::ostream& os, const ODPI& odpi) {
83  return os << odpi.constructor_name;
84}
85
86
87const ODPI kODPIs[] = {{&RawMachineAssembler::Int32AddWithOverflow,
88                        "Int32AddWithOverflow", kArmAdd, kArmAdd},
89                       {&RawMachineAssembler::Int32SubWithOverflow,
90                        "Int32SubWithOverflow", kArmSub, kArmRsb}};
91
92
93// Shifts.
94struct Shift {
95  Constructor constructor;
96  const char* constructor_name;
97  int32_t i_low;          // lowest possible immediate
98  int32_t i_high;         // highest possible immediate
99  AddressingMode i_mode;  // Operand2_R_<shift>_I
100  AddressingMode r_mode;  // Operand2_R_<shift>_R
101};
102
103
104std::ostream& operator<<(std::ostream& os, const Shift& shift) {
105  return os << shift.constructor_name;
106}
107
108
109const Shift kShifts[] = {{&RawMachineAssembler::Word32Sar, "Word32Sar", 1, 32,
110                          kMode_Operand2_R_ASR_I, kMode_Operand2_R_ASR_R},
111                         {&RawMachineAssembler::Word32Shl, "Word32Shl", 0, 31,
112                          kMode_Operand2_R_LSL_I, kMode_Operand2_R_LSL_R},
113                         {&RawMachineAssembler::Word32Shr, "Word32Shr", 1, 32,
114                          kMode_Operand2_R_LSR_I, kMode_Operand2_R_LSR_R},
115                         {&RawMachineAssembler::Word32Ror, "Word32Ror", 1, 31,
116                          kMode_Operand2_R_ROR_I, kMode_Operand2_R_ROR_R}};
117
118
119// Immediates (random subset).
120const int32_t kImmediates[] = {
121    std::numeric_limits<int32_t>::min(), -2147483617, -2147483606, -2113929216,
122    -2080374784, -1996488704, -1879048192, -1459617792, -1358954496,
123    -1342177265, -1275068414, -1073741818, -1073741777, -855638016, -805306368,
124    -402653184, -268435444, -16777216, 0, 35, 61, 105, 116, 171, 245, 255, 692,
125    1216, 1248, 1520, 1600, 1888, 3744, 4080, 5888, 8384, 9344, 9472, 9792,
126    13312, 15040, 15360, 20736, 22272, 23296, 32000, 33536, 37120, 45824, 47872,
127    56320, 59392, 65280, 72704, 101376, 147456, 161792, 164864, 167936, 173056,
128    195584, 209920, 212992, 356352, 655360, 704512, 716800, 851968, 901120,
129    1044480, 1523712, 2572288, 3211264, 3588096, 3833856, 3866624, 4325376,
130    5177344, 6488064, 7012352, 7471104, 14090240, 16711680, 19398656, 22282240,
131    28573696, 30408704, 30670848, 43253760, 54525952, 55312384, 56623104,
132    68157440, 115343360, 131072000, 187695104, 188743680, 195035136, 197132288,
133    203423744, 218103808, 267386880, 268435470, 285212672, 402653185, 415236096,
134    595591168, 603979776, 603979778, 629145600, 1073741835, 1073741855,
135    1073741861, 1073741884, 1157627904, 1476395008, 1476395010, 1610612741,
136    2030043136, 2080374785, 2097152000};
137
138}  // namespace
139
140
141// -----------------------------------------------------------------------------
142// Data processing instructions.
143
144
145typedef InstructionSelectorTestWithParam<DPI> InstructionSelectorDPITest;
146
147
148TEST_P(InstructionSelectorDPITest, Parameters) {
149  const DPI dpi = GetParam();
150  StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
151                  MachineType::Int32());
152  m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)));
153  Stream s = m.Build();
154  ASSERT_EQ(1U, s.size());
155  EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
156  EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
157  EXPECT_EQ(2U, s[0]->InputCount());
158  EXPECT_EQ(1U, s[0]->OutputCount());
159}
160
161
162TEST_P(InstructionSelectorDPITest, Immediate) {
163  const DPI dpi = GetParam();
164  TRACED_FOREACH(int32_t, imm, kImmediates) {
165    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
166    m.Return((m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm)));
167    Stream s = m.Build();
168    ASSERT_EQ(1U, s.size());
169    EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
170    EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode());
171    ASSERT_EQ(2U, s[0]->InputCount());
172    EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
173    EXPECT_EQ(1U, s[0]->OutputCount());
174  }
175  TRACED_FOREACH(int32_t, imm, kImmediates) {
176    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
177    m.Return((m.*dpi.constructor)(m.Int32Constant(imm), m.Parameter(0)));
178    Stream s = m.Build();
179    ASSERT_EQ(1U, s.size());
180    EXPECT_EQ(dpi.reverse_arch_opcode, s[0]->arch_opcode());
181    EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode());
182    ASSERT_EQ(2U, s[0]->InputCount());
183    EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
184    EXPECT_EQ(1U, s[0]->OutputCount());
185  }
186}
187
188
189TEST_P(InstructionSelectorDPITest, ShiftByParameter) {
190  const DPI dpi = GetParam();
191  TRACED_FOREACH(Shift, shift, kShifts) {
192    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
193                    MachineType::Int32(), MachineType::Int32());
194    m.Return((m.*dpi.constructor)(
195        m.Parameter(0),
196        (m.*shift.constructor)(m.Parameter(1), m.Parameter(2))));
197    Stream s = m.Build();
198    ASSERT_EQ(1U, s.size());
199    EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
200    EXPECT_EQ(shift.r_mode, s[0]->addressing_mode());
201    EXPECT_EQ(3U, s[0]->InputCount());
202    EXPECT_EQ(1U, s[0]->OutputCount());
203  }
204  TRACED_FOREACH(Shift, shift, kShifts) {
205    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
206                    MachineType::Int32(), MachineType::Int32());
207    m.Return((m.*dpi.constructor)(
208        (m.*shift.constructor)(m.Parameter(0), m.Parameter(1)),
209        m.Parameter(2)));
210    Stream s = m.Build();
211    ASSERT_EQ(1U, s.size());
212    EXPECT_EQ(dpi.reverse_arch_opcode, s[0]->arch_opcode());
213    EXPECT_EQ(shift.r_mode, s[0]->addressing_mode());
214    EXPECT_EQ(3U, s[0]->InputCount());
215    EXPECT_EQ(1U, s[0]->OutputCount());
216  }
217}
218
219
220TEST_P(InstructionSelectorDPITest, ShiftByImmediate) {
221  const DPI dpi = GetParam();
222  TRACED_FOREACH(Shift, shift, kShifts) {
223    TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) {
224      StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
225                      MachineType::Int32());
226      m.Return((m.*dpi.constructor)(
227          m.Parameter(0),
228          (m.*shift.constructor)(m.Parameter(1), m.Int32Constant(imm))));
229      Stream s = m.Build();
230      ASSERT_EQ(1U, s.size());
231      EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
232      EXPECT_EQ(shift.i_mode, s[0]->addressing_mode());
233      ASSERT_EQ(3U, s[0]->InputCount());
234      EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2)));
235      EXPECT_EQ(1U, s[0]->OutputCount());
236    }
237  }
238  TRACED_FOREACH(Shift, shift, kShifts) {
239    TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) {
240      StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
241                      MachineType::Int32());
242      m.Return((m.*dpi.constructor)(
243          (m.*shift.constructor)(m.Parameter(0), m.Int32Constant(imm)),
244          m.Parameter(1)));
245      Stream s = m.Build();
246      ASSERT_EQ(1U, s.size());
247      EXPECT_EQ(dpi.reverse_arch_opcode, s[0]->arch_opcode());
248      EXPECT_EQ(shift.i_mode, s[0]->addressing_mode());
249      ASSERT_EQ(3U, s[0]->InputCount());
250      EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2)));
251      EXPECT_EQ(1U, s[0]->OutputCount());
252    }
253  }
254}
255
256
257TEST_P(InstructionSelectorDPITest, BranchWithParameters) {
258  const DPI dpi = GetParam();
259  StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
260                  MachineType::Int32());
261  RawMachineLabel a, b;
262  m.Branch((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)), &a, &b);
263  m.Bind(&a);
264  m.Return(m.Int32Constant(1));
265  m.Bind(&b);
266  m.Return(m.Int32Constant(0));
267  Stream s = m.Build();
268  ASSERT_EQ(1U, s.size());
269  EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode());
270  EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
271  EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
272  EXPECT_EQ(kNotEqual, s[0]->flags_condition());
273}
274
275
276TEST_P(InstructionSelectorDPITest, BranchWithImmediate) {
277  const DPI dpi = GetParam();
278  TRACED_FOREACH(int32_t, imm, kImmediates) {
279    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
280    RawMachineLabel a, b;
281    m.Branch((m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm)), &a,
282             &b);
283    m.Bind(&a);
284    m.Return(m.Int32Constant(1));
285    m.Bind(&b);
286    m.Return(m.Int32Constant(0));
287    Stream s = m.Build();
288    ASSERT_EQ(1U, s.size());
289    EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode());
290    EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode());
291    EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
292    EXPECT_EQ(kNotEqual, s[0]->flags_condition());
293  }
294  TRACED_FOREACH(int32_t, imm, kImmediates) {
295    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
296    RawMachineLabel a, b;
297    m.Branch((m.*dpi.constructor)(m.Int32Constant(imm), m.Parameter(0)), &a,
298             &b);
299    m.Bind(&a);
300    m.Return(m.Int32Constant(1));
301    m.Bind(&b);
302    m.Return(m.Int32Constant(0));
303    Stream s = m.Build();
304    ASSERT_EQ(1U, s.size());
305    EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode());
306    EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode());
307    EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
308    EXPECT_EQ(kNotEqual, s[0]->flags_condition());
309  }
310}
311
312
313TEST_P(InstructionSelectorDPITest, BranchWithShiftByParameter) {
314  const DPI dpi = GetParam();
315  TRACED_FOREACH(Shift, shift, kShifts) {
316    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
317                    MachineType::Int32(), MachineType::Int32());
318    RawMachineLabel a, b;
319    m.Branch((m.*dpi.constructor)(
320                 m.Parameter(0),
321                 (m.*shift.constructor)(m.Parameter(1), m.Parameter(2))),
322             &a, &b);
323    m.Bind(&a);
324    m.Return(m.Int32Constant(1));
325    m.Bind(&b);
326    m.Return(m.Int32Constant(0));
327    Stream s = m.Build();
328    ASSERT_EQ(1U, s.size());
329    EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode());
330    EXPECT_EQ(shift.r_mode, s[0]->addressing_mode());
331    EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
332    EXPECT_EQ(kNotEqual, s[0]->flags_condition());
333  }
334  TRACED_FOREACH(Shift, shift, kShifts) {
335    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
336                    MachineType::Int32(), MachineType::Int32());
337    RawMachineLabel a, b;
338    m.Branch((m.*dpi.constructor)(
339                 (m.*shift.constructor)(m.Parameter(0), m.Parameter(1)),
340                 m.Parameter(2)),
341             &a, &b);
342    m.Bind(&a);
343    m.Return(m.Int32Constant(1));
344    m.Bind(&b);
345    m.Return(m.Int32Constant(0));
346    Stream s = m.Build();
347    ASSERT_EQ(1U, s.size());
348    EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode());
349    EXPECT_EQ(shift.r_mode, s[0]->addressing_mode());
350    EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
351    EXPECT_EQ(kNotEqual, s[0]->flags_condition());
352  }
353}
354
355
356TEST_P(InstructionSelectorDPITest, BranchWithShiftByImmediate) {
357  const DPI dpi = GetParam();
358  TRACED_FOREACH(Shift, shift, kShifts) {
359    TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) {
360      StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
361                      MachineType::Int32());
362      RawMachineLabel a, b;
363      m.Branch((m.*dpi.constructor)(m.Parameter(0),
364                                    (m.*shift.constructor)(
365                                        m.Parameter(1), m.Int32Constant(imm))),
366               &a, &b);
367      m.Bind(&a);
368      m.Return(m.Int32Constant(1));
369      m.Bind(&b);
370      m.Return(m.Int32Constant(0));
371      Stream s = m.Build();
372      ASSERT_EQ(1U, s.size());
373      EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode());
374      EXPECT_EQ(shift.i_mode, s[0]->addressing_mode());
375      ASSERT_EQ(5U, s[0]->InputCount());
376      EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2)));
377      EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
378      EXPECT_EQ(kNotEqual, s[0]->flags_condition());
379    }
380  }
381  TRACED_FOREACH(Shift, shift, kShifts) {
382    TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) {
383      StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
384                      MachineType::Int32());
385      RawMachineLabel a, b;
386      m.Branch((m.*dpi.constructor)(
387                   (m.*shift.constructor)(m.Parameter(0), m.Int32Constant(imm)),
388                   m.Parameter(1)),
389               &a, &b);
390      m.Bind(&a);
391      m.Return(m.Int32Constant(1));
392      m.Bind(&b);
393      m.Return(m.Int32Constant(0));
394      Stream s = m.Build();
395      ASSERT_EQ(1U, s.size());
396      EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode());
397      EXPECT_EQ(shift.i_mode, s[0]->addressing_mode());
398      ASSERT_EQ(5U, s[0]->InputCount());
399      EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2)));
400      EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
401      EXPECT_EQ(kNotEqual, s[0]->flags_condition());
402    }
403  }
404}
405
406
407TEST_P(InstructionSelectorDPITest, BranchIfZeroWithParameters) {
408  const DPI dpi = GetParam();
409  StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
410                  MachineType::Int32());
411  RawMachineLabel a, b;
412  m.Branch(m.Word32Equal((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)),
413                         m.Int32Constant(0)),
414           &a, &b);
415  m.Bind(&a);
416  m.Return(m.Int32Constant(1));
417  m.Bind(&b);
418  m.Return(m.Int32Constant(0));
419  Stream s = m.Build();
420  ASSERT_EQ(1U, s.size());
421  EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode());
422  EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
423  EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
424  EXPECT_EQ(kEqual, s[0]->flags_condition());
425}
426
427
428TEST_P(InstructionSelectorDPITest, BranchIfNotZeroWithParameters) {
429  const DPI dpi = GetParam();
430  StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
431                  MachineType::Int32());
432  RawMachineLabel a, b;
433  m.Branch(
434      m.Word32NotEqual((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)),
435                       m.Int32Constant(0)),
436      &a, &b);
437  m.Bind(&a);
438  m.Return(m.Int32Constant(1));
439  m.Bind(&b);
440  m.Return(m.Int32Constant(0));
441  Stream s = m.Build();
442  ASSERT_EQ(1U, s.size());
443  EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode());
444  EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
445  EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
446  EXPECT_EQ(kNotEqual, s[0]->flags_condition());
447}
448
449
450TEST_P(InstructionSelectorDPITest, BranchIfZeroWithImmediate) {
451  const DPI dpi = GetParam();
452  TRACED_FOREACH(int32_t, imm, kImmediates) {
453    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
454    RawMachineLabel a, b;
455    m.Branch(m.Word32Equal(
456                 (m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm)),
457                 m.Int32Constant(0)),
458             &a, &b);
459    m.Bind(&a);
460    m.Return(m.Int32Constant(1));
461    m.Bind(&b);
462    m.Return(m.Int32Constant(0));
463    Stream s = m.Build();
464    ASSERT_EQ(1U, s.size());
465    EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode());
466    EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode());
467    EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
468    EXPECT_EQ(kEqual, s[0]->flags_condition());
469  }
470  TRACED_FOREACH(int32_t, imm, kImmediates) {
471    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
472    RawMachineLabel a, b;
473    m.Branch(m.Word32Equal(
474                 (m.*dpi.constructor)(m.Int32Constant(imm), m.Parameter(0)),
475                 m.Int32Constant(0)),
476             &a, &b);
477    m.Bind(&a);
478    m.Return(m.Int32Constant(1));
479    m.Bind(&b);
480    m.Return(m.Int32Constant(0));
481    Stream s = m.Build();
482    ASSERT_EQ(1U, s.size());
483    EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode());
484    EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode());
485    EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
486    EXPECT_EQ(kEqual, s[0]->flags_condition());
487  }
488}
489
490
491TEST_P(InstructionSelectorDPITest, BranchIfNotZeroWithImmediate) {
492  const DPI dpi = GetParam();
493  TRACED_FOREACH(int32_t, imm, kImmediates) {
494    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
495    RawMachineLabel a, b;
496    m.Branch(m.Word32NotEqual(
497                 (m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm)),
498                 m.Int32Constant(0)),
499             &a, &b);
500    m.Bind(&a);
501    m.Return(m.Int32Constant(1));
502    m.Bind(&b);
503    m.Return(m.Int32Constant(0));
504    Stream s = m.Build();
505    ASSERT_EQ(1U, s.size());
506    EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode());
507    EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode());
508    EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
509    EXPECT_EQ(kNotEqual, s[0]->flags_condition());
510  }
511  TRACED_FOREACH(int32_t, imm, kImmediates) {
512    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
513    RawMachineLabel a, b;
514    m.Branch(m.Word32NotEqual(
515                 (m.*dpi.constructor)(m.Int32Constant(imm), m.Parameter(0)),
516                 m.Int32Constant(0)),
517             &a, &b);
518    m.Bind(&a);
519    m.Return(m.Int32Constant(1));
520    m.Bind(&b);
521    m.Return(m.Int32Constant(0));
522    Stream s = m.Build();
523    ASSERT_EQ(1U, s.size());
524    EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode());
525    EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode());
526    EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
527    EXPECT_EQ(kNotEqual, s[0]->flags_condition());
528  }
529}
530
531
532INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorDPITest,
533                        ::testing::ValuesIn(kDPIs));
534
535
536// -----------------------------------------------------------------------------
537// Data processing instructions with overflow.
538
539
540typedef InstructionSelectorTestWithParam<ODPI> InstructionSelectorODPITest;
541
542
543TEST_P(InstructionSelectorODPITest, OvfWithParameters) {
544  const ODPI odpi = GetParam();
545  StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
546                  MachineType::Int32());
547  m.Return(
548      m.Projection(1, (m.*odpi.constructor)(m.Parameter(0), m.Parameter(1))));
549  Stream s = m.Build();
550  ASSERT_EQ(1U, s.size());
551  EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode());
552  EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
553  EXPECT_EQ(2U, s[0]->InputCount());
554  EXPECT_LE(1U, s[0]->OutputCount());
555  EXPECT_EQ(kFlags_set, s[0]->flags_mode());
556  EXPECT_EQ(kOverflow, s[0]->flags_condition());
557}
558
559
560TEST_P(InstructionSelectorODPITest, OvfWithImmediate) {
561  const ODPI odpi = GetParam();
562  TRACED_FOREACH(int32_t, imm, kImmediates) {
563    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
564    m.Return(m.Projection(
565        1, (m.*odpi.constructor)(m.Parameter(0), m.Int32Constant(imm))));
566    Stream s = m.Build();
567    ASSERT_EQ(1U, s.size());
568    EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode());
569    EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode());
570    ASSERT_EQ(2U, s[0]->InputCount());
571    EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
572    EXPECT_LE(1U, s[0]->OutputCount());
573    EXPECT_EQ(kFlags_set, s[0]->flags_mode());
574    EXPECT_EQ(kOverflow, s[0]->flags_condition());
575  }
576  TRACED_FOREACH(int32_t, imm, kImmediates) {
577    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
578    m.Return(m.Projection(
579        1, (m.*odpi.constructor)(m.Int32Constant(imm), m.Parameter(0))));
580    Stream s = m.Build();
581    ASSERT_EQ(1U, s.size());
582    EXPECT_EQ(odpi.reverse_arch_opcode, s[0]->arch_opcode());
583    EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode());
584    ASSERT_EQ(2U, s[0]->InputCount());
585    EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
586    EXPECT_LE(1U, s[0]->OutputCount());
587    EXPECT_EQ(kFlags_set, s[0]->flags_mode());
588    EXPECT_EQ(kOverflow, s[0]->flags_condition());
589  }
590}
591
592
593TEST_P(InstructionSelectorODPITest, OvfWithShiftByParameter) {
594  const ODPI odpi = GetParam();
595  TRACED_FOREACH(Shift, shift, kShifts) {
596    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
597                    MachineType::Int32(), MachineType::Int32());
598    m.Return(m.Projection(
599        1, (m.*odpi.constructor)(
600               m.Parameter(0),
601               (m.*shift.constructor)(m.Parameter(1), m.Parameter(2)))));
602    Stream s = m.Build();
603    ASSERT_EQ(1U, s.size());
604    EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode());
605    EXPECT_EQ(shift.r_mode, s[0]->addressing_mode());
606    EXPECT_EQ(3U, s[0]->InputCount());
607    EXPECT_LE(1U, s[0]->OutputCount());
608    EXPECT_EQ(kFlags_set, s[0]->flags_mode());
609    EXPECT_EQ(kOverflow, s[0]->flags_condition());
610  }
611  TRACED_FOREACH(Shift, shift, kShifts) {
612    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
613                    MachineType::Int32(), MachineType::Int32());
614    m.Return(m.Projection(
615        1, (m.*odpi.constructor)(
616               (m.*shift.constructor)(m.Parameter(0), m.Parameter(1)),
617               m.Parameter(0))));
618    Stream s = m.Build();
619    ASSERT_EQ(1U, s.size());
620    EXPECT_EQ(odpi.reverse_arch_opcode, s[0]->arch_opcode());
621    EXPECT_EQ(shift.r_mode, s[0]->addressing_mode());
622    EXPECT_EQ(3U, s[0]->InputCount());
623    EXPECT_LE(1U, s[0]->OutputCount());
624    EXPECT_EQ(kFlags_set, s[0]->flags_mode());
625    EXPECT_EQ(kOverflow, s[0]->flags_condition());
626  }
627}
628
629
630TEST_P(InstructionSelectorODPITest, OvfWithShiftByImmediate) {
631  const ODPI odpi = GetParam();
632  TRACED_FOREACH(Shift, shift, kShifts) {
633    TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) {
634      StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
635                      MachineType::Int32());
636      m.Return(m.Projection(
637          1, (m.*odpi.constructor)(m.Parameter(0),
638                                   (m.*shift.constructor)(
639                                       m.Parameter(1), m.Int32Constant(imm)))));
640      Stream s = m.Build();
641      ASSERT_EQ(1U, s.size());
642      EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode());
643      EXPECT_EQ(shift.i_mode, s[0]->addressing_mode());
644      ASSERT_EQ(3U, s[0]->InputCount());
645      EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2)));
646      EXPECT_LE(1U, s[0]->OutputCount());
647      EXPECT_EQ(kFlags_set, s[0]->flags_mode());
648      EXPECT_EQ(kOverflow, s[0]->flags_condition());
649    }
650  }
651  TRACED_FOREACH(Shift, shift, kShifts) {
652    TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) {
653      StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
654                      MachineType::Int32());
655      m.Return(m.Projection(
656          1, (m.*odpi.constructor)(
657                 (m.*shift.constructor)(m.Parameter(1), m.Int32Constant(imm)),
658                 m.Parameter(0))));
659      Stream s = m.Build();
660      ASSERT_EQ(1U, s.size());
661      EXPECT_EQ(odpi.reverse_arch_opcode, s[0]->arch_opcode());
662      EXPECT_EQ(shift.i_mode, s[0]->addressing_mode());
663      ASSERT_EQ(3U, s[0]->InputCount());
664      EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2)));
665      EXPECT_LE(1U, s[0]->OutputCount());
666      EXPECT_EQ(kFlags_set, s[0]->flags_mode());
667      EXPECT_EQ(kOverflow, s[0]->flags_condition());
668    }
669  }
670}
671
672
673TEST_P(InstructionSelectorODPITest, ValWithParameters) {
674  const ODPI odpi = GetParam();
675  StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
676                  MachineType::Int32());
677  m.Return(
678      m.Projection(0, (m.*odpi.constructor)(m.Parameter(0), m.Parameter(1))));
679  Stream s = m.Build();
680  ASSERT_EQ(1U, s.size());
681  EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode());
682  EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
683  EXPECT_EQ(2U, s[0]->InputCount());
684  EXPECT_LE(1U, s[0]->OutputCount());
685  EXPECT_EQ(kFlags_none, s[0]->flags_mode());
686}
687
688
689TEST_P(InstructionSelectorODPITest, ValWithImmediate) {
690  const ODPI odpi = GetParam();
691  TRACED_FOREACH(int32_t, imm, kImmediates) {
692    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
693    m.Return(m.Projection(
694        0, (m.*odpi.constructor)(m.Parameter(0), m.Int32Constant(imm))));
695    Stream s = m.Build();
696    ASSERT_EQ(1U, s.size());
697    EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode());
698    EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode());
699    ASSERT_EQ(2U, s[0]->InputCount());
700    EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
701    EXPECT_LE(1U, s[0]->OutputCount());
702    EXPECT_EQ(kFlags_none, s[0]->flags_mode());
703  }
704  TRACED_FOREACH(int32_t, imm, kImmediates) {
705    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
706    m.Return(m.Projection(
707        0, (m.*odpi.constructor)(m.Int32Constant(imm), m.Parameter(0))));
708    Stream s = m.Build();
709    ASSERT_EQ(1U, s.size());
710    EXPECT_EQ(odpi.reverse_arch_opcode, s[0]->arch_opcode());
711    EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode());
712    ASSERT_EQ(2U, s[0]->InputCount());
713    EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
714    EXPECT_LE(1U, s[0]->OutputCount());
715    EXPECT_EQ(kFlags_none, s[0]->flags_mode());
716  }
717}
718
719
720TEST_P(InstructionSelectorODPITest, ValWithShiftByParameter) {
721  const ODPI odpi = GetParam();
722  TRACED_FOREACH(Shift, shift, kShifts) {
723    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
724                    MachineType::Int32(), MachineType::Int32());
725    m.Return(m.Projection(
726        0, (m.*odpi.constructor)(
727               m.Parameter(0),
728               (m.*shift.constructor)(m.Parameter(1), m.Parameter(2)))));
729    Stream s = m.Build();
730    ASSERT_EQ(1U, s.size());
731    EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode());
732    EXPECT_EQ(shift.r_mode, s[0]->addressing_mode());
733    EXPECT_EQ(3U, s[0]->InputCount());
734    EXPECT_LE(1U, s[0]->OutputCount());
735    EXPECT_EQ(kFlags_none, s[0]->flags_mode());
736  }
737  TRACED_FOREACH(Shift, shift, kShifts) {
738    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
739                    MachineType::Int32(), MachineType::Int32());
740    m.Return(m.Projection(
741        0, (m.*odpi.constructor)(
742               (m.*shift.constructor)(m.Parameter(0), m.Parameter(1)),
743               m.Parameter(0))));
744    Stream s = m.Build();
745    ASSERT_EQ(1U, s.size());
746    EXPECT_EQ(odpi.reverse_arch_opcode, s[0]->arch_opcode());
747    EXPECT_EQ(shift.r_mode, s[0]->addressing_mode());
748    EXPECT_EQ(3U, s[0]->InputCount());
749    EXPECT_LE(1U, s[0]->OutputCount());
750    EXPECT_EQ(kFlags_none, s[0]->flags_mode());
751  }
752}
753
754
755TEST_P(InstructionSelectorODPITest, ValWithShiftByImmediate) {
756  const ODPI odpi = GetParam();
757  TRACED_FOREACH(Shift, shift, kShifts) {
758    TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) {
759      StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
760                      MachineType::Int32());
761      m.Return(m.Projection(
762          0, (m.*odpi.constructor)(m.Parameter(0),
763                                   (m.*shift.constructor)(
764                                       m.Parameter(1), m.Int32Constant(imm)))));
765      Stream s = m.Build();
766      ASSERT_EQ(1U, s.size());
767      EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode());
768      EXPECT_EQ(shift.i_mode, s[0]->addressing_mode());
769      ASSERT_EQ(3U, s[0]->InputCount());
770      EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2)));
771      EXPECT_LE(1U, s[0]->OutputCount());
772      EXPECT_EQ(kFlags_none, s[0]->flags_mode());
773    }
774  }
775  TRACED_FOREACH(Shift, shift, kShifts) {
776    TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) {
777      StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
778                      MachineType::Int32());
779      m.Return(m.Projection(
780          0, (m.*odpi.constructor)(
781                 (m.*shift.constructor)(m.Parameter(1), m.Int32Constant(imm)),
782                 m.Parameter(0))));
783      Stream s = m.Build();
784      ASSERT_EQ(1U, s.size());
785      EXPECT_EQ(odpi.reverse_arch_opcode, s[0]->arch_opcode());
786      EXPECT_EQ(shift.i_mode, s[0]->addressing_mode());
787      ASSERT_EQ(3U, s[0]->InputCount());
788      EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2)));
789      EXPECT_LE(1U, s[0]->OutputCount());
790      EXPECT_EQ(kFlags_none, s[0]->flags_mode());
791    }
792  }
793}
794
795
796TEST_P(InstructionSelectorODPITest, BothWithParameters) {
797  const ODPI odpi = GetParam();
798  StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
799                  MachineType::Int32());
800  Node* n = (m.*odpi.constructor)(m.Parameter(0), m.Parameter(1));
801  m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n)));
802  Stream s = m.Build();
803  ASSERT_LE(1U, s.size());
804  EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode());
805  EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
806  EXPECT_EQ(2U, s[0]->InputCount());
807  EXPECT_EQ(2U, s[0]->OutputCount());
808  EXPECT_EQ(kFlags_set, s[0]->flags_mode());
809  EXPECT_EQ(kOverflow, s[0]->flags_condition());
810}
811
812
813TEST_P(InstructionSelectorODPITest, BothWithImmediate) {
814  const ODPI odpi = GetParam();
815  TRACED_FOREACH(int32_t, imm, kImmediates) {
816    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
817    Node* n = (m.*odpi.constructor)(m.Parameter(0), m.Int32Constant(imm));
818    m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n)));
819    Stream s = m.Build();
820    ASSERT_LE(1U, s.size());
821    EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode());
822    EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode());
823    ASSERT_EQ(2U, s[0]->InputCount());
824    EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
825    EXPECT_EQ(2U, s[0]->OutputCount());
826    EXPECT_EQ(kFlags_set, s[0]->flags_mode());
827    EXPECT_EQ(kOverflow, s[0]->flags_condition());
828  }
829  TRACED_FOREACH(int32_t, imm, kImmediates) {
830    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
831    Node* n = (m.*odpi.constructor)(m.Int32Constant(imm), m.Parameter(0));
832    m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n)));
833    Stream s = m.Build();
834    ASSERT_LE(1U, s.size());
835    EXPECT_EQ(odpi.reverse_arch_opcode, s[0]->arch_opcode());
836    EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode());
837    ASSERT_EQ(2U, s[0]->InputCount());
838    EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
839    EXPECT_EQ(2U, s[0]->OutputCount());
840    EXPECT_EQ(kFlags_set, s[0]->flags_mode());
841    EXPECT_EQ(kOverflow, s[0]->flags_condition());
842  }
843}
844
845
846TEST_P(InstructionSelectorODPITest, BothWithShiftByParameter) {
847  const ODPI odpi = GetParam();
848  TRACED_FOREACH(Shift, shift, kShifts) {
849    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
850                    MachineType::Int32(), MachineType::Int32());
851    Node* n = (m.*odpi.constructor)(
852        m.Parameter(0), (m.*shift.constructor)(m.Parameter(1), m.Parameter(2)));
853    m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n)));
854    Stream s = m.Build();
855    ASSERT_LE(1U, s.size());
856    EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode());
857    EXPECT_EQ(shift.r_mode, s[0]->addressing_mode());
858    EXPECT_EQ(3U, s[0]->InputCount());
859    EXPECT_EQ(2U, s[0]->OutputCount());
860    EXPECT_EQ(kFlags_set, s[0]->flags_mode());
861    EXPECT_EQ(kOverflow, s[0]->flags_condition());
862  }
863  TRACED_FOREACH(Shift, shift, kShifts) {
864    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
865                    MachineType::Int32(), MachineType::Int32());
866    Node* n = (m.*odpi.constructor)(
867        (m.*shift.constructor)(m.Parameter(0), m.Parameter(1)), m.Parameter(2));
868    m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n)));
869    Stream s = m.Build();
870    ASSERT_LE(1U, s.size());
871    EXPECT_EQ(odpi.reverse_arch_opcode, s[0]->arch_opcode());
872    EXPECT_EQ(shift.r_mode, s[0]->addressing_mode());
873    EXPECT_EQ(3U, s[0]->InputCount());
874    EXPECT_EQ(2U, s[0]->OutputCount());
875    EXPECT_EQ(kFlags_set, s[0]->flags_mode());
876    EXPECT_EQ(kOverflow, s[0]->flags_condition());
877  }
878}
879
880
881TEST_P(InstructionSelectorODPITest, BothWithShiftByImmediate) {
882  const ODPI odpi = GetParam();
883  TRACED_FOREACH(Shift, shift, kShifts) {
884    TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) {
885      StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
886                      MachineType::Int32());
887      Node* n = (m.*odpi.constructor)(
888          m.Parameter(0),
889          (m.*shift.constructor)(m.Parameter(1), m.Int32Constant(imm)));
890      m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n)));
891      Stream s = m.Build();
892      ASSERT_LE(1U, s.size());
893      EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode());
894      EXPECT_EQ(shift.i_mode, s[0]->addressing_mode());
895      ASSERT_EQ(3U, s[0]->InputCount());
896      EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2)));
897      EXPECT_EQ(2U, s[0]->OutputCount());
898      EXPECT_EQ(kFlags_set, s[0]->flags_mode());
899      EXPECT_EQ(kOverflow, s[0]->flags_condition());
900    }
901  }
902  TRACED_FOREACH(Shift, shift, kShifts) {
903    TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) {
904      StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
905                      MachineType::Int32());
906      Node* n = (m.*odpi.constructor)(
907          (m.*shift.constructor)(m.Parameter(0), m.Int32Constant(imm)),
908          m.Parameter(1));
909      m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n)));
910      Stream s = m.Build();
911      ASSERT_LE(1U, s.size());
912      EXPECT_EQ(odpi.reverse_arch_opcode, s[0]->arch_opcode());
913      EXPECT_EQ(shift.i_mode, s[0]->addressing_mode());
914      ASSERT_EQ(3U, s[0]->InputCount());
915      EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2)));
916      EXPECT_EQ(2U, s[0]->OutputCount());
917      EXPECT_EQ(kFlags_set, s[0]->flags_mode());
918      EXPECT_EQ(kOverflow, s[0]->flags_condition());
919    }
920  }
921}
922
923
924TEST_P(InstructionSelectorODPITest, BranchWithParameters) {
925  const ODPI odpi = GetParam();
926  StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
927                  MachineType::Int32());
928  RawMachineLabel a, b;
929  Node* n = (m.*odpi.constructor)(m.Parameter(0), m.Parameter(1));
930  m.Branch(m.Projection(1, n), &a, &b);
931  m.Bind(&a);
932  m.Return(m.Int32Constant(0));
933  m.Bind(&b);
934  m.Return(m.Projection(0, n));
935  Stream s = m.Build();
936  ASSERT_EQ(1U, s.size());
937  EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode());
938  EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
939  EXPECT_EQ(4U, s[0]->InputCount());
940  EXPECT_EQ(1U, s[0]->OutputCount());
941  EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
942  EXPECT_EQ(kOverflow, s[0]->flags_condition());
943}
944
945
946TEST_P(InstructionSelectorODPITest, BranchWithImmediate) {
947  const ODPI odpi = GetParam();
948  TRACED_FOREACH(int32_t, imm, kImmediates) {
949    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
950    RawMachineLabel a, b;
951    Node* n = (m.*odpi.constructor)(m.Parameter(0), m.Int32Constant(imm));
952    m.Branch(m.Projection(1, n), &a, &b);
953    m.Bind(&a);
954    m.Return(m.Int32Constant(0));
955    m.Bind(&b);
956    m.Return(m.Projection(0, n));
957    Stream s = m.Build();
958    ASSERT_EQ(1U, s.size());
959    EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode());
960    EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode());
961    ASSERT_EQ(4U, s[0]->InputCount());
962    EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
963    EXPECT_EQ(1U, s[0]->OutputCount());
964    EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
965    EXPECT_EQ(kOverflow, s[0]->flags_condition());
966  }
967  TRACED_FOREACH(int32_t, imm, kImmediates) {
968    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
969    RawMachineLabel a, b;
970    Node* n = (m.*odpi.constructor)(m.Int32Constant(imm), m.Parameter(0));
971    m.Branch(m.Projection(1, n), &a, &b);
972    m.Bind(&a);
973    m.Return(m.Int32Constant(0));
974    m.Bind(&b);
975    m.Return(m.Projection(0, n));
976    Stream s = m.Build();
977    ASSERT_EQ(1U, s.size());
978    EXPECT_EQ(odpi.reverse_arch_opcode, s[0]->arch_opcode());
979    EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode());
980    ASSERT_EQ(4U, s[0]->InputCount());
981    EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
982    EXPECT_EQ(1U, s[0]->OutputCount());
983    EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
984    EXPECT_EQ(kOverflow, s[0]->flags_condition());
985  }
986}
987
988
989TEST_P(InstructionSelectorODPITest, BranchIfZeroWithParameters) {
990  const ODPI odpi = GetParam();
991  StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
992                  MachineType::Int32());
993  RawMachineLabel a, b;
994  Node* n = (m.*odpi.constructor)(m.Parameter(0), m.Parameter(1));
995  m.Branch(m.Word32Equal(m.Projection(1, n), m.Int32Constant(0)), &a, &b);
996  m.Bind(&a);
997  m.Return(m.Projection(0, n));
998  m.Bind(&b);
999  m.Return(m.Int32Constant(0));
1000  Stream s = m.Build();
1001  ASSERT_EQ(1U, s.size());
1002  EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode());
1003  EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
1004  EXPECT_EQ(4U, s[0]->InputCount());
1005  EXPECT_EQ(1U, s[0]->OutputCount());
1006  EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
1007  EXPECT_EQ(kNotOverflow, s[0]->flags_condition());
1008}
1009
1010
1011TEST_P(InstructionSelectorODPITest, BranchIfNotZeroWithParameters) {
1012  const ODPI odpi = GetParam();
1013  StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
1014                  MachineType::Int32());
1015  RawMachineLabel a, b;
1016  Node* n = (m.*odpi.constructor)(m.Parameter(0), m.Parameter(1));
1017  m.Branch(m.Word32NotEqual(m.Projection(1, n), m.Int32Constant(0)), &a, &b);
1018  m.Bind(&a);
1019  m.Return(m.Projection(0, n));
1020  m.Bind(&b);
1021  m.Return(m.Int32Constant(0));
1022  Stream s = m.Build();
1023  ASSERT_EQ(1U, s.size());
1024  EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode());
1025  EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
1026  EXPECT_EQ(4U, s[0]->InputCount());
1027  EXPECT_EQ(1U, s[0]->OutputCount());
1028  EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
1029  EXPECT_EQ(kOverflow, s[0]->flags_condition());
1030}
1031
1032
1033INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorODPITest,
1034                        ::testing::ValuesIn(kODPIs));
1035
1036
1037// -----------------------------------------------------------------------------
1038// Shifts.
1039
1040
1041typedef InstructionSelectorTestWithParam<Shift> InstructionSelectorShiftTest;
1042
1043
1044TEST_P(InstructionSelectorShiftTest, Parameters) {
1045  const Shift shift = GetParam();
1046  StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
1047                  MachineType::Int32());
1048  m.Return((m.*shift.constructor)(m.Parameter(0), m.Parameter(1)));
1049  Stream s = m.Build();
1050  ASSERT_EQ(1U, s.size());
1051  EXPECT_EQ(kArmMov, s[0]->arch_opcode());
1052  EXPECT_EQ(shift.r_mode, s[0]->addressing_mode());
1053  EXPECT_EQ(2U, s[0]->InputCount());
1054  EXPECT_EQ(1U, s[0]->OutputCount());
1055}
1056
1057
1058TEST_P(InstructionSelectorShiftTest, Immediate) {
1059  const Shift shift = GetParam();
1060  TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) {
1061    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
1062    m.Return((m.*shift.constructor)(m.Parameter(0), m.Int32Constant(imm)));
1063    Stream s = m.Build();
1064    ASSERT_EQ(1U, s.size());
1065    EXPECT_EQ(kArmMov, s[0]->arch_opcode());
1066    EXPECT_EQ(shift.i_mode, s[0]->addressing_mode());
1067    ASSERT_EQ(2U, s[0]->InputCount());
1068    EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
1069    EXPECT_EQ(1U, s[0]->OutputCount());
1070  }
1071}
1072
1073
1074TEST_P(InstructionSelectorShiftTest, Word32EqualWithParameter) {
1075  const Shift shift = GetParam();
1076  {
1077    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
1078                    MachineType::Int32(), MachineType::Int32());
1079    m.Return(
1080        m.Word32Equal(m.Parameter(0),
1081                      (m.*shift.constructor)(m.Parameter(1), m.Parameter(2))));
1082    Stream s = m.Build();
1083    ASSERT_EQ(1U, s.size());
1084    EXPECT_EQ(kArmCmp, s[0]->arch_opcode());
1085    EXPECT_EQ(shift.r_mode, s[0]->addressing_mode());
1086    EXPECT_EQ(3U, s[0]->InputCount());
1087    EXPECT_EQ(1U, s[0]->OutputCount());
1088    EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1089    EXPECT_EQ(kEqual, s[0]->flags_condition());
1090  }
1091  {
1092    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
1093                    MachineType::Int32(), MachineType::Int32());
1094    m.Return(
1095        m.Word32Equal((m.*shift.constructor)(m.Parameter(1), m.Parameter(2)),
1096                      m.Parameter(0)));
1097    Stream s = m.Build();
1098    ASSERT_EQ(1U, s.size());
1099    EXPECT_EQ(kArmCmp, s[0]->arch_opcode());
1100    EXPECT_EQ(shift.r_mode, s[0]->addressing_mode());
1101    EXPECT_EQ(3U, s[0]->InputCount());
1102    EXPECT_EQ(1U, s[0]->OutputCount());
1103    EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1104    EXPECT_EQ(kEqual, s[0]->flags_condition());
1105  }
1106}
1107
1108
1109TEST_P(InstructionSelectorShiftTest, Word32EqualWithParameterAndImmediate) {
1110  const Shift shift = GetParam();
1111  TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) {
1112    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
1113                    MachineType::Int32());
1114    m.Return(m.Word32Equal(
1115        (m.*shift.constructor)(m.Parameter(1), m.Int32Constant(imm)),
1116        m.Parameter(0)));
1117    Stream s = m.Build();
1118    ASSERT_EQ(1U, s.size());
1119    EXPECT_EQ(kArmCmp, s[0]->arch_opcode());
1120    EXPECT_EQ(shift.i_mode, s[0]->addressing_mode());
1121    ASSERT_EQ(3U, s[0]->InputCount());
1122    EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2)));
1123    EXPECT_EQ(1U, s[0]->OutputCount());
1124    EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1125    EXPECT_EQ(kEqual, s[0]->flags_condition());
1126  }
1127  TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) {
1128    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
1129                    MachineType::Int32());
1130    m.Return(m.Word32Equal(
1131        m.Parameter(0),
1132        (m.*shift.constructor)(m.Parameter(1), m.Int32Constant(imm))));
1133    Stream s = m.Build();
1134    ASSERT_EQ(1U, s.size());
1135    EXPECT_EQ(kArmCmp, s[0]->arch_opcode());
1136    EXPECT_EQ(shift.i_mode, s[0]->addressing_mode());
1137    ASSERT_EQ(3U, s[0]->InputCount());
1138    EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2)));
1139    EXPECT_EQ(1U, s[0]->OutputCount());
1140    EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1141    EXPECT_EQ(kEqual, s[0]->flags_condition());
1142  }
1143}
1144
1145
1146TEST_P(InstructionSelectorShiftTest, Word32EqualToZeroWithParameters) {
1147  const Shift shift = GetParam();
1148  StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
1149                  MachineType::Int32());
1150  m.Return(
1151      m.Word32Equal(m.Int32Constant(0),
1152                    (m.*shift.constructor)(m.Parameter(0), m.Parameter(1))));
1153  Stream s = m.Build();
1154  ASSERT_EQ(1U, s.size());
1155  EXPECT_EQ(kArmMov, s[0]->arch_opcode());
1156  EXPECT_EQ(shift.r_mode, s[0]->addressing_mode());
1157  EXPECT_EQ(2U, s[0]->InputCount());
1158  EXPECT_EQ(2U, s[0]->OutputCount());
1159  EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1160  EXPECT_EQ(kEqual, s[0]->flags_condition());
1161}
1162
1163
1164TEST_P(InstructionSelectorShiftTest, Word32EqualToZeroWithImmediate) {
1165  const Shift shift = GetParam();
1166  TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) {
1167    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
1168                    MachineType::Int32());
1169    m.Return(m.Word32Equal(
1170        m.Int32Constant(0),
1171        (m.*shift.constructor)(m.Parameter(0), m.Int32Constant(imm))));
1172    Stream s = m.Build();
1173    ASSERT_EQ(1U, s.size());
1174    EXPECT_EQ(kArmMov, s[0]->arch_opcode());
1175    EXPECT_EQ(shift.i_mode, s[0]->addressing_mode());
1176    ASSERT_EQ(2U, s[0]->InputCount());
1177    EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
1178    EXPECT_EQ(2U, s[0]->OutputCount());
1179    EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1180    EXPECT_EQ(kEqual, s[0]->flags_condition());
1181  }
1182}
1183
1184
1185TEST_P(InstructionSelectorShiftTest, Word32NotWithParameters) {
1186  const Shift shift = GetParam();
1187  StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
1188                  MachineType::Int32());
1189  m.Return(m.Word32Not((m.*shift.constructor)(m.Parameter(0), m.Parameter(1))));
1190  Stream s = m.Build();
1191  ASSERT_EQ(1U, s.size());
1192  EXPECT_EQ(kArmMvn, s[0]->arch_opcode());
1193  EXPECT_EQ(shift.r_mode, s[0]->addressing_mode());
1194  EXPECT_EQ(2U, s[0]->InputCount());
1195  EXPECT_EQ(1U, s[0]->OutputCount());
1196}
1197
1198
1199TEST_P(InstructionSelectorShiftTest, Word32NotWithImmediate) {
1200  const Shift shift = GetParam();
1201  TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) {
1202    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
1203    m.Return(m.Word32Not(
1204        (m.*shift.constructor)(m.Parameter(0), m.Int32Constant(imm))));
1205    Stream s = m.Build();
1206    ASSERT_EQ(1U, s.size());
1207    EXPECT_EQ(kArmMvn, s[0]->arch_opcode());
1208    EXPECT_EQ(shift.i_mode, s[0]->addressing_mode());
1209    ASSERT_EQ(2U, s[0]->InputCount());
1210    EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
1211    EXPECT_EQ(1U, s[0]->OutputCount());
1212  }
1213}
1214
1215
1216TEST_P(InstructionSelectorShiftTest, Word32AndWithWord32NotWithParameters) {
1217  const Shift shift = GetParam();
1218  StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
1219                  MachineType::Int32(), MachineType::Int32());
1220  m.Return(m.Word32And(m.Parameter(0), m.Word32Not((m.*shift.constructor)(
1221                                           m.Parameter(1), m.Parameter(2)))));
1222  Stream s = m.Build();
1223  ASSERT_EQ(1U, s.size());
1224  EXPECT_EQ(kArmBic, s[0]->arch_opcode());
1225  EXPECT_EQ(shift.r_mode, s[0]->addressing_mode());
1226  EXPECT_EQ(3U, s[0]->InputCount());
1227  EXPECT_EQ(1U, s[0]->OutputCount());
1228}
1229
1230
1231TEST_P(InstructionSelectorShiftTest, Word32AndWithWord32NotWithImmediate) {
1232  const Shift shift = GetParam();
1233  TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) {
1234    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
1235                    MachineType::Int32());
1236    m.Return(m.Word32And(m.Parameter(0),
1237                         m.Word32Not((m.*shift.constructor)(
1238                             m.Parameter(1), m.Int32Constant(imm)))));
1239    Stream s = m.Build();
1240    ASSERT_EQ(1U, s.size());
1241    EXPECT_EQ(kArmBic, s[0]->arch_opcode());
1242    EXPECT_EQ(shift.i_mode, s[0]->addressing_mode());
1243    ASSERT_EQ(3U, s[0]->InputCount());
1244    EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2)));
1245    EXPECT_EQ(1U, s[0]->OutputCount());
1246  }
1247}
1248
1249
1250INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorShiftTest,
1251                        ::testing::ValuesIn(kShifts));
1252
1253
1254// -----------------------------------------------------------------------------
1255// Memory access instructions.
1256
1257
1258namespace {
1259
1260struct MemoryAccess {
1261  MachineType type;
1262  ArchOpcode ldr_opcode;
1263  ArchOpcode str_opcode;
1264  bool (InstructionSelectorTest::Stream::*val_predicate)(
1265      const InstructionOperand*) const;
1266  const int32_t immediates[40];
1267};
1268
1269
1270std::ostream& operator<<(std::ostream& os, const MemoryAccess& memacc) {
1271  return os << memacc.type;
1272}
1273
1274
1275const MemoryAccess kMemoryAccesses[] = {
1276    {MachineType::Int8(),
1277     kArmLdrsb,
1278     kArmStrb,
1279     &InstructionSelectorTest::Stream::IsInteger,
1280     {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89,
1281      -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109,
1282      115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}},
1283    {MachineType::Uint8(),
1284     kArmLdrb,
1285     kArmStrb,
1286     &InstructionSelectorTest::Stream::IsInteger,
1287     {-4095, -3914, -3536, -3234, -3185, -3169, -1073, -990, -859, -720, -434,
1288      -127, -124, -122, -105, -91, -86, -64, -55, -53, -30, -10, -3, 0, 20, 28,
1289      39, 58, 64, 73, 75, 100, 108, 121, 686, 963, 1363, 2759, 3449, 4095}},
1290    {MachineType::Int16(),
1291     kArmLdrsh,
1292     kArmStrh,
1293     &InstructionSelectorTest::Stream::IsInteger,
1294     {-255, -251, -232, -220, -144, -138, -130, -126, -116, -115, -102, -101,
1295      -98, -69, -59, -56, -39, -35, -23, -19, -7, 0, 22, 26, 37, 68, 83, 87, 98,
1296      102, 108, 111, 117, 171, 195, 203, 204, 245, 246, 255}},
1297    {MachineType::Uint16(),
1298     kArmLdrh,
1299     kArmStrh,
1300     &InstructionSelectorTest::Stream::IsInteger,
1301     {-255, -230, -201, -172, -125, -119, -118, -105, -98, -79, -54, -42, -41,
1302      -32, -12, -11, -5, -4, 0, 5, 9, 25, 28, 51, 58, 60, 89, 104, 108, 109,
1303      114, 116, 120, 138, 150, 161, 166, 172, 228, 255}},
1304    {MachineType::Int32(),
1305     kArmLdr,
1306     kArmStr,
1307     &InstructionSelectorTest::Stream::IsInteger,
1308     {-4095, -1898, -1685, -1562, -1408, -1313, -344, -128, -116, -100, -92,
1309      -80, -72, -71, -56, -25, -21, -11, -9, 0, 3, 5, 27, 28, 42, 52, 63, 88,
1310      93, 97, 125, 846, 1037, 2102, 2403, 2597, 2632, 2997, 3935, 4095}},
1311    {MachineType::Float32(),
1312     kArmVldrF32,
1313     kArmVstrF32,
1314     &InstructionSelectorTest::Stream::IsDouble,
1315     {-1020, -928, -896, -772, -728, -680, -660, -488, -372, -112, -100, -92,
1316      -84, -80, -72, -64, -60, -56, -52, -48, -36, -32, -20, -8, -4, 0, 8, 20,
1317      24, 40, 64, 112, 204, 388, 516, 852, 856, 976, 988, 1020}},
1318    {MachineType::Float64(),
1319     kArmVldrF64,
1320     kArmVstrF64,
1321     &InstructionSelectorTest::Stream::IsDouble,
1322     {-1020, -948, -796, -696, -612, -364, -320, -308, -128, -112, -108, -104,
1323      -96, -84, -80, -56, -48, -40, -20, 0, 24, 28, 36, 48, 64, 84, 96, 100,
1324      108, 116, 120, 140, 156, 408, 432, 444, 772, 832, 940, 1020}}};
1325
1326}  // namespace
1327
1328
1329typedef InstructionSelectorTestWithParam<MemoryAccess>
1330    InstructionSelectorMemoryAccessTest;
1331
1332
1333TEST_P(InstructionSelectorMemoryAccessTest, LoadWithParameters) {
1334  const MemoryAccess memacc = GetParam();
1335  StreamBuilder m(this, memacc.type, MachineType::Pointer(),
1336                  MachineType::Int32());
1337  m.Return(m.Load(memacc.type, m.Parameter(0), m.Parameter(1)));
1338  Stream s = m.Build();
1339  ASSERT_EQ(1U, s.size());
1340  EXPECT_EQ(memacc.ldr_opcode, s[0]->arch_opcode());
1341  EXPECT_EQ(kMode_Offset_RR, s[0]->addressing_mode());
1342  EXPECT_EQ(2U, s[0]->InputCount());
1343  ASSERT_EQ(1U, s[0]->OutputCount());
1344  EXPECT_TRUE((s.*memacc.val_predicate)(s[0]->Output()));
1345}
1346
1347
1348TEST_P(InstructionSelectorMemoryAccessTest, LoadWithImmediateIndex) {
1349  const MemoryAccess memacc = GetParam();
1350  TRACED_FOREACH(int32_t, index, memacc.immediates) {
1351    StreamBuilder m(this, memacc.type, MachineType::Pointer());
1352    m.Return(m.Load(memacc.type, m.Parameter(0), m.Int32Constant(index)));
1353    Stream s = m.Build();
1354    ASSERT_EQ(1U, s.size());
1355    EXPECT_EQ(memacc.ldr_opcode, s[0]->arch_opcode());
1356    EXPECT_EQ(kMode_Offset_RI, s[0]->addressing_mode());
1357    ASSERT_EQ(2U, s[0]->InputCount());
1358    ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
1359    EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1)));
1360    ASSERT_EQ(1U, s[0]->OutputCount());
1361    EXPECT_TRUE((s.*memacc.val_predicate)(s[0]->Output()));
1362  }
1363}
1364
1365
1366TEST_P(InstructionSelectorMemoryAccessTest, StoreWithParameters) {
1367  const MemoryAccess memacc = GetParam();
1368  StreamBuilder m(this, MachineType::Int32(), MachineType::Pointer(),
1369                  MachineType::Int32(), memacc.type);
1370  m.Store(memacc.type.representation(), m.Parameter(0), m.Parameter(1),
1371          m.Parameter(2), kNoWriteBarrier);
1372  m.Return(m.Int32Constant(0));
1373  Stream s = m.Build();
1374  ASSERT_EQ(1U, s.size());
1375  EXPECT_EQ(memacc.str_opcode, s[0]->arch_opcode());
1376  EXPECT_EQ(kMode_Offset_RR, s[0]->addressing_mode());
1377  EXPECT_EQ(3U, s[0]->InputCount());
1378  EXPECT_EQ(0U, s[0]->OutputCount());
1379}
1380
1381
1382TEST_P(InstructionSelectorMemoryAccessTest, StoreWithImmediateIndex) {
1383  const MemoryAccess memacc = GetParam();
1384  TRACED_FOREACH(int32_t, index, memacc.immediates) {
1385    StreamBuilder m(this, MachineType::Int32(), MachineType::Pointer(),
1386                    memacc.type);
1387    m.Store(memacc.type.representation(), m.Parameter(0),
1388            m.Int32Constant(index), m.Parameter(1), kNoWriteBarrier);
1389    m.Return(m.Int32Constant(0));
1390    Stream s = m.Build();
1391    ASSERT_EQ(1U, s.size());
1392    EXPECT_EQ(memacc.str_opcode, s[0]->arch_opcode());
1393    EXPECT_EQ(kMode_Offset_RI, s[0]->addressing_mode());
1394    ASSERT_EQ(3U, s[0]->InputCount());
1395    ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(2)->kind());
1396    EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(2)));
1397    EXPECT_EQ(0U, s[0]->OutputCount());
1398  }
1399}
1400
1401
1402INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1403                        InstructionSelectorMemoryAccessTest,
1404                        ::testing::ValuesIn(kMemoryAccesses));
1405
1406TEST_F(InstructionSelectorMemoryAccessTest, LoadWithShiftedIndex) {
1407  TRACED_FORRANGE(int, immediate_shift, 1, 31) {
1408    StreamBuilder m(this, MachineType::Int32(), MachineType::Pointer(),
1409                    MachineType::Int32());
1410    Node* const index =
1411        m.Word32Shl(m.Parameter(1), m.Int32Constant(immediate_shift));
1412    m.Return(m.Load(MachineType::Int32(), m.Parameter(0), index));
1413    Stream s = m.Build();
1414    ASSERT_EQ(1U, s.size());
1415    EXPECT_EQ(kArmLdr, s[0]->arch_opcode());
1416    EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
1417    EXPECT_EQ(3U, s[0]->InputCount());
1418    EXPECT_EQ(1U, s[0]->OutputCount());
1419  }
1420}
1421
1422TEST_F(InstructionSelectorMemoryAccessTest, StoreWithShiftedIndex) {
1423  TRACED_FORRANGE(int, immediate_shift, 1, 31) {
1424    StreamBuilder m(this, MachineType::Int32(), MachineType::Pointer(),
1425                    MachineType::Int32(), MachineType::Int32());
1426    Node* const index =
1427        m.Word32Shl(m.Parameter(1), m.Int32Constant(immediate_shift));
1428    m.Store(MachineRepresentation::kWord32, m.Parameter(0), index,
1429            m.Parameter(2), kNoWriteBarrier);
1430    m.Return(m.Int32Constant(0));
1431    Stream s = m.Build();
1432    ASSERT_EQ(1U, s.size());
1433    EXPECT_EQ(kArmStr, s[0]->arch_opcode());
1434    EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
1435    EXPECT_EQ(4U, s[0]->InputCount());
1436    EXPECT_EQ(0U, s[0]->OutputCount());
1437  }
1438}
1439
1440// -----------------------------------------------------------------------------
1441// Conversions.
1442
1443
1444TEST_F(InstructionSelectorTest, ChangeFloat32ToFloat64WithParameter) {
1445  StreamBuilder m(this, MachineType::Float64(), MachineType::Float32());
1446  m.Return(m.ChangeFloat32ToFloat64(m.Parameter(0)));
1447  Stream s = m.Build();
1448  ASSERT_EQ(1U, s.size());
1449  EXPECT_EQ(kArmVcvtF64F32, s[0]->arch_opcode());
1450  EXPECT_EQ(1U, s[0]->InputCount());
1451  EXPECT_EQ(1U, s[0]->OutputCount());
1452}
1453
1454
1455TEST_F(InstructionSelectorTest, TruncateFloat64ToFloat32WithParameter) {
1456  StreamBuilder m(this, MachineType::Float32(), MachineType::Float64());
1457  m.Return(m.TruncateFloat64ToFloat32(m.Parameter(0)));
1458  Stream s = m.Build();
1459  ASSERT_EQ(1U, s.size());
1460  EXPECT_EQ(kArmVcvtF32F64, s[0]->arch_opcode());
1461  EXPECT_EQ(1U, s[0]->InputCount());
1462  EXPECT_EQ(1U, s[0]->OutputCount());
1463}
1464
1465
1466// -----------------------------------------------------------------------------
1467// Comparisons.
1468
1469
1470namespace {
1471
1472struct Comparison {
1473  Constructor constructor;
1474  const char* constructor_name;
1475  FlagsCondition flags_condition;
1476  FlagsCondition negated_flags_condition;
1477  FlagsCondition commuted_flags_condition;
1478};
1479
1480
1481std::ostream& operator<<(std::ostream& os, const Comparison& cmp) {
1482  return os << cmp.constructor_name;
1483}
1484
1485
1486const Comparison kComparisons[] = {
1487    {&RawMachineAssembler::Word32Equal, "Word32Equal", kEqual, kNotEqual,
1488     kEqual},
1489    {&RawMachineAssembler::Int32LessThan, "Int32LessThan", kSignedLessThan,
1490     kSignedGreaterThanOrEqual, kSignedGreaterThan},
1491    {&RawMachineAssembler::Int32LessThanOrEqual, "Int32LessThanOrEqual",
1492     kSignedLessThanOrEqual, kSignedGreaterThan, kSignedGreaterThanOrEqual},
1493    {&RawMachineAssembler::Uint32LessThan, "Uint32LessThan", kUnsignedLessThan,
1494     kUnsignedGreaterThanOrEqual, kUnsignedGreaterThan},
1495    {&RawMachineAssembler::Uint32LessThanOrEqual, "Uint32LessThanOrEqual",
1496     kUnsignedLessThanOrEqual, kUnsignedGreaterThan,
1497     kUnsignedGreaterThanOrEqual}};
1498
1499}  // namespace
1500
1501
1502typedef InstructionSelectorTestWithParam<Comparison>
1503    InstructionSelectorComparisonTest;
1504
1505
1506TEST_P(InstructionSelectorComparisonTest, Parameters) {
1507  const Comparison& cmp = GetParam();
1508  StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
1509                  MachineType::Int32());
1510  Node* const p0 = m.Parameter(0);
1511  Node* const p1 = m.Parameter(1);
1512  Node* const r = (m.*cmp.constructor)(p0, p1);
1513  m.Return(r);
1514  Stream const s = m.Build();
1515  ASSERT_EQ(1U, s.size());
1516  EXPECT_EQ(kArmCmp, s[0]->arch_opcode());
1517  EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
1518  ASSERT_EQ(2U, s[0]->InputCount());
1519  EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1520  EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
1521  ASSERT_EQ(1U, s[0]->OutputCount());
1522  EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->OutputAt(0)));
1523  EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1524  EXPECT_EQ(cmp.flags_condition, s[0]->flags_condition());
1525}
1526
1527
1528TEST_P(InstructionSelectorComparisonTest, Word32EqualWithZero) {
1529  {
1530    const Comparison& cmp = GetParam();
1531    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
1532                    MachineType::Int32());
1533    Node* const p0 = m.Parameter(0);
1534    Node* const p1 = m.Parameter(1);
1535    Node* const r =
1536        m.Word32Equal((m.*cmp.constructor)(p0, p1), m.Int32Constant(0));
1537    m.Return(r);
1538    Stream const s = m.Build();
1539    ASSERT_EQ(1U, s.size());
1540    EXPECT_EQ(kArmCmp, s[0]->arch_opcode());
1541    EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
1542    ASSERT_EQ(2U, s[0]->InputCount());
1543    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1544    EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
1545    ASSERT_EQ(1U, s[0]->OutputCount());
1546    EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->OutputAt(0)));
1547    EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1548    EXPECT_EQ(cmp.negated_flags_condition, s[0]->flags_condition());
1549  }
1550  {
1551    const Comparison& cmp = GetParam();
1552    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
1553                    MachineType::Int32());
1554    Node* const p0 = m.Parameter(0);
1555    Node* const p1 = m.Parameter(1);
1556    Node* const r =
1557        m.Word32Equal(m.Int32Constant(0), (m.*cmp.constructor)(p0, p1));
1558    m.Return(r);
1559    Stream const s = m.Build();
1560    ASSERT_EQ(1U, s.size());
1561    EXPECT_EQ(kArmCmp, s[0]->arch_opcode());
1562    EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
1563    ASSERT_EQ(2U, s[0]->InputCount());
1564    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1565    EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
1566    ASSERT_EQ(1U, s[0]->OutputCount());
1567    EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->OutputAt(0)));
1568    EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1569    EXPECT_EQ(cmp.negated_flags_condition, s[0]->flags_condition());
1570  }
1571}
1572
1573
1574INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1575                        InstructionSelectorComparisonTest,
1576                        ::testing::ValuesIn(kComparisons));
1577
1578
1579// -----------------------------------------------------------------------------
1580// Floating point comparisons.
1581
1582
1583namespace {
1584
1585const Comparison kF32Comparisons[] = {
1586    {&RawMachineAssembler::Float32Equal, "Float32Equal", kEqual, kNotEqual,
1587     kEqual},
1588    {&RawMachineAssembler::Float32LessThan, "Float32LessThan",
1589     kFloatLessThan, kFloatGreaterThanOrEqualOrUnordered, kFloatGreaterThan},
1590    {&RawMachineAssembler::Float32LessThanOrEqual, "Float32LessThanOrEqual",
1591     kFloatLessThanOrEqual, kFloatGreaterThanOrUnordered,
1592     kFloatGreaterThanOrEqual}};
1593
1594}  // namespace
1595
1596typedef InstructionSelectorTestWithParam<Comparison>
1597    InstructionSelectorF32ComparisonTest;
1598
1599
1600TEST_P(InstructionSelectorF32ComparisonTest, WithParameters) {
1601  const Comparison& cmp = GetParam();
1602  StreamBuilder m(this, MachineType::Int32(), MachineType::Float32(),
1603                  MachineType::Float32());
1604  m.Return((m.*cmp.constructor)(m.Parameter(0), m.Parameter(1)));
1605  Stream const s = m.Build();
1606  ASSERT_EQ(1U, s.size());
1607  EXPECT_EQ(kArmVcmpF32, s[0]->arch_opcode());
1608  ASSERT_EQ(2U, s[0]->InputCount());
1609  ASSERT_EQ(1U, s[0]->OutputCount());
1610  EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1611  EXPECT_EQ(cmp.flags_condition, s[0]->flags_condition());
1612}
1613
1614
1615TEST_P(InstructionSelectorF32ComparisonTest, NegatedWithParameters) {
1616  const Comparison& cmp = GetParam();
1617  StreamBuilder m(this, MachineType::Int32(), MachineType::Float32(),
1618                  MachineType::Float32());
1619  m.Return(
1620      m.Word32BinaryNot((m.*cmp.constructor)(m.Parameter(0), m.Parameter(1))));
1621  Stream const s = m.Build();
1622  ASSERT_EQ(1U, s.size());
1623  EXPECT_EQ(kArmVcmpF32, s[0]->arch_opcode());
1624  ASSERT_EQ(2U, s[0]->InputCount());
1625  ASSERT_EQ(1U, s[0]->OutputCount());
1626  EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1627  EXPECT_EQ(cmp.negated_flags_condition, s[0]->flags_condition());
1628}
1629
1630
1631TEST_P(InstructionSelectorF32ComparisonTest, WithImmediateZeroOnRight) {
1632  const Comparison& cmp = GetParam();
1633  StreamBuilder m(this, MachineType::Int32(), MachineType::Float32());
1634  m.Return((m.*cmp.constructor)(m.Parameter(0), m.Float32Constant(0.0)));
1635  Stream const s = m.Build();
1636  ASSERT_EQ(1U, s.size());
1637  EXPECT_EQ(kArmVcmpF32, s[0]->arch_opcode());
1638  ASSERT_EQ(2U, s[0]->InputCount());
1639  EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
1640  ASSERT_EQ(1U, s[0]->OutputCount());
1641  EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1642  EXPECT_EQ(cmp.flags_condition, s[0]->flags_condition());
1643}
1644
1645
1646TEST_P(InstructionSelectorF32ComparisonTest, WithImmediateZeroOnLeft) {
1647  const Comparison& cmp = GetParam();
1648  StreamBuilder m(this, MachineType::Int32(), MachineType::Float32());
1649  m.Return((m.*cmp.constructor)(m.Float32Constant(0.0f), m.Parameter(0)));
1650  Stream const s = m.Build();
1651  ASSERT_EQ(1U, s.size());
1652  EXPECT_EQ(kArmVcmpF32, s[0]->arch_opcode());
1653  ASSERT_EQ(2U, s[0]->InputCount());
1654  EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
1655  ASSERT_EQ(1U, s[0]->OutputCount());
1656  EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1657  EXPECT_EQ(cmp.commuted_flags_condition, s[0]->flags_condition());
1658}
1659
1660
1661INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1662                        InstructionSelectorF32ComparisonTest,
1663                        ::testing::ValuesIn(kF32Comparisons));
1664
1665
1666namespace {
1667
1668const Comparison kF64Comparisons[] = {
1669    {&RawMachineAssembler::Float64Equal, "Float64Equal", kEqual, kNotEqual,
1670     kEqual},
1671    {&RawMachineAssembler::Float64LessThan, "Float64LessThan",
1672     kFloatLessThan, kFloatGreaterThanOrEqualOrUnordered, kFloatGreaterThan},
1673    {&RawMachineAssembler::Float64LessThanOrEqual, "Float64LessThanOrEqual",
1674     kFloatLessThanOrEqual, kFloatGreaterThanOrUnordered,
1675     kFloatGreaterThanOrEqual}};
1676
1677}  // namespace
1678
1679typedef InstructionSelectorTestWithParam<Comparison>
1680    InstructionSelectorF64ComparisonTest;
1681
1682
1683TEST_P(InstructionSelectorF64ComparisonTest, WithParameters) {
1684  const Comparison& cmp = GetParam();
1685  StreamBuilder m(this, MachineType::Int32(), MachineType::Float64(),
1686                  MachineType::Float64());
1687  m.Return((m.*cmp.constructor)(m.Parameter(0), m.Parameter(1)));
1688  Stream const s = m.Build();
1689  ASSERT_EQ(1U, s.size());
1690  EXPECT_EQ(kArmVcmpF64, s[0]->arch_opcode());
1691  ASSERT_EQ(2U, s[0]->InputCount());
1692  ASSERT_EQ(1U, s[0]->OutputCount());
1693  EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1694  EXPECT_EQ(cmp.flags_condition, s[0]->flags_condition());
1695}
1696
1697
1698TEST_P(InstructionSelectorF64ComparisonTest, NegatedWithParameters) {
1699  const Comparison& cmp = GetParam();
1700  StreamBuilder m(this, MachineType::Int32(), MachineType::Float64(),
1701                  MachineType::Float64());
1702  m.Return(
1703      m.Word32BinaryNot((m.*cmp.constructor)(m.Parameter(0), m.Parameter(1))));
1704  Stream const s = m.Build();
1705  ASSERT_EQ(1U, s.size());
1706  EXPECT_EQ(kArmVcmpF64, s[0]->arch_opcode());
1707  ASSERT_EQ(2U, s[0]->InputCount());
1708  ASSERT_EQ(1U, s[0]->OutputCount());
1709  EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1710  EXPECT_EQ(cmp.negated_flags_condition, s[0]->flags_condition());
1711}
1712
1713
1714TEST_P(InstructionSelectorF64ComparisonTest, WithImmediateZeroOnRight) {
1715  const Comparison& cmp = GetParam();
1716  StreamBuilder m(this, MachineType::Int32(), MachineType::Float64());
1717  m.Return((m.*cmp.constructor)(m.Parameter(0), m.Float64Constant(0.0)));
1718  Stream const s = m.Build();
1719  ASSERT_EQ(1U, s.size());
1720  EXPECT_EQ(kArmVcmpF64, s[0]->arch_opcode());
1721  ASSERT_EQ(2U, s[0]->InputCount());
1722  EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
1723  ASSERT_EQ(1U, s[0]->OutputCount());
1724  EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1725  EXPECT_EQ(cmp.flags_condition, s[0]->flags_condition());
1726}
1727
1728
1729TEST_P(InstructionSelectorF64ComparisonTest, WithImmediateZeroOnLeft) {
1730  const Comparison& cmp = GetParam();
1731  StreamBuilder m(this, MachineType::Int32(), MachineType::Float64());
1732  m.Return((m.*cmp.constructor)(m.Float64Constant(0.0), m.Parameter(0)));
1733  Stream const s = m.Build();
1734  ASSERT_EQ(1U, s.size());
1735  EXPECT_EQ(kArmVcmpF64, s[0]->arch_opcode());
1736  ASSERT_EQ(2U, s[0]->InputCount());
1737  EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
1738  ASSERT_EQ(1U, s[0]->OutputCount());
1739  EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1740  EXPECT_EQ(cmp.commuted_flags_condition, s[0]->flags_condition());
1741}
1742
1743
1744INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1745                        InstructionSelectorF64ComparisonTest,
1746                        ::testing::ValuesIn(kF64Comparisons));
1747
1748
1749// -----------------------------------------------------------------------------
1750// Floating point arithmetic.
1751
1752
1753typedef InstructionSelectorTestWithParam<FAI> InstructionSelectorFAITest;
1754
1755
1756TEST_P(InstructionSelectorFAITest, Parameters) {
1757  const FAI& fai = GetParam();
1758  StreamBuilder m(this, fai.machine_type, fai.machine_type, fai.machine_type);
1759  Node* const p0 = m.Parameter(0);
1760  Node* const p1 = m.Parameter(1);
1761  Node* const r = (m.*fai.constructor)(p0, p1);
1762  m.Return(r);
1763  Stream const s = m.Build();
1764  ASSERT_EQ(1U, s.size());
1765  EXPECT_EQ(fai.arch_opcode, s[0]->arch_opcode());
1766  EXPECT_EQ(kMode_None, s[0]->addressing_mode());
1767  ASSERT_EQ(2U, s[0]->InputCount());
1768  EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1769  EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
1770  ASSERT_EQ(1U, s[0]->OutputCount());
1771  EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->OutputAt(0)));
1772  EXPECT_EQ(kFlags_none, s[0]->flags_mode());
1773}
1774
1775
1776INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorFAITest,
1777                        ::testing::ValuesIn(kFAIs));
1778
1779
1780TEST_F(InstructionSelectorTest, Float32Abs) {
1781  StreamBuilder m(this, MachineType::Float32(), MachineType::Float32());
1782  Node* const p0 = m.Parameter(0);
1783  Node* const n = m.Float32Abs(p0);
1784  m.Return(n);
1785  Stream s = m.Build();
1786  ASSERT_EQ(1U, s.size());
1787  EXPECT_EQ(kArmVabsF32, s[0]->arch_opcode());
1788  ASSERT_EQ(1U, s[0]->InputCount());
1789  EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1790  ASSERT_EQ(1U, s[0]->OutputCount());
1791  EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1792}
1793
1794
1795TEST_F(InstructionSelectorTest, Float64Abs) {
1796  StreamBuilder m(this, MachineType::Float64(), MachineType::Float64());
1797  Node* const p0 = m.Parameter(0);
1798  Node* const n = m.Float64Abs(p0);
1799  m.Return(n);
1800  Stream s = m.Build();
1801  ASSERT_EQ(1U, s.size());
1802  EXPECT_EQ(kArmVabsF64, s[0]->arch_opcode());
1803  ASSERT_EQ(1U, s[0]->InputCount());
1804  EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1805  ASSERT_EQ(1U, s[0]->OutputCount());
1806  EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1807}
1808
1809
1810TEST_F(InstructionSelectorTest, Float32AddWithFloat32Mul) {
1811  {
1812    StreamBuilder m(this, MachineType::Float32(), MachineType::Float32(),
1813                    MachineType::Float32(), MachineType::Float32());
1814    Node* const p0 = m.Parameter(0);
1815    Node* const p1 = m.Parameter(1);
1816    Node* const p2 = m.Parameter(2);
1817    Node* const n = m.Float32Add(m.Float32Mul(p0, p1), p2);
1818    m.Return(n);
1819    Stream s = m.Build();
1820    ASSERT_EQ(1U, s.size());
1821    EXPECT_EQ(kArmVmlaF32, s[0]->arch_opcode());
1822    ASSERT_EQ(3U, s[0]->InputCount());
1823    EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(0)));
1824    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1)));
1825    EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(2)));
1826    ASSERT_EQ(1U, s[0]->OutputCount());
1827    EXPECT_TRUE(
1828        UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy());
1829    EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1830    EXPECT_EQ(kFlags_none, s[0]->flags_mode());
1831  }
1832  {
1833    StreamBuilder m(this, MachineType::Float32(), MachineType::Float32(),
1834                    MachineType::Float32(), MachineType::Float32());
1835    Node* const p0 = m.Parameter(0);
1836    Node* const p1 = m.Parameter(1);
1837    Node* const p2 = m.Parameter(2);
1838    Node* const n = m.Float32Add(p0, m.Float32Mul(p1, p2));
1839    m.Return(n);
1840    Stream s = m.Build();
1841    ASSERT_EQ(1U, s.size());
1842    EXPECT_EQ(kArmVmlaF32, s[0]->arch_opcode());
1843    ASSERT_EQ(3U, s[0]->InputCount());
1844    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1845    EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
1846    EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(2)));
1847    ASSERT_EQ(1U, s[0]->OutputCount());
1848    EXPECT_TRUE(
1849        UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy());
1850    EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1851    EXPECT_EQ(kFlags_none, s[0]->flags_mode());
1852  }
1853}
1854
1855
1856TEST_F(InstructionSelectorTest, Float64AddWithFloat64Mul) {
1857  {
1858    StreamBuilder m(this, MachineType::Float64(), MachineType::Float64(),
1859                    MachineType::Float64(), MachineType::Float64());
1860    Node* const p0 = m.Parameter(0);
1861    Node* const p1 = m.Parameter(1);
1862    Node* const p2 = m.Parameter(2);
1863    Node* const n = m.Float64Add(m.Float64Mul(p0, p1), p2);
1864    m.Return(n);
1865    Stream s = m.Build();
1866    ASSERT_EQ(1U, s.size());
1867    EXPECT_EQ(kArmVmlaF64, s[0]->arch_opcode());
1868    ASSERT_EQ(3U, s[0]->InputCount());
1869    EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(0)));
1870    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1)));
1871    EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(2)));
1872    ASSERT_EQ(1U, s[0]->OutputCount());
1873    EXPECT_TRUE(
1874        UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy());
1875    EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1876    EXPECT_EQ(kFlags_none, s[0]->flags_mode());
1877  }
1878  {
1879    StreamBuilder m(this, MachineType::Float64(), MachineType::Float64(),
1880                    MachineType::Float64(), MachineType::Float64());
1881    Node* const p0 = m.Parameter(0);
1882    Node* const p1 = m.Parameter(1);
1883    Node* const p2 = m.Parameter(2);
1884    Node* const n = m.Float64Add(p0, m.Float64Mul(p1, p2));
1885    m.Return(n);
1886    Stream s = m.Build();
1887    ASSERT_EQ(1U, s.size());
1888    EXPECT_EQ(kArmVmlaF64, s[0]->arch_opcode());
1889    ASSERT_EQ(3U, s[0]->InputCount());
1890    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1891    EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
1892    EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(2)));
1893    ASSERT_EQ(1U, s[0]->OutputCount());
1894    EXPECT_TRUE(
1895        UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy());
1896    EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1897    EXPECT_EQ(kFlags_none, s[0]->flags_mode());
1898  }
1899}
1900
1901
1902TEST_F(InstructionSelectorTest, Float32SubWithMinusZero) {
1903  StreamBuilder m(this, MachineType::Float32(), MachineType::Float32());
1904  Node* const p0 = m.Parameter(0);
1905  Node* const n = m.Float32Sub(m.Float32Constant(-0.0f), p0);
1906  m.Return(n);
1907  Stream s = m.Build();
1908  ASSERT_EQ(1U, s.size());
1909  EXPECT_EQ(kArmVnegF32, s[0]->arch_opcode());
1910  ASSERT_EQ(1U, s[0]->InputCount());
1911  EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1912  ASSERT_EQ(1U, s[0]->OutputCount());
1913  EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1914}
1915
1916
1917TEST_F(InstructionSelectorTest, Float64SubWithMinusZero) {
1918  StreamBuilder m(this, MachineType::Float64(), MachineType::Float64());
1919  Node* const p0 = m.Parameter(0);
1920  Node* const n = m.Float64Sub(m.Float64Constant(-0.0), p0);
1921  m.Return(n);
1922  Stream s = m.Build();
1923  ASSERT_EQ(1U, s.size());
1924  EXPECT_EQ(kArmVnegF64, s[0]->arch_opcode());
1925  ASSERT_EQ(1U, s[0]->InputCount());
1926  EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1927  ASSERT_EQ(1U, s[0]->OutputCount());
1928  EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1929}
1930
1931
1932TEST_F(InstructionSelectorTest, Float32SubWithFloat32Mul) {
1933  StreamBuilder m(this, MachineType::Float32(), MachineType::Float32(),
1934                  MachineType::Float32(), MachineType::Float32());
1935  Node* const p0 = m.Parameter(0);
1936  Node* const p1 = m.Parameter(1);
1937  Node* const p2 = m.Parameter(2);
1938  Node* const n = m.Float32Sub(p0, m.Float32Mul(p1, p2));
1939  m.Return(n);
1940  Stream s = m.Build();
1941  ASSERT_EQ(1U, s.size());
1942  EXPECT_EQ(kArmVmlsF32, s[0]->arch_opcode());
1943  ASSERT_EQ(3U, s[0]->InputCount());
1944  EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1945  EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
1946  EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(2)));
1947  ASSERT_EQ(1U, s[0]->OutputCount());
1948  EXPECT_TRUE(UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy());
1949  EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1950  EXPECT_EQ(kFlags_none, s[0]->flags_mode());
1951}
1952
1953
1954TEST_F(InstructionSelectorTest, Float64SubWithFloat64Mul) {
1955  StreamBuilder m(this, MachineType::Float64(), MachineType::Float64(),
1956                  MachineType::Float64(), MachineType::Float64());
1957  Node* const p0 = m.Parameter(0);
1958  Node* const p1 = m.Parameter(1);
1959  Node* const p2 = m.Parameter(2);
1960  Node* const n = m.Float64Sub(p0, m.Float64Mul(p1, p2));
1961  m.Return(n);
1962  Stream s = m.Build();
1963  ASSERT_EQ(1U, s.size());
1964  EXPECT_EQ(kArmVmlsF64, s[0]->arch_opcode());
1965  ASSERT_EQ(3U, s[0]->InputCount());
1966  EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1967  EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
1968  EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(2)));
1969  ASSERT_EQ(1U, s[0]->OutputCount());
1970  EXPECT_TRUE(UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy());
1971  EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1972  EXPECT_EQ(kFlags_none, s[0]->flags_mode());
1973}
1974
1975
1976TEST_F(InstructionSelectorTest, Float32Sqrt) {
1977  StreamBuilder m(this, MachineType::Float32(), MachineType::Float32());
1978  Node* const p0 = m.Parameter(0);
1979  Node* const n = m.Float32Sqrt(p0);
1980  m.Return(n);
1981  Stream s = m.Build();
1982  ASSERT_EQ(1U, s.size());
1983  EXPECT_EQ(kArmVsqrtF32, s[0]->arch_opcode());
1984  ASSERT_EQ(1U, s[0]->InputCount());
1985  EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1986  ASSERT_EQ(1U, s[0]->OutputCount());
1987  EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1988  EXPECT_EQ(kFlags_none, s[0]->flags_mode());
1989}
1990
1991
1992TEST_F(InstructionSelectorTest, Float64Sqrt) {
1993  StreamBuilder m(this, MachineType::Float64(), MachineType::Float64());
1994  Node* const p0 = m.Parameter(0);
1995  Node* const n = m.Float64Sqrt(p0);
1996  m.Return(n);
1997  Stream s = m.Build();
1998  ASSERT_EQ(1U, s.size());
1999  EXPECT_EQ(kArmVsqrtF64, s[0]->arch_opcode());
2000  ASSERT_EQ(1U, s[0]->InputCount());
2001  EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
2002  ASSERT_EQ(1U, s[0]->OutputCount());
2003  EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
2004  EXPECT_EQ(kFlags_none, s[0]->flags_mode());
2005}
2006
2007
2008// -----------------------------------------------------------------------------
2009// Miscellaneous.
2010
2011
2012TEST_F(InstructionSelectorTest, Int32AddWithInt32Mul) {
2013  {
2014    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2015                    MachineType::Int32(), MachineType::Int32());
2016    Node* const p0 = m.Parameter(0);
2017    Node* const p1 = m.Parameter(1);
2018    Node* const p2 = m.Parameter(2);
2019    Node* const n = m.Int32Add(p0, m.Int32Mul(p1, p2));
2020    m.Return(n);
2021    Stream s = m.Build();
2022    ASSERT_EQ(1U, s.size());
2023    EXPECT_EQ(kArmMla, s[0]->arch_opcode());
2024    ASSERT_EQ(3U, s[0]->InputCount());
2025    EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(0)));
2026    EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(1)));
2027    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(2)));
2028    ASSERT_EQ(1U, s[0]->OutputCount());
2029    EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
2030  }
2031  {
2032    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2033                    MachineType::Int32(), MachineType::Int32());
2034    Node* const p0 = m.Parameter(0);
2035    Node* const p1 = m.Parameter(1);
2036    Node* const p2 = m.Parameter(2);
2037    Node* const n = m.Int32Add(m.Int32Mul(p1, p2), p0);
2038    m.Return(n);
2039    Stream s = m.Build();
2040    ASSERT_EQ(1U, s.size());
2041    EXPECT_EQ(kArmMla, s[0]->arch_opcode());
2042    ASSERT_EQ(3U, s[0]->InputCount());
2043    EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(0)));
2044    EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(1)));
2045    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(2)));
2046    ASSERT_EQ(1U, s[0]->OutputCount());
2047    EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
2048  }
2049}
2050
2051
2052TEST_F(InstructionSelectorTest, Int32AddWithInt32MulHigh) {
2053  {
2054    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2055                    MachineType::Int32(), MachineType::Int32());
2056    Node* const p0 = m.Parameter(0);
2057    Node* const p1 = m.Parameter(1);
2058    Node* const p2 = m.Parameter(2);
2059    Node* const n = m.Int32Add(p0, m.Int32MulHigh(p1, p2));
2060    m.Return(n);
2061    Stream s = m.Build();
2062    ASSERT_EQ(1U, s.size());
2063    EXPECT_EQ(kArmSmmla, s[0]->arch_opcode());
2064    ASSERT_EQ(3U, s[0]->InputCount());
2065    EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(0)));
2066    EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(1)));
2067    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(2)));
2068    ASSERT_EQ(1U, s[0]->OutputCount());
2069    EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
2070  }
2071  {
2072    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2073                    MachineType::Int32(), MachineType::Int32());
2074    Node* const p0 = m.Parameter(0);
2075    Node* const p1 = m.Parameter(1);
2076    Node* const p2 = m.Parameter(2);
2077    Node* const n = m.Int32Add(m.Int32MulHigh(p1, p2), p0);
2078    m.Return(n);
2079    Stream s = m.Build();
2080    ASSERT_EQ(1U, s.size());
2081    EXPECT_EQ(kArmSmmla, s[0]->arch_opcode());
2082    ASSERT_EQ(3U, s[0]->InputCount());
2083    EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(0)));
2084    EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(1)));
2085    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(2)));
2086    ASSERT_EQ(1U, s[0]->OutputCount());
2087    EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
2088  }
2089}
2090
2091
2092TEST_F(InstructionSelectorTest, Int32AddWithWord32And) {
2093  {
2094    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2095                    MachineType::Int32());
2096    Node* const p0 = m.Parameter(0);
2097    Node* const p1 = m.Parameter(1);
2098    Node* const r = m.Int32Add(m.Word32And(p0, m.Int32Constant(0xff)), p1);
2099    m.Return(r);
2100    Stream s = m.Build();
2101    ASSERT_EQ(1U, s.size());
2102    EXPECT_EQ(kArmUxtab, s[0]->arch_opcode());
2103    ASSERT_EQ(3U, s[0]->InputCount());
2104    EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(0)));
2105    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1)));
2106    EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(2)));
2107    ASSERT_EQ(1U, s[0]->OutputCount());
2108    EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
2109  }
2110  {
2111    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2112                    MachineType::Int32());
2113    Node* const p0 = m.Parameter(0);
2114    Node* const p1 = m.Parameter(1);
2115    Node* const r = m.Int32Add(p1, m.Word32And(p0, m.Int32Constant(0xff)));
2116    m.Return(r);
2117    Stream s = m.Build();
2118    ASSERT_EQ(1U, s.size());
2119    EXPECT_EQ(kArmUxtab, s[0]->arch_opcode());
2120    ASSERT_EQ(3U, s[0]->InputCount());
2121    EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(0)));
2122    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1)));
2123    EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(2)));
2124    ASSERT_EQ(1U, s[0]->OutputCount());
2125    EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
2126  }
2127  {
2128    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2129                    MachineType::Int32());
2130    Node* const p0 = m.Parameter(0);
2131    Node* const p1 = m.Parameter(1);
2132    Node* const r = m.Int32Add(m.Word32And(p0, m.Int32Constant(0xffff)), p1);
2133    m.Return(r);
2134    Stream s = m.Build();
2135    ASSERT_EQ(1U, s.size());
2136    EXPECT_EQ(kArmUxtah, s[0]->arch_opcode());
2137    ASSERT_EQ(3U, s[0]->InputCount());
2138    EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(0)));
2139    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1)));
2140    EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(2)));
2141    ASSERT_EQ(1U, s[0]->OutputCount());
2142    EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
2143  }
2144  {
2145    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2146                    MachineType::Int32());
2147    Node* const p0 = m.Parameter(0);
2148    Node* const p1 = m.Parameter(1);
2149    Node* const r = m.Int32Add(p1, m.Word32And(p0, m.Int32Constant(0xffff)));
2150    m.Return(r);
2151    Stream s = m.Build();
2152    ASSERT_EQ(1U, s.size());
2153    EXPECT_EQ(kArmUxtah, s[0]->arch_opcode());
2154    ASSERT_EQ(3U, s[0]->InputCount());
2155    EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(0)));
2156    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1)));
2157    EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(2)));
2158    ASSERT_EQ(1U, s[0]->OutputCount());
2159    EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
2160  }
2161}
2162
2163
2164TEST_F(InstructionSelectorTest, Int32AddWithWord32SarWithWord32Shl) {
2165  {
2166    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2167                    MachineType::Int32());
2168    Node* const p0 = m.Parameter(0);
2169    Node* const p1 = m.Parameter(1);
2170    Node* const r = m.Int32Add(
2171        m.Word32Sar(m.Word32Shl(p0, m.Int32Constant(24)), m.Int32Constant(24)),
2172        p1);
2173    m.Return(r);
2174    Stream s = m.Build();
2175    ASSERT_EQ(1U, s.size());
2176    EXPECT_EQ(kArmSxtab, s[0]->arch_opcode());
2177    ASSERT_EQ(3U, s[0]->InputCount());
2178    EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(0)));
2179    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1)));
2180    EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(2)));
2181    ASSERT_EQ(1U, s[0]->OutputCount());
2182    EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
2183  }
2184  {
2185    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2186                    MachineType::Int32());
2187    Node* const p0 = m.Parameter(0);
2188    Node* const p1 = m.Parameter(1);
2189    Node* const r = m.Int32Add(
2190        p1,
2191        m.Word32Sar(m.Word32Shl(p0, m.Int32Constant(24)), m.Int32Constant(24)));
2192    m.Return(r);
2193    Stream s = m.Build();
2194    ASSERT_EQ(1U, s.size());
2195    EXPECT_EQ(kArmSxtab, s[0]->arch_opcode());
2196    ASSERT_EQ(3U, s[0]->InputCount());
2197    EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(0)));
2198    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1)));
2199    EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(2)));
2200    ASSERT_EQ(1U, s[0]->OutputCount());
2201    EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
2202  }
2203  {
2204    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2205                    MachineType::Int32());
2206    Node* const p0 = m.Parameter(0);
2207    Node* const p1 = m.Parameter(1);
2208    Node* const r = m.Int32Add(
2209        m.Word32Sar(m.Word32Shl(p0, m.Int32Constant(16)), m.Int32Constant(16)),
2210        p1);
2211    m.Return(r);
2212    Stream s = m.Build();
2213    ASSERT_EQ(1U, s.size());
2214    EXPECT_EQ(kArmSxtah, s[0]->arch_opcode());
2215    ASSERT_EQ(3U, s[0]->InputCount());
2216    EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(0)));
2217    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1)));
2218    EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(2)));
2219    ASSERT_EQ(1U, s[0]->OutputCount());
2220    EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
2221  }
2222  {
2223    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2224                    MachineType::Int32());
2225    Node* const p0 = m.Parameter(0);
2226    Node* const p1 = m.Parameter(1);
2227    Node* const r = m.Int32Add(
2228        p1,
2229        m.Word32Sar(m.Word32Shl(p0, m.Int32Constant(16)), m.Int32Constant(16)));
2230    m.Return(r);
2231    Stream s = m.Build();
2232    ASSERT_EQ(1U, s.size());
2233    EXPECT_EQ(kArmSxtah, s[0]->arch_opcode());
2234    ASSERT_EQ(3U, s[0]->InputCount());
2235    EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(0)));
2236    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1)));
2237    EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(2)));
2238    ASSERT_EQ(1U, s[0]->OutputCount());
2239    EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
2240  }
2241}
2242
2243
2244TEST_F(InstructionSelectorTest, Int32SubWithInt32Mul) {
2245  StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2246                  MachineType::Int32(), MachineType::Int32());
2247  m.Return(
2248      m.Int32Sub(m.Parameter(0), m.Int32Mul(m.Parameter(1), m.Parameter(2))));
2249  Stream s = m.Build();
2250  ASSERT_EQ(2U, s.size());
2251  EXPECT_EQ(kArmMul, s[0]->arch_opcode());
2252  ASSERT_EQ(1U, s[0]->OutputCount());
2253  EXPECT_EQ(kArmSub, s[1]->arch_opcode());
2254  ASSERT_EQ(2U, s[1]->InputCount());
2255  EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(1)));
2256}
2257
2258
2259TEST_F(InstructionSelectorTest, Int32SubWithInt32MulForMLS) {
2260  StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2261                  MachineType::Int32(), MachineType::Int32());
2262  m.Return(
2263      m.Int32Sub(m.Parameter(0), m.Int32Mul(m.Parameter(1), m.Parameter(2))));
2264  Stream s = m.Build(ARMv7);
2265  ASSERT_EQ(1U, s.size());
2266  EXPECT_EQ(kArmMls, s[0]->arch_opcode());
2267  EXPECT_EQ(1U, s[0]->OutputCount());
2268  EXPECT_EQ(3U, s[0]->InputCount());
2269}
2270
2271
2272TEST_F(InstructionSelectorTest, Int32DivWithParameters) {
2273  StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2274                  MachineType::Int32());
2275  m.Return(m.Int32Div(m.Parameter(0), m.Parameter(1)));
2276  Stream s = m.Build();
2277  ASSERT_EQ(4U, s.size());
2278  EXPECT_EQ(kArmVcvtF64S32, s[0]->arch_opcode());
2279  ASSERT_EQ(1U, s[0]->OutputCount());
2280  EXPECT_EQ(kArmVcvtF64S32, s[1]->arch_opcode());
2281  ASSERT_EQ(1U, s[1]->OutputCount());
2282  EXPECT_EQ(kArmVdivF64, s[2]->arch_opcode());
2283  ASSERT_EQ(2U, s[2]->InputCount());
2284  ASSERT_EQ(1U, s[2]->OutputCount());
2285  EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[2]->InputAt(0)));
2286  EXPECT_EQ(s.ToVreg(s[1]->Output()), s.ToVreg(s[2]->InputAt(1)));
2287  EXPECT_EQ(kArmVcvtS32F64, s[3]->arch_opcode());
2288  ASSERT_EQ(1U, s[3]->InputCount());
2289  EXPECT_EQ(s.ToVreg(s[2]->Output()), s.ToVreg(s[3]->InputAt(0)));
2290}
2291
2292
2293TEST_F(InstructionSelectorTest, Int32DivWithParametersForSUDIV) {
2294  StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2295                  MachineType::Int32());
2296  m.Return(m.Int32Div(m.Parameter(0), m.Parameter(1)));
2297  Stream s = m.Build(SUDIV);
2298  ASSERT_EQ(1U, s.size());
2299  EXPECT_EQ(kArmSdiv, s[0]->arch_opcode());
2300}
2301
2302
2303TEST_F(InstructionSelectorTest, Int32ModWithParameters) {
2304  StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2305                  MachineType::Int32());
2306  m.Return(m.Int32Mod(m.Parameter(0), m.Parameter(1)));
2307  Stream s = m.Build();
2308  ASSERT_EQ(6U, s.size());
2309  EXPECT_EQ(kArmVcvtF64S32, s[0]->arch_opcode());
2310  ASSERT_EQ(1U, s[0]->OutputCount());
2311  EXPECT_EQ(kArmVcvtF64S32, s[1]->arch_opcode());
2312  ASSERT_EQ(1U, s[1]->OutputCount());
2313  EXPECT_EQ(kArmVdivF64, s[2]->arch_opcode());
2314  ASSERT_EQ(2U, s[2]->InputCount());
2315  ASSERT_EQ(1U, s[2]->OutputCount());
2316  EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[2]->InputAt(0)));
2317  EXPECT_EQ(s.ToVreg(s[1]->Output()), s.ToVreg(s[2]->InputAt(1)));
2318  EXPECT_EQ(kArmVcvtS32F64, s[3]->arch_opcode());
2319  ASSERT_EQ(1U, s[3]->InputCount());
2320  EXPECT_EQ(s.ToVreg(s[2]->Output()), s.ToVreg(s[3]->InputAt(0)));
2321  EXPECT_EQ(kArmMul, s[4]->arch_opcode());
2322  ASSERT_EQ(1U, s[4]->OutputCount());
2323  ASSERT_EQ(2U, s[4]->InputCount());
2324  EXPECT_EQ(s.ToVreg(s[3]->Output()), s.ToVreg(s[4]->InputAt(0)));
2325  EXPECT_EQ(s.ToVreg(s[1]->InputAt(0)), s.ToVreg(s[4]->InputAt(1)));
2326  EXPECT_EQ(kArmSub, s[5]->arch_opcode());
2327  ASSERT_EQ(1U, s[5]->OutputCount());
2328  ASSERT_EQ(2U, s[5]->InputCount());
2329  EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[5]->InputAt(0)));
2330  EXPECT_EQ(s.ToVreg(s[4]->Output()), s.ToVreg(s[5]->InputAt(1)));
2331}
2332
2333
2334TEST_F(InstructionSelectorTest, Int32ModWithParametersForSUDIV) {
2335  StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2336                  MachineType::Int32());
2337  m.Return(m.Int32Mod(m.Parameter(0), m.Parameter(1)));
2338  Stream s = m.Build(SUDIV);
2339  ASSERT_EQ(3U, s.size());
2340  EXPECT_EQ(kArmSdiv, s[0]->arch_opcode());
2341  ASSERT_EQ(1U, s[0]->OutputCount());
2342  ASSERT_EQ(2U, s[0]->InputCount());
2343  EXPECT_EQ(kArmMul, s[1]->arch_opcode());
2344  ASSERT_EQ(1U, s[1]->OutputCount());
2345  ASSERT_EQ(2U, s[1]->InputCount());
2346  EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(0)));
2347  EXPECT_EQ(s.ToVreg(s[0]->InputAt(1)), s.ToVreg(s[1]->InputAt(1)));
2348  EXPECT_EQ(kArmSub, s[2]->arch_opcode());
2349  ASSERT_EQ(1U, s[2]->OutputCount());
2350  ASSERT_EQ(2U, s[2]->InputCount());
2351  EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[2]->InputAt(0)));
2352  EXPECT_EQ(s.ToVreg(s[1]->Output()), s.ToVreg(s[2]->InputAt(1)));
2353}
2354
2355
2356TEST_F(InstructionSelectorTest, Int32ModWithParametersForSUDIVAndMLS) {
2357  StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2358                  MachineType::Int32());
2359  m.Return(m.Int32Mod(m.Parameter(0), m.Parameter(1)));
2360  Stream s = m.Build(ARMv7, SUDIV);
2361  ASSERT_EQ(2U, s.size());
2362  EXPECT_EQ(kArmSdiv, s[0]->arch_opcode());
2363  ASSERT_EQ(1U, s[0]->OutputCount());
2364  ASSERT_EQ(2U, s[0]->InputCount());
2365  EXPECT_EQ(kArmMls, s[1]->arch_opcode());
2366  ASSERT_EQ(1U, s[1]->OutputCount());
2367  ASSERT_EQ(3U, s[1]->InputCount());
2368  EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(0)));
2369  EXPECT_EQ(s.ToVreg(s[0]->InputAt(1)), s.ToVreg(s[1]->InputAt(1)));
2370  EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[1]->InputAt(2)));
2371}
2372
2373
2374TEST_F(InstructionSelectorTest, Int32MulWithParameters) {
2375  StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2376                  MachineType::Int32());
2377  m.Return(m.Int32Mul(m.Parameter(0), m.Parameter(1)));
2378  Stream s = m.Build();
2379  ASSERT_EQ(1U, s.size());
2380  EXPECT_EQ(kArmMul, s[0]->arch_opcode());
2381  EXPECT_EQ(2U, s[0]->InputCount());
2382  EXPECT_EQ(1U, s[0]->OutputCount());
2383}
2384
2385
2386TEST_F(InstructionSelectorTest, Int32MulWithImmediate) {
2387  // x * (2^k + 1) -> x + (x >> k)
2388  TRACED_FORRANGE(int32_t, k, 1, 30) {
2389    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2390    m.Return(m.Int32Mul(m.Parameter(0), m.Int32Constant((1 << k) + 1)));
2391    Stream s = m.Build();
2392    ASSERT_EQ(1U, s.size());
2393    EXPECT_EQ(kArmAdd, s[0]->arch_opcode());
2394    EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
2395    ASSERT_EQ(3U, s[0]->InputCount());
2396    EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
2397    EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2)));
2398    EXPECT_EQ(1U, s[0]->OutputCount());
2399  }
2400  // x * (2^k - 1) -> -x + (x >> k)
2401  TRACED_FORRANGE(int32_t, k, 3, 30) {
2402    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2403    m.Return(m.Int32Mul(m.Parameter(0), m.Int32Constant((1 << k) - 1)));
2404    Stream s = m.Build();
2405    ASSERT_EQ(1U, s.size());
2406    EXPECT_EQ(kArmRsb, s[0]->arch_opcode());
2407    EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
2408    ASSERT_EQ(3U, s[0]->InputCount());
2409    EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
2410    EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2)));
2411    EXPECT_EQ(1U, s[0]->OutputCount());
2412  }
2413  // (2^k + 1) * x -> x + (x >> k)
2414  TRACED_FORRANGE(int32_t, k, 1, 30) {
2415    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2416    m.Return(m.Int32Mul(m.Int32Constant((1 << k) + 1), m.Parameter(0)));
2417    Stream s = m.Build();
2418    ASSERT_EQ(1U, s.size());
2419    EXPECT_EQ(kArmAdd, s[0]->arch_opcode());
2420    EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
2421    ASSERT_EQ(3U, s[0]->InputCount());
2422    EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
2423    EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2)));
2424    EXPECT_EQ(1U, s[0]->OutputCount());
2425  }
2426  // x * (2^k - 1) -> -x + (x >> k)
2427  TRACED_FORRANGE(int32_t, k, 3, 30) {
2428    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2429    m.Return(m.Int32Mul(m.Int32Constant((1 << k) - 1), m.Parameter(0)));
2430    Stream s = m.Build();
2431    ASSERT_EQ(1U, s.size());
2432    EXPECT_EQ(kArmRsb, s[0]->arch_opcode());
2433    EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
2434    ASSERT_EQ(3U, s[0]->InputCount());
2435    EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
2436    EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2)));
2437    EXPECT_EQ(1U, s[0]->OutputCount());
2438  }
2439}
2440
2441
2442TEST_F(InstructionSelectorTest, Int32MulHighWithParameters) {
2443  StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2444                  MachineType::Int32());
2445  Node* const p0 = m.Parameter(0);
2446  Node* const p1 = m.Parameter(1);
2447  Node* const n = m.Int32MulHigh(p0, p1);
2448  m.Return(n);
2449  Stream s = m.Build();
2450  ASSERT_EQ(1U, s.size());
2451  EXPECT_EQ(kArmSmmul, s[0]->arch_opcode());
2452  ASSERT_EQ(2U, s[0]->InputCount());
2453  EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
2454  EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
2455  ASSERT_EQ(1U, s[0]->OutputCount());
2456  EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
2457}
2458
2459
2460TEST_F(InstructionSelectorTest, Uint32MulHighWithParameters) {
2461  StreamBuilder m(this, MachineType::Uint32(), MachineType::Uint32(),
2462                  MachineType::Uint32());
2463  Node* const p0 = m.Parameter(0);
2464  Node* const p1 = m.Parameter(1);
2465  Node* const n = m.Uint32MulHigh(p0, p1);
2466  m.Return(n);
2467  Stream s = m.Build();
2468  ASSERT_EQ(1U, s.size());
2469  EXPECT_EQ(kArmUmull, s[0]->arch_opcode());
2470  ASSERT_EQ(2U, s[0]->InputCount());
2471  EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
2472  EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
2473  ASSERT_EQ(2U, s[0]->OutputCount());
2474  EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->OutputAt(1)));
2475}
2476
2477
2478TEST_F(InstructionSelectorTest, Uint32DivWithParameters) {
2479  StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2480                  MachineType::Int32());
2481  m.Return(m.Uint32Div(m.Parameter(0), m.Parameter(1)));
2482  Stream s = m.Build();
2483  ASSERT_EQ(4U, s.size());
2484  EXPECT_EQ(kArmVcvtF64U32, s[0]->arch_opcode());
2485  ASSERT_EQ(1U, s[0]->OutputCount());
2486  EXPECT_EQ(kArmVcvtF64U32, s[1]->arch_opcode());
2487  ASSERT_EQ(1U, s[1]->OutputCount());
2488  EXPECT_EQ(kArmVdivF64, s[2]->arch_opcode());
2489  ASSERT_EQ(2U, s[2]->InputCount());
2490  ASSERT_EQ(1U, s[2]->OutputCount());
2491  EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[2]->InputAt(0)));
2492  EXPECT_EQ(s.ToVreg(s[1]->Output()), s.ToVreg(s[2]->InputAt(1)));
2493  EXPECT_EQ(kArmVcvtU32F64, s[3]->arch_opcode());
2494  ASSERT_EQ(1U, s[3]->InputCount());
2495  EXPECT_EQ(s.ToVreg(s[2]->Output()), s.ToVreg(s[3]->InputAt(0)));
2496}
2497
2498
2499TEST_F(InstructionSelectorTest, Uint32DivWithParametersForSUDIV) {
2500  StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2501                  MachineType::Int32());
2502  m.Return(m.Uint32Div(m.Parameter(0), m.Parameter(1)));
2503  Stream s = m.Build(SUDIV);
2504  ASSERT_EQ(1U, s.size());
2505  EXPECT_EQ(kArmUdiv, s[0]->arch_opcode());
2506}
2507
2508
2509TEST_F(InstructionSelectorTest, Uint32ModWithParameters) {
2510  StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2511                  MachineType::Int32());
2512  m.Return(m.Uint32Mod(m.Parameter(0), m.Parameter(1)));
2513  Stream s = m.Build();
2514  ASSERT_EQ(6U, s.size());
2515  EXPECT_EQ(kArmVcvtF64U32, s[0]->arch_opcode());
2516  ASSERT_EQ(1U, s[0]->OutputCount());
2517  EXPECT_EQ(kArmVcvtF64U32, s[1]->arch_opcode());
2518  ASSERT_EQ(1U, s[1]->OutputCount());
2519  EXPECT_EQ(kArmVdivF64, s[2]->arch_opcode());
2520  ASSERT_EQ(2U, s[2]->InputCount());
2521  ASSERT_EQ(1U, s[2]->OutputCount());
2522  EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[2]->InputAt(0)));
2523  EXPECT_EQ(s.ToVreg(s[1]->Output()), s.ToVreg(s[2]->InputAt(1)));
2524  EXPECT_EQ(kArmVcvtU32F64, s[3]->arch_opcode());
2525  ASSERT_EQ(1U, s[3]->InputCount());
2526  EXPECT_EQ(s.ToVreg(s[2]->Output()), s.ToVreg(s[3]->InputAt(0)));
2527  EXPECT_EQ(kArmMul, s[4]->arch_opcode());
2528  ASSERT_EQ(1U, s[4]->OutputCount());
2529  ASSERT_EQ(2U, s[4]->InputCount());
2530  EXPECT_EQ(s.ToVreg(s[3]->Output()), s.ToVreg(s[4]->InputAt(0)));
2531  EXPECT_EQ(s.ToVreg(s[1]->InputAt(0)), s.ToVreg(s[4]->InputAt(1)));
2532  EXPECT_EQ(kArmSub, s[5]->arch_opcode());
2533  ASSERT_EQ(1U, s[5]->OutputCount());
2534  ASSERT_EQ(2U, s[5]->InputCount());
2535  EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[5]->InputAt(0)));
2536  EXPECT_EQ(s.ToVreg(s[4]->Output()), s.ToVreg(s[5]->InputAt(1)));
2537}
2538
2539
2540TEST_F(InstructionSelectorTest, Uint32ModWithParametersForSUDIV) {
2541  StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2542                  MachineType::Int32());
2543  m.Return(m.Uint32Mod(m.Parameter(0), m.Parameter(1)));
2544  Stream s = m.Build(SUDIV);
2545  ASSERT_EQ(3U, s.size());
2546  EXPECT_EQ(kArmUdiv, s[0]->arch_opcode());
2547  ASSERT_EQ(1U, s[0]->OutputCount());
2548  ASSERT_EQ(2U, s[0]->InputCount());
2549  EXPECT_EQ(kArmMul, s[1]->arch_opcode());
2550  ASSERT_EQ(1U, s[1]->OutputCount());
2551  ASSERT_EQ(2U, s[1]->InputCount());
2552  EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(0)));
2553  EXPECT_EQ(s.ToVreg(s[0]->InputAt(1)), s.ToVreg(s[1]->InputAt(1)));
2554  EXPECT_EQ(kArmSub, s[2]->arch_opcode());
2555  ASSERT_EQ(1U, s[2]->OutputCount());
2556  ASSERT_EQ(2U, s[2]->InputCount());
2557  EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[2]->InputAt(0)));
2558  EXPECT_EQ(s.ToVreg(s[1]->Output()), s.ToVreg(s[2]->InputAt(1)));
2559}
2560
2561
2562TEST_F(InstructionSelectorTest, Uint32ModWithParametersForSUDIVAndMLS) {
2563  StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2564                  MachineType::Int32());
2565  m.Return(m.Uint32Mod(m.Parameter(0), m.Parameter(1)));
2566  Stream s = m.Build(ARMv7, SUDIV);
2567  ASSERT_EQ(2U, s.size());
2568  EXPECT_EQ(kArmUdiv, s[0]->arch_opcode());
2569  ASSERT_EQ(1U, s[0]->OutputCount());
2570  ASSERT_EQ(2U, s[0]->InputCount());
2571  EXPECT_EQ(kArmMls, s[1]->arch_opcode());
2572  ASSERT_EQ(1U, s[1]->OutputCount());
2573  ASSERT_EQ(3U, s[1]->InputCount());
2574  EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(0)));
2575  EXPECT_EQ(s.ToVreg(s[0]->InputAt(1)), s.ToVreg(s[1]->InputAt(1)));
2576  EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[1]->InputAt(2)));
2577}
2578
2579
2580TEST_F(InstructionSelectorTest, Word32ShlWord32SarForSbfx) {
2581  TRACED_FORRANGE(int32_t, shl, 1, 31) {
2582    TRACED_FORRANGE(int32_t, sar, shl, 31) {
2583      if ((shl == sar) && (sar == 16)) continue;  // Sxth.
2584      if ((shl == sar) && (sar == 24)) continue;  // Sxtb.
2585      StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2586      m.Return(m.Word32Sar(m.Word32Shl(m.Parameter(0), m.Int32Constant(shl)),
2587                           m.Int32Constant(sar)));
2588      Stream s = m.Build(ARMv7);
2589      ASSERT_EQ(1U, s.size());
2590      EXPECT_EQ(kArmSbfx, s[0]->arch_opcode());
2591      ASSERT_EQ(3U, s[0]->InputCount());
2592      EXPECT_EQ(sar - shl, s.ToInt32(s[0]->InputAt(1)));
2593      EXPECT_EQ(32 - sar, s.ToInt32(s[0]->InputAt(2)));
2594    }
2595  }
2596}
2597
2598
2599TEST_F(InstructionSelectorTest, Word32AndWithUbfxImmediateForARMv7) {
2600  TRACED_FORRANGE(int32_t, width, 9, 23) {
2601    if (width == 16) continue;  // Uxth.
2602    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2603    m.Return(m.Word32And(m.Parameter(0),
2604                         m.Int32Constant(0xffffffffu >> (32 - width))));
2605    Stream s = m.Build(ARMv7);
2606    ASSERT_EQ(1U, s.size());
2607    EXPECT_EQ(kArmUbfx, s[0]->arch_opcode());
2608    ASSERT_EQ(3U, s[0]->InputCount());
2609    EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1)));
2610    EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
2611  }
2612  TRACED_FORRANGE(int32_t, width, 9, 23) {
2613    if (width == 16) continue;  // Uxth.
2614    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2615    m.Return(m.Word32And(m.Int32Constant(0xffffffffu >> (32 - width)),
2616                         m.Parameter(0)));
2617    Stream s = m.Build(ARMv7);
2618    ASSERT_EQ(1U, s.size());
2619    EXPECT_EQ(kArmUbfx, s[0]->arch_opcode());
2620    ASSERT_EQ(3U, s[0]->InputCount());
2621    EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1)));
2622    EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
2623  }
2624}
2625
2626
2627TEST_F(InstructionSelectorTest, Word32AndWithBfcImmediateForARMv7) {
2628  TRACED_FORRANGE(int32_t, lsb, 0, 31) {
2629    TRACED_FORRANGE(int32_t, width, 9, (24 - lsb) - 1) {
2630      StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2631      m.Return(m.Word32And(
2632          m.Parameter(0),
2633          m.Int32Constant(~((0xffffffffu >> (32 - width)) << lsb))));
2634      Stream s = m.Build(ARMv7);
2635      ASSERT_EQ(1U, s.size());
2636      EXPECT_EQ(kArmBfc, s[0]->arch_opcode());
2637      ASSERT_EQ(1U, s[0]->OutputCount());
2638      EXPECT_TRUE(
2639          UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy());
2640      ASSERT_EQ(3U, s[0]->InputCount());
2641      EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
2642      EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
2643    }
2644  }
2645  TRACED_FORRANGE(int32_t, lsb, 0, 31) {
2646    TRACED_FORRANGE(int32_t, width, 9, (24 - lsb) - 1) {
2647      StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2648      m.Return(
2649          m.Word32And(m.Int32Constant(~((0xffffffffu >> (32 - width)) << lsb)),
2650                      m.Parameter(0)));
2651      Stream s = m.Build(ARMv7);
2652      ASSERT_EQ(1U, s.size());
2653      EXPECT_EQ(kArmBfc, s[0]->arch_opcode());
2654      ASSERT_EQ(1U, s[0]->OutputCount());
2655      EXPECT_TRUE(
2656          UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy());
2657      ASSERT_EQ(3U, s[0]->InputCount());
2658      EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
2659      EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
2660    }
2661  }
2662}
2663
2664
2665TEST_F(InstructionSelectorTest, Word32AndWith0xffff) {
2666  {
2667    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2668    Node* const p0 = m.Parameter(0);
2669    Node* const r = m.Word32And(p0, m.Int32Constant(0xffff));
2670    m.Return(r);
2671    Stream s = m.Build();
2672    ASSERT_EQ(1U, s.size());
2673    EXPECT_EQ(kArmUxth, s[0]->arch_opcode());
2674    ASSERT_EQ(2U, s[0]->InputCount());
2675    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
2676    EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1)));
2677    ASSERT_EQ(1U, s[0]->OutputCount());
2678    EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
2679  }
2680  {
2681    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2682    Node* const p0 = m.Parameter(0);
2683    Node* const r = m.Word32And(m.Int32Constant(0xffff), p0);
2684    m.Return(r);
2685    Stream s = m.Build();
2686    ASSERT_EQ(1U, s.size());
2687    EXPECT_EQ(kArmUxth, s[0]->arch_opcode());
2688    ASSERT_EQ(2U, s[0]->InputCount());
2689    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
2690    EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1)));
2691    ASSERT_EQ(1U, s[0]->OutputCount());
2692    EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
2693  }
2694}
2695
2696
2697TEST_F(InstructionSelectorTest, Word32SarWithWord32Shl) {
2698  {
2699    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2700    Node* const p0 = m.Parameter(0);
2701    Node* const r =
2702        m.Word32Sar(m.Word32Shl(p0, m.Int32Constant(24)), m.Int32Constant(24));
2703    m.Return(r);
2704    Stream s = m.Build();
2705    ASSERT_EQ(1U, s.size());
2706    EXPECT_EQ(kArmSxtb, s[0]->arch_opcode());
2707    ASSERT_EQ(2U, s[0]->InputCount());
2708    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
2709    EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1)));
2710    ASSERT_EQ(1U, s[0]->OutputCount());
2711    EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
2712  }
2713  {
2714    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2715    Node* const p0 = m.Parameter(0);
2716    Node* const r =
2717        m.Word32Sar(m.Word32Shl(p0, m.Int32Constant(16)), m.Int32Constant(16));
2718    m.Return(r);
2719    Stream s = m.Build();
2720    ASSERT_EQ(1U, s.size());
2721    EXPECT_EQ(kArmSxth, s[0]->arch_opcode());
2722    ASSERT_EQ(2U, s[0]->InputCount());
2723    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
2724    EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1)));
2725    ASSERT_EQ(1U, s[0]->OutputCount());
2726    EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
2727  }
2728}
2729
2730
2731TEST_F(InstructionSelectorTest, Word32ShrWithWord32AndWithImmediateForARMv7) {
2732  TRACED_FORRANGE(int32_t, lsb, 0, 31) {
2733    TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) {
2734      uint32_t max = 1 << lsb;
2735      if (max > static_cast<uint32_t>(kMaxInt)) max -= 1;
2736      uint32_t jnk = rng()->NextInt(max);
2737      uint32_t msk = ((0xffffffffu >> (32 - width)) << lsb) | jnk;
2738      StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2739      m.Return(m.Word32Shr(m.Word32And(m.Parameter(0), m.Int32Constant(msk)),
2740                           m.Int32Constant(lsb)));
2741      Stream s = m.Build(ARMv7);
2742      ASSERT_EQ(1U, s.size());
2743      EXPECT_EQ(kArmUbfx, s[0]->arch_opcode());
2744      ASSERT_EQ(3U, s[0]->InputCount());
2745      EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
2746      EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
2747    }
2748  }
2749  TRACED_FORRANGE(int32_t, lsb, 0, 31) {
2750    TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) {
2751      uint32_t max = 1 << lsb;
2752      if (max > static_cast<uint32_t>(kMaxInt)) max -= 1;
2753      uint32_t jnk = rng()->NextInt(max);
2754      uint32_t msk = ((0xffffffffu >> (32 - width)) << lsb) | jnk;
2755      StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2756      m.Return(m.Word32Shr(m.Word32And(m.Int32Constant(msk), m.Parameter(0)),
2757                           m.Int32Constant(lsb)));
2758      Stream s = m.Build(ARMv7);
2759      ASSERT_EQ(1U, s.size());
2760      EXPECT_EQ(kArmUbfx, s[0]->arch_opcode());
2761      ASSERT_EQ(3U, s[0]->InputCount());
2762      EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
2763      EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
2764    }
2765  }
2766}
2767
2768
2769TEST_F(InstructionSelectorTest, Word32AndWithWord32Not) {
2770  {
2771    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2772                    MachineType::Int32());
2773    m.Return(m.Word32And(m.Parameter(0), m.Word32Not(m.Parameter(1))));
2774    Stream s = m.Build();
2775    ASSERT_EQ(1U, s.size());
2776    EXPECT_EQ(kArmBic, s[0]->arch_opcode());
2777    EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
2778    EXPECT_EQ(2U, s[0]->InputCount());
2779    EXPECT_EQ(1U, s[0]->OutputCount());
2780  }
2781  {
2782    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2783                    MachineType::Int32());
2784    m.Return(m.Word32And(m.Word32Not(m.Parameter(0)), m.Parameter(1)));
2785    Stream s = m.Build();
2786    ASSERT_EQ(1U, s.size());
2787    EXPECT_EQ(kArmBic, s[0]->arch_opcode());
2788    EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
2789    EXPECT_EQ(2U, s[0]->InputCount());
2790    EXPECT_EQ(1U, s[0]->OutputCount());
2791  }
2792}
2793
2794
2795TEST_F(InstructionSelectorTest, Word32EqualWithParameters) {
2796  StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2797                  MachineType::Int32());
2798  m.Return(m.Word32Equal(m.Parameter(0), m.Parameter(1)));
2799  Stream s = m.Build();
2800  ASSERT_EQ(1U, s.size());
2801  EXPECT_EQ(kArmCmp, s[0]->arch_opcode());
2802  EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
2803  EXPECT_EQ(2U, s[0]->InputCount());
2804  EXPECT_EQ(1U, s[0]->OutputCount());
2805  EXPECT_EQ(kFlags_set, s[0]->flags_mode());
2806  EXPECT_EQ(kEqual, s[0]->flags_condition());
2807}
2808
2809
2810TEST_F(InstructionSelectorTest, Word32EqualWithImmediate) {
2811  TRACED_FOREACH(int32_t, imm, kImmediates) {
2812    if (imm == 0) continue;
2813    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2814    m.Return(m.Word32Equal(m.Parameter(0), m.Int32Constant(imm)));
2815    Stream s = m.Build();
2816    ASSERT_EQ(1U, s.size());
2817    EXPECT_EQ(kArmCmp, s[0]->arch_opcode());
2818    EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode());
2819    ASSERT_EQ(2U, s[0]->InputCount());
2820    EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
2821    EXPECT_EQ(1U, s[0]->OutputCount());
2822    EXPECT_EQ(kFlags_set, s[0]->flags_mode());
2823    EXPECT_EQ(kEqual, s[0]->flags_condition());
2824  }
2825  TRACED_FOREACH(int32_t, imm, kImmediates) {
2826    if (imm == 0) continue;
2827    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2828    m.Return(m.Word32Equal(m.Int32Constant(imm), m.Parameter(0)));
2829    Stream s = m.Build();
2830    ASSERT_EQ(1U, s.size());
2831    EXPECT_EQ(kArmCmp, s[0]->arch_opcode());
2832    EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode());
2833    ASSERT_EQ(2U, s[0]->InputCount());
2834    EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
2835    EXPECT_EQ(1U, s[0]->OutputCount());
2836    EXPECT_EQ(kFlags_set, s[0]->flags_mode());
2837    EXPECT_EQ(kEqual, s[0]->flags_condition());
2838  }
2839}
2840
2841
2842TEST_F(InstructionSelectorTest, Word32EqualWithZero) {
2843  {
2844    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2845    m.Return(m.Word32Equal(m.Parameter(0), m.Int32Constant(0)));
2846    Stream s = m.Build();
2847    ASSERT_EQ(1U, s.size());
2848    EXPECT_EQ(kArmTst, s[0]->arch_opcode());
2849    EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
2850    ASSERT_EQ(2U, s[0]->InputCount());
2851    EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
2852    EXPECT_EQ(1U, s[0]->OutputCount());
2853    EXPECT_EQ(kFlags_set, s[0]->flags_mode());
2854    EXPECT_EQ(kEqual, s[0]->flags_condition());
2855  }
2856  {
2857    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2858    m.Return(m.Word32Equal(m.Int32Constant(0), m.Parameter(0)));
2859    Stream s = m.Build();
2860    ASSERT_EQ(1U, s.size());
2861    EXPECT_EQ(kArmTst, s[0]->arch_opcode());
2862    EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
2863    ASSERT_EQ(2U, s[0]->InputCount());
2864    EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
2865    EXPECT_EQ(1U, s[0]->OutputCount());
2866    EXPECT_EQ(kFlags_set, s[0]->flags_mode());
2867    EXPECT_EQ(kEqual, s[0]->flags_condition());
2868  }
2869}
2870
2871
2872TEST_F(InstructionSelectorTest, Word32NotWithParameter) {
2873  StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2874  m.Return(m.Word32Not(m.Parameter(0)));
2875  Stream s = m.Build();
2876  ASSERT_EQ(1U, s.size());
2877  EXPECT_EQ(kArmMvn, s[0]->arch_opcode());
2878  EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
2879  EXPECT_EQ(1U, s[0]->InputCount());
2880  EXPECT_EQ(1U, s[0]->OutputCount());
2881}
2882
2883
2884TEST_F(InstructionSelectorTest, Word32AndWithWord32ShrWithImmediateForARMv7) {
2885  TRACED_FORRANGE(int32_t, lsb, 1, 31) {
2886    TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) {
2887      if (((width == 8) || (width == 16)) &&
2888          ((lsb == 8) || (lsb == 16) || (lsb == 24)))
2889        continue;  // Uxtb/h ror.
2890      StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2891      m.Return(m.Word32And(m.Word32Shr(m.Parameter(0), m.Int32Constant(lsb)),
2892                           m.Int32Constant(0xffffffffu >> (32 - width))));
2893      Stream s = m.Build(ARMv7);
2894      ASSERT_EQ(1U, s.size());
2895      EXPECT_EQ(kArmUbfx, s[0]->arch_opcode());
2896      ASSERT_EQ(3U, s[0]->InputCount());
2897      EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
2898      EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
2899    }
2900  }
2901  TRACED_FORRANGE(int32_t, lsb, 1, 31) {
2902    TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) {
2903      if (((width == 8) || (width == 16)) &&
2904          ((lsb == 8) || (lsb == 16) || (lsb == 24)))
2905        continue;  // Uxtb/h ror.
2906      StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2907      m.Return(m.Word32And(m.Int32Constant(0xffffffffu >> (32 - width)),
2908                           m.Word32Shr(m.Parameter(0), m.Int32Constant(lsb))));
2909      Stream s = m.Build(ARMv7);
2910      ASSERT_EQ(1U, s.size());
2911      EXPECT_EQ(kArmUbfx, s[0]->arch_opcode());
2912      ASSERT_EQ(3U, s[0]->InputCount());
2913      EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
2914      EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
2915    }
2916  }
2917}
2918
2919
2920TEST_F(InstructionSelectorTest, Word32AndWithWord32ShrAnd0xff) {
2921  TRACED_FORRANGE(int32_t, shr, 1, 3) {
2922    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2923    Node* const p0 = m.Parameter(0);
2924    Node* const r = m.Word32And(m.Word32Shr(p0, m.Int32Constant(shr * 8)),
2925                                m.Int32Constant(0xff));
2926    m.Return(r);
2927    Stream s = m.Build();
2928    ASSERT_EQ(1U, s.size());
2929    EXPECT_EQ(kArmUxtb, s[0]->arch_opcode());
2930    ASSERT_EQ(2U, s[0]->InputCount());
2931    EXPECT_EQ(shr * 8, s.ToInt32(s[0]->InputAt(1)));
2932  }
2933  TRACED_FORRANGE(int32_t, shr, 1, 3) {
2934    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2935    Node* const p0 = m.Parameter(0);
2936    Node* const r = m.Word32And(m.Int32Constant(0xff),
2937                                m.Word32Shr(p0, m.Int32Constant(shr * 8)));
2938    m.Return(r);
2939    Stream s = m.Build();
2940    ASSERT_EQ(1U, s.size());
2941    EXPECT_EQ(kArmUxtb, s[0]->arch_opcode());
2942    ASSERT_EQ(2U, s[0]->InputCount());
2943    EXPECT_EQ(shr * 8, s.ToInt32(s[0]->InputAt(1)));
2944  }
2945}
2946
2947
2948TEST_F(InstructionSelectorTest, Word32AndWithWord32ShrAnd0xffff) {
2949  TRACED_FORRANGE(int32_t, shr, 1, 3) {
2950    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2951    Node* const p0 = m.Parameter(0);
2952    Node* const r = m.Word32And(m.Word32Shr(p0, m.Int32Constant(shr * 8)),
2953                                m.Int32Constant(0xffff));
2954    m.Return(r);
2955    Stream s = m.Build();
2956    ASSERT_EQ(1U, s.size());
2957    EXPECT_EQ(kArmUxth, s[0]->arch_opcode());
2958    ASSERT_EQ(2U, s[0]->InputCount());
2959    EXPECT_EQ(shr * 8, s.ToInt32(s[0]->InputAt(1)));
2960  }
2961  TRACED_FORRANGE(int32_t, shr, 1, 3) {
2962    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2963    Node* const p0 = m.Parameter(0);
2964    Node* const r = m.Word32And(m.Int32Constant(0xffff),
2965                                m.Word32Shr(p0, m.Int32Constant(shr * 8)));
2966    m.Return(r);
2967    Stream s = m.Build();
2968    ASSERT_EQ(1U, s.size());
2969    EXPECT_EQ(kArmUxth, s[0]->arch_opcode());
2970    ASSERT_EQ(2U, s[0]->InputCount());
2971    EXPECT_EQ(shr * 8, s.ToInt32(s[0]->InputAt(1)));
2972  }
2973}
2974
2975
2976TEST_F(InstructionSelectorTest, Word32Clz) {
2977  StreamBuilder m(this, MachineType::Uint32(), MachineType::Uint32());
2978  Node* const p0 = m.Parameter(0);
2979  Node* const n = m.Word32Clz(p0);
2980  m.Return(n);
2981  Stream s = m.Build();
2982  ASSERT_EQ(1U, s.size());
2983  EXPECT_EQ(kArmClz, s[0]->arch_opcode());
2984  ASSERT_EQ(1U, s[0]->InputCount());
2985  EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
2986  ASSERT_EQ(1U, s[0]->OutputCount());
2987  EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
2988}
2989
2990TEST_F(InstructionSelectorTest, Float32Max) {
2991  StreamBuilder m(this, MachineType::Float32(), MachineType::Float32(),
2992                  MachineType::Float32());
2993  Node* const p0 = m.Parameter(0);
2994  Node* const p1 = m.Parameter(1);
2995  Node* const n = m.Float32Max(p0, p1);
2996  m.Return(n);
2997  Stream s = m.Build(ARMv8);
2998  // Float32Max is `(b < a) ? a : b`.
2999  ASSERT_EQ(1U, s.size());
3000  EXPECT_EQ(kArmFloat32Max, s[0]->arch_opcode());
3001  ASSERT_EQ(2U, s[0]->InputCount());
3002  EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
3003  EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
3004  ASSERT_EQ(1U, s[0]->OutputCount());
3005  EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
3006}
3007
3008TEST_F(InstructionSelectorTest, Float32Min) {
3009  StreamBuilder m(this, MachineType::Float32(), MachineType::Float32(),
3010                  MachineType::Float32());
3011  Node* const p0 = m.Parameter(0);
3012  Node* const p1 = m.Parameter(1);
3013  Node* const n = m.Float32Min(p0, p1);
3014  m.Return(n);
3015  Stream s = m.Build(ARMv8);
3016  // Float32Min is `(a < b) ? a : b`.
3017  ASSERT_EQ(1U, s.size());
3018  EXPECT_EQ(kArmFloat32Min, s[0]->arch_opcode());
3019  ASSERT_EQ(2U, s[0]->InputCount());
3020  EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
3021  EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
3022  ASSERT_EQ(1U, s[0]->OutputCount());
3023  EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
3024}
3025
3026TEST_F(InstructionSelectorTest, Float64Max) {
3027  StreamBuilder m(this, MachineType::Float64(), MachineType::Float64(),
3028                  MachineType::Float64());
3029  Node* const p0 = m.Parameter(0);
3030  Node* const p1 = m.Parameter(1);
3031  Node* const n = m.Float64Max(p0, p1);
3032  m.Return(n);
3033  Stream s = m.Build(ARMv8);
3034  // Float64Max is `(b < a) ? a : b`.
3035  ASSERT_EQ(1U, s.size());
3036  EXPECT_EQ(kArmFloat64Max, s[0]->arch_opcode());
3037  ASSERT_EQ(2U, s[0]->InputCount());
3038  EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
3039  EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
3040  ASSERT_EQ(1U, s[0]->OutputCount());
3041  EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
3042}
3043
3044TEST_F(InstructionSelectorTest, Float64Min) {
3045  StreamBuilder m(this, MachineType::Float64(), MachineType::Float64(),
3046                  MachineType::Float64());
3047  Node* const p0 = m.Parameter(0);
3048  Node* const p1 = m.Parameter(1);
3049  Node* const n = m.Float64Min(p0, p1);
3050  m.Return(n);
3051  Stream s = m.Build(ARMv8);
3052  // Float64Min is `(a < b) ? a : b`.
3053  ASSERT_EQ(1U, s.size());
3054  EXPECT_EQ(kArmFloat64Min, s[0]->arch_opcode());
3055  ASSERT_EQ(2U, s[0]->InputCount());
3056  EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
3057  EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
3058  ASSERT_EQ(1U, s[0]->OutputCount());
3059  EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
3060}
3061
3062TEST_F(InstructionSelectorTest, Float32Neg) {
3063  StreamBuilder m(this, MachineType::Float32(), MachineType::Float32());
3064  Node* const p0 = m.Parameter(0);
3065  // Don't use m.Float32Neg() as that generates an explicit sub.
3066  Node* const n = m.AddNode(m.machine()->Float32Neg().op(), m.Parameter(0));
3067  m.Return(n);
3068  Stream s = m.Build();
3069  ASSERT_EQ(1U, s.size());
3070  EXPECT_EQ(kArmVnegF32, s[0]->arch_opcode());
3071  ASSERT_EQ(1U, s[0]->InputCount());
3072  EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
3073  ASSERT_EQ(1U, s[0]->OutputCount());
3074  EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
3075}
3076
3077TEST_F(InstructionSelectorTest, Float64Neg) {
3078  StreamBuilder m(this, MachineType::Float64(), MachineType::Float64());
3079  Node* const p0 = m.Parameter(0);
3080  // Don't use m.Float64Neg() as that generates an explicit sub.
3081  Node* const n = m.AddNode(m.machine()->Float64Neg().op(), m.Parameter(0));
3082  m.Return(n);
3083  Stream s = m.Build();
3084  ASSERT_EQ(1U, s.size());
3085  EXPECT_EQ(kArmVnegF64, s[0]->arch_opcode());
3086  ASSERT_EQ(1U, s[0]->InputCount());
3087  EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
3088  ASSERT_EQ(1U, s[0]->OutputCount());
3089  EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
3090}
3091
3092}  // namespace compiler
3093}  // namespace internal
3094}  // namespace v8
3095