V8 Project
instruction-selector-arm-unittest.cc
Go to the documentation of this file.
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 
6 
7 namespace v8 {
8 namespace internal {
9 namespace compiler {
10 
11 namespace {
12 
14 typedef Node* (RawMachineAssembler::*Constructor)(Node*, Node*);
15 
16 
17 // Data processing instructions.
18 struct DPI {
20  const char* constructor_name;
24 };
25 
26 
27 std::ostream& operator<<(std::ostream& os, const DPI& dpi) {
28  return os << dpi.constructor_name;
29 }
30 
31 
32 static 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.
41 struct ODPI {
43  const char* constructor_name;
46 };
47 
48 
49 std::ostream& operator<<(std::ostream& os, const ODPI& odpi) {
50  return os << odpi.constructor_name;
51 }
52 
53 
55  "Int32AddWithOverflow", kArmAdd, kArmAdd},
57  "Int32SubWithOverflow", kArmSub, kArmRsb}};
58 
59 
60 // Shifts.
61 struct Shift {
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 
71 std::ostream& operator<<(std::ostream& os, const Shift& shift) {
72  return os << shift.constructor_name;
73 }
74 
75 
76 static 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).
88 static 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 
122 
123 
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 
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 
164 TEST_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 
193 TEST_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 
228 TEST_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 
246 TEST_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 
283 TEST_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 
324 TEST_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 
373 TEST_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 
393 TEST_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 
414 TEST_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 
455 TEST_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 
497  ::testing::ValuesIn(kDPIs));
498 
499 
500 // -----------------------------------------------------------------------------
501 // Data processing instructions with overflow.
502 
503 
505 
506 
507 TEST_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 
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 
556 TEST_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 
591 TEST_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 
632 TEST_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 
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 
678 TEST_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 
711 TEST_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 
750 TEST_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 
766 TEST_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 
799 TEST_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 
832 TEST_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 
873 TEST_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 
894 TEST_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 
937 TEST_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 
958 TEST_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 
980  ::testing::ValuesIn(kODPIs));
981 
982 
983 // -----------------------------------------------------------------------------
984 // Shifts.
985 
986 
988 
989 
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 
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 
1019 TEST_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 
1052 TEST_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 
1087 TEST_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 
1104 TEST_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 
1124 TEST_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 
1137 TEST_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 
1154 TEST_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 
1168 TEST_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 
1187  ::testing::ValuesIn(kShifts));
1188 
1189 
1190 // -----------------------------------------------------------------------------
1191 // Memory access instructions.
1192 
1193 
1194 namespace {
1195 
1200  bool (InstructionSelectorTest::Stream::*val_predicate)(
1201  const InstructionOperand*) const;
1202  const int32_t immediates[40];
1203 };
1204 
1205 
1206 std::ostream& operator<<(std::ostream& os, const MemoryAccess& memacc) {
1207  OStringStream ost;
1208  ost << memacc.type;
1209  return os << ost.c_str();
1210 }
1211 
1212 
1213 static 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  kArmVldrF32,
1251  kArmVstrF32,
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  kArmVldrF64,
1258  kArmVstrF64,
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 
1267 typedef InstructionSelectorTestWithParam<MemoryAccess>
1269 
1270 
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 
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 
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 
1317 TEST_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 
1338  ::testing::ValuesIn(kMemoryAccesses));
1339 
1340 
1341 // -----------------------------------------------------------------------------
1342 // Conversions.
1343 
1344 
1345 TEST_F(InstructionSelectorTest, ChangeFloat32ToFloat64WithParameter) {
1346  StreamBuilder m(this, kMachFloat64, kMachFloat32);
1347  m.Return(m.ChangeFloat32ToFloat64(m.Parameter(0)));
1348  Stream s = m.Build();
1349  ASSERT_EQ(1U, s.size());
1350  EXPECT_EQ(kArmVcvtF64F32, s[0]->arch_opcode());
1351  EXPECT_EQ(1U, s[0]->InputCount());
1352  EXPECT_EQ(1U, s[0]->OutputCount());
1353 }
1354 
1355 
1356 TEST_F(InstructionSelectorTest, TruncateFloat64ToFloat32WithParameter) {
1357  StreamBuilder m(this, kMachFloat32, kMachFloat64);
1358  m.Return(m.TruncateFloat64ToFloat32(m.Parameter(0)));
1359  Stream s = m.Build();
1360  ASSERT_EQ(1U, s.size());
1361  EXPECT_EQ(kArmVcvtF32F64, s[0]->arch_opcode());
1362  EXPECT_EQ(1U, s[0]->InputCount());
1363  EXPECT_EQ(1U, s[0]->OutputCount());
1364 }
1365 
1366 
1367 // -----------------------------------------------------------------------------
1368 // Miscellaneous.
1369 
1370 
1371 TEST_F(InstructionSelectorTest, Int32AddWithInt32Mul) {
1372  {
1373  StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32, kMachInt32);
1374  m.Return(
1375  m.Int32Add(m.Parameter(0), m.Int32Mul(m.Parameter(1), m.Parameter(2))));
1376  Stream s = m.Build();
1377  ASSERT_EQ(1U, s.size());
1378  EXPECT_EQ(kArmMla, s[0]->arch_opcode());
1379  EXPECT_EQ(3U, s[0]->InputCount());
1380  EXPECT_EQ(1U, s[0]->OutputCount());
1381  }
1382  {
1383  StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32, kMachInt32);
1384  m.Return(
1385  m.Int32Add(m.Int32Mul(m.Parameter(1), m.Parameter(2)), m.Parameter(0)));
1386  Stream s = m.Build();
1387  ASSERT_EQ(1U, s.size());
1388  EXPECT_EQ(kArmMla, s[0]->arch_opcode());
1389  EXPECT_EQ(3U, s[0]->InputCount());
1390  EXPECT_EQ(1U, s[0]->OutputCount());
1391  }
1392 }
1393 
1394 
1395 TEST_F(InstructionSelectorTest, Int32DivWithParameters) {
1396  StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
1397  m.Return(m.Int32Div(m.Parameter(0), m.Parameter(1)));
1398  Stream s = m.Build();
1399  ASSERT_EQ(4U, s.size());
1400  EXPECT_EQ(kArmVcvtF64S32, s[0]->arch_opcode());
1401  ASSERT_EQ(1U, s[0]->OutputCount());
1402  EXPECT_EQ(kArmVcvtF64S32, s[1]->arch_opcode());
1403  ASSERT_EQ(1U, s[1]->OutputCount());
1404  EXPECT_EQ(kArmVdivF64, s[2]->arch_opcode());
1405  ASSERT_EQ(2U, s[2]->InputCount());
1406  ASSERT_EQ(1U, s[2]->OutputCount());
1407  EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[2]->InputAt(0)));
1408  EXPECT_EQ(s.ToVreg(s[1]->Output()), s.ToVreg(s[2]->InputAt(1)));
1409  EXPECT_EQ(kArmVcvtS32F64, s[3]->arch_opcode());
1410  ASSERT_EQ(1U, s[3]->InputCount());
1411  EXPECT_EQ(s.ToVreg(s[2]->Output()), s.ToVreg(s[3]->InputAt(0)));
1412 }
1413 
1414 
1415 TEST_F(InstructionSelectorTest, Int32DivWithParametersForSUDIV) {
1416  StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
1417  m.Return(m.Int32Div(m.Parameter(0), m.Parameter(1)));
1418  Stream s = m.Build(SUDIV);
1419  ASSERT_EQ(1U, s.size());
1420  EXPECT_EQ(kArmSdiv, s[0]->arch_opcode());
1421 }
1422 
1423 
1424 TEST_F(InstructionSelectorTest, Int32ModWithParameters) {
1425  StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
1426  m.Return(m.Int32Mod(m.Parameter(0), m.Parameter(1)));
1427  Stream s = m.Build();
1428  ASSERT_EQ(6U, s.size());
1429  EXPECT_EQ(kArmVcvtF64S32, s[0]->arch_opcode());
1430  ASSERT_EQ(1U, s[0]->OutputCount());
1431  EXPECT_EQ(kArmVcvtF64S32, s[1]->arch_opcode());
1432  ASSERT_EQ(1U, s[1]->OutputCount());
1433  EXPECT_EQ(kArmVdivF64, s[2]->arch_opcode());
1434  ASSERT_EQ(2U, s[2]->InputCount());
1435  ASSERT_EQ(1U, s[2]->OutputCount());
1436  EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[2]->InputAt(0)));
1437  EXPECT_EQ(s.ToVreg(s[1]->Output()), s.ToVreg(s[2]->InputAt(1)));
1438  EXPECT_EQ(kArmVcvtS32F64, s[3]->arch_opcode());
1439  ASSERT_EQ(1U, s[3]->InputCount());
1440  EXPECT_EQ(s.ToVreg(s[2]->Output()), s.ToVreg(s[3]->InputAt(0)));
1441  EXPECT_EQ(kArmMul, s[4]->arch_opcode());
1442  ASSERT_EQ(1U, s[4]->OutputCount());
1443  ASSERT_EQ(2U, s[4]->InputCount());
1444  EXPECT_EQ(s.ToVreg(s[3]->Output()), s.ToVreg(s[4]->InputAt(0)));
1445  EXPECT_EQ(s.ToVreg(s[1]->InputAt(0)), s.ToVreg(s[4]->InputAt(1)));
1446  EXPECT_EQ(kArmSub, s[5]->arch_opcode());
1447  ASSERT_EQ(1U, s[5]->OutputCount());
1448  ASSERT_EQ(2U, s[5]->InputCount());
1449  EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[5]->InputAt(0)));
1450  EXPECT_EQ(s.ToVreg(s[4]->Output()), s.ToVreg(s[5]->InputAt(1)));
1451 }
1452 
1453 
1454 TEST_F(InstructionSelectorTest, Int32ModWithParametersForSUDIV) {
1455  StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
1456  m.Return(m.Int32Mod(m.Parameter(0), m.Parameter(1)));
1457  Stream s = m.Build(SUDIV);
1458  ASSERT_EQ(3U, s.size());
1459  EXPECT_EQ(kArmSdiv, s[0]->arch_opcode());
1460  ASSERT_EQ(1U, s[0]->OutputCount());
1461  ASSERT_EQ(2U, s[0]->InputCount());
1462  EXPECT_EQ(kArmMul, s[1]->arch_opcode());
1463  ASSERT_EQ(1U, s[1]->OutputCount());
1464  ASSERT_EQ(2U, s[1]->InputCount());
1465  EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(0)));
1466  EXPECT_EQ(s.ToVreg(s[0]->InputAt(1)), s.ToVreg(s[1]->InputAt(1)));
1467  EXPECT_EQ(kArmSub, s[2]->arch_opcode());
1468  ASSERT_EQ(1U, s[2]->OutputCount());
1469  ASSERT_EQ(2U, s[2]->InputCount());
1470  EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[2]->InputAt(0)));
1471  EXPECT_EQ(s.ToVreg(s[1]->Output()), s.ToVreg(s[2]->InputAt(1)));
1472 }
1473 
1474 
1475 TEST_F(InstructionSelectorTest, Int32ModWithParametersForSUDIVAndMLS) {
1476  StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
1477  m.Return(m.Int32Mod(m.Parameter(0), m.Parameter(1)));
1478  Stream s = m.Build(MLS, SUDIV);
1479  ASSERT_EQ(2U, s.size());
1480  EXPECT_EQ(kArmSdiv, s[0]->arch_opcode());
1481  ASSERT_EQ(1U, s[0]->OutputCount());
1482  ASSERT_EQ(2U, s[0]->InputCount());
1483  EXPECT_EQ(kArmMls, s[1]->arch_opcode());
1484  ASSERT_EQ(1U, s[1]->OutputCount());
1485  ASSERT_EQ(3U, s[1]->InputCount());
1486  EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(0)));
1487  EXPECT_EQ(s.ToVreg(s[0]->InputAt(1)), s.ToVreg(s[1]->InputAt(1)));
1488  EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[1]->InputAt(2)));
1489 }
1490 
1491 
1492 TEST_F(InstructionSelectorTest, Int32MulWithParameters) {
1493  StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
1494  m.Return(m.Int32Mul(m.Parameter(0), m.Parameter(1)));
1495  Stream s = m.Build();
1496  ASSERT_EQ(1U, s.size());
1497  EXPECT_EQ(kArmMul, s[0]->arch_opcode());
1498  EXPECT_EQ(2U, s[0]->InputCount());
1499  EXPECT_EQ(1U, s[0]->OutputCount());
1500 }
1501 
1502 
1503 TEST_F(InstructionSelectorTest, Int32MulWithImmediate) {
1504  // x * (2^k + 1) -> x + (x >> k)
1505  TRACED_FORRANGE(int32_t, k, 1, 30) {
1506  StreamBuilder m(this, kMachInt32, kMachInt32);
1507  m.Return(m.Int32Mul(m.Parameter(0), m.Int32Constant((1 << k) + 1)));
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.Parameter(0), m.Int32Constant((1 << k) - 1)));
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  // (2^k + 1) * x -> x + (x >> k)
1531  TRACED_FORRANGE(int32_t, k, 1, 30) {
1532  StreamBuilder m(this, kMachInt32, kMachInt32);
1533  m.Return(m.Int32Mul(m.Int32Constant((1 << k) + 1), m.Parameter(0)));
1534  Stream s = m.Build();
1535  ASSERT_EQ(1U, s.size());
1536  EXPECT_EQ(kArmAdd, s[0]->arch_opcode());
1537  EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
1538  ASSERT_EQ(3U, s[0]->InputCount());
1539  EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
1540  EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2)));
1541  EXPECT_EQ(1U, s[0]->OutputCount());
1542  }
1543  // x * (2^k - 1) -> -x + (x >> k)
1544  TRACED_FORRANGE(int32_t, k, 3, 30) {
1545  StreamBuilder m(this, kMachInt32, kMachInt32);
1546  m.Return(m.Int32Mul(m.Int32Constant((1 << k) - 1), m.Parameter(0)));
1547  Stream s = m.Build();
1548  ASSERT_EQ(1U, s.size());
1549  EXPECT_EQ(kArmRsb, s[0]->arch_opcode());
1550  EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
1551  ASSERT_EQ(3U, s[0]->InputCount());
1552  EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
1553  EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2)));
1554  EXPECT_EQ(1U, s[0]->OutputCount());
1555  }
1556 }
1557 
1558 
1559 TEST_F(InstructionSelectorTest, Int32SubWithInt32Mul) {
1560  StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32, kMachInt32);
1561  m.Return(
1562  m.Int32Sub(m.Parameter(0), m.Int32Mul(m.Parameter(1), m.Parameter(2))));
1563  Stream s = m.Build();
1564  ASSERT_EQ(2U, s.size());
1565  EXPECT_EQ(kArmMul, s[0]->arch_opcode());
1566  ASSERT_EQ(1U, s[0]->OutputCount());
1567  EXPECT_EQ(kArmSub, s[1]->arch_opcode());
1568  ASSERT_EQ(2U, s[1]->InputCount());
1569  EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(1)));
1570 }
1571 
1572 
1573 TEST_F(InstructionSelectorTest, Int32SubWithInt32MulForMLS) {
1574  StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32, kMachInt32);
1575  m.Return(
1576  m.Int32Sub(m.Parameter(0), m.Int32Mul(m.Parameter(1), m.Parameter(2))));
1577  Stream s = m.Build(MLS);
1578  ASSERT_EQ(1U, s.size());
1579  EXPECT_EQ(kArmMls, s[0]->arch_opcode());
1580  EXPECT_EQ(1U, s[0]->OutputCount());
1581  EXPECT_EQ(3U, s[0]->InputCount());
1582 }
1583 
1584 
1585 TEST_F(InstructionSelectorTest, Int32UDivWithParameters) {
1586  StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
1587  m.Return(m.Int32UDiv(m.Parameter(0), m.Parameter(1)));
1588  Stream s = m.Build();
1589  ASSERT_EQ(4U, s.size());
1590  EXPECT_EQ(kArmVcvtF64U32, s[0]->arch_opcode());
1591  ASSERT_EQ(1U, s[0]->OutputCount());
1592  EXPECT_EQ(kArmVcvtF64U32, s[1]->arch_opcode());
1593  ASSERT_EQ(1U, s[1]->OutputCount());
1594  EXPECT_EQ(kArmVdivF64, s[2]->arch_opcode());
1595  ASSERT_EQ(2U, s[2]->InputCount());
1596  ASSERT_EQ(1U, s[2]->OutputCount());
1597  EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[2]->InputAt(0)));
1598  EXPECT_EQ(s.ToVreg(s[1]->Output()), s.ToVreg(s[2]->InputAt(1)));
1599  EXPECT_EQ(kArmVcvtU32F64, s[3]->arch_opcode());
1600  ASSERT_EQ(1U, s[3]->InputCount());
1601  EXPECT_EQ(s.ToVreg(s[2]->Output()), s.ToVreg(s[3]->InputAt(0)));
1602 }
1603 
1604 
1605 TEST_F(InstructionSelectorTest, Int32UDivWithParametersForSUDIV) {
1606  StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
1607  m.Return(m.Int32UDiv(m.Parameter(0), m.Parameter(1)));
1608  Stream s = m.Build(SUDIV);
1609  ASSERT_EQ(1U, s.size());
1610  EXPECT_EQ(kArmUdiv, s[0]->arch_opcode());
1611 }
1612 
1613 
1614 TEST_F(InstructionSelectorTest, Int32UModWithParameters) {
1615  StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
1616  m.Return(m.Int32UMod(m.Parameter(0), m.Parameter(1)));
1617  Stream s = m.Build();
1618  ASSERT_EQ(6U, s.size());
1619  EXPECT_EQ(kArmVcvtF64U32, s[0]->arch_opcode());
1620  ASSERT_EQ(1U, s[0]->OutputCount());
1621  EXPECT_EQ(kArmVcvtF64U32, s[1]->arch_opcode());
1622  ASSERT_EQ(1U, s[1]->OutputCount());
1623  EXPECT_EQ(kArmVdivF64, s[2]->arch_opcode());
1624  ASSERT_EQ(2U, s[2]->InputCount());
1625  ASSERT_EQ(1U, s[2]->OutputCount());
1626  EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[2]->InputAt(0)));
1627  EXPECT_EQ(s.ToVreg(s[1]->Output()), s.ToVreg(s[2]->InputAt(1)));
1628  EXPECT_EQ(kArmVcvtU32F64, s[3]->arch_opcode());
1629  ASSERT_EQ(1U, s[3]->InputCount());
1630  EXPECT_EQ(s.ToVreg(s[2]->Output()), s.ToVreg(s[3]->InputAt(0)));
1631  EXPECT_EQ(kArmMul, s[4]->arch_opcode());
1632  ASSERT_EQ(1U, s[4]->OutputCount());
1633  ASSERT_EQ(2U, s[4]->InputCount());
1634  EXPECT_EQ(s.ToVreg(s[3]->Output()), s.ToVreg(s[4]->InputAt(0)));
1635  EXPECT_EQ(s.ToVreg(s[1]->InputAt(0)), s.ToVreg(s[4]->InputAt(1)));
1636  EXPECT_EQ(kArmSub, s[5]->arch_opcode());
1637  ASSERT_EQ(1U, s[5]->OutputCount());
1638  ASSERT_EQ(2U, s[5]->InputCount());
1639  EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[5]->InputAt(0)));
1640  EXPECT_EQ(s.ToVreg(s[4]->Output()), s.ToVreg(s[5]->InputAt(1)));
1641 }
1642 
1643 
1644 TEST_F(InstructionSelectorTest, Int32UModWithParametersForSUDIV) {
1645  StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
1646  m.Return(m.Int32UMod(m.Parameter(0), m.Parameter(1)));
1647  Stream s = m.Build(SUDIV);
1648  ASSERT_EQ(3U, s.size());
1649  EXPECT_EQ(kArmUdiv, s[0]->arch_opcode());
1650  ASSERT_EQ(1U, s[0]->OutputCount());
1651  ASSERT_EQ(2U, s[0]->InputCount());
1652  EXPECT_EQ(kArmMul, s[1]->arch_opcode());
1653  ASSERT_EQ(1U, s[1]->OutputCount());
1654  ASSERT_EQ(2U, s[1]->InputCount());
1655  EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(0)));
1656  EXPECT_EQ(s.ToVreg(s[0]->InputAt(1)), s.ToVreg(s[1]->InputAt(1)));
1657  EXPECT_EQ(kArmSub, s[2]->arch_opcode());
1658  ASSERT_EQ(1U, s[2]->OutputCount());
1659  ASSERT_EQ(2U, s[2]->InputCount());
1660  EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[2]->InputAt(0)));
1661  EXPECT_EQ(s.ToVreg(s[1]->Output()), s.ToVreg(s[2]->InputAt(1)));
1662 }
1663 
1664 
1665 TEST_F(InstructionSelectorTest, Int32UModWithParametersForSUDIVAndMLS) {
1666  StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
1667  m.Return(m.Int32UMod(m.Parameter(0), m.Parameter(1)));
1668  Stream s = m.Build(MLS, SUDIV);
1669  ASSERT_EQ(2U, s.size());
1670  EXPECT_EQ(kArmUdiv, s[0]->arch_opcode());
1671  ASSERT_EQ(1U, s[0]->OutputCount());
1672  ASSERT_EQ(2U, s[0]->InputCount());
1673  EXPECT_EQ(kArmMls, s[1]->arch_opcode());
1674  ASSERT_EQ(1U, s[1]->OutputCount());
1675  ASSERT_EQ(3U, s[1]->InputCount());
1676  EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(0)));
1677  EXPECT_EQ(s.ToVreg(s[0]->InputAt(1)), s.ToVreg(s[1]->InputAt(1)));
1678  EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[1]->InputAt(2)));
1679 }
1680 
1681 
1682 TEST_F(InstructionSelectorTest, Word32AndWithUbfxImmediateForARMv7) {
1683  TRACED_FORRANGE(int32_t, width, 1, 32) {
1684  StreamBuilder m(this, kMachInt32, kMachInt32);
1685  m.Return(m.Word32And(m.Parameter(0),
1686  m.Int32Constant(0xffffffffu >> (32 - width))));
1687  Stream s = m.Build(ARMv7);
1688  ASSERT_EQ(1U, s.size());
1689  EXPECT_EQ(kArmUbfx, s[0]->arch_opcode());
1690  ASSERT_EQ(3U, s[0]->InputCount());
1691  EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1)));
1692  EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
1693  }
1694  TRACED_FORRANGE(int32_t, width, 1, 32) {
1695  StreamBuilder m(this, kMachInt32, kMachInt32);
1696  m.Return(m.Word32And(m.Int32Constant(0xffffffffu >> (32 - width)),
1697  m.Parameter(0)));
1698  Stream s = m.Build(ARMv7);
1699  ASSERT_EQ(1U, s.size());
1700  EXPECT_EQ(kArmUbfx, s[0]->arch_opcode());
1701  ASSERT_EQ(3U, s[0]->InputCount());
1702  EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1)));
1703  EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
1704  }
1705 }
1706 
1707 
1708 TEST_F(InstructionSelectorTest, Word32AndWithBfcImmediateForARMv7) {
1709  TRACED_FORRANGE(int32_t, lsb, 0, 31) {
1710  TRACED_FORRANGE(int32_t, width, 1, (32 - lsb) - 1) {
1711  StreamBuilder m(this, kMachInt32, kMachInt32);
1712  m.Return(m.Word32And(
1713  m.Parameter(0),
1714  m.Int32Constant(~((0xffffffffu >> (32 - width)) << lsb))));
1715  Stream s = m.Build(ARMv7);
1716  ASSERT_EQ(1U, s.size());
1717  EXPECT_EQ(kArmBfc, s[0]->arch_opcode());
1718  ASSERT_EQ(1U, s[0]->OutputCount());
1719  EXPECT_TRUE(
1720  UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy());
1721  ASSERT_EQ(3U, s[0]->InputCount());
1722  EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
1723  EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
1724  }
1725  }
1726  TRACED_FORRANGE(int32_t, lsb, 0, 31) {
1727  TRACED_FORRANGE(int32_t, width, 1, (32 - lsb) - 1) {
1728  StreamBuilder m(this, kMachInt32, kMachInt32);
1729  m.Return(
1730  m.Word32And(m.Int32Constant(~((0xffffffffu >> (32 - width)) << lsb)),
1731  m.Parameter(0)));
1732  Stream s = m.Build(ARMv7);
1733  ASSERT_EQ(1U, s.size());
1734  EXPECT_EQ(kArmBfc, s[0]->arch_opcode());
1735  ASSERT_EQ(1U, s[0]->OutputCount());
1736  EXPECT_TRUE(
1737  UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy());
1738  ASSERT_EQ(3U, s[0]->InputCount());
1739  EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
1740  EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
1741  }
1742  }
1743 }
1744 
1745 
1746 TEST_F(InstructionSelectorTest, Word32ShrWithWord32AndWithImmediateForARMv7) {
1747  TRACED_FORRANGE(int32_t, lsb, 0, 31) {
1748  TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) {
1749  uint32_t max = 1 << lsb;
1750  if (max > static_cast<uint32_t>(kMaxInt)) max -= 1;
1751  uint32_t jnk = rng()->NextInt(max);
1752  uint32_t msk = ((0xffffffffu >> (32 - width)) << lsb) | jnk;
1753  StreamBuilder m(this, kMachInt32, kMachInt32);
1754  m.Return(m.Word32Shr(m.Word32And(m.Parameter(0), m.Int32Constant(msk)),
1755  m.Int32Constant(lsb)));
1756  Stream s = m.Build(ARMv7);
1757  ASSERT_EQ(1U, s.size());
1758  EXPECT_EQ(kArmUbfx, s[0]->arch_opcode());
1759  ASSERT_EQ(3U, s[0]->InputCount());
1760  EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
1761  EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
1762  }
1763  }
1764  TRACED_FORRANGE(int32_t, lsb, 0, 31) {
1765  TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) {
1766  uint32_t max = 1 << lsb;
1767  if (max > static_cast<uint32_t>(kMaxInt)) max -= 1;
1768  uint32_t jnk = rng()->NextInt(max);
1769  uint32_t msk = ((0xffffffffu >> (32 - width)) << lsb) | jnk;
1770  StreamBuilder m(this, kMachInt32, kMachInt32);
1771  m.Return(m.Word32Shr(m.Word32And(m.Int32Constant(msk), m.Parameter(0)),
1772  m.Int32Constant(lsb)));
1773  Stream s = m.Build(ARMv7);
1774  ASSERT_EQ(1U, s.size());
1775  EXPECT_EQ(kArmUbfx, s[0]->arch_opcode());
1776  ASSERT_EQ(3U, s[0]->InputCount());
1777  EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
1778  EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
1779  }
1780  }
1781 }
1782 
1783 
1784 TEST_F(InstructionSelectorTest, Word32AndWithWord32Not) {
1785  {
1786  StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
1787  m.Return(m.Word32And(m.Parameter(0), m.Word32Not(m.Parameter(1))));
1788  Stream s = m.Build();
1789  ASSERT_EQ(1U, s.size());
1790  EXPECT_EQ(kArmBic, s[0]->arch_opcode());
1791  EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
1792  EXPECT_EQ(2U, s[0]->InputCount());
1793  EXPECT_EQ(1U, s[0]->OutputCount());
1794  }
1795  {
1796  StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
1797  m.Return(m.Word32And(m.Word32Not(m.Parameter(0)), m.Parameter(1)));
1798  Stream s = m.Build();
1799  ASSERT_EQ(1U, s.size());
1800  EXPECT_EQ(kArmBic, s[0]->arch_opcode());
1801  EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
1802  EXPECT_EQ(2U, s[0]->InputCount());
1803  EXPECT_EQ(1U, s[0]->OutputCount());
1804  }
1805 }
1806 
1807 
1808 TEST_F(InstructionSelectorTest, Word32EqualWithParameters) {
1809  StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
1810  m.Return(m.Word32Equal(m.Parameter(0), m.Parameter(1)));
1811  Stream s = m.Build();
1812  ASSERT_EQ(1U, s.size());
1813  EXPECT_EQ(kArmCmp, s[0]->arch_opcode());
1814  EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
1815  EXPECT_EQ(2U, s[0]->InputCount());
1816  EXPECT_EQ(1U, s[0]->OutputCount());
1817  EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1818  EXPECT_EQ(kEqual, s[0]->flags_condition());
1819 }
1820 
1821 
1822 TEST_F(InstructionSelectorTest, Word32EqualWithImmediate) {
1823  TRACED_FOREACH(int32_t, imm, kImmediates) {
1824  if (imm == 0) continue;
1825  StreamBuilder m(this, kMachInt32, kMachInt32);
1826  m.Return(m.Word32Equal(m.Parameter(0), m.Int32Constant(imm)));
1827  Stream s = m.Build();
1828  ASSERT_EQ(1U, s.size());
1829  EXPECT_EQ(kArmCmp, s[0]->arch_opcode());
1830  EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode());
1831  ASSERT_EQ(2U, s[0]->InputCount());
1832  EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
1833  EXPECT_EQ(1U, s[0]->OutputCount());
1834  EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1835  EXPECT_EQ(kEqual, s[0]->flags_condition());
1836  }
1837  TRACED_FOREACH(int32_t, imm, kImmediates) {
1838  if (imm == 0) continue;
1839  StreamBuilder m(this, kMachInt32, kMachInt32);
1840  m.Return(m.Word32Equal(m.Int32Constant(imm), m.Parameter(0)));
1841  Stream s = m.Build();
1842  ASSERT_EQ(1U, s.size());
1843  EXPECT_EQ(kArmCmp, s[0]->arch_opcode());
1844  EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode());
1845  ASSERT_EQ(2U, s[0]->InputCount());
1846  EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
1847  EXPECT_EQ(1U, s[0]->OutputCount());
1848  EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1849  EXPECT_EQ(kEqual, s[0]->flags_condition());
1850  }
1851 }
1852 
1853 
1854 TEST_F(InstructionSelectorTest, Word32EqualWithZero) {
1855  {
1856  StreamBuilder m(this, kMachInt32, kMachInt32);
1857  m.Return(m.Word32Equal(m.Parameter(0), m.Int32Constant(0)));
1858  Stream s = m.Build();
1859  ASSERT_EQ(1U, s.size());
1860  EXPECT_EQ(kArmTst, s[0]->arch_opcode());
1861  EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
1862  ASSERT_EQ(2U, s[0]->InputCount());
1863  EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
1864  EXPECT_EQ(1U, s[0]->OutputCount());
1865  EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1866  EXPECT_EQ(kEqual, s[0]->flags_condition());
1867  }
1868  {
1869  StreamBuilder m(this, kMachInt32, kMachInt32);
1870  m.Return(m.Word32Equal(m.Int32Constant(0), m.Parameter(0)));
1871  Stream s = m.Build();
1872  ASSERT_EQ(1U, s.size());
1873  EXPECT_EQ(kArmTst, s[0]->arch_opcode());
1874  EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
1875  ASSERT_EQ(2U, s[0]->InputCount());
1876  EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
1877  EXPECT_EQ(1U, s[0]->OutputCount());
1878  EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1879  EXPECT_EQ(kEqual, s[0]->flags_condition());
1880  }
1881 }
1882 
1883 
1884 TEST_F(InstructionSelectorTest, Word32NotWithParameter) {
1885  StreamBuilder m(this, kMachInt32, kMachInt32);
1886  m.Return(m.Word32Not(m.Parameter(0)));
1887  Stream s = m.Build();
1888  ASSERT_EQ(1U, s.size());
1889  EXPECT_EQ(kArmMvn, s[0]->arch_opcode());
1890  EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
1891  EXPECT_EQ(1U, s[0]->InputCount());
1892  EXPECT_EQ(1U, s[0]->OutputCount());
1893 }
1894 
1895 
1896 TEST_F(InstructionSelectorTest, Word32AndWithWord32ShrWithImmediateForARMv7) {
1897  TRACED_FORRANGE(int32_t, lsb, 0, 31) {
1898  TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) {
1899  StreamBuilder m(this, kMachInt32, kMachInt32);
1900  m.Return(m.Word32And(m.Word32Shr(m.Parameter(0), m.Int32Constant(lsb)),
1901  m.Int32Constant(0xffffffffu >> (32 - width))));
1902  Stream s = m.Build(ARMv7);
1903  ASSERT_EQ(1U, s.size());
1904  EXPECT_EQ(kArmUbfx, s[0]->arch_opcode());
1905  ASSERT_EQ(3U, s[0]->InputCount());
1906  EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
1907  EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
1908  }
1909  }
1910  TRACED_FORRANGE(int32_t, lsb, 0, 31) {
1911  TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) {
1912  StreamBuilder m(this, kMachInt32, kMachInt32);
1913  m.Return(m.Word32And(m.Int32Constant(0xffffffffu >> (32 - width)),
1914  m.Word32Shr(m.Parameter(0), m.Int32Constant(lsb))));
1915  Stream s = m.Build(ARMv7);
1916  ASSERT_EQ(1U, s.size());
1917  EXPECT_EQ(kArmUbfx, s[0]->arch_opcode());
1918  ASSERT_EQ(3U, s[0]->InputCount());
1919  EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
1920  EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
1921  }
1922  }
1923 }
1924 
1925 } // namespace compiler
1926 } // namespace internal
1927 } // namespace v8
const char * c_str() const
Definition: ostreams.h:84
static const UnallocatedOperand * cast(const InstructionOperand *op)
Definition: instruction.h:160
enable harmony numeric enable harmony object literal extensions Optimize object Array shift
int int32_t
Definition: unicode.cc:24
InstructionSelectorTestWithParam< Shift > InstructionSelectorShiftTest
InstructionSelectorTestWithParam< DPI > InstructionSelectorDPITest
std::ostream & operator<<(std::ostream &os, const MachineType &type)
static const MemoryAccess kMemoryAccesses[]
TEST_P(InstructionSelectorDPITest, Parameters)
InstructionSelectorTestWithParam< MemoryAccess > InstructionSelectorMemoryAccessTest
INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorDPITest, ::testing::ValuesIn(kDPIs))
TEST_F(InstructionSelectorTest, ChangeFloat32ToFloat64WithParameter)
InstructionSelectorTestWithParam< ODPI > InstructionSelectorODPITest
const int kMaxInt
Definition: globals.h:109
Debugger support for the V8 JavaScript engine.
Definition: accessors.cc:20