Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(217)

Side by Side Diff: src/compiler/arm64/instruction-selector-arm64-unittest.cc

Issue 615393002: Move unit tests to test/unittests. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: REBASE Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <list>
6
7 #include "src/compiler/instruction-selector-unittest.h"
8
9 namespace v8 {
10 namespace internal {
11 namespace compiler {
12
13 namespace {
14
15 typedef RawMachineAssembler::Label MLabel;
16
17 template <typename T>
18 struct MachInst {
19 T constructor;
20 const char* constructor_name;
21 ArchOpcode arch_opcode;
22 MachineType machine_type;
23 };
24
25 typedef MachInst<Node* (RawMachineAssembler::*)(Node*)> MachInst1;
26 typedef MachInst<Node* (RawMachineAssembler::*)(Node*, Node*)> MachInst2;
27
28
29 template <typename T>
30 std::ostream& operator<<(std::ostream& os, const MachInst<T>& mi) {
31 return os << mi.constructor_name;
32 }
33
34
35 // Helper to build Int32Constant or Int64Constant depending on the given
36 // machine type.
37 Node* BuildConstant(InstructionSelectorTest::StreamBuilder& m, MachineType type,
38 int64_t value) {
39 switch (type) {
40 case kMachInt32:
41 return m.Int32Constant(value);
42 break;
43
44 case kMachInt64:
45 return m.Int64Constant(value);
46 break;
47
48 default:
49 UNIMPLEMENTED();
50 }
51 return NULL;
52 }
53
54
55 // ARM64 logical instructions.
56 static const MachInst2 kLogicalInstructions[] = {
57 {&RawMachineAssembler::Word32And, "Word32And", kArm64And32, kMachInt32},
58 {&RawMachineAssembler::Word64And, "Word64And", kArm64And, kMachInt64},
59 {&RawMachineAssembler::Word32Or, "Word32Or", kArm64Or32, kMachInt32},
60 {&RawMachineAssembler::Word64Or, "Word64Or", kArm64Or, kMachInt64},
61 {&RawMachineAssembler::Word32Xor, "Word32Xor", kArm64Eor32, kMachInt32},
62 {&RawMachineAssembler::Word64Xor, "Word64Xor", kArm64Eor, kMachInt64}};
63
64
65 // ARM64 logical immediates: contiguous set bits, rotated about a power of two
66 // sized block. The block is then duplicated across the word. Below is a random
67 // subset of the 32-bit immediates.
68 static const uint32_t kLogicalImmediates[] = {
69 0x00000002, 0x00000003, 0x00000070, 0x00000080, 0x00000100, 0x000001c0,
70 0x00000300, 0x000007e0, 0x00003ffc, 0x00007fc0, 0x0003c000, 0x0003f000,
71 0x0003ffc0, 0x0003fff8, 0x0007ff00, 0x0007ffe0, 0x000e0000, 0x001e0000,
72 0x001ffffc, 0x003f0000, 0x003f8000, 0x00780000, 0x007fc000, 0x00ff0000,
73 0x01800000, 0x01800180, 0x01f801f8, 0x03fe0000, 0x03ffffc0, 0x03fffffc,
74 0x06000000, 0x07fc0000, 0x07ffc000, 0x07ffffc0, 0x07ffffe0, 0x0ffe0ffe,
75 0x0ffff800, 0x0ffffff0, 0x0fffffff, 0x18001800, 0x1f001f00, 0x1f801f80,
76 0x30303030, 0x3ff03ff0, 0x3ff83ff8, 0x3fff0000, 0x3fff8000, 0x3fffffc0,
77 0x70007000, 0x7f7f7f7f, 0x7fc00000, 0x7fffffc0, 0x8000001f, 0x800001ff,
78 0x81818181, 0x9fff9fff, 0xc00007ff, 0xc0ffffff, 0xdddddddd, 0xe00001ff,
79 0xe00003ff, 0xe007ffff, 0xefffefff, 0xf000003f, 0xf001f001, 0xf3fff3ff,
80 0xf800001f, 0xf80fffff, 0xf87ff87f, 0xfbfbfbfb, 0xfc00001f, 0xfc0000ff,
81 0xfc0001ff, 0xfc03fc03, 0xfe0001ff, 0xff000001, 0xff03ff03, 0xff800000,
82 0xff800fff, 0xff801fff, 0xff87ffff, 0xffc0003f, 0xffc007ff, 0xffcfffcf,
83 0xffe00003, 0xffe1ffff, 0xfff0001f, 0xfff07fff, 0xfff80007, 0xfff87fff,
84 0xfffc00ff, 0xfffe07ff, 0xffff00ff, 0xffffc001, 0xfffff007, 0xfffff3ff,
85 0xfffff807, 0xfffff9ff, 0xfffffc0f, 0xfffffeff};
86
87
88 // ARM64 arithmetic instructions.
89 static const MachInst2 kAddSubInstructions[] = {
90 {&RawMachineAssembler::Int32Add, "Int32Add", kArm64Add32, kMachInt32},
91 {&RawMachineAssembler::Int64Add, "Int64Add", kArm64Add, kMachInt64},
92 {&RawMachineAssembler::Int32Sub, "Int32Sub", kArm64Sub32, kMachInt32},
93 {&RawMachineAssembler::Int64Sub, "Int64Sub", kArm64Sub, kMachInt64}};
94
95
96 // ARM64 Add/Sub immediates: 12-bit immediate optionally shifted by 12.
97 // Below is a combination of a random subset and some edge values.
98 static const int32_t kAddSubImmediates[] = {
99 0, 1, 69, 493, 599, 701, 719,
100 768, 818, 842, 945, 1246, 1286, 1429,
101 1669, 2171, 2179, 2182, 2254, 2334, 2338,
102 2343, 2396, 2449, 2610, 2732, 2855, 2876,
103 2944, 3377, 3458, 3475, 3476, 3540, 3574,
104 3601, 3813, 3871, 3917, 4095, 4096, 16384,
105 364544, 462848, 970752, 1523712, 1863680, 2363392, 3219456,
106 3280896, 4247552, 4526080, 4575232, 4960256, 5505024, 5894144,
107 6004736, 6193152, 6385664, 6795264, 7114752, 7233536, 7348224,
108 7499776, 7573504, 7729152, 8634368, 8937472, 9465856, 10354688,
109 10682368, 11059200, 11460608, 13168640, 13176832, 14336000, 15028224,
110 15597568, 15892480, 16773120};
111
112
113 // ARM64 flag setting data processing instructions.
114 static const MachInst2 kDPFlagSetInstructions[] = {
115 {&RawMachineAssembler::Word32And, "Word32And", kArm64Tst32, kMachInt32},
116 {&RawMachineAssembler::Int32Add, "Int32Add", kArm64Cmn32, kMachInt32},
117 {&RawMachineAssembler::Int32Sub, "Int32Sub", kArm64Cmp32, kMachInt32}};
118
119
120 // ARM64 arithmetic with overflow instructions.
121 static const MachInst2 kOvfAddSubInstructions[] = {
122 {&RawMachineAssembler::Int32AddWithOverflow, "Int32AddWithOverflow",
123 kArm64Add32, kMachInt32},
124 {&RawMachineAssembler::Int32SubWithOverflow, "Int32SubWithOverflow",
125 kArm64Sub32, kMachInt32}};
126
127
128 // ARM64 shift instructions.
129 static const MachInst2 kShiftInstructions[] = {
130 {&RawMachineAssembler::Word32Shl, "Word32Shl", kArm64Shl32, kMachInt32},
131 {&RawMachineAssembler::Word64Shl, "Word64Shl", kArm64Shl, kMachInt64},
132 {&RawMachineAssembler::Word32Shr, "Word32Shr", kArm64Shr32, kMachInt32},
133 {&RawMachineAssembler::Word64Shr, "Word64Shr", kArm64Shr, kMachInt64},
134 {&RawMachineAssembler::Word32Sar, "Word32Sar", kArm64Sar32, kMachInt32},
135 {&RawMachineAssembler::Word64Sar, "Word64Sar", kArm64Sar, kMachInt64},
136 {&RawMachineAssembler::Word32Ror, "Word32Ror", kArm64Ror32, kMachInt32},
137 {&RawMachineAssembler::Word64Ror, "Word64Ror", kArm64Ror, kMachInt64}};
138
139
140 // ARM64 Mul/Div instructions.
141 static const MachInst2 kMulDivInstructions[] = {
142 {&RawMachineAssembler::Int32Mul, "Int32Mul", kArm64Mul32, kMachInt32},
143 {&RawMachineAssembler::Int64Mul, "Int64Mul", kArm64Mul, kMachInt64},
144 {&RawMachineAssembler::Int32Div, "Int32Div", kArm64Idiv32, kMachInt32},
145 {&RawMachineAssembler::Int64Div, "Int64Div", kArm64Idiv, kMachInt64},
146 {&RawMachineAssembler::Int32UDiv, "Int32UDiv", kArm64Udiv32, kMachInt32},
147 {&RawMachineAssembler::Int64UDiv, "Int64UDiv", kArm64Udiv, kMachInt64}};
148
149
150 // ARM64 FP arithmetic instructions.
151 static const MachInst2 kFPArithInstructions[] = {
152 {&RawMachineAssembler::Float64Add, "Float64Add", kArm64Float64Add,
153 kMachFloat64},
154 {&RawMachineAssembler::Float64Sub, "Float64Sub", kArm64Float64Sub,
155 kMachFloat64},
156 {&RawMachineAssembler::Float64Mul, "Float64Mul", kArm64Float64Mul,
157 kMachFloat64},
158 {&RawMachineAssembler::Float64Div, "Float64Div", kArm64Float64Div,
159 kMachFloat64}};
160
161
162 struct FPCmp {
163 MachInst2 mi;
164 FlagsCondition cond;
165 };
166
167
168 std::ostream& operator<<(std::ostream& os, const FPCmp& cmp) {
169 return os << cmp.mi;
170 }
171
172
173 // ARM64 FP comparison instructions.
174 static const FPCmp kFPCmpInstructions[] = {
175 {{&RawMachineAssembler::Float64Equal, "Float64Equal", kArm64Float64Cmp,
176 kMachFloat64},
177 kUnorderedEqual},
178 {{&RawMachineAssembler::Float64LessThan, "Float64LessThan",
179 kArm64Float64Cmp, kMachFloat64},
180 kUnorderedLessThan},
181 {{&RawMachineAssembler::Float64LessThanOrEqual, "Float64LessThanOrEqual",
182 kArm64Float64Cmp, kMachFloat64},
183 kUnorderedLessThanOrEqual}};
184
185
186 struct Conversion {
187 // The machine_type field in MachInst1 represents the destination type.
188 MachInst1 mi;
189 MachineType src_machine_type;
190 };
191
192
193 std::ostream& operator<<(std::ostream& os, const Conversion& conv) {
194 return os << conv.mi;
195 }
196
197
198 // ARM64 type conversion instructions.
199 static const Conversion kConversionInstructions[] = {
200 {{&RawMachineAssembler::ChangeFloat32ToFloat64, "ChangeFloat32ToFloat64",
201 kArm64Float32ToFloat64, kMachFloat64},
202 kMachFloat32},
203 {{&RawMachineAssembler::TruncateFloat64ToFloat32,
204 "TruncateFloat64ToFloat32", kArm64Float64ToFloat32, kMachFloat32},
205 kMachFloat64},
206 {{&RawMachineAssembler::ChangeInt32ToInt64, "ChangeInt32ToInt64",
207 kArm64Sxtw, kMachInt64},
208 kMachInt32},
209 {{&RawMachineAssembler::ChangeUint32ToUint64, "ChangeUint32ToUint64",
210 kArm64Mov32, kMachUint64},
211 kMachUint32},
212 {{&RawMachineAssembler::TruncateInt64ToInt32, "TruncateInt64ToInt32",
213 kArm64Mov32, kMachInt32},
214 kMachInt64},
215 {{&RawMachineAssembler::ChangeInt32ToFloat64, "ChangeInt32ToFloat64",
216 kArm64Int32ToFloat64, kMachFloat64},
217 kMachInt32},
218 {{&RawMachineAssembler::ChangeUint32ToFloat64, "ChangeUint32ToFloat64",
219 kArm64Uint32ToFloat64, kMachFloat64},
220 kMachUint32},
221 {{&RawMachineAssembler::ChangeFloat64ToInt32, "ChangeFloat64ToInt32",
222 kArm64Float64ToInt32, kMachInt32},
223 kMachFloat64},
224 {{&RawMachineAssembler::ChangeFloat64ToUint32, "ChangeFloat64ToUint32",
225 kArm64Float64ToUint32, kMachUint32},
226 kMachFloat64}};
227
228 } // namespace
229
230
231 // -----------------------------------------------------------------------------
232 // Logical instructions.
233
234
235 typedef InstructionSelectorTestWithParam<MachInst2>
236 InstructionSelectorLogicalTest;
237
238
239 TEST_P(InstructionSelectorLogicalTest, Parameter) {
240 const MachInst2 dpi = GetParam();
241 const MachineType type = dpi.machine_type;
242 StreamBuilder m(this, type, type, type);
243 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)));
244 Stream s = m.Build();
245 ASSERT_EQ(1U, s.size());
246 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
247 EXPECT_EQ(2U, s[0]->InputCount());
248 EXPECT_EQ(1U, s[0]->OutputCount());
249 }
250
251
252 TEST_P(InstructionSelectorLogicalTest, Immediate) {
253 const MachInst2 dpi = GetParam();
254 const MachineType type = dpi.machine_type;
255 // TODO(all): Add support for testing 64-bit immediates.
256 if (type == kMachInt32) {
257 // Immediate on the right.
258 TRACED_FOREACH(int32_t, imm, kLogicalImmediates) {
259 StreamBuilder m(this, type, type);
260 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm)));
261 Stream s = m.Build();
262 ASSERT_EQ(1U, s.size());
263 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
264 ASSERT_EQ(2U, s[0]->InputCount());
265 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
266 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
267 EXPECT_EQ(1U, s[0]->OutputCount());
268 }
269
270 // Immediate on the left; all logical ops should commute.
271 TRACED_FOREACH(int32_t, imm, kLogicalImmediates) {
272 StreamBuilder m(this, type, type);
273 m.Return((m.*dpi.constructor)(m.Int32Constant(imm), m.Parameter(0)));
274 Stream s = m.Build();
275 ASSERT_EQ(1U, s.size());
276 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
277 ASSERT_EQ(2U, s[0]->InputCount());
278 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
279 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
280 EXPECT_EQ(1U, s[0]->OutputCount());
281 }
282 }
283 }
284
285
286 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorLogicalTest,
287 ::testing::ValuesIn(kLogicalInstructions));
288
289
290 // -----------------------------------------------------------------------------
291 // Add and Sub instructions.
292
293 typedef InstructionSelectorTestWithParam<MachInst2>
294 InstructionSelectorAddSubTest;
295
296
297 TEST_P(InstructionSelectorAddSubTest, Parameter) {
298 const MachInst2 dpi = GetParam();
299 const MachineType type = dpi.machine_type;
300 StreamBuilder m(this, type, type, type);
301 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)));
302 Stream s = m.Build();
303 ASSERT_EQ(1U, s.size());
304 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
305 EXPECT_EQ(2U, s[0]->InputCount());
306 EXPECT_EQ(1U, s[0]->OutputCount());
307 }
308
309
310 TEST_P(InstructionSelectorAddSubTest, ImmediateOnRight) {
311 const MachInst2 dpi = GetParam();
312 const MachineType type = dpi.machine_type;
313 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
314 StreamBuilder m(this, type, type);
315 m.Return((m.*dpi.constructor)(m.Parameter(0), BuildConstant(m, type, imm)));
316 Stream s = m.Build();
317 ASSERT_EQ(1U, s.size());
318 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
319 ASSERT_EQ(2U, s[0]->InputCount());
320 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
321 EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(1)));
322 EXPECT_EQ(1U, s[0]->OutputCount());
323 }
324 }
325
326
327 TEST_P(InstructionSelectorAddSubTest, ImmediateOnLeft) {
328 const MachInst2 dpi = GetParam();
329 const MachineType type = dpi.machine_type;
330
331 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
332 StreamBuilder m(this, type, type);
333 m.Return((m.*dpi.constructor)(BuildConstant(m, type, imm), m.Parameter(0)));
334 Stream s = m.Build();
335
336 // Add can support an immediate on the left by commuting, but Sub can't
337 // commute. We test zero-on-left Sub later.
338 if (strstr(dpi.constructor_name, "Add") != NULL) {
339 ASSERT_EQ(1U, s.size());
340 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
341 ASSERT_EQ(2U, s[0]->InputCount());
342 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
343 EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(1)));
344 EXPECT_EQ(1U, s[0]->OutputCount());
345 }
346 }
347 }
348
349
350 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorAddSubTest,
351 ::testing::ValuesIn(kAddSubInstructions));
352
353
354 TEST_F(InstructionSelectorTest, SubZeroOnLeft) {
355 // Subtraction with zero on the left maps to Neg.
356 {
357 // 32-bit subtract.
358 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
359 m.Return(m.Int32Sub(m.Int32Constant(0), m.Parameter(0)));
360 Stream s = m.Build();
361
362 ASSERT_EQ(1U, s.size());
363 EXPECT_EQ(kArm64Neg32, s[0]->arch_opcode());
364 EXPECT_EQ(1U, s[0]->InputCount());
365 EXPECT_EQ(1U, s[0]->OutputCount());
366 }
367 {
368 // 64-bit subtract.
369 StreamBuilder m(this, kMachInt64, kMachInt64, kMachInt64);
370 m.Return(m.Int64Sub(m.Int64Constant(0), m.Parameter(0)));
371 Stream s = m.Build();
372
373 ASSERT_EQ(1U, s.size());
374 EXPECT_EQ(kArm64Neg, s[0]->arch_opcode());
375 EXPECT_EQ(1U, s[0]->InputCount());
376 EXPECT_EQ(1U, s[0]->OutputCount());
377 }
378 }
379
380
381 // -----------------------------------------------------------------------------
382 // Data processing controlled branches.
383
384
385 typedef InstructionSelectorTestWithParam<MachInst2>
386 InstructionSelectorDPFlagSetTest;
387
388
389 TEST_P(InstructionSelectorDPFlagSetTest, BranchWithParameters) {
390 const MachInst2 dpi = GetParam();
391 const MachineType type = dpi.machine_type;
392 StreamBuilder m(this, type, type, type);
393 MLabel a, b;
394 m.Branch((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)), &a, &b);
395 m.Bind(&a);
396 m.Return(m.Int32Constant(1));
397 m.Bind(&b);
398 m.Return(m.Int32Constant(0));
399 Stream s = m.Build();
400 ASSERT_EQ(1U, s.size());
401 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
402 EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
403 EXPECT_EQ(kNotEqual, s[0]->flags_condition());
404 }
405
406
407 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
408 InstructionSelectorDPFlagSetTest,
409 ::testing::ValuesIn(kDPFlagSetInstructions));
410
411
412 TEST_F(InstructionSelectorTest, AndBranchWithImmediateOnRight) {
413 TRACED_FOREACH(int32_t, imm, kLogicalImmediates) {
414 StreamBuilder m(this, kMachInt32, kMachInt32);
415 MLabel a, b;
416 m.Branch(m.Word32And(m.Parameter(0), m.Int32Constant(imm)), &a, &b);
417 m.Bind(&a);
418 m.Return(m.Int32Constant(1));
419 m.Bind(&b);
420 m.Return(m.Int32Constant(0));
421 Stream s = m.Build();
422 ASSERT_EQ(1U, s.size());
423 EXPECT_EQ(kArm64Tst32, s[0]->arch_opcode());
424 EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
425 EXPECT_EQ(kNotEqual, s[0]->flags_condition());
426 }
427 }
428
429
430 TEST_F(InstructionSelectorTest, AddBranchWithImmediateOnRight) {
431 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
432 StreamBuilder m(this, kMachInt32, kMachInt32);
433 MLabel a, b;
434 m.Branch(m.Int32Add(m.Parameter(0), m.Int32Constant(imm)), &a, &b);
435 m.Bind(&a);
436 m.Return(m.Int32Constant(1));
437 m.Bind(&b);
438 m.Return(m.Int32Constant(0));
439 Stream s = m.Build();
440 ASSERT_EQ(1U, s.size());
441 EXPECT_EQ(kArm64Cmn32, s[0]->arch_opcode());
442 EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
443 EXPECT_EQ(kNotEqual, s[0]->flags_condition());
444 }
445 }
446
447
448 TEST_F(InstructionSelectorTest, SubBranchWithImmediateOnRight) {
449 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
450 StreamBuilder m(this, kMachInt32, kMachInt32);
451 MLabel a, b;
452 m.Branch(m.Int32Sub(m.Parameter(0), m.Int32Constant(imm)), &a, &b);
453 m.Bind(&a);
454 m.Return(m.Int32Constant(1));
455 m.Bind(&b);
456 m.Return(m.Int32Constant(0));
457 Stream s = m.Build();
458 ASSERT_EQ(1U, s.size());
459 EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode());
460 EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
461 EXPECT_EQ(kNotEqual, s[0]->flags_condition());
462 }
463 }
464
465
466 TEST_F(InstructionSelectorTest, AndBranchWithImmediateOnLeft) {
467 TRACED_FOREACH(int32_t, imm, kLogicalImmediates) {
468 StreamBuilder m(this, kMachInt32, kMachInt32);
469 MLabel a, b;
470 m.Branch(m.Word32And(m.Int32Constant(imm), m.Parameter(0)), &a, &b);
471 m.Bind(&a);
472 m.Return(m.Int32Constant(1));
473 m.Bind(&b);
474 m.Return(m.Int32Constant(0));
475 Stream s = m.Build();
476 ASSERT_EQ(1U, s.size());
477 EXPECT_EQ(kArm64Tst32, s[0]->arch_opcode());
478 ASSERT_LE(1U, s[0]->InputCount());
479 EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
480 EXPECT_EQ(kNotEqual, s[0]->flags_condition());
481 }
482 }
483
484
485 TEST_F(InstructionSelectorTest, AddBranchWithImmediateOnLeft) {
486 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
487 StreamBuilder m(this, kMachInt32, kMachInt32);
488 MLabel a, b;
489 m.Branch(m.Int32Add(m.Int32Constant(imm), m.Parameter(0)), &a, &b);
490 m.Bind(&a);
491 m.Return(m.Int32Constant(1));
492 m.Bind(&b);
493 m.Return(m.Int32Constant(0));
494 Stream s = m.Build();
495 ASSERT_EQ(1U, s.size());
496 EXPECT_EQ(kArm64Cmn32, s[0]->arch_opcode());
497 ASSERT_LE(1U, s[0]->InputCount());
498 EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
499 EXPECT_EQ(kNotEqual, s[0]->flags_condition());
500 }
501 }
502
503
504 // -----------------------------------------------------------------------------
505 // Add and subtract instructions with overflow.
506
507
508 typedef InstructionSelectorTestWithParam<MachInst2>
509 InstructionSelectorOvfAddSubTest;
510
511
512 TEST_P(InstructionSelectorOvfAddSubTest, OvfParameter) {
513 const MachInst2 dpi = GetParam();
514 const MachineType type = dpi.machine_type;
515 StreamBuilder m(this, type, type, type);
516 m.Return(
517 m.Projection(1, (m.*dpi.constructor)(m.Parameter(0), m.Parameter(1))));
518 Stream s = m.Build();
519 ASSERT_EQ(1U, s.size());
520 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
521 EXPECT_EQ(2U, s[0]->InputCount());
522 EXPECT_LE(1U, s[0]->OutputCount());
523 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
524 EXPECT_EQ(kOverflow, s[0]->flags_condition());
525 }
526
527
528 TEST_P(InstructionSelectorOvfAddSubTest, OvfImmediateOnRight) {
529 const MachInst2 dpi = GetParam();
530 const MachineType type = dpi.machine_type;
531 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
532 StreamBuilder m(this, type, type);
533 m.Return(m.Projection(
534 1, (m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm))));
535 Stream s = m.Build();
536 ASSERT_EQ(1U, s.size());
537 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
538 ASSERT_EQ(2U, s[0]->InputCount());
539 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
540 EXPECT_LE(1U, s[0]->OutputCount());
541 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
542 EXPECT_EQ(kOverflow, s[0]->flags_condition());
543 }
544 }
545
546
547 TEST_P(InstructionSelectorOvfAddSubTest, ValParameter) {
548 const MachInst2 dpi = GetParam();
549 const MachineType type = dpi.machine_type;
550 StreamBuilder m(this, type, type, type);
551 m.Return(
552 m.Projection(0, (m.*dpi.constructor)(m.Parameter(0), m.Parameter(1))));
553 Stream s = m.Build();
554 ASSERT_EQ(1U, s.size());
555 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
556 EXPECT_EQ(2U, s[0]->InputCount());
557 EXPECT_LE(1U, s[0]->OutputCount());
558 EXPECT_EQ(kFlags_none, s[0]->flags_mode());
559 }
560
561
562 TEST_P(InstructionSelectorOvfAddSubTest, ValImmediateOnRight) {
563 const MachInst2 dpi = GetParam();
564 const MachineType type = dpi.machine_type;
565 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
566 StreamBuilder m(this, type, type);
567 m.Return(m.Projection(
568 0, (m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm))));
569 Stream s = m.Build();
570 ASSERT_EQ(1U, s.size());
571 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
572 ASSERT_EQ(2U, s[0]->InputCount());
573 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
574 EXPECT_LE(1U, s[0]->OutputCount());
575 EXPECT_EQ(kFlags_none, s[0]->flags_mode());
576 }
577 }
578
579
580 TEST_P(InstructionSelectorOvfAddSubTest, BothParameter) {
581 const MachInst2 dpi = GetParam();
582 const MachineType type = dpi.machine_type;
583 StreamBuilder m(this, type, type, type);
584 Node* n = (m.*dpi.constructor)(m.Parameter(0), m.Parameter(1));
585 m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n)));
586 Stream s = m.Build();
587 ASSERT_LE(1U, s.size());
588 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
589 EXPECT_EQ(2U, s[0]->InputCount());
590 EXPECT_EQ(2U, s[0]->OutputCount());
591 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
592 EXPECT_EQ(kOverflow, s[0]->flags_condition());
593 }
594
595
596 TEST_P(InstructionSelectorOvfAddSubTest, BothImmediateOnRight) {
597 const MachInst2 dpi = GetParam();
598 const MachineType type = dpi.machine_type;
599 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
600 StreamBuilder m(this, type, type);
601 Node* n = (m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm));
602 m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n)));
603 Stream s = m.Build();
604 ASSERT_LE(1U, s.size());
605 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
606 ASSERT_EQ(2U, s[0]->InputCount());
607 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
608 EXPECT_EQ(2U, s[0]->OutputCount());
609 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
610 EXPECT_EQ(kOverflow, s[0]->flags_condition());
611 }
612 }
613
614
615 TEST_P(InstructionSelectorOvfAddSubTest, BranchWithParameters) {
616 const MachInst2 dpi = GetParam();
617 const MachineType type = dpi.machine_type;
618 StreamBuilder m(this, type, type, type);
619 MLabel a, b;
620 Node* n = (m.*dpi.constructor)(m.Parameter(0), m.Parameter(1));
621 m.Branch(m.Projection(1, n), &a, &b);
622 m.Bind(&a);
623 m.Return(m.Int32Constant(0));
624 m.Bind(&b);
625 m.Return(m.Projection(0, n));
626 Stream s = m.Build();
627 ASSERT_EQ(1U, s.size());
628 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
629 EXPECT_EQ(4U, s[0]->InputCount());
630 EXPECT_EQ(1U, s[0]->OutputCount());
631 EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
632 EXPECT_EQ(kOverflow, s[0]->flags_condition());
633 }
634
635
636 TEST_P(InstructionSelectorOvfAddSubTest, BranchWithImmediateOnRight) {
637 const MachInst2 dpi = GetParam();
638 const MachineType type = dpi.machine_type;
639 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
640 StreamBuilder m(this, type, type);
641 MLabel a, b;
642 Node* n = (m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm));
643 m.Branch(m.Projection(1, n), &a, &b);
644 m.Bind(&a);
645 m.Return(m.Int32Constant(0));
646 m.Bind(&b);
647 m.Return(m.Projection(0, n));
648 Stream s = m.Build();
649 ASSERT_EQ(1U, s.size());
650 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
651 ASSERT_EQ(4U, s[0]->InputCount());
652 EXPECT_EQ(1U, s[0]->OutputCount());
653 EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
654 EXPECT_EQ(kOverflow, s[0]->flags_condition());
655 }
656 }
657
658
659 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
660 InstructionSelectorOvfAddSubTest,
661 ::testing::ValuesIn(kOvfAddSubInstructions));
662
663
664 TEST_F(InstructionSelectorTest, OvfFlagAddImmediateOnLeft) {
665 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
666 StreamBuilder m(this, kMachInt32, kMachInt32);
667 m.Return(m.Projection(
668 1, m.Int32AddWithOverflow(m.Int32Constant(imm), m.Parameter(0))));
669 Stream s = m.Build();
670
671 ASSERT_EQ(1U, s.size());
672 EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
673 EXPECT_EQ(2U, s[0]->InputCount());
674 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
675 EXPECT_LE(1U, s[0]->OutputCount());
676 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
677 EXPECT_EQ(kOverflow, s[0]->flags_condition());
678 }
679 }
680
681
682 TEST_F(InstructionSelectorTest, OvfValAddImmediateOnLeft) {
683 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
684 StreamBuilder m(this, kMachInt32, kMachInt32);
685 m.Return(m.Projection(
686 0, m.Int32AddWithOverflow(m.Int32Constant(imm), m.Parameter(0))));
687 Stream s = m.Build();
688
689 ASSERT_EQ(1U, s.size());
690 EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
691 ASSERT_EQ(2U, s[0]->InputCount());
692 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
693 EXPECT_LE(1U, s[0]->OutputCount());
694 EXPECT_EQ(kFlags_none, s[0]->flags_mode());
695 }
696 }
697
698
699 TEST_F(InstructionSelectorTest, OvfBothAddImmediateOnLeft) {
700 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
701 StreamBuilder m(this, kMachInt32, kMachInt32);
702 Node* n = m.Int32AddWithOverflow(m.Int32Constant(imm), m.Parameter(0));
703 m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n)));
704 Stream s = m.Build();
705
706 ASSERT_LE(1U, s.size());
707 EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
708 ASSERT_EQ(2U, s[0]->InputCount());
709 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
710 EXPECT_EQ(2U, s[0]->OutputCount());
711 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
712 EXPECT_EQ(kOverflow, s[0]->flags_condition());
713 }
714 }
715
716
717 TEST_F(InstructionSelectorTest, OvfBranchWithImmediateOnLeft) {
718 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
719 StreamBuilder m(this, kMachInt32, kMachInt32);
720 MLabel a, b;
721 Node* n = m.Int32AddWithOverflow(m.Int32Constant(imm), m.Parameter(0));
722 m.Branch(m.Projection(1, n), &a, &b);
723 m.Bind(&a);
724 m.Return(m.Int32Constant(0));
725 m.Bind(&b);
726 m.Return(m.Projection(0, n));
727 Stream s = m.Build();
728
729 ASSERT_EQ(1U, s.size());
730 EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
731 ASSERT_EQ(4U, s[0]->InputCount());
732 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
733 EXPECT_EQ(1U, s[0]->OutputCount());
734 EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
735 EXPECT_EQ(kOverflow, s[0]->flags_condition());
736 }
737 }
738
739
740 // -----------------------------------------------------------------------------
741 // Shift instructions.
742
743
744 typedef InstructionSelectorTestWithParam<MachInst2>
745 InstructionSelectorShiftTest;
746
747
748 TEST_P(InstructionSelectorShiftTest, Parameter) {
749 const MachInst2 dpi = GetParam();
750 const MachineType type = dpi.machine_type;
751 StreamBuilder m(this, type, type, type);
752 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)));
753 Stream s = m.Build();
754 ASSERT_EQ(1U, s.size());
755 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
756 EXPECT_EQ(2U, s[0]->InputCount());
757 EXPECT_EQ(1U, s[0]->OutputCount());
758 }
759
760
761 TEST_P(InstructionSelectorShiftTest, Immediate) {
762 const MachInst2 dpi = GetParam();
763 const MachineType type = dpi.machine_type;
764 TRACED_FORRANGE(int32_t, imm, 0, (ElementSizeOf(type) * 8) - 1) {
765 StreamBuilder m(this, type, type);
766 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm)));
767 Stream s = m.Build();
768 ASSERT_EQ(1U, s.size());
769 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
770 EXPECT_EQ(2U, s[0]->InputCount());
771 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
772 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
773 EXPECT_EQ(1U, s[0]->OutputCount());
774 }
775 }
776
777
778 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorShiftTest,
779 ::testing::ValuesIn(kShiftInstructions));
780
781
782 // -----------------------------------------------------------------------------
783 // Mul and Div instructions.
784
785
786 typedef InstructionSelectorTestWithParam<MachInst2>
787 InstructionSelectorMulDivTest;
788
789
790 TEST_P(InstructionSelectorMulDivTest, Parameter) {
791 const MachInst2 dpi = GetParam();
792 const MachineType type = dpi.machine_type;
793 StreamBuilder m(this, type, type, type);
794 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)));
795 Stream s = m.Build();
796 ASSERT_EQ(1U, s.size());
797 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
798 EXPECT_EQ(2U, s[0]->InputCount());
799 EXPECT_EQ(1U, s[0]->OutputCount());
800 }
801
802
803 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorMulDivTest,
804 ::testing::ValuesIn(kMulDivInstructions));
805
806
807 namespace {
808
809 struct MulDPInst {
810 const char* mul_constructor_name;
811 Node* (RawMachineAssembler::*mul_constructor)(Node*, Node*);
812 Node* (RawMachineAssembler::*add_constructor)(Node*, Node*);
813 Node* (RawMachineAssembler::*sub_constructor)(Node*, Node*);
814 ArchOpcode add_arch_opcode;
815 ArchOpcode sub_arch_opcode;
816 ArchOpcode neg_arch_opcode;
817 MachineType machine_type;
818 };
819
820
821 std::ostream& operator<<(std::ostream& os, const MulDPInst& inst) {
822 return os << inst.mul_constructor_name;
823 }
824
825 } // namespace
826
827
828 static const MulDPInst kMulDPInstructions[] = {
829 {"Int32Mul", &RawMachineAssembler::Int32Mul, &RawMachineAssembler::Int32Add,
830 &RawMachineAssembler::Int32Sub, kArm64Madd32, kArm64Msub32, kArm64Mneg32,
831 kMachInt32},
832 {"Int64Mul", &RawMachineAssembler::Int64Mul, &RawMachineAssembler::Int64Add,
833 &RawMachineAssembler::Int64Sub, kArm64Madd, kArm64Msub, kArm64Mneg,
834 kMachInt64}};
835
836
837 typedef InstructionSelectorTestWithParam<MulDPInst>
838 InstructionSelectorIntDPWithIntMulTest;
839
840
841 TEST_P(InstructionSelectorIntDPWithIntMulTest, AddWithMul) {
842 const MulDPInst mdpi = GetParam();
843 const MachineType type = mdpi.machine_type;
844 {
845 StreamBuilder m(this, type, type, type, type);
846 Node* n = (m.*mdpi.mul_constructor)(m.Parameter(1), m.Parameter(2));
847 m.Return((m.*mdpi.add_constructor)(m.Parameter(0), n));
848 Stream s = m.Build();
849 ASSERT_EQ(1U, s.size());
850 EXPECT_EQ(mdpi.add_arch_opcode, s[0]->arch_opcode());
851 EXPECT_EQ(3U, s[0]->InputCount());
852 EXPECT_EQ(1U, s[0]->OutputCount());
853 }
854 {
855 StreamBuilder m(this, type, type, type, type);
856 Node* n = (m.*mdpi.mul_constructor)(m.Parameter(0), m.Parameter(1));
857 m.Return((m.*mdpi.add_constructor)(n, m.Parameter(2)));
858 Stream s = m.Build();
859 ASSERT_EQ(1U, s.size());
860 EXPECT_EQ(mdpi.add_arch_opcode, s[0]->arch_opcode());
861 EXPECT_EQ(3U, s[0]->InputCount());
862 EXPECT_EQ(1U, s[0]->OutputCount());
863 }
864 }
865
866
867 TEST_P(InstructionSelectorIntDPWithIntMulTest, SubWithMul) {
868 const MulDPInst mdpi = GetParam();
869 const MachineType type = mdpi.machine_type;
870 {
871 StreamBuilder m(this, type, type, type, type);
872 Node* n = (m.*mdpi.mul_constructor)(m.Parameter(1), m.Parameter(2));
873 m.Return((m.*mdpi.sub_constructor)(m.Parameter(0), n));
874 Stream s = m.Build();
875 ASSERT_EQ(1U, s.size());
876 EXPECT_EQ(mdpi.sub_arch_opcode, s[0]->arch_opcode());
877 EXPECT_EQ(3U, s[0]->InputCount());
878 EXPECT_EQ(1U, s[0]->OutputCount());
879 }
880 }
881
882
883 TEST_P(InstructionSelectorIntDPWithIntMulTest, NegativeMul) {
884 const MulDPInst mdpi = GetParam();
885 const MachineType type = mdpi.machine_type;
886 {
887 StreamBuilder m(this, type, type, type);
888 Node* n =
889 (m.*mdpi.sub_constructor)(BuildConstant(m, type, 0), m.Parameter(0));
890 m.Return((m.*mdpi.mul_constructor)(n, m.Parameter(1)));
891 Stream s = m.Build();
892 ASSERT_EQ(1U, s.size());
893 EXPECT_EQ(mdpi.neg_arch_opcode, s[0]->arch_opcode());
894 EXPECT_EQ(2U, s[0]->InputCount());
895 EXPECT_EQ(1U, s[0]->OutputCount());
896 }
897 {
898 StreamBuilder m(this, type, type, type);
899 Node* n =
900 (m.*mdpi.sub_constructor)(BuildConstant(m, type, 0), m.Parameter(1));
901 m.Return((m.*mdpi.mul_constructor)(m.Parameter(0), n));
902 Stream s = m.Build();
903 ASSERT_EQ(1U, s.size());
904 EXPECT_EQ(mdpi.neg_arch_opcode, s[0]->arch_opcode());
905 EXPECT_EQ(2U, s[0]->InputCount());
906 EXPECT_EQ(1U, s[0]->OutputCount());
907 }
908 }
909
910
911 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
912 InstructionSelectorIntDPWithIntMulTest,
913 ::testing::ValuesIn(kMulDPInstructions));
914
915
916 // -----------------------------------------------------------------------------
917 // Floating point instructions.
918
919 typedef InstructionSelectorTestWithParam<MachInst2>
920 InstructionSelectorFPArithTest;
921
922
923 TEST_P(InstructionSelectorFPArithTest, Parameter) {
924 const MachInst2 fpa = GetParam();
925 StreamBuilder m(this, fpa.machine_type, fpa.machine_type, fpa.machine_type);
926 m.Return((m.*fpa.constructor)(m.Parameter(0), m.Parameter(1)));
927 Stream s = m.Build();
928 ASSERT_EQ(1U, s.size());
929 EXPECT_EQ(fpa.arch_opcode, s[0]->arch_opcode());
930 EXPECT_EQ(2U, s[0]->InputCount());
931 EXPECT_EQ(1U, s[0]->OutputCount());
932 }
933
934
935 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorFPArithTest,
936 ::testing::ValuesIn(kFPArithInstructions));
937
938
939 typedef InstructionSelectorTestWithParam<FPCmp> InstructionSelectorFPCmpTest;
940
941
942 TEST_P(InstructionSelectorFPCmpTest, Parameter) {
943 const FPCmp cmp = GetParam();
944 StreamBuilder m(this, kMachInt32, cmp.mi.machine_type, cmp.mi.machine_type);
945 m.Return((m.*cmp.mi.constructor)(m.Parameter(0), m.Parameter(1)));
946 Stream s = m.Build();
947 ASSERT_EQ(1U, s.size());
948 EXPECT_EQ(cmp.mi.arch_opcode, s[0]->arch_opcode());
949 EXPECT_EQ(2U, s[0]->InputCount());
950 EXPECT_EQ(1U, s[0]->OutputCount());
951 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
952 EXPECT_EQ(cmp.cond, s[0]->flags_condition());
953 }
954
955
956 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorFPCmpTest,
957 ::testing::ValuesIn(kFPCmpInstructions));
958
959
960 // -----------------------------------------------------------------------------
961 // Conversions.
962
963 typedef InstructionSelectorTestWithParam<Conversion>
964 InstructionSelectorConversionTest;
965
966
967 TEST_P(InstructionSelectorConversionTest, Parameter) {
968 const Conversion conv = GetParam();
969 StreamBuilder m(this, conv.mi.machine_type, conv.src_machine_type);
970 m.Return((m.*conv.mi.constructor)(m.Parameter(0)));
971 Stream s = m.Build();
972 ASSERT_EQ(1U, s.size());
973 EXPECT_EQ(conv.mi.arch_opcode, s[0]->arch_opcode());
974 EXPECT_EQ(1U, s[0]->InputCount());
975 EXPECT_EQ(1U, s[0]->OutputCount());
976 }
977
978
979 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
980 InstructionSelectorConversionTest,
981 ::testing::ValuesIn(kConversionInstructions));
982
983
984 // -----------------------------------------------------------------------------
985 // Memory access instructions.
986
987
988 namespace {
989
990 struct MemoryAccess {
991 MachineType type;
992 ArchOpcode ldr_opcode;
993 ArchOpcode str_opcode;
994 const int32_t immediates[20];
995 };
996
997
998 std::ostream& operator<<(std::ostream& os, const MemoryAccess& memacc) {
999 return os << memacc.type;
1000 }
1001
1002 } // namespace
1003
1004
1005 static const MemoryAccess kMemoryAccesses[] = {
1006 {kMachInt8, kArm64Ldrsb, kArm64Strb,
1007 {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 257, 258, 1000, 1001,
1008 2121, 2442, 4093, 4094, 4095}},
1009 {kMachUint8, kArm64Ldrb, kArm64Strb,
1010 {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 257, 258, 1000, 1001,
1011 2121, 2442, 4093, 4094, 4095}},
1012 {kMachInt16, kArm64Ldrsh, kArm64Strh,
1013 {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 258, 260, 4096, 4098,
1014 4100, 4242, 6786, 8188, 8190}},
1015 {kMachUint16, kArm64Ldrh, kArm64Strh,
1016 {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 258, 260, 4096, 4098,
1017 4100, 4242, 6786, 8188, 8190}},
1018 {kMachInt32, kArm64LdrW, kArm64StrW,
1019 {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 260, 4096, 4100, 8192,
1020 8196, 3276, 3280, 16376, 16380}},
1021 {kMachUint32, kArm64LdrW, kArm64StrW,
1022 {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 260, 4096, 4100, 8192,
1023 8196, 3276, 3280, 16376, 16380}},
1024 {kMachInt64, kArm64Ldr, kArm64Str,
1025 {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 264, 4096, 4104, 8192,
1026 8200, 16384, 16392, 32752, 32760}},
1027 {kMachUint64, kArm64Ldr, kArm64Str,
1028 {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 264, 4096, 4104, 8192,
1029 8200, 16384, 16392, 32752, 32760}},
1030 {kMachFloat32, kArm64LdrS, kArm64StrS,
1031 {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 260, 4096, 4100, 8192,
1032 8196, 3276, 3280, 16376, 16380}},
1033 {kMachFloat64, kArm64LdrD, kArm64StrD,
1034 {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 264, 4096, 4104, 8192,
1035 8200, 16384, 16392, 32752, 32760}}};
1036
1037
1038 typedef InstructionSelectorTestWithParam<MemoryAccess>
1039 InstructionSelectorMemoryAccessTest;
1040
1041
1042 TEST_P(InstructionSelectorMemoryAccessTest, LoadWithParameters) {
1043 const MemoryAccess memacc = GetParam();
1044 StreamBuilder m(this, memacc.type, kMachPtr, kMachInt32);
1045 m.Return(m.Load(memacc.type, m.Parameter(0), m.Parameter(1)));
1046 Stream s = m.Build();
1047 ASSERT_EQ(1U, s.size());
1048 EXPECT_EQ(memacc.ldr_opcode, s[0]->arch_opcode());
1049 EXPECT_EQ(kMode_MRR, s[0]->addressing_mode());
1050 EXPECT_EQ(2U, s[0]->InputCount());
1051 EXPECT_EQ(1U, s[0]->OutputCount());
1052 }
1053
1054
1055 TEST_P(InstructionSelectorMemoryAccessTest, LoadWithImmediateIndex) {
1056 const MemoryAccess memacc = GetParam();
1057 TRACED_FOREACH(int32_t, index, memacc.immediates) {
1058 StreamBuilder m(this, memacc.type, kMachPtr);
1059 m.Return(m.Load(memacc.type, m.Parameter(0), m.Int32Constant(index)));
1060 Stream s = m.Build();
1061 ASSERT_EQ(1U, s.size());
1062 EXPECT_EQ(memacc.ldr_opcode, s[0]->arch_opcode());
1063 EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
1064 EXPECT_EQ(2U, s[0]->InputCount());
1065 ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
1066 EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1)));
1067 ASSERT_EQ(1U, s[0]->OutputCount());
1068 }
1069 }
1070
1071
1072 TEST_P(InstructionSelectorMemoryAccessTest, StoreWithParameters) {
1073 const MemoryAccess memacc = GetParam();
1074 StreamBuilder m(this, kMachInt32, kMachPtr, kMachInt32, memacc.type);
1075 m.Store(memacc.type, m.Parameter(0), m.Parameter(1), m.Parameter(2));
1076 m.Return(m.Int32Constant(0));
1077 Stream s = m.Build();
1078 ASSERT_EQ(1U, s.size());
1079 EXPECT_EQ(memacc.str_opcode, s[0]->arch_opcode());
1080 EXPECT_EQ(kMode_MRR, s[0]->addressing_mode());
1081 EXPECT_EQ(3U, s[0]->InputCount());
1082 EXPECT_EQ(0U, s[0]->OutputCount());
1083 }
1084
1085
1086 TEST_P(InstructionSelectorMemoryAccessTest, StoreWithImmediateIndex) {
1087 const MemoryAccess memacc = GetParam();
1088 TRACED_FOREACH(int32_t, index, memacc.immediates) {
1089 StreamBuilder m(this, kMachInt32, kMachPtr, memacc.type);
1090 m.Store(memacc.type, m.Parameter(0), m.Int32Constant(index),
1091 m.Parameter(1));
1092 m.Return(m.Int32Constant(0));
1093 Stream s = m.Build();
1094 ASSERT_EQ(1U, s.size());
1095 EXPECT_EQ(memacc.str_opcode, s[0]->arch_opcode());
1096 EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
1097 ASSERT_EQ(3U, s[0]->InputCount());
1098 ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
1099 EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1)));
1100 EXPECT_EQ(0U, s[0]->OutputCount());
1101 }
1102 }
1103
1104
1105 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1106 InstructionSelectorMemoryAccessTest,
1107 ::testing::ValuesIn(kMemoryAccesses));
1108
1109
1110 // -----------------------------------------------------------------------------
1111 // Comparison instructions.
1112
1113 static const MachInst2 kComparisonInstructions[] = {
1114 {&RawMachineAssembler::Word32Equal, "Word32Equal", kArm64Cmp32, kMachInt32},
1115 {&RawMachineAssembler::Word64Equal, "Word64Equal", kArm64Cmp, kMachInt64},
1116 };
1117
1118
1119 typedef InstructionSelectorTestWithParam<MachInst2>
1120 InstructionSelectorComparisonTest;
1121
1122
1123 TEST_P(InstructionSelectorComparisonTest, WithParameters) {
1124 const MachInst2 cmp = GetParam();
1125 const MachineType type = cmp.machine_type;
1126 StreamBuilder m(this, type, type, type);
1127 m.Return((m.*cmp.constructor)(m.Parameter(0), m.Parameter(1)));
1128 Stream s = m.Build();
1129 ASSERT_EQ(1U, s.size());
1130 EXPECT_EQ(cmp.arch_opcode, s[0]->arch_opcode());
1131 EXPECT_EQ(2U, s[0]->InputCount());
1132 EXPECT_EQ(1U, s[0]->OutputCount());
1133 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1134 EXPECT_EQ(kEqual, s[0]->flags_condition());
1135 }
1136
1137
1138 TEST_P(InstructionSelectorComparisonTest, WithImmediate) {
1139 const MachInst2 cmp = GetParam();
1140 const MachineType type = cmp.machine_type;
1141 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
1142 // Compare with 0 are turned into tst instruction.
1143 if (imm == 0) continue;
1144 StreamBuilder m(this, type, type);
1145 m.Return((m.*cmp.constructor)(m.Parameter(0), BuildConstant(m, type, imm)));
1146 Stream s = m.Build();
1147 ASSERT_EQ(1U, s.size());
1148 EXPECT_EQ(cmp.arch_opcode, s[0]->arch_opcode());
1149 ASSERT_EQ(2U, s[0]->InputCount());
1150 ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
1151 EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(1)));
1152 EXPECT_EQ(1U, s[0]->OutputCount());
1153 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1154 EXPECT_EQ(kEqual, s[0]->flags_condition());
1155 }
1156 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
1157 // Compare with 0 are turned into tst instruction.
1158 if (imm == 0) continue;
1159 StreamBuilder m(this, type, type);
1160 m.Return((m.*cmp.constructor)(BuildConstant(m, type, imm), m.Parameter(0)));
1161 Stream s = m.Build();
1162 ASSERT_EQ(1U, s.size());
1163 EXPECT_EQ(cmp.arch_opcode, s[0]->arch_opcode());
1164 ASSERT_EQ(2U, s[0]->InputCount());
1165 ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
1166 EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(1)));
1167 EXPECT_EQ(1U, s[0]->OutputCount());
1168 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1169 EXPECT_EQ(kEqual, s[0]->flags_condition());
1170 }
1171 }
1172
1173 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1174 InstructionSelectorComparisonTest,
1175 ::testing::ValuesIn(kComparisonInstructions));
1176
1177
1178 TEST_F(InstructionSelectorTest, Word32EqualWithZero) {
1179 {
1180 StreamBuilder m(this, kMachInt32, kMachInt32);
1181 m.Return(m.Word32Equal(m.Parameter(0), m.Int32Constant(0)));
1182 Stream s = m.Build();
1183 ASSERT_EQ(1U, s.size());
1184 EXPECT_EQ(kArm64Tst32, s[0]->arch_opcode());
1185 ASSERT_EQ(2U, s[0]->InputCount());
1186 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
1187 EXPECT_EQ(1U, s[0]->OutputCount());
1188 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1189 EXPECT_EQ(kEqual, s[0]->flags_condition());
1190 }
1191 {
1192 StreamBuilder m(this, kMachInt32, kMachInt32);
1193 m.Return(m.Word32Equal(m.Int32Constant(0), m.Parameter(0)));
1194 Stream s = m.Build();
1195 ASSERT_EQ(1U, s.size());
1196 EXPECT_EQ(kArm64Tst32, s[0]->arch_opcode());
1197 ASSERT_EQ(2U, s[0]->InputCount());
1198 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
1199 EXPECT_EQ(1U, s[0]->OutputCount());
1200 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1201 EXPECT_EQ(kEqual, s[0]->flags_condition());
1202 }
1203 }
1204
1205
1206 TEST_F(InstructionSelectorTest, Word64EqualWithZero) {
1207 {
1208 StreamBuilder m(this, kMachInt64, kMachInt64);
1209 m.Return(m.Word64Equal(m.Parameter(0), m.Int64Constant(0)));
1210 Stream s = m.Build();
1211 ASSERT_EQ(1U, s.size());
1212 EXPECT_EQ(kArm64Tst, s[0]->arch_opcode());
1213 ASSERT_EQ(2U, s[0]->InputCount());
1214 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
1215 EXPECT_EQ(1U, s[0]->OutputCount());
1216 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1217 EXPECT_EQ(kEqual, s[0]->flags_condition());
1218 }
1219 {
1220 StreamBuilder m(this, kMachInt64, kMachInt64);
1221 m.Return(m.Word64Equal(m.Int64Constant(0), m.Parameter(0)));
1222 Stream s = m.Build();
1223 ASSERT_EQ(1U, s.size());
1224 EXPECT_EQ(kArm64Tst, s[0]->arch_opcode());
1225 ASSERT_EQ(2U, s[0]->InputCount());
1226 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
1227 EXPECT_EQ(1U, s[0]->OutputCount());
1228 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1229 EXPECT_EQ(kEqual, s[0]->flags_condition());
1230 }
1231 }
1232
1233
1234 // -----------------------------------------------------------------------------
1235 // Miscellaneous
1236
1237
1238 static const MachInst2 kLogicalWithNotRHSs[] = {
1239 {&RawMachineAssembler::Word32And, "Word32And", kArm64Bic32, kMachInt32},
1240 {&RawMachineAssembler::Word64And, "Word64And", kArm64Bic, kMachInt64},
1241 {&RawMachineAssembler::Word32Or, "Word32Or", kArm64Orn32, kMachInt32},
1242 {&RawMachineAssembler::Word64Or, "Word64Or", kArm64Orn, kMachInt64},
1243 {&RawMachineAssembler::Word32Xor, "Word32Xor", kArm64Eon32, kMachInt32},
1244 {&RawMachineAssembler::Word64Xor, "Word64Xor", kArm64Eon, kMachInt64}};
1245
1246
1247 typedef InstructionSelectorTestWithParam<MachInst2>
1248 InstructionSelectorLogicalWithNotRHSTest;
1249
1250
1251 TEST_P(InstructionSelectorLogicalWithNotRHSTest, Parameter) {
1252 const MachInst2 inst = GetParam();
1253 const MachineType type = inst.machine_type;
1254 // Test cases where RHS is Xor(x, -1).
1255 {
1256 StreamBuilder m(this, type, type, type);
1257 if (type == kMachInt32) {
1258 m.Return((m.*inst.constructor)(
1259 m.Parameter(0), m.Word32Xor(m.Parameter(1), m.Int32Constant(-1))));
1260 } else {
1261 ASSERT_EQ(kMachInt64, type);
1262 m.Return((m.*inst.constructor)(
1263 m.Parameter(0), m.Word64Xor(m.Parameter(1), m.Int64Constant(-1))));
1264 }
1265 Stream s = m.Build();
1266 ASSERT_EQ(1U, s.size());
1267 EXPECT_EQ(inst.arch_opcode, s[0]->arch_opcode());
1268 EXPECT_EQ(2U, s[0]->InputCount());
1269 EXPECT_EQ(1U, s[0]->OutputCount());
1270 }
1271 {
1272 StreamBuilder m(this, type, type, type);
1273 if (type == kMachInt32) {
1274 m.Return((m.*inst.constructor)(
1275 m.Word32Xor(m.Parameter(0), m.Int32Constant(-1)), m.Parameter(1)));
1276 } else {
1277 ASSERT_EQ(kMachInt64, type);
1278 m.Return((m.*inst.constructor)(
1279 m.Word64Xor(m.Parameter(0), m.Int64Constant(-1)), m.Parameter(1)));
1280 }
1281 Stream s = m.Build();
1282 ASSERT_EQ(1U, s.size());
1283 EXPECT_EQ(inst.arch_opcode, s[0]->arch_opcode());
1284 EXPECT_EQ(2U, s[0]->InputCount());
1285 EXPECT_EQ(1U, s[0]->OutputCount());
1286 }
1287 // Test cases where RHS is Not(x).
1288 {
1289 StreamBuilder m(this, type, type, type);
1290 if (type == kMachInt32) {
1291 m.Return(
1292 (m.*inst.constructor)(m.Parameter(0), m.Word32Not(m.Parameter(1))));
1293 } else {
1294 ASSERT_EQ(kMachInt64, type);
1295 m.Return(
1296 (m.*inst.constructor)(m.Parameter(0), m.Word64Not(m.Parameter(1))));
1297 }
1298 Stream s = m.Build();
1299 ASSERT_EQ(1U, s.size());
1300 EXPECT_EQ(inst.arch_opcode, s[0]->arch_opcode());
1301 EXPECT_EQ(2U, s[0]->InputCount());
1302 EXPECT_EQ(1U, s[0]->OutputCount());
1303 }
1304 {
1305 StreamBuilder m(this, type, type, type);
1306 if (type == kMachInt32) {
1307 m.Return(
1308 (m.*inst.constructor)(m.Word32Not(m.Parameter(0)), m.Parameter(1)));
1309 } else {
1310 ASSERT_EQ(kMachInt64, type);
1311 m.Return(
1312 (m.*inst.constructor)(m.Word64Not(m.Parameter(0)), m.Parameter(1)));
1313 }
1314 Stream s = m.Build();
1315 ASSERT_EQ(1U, s.size());
1316 EXPECT_EQ(inst.arch_opcode, s[0]->arch_opcode());
1317 EXPECT_EQ(2U, s[0]->InputCount());
1318 EXPECT_EQ(1U, s[0]->OutputCount());
1319 }
1320 }
1321
1322
1323 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1324 InstructionSelectorLogicalWithNotRHSTest,
1325 ::testing::ValuesIn(kLogicalWithNotRHSs));
1326
1327
1328 TEST_F(InstructionSelectorTest, Word32NotWithParameter) {
1329 StreamBuilder m(this, kMachInt32, kMachInt32);
1330 m.Return(m.Word32Not(m.Parameter(0)));
1331 Stream s = m.Build();
1332 ASSERT_EQ(1U, s.size());
1333 EXPECT_EQ(kArm64Not32, s[0]->arch_opcode());
1334 EXPECT_EQ(1U, s[0]->InputCount());
1335 EXPECT_EQ(1U, s[0]->OutputCount());
1336 }
1337
1338
1339 TEST_F(InstructionSelectorTest, Word64NotWithParameter) {
1340 StreamBuilder m(this, kMachInt64, kMachInt64);
1341 m.Return(m.Word64Not(m.Parameter(0)));
1342 Stream s = m.Build();
1343 ASSERT_EQ(1U, s.size());
1344 EXPECT_EQ(kArm64Not, s[0]->arch_opcode());
1345 EXPECT_EQ(1U, s[0]->InputCount());
1346 EXPECT_EQ(1U, s[0]->OutputCount());
1347 }
1348
1349
1350 TEST_F(InstructionSelectorTest, Word32XorMinusOneWithParameter) {
1351 {
1352 StreamBuilder m(this, kMachInt32, kMachInt32);
1353 m.Return(m.Word32Xor(m.Parameter(0), m.Int32Constant(-1)));
1354 Stream s = m.Build();
1355 ASSERT_EQ(1U, s.size());
1356 EXPECT_EQ(kArm64Not32, s[0]->arch_opcode());
1357 EXPECT_EQ(1U, s[0]->InputCount());
1358 EXPECT_EQ(1U, s[0]->OutputCount());
1359 }
1360 {
1361 StreamBuilder m(this, kMachInt32, kMachInt32);
1362 m.Return(m.Word32Xor(m.Int32Constant(-1), m.Parameter(0)));
1363 Stream s = m.Build();
1364 ASSERT_EQ(1U, s.size());
1365 EXPECT_EQ(kArm64Not32, s[0]->arch_opcode());
1366 EXPECT_EQ(1U, s[0]->InputCount());
1367 EXPECT_EQ(1U, s[0]->OutputCount());
1368 }
1369 }
1370
1371
1372 TEST_F(InstructionSelectorTest, Word64XorMinusOneWithParameter) {
1373 {
1374 StreamBuilder m(this, kMachInt64, kMachInt64);
1375 m.Return(m.Word64Xor(m.Parameter(0), m.Int64Constant(-1)));
1376 Stream s = m.Build();
1377 ASSERT_EQ(1U, s.size());
1378 EXPECT_EQ(kArm64Not, s[0]->arch_opcode());
1379 EXPECT_EQ(1U, s[0]->InputCount());
1380 EXPECT_EQ(1U, s[0]->OutputCount());
1381 }
1382 {
1383 StreamBuilder m(this, kMachInt64, kMachInt64);
1384 m.Return(m.Word64Xor(m.Int64Constant(-1), m.Parameter(0)));
1385 Stream s = m.Build();
1386 ASSERT_EQ(1U, s.size());
1387 EXPECT_EQ(kArm64Not, s[0]->arch_opcode());
1388 EXPECT_EQ(1U, s[0]->InputCount());
1389 EXPECT_EQ(1U, s[0]->OutputCount());
1390 }
1391 }
1392
1393 } // namespace compiler
1394 } // namespace internal
1395 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/arm/instruction-selector-arm-unittest.cc ('k') | src/compiler/change-lowering-unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698