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 <limits>
6
7 #include "test/unittests/compiler/instruction-selector-unittest.h"
8
9 namespace v8 {
10 namespace internal {
11 namespace compiler {
12
13 namespace {
14
15 typedef Node* (RawMachineAssembler::*Constructor)(Node*, Node*);
16
17
18 // Data processing instructions.
19 struct DPI {
20 Constructor constructor;
21 const char* constructor_name;
22 ArchOpcode arch_opcode;
23 ArchOpcode reverse_arch_opcode;
24 ArchOpcode test_arch_opcode;
25 };
26
27
operator <<(std::ostream & os,const DPI & dpi)28 std::ostream& operator<<(std::ostream& os, const DPI& dpi) {
29 return os << dpi.constructor_name;
30 }
31
32
33 const DPI kDPIs[] = {
34 {&RawMachineAssembler::Word32And, "Word32And", kArmAnd, kArmAnd, kArmTst},
35 {&RawMachineAssembler::Word32Or, "Word32Or", kArmOrr, kArmOrr, kArmOrr},
36 {&RawMachineAssembler::Word32Xor, "Word32Xor", kArmEor, kArmEor, kArmTeq},
37 {&RawMachineAssembler::Int32Add, "Int32Add", kArmAdd, kArmAdd, kArmCmn},
38 {&RawMachineAssembler::Int32Sub, "Int32Sub", kArmSub, kArmRsb, kArmCmp}};
39
40
41 // Floating point arithmetic instructions.
42 struct FAI {
43 Constructor constructor;
44 const char* constructor_name;
45 MachineType machine_type;
46 ArchOpcode arch_opcode;
47 };
48
49
operator <<(std::ostream & os,const FAI & fai)50 std::ostream& operator<<(std::ostream& os, const FAI& fai) {
51 return os << fai.constructor_name;
52 }
53
54
55 const FAI kFAIs[] = {{&RawMachineAssembler::Float32Add, "Float32Add",
56 MachineType::Float32(), kArmVaddF32},
57 {&RawMachineAssembler::Float64Add, "Float64Add",
58 MachineType::Float64(), kArmVaddF64},
59 {&RawMachineAssembler::Float32Sub, "Float32Sub",
60 MachineType::Float32(), kArmVsubF32},
61 {&RawMachineAssembler::Float64Sub, "Float64Sub",
62 MachineType::Float64(), kArmVsubF64},
63 {&RawMachineAssembler::Float32Mul, "Float32Mul",
64 MachineType::Float32(), kArmVmulF32},
65 {&RawMachineAssembler::Float64Mul, "Float64Mul",
66 MachineType::Float64(), kArmVmulF64},
67 {&RawMachineAssembler::Float32Div, "Float32Div",
68 MachineType::Float32(), kArmVdivF32},
69 {&RawMachineAssembler::Float64Div, "Float64Div",
70 MachineType::Float64(), kArmVdivF64}};
71
72
73 // Data processing instructions with overflow.
74 struct ODPI {
75 Constructor constructor;
76 const char* constructor_name;
77 ArchOpcode arch_opcode;
78 ArchOpcode reverse_arch_opcode;
79 };
80
81
operator <<(std::ostream & os,const ODPI & odpi)82 std::ostream& operator<<(std::ostream& os, const ODPI& odpi) {
83 return os << odpi.constructor_name;
84 }
85
86
87 const ODPI kODPIs[] = {{&RawMachineAssembler::Int32AddWithOverflow,
88 "Int32AddWithOverflow", kArmAdd, kArmAdd},
89 {&RawMachineAssembler::Int32SubWithOverflow,
90 "Int32SubWithOverflow", kArmSub, kArmRsb}};
91
92
93 // Shifts.
94 struct Shift {
95 Constructor constructor;
96 const char* constructor_name;
97 int32_t i_low; // lowest possible immediate
98 int32_t i_high; // highest possible immediate
99 AddressingMode i_mode; // Operand2_R_<shift>_I
100 AddressingMode r_mode; // Operand2_R_<shift>_R
101 };
102
103
operator <<(std::ostream & os,const Shift & shift)104 std::ostream& operator<<(std::ostream& os, const Shift& shift) {
105 return os << shift.constructor_name;
106 }
107
108
109 const Shift kShifts[] = {{&RawMachineAssembler::Word32Sar, "Word32Sar", 1, 32,
110 kMode_Operand2_R_ASR_I, kMode_Operand2_R_ASR_R},
111 {&RawMachineAssembler::Word32Shl, "Word32Shl", 0, 31,
112 kMode_Operand2_R_LSL_I, kMode_Operand2_R_LSL_R},
113 {&RawMachineAssembler::Word32Shr, "Word32Shr", 1, 32,
114 kMode_Operand2_R_LSR_I, kMode_Operand2_R_LSR_R},
115 {&RawMachineAssembler::Word32Ror, "Word32Ror", 1, 31,
116 kMode_Operand2_R_ROR_I, kMode_Operand2_R_ROR_R}};
117
118
119 // Immediates (random subset).
120 const int32_t kImmediates[] = {
121 std::numeric_limits<int32_t>::min(), -2147483617, -2147483606, -2113929216,
122 -2080374784, -1996488704, -1879048192, -1459617792, -1358954496,
123 -1342177265, -1275068414, -1073741818, -1073741777, -855638016, -805306368,
124 -402653184, -268435444, -16777216, 0, 35, 61, 105, 116, 171, 245, 255, 692,
125 1216, 1248, 1520, 1600, 1888, 3744, 4080, 5888, 8384, 9344, 9472, 9792,
126 13312, 15040, 15360, 20736, 22272, 23296, 32000, 33536, 37120, 45824, 47872,
127 56320, 59392, 65280, 72704, 101376, 147456, 161792, 164864, 167936, 173056,
128 195584, 209920, 212992, 356352, 655360, 704512, 716800, 851968, 901120,
129 1044480, 1523712, 2572288, 3211264, 3588096, 3833856, 3866624, 4325376,
130 5177344, 6488064, 7012352, 7471104, 14090240, 16711680, 19398656, 22282240,
131 28573696, 30408704, 30670848, 43253760, 54525952, 55312384, 56623104,
132 68157440, 115343360, 131072000, 187695104, 188743680, 195035136, 197132288,
133 203423744, 218103808, 267386880, 268435470, 285212672, 402653185, 415236096,
134 595591168, 603979776, 603979778, 629145600, 1073741835, 1073741855,
135 1073741861, 1073741884, 1157627904, 1476395008, 1476395010, 1610612741,
136 2030043136, 2080374785, 2097152000};
137
138 } // namespace
139
140
141 // -----------------------------------------------------------------------------
142 // Data processing instructions.
143
144
145 typedef InstructionSelectorTestWithParam<DPI> InstructionSelectorDPITest;
146
147
TEST_P(InstructionSelectorDPITest,Parameters)148 TEST_P(InstructionSelectorDPITest, Parameters) {
149 const DPI dpi = GetParam();
150 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
151 MachineType::Int32());
152 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)));
153 Stream s = m.Build();
154 ASSERT_EQ(1U, s.size());
155 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
156 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
157 EXPECT_EQ(2U, s[0]->InputCount());
158 EXPECT_EQ(1U, s[0]->OutputCount());
159 }
160
161
TEST_P(InstructionSelectorDPITest,Immediate)162 TEST_P(InstructionSelectorDPITest, Immediate) {
163 const DPI dpi = GetParam();
164 TRACED_FOREACH(int32_t, imm, kImmediates) {
165 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
166 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm)));
167 Stream s = m.Build();
168 ASSERT_EQ(1U, s.size());
169 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
170 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode());
171 ASSERT_EQ(2U, s[0]->InputCount());
172 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
173 EXPECT_EQ(1U, s[0]->OutputCount());
174 }
175 TRACED_FOREACH(int32_t, imm, kImmediates) {
176 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
177 m.Return((m.*dpi.constructor)(m.Int32Constant(imm), m.Parameter(0)));
178 Stream s = m.Build();
179 ASSERT_EQ(1U, s.size());
180 EXPECT_EQ(dpi.reverse_arch_opcode, s[0]->arch_opcode());
181 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode());
182 ASSERT_EQ(2U, s[0]->InputCount());
183 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
184 EXPECT_EQ(1U, s[0]->OutputCount());
185 }
186 }
187
188
TEST_P(InstructionSelectorDPITest,ShiftByParameter)189 TEST_P(InstructionSelectorDPITest, ShiftByParameter) {
190 const DPI dpi = GetParam();
191 TRACED_FOREACH(Shift, shift, kShifts) {
192 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
193 MachineType::Int32(), MachineType::Int32());
194 m.Return((m.*dpi.constructor)(
195 m.Parameter(0),
196 (m.*shift.constructor)(m.Parameter(1), m.Parameter(2))));
197 Stream s = m.Build();
198 ASSERT_EQ(1U, s.size());
199 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
200 EXPECT_EQ(shift.r_mode, s[0]->addressing_mode());
201 EXPECT_EQ(3U, s[0]->InputCount());
202 EXPECT_EQ(1U, s[0]->OutputCount());
203 }
204 TRACED_FOREACH(Shift, shift, kShifts) {
205 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
206 MachineType::Int32(), MachineType::Int32());
207 m.Return((m.*dpi.constructor)(
208 (m.*shift.constructor)(m.Parameter(0), m.Parameter(1)),
209 m.Parameter(2)));
210 Stream s = m.Build();
211 ASSERT_EQ(1U, s.size());
212 EXPECT_EQ(dpi.reverse_arch_opcode, s[0]->arch_opcode());
213 EXPECT_EQ(shift.r_mode, s[0]->addressing_mode());
214 EXPECT_EQ(3U, s[0]->InputCount());
215 EXPECT_EQ(1U, s[0]->OutputCount());
216 }
217 }
218
219
TEST_P(InstructionSelectorDPITest,ShiftByImmediate)220 TEST_P(InstructionSelectorDPITest, ShiftByImmediate) {
221 const DPI dpi = GetParam();
222 TRACED_FOREACH(Shift, shift, kShifts) {
223 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) {
224 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
225 MachineType::Int32());
226 m.Return((m.*dpi.constructor)(
227 m.Parameter(0),
228 (m.*shift.constructor)(m.Parameter(1), m.Int32Constant(imm))));
229 Stream s = m.Build();
230 ASSERT_EQ(1U, s.size());
231 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
232 EXPECT_EQ(shift.i_mode, s[0]->addressing_mode());
233 ASSERT_EQ(3U, s[0]->InputCount());
234 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2)));
235 EXPECT_EQ(1U, s[0]->OutputCount());
236 }
237 }
238 TRACED_FOREACH(Shift, shift, kShifts) {
239 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) {
240 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
241 MachineType::Int32());
242 m.Return((m.*dpi.constructor)(
243 (m.*shift.constructor)(m.Parameter(0), m.Int32Constant(imm)),
244 m.Parameter(1)));
245 Stream s = m.Build();
246 ASSERT_EQ(1U, s.size());
247 EXPECT_EQ(dpi.reverse_arch_opcode, s[0]->arch_opcode());
248 EXPECT_EQ(shift.i_mode, s[0]->addressing_mode());
249 ASSERT_EQ(3U, s[0]->InputCount());
250 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2)));
251 EXPECT_EQ(1U, s[0]->OutputCount());
252 }
253 }
254 }
255
256
TEST_P(InstructionSelectorDPITest,BranchWithParameters)257 TEST_P(InstructionSelectorDPITest, BranchWithParameters) {
258 const DPI dpi = GetParam();
259 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
260 MachineType::Int32());
261 RawMachineLabel a, b;
262 m.Branch((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)), &a, &b);
263 m.Bind(&a);
264 m.Return(m.Int32Constant(1));
265 m.Bind(&b);
266 m.Return(m.Int32Constant(0));
267 Stream s = m.Build();
268 ASSERT_EQ(1U, s.size());
269 EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode());
270 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
271 EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
272 EXPECT_EQ(kNotEqual, s[0]->flags_condition());
273 }
274
275
TEST_P(InstructionSelectorDPITest,BranchWithImmediate)276 TEST_P(InstructionSelectorDPITest, BranchWithImmediate) {
277 const DPI dpi = GetParam();
278 TRACED_FOREACH(int32_t, imm, kImmediates) {
279 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
280 RawMachineLabel a, b;
281 m.Branch((m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm)), &a,
282 &b);
283 m.Bind(&a);
284 m.Return(m.Int32Constant(1));
285 m.Bind(&b);
286 m.Return(m.Int32Constant(0));
287 Stream s = m.Build();
288 ASSERT_EQ(1U, s.size());
289 EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode());
290 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode());
291 EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
292 EXPECT_EQ(kNotEqual, s[0]->flags_condition());
293 }
294 TRACED_FOREACH(int32_t, imm, kImmediates) {
295 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
296 RawMachineLabel a, b;
297 m.Branch((m.*dpi.constructor)(m.Int32Constant(imm), m.Parameter(0)), &a,
298 &b);
299 m.Bind(&a);
300 m.Return(m.Int32Constant(1));
301 m.Bind(&b);
302 m.Return(m.Int32Constant(0));
303 Stream s = m.Build();
304 ASSERT_EQ(1U, s.size());
305 EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode());
306 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode());
307 EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
308 EXPECT_EQ(kNotEqual, s[0]->flags_condition());
309 }
310 }
311
312
TEST_P(InstructionSelectorDPITest,BranchWithShiftByParameter)313 TEST_P(InstructionSelectorDPITest, BranchWithShiftByParameter) {
314 const DPI dpi = GetParam();
315 TRACED_FOREACH(Shift, shift, kShifts) {
316 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
317 MachineType::Int32(), MachineType::Int32());
318 RawMachineLabel a, b;
319 m.Branch((m.*dpi.constructor)(
320 m.Parameter(0),
321 (m.*shift.constructor)(m.Parameter(1), m.Parameter(2))),
322 &a, &b);
323 m.Bind(&a);
324 m.Return(m.Int32Constant(1));
325 m.Bind(&b);
326 m.Return(m.Int32Constant(0));
327 Stream s = m.Build();
328 ASSERT_EQ(1U, s.size());
329 EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode());
330 EXPECT_EQ(shift.r_mode, s[0]->addressing_mode());
331 EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
332 EXPECT_EQ(kNotEqual, s[0]->flags_condition());
333 }
334 TRACED_FOREACH(Shift, shift, kShifts) {
335 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
336 MachineType::Int32(), MachineType::Int32());
337 RawMachineLabel a, b;
338 m.Branch((m.*dpi.constructor)(
339 (m.*shift.constructor)(m.Parameter(0), m.Parameter(1)),
340 m.Parameter(2)),
341 &a, &b);
342 m.Bind(&a);
343 m.Return(m.Int32Constant(1));
344 m.Bind(&b);
345 m.Return(m.Int32Constant(0));
346 Stream s = m.Build();
347 ASSERT_EQ(1U, s.size());
348 EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode());
349 EXPECT_EQ(shift.r_mode, s[0]->addressing_mode());
350 EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
351 EXPECT_EQ(kNotEqual, s[0]->flags_condition());
352 }
353 }
354
355
TEST_P(InstructionSelectorDPITest,BranchWithShiftByImmediate)356 TEST_P(InstructionSelectorDPITest, BranchWithShiftByImmediate) {
357 const DPI dpi = GetParam();
358 TRACED_FOREACH(Shift, shift, kShifts) {
359 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) {
360 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
361 MachineType::Int32());
362 RawMachineLabel a, b;
363 m.Branch((m.*dpi.constructor)(m.Parameter(0),
364 (m.*shift.constructor)(
365 m.Parameter(1), m.Int32Constant(imm))),
366 &a, &b);
367 m.Bind(&a);
368 m.Return(m.Int32Constant(1));
369 m.Bind(&b);
370 m.Return(m.Int32Constant(0));
371 Stream s = m.Build();
372 ASSERT_EQ(1U, s.size());
373 EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode());
374 EXPECT_EQ(shift.i_mode, s[0]->addressing_mode());
375 ASSERT_EQ(5U, s[0]->InputCount());
376 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2)));
377 EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
378 EXPECT_EQ(kNotEqual, s[0]->flags_condition());
379 }
380 }
381 TRACED_FOREACH(Shift, shift, kShifts) {
382 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) {
383 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
384 MachineType::Int32());
385 RawMachineLabel a, b;
386 m.Branch((m.*dpi.constructor)(
387 (m.*shift.constructor)(m.Parameter(0), m.Int32Constant(imm)),
388 m.Parameter(1)),
389 &a, &b);
390 m.Bind(&a);
391 m.Return(m.Int32Constant(1));
392 m.Bind(&b);
393 m.Return(m.Int32Constant(0));
394 Stream s = m.Build();
395 ASSERT_EQ(1U, s.size());
396 EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode());
397 EXPECT_EQ(shift.i_mode, s[0]->addressing_mode());
398 ASSERT_EQ(5U, s[0]->InputCount());
399 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2)));
400 EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
401 EXPECT_EQ(kNotEqual, s[0]->flags_condition());
402 }
403 }
404 }
405
406
TEST_P(InstructionSelectorDPITest,BranchIfZeroWithParameters)407 TEST_P(InstructionSelectorDPITest, BranchIfZeroWithParameters) {
408 const DPI dpi = GetParam();
409 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
410 MachineType::Int32());
411 RawMachineLabel a, b;
412 m.Branch(m.Word32Equal((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)),
413 m.Int32Constant(0)),
414 &a, &b);
415 m.Bind(&a);
416 m.Return(m.Int32Constant(1));
417 m.Bind(&b);
418 m.Return(m.Int32Constant(0));
419 Stream s = m.Build();
420 ASSERT_EQ(1U, s.size());
421 EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode());
422 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
423 EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
424 EXPECT_EQ(kEqual, s[0]->flags_condition());
425 }
426
427
TEST_P(InstructionSelectorDPITest,BranchIfNotZeroWithParameters)428 TEST_P(InstructionSelectorDPITest, BranchIfNotZeroWithParameters) {
429 const DPI dpi = GetParam();
430 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
431 MachineType::Int32());
432 RawMachineLabel a, b;
433 m.Branch(
434 m.Word32NotEqual((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)),
435 m.Int32Constant(0)),
436 &a, &b);
437 m.Bind(&a);
438 m.Return(m.Int32Constant(1));
439 m.Bind(&b);
440 m.Return(m.Int32Constant(0));
441 Stream s = m.Build();
442 ASSERT_EQ(1U, s.size());
443 EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode());
444 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
445 EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
446 EXPECT_EQ(kNotEqual, s[0]->flags_condition());
447 }
448
449
TEST_P(InstructionSelectorDPITest,BranchIfZeroWithImmediate)450 TEST_P(InstructionSelectorDPITest, BranchIfZeroWithImmediate) {
451 const DPI dpi = GetParam();
452 TRACED_FOREACH(int32_t, imm, kImmediates) {
453 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
454 RawMachineLabel a, b;
455 m.Branch(m.Word32Equal(
456 (m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm)),
457 m.Int32Constant(0)),
458 &a, &b);
459 m.Bind(&a);
460 m.Return(m.Int32Constant(1));
461 m.Bind(&b);
462 m.Return(m.Int32Constant(0));
463 Stream s = m.Build();
464 ASSERT_EQ(1U, s.size());
465 EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode());
466 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode());
467 EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
468 EXPECT_EQ(kEqual, s[0]->flags_condition());
469 }
470 TRACED_FOREACH(int32_t, imm, kImmediates) {
471 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
472 RawMachineLabel a, b;
473 m.Branch(m.Word32Equal(
474 (m.*dpi.constructor)(m.Int32Constant(imm), m.Parameter(0)),
475 m.Int32Constant(0)),
476 &a, &b);
477 m.Bind(&a);
478 m.Return(m.Int32Constant(1));
479 m.Bind(&b);
480 m.Return(m.Int32Constant(0));
481 Stream s = m.Build();
482 ASSERT_EQ(1U, s.size());
483 EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode());
484 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode());
485 EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
486 EXPECT_EQ(kEqual, s[0]->flags_condition());
487 }
488 }
489
490
TEST_P(InstructionSelectorDPITest,BranchIfNotZeroWithImmediate)491 TEST_P(InstructionSelectorDPITest, BranchIfNotZeroWithImmediate) {
492 const DPI dpi = GetParam();
493 TRACED_FOREACH(int32_t, imm, kImmediates) {
494 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
495 RawMachineLabel a, b;
496 m.Branch(m.Word32NotEqual(
497 (m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm)),
498 m.Int32Constant(0)),
499 &a, &b);
500 m.Bind(&a);
501 m.Return(m.Int32Constant(1));
502 m.Bind(&b);
503 m.Return(m.Int32Constant(0));
504 Stream s = m.Build();
505 ASSERT_EQ(1U, s.size());
506 EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode());
507 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode());
508 EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
509 EXPECT_EQ(kNotEqual, s[0]->flags_condition());
510 }
511 TRACED_FOREACH(int32_t, imm, kImmediates) {
512 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
513 RawMachineLabel a, b;
514 m.Branch(m.Word32NotEqual(
515 (m.*dpi.constructor)(m.Int32Constant(imm), m.Parameter(0)),
516 m.Int32Constant(0)),
517 &a, &b);
518 m.Bind(&a);
519 m.Return(m.Int32Constant(1));
520 m.Bind(&b);
521 m.Return(m.Int32Constant(0));
522 Stream s = m.Build();
523 ASSERT_EQ(1U, s.size());
524 EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode());
525 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode());
526 EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
527 EXPECT_EQ(kNotEqual, s[0]->flags_condition());
528 }
529 }
530
531
532 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorDPITest,
533 ::testing::ValuesIn(kDPIs));
534
535
536 // -----------------------------------------------------------------------------
537 // Data processing instructions with overflow.
538
539
540 typedef InstructionSelectorTestWithParam<ODPI> InstructionSelectorODPITest;
541
542
TEST_P(InstructionSelectorODPITest,OvfWithParameters)543 TEST_P(InstructionSelectorODPITest, OvfWithParameters) {
544 const ODPI odpi = GetParam();
545 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
546 MachineType::Int32());
547 m.Return(
548 m.Projection(1, (m.*odpi.constructor)(m.Parameter(0), m.Parameter(1))));
549 Stream s = m.Build();
550 ASSERT_EQ(1U, s.size());
551 EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode());
552 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
553 EXPECT_EQ(2U, s[0]->InputCount());
554 EXPECT_LE(1U, s[0]->OutputCount());
555 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
556 EXPECT_EQ(kOverflow, s[0]->flags_condition());
557 }
558
559
TEST_P(InstructionSelectorODPITest,OvfWithImmediate)560 TEST_P(InstructionSelectorODPITest, OvfWithImmediate) {
561 const ODPI odpi = GetParam();
562 TRACED_FOREACH(int32_t, imm, kImmediates) {
563 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
564 m.Return(m.Projection(
565 1, (m.*odpi.constructor)(m.Parameter(0), m.Int32Constant(imm))));
566 Stream s = m.Build();
567 ASSERT_EQ(1U, s.size());
568 EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode());
569 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode());
570 ASSERT_EQ(2U, s[0]->InputCount());
571 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
572 EXPECT_LE(1U, s[0]->OutputCount());
573 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
574 EXPECT_EQ(kOverflow, s[0]->flags_condition());
575 }
576 TRACED_FOREACH(int32_t, imm, kImmediates) {
577 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
578 m.Return(m.Projection(
579 1, (m.*odpi.constructor)(m.Int32Constant(imm), m.Parameter(0))));
580 Stream s = m.Build();
581 ASSERT_EQ(1U, s.size());
582 EXPECT_EQ(odpi.reverse_arch_opcode, s[0]->arch_opcode());
583 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode());
584 ASSERT_EQ(2U, s[0]->InputCount());
585 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
586 EXPECT_LE(1U, s[0]->OutputCount());
587 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
588 EXPECT_EQ(kOverflow, s[0]->flags_condition());
589 }
590 }
591
592
TEST_P(InstructionSelectorODPITest,OvfWithShiftByParameter)593 TEST_P(InstructionSelectorODPITest, OvfWithShiftByParameter) {
594 const ODPI odpi = GetParam();
595 TRACED_FOREACH(Shift, shift, kShifts) {
596 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
597 MachineType::Int32(), MachineType::Int32());
598 m.Return(m.Projection(
599 1, (m.*odpi.constructor)(
600 m.Parameter(0),
601 (m.*shift.constructor)(m.Parameter(1), m.Parameter(2)))));
602 Stream s = m.Build();
603 ASSERT_EQ(1U, s.size());
604 EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode());
605 EXPECT_EQ(shift.r_mode, s[0]->addressing_mode());
606 EXPECT_EQ(3U, s[0]->InputCount());
607 EXPECT_LE(1U, s[0]->OutputCount());
608 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
609 EXPECT_EQ(kOverflow, s[0]->flags_condition());
610 }
611 TRACED_FOREACH(Shift, shift, kShifts) {
612 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
613 MachineType::Int32(), MachineType::Int32());
614 m.Return(m.Projection(
615 1, (m.*odpi.constructor)(
616 (m.*shift.constructor)(m.Parameter(0), m.Parameter(1)),
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.r_mode, s[0]->addressing_mode());
622 EXPECT_EQ(3U, s[0]->InputCount());
623 EXPECT_LE(1U, s[0]->OutputCount());
624 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
625 EXPECT_EQ(kOverflow, s[0]->flags_condition());
626 }
627 }
628
629
TEST_P(InstructionSelectorODPITest,OvfWithShiftByImmediate)630 TEST_P(InstructionSelectorODPITest, OvfWithShiftByImmediate) {
631 const ODPI odpi = GetParam();
632 TRACED_FOREACH(Shift, shift, kShifts) {
633 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) {
634 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
635 MachineType::Int32());
636 m.Return(m.Projection(
637 1, (m.*odpi.constructor)(m.Parameter(0),
638 (m.*shift.constructor)(
639 m.Parameter(1), m.Int32Constant(imm)))));
640 Stream s = m.Build();
641 ASSERT_EQ(1U, s.size());
642 EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode());
643 EXPECT_EQ(shift.i_mode, s[0]->addressing_mode());
644 ASSERT_EQ(3U, s[0]->InputCount());
645 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2)));
646 EXPECT_LE(1U, s[0]->OutputCount());
647 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
648 EXPECT_EQ(kOverflow, s[0]->flags_condition());
649 }
650 }
651 TRACED_FOREACH(Shift, shift, kShifts) {
652 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) {
653 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
654 MachineType::Int32());
655 m.Return(m.Projection(
656 1, (m.*odpi.constructor)(
657 (m.*shift.constructor)(m.Parameter(1), m.Int32Constant(imm)),
658 m.Parameter(0))));
659 Stream s = m.Build();
660 ASSERT_EQ(1U, s.size());
661 EXPECT_EQ(odpi.reverse_arch_opcode, s[0]->arch_opcode());
662 EXPECT_EQ(shift.i_mode, s[0]->addressing_mode());
663 ASSERT_EQ(3U, s[0]->InputCount());
664 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2)));
665 EXPECT_LE(1U, s[0]->OutputCount());
666 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
667 EXPECT_EQ(kOverflow, s[0]->flags_condition());
668 }
669 }
670 }
671
672
TEST_P(InstructionSelectorODPITest,ValWithParameters)673 TEST_P(InstructionSelectorODPITest, ValWithParameters) {
674 const ODPI odpi = GetParam();
675 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
676 MachineType::Int32());
677 m.Return(
678 m.Projection(0, (m.*odpi.constructor)(m.Parameter(0), m.Parameter(1))));
679 Stream s = m.Build();
680 ASSERT_EQ(1U, s.size());
681 EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode());
682 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
683 EXPECT_EQ(2U, s[0]->InputCount());
684 EXPECT_LE(1U, s[0]->OutputCount());
685 EXPECT_EQ(kFlags_none, s[0]->flags_mode());
686 }
687
688
TEST_P(InstructionSelectorODPITest,ValWithImmediate)689 TEST_P(InstructionSelectorODPITest, ValWithImmediate) {
690 const ODPI odpi = GetParam();
691 TRACED_FOREACH(int32_t, imm, kImmediates) {
692 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
693 m.Return(m.Projection(
694 0, (m.*odpi.constructor)(m.Parameter(0), m.Int32Constant(imm))));
695 Stream s = m.Build();
696 ASSERT_EQ(1U, s.size());
697 EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode());
698 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode());
699 ASSERT_EQ(2U, s[0]->InputCount());
700 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
701 EXPECT_LE(1U, s[0]->OutputCount());
702 EXPECT_EQ(kFlags_none, s[0]->flags_mode());
703 }
704 TRACED_FOREACH(int32_t, imm, kImmediates) {
705 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
706 m.Return(m.Projection(
707 0, (m.*odpi.constructor)(m.Int32Constant(imm), m.Parameter(0))));
708 Stream s = m.Build();
709 ASSERT_EQ(1U, s.size());
710 EXPECT_EQ(odpi.reverse_arch_opcode, s[0]->arch_opcode());
711 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode());
712 ASSERT_EQ(2U, s[0]->InputCount());
713 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
714 EXPECT_LE(1U, s[0]->OutputCount());
715 EXPECT_EQ(kFlags_none, s[0]->flags_mode());
716 }
717 }
718
719
TEST_P(InstructionSelectorODPITest,ValWithShiftByParameter)720 TEST_P(InstructionSelectorODPITest, ValWithShiftByParameter) {
721 const ODPI odpi = GetParam();
722 TRACED_FOREACH(Shift, shift, kShifts) {
723 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
724 MachineType::Int32(), MachineType::Int32());
725 m.Return(m.Projection(
726 0, (m.*odpi.constructor)(
727 m.Parameter(0),
728 (m.*shift.constructor)(m.Parameter(1), m.Parameter(2)))));
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.r_mode, s[0]->addressing_mode());
733 EXPECT_EQ(3U, s[0]->InputCount());
734 EXPECT_LE(1U, s[0]->OutputCount());
735 EXPECT_EQ(kFlags_none, s[0]->flags_mode());
736 }
737 TRACED_FOREACH(Shift, shift, kShifts) {
738 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
739 MachineType::Int32(), MachineType::Int32());
740 m.Return(m.Projection(
741 0, (m.*odpi.constructor)(
742 (m.*shift.constructor)(m.Parameter(0), m.Parameter(1)),
743 m.Parameter(0))));
744 Stream s = m.Build();
745 ASSERT_EQ(1U, s.size());
746 EXPECT_EQ(odpi.reverse_arch_opcode, s[0]->arch_opcode());
747 EXPECT_EQ(shift.r_mode, s[0]->addressing_mode());
748 EXPECT_EQ(3U, s[0]->InputCount());
749 EXPECT_LE(1U, s[0]->OutputCount());
750 EXPECT_EQ(kFlags_none, s[0]->flags_mode());
751 }
752 }
753
754
TEST_P(InstructionSelectorODPITest,ValWithShiftByImmediate)755 TEST_P(InstructionSelectorODPITest, ValWithShiftByImmediate) {
756 const ODPI odpi = GetParam();
757 TRACED_FOREACH(Shift, shift, kShifts) {
758 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) {
759 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
760 MachineType::Int32());
761 m.Return(m.Projection(
762 0, (m.*odpi.constructor)(m.Parameter(0),
763 (m.*shift.constructor)(
764 m.Parameter(1), m.Int32Constant(imm)))));
765 Stream s = m.Build();
766 ASSERT_EQ(1U, s.size());
767 EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode());
768 EXPECT_EQ(shift.i_mode, s[0]->addressing_mode());
769 ASSERT_EQ(3U, s[0]->InputCount());
770 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2)));
771 EXPECT_LE(1U, s[0]->OutputCount());
772 EXPECT_EQ(kFlags_none, s[0]->flags_mode());
773 }
774 }
775 TRACED_FOREACH(Shift, shift, kShifts) {
776 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) {
777 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
778 MachineType::Int32());
779 m.Return(m.Projection(
780 0, (m.*odpi.constructor)(
781 (m.*shift.constructor)(m.Parameter(1), m.Int32Constant(imm)),
782 m.Parameter(0))));
783 Stream s = m.Build();
784 ASSERT_EQ(1U, s.size());
785 EXPECT_EQ(odpi.reverse_arch_opcode, s[0]->arch_opcode());
786 EXPECT_EQ(shift.i_mode, s[0]->addressing_mode());
787 ASSERT_EQ(3U, s[0]->InputCount());
788 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2)));
789 EXPECT_LE(1U, s[0]->OutputCount());
790 EXPECT_EQ(kFlags_none, s[0]->flags_mode());
791 }
792 }
793 }
794
795
TEST_P(InstructionSelectorODPITest,BothWithParameters)796 TEST_P(InstructionSelectorODPITest, BothWithParameters) {
797 const ODPI odpi = GetParam();
798 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
799 MachineType::Int32());
800 Node* n = (m.*odpi.constructor)(m.Parameter(0), m.Parameter(1));
801 m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n)));
802 Stream s = m.Build();
803 ASSERT_LE(1U, s.size());
804 EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode());
805 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
806 EXPECT_EQ(2U, s[0]->InputCount());
807 EXPECT_EQ(2U, s[0]->OutputCount());
808 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
809 EXPECT_EQ(kOverflow, s[0]->flags_condition());
810 }
811
812
TEST_P(InstructionSelectorODPITest,BothWithImmediate)813 TEST_P(InstructionSelectorODPITest, BothWithImmediate) {
814 const ODPI odpi = GetParam();
815 TRACED_FOREACH(int32_t, imm, kImmediates) {
816 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
817 Node* n = (m.*odpi.constructor)(m.Parameter(0), m.Int32Constant(imm));
818 m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n)));
819 Stream s = m.Build();
820 ASSERT_LE(1U, s.size());
821 EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode());
822 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode());
823 ASSERT_EQ(2U, s[0]->InputCount());
824 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
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 TRACED_FOREACH(int32_t, imm, kImmediates) {
830 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
831 Node* n = (m.*odpi.constructor)(m.Int32Constant(imm), m.Parameter(0));
832 m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n)));
833 Stream s = m.Build();
834 ASSERT_LE(1U, s.size());
835 EXPECT_EQ(odpi.reverse_arch_opcode, s[0]->arch_opcode());
836 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode());
837 ASSERT_EQ(2U, s[0]->InputCount());
838 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
839 EXPECT_EQ(2U, s[0]->OutputCount());
840 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
841 EXPECT_EQ(kOverflow, s[0]->flags_condition());
842 }
843 }
844
845
TEST_P(InstructionSelectorODPITest,BothWithShiftByParameter)846 TEST_P(InstructionSelectorODPITest, BothWithShiftByParameter) {
847 const ODPI odpi = GetParam();
848 TRACED_FOREACH(Shift, shift, kShifts) {
849 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
850 MachineType::Int32(), MachineType::Int32());
851 Node* n = (m.*odpi.constructor)(
852 m.Parameter(0), (m.*shift.constructor)(m.Parameter(1), m.Parameter(2)));
853 m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n)));
854 Stream s = m.Build();
855 ASSERT_LE(1U, s.size());
856 EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode());
857 EXPECT_EQ(shift.r_mode, s[0]->addressing_mode());
858 EXPECT_EQ(3U, s[0]->InputCount());
859 EXPECT_EQ(2U, s[0]->OutputCount());
860 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
861 EXPECT_EQ(kOverflow, s[0]->flags_condition());
862 }
863 TRACED_FOREACH(Shift, shift, kShifts) {
864 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
865 MachineType::Int32(), MachineType::Int32());
866 Node* n = (m.*odpi.constructor)(
867 (m.*shift.constructor)(m.Parameter(0), m.Parameter(1)), m.Parameter(2));
868 m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n)));
869 Stream s = m.Build();
870 ASSERT_LE(1U, s.size());
871 EXPECT_EQ(odpi.reverse_arch_opcode, s[0]->arch_opcode());
872 EXPECT_EQ(shift.r_mode, s[0]->addressing_mode());
873 EXPECT_EQ(3U, s[0]->InputCount());
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
TEST_P(InstructionSelectorODPITest,BothWithShiftByImmediate)881 TEST_P(InstructionSelectorODPITest, BothWithShiftByImmediate) {
882 const ODPI odpi = GetParam();
883 TRACED_FOREACH(Shift, shift, kShifts) {
884 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) {
885 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
886 MachineType::Int32());
887 Node* n = (m.*odpi.constructor)(
888 m.Parameter(0),
889 (m.*shift.constructor)(m.Parameter(1), m.Int32Constant(imm)));
890 m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n)));
891 Stream s = m.Build();
892 ASSERT_LE(1U, s.size());
893 EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode());
894 EXPECT_EQ(shift.i_mode, s[0]->addressing_mode());
895 ASSERT_EQ(3U, s[0]->InputCount());
896 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2)));
897 EXPECT_EQ(2U, s[0]->OutputCount());
898 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
899 EXPECT_EQ(kOverflow, s[0]->flags_condition());
900 }
901 }
902 TRACED_FOREACH(Shift, shift, kShifts) {
903 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) {
904 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
905 MachineType::Int32());
906 Node* n = (m.*odpi.constructor)(
907 (m.*shift.constructor)(m.Parameter(0), m.Int32Constant(imm)),
908 m.Parameter(1));
909 m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n)));
910 Stream s = m.Build();
911 ASSERT_LE(1U, s.size());
912 EXPECT_EQ(odpi.reverse_arch_opcode, s[0]->arch_opcode());
913 EXPECT_EQ(shift.i_mode, s[0]->addressing_mode());
914 ASSERT_EQ(3U, s[0]->InputCount());
915 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2)));
916 EXPECT_EQ(2U, s[0]->OutputCount());
917 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
918 EXPECT_EQ(kOverflow, s[0]->flags_condition());
919 }
920 }
921 }
922
923
TEST_P(InstructionSelectorODPITest,BranchWithParameters)924 TEST_P(InstructionSelectorODPITest, BranchWithParameters) {
925 const ODPI odpi = GetParam();
926 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
927 MachineType::Int32());
928 RawMachineLabel a, b;
929 Node* n = (m.*odpi.constructor)(m.Parameter(0), m.Parameter(1));
930 m.Branch(m.Projection(1, n), &a, &b);
931 m.Bind(&a);
932 m.Return(m.Int32Constant(0));
933 m.Bind(&b);
934 m.Return(m.Projection(0, n));
935 Stream s = m.Build();
936 ASSERT_EQ(1U, s.size());
937 EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode());
938 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
939 EXPECT_EQ(4U, s[0]->InputCount());
940 EXPECT_EQ(1U, s[0]->OutputCount());
941 EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
942 EXPECT_EQ(kOverflow, s[0]->flags_condition());
943 }
944
945
TEST_P(InstructionSelectorODPITest,BranchWithImmediate)946 TEST_P(InstructionSelectorODPITest, BranchWithImmediate) {
947 const ODPI odpi = GetParam();
948 TRACED_FOREACH(int32_t, imm, kImmediates) {
949 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
950 RawMachineLabel a, b;
951 Node* n = (m.*odpi.constructor)(m.Parameter(0), m.Int32Constant(imm));
952 m.Branch(m.Projection(1, n), &a, &b);
953 m.Bind(&a);
954 m.Return(m.Int32Constant(0));
955 m.Bind(&b);
956 m.Return(m.Projection(0, n));
957 Stream s = m.Build();
958 ASSERT_EQ(1U, s.size());
959 EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode());
960 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode());
961 ASSERT_EQ(4U, s[0]->InputCount());
962 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
963 EXPECT_EQ(1U, s[0]->OutputCount());
964 EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
965 EXPECT_EQ(kOverflow, s[0]->flags_condition());
966 }
967 TRACED_FOREACH(int32_t, imm, kImmediates) {
968 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
969 RawMachineLabel a, b;
970 Node* n = (m.*odpi.constructor)(m.Int32Constant(imm), m.Parameter(0));
971 m.Branch(m.Projection(1, n), &a, &b);
972 m.Bind(&a);
973 m.Return(m.Int32Constant(0));
974 m.Bind(&b);
975 m.Return(m.Projection(0, n));
976 Stream s = m.Build();
977 ASSERT_EQ(1U, s.size());
978 EXPECT_EQ(odpi.reverse_arch_opcode, s[0]->arch_opcode());
979 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode());
980 ASSERT_EQ(4U, s[0]->InputCount());
981 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
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
988
TEST_P(InstructionSelectorODPITest,BranchIfZeroWithParameters)989 TEST_P(InstructionSelectorODPITest, BranchIfZeroWithParameters) {
990 const ODPI odpi = GetParam();
991 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
992 MachineType::Int32());
993 RawMachineLabel a, b;
994 Node* n = (m.*odpi.constructor)(m.Parameter(0), m.Parameter(1));
995 m.Branch(m.Word32Equal(m.Projection(1, n), m.Int32Constant(0)), &a, &b);
996 m.Bind(&a);
997 m.Return(m.Projection(0, n));
998 m.Bind(&b);
999 m.Return(m.Int32Constant(0));
1000 Stream s = m.Build();
1001 ASSERT_EQ(1U, s.size());
1002 EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode());
1003 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
1004 EXPECT_EQ(4U, s[0]->InputCount());
1005 EXPECT_EQ(1U, s[0]->OutputCount());
1006 EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
1007 EXPECT_EQ(kNotOverflow, s[0]->flags_condition());
1008 }
1009
1010
TEST_P(InstructionSelectorODPITest,BranchIfNotZeroWithParameters)1011 TEST_P(InstructionSelectorODPITest, BranchIfNotZeroWithParameters) {
1012 const ODPI odpi = GetParam();
1013 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
1014 MachineType::Int32());
1015 RawMachineLabel a, b;
1016 Node* n = (m.*odpi.constructor)(m.Parameter(0), m.Parameter(1));
1017 m.Branch(m.Word32NotEqual(m.Projection(1, n), m.Int32Constant(0)), &a, &b);
1018 m.Bind(&a);
1019 m.Return(m.Projection(0, n));
1020 m.Bind(&b);
1021 m.Return(m.Int32Constant(0));
1022 Stream s = m.Build();
1023 ASSERT_EQ(1U, s.size());
1024 EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode());
1025 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
1026 EXPECT_EQ(4U, s[0]->InputCount());
1027 EXPECT_EQ(1U, s[0]->OutputCount());
1028 EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
1029 EXPECT_EQ(kOverflow, s[0]->flags_condition());
1030 }
1031
1032
1033 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorODPITest,
1034 ::testing::ValuesIn(kODPIs));
1035
1036
1037 // -----------------------------------------------------------------------------
1038 // Shifts.
1039
1040
1041 typedef InstructionSelectorTestWithParam<Shift> InstructionSelectorShiftTest;
1042
1043
TEST_P(InstructionSelectorShiftTest,Parameters)1044 TEST_P(InstructionSelectorShiftTest, Parameters) {
1045 const Shift shift = GetParam();
1046 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
1047 MachineType::Int32());
1048 m.Return((m.*shift.constructor)(m.Parameter(0), m.Parameter(1)));
1049 Stream s = m.Build();
1050 ASSERT_EQ(1U, s.size());
1051 EXPECT_EQ(kArmMov, s[0]->arch_opcode());
1052 EXPECT_EQ(shift.r_mode, s[0]->addressing_mode());
1053 EXPECT_EQ(2U, s[0]->InputCount());
1054 EXPECT_EQ(1U, s[0]->OutputCount());
1055 }
1056
1057
TEST_P(InstructionSelectorShiftTest,Immediate)1058 TEST_P(InstructionSelectorShiftTest, Immediate) {
1059 const Shift shift = GetParam();
1060 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) {
1061 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
1062 m.Return((m.*shift.constructor)(m.Parameter(0), m.Int32Constant(imm)));
1063 Stream s = m.Build();
1064 ASSERT_EQ(1U, s.size());
1065 EXPECT_EQ(kArmMov, s[0]->arch_opcode());
1066 EXPECT_EQ(shift.i_mode, s[0]->addressing_mode());
1067 ASSERT_EQ(2U, s[0]->InputCount());
1068 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
1069 EXPECT_EQ(1U, s[0]->OutputCount());
1070 }
1071 }
1072
1073
TEST_P(InstructionSelectorShiftTest,Word32EqualWithParameter)1074 TEST_P(InstructionSelectorShiftTest, Word32EqualWithParameter) {
1075 const Shift shift = GetParam();
1076 {
1077 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
1078 MachineType::Int32(), MachineType::Int32());
1079 m.Return(
1080 m.Word32Equal(m.Parameter(0),
1081 (m.*shift.constructor)(m.Parameter(1), m.Parameter(2))));
1082 Stream s = m.Build();
1083 ASSERT_EQ(1U, s.size());
1084 EXPECT_EQ(kArmCmp, s[0]->arch_opcode());
1085 EXPECT_EQ(shift.r_mode, s[0]->addressing_mode());
1086 EXPECT_EQ(3U, s[0]->InputCount());
1087 EXPECT_EQ(1U, s[0]->OutputCount());
1088 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1089 EXPECT_EQ(kEqual, s[0]->flags_condition());
1090 }
1091 {
1092 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
1093 MachineType::Int32(), MachineType::Int32());
1094 m.Return(
1095 m.Word32Equal((m.*shift.constructor)(m.Parameter(1), m.Parameter(2)),
1096 m.Parameter(0)));
1097 Stream s = m.Build();
1098 ASSERT_EQ(1U, s.size());
1099 EXPECT_EQ(kArmCmp, s[0]->arch_opcode());
1100 EXPECT_EQ(shift.r_mode, s[0]->addressing_mode());
1101 EXPECT_EQ(3U, s[0]->InputCount());
1102 EXPECT_EQ(1U, s[0]->OutputCount());
1103 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1104 EXPECT_EQ(kEqual, s[0]->flags_condition());
1105 }
1106 }
1107
1108
TEST_P(InstructionSelectorShiftTest,Word32EqualWithParameterAndImmediate)1109 TEST_P(InstructionSelectorShiftTest, Word32EqualWithParameterAndImmediate) {
1110 const Shift shift = GetParam();
1111 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) {
1112 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
1113 MachineType::Int32());
1114 m.Return(m.Word32Equal(
1115 (m.*shift.constructor)(m.Parameter(1), m.Int32Constant(imm)),
1116 m.Parameter(0)));
1117 Stream s = m.Build();
1118 ASSERT_EQ(1U, s.size());
1119 EXPECT_EQ(kArmCmp, s[0]->arch_opcode());
1120 EXPECT_EQ(shift.i_mode, s[0]->addressing_mode());
1121 ASSERT_EQ(3U, s[0]->InputCount());
1122 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2)));
1123 EXPECT_EQ(1U, s[0]->OutputCount());
1124 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1125 EXPECT_EQ(kEqual, s[0]->flags_condition());
1126 }
1127 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) {
1128 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
1129 MachineType::Int32());
1130 m.Return(m.Word32Equal(
1131 m.Parameter(0),
1132 (m.*shift.constructor)(m.Parameter(1), m.Int32Constant(imm))));
1133 Stream s = m.Build();
1134 ASSERT_EQ(1U, s.size());
1135 EXPECT_EQ(kArmCmp, s[0]->arch_opcode());
1136 EXPECT_EQ(shift.i_mode, s[0]->addressing_mode());
1137 ASSERT_EQ(3U, s[0]->InputCount());
1138 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2)));
1139 EXPECT_EQ(1U, s[0]->OutputCount());
1140 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1141 EXPECT_EQ(kEqual, s[0]->flags_condition());
1142 }
1143 }
1144
1145
TEST_P(InstructionSelectorShiftTest,Word32EqualToZeroWithParameters)1146 TEST_P(InstructionSelectorShiftTest, Word32EqualToZeroWithParameters) {
1147 const Shift shift = GetParam();
1148 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
1149 MachineType::Int32());
1150 m.Return(
1151 m.Word32Equal(m.Int32Constant(0),
1152 (m.*shift.constructor)(m.Parameter(0), m.Parameter(1))));
1153 Stream s = m.Build();
1154 ASSERT_EQ(1U, s.size());
1155 EXPECT_EQ(kArmMov, s[0]->arch_opcode());
1156 EXPECT_EQ(shift.r_mode, s[0]->addressing_mode());
1157 EXPECT_EQ(2U, s[0]->InputCount());
1158 EXPECT_EQ(2U, s[0]->OutputCount());
1159 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1160 EXPECT_EQ(kEqual, s[0]->flags_condition());
1161 }
1162
1163
TEST_P(InstructionSelectorShiftTest,Word32EqualToZeroWithImmediate)1164 TEST_P(InstructionSelectorShiftTest, Word32EqualToZeroWithImmediate) {
1165 const Shift shift = GetParam();
1166 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) {
1167 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
1168 MachineType::Int32());
1169 m.Return(m.Word32Equal(
1170 m.Int32Constant(0),
1171 (m.*shift.constructor)(m.Parameter(0), m.Int32Constant(imm))));
1172 Stream s = m.Build();
1173 ASSERT_EQ(1U, s.size());
1174 EXPECT_EQ(kArmMov, s[0]->arch_opcode());
1175 EXPECT_EQ(shift.i_mode, s[0]->addressing_mode());
1176 ASSERT_EQ(2U, s[0]->InputCount());
1177 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
1178 EXPECT_EQ(2U, s[0]->OutputCount());
1179 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1180 EXPECT_EQ(kEqual, s[0]->flags_condition());
1181 }
1182 }
1183
1184
TEST_P(InstructionSelectorShiftTest,Word32NotWithParameters)1185 TEST_P(InstructionSelectorShiftTest, Word32NotWithParameters) {
1186 const Shift shift = GetParam();
1187 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
1188 MachineType::Int32());
1189 m.Return(m.Word32Not((m.*shift.constructor)(m.Parameter(0), m.Parameter(1))));
1190 Stream s = m.Build();
1191 ASSERT_EQ(1U, s.size());
1192 EXPECT_EQ(kArmMvn, s[0]->arch_opcode());
1193 EXPECT_EQ(shift.r_mode, s[0]->addressing_mode());
1194 EXPECT_EQ(2U, s[0]->InputCount());
1195 EXPECT_EQ(1U, s[0]->OutputCount());
1196 }
1197
1198
TEST_P(InstructionSelectorShiftTest,Word32NotWithImmediate)1199 TEST_P(InstructionSelectorShiftTest, Word32NotWithImmediate) {
1200 const Shift shift = GetParam();
1201 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) {
1202 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
1203 m.Return(m.Word32Not(
1204 (m.*shift.constructor)(m.Parameter(0), m.Int32Constant(imm))));
1205 Stream s = m.Build();
1206 ASSERT_EQ(1U, s.size());
1207 EXPECT_EQ(kArmMvn, s[0]->arch_opcode());
1208 EXPECT_EQ(shift.i_mode, s[0]->addressing_mode());
1209 ASSERT_EQ(2U, s[0]->InputCount());
1210 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
1211 EXPECT_EQ(1U, s[0]->OutputCount());
1212 }
1213 }
1214
1215
TEST_P(InstructionSelectorShiftTest,Word32AndWithWord32NotWithParameters)1216 TEST_P(InstructionSelectorShiftTest, Word32AndWithWord32NotWithParameters) {
1217 const Shift shift = GetParam();
1218 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
1219 MachineType::Int32(), MachineType::Int32());
1220 m.Return(m.Word32And(m.Parameter(0), m.Word32Not((m.*shift.constructor)(
1221 m.Parameter(1), m.Parameter(2)))));
1222 Stream s = m.Build();
1223 ASSERT_EQ(1U, s.size());
1224 EXPECT_EQ(kArmBic, s[0]->arch_opcode());
1225 EXPECT_EQ(shift.r_mode, s[0]->addressing_mode());
1226 EXPECT_EQ(3U, s[0]->InputCount());
1227 EXPECT_EQ(1U, s[0]->OutputCount());
1228 }
1229
1230
TEST_P(InstructionSelectorShiftTest,Word32AndWithWord32NotWithImmediate)1231 TEST_P(InstructionSelectorShiftTest, Word32AndWithWord32NotWithImmediate) {
1232 const Shift shift = GetParam();
1233 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) {
1234 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
1235 MachineType::Int32());
1236 m.Return(m.Word32And(m.Parameter(0),
1237 m.Word32Not((m.*shift.constructor)(
1238 m.Parameter(1), m.Int32Constant(imm)))));
1239 Stream s = m.Build();
1240 ASSERT_EQ(1U, s.size());
1241 EXPECT_EQ(kArmBic, s[0]->arch_opcode());
1242 EXPECT_EQ(shift.i_mode, s[0]->addressing_mode());
1243 ASSERT_EQ(3U, s[0]->InputCount());
1244 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2)));
1245 EXPECT_EQ(1U, s[0]->OutputCount());
1246 }
1247 }
1248
1249
1250 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorShiftTest,
1251 ::testing::ValuesIn(kShifts));
1252
1253
1254 // -----------------------------------------------------------------------------
1255 // Memory access instructions.
1256
1257
1258 namespace {
1259
1260 struct MemoryAccess {
1261 MachineType type;
1262 ArchOpcode ldr_opcode;
1263 ArchOpcode str_opcode;
1264 bool (InstructionSelectorTest::Stream::*val_predicate)(
1265 const InstructionOperand*) const;
1266 const int32_t immediates[40];
1267 };
1268
1269
operator <<(std::ostream & os,const MemoryAccess & memacc)1270 std::ostream& operator<<(std::ostream& os, const MemoryAccess& memacc) {
1271 return os << memacc.type;
1272 }
1273
1274
1275 const MemoryAccess kMemoryAccesses[] = {
1276 {MachineType::Int8(),
1277 kArmLdrsb,
1278 kArmStrb,
1279 &InstructionSelectorTest::Stream::IsInteger,
1280 {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89,
1281 -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109,
1282 115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}},
1283 {MachineType::Uint8(),
1284 kArmLdrb,
1285 kArmStrb,
1286 &InstructionSelectorTest::Stream::IsInteger,
1287 {-4095, -3914, -3536, -3234, -3185, -3169, -1073, -990, -859, -720, -434,
1288 -127, -124, -122, -105, -91, -86, -64, -55, -53, -30, -10, -3, 0, 20, 28,
1289 39, 58, 64, 73, 75, 100, 108, 121, 686, 963, 1363, 2759, 3449, 4095}},
1290 {MachineType::Int16(),
1291 kArmLdrsh,
1292 kArmStrh,
1293 &InstructionSelectorTest::Stream::IsInteger,
1294 {-255, -251, -232, -220, -144, -138, -130, -126, -116, -115, -102, -101,
1295 -98, -69, -59, -56, -39, -35, -23, -19, -7, 0, 22, 26, 37, 68, 83, 87, 98,
1296 102, 108, 111, 117, 171, 195, 203, 204, 245, 246, 255}},
1297 {MachineType::Uint16(),
1298 kArmLdrh,
1299 kArmStrh,
1300 &InstructionSelectorTest::Stream::IsInteger,
1301 {-255, -230, -201, -172, -125, -119, -118, -105, -98, -79, -54, -42, -41,
1302 -32, -12, -11, -5, -4, 0, 5, 9, 25, 28, 51, 58, 60, 89, 104, 108, 109,
1303 114, 116, 120, 138, 150, 161, 166, 172, 228, 255}},
1304 {MachineType::Int32(),
1305 kArmLdr,
1306 kArmStr,
1307 &InstructionSelectorTest::Stream::IsInteger,
1308 {-4095, -1898, -1685, -1562, -1408, -1313, -344, -128, -116, -100, -92,
1309 -80, -72, -71, -56, -25, -21, -11, -9, 0, 3, 5, 27, 28, 42, 52, 63, 88,
1310 93, 97, 125, 846, 1037, 2102, 2403, 2597, 2632, 2997, 3935, 4095}},
1311 {MachineType::Float32(),
1312 kArmVldrF32,
1313 kArmVstrF32,
1314 &InstructionSelectorTest::Stream::IsDouble,
1315 {-1020, -928, -896, -772, -728, -680, -660, -488, -372, -112, -100, -92,
1316 -84, -80, -72, -64, -60, -56, -52, -48, -36, -32, -20, -8, -4, 0, 8, 20,
1317 24, 40, 64, 112, 204, 388, 516, 852, 856, 976, 988, 1020}},
1318 {MachineType::Float64(),
1319 kArmVldrF64,
1320 kArmVstrF64,
1321 &InstructionSelectorTest::Stream::IsDouble,
1322 {-1020, -948, -796, -696, -612, -364, -320, -308, -128, -112, -108, -104,
1323 -96, -84, -80, -56, -48, -40, -20, 0, 24, 28, 36, 48, 64, 84, 96, 100,
1324 108, 116, 120, 140, 156, 408, 432, 444, 772, 832, 940, 1020}}};
1325
1326 } // namespace
1327
1328
1329 typedef InstructionSelectorTestWithParam<MemoryAccess>
1330 InstructionSelectorMemoryAccessTest;
1331
1332
TEST_P(InstructionSelectorMemoryAccessTest,LoadWithParameters)1333 TEST_P(InstructionSelectorMemoryAccessTest, LoadWithParameters) {
1334 const MemoryAccess memacc = GetParam();
1335 StreamBuilder m(this, memacc.type, MachineType::Pointer(),
1336 MachineType::Int32());
1337 m.Return(m.Load(memacc.type, m.Parameter(0), m.Parameter(1)));
1338 Stream s = m.Build();
1339 ASSERT_EQ(1U, s.size());
1340 EXPECT_EQ(memacc.ldr_opcode, s[0]->arch_opcode());
1341 EXPECT_EQ(kMode_Offset_RR, s[0]->addressing_mode());
1342 EXPECT_EQ(2U, s[0]->InputCount());
1343 ASSERT_EQ(1U, s[0]->OutputCount());
1344 EXPECT_TRUE((s.*memacc.val_predicate)(s[0]->Output()));
1345 }
1346
1347
TEST_P(InstructionSelectorMemoryAccessTest,LoadWithImmediateIndex)1348 TEST_P(InstructionSelectorMemoryAccessTest, LoadWithImmediateIndex) {
1349 const MemoryAccess memacc = GetParam();
1350 TRACED_FOREACH(int32_t, index, memacc.immediates) {
1351 StreamBuilder m(this, memacc.type, MachineType::Pointer());
1352 m.Return(m.Load(memacc.type, m.Parameter(0), m.Int32Constant(index)));
1353 Stream s = m.Build();
1354 ASSERT_EQ(1U, s.size());
1355 EXPECT_EQ(memacc.ldr_opcode, s[0]->arch_opcode());
1356 EXPECT_EQ(kMode_Offset_RI, s[0]->addressing_mode());
1357 ASSERT_EQ(2U, s[0]->InputCount());
1358 ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
1359 EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1)));
1360 ASSERT_EQ(1U, s[0]->OutputCount());
1361 EXPECT_TRUE((s.*memacc.val_predicate)(s[0]->Output()));
1362 }
1363 }
1364
1365
TEST_P(InstructionSelectorMemoryAccessTest,StoreWithParameters)1366 TEST_P(InstructionSelectorMemoryAccessTest, StoreWithParameters) {
1367 const MemoryAccess memacc = GetParam();
1368 StreamBuilder m(this, MachineType::Int32(), MachineType::Pointer(),
1369 MachineType::Int32(), memacc.type);
1370 m.Store(memacc.type.representation(), m.Parameter(0), m.Parameter(1),
1371 m.Parameter(2), kNoWriteBarrier);
1372 m.Return(m.Int32Constant(0));
1373 Stream s = m.Build();
1374 ASSERT_EQ(1U, s.size());
1375 EXPECT_EQ(memacc.str_opcode, s[0]->arch_opcode());
1376 EXPECT_EQ(kMode_Offset_RR, s[0]->addressing_mode());
1377 EXPECT_EQ(3U, s[0]->InputCount());
1378 EXPECT_EQ(0U, s[0]->OutputCount());
1379 }
1380
1381
TEST_P(InstructionSelectorMemoryAccessTest,StoreWithImmediateIndex)1382 TEST_P(InstructionSelectorMemoryAccessTest, StoreWithImmediateIndex) {
1383 const MemoryAccess memacc = GetParam();
1384 TRACED_FOREACH(int32_t, index, memacc.immediates) {
1385 StreamBuilder m(this, MachineType::Int32(), MachineType::Pointer(),
1386 memacc.type);
1387 m.Store(memacc.type.representation(), m.Parameter(0),
1388 m.Int32Constant(index), m.Parameter(1), kNoWriteBarrier);
1389 m.Return(m.Int32Constant(0));
1390 Stream s = m.Build();
1391 ASSERT_EQ(1U, s.size());
1392 EXPECT_EQ(memacc.str_opcode, s[0]->arch_opcode());
1393 EXPECT_EQ(kMode_Offset_RI, s[0]->addressing_mode());
1394 ASSERT_EQ(3U, s[0]->InputCount());
1395 ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
1396 EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1)));
1397 EXPECT_EQ(0U, s[0]->OutputCount());
1398 }
1399 }
1400
1401
1402 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1403 InstructionSelectorMemoryAccessTest,
1404 ::testing::ValuesIn(kMemoryAccesses));
1405
1406
1407 // -----------------------------------------------------------------------------
1408 // Conversions.
1409
1410
TEST_F(InstructionSelectorTest,ChangeFloat32ToFloat64WithParameter)1411 TEST_F(InstructionSelectorTest, ChangeFloat32ToFloat64WithParameter) {
1412 StreamBuilder m(this, MachineType::Float64(), MachineType::Float32());
1413 m.Return(m.ChangeFloat32ToFloat64(m.Parameter(0)));
1414 Stream s = m.Build();
1415 ASSERT_EQ(1U, s.size());
1416 EXPECT_EQ(kArmVcvtF64F32, s[0]->arch_opcode());
1417 EXPECT_EQ(1U, s[0]->InputCount());
1418 EXPECT_EQ(1U, s[0]->OutputCount());
1419 }
1420
1421
TEST_F(InstructionSelectorTest,TruncateFloat64ToFloat32WithParameter)1422 TEST_F(InstructionSelectorTest, TruncateFloat64ToFloat32WithParameter) {
1423 StreamBuilder m(this, MachineType::Float32(), MachineType::Float64());
1424 m.Return(m.TruncateFloat64ToFloat32(m.Parameter(0)));
1425 Stream s = m.Build();
1426 ASSERT_EQ(1U, s.size());
1427 EXPECT_EQ(kArmVcvtF32F64, s[0]->arch_opcode());
1428 EXPECT_EQ(1U, s[0]->InputCount());
1429 EXPECT_EQ(1U, s[0]->OutputCount());
1430 }
1431
1432
1433 // -----------------------------------------------------------------------------
1434 // Comparisons.
1435
1436
1437 namespace {
1438
1439 struct Comparison {
1440 Constructor constructor;
1441 const char* constructor_name;
1442 FlagsCondition flags_condition;
1443 FlagsCondition negated_flags_condition;
1444 FlagsCondition commuted_flags_condition;
1445 };
1446
1447
operator <<(std::ostream & os,const Comparison & cmp)1448 std::ostream& operator<<(std::ostream& os, const Comparison& cmp) {
1449 return os << cmp.constructor_name;
1450 }
1451
1452
1453 const Comparison kComparisons[] = {
1454 {&RawMachineAssembler::Word32Equal, "Word32Equal", kEqual, kNotEqual,
1455 kEqual},
1456 {&RawMachineAssembler::Int32LessThan, "Int32LessThan", kSignedLessThan,
1457 kSignedGreaterThanOrEqual, kSignedGreaterThan},
1458 {&RawMachineAssembler::Int32LessThanOrEqual, "Int32LessThanOrEqual",
1459 kSignedLessThanOrEqual, kSignedGreaterThan, kSignedGreaterThanOrEqual},
1460 {&RawMachineAssembler::Uint32LessThan, "Uint32LessThan", kUnsignedLessThan,
1461 kUnsignedGreaterThanOrEqual, kUnsignedGreaterThan},
1462 {&RawMachineAssembler::Uint32LessThanOrEqual, "Uint32LessThanOrEqual",
1463 kUnsignedLessThanOrEqual, kUnsignedGreaterThan,
1464 kUnsignedGreaterThanOrEqual}};
1465
1466 } // namespace
1467
1468
1469 typedef InstructionSelectorTestWithParam<Comparison>
1470 InstructionSelectorComparisonTest;
1471
1472
TEST_P(InstructionSelectorComparisonTest,Parameters)1473 TEST_P(InstructionSelectorComparisonTest, Parameters) {
1474 const Comparison& cmp = GetParam();
1475 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
1476 MachineType::Int32());
1477 Node* const p0 = m.Parameter(0);
1478 Node* const p1 = m.Parameter(1);
1479 Node* const r = (m.*cmp.constructor)(p0, p1);
1480 m.Return(r);
1481 Stream const s = m.Build();
1482 ASSERT_EQ(1U, s.size());
1483 EXPECT_EQ(kArmCmp, s[0]->arch_opcode());
1484 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
1485 ASSERT_EQ(2U, s[0]->InputCount());
1486 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1487 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
1488 ASSERT_EQ(1U, s[0]->OutputCount());
1489 EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->OutputAt(0)));
1490 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1491 EXPECT_EQ(cmp.flags_condition, s[0]->flags_condition());
1492 }
1493
1494
TEST_P(InstructionSelectorComparisonTest,Word32EqualWithZero)1495 TEST_P(InstructionSelectorComparisonTest, Word32EqualWithZero) {
1496 {
1497 const Comparison& cmp = GetParam();
1498 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
1499 MachineType::Int32());
1500 Node* const p0 = m.Parameter(0);
1501 Node* const p1 = m.Parameter(1);
1502 Node* const r =
1503 m.Word32Equal((m.*cmp.constructor)(p0, p1), m.Int32Constant(0));
1504 m.Return(r);
1505 Stream const s = m.Build();
1506 ASSERT_EQ(1U, s.size());
1507 EXPECT_EQ(kArmCmp, s[0]->arch_opcode());
1508 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
1509 ASSERT_EQ(2U, s[0]->InputCount());
1510 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1511 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
1512 ASSERT_EQ(1U, s[0]->OutputCount());
1513 EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->OutputAt(0)));
1514 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1515 EXPECT_EQ(cmp.negated_flags_condition, s[0]->flags_condition());
1516 }
1517 {
1518 const Comparison& cmp = GetParam();
1519 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
1520 MachineType::Int32());
1521 Node* const p0 = m.Parameter(0);
1522 Node* const p1 = m.Parameter(1);
1523 Node* const r =
1524 m.Word32Equal(m.Int32Constant(0), (m.*cmp.constructor)(p0, p1));
1525 m.Return(r);
1526 Stream const s = m.Build();
1527 ASSERT_EQ(1U, s.size());
1528 EXPECT_EQ(kArmCmp, s[0]->arch_opcode());
1529 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
1530 ASSERT_EQ(2U, s[0]->InputCount());
1531 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1532 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
1533 ASSERT_EQ(1U, s[0]->OutputCount());
1534 EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->OutputAt(0)));
1535 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1536 EXPECT_EQ(cmp.negated_flags_condition, s[0]->flags_condition());
1537 }
1538 }
1539
1540
1541 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1542 InstructionSelectorComparisonTest,
1543 ::testing::ValuesIn(kComparisons));
1544
1545
1546 // -----------------------------------------------------------------------------
1547 // Floating point comparisons.
1548
1549
1550 namespace {
1551
1552 const Comparison kF32Comparisons[] = {
1553 {&RawMachineAssembler::Float32Equal, "Float32Equal", kEqual, kNotEqual,
1554 kEqual},
1555 {&RawMachineAssembler::Float32LessThan, "Float32LessThan",
1556 kFloatLessThan, kFloatGreaterThanOrEqualOrUnordered, kFloatGreaterThan},
1557 {&RawMachineAssembler::Float32LessThanOrEqual, "Float32LessThanOrEqual",
1558 kFloatLessThanOrEqual, kFloatGreaterThanOrUnordered,
1559 kFloatGreaterThanOrEqual}};
1560
1561 } // namespace
1562
1563 typedef InstructionSelectorTestWithParam<Comparison>
1564 InstructionSelectorF32ComparisonTest;
1565
1566
TEST_P(InstructionSelectorF32ComparisonTest,WithParameters)1567 TEST_P(InstructionSelectorF32ComparisonTest, WithParameters) {
1568 const Comparison& cmp = GetParam();
1569 StreamBuilder m(this, MachineType::Int32(), MachineType::Float32(),
1570 MachineType::Float32());
1571 m.Return((m.*cmp.constructor)(m.Parameter(0), m.Parameter(1)));
1572 Stream const s = m.Build();
1573 ASSERT_EQ(1U, s.size());
1574 EXPECT_EQ(kArmVcmpF32, s[0]->arch_opcode());
1575 ASSERT_EQ(2U, s[0]->InputCount());
1576 ASSERT_EQ(1U, s[0]->OutputCount());
1577 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1578 EXPECT_EQ(cmp.flags_condition, s[0]->flags_condition());
1579 }
1580
1581
TEST_P(InstructionSelectorF32ComparisonTest,NegatedWithParameters)1582 TEST_P(InstructionSelectorF32ComparisonTest, NegatedWithParameters) {
1583 const Comparison& cmp = GetParam();
1584 StreamBuilder m(this, MachineType::Int32(), MachineType::Float32(),
1585 MachineType::Float32());
1586 m.Return(
1587 m.WordBinaryNot((m.*cmp.constructor)(m.Parameter(0), m.Parameter(1))));
1588 Stream const s = m.Build();
1589 ASSERT_EQ(1U, s.size());
1590 EXPECT_EQ(kArmVcmpF32, s[0]->arch_opcode());
1591 ASSERT_EQ(2U, s[0]->InputCount());
1592 ASSERT_EQ(1U, s[0]->OutputCount());
1593 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1594 EXPECT_EQ(cmp.negated_flags_condition, s[0]->flags_condition());
1595 }
1596
1597
TEST_P(InstructionSelectorF32ComparisonTest,WithImmediateZeroOnRight)1598 TEST_P(InstructionSelectorF32ComparisonTest, WithImmediateZeroOnRight) {
1599 const Comparison& cmp = GetParam();
1600 StreamBuilder m(this, MachineType::Int32(), MachineType::Float32());
1601 m.Return((m.*cmp.constructor)(m.Parameter(0), m.Float32Constant(0.0)));
1602 Stream const s = m.Build();
1603 ASSERT_EQ(1U, s.size());
1604 EXPECT_EQ(kArmVcmpF32, s[0]->arch_opcode());
1605 ASSERT_EQ(2U, s[0]->InputCount());
1606 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
1607 ASSERT_EQ(1U, s[0]->OutputCount());
1608 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1609 EXPECT_EQ(cmp.flags_condition, s[0]->flags_condition());
1610 }
1611
1612
TEST_P(InstructionSelectorF32ComparisonTest,WithImmediateZeroOnLeft)1613 TEST_P(InstructionSelectorF32ComparisonTest, WithImmediateZeroOnLeft) {
1614 const Comparison& cmp = GetParam();
1615 StreamBuilder m(this, MachineType::Int32(), MachineType::Float32());
1616 m.Return((m.*cmp.constructor)(m.Float32Constant(0.0f), m.Parameter(0)));
1617 Stream const s = m.Build();
1618 ASSERT_EQ(1U, s.size());
1619 EXPECT_EQ(kArmVcmpF32, s[0]->arch_opcode());
1620 ASSERT_EQ(2U, s[0]->InputCount());
1621 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
1622 ASSERT_EQ(1U, s[0]->OutputCount());
1623 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1624 EXPECT_EQ(cmp.commuted_flags_condition, s[0]->flags_condition());
1625 }
1626
1627
1628 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1629 InstructionSelectorF32ComparisonTest,
1630 ::testing::ValuesIn(kF32Comparisons));
1631
1632
1633 namespace {
1634
1635 const Comparison kF64Comparisons[] = {
1636 {&RawMachineAssembler::Float64Equal, "Float64Equal", kEqual, kNotEqual,
1637 kEqual},
1638 {&RawMachineAssembler::Float64LessThan, "Float64LessThan",
1639 kFloatLessThan, kFloatGreaterThanOrEqualOrUnordered, kFloatGreaterThan},
1640 {&RawMachineAssembler::Float64LessThanOrEqual, "Float64LessThanOrEqual",
1641 kFloatLessThanOrEqual, kFloatGreaterThanOrUnordered,
1642 kFloatGreaterThanOrEqual}};
1643
1644 } // namespace
1645
1646 typedef InstructionSelectorTestWithParam<Comparison>
1647 InstructionSelectorF64ComparisonTest;
1648
1649
TEST_P(InstructionSelectorF64ComparisonTest,WithParameters)1650 TEST_P(InstructionSelectorF64ComparisonTest, WithParameters) {
1651 const Comparison& cmp = GetParam();
1652 StreamBuilder m(this, MachineType::Int32(), MachineType::Float64(),
1653 MachineType::Float64());
1654 m.Return((m.*cmp.constructor)(m.Parameter(0), m.Parameter(1)));
1655 Stream const s = m.Build();
1656 ASSERT_EQ(1U, s.size());
1657 EXPECT_EQ(kArmVcmpF64, s[0]->arch_opcode());
1658 ASSERT_EQ(2U, s[0]->InputCount());
1659 ASSERT_EQ(1U, s[0]->OutputCount());
1660 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1661 EXPECT_EQ(cmp.flags_condition, s[0]->flags_condition());
1662 }
1663
1664
TEST_P(InstructionSelectorF64ComparisonTest,NegatedWithParameters)1665 TEST_P(InstructionSelectorF64ComparisonTest, NegatedWithParameters) {
1666 const Comparison& cmp = GetParam();
1667 StreamBuilder m(this, MachineType::Int32(), MachineType::Float64(),
1668 MachineType::Float64());
1669 m.Return(
1670 m.WordBinaryNot((m.*cmp.constructor)(m.Parameter(0), m.Parameter(1))));
1671 Stream const s = m.Build();
1672 ASSERT_EQ(1U, s.size());
1673 EXPECT_EQ(kArmVcmpF64, s[0]->arch_opcode());
1674 ASSERT_EQ(2U, s[0]->InputCount());
1675 ASSERT_EQ(1U, s[0]->OutputCount());
1676 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1677 EXPECT_EQ(cmp.negated_flags_condition, s[0]->flags_condition());
1678 }
1679
1680
TEST_P(InstructionSelectorF64ComparisonTest,WithImmediateZeroOnRight)1681 TEST_P(InstructionSelectorF64ComparisonTest, WithImmediateZeroOnRight) {
1682 const Comparison& cmp = GetParam();
1683 StreamBuilder m(this, MachineType::Int32(), MachineType::Float64());
1684 m.Return((m.*cmp.constructor)(m.Parameter(0), m.Float64Constant(0.0)));
1685 Stream const s = m.Build();
1686 ASSERT_EQ(1U, s.size());
1687 EXPECT_EQ(kArmVcmpF64, s[0]->arch_opcode());
1688 ASSERT_EQ(2U, s[0]->InputCount());
1689 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
1690 ASSERT_EQ(1U, s[0]->OutputCount());
1691 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1692 EXPECT_EQ(cmp.flags_condition, s[0]->flags_condition());
1693 }
1694
1695
TEST_P(InstructionSelectorF64ComparisonTest,WithImmediateZeroOnLeft)1696 TEST_P(InstructionSelectorF64ComparisonTest, WithImmediateZeroOnLeft) {
1697 const Comparison& cmp = GetParam();
1698 StreamBuilder m(this, MachineType::Int32(), MachineType::Float64());
1699 m.Return((m.*cmp.constructor)(m.Float64Constant(0.0), m.Parameter(0)));
1700 Stream const s = m.Build();
1701 ASSERT_EQ(1U, s.size());
1702 EXPECT_EQ(kArmVcmpF64, s[0]->arch_opcode());
1703 ASSERT_EQ(2U, s[0]->InputCount());
1704 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
1705 ASSERT_EQ(1U, s[0]->OutputCount());
1706 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1707 EXPECT_EQ(cmp.commuted_flags_condition, s[0]->flags_condition());
1708 }
1709
1710
1711 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1712 InstructionSelectorF64ComparisonTest,
1713 ::testing::ValuesIn(kF64Comparisons));
1714
1715
1716 // -----------------------------------------------------------------------------
1717 // Floating point arithmetic.
1718
1719
1720 typedef InstructionSelectorTestWithParam<FAI> InstructionSelectorFAITest;
1721
1722
TEST_P(InstructionSelectorFAITest,Parameters)1723 TEST_P(InstructionSelectorFAITest, Parameters) {
1724 const FAI& fai = GetParam();
1725 StreamBuilder m(this, fai.machine_type, fai.machine_type, fai.machine_type);
1726 Node* const p0 = m.Parameter(0);
1727 Node* const p1 = m.Parameter(1);
1728 Node* const r = (m.*fai.constructor)(p0, p1);
1729 m.Return(r);
1730 Stream const s = m.Build();
1731 ASSERT_EQ(1U, s.size());
1732 EXPECT_EQ(fai.arch_opcode, s[0]->arch_opcode());
1733 EXPECT_EQ(kMode_None, s[0]->addressing_mode());
1734 ASSERT_EQ(2U, s[0]->InputCount());
1735 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1736 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
1737 ASSERT_EQ(1U, s[0]->OutputCount());
1738 EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->OutputAt(0)));
1739 EXPECT_EQ(kFlags_none, s[0]->flags_mode());
1740 }
1741
1742
1743 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorFAITest,
1744 ::testing::ValuesIn(kFAIs));
1745
1746
TEST_F(InstructionSelectorTest,Float32Abs)1747 TEST_F(InstructionSelectorTest, Float32Abs) {
1748 StreamBuilder m(this, MachineType::Float32(), MachineType::Float32());
1749 Node* const p0 = m.Parameter(0);
1750 Node* const n = m.Float32Abs(p0);
1751 m.Return(n);
1752 Stream s = m.Build();
1753 ASSERT_EQ(1U, s.size());
1754 EXPECT_EQ(kArmVabsF32, s[0]->arch_opcode());
1755 ASSERT_EQ(1U, s[0]->InputCount());
1756 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1757 ASSERT_EQ(1U, s[0]->OutputCount());
1758 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1759 }
1760
1761
TEST_F(InstructionSelectorTest,Float64Abs)1762 TEST_F(InstructionSelectorTest, Float64Abs) {
1763 StreamBuilder m(this, MachineType::Float64(), MachineType::Float64());
1764 Node* const p0 = m.Parameter(0);
1765 Node* const n = m.Float64Abs(p0);
1766 m.Return(n);
1767 Stream s = m.Build();
1768 ASSERT_EQ(1U, s.size());
1769 EXPECT_EQ(kArmVabsF64, s[0]->arch_opcode());
1770 ASSERT_EQ(1U, s[0]->InputCount());
1771 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1772 ASSERT_EQ(1U, s[0]->OutputCount());
1773 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1774 }
1775
1776
TEST_F(InstructionSelectorTest,Float32AddWithFloat32Mul)1777 TEST_F(InstructionSelectorTest, Float32AddWithFloat32Mul) {
1778 {
1779 StreamBuilder m(this, MachineType::Float32(), MachineType::Float32(),
1780 MachineType::Float32(), MachineType::Float32());
1781 Node* const p0 = m.Parameter(0);
1782 Node* const p1 = m.Parameter(1);
1783 Node* const p2 = m.Parameter(2);
1784 Node* const n = m.Float32Add(m.Float32Mul(p0, p1), p2);
1785 m.Return(n);
1786 Stream s = m.Build();
1787 ASSERT_EQ(1U, s.size());
1788 EXPECT_EQ(kArmVmlaF32, s[0]->arch_opcode());
1789 ASSERT_EQ(3U, s[0]->InputCount());
1790 EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(0)));
1791 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1)));
1792 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(2)));
1793 ASSERT_EQ(1U, s[0]->OutputCount());
1794 EXPECT_TRUE(
1795 UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy());
1796 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1797 EXPECT_EQ(kFlags_none, s[0]->flags_mode());
1798 }
1799 {
1800 StreamBuilder m(this, MachineType::Float32(), MachineType::Float32(),
1801 MachineType::Float32(), MachineType::Float32());
1802 Node* const p0 = m.Parameter(0);
1803 Node* const p1 = m.Parameter(1);
1804 Node* const p2 = m.Parameter(2);
1805 Node* const n = m.Float32Add(p0, m.Float32Mul(p1, p2));
1806 m.Return(n);
1807 Stream s = m.Build();
1808 ASSERT_EQ(1U, s.size());
1809 EXPECT_EQ(kArmVmlaF32, s[0]->arch_opcode());
1810 ASSERT_EQ(3U, s[0]->InputCount());
1811 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1812 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
1813 EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(2)));
1814 ASSERT_EQ(1U, s[0]->OutputCount());
1815 EXPECT_TRUE(
1816 UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy());
1817 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1818 EXPECT_EQ(kFlags_none, s[0]->flags_mode());
1819 }
1820 }
1821
1822
TEST_F(InstructionSelectorTest,Float64AddWithFloat64Mul)1823 TEST_F(InstructionSelectorTest, Float64AddWithFloat64Mul) {
1824 {
1825 StreamBuilder m(this, MachineType::Float64(), MachineType::Float64(),
1826 MachineType::Float64(), MachineType::Float64());
1827 Node* const p0 = m.Parameter(0);
1828 Node* const p1 = m.Parameter(1);
1829 Node* const p2 = m.Parameter(2);
1830 Node* const n = m.Float64Add(m.Float64Mul(p0, p1), p2);
1831 m.Return(n);
1832 Stream s = m.Build();
1833 ASSERT_EQ(1U, s.size());
1834 EXPECT_EQ(kArmVmlaF64, s[0]->arch_opcode());
1835 ASSERT_EQ(3U, s[0]->InputCount());
1836 EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(0)));
1837 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1)));
1838 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(2)));
1839 ASSERT_EQ(1U, s[0]->OutputCount());
1840 EXPECT_TRUE(
1841 UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy());
1842 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1843 EXPECT_EQ(kFlags_none, s[0]->flags_mode());
1844 }
1845 {
1846 StreamBuilder m(this, MachineType::Float64(), MachineType::Float64(),
1847 MachineType::Float64(), MachineType::Float64());
1848 Node* const p0 = m.Parameter(0);
1849 Node* const p1 = m.Parameter(1);
1850 Node* const p2 = m.Parameter(2);
1851 Node* const n = m.Float64Add(p0, m.Float64Mul(p1, p2));
1852 m.Return(n);
1853 Stream s = m.Build();
1854 ASSERT_EQ(1U, s.size());
1855 EXPECT_EQ(kArmVmlaF64, s[0]->arch_opcode());
1856 ASSERT_EQ(3U, s[0]->InputCount());
1857 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1858 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
1859 EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(2)));
1860 ASSERT_EQ(1U, s[0]->OutputCount());
1861 EXPECT_TRUE(
1862 UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy());
1863 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1864 EXPECT_EQ(kFlags_none, s[0]->flags_mode());
1865 }
1866 }
1867
1868
TEST_F(InstructionSelectorTest,Float32SubWithMinusZero)1869 TEST_F(InstructionSelectorTest, Float32SubWithMinusZero) {
1870 StreamBuilder m(this, MachineType::Float32(), MachineType::Float32());
1871 Node* const p0 = m.Parameter(0);
1872 Node* const n = m.Float32Sub(m.Float32Constant(-0.0f), p0);
1873 m.Return(n);
1874 Stream s = m.Build();
1875 ASSERT_EQ(1U, s.size());
1876 EXPECT_EQ(kArmVnegF32, s[0]->arch_opcode());
1877 ASSERT_EQ(1U, s[0]->InputCount());
1878 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1879 ASSERT_EQ(1U, s[0]->OutputCount());
1880 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1881 }
1882
1883
TEST_F(InstructionSelectorTest,Float64SubWithMinusZero)1884 TEST_F(InstructionSelectorTest, Float64SubWithMinusZero) {
1885 StreamBuilder m(this, MachineType::Float64(), MachineType::Float64());
1886 Node* const p0 = m.Parameter(0);
1887 Node* const n = m.Float64Sub(m.Float64Constant(-0.0), p0);
1888 m.Return(n);
1889 Stream s = m.Build();
1890 ASSERT_EQ(1U, s.size());
1891 EXPECT_EQ(kArmVnegF64, s[0]->arch_opcode());
1892 ASSERT_EQ(1U, s[0]->InputCount());
1893 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1894 ASSERT_EQ(1U, s[0]->OutputCount());
1895 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1896 }
1897
1898
TEST_F(InstructionSelectorTest,Float32SubWithFloat32Mul)1899 TEST_F(InstructionSelectorTest, Float32SubWithFloat32Mul) {
1900 StreamBuilder m(this, MachineType::Float32(), MachineType::Float32(),
1901 MachineType::Float32(), MachineType::Float32());
1902 Node* const p0 = m.Parameter(0);
1903 Node* const p1 = m.Parameter(1);
1904 Node* const p2 = m.Parameter(2);
1905 Node* const n = m.Float32Sub(p0, m.Float32Mul(p1, p2));
1906 m.Return(n);
1907 Stream s = m.Build();
1908 ASSERT_EQ(1U, s.size());
1909 EXPECT_EQ(kArmVmlsF32, s[0]->arch_opcode());
1910 ASSERT_EQ(3U, s[0]->InputCount());
1911 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1912 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
1913 EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(2)));
1914 ASSERT_EQ(1U, s[0]->OutputCount());
1915 EXPECT_TRUE(UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy());
1916 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1917 EXPECT_EQ(kFlags_none, s[0]->flags_mode());
1918 }
1919
1920
TEST_F(InstructionSelectorTest,Float64SubWithFloat64Mul)1921 TEST_F(InstructionSelectorTest, Float64SubWithFloat64Mul) {
1922 StreamBuilder m(this, MachineType::Float64(), MachineType::Float64(),
1923 MachineType::Float64(), MachineType::Float64());
1924 Node* const p0 = m.Parameter(0);
1925 Node* const p1 = m.Parameter(1);
1926 Node* const p2 = m.Parameter(2);
1927 Node* const n = m.Float64Sub(p0, m.Float64Mul(p1, p2));
1928 m.Return(n);
1929 Stream s = m.Build();
1930 ASSERT_EQ(1U, s.size());
1931 EXPECT_EQ(kArmVmlsF64, s[0]->arch_opcode());
1932 ASSERT_EQ(3U, s[0]->InputCount());
1933 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1934 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
1935 EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(2)));
1936 ASSERT_EQ(1U, s[0]->OutputCount());
1937 EXPECT_TRUE(UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy());
1938 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1939 EXPECT_EQ(kFlags_none, s[0]->flags_mode());
1940 }
1941
1942
TEST_F(InstructionSelectorTest,Float32Sqrt)1943 TEST_F(InstructionSelectorTest, Float32Sqrt) {
1944 StreamBuilder m(this, MachineType::Float32(), MachineType::Float32());
1945 Node* const p0 = m.Parameter(0);
1946 Node* const n = m.Float32Sqrt(p0);
1947 m.Return(n);
1948 Stream s = m.Build();
1949 ASSERT_EQ(1U, s.size());
1950 EXPECT_EQ(kArmVsqrtF32, s[0]->arch_opcode());
1951 ASSERT_EQ(1U, s[0]->InputCount());
1952 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1953 ASSERT_EQ(1U, s[0]->OutputCount());
1954 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1955 EXPECT_EQ(kFlags_none, s[0]->flags_mode());
1956 }
1957
1958
TEST_F(InstructionSelectorTest,Float64Sqrt)1959 TEST_F(InstructionSelectorTest, Float64Sqrt) {
1960 StreamBuilder m(this, MachineType::Float64(), MachineType::Float64());
1961 Node* const p0 = m.Parameter(0);
1962 Node* const n = m.Float64Sqrt(p0);
1963 m.Return(n);
1964 Stream s = m.Build();
1965 ASSERT_EQ(1U, s.size());
1966 EXPECT_EQ(kArmVsqrtF64, s[0]->arch_opcode());
1967 ASSERT_EQ(1U, s[0]->InputCount());
1968 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1969 ASSERT_EQ(1U, s[0]->OutputCount());
1970 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1971 EXPECT_EQ(kFlags_none, s[0]->flags_mode());
1972 }
1973
1974
1975 // -----------------------------------------------------------------------------
1976 // Miscellaneous.
1977
1978
TEST_F(InstructionSelectorTest,Int32AddWithInt32Mul)1979 TEST_F(InstructionSelectorTest, Int32AddWithInt32Mul) {
1980 {
1981 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
1982 MachineType::Int32(), MachineType::Int32());
1983 Node* const p0 = m.Parameter(0);
1984 Node* const p1 = m.Parameter(1);
1985 Node* const p2 = m.Parameter(2);
1986 Node* const n = m.Int32Add(p0, m.Int32Mul(p1, p2));
1987 m.Return(n);
1988 Stream s = m.Build();
1989 ASSERT_EQ(1U, s.size());
1990 EXPECT_EQ(kArmMla, s[0]->arch_opcode());
1991 ASSERT_EQ(3U, s[0]->InputCount());
1992 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(0)));
1993 EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(1)));
1994 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(2)));
1995 ASSERT_EQ(1U, s[0]->OutputCount());
1996 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1997 }
1998 {
1999 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2000 MachineType::Int32(), MachineType::Int32());
2001 Node* const p0 = m.Parameter(0);
2002 Node* const p1 = m.Parameter(1);
2003 Node* const p2 = m.Parameter(2);
2004 Node* const n = m.Int32Add(m.Int32Mul(p1, p2), p0);
2005 m.Return(n);
2006 Stream s = m.Build();
2007 ASSERT_EQ(1U, s.size());
2008 EXPECT_EQ(kArmMla, s[0]->arch_opcode());
2009 ASSERT_EQ(3U, s[0]->InputCount());
2010 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(0)));
2011 EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(1)));
2012 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(2)));
2013 ASSERT_EQ(1U, s[0]->OutputCount());
2014 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
2015 }
2016 }
2017
2018
TEST_F(InstructionSelectorTest,Int32AddWithInt32MulHigh)2019 TEST_F(InstructionSelectorTest, Int32AddWithInt32MulHigh) {
2020 {
2021 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2022 MachineType::Int32(), MachineType::Int32());
2023 Node* const p0 = m.Parameter(0);
2024 Node* const p1 = m.Parameter(1);
2025 Node* const p2 = m.Parameter(2);
2026 Node* const n = m.Int32Add(p0, m.Int32MulHigh(p1, p2));
2027 m.Return(n);
2028 Stream s = m.Build();
2029 ASSERT_EQ(1U, s.size());
2030 EXPECT_EQ(kArmSmmla, s[0]->arch_opcode());
2031 ASSERT_EQ(3U, s[0]->InputCount());
2032 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(0)));
2033 EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(1)));
2034 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(2)));
2035 ASSERT_EQ(1U, s[0]->OutputCount());
2036 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
2037 }
2038 {
2039 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2040 MachineType::Int32(), MachineType::Int32());
2041 Node* const p0 = m.Parameter(0);
2042 Node* const p1 = m.Parameter(1);
2043 Node* const p2 = m.Parameter(2);
2044 Node* const n = m.Int32Add(m.Int32MulHigh(p1, p2), p0);
2045 m.Return(n);
2046 Stream s = m.Build();
2047 ASSERT_EQ(1U, s.size());
2048 EXPECT_EQ(kArmSmmla, s[0]->arch_opcode());
2049 ASSERT_EQ(3U, s[0]->InputCount());
2050 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(0)));
2051 EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(1)));
2052 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(2)));
2053 ASSERT_EQ(1U, s[0]->OutputCount());
2054 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
2055 }
2056 }
2057
2058
TEST_F(InstructionSelectorTest,Int32AddWithWord32And)2059 TEST_F(InstructionSelectorTest, Int32AddWithWord32And) {
2060 {
2061 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2062 MachineType::Int32());
2063 Node* const p0 = m.Parameter(0);
2064 Node* const p1 = m.Parameter(1);
2065 Node* const r = m.Int32Add(m.Word32And(p0, m.Int32Constant(0xff)), p1);
2066 m.Return(r);
2067 Stream s = m.Build();
2068 ASSERT_EQ(1U, s.size());
2069 EXPECT_EQ(kArmUxtab, s[0]->arch_opcode());
2070 ASSERT_EQ(3U, s[0]->InputCount());
2071 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(0)));
2072 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1)));
2073 EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(2)));
2074 ASSERT_EQ(1U, s[0]->OutputCount());
2075 EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
2076 }
2077 {
2078 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2079 MachineType::Int32());
2080 Node* const p0 = m.Parameter(0);
2081 Node* const p1 = m.Parameter(1);
2082 Node* const r = m.Int32Add(p1, m.Word32And(p0, m.Int32Constant(0xff)));
2083 m.Return(r);
2084 Stream s = m.Build();
2085 ASSERT_EQ(1U, s.size());
2086 EXPECT_EQ(kArmUxtab, s[0]->arch_opcode());
2087 ASSERT_EQ(3U, s[0]->InputCount());
2088 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(0)));
2089 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1)));
2090 EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(2)));
2091 ASSERT_EQ(1U, s[0]->OutputCount());
2092 EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
2093 }
2094 {
2095 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2096 MachineType::Int32());
2097 Node* const p0 = m.Parameter(0);
2098 Node* const p1 = m.Parameter(1);
2099 Node* const r = m.Int32Add(m.Word32And(p0, m.Int32Constant(0xffff)), p1);
2100 m.Return(r);
2101 Stream s = m.Build();
2102 ASSERT_EQ(1U, s.size());
2103 EXPECT_EQ(kArmUxtah, s[0]->arch_opcode());
2104 ASSERT_EQ(3U, s[0]->InputCount());
2105 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(0)));
2106 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1)));
2107 EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(2)));
2108 ASSERT_EQ(1U, s[0]->OutputCount());
2109 EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
2110 }
2111 {
2112 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2113 MachineType::Int32());
2114 Node* const p0 = m.Parameter(0);
2115 Node* const p1 = m.Parameter(1);
2116 Node* const r = m.Int32Add(p1, m.Word32And(p0, m.Int32Constant(0xffff)));
2117 m.Return(r);
2118 Stream s = m.Build();
2119 ASSERT_EQ(1U, s.size());
2120 EXPECT_EQ(kArmUxtah, s[0]->arch_opcode());
2121 ASSERT_EQ(3U, s[0]->InputCount());
2122 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(0)));
2123 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1)));
2124 EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(2)));
2125 ASSERT_EQ(1U, s[0]->OutputCount());
2126 EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
2127 }
2128 }
2129
2130
TEST_F(InstructionSelectorTest,Int32AddWithWord32SarWithWord32Shl)2131 TEST_F(InstructionSelectorTest, Int32AddWithWord32SarWithWord32Shl) {
2132 {
2133 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2134 MachineType::Int32());
2135 Node* const p0 = m.Parameter(0);
2136 Node* const p1 = m.Parameter(1);
2137 Node* const r = m.Int32Add(
2138 m.Word32Sar(m.Word32Shl(p0, m.Int32Constant(24)), m.Int32Constant(24)),
2139 p1);
2140 m.Return(r);
2141 Stream s = m.Build();
2142 ASSERT_EQ(1U, s.size());
2143 EXPECT_EQ(kArmSxtab, s[0]->arch_opcode());
2144 ASSERT_EQ(3U, s[0]->InputCount());
2145 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(0)));
2146 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1)));
2147 EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(2)));
2148 ASSERT_EQ(1U, s[0]->OutputCount());
2149 EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
2150 }
2151 {
2152 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2153 MachineType::Int32());
2154 Node* const p0 = m.Parameter(0);
2155 Node* const p1 = m.Parameter(1);
2156 Node* const r = m.Int32Add(
2157 p1,
2158 m.Word32Sar(m.Word32Shl(p0, m.Int32Constant(24)), m.Int32Constant(24)));
2159 m.Return(r);
2160 Stream s = m.Build();
2161 ASSERT_EQ(1U, s.size());
2162 EXPECT_EQ(kArmSxtab, s[0]->arch_opcode());
2163 ASSERT_EQ(3U, s[0]->InputCount());
2164 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(0)));
2165 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1)));
2166 EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(2)));
2167 ASSERT_EQ(1U, s[0]->OutputCount());
2168 EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
2169 }
2170 {
2171 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2172 MachineType::Int32());
2173 Node* const p0 = m.Parameter(0);
2174 Node* const p1 = m.Parameter(1);
2175 Node* const r = m.Int32Add(
2176 m.Word32Sar(m.Word32Shl(p0, m.Int32Constant(16)), m.Int32Constant(16)),
2177 p1);
2178 m.Return(r);
2179 Stream s = m.Build();
2180 ASSERT_EQ(1U, s.size());
2181 EXPECT_EQ(kArmSxtah, s[0]->arch_opcode());
2182 ASSERT_EQ(3U, s[0]->InputCount());
2183 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(0)));
2184 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1)));
2185 EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(2)));
2186 ASSERT_EQ(1U, s[0]->OutputCount());
2187 EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
2188 }
2189 {
2190 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2191 MachineType::Int32());
2192 Node* const p0 = m.Parameter(0);
2193 Node* const p1 = m.Parameter(1);
2194 Node* const r = m.Int32Add(
2195 p1,
2196 m.Word32Sar(m.Word32Shl(p0, m.Int32Constant(16)), m.Int32Constant(16)));
2197 m.Return(r);
2198 Stream s = m.Build();
2199 ASSERT_EQ(1U, s.size());
2200 EXPECT_EQ(kArmSxtah, s[0]->arch_opcode());
2201 ASSERT_EQ(3U, s[0]->InputCount());
2202 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(0)));
2203 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1)));
2204 EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(2)));
2205 ASSERT_EQ(1U, s[0]->OutputCount());
2206 EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
2207 }
2208 }
2209
2210
TEST_F(InstructionSelectorTest,Int32SubWithInt32Mul)2211 TEST_F(InstructionSelectorTest, Int32SubWithInt32Mul) {
2212 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2213 MachineType::Int32(), MachineType::Int32());
2214 m.Return(
2215 m.Int32Sub(m.Parameter(0), m.Int32Mul(m.Parameter(1), m.Parameter(2))));
2216 Stream s = m.Build();
2217 ASSERT_EQ(2U, s.size());
2218 EXPECT_EQ(kArmMul, s[0]->arch_opcode());
2219 ASSERT_EQ(1U, s[0]->OutputCount());
2220 EXPECT_EQ(kArmSub, s[1]->arch_opcode());
2221 ASSERT_EQ(2U, s[1]->InputCount());
2222 EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(1)));
2223 }
2224
2225
TEST_F(InstructionSelectorTest,Int32SubWithInt32MulForMLS)2226 TEST_F(InstructionSelectorTest, Int32SubWithInt32MulForMLS) {
2227 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2228 MachineType::Int32(), MachineType::Int32());
2229 m.Return(
2230 m.Int32Sub(m.Parameter(0), m.Int32Mul(m.Parameter(1), m.Parameter(2))));
2231 Stream s = m.Build(MLS);
2232 ASSERT_EQ(1U, s.size());
2233 EXPECT_EQ(kArmMls, s[0]->arch_opcode());
2234 EXPECT_EQ(1U, s[0]->OutputCount());
2235 EXPECT_EQ(3U, s[0]->InputCount());
2236 }
2237
2238
TEST_F(InstructionSelectorTest,Int32DivWithParameters)2239 TEST_F(InstructionSelectorTest, Int32DivWithParameters) {
2240 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2241 MachineType::Int32());
2242 m.Return(m.Int32Div(m.Parameter(0), m.Parameter(1)));
2243 Stream s = m.Build();
2244 ASSERT_EQ(4U, s.size());
2245 EXPECT_EQ(kArmVcvtF64S32, s[0]->arch_opcode());
2246 ASSERT_EQ(1U, s[0]->OutputCount());
2247 EXPECT_EQ(kArmVcvtF64S32, s[1]->arch_opcode());
2248 ASSERT_EQ(1U, s[1]->OutputCount());
2249 EXPECT_EQ(kArmVdivF64, s[2]->arch_opcode());
2250 ASSERT_EQ(2U, s[2]->InputCount());
2251 ASSERT_EQ(1U, s[2]->OutputCount());
2252 EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[2]->InputAt(0)));
2253 EXPECT_EQ(s.ToVreg(s[1]->Output()), s.ToVreg(s[2]->InputAt(1)));
2254 EXPECT_EQ(kArmVcvtS32F64, s[3]->arch_opcode());
2255 ASSERT_EQ(1U, s[3]->InputCount());
2256 EXPECT_EQ(s.ToVreg(s[2]->Output()), s.ToVreg(s[3]->InputAt(0)));
2257 }
2258
2259
TEST_F(InstructionSelectorTest,Int32DivWithParametersForSUDIV)2260 TEST_F(InstructionSelectorTest, Int32DivWithParametersForSUDIV) {
2261 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2262 MachineType::Int32());
2263 m.Return(m.Int32Div(m.Parameter(0), m.Parameter(1)));
2264 Stream s = m.Build(SUDIV);
2265 ASSERT_EQ(1U, s.size());
2266 EXPECT_EQ(kArmSdiv, s[0]->arch_opcode());
2267 }
2268
2269
TEST_F(InstructionSelectorTest,Int32ModWithParameters)2270 TEST_F(InstructionSelectorTest, Int32ModWithParameters) {
2271 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2272 MachineType::Int32());
2273 m.Return(m.Int32Mod(m.Parameter(0), m.Parameter(1)));
2274 Stream s = m.Build();
2275 ASSERT_EQ(6U, s.size());
2276 EXPECT_EQ(kArmVcvtF64S32, s[0]->arch_opcode());
2277 ASSERT_EQ(1U, s[0]->OutputCount());
2278 EXPECT_EQ(kArmVcvtF64S32, s[1]->arch_opcode());
2279 ASSERT_EQ(1U, s[1]->OutputCount());
2280 EXPECT_EQ(kArmVdivF64, s[2]->arch_opcode());
2281 ASSERT_EQ(2U, s[2]->InputCount());
2282 ASSERT_EQ(1U, s[2]->OutputCount());
2283 EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[2]->InputAt(0)));
2284 EXPECT_EQ(s.ToVreg(s[1]->Output()), s.ToVreg(s[2]->InputAt(1)));
2285 EXPECT_EQ(kArmVcvtS32F64, s[3]->arch_opcode());
2286 ASSERT_EQ(1U, s[3]->InputCount());
2287 EXPECT_EQ(s.ToVreg(s[2]->Output()), s.ToVreg(s[3]->InputAt(0)));
2288 EXPECT_EQ(kArmMul, s[4]->arch_opcode());
2289 ASSERT_EQ(1U, s[4]->OutputCount());
2290 ASSERT_EQ(2U, s[4]->InputCount());
2291 EXPECT_EQ(s.ToVreg(s[3]->Output()), s.ToVreg(s[4]->InputAt(0)));
2292 EXPECT_EQ(s.ToVreg(s[1]->InputAt(0)), s.ToVreg(s[4]->InputAt(1)));
2293 EXPECT_EQ(kArmSub, s[5]->arch_opcode());
2294 ASSERT_EQ(1U, s[5]->OutputCount());
2295 ASSERT_EQ(2U, s[5]->InputCount());
2296 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[5]->InputAt(0)));
2297 EXPECT_EQ(s.ToVreg(s[4]->Output()), s.ToVreg(s[5]->InputAt(1)));
2298 }
2299
2300
TEST_F(InstructionSelectorTest,Int32ModWithParametersForSUDIV)2301 TEST_F(InstructionSelectorTest, Int32ModWithParametersForSUDIV) {
2302 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2303 MachineType::Int32());
2304 m.Return(m.Int32Mod(m.Parameter(0), m.Parameter(1)));
2305 Stream s = m.Build(SUDIV);
2306 ASSERT_EQ(3U, s.size());
2307 EXPECT_EQ(kArmSdiv, s[0]->arch_opcode());
2308 ASSERT_EQ(1U, s[0]->OutputCount());
2309 ASSERT_EQ(2U, s[0]->InputCount());
2310 EXPECT_EQ(kArmMul, s[1]->arch_opcode());
2311 ASSERT_EQ(1U, s[1]->OutputCount());
2312 ASSERT_EQ(2U, s[1]->InputCount());
2313 EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(0)));
2314 EXPECT_EQ(s.ToVreg(s[0]->InputAt(1)), s.ToVreg(s[1]->InputAt(1)));
2315 EXPECT_EQ(kArmSub, s[2]->arch_opcode());
2316 ASSERT_EQ(1U, s[2]->OutputCount());
2317 ASSERT_EQ(2U, s[2]->InputCount());
2318 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[2]->InputAt(0)));
2319 EXPECT_EQ(s.ToVreg(s[1]->Output()), s.ToVreg(s[2]->InputAt(1)));
2320 }
2321
2322
TEST_F(InstructionSelectorTest,Int32ModWithParametersForSUDIVAndMLS)2323 TEST_F(InstructionSelectorTest, Int32ModWithParametersForSUDIVAndMLS) {
2324 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2325 MachineType::Int32());
2326 m.Return(m.Int32Mod(m.Parameter(0), m.Parameter(1)));
2327 Stream s = m.Build(MLS, SUDIV);
2328 ASSERT_EQ(2U, s.size());
2329 EXPECT_EQ(kArmSdiv, s[0]->arch_opcode());
2330 ASSERT_EQ(1U, s[0]->OutputCount());
2331 ASSERT_EQ(2U, s[0]->InputCount());
2332 EXPECT_EQ(kArmMls, s[1]->arch_opcode());
2333 ASSERT_EQ(1U, s[1]->OutputCount());
2334 ASSERT_EQ(3U, s[1]->InputCount());
2335 EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(0)));
2336 EXPECT_EQ(s.ToVreg(s[0]->InputAt(1)), s.ToVreg(s[1]->InputAt(1)));
2337 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[1]->InputAt(2)));
2338 }
2339
2340
TEST_F(InstructionSelectorTest,Int32MulWithParameters)2341 TEST_F(InstructionSelectorTest, Int32MulWithParameters) {
2342 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2343 MachineType::Int32());
2344 m.Return(m.Int32Mul(m.Parameter(0), m.Parameter(1)));
2345 Stream s = m.Build();
2346 ASSERT_EQ(1U, s.size());
2347 EXPECT_EQ(kArmMul, s[0]->arch_opcode());
2348 EXPECT_EQ(2U, s[0]->InputCount());
2349 EXPECT_EQ(1U, s[0]->OutputCount());
2350 }
2351
2352
TEST_F(InstructionSelectorTest,Int32MulWithImmediate)2353 TEST_F(InstructionSelectorTest, Int32MulWithImmediate) {
2354 // x * (2^k + 1) -> x + (x >> k)
2355 TRACED_FORRANGE(int32_t, k, 1, 30) {
2356 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2357 m.Return(m.Int32Mul(m.Parameter(0), m.Int32Constant((1 << k) + 1)));
2358 Stream s = m.Build();
2359 ASSERT_EQ(1U, s.size());
2360 EXPECT_EQ(kArmAdd, s[0]->arch_opcode());
2361 EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
2362 ASSERT_EQ(3U, s[0]->InputCount());
2363 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
2364 EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2)));
2365 EXPECT_EQ(1U, s[0]->OutputCount());
2366 }
2367 // x * (2^k - 1) -> -x + (x >> k)
2368 TRACED_FORRANGE(int32_t, k, 3, 30) {
2369 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2370 m.Return(m.Int32Mul(m.Parameter(0), m.Int32Constant((1 << k) - 1)));
2371 Stream s = m.Build();
2372 ASSERT_EQ(1U, s.size());
2373 EXPECT_EQ(kArmRsb, s[0]->arch_opcode());
2374 EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
2375 ASSERT_EQ(3U, s[0]->InputCount());
2376 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
2377 EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2)));
2378 EXPECT_EQ(1U, s[0]->OutputCount());
2379 }
2380 // (2^k + 1) * x -> x + (x >> k)
2381 TRACED_FORRANGE(int32_t, k, 1, 30) {
2382 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2383 m.Return(m.Int32Mul(m.Int32Constant((1 << k) + 1), m.Parameter(0)));
2384 Stream s = m.Build();
2385 ASSERT_EQ(1U, s.size());
2386 EXPECT_EQ(kArmAdd, s[0]->arch_opcode());
2387 EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
2388 ASSERT_EQ(3U, s[0]->InputCount());
2389 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
2390 EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2)));
2391 EXPECT_EQ(1U, s[0]->OutputCount());
2392 }
2393 // x * (2^k - 1) -> -x + (x >> k)
2394 TRACED_FORRANGE(int32_t, k, 3, 30) {
2395 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2396 m.Return(m.Int32Mul(m.Int32Constant((1 << k) - 1), m.Parameter(0)));
2397 Stream s = m.Build();
2398 ASSERT_EQ(1U, s.size());
2399 EXPECT_EQ(kArmRsb, s[0]->arch_opcode());
2400 EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
2401 ASSERT_EQ(3U, s[0]->InputCount());
2402 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
2403 EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2)));
2404 EXPECT_EQ(1U, s[0]->OutputCount());
2405 }
2406 }
2407
2408
TEST_F(InstructionSelectorTest,Int32MulHighWithParameters)2409 TEST_F(InstructionSelectorTest, Int32MulHighWithParameters) {
2410 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2411 MachineType::Int32());
2412 Node* const p0 = m.Parameter(0);
2413 Node* const p1 = m.Parameter(1);
2414 Node* const n = m.Int32MulHigh(p0, p1);
2415 m.Return(n);
2416 Stream s = m.Build();
2417 ASSERT_EQ(1U, s.size());
2418 EXPECT_EQ(kArmSmmul, s[0]->arch_opcode());
2419 ASSERT_EQ(2U, s[0]->InputCount());
2420 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
2421 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
2422 ASSERT_EQ(1U, s[0]->OutputCount());
2423 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
2424 }
2425
2426
TEST_F(InstructionSelectorTest,Uint32MulHighWithParameters)2427 TEST_F(InstructionSelectorTest, Uint32MulHighWithParameters) {
2428 StreamBuilder m(this, MachineType::Uint32(), MachineType::Uint32(),
2429 MachineType::Uint32());
2430 Node* const p0 = m.Parameter(0);
2431 Node* const p1 = m.Parameter(1);
2432 Node* const n = m.Uint32MulHigh(p0, p1);
2433 m.Return(n);
2434 Stream s = m.Build();
2435 ASSERT_EQ(1U, s.size());
2436 EXPECT_EQ(kArmUmull, s[0]->arch_opcode());
2437 ASSERT_EQ(2U, s[0]->InputCount());
2438 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
2439 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
2440 ASSERT_EQ(2U, s[0]->OutputCount());
2441 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->OutputAt(1)));
2442 }
2443
2444
TEST_F(InstructionSelectorTest,Uint32DivWithParameters)2445 TEST_F(InstructionSelectorTest, Uint32DivWithParameters) {
2446 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2447 MachineType::Int32());
2448 m.Return(m.Uint32Div(m.Parameter(0), m.Parameter(1)));
2449 Stream s = m.Build();
2450 ASSERT_EQ(4U, s.size());
2451 EXPECT_EQ(kArmVcvtF64U32, s[0]->arch_opcode());
2452 ASSERT_EQ(1U, s[0]->OutputCount());
2453 EXPECT_EQ(kArmVcvtF64U32, s[1]->arch_opcode());
2454 ASSERT_EQ(1U, s[1]->OutputCount());
2455 EXPECT_EQ(kArmVdivF64, s[2]->arch_opcode());
2456 ASSERT_EQ(2U, s[2]->InputCount());
2457 ASSERT_EQ(1U, s[2]->OutputCount());
2458 EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[2]->InputAt(0)));
2459 EXPECT_EQ(s.ToVreg(s[1]->Output()), s.ToVreg(s[2]->InputAt(1)));
2460 EXPECT_EQ(kArmVcvtU32F64, s[3]->arch_opcode());
2461 ASSERT_EQ(1U, s[3]->InputCount());
2462 EXPECT_EQ(s.ToVreg(s[2]->Output()), s.ToVreg(s[3]->InputAt(0)));
2463 }
2464
2465
TEST_F(InstructionSelectorTest,Uint32DivWithParametersForSUDIV)2466 TEST_F(InstructionSelectorTest, Uint32DivWithParametersForSUDIV) {
2467 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2468 MachineType::Int32());
2469 m.Return(m.Uint32Div(m.Parameter(0), m.Parameter(1)));
2470 Stream s = m.Build(SUDIV);
2471 ASSERT_EQ(1U, s.size());
2472 EXPECT_EQ(kArmUdiv, s[0]->arch_opcode());
2473 }
2474
2475
TEST_F(InstructionSelectorTest,Uint32ModWithParameters)2476 TEST_F(InstructionSelectorTest, Uint32ModWithParameters) {
2477 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2478 MachineType::Int32());
2479 m.Return(m.Uint32Mod(m.Parameter(0), m.Parameter(1)));
2480 Stream s = m.Build();
2481 ASSERT_EQ(6U, s.size());
2482 EXPECT_EQ(kArmVcvtF64U32, s[0]->arch_opcode());
2483 ASSERT_EQ(1U, s[0]->OutputCount());
2484 EXPECT_EQ(kArmVcvtF64U32, s[1]->arch_opcode());
2485 ASSERT_EQ(1U, s[1]->OutputCount());
2486 EXPECT_EQ(kArmVdivF64, s[2]->arch_opcode());
2487 ASSERT_EQ(2U, s[2]->InputCount());
2488 ASSERT_EQ(1U, s[2]->OutputCount());
2489 EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[2]->InputAt(0)));
2490 EXPECT_EQ(s.ToVreg(s[1]->Output()), s.ToVreg(s[2]->InputAt(1)));
2491 EXPECT_EQ(kArmVcvtU32F64, s[3]->arch_opcode());
2492 ASSERT_EQ(1U, s[3]->InputCount());
2493 EXPECT_EQ(s.ToVreg(s[2]->Output()), s.ToVreg(s[3]->InputAt(0)));
2494 EXPECT_EQ(kArmMul, s[4]->arch_opcode());
2495 ASSERT_EQ(1U, s[4]->OutputCount());
2496 ASSERT_EQ(2U, s[4]->InputCount());
2497 EXPECT_EQ(s.ToVreg(s[3]->Output()), s.ToVreg(s[4]->InputAt(0)));
2498 EXPECT_EQ(s.ToVreg(s[1]->InputAt(0)), s.ToVreg(s[4]->InputAt(1)));
2499 EXPECT_EQ(kArmSub, s[5]->arch_opcode());
2500 ASSERT_EQ(1U, s[5]->OutputCount());
2501 ASSERT_EQ(2U, s[5]->InputCount());
2502 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[5]->InputAt(0)));
2503 EXPECT_EQ(s.ToVreg(s[4]->Output()), s.ToVreg(s[5]->InputAt(1)));
2504 }
2505
2506
TEST_F(InstructionSelectorTest,Uint32ModWithParametersForSUDIV)2507 TEST_F(InstructionSelectorTest, Uint32ModWithParametersForSUDIV) {
2508 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2509 MachineType::Int32());
2510 m.Return(m.Uint32Mod(m.Parameter(0), m.Parameter(1)));
2511 Stream s = m.Build(SUDIV);
2512 ASSERT_EQ(3U, s.size());
2513 EXPECT_EQ(kArmUdiv, s[0]->arch_opcode());
2514 ASSERT_EQ(1U, s[0]->OutputCount());
2515 ASSERT_EQ(2U, s[0]->InputCount());
2516 EXPECT_EQ(kArmMul, s[1]->arch_opcode());
2517 ASSERT_EQ(1U, s[1]->OutputCount());
2518 ASSERT_EQ(2U, s[1]->InputCount());
2519 EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(0)));
2520 EXPECT_EQ(s.ToVreg(s[0]->InputAt(1)), s.ToVreg(s[1]->InputAt(1)));
2521 EXPECT_EQ(kArmSub, s[2]->arch_opcode());
2522 ASSERT_EQ(1U, s[2]->OutputCount());
2523 ASSERT_EQ(2U, s[2]->InputCount());
2524 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[2]->InputAt(0)));
2525 EXPECT_EQ(s.ToVreg(s[1]->Output()), s.ToVreg(s[2]->InputAt(1)));
2526 }
2527
2528
TEST_F(InstructionSelectorTest,Uint32ModWithParametersForSUDIVAndMLS)2529 TEST_F(InstructionSelectorTest, Uint32ModWithParametersForSUDIVAndMLS) {
2530 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2531 MachineType::Int32());
2532 m.Return(m.Uint32Mod(m.Parameter(0), m.Parameter(1)));
2533 Stream s = m.Build(MLS, SUDIV);
2534 ASSERT_EQ(2U, s.size());
2535 EXPECT_EQ(kArmUdiv, s[0]->arch_opcode());
2536 ASSERT_EQ(1U, s[0]->OutputCount());
2537 ASSERT_EQ(2U, s[0]->InputCount());
2538 EXPECT_EQ(kArmMls, s[1]->arch_opcode());
2539 ASSERT_EQ(1U, s[1]->OutputCount());
2540 ASSERT_EQ(3U, s[1]->InputCount());
2541 EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(0)));
2542 EXPECT_EQ(s.ToVreg(s[0]->InputAt(1)), s.ToVreg(s[1]->InputAt(1)));
2543 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[1]->InputAt(2)));
2544 }
2545
2546
TEST_F(InstructionSelectorTest,Word32AndWithUbfxImmediateForARMv7)2547 TEST_F(InstructionSelectorTest, Word32AndWithUbfxImmediateForARMv7) {
2548 TRACED_FORRANGE(int32_t, width, 1, 32) {
2549 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2550 m.Return(m.Word32And(m.Parameter(0),
2551 m.Int32Constant(0xffffffffu >> (32 - width))));
2552 Stream s = m.Build(ARMv7);
2553 ASSERT_EQ(1U, s.size());
2554 EXPECT_EQ(kArmUbfx, s[0]->arch_opcode());
2555 ASSERT_EQ(3U, s[0]->InputCount());
2556 EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1)));
2557 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
2558 }
2559 TRACED_FORRANGE(int32_t, width, 1, 32) {
2560 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2561 m.Return(m.Word32And(m.Int32Constant(0xffffffffu >> (32 - width)),
2562 m.Parameter(0)));
2563 Stream s = m.Build(ARMv7);
2564 ASSERT_EQ(1U, s.size());
2565 EXPECT_EQ(kArmUbfx, s[0]->arch_opcode());
2566 ASSERT_EQ(3U, s[0]->InputCount());
2567 EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1)));
2568 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
2569 }
2570 }
2571
2572
TEST_F(InstructionSelectorTest,Word32AndWithBfcImmediateForARMv7)2573 TEST_F(InstructionSelectorTest, Word32AndWithBfcImmediateForARMv7) {
2574 TRACED_FORRANGE(int32_t, lsb, 0, 31) {
2575 TRACED_FORRANGE(int32_t, width, 9, (32 - lsb) - 1) {
2576 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2577 m.Return(m.Word32And(
2578 m.Parameter(0),
2579 m.Int32Constant(~((0xffffffffu >> (32 - width)) << lsb))));
2580 Stream s = m.Build(ARMv7);
2581 ASSERT_EQ(1U, s.size());
2582 EXPECT_EQ(kArmBfc, s[0]->arch_opcode());
2583 ASSERT_EQ(1U, s[0]->OutputCount());
2584 EXPECT_TRUE(
2585 UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy());
2586 ASSERT_EQ(3U, s[0]->InputCount());
2587 EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
2588 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
2589 }
2590 }
2591 TRACED_FORRANGE(int32_t, lsb, 0, 31) {
2592 TRACED_FORRANGE(int32_t, width, 9, (32 - lsb) - 1) {
2593 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2594 m.Return(
2595 m.Word32And(m.Int32Constant(~((0xffffffffu >> (32 - width)) << lsb)),
2596 m.Parameter(0)));
2597 Stream s = m.Build(ARMv7);
2598 ASSERT_EQ(1U, s.size());
2599 EXPECT_EQ(kArmBfc, s[0]->arch_opcode());
2600 ASSERT_EQ(1U, s[0]->OutputCount());
2601 EXPECT_TRUE(
2602 UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy());
2603 ASSERT_EQ(3U, s[0]->InputCount());
2604 EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
2605 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
2606 }
2607 }
2608 }
2609
2610
TEST_F(InstructionSelectorTest,Word32AndWith0xffff)2611 TEST_F(InstructionSelectorTest, Word32AndWith0xffff) {
2612 {
2613 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2614 Node* const p0 = m.Parameter(0);
2615 Node* const r = m.Word32And(p0, m.Int32Constant(0xffff));
2616 m.Return(r);
2617 Stream s = m.Build();
2618 ASSERT_EQ(1U, s.size());
2619 EXPECT_EQ(kArmUxth, s[0]->arch_opcode());
2620 ASSERT_EQ(2U, s[0]->InputCount());
2621 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
2622 EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1)));
2623 ASSERT_EQ(1U, s[0]->OutputCount());
2624 EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
2625 }
2626 {
2627 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2628 Node* const p0 = m.Parameter(0);
2629 Node* const r = m.Word32And(m.Int32Constant(0xffff), p0);
2630 m.Return(r);
2631 Stream s = m.Build();
2632 ASSERT_EQ(1U, s.size());
2633 EXPECT_EQ(kArmUxth, s[0]->arch_opcode());
2634 ASSERT_EQ(2U, s[0]->InputCount());
2635 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
2636 EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1)));
2637 ASSERT_EQ(1U, s[0]->OutputCount());
2638 EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
2639 }
2640 }
2641
2642
TEST_F(InstructionSelectorTest,Word32SarWithWord32Shl)2643 TEST_F(InstructionSelectorTest, Word32SarWithWord32Shl) {
2644 {
2645 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2646 Node* const p0 = m.Parameter(0);
2647 Node* const r =
2648 m.Word32Sar(m.Word32Shl(p0, m.Int32Constant(24)), m.Int32Constant(24));
2649 m.Return(r);
2650 Stream s = m.Build();
2651 ASSERT_EQ(1U, s.size());
2652 EXPECT_EQ(kArmSxtb, s[0]->arch_opcode());
2653 ASSERT_EQ(2U, s[0]->InputCount());
2654 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
2655 EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1)));
2656 ASSERT_EQ(1U, s[0]->OutputCount());
2657 EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
2658 }
2659 {
2660 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2661 Node* const p0 = m.Parameter(0);
2662 Node* const r =
2663 m.Word32Sar(m.Word32Shl(p0, m.Int32Constant(16)), m.Int32Constant(16));
2664 m.Return(r);
2665 Stream s = m.Build();
2666 ASSERT_EQ(1U, s.size());
2667 EXPECT_EQ(kArmSxth, s[0]->arch_opcode());
2668 ASSERT_EQ(2U, s[0]->InputCount());
2669 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
2670 EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1)));
2671 ASSERT_EQ(1U, s[0]->OutputCount());
2672 EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
2673 }
2674 }
2675
2676
TEST_F(InstructionSelectorTest,Word32ShrWithWord32AndWithImmediateForARMv7)2677 TEST_F(InstructionSelectorTest, Word32ShrWithWord32AndWithImmediateForARMv7) {
2678 TRACED_FORRANGE(int32_t, lsb, 0, 31) {
2679 TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) {
2680 uint32_t max = 1 << lsb;
2681 if (max > static_cast<uint32_t>(kMaxInt)) max -= 1;
2682 uint32_t jnk = rng()->NextInt(max);
2683 uint32_t msk = ((0xffffffffu >> (32 - width)) << lsb) | jnk;
2684 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2685 m.Return(m.Word32Shr(m.Word32And(m.Parameter(0), m.Int32Constant(msk)),
2686 m.Int32Constant(lsb)));
2687 Stream s = m.Build(ARMv7);
2688 ASSERT_EQ(1U, s.size());
2689 EXPECT_EQ(kArmUbfx, s[0]->arch_opcode());
2690 ASSERT_EQ(3U, s[0]->InputCount());
2691 EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
2692 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
2693 }
2694 }
2695 TRACED_FORRANGE(int32_t, lsb, 0, 31) {
2696 TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) {
2697 uint32_t max = 1 << lsb;
2698 if (max > static_cast<uint32_t>(kMaxInt)) max -= 1;
2699 uint32_t jnk = rng()->NextInt(max);
2700 uint32_t msk = ((0xffffffffu >> (32 - width)) << lsb) | jnk;
2701 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2702 m.Return(m.Word32Shr(m.Word32And(m.Int32Constant(msk), m.Parameter(0)),
2703 m.Int32Constant(lsb)));
2704 Stream s = m.Build(ARMv7);
2705 ASSERT_EQ(1U, s.size());
2706 EXPECT_EQ(kArmUbfx, s[0]->arch_opcode());
2707 ASSERT_EQ(3U, s[0]->InputCount());
2708 EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
2709 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
2710 }
2711 }
2712 }
2713
2714
TEST_F(InstructionSelectorTest,Word32AndWithWord32Not)2715 TEST_F(InstructionSelectorTest, Word32AndWithWord32Not) {
2716 {
2717 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2718 MachineType::Int32());
2719 m.Return(m.Word32And(m.Parameter(0), m.Word32Not(m.Parameter(1))));
2720 Stream s = m.Build();
2721 ASSERT_EQ(1U, s.size());
2722 EXPECT_EQ(kArmBic, s[0]->arch_opcode());
2723 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
2724 EXPECT_EQ(2U, s[0]->InputCount());
2725 EXPECT_EQ(1U, s[0]->OutputCount());
2726 }
2727 {
2728 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2729 MachineType::Int32());
2730 m.Return(m.Word32And(m.Word32Not(m.Parameter(0)), m.Parameter(1)));
2731 Stream s = m.Build();
2732 ASSERT_EQ(1U, s.size());
2733 EXPECT_EQ(kArmBic, s[0]->arch_opcode());
2734 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
2735 EXPECT_EQ(2U, s[0]->InputCount());
2736 EXPECT_EQ(1U, s[0]->OutputCount());
2737 }
2738 }
2739
2740
TEST_F(InstructionSelectorTest,Word32EqualWithParameters)2741 TEST_F(InstructionSelectorTest, Word32EqualWithParameters) {
2742 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2743 MachineType::Int32());
2744 m.Return(m.Word32Equal(m.Parameter(0), m.Parameter(1)));
2745 Stream s = m.Build();
2746 ASSERT_EQ(1U, s.size());
2747 EXPECT_EQ(kArmCmp, s[0]->arch_opcode());
2748 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
2749 EXPECT_EQ(2U, s[0]->InputCount());
2750 EXPECT_EQ(1U, s[0]->OutputCount());
2751 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
2752 EXPECT_EQ(kEqual, s[0]->flags_condition());
2753 }
2754
2755
TEST_F(InstructionSelectorTest,Word32EqualWithImmediate)2756 TEST_F(InstructionSelectorTest, Word32EqualWithImmediate) {
2757 TRACED_FOREACH(int32_t, imm, kImmediates) {
2758 if (imm == 0) continue;
2759 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2760 m.Return(m.Word32Equal(m.Parameter(0), m.Int32Constant(imm)));
2761 Stream s = m.Build();
2762 ASSERT_EQ(1U, s.size());
2763 EXPECT_EQ(kArmCmp, s[0]->arch_opcode());
2764 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode());
2765 ASSERT_EQ(2U, s[0]->InputCount());
2766 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
2767 EXPECT_EQ(1U, s[0]->OutputCount());
2768 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
2769 EXPECT_EQ(kEqual, s[0]->flags_condition());
2770 }
2771 TRACED_FOREACH(int32_t, imm, kImmediates) {
2772 if (imm == 0) continue;
2773 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2774 m.Return(m.Word32Equal(m.Int32Constant(imm), m.Parameter(0)));
2775 Stream s = m.Build();
2776 ASSERT_EQ(1U, s.size());
2777 EXPECT_EQ(kArmCmp, s[0]->arch_opcode());
2778 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode());
2779 ASSERT_EQ(2U, s[0]->InputCount());
2780 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
2781 EXPECT_EQ(1U, s[0]->OutputCount());
2782 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
2783 EXPECT_EQ(kEqual, s[0]->flags_condition());
2784 }
2785 }
2786
2787
TEST_F(InstructionSelectorTest,Word32EqualWithZero)2788 TEST_F(InstructionSelectorTest, Word32EqualWithZero) {
2789 {
2790 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2791 m.Return(m.Word32Equal(m.Parameter(0), m.Int32Constant(0)));
2792 Stream s = m.Build();
2793 ASSERT_EQ(1U, s.size());
2794 EXPECT_EQ(kArmTst, s[0]->arch_opcode());
2795 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
2796 ASSERT_EQ(2U, s[0]->InputCount());
2797 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
2798 EXPECT_EQ(1U, s[0]->OutputCount());
2799 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
2800 EXPECT_EQ(kEqual, s[0]->flags_condition());
2801 }
2802 {
2803 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2804 m.Return(m.Word32Equal(m.Int32Constant(0), m.Parameter(0)));
2805 Stream s = m.Build();
2806 ASSERT_EQ(1U, s.size());
2807 EXPECT_EQ(kArmTst, s[0]->arch_opcode());
2808 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
2809 ASSERT_EQ(2U, s[0]->InputCount());
2810 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
2811 EXPECT_EQ(1U, s[0]->OutputCount());
2812 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
2813 EXPECT_EQ(kEqual, s[0]->flags_condition());
2814 }
2815 }
2816
2817
TEST_F(InstructionSelectorTest,Word32NotWithParameter)2818 TEST_F(InstructionSelectorTest, Word32NotWithParameter) {
2819 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2820 m.Return(m.Word32Not(m.Parameter(0)));
2821 Stream s = m.Build();
2822 ASSERT_EQ(1U, s.size());
2823 EXPECT_EQ(kArmMvn, s[0]->arch_opcode());
2824 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
2825 EXPECT_EQ(1U, s[0]->InputCount());
2826 EXPECT_EQ(1U, s[0]->OutputCount());
2827 }
2828
2829
TEST_F(InstructionSelectorTest,Word32AndWithWord32ShrWithImmediateForARMv7)2830 TEST_F(InstructionSelectorTest, Word32AndWithWord32ShrWithImmediateForARMv7) {
2831 TRACED_FORRANGE(int32_t, lsb, 0, 31) {
2832 TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) {
2833 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2834 m.Return(m.Word32And(m.Word32Shr(m.Parameter(0), m.Int32Constant(lsb)),
2835 m.Int32Constant(0xffffffffu >> (32 - width))));
2836 Stream s = m.Build(ARMv7);
2837 ASSERT_EQ(1U, s.size());
2838 EXPECT_EQ(kArmUbfx, s[0]->arch_opcode());
2839 ASSERT_EQ(3U, s[0]->InputCount());
2840 EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
2841 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
2842 }
2843 }
2844 TRACED_FORRANGE(int32_t, lsb, 0, 31) {
2845 TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) {
2846 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2847 m.Return(m.Word32And(m.Int32Constant(0xffffffffu >> (32 - width)),
2848 m.Word32Shr(m.Parameter(0), m.Int32Constant(lsb))));
2849 Stream s = m.Build(ARMv7);
2850 ASSERT_EQ(1U, s.size());
2851 EXPECT_EQ(kArmUbfx, s[0]->arch_opcode());
2852 ASSERT_EQ(3U, s[0]->InputCount());
2853 EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
2854 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
2855 }
2856 }
2857 }
2858
2859
TEST_F(InstructionSelectorTest,Word32Clz)2860 TEST_F(InstructionSelectorTest, Word32Clz) {
2861 StreamBuilder m(this, MachineType::Uint32(), MachineType::Uint32());
2862 Node* const p0 = m.Parameter(0);
2863 Node* const n = m.Word32Clz(p0);
2864 m.Return(n);
2865 Stream s = m.Build();
2866 ASSERT_EQ(1U, s.size());
2867 EXPECT_EQ(kArmClz, s[0]->arch_opcode());
2868 ASSERT_EQ(1U, s[0]->InputCount());
2869 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
2870 ASSERT_EQ(1U, s[0]->OutputCount());
2871 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
2872 }
2873
2874 } // namespace compiler
2875 } // namespace internal
2876 } // namespace v8
2877