blob: b088d8e76ec12afbefbb01cafdf47fc72bbf79a7 [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// Copyright 2014 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005#include <limits>
6
7#include "test/unittests/compiler/instruction-selector-unittest.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008
9namespace v8 {
10namespace internal {
11namespace compiler {
12
13namespace {
14
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015typedef Node* (RawMachineAssembler::*Constructor)(Node*, Node*);
16
17
18// Data processing instructions.
19struct 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
28std::ostream& operator<<(std::ostream& os, const DPI& dpi) {
29 return os << dpi.constructor_name;
30}
31
32
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000033const DPI kDPIs[] = {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000034 {&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
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000041// Floating point arithmetic instructions.
42struct FAI {
43 Constructor constructor;
44 const char* constructor_name;
45 MachineType machine_type;
46 ArchOpcode arch_opcode;
47};
48
49
50std::ostream& operator<<(std::ostream& os, const FAI& fai) {
51 return os << fai.constructor_name;
52}
53
54
55const 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
Ben Murdochb8a8cc12014-11-26 15:28:44 +000073// Data processing instructions with overflow.
74struct ODPI {
75 Constructor constructor;
76 const char* constructor_name;
77 ArchOpcode arch_opcode;
78 ArchOpcode reverse_arch_opcode;
79};
80
81
82std::ostream& operator<<(std::ostream& os, const ODPI& odpi) {
83 return os << odpi.constructor_name;
84}
85
86
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000087const ODPI kODPIs[] = {{&RawMachineAssembler::Int32AddWithOverflow,
88 "Int32AddWithOverflow", kArmAdd, kArmAdd},
89 {&RawMachineAssembler::Int32SubWithOverflow,
90 "Int32SubWithOverflow", kArmSub, kArmRsb}};
Ben Murdochb8a8cc12014-11-26 15:28:44 +000091
92
93// Shifts.
94struct 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
104std::ostream& operator<<(std::ostream& os, const Shift& shift) {
105 return os << shift.constructor_name;
106}
107
108
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000109const 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}};
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000117
118
119// Immediates (random subset).
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000120const int32_t kImmediates[] = {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400121 std::numeric_limits<int32_t>::min(), -2147483617, -2147483606, -2113929216,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000122 -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};
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000137
138} // namespace
139
140
141// -----------------------------------------------------------------------------
142// Data processing instructions.
143
144
145typedef InstructionSelectorTestWithParam<DPI> InstructionSelectorDPITest;
146
147
148TEST_P(InstructionSelectorDPITest, Parameters) {
149 const DPI dpi = GetParam();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000150 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
151 MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000152 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
162TEST_P(InstructionSelectorDPITest, Immediate) {
163 const DPI dpi = GetParam();
164 TRACED_FOREACH(int32_t, imm, kImmediates) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000165 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000166 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) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000176 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000177 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
189TEST_P(InstructionSelectorDPITest, ShiftByParameter) {
190 const DPI dpi = GetParam();
191 TRACED_FOREACH(Shift, shift, kShifts) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000192 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
193 MachineType::Int32(), MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000194 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) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000205 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
206 MachineType::Int32(), MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000207 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
220TEST_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) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000224 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
225 MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000226 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) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000240 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
241 MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000242 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
257TEST_P(InstructionSelectorDPITest, BranchWithParameters) {
258 const DPI dpi = GetParam();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000259 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
260 MachineType::Int32());
261 RawMachineLabel a, b;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000262 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
276TEST_P(InstructionSelectorDPITest, BranchWithImmediate) {
277 const DPI dpi = GetParam();
278 TRACED_FOREACH(int32_t, imm, kImmediates) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000279 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
280 RawMachineLabel a, b;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000281 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) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000295 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
296 RawMachineLabel a, b;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000297 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
313TEST_P(InstructionSelectorDPITest, BranchWithShiftByParameter) {
314 const DPI dpi = GetParam();
315 TRACED_FOREACH(Shift, shift, kShifts) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000316 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
317 MachineType::Int32(), MachineType::Int32());
318 RawMachineLabel a, b;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000319 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) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000335 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
336 MachineType::Int32(), MachineType::Int32());
337 RawMachineLabel a, b;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000338 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
356TEST_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) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000360 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
361 MachineType::Int32());
362 RawMachineLabel a, b;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000363 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) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000383 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
384 MachineType::Int32());
385 RawMachineLabel a, b;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000386 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
407TEST_P(InstructionSelectorDPITest, BranchIfZeroWithParameters) {
408 const DPI dpi = GetParam();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000409 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
410 MachineType::Int32());
411 RawMachineLabel a, b;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000412 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
428TEST_P(InstructionSelectorDPITest, BranchIfNotZeroWithParameters) {
429 const DPI dpi = GetParam();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000430 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
431 MachineType::Int32());
432 RawMachineLabel a, b;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000433 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
450TEST_P(InstructionSelectorDPITest, BranchIfZeroWithImmediate) {
451 const DPI dpi = GetParam();
452 TRACED_FOREACH(int32_t, imm, kImmediates) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000453 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
454 RawMachineLabel a, b;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000455 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) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000471 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
472 RawMachineLabel a, b;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000473 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
491TEST_P(InstructionSelectorDPITest, BranchIfNotZeroWithImmediate) {
492 const DPI dpi = GetParam();
493 TRACED_FOREACH(int32_t, imm, kImmediates) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000494 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
495 RawMachineLabel a, b;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000496 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) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000512 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
513 RawMachineLabel a, b;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000514 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
532INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorDPITest,
533 ::testing::ValuesIn(kDPIs));
534
535
536// -----------------------------------------------------------------------------
537// Data processing instructions with overflow.
538
539
540typedef InstructionSelectorTestWithParam<ODPI> InstructionSelectorODPITest;
541
542
543TEST_P(InstructionSelectorODPITest, OvfWithParameters) {
544 const ODPI odpi = GetParam();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000545 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
546 MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000547 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
560TEST_P(InstructionSelectorODPITest, OvfWithImmediate) {
561 const ODPI odpi = GetParam();
562 TRACED_FOREACH(int32_t, imm, kImmediates) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000563 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000564 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) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000577 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000578 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
593TEST_P(InstructionSelectorODPITest, OvfWithShiftByParameter) {
594 const ODPI odpi = GetParam();
595 TRACED_FOREACH(Shift, shift, kShifts) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000596 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
597 MachineType::Int32(), MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000598 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) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000612 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
613 MachineType::Int32(), MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000614 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
630TEST_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) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000634 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
635 MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000636 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) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000653 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
654 MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000655 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
673TEST_P(InstructionSelectorODPITest, ValWithParameters) {
674 const ODPI odpi = GetParam();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000675 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
676 MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000677 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
689TEST_P(InstructionSelectorODPITest, ValWithImmediate) {
690 const ODPI odpi = GetParam();
691 TRACED_FOREACH(int32_t, imm, kImmediates) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000692 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000693 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) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000705 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000706 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
720TEST_P(InstructionSelectorODPITest, ValWithShiftByParameter) {
721 const ODPI odpi = GetParam();
722 TRACED_FOREACH(Shift, shift, kShifts) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000723 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
724 MachineType::Int32(), MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000725 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) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000738 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
739 MachineType::Int32(), MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000740 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
755TEST_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) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000759 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
760 MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000761 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) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000777 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
778 MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000779 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
796TEST_P(InstructionSelectorODPITest, BothWithParameters) {
797 const ODPI odpi = GetParam();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000798 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
799 MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000800 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
813TEST_P(InstructionSelectorODPITest, BothWithImmediate) {
814 const ODPI odpi = GetParam();
815 TRACED_FOREACH(int32_t, imm, kImmediates) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000816 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000817 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) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000830 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000831 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
846TEST_P(InstructionSelectorODPITest, BothWithShiftByParameter) {
847 const ODPI odpi = GetParam();
848 TRACED_FOREACH(Shift, shift, kShifts) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000849 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
850 MachineType::Int32(), MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000851 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) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000864 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
865 MachineType::Int32(), MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000866 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
881TEST_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) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000885 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
886 MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000887 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) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000904 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
905 MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000906 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
924TEST_P(InstructionSelectorODPITest, BranchWithParameters) {
925 const ODPI odpi = GetParam();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000926 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
927 MachineType::Int32());
928 RawMachineLabel a, b;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000929 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
946TEST_P(InstructionSelectorODPITest, BranchWithImmediate) {
947 const ODPI odpi = GetParam();
948 TRACED_FOREACH(int32_t, imm, kImmediates) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000949 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
950 RawMachineLabel a, b;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000951 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) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000968 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
969 RawMachineLabel a, b;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000970 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
989TEST_P(InstructionSelectorODPITest, BranchIfZeroWithParameters) {
990 const ODPI odpi = GetParam();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000991 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
992 MachineType::Int32());
993 RawMachineLabel a, b;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000994 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
1011TEST_P(InstructionSelectorODPITest, BranchIfNotZeroWithParameters) {
1012 const ODPI odpi = GetParam();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001013 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
1014 MachineType::Int32());
1015 RawMachineLabel a, b;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001016 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
1033INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorODPITest,
1034 ::testing::ValuesIn(kODPIs));
1035
1036
1037// -----------------------------------------------------------------------------
1038// Shifts.
1039
1040
1041typedef InstructionSelectorTestWithParam<Shift> InstructionSelectorShiftTest;
1042
1043
1044TEST_P(InstructionSelectorShiftTest, Parameters) {
1045 const Shift shift = GetParam();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001046 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
1047 MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001048 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
1058TEST_P(InstructionSelectorShiftTest, Immediate) {
1059 const Shift shift = GetParam();
1060 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001061 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001062 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
1074TEST_P(InstructionSelectorShiftTest, Word32EqualWithParameter) {
1075 const Shift shift = GetParam();
1076 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001077 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
1078 MachineType::Int32(), MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001079 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 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001092 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
1093 MachineType::Int32(), MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001094 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
1109TEST_P(InstructionSelectorShiftTest, Word32EqualWithParameterAndImmediate) {
1110 const Shift shift = GetParam();
1111 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001112 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
1113 MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001114 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) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001128 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
1129 MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001130 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
1146TEST_P(InstructionSelectorShiftTest, Word32EqualToZeroWithParameters) {
1147 const Shift shift = GetParam();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001148 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
1149 MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001150 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
1164TEST_P(InstructionSelectorShiftTest, Word32EqualToZeroWithImmediate) {
1165 const Shift shift = GetParam();
1166 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001167 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
1168 MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001169 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
1185TEST_P(InstructionSelectorShiftTest, Word32NotWithParameters) {
1186 const Shift shift = GetParam();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001187 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
1188 MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001189 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
1199TEST_P(InstructionSelectorShiftTest, Word32NotWithImmediate) {
1200 const Shift shift = GetParam();
1201 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001202 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001203 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
1216TEST_P(InstructionSelectorShiftTest, Word32AndWithWord32NotWithParameters) {
1217 const Shift shift = GetParam();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001218 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
1219 MachineType::Int32(), MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001220 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
1231TEST_P(InstructionSelectorShiftTest, Word32AndWithWord32NotWithImmediate) {
1232 const Shift shift = GetParam();
1233 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001234 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
1235 MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001236 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
1250INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorShiftTest,
1251 ::testing::ValuesIn(kShifts));
1252
1253
1254// -----------------------------------------------------------------------------
1255// Memory access instructions.
1256
1257
1258namespace {
1259
1260struct 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
1270std::ostream& operator<<(std::ostream& os, const MemoryAccess& memacc) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001271 return os << memacc.type;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001272}
1273
1274
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001275const MemoryAccess kMemoryAccesses[] = {
1276 {MachineType::Int8(),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001277 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}},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001283 {MachineType::Uint8(),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001284 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}},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001290 {MachineType::Int16(),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001291 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}},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001297 {MachineType::Uint16(),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001298 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}},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001304 {MachineType::Int32(),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001305 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}},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001311 {MachineType::Float32(),
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001312 kArmVldrF32,
1313 kArmVstrF32,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001314 &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}},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001318 {MachineType::Float64(),
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001319 kArmVldrF64,
1320 kArmVstrF64,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001321 &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
1329typedef InstructionSelectorTestWithParam<MemoryAccess>
1330 InstructionSelectorMemoryAccessTest;
1331
1332
1333TEST_P(InstructionSelectorMemoryAccessTest, LoadWithParameters) {
1334 const MemoryAccess memacc = GetParam();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001335 StreamBuilder m(this, memacc.type, MachineType::Pointer(),
1336 MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001337 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
1348TEST_P(InstructionSelectorMemoryAccessTest, LoadWithImmediateIndex) {
1349 const MemoryAccess memacc = GetParam();
1350 TRACED_FOREACH(int32_t, index, memacc.immediates) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001351 StreamBuilder m(this, memacc.type, MachineType::Pointer());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001352 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
1366TEST_P(InstructionSelectorMemoryAccessTest, StoreWithParameters) {
1367 const MemoryAccess memacc = GetParam();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001368 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);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001372 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
1382TEST_P(InstructionSelectorMemoryAccessTest, StoreWithImmediateIndex) {
1383 const MemoryAccess memacc = GetParam();
1384 TRACED_FOREACH(int32_t, index, memacc.immediates) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001385 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);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001389 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
1402INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1403 InstructionSelectorMemoryAccessTest,
1404 ::testing::ValuesIn(kMemoryAccesses));
1405
1406
1407// -----------------------------------------------------------------------------
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001408// Conversions.
1409
1410
1411TEST_F(InstructionSelectorTest, ChangeFloat32ToFloat64WithParameter) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001412 StreamBuilder m(this, MachineType::Float64(), MachineType::Float32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001413 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
1422TEST_F(InstructionSelectorTest, TruncateFloat64ToFloat32WithParameter) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001423 StreamBuilder m(this, MachineType::Float32(), MachineType::Float64());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001424 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
1437namespace {
1438
1439struct Comparison {
1440 Constructor constructor;
1441 const char* constructor_name;
1442 FlagsCondition flags_condition;
1443 FlagsCondition negated_flags_condition;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001444 FlagsCondition commuted_flags_condition;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001445};
1446
1447
1448std::ostream& operator<<(std::ostream& os, const Comparison& cmp) {
1449 return os << cmp.constructor_name;
1450}
1451
1452
1453const Comparison kComparisons[] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001454 {&RawMachineAssembler::Word32Equal, "Word32Equal", kEqual, kNotEqual,
1455 kEqual},
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001456 {&RawMachineAssembler::Int32LessThan, "Int32LessThan", kSignedLessThan,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001457 kSignedGreaterThanOrEqual, kSignedGreaterThan},
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001458 {&RawMachineAssembler::Int32LessThanOrEqual, "Int32LessThanOrEqual",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001459 kSignedLessThanOrEqual, kSignedGreaterThan, kSignedGreaterThanOrEqual},
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001460 {&RawMachineAssembler::Uint32LessThan, "Uint32LessThan", kUnsignedLessThan,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001461 kUnsignedGreaterThanOrEqual, kUnsignedGreaterThan},
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001462 {&RawMachineAssembler::Uint32LessThanOrEqual, "Uint32LessThanOrEqual",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001463 kUnsignedLessThanOrEqual, kUnsignedGreaterThan,
1464 kUnsignedGreaterThanOrEqual}};
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001465
1466} // namespace
1467
1468
1469typedef InstructionSelectorTestWithParam<Comparison>
1470 InstructionSelectorComparisonTest;
1471
1472
1473TEST_P(InstructionSelectorComparisonTest, Parameters) {
1474 const Comparison& cmp = GetParam();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001475 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
1476 MachineType::Int32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001477 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
1495TEST_P(InstructionSelectorComparisonTest, Word32EqualWithZero) {
1496 {
1497 const Comparison& cmp = GetParam();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001498 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
1499 MachineType::Int32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001500 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();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001519 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
1520 MachineType::Int32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001521 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
1541INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1542 InstructionSelectorComparisonTest,
1543 ::testing::ValuesIn(kComparisons));
1544
1545
1546// -----------------------------------------------------------------------------
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001547// Floating point comparisons.
1548
1549
1550namespace {
1551
1552const 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
1563typedef InstructionSelectorTestWithParam<Comparison>
1564 InstructionSelectorF32ComparisonTest;
1565
1566
1567TEST_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
1582TEST_P(InstructionSelectorF32ComparisonTest, NegatedWithParameters) {
1583 const Comparison& cmp = GetParam();
1584 StreamBuilder m(this, MachineType::Int32(), MachineType::Float32(),
1585 MachineType::Float32());
1586 m.Return(
Ben Murdoch097c5b22016-05-18 11:27:45 +01001587 m.Word32BinaryNot((m.*cmp.constructor)(m.Parameter(0), m.Parameter(1))));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001588 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
1598TEST_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
1613TEST_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
1628INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1629 InstructionSelectorF32ComparisonTest,
1630 ::testing::ValuesIn(kF32Comparisons));
1631
1632
1633namespace {
1634
1635const 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
1646typedef InstructionSelectorTestWithParam<Comparison>
1647 InstructionSelectorF64ComparisonTest;
1648
1649
1650TEST_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
1665TEST_P(InstructionSelectorF64ComparisonTest, NegatedWithParameters) {
1666 const Comparison& cmp = GetParam();
1667 StreamBuilder m(this, MachineType::Int32(), MachineType::Float64(),
1668 MachineType::Float64());
1669 m.Return(
Ben Murdoch097c5b22016-05-18 11:27:45 +01001670 m.Word32BinaryNot((m.*cmp.constructor)(m.Parameter(0), m.Parameter(1))));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001671 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
1681TEST_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
1696TEST_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
1711INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1712 InstructionSelectorF64ComparisonTest,
1713 ::testing::ValuesIn(kF64Comparisons));
1714
1715
1716// -----------------------------------------------------------------------------
1717// Floating point arithmetic.
1718
1719
1720typedef InstructionSelectorTestWithParam<FAI> InstructionSelectorFAITest;
1721
1722
1723TEST_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
1743INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorFAITest,
1744 ::testing::ValuesIn(kFAIs));
1745
1746
1747TEST_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
1762TEST_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
1777TEST_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
1823TEST_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
1869TEST_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}
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001882
1883
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001884TEST_F(InstructionSelectorTest, Float64SubWithMinusZero) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001885 StreamBuilder m(this, MachineType::Float64(), MachineType::Float64());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001886 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
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001899TEST_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
1921TEST_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
1943TEST_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
1959TEST_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
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001979TEST_F(InstructionSelectorTest, Int32AddWithInt32Mul) {
1980 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001981 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
1982 MachineType::Int32(), MachineType::Int32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001983 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);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001988 Stream s = m.Build();
1989 ASSERT_EQ(1U, s.size());
1990 EXPECT_EQ(kArmMla, s[0]->arch_opcode());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001991 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()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001997 }
1998 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001999 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2000 MachineType::Int32(), MachineType::Int32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002001 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);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002006 Stream s = m.Build();
2007 ASSERT_EQ(1U, s.size());
2008 EXPECT_EQ(kArmMla, s[0]->arch_opcode());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002009 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()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002015 }
2016}
2017
2018
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002019TEST_F(InstructionSelectorTest, Int32AddWithInt32MulHigh) {
2020 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002021 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2022 MachineType::Int32(), MachineType::Int32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002023 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 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002039 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2040 MachineType::Int32(), MachineType::Int32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002041 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
2059TEST_F(InstructionSelectorTest, Int32AddWithWord32And) {
2060 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002061 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2062 MachineType::Int32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002063 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 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002078 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2079 MachineType::Int32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002080 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 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002095 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2096 MachineType::Int32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002097 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 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002112 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2113 MachineType::Int32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002114 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
2131TEST_F(InstructionSelectorTest, Int32AddWithWord32SarWithWord32Shl) {
2132 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002133 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2134 MachineType::Int32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002135 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 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002152 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2153 MachineType::Int32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002154 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 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002171 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2172 MachineType::Int32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002173 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 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002190 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2191 MachineType::Int32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002192 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
2211TEST_F(InstructionSelectorTest, Int32SubWithInt32Mul) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002212 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2213 MachineType::Int32(), MachineType::Int32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002214 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
2226TEST_F(InstructionSelectorTest, Int32SubWithInt32MulForMLS) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002227 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2228 MachineType::Int32(), MachineType::Int32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002229 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
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002239TEST_F(InstructionSelectorTest, Int32DivWithParameters) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002240 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2241 MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002242 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
2260TEST_F(InstructionSelectorTest, Int32DivWithParametersForSUDIV) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002261 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2262 MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002263 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
2270TEST_F(InstructionSelectorTest, Int32ModWithParameters) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002271 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2272 MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002273 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
2301TEST_F(InstructionSelectorTest, Int32ModWithParametersForSUDIV) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002302 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2303 MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002304 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
2323TEST_F(InstructionSelectorTest, Int32ModWithParametersForSUDIVAndMLS) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002324 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2325 MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002326 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
2341TEST_F(InstructionSelectorTest, Int32MulWithParameters) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002342 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2343 MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002344 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
2353TEST_F(InstructionSelectorTest, Int32MulWithImmediate) {
2354 // x * (2^k + 1) -> x + (x >> k)
2355 TRACED_FORRANGE(int32_t, k, 1, 30) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002356 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002357 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) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002369 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002370 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) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002382 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002383 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) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002395 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002396 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
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002409TEST_F(InstructionSelectorTest, Int32MulHighWithParameters) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002410 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2411 MachineType::Int32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002412 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
2427TEST_F(InstructionSelectorTest, Uint32MulHighWithParameters) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002428 StreamBuilder m(this, MachineType::Uint32(), MachineType::Uint32(),
2429 MachineType::Uint32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002430 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
2445TEST_F(InstructionSelectorTest, Uint32DivWithParameters) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002446 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2447 MachineType::Int32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002448 m.Return(m.Uint32Div(m.Parameter(0), m.Parameter(1)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002449 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
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002466TEST_F(InstructionSelectorTest, Uint32DivWithParametersForSUDIV) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002467 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2468 MachineType::Int32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002469 m.Return(m.Uint32Div(m.Parameter(0), m.Parameter(1)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002470 Stream s = m.Build(SUDIV);
2471 ASSERT_EQ(1U, s.size());
2472 EXPECT_EQ(kArmUdiv, s[0]->arch_opcode());
2473}
2474
2475
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002476TEST_F(InstructionSelectorTest, Uint32ModWithParameters) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002477 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2478 MachineType::Int32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002479 m.Return(m.Uint32Mod(m.Parameter(0), m.Parameter(1)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002480 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
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002507TEST_F(InstructionSelectorTest, Uint32ModWithParametersForSUDIV) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002508 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2509 MachineType::Int32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002510 m.Return(m.Uint32Mod(m.Parameter(0), m.Parameter(1)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002511 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
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002529TEST_F(InstructionSelectorTest, Uint32ModWithParametersForSUDIVAndMLS) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002530 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2531 MachineType::Int32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002532 m.Return(m.Uint32Mod(m.Parameter(0), m.Parameter(1)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002533 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
Ben Murdoch097c5b22016-05-18 11:27:45 +01002547TEST_F(InstructionSelectorTest, Word32ShlWord32SarForSbfx) {
2548 TRACED_FORRANGE(int32_t, shl, 1, 31) {
2549 TRACED_FORRANGE(int32_t, sar, shl, 31) {
2550 if ((shl == sar) && (sar == 16)) continue; // Sxth.
2551 if ((shl == sar) && (sar == 24)) continue; // Sxtb.
2552 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2553 m.Return(m.Word32Sar(m.Word32Shl(m.Parameter(0), m.Int32Constant(shl)),
2554 m.Int32Constant(sar)));
2555 Stream s = m.Build(ARMv7);
2556 ASSERT_EQ(1U, s.size());
2557 EXPECT_EQ(kArmSbfx, s[0]->arch_opcode());
2558 ASSERT_EQ(3U, s[0]->InputCount());
2559 EXPECT_EQ(sar - shl, s.ToInt32(s[0]->InputAt(1)));
2560 EXPECT_EQ(32 - sar, s.ToInt32(s[0]->InputAt(2)));
2561 }
2562 }
2563}
2564
2565
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002566TEST_F(InstructionSelectorTest, Word32AndWithUbfxImmediateForARMv7) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01002567 TRACED_FORRANGE(int32_t, width, 9, 23) {
2568 if (width == 16) continue; // Uxth.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002569 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002570 m.Return(m.Word32And(m.Parameter(0),
2571 m.Int32Constant(0xffffffffu >> (32 - width))));
2572 Stream s = m.Build(ARMv7);
2573 ASSERT_EQ(1U, s.size());
2574 EXPECT_EQ(kArmUbfx, s[0]->arch_opcode());
2575 ASSERT_EQ(3U, s[0]->InputCount());
2576 EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1)));
2577 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
2578 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01002579 TRACED_FORRANGE(int32_t, width, 9, 23) {
2580 if (width == 16) continue; // Uxth.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002581 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002582 m.Return(m.Word32And(m.Int32Constant(0xffffffffu >> (32 - width)),
2583 m.Parameter(0)));
2584 Stream s = m.Build(ARMv7);
2585 ASSERT_EQ(1U, s.size());
2586 EXPECT_EQ(kArmUbfx, s[0]->arch_opcode());
2587 ASSERT_EQ(3U, s[0]->InputCount());
2588 EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1)));
2589 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
2590 }
2591}
2592
2593
2594TEST_F(InstructionSelectorTest, Word32AndWithBfcImmediateForARMv7) {
2595 TRACED_FORRANGE(int32_t, lsb, 0, 31) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01002596 TRACED_FORRANGE(int32_t, width, 9, (24 - lsb) - 1) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002597 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002598 m.Return(m.Word32And(
2599 m.Parameter(0),
2600 m.Int32Constant(~((0xffffffffu >> (32 - width)) << lsb))));
2601 Stream s = m.Build(ARMv7);
2602 ASSERT_EQ(1U, s.size());
2603 EXPECT_EQ(kArmBfc, s[0]->arch_opcode());
2604 ASSERT_EQ(1U, s[0]->OutputCount());
2605 EXPECT_TRUE(
2606 UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy());
2607 ASSERT_EQ(3U, s[0]->InputCount());
2608 EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
2609 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
2610 }
2611 }
2612 TRACED_FORRANGE(int32_t, lsb, 0, 31) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01002613 TRACED_FORRANGE(int32_t, width, 9, (24 - lsb) - 1) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002614 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002615 m.Return(
2616 m.Word32And(m.Int32Constant(~((0xffffffffu >> (32 - width)) << lsb)),
2617 m.Parameter(0)));
2618 Stream s = m.Build(ARMv7);
2619 ASSERT_EQ(1U, s.size());
2620 EXPECT_EQ(kArmBfc, s[0]->arch_opcode());
2621 ASSERT_EQ(1U, s[0]->OutputCount());
2622 EXPECT_TRUE(
2623 UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy());
2624 ASSERT_EQ(3U, s[0]->InputCount());
2625 EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
2626 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
2627 }
2628 }
2629}
2630
2631
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002632TEST_F(InstructionSelectorTest, Word32AndWith0xffff) {
2633 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002634 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002635 Node* const p0 = m.Parameter(0);
2636 Node* const r = m.Word32And(p0, m.Int32Constant(0xffff));
2637 m.Return(r);
2638 Stream s = m.Build();
2639 ASSERT_EQ(1U, s.size());
2640 EXPECT_EQ(kArmUxth, s[0]->arch_opcode());
2641 ASSERT_EQ(2U, s[0]->InputCount());
2642 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
2643 EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1)));
2644 ASSERT_EQ(1U, s[0]->OutputCount());
2645 EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
2646 }
2647 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002648 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002649 Node* const p0 = m.Parameter(0);
2650 Node* const r = m.Word32And(m.Int32Constant(0xffff), p0);
2651 m.Return(r);
2652 Stream s = m.Build();
2653 ASSERT_EQ(1U, s.size());
2654 EXPECT_EQ(kArmUxth, s[0]->arch_opcode());
2655 ASSERT_EQ(2U, s[0]->InputCount());
2656 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
2657 EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1)));
2658 ASSERT_EQ(1U, s[0]->OutputCount());
2659 EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
2660 }
2661}
2662
2663
2664TEST_F(InstructionSelectorTest, Word32SarWithWord32Shl) {
2665 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002666 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002667 Node* const p0 = m.Parameter(0);
2668 Node* const r =
2669 m.Word32Sar(m.Word32Shl(p0, m.Int32Constant(24)), m.Int32Constant(24));
2670 m.Return(r);
2671 Stream s = m.Build();
2672 ASSERT_EQ(1U, s.size());
2673 EXPECT_EQ(kArmSxtb, s[0]->arch_opcode());
2674 ASSERT_EQ(2U, s[0]->InputCount());
2675 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
2676 EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1)));
2677 ASSERT_EQ(1U, s[0]->OutputCount());
2678 EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
2679 }
2680 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002681 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002682 Node* const p0 = m.Parameter(0);
2683 Node* const r =
2684 m.Word32Sar(m.Word32Shl(p0, m.Int32Constant(16)), m.Int32Constant(16));
2685 m.Return(r);
2686 Stream s = m.Build();
2687 ASSERT_EQ(1U, s.size());
2688 EXPECT_EQ(kArmSxth, s[0]->arch_opcode());
2689 ASSERT_EQ(2U, s[0]->InputCount());
2690 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
2691 EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1)));
2692 ASSERT_EQ(1U, s[0]->OutputCount());
2693 EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
2694 }
2695}
2696
2697
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002698TEST_F(InstructionSelectorTest, Word32ShrWithWord32AndWithImmediateForARMv7) {
2699 TRACED_FORRANGE(int32_t, lsb, 0, 31) {
2700 TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) {
2701 uint32_t max = 1 << lsb;
2702 if (max > static_cast<uint32_t>(kMaxInt)) max -= 1;
2703 uint32_t jnk = rng()->NextInt(max);
2704 uint32_t msk = ((0xffffffffu >> (32 - width)) << lsb) | jnk;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002705 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002706 m.Return(m.Word32Shr(m.Word32And(m.Parameter(0), m.Int32Constant(msk)),
2707 m.Int32Constant(lsb)));
2708 Stream s = m.Build(ARMv7);
2709 ASSERT_EQ(1U, s.size());
2710 EXPECT_EQ(kArmUbfx, s[0]->arch_opcode());
2711 ASSERT_EQ(3U, s[0]->InputCount());
2712 EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
2713 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
2714 }
2715 }
2716 TRACED_FORRANGE(int32_t, lsb, 0, 31) {
2717 TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) {
2718 uint32_t max = 1 << lsb;
2719 if (max > static_cast<uint32_t>(kMaxInt)) max -= 1;
2720 uint32_t jnk = rng()->NextInt(max);
2721 uint32_t msk = ((0xffffffffu >> (32 - width)) << lsb) | jnk;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002722 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002723 m.Return(m.Word32Shr(m.Word32And(m.Int32Constant(msk), m.Parameter(0)),
2724 m.Int32Constant(lsb)));
2725 Stream s = m.Build(ARMv7);
2726 ASSERT_EQ(1U, s.size());
2727 EXPECT_EQ(kArmUbfx, s[0]->arch_opcode());
2728 ASSERT_EQ(3U, s[0]->InputCount());
2729 EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
2730 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
2731 }
2732 }
2733}
2734
2735
2736TEST_F(InstructionSelectorTest, Word32AndWithWord32Not) {
2737 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002738 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2739 MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002740 m.Return(m.Word32And(m.Parameter(0), m.Word32Not(m.Parameter(1))));
2741 Stream s = m.Build();
2742 ASSERT_EQ(1U, s.size());
2743 EXPECT_EQ(kArmBic, s[0]->arch_opcode());
2744 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
2745 EXPECT_EQ(2U, s[0]->InputCount());
2746 EXPECT_EQ(1U, s[0]->OutputCount());
2747 }
2748 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002749 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2750 MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002751 m.Return(m.Word32And(m.Word32Not(m.Parameter(0)), m.Parameter(1)));
2752 Stream s = m.Build();
2753 ASSERT_EQ(1U, s.size());
2754 EXPECT_EQ(kArmBic, s[0]->arch_opcode());
2755 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
2756 EXPECT_EQ(2U, s[0]->InputCount());
2757 EXPECT_EQ(1U, s[0]->OutputCount());
2758 }
2759}
2760
2761
2762TEST_F(InstructionSelectorTest, Word32EqualWithParameters) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002763 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2764 MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002765 m.Return(m.Word32Equal(m.Parameter(0), m.Parameter(1)));
2766 Stream s = m.Build();
2767 ASSERT_EQ(1U, s.size());
2768 EXPECT_EQ(kArmCmp, s[0]->arch_opcode());
2769 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
2770 EXPECT_EQ(2U, s[0]->InputCount());
2771 EXPECT_EQ(1U, s[0]->OutputCount());
2772 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
2773 EXPECT_EQ(kEqual, s[0]->flags_condition());
2774}
2775
2776
2777TEST_F(InstructionSelectorTest, Word32EqualWithImmediate) {
2778 TRACED_FOREACH(int32_t, imm, kImmediates) {
2779 if (imm == 0) continue;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002780 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002781 m.Return(m.Word32Equal(m.Parameter(0), m.Int32Constant(imm)));
2782 Stream s = m.Build();
2783 ASSERT_EQ(1U, s.size());
2784 EXPECT_EQ(kArmCmp, s[0]->arch_opcode());
2785 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode());
2786 ASSERT_EQ(2U, s[0]->InputCount());
2787 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
2788 EXPECT_EQ(1U, s[0]->OutputCount());
2789 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
2790 EXPECT_EQ(kEqual, s[0]->flags_condition());
2791 }
2792 TRACED_FOREACH(int32_t, imm, kImmediates) {
2793 if (imm == 0) continue;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002794 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002795 m.Return(m.Word32Equal(m.Int32Constant(imm), m.Parameter(0)));
2796 Stream s = m.Build();
2797 ASSERT_EQ(1U, s.size());
2798 EXPECT_EQ(kArmCmp, s[0]->arch_opcode());
2799 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode());
2800 ASSERT_EQ(2U, s[0]->InputCount());
2801 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
2802 EXPECT_EQ(1U, s[0]->OutputCount());
2803 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
2804 EXPECT_EQ(kEqual, s[0]->flags_condition());
2805 }
2806}
2807
2808
2809TEST_F(InstructionSelectorTest, Word32EqualWithZero) {
2810 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002811 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002812 m.Return(m.Word32Equal(m.Parameter(0), m.Int32Constant(0)));
2813 Stream s = m.Build();
2814 ASSERT_EQ(1U, s.size());
2815 EXPECT_EQ(kArmTst, s[0]->arch_opcode());
2816 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
2817 ASSERT_EQ(2U, s[0]->InputCount());
2818 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
2819 EXPECT_EQ(1U, s[0]->OutputCount());
2820 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
2821 EXPECT_EQ(kEqual, s[0]->flags_condition());
2822 }
2823 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002824 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002825 m.Return(m.Word32Equal(m.Int32Constant(0), m.Parameter(0)));
2826 Stream s = m.Build();
2827 ASSERT_EQ(1U, s.size());
2828 EXPECT_EQ(kArmTst, s[0]->arch_opcode());
2829 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
2830 ASSERT_EQ(2U, s[0]->InputCount());
2831 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
2832 EXPECT_EQ(1U, s[0]->OutputCount());
2833 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
2834 EXPECT_EQ(kEqual, s[0]->flags_condition());
2835 }
2836}
2837
2838
2839TEST_F(InstructionSelectorTest, Word32NotWithParameter) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002840 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002841 m.Return(m.Word32Not(m.Parameter(0)));
2842 Stream s = m.Build();
2843 ASSERT_EQ(1U, s.size());
2844 EXPECT_EQ(kArmMvn, s[0]->arch_opcode());
2845 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
2846 EXPECT_EQ(1U, s[0]->InputCount());
2847 EXPECT_EQ(1U, s[0]->OutputCount());
2848}
2849
2850
2851TEST_F(InstructionSelectorTest, Word32AndWithWord32ShrWithImmediateForARMv7) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01002852 TRACED_FORRANGE(int32_t, lsb, 1, 31) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002853 TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01002854 if (((width == 8) || (width == 16)) &&
2855 ((lsb == 8) || (lsb == 16) || (lsb == 24)))
2856 continue; // Uxtb/h ror.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002857 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002858 m.Return(m.Word32And(m.Word32Shr(m.Parameter(0), m.Int32Constant(lsb)),
2859 m.Int32Constant(0xffffffffu >> (32 - width))));
2860 Stream s = m.Build(ARMv7);
2861 ASSERT_EQ(1U, s.size());
2862 EXPECT_EQ(kArmUbfx, s[0]->arch_opcode());
2863 ASSERT_EQ(3U, s[0]->InputCount());
2864 EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
2865 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
2866 }
2867 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01002868 TRACED_FORRANGE(int32_t, lsb, 1, 31) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002869 TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01002870 if (((width == 8) || (width == 16)) &&
2871 ((lsb == 8) || (lsb == 16) || (lsb == 24)))
2872 continue; // Uxtb/h ror.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002873 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002874 m.Return(m.Word32And(m.Int32Constant(0xffffffffu >> (32 - width)),
2875 m.Word32Shr(m.Parameter(0), m.Int32Constant(lsb))));
2876 Stream s = m.Build(ARMv7);
2877 ASSERT_EQ(1U, s.size());
2878 EXPECT_EQ(kArmUbfx, s[0]->arch_opcode());
2879 ASSERT_EQ(3U, s[0]->InputCount());
2880 EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
2881 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
2882 }
2883 }
2884}
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002885
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002886
Ben Murdoch097c5b22016-05-18 11:27:45 +01002887TEST_F(InstructionSelectorTest, Word32AndWithWord32ShrAnd0xff) {
2888 TRACED_FORRANGE(int32_t, shr, 1, 3) {
2889 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2890 Node* const p0 = m.Parameter(0);
2891 Node* const r = m.Word32And(m.Word32Shr(p0, m.Int32Constant(shr * 8)),
2892 m.Int32Constant(0xff));
2893 m.Return(r);
2894 Stream s = m.Build();
2895 ASSERT_EQ(1U, s.size());
2896 EXPECT_EQ(kArmUxtb, s[0]->arch_opcode());
2897 ASSERT_EQ(2U, s[0]->InputCount());
2898 EXPECT_EQ(shr * 8, s.ToInt32(s[0]->InputAt(1)));
2899 }
2900 TRACED_FORRANGE(int32_t, shr, 1, 3) {
2901 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2902 Node* const p0 = m.Parameter(0);
2903 Node* const r = m.Word32And(m.Int32Constant(0xff),
2904 m.Word32Shr(p0, m.Int32Constant(shr * 8)));
2905 m.Return(r);
2906 Stream s = m.Build();
2907 ASSERT_EQ(1U, s.size());
2908 EXPECT_EQ(kArmUxtb, s[0]->arch_opcode());
2909 ASSERT_EQ(2U, s[0]->InputCount());
2910 EXPECT_EQ(shr * 8, s.ToInt32(s[0]->InputAt(1)));
2911 }
2912}
2913
2914
2915TEST_F(InstructionSelectorTest, Word32AndWithWord32ShrAnd0xffff) {
2916 TRACED_FORRANGE(int32_t, shr, 1, 3) {
2917 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2918 Node* const p0 = m.Parameter(0);
2919 Node* const r = m.Word32And(m.Word32Shr(p0, m.Int32Constant(shr * 8)),
2920 m.Int32Constant(0xffff));
2921 m.Return(r);
2922 Stream s = m.Build();
2923 ASSERT_EQ(1U, s.size());
2924 EXPECT_EQ(kArmUxth, s[0]->arch_opcode());
2925 ASSERT_EQ(2U, s[0]->InputCount());
2926 EXPECT_EQ(shr * 8, s.ToInt32(s[0]->InputAt(1)));
2927 }
2928 TRACED_FORRANGE(int32_t, shr, 1, 3) {
2929 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2930 Node* const p0 = m.Parameter(0);
2931 Node* const r = m.Word32And(m.Int32Constant(0xffff),
2932 m.Word32Shr(p0, m.Int32Constant(shr * 8)));
2933 m.Return(r);
2934 Stream s = m.Build();
2935 ASSERT_EQ(1U, s.size());
2936 EXPECT_EQ(kArmUxth, s[0]->arch_opcode());
2937 ASSERT_EQ(2U, s[0]->InputCount());
2938 EXPECT_EQ(shr * 8, s.ToInt32(s[0]->InputAt(1)));
2939 }
2940}
2941
2942
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002943TEST_F(InstructionSelectorTest, Word32Clz) {
2944 StreamBuilder m(this, MachineType::Uint32(), MachineType::Uint32());
2945 Node* const p0 = m.Parameter(0);
2946 Node* const n = m.Word32Clz(p0);
2947 m.Return(n);
2948 Stream s = m.Build();
2949 ASSERT_EQ(1U, s.size());
2950 EXPECT_EQ(kArmClz, s[0]->arch_opcode());
2951 ASSERT_EQ(1U, s[0]->InputCount());
2952 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
2953 ASSERT_EQ(1U, s[0]->OutputCount());
2954 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
2955}
2956
Ben Murdochc5610432016-08-08 18:44:38 +01002957TEST_F(InstructionSelectorTest, Float32Max) {
2958 StreamBuilder m(this, MachineType::Float32(), MachineType::Float32(),
2959 MachineType::Float32());
2960 Node* const p0 = m.Parameter(0);
2961 Node* const p1 = m.Parameter(1);
2962 Node* const n = m.Float32Max(p0, p1);
2963 m.Return(n);
2964 Stream s = m.Build(ARMv8);
2965 // Float32Max is `(b < a) ? a : b`.
2966 ASSERT_EQ(1U, s.size());
2967 EXPECT_EQ(kArmFloat32Max, s[0]->arch_opcode());
2968 ASSERT_EQ(2U, s[0]->InputCount());
2969 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
2970 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
2971 ASSERT_EQ(1U, s[0]->OutputCount());
2972 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
2973}
2974
2975TEST_F(InstructionSelectorTest, Float32Min) {
2976 StreamBuilder m(this, MachineType::Float32(), MachineType::Float32(),
2977 MachineType::Float32());
2978 Node* const p0 = m.Parameter(0);
2979 Node* const p1 = m.Parameter(1);
2980 Node* const n = m.Float32Min(p0, p1);
2981 m.Return(n);
2982 Stream s = m.Build(ARMv8);
2983 // Float32Min is `(a < b) ? a : b`.
2984 ASSERT_EQ(1U, s.size());
2985 EXPECT_EQ(kArmFloat32Min, s[0]->arch_opcode());
2986 ASSERT_EQ(2U, s[0]->InputCount());
2987 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
2988 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
2989 ASSERT_EQ(1U, s[0]->OutputCount());
2990 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
2991}
2992
2993TEST_F(InstructionSelectorTest, Float64Max) {
2994 StreamBuilder m(this, MachineType::Float64(), MachineType::Float64(),
2995 MachineType::Float64());
2996 Node* const p0 = m.Parameter(0);
2997 Node* const p1 = m.Parameter(1);
2998 Node* const n = m.Float64Max(p0, p1);
2999 m.Return(n);
3000 Stream s = m.Build(ARMv8);
3001 // Float64Max is `(b < a) ? a : b`.
3002 ASSERT_EQ(1U, s.size());
3003 EXPECT_EQ(kArmFloat64Max, s[0]->arch_opcode());
3004 ASSERT_EQ(2U, s[0]->InputCount());
3005 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
3006 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
3007 ASSERT_EQ(1U, s[0]->OutputCount());
3008 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
3009}
3010
3011TEST_F(InstructionSelectorTest, Float64Min) {
3012 StreamBuilder m(this, MachineType::Float64(), MachineType::Float64(),
3013 MachineType::Float64());
3014 Node* const p0 = m.Parameter(0);
3015 Node* const p1 = m.Parameter(1);
3016 Node* const n = m.Float64Min(p0, p1);
3017 m.Return(n);
3018 Stream s = m.Build(ARMv8);
3019 // Float64Min is `(a < b) ? a : b`.
3020 ASSERT_EQ(1U, s.size());
3021 EXPECT_EQ(kArmFloat64Min, s[0]->arch_opcode());
3022 ASSERT_EQ(2U, s[0]->InputCount());
3023 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
3024 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
3025 ASSERT_EQ(1U, s[0]->OutputCount());
3026 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
3027}
3028
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003029} // namespace compiler
3030} // namespace internal
3031} // namespace v8