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(1)->kind());
1396    EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1)));
1397    EXPECT_EQ(0U, s[0]->OutputCount());
1398  }
1399}
1400
1401
1402INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1403                        InstructionSelectorMemoryAccessTest,
1404                        ::testing::ValuesIn(kMemoryAccesses));
1405
1406
1407// -----------------------------------------------------------------------------
1408// Conversions.
1409
1410
1411TEST_F(InstructionSelectorTest, ChangeFloat32ToFloat64WithParameter) {
1412  StreamBuilder m(this, MachineType::Float64(), MachineType::Float32());
1413  m.Return(m.ChangeFloat32ToFloat64(m.Parameter(0)));
1414  Stream s = m.Build();
1415  ASSERT_EQ(1U, s.size());
1416  EXPECT_EQ(kArmVcvtF64F32, s[0]->arch_opcode());
1417  EXPECT_EQ(1U, s[0]->InputCount());
1418  EXPECT_EQ(1U, s[0]->OutputCount());
1419}
1420
1421
1422TEST_F(InstructionSelectorTest, TruncateFloat64ToFloat32WithParameter) {
1423  StreamBuilder m(this, MachineType::Float32(), MachineType::Float64());
1424  m.Return(m.TruncateFloat64ToFloat32(m.Parameter(0)));
1425  Stream s = m.Build();
1426  ASSERT_EQ(1U, s.size());
1427  EXPECT_EQ(kArmVcvtF32F64, s[0]->arch_opcode());
1428  EXPECT_EQ(1U, s[0]->InputCount());
1429  EXPECT_EQ(1U, s[0]->OutputCount());
1430}
1431
1432
1433// -----------------------------------------------------------------------------
1434// Comparisons.
1435
1436
1437namespace {
1438
1439struct Comparison {
1440  Constructor constructor;
1441  const char* constructor_name;
1442  FlagsCondition flags_condition;
1443  FlagsCondition negated_flags_condition;
1444  FlagsCondition commuted_flags_condition;
1445};
1446
1447
1448std::ostream& operator<<(std::ostream& os, const Comparison& cmp) {
1449  return os << cmp.constructor_name;
1450}
1451
1452
1453const Comparison kComparisons[] = {
1454    {&RawMachineAssembler::Word32Equal, "Word32Equal", kEqual, kNotEqual,
1455     kEqual},
1456    {&RawMachineAssembler::Int32LessThan, "Int32LessThan", kSignedLessThan,
1457     kSignedGreaterThanOrEqual, kSignedGreaterThan},
1458    {&RawMachineAssembler::Int32LessThanOrEqual, "Int32LessThanOrEqual",
1459     kSignedLessThanOrEqual, kSignedGreaterThan, kSignedGreaterThanOrEqual},
1460    {&RawMachineAssembler::Uint32LessThan, "Uint32LessThan", kUnsignedLessThan,
1461     kUnsignedGreaterThanOrEqual, kUnsignedGreaterThan},
1462    {&RawMachineAssembler::Uint32LessThanOrEqual, "Uint32LessThanOrEqual",
1463     kUnsignedLessThanOrEqual, kUnsignedGreaterThan,
1464     kUnsignedGreaterThanOrEqual}};
1465
1466}  // namespace
1467
1468
1469typedef InstructionSelectorTestWithParam<Comparison>
1470    InstructionSelectorComparisonTest;
1471
1472
1473TEST_P(InstructionSelectorComparisonTest, Parameters) {
1474  const Comparison& cmp = GetParam();
1475  StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
1476                  MachineType::Int32());
1477  Node* const p0 = m.Parameter(0);
1478  Node* const p1 = m.Parameter(1);
1479  Node* const r = (m.*cmp.constructor)(p0, p1);
1480  m.Return(r);
1481  Stream const s = m.Build();
1482  ASSERT_EQ(1U, s.size());
1483  EXPECT_EQ(kArmCmp, s[0]->arch_opcode());
1484  EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
1485  ASSERT_EQ(2U, s[0]->InputCount());
1486  EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1487  EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
1488  ASSERT_EQ(1U, s[0]->OutputCount());
1489  EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->OutputAt(0)));
1490  EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1491  EXPECT_EQ(cmp.flags_condition, s[0]->flags_condition());
1492}
1493
1494
1495TEST_P(InstructionSelectorComparisonTest, Word32EqualWithZero) {
1496  {
1497    const Comparison& cmp = GetParam();
1498    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
1499                    MachineType::Int32());
1500    Node* const p0 = m.Parameter(0);
1501    Node* const p1 = m.Parameter(1);
1502    Node* const r =
1503        m.Word32Equal((m.*cmp.constructor)(p0, p1), m.Int32Constant(0));
1504    m.Return(r);
1505    Stream const s = m.Build();
1506    ASSERT_EQ(1U, s.size());
1507    EXPECT_EQ(kArmCmp, s[0]->arch_opcode());
1508    EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
1509    ASSERT_EQ(2U, s[0]->InputCount());
1510    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1511    EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
1512    ASSERT_EQ(1U, s[0]->OutputCount());
1513    EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->OutputAt(0)));
1514    EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1515    EXPECT_EQ(cmp.negated_flags_condition, s[0]->flags_condition());
1516  }
1517  {
1518    const Comparison& cmp = GetParam();
1519    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
1520                    MachineType::Int32());
1521    Node* const p0 = m.Parameter(0);
1522    Node* const p1 = m.Parameter(1);
1523    Node* const r =
1524        m.Word32Equal(m.Int32Constant(0), (m.*cmp.constructor)(p0, p1));
1525    m.Return(r);
1526    Stream const s = m.Build();
1527    ASSERT_EQ(1U, s.size());
1528    EXPECT_EQ(kArmCmp, s[0]->arch_opcode());
1529    EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
1530    ASSERT_EQ(2U, s[0]->InputCount());
1531    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1532    EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
1533    ASSERT_EQ(1U, s[0]->OutputCount());
1534    EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->OutputAt(0)));
1535    EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1536    EXPECT_EQ(cmp.negated_flags_condition, s[0]->flags_condition());
1537  }
1538}
1539
1540
1541INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1542                        InstructionSelectorComparisonTest,
1543                        ::testing::ValuesIn(kComparisons));
1544
1545
1546// -----------------------------------------------------------------------------
1547// Floating point comparisons.
1548
1549
1550namespace {
1551
1552const Comparison kF32Comparisons[] = {
1553    {&RawMachineAssembler::Float32Equal, "Float32Equal", kEqual, kNotEqual,
1554     kEqual},
1555    {&RawMachineAssembler::Float32LessThan, "Float32LessThan",
1556     kFloatLessThan, kFloatGreaterThanOrEqualOrUnordered, kFloatGreaterThan},
1557    {&RawMachineAssembler::Float32LessThanOrEqual, "Float32LessThanOrEqual",
1558     kFloatLessThanOrEqual, kFloatGreaterThanOrUnordered,
1559     kFloatGreaterThanOrEqual}};
1560
1561}  // namespace
1562
1563typedef InstructionSelectorTestWithParam<Comparison>
1564    InstructionSelectorF32ComparisonTest;
1565
1566
1567TEST_P(InstructionSelectorF32ComparisonTest, WithParameters) {
1568  const Comparison& cmp = GetParam();
1569  StreamBuilder m(this, MachineType::Int32(), MachineType::Float32(),
1570                  MachineType::Float32());
1571  m.Return((m.*cmp.constructor)(m.Parameter(0), m.Parameter(1)));
1572  Stream const s = m.Build();
1573  ASSERT_EQ(1U, s.size());
1574  EXPECT_EQ(kArmVcmpF32, s[0]->arch_opcode());
1575  ASSERT_EQ(2U, s[0]->InputCount());
1576  ASSERT_EQ(1U, s[0]->OutputCount());
1577  EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1578  EXPECT_EQ(cmp.flags_condition, s[0]->flags_condition());
1579}
1580
1581
1582TEST_P(InstructionSelectorF32ComparisonTest, NegatedWithParameters) {
1583  const Comparison& cmp = GetParam();
1584  StreamBuilder m(this, MachineType::Int32(), MachineType::Float32(),
1585                  MachineType::Float32());
1586  m.Return(
1587      m.WordBinaryNot((m.*cmp.constructor)(m.Parameter(0), m.Parameter(1))));
1588  Stream const s = m.Build();
1589  ASSERT_EQ(1U, s.size());
1590  EXPECT_EQ(kArmVcmpF32, s[0]->arch_opcode());
1591  ASSERT_EQ(2U, s[0]->InputCount());
1592  ASSERT_EQ(1U, s[0]->OutputCount());
1593  EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1594  EXPECT_EQ(cmp.negated_flags_condition, s[0]->flags_condition());
1595}
1596
1597
1598TEST_P(InstructionSelectorF32ComparisonTest, WithImmediateZeroOnRight) {
1599  const Comparison& cmp = GetParam();
1600  StreamBuilder m(this, MachineType::Int32(), MachineType::Float32());
1601  m.Return((m.*cmp.constructor)(m.Parameter(0), m.Float32Constant(0.0)));
1602  Stream const s = m.Build();
1603  ASSERT_EQ(1U, s.size());
1604  EXPECT_EQ(kArmVcmpF32, s[0]->arch_opcode());
1605  ASSERT_EQ(2U, s[0]->InputCount());
1606  EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
1607  ASSERT_EQ(1U, s[0]->OutputCount());
1608  EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1609  EXPECT_EQ(cmp.flags_condition, s[0]->flags_condition());
1610}
1611
1612
1613TEST_P(InstructionSelectorF32ComparisonTest, WithImmediateZeroOnLeft) {
1614  const Comparison& cmp = GetParam();
1615  StreamBuilder m(this, MachineType::Int32(), MachineType::Float32());
1616  m.Return((m.*cmp.constructor)(m.Float32Constant(0.0f), m.Parameter(0)));
1617  Stream const s = m.Build();
1618  ASSERT_EQ(1U, s.size());
1619  EXPECT_EQ(kArmVcmpF32, s[0]->arch_opcode());
1620  ASSERT_EQ(2U, s[0]->InputCount());
1621  EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
1622  ASSERT_EQ(1U, s[0]->OutputCount());
1623  EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1624  EXPECT_EQ(cmp.commuted_flags_condition, s[0]->flags_condition());
1625}
1626
1627
1628INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1629                        InstructionSelectorF32ComparisonTest,
1630                        ::testing::ValuesIn(kF32Comparisons));
1631
1632
1633namespace {
1634
1635const Comparison kF64Comparisons[] = {
1636    {&RawMachineAssembler::Float64Equal, "Float64Equal", kEqual, kNotEqual,
1637     kEqual},
1638    {&RawMachineAssembler::Float64LessThan, "Float64LessThan",
1639     kFloatLessThan, kFloatGreaterThanOrEqualOrUnordered, kFloatGreaterThan},
1640    {&RawMachineAssembler::Float64LessThanOrEqual, "Float64LessThanOrEqual",
1641     kFloatLessThanOrEqual, kFloatGreaterThanOrUnordered,
1642     kFloatGreaterThanOrEqual}};
1643
1644}  // namespace
1645
1646typedef InstructionSelectorTestWithParam<Comparison>
1647    InstructionSelectorF64ComparisonTest;
1648
1649
1650TEST_P(InstructionSelectorF64ComparisonTest, WithParameters) {
1651  const Comparison& cmp = GetParam();
1652  StreamBuilder m(this, MachineType::Int32(), MachineType::Float64(),
1653                  MachineType::Float64());
1654  m.Return((m.*cmp.constructor)(m.Parameter(0), m.Parameter(1)));
1655  Stream const s = m.Build();
1656  ASSERT_EQ(1U, s.size());
1657  EXPECT_EQ(kArmVcmpF64, s[0]->arch_opcode());
1658  ASSERT_EQ(2U, s[0]->InputCount());
1659  ASSERT_EQ(1U, s[0]->OutputCount());
1660  EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1661  EXPECT_EQ(cmp.flags_condition, s[0]->flags_condition());
1662}
1663
1664
1665TEST_P(InstructionSelectorF64ComparisonTest, NegatedWithParameters) {
1666  const Comparison& cmp = GetParam();
1667  StreamBuilder m(this, MachineType::Int32(), MachineType::Float64(),
1668                  MachineType::Float64());
1669  m.Return(
1670      m.WordBinaryNot((m.*cmp.constructor)(m.Parameter(0), m.Parameter(1))));
1671  Stream const s = m.Build();
1672  ASSERT_EQ(1U, s.size());
1673  EXPECT_EQ(kArmVcmpF64, s[0]->arch_opcode());
1674  ASSERT_EQ(2U, s[0]->InputCount());
1675  ASSERT_EQ(1U, s[0]->OutputCount());
1676  EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1677  EXPECT_EQ(cmp.negated_flags_condition, s[0]->flags_condition());
1678}
1679
1680
1681TEST_P(InstructionSelectorF64ComparisonTest, WithImmediateZeroOnRight) {
1682  const Comparison& cmp = GetParam();
1683  StreamBuilder m(this, MachineType::Int32(), MachineType::Float64());
1684  m.Return((m.*cmp.constructor)(m.Parameter(0), m.Float64Constant(0.0)));
1685  Stream const s = m.Build();
1686  ASSERT_EQ(1U, s.size());
1687  EXPECT_EQ(kArmVcmpF64, s[0]->arch_opcode());
1688  ASSERT_EQ(2U, s[0]->InputCount());
1689  EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
1690  ASSERT_EQ(1U, s[0]->OutputCount());
1691  EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1692  EXPECT_EQ(cmp.flags_condition, s[0]->flags_condition());
1693}
1694
1695
1696TEST_P(InstructionSelectorF64ComparisonTest, WithImmediateZeroOnLeft) {
1697  const Comparison& cmp = GetParam();
1698  StreamBuilder m(this, MachineType::Int32(), MachineType::Float64());
1699  m.Return((m.*cmp.constructor)(m.Float64Constant(0.0), m.Parameter(0)));
1700  Stream const s = m.Build();
1701  ASSERT_EQ(1U, s.size());
1702  EXPECT_EQ(kArmVcmpF64, s[0]->arch_opcode());
1703  ASSERT_EQ(2U, s[0]->InputCount());
1704  EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
1705  ASSERT_EQ(1U, s[0]->OutputCount());
1706  EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1707  EXPECT_EQ(cmp.commuted_flags_condition, s[0]->flags_condition());
1708}
1709
1710
1711INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1712                        InstructionSelectorF64ComparisonTest,
1713                        ::testing::ValuesIn(kF64Comparisons));
1714
1715
1716// -----------------------------------------------------------------------------
1717// Floating point arithmetic.
1718
1719
1720typedef InstructionSelectorTestWithParam<FAI> InstructionSelectorFAITest;
1721
1722
1723TEST_P(InstructionSelectorFAITest, Parameters) {
1724  const FAI& fai = GetParam();
1725  StreamBuilder m(this, fai.machine_type, fai.machine_type, fai.machine_type);
1726  Node* const p0 = m.Parameter(0);
1727  Node* const p1 = m.Parameter(1);
1728  Node* const r = (m.*fai.constructor)(p0, p1);
1729  m.Return(r);
1730  Stream const s = m.Build();
1731  ASSERT_EQ(1U, s.size());
1732  EXPECT_EQ(fai.arch_opcode, s[0]->arch_opcode());
1733  EXPECT_EQ(kMode_None, s[0]->addressing_mode());
1734  ASSERT_EQ(2U, s[0]->InputCount());
1735  EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1736  EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
1737  ASSERT_EQ(1U, s[0]->OutputCount());
1738  EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->OutputAt(0)));
1739  EXPECT_EQ(kFlags_none, s[0]->flags_mode());
1740}
1741
1742
1743INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorFAITest,
1744                        ::testing::ValuesIn(kFAIs));
1745
1746
1747TEST_F(InstructionSelectorTest, Float32Abs) {
1748  StreamBuilder m(this, MachineType::Float32(), MachineType::Float32());
1749  Node* const p0 = m.Parameter(0);
1750  Node* const n = m.Float32Abs(p0);
1751  m.Return(n);
1752  Stream s = m.Build();
1753  ASSERT_EQ(1U, s.size());
1754  EXPECT_EQ(kArmVabsF32, s[0]->arch_opcode());
1755  ASSERT_EQ(1U, s[0]->InputCount());
1756  EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1757  ASSERT_EQ(1U, s[0]->OutputCount());
1758  EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1759}
1760
1761
1762TEST_F(InstructionSelectorTest, Float64Abs) {
1763  StreamBuilder m(this, MachineType::Float64(), MachineType::Float64());
1764  Node* const p0 = m.Parameter(0);
1765  Node* const n = m.Float64Abs(p0);
1766  m.Return(n);
1767  Stream s = m.Build();
1768  ASSERT_EQ(1U, s.size());
1769  EXPECT_EQ(kArmVabsF64, s[0]->arch_opcode());
1770  ASSERT_EQ(1U, s[0]->InputCount());
1771  EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1772  ASSERT_EQ(1U, s[0]->OutputCount());
1773  EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1774}
1775
1776
1777TEST_F(InstructionSelectorTest, Float32AddWithFloat32Mul) {
1778  {
1779    StreamBuilder m(this, MachineType::Float32(), MachineType::Float32(),
1780                    MachineType::Float32(), MachineType::Float32());
1781    Node* const p0 = m.Parameter(0);
1782    Node* const p1 = m.Parameter(1);
1783    Node* const p2 = m.Parameter(2);
1784    Node* const n = m.Float32Add(m.Float32Mul(p0, p1), p2);
1785    m.Return(n);
1786    Stream s = m.Build();
1787    ASSERT_EQ(1U, s.size());
1788    EXPECT_EQ(kArmVmlaF32, s[0]->arch_opcode());
1789    ASSERT_EQ(3U, s[0]->InputCount());
1790    EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(0)));
1791    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1)));
1792    EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(2)));
1793    ASSERT_EQ(1U, s[0]->OutputCount());
1794    EXPECT_TRUE(
1795        UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy());
1796    EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1797    EXPECT_EQ(kFlags_none, s[0]->flags_mode());
1798  }
1799  {
1800    StreamBuilder m(this, MachineType::Float32(), MachineType::Float32(),
1801                    MachineType::Float32(), MachineType::Float32());
1802    Node* const p0 = m.Parameter(0);
1803    Node* const p1 = m.Parameter(1);
1804    Node* const p2 = m.Parameter(2);
1805    Node* const n = m.Float32Add(p0, m.Float32Mul(p1, p2));
1806    m.Return(n);
1807    Stream s = m.Build();
1808    ASSERT_EQ(1U, s.size());
1809    EXPECT_EQ(kArmVmlaF32, s[0]->arch_opcode());
1810    ASSERT_EQ(3U, s[0]->InputCount());
1811    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1812    EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
1813    EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(2)));
1814    ASSERT_EQ(1U, s[0]->OutputCount());
1815    EXPECT_TRUE(
1816        UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy());
1817    EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1818    EXPECT_EQ(kFlags_none, s[0]->flags_mode());
1819  }
1820}
1821
1822
1823TEST_F(InstructionSelectorTest, Float64AddWithFloat64Mul) {
1824  {
1825    StreamBuilder m(this, MachineType::Float64(), MachineType::Float64(),
1826                    MachineType::Float64(), MachineType::Float64());
1827    Node* const p0 = m.Parameter(0);
1828    Node* const p1 = m.Parameter(1);
1829    Node* const p2 = m.Parameter(2);
1830    Node* const n = m.Float64Add(m.Float64Mul(p0, p1), p2);
1831    m.Return(n);
1832    Stream s = m.Build();
1833    ASSERT_EQ(1U, s.size());
1834    EXPECT_EQ(kArmVmlaF64, s[0]->arch_opcode());
1835    ASSERT_EQ(3U, s[0]->InputCount());
1836    EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(0)));
1837    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1)));
1838    EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(2)));
1839    ASSERT_EQ(1U, s[0]->OutputCount());
1840    EXPECT_TRUE(
1841        UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy());
1842    EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1843    EXPECT_EQ(kFlags_none, s[0]->flags_mode());
1844  }
1845  {
1846    StreamBuilder m(this, MachineType::Float64(), MachineType::Float64(),
1847                    MachineType::Float64(), MachineType::Float64());
1848    Node* const p0 = m.Parameter(0);
1849    Node* const p1 = m.Parameter(1);
1850    Node* const p2 = m.Parameter(2);
1851    Node* const n = m.Float64Add(p0, m.Float64Mul(p1, p2));
1852    m.Return(n);
1853    Stream s = m.Build();
1854    ASSERT_EQ(1U, s.size());
1855    EXPECT_EQ(kArmVmlaF64, s[0]->arch_opcode());
1856    ASSERT_EQ(3U, s[0]->InputCount());
1857    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1858    EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
1859    EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(2)));
1860    ASSERT_EQ(1U, s[0]->OutputCount());
1861    EXPECT_TRUE(
1862        UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy());
1863    EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1864    EXPECT_EQ(kFlags_none, s[0]->flags_mode());
1865  }
1866}
1867
1868
1869TEST_F(InstructionSelectorTest, Float32SubWithMinusZero) {
1870  StreamBuilder m(this, MachineType::Float32(), MachineType::Float32());
1871  Node* const p0 = m.Parameter(0);
1872  Node* const n = m.Float32Sub(m.Float32Constant(-0.0f), p0);
1873  m.Return(n);
1874  Stream s = m.Build();
1875  ASSERT_EQ(1U, s.size());
1876  EXPECT_EQ(kArmVnegF32, s[0]->arch_opcode());
1877  ASSERT_EQ(1U, s[0]->InputCount());
1878  EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1879  ASSERT_EQ(1U, s[0]->OutputCount());
1880  EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1881}
1882
1883
1884TEST_F(InstructionSelectorTest, Float64SubWithMinusZero) {
1885  StreamBuilder m(this, MachineType::Float64(), MachineType::Float64());
1886  Node* const p0 = m.Parameter(0);
1887  Node* const n = m.Float64Sub(m.Float64Constant(-0.0), p0);
1888  m.Return(n);
1889  Stream s = m.Build();
1890  ASSERT_EQ(1U, s.size());
1891  EXPECT_EQ(kArmVnegF64, s[0]->arch_opcode());
1892  ASSERT_EQ(1U, s[0]->InputCount());
1893  EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1894  ASSERT_EQ(1U, s[0]->OutputCount());
1895  EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1896}
1897
1898
1899TEST_F(InstructionSelectorTest, Float32SubWithFloat32Mul) {
1900  StreamBuilder m(this, MachineType::Float32(), MachineType::Float32(),
1901                  MachineType::Float32(), MachineType::Float32());
1902  Node* const p0 = m.Parameter(0);
1903  Node* const p1 = m.Parameter(1);
1904  Node* const p2 = m.Parameter(2);
1905  Node* const n = m.Float32Sub(p0, m.Float32Mul(p1, p2));
1906  m.Return(n);
1907  Stream s = m.Build();
1908  ASSERT_EQ(1U, s.size());
1909  EXPECT_EQ(kArmVmlsF32, s[0]->arch_opcode());
1910  ASSERT_EQ(3U, s[0]->InputCount());
1911  EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1912  EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
1913  EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(2)));
1914  ASSERT_EQ(1U, s[0]->OutputCount());
1915  EXPECT_TRUE(UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy());
1916  EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1917  EXPECT_EQ(kFlags_none, s[0]->flags_mode());
1918}
1919
1920
1921TEST_F(InstructionSelectorTest, Float64SubWithFloat64Mul) {
1922  StreamBuilder m(this, MachineType::Float64(), MachineType::Float64(),
1923                  MachineType::Float64(), MachineType::Float64());
1924  Node* const p0 = m.Parameter(0);
1925  Node* const p1 = m.Parameter(1);
1926  Node* const p2 = m.Parameter(2);
1927  Node* const n = m.Float64Sub(p0, m.Float64Mul(p1, p2));
1928  m.Return(n);
1929  Stream s = m.Build();
1930  ASSERT_EQ(1U, s.size());
1931  EXPECT_EQ(kArmVmlsF64, s[0]->arch_opcode());
1932  ASSERT_EQ(3U, s[0]->InputCount());
1933  EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1934  EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
1935  EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(2)));
1936  ASSERT_EQ(1U, s[0]->OutputCount());
1937  EXPECT_TRUE(UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy());
1938  EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1939  EXPECT_EQ(kFlags_none, s[0]->flags_mode());
1940}
1941
1942
1943TEST_F(InstructionSelectorTest, Float32Sqrt) {
1944  StreamBuilder m(this, MachineType::Float32(), MachineType::Float32());
1945  Node* const p0 = m.Parameter(0);
1946  Node* const n = m.Float32Sqrt(p0);
1947  m.Return(n);
1948  Stream s = m.Build();
1949  ASSERT_EQ(1U, s.size());
1950  EXPECT_EQ(kArmVsqrtF32, s[0]->arch_opcode());
1951  ASSERT_EQ(1U, s[0]->InputCount());
1952  EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1953  ASSERT_EQ(1U, s[0]->OutputCount());
1954  EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1955  EXPECT_EQ(kFlags_none, s[0]->flags_mode());
1956}
1957
1958
1959TEST_F(InstructionSelectorTest, Float64Sqrt) {
1960  StreamBuilder m(this, MachineType::Float64(), MachineType::Float64());
1961  Node* const p0 = m.Parameter(0);
1962  Node* const n = m.Float64Sqrt(p0);
1963  m.Return(n);
1964  Stream s = m.Build();
1965  ASSERT_EQ(1U, s.size());
1966  EXPECT_EQ(kArmVsqrtF64, s[0]->arch_opcode());
1967  ASSERT_EQ(1U, s[0]->InputCount());
1968  EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1969  ASSERT_EQ(1U, s[0]->OutputCount());
1970  EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1971  EXPECT_EQ(kFlags_none, s[0]->flags_mode());
1972}
1973
1974
1975// -----------------------------------------------------------------------------
1976// Miscellaneous.
1977
1978
1979TEST_F(InstructionSelectorTest, Int32AddWithInt32Mul) {
1980  {
1981    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
1982                    MachineType::Int32(), MachineType::Int32());
1983    Node* const p0 = m.Parameter(0);
1984    Node* const p1 = m.Parameter(1);
1985    Node* const p2 = m.Parameter(2);
1986    Node* const n = m.Int32Add(p0, m.Int32Mul(p1, p2));
1987    m.Return(n);
1988    Stream s = m.Build();
1989    ASSERT_EQ(1U, s.size());
1990    EXPECT_EQ(kArmMla, s[0]->arch_opcode());
1991    ASSERT_EQ(3U, s[0]->InputCount());
1992    EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(0)));
1993    EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(1)));
1994    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(2)));
1995    ASSERT_EQ(1U, s[0]->OutputCount());
1996    EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1997  }
1998  {
1999    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2000                    MachineType::Int32(), MachineType::Int32());
2001    Node* const p0 = m.Parameter(0);
2002    Node* const p1 = m.Parameter(1);
2003    Node* const p2 = m.Parameter(2);
2004    Node* const n = m.Int32Add(m.Int32Mul(p1, p2), p0);
2005    m.Return(n);
2006    Stream s = m.Build();
2007    ASSERT_EQ(1U, s.size());
2008    EXPECT_EQ(kArmMla, s[0]->arch_opcode());
2009    ASSERT_EQ(3U, s[0]->InputCount());
2010    EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(0)));
2011    EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(1)));
2012    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(2)));
2013    ASSERT_EQ(1U, s[0]->OutputCount());
2014    EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
2015  }
2016}
2017
2018
2019TEST_F(InstructionSelectorTest, Int32AddWithInt32MulHigh) {
2020  {
2021    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2022                    MachineType::Int32(), MachineType::Int32());
2023    Node* const p0 = m.Parameter(0);
2024    Node* const p1 = m.Parameter(1);
2025    Node* const p2 = m.Parameter(2);
2026    Node* const n = m.Int32Add(p0, m.Int32MulHigh(p1, p2));
2027    m.Return(n);
2028    Stream s = m.Build();
2029    ASSERT_EQ(1U, s.size());
2030    EXPECT_EQ(kArmSmmla, s[0]->arch_opcode());
2031    ASSERT_EQ(3U, s[0]->InputCount());
2032    EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(0)));
2033    EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(1)));
2034    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(2)));
2035    ASSERT_EQ(1U, s[0]->OutputCount());
2036    EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
2037  }
2038  {
2039    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2040                    MachineType::Int32(), MachineType::Int32());
2041    Node* const p0 = m.Parameter(0);
2042    Node* const p1 = m.Parameter(1);
2043    Node* const p2 = m.Parameter(2);
2044    Node* const n = m.Int32Add(m.Int32MulHigh(p1, p2), p0);
2045    m.Return(n);
2046    Stream s = m.Build();
2047    ASSERT_EQ(1U, s.size());
2048    EXPECT_EQ(kArmSmmla, s[0]->arch_opcode());
2049    ASSERT_EQ(3U, s[0]->InputCount());
2050    EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(0)));
2051    EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(1)));
2052    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(2)));
2053    ASSERT_EQ(1U, s[0]->OutputCount());
2054    EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
2055  }
2056}
2057
2058
2059TEST_F(InstructionSelectorTest, Int32AddWithWord32And) {
2060  {
2061    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2062                    MachineType::Int32());
2063    Node* const p0 = m.Parameter(0);
2064    Node* const p1 = m.Parameter(1);
2065    Node* const r = m.Int32Add(m.Word32And(p0, m.Int32Constant(0xff)), p1);
2066    m.Return(r);
2067    Stream s = m.Build();
2068    ASSERT_EQ(1U, s.size());
2069    EXPECT_EQ(kArmUxtab, s[0]->arch_opcode());
2070    ASSERT_EQ(3U, s[0]->InputCount());
2071    EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(0)));
2072    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1)));
2073    EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(2)));
2074    ASSERT_EQ(1U, s[0]->OutputCount());
2075    EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
2076  }
2077  {
2078    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2079                    MachineType::Int32());
2080    Node* const p0 = m.Parameter(0);
2081    Node* const p1 = m.Parameter(1);
2082    Node* const r = m.Int32Add(p1, m.Word32And(p0, m.Int32Constant(0xff)));
2083    m.Return(r);
2084    Stream s = m.Build();
2085    ASSERT_EQ(1U, s.size());
2086    EXPECT_EQ(kArmUxtab, s[0]->arch_opcode());
2087    ASSERT_EQ(3U, s[0]->InputCount());
2088    EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(0)));
2089    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1)));
2090    EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(2)));
2091    ASSERT_EQ(1U, s[0]->OutputCount());
2092    EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
2093  }
2094  {
2095    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2096                    MachineType::Int32());
2097    Node* const p0 = m.Parameter(0);
2098    Node* const p1 = m.Parameter(1);
2099    Node* const r = m.Int32Add(m.Word32And(p0, m.Int32Constant(0xffff)), p1);
2100    m.Return(r);
2101    Stream s = m.Build();
2102    ASSERT_EQ(1U, s.size());
2103    EXPECT_EQ(kArmUxtah, s[0]->arch_opcode());
2104    ASSERT_EQ(3U, s[0]->InputCount());
2105    EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(0)));
2106    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1)));
2107    EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(2)));
2108    ASSERT_EQ(1U, s[0]->OutputCount());
2109    EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
2110  }
2111  {
2112    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2113                    MachineType::Int32());
2114    Node* const p0 = m.Parameter(0);
2115    Node* const p1 = m.Parameter(1);
2116    Node* const r = m.Int32Add(p1, m.Word32And(p0, m.Int32Constant(0xffff)));
2117    m.Return(r);
2118    Stream s = m.Build();
2119    ASSERT_EQ(1U, s.size());
2120    EXPECT_EQ(kArmUxtah, s[0]->arch_opcode());
2121    ASSERT_EQ(3U, s[0]->InputCount());
2122    EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(0)));
2123    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1)));
2124    EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(2)));
2125    ASSERT_EQ(1U, s[0]->OutputCount());
2126    EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
2127  }
2128}
2129
2130
2131TEST_F(InstructionSelectorTest, Int32AddWithWord32SarWithWord32Shl) {
2132  {
2133    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2134                    MachineType::Int32());
2135    Node* const p0 = m.Parameter(0);
2136    Node* const p1 = m.Parameter(1);
2137    Node* const r = m.Int32Add(
2138        m.Word32Sar(m.Word32Shl(p0, m.Int32Constant(24)), m.Int32Constant(24)),
2139        p1);
2140    m.Return(r);
2141    Stream s = m.Build();
2142    ASSERT_EQ(1U, s.size());
2143    EXPECT_EQ(kArmSxtab, s[0]->arch_opcode());
2144    ASSERT_EQ(3U, s[0]->InputCount());
2145    EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(0)));
2146    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1)));
2147    EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(2)));
2148    ASSERT_EQ(1U, s[0]->OutputCount());
2149    EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
2150  }
2151  {
2152    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2153                    MachineType::Int32());
2154    Node* const p0 = m.Parameter(0);
2155    Node* const p1 = m.Parameter(1);
2156    Node* const r = m.Int32Add(
2157        p1,
2158        m.Word32Sar(m.Word32Shl(p0, m.Int32Constant(24)), m.Int32Constant(24)));
2159    m.Return(r);
2160    Stream s = m.Build();
2161    ASSERT_EQ(1U, s.size());
2162    EXPECT_EQ(kArmSxtab, s[0]->arch_opcode());
2163    ASSERT_EQ(3U, s[0]->InputCount());
2164    EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(0)));
2165    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1)));
2166    EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(2)));
2167    ASSERT_EQ(1U, s[0]->OutputCount());
2168    EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
2169  }
2170  {
2171    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2172                    MachineType::Int32());
2173    Node* const p0 = m.Parameter(0);
2174    Node* const p1 = m.Parameter(1);
2175    Node* const r = m.Int32Add(
2176        m.Word32Sar(m.Word32Shl(p0, m.Int32Constant(16)), m.Int32Constant(16)),
2177        p1);
2178    m.Return(r);
2179    Stream s = m.Build();
2180    ASSERT_EQ(1U, s.size());
2181    EXPECT_EQ(kArmSxtah, s[0]->arch_opcode());
2182    ASSERT_EQ(3U, s[0]->InputCount());
2183    EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(0)));
2184    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1)));
2185    EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(2)));
2186    ASSERT_EQ(1U, s[0]->OutputCount());
2187    EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
2188  }
2189  {
2190    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2191                    MachineType::Int32());
2192    Node* const p0 = m.Parameter(0);
2193    Node* const p1 = m.Parameter(1);
2194    Node* const r = m.Int32Add(
2195        p1,
2196        m.Word32Sar(m.Word32Shl(p0, m.Int32Constant(16)), m.Int32Constant(16)));
2197    m.Return(r);
2198    Stream s = m.Build();
2199    ASSERT_EQ(1U, s.size());
2200    EXPECT_EQ(kArmSxtah, s[0]->arch_opcode());
2201    ASSERT_EQ(3U, s[0]->InputCount());
2202    EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(0)));
2203    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1)));
2204    EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(2)));
2205    ASSERT_EQ(1U, s[0]->OutputCount());
2206    EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
2207  }
2208}
2209
2210
2211TEST_F(InstructionSelectorTest, Int32SubWithInt32Mul) {
2212  StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2213                  MachineType::Int32(), MachineType::Int32());
2214  m.Return(
2215      m.Int32Sub(m.Parameter(0), m.Int32Mul(m.Parameter(1), m.Parameter(2))));
2216  Stream s = m.Build();
2217  ASSERT_EQ(2U, s.size());
2218  EXPECT_EQ(kArmMul, s[0]->arch_opcode());
2219  ASSERT_EQ(1U, s[0]->OutputCount());
2220  EXPECT_EQ(kArmSub, s[1]->arch_opcode());
2221  ASSERT_EQ(2U, s[1]->InputCount());
2222  EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(1)));
2223}
2224
2225
2226TEST_F(InstructionSelectorTest, Int32SubWithInt32MulForMLS) {
2227  StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2228                  MachineType::Int32(), MachineType::Int32());
2229  m.Return(
2230      m.Int32Sub(m.Parameter(0), m.Int32Mul(m.Parameter(1), m.Parameter(2))));
2231  Stream s = m.Build(MLS);
2232  ASSERT_EQ(1U, s.size());
2233  EXPECT_EQ(kArmMls, s[0]->arch_opcode());
2234  EXPECT_EQ(1U, s[0]->OutputCount());
2235  EXPECT_EQ(3U, s[0]->InputCount());
2236}
2237
2238
2239TEST_F(InstructionSelectorTest, Int32DivWithParameters) {
2240  StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2241                  MachineType::Int32());
2242  m.Return(m.Int32Div(m.Parameter(0), m.Parameter(1)));
2243  Stream s = m.Build();
2244  ASSERT_EQ(4U, s.size());
2245  EXPECT_EQ(kArmVcvtF64S32, s[0]->arch_opcode());
2246  ASSERT_EQ(1U, s[0]->OutputCount());
2247  EXPECT_EQ(kArmVcvtF64S32, s[1]->arch_opcode());
2248  ASSERT_EQ(1U, s[1]->OutputCount());
2249  EXPECT_EQ(kArmVdivF64, s[2]->arch_opcode());
2250  ASSERT_EQ(2U, s[2]->InputCount());
2251  ASSERT_EQ(1U, s[2]->OutputCount());
2252  EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[2]->InputAt(0)));
2253  EXPECT_EQ(s.ToVreg(s[1]->Output()), s.ToVreg(s[2]->InputAt(1)));
2254  EXPECT_EQ(kArmVcvtS32F64, s[3]->arch_opcode());
2255  ASSERT_EQ(1U, s[3]->InputCount());
2256  EXPECT_EQ(s.ToVreg(s[2]->Output()), s.ToVreg(s[3]->InputAt(0)));
2257}
2258
2259
2260TEST_F(InstructionSelectorTest, Int32DivWithParametersForSUDIV) {
2261  StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2262                  MachineType::Int32());
2263  m.Return(m.Int32Div(m.Parameter(0), m.Parameter(1)));
2264  Stream s = m.Build(SUDIV);
2265  ASSERT_EQ(1U, s.size());
2266  EXPECT_EQ(kArmSdiv, s[0]->arch_opcode());
2267}
2268
2269
2270TEST_F(InstructionSelectorTest, Int32ModWithParameters) {
2271  StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2272                  MachineType::Int32());
2273  m.Return(m.Int32Mod(m.Parameter(0), m.Parameter(1)));
2274  Stream s = m.Build();
2275  ASSERT_EQ(6U, s.size());
2276  EXPECT_EQ(kArmVcvtF64S32, s[0]->arch_opcode());
2277  ASSERT_EQ(1U, s[0]->OutputCount());
2278  EXPECT_EQ(kArmVcvtF64S32, s[1]->arch_opcode());
2279  ASSERT_EQ(1U, s[1]->OutputCount());
2280  EXPECT_EQ(kArmVdivF64, s[2]->arch_opcode());
2281  ASSERT_EQ(2U, s[2]->InputCount());
2282  ASSERT_EQ(1U, s[2]->OutputCount());
2283  EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[2]->InputAt(0)));
2284  EXPECT_EQ(s.ToVreg(s[1]->Output()), s.ToVreg(s[2]->InputAt(1)));
2285  EXPECT_EQ(kArmVcvtS32F64, s[3]->arch_opcode());
2286  ASSERT_EQ(1U, s[3]->InputCount());
2287  EXPECT_EQ(s.ToVreg(s[2]->Output()), s.ToVreg(s[3]->InputAt(0)));
2288  EXPECT_EQ(kArmMul, s[4]->arch_opcode());
2289  ASSERT_EQ(1U, s[4]->OutputCount());
2290  ASSERT_EQ(2U, s[4]->InputCount());
2291  EXPECT_EQ(s.ToVreg(s[3]->Output()), s.ToVreg(s[4]->InputAt(0)));
2292  EXPECT_EQ(s.ToVreg(s[1]->InputAt(0)), s.ToVreg(s[4]->InputAt(1)));
2293  EXPECT_EQ(kArmSub, s[5]->arch_opcode());
2294  ASSERT_EQ(1U, s[5]->OutputCount());
2295  ASSERT_EQ(2U, s[5]->InputCount());
2296  EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[5]->InputAt(0)));
2297  EXPECT_EQ(s.ToVreg(s[4]->Output()), s.ToVreg(s[5]->InputAt(1)));
2298}
2299
2300
2301TEST_F(InstructionSelectorTest, Int32ModWithParametersForSUDIV) {
2302  StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2303                  MachineType::Int32());
2304  m.Return(m.Int32Mod(m.Parameter(0), m.Parameter(1)));
2305  Stream s = m.Build(SUDIV);
2306  ASSERT_EQ(3U, s.size());
2307  EXPECT_EQ(kArmSdiv, s[0]->arch_opcode());
2308  ASSERT_EQ(1U, s[0]->OutputCount());
2309  ASSERT_EQ(2U, s[0]->InputCount());
2310  EXPECT_EQ(kArmMul, s[1]->arch_opcode());
2311  ASSERT_EQ(1U, s[1]->OutputCount());
2312  ASSERT_EQ(2U, s[1]->InputCount());
2313  EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(0)));
2314  EXPECT_EQ(s.ToVreg(s[0]->InputAt(1)), s.ToVreg(s[1]->InputAt(1)));
2315  EXPECT_EQ(kArmSub, s[2]->arch_opcode());
2316  ASSERT_EQ(1U, s[2]->OutputCount());
2317  ASSERT_EQ(2U, s[2]->InputCount());
2318  EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[2]->InputAt(0)));
2319  EXPECT_EQ(s.ToVreg(s[1]->Output()), s.ToVreg(s[2]->InputAt(1)));
2320}
2321
2322
2323TEST_F(InstructionSelectorTest, Int32ModWithParametersForSUDIVAndMLS) {
2324  StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2325                  MachineType::Int32());
2326  m.Return(m.Int32Mod(m.Parameter(0), m.Parameter(1)));
2327  Stream s = m.Build(MLS, SUDIV);
2328  ASSERT_EQ(2U, s.size());
2329  EXPECT_EQ(kArmSdiv, s[0]->arch_opcode());
2330  ASSERT_EQ(1U, s[0]->OutputCount());
2331  ASSERT_EQ(2U, s[0]->InputCount());
2332  EXPECT_EQ(kArmMls, s[1]->arch_opcode());
2333  ASSERT_EQ(1U, s[1]->OutputCount());
2334  ASSERT_EQ(3U, s[1]->InputCount());
2335  EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(0)));
2336  EXPECT_EQ(s.ToVreg(s[0]->InputAt(1)), s.ToVreg(s[1]->InputAt(1)));
2337  EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[1]->InputAt(2)));
2338}
2339
2340
2341TEST_F(InstructionSelectorTest, Int32MulWithParameters) {
2342  StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2343                  MachineType::Int32());
2344  m.Return(m.Int32Mul(m.Parameter(0), m.Parameter(1)));
2345  Stream s = m.Build();
2346  ASSERT_EQ(1U, s.size());
2347  EXPECT_EQ(kArmMul, s[0]->arch_opcode());
2348  EXPECT_EQ(2U, s[0]->InputCount());
2349  EXPECT_EQ(1U, s[0]->OutputCount());
2350}
2351
2352
2353TEST_F(InstructionSelectorTest, Int32MulWithImmediate) {
2354  // x * (2^k + 1) -> x + (x >> k)
2355  TRACED_FORRANGE(int32_t, k, 1, 30) {
2356    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2357    m.Return(m.Int32Mul(m.Parameter(0), m.Int32Constant((1 << k) + 1)));
2358    Stream s = m.Build();
2359    ASSERT_EQ(1U, s.size());
2360    EXPECT_EQ(kArmAdd, s[0]->arch_opcode());
2361    EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
2362    ASSERT_EQ(3U, s[0]->InputCount());
2363    EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
2364    EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2)));
2365    EXPECT_EQ(1U, s[0]->OutputCount());
2366  }
2367  // x * (2^k - 1) -> -x + (x >> k)
2368  TRACED_FORRANGE(int32_t, k, 3, 30) {
2369    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2370    m.Return(m.Int32Mul(m.Parameter(0), m.Int32Constant((1 << k) - 1)));
2371    Stream s = m.Build();
2372    ASSERT_EQ(1U, s.size());
2373    EXPECT_EQ(kArmRsb, s[0]->arch_opcode());
2374    EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
2375    ASSERT_EQ(3U, s[0]->InputCount());
2376    EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
2377    EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2)));
2378    EXPECT_EQ(1U, s[0]->OutputCount());
2379  }
2380  // (2^k + 1) * x -> x + (x >> k)
2381  TRACED_FORRANGE(int32_t, k, 1, 30) {
2382    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2383    m.Return(m.Int32Mul(m.Int32Constant((1 << k) + 1), m.Parameter(0)));
2384    Stream s = m.Build();
2385    ASSERT_EQ(1U, s.size());
2386    EXPECT_EQ(kArmAdd, s[0]->arch_opcode());
2387    EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
2388    ASSERT_EQ(3U, s[0]->InputCount());
2389    EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
2390    EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2)));
2391    EXPECT_EQ(1U, s[0]->OutputCount());
2392  }
2393  // x * (2^k - 1) -> -x + (x >> k)
2394  TRACED_FORRANGE(int32_t, k, 3, 30) {
2395    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2396    m.Return(m.Int32Mul(m.Int32Constant((1 << k) - 1), m.Parameter(0)));
2397    Stream s = m.Build();
2398    ASSERT_EQ(1U, s.size());
2399    EXPECT_EQ(kArmRsb, s[0]->arch_opcode());
2400    EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
2401    ASSERT_EQ(3U, s[0]->InputCount());
2402    EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
2403    EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2)));
2404    EXPECT_EQ(1U, s[0]->OutputCount());
2405  }
2406}
2407
2408
2409TEST_F(InstructionSelectorTest, Int32MulHighWithParameters) {
2410  StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2411                  MachineType::Int32());
2412  Node* const p0 = m.Parameter(0);
2413  Node* const p1 = m.Parameter(1);
2414  Node* const n = m.Int32MulHigh(p0, p1);
2415  m.Return(n);
2416  Stream s = m.Build();
2417  ASSERT_EQ(1U, s.size());
2418  EXPECT_EQ(kArmSmmul, s[0]->arch_opcode());
2419  ASSERT_EQ(2U, s[0]->InputCount());
2420  EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
2421  EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
2422  ASSERT_EQ(1U, s[0]->OutputCount());
2423  EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
2424}
2425
2426
2427TEST_F(InstructionSelectorTest, Uint32MulHighWithParameters) {
2428  StreamBuilder m(this, MachineType::Uint32(), MachineType::Uint32(),
2429                  MachineType::Uint32());
2430  Node* const p0 = m.Parameter(0);
2431  Node* const p1 = m.Parameter(1);
2432  Node* const n = m.Uint32MulHigh(p0, p1);
2433  m.Return(n);
2434  Stream s = m.Build();
2435  ASSERT_EQ(1U, s.size());
2436  EXPECT_EQ(kArmUmull, s[0]->arch_opcode());
2437  ASSERT_EQ(2U, s[0]->InputCount());
2438  EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
2439  EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
2440  ASSERT_EQ(2U, s[0]->OutputCount());
2441  EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->OutputAt(1)));
2442}
2443
2444
2445TEST_F(InstructionSelectorTest, Uint32DivWithParameters) {
2446  StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2447                  MachineType::Int32());
2448  m.Return(m.Uint32Div(m.Parameter(0), m.Parameter(1)));
2449  Stream s = m.Build();
2450  ASSERT_EQ(4U, s.size());
2451  EXPECT_EQ(kArmVcvtF64U32, s[0]->arch_opcode());
2452  ASSERT_EQ(1U, s[0]->OutputCount());
2453  EXPECT_EQ(kArmVcvtF64U32, s[1]->arch_opcode());
2454  ASSERT_EQ(1U, s[1]->OutputCount());
2455  EXPECT_EQ(kArmVdivF64, s[2]->arch_opcode());
2456  ASSERT_EQ(2U, s[2]->InputCount());
2457  ASSERT_EQ(1U, s[2]->OutputCount());
2458  EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[2]->InputAt(0)));
2459  EXPECT_EQ(s.ToVreg(s[1]->Output()), s.ToVreg(s[2]->InputAt(1)));
2460  EXPECT_EQ(kArmVcvtU32F64, s[3]->arch_opcode());
2461  ASSERT_EQ(1U, s[3]->InputCount());
2462  EXPECT_EQ(s.ToVreg(s[2]->Output()), s.ToVreg(s[3]->InputAt(0)));
2463}
2464
2465
2466TEST_F(InstructionSelectorTest, Uint32DivWithParametersForSUDIV) {
2467  StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2468                  MachineType::Int32());
2469  m.Return(m.Uint32Div(m.Parameter(0), m.Parameter(1)));
2470  Stream s = m.Build(SUDIV);
2471  ASSERT_EQ(1U, s.size());
2472  EXPECT_EQ(kArmUdiv, s[0]->arch_opcode());
2473}
2474
2475
2476TEST_F(InstructionSelectorTest, Uint32ModWithParameters) {
2477  StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2478                  MachineType::Int32());
2479  m.Return(m.Uint32Mod(m.Parameter(0), m.Parameter(1)));
2480  Stream s = m.Build();
2481  ASSERT_EQ(6U, s.size());
2482  EXPECT_EQ(kArmVcvtF64U32, s[0]->arch_opcode());
2483  ASSERT_EQ(1U, s[0]->OutputCount());
2484  EXPECT_EQ(kArmVcvtF64U32, s[1]->arch_opcode());
2485  ASSERT_EQ(1U, s[1]->OutputCount());
2486  EXPECT_EQ(kArmVdivF64, s[2]->arch_opcode());
2487  ASSERT_EQ(2U, s[2]->InputCount());
2488  ASSERT_EQ(1U, s[2]->OutputCount());
2489  EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[2]->InputAt(0)));
2490  EXPECT_EQ(s.ToVreg(s[1]->Output()), s.ToVreg(s[2]->InputAt(1)));
2491  EXPECT_EQ(kArmVcvtU32F64, s[3]->arch_opcode());
2492  ASSERT_EQ(1U, s[3]->InputCount());
2493  EXPECT_EQ(s.ToVreg(s[2]->Output()), s.ToVreg(s[3]->InputAt(0)));
2494  EXPECT_EQ(kArmMul, s[4]->arch_opcode());
2495  ASSERT_EQ(1U, s[4]->OutputCount());
2496  ASSERT_EQ(2U, s[4]->InputCount());
2497  EXPECT_EQ(s.ToVreg(s[3]->Output()), s.ToVreg(s[4]->InputAt(0)));
2498  EXPECT_EQ(s.ToVreg(s[1]->InputAt(0)), s.ToVreg(s[4]->InputAt(1)));
2499  EXPECT_EQ(kArmSub, s[5]->arch_opcode());
2500  ASSERT_EQ(1U, s[5]->OutputCount());
2501  ASSERT_EQ(2U, s[5]->InputCount());
2502  EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[5]->InputAt(0)));
2503  EXPECT_EQ(s.ToVreg(s[4]->Output()), s.ToVreg(s[5]->InputAt(1)));
2504}
2505
2506
2507TEST_F(InstructionSelectorTest, Uint32ModWithParametersForSUDIV) {
2508  StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2509                  MachineType::Int32());
2510  m.Return(m.Uint32Mod(m.Parameter(0), m.Parameter(1)));
2511  Stream s = m.Build(SUDIV);
2512  ASSERT_EQ(3U, s.size());
2513  EXPECT_EQ(kArmUdiv, s[0]->arch_opcode());
2514  ASSERT_EQ(1U, s[0]->OutputCount());
2515  ASSERT_EQ(2U, s[0]->InputCount());
2516  EXPECT_EQ(kArmMul, s[1]->arch_opcode());
2517  ASSERT_EQ(1U, s[1]->OutputCount());
2518  ASSERT_EQ(2U, s[1]->InputCount());
2519  EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(0)));
2520  EXPECT_EQ(s.ToVreg(s[0]->InputAt(1)), s.ToVreg(s[1]->InputAt(1)));
2521  EXPECT_EQ(kArmSub, s[2]->arch_opcode());
2522  ASSERT_EQ(1U, s[2]->OutputCount());
2523  ASSERT_EQ(2U, s[2]->InputCount());
2524  EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[2]->InputAt(0)));
2525  EXPECT_EQ(s.ToVreg(s[1]->Output()), s.ToVreg(s[2]->InputAt(1)));
2526}
2527
2528
2529TEST_F(InstructionSelectorTest, Uint32ModWithParametersForSUDIVAndMLS) {
2530  StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2531                  MachineType::Int32());
2532  m.Return(m.Uint32Mod(m.Parameter(0), m.Parameter(1)));
2533  Stream s = m.Build(MLS, SUDIV);
2534  ASSERT_EQ(2U, s.size());
2535  EXPECT_EQ(kArmUdiv, s[0]->arch_opcode());
2536  ASSERT_EQ(1U, s[0]->OutputCount());
2537  ASSERT_EQ(2U, s[0]->InputCount());
2538  EXPECT_EQ(kArmMls, s[1]->arch_opcode());
2539  ASSERT_EQ(1U, s[1]->OutputCount());
2540  ASSERT_EQ(3U, s[1]->InputCount());
2541  EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(0)));
2542  EXPECT_EQ(s.ToVreg(s[0]->InputAt(1)), s.ToVreg(s[1]->InputAt(1)));
2543  EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[1]->InputAt(2)));
2544}
2545
2546
2547TEST_F(InstructionSelectorTest, Word32AndWithUbfxImmediateForARMv7) {
2548  TRACED_FORRANGE(int32_t, width, 1, 32) {
2549    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2550    m.Return(m.Word32And(m.Parameter(0),
2551                         m.Int32Constant(0xffffffffu >> (32 - width))));
2552    Stream s = m.Build(ARMv7);
2553    ASSERT_EQ(1U, s.size());
2554    EXPECT_EQ(kArmUbfx, s[0]->arch_opcode());
2555    ASSERT_EQ(3U, s[0]->InputCount());
2556    EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1)));
2557    EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
2558  }
2559  TRACED_FORRANGE(int32_t, width, 1, 32) {
2560    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2561    m.Return(m.Word32And(m.Int32Constant(0xffffffffu >> (32 - width)),
2562                         m.Parameter(0)));
2563    Stream s = m.Build(ARMv7);
2564    ASSERT_EQ(1U, s.size());
2565    EXPECT_EQ(kArmUbfx, s[0]->arch_opcode());
2566    ASSERT_EQ(3U, s[0]->InputCount());
2567    EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1)));
2568    EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
2569  }
2570}
2571
2572
2573TEST_F(InstructionSelectorTest, Word32AndWithBfcImmediateForARMv7) {
2574  TRACED_FORRANGE(int32_t, lsb, 0, 31) {
2575    TRACED_FORRANGE(int32_t, width, 9, (32 - lsb) - 1) {
2576      StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2577      m.Return(m.Word32And(
2578          m.Parameter(0),
2579          m.Int32Constant(~((0xffffffffu >> (32 - width)) << lsb))));
2580      Stream s = m.Build(ARMv7);
2581      ASSERT_EQ(1U, s.size());
2582      EXPECT_EQ(kArmBfc, s[0]->arch_opcode());
2583      ASSERT_EQ(1U, s[0]->OutputCount());
2584      EXPECT_TRUE(
2585          UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy());
2586      ASSERT_EQ(3U, s[0]->InputCount());
2587      EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
2588      EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
2589    }
2590  }
2591  TRACED_FORRANGE(int32_t, lsb, 0, 31) {
2592    TRACED_FORRANGE(int32_t, width, 9, (32 - lsb) - 1) {
2593      StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2594      m.Return(
2595          m.Word32And(m.Int32Constant(~((0xffffffffu >> (32 - width)) << lsb)),
2596                      m.Parameter(0)));
2597      Stream s = m.Build(ARMv7);
2598      ASSERT_EQ(1U, s.size());
2599      EXPECT_EQ(kArmBfc, s[0]->arch_opcode());
2600      ASSERT_EQ(1U, s[0]->OutputCount());
2601      EXPECT_TRUE(
2602          UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy());
2603      ASSERT_EQ(3U, s[0]->InputCount());
2604      EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
2605      EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
2606    }
2607  }
2608}
2609
2610
2611TEST_F(InstructionSelectorTest, Word32AndWith0xffff) {
2612  {
2613    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2614    Node* const p0 = m.Parameter(0);
2615    Node* const r = m.Word32And(p0, m.Int32Constant(0xffff));
2616    m.Return(r);
2617    Stream s = m.Build();
2618    ASSERT_EQ(1U, s.size());
2619    EXPECT_EQ(kArmUxth, s[0]->arch_opcode());
2620    ASSERT_EQ(2U, s[0]->InputCount());
2621    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
2622    EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1)));
2623    ASSERT_EQ(1U, s[0]->OutputCount());
2624    EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
2625  }
2626  {
2627    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2628    Node* const p0 = m.Parameter(0);
2629    Node* const r = m.Word32And(m.Int32Constant(0xffff), p0);
2630    m.Return(r);
2631    Stream s = m.Build();
2632    ASSERT_EQ(1U, s.size());
2633    EXPECT_EQ(kArmUxth, s[0]->arch_opcode());
2634    ASSERT_EQ(2U, s[0]->InputCount());
2635    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
2636    EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1)));
2637    ASSERT_EQ(1U, s[0]->OutputCount());
2638    EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
2639  }
2640}
2641
2642
2643TEST_F(InstructionSelectorTest, Word32SarWithWord32Shl) {
2644  {
2645    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2646    Node* const p0 = m.Parameter(0);
2647    Node* const r =
2648        m.Word32Sar(m.Word32Shl(p0, m.Int32Constant(24)), m.Int32Constant(24));
2649    m.Return(r);
2650    Stream s = m.Build();
2651    ASSERT_EQ(1U, s.size());
2652    EXPECT_EQ(kArmSxtb, s[0]->arch_opcode());
2653    ASSERT_EQ(2U, s[0]->InputCount());
2654    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
2655    EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1)));
2656    ASSERT_EQ(1U, s[0]->OutputCount());
2657    EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
2658  }
2659  {
2660    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2661    Node* const p0 = m.Parameter(0);
2662    Node* const r =
2663        m.Word32Sar(m.Word32Shl(p0, m.Int32Constant(16)), m.Int32Constant(16));
2664    m.Return(r);
2665    Stream s = m.Build();
2666    ASSERT_EQ(1U, s.size());
2667    EXPECT_EQ(kArmSxth, s[0]->arch_opcode());
2668    ASSERT_EQ(2U, s[0]->InputCount());
2669    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
2670    EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1)));
2671    ASSERT_EQ(1U, s[0]->OutputCount());
2672    EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
2673  }
2674}
2675
2676
2677TEST_F(InstructionSelectorTest, Word32ShrWithWord32AndWithImmediateForARMv7) {
2678  TRACED_FORRANGE(int32_t, lsb, 0, 31) {
2679    TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) {
2680      uint32_t max = 1 << lsb;
2681      if (max > static_cast<uint32_t>(kMaxInt)) max -= 1;
2682      uint32_t jnk = rng()->NextInt(max);
2683      uint32_t msk = ((0xffffffffu >> (32 - width)) << lsb) | jnk;
2684      StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2685      m.Return(m.Word32Shr(m.Word32And(m.Parameter(0), m.Int32Constant(msk)),
2686                           m.Int32Constant(lsb)));
2687      Stream s = m.Build(ARMv7);
2688      ASSERT_EQ(1U, s.size());
2689      EXPECT_EQ(kArmUbfx, s[0]->arch_opcode());
2690      ASSERT_EQ(3U, s[0]->InputCount());
2691      EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
2692      EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
2693    }
2694  }
2695  TRACED_FORRANGE(int32_t, lsb, 0, 31) {
2696    TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) {
2697      uint32_t max = 1 << lsb;
2698      if (max > static_cast<uint32_t>(kMaxInt)) max -= 1;
2699      uint32_t jnk = rng()->NextInt(max);
2700      uint32_t msk = ((0xffffffffu >> (32 - width)) << lsb) | jnk;
2701      StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2702      m.Return(m.Word32Shr(m.Word32And(m.Int32Constant(msk), m.Parameter(0)),
2703                           m.Int32Constant(lsb)));
2704      Stream s = m.Build(ARMv7);
2705      ASSERT_EQ(1U, s.size());
2706      EXPECT_EQ(kArmUbfx, s[0]->arch_opcode());
2707      ASSERT_EQ(3U, s[0]->InputCount());
2708      EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
2709      EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
2710    }
2711  }
2712}
2713
2714
2715TEST_F(InstructionSelectorTest, Word32AndWithWord32Not) {
2716  {
2717    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2718                    MachineType::Int32());
2719    m.Return(m.Word32And(m.Parameter(0), m.Word32Not(m.Parameter(1))));
2720    Stream s = m.Build();
2721    ASSERT_EQ(1U, s.size());
2722    EXPECT_EQ(kArmBic, s[0]->arch_opcode());
2723    EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
2724    EXPECT_EQ(2U, s[0]->InputCount());
2725    EXPECT_EQ(1U, s[0]->OutputCount());
2726  }
2727  {
2728    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2729                    MachineType::Int32());
2730    m.Return(m.Word32And(m.Word32Not(m.Parameter(0)), m.Parameter(1)));
2731    Stream s = m.Build();
2732    ASSERT_EQ(1U, s.size());
2733    EXPECT_EQ(kArmBic, s[0]->arch_opcode());
2734    EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
2735    EXPECT_EQ(2U, s[0]->InputCount());
2736    EXPECT_EQ(1U, s[0]->OutputCount());
2737  }
2738}
2739
2740
2741TEST_F(InstructionSelectorTest, Word32EqualWithParameters) {
2742  StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2743                  MachineType::Int32());
2744  m.Return(m.Word32Equal(m.Parameter(0), m.Parameter(1)));
2745  Stream s = m.Build();
2746  ASSERT_EQ(1U, s.size());
2747  EXPECT_EQ(kArmCmp, s[0]->arch_opcode());
2748  EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
2749  EXPECT_EQ(2U, s[0]->InputCount());
2750  EXPECT_EQ(1U, s[0]->OutputCount());
2751  EXPECT_EQ(kFlags_set, s[0]->flags_mode());
2752  EXPECT_EQ(kEqual, s[0]->flags_condition());
2753}
2754
2755
2756TEST_F(InstructionSelectorTest, Word32EqualWithImmediate) {
2757  TRACED_FOREACH(int32_t, imm, kImmediates) {
2758    if (imm == 0) continue;
2759    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2760    m.Return(m.Word32Equal(m.Parameter(0), m.Int32Constant(imm)));
2761    Stream s = m.Build();
2762    ASSERT_EQ(1U, s.size());
2763    EXPECT_EQ(kArmCmp, s[0]->arch_opcode());
2764    EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode());
2765    ASSERT_EQ(2U, s[0]->InputCount());
2766    EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
2767    EXPECT_EQ(1U, s[0]->OutputCount());
2768    EXPECT_EQ(kFlags_set, s[0]->flags_mode());
2769    EXPECT_EQ(kEqual, s[0]->flags_condition());
2770  }
2771  TRACED_FOREACH(int32_t, imm, kImmediates) {
2772    if (imm == 0) continue;
2773    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2774    m.Return(m.Word32Equal(m.Int32Constant(imm), m.Parameter(0)));
2775    Stream s = m.Build();
2776    ASSERT_EQ(1U, s.size());
2777    EXPECT_EQ(kArmCmp, s[0]->arch_opcode());
2778    EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode());
2779    ASSERT_EQ(2U, s[0]->InputCount());
2780    EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
2781    EXPECT_EQ(1U, s[0]->OutputCount());
2782    EXPECT_EQ(kFlags_set, s[0]->flags_mode());
2783    EXPECT_EQ(kEqual, s[0]->flags_condition());
2784  }
2785}
2786
2787
2788TEST_F(InstructionSelectorTest, Word32EqualWithZero) {
2789  {
2790    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2791    m.Return(m.Word32Equal(m.Parameter(0), m.Int32Constant(0)));
2792    Stream s = m.Build();
2793    ASSERT_EQ(1U, s.size());
2794    EXPECT_EQ(kArmTst, s[0]->arch_opcode());
2795    EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
2796    ASSERT_EQ(2U, s[0]->InputCount());
2797    EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
2798    EXPECT_EQ(1U, s[0]->OutputCount());
2799    EXPECT_EQ(kFlags_set, s[0]->flags_mode());
2800    EXPECT_EQ(kEqual, s[0]->flags_condition());
2801  }
2802  {
2803    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2804    m.Return(m.Word32Equal(m.Int32Constant(0), m.Parameter(0)));
2805    Stream s = m.Build();
2806    ASSERT_EQ(1U, s.size());
2807    EXPECT_EQ(kArmTst, s[0]->arch_opcode());
2808    EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
2809    ASSERT_EQ(2U, s[0]->InputCount());
2810    EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
2811    EXPECT_EQ(1U, s[0]->OutputCount());
2812    EXPECT_EQ(kFlags_set, s[0]->flags_mode());
2813    EXPECT_EQ(kEqual, s[0]->flags_condition());
2814  }
2815}
2816
2817
2818TEST_F(InstructionSelectorTest, Word32NotWithParameter) {
2819  StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2820  m.Return(m.Word32Not(m.Parameter(0)));
2821  Stream s = m.Build();
2822  ASSERT_EQ(1U, s.size());
2823  EXPECT_EQ(kArmMvn, s[0]->arch_opcode());
2824  EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
2825  EXPECT_EQ(1U, s[0]->InputCount());
2826  EXPECT_EQ(1U, s[0]->OutputCount());
2827}
2828
2829
2830TEST_F(InstructionSelectorTest, Word32AndWithWord32ShrWithImmediateForARMv7) {
2831  TRACED_FORRANGE(int32_t, lsb, 0, 31) {
2832    TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) {
2833      StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2834      m.Return(m.Word32And(m.Word32Shr(m.Parameter(0), m.Int32Constant(lsb)),
2835                           m.Int32Constant(0xffffffffu >> (32 - width))));
2836      Stream s = m.Build(ARMv7);
2837      ASSERT_EQ(1U, s.size());
2838      EXPECT_EQ(kArmUbfx, s[0]->arch_opcode());
2839      ASSERT_EQ(3U, s[0]->InputCount());
2840      EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
2841      EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
2842    }
2843  }
2844  TRACED_FORRANGE(int32_t, lsb, 0, 31) {
2845    TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) {
2846      StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2847      m.Return(m.Word32And(m.Int32Constant(0xffffffffu >> (32 - width)),
2848                           m.Word32Shr(m.Parameter(0), m.Int32Constant(lsb))));
2849      Stream s = m.Build(ARMv7);
2850      ASSERT_EQ(1U, s.size());
2851      EXPECT_EQ(kArmUbfx, s[0]->arch_opcode());
2852      ASSERT_EQ(3U, s[0]->InputCount());
2853      EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
2854      EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
2855    }
2856  }
2857}
2858
2859
2860TEST_F(InstructionSelectorTest, Word32Clz) {
2861  StreamBuilder m(this, MachineType::Uint32(), MachineType::Uint32());
2862  Node* const p0 = m.Parameter(0);
2863  Node* const n = m.Word32Clz(p0);
2864  m.Return(n);
2865  Stream s = m.Build();
2866  ASSERT_EQ(1U, s.size());
2867  EXPECT_EQ(kArmClz, s[0]->arch_opcode());
2868  ASSERT_EQ(1U, s[0]->InputCount());
2869  EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
2870  ASSERT_EQ(1U, s[0]->OutputCount());
2871  EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
2872}
2873
2874}  // namespace compiler
2875}  // namespace internal
2876}  // namespace v8
2877