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