blob: fa030394d761e6c3c1c2210feddb97855986fdd7 [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());
Ben Murdoch61f157c2016-09-16 13:49:30 +01001395 ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(2)->kind());
1396 EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(2)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001397 EXPECT_EQ(0U, s[0]->OutputCount());
1398 }
1399}
1400
1401
1402INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1403 InstructionSelectorMemoryAccessTest,
1404 ::testing::ValuesIn(kMemoryAccesses));
1405
Ben Murdoch61f157c2016-09-16 13:49:30 +01001406TEST_F(InstructionSelectorMemoryAccessTest, LoadWithShiftedIndex) {
1407 TRACED_FORRANGE(int, immediate_shift, 1, 31) {
1408 StreamBuilder m(this, MachineType::Int32(), MachineType::Pointer(),
1409 MachineType::Int32());
1410 Node* const index =
1411 m.Word32Shl(m.Parameter(1), m.Int32Constant(immediate_shift));
1412 m.Return(m.Load(MachineType::Int32(), m.Parameter(0), index));
1413 Stream s = m.Build();
1414 ASSERT_EQ(1U, s.size());
1415 EXPECT_EQ(kArmLdr, s[0]->arch_opcode());
1416 EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
1417 EXPECT_EQ(3U, s[0]->InputCount());
1418 EXPECT_EQ(1U, s[0]->OutputCount());
1419 }
1420}
1421
1422TEST_F(InstructionSelectorMemoryAccessTest, StoreWithShiftedIndex) {
1423 TRACED_FORRANGE(int, immediate_shift, 1, 31) {
1424 StreamBuilder m(this, MachineType::Int32(), MachineType::Pointer(),
1425 MachineType::Int32(), MachineType::Int32());
1426 Node* const index =
1427 m.Word32Shl(m.Parameter(1), m.Int32Constant(immediate_shift));
1428 m.Store(MachineRepresentation::kWord32, m.Parameter(0), index,
1429 m.Parameter(2), kNoWriteBarrier);
1430 m.Return(m.Int32Constant(0));
1431 Stream s = m.Build();
1432 ASSERT_EQ(1U, s.size());
1433 EXPECT_EQ(kArmStr, s[0]->arch_opcode());
1434 EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
1435 EXPECT_EQ(4U, s[0]->InputCount());
1436 EXPECT_EQ(0U, s[0]->OutputCount());
1437 }
1438}
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001439
1440// -----------------------------------------------------------------------------
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001441// Conversions.
1442
1443
1444TEST_F(InstructionSelectorTest, ChangeFloat32ToFloat64WithParameter) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001445 StreamBuilder m(this, MachineType::Float64(), MachineType::Float32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001446 m.Return(m.ChangeFloat32ToFloat64(m.Parameter(0)));
1447 Stream s = m.Build();
1448 ASSERT_EQ(1U, s.size());
1449 EXPECT_EQ(kArmVcvtF64F32, s[0]->arch_opcode());
1450 EXPECT_EQ(1U, s[0]->InputCount());
1451 EXPECT_EQ(1U, s[0]->OutputCount());
1452}
1453
1454
1455TEST_F(InstructionSelectorTest, TruncateFloat64ToFloat32WithParameter) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001456 StreamBuilder m(this, MachineType::Float32(), MachineType::Float64());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001457 m.Return(m.TruncateFloat64ToFloat32(m.Parameter(0)));
1458 Stream s = m.Build();
1459 ASSERT_EQ(1U, s.size());
1460 EXPECT_EQ(kArmVcvtF32F64, s[0]->arch_opcode());
1461 EXPECT_EQ(1U, s[0]->InputCount());
1462 EXPECT_EQ(1U, s[0]->OutputCount());
1463}
1464
1465
1466// -----------------------------------------------------------------------------
1467// Comparisons.
1468
1469
1470namespace {
1471
1472struct Comparison {
1473 Constructor constructor;
1474 const char* constructor_name;
1475 FlagsCondition flags_condition;
1476 FlagsCondition negated_flags_condition;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001477 FlagsCondition commuted_flags_condition;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001478};
1479
1480
1481std::ostream& operator<<(std::ostream& os, const Comparison& cmp) {
1482 return os << cmp.constructor_name;
1483}
1484
1485
1486const Comparison kComparisons[] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001487 {&RawMachineAssembler::Word32Equal, "Word32Equal", kEqual, kNotEqual,
1488 kEqual},
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001489 {&RawMachineAssembler::Int32LessThan, "Int32LessThan", kSignedLessThan,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001490 kSignedGreaterThanOrEqual, kSignedGreaterThan},
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001491 {&RawMachineAssembler::Int32LessThanOrEqual, "Int32LessThanOrEqual",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001492 kSignedLessThanOrEqual, kSignedGreaterThan, kSignedGreaterThanOrEqual},
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001493 {&RawMachineAssembler::Uint32LessThan, "Uint32LessThan", kUnsignedLessThan,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001494 kUnsignedGreaterThanOrEqual, kUnsignedGreaterThan},
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001495 {&RawMachineAssembler::Uint32LessThanOrEqual, "Uint32LessThanOrEqual",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001496 kUnsignedLessThanOrEqual, kUnsignedGreaterThan,
1497 kUnsignedGreaterThanOrEqual}};
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001498
1499} // namespace
1500
1501
1502typedef InstructionSelectorTestWithParam<Comparison>
1503 InstructionSelectorComparisonTest;
1504
1505
1506TEST_P(InstructionSelectorComparisonTest, Parameters) {
1507 const Comparison& cmp = GetParam();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001508 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
1509 MachineType::Int32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001510 Node* const p0 = m.Parameter(0);
1511 Node* const p1 = m.Parameter(1);
1512 Node* const r = (m.*cmp.constructor)(p0, p1);
1513 m.Return(r);
1514 Stream const s = m.Build();
1515 ASSERT_EQ(1U, s.size());
1516 EXPECT_EQ(kArmCmp, s[0]->arch_opcode());
1517 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
1518 ASSERT_EQ(2U, s[0]->InputCount());
1519 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1520 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
1521 ASSERT_EQ(1U, s[0]->OutputCount());
1522 EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->OutputAt(0)));
1523 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1524 EXPECT_EQ(cmp.flags_condition, s[0]->flags_condition());
1525}
1526
1527
1528TEST_P(InstructionSelectorComparisonTest, Word32EqualWithZero) {
1529 {
1530 const Comparison& cmp = GetParam();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001531 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
1532 MachineType::Int32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001533 Node* const p0 = m.Parameter(0);
1534 Node* const p1 = m.Parameter(1);
1535 Node* const r =
1536 m.Word32Equal((m.*cmp.constructor)(p0, p1), m.Int32Constant(0));
1537 m.Return(r);
1538 Stream const s = m.Build();
1539 ASSERT_EQ(1U, s.size());
1540 EXPECT_EQ(kArmCmp, s[0]->arch_opcode());
1541 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
1542 ASSERT_EQ(2U, s[0]->InputCount());
1543 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1544 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
1545 ASSERT_EQ(1U, s[0]->OutputCount());
1546 EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->OutputAt(0)));
1547 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1548 EXPECT_EQ(cmp.negated_flags_condition, s[0]->flags_condition());
1549 }
1550 {
1551 const Comparison& cmp = GetParam();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001552 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
1553 MachineType::Int32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001554 Node* const p0 = m.Parameter(0);
1555 Node* const p1 = m.Parameter(1);
1556 Node* const r =
1557 m.Word32Equal(m.Int32Constant(0), (m.*cmp.constructor)(p0, p1));
1558 m.Return(r);
1559 Stream const s = m.Build();
1560 ASSERT_EQ(1U, s.size());
1561 EXPECT_EQ(kArmCmp, s[0]->arch_opcode());
1562 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
1563 ASSERT_EQ(2U, s[0]->InputCount());
1564 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1565 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
1566 ASSERT_EQ(1U, s[0]->OutputCount());
1567 EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->OutputAt(0)));
1568 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1569 EXPECT_EQ(cmp.negated_flags_condition, s[0]->flags_condition());
1570 }
1571}
1572
1573
1574INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1575 InstructionSelectorComparisonTest,
1576 ::testing::ValuesIn(kComparisons));
1577
1578
1579// -----------------------------------------------------------------------------
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001580// Floating point comparisons.
1581
1582
1583namespace {
1584
1585const Comparison kF32Comparisons[] = {
1586 {&RawMachineAssembler::Float32Equal, "Float32Equal", kEqual, kNotEqual,
1587 kEqual},
1588 {&RawMachineAssembler::Float32LessThan, "Float32LessThan",
1589 kFloatLessThan, kFloatGreaterThanOrEqualOrUnordered, kFloatGreaterThan},
1590 {&RawMachineAssembler::Float32LessThanOrEqual, "Float32LessThanOrEqual",
1591 kFloatLessThanOrEqual, kFloatGreaterThanOrUnordered,
1592 kFloatGreaterThanOrEqual}};
1593
1594} // namespace
1595
1596typedef InstructionSelectorTestWithParam<Comparison>
1597 InstructionSelectorF32ComparisonTest;
1598
1599
1600TEST_P(InstructionSelectorF32ComparisonTest, WithParameters) {
1601 const Comparison& cmp = GetParam();
1602 StreamBuilder m(this, MachineType::Int32(), MachineType::Float32(),
1603 MachineType::Float32());
1604 m.Return((m.*cmp.constructor)(m.Parameter(0), m.Parameter(1)));
1605 Stream const s = m.Build();
1606 ASSERT_EQ(1U, s.size());
1607 EXPECT_EQ(kArmVcmpF32, s[0]->arch_opcode());
1608 ASSERT_EQ(2U, s[0]->InputCount());
1609 ASSERT_EQ(1U, s[0]->OutputCount());
1610 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1611 EXPECT_EQ(cmp.flags_condition, s[0]->flags_condition());
1612}
1613
1614
1615TEST_P(InstructionSelectorF32ComparisonTest, NegatedWithParameters) {
1616 const Comparison& cmp = GetParam();
1617 StreamBuilder m(this, MachineType::Int32(), MachineType::Float32(),
1618 MachineType::Float32());
1619 m.Return(
Ben Murdoch097c5b22016-05-18 11:27:45 +01001620 m.Word32BinaryNot((m.*cmp.constructor)(m.Parameter(0), m.Parameter(1))));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001621 Stream const s = m.Build();
1622 ASSERT_EQ(1U, s.size());
1623 EXPECT_EQ(kArmVcmpF32, s[0]->arch_opcode());
1624 ASSERT_EQ(2U, s[0]->InputCount());
1625 ASSERT_EQ(1U, s[0]->OutputCount());
1626 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1627 EXPECT_EQ(cmp.negated_flags_condition, s[0]->flags_condition());
1628}
1629
1630
1631TEST_P(InstructionSelectorF32ComparisonTest, WithImmediateZeroOnRight) {
1632 const Comparison& cmp = GetParam();
1633 StreamBuilder m(this, MachineType::Int32(), MachineType::Float32());
1634 m.Return((m.*cmp.constructor)(m.Parameter(0), m.Float32Constant(0.0)));
1635 Stream const s = m.Build();
1636 ASSERT_EQ(1U, s.size());
1637 EXPECT_EQ(kArmVcmpF32, s[0]->arch_opcode());
1638 ASSERT_EQ(2U, s[0]->InputCount());
1639 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
1640 ASSERT_EQ(1U, s[0]->OutputCount());
1641 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1642 EXPECT_EQ(cmp.flags_condition, s[0]->flags_condition());
1643}
1644
1645
1646TEST_P(InstructionSelectorF32ComparisonTest, WithImmediateZeroOnLeft) {
1647 const Comparison& cmp = GetParam();
1648 StreamBuilder m(this, MachineType::Int32(), MachineType::Float32());
1649 m.Return((m.*cmp.constructor)(m.Float32Constant(0.0f), m.Parameter(0)));
1650 Stream const s = m.Build();
1651 ASSERT_EQ(1U, s.size());
1652 EXPECT_EQ(kArmVcmpF32, s[0]->arch_opcode());
1653 ASSERT_EQ(2U, s[0]->InputCount());
1654 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
1655 ASSERT_EQ(1U, s[0]->OutputCount());
1656 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1657 EXPECT_EQ(cmp.commuted_flags_condition, s[0]->flags_condition());
1658}
1659
1660
1661INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1662 InstructionSelectorF32ComparisonTest,
1663 ::testing::ValuesIn(kF32Comparisons));
1664
1665
1666namespace {
1667
1668const Comparison kF64Comparisons[] = {
1669 {&RawMachineAssembler::Float64Equal, "Float64Equal", kEqual, kNotEqual,
1670 kEqual},
1671 {&RawMachineAssembler::Float64LessThan, "Float64LessThan",
1672 kFloatLessThan, kFloatGreaterThanOrEqualOrUnordered, kFloatGreaterThan},
1673 {&RawMachineAssembler::Float64LessThanOrEqual, "Float64LessThanOrEqual",
1674 kFloatLessThanOrEqual, kFloatGreaterThanOrUnordered,
1675 kFloatGreaterThanOrEqual}};
1676
1677} // namespace
1678
1679typedef InstructionSelectorTestWithParam<Comparison>
1680 InstructionSelectorF64ComparisonTest;
1681
1682
1683TEST_P(InstructionSelectorF64ComparisonTest, WithParameters) {
1684 const Comparison& cmp = GetParam();
1685 StreamBuilder m(this, MachineType::Int32(), MachineType::Float64(),
1686 MachineType::Float64());
1687 m.Return((m.*cmp.constructor)(m.Parameter(0), m.Parameter(1)));
1688 Stream const s = m.Build();
1689 ASSERT_EQ(1U, s.size());
1690 EXPECT_EQ(kArmVcmpF64, s[0]->arch_opcode());
1691 ASSERT_EQ(2U, s[0]->InputCount());
1692 ASSERT_EQ(1U, s[0]->OutputCount());
1693 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1694 EXPECT_EQ(cmp.flags_condition, s[0]->flags_condition());
1695}
1696
1697
1698TEST_P(InstructionSelectorF64ComparisonTest, NegatedWithParameters) {
1699 const Comparison& cmp = GetParam();
1700 StreamBuilder m(this, MachineType::Int32(), MachineType::Float64(),
1701 MachineType::Float64());
1702 m.Return(
Ben Murdoch097c5b22016-05-18 11:27:45 +01001703 m.Word32BinaryNot((m.*cmp.constructor)(m.Parameter(0), m.Parameter(1))));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001704 Stream const s = m.Build();
1705 ASSERT_EQ(1U, s.size());
1706 EXPECT_EQ(kArmVcmpF64, s[0]->arch_opcode());
1707 ASSERT_EQ(2U, s[0]->InputCount());
1708 ASSERT_EQ(1U, s[0]->OutputCount());
1709 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1710 EXPECT_EQ(cmp.negated_flags_condition, s[0]->flags_condition());
1711}
1712
1713
1714TEST_P(InstructionSelectorF64ComparisonTest, WithImmediateZeroOnRight) {
1715 const Comparison& cmp = GetParam();
1716 StreamBuilder m(this, MachineType::Int32(), MachineType::Float64());
1717 m.Return((m.*cmp.constructor)(m.Parameter(0), m.Float64Constant(0.0)));
1718 Stream const s = m.Build();
1719 ASSERT_EQ(1U, s.size());
1720 EXPECT_EQ(kArmVcmpF64, s[0]->arch_opcode());
1721 ASSERT_EQ(2U, s[0]->InputCount());
1722 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
1723 ASSERT_EQ(1U, s[0]->OutputCount());
1724 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1725 EXPECT_EQ(cmp.flags_condition, s[0]->flags_condition());
1726}
1727
1728
1729TEST_P(InstructionSelectorF64ComparisonTest, WithImmediateZeroOnLeft) {
1730 const Comparison& cmp = GetParam();
1731 StreamBuilder m(this, MachineType::Int32(), MachineType::Float64());
1732 m.Return((m.*cmp.constructor)(m.Float64Constant(0.0), m.Parameter(0)));
1733 Stream const s = m.Build();
1734 ASSERT_EQ(1U, s.size());
1735 EXPECT_EQ(kArmVcmpF64, s[0]->arch_opcode());
1736 ASSERT_EQ(2U, s[0]->InputCount());
1737 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
1738 ASSERT_EQ(1U, s[0]->OutputCount());
1739 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1740 EXPECT_EQ(cmp.commuted_flags_condition, s[0]->flags_condition());
1741}
1742
1743
1744INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1745 InstructionSelectorF64ComparisonTest,
1746 ::testing::ValuesIn(kF64Comparisons));
1747
1748
1749// -----------------------------------------------------------------------------
1750// Floating point arithmetic.
1751
1752
1753typedef InstructionSelectorTestWithParam<FAI> InstructionSelectorFAITest;
1754
1755
1756TEST_P(InstructionSelectorFAITest, Parameters) {
1757 const FAI& fai = GetParam();
1758 StreamBuilder m(this, fai.machine_type, fai.machine_type, fai.machine_type);
1759 Node* const p0 = m.Parameter(0);
1760 Node* const p1 = m.Parameter(1);
1761 Node* const r = (m.*fai.constructor)(p0, p1);
1762 m.Return(r);
1763 Stream const s = m.Build();
1764 ASSERT_EQ(1U, s.size());
1765 EXPECT_EQ(fai.arch_opcode, s[0]->arch_opcode());
1766 EXPECT_EQ(kMode_None, s[0]->addressing_mode());
1767 ASSERT_EQ(2U, s[0]->InputCount());
1768 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1769 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
1770 ASSERT_EQ(1U, s[0]->OutputCount());
1771 EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->OutputAt(0)));
1772 EXPECT_EQ(kFlags_none, s[0]->flags_mode());
1773}
1774
1775
1776INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorFAITest,
1777 ::testing::ValuesIn(kFAIs));
1778
1779
1780TEST_F(InstructionSelectorTest, Float32Abs) {
1781 StreamBuilder m(this, MachineType::Float32(), MachineType::Float32());
1782 Node* const p0 = m.Parameter(0);
1783 Node* const n = m.Float32Abs(p0);
1784 m.Return(n);
1785 Stream s = m.Build();
1786 ASSERT_EQ(1U, s.size());
1787 EXPECT_EQ(kArmVabsF32, s[0]->arch_opcode());
1788 ASSERT_EQ(1U, s[0]->InputCount());
1789 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1790 ASSERT_EQ(1U, s[0]->OutputCount());
1791 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1792}
1793
1794
1795TEST_F(InstructionSelectorTest, Float64Abs) {
1796 StreamBuilder m(this, MachineType::Float64(), MachineType::Float64());
1797 Node* const p0 = m.Parameter(0);
1798 Node* const n = m.Float64Abs(p0);
1799 m.Return(n);
1800 Stream s = m.Build();
1801 ASSERT_EQ(1U, s.size());
1802 EXPECT_EQ(kArmVabsF64, s[0]->arch_opcode());
1803 ASSERT_EQ(1U, s[0]->InputCount());
1804 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1805 ASSERT_EQ(1U, s[0]->OutputCount());
1806 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1807}
1808
1809
1810TEST_F(InstructionSelectorTest, Float32AddWithFloat32Mul) {
1811 {
1812 StreamBuilder m(this, MachineType::Float32(), MachineType::Float32(),
1813 MachineType::Float32(), MachineType::Float32());
1814 Node* const p0 = m.Parameter(0);
1815 Node* const p1 = m.Parameter(1);
1816 Node* const p2 = m.Parameter(2);
1817 Node* const n = m.Float32Add(m.Float32Mul(p0, p1), p2);
1818 m.Return(n);
1819 Stream s = m.Build();
1820 ASSERT_EQ(1U, s.size());
1821 EXPECT_EQ(kArmVmlaF32, s[0]->arch_opcode());
1822 ASSERT_EQ(3U, s[0]->InputCount());
1823 EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(0)));
1824 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1)));
1825 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(2)));
1826 ASSERT_EQ(1U, s[0]->OutputCount());
1827 EXPECT_TRUE(
1828 UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy());
1829 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1830 EXPECT_EQ(kFlags_none, s[0]->flags_mode());
1831 }
1832 {
1833 StreamBuilder m(this, MachineType::Float32(), MachineType::Float32(),
1834 MachineType::Float32(), MachineType::Float32());
1835 Node* const p0 = m.Parameter(0);
1836 Node* const p1 = m.Parameter(1);
1837 Node* const p2 = m.Parameter(2);
1838 Node* const n = m.Float32Add(p0, m.Float32Mul(p1, p2));
1839 m.Return(n);
1840 Stream s = m.Build();
1841 ASSERT_EQ(1U, s.size());
1842 EXPECT_EQ(kArmVmlaF32, s[0]->arch_opcode());
1843 ASSERT_EQ(3U, s[0]->InputCount());
1844 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1845 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
1846 EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(2)));
1847 ASSERT_EQ(1U, s[0]->OutputCount());
1848 EXPECT_TRUE(
1849 UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy());
1850 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1851 EXPECT_EQ(kFlags_none, s[0]->flags_mode());
1852 }
1853}
1854
1855
1856TEST_F(InstructionSelectorTest, Float64AddWithFloat64Mul) {
1857 {
1858 StreamBuilder m(this, MachineType::Float64(), MachineType::Float64(),
1859 MachineType::Float64(), MachineType::Float64());
1860 Node* const p0 = m.Parameter(0);
1861 Node* const p1 = m.Parameter(1);
1862 Node* const p2 = m.Parameter(2);
1863 Node* const n = m.Float64Add(m.Float64Mul(p0, p1), p2);
1864 m.Return(n);
1865 Stream s = m.Build();
1866 ASSERT_EQ(1U, s.size());
1867 EXPECT_EQ(kArmVmlaF64, s[0]->arch_opcode());
1868 ASSERT_EQ(3U, s[0]->InputCount());
1869 EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(0)));
1870 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1)));
1871 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(2)));
1872 ASSERT_EQ(1U, s[0]->OutputCount());
1873 EXPECT_TRUE(
1874 UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy());
1875 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1876 EXPECT_EQ(kFlags_none, s[0]->flags_mode());
1877 }
1878 {
1879 StreamBuilder m(this, MachineType::Float64(), MachineType::Float64(),
1880 MachineType::Float64(), MachineType::Float64());
1881 Node* const p0 = m.Parameter(0);
1882 Node* const p1 = m.Parameter(1);
1883 Node* const p2 = m.Parameter(2);
1884 Node* const n = m.Float64Add(p0, m.Float64Mul(p1, p2));
1885 m.Return(n);
1886 Stream s = m.Build();
1887 ASSERT_EQ(1U, s.size());
1888 EXPECT_EQ(kArmVmlaF64, s[0]->arch_opcode());
1889 ASSERT_EQ(3U, s[0]->InputCount());
1890 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1891 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
1892 EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(2)));
1893 ASSERT_EQ(1U, s[0]->OutputCount());
1894 EXPECT_TRUE(
1895 UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy());
1896 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1897 EXPECT_EQ(kFlags_none, s[0]->flags_mode());
1898 }
1899}
1900
1901
1902TEST_F(InstructionSelectorTest, Float32SubWithMinusZero) {
1903 StreamBuilder m(this, MachineType::Float32(), MachineType::Float32());
1904 Node* const p0 = m.Parameter(0);
1905 Node* const n = m.Float32Sub(m.Float32Constant(-0.0f), p0);
1906 m.Return(n);
1907 Stream s = m.Build();
1908 ASSERT_EQ(1U, s.size());
1909 EXPECT_EQ(kArmVnegF32, s[0]->arch_opcode());
1910 ASSERT_EQ(1U, s[0]->InputCount());
1911 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1912 ASSERT_EQ(1U, s[0]->OutputCount());
1913 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1914}
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001915
1916
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001917TEST_F(InstructionSelectorTest, Float64SubWithMinusZero) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001918 StreamBuilder m(this, MachineType::Float64(), MachineType::Float64());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001919 Node* const p0 = m.Parameter(0);
1920 Node* const n = m.Float64Sub(m.Float64Constant(-0.0), p0);
1921 m.Return(n);
1922 Stream s = m.Build();
1923 ASSERT_EQ(1U, s.size());
1924 EXPECT_EQ(kArmVnegF64, s[0]->arch_opcode());
1925 ASSERT_EQ(1U, s[0]->InputCount());
1926 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1927 ASSERT_EQ(1U, s[0]->OutputCount());
1928 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1929}
1930
1931
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001932TEST_F(InstructionSelectorTest, Float32SubWithFloat32Mul) {
1933 StreamBuilder m(this, MachineType::Float32(), MachineType::Float32(),
1934 MachineType::Float32(), MachineType::Float32());
1935 Node* const p0 = m.Parameter(0);
1936 Node* const p1 = m.Parameter(1);
1937 Node* const p2 = m.Parameter(2);
1938 Node* const n = m.Float32Sub(p0, m.Float32Mul(p1, p2));
1939 m.Return(n);
1940 Stream s = m.Build();
1941 ASSERT_EQ(1U, s.size());
1942 EXPECT_EQ(kArmVmlsF32, s[0]->arch_opcode());
1943 ASSERT_EQ(3U, s[0]->InputCount());
1944 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1945 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
1946 EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(2)));
1947 ASSERT_EQ(1U, s[0]->OutputCount());
1948 EXPECT_TRUE(UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy());
1949 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1950 EXPECT_EQ(kFlags_none, s[0]->flags_mode());
1951}
1952
1953
1954TEST_F(InstructionSelectorTest, Float64SubWithFloat64Mul) {
1955 StreamBuilder m(this, MachineType::Float64(), MachineType::Float64(),
1956 MachineType::Float64(), MachineType::Float64());
1957 Node* const p0 = m.Parameter(0);
1958 Node* const p1 = m.Parameter(1);
1959 Node* const p2 = m.Parameter(2);
1960 Node* const n = m.Float64Sub(p0, m.Float64Mul(p1, p2));
1961 m.Return(n);
1962 Stream s = m.Build();
1963 ASSERT_EQ(1U, s.size());
1964 EXPECT_EQ(kArmVmlsF64, s[0]->arch_opcode());
1965 ASSERT_EQ(3U, s[0]->InputCount());
1966 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1967 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
1968 EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(2)));
1969 ASSERT_EQ(1U, s[0]->OutputCount());
1970 EXPECT_TRUE(UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy());
1971 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1972 EXPECT_EQ(kFlags_none, s[0]->flags_mode());
1973}
1974
1975
1976TEST_F(InstructionSelectorTest, Float32Sqrt) {
1977 StreamBuilder m(this, MachineType::Float32(), MachineType::Float32());
1978 Node* const p0 = m.Parameter(0);
1979 Node* const n = m.Float32Sqrt(p0);
1980 m.Return(n);
1981 Stream s = m.Build();
1982 ASSERT_EQ(1U, s.size());
1983 EXPECT_EQ(kArmVsqrtF32, s[0]->arch_opcode());
1984 ASSERT_EQ(1U, s[0]->InputCount());
1985 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1986 ASSERT_EQ(1U, s[0]->OutputCount());
1987 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1988 EXPECT_EQ(kFlags_none, s[0]->flags_mode());
1989}
1990
1991
1992TEST_F(InstructionSelectorTest, Float64Sqrt) {
1993 StreamBuilder m(this, MachineType::Float64(), MachineType::Float64());
1994 Node* const p0 = m.Parameter(0);
1995 Node* const n = m.Float64Sqrt(p0);
1996 m.Return(n);
1997 Stream s = m.Build();
1998 ASSERT_EQ(1U, s.size());
1999 EXPECT_EQ(kArmVsqrtF64, s[0]->arch_opcode());
2000 ASSERT_EQ(1U, s[0]->InputCount());
2001 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
2002 ASSERT_EQ(1U, s[0]->OutputCount());
2003 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
2004 EXPECT_EQ(kFlags_none, s[0]->flags_mode());
2005}
2006
2007
2008// -----------------------------------------------------------------------------
2009// Miscellaneous.
2010
2011
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002012TEST_F(InstructionSelectorTest, Int32AddWithInt32Mul) {
2013 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002014 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2015 MachineType::Int32(), MachineType::Int32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002016 Node* const p0 = m.Parameter(0);
2017 Node* const p1 = m.Parameter(1);
2018 Node* const p2 = m.Parameter(2);
2019 Node* const n = m.Int32Add(p0, m.Int32Mul(p1, p2));
2020 m.Return(n);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002021 Stream s = m.Build();
2022 ASSERT_EQ(1U, s.size());
2023 EXPECT_EQ(kArmMla, s[0]->arch_opcode());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002024 ASSERT_EQ(3U, s[0]->InputCount());
2025 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(0)));
2026 EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(1)));
2027 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(2)));
2028 ASSERT_EQ(1U, s[0]->OutputCount());
2029 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002030 }
2031 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002032 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2033 MachineType::Int32(), MachineType::Int32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002034 Node* const p0 = m.Parameter(0);
2035 Node* const p1 = m.Parameter(1);
2036 Node* const p2 = m.Parameter(2);
2037 Node* const n = m.Int32Add(m.Int32Mul(p1, p2), p0);
2038 m.Return(n);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002039 Stream s = m.Build();
2040 ASSERT_EQ(1U, s.size());
2041 EXPECT_EQ(kArmMla, s[0]->arch_opcode());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002042 ASSERT_EQ(3U, s[0]->InputCount());
2043 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(0)));
2044 EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(1)));
2045 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(2)));
2046 ASSERT_EQ(1U, s[0]->OutputCount());
2047 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002048 }
2049}
2050
2051
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002052TEST_F(InstructionSelectorTest, Int32AddWithInt32MulHigh) {
2053 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002054 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2055 MachineType::Int32(), MachineType::Int32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002056 Node* const p0 = m.Parameter(0);
2057 Node* const p1 = m.Parameter(1);
2058 Node* const p2 = m.Parameter(2);
2059 Node* const n = m.Int32Add(p0, m.Int32MulHigh(p1, p2));
2060 m.Return(n);
2061 Stream s = m.Build();
2062 ASSERT_EQ(1U, s.size());
2063 EXPECT_EQ(kArmSmmla, s[0]->arch_opcode());
2064 ASSERT_EQ(3U, s[0]->InputCount());
2065 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(0)));
2066 EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(1)));
2067 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(2)));
2068 ASSERT_EQ(1U, s[0]->OutputCount());
2069 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
2070 }
2071 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002072 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2073 MachineType::Int32(), MachineType::Int32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002074 Node* const p0 = m.Parameter(0);
2075 Node* const p1 = m.Parameter(1);
2076 Node* const p2 = m.Parameter(2);
2077 Node* const n = m.Int32Add(m.Int32MulHigh(p1, p2), p0);
2078 m.Return(n);
2079 Stream s = m.Build();
2080 ASSERT_EQ(1U, s.size());
2081 EXPECT_EQ(kArmSmmla, s[0]->arch_opcode());
2082 ASSERT_EQ(3U, s[0]->InputCount());
2083 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(0)));
2084 EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(1)));
2085 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(2)));
2086 ASSERT_EQ(1U, s[0]->OutputCount());
2087 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
2088 }
2089}
2090
2091
2092TEST_F(InstructionSelectorTest, Int32AddWithWord32And) {
2093 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002094 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2095 MachineType::Int32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002096 Node* const p0 = m.Parameter(0);
2097 Node* const p1 = m.Parameter(1);
2098 Node* const r = m.Int32Add(m.Word32And(p0, m.Int32Constant(0xff)), p1);
2099 m.Return(r);
2100 Stream s = m.Build();
2101 ASSERT_EQ(1U, s.size());
2102 EXPECT_EQ(kArmUxtab, s[0]->arch_opcode());
2103 ASSERT_EQ(3U, s[0]->InputCount());
2104 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(0)));
2105 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1)));
2106 EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(2)));
2107 ASSERT_EQ(1U, s[0]->OutputCount());
2108 EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
2109 }
2110 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002111 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2112 MachineType::Int32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002113 Node* const p0 = m.Parameter(0);
2114 Node* const p1 = m.Parameter(1);
2115 Node* const r = m.Int32Add(p1, m.Word32And(p0, m.Int32Constant(0xff)));
2116 m.Return(r);
2117 Stream s = m.Build();
2118 ASSERT_EQ(1U, s.size());
2119 EXPECT_EQ(kArmUxtab, s[0]->arch_opcode());
2120 ASSERT_EQ(3U, s[0]->InputCount());
2121 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(0)));
2122 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1)));
2123 EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(2)));
2124 ASSERT_EQ(1U, s[0]->OutputCount());
2125 EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
2126 }
2127 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002128 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2129 MachineType::Int32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002130 Node* const p0 = m.Parameter(0);
2131 Node* const p1 = m.Parameter(1);
2132 Node* const r = m.Int32Add(m.Word32And(p0, m.Int32Constant(0xffff)), p1);
2133 m.Return(r);
2134 Stream s = m.Build();
2135 ASSERT_EQ(1U, s.size());
2136 EXPECT_EQ(kArmUxtah, s[0]->arch_opcode());
2137 ASSERT_EQ(3U, s[0]->InputCount());
2138 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(0)));
2139 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1)));
2140 EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(2)));
2141 ASSERT_EQ(1U, s[0]->OutputCount());
2142 EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
2143 }
2144 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002145 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2146 MachineType::Int32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002147 Node* const p0 = m.Parameter(0);
2148 Node* const p1 = m.Parameter(1);
2149 Node* const r = m.Int32Add(p1, m.Word32And(p0, m.Int32Constant(0xffff)));
2150 m.Return(r);
2151 Stream s = m.Build();
2152 ASSERT_EQ(1U, s.size());
2153 EXPECT_EQ(kArmUxtah, s[0]->arch_opcode());
2154 ASSERT_EQ(3U, s[0]->InputCount());
2155 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(0)));
2156 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1)));
2157 EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(2)));
2158 ASSERT_EQ(1U, s[0]->OutputCount());
2159 EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
2160 }
2161}
2162
2163
2164TEST_F(InstructionSelectorTest, Int32AddWithWord32SarWithWord32Shl) {
2165 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002166 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2167 MachineType::Int32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002168 Node* const p0 = m.Parameter(0);
2169 Node* const p1 = m.Parameter(1);
2170 Node* const r = m.Int32Add(
2171 m.Word32Sar(m.Word32Shl(p0, m.Int32Constant(24)), m.Int32Constant(24)),
2172 p1);
2173 m.Return(r);
2174 Stream s = m.Build();
2175 ASSERT_EQ(1U, s.size());
2176 EXPECT_EQ(kArmSxtab, s[0]->arch_opcode());
2177 ASSERT_EQ(3U, s[0]->InputCount());
2178 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(0)));
2179 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1)));
2180 EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(2)));
2181 ASSERT_EQ(1U, s[0]->OutputCount());
2182 EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
2183 }
2184 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002185 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2186 MachineType::Int32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002187 Node* const p0 = m.Parameter(0);
2188 Node* const p1 = m.Parameter(1);
2189 Node* const r = m.Int32Add(
2190 p1,
2191 m.Word32Sar(m.Word32Shl(p0, m.Int32Constant(24)), m.Int32Constant(24)));
2192 m.Return(r);
2193 Stream s = m.Build();
2194 ASSERT_EQ(1U, s.size());
2195 EXPECT_EQ(kArmSxtab, s[0]->arch_opcode());
2196 ASSERT_EQ(3U, s[0]->InputCount());
2197 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(0)));
2198 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1)));
2199 EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(2)));
2200 ASSERT_EQ(1U, s[0]->OutputCount());
2201 EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
2202 }
2203 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002204 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2205 MachineType::Int32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002206 Node* const p0 = m.Parameter(0);
2207 Node* const p1 = m.Parameter(1);
2208 Node* const r = m.Int32Add(
2209 m.Word32Sar(m.Word32Shl(p0, m.Int32Constant(16)), m.Int32Constant(16)),
2210 p1);
2211 m.Return(r);
2212 Stream s = m.Build();
2213 ASSERT_EQ(1U, s.size());
2214 EXPECT_EQ(kArmSxtah, s[0]->arch_opcode());
2215 ASSERT_EQ(3U, s[0]->InputCount());
2216 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(0)));
2217 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1)));
2218 EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(2)));
2219 ASSERT_EQ(1U, s[0]->OutputCount());
2220 EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
2221 }
2222 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002223 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2224 MachineType::Int32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002225 Node* const p0 = m.Parameter(0);
2226 Node* const p1 = m.Parameter(1);
2227 Node* const r = m.Int32Add(
2228 p1,
2229 m.Word32Sar(m.Word32Shl(p0, m.Int32Constant(16)), m.Int32Constant(16)));
2230 m.Return(r);
2231 Stream s = m.Build();
2232 ASSERT_EQ(1U, s.size());
2233 EXPECT_EQ(kArmSxtah, s[0]->arch_opcode());
2234 ASSERT_EQ(3U, s[0]->InputCount());
2235 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(0)));
2236 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1)));
2237 EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(2)));
2238 ASSERT_EQ(1U, s[0]->OutputCount());
2239 EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
2240 }
2241}
2242
2243
2244TEST_F(InstructionSelectorTest, Int32SubWithInt32Mul) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002245 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2246 MachineType::Int32(), MachineType::Int32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002247 m.Return(
2248 m.Int32Sub(m.Parameter(0), m.Int32Mul(m.Parameter(1), m.Parameter(2))));
2249 Stream s = m.Build();
2250 ASSERT_EQ(2U, s.size());
2251 EXPECT_EQ(kArmMul, s[0]->arch_opcode());
2252 ASSERT_EQ(1U, s[0]->OutputCount());
2253 EXPECT_EQ(kArmSub, s[1]->arch_opcode());
2254 ASSERT_EQ(2U, s[1]->InputCount());
2255 EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(1)));
2256}
2257
2258
2259TEST_F(InstructionSelectorTest, Int32SubWithInt32MulForMLS) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002260 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2261 MachineType::Int32(), MachineType::Int32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002262 m.Return(
2263 m.Int32Sub(m.Parameter(0), m.Int32Mul(m.Parameter(1), m.Parameter(2))));
Ben Murdoch61f157c2016-09-16 13:49:30 +01002264 Stream s = m.Build(ARMv7);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002265 ASSERT_EQ(1U, s.size());
2266 EXPECT_EQ(kArmMls, s[0]->arch_opcode());
2267 EXPECT_EQ(1U, s[0]->OutputCount());
2268 EXPECT_EQ(3U, s[0]->InputCount());
2269}
2270
2271
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002272TEST_F(InstructionSelectorTest, Int32DivWithParameters) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002273 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2274 MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002275 m.Return(m.Int32Div(m.Parameter(0), m.Parameter(1)));
2276 Stream s = m.Build();
2277 ASSERT_EQ(4U, s.size());
2278 EXPECT_EQ(kArmVcvtF64S32, s[0]->arch_opcode());
2279 ASSERT_EQ(1U, s[0]->OutputCount());
2280 EXPECT_EQ(kArmVcvtF64S32, s[1]->arch_opcode());
2281 ASSERT_EQ(1U, s[1]->OutputCount());
2282 EXPECT_EQ(kArmVdivF64, s[2]->arch_opcode());
2283 ASSERT_EQ(2U, s[2]->InputCount());
2284 ASSERT_EQ(1U, s[2]->OutputCount());
2285 EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[2]->InputAt(0)));
2286 EXPECT_EQ(s.ToVreg(s[1]->Output()), s.ToVreg(s[2]->InputAt(1)));
2287 EXPECT_EQ(kArmVcvtS32F64, s[3]->arch_opcode());
2288 ASSERT_EQ(1U, s[3]->InputCount());
2289 EXPECT_EQ(s.ToVreg(s[2]->Output()), s.ToVreg(s[3]->InputAt(0)));
2290}
2291
2292
2293TEST_F(InstructionSelectorTest, Int32DivWithParametersForSUDIV) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002294 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2295 MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002296 m.Return(m.Int32Div(m.Parameter(0), m.Parameter(1)));
2297 Stream s = m.Build(SUDIV);
2298 ASSERT_EQ(1U, s.size());
2299 EXPECT_EQ(kArmSdiv, s[0]->arch_opcode());
2300}
2301
2302
2303TEST_F(InstructionSelectorTest, Int32ModWithParameters) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002304 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2305 MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002306 m.Return(m.Int32Mod(m.Parameter(0), m.Parameter(1)));
2307 Stream s = m.Build();
2308 ASSERT_EQ(6U, s.size());
2309 EXPECT_EQ(kArmVcvtF64S32, s[0]->arch_opcode());
2310 ASSERT_EQ(1U, s[0]->OutputCount());
2311 EXPECT_EQ(kArmVcvtF64S32, s[1]->arch_opcode());
2312 ASSERT_EQ(1U, s[1]->OutputCount());
2313 EXPECT_EQ(kArmVdivF64, s[2]->arch_opcode());
2314 ASSERT_EQ(2U, s[2]->InputCount());
2315 ASSERT_EQ(1U, s[2]->OutputCount());
2316 EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[2]->InputAt(0)));
2317 EXPECT_EQ(s.ToVreg(s[1]->Output()), s.ToVreg(s[2]->InputAt(1)));
2318 EXPECT_EQ(kArmVcvtS32F64, s[3]->arch_opcode());
2319 ASSERT_EQ(1U, s[3]->InputCount());
2320 EXPECT_EQ(s.ToVreg(s[2]->Output()), s.ToVreg(s[3]->InputAt(0)));
2321 EXPECT_EQ(kArmMul, s[4]->arch_opcode());
2322 ASSERT_EQ(1U, s[4]->OutputCount());
2323 ASSERT_EQ(2U, s[4]->InputCount());
2324 EXPECT_EQ(s.ToVreg(s[3]->Output()), s.ToVreg(s[4]->InputAt(0)));
2325 EXPECT_EQ(s.ToVreg(s[1]->InputAt(0)), s.ToVreg(s[4]->InputAt(1)));
2326 EXPECT_EQ(kArmSub, s[5]->arch_opcode());
2327 ASSERT_EQ(1U, s[5]->OutputCount());
2328 ASSERT_EQ(2U, s[5]->InputCount());
2329 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[5]->InputAt(0)));
2330 EXPECT_EQ(s.ToVreg(s[4]->Output()), s.ToVreg(s[5]->InputAt(1)));
2331}
2332
2333
2334TEST_F(InstructionSelectorTest, Int32ModWithParametersForSUDIV) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002335 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2336 MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002337 m.Return(m.Int32Mod(m.Parameter(0), m.Parameter(1)));
2338 Stream s = m.Build(SUDIV);
2339 ASSERT_EQ(3U, s.size());
2340 EXPECT_EQ(kArmSdiv, s[0]->arch_opcode());
2341 ASSERT_EQ(1U, s[0]->OutputCount());
2342 ASSERT_EQ(2U, s[0]->InputCount());
2343 EXPECT_EQ(kArmMul, s[1]->arch_opcode());
2344 ASSERT_EQ(1U, s[1]->OutputCount());
2345 ASSERT_EQ(2U, s[1]->InputCount());
2346 EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(0)));
2347 EXPECT_EQ(s.ToVreg(s[0]->InputAt(1)), s.ToVreg(s[1]->InputAt(1)));
2348 EXPECT_EQ(kArmSub, s[2]->arch_opcode());
2349 ASSERT_EQ(1U, s[2]->OutputCount());
2350 ASSERT_EQ(2U, s[2]->InputCount());
2351 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[2]->InputAt(0)));
2352 EXPECT_EQ(s.ToVreg(s[1]->Output()), s.ToVreg(s[2]->InputAt(1)));
2353}
2354
2355
2356TEST_F(InstructionSelectorTest, Int32ModWithParametersForSUDIVAndMLS) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002357 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2358 MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002359 m.Return(m.Int32Mod(m.Parameter(0), m.Parameter(1)));
Ben Murdoch61f157c2016-09-16 13:49:30 +01002360 Stream s = m.Build(ARMv7, SUDIV);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002361 ASSERT_EQ(2U, s.size());
2362 EXPECT_EQ(kArmSdiv, s[0]->arch_opcode());
2363 ASSERT_EQ(1U, s[0]->OutputCount());
2364 ASSERT_EQ(2U, s[0]->InputCount());
2365 EXPECT_EQ(kArmMls, s[1]->arch_opcode());
2366 ASSERT_EQ(1U, s[1]->OutputCount());
2367 ASSERT_EQ(3U, s[1]->InputCount());
2368 EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(0)));
2369 EXPECT_EQ(s.ToVreg(s[0]->InputAt(1)), s.ToVreg(s[1]->InputAt(1)));
2370 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[1]->InputAt(2)));
2371}
2372
2373
2374TEST_F(InstructionSelectorTest, Int32MulWithParameters) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002375 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2376 MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002377 m.Return(m.Int32Mul(m.Parameter(0), m.Parameter(1)));
2378 Stream s = m.Build();
2379 ASSERT_EQ(1U, s.size());
2380 EXPECT_EQ(kArmMul, s[0]->arch_opcode());
2381 EXPECT_EQ(2U, s[0]->InputCount());
2382 EXPECT_EQ(1U, s[0]->OutputCount());
2383}
2384
2385
2386TEST_F(InstructionSelectorTest, Int32MulWithImmediate) {
2387 // x * (2^k + 1) -> x + (x >> k)
2388 TRACED_FORRANGE(int32_t, k, 1, 30) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002389 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002390 m.Return(m.Int32Mul(m.Parameter(0), m.Int32Constant((1 << k) + 1)));
2391 Stream s = m.Build();
2392 ASSERT_EQ(1U, s.size());
2393 EXPECT_EQ(kArmAdd, s[0]->arch_opcode());
2394 EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
2395 ASSERT_EQ(3U, s[0]->InputCount());
2396 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
2397 EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2)));
2398 EXPECT_EQ(1U, s[0]->OutputCount());
2399 }
2400 // x * (2^k - 1) -> -x + (x >> k)
2401 TRACED_FORRANGE(int32_t, k, 3, 30) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002402 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002403 m.Return(m.Int32Mul(m.Parameter(0), m.Int32Constant((1 << k) - 1)));
2404 Stream s = m.Build();
2405 ASSERT_EQ(1U, s.size());
2406 EXPECT_EQ(kArmRsb, s[0]->arch_opcode());
2407 EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
2408 ASSERT_EQ(3U, s[0]->InputCount());
2409 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
2410 EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2)));
2411 EXPECT_EQ(1U, s[0]->OutputCount());
2412 }
2413 // (2^k + 1) * x -> x + (x >> k)
2414 TRACED_FORRANGE(int32_t, k, 1, 30) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002415 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002416 m.Return(m.Int32Mul(m.Int32Constant((1 << k) + 1), m.Parameter(0)));
2417 Stream s = m.Build();
2418 ASSERT_EQ(1U, s.size());
2419 EXPECT_EQ(kArmAdd, s[0]->arch_opcode());
2420 EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
2421 ASSERT_EQ(3U, s[0]->InputCount());
2422 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
2423 EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2)));
2424 EXPECT_EQ(1U, s[0]->OutputCount());
2425 }
2426 // x * (2^k - 1) -> -x + (x >> k)
2427 TRACED_FORRANGE(int32_t, k, 3, 30) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002428 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002429 m.Return(m.Int32Mul(m.Int32Constant((1 << k) - 1), m.Parameter(0)));
2430 Stream s = m.Build();
2431 ASSERT_EQ(1U, s.size());
2432 EXPECT_EQ(kArmRsb, s[0]->arch_opcode());
2433 EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
2434 ASSERT_EQ(3U, s[0]->InputCount());
2435 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
2436 EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2)));
2437 EXPECT_EQ(1U, s[0]->OutputCount());
2438 }
2439}
2440
2441
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002442TEST_F(InstructionSelectorTest, Int32MulHighWithParameters) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002443 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2444 MachineType::Int32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002445 Node* const p0 = m.Parameter(0);
2446 Node* const p1 = m.Parameter(1);
2447 Node* const n = m.Int32MulHigh(p0, p1);
2448 m.Return(n);
2449 Stream s = m.Build();
2450 ASSERT_EQ(1U, s.size());
2451 EXPECT_EQ(kArmSmmul, s[0]->arch_opcode());
2452 ASSERT_EQ(2U, s[0]->InputCount());
2453 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
2454 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
2455 ASSERT_EQ(1U, s[0]->OutputCount());
2456 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
2457}
2458
2459
2460TEST_F(InstructionSelectorTest, Uint32MulHighWithParameters) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002461 StreamBuilder m(this, MachineType::Uint32(), MachineType::Uint32(),
2462 MachineType::Uint32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002463 Node* const p0 = m.Parameter(0);
2464 Node* const p1 = m.Parameter(1);
2465 Node* const n = m.Uint32MulHigh(p0, p1);
2466 m.Return(n);
2467 Stream s = m.Build();
2468 ASSERT_EQ(1U, s.size());
2469 EXPECT_EQ(kArmUmull, s[0]->arch_opcode());
2470 ASSERT_EQ(2U, s[0]->InputCount());
2471 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
2472 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
2473 ASSERT_EQ(2U, s[0]->OutputCount());
2474 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->OutputAt(1)));
2475}
2476
2477
2478TEST_F(InstructionSelectorTest, Uint32DivWithParameters) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002479 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2480 MachineType::Int32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002481 m.Return(m.Uint32Div(m.Parameter(0), m.Parameter(1)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002482 Stream s = m.Build();
2483 ASSERT_EQ(4U, s.size());
2484 EXPECT_EQ(kArmVcvtF64U32, s[0]->arch_opcode());
2485 ASSERT_EQ(1U, s[0]->OutputCount());
2486 EXPECT_EQ(kArmVcvtF64U32, s[1]->arch_opcode());
2487 ASSERT_EQ(1U, s[1]->OutputCount());
2488 EXPECT_EQ(kArmVdivF64, s[2]->arch_opcode());
2489 ASSERT_EQ(2U, s[2]->InputCount());
2490 ASSERT_EQ(1U, s[2]->OutputCount());
2491 EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[2]->InputAt(0)));
2492 EXPECT_EQ(s.ToVreg(s[1]->Output()), s.ToVreg(s[2]->InputAt(1)));
2493 EXPECT_EQ(kArmVcvtU32F64, s[3]->arch_opcode());
2494 ASSERT_EQ(1U, s[3]->InputCount());
2495 EXPECT_EQ(s.ToVreg(s[2]->Output()), s.ToVreg(s[3]->InputAt(0)));
2496}
2497
2498
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002499TEST_F(InstructionSelectorTest, Uint32DivWithParametersForSUDIV) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002500 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2501 MachineType::Int32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002502 m.Return(m.Uint32Div(m.Parameter(0), m.Parameter(1)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002503 Stream s = m.Build(SUDIV);
2504 ASSERT_EQ(1U, s.size());
2505 EXPECT_EQ(kArmUdiv, s[0]->arch_opcode());
2506}
2507
2508
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002509TEST_F(InstructionSelectorTest, Uint32ModWithParameters) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002510 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2511 MachineType::Int32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002512 m.Return(m.Uint32Mod(m.Parameter(0), m.Parameter(1)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002513 Stream s = m.Build();
2514 ASSERT_EQ(6U, s.size());
2515 EXPECT_EQ(kArmVcvtF64U32, s[0]->arch_opcode());
2516 ASSERT_EQ(1U, s[0]->OutputCount());
2517 EXPECT_EQ(kArmVcvtF64U32, s[1]->arch_opcode());
2518 ASSERT_EQ(1U, s[1]->OutputCount());
2519 EXPECT_EQ(kArmVdivF64, s[2]->arch_opcode());
2520 ASSERT_EQ(2U, s[2]->InputCount());
2521 ASSERT_EQ(1U, s[2]->OutputCount());
2522 EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[2]->InputAt(0)));
2523 EXPECT_EQ(s.ToVreg(s[1]->Output()), s.ToVreg(s[2]->InputAt(1)));
2524 EXPECT_EQ(kArmVcvtU32F64, s[3]->arch_opcode());
2525 ASSERT_EQ(1U, s[3]->InputCount());
2526 EXPECT_EQ(s.ToVreg(s[2]->Output()), s.ToVreg(s[3]->InputAt(0)));
2527 EXPECT_EQ(kArmMul, s[4]->arch_opcode());
2528 ASSERT_EQ(1U, s[4]->OutputCount());
2529 ASSERT_EQ(2U, s[4]->InputCount());
2530 EXPECT_EQ(s.ToVreg(s[3]->Output()), s.ToVreg(s[4]->InputAt(0)));
2531 EXPECT_EQ(s.ToVreg(s[1]->InputAt(0)), s.ToVreg(s[4]->InputAt(1)));
2532 EXPECT_EQ(kArmSub, s[5]->arch_opcode());
2533 ASSERT_EQ(1U, s[5]->OutputCount());
2534 ASSERT_EQ(2U, s[5]->InputCount());
2535 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[5]->InputAt(0)));
2536 EXPECT_EQ(s.ToVreg(s[4]->Output()), s.ToVreg(s[5]->InputAt(1)));
2537}
2538
2539
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002540TEST_F(InstructionSelectorTest, Uint32ModWithParametersForSUDIV) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002541 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2542 MachineType::Int32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002543 m.Return(m.Uint32Mod(m.Parameter(0), m.Parameter(1)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002544 Stream s = m.Build(SUDIV);
2545 ASSERT_EQ(3U, s.size());
2546 EXPECT_EQ(kArmUdiv, s[0]->arch_opcode());
2547 ASSERT_EQ(1U, s[0]->OutputCount());
2548 ASSERT_EQ(2U, s[0]->InputCount());
2549 EXPECT_EQ(kArmMul, s[1]->arch_opcode());
2550 ASSERT_EQ(1U, s[1]->OutputCount());
2551 ASSERT_EQ(2U, s[1]->InputCount());
2552 EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(0)));
2553 EXPECT_EQ(s.ToVreg(s[0]->InputAt(1)), s.ToVreg(s[1]->InputAt(1)));
2554 EXPECT_EQ(kArmSub, s[2]->arch_opcode());
2555 ASSERT_EQ(1U, s[2]->OutputCount());
2556 ASSERT_EQ(2U, s[2]->InputCount());
2557 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[2]->InputAt(0)));
2558 EXPECT_EQ(s.ToVreg(s[1]->Output()), s.ToVreg(s[2]->InputAt(1)));
2559}
2560
2561
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002562TEST_F(InstructionSelectorTest, Uint32ModWithParametersForSUDIVAndMLS) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002563 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2564 MachineType::Int32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002565 m.Return(m.Uint32Mod(m.Parameter(0), m.Parameter(1)));
Ben Murdoch61f157c2016-09-16 13:49:30 +01002566 Stream s = m.Build(ARMv7, SUDIV);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002567 ASSERT_EQ(2U, s.size());
2568 EXPECT_EQ(kArmUdiv, s[0]->arch_opcode());
2569 ASSERT_EQ(1U, s[0]->OutputCount());
2570 ASSERT_EQ(2U, s[0]->InputCount());
2571 EXPECT_EQ(kArmMls, s[1]->arch_opcode());
2572 ASSERT_EQ(1U, s[1]->OutputCount());
2573 ASSERT_EQ(3U, s[1]->InputCount());
2574 EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(0)));
2575 EXPECT_EQ(s.ToVreg(s[0]->InputAt(1)), s.ToVreg(s[1]->InputAt(1)));
2576 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[1]->InputAt(2)));
2577}
2578
2579
Ben Murdoch097c5b22016-05-18 11:27:45 +01002580TEST_F(InstructionSelectorTest, Word32ShlWord32SarForSbfx) {
2581 TRACED_FORRANGE(int32_t, shl, 1, 31) {
2582 TRACED_FORRANGE(int32_t, sar, shl, 31) {
2583 if ((shl == sar) && (sar == 16)) continue; // Sxth.
2584 if ((shl == sar) && (sar == 24)) continue; // Sxtb.
2585 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2586 m.Return(m.Word32Sar(m.Word32Shl(m.Parameter(0), m.Int32Constant(shl)),
2587 m.Int32Constant(sar)));
2588 Stream s = m.Build(ARMv7);
2589 ASSERT_EQ(1U, s.size());
2590 EXPECT_EQ(kArmSbfx, s[0]->arch_opcode());
2591 ASSERT_EQ(3U, s[0]->InputCount());
2592 EXPECT_EQ(sar - shl, s.ToInt32(s[0]->InputAt(1)));
2593 EXPECT_EQ(32 - sar, s.ToInt32(s[0]->InputAt(2)));
2594 }
2595 }
2596}
2597
2598
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002599TEST_F(InstructionSelectorTest, Word32AndWithUbfxImmediateForARMv7) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01002600 TRACED_FORRANGE(int32_t, width, 9, 23) {
2601 if (width == 16) continue; // Uxth.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002602 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002603 m.Return(m.Word32And(m.Parameter(0),
2604 m.Int32Constant(0xffffffffu >> (32 - width))));
2605 Stream s = m.Build(ARMv7);
2606 ASSERT_EQ(1U, s.size());
2607 EXPECT_EQ(kArmUbfx, s[0]->arch_opcode());
2608 ASSERT_EQ(3U, s[0]->InputCount());
2609 EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1)));
2610 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
2611 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01002612 TRACED_FORRANGE(int32_t, width, 9, 23) {
2613 if (width == 16) continue; // Uxth.
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(m.Word32And(m.Int32Constant(0xffffffffu >> (32 - width)),
2616 m.Parameter(0)));
2617 Stream s = m.Build(ARMv7);
2618 ASSERT_EQ(1U, s.size());
2619 EXPECT_EQ(kArmUbfx, s[0]->arch_opcode());
2620 ASSERT_EQ(3U, s[0]->InputCount());
2621 EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1)));
2622 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
2623 }
2624}
2625
2626
2627TEST_F(InstructionSelectorTest, Word32AndWithBfcImmediateForARMv7) {
2628 TRACED_FORRANGE(int32_t, lsb, 0, 31) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01002629 TRACED_FORRANGE(int32_t, width, 9, (24 - lsb) - 1) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002630 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002631 m.Return(m.Word32And(
2632 m.Parameter(0),
2633 m.Int32Constant(~((0xffffffffu >> (32 - width)) << lsb))));
2634 Stream s = m.Build(ARMv7);
2635 ASSERT_EQ(1U, s.size());
2636 EXPECT_EQ(kArmBfc, s[0]->arch_opcode());
2637 ASSERT_EQ(1U, s[0]->OutputCount());
2638 EXPECT_TRUE(
2639 UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy());
2640 ASSERT_EQ(3U, s[0]->InputCount());
2641 EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
2642 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
2643 }
2644 }
2645 TRACED_FORRANGE(int32_t, lsb, 0, 31) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01002646 TRACED_FORRANGE(int32_t, width, 9, (24 - lsb) - 1) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002647 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002648 m.Return(
2649 m.Word32And(m.Int32Constant(~((0xffffffffu >> (32 - width)) << lsb)),
2650 m.Parameter(0)));
2651 Stream s = m.Build(ARMv7);
2652 ASSERT_EQ(1U, s.size());
2653 EXPECT_EQ(kArmBfc, s[0]->arch_opcode());
2654 ASSERT_EQ(1U, s[0]->OutputCount());
2655 EXPECT_TRUE(
2656 UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy());
2657 ASSERT_EQ(3U, s[0]->InputCount());
2658 EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
2659 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
2660 }
2661 }
2662}
2663
2664
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002665TEST_F(InstructionSelectorTest, Word32AndWith0xffff) {
2666 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002667 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002668 Node* const p0 = m.Parameter(0);
2669 Node* const r = m.Word32And(p0, m.Int32Constant(0xffff));
2670 m.Return(r);
2671 Stream s = m.Build();
2672 ASSERT_EQ(1U, s.size());
2673 EXPECT_EQ(kArmUxth, 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 = m.Word32And(m.Int32Constant(0xffff), p0);
2684 m.Return(r);
2685 Stream s = m.Build();
2686 ASSERT_EQ(1U, s.size());
2687 EXPECT_EQ(kArmUxth, s[0]->arch_opcode());
2688 ASSERT_EQ(2U, s[0]->InputCount());
2689 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
2690 EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1)));
2691 ASSERT_EQ(1U, s[0]->OutputCount());
2692 EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
2693 }
2694}
2695
2696
2697TEST_F(InstructionSelectorTest, Word32SarWithWord32Shl) {
2698 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002699 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002700 Node* const p0 = m.Parameter(0);
2701 Node* const r =
2702 m.Word32Sar(m.Word32Shl(p0, m.Int32Constant(24)), m.Int32Constant(24));
2703 m.Return(r);
2704 Stream s = m.Build();
2705 ASSERT_EQ(1U, s.size());
2706 EXPECT_EQ(kArmSxtb, s[0]->arch_opcode());
2707 ASSERT_EQ(2U, s[0]->InputCount());
2708 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
2709 EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1)));
2710 ASSERT_EQ(1U, s[0]->OutputCount());
2711 EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
2712 }
2713 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002714 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002715 Node* const p0 = m.Parameter(0);
2716 Node* const r =
2717 m.Word32Sar(m.Word32Shl(p0, m.Int32Constant(16)), m.Int32Constant(16));
2718 m.Return(r);
2719 Stream s = m.Build();
2720 ASSERT_EQ(1U, s.size());
2721 EXPECT_EQ(kArmSxth, s[0]->arch_opcode());
2722 ASSERT_EQ(2U, s[0]->InputCount());
2723 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
2724 EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1)));
2725 ASSERT_EQ(1U, s[0]->OutputCount());
2726 EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
2727 }
2728}
2729
2730
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002731TEST_F(InstructionSelectorTest, Word32ShrWithWord32AndWithImmediateForARMv7) {
2732 TRACED_FORRANGE(int32_t, lsb, 0, 31) {
2733 TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) {
2734 uint32_t max = 1 << lsb;
2735 if (max > static_cast<uint32_t>(kMaxInt)) max -= 1;
2736 uint32_t jnk = rng()->NextInt(max);
2737 uint32_t msk = ((0xffffffffu >> (32 - width)) << lsb) | jnk;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002738 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002739 m.Return(m.Word32Shr(m.Word32And(m.Parameter(0), m.Int32Constant(msk)),
2740 m.Int32Constant(lsb)));
2741 Stream s = m.Build(ARMv7);
2742 ASSERT_EQ(1U, s.size());
2743 EXPECT_EQ(kArmUbfx, s[0]->arch_opcode());
2744 ASSERT_EQ(3U, s[0]->InputCount());
2745 EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
2746 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
2747 }
2748 }
2749 TRACED_FORRANGE(int32_t, lsb, 0, 31) {
2750 TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) {
2751 uint32_t max = 1 << lsb;
2752 if (max > static_cast<uint32_t>(kMaxInt)) max -= 1;
2753 uint32_t jnk = rng()->NextInt(max);
2754 uint32_t msk = ((0xffffffffu >> (32 - width)) << lsb) | jnk;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002755 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002756 m.Return(m.Word32Shr(m.Word32And(m.Int32Constant(msk), m.Parameter(0)),
2757 m.Int32Constant(lsb)));
2758 Stream s = m.Build(ARMv7);
2759 ASSERT_EQ(1U, s.size());
2760 EXPECT_EQ(kArmUbfx, s[0]->arch_opcode());
2761 ASSERT_EQ(3U, s[0]->InputCount());
2762 EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
2763 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
2764 }
2765 }
2766}
2767
2768
2769TEST_F(InstructionSelectorTest, Word32AndWithWord32Not) {
2770 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002771 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2772 MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002773 m.Return(m.Word32And(m.Parameter(0), m.Word32Not(m.Parameter(1))));
2774 Stream s = m.Build();
2775 ASSERT_EQ(1U, s.size());
2776 EXPECT_EQ(kArmBic, s[0]->arch_opcode());
2777 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
2778 EXPECT_EQ(2U, s[0]->InputCount());
2779 EXPECT_EQ(1U, s[0]->OutputCount());
2780 }
2781 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002782 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2783 MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002784 m.Return(m.Word32And(m.Word32Not(m.Parameter(0)), m.Parameter(1)));
2785 Stream s = m.Build();
2786 ASSERT_EQ(1U, s.size());
2787 EXPECT_EQ(kArmBic, s[0]->arch_opcode());
2788 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
2789 EXPECT_EQ(2U, s[0]->InputCount());
2790 EXPECT_EQ(1U, s[0]->OutputCount());
2791 }
2792}
2793
2794
2795TEST_F(InstructionSelectorTest, Word32EqualWithParameters) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002796 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2797 MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002798 m.Return(m.Word32Equal(m.Parameter(0), m.Parameter(1)));
2799 Stream s = m.Build();
2800 ASSERT_EQ(1U, s.size());
2801 EXPECT_EQ(kArmCmp, s[0]->arch_opcode());
2802 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
2803 EXPECT_EQ(2U, s[0]->InputCount());
2804 EXPECT_EQ(1U, s[0]->OutputCount());
2805 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
2806 EXPECT_EQ(kEqual, s[0]->flags_condition());
2807}
2808
2809
2810TEST_F(InstructionSelectorTest, Word32EqualWithImmediate) {
2811 TRACED_FOREACH(int32_t, imm, kImmediates) {
2812 if (imm == 0) continue;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002813 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002814 m.Return(m.Word32Equal(m.Parameter(0), m.Int32Constant(imm)));
2815 Stream s = m.Build();
2816 ASSERT_EQ(1U, s.size());
2817 EXPECT_EQ(kArmCmp, s[0]->arch_opcode());
2818 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode());
2819 ASSERT_EQ(2U, s[0]->InputCount());
2820 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
2821 EXPECT_EQ(1U, s[0]->OutputCount());
2822 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
2823 EXPECT_EQ(kEqual, s[0]->flags_condition());
2824 }
2825 TRACED_FOREACH(int32_t, imm, kImmediates) {
2826 if (imm == 0) continue;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002827 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002828 m.Return(m.Word32Equal(m.Int32Constant(imm), m.Parameter(0)));
2829 Stream s = m.Build();
2830 ASSERT_EQ(1U, s.size());
2831 EXPECT_EQ(kArmCmp, s[0]->arch_opcode());
2832 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode());
2833 ASSERT_EQ(2U, s[0]->InputCount());
2834 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
2835 EXPECT_EQ(1U, s[0]->OutputCount());
2836 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
2837 EXPECT_EQ(kEqual, s[0]->flags_condition());
2838 }
2839}
2840
2841
2842TEST_F(InstructionSelectorTest, Word32EqualWithZero) {
2843 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002844 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002845 m.Return(m.Word32Equal(m.Parameter(0), m.Int32Constant(0)));
2846 Stream s = m.Build();
2847 ASSERT_EQ(1U, s.size());
2848 EXPECT_EQ(kArmTst, s[0]->arch_opcode());
2849 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
2850 ASSERT_EQ(2U, s[0]->InputCount());
2851 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
2852 EXPECT_EQ(1U, s[0]->OutputCount());
2853 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
2854 EXPECT_EQ(kEqual, s[0]->flags_condition());
2855 }
2856 {
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.Word32Equal(m.Int32Constant(0), m.Parameter(0)));
2859 Stream s = m.Build();
2860 ASSERT_EQ(1U, s.size());
2861 EXPECT_EQ(kArmTst, s[0]->arch_opcode());
2862 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
2863 ASSERT_EQ(2U, s[0]->InputCount());
2864 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
2865 EXPECT_EQ(1U, s[0]->OutputCount());
2866 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
2867 EXPECT_EQ(kEqual, s[0]->flags_condition());
2868 }
2869}
2870
2871
2872TEST_F(InstructionSelectorTest, Word32NotWithParameter) {
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.Word32Not(m.Parameter(0)));
2875 Stream s = m.Build();
2876 ASSERT_EQ(1U, s.size());
2877 EXPECT_EQ(kArmMvn, s[0]->arch_opcode());
2878 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
2879 EXPECT_EQ(1U, s[0]->InputCount());
2880 EXPECT_EQ(1U, s[0]->OutputCount());
2881}
2882
2883
2884TEST_F(InstructionSelectorTest, Word32AndWithWord32ShrWithImmediateForARMv7) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01002885 TRACED_FORRANGE(int32_t, lsb, 1, 31) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002886 TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01002887 if (((width == 8) || (width == 16)) &&
2888 ((lsb == 8) || (lsb == 16) || (lsb == 24)))
2889 continue; // Uxtb/h ror.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002890 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002891 m.Return(m.Word32And(m.Word32Shr(m.Parameter(0), m.Int32Constant(lsb)),
2892 m.Int32Constant(0xffffffffu >> (32 - width))));
2893 Stream s = m.Build(ARMv7);
2894 ASSERT_EQ(1U, s.size());
2895 EXPECT_EQ(kArmUbfx, s[0]->arch_opcode());
2896 ASSERT_EQ(3U, s[0]->InputCount());
2897 EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
2898 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
2899 }
2900 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01002901 TRACED_FORRANGE(int32_t, lsb, 1, 31) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002902 TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01002903 if (((width == 8) || (width == 16)) &&
2904 ((lsb == 8) || (lsb == 16) || (lsb == 24)))
2905 continue; // Uxtb/h ror.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002906 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002907 m.Return(m.Word32And(m.Int32Constant(0xffffffffu >> (32 - width)),
2908 m.Word32Shr(m.Parameter(0), m.Int32Constant(lsb))));
2909 Stream s = m.Build(ARMv7);
2910 ASSERT_EQ(1U, s.size());
2911 EXPECT_EQ(kArmUbfx, s[0]->arch_opcode());
2912 ASSERT_EQ(3U, s[0]->InputCount());
2913 EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
2914 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
2915 }
2916 }
2917}
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002918
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002919
Ben Murdoch097c5b22016-05-18 11:27:45 +01002920TEST_F(InstructionSelectorTest, Word32AndWithWord32ShrAnd0xff) {
2921 TRACED_FORRANGE(int32_t, shr, 1, 3) {
2922 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2923 Node* const p0 = m.Parameter(0);
2924 Node* const r = m.Word32And(m.Word32Shr(p0, m.Int32Constant(shr * 8)),
2925 m.Int32Constant(0xff));
2926 m.Return(r);
2927 Stream s = m.Build();
2928 ASSERT_EQ(1U, s.size());
2929 EXPECT_EQ(kArmUxtb, s[0]->arch_opcode());
2930 ASSERT_EQ(2U, s[0]->InputCount());
2931 EXPECT_EQ(shr * 8, s.ToInt32(s[0]->InputAt(1)));
2932 }
2933 TRACED_FORRANGE(int32_t, shr, 1, 3) {
2934 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2935 Node* const p0 = m.Parameter(0);
2936 Node* const r = m.Word32And(m.Int32Constant(0xff),
2937 m.Word32Shr(p0, m.Int32Constant(shr * 8)));
2938 m.Return(r);
2939 Stream s = m.Build();
2940 ASSERT_EQ(1U, s.size());
2941 EXPECT_EQ(kArmUxtb, s[0]->arch_opcode());
2942 ASSERT_EQ(2U, s[0]->InputCount());
2943 EXPECT_EQ(shr * 8, s.ToInt32(s[0]->InputAt(1)));
2944 }
2945}
2946
2947
2948TEST_F(InstructionSelectorTest, Word32AndWithWord32ShrAnd0xffff) {
2949 TRACED_FORRANGE(int32_t, shr, 1, 3) {
2950 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2951 Node* const p0 = m.Parameter(0);
2952 Node* const r = m.Word32And(m.Word32Shr(p0, m.Int32Constant(shr * 8)),
2953 m.Int32Constant(0xffff));
2954 m.Return(r);
2955 Stream s = m.Build();
2956 ASSERT_EQ(1U, s.size());
2957 EXPECT_EQ(kArmUxth, s[0]->arch_opcode());
2958 ASSERT_EQ(2U, s[0]->InputCount());
2959 EXPECT_EQ(shr * 8, s.ToInt32(s[0]->InputAt(1)));
2960 }
2961 TRACED_FORRANGE(int32_t, shr, 1, 3) {
2962 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2963 Node* const p0 = m.Parameter(0);
2964 Node* const r = m.Word32And(m.Int32Constant(0xffff),
2965 m.Word32Shr(p0, m.Int32Constant(shr * 8)));
2966 m.Return(r);
2967 Stream s = m.Build();
2968 ASSERT_EQ(1U, s.size());
2969 EXPECT_EQ(kArmUxth, s[0]->arch_opcode());
2970 ASSERT_EQ(2U, s[0]->InputCount());
2971 EXPECT_EQ(shr * 8, s.ToInt32(s[0]->InputAt(1)));
2972 }
2973}
2974
2975
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002976TEST_F(InstructionSelectorTest, Word32Clz) {
2977 StreamBuilder m(this, MachineType::Uint32(), MachineType::Uint32());
2978 Node* const p0 = m.Parameter(0);
2979 Node* const n = m.Word32Clz(p0);
2980 m.Return(n);
2981 Stream s = m.Build();
2982 ASSERT_EQ(1U, s.size());
2983 EXPECT_EQ(kArmClz, s[0]->arch_opcode());
2984 ASSERT_EQ(1U, s[0]->InputCount());
2985 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
2986 ASSERT_EQ(1U, s[0]->OutputCount());
2987 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
2988}
2989
Ben Murdochc5610432016-08-08 18:44:38 +01002990TEST_F(InstructionSelectorTest, Float32Max) {
2991 StreamBuilder m(this, MachineType::Float32(), MachineType::Float32(),
2992 MachineType::Float32());
2993 Node* const p0 = m.Parameter(0);
2994 Node* const p1 = m.Parameter(1);
2995 Node* const n = m.Float32Max(p0, p1);
2996 m.Return(n);
2997 Stream s = m.Build(ARMv8);
2998 // Float32Max is `(b < a) ? a : b`.
2999 ASSERT_EQ(1U, s.size());
3000 EXPECT_EQ(kArmFloat32Max, s[0]->arch_opcode());
3001 ASSERT_EQ(2U, s[0]->InputCount());
3002 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
3003 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
3004 ASSERT_EQ(1U, s[0]->OutputCount());
3005 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
3006}
3007
3008TEST_F(InstructionSelectorTest, Float32Min) {
3009 StreamBuilder m(this, MachineType::Float32(), MachineType::Float32(),
3010 MachineType::Float32());
3011 Node* const p0 = m.Parameter(0);
3012 Node* const p1 = m.Parameter(1);
3013 Node* const n = m.Float32Min(p0, p1);
3014 m.Return(n);
3015 Stream s = m.Build(ARMv8);
3016 // Float32Min is `(a < b) ? a : b`.
3017 ASSERT_EQ(1U, s.size());
3018 EXPECT_EQ(kArmFloat32Min, s[0]->arch_opcode());
3019 ASSERT_EQ(2U, s[0]->InputCount());
3020 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
3021 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
3022 ASSERT_EQ(1U, s[0]->OutputCount());
3023 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
3024}
3025
3026TEST_F(InstructionSelectorTest, Float64Max) {
3027 StreamBuilder m(this, MachineType::Float64(), MachineType::Float64(),
3028 MachineType::Float64());
3029 Node* const p0 = m.Parameter(0);
3030 Node* const p1 = m.Parameter(1);
3031 Node* const n = m.Float64Max(p0, p1);
3032 m.Return(n);
3033 Stream s = m.Build(ARMv8);
3034 // Float64Max is `(b < a) ? a : b`.
3035 ASSERT_EQ(1U, s.size());
3036 EXPECT_EQ(kArmFloat64Max, s[0]->arch_opcode());
3037 ASSERT_EQ(2U, s[0]->InputCount());
3038 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
3039 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
3040 ASSERT_EQ(1U, s[0]->OutputCount());
3041 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
3042}
3043
3044TEST_F(InstructionSelectorTest, Float64Min) {
3045 StreamBuilder m(this, MachineType::Float64(), MachineType::Float64(),
3046 MachineType::Float64());
3047 Node* const p0 = m.Parameter(0);
3048 Node* const p1 = m.Parameter(1);
3049 Node* const n = m.Float64Min(p0, p1);
3050 m.Return(n);
3051 Stream s = m.Build(ARMv8);
3052 // Float64Min is `(a < b) ? a : b`.
3053 ASSERT_EQ(1U, s.size());
3054 EXPECT_EQ(kArmFloat64Min, s[0]->arch_opcode());
3055 ASSERT_EQ(2U, s[0]->InputCount());
3056 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
3057 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
3058 ASSERT_EQ(1U, s[0]->OutputCount());
3059 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
3060}
3061
Ben Murdoch61f157c2016-09-16 13:49:30 +01003062TEST_F(InstructionSelectorTest, Float32Neg) {
3063 StreamBuilder m(this, MachineType::Float32(), MachineType::Float32());
3064 Node* const p0 = m.Parameter(0);
3065 // Don't use m.Float32Neg() as that generates an explicit sub.
3066 Node* const n = m.AddNode(m.machine()->Float32Neg().op(), m.Parameter(0));
3067 m.Return(n);
3068 Stream s = m.Build();
3069 ASSERT_EQ(1U, s.size());
3070 EXPECT_EQ(kArmVnegF32, s[0]->arch_opcode());
3071 ASSERT_EQ(1U, s[0]->InputCount());
3072 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
3073 ASSERT_EQ(1U, s[0]->OutputCount());
3074 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
3075}
3076
3077TEST_F(InstructionSelectorTest, Float64Neg) {
3078 StreamBuilder m(this, MachineType::Float64(), MachineType::Float64());
3079 Node* const p0 = m.Parameter(0);
3080 // Don't use m.Float64Neg() as that generates an explicit sub.
3081 Node* const n = m.AddNode(m.machine()->Float64Neg().op(), m.Parameter(0));
3082 m.Return(n);
3083 Stream s = m.Build();
3084 ASSERT_EQ(1U, s.size());
3085 EXPECT_EQ(kArmVnegF64, s[0]->arch_opcode());
3086 ASSERT_EQ(1U, s[0]->InputCount());
3087 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
3088 ASSERT_EQ(1U, s[0]->OutputCount());
3089 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
3090}
3091
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003092} // namespace compiler
3093} // namespace internal
3094} // namespace v8