deps: update v8 to 4.3.61.21
[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 TEST_P(InstructionSelectorAddSubTest, ExtendByte) {
476   const AddSub dpi = GetParam();
477   const MachineType type = dpi.mi.machine_type;
478   StreamBuilder m(this, type, type, type);
479   m.Return((m.*dpi.mi.constructor)(
480       m.Parameter(0), m.Word32And(m.Parameter(1), m.Int32Constant(0xff))));
481   Stream s = m.Build();
482   ASSERT_EQ(1U, s.size());
483   EXPECT_EQ(dpi.mi.arch_opcode, s[0]->arch_opcode());
484   EXPECT_EQ(kMode_Operand2_R_UXTB, s[0]->addressing_mode());
485   ASSERT_EQ(2U, s[0]->InputCount());
486   ASSERT_EQ(1U, s[0]->OutputCount());
487 }
488
489
490 TEST_P(InstructionSelectorAddSubTest, ExtendHalfword) {
491   const AddSub dpi = GetParam();
492   const MachineType type = dpi.mi.machine_type;
493   StreamBuilder m(this, type, type, type);
494   m.Return((m.*dpi.mi.constructor)(
495       m.Parameter(0), m.Word32And(m.Parameter(1), m.Int32Constant(0xffff))));
496   Stream s = m.Build();
497   ASSERT_EQ(1U, s.size());
498   EXPECT_EQ(dpi.mi.arch_opcode, s[0]->arch_opcode());
499   EXPECT_EQ(kMode_Operand2_R_UXTH, s[0]->addressing_mode());
500   ASSERT_EQ(2U, s[0]->InputCount());
501   ASSERT_EQ(1U, s[0]->OutputCount());
502 }
503
504
505 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorAddSubTest,
506                         ::testing::ValuesIn(kAddSubInstructions));
507
508
509 TEST_F(InstructionSelectorTest, AddImmediateOnLeft) {
510   {
511     // 32-bit add.
512     TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
513       StreamBuilder m(this, kMachInt32, kMachInt32);
514       m.Return(m.Int32Add(m.Int32Constant(imm), m.Parameter(0)));
515       Stream s = m.Build();
516       ASSERT_EQ(1U, s.size());
517       EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
518       ASSERT_EQ(2U, s[0]->InputCount());
519       EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
520       EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
521       EXPECT_EQ(1U, s[0]->OutputCount());
522     }
523   }
524   {
525     // 64-bit add.
526     TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
527       StreamBuilder m(this, kMachInt64, kMachInt64);
528       m.Return(m.Int64Add(m.Int64Constant(imm), m.Parameter(0)));
529       Stream s = m.Build();
530       ASSERT_EQ(1U, s.size());
531       EXPECT_EQ(kArm64Add, s[0]->arch_opcode());
532       ASSERT_EQ(2U, s[0]->InputCount());
533       EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
534       EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(1)));
535       EXPECT_EQ(1U, s[0]->OutputCount());
536     }
537   }
538 }
539
540
541 TEST_F(InstructionSelectorTest, SubZeroOnLeft) {
542   // Subtraction with zero on the left maps to Neg.
543   {
544     // 32-bit subtract.
545     StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
546     m.Return(m.Int32Sub(m.Int32Constant(0), m.Parameter(0)));
547     Stream s = m.Build();
548
549     ASSERT_EQ(1U, s.size());
550     EXPECT_EQ(kArm64Neg32, s[0]->arch_opcode());
551     EXPECT_EQ(1U, s[0]->InputCount());
552     EXPECT_EQ(1U, s[0]->OutputCount());
553   }
554   {
555     // 64-bit subtract.
556     StreamBuilder m(this, kMachInt64, kMachInt64, kMachInt64);
557     m.Return(m.Int64Sub(m.Int64Constant(0), m.Parameter(0)));
558     Stream s = m.Build();
559
560     ASSERT_EQ(1U, s.size());
561     EXPECT_EQ(kArm64Neg, s[0]->arch_opcode());
562     EXPECT_EQ(1U, s[0]->InputCount());
563     EXPECT_EQ(1U, s[0]->OutputCount());
564   }
565 }
566
567
568 TEST_F(InstructionSelectorTest, AddNegImmediateOnLeft) {
569   {
570     // 32-bit add.
571     TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
572       if (imm == 0) continue;
573       StreamBuilder m(this, kMachInt32, kMachInt32);
574       m.Return(m.Int32Add(m.Int32Constant(-imm), m.Parameter(0)));
575       Stream s = m.Build();
576
577       ASSERT_EQ(1U, s.size());
578       EXPECT_EQ(kArm64Sub32, s[0]->arch_opcode());
579       ASSERT_EQ(2U, s[0]->InputCount());
580       ASSERT_TRUE(s[0]->InputAt(1)->IsImmediate());
581       EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
582       EXPECT_EQ(1U, s[0]->OutputCount());
583     }
584   }
585   {
586     // 64-bit add.
587     TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
588       if (imm == 0) continue;
589       StreamBuilder m(this, kMachInt64, kMachInt64);
590       m.Return(m.Int64Add(m.Int64Constant(-imm), m.Parameter(0)));
591       Stream s = m.Build();
592
593       ASSERT_EQ(1U, s.size());
594       EXPECT_EQ(kArm64Sub, s[0]->arch_opcode());
595       ASSERT_EQ(2U, s[0]->InputCount());
596       ASSERT_TRUE(s[0]->InputAt(1)->IsImmediate());
597       EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(1)));
598       EXPECT_EQ(1U, s[0]->OutputCount());
599     }
600   }
601 }
602
603
604 TEST_F(InstructionSelectorTest, AddShiftByImmediateOnLeft) {
605   // 32-bit add.
606   TRACED_FOREACH(Shift, shift, kShiftInstructions) {
607     // Only test relevant shifted operands.
608     if (shift.mi.machine_type != kMachInt32) continue;
609     if (shift.mi.arch_opcode == kArm64Ror32) continue;
610
611     TRACED_FORRANGE(int, imm, 0, 31) {
612       StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
613       m.Return((m.Int32Add)(
614           (m.*shift.mi.constructor)(m.Parameter(1), m.Int32Constant(imm)),
615           m.Parameter(0)));
616       Stream s = m.Build();
617       ASSERT_EQ(1U, s.size());
618       EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
619       EXPECT_EQ(shift.mode, s[0]->addressing_mode());
620       EXPECT_EQ(3U, s[0]->InputCount());
621       EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(2)));
622       EXPECT_EQ(1U, s[0]->OutputCount());
623     }
624   }
625
626   // 64-bit add.
627   TRACED_FOREACH(Shift, shift, kShiftInstructions) {
628     // Only test relevant shifted operands.
629     if (shift.mi.machine_type != kMachInt64) continue;
630     if (shift.mi.arch_opcode == kArm64Ror) continue;
631
632     TRACED_FORRANGE(int, imm, 0, 63) {
633       StreamBuilder m(this, kMachInt64, kMachInt64, kMachInt64);
634       m.Return((m.Int64Add)(
635           (m.*shift.mi.constructor)(m.Parameter(1), m.Int64Constant(imm)),
636           m.Parameter(0)));
637       Stream s = m.Build();
638       ASSERT_EQ(1U, s.size());
639       EXPECT_EQ(kArm64Add, s[0]->arch_opcode());
640       EXPECT_EQ(shift.mode, s[0]->addressing_mode());
641       EXPECT_EQ(3U, s[0]->InputCount());
642       EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(2)));
643       EXPECT_EQ(1U, s[0]->OutputCount());
644     }
645   }
646 }
647
648
649 TEST_F(InstructionSelectorTest, AddExtendByteOnLeft) {
650   {
651     StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
652     m.Return(m.Int32Add(m.Word32And(m.Parameter(0), m.Int32Constant(0xff)),
653                         m.Parameter(1)));
654     Stream s = m.Build();
655     ASSERT_EQ(1U, s.size());
656     EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
657     EXPECT_EQ(kMode_Operand2_R_UXTB, s[0]->addressing_mode());
658     ASSERT_EQ(2U, s[0]->InputCount());
659     ASSERT_EQ(1U, s[0]->OutputCount());
660   }
661   {
662     StreamBuilder m(this, kMachInt64, kMachInt32, kMachInt64);
663     m.Return(m.Int64Add(m.Word32And(m.Parameter(0), m.Int32Constant(0xff)),
664                         m.Parameter(1)));
665     Stream s = m.Build();
666     ASSERT_EQ(1U, s.size());
667     EXPECT_EQ(kArm64Add, s[0]->arch_opcode());
668     EXPECT_EQ(kMode_Operand2_R_UXTB, s[0]->addressing_mode());
669     ASSERT_EQ(2U, s[0]->InputCount());
670     ASSERT_EQ(1U, s[0]->OutputCount());
671   }
672 }
673
674
675 TEST_F(InstructionSelectorTest, AddExtendHalfwordOnLeft) {
676   {
677     StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
678     m.Return(m.Int32Add(m.Word32And(m.Parameter(0), m.Int32Constant(0xffff)),
679                         m.Parameter(1)));
680     Stream s = m.Build();
681     ASSERT_EQ(1U, s.size());
682     EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
683     EXPECT_EQ(kMode_Operand2_R_UXTH, s[0]->addressing_mode());
684     ASSERT_EQ(2U, s[0]->InputCount());
685     ASSERT_EQ(1U, s[0]->OutputCount());
686   }
687   {
688     StreamBuilder m(this, kMachInt64, kMachInt32, kMachInt64);
689     m.Return(m.Int64Add(m.Word32And(m.Parameter(0), m.Int32Constant(0xffff)),
690                         m.Parameter(1)));
691     Stream s = m.Build();
692     ASSERT_EQ(1U, s.size());
693     EXPECT_EQ(kArm64Add, s[0]->arch_opcode());
694     EXPECT_EQ(kMode_Operand2_R_UXTH, s[0]->addressing_mode());
695     ASSERT_EQ(2U, s[0]->InputCount());
696     ASSERT_EQ(1U, s[0]->OutputCount());
697   }
698 }
699
700
701 // -----------------------------------------------------------------------------
702 // Data processing controlled branches.
703
704
705 typedef InstructionSelectorTestWithParam<MachInst2>
706     InstructionSelectorDPFlagSetTest;
707
708
709 TEST_P(InstructionSelectorDPFlagSetTest, BranchWithParameters) {
710   const MachInst2 dpi = GetParam();
711   const MachineType type = dpi.machine_type;
712   StreamBuilder m(this, type, type, type);
713   MLabel a, b;
714   m.Branch((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)), &a, &b);
715   m.Bind(&a);
716   m.Return(m.Int32Constant(1));
717   m.Bind(&b);
718   m.Return(m.Int32Constant(0));
719   Stream s = m.Build();
720   ASSERT_EQ(1U, s.size());
721   EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
722   EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
723   EXPECT_EQ(kNotEqual, s[0]->flags_condition());
724 }
725
726
727 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
728                         InstructionSelectorDPFlagSetTest,
729                         ::testing::ValuesIn(kDPFlagSetInstructions));
730
731
732 TEST_F(InstructionSelectorTest, Word32AndBranchWithImmediateOnRight) {
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.Parameter(0), m.Int32Constant(imm)), &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     EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
750     EXPECT_EQ(kNotEqual, s[0]->flags_condition());
751   }
752 }
753
754
755 TEST_F(InstructionSelectorTest, Word64AndBranchWithImmediateOnRight) {
756   TRACED_FOREACH(int64_t, imm, kLogical64Immediates) {
757     // Skip the cases where the instruction selector would use tbz/tbnz.
758     if (base::bits::CountPopulation64(imm) == 1) continue;
759
760     StreamBuilder m(this, kMachInt64, kMachInt64);
761     MLabel a, b;
762     m.Branch(m.Word64And(m.Parameter(0), m.Int64Constant(imm)), &a, &b);
763     m.Bind(&a);
764     m.Return(m.Int32Constant(1));
765     m.Bind(&b);
766     m.Return(m.Int32Constant(0));
767     Stream s = m.Build();
768     ASSERT_EQ(1U, s.size());
769     EXPECT_EQ(kArm64Tst, s[0]->arch_opcode());
770     EXPECT_EQ(4U, s[0]->InputCount());
771     EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
772     EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
773     EXPECT_EQ(kNotEqual, s[0]->flags_condition());
774   }
775 }
776
777
778 TEST_F(InstructionSelectorTest, AddBranchWithImmediateOnRight) {
779   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
780     StreamBuilder m(this, kMachInt32, kMachInt32);
781     MLabel a, b;
782     m.Branch(m.Int32Add(m.Parameter(0), m.Int32Constant(imm)), &a, &b);
783     m.Bind(&a);
784     m.Return(m.Int32Constant(1));
785     m.Bind(&b);
786     m.Return(m.Int32Constant(0));
787     Stream s = m.Build();
788     ASSERT_EQ(1U, s.size());
789     EXPECT_EQ(kArm64Cmn32, s[0]->arch_opcode());
790     EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
791     EXPECT_EQ(kNotEqual, s[0]->flags_condition());
792   }
793 }
794
795
796 TEST_F(InstructionSelectorTest, SubBranchWithImmediateOnRight) {
797   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
798     StreamBuilder m(this, kMachInt32, kMachInt32);
799     MLabel a, b;
800     m.Branch(m.Int32Sub(m.Parameter(0), m.Int32Constant(imm)), &a, &b);
801     m.Bind(&a);
802     m.Return(m.Int32Constant(1));
803     m.Bind(&b);
804     m.Return(m.Int32Constant(0));
805     Stream s = m.Build();
806     ASSERT_EQ(1U, s.size());
807     EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode());
808     EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
809     EXPECT_EQ(kNotEqual, s[0]->flags_condition());
810   }
811 }
812
813
814 TEST_F(InstructionSelectorTest, Word32AndBranchWithImmediateOnLeft) {
815   TRACED_FOREACH(int32_t, imm, kLogical32Immediates) {
816     // Skip the cases where the instruction selector would use tbz/tbnz.
817     if (base::bits::CountPopulation32(imm) == 1) continue;
818
819     StreamBuilder m(this, kMachInt32, kMachInt32);
820     MLabel a, b;
821     m.Branch(m.Word32And(m.Int32Constant(imm), m.Parameter(0)), &a, &b);
822     m.Bind(&a);
823     m.Return(m.Int32Constant(1));
824     m.Bind(&b);
825     m.Return(m.Int32Constant(0));
826     Stream s = m.Build();
827     ASSERT_EQ(1U, s.size());
828     EXPECT_EQ(kArm64Tst32, s[0]->arch_opcode());
829     EXPECT_EQ(4U, s[0]->InputCount());
830     EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
831     ASSERT_LE(1U, s[0]->InputCount());
832     EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
833     EXPECT_EQ(kNotEqual, s[0]->flags_condition());
834   }
835 }
836
837
838 TEST_F(InstructionSelectorTest, Word64AndBranchWithImmediateOnLeft) {
839   TRACED_FOREACH(int64_t, imm, kLogical64Immediates) {
840     // Skip the cases where the instruction selector would use tbz/tbnz.
841     if (base::bits::CountPopulation64(imm) == 1) continue;
842
843     StreamBuilder m(this, kMachInt64, kMachInt64);
844     MLabel a, b;
845     m.Branch(m.Word64And(m.Int64Constant(imm), 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(kArm64Tst, s[0]->arch_opcode());
853     EXPECT_EQ(4U, s[0]->InputCount());
854     EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
855     ASSERT_LE(1U, s[0]->InputCount());
856     EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
857     EXPECT_EQ(kNotEqual, s[0]->flags_condition());
858   }
859 }
860
861
862 TEST_F(InstructionSelectorTest, AddBranchWithImmediateOnLeft) {
863   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
864     StreamBuilder m(this, kMachInt32, kMachInt32);
865     MLabel a, b;
866     m.Branch(m.Int32Add(m.Int32Constant(imm), m.Parameter(0)), &a, &b);
867     m.Bind(&a);
868     m.Return(m.Int32Constant(1));
869     m.Bind(&b);
870     m.Return(m.Int32Constant(0));
871     Stream s = m.Build();
872     ASSERT_EQ(1U, s.size());
873     EXPECT_EQ(kArm64Cmn32, s[0]->arch_opcode());
874     ASSERT_LE(1U, s[0]->InputCount());
875     EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
876     EXPECT_EQ(kNotEqual, s[0]->flags_condition());
877   }
878 }
879
880
881 TEST_F(InstructionSelectorTest, Word32AndBranchWithOneBitMaskOnRight) {
882   TRACED_FORRANGE(int, bit, 0, 31) {
883     uint32_t mask = 1 << bit;
884     StreamBuilder m(this, kMachInt32, kMachInt32);
885     MLabel a, b;
886     m.Branch(m.Word32And(m.Parameter(0), m.Int32Constant(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(kArm64TestAndBranch32, 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.ToInt32(s[0]->InputAt(1)));
898   }
899
900   TRACED_FORRANGE(int, bit, 0, 31) {
901     uint32_t mask = 1 << bit;
902     StreamBuilder m(this, kMachInt32, kMachInt32);
903     MLabel a, b;
904     m.Branch(
905         m.Word32BinaryNot(m.Word32And(m.Parameter(0), m.Int32Constant(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(kArm64TestAndBranch32, 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.ToInt32(s[0]->InputAt(1)));
918   }
919 }
920
921
922 TEST_F(InstructionSelectorTest, Word32AndBranchWithOneBitMaskOnLeft) {
923   TRACED_FORRANGE(int, bit, 0, 31) {
924     uint32_t mask = 1 << bit;
925     StreamBuilder m(this, kMachInt32, kMachInt32);
926     MLabel a, b;
927     m.Branch(m.Word32And(m.Int32Constant(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(kArm64TestAndBranch32, 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.ToInt32(s[0]->InputAt(1)));
939   }
940
941   TRACED_FORRANGE(int, bit, 0, 31) {
942     uint32_t mask = 1 << bit;
943     StreamBuilder m(this, kMachInt32, kMachInt32);
944     MLabel a, b;
945     m.Branch(
946         m.Word32BinaryNot(m.Word32And(m.Int32Constant(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(kArm64TestAndBranch32, 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.ToInt32(s[0]->InputAt(1)));
959   }
960 }
961
962
963 TEST_F(InstructionSelectorTest, Word64AndBranchWithOneBitMaskOnRight) {
964   TRACED_FORRANGE(int, bit, 0, 63) {
965     uint64_t mask = 1L << bit;
966     StreamBuilder m(this, kMachInt64, kMachInt64);
967     MLabel a, b;
968     m.Branch(m.Word64And(m.Parameter(0), m.Int64Constant(mask)), &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(kArm64TestAndBranch, s[0]->arch_opcode());
976     EXPECT_EQ(kNotEqual, s[0]->flags_condition());
977     EXPECT_EQ(4U, s[0]->InputCount());
978     EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
979     EXPECT_EQ(bit, s.ToInt64(s[0]->InputAt(1)));
980   }
981 }
982
983
984 TEST_F(InstructionSelectorTest, Word64AndBranchWithOneBitMaskOnLeft) {
985   TRACED_FORRANGE(int, bit, 0, 63) {
986     uint64_t mask = 1L << bit;
987     StreamBuilder m(this, kMachInt64, kMachInt64);
988     MLabel a, b;
989     m.Branch(m.Word64And(m.Int64Constant(mask), m.Parameter(0)), &a, &b);
990     m.Bind(&a);
991     m.Return(m.Int32Constant(1));
992     m.Bind(&b);
993     m.Return(m.Int32Constant(0));
994     Stream s = m.Build();
995     ASSERT_EQ(1U, s.size());
996     EXPECT_EQ(kArm64TestAndBranch, s[0]->arch_opcode());
997     EXPECT_EQ(kNotEqual, s[0]->flags_condition());
998     EXPECT_EQ(4U, s[0]->InputCount());
999     EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
1000     EXPECT_EQ(bit, s.ToInt64(s[0]->InputAt(1)));
1001   }
1002 }
1003
1004
1005 TEST_F(InstructionSelectorTest, CompareAgainstZeroAndBranch) {
1006   {
1007     StreamBuilder m(this, kMachInt32, kMachInt32);
1008     MLabel a, b;
1009     Node* p0 = m.Parameter(0);
1010     m.Branch(p0, &a, &b);
1011     m.Bind(&a);
1012     m.Return(m.Int32Constant(1));
1013     m.Bind(&b);
1014     m.Return(m.Int32Constant(0));
1015     Stream s = m.Build();
1016     ASSERT_EQ(1U, s.size());
1017     EXPECT_EQ(kArm64CompareAndBranch32, s[0]->arch_opcode());
1018     EXPECT_EQ(kNotEqual, s[0]->flags_condition());
1019     EXPECT_EQ(3U, s[0]->InputCount());
1020     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1021   }
1022
1023   {
1024     StreamBuilder m(this, kMachInt32, kMachInt32);
1025     MLabel a, b;
1026     Node* p0 = m.Parameter(0);
1027     m.Branch(m.Word32BinaryNot(p0), &a, &b);
1028     m.Bind(&a);
1029     m.Return(m.Int32Constant(1));
1030     m.Bind(&b);
1031     m.Return(m.Int32Constant(0));
1032     Stream s = m.Build();
1033     ASSERT_EQ(1U, s.size());
1034     EXPECT_EQ(kArm64CompareAndBranch32, s[0]->arch_opcode());
1035     EXPECT_EQ(kEqual, s[0]->flags_condition());
1036     EXPECT_EQ(3U, s[0]->InputCount());
1037     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1038   }
1039 }
1040
1041
1042 // -----------------------------------------------------------------------------
1043 // Add and subtract instructions with overflow.
1044
1045
1046 typedef InstructionSelectorTestWithParam<MachInst2>
1047     InstructionSelectorOvfAddSubTest;
1048
1049
1050 TEST_P(InstructionSelectorOvfAddSubTest, OvfParameter) {
1051   const MachInst2 dpi = GetParam();
1052   const MachineType type = dpi.machine_type;
1053   StreamBuilder m(this, type, type, type);
1054   m.Return(
1055       m.Projection(1, (m.*dpi.constructor)(m.Parameter(0), m.Parameter(1))));
1056   Stream s = m.Build();
1057   ASSERT_EQ(1U, s.size());
1058   EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
1059   EXPECT_EQ(2U, s[0]->InputCount());
1060   EXPECT_LE(1U, s[0]->OutputCount());
1061   EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1062   EXPECT_EQ(kOverflow, s[0]->flags_condition());
1063 }
1064
1065
1066 TEST_P(InstructionSelectorOvfAddSubTest, OvfImmediateOnRight) {
1067   const MachInst2 dpi = GetParam();
1068   const MachineType type = dpi.machine_type;
1069   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
1070     StreamBuilder m(this, type, type);
1071     m.Return(m.Projection(
1072         1, (m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm))));
1073     Stream s = m.Build();
1074     ASSERT_EQ(1U, s.size());
1075     EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
1076     ASSERT_EQ(2U, s[0]->InputCount());
1077     EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
1078     EXPECT_LE(1U, s[0]->OutputCount());
1079     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1080     EXPECT_EQ(kOverflow, s[0]->flags_condition());
1081   }
1082 }
1083
1084
1085 TEST_P(InstructionSelectorOvfAddSubTest, ValParameter) {
1086   const MachInst2 dpi = GetParam();
1087   const MachineType type = dpi.machine_type;
1088   StreamBuilder m(this, type, type, type);
1089   m.Return(
1090       m.Projection(0, (m.*dpi.constructor)(m.Parameter(0), m.Parameter(1))));
1091   Stream s = m.Build();
1092   ASSERT_EQ(1U, s.size());
1093   EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
1094   EXPECT_EQ(2U, s[0]->InputCount());
1095   EXPECT_LE(1U, s[0]->OutputCount());
1096   EXPECT_EQ(kFlags_none, s[0]->flags_mode());
1097 }
1098
1099
1100 TEST_P(InstructionSelectorOvfAddSubTest, ValImmediateOnRight) {
1101   const MachInst2 dpi = GetParam();
1102   const MachineType type = dpi.machine_type;
1103   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
1104     StreamBuilder m(this, type, type);
1105     m.Return(m.Projection(
1106         0, (m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm))));
1107     Stream s = m.Build();
1108     ASSERT_EQ(1U, s.size());
1109     EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
1110     ASSERT_EQ(2U, s[0]->InputCount());
1111     EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
1112     EXPECT_LE(1U, s[0]->OutputCount());
1113     EXPECT_EQ(kFlags_none, s[0]->flags_mode());
1114   }
1115 }
1116
1117
1118 TEST_P(InstructionSelectorOvfAddSubTest, BothParameter) {
1119   const MachInst2 dpi = GetParam();
1120   const MachineType type = dpi.machine_type;
1121   StreamBuilder m(this, type, type, type);
1122   Node* n = (m.*dpi.constructor)(m.Parameter(0), m.Parameter(1));
1123   m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n)));
1124   Stream s = m.Build();
1125   ASSERT_LE(1U, s.size());
1126   EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
1127   EXPECT_EQ(2U, s[0]->InputCount());
1128   EXPECT_EQ(2U, s[0]->OutputCount());
1129   EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1130   EXPECT_EQ(kOverflow, s[0]->flags_condition());
1131 }
1132
1133
1134 TEST_P(InstructionSelectorOvfAddSubTest, BothImmediateOnRight) {
1135   const MachInst2 dpi = GetParam();
1136   const MachineType type = dpi.machine_type;
1137   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
1138     StreamBuilder m(this, type, type);
1139     Node* n = (m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm));
1140     m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n)));
1141     Stream s = m.Build();
1142     ASSERT_LE(1U, s.size());
1143     EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
1144     ASSERT_EQ(2U, s[0]->InputCount());
1145     EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
1146     EXPECT_EQ(2U, s[0]->OutputCount());
1147     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1148     EXPECT_EQ(kOverflow, s[0]->flags_condition());
1149   }
1150 }
1151
1152
1153 TEST_P(InstructionSelectorOvfAddSubTest, BranchWithParameters) {
1154   const MachInst2 dpi = GetParam();
1155   const MachineType type = dpi.machine_type;
1156   StreamBuilder m(this, type, type, type);
1157   MLabel a, b;
1158   Node* n = (m.*dpi.constructor)(m.Parameter(0), m.Parameter(1));
1159   m.Branch(m.Projection(1, n), &a, &b);
1160   m.Bind(&a);
1161   m.Return(m.Int32Constant(0));
1162   m.Bind(&b);
1163   m.Return(m.Projection(0, n));
1164   Stream s = m.Build();
1165   ASSERT_EQ(1U, s.size());
1166   EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
1167   EXPECT_EQ(4U, s[0]->InputCount());
1168   EXPECT_EQ(1U, s[0]->OutputCount());
1169   EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
1170   EXPECT_EQ(kOverflow, s[0]->flags_condition());
1171 }
1172
1173
1174 TEST_P(InstructionSelectorOvfAddSubTest, BranchWithImmediateOnRight) {
1175   const MachInst2 dpi = GetParam();
1176   const MachineType type = dpi.machine_type;
1177   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
1178     StreamBuilder m(this, type, type);
1179     MLabel a, b;
1180     Node* n = (m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm));
1181     m.Branch(m.Projection(1, n), &a, &b);
1182     m.Bind(&a);
1183     m.Return(m.Int32Constant(0));
1184     m.Bind(&b);
1185     m.Return(m.Projection(0, n));
1186     Stream s = m.Build();
1187     ASSERT_EQ(1U, s.size());
1188     EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
1189     ASSERT_EQ(4U, s[0]->InputCount());
1190     EXPECT_EQ(1U, s[0]->OutputCount());
1191     EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
1192     EXPECT_EQ(kOverflow, s[0]->flags_condition());
1193   }
1194 }
1195
1196
1197 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1198                         InstructionSelectorOvfAddSubTest,
1199                         ::testing::ValuesIn(kOvfAddSubInstructions));
1200
1201
1202 TEST_F(InstructionSelectorTest, OvfFlagAddImmediateOnLeft) {
1203   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
1204     StreamBuilder m(this, kMachInt32, kMachInt32);
1205     m.Return(m.Projection(
1206         1, m.Int32AddWithOverflow(m.Int32Constant(imm), m.Parameter(0))));
1207     Stream s = m.Build();
1208
1209     ASSERT_EQ(1U, s.size());
1210     EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
1211     EXPECT_EQ(2U, s[0]->InputCount());
1212     EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
1213     EXPECT_LE(1U, s[0]->OutputCount());
1214     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1215     EXPECT_EQ(kOverflow, s[0]->flags_condition());
1216   }
1217 }
1218
1219
1220 TEST_F(InstructionSelectorTest, OvfValAddImmediateOnLeft) {
1221   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
1222     StreamBuilder m(this, kMachInt32, kMachInt32);
1223     m.Return(m.Projection(
1224         0, m.Int32AddWithOverflow(m.Int32Constant(imm), m.Parameter(0))));
1225     Stream s = m.Build();
1226
1227     ASSERT_EQ(1U, s.size());
1228     EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
1229     ASSERT_EQ(2U, s[0]->InputCount());
1230     EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
1231     EXPECT_LE(1U, s[0]->OutputCount());
1232     EXPECT_EQ(kFlags_none, s[0]->flags_mode());
1233   }
1234 }
1235
1236
1237 TEST_F(InstructionSelectorTest, OvfBothAddImmediateOnLeft) {
1238   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
1239     StreamBuilder m(this, kMachInt32, kMachInt32);
1240     Node* n = m.Int32AddWithOverflow(m.Int32Constant(imm), m.Parameter(0));
1241     m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n)));
1242     Stream s = m.Build();
1243
1244     ASSERT_LE(1U, s.size());
1245     EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
1246     ASSERT_EQ(2U, s[0]->InputCount());
1247     EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
1248     EXPECT_EQ(2U, s[0]->OutputCount());
1249     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1250     EXPECT_EQ(kOverflow, s[0]->flags_condition());
1251   }
1252 }
1253
1254
1255 TEST_F(InstructionSelectorTest, OvfBranchWithImmediateOnLeft) {
1256   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
1257     StreamBuilder m(this, kMachInt32, kMachInt32);
1258     MLabel a, b;
1259     Node* n = m.Int32AddWithOverflow(m.Int32Constant(imm), m.Parameter(0));
1260     m.Branch(m.Projection(1, n), &a, &b);
1261     m.Bind(&a);
1262     m.Return(m.Int32Constant(0));
1263     m.Bind(&b);
1264     m.Return(m.Projection(0, n));
1265     Stream s = m.Build();
1266
1267     ASSERT_EQ(1U, s.size());
1268     EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
1269     ASSERT_EQ(4U, s[0]->InputCount());
1270     EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
1271     EXPECT_EQ(1U, s[0]->OutputCount());
1272     EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
1273     EXPECT_EQ(kOverflow, s[0]->flags_condition());
1274   }
1275 }
1276
1277
1278 // -----------------------------------------------------------------------------
1279 // Shift instructions.
1280
1281
1282 typedef InstructionSelectorTestWithParam<Shift> InstructionSelectorShiftTest;
1283
1284
1285 TEST_P(InstructionSelectorShiftTest, Parameter) {
1286   const Shift shift = GetParam();
1287   const MachineType type = shift.mi.machine_type;
1288   StreamBuilder m(this, type, type, type);
1289   m.Return((m.*shift.mi.constructor)(m.Parameter(0), m.Parameter(1)));
1290   Stream s = m.Build();
1291   ASSERT_EQ(1U, s.size());
1292   EXPECT_EQ(shift.mi.arch_opcode, s[0]->arch_opcode());
1293   EXPECT_EQ(2U, s[0]->InputCount());
1294   EXPECT_EQ(1U, s[0]->OutputCount());
1295 }
1296
1297
1298 TEST_P(InstructionSelectorShiftTest, Immediate) {
1299   const Shift shift = GetParam();
1300   const MachineType type = shift.mi.machine_type;
1301   TRACED_FORRANGE(int32_t, imm, 0, (ElementSizeOf(type) * 8) - 1) {
1302     StreamBuilder m(this, type, type);
1303     m.Return((m.*shift.mi.constructor)(m.Parameter(0), m.Int32Constant(imm)));
1304     Stream s = m.Build();
1305     ASSERT_EQ(1U, s.size());
1306     EXPECT_EQ(shift.mi.arch_opcode, s[0]->arch_opcode());
1307     EXPECT_EQ(2U, s[0]->InputCount());
1308     EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
1309     EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
1310     EXPECT_EQ(1U, s[0]->OutputCount());
1311   }
1312 }
1313
1314
1315 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorShiftTest,
1316                         ::testing::ValuesIn(kShiftInstructions));
1317
1318
1319 TEST_F(InstructionSelectorTest, Word64ShlWithChangeInt32ToInt64) {
1320   TRACED_FORRANGE(int64_t, x, 32, 63) {
1321     StreamBuilder m(this, kMachInt64, kMachInt32);
1322     Node* const p0 = m.Parameter(0);
1323     Node* const n = m.Word64Shl(m.ChangeInt32ToInt64(p0), m.Int64Constant(x));
1324     m.Return(n);
1325     Stream s = m.Build();
1326     ASSERT_EQ(1U, s.size());
1327     EXPECT_EQ(kArm64Lsl, s[0]->arch_opcode());
1328     ASSERT_EQ(2U, s[0]->InputCount());
1329     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1330     EXPECT_EQ(x, s.ToInt64(s[0]->InputAt(1)));
1331     ASSERT_EQ(1U, s[0]->OutputCount());
1332     EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1333   }
1334 }
1335
1336
1337 TEST_F(InstructionSelectorTest, Word64ShlWithChangeUint32ToUint64) {
1338   TRACED_FORRANGE(int64_t, x, 32, 63) {
1339     StreamBuilder m(this, kMachInt64, kMachUint32);
1340     Node* const p0 = m.Parameter(0);
1341     Node* const n = m.Word64Shl(m.ChangeUint32ToUint64(p0), m.Int64Constant(x));
1342     m.Return(n);
1343     Stream s = m.Build();
1344     ASSERT_EQ(1U, s.size());
1345     EXPECT_EQ(kArm64Lsl, s[0]->arch_opcode());
1346     ASSERT_EQ(2U, s[0]->InputCount());
1347     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1348     EXPECT_EQ(x, s.ToInt64(s[0]->InputAt(1)));
1349     ASSERT_EQ(1U, s[0]->OutputCount());
1350     EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1351   }
1352 }
1353
1354
1355 TEST_F(InstructionSelectorTest, TruncateInt64ToInt32WithWord64Sar) {
1356   StreamBuilder m(this, kMachInt32, kMachInt64);
1357   Node* const p = m.Parameter(0);
1358   Node* const t = m.TruncateInt64ToInt32(m.Word64Sar(p, m.Int64Constant(32)));
1359   m.Return(t);
1360   Stream s = m.Build();
1361   ASSERT_EQ(1U, s.size());
1362   EXPECT_EQ(kArm64Lsr, s[0]->arch_opcode());
1363   ASSERT_EQ(2U, s[0]->InputCount());
1364   EXPECT_EQ(s.ToVreg(p), s.ToVreg(s[0]->InputAt(0)));
1365   EXPECT_EQ(32, s.ToInt64(s[0]->InputAt(1)));
1366   ASSERT_EQ(1U, s[0]->OutputCount());
1367   EXPECT_EQ(s.ToVreg(t), s.ToVreg(s[0]->OutputAt(0)));
1368 }
1369
1370
1371 TEST_F(InstructionSelectorTest, TruncateInt64ToInt32WithWord64Shr) {
1372   TRACED_FORRANGE(int64_t, x, 32, 63) {
1373     StreamBuilder m(this, kMachInt32, kMachInt64);
1374     Node* const p = m.Parameter(0);
1375     Node* const t = m.TruncateInt64ToInt32(m.Word64Shr(p, m.Int64Constant(x)));
1376     m.Return(t);
1377     Stream s = m.Build();
1378     ASSERT_EQ(1U, s.size());
1379     EXPECT_EQ(kArm64Lsr, s[0]->arch_opcode());
1380     ASSERT_EQ(2U, s[0]->InputCount());
1381     EXPECT_EQ(s.ToVreg(p), s.ToVreg(s[0]->InputAt(0)));
1382     EXPECT_EQ(x, s.ToInt64(s[0]->InputAt(1)));
1383     ASSERT_EQ(1U, s[0]->OutputCount());
1384     EXPECT_EQ(s.ToVreg(t), s.ToVreg(s[0]->OutputAt(0)));
1385   }
1386 }
1387
1388
1389 // -----------------------------------------------------------------------------
1390 // Mul and Div instructions.
1391
1392
1393 typedef InstructionSelectorTestWithParam<MachInst2>
1394     InstructionSelectorMulDivTest;
1395
1396
1397 TEST_P(InstructionSelectorMulDivTest, Parameter) {
1398   const MachInst2 dpi = GetParam();
1399   const MachineType type = dpi.machine_type;
1400   StreamBuilder m(this, type, type, type);
1401   m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)));
1402   Stream s = m.Build();
1403   ASSERT_EQ(1U, s.size());
1404   EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
1405   EXPECT_EQ(2U, s[0]->InputCount());
1406   EXPECT_EQ(1U, s[0]->OutputCount());
1407 }
1408
1409
1410 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorMulDivTest,
1411                         ::testing::ValuesIn(kMulDivInstructions));
1412
1413
1414 namespace {
1415
1416 struct MulDPInst {
1417   const char* mul_constructor_name;
1418   Node* (RawMachineAssembler::*mul_constructor)(Node*, Node*);
1419   Node* (RawMachineAssembler::*add_constructor)(Node*, Node*);
1420   Node* (RawMachineAssembler::*sub_constructor)(Node*, Node*);
1421   ArchOpcode add_arch_opcode;
1422   ArchOpcode sub_arch_opcode;
1423   ArchOpcode neg_arch_opcode;
1424   MachineType machine_type;
1425 };
1426
1427
1428 std::ostream& operator<<(std::ostream& os, const MulDPInst& inst) {
1429   return os << inst.mul_constructor_name;
1430 }
1431
1432 }  // namespace
1433
1434
1435 static const MulDPInst kMulDPInstructions[] = {
1436     {"Int32Mul", &RawMachineAssembler::Int32Mul, &RawMachineAssembler::Int32Add,
1437      &RawMachineAssembler::Int32Sub, kArm64Madd32, kArm64Msub32, kArm64Mneg32,
1438      kMachInt32},
1439     {"Int64Mul", &RawMachineAssembler::Int64Mul, &RawMachineAssembler::Int64Add,
1440      &RawMachineAssembler::Int64Sub, kArm64Madd, kArm64Msub, kArm64Mneg,
1441      kMachInt64}};
1442
1443
1444 typedef InstructionSelectorTestWithParam<MulDPInst>
1445     InstructionSelectorIntDPWithIntMulTest;
1446
1447
1448 TEST_P(InstructionSelectorIntDPWithIntMulTest, AddWithMul) {
1449   const MulDPInst mdpi = GetParam();
1450   const MachineType type = mdpi.machine_type;
1451   {
1452     StreamBuilder m(this, type, type, type, type);
1453     Node* n = (m.*mdpi.mul_constructor)(m.Parameter(1), m.Parameter(2));
1454     m.Return((m.*mdpi.add_constructor)(m.Parameter(0), n));
1455     Stream s = m.Build();
1456     ASSERT_EQ(1U, s.size());
1457     EXPECT_EQ(mdpi.add_arch_opcode, s[0]->arch_opcode());
1458     EXPECT_EQ(3U, s[0]->InputCount());
1459     EXPECT_EQ(1U, s[0]->OutputCount());
1460   }
1461   {
1462     StreamBuilder m(this, type, type, type, type);
1463     Node* n = (m.*mdpi.mul_constructor)(m.Parameter(0), m.Parameter(1));
1464     m.Return((m.*mdpi.add_constructor)(n, m.Parameter(2)));
1465     Stream s = m.Build();
1466     ASSERT_EQ(1U, s.size());
1467     EXPECT_EQ(mdpi.add_arch_opcode, s[0]->arch_opcode());
1468     EXPECT_EQ(3U, s[0]->InputCount());
1469     EXPECT_EQ(1U, s[0]->OutputCount());
1470   }
1471 }
1472
1473
1474 TEST_P(InstructionSelectorIntDPWithIntMulTest, SubWithMul) {
1475   const MulDPInst mdpi = GetParam();
1476   const MachineType type = mdpi.machine_type;
1477   {
1478     StreamBuilder m(this, type, type, type, type);
1479     Node* n = (m.*mdpi.mul_constructor)(m.Parameter(1), m.Parameter(2));
1480     m.Return((m.*mdpi.sub_constructor)(m.Parameter(0), n));
1481     Stream s = m.Build();
1482     ASSERT_EQ(1U, s.size());
1483     EXPECT_EQ(mdpi.sub_arch_opcode, s[0]->arch_opcode());
1484     EXPECT_EQ(3U, s[0]->InputCount());
1485     EXPECT_EQ(1U, s[0]->OutputCount());
1486   }
1487 }
1488
1489
1490 TEST_P(InstructionSelectorIntDPWithIntMulTest, NegativeMul) {
1491   const MulDPInst mdpi = GetParam();
1492   const MachineType type = mdpi.machine_type;
1493   {
1494     StreamBuilder m(this, type, type, type);
1495     Node* n =
1496         (m.*mdpi.sub_constructor)(BuildConstant(m, type, 0), m.Parameter(0));
1497     m.Return((m.*mdpi.mul_constructor)(n, m.Parameter(1)));
1498     Stream s = m.Build();
1499     ASSERT_EQ(1U, s.size());
1500     EXPECT_EQ(mdpi.neg_arch_opcode, s[0]->arch_opcode());
1501     EXPECT_EQ(2U, s[0]->InputCount());
1502     EXPECT_EQ(1U, s[0]->OutputCount());
1503   }
1504   {
1505     StreamBuilder m(this, type, type, type);
1506     Node* n =
1507         (m.*mdpi.sub_constructor)(BuildConstant(m, type, 0), m.Parameter(1));
1508     m.Return((m.*mdpi.mul_constructor)(m.Parameter(0), n));
1509     Stream s = m.Build();
1510     ASSERT_EQ(1U, s.size());
1511     EXPECT_EQ(mdpi.neg_arch_opcode, s[0]->arch_opcode());
1512     EXPECT_EQ(2U, s[0]->InputCount());
1513     EXPECT_EQ(1U, s[0]->OutputCount());
1514   }
1515 }
1516
1517
1518 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1519                         InstructionSelectorIntDPWithIntMulTest,
1520                         ::testing::ValuesIn(kMulDPInstructions));
1521
1522
1523 // -----------------------------------------------------------------------------
1524 // Floating point instructions.
1525
1526 typedef InstructionSelectorTestWithParam<MachInst2>
1527     InstructionSelectorFPArithTest;
1528
1529
1530 TEST_P(InstructionSelectorFPArithTest, Parameter) {
1531   const MachInst2 fpa = GetParam();
1532   StreamBuilder m(this, fpa.machine_type, fpa.machine_type, fpa.machine_type);
1533   m.Return((m.*fpa.constructor)(m.Parameter(0), m.Parameter(1)));
1534   Stream s = m.Build();
1535   ASSERT_EQ(1U, s.size());
1536   EXPECT_EQ(fpa.arch_opcode, s[0]->arch_opcode());
1537   EXPECT_EQ(2U, s[0]->InputCount());
1538   EXPECT_EQ(1U, s[0]->OutputCount());
1539 }
1540
1541
1542 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorFPArithTest,
1543                         ::testing::ValuesIn(kFPArithInstructions));
1544
1545
1546 typedef InstructionSelectorTestWithParam<FPCmp> InstructionSelectorFPCmpTest;
1547
1548
1549 TEST_P(InstructionSelectorFPCmpTest, Parameter) {
1550   const FPCmp cmp = GetParam();
1551   StreamBuilder m(this, kMachInt32, cmp.mi.machine_type, cmp.mi.machine_type);
1552   m.Return((m.*cmp.mi.constructor)(m.Parameter(0), m.Parameter(1)));
1553   Stream s = m.Build();
1554   ASSERT_EQ(1U, s.size());
1555   EXPECT_EQ(cmp.mi.arch_opcode, s[0]->arch_opcode());
1556   EXPECT_EQ(2U, s[0]->InputCount());
1557   EXPECT_EQ(1U, s[0]->OutputCount());
1558   EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1559   EXPECT_EQ(cmp.cond, s[0]->flags_condition());
1560 }
1561
1562
1563 TEST_P(InstructionSelectorFPCmpTest, WithImmediateZeroOnRight) {
1564   const FPCmp cmp = GetParam();
1565   StreamBuilder m(this, kMachInt32, cmp.mi.machine_type);
1566   m.Return((m.*cmp.mi.constructor)(m.Parameter(0), m.Float64Constant(0.0)));
1567   Stream s = m.Build();
1568   ASSERT_EQ(1U, s.size());
1569   EXPECT_EQ(cmp.mi.arch_opcode, s[0]->arch_opcode());
1570   EXPECT_EQ(2U, s[0]->InputCount());
1571   EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
1572   EXPECT_EQ(1U, s[0]->OutputCount());
1573   EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1574   EXPECT_EQ(cmp.cond, s[0]->flags_condition());
1575 }
1576
1577
1578 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorFPCmpTest,
1579                         ::testing::ValuesIn(kFPCmpInstructions));
1580
1581
1582 TEST_F(InstructionSelectorTest, Float64EqualWithImmediateZeroOnLeft) {
1583   StreamBuilder m(this, kMachInt32, kMachFloat64);
1584   m.Return(m.Float64Equal(m.Float64Constant(0.0), m.Parameter(0)));
1585   Stream s = m.Build();
1586   ASSERT_EQ(1U, s.size());
1587   EXPECT_EQ(kArm64Float64Cmp, s[0]->arch_opcode());
1588   EXPECT_EQ(2U, s[0]->InputCount());
1589   EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
1590   EXPECT_EQ(1U, s[0]->OutputCount());
1591   EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1592   EXPECT_EQ(kEqual, s[0]->flags_condition());
1593 }
1594
1595
1596 // -----------------------------------------------------------------------------
1597 // Conversions.
1598
1599 typedef InstructionSelectorTestWithParam<Conversion>
1600     InstructionSelectorConversionTest;
1601
1602
1603 TEST_P(InstructionSelectorConversionTest, Parameter) {
1604   const Conversion conv = GetParam();
1605   StreamBuilder m(this, conv.mi.machine_type, conv.src_machine_type);
1606   m.Return((m.*conv.mi.constructor)(m.Parameter(0)));
1607   Stream s = m.Build();
1608   ASSERT_EQ(1U, s.size());
1609   EXPECT_EQ(conv.mi.arch_opcode, s[0]->arch_opcode());
1610   EXPECT_EQ(1U, s[0]->InputCount());
1611   EXPECT_EQ(1U, s[0]->OutputCount());
1612 }
1613
1614
1615 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1616                         InstructionSelectorConversionTest,
1617                         ::testing::ValuesIn(kConversionInstructions));
1618
1619
1620 // -----------------------------------------------------------------------------
1621 // Memory access instructions.
1622
1623
1624 namespace {
1625
1626 struct MemoryAccess {
1627   MachineType type;
1628   ArchOpcode ldr_opcode;
1629   ArchOpcode str_opcode;
1630   const int32_t immediates[20];
1631 };
1632
1633
1634 std::ostream& operator<<(std::ostream& os, const MemoryAccess& memacc) {
1635   return os << memacc.type;
1636 }
1637
1638 }  // namespace
1639
1640
1641 static const MemoryAccess kMemoryAccesses[] = {
1642     {kMachInt8,
1643      kArm64Ldrsb,
1644      kArm64Strb,
1645      {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 257, 258, 1000, 1001, 2121,
1646       2442, 4093, 4094, 4095}},
1647     {kMachUint8,
1648      kArm64Ldrb,
1649      kArm64Strb,
1650      {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 257, 258, 1000, 1001, 2121,
1651       2442, 4093, 4094, 4095}},
1652     {kMachInt16,
1653      kArm64Ldrsh,
1654      kArm64Strh,
1655      {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 258, 260, 4096, 4098, 4100,
1656       4242, 6786, 8188, 8190}},
1657     {kMachUint16,
1658      kArm64Ldrh,
1659      kArm64Strh,
1660      {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 258, 260, 4096, 4098, 4100,
1661       4242, 6786, 8188, 8190}},
1662     {kMachInt32,
1663      kArm64LdrW,
1664      kArm64StrW,
1665      {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 260, 4096, 4100, 8192, 8196,
1666       3276, 3280, 16376, 16380}},
1667     {kMachUint32,
1668      kArm64LdrW,
1669      kArm64StrW,
1670      {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 260, 4096, 4100, 8192, 8196,
1671       3276, 3280, 16376, 16380}},
1672     {kMachInt64,
1673      kArm64Ldr,
1674      kArm64Str,
1675      {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 264, 4096, 4104, 8192, 8200,
1676       16384, 16392, 32752, 32760}},
1677     {kMachUint64,
1678      kArm64Ldr,
1679      kArm64Str,
1680      {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 264, 4096, 4104, 8192, 8200,
1681       16384, 16392, 32752, 32760}},
1682     {kMachFloat32,
1683      kArm64LdrS,
1684      kArm64StrS,
1685      {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 260, 4096, 4100, 8192, 8196,
1686       3276, 3280, 16376, 16380}},
1687     {kMachFloat64,
1688      kArm64LdrD,
1689      kArm64StrD,
1690      {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 264, 4096, 4104, 8192, 8200,
1691       16384, 16392, 32752, 32760}}};
1692
1693
1694 typedef InstructionSelectorTestWithParam<MemoryAccess>
1695     InstructionSelectorMemoryAccessTest;
1696
1697
1698 TEST_P(InstructionSelectorMemoryAccessTest, LoadWithParameters) {
1699   const MemoryAccess memacc = GetParam();
1700   StreamBuilder m(this, memacc.type, kMachPtr, kMachInt32);
1701   m.Return(m.Load(memacc.type, m.Parameter(0), m.Parameter(1)));
1702   Stream s = m.Build();
1703   ASSERT_EQ(1U, s.size());
1704   EXPECT_EQ(memacc.ldr_opcode, s[0]->arch_opcode());
1705   EXPECT_EQ(kMode_MRR, s[0]->addressing_mode());
1706   EXPECT_EQ(2U, s[0]->InputCount());
1707   EXPECT_EQ(1U, s[0]->OutputCount());
1708 }
1709
1710
1711 TEST_P(InstructionSelectorMemoryAccessTest, LoadWithImmediateIndex) {
1712   const MemoryAccess memacc = GetParam();
1713   TRACED_FOREACH(int32_t, index, memacc.immediates) {
1714     StreamBuilder m(this, memacc.type, kMachPtr);
1715     m.Return(m.Load(memacc.type, m.Parameter(0), m.Int32Constant(index)));
1716     Stream s = m.Build();
1717     ASSERT_EQ(1U, s.size());
1718     EXPECT_EQ(memacc.ldr_opcode, s[0]->arch_opcode());
1719     EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
1720     EXPECT_EQ(2U, s[0]->InputCount());
1721     ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
1722     EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1)));
1723     ASSERT_EQ(1U, s[0]->OutputCount());
1724   }
1725 }
1726
1727
1728 TEST_P(InstructionSelectorMemoryAccessTest, StoreWithParameters) {
1729   const MemoryAccess memacc = GetParam();
1730   StreamBuilder m(this, kMachInt32, kMachPtr, kMachInt32, memacc.type);
1731   m.Store(memacc.type, m.Parameter(0), m.Parameter(1), m.Parameter(2));
1732   m.Return(m.Int32Constant(0));
1733   Stream s = m.Build();
1734   ASSERT_EQ(1U, s.size());
1735   EXPECT_EQ(memacc.str_opcode, s[0]->arch_opcode());
1736   EXPECT_EQ(kMode_MRR, s[0]->addressing_mode());
1737   EXPECT_EQ(3U, s[0]->InputCount());
1738   EXPECT_EQ(0U, s[0]->OutputCount());
1739 }
1740
1741
1742 TEST_P(InstructionSelectorMemoryAccessTest, StoreWithImmediateIndex) {
1743   const MemoryAccess memacc = GetParam();
1744   TRACED_FOREACH(int32_t, index, memacc.immediates) {
1745     StreamBuilder m(this, kMachInt32, kMachPtr, memacc.type);
1746     m.Store(memacc.type, m.Parameter(0), m.Int32Constant(index),
1747             m.Parameter(1));
1748     m.Return(m.Int32Constant(0));
1749     Stream s = m.Build();
1750     ASSERT_EQ(1U, s.size());
1751     EXPECT_EQ(memacc.str_opcode, s[0]->arch_opcode());
1752     EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
1753     ASSERT_EQ(3U, s[0]->InputCount());
1754     ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
1755     EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1)));
1756     EXPECT_EQ(0U, s[0]->OutputCount());
1757   }
1758 }
1759
1760
1761 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1762                         InstructionSelectorMemoryAccessTest,
1763                         ::testing::ValuesIn(kMemoryAccesses));
1764
1765
1766 // -----------------------------------------------------------------------------
1767 // Comparison instructions.
1768
1769 static const MachInst2 kComparisonInstructions[] = {
1770     {&RawMachineAssembler::Word32Equal, "Word32Equal", kArm64Cmp32, kMachInt32},
1771     {&RawMachineAssembler::Word64Equal, "Word64Equal", kArm64Cmp, kMachInt64},
1772 };
1773
1774
1775 typedef InstructionSelectorTestWithParam<MachInst2>
1776     InstructionSelectorComparisonTest;
1777
1778
1779 TEST_P(InstructionSelectorComparisonTest, WithParameters) {
1780   const MachInst2 cmp = GetParam();
1781   const MachineType type = cmp.machine_type;
1782   StreamBuilder m(this, type, type, type);
1783   m.Return((m.*cmp.constructor)(m.Parameter(0), m.Parameter(1)));
1784   Stream s = m.Build();
1785   ASSERT_EQ(1U, s.size());
1786   EXPECT_EQ(cmp.arch_opcode, s[0]->arch_opcode());
1787   EXPECT_EQ(2U, s[0]->InputCount());
1788   EXPECT_EQ(1U, s[0]->OutputCount());
1789   EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1790   EXPECT_EQ(kEqual, s[0]->flags_condition());
1791 }
1792
1793
1794 TEST_P(InstructionSelectorComparisonTest, WithImmediate) {
1795   const MachInst2 cmp = GetParam();
1796   const MachineType type = cmp.machine_type;
1797   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
1798     // Compare with 0 are turned into tst instruction.
1799     if (imm == 0) continue;
1800     StreamBuilder m(this, type, type);
1801     m.Return((m.*cmp.constructor)(m.Parameter(0), BuildConstant(m, type, imm)));
1802     Stream s = m.Build();
1803     ASSERT_EQ(1U, s.size());
1804     EXPECT_EQ(cmp.arch_opcode, s[0]->arch_opcode());
1805     ASSERT_EQ(2U, s[0]->InputCount());
1806     ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
1807     EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(1)));
1808     EXPECT_EQ(1U, s[0]->OutputCount());
1809     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1810     EXPECT_EQ(kEqual, s[0]->flags_condition());
1811   }
1812   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
1813     // Compare with 0 are turned into tst instruction.
1814     if (imm == 0) continue;
1815     StreamBuilder m(this, type, type);
1816     m.Return((m.*cmp.constructor)(BuildConstant(m, type, imm), m.Parameter(0)));
1817     Stream s = m.Build();
1818     ASSERT_EQ(1U, s.size());
1819     EXPECT_EQ(cmp.arch_opcode, s[0]->arch_opcode());
1820     ASSERT_EQ(2U, s[0]->InputCount());
1821     ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
1822     EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(1)));
1823     EXPECT_EQ(1U, s[0]->OutputCount());
1824     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1825     EXPECT_EQ(kEqual, s[0]->flags_condition());
1826   }
1827 }
1828
1829 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1830                         InstructionSelectorComparisonTest,
1831                         ::testing::ValuesIn(kComparisonInstructions));
1832
1833
1834 TEST_F(InstructionSelectorTest, Word32EqualWithZero) {
1835   {
1836     StreamBuilder m(this, kMachInt32, kMachInt32);
1837     m.Return(m.Word32Equal(m.Parameter(0), m.Int32Constant(0)));
1838     Stream s = m.Build();
1839     ASSERT_EQ(1U, s.size());
1840     EXPECT_EQ(kArm64Tst32, s[0]->arch_opcode());
1841     ASSERT_EQ(2U, s[0]->InputCount());
1842     EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
1843     EXPECT_EQ(1U, s[0]->OutputCount());
1844     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1845     EXPECT_EQ(kEqual, s[0]->flags_condition());
1846   }
1847   {
1848     StreamBuilder m(this, kMachInt32, kMachInt32);
1849     m.Return(m.Word32Equal(m.Int32Constant(0), m.Parameter(0)));
1850     Stream s = m.Build();
1851     ASSERT_EQ(1U, s.size());
1852     EXPECT_EQ(kArm64Tst32, s[0]->arch_opcode());
1853     ASSERT_EQ(2U, s[0]->InputCount());
1854     EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
1855     EXPECT_EQ(1U, s[0]->OutputCount());
1856     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1857     EXPECT_EQ(kEqual, s[0]->flags_condition());
1858   }
1859 }
1860
1861
1862 TEST_F(InstructionSelectorTest, Word64EqualWithZero) {
1863   {
1864     StreamBuilder m(this, kMachInt64, kMachInt64);
1865     m.Return(m.Word64Equal(m.Parameter(0), m.Int64Constant(0)));
1866     Stream s = m.Build();
1867     ASSERT_EQ(1U, s.size());
1868     EXPECT_EQ(kArm64Tst, s[0]->arch_opcode());
1869     ASSERT_EQ(2U, s[0]->InputCount());
1870     EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
1871     EXPECT_EQ(1U, s[0]->OutputCount());
1872     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1873     EXPECT_EQ(kEqual, s[0]->flags_condition());
1874   }
1875   {
1876     StreamBuilder m(this, kMachInt64, kMachInt64);
1877     m.Return(m.Word64Equal(m.Int64Constant(0), m.Parameter(0)));
1878     Stream s = m.Build();
1879     ASSERT_EQ(1U, s.size());
1880     EXPECT_EQ(kArm64Tst, s[0]->arch_opcode());
1881     ASSERT_EQ(2U, s[0]->InputCount());
1882     EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
1883     EXPECT_EQ(1U, s[0]->OutputCount());
1884     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1885     EXPECT_EQ(kEqual, s[0]->flags_condition());
1886   }
1887 }
1888
1889
1890 // -----------------------------------------------------------------------------
1891 // Miscellaneous
1892
1893
1894 static const MachInst2 kLogicalWithNotRHSs[] = {
1895     {&RawMachineAssembler::Word32And, "Word32And", kArm64Bic32, kMachInt32},
1896     {&RawMachineAssembler::Word64And, "Word64And", kArm64Bic, kMachInt64},
1897     {&RawMachineAssembler::Word32Or, "Word32Or", kArm64Orn32, kMachInt32},
1898     {&RawMachineAssembler::Word64Or, "Word64Or", kArm64Orn, kMachInt64},
1899     {&RawMachineAssembler::Word32Xor, "Word32Xor", kArm64Eon32, kMachInt32},
1900     {&RawMachineAssembler::Word64Xor, "Word64Xor", kArm64Eon, kMachInt64}};
1901
1902
1903 typedef InstructionSelectorTestWithParam<MachInst2>
1904     InstructionSelectorLogicalWithNotRHSTest;
1905
1906
1907 TEST_P(InstructionSelectorLogicalWithNotRHSTest, Parameter) {
1908   const MachInst2 inst = GetParam();
1909   const MachineType type = inst.machine_type;
1910   // Test cases where RHS is Xor(x, -1).
1911   {
1912     StreamBuilder m(this, type, type, type);
1913     if (type == kMachInt32) {
1914       m.Return((m.*inst.constructor)(
1915           m.Parameter(0), m.Word32Xor(m.Parameter(1), m.Int32Constant(-1))));
1916     } else {
1917       ASSERT_EQ(kMachInt64, type);
1918       m.Return((m.*inst.constructor)(
1919           m.Parameter(0), m.Word64Xor(m.Parameter(1), m.Int64Constant(-1))));
1920     }
1921     Stream s = m.Build();
1922     ASSERT_EQ(1U, s.size());
1923     EXPECT_EQ(inst.arch_opcode, s[0]->arch_opcode());
1924     EXPECT_EQ(2U, s[0]->InputCount());
1925     EXPECT_EQ(1U, s[0]->OutputCount());
1926   }
1927   {
1928     StreamBuilder m(this, type, type, type);
1929     if (type == kMachInt32) {
1930       m.Return((m.*inst.constructor)(
1931           m.Word32Xor(m.Parameter(0), m.Int32Constant(-1)), m.Parameter(1)));
1932     } else {
1933       ASSERT_EQ(kMachInt64, type);
1934       m.Return((m.*inst.constructor)(
1935           m.Word64Xor(m.Parameter(0), m.Int64Constant(-1)), m.Parameter(1)));
1936     }
1937     Stream s = m.Build();
1938     ASSERT_EQ(1U, s.size());
1939     EXPECT_EQ(inst.arch_opcode, s[0]->arch_opcode());
1940     EXPECT_EQ(2U, s[0]->InputCount());
1941     EXPECT_EQ(1U, s[0]->OutputCount());
1942   }
1943   // Test cases where RHS is Not(x).
1944   {
1945     StreamBuilder m(this, type, type, type);
1946     if (type == kMachInt32) {
1947       m.Return(
1948           (m.*inst.constructor)(m.Parameter(0), m.Word32Not(m.Parameter(1))));
1949     } else {
1950       ASSERT_EQ(kMachInt64, type);
1951       m.Return(
1952           (m.*inst.constructor)(m.Parameter(0), m.Word64Not(m.Parameter(1))));
1953     }
1954     Stream s = m.Build();
1955     ASSERT_EQ(1U, s.size());
1956     EXPECT_EQ(inst.arch_opcode, s[0]->arch_opcode());
1957     EXPECT_EQ(2U, s[0]->InputCount());
1958     EXPECT_EQ(1U, s[0]->OutputCount());
1959   }
1960   {
1961     StreamBuilder m(this, type, type, type);
1962     if (type == kMachInt32) {
1963       m.Return(
1964           (m.*inst.constructor)(m.Word32Not(m.Parameter(0)), m.Parameter(1)));
1965     } else {
1966       ASSERT_EQ(kMachInt64, type);
1967       m.Return(
1968           (m.*inst.constructor)(m.Word64Not(m.Parameter(0)), m.Parameter(1)));
1969     }
1970     Stream s = m.Build();
1971     ASSERT_EQ(1U, s.size());
1972     EXPECT_EQ(inst.arch_opcode, s[0]->arch_opcode());
1973     EXPECT_EQ(2U, s[0]->InputCount());
1974     EXPECT_EQ(1U, s[0]->OutputCount());
1975   }
1976 }
1977
1978
1979 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1980                         InstructionSelectorLogicalWithNotRHSTest,
1981                         ::testing::ValuesIn(kLogicalWithNotRHSs));
1982
1983
1984 TEST_F(InstructionSelectorTest, Word32NotWithParameter) {
1985   StreamBuilder m(this, kMachInt32, kMachInt32);
1986   m.Return(m.Word32Not(m.Parameter(0)));
1987   Stream s = m.Build();
1988   ASSERT_EQ(1U, s.size());
1989   EXPECT_EQ(kArm64Not32, s[0]->arch_opcode());
1990   EXPECT_EQ(1U, s[0]->InputCount());
1991   EXPECT_EQ(1U, s[0]->OutputCount());
1992 }
1993
1994
1995 TEST_F(InstructionSelectorTest, Word64NotWithParameter) {
1996   StreamBuilder m(this, kMachInt64, kMachInt64);
1997   m.Return(m.Word64Not(m.Parameter(0)));
1998   Stream s = m.Build();
1999   ASSERT_EQ(1U, s.size());
2000   EXPECT_EQ(kArm64Not, s[0]->arch_opcode());
2001   EXPECT_EQ(1U, s[0]->InputCount());
2002   EXPECT_EQ(1U, s[0]->OutputCount());
2003 }
2004
2005
2006 TEST_F(InstructionSelectorTest, Word32XorMinusOneWithParameter) {
2007   {
2008     StreamBuilder m(this, kMachInt32, kMachInt32);
2009     m.Return(m.Word32Xor(m.Parameter(0), m.Int32Constant(-1)));
2010     Stream s = m.Build();
2011     ASSERT_EQ(1U, s.size());
2012     EXPECT_EQ(kArm64Not32, s[0]->arch_opcode());
2013     EXPECT_EQ(1U, s[0]->InputCount());
2014     EXPECT_EQ(1U, s[0]->OutputCount());
2015   }
2016   {
2017     StreamBuilder m(this, kMachInt32, kMachInt32);
2018     m.Return(m.Word32Xor(m.Int32Constant(-1), m.Parameter(0)));
2019     Stream s = m.Build();
2020     ASSERT_EQ(1U, s.size());
2021     EXPECT_EQ(kArm64Not32, s[0]->arch_opcode());
2022     EXPECT_EQ(1U, s[0]->InputCount());
2023     EXPECT_EQ(1U, s[0]->OutputCount());
2024   }
2025 }
2026
2027
2028 TEST_F(InstructionSelectorTest, Word64XorMinusOneWithParameter) {
2029   {
2030     StreamBuilder m(this, kMachInt64, kMachInt64);
2031     m.Return(m.Word64Xor(m.Parameter(0), m.Int64Constant(-1)));
2032     Stream s = m.Build();
2033     ASSERT_EQ(1U, s.size());
2034     EXPECT_EQ(kArm64Not, s[0]->arch_opcode());
2035     EXPECT_EQ(1U, s[0]->InputCount());
2036     EXPECT_EQ(1U, s[0]->OutputCount());
2037   }
2038   {
2039     StreamBuilder m(this, kMachInt64, kMachInt64);
2040     m.Return(m.Word64Xor(m.Int64Constant(-1), m.Parameter(0)));
2041     Stream s = m.Build();
2042     ASSERT_EQ(1U, s.size());
2043     EXPECT_EQ(kArm64Not, s[0]->arch_opcode());
2044     EXPECT_EQ(1U, s[0]->InputCount());
2045     EXPECT_EQ(1U, s[0]->OutputCount());
2046   }
2047 }
2048
2049
2050 TEST_F(InstructionSelectorTest, Word32ShrWithWord32AndWithImmediate) {
2051   TRACED_FORRANGE(int32_t, lsb, 1, 31) {
2052     TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) {
2053       uint32_t jnk = rng()->NextInt();
2054       jnk >>= 32 - lsb;
2055       uint32_t msk = ((0xffffffffu >> (32 - width)) << lsb) | jnk;
2056       StreamBuilder m(this, kMachInt32, kMachInt32);
2057       m.Return(m.Word32Shr(m.Word32And(m.Parameter(0), m.Int32Constant(msk)),
2058                            m.Int32Constant(lsb)));
2059       Stream s = m.Build();
2060       ASSERT_EQ(1U, s.size());
2061       EXPECT_EQ(kArm64Ubfx32, s[0]->arch_opcode());
2062       ASSERT_EQ(3U, s[0]->InputCount());
2063       EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
2064       EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
2065     }
2066   }
2067   TRACED_FORRANGE(int32_t, lsb, 1, 31) {
2068     TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) {
2069       uint32_t jnk = rng()->NextInt();
2070       jnk >>= 32 - lsb;
2071       uint32_t msk = ((0xffffffffu >> (32 - width)) << lsb) | jnk;
2072       StreamBuilder m(this, kMachInt32, kMachInt32);
2073       m.Return(m.Word32Shr(m.Word32And(m.Int32Constant(msk), m.Parameter(0)),
2074                            m.Int32Constant(lsb)));
2075       Stream s = m.Build();
2076       ASSERT_EQ(1U, s.size());
2077       EXPECT_EQ(kArm64Ubfx32, s[0]->arch_opcode());
2078       ASSERT_EQ(3U, s[0]->InputCount());
2079       EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
2080       EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
2081     }
2082   }
2083 }
2084
2085
2086 TEST_F(InstructionSelectorTest, Word64ShrWithWord64AndWithImmediate) {
2087   TRACED_FORRANGE(int32_t, lsb, 1, 63) {
2088     TRACED_FORRANGE(int32_t, width, 1, 64 - lsb) {
2089       uint64_t jnk = rng()->NextInt64();
2090       jnk >>= 64 - lsb;
2091       uint64_t msk =
2092           ((V8_UINT64_C(0xffffffffffffffff) >> (64 - width)) << lsb) | jnk;
2093       StreamBuilder m(this, kMachInt64, kMachInt64);
2094       m.Return(m.Word64Shr(m.Word64And(m.Parameter(0), m.Int64Constant(msk)),
2095                            m.Int64Constant(lsb)));
2096       Stream s = m.Build();
2097       ASSERT_EQ(1U, s.size());
2098       EXPECT_EQ(kArm64Ubfx, s[0]->arch_opcode());
2099       ASSERT_EQ(3U, s[0]->InputCount());
2100       EXPECT_EQ(lsb, s.ToInt64(s[0]->InputAt(1)));
2101       EXPECT_EQ(width, s.ToInt64(s[0]->InputAt(2)));
2102     }
2103   }
2104   TRACED_FORRANGE(int32_t, lsb, 1, 63) {
2105     TRACED_FORRANGE(int32_t, width, 1, 64 - lsb) {
2106       uint64_t jnk = rng()->NextInt64();
2107       jnk >>= 64 - lsb;
2108       uint64_t msk =
2109           ((V8_UINT64_C(0xffffffffffffffff) >> (64 - width)) << lsb) | jnk;
2110       StreamBuilder m(this, kMachInt64, kMachInt64);
2111       m.Return(m.Word64Shr(m.Word64And(m.Int64Constant(msk), m.Parameter(0)),
2112                            m.Int64Constant(lsb)));
2113       Stream s = m.Build();
2114       ASSERT_EQ(1U, s.size());
2115       EXPECT_EQ(kArm64Ubfx, s[0]->arch_opcode());
2116       ASSERT_EQ(3U, s[0]->InputCount());
2117       EXPECT_EQ(lsb, s.ToInt64(s[0]->InputAt(1)));
2118       EXPECT_EQ(width, s.ToInt64(s[0]->InputAt(2)));
2119     }
2120   }
2121 }
2122
2123
2124 TEST_F(InstructionSelectorTest, Word32AndWithImmediateWithWord32Shr) {
2125   TRACED_FORRANGE(int32_t, lsb, 1, 31) {
2126     TRACED_FORRANGE(int32_t, width, 1, 31) {
2127       uint32_t msk = (1 << width) - 1;
2128       StreamBuilder m(this, kMachInt32, kMachInt32);
2129       m.Return(m.Word32And(m.Word32Shr(m.Parameter(0), m.Int32Constant(lsb)),
2130                            m.Int32Constant(msk)));
2131       Stream s = m.Build();
2132       ASSERT_EQ(1U, s.size());
2133       EXPECT_EQ(kArm64Ubfx32, s[0]->arch_opcode());
2134       ASSERT_EQ(3U, s[0]->InputCount());
2135       EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
2136       int32_t actual_width = (lsb + width > 32) ? (32 - lsb) : width;
2137       EXPECT_EQ(actual_width, s.ToInt32(s[0]->InputAt(2)));
2138     }
2139   }
2140   TRACED_FORRANGE(int32_t, lsb, 1, 31) {
2141     TRACED_FORRANGE(int32_t, width, 1, 31) {
2142       uint32_t msk = (1 << width) - 1;
2143       StreamBuilder m(this, kMachInt32, kMachInt32);
2144       m.Return(m.Word32And(m.Int32Constant(msk),
2145                            m.Word32Shr(m.Parameter(0), m.Int32Constant(lsb))));
2146       Stream s = m.Build();
2147       ASSERT_EQ(1U, s.size());
2148       EXPECT_EQ(kArm64Ubfx32, s[0]->arch_opcode());
2149       ASSERT_EQ(3U, s[0]->InputCount());
2150       EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
2151       int32_t actual_width = (lsb + width > 32) ? (32 - lsb) : width;
2152       EXPECT_EQ(actual_width, s.ToInt32(s[0]->InputAt(2)));
2153     }
2154   }
2155 }
2156
2157
2158 TEST_F(InstructionSelectorTest, Word64AndWithImmediateWithWord64Shr) {
2159   TRACED_FORRANGE(int64_t, lsb, 1, 63) {
2160     TRACED_FORRANGE(int64_t, width, 1, 63) {
2161       uint64_t msk = (V8_UINT64_C(1) << width) - 1;
2162       StreamBuilder m(this, kMachInt64, kMachInt64);
2163       m.Return(m.Word64And(m.Word64Shr(m.Parameter(0), m.Int64Constant(lsb)),
2164                            m.Int64Constant(msk)));
2165       Stream s = m.Build();
2166       ASSERT_EQ(1U, s.size());
2167       EXPECT_EQ(kArm64Ubfx, s[0]->arch_opcode());
2168       ASSERT_EQ(3U, s[0]->InputCount());
2169       EXPECT_EQ(lsb, s.ToInt64(s[0]->InputAt(1)));
2170       int64_t actual_width = (lsb + width > 64) ? (64 - lsb) : width;
2171       EXPECT_EQ(actual_width, s.ToInt64(s[0]->InputAt(2)));
2172     }
2173   }
2174   TRACED_FORRANGE(int64_t, lsb, 1, 63) {
2175     TRACED_FORRANGE(int64_t, width, 1, 63) {
2176       uint64_t msk = (V8_UINT64_C(1) << width) - 1;
2177       StreamBuilder m(this, kMachInt64, kMachInt64);
2178       m.Return(m.Word64And(m.Int64Constant(msk),
2179                            m.Word64Shr(m.Parameter(0), m.Int64Constant(lsb))));
2180       Stream s = m.Build();
2181       ASSERT_EQ(1U, s.size());
2182       EXPECT_EQ(kArm64Ubfx, s[0]->arch_opcode());
2183       ASSERT_EQ(3U, s[0]->InputCount());
2184       EXPECT_EQ(lsb, s.ToInt64(s[0]->InputAt(1)));
2185       int64_t actual_width = (lsb + width > 64) ? (64 - lsb) : width;
2186       EXPECT_EQ(actual_width, s.ToInt64(s[0]->InputAt(2)));
2187     }
2188   }
2189 }
2190
2191
2192 TEST_F(InstructionSelectorTest, Int32MulHighWithParameters) {
2193   StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
2194   Node* const p0 = m.Parameter(0);
2195   Node* const p1 = m.Parameter(1);
2196   Node* const n = m.Int32MulHigh(p0, p1);
2197   m.Return(n);
2198   Stream s = m.Build();
2199   ASSERT_EQ(2U, s.size());
2200   EXPECT_EQ(kArm64Smull, s[0]->arch_opcode());
2201   ASSERT_EQ(2U, s[0]->InputCount());
2202   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
2203   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
2204   ASSERT_EQ(1U, s[0]->OutputCount());
2205   EXPECT_EQ(kArm64Asr, s[1]->arch_opcode());
2206   ASSERT_EQ(2U, s[1]->InputCount());
2207   EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(0)));
2208   EXPECT_EQ(32, s.ToInt64(s[1]->InputAt(1)));
2209   ASSERT_EQ(1U, s[1]->OutputCount());
2210   EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[1]->Output()));
2211 }
2212
2213
2214 TEST_F(InstructionSelectorTest, Word32SarWithWord32Shl) {
2215   {
2216     StreamBuilder m(this, kMachInt32, kMachInt32);
2217     Node* const p0 = m.Parameter(0);
2218     Node* const r =
2219         m.Word32Sar(m.Word32Shl(p0, m.Int32Constant(24)), m.Int32Constant(24));
2220     m.Return(r);
2221     Stream s = m.Build();
2222     ASSERT_EQ(1U, s.size());
2223     EXPECT_EQ(kArm64Sxtb32, s[0]->arch_opcode());
2224     ASSERT_EQ(1U, s[0]->InputCount());
2225     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
2226     ASSERT_EQ(1U, s[0]->OutputCount());
2227     EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
2228   }
2229   {
2230     StreamBuilder m(this, kMachInt32, kMachInt32);
2231     Node* const p0 = m.Parameter(0);
2232     Node* const r =
2233         m.Word32Sar(m.Word32Shl(p0, m.Int32Constant(16)), m.Int32Constant(16));
2234     m.Return(r);
2235     Stream s = m.Build();
2236     ASSERT_EQ(1U, s.size());
2237     EXPECT_EQ(kArm64Sxth32, s[0]->arch_opcode());
2238     ASSERT_EQ(1U, s[0]->InputCount());
2239     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
2240     ASSERT_EQ(1U, s[0]->OutputCount());
2241     EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
2242   }
2243 }
2244
2245
2246 TEST_F(InstructionSelectorTest, Word32Clz) {
2247   StreamBuilder m(this, kMachUint32, kMachUint32);
2248   Node* const p0 = m.Parameter(0);
2249   Node* const n = m.Word32Clz(p0);
2250   m.Return(n);
2251   Stream s = m.Build();
2252   ASSERT_EQ(1U, s.size());
2253   EXPECT_EQ(kArm64Clz32, s[0]->arch_opcode());
2254   ASSERT_EQ(1U, s[0]->InputCount());
2255   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
2256   ASSERT_EQ(1U, s[0]->OutputCount());
2257   EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
2258 }
2259
2260 }  // namespace compiler
2261 }  // namespace internal
2262 }  // namespace v8