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 template <typename T>
15 struct MachInst {
16   T constructor;
17   const char* constructor_name;
18   ArchOpcode arch_opcode;
19   MachineType machine_type;
20 };
21 
22 template <typename T>
operator <<(std::ostream & os,const MachInst<T> & mi)23 std::ostream& operator<<(std::ostream& os, const MachInst<T>& mi) {
24   return os << mi.constructor_name;
25 }
26 
27 using MachInst1 = MachInst<Node* (RawMachineAssembler::*)(Node*)>;
28 using MachInst2 = MachInst<Node* (RawMachineAssembler::*)(Node*, Node*)>;
29 
30 // To avoid duplicated code IntCmp helper structure
31 // is created. It contains MachInst2 with two nodes and expected_size
32 // because different cmp instructions have different size.
33 struct IntCmp {
34   MachInst2 mi;
35   uint32_t expected_size;
36 };
37 
38 struct FPCmp {
39   MachInst2 mi;
40   FlagsCondition cond;
41 };
42 
43 const FPCmp kFPCmpInstructions[] = {
44     {{&RawMachineAssembler::Float64Equal, "Float64Equal", kMips64CmpD,
45       MachineType::Float64()},
46      kEqual},
47     {{&RawMachineAssembler::Float64LessThan, "Float64LessThan", kMips64CmpD,
48       MachineType::Float64()},
49      kUnsignedLessThan},
50     {{&RawMachineAssembler::Float64LessThanOrEqual, "Float64LessThanOrEqual",
51       kMips64CmpD, MachineType::Float64()},
52      kUnsignedLessThanOrEqual},
53     {{&RawMachineAssembler::Float64GreaterThan, "Float64GreaterThan",
54       kMips64CmpD, MachineType::Float64()},
55      kUnsignedLessThan},
56     {{&RawMachineAssembler::Float64GreaterThanOrEqual,
57       "Float64GreaterThanOrEqual", kMips64CmpD, MachineType::Float64()},
58      kUnsignedLessThanOrEqual}};
59 
60 struct Conversion {
61   // The machine_type field in MachInst1 represents the destination type.
62   MachInst1 mi;
63   MachineType src_machine_type;
64 };
65 
66 
67 // ----------------------------------------------------------------------------
68 // Logical instructions.
69 // ----------------------------------------------------------------------------
70 
71 const MachInst2 kLogicalInstructions[] = {
72     {&RawMachineAssembler::Word32And, "Word32And", kMips64And32,
73      MachineType::Int32()},
74     {&RawMachineAssembler::Word64And, "Word64And", kMips64And,
75      MachineType::Int64()},
76     {&RawMachineAssembler::Word32Or, "Word32Or", kMips64Or32,
77      MachineType::Int32()},
78     {&RawMachineAssembler::Word64Or, "Word64Or", kMips64Or,
79      MachineType::Int64()},
80     {&RawMachineAssembler::Word32Xor, "Word32Xor", kMips64Xor32,
81      MachineType::Int32()},
82     {&RawMachineAssembler::Word64Xor, "Word64Xor", kMips64Xor,
83      MachineType::Int64()}};
84 
85 // ----------------------------------------------------------------------------
86 // Shift instructions.
87 // ----------------------------------------------------------------------------
88 
89 
90 const MachInst2 kShiftInstructions[] = {
91     {&RawMachineAssembler::Word32Shl, "Word32Shl", kMips64Shl,
92      MachineType::Int32()},
93     {&RawMachineAssembler::Word64Shl, "Word64Shl", kMips64Dshl,
94      MachineType::Int64()},
95     {&RawMachineAssembler::Word32Shr, "Word32Shr", kMips64Shr,
96      MachineType::Int32()},
97     {&RawMachineAssembler::Word64Shr, "Word64Shr", kMips64Dshr,
98      MachineType::Int64()},
99     {&RawMachineAssembler::Word32Sar, "Word32Sar", kMips64Sar,
100      MachineType::Int32()},
101     {&RawMachineAssembler::Word64Sar, "Word64Sar", kMips64Dsar,
102      MachineType::Int64()},
103     {&RawMachineAssembler::Word32Ror, "Word32Ror", kMips64Ror,
104      MachineType::Int32()},
105     {&RawMachineAssembler::Word64Ror, "Word64Ror", kMips64Dror,
106      MachineType::Int64()}};
107 
108 
109 // ----------------------------------------------------------------------------
110 // MUL/DIV instructions.
111 // ----------------------------------------------------------------------------
112 
113 
114 const MachInst2 kMulDivInstructions[] = {
115     {&RawMachineAssembler::Int32Mul, "Int32Mul", kMips64Mul,
116      MachineType::Int32()},
117     {&RawMachineAssembler::Int32Div, "Int32Div", kMips64Div,
118      MachineType::Int32()},
119     {&RawMachineAssembler::Uint32Div, "Uint32Div", kMips64DivU,
120      MachineType::Uint32()},
121     {&RawMachineAssembler::Int64Mul, "Int64Mul", kMips64Dmul,
122      MachineType::Int64()},
123     {&RawMachineAssembler::Int64Div, "Int64Div", kMips64Ddiv,
124      MachineType::Int64()},
125     {&RawMachineAssembler::Uint64Div, "Uint64Div", kMips64DdivU,
126      MachineType::Uint64()},
127     {&RawMachineAssembler::Float64Mul, "Float64Mul", kMips64MulD,
128      MachineType::Float64()},
129     {&RawMachineAssembler::Float64Div, "Float64Div", kMips64DivD,
130      MachineType::Float64()}};
131 
132 
133 // ----------------------------------------------------------------------------
134 // MOD instructions.
135 // ----------------------------------------------------------------------------
136 
137 
138 const MachInst2 kModInstructions[] = {
139     {&RawMachineAssembler::Int32Mod, "Int32Mod", kMips64Mod,
140      MachineType::Int32()},
141     {&RawMachineAssembler::Uint32Mod, "Uint32Mod", kMips64ModU,
142      MachineType::Int32()},
143     {&RawMachineAssembler::Float64Mod, "Float64Mod", kMips64ModD,
144      MachineType::Float64()}};
145 
146 
147 // ----------------------------------------------------------------------------
148 // Arithmetic FPU instructions.
149 // ----------------------------------------------------------------------------
150 
151 
152 const MachInst2 kFPArithInstructions[] = {
153     {&RawMachineAssembler::Float64Add, "Float64Add", kMips64AddD,
154      MachineType::Float64()},
155     {&RawMachineAssembler::Float64Sub, "Float64Sub", kMips64SubD,
156      MachineType::Float64()}};
157 
158 
159 // ----------------------------------------------------------------------------
160 // IntArithTest instructions, two nodes.
161 // ----------------------------------------------------------------------------
162 
163 
164 const MachInst2 kAddSubInstructions[] = {
165     {&RawMachineAssembler::Int32Add, "Int32Add", kMips64Add,
166      MachineType::Int32()},
167     {&RawMachineAssembler::Int64Add, "Int64Add", kMips64Dadd,
168      MachineType::Int64()},
169     {&RawMachineAssembler::Int32Sub, "Int32Sub", kMips64Sub,
170      MachineType::Int32()},
171     {&RawMachineAssembler::Int64Sub, "Int64Sub", kMips64Dsub,
172      MachineType::Int64()}};
173 
174 
175 // ----------------------------------------------------------------------------
176 // IntArithTest instructions, one node.
177 // ----------------------------------------------------------------------------
178 
179 
180 const MachInst1 kAddSubOneInstructions[] = {
181     {&RawMachineAssembler::Int32Neg, "Int32Neg", kMips64Sub,
182      MachineType::Int32()},
183     {&RawMachineAssembler::Int64Neg, "Int64Neg", kMips64Dsub,
184      MachineType::Int64()}};
185 
186 
187 // ----------------------------------------------------------------------------
188 // Arithmetic compare instructions.
189 // ----------------------------------------------------------------------------
190 
191 
192 const IntCmp kCmpInstructions[] = {
193     {{&RawMachineAssembler::WordEqual, "WordEqual", kMips64Cmp,
194       MachineType::Int64()},
195      1U},
196     {{&RawMachineAssembler::WordNotEqual, "WordNotEqual", kMips64Cmp,
197       MachineType::Int64()},
198      1U},
199     {{&RawMachineAssembler::Word32Equal, "Word32Equal", kMips64Cmp,
200       MachineType::Int32()},
201      1U},
202     {{&RawMachineAssembler::Word32NotEqual, "Word32NotEqual", kMips64Cmp,
203       MachineType::Int32()},
204      1U},
205     {{&RawMachineAssembler::Int32LessThan, "Int32LessThan", kMips64Cmp,
206       MachineType::Int32()},
207      1U},
208     {{&RawMachineAssembler::Int32LessThanOrEqual, "Int32LessThanOrEqual",
209       kMips64Cmp, MachineType::Int32()},
210      1U},
211     {{&RawMachineAssembler::Int32GreaterThan, "Int32GreaterThan", kMips64Cmp,
212       MachineType::Int32()},
213      1U},
214     {{&RawMachineAssembler::Int32GreaterThanOrEqual, "Int32GreaterThanOrEqual",
215       kMips64Cmp, MachineType::Int32()},
216      1U},
217     {{&RawMachineAssembler::Uint32LessThan, "Uint32LessThan", kMips64Cmp,
218       MachineType::Uint32()},
219      1U},
220     {{&RawMachineAssembler::Uint32LessThanOrEqual, "Uint32LessThanOrEqual",
221       kMips64Cmp, MachineType::Uint32()},
222      1U}};
223 
224 
225 // ----------------------------------------------------------------------------
226 // Conversion instructions.
227 // ----------------------------------------------------------------------------
228 
229 const Conversion kConversionInstructions[] = {
230     // Conversion instructions are related to machine_operator.h:
231     // FPU conversions:
232     // Convert representation of integers between float64 and int32/uint32.
233     // The precise rounding mode and handling of out of range inputs are *not*
234     // defined for these operators, since they are intended only for use with
235     // integers.
236     // mips instructions:
237     // mtc1, cvt.d.w
238     {{&RawMachineAssembler::ChangeInt32ToFloat64, "ChangeInt32ToFloat64",
239       kMips64CvtDW, MachineType::Float64()},
240      MachineType::Int32()},
241 
242     // mips instructions:
243     // cvt.d.uw
244     {{&RawMachineAssembler::ChangeUint32ToFloat64, "ChangeUint32ToFloat64",
245       kMips64CvtDUw, MachineType::Float64()},
246      MachineType::Int32()},
247 
248     // mips instructions:
249     // mfc1, trunc double to word, for more details look at mips macro
250     // asm and mips asm file
251     {{&RawMachineAssembler::ChangeFloat64ToInt32, "ChangeFloat64ToInt32",
252       kMips64TruncWD, MachineType::Float64()},
253      MachineType::Int32()},
254 
255     // mips instructions:
256     // trunc double to unsigned word, for more details look at mips macro
257     // asm and mips asm file
258     {{&RawMachineAssembler::ChangeFloat64ToUint32, "ChangeFloat64ToUint32",
259       kMips64TruncUwD, MachineType::Float64()},
260      MachineType::Int32()}};
261 
262 const Conversion kFloat64RoundInstructions[] = {
263     {{&RawMachineAssembler::Float64RoundUp, "Float64RoundUp", kMips64CeilWD,
264       MachineType::Int32()},
265      MachineType::Float64()},
266     {{&RawMachineAssembler::Float64RoundDown, "Float64RoundDown",
267       kMips64FloorWD, MachineType::Int32()},
268      MachineType::Float64()},
269     {{&RawMachineAssembler::Float64RoundTiesEven, "Float64RoundTiesEven",
270       kMips64RoundWD, MachineType::Int32()},
271      MachineType::Float64()},
272     {{&RawMachineAssembler::Float64RoundTruncate, "Float64RoundTruncate",
273       kMips64TruncWD, MachineType::Int32()},
274      MachineType::Float64()}};
275 
276 const Conversion kFloat32RoundInstructions[] = {
277     {{&RawMachineAssembler::Float32RoundUp, "Float32RoundUp", kMips64CeilWS,
278       MachineType::Int32()},
279      MachineType::Float32()},
280     {{&RawMachineAssembler::Float32RoundDown, "Float32RoundDown",
281       kMips64FloorWS, MachineType::Int32()},
282      MachineType::Float32()},
283     {{&RawMachineAssembler::Float32RoundTiesEven, "Float32RoundTiesEven",
284       kMips64RoundWS, MachineType::Int32()},
285      MachineType::Float32()},
286     {{&RawMachineAssembler::Float32RoundTruncate, "Float32RoundTruncate",
287       kMips64TruncWS, MachineType::Int32()},
288      MachineType::Float32()}};
289 
290 // MIPS64 instructions that clear the top 32 bits of the destination.
291 const MachInst2 kCanElideChangeUint32ToUint64[] = {
292     {&RawMachineAssembler::Word32Equal, "Word32Equal", kMips64Cmp,
293      MachineType::Uint32()},
294     {&RawMachineAssembler::Int32LessThan, "Int32LessThan", kMips64Cmp,
295      MachineType::Uint32()},
296     {&RawMachineAssembler::Int32LessThanOrEqual, "Int32LessThanOrEqual",
297      kMips64Cmp, MachineType::Uint32()},
298     {&RawMachineAssembler::Uint32LessThan, "Uint32LessThan", kMips64Cmp,
299      MachineType::Uint32()},
300     {&RawMachineAssembler::Uint32LessThanOrEqual, "Uint32LessThanOrEqual",
301      kMips64Cmp, MachineType::Uint32()},
302 };
303 
304 }  // namespace
305 
306 using InstructionSelectorFPCmpTest = InstructionSelectorTestWithParam<FPCmp>;
307 
TEST_P(InstructionSelectorFPCmpTest,Parameter)308 TEST_P(InstructionSelectorFPCmpTest, Parameter) {
309   const FPCmp cmp = GetParam();
310   StreamBuilder m(this, MachineType::Int32(), cmp.mi.machine_type,
311                   cmp.mi.machine_type);
312   m.Return((m.*cmp.mi.constructor)(m.Parameter(0), m.Parameter(1)));
313   Stream s = m.Build();
314   ASSERT_EQ(1U, s.size());
315   EXPECT_EQ(cmp.mi.arch_opcode, s[0]->arch_opcode());
316   EXPECT_EQ(2U, s[0]->InputCount());
317   EXPECT_EQ(1U, s[0]->OutputCount());
318   EXPECT_EQ(kFlags_set, s[0]->flags_mode());
319   EXPECT_EQ(cmp.cond, s[0]->flags_condition());
320 }
321 
322 INSTANTIATE_TEST_SUITE_P(InstructionSelectorTest, InstructionSelectorFPCmpTest,
323                          ::testing::ValuesIn(kFPCmpInstructions));
324 
325 // ----------------------------------------------------------------------------
326 // Arithmetic compare instructions integers
327 // ----------------------------------------------------------------------------
328 using InstructionSelectorCmpTest = InstructionSelectorTestWithParam<IntCmp>;
329 
TEST_P(InstructionSelectorCmpTest,Parameter)330 TEST_P(InstructionSelectorCmpTest, Parameter) {
331   const IntCmp cmp = GetParam();
332   const MachineType type = cmp.mi.machine_type;
333   StreamBuilder m(this, type, type, type);
334   m.Return((m.*cmp.mi.constructor)(m.Parameter(0), m.Parameter(1)));
335   Stream s = m.Build();
336 
337   if (FLAG_debug_code &&
338       type.representation() == MachineRepresentation::kWord32) {
339     ASSERT_EQ(6U, s.size());
340 
341     EXPECT_EQ(cmp.mi.arch_opcode, s[0]->arch_opcode());
342     EXPECT_EQ(2U, s[0]->InputCount());
343     EXPECT_EQ(1U, s[0]->OutputCount());
344 
345     EXPECT_EQ(kMips64Dshl, s[1]->arch_opcode());
346     EXPECT_EQ(2U, s[1]->InputCount());
347     EXPECT_EQ(1U, s[1]->OutputCount());
348 
349     EXPECT_EQ(kMips64Dshl, s[2]->arch_opcode());
350     EXPECT_EQ(2U, s[2]->InputCount());
351     EXPECT_EQ(1U, s[2]->OutputCount());
352 
353     EXPECT_EQ(cmp.mi.arch_opcode, s[3]->arch_opcode());
354     EXPECT_EQ(2U, s[3]->InputCount());
355     EXPECT_EQ(1U, s[3]->OutputCount());
356 
357     EXPECT_EQ(kMips64AssertEqual, s[4]->arch_opcode());
358     EXPECT_EQ(3U, s[4]->InputCount());
359     EXPECT_EQ(0U, s[4]->OutputCount());
360 
361     EXPECT_EQ(cmp.mi.arch_opcode, s[5]->arch_opcode());
362     EXPECT_EQ(2U, s[5]->InputCount());
363     EXPECT_EQ(1U, s[5]->OutputCount());
364   } else {
365     ASSERT_EQ(cmp.expected_size, s.size());
366     EXPECT_EQ(cmp.mi.arch_opcode, s[0]->arch_opcode());
367     EXPECT_EQ(2U, s[0]->InputCount());
368     EXPECT_EQ(1U, s[0]->OutputCount());
369   }
370 }
371 
372 INSTANTIATE_TEST_SUITE_P(InstructionSelectorTest, InstructionSelectorCmpTest,
373                          ::testing::ValuesIn(kCmpInstructions));
374 
375 // ----------------------------------------------------------------------------
376 // Shift instructions.
377 // ----------------------------------------------------------------------------
378 using InstructionSelectorShiftTest =
379     InstructionSelectorTestWithParam<MachInst2>;
380 
TEST_P(InstructionSelectorShiftTest,Immediate)381 TEST_P(InstructionSelectorShiftTest, Immediate) {
382   const MachInst2 dpi = GetParam();
383   const MachineType type = dpi.machine_type;
384   TRACED_FORRANGE(int32_t, imm, 0,
385                   ((1 << ElementSizeLog2Of(type.representation())) * 8) - 1) {
386     StreamBuilder m(this, type, type);
387     m.Return((m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm)));
388     Stream s = m.Build();
389     ASSERT_EQ(1U, s.size());
390     EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
391     EXPECT_EQ(2U, s[0]->InputCount());
392     EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
393     EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
394     EXPECT_EQ(1U, s[0]->OutputCount());
395   }
396 }
397 
398 INSTANTIATE_TEST_SUITE_P(InstructionSelectorTest, InstructionSelectorShiftTest,
399                          ::testing::ValuesIn(kShiftInstructions));
400 
TEST_F(InstructionSelectorTest,Word32ShrWithWord32AndWithImmediate)401 TEST_F(InstructionSelectorTest, Word32ShrWithWord32AndWithImmediate) {
402   // The available shift operand range is `0 <= imm < 32`, but we also test
403   // that immediates outside this range are handled properly (modulo-32).
404   TRACED_FORRANGE(int32_t, shift, -32, 63) {
405     int32_t lsb = shift & 0x1F;
406     TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) {
407       uint32_t jnk = rng()->NextInt();
408       jnk = (lsb > 0) ? (jnk >> (32 - lsb)) : 0;
409       uint32_t msk = ((0xFFFFFFFFu >> (32 - width)) << lsb) | jnk;
410       StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
411       m.Return(m.Word32Shr(m.Word32And(m.Parameter(0), m.Int32Constant(msk)),
412                            m.Int32Constant(shift)));
413       Stream s = m.Build();
414       ASSERT_EQ(1U, s.size());
415       EXPECT_EQ(kMips64Ext, s[0]->arch_opcode());
416       ASSERT_EQ(3U, s[0]->InputCount());
417       EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
418       EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
419     }
420   }
421   TRACED_FORRANGE(int32_t, shift, -32, 63) {
422     int32_t lsb = shift & 0x1F;
423     TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) {
424       uint32_t jnk = rng()->NextInt();
425       jnk = (lsb > 0) ? (jnk >> (32 - lsb)) : 0;
426       uint32_t msk = ((0xFFFFFFFFu >> (32 - width)) << lsb) | jnk;
427       StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
428       m.Return(m.Word32Shr(m.Word32And(m.Int32Constant(msk), m.Parameter(0)),
429                            m.Int32Constant(shift)));
430       Stream s = m.Build();
431       ASSERT_EQ(1U, s.size());
432       EXPECT_EQ(kMips64Ext, s[0]->arch_opcode());
433       ASSERT_EQ(3U, s[0]->InputCount());
434       EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
435       EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
436     }
437   }
438 }
439 
440 
TEST_F(InstructionSelectorTest,Word64ShrWithWord64AndWithImmediate)441 TEST_F(InstructionSelectorTest, Word64ShrWithWord64AndWithImmediate) {
442   // The available shift operand range is `0 <= imm < 64`, but we also test
443   // that immediates outside this range are handled properly (modulo-64).
444   TRACED_FORRANGE(int32_t, shift, -64, 127) {
445     int32_t lsb = shift & 0x3F;
446     TRACED_FORRANGE(int32_t, width, 1, 64 - lsb) {
447       uint64_t jnk = rng()->NextInt64();
448       jnk = (lsb > 0) ? (jnk >> (64 - lsb)) : 0;
449       uint64_t msk =
450           ((uint64_t{0xFFFFFFFFFFFFFFFF} >> (64 - width)) << lsb) | jnk;
451       StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
452       m.Return(m.Word64Shr(m.Word64And(m.Parameter(0), m.Int64Constant(msk)),
453                            m.Int64Constant(shift)));
454       Stream s = m.Build();
455       ASSERT_EQ(1U, s.size());
456       EXPECT_EQ(kMips64Dext, s[0]->arch_opcode());
457       ASSERT_EQ(3U, s[0]->InputCount());
458       EXPECT_EQ(lsb, s.ToInt64(s[0]->InputAt(1)));
459       EXPECT_EQ(width, s.ToInt64(s[0]->InputAt(2)));
460     }
461   }
462   TRACED_FORRANGE(int32_t, shift, -64, 127) {
463     int32_t lsb = shift & 0x3F;
464     TRACED_FORRANGE(int32_t, width, 1, 64 - lsb) {
465       uint64_t jnk = rng()->NextInt64();
466       jnk = (lsb > 0) ? (jnk >> (64 - lsb)) : 0;
467       uint64_t msk =
468           ((uint64_t{0xFFFFFFFFFFFFFFFF} >> (64 - width)) << lsb) | jnk;
469       StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
470       m.Return(m.Word64Shr(m.Word64And(m.Int64Constant(msk), m.Parameter(0)),
471                            m.Int64Constant(shift)));
472       Stream s = m.Build();
473       ASSERT_EQ(1U, s.size());
474       EXPECT_EQ(kMips64Dext, s[0]->arch_opcode());
475       ASSERT_EQ(3U, s[0]->InputCount());
476       EXPECT_EQ(lsb, s.ToInt64(s[0]->InputAt(1)));
477       EXPECT_EQ(width, s.ToInt64(s[0]->InputAt(2)));
478     }
479   }
480 }
481 
482 
TEST_F(InstructionSelectorTest,Word32AndToClearBits)483 TEST_F(InstructionSelectorTest, Word32AndToClearBits) {
484   TRACED_FORRANGE(int32_t, shift, 1, 31) {
485     int32_t mask = ~((1 << shift) - 1);
486     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
487     m.Return(m.Word32And(m.Parameter(0), m.Int32Constant(mask)));
488     Stream s = m.Build();
489     ASSERT_EQ(1U, s.size());
490     EXPECT_EQ(kMips64Ins, s[0]->arch_opcode());
491     ASSERT_EQ(3U, s[0]->InputCount());
492     EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1)));
493     EXPECT_EQ(shift, s.ToInt32(s[0]->InputAt(2)));
494   }
495   TRACED_FORRANGE(int32_t, shift, 1, 31) {
496     int32_t mask = ~((1 << shift) - 1);
497     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
498     m.Return(m.Word32And(m.Int32Constant(mask), m.Parameter(0)));
499     Stream s = m.Build();
500     ASSERT_EQ(1U, s.size());
501     EXPECT_EQ(kMips64Ins, s[0]->arch_opcode());
502     ASSERT_EQ(3U, s[0]->InputCount());
503     EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1)));
504     EXPECT_EQ(shift, s.ToInt32(s[0]->InputAt(2)));
505   }
506 }
507 
508 
TEST_F(InstructionSelectorTest,Word64AndToClearBits)509 TEST_F(InstructionSelectorTest, Word64AndToClearBits) {
510   TRACED_FORRANGE(int32_t, shift, 1, 31) {
511     int64_t mask = ~((1 << shift) - 1);
512     StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
513     m.Return(m.Word64And(m.Parameter(0), m.Int64Constant(mask)));
514     Stream s = m.Build();
515     ASSERT_EQ(1U, s.size());
516     EXPECT_EQ(kMips64Dins, s[0]->arch_opcode());
517     ASSERT_EQ(3U, s[0]->InputCount());
518     EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1)));
519     EXPECT_EQ(shift, s.ToInt32(s[0]->InputAt(2)));
520   }
521   TRACED_FORRANGE(int32_t, shift, 1, 31) {
522     int64_t mask = ~((1 << shift) - 1);
523     StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
524     m.Return(m.Word64And(m.Int64Constant(mask), m.Parameter(0)));
525     Stream s = m.Build();
526     ASSERT_EQ(1U, s.size());
527     EXPECT_EQ(kMips64Dins, s[0]->arch_opcode());
528     ASSERT_EQ(3U, s[0]->InputCount());
529     EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1)));
530     EXPECT_EQ(shift, s.ToInt32(s[0]->InputAt(2)));
531   }
532 }
533 
534 
535 // ----------------------------------------------------------------------------
536 // Logical instructions.
537 // ----------------------------------------------------------------------------
538 using InstructionSelectorLogicalTest =
539     InstructionSelectorTestWithParam<MachInst2>;
540 
TEST_P(InstructionSelectorLogicalTest,Parameter)541 TEST_P(InstructionSelectorLogicalTest, Parameter) {
542   const MachInst2 dpi = GetParam();
543   const MachineType type = dpi.machine_type;
544   StreamBuilder m(this, type, type, type);
545   m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)));
546   Stream s = m.Build();
547   ASSERT_EQ(1U, s.size());
548   EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
549   EXPECT_EQ(2U, s[0]->InputCount());
550   EXPECT_EQ(1U, s[0]->OutputCount());
551 }
552 
553 INSTANTIATE_TEST_SUITE_P(InstructionSelectorTest,
554                          InstructionSelectorLogicalTest,
555                          ::testing::ValuesIn(kLogicalInstructions));
556 
TEST_F(InstructionSelectorTest,Word64XorMinusOneWithParameter)557 TEST_F(InstructionSelectorTest, Word64XorMinusOneWithParameter) {
558   {
559     StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
560     m.Return(m.Word64Xor(m.Parameter(0), m.Int64Constant(-1)));
561     Stream s = m.Build();
562     ASSERT_EQ(1U, s.size());
563     EXPECT_EQ(kMips64Nor, s[0]->arch_opcode());
564     EXPECT_EQ(2U, s[0]->InputCount());
565     EXPECT_EQ(1U, s[0]->OutputCount());
566   }
567   {
568     StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
569     m.Return(m.Word64Xor(m.Int64Constant(-1), m.Parameter(0)));
570     Stream s = m.Build();
571     ASSERT_EQ(1U, s.size());
572     EXPECT_EQ(kMips64Nor, s[0]->arch_opcode());
573     EXPECT_EQ(2U, s[0]->InputCount());
574     EXPECT_EQ(1U, s[0]->OutputCount());
575   }
576 }
577 
578 
TEST_F(InstructionSelectorTest,Word32XorMinusOneWithParameter)579 TEST_F(InstructionSelectorTest, Word32XorMinusOneWithParameter) {
580   {
581     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
582     m.Return(m.Word32Xor(m.Parameter(0), m.Int32Constant(-1)));
583     Stream s = m.Build();
584     ASSERT_EQ(1U, s.size());
585     EXPECT_EQ(kMips64Nor32, s[0]->arch_opcode());
586     EXPECT_EQ(2U, s[0]->InputCount());
587     EXPECT_EQ(1U, s[0]->OutputCount());
588   }
589   {
590     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
591     m.Return(m.Word32Xor(m.Int32Constant(-1), m.Parameter(0)));
592     Stream s = m.Build();
593     ASSERT_EQ(1U, s.size());
594     EXPECT_EQ(kMips64Nor32, s[0]->arch_opcode());
595     EXPECT_EQ(2U, s[0]->InputCount());
596     EXPECT_EQ(1U, s[0]->OutputCount());
597   }
598 }
599 
600 
TEST_F(InstructionSelectorTest,Word64XorMinusOneWithWord64Or)601 TEST_F(InstructionSelectorTest, Word64XorMinusOneWithWord64Or) {
602   {
603     StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
604     m.Return(m.Word64Xor(m.Word64Or(m.Parameter(0), m.Parameter(0)),
605                          m.Int64Constant(-1)));
606     Stream s = m.Build();
607     ASSERT_EQ(1U, s.size());
608     EXPECT_EQ(kMips64Nor, s[0]->arch_opcode());
609     EXPECT_EQ(2U, s[0]->InputCount());
610     EXPECT_EQ(1U, s[0]->OutputCount());
611   }
612   {
613     StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
614     m.Return(m.Word64Xor(m.Int64Constant(-1),
615                          m.Word64Or(m.Parameter(0), m.Parameter(0))));
616     Stream s = m.Build();
617     ASSERT_EQ(1U, s.size());
618     EXPECT_EQ(kMips64Nor, s[0]->arch_opcode());
619     EXPECT_EQ(2U, s[0]->InputCount());
620     EXPECT_EQ(1U, s[0]->OutputCount());
621   }
622 }
623 
624 
TEST_F(InstructionSelectorTest,Word32XorMinusOneWithWord32Or)625 TEST_F(InstructionSelectorTest, Word32XorMinusOneWithWord32Or) {
626   {
627     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
628     m.Return(m.Word32Xor(m.Word32Or(m.Parameter(0), m.Parameter(0)),
629                          m.Int32Constant(-1)));
630     Stream s = m.Build();
631     ASSERT_EQ(1U, s.size());
632     EXPECT_EQ(kMips64Nor32, s[0]->arch_opcode());
633     EXPECT_EQ(2U, s[0]->InputCount());
634     EXPECT_EQ(1U, s[0]->OutputCount());
635   }
636   {
637     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
638     m.Return(m.Word32Xor(m.Int32Constant(-1),
639                          m.Word32Or(m.Parameter(0), m.Parameter(0))));
640     Stream s = m.Build();
641     ASSERT_EQ(1U, s.size());
642     EXPECT_EQ(kMips64Nor32, s[0]->arch_opcode());
643     EXPECT_EQ(2U, s[0]->InputCount());
644     EXPECT_EQ(1U, s[0]->OutputCount());
645   }
646 }
647 
648 
TEST_F(InstructionSelectorTest,Word32AndWithImmediateWithWord32Shr)649 TEST_F(InstructionSelectorTest, Word32AndWithImmediateWithWord32Shr) {
650   // The available shift operand range is `0 <= imm < 32`, but we also test
651   // that immediates outside this range are handled properly (modulo-32).
652   TRACED_FORRANGE(int32_t, shift, -32, 63) {
653     int32_t lsb = shift & 0x1F;
654     TRACED_FORRANGE(int32_t, width, 1, 31) {
655       uint32_t msk = (1 << width) - 1;
656       StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
657       m.Return(m.Word32And(m.Word32Shr(m.Parameter(0), m.Int32Constant(shift)),
658                            m.Int32Constant(msk)));
659       Stream s = m.Build();
660       ASSERT_EQ(1U, s.size());
661       EXPECT_EQ(kMips64Ext, s[0]->arch_opcode());
662       ASSERT_EQ(3U, s[0]->InputCount());
663       EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
664       int32_t actual_width = (lsb + width > 32) ? (32 - lsb) : width;
665       EXPECT_EQ(actual_width, s.ToInt32(s[0]->InputAt(2)));
666     }
667   }
668   TRACED_FORRANGE(int32_t, shift, -32, 63) {
669     int32_t lsb = shift & 0x1F;
670     TRACED_FORRANGE(int32_t, width, 1, 31) {
671       uint32_t msk = (1 << width) - 1;
672       StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
673       m.Return(
674           m.Word32And(m.Int32Constant(msk),
675                       m.Word32Shr(m.Parameter(0), m.Int32Constant(shift))));
676       Stream s = m.Build();
677       ASSERT_EQ(1U, s.size());
678       EXPECT_EQ(kMips64Ext, s[0]->arch_opcode());
679       ASSERT_EQ(3U, s[0]->InputCount());
680       EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
681       int32_t actual_width = (lsb + width > 32) ? (32 - lsb) : width;
682       EXPECT_EQ(actual_width, s.ToInt32(s[0]->InputAt(2)));
683     }
684   }
685 }
686 
687 
TEST_F(InstructionSelectorTest,Word64AndWithImmediateWithWord64Shr)688 TEST_F(InstructionSelectorTest, Word64AndWithImmediateWithWord64Shr) {
689   // The available shift operand range is `0 <= imm < 64`, but we also test
690   // that immediates outside this range are handled properly (modulo-64).
691   TRACED_FORRANGE(int64_t, shift, -64, 127) {
692     int64_t lsb = shift & 0x3F;
693     TRACED_FORRANGE(int64_t, width, 1, 63) {
694       uint64_t msk = (uint64_t{1} << width) - 1;
695       StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
696       m.Return(m.Word64And(m.Word64Shr(m.Parameter(0), m.Int64Constant(shift)),
697                            m.Int64Constant(msk)));
698       Stream s = m.Build();
699       ASSERT_EQ(1U, s.size());
700       EXPECT_EQ(kMips64Dext, s[0]->arch_opcode());
701       ASSERT_EQ(3U, s[0]->InputCount());
702       EXPECT_EQ(lsb, s.ToInt64(s[0]->InputAt(1)));
703       int64_t actual_width = (lsb + width > 64) ? (64 - lsb) : width;
704       EXPECT_EQ(actual_width, s.ToInt64(s[0]->InputAt(2)));
705     }
706   }
707   TRACED_FORRANGE(int64_t, shift, -64, 127) {
708     int64_t lsb = shift & 0x3F;
709     TRACED_FORRANGE(int64_t, width, 1, 63) {
710       uint64_t msk = (uint64_t{1} << width) - 1;
711       StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
712       m.Return(
713           m.Word64And(m.Int64Constant(msk),
714                       m.Word64Shr(m.Parameter(0), m.Int64Constant(shift))));
715       Stream s = m.Build();
716       ASSERT_EQ(1U, s.size());
717       EXPECT_EQ(kMips64Dext, s[0]->arch_opcode());
718       ASSERT_EQ(3U, s[0]->InputCount());
719       EXPECT_EQ(lsb, s.ToInt64(s[0]->InputAt(1)));
720       int64_t actual_width = (lsb + width > 64) ? (64 - lsb) : width;
721       EXPECT_EQ(actual_width, s.ToInt64(s[0]->InputAt(2)));
722     }
723   }
724 }
725 
726 
TEST_F(InstructionSelectorTest,Word32ShlWithWord32And)727 TEST_F(InstructionSelectorTest, Word32ShlWithWord32And) {
728   TRACED_FORRANGE(int32_t, shift, 0, 30) {
729     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
730     Node* const p0 = m.Parameter(0);
731     Node* const r =
732         m.Word32Shl(m.Word32And(p0, m.Int32Constant((1 << (31 - shift)) - 1)),
733                     m.Int32Constant(shift + 1));
734     m.Return(r);
735     Stream s = m.Build();
736     ASSERT_EQ(1U, s.size());
737     EXPECT_EQ(kMips64Shl, s[0]->arch_opcode());
738     ASSERT_EQ(2U, s[0]->InputCount());
739     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
740     ASSERT_EQ(1U, s[0]->OutputCount());
741     EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
742   }
743 }
744 
745 
TEST_F(InstructionSelectorTest,Word64ShlWithWord64And)746 TEST_F(InstructionSelectorTest, Word64ShlWithWord64And) {
747   TRACED_FORRANGE(int32_t, shift, 0, 62) {
748     StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
749     Node* const p0 = m.Parameter(0);
750     Node* const r =
751         m.Word64Shl(m.Word64And(p0, m.Int64Constant((1L << (63 - shift)) - 1)),
752                     m.Int64Constant(shift + 1));
753     m.Return(r);
754     Stream s = m.Build();
755     ASSERT_EQ(1U, s.size());
756     EXPECT_EQ(kMips64Dshl, s[0]->arch_opcode());
757     ASSERT_EQ(2U, s[0]->InputCount());
758     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
759     ASSERT_EQ(1U, s[0]->OutputCount());
760     EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
761   }
762 }
763 
TEST_F(InstructionSelectorTest,Word32SarWithWord32Shl)764 TEST_F(InstructionSelectorTest, Word32SarWithWord32Shl) {
765   {
766     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
767     Node* const p0 = m.Parameter(0);
768     Node* const r =
769         m.Word32Sar(m.Word32Shl(p0, m.Int32Constant(24)), m.Int32Constant(24));
770     m.Return(r);
771     Stream s = m.Build();
772     ASSERT_EQ(1U, s.size());
773     EXPECT_EQ(kMips64Seb, s[0]->arch_opcode());
774     ASSERT_EQ(1U, s[0]->InputCount());
775     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
776     ASSERT_EQ(1U, s[0]->OutputCount());
777     EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
778   }
779   {
780     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
781     Node* const p0 = m.Parameter(0);
782     Node* const r =
783         m.Word32Sar(m.Word32Shl(p0, m.Int32Constant(16)), m.Int32Constant(16));
784     m.Return(r);
785     Stream s = m.Build();
786     ASSERT_EQ(1U, s.size());
787     EXPECT_EQ(kMips64Seh, s[0]->arch_opcode());
788     ASSERT_EQ(1U, s[0]->InputCount());
789     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
790     ASSERT_EQ(1U, s[0]->OutputCount());
791     EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
792   }
793   {
794     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
795     Node* const p0 = m.Parameter(0);
796     Node* const r =
797         m.Word32Sar(m.Word32Shl(p0, m.Int32Constant(32)), m.Int32Constant(32));
798     m.Return(r);
799     Stream s = m.Build();
800     ASSERT_EQ(1U, s.size());
801     EXPECT_EQ(kMips64Shl, s[0]->arch_opcode());
802     ASSERT_EQ(2U, s[0]->InputCount());
803     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
804     EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1)));
805     ASSERT_EQ(1U, s[0]->OutputCount());
806     EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
807   }
808 }
809 
810 // ----------------------------------------------------------------------------
811 // MUL/DIV instructions.
812 // ----------------------------------------------------------------------------
813 using InstructionSelectorMulDivTest =
814     InstructionSelectorTestWithParam<MachInst2>;
815 
TEST_P(InstructionSelectorMulDivTest,Parameter)816 TEST_P(InstructionSelectorMulDivTest, Parameter) {
817   const MachInst2 dpi = GetParam();
818   const MachineType type = dpi.machine_type;
819   StreamBuilder m(this, type, type, type);
820   m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)));
821   Stream s = m.Build();
822   ASSERT_EQ(1U, s.size());
823   EXPECT_EQ(dpi.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_SUITE_P(InstructionSelectorTest, InstructionSelectorMulDivTest,
829                          ::testing::ValuesIn(kMulDivInstructions));
830 
831 // ----------------------------------------------------------------------------
832 // MOD instructions.
833 // ----------------------------------------------------------------------------
834 using InstructionSelectorModTest = InstructionSelectorTestWithParam<MachInst2>;
835 
TEST_P(InstructionSelectorModTest,Parameter)836 TEST_P(InstructionSelectorModTest, Parameter) {
837   const MachInst2 dpi = GetParam();
838   const MachineType type = dpi.machine_type;
839   StreamBuilder m(this, type, type, type);
840   m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)));
841   Stream s = m.Build();
842   ASSERT_EQ(1U, s.size());
843   EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
844   EXPECT_EQ(2U, s[0]->InputCount());
845   EXPECT_EQ(1U, s[0]->OutputCount());
846 }
847 
848 INSTANTIATE_TEST_SUITE_P(InstructionSelectorTest, InstructionSelectorModTest,
849                          ::testing::ValuesIn(kModInstructions));
850 
851 // ----------------------------------------------------------------------------
852 // Floating point instructions.
853 // ----------------------------------------------------------------------------
854 using InstructionSelectorFPArithTest =
855     InstructionSelectorTestWithParam<MachInst2>;
856 
TEST_P(InstructionSelectorFPArithTest,Parameter)857 TEST_P(InstructionSelectorFPArithTest, Parameter) {
858   const MachInst2 fpa = GetParam();
859   StreamBuilder m(this, fpa.machine_type, fpa.machine_type, fpa.machine_type);
860   m.Return((m.*fpa.constructor)(m.Parameter(0), m.Parameter(1)));
861   Stream s = m.Build();
862   ASSERT_EQ(1U, s.size());
863   EXPECT_EQ(fpa.arch_opcode, s[0]->arch_opcode());
864   EXPECT_EQ(2U, s[0]->InputCount());
865   EXPECT_EQ(1U, s[0]->OutputCount());
866 }
867 
868 INSTANTIATE_TEST_SUITE_P(InstructionSelectorTest,
869                          InstructionSelectorFPArithTest,
870                          ::testing::ValuesIn(kFPArithInstructions));
871 // ----------------------------------------------------------------------------
872 // Integer arithmetic
873 // ----------------------------------------------------------------------------
874 using InstructionSelectorIntArithTwoTest =
875     InstructionSelectorTestWithParam<MachInst2>;
876 
TEST_P(InstructionSelectorIntArithTwoTest,Parameter)877 TEST_P(InstructionSelectorIntArithTwoTest, Parameter) {
878   const MachInst2 intpa = GetParam();
879   StreamBuilder m(this, intpa.machine_type, intpa.machine_type,
880                   intpa.machine_type);
881   m.Return((m.*intpa.constructor)(m.Parameter(0), m.Parameter(1)));
882   Stream s = m.Build();
883   ASSERT_EQ(1U, s.size());
884   EXPECT_EQ(intpa.arch_opcode, s[0]->arch_opcode());
885   EXPECT_EQ(2U, s[0]->InputCount());
886   EXPECT_EQ(1U, s[0]->OutputCount());
887 }
888 
889 INSTANTIATE_TEST_SUITE_P(InstructionSelectorTest,
890                          InstructionSelectorIntArithTwoTest,
891                          ::testing::ValuesIn(kAddSubInstructions));
892 
893 // ----------------------------------------------------------------------------
894 // One node.
895 // ----------------------------------------------------------------------------
896 
897 using InstructionSelectorIntArithOneTest =
898     InstructionSelectorTestWithParam<MachInst1>;
899 
TEST_P(InstructionSelectorIntArithOneTest,Parameter)900 TEST_P(InstructionSelectorIntArithOneTest, Parameter) {
901   const MachInst1 intpa = GetParam();
902   StreamBuilder m(this, intpa.machine_type, intpa.machine_type,
903                   intpa.machine_type);
904   m.Return((m.*intpa.constructor)(m.Parameter(0)));
905   Stream s = m.Build();
906   ASSERT_EQ(1U, s.size());
907   EXPECT_EQ(intpa.arch_opcode, s[0]->arch_opcode());
908   EXPECT_EQ(2U, s[0]->InputCount());
909   EXPECT_EQ(1U, s[0]->OutputCount());
910 }
911 
912 INSTANTIATE_TEST_SUITE_P(InstructionSelectorTest,
913                          InstructionSelectorIntArithOneTest,
914                          ::testing::ValuesIn(kAddSubOneInstructions));
915 // ----------------------------------------------------------------------------
916 // Conversions.
917 // ----------------------------------------------------------------------------
918 using InstructionSelectorConversionTest =
919     InstructionSelectorTestWithParam<Conversion>;
920 
TEST_P(InstructionSelectorConversionTest,Parameter)921 TEST_P(InstructionSelectorConversionTest, Parameter) {
922   const Conversion conv = GetParam();
923   StreamBuilder m(this, conv.mi.machine_type, conv.src_machine_type);
924   m.Return((m.*conv.mi.constructor)(m.Parameter(0)));
925   Stream s = m.Build();
926   ASSERT_EQ(1U, s.size());
927   EXPECT_EQ(conv.mi.arch_opcode, s[0]->arch_opcode());
928   EXPECT_EQ(1U, s[0]->InputCount());
929   EXPECT_EQ(1U, s[0]->OutputCount());
930 }
931 
932 INSTANTIATE_TEST_SUITE_P(InstructionSelectorTest,
933                          InstructionSelectorConversionTest,
934                          ::testing::ValuesIn(kConversionInstructions));
935 
TEST_F(InstructionSelectorTest,ChangesFromToSmi)936 TEST_F(InstructionSelectorTest, ChangesFromToSmi) {
937   {
938     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
939     m.Return(m.TruncateInt64ToInt32(
940         m.Word64Sar(m.Parameter(0), m.Int32Constant(32))));
941     Stream s = m.Build();
942     ASSERT_EQ(1U, s.size());
943     EXPECT_EQ(kMips64Dsar, s[0]->arch_opcode());
944     EXPECT_EQ(kMode_None, s[0]->addressing_mode());
945     ASSERT_EQ(2U, s[0]->InputCount());
946     EXPECT_EQ(1U, s[0]->OutputCount());
947   }
948   {
949     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
950     m.Return(
951         m.Word64Shl(m.ChangeInt32ToInt64(m.Parameter(0)), m.Int32Constant(32)));
952     Stream s = m.Build();
953     ASSERT_EQ(1U, s.size());
954     EXPECT_EQ(kMips64Dshl, s[0]->arch_opcode());
955     ASSERT_EQ(2U, s[0]->InputCount());
956     EXPECT_EQ(1U, s[0]->OutputCount());
957   }
958 }
959 
960 using CombineChangeFloat64ToInt32WithRoundFloat64 =
961     InstructionSelectorTestWithParam<Conversion>;
962 
TEST_P(CombineChangeFloat64ToInt32WithRoundFloat64,Parameter)963 TEST_P(CombineChangeFloat64ToInt32WithRoundFloat64, Parameter) {
964   {
965     const Conversion conv = GetParam();
966     StreamBuilder m(this, conv.mi.machine_type, conv.src_machine_type);
967     m.Return(m.ChangeFloat64ToInt32((m.*conv.mi.constructor)(m.Parameter(0))));
968     Stream s = m.Build();
969     ASSERT_EQ(1U, s.size());
970     EXPECT_EQ(conv.mi.arch_opcode, s[0]->arch_opcode());
971     EXPECT_EQ(kMode_None, s[0]->addressing_mode());
972     ASSERT_EQ(1U, s[0]->InputCount());
973     EXPECT_EQ(1U, s[0]->OutputCount());
974   }
975 }
976 
977 INSTANTIATE_TEST_SUITE_P(InstructionSelectorTest,
978                          CombineChangeFloat64ToInt32WithRoundFloat64,
979                          ::testing::ValuesIn(kFloat64RoundInstructions));
980 
981 using CombineChangeFloat32ToInt32WithRoundFloat32 =
982     InstructionSelectorTestWithParam<Conversion>;
983 
TEST_P(CombineChangeFloat32ToInt32WithRoundFloat32,Parameter)984 TEST_P(CombineChangeFloat32ToInt32WithRoundFloat32, Parameter) {
985   {
986     const Conversion conv = GetParam();
987     StreamBuilder m(this, conv.mi.machine_type, conv.src_machine_type);
988     m.Return(m.ChangeFloat64ToInt32(
989         m.ChangeFloat32ToFloat64((m.*conv.mi.constructor)(m.Parameter(0)))));
990     Stream s = m.Build();
991     ASSERT_EQ(1U, s.size());
992     EXPECT_EQ(conv.mi.arch_opcode, s[0]->arch_opcode());
993     EXPECT_EQ(kMode_None, s[0]->addressing_mode());
994     ASSERT_EQ(1U, s[0]->InputCount());
995     EXPECT_EQ(1U, s[0]->OutputCount());
996   }
997 }
998 
999 INSTANTIATE_TEST_SUITE_P(InstructionSelectorTest,
1000                          CombineChangeFloat32ToInt32WithRoundFloat32,
1001                          ::testing::ValuesIn(kFloat32RoundInstructions));
1002 
TEST_F(InstructionSelectorTest,ChangeFloat64ToInt32OfChangeFloat32ToFloat64)1003 TEST_F(InstructionSelectorTest, ChangeFloat64ToInt32OfChangeFloat32ToFloat64) {
1004   {
1005     StreamBuilder m(this, MachineType::Int32(), MachineType::Float32());
1006     m.Return(m.ChangeFloat64ToInt32(m.ChangeFloat32ToFloat64(m.Parameter(0))));
1007     Stream s = m.Build();
1008     ASSERT_EQ(1U, s.size());
1009     EXPECT_EQ(kMips64TruncWS, s[0]->arch_opcode());
1010     EXPECT_EQ(kMode_None, s[0]->addressing_mode());
1011     ASSERT_EQ(1U, s[0]->InputCount());
1012     EXPECT_EQ(1U, s[0]->OutputCount());
1013   }
1014 }
1015 
1016 
TEST_F(InstructionSelectorTest,TruncateFloat64ToFloat32OfChangeInt32ToFloat64)1017 TEST_F(InstructionSelectorTest,
1018        TruncateFloat64ToFloat32OfChangeInt32ToFloat64) {
1019   {
1020     StreamBuilder m(this, MachineType::Float32(), MachineType::Int32());
1021     m.Return(
1022         m.TruncateFloat64ToFloat32(m.ChangeInt32ToFloat64(m.Parameter(0))));
1023     Stream s = m.Build();
1024     ASSERT_EQ(1U, s.size());
1025     EXPECT_EQ(kMips64CvtSW, s[0]->arch_opcode());
1026     EXPECT_EQ(kMode_None, s[0]->addressing_mode());
1027     ASSERT_EQ(1U, s[0]->InputCount());
1028     EXPECT_EQ(1U, s[0]->OutputCount());
1029   }
1030 }
1031 
1032 
TEST_F(InstructionSelectorTest,CombineShiftsWithMul)1033 TEST_F(InstructionSelectorTest, CombineShiftsWithMul) {
1034   {
1035     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
1036     m.Return(m.Int32Mul(m.Word64Sar(m.Parameter(0), m.Int32Constant(32)),
1037                         m.Word64Sar(m.Parameter(0), m.Int32Constant(32))));
1038     Stream s = m.Build();
1039     ASSERT_EQ(1U, s.size());
1040     EXPECT_EQ(kMips64DMulHigh, s[0]->arch_opcode());
1041     EXPECT_EQ(kMode_None, s[0]->addressing_mode());
1042     ASSERT_EQ(2U, s[0]->InputCount());
1043     EXPECT_EQ(1U, s[0]->OutputCount());
1044   }
1045 }
1046 
1047 
TEST_F(InstructionSelectorTest,CombineShiftsWithDivMod)1048 TEST_F(InstructionSelectorTest, CombineShiftsWithDivMod) {
1049   {
1050     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
1051     m.Return(m.Int32Div(m.Word64Sar(m.Parameter(0), m.Int32Constant(32)),
1052                         m.Word64Sar(m.Parameter(0), m.Int32Constant(32))));
1053     Stream s = m.Build();
1054     ASSERT_EQ(1U, s.size());
1055     EXPECT_EQ(kMips64Ddiv, s[0]->arch_opcode());
1056     EXPECT_EQ(kMode_None, s[0]->addressing_mode());
1057     ASSERT_EQ(2U, s[0]->InputCount());
1058     EXPECT_EQ(1U, s[0]->OutputCount());
1059   }
1060   {
1061     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
1062     m.Return(m.Int32Mod(m.Word64Sar(m.Parameter(0), m.Int32Constant(32)),
1063                         m.Word64Sar(m.Parameter(0), m.Int32Constant(32))));
1064     Stream s = m.Build();
1065     ASSERT_EQ(1U, s.size());
1066     EXPECT_EQ(kMips64Dmod, s[0]->arch_opcode());
1067     EXPECT_EQ(kMode_None, s[0]->addressing_mode());
1068     ASSERT_EQ(2U, s[0]->InputCount());
1069     EXPECT_EQ(1U, s[0]->OutputCount());
1070   }
1071 }
1072 
TEST_F(InstructionSelectorTest,ChangeInt32ToInt64AfterLoad)1073 TEST_F(InstructionSelectorTest, ChangeInt32ToInt64AfterLoad) {
1074   // For each case, test that the conversion is merged into the load
1075   // operation.
1076   // ChangeInt32ToInt64(Load_Uint8) -> Lbu
1077   {
1078     StreamBuilder m(this, MachineType::Int64(), MachineType::Pointer(),
1079                     MachineType::Int32());
1080     m.Return(m.ChangeInt32ToInt64(
1081         m.Load(MachineType::Uint8(), m.Parameter(0), m.Parameter(1))));
1082     Stream s = m.Build();
1083     ASSERT_EQ(2U, s.size());
1084     EXPECT_EQ(kMips64Lbu, s[1]->arch_opcode());
1085     EXPECT_EQ(kMode_MRI, s[1]->addressing_mode());
1086     EXPECT_EQ(2U, s[1]->InputCount());
1087     EXPECT_EQ(1U, s[1]->OutputCount());
1088   }
1089   // ChangeInt32ToInt64(Load_Int8) -> Lb
1090   {
1091     StreamBuilder m(this, MachineType::Int64(), MachineType::Pointer(),
1092                     MachineType::Int32());
1093     m.Return(m.ChangeInt32ToInt64(
1094         m.Load(MachineType::Int8(), m.Parameter(0), m.Parameter(1))));
1095     Stream s = m.Build();
1096     ASSERT_EQ(2U, s.size());
1097     EXPECT_EQ(kMips64Lb, s[1]->arch_opcode());
1098     EXPECT_EQ(kMode_MRI, s[1]->addressing_mode());
1099     EXPECT_EQ(2U, s[1]->InputCount());
1100     EXPECT_EQ(1U, s[1]->OutputCount());
1101   }
1102   // ChangeInt32ToInt64(Load_Uint16) -> Lhu
1103   {
1104     StreamBuilder m(this, MachineType::Int64(), MachineType::Pointer(),
1105                     MachineType::Int32());
1106     m.Return(m.ChangeInt32ToInt64(
1107         m.Load(MachineType::Uint16(), m.Parameter(0), m.Parameter(1))));
1108     Stream s = m.Build();
1109     ASSERT_EQ(2U, s.size());
1110     EXPECT_EQ(kMips64Lhu, s[1]->arch_opcode());
1111     EXPECT_EQ(kMode_MRI, s[1]->addressing_mode());
1112     EXPECT_EQ(2U, s[1]->InputCount());
1113     EXPECT_EQ(1U, s[1]->OutputCount());
1114   }
1115   // ChangeInt32ToInt64(Load_Int16) -> Lh
1116   {
1117     StreamBuilder m(this, MachineType::Int64(), MachineType::Pointer(),
1118                     MachineType::Int32());
1119     m.Return(m.ChangeInt32ToInt64(
1120         m.Load(MachineType::Int16(), m.Parameter(0), m.Parameter(1))));
1121     Stream s = m.Build();
1122     ASSERT_EQ(2U, s.size());
1123     EXPECT_EQ(kMips64Lh, s[1]->arch_opcode());
1124     EXPECT_EQ(kMode_MRI, s[1]->addressing_mode());
1125     EXPECT_EQ(2U, s[1]->InputCount());
1126     EXPECT_EQ(1U, s[1]->OutputCount());
1127   }
1128   // ChangeInt32ToInt64(Load_Uint32) -> Lw
1129   {
1130     StreamBuilder m(this, MachineType::Int64(), MachineType::Pointer(),
1131                     MachineType::Int32());
1132     m.Return(m.ChangeInt32ToInt64(
1133         m.Load(MachineType::Uint32(), m.Parameter(0), m.Parameter(1))));
1134     Stream s = m.Build();
1135     ASSERT_EQ(2U, s.size());
1136     EXPECT_EQ(kMips64Lw, s[1]->arch_opcode());
1137     EXPECT_EQ(kMode_MRI, s[1]->addressing_mode());
1138     EXPECT_EQ(2U, s[1]->InputCount());
1139     EXPECT_EQ(1U, s[1]->OutputCount());
1140   }
1141   // ChangeInt32ToInt64(Load_Int32) -> Lw
1142   {
1143     StreamBuilder m(this, MachineType::Int64(), MachineType::Pointer(),
1144                     MachineType::Int32());
1145     m.Return(m.ChangeInt32ToInt64(
1146         m.Load(MachineType::Int32(), m.Parameter(0), m.Parameter(1))));
1147     Stream s = m.Build();
1148     ASSERT_EQ(2U, s.size());
1149     EXPECT_EQ(kMips64Lw, s[1]->arch_opcode());
1150     EXPECT_EQ(kMode_MRI, s[1]->addressing_mode());
1151     EXPECT_EQ(2U, s[1]->InputCount());
1152     EXPECT_EQ(1U, s[1]->OutputCount());
1153   }
1154 }
1155 
1156 using InstructionSelectorElidedChangeUint32ToUint64Test =
1157     InstructionSelectorTestWithParam<MachInst2>;
1158 
TEST_P(InstructionSelectorElidedChangeUint32ToUint64Test,Parameter)1159 TEST_P(InstructionSelectorElidedChangeUint32ToUint64Test, Parameter) {
1160   const MachInst2 binop = GetParam();
1161   StreamBuilder m(this, MachineType::Uint64(), binop.machine_type,
1162                   binop.machine_type);
1163   m.Return(m.ChangeUint32ToUint64(
1164       (m.*binop.constructor)(m.Parameter(0), m.Parameter(1))));
1165   Stream s = m.Build();
1166   // Make sure the `ChangeUint32ToUint64` node turned into a no-op.
1167   if (FLAG_debug_code && binop.arch_opcode == kMips64Cmp) {
1168     ASSERT_EQ(6U, s.size());
1169     EXPECT_EQ(kMips64Cmp, s[0]->arch_opcode());
1170     EXPECT_EQ(kMips64Dshl, s[1]->arch_opcode());
1171     EXPECT_EQ(kMips64Dshl, s[2]->arch_opcode());
1172     EXPECT_EQ(kMips64Cmp, s[3]->arch_opcode());
1173     EXPECT_EQ(kMips64AssertEqual, s[4]->arch_opcode());
1174     EXPECT_EQ(kMips64Cmp, s[5]->arch_opcode());
1175     EXPECT_EQ(2U, s[5]->InputCount());
1176     EXPECT_EQ(1U, s[5]->OutputCount());
1177   } else {
1178     ASSERT_EQ(1U, s.size());
1179     EXPECT_EQ(binop.arch_opcode, s[0]->arch_opcode());
1180     EXPECT_EQ(2U, s[0]->InputCount());
1181     EXPECT_EQ(1U, s[0]->OutputCount());
1182   }
1183 }
1184 
1185 INSTANTIATE_TEST_SUITE_P(InstructionSelectorTest,
1186                          InstructionSelectorElidedChangeUint32ToUint64Test,
1187                          ::testing::ValuesIn(kCanElideChangeUint32ToUint64));
1188 
TEST_F(InstructionSelectorTest,ChangeUint32ToUint64AfterLoad)1189 TEST_F(InstructionSelectorTest, ChangeUint32ToUint64AfterLoad) {
1190   // For each case, make sure the `ChangeUint32ToUint64` node turned into a
1191   // no-op.
1192 
1193   // Lbu
1194   {
1195     StreamBuilder m(this, MachineType::Uint64(), MachineType::Pointer(),
1196                     MachineType::Int32());
1197     m.Return(m.ChangeUint32ToUint64(
1198         m.Load(MachineType::Uint8(), m.Parameter(0), m.Parameter(1))));
1199     Stream s = m.Build();
1200     ASSERT_EQ(2U, s.size());
1201     EXPECT_EQ(kMips64Dadd, s[0]->arch_opcode());
1202     EXPECT_EQ(kMode_None, s[0]->addressing_mode());
1203     EXPECT_EQ(2U, s[0]->InputCount());
1204     EXPECT_EQ(1U, s[0]->OutputCount());
1205     EXPECT_EQ(kMips64Lbu, s[1]->arch_opcode());
1206     EXPECT_EQ(kMode_MRI, s[1]->addressing_mode());
1207     EXPECT_EQ(2U, s[1]->InputCount());
1208     EXPECT_EQ(1U, s[1]->OutputCount());
1209   }
1210   // Lhu
1211   {
1212     StreamBuilder m(this, MachineType::Uint64(), MachineType::Pointer(),
1213                     MachineType::Int32());
1214     m.Return(m.ChangeUint32ToUint64(
1215         m.Load(MachineType::Uint16(), m.Parameter(0), m.Parameter(1))));
1216     Stream s = m.Build();
1217     ASSERT_EQ(2U, s.size());
1218     EXPECT_EQ(kMips64Dadd, s[0]->arch_opcode());
1219     EXPECT_EQ(kMode_None, s[0]->addressing_mode());
1220     EXPECT_EQ(2U, s[0]->InputCount());
1221     EXPECT_EQ(1U, s[0]->OutputCount());
1222     EXPECT_EQ(kMips64Lhu, s[1]->arch_opcode());
1223     EXPECT_EQ(kMode_MRI, s[1]->addressing_mode());
1224     EXPECT_EQ(2U, s[1]->InputCount());
1225     EXPECT_EQ(1U, s[1]->OutputCount());
1226   }
1227   // Lwu
1228   {
1229     StreamBuilder m(this, MachineType::Uint64(), MachineType::Pointer(),
1230                     MachineType::Int32());
1231     m.Return(m.ChangeUint32ToUint64(
1232         m.Load(MachineType::Uint32(), m.Parameter(0), m.Parameter(1))));
1233     Stream s = m.Build();
1234     ASSERT_EQ(2U, s.size());
1235     EXPECT_EQ(kMips64Dadd, s[0]->arch_opcode());
1236     EXPECT_EQ(kMode_None, s[0]->addressing_mode());
1237     EXPECT_EQ(2U, s[0]->InputCount());
1238     EXPECT_EQ(1U, s[0]->OutputCount());
1239     EXPECT_EQ(kMips64Lwu, s[1]->arch_opcode());
1240     EXPECT_EQ(kMode_MRI, s[1]->addressing_mode());
1241     EXPECT_EQ(2U, s[1]->InputCount());
1242     EXPECT_EQ(1U, s[1]->OutputCount());
1243   }
1244 }
1245 
1246 // ----------------------------------------------------------------------------
1247 // Loads and stores.
1248 // ----------------------------------------------------------------------------
1249 
1250 
1251 namespace {
1252 
1253 struct MemoryAccess {
1254   MachineType type;
1255   ArchOpcode load_opcode;
1256   ArchOpcode store_opcode;
1257 };
1258 
1259 static const MemoryAccess kMemoryAccesses[] = {
1260     {MachineType::Int8(), kMips64Lb, kMips64Sb},
1261     {MachineType::Uint8(), kMips64Lbu, kMips64Sb},
1262     {MachineType::Int16(), kMips64Lh, kMips64Sh},
1263     {MachineType::Uint16(), kMips64Lhu, kMips64Sh},
1264     {MachineType::Int32(), kMips64Lw, kMips64Sw},
1265     {MachineType::Float32(), kMips64Lwc1, kMips64Swc1},
1266     {MachineType::Float64(), kMips64Ldc1, kMips64Sdc1},
1267     {MachineType::Int64(), kMips64Ld, kMips64Sd}};
1268 
1269 
1270 struct MemoryAccessImm {
1271   MachineType type;
1272   ArchOpcode load_opcode;
1273   ArchOpcode store_opcode;
1274   bool (InstructionSelectorTest::Stream::*val_predicate)(
1275       const InstructionOperand*) const;
1276   const int32_t immediates[40];
1277 };
1278 
1279 
operator <<(std::ostream & os,const MemoryAccessImm & acc)1280 std::ostream& operator<<(std::ostream& os, const MemoryAccessImm& acc) {
1281   return os << acc.type;
1282 }
1283 
1284 
1285 struct MemoryAccessImm1 {
1286   MachineType type;
1287   ArchOpcode load_opcode;
1288   ArchOpcode store_opcode;
1289   bool (InstructionSelectorTest::Stream::*val_predicate)(
1290       const InstructionOperand*) const;
1291   const int32_t immediates[5];
1292 };
1293 
1294 
operator <<(std::ostream & os,const MemoryAccessImm1 & acc)1295 std::ostream& operator<<(std::ostream& os, const MemoryAccessImm1& acc) {
1296   return os << acc.type;
1297 }
1298 
1299 struct MemoryAccessImm2 {
1300   MachineType type;
1301   ArchOpcode store_opcode;
1302   ArchOpcode store_opcode_unaligned;
1303   bool (InstructionSelectorTest::Stream::*val_predicate)(
1304       const InstructionOperand*) const;
1305   const int32_t immediates[40];
1306 };
1307 
operator <<(std::ostream & os,const MemoryAccessImm2 & acc)1308 std::ostream& operator<<(std::ostream& os, const MemoryAccessImm2& acc) {
1309   return os << acc.type;
1310 }
1311 
1312 // ----------------------------------------------------------------------------
1313 // Loads and stores immediate values
1314 // ----------------------------------------------------------------------------
1315 
1316 
1317 const MemoryAccessImm kMemoryAccessesImm[] = {
1318     {MachineType::Int8(),
1319      kMips64Lb,
1320      kMips64Sb,
1321      &InstructionSelectorTest::Stream::IsInteger,
1322      {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89,
1323       -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109,
1324       115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}},
1325     {MachineType::Uint8(),
1326      kMips64Lbu,
1327      kMips64Sb,
1328      &InstructionSelectorTest::Stream::IsInteger,
1329      {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89,
1330       -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109,
1331       115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}},
1332     {MachineType::Int16(),
1333      kMips64Lh,
1334      kMips64Sh,
1335      &InstructionSelectorTest::Stream::IsInteger,
1336      {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89,
1337       -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109,
1338       115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}},
1339     {MachineType::Uint16(),
1340      kMips64Lhu,
1341      kMips64Sh,
1342      &InstructionSelectorTest::Stream::IsInteger,
1343      {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89,
1344       -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109,
1345       115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}},
1346     {MachineType::Int32(),
1347      kMips64Lw,
1348      kMips64Sw,
1349      &InstructionSelectorTest::Stream::IsInteger,
1350      {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89,
1351       -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109,
1352       115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}},
1353     {MachineType::Float32(),
1354      kMips64Lwc1,
1355      kMips64Swc1,
1356      &InstructionSelectorTest::Stream::IsDouble,
1357      {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89,
1358       -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109,
1359       115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}},
1360     {MachineType::Float64(),
1361      kMips64Ldc1,
1362      kMips64Sdc1,
1363      &InstructionSelectorTest::Stream::IsDouble,
1364      {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89,
1365       -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109,
1366       115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}},
1367     {MachineType::Int64(),
1368      kMips64Ld,
1369      kMips64Sd,
1370      &InstructionSelectorTest::Stream::IsInteger,
1371      {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89,
1372       -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109,
1373       115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}}};
1374 
1375 const MemoryAccessImm1 kMemoryAccessImmMoreThan16bit[] = {
1376     {MachineType::Int8(),
1377      kMips64Lb,
1378      kMips64Sb,
1379      &InstructionSelectorTest::Stream::IsInteger,
1380      {-65000, -55000, 32777, 55000, 65000}},
1381     {MachineType::Uint8(),
1382      kMips64Lbu,
1383      kMips64Sb,
1384      &InstructionSelectorTest::Stream::IsInteger,
1385      {-65000, -55000, 32777, 55000, 65000}},
1386     {MachineType::Int16(),
1387      kMips64Lh,
1388      kMips64Sh,
1389      &InstructionSelectorTest::Stream::IsInteger,
1390      {-65000, -55000, 32777, 55000, 65000}},
1391     {MachineType::Uint16(),
1392      kMips64Lhu,
1393      kMips64Sh,
1394      &InstructionSelectorTest::Stream::IsInteger,
1395      {-65000, -55000, 32777, 55000, 65000}},
1396     {MachineType::Int32(),
1397      kMips64Lw,
1398      kMips64Sw,
1399      &InstructionSelectorTest::Stream::IsInteger,
1400      {-65000, -55000, 32777, 55000, 65000}},
1401     {MachineType::Float32(),
1402      kMips64Lwc1,
1403      kMips64Swc1,
1404      &InstructionSelectorTest::Stream::IsDouble,
1405      {-65000, -55000, 32777, 55000, 65000}},
1406     {MachineType::Float64(),
1407      kMips64Ldc1,
1408      kMips64Sdc1,
1409      &InstructionSelectorTest::Stream::IsDouble,
1410      {-65000, -55000, 32777, 55000, 65000}},
1411     {MachineType::Int64(),
1412      kMips64Ld,
1413      kMips64Sd,
1414      &InstructionSelectorTest::Stream::IsInteger,
1415      {-65000, -55000, 32777, 55000, 65000}}};
1416 
1417 const MemoryAccessImm2 kMemoryAccessesImmUnaligned[] = {
1418     {MachineType::Int16(),
1419      kMips64Ush,
1420      kMips64Sh,
1421      &InstructionSelectorTest::Stream::IsInteger,
1422      {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91,
1423       -89,   -87,   -86,   -82,   -44,   -23,   -3,    0,    7,    10,
1424       39,    52,    69,    71,    91,    92,    107,   109,  115,  124,
1425       286,   655,   1362,  1569,  2587,  3067,  3096,  3462, 3510, 4095}},
1426     {MachineType::Int32(),
1427      kMips64Usw,
1428      kMips64Sw,
1429      &InstructionSelectorTest::Stream::IsInteger,
1430      {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91,
1431       -89,   -87,   -86,   -82,   -44,   -23,   -3,    0,    7,    10,
1432       39,    52,    69,    71,    91,    92,    107,   109,  115,  124,
1433       286,   655,   1362,  1569,  2587,  3067,  3096,  3462, 3510, 4095}},
1434     {MachineType::Int64(),
1435      kMips64Usd,
1436      kMips64Sd,
1437      &InstructionSelectorTest::Stream::IsInteger,
1438      {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91,
1439       -89,   -87,   -86,   -82,   -44,   -23,   -3,    0,    7,    10,
1440       39,    52,    69,    71,    91,    92,    107,   109,  115,  124,
1441       286,   655,   1362,  1569,  2587,  3067,  3096,  3462, 3510, 4095}},
1442     {MachineType::Float32(),
1443      kMips64Uswc1,
1444      kMips64Swc1,
1445      &InstructionSelectorTest::Stream::IsDouble,
1446      {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91,
1447       -89,   -87,   -86,   -82,   -44,   -23,   -3,    0,    7,    10,
1448       39,    52,    69,    71,    91,    92,    107,   109,  115,  124,
1449       286,   655,   1362,  1569,  2587,  3067,  3096,  3462, 3510, 4095}},
1450     {MachineType::Float64(),
1451      kMips64Usdc1,
1452      kMips64Sdc1,
1453      &InstructionSelectorTest::Stream::IsDouble,
1454      {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91,
1455       -89,   -87,   -86,   -82,   -44,   -23,   -3,    0,    7,    10,
1456       39,    52,    69,    71,    91,    92,    107,   109,  115,  124,
1457       286,   655,   1362,  1569,  2587,  3067,  3096,  3462, 3510, 4095}}};
1458 
1459 }  // namespace
1460 
1461 using InstructionSelectorMemoryAccessTest =
1462     InstructionSelectorTestWithParam<MemoryAccess>;
1463 
TEST_P(InstructionSelectorMemoryAccessTest,LoadWithParameters)1464 TEST_P(InstructionSelectorMemoryAccessTest, LoadWithParameters) {
1465   const MemoryAccess memacc = GetParam();
1466   StreamBuilder m(this, memacc.type, MachineType::Pointer(),
1467                   MachineType::Int32());
1468   m.Return(m.Load(memacc.type, m.Parameter(0)));
1469   Stream s = m.Build();
1470   ASSERT_EQ(1U, s.size());
1471   EXPECT_EQ(memacc.load_opcode, s[0]->arch_opcode());
1472   EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
1473 }
1474 
1475 
TEST_P(InstructionSelectorMemoryAccessTest,StoreWithParameters)1476 TEST_P(InstructionSelectorMemoryAccessTest, StoreWithParameters) {
1477   const MemoryAccess memacc = GetParam();
1478   StreamBuilder m(this, MachineType::Int32(), MachineType::Pointer(),
1479                   MachineType::Int32(), memacc.type);
1480   m.Store(memacc.type.representation(), m.Parameter(0), m.Parameter(1),
1481           kNoWriteBarrier);
1482   m.Return(m.Int32Constant(0));
1483   Stream s = m.Build();
1484   ASSERT_EQ(1U, s.size());
1485   EXPECT_EQ(memacc.store_opcode, s[0]->arch_opcode());
1486   EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
1487 }
1488 
1489 INSTANTIATE_TEST_SUITE_P(InstructionSelectorTest,
1490                          InstructionSelectorMemoryAccessTest,
1491                          ::testing::ValuesIn(kMemoryAccesses));
1492 
1493 // ----------------------------------------------------------------------------
1494 // Load immediate.
1495 // ----------------------------------------------------------------------------
1496 
1497 using InstructionSelectorMemoryAccessImmTest =
1498     InstructionSelectorTestWithParam<MemoryAccessImm>;
1499 
TEST_P(InstructionSelectorMemoryAccessImmTest,LoadWithImmediateIndex)1500 TEST_P(InstructionSelectorMemoryAccessImmTest, LoadWithImmediateIndex) {
1501   const MemoryAccessImm memacc = GetParam();
1502   TRACED_FOREACH(int32_t, index, memacc.immediates) {
1503     StreamBuilder m(this, memacc.type, MachineType::Pointer());
1504     m.Return(m.Load(memacc.type, m.Parameter(0), m.Int32Constant(index)));
1505     Stream s = m.Build();
1506     ASSERT_EQ(1U, s.size());
1507     EXPECT_EQ(memacc.load_opcode, s[0]->arch_opcode());
1508     EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
1509     ASSERT_EQ(2U, s[0]->InputCount());
1510     ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
1511     EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1)));
1512     ASSERT_EQ(1U, s[0]->OutputCount());
1513     EXPECT_TRUE((s.*memacc.val_predicate)(s[0]->Output()));
1514   }
1515 }
1516 
1517 
1518 // ----------------------------------------------------------------------------
1519 // Store immediate.
1520 // ----------------------------------------------------------------------------
1521 
1522 
TEST_P(InstructionSelectorMemoryAccessImmTest,StoreWithImmediateIndex)1523 TEST_P(InstructionSelectorMemoryAccessImmTest, StoreWithImmediateIndex) {
1524   const MemoryAccessImm memacc = GetParam();
1525   TRACED_FOREACH(int32_t, index, memacc.immediates) {
1526     StreamBuilder m(this, MachineType::Int32(), MachineType::Pointer(),
1527                     memacc.type);
1528     m.Store(memacc.type.representation(), m.Parameter(0),
1529             m.Int32Constant(index), m.Parameter(1), kNoWriteBarrier);
1530     m.Return(m.Int32Constant(0));
1531     Stream s = m.Build();
1532     ASSERT_EQ(1U, s.size());
1533     EXPECT_EQ(memacc.store_opcode, s[0]->arch_opcode());
1534     EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
1535     ASSERT_EQ(3U, s[0]->InputCount());
1536     ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
1537     EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1)));
1538     EXPECT_EQ(0U, s[0]->OutputCount());
1539   }
1540 }
1541 
TEST_P(InstructionSelectorMemoryAccessImmTest,StoreZero)1542 TEST_P(InstructionSelectorMemoryAccessImmTest, StoreZero) {
1543   const MemoryAccessImm memacc = GetParam();
1544   TRACED_FOREACH(int32_t, index, memacc.immediates) {
1545     StreamBuilder m(this, MachineType::Int32(), MachineType::Pointer());
1546     m.Store(memacc.type.representation(), m.Parameter(0),
1547             m.Int32Constant(index), m.Int32Constant(0), kNoWriteBarrier);
1548     m.Return(m.Int32Constant(0));
1549     Stream s = m.Build();
1550     ASSERT_EQ(1U, s.size());
1551     EXPECT_EQ(memacc.store_opcode, s[0]->arch_opcode());
1552     EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
1553     ASSERT_EQ(3U, s[0]->InputCount());
1554     ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
1555     EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1)));
1556     ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(2)->kind());
1557     EXPECT_EQ(0, s.ToInt64(s[0]->InputAt(2)));
1558     EXPECT_EQ(0U, s[0]->OutputCount());
1559   }
1560 }
1561 
1562 INSTANTIATE_TEST_SUITE_P(InstructionSelectorTest,
1563                          InstructionSelectorMemoryAccessImmTest,
1564                          ::testing::ValuesIn(kMemoryAccessesImm));
1565 
1566 using InstructionSelectorMemoryAccessUnalignedImmTest =
1567     InstructionSelectorTestWithParam<MemoryAccessImm2>;
1568 
TEST_P(InstructionSelectorMemoryAccessUnalignedImmTest,StoreZero)1569 TEST_P(InstructionSelectorMemoryAccessUnalignedImmTest, StoreZero) {
1570   const MemoryAccessImm2 memacc = GetParam();
1571   TRACED_FOREACH(int32_t, index, memacc.immediates) {
1572     StreamBuilder m(this, MachineType::Int32(), MachineType::Pointer());
1573     bool unaligned_store_supported =
1574         m.machine()->UnalignedStoreSupported(memacc.type.representation());
1575     m.UnalignedStore(memacc.type.representation(), m.Parameter(0),
1576                      m.Int32Constant(index), m.Int32Constant(0));
1577     m.Return(m.Int32Constant(0));
1578     Stream s = m.Build();
1579     ASSERT_EQ(1U, s.size());
1580     EXPECT_EQ(unaligned_store_supported ? memacc.store_opcode_unaligned
1581                                         : memacc.store_opcode,
1582               s[0]->arch_opcode());
1583     EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
1584     ASSERT_EQ(3U, s[0]->InputCount());
1585     ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
1586     EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1)));
1587     ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(2)->kind());
1588     EXPECT_EQ(0, s.ToInt64(s[0]->InputAt(2)));
1589     EXPECT_EQ(0U, s[0]->OutputCount());
1590   }
1591 }
1592 
1593 INSTANTIATE_TEST_SUITE_P(InstructionSelectorTest,
1594                          InstructionSelectorMemoryAccessUnalignedImmTest,
1595                          ::testing::ValuesIn(kMemoryAccessesImmUnaligned));
1596 
1597 // ----------------------------------------------------------------------------
1598 // Load/store offsets more than 16 bits.
1599 // ----------------------------------------------------------------------------
1600 
1601 using InstructionSelectorMemoryAccessImmMoreThan16bitTest =
1602     InstructionSelectorTestWithParam<MemoryAccessImm1>;
1603 
TEST_P(InstructionSelectorMemoryAccessImmMoreThan16bitTest,LoadWithImmediateIndex)1604 TEST_P(InstructionSelectorMemoryAccessImmMoreThan16bitTest,
1605        LoadWithImmediateIndex) {
1606   const MemoryAccessImm1 memacc = GetParam();
1607   TRACED_FOREACH(int32_t, index, memacc.immediates) {
1608     StreamBuilder m(this, memacc.type, MachineType::Pointer());
1609     m.Return(m.Load(memacc.type, m.Parameter(0), m.Int32Constant(index)));
1610     Stream s = m.Build();
1611     ASSERT_EQ(1U, s.size());
1612     EXPECT_EQ(memacc.load_opcode, s[0]->arch_opcode());
1613     EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
1614     EXPECT_EQ(2U, s[0]->InputCount());
1615     EXPECT_EQ(1U, s[0]->OutputCount());
1616   }
1617 }
1618 
TEST_P(InstructionSelectorMemoryAccessImmMoreThan16bitTest,StoreWithImmediateIndex)1619 TEST_P(InstructionSelectorMemoryAccessImmMoreThan16bitTest,
1620        StoreWithImmediateIndex) {
1621   const MemoryAccessImm1 memacc = GetParam();
1622   TRACED_FOREACH(int32_t, index, memacc.immediates) {
1623     StreamBuilder m(this, MachineType::Int32(), MachineType::Pointer(),
1624                     memacc.type);
1625     m.Store(memacc.type.representation(), m.Parameter(0),
1626             m.Int32Constant(index), m.Parameter(1), kNoWriteBarrier);
1627     m.Return(m.Int32Constant(0));
1628     Stream s = m.Build();
1629     ASSERT_EQ(1U, s.size());
1630     EXPECT_EQ(memacc.store_opcode, s[0]->arch_opcode());
1631     EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
1632     EXPECT_EQ(3U, s[0]->InputCount());
1633     EXPECT_EQ(0U, s[0]->OutputCount());
1634   }
1635 }
1636 
1637 INSTANTIATE_TEST_SUITE_P(InstructionSelectorTest,
1638                          InstructionSelectorMemoryAccessImmMoreThan16bitTest,
1639                          ::testing::ValuesIn(kMemoryAccessImmMoreThan16bit));
1640 
1641 // ----------------------------------------------------------------------------
1642 // kMips64Cmp with zero testing.
1643 // ----------------------------------------------------------------------------
1644 
1645 
TEST_F(InstructionSelectorTest,Word32EqualWithZero)1646 TEST_F(InstructionSelectorTest, Word32EqualWithZero) {
1647   {
1648     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
1649     m.Return(m.Word32Equal(m.Parameter(0), m.Int32Constant(0)));
1650     Stream s = m.Build();
1651     ASSERT_EQ(1U, s.size());
1652     EXPECT_EQ(kMips64Cmp, s[0]->arch_opcode());
1653     EXPECT_EQ(kMode_None, s[0]->addressing_mode());
1654     ASSERT_EQ(2U, s[0]->InputCount());
1655     EXPECT_EQ(1U, s[0]->OutputCount());
1656     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1657     EXPECT_EQ(kEqual, s[0]->flags_condition());
1658   }
1659   {
1660     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
1661     m.Return(m.Word32Equal(m.Int32Constant(0), m.Parameter(0)));
1662     Stream s = m.Build();
1663     ASSERT_EQ(1U, s.size());
1664     EXPECT_EQ(kMips64Cmp, s[0]->arch_opcode());
1665     EXPECT_EQ(kMode_None, s[0]->addressing_mode());
1666     ASSERT_EQ(2U, s[0]->InputCount());
1667     EXPECT_EQ(1U, s[0]->OutputCount());
1668     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1669     EXPECT_EQ(kEqual, s[0]->flags_condition());
1670   }
1671 }
1672 
1673 
TEST_F(InstructionSelectorTest,Word64EqualWithZero)1674 TEST_F(InstructionSelectorTest, Word64EqualWithZero) {
1675   {
1676     StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
1677     m.Return(m.Word64Equal(m.Parameter(0), m.Int64Constant(0)));
1678     Stream s = m.Build();
1679     ASSERT_EQ(1U, s.size());
1680     EXPECT_EQ(kMips64Cmp, s[0]->arch_opcode());
1681     EXPECT_EQ(kMode_None, s[0]->addressing_mode());
1682     ASSERT_EQ(2U, s[0]->InputCount());
1683     EXPECT_EQ(1U, s[0]->OutputCount());
1684     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1685     EXPECT_EQ(kEqual, s[0]->flags_condition());
1686   }
1687   {
1688     StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
1689     m.Return(m.Word64Equal(m.Int32Constant(0), m.Parameter(0)));
1690     Stream s = m.Build();
1691     ASSERT_EQ(1U, s.size());
1692     EXPECT_EQ(kMips64Cmp, s[0]->arch_opcode());
1693     EXPECT_EQ(kMode_None, s[0]->addressing_mode());
1694     ASSERT_EQ(2U, s[0]->InputCount());
1695     EXPECT_EQ(1U, s[0]->OutputCount());
1696     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1697     EXPECT_EQ(kEqual, s[0]->flags_condition());
1698   }
1699 }
1700 
1701 
TEST_F(InstructionSelectorTest,Word32Clz)1702 TEST_F(InstructionSelectorTest, Word32Clz) {
1703   StreamBuilder m(this, MachineType::Uint32(), MachineType::Uint32());
1704   Node* const p0 = m.Parameter(0);
1705   Node* const n = m.Word32Clz(p0);
1706   m.Return(n);
1707   Stream s = m.Build();
1708   ASSERT_EQ(1U, s.size());
1709   EXPECT_EQ(kMips64Clz, s[0]->arch_opcode());
1710   ASSERT_EQ(1U, s[0]->InputCount());
1711   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1712   ASSERT_EQ(1U, s[0]->OutputCount());
1713   EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1714 }
1715 
1716 
TEST_F(InstructionSelectorTest,Word64Clz)1717 TEST_F(InstructionSelectorTest, Word64Clz) {
1718   StreamBuilder m(this, MachineType::Uint64(), MachineType::Uint64());
1719   Node* const p0 = m.Parameter(0);
1720   Node* const n = m.Word64Clz(p0);
1721   m.Return(n);
1722   Stream s = m.Build();
1723   ASSERT_EQ(1U, s.size());
1724   EXPECT_EQ(kMips64Dclz, s[0]->arch_opcode());
1725   ASSERT_EQ(1U, s[0]->InputCount());
1726   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1727   ASSERT_EQ(1U, s[0]->OutputCount());
1728   EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1729 }
1730 
1731 
TEST_F(InstructionSelectorTest,Float32Abs)1732 TEST_F(InstructionSelectorTest, Float32Abs) {
1733   StreamBuilder m(this, MachineType::Float32(), MachineType::Float32());
1734   Node* const p0 = m.Parameter(0);
1735   Node* const n = m.Float32Abs(p0);
1736   m.Return(n);
1737   Stream s = m.Build();
1738   ASSERT_EQ(1U, s.size());
1739   EXPECT_EQ(kMips64AbsS, s[0]->arch_opcode());
1740   ASSERT_EQ(1U, s[0]->InputCount());
1741   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1742   ASSERT_EQ(1U, s[0]->OutputCount());
1743   EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1744 }
1745 
1746 
TEST_F(InstructionSelectorTest,Float64Abs)1747 TEST_F(InstructionSelectorTest, Float64Abs) {
1748   StreamBuilder m(this, MachineType::Float64(), MachineType::Float64());
1749   Node* const p0 = m.Parameter(0);
1750   Node* const n = m.Float64Abs(p0);
1751   m.Return(n);
1752   Stream s = m.Build();
1753   ASSERT_EQ(1U, s.size());
1754   EXPECT_EQ(kMips64AbsD, s[0]->arch_opcode());
1755   ASSERT_EQ(1U, s[0]->InputCount());
1756   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1757   ASSERT_EQ(1U, s[0]->OutputCount());
1758   EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1759 }
1760 
1761 
TEST_F(InstructionSelectorTest,Float64Max)1762 TEST_F(InstructionSelectorTest, Float64Max) {
1763   StreamBuilder m(this, MachineType::Float64(), MachineType::Float64(),
1764                   MachineType::Float64());
1765   Node* const p0 = m.Parameter(0);
1766   Node* const p1 = m.Parameter(1);
1767   Node* const n = m.Float64Max(p0, p1);
1768   m.Return(n);
1769   Stream s = m.Build();
1770   ASSERT_EQ(1U, s.size());
1771   EXPECT_EQ(kMips64Float64Max, s[0]->arch_opcode());
1772   ASSERT_EQ(2U, s[0]->InputCount());
1773   ASSERT_EQ(1U, s[0]->OutputCount());
1774   EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1775 }
1776 
1777 
TEST_F(InstructionSelectorTest,Float64Min)1778 TEST_F(InstructionSelectorTest, Float64Min) {
1779   StreamBuilder m(this, MachineType::Float64(), MachineType::Float64(),
1780                   MachineType::Float64());
1781   Node* const p0 = m.Parameter(0);
1782   Node* const p1 = m.Parameter(1);
1783   Node* const n = m.Float64Min(p0, p1);
1784   m.Return(n);
1785   Stream s = m.Build();
1786   ASSERT_EQ(1U, s.size());
1787   EXPECT_EQ(kMips64Float64Min, s[0]->arch_opcode());
1788   ASSERT_EQ(2U, s[0]->InputCount());
1789   ASSERT_EQ(1U, s[0]->OutputCount());
1790   EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1791 }
1792 
TEST_F(InstructionSelectorTest,LoadAndShiftRight)1793 TEST_F(InstructionSelectorTest, LoadAndShiftRight) {
1794   {
1795     int32_t immediates[] = {-256, -255, -3,   -2,   -1,    0,    1,
1796                             2,    3,    255,  256,  260,   4096, 4100,
1797                             8192, 8196, 3276, 3280, 16376, 16380};
1798     TRACED_FOREACH(int32_t, index, immediates) {
1799       StreamBuilder m(this, MachineType::Uint64(), MachineType::Pointer());
1800       Node* const load =
1801           m.Load(MachineType::Uint64(), m.Parameter(0), m.Int32Constant(index));
1802       Node* const sar = m.Word64Sar(load, m.Int32Constant(32));
1803       // Make sure we don't fold the shift into the following add:
1804       m.Return(m.Int64Add(sar, m.Parameter(0)));
1805       Stream s = m.Build();
1806       ASSERT_EQ(2U, s.size());
1807       EXPECT_EQ(kMips64Lw, s[0]->arch_opcode());
1808       EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
1809       EXPECT_EQ(2U, s[0]->InputCount());
1810       EXPECT_EQ(s.ToVreg(m.Parameter(0)), s.ToVreg(s[0]->InputAt(0)));
1811       ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
1812 #if defined(V8_TARGET_LITTLE_ENDIAN)
1813       EXPECT_EQ(index + 4, s.ToInt32(s[0]->InputAt(1)));
1814 #elif defined(V8_TARGET_BIG_ENDIAN)
1815       EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1)));
1816 #endif
1817 
1818       ASSERT_EQ(1U, s[0]->OutputCount());
1819     }
1820   }
1821 }
1822 
TEST_F(InstructionSelectorTest,Word32ReverseBytes)1823 TEST_F(InstructionSelectorTest, Word32ReverseBytes) {
1824   {
1825     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
1826     m.Return(m.Word32ReverseBytes(m.Parameter(0)));
1827     Stream s = m.Build();
1828     ASSERT_EQ(1U, s.size());
1829     EXPECT_EQ(kMips64ByteSwap32, s[0]->arch_opcode());
1830     EXPECT_EQ(1U, s[0]->InputCount());
1831     EXPECT_EQ(1U, s[0]->OutputCount());
1832   }
1833 }
1834 
TEST_F(InstructionSelectorTest,Word64ReverseBytes)1835 TEST_F(InstructionSelectorTest, Word64ReverseBytes) {
1836   {
1837     StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
1838     m.Return(m.Word64ReverseBytes(m.Parameter(0)));
1839     Stream s = m.Build();
1840     ASSERT_EQ(1U, s.size());
1841     EXPECT_EQ(kMips64ByteSwap64, s[0]->arch_opcode());
1842     EXPECT_EQ(1U, s[0]->InputCount());
1843     EXPECT_EQ(1U, s[0]->OutputCount());
1844   }
1845 }
1846 
1847 }  // namespace compiler
1848 }  // namespace internal
1849 }  // namespace v8
1850