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
7namespace v8 {
8namespace internal {
9namespace compiler {
10
11namespace {
12
13template <typename T>
14struct MachInst {
15  T constructor;
16  const char* constructor_name;
17  ArchOpcode arch_opcode;
18  MachineType machine_type;
19};
20
21template <typename T>
22std::ostream& operator<<(std::ostream& os, const MachInst<T>& mi) {
23  return os << mi.constructor_name;
24}
25
26typedef MachInst<Node* (RawMachineAssembler::*)(Node*)> MachInst1;
27typedef MachInst<Node* (RawMachineAssembler::*)(Node*, Node*)> MachInst2;
28
29// To avoid duplicated code IntCmp helper structure
30// is created. It contains MachInst2 with two nodes and expected_size
31// because different cmp instructions have different size.
32struct IntCmp {
33  MachInst2 mi;
34  uint32_t expected_size;
35};
36
37struct FPCmp {
38  MachInst2 mi;
39  FlagsCondition cond;
40};
41
42const FPCmp kFPCmpInstructions[] = {
43    {{&RawMachineAssembler::Float64Equal, "Float64Equal", kMipsCmpD,
44      MachineType::Float64()},
45     kEqual},
46    {{&RawMachineAssembler::Float64LessThan, "Float64LessThan", kMipsCmpD,
47      MachineType::Float64()},
48     kUnsignedLessThan},
49    {{&RawMachineAssembler::Float64LessThanOrEqual, "Float64LessThanOrEqual",
50      kMipsCmpD, MachineType::Float64()},
51     kUnsignedLessThanOrEqual},
52    {{&RawMachineAssembler::Float64GreaterThan, "Float64GreaterThan", kMipsCmpD,
53      MachineType::Float64()},
54     kUnsignedLessThan},
55    {{&RawMachineAssembler::Float64GreaterThanOrEqual,
56      "Float64GreaterThanOrEqual", kMipsCmpD, MachineType::Float64()},
57     kUnsignedLessThanOrEqual}};
58
59struct Conversion {
60  // The machine_type field in MachInst1 represents the destination type.
61  MachInst1 mi;
62  MachineType src_machine_type;
63};
64
65
66// ----------------------------------------------------------------------------
67// Logical instructions.
68// ----------------------------------------------------------------------------
69
70
71const MachInst2 kLogicalInstructions[] = {
72    {&RawMachineAssembler::WordAnd, "WordAnd", kMipsAnd, MachineType::Int16()},
73    {&RawMachineAssembler::WordOr, "WordOr", kMipsOr, MachineType::Int16()},
74    {&RawMachineAssembler::WordXor, "WordXor", kMipsXor, MachineType::Int16()},
75    {&RawMachineAssembler::Word32And, "Word32And", kMipsAnd,
76     MachineType::Int32()},
77    {&RawMachineAssembler::Word32Or, "Word32Or", kMipsOr, MachineType::Int32()},
78    {&RawMachineAssembler::Word32Xor, "Word32Xor", kMipsXor,
79     MachineType::Int32()}};
80
81
82// ----------------------------------------------------------------------------
83// Shift instructions.
84// ----------------------------------------------------------------------------
85
86
87const MachInst2 kShiftInstructions[] = {
88    {&RawMachineAssembler::WordShl, "WordShl", kMipsShl, MachineType::Int16()},
89    {&RawMachineAssembler::WordShr, "WordShr", kMipsShr, MachineType::Int16()},
90    {&RawMachineAssembler::WordSar, "WordSar", kMipsSar, MachineType::Int16()},
91    {&RawMachineAssembler::WordRor, "WordRor", kMipsRor, MachineType::Int16()},
92    {&RawMachineAssembler::Word32Shl, "Word32Shl", kMipsShl,
93     MachineType::Int32()},
94    {&RawMachineAssembler::Word32Shr, "Word32Shr", kMipsShr,
95     MachineType::Int32()},
96    {&RawMachineAssembler::Word32Sar, "Word32Sar", kMipsSar,
97     MachineType::Int32()},
98    {&RawMachineAssembler::Word32Ror, "Word32Ror", kMipsRor,
99     MachineType::Int32()}};
100
101
102// ----------------------------------------------------------------------------
103// MUL/DIV instructions.
104// ----------------------------------------------------------------------------
105
106
107const MachInst2 kMulDivInstructions[] = {
108    {&RawMachineAssembler::Int32Mul, "Int32Mul", kMipsMul,
109     MachineType::Int32()},
110    {&RawMachineAssembler::Int32Div, "Int32Div", kMipsDiv,
111     MachineType::Int32()},
112    {&RawMachineAssembler::Uint32Div, "Uint32Div", kMipsDivU,
113     MachineType::Uint32()},
114    {&RawMachineAssembler::Float64Mul, "Float64Mul", kMipsMulD,
115     MachineType::Float64()},
116    {&RawMachineAssembler::Float64Div, "Float64Div", kMipsDivD,
117     MachineType::Float64()}};
118
119
120// ----------------------------------------------------------------------------
121// MOD instructions.
122// ----------------------------------------------------------------------------
123
124
125const MachInst2 kModInstructions[] = {
126    {&RawMachineAssembler::Int32Mod, "Int32Mod", kMipsMod,
127     MachineType::Int32()},
128    {&RawMachineAssembler::Uint32Mod, "Int32UMod", kMipsModU,
129     MachineType::Int32()},
130    {&RawMachineAssembler::Float64Mod, "Float64Mod", kMipsModD,
131     MachineType::Float64()}};
132
133
134// ----------------------------------------------------------------------------
135// Arithmetic FPU instructions.
136// ----------------------------------------------------------------------------
137
138
139const MachInst2 kFPArithInstructions[] = {
140    {&RawMachineAssembler::Float64Add, "Float64Add", kMipsAddD,
141     MachineType::Float64()},
142    {&RawMachineAssembler::Float64Sub, "Float64Sub", kMipsSubD,
143     MachineType::Float64()}};
144
145
146// ----------------------------------------------------------------------------
147// IntArithTest instructions, two nodes.
148// ----------------------------------------------------------------------------
149
150
151const MachInst2 kAddSubInstructions[] = {
152    {&RawMachineAssembler::Int32Add, "Int32Add", kMipsAdd,
153     MachineType::Int32()},
154    {&RawMachineAssembler::Int32Sub, "Int32Sub", kMipsSub,
155     MachineType::Int32()},
156    {&RawMachineAssembler::Int32AddWithOverflow, "Int32AddWithOverflow",
157     kMipsAddOvf, MachineType::Int32()},
158    {&RawMachineAssembler::Int32SubWithOverflow, "Int32SubWithOverflow",
159     kMipsSubOvf, MachineType::Int32()}};
160
161
162// ----------------------------------------------------------------------------
163// IntArithTest instructions, one node.
164// ----------------------------------------------------------------------------
165
166
167const MachInst1 kAddSubOneInstructions[] = {
168    {&RawMachineAssembler::Int32Neg, "Int32Neg", kMipsSub,
169     MachineType::Int32()},
170    // TODO(dusmil): check this ...
171    // {&RawMachineAssembler::WordEqual  , "WordEqual"  , kMipsTst,
172    // MachineType::Int32()}
173};
174
175
176// ----------------------------------------------------------------------------
177// Arithmetic compare instructions.
178// ----------------------------------------------------------------------------
179
180
181const IntCmp kCmpInstructions[] = {
182    {{&RawMachineAssembler::WordEqual, "WordEqual", kMipsCmp,
183      MachineType::Int16()},
184     1U},
185    {{&RawMachineAssembler::WordNotEqual, "WordNotEqual", kMipsCmp,
186      MachineType::Int16()},
187     1U},
188    {{&RawMachineAssembler::Word32Equal, "Word32Equal", kMipsCmp,
189      MachineType::Int32()},
190     1U},
191    {{&RawMachineAssembler::Word32NotEqual, "Word32NotEqual", kMipsCmp,
192      MachineType::Int32()},
193     1U},
194    {{&RawMachineAssembler::Int32LessThan, "Int32LessThan", kMipsCmp,
195      MachineType::Int32()},
196     1U},
197    {{&RawMachineAssembler::Int32LessThanOrEqual, "Int32LessThanOrEqual",
198      kMipsCmp, MachineType::Int32()},
199     1U},
200    {{&RawMachineAssembler::Int32GreaterThan, "Int32GreaterThan", kMipsCmp,
201      MachineType::Int32()},
202     1U},
203    {{&RawMachineAssembler::Int32GreaterThanOrEqual, "Int32GreaterThanOrEqual",
204      kMipsCmp, MachineType::Int32()},
205     1U},
206    {{&RawMachineAssembler::Uint32LessThan, "Uint32LessThan", kMipsCmp,
207      MachineType::Uint32()},
208     1U},
209    {{&RawMachineAssembler::Uint32LessThanOrEqual, "Uint32LessThanOrEqual",
210      kMipsCmp, MachineType::Uint32()},
211     1U}};
212
213
214// ----------------------------------------------------------------------------
215// Conversion instructions.
216// ----------------------------------------------------------------------------
217
218const Conversion kConversionInstructions[] = {
219    // Conversion instructions are related to machine_operator.h:
220    // FPU conversions:
221    // Convert representation of integers between float64 and int32/uint32.
222    // The precise rounding mode and handling of out of range inputs are *not*
223    // defined for these operators, since they are intended only for use with
224    // integers.
225    // mips instruction: cvt_d_w
226    {{&RawMachineAssembler::ChangeInt32ToFloat64, "ChangeInt32ToFloat64",
227      kMipsCvtDW, MachineType::Float64()},
228     MachineType::Int32()},
229
230    // mips instruction: cvt_d_uw
231    {{&RawMachineAssembler::ChangeUint32ToFloat64, "ChangeUint32ToFloat64",
232      kMipsCvtDUw, MachineType::Float64()},
233     MachineType::Int32()},
234
235    // mips instruction: trunc_w_d
236    {{&RawMachineAssembler::ChangeFloat64ToInt32, "ChangeFloat64ToInt32",
237      kMipsTruncWD, MachineType::Float64()},
238     MachineType::Int32()},
239
240    // mips instruction: trunc_uw_d
241    {{&RawMachineAssembler::ChangeFloat64ToUint32, "ChangeFloat64ToUint32",
242      kMipsTruncUwD, MachineType::Float64()},
243     MachineType::Int32()}};
244
245const Conversion kFloat64RoundInstructions[] = {
246    {{&RawMachineAssembler::Float64RoundUp, "Float64RoundUp", kMipsCeilWD,
247      MachineType::Int32()},
248     MachineType::Float64()},
249    {{&RawMachineAssembler::Float64RoundDown, "Float64RoundDown", kMipsFloorWD,
250      MachineType::Int32()},
251     MachineType::Float64()},
252    {{&RawMachineAssembler::Float64RoundTiesEven, "Float64RoundTiesEven",
253      kMipsRoundWD, MachineType::Int32()},
254     MachineType::Float64()},
255    {{&RawMachineAssembler::Float64RoundTruncate, "Float64RoundTruncate",
256      kMipsTruncWD, MachineType::Int32()},
257     MachineType::Float64()}};
258
259const Conversion kFloat32RoundInstructions[] = {
260    {{&RawMachineAssembler::Float32RoundUp, "Float32RoundUp", kMipsCeilWS,
261      MachineType::Int32()},
262     MachineType::Float32()},
263    {{&RawMachineAssembler::Float32RoundDown, "Float32RoundDown", kMipsFloorWS,
264      MachineType::Int32()},
265     MachineType::Float32()},
266    {{&RawMachineAssembler::Float32RoundTiesEven, "Float32RoundTiesEven",
267      kMipsRoundWS, MachineType::Int32()},
268     MachineType::Float32()},
269    {{&RawMachineAssembler::Float32RoundTruncate, "Float32RoundTruncate",
270      kMipsTruncWS, MachineType::Int32()},
271     MachineType::Float32()}};
272
273}  // namespace
274
275
276typedef InstructionSelectorTestWithParam<FPCmp> InstructionSelectorFPCmpTest;
277
278
279TEST_P(InstructionSelectorFPCmpTest, Parameter) {
280  const FPCmp cmp = GetParam();
281  StreamBuilder m(this, MachineType::Int32(), cmp.mi.machine_type,
282                  cmp.mi.machine_type);
283  m.Return((m.*cmp.mi.constructor)(m.Parameter(0), m.Parameter(1)));
284  Stream s = m.Build();
285  ASSERT_EQ(1U, s.size());
286  EXPECT_EQ(cmp.mi.arch_opcode, s[0]->arch_opcode());
287  EXPECT_EQ(2U, s[0]->InputCount());
288  EXPECT_EQ(1U, s[0]->OutputCount());
289  EXPECT_EQ(kFlags_set, s[0]->flags_mode());
290  EXPECT_EQ(cmp.cond, s[0]->flags_condition());
291}
292
293INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorFPCmpTest,
294                        ::testing::ValuesIn(kFPCmpInstructions));
295
296
297// ----------------------------------------------------------------------------
298// Arithmetic compare instructions integers.
299// ----------------------------------------------------------------------------
300
301
302typedef InstructionSelectorTestWithParam<IntCmp> InstructionSelectorCmpTest;
303
304
305TEST_P(InstructionSelectorCmpTest, Parameter) {
306  const IntCmp cmp = GetParam();
307  const MachineType type = cmp.mi.machine_type;
308  StreamBuilder m(this, type, type, type);
309  m.Return((m.*cmp.mi.constructor)(m.Parameter(0), m.Parameter(1)));
310  Stream s = m.Build();
311  ASSERT_EQ(cmp.expected_size, s.size());
312  EXPECT_EQ(cmp.mi.arch_opcode, s[0]->arch_opcode());
313  EXPECT_EQ(2U, s[0]->InputCount());
314  EXPECT_EQ(1U, s[0]->OutputCount());
315}
316
317
318INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorCmpTest,
319                        ::testing::ValuesIn(kCmpInstructions));
320
321
322// ----------------------------------------------------------------------------
323// Shift instructions.
324// ----------------------------------------------------------------------------
325
326
327typedef InstructionSelectorTestWithParam<MachInst2>
328    InstructionSelectorShiftTest;
329
330
331TEST_P(InstructionSelectorShiftTest, Immediate) {
332  const MachInst2 dpi = GetParam();
333  const MachineType type = dpi.machine_type;
334  TRACED_FORRANGE(int32_t, imm, 0,
335                  ((1 << ElementSizeLog2Of(type.representation())) * 8) - 1) {
336    StreamBuilder m(this, type, type);
337    m.Return((m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm)));
338    Stream s = m.Build();
339    ASSERT_EQ(1U, s.size());
340    EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
341    EXPECT_EQ(2U, s[0]->InputCount());
342    EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
343    EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
344    EXPECT_EQ(1U, s[0]->OutputCount());
345  }
346}
347
348
349INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorShiftTest,
350                        ::testing::ValuesIn(kShiftInstructions));
351
352
353TEST_F(InstructionSelectorTest, Word32ShrWithWord32AndWithImmediate) {
354  // The available shift operand range is `0 <= imm < 32`, but we also test
355  // that immediates outside this range are handled properly (modulo-32).
356  TRACED_FORRANGE(int32_t, shift, -32, 63) {
357    int32_t lsb = shift & 0x1f;
358    TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) {
359      uint32_t jnk = rng()->NextInt();
360      jnk = (lsb > 0) ? (jnk >> (32 - lsb)) : 0;
361      uint32_t msk = ((0xffffffffu >> (32 - width)) << lsb) | jnk;
362      StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
363      m.Return(m.Word32Shr(m.Word32And(m.Parameter(0), m.Int32Constant(msk)),
364                           m.Int32Constant(shift)));
365      Stream s = m.Build();
366      ASSERT_EQ(1U, s.size());
367      EXPECT_EQ(kMipsExt, s[0]->arch_opcode());
368      ASSERT_EQ(3U, s[0]->InputCount());
369      EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
370      EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
371    }
372  }
373  TRACED_FORRANGE(int32_t, shift, -32, 63) {
374    int32_t lsb = shift & 0x1f;
375    TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) {
376      uint32_t jnk = rng()->NextInt();
377      jnk = (lsb > 0) ? (jnk >> (32 - lsb)) : 0;
378      uint32_t msk = ((0xffffffffu >> (32 - width)) << lsb) | jnk;
379      StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
380      m.Return(m.Word32Shr(m.Word32And(m.Int32Constant(msk), m.Parameter(0)),
381                           m.Int32Constant(shift)));
382      Stream s = m.Build();
383      ASSERT_EQ(1U, s.size());
384      EXPECT_EQ(kMipsExt, s[0]->arch_opcode());
385      ASSERT_EQ(3U, s[0]->InputCount());
386      EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
387      EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
388    }
389  }
390}
391
392
393TEST_F(InstructionSelectorTest, Word32ShlWithWord32And) {
394  TRACED_FORRANGE(int32_t, shift, 0, 30) {
395    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
396    Node* const p0 = m.Parameter(0);
397    Node* const r =
398        m.Word32Shl(m.Word32And(p0, m.Int32Constant((1 << (31 - shift)) - 1)),
399                    m.Int32Constant(shift + 1));
400    m.Return(r);
401    Stream s = m.Build();
402    ASSERT_EQ(1U, s.size());
403    EXPECT_EQ(kMipsShl, s[0]->arch_opcode());
404    ASSERT_EQ(2U, s[0]->InputCount());
405    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
406    ASSERT_EQ(1U, s[0]->OutputCount());
407    EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
408  }
409}
410
411
412// ----------------------------------------------------------------------------
413// Logical instructions.
414// ----------------------------------------------------------------------------
415
416
417typedef InstructionSelectorTestWithParam<MachInst2>
418    InstructionSelectorLogicalTest;
419
420
421TEST_P(InstructionSelectorLogicalTest, Parameter) {
422  const MachInst2 dpi = GetParam();
423  const MachineType type = dpi.machine_type;
424  StreamBuilder m(this, type, type, type);
425  m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)));
426  Stream s = m.Build();
427  ASSERT_EQ(1U, s.size());
428  EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
429  EXPECT_EQ(2U, s[0]->InputCount());
430  EXPECT_EQ(1U, s[0]->OutputCount());
431}
432
433
434INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorLogicalTest,
435                        ::testing::ValuesIn(kLogicalInstructions));
436
437
438TEST_F(InstructionSelectorTest, Word32XorMinusOneWithParameter) {
439  {
440    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
441    m.Return(m.Word32Xor(m.Parameter(0), m.Int32Constant(-1)));
442    Stream s = m.Build();
443    ASSERT_EQ(1U, s.size());
444    EXPECT_EQ(kMipsNor, s[0]->arch_opcode());
445    EXPECT_EQ(2U, s[0]->InputCount());
446    EXPECT_EQ(1U, s[0]->OutputCount());
447  }
448  {
449    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
450    m.Return(m.Word32Xor(m.Int32Constant(-1), m.Parameter(0)));
451    Stream s = m.Build();
452    ASSERT_EQ(1U, s.size());
453    EXPECT_EQ(kMipsNor, s[0]->arch_opcode());
454    EXPECT_EQ(2U, s[0]->InputCount());
455    EXPECT_EQ(1U, s[0]->OutputCount());
456  }
457}
458
459
460TEST_F(InstructionSelectorTest, Word32XorMinusOneWithWord32Or) {
461  {
462    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
463    m.Return(m.Word32Xor(m.Word32Or(m.Parameter(0), m.Parameter(0)),
464                         m.Int32Constant(-1)));
465    Stream s = m.Build();
466    ASSERT_EQ(1U, s.size());
467    EXPECT_EQ(kMipsNor, s[0]->arch_opcode());
468    EXPECT_EQ(2U, s[0]->InputCount());
469    EXPECT_EQ(1U, s[0]->OutputCount());
470  }
471  {
472    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
473    m.Return(m.Word32Xor(m.Int32Constant(-1),
474                         m.Word32Or(m.Parameter(0), m.Parameter(0))));
475    Stream s = m.Build();
476    ASSERT_EQ(1U, s.size());
477    EXPECT_EQ(kMipsNor, s[0]->arch_opcode());
478    EXPECT_EQ(2U, s[0]->InputCount());
479    EXPECT_EQ(1U, s[0]->OutputCount());
480  }
481}
482
483
484TEST_F(InstructionSelectorTest, Word32AndWithImmediateWithWord32Shr) {
485  // The available shift operand range is `0 <= imm < 32`, but we also test
486  // that immediates outside this range are handled properly (modulo-32).
487  TRACED_FORRANGE(int32_t, shift, -32, 63) {
488    int32_t lsb = shift & 0x1f;
489    TRACED_FORRANGE(int32_t, width, 1, 31) {
490      uint32_t msk = (1 << width) - 1;
491      StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
492      m.Return(m.Word32And(m.Word32Shr(m.Parameter(0), m.Int32Constant(shift)),
493                           m.Int32Constant(msk)));
494      Stream s = m.Build();
495      ASSERT_EQ(1U, s.size());
496      EXPECT_EQ(kMipsExt, s[0]->arch_opcode());
497      ASSERT_EQ(3U, s[0]->InputCount());
498      EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
499      int32_t actual_width = (lsb + width > 32) ? (32 - lsb) : width;
500      EXPECT_EQ(actual_width, s.ToInt32(s[0]->InputAt(2)));
501    }
502  }
503  TRACED_FORRANGE(int32_t, shift, -32, 63) {
504    int32_t lsb = shift & 0x1f;
505    TRACED_FORRANGE(int32_t, width, 1, 31) {
506      uint32_t msk = (1 << width) - 1;
507      StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
508      m.Return(
509          m.Word32And(m.Int32Constant(msk),
510                      m.Word32Shr(m.Parameter(0), m.Int32Constant(shift))));
511      Stream s = m.Build();
512      ASSERT_EQ(1U, s.size());
513      EXPECT_EQ(kMipsExt, s[0]->arch_opcode());
514      ASSERT_EQ(3U, s[0]->InputCount());
515      EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
516      int32_t actual_width = (lsb + width > 32) ? (32 - lsb) : width;
517      EXPECT_EQ(actual_width, s.ToInt32(s[0]->InputAt(2)));
518    }
519  }
520}
521
522
523TEST_F(InstructionSelectorTest, Word32AndToClearBits) {
524  TRACED_FORRANGE(int32_t, shift, 1, 31) {
525    int32_t mask = ~((1 << shift) - 1);
526    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
527    m.Return(m.Word32And(m.Parameter(0), m.Int32Constant(mask)));
528    Stream s = m.Build();
529    ASSERT_EQ(1U, s.size());
530    EXPECT_EQ(kMipsIns, s[0]->arch_opcode());
531    ASSERT_EQ(3U, s[0]->InputCount());
532    EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1)));
533    EXPECT_EQ(shift, s.ToInt32(s[0]->InputAt(2)));
534  }
535  TRACED_FORRANGE(int32_t, shift, 1, 31) {
536    int32_t mask = ~((1 << shift) - 1);
537    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
538    m.Return(m.Word32And(m.Int32Constant(mask), m.Parameter(0)));
539    Stream s = m.Build();
540    ASSERT_EQ(1U, s.size());
541    EXPECT_EQ(kMipsIns, s[0]->arch_opcode());
542    ASSERT_EQ(3U, s[0]->InputCount());
543    EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1)));
544    EXPECT_EQ(shift, s.ToInt32(s[0]->InputAt(2)));
545  }
546}
547
548
549// ----------------------------------------------------------------------------
550// MUL/DIV instructions.
551// ----------------------------------------------------------------------------
552
553
554typedef InstructionSelectorTestWithParam<MachInst2>
555    InstructionSelectorMulDivTest;
556
557
558TEST_P(InstructionSelectorMulDivTest, Parameter) {
559  const MachInst2 dpi = GetParam();
560  const MachineType type = dpi.machine_type;
561  StreamBuilder m(this, type, type, type);
562  m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)));
563  Stream s = m.Build();
564  ASSERT_EQ(1U, s.size());
565  EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
566  EXPECT_EQ(2U, s[0]->InputCount());
567  EXPECT_EQ(1U, s[0]->OutputCount());
568}
569
570
571INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorMulDivTest,
572                        ::testing::ValuesIn(kMulDivInstructions));
573
574
575// ----------------------------------------------------------------------------
576// MOD instructions.
577// ----------------------------------------------------------------------------
578
579
580typedef InstructionSelectorTestWithParam<MachInst2> InstructionSelectorModTest;
581
582
583TEST_P(InstructionSelectorModTest, Parameter) {
584  const MachInst2 dpi = GetParam();
585  const MachineType type = dpi.machine_type;
586  StreamBuilder m(this, type, type, type);
587  m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)));
588  Stream s = m.Build();
589  ASSERT_EQ(1U, s.size());
590  EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
591  EXPECT_EQ(2U, s[0]->InputCount());
592  EXPECT_EQ(1U, s[0]->OutputCount());
593}
594
595
596INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorModTest,
597                        ::testing::ValuesIn(kModInstructions));
598
599
600// ----------------------------------------------------------------------------
601// Floating point instructions.
602// ----------------------------------------------------------------------------
603
604
605typedef InstructionSelectorTestWithParam<MachInst2>
606    InstructionSelectorFPArithTest;
607
608
609TEST_P(InstructionSelectorFPArithTest, Parameter) {
610  const MachInst2 fpa = GetParam();
611  StreamBuilder m(this, fpa.machine_type, fpa.machine_type, fpa.machine_type);
612  m.Return((m.*fpa.constructor)(m.Parameter(0), m.Parameter(1)));
613  Stream s = m.Build();
614  ASSERT_EQ(1U, s.size());
615  EXPECT_EQ(fpa.arch_opcode, s[0]->arch_opcode());
616  EXPECT_EQ(2U, s[0]->InputCount());
617  EXPECT_EQ(1U, s[0]->OutputCount());
618}
619
620
621INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorFPArithTest,
622                        ::testing::ValuesIn(kFPArithInstructions));
623
624
625// ----------------------------------------------------------------------------
626// Integer arithmetic.
627// ----------------------------------------------------------------------------
628
629
630typedef InstructionSelectorTestWithParam<MachInst2>
631    InstructionSelectorIntArithTwoTest;
632
633
634TEST_P(InstructionSelectorIntArithTwoTest, Parameter) {
635  const MachInst2 intpa = GetParam();
636  StreamBuilder m(this, intpa.machine_type, intpa.machine_type,
637                  intpa.machine_type);
638  m.Return((m.*intpa.constructor)(m.Parameter(0), m.Parameter(1)));
639  Stream s = m.Build();
640  ASSERT_EQ(1U, s.size());
641  EXPECT_EQ(intpa.arch_opcode, s[0]->arch_opcode());
642  EXPECT_EQ(2U, s[0]->InputCount());
643  EXPECT_EQ(1U, s[0]->OutputCount());
644}
645
646
647INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
648                        InstructionSelectorIntArithTwoTest,
649                        ::testing::ValuesIn(kAddSubInstructions));
650
651
652// ----------------------------------------------------------------------------
653// One node.
654// ----------------------------------------------------------------------------
655
656
657typedef InstructionSelectorTestWithParam<MachInst1>
658    InstructionSelectorIntArithOneTest;
659
660
661TEST_P(InstructionSelectorIntArithOneTest, Parameter) {
662  const MachInst1 intpa = GetParam();
663  StreamBuilder m(this, intpa.machine_type, intpa.machine_type,
664                  intpa.machine_type);
665  m.Return((m.*intpa.constructor)(m.Parameter(0)));
666  Stream s = m.Build();
667  ASSERT_EQ(1U, s.size());
668  EXPECT_EQ(intpa.arch_opcode, s[0]->arch_opcode());
669  EXPECT_EQ(2U, s[0]->InputCount());
670  EXPECT_EQ(1U, s[0]->OutputCount());
671}
672
673
674INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
675                        InstructionSelectorIntArithOneTest,
676                        ::testing::ValuesIn(kAddSubOneInstructions));
677
678
679// ----------------------------------------------------------------------------
680// Conversions.
681// ----------------------------------------------------------------------------
682
683
684typedef InstructionSelectorTestWithParam<Conversion>
685    InstructionSelectorConversionTest;
686
687
688TEST_P(InstructionSelectorConversionTest, Parameter) {
689  const Conversion conv = GetParam();
690  StreamBuilder m(this, conv.mi.machine_type, conv.src_machine_type);
691  m.Return((m.*conv.mi.constructor)(m.Parameter(0)));
692  Stream s = m.Build();
693  ASSERT_EQ(1U, s.size());
694  EXPECT_EQ(conv.mi.arch_opcode, s[0]->arch_opcode());
695  EXPECT_EQ(1U, s[0]->InputCount());
696  EXPECT_EQ(1U, s[0]->OutputCount());
697}
698
699
700INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
701                        InstructionSelectorConversionTest,
702                        ::testing::ValuesIn(kConversionInstructions));
703
704
705typedef InstructionSelectorTestWithParam<Conversion>
706    CombineChangeFloat64ToInt32WithRoundFloat64;
707
708TEST_P(CombineChangeFloat64ToInt32WithRoundFloat64, Parameter) {
709  {
710    const Conversion conv = GetParam();
711    StreamBuilder m(this, conv.mi.machine_type, conv.src_machine_type);
712    m.Return(m.ChangeFloat64ToInt32((m.*conv.mi.constructor)(m.Parameter(0))));
713    Stream s = m.Build();
714    ASSERT_EQ(1U, s.size());
715    EXPECT_EQ(conv.mi.arch_opcode, s[0]->arch_opcode());
716    EXPECT_EQ(kMode_None, s[0]->addressing_mode());
717    ASSERT_EQ(1U, s[0]->InputCount());
718    EXPECT_EQ(1U, s[0]->OutputCount());
719  }
720}
721
722INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
723                        CombineChangeFloat64ToInt32WithRoundFloat64,
724                        ::testing::ValuesIn(kFloat64RoundInstructions));
725
726
727typedef InstructionSelectorTestWithParam<Conversion>
728    CombineChangeFloat32ToInt32WithRoundFloat32;
729
730TEST_P(CombineChangeFloat32ToInt32WithRoundFloat32, Parameter) {
731  {
732    const Conversion conv = GetParam();
733    StreamBuilder m(this, conv.mi.machine_type, conv.src_machine_type);
734    m.Return(m.ChangeFloat64ToInt32(
735        m.ChangeFloat32ToFloat64((m.*conv.mi.constructor)(m.Parameter(0)))));
736    Stream s = m.Build();
737    ASSERT_EQ(1U, s.size());
738    EXPECT_EQ(conv.mi.arch_opcode, s[0]->arch_opcode());
739    EXPECT_EQ(kMode_None, s[0]->addressing_mode());
740    ASSERT_EQ(1U, s[0]->InputCount());
741    EXPECT_EQ(1U, s[0]->OutputCount());
742  }
743}
744
745INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
746                        CombineChangeFloat32ToInt32WithRoundFloat32,
747                        ::testing::ValuesIn(kFloat32RoundInstructions));
748
749
750TEST_F(InstructionSelectorTest, ChangeFloat64ToInt32OfChangeFloat32ToFloat64) {
751  {
752    StreamBuilder m(this, MachineType::Int32(), MachineType::Float32());
753    m.Return(m.ChangeFloat64ToInt32(m.ChangeFloat32ToFloat64(m.Parameter(0))));
754    Stream s = m.Build();
755    ASSERT_EQ(1U, s.size());
756    EXPECT_EQ(kMipsTruncWS, s[0]->arch_opcode());
757    EXPECT_EQ(kMode_None, s[0]->addressing_mode());
758    ASSERT_EQ(1U, s[0]->InputCount());
759    EXPECT_EQ(1U, s[0]->OutputCount());
760  }
761}
762
763
764TEST_F(InstructionSelectorTest,
765       TruncateFloat64ToFloat32OfChangeInt32ToFloat64) {
766  {
767    StreamBuilder m(this, MachineType::Float32(), MachineType::Int32());
768    m.Return(
769        m.TruncateFloat64ToFloat32(m.ChangeInt32ToFloat64(m.Parameter(0))));
770    Stream s = m.Build();
771    ASSERT_EQ(1U, s.size());
772    EXPECT_EQ(kMipsCvtSW, s[0]->arch_opcode());
773    EXPECT_EQ(kMode_None, s[0]->addressing_mode());
774    ASSERT_EQ(1U, s[0]->InputCount());
775    EXPECT_EQ(1U, s[0]->OutputCount());
776  }
777}
778
779
780// ----------------------------------------------------------------------------
781// Loads and stores.
782// ----------------------------------------------------------------------------
783
784namespace {
785
786struct MemoryAccess {
787  MachineType type;
788  ArchOpcode load_opcode;
789  ArchOpcode store_opcode;
790};
791
792
793static const MemoryAccess kMemoryAccesses[] = {
794    {MachineType::Int8(), kMipsLb, kMipsSb},
795    {MachineType::Uint8(), kMipsLbu, kMipsSb},
796    {MachineType::Int16(), kMipsLh, kMipsSh},
797    {MachineType::Uint16(), kMipsLhu, kMipsSh},
798    {MachineType::Int32(), kMipsLw, kMipsSw},
799    {MachineType::Float32(), kMipsLwc1, kMipsSwc1},
800    {MachineType::Float64(), kMipsLdc1, kMipsSdc1}};
801
802
803struct MemoryAccessImm {
804  MachineType type;
805  ArchOpcode load_opcode;
806  ArchOpcode store_opcode;
807  bool (InstructionSelectorTest::Stream::*val_predicate)(
808      const InstructionOperand*) const;
809  const int32_t immediates[40];
810};
811
812
813std::ostream& operator<<(std::ostream& os, const MemoryAccessImm& acc) {
814  return os << acc.type;
815}
816
817
818struct MemoryAccessImm1 {
819  MachineType type;
820  ArchOpcode load_opcode;
821  ArchOpcode store_opcode;
822  bool (InstructionSelectorTest::Stream::*val_predicate)(
823      const InstructionOperand*) const;
824  const int32_t immediates[5];
825};
826
827
828std::ostream& operator<<(std::ostream& os, const MemoryAccessImm1& acc) {
829  return os << acc.type;
830}
831
832
833// ----------------------------------------------------------------------------
834// Loads and stores immediate values.
835// ----------------------------------------------------------------------------
836
837
838const MemoryAccessImm kMemoryAccessesImm[] = {
839    {MachineType::Int8(),
840     kMipsLb,
841     kMipsSb,
842     &InstructionSelectorTest::Stream::IsInteger,
843     {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89,
844      -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109,
845      115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}},
846    {MachineType::Uint8(),
847     kMipsLbu,
848     kMipsSb,
849     &InstructionSelectorTest::Stream::IsInteger,
850     {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89,
851      -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109,
852      115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}},
853    {MachineType::Int16(),
854     kMipsLh,
855     kMipsSh,
856     &InstructionSelectorTest::Stream::IsInteger,
857     {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89,
858      -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109,
859      115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}},
860    {MachineType::Uint16(),
861     kMipsLhu,
862     kMipsSh,
863     &InstructionSelectorTest::Stream::IsInteger,
864     {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89,
865      -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109,
866      115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}},
867    {MachineType::Int32(),
868     kMipsLw,
869     kMipsSw,
870     &InstructionSelectorTest::Stream::IsInteger,
871     {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89,
872      -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109,
873      115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}},
874    {MachineType::Float32(),
875     kMipsLwc1,
876     kMipsSwc1,
877     &InstructionSelectorTest::Stream::IsDouble,
878     {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89,
879      -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109,
880      115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}},
881    {MachineType::Float64(),
882     kMipsLdc1,
883     kMipsSdc1,
884     &InstructionSelectorTest::Stream::IsDouble,
885     {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89,
886      -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109,
887      115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}}};
888
889
890const MemoryAccessImm1 kMemoryAccessImmMoreThan16bit[] = {
891    {MachineType::Int8(),
892     kMipsLb,
893     kMipsSb,
894     &InstructionSelectorTest::Stream::IsInteger,
895     {-65000, -55000, 32777, 55000, 65000}},
896    {MachineType::Int8(),
897     kMipsLbu,
898     kMipsSb,
899     &InstructionSelectorTest::Stream::IsInteger,
900     {-65000, -55000, 32777, 55000, 65000}},
901    {MachineType::Int16(),
902     kMipsLh,
903     kMipsSh,
904     &InstructionSelectorTest::Stream::IsInteger,
905     {-65000, -55000, 32777, 55000, 65000}},
906    {MachineType::Int16(),
907     kMipsLhu,
908     kMipsSh,
909     &InstructionSelectorTest::Stream::IsInteger,
910     {-65000, -55000, 32777, 55000, 65000}},
911    {MachineType::Int32(),
912     kMipsLw,
913     kMipsSw,
914     &InstructionSelectorTest::Stream::IsInteger,
915     {-65000, -55000, 32777, 55000, 65000}},
916    {MachineType::Float32(),
917     kMipsLwc1,
918     kMipsSwc1,
919     &InstructionSelectorTest::Stream::IsDouble,
920     {-65000, -55000, 32777, 55000, 65000}},
921    {MachineType::Float64(),
922     kMipsLdc1,
923     kMipsSdc1,
924     &InstructionSelectorTest::Stream::IsDouble,
925     {-65000, -55000, 32777, 55000, 65000}}};
926
927}  // namespace
928
929
930typedef InstructionSelectorTestWithParam<MemoryAccess>
931    InstructionSelectorMemoryAccessTest;
932
933
934TEST_P(InstructionSelectorMemoryAccessTest, LoadWithParameters) {
935  const MemoryAccess memacc = GetParam();
936  StreamBuilder m(this, memacc.type, MachineType::Pointer(),
937                  MachineType::Int32());
938  m.Return(m.Load(memacc.type, m.Parameter(0)));
939  Stream s = m.Build();
940  ASSERT_EQ(1U, s.size());
941  EXPECT_EQ(memacc.load_opcode, s[0]->arch_opcode());
942  EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
943}
944
945
946TEST_P(InstructionSelectorMemoryAccessTest, StoreWithParameters) {
947  const MemoryAccess memacc = GetParam();
948  StreamBuilder m(this, MachineType::Int32(), MachineType::Pointer(),
949                  MachineType::Int32(), memacc.type);
950  m.Store(memacc.type.representation(), m.Parameter(0), m.Parameter(1),
951          kNoWriteBarrier);
952  m.Return(m.Int32Constant(0));
953  Stream s = m.Build();
954  ASSERT_EQ(1U, s.size());
955  EXPECT_EQ(memacc.store_opcode, s[0]->arch_opcode());
956  EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
957}
958
959
960INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
961                        InstructionSelectorMemoryAccessTest,
962                        ::testing::ValuesIn(kMemoryAccesses));
963
964
965// ----------------------------------------------------------------------------
966// Load immediate.
967// ----------------------------------------------------------------------------
968
969
970typedef InstructionSelectorTestWithParam<MemoryAccessImm>
971    InstructionSelectorMemoryAccessImmTest;
972
973
974TEST_P(InstructionSelectorMemoryAccessImmTest, LoadWithImmediateIndex) {
975  const MemoryAccessImm memacc = GetParam();
976  TRACED_FOREACH(int32_t, index, memacc.immediates) {
977    StreamBuilder m(this, memacc.type, MachineType::Pointer());
978    m.Return(m.Load(memacc.type, m.Parameter(0), m.Int32Constant(index)));
979    Stream s = m.Build();
980    ASSERT_EQ(1U, s.size());
981    EXPECT_EQ(memacc.load_opcode, s[0]->arch_opcode());
982    EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
983    ASSERT_EQ(2U, s[0]->InputCount());
984    ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
985    EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1)));
986    ASSERT_EQ(1U, s[0]->OutputCount());
987    EXPECT_TRUE((s.*memacc.val_predicate)(s[0]->Output()));
988  }
989}
990
991
992// ----------------------------------------------------------------------------
993// Store immediate.
994// ----------------------------------------------------------------------------
995
996
997TEST_P(InstructionSelectorMemoryAccessImmTest, StoreWithImmediateIndex) {
998  const MemoryAccessImm memacc = GetParam();
999  TRACED_FOREACH(int32_t, index, memacc.immediates) {
1000    StreamBuilder m(this, MachineType::Int32(), MachineType::Pointer(),
1001                    memacc.type);
1002    m.Store(memacc.type.representation(), m.Parameter(0),
1003            m.Int32Constant(index), m.Parameter(1), kNoWriteBarrier);
1004    m.Return(m.Int32Constant(0));
1005    Stream s = m.Build();
1006    ASSERT_EQ(1U, s.size());
1007    EXPECT_EQ(memacc.store_opcode, s[0]->arch_opcode());
1008    EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
1009    ASSERT_EQ(3U, s[0]->InputCount());
1010    ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
1011    EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1)));
1012    EXPECT_EQ(0U, s[0]->OutputCount());
1013  }
1014}
1015
1016
1017INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1018                        InstructionSelectorMemoryAccessImmTest,
1019                        ::testing::ValuesIn(kMemoryAccessesImm));
1020
1021
1022// ----------------------------------------------------------------------------
1023// Load/store offsets more than 16 bits.
1024// ----------------------------------------------------------------------------
1025
1026
1027typedef InstructionSelectorTestWithParam<MemoryAccessImm1>
1028    InstructionSelectorMemoryAccessImmMoreThan16bitTest;
1029
1030
1031TEST_P(InstructionSelectorMemoryAccessImmMoreThan16bitTest,
1032       LoadWithImmediateIndex) {
1033  const MemoryAccessImm1 memacc = GetParam();
1034  TRACED_FOREACH(int32_t, index, memacc.immediates) {
1035    StreamBuilder m(this, memacc.type, MachineType::Pointer());
1036    m.Return(m.Load(memacc.type, m.Parameter(0), m.Int32Constant(index)));
1037    Stream s = m.Build();
1038    ASSERT_EQ(2U, s.size());
1039    // kMipsAdd is expected opcode.
1040    // size more than 16 bits wide.
1041    EXPECT_EQ(kMipsAdd, s[0]->arch_opcode());
1042    EXPECT_EQ(kMode_None, s[0]->addressing_mode());
1043    EXPECT_EQ(2U, s[0]->InputCount());
1044    EXPECT_EQ(1U, s[0]->OutputCount());
1045  }
1046}
1047
1048
1049TEST_P(InstructionSelectorMemoryAccessImmMoreThan16bitTest,
1050       StoreWithImmediateIndex) {
1051  const MemoryAccessImm1 memacc = GetParam();
1052  TRACED_FOREACH(int32_t, index, memacc.immediates) {
1053    StreamBuilder m(this, MachineType::Int32(), MachineType::Pointer(),
1054                    memacc.type);
1055    m.Store(memacc.type.representation(), m.Parameter(0),
1056            m.Int32Constant(index), m.Parameter(1), kNoWriteBarrier);
1057    m.Return(m.Int32Constant(0));
1058    Stream s = m.Build();
1059    ASSERT_EQ(2U, s.size());
1060    // kMipsAdd is expected opcode
1061    // size more than 16 bits wide
1062    EXPECT_EQ(kMipsAdd, s[0]->arch_opcode());
1063    EXPECT_EQ(kMode_None, s[0]->addressing_mode());
1064    EXPECT_EQ(2U, s[0]->InputCount());
1065    EXPECT_EQ(1U, s[0]->OutputCount());
1066  }
1067}
1068
1069
1070INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1071                        InstructionSelectorMemoryAccessImmMoreThan16bitTest,
1072                        ::testing::ValuesIn(kMemoryAccessImmMoreThan16bit));
1073
1074
1075// ----------------------------------------------------------------------------
1076// kMipsTst testing.
1077// ----------------------------------------------------------------------------
1078
1079
1080TEST_F(InstructionSelectorTest, Word32EqualWithZero) {
1081  {
1082    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
1083    m.Return(m.Word32Equal(m.Parameter(0), m.Int32Constant(0)));
1084    Stream s = m.Build();
1085    ASSERT_EQ(1U, s.size());
1086    EXPECT_EQ(kMipsCmp, s[0]->arch_opcode());
1087    EXPECT_EQ(kMode_None, s[0]->addressing_mode());
1088    ASSERT_EQ(2U, s[0]->InputCount());
1089    EXPECT_EQ(1U, s[0]->OutputCount());
1090    EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1091    EXPECT_EQ(kEqual, s[0]->flags_condition());
1092  }
1093  {
1094    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
1095    m.Return(m.Word32Equal(m.Int32Constant(0), m.Parameter(0)));
1096    Stream s = m.Build();
1097    ASSERT_EQ(1U, s.size());
1098    EXPECT_EQ(kMipsCmp, s[0]->arch_opcode());
1099    EXPECT_EQ(kMode_None, s[0]->addressing_mode());
1100    ASSERT_EQ(2U, s[0]->InputCount());
1101    EXPECT_EQ(1U, s[0]->OutputCount());
1102    EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1103    EXPECT_EQ(kEqual, s[0]->flags_condition());
1104  }
1105}
1106
1107
1108TEST_F(InstructionSelectorTest, Word32Clz) {
1109  StreamBuilder m(this, MachineType::Uint32(), MachineType::Uint32());
1110  Node* const p0 = m.Parameter(0);
1111  Node* const n = m.Word32Clz(p0);
1112  m.Return(n);
1113  Stream s = m.Build();
1114  ASSERT_EQ(1U, s.size());
1115  EXPECT_EQ(kMipsClz, s[0]->arch_opcode());
1116  ASSERT_EQ(1U, s[0]->InputCount());
1117  EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1118  ASSERT_EQ(1U, s[0]->OutputCount());
1119  EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1120}
1121
1122
1123TEST_F(InstructionSelectorTest, Float32Abs) {
1124  StreamBuilder m(this, MachineType::Float32(), MachineType::Float32());
1125  Node* const p0 = m.Parameter(0);
1126  Node* const n = m.Float32Abs(p0);
1127  m.Return(n);
1128  Stream s = m.Build();
1129  ASSERT_EQ(1U, s.size());
1130  EXPECT_EQ(kMipsAbsS, s[0]->arch_opcode());
1131  ASSERT_EQ(1U, s[0]->InputCount());
1132  EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1133  ASSERT_EQ(1U, s[0]->OutputCount());
1134  EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1135}
1136
1137
1138TEST_F(InstructionSelectorTest, Float64Abs) {
1139  StreamBuilder m(this, MachineType::Float64(), MachineType::Float64());
1140  Node* const p0 = m.Parameter(0);
1141  Node* const n = m.Float64Abs(p0);
1142  m.Return(n);
1143  Stream s = m.Build();
1144  ASSERT_EQ(1U, s.size());
1145  EXPECT_EQ(kMipsAbsD, s[0]->arch_opcode());
1146  ASSERT_EQ(1U, s[0]->InputCount());
1147  EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1148  ASSERT_EQ(1U, s[0]->OutputCount());
1149  EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1150}
1151
1152
1153TEST_F(InstructionSelectorTest, Float32Max) {
1154  StreamBuilder m(this, MachineType::Float32(), MachineType::Float32(),
1155                  MachineType::Float32());
1156  Node* const p0 = m.Parameter(0);
1157  Node* const p1 = m.Parameter(1);
1158  Node* const n = m.Float32Max(p0, p1);
1159  m.Return(n);
1160  Stream s = m.Build();
1161  // Float32Max is `(b < a) ? a : b`.
1162  ASSERT_EQ(1U, s.size());
1163  EXPECT_EQ(kMipsFloat32Max, s[0]->arch_opcode());
1164  ASSERT_EQ(2U, s[0]->InputCount());
1165  ASSERT_EQ(1U, s[0]->OutputCount());
1166  EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1167}
1168
1169
1170TEST_F(InstructionSelectorTest, Float32Min) {
1171  StreamBuilder m(this, MachineType::Float32(), MachineType::Float32(),
1172                  MachineType::Float32());
1173  Node* const p0 = m.Parameter(0);
1174  Node* const p1 = m.Parameter(1);
1175  Node* const n = m.Float32Min(p0, p1);
1176  m.Return(n);
1177  Stream s = m.Build();
1178  // Float32Min is `(a < b) ? a : b`.
1179  ASSERT_EQ(1U, s.size());
1180  EXPECT_EQ(kMipsFloat32Min, s[0]->arch_opcode());
1181  ASSERT_EQ(2U, s[0]->InputCount());
1182  ASSERT_EQ(1U, s[0]->OutputCount());
1183  EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1184}
1185
1186
1187TEST_F(InstructionSelectorTest, Float64Max) {
1188  StreamBuilder m(this, MachineType::Float64(), MachineType::Float64(),
1189                  MachineType::Float64());
1190  Node* const p0 = m.Parameter(0);
1191  Node* const p1 = m.Parameter(1);
1192  Node* const n = m.Float64Max(p0, p1);
1193  m.Return(n);
1194  Stream s = m.Build();
1195  // Float64Max is `(b < a) ? a : b`.
1196  ASSERT_EQ(1U, s.size());
1197  EXPECT_EQ(kMipsFloat64Max, s[0]->arch_opcode());
1198  ASSERT_EQ(2U, s[0]->InputCount());
1199  ASSERT_EQ(1U, s[0]->OutputCount());
1200  EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1201}
1202
1203
1204TEST_F(InstructionSelectorTest, Float64Min) {
1205  StreamBuilder m(this, MachineType::Float64(), MachineType::Float64(),
1206                  MachineType::Float64());
1207  Node* const p0 = m.Parameter(0);
1208  Node* const p1 = m.Parameter(1);
1209  Node* const n = m.Float64Min(p0, p1);
1210  m.Return(n);
1211  Stream s = m.Build();
1212  // Float64Min is `(a < b) ? a : b`.
1213  ASSERT_EQ(1U, s.size());
1214  EXPECT_EQ(kMipsFloat64Min, s[0]->arch_opcode());
1215  ASSERT_EQ(2U, s[0]->InputCount());
1216  ASSERT_EQ(1U, s[0]->OutputCount());
1217  EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1218}
1219
1220
1221}  // namespace compiler
1222}  // namespace internal
1223}  // namespace v8
1224