blob: d9cd96f47108be5a33fd3e336162125a95b78555 [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 {
12template <typename T>
13struct MachInst {
14 T constructor;
15 const char* constructor_name;
16 ArchOpcode arch_opcode;
17 MachineType machine_type;
18};
19
20template <typename T>
21std::ostream& operator<<(std::ostream& os, const MachInst<T>& mi) {
22 return os << mi.constructor_name;
23}
24
25typedef MachInst<Node* (RawMachineAssembler::*)(Node*)> MachInst1;
26typedef MachInst<Node* (RawMachineAssembler::*)(Node*, Node*)> MachInst2;
27
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", kMips64CmpD,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000044 MachineType::Float64()},
45 kEqual},
Emily Bernierd0a1eb72015-03-24 16:35:39 -040046 {{&RawMachineAssembler::Float64LessThan, "Float64LessThan", kMips64CmpD,
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 kMips64CmpD, MachineType::Float64()},
51 kUnsignedLessThanOrEqual},
Emily Bernierd0a1eb72015-03-24 16:35:39 -040052 {{&RawMachineAssembler::Float64GreaterThan, "Float64GreaterThan",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000053 kMips64CmpD, MachineType::Float64()},
54 kUnsignedLessThan},
Emily Bernierd0a1eb72015-03-24 16:35:39 -040055 {{&RawMachineAssembler::Float64GreaterThanOrEqual,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000056 "Float64GreaterThanOrEqual", kMips64CmpD, 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::Word32And, "Word32And", kMips64And,
73 MachineType::Int32()},
74 {&RawMachineAssembler::Word64And, "Word64And", kMips64And,
75 MachineType::Int64()},
76 {&RawMachineAssembler::Word32Or, "Word32Or", kMips64Or,
77 MachineType::Int32()},
78 {&RawMachineAssembler::Word64Or, "Word64Or", kMips64Or,
79 MachineType::Int64()},
80 {&RawMachineAssembler::Word32Xor, "Word32Xor", kMips64Xor,
81 MachineType::Int32()},
82 {&RawMachineAssembler::Word64Xor, "Word64Xor", kMips64Xor,
83 MachineType::Int64()}};
Emily Bernierd0a1eb72015-03-24 16:35:39 -040084
85
86// ----------------------------------------------------------------------------
87// Shift instructions.
88// ----------------------------------------------------------------------------
89
90
91const MachInst2 kShiftInstructions[] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000092 {&RawMachineAssembler::Word32Shl, "Word32Shl", kMips64Shl,
93 MachineType::Int32()},
94 {&RawMachineAssembler::Word64Shl, "Word64Shl", kMips64Dshl,
95 MachineType::Int64()},
96 {&RawMachineAssembler::Word32Shr, "Word32Shr", kMips64Shr,
97 MachineType::Int32()},
98 {&RawMachineAssembler::Word64Shr, "Word64Shr", kMips64Dshr,
99 MachineType::Int64()},
100 {&RawMachineAssembler::Word32Sar, "Word32Sar", kMips64Sar,
101 MachineType::Int32()},
102 {&RawMachineAssembler::Word64Sar, "Word64Sar", kMips64Dsar,
103 MachineType::Int64()},
104 {&RawMachineAssembler::Word32Ror, "Word32Ror", kMips64Ror,
105 MachineType::Int32()},
106 {&RawMachineAssembler::Word64Ror, "Word64Ror", kMips64Dror,
107 MachineType::Int64()}};
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400108
109
110// ----------------------------------------------------------------------------
111// MUL/DIV instructions.
112// ----------------------------------------------------------------------------
113
114
115const MachInst2 kMulDivInstructions[] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000116 {&RawMachineAssembler::Int32Mul, "Int32Mul", kMips64Mul,
117 MachineType::Int32()},
118 {&RawMachineAssembler::Int32Div, "Int32Div", kMips64Div,
119 MachineType::Int32()},
120 {&RawMachineAssembler::Uint32Div, "Uint32Div", kMips64DivU,
121 MachineType::Uint32()},
122 {&RawMachineAssembler::Int64Mul, "Int64Mul", kMips64Dmul,
123 MachineType::Int64()},
124 {&RawMachineAssembler::Int64Div, "Int64Div", kMips64Ddiv,
125 MachineType::Int64()},
126 {&RawMachineAssembler::Uint64Div, "Uint64Div", kMips64DdivU,
127 MachineType::Uint64()},
128 {&RawMachineAssembler::Float64Mul, "Float64Mul", kMips64MulD,
129 MachineType::Float64()},
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400130 {&RawMachineAssembler::Float64Div, "Float64Div", kMips64DivD,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000131 MachineType::Float64()}};
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400132
133
134// ----------------------------------------------------------------------------
135// MOD instructions.
136// ----------------------------------------------------------------------------
137
138
139const MachInst2 kModInstructions[] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000140 {&RawMachineAssembler::Int32Mod, "Int32Mod", kMips64Mod,
141 MachineType::Int32()},
142 {&RawMachineAssembler::Uint32Mod, "Uint32Mod", kMips64ModU,
143 MachineType::Int32()},
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400144 {&RawMachineAssembler::Float64Mod, "Float64Mod", kMips64ModD,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000145 MachineType::Float64()}};
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400146
147
148// ----------------------------------------------------------------------------
149// Arithmetic FPU instructions.
150// ----------------------------------------------------------------------------
151
152
153const MachInst2 kFPArithInstructions[] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000154 {&RawMachineAssembler::Float64Add, "Float64Add", kMips64AddD,
155 MachineType::Float64()},
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400156 {&RawMachineAssembler::Float64Sub, "Float64Sub", kMips64SubD,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000157 MachineType::Float64()}};
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400158
159
160// ----------------------------------------------------------------------------
161// IntArithTest instructions, two nodes.
162// ----------------------------------------------------------------------------
163
164
165const MachInst2 kAddSubInstructions[] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000166 {&RawMachineAssembler::Int32Add, "Int32Add", kMips64Add,
167 MachineType::Int32()},
168 {&RawMachineAssembler::Int64Add, "Int64Add", kMips64Dadd,
169 MachineType::Int64()},
170 {&RawMachineAssembler::Int32Sub, "Int32Sub", kMips64Sub,
171 MachineType::Int32()},
172 {&RawMachineAssembler::Int64Sub, "Int64Sub", kMips64Dsub,
173 MachineType::Int64()}};
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400174
175
176// ----------------------------------------------------------------------------
177// IntArithTest instructions, one node.
178// ----------------------------------------------------------------------------
179
180
181const MachInst1 kAddSubOneInstructions[] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000182 {&RawMachineAssembler::Int32Neg, "Int32Neg", kMips64Sub,
183 MachineType::Int32()},
184 {&RawMachineAssembler::Int64Neg, "Int64Neg", kMips64Dsub,
185 MachineType::Int64()}};
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400186
187
188// ----------------------------------------------------------------------------
189// Arithmetic compare instructions.
190// ----------------------------------------------------------------------------
191
192
193const IntCmp kCmpInstructions[] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000194 {{&RawMachineAssembler::WordEqual, "WordEqual", kMips64Cmp,
195 MachineType::Int64()},
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400196 1U},
197 {{&RawMachineAssembler::WordNotEqual, "WordNotEqual", kMips64Cmp,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000198 MachineType::Int64()},
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400199 1U},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000200 {{&RawMachineAssembler::Word32Equal, "Word32Equal", kMips64Cmp,
201 MachineType::Int32()},
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400202 1U},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000203 {{&RawMachineAssembler::Word32NotEqual, "Word32NotEqual", kMips64Cmp,
204 MachineType::Int32()},
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400205 1U},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000206 {{&RawMachineAssembler::Int32LessThan, "Int32LessThan", kMips64Cmp,
207 MachineType::Int32()},
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400208 1U},
209 {{&RawMachineAssembler::Int32LessThanOrEqual, "Int32LessThanOrEqual",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000210 kMips64Cmp, MachineType::Int32()},
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400211 1U},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000212 {{&RawMachineAssembler::Int32GreaterThan, "Int32GreaterThan", kMips64Cmp,
213 MachineType::Int32()},
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400214 1U},
215 {{&RawMachineAssembler::Int32GreaterThanOrEqual, "Int32GreaterThanOrEqual",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000216 kMips64Cmp, MachineType::Int32()},
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400217 1U},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000218 {{&RawMachineAssembler::Uint32LessThan, "Uint32LessThan", kMips64Cmp,
219 MachineType::Uint32()},
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400220 1U},
221 {{&RawMachineAssembler::Uint32LessThanOrEqual, "Uint32LessThanOrEqual",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000222 kMips64Cmp, MachineType::Uint32()},
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400223 1U}};
224
225
226// ----------------------------------------------------------------------------
227// Conversion instructions.
228// ----------------------------------------------------------------------------
229
230const Conversion kConversionInstructions[] = {
231 // Conversion instructions are related to machine_operator.h:
232 // FPU conversions:
233 // Convert representation of integers between float64 and int32/uint32.
234 // The precise rounding mode and handling of out of range inputs are *not*
235 // defined for these operators, since they are intended only for use with
236 // integers.
237 // mips instructions:
238 // mtc1, cvt.d.w
239 {{&RawMachineAssembler::ChangeInt32ToFloat64, "ChangeInt32ToFloat64",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000240 kMips64CvtDW, MachineType::Float64()},
241 MachineType::Int32()},
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400242
243 // mips instructions:
244 // cvt.d.uw
245 {{&RawMachineAssembler::ChangeUint32ToFloat64, "ChangeUint32ToFloat64",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000246 kMips64CvtDUw, MachineType::Float64()},
247 MachineType::Int32()},
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400248
249 // mips instructions:
250 // mfc1, trunc double to word, for more details look at mips macro
251 // asm and mips asm file
252 {{&RawMachineAssembler::ChangeFloat64ToInt32, "ChangeFloat64ToInt32",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000253 kMips64TruncWD, MachineType::Float64()},
254 MachineType::Int32()},
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400255
256 // mips instructions:
257 // trunc double to unsigned word, for more details look at mips macro
258 // asm and mips asm file
259 {{&RawMachineAssembler::ChangeFloat64ToUint32, "ChangeFloat64ToUint32",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000260 kMips64TruncUwD, MachineType::Float64()},
261 MachineType::Int32()}};
262
263const Conversion kFloat64RoundInstructions[] = {
264 {{&RawMachineAssembler::Float64RoundUp, "Float64RoundUp", kMips64CeilWD,
265 MachineType::Int32()},
266 MachineType::Float64()},
267 {{&RawMachineAssembler::Float64RoundDown, "Float64RoundDown",
268 kMips64FloorWD, MachineType::Int32()},
269 MachineType::Float64()},
270 {{&RawMachineAssembler::Float64RoundTiesEven, "Float64RoundTiesEven",
271 kMips64RoundWD, MachineType::Int32()},
272 MachineType::Float64()},
273 {{&RawMachineAssembler::Float64RoundTruncate, "Float64RoundTruncate",
274 kMips64TruncWD, MachineType::Int32()},
275 MachineType::Float64()}};
276
277const Conversion kFloat32RoundInstructions[] = {
278 {{&RawMachineAssembler::Float32RoundUp, "Float32RoundUp", kMips64CeilWS,
279 MachineType::Int32()},
280 MachineType::Float32()},
281 {{&RawMachineAssembler::Float32RoundDown, "Float32RoundDown",
282 kMips64FloorWS, MachineType::Int32()},
283 MachineType::Float32()},
284 {{&RawMachineAssembler::Float32RoundTiesEven, "Float32RoundTiesEven",
285 kMips64RoundWS, MachineType::Int32()},
286 MachineType::Float32()},
287 {{&RawMachineAssembler::Float32RoundTruncate, "Float32RoundTruncate",
288 kMips64TruncWS, MachineType::Int32()},
289 MachineType::Float32()}};
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400290
291} // namespace
292
293
294typedef InstructionSelectorTestWithParam<FPCmp> InstructionSelectorFPCmpTest;
295
296TEST_P(InstructionSelectorFPCmpTest, Parameter) {
297 const FPCmp cmp = GetParam();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000298 StreamBuilder m(this, MachineType::Int32(), cmp.mi.machine_type,
299 cmp.mi.machine_type);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400300 m.Return((m.*cmp.mi.constructor)(m.Parameter(0), m.Parameter(1)));
301 Stream s = m.Build();
302 ASSERT_EQ(1U, s.size());
303 EXPECT_EQ(cmp.mi.arch_opcode, s[0]->arch_opcode());
304 EXPECT_EQ(2U, s[0]->InputCount());
305 EXPECT_EQ(1U, s[0]->OutputCount());
306 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
307 EXPECT_EQ(cmp.cond, s[0]->flags_condition());
308}
309
310INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorFPCmpTest,
311 ::testing::ValuesIn(kFPCmpInstructions));
312
313// ----------------------------------------------------------------------------
314// Arithmetic compare instructions integers
315// ----------------------------------------------------------------------------
316typedef InstructionSelectorTestWithParam<IntCmp> InstructionSelectorCmpTest;
317
318
319TEST_P(InstructionSelectorCmpTest, Parameter) {
320 const IntCmp cmp = GetParam();
321 const MachineType type = cmp.mi.machine_type;
322 StreamBuilder m(this, type, type, type);
323 m.Return((m.*cmp.mi.constructor)(m.Parameter(0), m.Parameter(1)));
324 Stream s = m.Build();
325 ASSERT_EQ(cmp.expected_size, s.size());
326 EXPECT_EQ(cmp.mi.arch_opcode, s[0]->arch_opcode());
327 EXPECT_EQ(2U, s[0]->InputCount());
328 EXPECT_EQ(1U, s[0]->OutputCount());
329}
330
331INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorCmpTest,
332 ::testing::ValuesIn(kCmpInstructions));
333
334// ----------------------------------------------------------------------------
335// Shift instructions.
336// ----------------------------------------------------------------------------
337typedef InstructionSelectorTestWithParam<MachInst2>
338 InstructionSelectorShiftTest;
339
340TEST_P(InstructionSelectorShiftTest, Immediate) {
341 const MachInst2 dpi = GetParam();
342 const MachineType type = dpi.machine_type;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000343 TRACED_FORRANGE(int32_t, imm, 0,
344 ((1 << ElementSizeLog2Of(type.representation())) * 8) - 1) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400345 StreamBuilder m(this, type, type);
346 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm)));
347 Stream s = m.Build();
348 ASSERT_EQ(1U, s.size());
349 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
350 EXPECT_EQ(2U, s[0]->InputCount());
351 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
352 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
353 EXPECT_EQ(1U, s[0]->OutputCount());
354 }
355}
356
357INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorShiftTest,
358 ::testing::ValuesIn(kShiftInstructions));
359
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000360TEST_F(InstructionSelectorTest, Word32ShrWithWord32AndWithImmediate) {
361 // The available shift operand range is `0 <= imm < 32`, but we also test
362 // that immediates outside this range are handled properly (modulo-32).
363 TRACED_FORRANGE(int32_t, shift, -32, 63) {
364 int32_t lsb = shift & 0x1f;
365 TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) {
366 uint32_t jnk = rng()->NextInt();
367 jnk = (lsb > 0) ? (jnk >> (32 - lsb)) : 0;
368 uint32_t msk = ((0xffffffffu >> (32 - width)) << lsb) | jnk;
369 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
370 m.Return(m.Word32Shr(m.Word32And(m.Parameter(0), m.Int32Constant(msk)),
371 m.Int32Constant(shift)));
372 Stream s = m.Build();
373 ASSERT_EQ(1U, s.size());
374 EXPECT_EQ(kMips64Ext, s[0]->arch_opcode());
375 ASSERT_EQ(3U, s[0]->InputCount());
376 EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
377 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
378 }
379 }
380 TRACED_FORRANGE(int32_t, shift, -32, 63) {
381 int32_t lsb = shift & 0x1f;
382 TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) {
383 uint32_t jnk = rng()->NextInt();
384 jnk = (lsb > 0) ? (jnk >> (32 - lsb)) : 0;
385 uint32_t msk = ((0xffffffffu >> (32 - width)) << lsb) | jnk;
386 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
387 m.Return(m.Word32Shr(m.Word32And(m.Int32Constant(msk), m.Parameter(0)),
388 m.Int32Constant(shift)));
389 Stream s = m.Build();
390 ASSERT_EQ(1U, s.size());
391 EXPECT_EQ(kMips64Ext, s[0]->arch_opcode());
392 ASSERT_EQ(3U, s[0]->InputCount());
393 EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
394 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
395 }
396 }
397}
398
399
400TEST_F(InstructionSelectorTest, Word64ShrWithWord64AndWithImmediate) {
401 // The available shift operand range is `0 <= imm < 64`, but we also test
402 // that immediates outside this range are handled properly (modulo-64).
403 TRACED_FORRANGE(int32_t, shift, -64, 127) {
404 int32_t lsb = shift & 0x3f;
405 TRACED_FORRANGE(int32_t, width, 1, 64 - lsb) {
406 uint64_t jnk = rng()->NextInt64();
407 jnk = (lsb > 0) ? (jnk >> (64 - lsb)) : 0;
408 uint64_t msk =
409 ((V8_UINT64_C(0xffffffffffffffff) >> (64 - width)) << lsb) | jnk;
410 StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
411 m.Return(m.Word64Shr(m.Word64And(m.Parameter(0), m.Int64Constant(msk)),
412 m.Int64Constant(shift)));
413 Stream s = m.Build();
414 ASSERT_EQ(1U, s.size());
415 EXPECT_EQ(kMips64Dext, s[0]->arch_opcode());
416 ASSERT_EQ(3U, s[0]->InputCount());
417 EXPECT_EQ(lsb, s.ToInt64(s[0]->InputAt(1)));
418 EXPECT_EQ(width, s.ToInt64(s[0]->InputAt(2)));
419 }
420 }
421 TRACED_FORRANGE(int32_t, shift, -64, 127) {
422 int32_t lsb = shift & 0x3f;
423 TRACED_FORRANGE(int32_t, width, 1, 64 - lsb) {
424 uint64_t jnk = rng()->NextInt64();
425 jnk = (lsb > 0) ? (jnk >> (64 - lsb)) : 0;
426 uint64_t msk =
427 ((V8_UINT64_C(0xffffffffffffffff) >> (64 - width)) << lsb) | jnk;
428 StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
429 m.Return(m.Word64Shr(m.Word64And(m.Int64Constant(msk), m.Parameter(0)),
430 m.Int64Constant(shift)));
431 Stream s = m.Build();
432 ASSERT_EQ(1U, s.size());
433 EXPECT_EQ(kMips64Dext, s[0]->arch_opcode());
434 ASSERT_EQ(3U, s[0]->InputCount());
435 EXPECT_EQ(lsb, s.ToInt64(s[0]->InputAt(1)));
436 EXPECT_EQ(width, s.ToInt64(s[0]->InputAt(2)));
437 }
438 }
439}
440
441
442TEST_F(InstructionSelectorTest, Word32AndToClearBits) {
443 TRACED_FORRANGE(int32_t, shift, 1, 31) {
444 int32_t mask = ~((1 << shift) - 1);
445 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
446 m.Return(m.Word32And(m.Parameter(0), m.Int32Constant(mask)));
447 Stream s = m.Build();
448 ASSERT_EQ(1U, s.size());
449 EXPECT_EQ(kMips64Ins, s[0]->arch_opcode());
450 ASSERT_EQ(3U, s[0]->InputCount());
451 EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1)));
452 EXPECT_EQ(shift, s.ToInt32(s[0]->InputAt(2)));
453 }
454 TRACED_FORRANGE(int32_t, shift, 1, 31) {
455 int32_t mask = ~((1 << shift) - 1);
456 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
457 m.Return(m.Word32And(m.Int32Constant(mask), m.Parameter(0)));
458 Stream s = m.Build();
459 ASSERT_EQ(1U, s.size());
460 EXPECT_EQ(kMips64Ins, s[0]->arch_opcode());
461 ASSERT_EQ(3U, s[0]->InputCount());
462 EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1)));
463 EXPECT_EQ(shift, s.ToInt32(s[0]->InputAt(2)));
464 }
465}
466
467
468TEST_F(InstructionSelectorTest, Word64AndToClearBits) {
469 TRACED_FORRANGE(int32_t, shift, 1, 31) {
470 int64_t mask = ~((1 << shift) - 1);
471 StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
472 m.Return(m.Word64And(m.Parameter(0), m.Int64Constant(mask)));
473 Stream s = m.Build();
474 ASSERT_EQ(1U, s.size());
475 EXPECT_EQ(kMips64Dins, s[0]->arch_opcode());
476 ASSERT_EQ(3U, s[0]->InputCount());
477 EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1)));
478 EXPECT_EQ(shift, s.ToInt32(s[0]->InputAt(2)));
479 }
480 TRACED_FORRANGE(int32_t, shift, 1, 31) {
481 int64_t mask = ~((1 << shift) - 1);
482 StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
483 m.Return(m.Word64And(m.Int64Constant(mask), m.Parameter(0)));
484 Stream s = m.Build();
485 ASSERT_EQ(1U, s.size());
486 EXPECT_EQ(kMips64Dins, s[0]->arch_opcode());
487 ASSERT_EQ(3U, s[0]->InputCount());
488 EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1)));
489 EXPECT_EQ(shift, s.ToInt32(s[0]->InputAt(2)));
490 }
491}
492
493
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400494// ----------------------------------------------------------------------------
495// Logical instructions.
496// ----------------------------------------------------------------------------
497typedef InstructionSelectorTestWithParam<MachInst2>
498 InstructionSelectorLogicalTest;
499
500
501TEST_P(InstructionSelectorLogicalTest, Parameter) {
502 const MachInst2 dpi = GetParam();
503 const MachineType type = dpi.machine_type;
504 StreamBuilder m(this, type, type, type);
505 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)));
506 Stream s = m.Build();
507 ASSERT_EQ(1U, s.size());
508 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
509 EXPECT_EQ(2U, s[0]->InputCount());
510 EXPECT_EQ(1U, s[0]->OutputCount());
511}
512
513INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorLogicalTest,
514 ::testing::ValuesIn(kLogicalInstructions));
515
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000516
517TEST_F(InstructionSelectorTest, Word64XorMinusOneWithParameter) {
518 {
519 StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
520 m.Return(m.Word64Xor(m.Parameter(0), m.Int64Constant(-1)));
521 Stream s = m.Build();
522 ASSERT_EQ(1U, s.size());
523 EXPECT_EQ(kMips64Nor, s[0]->arch_opcode());
524 EXPECT_EQ(2U, s[0]->InputCount());
525 EXPECT_EQ(1U, s[0]->OutputCount());
526 }
527 {
528 StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
529 m.Return(m.Word64Xor(m.Int64Constant(-1), m.Parameter(0)));
530 Stream s = m.Build();
531 ASSERT_EQ(1U, s.size());
532 EXPECT_EQ(kMips64Nor, s[0]->arch_opcode());
533 EXPECT_EQ(2U, s[0]->InputCount());
534 EXPECT_EQ(1U, s[0]->OutputCount());
535 }
536}
537
538
539TEST_F(InstructionSelectorTest, Word32XorMinusOneWithParameter) {
540 {
541 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
542 m.Return(m.Word32Xor(m.Parameter(0), m.Int32Constant(-1)));
543 Stream s = m.Build();
544 ASSERT_EQ(1U, s.size());
545 EXPECT_EQ(kMips64Nor, s[0]->arch_opcode());
546 EXPECT_EQ(2U, s[0]->InputCount());
547 EXPECT_EQ(1U, s[0]->OutputCount());
548 }
549 {
550 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
551 m.Return(m.Word32Xor(m.Int32Constant(-1), m.Parameter(0)));
552 Stream s = m.Build();
553 ASSERT_EQ(1U, s.size());
554 EXPECT_EQ(kMips64Nor, s[0]->arch_opcode());
555 EXPECT_EQ(2U, s[0]->InputCount());
556 EXPECT_EQ(1U, s[0]->OutputCount());
557 }
558}
559
560
561TEST_F(InstructionSelectorTest, Word64XorMinusOneWithWord64Or) {
562 {
563 StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
564 m.Return(m.Word64Xor(m.Word64Or(m.Parameter(0), m.Parameter(0)),
565 m.Int64Constant(-1)));
566 Stream s = m.Build();
567 ASSERT_EQ(1U, s.size());
568 EXPECT_EQ(kMips64Nor, s[0]->arch_opcode());
569 EXPECT_EQ(2U, s[0]->InputCount());
570 EXPECT_EQ(1U, s[0]->OutputCount());
571 }
572 {
573 StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
574 m.Return(m.Word64Xor(m.Int64Constant(-1),
575 m.Word64Or(m.Parameter(0), m.Parameter(0))));
576 Stream s = m.Build();
577 ASSERT_EQ(1U, s.size());
578 EXPECT_EQ(kMips64Nor, s[0]->arch_opcode());
579 EXPECT_EQ(2U, s[0]->InputCount());
580 EXPECT_EQ(1U, s[0]->OutputCount());
581 }
582}
583
584
585TEST_F(InstructionSelectorTest, Word32XorMinusOneWithWord32Or) {
586 {
587 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
588 m.Return(m.Word32Xor(m.Word32Or(m.Parameter(0), m.Parameter(0)),
589 m.Int32Constant(-1)));
590 Stream s = m.Build();
591 ASSERT_EQ(1U, s.size());
592 EXPECT_EQ(kMips64Nor, s[0]->arch_opcode());
593 EXPECT_EQ(2U, s[0]->InputCount());
594 EXPECT_EQ(1U, s[0]->OutputCount());
595 }
596 {
597 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
598 m.Return(m.Word32Xor(m.Int32Constant(-1),
599 m.Word32Or(m.Parameter(0), m.Parameter(0))));
600 Stream s = m.Build();
601 ASSERT_EQ(1U, s.size());
602 EXPECT_EQ(kMips64Nor, s[0]->arch_opcode());
603 EXPECT_EQ(2U, s[0]->InputCount());
604 EXPECT_EQ(1U, s[0]->OutputCount());
605 }
606}
607
608
609TEST_F(InstructionSelectorTest, Word32AndWithImmediateWithWord32Shr) {
610 // The available shift operand range is `0 <= imm < 32`, but we also test
611 // that immediates outside this range are handled properly (modulo-32).
612 TRACED_FORRANGE(int32_t, shift, -32, 63) {
613 int32_t lsb = shift & 0x1f;
614 TRACED_FORRANGE(int32_t, width, 1, 31) {
615 uint32_t msk = (1 << width) - 1;
616 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
617 m.Return(m.Word32And(m.Word32Shr(m.Parameter(0), m.Int32Constant(shift)),
618 m.Int32Constant(msk)));
619 Stream s = m.Build();
620 ASSERT_EQ(1U, s.size());
621 EXPECT_EQ(kMips64Ext, s[0]->arch_opcode());
622 ASSERT_EQ(3U, s[0]->InputCount());
623 EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
624 int32_t actual_width = (lsb + width > 32) ? (32 - lsb) : width;
625 EXPECT_EQ(actual_width, s.ToInt32(s[0]->InputAt(2)));
626 }
627 }
628 TRACED_FORRANGE(int32_t, shift, -32, 63) {
629 int32_t lsb = shift & 0x1f;
630 TRACED_FORRANGE(int32_t, width, 1, 31) {
631 uint32_t msk = (1 << width) - 1;
632 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
633 m.Return(
634 m.Word32And(m.Int32Constant(msk),
635 m.Word32Shr(m.Parameter(0), m.Int32Constant(shift))));
636 Stream s = m.Build();
637 ASSERT_EQ(1U, s.size());
638 EXPECT_EQ(kMips64Ext, s[0]->arch_opcode());
639 ASSERT_EQ(3U, s[0]->InputCount());
640 EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
641 int32_t actual_width = (lsb + width > 32) ? (32 - lsb) : width;
642 EXPECT_EQ(actual_width, s.ToInt32(s[0]->InputAt(2)));
643 }
644 }
645}
646
647
648TEST_F(InstructionSelectorTest, Word64AndWithImmediateWithWord64Shr) {
649 // The available shift operand range is `0 <= imm < 64`, but we also test
650 // that immediates outside this range are handled properly (modulo-64).
651 TRACED_FORRANGE(int64_t, shift, -64, 127) {
652 int64_t lsb = shift & 0x3f;
653 TRACED_FORRANGE(int64_t, width, 1, 63) {
654 uint64_t msk = (V8_UINT64_C(1) << width) - 1;
655 StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
656 m.Return(m.Word64And(m.Word64Shr(m.Parameter(0), m.Int64Constant(shift)),
657 m.Int64Constant(msk)));
658 Stream s = m.Build();
659 ASSERT_EQ(1U, s.size());
660 EXPECT_EQ(kMips64Dext, s[0]->arch_opcode());
661 ASSERT_EQ(3U, s[0]->InputCount());
662 EXPECT_EQ(lsb, s.ToInt64(s[0]->InputAt(1)));
663 int64_t actual_width = (lsb + width > 64) ? (64 - lsb) : width;
664 EXPECT_EQ(actual_width, s.ToInt64(s[0]->InputAt(2)));
665 }
666 }
667 TRACED_FORRANGE(int64_t, shift, -64, 127) {
668 int64_t lsb = shift & 0x3f;
669 TRACED_FORRANGE(int64_t, width, 1, 63) {
670 uint64_t msk = (V8_UINT64_C(1) << width) - 1;
671 StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
672 m.Return(
673 m.Word64And(m.Int64Constant(msk),
674 m.Word64Shr(m.Parameter(0), m.Int64Constant(shift))));
675 Stream s = m.Build();
676 ASSERT_EQ(1U, s.size());
677 EXPECT_EQ(kMips64Dext, s[0]->arch_opcode());
678 ASSERT_EQ(3U, s[0]->InputCount());
679 EXPECT_EQ(lsb, s.ToInt64(s[0]->InputAt(1)));
680 int64_t actual_width = (lsb + width > 64) ? (64 - lsb) : width;
681 EXPECT_EQ(actual_width, s.ToInt64(s[0]->InputAt(2)));
682 }
683 }
684}
685
686
687TEST_F(InstructionSelectorTest, Word32ShlWithWord32And) {
688 TRACED_FORRANGE(int32_t, shift, 0, 30) {
689 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
690 Node* const p0 = m.Parameter(0);
691 Node* const r =
692 m.Word32Shl(m.Word32And(p0, m.Int32Constant((1 << (31 - shift)) - 1)),
693 m.Int32Constant(shift + 1));
694 m.Return(r);
695 Stream s = m.Build();
696 ASSERT_EQ(1U, s.size());
697 EXPECT_EQ(kMips64Shl, s[0]->arch_opcode());
698 ASSERT_EQ(2U, s[0]->InputCount());
699 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
700 ASSERT_EQ(1U, s[0]->OutputCount());
701 EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
702 }
703}
704
705
706TEST_F(InstructionSelectorTest, Word64ShlWithWord64And) {
707 TRACED_FORRANGE(int32_t, shift, 0, 62) {
708 StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
709 Node* const p0 = m.Parameter(0);
710 Node* const r =
711 m.Word64Shl(m.Word64And(p0, m.Int64Constant((1L << (63 - shift)) - 1)),
712 m.Int64Constant(shift + 1));
713 m.Return(r);
714 Stream s = m.Build();
715 ASSERT_EQ(1U, s.size());
716 EXPECT_EQ(kMips64Dshl, s[0]->arch_opcode());
717 ASSERT_EQ(2U, s[0]->InputCount());
718 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
719 ASSERT_EQ(1U, s[0]->OutputCount());
720 EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
721 }
722}
723
724
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400725// ----------------------------------------------------------------------------
726// MUL/DIV instructions.
727// ----------------------------------------------------------------------------
728typedef InstructionSelectorTestWithParam<MachInst2>
729 InstructionSelectorMulDivTest;
730
731TEST_P(InstructionSelectorMulDivTest, Parameter) {
732 const MachInst2 dpi = GetParam();
733 const MachineType type = dpi.machine_type;
734 StreamBuilder m(this, type, type, type);
735 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)));
736 Stream s = m.Build();
737 ASSERT_EQ(1U, s.size());
738 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
739 EXPECT_EQ(2U, s[0]->InputCount());
740 EXPECT_EQ(1U, s[0]->OutputCount());
741}
742
743INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorMulDivTest,
744 ::testing::ValuesIn(kMulDivInstructions));
745
746// ----------------------------------------------------------------------------
747// MOD instructions.
748// ----------------------------------------------------------------------------
749typedef InstructionSelectorTestWithParam<MachInst2> InstructionSelectorModTest;
750
751TEST_P(InstructionSelectorModTest, Parameter) {
752 const MachInst2 dpi = GetParam();
753 const MachineType type = dpi.machine_type;
754 StreamBuilder m(this, type, type, type);
755 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)));
756 Stream s = m.Build();
757 ASSERT_EQ(1U, s.size());
758 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
759 EXPECT_EQ(2U, s[0]->InputCount());
760 EXPECT_EQ(1U, s[0]->OutputCount());
761}
762
763INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorModTest,
764 ::testing::ValuesIn(kModInstructions));
765
766// ----------------------------------------------------------------------------
767// Floating point instructions.
768// ----------------------------------------------------------------------------
769typedef InstructionSelectorTestWithParam<MachInst2>
770 InstructionSelectorFPArithTest;
771
772TEST_P(InstructionSelectorFPArithTest, Parameter) {
773 const MachInst2 fpa = GetParam();
774 StreamBuilder m(this, fpa.machine_type, fpa.machine_type, fpa.machine_type);
775 m.Return((m.*fpa.constructor)(m.Parameter(0), m.Parameter(1)));
776 Stream s = m.Build();
777 ASSERT_EQ(1U, s.size());
778 EXPECT_EQ(fpa.arch_opcode, s[0]->arch_opcode());
779 EXPECT_EQ(2U, s[0]->InputCount());
780 EXPECT_EQ(1U, s[0]->OutputCount());
781}
782
783INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorFPArithTest,
784 ::testing::ValuesIn(kFPArithInstructions));
785// ----------------------------------------------------------------------------
786// Integer arithmetic
787// ----------------------------------------------------------------------------
788typedef InstructionSelectorTestWithParam<MachInst2>
789 InstructionSelectorIntArithTwoTest;
790
791TEST_P(InstructionSelectorIntArithTwoTest, Parameter) {
792 const MachInst2 intpa = GetParam();
793 StreamBuilder m(this, intpa.machine_type, intpa.machine_type,
794 intpa.machine_type);
795 m.Return((m.*intpa.constructor)(m.Parameter(0), m.Parameter(1)));
796 Stream s = m.Build();
797 ASSERT_EQ(1U, s.size());
798 EXPECT_EQ(intpa.arch_opcode, s[0]->arch_opcode());
799 EXPECT_EQ(2U, s[0]->InputCount());
800 EXPECT_EQ(1U, s[0]->OutputCount());
801}
802
803INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
804 InstructionSelectorIntArithTwoTest,
805 ::testing::ValuesIn(kAddSubInstructions));
806
807
808// ----------------------------------------------------------------------------
809// One node.
810// ----------------------------------------------------------------------------
811
812
813typedef InstructionSelectorTestWithParam<MachInst1>
814 InstructionSelectorIntArithOneTest;
815
816TEST_P(InstructionSelectorIntArithOneTest, Parameter) {
817 const MachInst1 intpa = GetParam();
818 StreamBuilder m(this, intpa.machine_type, intpa.machine_type,
819 intpa.machine_type);
820 m.Return((m.*intpa.constructor)(m.Parameter(0)));
821 Stream s = m.Build();
822 ASSERT_EQ(1U, s.size());
823 EXPECT_EQ(intpa.arch_opcode, s[0]->arch_opcode());
824 EXPECT_EQ(2U, s[0]->InputCount());
825 EXPECT_EQ(1U, s[0]->OutputCount());
826}
827
828INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
829 InstructionSelectorIntArithOneTest,
830 ::testing::ValuesIn(kAddSubOneInstructions));
831// ----------------------------------------------------------------------------
832// Conversions.
833// ----------------------------------------------------------------------------
834typedef InstructionSelectorTestWithParam<Conversion>
835 InstructionSelectorConversionTest;
836
837TEST_P(InstructionSelectorConversionTest, Parameter) {
838 const Conversion conv = GetParam();
839 StreamBuilder m(this, conv.mi.machine_type, conv.src_machine_type);
840 m.Return((m.*conv.mi.constructor)(m.Parameter(0)));
841 Stream s = m.Build();
842 ASSERT_EQ(1U, s.size());
843 EXPECT_EQ(conv.mi.arch_opcode, s[0]->arch_opcode());
844 EXPECT_EQ(1U, s[0]->InputCount());
845 EXPECT_EQ(1U, s[0]->OutputCount());
846}
847
848INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
849 InstructionSelectorConversionTest,
850 ::testing::ValuesIn(kConversionInstructions));
851
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000852TEST_F(InstructionSelectorTest, ChangesFromToSmi) {
853 {
854 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
855 m.Return(m.TruncateInt64ToInt32(
856 m.Word64Sar(m.Parameter(0), m.Int32Constant(32))));
857 Stream s = m.Build();
858 ASSERT_EQ(1U, s.size());
859 EXPECT_EQ(kMips64Dsar, s[0]->arch_opcode());
860 EXPECT_EQ(kMode_None, s[0]->addressing_mode());
861 ASSERT_EQ(2U, s[0]->InputCount());
862 EXPECT_EQ(1U, s[0]->OutputCount());
863 }
864 {
865 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
866 m.Return(
867 m.Word64Shl(m.ChangeInt32ToInt64(m.Parameter(0)), m.Int32Constant(32)));
868 Stream s = m.Build();
869 ASSERT_EQ(1U, s.size());
870 EXPECT_EQ(kMips64Dshl, s[0]->arch_opcode());
871 ASSERT_EQ(2U, s[0]->InputCount());
872 EXPECT_EQ(1U, s[0]->OutputCount());
873 }
874}
875
876
877typedef InstructionSelectorTestWithParam<Conversion>
878 CombineChangeFloat64ToInt32WithRoundFloat64;
879
880TEST_P(CombineChangeFloat64ToInt32WithRoundFloat64, Parameter) {
881 {
882 const Conversion conv = GetParam();
883 StreamBuilder m(this, conv.mi.machine_type, conv.src_machine_type);
884 m.Return(m.ChangeFloat64ToInt32((m.*conv.mi.constructor)(m.Parameter(0))));
885 Stream s = m.Build();
886 ASSERT_EQ(1U, s.size());
887 EXPECT_EQ(conv.mi.arch_opcode, s[0]->arch_opcode());
888 EXPECT_EQ(kMode_None, s[0]->addressing_mode());
889 ASSERT_EQ(1U, s[0]->InputCount());
890 EXPECT_EQ(1U, s[0]->OutputCount());
891 }
892}
893
894INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
895 CombineChangeFloat64ToInt32WithRoundFloat64,
896 ::testing::ValuesIn(kFloat64RoundInstructions));
897
898typedef InstructionSelectorTestWithParam<Conversion>
899 CombineChangeFloat32ToInt32WithRoundFloat32;
900
901TEST_P(CombineChangeFloat32ToInt32WithRoundFloat32, Parameter) {
902 {
903 const Conversion conv = GetParam();
904 StreamBuilder m(this, conv.mi.machine_type, conv.src_machine_type);
905 m.Return(m.ChangeFloat64ToInt32(
906 m.ChangeFloat32ToFloat64((m.*conv.mi.constructor)(m.Parameter(0)))));
907 Stream s = m.Build();
908 ASSERT_EQ(1U, s.size());
909 EXPECT_EQ(conv.mi.arch_opcode, s[0]->arch_opcode());
910 EXPECT_EQ(kMode_None, s[0]->addressing_mode());
911 ASSERT_EQ(1U, s[0]->InputCount());
912 EXPECT_EQ(1U, s[0]->OutputCount());
913 }
914}
915
916INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
917 CombineChangeFloat32ToInt32WithRoundFloat32,
918 ::testing::ValuesIn(kFloat32RoundInstructions));
919
920
921TEST_F(InstructionSelectorTest, ChangeFloat64ToInt32OfChangeFloat32ToFloat64) {
922 {
923 StreamBuilder m(this, MachineType::Int32(), MachineType::Float32());
924 m.Return(m.ChangeFloat64ToInt32(m.ChangeFloat32ToFloat64(m.Parameter(0))));
925 Stream s = m.Build();
926 ASSERT_EQ(1U, s.size());
927 EXPECT_EQ(kMips64TruncWS, s[0]->arch_opcode());
928 EXPECT_EQ(kMode_None, s[0]->addressing_mode());
929 ASSERT_EQ(1U, s[0]->InputCount());
930 EXPECT_EQ(1U, s[0]->OutputCount());
931 }
932}
933
934
935TEST_F(InstructionSelectorTest,
936 TruncateFloat64ToFloat32OfChangeInt32ToFloat64) {
937 {
938 StreamBuilder m(this, MachineType::Float32(), MachineType::Int32());
939 m.Return(
940 m.TruncateFloat64ToFloat32(m.ChangeInt32ToFloat64(m.Parameter(0))));
941 Stream s = m.Build();
942 ASSERT_EQ(1U, s.size());
943 EXPECT_EQ(kMips64CvtSW, s[0]->arch_opcode());
944 EXPECT_EQ(kMode_None, s[0]->addressing_mode());
945 ASSERT_EQ(1U, s[0]->InputCount());
946 EXPECT_EQ(1U, s[0]->OutputCount());
947 }
948}
949
950
951TEST_F(InstructionSelectorTest, CombineShiftsWithMul) {
952 {
953 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
954 m.Return(m.Int32Mul(m.Word64Sar(m.Parameter(0), m.Int32Constant(32)),
955 m.Word64Sar(m.Parameter(0), m.Int32Constant(32))));
956 Stream s = m.Build();
957 ASSERT_EQ(1U, s.size());
958 EXPECT_EQ(kMips64DMulHigh, s[0]->arch_opcode());
959 EXPECT_EQ(kMode_None, s[0]->addressing_mode());
960 ASSERT_EQ(2U, s[0]->InputCount());
961 EXPECT_EQ(1U, s[0]->OutputCount());
962 }
963}
964
965
966TEST_F(InstructionSelectorTest, CombineShiftsWithDivMod) {
967 {
968 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
969 m.Return(m.Int32Div(m.Word64Sar(m.Parameter(0), m.Int32Constant(32)),
970 m.Word64Sar(m.Parameter(0), m.Int32Constant(32))));
971 Stream s = m.Build();
972 ASSERT_EQ(1U, s.size());
973 EXPECT_EQ(kMips64Ddiv, s[0]->arch_opcode());
974 EXPECT_EQ(kMode_None, s[0]->addressing_mode());
975 ASSERT_EQ(2U, s[0]->InputCount());
976 EXPECT_EQ(1U, s[0]->OutputCount());
977 }
978 {
979 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
980 m.Return(m.Int32Mod(m.Word64Sar(m.Parameter(0), m.Int32Constant(32)),
981 m.Word64Sar(m.Parameter(0), m.Int32Constant(32))));
982 Stream s = m.Build();
983 ASSERT_EQ(1U, s.size());
984 EXPECT_EQ(kMips64Dmod, s[0]->arch_opcode());
985 EXPECT_EQ(kMode_None, s[0]->addressing_mode());
986 ASSERT_EQ(2U, s[0]->InputCount());
987 EXPECT_EQ(1U, s[0]->OutputCount());
988 }
989}
990
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400991
992// ----------------------------------------------------------------------------
993// Loads and stores.
994// ----------------------------------------------------------------------------
995
996
997namespace {
998
999struct MemoryAccess {
1000 MachineType type;
1001 ArchOpcode load_opcode;
1002 ArchOpcode store_opcode;
1003};
1004
1005static const MemoryAccess kMemoryAccesses[] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001006 {MachineType::Int8(), kMips64Lb, kMips64Sb},
1007 {MachineType::Uint8(), kMips64Lbu, kMips64Sb},
1008 {MachineType::Int16(), kMips64Lh, kMips64Sh},
1009 {MachineType::Uint16(), kMips64Lhu, kMips64Sh},
1010 {MachineType::Int32(), kMips64Lw, kMips64Sw},
1011 {MachineType::Float32(), kMips64Lwc1, kMips64Swc1},
1012 {MachineType::Float64(), kMips64Ldc1, kMips64Sdc1},
1013 {MachineType::Int64(), kMips64Ld, kMips64Sd}};
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001014
1015
1016struct MemoryAccessImm {
1017 MachineType type;
1018 ArchOpcode load_opcode;
1019 ArchOpcode store_opcode;
1020 bool (InstructionSelectorTest::Stream::*val_predicate)(
1021 const InstructionOperand*) const;
1022 const int32_t immediates[40];
1023};
1024
1025
1026std::ostream& operator<<(std::ostream& os, const MemoryAccessImm& acc) {
1027 return os << acc.type;
1028}
1029
1030
1031struct MemoryAccessImm1 {
1032 MachineType type;
1033 ArchOpcode load_opcode;
1034 ArchOpcode store_opcode;
1035 bool (InstructionSelectorTest::Stream::*val_predicate)(
1036 const InstructionOperand*) const;
1037 const int32_t immediates[5];
1038};
1039
1040
1041std::ostream& operator<<(std::ostream& os, const MemoryAccessImm1& acc) {
1042 return os << acc.type;
1043}
1044
1045
1046// ----------------------------------------------------------------------------
1047// Loads and stores immediate values
1048// ----------------------------------------------------------------------------
1049
1050
1051const MemoryAccessImm kMemoryAccessesImm[] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001052 {MachineType::Int8(),
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001053 kMips64Lb,
1054 kMips64Sb,
1055 &InstructionSelectorTest::Stream::IsInteger,
1056 {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89,
1057 -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109,
1058 115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001059 {MachineType::Uint8(),
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001060 kMips64Lbu,
1061 kMips64Sb,
1062 &InstructionSelectorTest::Stream::IsInteger,
1063 {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89,
1064 -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109,
1065 115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001066 {MachineType::Int16(),
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001067 kMips64Lh,
1068 kMips64Sh,
1069 &InstructionSelectorTest::Stream::IsInteger,
1070 {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89,
1071 -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109,
1072 115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001073 {MachineType::Uint16(),
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001074 kMips64Lhu,
1075 kMips64Sh,
1076 &InstructionSelectorTest::Stream::IsInteger,
1077 {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89,
1078 -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109,
1079 115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001080 {MachineType::Int32(),
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001081 kMips64Lw,
1082 kMips64Sw,
1083 &InstructionSelectorTest::Stream::IsInteger,
1084 {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89,
1085 -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109,
1086 115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001087 {MachineType::Float32(),
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001088 kMips64Lwc1,
1089 kMips64Swc1,
1090 &InstructionSelectorTest::Stream::IsDouble,
1091 {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89,
1092 -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109,
1093 115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001094 {MachineType::Float64(),
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001095 kMips64Ldc1,
1096 kMips64Sdc1,
1097 &InstructionSelectorTest::Stream::IsDouble,
1098 {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89,
1099 -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109,
1100 115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001101 {MachineType::Int64(),
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001102 kMips64Ld,
1103 kMips64Sd,
1104 &InstructionSelectorTest::Stream::IsInteger,
1105 {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89,
1106 -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109,
1107 115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}}};
1108
1109
1110const MemoryAccessImm1 kMemoryAccessImmMoreThan16bit[] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001111 {MachineType::Int8(),
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001112 kMips64Lb,
1113 kMips64Sb,
1114 &InstructionSelectorTest::Stream::IsInteger,
1115 {-65000, -55000, 32777, 55000, 65000}},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001116 {MachineType::Int8(),
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001117 kMips64Lbu,
1118 kMips64Sb,
1119 &InstructionSelectorTest::Stream::IsInteger,
1120 {-65000, -55000, 32777, 55000, 65000}},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001121 {MachineType::Int16(),
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001122 kMips64Lh,
1123 kMips64Sh,
1124 &InstructionSelectorTest::Stream::IsInteger,
1125 {-65000, -55000, 32777, 55000, 65000}},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001126 {MachineType::Int16(),
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001127 kMips64Lhu,
1128 kMips64Sh,
1129 &InstructionSelectorTest::Stream::IsInteger,
1130 {-65000, -55000, 32777, 55000, 65000}},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001131 {MachineType::Int32(),
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001132 kMips64Lw,
1133 kMips64Sw,
1134 &InstructionSelectorTest::Stream::IsInteger,
1135 {-65000, -55000, 32777, 55000, 65000}},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001136 {MachineType::Float32(),
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001137 kMips64Lwc1,
1138 kMips64Swc1,
1139 &InstructionSelectorTest::Stream::IsDouble,
1140 {-65000, -55000, 32777, 55000, 65000}},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001141 {MachineType::Float64(),
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001142 kMips64Ldc1,
1143 kMips64Sdc1,
1144 &InstructionSelectorTest::Stream::IsDouble,
1145 {-65000, -55000, 32777, 55000, 65000}},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001146 {MachineType::Int64(),
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001147 kMips64Ld,
1148 kMips64Sd,
1149 &InstructionSelectorTest::Stream::IsInteger,
1150 {-65000, -55000, 32777, 55000, 65000}}};
1151
1152} // namespace
1153
1154
1155typedef InstructionSelectorTestWithParam<MemoryAccess>
1156 InstructionSelectorMemoryAccessTest;
1157
1158TEST_P(InstructionSelectorMemoryAccessTest, LoadWithParameters) {
1159 const MemoryAccess memacc = GetParam();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001160 StreamBuilder m(this, memacc.type, MachineType::Pointer(),
1161 MachineType::Int32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001162 m.Return(m.Load(memacc.type, m.Parameter(0)));
1163 Stream s = m.Build();
1164 ASSERT_EQ(1U, s.size());
1165 EXPECT_EQ(memacc.load_opcode, s[0]->arch_opcode());
1166 EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
1167}
1168
1169
1170TEST_P(InstructionSelectorMemoryAccessTest, StoreWithParameters) {
1171 const MemoryAccess memacc = GetParam();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001172 StreamBuilder m(this, MachineType::Int32(), MachineType::Pointer(),
1173 MachineType::Int32(), memacc.type);
1174 m.Store(memacc.type.representation(), m.Parameter(0), m.Parameter(1),
1175 kNoWriteBarrier);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001176 m.Return(m.Int32Constant(0));
1177 Stream s = m.Build();
1178 ASSERT_EQ(1U, s.size());
1179 EXPECT_EQ(memacc.store_opcode, s[0]->arch_opcode());
1180 EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
1181}
1182
1183INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1184 InstructionSelectorMemoryAccessTest,
1185 ::testing::ValuesIn(kMemoryAccesses));
1186
1187
1188// ----------------------------------------------------------------------------
1189// Load immediate.
1190// ----------------------------------------------------------------------------
1191
1192
1193typedef InstructionSelectorTestWithParam<MemoryAccessImm>
1194 InstructionSelectorMemoryAccessImmTest;
1195
1196TEST_P(InstructionSelectorMemoryAccessImmTest, LoadWithImmediateIndex) {
1197 const MemoryAccessImm memacc = GetParam();
1198 TRACED_FOREACH(int32_t, index, memacc.immediates) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001199 StreamBuilder m(this, memacc.type, MachineType::Pointer());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001200 m.Return(m.Load(memacc.type, m.Parameter(0), m.Int32Constant(index)));
1201 Stream s = m.Build();
1202 ASSERT_EQ(1U, s.size());
1203 EXPECT_EQ(memacc.load_opcode, s[0]->arch_opcode());
1204 EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
1205 ASSERT_EQ(2U, s[0]->InputCount());
1206 ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
1207 EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1)));
1208 ASSERT_EQ(1U, s[0]->OutputCount());
1209 EXPECT_TRUE((s.*memacc.val_predicate)(s[0]->Output()));
1210 }
1211}
1212
1213
1214// ----------------------------------------------------------------------------
1215// Store immediate.
1216// ----------------------------------------------------------------------------
1217
1218
1219TEST_P(InstructionSelectorMemoryAccessImmTest, StoreWithImmediateIndex) {
1220 const MemoryAccessImm memacc = GetParam();
1221 TRACED_FOREACH(int32_t, index, memacc.immediates) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001222 StreamBuilder m(this, MachineType::Int32(), MachineType::Pointer(),
1223 memacc.type);
1224 m.Store(memacc.type.representation(), m.Parameter(0),
1225 m.Int32Constant(index), m.Parameter(1), kNoWriteBarrier);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001226 m.Return(m.Int32Constant(0));
1227 Stream s = m.Build();
1228 ASSERT_EQ(1U, s.size());
1229 EXPECT_EQ(memacc.store_opcode, s[0]->arch_opcode());
1230 EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
1231 ASSERT_EQ(3U, s[0]->InputCount());
1232 ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
1233 EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1)));
1234 EXPECT_EQ(0U, s[0]->OutputCount());
1235 }
1236}
1237
1238INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1239 InstructionSelectorMemoryAccessImmTest,
1240 ::testing::ValuesIn(kMemoryAccessesImm));
1241
1242
1243// ----------------------------------------------------------------------------
1244// Load/store offsets more than 16 bits.
1245// ----------------------------------------------------------------------------
1246
1247
1248typedef InstructionSelectorTestWithParam<MemoryAccessImm1>
1249 InstructionSelectorMemoryAccessImmMoreThan16bitTest;
1250
1251TEST_P(InstructionSelectorMemoryAccessImmMoreThan16bitTest,
1252 LoadWithImmediateIndex) {
1253 const MemoryAccessImm1 memacc = GetParam();
1254 TRACED_FOREACH(int32_t, index, memacc.immediates) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001255 StreamBuilder m(this, memacc.type, MachineType::Pointer());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001256 m.Return(m.Load(memacc.type, m.Parameter(0), m.Int32Constant(index)));
1257 Stream s = m.Build();
1258 ASSERT_EQ(2U, s.size());
1259 // kMips64Dadd is expected opcode
1260 // size more than 16 bits wide
1261 EXPECT_EQ(kMips64Dadd, s[0]->arch_opcode());
1262 EXPECT_EQ(kMode_None, s[0]->addressing_mode());
1263 EXPECT_EQ(2U, s[0]->InputCount());
1264 EXPECT_EQ(1U, s[0]->OutputCount());
1265 }
1266}
1267
1268TEST_P(InstructionSelectorMemoryAccessImmMoreThan16bitTest,
1269 StoreWithImmediateIndex) {
1270 const MemoryAccessImm1 memacc = GetParam();
1271 TRACED_FOREACH(int32_t, index, memacc.immediates) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001272 StreamBuilder m(this, MachineType::Int32(), MachineType::Pointer(),
1273 memacc.type);
1274 m.Store(memacc.type.representation(), m.Parameter(0),
1275 m.Int32Constant(index), m.Parameter(1), kNoWriteBarrier);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001276 m.Return(m.Int32Constant(0));
1277 Stream s = m.Build();
1278 ASSERT_EQ(2U, s.size());
1279 // kMips64Add is expected opcode
1280 // size more than 16 bits wide
1281 EXPECT_EQ(kMips64Dadd, s[0]->arch_opcode());
1282 EXPECT_EQ(kMode_None, s[0]->addressing_mode());
1283 EXPECT_EQ(2U, s[0]->InputCount());
1284 EXPECT_EQ(1U, s[0]->OutputCount());
1285 }
1286}
1287
1288INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1289 InstructionSelectorMemoryAccessImmMoreThan16bitTest,
1290 ::testing::ValuesIn(kMemoryAccessImmMoreThan16bit));
1291
1292
1293// ----------------------------------------------------------------------------
1294// kMips64Cmp with zero testing.
1295// ----------------------------------------------------------------------------
1296
1297
1298TEST_F(InstructionSelectorTest, Word32EqualWithZero) {
1299 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001300 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001301 m.Return(m.Word32Equal(m.Parameter(0), m.Int32Constant(0)));
1302 Stream s = m.Build();
1303 ASSERT_EQ(1U, s.size());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001304 EXPECT_EQ(kMips64Cmp, s[0]->arch_opcode());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001305 EXPECT_EQ(kMode_None, s[0]->addressing_mode());
1306 ASSERT_EQ(2U, s[0]->InputCount());
1307 EXPECT_EQ(1U, s[0]->OutputCount());
1308 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1309 EXPECT_EQ(kEqual, s[0]->flags_condition());
1310 }
1311 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001312 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001313 m.Return(m.Word32Equal(m.Int32Constant(0), m.Parameter(0)));
1314 Stream s = m.Build();
1315 ASSERT_EQ(1U, s.size());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001316 EXPECT_EQ(kMips64Cmp, s[0]->arch_opcode());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001317 EXPECT_EQ(kMode_None, s[0]->addressing_mode());
1318 ASSERT_EQ(2U, s[0]->InputCount());
1319 EXPECT_EQ(1U, s[0]->OutputCount());
1320 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1321 EXPECT_EQ(kEqual, s[0]->flags_condition());
1322 }
1323}
1324
1325
1326TEST_F(InstructionSelectorTest, Word64EqualWithZero) {
1327 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001328 StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001329 m.Return(m.Word64Equal(m.Parameter(0), m.Int64Constant(0)));
1330 Stream s = m.Build();
1331 ASSERT_EQ(1U, s.size());
1332 EXPECT_EQ(kMips64Cmp, s[0]->arch_opcode());
1333 EXPECT_EQ(kMode_None, s[0]->addressing_mode());
1334 ASSERT_EQ(2U, s[0]->InputCount());
1335 EXPECT_EQ(1U, s[0]->OutputCount());
1336 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1337 EXPECT_EQ(kEqual, s[0]->flags_condition());
1338 }
1339 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001340 StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001341 m.Return(m.Word64Equal(m.Int32Constant(0), m.Parameter(0)));
1342 Stream s = m.Build();
1343 ASSERT_EQ(1U, s.size());
1344 EXPECT_EQ(kMips64Cmp, s[0]->arch_opcode());
1345 EXPECT_EQ(kMode_None, s[0]->addressing_mode());
1346 ASSERT_EQ(2U, s[0]->InputCount());
1347 EXPECT_EQ(1U, s[0]->OutputCount());
1348 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1349 EXPECT_EQ(kEqual, s[0]->flags_condition());
1350 }
1351}
1352
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001353
1354TEST_F(InstructionSelectorTest, Word32Clz) {
1355 StreamBuilder m(this, MachineType::Uint32(), MachineType::Uint32());
1356 Node* const p0 = m.Parameter(0);
1357 Node* const n = m.Word32Clz(p0);
1358 m.Return(n);
1359 Stream s = m.Build();
1360 ASSERT_EQ(1U, s.size());
1361 EXPECT_EQ(kMips64Clz, s[0]->arch_opcode());
1362 ASSERT_EQ(1U, s[0]->InputCount());
1363 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1364 ASSERT_EQ(1U, s[0]->OutputCount());
1365 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1366}
1367
1368
1369TEST_F(InstructionSelectorTest, Word64Clz) {
1370 StreamBuilder m(this, MachineType::Uint64(), MachineType::Uint64());
1371 Node* const p0 = m.Parameter(0);
1372 Node* const n = m.Word64Clz(p0);
1373 m.Return(n);
1374 Stream s = m.Build();
1375 ASSERT_EQ(1U, s.size());
1376 EXPECT_EQ(kMips64Dclz, s[0]->arch_opcode());
1377 ASSERT_EQ(1U, s[0]->InputCount());
1378 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1379 ASSERT_EQ(1U, s[0]->OutputCount());
1380 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1381}
1382
1383
1384TEST_F(InstructionSelectorTest, Float32Abs) {
1385 StreamBuilder m(this, MachineType::Float32(), MachineType::Float32());
1386 Node* const p0 = m.Parameter(0);
1387 Node* const n = m.Float32Abs(p0);
1388 m.Return(n);
1389 Stream s = m.Build();
1390 ASSERT_EQ(1U, s.size());
1391 EXPECT_EQ(kMips64AbsS, s[0]->arch_opcode());
1392 ASSERT_EQ(1U, s[0]->InputCount());
1393 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1394 ASSERT_EQ(1U, s[0]->OutputCount());
1395 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1396}
1397
1398
1399TEST_F(InstructionSelectorTest, Float64Abs) {
1400 StreamBuilder m(this, MachineType::Float64(), MachineType::Float64());
1401 Node* const p0 = m.Parameter(0);
1402 Node* const n = m.Float64Abs(p0);
1403 m.Return(n);
1404 Stream s = m.Build();
1405 ASSERT_EQ(1U, s.size());
1406 EXPECT_EQ(kMips64AbsD, s[0]->arch_opcode());
1407 ASSERT_EQ(1U, s[0]->InputCount());
1408 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1409 ASSERT_EQ(1U, s[0]->OutputCount());
1410 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1411}
1412
1413
1414TEST_F(InstructionSelectorTest, Float32Max) {
1415 StreamBuilder m(this, MachineType::Float32(), MachineType::Float32(),
1416 MachineType::Float32());
1417 Node* const p0 = m.Parameter(0);
1418 Node* const p1 = m.Parameter(1);
1419 Node* const n = m.Float32Max(p0, p1);
1420 m.Return(n);
1421 Stream s = m.Build();
1422 // Float32Max is `(b < a) ? a : b`.
1423 ASSERT_EQ(1U, s.size());
1424 EXPECT_EQ(kMips64Float32Max, s[0]->arch_opcode());
1425 ASSERT_EQ(2U, s[0]->InputCount());
1426 ASSERT_EQ(1U, s[0]->OutputCount());
1427 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1428}
1429
1430
1431TEST_F(InstructionSelectorTest, Float32Min) {
1432 StreamBuilder m(this, MachineType::Float32(), MachineType::Float32(),
1433 MachineType::Float32());
1434 Node* const p0 = m.Parameter(0);
1435 Node* const p1 = m.Parameter(1);
1436 Node* const n = m.Float32Min(p0, p1);
1437 m.Return(n);
1438 Stream s = m.Build();
1439 // Float32Min is `(a < b) ? a : b`.
1440 ASSERT_EQ(1U, s.size());
1441 EXPECT_EQ(kMips64Float32Min, s[0]->arch_opcode());
1442 ASSERT_EQ(2U, s[0]->InputCount());
1443 ASSERT_EQ(1U, s[0]->OutputCount());
1444 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1445}
1446
1447
1448TEST_F(InstructionSelectorTest, Float64Max) {
1449 StreamBuilder m(this, MachineType::Float64(), MachineType::Float64(),
1450 MachineType::Float64());
1451 Node* const p0 = m.Parameter(0);
1452 Node* const p1 = m.Parameter(1);
1453 Node* const n = m.Float64Max(p0, p1);
1454 m.Return(n);
1455 Stream s = m.Build();
1456 // Float64Max is `(b < a) ? a : b`.
1457 ASSERT_EQ(1U, s.size());
1458 EXPECT_EQ(kMips64Float64Max, s[0]->arch_opcode());
1459 ASSERT_EQ(2U, s[0]->InputCount());
1460 ASSERT_EQ(1U, s[0]->OutputCount());
1461 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1462}
1463
1464
1465TEST_F(InstructionSelectorTest, Float64Min) {
1466 StreamBuilder m(this, MachineType::Float64(), MachineType::Float64(),
1467 MachineType::Float64());
1468 Node* const p0 = m.Parameter(0);
1469 Node* const p1 = m.Parameter(1);
1470 Node* const n = m.Float64Min(p0, p1);
1471 m.Return(n);
1472 Stream s = m.Build();
1473 // Float64Min is `(a < b) ? a : b`.
1474 ASSERT_EQ(1U, s.size());
1475 EXPECT_EQ(kMips64Float64Min, s[0]->arch_opcode());
1476 ASSERT_EQ(2U, s[0]->InputCount());
1477 ASSERT_EQ(1U, s[0]->OutputCount());
1478 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1479}
1480
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001481} // namespace compiler
1482} // namespace internal
1483} // namespace v8