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