deps: update v8 to 4.3.61.21
[platform/upstream/nodejs.git] / deps / v8 / test / unittests / compiler / ia32 / instruction-selector-ia32-unittest.cc
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 "test/unittests/compiler/instruction-selector-unittest.h"
6
7 namespace v8 {
8 namespace internal {
9 namespace compiler {
10
11 namespace {
12
13 // Immediates (random subset).
14 const int32_t kImmediates[] = {kMinInt, -42, -1,   0,      1,          2,
15                                3,       4,   5,    6,      7,          8,
16                                16,      42,  0xff, 0xffff, 0x0f0f0f0f, kMaxInt};
17
18 }  // namespace
19
20
21 TEST_F(InstructionSelectorTest, Int32AddWithParameter) {
22   StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
23   m.Return(m.Int32Add(m.Parameter(0), m.Parameter(1)));
24   Stream s = m.Build();
25   ASSERT_EQ(1U, s.size());
26   EXPECT_EQ(kIA32Lea, s[0]->arch_opcode());
27 }
28
29
30 TEST_F(InstructionSelectorTest, Int32AddWithImmediate) {
31   TRACED_FOREACH(int32_t, imm, kImmediates) {
32     {
33       StreamBuilder m(this, kMachInt32, kMachInt32);
34       m.Return(m.Int32Add(m.Parameter(0), m.Int32Constant(imm)));
35       Stream s = m.Build();
36       ASSERT_EQ(1U, s.size());
37       EXPECT_EQ(kIA32Lea, s[0]->arch_opcode());
38       if (imm == 0) {
39         ASSERT_EQ(1U, s[0]->InputCount());
40       } else {
41         ASSERT_EQ(2U, s[0]->InputCount());
42         EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
43       }
44     }
45     {
46       StreamBuilder m(this, kMachInt32, kMachInt32);
47       m.Return(m.Int32Add(m.Int32Constant(imm), m.Parameter(0)));
48       Stream s = m.Build();
49       ASSERT_EQ(1U, s.size());
50       EXPECT_EQ(kIA32Lea, s[0]->arch_opcode());
51       if (imm == 0) {
52         ASSERT_EQ(1U, s[0]->InputCount());
53       } else {
54         ASSERT_EQ(2U, s[0]->InputCount());
55         EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
56       }
57     }
58   }
59 }
60
61
62 TEST_F(InstructionSelectorTest, Int32SubWithParameter) {
63   StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
64   m.Return(m.Int32Sub(m.Parameter(0), m.Parameter(1)));
65   Stream s = m.Build();
66   ASSERT_EQ(1U, s.size());
67   EXPECT_EQ(kIA32Sub, s[0]->arch_opcode());
68   EXPECT_EQ(1U, s[0]->OutputCount());
69 }
70
71
72 TEST_F(InstructionSelectorTest, Int32SubWithImmediate) {
73   TRACED_FOREACH(int32_t, imm, kImmediates) {
74     StreamBuilder m(this, kMachInt32, kMachInt32);
75     m.Return(m.Int32Sub(m.Parameter(0), m.Int32Constant(imm)));
76     Stream s = m.Build();
77     ASSERT_EQ(1U, s.size());
78     EXPECT_EQ(kIA32Sub, s[0]->arch_opcode());
79     ASSERT_EQ(2U, s[0]->InputCount());
80     EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
81   }
82 }
83
84
85 // -----------------------------------------------------------------------------
86 // Conversions.
87
88
89 TEST_F(InstructionSelectorTest, ChangeFloat32ToFloat64WithParameter) {
90   StreamBuilder m(this, kMachFloat32, kMachFloat64);
91   m.Return(m.ChangeFloat32ToFloat64(m.Parameter(0)));
92   Stream s = m.Build();
93   ASSERT_EQ(1U, s.size());
94   EXPECT_EQ(kSSECvtss2sd, s[0]->arch_opcode());
95   EXPECT_EQ(1U, s[0]->InputCount());
96   EXPECT_EQ(1U, s[0]->OutputCount());
97 }
98
99
100 TEST_F(InstructionSelectorTest, TruncateFloat64ToFloat32WithParameter) {
101   StreamBuilder m(this, kMachFloat64, kMachFloat32);
102   m.Return(m.TruncateFloat64ToFloat32(m.Parameter(0)));
103   Stream s = m.Build();
104   ASSERT_EQ(1U, s.size());
105   EXPECT_EQ(kSSECvtsd2ss, s[0]->arch_opcode());
106   EXPECT_EQ(1U, s[0]->InputCount());
107   EXPECT_EQ(1U, s[0]->OutputCount());
108 }
109
110
111 // -----------------------------------------------------------------------------
112 // Better left operand for commutative binops
113
114
115 TEST_F(InstructionSelectorTest, BetterLeftOperandTestAddBinop) {
116   StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
117   Node* param1 = m.Parameter(0);
118   Node* param2 = m.Parameter(1);
119   Node* add = m.Int32Add(param1, param2);
120   m.Return(m.Int32Add(add, param1));
121   Stream s = m.Build();
122   ASSERT_EQ(2U, s.size());
123   EXPECT_EQ(kIA32Lea, s[0]->arch_opcode());
124   ASSERT_EQ(2U, s[0]->InputCount());
125   ASSERT_TRUE(s[0]->InputAt(0)->IsUnallocated());
126   EXPECT_EQ(s.ToVreg(param1), s.ToVreg(s[0]->InputAt(0)));
127   EXPECT_EQ(s.ToVreg(param2), s.ToVreg(s[0]->InputAt(1)));
128   ASSERT_EQ(2U, s[1]->InputCount());
129   EXPECT_EQ(s.ToVreg(param1), s.ToVreg(s[0]->InputAt(0)));
130 }
131
132
133 TEST_F(InstructionSelectorTest, BetterLeftOperandTestMulBinop) {
134   StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
135   Node* param1 = m.Parameter(0);
136   Node* param2 = m.Parameter(1);
137   Node* mul = m.Int32Mul(param1, param2);
138   m.Return(m.Int32Mul(mul, param1));
139   Stream s = m.Build();
140   ASSERT_EQ(2U, s.size());
141   EXPECT_EQ(kIA32Imul, s[0]->arch_opcode());
142   ASSERT_EQ(2U, s[0]->InputCount());
143   ASSERT_TRUE(s[0]->InputAt(0)->IsUnallocated());
144   EXPECT_EQ(s.ToVreg(param2), s.ToVreg(s[0]->InputAt(0)));
145   EXPECT_EQ(s.ToVreg(param1), s.ToVreg(s[0]->InputAt(1)));
146 }
147
148
149 // -----------------------------------------------------------------------------
150 // Conversions.
151
152
153 TEST_F(InstructionSelectorTest, ChangeUint32ToFloat64WithParameter) {
154   StreamBuilder m(this, kMachFloat64, kMachUint32);
155   m.Return(m.ChangeUint32ToFloat64(m.Parameter(0)));
156   Stream s = m.Build();
157   ASSERT_EQ(1U, s.size());
158   EXPECT_EQ(kSSEUint32ToFloat64, s[0]->arch_opcode());
159 }
160
161
162 // -----------------------------------------------------------------------------
163 // Loads and stores
164
165
166 namespace {
167
168 struct MemoryAccess {
169   MachineType type;
170   ArchOpcode load_opcode;
171   ArchOpcode store_opcode;
172 };
173
174
175 std::ostream& operator<<(std::ostream& os, const MemoryAccess& memacc) {
176   return os << memacc.type;
177 }
178
179
180 static const MemoryAccess kMemoryAccesses[] = {
181     {kMachInt8, kIA32Movsxbl, kIA32Movb},
182     {kMachUint8, kIA32Movzxbl, kIA32Movb},
183     {kMachInt16, kIA32Movsxwl, kIA32Movw},
184     {kMachUint16, kIA32Movzxwl, kIA32Movw},
185     {kMachInt32, kIA32Movl, kIA32Movl},
186     {kMachUint32, kIA32Movl, kIA32Movl},
187     {kMachFloat32, kIA32Movss, kIA32Movss},
188     {kMachFloat64, kIA32Movsd, kIA32Movsd}};
189
190 }  // namespace
191
192
193 typedef InstructionSelectorTestWithParam<MemoryAccess>
194     InstructionSelectorMemoryAccessTest;
195
196
197 TEST_P(InstructionSelectorMemoryAccessTest, LoadWithParameters) {
198   const MemoryAccess memacc = GetParam();
199   StreamBuilder m(this, memacc.type, kMachPtr, kMachInt32);
200   m.Return(m.Load(memacc.type, m.Parameter(0), m.Parameter(1)));
201   Stream s = m.Build();
202   ASSERT_EQ(1U, s.size());
203   EXPECT_EQ(memacc.load_opcode, s[0]->arch_opcode());
204   EXPECT_EQ(2U, s[0]->InputCount());
205   EXPECT_EQ(1U, s[0]->OutputCount());
206 }
207
208
209 TEST_P(InstructionSelectorMemoryAccessTest, LoadWithImmediateBase) {
210   const MemoryAccess memacc = GetParam();
211   TRACED_FOREACH(int32_t, base, kImmediates) {
212     StreamBuilder m(this, memacc.type, kMachPtr);
213     m.Return(m.Load(memacc.type, m.Int32Constant(base), m.Parameter(0)));
214     Stream s = m.Build();
215     ASSERT_EQ(1U, s.size());
216     EXPECT_EQ(memacc.load_opcode, s[0]->arch_opcode());
217     if (base == 0) {
218       ASSERT_EQ(1U, s[0]->InputCount());
219     } else {
220       ASSERT_EQ(2U, s[0]->InputCount());
221       ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
222       EXPECT_EQ(base, s.ToInt32(s[0]->InputAt(1)));
223     }
224     EXPECT_EQ(1U, s[0]->OutputCount());
225   }
226 }
227
228
229 TEST_P(InstructionSelectorMemoryAccessTest, LoadWithImmediateIndex) {
230   const MemoryAccess memacc = GetParam();
231   TRACED_FOREACH(int32_t, index, kImmediates) {
232     StreamBuilder m(this, memacc.type, kMachPtr);
233     m.Return(m.Load(memacc.type, m.Parameter(0), m.Int32Constant(index)));
234     Stream s = m.Build();
235     ASSERT_EQ(1U, s.size());
236     EXPECT_EQ(memacc.load_opcode, s[0]->arch_opcode());
237     if (index == 0) {
238       ASSERT_EQ(1U, s[0]->InputCount());
239     } else {
240       ASSERT_EQ(2U, s[0]->InputCount());
241       ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
242       EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1)));
243     }
244     EXPECT_EQ(1U, s[0]->OutputCount());
245   }
246 }
247
248
249 TEST_P(InstructionSelectorMemoryAccessTest, StoreWithParameters) {
250   const MemoryAccess memacc = GetParam();
251   StreamBuilder m(this, kMachInt32, kMachPtr, kMachInt32, memacc.type);
252   m.Store(memacc.type, m.Parameter(0), m.Parameter(1), m.Parameter(2));
253   m.Return(m.Int32Constant(0));
254   Stream s = m.Build();
255   ASSERT_EQ(1U, s.size());
256   EXPECT_EQ(memacc.store_opcode, s[0]->arch_opcode());
257   EXPECT_EQ(3U, s[0]->InputCount());
258   EXPECT_EQ(0U, s[0]->OutputCount());
259 }
260
261
262 TEST_P(InstructionSelectorMemoryAccessTest, StoreWithImmediateBase) {
263   const MemoryAccess memacc = GetParam();
264   TRACED_FOREACH(int32_t, base, kImmediates) {
265     StreamBuilder m(this, kMachInt32, kMachInt32, memacc.type);
266     m.Store(memacc.type, m.Int32Constant(base), m.Parameter(0), m.Parameter(1));
267     m.Return(m.Int32Constant(0));
268     Stream s = m.Build();
269     ASSERT_EQ(1U, s.size());
270     EXPECT_EQ(memacc.store_opcode, s[0]->arch_opcode());
271     if (base == 0) {
272       ASSERT_EQ(2U, s[0]->InputCount());
273     } else {
274       ASSERT_EQ(3U, s[0]->InputCount());
275       ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
276       EXPECT_EQ(base, s.ToInt32(s[0]->InputAt(1)));
277     }
278     EXPECT_EQ(0U, s[0]->OutputCount());
279   }
280 }
281
282
283 TEST_P(InstructionSelectorMemoryAccessTest, StoreWithImmediateIndex) {
284   const MemoryAccess memacc = GetParam();
285   TRACED_FOREACH(int32_t, index, kImmediates) {
286     StreamBuilder m(this, kMachInt32, kMachPtr, memacc.type);
287     m.Store(memacc.type, m.Parameter(0), m.Int32Constant(index),
288             m.Parameter(1));
289     m.Return(m.Int32Constant(0));
290     Stream s = m.Build();
291     ASSERT_EQ(1U, s.size());
292     EXPECT_EQ(memacc.store_opcode, s[0]->arch_opcode());
293     if (index == 0) {
294       ASSERT_EQ(2U, s[0]->InputCount());
295     } else {
296       ASSERT_EQ(3U, s[0]->InputCount());
297       ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
298       EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1)));
299     }
300     EXPECT_EQ(0U, s[0]->OutputCount());
301   }
302 }
303
304
305 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
306                         InstructionSelectorMemoryAccessTest,
307                         ::testing::ValuesIn(kMemoryAccesses));
308
309
310 // -----------------------------------------------------------------------------
311 // AddressingMode for loads and stores.
312
313
314 class AddressingModeUnitTest : public InstructionSelectorTest {
315  public:
316   AddressingModeUnitTest() : m(NULL) { Reset(); }
317   ~AddressingModeUnitTest() { delete m; }
318
319   void Run(Node* base, Node* load_index, Node* store_index,
320            AddressingMode mode) {
321     Node* load = m->Load(kMachInt32, base, load_index);
322     m->Store(kMachInt32, base, store_index, load);
323     m->Return(m->Int32Constant(0));
324     Stream s = m->Build();
325     ASSERT_EQ(2U, s.size());
326     EXPECT_EQ(mode, s[0]->addressing_mode());
327     EXPECT_EQ(mode, s[1]->addressing_mode());
328   }
329
330   Node* zero;
331   Node* null_ptr;
332   Node* non_zero;
333   Node* base_reg;   // opaque value to generate base as register
334   Node* index_reg;  // opaque value to generate index as register
335   Node* scales[4];
336   StreamBuilder* m;
337
338   void Reset() {
339     delete m;
340     m = new StreamBuilder(this, kMachInt32, kMachInt32, kMachInt32);
341     zero = m->Int32Constant(0);
342     null_ptr = m->Int32Constant(0);
343     non_zero = m->Int32Constant(127);
344     base_reg = m->Parameter(0);
345     index_reg = m->Parameter(0);
346
347     scales[0] = m->Int32Constant(1);
348     scales[1] = m->Int32Constant(2);
349     scales[2] = m->Int32Constant(4);
350     scales[3] = m->Int32Constant(8);
351   }
352 };
353
354
355 TEST_F(AddressingModeUnitTest, AddressingMode_MR) {
356   Node* base = base_reg;
357   Node* index = zero;
358   Run(base, index, index, kMode_MR);
359 }
360
361
362 TEST_F(AddressingModeUnitTest, AddressingMode_MRI) {
363   Node* base = base_reg;
364   Node* index = non_zero;
365   Run(base, index, index, kMode_MRI);
366 }
367
368
369 TEST_F(AddressingModeUnitTest, AddressingMode_MR1) {
370   Node* base = base_reg;
371   Node* index = index_reg;
372   Run(base, index, index, kMode_MR1);
373 }
374
375
376 TEST_F(AddressingModeUnitTest, AddressingMode_MRN) {
377   AddressingMode expected[] = {kMode_MR1, kMode_MR2, kMode_MR4, kMode_MR8};
378   for (size_t i = 0; i < arraysize(scales); ++i) {
379     Reset();
380     Node* base = base_reg;
381     Node* load_index = m->Int32Mul(index_reg, scales[i]);
382     Node* store_index = m->Int32Mul(index_reg, scales[i]);
383     Run(base, load_index, store_index, expected[i]);
384   }
385 }
386
387
388 TEST_F(AddressingModeUnitTest, AddressingMode_MR1I) {
389   Node* base = base_reg;
390   Node* load_index = m->Int32Add(index_reg, non_zero);
391   Node* store_index = m->Int32Add(index_reg, non_zero);
392   Run(base, load_index, store_index, kMode_MR1I);
393 }
394
395
396 TEST_F(AddressingModeUnitTest, AddressingMode_MRNI) {
397   AddressingMode expected[] = {kMode_MR1I, kMode_MR2I, kMode_MR4I, kMode_MR8I};
398   for (size_t i = 0; i < arraysize(scales); ++i) {
399     Reset();
400     Node* base = base_reg;
401     Node* load_index = m->Int32Add(m->Int32Mul(index_reg, scales[i]), non_zero);
402     Node* store_index =
403         m->Int32Add(m->Int32Mul(index_reg, scales[i]), non_zero);
404     Run(base, load_index, store_index, expected[i]);
405   }
406 }
407
408
409 TEST_F(AddressingModeUnitTest, AddressingMode_M1ToMR) {
410   Node* base = null_ptr;
411   Node* index = index_reg;
412   // M1 maps to MR
413   Run(base, index, index, kMode_MR);
414 }
415
416
417 TEST_F(AddressingModeUnitTest, AddressingMode_MN) {
418   AddressingMode expected[] = {kMode_MR, kMode_M2, kMode_M4, kMode_M8};
419   for (size_t i = 0; i < arraysize(scales); ++i) {
420     Reset();
421     Node* base = null_ptr;
422     Node* load_index = m->Int32Mul(index_reg, scales[i]);
423     Node* store_index = m->Int32Mul(index_reg, scales[i]);
424     Run(base, load_index, store_index, expected[i]);
425   }
426 }
427
428
429 TEST_F(AddressingModeUnitTest, AddressingMode_M1IToMRI) {
430   Node* base = null_ptr;
431   Node* load_index = m->Int32Add(index_reg, non_zero);
432   Node* store_index = m->Int32Add(index_reg, non_zero);
433   // M1I maps to MRI
434   Run(base, load_index, store_index, kMode_MRI);
435 }
436
437
438 TEST_F(AddressingModeUnitTest, AddressingMode_MNI) {
439   AddressingMode expected[] = {kMode_MRI, kMode_M2I, kMode_M4I, kMode_M8I};
440   for (size_t i = 0; i < arraysize(scales); ++i) {
441     Reset();
442     Node* base = null_ptr;
443     Node* load_index = m->Int32Add(m->Int32Mul(index_reg, scales[i]), non_zero);
444     Node* store_index =
445         m->Int32Add(m->Int32Mul(index_reg, scales[i]), non_zero);
446     Run(base, load_index, store_index, expected[i]);
447   }
448 }
449
450
451 TEST_F(AddressingModeUnitTest, AddressingMode_MI) {
452   Node* bases[] = {null_ptr, non_zero};
453   Node* indices[] = {zero, non_zero};
454   for (size_t i = 0; i < arraysize(bases); ++i) {
455     for (size_t j = 0; j < arraysize(indices); ++j) {
456       Reset();
457       Node* base = bases[i];
458       Node* index = indices[j];
459       Run(base, index, index, kMode_MI);
460     }
461   }
462 }
463
464
465 // -----------------------------------------------------------------------------
466 // Multiplication.
467
468
469 namespace {
470
471 struct MultParam {
472   int value;
473   bool lea_expected;
474   AddressingMode addressing_mode;
475 };
476
477
478 std::ostream& operator<<(std::ostream& os, const MultParam& m) {
479   return os << m.value << "." << m.lea_expected << "." << m.addressing_mode;
480 }
481
482
483 const MultParam kMultParams[] = {{-1, false, kMode_None},
484                                  {0, false, kMode_None},
485                                  {1, true, kMode_MR},
486                                  {2, true, kMode_M2},
487                                  {3, true, kMode_MR2},
488                                  {4, true, kMode_M4},
489                                  {5, true, kMode_MR4},
490                                  {6, false, kMode_None},
491                                  {7, false, kMode_None},
492                                  {8, true, kMode_M8},
493                                  {9, true, kMode_MR8},
494                                  {10, false, kMode_None},
495                                  {11, false, kMode_None}};
496
497 }  // namespace
498
499
500 typedef InstructionSelectorTestWithParam<MultParam> InstructionSelectorMultTest;
501
502
503 static unsigned InputCountForLea(AddressingMode mode) {
504   switch (mode) {
505     case kMode_MR1I:
506     case kMode_MR2I:
507     case kMode_MR4I:
508     case kMode_MR8I:
509       return 3U;
510     case kMode_M1I:
511     case kMode_M2I:
512     case kMode_M4I:
513     case kMode_M8I:
514       return 2U;
515     case kMode_MR1:
516     case kMode_MR2:
517     case kMode_MR4:
518     case kMode_MR8:
519     case kMode_MRI:
520       return 2U;
521     case kMode_M1:
522     case kMode_M2:
523     case kMode_M4:
524     case kMode_M8:
525     case kMode_MI:
526     case kMode_MR:
527       return 1U;
528     default:
529       UNREACHABLE();
530       return 0U;
531   }
532 }
533
534
535 static AddressingMode AddressingModeForAddMult(int32_t imm,
536                                                const MultParam& m) {
537   if (imm == 0) return m.addressing_mode;
538   switch (m.addressing_mode) {
539     case kMode_MR1:
540       return kMode_MR1I;
541     case kMode_MR2:
542       return kMode_MR2I;
543     case kMode_MR4:
544       return kMode_MR4I;
545     case kMode_MR8:
546       return kMode_MR8I;
547     case kMode_M1:
548       return kMode_M1I;
549     case kMode_M2:
550       return kMode_M2I;
551     case kMode_M4:
552       return kMode_M4I;
553     case kMode_M8:
554       return kMode_M8I;
555     case kMode_MR:
556       return kMode_MRI;
557     default:
558       UNREACHABLE();
559       return kMode_None;
560   }
561 }
562
563
564 TEST_P(InstructionSelectorMultTest, Mult32) {
565   const MultParam m_param = GetParam();
566   StreamBuilder m(this, kMachInt32, kMachInt32);
567   Node* param = m.Parameter(0);
568   Node* mult = m.Int32Mul(param, m.Int32Constant(m_param.value));
569   m.Return(mult);
570   Stream s = m.Build();
571   ASSERT_EQ(1U, s.size());
572   EXPECT_EQ(m_param.addressing_mode, s[0]->addressing_mode());
573   if (m_param.lea_expected) {
574     EXPECT_EQ(kIA32Lea, s[0]->arch_opcode());
575     ASSERT_EQ(InputCountForLea(s[0]->addressing_mode()), s[0]->InputCount());
576   } else {
577     EXPECT_EQ(kIA32Imul, s[0]->arch_opcode());
578     ASSERT_EQ(2U, s[0]->InputCount());
579   }
580   EXPECT_EQ(s.ToVreg(param), s.ToVreg(s[0]->InputAt(0)));
581 }
582
583
584 TEST_P(InstructionSelectorMultTest, MultAdd32) {
585   TRACED_FOREACH(int32_t, imm, kImmediates) {
586     const MultParam m_param = GetParam();
587     StreamBuilder m(this, kMachInt32, kMachInt32);
588     Node* param = m.Parameter(0);
589     Node* mult = m.Int32Add(m.Int32Mul(param, m.Int32Constant(m_param.value)),
590                             m.Int32Constant(imm));
591     m.Return(mult);
592     Stream s = m.Build();
593     if (m_param.lea_expected) {
594       ASSERT_EQ(1U, s.size());
595       EXPECT_EQ(kIA32Lea, s[0]->arch_opcode());
596       EXPECT_EQ(AddressingModeForAddMult(imm, m_param),
597                 s[0]->addressing_mode());
598       unsigned input_count = InputCountForLea(s[0]->addressing_mode());
599       ASSERT_EQ(input_count, s[0]->InputCount());
600       if (imm != 0) {
601         ASSERT_EQ(InstructionOperand::IMMEDIATE,
602                   s[0]->InputAt(input_count - 1)->kind());
603         EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(input_count - 1)));
604       }
605     } else {
606       ASSERT_EQ(2U, s.size());
607       EXPECT_EQ(kIA32Imul, s[0]->arch_opcode());
608       EXPECT_EQ(kIA32Lea, s[1]->arch_opcode());
609     }
610   }
611 }
612
613
614 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorMultTest,
615                         ::testing::ValuesIn(kMultParams));
616
617
618 TEST_F(InstructionSelectorTest, Int32MulHigh) {
619   StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
620   Node* const p0 = m.Parameter(0);
621   Node* const p1 = m.Parameter(1);
622   Node* const n = m.Int32MulHigh(p0, p1);
623   m.Return(n);
624   Stream s = m.Build();
625   ASSERT_EQ(1U, s.size());
626   EXPECT_EQ(kIA32ImulHigh, s[0]->arch_opcode());
627   ASSERT_EQ(2U, s[0]->InputCount());
628   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
629   EXPECT_TRUE(s.IsFixed(s[0]->InputAt(0), eax));
630   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
631   EXPECT_TRUE(!s.IsUsedAtStart(s[0]->InputAt(1)));
632   ASSERT_EQ(1U, s[0]->OutputCount());
633   EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
634   EXPECT_TRUE(s.IsFixed(s[0]->OutputAt(0), edx));
635 }
636
637
638 TEST_F(InstructionSelectorTest, Float64BinopArithmetic) {
639   {
640     StreamBuilder m(this, kMachFloat64, kMachFloat64, kMachFloat64);
641     Node* add = m.Float64Add(m.Parameter(0), m.Parameter(1));
642     Node* mul = m.Float64Mul(add, m.Parameter(1));
643     Node* sub = m.Float64Sub(mul, add);
644     Node* ret = m.Float64Div(mul, sub);
645     m.Return(ret);
646     Stream s = m.Build(AVX);
647     ASSERT_EQ(4U, s.size());
648     EXPECT_EQ(kAVXFloat64Add, s[0]->arch_opcode());
649     EXPECT_EQ(kAVXFloat64Mul, s[1]->arch_opcode());
650     EXPECT_EQ(kAVXFloat64Sub, s[2]->arch_opcode());
651     EXPECT_EQ(kAVXFloat64Div, s[3]->arch_opcode());
652   }
653   {
654     StreamBuilder m(this, kMachFloat64, kMachFloat64, kMachFloat64);
655     Node* add = m.Float64Add(m.Parameter(0), m.Parameter(1));
656     Node* mul = m.Float64Mul(add, m.Parameter(1));
657     Node* sub = m.Float64Sub(mul, add);
658     Node* ret = m.Float64Div(mul, sub);
659     m.Return(ret);
660     Stream s = m.Build();
661     ASSERT_EQ(4U, s.size());
662     EXPECT_EQ(kSSEFloat64Add, s[0]->arch_opcode());
663     EXPECT_EQ(kSSEFloat64Mul, s[1]->arch_opcode());
664     EXPECT_EQ(kSSEFloat64Sub, s[2]->arch_opcode());
665     EXPECT_EQ(kSSEFloat64Div, s[3]->arch_opcode());
666   }
667 }
668
669
670 // -----------------------------------------------------------------------------
671 // Miscellaneous.
672
673
674 TEST_F(InstructionSelectorTest, Uint32LessThanWithLoadAndLoadStackPointer) {
675   StreamBuilder m(this, kMachBool);
676   Node* const sl = m.Load(
677       kMachPtr,
678       m.ExternalConstant(ExternalReference::address_of_stack_limit(isolate())));
679   Node* const sp = m.LoadStackPointer();
680   Node* const n = m.Uint32LessThan(sl, sp);
681   m.Return(n);
682   Stream s = m.Build();
683   ASSERT_EQ(1U, s.size());
684   EXPECT_EQ(kIA32StackCheck, s[0]->arch_opcode());
685   ASSERT_EQ(0U, s[0]->InputCount());
686   ASSERT_EQ(1U, s[0]->OutputCount());
687   EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
688   EXPECT_EQ(kFlags_set, s[0]->flags_mode());
689   EXPECT_EQ(kUnsignedGreaterThan, s[0]->flags_condition());
690 }
691
692
693 TEST_F(InstructionSelectorTest, Word32Clz) {
694   StreamBuilder m(this, kMachUint32, kMachUint32);
695   Node* const p0 = m.Parameter(0);
696   Node* const n = m.Word32Clz(p0);
697   m.Return(n);
698   Stream s = m.Build();
699   ASSERT_EQ(1U, s.size());
700   EXPECT_EQ(kIA32Lzcnt, s[0]->arch_opcode());
701   ASSERT_EQ(1U, s[0]->InputCount());
702   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
703   ASSERT_EQ(1U, s[0]->OutputCount());
704   EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
705 }
706
707 }  // namespace compiler
708 }  // namespace internal
709 }  // namespace v8