• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 template <typename T>
13 struct MachInst {
14   T constructor;
15   const char* constructor_name;
16   ArchOpcode arch_opcode;
17   MachineType machine_type;
18 };
19 
20 template <typename T>
operator <<(std::ostream & os,const MachInst<T> & mi)21 std::ostream& operator<<(std::ostream& os, const MachInst<T>& mi) {
22   return os << mi.constructor_name;
23 }
24 
25 typedef MachInst<Node* (RawMachineAssembler::*)(Node*)> MachInst1;
26 typedef MachInst<Node* (RawMachineAssembler::*)(Node*, Node*)> MachInst2;
27 
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.
32 struct IntCmp {
33   MachInst2 mi;
34   uint32_t expected_size;
35 };
36 
37 struct FPCmp {
38   MachInst2 mi;
39   FlagsCondition cond;
40 };
41 
42 const FPCmp kFPCmpInstructions[] = {
43     {{&RawMachineAssembler::Float64Equal, "Float64Equal", kMips64CmpD,
44       MachineType::Float64()},
45      kEqual},
46     {{&RawMachineAssembler::Float64LessThan, "Float64LessThan", kMips64CmpD,
47       MachineType::Float64()},
48      kUnsignedLessThan},
49     {{&RawMachineAssembler::Float64LessThanOrEqual, "Float64LessThanOrEqual",
50       kMips64CmpD, MachineType::Float64()},
51      kUnsignedLessThanOrEqual},
52     {{&RawMachineAssembler::Float64GreaterThan, "Float64GreaterThan",
53       kMips64CmpD, MachineType::Float64()},
54      kUnsignedLessThan},
55     {{&RawMachineAssembler::Float64GreaterThanOrEqual,
56       "Float64GreaterThanOrEqual", kMips64CmpD, MachineType::Float64()},
57      kUnsignedLessThanOrEqual}};
58 
59 struct 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 
71 const MachInst2 kLogicalInstructions[] = {
72     {&RawMachineAssembler::Word32And, "Word32And", kMips64And,
73      MachineType::Int32()},
74     {&RawMachineAssembler::Word64And, "Word64And", kMips64And,
75      MachineType::Int64()},
76     {&RawMachineAssembler::Word32Or, "Word32Or", kMips64Or,
77      MachineType::Int32()},
78     {&RawMachineAssembler::Word64Or, "Word64Or", kMips64Or,
79      MachineType::Int64()},
80     {&RawMachineAssembler::Word32Xor, "Word32Xor", kMips64Xor,
81      MachineType::Int32()},
82     {&RawMachineAssembler::Word64Xor, "Word64Xor", kMips64Xor,
83      MachineType::Int64()}};
84 
85 
86 // ----------------------------------------------------------------------------
87 // Shift instructions.
88 // ----------------------------------------------------------------------------
89 
90 
91 const MachInst2 kShiftInstructions[] = {
92     {&RawMachineAssembler::Word32Shl, "Word32Shl", kMips64Shl,
93      MachineType::Int32()},
94     {&RawMachineAssembler::Word64Shl, "Word64Shl", kMips64Dshl,
95      MachineType::Int64()},
96     {&RawMachineAssembler::Word32Shr, "Word32Shr", kMips64Shr,
97      MachineType::Int32()},
98     {&RawMachineAssembler::Word64Shr, "Word64Shr", kMips64Dshr,
99      MachineType::Int64()},
100     {&RawMachineAssembler::Word32Sar, "Word32Sar", kMips64Sar,
101      MachineType::Int32()},
102     {&RawMachineAssembler::Word64Sar, "Word64Sar", kMips64Dsar,
103      MachineType::Int64()},
104     {&RawMachineAssembler::Word32Ror, "Word32Ror", kMips64Ror,
105      MachineType::Int32()},
106     {&RawMachineAssembler::Word64Ror, "Word64Ror", kMips64Dror,
107      MachineType::Int64()}};
108 
109 
110 // ----------------------------------------------------------------------------
111 // MUL/DIV instructions.
112 // ----------------------------------------------------------------------------
113 
114 
115 const MachInst2 kMulDivInstructions[] = {
116     {&RawMachineAssembler::Int32Mul, "Int32Mul", kMips64Mul,
117      MachineType::Int32()},
118     {&RawMachineAssembler::Int32Div, "Int32Div", kMips64Div,
119      MachineType::Int32()},
120     {&RawMachineAssembler::Uint32Div, "Uint32Div", kMips64DivU,
121      MachineType::Uint32()},
122     {&RawMachineAssembler::Int64Mul, "Int64Mul", kMips64Dmul,
123      MachineType::Int64()},
124     {&RawMachineAssembler::Int64Div, "Int64Div", kMips64Ddiv,
125      MachineType::Int64()},
126     {&RawMachineAssembler::Uint64Div, "Uint64Div", kMips64DdivU,
127      MachineType::Uint64()},
128     {&RawMachineAssembler::Float64Mul, "Float64Mul", kMips64MulD,
129      MachineType::Float64()},
130     {&RawMachineAssembler::Float64Div, "Float64Div", kMips64DivD,
131      MachineType::Float64()}};
132 
133 
134 // ----------------------------------------------------------------------------
135 // MOD instructions.
136 // ----------------------------------------------------------------------------
137 
138 
139 const MachInst2 kModInstructions[] = {
140     {&RawMachineAssembler::Int32Mod, "Int32Mod", kMips64Mod,
141      MachineType::Int32()},
142     {&RawMachineAssembler::Uint32Mod, "Uint32Mod", kMips64ModU,
143      MachineType::Int32()},
144     {&RawMachineAssembler::Float64Mod, "Float64Mod", kMips64ModD,
145      MachineType::Float64()}};
146 
147 
148 // ----------------------------------------------------------------------------
149 // Arithmetic FPU instructions.
150 // ----------------------------------------------------------------------------
151 
152 
153 const MachInst2 kFPArithInstructions[] = {
154     {&RawMachineAssembler::Float64Add, "Float64Add", kMips64AddD,
155      MachineType::Float64()},
156     {&RawMachineAssembler::Float64Sub, "Float64Sub", kMips64SubD,
157      MachineType::Float64()}};
158 
159 
160 // ----------------------------------------------------------------------------
161 // IntArithTest instructions, two nodes.
162 // ----------------------------------------------------------------------------
163 
164 
165 const MachInst2 kAddSubInstructions[] = {
166     {&RawMachineAssembler::Int32Add, "Int32Add", kMips64Add,
167      MachineType::Int32()},
168     {&RawMachineAssembler::Int64Add, "Int64Add", kMips64Dadd,
169      MachineType::Int64()},
170     {&RawMachineAssembler::Int32Sub, "Int32Sub", kMips64Sub,
171      MachineType::Int32()},
172     {&RawMachineAssembler::Int64Sub, "Int64Sub", kMips64Dsub,
173      MachineType::Int64()}};
174 
175 
176 // ----------------------------------------------------------------------------
177 // IntArithTest instructions, one node.
178 // ----------------------------------------------------------------------------
179 
180 
181 const MachInst1 kAddSubOneInstructions[] = {
182     {&RawMachineAssembler::Int32Neg, "Int32Neg", kMips64Sub,
183      MachineType::Int32()},
184     {&RawMachineAssembler::Int64Neg, "Int64Neg", kMips64Dsub,
185      MachineType::Int64()}};
186 
187 
188 // ----------------------------------------------------------------------------
189 // Arithmetic compare instructions.
190 // ----------------------------------------------------------------------------
191 
192 
193 const IntCmp kCmpInstructions[] = {
194     {{&RawMachineAssembler::WordEqual, "WordEqual", kMips64Cmp,
195       MachineType::Int64()},
196      1U},
197     {{&RawMachineAssembler::WordNotEqual, "WordNotEqual", kMips64Cmp,
198       MachineType::Int64()},
199      1U},
200     {{&RawMachineAssembler::Word32Equal, "Word32Equal", kMips64Cmp,
201       MachineType::Int32()},
202      1U},
203     {{&RawMachineAssembler::Word32NotEqual, "Word32NotEqual", kMips64Cmp,
204       MachineType::Int32()},
205      1U},
206     {{&RawMachineAssembler::Int32LessThan, "Int32LessThan", kMips64Cmp,
207       MachineType::Int32()},
208      1U},
209     {{&RawMachineAssembler::Int32LessThanOrEqual, "Int32LessThanOrEqual",
210       kMips64Cmp, MachineType::Int32()},
211      1U},
212     {{&RawMachineAssembler::Int32GreaterThan, "Int32GreaterThan", kMips64Cmp,
213       MachineType::Int32()},
214      1U},
215     {{&RawMachineAssembler::Int32GreaterThanOrEqual, "Int32GreaterThanOrEqual",
216       kMips64Cmp, MachineType::Int32()},
217      1U},
218     {{&RawMachineAssembler::Uint32LessThan, "Uint32LessThan", kMips64Cmp,
219       MachineType::Uint32()},
220      1U},
221     {{&RawMachineAssembler::Uint32LessThanOrEqual, "Uint32LessThanOrEqual",
222       kMips64Cmp, MachineType::Uint32()},
223      1U}};
224 
225 
226 // ----------------------------------------------------------------------------
227 // Conversion instructions.
228 // ----------------------------------------------------------------------------
229 
230 const Conversion kConversionInstructions[] = {
231     // Conversion instructions are related to machine_operator.h:
232     // FPU conversions:
233     // Convert representation of integers between float64 and int32/uint32.
234     // The precise rounding mode and handling of out of range inputs are *not*
235     // defined for these operators, since they are intended only for use with
236     // integers.
237     // mips instructions:
238     // mtc1, cvt.d.w
239     {{&RawMachineAssembler::ChangeInt32ToFloat64, "ChangeInt32ToFloat64",
240       kMips64CvtDW, MachineType::Float64()},
241      MachineType::Int32()},
242 
243     // mips instructions:
244     // cvt.d.uw
245     {{&RawMachineAssembler::ChangeUint32ToFloat64, "ChangeUint32ToFloat64",
246       kMips64CvtDUw, MachineType::Float64()},
247      MachineType::Int32()},
248 
249     // mips instructions:
250     // mfc1, trunc double to word, for more details look at mips macro
251     // asm and mips asm file
252     {{&RawMachineAssembler::ChangeFloat64ToInt32, "ChangeFloat64ToInt32",
253       kMips64TruncWD, MachineType::Float64()},
254      MachineType::Int32()},
255 
256     // mips instructions:
257     // trunc double to unsigned word, for more details look at mips macro
258     // asm and mips asm file
259     {{&RawMachineAssembler::ChangeFloat64ToUint32, "ChangeFloat64ToUint32",
260       kMips64TruncUwD, MachineType::Float64()},
261      MachineType::Int32()}};
262 
263 const Conversion kFloat64RoundInstructions[] = {
264     {{&RawMachineAssembler::Float64RoundUp, "Float64RoundUp", kMips64CeilWD,
265       MachineType::Int32()},
266      MachineType::Float64()},
267     {{&RawMachineAssembler::Float64RoundDown, "Float64RoundDown",
268       kMips64FloorWD, MachineType::Int32()},
269      MachineType::Float64()},
270     {{&RawMachineAssembler::Float64RoundTiesEven, "Float64RoundTiesEven",
271       kMips64RoundWD, MachineType::Int32()},
272      MachineType::Float64()},
273     {{&RawMachineAssembler::Float64RoundTruncate, "Float64RoundTruncate",
274       kMips64TruncWD, MachineType::Int32()},
275      MachineType::Float64()}};
276 
277 const Conversion kFloat32RoundInstructions[] = {
278     {{&RawMachineAssembler::Float32RoundUp, "Float32RoundUp", kMips64CeilWS,
279       MachineType::Int32()},
280      MachineType::Float32()},
281     {{&RawMachineAssembler::Float32RoundDown, "Float32RoundDown",
282       kMips64FloorWS, MachineType::Int32()},
283      MachineType::Float32()},
284     {{&RawMachineAssembler::Float32RoundTiesEven, "Float32RoundTiesEven",
285       kMips64RoundWS, MachineType::Int32()},
286      MachineType::Float32()},
287     {{&RawMachineAssembler::Float32RoundTruncate, "Float32RoundTruncate",
288       kMips64TruncWS, MachineType::Int32()},
289      MachineType::Float32()}};
290 
291 }  // namespace
292 
293 
294 typedef InstructionSelectorTestWithParam<FPCmp> InstructionSelectorFPCmpTest;
295 
TEST_P(InstructionSelectorFPCmpTest,Parameter)296 TEST_P(InstructionSelectorFPCmpTest, Parameter) {
297   const FPCmp cmp = GetParam();
298   StreamBuilder m(this, MachineType::Int32(), cmp.mi.machine_type,
299                   cmp.mi.machine_type);
300   m.Return((m.*cmp.mi.constructor)(m.Parameter(0), m.Parameter(1)));
301   Stream s = m.Build();
302   ASSERT_EQ(1U, s.size());
303   EXPECT_EQ(cmp.mi.arch_opcode, s[0]->arch_opcode());
304   EXPECT_EQ(2U, s[0]->InputCount());
305   EXPECT_EQ(1U, s[0]->OutputCount());
306   EXPECT_EQ(kFlags_set, s[0]->flags_mode());
307   EXPECT_EQ(cmp.cond, s[0]->flags_condition());
308 }
309 
310 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorFPCmpTest,
311                         ::testing::ValuesIn(kFPCmpInstructions));
312 
313 // ----------------------------------------------------------------------------
314 // Arithmetic compare instructions integers
315 // ----------------------------------------------------------------------------
316 typedef InstructionSelectorTestWithParam<IntCmp> InstructionSelectorCmpTest;
317 
318 
TEST_P(InstructionSelectorCmpTest,Parameter)319 TEST_P(InstructionSelectorCmpTest, Parameter) {
320   const IntCmp cmp = GetParam();
321   const MachineType type = cmp.mi.machine_type;
322   StreamBuilder m(this, type, type, type);
323   m.Return((m.*cmp.mi.constructor)(m.Parameter(0), m.Parameter(1)));
324   Stream s = m.Build();
325   ASSERT_EQ(cmp.expected_size, s.size());
326   EXPECT_EQ(cmp.mi.arch_opcode, s[0]->arch_opcode());
327   EXPECT_EQ(2U, s[0]->InputCount());
328   EXPECT_EQ(1U, s[0]->OutputCount());
329 }
330 
331 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorCmpTest,
332                         ::testing::ValuesIn(kCmpInstructions));
333 
334 // ----------------------------------------------------------------------------
335 // Shift instructions.
336 // ----------------------------------------------------------------------------
337 typedef InstructionSelectorTestWithParam<MachInst2>
338     InstructionSelectorShiftTest;
339 
TEST_P(InstructionSelectorShiftTest,Immediate)340 TEST_P(InstructionSelectorShiftTest, Immediate) {
341   const MachInst2 dpi = GetParam();
342   const MachineType type = dpi.machine_type;
343   TRACED_FORRANGE(int32_t, imm, 0,
344                   ((1 << ElementSizeLog2Of(type.representation())) * 8) - 1) {
345     StreamBuilder m(this, type, type);
346     m.Return((m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm)));
347     Stream s = m.Build();
348     ASSERT_EQ(1U, s.size());
349     EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
350     EXPECT_EQ(2U, s[0]->InputCount());
351     EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
352     EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
353     EXPECT_EQ(1U, s[0]->OutputCount());
354   }
355 }
356 
357 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorShiftTest,
358                         ::testing::ValuesIn(kShiftInstructions));
359 
TEST_F(InstructionSelectorTest,Word32ShrWithWord32AndWithImmediate)360 TEST_F(InstructionSelectorTest, Word32ShrWithWord32AndWithImmediate) {
361   // The available shift operand range is `0 <= imm < 32`, but we also test
362   // that immediates outside this range are handled properly (modulo-32).
363   TRACED_FORRANGE(int32_t, shift, -32, 63) {
364     int32_t lsb = shift & 0x1f;
365     TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) {
366       uint32_t jnk = rng()->NextInt();
367       jnk = (lsb > 0) ? (jnk >> (32 - lsb)) : 0;
368       uint32_t msk = ((0xffffffffu >> (32 - width)) << lsb) | jnk;
369       StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
370       m.Return(m.Word32Shr(m.Word32And(m.Parameter(0), m.Int32Constant(msk)),
371                            m.Int32Constant(shift)));
372       Stream s = m.Build();
373       ASSERT_EQ(1U, s.size());
374       EXPECT_EQ(kMips64Ext, s[0]->arch_opcode());
375       ASSERT_EQ(3U, s[0]->InputCount());
376       EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
377       EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
378     }
379   }
380   TRACED_FORRANGE(int32_t, shift, -32, 63) {
381     int32_t lsb = shift & 0x1f;
382     TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) {
383       uint32_t jnk = rng()->NextInt();
384       jnk = (lsb > 0) ? (jnk >> (32 - lsb)) : 0;
385       uint32_t msk = ((0xffffffffu >> (32 - width)) << lsb) | jnk;
386       StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
387       m.Return(m.Word32Shr(m.Word32And(m.Int32Constant(msk), m.Parameter(0)),
388                            m.Int32Constant(shift)));
389       Stream s = m.Build();
390       ASSERT_EQ(1U, s.size());
391       EXPECT_EQ(kMips64Ext, s[0]->arch_opcode());
392       ASSERT_EQ(3U, s[0]->InputCount());
393       EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
394       EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
395     }
396   }
397 }
398 
399 
TEST_F(InstructionSelectorTest,Word64ShrWithWord64AndWithImmediate)400 TEST_F(InstructionSelectorTest, Word64ShrWithWord64AndWithImmediate) {
401   // The available shift operand range is `0 <= imm < 64`, but we also test
402   // that immediates outside this range are handled properly (modulo-64).
403   TRACED_FORRANGE(int32_t, shift, -64, 127) {
404     int32_t lsb = shift & 0x3f;
405     TRACED_FORRANGE(int32_t, width, 1, 64 - lsb) {
406       uint64_t jnk = rng()->NextInt64();
407       jnk = (lsb > 0) ? (jnk >> (64 - lsb)) : 0;
408       uint64_t msk =
409           ((V8_UINT64_C(0xffffffffffffffff) >> (64 - width)) << lsb) | jnk;
410       StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
411       m.Return(m.Word64Shr(m.Word64And(m.Parameter(0), m.Int64Constant(msk)),
412                            m.Int64Constant(shift)));
413       Stream s = m.Build();
414       ASSERT_EQ(1U, s.size());
415       EXPECT_EQ(kMips64Dext, s[0]->arch_opcode());
416       ASSERT_EQ(3U, s[0]->InputCount());
417       EXPECT_EQ(lsb, s.ToInt64(s[0]->InputAt(1)));
418       EXPECT_EQ(width, s.ToInt64(s[0]->InputAt(2)));
419     }
420   }
421   TRACED_FORRANGE(int32_t, shift, -64, 127) {
422     int32_t lsb = shift & 0x3f;
423     TRACED_FORRANGE(int32_t, width, 1, 64 - lsb) {
424       uint64_t jnk = rng()->NextInt64();
425       jnk = (lsb > 0) ? (jnk >> (64 - lsb)) : 0;
426       uint64_t msk =
427           ((V8_UINT64_C(0xffffffffffffffff) >> (64 - width)) << lsb) | jnk;
428       StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
429       m.Return(m.Word64Shr(m.Word64And(m.Int64Constant(msk), m.Parameter(0)),
430                            m.Int64Constant(shift)));
431       Stream s = m.Build();
432       ASSERT_EQ(1U, s.size());
433       EXPECT_EQ(kMips64Dext, s[0]->arch_opcode());
434       ASSERT_EQ(3U, s[0]->InputCount());
435       EXPECT_EQ(lsb, s.ToInt64(s[0]->InputAt(1)));
436       EXPECT_EQ(width, s.ToInt64(s[0]->InputAt(2)));
437     }
438   }
439 }
440 
441 
TEST_F(InstructionSelectorTest,Word32AndToClearBits)442 TEST_F(InstructionSelectorTest, Word32AndToClearBits) {
443   TRACED_FORRANGE(int32_t, shift, 1, 31) {
444     int32_t mask = ~((1 << shift) - 1);
445     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
446     m.Return(m.Word32And(m.Parameter(0), m.Int32Constant(mask)));
447     Stream s = m.Build();
448     ASSERT_EQ(1U, s.size());
449     EXPECT_EQ(kMips64Ins, s[0]->arch_opcode());
450     ASSERT_EQ(3U, s[0]->InputCount());
451     EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1)));
452     EXPECT_EQ(shift, s.ToInt32(s[0]->InputAt(2)));
453   }
454   TRACED_FORRANGE(int32_t, shift, 1, 31) {
455     int32_t mask = ~((1 << shift) - 1);
456     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
457     m.Return(m.Word32And(m.Int32Constant(mask), m.Parameter(0)));
458     Stream s = m.Build();
459     ASSERT_EQ(1U, s.size());
460     EXPECT_EQ(kMips64Ins, s[0]->arch_opcode());
461     ASSERT_EQ(3U, s[0]->InputCount());
462     EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1)));
463     EXPECT_EQ(shift, s.ToInt32(s[0]->InputAt(2)));
464   }
465 }
466 
467 
TEST_F(InstructionSelectorTest,Word64AndToClearBits)468 TEST_F(InstructionSelectorTest, Word64AndToClearBits) {
469   TRACED_FORRANGE(int32_t, shift, 1, 31) {
470     int64_t mask = ~((1 << shift) - 1);
471     StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
472     m.Return(m.Word64And(m.Parameter(0), m.Int64Constant(mask)));
473     Stream s = m.Build();
474     ASSERT_EQ(1U, s.size());
475     EXPECT_EQ(kMips64Dins, s[0]->arch_opcode());
476     ASSERT_EQ(3U, s[0]->InputCount());
477     EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1)));
478     EXPECT_EQ(shift, s.ToInt32(s[0]->InputAt(2)));
479   }
480   TRACED_FORRANGE(int32_t, shift, 1, 31) {
481     int64_t mask = ~((1 << shift) - 1);
482     StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
483     m.Return(m.Word64And(m.Int64Constant(mask), m.Parameter(0)));
484     Stream s = m.Build();
485     ASSERT_EQ(1U, s.size());
486     EXPECT_EQ(kMips64Dins, s[0]->arch_opcode());
487     ASSERT_EQ(3U, s[0]->InputCount());
488     EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1)));
489     EXPECT_EQ(shift, s.ToInt32(s[0]->InputAt(2)));
490   }
491 }
492 
493 
494 // ----------------------------------------------------------------------------
495 // Logical instructions.
496 // ----------------------------------------------------------------------------
497 typedef InstructionSelectorTestWithParam<MachInst2>
498     InstructionSelectorLogicalTest;
499 
500 
TEST_P(InstructionSelectorLogicalTest,Parameter)501 TEST_P(InstructionSelectorLogicalTest, Parameter) {
502   const MachInst2 dpi = GetParam();
503   const MachineType type = dpi.machine_type;
504   StreamBuilder m(this, type, type, type);
505   m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)));
506   Stream s = m.Build();
507   ASSERT_EQ(1U, s.size());
508   EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
509   EXPECT_EQ(2U, s[0]->InputCount());
510   EXPECT_EQ(1U, s[0]->OutputCount());
511 }
512 
513 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorLogicalTest,
514                         ::testing::ValuesIn(kLogicalInstructions));
515 
516 
TEST_F(InstructionSelectorTest,Word64XorMinusOneWithParameter)517 TEST_F(InstructionSelectorTest, Word64XorMinusOneWithParameter) {
518   {
519     StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
520     m.Return(m.Word64Xor(m.Parameter(0), m.Int64Constant(-1)));
521     Stream s = m.Build();
522     ASSERT_EQ(1U, s.size());
523     EXPECT_EQ(kMips64Nor, s[0]->arch_opcode());
524     EXPECT_EQ(2U, s[0]->InputCount());
525     EXPECT_EQ(1U, s[0]->OutputCount());
526   }
527   {
528     StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
529     m.Return(m.Word64Xor(m.Int64Constant(-1), m.Parameter(0)));
530     Stream s = m.Build();
531     ASSERT_EQ(1U, s.size());
532     EXPECT_EQ(kMips64Nor, s[0]->arch_opcode());
533     EXPECT_EQ(2U, s[0]->InputCount());
534     EXPECT_EQ(1U, s[0]->OutputCount());
535   }
536 }
537 
538 
TEST_F(InstructionSelectorTest,Word32XorMinusOneWithParameter)539 TEST_F(InstructionSelectorTest, Word32XorMinusOneWithParameter) {
540   {
541     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
542     m.Return(m.Word32Xor(m.Parameter(0), m.Int32Constant(-1)));
543     Stream s = m.Build();
544     ASSERT_EQ(1U, s.size());
545     EXPECT_EQ(kMips64Nor, s[0]->arch_opcode());
546     EXPECT_EQ(2U, s[0]->InputCount());
547     EXPECT_EQ(1U, s[0]->OutputCount());
548   }
549   {
550     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
551     m.Return(m.Word32Xor(m.Int32Constant(-1), m.Parameter(0)));
552     Stream s = m.Build();
553     ASSERT_EQ(1U, s.size());
554     EXPECT_EQ(kMips64Nor, s[0]->arch_opcode());
555     EXPECT_EQ(2U, s[0]->InputCount());
556     EXPECT_EQ(1U, s[0]->OutputCount());
557   }
558 }
559 
560 
TEST_F(InstructionSelectorTest,Word64XorMinusOneWithWord64Or)561 TEST_F(InstructionSelectorTest, Word64XorMinusOneWithWord64Or) {
562   {
563     StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
564     m.Return(m.Word64Xor(m.Word64Or(m.Parameter(0), m.Parameter(0)),
565                          m.Int64Constant(-1)));
566     Stream s = m.Build();
567     ASSERT_EQ(1U, s.size());
568     EXPECT_EQ(kMips64Nor, s[0]->arch_opcode());
569     EXPECT_EQ(2U, s[0]->InputCount());
570     EXPECT_EQ(1U, s[0]->OutputCount());
571   }
572   {
573     StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
574     m.Return(m.Word64Xor(m.Int64Constant(-1),
575                          m.Word64Or(m.Parameter(0), m.Parameter(0))));
576     Stream s = m.Build();
577     ASSERT_EQ(1U, s.size());
578     EXPECT_EQ(kMips64Nor, s[0]->arch_opcode());
579     EXPECT_EQ(2U, s[0]->InputCount());
580     EXPECT_EQ(1U, s[0]->OutputCount());
581   }
582 }
583 
584 
TEST_F(InstructionSelectorTest,Word32XorMinusOneWithWord32Or)585 TEST_F(InstructionSelectorTest, Word32XorMinusOneWithWord32Or) {
586   {
587     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
588     m.Return(m.Word32Xor(m.Word32Or(m.Parameter(0), m.Parameter(0)),
589                          m.Int32Constant(-1)));
590     Stream s = m.Build();
591     ASSERT_EQ(1U, s.size());
592     EXPECT_EQ(kMips64Nor, s[0]->arch_opcode());
593     EXPECT_EQ(2U, s[0]->InputCount());
594     EXPECT_EQ(1U, s[0]->OutputCount());
595   }
596   {
597     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
598     m.Return(m.Word32Xor(m.Int32Constant(-1),
599                          m.Word32Or(m.Parameter(0), m.Parameter(0))));
600     Stream s = m.Build();
601     ASSERT_EQ(1U, s.size());
602     EXPECT_EQ(kMips64Nor, s[0]->arch_opcode());
603     EXPECT_EQ(2U, s[0]->InputCount());
604     EXPECT_EQ(1U, s[0]->OutputCount());
605   }
606 }
607 
608 
TEST_F(InstructionSelectorTest,Word32AndWithImmediateWithWord32Shr)609 TEST_F(InstructionSelectorTest, Word32AndWithImmediateWithWord32Shr) {
610   // The available shift operand range is `0 <= imm < 32`, but we also test
611   // that immediates outside this range are handled properly (modulo-32).
612   TRACED_FORRANGE(int32_t, shift, -32, 63) {
613     int32_t lsb = shift & 0x1f;
614     TRACED_FORRANGE(int32_t, width, 1, 31) {
615       uint32_t msk = (1 << width) - 1;
616       StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
617       m.Return(m.Word32And(m.Word32Shr(m.Parameter(0), m.Int32Constant(shift)),
618                            m.Int32Constant(msk)));
619       Stream s = m.Build();
620       ASSERT_EQ(1U, s.size());
621       EXPECT_EQ(kMips64Ext, s[0]->arch_opcode());
622       ASSERT_EQ(3U, s[0]->InputCount());
623       EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
624       int32_t actual_width = (lsb + width > 32) ? (32 - lsb) : width;
625       EXPECT_EQ(actual_width, s.ToInt32(s[0]->InputAt(2)));
626     }
627   }
628   TRACED_FORRANGE(int32_t, shift, -32, 63) {
629     int32_t lsb = shift & 0x1f;
630     TRACED_FORRANGE(int32_t, width, 1, 31) {
631       uint32_t msk = (1 << width) - 1;
632       StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
633       m.Return(
634           m.Word32And(m.Int32Constant(msk),
635                       m.Word32Shr(m.Parameter(0), m.Int32Constant(shift))));
636       Stream s = m.Build();
637       ASSERT_EQ(1U, s.size());
638       EXPECT_EQ(kMips64Ext, s[0]->arch_opcode());
639       ASSERT_EQ(3U, s[0]->InputCount());
640       EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
641       int32_t actual_width = (lsb + width > 32) ? (32 - lsb) : width;
642       EXPECT_EQ(actual_width, s.ToInt32(s[0]->InputAt(2)));
643     }
644   }
645 }
646 
647 
TEST_F(InstructionSelectorTest,Word64AndWithImmediateWithWord64Shr)648 TEST_F(InstructionSelectorTest, Word64AndWithImmediateWithWord64Shr) {
649   // The available shift operand range is `0 <= imm < 64`, but we also test
650   // that immediates outside this range are handled properly (modulo-64).
651   TRACED_FORRANGE(int64_t, shift, -64, 127) {
652     int64_t lsb = shift & 0x3f;
653     TRACED_FORRANGE(int64_t, width, 1, 63) {
654       uint64_t msk = (V8_UINT64_C(1) << width) - 1;
655       StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
656       m.Return(m.Word64And(m.Word64Shr(m.Parameter(0), m.Int64Constant(shift)),
657                            m.Int64Constant(msk)));
658       Stream s = m.Build();
659       ASSERT_EQ(1U, s.size());
660       EXPECT_EQ(kMips64Dext, s[0]->arch_opcode());
661       ASSERT_EQ(3U, s[0]->InputCount());
662       EXPECT_EQ(lsb, s.ToInt64(s[0]->InputAt(1)));
663       int64_t actual_width = (lsb + width > 64) ? (64 - lsb) : width;
664       EXPECT_EQ(actual_width, s.ToInt64(s[0]->InputAt(2)));
665     }
666   }
667   TRACED_FORRANGE(int64_t, shift, -64, 127) {
668     int64_t lsb = shift & 0x3f;
669     TRACED_FORRANGE(int64_t, width, 1, 63) {
670       uint64_t msk = (V8_UINT64_C(1) << width) - 1;
671       StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
672       m.Return(
673           m.Word64And(m.Int64Constant(msk),
674                       m.Word64Shr(m.Parameter(0), m.Int64Constant(shift))));
675       Stream s = m.Build();
676       ASSERT_EQ(1U, s.size());
677       EXPECT_EQ(kMips64Dext, s[0]->arch_opcode());
678       ASSERT_EQ(3U, s[0]->InputCount());
679       EXPECT_EQ(lsb, s.ToInt64(s[0]->InputAt(1)));
680       int64_t actual_width = (lsb + width > 64) ? (64 - lsb) : width;
681       EXPECT_EQ(actual_width, s.ToInt64(s[0]->InputAt(2)));
682     }
683   }
684 }
685 
686 
TEST_F(InstructionSelectorTest,Word32ShlWithWord32And)687 TEST_F(InstructionSelectorTest, Word32ShlWithWord32And) {
688   TRACED_FORRANGE(int32_t, shift, 0, 30) {
689     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
690     Node* const p0 = m.Parameter(0);
691     Node* const r =
692         m.Word32Shl(m.Word32And(p0, m.Int32Constant((1 << (31 - shift)) - 1)),
693                     m.Int32Constant(shift + 1));
694     m.Return(r);
695     Stream s = m.Build();
696     ASSERT_EQ(1U, s.size());
697     EXPECT_EQ(kMips64Shl, s[0]->arch_opcode());
698     ASSERT_EQ(2U, s[0]->InputCount());
699     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
700     ASSERT_EQ(1U, s[0]->OutputCount());
701     EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
702   }
703 }
704 
705 
TEST_F(InstructionSelectorTest,Word64ShlWithWord64And)706 TEST_F(InstructionSelectorTest, Word64ShlWithWord64And) {
707   TRACED_FORRANGE(int32_t, shift, 0, 62) {
708     StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
709     Node* const p0 = m.Parameter(0);
710     Node* const r =
711         m.Word64Shl(m.Word64And(p0, m.Int64Constant((1L << (63 - shift)) - 1)),
712                     m.Int64Constant(shift + 1));
713     m.Return(r);
714     Stream s = m.Build();
715     ASSERT_EQ(1U, s.size());
716     EXPECT_EQ(kMips64Dshl, s[0]->arch_opcode());
717     ASSERT_EQ(2U, s[0]->InputCount());
718     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
719     ASSERT_EQ(1U, s[0]->OutputCount());
720     EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
721   }
722 }
723 
724 
725 // ----------------------------------------------------------------------------
726 // MUL/DIV instructions.
727 // ----------------------------------------------------------------------------
728 typedef InstructionSelectorTestWithParam<MachInst2>
729     InstructionSelectorMulDivTest;
730 
TEST_P(InstructionSelectorMulDivTest,Parameter)731 TEST_P(InstructionSelectorMulDivTest, Parameter) {
732   const MachInst2 dpi = GetParam();
733   const MachineType type = dpi.machine_type;
734   StreamBuilder m(this, type, type, type);
735   m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)));
736   Stream s = m.Build();
737   ASSERT_EQ(1U, s.size());
738   EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
739   EXPECT_EQ(2U, s[0]->InputCount());
740   EXPECT_EQ(1U, s[0]->OutputCount());
741 }
742 
743 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorMulDivTest,
744                         ::testing::ValuesIn(kMulDivInstructions));
745 
746 // ----------------------------------------------------------------------------
747 // MOD instructions.
748 // ----------------------------------------------------------------------------
749 typedef InstructionSelectorTestWithParam<MachInst2> InstructionSelectorModTest;
750 
TEST_P(InstructionSelectorModTest,Parameter)751 TEST_P(InstructionSelectorModTest, Parameter) {
752   const MachInst2 dpi = GetParam();
753   const MachineType type = dpi.machine_type;
754   StreamBuilder m(this, type, type, type);
755   m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)));
756   Stream s = m.Build();
757   ASSERT_EQ(1U, s.size());
758   EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
759   EXPECT_EQ(2U, s[0]->InputCount());
760   EXPECT_EQ(1U, s[0]->OutputCount());
761 }
762 
763 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorModTest,
764                         ::testing::ValuesIn(kModInstructions));
765 
766 // ----------------------------------------------------------------------------
767 // Floating point instructions.
768 // ----------------------------------------------------------------------------
769 typedef InstructionSelectorTestWithParam<MachInst2>
770     InstructionSelectorFPArithTest;
771 
TEST_P(InstructionSelectorFPArithTest,Parameter)772 TEST_P(InstructionSelectorFPArithTest, Parameter) {
773   const MachInst2 fpa = GetParam();
774   StreamBuilder m(this, fpa.machine_type, fpa.machine_type, fpa.machine_type);
775   m.Return((m.*fpa.constructor)(m.Parameter(0), m.Parameter(1)));
776   Stream s = m.Build();
777   ASSERT_EQ(1U, s.size());
778   EXPECT_EQ(fpa.arch_opcode, s[0]->arch_opcode());
779   EXPECT_EQ(2U, s[0]->InputCount());
780   EXPECT_EQ(1U, s[0]->OutputCount());
781 }
782 
783 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorFPArithTest,
784                         ::testing::ValuesIn(kFPArithInstructions));
785 // ----------------------------------------------------------------------------
786 // Integer arithmetic
787 // ----------------------------------------------------------------------------
788 typedef InstructionSelectorTestWithParam<MachInst2>
789     InstructionSelectorIntArithTwoTest;
790 
TEST_P(InstructionSelectorIntArithTwoTest,Parameter)791 TEST_P(InstructionSelectorIntArithTwoTest, Parameter) {
792   const MachInst2 intpa = GetParam();
793   StreamBuilder m(this, intpa.machine_type, intpa.machine_type,
794                   intpa.machine_type);
795   m.Return((m.*intpa.constructor)(m.Parameter(0), m.Parameter(1)));
796   Stream s = m.Build();
797   ASSERT_EQ(1U, s.size());
798   EXPECT_EQ(intpa.arch_opcode, s[0]->arch_opcode());
799   EXPECT_EQ(2U, s[0]->InputCount());
800   EXPECT_EQ(1U, s[0]->OutputCount());
801 }
802 
803 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
804                         InstructionSelectorIntArithTwoTest,
805                         ::testing::ValuesIn(kAddSubInstructions));
806 
807 
808 // ----------------------------------------------------------------------------
809 // One node.
810 // ----------------------------------------------------------------------------
811 
812 
813 typedef InstructionSelectorTestWithParam<MachInst1>
814     InstructionSelectorIntArithOneTest;
815 
TEST_P(InstructionSelectorIntArithOneTest,Parameter)816 TEST_P(InstructionSelectorIntArithOneTest, Parameter) {
817   const MachInst1 intpa = GetParam();
818   StreamBuilder m(this, intpa.machine_type, intpa.machine_type,
819                   intpa.machine_type);
820   m.Return((m.*intpa.constructor)(m.Parameter(0)));
821   Stream s = m.Build();
822   ASSERT_EQ(1U, s.size());
823   EXPECT_EQ(intpa.arch_opcode, s[0]->arch_opcode());
824   EXPECT_EQ(2U, s[0]->InputCount());
825   EXPECT_EQ(1U, s[0]->OutputCount());
826 }
827 
828 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
829                         InstructionSelectorIntArithOneTest,
830                         ::testing::ValuesIn(kAddSubOneInstructions));
831 // ----------------------------------------------------------------------------
832 // Conversions.
833 // ----------------------------------------------------------------------------
834 typedef InstructionSelectorTestWithParam<Conversion>
835     InstructionSelectorConversionTest;
836 
TEST_P(InstructionSelectorConversionTest,Parameter)837 TEST_P(InstructionSelectorConversionTest, Parameter) {
838   const Conversion conv = GetParam();
839   StreamBuilder m(this, conv.mi.machine_type, conv.src_machine_type);
840   m.Return((m.*conv.mi.constructor)(m.Parameter(0)));
841   Stream s = m.Build();
842   ASSERT_EQ(1U, s.size());
843   EXPECT_EQ(conv.mi.arch_opcode, s[0]->arch_opcode());
844   EXPECT_EQ(1U, s[0]->InputCount());
845   EXPECT_EQ(1U, s[0]->OutputCount());
846 }
847 
848 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
849                         InstructionSelectorConversionTest,
850                         ::testing::ValuesIn(kConversionInstructions));
851 
TEST_F(InstructionSelectorTest,ChangesFromToSmi)852 TEST_F(InstructionSelectorTest, ChangesFromToSmi) {
853   {
854     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
855     m.Return(m.TruncateInt64ToInt32(
856         m.Word64Sar(m.Parameter(0), m.Int32Constant(32))));
857     Stream s = m.Build();
858     ASSERT_EQ(1U, s.size());
859     EXPECT_EQ(kMips64Dsar, s[0]->arch_opcode());
860     EXPECT_EQ(kMode_None, s[0]->addressing_mode());
861     ASSERT_EQ(2U, s[0]->InputCount());
862     EXPECT_EQ(1U, s[0]->OutputCount());
863   }
864   {
865     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
866     m.Return(
867         m.Word64Shl(m.ChangeInt32ToInt64(m.Parameter(0)), m.Int32Constant(32)));
868     Stream s = m.Build();
869     ASSERT_EQ(1U, s.size());
870     EXPECT_EQ(kMips64Dshl, s[0]->arch_opcode());
871     ASSERT_EQ(2U, s[0]->InputCount());
872     EXPECT_EQ(1U, s[0]->OutputCount());
873   }
874 }
875 
876 
877 typedef InstructionSelectorTestWithParam<Conversion>
878     CombineChangeFloat64ToInt32WithRoundFloat64;
879 
TEST_P(CombineChangeFloat64ToInt32WithRoundFloat64,Parameter)880 TEST_P(CombineChangeFloat64ToInt32WithRoundFloat64, Parameter) {
881   {
882     const Conversion conv = GetParam();
883     StreamBuilder m(this, conv.mi.machine_type, conv.src_machine_type);
884     m.Return(m.ChangeFloat64ToInt32((m.*conv.mi.constructor)(m.Parameter(0))));
885     Stream s = m.Build();
886     ASSERT_EQ(1U, s.size());
887     EXPECT_EQ(conv.mi.arch_opcode, s[0]->arch_opcode());
888     EXPECT_EQ(kMode_None, s[0]->addressing_mode());
889     ASSERT_EQ(1U, s[0]->InputCount());
890     EXPECT_EQ(1U, s[0]->OutputCount());
891   }
892 }
893 
894 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
895                         CombineChangeFloat64ToInt32WithRoundFloat64,
896                         ::testing::ValuesIn(kFloat64RoundInstructions));
897 
898 typedef InstructionSelectorTestWithParam<Conversion>
899     CombineChangeFloat32ToInt32WithRoundFloat32;
900 
TEST_P(CombineChangeFloat32ToInt32WithRoundFloat32,Parameter)901 TEST_P(CombineChangeFloat32ToInt32WithRoundFloat32, Parameter) {
902   {
903     const Conversion conv = GetParam();
904     StreamBuilder m(this, conv.mi.machine_type, conv.src_machine_type);
905     m.Return(m.ChangeFloat64ToInt32(
906         m.ChangeFloat32ToFloat64((m.*conv.mi.constructor)(m.Parameter(0)))));
907     Stream s = m.Build();
908     ASSERT_EQ(1U, s.size());
909     EXPECT_EQ(conv.mi.arch_opcode, s[0]->arch_opcode());
910     EXPECT_EQ(kMode_None, s[0]->addressing_mode());
911     ASSERT_EQ(1U, s[0]->InputCount());
912     EXPECT_EQ(1U, s[0]->OutputCount());
913   }
914 }
915 
916 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
917                         CombineChangeFloat32ToInt32WithRoundFloat32,
918                         ::testing::ValuesIn(kFloat32RoundInstructions));
919 
920 
TEST_F(InstructionSelectorTest,ChangeFloat64ToInt32OfChangeFloat32ToFloat64)921 TEST_F(InstructionSelectorTest, ChangeFloat64ToInt32OfChangeFloat32ToFloat64) {
922   {
923     StreamBuilder m(this, MachineType::Int32(), MachineType::Float32());
924     m.Return(m.ChangeFloat64ToInt32(m.ChangeFloat32ToFloat64(m.Parameter(0))));
925     Stream s = m.Build();
926     ASSERT_EQ(1U, s.size());
927     EXPECT_EQ(kMips64TruncWS, s[0]->arch_opcode());
928     EXPECT_EQ(kMode_None, s[0]->addressing_mode());
929     ASSERT_EQ(1U, s[0]->InputCount());
930     EXPECT_EQ(1U, s[0]->OutputCount());
931   }
932 }
933 
934 
TEST_F(InstructionSelectorTest,TruncateFloat64ToFloat32OfChangeInt32ToFloat64)935 TEST_F(InstructionSelectorTest,
936        TruncateFloat64ToFloat32OfChangeInt32ToFloat64) {
937   {
938     StreamBuilder m(this, MachineType::Float32(), MachineType::Int32());
939     m.Return(
940         m.TruncateFloat64ToFloat32(m.ChangeInt32ToFloat64(m.Parameter(0))));
941     Stream s = m.Build();
942     ASSERT_EQ(1U, s.size());
943     EXPECT_EQ(kMips64CvtSW, s[0]->arch_opcode());
944     EXPECT_EQ(kMode_None, s[0]->addressing_mode());
945     ASSERT_EQ(1U, s[0]->InputCount());
946     EXPECT_EQ(1U, s[0]->OutputCount());
947   }
948 }
949 
950 
TEST_F(InstructionSelectorTest,CombineShiftsWithMul)951 TEST_F(InstructionSelectorTest, CombineShiftsWithMul) {
952   {
953     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
954     m.Return(m.Int32Mul(m.Word64Sar(m.Parameter(0), m.Int32Constant(32)),
955                         m.Word64Sar(m.Parameter(0), m.Int32Constant(32))));
956     Stream s = m.Build();
957     ASSERT_EQ(1U, s.size());
958     EXPECT_EQ(kMips64DMulHigh, s[0]->arch_opcode());
959     EXPECT_EQ(kMode_None, s[0]->addressing_mode());
960     ASSERT_EQ(2U, s[0]->InputCount());
961     EXPECT_EQ(1U, s[0]->OutputCount());
962   }
963 }
964 
965 
TEST_F(InstructionSelectorTest,CombineShiftsWithDivMod)966 TEST_F(InstructionSelectorTest, CombineShiftsWithDivMod) {
967   {
968     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
969     m.Return(m.Int32Div(m.Word64Sar(m.Parameter(0), m.Int32Constant(32)),
970                         m.Word64Sar(m.Parameter(0), m.Int32Constant(32))));
971     Stream s = m.Build();
972     ASSERT_EQ(1U, s.size());
973     EXPECT_EQ(kMips64Ddiv, s[0]->arch_opcode());
974     EXPECT_EQ(kMode_None, s[0]->addressing_mode());
975     ASSERT_EQ(2U, s[0]->InputCount());
976     EXPECT_EQ(1U, s[0]->OutputCount());
977   }
978   {
979     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
980     m.Return(m.Int32Mod(m.Word64Sar(m.Parameter(0), m.Int32Constant(32)),
981                         m.Word64Sar(m.Parameter(0), m.Int32Constant(32))));
982     Stream s = m.Build();
983     ASSERT_EQ(1U, s.size());
984     EXPECT_EQ(kMips64Dmod, s[0]->arch_opcode());
985     EXPECT_EQ(kMode_None, s[0]->addressing_mode());
986     ASSERT_EQ(2U, s[0]->InputCount());
987     EXPECT_EQ(1U, s[0]->OutputCount());
988   }
989 }
990 
991 
992 // ----------------------------------------------------------------------------
993 // Loads and stores.
994 // ----------------------------------------------------------------------------
995 
996 
997 namespace {
998 
999 struct MemoryAccess {
1000   MachineType type;
1001   ArchOpcode load_opcode;
1002   ArchOpcode store_opcode;
1003 };
1004 
1005 static const MemoryAccess kMemoryAccesses[] = {
1006     {MachineType::Int8(), kMips64Lb, kMips64Sb},
1007     {MachineType::Uint8(), kMips64Lbu, kMips64Sb},
1008     {MachineType::Int16(), kMips64Lh, kMips64Sh},
1009     {MachineType::Uint16(), kMips64Lhu, kMips64Sh},
1010     {MachineType::Int32(), kMips64Lw, kMips64Sw},
1011     {MachineType::Float32(), kMips64Lwc1, kMips64Swc1},
1012     {MachineType::Float64(), kMips64Ldc1, kMips64Sdc1},
1013     {MachineType::Int64(), kMips64Ld, kMips64Sd}};
1014 
1015 
1016 struct MemoryAccessImm {
1017   MachineType type;
1018   ArchOpcode load_opcode;
1019   ArchOpcode store_opcode;
1020   bool (InstructionSelectorTest::Stream::*val_predicate)(
1021       const InstructionOperand*) const;
1022   const int32_t immediates[40];
1023 };
1024 
1025 
operator <<(std::ostream & os,const MemoryAccessImm & acc)1026 std::ostream& operator<<(std::ostream& os, const MemoryAccessImm& acc) {
1027   return os << acc.type;
1028 }
1029 
1030 
1031 struct MemoryAccessImm1 {
1032   MachineType type;
1033   ArchOpcode load_opcode;
1034   ArchOpcode store_opcode;
1035   bool (InstructionSelectorTest::Stream::*val_predicate)(
1036       const InstructionOperand*) const;
1037   const int32_t immediates[5];
1038 };
1039 
1040 
operator <<(std::ostream & os,const MemoryAccessImm1 & acc)1041 std::ostream& operator<<(std::ostream& os, const MemoryAccessImm1& acc) {
1042   return os << acc.type;
1043 }
1044 
1045 
1046 // ----------------------------------------------------------------------------
1047 // Loads and stores immediate values
1048 // ----------------------------------------------------------------------------
1049 
1050 
1051 const MemoryAccessImm kMemoryAccessesImm[] = {
1052     {MachineType::Int8(),
1053      kMips64Lb,
1054      kMips64Sb,
1055      &InstructionSelectorTest::Stream::IsInteger,
1056      {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89,
1057       -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109,
1058       115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}},
1059     {MachineType::Uint8(),
1060      kMips64Lbu,
1061      kMips64Sb,
1062      &InstructionSelectorTest::Stream::IsInteger,
1063      {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89,
1064       -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109,
1065       115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}},
1066     {MachineType::Int16(),
1067      kMips64Lh,
1068      kMips64Sh,
1069      &InstructionSelectorTest::Stream::IsInteger,
1070      {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89,
1071       -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109,
1072       115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}},
1073     {MachineType::Uint16(),
1074      kMips64Lhu,
1075      kMips64Sh,
1076      &InstructionSelectorTest::Stream::IsInteger,
1077      {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89,
1078       -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109,
1079       115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}},
1080     {MachineType::Int32(),
1081      kMips64Lw,
1082      kMips64Sw,
1083      &InstructionSelectorTest::Stream::IsInteger,
1084      {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89,
1085       -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109,
1086       115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}},
1087     {MachineType::Float32(),
1088      kMips64Lwc1,
1089      kMips64Swc1,
1090      &InstructionSelectorTest::Stream::IsDouble,
1091      {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89,
1092       -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109,
1093       115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}},
1094     {MachineType::Float64(),
1095      kMips64Ldc1,
1096      kMips64Sdc1,
1097      &InstructionSelectorTest::Stream::IsDouble,
1098      {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89,
1099       -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109,
1100       115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}},
1101     {MachineType::Int64(),
1102      kMips64Ld,
1103      kMips64Sd,
1104      &InstructionSelectorTest::Stream::IsInteger,
1105      {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89,
1106       -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109,
1107       115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}}};
1108 
1109 
1110 const MemoryAccessImm1 kMemoryAccessImmMoreThan16bit[] = {
1111     {MachineType::Int8(),
1112      kMips64Lb,
1113      kMips64Sb,
1114      &InstructionSelectorTest::Stream::IsInteger,
1115      {-65000, -55000, 32777, 55000, 65000}},
1116     {MachineType::Int8(),
1117      kMips64Lbu,
1118      kMips64Sb,
1119      &InstructionSelectorTest::Stream::IsInteger,
1120      {-65000, -55000, 32777, 55000, 65000}},
1121     {MachineType::Int16(),
1122      kMips64Lh,
1123      kMips64Sh,
1124      &InstructionSelectorTest::Stream::IsInteger,
1125      {-65000, -55000, 32777, 55000, 65000}},
1126     {MachineType::Int16(),
1127      kMips64Lhu,
1128      kMips64Sh,
1129      &InstructionSelectorTest::Stream::IsInteger,
1130      {-65000, -55000, 32777, 55000, 65000}},
1131     {MachineType::Int32(),
1132      kMips64Lw,
1133      kMips64Sw,
1134      &InstructionSelectorTest::Stream::IsInteger,
1135      {-65000, -55000, 32777, 55000, 65000}},
1136     {MachineType::Float32(),
1137      kMips64Lwc1,
1138      kMips64Swc1,
1139      &InstructionSelectorTest::Stream::IsDouble,
1140      {-65000, -55000, 32777, 55000, 65000}},
1141     {MachineType::Float64(),
1142      kMips64Ldc1,
1143      kMips64Sdc1,
1144      &InstructionSelectorTest::Stream::IsDouble,
1145      {-65000, -55000, 32777, 55000, 65000}},
1146     {MachineType::Int64(),
1147      kMips64Ld,
1148      kMips64Sd,
1149      &InstructionSelectorTest::Stream::IsInteger,
1150      {-65000, -55000, 32777, 55000, 65000}}};
1151 
1152 }  // namespace
1153 
1154 
1155 typedef InstructionSelectorTestWithParam<MemoryAccess>
1156     InstructionSelectorMemoryAccessTest;
1157 
TEST_P(InstructionSelectorMemoryAccessTest,LoadWithParameters)1158 TEST_P(InstructionSelectorMemoryAccessTest, LoadWithParameters) {
1159   const MemoryAccess memacc = GetParam();
1160   StreamBuilder m(this, memacc.type, MachineType::Pointer(),
1161                   MachineType::Int32());
1162   m.Return(m.Load(memacc.type, m.Parameter(0)));
1163   Stream s = m.Build();
1164   ASSERT_EQ(1U, s.size());
1165   EXPECT_EQ(memacc.load_opcode, s[0]->arch_opcode());
1166   EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
1167 }
1168 
1169 
TEST_P(InstructionSelectorMemoryAccessTest,StoreWithParameters)1170 TEST_P(InstructionSelectorMemoryAccessTest, StoreWithParameters) {
1171   const MemoryAccess memacc = GetParam();
1172   StreamBuilder m(this, MachineType::Int32(), MachineType::Pointer(),
1173                   MachineType::Int32(), memacc.type);
1174   m.Store(memacc.type.representation(), m.Parameter(0), m.Parameter(1),
1175           kNoWriteBarrier);
1176   m.Return(m.Int32Constant(0));
1177   Stream s = m.Build();
1178   ASSERT_EQ(1U, s.size());
1179   EXPECT_EQ(memacc.store_opcode, s[0]->arch_opcode());
1180   EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
1181 }
1182 
1183 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1184                         InstructionSelectorMemoryAccessTest,
1185                         ::testing::ValuesIn(kMemoryAccesses));
1186 
1187 
1188 // ----------------------------------------------------------------------------
1189 // Load immediate.
1190 // ----------------------------------------------------------------------------
1191 
1192 
1193 typedef InstructionSelectorTestWithParam<MemoryAccessImm>
1194     InstructionSelectorMemoryAccessImmTest;
1195 
TEST_P(InstructionSelectorMemoryAccessImmTest,LoadWithImmediateIndex)1196 TEST_P(InstructionSelectorMemoryAccessImmTest, LoadWithImmediateIndex) {
1197   const MemoryAccessImm memacc = GetParam();
1198   TRACED_FOREACH(int32_t, index, memacc.immediates) {
1199     StreamBuilder m(this, memacc.type, MachineType::Pointer());
1200     m.Return(m.Load(memacc.type, m.Parameter(0), m.Int32Constant(index)));
1201     Stream s = m.Build();
1202     ASSERT_EQ(1U, s.size());
1203     EXPECT_EQ(memacc.load_opcode, s[0]->arch_opcode());
1204     EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
1205     ASSERT_EQ(2U, s[0]->InputCount());
1206     ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
1207     EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1)));
1208     ASSERT_EQ(1U, s[0]->OutputCount());
1209     EXPECT_TRUE((s.*memacc.val_predicate)(s[0]->Output()));
1210   }
1211 }
1212 
1213 
1214 // ----------------------------------------------------------------------------
1215 // Store immediate.
1216 // ----------------------------------------------------------------------------
1217 
1218 
TEST_P(InstructionSelectorMemoryAccessImmTest,StoreWithImmediateIndex)1219 TEST_P(InstructionSelectorMemoryAccessImmTest, StoreWithImmediateIndex) {
1220   const MemoryAccessImm memacc = GetParam();
1221   TRACED_FOREACH(int32_t, index, memacc.immediates) {
1222     StreamBuilder m(this, MachineType::Int32(), MachineType::Pointer(),
1223                     memacc.type);
1224     m.Store(memacc.type.representation(), m.Parameter(0),
1225             m.Int32Constant(index), m.Parameter(1), kNoWriteBarrier);
1226     m.Return(m.Int32Constant(0));
1227     Stream s = m.Build();
1228     ASSERT_EQ(1U, s.size());
1229     EXPECT_EQ(memacc.store_opcode, s[0]->arch_opcode());
1230     EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
1231     ASSERT_EQ(3U, s[0]->InputCount());
1232     ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
1233     EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1)));
1234     EXPECT_EQ(0U, s[0]->OutputCount());
1235   }
1236 }
1237 
1238 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1239                         InstructionSelectorMemoryAccessImmTest,
1240                         ::testing::ValuesIn(kMemoryAccessesImm));
1241 
1242 
1243 // ----------------------------------------------------------------------------
1244 // Load/store offsets more than 16 bits.
1245 // ----------------------------------------------------------------------------
1246 
1247 
1248 typedef InstructionSelectorTestWithParam<MemoryAccessImm1>
1249     InstructionSelectorMemoryAccessImmMoreThan16bitTest;
1250 
TEST_P(InstructionSelectorMemoryAccessImmMoreThan16bitTest,LoadWithImmediateIndex)1251 TEST_P(InstructionSelectorMemoryAccessImmMoreThan16bitTest,
1252        LoadWithImmediateIndex) {
1253   const MemoryAccessImm1 memacc = GetParam();
1254   TRACED_FOREACH(int32_t, index, memacc.immediates) {
1255     StreamBuilder m(this, memacc.type, MachineType::Pointer());
1256     m.Return(m.Load(memacc.type, m.Parameter(0), m.Int32Constant(index)));
1257     Stream s = m.Build();
1258     ASSERT_EQ(2U, s.size());
1259     // kMips64Dadd is expected opcode
1260     // size more than 16 bits wide
1261     EXPECT_EQ(kMips64Dadd, s[0]->arch_opcode());
1262     EXPECT_EQ(kMode_None, s[0]->addressing_mode());
1263     EXPECT_EQ(2U, s[0]->InputCount());
1264     EXPECT_EQ(1U, s[0]->OutputCount());
1265   }
1266 }
1267 
TEST_P(InstructionSelectorMemoryAccessImmMoreThan16bitTest,StoreWithImmediateIndex)1268 TEST_P(InstructionSelectorMemoryAccessImmMoreThan16bitTest,
1269        StoreWithImmediateIndex) {
1270   const MemoryAccessImm1 memacc = GetParam();
1271   TRACED_FOREACH(int32_t, index, memacc.immediates) {
1272     StreamBuilder m(this, MachineType::Int32(), MachineType::Pointer(),
1273                     memacc.type);
1274     m.Store(memacc.type.representation(), m.Parameter(0),
1275             m.Int32Constant(index), m.Parameter(1), kNoWriteBarrier);
1276     m.Return(m.Int32Constant(0));
1277     Stream s = m.Build();
1278     ASSERT_EQ(2U, s.size());
1279     // kMips64Add is expected opcode
1280     // size more than 16 bits wide
1281     EXPECT_EQ(kMips64Dadd, s[0]->arch_opcode());
1282     EXPECT_EQ(kMode_None, s[0]->addressing_mode());
1283     EXPECT_EQ(2U, s[0]->InputCount());
1284     EXPECT_EQ(1U, s[0]->OutputCount());
1285   }
1286 }
1287 
1288 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1289                         InstructionSelectorMemoryAccessImmMoreThan16bitTest,
1290                         ::testing::ValuesIn(kMemoryAccessImmMoreThan16bit));
1291 
1292 
1293 // ----------------------------------------------------------------------------
1294 // kMips64Cmp with zero testing.
1295 // ----------------------------------------------------------------------------
1296 
1297 
TEST_F(InstructionSelectorTest,Word32EqualWithZero)1298 TEST_F(InstructionSelectorTest, Word32EqualWithZero) {
1299   {
1300     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
1301     m.Return(m.Word32Equal(m.Parameter(0), m.Int32Constant(0)));
1302     Stream s = m.Build();
1303     ASSERT_EQ(1U, s.size());
1304     EXPECT_EQ(kMips64Cmp, s[0]->arch_opcode());
1305     EXPECT_EQ(kMode_None, s[0]->addressing_mode());
1306     ASSERT_EQ(2U, s[0]->InputCount());
1307     EXPECT_EQ(1U, s[0]->OutputCount());
1308     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1309     EXPECT_EQ(kEqual, s[0]->flags_condition());
1310   }
1311   {
1312     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
1313     m.Return(m.Word32Equal(m.Int32Constant(0), m.Parameter(0)));
1314     Stream s = m.Build();
1315     ASSERT_EQ(1U, s.size());
1316     EXPECT_EQ(kMips64Cmp, s[0]->arch_opcode());
1317     EXPECT_EQ(kMode_None, s[0]->addressing_mode());
1318     ASSERT_EQ(2U, s[0]->InputCount());
1319     EXPECT_EQ(1U, s[0]->OutputCount());
1320     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1321     EXPECT_EQ(kEqual, s[0]->flags_condition());
1322   }
1323 }
1324 
1325 
TEST_F(InstructionSelectorTest,Word64EqualWithZero)1326 TEST_F(InstructionSelectorTest, Word64EqualWithZero) {
1327   {
1328     StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
1329     m.Return(m.Word64Equal(m.Parameter(0), m.Int64Constant(0)));
1330     Stream s = m.Build();
1331     ASSERT_EQ(1U, s.size());
1332     EXPECT_EQ(kMips64Cmp, s[0]->arch_opcode());
1333     EXPECT_EQ(kMode_None, s[0]->addressing_mode());
1334     ASSERT_EQ(2U, s[0]->InputCount());
1335     EXPECT_EQ(1U, s[0]->OutputCount());
1336     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1337     EXPECT_EQ(kEqual, s[0]->flags_condition());
1338   }
1339   {
1340     StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
1341     m.Return(m.Word64Equal(m.Int32Constant(0), m.Parameter(0)));
1342     Stream s = m.Build();
1343     ASSERT_EQ(1U, s.size());
1344     EXPECT_EQ(kMips64Cmp, s[0]->arch_opcode());
1345     EXPECT_EQ(kMode_None, s[0]->addressing_mode());
1346     ASSERT_EQ(2U, s[0]->InputCount());
1347     EXPECT_EQ(1U, s[0]->OutputCount());
1348     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1349     EXPECT_EQ(kEqual, s[0]->flags_condition());
1350   }
1351 }
1352 
1353 
TEST_F(InstructionSelectorTest,Word32Clz)1354 TEST_F(InstructionSelectorTest, Word32Clz) {
1355   StreamBuilder m(this, MachineType::Uint32(), MachineType::Uint32());
1356   Node* const p0 = m.Parameter(0);
1357   Node* const n = m.Word32Clz(p0);
1358   m.Return(n);
1359   Stream s = m.Build();
1360   ASSERT_EQ(1U, s.size());
1361   EXPECT_EQ(kMips64Clz, s[0]->arch_opcode());
1362   ASSERT_EQ(1U, s[0]->InputCount());
1363   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1364   ASSERT_EQ(1U, s[0]->OutputCount());
1365   EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1366 }
1367 
1368 
TEST_F(InstructionSelectorTest,Word64Clz)1369 TEST_F(InstructionSelectorTest, Word64Clz) {
1370   StreamBuilder m(this, MachineType::Uint64(), MachineType::Uint64());
1371   Node* const p0 = m.Parameter(0);
1372   Node* const n = m.Word64Clz(p0);
1373   m.Return(n);
1374   Stream s = m.Build();
1375   ASSERT_EQ(1U, s.size());
1376   EXPECT_EQ(kMips64Dclz, s[0]->arch_opcode());
1377   ASSERT_EQ(1U, s[0]->InputCount());
1378   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1379   ASSERT_EQ(1U, s[0]->OutputCount());
1380   EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1381 }
1382 
1383 
TEST_F(InstructionSelectorTest,Float32Abs)1384 TEST_F(InstructionSelectorTest, Float32Abs) {
1385   StreamBuilder m(this, MachineType::Float32(), MachineType::Float32());
1386   Node* const p0 = m.Parameter(0);
1387   Node* const n = m.Float32Abs(p0);
1388   m.Return(n);
1389   Stream s = m.Build();
1390   ASSERT_EQ(1U, s.size());
1391   EXPECT_EQ(kMips64AbsS, s[0]->arch_opcode());
1392   ASSERT_EQ(1U, s[0]->InputCount());
1393   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1394   ASSERT_EQ(1U, s[0]->OutputCount());
1395   EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1396 }
1397 
1398 
TEST_F(InstructionSelectorTest,Float64Abs)1399 TEST_F(InstructionSelectorTest, Float64Abs) {
1400   StreamBuilder m(this, MachineType::Float64(), MachineType::Float64());
1401   Node* const p0 = m.Parameter(0);
1402   Node* const n = m.Float64Abs(p0);
1403   m.Return(n);
1404   Stream s = m.Build();
1405   ASSERT_EQ(1U, s.size());
1406   EXPECT_EQ(kMips64AbsD, s[0]->arch_opcode());
1407   ASSERT_EQ(1U, s[0]->InputCount());
1408   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1409   ASSERT_EQ(1U, s[0]->OutputCount());
1410   EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1411 }
1412 
1413 
TEST_F(InstructionSelectorTest,Float32Max)1414 TEST_F(InstructionSelectorTest, Float32Max) {
1415   StreamBuilder m(this, MachineType::Float32(), MachineType::Float32(),
1416                   MachineType::Float32());
1417   Node* const p0 = m.Parameter(0);
1418   Node* const p1 = m.Parameter(1);
1419   Node* const n = m.Float32Max(p0, p1);
1420   m.Return(n);
1421   Stream s = m.Build();
1422   // Float32Max is `(b < a) ? a : b`.
1423   ASSERT_EQ(1U, s.size());
1424   EXPECT_EQ(kMips64Float32Max, s[0]->arch_opcode());
1425   ASSERT_EQ(2U, s[0]->InputCount());
1426   ASSERT_EQ(1U, s[0]->OutputCount());
1427   EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1428 }
1429 
1430 
TEST_F(InstructionSelectorTest,Float32Min)1431 TEST_F(InstructionSelectorTest, Float32Min) {
1432   StreamBuilder m(this, MachineType::Float32(), MachineType::Float32(),
1433                   MachineType::Float32());
1434   Node* const p0 = m.Parameter(0);
1435   Node* const p1 = m.Parameter(1);
1436   Node* const n = m.Float32Min(p0, p1);
1437   m.Return(n);
1438   Stream s = m.Build();
1439   // Float32Min is `(a < b) ? a : b`.
1440   ASSERT_EQ(1U, s.size());
1441   EXPECT_EQ(kMips64Float32Min, s[0]->arch_opcode());
1442   ASSERT_EQ(2U, s[0]->InputCount());
1443   ASSERT_EQ(1U, s[0]->OutputCount());
1444   EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1445 }
1446 
1447 
TEST_F(InstructionSelectorTest,Float64Max)1448 TEST_F(InstructionSelectorTest, Float64Max) {
1449   StreamBuilder m(this, MachineType::Float64(), MachineType::Float64(),
1450                   MachineType::Float64());
1451   Node* const p0 = m.Parameter(0);
1452   Node* const p1 = m.Parameter(1);
1453   Node* const n = m.Float64Max(p0, p1);
1454   m.Return(n);
1455   Stream s = m.Build();
1456   // Float64Max is `(b < a) ? a : b`.
1457   ASSERT_EQ(1U, s.size());
1458   EXPECT_EQ(kMips64Float64Max, s[0]->arch_opcode());
1459   ASSERT_EQ(2U, s[0]->InputCount());
1460   ASSERT_EQ(1U, s[0]->OutputCount());
1461   EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1462 }
1463 
1464 
TEST_F(InstructionSelectorTest,Float64Min)1465 TEST_F(InstructionSelectorTest, Float64Min) {
1466   StreamBuilder m(this, MachineType::Float64(), MachineType::Float64(),
1467                   MachineType::Float64());
1468   Node* const p0 = m.Parameter(0);
1469   Node* const p1 = m.Parameter(1);
1470   Node* const n = m.Float64Min(p0, p1);
1471   m.Return(n);
1472   Stream s = m.Build();
1473   // Float64Min is `(a < b) ? a : b`.
1474   ASSERT_EQ(1U, s.size());
1475   EXPECT_EQ(kMips64Float64Min, s[0]->arch_opcode());
1476   ASSERT_EQ(2U, s[0]->InputCount());
1477   ASSERT_EQ(1U, s[0]->OutputCount());
1478   EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1479 }
1480 
1481 }  // namespace compiler
1482 }  // namespace internal
1483 }  // namespace v8
1484