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 typedef RawMachineAssembler::Label MLabel; | |
14 typedef Node* (RawMachineAssembler::*Constructor)(Node*, Node*); | |
15 | |
16 | |
17 // Data processing instructions. | |
18 struct DPI { | |
19 Constructor constructor; | |
20 const char* constructor_name; | |
21 ArchOpcode arch_opcode; | |
22 ArchOpcode reverse_arch_opcode; | |
23 ArchOpcode test_arch_opcode; | |
24 }; | |
25 | |
26 | |
27 std::ostream& operator<<(std::ostream& os, const DPI& dpi) { | |
28 return os << dpi.constructor_name; | |
29 } | |
30 | |
31 | |
32 static const DPI kDPIs[] = { | |
33 {&RawMachineAssembler::Word32And, "Word32And", kArmAnd, kArmAnd, kArmTst}, | |
34 {&RawMachineAssembler::Word32Or, "Word32Or", kArmOrr, kArmOrr, kArmOrr}, | |
35 {&RawMachineAssembler::Word32Xor, "Word32Xor", kArmEor, kArmEor, kArmTeq}, | |
36 {&RawMachineAssembler::Int32Add, "Int32Add", kArmAdd, kArmAdd, kArmCmn}, | |
37 {&RawMachineAssembler::Int32Sub, "Int32Sub", kArmSub, kArmRsb, kArmCmp}}; | |
38 | |
39 | |
40 // Data processing instructions with overflow. | |
41 struct ODPI { | |
42 Constructor constructor; | |
43 const char* constructor_name; | |
44 ArchOpcode arch_opcode; | |
45 ArchOpcode reverse_arch_opcode; | |
46 }; | |
47 | |
48 | |
49 std::ostream& operator<<(std::ostream& os, const ODPI& odpi) { | |
50 return os << odpi.constructor_name; | |
51 } | |
52 | |
53 | |
54 static const ODPI kODPIs[] = {{&RawMachineAssembler::Int32AddWithOverflow, | |
55 "Int32AddWithOverflow", kArmAdd, kArmAdd}, | |
56 {&RawMachineAssembler::Int32SubWithOverflow, | |
57 "Int32SubWithOverflow", kArmSub, kArmRsb}}; | |
58 | |
59 | |
60 // Shifts. | |
61 struct Shift { | |
62 Constructor constructor; | |
63 const char* constructor_name; | |
64 int32_t i_low; // lowest possible immediate | |
65 int32_t i_high; // highest possible immediate | |
66 AddressingMode i_mode; // Operand2_R_<shift>_I | |
67 AddressingMode r_mode; // Operand2_R_<shift>_R | |
68 }; | |
69 | |
70 | |
71 std::ostream& operator<<(std::ostream& os, const Shift& shift) { | |
72 return os << shift.constructor_name; | |
73 } | |
74 | |
75 | |
76 static const Shift kShifts[] = { | |
77 {&RawMachineAssembler::Word32Sar, "Word32Sar", 1, 32, | |
78 kMode_Operand2_R_ASR_I, kMode_Operand2_R_ASR_R}, | |
79 {&RawMachineAssembler::Word32Shl, "Word32Shl", 0, 31, | |
80 kMode_Operand2_R_LSL_I, kMode_Operand2_R_LSL_R}, | |
81 {&RawMachineAssembler::Word32Shr, "Word32Shr", 1, 32, | |
82 kMode_Operand2_R_LSR_I, kMode_Operand2_R_LSR_R}, | |
83 {&RawMachineAssembler::Word32Ror, "Word32Ror", 1, 31, | |
84 kMode_Operand2_R_ROR_I, kMode_Operand2_R_ROR_R}}; | |
85 | |
86 | |
87 // Immediates (random subset). | |
88 static const int32_t kImmediates[] = { | |
89 -2147483617, -2147483606, -2113929216, -2080374784, -1996488704, | |
90 -1879048192, -1459617792, -1358954496, -1342177265, -1275068414, | |
91 -1073741818, -1073741777, -855638016, -805306368, -402653184, | |
92 -268435444, -16777216, 0, 35, 61, | |
93 105, 116, 171, 245, 255, | |
94 692, 1216, 1248, 1520, 1600, | |
95 1888, 3744, 4080, 5888, 8384, | |
96 9344, 9472, 9792, 13312, 15040, | |
97 15360, 20736, 22272, 23296, 32000, | |
98 33536, 37120, 45824, 47872, 56320, | |
99 59392, 65280, 72704, 101376, 147456, | |
100 161792, 164864, 167936, 173056, 195584, | |
101 209920, 212992, 356352, 655360, 704512, | |
102 716800, 851968, 901120, 1044480, 1523712, | |
103 2572288, 3211264, 3588096, 3833856, 3866624, | |
104 4325376, 5177344, 6488064, 7012352, 7471104, | |
105 14090240, 16711680, 19398656, 22282240, 28573696, | |
106 30408704, 30670848, 43253760, 54525952, 55312384, | |
107 56623104, 68157440, 115343360, 131072000, 187695104, | |
108 188743680, 195035136, 197132288, 203423744, 218103808, | |
109 267386880, 268435470, 285212672, 402653185, 415236096, | |
110 595591168, 603979776, 603979778, 629145600, 1073741835, | |
111 1073741855, 1073741861, 1073741884, 1157627904, 1476395008, | |
112 1476395010, 1610612741, 2030043136, 2080374785, 2097152000}; | |
113 | |
114 } // namespace | |
115 | |
116 | |
117 // ----------------------------------------------------------------------------- | |
118 // Data processing instructions. | |
119 | |
120 | |
121 typedef InstructionSelectorTestWithParam<DPI> InstructionSelectorDPITest; | |
122 | |
123 | |
124 TEST_P(InstructionSelectorDPITest, Parameters) { | |
125 const DPI dpi = GetParam(); | |
126 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); | |
127 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1))); | |
128 Stream s = m.Build(); | |
129 ASSERT_EQ(1U, s.size()); | |
130 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); | |
131 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode()); | |
132 EXPECT_EQ(2U, s[0]->InputCount()); | |
133 EXPECT_EQ(1U, s[0]->OutputCount()); | |
134 } | |
135 | |
136 | |
137 TEST_P(InstructionSelectorDPITest, Immediate) { | |
138 const DPI dpi = GetParam(); | |
139 TRACED_FOREACH(int32_t, imm, kImmediates) { | |
140 StreamBuilder m(this, kMachInt32, kMachInt32); | |
141 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm))); | |
142 Stream s = m.Build(); | |
143 ASSERT_EQ(1U, s.size()); | |
144 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); | |
145 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode()); | |
146 ASSERT_EQ(2U, s[0]->InputCount()); | |
147 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); | |
148 EXPECT_EQ(1U, s[0]->OutputCount()); | |
149 } | |
150 TRACED_FOREACH(int32_t, imm, kImmediates) { | |
151 StreamBuilder m(this, kMachInt32, kMachInt32); | |
152 m.Return((m.*dpi.constructor)(m.Int32Constant(imm), m.Parameter(0))); | |
153 Stream s = m.Build(); | |
154 ASSERT_EQ(1U, s.size()); | |
155 EXPECT_EQ(dpi.reverse_arch_opcode, s[0]->arch_opcode()); | |
156 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode()); | |
157 ASSERT_EQ(2U, s[0]->InputCount()); | |
158 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); | |
159 EXPECT_EQ(1U, s[0]->OutputCount()); | |
160 } | |
161 } | |
162 | |
163 | |
164 TEST_P(InstructionSelectorDPITest, ShiftByParameter) { | |
165 const DPI dpi = GetParam(); | |
166 TRACED_FOREACH(Shift, shift, kShifts) { | |
167 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32, kMachInt32); | |
168 m.Return((m.*dpi.constructor)( | |
169 m.Parameter(0), | |
170 (m.*shift.constructor)(m.Parameter(1), m.Parameter(2)))); | |
171 Stream s = m.Build(); | |
172 ASSERT_EQ(1U, s.size()); | |
173 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); | |
174 EXPECT_EQ(shift.r_mode, s[0]->addressing_mode()); | |
175 EXPECT_EQ(3U, s[0]->InputCount()); | |
176 EXPECT_EQ(1U, s[0]->OutputCount()); | |
177 } | |
178 TRACED_FOREACH(Shift, shift, kShifts) { | |
179 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32, kMachInt32); | |
180 m.Return((m.*dpi.constructor)( | |
181 (m.*shift.constructor)(m.Parameter(0), m.Parameter(1)), | |
182 m.Parameter(2))); | |
183 Stream s = m.Build(); | |
184 ASSERT_EQ(1U, s.size()); | |
185 EXPECT_EQ(dpi.reverse_arch_opcode, s[0]->arch_opcode()); | |
186 EXPECT_EQ(shift.r_mode, s[0]->addressing_mode()); | |
187 EXPECT_EQ(3U, s[0]->InputCount()); | |
188 EXPECT_EQ(1U, s[0]->OutputCount()); | |
189 } | |
190 } | |
191 | |
192 | |
193 TEST_P(InstructionSelectorDPITest, ShiftByImmediate) { | |
194 const DPI dpi = GetParam(); | |
195 TRACED_FOREACH(Shift, shift, kShifts) { | |
196 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) { | |
197 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); | |
198 m.Return((m.*dpi.constructor)( | |
199 m.Parameter(0), | |
200 (m.*shift.constructor)(m.Parameter(1), m.Int32Constant(imm)))); | |
201 Stream s = m.Build(); | |
202 ASSERT_EQ(1U, s.size()); | |
203 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); | |
204 EXPECT_EQ(shift.i_mode, s[0]->addressing_mode()); | |
205 ASSERT_EQ(3U, s[0]->InputCount()); | |
206 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2))); | |
207 EXPECT_EQ(1U, s[0]->OutputCount()); | |
208 } | |
209 } | |
210 TRACED_FOREACH(Shift, shift, kShifts) { | |
211 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) { | |
212 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); | |
213 m.Return((m.*dpi.constructor)( | |
214 (m.*shift.constructor)(m.Parameter(0), m.Int32Constant(imm)), | |
215 m.Parameter(1))); | |
216 Stream s = m.Build(); | |
217 ASSERT_EQ(1U, s.size()); | |
218 EXPECT_EQ(dpi.reverse_arch_opcode, s[0]->arch_opcode()); | |
219 EXPECT_EQ(shift.i_mode, s[0]->addressing_mode()); | |
220 ASSERT_EQ(3U, s[0]->InputCount()); | |
221 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2))); | |
222 EXPECT_EQ(1U, s[0]->OutputCount()); | |
223 } | |
224 } | |
225 } | |
226 | |
227 | |
228 TEST_P(InstructionSelectorDPITest, BranchWithParameters) { | |
229 const DPI dpi = GetParam(); | |
230 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); | |
231 MLabel a, b; | |
232 m.Branch((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)), &a, &b); | |
233 m.Bind(&a); | |
234 m.Return(m.Int32Constant(1)); | |
235 m.Bind(&b); | |
236 m.Return(m.Int32Constant(0)); | |
237 Stream s = m.Build(); | |
238 ASSERT_EQ(1U, s.size()); | |
239 EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode()); | |
240 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode()); | |
241 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); | |
242 EXPECT_EQ(kNotEqual, s[0]->flags_condition()); | |
243 } | |
244 | |
245 | |
246 TEST_P(InstructionSelectorDPITest, BranchWithImmediate) { | |
247 const DPI dpi = GetParam(); | |
248 TRACED_FOREACH(int32_t, imm, kImmediates) { | |
249 StreamBuilder m(this, kMachInt32, kMachInt32); | |
250 MLabel a, b; | |
251 m.Branch((m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm)), &a, | |
252 &b); | |
253 m.Bind(&a); | |
254 m.Return(m.Int32Constant(1)); | |
255 m.Bind(&b); | |
256 m.Return(m.Int32Constant(0)); | |
257 Stream s = m.Build(); | |
258 ASSERT_EQ(1U, s.size()); | |
259 EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode()); | |
260 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode()); | |
261 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); | |
262 EXPECT_EQ(kNotEqual, s[0]->flags_condition()); | |
263 } | |
264 TRACED_FOREACH(int32_t, imm, kImmediates) { | |
265 StreamBuilder m(this, kMachInt32, kMachInt32); | |
266 MLabel a, b; | |
267 m.Branch((m.*dpi.constructor)(m.Int32Constant(imm), m.Parameter(0)), &a, | |
268 &b); | |
269 m.Bind(&a); | |
270 m.Return(m.Int32Constant(1)); | |
271 m.Bind(&b); | |
272 m.Return(m.Int32Constant(0)); | |
273 Stream s = m.Build(); | |
274 ASSERT_EQ(1U, s.size()); | |
275 EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode()); | |
276 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode()); | |
277 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); | |
278 EXPECT_EQ(kNotEqual, s[0]->flags_condition()); | |
279 } | |
280 } | |
281 | |
282 | |
283 TEST_P(InstructionSelectorDPITest, BranchWithShiftByParameter) { | |
284 const DPI dpi = GetParam(); | |
285 TRACED_FOREACH(Shift, shift, kShifts) { | |
286 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32, kMachInt32); | |
287 MLabel a, b; | |
288 m.Branch((m.*dpi.constructor)( | |
289 m.Parameter(0), | |
290 (m.*shift.constructor)(m.Parameter(1), m.Parameter(2))), | |
291 &a, &b); | |
292 m.Bind(&a); | |
293 m.Return(m.Int32Constant(1)); | |
294 m.Bind(&b); | |
295 m.Return(m.Int32Constant(0)); | |
296 Stream s = m.Build(); | |
297 ASSERT_EQ(1U, s.size()); | |
298 EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode()); | |
299 EXPECT_EQ(shift.r_mode, s[0]->addressing_mode()); | |
300 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); | |
301 EXPECT_EQ(kNotEqual, s[0]->flags_condition()); | |
302 } | |
303 TRACED_FOREACH(Shift, shift, kShifts) { | |
304 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32, kMachInt32); | |
305 MLabel a, b; | |
306 m.Branch((m.*dpi.constructor)( | |
307 (m.*shift.constructor)(m.Parameter(0), m.Parameter(1)), | |
308 m.Parameter(2)), | |
309 &a, &b); | |
310 m.Bind(&a); | |
311 m.Return(m.Int32Constant(1)); | |
312 m.Bind(&b); | |
313 m.Return(m.Int32Constant(0)); | |
314 Stream s = m.Build(); | |
315 ASSERT_EQ(1U, s.size()); | |
316 EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode()); | |
317 EXPECT_EQ(shift.r_mode, s[0]->addressing_mode()); | |
318 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); | |
319 EXPECT_EQ(kNotEqual, s[0]->flags_condition()); | |
320 } | |
321 } | |
322 | |
323 | |
324 TEST_P(InstructionSelectorDPITest, BranchWithShiftByImmediate) { | |
325 const DPI dpi = GetParam(); | |
326 TRACED_FOREACH(Shift, shift, kShifts) { | |
327 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) { | |
328 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); | |
329 MLabel a, b; | |
330 m.Branch((m.*dpi.constructor)(m.Parameter(0), | |
331 (m.*shift.constructor)( | |
332 m.Parameter(1), m.Int32Constant(imm))), | |
333 &a, &b); | |
334 m.Bind(&a); | |
335 m.Return(m.Int32Constant(1)); | |
336 m.Bind(&b); | |
337 m.Return(m.Int32Constant(0)); | |
338 Stream s = m.Build(); | |
339 ASSERT_EQ(1U, s.size()); | |
340 EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode()); | |
341 EXPECT_EQ(shift.i_mode, s[0]->addressing_mode()); | |
342 ASSERT_EQ(5U, s[0]->InputCount()); | |
343 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2))); | |
344 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); | |
345 EXPECT_EQ(kNotEqual, s[0]->flags_condition()); | |
346 } | |
347 } | |
348 TRACED_FOREACH(Shift, shift, kShifts) { | |
349 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) { | |
350 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); | |
351 MLabel a, b; | |
352 m.Branch((m.*dpi.constructor)( | |
353 (m.*shift.constructor)(m.Parameter(0), m.Int32Constant(imm)), | |
354 m.Parameter(1)), | |
355 &a, &b); | |
356 m.Bind(&a); | |
357 m.Return(m.Int32Constant(1)); | |
358 m.Bind(&b); | |
359 m.Return(m.Int32Constant(0)); | |
360 Stream s = m.Build(); | |
361 ASSERT_EQ(1U, s.size()); | |
362 EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode()); | |
363 EXPECT_EQ(shift.i_mode, s[0]->addressing_mode()); | |
364 ASSERT_EQ(5U, s[0]->InputCount()); | |
365 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2))); | |
366 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); | |
367 EXPECT_EQ(kNotEqual, s[0]->flags_condition()); | |
368 } | |
369 } | |
370 } | |
371 | |
372 | |
373 TEST_P(InstructionSelectorDPITest, BranchIfZeroWithParameters) { | |
374 const DPI dpi = GetParam(); | |
375 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); | |
376 MLabel a, b; | |
377 m.Branch(m.Word32Equal((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)), | |
378 m.Int32Constant(0)), | |
379 &a, &b); | |
380 m.Bind(&a); | |
381 m.Return(m.Int32Constant(1)); | |
382 m.Bind(&b); | |
383 m.Return(m.Int32Constant(0)); | |
384 Stream s = m.Build(); | |
385 ASSERT_EQ(1U, s.size()); | |
386 EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode()); | |
387 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode()); | |
388 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); | |
389 EXPECT_EQ(kEqual, s[0]->flags_condition()); | |
390 } | |
391 | |
392 | |
393 TEST_P(InstructionSelectorDPITest, BranchIfNotZeroWithParameters) { | |
394 const DPI dpi = GetParam(); | |
395 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); | |
396 MLabel a, b; | |
397 m.Branch( | |
398 m.Word32NotEqual((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)), | |
399 m.Int32Constant(0)), | |
400 &a, &b); | |
401 m.Bind(&a); | |
402 m.Return(m.Int32Constant(1)); | |
403 m.Bind(&b); | |
404 m.Return(m.Int32Constant(0)); | |
405 Stream s = m.Build(); | |
406 ASSERT_EQ(1U, s.size()); | |
407 EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode()); | |
408 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode()); | |
409 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); | |
410 EXPECT_EQ(kNotEqual, s[0]->flags_condition()); | |
411 } | |
412 | |
413 | |
414 TEST_P(InstructionSelectorDPITest, BranchIfZeroWithImmediate) { | |
415 const DPI dpi = GetParam(); | |
416 TRACED_FOREACH(int32_t, imm, kImmediates) { | |
417 StreamBuilder m(this, kMachInt32, kMachInt32); | |
418 MLabel a, b; | |
419 m.Branch(m.Word32Equal( | |
420 (m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm)), | |
421 m.Int32Constant(0)), | |
422 &a, &b); | |
423 m.Bind(&a); | |
424 m.Return(m.Int32Constant(1)); | |
425 m.Bind(&b); | |
426 m.Return(m.Int32Constant(0)); | |
427 Stream s = m.Build(); | |
428 ASSERT_EQ(1U, s.size()); | |
429 EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode()); | |
430 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode()); | |
431 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); | |
432 EXPECT_EQ(kEqual, s[0]->flags_condition()); | |
433 } | |
434 TRACED_FOREACH(int32_t, imm, kImmediates) { | |
435 StreamBuilder m(this, kMachInt32, kMachInt32); | |
436 MLabel a, b; | |
437 m.Branch(m.Word32Equal( | |
438 (m.*dpi.constructor)(m.Int32Constant(imm), m.Parameter(0)), | |
439 m.Int32Constant(0)), | |
440 &a, &b); | |
441 m.Bind(&a); | |
442 m.Return(m.Int32Constant(1)); | |
443 m.Bind(&b); | |
444 m.Return(m.Int32Constant(0)); | |
445 Stream s = m.Build(); | |
446 ASSERT_EQ(1U, s.size()); | |
447 EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode()); | |
448 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode()); | |
449 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); | |
450 EXPECT_EQ(kEqual, s[0]->flags_condition()); | |
451 } | |
452 } | |
453 | |
454 | |
455 TEST_P(InstructionSelectorDPITest, BranchIfNotZeroWithImmediate) { | |
456 const DPI dpi = GetParam(); | |
457 TRACED_FOREACH(int32_t, imm, kImmediates) { | |
458 StreamBuilder m(this, kMachInt32, kMachInt32); | |
459 MLabel a, b; | |
460 m.Branch(m.Word32NotEqual( | |
461 (m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm)), | |
462 m.Int32Constant(0)), | |
463 &a, &b); | |
464 m.Bind(&a); | |
465 m.Return(m.Int32Constant(1)); | |
466 m.Bind(&b); | |
467 m.Return(m.Int32Constant(0)); | |
468 Stream s = m.Build(); | |
469 ASSERT_EQ(1U, s.size()); | |
470 EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode()); | |
471 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode()); | |
472 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); | |
473 EXPECT_EQ(kNotEqual, s[0]->flags_condition()); | |
474 } | |
475 TRACED_FOREACH(int32_t, imm, kImmediates) { | |
476 StreamBuilder m(this, kMachInt32, kMachInt32); | |
477 MLabel a, b; | |
478 m.Branch(m.Word32NotEqual( | |
479 (m.*dpi.constructor)(m.Int32Constant(imm), m.Parameter(0)), | |
480 m.Int32Constant(0)), | |
481 &a, &b); | |
482 m.Bind(&a); | |
483 m.Return(m.Int32Constant(1)); | |
484 m.Bind(&b); | |
485 m.Return(m.Int32Constant(0)); | |
486 Stream s = m.Build(); | |
487 ASSERT_EQ(1U, s.size()); | |
488 EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode()); | |
489 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode()); | |
490 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); | |
491 EXPECT_EQ(kNotEqual, s[0]->flags_condition()); | |
492 } | |
493 } | |
494 | |
495 | |
496 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorDPITest, | |
497 ::testing::ValuesIn(kDPIs)); | |
498 | |
499 | |
500 // ----------------------------------------------------------------------------- | |
501 // Data processing instructions with overflow. | |
502 | |
503 | |
504 typedef InstructionSelectorTestWithParam<ODPI> InstructionSelectorODPITest; | |
505 | |
506 | |
507 TEST_P(InstructionSelectorODPITest, OvfWithParameters) { | |
508 const ODPI odpi = GetParam(); | |
509 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); | |
510 m.Return( | |
511 m.Projection(1, (m.*odpi.constructor)(m.Parameter(0), m.Parameter(1)))); | |
512 Stream s = m.Build(); | |
513 ASSERT_EQ(1U, s.size()); | |
514 EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode()); | |
515 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode()); | |
516 EXPECT_EQ(2U, s[0]->InputCount()); | |
517 EXPECT_LE(1U, s[0]->OutputCount()); | |
518 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); | |
519 EXPECT_EQ(kOverflow, s[0]->flags_condition()); | |
520 } | |
521 | |
522 | |
523 TEST_P(InstructionSelectorODPITest, OvfWithImmediate) { | |
524 const ODPI odpi = GetParam(); | |
525 TRACED_FOREACH(int32_t, imm, kImmediates) { | |
526 StreamBuilder m(this, kMachInt32, kMachInt32); | |
527 m.Return(m.Projection( | |
528 1, (m.*odpi.constructor)(m.Parameter(0), m.Int32Constant(imm)))); | |
529 Stream s = m.Build(); | |
530 ASSERT_EQ(1U, s.size()); | |
531 EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode()); | |
532 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode()); | |
533 ASSERT_EQ(2U, s[0]->InputCount()); | |
534 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); | |
535 EXPECT_LE(1U, s[0]->OutputCount()); | |
536 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); | |
537 EXPECT_EQ(kOverflow, s[0]->flags_condition()); | |
538 } | |
539 TRACED_FOREACH(int32_t, imm, kImmediates) { | |
540 StreamBuilder m(this, kMachInt32, kMachInt32); | |
541 m.Return(m.Projection( | |
542 1, (m.*odpi.constructor)(m.Int32Constant(imm), m.Parameter(0)))); | |
543 Stream s = m.Build(); | |
544 ASSERT_EQ(1U, s.size()); | |
545 EXPECT_EQ(odpi.reverse_arch_opcode, s[0]->arch_opcode()); | |
546 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode()); | |
547 ASSERT_EQ(2U, s[0]->InputCount()); | |
548 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); | |
549 EXPECT_LE(1U, s[0]->OutputCount()); | |
550 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); | |
551 EXPECT_EQ(kOverflow, s[0]->flags_condition()); | |
552 } | |
553 } | |
554 | |
555 | |
556 TEST_P(InstructionSelectorODPITest, OvfWithShiftByParameter) { | |
557 const ODPI odpi = GetParam(); | |
558 TRACED_FOREACH(Shift, shift, kShifts) { | |
559 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32, kMachInt32); | |
560 m.Return(m.Projection( | |
561 1, (m.*odpi.constructor)( | |
562 m.Parameter(0), | |
563 (m.*shift.constructor)(m.Parameter(1), m.Parameter(2))))); | |
564 Stream s = m.Build(); | |
565 ASSERT_EQ(1U, s.size()); | |
566 EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode()); | |
567 EXPECT_EQ(shift.r_mode, s[0]->addressing_mode()); | |
568 EXPECT_EQ(3U, s[0]->InputCount()); | |
569 EXPECT_LE(1U, s[0]->OutputCount()); | |
570 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); | |
571 EXPECT_EQ(kOverflow, s[0]->flags_condition()); | |
572 } | |
573 TRACED_FOREACH(Shift, shift, kShifts) { | |
574 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32, kMachInt32); | |
575 m.Return(m.Projection( | |
576 1, (m.*odpi.constructor)( | |
577 (m.*shift.constructor)(m.Parameter(0), m.Parameter(1)), | |
578 m.Parameter(0)))); | |
579 Stream s = m.Build(); | |
580 ASSERT_EQ(1U, s.size()); | |
581 EXPECT_EQ(odpi.reverse_arch_opcode, s[0]->arch_opcode()); | |
582 EXPECT_EQ(shift.r_mode, s[0]->addressing_mode()); | |
583 EXPECT_EQ(3U, s[0]->InputCount()); | |
584 EXPECT_LE(1U, s[0]->OutputCount()); | |
585 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); | |
586 EXPECT_EQ(kOverflow, s[0]->flags_condition()); | |
587 } | |
588 } | |
589 | |
590 | |
591 TEST_P(InstructionSelectorODPITest, OvfWithShiftByImmediate) { | |
592 const ODPI odpi = GetParam(); | |
593 TRACED_FOREACH(Shift, shift, kShifts) { | |
594 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) { | |
595 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); | |
596 m.Return(m.Projection( | |
597 1, (m.*odpi.constructor)(m.Parameter(0), | |
598 (m.*shift.constructor)( | |
599 m.Parameter(1), m.Int32Constant(imm))))); | |
600 Stream s = m.Build(); | |
601 ASSERT_EQ(1U, s.size()); | |
602 EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode()); | |
603 EXPECT_EQ(shift.i_mode, s[0]->addressing_mode()); | |
604 ASSERT_EQ(3U, s[0]->InputCount()); | |
605 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2))); | |
606 EXPECT_LE(1U, s[0]->OutputCount()); | |
607 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); | |
608 EXPECT_EQ(kOverflow, s[0]->flags_condition()); | |
609 } | |
610 } | |
611 TRACED_FOREACH(Shift, shift, kShifts) { | |
612 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) { | |
613 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); | |
614 m.Return(m.Projection( | |
615 1, (m.*odpi.constructor)( | |
616 (m.*shift.constructor)(m.Parameter(1), m.Int32Constant(imm)), | |
617 m.Parameter(0)))); | |
618 Stream s = m.Build(); | |
619 ASSERT_EQ(1U, s.size()); | |
620 EXPECT_EQ(odpi.reverse_arch_opcode, s[0]->arch_opcode()); | |
621 EXPECT_EQ(shift.i_mode, s[0]->addressing_mode()); | |
622 ASSERT_EQ(3U, s[0]->InputCount()); | |
623 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2))); | |
624 EXPECT_LE(1U, s[0]->OutputCount()); | |
625 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); | |
626 EXPECT_EQ(kOverflow, s[0]->flags_condition()); | |
627 } | |
628 } | |
629 } | |
630 | |
631 | |
632 TEST_P(InstructionSelectorODPITest, ValWithParameters) { | |
633 const ODPI odpi = GetParam(); | |
634 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); | |
635 m.Return( | |
636 m.Projection(0, (m.*odpi.constructor)(m.Parameter(0), m.Parameter(1)))); | |
637 Stream s = m.Build(); | |
638 ASSERT_EQ(1U, s.size()); | |
639 EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode()); | |
640 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode()); | |
641 EXPECT_EQ(2U, s[0]->InputCount()); | |
642 EXPECT_LE(1U, s[0]->OutputCount()); | |
643 EXPECT_EQ(kFlags_none, s[0]->flags_mode()); | |
644 } | |
645 | |
646 | |
647 TEST_P(InstructionSelectorODPITest, ValWithImmediate) { | |
648 const ODPI odpi = GetParam(); | |
649 TRACED_FOREACH(int32_t, imm, kImmediates) { | |
650 StreamBuilder m(this, kMachInt32, kMachInt32); | |
651 m.Return(m.Projection( | |
652 0, (m.*odpi.constructor)(m.Parameter(0), m.Int32Constant(imm)))); | |
653 Stream s = m.Build(); | |
654 ASSERT_EQ(1U, s.size()); | |
655 EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode()); | |
656 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode()); | |
657 ASSERT_EQ(2U, s[0]->InputCount()); | |
658 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); | |
659 EXPECT_LE(1U, s[0]->OutputCount()); | |
660 EXPECT_EQ(kFlags_none, s[0]->flags_mode()); | |
661 } | |
662 TRACED_FOREACH(int32_t, imm, kImmediates) { | |
663 StreamBuilder m(this, kMachInt32, kMachInt32); | |
664 m.Return(m.Projection( | |
665 0, (m.*odpi.constructor)(m.Int32Constant(imm), m.Parameter(0)))); | |
666 Stream s = m.Build(); | |
667 ASSERT_EQ(1U, s.size()); | |
668 EXPECT_EQ(odpi.reverse_arch_opcode, s[0]->arch_opcode()); | |
669 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode()); | |
670 ASSERT_EQ(2U, s[0]->InputCount()); | |
671 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); | |
672 EXPECT_LE(1U, s[0]->OutputCount()); | |
673 EXPECT_EQ(kFlags_none, s[0]->flags_mode()); | |
674 } | |
675 } | |
676 | |
677 | |
678 TEST_P(InstructionSelectorODPITest, ValWithShiftByParameter) { | |
679 const ODPI odpi = GetParam(); | |
680 TRACED_FOREACH(Shift, shift, kShifts) { | |
681 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32, kMachInt32); | |
682 m.Return(m.Projection( | |
683 0, (m.*odpi.constructor)( | |
684 m.Parameter(0), | |
685 (m.*shift.constructor)(m.Parameter(1), m.Parameter(2))))); | |
686 Stream s = m.Build(); | |
687 ASSERT_EQ(1U, s.size()); | |
688 EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode()); | |
689 EXPECT_EQ(shift.r_mode, s[0]->addressing_mode()); | |
690 EXPECT_EQ(3U, s[0]->InputCount()); | |
691 EXPECT_LE(1U, s[0]->OutputCount()); | |
692 EXPECT_EQ(kFlags_none, s[0]->flags_mode()); | |
693 } | |
694 TRACED_FOREACH(Shift, shift, kShifts) { | |
695 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32, kMachInt32); | |
696 m.Return(m.Projection( | |
697 0, (m.*odpi.constructor)( | |
698 (m.*shift.constructor)(m.Parameter(0), m.Parameter(1)), | |
699 m.Parameter(0)))); | |
700 Stream s = m.Build(); | |
701 ASSERT_EQ(1U, s.size()); | |
702 EXPECT_EQ(odpi.reverse_arch_opcode, s[0]->arch_opcode()); | |
703 EXPECT_EQ(shift.r_mode, s[0]->addressing_mode()); | |
704 EXPECT_EQ(3U, s[0]->InputCount()); | |
705 EXPECT_LE(1U, s[0]->OutputCount()); | |
706 EXPECT_EQ(kFlags_none, s[0]->flags_mode()); | |
707 } | |
708 } | |
709 | |
710 | |
711 TEST_P(InstructionSelectorODPITest, ValWithShiftByImmediate) { | |
712 const ODPI odpi = GetParam(); | |
713 TRACED_FOREACH(Shift, shift, kShifts) { | |
714 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) { | |
715 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); | |
716 m.Return(m.Projection( | |
717 0, (m.*odpi.constructor)(m.Parameter(0), | |
718 (m.*shift.constructor)( | |
719 m.Parameter(1), m.Int32Constant(imm))))); | |
720 Stream s = m.Build(); | |
721 ASSERT_EQ(1U, s.size()); | |
722 EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode()); | |
723 EXPECT_EQ(shift.i_mode, s[0]->addressing_mode()); | |
724 ASSERT_EQ(3U, s[0]->InputCount()); | |
725 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2))); | |
726 EXPECT_LE(1U, s[0]->OutputCount()); | |
727 EXPECT_EQ(kFlags_none, s[0]->flags_mode()); | |
728 } | |
729 } | |
730 TRACED_FOREACH(Shift, shift, kShifts) { | |
731 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) { | |
732 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); | |
733 m.Return(m.Projection( | |
734 0, (m.*odpi.constructor)( | |
735 (m.*shift.constructor)(m.Parameter(1), m.Int32Constant(imm)), | |
736 m.Parameter(0)))); | |
737 Stream s = m.Build(); | |
738 ASSERT_EQ(1U, s.size()); | |
739 EXPECT_EQ(odpi.reverse_arch_opcode, s[0]->arch_opcode()); | |
740 EXPECT_EQ(shift.i_mode, s[0]->addressing_mode()); | |
741 ASSERT_EQ(3U, s[0]->InputCount()); | |
742 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2))); | |
743 EXPECT_LE(1U, s[0]->OutputCount()); | |
744 EXPECT_EQ(kFlags_none, s[0]->flags_mode()); | |
745 } | |
746 } | |
747 } | |
748 | |
749 | |
750 TEST_P(InstructionSelectorODPITest, BothWithParameters) { | |
751 const ODPI odpi = GetParam(); | |
752 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); | |
753 Node* n = (m.*odpi.constructor)(m.Parameter(0), m.Parameter(1)); | |
754 m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n))); | |
755 Stream s = m.Build(); | |
756 ASSERT_LE(1U, s.size()); | |
757 EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode()); | |
758 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode()); | |
759 EXPECT_EQ(2U, s[0]->InputCount()); | |
760 EXPECT_EQ(2U, s[0]->OutputCount()); | |
761 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); | |
762 EXPECT_EQ(kOverflow, s[0]->flags_condition()); | |
763 } | |
764 | |
765 | |
766 TEST_P(InstructionSelectorODPITest, BothWithImmediate) { | |
767 const ODPI odpi = GetParam(); | |
768 TRACED_FOREACH(int32_t, imm, kImmediates) { | |
769 StreamBuilder m(this, kMachInt32, kMachInt32); | |
770 Node* n = (m.*odpi.constructor)(m.Parameter(0), m.Int32Constant(imm)); | |
771 m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n))); | |
772 Stream s = m.Build(); | |
773 ASSERT_LE(1U, s.size()); | |
774 EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode()); | |
775 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode()); | |
776 ASSERT_EQ(2U, s[0]->InputCount()); | |
777 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); | |
778 EXPECT_EQ(2U, s[0]->OutputCount()); | |
779 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); | |
780 EXPECT_EQ(kOverflow, s[0]->flags_condition()); | |
781 } | |
782 TRACED_FOREACH(int32_t, imm, kImmediates) { | |
783 StreamBuilder m(this, kMachInt32, kMachInt32); | |
784 Node* n = (m.*odpi.constructor)(m.Int32Constant(imm), m.Parameter(0)); | |
785 m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n))); | |
786 Stream s = m.Build(); | |
787 ASSERT_LE(1U, s.size()); | |
788 EXPECT_EQ(odpi.reverse_arch_opcode, s[0]->arch_opcode()); | |
789 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode()); | |
790 ASSERT_EQ(2U, s[0]->InputCount()); | |
791 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); | |
792 EXPECT_EQ(2U, s[0]->OutputCount()); | |
793 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); | |
794 EXPECT_EQ(kOverflow, s[0]->flags_condition()); | |
795 } | |
796 } | |
797 | |
798 | |
799 TEST_P(InstructionSelectorODPITest, BothWithShiftByParameter) { | |
800 const ODPI odpi = GetParam(); | |
801 TRACED_FOREACH(Shift, shift, kShifts) { | |
802 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32, kMachInt32); | |
803 Node* n = (m.*odpi.constructor)( | |
804 m.Parameter(0), (m.*shift.constructor)(m.Parameter(1), m.Parameter(2))); | |
805 m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n))); | |
806 Stream s = m.Build(); | |
807 ASSERT_LE(1U, s.size()); | |
808 EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode()); | |
809 EXPECT_EQ(shift.r_mode, s[0]->addressing_mode()); | |
810 EXPECT_EQ(3U, s[0]->InputCount()); | |
811 EXPECT_EQ(2U, s[0]->OutputCount()); | |
812 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); | |
813 EXPECT_EQ(kOverflow, s[0]->flags_condition()); | |
814 } | |
815 TRACED_FOREACH(Shift, shift, kShifts) { | |
816 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32, kMachInt32); | |
817 Node* n = (m.*odpi.constructor)( | |
818 (m.*shift.constructor)(m.Parameter(0), m.Parameter(1)), m.Parameter(2)); | |
819 m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n))); | |
820 Stream s = m.Build(); | |
821 ASSERT_LE(1U, s.size()); | |
822 EXPECT_EQ(odpi.reverse_arch_opcode, s[0]->arch_opcode()); | |
823 EXPECT_EQ(shift.r_mode, s[0]->addressing_mode()); | |
824 EXPECT_EQ(3U, s[0]->InputCount()); | |
825 EXPECT_EQ(2U, s[0]->OutputCount()); | |
826 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); | |
827 EXPECT_EQ(kOverflow, s[0]->flags_condition()); | |
828 } | |
829 } | |
830 | |
831 | |
832 TEST_P(InstructionSelectorODPITest, BothWithShiftByImmediate) { | |
833 const ODPI odpi = GetParam(); | |
834 TRACED_FOREACH(Shift, shift, kShifts) { | |
835 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) { | |
836 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); | |
837 Node* n = (m.*odpi.constructor)( | |
838 m.Parameter(0), | |
839 (m.*shift.constructor)(m.Parameter(1), m.Int32Constant(imm))); | |
840 m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n))); | |
841 Stream s = m.Build(); | |
842 ASSERT_LE(1U, s.size()); | |
843 EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode()); | |
844 EXPECT_EQ(shift.i_mode, s[0]->addressing_mode()); | |
845 ASSERT_EQ(3U, s[0]->InputCount()); | |
846 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2))); | |
847 EXPECT_EQ(2U, s[0]->OutputCount()); | |
848 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); | |
849 EXPECT_EQ(kOverflow, s[0]->flags_condition()); | |
850 } | |
851 } | |
852 TRACED_FOREACH(Shift, shift, kShifts) { | |
853 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) { | |
854 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); | |
855 Node* n = (m.*odpi.constructor)( | |
856 (m.*shift.constructor)(m.Parameter(0), m.Int32Constant(imm)), | |
857 m.Parameter(1)); | |
858 m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n))); | |
859 Stream s = m.Build(); | |
860 ASSERT_LE(1U, s.size()); | |
861 EXPECT_EQ(odpi.reverse_arch_opcode, s[0]->arch_opcode()); | |
862 EXPECT_EQ(shift.i_mode, s[0]->addressing_mode()); | |
863 ASSERT_EQ(3U, s[0]->InputCount()); | |
864 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2))); | |
865 EXPECT_EQ(2U, s[0]->OutputCount()); | |
866 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); | |
867 EXPECT_EQ(kOverflow, s[0]->flags_condition()); | |
868 } | |
869 } | |
870 } | |
871 | |
872 | |
873 TEST_P(InstructionSelectorODPITest, BranchWithParameters) { | |
874 const ODPI odpi = GetParam(); | |
875 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); | |
876 MLabel a, b; | |
877 Node* n = (m.*odpi.constructor)(m.Parameter(0), m.Parameter(1)); | |
878 m.Branch(m.Projection(1, n), &a, &b); | |
879 m.Bind(&a); | |
880 m.Return(m.Int32Constant(0)); | |
881 m.Bind(&b); | |
882 m.Return(m.Projection(0, n)); | |
883 Stream s = m.Build(); | |
884 ASSERT_EQ(1U, s.size()); | |
885 EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode()); | |
886 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode()); | |
887 EXPECT_EQ(4U, s[0]->InputCount()); | |
888 EXPECT_EQ(1U, s[0]->OutputCount()); | |
889 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); | |
890 EXPECT_EQ(kOverflow, s[0]->flags_condition()); | |
891 } | |
892 | |
893 | |
894 TEST_P(InstructionSelectorODPITest, BranchWithImmediate) { | |
895 const ODPI odpi = GetParam(); | |
896 TRACED_FOREACH(int32_t, imm, kImmediates) { | |
897 StreamBuilder m(this, kMachInt32, kMachInt32); | |
898 MLabel a, b; | |
899 Node* n = (m.*odpi.constructor)(m.Parameter(0), m.Int32Constant(imm)); | |
900 m.Branch(m.Projection(1, n), &a, &b); | |
901 m.Bind(&a); | |
902 m.Return(m.Int32Constant(0)); | |
903 m.Bind(&b); | |
904 m.Return(m.Projection(0, n)); | |
905 Stream s = m.Build(); | |
906 ASSERT_EQ(1U, s.size()); | |
907 EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode()); | |
908 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode()); | |
909 ASSERT_EQ(4U, s[0]->InputCount()); | |
910 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); | |
911 EXPECT_EQ(1U, s[0]->OutputCount()); | |
912 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); | |
913 EXPECT_EQ(kOverflow, s[0]->flags_condition()); | |
914 } | |
915 TRACED_FOREACH(int32_t, imm, kImmediates) { | |
916 StreamBuilder m(this, kMachInt32, kMachInt32); | |
917 MLabel a, b; | |
918 Node* n = (m.*odpi.constructor)(m.Int32Constant(imm), m.Parameter(0)); | |
919 m.Branch(m.Projection(1, n), &a, &b); | |
920 m.Bind(&a); | |
921 m.Return(m.Int32Constant(0)); | |
922 m.Bind(&b); | |
923 m.Return(m.Projection(0, n)); | |
924 Stream s = m.Build(); | |
925 ASSERT_EQ(1U, s.size()); | |
926 EXPECT_EQ(odpi.reverse_arch_opcode, s[0]->arch_opcode()); | |
927 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode()); | |
928 ASSERT_EQ(4U, s[0]->InputCount()); | |
929 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); | |
930 EXPECT_EQ(1U, s[0]->OutputCount()); | |
931 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); | |
932 EXPECT_EQ(kOverflow, s[0]->flags_condition()); | |
933 } | |
934 } | |
935 | |
936 | |
937 TEST_P(InstructionSelectorODPITest, BranchIfZeroWithParameters) { | |
938 const ODPI odpi = GetParam(); | |
939 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); | |
940 MLabel a, b; | |
941 Node* n = (m.*odpi.constructor)(m.Parameter(0), m.Parameter(1)); | |
942 m.Branch(m.Word32Equal(m.Projection(1, n), m.Int32Constant(0)), &a, &b); | |
943 m.Bind(&a); | |
944 m.Return(m.Projection(0, n)); | |
945 m.Bind(&b); | |
946 m.Return(m.Int32Constant(0)); | |
947 Stream s = m.Build(); | |
948 ASSERT_EQ(1U, s.size()); | |
949 EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode()); | |
950 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode()); | |
951 EXPECT_EQ(4U, s[0]->InputCount()); | |
952 EXPECT_EQ(1U, s[0]->OutputCount()); | |
953 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); | |
954 EXPECT_EQ(kNotOverflow, s[0]->flags_condition()); | |
955 } | |
956 | |
957 | |
958 TEST_P(InstructionSelectorODPITest, BranchIfNotZeroWithParameters) { | |
959 const ODPI odpi = GetParam(); | |
960 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); | |
961 MLabel a, b; | |
962 Node* n = (m.*odpi.constructor)(m.Parameter(0), m.Parameter(1)); | |
963 m.Branch(m.Word32NotEqual(m.Projection(1, n), m.Int32Constant(0)), &a, &b); | |
964 m.Bind(&a); | |
965 m.Return(m.Projection(0, n)); | |
966 m.Bind(&b); | |
967 m.Return(m.Int32Constant(0)); | |
968 Stream s = m.Build(); | |
969 ASSERT_EQ(1U, s.size()); | |
970 EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode()); | |
971 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode()); | |
972 EXPECT_EQ(4U, s[0]->InputCount()); | |
973 EXPECT_EQ(1U, s[0]->OutputCount()); | |
974 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); | |
975 EXPECT_EQ(kOverflow, s[0]->flags_condition()); | |
976 } | |
977 | |
978 | |
979 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorODPITest, | |
980 ::testing::ValuesIn(kODPIs)); | |
981 | |
982 | |
983 // ----------------------------------------------------------------------------- | |
984 // Shifts. | |
985 | |
986 | |
987 typedef InstructionSelectorTestWithParam<Shift> InstructionSelectorShiftTest; | |
988 | |
989 | |
990 TEST_P(InstructionSelectorShiftTest, Parameters) { | |
991 const Shift shift = GetParam(); | |
992 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); | |
993 m.Return((m.*shift.constructor)(m.Parameter(0), m.Parameter(1))); | |
994 Stream s = m.Build(); | |
995 ASSERT_EQ(1U, s.size()); | |
996 EXPECT_EQ(kArmMov, s[0]->arch_opcode()); | |
997 EXPECT_EQ(shift.r_mode, s[0]->addressing_mode()); | |
998 EXPECT_EQ(2U, s[0]->InputCount()); | |
999 EXPECT_EQ(1U, s[0]->OutputCount()); | |
1000 } | |
1001 | |
1002 | |
1003 TEST_P(InstructionSelectorShiftTest, Immediate) { | |
1004 const Shift shift = GetParam(); | |
1005 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) { | |
1006 StreamBuilder m(this, kMachInt32, kMachInt32); | |
1007 m.Return((m.*shift.constructor)(m.Parameter(0), m.Int32Constant(imm))); | |
1008 Stream s = m.Build(); | |
1009 ASSERT_EQ(1U, s.size()); | |
1010 EXPECT_EQ(kArmMov, s[0]->arch_opcode()); | |
1011 EXPECT_EQ(shift.i_mode, s[0]->addressing_mode()); | |
1012 ASSERT_EQ(2U, s[0]->InputCount()); | |
1013 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); | |
1014 EXPECT_EQ(1U, s[0]->OutputCount()); | |
1015 } | |
1016 } | |
1017 | |
1018 | |
1019 TEST_P(InstructionSelectorShiftTest, Word32EqualWithParameter) { | |
1020 const Shift shift = GetParam(); | |
1021 { | |
1022 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32, kMachInt32); | |
1023 m.Return( | |
1024 m.Word32Equal(m.Parameter(0), | |
1025 (m.*shift.constructor)(m.Parameter(1), m.Parameter(2)))); | |
1026 Stream s = m.Build(); | |
1027 ASSERT_EQ(1U, s.size()); | |
1028 EXPECT_EQ(kArmCmp, s[0]->arch_opcode()); | |
1029 EXPECT_EQ(shift.r_mode, s[0]->addressing_mode()); | |
1030 EXPECT_EQ(3U, s[0]->InputCount()); | |
1031 EXPECT_EQ(1U, s[0]->OutputCount()); | |
1032 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); | |
1033 EXPECT_EQ(kEqual, s[0]->flags_condition()); | |
1034 } | |
1035 { | |
1036 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32, kMachInt32); | |
1037 m.Return( | |
1038 m.Word32Equal((m.*shift.constructor)(m.Parameter(1), m.Parameter(2)), | |
1039 m.Parameter(0))); | |
1040 Stream s = m.Build(); | |
1041 ASSERT_EQ(1U, s.size()); | |
1042 EXPECT_EQ(kArmCmp, s[0]->arch_opcode()); | |
1043 EXPECT_EQ(shift.r_mode, s[0]->addressing_mode()); | |
1044 EXPECT_EQ(3U, s[0]->InputCount()); | |
1045 EXPECT_EQ(1U, s[0]->OutputCount()); | |
1046 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); | |
1047 EXPECT_EQ(kEqual, s[0]->flags_condition()); | |
1048 } | |
1049 } | |
1050 | |
1051 | |
1052 TEST_P(InstructionSelectorShiftTest, Word32EqualWithParameterAndImmediate) { | |
1053 const Shift shift = GetParam(); | |
1054 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) { | |
1055 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); | |
1056 m.Return(m.Word32Equal( | |
1057 (m.*shift.constructor)(m.Parameter(1), m.Int32Constant(imm)), | |
1058 m.Parameter(0))); | |
1059 Stream s = m.Build(); | |
1060 ASSERT_EQ(1U, s.size()); | |
1061 EXPECT_EQ(kArmCmp, s[0]->arch_opcode()); | |
1062 EXPECT_EQ(shift.i_mode, s[0]->addressing_mode()); | |
1063 ASSERT_EQ(3U, s[0]->InputCount()); | |
1064 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2))); | |
1065 EXPECT_EQ(1U, s[0]->OutputCount()); | |
1066 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); | |
1067 EXPECT_EQ(kEqual, s[0]->flags_condition()); | |
1068 } | |
1069 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) { | |
1070 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); | |
1071 m.Return(m.Word32Equal( | |
1072 m.Parameter(0), | |
1073 (m.*shift.constructor)(m.Parameter(1), m.Int32Constant(imm)))); | |
1074 Stream s = m.Build(); | |
1075 ASSERT_EQ(1U, s.size()); | |
1076 EXPECT_EQ(kArmCmp, s[0]->arch_opcode()); | |
1077 EXPECT_EQ(shift.i_mode, s[0]->addressing_mode()); | |
1078 ASSERT_EQ(3U, s[0]->InputCount()); | |
1079 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2))); | |
1080 EXPECT_EQ(1U, s[0]->OutputCount()); | |
1081 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); | |
1082 EXPECT_EQ(kEqual, s[0]->flags_condition()); | |
1083 } | |
1084 } | |
1085 | |
1086 | |
1087 TEST_P(InstructionSelectorShiftTest, Word32EqualToZeroWithParameters) { | |
1088 const Shift shift = GetParam(); | |
1089 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); | |
1090 m.Return( | |
1091 m.Word32Equal(m.Int32Constant(0), | |
1092 (m.*shift.constructor)(m.Parameter(0), m.Parameter(1)))); | |
1093 Stream s = m.Build(); | |
1094 ASSERT_EQ(1U, s.size()); | |
1095 EXPECT_EQ(kArmMov, s[0]->arch_opcode()); | |
1096 EXPECT_EQ(shift.r_mode, s[0]->addressing_mode()); | |
1097 EXPECT_EQ(2U, s[0]->InputCount()); | |
1098 EXPECT_EQ(2U, s[0]->OutputCount()); | |
1099 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); | |
1100 EXPECT_EQ(kEqual, s[0]->flags_condition()); | |
1101 } | |
1102 | |
1103 | |
1104 TEST_P(InstructionSelectorShiftTest, Word32EqualToZeroWithImmediate) { | |
1105 const Shift shift = GetParam(); | |
1106 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) { | |
1107 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); | |
1108 m.Return(m.Word32Equal( | |
1109 m.Int32Constant(0), | |
1110 (m.*shift.constructor)(m.Parameter(0), m.Int32Constant(imm)))); | |
1111 Stream s = m.Build(); | |
1112 ASSERT_EQ(1U, s.size()); | |
1113 EXPECT_EQ(kArmMov, s[0]->arch_opcode()); | |
1114 EXPECT_EQ(shift.i_mode, s[0]->addressing_mode()); | |
1115 ASSERT_EQ(2U, s[0]->InputCount()); | |
1116 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); | |
1117 EXPECT_EQ(2U, s[0]->OutputCount()); | |
1118 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); | |
1119 EXPECT_EQ(kEqual, s[0]->flags_condition()); | |
1120 } | |
1121 } | |
1122 | |
1123 | |
1124 TEST_P(InstructionSelectorShiftTest, Word32NotWithParameters) { | |
1125 const Shift shift = GetParam(); | |
1126 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); | |
1127 m.Return(m.Word32Not((m.*shift.constructor)(m.Parameter(0), m.Parameter(1)))); | |
1128 Stream s = m.Build(); | |
1129 ASSERT_EQ(1U, s.size()); | |
1130 EXPECT_EQ(kArmMvn, s[0]->arch_opcode()); | |
1131 EXPECT_EQ(shift.r_mode, s[0]->addressing_mode()); | |
1132 EXPECT_EQ(2U, s[0]->InputCount()); | |
1133 EXPECT_EQ(1U, s[0]->OutputCount()); | |
1134 } | |
1135 | |
1136 | |
1137 TEST_P(InstructionSelectorShiftTest, Word32NotWithImmediate) { | |
1138 const Shift shift = GetParam(); | |
1139 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) { | |
1140 StreamBuilder m(this, kMachInt32, kMachInt32); | |
1141 m.Return(m.Word32Not( | |
1142 (m.*shift.constructor)(m.Parameter(0), m.Int32Constant(imm)))); | |
1143 Stream s = m.Build(); | |
1144 ASSERT_EQ(1U, s.size()); | |
1145 EXPECT_EQ(kArmMvn, s[0]->arch_opcode()); | |
1146 EXPECT_EQ(shift.i_mode, s[0]->addressing_mode()); | |
1147 ASSERT_EQ(2U, s[0]->InputCount()); | |
1148 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); | |
1149 EXPECT_EQ(1U, s[0]->OutputCount()); | |
1150 } | |
1151 } | |
1152 | |
1153 | |
1154 TEST_P(InstructionSelectorShiftTest, Word32AndWithWord32NotWithParameters) { | |
1155 const Shift shift = GetParam(); | |
1156 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32, kMachInt32); | |
1157 m.Return(m.Word32And(m.Parameter(0), m.Word32Not((m.*shift.constructor)( | |
1158 m.Parameter(1), m.Parameter(2))))); | |
1159 Stream s = m.Build(); | |
1160 ASSERT_EQ(1U, s.size()); | |
1161 EXPECT_EQ(kArmBic, s[0]->arch_opcode()); | |
1162 EXPECT_EQ(shift.r_mode, s[0]->addressing_mode()); | |
1163 EXPECT_EQ(3U, s[0]->InputCount()); | |
1164 EXPECT_EQ(1U, s[0]->OutputCount()); | |
1165 } | |
1166 | |
1167 | |
1168 TEST_P(InstructionSelectorShiftTest, Word32AndWithWord32NotWithImmediate) { | |
1169 const Shift shift = GetParam(); | |
1170 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) { | |
1171 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); | |
1172 m.Return(m.Word32And(m.Parameter(0), | |
1173 m.Word32Not((m.*shift.constructor)( | |
1174 m.Parameter(1), m.Int32Constant(imm))))); | |
1175 Stream s = m.Build(); | |
1176 ASSERT_EQ(1U, s.size()); | |
1177 EXPECT_EQ(kArmBic, s[0]->arch_opcode()); | |
1178 EXPECT_EQ(shift.i_mode, s[0]->addressing_mode()); | |
1179 ASSERT_EQ(3U, s[0]->InputCount()); | |
1180 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2))); | |
1181 EXPECT_EQ(1U, s[0]->OutputCount()); | |
1182 } | |
1183 } | |
1184 | |
1185 | |
1186 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorShiftTest, | |
1187 ::testing::ValuesIn(kShifts)); | |
1188 | |
1189 | |
1190 // ----------------------------------------------------------------------------- | |
1191 // Memory access instructions. | |
1192 | |
1193 | |
1194 namespace { | |
1195 | |
1196 struct MemoryAccess { | |
1197 MachineType type; | |
1198 ArchOpcode ldr_opcode; | |
1199 ArchOpcode str_opcode; | |
1200 bool (InstructionSelectorTest::Stream::*val_predicate)( | |
1201 const InstructionOperand*) const; | |
1202 const int32_t immediates[40]; | |
1203 }; | |
1204 | |
1205 | |
1206 std::ostream& operator<<(std::ostream& os, const MemoryAccess& memacc) { | |
1207 return os << memacc.type; | |
1208 } | |
1209 | |
1210 | |
1211 static const MemoryAccess kMemoryAccesses[] = { | |
1212 {kMachInt8, | |
1213 kArmLdrsb, | |
1214 kArmStrb, | |
1215 &InstructionSelectorTest::Stream::IsInteger, | |
1216 {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89, | |
1217 -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109, | |
1218 115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}}, | |
1219 {kMachUint8, | |
1220 kArmLdrb, | |
1221 kArmStrb, | |
1222 &InstructionSelectorTest::Stream::IsInteger, | |
1223 {-4095, -3914, -3536, -3234, -3185, -3169, -1073, -990, -859, -720, -434, | |
1224 -127, -124, -122, -105, -91, -86, -64, -55, -53, -30, -10, -3, 0, 20, 28, | |
1225 39, 58, 64, 73, 75, 100, 108, 121, 686, 963, 1363, 2759, 3449, 4095}}, | |
1226 {kMachInt16, | |
1227 kArmLdrsh, | |
1228 kArmStrh, | |
1229 &InstructionSelectorTest::Stream::IsInteger, | |
1230 {-255, -251, -232, -220, -144, -138, -130, -126, -116, -115, -102, -101, | |
1231 -98, -69, -59, -56, -39, -35, -23, -19, -7, 0, 22, 26, 37, 68, 83, 87, 98, | |
1232 102, 108, 111, 117, 171, 195, 203, 204, 245, 246, 255}}, | |
1233 {kMachUint16, | |
1234 kArmLdrh, | |
1235 kArmStrh, | |
1236 &InstructionSelectorTest::Stream::IsInteger, | |
1237 {-255, -230, -201, -172, -125, -119, -118, -105, -98, -79, -54, -42, -41, | |
1238 -32, -12, -11, -5, -4, 0, 5, 9, 25, 28, 51, 58, 60, 89, 104, 108, 109, | |
1239 114, 116, 120, 138, 150, 161, 166, 172, 228, 255}}, | |
1240 {kMachInt32, | |
1241 kArmLdr, | |
1242 kArmStr, | |
1243 &InstructionSelectorTest::Stream::IsInteger, | |
1244 {-4095, -1898, -1685, -1562, -1408, -1313, -344, -128, -116, -100, -92, | |
1245 -80, -72, -71, -56, -25, -21, -11, -9, 0, 3, 5, 27, 28, 42, 52, 63, 88, | |
1246 93, 97, 125, 846, 1037, 2102, 2403, 2597, 2632, 2997, 3935, 4095}}, | |
1247 {kMachFloat32, | |
1248 kArmVldrF32, | |
1249 kArmVstrF32, | |
1250 &InstructionSelectorTest::Stream::IsDouble, | |
1251 {-1020, -928, -896, -772, -728, -680, -660, -488, -372, -112, -100, -92, | |
1252 -84, -80, -72, -64, -60, -56, -52, -48, -36, -32, -20, -8, -4, 0, 8, 20, | |
1253 24, 40, 64, 112, 204, 388, 516, 852, 856, 976, 988, 1020}}, | |
1254 {kMachFloat64, | |
1255 kArmVldrF64, | |
1256 kArmVstrF64, | |
1257 &InstructionSelectorTest::Stream::IsDouble, | |
1258 {-1020, -948, -796, -696, -612, -364, -320, -308, -128, -112, -108, -104, | |
1259 -96, -84, -80, -56, -48, -40, -20, 0, 24, 28, 36, 48, 64, 84, 96, 100, | |
1260 108, 116, 120, 140, 156, 408, 432, 444, 772, 832, 940, 1020}}}; | |
1261 | |
1262 } // namespace | |
1263 | |
1264 | |
1265 typedef InstructionSelectorTestWithParam<MemoryAccess> | |
1266 InstructionSelectorMemoryAccessTest; | |
1267 | |
1268 | |
1269 TEST_P(InstructionSelectorMemoryAccessTest, LoadWithParameters) { | |
1270 const MemoryAccess memacc = GetParam(); | |
1271 StreamBuilder m(this, memacc.type, kMachPtr, kMachInt32); | |
1272 m.Return(m.Load(memacc.type, m.Parameter(0), m.Parameter(1))); | |
1273 Stream s = m.Build(); | |
1274 ASSERT_EQ(1U, s.size()); | |
1275 EXPECT_EQ(memacc.ldr_opcode, s[0]->arch_opcode()); | |
1276 EXPECT_EQ(kMode_Offset_RR, s[0]->addressing_mode()); | |
1277 EXPECT_EQ(2U, s[0]->InputCount()); | |
1278 ASSERT_EQ(1U, s[0]->OutputCount()); | |
1279 EXPECT_TRUE((s.*memacc.val_predicate)(s[0]->Output())); | |
1280 } | |
1281 | |
1282 | |
1283 TEST_P(InstructionSelectorMemoryAccessTest, LoadWithImmediateIndex) { | |
1284 const MemoryAccess memacc = GetParam(); | |
1285 TRACED_FOREACH(int32_t, index, memacc.immediates) { | |
1286 StreamBuilder m(this, memacc.type, kMachPtr); | |
1287 m.Return(m.Load(memacc.type, m.Parameter(0), m.Int32Constant(index))); | |
1288 Stream s = m.Build(); | |
1289 ASSERT_EQ(1U, s.size()); | |
1290 EXPECT_EQ(memacc.ldr_opcode, s[0]->arch_opcode()); | |
1291 EXPECT_EQ(kMode_Offset_RI, s[0]->addressing_mode()); | |
1292 ASSERT_EQ(2U, s[0]->InputCount()); | |
1293 ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind()); | |
1294 EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1))); | |
1295 ASSERT_EQ(1U, s[0]->OutputCount()); | |
1296 EXPECT_TRUE((s.*memacc.val_predicate)(s[0]->Output())); | |
1297 } | |
1298 } | |
1299 | |
1300 | |
1301 TEST_P(InstructionSelectorMemoryAccessTest, StoreWithParameters) { | |
1302 const MemoryAccess memacc = GetParam(); | |
1303 StreamBuilder m(this, kMachInt32, kMachPtr, kMachInt32, memacc.type); | |
1304 m.Store(memacc.type, m.Parameter(0), m.Parameter(1), m.Parameter(2)); | |
1305 m.Return(m.Int32Constant(0)); | |
1306 Stream s = m.Build(); | |
1307 ASSERT_EQ(1U, s.size()); | |
1308 EXPECT_EQ(memacc.str_opcode, s[0]->arch_opcode()); | |
1309 EXPECT_EQ(kMode_Offset_RR, s[0]->addressing_mode()); | |
1310 EXPECT_EQ(3U, s[0]->InputCount()); | |
1311 EXPECT_EQ(0U, s[0]->OutputCount()); | |
1312 } | |
1313 | |
1314 | |
1315 TEST_P(InstructionSelectorMemoryAccessTest, StoreWithImmediateIndex) { | |
1316 const MemoryAccess memacc = GetParam(); | |
1317 TRACED_FOREACH(int32_t, index, memacc.immediates) { | |
1318 StreamBuilder m(this, kMachInt32, kMachPtr, memacc.type); | |
1319 m.Store(memacc.type, m.Parameter(0), m.Int32Constant(index), | |
1320 m.Parameter(1)); | |
1321 m.Return(m.Int32Constant(0)); | |
1322 Stream s = m.Build(); | |
1323 ASSERT_EQ(1U, s.size()); | |
1324 EXPECT_EQ(memacc.str_opcode, s[0]->arch_opcode()); | |
1325 EXPECT_EQ(kMode_Offset_RI, s[0]->addressing_mode()); | |
1326 ASSERT_EQ(3U, s[0]->InputCount()); | |
1327 ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind()); | |
1328 EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1))); | |
1329 EXPECT_EQ(0U, s[0]->OutputCount()); | |
1330 } | |
1331 } | |
1332 | |
1333 | |
1334 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, | |
1335 InstructionSelectorMemoryAccessTest, | |
1336 ::testing::ValuesIn(kMemoryAccesses)); | |
1337 | |
1338 | |
1339 // ----------------------------------------------------------------------------- | |
1340 // Conversions. | |
1341 | |
1342 | |
1343 TEST_F(InstructionSelectorTest, ChangeFloat32ToFloat64WithParameter) { | |
1344 StreamBuilder m(this, kMachFloat64, kMachFloat32); | |
1345 m.Return(m.ChangeFloat32ToFloat64(m.Parameter(0))); | |
1346 Stream s = m.Build(); | |
1347 ASSERT_EQ(1U, s.size()); | |
1348 EXPECT_EQ(kArmVcvtF64F32, s[0]->arch_opcode()); | |
1349 EXPECT_EQ(1U, s[0]->InputCount()); | |
1350 EXPECT_EQ(1U, s[0]->OutputCount()); | |
1351 } | |
1352 | |
1353 | |
1354 TEST_F(InstructionSelectorTest, TruncateFloat64ToFloat32WithParameter) { | |
1355 StreamBuilder m(this, kMachFloat32, kMachFloat64); | |
1356 m.Return(m.TruncateFloat64ToFloat32(m.Parameter(0))); | |
1357 Stream s = m.Build(); | |
1358 ASSERT_EQ(1U, s.size()); | |
1359 EXPECT_EQ(kArmVcvtF32F64, s[0]->arch_opcode()); | |
1360 EXPECT_EQ(1U, s[0]->InputCount()); | |
1361 EXPECT_EQ(1U, s[0]->OutputCount()); | |
1362 } | |
1363 | |
1364 | |
1365 // ----------------------------------------------------------------------------- | |
1366 // Miscellaneous. | |
1367 | |
1368 | |
1369 TEST_F(InstructionSelectorTest, Int32AddWithInt32Mul) { | |
1370 { | |
1371 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32, kMachInt32); | |
1372 m.Return( | |
1373 m.Int32Add(m.Parameter(0), m.Int32Mul(m.Parameter(1), m.Parameter(2)))); | |
1374 Stream s = m.Build(); | |
1375 ASSERT_EQ(1U, s.size()); | |
1376 EXPECT_EQ(kArmMla, s[0]->arch_opcode()); | |
1377 EXPECT_EQ(3U, s[0]->InputCount()); | |
1378 EXPECT_EQ(1U, s[0]->OutputCount()); | |
1379 } | |
1380 { | |
1381 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32, kMachInt32); | |
1382 m.Return( | |
1383 m.Int32Add(m.Int32Mul(m.Parameter(1), m.Parameter(2)), m.Parameter(0))); | |
1384 Stream s = m.Build(); | |
1385 ASSERT_EQ(1U, s.size()); | |
1386 EXPECT_EQ(kArmMla, s[0]->arch_opcode()); | |
1387 EXPECT_EQ(3U, s[0]->InputCount()); | |
1388 EXPECT_EQ(1U, s[0]->OutputCount()); | |
1389 } | |
1390 } | |
1391 | |
1392 | |
1393 TEST_F(InstructionSelectorTest, Int32DivWithParameters) { | |
1394 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); | |
1395 m.Return(m.Int32Div(m.Parameter(0), m.Parameter(1))); | |
1396 Stream s = m.Build(); | |
1397 ASSERT_EQ(4U, s.size()); | |
1398 EXPECT_EQ(kArmVcvtF64S32, s[0]->arch_opcode()); | |
1399 ASSERT_EQ(1U, s[0]->OutputCount()); | |
1400 EXPECT_EQ(kArmVcvtF64S32, s[1]->arch_opcode()); | |
1401 ASSERT_EQ(1U, s[1]->OutputCount()); | |
1402 EXPECT_EQ(kArmVdivF64, s[2]->arch_opcode()); | |
1403 ASSERT_EQ(2U, s[2]->InputCount()); | |
1404 ASSERT_EQ(1U, s[2]->OutputCount()); | |
1405 EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[2]->InputAt(0))); | |
1406 EXPECT_EQ(s.ToVreg(s[1]->Output()), s.ToVreg(s[2]->InputAt(1))); | |
1407 EXPECT_EQ(kArmVcvtS32F64, s[3]->arch_opcode()); | |
1408 ASSERT_EQ(1U, s[3]->InputCount()); | |
1409 EXPECT_EQ(s.ToVreg(s[2]->Output()), s.ToVreg(s[3]->InputAt(0))); | |
1410 } | |
1411 | |
1412 | |
1413 TEST_F(InstructionSelectorTest, Int32DivWithParametersForSUDIV) { | |
1414 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); | |
1415 m.Return(m.Int32Div(m.Parameter(0), m.Parameter(1))); | |
1416 Stream s = m.Build(SUDIV); | |
1417 ASSERT_EQ(1U, s.size()); | |
1418 EXPECT_EQ(kArmSdiv, s[0]->arch_opcode()); | |
1419 } | |
1420 | |
1421 | |
1422 TEST_F(InstructionSelectorTest, Int32ModWithParameters) { | |
1423 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); | |
1424 m.Return(m.Int32Mod(m.Parameter(0), m.Parameter(1))); | |
1425 Stream s = m.Build(); | |
1426 ASSERT_EQ(6U, s.size()); | |
1427 EXPECT_EQ(kArmVcvtF64S32, s[0]->arch_opcode()); | |
1428 ASSERT_EQ(1U, s[0]->OutputCount()); | |
1429 EXPECT_EQ(kArmVcvtF64S32, s[1]->arch_opcode()); | |
1430 ASSERT_EQ(1U, s[1]->OutputCount()); | |
1431 EXPECT_EQ(kArmVdivF64, s[2]->arch_opcode()); | |
1432 ASSERT_EQ(2U, s[2]->InputCount()); | |
1433 ASSERT_EQ(1U, s[2]->OutputCount()); | |
1434 EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[2]->InputAt(0))); | |
1435 EXPECT_EQ(s.ToVreg(s[1]->Output()), s.ToVreg(s[2]->InputAt(1))); | |
1436 EXPECT_EQ(kArmVcvtS32F64, s[3]->arch_opcode()); | |
1437 ASSERT_EQ(1U, s[3]->InputCount()); | |
1438 EXPECT_EQ(s.ToVreg(s[2]->Output()), s.ToVreg(s[3]->InputAt(0))); | |
1439 EXPECT_EQ(kArmMul, s[4]->arch_opcode()); | |
1440 ASSERT_EQ(1U, s[4]->OutputCount()); | |
1441 ASSERT_EQ(2U, s[4]->InputCount()); | |
1442 EXPECT_EQ(s.ToVreg(s[3]->Output()), s.ToVreg(s[4]->InputAt(0))); | |
1443 EXPECT_EQ(s.ToVreg(s[1]->InputAt(0)), s.ToVreg(s[4]->InputAt(1))); | |
1444 EXPECT_EQ(kArmSub, s[5]->arch_opcode()); | |
1445 ASSERT_EQ(1U, s[5]->OutputCount()); | |
1446 ASSERT_EQ(2U, s[5]->InputCount()); | |
1447 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[5]->InputAt(0))); | |
1448 EXPECT_EQ(s.ToVreg(s[4]->Output()), s.ToVreg(s[5]->InputAt(1))); | |
1449 } | |
1450 | |
1451 | |
1452 TEST_F(InstructionSelectorTest, Int32ModWithParametersForSUDIV) { | |
1453 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); | |
1454 m.Return(m.Int32Mod(m.Parameter(0), m.Parameter(1))); | |
1455 Stream s = m.Build(SUDIV); | |
1456 ASSERT_EQ(3U, s.size()); | |
1457 EXPECT_EQ(kArmSdiv, s[0]->arch_opcode()); | |
1458 ASSERT_EQ(1U, s[0]->OutputCount()); | |
1459 ASSERT_EQ(2U, s[0]->InputCount()); | |
1460 EXPECT_EQ(kArmMul, s[1]->arch_opcode()); | |
1461 ASSERT_EQ(1U, s[1]->OutputCount()); | |
1462 ASSERT_EQ(2U, s[1]->InputCount()); | |
1463 EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(0))); | |
1464 EXPECT_EQ(s.ToVreg(s[0]->InputAt(1)), s.ToVreg(s[1]->InputAt(1))); | |
1465 EXPECT_EQ(kArmSub, s[2]->arch_opcode()); | |
1466 ASSERT_EQ(1U, s[2]->OutputCount()); | |
1467 ASSERT_EQ(2U, s[2]->InputCount()); | |
1468 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[2]->InputAt(0))); | |
1469 EXPECT_EQ(s.ToVreg(s[1]->Output()), s.ToVreg(s[2]->InputAt(1))); | |
1470 } | |
1471 | |
1472 | |
1473 TEST_F(InstructionSelectorTest, Int32ModWithParametersForSUDIVAndMLS) { | |
1474 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); | |
1475 m.Return(m.Int32Mod(m.Parameter(0), m.Parameter(1))); | |
1476 Stream s = m.Build(MLS, SUDIV); | |
1477 ASSERT_EQ(2U, s.size()); | |
1478 EXPECT_EQ(kArmSdiv, s[0]->arch_opcode()); | |
1479 ASSERT_EQ(1U, s[0]->OutputCount()); | |
1480 ASSERT_EQ(2U, s[0]->InputCount()); | |
1481 EXPECT_EQ(kArmMls, s[1]->arch_opcode()); | |
1482 ASSERT_EQ(1U, s[1]->OutputCount()); | |
1483 ASSERT_EQ(3U, s[1]->InputCount()); | |
1484 EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(0))); | |
1485 EXPECT_EQ(s.ToVreg(s[0]->InputAt(1)), s.ToVreg(s[1]->InputAt(1))); | |
1486 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[1]->InputAt(2))); | |
1487 } | |
1488 | |
1489 | |
1490 TEST_F(InstructionSelectorTest, Int32MulWithParameters) { | |
1491 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); | |
1492 m.Return(m.Int32Mul(m.Parameter(0), m.Parameter(1))); | |
1493 Stream s = m.Build(); | |
1494 ASSERT_EQ(1U, s.size()); | |
1495 EXPECT_EQ(kArmMul, s[0]->arch_opcode()); | |
1496 EXPECT_EQ(2U, s[0]->InputCount()); | |
1497 EXPECT_EQ(1U, s[0]->OutputCount()); | |
1498 } | |
1499 | |
1500 | |
1501 TEST_F(InstructionSelectorTest, Int32MulWithImmediate) { | |
1502 // x * (2^k + 1) -> x + (x >> k) | |
1503 TRACED_FORRANGE(int32_t, k, 1, 30) { | |
1504 StreamBuilder m(this, kMachInt32, kMachInt32); | |
1505 m.Return(m.Int32Mul(m.Parameter(0), m.Int32Constant((1 << k) + 1))); | |
1506 Stream s = m.Build(); | |
1507 ASSERT_EQ(1U, s.size()); | |
1508 EXPECT_EQ(kArmAdd, s[0]->arch_opcode()); | |
1509 EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode()); | |
1510 ASSERT_EQ(3U, s[0]->InputCount()); | |
1511 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1))); | |
1512 EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2))); | |
1513 EXPECT_EQ(1U, s[0]->OutputCount()); | |
1514 } | |
1515 // x * (2^k - 1) -> -x + (x >> k) | |
1516 TRACED_FORRANGE(int32_t, k, 3, 30) { | |
1517 StreamBuilder m(this, kMachInt32, kMachInt32); | |
1518 m.Return(m.Int32Mul(m.Parameter(0), m.Int32Constant((1 << k) - 1))); | |
1519 Stream s = m.Build(); | |
1520 ASSERT_EQ(1U, s.size()); | |
1521 EXPECT_EQ(kArmRsb, s[0]->arch_opcode()); | |
1522 EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode()); | |
1523 ASSERT_EQ(3U, s[0]->InputCount()); | |
1524 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1))); | |
1525 EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2))); | |
1526 EXPECT_EQ(1U, s[0]->OutputCount()); | |
1527 } | |
1528 // (2^k + 1) * x -> x + (x >> k) | |
1529 TRACED_FORRANGE(int32_t, k, 1, 30) { | |
1530 StreamBuilder m(this, kMachInt32, kMachInt32); | |
1531 m.Return(m.Int32Mul(m.Int32Constant((1 << k) + 1), m.Parameter(0))); | |
1532 Stream s = m.Build(); | |
1533 ASSERT_EQ(1U, s.size()); | |
1534 EXPECT_EQ(kArmAdd, s[0]->arch_opcode()); | |
1535 EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode()); | |
1536 ASSERT_EQ(3U, s[0]->InputCount()); | |
1537 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1))); | |
1538 EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2))); | |
1539 EXPECT_EQ(1U, s[0]->OutputCount()); | |
1540 } | |
1541 // x * (2^k - 1) -> -x + (x >> k) | |
1542 TRACED_FORRANGE(int32_t, k, 3, 30) { | |
1543 StreamBuilder m(this, kMachInt32, kMachInt32); | |
1544 m.Return(m.Int32Mul(m.Int32Constant((1 << k) - 1), m.Parameter(0))); | |
1545 Stream s = m.Build(); | |
1546 ASSERT_EQ(1U, s.size()); | |
1547 EXPECT_EQ(kArmRsb, s[0]->arch_opcode()); | |
1548 EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode()); | |
1549 ASSERT_EQ(3U, s[0]->InputCount()); | |
1550 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1))); | |
1551 EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2))); | |
1552 EXPECT_EQ(1U, s[0]->OutputCount()); | |
1553 } | |
1554 } | |
1555 | |
1556 | |
1557 TEST_F(InstructionSelectorTest, Int32SubWithInt32Mul) { | |
1558 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32, kMachInt32); | |
1559 m.Return( | |
1560 m.Int32Sub(m.Parameter(0), m.Int32Mul(m.Parameter(1), m.Parameter(2)))); | |
1561 Stream s = m.Build(); | |
1562 ASSERT_EQ(2U, s.size()); | |
1563 EXPECT_EQ(kArmMul, s[0]->arch_opcode()); | |
1564 ASSERT_EQ(1U, s[0]->OutputCount()); | |
1565 EXPECT_EQ(kArmSub, s[1]->arch_opcode()); | |
1566 ASSERT_EQ(2U, s[1]->InputCount()); | |
1567 EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(1))); | |
1568 } | |
1569 | |
1570 | |
1571 TEST_F(InstructionSelectorTest, Int32SubWithInt32MulForMLS) { | |
1572 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32, kMachInt32); | |
1573 m.Return( | |
1574 m.Int32Sub(m.Parameter(0), m.Int32Mul(m.Parameter(1), m.Parameter(2)))); | |
1575 Stream s = m.Build(MLS); | |
1576 ASSERT_EQ(1U, s.size()); | |
1577 EXPECT_EQ(kArmMls, s[0]->arch_opcode()); | |
1578 EXPECT_EQ(1U, s[0]->OutputCount()); | |
1579 EXPECT_EQ(3U, s[0]->InputCount()); | |
1580 } | |
1581 | |
1582 | |
1583 TEST_F(InstructionSelectorTest, Int32UDivWithParameters) { | |
1584 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); | |
1585 m.Return(m.Int32UDiv(m.Parameter(0), m.Parameter(1))); | |
1586 Stream s = m.Build(); | |
1587 ASSERT_EQ(4U, s.size()); | |
1588 EXPECT_EQ(kArmVcvtF64U32, s[0]->arch_opcode()); | |
1589 ASSERT_EQ(1U, s[0]->OutputCount()); | |
1590 EXPECT_EQ(kArmVcvtF64U32, s[1]->arch_opcode()); | |
1591 ASSERT_EQ(1U, s[1]->OutputCount()); | |
1592 EXPECT_EQ(kArmVdivF64, s[2]->arch_opcode()); | |
1593 ASSERT_EQ(2U, s[2]->InputCount()); | |
1594 ASSERT_EQ(1U, s[2]->OutputCount()); | |
1595 EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[2]->InputAt(0))); | |
1596 EXPECT_EQ(s.ToVreg(s[1]->Output()), s.ToVreg(s[2]->InputAt(1))); | |
1597 EXPECT_EQ(kArmVcvtU32F64, s[3]->arch_opcode()); | |
1598 ASSERT_EQ(1U, s[3]->InputCount()); | |
1599 EXPECT_EQ(s.ToVreg(s[2]->Output()), s.ToVreg(s[3]->InputAt(0))); | |
1600 } | |
1601 | |
1602 | |
1603 TEST_F(InstructionSelectorTest, Int32UDivWithParametersForSUDIV) { | |
1604 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); | |
1605 m.Return(m.Int32UDiv(m.Parameter(0), m.Parameter(1))); | |
1606 Stream s = m.Build(SUDIV); | |
1607 ASSERT_EQ(1U, s.size()); | |
1608 EXPECT_EQ(kArmUdiv, s[0]->arch_opcode()); | |
1609 } | |
1610 | |
1611 | |
1612 TEST_F(InstructionSelectorTest, Int32UModWithParameters) { | |
1613 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); | |
1614 m.Return(m.Int32UMod(m.Parameter(0), m.Parameter(1))); | |
1615 Stream s = m.Build(); | |
1616 ASSERT_EQ(6U, s.size()); | |
1617 EXPECT_EQ(kArmVcvtF64U32, s[0]->arch_opcode()); | |
1618 ASSERT_EQ(1U, s[0]->OutputCount()); | |
1619 EXPECT_EQ(kArmVcvtF64U32, s[1]->arch_opcode()); | |
1620 ASSERT_EQ(1U, s[1]->OutputCount()); | |
1621 EXPECT_EQ(kArmVdivF64, s[2]->arch_opcode()); | |
1622 ASSERT_EQ(2U, s[2]->InputCount()); | |
1623 ASSERT_EQ(1U, s[2]->OutputCount()); | |
1624 EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[2]->InputAt(0))); | |
1625 EXPECT_EQ(s.ToVreg(s[1]->Output()), s.ToVreg(s[2]->InputAt(1))); | |
1626 EXPECT_EQ(kArmVcvtU32F64, s[3]->arch_opcode()); | |
1627 ASSERT_EQ(1U, s[3]->InputCount()); | |
1628 EXPECT_EQ(s.ToVreg(s[2]->Output()), s.ToVreg(s[3]->InputAt(0))); | |
1629 EXPECT_EQ(kArmMul, s[4]->arch_opcode()); | |
1630 ASSERT_EQ(1U, s[4]->OutputCount()); | |
1631 ASSERT_EQ(2U, s[4]->InputCount()); | |
1632 EXPECT_EQ(s.ToVreg(s[3]->Output()), s.ToVreg(s[4]->InputAt(0))); | |
1633 EXPECT_EQ(s.ToVreg(s[1]->InputAt(0)), s.ToVreg(s[4]->InputAt(1))); | |
1634 EXPECT_EQ(kArmSub, s[5]->arch_opcode()); | |
1635 ASSERT_EQ(1U, s[5]->OutputCount()); | |
1636 ASSERT_EQ(2U, s[5]->InputCount()); | |
1637 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[5]->InputAt(0))); | |
1638 EXPECT_EQ(s.ToVreg(s[4]->Output()), s.ToVreg(s[5]->InputAt(1))); | |
1639 } | |
1640 | |
1641 | |
1642 TEST_F(InstructionSelectorTest, Int32UModWithParametersForSUDIV) { | |
1643 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); | |
1644 m.Return(m.Int32UMod(m.Parameter(0), m.Parameter(1))); | |
1645 Stream s = m.Build(SUDIV); | |
1646 ASSERT_EQ(3U, s.size()); | |
1647 EXPECT_EQ(kArmUdiv, s[0]->arch_opcode()); | |
1648 ASSERT_EQ(1U, s[0]->OutputCount()); | |
1649 ASSERT_EQ(2U, s[0]->InputCount()); | |
1650 EXPECT_EQ(kArmMul, s[1]->arch_opcode()); | |
1651 ASSERT_EQ(1U, s[1]->OutputCount()); | |
1652 ASSERT_EQ(2U, s[1]->InputCount()); | |
1653 EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(0))); | |
1654 EXPECT_EQ(s.ToVreg(s[0]->InputAt(1)), s.ToVreg(s[1]->InputAt(1))); | |
1655 EXPECT_EQ(kArmSub, s[2]->arch_opcode()); | |
1656 ASSERT_EQ(1U, s[2]->OutputCount()); | |
1657 ASSERT_EQ(2U, s[2]->InputCount()); | |
1658 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[2]->InputAt(0))); | |
1659 EXPECT_EQ(s.ToVreg(s[1]->Output()), s.ToVreg(s[2]->InputAt(1))); | |
1660 } | |
1661 | |
1662 | |
1663 TEST_F(InstructionSelectorTest, Int32UModWithParametersForSUDIVAndMLS) { | |
1664 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); | |
1665 m.Return(m.Int32UMod(m.Parameter(0), m.Parameter(1))); | |
1666 Stream s = m.Build(MLS, SUDIV); | |
1667 ASSERT_EQ(2U, s.size()); | |
1668 EXPECT_EQ(kArmUdiv, s[0]->arch_opcode()); | |
1669 ASSERT_EQ(1U, s[0]->OutputCount()); | |
1670 ASSERT_EQ(2U, s[0]->InputCount()); | |
1671 EXPECT_EQ(kArmMls, s[1]->arch_opcode()); | |
1672 ASSERT_EQ(1U, s[1]->OutputCount()); | |
1673 ASSERT_EQ(3U, s[1]->InputCount()); | |
1674 EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(0))); | |
1675 EXPECT_EQ(s.ToVreg(s[0]->InputAt(1)), s.ToVreg(s[1]->InputAt(1))); | |
1676 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[1]->InputAt(2))); | |
1677 } | |
1678 | |
1679 | |
1680 TEST_F(InstructionSelectorTest, Word32AndWithUbfxImmediateForARMv7) { | |
1681 TRACED_FORRANGE(int32_t, width, 1, 32) { | |
1682 StreamBuilder m(this, kMachInt32, kMachInt32); | |
1683 m.Return(m.Word32And(m.Parameter(0), | |
1684 m.Int32Constant(0xffffffffu >> (32 - width)))); | |
1685 Stream s = m.Build(ARMv7); | |
1686 ASSERT_EQ(1U, s.size()); | |
1687 EXPECT_EQ(kArmUbfx, s[0]->arch_opcode()); | |
1688 ASSERT_EQ(3U, s[0]->InputCount()); | |
1689 EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1))); | |
1690 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2))); | |
1691 } | |
1692 TRACED_FORRANGE(int32_t, width, 1, 32) { | |
1693 StreamBuilder m(this, kMachInt32, kMachInt32); | |
1694 m.Return(m.Word32And(m.Int32Constant(0xffffffffu >> (32 - width)), | |
1695 m.Parameter(0))); | |
1696 Stream s = m.Build(ARMv7); | |
1697 ASSERT_EQ(1U, s.size()); | |
1698 EXPECT_EQ(kArmUbfx, s[0]->arch_opcode()); | |
1699 ASSERT_EQ(3U, s[0]->InputCount()); | |
1700 EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1))); | |
1701 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2))); | |
1702 } | |
1703 } | |
1704 | |
1705 | |
1706 TEST_F(InstructionSelectorTest, Word32AndWithBfcImmediateForARMv7) { | |
1707 TRACED_FORRANGE(int32_t, lsb, 0, 31) { | |
1708 TRACED_FORRANGE(int32_t, width, 1, (32 - lsb) - 1) { | |
1709 StreamBuilder m(this, kMachInt32, kMachInt32); | |
1710 m.Return(m.Word32And( | |
1711 m.Parameter(0), | |
1712 m.Int32Constant(~((0xffffffffu >> (32 - width)) << lsb)))); | |
1713 Stream s = m.Build(ARMv7); | |
1714 ASSERT_EQ(1U, s.size()); | |
1715 EXPECT_EQ(kArmBfc, s[0]->arch_opcode()); | |
1716 ASSERT_EQ(1U, s[0]->OutputCount()); | |
1717 EXPECT_TRUE( | |
1718 UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy()); | |
1719 ASSERT_EQ(3U, s[0]->InputCount()); | |
1720 EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1))); | |
1721 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2))); | |
1722 } | |
1723 } | |
1724 TRACED_FORRANGE(int32_t, lsb, 0, 31) { | |
1725 TRACED_FORRANGE(int32_t, width, 1, (32 - lsb) - 1) { | |
1726 StreamBuilder m(this, kMachInt32, kMachInt32); | |
1727 m.Return( | |
1728 m.Word32And(m.Int32Constant(~((0xffffffffu >> (32 - width)) << lsb)), | |
1729 m.Parameter(0))); | |
1730 Stream s = m.Build(ARMv7); | |
1731 ASSERT_EQ(1U, s.size()); | |
1732 EXPECT_EQ(kArmBfc, s[0]->arch_opcode()); | |
1733 ASSERT_EQ(1U, s[0]->OutputCount()); | |
1734 EXPECT_TRUE( | |
1735 UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy()); | |
1736 ASSERT_EQ(3U, s[0]->InputCount()); | |
1737 EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1))); | |
1738 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2))); | |
1739 } | |
1740 } | |
1741 } | |
1742 | |
1743 | |
1744 TEST_F(InstructionSelectorTest, Word32ShrWithWord32AndWithImmediateForARMv7) { | |
1745 TRACED_FORRANGE(int32_t, lsb, 0, 31) { | |
1746 TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) { | |
1747 uint32_t max = 1 << lsb; | |
1748 if (max > static_cast<uint32_t>(kMaxInt)) max -= 1; | |
1749 uint32_t jnk = rng()->NextInt(max); | |
1750 uint32_t msk = ((0xffffffffu >> (32 - width)) << lsb) | jnk; | |
1751 StreamBuilder m(this, kMachInt32, kMachInt32); | |
1752 m.Return(m.Word32Shr(m.Word32And(m.Parameter(0), m.Int32Constant(msk)), | |
1753 m.Int32Constant(lsb))); | |
1754 Stream s = m.Build(ARMv7); | |
1755 ASSERT_EQ(1U, s.size()); | |
1756 EXPECT_EQ(kArmUbfx, s[0]->arch_opcode()); | |
1757 ASSERT_EQ(3U, s[0]->InputCount()); | |
1758 EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1))); | |
1759 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2))); | |
1760 } | |
1761 } | |
1762 TRACED_FORRANGE(int32_t, lsb, 0, 31) { | |
1763 TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) { | |
1764 uint32_t max = 1 << lsb; | |
1765 if (max > static_cast<uint32_t>(kMaxInt)) max -= 1; | |
1766 uint32_t jnk = rng()->NextInt(max); | |
1767 uint32_t msk = ((0xffffffffu >> (32 - width)) << lsb) | jnk; | |
1768 StreamBuilder m(this, kMachInt32, kMachInt32); | |
1769 m.Return(m.Word32Shr(m.Word32And(m.Int32Constant(msk), m.Parameter(0)), | |
1770 m.Int32Constant(lsb))); | |
1771 Stream s = m.Build(ARMv7); | |
1772 ASSERT_EQ(1U, s.size()); | |
1773 EXPECT_EQ(kArmUbfx, s[0]->arch_opcode()); | |
1774 ASSERT_EQ(3U, s[0]->InputCount()); | |
1775 EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1))); | |
1776 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2))); | |
1777 } | |
1778 } | |
1779 } | |
1780 | |
1781 | |
1782 TEST_F(InstructionSelectorTest, Word32AndWithWord32Not) { | |
1783 { | |
1784 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); | |
1785 m.Return(m.Word32And(m.Parameter(0), m.Word32Not(m.Parameter(1)))); | |
1786 Stream s = m.Build(); | |
1787 ASSERT_EQ(1U, s.size()); | |
1788 EXPECT_EQ(kArmBic, s[0]->arch_opcode()); | |
1789 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode()); | |
1790 EXPECT_EQ(2U, s[0]->InputCount()); | |
1791 EXPECT_EQ(1U, s[0]->OutputCount()); | |
1792 } | |
1793 { | |
1794 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); | |
1795 m.Return(m.Word32And(m.Word32Not(m.Parameter(0)), m.Parameter(1))); | |
1796 Stream s = m.Build(); | |
1797 ASSERT_EQ(1U, s.size()); | |
1798 EXPECT_EQ(kArmBic, s[0]->arch_opcode()); | |
1799 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode()); | |
1800 EXPECT_EQ(2U, s[0]->InputCount()); | |
1801 EXPECT_EQ(1U, s[0]->OutputCount()); | |
1802 } | |
1803 } | |
1804 | |
1805 | |
1806 TEST_F(InstructionSelectorTest, Word32EqualWithParameters) { | |
1807 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); | |
1808 m.Return(m.Word32Equal(m.Parameter(0), m.Parameter(1))); | |
1809 Stream s = m.Build(); | |
1810 ASSERT_EQ(1U, s.size()); | |
1811 EXPECT_EQ(kArmCmp, s[0]->arch_opcode()); | |
1812 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode()); | |
1813 EXPECT_EQ(2U, s[0]->InputCount()); | |
1814 EXPECT_EQ(1U, s[0]->OutputCount()); | |
1815 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); | |
1816 EXPECT_EQ(kEqual, s[0]->flags_condition()); | |
1817 } | |
1818 | |
1819 | |
1820 TEST_F(InstructionSelectorTest, Word32EqualWithImmediate) { | |
1821 TRACED_FOREACH(int32_t, imm, kImmediates) { | |
1822 if (imm == 0) continue; | |
1823 StreamBuilder m(this, kMachInt32, kMachInt32); | |
1824 m.Return(m.Word32Equal(m.Parameter(0), m.Int32Constant(imm))); | |
1825 Stream s = m.Build(); | |
1826 ASSERT_EQ(1U, s.size()); | |
1827 EXPECT_EQ(kArmCmp, s[0]->arch_opcode()); | |
1828 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode()); | |
1829 ASSERT_EQ(2U, s[0]->InputCount()); | |
1830 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); | |
1831 EXPECT_EQ(1U, s[0]->OutputCount()); | |
1832 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); | |
1833 EXPECT_EQ(kEqual, s[0]->flags_condition()); | |
1834 } | |
1835 TRACED_FOREACH(int32_t, imm, kImmediates) { | |
1836 if (imm == 0) continue; | |
1837 StreamBuilder m(this, kMachInt32, kMachInt32); | |
1838 m.Return(m.Word32Equal(m.Int32Constant(imm), m.Parameter(0))); | |
1839 Stream s = m.Build(); | |
1840 ASSERT_EQ(1U, s.size()); | |
1841 EXPECT_EQ(kArmCmp, s[0]->arch_opcode()); | |
1842 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode()); | |
1843 ASSERT_EQ(2U, s[0]->InputCount()); | |
1844 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); | |
1845 EXPECT_EQ(1U, s[0]->OutputCount()); | |
1846 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); | |
1847 EXPECT_EQ(kEqual, s[0]->flags_condition()); | |
1848 } | |
1849 } | |
1850 | |
1851 | |
1852 TEST_F(InstructionSelectorTest, Word32EqualWithZero) { | |
1853 { | |
1854 StreamBuilder m(this, kMachInt32, kMachInt32); | |
1855 m.Return(m.Word32Equal(m.Parameter(0), m.Int32Constant(0))); | |
1856 Stream s = m.Build(); | |
1857 ASSERT_EQ(1U, s.size()); | |
1858 EXPECT_EQ(kArmTst, s[0]->arch_opcode()); | |
1859 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode()); | |
1860 ASSERT_EQ(2U, s[0]->InputCount()); | |
1861 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1))); | |
1862 EXPECT_EQ(1U, s[0]->OutputCount()); | |
1863 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); | |
1864 EXPECT_EQ(kEqual, s[0]->flags_condition()); | |
1865 } | |
1866 { | |
1867 StreamBuilder m(this, kMachInt32, kMachInt32); | |
1868 m.Return(m.Word32Equal(m.Int32Constant(0), m.Parameter(0))); | |
1869 Stream s = m.Build(); | |
1870 ASSERT_EQ(1U, s.size()); | |
1871 EXPECT_EQ(kArmTst, s[0]->arch_opcode()); | |
1872 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode()); | |
1873 ASSERT_EQ(2U, s[0]->InputCount()); | |
1874 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1))); | |
1875 EXPECT_EQ(1U, s[0]->OutputCount()); | |
1876 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); | |
1877 EXPECT_EQ(kEqual, s[0]->flags_condition()); | |
1878 } | |
1879 } | |
1880 | |
1881 | |
1882 TEST_F(InstructionSelectorTest, Word32NotWithParameter) { | |
1883 StreamBuilder m(this, kMachInt32, kMachInt32); | |
1884 m.Return(m.Word32Not(m.Parameter(0))); | |
1885 Stream s = m.Build(); | |
1886 ASSERT_EQ(1U, s.size()); | |
1887 EXPECT_EQ(kArmMvn, s[0]->arch_opcode()); | |
1888 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode()); | |
1889 EXPECT_EQ(1U, s[0]->InputCount()); | |
1890 EXPECT_EQ(1U, s[0]->OutputCount()); | |
1891 } | |
1892 | |
1893 | |
1894 TEST_F(InstructionSelectorTest, Word32AndWithWord32ShrWithImmediateForARMv7) { | |
1895 TRACED_FORRANGE(int32_t, lsb, 0, 31) { | |
1896 TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) { | |
1897 StreamBuilder m(this, kMachInt32, kMachInt32); | |
1898 m.Return(m.Word32And(m.Word32Shr(m.Parameter(0), m.Int32Constant(lsb)), | |
1899 m.Int32Constant(0xffffffffu >> (32 - width)))); | |
1900 Stream s = m.Build(ARMv7); | |
1901 ASSERT_EQ(1U, s.size()); | |
1902 EXPECT_EQ(kArmUbfx, s[0]->arch_opcode()); | |
1903 ASSERT_EQ(3U, s[0]->InputCount()); | |
1904 EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1))); | |
1905 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2))); | |
1906 } | |
1907 } | |
1908 TRACED_FORRANGE(int32_t, lsb, 0, 31) { | |
1909 TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) { | |
1910 StreamBuilder m(this, kMachInt32, kMachInt32); | |
1911 m.Return(m.Word32And(m.Int32Constant(0xffffffffu >> (32 - width)), | |
1912 m.Word32Shr(m.Parameter(0), m.Int32Constant(lsb)))); | |
1913 Stream s = m.Build(ARMv7); | |
1914 ASSERT_EQ(1U, s.size()); | |
1915 EXPECT_EQ(kArmUbfx, s[0]->arch_opcode()); | |
1916 ASSERT_EQ(3U, s[0]->InputCount()); | |
1917 EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1))); | |
1918 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2))); | |
1919 } | |
1920 } | |
1921 } | |
1922 | |
1923 } // namespace compiler | |
1924 } // namespace internal | |
1925 } // namespace v8 | |
OLD | NEW |