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