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 "src/compiler/instruction-selector-unittest.h" | |
6 | |
7 namespace v8 { | |
8 namespace internal { | |
9 namespace compiler { | |
10 | |
11 namespace { | |
12 | |
13 template <typename T> | |
14 struct MachInst { | |
15 T constructor; | |
16 const char* constructor_name; | |
17 ArchOpcode arch_opcode; | |
18 MachineType machine_type; | |
19 }; | |
20 | |
Benedikt Meurer
2014/09/25 05:37:11
You should add std::ostream& operator<<(std::ostre
paul.l...
2014/09/25 17:18:39
Done.
| |
21 typedef MachInst<Node* (RawMachineAssembler::*)(Node*)> MachInst1; | |
22 typedef MachInst<Node* (RawMachineAssembler::*)(Node*, Node*)> MachInst2; | |
23 | |
24 // To avoid duplicated code IntCmp helper structure | |
25 // is created. It contains MachInst2 with two nodes and expected_size | |
26 // because different cmp instructions have different size. | |
27 struct IntCmp { | |
28 MachInst2 mi; | |
29 uint32_t expected_size; | |
30 }; | |
31 | |
32 struct FPCmp { | |
33 MachInst2 mi; | |
34 FlagsCondition cond; | |
35 }; | |
36 | |
37 static const FPCmp kFPCmpInstructions[] = { | |
Benedikt Meurer
2014/09/25 05:37:11
Nit: no need to use static, it's in an anonymous n
paul.l...
2014/09/25 17:18:39
Done.
| |
38 {{&RawMachineAssembler::Float64Equal, "Float64Equal", kMipsFloat64Cmp, | |
39 kMachFloat64}, | |
40 kUnorderedEqual}, | |
41 {{&RawMachineAssembler::Float64LessThan, "Float64LessThan", kMipsFloat64Cmp, | |
42 kMachFloat64}, | |
43 kUnorderedLessThan}, | |
44 {{&RawMachineAssembler::Float64LessThanOrEqual, "Float64LessThanOrEqual", | |
45 kMipsFloat64Cmp, kMachFloat64}, | |
46 kUnorderedLessThanOrEqual}, | |
47 {{&RawMachineAssembler::Float64GreaterThan, "Float64GreaterThan", | |
48 kMipsFloat64Cmp, kMachFloat64}, | |
49 kUnorderedLessThan}, | |
50 {{&RawMachineAssembler::Float64GreaterThanOrEqual, | |
51 "Float64GreaterThanOrEqual", kMipsFloat64Cmp, kMachFloat64}, | |
52 kUnorderedLessThanOrEqual}}; | |
53 | |
54 struct Conversion { | |
55 // The machine_type field in MachInst1 represents the destination type. | |
56 MachInst1 mi; | |
57 MachineType src_machine_type; | |
58 }; | |
59 | |
60 | |
61 // ---------------------------------------------------------------------------- | |
62 // Logical instructions. | |
63 // ---------------------------------------------------------------------------- | |
64 | |
65 | |
66 static const MachInst2 kLogicalInstructions[] = { | |
Benedikt Meurer
2014/09/25 05:37:11
Nit: no need to use static, it's in an anonymous n
paul.l...
2014/09/25 17:18:40
Done.
| |
67 {&RawMachineAssembler::WordAnd, "WordAnd", kMipsAnd, kMachInt16}, | |
68 {&RawMachineAssembler::WordOr, "WordOr", kMipsOr, kMachInt16}, | |
69 {&RawMachineAssembler::WordXor, "WordXor", kMipsXor, kMachInt16}, | |
70 {&RawMachineAssembler::Word32And, "Word32And", kMipsAnd, kMachInt32}, | |
71 {&RawMachineAssembler::Word32Or, "Word32Or", kMipsOr, kMachInt32}, | |
72 {&RawMachineAssembler::Word32Xor, "Word32Xor", kMipsXor, kMachInt32}}; | |
73 | |
74 | |
75 // ---------------------------------------------------------------------------- | |
76 // Shift instructions. | |
77 // ---------------------------------------------------------------------------- | |
78 | |
79 | |
80 static const MachInst2 kShiftInstructions[] = { | |
Benedikt Meurer
2014/09/25 05:37:11
Nit: no need to use static, it's in an anonymous n
paul.l...
2014/09/25 17:18:39
Done.
| |
81 {&RawMachineAssembler::WordShl, "WordShl", kMipsShl, kMachInt16}, | |
82 {&RawMachineAssembler::WordShr, "WordShr", kMipsShr, kMachInt16}, | |
83 {&RawMachineAssembler::WordSar, "WordSar", kMipsSar, kMachInt16}, | |
84 {&RawMachineAssembler::WordRor, "WordRor", kMipsRor, kMachInt16}, | |
85 {&RawMachineAssembler::Word32Shl, "Word32Shl", kMipsShl, kMachInt32}, | |
86 {&RawMachineAssembler::Word32Shr, "Word32Shr", kMipsShr, kMachInt32}, | |
87 {&RawMachineAssembler::Word32Sar, "Word32Sar", kMipsSar, kMachInt32}, | |
88 {&RawMachineAssembler::Word32Ror, "Word32Ror", kMipsRor, kMachInt32}}; | |
89 | |
90 | |
91 // ---------------------------------------------------------------------------- | |
92 // MUL/DIV instructions. | |
93 // ---------------------------------------------------------------------------- | |
94 | |
95 | |
96 static const MachInst2 kMulDivInstructions[] = { | |
Benedikt Meurer
2014/09/25 05:37:11
Nit: no need to use static, it's in an anonymous n
paul.l...
2014/09/25 17:18:39
Done.
| |
97 {&RawMachineAssembler::Int32Mul, "Int32Mul", kMipsMul, kMachInt32}, | |
98 {&RawMachineAssembler::Int32Div, "Int32Div", kMipsDiv, kMachInt32}, | |
99 {&RawMachineAssembler::Int32UDiv, "Int32UDiv", kMipsDivU, kMachUint32}, | |
100 {&RawMachineAssembler::Float64Mul, "Float64Mul", kMipsFloat64Mul, | |
101 kMachFloat64}, | |
102 {&RawMachineAssembler::Float64Div, "Float64Div", kMipsFloat64Div, | |
103 kMachFloat64}}; | |
104 | |
105 | |
106 // ---------------------------------------------------------------------------- | |
107 // MOD instructions. | |
108 // ---------------------------------------------------------------------------- | |
109 | |
110 | |
111 static const MachInst2 kModInstructions[] = { | |
Benedikt Meurer
2014/09/25 05:37:11
Nit: no need to use static, it's in an anonymous n
paul.l...
2014/09/25 17:18:39
Done.
| |
112 {&RawMachineAssembler::Int32Mod, "Int32Mod", kMipsMod, kMachInt32}, | |
113 {&RawMachineAssembler::Int32UMod, "Int32UMod", kMipsModU, kMachInt32}, | |
114 {&RawMachineAssembler::Float64Mod, "Float64Mod", kMipsFloat64Mod, | |
115 kMachFloat64}}; | |
116 | |
117 | |
118 // ---------------------------------------------------------------------------- | |
119 // Arithmetic FPU instructions. | |
120 // ---------------------------------------------------------------------------- | |
121 | |
122 | |
123 static const MachInst2 kFPArithInstructions[] = { | |
Benedikt Meurer
2014/09/25 05:37:11
Nit: no need to use static, it's in an anonymous n
paul.l...
2014/09/25 17:18:39
Done.
| |
124 {&RawMachineAssembler::Float64Add, "Float64Add", kMipsFloat64Add, | |
125 kMachFloat64}, | |
126 {&RawMachineAssembler::Float64Sub, "Float64Sub", kMipsFloat64Sub, | |
127 kMachFloat64}}; | |
128 | |
129 | |
130 // ---------------------------------------------------------------------------- | |
131 // IntArithTest instructions, two nodes. | |
132 // ---------------------------------------------------------------------------- | |
133 | |
134 | |
135 static const MachInst2 kAddSubInstructions[] = { | |
Benedikt Meurer
2014/09/25 05:37:11
Nit: no need to use static, it's in an anonymous n
paul.l...
2014/09/25 17:18:39
Done.
| |
136 {&RawMachineAssembler::Int32Add, "Int32Add", kMipsAdd, kMachInt32}, | |
137 {&RawMachineAssembler::Int32Sub, "Int32Sub", kMipsSub, kMachInt32}, | |
138 {&RawMachineAssembler::Int32AddWithOverflow, "Int32AddWithOverflow", | |
139 kMipsAddOvf, kMachInt32}, | |
140 {&RawMachineAssembler::Int32SubWithOverflow, "Int32SubWithOverflow", | |
141 kMipsSubOvf, kMachInt32}}; | |
142 | |
143 | |
144 // ---------------------------------------------------------------------------- | |
145 // IntArithTest instructions, one node. | |
146 // ---------------------------------------------------------------------------- | |
147 | |
148 | |
149 static const MachInst1 kAddSubOneInstructions[] = { | |
Benedikt Meurer
2014/09/25 05:37:11
Nit: no need to use static, it's in an anonymous n
paul.l...
2014/09/25 17:18:39
Done.
| |
150 {&RawMachineAssembler::Int32Neg, "Int32Neg", kMipsSub, kMachInt32}, | |
151 // TODO(dusmil): check this ... | |
152 // {&RawMachineAssembler::WordEqual , "WordEqual" , kMipsTst, kMachInt32} | |
153 }; | |
154 | |
155 | |
156 // ---------------------------------------------------------------------------- | |
157 // Arithmetic compare instructions. | |
158 // ---------------------------------------------------------------------------- | |
159 | |
160 | |
161 static const IntCmp kCmpInstructions[] = { | |
Benedikt Meurer
2014/09/25 05:37:11
Nit: no need to use static, it's in an anonymous n
paul.l...
2014/09/25 17:18:39
Done.
| |
162 {{&RawMachineAssembler::WordEqual, "WordEqual", kMipsCmp, kMachInt16}, 1U}, | |
163 {{&RawMachineAssembler::WordNotEqual, "WordNotEqual", kMipsCmp, kMachInt16}, | |
164 2U}, | |
165 {{&RawMachineAssembler::Word32Equal, "Word32Equal", kMipsCmp, kMachInt32}, | |
166 1U}, | |
167 {{&RawMachineAssembler::Word32NotEqual, "Word32NotEqual", kMipsCmp, | |
168 kMachInt32}, | |
169 2U}, | |
170 {{&RawMachineAssembler::Int32LessThan, "Int32LessThan", kMipsCmp, | |
171 kMachInt32}, | |
172 1U}, | |
173 {{&RawMachineAssembler::Int32LessThanOrEqual, "Int32LessThanOrEqual", | |
174 kMipsCmp, kMachInt32}, | |
175 1U}, | |
176 {{&RawMachineAssembler::Int32GreaterThan, "Int32GreaterThan", kMipsCmp, | |
177 kMachInt32}, | |
178 1U}, | |
179 {{&RawMachineAssembler::Int32GreaterThanOrEqual, "Int32GreaterThanOrEqual", | |
180 kMipsCmp, kMachInt32}, | |
181 1U}, | |
182 {{&RawMachineAssembler::Uint32LessThan, "Uint32LessThan", kMipsCmp, | |
183 kMachUint32}, | |
184 1U}, | |
185 {{&RawMachineAssembler::Uint32LessThanOrEqual, "Uint32LessThanOrEqual", | |
186 kMipsCmp, kMachUint32}, | |
187 1U}}; | |
188 | |
189 | |
190 // ---------------------------------------------------------------------------- | |
191 // Conversion instructions. | |
192 // ---------------------------------------------------------------------------- | |
193 | |
194 static const Conversion kConversionInstructions[] = { | |
Benedikt Meurer
2014/09/25 05:37:11
Nit: no need to use static, it's in an anonymous n
paul.l...
2014/09/25 17:18:40
Done.
| |
195 // Conversion instructions are related to machine_operator.h: | |
196 // FPU conversions: | |
197 // Convert representation of integers between float64 and int32/uint32. | |
198 // The precise rounding mode and handling of out of range inputs are *not* | |
199 // defined for these operators, since they are intended only for use with | |
200 // integers. | |
201 // mips instruction: cvt_d_w | |
202 {{&RawMachineAssembler::ChangeInt32ToFloat64, "ChangeInt32ToFloat64", | |
203 kMipsInt32ToFloat64, kMachFloat64}, | |
204 kMachInt32}, | |
205 | |
206 // mips instruction: cvt_d_uw | |
207 {{&RawMachineAssembler::ChangeUint32ToFloat64, "ChangeUint32ToFloat64", | |
208 kMipsUint32ToFloat64, kMachFloat64}, | |
209 kMachInt32}, | |
210 | |
211 // mips instruction: trunc_w_d | |
212 {{&RawMachineAssembler::ChangeFloat64ToInt32, "ChangeFloat64ToInt32", | |
213 kMipsFloat64ToInt32, kMachFloat64}, | |
214 kMachInt32}, | |
215 | |
216 // mips instruction: trunc_uw_d | |
217 {{&RawMachineAssembler::ChangeFloat64ToUint32, "ChangeFloat64ToUint32", | |
218 kMipsFloat64ToUint32, kMachFloat64}, | |
219 kMachInt32}}; | |
220 | |
221 } // namespace | |
222 | |
223 | |
224 typedef InstructionSelectorTestWithParam<FPCmp> InstructionSelectorFPCmpTest; | |
225 | |
226 | |
227 TEST_P(InstructionSelectorFPCmpTest, Parameter) { | |
228 const FPCmp cmp = GetParam(); | |
229 StreamBuilder m(this, kMachInt32, cmp.mi.machine_type, cmp.mi.machine_type); | |
230 m.Return((m.*cmp.mi.constructor)(m.Parameter(0), m.Parameter(1))); | |
231 Stream s = m.Build(); | |
232 ASSERT_EQ(1U, s.size()); | |
233 EXPECT_EQ(cmp.mi.arch_opcode, s[0]->arch_opcode()); | |
234 EXPECT_EQ(2U, s[0]->InputCount()); | |
235 EXPECT_EQ(1U, s[0]->OutputCount()); | |
236 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); | |
237 EXPECT_EQ(cmp.cond, s[0]->flags_condition()); | |
238 } | |
239 | |
240 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorFPCmpTest, | |
241 ::testing::ValuesIn(kFPCmpInstructions)); | |
242 | |
243 | |
244 // ---------------------------------------------------------------------------- | |
245 // Arithmetic compare instructions integers. | |
246 // ---------------------------------------------------------------------------- | |
247 | |
248 | |
249 typedef InstructionSelectorTestWithParam<IntCmp> InstructionSelectorCmpTest; | |
250 | |
251 | |
252 TEST_P(InstructionSelectorCmpTest, Parameter) { | |
253 const IntCmp cmp = GetParam(); | |
254 const MachineType type = cmp.mi.machine_type; | |
255 StreamBuilder m(this, type, type, type); | |
256 m.Return((m.*cmp.mi.constructor)(m.Parameter(0), m.Parameter(1))); | |
257 Stream s = m.Build(); | |
258 ASSERT_EQ(cmp.expected_size, s.size()); | |
259 EXPECT_EQ(cmp.mi.arch_opcode, s[0]->arch_opcode()); | |
260 EXPECT_EQ(2U, s[0]->InputCount()); | |
261 EXPECT_EQ(1U, s[0]->OutputCount()); | |
262 } | |
263 | |
264 | |
265 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorCmpTest, | |
266 ::testing::ValuesIn(kCmpInstructions)); | |
267 | |
268 | |
269 // ---------------------------------------------------------------------------- | |
270 // Shift instructions. | |
271 // ---------------------------------------------------------------------------- | |
272 | |
273 | |
274 typedef InstructionSelectorTestWithParam<MachInst2> | |
275 InstructionSelectorShiftTest; | |
276 | |
277 | |
278 TEST_P(InstructionSelectorShiftTest, Immediate) { | |
279 const MachInst2 dpi = GetParam(); | |
280 const MachineType type = dpi.machine_type; | |
281 TRACED_FORRANGE(int32_t, imm, 0, (ElementSizeOf(type) * 8) - 1) { | |
282 StreamBuilder m(this, type, type); | |
283 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm))); | |
284 Stream s = m.Build(); | |
285 ASSERT_EQ(1U, s.size()); | |
286 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); | |
287 EXPECT_EQ(2U, s[0]->InputCount()); | |
288 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate()); | |
289 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); | |
290 EXPECT_EQ(1U, s[0]->OutputCount()); | |
291 } | |
292 } | |
293 | |
294 | |
295 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorShiftTest, | |
296 ::testing::ValuesIn(kShiftInstructions)); | |
297 | |
298 | |
299 // ---------------------------------------------------------------------------- | |
300 // Logical instructions. | |
301 // ---------------------------------------------------------------------------- | |
302 | |
303 | |
304 typedef InstructionSelectorTestWithParam<MachInst2> | |
305 InstructionSelectorLogicalTest; | |
306 | |
307 | |
308 TEST_P(InstructionSelectorLogicalTest, Parameter) { | |
309 const MachInst2 dpi = GetParam(); | |
310 const MachineType type = dpi.machine_type; | |
311 StreamBuilder m(this, type, type, type); | |
312 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1))); | |
313 Stream s = m.Build(); | |
314 ASSERT_EQ(1U, s.size()); | |
315 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); | |
316 EXPECT_EQ(2U, s[0]->InputCount()); | |
317 EXPECT_EQ(1U, s[0]->OutputCount()); | |
318 } | |
319 | |
320 | |
321 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorLogicalTest, | |
322 ::testing::ValuesIn(kLogicalInstructions)); | |
323 | |
324 | |
325 // ---------------------------------------------------------------------------- | |
326 // MUL/DIV instructions. | |
327 // ---------------------------------------------------------------------------- | |
328 | |
329 | |
330 typedef InstructionSelectorTestWithParam<MachInst2> | |
331 InstructionSelectorMulDivTest; | |
332 | |
333 | |
334 TEST_P(InstructionSelectorMulDivTest, Parameter) { | |
335 const MachInst2 dpi = GetParam(); | |
336 const MachineType type = dpi.machine_type; | |
337 StreamBuilder m(this, type, type, type); | |
338 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1))); | |
339 Stream s = m.Build(); | |
340 ASSERT_EQ(1U, s.size()); | |
341 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); | |
342 EXPECT_EQ(2U, s[0]->InputCount()); | |
343 EXPECT_EQ(1U, s[0]->OutputCount()); | |
344 } | |
345 | |
346 | |
347 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorMulDivTest, | |
348 ::testing::ValuesIn(kMulDivInstructions)); | |
349 | |
350 | |
351 // ---------------------------------------------------------------------------- | |
352 // MOD instructions. | |
353 // ---------------------------------------------------------------------------- | |
354 | |
355 | |
356 typedef InstructionSelectorTestWithParam<MachInst2> InstructionSelectorModTest; | |
357 | |
358 | |
359 TEST_P(InstructionSelectorModTest, Parameter) { | |
360 const MachInst2 dpi = GetParam(); | |
361 const MachineType type = dpi.machine_type; | |
362 StreamBuilder m(this, type, type, type); | |
363 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1))); | |
364 Stream s = m.Build(); | |
365 ASSERT_EQ(1U, s.size()); | |
366 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); | |
367 EXPECT_EQ(2U, s[0]->InputCount()); | |
368 EXPECT_EQ(1U, s[0]->OutputCount()); | |
369 } | |
370 | |
371 | |
372 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorModTest, | |
373 ::testing::ValuesIn(kModInstructions)); | |
374 | |
375 | |
376 // ---------------------------------------------------------------------------- | |
377 // Floating point instructions. | |
378 // ---------------------------------------------------------------------------- | |
379 | |
380 | |
381 typedef InstructionSelectorTestWithParam<MachInst2> | |
382 InstructionSelectorFPArithTest; | |
383 | |
384 | |
385 TEST_P(InstructionSelectorFPArithTest, Parameter) { | |
386 const MachInst2 fpa = GetParam(); | |
387 StreamBuilder m(this, fpa.machine_type, fpa.machine_type, fpa.machine_type); | |
388 m.Return((m.*fpa.constructor)(m.Parameter(0), m.Parameter(1))); | |
389 Stream s = m.Build(); | |
390 ASSERT_EQ(1U, s.size()); | |
391 EXPECT_EQ(fpa.arch_opcode, s[0]->arch_opcode()); | |
392 EXPECT_EQ(2U, s[0]->InputCount()); | |
393 EXPECT_EQ(1U, s[0]->OutputCount()); | |
394 } | |
395 | |
396 | |
397 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorFPArithTest, | |
398 ::testing::ValuesIn(kFPArithInstructions)); | |
399 | |
400 | |
401 // ---------------------------------------------------------------------------- | |
402 // Integer arithmetic. | |
403 // ---------------------------------------------------------------------------- | |
404 | |
405 | |
406 typedef InstructionSelectorTestWithParam<MachInst2> | |
407 InstructionSelectorIntArithTwoTest; | |
408 | |
409 | |
410 TEST_P(InstructionSelectorIntArithTwoTest, Parameter) { | |
411 const MachInst2 intpa = GetParam(); | |
412 StreamBuilder m(this, intpa.machine_type, intpa.machine_type, | |
413 intpa.machine_type); | |
414 m.Return((m.*intpa.constructor)(m.Parameter(0), m.Parameter(1))); | |
415 Stream s = m.Build(); | |
416 ASSERT_EQ(1U, s.size()); | |
417 EXPECT_EQ(intpa.arch_opcode, s[0]->arch_opcode()); | |
418 EXPECT_EQ(2U, s[0]->InputCount()); | |
419 EXPECT_EQ(1U, s[0]->OutputCount()); | |
420 } | |
421 | |
422 | |
423 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, | |
424 InstructionSelectorIntArithTwoTest, | |
425 ::testing::ValuesIn(kAddSubInstructions)); | |
426 | |
427 | |
428 // ---------------------------------------------------------------------------- | |
429 // One node. | |
430 // ---------------------------------------------------------------------------- | |
431 | |
432 | |
433 typedef InstructionSelectorTestWithParam<MachInst1> | |
434 InstructionSelectorIntArithOneTest; | |
435 | |
436 | |
437 TEST_P(InstructionSelectorIntArithOneTest, Parameter) { | |
438 const MachInst1 intpa = GetParam(); | |
439 StreamBuilder m(this, intpa.machine_type, intpa.machine_type, | |
440 intpa.machine_type); | |
441 m.Return((m.*intpa.constructor)(m.Parameter(0))); | |
442 Stream s = m.Build(); | |
443 ASSERT_EQ(1U, s.size()); | |
444 EXPECT_EQ(intpa.arch_opcode, s[0]->arch_opcode()); | |
445 EXPECT_EQ(2U, s[0]->InputCount()); | |
446 EXPECT_EQ(1U, s[0]->OutputCount()); | |
447 } | |
448 | |
449 | |
450 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, | |
451 InstructionSelectorIntArithOneTest, | |
452 ::testing::ValuesIn(kAddSubOneInstructions)); | |
453 | |
454 | |
455 // ---------------------------------------------------------------------------- | |
456 // Conversions. | |
457 // ---------------------------------------------------------------------------- | |
458 | |
459 | |
460 typedef InstructionSelectorTestWithParam<Conversion> | |
461 InstructionSelectorConversionTest; | |
462 | |
463 | |
464 TEST_P(InstructionSelectorConversionTest, Parameter) { | |
465 const Conversion conv = GetParam(); | |
466 StreamBuilder m(this, conv.mi.machine_type, conv.src_machine_type); | |
467 m.Return((m.*conv.mi.constructor)(m.Parameter(0))); | |
468 Stream s = m.Build(); | |
469 ASSERT_EQ(1U, s.size()); | |
470 EXPECT_EQ(conv.mi.arch_opcode, s[0]->arch_opcode()); | |
471 EXPECT_EQ(1U, s[0]->InputCount()); | |
472 EXPECT_EQ(1U, s[0]->OutputCount()); | |
473 } | |
474 | |
475 | |
476 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, | |
477 InstructionSelectorConversionTest, | |
478 ::testing::ValuesIn(kConversionInstructions)); | |
479 | |
480 | |
481 // ---------------------------------------------------------------------------- | |
482 // Loads and stores. | |
483 // ---------------------------------------------------------------------------- | |
484 | |
485 namespace { | |
486 | |
487 struct MemoryAccess { | |
488 MachineType type; | |
489 ArchOpcode load_opcode; | |
490 ArchOpcode store_opcode; | |
491 }; | |
492 | |
493 | |
494 static const MemoryAccess kMemoryAccesses[] = { | |
495 {kMachInt8, kMipsLb, kMipsSb}, | |
496 {kMachUint8, kMipsLbu, kMipsSb}, | |
497 {kMachInt16, kMipsLh, kMipsSh}, | |
498 {kMachUint16, kMipsLhu, kMipsSh}, | |
499 {kMachInt32, kMipsLw, kMipsSw}, | |
500 {kRepFloat32, kMipsLwc1, kMipsSwc1}, | |
501 {kRepFloat64, kMipsLdc1, kMipsSdc1}}; | |
502 | |
503 | |
504 struct MemoryAccessImm { | |
505 MachineType type; | |
506 ArchOpcode load_opcode; | |
507 ArchOpcode store_opcode; | |
508 bool (InstructionSelectorTest::Stream::*val_predicate)( | |
509 const InstructionOperand*) const; | |
510 const int32_t immediates[40]; | |
511 }; | |
512 | |
Benedikt Meurer
2014/09/25 05:37:11
You should add
std::ostream& operator<<(std::ostr
paul.l...
2014/09/25 17:18:39
Done.
| |
513 | |
514 struct MemoryAccessImm1 { | |
515 MachineType type; | |
516 ArchOpcode load_opcode; | |
517 ArchOpcode store_opcode; | |
518 bool (InstructionSelectorTest::Stream::*val_predicate)( | |
519 const InstructionOperand*) const; | |
520 const int32_t immediates[5]; | |
521 }; | |
522 | |
Benedikt Meurer
2014/09/25 05:37:11
Stream operator, see above.
paul.l...
2014/09/25 17:18:39
Done.
| |
523 | |
524 // ---------------------------------------------------------------------------- | |
525 // Loads and stores immediate values. | |
526 // ---------------------------------------------------------------------------- | |
527 | |
528 | |
529 static const MemoryAccessImm kMemoryAccessesImm[] = { | |
Benedikt Meurer
2014/09/25 05:37:11
Nit: static, see above.
paul.l...
2014/09/25 17:18:40
Done.
| |
530 {kMachInt8, | |
531 kMipsLb, | |
532 kMipsSb, | |
533 &InstructionSelectorTest::Stream::IsInteger, | |
534 {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89, | |
535 -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109, | |
536 115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}}, | |
537 {kMachUint8, | |
538 kMipsLbu, | |
539 kMipsSb, | |
540 &InstructionSelectorTest::Stream::IsInteger, | |
541 {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89, | |
542 -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109, | |
543 115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}}, | |
544 {kMachInt16, | |
545 kMipsLh, | |
546 kMipsSh, | |
547 &InstructionSelectorTest::Stream::IsInteger, | |
548 {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89, | |
549 -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109, | |
550 115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}}, | |
551 {kMachUint16, | |
552 kMipsLhu, | |
553 kMipsSh, | |
554 &InstructionSelectorTest::Stream::IsInteger, | |
555 {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89, | |
556 -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109, | |
557 115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}}, | |
558 {kMachInt32, | |
559 kMipsLw, | |
560 kMipsSw, | |
561 &InstructionSelectorTest::Stream::IsInteger, | |
562 {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89, | |
563 -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109, | |
564 115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}}, | |
565 {kMachFloat32, | |
566 kMipsLwc1, | |
567 kMipsSwc1, | |
568 &InstructionSelectorTest::Stream::IsDouble, | |
569 {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89, | |
570 -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109, | |
571 115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}}, | |
572 {kMachFloat64, | |
573 kMipsLdc1, | |
574 kMipsSdc1, | |
575 &InstructionSelectorTest::Stream::IsDouble, | |
576 {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89, | |
577 -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109, | |
578 115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}}}; | |
579 | |
580 | |
581 static const MemoryAccessImm1 kMemoryAccessImmMoreThan16bit[] = { | |
Benedikt Meurer
2014/09/25 05:37:11
Nit: static, see above.
paul.l...
2014/09/25 17:18:39
Done.
| |
582 {kMachInt8, | |
583 kMipsLb, | |
584 kMipsSb, | |
585 &InstructionSelectorTest::Stream::IsInteger, | |
586 {-65000, -55000, 32777, 55000, 65000}}, | |
587 {kMachInt8, | |
588 kMipsLbu, | |
589 kMipsSb, | |
590 &InstructionSelectorTest::Stream::IsInteger, | |
591 {-65000, -55000, 32777, 55000, 65000}}, | |
592 {kMachInt16, | |
593 kMipsLh, | |
594 kMipsSh, | |
595 &InstructionSelectorTest::Stream::IsInteger, | |
596 {-65000, -55000, 32777, 55000, 65000}}, | |
597 {kMachInt16, | |
598 kMipsLhu, | |
599 kMipsSh, | |
600 &InstructionSelectorTest::Stream::IsInteger, | |
601 {-65000, -55000, 32777, 55000, 65000}}, | |
602 {kMachInt32, | |
603 kMipsLw, | |
604 kMipsSw, | |
605 &InstructionSelectorTest::Stream::IsInteger, | |
606 {-65000, -55000, 32777, 55000, 65000}}, | |
607 {kMachFloat32, | |
608 kMipsLwc1, | |
609 kMipsSwc1, | |
610 &InstructionSelectorTest::Stream::IsDouble, | |
611 {-65000, -55000, 32777, 55000, 65000}}, | |
612 {kMachFloat64, | |
613 kMipsLdc1, | |
614 kMipsSdc1, | |
615 &InstructionSelectorTest::Stream::IsDouble, | |
616 {-65000, -55000, 32777, 55000, 65000}}}; | |
617 | |
618 } // namespace | |
619 | |
620 | |
621 typedef InstructionSelectorTestWithParam<MemoryAccess> | |
622 InstructionSelectorMemoryAccessTest; | |
623 | |
624 | |
625 TEST_P(InstructionSelectorMemoryAccessTest, LoadWithParameters) { | |
626 const MemoryAccess memacc = GetParam(); | |
627 StreamBuilder m(this, memacc.type, kMachPtr, kMachInt32); | |
628 m.Return(m.Load(memacc.type, m.Parameter(0))); | |
629 Stream s = m.Build(); | |
630 ASSERT_EQ(1U, s.size()); | |
631 EXPECT_EQ(memacc.load_opcode, s[0]->arch_opcode()); | |
632 EXPECT_EQ(kMode_MRI, s[0]->addressing_mode()); | |
633 } | |
634 | |
635 | |
636 TEST_P(InstructionSelectorMemoryAccessTest, StoreWithParameters) { | |
637 const MemoryAccess memacc = GetParam(); | |
638 StreamBuilder m(this, kMachInt32, kMachPtr, kMachInt32, memacc.type); | |
639 m.Store(memacc.type, m.Parameter(0), m.Parameter(1)); | |
640 m.Return(m.Int32Constant(0)); | |
641 Stream s = m.Build(); | |
642 ASSERT_EQ(1U, s.size()); | |
643 EXPECT_EQ(memacc.store_opcode, s[0]->arch_opcode()); | |
644 EXPECT_EQ(kMode_MRI, s[0]->addressing_mode()); | |
645 } | |
646 | |
647 | |
648 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, | |
649 InstructionSelectorMemoryAccessTest, | |
650 ::testing::ValuesIn(kMemoryAccesses)); | |
651 | |
652 | |
653 // ---------------------------------------------------------------------------- | |
654 // Load immediate. | |
655 // ---------------------------------------------------------------------------- | |
656 | |
657 | |
658 typedef InstructionSelectorTestWithParam<MemoryAccessImm> | |
659 InstructionSelectorMemoryAccessImmTest; | |
660 | |
661 | |
662 TEST_P(InstructionSelectorMemoryAccessImmTest, LoadWithImmediateIndex) { | |
663 const MemoryAccessImm memacc = GetParam(); | |
664 TRACED_FOREACH(int32_t, index, memacc.immediates) { | |
665 StreamBuilder m(this, memacc.type, kMachPtr); | |
666 m.Return(m.Load(memacc.type, m.Parameter(0), m.Int32Constant(index))); | |
667 Stream s = m.Build(); | |
668 ASSERT_EQ(1U, s.size()); | |
669 EXPECT_EQ(memacc.load_opcode, s[0]->arch_opcode()); | |
670 EXPECT_EQ(kMode_MRI, s[0]->addressing_mode()); | |
671 ASSERT_EQ(2U, s[0]->InputCount()); | |
672 ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind()); | |
673 EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1))); | |
674 ASSERT_EQ(1U, s[0]->OutputCount()); | |
675 EXPECT_TRUE((s.*memacc.val_predicate)(s[0]->Output())); | |
676 } | |
677 } | |
678 | |
679 | |
680 // ---------------------------------------------------------------------------- | |
681 // Store immediate. | |
682 // ---------------------------------------------------------------------------- | |
683 | |
684 | |
685 TEST_P(InstructionSelectorMemoryAccessImmTest, StoreWithImmediateIndex) { | |
686 const MemoryAccessImm memacc = GetParam(); | |
687 TRACED_FOREACH(int32_t, index, memacc.immediates) { | |
688 StreamBuilder m(this, kMachInt32, kMachPtr, memacc.type); | |
689 m.Store(memacc.type, m.Parameter(0), m.Int32Constant(index), | |
690 m.Parameter(1)); | |
691 m.Return(m.Int32Constant(0)); | |
692 Stream s = m.Build(); | |
693 ASSERT_EQ(1U, s.size()); | |
694 EXPECT_EQ(memacc.store_opcode, s[0]->arch_opcode()); | |
695 EXPECT_EQ(kMode_MRI, s[0]->addressing_mode()); | |
696 ASSERT_EQ(3U, s[0]->InputCount()); | |
697 ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind()); | |
698 EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1))); | |
699 EXPECT_EQ(0U, s[0]->OutputCount()); | |
700 } | |
701 } | |
702 | |
703 | |
704 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, | |
705 InstructionSelectorMemoryAccessImmTest, | |
706 ::testing::ValuesIn(kMemoryAccessesImm)); | |
707 | |
708 | |
709 // ---------------------------------------------------------------------------- | |
710 // Load/store offsets more than 16 bits. | |
711 // ---------------------------------------------------------------------------- | |
712 | |
713 | |
714 typedef InstructionSelectorTestWithParam<MemoryAccessImm1> | |
715 InstructionSelectorMemoryAccessImmMoreThan16bitTest; | |
716 | |
717 | |
718 TEST_P(InstructionSelectorMemoryAccessImmMoreThan16bitTest, | |
719 LoadWithImmediateIndex) { | |
720 const MemoryAccessImm1 memacc = GetParam(); | |
721 TRACED_FOREACH(int32_t, index, memacc.immediates) { | |
722 StreamBuilder m(this, memacc.type, kMachPtr); | |
723 m.Return(m.Load(memacc.type, m.Parameter(0), m.Int32Constant(index))); | |
724 Stream s = m.Build(); | |
725 ASSERT_EQ(2U, s.size()); | |
726 // kMipsAdd is expected opcode. | |
727 // size more than 16 bits wide. | |
728 EXPECT_EQ(kMipsAdd, s[0]->arch_opcode()); | |
729 EXPECT_EQ(kMode_None, s[0]->addressing_mode()); | |
730 EXPECT_EQ(2U, s[0]->InputCount()); | |
731 EXPECT_EQ(1U, s[0]->OutputCount()); | |
732 } | |
733 } | |
734 | |
735 | |
736 TEST_P(InstructionSelectorMemoryAccessImmMoreThan16bitTest, | |
737 StoreWithImmediateIndex) { | |
738 const MemoryAccessImm1 memacc = GetParam(); | |
739 TRACED_FOREACH(int32_t, index, memacc.immediates) { | |
740 StreamBuilder m(this, kMachInt32, kMachPtr, memacc.type); | |
741 m.Store(memacc.type, m.Parameter(0), m.Int32Constant(index), | |
742 m.Parameter(1)); | |
743 m.Return(m.Int32Constant(0)); | |
744 Stream s = m.Build(); | |
745 ASSERT_EQ(2U, s.size()); | |
746 // kMipsAdd is expected opcode | |
747 // size more than 16 bits wide | |
748 EXPECT_EQ(kMipsAdd, s[0]->arch_opcode()); | |
749 EXPECT_EQ(kMode_None, s[0]->addressing_mode()); | |
750 EXPECT_EQ(2U, s[0]->InputCount()); | |
751 EXPECT_EQ(1U, s[0]->OutputCount()); | |
752 } | |
753 } | |
754 | |
755 | |
756 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, | |
757 InstructionSelectorMemoryAccessImmMoreThan16bitTest, | |
758 ::testing::ValuesIn(kMemoryAccessImmMoreThan16bit)); | |
759 | |
760 | |
761 // ---------------------------------------------------------------------------- | |
762 // kMipsTst testing. | |
763 // ---------------------------------------------------------------------------- | |
764 | |
765 | |
766 TEST_F(InstructionSelectorTest, Word32EqualWithZero) { | |
767 { | |
768 StreamBuilder m(this, kMachInt32, kMachInt32); | |
769 m.Return(m.Word32Equal(m.Parameter(0), m.Int32Constant(0))); | |
770 Stream s = m.Build(); | |
771 ASSERT_EQ(1U, s.size()); | |
772 EXPECT_EQ(kMipsTst, s[0]->arch_opcode()); | |
773 EXPECT_EQ(kMode_None, s[0]->addressing_mode()); | |
774 ASSERT_EQ(2U, s[0]->InputCount()); | |
775 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1))); | |
776 EXPECT_EQ(1U, s[0]->OutputCount()); | |
777 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); | |
778 EXPECT_EQ(kEqual, s[0]->flags_condition()); | |
779 } | |
780 { | |
781 StreamBuilder m(this, kMachInt32, kMachInt32); | |
782 m.Return(m.Word32Equal(m.Int32Constant(0), m.Parameter(0))); | |
783 Stream s = m.Build(); | |
784 ASSERT_EQ(1U, s.size()); | |
785 EXPECT_EQ(kMipsTst, s[0]->arch_opcode()); | |
786 EXPECT_EQ(kMode_None, s[0]->addressing_mode()); | |
787 ASSERT_EQ(2U, s[0]->InputCount()); | |
788 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1))); | |
789 EXPECT_EQ(1U, s[0]->OutputCount()); | |
790 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); | |
791 EXPECT_EQ(kEqual, s[0]->flags_condition()); | |
792 } | |
793 } | |
794 | |
795 | |
Benedikt Meurer
2014/09/25 05:37:11
Nit: extra new line :-)
paul.l...
2014/09/25 17:18:39
Done.
| |
796 } // namespace compiler | |
797 } // namespace internal | |
798 } // namespace v8 | |
OLD | NEW |