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
operator <<(std::ostream & os,const DPI & dpi)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
operator <<(std::ostream & os,const ODPI & odpi)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
operator <<(std::ostream & os,const Shift & shift)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
TEST_P(InstructionSelectorDPITest,Parameters)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
TEST_P(InstructionSelectorDPITest,Immediate)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
TEST_P(InstructionSelectorDPITest,ShiftByParameter)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
TEST_P(InstructionSelectorDPITest,ShiftByImmediate)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
TEST_P(InstructionSelectorDPITest,BranchWithParameters)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
TEST_P(InstructionSelectorDPITest,BranchWithImmediate)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
TEST_P(InstructionSelectorDPITest,BranchWithShiftByParameter)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
TEST_P(InstructionSelectorDPITest,BranchWithShiftByImmediate)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
TEST_P(InstructionSelectorDPITest,BranchIfZeroWithParameters)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
TEST_P(InstructionSelectorDPITest,BranchIfNotZeroWithParameters)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
TEST_P(InstructionSelectorDPITest,BranchIfZeroWithImmediate)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
TEST_P(InstructionSelectorDPITest,BranchIfNotZeroWithImmediate)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
TEST_P(InstructionSelectorODPITest,OvfWithParameters)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
TEST_P(InstructionSelectorODPITest,OvfWithImmediate)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
TEST_P(InstructionSelectorODPITest,OvfWithShiftByParameter)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
TEST_P(InstructionSelectorODPITest,OvfWithShiftByImmediate)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
TEST_P(InstructionSelectorODPITest,ValWithParameters)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
TEST_P(InstructionSelectorODPITest,ValWithImmediate)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
TEST_P(InstructionSelectorODPITest,ValWithShiftByParameter)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
TEST_P(InstructionSelectorODPITest,ValWithShiftByImmediate)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
TEST_P(InstructionSelectorODPITest,BothWithParameters)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
TEST_P(InstructionSelectorODPITest,BothWithImmediate)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
TEST_P(InstructionSelectorODPITest,BothWithShiftByParameter)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
TEST_P(InstructionSelectorODPITest,BothWithShiftByImmediate)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
TEST_P(InstructionSelectorODPITest,BranchWithParameters)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
TEST_P(InstructionSelectorODPITest,BranchWithImmediate)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
TEST_P(InstructionSelectorODPITest,BranchIfZeroWithParameters)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
TEST_P(InstructionSelectorODPITest,BranchIfNotZeroWithParameters)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
TEST_P(InstructionSelectorShiftTest,Parameters)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
TEST_P(InstructionSelectorShiftTest,Immediate)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
TEST_P(InstructionSelectorShiftTest,Word32EqualWithParameter)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
TEST_P(InstructionSelectorShiftTest,Word32EqualWithParameterAndImmediate)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
TEST_P(InstructionSelectorShiftTest,Word32EqualToZeroWithParameters)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
TEST_P(InstructionSelectorShiftTest,Word32EqualToZeroWithImmediate)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
TEST_P(InstructionSelectorShiftTest,Word32NotWithParameters)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
TEST_P(InstructionSelectorShiftTest,Word32NotWithImmediate)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
TEST_P(InstructionSelectorShiftTest,Word32AndWithWord32NotWithParameters)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
TEST_P(InstructionSelectorShiftTest,Word32AndWithWord32NotWithImmediate)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
operator <<(std::ostream & os,const MemoryAccess & memacc)1206 std::ostream& operator<<(std::ostream& os, const MemoryAccess& memacc) {
1207 OStringStream ost;
1208 ost << memacc.type;
1209 return os << ost.c_str();
1210 }
1211
1212
1213 static const MemoryAccess kMemoryAccesses[] = {
1214 {kMachInt8,
1215 kArmLdrsb,
1216 kArmStrb,
1217 &InstructionSelectorTest::Stream::IsInteger,
1218 {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89,
1219 -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109,
1220 115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}},
1221 {kMachUint8,
1222 kArmLdrb,
1223 kArmStrb,
1224 &InstructionSelectorTest::Stream::IsInteger,
1225 {-4095, -3914, -3536, -3234, -3185, -3169, -1073, -990, -859, -720, -434,
1226 -127, -124, -122, -105, -91, -86, -64, -55, -53, -30, -10, -3, 0, 20, 28,
1227 39, 58, 64, 73, 75, 100, 108, 121, 686, 963, 1363, 2759, 3449, 4095}},
1228 {kMachInt16,
1229 kArmLdrsh,
1230 kArmStrh,
1231 &InstructionSelectorTest::Stream::IsInteger,
1232 {-255, -251, -232, -220, -144, -138, -130, -126, -116, -115, -102, -101,
1233 -98, -69, -59, -56, -39, -35, -23, -19, -7, 0, 22, 26, 37, 68, 83, 87, 98,
1234 102, 108, 111, 117, 171, 195, 203, 204, 245, 246, 255}},
1235 {kMachUint16,
1236 kArmLdrh,
1237 kArmStrh,
1238 &InstructionSelectorTest::Stream::IsInteger,
1239 {-255, -230, -201, -172, -125, -119, -118, -105, -98, -79, -54, -42, -41,
1240 -32, -12, -11, -5, -4, 0, 5, 9, 25, 28, 51, 58, 60, 89, 104, 108, 109,
1241 114, 116, 120, 138, 150, 161, 166, 172, 228, 255}},
1242 {kMachInt32,
1243 kArmLdr,
1244 kArmStr,
1245 &InstructionSelectorTest::Stream::IsInteger,
1246 {-4095, -1898, -1685, -1562, -1408, -1313, -344, -128, -116, -100, -92,
1247 -80, -72, -71, -56, -25, -21, -11, -9, 0, 3, 5, 27, 28, 42, 52, 63, 88,
1248 93, 97, 125, 846, 1037, 2102, 2403, 2597, 2632, 2997, 3935, 4095}},
1249 {kMachFloat32,
1250 kArmVldr32,
1251 kArmVstr32,
1252 &InstructionSelectorTest::Stream::IsDouble,
1253 {-1020, -928, -896, -772, -728, -680, -660, -488, -372, -112, -100, -92,
1254 -84, -80, -72, -64, -60, -56, -52, -48, -36, -32, -20, -8, -4, 0, 8, 20,
1255 24, 40, 64, 112, 204, 388, 516, 852, 856, 976, 988, 1020}},
1256 {kMachFloat64,
1257 kArmVldr64,
1258 kArmVstr64,
1259 &InstructionSelectorTest::Stream::IsDouble,
1260 {-1020, -948, -796, -696, -612, -364, -320, -308, -128, -112, -108, -104,
1261 -96, -84, -80, -56, -48, -40, -20, 0, 24, 28, 36, 48, 64, 84, 96, 100,
1262 108, 116, 120, 140, 156, 408, 432, 444, 772, 832, 940, 1020}}};
1263
1264 } // namespace
1265
1266
1267 typedef InstructionSelectorTestWithParam<MemoryAccess>
1268 InstructionSelectorMemoryAccessTest;
1269
1270
TEST_P(InstructionSelectorMemoryAccessTest,LoadWithParameters)1271 TEST_P(InstructionSelectorMemoryAccessTest, LoadWithParameters) {
1272 const MemoryAccess memacc = GetParam();
1273 StreamBuilder m(this, memacc.type, kMachPtr, kMachInt32);
1274 m.Return(m.Load(memacc.type, m.Parameter(0), m.Parameter(1)));
1275 Stream s = m.Build();
1276 ASSERT_EQ(1U, s.size());
1277 EXPECT_EQ(memacc.ldr_opcode, s[0]->arch_opcode());
1278 EXPECT_EQ(kMode_Offset_RR, s[0]->addressing_mode());
1279 EXPECT_EQ(2U, s[0]->InputCount());
1280 ASSERT_EQ(1U, s[0]->OutputCount());
1281 EXPECT_TRUE((s.*memacc.val_predicate)(s[0]->Output()));
1282 }
1283
1284
TEST_P(InstructionSelectorMemoryAccessTest,LoadWithImmediateIndex)1285 TEST_P(InstructionSelectorMemoryAccessTest, LoadWithImmediateIndex) {
1286 const MemoryAccess memacc = GetParam();
1287 TRACED_FOREACH(int32_t, index, memacc.immediates) {
1288 StreamBuilder m(this, memacc.type, kMachPtr);
1289 m.Return(m.Load(memacc.type, m.Parameter(0), m.Int32Constant(index)));
1290 Stream s = m.Build();
1291 ASSERT_EQ(1U, s.size());
1292 EXPECT_EQ(memacc.ldr_opcode, s[0]->arch_opcode());
1293 EXPECT_EQ(kMode_Offset_RI, s[0]->addressing_mode());
1294 ASSERT_EQ(2U, s[0]->InputCount());
1295 ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
1296 EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1)));
1297 ASSERT_EQ(1U, s[0]->OutputCount());
1298 EXPECT_TRUE((s.*memacc.val_predicate)(s[0]->Output()));
1299 }
1300 }
1301
1302
TEST_P(InstructionSelectorMemoryAccessTest,StoreWithParameters)1303 TEST_P(InstructionSelectorMemoryAccessTest, StoreWithParameters) {
1304 const MemoryAccess memacc = GetParam();
1305 StreamBuilder m(this, kMachInt32, kMachPtr, kMachInt32, memacc.type);
1306 m.Store(memacc.type, m.Parameter(0), m.Parameter(1), m.Parameter(2));
1307 m.Return(m.Int32Constant(0));
1308 Stream s = m.Build();
1309 ASSERT_EQ(1U, s.size());
1310 EXPECT_EQ(memacc.str_opcode, s[0]->arch_opcode());
1311 EXPECT_EQ(kMode_Offset_RR, s[0]->addressing_mode());
1312 EXPECT_EQ(3U, s[0]->InputCount());
1313 EXPECT_EQ(0U, s[0]->OutputCount());
1314 }
1315
1316
TEST_P(InstructionSelectorMemoryAccessTest,StoreWithImmediateIndex)1317 TEST_P(InstructionSelectorMemoryAccessTest, StoreWithImmediateIndex) {
1318 const MemoryAccess memacc = GetParam();
1319 TRACED_FOREACH(int32_t, index, memacc.immediates) {
1320 StreamBuilder m(this, kMachInt32, kMachPtr, memacc.type);
1321 m.Store(memacc.type, m.Parameter(0), m.Int32Constant(index),
1322 m.Parameter(1));
1323 m.Return(m.Int32Constant(0));
1324 Stream s = m.Build();
1325 ASSERT_EQ(1U, s.size());
1326 EXPECT_EQ(memacc.str_opcode, s[0]->arch_opcode());
1327 EXPECT_EQ(kMode_Offset_RI, s[0]->addressing_mode());
1328 ASSERT_EQ(3U, s[0]->InputCount());
1329 ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
1330 EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1)));
1331 EXPECT_EQ(0U, s[0]->OutputCount());
1332 }
1333 }
1334
1335
1336 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1337 InstructionSelectorMemoryAccessTest,
1338 ::testing::ValuesIn(kMemoryAccesses));
1339
1340
1341 // -----------------------------------------------------------------------------
1342 // Miscellaneous.
1343
1344
TEST_F(InstructionSelectorTest,Int32AddWithInt32Mul)1345 TEST_F(InstructionSelectorTest, Int32AddWithInt32Mul) {
1346 {
1347 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32, kMachInt32);
1348 m.Return(
1349 m.Int32Add(m.Parameter(0), m.Int32Mul(m.Parameter(1), m.Parameter(2))));
1350 Stream s = m.Build();
1351 ASSERT_EQ(1U, s.size());
1352 EXPECT_EQ(kArmMla, s[0]->arch_opcode());
1353 EXPECT_EQ(3U, s[0]->InputCount());
1354 EXPECT_EQ(1U, s[0]->OutputCount());
1355 }
1356 {
1357 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32, kMachInt32);
1358 m.Return(
1359 m.Int32Add(m.Int32Mul(m.Parameter(1), m.Parameter(2)), m.Parameter(0)));
1360 Stream s = m.Build();
1361 ASSERT_EQ(1U, s.size());
1362 EXPECT_EQ(kArmMla, s[0]->arch_opcode());
1363 EXPECT_EQ(3U, s[0]->InputCount());
1364 EXPECT_EQ(1U, s[0]->OutputCount());
1365 }
1366 }
1367
1368
TEST_F(InstructionSelectorTest,Int32DivWithParameters)1369 TEST_F(InstructionSelectorTest, Int32DivWithParameters) {
1370 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
1371 m.Return(m.Int32Div(m.Parameter(0), m.Parameter(1)));
1372 Stream s = m.Build();
1373 ASSERT_EQ(4U, s.size());
1374 EXPECT_EQ(kArmVcvtF64S32, s[0]->arch_opcode());
1375 ASSERT_EQ(1U, s[0]->OutputCount());
1376 EXPECT_EQ(kArmVcvtF64S32, s[1]->arch_opcode());
1377 ASSERT_EQ(1U, s[1]->OutputCount());
1378 EXPECT_EQ(kArmVdivF64, s[2]->arch_opcode());
1379 ASSERT_EQ(2U, s[2]->InputCount());
1380 ASSERT_EQ(1U, s[2]->OutputCount());
1381 EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[2]->InputAt(0)));
1382 EXPECT_EQ(s.ToVreg(s[1]->Output()), s.ToVreg(s[2]->InputAt(1)));
1383 EXPECT_EQ(kArmVcvtS32F64, s[3]->arch_opcode());
1384 ASSERT_EQ(1U, s[3]->InputCount());
1385 EXPECT_EQ(s.ToVreg(s[2]->Output()), s.ToVreg(s[3]->InputAt(0)));
1386 }
1387
1388
TEST_F(InstructionSelectorTest,Int32DivWithParametersForSUDIV)1389 TEST_F(InstructionSelectorTest, Int32DivWithParametersForSUDIV) {
1390 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
1391 m.Return(m.Int32Div(m.Parameter(0), m.Parameter(1)));
1392 Stream s = m.Build(SUDIV);
1393 ASSERT_EQ(1U, s.size());
1394 EXPECT_EQ(kArmSdiv, s[0]->arch_opcode());
1395 }
1396
1397
TEST_F(InstructionSelectorTest,Int32ModWithParameters)1398 TEST_F(InstructionSelectorTest, Int32ModWithParameters) {
1399 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
1400 m.Return(m.Int32Mod(m.Parameter(0), m.Parameter(1)));
1401 Stream s = m.Build();
1402 ASSERT_EQ(6U, s.size());
1403 EXPECT_EQ(kArmVcvtF64S32, s[0]->arch_opcode());
1404 ASSERT_EQ(1U, s[0]->OutputCount());
1405 EXPECT_EQ(kArmVcvtF64S32, s[1]->arch_opcode());
1406 ASSERT_EQ(1U, s[1]->OutputCount());
1407 EXPECT_EQ(kArmVdivF64, s[2]->arch_opcode());
1408 ASSERT_EQ(2U, s[2]->InputCount());
1409 ASSERT_EQ(1U, s[2]->OutputCount());
1410 EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[2]->InputAt(0)));
1411 EXPECT_EQ(s.ToVreg(s[1]->Output()), s.ToVreg(s[2]->InputAt(1)));
1412 EXPECT_EQ(kArmVcvtS32F64, s[3]->arch_opcode());
1413 ASSERT_EQ(1U, s[3]->InputCount());
1414 EXPECT_EQ(s.ToVreg(s[2]->Output()), s.ToVreg(s[3]->InputAt(0)));
1415 EXPECT_EQ(kArmMul, s[4]->arch_opcode());
1416 ASSERT_EQ(1U, s[4]->OutputCount());
1417 ASSERT_EQ(2U, s[4]->InputCount());
1418 EXPECT_EQ(s.ToVreg(s[3]->Output()), s.ToVreg(s[4]->InputAt(0)));
1419 EXPECT_EQ(s.ToVreg(s[1]->InputAt(0)), s.ToVreg(s[4]->InputAt(1)));
1420 EXPECT_EQ(kArmSub, s[5]->arch_opcode());
1421 ASSERT_EQ(1U, s[5]->OutputCount());
1422 ASSERT_EQ(2U, s[5]->InputCount());
1423 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[5]->InputAt(0)));
1424 EXPECT_EQ(s.ToVreg(s[4]->Output()), s.ToVreg(s[5]->InputAt(1)));
1425 }
1426
1427
TEST_F(InstructionSelectorTest,Int32ModWithParametersForSUDIV)1428 TEST_F(InstructionSelectorTest, Int32ModWithParametersForSUDIV) {
1429 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
1430 m.Return(m.Int32Mod(m.Parameter(0), m.Parameter(1)));
1431 Stream s = m.Build(SUDIV);
1432 ASSERT_EQ(3U, s.size());
1433 EXPECT_EQ(kArmSdiv, s[0]->arch_opcode());
1434 ASSERT_EQ(1U, s[0]->OutputCount());
1435 ASSERT_EQ(2U, s[0]->InputCount());
1436 EXPECT_EQ(kArmMul, s[1]->arch_opcode());
1437 ASSERT_EQ(1U, s[1]->OutputCount());
1438 ASSERT_EQ(2U, s[1]->InputCount());
1439 EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(0)));
1440 EXPECT_EQ(s.ToVreg(s[0]->InputAt(1)), s.ToVreg(s[1]->InputAt(1)));
1441 EXPECT_EQ(kArmSub, s[2]->arch_opcode());
1442 ASSERT_EQ(1U, s[2]->OutputCount());
1443 ASSERT_EQ(2U, s[2]->InputCount());
1444 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[2]->InputAt(0)));
1445 EXPECT_EQ(s.ToVreg(s[1]->Output()), s.ToVreg(s[2]->InputAt(1)));
1446 }
1447
1448
TEST_F(InstructionSelectorTest,Int32ModWithParametersForSUDIVAndMLS)1449 TEST_F(InstructionSelectorTest, Int32ModWithParametersForSUDIVAndMLS) {
1450 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
1451 m.Return(m.Int32Mod(m.Parameter(0), m.Parameter(1)));
1452 Stream s = m.Build(MLS, SUDIV);
1453 ASSERT_EQ(2U, s.size());
1454 EXPECT_EQ(kArmSdiv, s[0]->arch_opcode());
1455 ASSERT_EQ(1U, s[0]->OutputCount());
1456 ASSERT_EQ(2U, s[0]->InputCount());
1457 EXPECT_EQ(kArmMls, s[1]->arch_opcode());
1458 ASSERT_EQ(1U, s[1]->OutputCount());
1459 ASSERT_EQ(3U, s[1]->InputCount());
1460 EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(0)));
1461 EXPECT_EQ(s.ToVreg(s[0]->InputAt(1)), s.ToVreg(s[1]->InputAt(1)));
1462 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[1]->InputAt(2)));
1463 }
1464
1465
TEST_F(InstructionSelectorTest,Int32MulWithParameters)1466 TEST_F(InstructionSelectorTest, Int32MulWithParameters) {
1467 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
1468 m.Return(m.Int32Mul(m.Parameter(0), m.Parameter(1)));
1469 Stream s = m.Build();
1470 ASSERT_EQ(1U, s.size());
1471 EXPECT_EQ(kArmMul, s[0]->arch_opcode());
1472 EXPECT_EQ(2U, s[0]->InputCount());
1473 EXPECT_EQ(1U, s[0]->OutputCount());
1474 }
1475
1476
TEST_F(InstructionSelectorTest,Int32MulWithImmediate)1477 TEST_F(InstructionSelectorTest, Int32MulWithImmediate) {
1478 // x * (2^k + 1) -> x + (x >> k)
1479 TRACED_FORRANGE(int32_t, k, 1, 30) {
1480 StreamBuilder m(this, kMachInt32, kMachInt32);
1481 m.Return(m.Int32Mul(m.Parameter(0), m.Int32Constant((1 << k) + 1)));
1482 Stream s = m.Build();
1483 ASSERT_EQ(1U, s.size());
1484 EXPECT_EQ(kArmAdd, s[0]->arch_opcode());
1485 EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
1486 ASSERT_EQ(3U, s[0]->InputCount());
1487 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
1488 EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2)));
1489 EXPECT_EQ(1U, s[0]->OutputCount());
1490 }
1491 // x * (2^k - 1) -> -x + (x >> k)
1492 TRACED_FORRANGE(int32_t, k, 3, 30) {
1493 StreamBuilder m(this, kMachInt32, kMachInt32);
1494 m.Return(m.Int32Mul(m.Parameter(0), m.Int32Constant((1 << k) - 1)));
1495 Stream s = m.Build();
1496 ASSERT_EQ(1U, s.size());
1497 EXPECT_EQ(kArmRsb, s[0]->arch_opcode());
1498 EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
1499 ASSERT_EQ(3U, s[0]->InputCount());
1500 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
1501 EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2)));
1502 EXPECT_EQ(1U, s[0]->OutputCount());
1503 }
1504 // (2^k + 1) * x -> x + (x >> k)
1505 TRACED_FORRANGE(int32_t, k, 1, 30) {
1506 StreamBuilder m(this, kMachInt32, kMachInt32);
1507 m.Return(m.Int32Mul(m.Int32Constant((1 << k) + 1), m.Parameter(0)));
1508 Stream s = m.Build();
1509 ASSERT_EQ(1U, s.size());
1510 EXPECT_EQ(kArmAdd, s[0]->arch_opcode());
1511 EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
1512 ASSERT_EQ(3U, s[0]->InputCount());
1513 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
1514 EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2)));
1515 EXPECT_EQ(1U, s[0]->OutputCount());
1516 }
1517 // x * (2^k - 1) -> -x + (x >> k)
1518 TRACED_FORRANGE(int32_t, k, 3, 30) {
1519 StreamBuilder m(this, kMachInt32, kMachInt32);
1520 m.Return(m.Int32Mul(m.Int32Constant((1 << k) - 1), m.Parameter(0)));
1521 Stream s = m.Build();
1522 ASSERT_EQ(1U, s.size());
1523 EXPECT_EQ(kArmRsb, s[0]->arch_opcode());
1524 EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
1525 ASSERT_EQ(3U, s[0]->InputCount());
1526 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
1527 EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2)));
1528 EXPECT_EQ(1U, s[0]->OutputCount());
1529 }
1530 }
1531
1532
TEST_F(InstructionSelectorTest,Int32SubWithInt32Mul)1533 TEST_F(InstructionSelectorTest, Int32SubWithInt32Mul) {
1534 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32, kMachInt32);
1535 m.Return(
1536 m.Int32Sub(m.Parameter(0), m.Int32Mul(m.Parameter(1), m.Parameter(2))));
1537 Stream s = m.Build();
1538 ASSERT_EQ(2U, s.size());
1539 EXPECT_EQ(kArmMul, s[0]->arch_opcode());
1540 ASSERT_EQ(1U, s[0]->OutputCount());
1541 EXPECT_EQ(kArmSub, s[1]->arch_opcode());
1542 ASSERT_EQ(2U, s[1]->InputCount());
1543 EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(1)));
1544 }
1545
1546
TEST_F(InstructionSelectorTest,Int32SubWithInt32MulForMLS)1547 TEST_F(InstructionSelectorTest, Int32SubWithInt32MulForMLS) {
1548 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32, kMachInt32);
1549 m.Return(
1550 m.Int32Sub(m.Parameter(0), m.Int32Mul(m.Parameter(1), m.Parameter(2))));
1551 Stream s = m.Build(MLS);
1552 ASSERT_EQ(1U, s.size());
1553 EXPECT_EQ(kArmMls, s[0]->arch_opcode());
1554 EXPECT_EQ(1U, s[0]->OutputCount());
1555 EXPECT_EQ(3U, s[0]->InputCount());
1556 }
1557
1558
TEST_F(InstructionSelectorTest,Int32UDivWithParameters)1559 TEST_F(InstructionSelectorTest, Int32UDivWithParameters) {
1560 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
1561 m.Return(m.Int32UDiv(m.Parameter(0), m.Parameter(1)));
1562 Stream s = m.Build();
1563 ASSERT_EQ(4U, s.size());
1564 EXPECT_EQ(kArmVcvtF64U32, s[0]->arch_opcode());
1565 ASSERT_EQ(1U, s[0]->OutputCount());
1566 EXPECT_EQ(kArmVcvtF64U32, s[1]->arch_opcode());
1567 ASSERT_EQ(1U, s[1]->OutputCount());
1568 EXPECT_EQ(kArmVdivF64, s[2]->arch_opcode());
1569 ASSERT_EQ(2U, s[2]->InputCount());
1570 ASSERT_EQ(1U, s[2]->OutputCount());
1571 EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[2]->InputAt(0)));
1572 EXPECT_EQ(s.ToVreg(s[1]->Output()), s.ToVreg(s[2]->InputAt(1)));
1573 EXPECT_EQ(kArmVcvtU32F64, s[3]->arch_opcode());
1574 ASSERT_EQ(1U, s[3]->InputCount());
1575 EXPECT_EQ(s.ToVreg(s[2]->Output()), s.ToVreg(s[3]->InputAt(0)));
1576 }
1577
1578
TEST_F(InstructionSelectorTest,Int32UDivWithParametersForSUDIV)1579 TEST_F(InstructionSelectorTest, Int32UDivWithParametersForSUDIV) {
1580 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
1581 m.Return(m.Int32UDiv(m.Parameter(0), m.Parameter(1)));
1582 Stream s = m.Build(SUDIV);
1583 ASSERT_EQ(1U, s.size());
1584 EXPECT_EQ(kArmUdiv, s[0]->arch_opcode());
1585 }
1586
1587
TEST_F(InstructionSelectorTest,Int32UModWithParameters)1588 TEST_F(InstructionSelectorTest, Int32UModWithParameters) {
1589 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
1590 m.Return(m.Int32UMod(m.Parameter(0), m.Parameter(1)));
1591 Stream s = m.Build();
1592 ASSERT_EQ(6U, s.size());
1593 EXPECT_EQ(kArmVcvtF64U32, s[0]->arch_opcode());
1594 ASSERT_EQ(1U, s[0]->OutputCount());
1595 EXPECT_EQ(kArmVcvtF64U32, s[1]->arch_opcode());
1596 ASSERT_EQ(1U, s[1]->OutputCount());
1597 EXPECT_EQ(kArmVdivF64, s[2]->arch_opcode());
1598 ASSERT_EQ(2U, s[2]->InputCount());
1599 ASSERT_EQ(1U, s[2]->OutputCount());
1600 EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[2]->InputAt(0)));
1601 EXPECT_EQ(s.ToVreg(s[1]->Output()), s.ToVreg(s[2]->InputAt(1)));
1602 EXPECT_EQ(kArmVcvtU32F64, s[3]->arch_opcode());
1603 ASSERT_EQ(1U, s[3]->InputCount());
1604 EXPECT_EQ(s.ToVreg(s[2]->Output()), s.ToVreg(s[3]->InputAt(0)));
1605 EXPECT_EQ(kArmMul, s[4]->arch_opcode());
1606 ASSERT_EQ(1U, s[4]->OutputCount());
1607 ASSERT_EQ(2U, s[4]->InputCount());
1608 EXPECT_EQ(s.ToVreg(s[3]->Output()), s.ToVreg(s[4]->InputAt(0)));
1609 EXPECT_EQ(s.ToVreg(s[1]->InputAt(0)), s.ToVreg(s[4]->InputAt(1)));
1610 EXPECT_EQ(kArmSub, s[5]->arch_opcode());
1611 ASSERT_EQ(1U, s[5]->OutputCount());
1612 ASSERT_EQ(2U, s[5]->InputCount());
1613 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[5]->InputAt(0)));
1614 EXPECT_EQ(s.ToVreg(s[4]->Output()), s.ToVreg(s[5]->InputAt(1)));
1615 }
1616
1617
TEST_F(InstructionSelectorTest,Int32UModWithParametersForSUDIV)1618 TEST_F(InstructionSelectorTest, Int32UModWithParametersForSUDIV) {
1619 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
1620 m.Return(m.Int32UMod(m.Parameter(0), m.Parameter(1)));
1621 Stream s = m.Build(SUDIV);
1622 ASSERT_EQ(3U, s.size());
1623 EXPECT_EQ(kArmUdiv, s[0]->arch_opcode());
1624 ASSERT_EQ(1U, s[0]->OutputCount());
1625 ASSERT_EQ(2U, s[0]->InputCount());
1626 EXPECT_EQ(kArmMul, s[1]->arch_opcode());
1627 ASSERT_EQ(1U, s[1]->OutputCount());
1628 ASSERT_EQ(2U, s[1]->InputCount());
1629 EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(0)));
1630 EXPECT_EQ(s.ToVreg(s[0]->InputAt(1)), s.ToVreg(s[1]->InputAt(1)));
1631 EXPECT_EQ(kArmSub, s[2]->arch_opcode());
1632 ASSERT_EQ(1U, s[2]->OutputCount());
1633 ASSERT_EQ(2U, s[2]->InputCount());
1634 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[2]->InputAt(0)));
1635 EXPECT_EQ(s.ToVreg(s[1]->Output()), s.ToVreg(s[2]->InputAt(1)));
1636 }
1637
1638
TEST_F(InstructionSelectorTest,Int32UModWithParametersForSUDIVAndMLS)1639 TEST_F(InstructionSelectorTest, Int32UModWithParametersForSUDIVAndMLS) {
1640 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
1641 m.Return(m.Int32UMod(m.Parameter(0), m.Parameter(1)));
1642 Stream s = m.Build(MLS, SUDIV);
1643 ASSERT_EQ(2U, s.size());
1644 EXPECT_EQ(kArmUdiv, s[0]->arch_opcode());
1645 ASSERT_EQ(1U, s[0]->OutputCount());
1646 ASSERT_EQ(2U, s[0]->InputCount());
1647 EXPECT_EQ(kArmMls, s[1]->arch_opcode());
1648 ASSERT_EQ(1U, s[1]->OutputCount());
1649 ASSERT_EQ(3U, s[1]->InputCount());
1650 EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(0)));
1651 EXPECT_EQ(s.ToVreg(s[0]->InputAt(1)), s.ToVreg(s[1]->InputAt(1)));
1652 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[1]->InputAt(2)));
1653 }
1654
1655
TEST_F(InstructionSelectorTest,Word32AndWithUbfxImmediateForARMv7)1656 TEST_F(InstructionSelectorTest, Word32AndWithUbfxImmediateForARMv7) {
1657 TRACED_FORRANGE(int32_t, width, 1, 32) {
1658 StreamBuilder m(this, kMachInt32, kMachInt32);
1659 m.Return(m.Word32And(m.Parameter(0),
1660 m.Int32Constant(0xffffffffu >> (32 - width))));
1661 Stream s = m.Build(ARMv7);
1662 ASSERT_EQ(1U, s.size());
1663 EXPECT_EQ(kArmUbfx, s[0]->arch_opcode());
1664 ASSERT_EQ(3U, s[0]->InputCount());
1665 EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1)));
1666 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
1667 }
1668 TRACED_FORRANGE(int32_t, width, 1, 32) {
1669 StreamBuilder m(this, kMachInt32, kMachInt32);
1670 m.Return(m.Word32And(m.Int32Constant(0xffffffffu >> (32 - width)),
1671 m.Parameter(0)));
1672 Stream s = m.Build(ARMv7);
1673 ASSERT_EQ(1U, s.size());
1674 EXPECT_EQ(kArmUbfx, s[0]->arch_opcode());
1675 ASSERT_EQ(3U, s[0]->InputCount());
1676 EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1)));
1677 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
1678 }
1679 }
1680
1681
TEST_F(InstructionSelectorTest,Word32AndWithBfcImmediateForARMv7)1682 TEST_F(InstructionSelectorTest, Word32AndWithBfcImmediateForARMv7) {
1683 TRACED_FORRANGE(int32_t, lsb, 0, 31) {
1684 TRACED_FORRANGE(int32_t, width, 1, (32 - lsb) - 1) {
1685 StreamBuilder m(this, kMachInt32, kMachInt32);
1686 m.Return(m.Word32And(
1687 m.Parameter(0),
1688 m.Int32Constant(~((0xffffffffu >> (32 - width)) << lsb))));
1689 Stream s = m.Build(ARMv7);
1690 ASSERT_EQ(1U, s.size());
1691 EXPECT_EQ(kArmBfc, s[0]->arch_opcode());
1692 ASSERT_EQ(1U, s[0]->OutputCount());
1693 EXPECT_TRUE(
1694 UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy());
1695 ASSERT_EQ(3U, s[0]->InputCount());
1696 EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
1697 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
1698 }
1699 }
1700 TRACED_FORRANGE(int32_t, lsb, 0, 31) {
1701 TRACED_FORRANGE(int32_t, width, 1, (32 - lsb) - 1) {
1702 StreamBuilder m(this, kMachInt32, kMachInt32);
1703 m.Return(
1704 m.Word32And(m.Int32Constant(~((0xffffffffu >> (32 - width)) << lsb)),
1705 m.Parameter(0)));
1706 Stream s = m.Build(ARMv7);
1707 ASSERT_EQ(1U, s.size());
1708 EXPECT_EQ(kArmBfc, s[0]->arch_opcode());
1709 ASSERT_EQ(1U, s[0]->OutputCount());
1710 EXPECT_TRUE(
1711 UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy());
1712 ASSERT_EQ(3U, s[0]->InputCount());
1713 EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
1714 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
1715 }
1716 }
1717 }
1718
1719
TEST_F(InstructionSelectorTest,Word32ShrWithWord32AndWithImmediateForARMv7)1720 TEST_F(InstructionSelectorTest, Word32ShrWithWord32AndWithImmediateForARMv7) {
1721 TRACED_FORRANGE(int32_t, lsb, 0, 31) {
1722 TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) {
1723 uint32_t max = 1 << lsb;
1724 if (max > static_cast<uint32_t>(kMaxInt)) max -= 1;
1725 uint32_t jnk = rng()->NextInt(max);
1726 uint32_t msk = ((0xffffffffu >> (32 - width)) << lsb) | jnk;
1727 StreamBuilder m(this, kMachInt32, kMachInt32);
1728 m.Return(m.Word32Shr(m.Word32And(m.Parameter(0), m.Int32Constant(msk)),
1729 m.Int32Constant(lsb)));
1730 Stream s = m.Build(ARMv7);
1731 ASSERT_EQ(1U, s.size());
1732 EXPECT_EQ(kArmUbfx, s[0]->arch_opcode());
1733 ASSERT_EQ(3U, s[0]->InputCount());
1734 EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
1735 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
1736 }
1737 }
1738 TRACED_FORRANGE(int32_t, lsb, 0, 31) {
1739 TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) {
1740 uint32_t max = 1 << lsb;
1741 if (max > static_cast<uint32_t>(kMaxInt)) max -= 1;
1742 uint32_t jnk = rng()->NextInt(max);
1743 uint32_t msk = ((0xffffffffu >> (32 - width)) << lsb) | jnk;
1744 StreamBuilder m(this, kMachInt32, kMachInt32);
1745 m.Return(m.Word32Shr(m.Word32And(m.Int32Constant(msk), m.Parameter(0)),
1746 m.Int32Constant(lsb)));
1747 Stream s = m.Build(ARMv7);
1748 ASSERT_EQ(1U, s.size());
1749 EXPECT_EQ(kArmUbfx, s[0]->arch_opcode());
1750 ASSERT_EQ(3U, s[0]->InputCount());
1751 EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
1752 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
1753 }
1754 }
1755 }
1756
1757
TEST_F(InstructionSelectorTest,Word32AndWithWord32Not)1758 TEST_F(InstructionSelectorTest, Word32AndWithWord32Not) {
1759 {
1760 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
1761 m.Return(m.Word32And(m.Parameter(0), m.Word32Not(m.Parameter(1))));
1762 Stream s = m.Build();
1763 ASSERT_EQ(1U, s.size());
1764 EXPECT_EQ(kArmBic, s[0]->arch_opcode());
1765 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
1766 EXPECT_EQ(2U, s[0]->InputCount());
1767 EXPECT_EQ(1U, s[0]->OutputCount());
1768 }
1769 {
1770 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
1771 m.Return(m.Word32And(m.Word32Not(m.Parameter(0)), m.Parameter(1)));
1772 Stream s = m.Build();
1773 ASSERT_EQ(1U, s.size());
1774 EXPECT_EQ(kArmBic, s[0]->arch_opcode());
1775 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
1776 EXPECT_EQ(2U, s[0]->InputCount());
1777 EXPECT_EQ(1U, s[0]->OutputCount());
1778 }
1779 }
1780
1781
TEST_F(InstructionSelectorTest,Word32EqualWithParameters)1782 TEST_F(InstructionSelectorTest, Word32EqualWithParameters) {
1783 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
1784 m.Return(m.Word32Equal(m.Parameter(0), m.Parameter(1)));
1785 Stream s = m.Build();
1786 ASSERT_EQ(1U, s.size());
1787 EXPECT_EQ(kArmCmp, s[0]->arch_opcode());
1788 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
1789 EXPECT_EQ(2U, s[0]->InputCount());
1790 EXPECT_EQ(1U, s[0]->OutputCount());
1791 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1792 EXPECT_EQ(kEqual, s[0]->flags_condition());
1793 }
1794
1795
TEST_F(InstructionSelectorTest,Word32EqualWithImmediate)1796 TEST_F(InstructionSelectorTest, Word32EqualWithImmediate) {
1797 TRACED_FOREACH(int32_t, imm, kImmediates) {
1798 if (imm == 0) continue;
1799 StreamBuilder m(this, kMachInt32, kMachInt32);
1800 m.Return(m.Word32Equal(m.Parameter(0), m.Int32Constant(imm)));
1801 Stream s = m.Build();
1802 ASSERT_EQ(1U, s.size());
1803 EXPECT_EQ(kArmCmp, s[0]->arch_opcode());
1804 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode());
1805 ASSERT_EQ(2U, s[0]->InputCount());
1806 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
1807 EXPECT_EQ(1U, s[0]->OutputCount());
1808 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1809 EXPECT_EQ(kEqual, s[0]->flags_condition());
1810 }
1811 TRACED_FOREACH(int32_t, imm, kImmediates) {
1812 if (imm == 0) continue;
1813 StreamBuilder m(this, kMachInt32, kMachInt32);
1814 m.Return(m.Word32Equal(m.Int32Constant(imm), m.Parameter(0)));
1815 Stream s = m.Build();
1816 ASSERT_EQ(1U, s.size());
1817 EXPECT_EQ(kArmCmp, s[0]->arch_opcode());
1818 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode());
1819 ASSERT_EQ(2U, s[0]->InputCount());
1820 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
1821 EXPECT_EQ(1U, s[0]->OutputCount());
1822 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1823 EXPECT_EQ(kEqual, s[0]->flags_condition());
1824 }
1825 }
1826
1827
TEST_F(InstructionSelectorTest,Word32EqualWithZero)1828 TEST_F(InstructionSelectorTest, Word32EqualWithZero) {
1829 {
1830 StreamBuilder m(this, kMachInt32, kMachInt32);
1831 m.Return(m.Word32Equal(m.Parameter(0), m.Int32Constant(0)));
1832 Stream s = m.Build();
1833 ASSERT_EQ(1U, s.size());
1834 EXPECT_EQ(kArmTst, s[0]->arch_opcode());
1835 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
1836 ASSERT_EQ(2U, s[0]->InputCount());
1837 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
1838 EXPECT_EQ(1U, s[0]->OutputCount());
1839 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1840 EXPECT_EQ(kEqual, s[0]->flags_condition());
1841 }
1842 {
1843 StreamBuilder m(this, kMachInt32, kMachInt32);
1844 m.Return(m.Word32Equal(m.Int32Constant(0), m.Parameter(0)));
1845 Stream s = m.Build();
1846 ASSERT_EQ(1U, s.size());
1847 EXPECT_EQ(kArmTst, s[0]->arch_opcode());
1848 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
1849 ASSERT_EQ(2U, s[0]->InputCount());
1850 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
1851 EXPECT_EQ(1U, s[0]->OutputCount());
1852 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1853 EXPECT_EQ(kEqual, s[0]->flags_condition());
1854 }
1855 }
1856
1857
TEST_F(InstructionSelectorTest,Word32NotWithParameter)1858 TEST_F(InstructionSelectorTest, Word32NotWithParameter) {
1859 StreamBuilder m(this, kMachInt32, kMachInt32);
1860 m.Return(m.Word32Not(m.Parameter(0)));
1861 Stream s = m.Build();
1862 ASSERT_EQ(1U, s.size());
1863 EXPECT_EQ(kArmMvn, s[0]->arch_opcode());
1864 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
1865 EXPECT_EQ(1U, s[0]->InputCount());
1866 EXPECT_EQ(1U, s[0]->OutputCount());
1867 }
1868
1869
TEST_F(InstructionSelectorTest,Word32AndWithWord32ShrWithImmediateForARMv7)1870 TEST_F(InstructionSelectorTest, Word32AndWithWord32ShrWithImmediateForARMv7) {
1871 TRACED_FORRANGE(int32_t, lsb, 0, 31) {
1872 TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) {
1873 StreamBuilder m(this, kMachInt32, kMachInt32);
1874 m.Return(m.Word32And(m.Word32Shr(m.Parameter(0), m.Int32Constant(lsb)),
1875 m.Int32Constant(0xffffffffu >> (32 - width))));
1876 Stream s = m.Build(ARMv7);
1877 ASSERT_EQ(1U, s.size());
1878 EXPECT_EQ(kArmUbfx, s[0]->arch_opcode());
1879 ASSERT_EQ(3U, s[0]->InputCount());
1880 EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
1881 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
1882 }
1883 }
1884 TRACED_FORRANGE(int32_t, lsb, 0, 31) {
1885 TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) {
1886 StreamBuilder m(this, kMachInt32, kMachInt32);
1887 m.Return(m.Word32And(m.Int32Constant(0xffffffffu >> (32 - width)),
1888 m.Word32Shr(m.Parameter(0), m.Int32Constant(lsb))));
1889 Stream s = m.Build(ARMv7);
1890 ASSERT_EQ(1U, s.size());
1891 EXPECT_EQ(kArmUbfx, s[0]->arch_opcode());
1892 ASSERT_EQ(3U, s[0]->InputCount());
1893 EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
1894 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
1895 }
1896 }
1897 }
1898 } // namespace compiler
1899 } // namespace internal
1900 } // namespace v8
1901