1// Copyright 2014 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "src/compiler/instruction-selector-unittest.h"
6
7namespace v8 {
8namespace internal {
9namespace compiler {
10
11namespace {
12
13typedef RawMachineAssembler::Label MLabel;
14typedef Node* (RawMachineAssembler::*Constructor)(Node*, Node*);
15
16
17// Data processing instructions.
18struct DPI {
19  Constructor constructor;
20  const char* constructor_name;
21  ArchOpcode arch_opcode;
22  ArchOpcode reverse_arch_opcode;
23  ArchOpcode test_arch_opcode;
24};
25
26
27std::ostream& operator<<(std::ostream& os, const DPI& dpi) {
28  return os << dpi.constructor_name;
29}
30
31
32static const DPI kDPIs[] = {
33    {&RawMachineAssembler::Word32And, "Word32And", kArmAnd, kArmAnd, kArmTst},
34    {&RawMachineAssembler::Word32Or, "Word32Or", kArmOrr, kArmOrr, kArmOrr},
35    {&RawMachineAssembler::Word32Xor, "Word32Xor", kArmEor, kArmEor, kArmTeq},
36    {&RawMachineAssembler::Int32Add, "Int32Add", kArmAdd, kArmAdd, kArmCmn},
37    {&RawMachineAssembler::Int32Sub, "Int32Sub", kArmSub, kArmRsb, kArmCmp}};
38
39
40// Data processing instructions with overflow.
41struct ODPI {
42  Constructor constructor;
43  const char* constructor_name;
44  ArchOpcode arch_opcode;
45  ArchOpcode reverse_arch_opcode;
46};
47
48
49std::ostream& operator<<(std::ostream& os, const ODPI& odpi) {
50  return os << odpi.constructor_name;
51}
52
53
54static const ODPI kODPIs[] = {{&RawMachineAssembler::Int32AddWithOverflow,
55                               "Int32AddWithOverflow", kArmAdd, kArmAdd},
56                              {&RawMachineAssembler::Int32SubWithOverflow,
57                               "Int32SubWithOverflow", kArmSub, kArmRsb}};
58
59
60// Shifts.
61struct Shift {
62  Constructor constructor;
63  const char* constructor_name;
64  int32_t i_low;          // lowest possible immediate
65  int32_t i_high;         // highest possible immediate
66  AddressingMode i_mode;  // Operand2_R_<shift>_I
67  AddressingMode r_mode;  // Operand2_R_<shift>_R
68};
69
70
71std::ostream& operator<<(std::ostream& os, const Shift& shift) {
72  return os << shift.constructor_name;
73}
74
75
76static const Shift kShifts[] = {
77    {&RawMachineAssembler::Word32Sar, "Word32Sar", 1, 32,
78     kMode_Operand2_R_ASR_I, kMode_Operand2_R_ASR_R},
79    {&RawMachineAssembler::Word32Shl, "Word32Shl", 0, 31,
80     kMode_Operand2_R_LSL_I, kMode_Operand2_R_LSL_R},
81    {&RawMachineAssembler::Word32Shr, "Word32Shr", 1, 32,
82     kMode_Operand2_R_LSR_I, kMode_Operand2_R_LSR_R},
83    {&RawMachineAssembler::Word32Ror, "Word32Ror", 1, 31,
84     kMode_Operand2_R_ROR_I, kMode_Operand2_R_ROR_R}};
85
86
87// Immediates (random subset).
88static const int32_t kImmediates[] = {
89    -2147483617, -2147483606, -2113929216, -2080374784, -1996488704,
90    -1879048192, -1459617792, -1358954496, -1342177265, -1275068414,
91    -1073741818, -1073741777, -855638016,  -805306368,  -402653184,
92    -268435444,  -16777216,   0,           35,          61,
93    105,         116,         171,         245,         255,
94    692,         1216,        1248,        1520,        1600,
95    1888,        3744,        4080,        5888,        8384,
96    9344,        9472,        9792,        13312,       15040,
97    15360,       20736,       22272,       23296,       32000,
98    33536,       37120,       45824,       47872,       56320,
99    59392,       65280,       72704,       101376,      147456,
100    161792,      164864,      167936,      173056,      195584,
101    209920,      212992,      356352,      655360,      704512,
102    716800,      851968,      901120,      1044480,     1523712,
103    2572288,     3211264,     3588096,     3833856,     3866624,
104    4325376,     5177344,     6488064,     7012352,     7471104,
105    14090240,    16711680,    19398656,    22282240,    28573696,
106    30408704,    30670848,    43253760,    54525952,    55312384,
107    56623104,    68157440,    115343360,   131072000,   187695104,
108    188743680,   195035136,   197132288,   203423744,   218103808,
109    267386880,   268435470,   285212672,   402653185,   415236096,
110    595591168,   603979776,   603979778,   629145600,   1073741835,
111    1073741855,  1073741861,  1073741884,  1157627904,  1476395008,
112    1476395010,  1610612741,  2030043136,  2080374785,  2097152000};
113
114}  // namespace
115
116
117// -----------------------------------------------------------------------------
118// Data processing instructions.
119
120
121typedef InstructionSelectorTestWithParam<DPI> InstructionSelectorDPITest;
122
123
124TEST_P(InstructionSelectorDPITest, Parameters) {
125  const DPI dpi = GetParam();
126  StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
127  m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)));
128  Stream s = m.Build();
129  ASSERT_EQ(1U, s.size());
130  EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
131  EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
132  EXPECT_EQ(2U, s[0]->InputCount());
133  EXPECT_EQ(1U, s[0]->OutputCount());
134}
135
136
137TEST_P(InstructionSelectorDPITest, Immediate) {
138  const DPI dpi = GetParam();
139  TRACED_FOREACH(int32_t, imm, kImmediates) {
140    StreamBuilder m(this, kMachInt32, kMachInt32);
141    m.Return((m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm)));
142    Stream s = m.Build();
143    ASSERT_EQ(1U, s.size());
144    EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
145    EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode());
146    ASSERT_EQ(2U, s[0]->InputCount());
147    EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
148    EXPECT_EQ(1U, s[0]->OutputCount());
149  }
150  TRACED_FOREACH(int32_t, imm, kImmediates) {
151    StreamBuilder m(this, kMachInt32, kMachInt32);
152    m.Return((m.*dpi.constructor)(m.Int32Constant(imm), m.Parameter(0)));
153    Stream s = m.Build();
154    ASSERT_EQ(1U, s.size());
155    EXPECT_EQ(dpi.reverse_arch_opcode, s[0]->arch_opcode());
156    EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode());
157    ASSERT_EQ(2U, s[0]->InputCount());
158    EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
159    EXPECT_EQ(1U, s[0]->OutputCount());
160  }
161}
162
163
164TEST_P(InstructionSelectorDPITest, ShiftByParameter) {
165  const DPI dpi = GetParam();
166  TRACED_FOREACH(Shift, shift, kShifts) {
167    StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32, kMachInt32);
168    m.Return((m.*dpi.constructor)(
169        m.Parameter(0),
170        (m.*shift.constructor)(m.Parameter(1), m.Parameter(2))));
171    Stream s = m.Build();
172    ASSERT_EQ(1U, s.size());
173    EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
174    EXPECT_EQ(shift.r_mode, s[0]->addressing_mode());
175    EXPECT_EQ(3U, s[0]->InputCount());
176    EXPECT_EQ(1U, s[0]->OutputCount());
177  }
178  TRACED_FOREACH(Shift, shift, kShifts) {
179    StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32, kMachInt32);
180    m.Return((m.*dpi.constructor)(
181        (m.*shift.constructor)(m.Parameter(0), m.Parameter(1)),
182        m.Parameter(2)));
183    Stream s = m.Build();
184    ASSERT_EQ(1U, s.size());
185    EXPECT_EQ(dpi.reverse_arch_opcode, s[0]->arch_opcode());
186    EXPECT_EQ(shift.r_mode, s[0]->addressing_mode());
187    EXPECT_EQ(3U, s[0]->InputCount());
188    EXPECT_EQ(1U, s[0]->OutputCount());
189  }
190}
191
192
193TEST_P(InstructionSelectorDPITest, ShiftByImmediate) {
194  const DPI dpi = GetParam();
195  TRACED_FOREACH(Shift, shift, kShifts) {
196    TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) {
197      StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
198      m.Return((m.*dpi.constructor)(
199          m.Parameter(0),
200          (m.*shift.constructor)(m.Parameter(1), m.Int32Constant(imm))));
201      Stream s = m.Build();
202      ASSERT_EQ(1U, s.size());
203      EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
204      EXPECT_EQ(shift.i_mode, s[0]->addressing_mode());
205      ASSERT_EQ(3U, s[0]->InputCount());
206      EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2)));
207      EXPECT_EQ(1U, s[0]->OutputCount());
208    }
209  }
210  TRACED_FOREACH(Shift, shift, kShifts) {
211    TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) {
212      StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
213      m.Return((m.*dpi.constructor)(
214          (m.*shift.constructor)(m.Parameter(0), m.Int32Constant(imm)),
215          m.Parameter(1)));
216      Stream s = m.Build();
217      ASSERT_EQ(1U, s.size());
218      EXPECT_EQ(dpi.reverse_arch_opcode, s[0]->arch_opcode());
219      EXPECT_EQ(shift.i_mode, s[0]->addressing_mode());
220      ASSERT_EQ(3U, s[0]->InputCount());
221      EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2)));
222      EXPECT_EQ(1U, s[0]->OutputCount());
223    }
224  }
225}
226
227
228TEST_P(InstructionSelectorDPITest, BranchWithParameters) {
229  const DPI dpi = GetParam();
230  StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
231  MLabel a, b;
232  m.Branch((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)), &a, &b);
233  m.Bind(&a);
234  m.Return(m.Int32Constant(1));
235  m.Bind(&b);
236  m.Return(m.Int32Constant(0));
237  Stream s = m.Build();
238  ASSERT_EQ(1U, s.size());
239  EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode());
240  EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
241  EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
242  EXPECT_EQ(kNotEqual, s[0]->flags_condition());
243}
244
245
246TEST_P(InstructionSelectorDPITest, BranchWithImmediate) {
247  const DPI dpi = GetParam();
248  TRACED_FOREACH(int32_t, imm, kImmediates) {
249    StreamBuilder m(this, kMachInt32, kMachInt32);
250    MLabel a, b;
251    m.Branch((m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm)), &a,
252             &b);
253    m.Bind(&a);
254    m.Return(m.Int32Constant(1));
255    m.Bind(&b);
256    m.Return(m.Int32Constant(0));
257    Stream s = m.Build();
258    ASSERT_EQ(1U, s.size());
259    EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode());
260    EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode());
261    EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
262    EXPECT_EQ(kNotEqual, s[0]->flags_condition());
263  }
264  TRACED_FOREACH(int32_t, imm, kImmediates) {
265    StreamBuilder m(this, kMachInt32, kMachInt32);
266    MLabel a, b;
267    m.Branch((m.*dpi.constructor)(m.Int32Constant(imm), m.Parameter(0)), &a,
268             &b);
269    m.Bind(&a);
270    m.Return(m.Int32Constant(1));
271    m.Bind(&b);
272    m.Return(m.Int32Constant(0));
273    Stream s = m.Build();
274    ASSERT_EQ(1U, s.size());
275    EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode());
276    EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode());
277    EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
278    EXPECT_EQ(kNotEqual, s[0]->flags_condition());
279  }
280}
281
282
283TEST_P(InstructionSelectorDPITest, BranchWithShiftByParameter) {
284  const DPI dpi = GetParam();
285  TRACED_FOREACH(Shift, shift, kShifts) {
286    StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32, kMachInt32);
287    MLabel a, b;
288    m.Branch((m.*dpi.constructor)(
289                 m.Parameter(0),
290                 (m.*shift.constructor)(m.Parameter(1), m.Parameter(2))),
291             &a, &b);
292    m.Bind(&a);
293    m.Return(m.Int32Constant(1));
294    m.Bind(&b);
295    m.Return(m.Int32Constant(0));
296    Stream s = m.Build();
297    ASSERT_EQ(1U, s.size());
298    EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode());
299    EXPECT_EQ(shift.r_mode, s[0]->addressing_mode());
300    EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
301    EXPECT_EQ(kNotEqual, s[0]->flags_condition());
302  }
303  TRACED_FOREACH(Shift, shift, kShifts) {
304    StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32, kMachInt32);
305    MLabel a, b;
306    m.Branch((m.*dpi.constructor)(
307                 (m.*shift.constructor)(m.Parameter(0), m.Parameter(1)),
308                 m.Parameter(2)),
309             &a, &b);
310    m.Bind(&a);
311    m.Return(m.Int32Constant(1));
312    m.Bind(&b);
313    m.Return(m.Int32Constant(0));
314    Stream s = m.Build();
315    ASSERT_EQ(1U, s.size());
316    EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode());
317    EXPECT_EQ(shift.r_mode, s[0]->addressing_mode());
318    EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
319    EXPECT_EQ(kNotEqual, s[0]->flags_condition());
320  }
321}
322
323
324TEST_P(InstructionSelectorDPITest, BranchWithShiftByImmediate) {
325  const DPI dpi = GetParam();
326  TRACED_FOREACH(Shift, shift, kShifts) {
327    TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) {
328      StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
329      MLabel a, b;
330      m.Branch((m.*dpi.constructor)(m.Parameter(0),
331                                    (m.*shift.constructor)(
332                                        m.Parameter(1), m.Int32Constant(imm))),
333               &a, &b);
334      m.Bind(&a);
335      m.Return(m.Int32Constant(1));
336      m.Bind(&b);
337      m.Return(m.Int32Constant(0));
338      Stream s = m.Build();
339      ASSERT_EQ(1U, s.size());
340      EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode());
341      EXPECT_EQ(shift.i_mode, s[0]->addressing_mode());
342      ASSERT_EQ(5U, s[0]->InputCount());
343      EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2)));
344      EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
345      EXPECT_EQ(kNotEqual, s[0]->flags_condition());
346    }
347  }
348  TRACED_FOREACH(Shift, shift, kShifts) {
349    TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) {
350      StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
351      MLabel a, b;
352      m.Branch((m.*dpi.constructor)(
353                   (m.*shift.constructor)(m.Parameter(0), m.Int32Constant(imm)),
354                   m.Parameter(1)),
355               &a, &b);
356      m.Bind(&a);
357      m.Return(m.Int32Constant(1));
358      m.Bind(&b);
359      m.Return(m.Int32Constant(0));
360      Stream s = m.Build();
361      ASSERT_EQ(1U, s.size());
362      EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode());
363      EXPECT_EQ(shift.i_mode, s[0]->addressing_mode());
364      ASSERT_EQ(5U, s[0]->InputCount());
365      EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2)));
366      EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
367      EXPECT_EQ(kNotEqual, s[0]->flags_condition());
368    }
369  }
370}
371
372
373TEST_P(InstructionSelectorDPITest, BranchIfZeroWithParameters) {
374  const DPI dpi = GetParam();
375  StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
376  MLabel a, b;
377  m.Branch(m.Word32Equal((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)),
378                         m.Int32Constant(0)),
379           &a, &b);
380  m.Bind(&a);
381  m.Return(m.Int32Constant(1));
382  m.Bind(&b);
383  m.Return(m.Int32Constant(0));
384  Stream s = m.Build();
385  ASSERT_EQ(1U, s.size());
386  EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode());
387  EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
388  EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
389  EXPECT_EQ(kEqual, s[0]->flags_condition());
390}
391
392
393TEST_P(InstructionSelectorDPITest, BranchIfNotZeroWithParameters) {
394  const DPI dpi = GetParam();
395  StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
396  MLabel a, b;
397  m.Branch(
398      m.Word32NotEqual((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)),
399                       m.Int32Constant(0)),
400      &a, &b);
401  m.Bind(&a);
402  m.Return(m.Int32Constant(1));
403  m.Bind(&b);
404  m.Return(m.Int32Constant(0));
405  Stream s = m.Build();
406  ASSERT_EQ(1U, s.size());
407  EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode());
408  EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
409  EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
410  EXPECT_EQ(kNotEqual, s[0]->flags_condition());
411}
412
413
414TEST_P(InstructionSelectorDPITest, BranchIfZeroWithImmediate) {
415  const DPI dpi = GetParam();
416  TRACED_FOREACH(int32_t, imm, kImmediates) {
417    StreamBuilder m(this, kMachInt32, kMachInt32);
418    MLabel a, b;
419    m.Branch(m.Word32Equal(
420                 (m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm)),
421                 m.Int32Constant(0)),
422             &a, &b);
423    m.Bind(&a);
424    m.Return(m.Int32Constant(1));
425    m.Bind(&b);
426    m.Return(m.Int32Constant(0));
427    Stream s = m.Build();
428    ASSERT_EQ(1U, s.size());
429    EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode());
430    EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode());
431    EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
432    EXPECT_EQ(kEqual, s[0]->flags_condition());
433  }
434  TRACED_FOREACH(int32_t, imm, kImmediates) {
435    StreamBuilder m(this, kMachInt32, kMachInt32);
436    MLabel a, b;
437    m.Branch(m.Word32Equal(
438                 (m.*dpi.constructor)(m.Int32Constant(imm), m.Parameter(0)),
439                 m.Int32Constant(0)),
440             &a, &b);
441    m.Bind(&a);
442    m.Return(m.Int32Constant(1));
443    m.Bind(&b);
444    m.Return(m.Int32Constant(0));
445    Stream s = m.Build();
446    ASSERT_EQ(1U, s.size());
447    EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode());
448    EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode());
449    EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
450    EXPECT_EQ(kEqual, s[0]->flags_condition());
451  }
452}
453
454
455TEST_P(InstructionSelectorDPITest, BranchIfNotZeroWithImmediate) {
456  const DPI dpi = GetParam();
457  TRACED_FOREACH(int32_t, imm, kImmediates) {
458    StreamBuilder m(this, kMachInt32, kMachInt32);
459    MLabel a, b;
460    m.Branch(m.Word32NotEqual(
461                 (m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm)),
462                 m.Int32Constant(0)),
463             &a, &b);
464    m.Bind(&a);
465    m.Return(m.Int32Constant(1));
466    m.Bind(&b);
467    m.Return(m.Int32Constant(0));
468    Stream s = m.Build();
469    ASSERT_EQ(1U, s.size());
470    EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode());
471    EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode());
472    EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
473    EXPECT_EQ(kNotEqual, s[0]->flags_condition());
474  }
475  TRACED_FOREACH(int32_t, imm, kImmediates) {
476    StreamBuilder m(this, kMachInt32, kMachInt32);
477    MLabel a, b;
478    m.Branch(m.Word32NotEqual(
479                 (m.*dpi.constructor)(m.Int32Constant(imm), m.Parameter(0)),
480                 m.Int32Constant(0)),
481             &a, &b);
482    m.Bind(&a);
483    m.Return(m.Int32Constant(1));
484    m.Bind(&b);
485    m.Return(m.Int32Constant(0));
486    Stream s = m.Build();
487    ASSERT_EQ(1U, s.size());
488    EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode());
489    EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode());
490    EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
491    EXPECT_EQ(kNotEqual, s[0]->flags_condition());
492  }
493}
494
495
496INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorDPITest,
497                        ::testing::ValuesIn(kDPIs));
498
499
500// -----------------------------------------------------------------------------
501// Data processing instructions with overflow.
502
503
504typedef InstructionSelectorTestWithParam<ODPI> InstructionSelectorODPITest;
505
506
507TEST_P(InstructionSelectorODPITest, OvfWithParameters) {
508  const ODPI odpi = GetParam();
509  StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
510  m.Return(
511      m.Projection(1, (m.*odpi.constructor)(m.Parameter(0), m.Parameter(1))));
512  Stream s = m.Build();
513  ASSERT_EQ(1U, s.size());
514  EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode());
515  EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
516  EXPECT_EQ(2U, s[0]->InputCount());
517  EXPECT_LE(1U, s[0]->OutputCount());
518  EXPECT_EQ(kFlags_set, s[0]->flags_mode());
519  EXPECT_EQ(kOverflow, s[0]->flags_condition());
520}
521
522
523TEST_P(InstructionSelectorODPITest, OvfWithImmediate) {
524  const ODPI odpi = GetParam();
525  TRACED_FOREACH(int32_t, imm, kImmediates) {
526    StreamBuilder m(this, kMachInt32, kMachInt32);
527    m.Return(m.Projection(
528        1, (m.*odpi.constructor)(m.Parameter(0), m.Int32Constant(imm))));
529    Stream s = m.Build();
530    ASSERT_EQ(1U, s.size());
531    EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode());
532    EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode());
533    ASSERT_EQ(2U, s[0]->InputCount());
534    EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
535    EXPECT_LE(1U, s[0]->OutputCount());
536    EXPECT_EQ(kFlags_set, s[0]->flags_mode());
537    EXPECT_EQ(kOverflow, s[0]->flags_condition());
538  }
539  TRACED_FOREACH(int32_t, imm, kImmediates) {
540    StreamBuilder m(this, kMachInt32, kMachInt32);
541    m.Return(m.Projection(
542        1, (m.*odpi.constructor)(m.Int32Constant(imm), m.Parameter(0))));
543    Stream s = m.Build();
544    ASSERT_EQ(1U, s.size());
545    EXPECT_EQ(odpi.reverse_arch_opcode, s[0]->arch_opcode());
546    EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode());
547    ASSERT_EQ(2U, s[0]->InputCount());
548    EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
549    EXPECT_LE(1U, s[0]->OutputCount());
550    EXPECT_EQ(kFlags_set, s[0]->flags_mode());
551    EXPECT_EQ(kOverflow, s[0]->flags_condition());
552  }
553}
554
555
556TEST_P(InstructionSelectorODPITest, OvfWithShiftByParameter) {
557  const ODPI odpi = GetParam();
558  TRACED_FOREACH(Shift, shift, kShifts) {
559    StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32, kMachInt32);
560    m.Return(m.Projection(
561        1, (m.*odpi.constructor)(
562               m.Parameter(0),
563               (m.*shift.constructor)(m.Parameter(1), m.Parameter(2)))));
564    Stream s = m.Build();
565    ASSERT_EQ(1U, s.size());
566    EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode());
567    EXPECT_EQ(shift.r_mode, s[0]->addressing_mode());
568    EXPECT_EQ(3U, s[0]->InputCount());
569    EXPECT_LE(1U, s[0]->OutputCount());
570    EXPECT_EQ(kFlags_set, s[0]->flags_mode());
571    EXPECT_EQ(kOverflow, s[0]->flags_condition());
572  }
573  TRACED_FOREACH(Shift, shift, kShifts) {
574    StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32, kMachInt32);
575    m.Return(m.Projection(
576        1, (m.*odpi.constructor)(
577               (m.*shift.constructor)(m.Parameter(0), m.Parameter(1)),
578               m.Parameter(0))));
579    Stream s = m.Build();
580    ASSERT_EQ(1U, s.size());
581    EXPECT_EQ(odpi.reverse_arch_opcode, s[0]->arch_opcode());
582    EXPECT_EQ(shift.r_mode, s[0]->addressing_mode());
583    EXPECT_EQ(3U, s[0]->InputCount());
584    EXPECT_LE(1U, s[0]->OutputCount());
585    EXPECT_EQ(kFlags_set, s[0]->flags_mode());
586    EXPECT_EQ(kOverflow, s[0]->flags_condition());
587  }
588}
589
590
591TEST_P(InstructionSelectorODPITest, OvfWithShiftByImmediate) {
592  const ODPI odpi = GetParam();
593  TRACED_FOREACH(Shift, shift, kShifts) {
594    TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) {
595      StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
596      m.Return(m.Projection(
597          1, (m.*odpi.constructor)(m.Parameter(0),
598                                   (m.*shift.constructor)(
599                                       m.Parameter(1), m.Int32Constant(imm)))));
600      Stream s = m.Build();
601      ASSERT_EQ(1U, s.size());
602      EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode());
603      EXPECT_EQ(shift.i_mode, s[0]->addressing_mode());
604      ASSERT_EQ(3U, s[0]->InputCount());
605      EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2)));
606      EXPECT_LE(1U, s[0]->OutputCount());
607      EXPECT_EQ(kFlags_set, s[0]->flags_mode());
608      EXPECT_EQ(kOverflow, s[0]->flags_condition());
609    }
610  }
611  TRACED_FOREACH(Shift, shift, kShifts) {
612    TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) {
613      StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
614      m.Return(m.Projection(
615          1, (m.*odpi.constructor)(
616                 (m.*shift.constructor)(m.Parameter(1), m.Int32Constant(imm)),
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.i_mode, s[0]->addressing_mode());
622      ASSERT_EQ(3U, s[0]->InputCount());
623      EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2)));
624      EXPECT_LE(1U, s[0]->OutputCount());
625      EXPECT_EQ(kFlags_set, s[0]->flags_mode());
626      EXPECT_EQ(kOverflow, s[0]->flags_condition());
627    }
628  }
629}
630
631
632TEST_P(InstructionSelectorODPITest, ValWithParameters) {
633  const ODPI odpi = GetParam();
634  StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
635  m.Return(
636      m.Projection(0, (m.*odpi.constructor)(m.Parameter(0), m.Parameter(1))));
637  Stream s = m.Build();
638  ASSERT_EQ(1U, s.size());
639  EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode());
640  EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
641  EXPECT_EQ(2U, s[0]->InputCount());
642  EXPECT_LE(1U, s[0]->OutputCount());
643  EXPECT_EQ(kFlags_none, s[0]->flags_mode());
644}
645
646
647TEST_P(InstructionSelectorODPITest, ValWithImmediate) {
648  const ODPI odpi = GetParam();
649  TRACED_FOREACH(int32_t, imm, kImmediates) {
650    StreamBuilder m(this, kMachInt32, kMachInt32);
651    m.Return(m.Projection(
652        0, (m.*odpi.constructor)(m.Parameter(0), m.Int32Constant(imm))));
653    Stream s = m.Build();
654    ASSERT_EQ(1U, s.size());
655    EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode());
656    EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode());
657    ASSERT_EQ(2U, s[0]->InputCount());
658    EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
659    EXPECT_LE(1U, s[0]->OutputCount());
660    EXPECT_EQ(kFlags_none, s[0]->flags_mode());
661  }
662  TRACED_FOREACH(int32_t, imm, kImmediates) {
663    StreamBuilder m(this, kMachInt32, kMachInt32);
664    m.Return(m.Projection(
665        0, (m.*odpi.constructor)(m.Int32Constant(imm), m.Parameter(0))));
666    Stream s = m.Build();
667    ASSERT_EQ(1U, s.size());
668    EXPECT_EQ(odpi.reverse_arch_opcode, s[0]->arch_opcode());
669    EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode());
670    ASSERT_EQ(2U, s[0]->InputCount());
671    EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
672    EXPECT_LE(1U, s[0]->OutputCount());
673    EXPECT_EQ(kFlags_none, s[0]->flags_mode());
674  }
675}
676
677
678TEST_P(InstructionSelectorODPITest, ValWithShiftByParameter) {
679  const ODPI odpi = GetParam();
680  TRACED_FOREACH(Shift, shift, kShifts) {
681    StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32, kMachInt32);
682    m.Return(m.Projection(
683        0, (m.*odpi.constructor)(
684               m.Parameter(0),
685               (m.*shift.constructor)(m.Parameter(1), m.Parameter(2)))));
686    Stream s = m.Build();
687    ASSERT_EQ(1U, s.size());
688    EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode());
689    EXPECT_EQ(shift.r_mode, s[0]->addressing_mode());
690    EXPECT_EQ(3U, s[0]->InputCount());
691    EXPECT_LE(1U, s[0]->OutputCount());
692    EXPECT_EQ(kFlags_none, s[0]->flags_mode());
693  }
694  TRACED_FOREACH(Shift, shift, kShifts) {
695    StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32, kMachInt32);
696    m.Return(m.Projection(
697        0, (m.*odpi.constructor)(
698               (m.*shift.constructor)(m.Parameter(0), m.Parameter(1)),
699               m.Parameter(0))));
700    Stream s = m.Build();
701    ASSERT_EQ(1U, s.size());
702    EXPECT_EQ(odpi.reverse_arch_opcode, s[0]->arch_opcode());
703    EXPECT_EQ(shift.r_mode, s[0]->addressing_mode());
704    EXPECT_EQ(3U, s[0]->InputCount());
705    EXPECT_LE(1U, s[0]->OutputCount());
706    EXPECT_EQ(kFlags_none, s[0]->flags_mode());
707  }
708}
709
710
711TEST_P(InstructionSelectorODPITest, ValWithShiftByImmediate) {
712  const ODPI odpi = GetParam();
713  TRACED_FOREACH(Shift, shift, kShifts) {
714    TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) {
715      StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
716      m.Return(m.Projection(
717          0, (m.*odpi.constructor)(m.Parameter(0),
718                                   (m.*shift.constructor)(
719                                       m.Parameter(1), m.Int32Constant(imm)))));
720      Stream s = m.Build();
721      ASSERT_EQ(1U, s.size());
722      EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode());
723      EXPECT_EQ(shift.i_mode, s[0]->addressing_mode());
724      ASSERT_EQ(3U, s[0]->InputCount());
725      EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2)));
726      EXPECT_LE(1U, s[0]->OutputCount());
727      EXPECT_EQ(kFlags_none, s[0]->flags_mode());
728    }
729  }
730  TRACED_FOREACH(Shift, shift, kShifts) {
731    TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) {
732      StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
733      m.Return(m.Projection(
734          0, (m.*odpi.constructor)(
735                 (m.*shift.constructor)(m.Parameter(1), m.Int32Constant(imm)),
736                 m.Parameter(0))));
737      Stream s = m.Build();
738      ASSERT_EQ(1U, s.size());
739      EXPECT_EQ(odpi.reverse_arch_opcode, s[0]->arch_opcode());
740      EXPECT_EQ(shift.i_mode, s[0]->addressing_mode());
741      ASSERT_EQ(3U, s[0]->InputCount());
742      EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2)));
743      EXPECT_LE(1U, s[0]->OutputCount());
744      EXPECT_EQ(kFlags_none, s[0]->flags_mode());
745    }
746  }
747}
748
749
750TEST_P(InstructionSelectorODPITest, BothWithParameters) {
751  const ODPI odpi = GetParam();
752  StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
753  Node* n = (m.*odpi.constructor)(m.Parameter(0), m.Parameter(1));
754  m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n)));
755  Stream s = m.Build();
756  ASSERT_LE(1U, s.size());
757  EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode());
758  EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
759  EXPECT_EQ(2U, s[0]->InputCount());
760  EXPECT_EQ(2U, s[0]->OutputCount());
761  EXPECT_EQ(kFlags_set, s[0]->flags_mode());
762  EXPECT_EQ(kOverflow, s[0]->flags_condition());
763}
764
765
766TEST_P(InstructionSelectorODPITest, BothWithImmediate) {
767  const ODPI odpi = GetParam();
768  TRACED_FOREACH(int32_t, imm, kImmediates) {
769    StreamBuilder m(this, kMachInt32, kMachInt32);
770    Node* n = (m.*odpi.constructor)(m.Parameter(0), m.Int32Constant(imm));
771    m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n)));
772    Stream s = m.Build();
773    ASSERT_LE(1U, s.size());
774    EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode());
775    EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode());
776    ASSERT_EQ(2U, s[0]->InputCount());
777    EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
778    EXPECT_EQ(2U, s[0]->OutputCount());
779    EXPECT_EQ(kFlags_set, s[0]->flags_mode());
780    EXPECT_EQ(kOverflow, s[0]->flags_condition());
781  }
782  TRACED_FOREACH(int32_t, imm, kImmediates) {
783    StreamBuilder m(this, kMachInt32, kMachInt32);
784    Node* n = (m.*odpi.constructor)(m.Int32Constant(imm), m.Parameter(0));
785    m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n)));
786    Stream s = m.Build();
787    ASSERT_LE(1U, s.size());
788    EXPECT_EQ(odpi.reverse_arch_opcode, s[0]->arch_opcode());
789    EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode());
790    ASSERT_EQ(2U, s[0]->InputCount());
791    EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
792    EXPECT_EQ(2U, s[0]->OutputCount());
793    EXPECT_EQ(kFlags_set, s[0]->flags_mode());
794    EXPECT_EQ(kOverflow, s[0]->flags_condition());
795  }
796}
797
798
799TEST_P(InstructionSelectorODPITest, BothWithShiftByParameter) {
800  const ODPI odpi = GetParam();
801  TRACED_FOREACH(Shift, shift, kShifts) {
802    StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32, kMachInt32);
803    Node* n = (m.*odpi.constructor)(
804        m.Parameter(0), (m.*shift.constructor)(m.Parameter(1), m.Parameter(2)));
805    m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n)));
806    Stream s = m.Build();
807    ASSERT_LE(1U, s.size());
808    EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode());
809    EXPECT_EQ(shift.r_mode, s[0]->addressing_mode());
810    EXPECT_EQ(3U, s[0]->InputCount());
811    EXPECT_EQ(2U, s[0]->OutputCount());
812    EXPECT_EQ(kFlags_set, s[0]->flags_mode());
813    EXPECT_EQ(kOverflow, s[0]->flags_condition());
814  }
815  TRACED_FOREACH(Shift, shift, kShifts) {
816    StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32, kMachInt32);
817    Node* n = (m.*odpi.constructor)(
818        (m.*shift.constructor)(m.Parameter(0), m.Parameter(1)), m.Parameter(2));
819    m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n)));
820    Stream s = m.Build();
821    ASSERT_LE(1U, s.size());
822    EXPECT_EQ(odpi.reverse_arch_opcode, s[0]->arch_opcode());
823    EXPECT_EQ(shift.r_mode, s[0]->addressing_mode());
824    EXPECT_EQ(3U, s[0]->InputCount());
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}
830
831
832TEST_P(InstructionSelectorODPITest, BothWithShiftByImmediate) {
833  const ODPI odpi = GetParam();
834  TRACED_FOREACH(Shift, shift, kShifts) {
835    TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) {
836      StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
837      Node* n = (m.*odpi.constructor)(
838          m.Parameter(0),
839          (m.*shift.constructor)(m.Parameter(1), m.Int32Constant(imm)));
840      m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n)));
841      Stream s = m.Build();
842      ASSERT_LE(1U, s.size());
843      EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode());
844      EXPECT_EQ(shift.i_mode, s[0]->addressing_mode());
845      ASSERT_EQ(3U, s[0]->InputCount());
846      EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2)));
847      EXPECT_EQ(2U, s[0]->OutputCount());
848      EXPECT_EQ(kFlags_set, s[0]->flags_mode());
849      EXPECT_EQ(kOverflow, s[0]->flags_condition());
850    }
851  }
852  TRACED_FOREACH(Shift, shift, kShifts) {
853    TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) {
854      StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
855      Node* n = (m.*odpi.constructor)(
856          (m.*shift.constructor)(m.Parameter(0), m.Int32Constant(imm)),
857          m.Parameter(1));
858      m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n)));
859      Stream s = m.Build();
860      ASSERT_LE(1U, s.size());
861      EXPECT_EQ(odpi.reverse_arch_opcode, s[0]->arch_opcode());
862      EXPECT_EQ(shift.i_mode, s[0]->addressing_mode());
863      ASSERT_EQ(3U, s[0]->InputCount());
864      EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2)));
865      EXPECT_EQ(2U, s[0]->OutputCount());
866      EXPECT_EQ(kFlags_set, s[0]->flags_mode());
867      EXPECT_EQ(kOverflow, s[0]->flags_condition());
868    }
869  }
870}
871
872
873TEST_P(InstructionSelectorODPITest, BranchWithParameters) {
874  const ODPI odpi = GetParam();
875  StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
876  MLabel a, b;
877  Node* n = (m.*odpi.constructor)(m.Parameter(0), m.Parameter(1));
878  m.Branch(m.Projection(1, n), &a, &b);
879  m.Bind(&a);
880  m.Return(m.Int32Constant(0));
881  m.Bind(&b);
882  m.Return(m.Projection(0, n));
883  Stream s = m.Build();
884  ASSERT_EQ(1U, s.size());
885  EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode());
886  EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
887  EXPECT_EQ(4U, s[0]->InputCount());
888  EXPECT_EQ(1U, s[0]->OutputCount());
889  EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
890  EXPECT_EQ(kOverflow, s[0]->flags_condition());
891}
892
893
894TEST_P(InstructionSelectorODPITest, BranchWithImmediate) {
895  const ODPI odpi = GetParam();
896  TRACED_FOREACH(int32_t, imm, kImmediates) {
897    StreamBuilder m(this, kMachInt32, kMachInt32);
898    MLabel a, b;
899    Node* n = (m.*odpi.constructor)(m.Parameter(0), m.Int32Constant(imm));
900    m.Branch(m.Projection(1, n), &a, &b);
901    m.Bind(&a);
902    m.Return(m.Int32Constant(0));
903    m.Bind(&b);
904    m.Return(m.Projection(0, n));
905    Stream s = m.Build();
906    ASSERT_EQ(1U, s.size());
907    EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode());
908    EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode());
909    ASSERT_EQ(4U, s[0]->InputCount());
910    EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
911    EXPECT_EQ(1U, s[0]->OutputCount());
912    EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
913    EXPECT_EQ(kOverflow, s[0]->flags_condition());
914  }
915  TRACED_FOREACH(int32_t, imm, kImmediates) {
916    StreamBuilder m(this, kMachInt32, kMachInt32);
917    MLabel a, b;
918    Node* n = (m.*odpi.constructor)(m.Int32Constant(imm), m.Parameter(0));
919    m.Branch(m.Projection(1, n), &a, &b);
920    m.Bind(&a);
921    m.Return(m.Int32Constant(0));
922    m.Bind(&b);
923    m.Return(m.Projection(0, n));
924    Stream s = m.Build();
925    ASSERT_EQ(1U, s.size());
926    EXPECT_EQ(odpi.reverse_arch_opcode, s[0]->arch_opcode());
927    EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode());
928    ASSERT_EQ(4U, s[0]->InputCount());
929    EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
930    EXPECT_EQ(1U, s[0]->OutputCount());
931    EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
932    EXPECT_EQ(kOverflow, s[0]->flags_condition());
933  }
934}
935
936
937TEST_P(InstructionSelectorODPITest, BranchIfZeroWithParameters) {
938  const ODPI odpi = GetParam();
939  StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
940  MLabel a, b;
941  Node* n = (m.*odpi.constructor)(m.Parameter(0), m.Parameter(1));
942  m.Branch(m.Word32Equal(m.Projection(1, n), m.Int32Constant(0)), &a, &b);
943  m.Bind(&a);
944  m.Return(m.Projection(0, n));
945  m.Bind(&b);
946  m.Return(m.Int32Constant(0));
947  Stream s = m.Build();
948  ASSERT_EQ(1U, s.size());
949  EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode());
950  EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
951  EXPECT_EQ(4U, s[0]->InputCount());
952  EXPECT_EQ(1U, s[0]->OutputCount());
953  EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
954  EXPECT_EQ(kNotOverflow, s[0]->flags_condition());
955}
956
957
958TEST_P(InstructionSelectorODPITest, BranchIfNotZeroWithParameters) {
959  const ODPI odpi = GetParam();
960  StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
961  MLabel a, b;
962  Node* n = (m.*odpi.constructor)(m.Parameter(0), m.Parameter(1));
963  m.Branch(m.Word32NotEqual(m.Projection(1, n), m.Int32Constant(0)), &a, &b);
964  m.Bind(&a);
965  m.Return(m.Projection(0, n));
966  m.Bind(&b);
967  m.Return(m.Int32Constant(0));
968  Stream s = m.Build();
969  ASSERT_EQ(1U, s.size());
970  EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode());
971  EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
972  EXPECT_EQ(4U, s[0]->InputCount());
973  EXPECT_EQ(1U, s[0]->OutputCount());
974  EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
975  EXPECT_EQ(kOverflow, s[0]->flags_condition());
976}
977
978
979INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorODPITest,
980                        ::testing::ValuesIn(kODPIs));
981
982
983// -----------------------------------------------------------------------------
984// Shifts.
985
986
987typedef InstructionSelectorTestWithParam<Shift> InstructionSelectorShiftTest;
988
989
990TEST_P(InstructionSelectorShiftTest, Parameters) {
991  const Shift shift = GetParam();
992  StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
993  m.Return((m.*shift.constructor)(m.Parameter(0), m.Parameter(1)));
994  Stream s = m.Build();
995  ASSERT_EQ(1U, s.size());
996  EXPECT_EQ(kArmMov, s[0]->arch_opcode());
997  EXPECT_EQ(shift.r_mode, s[0]->addressing_mode());
998  EXPECT_EQ(2U, s[0]->InputCount());
999  EXPECT_EQ(1U, s[0]->OutputCount());
1000}
1001
1002
1003TEST_P(InstructionSelectorShiftTest, Immediate) {
1004  const Shift shift = GetParam();
1005  TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) {
1006    StreamBuilder m(this, kMachInt32, kMachInt32);
1007    m.Return((m.*shift.constructor)(m.Parameter(0), m.Int32Constant(imm)));
1008    Stream s = m.Build();
1009    ASSERT_EQ(1U, s.size());
1010    EXPECT_EQ(kArmMov, s[0]->arch_opcode());
1011    EXPECT_EQ(shift.i_mode, s[0]->addressing_mode());
1012    ASSERT_EQ(2U, s[0]->InputCount());
1013    EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
1014    EXPECT_EQ(1U, s[0]->OutputCount());
1015  }
1016}
1017
1018
1019TEST_P(InstructionSelectorShiftTest, Word32EqualWithParameter) {
1020  const Shift shift = GetParam();
1021  {
1022    StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32, kMachInt32);
1023    m.Return(
1024        m.Word32Equal(m.Parameter(0),
1025                      (m.*shift.constructor)(m.Parameter(1), m.Parameter(2))));
1026    Stream s = m.Build();
1027    ASSERT_EQ(1U, s.size());
1028    EXPECT_EQ(kArmCmp, s[0]->arch_opcode());
1029    EXPECT_EQ(shift.r_mode, s[0]->addressing_mode());
1030    EXPECT_EQ(3U, s[0]->InputCount());
1031    EXPECT_EQ(1U, s[0]->OutputCount());
1032    EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1033    EXPECT_EQ(kEqual, s[0]->flags_condition());
1034  }
1035  {
1036    StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32, kMachInt32);
1037    m.Return(
1038        m.Word32Equal((m.*shift.constructor)(m.Parameter(1), m.Parameter(2)),
1039                      m.Parameter(0)));
1040    Stream s = m.Build();
1041    ASSERT_EQ(1U, s.size());
1042    EXPECT_EQ(kArmCmp, s[0]->arch_opcode());
1043    EXPECT_EQ(shift.r_mode, s[0]->addressing_mode());
1044    EXPECT_EQ(3U, s[0]->InputCount());
1045    EXPECT_EQ(1U, s[0]->OutputCount());
1046    EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1047    EXPECT_EQ(kEqual, s[0]->flags_condition());
1048  }
1049}
1050
1051
1052TEST_P(InstructionSelectorShiftTest, Word32EqualWithParameterAndImmediate) {
1053  const Shift shift = GetParam();
1054  TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) {
1055    StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
1056    m.Return(m.Word32Equal(
1057        (m.*shift.constructor)(m.Parameter(1), m.Int32Constant(imm)),
1058        m.Parameter(0)));
1059    Stream s = m.Build();
1060    ASSERT_EQ(1U, s.size());
1061    EXPECT_EQ(kArmCmp, s[0]->arch_opcode());
1062    EXPECT_EQ(shift.i_mode, s[0]->addressing_mode());
1063    ASSERT_EQ(3U, s[0]->InputCount());
1064    EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2)));
1065    EXPECT_EQ(1U, s[0]->OutputCount());
1066    EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1067    EXPECT_EQ(kEqual, s[0]->flags_condition());
1068  }
1069  TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) {
1070    StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
1071    m.Return(m.Word32Equal(
1072        m.Parameter(0),
1073        (m.*shift.constructor)(m.Parameter(1), m.Int32Constant(imm))));
1074    Stream s = m.Build();
1075    ASSERT_EQ(1U, s.size());
1076    EXPECT_EQ(kArmCmp, s[0]->arch_opcode());
1077    EXPECT_EQ(shift.i_mode, s[0]->addressing_mode());
1078    ASSERT_EQ(3U, s[0]->InputCount());
1079    EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2)));
1080    EXPECT_EQ(1U, s[0]->OutputCount());
1081    EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1082    EXPECT_EQ(kEqual, s[0]->flags_condition());
1083  }
1084}
1085
1086
1087TEST_P(InstructionSelectorShiftTest, Word32EqualToZeroWithParameters) {
1088  const Shift shift = GetParam();
1089  StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
1090  m.Return(
1091      m.Word32Equal(m.Int32Constant(0),
1092                    (m.*shift.constructor)(m.Parameter(0), m.Parameter(1))));
1093  Stream s = m.Build();
1094  ASSERT_EQ(1U, s.size());
1095  EXPECT_EQ(kArmMov, s[0]->arch_opcode());
1096  EXPECT_EQ(shift.r_mode, s[0]->addressing_mode());
1097  EXPECT_EQ(2U, s[0]->InputCount());
1098  EXPECT_EQ(2U, s[0]->OutputCount());
1099  EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1100  EXPECT_EQ(kEqual, s[0]->flags_condition());
1101}
1102
1103
1104TEST_P(InstructionSelectorShiftTest, Word32EqualToZeroWithImmediate) {
1105  const Shift shift = GetParam();
1106  TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) {
1107    StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
1108    m.Return(m.Word32Equal(
1109        m.Int32Constant(0),
1110        (m.*shift.constructor)(m.Parameter(0), m.Int32Constant(imm))));
1111    Stream s = m.Build();
1112    ASSERT_EQ(1U, s.size());
1113    EXPECT_EQ(kArmMov, s[0]->arch_opcode());
1114    EXPECT_EQ(shift.i_mode, s[0]->addressing_mode());
1115    ASSERT_EQ(2U, s[0]->InputCount());
1116    EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
1117    EXPECT_EQ(2U, s[0]->OutputCount());
1118    EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1119    EXPECT_EQ(kEqual, s[0]->flags_condition());
1120  }
1121}
1122
1123
1124TEST_P(InstructionSelectorShiftTest, Word32NotWithParameters) {
1125  const Shift shift = GetParam();
1126  StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
1127  m.Return(m.Word32Not((m.*shift.constructor)(m.Parameter(0), m.Parameter(1))));
1128  Stream s = m.Build();
1129  ASSERT_EQ(1U, s.size());
1130  EXPECT_EQ(kArmMvn, s[0]->arch_opcode());
1131  EXPECT_EQ(shift.r_mode, s[0]->addressing_mode());
1132  EXPECT_EQ(2U, s[0]->InputCount());
1133  EXPECT_EQ(1U, s[0]->OutputCount());
1134}
1135
1136
1137TEST_P(InstructionSelectorShiftTest, Word32NotWithImmediate) {
1138  const Shift shift = GetParam();
1139  TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) {
1140    StreamBuilder m(this, kMachInt32, kMachInt32);
1141    m.Return(m.Word32Not(
1142        (m.*shift.constructor)(m.Parameter(0), m.Int32Constant(imm))));
1143    Stream s = m.Build();
1144    ASSERT_EQ(1U, s.size());
1145    EXPECT_EQ(kArmMvn, s[0]->arch_opcode());
1146    EXPECT_EQ(shift.i_mode, s[0]->addressing_mode());
1147    ASSERT_EQ(2U, s[0]->InputCount());
1148    EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
1149    EXPECT_EQ(1U, s[0]->OutputCount());
1150  }
1151}
1152
1153
1154TEST_P(InstructionSelectorShiftTest, Word32AndWithWord32NotWithParameters) {
1155  const Shift shift = GetParam();
1156  StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32, kMachInt32);
1157  m.Return(m.Word32And(m.Parameter(0), m.Word32Not((m.*shift.constructor)(
1158                                           m.Parameter(1), m.Parameter(2)))));
1159  Stream s = m.Build();
1160  ASSERT_EQ(1U, s.size());
1161  EXPECT_EQ(kArmBic, s[0]->arch_opcode());
1162  EXPECT_EQ(shift.r_mode, s[0]->addressing_mode());
1163  EXPECT_EQ(3U, s[0]->InputCount());
1164  EXPECT_EQ(1U, s[0]->OutputCount());
1165}
1166
1167
1168TEST_P(InstructionSelectorShiftTest, Word32AndWithWord32NotWithImmediate) {
1169  const Shift shift = GetParam();
1170  TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) {
1171    StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
1172    m.Return(m.Word32And(m.Parameter(0),
1173                         m.Word32Not((m.*shift.constructor)(
1174                             m.Parameter(1), m.Int32Constant(imm)))));
1175    Stream s = m.Build();
1176    ASSERT_EQ(1U, s.size());
1177    EXPECT_EQ(kArmBic, s[0]->arch_opcode());
1178    EXPECT_EQ(shift.i_mode, s[0]->addressing_mode());
1179    ASSERT_EQ(3U, s[0]->InputCount());
1180    EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2)));
1181    EXPECT_EQ(1U, s[0]->OutputCount());
1182  }
1183}
1184
1185
1186INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorShiftTest,
1187                        ::testing::ValuesIn(kShifts));
1188
1189
1190// -----------------------------------------------------------------------------
1191// Memory access instructions.
1192
1193
1194namespace {
1195
1196struct MemoryAccess {
1197  MachineType type;
1198  ArchOpcode ldr_opcode;
1199  ArchOpcode str_opcode;
1200  bool (InstructionSelectorTest::Stream::*val_predicate)(
1201      const InstructionOperand*) const;
1202  const int32_t immediates[40];
1203};
1204
1205
1206std::ostream& operator<<(std::ostream& os, const MemoryAccess& memacc) {
1207  OStringStream ost;
1208  ost << memacc.type;
1209  return os << ost.c_str();
1210}
1211
1212
1213static const MemoryAccess kMemoryAccesses[] = {
1214    {kMachInt8,
1215     kArmLdrsb,
1216     kArmStrb,
1217     &InstructionSelectorTest::Stream::IsInteger,
1218     {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89,
1219      -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109,
1220      115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}},
1221    {kMachUint8,
1222     kArmLdrb,
1223     kArmStrb,
1224     &InstructionSelectorTest::Stream::IsInteger,
1225     {-4095, -3914, -3536, -3234, -3185, -3169, -1073, -990, -859, -720, -434,
1226      -127, -124, -122, -105, -91, -86, -64, -55, -53, -30, -10, -3, 0, 20, 28,
1227      39, 58, 64, 73, 75, 100, 108, 121, 686, 963, 1363, 2759, 3449, 4095}},
1228    {kMachInt16,
1229     kArmLdrsh,
1230     kArmStrh,
1231     &InstructionSelectorTest::Stream::IsInteger,
1232     {-255, -251, -232, -220, -144, -138, -130, -126, -116, -115, -102, -101,
1233      -98, -69, -59, -56, -39, -35, -23, -19, -7, 0, 22, 26, 37, 68, 83, 87, 98,
1234      102, 108, 111, 117, 171, 195, 203, 204, 245, 246, 255}},
1235    {kMachUint16,
1236     kArmLdrh,
1237     kArmStrh,
1238     &InstructionSelectorTest::Stream::IsInteger,
1239     {-255, -230, -201, -172, -125, -119, -118, -105, -98, -79, -54, -42, -41,
1240      -32, -12, -11, -5, -4, 0, 5, 9, 25, 28, 51, 58, 60, 89, 104, 108, 109,
1241      114, 116, 120, 138, 150, 161, 166, 172, 228, 255}},
1242    {kMachInt32,
1243     kArmLdr,
1244     kArmStr,
1245     &InstructionSelectorTest::Stream::IsInteger,
1246     {-4095, -1898, -1685, -1562, -1408, -1313, -344, -128, -116, -100, -92,
1247      -80, -72, -71, -56, -25, -21, -11, -9, 0, 3, 5, 27, 28, 42, 52, 63, 88,
1248      93, 97, 125, 846, 1037, 2102, 2403, 2597, 2632, 2997, 3935, 4095}},
1249    {kMachFloat32,
1250     kArmVldr32,
1251     kArmVstr32,
1252     &InstructionSelectorTest::Stream::IsDouble,
1253     {-1020, -928, -896, -772, -728, -680, -660, -488, -372, -112, -100, -92,
1254      -84, -80, -72, -64, -60, -56, -52, -48, -36, -32, -20, -8, -4, 0, 8, 20,
1255      24, 40, 64, 112, 204, 388, 516, 852, 856, 976, 988, 1020}},
1256    {kMachFloat64,
1257     kArmVldr64,
1258     kArmVstr64,
1259     &InstructionSelectorTest::Stream::IsDouble,
1260     {-1020, -948, -796, -696, -612, -364, -320, -308, -128, -112, -108, -104,
1261      -96, -84, -80, -56, -48, -40, -20, 0, 24, 28, 36, 48, 64, 84, 96, 100,
1262      108, 116, 120, 140, 156, 408, 432, 444, 772, 832, 940, 1020}}};
1263
1264}  // namespace
1265
1266
1267typedef InstructionSelectorTestWithParam<MemoryAccess>
1268    InstructionSelectorMemoryAccessTest;
1269
1270
1271TEST_P(InstructionSelectorMemoryAccessTest, LoadWithParameters) {
1272  const MemoryAccess memacc = GetParam();
1273  StreamBuilder m(this, memacc.type, kMachPtr, kMachInt32);
1274  m.Return(m.Load(memacc.type, m.Parameter(0), m.Parameter(1)));
1275  Stream s = m.Build();
1276  ASSERT_EQ(1U, s.size());
1277  EXPECT_EQ(memacc.ldr_opcode, s[0]->arch_opcode());
1278  EXPECT_EQ(kMode_Offset_RR, s[0]->addressing_mode());
1279  EXPECT_EQ(2U, s[0]->InputCount());
1280  ASSERT_EQ(1U, s[0]->OutputCount());
1281  EXPECT_TRUE((s.*memacc.val_predicate)(s[0]->Output()));
1282}
1283
1284
1285TEST_P(InstructionSelectorMemoryAccessTest, LoadWithImmediateIndex) {
1286  const MemoryAccess memacc = GetParam();
1287  TRACED_FOREACH(int32_t, index, memacc.immediates) {
1288    StreamBuilder m(this, memacc.type, kMachPtr);
1289    m.Return(m.Load(memacc.type, m.Parameter(0), m.Int32Constant(index)));
1290    Stream s = m.Build();
1291    ASSERT_EQ(1U, s.size());
1292    EXPECT_EQ(memacc.ldr_opcode, s[0]->arch_opcode());
1293    EXPECT_EQ(kMode_Offset_RI, s[0]->addressing_mode());
1294    ASSERT_EQ(2U, s[0]->InputCount());
1295    ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
1296    EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1)));
1297    ASSERT_EQ(1U, s[0]->OutputCount());
1298    EXPECT_TRUE((s.*memacc.val_predicate)(s[0]->Output()));
1299  }
1300}
1301
1302
1303TEST_P(InstructionSelectorMemoryAccessTest, StoreWithParameters) {
1304  const MemoryAccess memacc = GetParam();
1305  StreamBuilder m(this, kMachInt32, kMachPtr, kMachInt32, memacc.type);
1306  m.Store(memacc.type, m.Parameter(0), m.Parameter(1), m.Parameter(2));
1307  m.Return(m.Int32Constant(0));
1308  Stream s = m.Build();
1309  ASSERT_EQ(1U, s.size());
1310  EXPECT_EQ(memacc.str_opcode, s[0]->arch_opcode());
1311  EXPECT_EQ(kMode_Offset_RR, s[0]->addressing_mode());
1312  EXPECT_EQ(3U, s[0]->InputCount());
1313  EXPECT_EQ(0U, s[0]->OutputCount());
1314}
1315
1316
1317TEST_P(InstructionSelectorMemoryAccessTest, StoreWithImmediateIndex) {
1318  const MemoryAccess memacc = GetParam();
1319  TRACED_FOREACH(int32_t, index, memacc.immediates) {
1320    StreamBuilder m(this, kMachInt32, kMachPtr, memacc.type);
1321    m.Store(memacc.type, m.Parameter(0), m.Int32Constant(index),
1322            m.Parameter(1));
1323    m.Return(m.Int32Constant(0));
1324    Stream s = m.Build();
1325    ASSERT_EQ(1U, s.size());
1326    EXPECT_EQ(memacc.str_opcode, s[0]->arch_opcode());
1327    EXPECT_EQ(kMode_Offset_RI, s[0]->addressing_mode());
1328    ASSERT_EQ(3U, s[0]->InputCount());
1329    ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
1330    EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1)));
1331    EXPECT_EQ(0U, s[0]->OutputCount());
1332  }
1333}
1334
1335
1336INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1337                        InstructionSelectorMemoryAccessTest,
1338                        ::testing::ValuesIn(kMemoryAccesses));
1339
1340
1341// -----------------------------------------------------------------------------
1342// Miscellaneous.
1343
1344
1345TEST_F(InstructionSelectorTest, Int32AddWithInt32Mul) {
1346  {
1347    StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32, kMachInt32);
1348    m.Return(
1349        m.Int32Add(m.Parameter(0), m.Int32Mul(m.Parameter(1), m.Parameter(2))));
1350    Stream s = m.Build();
1351    ASSERT_EQ(1U, s.size());
1352    EXPECT_EQ(kArmMla, s[0]->arch_opcode());
1353    EXPECT_EQ(3U, s[0]->InputCount());
1354    EXPECT_EQ(1U, s[0]->OutputCount());
1355  }
1356  {
1357    StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32, kMachInt32);
1358    m.Return(
1359        m.Int32Add(m.Int32Mul(m.Parameter(1), m.Parameter(2)), m.Parameter(0)));
1360    Stream s = m.Build();
1361    ASSERT_EQ(1U, s.size());
1362    EXPECT_EQ(kArmMla, s[0]->arch_opcode());
1363    EXPECT_EQ(3U, s[0]->InputCount());
1364    EXPECT_EQ(1U, s[0]->OutputCount());
1365  }
1366}
1367
1368
1369TEST_F(InstructionSelectorTest, Int32DivWithParameters) {
1370  StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
1371  m.Return(m.Int32Div(m.Parameter(0), m.Parameter(1)));
1372  Stream s = m.Build();
1373  ASSERT_EQ(4U, s.size());
1374  EXPECT_EQ(kArmVcvtF64S32, s[0]->arch_opcode());
1375  ASSERT_EQ(1U, s[0]->OutputCount());
1376  EXPECT_EQ(kArmVcvtF64S32, s[1]->arch_opcode());
1377  ASSERT_EQ(1U, s[1]->OutputCount());
1378  EXPECT_EQ(kArmVdivF64, s[2]->arch_opcode());
1379  ASSERT_EQ(2U, s[2]->InputCount());
1380  ASSERT_EQ(1U, s[2]->OutputCount());
1381  EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[2]->InputAt(0)));
1382  EXPECT_EQ(s.ToVreg(s[1]->Output()), s.ToVreg(s[2]->InputAt(1)));
1383  EXPECT_EQ(kArmVcvtS32F64, s[3]->arch_opcode());
1384  ASSERT_EQ(1U, s[3]->InputCount());
1385  EXPECT_EQ(s.ToVreg(s[2]->Output()), s.ToVreg(s[3]->InputAt(0)));
1386}
1387
1388
1389TEST_F(InstructionSelectorTest, Int32DivWithParametersForSUDIV) {
1390  StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
1391  m.Return(m.Int32Div(m.Parameter(0), m.Parameter(1)));
1392  Stream s = m.Build(SUDIV);
1393  ASSERT_EQ(1U, s.size());
1394  EXPECT_EQ(kArmSdiv, s[0]->arch_opcode());
1395}
1396
1397
1398TEST_F(InstructionSelectorTest, Int32ModWithParameters) {
1399  StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
1400  m.Return(m.Int32Mod(m.Parameter(0), m.Parameter(1)));
1401  Stream s = m.Build();
1402  ASSERT_EQ(6U, s.size());
1403  EXPECT_EQ(kArmVcvtF64S32, s[0]->arch_opcode());
1404  ASSERT_EQ(1U, s[0]->OutputCount());
1405  EXPECT_EQ(kArmVcvtF64S32, s[1]->arch_opcode());
1406  ASSERT_EQ(1U, s[1]->OutputCount());
1407  EXPECT_EQ(kArmVdivF64, s[2]->arch_opcode());
1408  ASSERT_EQ(2U, s[2]->InputCount());
1409  ASSERT_EQ(1U, s[2]->OutputCount());
1410  EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[2]->InputAt(0)));
1411  EXPECT_EQ(s.ToVreg(s[1]->Output()), s.ToVreg(s[2]->InputAt(1)));
1412  EXPECT_EQ(kArmVcvtS32F64, s[3]->arch_opcode());
1413  ASSERT_EQ(1U, s[3]->InputCount());
1414  EXPECT_EQ(s.ToVreg(s[2]->Output()), s.ToVreg(s[3]->InputAt(0)));
1415  EXPECT_EQ(kArmMul, s[4]->arch_opcode());
1416  ASSERT_EQ(1U, s[4]->OutputCount());
1417  ASSERT_EQ(2U, s[4]->InputCount());
1418  EXPECT_EQ(s.ToVreg(s[3]->Output()), s.ToVreg(s[4]->InputAt(0)));
1419  EXPECT_EQ(s.ToVreg(s[1]->InputAt(0)), s.ToVreg(s[4]->InputAt(1)));
1420  EXPECT_EQ(kArmSub, s[5]->arch_opcode());
1421  ASSERT_EQ(1U, s[5]->OutputCount());
1422  ASSERT_EQ(2U, s[5]->InputCount());
1423  EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[5]->InputAt(0)));
1424  EXPECT_EQ(s.ToVreg(s[4]->Output()), s.ToVreg(s[5]->InputAt(1)));
1425}
1426
1427
1428TEST_F(InstructionSelectorTest, Int32ModWithParametersForSUDIV) {
1429  StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
1430  m.Return(m.Int32Mod(m.Parameter(0), m.Parameter(1)));
1431  Stream s = m.Build(SUDIV);
1432  ASSERT_EQ(3U, s.size());
1433  EXPECT_EQ(kArmSdiv, s[0]->arch_opcode());
1434  ASSERT_EQ(1U, s[0]->OutputCount());
1435  ASSERT_EQ(2U, s[0]->InputCount());
1436  EXPECT_EQ(kArmMul, s[1]->arch_opcode());
1437  ASSERT_EQ(1U, s[1]->OutputCount());
1438  ASSERT_EQ(2U, s[1]->InputCount());
1439  EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(0)));
1440  EXPECT_EQ(s.ToVreg(s[0]->InputAt(1)), s.ToVreg(s[1]->InputAt(1)));
1441  EXPECT_EQ(kArmSub, s[2]->arch_opcode());
1442  ASSERT_EQ(1U, s[2]->OutputCount());
1443  ASSERT_EQ(2U, s[2]->InputCount());
1444  EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[2]->InputAt(0)));
1445  EXPECT_EQ(s.ToVreg(s[1]->Output()), s.ToVreg(s[2]->InputAt(1)));
1446}
1447
1448
1449TEST_F(InstructionSelectorTest, Int32ModWithParametersForSUDIVAndMLS) {
1450  StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
1451  m.Return(m.Int32Mod(m.Parameter(0), m.Parameter(1)));
1452  Stream s = m.Build(MLS, SUDIV);
1453  ASSERT_EQ(2U, s.size());
1454  EXPECT_EQ(kArmSdiv, s[0]->arch_opcode());
1455  ASSERT_EQ(1U, s[0]->OutputCount());
1456  ASSERT_EQ(2U, s[0]->InputCount());
1457  EXPECT_EQ(kArmMls, s[1]->arch_opcode());
1458  ASSERT_EQ(1U, s[1]->OutputCount());
1459  ASSERT_EQ(3U, s[1]->InputCount());
1460  EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(0)));
1461  EXPECT_EQ(s.ToVreg(s[0]->InputAt(1)), s.ToVreg(s[1]->InputAt(1)));
1462  EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[1]->InputAt(2)));
1463}
1464
1465
1466TEST_F(InstructionSelectorTest, Int32MulWithParameters) {
1467  StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
1468  m.Return(m.Int32Mul(m.Parameter(0), m.Parameter(1)));
1469  Stream s = m.Build();
1470  ASSERT_EQ(1U, s.size());
1471  EXPECT_EQ(kArmMul, s[0]->arch_opcode());
1472  EXPECT_EQ(2U, s[0]->InputCount());
1473  EXPECT_EQ(1U, s[0]->OutputCount());
1474}
1475
1476
1477TEST_F(InstructionSelectorTest, Int32MulWithImmediate) {
1478  // x * (2^k + 1) -> x + (x >> k)
1479  TRACED_FORRANGE(int32_t, k, 1, 30) {
1480    StreamBuilder m(this, kMachInt32, kMachInt32);
1481    m.Return(m.Int32Mul(m.Parameter(0), m.Int32Constant((1 << k) + 1)));
1482    Stream s = m.Build();
1483    ASSERT_EQ(1U, s.size());
1484    EXPECT_EQ(kArmAdd, s[0]->arch_opcode());
1485    EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
1486    ASSERT_EQ(3U, s[0]->InputCount());
1487    EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
1488    EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2)));
1489    EXPECT_EQ(1U, s[0]->OutputCount());
1490  }
1491  // x * (2^k - 1) -> -x + (x >> k)
1492  TRACED_FORRANGE(int32_t, k, 3, 30) {
1493    StreamBuilder m(this, kMachInt32, kMachInt32);
1494    m.Return(m.Int32Mul(m.Parameter(0), m.Int32Constant((1 << k) - 1)));
1495    Stream s = m.Build();
1496    ASSERT_EQ(1U, s.size());
1497    EXPECT_EQ(kArmRsb, s[0]->arch_opcode());
1498    EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
1499    ASSERT_EQ(3U, s[0]->InputCount());
1500    EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
1501    EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2)));
1502    EXPECT_EQ(1U, s[0]->OutputCount());
1503  }
1504  // (2^k + 1) * x -> x + (x >> k)
1505  TRACED_FORRANGE(int32_t, k, 1, 30) {
1506    StreamBuilder m(this, kMachInt32, kMachInt32);
1507    m.Return(m.Int32Mul(m.Int32Constant((1 << k) + 1), m.Parameter(0)));
1508    Stream s = m.Build();
1509    ASSERT_EQ(1U, s.size());
1510    EXPECT_EQ(kArmAdd, s[0]->arch_opcode());
1511    EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
1512    ASSERT_EQ(3U, s[0]->InputCount());
1513    EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
1514    EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2)));
1515    EXPECT_EQ(1U, s[0]->OutputCount());
1516  }
1517  // x * (2^k - 1) -> -x + (x >> k)
1518  TRACED_FORRANGE(int32_t, k, 3, 30) {
1519    StreamBuilder m(this, kMachInt32, kMachInt32);
1520    m.Return(m.Int32Mul(m.Int32Constant((1 << k) - 1), m.Parameter(0)));
1521    Stream s = m.Build();
1522    ASSERT_EQ(1U, s.size());
1523    EXPECT_EQ(kArmRsb, s[0]->arch_opcode());
1524    EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
1525    ASSERT_EQ(3U, s[0]->InputCount());
1526    EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
1527    EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2)));
1528    EXPECT_EQ(1U, s[0]->OutputCount());
1529  }
1530}
1531
1532
1533TEST_F(InstructionSelectorTest, Int32SubWithInt32Mul) {
1534  StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32, kMachInt32);
1535  m.Return(
1536      m.Int32Sub(m.Parameter(0), m.Int32Mul(m.Parameter(1), m.Parameter(2))));
1537  Stream s = m.Build();
1538  ASSERT_EQ(2U, s.size());
1539  EXPECT_EQ(kArmMul, s[0]->arch_opcode());
1540  ASSERT_EQ(1U, s[0]->OutputCount());
1541  EXPECT_EQ(kArmSub, s[1]->arch_opcode());
1542  ASSERT_EQ(2U, s[1]->InputCount());
1543  EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(1)));
1544}
1545
1546
1547TEST_F(InstructionSelectorTest, Int32SubWithInt32MulForMLS) {
1548  StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32, kMachInt32);
1549  m.Return(
1550      m.Int32Sub(m.Parameter(0), m.Int32Mul(m.Parameter(1), m.Parameter(2))));
1551  Stream s = m.Build(MLS);
1552  ASSERT_EQ(1U, s.size());
1553  EXPECT_EQ(kArmMls, s[0]->arch_opcode());
1554  EXPECT_EQ(1U, s[0]->OutputCount());
1555  EXPECT_EQ(3U, s[0]->InputCount());
1556}
1557
1558
1559TEST_F(InstructionSelectorTest, Int32UDivWithParameters) {
1560  StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
1561  m.Return(m.Int32UDiv(m.Parameter(0), m.Parameter(1)));
1562  Stream s = m.Build();
1563  ASSERT_EQ(4U, s.size());
1564  EXPECT_EQ(kArmVcvtF64U32, s[0]->arch_opcode());
1565  ASSERT_EQ(1U, s[0]->OutputCount());
1566  EXPECT_EQ(kArmVcvtF64U32, s[1]->arch_opcode());
1567  ASSERT_EQ(1U, s[1]->OutputCount());
1568  EXPECT_EQ(kArmVdivF64, s[2]->arch_opcode());
1569  ASSERT_EQ(2U, s[2]->InputCount());
1570  ASSERT_EQ(1U, s[2]->OutputCount());
1571  EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[2]->InputAt(0)));
1572  EXPECT_EQ(s.ToVreg(s[1]->Output()), s.ToVreg(s[2]->InputAt(1)));
1573  EXPECT_EQ(kArmVcvtU32F64, s[3]->arch_opcode());
1574  ASSERT_EQ(1U, s[3]->InputCount());
1575  EXPECT_EQ(s.ToVreg(s[2]->Output()), s.ToVreg(s[3]->InputAt(0)));
1576}
1577
1578
1579TEST_F(InstructionSelectorTest, Int32UDivWithParametersForSUDIV) {
1580  StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
1581  m.Return(m.Int32UDiv(m.Parameter(0), m.Parameter(1)));
1582  Stream s = m.Build(SUDIV);
1583  ASSERT_EQ(1U, s.size());
1584  EXPECT_EQ(kArmUdiv, s[0]->arch_opcode());
1585}
1586
1587
1588TEST_F(InstructionSelectorTest, Int32UModWithParameters) {
1589  StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
1590  m.Return(m.Int32UMod(m.Parameter(0), m.Parameter(1)));
1591  Stream s = m.Build();
1592  ASSERT_EQ(6U, s.size());
1593  EXPECT_EQ(kArmVcvtF64U32, s[0]->arch_opcode());
1594  ASSERT_EQ(1U, s[0]->OutputCount());
1595  EXPECT_EQ(kArmVcvtF64U32, s[1]->arch_opcode());
1596  ASSERT_EQ(1U, s[1]->OutputCount());
1597  EXPECT_EQ(kArmVdivF64, s[2]->arch_opcode());
1598  ASSERT_EQ(2U, s[2]->InputCount());
1599  ASSERT_EQ(1U, s[2]->OutputCount());
1600  EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[2]->InputAt(0)));
1601  EXPECT_EQ(s.ToVreg(s[1]->Output()), s.ToVreg(s[2]->InputAt(1)));
1602  EXPECT_EQ(kArmVcvtU32F64, s[3]->arch_opcode());
1603  ASSERT_EQ(1U, s[3]->InputCount());
1604  EXPECT_EQ(s.ToVreg(s[2]->Output()), s.ToVreg(s[3]->InputAt(0)));
1605  EXPECT_EQ(kArmMul, s[4]->arch_opcode());
1606  ASSERT_EQ(1U, s[4]->OutputCount());
1607  ASSERT_EQ(2U, s[4]->InputCount());
1608  EXPECT_EQ(s.ToVreg(s[3]->Output()), s.ToVreg(s[4]->InputAt(0)));
1609  EXPECT_EQ(s.ToVreg(s[1]->InputAt(0)), s.ToVreg(s[4]->InputAt(1)));
1610  EXPECT_EQ(kArmSub, s[5]->arch_opcode());
1611  ASSERT_EQ(1U, s[5]->OutputCount());
1612  ASSERT_EQ(2U, s[5]->InputCount());
1613  EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[5]->InputAt(0)));
1614  EXPECT_EQ(s.ToVreg(s[4]->Output()), s.ToVreg(s[5]->InputAt(1)));
1615}
1616
1617
1618TEST_F(InstructionSelectorTest, Int32UModWithParametersForSUDIV) {
1619  StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
1620  m.Return(m.Int32UMod(m.Parameter(0), m.Parameter(1)));
1621  Stream s = m.Build(SUDIV);
1622  ASSERT_EQ(3U, s.size());
1623  EXPECT_EQ(kArmUdiv, s[0]->arch_opcode());
1624  ASSERT_EQ(1U, s[0]->OutputCount());
1625  ASSERT_EQ(2U, s[0]->InputCount());
1626  EXPECT_EQ(kArmMul, s[1]->arch_opcode());
1627  ASSERT_EQ(1U, s[1]->OutputCount());
1628  ASSERT_EQ(2U, s[1]->InputCount());
1629  EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(0)));
1630  EXPECT_EQ(s.ToVreg(s[0]->InputAt(1)), s.ToVreg(s[1]->InputAt(1)));
1631  EXPECT_EQ(kArmSub, s[2]->arch_opcode());
1632  ASSERT_EQ(1U, s[2]->OutputCount());
1633  ASSERT_EQ(2U, s[2]->InputCount());
1634  EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[2]->InputAt(0)));
1635  EXPECT_EQ(s.ToVreg(s[1]->Output()), s.ToVreg(s[2]->InputAt(1)));
1636}
1637
1638
1639TEST_F(InstructionSelectorTest, Int32UModWithParametersForSUDIVAndMLS) {
1640  StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
1641  m.Return(m.Int32UMod(m.Parameter(0), m.Parameter(1)));
1642  Stream s = m.Build(MLS, SUDIV);
1643  ASSERT_EQ(2U, s.size());
1644  EXPECT_EQ(kArmUdiv, s[0]->arch_opcode());
1645  ASSERT_EQ(1U, s[0]->OutputCount());
1646  ASSERT_EQ(2U, s[0]->InputCount());
1647  EXPECT_EQ(kArmMls, s[1]->arch_opcode());
1648  ASSERT_EQ(1U, s[1]->OutputCount());
1649  ASSERT_EQ(3U, s[1]->InputCount());
1650  EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(0)));
1651  EXPECT_EQ(s.ToVreg(s[0]->InputAt(1)), s.ToVreg(s[1]->InputAt(1)));
1652  EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[1]->InputAt(2)));
1653}
1654
1655
1656TEST_F(InstructionSelectorTest, Word32AndWithUbfxImmediateForARMv7) {
1657  TRACED_FORRANGE(int32_t, width, 1, 32) {
1658    StreamBuilder m(this, kMachInt32, kMachInt32);
1659    m.Return(m.Word32And(m.Parameter(0),
1660                         m.Int32Constant(0xffffffffu >> (32 - width))));
1661    Stream s = m.Build(ARMv7);
1662    ASSERT_EQ(1U, s.size());
1663    EXPECT_EQ(kArmUbfx, s[0]->arch_opcode());
1664    ASSERT_EQ(3U, s[0]->InputCount());
1665    EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1)));
1666    EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
1667  }
1668  TRACED_FORRANGE(int32_t, width, 1, 32) {
1669    StreamBuilder m(this, kMachInt32, kMachInt32);
1670    m.Return(m.Word32And(m.Int32Constant(0xffffffffu >> (32 - width)),
1671                         m.Parameter(0)));
1672    Stream s = m.Build(ARMv7);
1673    ASSERT_EQ(1U, s.size());
1674    EXPECT_EQ(kArmUbfx, s[0]->arch_opcode());
1675    ASSERT_EQ(3U, s[0]->InputCount());
1676    EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1)));
1677    EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
1678  }
1679}
1680
1681
1682TEST_F(InstructionSelectorTest, Word32AndWithBfcImmediateForARMv7) {
1683  TRACED_FORRANGE(int32_t, lsb, 0, 31) {
1684    TRACED_FORRANGE(int32_t, width, 1, (32 - lsb) - 1) {
1685      StreamBuilder m(this, kMachInt32, kMachInt32);
1686      m.Return(m.Word32And(
1687          m.Parameter(0),
1688          m.Int32Constant(~((0xffffffffu >> (32 - width)) << lsb))));
1689      Stream s = m.Build(ARMv7);
1690      ASSERT_EQ(1U, s.size());
1691      EXPECT_EQ(kArmBfc, s[0]->arch_opcode());
1692      ASSERT_EQ(1U, s[0]->OutputCount());
1693      EXPECT_TRUE(
1694          UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy());
1695      ASSERT_EQ(3U, s[0]->InputCount());
1696      EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
1697      EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
1698    }
1699  }
1700  TRACED_FORRANGE(int32_t, lsb, 0, 31) {
1701    TRACED_FORRANGE(int32_t, width, 1, (32 - lsb) - 1) {
1702      StreamBuilder m(this, kMachInt32, kMachInt32);
1703      m.Return(
1704          m.Word32And(m.Int32Constant(~((0xffffffffu >> (32 - width)) << lsb)),
1705                      m.Parameter(0)));
1706      Stream s = m.Build(ARMv7);
1707      ASSERT_EQ(1U, s.size());
1708      EXPECT_EQ(kArmBfc, s[0]->arch_opcode());
1709      ASSERT_EQ(1U, s[0]->OutputCount());
1710      EXPECT_TRUE(
1711          UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy());
1712      ASSERT_EQ(3U, s[0]->InputCount());
1713      EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
1714      EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
1715    }
1716  }
1717}
1718
1719
1720TEST_F(InstructionSelectorTest, Word32ShrWithWord32AndWithImmediateForARMv7) {
1721  TRACED_FORRANGE(int32_t, lsb, 0, 31) {
1722    TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) {
1723      uint32_t max = 1 << lsb;
1724      if (max > static_cast<uint32_t>(kMaxInt)) max -= 1;
1725      uint32_t jnk = rng()->NextInt(max);
1726      uint32_t msk = ((0xffffffffu >> (32 - width)) << lsb) | jnk;
1727      StreamBuilder m(this, kMachInt32, kMachInt32);
1728      m.Return(m.Word32Shr(m.Word32And(m.Parameter(0), m.Int32Constant(msk)),
1729                           m.Int32Constant(lsb)));
1730      Stream s = m.Build(ARMv7);
1731      ASSERT_EQ(1U, s.size());
1732      EXPECT_EQ(kArmUbfx, s[0]->arch_opcode());
1733      ASSERT_EQ(3U, s[0]->InputCount());
1734      EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
1735      EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
1736    }
1737  }
1738  TRACED_FORRANGE(int32_t, lsb, 0, 31) {
1739    TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) {
1740      uint32_t max = 1 << lsb;
1741      if (max > static_cast<uint32_t>(kMaxInt)) max -= 1;
1742      uint32_t jnk = rng()->NextInt(max);
1743      uint32_t msk = ((0xffffffffu >> (32 - width)) << lsb) | jnk;
1744      StreamBuilder m(this, kMachInt32, kMachInt32);
1745      m.Return(m.Word32Shr(m.Word32And(m.Int32Constant(msk), m.Parameter(0)),
1746                           m.Int32Constant(lsb)));
1747      Stream s = m.Build(ARMv7);
1748      ASSERT_EQ(1U, s.size());
1749      EXPECT_EQ(kArmUbfx, s[0]->arch_opcode());
1750      ASSERT_EQ(3U, s[0]->InputCount());
1751      EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
1752      EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
1753    }
1754  }
1755}
1756
1757
1758TEST_F(InstructionSelectorTest, Word32AndWithWord32Not) {
1759  {
1760    StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
1761    m.Return(m.Word32And(m.Parameter(0), m.Word32Not(m.Parameter(1))));
1762    Stream s = m.Build();
1763    ASSERT_EQ(1U, s.size());
1764    EXPECT_EQ(kArmBic, s[0]->arch_opcode());
1765    EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
1766    EXPECT_EQ(2U, s[0]->InputCount());
1767    EXPECT_EQ(1U, s[0]->OutputCount());
1768  }
1769  {
1770    StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
1771    m.Return(m.Word32And(m.Word32Not(m.Parameter(0)), m.Parameter(1)));
1772    Stream s = m.Build();
1773    ASSERT_EQ(1U, s.size());
1774    EXPECT_EQ(kArmBic, s[0]->arch_opcode());
1775    EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
1776    EXPECT_EQ(2U, s[0]->InputCount());
1777    EXPECT_EQ(1U, s[0]->OutputCount());
1778  }
1779}
1780
1781
1782TEST_F(InstructionSelectorTest, Word32EqualWithParameters) {
1783  StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
1784  m.Return(m.Word32Equal(m.Parameter(0), m.Parameter(1)));
1785  Stream s = m.Build();
1786  ASSERT_EQ(1U, s.size());
1787  EXPECT_EQ(kArmCmp, s[0]->arch_opcode());
1788  EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
1789  EXPECT_EQ(2U, s[0]->InputCount());
1790  EXPECT_EQ(1U, s[0]->OutputCount());
1791  EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1792  EXPECT_EQ(kEqual, s[0]->flags_condition());
1793}
1794
1795
1796TEST_F(InstructionSelectorTest, Word32EqualWithImmediate) {
1797  TRACED_FOREACH(int32_t, imm, kImmediates) {
1798    if (imm == 0) continue;
1799    StreamBuilder m(this, kMachInt32, kMachInt32);
1800    m.Return(m.Word32Equal(m.Parameter(0), m.Int32Constant(imm)));
1801    Stream s = m.Build();
1802    ASSERT_EQ(1U, s.size());
1803    EXPECT_EQ(kArmCmp, s[0]->arch_opcode());
1804    EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode());
1805    ASSERT_EQ(2U, s[0]->InputCount());
1806    EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
1807    EXPECT_EQ(1U, s[0]->OutputCount());
1808    EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1809    EXPECT_EQ(kEqual, s[0]->flags_condition());
1810  }
1811  TRACED_FOREACH(int32_t, imm, kImmediates) {
1812    if (imm == 0) continue;
1813    StreamBuilder m(this, kMachInt32, kMachInt32);
1814    m.Return(m.Word32Equal(m.Int32Constant(imm), m.Parameter(0)));
1815    Stream s = m.Build();
1816    ASSERT_EQ(1U, s.size());
1817    EXPECT_EQ(kArmCmp, s[0]->arch_opcode());
1818    EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode());
1819    ASSERT_EQ(2U, s[0]->InputCount());
1820    EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
1821    EXPECT_EQ(1U, s[0]->OutputCount());
1822    EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1823    EXPECT_EQ(kEqual, s[0]->flags_condition());
1824  }
1825}
1826
1827
1828TEST_F(InstructionSelectorTest, Word32EqualWithZero) {
1829  {
1830    StreamBuilder m(this, kMachInt32, kMachInt32);
1831    m.Return(m.Word32Equal(m.Parameter(0), m.Int32Constant(0)));
1832    Stream s = m.Build();
1833    ASSERT_EQ(1U, s.size());
1834    EXPECT_EQ(kArmTst, s[0]->arch_opcode());
1835    EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
1836    ASSERT_EQ(2U, s[0]->InputCount());
1837    EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
1838    EXPECT_EQ(1U, s[0]->OutputCount());
1839    EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1840    EXPECT_EQ(kEqual, s[0]->flags_condition());
1841  }
1842  {
1843    StreamBuilder m(this, kMachInt32, kMachInt32);
1844    m.Return(m.Word32Equal(m.Int32Constant(0), m.Parameter(0)));
1845    Stream s = m.Build();
1846    ASSERT_EQ(1U, s.size());
1847    EXPECT_EQ(kArmTst, s[0]->arch_opcode());
1848    EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
1849    ASSERT_EQ(2U, s[0]->InputCount());
1850    EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
1851    EXPECT_EQ(1U, s[0]->OutputCount());
1852    EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1853    EXPECT_EQ(kEqual, s[0]->flags_condition());
1854  }
1855}
1856
1857
1858TEST_F(InstructionSelectorTest, Word32NotWithParameter) {
1859  StreamBuilder m(this, kMachInt32, kMachInt32);
1860  m.Return(m.Word32Not(m.Parameter(0)));
1861  Stream s = m.Build();
1862  ASSERT_EQ(1U, s.size());
1863  EXPECT_EQ(kArmMvn, s[0]->arch_opcode());
1864  EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
1865  EXPECT_EQ(1U, s[0]->InputCount());
1866  EXPECT_EQ(1U, s[0]->OutputCount());
1867}
1868
1869
1870TEST_F(InstructionSelectorTest, Word32AndWithWord32ShrWithImmediateForARMv7) {
1871  TRACED_FORRANGE(int32_t, lsb, 0, 31) {
1872    TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) {
1873      StreamBuilder m(this, kMachInt32, kMachInt32);
1874      m.Return(m.Word32And(m.Word32Shr(m.Parameter(0), m.Int32Constant(lsb)),
1875                           m.Int32Constant(0xffffffffu >> (32 - width))));
1876      Stream s = m.Build(ARMv7);
1877      ASSERT_EQ(1U, s.size());
1878      EXPECT_EQ(kArmUbfx, s[0]->arch_opcode());
1879      ASSERT_EQ(3U, s[0]->InputCount());
1880      EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
1881      EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
1882    }
1883  }
1884  TRACED_FORRANGE(int32_t, lsb, 0, 31) {
1885    TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) {
1886      StreamBuilder m(this, kMachInt32, kMachInt32);
1887      m.Return(m.Word32And(m.Int32Constant(0xffffffffu >> (32 - width)),
1888                           m.Word32Shr(m.Parameter(0), m.Int32Constant(lsb))));
1889      Stream s = m.Build(ARMv7);
1890      ASSERT_EQ(1U, s.size());
1891      EXPECT_EQ(kArmUbfx, s[0]->arch_opcode());
1892      ASSERT_EQ(3U, s[0]->InputCount());
1893      EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
1894      EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
1895    }
1896  }
1897}
1898}  // namespace compiler
1899}  // namespace internal
1900}  // namespace v8
1901