blob: 122c398e2069be5cce19063a6d4a713a14c5f5f4 [file] [log] [blame]
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001// 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/instruction-selector-unittest.h"
6
7namespace v8 {
8namespace internal {
9namespace compiler {
10
11namespace {
12
13template <typename T>
14struct MachInst {
15 T constructor;
16 const char* constructor_name;
17 ArchOpcode arch_opcode;
18 MachineType machine_type;
19};
20
21template <typename T>
22std::ostream& operator<<(std::ostream& os, const MachInst<T>& mi) {
23 return os << mi.constructor_name;
24}
25
26typedef MachInst<Node* (RawMachineAssembler::*)(Node*)> MachInst1;
27typedef MachInst<Node* (RawMachineAssembler::*)(Node*, Node*)> MachInst2;
28
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.
32struct IntCmp {
33 MachInst2 mi;
34 uint32_t expected_size;
35};
36
37struct FPCmp {
38 MachInst2 mi;
39 FlagsCondition cond;
40};
41
42const FPCmp kFPCmpInstructions[] = {
43 {{&RawMachineAssembler::Float64Equal, "Float64Equal", kMipsCmpD,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000044 MachineType::Float64()},
45 kEqual},
Emily Bernierd0a1eb72015-03-24 16:35:39 -040046 {{&RawMachineAssembler::Float64LessThan, "Float64LessThan", kMipsCmpD,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000047 MachineType::Float64()},
48 kUnsignedLessThan},
Emily Bernierd0a1eb72015-03-24 16:35:39 -040049 {{&RawMachineAssembler::Float64LessThanOrEqual, "Float64LessThanOrEqual",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000050 kMipsCmpD, MachineType::Float64()},
51 kUnsignedLessThanOrEqual},
Emily Bernierd0a1eb72015-03-24 16:35:39 -040052 {{&RawMachineAssembler::Float64GreaterThan, "Float64GreaterThan", kMipsCmpD,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000053 MachineType::Float64()},
54 kUnsignedLessThan},
Emily Bernierd0a1eb72015-03-24 16:35:39 -040055 {{&RawMachineAssembler::Float64GreaterThanOrEqual,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000056 "Float64GreaterThanOrEqual", kMipsCmpD, MachineType::Float64()},
57 kUnsignedLessThanOrEqual}};
Emily Bernierd0a1eb72015-03-24 16:35:39 -040058
59struct Conversion {
60 // The machine_type field in MachInst1 represents the destination type.
61 MachInst1 mi;
62 MachineType src_machine_type;
63};
64
65
66// ----------------------------------------------------------------------------
67// Logical instructions.
68// ----------------------------------------------------------------------------
69
70
71const MachInst2 kLogicalInstructions[] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000072 {&RawMachineAssembler::WordAnd, "WordAnd", kMipsAnd, MachineType::Int16()},
73 {&RawMachineAssembler::WordOr, "WordOr", kMipsOr, MachineType::Int16()},
74 {&RawMachineAssembler::WordXor, "WordXor", kMipsXor, MachineType::Int16()},
75 {&RawMachineAssembler::Word32And, "Word32And", kMipsAnd,
76 MachineType::Int32()},
77 {&RawMachineAssembler::Word32Or, "Word32Or", kMipsOr, MachineType::Int32()},
78 {&RawMachineAssembler::Word32Xor, "Word32Xor", kMipsXor,
79 MachineType::Int32()}};
Emily Bernierd0a1eb72015-03-24 16:35:39 -040080
81
82// ----------------------------------------------------------------------------
83// Shift instructions.
84// ----------------------------------------------------------------------------
85
86
87const MachInst2 kShiftInstructions[] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000088 {&RawMachineAssembler::WordShl, "WordShl", kMipsShl, MachineType::Int16()},
89 {&RawMachineAssembler::WordShr, "WordShr", kMipsShr, MachineType::Int16()},
90 {&RawMachineAssembler::WordSar, "WordSar", kMipsSar, MachineType::Int16()},
91 {&RawMachineAssembler::WordRor, "WordRor", kMipsRor, MachineType::Int16()},
92 {&RawMachineAssembler::Word32Shl, "Word32Shl", kMipsShl,
93 MachineType::Int32()},
94 {&RawMachineAssembler::Word32Shr, "Word32Shr", kMipsShr,
95 MachineType::Int32()},
96 {&RawMachineAssembler::Word32Sar, "Word32Sar", kMipsSar,
97 MachineType::Int32()},
98 {&RawMachineAssembler::Word32Ror, "Word32Ror", kMipsRor,
99 MachineType::Int32()}};
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400100
101
102// ----------------------------------------------------------------------------
103// MUL/DIV instructions.
104// ----------------------------------------------------------------------------
105
106
107const MachInst2 kMulDivInstructions[] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000108 {&RawMachineAssembler::Int32Mul, "Int32Mul", kMipsMul,
109 MachineType::Int32()},
110 {&RawMachineAssembler::Int32Div, "Int32Div", kMipsDiv,
111 MachineType::Int32()},
112 {&RawMachineAssembler::Uint32Div, "Uint32Div", kMipsDivU,
113 MachineType::Uint32()},
114 {&RawMachineAssembler::Float64Mul, "Float64Mul", kMipsMulD,
115 MachineType::Float64()},
116 {&RawMachineAssembler::Float64Div, "Float64Div", kMipsDivD,
117 MachineType::Float64()}};
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400118
119
120// ----------------------------------------------------------------------------
121// MOD instructions.
122// ----------------------------------------------------------------------------
123
124
125const MachInst2 kModInstructions[] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000126 {&RawMachineAssembler::Int32Mod, "Int32Mod", kMipsMod,
127 MachineType::Int32()},
128 {&RawMachineAssembler::Uint32Mod, "Int32UMod", kMipsModU,
129 MachineType::Int32()},
130 {&RawMachineAssembler::Float64Mod, "Float64Mod", kMipsModD,
131 MachineType::Float64()}};
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400132
133
134// ----------------------------------------------------------------------------
135// Arithmetic FPU instructions.
136// ----------------------------------------------------------------------------
137
138
139const MachInst2 kFPArithInstructions[] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000140 {&RawMachineAssembler::Float64Add, "Float64Add", kMipsAddD,
141 MachineType::Float64()},
142 {&RawMachineAssembler::Float64Sub, "Float64Sub", kMipsSubD,
143 MachineType::Float64()}};
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400144
145
146// ----------------------------------------------------------------------------
147// IntArithTest instructions, two nodes.
148// ----------------------------------------------------------------------------
149
150
151const MachInst2 kAddSubInstructions[] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000152 {&RawMachineAssembler::Int32Add, "Int32Add", kMipsAdd,
153 MachineType::Int32()},
154 {&RawMachineAssembler::Int32Sub, "Int32Sub", kMipsSub,
155 MachineType::Int32()},
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400156 {&RawMachineAssembler::Int32AddWithOverflow, "Int32AddWithOverflow",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000157 kMipsAddOvf, MachineType::Int32()},
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400158 {&RawMachineAssembler::Int32SubWithOverflow, "Int32SubWithOverflow",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000159 kMipsSubOvf, MachineType::Int32()}};
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400160
161
162// ----------------------------------------------------------------------------
163// IntArithTest instructions, one node.
164// ----------------------------------------------------------------------------
165
166
167const MachInst1 kAddSubOneInstructions[] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000168 {&RawMachineAssembler::Int32Neg, "Int32Neg", kMipsSub,
169 MachineType::Int32()},
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400170 // TODO(dusmil): check this ...
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000171 // {&RawMachineAssembler::WordEqual , "WordEqual" , kMipsTst,
172 // MachineType::Int32()}
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400173};
174
175
176// ----------------------------------------------------------------------------
177// Arithmetic compare instructions.
178// ----------------------------------------------------------------------------
179
180
181const IntCmp kCmpInstructions[] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000182 {{&RawMachineAssembler::WordEqual, "WordEqual", kMipsCmp,
183 MachineType::Int16()},
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400184 1U},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000185 {{&RawMachineAssembler::WordNotEqual, "WordNotEqual", kMipsCmp,
186 MachineType::Int16()},
187 1U},
188 {{&RawMachineAssembler::Word32Equal, "Word32Equal", kMipsCmp,
189 MachineType::Int32()},
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400190 1U},
191 {{&RawMachineAssembler::Word32NotEqual, "Word32NotEqual", kMipsCmp,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000192 MachineType::Int32()},
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400193 1U},
194 {{&RawMachineAssembler::Int32LessThan, "Int32LessThan", kMipsCmp,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000195 MachineType::Int32()},
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400196 1U},
197 {{&RawMachineAssembler::Int32LessThanOrEqual, "Int32LessThanOrEqual",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000198 kMipsCmp, MachineType::Int32()},
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400199 1U},
200 {{&RawMachineAssembler::Int32GreaterThan, "Int32GreaterThan", kMipsCmp,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000201 MachineType::Int32()},
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400202 1U},
203 {{&RawMachineAssembler::Int32GreaterThanOrEqual, "Int32GreaterThanOrEqual",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000204 kMipsCmp, MachineType::Int32()},
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400205 1U},
206 {{&RawMachineAssembler::Uint32LessThan, "Uint32LessThan", kMipsCmp,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000207 MachineType::Uint32()},
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400208 1U},
209 {{&RawMachineAssembler::Uint32LessThanOrEqual, "Uint32LessThanOrEqual",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000210 kMipsCmp, MachineType::Uint32()},
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400211 1U}};
212
213
214// ----------------------------------------------------------------------------
215// Conversion instructions.
216// ----------------------------------------------------------------------------
217
218const Conversion kConversionInstructions[] = {
219 // Conversion instructions are related to machine_operator.h:
220 // FPU conversions:
221 // Convert representation of integers between float64 and int32/uint32.
222 // The precise rounding mode and handling of out of range inputs are *not*
223 // defined for these operators, since they are intended only for use with
224 // integers.
225 // mips instruction: cvt_d_w
226 {{&RawMachineAssembler::ChangeInt32ToFloat64, "ChangeInt32ToFloat64",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000227 kMipsCvtDW, MachineType::Float64()},
228 MachineType::Int32()},
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400229
230 // mips instruction: cvt_d_uw
231 {{&RawMachineAssembler::ChangeUint32ToFloat64, "ChangeUint32ToFloat64",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000232 kMipsCvtDUw, MachineType::Float64()},
233 MachineType::Int32()},
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400234
235 // mips instruction: trunc_w_d
236 {{&RawMachineAssembler::ChangeFloat64ToInt32, "ChangeFloat64ToInt32",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000237 kMipsTruncWD, MachineType::Float64()},
238 MachineType::Int32()},
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400239
240 // mips instruction: trunc_uw_d
241 {{&RawMachineAssembler::ChangeFloat64ToUint32, "ChangeFloat64ToUint32",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000242 kMipsTruncUwD, MachineType::Float64()},
243 MachineType::Int32()}};
244
245const Conversion kFloat64RoundInstructions[] = {
246 {{&RawMachineAssembler::Float64RoundUp, "Float64RoundUp", kMipsCeilWD,
247 MachineType::Int32()},
248 MachineType::Float64()},
249 {{&RawMachineAssembler::Float64RoundDown, "Float64RoundDown", kMipsFloorWD,
250 MachineType::Int32()},
251 MachineType::Float64()},
252 {{&RawMachineAssembler::Float64RoundTiesEven, "Float64RoundTiesEven",
253 kMipsRoundWD, MachineType::Int32()},
254 MachineType::Float64()},
255 {{&RawMachineAssembler::Float64RoundTruncate, "Float64RoundTruncate",
256 kMipsTruncWD, MachineType::Int32()},
257 MachineType::Float64()}};
258
259const Conversion kFloat32RoundInstructions[] = {
260 {{&RawMachineAssembler::Float32RoundUp, "Float32RoundUp", kMipsCeilWS,
261 MachineType::Int32()},
262 MachineType::Float32()},
263 {{&RawMachineAssembler::Float32RoundDown, "Float32RoundDown", kMipsFloorWS,
264 MachineType::Int32()},
265 MachineType::Float32()},
266 {{&RawMachineAssembler::Float32RoundTiesEven, "Float32RoundTiesEven",
267 kMipsRoundWS, MachineType::Int32()},
268 MachineType::Float32()},
269 {{&RawMachineAssembler::Float32RoundTruncate, "Float32RoundTruncate",
270 kMipsTruncWS, MachineType::Int32()},
271 MachineType::Float32()}};
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400272
273} // namespace
274
275
276typedef InstructionSelectorTestWithParam<FPCmp> InstructionSelectorFPCmpTest;
277
278
279TEST_P(InstructionSelectorFPCmpTest, Parameter) {
280 const FPCmp cmp = GetParam();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000281 StreamBuilder m(this, MachineType::Int32(), cmp.mi.machine_type,
282 cmp.mi.machine_type);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400283 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
293INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorFPCmpTest,
294 ::testing::ValuesIn(kFPCmpInstructions));
295
296
297// ----------------------------------------------------------------------------
298// Arithmetic compare instructions integers.
299// ----------------------------------------------------------------------------
300
301
302typedef InstructionSelectorTestWithParam<IntCmp> InstructionSelectorCmpTest;
303
304
305TEST_P(InstructionSelectorCmpTest, Parameter) {
306 const IntCmp cmp = GetParam();
307 const MachineType type = cmp.mi.machine_type;
308 StreamBuilder m(this, type, type, type);
309 m.Return((m.*cmp.mi.constructor)(m.Parameter(0), m.Parameter(1)));
310 Stream s = m.Build();
311 ASSERT_EQ(cmp.expected_size, s.size());
312 EXPECT_EQ(cmp.mi.arch_opcode, s[0]->arch_opcode());
313 EXPECT_EQ(2U, s[0]->InputCount());
314 EXPECT_EQ(1U, s[0]->OutputCount());
315}
316
317
318INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorCmpTest,
319 ::testing::ValuesIn(kCmpInstructions));
320
321
322// ----------------------------------------------------------------------------
323// Shift instructions.
324// ----------------------------------------------------------------------------
325
326
327typedef InstructionSelectorTestWithParam<MachInst2>
328 InstructionSelectorShiftTest;
329
330
331TEST_P(InstructionSelectorShiftTest, Immediate) {
332 const MachInst2 dpi = GetParam();
333 const MachineType type = dpi.machine_type;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000334 TRACED_FORRANGE(int32_t, imm, 0,
335 ((1 << ElementSizeLog2Of(type.representation())) * 8) - 1) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400336 StreamBuilder m(this, type, type);
337 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm)));
338 Stream s = m.Build();
339 ASSERT_EQ(1U, s.size());
340 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
341 EXPECT_EQ(2U, s[0]->InputCount());
342 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
343 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
344 EXPECT_EQ(1U, s[0]->OutputCount());
345 }
346}
347
348
349INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorShiftTest,
350 ::testing::ValuesIn(kShiftInstructions));
351
352
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000353TEST_F(InstructionSelectorTest, Word32ShrWithWord32AndWithImmediate) {
354 // The available shift operand range is `0 <= imm < 32`, but we also test
355 // that immediates outside this range are handled properly (modulo-32).
356 TRACED_FORRANGE(int32_t, shift, -32, 63) {
357 int32_t lsb = shift & 0x1f;
358 TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) {
359 uint32_t jnk = rng()->NextInt();
360 jnk = (lsb > 0) ? (jnk >> (32 - lsb)) : 0;
361 uint32_t msk = ((0xffffffffu >> (32 - width)) << lsb) | jnk;
362 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
363 m.Return(m.Word32Shr(m.Word32And(m.Parameter(0), m.Int32Constant(msk)),
364 m.Int32Constant(shift)));
365 Stream s = m.Build();
366 ASSERT_EQ(1U, s.size());
367 EXPECT_EQ(kMipsExt, s[0]->arch_opcode());
368 ASSERT_EQ(3U, s[0]->InputCount());
369 EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
370 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
371 }
372 }
373 TRACED_FORRANGE(int32_t, shift, -32, 63) {
374 int32_t lsb = shift & 0x1f;
375 TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) {
376 uint32_t jnk = rng()->NextInt();
377 jnk = (lsb > 0) ? (jnk >> (32 - lsb)) : 0;
378 uint32_t msk = ((0xffffffffu >> (32 - width)) << lsb) | jnk;
379 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
380 m.Return(m.Word32Shr(m.Word32And(m.Int32Constant(msk), m.Parameter(0)),
381 m.Int32Constant(shift)));
382 Stream s = m.Build();
383 ASSERT_EQ(1U, s.size());
384 EXPECT_EQ(kMipsExt, s[0]->arch_opcode());
385 ASSERT_EQ(3U, s[0]->InputCount());
386 EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
387 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
388 }
389 }
390}
391
392
393TEST_F(InstructionSelectorTest, Word32ShlWithWord32And) {
394 TRACED_FORRANGE(int32_t, shift, 0, 30) {
395 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
396 Node* const p0 = m.Parameter(0);
397 Node* const r =
398 m.Word32Shl(m.Word32And(p0, m.Int32Constant((1 << (31 - shift)) - 1)),
399 m.Int32Constant(shift + 1));
400 m.Return(r);
401 Stream s = m.Build();
402 ASSERT_EQ(1U, s.size());
403 EXPECT_EQ(kMipsShl, s[0]->arch_opcode());
404 ASSERT_EQ(2U, s[0]->InputCount());
405 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
406 ASSERT_EQ(1U, s[0]->OutputCount());
407 EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
408 }
409}
410
411
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400412// ----------------------------------------------------------------------------
413// Logical instructions.
414// ----------------------------------------------------------------------------
415
416
417typedef InstructionSelectorTestWithParam<MachInst2>
418 InstructionSelectorLogicalTest;
419
420
421TEST_P(InstructionSelectorLogicalTest, Parameter) {
422 const MachInst2 dpi = GetParam();
423 const MachineType type = dpi.machine_type;
424 StreamBuilder m(this, type, type, type);
425 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)));
426 Stream s = m.Build();
427 ASSERT_EQ(1U, s.size());
428 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
429 EXPECT_EQ(2U, s[0]->InputCount());
430 EXPECT_EQ(1U, s[0]->OutputCount());
431}
432
433
434INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorLogicalTest,
435 ::testing::ValuesIn(kLogicalInstructions));
436
437
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000438TEST_F(InstructionSelectorTest, Word32XorMinusOneWithParameter) {
439 {
440 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
441 m.Return(m.Word32Xor(m.Parameter(0), m.Int32Constant(-1)));
442 Stream s = m.Build();
443 ASSERT_EQ(1U, s.size());
444 EXPECT_EQ(kMipsNor, s[0]->arch_opcode());
445 EXPECT_EQ(2U, s[0]->InputCount());
446 EXPECT_EQ(1U, s[0]->OutputCount());
447 }
448 {
449 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
450 m.Return(m.Word32Xor(m.Int32Constant(-1), m.Parameter(0)));
451 Stream s = m.Build();
452 ASSERT_EQ(1U, s.size());
453 EXPECT_EQ(kMipsNor, s[0]->arch_opcode());
454 EXPECT_EQ(2U, s[0]->InputCount());
455 EXPECT_EQ(1U, s[0]->OutputCount());
456 }
457}
458
459
460TEST_F(InstructionSelectorTest, Word32XorMinusOneWithWord32Or) {
461 {
462 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
463 m.Return(m.Word32Xor(m.Word32Or(m.Parameter(0), m.Parameter(0)),
464 m.Int32Constant(-1)));
465 Stream s = m.Build();
466 ASSERT_EQ(1U, s.size());
467 EXPECT_EQ(kMipsNor, s[0]->arch_opcode());
468 EXPECT_EQ(2U, s[0]->InputCount());
469 EXPECT_EQ(1U, s[0]->OutputCount());
470 }
471 {
472 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
473 m.Return(m.Word32Xor(m.Int32Constant(-1),
474 m.Word32Or(m.Parameter(0), m.Parameter(0))));
475 Stream s = m.Build();
476 ASSERT_EQ(1U, s.size());
477 EXPECT_EQ(kMipsNor, s[0]->arch_opcode());
478 EXPECT_EQ(2U, s[0]->InputCount());
479 EXPECT_EQ(1U, s[0]->OutputCount());
480 }
481}
482
483
484TEST_F(InstructionSelectorTest, Word32AndWithImmediateWithWord32Shr) {
485 // The available shift operand range is `0 <= imm < 32`, but we also test
486 // that immediates outside this range are handled properly (modulo-32).
487 TRACED_FORRANGE(int32_t, shift, -32, 63) {
488 int32_t lsb = shift & 0x1f;
489 TRACED_FORRANGE(int32_t, width, 1, 31) {
490 uint32_t msk = (1 << width) - 1;
491 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
492 m.Return(m.Word32And(m.Word32Shr(m.Parameter(0), m.Int32Constant(shift)),
493 m.Int32Constant(msk)));
494 Stream s = m.Build();
495 ASSERT_EQ(1U, s.size());
496 EXPECT_EQ(kMipsExt, s[0]->arch_opcode());
497 ASSERT_EQ(3U, s[0]->InputCount());
498 EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
499 int32_t actual_width = (lsb + width > 32) ? (32 - lsb) : width;
500 EXPECT_EQ(actual_width, s.ToInt32(s[0]->InputAt(2)));
501 }
502 }
503 TRACED_FORRANGE(int32_t, shift, -32, 63) {
504 int32_t lsb = shift & 0x1f;
505 TRACED_FORRANGE(int32_t, width, 1, 31) {
506 uint32_t msk = (1 << width) - 1;
507 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
508 m.Return(
509 m.Word32And(m.Int32Constant(msk),
510 m.Word32Shr(m.Parameter(0), m.Int32Constant(shift))));
511 Stream s = m.Build();
512 ASSERT_EQ(1U, s.size());
513 EXPECT_EQ(kMipsExt, s[0]->arch_opcode());
514 ASSERT_EQ(3U, s[0]->InputCount());
515 EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
516 int32_t actual_width = (lsb + width > 32) ? (32 - lsb) : width;
517 EXPECT_EQ(actual_width, s.ToInt32(s[0]->InputAt(2)));
518 }
519 }
520}
521
522
523TEST_F(InstructionSelectorTest, Word32AndToClearBits) {
524 TRACED_FORRANGE(int32_t, shift, 1, 31) {
525 int32_t mask = ~((1 << shift) - 1);
526 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
527 m.Return(m.Word32And(m.Parameter(0), m.Int32Constant(mask)));
528 Stream s = m.Build();
529 ASSERT_EQ(1U, s.size());
530 EXPECT_EQ(kMipsIns, s[0]->arch_opcode());
531 ASSERT_EQ(3U, s[0]->InputCount());
532 EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1)));
533 EXPECT_EQ(shift, s.ToInt32(s[0]->InputAt(2)));
534 }
535 TRACED_FORRANGE(int32_t, shift, 1, 31) {
536 int32_t mask = ~((1 << shift) - 1);
537 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
538 m.Return(m.Word32And(m.Int32Constant(mask), m.Parameter(0)));
539 Stream s = m.Build();
540 ASSERT_EQ(1U, s.size());
541 EXPECT_EQ(kMipsIns, s[0]->arch_opcode());
542 ASSERT_EQ(3U, s[0]->InputCount());
543 EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1)));
544 EXPECT_EQ(shift, s.ToInt32(s[0]->InputAt(2)));
545 }
546}
547
548
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400549// ----------------------------------------------------------------------------
550// MUL/DIV instructions.
551// ----------------------------------------------------------------------------
552
553
554typedef InstructionSelectorTestWithParam<MachInst2>
555 InstructionSelectorMulDivTest;
556
557
558TEST_P(InstructionSelectorMulDivTest, Parameter) {
559 const MachInst2 dpi = GetParam();
560 const MachineType type = dpi.machine_type;
561 StreamBuilder m(this, type, type, type);
562 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)));
563 Stream s = m.Build();
564 ASSERT_EQ(1U, s.size());
565 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
566 EXPECT_EQ(2U, s[0]->InputCount());
567 EXPECT_EQ(1U, s[0]->OutputCount());
568}
569
570
571INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorMulDivTest,
572 ::testing::ValuesIn(kMulDivInstructions));
573
574
575// ----------------------------------------------------------------------------
576// MOD instructions.
577// ----------------------------------------------------------------------------
578
579
580typedef InstructionSelectorTestWithParam<MachInst2> InstructionSelectorModTest;
581
582
583TEST_P(InstructionSelectorModTest, Parameter) {
584 const MachInst2 dpi = GetParam();
585 const MachineType type = dpi.machine_type;
586 StreamBuilder m(this, type, type, type);
587 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)));
588 Stream s = m.Build();
589 ASSERT_EQ(1U, s.size());
590 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
591 EXPECT_EQ(2U, s[0]->InputCount());
592 EXPECT_EQ(1U, s[0]->OutputCount());
593}
594
595
596INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorModTest,
597 ::testing::ValuesIn(kModInstructions));
598
599
600// ----------------------------------------------------------------------------
601// Floating point instructions.
602// ----------------------------------------------------------------------------
603
604
605typedef InstructionSelectorTestWithParam<MachInst2>
606 InstructionSelectorFPArithTest;
607
608
609TEST_P(InstructionSelectorFPArithTest, Parameter) {
610 const MachInst2 fpa = GetParam();
611 StreamBuilder m(this, fpa.machine_type, fpa.machine_type, fpa.machine_type);
612 m.Return((m.*fpa.constructor)(m.Parameter(0), m.Parameter(1)));
613 Stream s = m.Build();
614 ASSERT_EQ(1U, s.size());
615 EXPECT_EQ(fpa.arch_opcode, s[0]->arch_opcode());
616 EXPECT_EQ(2U, s[0]->InputCount());
617 EXPECT_EQ(1U, s[0]->OutputCount());
618}
619
620
621INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorFPArithTest,
622 ::testing::ValuesIn(kFPArithInstructions));
623
624
625// ----------------------------------------------------------------------------
626// Integer arithmetic.
627// ----------------------------------------------------------------------------
628
629
630typedef InstructionSelectorTestWithParam<MachInst2>
631 InstructionSelectorIntArithTwoTest;
632
633
634TEST_P(InstructionSelectorIntArithTwoTest, Parameter) {
635 const MachInst2 intpa = GetParam();
636 StreamBuilder m(this, intpa.machine_type, intpa.machine_type,
637 intpa.machine_type);
638 m.Return((m.*intpa.constructor)(m.Parameter(0), m.Parameter(1)));
639 Stream s = m.Build();
640 ASSERT_EQ(1U, s.size());
641 EXPECT_EQ(intpa.arch_opcode, s[0]->arch_opcode());
642 EXPECT_EQ(2U, s[0]->InputCount());
643 EXPECT_EQ(1U, s[0]->OutputCount());
644}
645
646
647INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
648 InstructionSelectorIntArithTwoTest,
649 ::testing::ValuesIn(kAddSubInstructions));
650
651
652// ----------------------------------------------------------------------------
653// One node.
654// ----------------------------------------------------------------------------
655
656
657typedef InstructionSelectorTestWithParam<MachInst1>
658 InstructionSelectorIntArithOneTest;
659
660
661TEST_P(InstructionSelectorIntArithOneTest, Parameter) {
662 const MachInst1 intpa = GetParam();
663 StreamBuilder m(this, intpa.machine_type, intpa.machine_type,
664 intpa.machine_type);
665 m.Return((m.*intpa.constructor)(m.Parameter(0)));
666 Stream s = m.Build();
667 ASSERT_EQ(1U, s.size());
668 EXPECT_EQ(intpa.arch_opcode, s[0]->arch_opcode());
669 EXPECT_EQ(2U, s[0]->InputCount());
670 EXPECT_EQ(1U, s[0]->OutputCount());
671}
672
673
674INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
675 InstructionSelectorIntArithOneTest,
676 ::testing::ValuesIn(kAddSubOneInstructions));
677
678
679// ----------------------------------------------------------------------------
680// Conversions.
681// ----------------------------------------------------------------------------
682
683
684typedef InstructionSelectorTestWithParam<Conversion>
685 InstructionSelectorConversionTest;
686
687
688TEST_P(InstructionSelectorConversionTest, Parameter) {
689 const Conversion conv = GetParam();
690 StreamBuilder m(this, conv.mi.machine_type, conv.src_machine_type);
691 m.Return((m.*conv.mi.constructor)(m.Parameter(0)));
692 Stream s = m.Build();
693 ASSERT_EQ(1U, s.size());
694 EXPECT_EQ(conv.mi.arch_opcode, s[0]->arch_opcode());
695 EXPECT_EQ(1U, s[0]->InputCount());
696 EXPECT_EQ(1U, s[0]->OutputCount());
697}
698
699
700INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
701 InstructionSelectorConversionTest,
702 ::testing::ValuesIn(kConversionInstructions));
703
704
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000705typedef InstructionSelectorTestWithParam<Conversion>
706 CombineChangeFloat64ToInt32WithRoundFloat64;
707
708TEST_P(CombineChangeFloat64ToInt32WithRoundFloat64, Parameter) {
709 {
710 const Conversion conv = GetParam();
711 StreamBuilder m(this, conv.mi.machine_type, conv.src_machine_type);
712 m.Return(m.ChangeFloat64ToInt32((m.*conv.mi.constructor)(m.Parameter(0))));
713 Stream s = m.Build();
714 ASSERT_EQ(1U, s.size());
715 EXPECT_EQ(conv.mi.arch_opcode, s[0]->arch_opcode());
716 EXPECT_EQ(kMode_None, s[0]->addressing_mode());
717 ASSERT_EQ(1U, s[0]->InputCount());
718 EXPECT_EQ(1U, s[0]->OutputCount());
719 }
720}
721
722INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
723 CombineChangeFloat64ToInt32WithRoundFloat64,
724 ::testing::ValuesIn(kFloat64RoundInstructions));
725
726
727typedef InstructionSelectorTestWithParam<Conversion>
728 CombineChangeFloat32ToInt32WithRoundFloat32;
729
730TEST_P(CombineChangeFloat32ToInt32WithRoundFloat32, Parameter) {
731 {
732 const Conversion conv = GetParam();
733 StreamBuilder m(this, conv.mi.machine_type, conv.src_machine_type);
734 m.Return(m.ChangeFloat64ToInt32(
735 m.ChangeFloat32ToFloat64((m.*conv.mi.constructor)(m.Parameter(0)))));
736 Stream s = m.Build();
737 ASSERT_EQ(1U, s.size());
738 EXPECT_EQ(conv.mi.arch_opcode, s[0]->arch_opcode());
739 EXPECT_EQ(kMode_None, s[0]->addressing_mode());
740 ASSERT_EQ(1U, s[0]->InputCount());
741 EXPECT_EQ(1U, s[0]->OutputCount());
742 }
743}
744
745INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
746 CombineChangeFloat32ToInt32WithRoundFloat32,
747 ::testing::ValuesIn(kFloat32RoundInstructions));
748
749
750TEST_F(InstructionSelectorTest, ChangeFloat64ToInt32OfChangeFloat32ToFloat64) {
751 {
752 StreamBuilder m(this, MachineType::Int32(), MachineType::Float32());
753 m.Return(m.ChangeFloat64ToInt32(m.ChangeFloat32ToFloat64(m.Parameter(0))));
754 Stream s = m.Build();
755 ASSERT_EQ(1U, s.size());
756 EXPECT_EQ(kMipsTruncWS, s[0]->arch_opcode());
757 EXPECT_EQ(kMode_None, s[0]->addressing_mode());
758 ASSERT_EQ(1U, s[0]->InputCount());
759 EXPECT_EQ(1U, s[0]->OutputCount());
760 }
761}
762
763
764TEST_F(InstructionSelectorTest,
765 TruncateFloat64ToFloat32OfChangeInt32ToFloat64) {
766 {
767 StreamBuilder m(this, MachineType::Float32(), MachineType::Int32());
768 m.Return(
769 m.TruncateFloat64ToFloat32(m.ChangeInt32ToFloat64(m.Parameter(0))));
770 Stream s = m.Build();
771 ASSERT_EQ(1U, s.size());
772 EXPECT_EQ(kMipsCvtSW, s[0]->arch_opcode());
773 EXPECT_EQ(kMode_None, s[0]->addressing_mode());
774 ASSERT_EQ(1U, s[0]->InputCount());
775 EXPECT_EQ(1U, s[0]->OutputCount());
776 }
777}
778
779
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400780// ----------------------------------------------------------------------------
781// Loads and stores.
782// ----------------------------------------------------------------------------
783
784namespace {
785
786struct MemoryAccess {
787 MachineType type;
788 ArchOpcode load_opcode;
789 ArchOpcode store_opcode;
790};
791
792
793static const MemoryAccess kMemoryAccesses[] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000794 {MachineType::Int8(), kMipsLb, kMipsSb},
795 {MachineType::Uint8(), kMipsLbu, kMipsSb},
796 {MachineType::Int16(), kMipsLh, kMipsSh},
797 {MachineType::Uint16(), kMipsLhu, kMipsSh},
798 {MachineType::Int32(), kMipsLw, kMipsSw},
799 {MachineType::Float32(), kMipsLwc1, kMipsSwc1},
800 {MachineType::Float64(), kMipsLdc1, kMipsSdc1}};
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400801
802
803struct MemoryAccessImm {
804 MachineType type;
805 ArchOpcode load_opcode;
806 ArchOpcode store_opcode;
807 bool (InstructionSelectorTest::Stream::*val_predicate)(
808 const InstructionOperand*) const;
809 const int32_t immediates[40];
810};
811
812
813std::ostream& operator<<(std::ostream& os, const MemoryAccessImm& acc) {
814 return os << acc.type;
815}
816
817
818struct MemoryAccessImm1 {
819 MachineType type;
820 ArchOpcode load_opcode;
821 ArchOpcode store_opcode;
822 bool (InstructionSelectorTest::Stream::*val_predicate)(
823 const InstructionOperand*) const;
824 const int32_t immediates[5];
825};
826
827
828std::ostream& operator<<(std::ostream& os, const MemoryAccessImm1& acc) {
829 return os << acc.type;
830}
831
832
833// ----------------------------------------------------------------------------
834// Loads and stores immediate values.
835// ----------------------------------------------------------------------------
836
837
838const MemoryAccessImm kMemoryAccessesImm[] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000839 {MachineType::Int8(),
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400840 kMipsLb,
841 kMipsSb,
842 &InstructionSelectorTest::Stream::IsInteger,
843 {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89,
844 -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109,
845 115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000846 {MachineType::Uint8(),
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400847 kMipsLbu,
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}},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000853 {MachineType::Int16(),
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400854 kMipsLh,
855 kMipsSh,
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}},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000860 {MachineType::Uint16(),
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400861 kMipsLhu,
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}},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000867 {MachineType::Int32(),
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400868 kMipsLw,
869 kMipsSw,
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}},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000874 {MachineType::Float32(),
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400875 kMipsLwc1,
876 kMipsSwc1,
877 &InstructionSelectorTest::Stream::IsDouble,
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}},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000881 {MachineType::Float64(),
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400882 kMipsLdc1,
883 kMipsSdc1,
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
889
890const MemoryAccessImm1 kMemoryAccessImmMoreThan16bit[] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000891 {MachineType::Int8(),
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400892 kMipsLb,
893 kMipsSb,
894 &InstructionSelectorTest::Stream::IsInteger,
895 {-65000, -55000, 32777, 55000, 65000}},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000896 {MachineType::Int8(),
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400897 kMipsLbu,
898 kMipsSb,
899 &InstructionSelectorTest::Stream::IsInteger,
900 {-65000, -55000, 32777, 55000, 65000}},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000901 {MachineType::Int16(),
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400902 kMipsLh,
903 kMipsSh,
904 &InstructionSelectorTest::Stream::IsInteger,
905 {-65000, -55000, 32777, 55000, 65000}},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000906 {MachineType::Int16(),
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400907 kMipsLhu,
908 kMipsSh,
909 &InstructionSelectorTest::Stream::IsInteger,
910 {-65000, -55000, 32777, 55000, 65000}},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000911 {MachineType::Int32(),
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400912 kMipsLw,
913 kMipsSw,
914 &InstructionSelectorTest::Stream::IsInteger,
915 {-65000, -55000, 32777, 55000, 65000}},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000916 {MachineType::Float32(),
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400917 kMipsLwc1,
918 kMipsSwc1,
919 &InstructionSelectorTest::Stream::IsDouble,
920 {-65000, -55000, 32777, 55000, 65000}},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000921 {MachineType::Float64(),
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400922 kMipsLdc1,
923 kMipsSdc1,
924 &InstructionSelectorTest::Stream::IsDouble,
925 {-65000, -55000, 32777, 55000, 65000}}};
926
927} // namespace
928
929
930typedef InstructionSelectorTestWithParam<MemoryAccess>
931 InstructionSelectorMemoryAccessTest;
932
933
934TEST_P(InstructionSelectorMemoryAccessTest, LoadWithParameters) {
935 const MemoryAccess memacc = GetParam();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000936 StreamBuilder m(this, memacc.type, MachineType::Pointer(),
937 MachineType::Int32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400938 m.Return(m.Load(memacc.type, m.Parameter(0)));
939 Stream s = m.Build();
940 ASSERT_EQ(1U, s.size());
941 EXPECT_EQ(memacc.load_opcode, s[0]->arch_opcode());
942 EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
943}
944
945
946TEST_P(InstructionSelectorMemoryAccessTest, StoreWithParameters) {
947 const MemoryAccess memacc = GetParam();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000948 StreamBuilder m(this, MachineType::Int32(), MachineType::Pointer(),
949 MachineType::Int32(), memacc.type);
950 m.Store(memacc.type.representation(), m.Parameter(0), m.Parameter(1),
951 kNoWriteBarrier);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400952 m.Return(m.Int32Constant(0));
953 Stream s = m.Build();
954 ASSERT_EQ(1U, s.size());
955 EXPECT_EQ(memacc.store_opcode, s[0]->arch_opcode());
956 EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
957}
958
959
960INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
961 InstructionSelectorMemoryAccessTest,
962 ::testing::ValuesIn(kMemoryAccesses));
963
964
965// ----------------------------------------------------------------------------
966// Load immediate.
967// ----------------------------------------------------------------------------
968
969
970typedef InstructionSelectorTestWithParam<MemoryAccessImm>
971 InstructionSelectorMemoryAccessImmTest;
972
973
974TEST_P(InstructionSelectorMemoryAccessImmTest, LoadWithImmediateIndex) {
975 const MemoryAccessImm memacc = GetParam();
976 TRACED_FOREACH(int32_t, index, memacc.immediates) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000977 StreamBuilder m(this, memacc.type, MachineType::Pointer());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400978 m.Return(m.Load(memacc.type, m.Parameter(0), m.Int32Constant(index)));
979 Stream s = m.Build();
980 ASSERT_EQ(1U, s.size());
981 EXPECT_EQ(memacc.load_opcode, s[0]->arch_opcode());
982 EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
983 ASSERT_EQ(2U, s[0]->InputCount());
984 ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
985 EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1)));
986 ASSERT_EQ(1U, s[0]->OutputCount());
987 EXPECT_TRUE((s.*memacc.val_predicate)(s[0]->Output()));
988 }
989}
990
991
992// ----------------------------------------------------------------------------
993// Store immediate.
994// ----------------------------------------------------------------------------
995
996
997TEST_P(InstructionSelectorMemoryAccessImmTest, StoreWithImmediateIndex) {
998 const MemoryAccessImm memacc = GetParam();
999 TRACED_FOREACH(int32_t, index, memacc.immediates) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001000 StreamBuilder m(this, MachineType::Int32(), MachineType::Pointer(),
1001 memacc.type);
1002 m.Store(memacc.type.representation(), m.Parameter(0),
1003 m.Int32Constant(index), m.Parameter(1), kNoWriteBarrier);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001004 m.Return(m.Int32Constant(0));
1005 Stream s = m.Build();
1006 ASSERT_EQ(1U, s.size());
1007 EXPECT_EQ(memacc.store_opcode, s[0]->arch_opcode());
1008 EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
1009 ASSERT_EQ(3U, s[0]->InputCount());
1010 ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
1011 EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1)));
1012 EXPECT_EQ(0U, s[0]->OutputCount());
1013 }
1014}
1015
1016
1017INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1018 InstructionSelectorMemoryAccessImmTest,
1019 ::testing::ValuesIn(kMemoryAccessesImm));
1020
1021
1022// ----------------------------------------------------------------------------
1023// Load/store offsets more than 16 bits.
1024// ----------------------------------------------------------------------------
1025
1026
1027typedef InstructionSelectorTestWithParam<MemoryAccessImm1>
1028 InstructionSelectorMemoryAccessImmMoreThan16bitTest;
1029
1030
1031TEST_P(InstructionSelectorMemoryAccessImmMoreThan16bitTest,
1032 LoadWithImmediateIndex) {
1033 const MemoryAccessImm1 memacc = GetParam();
1034 TRACED_FOREACH(int32_t, index, memacc.immediates) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001035 StreamBuilder m(this, memacc.type, MachineType::Pointer());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001036 m.Return(m.Load(memacc.type, m.Parameter(0), m.Int32Constant(index)));
1037 Stream s = m.Build();
1038 ASSERT_EQ(2U, s.size());
1039 // kMipsAdd is expected opcode.
1040 // size more than 16 bits wide.
1041 EXPECT_EQ(kMipsAdd, s[0]->arch_opcode());
1042 EXPECT_EQ(kMode_None, s[0]->addressing_mode());
1043 EXPECT_EQ(2U, s[0]->InputCount());
1044 EXPECT_EQ(1U, s[0]->OutputCount());
1045 }
1046}
1047
1048
1049TEST_P(InstructionSelectorMemoryAccessImmMoreThan16bitTest,
1050 StoreWithImmediateIndex) {
1051 const MemoryAccessImm1 memacc = GetParam();
1052 TRACED_FOREACH(int32_t, index, memacc.immediates) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001053 StreamBuilder m(this, MachineType::Int32(), MachineType::Pointer(),
1054 memacc.type);
1055 m.Store(memacc.type.representation(), m.Parameter(0),
1056 m.Int32Constant(index), m.Parameter(1), kNoWriteBarrier);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001057 m.Return(m.Int32Constant(0));
1058 Stream s = m.Build();
1059 ASSERT_EQ(2U, s.size());
1060 // kMipsAdd is expected opcode
1061 // size more than 16 bits wide
1062 EXPECT_EQ(kMipsAdd, s[0]->arch_opcode());
1063 EXPECT_EQ(kMode_None, s[0]->addressing_mode());
1064 EXPECT_EQ(2U, s[0]->InputCount());
1065 EXPECT_EQ(1U, s[0]->OutputCount());
1066 }
1067}
1068
1069
1070INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1071 InstructionSelectorMemoryAccessImmMoreThan16bitTest,
1072 ::testing::ValuesIn(kMemoryAccessImmMoreThan16bit));
1073
1074
1075// ----------------------------------------------------------------------------
1076// kMipsTst testing.
1077// ----------------------------------------------------------------------------
1078
1079
1080TEST_F(InstructionSelectorTest, Word32EqualWithZero) {
1081 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001082 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001083 m.Return(m.Word32Equal(m.Parameter(0), m.Int32Constant(0)));
1084 Stream s = m.Build();
1085 ASSERT_EQ(1U, s.size());
1086 EXPECT_EQ(kMipsCmp, s[0]->arch_opcode());
1087 EXPECT_EQ(kMode_None, s[0]->addressing_mode());
1088 ASSERT_EQ(2U, s[0]->InputCount());
1089 EXPECT_EQ(1U, s[0]->OutputCount());
1090 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1091 EXPECT_EQ(kEqual, s[0]->flags_condition());
1092 }
1093 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001094 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001095 m.Return(m.Word32Equal(m.Int32Constant(0), m.Parameter(0)));
1096 Stream s = m.Build();
1097 ASSERT_EQ(1U, s.size());
1098 EXPECT_EQ(kMipsCmp, s[0]->arch_opcode());
1099 EXPECT_EQ(kMode_None, s[0]->addressing_mode());
1100 ASSERT_EQ(2U, s[0]->InputCount());
1101 EXPECT_EQ(1U, s[0]->OutputCount());
1102 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1103 EXPECT_EQ(kEqual, s[0]->flags_condition());
1104 }
1105}
1106
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001107
1108TEST_F(InstructionSelectorTest, Word32Clz) {
1109 StreamBuilder m(this, MachineType::Uint32(), MachineType::Uint32());
1110 Node* const p0 = m.Parameter(0);
1111 Node* const n = m.Word32Clz(p0);
1112 m.Return(n);
1113 Stream s = m.Build();
1114 ASSERT_EQ(1U, s.size());
1115 EXPECT_EQ(kMipsClz, s[0]->arch_opcode());
1116 ASSERT_EQ(1U, s[0]->InputCount());
1117 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1118 ASSERT_EQ(1U, s[0]->OutputCount());
1119 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1120}
1121
1122
1123TEST_F(InstructionSelectorTest, Float32Abs) {
1124 StreamBuilder m(this, MachineType::Float32(), MachineType::Float32());
1125 Node* const p0 = m.Parameter(0);
1126 Node* const n = m.Float32Abs(p0);
1127 m.Return(n);
1128 Stream s = m.Build();
1129 ASSERT_EQ(1U, s.size());
1130 EXPECT_EQ(kMipsAbsS, s[0]->arch_opcode());
1131 ASSERT_EQ(1U, s[0]->InputCount());
1132 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1133 ASSERT_EQ(1U, s[0]->OutputCount());
1134 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1135}
1136
1137
1138TEST_F(InstructionSelectorTest, Float64Abs) {
1139 StreamBuilder m(this, MachineType::Float64(), MachineType::Float64());
1140 Node* const p0 = m.Parameter(0);
1141 Node* const n = m.Float64Abs(p0);
1142 m.Return(n);
1143 Stream s = m.Build();
1144 ASSERT_EQ(1U, s.size());
1145 EXPECT_EQ(kMipsAbsD, s[0]->arch_opcode());
1146 ASSERT_EQ(1U, s[0]->InputCount());
1147 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1148 ASSERT_EQ(1U, s[0]->OutputCount());
1149 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1150}
1151
1152
1153TEST_F(InstructionSelectorTest, Float32Max) {
1154 StreamBuilder m(this, MachineType::Float32(), MachineType::Float32(),
1155 MachineType::Float32());
1156 Node* const p0 = m.Parameter(0);
1157 Node* const p1 = m.Parameter(1);
1158 Node* const n = m.Float32Max(p0, p1);
1159 m.Return(n);
1160 Stream s = m.Build();
1161 // Float32Max is `(b < a) ? a : b`.
1162 ASSERT_EQ(1U, s.size());
1163 EXPECT_EQ(kMipsFloat32Max, s[0]->arch_opcode());
1164 ASSERT_EQ(2U, s[0]->InputCount());
1165 ASSERT_EQ(1U, s[0]->OutputCount());
1166 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1167}
1168
1169
1170TEST_F(InstructionSelectorTest, Float32Min) {
1171 StreamBuilder m(this, MachineType::Float32(), MachineType::Float32(),
1172 MachineType::Float32());
1173 Node* const p0 = m.Parameter(0);
1174 Node* const p1 = m.Parameter(1);
1175 Node* const n = m.Float32Min(p0, p1);
1176 m.Return(n);
1177 Stream s = m.Build();
1178 // Float32Min is `(a < b) ? a : b`.
1179 ASSERT_EQ(1U, s.size());
1180 EXPECT_EQ(kMipsFloat32Min, s[0]->arch_opcode());
1181 ASSERT_EQ(2U, s[0]->InputCount());
1182 ASSERT_EQ(1U, s[0]->OutputCount());
1183 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1184}
1185
1186
1187TEST_F(InstructionSelectorTest, Float64Max) {
1188 StreamBuilder m(this, MachineType::Float64(), MachineType::Float64(),
1189 MachineType::Float64());
1190 Node* const p0 = m.Parameter(0);
1191 Node* const p1 = m.Parameter(1);
1192 Node* const n = m.Float64Max(p0, p1);
1193 m.Return(n);
1194 Stream s = m.Build();
1195 // Float64Max is `(b < a) ? a : b`.
1196 ASSERT_EQ(1U, s.size());
1197 EXPECT_EQ(kMipsFloat64Max, s[0]->arch_opcode());
1198 ASSERT_EQ(2U, s[0]->InputCount());
1199 ASSERT_EQ(1U, s[0]->OutputCount());
1200 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1201}
1202
1203
1204TEST_F(InstructionSelectorTest, Float64Min) {
1205 StreamBuilder m(this, MachineType::Float64(), MachineType::Float64(),
1206 MachineType::Float64());
1207 Node* const p0 = m.Parameter(0);
1208 Node* const p1 = m.Parameter(1);
1209 Node* const n = m.Float64Min(p0, p1);
1210 m.Return(n);
1211 Stream s = m.Build();
1212 // Float64Min is `(a < b) ? a : b`.
1213 ASSERT_EQ(1U, s.size());
1214 EXPECT_EQ(kMipsFloat64Min, s[0]->arch_opcode());
1215 ASSERT_EQ(2U, s[0]->InputCount());
1216 ASSERT_EQ(1U, s[0]->OutputCount());
1217 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1218}
1219
1220
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001221} // namespace compiler
1222} // namespace internal
1223} // namespace v8