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
5 #include "test/unittests/compiler/instruction-selector-unittest.h"
15 const char* constructor_name;
16 ArchOpcode arch_opcode;
17 MachineType machine_type;
21 std::ostream& operator<<(std::ostream& os, const MachInst<T>& mi) {
22 return os << mi.constructor_name;
25 typedef MachInst<Node* (RawMachineAssembler::*)(Node*)> MachInst1;
26 typedef MachInst<Node* (RawMachineAssembler::*)(Node*, Node*)> MachInst2;
29 // To avoid duplicated code IntCmp helper structure
30 // is created. It contains MachInst2 with two nodes and expected_size
31 // because different cmp instructions have different size.
34 uint32_t expected_size;
42 const FPCmp kFPCmpInstructions[] = {
43 {{&RawMachineAssembler::Float64Equal, "Float64Equal", kMips64CmpD,
46 {{&RawMachineAssembler::Float64LessThan, "Float64LessThan", kMips64CmpD,
49 {{&RawMachineAssembler::Float64LessThanOrEqual, "Float64LessThanOrEqual",
50 kMips64CmpD, kMachFloat64},
51 kUnsignedLessThanOrEqual},
52 {{&RawMachineAssembler::Float64GreaterThan, "Float64GreaterThan",
53 kMips64CmpD, kMachFloat64},
55 {{&RawMachineAssembler::Float64GreaterThanOrEqual,
56 "Float64GreaterThanOrEqual", kMips64CmpD, kMachFloat64},
57 kUnsignedLessThanOrEqual}};
60 // The machine_type field in MachInst1 represents the destination type.
62 MachineType src_machine_type;
66 // ----------------------------------------------------------------------------
67 // Logical instructions.
68 // ----------------------------------------------------------------------------
71 const MachInst2 kLogicalInstructions[] = {
72 {&RawMachineAssembler::Word32And, "Word32And", kMips64And, kMachInt32},
73 {&RawMachineAssembler::Word64And, "Word64And", kMips64And, kMachInt64},
74 {&RawMachineAssembler::Word32Or, "Word32Or", kMips64Or, kMachInt32},
75 {&RawMachineAssembler::Word64Or, "Word64Or", kMips64Or, kMachInt64},
76 {&RawMachineAssembler::Word32Xor, "Word32Xor", kMips64Xor, kMachInt32},
77 {&RawMachineAssembler::Word64Xor, "Word64Xor", kMips64Xor, kMachInt64}};
80 // ----------------------------------------------------------------------------
81 // Shift instructions.
82 // ----------------------------------------------------------------------------
85 const MachInst2 kShiftInstructions[] = {
86 {&RawMachineAssembler::Word32Shl, "Word32Shl", kMips64Shl, kMachInt32},
87 {&RawMachineAssembler::Word64Shl, "Word64Shl", kMips64Dshl, kMachInt64},
88 {&RawMachineAssembler::Word32Shr, "Word32Shr", kMips64Shr, kMachInt32},
89 {&RawMachineAssembler::Word64Shr, "Word64Shr", kMips64Dshr, kMachInt64},
90 {&RawMachineAssembler::Word32Sar, "Word32Sar", kMips64Sar, kMachInt32},
91 {&RawMachineAssembler::Word64Sar, "Word64Sar", kMips64Dsar, kMachInt64},
92 {&RawMachineAssembler::Word32Ror, "Word32Ror", kMips64Ror, kMachInt32},
93 {&RawMachineAssembler::Word64Ror, "Word64Ror", kMips64Dror, kMachInt64}};
96 // ----------------------------------------------------------------------------
97 // MUL/DIV instructions.
98 // ----------------------------------------------------------------------------
101 const MachInst2 kMulDivInstructions[] = {
102 {&RawMachineAssembler::Int32Mul, "Int32Mul", kMips64Mul, kMachInt32},
103 {&RawMachineAssembler::Int32Div, "Int32Div", kMips64Div, kMachInt32},
104 {&RawMachineAssembler::Uint32Div, "Uint32Div", kMips64DivU, kMachUint32},
105 {&RawMachineAssembler::Int64Mul, "Int64Mul", kMips64Dmul, kMachInt64},
106 {&RawMachineAssembler::Int64Div, "Int64Div", kMips64Ddiv, kMachInt64},
107 {&RawMachineAssembler::Uint64Div, "Uint64Div", kMips64DdivU, kMachUint64},
108 {&RawMachineAssembler::Float64Mul, "Float64Mul", kMips64MulD, kMachFloat64},
109 {&RawMachineAssembler::Float64Div, "Float64Div", kMips64DivD,
113 // ----------------------------------------------------------------------------
115 // ----------------------------------------------------------------------------
118 const MachInst2 kModInstructions[] = {
119 {&RawMachineAssembler::Int32Mod, "Int32Mod", kMips64Mod, kMachInt32},
120 {&RawMachineAssembler::Uint32Mod, "Uint32Mod", kMips64ModU, kMachInt32},
121 {&RawMachineAssembler::Float64Mod, "Float64Mod", kMips64ModD,
125 // ----------------------------------------------------------------------------
126 // Arithmetic FPU instructions.
127 // ----------------------------------------------------------------------------
130 const MachInst2 kFPArithInstructions[] = {
131 {&RawMachineAssembler::Float64Add, "Float64Add", kMips64AddD, kMachFloat64},
132 {&RawMachineAssembler::Float64Sub, "Float64Sub", kMips64SubD,
136 // ----------------------------------------------------------------------------
137 // IntArithTest instructions, two nodes.
138 // ----------------------------------------------------------------------------
141 const MachInst2 kAddSubInstructions[] = {
142 {&RawMachineAssembler::Int32Add, "Int32Add", kMips64Add, kMachInt32},
143 {&RawMachineAssembler::Int64Add, "Int64Add", kMips64Dadd, kMachInt64},
144 {&RawMachineAssembler::Int32Sub, "Int32Sub", kMips64Sub, kMachInt32},
145 {&RawMachineAssembler::Int64Sub, "Int64Sub", kMips64Dsub, kMachInt64}};
148 // ----------------------------------------------------------------------------
149 // IntArithTest instructions, one node.
150 // ----------------------------------------------------------------------------
153 const MachInst1 kAddSubOneInstructions[] = {
154 {&RawMachineAssembler::Int32Neg, "Int32Neg", kMips64Sub, kMachInt32},
155 {&RawMachineAssembler::Int64Neg, "Int64Neg", kMips64Dsub, kMachInt64}};
158 // ----------------------------------------------------------------------------
159 // Arithmetic compare instructions.
160 // ----------------------------------------------------------------------------
163 const IntCmp kCmpInstructions[] = {
164 {{&RawMachineAssembler::WordEqual, "WordEqual", kMips64Cmp, kMachInt64},
166 {{&RawMachineAssembler::WordNotEqual, "WordNotEqual", kMips64Cmp,
169 {{&RawMachineAssembler::Word32Equal, "Word32Equal", kMips64Cmp32,
172 {{&RawMachineAssembler::Word32NotEqual, "Word32NotEqual", kMips64Cmp32,
175 {{&RawMachineAssembler::Int32LessThan, "Int32LessThan", kMips64Cmp32,
178 {{&RawMachineAssembler::Int32LessThanOrEqual, "Int32LessThanOrEqual",
179 kMips64Cmp32, kMachInt32},
181 {{&RawMachineAssembler::Int32GreaterThan, "Int32GreaterThan", kMips64Cmp32,
184 {{&RawMachineAssembler::Int32GreaterThanOrEqual, "Int32GreaterThanOrEqual",
185 kMips64Cmp32, kMachInt32},
187 {{&RawMachineAssembler::Uint32LessThan, "Uint32LessThan", kMips64Cmp32,
190 {{&RawMachineAssembler::Uint32LessThanOrEqual, "Uint32LessThanOrEqual",
191 kMips64Cmp32, kMachUint32},
195 // ----------------------------------------------------------------------------
196 // Conversion instructions.
197 // ----------------------------------------------------------------------------
199 const Conversion kConversionInstructions[] = {
200 // Conversion instructions are related to machine_operator.h:
202 // Convert representation of integers between float64 and int32/uint32.
203 // The precise rounding mode and handling of out of range inputs are *not*
204 // defined for these operators, since they are intended only for use with
206 // mips instructions:
208 {{&RawMachineAssembler::ChangeInt32ToFloat64, "ChangeInt32ToFloat64",
209 kMips64CvtDW, kMachFloat64},
212 // mips instructions:
214 {{&RawMachineAssembler::ChangeUint32ToFloat64, "ChangeUint32ToFloat64",
215 kMips64CvtDUw, kMachFloat64},
218 // mips instructions:
219 // mfc1, trunc double to word, for more details look at mips macro
220 // asm and mips asm file
221 {{&RawMachineAssembler::ChangeFloat64ToInt32, "ChangeFloat64ToInt32",
222 kMips64TruncWD, kMachFloat64},
225 // mips instructions:
226 // trunc double to unsigned word, for more details look at mips macro
227 // asm and mips asm file
228 {{&RawMachineAssembler::ChangeFloat64ToUint32, "ChangeFloat64ToUint32",
229 kMips64TruncUwD, kMachFloat64},
235 typedef InstructionSelectorTestWithParam<FPCmp> InstructionSelectorFPCmpTest;
237 TEST_P(InstructionSelectorFPCmpTest, Parameter) {
238 const FPCmp cmp = GetParam();
239 StreamBuilder m(this, kMachInt32, cmp.mi.machine_type, cmp.mi.machine_type);
240 m.Return((m.*cmp.mi.constructor)(m.Parameter(0), m.Parameter(1)));
241 Stream s = m.Build();
242 ASSERT_EQ(1U, s.size());
243 EXPECT_EQ(cmp.mi.arch_opcode, s[0]->arch_opcode());
244 EXPECT_EQ(2U, s[0]->InputCount());
245 EXPECT_EQ(1U, s[0]->OutputCount());
246 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
247 EXPECT_EQ(cmp.cond, s[0]->flags_condition());
250 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorFPCmpTest,
251 ::testing::ValuesIn(kFPCmpInstructions));
253 // ----------------------------------------------------------------------------
254 // Arithmetic compare instructions integers
255 // ----------------------------------------------------------------------------
256 typedef InstructionSelectorTestWithParam<IntCmp> InstructionSelectorCmpTest;
259 TEST_P(InstructionSelectorCmpTest, Parameter) {
260 const IntCmp cmp = GetParam();
261 const MachineType type = cmp.mi.machine_type;
262 StreamBuilder m(this, type, type, type);
263 m.Return((m.*cmp.mi.constructor)(m.Parameter(0), m.Parameter(1)));
264 Stream s = m.Build();
265 ASSERT_EQ(cmp.expected_size, s.size());
266 EXPECT_EQ(cmp.mi.arch_opcode, s[0]->arch_opcode());
267 EXPECT_EQ(2U, s[0]->InputCount());
268 EXPECT_EQ(1U, s[0]->OutputCount());
271 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorCmpTest,
272 ::testing::ValuesIn(kCmpInstructions));
274 // ----------------------------------------------------------------------------
275 // Shift instructions.
276 // ----------------------------------------------------------------------------
277 typedef InstructionSelectorTestWithParam<MachInst2>
278 InstructionSelectorShiftTest;
280 TEST_P(InstructionSelectorShiftTest, Immediate) {
281 const MachInst2 dpi = GetParam();
282 const MachineType type = dpi.machine_type;
283 TRACED_FORRANGE(int32_t, imm, 0, (ElementSizeOf(type) * 8) - 1) {
284 StreamBuilder m(this, type, type);
285 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm)));
286 Stream s = m.Build();
287 ASSERT_EQ(1U, s.size());
288 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
289 EXPECT_EQ(2U, s[0]->InputCount());
290 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
291 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
292 EXPECT_EQ(1U, s[0]->OutputCount());
296 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorShiftTest,
297 ::testing::ValuesIn(kShiftInstructions));
299 // ----------------------------------------------------------------------------
300 // Logical instructions.
301 // ----------------------------------------------------------------------------
302 typedef InstructionSelectorTestWithParam<MachInst2>
303 InstructionSelectorLogicalTest;
306 TEST_P(InstructionSelectorLogicalTest, Parameter) {
307 const MachInst2 dpi = GetParam();
308 const MachineType type = dpi.machine_type;
309 StreamBuilder m(this, type, type, type);
310 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)));
311 Stream s = m.Build();
312 ASSERT_EQ(1U, s.size());
313 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
314 EXPECT_EQ(2U, s[0]->InputCount());
315 EXPECT_EQ(1U, s[0]->OutputCount());
318 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorLogicalTest,
319 ::testing::ValuesIn(kLogicalInstructions));
321 // ----------------------------------------------------------------------------
322 // MUL/DIV instructions.
323 // ----------------------------------------------------------------------------
324 typedef InstructionSelectorTestWithParam<MachInst2>
325 InstructionSelectorMulDivTest;
327 TEST_P(InstructionSelectorMulDivTest, Parameter) {
328 const MachInst2 dpi = GetParam();
329 const MachineType type = dpi.machine_type;
330 StreamBuilder m(this, type, type, type);
331 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)));
332 Stream s = m.Build();
333 ASSERT_EQ(1U, s.size());
334 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
335 EXPECT_EQ(2U, s[0]->InputCount());
336 EXPECT_EQ(1U, s[0]->OutputCount());
339 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorMulDivTest,
340 ::testing::ValuesIn(kMulDivInstructions));
342 // ----------------------------------------------------------------------------
344 // ----------------------------------------------------------------------------
345 typedef InstructionSelectorTestWithParam<MachInst2> InstructionSelectorModTest;
347 TEST_P(InstructionSelectorModTest, Parameter) {
348 const MachInst2 dpi = GetParam();
349 const MachineType type = dpi.machine_type;
350 StreamBuilder m(this, type, type, type);
351 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)));
352 Stream s = m.Build();
353 ASSERT_EQ(1U, s.size());
354 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
355 EXPECT_EQ(2U, s[0]->InputCount());
356 EXPECT_EQ(1U, s[0]->OutputCount());
359 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorModTest,
360 ::testing::ValuesIn(kModInstructions));
362 // ----------------------------------------------------------------------------
363 // Floating point instructions.
364 // ----------------------------------------------------------------------------
365 typedef InstructionSelectorTestWithParam<MachInst2>
366 InstructionSelectorFPArithTest;
368 TEST_P(InstructionSelectorFPArithTest, Parameter) {
369 const MachInst2 fpa = GetParam();
370 StreamBuilder m(this, fpa.machine_type, fpa.machine_type, fpa.machine_type);
371 m.Return((m.*fpa.constructor)(m.Parameter(0), m.Parameter(1)));
372 Stream s = m.Build();
373 ASSERT_EQ(1U, s.size());
374 EXPECT_EQ(fpa.arch_opcode, s[0]->arch_opcode());
375 EXPECT_EQ(2U, s[0]->InputCount());
376 EXPECT_EQ(1U, s[0]->OutputCount());
379 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorFPArithTest,
380 ::testing::ValuesIn(kFPArithInstructions));
381 // ----------------------------------------------------------------------------
382 // Integer arithmetic
383 // ----------------------------------------------------------------------------
384 typedef InstructionSelectorTestWithParam<MachInst2>
385 InstructionSelectorIntArithTwoTest;
387 TEST_P(InstructionSelectorIntArithTwoTest, Parameter) {
388 const MachInst2 intpa = GetParam();
389 StreamBuilder m(this, intpa.machine_type, intpa.machine_type,
391 m.Return((m.*intpa.constructor)(m.Parameter(0), m.Parameter(1)));
392 Stream s = m.Build();
393 ASSERT_EQ(1U, s.size());
394 EXPECT_EQ(intpa.arch_opcode, s[0]->arch_opcode());
395 EXPECT_EQ(2U, s[0]->InputCount());
396 EXPECT_EQ(1U, s[0]->OutputCount());
399 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
400 InstructionSelectorIntArithTwoTest,
401 ::testing::ValuesIn(kAddSubInstructions));
404 // ----------------------------------------------------------------------------
406 // ----------------------------------------------------------------------------
409 typedef InstructionSelectorTestWithParam<MachInst1>
410 InstructionSelectorIntArithOneTest;
412 TEST_P(InstructionSelectorIntArithOneTest, Parameter) {
413 const MachInst1 intpa = GetParam();
414 StreamBuilder m(this, intpa.machine_type, intpa.machine_type,
416 m.Return((m.*intpa.constructor)(m.Parameter(0)));
417 Stream s = m.Build();
418 ASSERT_EQ(1U, s.size());
419 EXPECT_EQ(intpa.arch_opcode, s[0]->arch_opcode());
420 EXPECT_EQ(2U, s[0]->InputCount());
421 EXPECT_EQ(1U, s[0]->OutputCount());
424 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
425 InstructionSelectorIntArithOneTest,
426 ::testing::ValuesIn(kAddSubOneInstructions));
427 // ----------------------------------------------------------------------------
429 // ----------------------------------------------------------------------------
430 typedef InstructionSelectorTestWithParam<Conversion>
431 InstructionSelectorConversionTest;
433 TEST_P(InstructionSelectorConversionTest, Parameter) {
434 const Conversion conv = GetParam();
435 StreamBuilder m(this, conv.mi.machine_type, conv.src_machine_type);
436 m.Return((m.*conv.mi.constructor)(m.Parameter(0)));
437 Stream s = m.Build();
438 ASSERT_EQ(1U, s.size());
439 EXPECT_EQ(conv.mi.arch_opcode, s[0]->arch_opcode());
440 EXPECT_EQ(1U, s[0]->InputCount());
441 EXPECT_EQ(1U, s[0]->OutputCount());
444 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
445 InstructionSelectorConversionTest,
446 ::testing::ValuesIn(kConversionInstructions));
449 // ----------------------------------------------------------------------------
451 // ----------------------------------------------------------------------------
456 struct MemoryAccess {
458 ArchOpcode load_opcode;
459 ArchOpcode store_opcode;
462 static const MemoryAccess kMemoryAccesses[] = {
463 {kMachInt8, kMips64Lb, kMips64Sb},
464 {kMachUint8, kMips64Lbu, kMips64Sb},
465 {kMachInt16, kMips64Lh, kMips64Sh},
466 {kMachUint16, kMips64Lhu, kMips64Sh},
467 {kMachInt32, kMips64Lw, kMips64Sw},
468 {kRepFloat32, kMips64Lwc1, kMips64Swc1},
469 {kRepFloat64, kMips64Ldc1, kMips64Sdc1},
470 {kMachInt64, kMips64Ld, kMips64Sd}};
473 struct MemoryAccessImm {
475 ArchOpcode load_opcode;
476 ArchOpcode store_opcode;
477 bool (InstructionSelectorTest::Stream::*val_predicate)(
478 const InstructionOperand*) const;
479 const int32_t immediates[40];
483 std::ostream& operator<<(std::ostream& os, const MemoryAccessImm& acc) {
484 return os << acc.type;
488 struct MemoryAccessImm1 {
490 ArchOpcode load_opcode;
491 ArchOpcode store_opcode;
492 bool (InstructionSelectorTest::Stream::*val_predicate)(
493 const InstructionOperand*) const;
494 const int32_t immediates[5];
498 std::ostream& operator<<(std::ostream& os, const MemoryAccessImm1& acc) {
499 return os << acc.type;
503 // ----------------------------------------------------------------------------
504 // Loads and stores immediate values
505 // ----------------------------------------------------------------------------
508 const MemoryAccessImm kMemoryAccessesImm[] = {
512 &InstructionSelectorTest::Stream::IsInteger,
513 {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89,
514 -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109,
515 115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}},
519 &InstructionSelectorTest::Stream::IsInteger,
520 {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89,
521 -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109,
522 115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}},
526 &InstructionSelectorTest::Stream::IsInteger,
527 {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89,
528 -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109,
529 115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}},
533 &InstructionSelectorTest::Stream::IsInteger,
534 {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89,
535 -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109,
536 115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}},
540 &InstructionSelectorTest::Stream::IsInteger,
541 {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89,
542 -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109,
543 115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}},
547 &InstructionSelectorTest::Stream::IsDouble,
548 {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89,
549 -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109,
550 115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}},
554 &InstructionSelectorTest::Stream::IsDouble,
555 {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89,
556 -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109,
557 115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}},
561 &InstructionSelectorTest::Stream::IsInteger,
562 {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89,
563 -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109,
564 115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}}};
567 const MemoryAccessImm1 kMemoryAccessImmMoreThan16bit[] = {
571 &InstructionSelectorTest::Stream::IsInteger,
572 {-65000, -55000, 32777, 55000, 65000}},
576 &InstructionSelectorTest::Stream::IsInteger,
577 {-65000, -55000, 32777, 55000, 65000}},
581 &InstructionSelectorTest::Stream::IsInteger,
582 {-65000, -55000, 32777, 55000, 65000}},
586 &InstructionSelectorTest::Stream::IsInteger,
587 {-65000, -55000, 32777, 55000, 65000}},
591 &InstructionSelectorTest::Stream::IsInteger,
592 {-65000, -55000, 32777, 55000, 65000}},
596 &InstructionSelectorTest::Stream::IsDouble,
597 {-65000, -55000, 32777, 55000, 65000}},
601 &InstructionSelectorTest::Stream::IsDouble,
602 {-65000, -55000, 32777, 55000, 65000}},
606 &InstructionSelectorTest::Stream::IsInteger,
607 {-65000, -55000, 32777, 55000, 65000}}};
612 typedef InstructionSelectorTestWithParam<MemoryAccess>
613 InstructionSelectorMemoryAccessTest;
615 TEST_P(InstructionSelectorMemoryAccessTest, LoadWithParameters) {
616 const MemoryAccess memacc = GetParam();
617 StreamBuilder m(this, memacc.type, kMachPtr, kMachInt32);
618 m.Return(m.Load(memacc.type, m.Parameter(0)));
619 Stream s = m.Build();
620 ASSERT_EQ(1U, s.size());
621 EXPECT_EQ(memacc.load_opcode, s[0]->arch_opcode());
622 EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
626 TEST_P(InstructionSelectorMemoryAccessTest, StoreWithParameters) {
627 const MemoryAccess memacc = GetParam();
628 StreamBuilder m(this, kMachInt32, kMachPtr, kMachInt32, memacc.type);
629 m.Store(memacc.type, m.Parameter(0), m.Parameter(1));
630 m.Return(m.Int32Constant(0));
631 Stream s = m.Build();
632 ASSERT_EQ(1U, s.size());
633 EXPECT_EQ(memacc.store_opcode, s[0]->arch_opcode());
634 EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
637 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
638 InstructionSelectorMemoryAccessTest,
639 ::testing::ValuesIn(kMemoryAccesses));
642 // ----------------------------------------------------------------------------
644 // ----------------------------------------------------------------------------
647 typedef InstructionSelectorTestWithParam<MemoryAccessImm>
648 InstructionSelectorMemoryAccessImmTest;
650 TEST_P(InstructionSelectorMemoryAccessImmTest, LoadWithImmediateIndex) {
651 const MemoryAccessImm memacc = GetParam();
652 TRACED_FOREACH(int32_t, index, memacc.immediates) {
653 StreamBuilder m(this, memacc.type, kMachPtr);
654 m.Return(m.Load(memacc.type, m.Parameter(0), m.Int32Constant(index)));
655 Stream s = m.Build();
656 ASSERT_EQ(1U, s.size());
657 EXPECT_EQ(memacc.load_opcode, s[0]->arch_opcode());
658 EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
659 ASSERT_EQ(2U, s[0]->InputCount());
660 ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
661 EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1)));
662 ASSERT_EQ(1U, s[0]->OutputCount());
663 EXPECT_TRUE((s.*memacc.val_predicate)(s[0]->Output()));
668 // ----------------------------------------------------------------------------
670 // ----------------------------------------------------------------------------
673 TEST_P(InstructionSelectorMemoryAccessImmTest, StoreWithImmediateIndex) {
674 const MemoryAccessImm memacc = GetParam();
675 TRACED_FOREACH(int32_t, index, memacc.immediates) {
676 StreamBuilder m(this, kMachInt32, kMachPtr, memacc.type);
677 m.Store(memacc.type, m.Parameter(0), m.Int32Constant(index),
679 m.Return(m.Int32Constant(0));
680 Stream s = m.Build();
681 ASSERT_EQ(1U, s.size());
682 EXPECT_EQ(memacc.store_opcode, s[0]->arch_opcode());
683 EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
684 ASSERT_EQ(3U, s[0]->InputCount());
685 ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
686 EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1)));
687 EXPECT_EQ(0U, s[0]->OutputCount());
691 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
692 InstructionSelectorMemoryAccessImmTest,
693 ::testing::ValuesIn(kMemoryAccessesImm));
696 // ----------------------------------------------------------------------------
697 // Load/store offsets more than 16 bits.
698 // ----------------------------------------------------------------------------
701 typedef InstructionSelectorTestWithParam<MemoryAccessImm1>
702 InstructionSelectorMemoryAccessImmMoreThan16bitTest;
704 TEST_P(InstructionSelectorMemoryAccessImmMoreThan16bitTest,
705 LoadWithImmediateIndex) {
706 const MemoryAccessImm1 memacc = GetParam();
707 TRACED_FOREACH(int32_t, index, memacc.immediates) {
708 StreamBuilder m(this, memacc.type, kMachPtr);
709 m.Return(m.Load(memacc.type, m.Parameter(0), m.Int32Constant(index)));
710 Stream s = m.Build();
711 ASSERT_EQ(2U, s.size());
712 // kMips64Dadd is expected opcode
713 // size more than 16 bits wide
714 EXPECT_EQ(kMips64Dadd, s[0]->arch_opcode());
715 EXPECT_EQ(kMode_None, s[0]->addressing_mode());
716 EXPECT_EQ(2U, s[0]->InputCount());
717 EXPECT_EQ(1U, s[0]->OutputCount());
721 TEST_P(InstructionSelectorMemoryAccessImmMoreThan16bitTest,
722 StoreWithImmediateIndex) {
723 const MemoryAccessImm1 memacc = GetParam();
724 TRACED_FOREACH(int32_t, index, memacc.immediates) {
725 StreamBuilder m(this, kMachInt32, kMachPtr, memacc.type);
726 m.Store(memacc.type, m.Parameter(0), m.Int32Constant(index),
728 m.Return(m.Int32Constant(0));
729 Stream s = m.Build();
730 ASSERT_EQ(2U, s.size());
731 // kMips64Add is expected opcode
732 // size more than 16 bits wide
733 EXPECT_EQ(kMips64Dadd, s[0]->arch_opcode());
734 EXPECT_EQ(kMode_None, s[0]->addressing_mode());
735 EXPECT_EQ(2U, s[0]->InputCount());
736 EXPECT_EQ(1U, s[0]->OutputCount());
740 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
741 InstructionSelectorMemoryAccessImmMoreThan16bitTest,
742 ::testing::ValuesIn(kMemoryAccessImmMoreThan16bit));
745 // ----------------------------------------------------------------------------
746 // kMips64Cmp with zero testing.
747 // ----------------------------------------------------------------------------
750 TEST_F(InstructionSelectorTest, Word32EqualWithZero) {
752 StreamBuilder m(this, kMachInt32, kMachInt32);
753 m.Return(m.Word32Equal(m.Parameter(0), m.Int32Constant(0)));
754 Stream s = m.Build();
755 ASSERT_EQ(1U, s.size());
756 EXPECT_EQ(kMips64Cmp32, s[0]->arch_opcode());
757 EXPECT_EQ(kMode_None, s[0]->addressing_mode());
758 ASSERT_EQ(2U, s[0]->InputCount());
759 EXPECT_EQ(1U, s[0]->OutputCount());
760 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
761 EXPECT_EQ(kEqual, s[0]->flags_condition());
764 StreamBuilder m(this, kMachInt32, kMachInt32);
765 m.Return(m.Word32Equal(m.Int32Constant(0), m.Parameter(0)));
766 Stream s = m.Build();
767 ASSERT_EQ(1U, s.size());
768 EXPECT_EQ(kMips64Cmp32, s[0]->arch_opcode());
769 EXPECT_EQ(kMode_None, s[0]->addressing_mode());
770 ASSERT_EQ(2U, s[0]->InputCount());
771 EXPECT_EQ(1U, s[0]->OutputCount());
772 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
773 EXPECT_EQ(kEqual, s[0]->flags_condition());
778 TEST_F(InstructionSelectorTest, Word64EqualWithZero) {
780 StreamBuilder m(this, kMachInt64, kMachInt64);
781 m.Return(m.Word64Equal(m.Parameter(0), m.Int64Constant(0)));
782 Stream s = m.Build();
783 ASSERT_EQ(1U, s.size());
784 EXPECT_EQ(kMips64Cmp, s[0]->arch_opcode());
785 EXPECT_EQ(kMode_None, s[0]->addressing_mode());
786 ASSERT_EQ(2U, s[0]->InputCount());
787 EXPECT_EQ(1U, s[0]->OutputCount());
788 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
789 EXPECT_EQ(kEqual, s[0]->flags_condition());
792 StreamBuilder m(this, kMachInt64, kMachInt64);
793 m.Return(m.Word64Equal(m.Int32Constant(0), m.Parameter(0)));
794 Stream s = m.Build();
795 ASSERT_EQ(1U, s.size());
796 EXPECT_EQ(kMips64Cmp, s[0]->arch_opcode());
797 EXPECT_EQ(kMode_None, s[0]->addressing_mode());
798 ASSERT_EQ(2U, s[0]->InputCount());
799 EXPECT_EQ(1U, s[0]->OutputCount());
800 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
801 EXPECT_EQ(kEqual, s[0]->flags_condition());
805 } // namespace compiler
806 } // namespace internal