OLD | NEW |
| (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 "test/compiler-unittests/instruction-selector-unittest.h" | |
8 | |
9 namespace v8 { | |
10 namespace internal { | |
11 namespace compiler { | |
12 | |
13 namespace { | |
14 | |
15 template <typename T> | |
16 struct MachInst { | |
17 T constructor; | |
18 const char* constructor_name; | |
19 ArchOpcode arch_opcode; | |
20 MachineType machine_type; | |
21 }; | |
22 | |
23 typedef MachInst<Node* (RawMachineAssembler::*)(Node*)> MachInst1; | |
24 typedef MachInst<Node* (RawMachineAssembler::*)(Node*, Node*)> MachInst2; | |
25 | |
26 | |
27 template <typename T> | |
28 std::ostream& operator<<(std::ostream& os, const MachInst<T>& mi) { | |
29 return os << mi.constructor_name; | |
30 } | |
31 | |
32 | |
33 // ARM64 logical instructions. | |
34 static const MachInst2 kLogicalInstructions[] = { | |
35 {&RawMachineAssembler::Word32And, "Word32And", kArm64And32, kMachInt32}, | |
36 {&RawMachineAssembler::Word64And, "Word64And", kArm64And, kMachInt64}, | |
37 {&RawMachineAssembler::Word32Or, "Word32Or", kArm64Or32, kMachInt32}, | |
38 {&RawMachineAssembler::Word64Or, "Word64Or", kArm64Or, kMachInt64}, | |
39 {&RawMachineAssembler::Word32Xor, "Word32Xor", kArm64Xor32, kMachInt32}, | |
40 {&RawMachineAssembler::Word64Xor, "Word64Xor", kArm64Xor, kMachInt64}}; | |
41 | |
42 | |
43 // ARM64 logical immediates: contiguous set bits, rotated about a power of two | |
44 // sized block. The block is then duplicated across the word. Below is a random | |
45 // subset of the 32-bit immediates. | |
46 static const uint32_t kLogicalImmediates[] = { | |
47 0x00000002, 0x00000003, 0x00000070, 0x00000080, 0x00000100, 0x000001c0, | |
48 0x00000300, 0x000007e0, 0x00003ffc, 0x00007fc0, 0x0003c000, 0x0003f000, | |
49 0x0003ffc0, 0x0003fff8, 0x0007ff00, 0x0007ffe0, 0x000e0000, 0x001e0000, | |
50 0x001ffffc, 0x003f0000, 0x003f8000, 0x00780000, 0x007fc000, 0x00ff0000, | |
51 0x01800000, 0x01800180, 0x01f801f8, 0x03fe0000, 0x03ffffc0, 0x03fffffc, | |
52 0x06000000, 0x07fc0000, 0x07ffc000, 0x07ffffc0, 0x07ffffe0, 0x0ffe0ffe, | |
53 0x0ffff800, 0x0ffffff0, 0x0fffffff, 0x18001800, 0x1f001f00, 0x1f801f80, | |
54 0x30303030, 0x3ff03ff0, 0x3ff83ff8, 0x3fff0000, 0x3fff8000, 0x3fffffc0, | |
55 0x70007000, 0x7f7f7f7f, 0x7fc00000, 0x7fffffc0, 0x8000001f, 0x800001ff, | |
56 0x81818181, 0x9fff9fff, 0xc00007ff, 0xc0ffffff, 0xdddddddd, 0xe00001ff, | |
57 0xe00003ff, 0xe007ffff, 0xefffefff, 0xf000003f, 0xf001f001, 0xf3fff3ff, | |
58 0xf800001f, 0xf80fffff, 0xf87ff87f, 0xfbfbfbfb, 0xfc00001f, 0xfc0000ff, | |
59 0xfc0001ff, 0xfc03fc03, 0xfe0001ff, 0xff000001, 0xff03ff03, 0xff800000, | |
60 0xff800fff, 0xff801fff, 0xff87ffff, 0xffc0003f, 0xffc007ff, 0xffcfffcf, | |
61 0xffe00003, 0xffe1ffff, 0xfff0001f, 0xfff07fff, 0xfff80007, 0xfff87fff, | |
62 0xfffc00ff, 0xfffe07ff, 0xffff00ff, 0xffffc001, 0xfffff007, 0xfffff3ff, | |
63 0xfffff807, 0xfffff9ff, 0xfffffc0f, 0xfffffeff}; | |
64 | |
65 | |
66 // ARM64 arithmetic instructions. | |
67 static const MachInst2 kAddSubInstructions[] = { | |
68 {&RawMachineAssembler::Int32Add, "Int32Add", kArm64Add32, kMachInt32}, | |
69 {&RawMachineAssembler::Int64Add, "Int64Add", kArm64Add, kMachInt64}, | |
70 {&RawMachineAssembler::Int32Sub, "Int32Sub", kArm64Sub32, kMachInt32}, | |
71 {&RawMachineAssembler::Int64Sub, "Int64Sub", kArm64Sub, kMachInt64}}; | |
72 | |
73 | |
74 // ARM64 Add/Sub immediates: 12-bit immediate optionally shifted by 12. | |
75 // Below is a combination of a random subset and some edge values. | |
76 static const int32_t kAddSubImmediates[] = { | |
77 0, 1, 69, 493, 599, 701, 719, | |
78 768, 818, 842, 945, 1246, 1286, 1429, | |
79 1669, 2171, 2179, 2182, 2254, 2334, 2338, | |
80 2343, 2396, 2449, 2610, 2732, 2855, 2876, | |
81 2944, 3377, 3458, 3475, 3476, 3540, 3574, | |
82 3601, 3813, 3871, 3917, 4095, 4096, 16384, | |
83 364544, 462848, 970752, 1523712, 1863680, 2363392, 3219456, | |
84 3280896, 4247552, 4526080, 4575232, 4960256, 5505024, 5894144, | |
85 6004736, 6193152, 6385664, 6795264, 7114752, 7233536, 7348224, | |
86 7499776, 7573504, 7729152, 8634368, 8937472, 9465856, 10354688, | |
87 10682368, 11059200, 11460608, 13168640, 13176832, 14336000, 15028224, | |
88 15597568, 15892480, 16773120}; | |
89 | |
90 | |
91 // ARM64 shift instructions. | |
92 static const MachInst2 kShiftInstructions[] = { | |
93 {&RawMachineAssembler::Word32Shl, "Word32Shl", kArm64Shl32, kMachInt32}, | |
94 {&RawMachineAssembler::Word64Shl, "Word64Shl", kArm64Shl, kMachInt64}, | |
95 {&RawMachineAssembler::Word32Shr, "Word32Shr", kArm64Shr32, kMachInt32}, | |
96 {&RawMachineAssembler::Word64Shr, "Word64Shr", kArm64Shr, kMachInt64}, | |
97 {&RawMachineAssembler::Word32Sar, "Word32Sar", kArm64Sar32, kMachInt32}, | |
98 {&RawMachineAssembler::Word64Sar, "Word64Sar", kArm64Sar, kMachInt64}, | |
99 {&RawMachineAssembler::Word32Ror, "Word32Ror", kArm64Ror32, kMachInt32}, | |
100 {&RawMachineAssembler::Word64Ror, "Word64Ror", kArm64Ror, kMachInt64}}; | |
101 | |
102 | |
103 // ARM64 Mul/Div instructions. | |
104 static const MachInst2 kMulDivInstructions[] = { | |
105 {&RawMachineAssembler::Int32Mul, "Int32Mul", kArm64Mul32, kMachInt32}, | |
106 {&RawMachineAssembler::Int64Mul, "Int64Mul", kArm64Mul, kMachInt64}, | |
107 {&RawMachineAssembler::Int32Div, "Int32Div", kArm64Idiv32, kMachInt32}, | |
108 {&RawMachineAssembler::Int64Div, "Int64Div", kArm64Idiv, kMachInt64}, | |
109 {&RawMachineAssembler::Int32UDiv, "Int32UDiv", kArm64Udiv32, kMachInt32}, | |
110 {&RawMachineAssembler::Int64UDiv, "Int64UDiv", kArm64Udiv, kMachInt64}}; | |
111 | |
112 | |
113 // ARM64 FP arithmetic instructions. | |
114 static const MachInst2 kFPArithInstructions[] = { | |
115 {&RawMachineAssembler::Float64Add, "Float64Add", kArm64Float64Add, | |
116 kMachFloat64}, | |
117 {&RawMachineAssembler::Float64Sub, "Float64Sub", kArm64Float64Sub, | |
118 kMachFloat64}, | |
119 {&RawMachineAssembler::Float64Mul, "Float64Mul", kArm64Float64Mul, | |
120 kMachFloat64}, | |
121 {&RawMachineAssembler::Float64Div, "Float64Div", kArm64Float64Div, | |
122 kMachFloat64}}; | |
123 | |
124 | |
125 struct FPCmp { | |
126 MachInst2 mi; | |
127 FlagsCondition cond; | |
128 }; | |
129 | |
130 | |
131 std::ostream& operator<<(std::ostream& os, const FPCmp& cmp) { | |
132 return os << cmp.mi; | |
133 } | |
134 | |
135 | |
136 // ARM64 FP comparison instructions. | |
137 static const FPCmp kFPCmpInstructions[] = { | |
138 {{&RawMachineAssembler::Float64Equal, "Float64Equal", kArm64Float64Cmp, | |
139 kMachFloat64}, | |
140 kUnorderedEqual}, | |
141 {{&RawMachineAssembler::Float64LessThan, "Float64LessThan", | |
142 kArm64Float64Cmp, kMachFloat64}, | |
143 kUnorderedLessThan}, | |
144 {{&RawMachineAssembler::Float64LessThanOrEqual, "Float64LessThanOrEqual", | |
145 kArm64Float64Cmp, kMachFloat64}, | |
146 kUnorderedLessThanOrEqual}}; | |
147 | |
148 | |
149 struct Conversion { | |
150 // The machine_type field in MachInst1 represents the destination type. | |
151 MachInst1 mi; | |
152 MachineType src_machine_type; | |
153 }; | |
154 | |
155 | |
156 std::ostream& operator<<(std::ostream& os, const Conversion& conv) { | |
157 return os << conv.mi; | |
158 } | |
159 | |
160 | |
161 // ARM64 type conversion instructions. | |
162 static const Conversion kConversionInstructions[] = { | |
163 {{&RawMachineAssembler::ChangeInt32ToInt64, "ChangeInt32ToInt64", | |
164 kArm64Sxtw, kMachInt64}, | |
165 kMachInt32}, | |
166 {{&RawMachineAssembler::ChangeUint32ToUint64, "ChangeUint32ToUint64", | |
167 kArm64Mov32, kMachUint64}, | |
168 kMachUint32}, | |
169 {{&RawMachineAssembler::TruncateInt64ToInt32, "TruncateInt64ToInt32", | |
170 kArm64Mov32, kMachInt32}, | |
171 kMachInt64}, | |
172 {{&RawMachineAssembler::ChangeInt32ToFloat64, "ChangeInt32ToFloat64", | |
173 kArm64Int32ToFloat64, kMachFloat64}, | |
174 kMachInt32}, | |
175 {{&RawMachineAssembler::ChangeUint32ToFloat64, "ChangeUint32ToFloat64", | |
176 kArm64Uint32ToFloat64, kMachFloat64}, | |
177 kMachUint32}, | |
178 {{&RawMachineAssembler::ChangeFloat64ToInt32, "ChangeFloat64ToInt32", | |
179 kArm64Float64ToInt32, kMachInt32}, | |
180 kMachFloat64}, | |
181 {{&RawMachineAssembler::ChangeFloat64ToUint32, "ChangeFloat64ToUint32", | |
182 kArm64Float64ToUint32, kMachUint32}, | |
183 kMachFloat64}}; | |
184 | |
185 } // namespace | |
186 | |
187 | |
188 // ----------------------------------------------------------------------------- | |
189 // Logical instructions. | |
190 | |
191 | |
192 typedef InstructionSelectorTestWithParam<MachInst2> | |
193 InstructionSelectorLogicalTest; | |
194 | |
195 | |
196 TEST_P(InstructionSelectorLogicalTest, Parameter) { | |
197 const MachInst2 dpi = GetParam(); | |
198 const MachineType type = dpi.machine_type; | |
199 StreamBuilder m(this, type, type, type); | |
200 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1))); | |
201 Stream s = m.Build(); | |
202 ASSERT_EQ(1U, s.size()); | |
203 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); | |
204 EXPECT_EQ(2U, s[0]->InputCount()); | |
205 EXPECT_EQ(1U, s[0]->OutputCount()); | |
206 } | |
207 | |
208 | |
209 TEST_P(InstructionSelectorLogicalTest, Immediate) { | |
210 const MachInst2 dpi = GetParam(); | |
211 const MachineType type = dpi.machine_type; | |
212 // TODO(all): Add support for testing 64-bit immediates. | |
213 if (type == kMachInt32) { | |
214 // Immediate on the right. | |
215 TRACED_FOREACH(int32_t, imm, kLogicalImmediates) { | |
216 StreamBuilder m(this, type, type); | |
217 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm))); | |
218 Stream s = m.Build(); | |
219 ASSERT_EQ(1U, s.size()); | |
220 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); | |
221 ASSERT_EQ(2U, s[0]->InputCount()); | |
222 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate()); | |
223 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); | |
224 EXPECT_EQ(1U, s[0]->OutputCount()); | |
225 } | |
226 | |
227 // Immediate on the left; all logical ops should commute. | |
228 TRACED_FOREACH(int32_t, imm, kLogicalImmediates) { | |
229 StreamBuilder m(this, type, type); | |
230 m.Return((m.*dpi.constructor)(m.Int32Constant(imm), m.Parameter(0))); | |
231 Stream s = m.Build(); | |
232 ASSERT_EQ(1U, s.size()); | |
233 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); | |
234 ASSERT_EQ(2U, s[0]->InputCount()); | |
235 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate()); | |
236 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); | |
237 EXPECT_EQ(1U, s[0]->OutputCount()); | |
238 } | |
239 } | |
240 } | |
241 | |
242 | |
243 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorLogicalTest, | |
244 ::testing::ValuesIn(kLogicalInstructions)); | |
245 | |
246 | |
247 // ----------------------------------------------------------------------------- | |
248 // Add and Sub instructions. | |
249 | |
250 typedef InstructionSelectorTestWithParam<MachInst2> | |
251 InstructionSelectorAddSubTest; | |
252 | |
253 | |
254 TEST_P(InstructionSelectorAddSubTest, Parameter) { | |
255 const MachInst2 dpi = GetParam(); | |
256 const MachineType type = dpi.machine_type; | |
257 StreamBuilder m(this, type, type, type); | |
258 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1))); | |
259 Stream s = m.Build(); | |
260 ASSERT_EQ(1U, s.size()); | |
261 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); | |
262 EXPECT_EQ(2U, s[0]->InputCount()); | |
263 EXPECT_EQ(1U, s[0]->OutputCount()); | |
264 } | |
265 | |
266 | |
267 TEST_P(InstructionSelectorAddSubTest, Immediate) { | |
268 const MachInst2 dpi = GetParam(); | |
269 const MachineType type = dpi.machine_type; | |
270 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) { | |
271 StreamBuilder m(this, type, type); | |
272 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm))); | |
273 Stream s = m.Build(); | |
274 ASSERT_EQ(1U, s.size()); | |
275 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); | |
276 ASSERT_EQ(2U, s[0]->InputCount()); | |
277 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate()); | |
278 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); | |
279 EXPECT_EQ(1U, s[0]->OutputCount()); | |
280 } | |
281 } | |
282 | |
283 | |
284 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorAddSubTest, | |
285 ::testing::ValuesIn(kAddSubInstructions)); | |
286 | |
287 | |
288 // ----------------------------------------------------------------------------- | |
289 // Shift instructions. | |
290 | |
291 | |
292 typedef InstructionSelectorTestWithParam<MachInst2> | |
293 InstructionSelectorShiftTest; | |
294 | |
295 | |
296 TEST_P(InstructionSelectorShiftTest, Parameter) { | |
297 const MachInst2 dpi = GetParam(); | |
298 const MachineType type = dpi.machine_type; | |
299 StreamBuilder m(this, type, type, type); | |
300 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1))); | |
301 Stream s = m.Build(); | |
302 ASSERT_EQ(1U, s.size()); | |
303 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); | |
304 EXPECT_EQ(2U, s[0]->InputCount()); | |
305 EXPECT_EQ(1U, s[0]->OutputCount()); | |
306 } | |
307 | |
308 | |
309 TEST_P(InstructionSelectorShiftTest, Immediate) { | |
310 const MachInst2 dpi = GetParam(); | |
311 const MachineType type = dpi.machine_type; | |
312 TRACED_FORRANGE(int32_t, imm, 0, (ElementSizeOf(type) * 8) - 1) { | |
313 StreamBuilder m(this, type, type); | |
314 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm))); | |
315 Stream s = m.Build(); | |
316 ASSERT_EQ(1U, s.size()); | |
317 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); | |
318 EXPECT_EQ(2U, s[0]->InputCount()); | |
319 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate()); | |
320 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); | |
321 EXPECT_EQ(1U, s[0]->OutputCount()); | |
322 } | |
323 } | |
324 | |
325 | |
326 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorShiftTest, | |
327 ::testing::ValuesIn(kShiftInstructions)); | |
328 | |
329 | |
330 // ----------------------------------------------------------------------------- | |
331 // Mul and Div instructions. | |
332 | |
333 | |
334 typedef InstructionSelectorTestWithParam<MachInst2> | |
335 InstructionSelectorMulDivTest; | |
336 | |
337 | |
338 TEST_P(InstructionSelectorMulDivTest, Parameter) { | |
339 const MachInst2 dpi = GetParam(); | |
340 const MachineType type = dpi.machine_type; | |
341 StreamBuilder m(this, type, type, type); | |
342 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1))); | |
343 Stream s = m.Build(); | |
344 ASSERT_EQ(1U, s.size()); | |
345 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); | |
346 EXPECT_EQ(2U, s[0]->InputCount()); | |
347 EXPECT_EQ(1U, s[0]->OutputCount()); | |
348 } | |
349 | |
350 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorMulDivTest, | |
351 ::testing::ValuesIn(kMulDivInstructions)); | |
352 | |
353 | |
354 // ----------------------------------------------------------------------------- | |
355 // Floating point instructions. | |
356 | |
357 typedef InstructionSelectorTestWithParam<MachInst2> | |
358 InstructionSelectorFPArithTest; | |
359 | |
360 | |
361 TEST_P(InstructionSelectorFPArithTest, Parameter) { | |
362 const MachInst2 fpa = GetParam(); | |
363 StreamBuilder m(this, fpa.machine_type, fpa.machine_type, fpa.machine_type); | |
364 m.Return((m.*fpa.constructor)(m.Parameter(0), m.Parameter(1))); | |
365 Stream s = m.Build(); | |
366 ASSERT_EQ(1U, s.size()); | |
367 EXPECT_EQ(fpa.arch_opcode, s[0]->arch_opcode()); | |
368 EXPECT_EQ(2U, s[0]->InputCount()); | |
369 EXPECT_EQ(1U, s[0]->OutputCount()); | |
370 } | |
371 | |
372 | |
373 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorFPArithTest, | |
374 ::testing::ValuesIn(kFPArithInstructions)); | |
375 | |
376 | |
377 typedef InstructionSelectorTestWithParam<FPCmp> InstructionSelectorFPCmpTest; | |
378 | |
379 | |
380 TEST_P(InstructionSelectorFPCmpTest, Parameter) { | |
381 const FPCmp cmp = GetParam(); | |
382 StreamBuilder m(this, kMachInt32, cmp.mi.machine_type, cmp.mi.machine_type); | |
383 m.Return((m.*cmp.mi.constructor)(m.Parameter(0), m.Parameter(1))); | |
384 Stream s = m.Build(); | |
385 ASSERT_EQ(1U, s.size()); | |
386 EXPECT_EQ(cmp.mi.arch_opcode, s[0]->arch_opcode()); | |
387 EXPECT_EQ(2U, s[0]->InputCount()); | |
388 EXPECT_EQ(1U, s[0]->OutputCount()); | |
389 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); | |
390 EXPECT_EQ(cmp.cond, s[0]->flags_condition()); | |
391 } | |
392 | |
393 | |
394 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorFPCmpTest, | |
395 ::testing::ValuesIn(kFPCmpInstructions)); | |
396 | |
397 | |
398 // ----------------------------------------------------------------------------- | |
399 // Conversions. | |
400 | |
401 typedef InstructionSelectorTestWithParam<Conversion> | |
402 InstructionSelectorConversionTest; | |
403 | |
404 | |
405 TEST_P(InstructionSelectorConversionTest, Parameter) { | |
406 const Conversion conv = GetParam(); | |
407 StreamBuilder m(this, conv.mi.machine_type, conv.src_machine_type); | |
408 m.Return((m.*conv.mi.constructor)(m.Parameter(0))); | |
409 Stream s = m.Build(); | |
410 ASSERT_EQ(1U, s.size()); | |
411 EXPECT_EQ(conv.mi.arch_opcode, s[0]->arch_opcode()); | |
412 EXPECT_EQ(1U, s[0]->InputCount()); | |
413 EXPECT_EQ(1U, s[0]->OutputCount()); | |
414 } | |
415 | |
416 | |
417 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, | |
418 InstructionSelectorConversionTest, | |
419 ::testing::ValuesIn(kConversionInstructions)); | |
420 | |
421 | |
422 // ----------------------------------------------------------------------------- | |
423 // Memory access instructions. | |
424 | |
425 | |
426 namespace { | |
427 | |
428 struct MemoryAccess { | |
429 MachineType type; | |
430 ArchOpcode ldr_opcode; | |
431 ArchOpcode str_opcode; | |
432 }; | |
433 | |
434 | |
435 std::ostream& operator<<(std::ostream& os, const MemoryAccess& memacc) { | |
436 OStringStream ost; | |
437 ost << memacc.type; | |
438 return os << ost.c_str(); | |
439 } | |
440 | |
441 } // namespace | |
442 | |
443 | |
444 static const MemoryAccess kMemoryAccesses[] = { | |
445 {kMachInt8, kArm64Ldrsb, kArm64Strb}, | |
446 {kMachUint8, kArm64Ldrb, kArm64Strb}, | |
447 {kMachInt16, kArm64Ldrsh, kArm64Strh}, | |
448 {kMachUint16, kArm64Ldrh, kArm64Strh}, | |
449 {kMachInt32, kArm64LdrW, kArm64StrW}, | |
450 {kMachUint32, kArm64LdrW, kArm64StrW}, | |
451 {kMachInt64, kArm64Ldr, kArm64Str}, | |
452 {kMachUint64, kArm64Ldr, kArm64Str}, | |
453 {kMachFloat32, kArm64LdrS, kArm64StrS}, | |
454 {kMachFloat64, kArm64LdrD, kArm64StrD}}; | |
455 | |
456 | |
457 typedef InstructionSelectorTestWithParam<MemoryAccess> | |
458 InstructionSelectorMemoryAccessTest; | |
459 | |
460 | |
461 TEST_P(InstructionSelectorMemoryAccessTest, LoadWithParameters) { | |
462 const MemoryAccess memacc = GetParam(); | |
463 StreamBuilder m(this, memacc.type, kMachPtr, kMachInt32); | |
464 m.Return(m.Load(memacc.type, m.Parameter(0), m.Parameter(1))); | |
465 Stream s = m.Build(); | |
466 ASSERT_EQ(1U, s.size()); | |
467 EXPECT_EQ(memacc.ldr_opcode, s[0]->arch_opcode()); | |
468 EXPECT_EQ(kMode_MRR, s[0]->addressing_mode()); | |
469 EXPECT_EQ(2U, s[0]->InputCount()); | |
470 EXPECT_EQ(1U, s[0]->OutputCount()); | |
471 } | |
472 | |
473 | |
474 TEST_P(InstructionSelectorMemoryAccessTest, StoreWithParameters) { | |
475 const MemoryAccess memacc = GetParam(); | |
476 StreamBuilder m(this, kMachInt32, kMachPtr, kMachInt32, memacc.type); | |
477 m.Store(memacc.type, m.Parameter(0), m.Parameter(1), m.Parameter(2)); | |
478 m.Return(m.Int32Constant(0)); | |
479 Stream s = m.Build(); | |
480 ASSERT_EQ(1U, s.size()); | |
481 EXPECT_EQ(memacc.str_opcode, s[0]->arch_opcode()); | |
482 EXPECT_EQ(kMode_MRR, s[0]->addressing_mode()); | |
483 EXPECT_EQ(3U, s[0]->InputCount()); | |
484 EXPECT_EQ(0U, s[0]->OutputCount()); | |
485 } | |
486 | |
487 | |
488 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, | |
489 InstructionSelectorMemoryAccessTest, | |
490 ::testing::ValuesIn(kMemoryAccesses)); | |
491 | |
492 } // namespace compiler | |
493 } // namespace internal | |
494 } // namespace v8 | |
OLD | NEW |