Upstream version 11.40.271.0
[platform/framework/web/crosswalk.git] / src / v8 / test / unittests / compiler / arm64 / instruction-selector-arm64-unittest.cc
1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "test/unittests/compiler/instruction-selector-unittest.h"
6
7 namespace v8 {
8 namespace internal {
9 namespace compiler {
10
11 namespace {
12
13 typedef RawMachineAssembler::Label MLabel;
14
15 template <typename T>
16 struct MachInst {
17   T constructor;
18   const char* constructor_name;
19   ArchOpcode arch_opcode;
20   MachineType machine_type;
21 };
22
23 typedef MachInst<Node* (RawMachineAssembler::*)(Node*)> MachInst1;
24 typedef MachInst<Node* (RawMachineAssembler::*)(Node*, Node*)> MachInst2;
25
26
27 template <typename T>
28 std::ostream& operator<<(std::ostream& os, const MachInst<T>& mi) {
29   return os << mi.constructor_name;
30 }
31
32
33 struct Shift {
34   MachInst2 mi;
35   AddressingMode mode;
36 };
37
38
39 std::ostream& operator<<(std::ostream& os, const Shift& shift) {
40   return os << shift.mi;
41 }
42
43
44 // Helper to build Int32Constant or Int64Constant depending on the given
45 // machine type.
46 Node* BuildConstant(InstructionSelectorTest::StreamBuilder& m, MachineType type,
47                     int64_t value) {
48   switch (type) {
49     case kMachInt32:
50       return m.Int32Constant(value);
51       break;
52
53     case kMachInt64:
54       return m.Int64Constant(value);
55       break;
56
57     default:
58       UNIMPLEMENTED();
59   }
60   return NULL;
61 }
62
63
64 // ARM64 logical instructions.
65 static const MachInst2 kLogicalInstructions[] = {
66     {&RawMachineAssembler::Word32And, "Word32And", kArm64And32, kMachInt32},
67     {&RawMachineAssembler::Word64And, "Word64And", kArm64And, kMachInt64},
68     {&RawMachineAssembler::Word32Or, "Word32Or", kArm64Or32, kMachInt32},
69     {&RawMachineAssembler::Word64Or, "Word64Or", kArm64Or, kMachInt64},
70     {&RawMachineAssembler::Word32Xor, "Word32Xor", kArm64Eor32, kMachInt32},
71     {&RawMachineAssembler::Word64Xor, "Word64Xor", kArm64Eor, kMachInt64}};
72
73
74 // ARM64 logical immediates: contiguous set bits, rotated about a power of two
75 // sized block. The block is then duplicated across the word. Below is a random
76 // subset of the 32-bit immediates.
77 static const uint32_t kLogical32Immediates[] = {
78     0x00000002, 0x00000003, 0x00000070, 0x00000080, 0x00000100, 0x000001c0,
79     0x00000300, 0x000007e0, 0x00003ffc, 0x00007fc0, 0x0003c000, 0x0003f000,
80     0x0003ffc0, 0x0003fff8, 0x0007ff00, 0x0007ffe0, 0x000e0000, 0x001e0000,
81     0x001ffffc, 0x003f0000, 0x003f8000, 0x00780000, 0x007fc000, 0x00ff0000,
82     0x01800000, 0x01800180, 0x01f801f8, 0x03fe0000, 0x03ffffc0, 0x03fffffc,
83     0x06000000, 0x07fc0000, 0x07ffc000, 0x07ffffc0, 0x07ffffe0, 0x0ffe0ffe,
84     0x0ffff800, 0x0ffffff0, 0x0fffffff, 0x18001800, 0x1f001f00, 0x1f801f80,
85     0x30303030, 0x3ff03ff0, 0x3ff83ff8, 0x3fff0000, 0x3fff8000, 0x3fffffc0,
86     0x70007000, 0x7f7f7f7f, 0x7fc00000, 0x7fffffc0, 0x8000001f, 0x800001ff,
87     0x81818181, 0x9fff9fff, 0xc00007ff, 0xc0ffffff, 0xdddddddd, 0xe00001ff,
88     0xe00003ff, 0xe007ffff, 0xefffefff, 0xf000003f, 0xf001f001, 0xf3fff3ff,
89     0xf800001f, 0xf80fffff, 0xf87ff87f, 0xfbfbfbfb, 0xfc00001f, 0xfc0000ff,
90     0xfc0001ff, 0xfc03fc03, 0xfe0001ff, 0xff000001, 0xff03ff03, 0xff800000,
91     0xff800fff, 0xff801fff, 0xff87ffff, 0xffc0003f, 0xffc007ff, 0xffcfffcf,
92     0xffe00003, 0xffe1ffff, 0xfff0001f, 0xfff07fff, 0xfff80007, 0xfff87fff,
93     0xfffc00ff, 0xfffe07ff, 0xffff00ff, 0xffffc001, 0xfffff007, 0xfffff3ff,
94     0xfffff807, 0xfffff9ff, 0xfffffc0f, 0xfffffeff};
95
96
97 // Random subset of 64-bit logical immediates.
98 static const uint64_t kLogical64Immediates[] = {
99     0x0000000000000001, 0x0000000000000002, 0x0000000000000003,
100     0x0000000000000070, 0x0000000000000080, 0x0000000000000100,
101     0x00000000000001c0, 0x0000000000000300, 0x0000000000000600,
102     0x00000000000007e0, 0x0000000000003ffc, 0x0000000000007fc0,
103     0x0000000600000000, 0x0000003ffffffffc, 0x000000f000000000,
104     0x000001f800000000, 0x0003fc0000000000, 0x0003fc000003fc00,
105     0x0003ffffffc00000, 0x0003ffffffffffc0, 0x0006000000060000,
106     0x003ffffffffc0000, 0x0180018001800180, 0x01f801f801f801f8,
107     0x0600000000000000, 0x1000000010000000, 0x1000100010001000,
108     0x1010101010101010, 0x1111111111111111, 0x1f001f001f001f00,
109     0x1f1f1f1f1f1f1f1f, 0x1ffffffffffffffe, 0x3ffc3ffc3ffc3ffc,
110     0x5555555555555555, 0x7f7f7f7f7f7f7f7f, 0x8000000000000000,
111     0x8000001f8000001f, 0x8181818181818181, 0x9999999999999999,
112     0x9fff9fff9fff9fff, 0xaaaaaaaaaaaaaaaa, 0xdddddddddddddddd,
113     0xe0000000000001ff, 0xf800000000000000, 0xf8000000000001ff,
114     0xf807f807f807f807, 0xfefefefefefefefe, 0xfffefffefffefffe,
115     0xfffff807fffff807, 0xfffff9fffffff9ff, 0xfffffc0ffffffc0f,
116     0xfffffc0fffffffff, 0xfffffefffffffeff, 0xfffffeffffffffff,
117     0xffffff8000000000, 0xfffffffefffffffe, 0xffffffffefffffff,
118     0xfffffffff9ffffff, 0xffffffffff800000, 0xffffffffffffc0ff,
119     0xfffffffffffffffe};
120
121
122 // ARM64 arithmetic instructions.
123 struct AddSub {
124   MachInst2 mi;
125   ArchOpcode negate_arch_opcode;
126 };
127
128
129 std::ostream& operator<<(std::ostream& os, const AddSub& op) {
130   return os << op.mi;
131 }
132
133
134 static const AddSub kAddSubInstructions[] = {
135     {{&RawMachineAssembler::Int32Add, "Int32Add", kArm64Add32, kMachInt32},
136      kArm64Sub32},
137     {{&RawMachineAssembler::Int64Add, "Int64Add", kArm64Add, kMachInt64},
138      kArm64Sub},
139     {{&RawMachineAssembler::Int32Sub, "Int32Sub", kArm64Sub32, kMachInt32},
140      kArm64Add32},
141     {{&RawMachineAssembler::Int64Sub, "Int64Sub", kArm64Sub, kMachInt64},
142      kArm64Add}};
143
144
145 // ARM64 Add/Sub immediates: 12-bit immediate optionally shifted by 12.
146 // Below is a combination of a random subset and some edge values.
147 static const int32_t kAddSubImmediates[] = {
148     0,        1,        69,       493,      599,      701,      719,
149     768,      818,      842,      945,      1246,     1286,     1429,
150     1669,     2171,     2179,     2182,     2254,     2334,     2338,
151     2343,     2396,     2449,     2610,     2732,     2855,     2876,
152     2944,     3377,     3458,     3475,     3476,     3540,     3574,
153     3601,     3813,     3871,     3917,     4095,     4096,     16384,
154     364544,   462848,   970752,   1523712,  1863680,  2363392,  3219456,
155     3280896,  4247552,  4526080,  4575232,  4960256,  5505024,  5894144,
156     6004736,  6193152,  6385664,  6795264,  7114752,  7233536,  7348224,
157     7499776,  7573504,  7729152,  8634368,  8937472,  9465856,  10354688,
158     10682368, 11059200, 11460608, 13168640, 13176832, 14336000, 15028224,
159     15597568, 15892480, 16773120};
160
161
162 // ARM64 flag setting data processing instructions.
163 static const MachInst2 kDPFlagSetInstructions[] = {
164     {&RawMachineAssembler::Word32And, "Word32And", kArm64Tst32, kMachInt32},
165     {&RawMachineAssembler::Int32Add, "Int32Add", kArm64Cmn32, kMachInt32},
166     {&RawMachineAssembler::Int32Sub, "Int32Sub", kArm64Cmp32, kMachInt32},
167     {&RawMachineAssembler::Word64And, "Word64And", kArm64Tst, kMachInt64}};
168
169
170 // ARM64 arithmetic with overflow instructions.
171 static const MachInst2 kOvfAddSubInstructions[] = {
172     {&RawMachineAssembler::Int32AddWithOverflow, "Int32AddWithOverflow",
173      kArm64Add32, kMachInt32},
174     {&RawMachineAssembler::Int32SubWithOverflow, "Int32SubWithOverflow",
175      kArm64Sub32, kMachInt32}};
176
177
178 // ARM64 shift instructions.
179 static const Shift kShiftInstructions[] = {
180     {{&RawMachineAssembler::Word32Shl, "Word32Shl", kArm64Lsl32, kMachInt32},
181      kMode_Operand2_R_LSL_I},
182     {{&RawMachineAssembler::Word64Shl, "Word64Shl", kArm64Lsl, kMachInt64},
183      kMode_Operand2_R_LSL_I},
184     {{&RawMachineAssembler::Word32Shr, "Word32Shr", kArm64Lsr32, kMachInt32},
185      kMode_Operand2_R_LSR_I},
186     {{&RawMachineAssembler::Word64Shr, "Word64Shr", kArm64Lsr, kMachInt64},
187      kMode_Operand2_R_LSR_I},
188     {{&RawMachineAssembler::Word32Sar, "Word32Sar", kArm64Asr32, kMachInt32},
189      kMode_Operand2_R_ASR_I},
190     {{&RawMachineAssembler::Word64Sar, "Word64Sar", kArm64Asr, kMachInt64},
191      kMode_Operand2_R_ASR_I},
192     {{&RawMachineAssembler::Word32Ror, "Word32Ror", kArm64Ror32, kMachInt32},
193      kMode_Operand2_R_ROR_I},
194     {{&RawMachineAssembler::Word64Ror, "Word64Ror", kArm64Ror, kMachInt64},
195      kMode_Operand2_R_ROR_I}};
196
197
198 // ARM64 Mul/Div instructions.
199 static const MachInst2 kMulDivInstructions[] = {
200     {&RawMachineAssembler::Int32Mul, "Int32Mul", kArm64Mul32, kMachInt32},
201     {&RawMachineAssembler::Int64Mul, "Int64Mul", kArm64Mul, kMachInt64},
202     {&RawMachineAssembler::Int32Div, "Int32Div", kArm64Idiv32, kMachInt32},
203     {&RawMachineAssembler::Int64Div, "Int64Div", kArm64Idiv, kMachInt64},
204     {&RawMachineAssembler::Uint32Div, "Uint32Div", kArm64Udiv32, kMachInt32},
205     {&RawMachineAssembler::Uint64Div, "Uint64Div", kArm64Udiv, kMachInt64}};
206
207
208 // ARM64 FP arithmetic instructions.
209 static const MachInst2 kFPArithInstructions[] = {
210     {&RawMachineAssembler::Float64Add, "Float64Add", kArm64Float64Add,
211      kMachFloat64},
212     {&RawMachineAssembler::Float64Sub, "Float64Sub", kArm64Float64Sub,
213      kMachFloat64},
214     {&RawMachineAssembler::Float64Mul, "Float64Mul", kArm64Float64Mul,
215      kMachFloat64},
216     {&RawMachineAssembler::Float64Div, "Float64Div", kArm64Float64Div,
217      kMachFloat64}};
218
219
220 struct FPCmp {
221   MachInst2 mi;
222   FlagsCondition cond;
223 };
224
225
226 std::ostream& operator<<(std::ostream& os, const FPCmp& cmp) {
227   return os << cmp.mi;
228 }
229
230
231 // ARM64 FP comparison instructions.
232 static const FPCmp kFPCmpInstructions[] = {
233     {{&RawMachineAssembler::Float64Equal, "Float64Equal", kArm64Float64Cmp,
234       kMachFloat64},
235      kUnorderedEqual},
236     {{&RawMachineAssembler::Float64LessThan, "Float64LessThan",
237       kArm64Float64Cmp, kMachFloat64},
238      kUnorderedLessThan},
239     {{&RawMachineAssembler::Float64LessThanOrEqual, "Float64LessThanOrEqual",
240       kArm64Float64Cmp, kMachFloat64},
241      kUnorderedLessThanOrEqual}};
242
243
244 struct Conversion {
245   // The machine_type field in MachInst1 represents the destination type.
246   MachInst1 mi;
247   MachineType src_machine_type;
248 };
249
250
251 std::ostream& operator<<(std::ostream& os, const Conversion& conv) {
252   return os << conv.mi;
253 }
254
255
256 // ARM64 type conversion instructions.
257 static const Conversion kConversionInstructions[] = {
258     {{&RawMachineAssembler::ChangeFloat32ToFloat64, "ChangeFloat32ToFloat64",
259       kArm64Float32ToFloat64, kMachFloat64},
260      kMachFloat32},
261     {{&RawMachineAssembler::TruncateFloat64ToFloat32,
262       "TruncateFloat64ToFloat32", kArm64Float64ToFloat32, kMachFloat32},
263      kMachFloat64},
264     {{&RawMachineAssembler::ChangeInt32ToInt64, "ChangeInt32ToInt64",
265       kArm64Sxtw, kMachInt64},
266      kMachInt32},
267     {{&RawMachineAssembler::ChangeUint32ToUint64, "ChangeUint32ToUint64",
268       kArm64Mov32, kMachUint64},
269      kMachUint32},
270     {{&RawMachineAssembler::TruncateInt64ToInt32, "TruncateInt64ToInt32",
271       kArm64Mov32, kMachInt32},
272      kMachInt64},
273     {{&RawMachineAssembler::ChangeInt32ToFloat64, "ChangeInt32ToFloat64",
274       kArm64Int32ToFloat64, kMachFloat64},
275      kMachInt32},
276     {{&RawMachineAssembler::ChangeUint32ToFloat64, "ChangeUint32ToFloat64",
277       kArm64Uint32ToFloat64, kMachFloat64},
278      kMachUint32},
279     {{&RawMachineAssembler::ChangeFloat64ToInt32, "ChangeFloat64ToInt32",
280       kArm64Float64ToInt32, kMachInt32},
281      kMachFloat64},
282     {{&RawMachineAssembler::ChangeFloat64ToUint32, "ChangeFloat64ToUint32",
283       kArm64Float64ToUint32, kMachUint32},
284      kMachFloat64}};
285
286 }  // namespace
287
288
289 // -----------------------------------------------------------------------------
290 // Logical instructions.
291
292
293 typedef InstructionSelectorTestWithParam<MachInst2>
294     InstructionSelectorLogicalTest;
295
296
297 TEST_P(InstructionSelectorLogicalTest, Parameter) {
298   const MachInst2 dpi = GetParam();
299   const MachineType type = dpi.machine_type;
300   StreamBuilder m(this, type, type, type);
301   m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)));
302   Stream s = m.Build();
303   ASSERT_EQ(1U, s.size());
304   EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
305   EXPECT_EQ(2U, s[0]->InputCount());
306   EXPECT_EQ(1U, s[0]->OutputCount());
307 }
308
309
310 TEST_P(InstructionSelectorLogicalTest, Immediate) {
311   const MachInst2 dpi = GetParam();
312   const MachineType type = dpi.machine_type;
313   // TODO(all): Add support for testing 64-bit immediates.
314   if (type == kMachInt32) {
315     // Immediate on the right.
316     TRACED_FOREACH(int32_t, imm, kLogical32Immediates) {
317       StreamBuilder m(this, type, type);
318       m.Return((m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm)));
319       Stream s = m.Build();
320       ASSERT_EQ(1U, s.size());
321       EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
322       ASSERT_EQ(2U, s[0]->InputCount());
323       EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
324       EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
325       EXPECT_EQ(1U, s[0]->OutputCount());
326     }
327
328     // Immediate on the left; all logical ops should commute.
329     TRACED_FOREACH(int32_t, imm, kLogical32Immediates) {
330       StreamBuilder m(this, type, type);
331       m.Return((m.*dpi.constructor)(m.Int32Constant(imm), m.Parameter(0)));
332       Stream s = m.Build();
333       ASSERT_EQ(1U, s.size());
334       EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
335       ASSERT_EQ(2U, s[0]->InputCount());
336       EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
337       EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
338       EXPECT_EQ(1U, s[0]->OutputCount());
339     }
340   }
341 }
342
343
344 TEST_P(InstructionSelectorLogicalTest, ShiftByImmediate) {
345   const MachInst2 dpi = GetParam();
346   const MachineType type = dpi.machine_type;
347   TRACED_FOREACH(Shift, shift, kShiftInstructions) {
348     // Only test 64-bit shifted operands with 64-bit instructions.
349     if (shift.mi.machine_type != type) continue;
350
351     TRACED_FORRANGE(int, imm, 0, ((type == kMachInt32) ? 31 : 63)) {
352       StreamBuilder m(this, type, type, type);
353       m.Return((m.*dpi.constructor)(
354           m.Parameter(0),
355           (m.*shift.mi.constructor)(m.Parameter(1),
356                                     BuildConstant(m, type, imm))));
357       Stream s = m.Build();
358       ASSERT_EQ(1U, s.size());
359       EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
360       EXPECT_EQ(shift.mode, s[0]->addressing_mode());
361       EXPECT_EQ(3U, s[0]->InputCount());
362       EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(2)));
363       EXPECT_EQ(1U, s[0]->OutputCount());
364     }
365
366     TRACED_FORRANGE(int, imm, 0, ((type == kMachInt32) ? 31 : 63)) {
367       StreamBuilder m(this, type, type, type);
368       m.Return((m.*dpi.constructor)(
369           (m.*shift.mi.constructor)(m.Parameter(1),
370                                     BuildConstant(m, type, imm)),
371           m.Parameter(0)));
372       Stream s = m.Build();
373       ASSERT_EQ(1U, s.size());
374       EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
375       EXPECT_EQ(shift.mode, s[0]->addressing_mode());
376       EXPECT_EQ(3U, s[0]->InputCount());
377       EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(2)));
378       EXPECT_EQ(1U, s[0]->OutputCount());
379     }
380   }
381 }
382
383
384 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorLogicalTest,
385                         ::testing::ValuesIn(kLogicalInstructions));
386
387
388 // -----------------------------------------------------------------------------
389 // Add and Sub instructions.
390
391 typedef InstructionSelectorTestWithParam<AddSub> InstructionSelectorAddSubTest;
392
393
394 TEST_P(InstructionSelectorAddSubTest, Parameter) {
395   const AddSub dpi = GetParam();
396   const MachineType type = dpi.mi.machine_type;
397   StreamBuilder m(this, type, type, type);
398   m.Return((m.*dpi.mi.constructor)(m.Parameter(0), m.Parameter(1)));
399   Stream s = m.Build();
400   ASSERT_EQ(1U, s.size());
401   EXPECT_EQ(dpi.mi.arch_opcode, s[0]->arch_opcode());
402   EXPECT_EQ(2U, s[0]->InputCount());
403   EXPECT_EQ(1U, s[0]->OutputCount());
404 }
405
406
407 TEST_P(InstructionSelectorAddSubTest, ImmediateOnRight) {
408   const AddSub dpi = GetParam();
409   const MachineType type = dpi.mi.machine_type;
410   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
411     StreamBuilder m(this, type, type);
412     m.Return(
413         (m.*dpi.mi.constructor)(m.Parameter(0), BuildConstant(m, type, imm)));
414     Stream s = m.Build();
415     ASSERT_EQ(1U, s.size());
416     EXPECT_EQ(dpi.mi.arch_opcode, s[0]->arch_opcode());
417     ASSERT_EQ(2U, s[0]->InputCount());
418     EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
419     EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(1)));
420     EXPECT_EQ(1U, s[0]->OutputCount());
421   }
422 }
423
424
425 TEST_P(InstructionSelectorAddSubTest, NegImmediateOnRight) {
426   const AddSub dpi = GetParam();
427   const MachineType type = dpi.mi.machine_type;
428   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
429     if (imm == 0) continue;
430     StreamBuilder m(this, type, type);
431     m.Return(
432         (m.*dpi.mi.constructor)(m.Parameter(0), BuildConstant(m, type, -imm)));
433     Stream s = m.Build();
434     ASSERT_EQ(1U, s.size());
435     EXPECT_EQ(dpi.negate_arch_opcode, s[0]->arch_opcode());
436     ASSERT_EQ(2U, s[0]->InputCount());
437     ASSERT_TRUE(s[0]->InputAt(1)->IsImmediate());
438     EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
439     EXPECT_EQ(1U, s[0]->OutputCount());
440   }
441 }
442
443
444 TEST_P(InstructionSelectorAddSubTest, ShiftByImmediateOnRight) {
445   const AddSub dpi = GetParam();
446   const MachineType type = dpi.mi.machine_type;
447   TRACED_FOREACH(Shift, shift, kShiftInstructions) {
448     // Only test 64-bit shifted operands with 64-bit instructions.
449     if (shift.mi.machine_type != type) continue;
450
451     if ((shift.mi.arch_opcode == kArm64Ror32) ||
452         (shift.mi.arch_opcode == kArm64Ror)) {
453       // Not supported by add/sub instructions.
454       continue;
455     }
456
457     TRACED_FORRANGE(int, imm, 0, ((type == kMachInt32) ? 31 : 63)) {
458       StreamBuilder m(this, type, type, type);
459       m.Return((m.*dpi.mi.constructor)(
460           m.Parameter(0),
461           (m.*shift.mi.constructor)(m.Parameter(1),
462                                     BuildConstant(m, type, imm))));
463       Stream s = m.Build();
464       ASSERT_EQ(1U, s.size());
465       EXPECT_EQ(dpi.mi.arch_opcode, s[0]->arch_opcode());
466       EXPECT_EQ(shift.mode, s[0]->addressing_mode());
467       EXPECT_EQ(3U, s[0]->InputCount());
468       EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(2)));
469       EXPECT_EQ(1U, s[0]->OutputCount());
470     }
471   }
472 }
473
474
475 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorAddSubTest,
476                         ::testing::ValuesIn(kAddSubInstructions));
477
478
479 TEST_F(InstructionSelectorTest, AddImmediateOnLeft) {
480   {
481     // 32-bit add.
482     TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
483       StreamBuilder m(this, kMachInt32, kMachInt32);
484       m.Return(m.Int32Add(m.Int32Constant(imm), m.Parameter(0)));
485       Stream s = m.Build();
486       ASSERT_EQ(1U, s.size());
487       EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
488       ASSERT_EQ(2U, s[0]->InputCount());
489       EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
490       EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
491       EXPECT_EQ(1U, s[0]->OutputCount());
492     }
493   }
494   {
495     // 64-bit add.
496     TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
497       StreamBuilder m(this, kMachInt64, kMachInt64);
498       m.Return(m.Int64Add(m.Int64Constant(imm), m.Parameter(0)));
499       Stream s = m.Build();
500       ASSERT_EQ(1U, s.size());
501       EXPECT_EQ(kArm64Add, s[0]->arch_opcode());
502       ASSERT_EQ(2U, s[0]->InputCount());
503       EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
504       EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(1)));
505       EXPECT_EQ(1U, s[0]->OutputCount());
506     }
507   }
508 }
509
510
511 TEST_F(InstructionSelectorTest, SubZeroOnLeft) {
512   // Subtraction with zero on the left maps to Neg.
513   {
514     // 32-bit subtract.
515     StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
516     m.Return(m.Int32Sub(m.Int32Constant(0), m.Parameter(0)));
517     Stream s = m.Build();
518
519     ASSERT_EQ(1U, s.size());
520     EXPECT_EQ(kArm64Neg32, s[0]->arch_opcode());
521     EXPECT_EQ(1U, s[0]->InputCount());
522     EXPECT_EQ(1U, s[0]->OutputCount());
523   }
524   {
525     // 64-bit subtract.
526     StreamBuilder m(this, kMachInt64, kMachInt64, kMachInt64);
527     m.Return(m.Int64Sub(m.Int64Constant(0), m.Parameter(0)));
528     Stream s = m.Build();
529
530     ASSERT_EQ(1U, s.size());
531     EXPECT_EQ(kArm64Neg, s[0]->arch_opcode());
532     EXPECT_EQ(1U, s[0]->InputCount());
533     EXPECT_EQ(1U, s[0]->OutputCount());
534   }
535 }
536
537
538 TEST_F(InstructionSelectorTest, AddNegImmediateOnLeft) {
539   {
540     // 32-bit add.
541     TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
542       if (imm == 0) continue;
543       StreamBuilder m(this, kMachInt32, kMachInt32);
544       m.Return(m.Int32Add(m.Int32Constant(-imm), m.Parameter(0)));
545       Stream s = m.Build();
546
547       ASSERT_EQ(1U, s.size());
548       EXPECT_EQ(kArm64Sub32, s[0]->arch_opcode());
549       ASSERT_EQ(2U, s[0]->InputCount());
550       ASSERT_TRUE(s[0]->InputAt(1)->IsImmediate());
551       EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
552       EXPECT_EQ(1U, s[0]->OutputCount());
553     }
554   }
555   {
556     // 64-bit add.
557     TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
558       if (imm == 0) continue;
559       StreamBuilder m(this, kMachInt64, kMachInt64);
560       m.Return(m.Int64Add(m.Int64Constant(-imm), m.Parameter(0)));
561       Stream s = m.Build();
562
563       ASSERT_EQ(1U, s.size());
564       EXPECT_EQ(kArm64Sub, s[0]->arch_opcode());
565       ASSERT_EQ(2U, s[0]->InputCount());
566       ASSERT_TRUE(s[0]->InputAt(1)->IsImmediate());
567       EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(1)));
568       EXPECT_EQ(1U, s[0]->OutputCount());
569     }
570   }
571 }
572
573
574 TEST_F(InstructionSelectorTest, AddShiftByImmediateOnLeft) {
575   // 32-bit add.
576   TRACED_FOREACH(Shift, shift, kShiftInstructions) {
577     // Only test relevant shifted operands.
578     if (shift.mi.machine_type != kMachInt32) continue;
579     if (shift.mi.arch_opcode == kArm64Ror32) continue;
580
581     TRACED_FORRANGE(int, imm, 0, 31) {
582       StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
583       m.Return((m.Int32Add)(
584           (m.*shift.mi.constructor)(m.Parameter(1), m.Int32Constant(imm)),
585           m.Parameter(0)));
586       Stream s = m.Build();
587       ASSERT_EQ(1U, s.size());
588       EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
589       EXPECT_EQ(shift.mode, s[0]->addressing_mode());
590       EXPECT_EQ(3U, s[0]->InputCount());
591       EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(2)));
592       EXPECT_EQ(1U, s[0]->OutputCount());
593     }
594   }
595
596   // 64-bit add.
597   TRACED_FOREACH(Shift, shift, kShiftInstructions) {
598     // Only test relevant shifted operands.
599     if (shift.mi.machine_type != kMachInt64) continue;
600     if (shift.mi.arch_opcode == kArm64Ror) continue;
601
602     TRACED_FORRANGE(int, imm, 0, 63) {
603       StreamBuilder m(this, kMachInt64, kMachInt64, kMachInt64);
604       m.Return((m.Int64Add)(
605           (m.*shift.mi.constructor)(m.Parameter(1), m.Int64Constant(imm)),
606           m.Parameter(0)));
607       Stream s = m.Build();
608       ASSERT_EQ(1U, s.size());
609       EXPECT_EQ(kArm64Add, s[0]->arch_opcode());
610       EXPECT_EQ(shift.mode, s[0]->addressing_mode());
611       EXPECT_EQ(3U, s[0]->InputCount());
612       EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(2)));
613       EXPECT_EQ(1U, s[0]->OutputCount());
614     }
615   }
616 }
617
618
619 // -----------------------------------------------------------------------------
620 // Data processing controlled branches.
621
622
623 typedef InstructionSelectorTestWithParam<MachInst2>
624     InstructionSelectorDPFlagSetTest;
625
626
627 TEST_P(InstructionSelectorDPFlagSetTest, BranchWithParameters) {
628   const MachInst2 dpi = GetParam();
629   const MachineType type = dpi.machine_type;
630   StreamBuilder m(this, type, type, type);
631   MLabel a, b;
632   m.Branch((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)), &a, &b);
633   m.Bind(&a);
634   m.Return(m.Int32Constant(1));
635   m.Bind(&b);
636   m.Return(m.Int32Constant(0));
637   Stream s = m.Build();
638   ASSERT_EQ(1U, s.size());
639   EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
640   EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
641   EXPECT_EQ(kNotEqual, s[0]->flags_condition());
642 }
643
644
645 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
646                         InstructionSelectorDPFlagSetTest,
647                         ::testing::ValuesIn(kDPFlagSetInstructions));
648
649
650 TEST_F(InstructionSelectorTest, Word32AndBranchWithImmediateOnRight) {
651   TRACED_FOREACH(int32_t, imm, kLogical32Immediates) {
652     // Skip the cases where the instruction selector would use tbz/tbnz.
653     if (base::bits::CountPopulation32(imm) == 1) continue;
654
655     StreamBuilder m(this, kMachInt32, kMachInt32);
656     MLabel a, b;
657     m.Branch(m.Word32And(m.Parameter(0), m.Int32Constant(imm)), &a, &b);
658     m.Bind(&a);
659     m.Return(m.Int32Constant(1));
660     m.Bind(&b);
661     m.Return(m.Int32Constant(0));
662     Stream s = m.Build();
663     ASSERT_EQ(1U, s.size());
664     EXPECT_EQ(kArm64Tst32, s[0]->arch_opcode());
665     EXPECT_EQ(4U, s[0]->InputCount());
666     EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
667     EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
668     EXPECT_EQ(kNotEqual, s[0]->flags_condition());
669   }
670 }
671
672
673 TEST_F(InstructionSelectorTest, Word64AndBranchWithImmediateOnRight) {
674   TRACED_FOREACH(int64_t, imm, kLogical64Immediates) {
675     // Skip the cases where the instruction selector would use tbz/tbnz.
676     if (base::bits::CountPopulation64(imm) == 1) continue;
677
678     StreamBuilder m(this, kMachInt64, kMachInt64);
679     MLabel a, b;
680     m.Branch(m.Word64And(m.Parameter(0), m.Int64Constant(imm)), &a, &b);
681     m.Bind(&a);
682     m.Return(m.Int32Constant(1));
683     m.Bind(&b);
684     m.Return(m.Int32Constant(0));
685     Stream s = m.Build();
686     ASSERT_EQ(1U, s.size());
687     EXPECT_EQ(kArm64Tst, s[0]->arch_opcode());
688     EXPECT_EQ(4U, s[0]->InputCount());
689     EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
690     EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
691     EXPECT_EQ(kNotEqual, s[0]->flags_condition());
692   }
693 }
694
695
696 TEST_F(InstructionSelectorTest, AddBranchWithImmediateOnRight) {
697   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
698     StreamBuilder m(this, kMachInt32, kMachInt32);
699     MLabel a, b;
700     m.Branch(m.Int32Add(m.Parameter(0), m.Int32Constant(imm)), &a, &b);
701     m.Bind(&a);
702     m.Return(m.Int32Constant(1));
703     m.Bind(&b);
704     m.Return(m.Int32Constant(0));
705     Stream s = m.Build();
706     ASSERT_EQ(1U, s.size());
707     EXPECT_EQ(kArm64Cmn32, s[0]->arch_opcode());
708     EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
709     EXPECT_EQ(kNotEqual, s[0]->flags_condition());
710   }
711 }
712
713
714 TEST_F(InstructionSelectorTest, SubBranchWithImmediateOnRight) {
715   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
716     StreamBuilder m(this, kMachInt32, kMachInt32);
717     MLabel a, b;
718     m.Branch(m.Int32Sub(m.Parameter(0), m.Int32Constant(imm)), &a, &b);
719     m.Bind(&a);
720     m.Return(m.Int32Constant(1));
721     m.Bind(&b);
722     m.Return(m.Int32Constant(0));
723     Stream s = m.Build();
724     ASSERT_EQ(1U, s.size());
725     EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode());
726     EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
727     EXPECT_EQ(kNotEqual, s[0]->flags_condition());
728   }
729 }
730
731
732 TEST_F(InstructionSelectorTest, Word32AndBranchWithImmediateOnLeft) {
733   TRACED_FOREACH(int32_t, imm, kLogical32Immediates) {
734     // Skip the cases where the instruction selector would use tbz/tbnz.
735     if (base::bits::CountPopulation32(imm) == 1) continue;
736
737     StreamBuilder m(this, kMachInt32, kMachInt32);
738     MLabel a, b;
739     m.Branch(m.Word32And(m.Int32Constant(imm), m.Parameter(0)), &a, &b);
740     m.Bind(&a);
741     m.Return(m.Int32Constant(1));
742     m.Bind(&b);
743     m.Return(m.Int32Constant(0));
744     Stream s = m.Build();
745     ASSERT_EQ(1U, s.size());
746     EXPECT_EQ(kArm64Tst32, s[0]->arch_opcode());
747     EXPECT_EQ(4U, s[0]->InputCount());
748     EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
749     ASSERT_LE(1U, s[0]->InputCount());
750     EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
751     EXPECT_EQ(kNotEqual, s[0]->flags_condition());
752   }
753 }
754
755
756 TEST_F(InstructionSelectorTest, Word64AndBranchWithImmediateOnLeft) {
757   TRACED_FOREACH(int64_t, imm, kLogical64Immediates) {
758     // Skip the cases where the instruction selector would use tbz/tbnz.
759     if (base::bits::CountPopulation64(imm) == 1) continue;
760
761     StreamBuilder m(this, kMachInt64, kMachInt64);
762     MLabel a, b;
763     m.Branch(m.Word64And(m.Int64Constant(imm), m.Parameter(0)), &a, &b);
764     m.Bind(&a);
765     m.Return(m.Int32Constant(1));
766     m.Bind(&b);
767     m.Return(m.Int32Constant(0));
768     Stream s = m.Build();
769     ASSERT_EQ(1U, s.size());
770     EXPECT_EQ(kArm64Tst, s[0]->arch_opcode());
771     EXPECT_EQ(4U, s[0]->InputCount());
772     EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
773     ASSERT_LE(1U, s[0]->InputCount());
774     EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
775     EXPECT_EQ(kNotEqual, s[0]->flags_condition());
776   }
777 }
778
779
780 TEST_F(InstructionSelectorTest, AddBranchWithImmediateOnLeft) {
781   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
782     StreamBuilder m(this, kMachInt32, kMachInt32);
783     MLabel a, b;
784     m.Branch(m.Int32Add(m.Int32Constant(imm), m.Parameter(0)), &a, &b);
785     m.Bind(&a);
786     m.Return(m.Int32Constant(1));
787     m.Bind(&b);
788     m.Return(m.Int32Constant(0));
789     Stream s = m.Build();
790     ASSERT_EQ(1U, s.size());
791     EXPECT_EQ(kArm64Cmn32, s[0]->arch_opcode());
792     ASSERT_LE(1U, s[0]->InputCount());
793     EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
794     EXPECT_EQ(kNotEqual, s[0]->flags_condition());
795   }
796 }
797
798
799 TEST_F(InstructionSelectorTest, Word32AndBranchWithOneBitMaskOnRight) {
800   TRACED_FORRANGE(int, bit, 0, 31) {
801     uint32_t mask = 1 << bit;
802     StreamBuilder m(this, kMachInt32, kMachInt32);
803     MLabel a, b;
804     m.Branch(m.Word32And(m.Parameter(0), m.Int32Constant(mask)), &a, &b);
805     m.Bind(&a);
806     m.Return(m.Int32Constant(1));
807     m.Bind(&b);
808     m.Return(m.Int32Constant(0));
809     Stream s = m.Build();
810     ASSERT_EQ(1U, s.size());
811     EXPECT_EQ(kArm64Tbnz32, s[0]->arch_opcode());
812     EXPECT_EQ(4U, s[0]->InputCount());
813     EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
814     EXPECT_EQ(bit, s.ToInt32(s[0]->InputAt(1)));
815   }
816
817   TRACED_FORRANGE(int, bit, 0, 31) {
818     uint32_t mask = 1 << bit;
819     StreamBuilder m(this, kMachInt32, kMachInt32);
820     MLabel a, b;
821     m.Branch(
822         m.Word32BinaryNot(m.Word32And(m.Parameter(0), m.Int32Constant(mask))),
823         &a, &b);
824     m.Bind(&a);
825     m.Return(m.Int32Constant(1));
826     m.Bind(&b);
827     m.Return(m.Int32Constant(0));
828     Stream s = m.Build();
829     ASSERT_EQ(1U, s.size());
830     EXPECT_EQ(kArm64Tbz32, s[0]->arch_opcode());
831     EXPECT_EQ(4U, s[0]->InputCount());
832     EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
833     EXPECT_EQ(bit, s.ToInt32(s[0]->InputAt(1)));
834   }
835 }
836
837
838 TEST_F(InstructionSelectorTest, Word32AndBranchWithOneBitMaskOnLeft) {
839   TRACED_FORRANGE(int, bit, 0, 31) {
840     uint32_t mask = 1 << bit;
841     StreamBuilder m(this, kMachInt32, kMachInt32);
842     MLabel a, b;
843     m.Branch(m.Word32And(m.Int32Constant(mask), m.Parameter(0)), &a, &b);
844     m.Bind(&a);
845     m.Return(m.Int32Constant(1));
846     m.Bind(&b);
847     m.Return(m.Int32Constant(0));
848     Stream s = m.Build();
849     ASSERT_EQ(1U, s.size());
850     EXPECT_EQ(kArm64Tbnz32, s[0]->arch_opcode());
851     EXPECT_EQ(4U, s[0]->InputCount());
852     EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
853     EXPECT_EQ(bit, s.ToInt32(s[0]->InputAt(1)));
854   }
855
856   TRACED_FORRANGE(int, bit, 0, 31) {
857     uint32_t mask = 1 << bit;
858     StreamBuilder m(this, kMachInt32, kMachInt32);
859     MLabel a, b;
860     m.Branch(
861         m.Word32BinaryNot(m.Word32And(m.Int32Constant(mask), m.Parameter(0))),
862         &a, &b);
863     m.Bind(&a);
864     m.Return(m.Int32Constant(1));
865     m.Bind(&b);
866     m.Return(m.Int32Constant(0));
867     Stream s = m.Build();
868     ASSERT_EQ(1U, s.size());
869     EXPECT_EQ(kArm64Tbz32, s[0]->arch_opcode());
870     EXPECT_EQ(4U, s[0]->InputCount());
871     EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
872     EXPECT_EQ(bit, s.ToInt32(s[0]->InputAt(1)));
873   }
874 }
875
876
877 TEST_F(InstructionSelectorTest, Word64AndBranchWithOneBitMaskOnRight) {
878   TRACED_FORRANGE(int, bit, 0, 63) {
879     uint64_t mask = 1L << bit;
880     StreamBuilder m(this, kMachInt64, kMachInt64);
881     MLabel a, b;
882     m.Branch(m.Word64And(m.Parameter(0), m.Int64Constant(mask)), &a, &b);
883     m.Bind(&a);
884     m.Return(m.Int32Constant(1));
885     m.Bind(&b);
886     m.Return(m.Int32Constant(0));
887     Stream s = m.Build();
888     ASSERT_EQ(1U, s.size());
889     EXPECT_EQ(kArm64Tbnz, s[0]->arch_opcode());
890     EXPECT_EQ(4U, s[0]->InputCount());
891     EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
892     EXPECT_EQ(bit, s.ToInt64(s[0]->InputAt(1)));
893   }
894
895   TRACED_FORRANGE(int, bit, 0, 63) {
896     uint64_t mask = 1L << bit;
897     StreamBuilder m(this, kMachInt64, kMachInt64);
898     MLabel a, b;
899     m.Branch(
900         m.Word64BinaryNot(m.Word64And(m.Parameter(0), m.Int64Constant(mask))),
901         &a, &b);
902     m.Bind(&a);
903     m.Return(m.Int32Constant(1));
904     m.Bind(&b);
905     m.Return(m.Int32Constant(0));
906     Stream s = m.Build();
907     ASSERT_EQ(1U, s.size());
908     EXPECT_EQ(kArm64Tbz, s[0]->arch_opcode());
909     EXPECT_EQ(4U, s[0]->InputCount());
910     EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
911     EXPECT_EQ(bit, s.ToInt64(s[0]->InputAt(1)));
912   }
913 }
914
915
916 TEST_F(InstructionSelectorTest, Word64AndBranchWithOneBitMaskOnLeft) {
917   TRACED_FORRANGE(int, bit, 0, 63) {
918     uint64_t mask = 1L << bit;
919     StreamBuilder m(this, kMachInt64, kMachInt64);
920     MLabel a, b;
921     m.Branch(m.Word64And(m.Int64Constant(mask), m.Parameter(0)), &a, &b);
922     m.Bind(&a);
923     m.Return(m.Int32Constant(1));
924     m.Bind(&b);
925     m.Return(m.Int32Constant(0));
926     Stream s = m.Build();
927     ASSERT_EQ(1U, s.size());
928     EXPECT_EQ(kArm64Tbnz, s[0]->arch_opcode());
929     EXPECT_EQ(4U, s[0]->InputCount());
930     EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
931     EXPECT_EQ(bit, s.ToInt64(s[0]->InputAt(1)));
932   }
933
934   TRACED_FORRANGE(int, bit, 0, 63) {
935     uint64_t mask = 1L << bit;
936     StreamBuilder m(this, kMachInt64, kMachInt64);
937     MLabel a, b;
938     m.Branch(
939         m.Word64BinaryNot(m.Word64And(m.Int64Constant(mask), m.Parameter(0))),
940         &a, &b);
941     m.Bind(&a);
942     m.Return(m.Int32Constant(1));
943     m.Bind(&b);
944     m.Return(m.Int32Constant(0));
945     Stream s = m.Build();
946     ASSERT_EQ(1U, s.size());
947     EXPECT_EQ(kArm64Tbz, s[0]->arch_opcode());
948     EXPECT_EQ(4U, s[0]->InputCount());
949     EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
950     EXPECT_EQ(bit, s.ToInt64(s[0]->InputAt(1)));
951   }
952 }
953
954
955 // -----------------------------------------------------------------------------
956 // Add and subtract instructions with overflow.
957
958
959 typedef InstructionSelectorTestWithParam<MachInst2>
960     InstructionSelectorOvfAddSubTest;
961
962
963 TEST_P(InstructionSelectorOvfAddSubTest, OvfParameter) {
964   const MachInst2 dpi = GetParam();
965   const MachineType type = dpi.machine_type;
966   StreamBuilder m(this, type, type, type);
967   m.Return(
968       m.Projection(1, (m.*dpi.constructor)(m.Parameter(0), m.Parameter(1))));
969   Stream s = m.Build();
970   ASSERT_EQ(1U, s.size());
971   EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
972   EXPECT_EQ(2U, s[0]->InputCount());
973   EXPECT_LE(1U, s[0]->OutputCount());
974   EXPECT_EQ(kFlags_set, s[0]->flags_mode());
975   EXPECT_EQ(kOverflow, s[0]->flags_condition());
976 }
977
978
979 TEST_P(InstructionSelectorOvfAddSubTest, OvfImmediateOnRight) {
980   const MachInst2 dpi = GetParam();
981   const MachineType type = dpi.machine_type;
982   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
983     StreamBuilder m(this, type, type);
984     m.Return(m.Projection(
985         1, (m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm))));
986     Stream s = m.Build();
987     ASSERT_EQ(1U, s.size());
988     EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
989     ASSERT_EQ(2U, s[0]->InputCount());
990     EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
991     EXPECT_LE(1U, s[0]->OutputCount());
992     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
993     EXPECT_EQ(kOverflow, s[0]->flags_condition());
994   }
995 }
996
997
998 TEST_P(InstructionSelectorOvfAddSubTest, ValParameter) {
999   const MachInst2 dpi = GetParam();
1000   const MachineType type = dpi.machine_type;
1001   StreamBuilder m(this, type, type, type);
1002   m.Return(
1003       m.Projection(0, (m.*dpi.constructor)(m.Parameter(0), m.Parameter(1))));
1004   Stream s = m.Build();
1005   ASSERT_EQ(1U, s.size());
1006   EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
1007   EXPECT_EQ(2U, s[0]->InputCount());
1008   EXPECT_LE(1U, s[0]->OutputCount());
1009   EXPECT_EQ(kFlags_none, s[0]->flags_mode());
1010 }
1011
1012
1013 TEST_P(InstructionSelectorOvfAddSubTest, ValImmediateOnRight) {
1014   const MachInst2 dpi = GetParam();
1015   const MachineType type = dpi.machine_type;
1016   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
1017     StreamBuilder m(this, type, type);
1018     m.Return(m.Projection(
1019         0, (m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm))));
1020     Stream s = m.Build();
1021     ASSERT_EQ(1U, s.size());
1022     EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
1023     ASSERT_EQ(2U, s[0]->InputCount());
1024     EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
1025     EXPECT_LE(1U, s[0]->OutputCount());
1026     EXPECT_EQ(kFlags_none, s[0]->flags_mode());
1027   }
1028 }
1029
1030
1031 TEST_P(InstructionSelectorOvfAddSubTest, BothParameter) {
1032   const MachInst2 dpi = GetParam();
1033   const MachineType type = dpi.machine_type;
1034   StreamBuilder m(this, type, type, type);
1035   Node* n = (m.*dpi.constructor)(m.Parameter(0), m.Parameter(1));
1036   m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n)));
1037   Stream s = m.Build();
1038   ASSERT_LE(1U, s.size());
1039   EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
1040   EXPECT_EQ(2U, s[0]->InputCount());
1041   EXPECT_EQ(2U, s[0]->OutputCount());
1042   EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1043   EXPECT_EQ(kOverflow, s[0]->flags_condition());
1044 }
1045
1046
1047 TEST_P(InstructionSelectorOvfAddSubTest, BothImmediateOnRight) {
1048   const MachInst2 dpi = GetParam();
1049   const MachineType type = dpi.machine_type;
1050   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
1051     StreamBuilder m(this, type, type);
1052     Node* n = (m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm));
1053     m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n)));
1054     Stream s = m.Build();
1055     ASSERT_LE(1U, s.size());
1056     EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
1057     ASSERT_EQ(2U, s[0]->InputCount());
1058     EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
1059     EXPECT_EQ(2U, s[0]->OutputCount());
1060     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1061     EXPECT_EQ(kOverflow, s[0]->flags_condition());
1062   }
1063 }
1064
1065
1066 TEST_P(InstructionSelectorOvfAddSubTest, BranchWithParameters) {
1067   const MachInst2 dpi = GetParam();
1068   const MachineType type = dpi.machine_type;
1069   StreamBuilder m(this, type, type, type);
1070   MLabel a, b;
1071   Node* n = (m.*dpi.constructor)(m.Parameter(0), m.Parameter(1));
1072   m.Branch(m.Projection(1, n), &a, &b);
1073   m.Bind(&a);
1074   m.Return(m.Int32Constant(0));
1075   m.Bind(&b);
1076   m.Return(m.Projection(0, n));
1077   Stream s = m.Build();
1078   ASSERT_EQ(1U, s.size());
1079   EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
1080   EXPECT_EQ(4U, s[0]->InputCount());
1081   EXPECT_EQ(1U, s[0]->OutputCount());
1082   EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
1083   EXPECT_EQ(kOverflow, s[0]->flags_condition());
1084 }
1085
1086
1087 TEST_P(InstructionSelectorOvfAddSubTest, BranchWithImmediateOnRight) {
1088   const MachInst2 dpi = GetParam();
1089   const MachineType type = dpi.machine_type;
1090   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
1091     StreamBuilder m(this, type, type);
1092     MLabel a, b;
1093     Node* n = (m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm));
1094     m.Branch(m.Projection(1, n), &a, &b);
1095     m.Bind(&a);
1096     m.Return(m.Int32Constant(0));
1097     m.Bind(&b);
1098     m.Return(m.Projection(0, n));
1099     Stream s = m.Build();
1100     ASSERT_EQ(1U, s.size());
1101     EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
1102     ASSERT_EQ(4U, s[0]->InputCount());
1103     EXPECT_EQ(1U, s[0]->OutputCount());
1104     EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
1105     EXPECT_EQ(kOverflow, s[0]->flags_condition());
1106   }
1107 }
1108
1109
1110 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1111                         InstructionSelectorOvfAddSubTest,
1112                         ::testing::ValuesIn(kOvfAddSubInstructions));
1113
1114
1115 TEST_F(InstructionSelectorTest, OvfFlagAddImmediateOnLeft) {
1116   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
1117     StreamBuilder m(this, kMachInt32, kMachInt32);
1118     m.Return(m.Projection(
1119         1, m.Int32AddWithOverflow(m.Int32Constant(imm), m.Parameter(0))));
1120     Stream s = m.Build();
1121
1122     ASSERT_EQ(1U, s.size());
1123     EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
1124     EXPECT_EQ(2U, s[0]->InputCount());
1125     EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
1126     EXPECT_LE(1U, s[0]->OutputCount());
1127     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1128     EXPECT_EQ(kOverflow, s[0]->flags_condition());
1129   }
1130 }
1131
1132
1133 TEST_F(InstructionSelectorTest, OvfValAddImmediateOnLeft) {
1134   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
1135     StreamBuilder m(this, kMachInt32, kMachInt32);
1136     m.Return(m.Projection(
1137         0, m.Int32AddWithOverflow(m.Int32Constant(imm), m.Parameter(0))));
1138     Stream s = m.Build();
1139
1140     ASSERT_EQ(1U, s.size());
1141     EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
1142     ASSERT_EQ(2U, s[0]->InputCount());
1143     EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
1144     EXPECT_LE(1U, s[0]->OutputCount());
1145     EXPECT_EQ(kFlags_none, s[0]->flags_mode());
1146   }
1147 }
1148
1149
1150 TEST_F(InstructionSelectorTest, OvfBothAddImmediateOnLeft) {
1151   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
1152     StreamBuilder m(this, kMachInt32, kMachInt32);
1153     Node* n = m.Int32AddWithOverflow(m.Int32Constant(imm), m.Parameter(0));
1154     m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n)));
1155     Stream s = m.Build();
1156
1157     ASSERT_LE(1U, s.size());
1158     EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
1159     ASSERT_EQ(2U, s[0]->InputCount());
1160     EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
1161     EXPECT_EQ(2U, s[0]->OutputCount());
1162     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1163     EXPECT_EQ(kOverflow, s[0]->flags_condition());
1164   }
1165 }
1166
1167
1168 TEST_F(InstructionSelectorTest, OvfBranchWithImmediateOnLeft) {
1169   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
1170     StreamBuilder m(this, kMachInt32, kMachInt32);
1171     MLabel a, b;
1172     Node* n = m.Int32AddWithOverflow(m.Int32Constant(imm), m.Parameter(0));
1173     m.Branch(m.Projection(1, n), &a, &b);
1174     m.Bind(&a);
1175     m.Return(m.Int32Constant(0));
1176     m.Bind(&b);
1177     m.Return(m.Projection(0, n));
1178     Stream s = m.Build();
1179
1180     ASSERT_EQ(1U, s.size());
1181     EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
1182     ASSERT_EQ(4U, s[0]->InputCount());
1183     EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
1184     EXPECT_EQ(1U, s[0]->OutputCount());
1185     EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
1186     EXPECT_EQ(kOverflow, s[0]->flags_condition());
1187   }
1188 }
1189
1190
1191 // -----------------------------------------------------------------------------
1192 // Shift instructions.
1193
1194
1195 typedef InstructionSelectorTestWithParam<Shift> InstructionSelectorShiftTest;
1196
1197
1198 TEST_P(InstructionSelectorShiftTest, Parameter) {
1199   const Shift shift = GetParam();
1200   const MachineType type = shift.mi.machine_type;
1201   StreamBuilder m(this, type, type, type);
1202   m.Return((m.*shift.mi.constructor)(m.Parameter(0), m.Parameter(1)));
1203   Stream s = m.Build();
1204   ASSERT_EQ(1U, s.size());
1205   EXPECT_EQ(shift.mi.arch_opcode, s[0]->arch_opcode());
1206   EXPECT_EQ(2U, s[0]->InputCount());
1207   EXPECT_EQ(1U, s[0]->OutputCount());
1208 }
1209
1210
1211 TEST_P(InstructionSelectorShiftTest, Immediate) {
1212   const Shift shift = GetParam();
1213   const MachineType type = shift.mi.machine_type;
1214   TRACED_FORRANGE(int32_t, imm, 0, (ElementSizeOf(type) * 8) - 1) {
1215     StreamBuilder m(this, type, type);
1216     m.Return((m.*shift.mi.constructor)(m.Parameter(0), m.Int32Constant(imm)));
1217     Stream s = m.Build();
1218     ASSERT_EQ(1U, s.size());
1219     EXPECT_EQ(shift.mi.arch_opcode, s[0]->arch_opcode());
1220     EXPECT_EQ(2U, s[0]->InputCount());
1221     EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
1222     EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
1223     EXPECT_EQ(1U, s[0]->OutputCount());
1224   }
1225 }
1226
1227
1228 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorShiftTest,
1229                         ::testing::ValuesIn(kShiftInstructions));
1230
1231
1232 // -----------------------------------------------------------------------------
1233 // Mul and Div instructions.
1234
1235
1236 typedef InstructionSelectorTestWithParam<MachInst2>
1237     InstructionSelectorMulDivTest;
1238
1239
1240 TEST_P(InstructionSelectorMulDivTest, Parameter) {
1241   const MachInst2 dpi = GetParam();
1242   const MachineType type = dpi.machine_type;
1243   StreamBuilder m(this, type, type, type);
1244   m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)));
1245   Stream s = m.Build();
1246   ASSERT_EQ(1U, s.size());
1247   EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
1248   EXPECT_EQ(2U, s[0]->InputCount());
1249   EXPECT_EQ(1U, s[0]->OutputCount());
1250 }
1251
1252
1253 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorMulDivTest,
1254                         ::testing::ValuesIn(kMulDivInstructions));
1255
1256
1257 namespace {
1258
1259 struct MulDPInst {
1260   const char* mul_constructor_name;
1261   Node* (RawMachineAssembler::*mul_constructor)(Node*, Node*);
1262   Node* (RawMachineAssembler::*add_constructor)(Node*, Node*);
1263   Node* (RawMachineAssembler::*sub_constructor)(Node*, Node*);
1264   ArchOpcode add_arch_opcode;
1265   ArchOpcode sub_arch_opcode;
1266   ArchOpcode neg_arch_opcode;
1267   MachineType machine_type;
1268 };
1269
1270
1271 std::ostream& operator<<(std::ostream& os, const MulDPInst& inst) {
1272   return os << inst.mul_constructor_name;
1273 }
1274
1275 }  // namespace
1276
1277
1278 static const MulDPInst kMulDPInstructions[] = {
1279     {"Int32Mul", &RawMachineAssembler::Int32Mul, &RawMachineAssembler::Int32Add,
1280      &RawMachineAssembler::Int32Sub, kArm64Madd32, kArm64Msub32, kArm64Mneg32,
1281      kMachInt32},
1282     {"Int64Mul", &RawMachineAssembler::Int64Mul, &RawMachineAssembler::Int64Add,
1283      &RawMachineAssembler::Int64Sub, kArm64Madd, kArm64Msub, kArm64Mneg,
1284      kMachInt64}};
1285
1286
1287 typedef InstructionSelectorTestWithParam<MulDPInst>
1288     InstructionSelectorIntDPWithIntMulTest;
1289
1290
1291 TEST_P(InstructionSelectorIntDPWithIntMulTest, AddWithMul) {
1292   const MulDPInst mdpi = GetParam();
1293   const MachineType type = mdpi.machine_type;
1294   {
1295     StreamBuilder m(this, type, type, type, type);
1296     Node* n = (m.*mdpi.mul_constructor)(m.Parameter(1), m.Parameter(2));
1297     m.Return((m.*mdpi.add_constructor)(m.Parameter(0), n));
1298     Stream s = m.Build();
1299     ASSERT_EQ(1U, s.size());
1300     EXPECT_EQ(mdpi.add_arch_opcode, s[0]->arch_opcode());
1301     EXPECT_EQ(3U, s[0]->InputCount());
1302     EXPECT_EQ(1U, s[0]->OutputCount());
1303   }
1304   {
1305     StreamBuilder m(this, type, type, type, type);
1306     Node* n = (m.*mdpi.mul_constructor)(m.Parameter(0), m.Parameter(1));
1307     m.Return((m.*mdpi.add_constructor)(n, m.Parameter(2)));
1308     Stream s = m.Build();
1309     ASSERT_EQ(1U, s.size());
1310     EXPECT_EQ(mdpi.add_arch_opcode, s[0]->arch_opcode());
1311     EXPECT_EQ(3U, s[0]->InputCount());
1312     EXPECT_EQ(1U, s[0]->OutputCount());
1313   }
1314 }
1315
1316
1317 TEST_P(InstructionSelectorIntDPWithIntMulTest, SubWithMul) {
1318   const MulDPInst mdpi = GetParam();
1319   const MachineType type = mdpi.machine_type;
1320   {
1321     StreamBuilder m(this, type, type, type, type);
1322     Node* n = (m.*mdpi.mul_constructor)(m.Parameter(1), m.Parameter(2));
1323     m.Return((m.*mdpi.sub_constructor)(m.Parameter(0), n));
1324     Stream s = m.Build();
1325     ASSERT_EQ(1U, s.size());
1326     EXPECT_EQ(mdpi.sub_arch_opcode, s[0]->arch_opcode());
1327     EXPECT_EQ(3U, s[0]->InputCount());
1328     EXPECT_EQ(1U, s[0]->OutputCount());
1329   }
1330 }
1331
1332
1333 TEST_P(InstructionSelectorIntDPWithIntMulTest, NegativeMul) {
1334   const MulDPInst mdpi = GetParam();
1335   const MachineType type = mdpi.machine_type;
1336   {
1337     StreamBuilder m(this, type, type, type);
1338     Node* n =
1339         (m.*mdpi.sub_constructor)(BuildConstant(m, type, 0), m.Parameter(0));
1340     m.Return((m.*mdpi.mul_constructor)(n, m.Parameter(1)));
1341     Stream s = m.Build();
1342     ASSERT_EQ(1U, s.size());
1343     EXPECT_EQ(mdpi.neg_arch_opcode, s[0]->arch_opcode());
1344     EXPECT_EQ(2U, s[0]->InputCount());
1345     EXPECT_EQ(1U, s[0]->OutputCount());
1346   }
1347   {
1348     StreamBuilder m(this, type, type, type);
1349     Node* n =
1350         (m.*mdpi.sub_constructor)(BuildConstant(m, type, 0), m.Parameter(1));
1351     m.Return((m.*mdpi.mul_constructor)(m.Parameter(0), n));
1352     Stream s = m.Build();
1353     ASSERT_EQ(1U, s.size());
1354     EXPECT_EQ(mdpi.neg_arch_opcode, s[0]->arch_opcode());
1355     EXPECT_EQ(2U, s[0]->InputCount());
1356     EXPECT_EQ(1U, s[0]->OutputCount());
1357   }
1358 }
1359
1360
1361 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1362                         InstructionSelectorIntDPWithIntMulTest,
1363                         ::testing::ValuesIn(kMulDPInstructions));
1364
1365
1366 // -----------------------------------------------------------------------------
1367 // Floating point instructions.
1368
1369 typedef InstructionSelectorTestWithParam<MachInst2>
1370     InstructionSelectorFPArithTest;
1371
1372
1373 TEST_P(InstructionSelectorFPArithTest, Parameter) {
1374   const MachInst2 fpa = GetParam();
1375   StreamBuilder m(this, fpa.machine_type, fpa.machine_type, fpa.machine_type);
1376   m.Return((m.*fpa.constructor)(m.Parameter(0), m.Parameter(1)));
1377   Stream s = m.Build();
1378   ASSERT_EQ(1U, s.size());
1379   EXPECT_EQ(fpa.arch_opcode, s[0]->arch_opcode());
1380   EXPECT_EQ(2U, s[0]->InputCount());
1381   EXPECT_EQ(1U, s[0]->OutputCount());
1382 }
1383
1384
1385 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorFPArithTest,
1386                         ::testing::ValuesIn(kFPArithInstructions));
1387
1388
1389 typedef InstructionSelectorTestWithParam<FPCmp> InstructionSelectorFPCmpTest;
1390
1391
1392 TEST_P(InstructionSelectorFPCmpTest, Parameter) {
1393   const FPCmp cmp = GetParam();
1394   StreamBuilder m(this, kMachInt32, cmp.mi.machine_type, cmp.mi.machine_type);
1395   m.Return((m.*cmp.mi.constructor)(m.Parameter(0), m.Parameter(1)));
1396   Stream s = m.Build();
1397   ASSERT_EQ(1U, s.size());
1398   EXPECT_EQ(cmp.mi.arch_opcode, s[0]->arch_opcode());
1399   EXPECT_EQ(2U, s[0]->InputCount());
1400   EXPECT_EQ(1U, s[0]->OutputCount());
1401   EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1402   EXPECT_EQ(cmp.cond, s[0]->flags_condition());
1403 }
1404
1405
1406 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorFPCmpTest,
1407                         ::testing::ValuesIn(kFPCmpInstructions));
1408
1409
1410 // -----------------------------------------------------------------------------
1411 // Conversions.
1412
1413 typedef InstructionSelectorTestWithParam<Conversion>
1414     InstructionSelectorConversionTest;
1415
1416
1417 TEST_P(InstructionSelectorConversionTest, Parameter) {
1418   const Conversion conv = GetParam();
1419   StreamBuilder m(this, conv.mi.machine_type, conv.src_machine_type);
1420   m.Return((m.*conv.mi.constructor)(m.Parameter(0)));
1421   Stream s = m.Build();
1422   ASSERT_EQ(1U, s.size());
1423   EXPECT_EQ(conv.mi.arch_opcode, s[0]->arch_opcode());
1424   EXPECT_EQ(1U, s[0]->InputCount());
1425   EXPECT_EQ(1U, s[0]->OutputCount());
1426 }
1427
1428
1429 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1430                         InstructionSelectorConversionTest,
1431                         ::testing::ValuesIn(kConversionInstructions));
1432
1433
1434 // -----------------------------------------------------------------------------
1435 // Memory access instructions.
1436
1437
1438 namespace {
1439
1440 struct MemoryAccess {
1441   MachineType type;
1442   ArchOpcode ldr_opcode;
1443   ArchOpcode str_opcode;
1444   const int32_t immediates[20];
1445 };
1446
1447
1448 std::ostream& operator<<(std::ostream& os, const MemoryAccess& memacc) {
1449   return os << memacc.type;
1450 }
1451
1452 }  // namespace
1453
1454
1455 static const MemoryAccess kMemoryAccesses[] = {
1456     {kMachInt8,
1457      kArm64Ldrsb,
1458      kArm64Strb,
1459      {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 257, 258, 1000, 1001, 2121,
1460       2442, 4093, 4094, 4095}},
1461     {kMachUint8,
1462      kArm64Ldrb,
1463      kArm64Strb,
1464      {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 257, 258, 1000, 1001, 2121,
1465       2442, 4093, 4094, 4095}},
1466     {kMachInt16,
1467      kArm64Ldrsh,
1468      kArm64Strh,
1469      {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 258, 260, 4096, 4098, 4100,
1470       4242, 6786, 8188, 8190}},
1471     {kMachUint16,
1472      kArm64Ldrh,
1473      kArm64Strh,
1474      {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 258, 260, 4096, 4098, 4100,
1475       4242, 6786, 8188, 8190}},
1476     {kMachInt32,
1477      kArm64LdrW,
1478      kArm64StrW,
1479      {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 260, 4096, 4100, 8192, 8196,
1480       3276, 3280, 16376, 16380}},
1481     {kMachUint32,
1482      kArm64LdrW,
1483      kArm64StrW,
1484      {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 260, 4096, 4100, 8192, 8196,
1485       3276, 3280, 16376, 16380}},
1486     {kMachInt64,
1487      kArm64Ldr,
1488      kArm64Str,
1489      {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 264, 4096, 4104, 8192, 8200,
1490       16384, 16392, 32752, 32760}},
1491     {kMachUint64,
1492      kArm64Ldr,
1493      kArm64Str,
1494      {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 264, 4096, 4104, 8192, 8200,
1495       16384, 16392, 32752, 32760}},
1496     {kMachFloat32,
1497      kArm64LdrS,
1498      kArm64StrS,
1499      {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 260, 4096, 4100, 8192, 8196,
1500       3276, 3280, 16376, 16380}},
1501     {kMachFloat64,
1502      kArm64LdrD,
1503      kArm64StrD,
1504      {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 264, 4096, 4104, 8192, 8200,
1505       16384, 16392, 32752, 32760}}};
1506
1507
1508 typedef InstructionSelectorTestWithParam<MemoryAccess>
1509     InstructionSelectorMemoryAccessTest;
1510
1511
1512 TEST_P(InstructionSelectorMemoryAccessTest, LoadWithParameters) {
1513   const MemoryAccess memacc = GetParam();
1514   StreamBuilder m(this, memacc.type, kMachPtr, kMachInt32);
1515   m.Return(m.Load(memacc.type, m.Parameter(0), m.Parameter(1)));
1516   Stream s = m.Build();
1517   ASSERT_EQ(1U, s.size());
1518   EXPECT_EQ(memacc.ldr_opcode, s[0]->arch_opcode());
1519   EXPECT_EQ(kMode_MRR, s[0]->addressing_mode());
1520   EXPECT_EQ(2U, s[0]->InputCount());
1521   EXPECT_EQ(1U, s[0]->OutputCount());
1522 }
1523
1524
1525 TEST_P(InstructionSelectorMemoryAccessTest, LoadWithImmediateIndex) {
1526   const MemoryAccess memacc = GetParam();
1527   TRACED_FOREACH(int32_t, index, memacc.immediates) {
1528     StreamBuilder m(this, memacc.type, kMachPtr);
1529     m.Return(m.Load(memacc.type, m.Parameter(0), m.Int32Constant(index)));
1530     Stream s = m.Build();
1531     ASSERT_EQ(1U, s.size());
1532     EXPECT_EQ(memacc.ldr_opcode, s[0]->arch_opcode());
1533     EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
1534     EXPECT_EQ(2U, s[0]->InputCount());
1535     ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
1536     EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1)));
1537     ASSERT_EQ(1U, s[0]->OutputCount());
1538   }
1539 }
1540
1541
1542 TEST_P(InstructionSelectorMemoryAccessTest, StoreWithParameters) {
1543   const MemoryAccess memacc = GetParam();
1544   StreamBuilder m(this, kMachInt32, kMachPtr, kMachInt32, memacc.type);
1545   m.Store(memacc.type, m.Parameter(0), m.Parameter(1), m.Parameter(2));
1546   m.Return(m.Int32Constant(0));
1547   Stream s = m.Build();
1548   ASSERT_EQ(1U, s.size());
1549   EXPECT_EQ(memacc.str_opcode, s[0]->arch_opcode());
1550   EXPECT_EQ(kMode_MRR, s[0]->addressing_mode());
1551   EXPECT_EQ(3U, s[0]->InputCount());
1552   EXPECT_EQ(0U, s[0]->OutputCount());
1553 }
1554
1555
1556 TEST_P(InstructionSelectorMemoryAccessTest, StoreWithImmediateIndex) {
1557   const MemoryAccess memacc = GetParam();
1558   TRACED_FOREACH(int32_t, index, memacc.immediates) {
1559     StreamBuilder m(this, kMachInt32, kMachPtr, memacc.type);
1560     m.Store(memacc.type, m.Parameter(0), m.Int32Constant(index),
1561             m.Parameter(1));
1562     m.Return(m.Int32Constant(0));
1563     Stream s = m.Build();
1564     ASSERT_EQ(1U, s.size());
1565     EXPECT_EQ(memacc.str_opcode, s[0]->arch_opcode());
1566     EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
1567     ASSERT_EQ(3U, s[0]->InputCount());
1568     ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
1569     EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1)));
1570     EXPECT_EQ(0U, s[0]->OutputCount());
1571   }
1572 }
1573
1574
1575 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1576                         InstructionSelectorMemoryAccessTest,
1577                         ::testing::ValuesIn(kMemoryAccesses));
1578
1579
1580 // -----------------------------------------------------------------------------
1581 // Comparison instructions.
1582
1583 static const MachInst2 kComparisonInstructions[] = {
1584     {&RawMachineAssembler::Word32Equal, "Word32Equal", kArm64Cmp32, kMachInt32},
1585     {&RawMachineAssembler::Word64Equal, "Word64Equal", kArm64Cmp, kMachInt64},
1586 };
1587
1588
1589 typedef InstructionSelectorTestWithParam<MachInst2>
1590     InstructionSelectorComparisonTest;
1591
1592
1593 TEST_P(InstructionSelectorComparisonTest, WithParameters) {
1594   const MachInst2 cmp = GetParam();
1595   const MachineType type = cmp.machine_type;
1596   StreamBuilder m(this, type, type, type);
1597   m.Return((m.*cmp.constructor)(m.Parameter(0), m.Parameter(1)));
1598   Stream s = m.Build();
1599   ASSERT_EQ(1U, s.size());
1600   EXPECT_EQ(cmp.arch_opcode, s[0]->arch_opcode());
1601   EXPECT_EQ(2U, s[0]->InputCount());
1602   EXPECT_EQ(1U, s[0]->OutputCount());
1603   EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1604   EXPECT_EQ(kEqual, s[0]->flags_condition());
1605 }
1606
1607
1608 TEST_P(InstructionSelectorComparisonTest, WithImmediate) {
1609   const MachInst2 cmp = GetParam();
1610   const MachineType type = cmp.machine_type;
1611   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
1612     // Compare with 0 are turned into tst instruction.
1613     if (imm == 0) continue;
1614     StreamBuilder m(this, type, type);
1615     m.Return((m.*cmp.constructor)(m.Parameter(0), BuildConstant(m, type, imm)));
1616     Stream s = m.Build();
1617     ASSERT_EQ(1U, s.size());
1618     EXPECT_EQ(cmp.arch_opcode, s[0]->arch_opcode());
1619     ASSERT_EQ(2U, s[0]->InputCount());
1620     ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
1621     EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(1)));
1622     EXPECT_EQ(1U, s[0]->OutputCount());
1623     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1624     EXPECT_EQ(kEqual, s[0]->flags_condition());
1625   }
1626   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
1627     // Compare with 0 are turned into tst instruction.
1628     if (imm == 0) continue;
1629     StreamBuilder m(this, type, type);
1630     m.Return((m.*cmp.constructor)(BuildConstant(m, type, imm), m.Parameter(0)));
1631     Stream s = m.Build();
1632     ASSERT_EQ(1U, s.size());
1633     EXPECT_EQ(cmp.arch_opcode, s[0]->arch_opcode());
1634     ASSERT_EQ(2U, s[0]->InputCount());
1635     ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
1636     EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(1)));
1637     EXPECT_EQ(1U, s[0]->OutputCount());
1638     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1639     EXPECT_EQ(kEqual, s[0]->flags_condition());
1640   }
1641 }
1642
1643 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1644                         InstructionSelectorComparisonTest,
1645                         ::testing::ValuesIn(kComparisonInstructions));
1646
1647
1648 TEST_F(InstructionSelectorTest, Word32EqualWithZero) {
1649   {
1650     StreamBuilder m(this, kMachInt32, kMachInt32);
1651     m.Return(m.Word32Equal(m.Parameter(0), m.Int32Constant(0)));
1652     Stream s = m.Build();
1653     ASSERT_EQ(1U, s.size());
1654     EXPECT_EQ(kArm64Tst32, s[0]->arch_opcode());
1655     ASSERT_EQ(2U, s[0]->InputCount());
1656     EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
1657     EXPECT_EQ(1U, s[0]->OutputCount());
1658     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1659     EXPECT_EQ(kEqual, s[0]->flags_condition());
1660   }
1661   {
1662     StreamBuilder m(this, kMachInt32, kMachInt32);
1663     m.Return(m.Word32Equal(m.Int32Constant(0), m.Parameter(0)));
1664     Stream s = m.Build();
1665     ASSERT_EQ(1U, s.size());
1666     EXPECT_EQ(kArm64Tst32, s[0]->arch_opcode());
1667     ASSERT_EQ(2U, s[0]->InputCount());
1668     EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
1669     EXPECT_EQ(1U, s[0]->OutputCount());
1670     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1671     EXPECT_EQ(kEqual, s[0]->flags_condition());
1672   }
1673 }
1674
1675
1676 TEST_F(InstructionSelectorTest, Word64EqualWithZero) {
1677   {
1678     StreamBuilder m(this, kMachInt64, kMachInt64);
1679     m.Return(m.Word64Equal(m.Parameter(0), m.Int64Constant(0)));
1680     Stream s = m.Build();
1681     ASSERT_EQ(1U, s.size());
1682     EXPECT_EQ(kArm64Tst, s[0]->arch_opcode());
1683     ASSERT_EQ(2U, s[0]->InputCount());
1684     EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
1685     EXPECT_EQ(1U, s[0]->OutputCount());
1686     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1687     EXPECT_EQ(kEqual, s[0]->flags_condition());
1688   }
1689   {
1690     StreamBuilder m(this, kMachInt64, kMachInt64);
1691     m.Return(m.Word64Equal(m.Int64Constant(0), m.Parameter(0)));
1692     Stream s = m.Build();
1693     ASSERT_EQ(1U, s.size());
1694     EXPECT_EQ(kArm64Tst, s[0]->arch_opcode());
1695     ASSERT_EQ(2U, s[0]->InputCount());
1696     EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
1697     EXPECT_EQ(1U, s[0]->OutputCount());
1698     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1699     EXPECT_EQ(kEqual, s[0]->flags_condition());
1700   }
1701 }
1702
1703
1704 // -----------------------------------------------------------------------------
1705 // Miscellaneous
1706
1707
1708 static const MachInst2 kLogicalWithNotRHSs[] = {
1709     {&RawMachineAssembler::Word32And, "Word32And", kArm64Bic32, kMachInt32},
1710     {&RawMachineAssembler::Word64And, "Word64And", kArm64Bic, kMachInt64},
1711     {&RawMachineAssembler::Word32Or, "Word32Or", kArm64Orn32, kMachInt32},
1712     {&RawMachineAssembler::Word64Or, "Word64Or", kArm64Orn, kMachInt64},
1713     {&RawMachineAssembler::Word32Xor, "Word32Xor", kArm64Eon32, kMachInt32},
1714     {&RawMachineAssembler::Word64Xor, "Word64Xor", kArm64Eon, kMachInt64}};
1715
1716
1717 typedef InstructionSelectorTestWithParam<MachInst2>
1718     InstructionSelectorLogicalWithNotRHSTest;
1719
1720
1721 TEST_P(InstructionSelectorLogicalWithNotRHSTest, Parameter) {
1722   const MachInst2 inst = GetParam();
1723   const MachineType type = inst.machine_type;
1724   // Test cases where RHS is Xor(x, -1).
1725   {
1726     StreamBuilder m(this, type, type, type);
1727     if (type == kMachInt32) {
1728       m.Return((m.*inst.constructor)(
1729           m.Parameter(0), m.Word32Xor(m.Parameter(1), m.Int32Constant(-1))));
1730     } else {
1731       ASSERT_EQ(kMachInt64, type);
1732       m.Return((m.*inst.constructor)(
1733           m.Parameter(0), m.Word64Xor(m.Parameter(1), m.Int64Constant(-1))));
1734     }
1735     Stream s = m.Build();
1736     ASSERT_EQ(1U, s.size());
1737     EXPECT_EQ(inst.arch_opcode, s[0]->arch_opcode());
1738     EXPECT_EQ(2U, s[0]->InputCount());
1739     EXPECT_EQ(1U, s[0]->OutputCount());
1740   }
1741   {
1742     StreamBuilder m(this, type, type, type);
1743     if (type == kMachInt32) {
1744       m.Return((m.*inst.constructor)(
1745           m.Word32Xor(m.Parameter(0), m.Int32Constant(-1)), m.Parameter(1)));
1746     } else {
1747       ASSERT_EQ(kMachInt64, type);
1748       m.Return((m.*inst.constructor)(
1749           m.Word64Xor(m.Parameter(0), m.Int64Constant(-1)), m.Parameter(1)));
1750     }
1751     Stream s = m.Build();
1752     ASSERT_EQ(1U, s.size());
1753     EXPECT_EQ(inst.arch_opcode, s[0]->arch_opcode());
1754     EXPECT_EQ(2U, s[0]->InputCount());
1755     EXPECT_EQ(1U, s[0]->OutputCount());
1756   }
1757   // Test cases where RHS is Not(x).
1758   {
1759     StreamBuilder m(this, type, type, type);
1760     if (type == kMachInt32) {
1761       m.Return(
1762           (m.*inst.constructor)(m.Parameter(0), m.Word32Not(m.Parameter(1))));
1763     } else {
1764       ASSERT_EQ(kMachInt64, type);
1765       m.Return(
1766           (m.*inst.constructor)(m.Parameter(0), m.Word64Not(m.Parameter(1))));
1767     }
1768     Stream s = m.Build();
1769     ASSERT_EQ(1U, s.size());
1770     EXPECT_EQ(inst.arch_opcode, s[0]->arch_opcode());
1771     EXPECT_EQ(2U, s[0]->InputCount());
1772     EXPECT_EQ(1U, s[0]->OutputCount());
1773   }
1774   {
1775     StreamBuilder m(this, type, type, type);
1776     if (type == kMachInt32) {
1777       m.Return(
1778           (m.*inst.constructor)(m.Word32Not(m.Parameter(0)), m.Parameter(1)));
1779     } else {
1780       ASSERT_EQ(kMachInt64, type);
1781       m.Return(
1782           (m.*inst.constructor)(m.Word64Not(m.Parameter(0)), m.Parameter(1)));
1783     }
1784     Stream s = m.Build();
1785     ASSERT_EQ(1U, s.size());
1786     EXPECT_EQ(inst.arch_opcode, s[0]->arch_opcode());
1787     EXPECT_EQ(2U, s[0]->InputCount());
1788     EXPECT_EQ(1U, s[0]->OutputCount());
1789   }
1790 }
1791
1792
1793 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1794                         InstructionSelectorLogicalWithNotRHSTest,
1795                         ::testing::ValuesIn(kLogicalWithNotRHSs));
1796
1797
1798 TEST_F(InstructionSelectorTest, Word32NotWithParameter) {
1799   StreamBuilder m(this, kMachInt32, kMachInt32);
1800   m.Return(m.Word32Not(m.Parameter(0)));
1801   Stream s = m.Build();
1802   ASSERT_EQ(1U, s.size());
1803   EXPECT_EQ(kArm64Not32, s[0]->arch_opcode());
1804   EXPECT_EQ(1U, s[0]->InputCount());
1805   EXPECT_EQ(1U, s[0]->OutputCount());
1806 }
1807
1808
1809 TEST_F(InstructionSelectorTest, Word64NotWithParameter) {
1810   StreamBuilder m(this, kMachInt64, kMachInt64);
1811   m.Return(m.Word64Not(m.Parameter(0)));
1812   Stream s = m.Build();
1813   ASSERT_EQ(1U, s.size());
1814   EXPECT_EQ(kArm64Not, s[0]->arch_opcode());
1815   EXPECT_EQ(1U, s[0]->InputCount());
1816   EXPECT_EQ(1U, s[0]->OutputCount());
1817 }
1818
1819
1820 TEST_F(InstructionSelectorTest, Word32XorMinusOneWithParameter) {
1821   {
1822     StreamBuilder m(this, kMachInt32, kMachInt32);
1823     m.Return(m.Word32Xor(m.Parameter(0), m.Int32Constant(-1)));
1824     Stream s = m.Build();
1825     ASSERT_EQ(1U, s.size());
1826     EXPECT_EQ(kArm64Not32, s[0]->arch_opcode());
1827     EXPECT_EQ(1U, s[0]->InputCount());
1828     EXPECT_EQ(1U, s[0]->OutputCount());
1829   }
1830   {
1831     StreamBuilder m(this, kMachInt32, kMachInt32);
1832     m.Return(m.Word32Xor(m.Int32Constant(-1), m.Parameter(0)));
1833     Stream s = m.Build();
1834     ASSERT_EQ(1U, s.size());
1835     EXPECT_EQ(kArm64Not32, s[0]->arch_opcode());
1836     EXPECT_EQ(1U, s[0]->InputCount());
1837     EXPECT_EQ(1U, s[0]->OutputCount());
1838   }
1839 }
1840
1841
1842 TEST_F(InstructionSelectorTest, Word64XorMinusOneWithParameter) {
1843   {
1844     StreamBuilder m(this, kMachInt64, kMachInt64);
1845     m.Return(m.Word64Xor(m.Parameter(0), m.Int64Constant(-1)));
1846     Stream s = m.Build();
1847     ASSERT_EQ(1U, s.size());
1848     EXPECT_EQ(kArm64Not, s[0]->arch_opcode());
1849     EXPECT_EQ(1U, s[0]->InputCount());
1850     EXPECT_EQ(1U, s[0]->OutputCount());
1851   }
1852   {
1853     StreamBuilder m(this, kMachInt64, kMachInt64);
1854     m.Return(m.Word64Xor(m.Int64Constant(-1), m.Parameter(0)));
1855     Stream s = m.Build();
1856     ASSERT_EQ(1U, s.size());
1857     EXPECT_EQ(kArm64Not, s[0]->arch_opcode());
1858     EXPECT_EQ(1U, s[0]->InputCount());
1859     EXPECT_EQ(1U, s[0]->OutputCount());
1860   }
1861 }
1862
1863
1864 TEST_F(InstructionSelectorTest, Word32ShrWithWord32AndWithImmediate) {
1865   TRACED_FORRANGE(int32_t, lsb, 1, 31) {
1866     TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) {
1867       uint32_t jnk = rng()->NextInt();
1868       jnk >>= 32 - lsb;
1869       uint32_t msk = ((0xffffffffu >> (32 - width)) << lsb) | jnk;
1870       StreamBuilder m(this, kMachInt32, kMachInt32);
1871       m.Return(m.Word32Shr(m.Word32And(m.Parameter(0), m.Int32Constant(msk)),
1872                            m.Int32Constant(lsb)));
1873       Stream s = m.Build();
1874       ASSERT_EQ(1U, s.size());
1875       EXPECT_EQ(kArm64Ubfx32, s[0]->arch_opcode());
1876       ASSERT_EQ(3U, s[0]->InputCount());
1877       EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
1878       EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
1879     }
1880   }
1881   TRACED_FORRANGE(int32_t, lsb, 1, 31) {
1882     TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) {
1883       uint32_t jnk = rng()->NextInt();
1884       jnk >>= 32 - lsb;
1885       uint32_t msk = ((0xffffffffu >> (32 - width)) << lsb) | jnk;
1886       StreamBuilder m(this, kMachInt32, kMachInt32);
1887       m.Return(m.Word32Shr(m.Word32And(m.Int32Constant(msk), m.Parameter(0)),
1888                            m.Int32Constant(lsb)));
1889       Stream s = m.Build();
1890       ASSERT_EQ(1U, s.size());
1891       EXPECT_EQ(kArm64Ubfx32, s[0]->arch_opcode());
1892       ASSERT_EQ(3U, s[0]->InputCount());
1893       EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
1894       EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
1895     }
1896   }
1897 }
1898
1899
1900 TEST_F(InstructionSelectorTest, Word64ShrWithWord64AndWithImmediate) {
1901   TRACED_FORRANGE(int32_t, lsb, 1, 63) {
1902     TRACED_FORRANGE(int32_t, width, 1, 64 - lsb) {
1903       uint64_t jnk = rng()->NextInt64();
1904       jnk >>= 64 - lsb;
1905       uint64_t msk =
1906           ((V8_UINT64_C(0xffffffffffffffff) >> (64 - width)) << lsb) | jnk;
1907       StreamBuilder m(this, kMachInt64, kMachInt64);
1908       m.Return(m.Word64Shr(m.Word64And(m.Parameter(0), m.Int64Constant(msk)),
1909                            m.Int64Constant(lsb)));
1910       Stream s = m.Build();
1911       ASSERT_EQ(1U, s.size());
1912       EXPECT_EQ(kArm64Ubfx, s[0]->arch_opcode());
1913       ASSERT_EQ(3U, s[0]->InputCount());
1914       EXPECT_EQ(lsb, s.ToInt64(s[0]->InputAt(1)));
1915       EXPECT_EQ(width, s.ToInt64(s[0]->InputAt(2)));
1916     }
1917   }
1918   TRACED_FORRANGE(int32_t, lsb, 1, 63) {
1919     TRACED_FORRANGE(int32_t, width, 1, 64 - lsb) {
1920       uint64_t jnk = rng()->NextInt64();
1921       jnk >>= 64 - lsb;
1922       uint64_t msk =
1923           ((V8_UINT64_C(0xffffffffffffffff) >> (64 - width)) << lsb) | jnk;
1924       StreamBuilder m(this, kMachInt64, kMachInt64);
1925       m.Return(m.Word64Shr(m.Word64And(m.Int64Constant(msk), m.Parameter(0)),
1926                            m.Int64Constant(lsb)));
1927       Stream s = m.Build();
1928       ASSERT_EQ(1U, s.size());
1929       EXPECT_EQ(kArm64Ubfx, s[0]->arch_opcode());
1930       ASSERT_EQ(3U, s[0]->InputCount());
1931       EXPECT_EQ(lsb, s.ToInt64(s[0]->InputAt(1)));
1932       EXPECT_EQ(width, s.ToInt64(s[0]->InputAt(2)));
1933     }
1934   }
1935 }
1936
1937
1938 TEST_F(InstructionSelectorTest, Word32AndWithImmediateWithWord32Shr) {
1939   TRACED_FORRANGE(int32_t, lsb, 1, 31) {
1940     TRACED_FORRANGE(int32_t, width, 1, 31) {
1941       uint32_t msk = (1 << width) - 1;
1942       StreamBuilder m(this, kMachInt32, kMachInt32);
1943       m.Return(m.Word32And(m.Word32Shr(m.Parameter(0), m.Int32Constant(lsb)),
1944                            m.Int32Constant(msk)));
1945       Stream s = m.Build();
1946       ASSERT_EQ(1U, s.size());
1947       EXPECT_EQ(kArm64Ubfx32, s[0]->arch_opcode());
1948       ASSERT_EQ(3U, s[0]->InputCount());
1949       EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
1950       int32_t actual_width = (lsb + width > 32) ? (32 - lsb) : width;
1951       EXPECT_EQ(actual_width, s.ToInt32(s[0]->InputAt(2)));
1952     }
1953   }
1954   TRACED_FORRANGE(int32_t, lsb, 1, 31) {
1955     TRACED_FORRANGE(int32_t, width, 1, 31) {
1956       uint32_t msk = (1 << width) - 1;
1957       StreamBuilder m(this, kMachInt32, kMachInt32);
1958       m.Return(m.Word32And(m.Int32Constant(msk),
1959                            m.Word32Shr(m.Parameter(0), m.Int32Constant(lsb))));
1960       Stream s = m.Build();
1961       ASSERT_EQ(1U, s.size());
1962       EXPECT_EQ(kArm64Ubfx32, s[0]->arch_opcode());
1963       ASSERT_EQ(3U, s[0]->InputCount());
1964       EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
1965       int32_t actual_width = (lsb + width > 32) ? (32 - lsb) : width;
1966       EXPECT_EQ(actual_width, s.ToInt32(s[0]->InputAt(2)));
1967     }
1968   }
1969 }
1970
1971
1972 TEST_F(InstructionSelectorTest, Word64AndWithImmediateWithWord64Shr) {
1973   TRACED_FORRANGE(int64_t, lsb, 1, 63) {
1974     TRACED_FORRANGE(int64_t, width, 1, 63) {
1975       uint64_t msk = (V8_UINT64_C(1) << width) - 1;
1976       StreamBuilder m(this, kMachInt64, kMachInt64);
1977       m.Return(m.Word64And(m.Word64Shr(m.Parameter(0), m.Int64Constant(lsb)),
1978                            m.Int64Constant(msk)));
1979       Stream s = m.Build();
1980       ASSERT_EQ(1U, s.size());
1981       EXPECT_EQ(kArm64Ubfx, s[0]->arch_opcode());
1982       ASSERT_EQ(3U, s[0]->InputCount());
1983       EXPECT_EQ(lsb, s.ToInt64(s[0]->InputAt(1)));
1984       int64_t actual_width = (lsb + width > 64) ? (64 - lsb) : width;
1985       EXPECT_EQ(actual_width, s.ToInt64(s[0]->InputAt(2)));
1986     }
1987   }
1988   TRACED_FORRANGE(int64_t, lsb, 1, 63) {
1989     TRACED_FORRANGE(int64_t, width, 1, 63) {
1990       uint64_t msk = (V8_UINT64_C(1) << width) - 1;
1991       StreamBuilder m(this, kMachInt64, kMachInt64);
1992       m.Return(m.Word64And(m.Int64Constant(msk),
1993                            m.Word64Shr(m.Parameter(0), m.Int64Constant(lsb))));
1994       Stream s = m.Build();
1995       ASSERT_EQ(1U, s.size());
1996       EXPECT_EQ(kArm64Ubfx, s[0]->arch_opcode());
1997       ASSERT_EQ(3U, s[0]->InputCount());
1998       EXPECT_EQ(lsb, s.ToInt64(s[0]->InputAt(1)));
1999       int64_t actual_width = (lsb + width > 64) ? (64 - lsb) : width;
2000       EXPECT_EQ(actual_width, s.ToInt64(s[0]->InputAt(2)));
2001     }
2002   }
2003 }
2004
2005
2006 TEST_F(InstructionSelectorTest, Int32MulHighWithParameters) {
2007   StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
2008   Node* const p0 = m.Parameter(0);
2009   Node* const p1 = m.Parameter(1);
2010   Node* const n = m.Int32MulHigh(p0, p1);
2011   m.Return(n);
2012   Stream s = m.Build();
2013   ASSERT_EQ(2U, s.size());
2014   EXPECT_EQ(kArm64Smull, s[0]->arch_opcode());
2015   ASSERT_EQ(2U, s[0]->InputCount());
2016   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
2017   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
2018   ASSERT_EQ(1U, s[0]->OutputCount());
2019   EXPECT_EQ(kArm64Asr, s[1]->arch_opcode());
2020   ASSERT_EQ(2U, s[1]->InputCount());
2021   EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(0)));
2022   EXPECT_EQ(32, s.ToInt64(s[1]->InputAt(1)));
2023   ASSERT_EQ(1U, s[1]->OutputCount());
2024   EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[1]->Output()));
2025 }
2026
2027 }  // namespace compiler
2028 }  // namespace internal
2029 }  // namespace v8