571dbecd14071425b0eb05215a3430790398fdf4
[platform/upstream/nodejs.git] / deps / 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 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 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 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 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 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 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 const MachInst2 kOvfAddSubInstructions[] = {
172     {&RawMachineAssembler::Int32AddWithOverflow, "Int32AddWithOverflow",
173      kArm64Add32, kMachInt32},
174     {&RawMachineAssembler::Int32SubWithOverflow, "Int32SubWithOverflow",
175      kArm64Sub32, kMachInt32}};
176
177
178 // ARM64 shift instructions.
179 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 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 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 const FPCmp kFPCmpInstructions[] = {
233     {{&RawMachineAssembler::Float64Equal, "Float64Equal", kArm64Float64Cmp,
234       kMachFloat64},
235      kEqual},
236     {{&RawMachineAssembler::Float64LessThan, "Float64LessThan",
237       kArm64Float64Cmp, kMachFloat64},
238      kUnsignedLessThan},
239     {{&RawMachineAssembler::Float64LessThanOrEqual, "Float64LessThanOrEqual",
240       kArm64Float64Cmp, kMachFloat64},
241      kUnsignedLessThanOrEqual}};
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 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(kArm64TestAndBranch32, s[0]->arch_opcode());
812     EXPECT_EQ(kNotEqual, s[0]->flags_condition());
813     EXPECT_EQ(4U, s[0]->InputCount());
814     EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
815     EXPECT_EQ(bit, s.ToInt32(s[0]->InputAt(1)));
816   }
817
818   TRACED_FORRANGE(int, bit, 0, 31) {
819     uint32_t mask = 1 << bit;
820     StreamBuilder m(this, kMachInt32, kMachInt32);
821     MLabel a, b;
822     m.Branch(
823         m.Word32BinaryNot(m.Word32And(m.Parameter(0), m.Int32Constant(mask))),
824         &a, &b);
825     m.Bind(&a);
826     m.Return(m.Int32Constant(1));
827     m.Bind(&b);
828     m.Return(m.Int32Constant(0));
829     Stream s = m.Build();
830     ASSERT_EQ(1U, s.size());
831     EXPECT_EQ(kArm64TestAndBranch32, s[0]->arch_opcode());
832     EXPECT_EQ(kEqual, s[0]->flags_condition());
833     EXPECT_EQ(4U, s[0]->InputCount());
834     EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
835     EXPECT_EQ(bit, s.ToInt32(s[0]->InputAt(1)));
836   }
837 }
838
839
840 TEST_F(InstructionSelectorTest, Word32AndBranchWithOneBitMaskOnLeft) {
841   TRACED_FORRANGE(int, bit, 0, 31) {
842     uint32_t mask = 1 << bit;
843     StreamBuilder m(this, kMachInt32, kMachInt32);
844     MLabel a, b;
845     m.Branch(m.Word32And(m.Int32Constant(mask), m.Parameter(0)), &a, &b);
846     m.Bind(&a);
847     m.Return(m.Int32Constant(1));
848     m.Bind(&b);
849     m.Return(m.Int32Constant(0));
850     Stream s = m.Build();
851     ASSERT_EQ(1U, s.size());
852     EXPECT_EQ(kArm64TestAndBranch32, s[0]->arch_opcode());
853     EXPECT_EQ(kNotEqual, s[0]->flags_condition());
854     EXPECT_EQ(4U, s[0]->InputCount());
855     EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
856     EXPECT_EQ(bit, s.ToInt32(s[0]->InputAt(1)));
857   }
858
859   TRACED_FORRANGE(int, bit, 0, 31) {
860     uint32_t mask = 1 << bit;
861     StreamBuilder m(this, kMachInt32, kMachInt32);
862     MLabel a, b;
863     m.Branch(
864         m.Word32BinaryNot(m.Word32And(m.Int32Constant(mask), m.Parameter(0))),
865         &a, &b);
866     m.Bind(&a);
867     m.Return(m.Int32Constant(1));
868     m.Bind(&b);
869     m.Return(m.Int32Constant(0));
870     Stream s = m.Build();
871     ASSERT_EQ(1U, s.size());
872     EXPECT_EQ(kArm64TestAndBranch32, s[0]->arch_opcode());
873     EXPECT_EQ(kEqual, s[0]->flags_condition());
874     EXPECT_EQ(4U, s[0]->InputCount());
875     EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
876     EXPECT_EQ(bit, s.ToInt32(s[0]->InputAt(1)));
877   }
878 }
879
880
881 TEST_F(InstructionSelectorTest, Word64AndBranchWithOneBitMaskOnRight) {
882   TRACED_FORRANGE(int, bit, 0, 63) {
883     uint64_t mask = 1L << bit;
884     StreamBuilder m(this, kMachInt64, kMachInt64);
885     MLabel a, b;
886     m.Branch(m.Word64And(m.Parameter(0), m.Int64Constant(mask)), &a, &b);
887     m.Bind(&a);
888     m.Return(m.Int32Constant(1));
889     m.Bind(&b);
890     m.Return(m.Int32Constant(0));
891     Stream s = m.Build();
892     ASSERT_EQ(1U, s.size());
893     EXPECT_EQ(kArm64TestAndBranch, s[0]->arch_opcode());
894     EXPECT_EQ(kNotEqual, s[0]->flags_condition());
895     EXPECT_EQ(4U, s[0]->InputCount());
896     EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
897     EXPECT_EQ(bit, s.ToInt64(s[0]->InputAt(1)));
898   }
899
900   TRACED_FORRANGE(int, bit, 0, 63) {
901     uint64_t mask = 1L << bit;
902     StreamBuilder m(this, kMachInt64, kMachInt64);
903     MLabel a, b;
904     m.Branch(
905         m.Word64BinaryNot(m.Word64And(m.Parameter(0), m.Int64Constant(mask))),
906         &a, &b);
907     m.Bind(&a);
908     m.Return(m.Int32Constant(1));
909     m.Bind(&b);
910     m.Return(m.Int32Constant(0));
911     Stream s = m.Build();
912     ASSERT_EQ(1U, s.size());
913     EXPECT_EQ(kArm64TestAndBranch, s[0]->arch_opcode());
914     EXPECT_EQ(kEqual, s[0]->flags_condition());
915     EXPECT_EQ(4U, s[0]->InputCount());
916     EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
917     EXPECT_EQ(bit, s.ToInt64(s[0]->InputAt(1)));
918   }
919 }
920
921
922 TEST_F(InstructionSelectorTest, Word64AndBranchWithOneBitMaskOnLeft) {
923   TRACED_FORRANGE(int, bit, 0, 63) {
924     uint64_t mask = 1L << bit;
925     StreamBuilder m(this, kMachInt64, kMachInt64);
926     MLabel a, b;
927     m.Branch(m.Word64And(m.Int64Constant(mask), m.Parameter(0)), &a, &b);
928     m.Bind(&a);
929     m.Return(m.Int32Constant(1));
930     m.Bind(&b);
931     m.Return(m.Int32Constant(0));
932     Stream s = m.Build();
933     ASSERT_EQ(1U, s.size());
934     EXPECT_EQ(kArm64TestAndBranch, s[0]->arch_opcode());
935     EXPECT_EQ(kNotEqual, s[0]->flags_condition());
936     EXPECT_EQ(4U, s[0]->InputCount());
937     EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
938     EXPECT_EQ(bit, s.ToInt64(s[0]->InputAt(1)));
939   }
940
941   TRACED_FORRANGE(int, bit, 0, 63) {
942     uint64_t mask = 1L << bit;
943     StreamBuilder m(this, kMachInt64, kMachInt64);
944     MLabel a, b;
945     m.Branch(
946         m.Word64BinaryNot(m.Word64And(m.Int64Constant(mask), m.Parameter(0))),
947         &a, &b);
948     m.Bind(&a);
949     m.Return(m.Int32Constant(1));
950     m.Bind(&b);
951     m.Return(m.Int32Constant(0));
952     Stream s = m.Build();
953     ASSERT_EQ(1U, s.size());
954     EXPECT_EQ(kArm64TestAndBranch, s[0]->arch_opcode());
955     EXPECT_EQ(kEqual, s[0]->flags_condition());
956     EXPECT_EQ(4U, s[0]->InputCount());
957     EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
958     EXPECT_EQ(bit, s.ToInt64(s[0]->InputAt(1)));
959   }
960 }
961
962
963 TEST_F(InstructionSelectorTest, CompareAgainstZeroAndBranch) {
964   {
965     StreamBuilder m(this, kMachInt32, kMachInt32);
966     MLabel a, b;
967     Node* p0 = m.Parameter(0);
968     m.Branch(p0, &a, &b);
969     m.Bind(&a);
970     m.Return(m.Int32Constant(1));
971     m.Bind(&b);
972     m.Return(m.Int32Constant(0));
973     Stream s = m.Build();
974     ASSERT_EQ(1U, s.size());
975     EXPECT_EQ(kArm64CompareAndBranch32, s[0]->arch_opcode());
976     EXPECT_EQ(kNotEqual, s[0]->flags_condition());
977     EXPECT_EQ(3U, s[0]->InputCount());
978     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
979   }
980
981   {
982     StreamBuilder m(this, kMachInt32, kMachInt32);
983     MLabel a, b;
984     Node* p0 = m.Parameter(0);
985     m.Branch(m.Word32BinaryNot(p0), &a, &b);
986     m.Bind(&a);
987     m.Return(m.Int32Constant(1));
988     m.Bind(&b);
989     m.Return(m.Int32Constant(0));
990     Stream s = m.Build();
991     ASSERT_EQ(1U, s.size());
992     EXPECT_EQ(kArm64CompareAndBranch32, s[0]->arch_opcode());
993     EXPECT_EQ(kEqual, s[0]->flags_condition());
994     EXPECT_EQ(3U, s[0]->InputCount());
995     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
996   }
997 }
998
999
1000 // -----------------------------------------------------------------------------
1001 // Add and subtract instructions with overflow.
1002
1003
1004 typedef InstructionSelectorTestWithParam<MachInst2>
1005     InstructionSelectorOvfAddSubTest;
1006
1007
1008 TEST_P(InstructionSelectorOvfAddSubTest, OvfParameter) {
1009   const MachInst2 dpi = GetParam();
1010   const MachineType type = dpi.machine_type;
1011   StreamBuilder m(this, type, type, type);
1012   m.Return(
1013       m.Projection(1, (m.*dpi.constructor)(m.Parameter(0), m.Parameter(1))));
1014   Stream s = m.Build();
1015   ASSERT_EQ(1U, s.size());
1016   EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
1017   EXPECT_EQ(2U, s[0]->InputCount());
1018   EXPECT_LE(1U, s[0]->OutputCount());
1019   EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1020   EXPECT_EQ(kOverflow, s[0]->flags_condition());
1021 }
1022
1023
1024 TEST_P(InstructionSelectorOvfAddSubTest, OvfImmediateOnRight) {
1025   const MachInst2 dpi = GetParam();
1026   const MachineType type = dpi.machine_type;
1027   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
1028     StreamBuilder m(this, type, type);
1029     m.Return(m.Projection(
1030         1, (m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm))));
1031     Stream s = m.Build();
1032     ASSERT_EQ(1U, s.size());
1033     EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
1034     ASSERT_EQ(2U, s[0]->InputCount());
1035     EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
1036     EXPECT_LE(1U, s[0]->OutputCount());
1037     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1038     EXPECT_EQ(kOverflow, s[0]->flags_condition());
1039   }
1040 }
1041
1042
1043 TEST_P(InstructionSelectorOvfAddSubTest, ValParameter) {
1044   const MachInst2 dpi = GetParam();
1045   const MachineType type = dpi.machine_type;
1046   StreamBuilder m(this, type, type, type);
1047   m.Return(
1048       m.Projection(0, (m.*dpi.constructor)(m.Parameter(0), m.Parameter(1))));
1049   Stream s = m.Build();
1050   ASSERT_EQ(1U, s.size());
1051   EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
1052   EXPECT_EQ(2U, s[0]->InputCount());
1053   EXPECT_LE(1U, s[0]->OutputCount());
1054   EXPECT_EQ(kFlags_none, s[0]->flags_mode());
1055 }
1056
1057
1058 TEST_P(InstructionSelectorOvfAddSubTest, ValImmediateOnRight) {
1059   const MachInst2 dpi = GetParam();
1060   const MachineType type = dpi.machine_type;
1061   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
1062     StreamBuilder m(this, type, type);
1063     m.Return(m.Projection(
1064         0, (m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm))));
1065     Stream s = m.Build();
1066     ASSERT_EQ(1U, s.size());
1067     EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
1068     ASSERT_EQ(2U, s[0]->InputCount());
1069     EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
1070     EXPECT_LE(1U, s[0]->OutputCount());
1071     EXPECT_EQ(kFlags_none, s[0]->flags_mode());
1072   }
1073 }
1074
1075
1076 TEST_P(InstructionSelectorOvfAddSubTest, BothParameter) {
1077   const MachInst2 dpi = GetParam();
1078   const MachineType type = dpi.machine_type;
1079   StreamBuilder m(this, type, type, type);
1080   Node* n = (m.*dpi.constructor)(m.Parameter(0), m.Parameter(1));
1081   m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n)));
1082   Stream s = m.Build();
1083   ASSERT_LE(1U, s.size());
1084   EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
1085   EXPECT_EQ(2U, s[0]->InputCount());
1086   EXPECT_EQ(2U, s[0]->OutputCount());
1087   EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1088   EXPECT_EQ(kOverflow, s[0]->flags_condition());
1089 }
1090
1091
1092 TEST_P(InstructionSelectorOvfAddSubTest, BothImmediateOnRight) {
1093   const MachInst2 dpi = GetParam();
1094   const MachineType type = dpi.machine_type;
1095   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
1096     StreamBuilder m(this, type, type);
1097     Node* n = (m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm));
1098     m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n)));
1099     Stream s = m.Build();
1100     ASSERT_LE(1U, s.size());
1101     EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
1102     ASSERT_EQ(2U, s[0]->InputCount());
1103     EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
1104     EXPECT_EQ(2U, s[0]->OutputCount());
1105     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1106     EXPECT_EQ(kOverflow, s[0]->flags_condition());
1107   }
1108 }
1109
1110
1111 TEST_P(InstructionSelectorOvfAddSubTest, BranchWithParameters) {
1112   const MachInst2 dpi = GetParam();
1113   const MachineType type = dpi.machine_type;
1114   StreamBuilder m(this, type, type, type);
1115   MLabel a, b;
1116   Node* n = (m.*dpi.constructor)(m.Parameter(0), m.Parameter(1));
1117   m.Branch(m.Projection(1, n), &a, &b);
1118   m.Bind(&a);
1119   m.Return(m.Int32Constant(0));
1120   m.Bind(&b);
1121   m.Return(m.Projection(0, n));
1122   Stream s = m.Build();
1123   ASSERT_EQ(1U, s.size());
1124   EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
1125   EXPECT_EQ(4U, s[0]->InputCount());
1126   EXPECT_EQ(1U, s[0]->OutputCount());
1127   EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
1128   EXPECT_EQ(kOverflow, s[0]->flags_condition());
1129 }
1130
1131
1132 TEST_P(InstructionSelectorOvfAddSubTest, BranchWithImmediateOnRight) {
1133   const MachInst2 dpi = GetParam();
1134   const MachineType type = dpi.machine_type;
1135   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
1136     StreamBuilder m(this, type, type);
1137     MLabel a, b;
1138     Node* n = (m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm));
1139     m.Branch(m.Projection(1, n), &a, &b);
1140     m.Bind(&a);
1141     m.Return(m.Int32Constant(0));
1142     m.Bind(&b);
1143     m.Return(m.Projection(0, n));
1144     Stream s = m.Build();
1145     ASSERT_EQ(1U, s.size());
1146     EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
1147     ASSERT_EQ(4U, s[0]->InputCount());
1148     EXPECT_EQ(1U, s[0]->OutputCount());
1149     EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
1150     EXPECT_EQ(kOverflow, s[0]->flags_condition());
1151   }
1152 }
1153
1154
1155 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1156                         InstructionSelectorOvfAddSubTest,
1157                         ::testing::ValuesIn(kOvfAddSubInstructions));
1158
1159
1160 TEST_F(InstructionSelectorTest, OvfFlagAddImmediateOnLeft) {
1161   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
1162     StreamBuilder m(this, kMachInt32, kMachInt32);
1163     m.Return(m.Projection(
1164         1, m.Int32AddWithOverflow(m.Int32Constant(imm), m.Parameter(0))));
1165     Stream s = m.Build();
1166
1167     ASSERT_EQ(1U, s.size());
1168     EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
1169     EXPECT_EQ(2U, s[0]->InputCount());
1170     EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
1171     EXPECT_LE(1U, s[0]->OutputCount());
1172     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1173     EXPECT_EQ(kOverflow, s[0]->flags_condition());
1174   }
1175 }
1176
1177
1178 TEST_F(InstructionSelectorTest, OvfValAddImmediateOnLeft) {
1179   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
1180     StreamBuilder m(this, kMachInt32, kMachInt32);
1181     m.Return(m.Projection(
1182         0, m.Int32AddWithOverflow(m.Int32Constant(imm), m.Parameter(0))));
1183     Stream s = m.Build();
1184
1185     ASSERT_EQ(1U, s.size());
1186     EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
1187     ASSERT_EQ(2U, s[0]->InputCount());
1188     EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
1189     EXPECT_LE(1U, s[0]->OutputCount());
1190     EXPECT_EQ(kFlags_none, s[0]->flags_mode());
1191   }
1192 }
1193
1194
1195 TEST_F(InstructionSelectorTest, OvfBothAddImmediateOnLeft) {
1196   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
1197     StreamBuilder m(this, kMachInt32, kMachInt32);
1198     Node* n = m.Int32AddWithOverflow(m.Int32Constant(imm), m.Parameter(0));
1199     m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n)));
1200     Stream s = m.Build();
1201
1202     ASSERT_LE(1U, s.size());
1203     EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
1204     ASSERT_EQ(2U, s[0]->InputCount());
1205     EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
1206     EXPECT_EQ(2U, s[0]->OutputCount());
1207     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1208     EXPECT_EQ(kOverflow, s[0]->flags_condition());
1209   }
1210 }
1211
1212
1213 TEST_F(InstructionSelectorTest, OvfBranchWithImmediateOnLeft) {
1214   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
1215     StreamBuilder m(this, kMachInt32, kMachInt32);
1216     MLabel a, b;
1217     Node* n = m.Int32AddWithOverflow(m.Int32Constant(imm), m.Parameter(0));
1218     m.Branch(m.Projection(1, n), &a, &b);
1219     m.Bind(&a);
1220     m.Return(m.Int32Constant(0));
1221     m.Bind(&b);
1222     m.Return(m.Projection(0, n));
1223     Stream s = m.Build();
1224
1225     ASSERT_EQ(1U, s.size());
1226     EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
1227     ASSERT_EQ(4U, s[0]->InputCount());
1228     EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
1229     EXPECT_EQ(1U, s[0]->OutputCount());
1230     EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
1231     EXPECT_EQ(kOverflow, s[0]->flags_condition());
1232   }
1233 }
1234
1235
1236 // -----------------------------------------------------------------------------
1237 // Shift instructions.
1238
1239
1240 typedef InstructionSelectorTestWithParam<Shift> InstructionSelectorShiftTest;
1241
1242
1243 TEST_P(InstructionSelectorShiftTest, Parameter) {
1244   const Shift shift = GetParam();
1245   const MachineType type = shift.mi.machine_type;
1246   StreamBuilder m(this, type, type, type);
1247   m.Return((m.*shift.mi.constructor)(m.Parameter(0), m.Parameter(1)));
1248   Stream s = m.Build();
1249   ASSERT_EQ(1U, s.size());
1250   EXPECT_EQ(shift.mi.arch_opcode, s[0]->arch_opcode());
1251   EXPECT_EQ(2U, s[0]->InputCount());
1252   EXPECT_EQ(1U, s[0]->OutputCount());
1253 }
1254
1255
1256 TEST_P(InstructionSelectorShiftTest, Immediate) {
1257   const Shift shift = GetParam();
1258   const MachineType type = shift.mi.machine_type;
1259   TRACED_FORRANGE(int32_t, imm, 0, (ElementSizeOf(type) * 8) - 1) {
1260     StreamBuilder m(this, type, type);
1261     m.Return((m.*shift.mi.constructor)(m.Parameter(0), m.Int32Constant(imm)));
1262     Stream s = m.Build();
1263     ASSERT_EQ(1U, s.size());
1264     EXPECT_EQ(shift.mi.arch_opcode, s[0]->arch_opcode());
1265     EXPECT_EQ(2U, s[0]->InputCount());
1266     EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
1267     EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
1268     EXPECT_EQ(1U, s[0]->OutputCount());
1269   }
1270 }
1271
1272
1273 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorShiftTest,
1274                         ::testing::ValuesIn(kShiftInstructions));
1275
1276
1277 TEST_F(InstructionSelectorTest, Word64ShlWithChangeInt32ToInt64) {
1278   TRACED_FORRANGE(int64_t, x, 32, 63) {
1279     StreamBuilder m(this, kMachInt64, kMachInt32);
1280     Node* const p0 = m.Parameter(0);
1281     Node* const n = m.Word64Shl(m.ChangeInt32ToInt64(p0), m.Int64Constant(x));
1282     m.Return(n);
1283     Stream s = m.Build();
1284     ASSERT_EQ(1U, s.size());
1285     EXPECT_EQ(kArm64Lsl, s[0]->arch_opcode());
1286     ASSERT_EQ(2U, s[0]->InputCount());
1287     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1288     EXPECT_EQ(x, s.ToInt64(s[0]->InputAt(1)));
1289     ASSERT_EQ(1U, s[0]->OutputCount());
1290     EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1291   }
1292 }
1293
1294
1295 TEST_F(InstructionSelectorTest, Word64ShlWithChangeUint32ToUint64) {
1296   TRACED_FORRANGE(int64_t, x, 32, 63) {
1297     StreamBuilder m(this, kMachInt64, kMachUint32);
1298     Node* const p0 = m.Parameter(0);
1299     Node* const n = m.Word64Shl(m.ChangeUint32ToUint64(p0), m.Int64Constant(x));
1300     m.Return(n);
1301     Stream s = m.Build();
1302     ASSERT_EQ(1U, s.size());
1303     EXPECT_EQ(kArm64Lsl, s[0]->arch_opcode());
1304     ASSERT_EQ(2U, s[0]->InputCount());
1305     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1306     EXPECT_EQ(x, s.ToInt64(s[0]->InputAt(1)));
1307     ASSERT_EQ(1U, s[0]->OutputCount());
1308     EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1309   }
1310 }
1311
1312
1313 TEST_F(InstructionSelectorTest, TruncateInt64ToInt32WithWord64Sar) {
1314   StreamBuilder m(this, kMachInt32, kMachInt64);
1315   Node* const p = m.Parameter(0);
1316   Node* const t = m.TruncateInt64ToInt32(m.Word64Sar(p, m.Int64Constant(32)));
1317   m.Return(t);
1318   Stream s = m.Build();
1319   ASSERT_EQ(1U, s.size());
1320   EXPECT_EQ(kArm64Lsr, s[0]->arch_opcode());
1321   ASSERT_EQ(2U, s[0]->InputCount());
1322   EXPECT_EQ(s.ToVreg(p), s.ToVreg(s[0]->InputAt(0)));
1323   EXPECT_EQ(32, s.ToInt64(s[0]->InputAt(1)));
1324   ASSERT_EQ(1U, s[0]->OutputCount());
1325   EXPECT_EQ(s.ToVreg(t), s.ToVreg(s[0]->OutputAt(0)));
1326 }
1327
1328
1329 TEST_F(InstructionSelectorTest, TruncateInt64ToInt32WithWord64Shr) {
1330   TRACED_FORRANGE(int64_t, x, 32, 63) {
1331     StreamBuilder m(this, kMachInt32, kMachInt64);
1332     Node* const p = m.Parameter(0);
1333     Node* const t = m.TruncateInt64ToInt32(m.Word64Shr(p, m.Int64Constant(x)));
1334     m.Return(t);
1335     Stream s = m.Build();
1336     ASSERT_EQ(1U, s.size());
1337     EXPECT_EQ(kArm64Lsr, s[0]->arch_opcode());
1338     ASSERT_EQ(2U, s[0]->InputCount());
1339     EXPECT_EQ(s.ToVreg(p), s.ToVreg(s[0]->InputAt(0)));
1340     EXPECT_EQ(x, s.ToInt64(s[0]->InputAt(1)));
1341     ASSERT_EQ(1U, s[0]->OutputCount());
1342     EXPECT_EQ(s.ToVreg(t), s.ToVreg(s[0]->OutputAt(0)));
1343   }
1344 }
1345
1346
1347 // -----------------------------------------------------------------------------
1348 // Mul and Div instructions.
1349
1350
1351 typedef InstructionSelectorTestWithParam<MachInst2>
1352     InstructionSelectorMulDivTest;
1353
1354
1355 TEST_P(InstructionSelectorMulDivTest, Parameter) {
1356   const MachInst2 dpi = GetParam();
1357   const MachineType type = dpi.machine_type;
1358   StreamBuilder m(this, type, type, type);
1359   m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)));
1360   Stream s = m.Build();
1361   ASSERT_EQ(1U, s.size());
1362   EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
1363   EXPECT_EQ(2U, s[0]->InputCount());
1364   EXPECT_EQ(1U, s[0]->OutputCount());
1365 }
1366
1367
1368 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorMulDivTest,
1369                         ::testing::ValuesIn(kMulDivInstructions));
1370
1371
1372 namespace {
1373
1374 struct MulDPInst {
1375   const char* mul_constructor_name;
1376   Node* (RawMachineAssembler::*mul_constructor)(Node*, Node*);
1377   Node* (RawMachineAssembler::*add_constructor)(Node*, Node*);
1378   Node* (RawMachineAssembler::*sub_constructor)(Node*, Node*);
1379   ArchOpcode add_arch_opcode;
1380   ArchOpcode sub_arch_opcode;
1381   ArchOpcode neg_arch_opcode;
1382   MachineType machine_type;
1383 };
1384
1385
1386 std::ostream& operator<<(std::ostream& os, const MulDPInst& inst) {
1387   return os << inst.mul_constructor_name;
1388 }
1389
1390 }  // namespace
1391
1392
1393 static const MulDPInst kMulDPInstructions[] = {
1394     {"Int32Mul", &RawMachineAssembler::Int32Mul, &RawMachineAssembler::Int32Add,
1395      &RawMachineAssembler::Int32Sub, kArm64Madd32, kArm64Msub32, kArm64Mneg32,
1396      kMachInt32},
1397     {"Int64Mul", &RawMachineAssembler::Int64Mul, &RawMachineAssembler::Int64Add,
1398      &RawMachineAssembler::Int64Sub, kArm64Madd, kArm64Msub, kArm64Mneg,
1399      kMachInt64}};
1400
1401
1402 typedef InstructionSelectorTestWithParam<MulDPInst>
1403     InstructionSelectorIntDPWithIntMulTest;
1404
1405
1406 TEST_P(InstructionSelectorIntDPWithIntMulTest, AddWithMul) {
1407   const MulDPInst mdpi = GetParam();
1408   const MachineType type = mdpi.machine_type;
1409   {
1410     StreamBuilder m(this, type, type, type, type);
1411     Node* n = (m.*mdpi.mul_constructor)(m.Parameter(1), m.Parameter(2));
1412     m.Return((m.*mdpi.add_constructor)(m.Parameter(0), n));
1413     Stream s = m.Build();
1414     ASSERT_EQ(1U, s.size());
1415     EXPECT_EQ(mdpi.add_arch_opcode, s[0]->arch_opcode());
1416     EXPECT_EQ(3U, s[0]->InputCount());
1417     EXPECT_EQ(1U, s[0]->OutputCount());
1418   }
1419   {
1420     StreamBuilder m(this, type, type, type, type);
1421     Node* n = (m.*mdpi.mul_constructor)(m.Parameter(0), m.Parameter(1));
1422     m.Return((m.*mdpi.add_constructor)(n, m.Parameter(2)));
1423     Stream s = m.Build();
1424     ASSERT_EQ(1U, s.size());
1425     EXPECT_EQ(mdpi.add_arch_opcode, s[0]->arch_opcode());
1426     EXPECT_EQ(3U, s[0]->InputCount());
1427     EXPECT_EQ(1U, s[0]->OutputCount());
1428   }
1429 }
1430
1431
1432 TEST_P(InstructionSelectorIntDPWithIntMulTest, SubWithMul) {
1433   const MulDPInst mdpi = GetParam();
1434   const MachineType type = mdpi.machine_type;
1435   {
1436     StreamBuilder m(this, type, type, type, type);
1437     Node* n = (m.*mdpi.mul_constructor)(m.Parameter(1), m.Parameter(2));
1438     m.Return((m.*mdpi.sub_constructor)(m.Parameter(0), n));
1439     Stream s = m.Build();
1440     ASSERT_EQ(1U, s.size());
1441     EXPECT_EQ(mdpi.sub_arch_opcode, s[0]->arch_opcode());
1442     EXPECT_EQ(3U, s[0]->InputCount());
1443     EXPECT_EQ(1U, s[0]->OutputCount());
1444   }
1445 }
1446
1447
1448 TEST_P(InstructionSelectorIntDPWithIntMulTest, NegativeMul) {
1449   const MulDPInst mdpi = GetParam();
1450   const MachineType type = mdpi.machine_type;
1451   {
1452     StreamBuilder m(this, type, type, type);
1453     Node* n =
1454         (m.*mdpi.sub_constructor)(BuildConstant(m, type, 0), m.Parameter(0));
1455     m.Return((m.*mdpi.mul_constructor)(n, m.Parameter(1)));
1456     Stream s = m.Build();
1457     ASSERT_EQ(1U, s.size());
1458     EXPECT_EQ(mdpi.neg_arch_opcode, s[0]->arch_opcode());
1459     EXPECT_EQ(2U, s[0]->InputCount());
1460     EXPECT_EQ(1U, s[0]->OutputCount());
1461   }
1462   {
1463     StreamBuilder m(this, type, type, type);
1464     Node* n =
1465         (m.*mdpi.sub_constructor)(BuildConstant(m, type, 0), m.Parameter(1));
1466     m.Return((m.*mdpi.mul_constructor)(m.Parameter(0), n));
1467     Stream s = m.Build();
1468     ASSERT_EQ(1U, s.size());
1469     EXPECT_EQ(mdpi.neg_arch_opcode, s[0]->arch_opcode());
1470     EXPECT_EQ(2U, s[0]->InputCount());
1471     EXPECT_EQ(1U, s[0]->OutputCount());
1472   }
1473 }
1474
1475
1476 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1477                         InstructionSelectorIntDPWithIntMulTest,
1478                         ::testing::ValuesIn(kMulDPInstructions));
1479
1480
1481 // -----------------------------------------------------------------------------
1482 // Floating point instructions.
1483
1484 typedef InstructionSelectorTestWithParam<MachInst2>
1485     InstructionSelectorFPArithTest;
1486
1487
1488 TEST_P(InstructionSelectorFPArithTest, Parameter) {
1489   const MachInst2 fpa = GetParam();
1490   StreamBuilder m(this, fpa.machine_type, fpa.machine_type, fpa.machine_type);
1491   m.Return((m.*fpa.constructor)(m.Parameter(0), m.Parameter(1)));
1492   Stream s = m.Build();
1493   ASSERT_EQ(1U, s.size());
1494   EXPECT_EQ(fpa.arch_opcode, s[0]->arch_opcode());
1495   EXPECT_EQ(2U, s[0]->InputCount());
1496   EXPECT_EQ(1U, s[0]->OutputCount());
1497 }
1498
1499
1500 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorFPArithTest,
1501                         ::testing::ValuesIn(kFPArithInstructions));
1502
1503
1504 typedef InstructionSelectorTestWithParam<FPCmp> InstructionSelectorFPCmpTest;
1505
1506
1507 TEST_P(InstructionSelectorFPCmpTest, Parameter) {
1508   const FPCmp cmp = GetParam();
1509   StreamBuilder m(this, kMachInt32, cmp.mi.machine_type, cmp.mi.machine_type);
1510   m.Return((m.*cmp.mi.constructor)(m.Parameter(0), m.Parameter(1)));
1511   Stream s = m.Build();
1512   ASSERT_EQ(1U, s.size());
1513   EXPECT_EQ(cmp.mi.arch_opcode, s[0]->arch_opcode());
1514   EXPECT_EQ(2U, s[0]->InputCount());
1515   EXPECT_EQ(1U, s[0]->OutputCount());
1516   EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1517   EXPECT_EQ(cmp.cond, s[0]->flags_condition());
1518 }
1519
1520
1521 TEST_P(InstructionSelectorFPCmpTest, WithImmediateZeroOnRight) {
1522   const FPCmp cmp = GetParam();
1523   StreamBuilder m(this, kMachInt32, cmp.mi.machine_type);
1524   m.Return((m.*cmp.mi.constructor)(m.Parameter(0), m.Float64Constant(0.0)));
1525   Stream s = m.Build();
1526   ASSERT_EQ(1U, s.size());
1527   EXPECT_EQ(cmp.mi.arch_opcode, s[0]->arch_opcode());
1528   EXPECT_EQ(2U, s[0]->InputCount());
1529   EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
1530   EXPECT_EQ(1U, s[0]->OutputCount());
1531   EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1532   EXPECT_EQ(cmp.cond, s[0]->flags_condition());
1533 }
1534
1535
1536 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorFPCmpTest,
1537                         ::testing::ValuesIn(kFPCmpInstructions));
1538
1539
1540 TEST_F(InstructionSelectorTest, Float64EqualWithImmediateZeroOnLeft) {
1541   StreamBuilder m(this, kMachInt32, kMachFloat64);
1542   m.Return(m.Float64Equal(m.Float64Constant(0.0), m.Parameter(0)));
1543   Stream s = m.Build();
1544   ASSERT_EQ(1U, s.size());
1545   EXPECT_EQ(kArm64Float64Cmp, s[0]->arch_opcode());
1546   EXPECT_EQ(2U, s[0]->InputCount());
1547   EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
1548   EXPECT_EQ(1U, s[0]->OutputCount());
1549   EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1550   EXPECT_EQ(kEqual, s[0]->flags_condition());
1551 }
1552
1553
1554 // -----------------------------------------------------------------------------
1555 // Conversions.
1556
1557 typedef InstructionSelectorTestWithParam<Conversion>
1558     InstructionSelectorConversionTest;
1559
1560
1561 TEST_P(InstructionSelectorConversionTest, Parameter) {
1562   const Conversion conv = GetParam();
1563   StreamBuilder m(this, conv.mi.machine_type, conv.src_machine_type);
1564   m.Return((m.*conv.mi.constructor)(m.Parameter(0)));
1565   Stream s = m.Build();
1566   ASSERT_EQ(1U, s.size());
1567   EXPECT_EQ(conv.mi.arch_opcode, s[0]->arch_opcode());
1568   EXPECT_EQ(1U, s[0]->InputCount());
1569   EXPECT_EQ(1U, s[0]->OutputCount());
1570 }
1571
1572
1573 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1574                         InstructionSelectorConversionTest,
1575                         ::testing::ValuesIn(kConversionInstructions));
1576
1577
1578 // -----------------------------------------------------------------------------
1579 // Memory access instructions.
1580
1581
1582 namespace {
1583
1584 struct MemoryAccess {
1585   MachineType type;
1586   ArchOpcode ldr_opcode;
1587   ArchOpcode str_opcode;
1588   const int32_t immediates[20];
1589 };
1590
1591
1592 std::ostream& operator<<(std::ostream& os, const MemoryAccess& memacc) {
1593   return os << memacc.type;
1594 }
1595
1596 }  // namespace
1597
1598
1599 static const MemoryAccess kMemoryAccesses[] = {
1600     {kMachInt8,
1601      kArm64Ldrsb,
1602      kArm64Strb,
1603      {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 257, 258, 1000, 1001, 2121,
1604       2442, 4093, 4094, 4095}},
1605     {kMachUint8,
1606      kArm64Ldrb,
1607      kArm64Strb,
1608      {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 257, 258, 1000, 1001, 2121,
1609       2442, 4093, 4094, 4095}},
1610     {kMachInt16,
1611      kArm64Ldrsh,
1612      kArm64Strh,
1613      {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 258, 260, 4096, 4098, 4100,
1614       4242, 6786, 8188, 8190}},
1615     {kMachUint16,
1616      kArm64Ldrh,
1617      kArm64Strh,
1618      {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 258, 260, 4096, 4098, 4100,
1619       4242, 6786, 8188, 8190}},
1620     {kMachInt32,
1621      kArm64LdrW,
1622      kArm64StrW,
1623      {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 260, 4096, 4100, 8192, 8196,
1624       3276, 3280, 16376, 16380}},
1625     {kMachUint32,
1626      kArm64LdrW,
1627      kArm64StrW,
1628      {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 260, 4096, 4100, 8192, 8196,
1629       3276, 3280, 16376, 16380}},
1630     {kMachInt64,
1631      kArm64Ldr,
1632      kArm64Str,
1633      {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 264, 4096, 4104, 8192, 8200,
1634       16384, 16392, 32752, 32760}},
1635     {kMachUint64,
1636      kArm64Ldr,
1637      kArm64Str,
1638      {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 264, 4096, 4104, 8192, 8200,
1639       16384, 16392, 32752, 32760}},
1640     {kMachFloat32,
1641      kArm64LdrS,
1642      kArm64StrS,
1643      {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 260, 4096, 4100, 8192, 8196,
1644       3276, 3280, 16376, 16380}},
1645     {kMachFloat64,
1646      kArm64LdrD,
1647      kArm64StrD,
1648      {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 264, 4096, 4104, 8192, 8200,
1649       16384, 16392, 32752, 32760}}};
1650
1651
1652 typedef InstructionSelectorTestWithParam<MemoryAccess>
1653     InstructionSelectorMemoryAccessTest;
1654
1655
1656 TEST_P(InstructionSelectorMemoryAccessTest, LoadWithParameters) {
1657   const MemoryAccess memacc = GetParam();
1658   StreamBuilder m(this, memacc.type, kMachPtr, kMachInt32);
1659   m.Return(m.Load(memacc.type, m.Parameter(0), m.Parameter(1)));
1660   Stream s = m.Build();
1661   ASSERT_EQ(1U, s.size());
1662   EXPECT_EQ(memacc.ldr_opcode, s[0]->arch_opcode());
1663   EXPECT_EQ(kMode_MRR, s[0]->addressing_mode());
1664   EXPECT_EQ(2U, s[0]->InputCount());
1665   EXPECT_EQ(1U, s[0]->OutputCount());
1666 }
1667
1668
1669 TEST_P(InstructionSelectorMemoryAccessTest, LoadWithImmediateIndex) {
1670   const MemoryAccess memacc = GetParam();
1671   TRACED_FOREACH(int32_t, index, memacc.immediates) {
1672     StreamBuilder m(this, memacc.type, kMachPtr);
1673     m.Return(m.Load(memacc.type, m.Parameter(0), m.Int32Constant(index)));
1674     Stream s = m.Build();
1675     ASSERT_EQ(1U, s.size());
1676     EXPECT_EQ(memacc.ldr_opcode, s[0]->arch_opcode());
1677     EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
1678     EXPECT_EQ(2U, s[0]->InputCount());
1679     ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
1680     EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1)));
1681     ASSERT_EQ(1U, s[0]->OutputCount());
1682   }
1683 }
1684
1685
1686 TEST_P(InstructionSelectorMemoryAccessTest, StoreWithParameters) {
1687   const MemoryAccess memacc = GetParam();
1688   StreamBuilder m(this, kMachInt32, kMachPtr, kMachInt32, memacc.type);
1689   m.Store(memacc.type, m.Parameter(0), m.Parameter(1), m.Parameter(2));
1690   m.Return(m.Int32Constant(0));
1691   Stream s = m.Build();
1692   ASSERT_EQ(1U, s.size());
1693   EXPECT_EQ(memacc.str_opcode, s[0]->arch_opcode());
1694   EXPECT_EQ(kMode_MRR, s[0]->addressing_mode());
1695   EXPECT_EQ(3U, s[0]->InputCount());
1696   EXPECT_EQ(0U, s[0]->OutputCount());
1697 }
1698
1699
1700 TEST_P(InstructionSelectorMemoryAccessTest, StoreWithImmediateIndex) {
1701   const MemoryAccess memacc = GetParam();
1702   TRACED_FOREACH(int32_t, index, memacc.immediates) {
1703     StreamBuilder m(this, kMachInt32, kMachPtr, memacc.type);
1704     m.Store(memacc.type, m.Parameter(0), m.Int32Constant(index),
1705             m.Parameter(1));
1706     m.Return(m.Int32Constant(0));
1707     Stream s = m.Build();
1708     ASSERT_EQ(1U, s.size());
1709     EXPECT_EQ(memacc.str_opcode, s[0]->arch_opcode());
1710     EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
1711     ASSERT_EQ(3U, s[0]->InputCount());
1712     ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
1713     EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1)));
1714     EXPECT_EQ(0U, s[0]->OutputCount());
1715   }
1716 }
1717
1718
1719 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1720                         InstructionSelectorMemoryAccessTest,
1721                         ::testing::ValuesIn(kMemoryAccesses));
1722
1723
1724 // -----------------------------------------------------------------------------
1725 // Comparison instructions.
1726
1727 static const MachInst2 kComparisonInstructions[] = {
1728     {&RawMachineAssembler::Word32Equal, "Word32Equal", kArm64Cmp32, kMachInt32},
1729     {&RawMachineAssembler::Word64Equal, "Word64Equal", kArm64Cmp, kMachInt64},
1730 };
1731
1732
1733 typedef InstructionSelectorTestWithParam<MachInst2>
1734     InstructionSelectorComparisonTest;
1735
1736
1737 TEST_P(InstructionSelectorComparisonTest, WithParameters) {
1738   const MachInst2 cmp = GetParam();
1739   const MachineType type = cmp.machine_type;
1740   StreamBuilder m(this, type, type, type);
1741   m.Return((m.*cmp.constructor)(m.Parameter(0), m.Parameter(1)));
1742   Stream s = m.Build();
1743   ASSERT_EQ(1U, s.size());
1744   EXPECT_EQ(cmp.arch_opcode, s[0]->arch_opcode());
1745   EXPECT_EQ(2U, s[0]->InputCount());
1746   EXPECT_EQ(1U, s[0]->OutputCount());
1747   EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1748   EXPECT_EQ(kEqual, s[0]->flags_condition());
1749 }
1750
1751
1752 TEST_P(InstructionSelectorComparisonTest, WithImmediate) {
1753   const MachInst2 cmp = GetParam();
1754   const MachineType type = cmp.machine_type;
1755   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
1756     // Compare with 0 are turned into tst instruction.
1757     if (imm == 0) continue;
1758     StreamBuilder m(this, type, type);
1759     m.Return((m.*cmp.constructor)(m.Parameter(0), BuildConstant(m, type, imm)));
1760     Stream s = m.Build();
1761     ASSERT_EQ(1U, s.size());
1762     EXPECT_EQ(cmp.arch_opcode, s[0]->arch_opcode());
1763     ASSERT_EQ(2U, s[0]->InputCount());
1764     ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
1765     EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(1)));
1766     EXPECT_EQ(1U, s[0]->OutputCount());
1767     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1768     EXPECT_EQ(kEqual, s[0]->flags_condition());
1769   }
1770   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
1771     // Compare with 0 are turned into tst instruction.
1772     if (imm == 0) continue;
1773     StreamBuilder m(this, type, type);
1774     m.Return((m.*cmp.constructor)(BuildConstant(m, type, imm), m.Parameter(0)));
1775     Stream s = m.Build();
1776     ASSERT_EQ(1U, s.size());
1777     EXPECT_EQ(cmp.arch_opcode, s[0]->arch_opcode());
1778     ASSERT_EQ(2U, s[0]->InputCount());
1779     ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
1780     EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(1)));
1781     EXPECT_EQ(1U, s[0]->OutputCount());
1782     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1783     EXPECT_EQ(kEqual, s[0]->flags_condition());
1784   }
1785 }
1786
1787 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1788                         InstructionSelectorComparisonTest,
1789                         ::testing::ValuesIn(kComparisonInstructions));
1790
1791
1792 TEST_F(InstructionSelectorTest, Word32EqualWithZero) {
1793   {
1794     StreamBuilder m(this, kMachInt32, kMachInt32);
1795     m.Return(m.Word32Equal(m.Parameter(0), m.Int32Constant(0)));
1796     Stream s = m.Build();
1797     ASSERT_EQ(1U, s.size());
1798     EXPECT_EQ(kArm64Tst32, s[0]->arch_opcode());
1799     ASSERT_EQ(2U, s[0]->InputCount());
1800     EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
1801     EXPECT_EQ(1U, s[0]->OutputCount());
1802     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1803     EXPECT_EQ(kEqual, s[0]->flags_condition());
1804   }
1805   {
1806     StreamBuilder m(this, kMachInt32, kMachInt32);
1807     m.Return(m.Word32Equal(m.Int32Constant(0), m.Parameter(0)));
1808     Stream s = m.Build();
1809     ASSERT_EQ(1U, s.size());
1810     EXPECT_EQ(kArm64Tst32, s[0]->arch_opcode());
1811     ASSERT_EQ(2U, s[0]->InputCount());
1812     EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
1813     EXPECT_EQ(1U, s[0]->OutputCount());
1814     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1815     EXPECT_EQ(kEqual, s[0]->flags_condition());
1816   }
1817 }
1818
1819
1820 TEST_F(InstructionSelectorTest, Word64EqualWithZero) {
1821   {
1822     StreamBuilder m(this, kMachInt64, kMachInt64);
1823     m.Return(m.Word64Equal(m.Parameter(0), m.Int64Constant(0)));
1824     Stream s = m.Build();
1825     ASSERT_EQ(1U, s.size());
1826     EXPECT_EQ(kArm64Tst, s[0]->arch_opcode());
1827     ASSERT_EQ(2U, s[0]->InputCount());
1828     EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
1829     EXPECT_EQ(1U, s[0]->OutputCount());
1830     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1831     EXPECT_EQ(kEqual, s[0]->flags_condition());
1832   }
1833   {
1834     StreamBuilder m(this, kMachInt64, kMachInt64);
1835     m.Return(m.Word64Equal(m.Int64Constant(0), m.Parameter(0)));
1836     Stream s = m.Build();
1837     ASSERT_EQ(1U, s.size());
1838     EXPECT_EQ(kArm64Tst, s[0]->arch_opcode());
1839     ASSERT_EQ(2U, s[0]->InputCount());
1840     EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
1841     EXPECT_EQ(1U, s[0]->OutputCount());
1842     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1843     EXPECT_EQ(kEqual, s[0]->flags_condition());
1844   }
1845 }
1846
1847
1848 // -----------------------------------------------------------------------------
1849 // Miscellaneous
1850
1851
1852 static const MachInst2 kLogicalWithNotRHSs[] = {
1853     {&RawMachineAssembler::Word32And, "Word32And", kArm64Bic32, kMachInt32},
1854     {&RawMachineAssembler::Word64And, "Word64And", kArm64Bic, kMachInt64},
1855     {&RawMachineAssembler::Word32Or, "Word32Or", kArm64Orn32, kMachInt32},
1856     {&RawMachineAssembler::Word64Or, "Word64Or", kArm64Orn, kMachInt64},
1857     {&RawMachineAssembler::Word32Xor, "Word32Xor", kArm64Eon32, kMachInt32},
1858     {&RawMachineAssembler::Word64Xor, "Word64Xor", kArm64Eon, kMachInt64}};
1859
1860
1861 typedef InstructionSelectorTestWithParam<MachInst2>
1862     InstructionSelectorLogicalWithNotRHSTest;
1863
1864
1865 TEST_P(InstructionSelectorLogicalWithNotRHSTest, Parameter) {
1866   const MachInst2 inst = GetParam();
1867   const MachineType type = inst.machine_type;
1868   // Test cases where RHS is Xor(x, -1).
1869   {
1870     StreamBuilder m(this, type, type, type);
1871     if (type == kMachInt32) {
1872       m.Return((m.*inst.constructor)(
1873           m.Parameter(0), m.Word32Xor(m.Parameter(1), m.Int32Constant(-1))));
1874     } else {
1875       ASSERT_EQ(kMachInt64, type);
1876       m.Return((m.*inst.constructor)(
1877           m.Parameter(0), m.Word64Xor(m.Parameter(1), m.Int64Constant(-1))));
1878     }
1879     Stream s = m.Build();
1880     ASSERT_EQ(1U, s.size());
1881     EXPECT_EQ(inst.arch_opcode, s[0]->arch_opcode());
1882     EXPECT_EQ(2U, s[0]->InputCount());
1883     EXPECT_EQ(1U, s[0]->OutputCount());
1884   }
1885   {
1886     StreamBuilder m(this, type, type, type);
1887     if (type == kMachInt32) {
1888       m.Return((m.*inst.constructor)(
1889           m.Word32Xor(m.Parameter(0), m.Int32Constant(-1)), m.Parameter(1)));
1890     } else {
1891       ASSERT_EQ(kMachInt64, type);
1892       m.Return((m.*inst.constructor)(
1893           m.Word64Xor(m.Parameter(0), m.Int64Constant(-1)), m.Parameter(1)));
1894     }
1895     Stream s = m.Build();
1896     ASSERT_EQ(1U, s.size());
1897     EXPECT_EQ(inst.arch_opcode, s[0]->arch_opcode());
1898     EXPECT_EQ(2U, s[0]->InputCount());
1899     EXPECT_EQ(1U, s[0]->OutputCount());
1900   }
1901   // Test cases where RHS is Not(x).
1902   {
1903     StreamBuilder m(this, type, type, type);
1904     if (type == kMachInt32) {
1905       m.Return(
1906           (m.*inst.constructor)(m.Parameter(0), m.Word32Not(m.Parameter(1))));
1907     } else {
1908       ASSERT_EQ(kMachInt64, type);
1909       m.Return(
1910           (m.*inst.constructor)(m.Parameter(0), m.Word64Not(m.Parameter(1))));
1911     }
1912     Stream s = m.Build();
1913     ASSERT_EQ(1U, s.size());
1914     EXPECT_EQ(inst.arch_opcode, s[0]->arch_opcode());
1915     EXPECT_EQ(2U, s[0]->InputCount());
1916     EXPECT_EQ(1U, s[0]->OutputCount());
1917   }
1918   {
1919     StreamBuilder m(this, type, type, type);
1920     if (type == kMachInt32) {
1921       m.Return(
1922           (m.*inst.constructor)(m.Word32Not(m.Parameter(0)), m.Parameter(1)));
1923     } else {
1924       ASSERT_EQ(kMachInt64, type);
1925       m.Return(
1926           (m.*inst.constructor)(m.Word64Not(m.Parameter(0)), m.Parameter(1)));
1927     }
1928     Stream s = m.Build();
1929     ASSERT_EQ(1U, s.size());
1930     EXPECT_EQ(inst.arch_opcode, s[0]->arch_opcode());
1931     EXPECT_EQ(2U, s[0]->InputCount());
1932     EXPECT_EQ(1U, s[0]->OutputCount());
1933   }
1934 }
1935
1936
1937 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1938                         InstructionSelectorLogicalWithNotRHSTest,
1939                         ::testing::ValuesIn(kLogicalWithNotRHSs));
1940
1941
1942 TEST_F(InstructionSelectorTest, Word32NotWithParameter) {
1943   StreamBuilder m(this, kMachInt32, kMachInt32);
1944   m.Return(m.Word32Not(m.Parameter(0)));
1945   Stream s = m.Build();
1946   ASSERT_EQ(1U, s.size());
1947   EXPECT_EQ(kArm64Not32, s[0]->arch_opcode());
1948   EXPECT_EQ(1U, s[0]->InputCount());
1949   EXPECT_EQ(1U, s[0]->OutputCount());
1950 }
1951
1952
1953 TEST_F(InstructionSelectorTest, Word64NotWithParameter) {
1954   StreamBuilder m(this, kMachInt64, kMachInt64);
1955   m.Return(m.Word64Not(m.Parameter(0)));
1956   Stream s = m.Build();
1957   ASSERT_EQ(1U, s.size());
1958   EXPECT_EQ(kArm64Not, s[0]->arch_opcode());
1959   EXPECT_EQ(1U, s[0]->InputCount());
1960   EXPECT_EQ(1U, s[0]->OutputCount());
1961 }
1962
1963
1964 TEST_F(InstructionSelectorTest, Word32XorMinusOneWithParameter) {
1965   {
1966     StreamBuilder m(this, kMachInt32, kMachInt32);
1967     m.Return(m.Word32Xor(m.Parameter(0), m.Int32Constant(-1)));
1968     Stream s = m.Build();
1969     ASSERT_EQ(1U, s.size());
1970     EXPECT_EQ(kArm64Not32, s[0]->arch_opcode());
1971     EXPECT_EQ(1U, s[0]->InputCount());
1972     EXPECT_EQ(1U, s[0]->OutputCount());
1973   }
1974   {
1975     StreamBuilder m(this, kMachInt32, kMachInt32);
1976     m.Return(m.Word32Xor(m.Int32Constant(-1), m.Parameter(0)));
1977     Stream s = m.Build();
1978     ASSERT_EQ(1U, s.size());
1979     EXPECT_EQ(kArm64Not32, s[0]->arch_opcode());
1980     EXPECT_EQ(1U, s[0]->InputCount());
1981     EXPECT_EQ(1U, s[0]->OutputCount());
1982   }
1983 }
1984
1985
1986 TEST_F(InstructionSelectorTest, Word64XorMinusOneWithParameter) {
1987   {
1988     StreamBuilder m(this, kMachInt64, kMachInt64);
1989     m.Return(m.Word64Xor(m.Parameter(0), m.Int64Constant(-1)));
1990     Stream s = m.Build();
1991     ASSERT_EQ(1U, s.size());
1992     EXPECT_EQ(kArm64Not, s[0]->arch_opcode());
1993     EXPECT_EQ(1U, s[0]->InputCount());
1994     EXPECT_EQ(1U, s[0]->OutputCount());
1995   }
1996   {
1997     StreamBuilder m(this, kMachInt64, kMachInt64);
1998     m.Return(m.Word64Xor(m.Int64Constant(-1), m.Parameter(0)));
1999     Stream s = m.Build();
2000     ASSERT_EQ(1U, s.size());
2001     EXPECT_EQ(kArm64Not, s[0]->arch_opcode());
2002     EXPECT_EQ(1U, s[0]->InputCount());
2003     EXPECT_EQ(1U, s[0]->OutputCount());
2004   }
2005 }
2006
2007
2008 TEST_F(InstructionSelectorTest, Word32ShrWithWord32AndWithImmediate) {
2009   TRACED_FORRANGE(int32_t, lsb, 1, 31) {
2010     TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) {
2011       uint32_t jnk = rng()->NextInt();
2012       jnk >>= 32 - lsb;
2013       uint32_t msk = ((0xffffffffu >> (32 - width)) << lsb) | jnk;
2014       StreamBuilder m(this, kMachInt32, kMachInt32);
2015       m.Return(m.Word32Shr(m.Word32And(m.Parameter(0), m.Int32Constant(msk)),
2016                            m.Int32Constant(lsb)));
2017       Stream s = m.Build();
2018       ASSERT_EQ(1U, s.size());
2019       EXPECT_EQ(kArm64Ubfx32, s[0]->arch_opcode());
2020       ASSERT_EQ(3U, s[0]->InputCount());
2021       EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
2022       EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
2023     }
2024   }
2025   TRACED_FORRANGE(int32_t, lsb, 1, 31) {
2026     TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) {
2027       uint32_t jnk = rng()->NextInt();
2028       jnk >>= 32 - lsb;
2029       uint32_t msk = ((0xffffffffu >> (32 - width)) << lsb) | jnk;
2030       StreamBuilder m(this, kMachInt32, kMachInt32);
2031       m.Return(m.Word32Shr(m.Word32And(m.Int32Constant(msk), m.Parameter(0)),
2032                            m.Int32Constant(lsb)));
2033       Stream s = m.Build();
2034       ASSERT_EQ(1U, s.size());
2035       EXPECT_EQ(kArm64Ubfx32, s[0]->arch_opcode());
2036       ASSERT_EQ(3U, s[0]->InputCount());
2037       EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
2038       EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
2039     }
2040   }
2041 }
2042
2043
2044 TEST_F(InstructionSelectorTest, Word64ShrWithWord64AndWithImmediate) {
2045   TRACED_FORRANGE(int32_t, lsb, 1, 63) {
2046     TRACED_FORRANGE(int32_t, width, 1, 64 - lsb) {
2047       uint64_t jnk = rng()->NextInt64();
2048       jnk >>= 64 - lsb;
2049       uint64_t msk =
2050           ((V8_UINT64_C(0xffffffffffffffff) >> (64 - width)) << lsb) | jnk;
2051       StreamBuilder m(this, kMachInt64, kMachInt64);
2052       m.Return(m.Word64Shr(m.Word64And(m.Parameter(0), m.Int64Constant(msk)),
2053                            m.Int64Constant(lsb)));
2054       Stream s = m.Build();
2055       ASSERT_EQ(1U, s.size());
2056       EXPECT_EQ(kArm64Ubfx, s[0]->arch_opcode());
2057       ASSERT_EQ(3U, s[0]->InputCount());
2058       EXPECT_EQ(lsb, s.ToInt64(s[0]->InputAt(1)));
2059       EXPECT_EQ(width, s.ToInt64(s[0]->InputAt(2)));
2060     }
2061   }
2062   TRACED_FORRANGE(int32_t, lsb, 1, 63) {
2063     TRACED_FORRANGE(int32_t, width, 1, 64 - lsb) {
2064       uint64_t jnk = rng()->NextInt64();
2065       jnk >>= 64 - lsb;
2066       uint64_t msk =
2067           ((V8_UINT64_C(0xffffffffffffffff) >> (64 - width)) << lsb) | jnk;
2068       StreamBuilder m(this, kMachInt64, kMachInt64);
2069       m.Return(m.Word64Shr(m.Word64And(m.Int64Constant(msk), m.Parameter(0)),
2070                            m.Int64Constant(lsb)));
2071       Stream s = m.Build();
2072       ASSERT_EQ(1U, s.size());
2073       EXPECT_EQ(kArm64Ubfx, s[0]->arch_opcode());
2074       ASSERT_EQ(3U, s[0]->InputCount());
2075       EXPECT_EQ(lsb, s.ToInt64(s[0]->InputAt(1)));
2076       EXPECT_EQ(width, s.ToInt64(s[0]->InputAt(2)));
2077     }
2078   }
2079 }
2080
2081
2082 TEST_F(InstructionSelectorTest, Word32AndWithImmediateWithWord32Shr) {
2083   TRACED_FORRANGE(int32_t, lsb, 1, 31) {
2084     TRACED_FORRANGE(int32_t, width, 1, 31) {
2085       uint32_t msk = (1 << width) - 1;
2086       StreamBuilder m(this, kMachInt32, kMachInt32);
2087       m.Return(m.Word32And(m.Word32Shr(m.Parameter(0), m.Int32Constant(lsb)),
2088                            m.Int32Constant(msk)));
2089       Stream s = m.Build();
2090       ASSERT_EQ(1U, s.size());
2091       EXPECT_EQ(kArm64Ubfx32, s[0]->arch_opcode());
2092       ASSERT_EQ(3U, s[0]->InputCount());
2093       EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
2094       int32_t actual_width = (lsb + width > 32) ? (32 - lsb) : width;
2095       EXPECT_EQ(actual_width, s.ToInt32(s[0]->InputAt(2)));
2096     }
2097   }
2098   TRACED_FORRANGE(int32_t, lsb, 1, 31) {
2099     TRACED_FORRANGE(int32_t, width, 1, 31) {
2100       uint32_t msk = (1 << width) - 1;
2101       StreamBuilder m(this, kMachInt32, kMachInt32);
2102       m.Return(m.Word32And(m.Int32Constant(msk),
2103                            m.Word32Shr(m.Parameter(0), m.Int32Constant(lsb))));
2104       Stream s = m.Build();
2105       ASSERT_EQ(1U, s.size());
2106       EXPECT_EQ(kArm64Ubfx32, s[0]->arch_opcode());
2107       ASSERT_EQ(3U, s[0]->InputCount());
2108       EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
2109       int32_t actual_width = (lsb + width > 32) ? (32 - lsb) : width;
2110       EXPECT_EQ(actual_width, s.ToInt32(s[0]->InputAt(2)));
2111     }
2112   }
2113 }
2114
2115
2116 TEST_F(InstructionSelectorTest, Word64AndWithImmediateWithWord64Shr) {
2117   TRACED_FORRANGE(int64_t, lsb, 1, 63) {
2118     TRACED_FORRANGE(int64_t, width, 1, 63) {
2119       uint64_t msk = (V8_UINT64_C(1) << width) - 1;
2120       StreamBuilder m(this, kMachInt64, kMachInt64);
2121       m.Return(m.Word64And(m.Word64Shr(m.Parameter(0), m.Int64Constant(lsb)),
2122                            m.Int64Constant(msk)));
2123       Stream s = m.Build();
2124       ASSERT_EQ(1U, s.size());
2125       EXPECT_EQ(kArm64Ubfx, s[0]->arch_opcode());
2126       ASSERT_EQ(3U, s[0]->InputCount());
2127       EXPECT_EQ(lsb, s.ToInt64(s[0]->InputAt(1)));
2128       int64_t actual_width = (lsb + width > 64) ? (64 - lsb) : width;
2129       EXPECT_EQ(actual_width, s.ToInt64(s[0]->InputAt(2)));
2130     }
2131   }
2132   TRACED_FORRANGE(int64_t, lsb, 1, 63) {
2133     TRACED_FORRANGE(int64_t, width, 1, 63) {
2134       uint64_t msk = (V8_UINT64_C(1) << width) - 1;
2135       StreamBuilder m(this, kMachInt64, kMachInt64);
2136       m.Return(m.Word64And(m.Int64Constant(msk),
2137                            m.Word64Shr(m.Parameter(0), m.Int64Constant(lsb))));
2138       Stream s = m.Build();
2139       ASSERT_EQ(1U, s.size());
2140       EXPECT_EQ(kArm64Ubfx, s[0]->arch_opcode());
2141       ASSERT_EQ(3U, s[0]->InputCount());
2142       EXPECT_EQ(lsb, s.ToInt64(s[0]->InputAt(1)));
2143       int64_t actual_width = (lsb + width > 64) ? (64 - lsb) : width;
2144       EXPECT_EQ(actual_width, s.ToInt64(s[0]->InputAt(2)));
2145     }
2146   }
2147 }
2148
2149
2150 TEST_F(InstructionSelectorTest, Int32MulHighWithParameters) {
2151   StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
2152   Node* const p0 = m.Parameter(0);
2153   Node* const p1 = m.Parameter(1);
2154   Node* const n = m.Int32MulHigh(p0, p1);
2155   m.Return(n);
2156   Stream s = m.Build();
2157   ASSERT_EQ(2U, s.size());
2158   EXPECT_EQ(kArm64Smull, s[0]->arch_opcode());
2159   ASSERT_EQ(2U, s[0]->InputCount());
2160   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
2161   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
2162   ASSERT_EQ(1U, s[0]->OutputCount());
2163   EXPECT_EQ(kArm64Asr, s[1]->arch_opcode());
2164   ASSERT_EQ(2U, s[1]->InputCount());
2165   EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(0)));
2166   EXPECT_EQ(32, s.ToInt64(s[1]->InputAt(1)));
2167   ASSERT_EQ(1U, s[1]->OutputCount());
2168   EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[1]->Output()));
2169 }
2170
2171
2172 TEST_F(InstructionSelectorTest, Word32SarWithWord32Shl) {
2173   {
2174     StreamBuilder m(this, kMachInt32, kMachInt32);
2175     Node* const p0 = m.Parameter(0);
2176     Node* const r =
2177         m.Word32Sar(m.Word32Shl(p0, m.Int32Constant(24)), m.Int32Constant(24));
2178     m.Return(r);
2179     Stream s = m.Build();
2180     ASSERT_EQ(1U, s.size());
2181     EXPECT_EQ(kArm64Sxtb32, s[0]->arch_opcode());
2182     ASSERT_EQ(1U, s[0]->InputCount());
2183     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
2184     ASSERT_EQ(1U, s[0]->OutputCount());
2185     EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
2186   }
2187   {
2188     StreamBuilder m(this, kMachInt32, kMachInt32);
2189     Node* const p0 = m.Parameter(0);
2190     Node* const r =
2191         m.Word32Sar(m.Word32Shl(p0, m.Int32Constant(16)), m.Int32Constant(16));
2192     m.Return(r);
2193     Stream s = m.Build();
2194     ASSERT_EQ(1U, s.size());
2195     EXPECT_EQ(kArm64Sxth32, s[0]->arch_opcode());
2196     ASSERT_EQ(1U, s[0]->InputCount());
2197     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
2198     ASSERT_EQ(1U, s[0]->OutputCount());
2199     EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
2200   }
2201 }
2202
2203 }  // namespace compiler
2204 }  // namespace internal
2205 }  // namespace v8