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"
16 const char* constructor_name;
17 ArchOpcode arch_opcode;
18 MachineType machine_type;
22 std::ostream& operator<<(std::ostream& os, const MachInst<T>& mi) {
23 return os << mi.constructor_name;
26 typedef MachInst<Node* (RawMachineAssembler::*)(Node*)> MachInst1;
27 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", kMipsCmpD,
46 {{&RawMachineAssembler::Float64LessThan, "Float64LessThan", kMipsCmpD,
49 {{&RawMachineAssembler::Float64LessThanOrEqual, "Float64LessThanOrEqual",
50 kMipsCmpD, kMachFloat64},
51 kUnsignedLessThanOrEqual},
52 {{&RawMachineAssembler::Float64GreaterThan, "Float64GreaterThan", kMipsCmpD,
55 {{&RawMachineAssembler::Float64GreaterThanOrEqual,
56 "Float64GreaterThanOrEqual", kMipsCmpD, 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::WordAnd, "WordAnd", kMipsAnd, kMachInt16},
73 {&RawMachineAssembler::WordOr, "WordOr", kMipsOr, kMachInt16},
74 {&RawMachineAssembler::WordXor, "WordXor", kMipsXor, kMachInt16},
75 {&RawMachineAssembler::Word32And, "Word32And", kMipsAnd, kMachInt32},
76 {&RawMachineAssembler::Word32Or, "Word32Or", kMipsOr, kMachInt32},
77 {&RawMachineAssembler::Word32Xor, "Word32Xor", kMipsXor, kMachInt32}};
80 // ----------------------------------------------------------------------------
81 // Shift instructions.
82 // ----------------------------------------------------------------------------
85 const MachInst2 kShiftInstructions[] = {
86 {&RawMachineAssembler::WordShl, "WordShl", kMipsShl, kMachInt16},
87 {&RawMachineAssembler::WordShr, "WordShr", kMipsShr, kMachInt16},
88 {&RawMachineAssembler::WordSar, "WordSar", kMipsSar, kMachInt16},
89 {&RawMachineAssembler::WordRor, "WordRor", kMipsRor, kMachInt16},
90 {&RawMachineAssembler::Word32Shl, "Word32Shl", kMipsShl, kMachInt32},
91 {&RawMachineAssembler::Word32Shr, "Word32Shr", kMipsShr, kMachInt32},
92 {&RawMachineAssembler::Word32Sar, "Word32Sar", kMipsSar, kMachInt32},
93 {&RawMachineAssembler::Word32Ror, "Word32Ror", kMipsRor, kMachInt32}};
96 // ----------------------------------------------------------------------------
97 // MUL/DIV instructions.
98 // ----------------------------------------------------------------------------
101 const MachInst2 kMulDivInstructions[] = {
102 {&RawMachineAssembler::Int32Mul, "Int32Mul", kMipsMul, kMachInt32},
103 {&RawMachineAssembler::Int32Div, "Int32Div", kMipsDiv, kMachInt32},
104 {&RawMachineAssembler::Uint32Div, "Uint32Div", kMipsDivU, kMachUint32},
105 {&RawMachineAssembler::Float64Mul, "Float64Mul", kMipsMulD, kMachFloat64},
106 {&RawMachineAssembler::Float64Div, "Float64Div", kMipsDivD, kMachFloat64}};
109 // ----------------------------------------------------------------------------
111 // ----------------------------------------------------------------------------
114 const MachInst2 kModInstructions[] = {
115 {&RawMachineAssembler::Int32Mod, "Int32Mod", kMipsMod, kMachInt32},
116 {&RawMachineAssembler::Uint32Mod, "Int32UMod", kMipsModU, kMachInt32},
117 {&RawMachineAssembler::Float64Mod, "Float64Mod", kMipsModD, kMachFloat64}};
120 // ----------------------------------------------------------------------------
121 // Arithmetic FPU instructions.
122 // ----------------------------------------------------------------------------
125 const MachInst2 kFPArithInstructions[] = {
126 {&RawMachineAssembler::Float64Add, "Float64Add", kMipsAddD, kMachFloat64},
127 {&RawMachineAssembler::Float64Sub, "Float64Sub", kMipsSubD, kMachFloat64}};
130 // ----------------------------------------------------------------------------
131 // IntArithTest instructions, two nodes.
132 // ----------------------------------------------------------------------------
135 const MachInst2 kAddSubInstructions[] = {
136 {&RawMachineAssembler::Int32Add, "Int32Add", kMipsAdd, kMachInt32},
137 {&RawMachineAssembler::Int32Sub, "Int32Sub", kMipsSub, kMachInt32},
138 {&RawMachineAssembler::Int32AddWithOverflow, "Int32AddWithOverflow",
139 kMipsAddOvf, kMachInt32},
140 {&RawMachineAssembler::Int32SubWithOverflow, "Int32SubWithOverflow",
141 kMipsSubOvf, kMachInt32}};
144 // ----------------------------------------------------------------------------
145 // IntArithTest instructions, one node.
146 // ----------------------------------------------------------------------------
149 const MachInst1 kAddSubOneInstructions[] = {
150 {&RawMachineAssembler::Int32Neg, "Int32Neg", kMipsSub, kMachInt32},
151 // TODO(dusmil): check this ...
152 // {&RawMachineAssembler::WordEqual , "WordEqual" , kMipsTst, kMachInt32}
156 // ----------------------------------------------------------------------------
157 // Arithmetic compare instructions.
158 // ----------------------------------------------------------------------------
161 const IntCmp kCmpInstructions[] = {
162 {{&RawMachineAssembler::WordEqual, "WordEqual", kMipsCmp, kMachInt16}, 1U},
163 {{&RawMachineAssembler::WordNotEqual, "WordNotEqual", kMipsCmp, kMachInt16},
165 {{&RawMachineAssembler::Word32Equal, "Word32Equal", kMipsCmp, kMachInt32},
167 {{&RawMachineAssembler::Word32NotEqual, "Word32NotEqual", kMipsCmp,
170 {{&RawMachineAssembler::Int32LessThan, "Int32LessThan", kMipsCmp,
173 {{&RawMachineAssembler::Int32LessThanOrEqual, "Int32LessThanOrEqual",
174 kMipsCmp, kMachInt32},
176 {{&RawMachineAssembler::Int32GreaterThan, "Int32GreaterThan", kMipsCmp,
179 {{&RawMachineAssembler::Int32GreaterThanOrEqual, "Int32GreaterThanOrEqual",
180 kMipsCmp, kMachInt32},
182 {{&RawMachineAssembler::Uint32LessThan, "Uint32LessThan", kMipsCmp,
185 {{&RawMachineAssembler::Uint32LessThanOrEqual, "Uint32LessThanOrEqual",
186 kMipsCmp, kMachUint32},
190 // ----------------------------------------------------------------------------
191 // Conversion instructions.
192 // ----------------------------------------------------------------------------
194 const Conversion kConversionInstructions[] = {
195 // Conversion instructions are related to machine_operator.h:
197 // Convert representation of integers between float64 and int32/uint32.
198 // The precise rounding mode and handling of out of range inputs are *not*
199 // defined for these operators, since they are intended only for use with
201 // mips instruction: cvt_d_w
202 {{&RawMachineAssembler::ChangeInt32ToFloat64, "ChangeInt32ToFloat64",
203 kMipsCvtDW, kMachFloat64},
206 // mips instruction: cvt_d_uw
207 {{&RawMachineAssembler::ChangeUint32ToFloat64, "ChangeUint32ToFloat64",
208 kMipsCvtDUw, kMachFloat64},
211 // mips instruction: trunc_w_d
212 {{&RawMachineAssembler::ChangeFloat64ToInt32, "ChangeFloat64ToInt32",
213 kMipsTruncWD, kMachFloat64},
216 // mips instruction: trunc_uw_d
217 {{&RawMachineAssembler::ChangeFloat64ToUint32, "ChangeFloat64ToUint32",
218 kMipsTruncUwD, kMachFloat64},
224 typedef InstructionSelectorTestWithParam<FPCmp> InstructionSelectorFPCmpTest;
227 TEST_P(InstructionSelectorFPCmpTest, Parameter) {
228 const FPCmp cmp = GetParam();
229 StreamBuilder m(this, kMachInt32, cmp.mi.machine_type, cmp.mi.machine_type);
230 m.Return((m.*cmp.mi.constructor)(m.Parameter(0), m.Parameter(1)));
231 Stream s = m.Build();
232 ASSERT_EQ(1U, s.size());
233 EXPECT_EQ(cmp.mi.arch_opcode, s[0]->arch_opcode());
234 EXPECT_EQ(2U, s[0]->InputCount());
235 EXPECT_EQ(1U, s[0]->OutputCount());
236 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
237 EXPECT_EQ(cmp.cond, s[0]->flags_condition());
240 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorFPCmpTest,
241 ::testing::ValuesIn(kFPCmpInstructions));
244 // ----------------------------------------------------------------------------
245 // Arithmetic compare instructions integers.
246 // ----------------------------------------------------------------------------
249 typedef InstructionSelectorTestWithParam<IntCmp> InstructionSelectorCmpTest;
252 TEST_P(InstructionSelectorCmpTest, Parameter) {
253 const IntCmp cmp = GetParam();
254 const MachineType type = cmp.mi.machine_type;
255 StreamBuilder m(this, type, type, type);
256 m.Return((m.*cmp.mi.constructor)(m.Parameter(0), m.Parameter(1)));
257 Stream s = m.Build();
258 ASSERT_EQ(cmp.expected_size, s.size());
259 EXPECT_EQ(cmp.mi.arch_opcode, s[0]->arch_opcode());
260 EXPECT_EQ(2U, s[0]->InputCount());
261 EXPECT_EQ(1U, s[0]->OutputCount());
265 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorCmpTest,
266 ::testing::ValuesIn(kCmpInstructions));
269 // ----------------------------------------------------------------------------
270 // Shift instructions.
271 // ----------------------------------------------------------------------------
274 typedef InstructionSelectorTestWithParam<MachInst2>
275 InstructionSelectorShiftTest;
278 TEST_P(InstructionSelectorShiftTest, Immediate) {
279 const MachInst2 dpi = GetParam();
280 const MachineType type = dpi.machine_type;
281 TRACED_FORRANGE(int32_t, imm, 0, (ElementSizeOf(type) * 8) - 1) {
282 StreamBuilder m(this, type, type);
283 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm)));
284 Stream s = m.Build();
285 ASSERT_EQ(1U, s.size());
286 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
287 EXPECT_EQ(2U, s[0]->InputCount());
288 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
289 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
290 EXPECT_EQ(1U, s[0]->OutputCount());
295 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorShiftTest,
296 ::testing::ValuesIn(kShiftInstructions));
299 // ----------------------------------------------------------------------------
300 // Logical instructions.
301 // ----------------------------------------------------------------------------
304 typedef InstructionSelectorTestWithParam<MachInst2>
305 InstructionSelectorLogicalTest;
308 TEST_P(InstructionSelectorLogicalTest, Parameter) {
309 const MachInst2 dpi = GetParam();
310 const MachineType type = dpi.machine_type;
311 StreamBuilder m(this, type, type, type);
312 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)));
313 Stream s = m.Build();
314 ASSERT_EQ(1U, s.size());
315 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
316 EXPECT_EQ(2U, s[0]->InputCount());
317 EXPECT_EQ(1U, s[0]->OutputCount());
321 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorLogicalTest,
322 ::testing::ValuesIn(kLogicalInstructions));
325 // ----------------------------------------------------------------------------
326 // MUL/DIV instructions.
327 // ----------------------------------------------------------------------------
330 typedef InstructionSelectorTestWithParam<MachInst2>
331 InstructionSelectorMulDivTest;
334 TEST_P(InstructionSelectorMulDivTest, Parameter) {
335 const MachInst2 dpi = GetParam();
336 const MachineType type = dpi.machine_type;
337 StreamBuilder m(this, type, type, type);
338 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)));
339 Stream s = m.Build();
340 ASSERT_EQ(1U, s.size());
341 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
342 EXPECT_EQ(2U, s[0]->InputCount());
343 EXPECT_EQ(1U, s[0]->OutputCount());
347 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorMulDivTest,
348 ::testing::ValuesIn(kMulDivInstructions));
351 // ----------------------------------------------------------------------------
353 // ----------------------------------------------------------------------------
356 typedef InstructionSelectorTestWithParam<MachInst2> InstructionSelectorModTest;
359 TEST_P(InstructionSelectorModTest, Parameter) {
360 const MachInst2 dpi = GetParam();
361 const MachineType type = dpi.machine_type;
362 StreamBuilder m(this, type, type, type);
363 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)));
364 Stream s = m.Build();
365 ASSERT_EQ(1U, s.size());
366 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
367 EXPECT_EQ(2U, s[0]->InputCount());
368 EXPECT_EQ(1U, s[0]->OutputCount());
372 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorModTest,
373 ::testing::ValuesIn(kModInstructions));
376 // ----------------------------------------------------------------------------
377 // Floating point instructions.
378 // ----------------------------------------------------------------------------
381 typedef InstructionSelectorTestWithParam<MachInst2>
382 InstructionSelectorFPArithTest;
385 TEST_P(InstructionSelectorFPArithTest, Parameter) {
386 const MachInst2 fpa = GetParam();
387 StreamBuilder m(this, fpa.machine_type, fpa.machine_type, fpa.machine_type);
388 m.Return((m.*fpa.constructor)(m.Parameter(0), m.Parameter(1)));
389 Stream s = m.Build();
390 ASSERT_EQ(1U, s.size());
391 EXPECT_EQ(fpa.arch_opcode, s[0]->arch_opcode());
392 EXPECT_EQ(2U, s[0]->InputCount());
393 EXPECT_EQ(1U, s[0]->OutputCount());
397 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorFPArithTest,
398 ::testing::ValuesIn(kFPArithInstructions));
401 // ----------------------------------------------------------------------------
402 // Integer arithmetic.
403 // ----------------------------------------------------------------------------
406 typedef InstructionSelectorTestWithParam<MachInst2>
407 InstructionSelectorIntArithTwoTest;
410 TEST_P(InstructionSelectorIntArithTwoTest, Parameter) {
411 const MachInst2 intpa = GetParam();
412 StreamBuilder m(this, intpa.machine_type, intpa.machine_type,
414 m.Return((m.*intpa.constructor)(m.Parameter(0), m.Parameter(1)));
415 Stream s = m.Build();
416 ASSERT_EQ(1U, s.size());
417 EXPECT_EQ(intpa.arch_opcode, s[0]->arch_opcode());
418 EXPECT_EQ(2U, s[0]->InputCount());
419 EXPECT_EQ(1U, s[0]->OutputCount());
423 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
424 InstructionSelectorIntArithTwoTest,
425 ::testing::ValuesIn(kAddSubInstructions));
428 // ----------------------------------------------------------------------------
430 // ----------------------------------------------------------------------------
433 typedef InstructionSelectorTestWithParam<MachInst1>
434 InstructionSelectorIntArithOneTest;
437 TEST_P(InstructionSelectorIntArithOneTest, Parameter) {
438 const MachInst1 intpa = GetParam();
439 StreamBuilder m(this, intpa.machine_type, intpa.machine_type,
441 m.Return((m.*intpa.constructor)(m.Parameter(0)));
442 Stream s = m.Build();
443 ASSERT_EQ(1U, s.size());
444 EXPECT_EQ(intpa.arch_opcode, s[0]->arch_opcode());
445 EXPECT_EQ(2U, s[0]->InputCount());
446 EXPECT_EQ(1U, s[0]->OutputCount());
450 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
451 InstructionSelectorIntArithOneTest,
452 ::testing::ValuesIn(kAddSubOneInstructions));
455 // ----------------------------------------------------------------------------
457 // ----------------------------------------------------------------------------
460 typedef InstructionSelectorTestWithParam<Conversion>
461 InstructionSelectorConversionTest;
464 TEST_P(InstructionSelectorConversionTest, Parameter) {
465 const Conversion conv = GetParam();
466 StreamBuilder m(this, conv.mi.machine_type, conv.src_machine_type);
467 m.Return((m.*conv.mi.constructor)(m.Parameter(0)));
468 Stream s = m.Build();
469 ASSERT_EQ(1U, s.size());
470 EXPECT_EQ(conv.mi.arch_opcode, s[0]->arch_opcode());
471 EXPECT_EQ(1U, s[0]->InputCount());
472 EXPECT_EQ(1U, s[0]->OutputCount());
476 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
477 InstructionSelectorConversionTest,
478 ::testing::ValuesIn(kConversionInstructions));
481 // ----------------------------------------------------------------------------
483 // ----------------------------------------------------------------------------
487 struct MemoryAccess {
489 ArchOpcode load_opcode;
490 ArchOpcode store_opcode;
494 static const MemoryAccess kMemoryAccesses[] = {
495 {kMachInt8, kMipsLb, kMipsSb},
496 {kMachUint8, kMipsLbu, kMipsSb},
497 {kMachInt16, kMipsLh, kMipsSh},
498 {kMachUint16, kMipsLhu, kMipsSh},
499 {kMachInt32, kMipsLw, kMipsSw},
500 {kRepFloat32, kMipsLwc1, kMipsSwc1},
501 {kRepFloat64, kMipsLdc1, kMipsSdc1}};
504 struct MemoryAccessImm {
506 ArchOpcode load_opcode;
507 ArchOpcode store_opcode;
508 bool (InstructionSelectorTest::Stream::*val_predicate)(
509 const InstructionOperand*) const;
510 const int32_t immediates[40];
514 std::ostream& operator<<(std::ostream& os, const MemoryAccessImm& acc) {
515 return os << acc.type;
519 struct MemoryAccessImm1 {
521 ArchOpcode load_opcode;
522 ArchOpcode store_opcode;
523 bool (InstructionSelectorTest::Stream::*val_predicate)(
524 const InstructionOperand*) const;
525 const int32_t immediates[5];
529 std::ostream& operator<<(std::ostream& os, const MemoryAccessImm1& acc) {
530 return os << acc.type;
534 // ----------------------------------------------------------------------------
535 // Loads and stores immediate values.
536 // ----------------------------------------------------------------------------
539 const MemoryAccessImm kMemoryAccessesImm[] = {
543 &InstructionSelectorTest::Stream::IsInteger,
544 {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89,
545 -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109,
546 115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}},
550 &InstructionSelectorTest::Stream::IsInteger,
551 {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89,
552 -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109,
553 115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}},
557 &InstructionSelectorTest::Stream::IsInteger,
558 {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89,
559 -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109,
560 115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}},
564 &InstructionSelectorTest::Stream::IsInteger,
565 {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89,
566 -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109,
567 115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}},
571 &InstructionSelectorTest::Stream::IsInteger,
572 {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89,
573 -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109,
574 115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}},
578 &InstructionSelectorTest::Stream::IsDouble,
579 {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89,
580 -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109,
581 115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}},
585 &InstructionSelectorTest::Stream::IsDouble,
586 {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89,
587 -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109,
588 115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}}};
591 const MemoryAccessImm1 kMemoryAccessImmMoreThan16bit[] = {
595 &InstructionSelectorTest::Stream::IsInteger,
596 {-65000, -55000, 32777, 55000, 65000}},
600 &InstructionSelectorTest::Stream::IsInteger,
601 {-65000, -55000, 32777, 55000, 65000}},
605 &InstructionSelectorTest::Stream::IsInteger,
606 {-65000, -55000, 32777, 55000, 65000}},
610 &InstructionSelectorTest::Stream::IsInteger,
611 {-65000, -55000, 32777, 55000, 65000}},
615 &InstructionSelectorTest::Stream::IsInteger,
616 {-65000, -55000, 32777, 55000, 65000}},
620 &InstructionSelectorTest::Stream::IsDouble,
621 {-65000, -55000, 32777, 55000, 65000}},
625 &InstructionSelectorTest::Stream::IsDouble,
626 {-65000, -55000, 32777, 55000, 65000}}};
631 typedef InstructionSelectorTestWithParam<MemoryAccess>
632 InstructionSelectorMemoryAccessTest;
635 TEST_P(InstructionSelectorMemoryAccessTest, LoadWithParameters) {
636 const MemoryAccess memacc = GetParam();
637 StreamBuilder m(this, memacc.type, kMachPtr, kMachInt32);
638 m.Return(m.Load(memacc.type, m.Parameter(0)));
639 Stream s = m.Build();
640 ASSERT_EQ(1U, s.size());
641 EXPECT_EQ(memacc.load_opcode, s[0]->arch_opcode());
642 EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
646 TEST_P(InstructionSelectorMemoryAccessTest, StoreWithParameters) {
647 const MemoryAccess memacc = GetParam();
648 StreamBuilder m(this, kMachInt32, kMachPtr, kMachInt32, memacc.type);
649 m.Store(memacc.type, m.Parameter(0), m.Parameter(1));
650 m.Return(m.Int32Constant(0));
651 Stream s = m.Build();
652 ASSERT_EQ(1U, s.size());
653 EXPECT_EQ(memacc.store_opcode, s[0]->arch_opcode());
654 EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
658 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
659 InstructionSelectorMemoryAccessTest,
660 ::testing::ValuesIn(kMemoryAccesses));
663 // ----------------------------------------------------------------------------
665 // ----------------------------------------------------------------------------
668 typedef InstructionSelectorTestWithParam<MemoryAccessImm>
669 InstructionSelectorMemoryAccessImmTest;
672 TEST_P(InstructionSelectorMemoryAccessImmTest, LoadWithImmediateIndex) {
673 const MemoryAccessImm memacc = GetParam();
674 TRACED_FOREACH(int32_t, index, memacc.immediates) {
675 StreamBuilder m(this, memacc.type, kMachPtr);
676 m.Return(m.Load(memacc.type, m.Parameter(0), m.Int32Constant(index)));
677 Stream s = m.Build();
678 ASSERT_EQ(1U, s.size());
679 EXPECT_EQ(memacc.load_opcode, s[0]->arch_opcode());
680 EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
681 ASSERT_EQ(2U, s[0]->InputCount());
682 ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
683 EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1)));
684 ASSERT_EQ(1U, s[0]->OutputCount());
685 EXPECT_TRUE((s.*memacc.val_predicate)(s[0]->Output()));
690 // ----------------------------------------------------------------------------
692 // ----------------------------------------------------------------------------
695 TEST_P(InstructionSelectorMemoryAccessImmTest, StoreWithImmediateIndex) {
696 const MemoryAccessImm memacc = GetParam();
697 TRACED_FOREACH(int32_t, index, memacc.immediates) {
698 StreamBuilder m(this, kMachInt32, kMachPtr, memacc.type);
699 m.Store(memacc.type, m.Parameter(0), m.Int32Constant(index),
701 m.Return(m.Int32Constant(0));
702 Stream s = m.Build();
703 ASSERT_EQ(1U, s.size());
704 EXPECT_EQ(memacc.store_opcode, s[0]->arch_opcode());
705 EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
706 ASSERT_EQ(3U, s[0]->InputCount());
707 ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
708 EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1)));
709 EXPECT_EQ(0U, s[0]->OutputCount());
714 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
715 InstructionSelectorMemoryAccessImmTest,
716 ::testing::ValuesIn(kMemoryAccessesImm));
719 // ----------------------------------------------------------------------------
720 // Load/store offsets more than 16 bits.
721 // ----------------------------------------------------------------------------
724 typedef InstructionSelectorTestWithParam<MemoryAccessImm1>
725 InstructionSelectorMemoryAccessImmMoreThan16bitTest;
728 TEST_P(InstructionSelectorMemoryAccessImmMoreThan16bitTest,
729 LoadWithImmediateIndex) {
730 const MemoryAccessImm1 memacc = GetParam();
731 TRACED_FOREACH(int32_t, index, memacc.immediates) {
732 StreamBuilder m(this, memacc.type, kMachPtr);
733 m.Return(m.Load(memacc.type, m.Parameter(0), m.Int32Constant(index)));
734 Stream s = m.Build();
735 ASSERT_EQ(2U, s.size());
736 // kMipsAdd is expected opcode.
737 // size more than 16 bits wide.
738 EXPECT_EQ(kMipsAdd, s[0]->arch_opcode());
739 EXPECT_EQ(kMode_None, s[0]->addressing_mode());
740 EXPECT_EQ(2U, s[0]->InputCount());
741 EXPECT_EQ(1U, s[0]->OutputCount());
746 TEST_P(InstructionSelectorMemoryAccessImmMoreThan16bitTest,
747 StoreWithImmediateIndex) {
748 const MemoryAccessImm1 memacc = GetParam();
749 TRACED_FOREACH(int32_t, index, memacc.immediates) {
750 StreamBuilder m(this, kMachInt32, kMachPtr, memacc.type);
751 m.Store(memacc.type, m.Parameter(0), m.Int32Constant(index),
753 m.Return(m.Int32Constant(0));
754 Stream s = m.Build();
755 ASSERT_EQ(2U, s.size());
756 // kMipsAdd is expected opcode
757 // size more than 16 bits wide
758 EXPECT_EQ(kMipsAdd, s[0]->arch_opcode());
759 EXPECT_EQ(kMode_None, s[0]->addressing_mode());
760 EXPECT_EQ(2U, s[0]->InputCount());
761 EXPECT_EQ(1U, s[0]->OutputCount());
766 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
767 InstructionSelectorMemoryAccessImmMoreThan16bitTest,
768 ::testing::ValuesIn(kMemoryAccessImmMoreThan16bit));
771 // ----------------------------------------------------------------------------
773 // ----------------------------------------------------------------------------
776 TEST_F(InstructionSelectorTest, Word32EqualWithZero) {
778 StreamBuilder m(this, kMachInt32, kMachInt32);
779 m.Return(m.Word32Equal(m.Parameter(0), m.Int32Constant(0)));
780 Stream s = m.Build();
781 ASSERT_EQ(1U, s.size());
782 EXPECT_EQ(kMipsCmp, s[0]->arch_opcode());
783 EXPECT_EQ(kMode_None, s[0]->addressing_mode());
784 ASSERT_EQ(2U, s[0]->InputCount());
785 EXPECT_EQ(1U, s[0]->OutputCount());
786 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
787 EXPECT_EQ(kEqual, s[0]->flags_condition());
790 StreamBuilder m(this, kMachInt32, kMachInt32);
791 m.Return(m.Word32Equal(m.Int32Constant(0), m.Parameter(0)));
792 Stream s = m.Build();
793 ASSERT_EQ(1U, s.size());
794 EXPECT_EQ(kMipsCmp, s[0]->arch_opcode());
795 EXPECT_EQ(kMode_None, s[0]->addressing_mode());
796 ASSERT_EQ(2U, s[0]->InputCount());
797 EXPECT_EQ(1U, s[0]->OutputCount());
798 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
799 EXPECT_EQ(kEqual, s[0]->flags_condition());
803 } // namespace compiler
804 } // namespace internal