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
7namespace v8 {
8namespace internal {
9namespace compiler {
10
11namespace {
12
13template <typename T>
14struct MachInst {
15  T constructor;
16  const char* constructor_name;
17  ArchOpcode arch_opcode;
18  MachineType machine_type;
19};
20
21typedef MachInst<Node* (RawMachineAssembler::*)(Node*)> MachInst1;
22typedef MachInst<Node* (RawMachineAssembler::*)(Node*, Node*)> MachInst2;
23
24
25template <typename T>
26std::ostream& operator<<(std::ostream& os, const MachInst<T>& mi) {
27  return os << mi.constructor_name;
28}
29
30
31struct Shift {
32  MachInst2 mi;
33  AddressingMode mode;
34};
35
36
37std::ostream& operator<<(std::ostream& os, const Shift& shift) {
38  return os << shift.mi;
39}
40
41
42// Helper to build Int32Constant or Int64Constant depending on the given
43// machine type.
44Node* BuildConstant(InstructionSelectorTest::StreamBuilder& m, MachineType type,
45                    int64_t value) {
46  switch (type.representation()) {
47    case MachineRepresentation::kWord32:
48      return m.Int32Constant(static_cast<int32_t>(value));
49      break;
50
51    case MachineRepresentation::kWord64:
52      return m.Int64Constant(value);
53      break;
54
55    default:
56      UNIMPLEMENTED();
57  }
58  return NULL;
59}
60
61
62// ARM64 logical instructions.
63const MachInst2 kLogicalInstructions[] = {
64    {&RawMachineAssembler::Word32And, "Word32And", kArm64And32,
65     MachineType::Int32()},
66    {&RawMachineAssembler::Word64And, "Word64And", kArm64And,
67     MachineType::Int64()},
68    {&RawMachineAssembler::Word32Or, "Word32Or", kArm64Or32,
69     MachineType::Int32()},
70    {&RawMachineAssembler::Word64Or, "Word64Or", kArm64Or,
71     MachineType::Int64()},
72    {&RawMachineAssembler::Word32Xor, "Word32Xor", kArm64Eor32,
73     MachineType::Int32()},
74    {&RawMachineAssembler::Word64Xor, "Word64Xor", kArm64Eor,
75     MachineType::Int64()}};
76
77
78// ARM64 logical immediates: contiguous set bits, rotated about a power of two
79// sized block. The block is then duplicated across the word. Below is a random
80// subset of the 32-bit immediates.
81const uint32_t kLogical32Immediates[] = {
82    0x00000002, 0x00000003, 0x00000070, 0x00000080, 0x00000100, 0x000001c0,
83    0x00000300, 0x000007e0, 0x00003ffc, 0x00007fc0, 0x0003c000, 0x0003f000,
84    0x0003ffc0, 0x0003fff8, 0x0007ff00, 0x0007ffe0, 0x000e0000, 0x001e0000,
85    0x001ffffc, 0x003f0000, 0x003f8000, 0x00780000, 0x007fc000, 0x00ff0000,
86    0x01800000, 0x01800180, 0x01f801f8, 0x03fe0000, 0x03ffffc0, 0x03fffffc,
87    0x06000000, 0x07fc0000, 0x07ffc000, 0x07ffffc0, 0x07ffffe0, 0x0ffe0ffe,
88    0x0ffff800, 0x0ffffff0, 0x0fffffff, 0x18001800, 0x1f001f00, 0x1f801f80,
89    0x30303030, 0x3ff03ff0, 0x3ff83ff8, 0x3fff0000, 0x3fff8000, 0x3fffffc0,
90    0x70007000, 0x7f7f7f7f, 0x7fc00000, 0x7fffffc0, 0x8000001f, 0x800001ff,
91    0x81818181, 0x9fff9fff, 0xc00007ff, 0xc0ffffff, 0xdddddddd, 0xe00001ff,
92    0xe00003ff, 0xe007ffff, 0xefffefff, 0xf000003f, 0xf001f001, 0xf3fff3ff,
93    0xf800001f, 0xf80fffff, 0xf87ff87f, 0xfbfbfbfb, 0xfc00001f, 0xfc0000ff,
94    0xfc0001ff, 0xfc03fc03, 0xfe0001ff, 0xff000001, 0xff03ff03, 0xff800000,
95    0xff800fff, 0xff801fff, 0xff87ffff, 0xffc0003f, 0xffc007ff, 0xffcfffcf,
96    0xffe00003, 0xffe1ffff, 0xfff0001f, 0xfff07fff, 0xfff80007, 0xfff87fff,
97    0xfffc00ff, 0xfffe07ff, 0xffff00ff, 0xffffc001, 0xfffff007, 0xfffff3ff,
98    0xfffff807, 0xfffff9ff, 0xfffffc0f, 0xfffffeff};
99
100
101// Random subset of 64-bit logical immediates.
102const uint64_t kLogical64Immediates[] = {
103    0x0000000000000001, 0x0000000000000002, 0x0000000000000003,
104    0x0000000000000070, 0x0000000000000080, 0x0000000000000100,
105    0x00000000000001c0, 0x0000000000000300, 0x0000000000000600,
106    0x00000000000007e0, 0x0000000000003ffc, 0x0000000000007fc0,
107    0x0000000600000000, 0x0000003ffffffffc, 0x000000f000000000,
108    0x000001f800000000, 0x0003fc0000000000, 0x0003fc000003fc00,
109    0x0003ffffffc00000, 0x0003ffffffffffc0, 0x0006000000060000,
110    0x003ffffffffc0000, 0x0180018001800180, 0x01f801f801f801f8,
111    0x0600000000000000, 0x1000000010000000, 0x1000100010001000,
112    0x1010101010101010, 0x1111111111111111, 0x1f001f001f001f00,
113    0x1f1f1f1f1f1f1f1f, 0x1ffffffffffffffe, 0x3ffc3ffc3ffc3ffc,
114    0x5555555555555555, 0x7f7f7f7f7f7f7f7f, 0x8000000000000000,
115    0x8000001f8000001f, 0x8181818181818181, 0x9999999999999999,
116    0x9fff9fff9fff9fff, 0xaaaaaaaaaaaaaaaa, 0xdddddddddddddddd,
117    0xe0000000000001ff, 0xf800000000000000, 0xf8000000000001ff,
118    0xf807f807f807f807, 0xfefefefefefefefe, 0xfffefffefffefffe,
119    0xfffff807fffff807, 0xfffff9fffffff9ff, 0xfffffc0ffffffc0f,
120    0xfffffc0fffffffff, 0xfffffefffffffeff, 0xfffffeffffffffff,
121    0xffffff8000000000, 0xfffffffefffffffe, 0xffffffffefffffff,
122    0xfffffffff9ffffff, 0xffffffffff800000, 0xffffffffffffc0ff,
123    0xfffffffffffffffe};
124
125
126// ARM64 arithmetic instructions.
127struct AddSub {
128  MachInst2 mi;
129  ArchOpcode negate_arch_opcode;
130};
131
132
133std::ostream& operator<<(std::ostream& os, const AddSub& op) {
134  return os << op.mi;
135}
136
137
138const AddSub kAddSubInstructions[] = {
139    {{&RawMachineAssembler::Int32Add, "Int32Add", kArm64Add32,
140      MachineType::Int32()},
141     kArm64Sub32},
142    {{&RawMachineAssembler::Int64Add, "Int64Add", kArm64Add,
143      MachineType::Int64()},
144     kArm64Sub},
145    {{&RawMachineAssembler::Int32Sub, "Int32Sub", kArm64Sub32,
146      MachineType::Int32()},
147     kArm64Add32},
148    {{&RawMachineAssembler::Int64Sub, "Int64Sub", kArm64Sub,
149      MachineType::Int64()},
150     kArm64Add}};
151
152
153// ARM64 Add/Sub immediates: 12-bit immediate optionally shifted by 12.
154// Below is a combination of a random subset and some edge values.
155const int32_t kAddSubImmediates[] = {
156    0,        1,        69,       493,      599,      701,      719,
157    768,      818,      842,      945,      1246,     1286,     1429,
158    1669,     2171,     2179,     2182,     2254,     2334,     2338,
159    2343,     2396,     2449,     2610,     2732,     2855,     2876,
160    2944,     3377,     3458,     3475,     3476,     3540,     3574,
161    3601,     3813,     3871,     3917,     4095,     4096,     16384,
162    364544,   462848,   970752,   1523712,  1863680,  2363392,  3219456,
163    3280896,  4247552,  4526080,  4575232,  4960256,  5505024,  5894144,
164    6004736,  6193152,  6385664,  6795264,  7114752,  7233536,  7348224,
165    7499776,  7573504,  7729152,  8634368,  8937472,  9465856,  10354688,
166    10682368, 11059200, 11460608, 13168640, 13176832, 14336000, 15028224,
167    15597568, 15892480, 16773120};
168
169
170// ARM64 flag setting data processing instructions.
171const MachInst2 kDPFlagSetInstructions[] = {
172    {&RawMachineAssembler::Word32And, "Word32And", kArm64Tst32,
173     MachineType::Int32()},
174    {&RawMachineAssembler::Int32Add, "Int32Add", kArm64Cmn32,
175     MachineType::Int32()},
176    {&RawMachineAssembler::Int32Sub, "Int32Sub", kArm64Cmp32,
177     MachineType::Int32()},
178    {&RawMachineAssembler::Word64And, "Word64And", kArm64Tst,
179     MachineType::Int64()}};
180
181
182// ARM64 arithmetic with overflow instructions.
183const MachInst2 kOvfAddSubInstructions[] = {
184    {&RawMachineAssembler::Int32AddWithOverflow, "Int32AddWithOverflow",
185     kArm64Add32, MachineType::Int32()},
186    {&RawMachineAssembler::Int32SubWithOverflow, "Int32SubWithOverflow",
187     kArm64Sub32, MachineType::Int32()},
188    {&RawMachineAssembler::Int64AddWithOverflow, "Int64AddWithOverflow",
189     kArm64Add, MachineType::Int64()},
190    {&RawMachineAssembler::Int64SubWithOverflow, "Int64SubWithOverflow",
191     kArm64Sub, MachineType::Int64()}};
192
193// ARM64 shift instructions.
194const Shift kShiftInstructions[] = {
195    {{&RawMachineAssembler::Word32Shl, "Word32Shl", kArm64Lsl32,
196      MachineType::Int32()},
197     kMode_Operand2_R_LSL_I},
198    {{&RawMachineAssembler::Word64Shl, "Word64Shl", kArm64Lsl,
199      MachineType::Int64()},
200     kMode_Operand2_R_LSL_I},
201    {{&RawMachineAssembler::Word32Shr, "Word32Shr", kArm64Lsr32,
202      MachineType::Int32()},
203     kMode_Operand2_R_LSR_I},
204    {{&RawMachineAssembler::Word64Shr, "Word64Shr", kArm64Lsr,
205      MachineType::Int64()},
206     kMode_Operand2_R_LSR_I},
207    {{&RawMachineAssembler::Word32Sar, "Word32Sar", kArm64Asr32,
208      MachineType::Int32()},
209     kMode_Operand2_R_ASR_I},
210    {{&RawMachineAssembler::Word64Sar, "Word64Sar", kArm64Asr,
211      MachineType::Int64()},
212     kMode_Operand2_R_ASR_I},
213    {{&RawMachineAssembler::Word32Ror, "Word32Ror", kArm64Ror32,
214      MachineType::Int32()},
215     kMode_Operand2_R_ROR_I},
216    {{&RawMachineAssembler::Word64Ror, "Word64Ror", kArm64Ror,
217      MachineType::Int64()},
218     kMode_Operand2_R_ROR_I}};
219
220
221// ARM64 Mul/Div instructions.
222const MachInst2 kMulDivInstructions[] = {
223    {&RawMachineAssembler::Int32Mul, "Int32Mul", kArm64Mul32,
224     MachineType::Int32()},
225    {&RawMachineAssembler::Int64Mul, "Int64Mul", kArm64Mul,
226     MachineType::Int64()},
227    {&RawMachineAssembler::Int32Div, "Int32Div", kArm64Idiv32,
228     MachineType::Int32()},
229    {&RawMachineAssembler::Int64Div, "Int64Div", kArm64Idiv,
230     MachineType::Int64()},
231    {&RawMachineAssembler::Uint32Div, "Uint32Div", kArm64Udiv32,
232     MachineType::Int32()},
233    {&RawMachineAssembler::Uint64Div, "Uint64Div", kArm64Udiv,
234     MachineType::Int64()}};
235
236
237// ARM64 FP arithmetic instructions.
238const MachInst2 kFPArithInstructions[] = {
239    {&RawMachineAssembler::Float64Add, "Float64Add", kArm64Float64Add,
240     MachineType::Float64()},
241    {&RawMachineAssembler::Float64Sub, "Float64Sub", kArm64Float64Sub,
242     MachineType::Float64()},
243    {&RawMachineAssembler::Float64Mul, "Float64Mul", kArm64Float64Mul,
244     MachineType::Float64()},
245    {&RawMachineAssembler::Float64Div, "Float64Div", kArm64Float64Div,
246     MachineType::Float64()}};
247
248
249struct FPCmp {
250  MachInst2 mi;
251  FlagsCondition cond;
252  FlagsCondition commuted_cond;
253};
254
255
256std::ostream& operator<<(std::ostream& os, const FPCmp& cmp) {
257  return os << cmp.mi;
258}
259
260
261// ARM64 FP comparison instructions.
262const FPCmp kFPCmpInstructions[] = {
263    {{&RawMachineAssembler::Float64Equal, "Float64Equal", kArm64Float64Cmp,
264      MachineType::Float64()},
265     kEqual,
266     kEqual},
267    {{&RawMachineAssembler::Float64LessThan, "Float64LessThan",
268      kArm64Float64Cmp, MachineType::Float64()},
269     kFloatLessThan,
270     kFloatGreaterThan},
271    {{&RawMachineAssembler::Float64LessThanOrEqual, "Float64LessThanOrEqual",
272      kArm64Float64Cmp, MachineType::Float64()},
273     kFloatLessThanOrEqual,
274     kFloatGreaterThanOrEqual},
275    {{&RawMachineAssembler::Float32Equal, "Float32Equal", kArm64Float32Cmp,
276      MachineType::Float32()},
277     kEqual,
278     kEqual},
279    {{&RawMachineAssembler::Float32LessThan, "Float32LessThan",
280      kArm64Float32Cmp, MachineType::Float32()},
281     kFloatLessThan,
282     kFloatGreaterThan},
283    {{&RawMachineAssembler::Float32LessThanOrEqual, "Float32LessThanOrEqual",
284      kArm64Float32Cmp, MachineType::Float32()},
285     kFloatLessThanOrEqual,
286     kFloatGreaterThanOrEqual}};
287
288
289struct Conversion {
290  // The machine_type field in MachInst1 represents the destination type.
291  MachInst1 mi;
292  MachineType src_machine_type;
293};
294
295
296std::ostream& operator<<(std::ostream& os, const Conversion& conv) {
297  return os << conv.mi;
298}
299
300
301// ARM64 type conversion instructions.
302const Conversion kConversionInstructions[] = {
303    {{&RawMachineAssembler::ChangeFloat32ToFloat64, "ChangeFloat32ToFloat64",
304      kArm64Float32ToFloat64, MachineType::Float64()},
305     MachineType::Float32()},
306    {{&RawMachineAssembler::TruncateFloat64ToFloat32,
307      "TruncateFloat64ToFloat32", kArm64Float64ToFloat32,
308      MachineType::Float32()},
309     MachineType::Float64()},
310    {{&RawMachineAssembler::ChangeInt32ToInt64, "ChangeInt32ToInt64",
311      kArm64Sxtw, MachineType::Int64()},
312     MachineType::Int32()},
313    {{&RawMachineAssembler::ChangeUint32ToUint64, "ChangeUint32ToUint64",
314      kArm64Mov32, MachineType::Uint64()},
315     MachineType::Uint32()},
316    {{&RawMachineAssembler::TruncateInt64ToInt32, "TruncateInt64ToInt32",
317      kArm64Mov32, MachineType::Int32()},
318     MachineType::Int64()},
319    {{&RawMachineAssembler::ChangeInt32ToFloat64, "ChangeInt32ToFloat64",
320      kArm64Int32ToFloat64, MachineType::Float64()},
321     MachineType::Int32()},
322    {{&RawMachineAssembler::ChangeUint32ToFloat64, "ChangeUint32ToFloat64",
323      kArm64Uint32ToFloat64, MachineType::Float64()},
324     MachineType::Uint32()},
325    {{&RawMachineAssembler::ChangeFloat64ToInt32, "ChangeFloat64ToInt32",
326      kArm64Float64ToInt32, MachineType::Int32()},
327     MachineType::Float64()},
328    {{&RawMachineAssembler::ChangeFloat64ToUint32, "ChangeFloat64ToUint32",
329      kArm64Float64ToUint32, MachineType::Uint32()},
330     MachineType::Float64()}};
331
332// ARM64 instructions that clear the top 32 bits of the destination.
333const MachInst2 kCanElideChangeUint32ToUint64[] = {
334    {&RawMachineAssembler::Word32And, "Word32And", kArm64And32,
335     MachineType::Uint32()},
336    {&RawMachineAssembler::Word32Or, "Word32Or", kArm64Or32,
337     MachineType::Uint32()},
338    {&RawMachineAssembler::Word32Xor, "Word32Xor", kArm64Eor32,
339     MachineType::Uint32()},
340    {&RawMachineAssembler::Word32Shl, "Word32Shl", kArm64Lsl32,
341     MachineType::Uint32()},
342    {&RawMachineAssembler::Word32Shr, "Word32Shr", kArm64Lsr32,
343     MachineType::Uint32()},
344    {&RawMachineAssembler::Word32Sar, "Word32Sar", kArm64Asr32,
345     MachineType::Uint32()},
346    {&RawMachineAssembler::Word32Ror, "Word32Ror", kArm64Ror32,
347     MachineType::Uint32()},
348    {&RawMachineAssembler::Word32Equal, "Word32Equal", kArm64Cmp32,
349     MachineType::Uint32()},
350    {&RawMachineAssembler::Int32Add, "Int32Add", kArm64Add32,
351     MachineType::Int32()},
352    {&RawMachineAssembler::Int32AddWithOverflow, "Int32AddWithOverflow",
353     kArm64Add32, MachineType::Int32()},
354    {&RawMachineAssembler::Int32Sub, "Int32Sub", kArm64Sub32,
355     MachineType::Int32()},
356    {&RawMachineAssembler::Int32SubWithOverflow, "Int32SubWithOverflow",
357     kArm64Sub32, MachineType::Int32()},
358    {&RawMachineAssembler::Int32Mul, "Int32Mul", kArm64Mul32,
359     MachineType::Int32()},
360    {&RawMachineAssembler::Int32Div, "Int32Div", kArm64Idiv32,
361     MachineType::Int32()},
362    {&RawMachineAssembler::Int32Mod, "Int32Mod", kArm64Imod32,
363     MachineType::Int32()},
364    {&RawMachineAssembler::Int32LessThan, "Int32LessThan", kArm64Cmp32,
365     MachineType::Int32()},
366    {&RawMachineAssembler::Int32LessThanOrEqual, "Int32LessThanOrEqual",
367     kArm64Cmp32, MachineType::Int32()},
368    {&RawMachineAssembler::Uint32Div, "Uint32Div", kArm64Udiv32,
369     MachineType::Uint32()},
370    {&RawMachineAssembler::Uint32LessThan, "Uint32LessThan", kArm64Cmp32,
371     MachineType::Uint32()},
372    {&RawMachineAssembler::Uint32LessThanOrEqual, "Uint32LessThanOrEqual",
373     kArm64Cmp32, MachineType::Uint32()},
374    {&RawMachineAssembler::Uint32Mod, "Uint32Mod", kArm64Umod32,
375     MachineType::Uint32()},
376};
377
378}  // namespace
379
380
381// -----------------------------------------------------------------------------
382// Logical instructions.
383
384
385typedef InstructionSelectorTestWithParam<MachInst2>
386    InstructionSelectorLogicalTest;
387
388
389TEST_P(InstructionSelectorLogicalTest, Parameter) {
390  const MachInst2 dpi = GetParam();
391  const MachineType type = dpi.machine_type;
392  StreamBuilder m(this, type, type, type);
393  m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)));
394  Stream s = m.Build();
395  ASSERT_EQ(1U, s.size());
396  EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
397  EXPECT_EQ(2U, s[0]->InputCount());
398  EXPECT_EQ(1U, s[0]->OutputCount());
399}
400
401
402TEST_P(InstructionSelectorLogicalTest, Immediate) {
403  const MachInst2 dpi = GetParam();
404  const MachineType type = dpi.machine_type;
405  // TODO(all): Add support for testing 64-bit immediates.
406  if (type == MachineType::Int32()) {
407    // Immediate on the right.
408    TRACED_FOREACH(int32_t, imm, kLogical32Immediates) {
409      StreamBuilder m(this, type, type);
410      m.Return((m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm)));
411      Stream s = m.Build();
412      ASSERT_EQ(1U, s.size());
413      EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
414      ASSERT_EQ(2U, s[0]->InputCount());
415      EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
416      EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
417      EXPECT_EQ(1U, s[0]->OutputCount());
418    }
419
420    // Immediate on the left; all logical ops should commute.
421    TRACED_FOREACH(int32_t, imm, kLogical32Immediates) {
422      StreamBuilder m(this, type, type);
423      m.Return((m.*dpi.constructor)(m.Int32Constant(imm), m.Parameter(0)));
424      Stream s = m.Build();
425      ASSERT_EQ(1U, s.size());
426      EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
427      ASSERT_EQ(2U, s[0]->InputCount());
428      EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
429      EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
430      EXPECT_EQ(1U, s[0]->OutputCount());
431    }
432  }
433}
434
435
436TEST_P(InstructionSelectorLogicalTest, ShiftByImmediate) {
437  const MachInst2 dpi = GetParam();
438  const MachineType type = dpi.machine_type;
439  TRACED_FOREACH(Shift, shift, kShiftInstructions) {
440    // Only test 64-bit shifted operands with 64-bit instructions.
441    if (shift.mi.machine_type != type) continue;
442
443    TRACED_FORRANGE(int, imm, 0, ((type == MachineType::Int32()) ? 31 : 63)) {
444      StreamBuilder m(this, type, type, type);
445      m.Return((m.*dpi.constructor)(
446          m.Parameter(0),
447          (m.*shift.mi.constructor)(m.Parameter(1),
448                                    BuildConstant(m, type, imm))));
449      Stream s = m.Build();
450      ASSERT_EQ(1U, s.size());
451      EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
452      EXPECT_EQ(shift.mode, s[0]->addressing_mode());
453      EXPECT_EQ(3U, s[0]->InputCount());
454      EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(2)));
455      EXPECT_EQ(1U, s[0]->OutputCount());
456    }
457
458    TRACED_FORRANGE(int, imm, 0, ((type == MachineType::Int32()) ? 31 : 63)) {
459      StreamBuilder m(this, type, type, type);
460      m.Return((m.*dpi.constructor)(
461          (m.*shift.mi.constructor)(m.Parameter(1),
462                                    BuildConstant(m, type, imm)),
463          m.Parameter(0)));
464      Stream s = m.Build();
465      ASSERT_EQ(1U, s.size());
466      EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
467      EXPECT_EQ(shift.mode, s[0]->addressing_mode());
468      EXPECT_EQ(3U, s[0]->InputCount());
469      EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(2)));
470      EXPECT_EQ(1U, s[0]->OutputCount());
471    }
472  }
473}
474
475
476INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorLogicalTest,
477                        ::testing::ValuesIn(kLogicalInstructions));
478
479
480// -----------------------------------------------------------------------------
481// Add and Sub instructions.
482
483typedef InstructionSelectorTestWithParam<AddSub> InstructionSelectorAddSubTest;
484
485
486TEST_P(InstructionSelectorAddSubTest, Parameter) {
487  const AddSub dpi = GetParam();
488  const MachineType type = dpi.mi.machine_type;
489  StreamBuilder m(this, type, type, type);
490  m.Return((m.*dpi.mi.constructor)(m.Parameter(0), m.Parameter(1)));
491  Stream s = m.Build();
492  ASSERT_EQ(1U, s.size());
493  EXPECT_EQ(dpi.mi.arch_opcode, s[0]->arch_opcode());
494  EXPECT_EQ(2U, s[0]->InputCount());
495  EXPECT_EQ(1U, s[0]->OutputCount());
496}
497
498
499TEST_P(InstructionSelectorAddSubTest, ImmediateOnRight) {
500  const AddSub dpi = GetParam();
501  const MachineType type = dpi.mi.machine_type;
502  TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
503    StreamBuilder m(this, type, type);
504    m.Return(
505        (m.*dpi.mi.constructor)(m.Parameter(0), BuildConstant(m, type, imm)));
506    Stream s = m.Build();
507    ASSERT_EQ(1U, s.size());
508    EXPECT_EQ(dpi.mi.arch_opcode, s[0]->arch_opcode());
509    ASSERT_EQ(2U, s[0]->InputCount());
510    EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
511    EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(1)));
512    EXPECT_EQ(1U, s[0]->OutputCount());
513  }
514}
515
516
517TEST_P(InstructionSelectorAddSubTest, NegImmediateOnRight) {
518  const AddSub dpi = GetParam();
519  const MachineType type = dpi.mi.machine_type;
520  TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
521    if (imm == 0) continue;
522    StreamBuilder m(this, type, type);
523    m.Return(
524        (m.*dpi.mi.constructor)(m.Parameter(0), BuildConstant(m, type, -imm)));
525    Stream s = m.Build();
526    ASSERT_EQ(1U, s.size());
527    EXPECT_EQ(dpi.negate_arch_opcode, s[0]->arch_opcode());
528    ASSERT_EQ(2U, s[0]->InputCount());
529    ASSERT_TRUE(s[0]->InputAt(1)->IsImmediate());
530    EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
531    EXPECT_EQ(1U, s[0]->OutputCount());
532  }
533}
534
535
536TEST_P(InstructionSelectorAddSubTest, ShiftByImmediateOnRight) {
537  const AddSub dpi = GetParam();
538  const MachineType type = dpi.mi.machine_type;
539  TRACED_FOREACH(Shift, shift, kShiftInstructions) {
540    // Only test 64-bit shifted operands with 64-bit instructions.
541    if (shift.mi.machine_type != type) continue;
542
543    if ((shift.mi.arch_opcode == kArm64Ror32) ||
544        (shift.mi.arch_opcode == kArm64Ror)) {
545      // Not supported by add/sub instructions.
546      continue;
547    }
548
549    TRACED_FORRANGE(int, imm, 0, ((type == MachineType::Int32()) ? 31 : 63)) {
550      StreamBuilder m(this, type, type, type);
551      m.Return((m.*dpi.mi.constructor)(
552          m.Parameter(0),
553          (m.*shift.mi.constructor)(m.Parameter(1),
554                                    BuildConstant(m, type, imm))));
555      Stream s = m.Build();
556      ASSERT_EQ(1U, s.size());
557      EXPECT_EQ(dpi.mi.arch_opcode, s[0]->arch_opcode());
558      EXPECT_EQ(shift.mode, s[0]->addressing_mode());
559      EXPECT_EQ(3U, s[0]->InputCount());
560      EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(2)));
561      EXPECT_EQ(1U, s[0]->OutputCount());
562    }
563  }
564}
565
566
567TEST_P(InstructionSelectorAddSubTest, UnsignedExtendByte) {
568  const AddSub dpi = GetParam();
569  const MachineType type = dpi.mi.machine_type;
570  StreamBuilder m(this, type, type, type);
571  m.Return((m.*dpi.mi.constructor)(
572      m.Parameter(0), m.Word32And(m.Parameter(1), m.Int32Constant(0xff))));
573  Stream s = m.Build();
574  ASSERT_EQ(1U, s.size());
575  EXPECT_EQ(dpi.mi.arch_opcode, s[0]->arch_opcode());
576  EXPECT_EQ(kMode_Operand2_R_UXTB, s[0]->addressing_mode());
577  ASSERT_EQ(2U, s[0]->InputCount());
578  ASSERT_EQ(1U, s[0]->OutputCount());
579}
580
581
582TEST_P(InstructionSelectorAddSubTest, UnsignedExtendHalfword) {
583  const AddSub dpi = GetParam();
584  const MachineType type = dpi.mi.machine_type;
585  StreamBuilder m(this, type, type, type);
586  m.Return((m.*dpi.mi.constructor)(
587      m.Parameter(0), m.Word32And(m.Parameter(1), m.Int32Constant(0xffff))));
588  Stream s = m.Build();
589  ASSERT_EQ(1U, s.size());
590  EXPECT_EQ(dpi.mi.arch_opcode, s[0]->arch_opcode());
591  EXPECT_EQ(kMode_Operand2_R_UXTH, s[0]->addressing_mode());
592  ASSERT_EQ(2U, s[0]->InputCount());
593  ASSERT_EQ(1U, s[0]->OutputCount());
594}
595
596
597TEST_P(InstructionSelectorAddSubTest, SignedExtendByte) {
598  const AddSub dpi = GetParam();
599  const MachineType type = dpi.mi.machine_type;
600  StreamBuilder m(this, type, type, type);
601  m.Return((m.*dpi.mi.constructor)(
602      m.Parameter(0),
603      m.Word32Sar(m.Word32Shl(m.Parameter(1), m.Int32Constant(24)),
604                  m.Int32Constant(24))));
605  Stream s = m.Build();
606  ASSERT_EQ(1U, s.size());
607  EXPECT_EQ(dpi.mi.arch_opcode, s[0]->arch_opcode());
608  EXPECT_EQ(kMode_Operand2_R_SXTB, s[0]->addressing_mode());
609  ASSERT_EQ(2U, s[0]->InputCount());
610  ASSERT_EQ(1U, s[0]->OutputCount());
611}
612
613
614TEST_P(InstructionSelectorAddSubTest, SignedExtendHalfword) {
615  const AddSub dpi = GetParam();
616  const MachineType type = dpi.mi.machine_type;
617  StreamBuilder m(this, type, type, type);
618  m.Return((m.*dpi.mi.constructor)(
619      m.Parameter(0),
620      m.Word32Sar(m.Word32Shl(m.Parameter(1), m.Int32Constant(16)),
621                  m.Int32Constant(16))));
622  Stream s = m.Build();
623  ASSERT_EQ(1U, s.size());
624  EXPECT_EQ(dpi.mi.arch_opcode, s[0]->arch_opcode());
625  EXPECT_EQ(kMode_Operand2_R_SXTH, s[0]->addressing_mode());
626  ASSERT_EQ(2U, s[0]->InputCount());
627  ASSERT_EQ(1U, s[0]->OutputCount());
628}
629
630
631INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorAddSubTest,
632                        ::testing::ValuesIn(kAddSubInstructions));
633
634
635TEST_F(InstructionSelectorTest, AddImmediateOnLeft) {
636  {
637    // 32-bit add.
638    TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
639      StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
640      m.Return(m.Int32Add(m.Int32Constant(imm), m.Parameter(0)));
641      Stream s = m.Build();
642      ASSERT_EQ(1U, s.size());
643      EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
644      ASSERT_EQ(2U, s[0]->InputCount());
645      EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
646      EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
647      EXPECT_EQ(1U, s[0]->OutputCount());
648    }
649  }
650  {
651    // 64-bit add.
652    TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
653      StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
654      m.Return(m.Int64Add(m.Int64Constant(imm), m.Parameter(0)));
655      Stream s = m.Build();
656      ASSERT_EQ(1U, s.size());
657      EXPECT_EQ(kArm64Add, s[0]->arch_opcode());
658      ASSERT_EQ(2U, s[0]->InputCount());
659      EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
660      EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(1)));
661      EXPECT_EQ(1U, s[0]->OutputCount());
662    }
663  }
664}
665
666
667TEST_F(InstructionSelectorTest, SubZeroOnLeft) {
668  {
669    // 32-bit subtract.
670    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
671                    MachineType::Int32());
672    m.Return(m.Int32Sub(m.Int32Constant(0), m.Parameter(0)));
673    Stream s = m.Build();
674
675    ASSERT_EQ(1U, s.size());
676    EXPECT_EQ(kArm64Sub32, s[0]->arch_opcode());
677    ASSERT_EQ(2U, s[0]->InputCount());
678    EXPECT_TRUE(s[0]->InputAt(0)->IsImmediate());
679    EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(0)));
680    EXPECT_EQ(1U, s[0]->OutputCount());
681  }
682  {
683    // 64-bit subtract.
684    StreamBuilder m(this, MachineType::Int64(), MachineType::Int64(),
685                    MachineType::Int64());
686    m.Return(m.Int64Sub(m.Int64Constant(0), m.Parameter(0)));
687    Stream s = m.Build();
688
689    ASSERT_EQ(1U, s.size());
690    EXPECT_EQ(kArm64Sub, s[0]->arch_opcode());
691    ASSERT_EQ(2U, s[0]->InputCount());
692    EXPECT_TRUE(s[0]->InputAt(0)->IsImmediate());
693    EXPECT_EQ(0, s.ToInt64(s[0]->InputAt(0)));
694    EXPECT_EQ(1U, s[0]->OutputCount());
695  }
696}
697
698
699TEST_F(InstructionSelectorTest, SubZeroOnLeftWithShift) {
700  TRACED_FOREACH(Shift, shift, kShiftInstructions) {
701    {
702      // Test 32-bit operations. Ignore ROR shifts, as subtract does not
703      // support them.
704      if ((shift.mi.machine_type != MachineType::Int32()) ||
705          (shift.mi.arch_opcode == kArm64Ror32) ||
706          (shift.mi.arch_opcode == kArm64Ror))
707        continue;
708
709      TRACED_FORRANGE(int, imm, -32, 63) {
710        StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
711                        MachineType::Int32());
712        m.Return(m.Int32Sub(
713            m.Int32Constant(0),
714            (m.*shift.mi.constructor)(m.Parameter(1), m.Int32Constant(imm))));
715        Stream s = m.Build();
716
717        ASSERT_EQ(1U, s.size());
718        EXPECT_EQ(kArm64Sub32, s[0]->arch_opcode());
719        ASSERT_EQ(3U, s[0]->InputCount());
720        EXPECT_TRUE(s[0]->InputAt(0)->IsImmediate());
721        EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(0)));
722        EXPECT_EQ(shift.mode, s[0]->addressing_mode());
723        EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2)));
724        EXPECT_EQ(1U, s[0]->OutputCount());
725      }
726    }
727    {
728      // Test 64-bit operations. Ignore ROR shifts, as subtract does not
729      // support them.
730      if ((shift.mi.machine_type != MachineType::Int64()) ||
731          (shift.mi.arch_opcode == kArm64Ror32) ||
732          (shift.mi.arch_opcode == kArm64Ror))
733        continue;
734
735      TRACED_FORRANGE(int, imm, -32, 127) {
736        StreamBuilder m(this, MachineType::Int64(), MachineType::Int64(),
737                        MachineType::Int64());
738        m.Return(m.Int64Sub(
739            m.Int64Constant(0),
740            (m.*shift.mi.constructor)(m.Parameter(1), m.Int64Constant(imm))));
741        Stream s = m.Build();
742
743        ASSERT_EQ(1U, s.size());
744        EXPECT_EQ(kArm64Sub, s[0]->arch_opcode());
745        ASSERT_EQ(3U, s[0]->InputCount());
746        EXPECT_TRUE(s[0]->InputAt(0)->IsImmediate());
747        EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(0)));
748        EXPECT_EQ(shift.mode, s[0]->addressing_mode());
749        EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2)));
750        EXPECT_EQ(1U, s[0]->OutputCount());
751      }
752    }
753  }
754}
755
756
757TEST_F(InstructionSelectorTest, AddNegImmediateOnLeft) {
758  {
759    // 32-bit add.
760    TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
761      if (imm == 0) continue;
762      StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
763      m.Return(m.Int32Add(m.Int32Constant(-imm), m.Parameter(0)));
764      Stream s = m.Build();
765
766      ASSERT_EQ(1U, s.size());
767      EXPECT_EQ(kArm64Sub32, s[0]->arch_opcode());
768      ASSERT_EQ(2U, s[0]->InputCount());
769      ASSERT_TRUE(s[0]->InputAt(1)->IsImmediate());
770      EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
771      EXPECT_EQ(1U, s[0]->OutputCount());
772    }
773  }
774  {
775    // 64-bit add.
776    TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
777      if (imm == 0) continue;
778      StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
779      m.Return(m.Int64Add(m.Int64Constant(-imm), m.Parameter(0)));
780      Stream s = m.Build();
781
782      ASSERT_EQ(1U, s.size());
783      EXPECT_EQ(kArm64Sub, s[0]->arch_opcode());
784      ASSERT_EQ(2U, s[0]->InputCount());
785      ASSERT_TRUE(s[0]->InputAt(1)->IsImmediate());
786      EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(1)));
787      EXPECT_EQ(1U, s[0]->OutputCount());
788    }
789  }
790}
791
792
793TEST_F(InstructionSelectorTest, AddShiftByImmediateOnLeft) {
794  // 32-bit add.
795  TRACED_FOREACH(Shift, shift, kShiftInstructions) {
796    // Only test relevant shifted operands.
797    if (shift.mi.machine_type != MachineType::Int32()) continue;
798    if (shift.mi.arch_opcode == kArm64Ror32) continue;
799
800    // The available shift operand range is `0 <= imm < 32`, but we also test
801    // that immediates outside this range are handled properly (modulo-32).
802    TRACED_FORRANGE(int, imm, -32, 63) {
803      StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
804                      MachineType::Int32());
805      m.Return((m.Int32Add)(
806          (m.*shift.mi.constructor)(m.Parameter(1), m.Int32Constant(imm)),
807          m.Parameter(0)));
808      Stream s = m.Build();
809      ASSERT_EQ(1U, s.size());
810      EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
811      EXPECT_EQ(shift.mode, s[0]->addressing_mode());
812      EXPECT_EQ(3U, s[0]->InputCount());
813      EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(2)));
814      EXPECT_EQ(1U, s[0]->OutputCount());
815    }
816  }
817
818  // 64-bit add.
819  TRACED_FOREACH(Shift, shift, kShiftInstructions) {
820    // Only test relevant shifted operands.
821    if (shift.mi.machine_type != MachineType::Int64()) continue;
822    if (shift.mi.arch_opcode == kArm64Ror) continue;
823
824    // The available shift operand range is `0 <= imm < 64`, but we also test
825    // that immediates outside this range are handled properly (modulo-64).
826    TRACED_FORRANGE(int, imm, -64, 127) {
827      StreamBuilder m(this, MachineType::Int64(), MachineType::Int64(),
828                      MachineType::Int64());
829      m.Return((m.Int64Add)(
830          (m.*shift.mi.constructor)(m.Parameter(1), m.Int64Constant(imm)),
831          m.Parameter(0)));
832      Stream s = m.Build();
833      ASSERT_EQ(1U, s.size());
834      EXPECT_EQ(kArm64Add, s[0]->arch_opcode());
835      EXPECT_EQ(shift.mode, s[0]->addressing_mode());
836      EXPECT_EQ(3U, s[0]->InputCount());
837      EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(2)));
838      EXPECT_EQ(1U, s[0]->OutputCount());
839    }
840  }
841}
842
843
844TEST_F(InstructionSelectorTest, AddUnsignedExtendByteOnLeft) {
845  {
846    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
847                    MachineType::Int32());
848    m.Return(m.Int32Add(m.Word32And(m.Parameter(0), m.Int32Constant(0xff)),
849                        m.Parameter(1)));
850    Stream s = m.Build();
851    ASSERT_EQ(1U, s.size());
852    EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
853    EXPECT_EQ(kMode_Operand2_R_UXTB, s[0]->addressing_mode());
854    ASSERT_EQ(2U, s[0]->InputCount());
855    ASSERT_EQ(1U, s[0]->OutputCount());
856  }
857  {
858    StreamBuilder m(this, MachineType::Int64(), MachineType::Int32(),
859                    MachineType::Int64());
860    m.Return(m.Int64Add(m.Word32And(m.Parameter(0), m.Int32Constant(0xff)),
861                        m.Parameter(1)));
862    Stream s = m.Build();
863    ASSERT_EQ(1U, s.size());
864    EXPECT_EQ(kArm64Add, s[0]->arch_opcode());
865    EXPECT_EQ(kMode_Operand2_R_UXTB, s[0]->addressing_mode());
866    ASSERT_EQ(2U, s[0]->InputCount());
867    ASSERT_EQ(1U, s[0]->OutputCount());
868  }
869}
870
871
872TEST_F(InstructionSelectorTest, AddUnsignedExtendHalfwordOnLeft) {
873  {
874    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
875                    MachineType::Int32());
876    m.Return(m.Int32Add(m.Word32And(m.Parameter(0), m.Int32Constant(0xffff)),
877                        m.Parameter(1)));
878    Stream s = m.Build();
879    ASSERT_EQ(1U, s.size());
880    EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
881    EXPECT_EQ(kMode_Operand2_R_UXTH, s[0]->addressing_mode());
882    ASSERT_EQ(2U, s[0]->InputCount());
883    ASSERT_EQ(1U, s[0]->OutputCount());
884  }
885  {
886    StreamBuilder m(this, MachineType::Int64(), MachineType::Int32(),
887                    MachineType::Int64());
888    m.Return(m.Int64Add(m.Word32And(m.Parameter(0), m.Int32Constant(0xffff)),
889                        m.Parameter(1)));
890    Stream s = m.Build();
891    ASSERT_EQ(1U, s.size());
892    EXPECT_EQ(kArm64Add, s[0]->arch_opcode());
893    EXPECT_EQ(kMode_Operand2_R_UXTH, s[0]->addressing_mode());
894    ASSERT_EQ(2U, s[0]->InputCount());
895    ASSERT_EQ(1U, s[0]->OutputCount());
896  }
897}
898
899
900TEST_F(InstructionSelectorTest, AddSignedExtendByteOnLeft) {
901  {
902    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
903                    MachineType::Int32());
904    m.Return(
905        m.Int32Add(m.Word32Sar(m.Word32Shl(m.Parameter(0), m.Int32Constant(24)),
906                               m.Int32Constant(24)),
907                   m.Parameter(1)));
908    Stream s = m.Build();
909    ASSERT_EQ(1U, s.size());
910    EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
911    EXPECT_EQ(kMode_Operand2_R_SXTB, s[0]->addressing_mode());
912    ASSERT_EQ(2U, s[0]->InputCount());
913    ASSERT_EQ(1U, s[0]->OutputCount());
914  }
915  {
916    StreamBuilder m(this, MachineType::Int64(), MachineType::Int32(),
917                    MachineType::Int64());
918    m.Return(
919        m.Int64Add(m.Word32Sar(m.Word32Shl(m.Parameter(0), m.Int32Constant(24)),
920                               m.Int32Constant(24)),
921                   m.Parameter(1)));
922    Stream s = m.Build();
923    ASSERT_EQ(1U, s.size());
924    EXPECT_EQ(kArm64Add, s[0]->arch_opcode());
925    EXPECT_EQ(kMode_Operand2_R_SXTB, s[0]->addressing_mode());
926    ASSERT_EQ(2U, s[0]->InputCount());
927    ASSERT_EQ(1U, s[0]->OutputCount());
928  }
929}
930
931
932TEST_F(InstructionSelectorTest, AddSignedExtendHalfwordOnLeft) {
933  {
934    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
935                    MachineType::Int32());
936    m.Return(
937        m.Int32Add(m.Word32Sar(m.Word32Shl(m.Parameter(0), m.Int32Constant(16)),
938                               m.Int32Constant(16)),
939                   m.Parameter(1)));
940    Stream s = m.Build();
941    ASSERT_EQ(1U, s.size());
942    EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
943    EXPECT_EQ(kMode_Operand2_R_SXTH, s[0]->addressing_mode());
944    ASSERT_EQ(2U, s[0]->InputCount());
945    ASSERT_EQ(1U, s[0]->OutputCount());
946  }
947  {
948    StreamBuilder m(this, MachineType::Int64(), MachineType::Int32(),
949                    MachineType::Int64());
950    m.Return(
951        m.Int64Add(m.Word32Sar(m.Word32Shl(m.Parameter(0), m.Int32Constant(16)),
952                               m.Int32Constant(16)),
953                   m.Parameter(1)));
954    Stream s = m.Build();
955    ASSERT_EQ(1U, s.size());
956    EXPECT_EQ(kArm64Add, s[0]->arch_opcode());
957    EXPECT_EQ(kMode_Operand2_R_SXTH, s[0]->addressing_mode());
958    ASSERT_EQ(2U, s[0]->InputCount());
959    ASSERT_EQ(1U, s[0]->OutputCount());
960  }
961}
962
963
964// -----------------------------------------------------------------------------
965// Data processing controlled branches.
966
967
968typedef InstructionSelectorTestWithParam<MachInst2>
969    InstructionSelectorDPFlagSetTest;
970
971
972TEST_P(InstructionSelectorDPFlagSetTest, BranchWithParameters) {
973  const MachInst2 dpi = GetParam();
974  const MachineType type = dpi.machine_type;
975  StreamBuilder m(this, type, type, type);
976  RawMachineLabel a, b;
977  m.Branch((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)), &a, &b);
978  m.Bind(&a);
979  m.Return(m.Int32Constant(1));
980  m.Bind(&b);
981  m.Return(m.Int32Constant(0));
982  Stream s = m.Build();
983  ASSERT_EQ(1U, s.size());
984  EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
985  EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
986  EXPECT_EQ(kNotEqual, s[0]->flags_condition());
987}
988
989
990INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
991                        InstructionSelectorDPFlagSetTest,
992                        ::testing::ValuesIn(kDPFlagSetInstructions));
993
994
995TEST_F(InstructionSelectorTest, Word32AndBranchWithImmediateOnRight) {
996  TRACED_FOREACH(int32_t, imm, kLogical32Immediates) {
997    // Skip the cases where the instruction selector would use tbz/tbnz.
998    if (base::bits::CountPopulation32(imm) == 1) continue;
999
1000    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
1001    RawMachineLabel a, b;
1002    m.Branch(m.Word32And(m.Parameter(0), m.Int32Constant(imm)), &a, &b);
1003    m.Bind(&a);
1004    m.Return(m.Int32Constant(1));
1005    m.Bind(&b);
1006    m.Return(m.Int32Constant(0));
1007    Stream s = m.Build();
1008    ASSERT_EQ(1U, s.size());
1009    EXPECT_EQ(kArm64Tst32, s[0]->arch_opcode());
1010    EXPECT_EQ(4U, s[0]->InputCount());
1011    EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
1012    EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
1013    EXPECT_EQ(kNotEqual, s[0]->flags_condition());
1014  }
1015}
1016
1017
1018TEST_F(InstructionSelectorTest, Word64AndBranchWithImmediateOnRight) {
1019  TRACED_FOREACH(int64_t, imm, kLogical64Immediates) {
1020    // Skip the cases where the instruction selector would use tbz/tbnz.
1021    if (base::bits::CountPopulation64(imm) == 1) continue;
1022
1023    StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
1024    RawMachineLabel a, b;
1025    m.Branch(m.Word64And(m.Parameter(0), m.Int64Constant(imm)), &a, &b);
1026    m.Bind(&a);
1027    m.Return(m.Int32Constant(1));
1028    m.Bind(&b);
1029    m.Return(m.Int32Constant(0));
1030    Stream s = m.Build();
1031    ASSERT_EQ(1U, s.size());
1032    EXPECT_EQ(kArm64Tst, s[0]->arch_opcode());
1033    EXPECT_EQ(4U, s[0]->InputCount());
1034    EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
1035    EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
1036    EXPECT_EQ(kNotEqual, s[0]->flags_condition());
1037  }
1038}
1039
1040
1041TEST_F(InstructionSelectorTest, AddBranchWithImmediateOnRight) {
1042  TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
1043    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
1044    RawMachineLabel a, b;
1045    m.Branch(m.Int32Add(m.Parameter(0), m.Int32Constant(imm)), &a, &b);
1046    m.Bind(&a);
1047    m.Return(m.Int32Constant(1));
1048    m.Bind(&b);
1049    m.Return(m.Int32Constant(0));
1050    Stream s = m.Build();
1051    ASSERT_EQ(1U, s.size());
1052    EXPECT_EQ(kArm64Cmn32, s[0]->arch_opcode());
1053    EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
1054    EXPECT_EQ(kNotEqual, s[0]->flags_condition());
1055  }
1056}
1057
1058
1059TEST_F(InstructionSelectorTest, SubBranchWithImmediateOnRight) {
1060  TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
1061    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
1062    RawMachineLabel a, b;
1063    m.Branch(m.Int32Sub(m.Parameter(0), m.Int32Constant(imm)), &a, &b);
1064    m.Bind(&a);
1065    m.Return(m.Int32Constant(1));
1066    m.Bind(&b);
1067    m.Return(m.Int32Constant(0));
1068    Stream s = m.Build();
1069    ASSERT_EQ(1U, s.size());
1070    EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode());
1071    EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
1072    EXPECT_EQ(kNotEqual, s[0]->flags_condition());
1073  }
1074}
1075
1076
1077TEST_F(InstructionSelectorTest, Word32AndBranchWithImmediateOnLeft) {
1078  TRACED_FOREACH(int32_t, imm, kLogical32Immediates) {
1079    // Skip the cases where the instruction selector would use tbz/tbnz.
1080    if (base::bits::CountPopulation32(imm) == 1) continue;
1081
1082    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
1083    RawMachineLabel a, b;
1084    m.Branch(m.Word32And(m.Int32Constant(imm), m.Parameter(0)), &a, &b);
1085    m.Bind(&a);
1086    m.Return(m.Int32Constant(1));
1087    m.Bind(&b);
1088    m.Return(m.Int32Constant(0));
1089    Stream s = m.Build();
1090    ASSERT_EQ(1U, s.size());
1091    EXPECT_EQ(kArm64Tst32, s[0]->arch_opcode());
1092    EXPECT_EQ(4U, s[0]->InputCount());
1093    EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
1094    ASSERT_LE(1U, s[0]->InputCount());
1095    EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
1096    EXPECT_EQ(kNotEqual, s[0]->flags_condition());
1097  }
1098}
1099
1100
1101TEST_F(InstructionSelectorTest, Word64AndBranchWithImmediateOnLeft) {
1102  TRACED_FOREACH(int64_t, imm, kLogical64Immediates) {
1103    // Skip the cases where the instruction selector would use tbz/tbnz.
1104    if (base::bits::CountPopulation64(imm) == 1) continue;
1105
1106    StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
1107    RawMachineLabel a, b;
1108    m.Branch(m.Word64And(m.Int64Constant(imm), m.Parameter(0)), &a, &b);
1109    m.Bind(&a);
1110    m.Return(m.Int32Constant(1));
1111    m.Bind(&b);
1112    m.Return(m.Int32Constant(0));
1113    Stream s = m.Build();
1114    ASSERT_EQ(1U, s.size());
1115    EXPECT_EQ(kArm64Tst, s[0]->arch_opcode());
1116    EXPECT_EQ(4U, s[0]->InputCount());
1117    EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
1118    ASSERT_LE(1U, s[0]->InputCount());
1119    EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
1120    EXPECT_EQ(kNotEqual, s[0]->flags_condition());
1121  }
1122}
1123
1124
1125TEST_F(InstructionSelectorTest, AddBranchWithImmediateOnLeft) {
1126  TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
1127    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
1128    RawMachineLabel a, b;
1129    m.Branch(m.Int32Add(m.Int32Constant(imm), m.Parameter(0)), &a, &b);
1130    m.Bind(&a);
1131    m.Return(m.Int32Constant(1));
1132    m.Bind(&b);
1133    m.Return(m.Int32Constant(0));
1134    Stream s = m.Build();
1135    ASSERT_EQ(1U, s.size());
1136    EXPECT_EQ(kArm64Cmn32, s[0]->arch_opcode());
1137    ASSERT_LE(1U, s[0]->InputCount());
1138    EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
1139    EXPECT_EQ(kNotEqual, s[0]->flags_condition());
1140  }
1141}
1142
1143
1144TEST_F(InstructionSelectorTest, Word32AndBranchWithOneBitMaskOnRight) {
1145  TRACED_FORRANGE(int, bit, 0, 31) {
1146    uint32_t mask = 1 << bit;
1147    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
1148    RawMachineLabel a, b;
1149    m.Branch(m.Word32And(m.Parameter(0), m.Int32Constant(mask)), &a, &b);
1150    m.Bind(&a);
1151    m.Return(m.Int32Constant(1));
1152    m.Bind(&b);
1153    m.Return(m.Int32Constant(0));
1154    Stream s = m.Build();
1155    ASSERT_EQ(1U, s.size());
1156    EXPECT_EQ(kArm64TestAndBranch32, s[0]->arch_opcode());
1157    EXPECT_EQ(kNotEqual, s[0]->flags_condition());
1158    EXPECT_EQ(4U, s[0]->InputCount());
1159    EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
1160    EXPECT_EQ(bit, s.ToInt32(s[0]->InputAt(1)));
1161  }
1162
1163  TRACED_FORRANGE(int, bit, 0, 31) {
1164    uint32_t mask = 1 << bit;
1165    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
1166    RawMachineLabel a, b;
1167    m.Branch(
1168        m.Word32BinaryNot(m.Word32And(m.Parameter(0), m.Int32Constant(mask))),
1169        &a, &b);
1170    m.Bind(&a);
1171    m.Return(m.Int32Constant(1));
1172    m.Bind(&b);
1173    m.Return(m.Int32Constant(0));
1174    Stream s = m.Build();
1175    ASSERT_EQ(1U, s.size());
1176    EXPECT_EQ(kArm64TestAndBranch32, s[0]->arch_opcode());
1177    EXPECT_EQ(kEqual, s[0]->flags_condition());
1178    EXPECT_EQ(4U, s[0]->InputCount());
1179    EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
1180    EXPECT_EQ(bit, s.ToInt32(s[0]->InputAt(1)));
1181  }
1182}
1183
1184TEST_F(InstructionSelectorTest, Word32AndBranchWithOneBitMaskOnLeft) {
1185  TRACED_FORRANGE(int, bit, 0, 31) {
1186    uint32_t mask = 1 << bit;
1187    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
1188    RawMachineLabel a, b;
1189    m.Branch(m.Word32And(m.Int32Constant(mask), m.Parameter(0)), &a, &b);
1190    m.Bind(&a);
1191    m.Return(m.Int32Constant(1));
1192    m.Bind(&b);
1193    m.Return(m.Int32Constant(0));
1194    Stream s = m.Build();
1195    ASSERT_EQ(1U, s.size());
1196    EXPECT_EQ(kArm64TestAndBranch32, s[0]->arch_opcode());
1197    EXPECT_EQ(kNotEqual, s[0]->flags_condition());
1198    EXPECT_EQ(4U, s[0]->InputCount());
1199    EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
1200    EXPECT_EQ(bit, s.ToInt32(s[0]->InputAt(1)));
1201  }
1202
1203  TRACED_FORRANGE(int, bit, 0, 31) {
1204    uint32_t mask = 1 << bit;
1205    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
1206    RawMachineLabel a, b;
1207    m.Branch(
1208        m.Word32BinaryNot(m.Word32And(m.Int32Constant(mask), m.Parameter(0))),
1209        &a, &b);
1210    m.Bind(&a);
1211    m.Return(m.Int32Constant(1));
1212    m.Bind(&b);
1213    m.Return(m.Int32Constant(0));
1214    Stream s = m.Build();
1215    ASSERT_EQ(1U, s.size());
1216    EXPECT_EQ(kArm64TestAndBranch32, s[0]->arch_opcode());
1217    EXPECT_EQ(kEqual, s[0]->flags_condition());
1218    EXPECT_EQ(4U, s[0]->InputCount());
1219    EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
1220    EXPECT_EQ(bit, s.ToInt32(s[0]->InputAt(1)));
1221  }
1222}
1223
1224
1225TEST_F(InstructionSelectorTest, Word64AndBranchWithOneBitMaskOnRight) {
1226  TRACED_FORRANGE(int, bit, 0, 63) {
1227    uint64_t mask = 1L << bit;
1228    StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
1229    RawMachineLabel a, b;
1230    m.Branch(m.Word64And(m.Parameter(0), m.Int64Constant(mask)), &a, &b);
1231    m.Bind(&a);
1232    m.Return(m.Int32Constant(1));
1233    m.Bind(&b);
1234    m.Return(m.Int32Constant(0));
1235    Stream s = m.Build();
1236    ASSERT_EQ(1U, s.size());
1237    EXPECT_EQ(kArm64TestAndBranch, s[0]->arch_opcode());
1238    EXPECT_EQ(kNotEqual, s[0]->flags_condition());
1239    EXPECT_EQ(4U, s[0]->InputCount());
1240    EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
1241    EXPECT_EQ(bit, s.ToInt64(s[0]->InputAt(1)));
1242  }
1243}
1244
1245
1246TEST_F(InstructionSelectorTest, Word64AndBranchWithOneBitMaskOnLeft) {
1247  TRACED_FORRANGE(int, bit, 0, 63) {
1248    uint64_t mask = 1L << bit;
1249    StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
1250    RawMachineLabel a, b;
1251    m.Branch(m.Word64And(m.Int64Constant(mask), m.Parameter(0)), &a, &b);
1252    m.Bind(&a);
1253    m.Return(m.Int32Constant(1));
1254    m.Bind(&b);
1255    m.Return(m.Int32Constant(0));
1256    Stream s = m.Build();
1257    ASSERT_EQ(1U, s.size());
1258    EXPECT_EQ(kArm64TestAndBranch, s[0]->arch_opcode());
1259    EXPECT_EQ(kNotEqual, s[0]->flags_condition());
1260    EXPECT_EQ(4U, s[0]->InputCount());
1261    EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
1262    EXPECT_EQ(bit, s.ToInt64(s[0]->InputAt(1)));
1263  }
1264}
1265
1266TEST_F(InstructionSelectorTest, Word32EqualZeroAndBranchWithOneBitMask) {
1267  TRACED_FORRANGE(int, bit, 0, 31) {
1268    uint32_t mask = 1 << bit;
1269    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
1270    RawMachineLabel a, b;
1271    m.Branch(m.Word32Equal(m.Word32And(m.Int32Constant(mask), m.Parameter(0)),
1272                           m.Int32Constant(0)),
1273             &a, &b);
1274    m.Bind(&a);
1275    m.Return(m.Int32Constant(1));
1276    m.Bind(&b);
1277    m.Return(m.Int32Constant(0));
1278    Stream s = m.Build();
1279    ASSERT_EQ(1U, s.size());
1280    EXPECT_EQ(kArm64TestAndBranch32, s[0]->arch_opcode());
1281    EXPECT_EQ(kEqual, s[0]->flags_condition());
1282    EXPECT_EQ(4U, s[0]->InputCount());
1283    EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
1284    EXPECT_EQ(bit, s.ToInt32(s[0]->InputAt(1)));
1285  }
1286
1287  TRACED_FORRANGE(int, bit, 0, 31) {
1288    uint32_t mask = 1 << bit;
1289    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
1290    RawMachineLabel a, b;
1291    m.Branch(
1292        m.Word32NotEqual(m.Word32And(m.Int32Constant(mask), m.Parameter(0)),
1293                         m.Int32Constant(0)),
1294        &a, &b);
1295    m.Bind(&a);
1296    m.Return(m.Int32Constant(1));
1297    m.Bind(&b);
1298    m.Return(m.Int32Constant(0));
1299    Stream s = m.Build();
1300    ASSERT_EQ(1U, s.size());
1301    EXPECT_EQ(kArm64TestAndBranch32, s[0]->arch_opcode());
1302    EXPECT_EQ(kNotEqual, s[0]->flags_condition());
1303    EXPECT_EQ(4U, s[0]->InputCount());
1304    EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
1305    EXPECT_EQ(bit, s.ToInt32(s[0]->InputAt(1)));
1306  }
1307}
1308
1309TEST_F(InstructionSelectorTest, Word64EqualZeroAndBranchWithOneBitMask) {
1310  TRACED_FORRANGE(int, bit, 0, 63) {
1311    uint64_t mask = V8_UINT64_C(1) << bit;
1312    StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
1313    RawMachineLabel a, b;
1314    m.Branch(m.Word64Equal(m.Word64And(m.Int64Constant(mask), m.Parameter(0)),
1315                           m.Int64Constant(0)),
1316             &a, &b);
1317    m.Bind(&a);
1318    m.Return(m.Int64Constant(1));
1319    m.Bind(&b);
1320    m.Return(m.Int64Constant(0));
1321    Stream s = m.Build();
1322    ASSERT_EQ(1U, s.size());
1323    EXPECT_EQ(kArm64TestAndBranch, s[0]->arch_opcode());
1324    EXPECT_EQ(kEqual, s[0]->flags_condition());
1325    EXPECT_EQ(4U, s[0]->InputCount());
1326    EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
1327    EXPECT_EQ(bit, s.ToInt64(s[0]->InputAt(1)));
1328  }
1329
1330  TRACED_FORRANGE(int, bit, 0, 63) {
1331    uint64_t mask = V8_UINT64_C(1) << bit;
1332    StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
1333    RawMachineLabel a, b;
1334    m.Branch(
1335        m.Word64NotEqual(m.Word64And(m.Int64Constant(mask), m.Parameter(0)),
1336                         m.Int64Constant(0)),
1337        &a, &b);
1338    m.Bind(&a);
1339    m.Return(m.Int64Constant(1));
1340    m.Bind(&b);
1341    m.Return(m.Int64Constant(0));
1342    Stream s = m.Build();
1343    ASSERT_EQ(1U, s.size());
1344    EXPECT_EQ(kArm64TestAndBranch, s[0]->arch_opcode());
1345    EXPECT_EQ(kNotEqual, s[0]->flags_condition());
1346    EXPECT_EQ(4U, s[0]->InputCount());
1347    EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
1348    EXPECT_EQ(bit, s.ToInt64(s[0]->InputAt(1)));
1349  }
1350}
1351
1352TEST_F(InstructionSelectorTest, CompareAgainstZeroAndBranch) {
1353  {
1354    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
1355    RawMachineLabel a, b;
1356    Node* p0 = m.Parameter(0);
1357    m.Branch(p0, &a, &b);
1358    m.Bind(&a);
1359    m.Return(m.Int32Constant(1));
1360    m.Bind(&b);
1361    m.Return(m.Int32Constant(0));
1362    Stream s = m.Build();
1363    ASSERT_EQ(1U, s.size());
1364    EXPECT_EQ(kArm64CompareAndBranch32, s[0]->arch_opcode());
1365    EXPECT_EQ(kNotEqual, s[0]->flags_condition());
1366    EXPECT_EQ(3U, s[0]->InputCount());
1367    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1368  }
1369
1370  {
1371    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
1372    RawMachineLabel a, b;
1373    Node* p0 = m.Parameter(0);
1374    m.Branch(m.Word32BinaryNot(p0), &a, &b);
1375    m.Bind(&a);
1376    m.Return(m.Int32Constant(1));
1377    m.Bind(&b);
1378    m.Return(m.Int32Constant(0));
1379    Stream s = m.Build();
1380    ASSERT_EQ(1U, s.size());
1381    EXPECT_EQ(kArm64CompareAndBranch32, s[0]->arch_opcode());
1382    EXPECT_EQ(kEqual, s[0]->flags_condition());
1383    EXPECT_EQ(3U, s[0]->InputCount());
1384    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1385  }
1386}
1387
1388TEST_F(InstructionSelectorTest, EqualZeroAndBranch) {
1389  {
1390    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
1391    RawMachineLabel a, b;
1392    Node* p0 = m.Parameter(0);
1393    m.Branch(m.Word32Equal(p0, m.Int32Constant(0)), &a, &b);
1394    m.Bind(&a);
1395    m.Return(m.Int32Constant(1));
1396    m.Bind(&b);
1397    m.Return(m.Int32Constant(0));
1398    Stream s = m.Build();
1399    ASSERT_EQ(1U, s.size());
1400    EXPECT_EQ(kArm64CompareAndBranch32, s[0]->arch_opcode());
1401    EXPECT_EQ(kEqual, s[0]->flags_condition());
1402    EXPECT_EQ(3U, s[0]->InputCount());
1403    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1404  }
1405
1406  {
1407    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
1408    RawMachineLabel a, b;
1409    Node* p0 = m.Parameter(0);
1410    m.Branch(m.Word32NotEqual(p0, m.Int32Constant(0)), &a, &b);
1411    m.Bind(&a);
1412    m.Return(m.Int32Constant(1));
1413    m.Bind(&b);
1414    m.Return(m.Int32Constant(0));
1415    Stream s = m.Build();
1416    ASSERT_EQ(1U, s.size());
1417    EXPECT_EQ(kArm64CompareAndBranch32, s[0]->arch_opcode());
1418    EXPECT_EQ(kNotEqual, s[0]->flags_condition());
1419    EXPECT_EQ(3U, s[0]->InputCount());
1420    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1421  }
1422
1423  {
1424    StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
1425    RawMachineLabel a, b;
1426    Node* p0 = m.Parameter(0);
1427    m.Branch(m.Word64Equal(p0, m.Int64Constant(0)), &a, &b);
1428    m.Bind(&a);
1429    m.Return(m.Int64Constant(1));
1430    m.Bind(&b);
1431    m.Return(m.Int64Constant(0));
1432    Stream s = m.Build();
1433    ASSERT_EQ(1U, s.size());
1434    EXPECT_EQ(kArm64CompareAndBranch, s[0]->arch_opcode());
1435    EXPECT_EQ(kEqual, s[0]->flags_condition());
1436    EXPECT_EQ(3U, s[0]->InputCount());
1437    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1438  }
1439
1440  {
1441    StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
1442    RawMachineLabel a, b;
1443    Node* p0 = m.Parameter(0);
1444    m.Branch(m.Word64NotEqual(p0, m.Int64Constant(0)), &a, &b);
1445    m.Bind(&a);
1446    m.Return(m.Int64Constant(1));
1447    m.Bind(&b);
1448    m.Return(m.Int64Constant(0));
1449    Stream s = m.Build();
1450    ASSERT_EQ(1U, s.size());
1451    EXPECT_EQ(kArm64CompareAndBranch, s[0]->arch_opcode());
1452    EXPECT_EQ(kNotEqual, s[0]->flags_condition());
1453    EXPECT_EQ(3U, s[0]->InputCount());
1454    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1455  }
1456}
1457
1458// -----------------------------------------------------------------------------
1459// Add and subtract instructions with overflow.
1460
1461
1462typedef InstructionSelectorTestWithParam<MachInst2>
1463    InstructionSelectorOvfAddSubTest;
1464
1465
1466TEST_P(InstructionSelectorOvfAddSubTest, OvfParameter) {
1467  const MachInst2 dpi = GetParam();
1468  const MachineType type = dpi.machine_type;
1469  StreamBuilder m(this, type, type, type);
1470  m.Return(
1471      m.Projection(1, (m.*dpi.constructor)(m.Parameter(0), m.Parameter(1))));
1472  Stream s = m.Build();
1473  ASSERT_EQ(1U, s.size());
1474  EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
1475  EXPECT_EQ(2U, s[0]->InputCount());
1476  EXPECT_LE(1U, s[0]->OutputCount());
1477  EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1478  EXPECT_EQ(kOverflow, s[0]->flags_condition());
1479}
1480
1481
1482TEST_P(InstructionSelectorOvfAddSubTest, OvfImmediateOnRight) {
1483  const MachInst2 dpi = GetParam();
1484  const MachineType type = dpi.machine_type;
1485  TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
1486    StreamBuilder m(this, type, type);
1487    m.Return(m.Projection(
1488        1, (m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm))));
1489    Stream s = m.Build();
1490    ASSERT_EQ(1U, s.size());
1491    EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
1492    ASSERT_EQ(2U, s[0]->InputCount());
1493    EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
1494    EXPECT_LE(1U, s[0]->OutputCount());
1495    EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1496    EXPECT_EQ(kOverflow, s[0]->flags_condition());
1497  }
1498}
1499
1500
1501TEST_P(InstructionSelectorOvfAddSubTest, ValParameter) {
1502  const MachInst2 dpi = GetParam();
1503  const MachineType type = dpi.machine_type;
1504  StreamBuilder m(this, type, type, type);
1505  m.Return(
1506      m.Projection(0, (m.*dpi.constructor)(m.Parameter(0), m.Parameter(1))));
1507  Stream s = m.Build();
1508  ASSERT_EQ(1U, s.size());
1509  EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
1510  EXPECT_EQ(2U, s[0]->InputCount());
1511  EXPECT_LE(1U, s[0]->OutputCount());
1512  EXPECT_EQ(kFlags_none, s[0]->flags_mode());
1513}
1514
1515
1516TEST_P(InstructionSelectorOvfAddSubTest, ValImmediateOnRight) {
1517  const MachInst2 dpi = GetParam();
1518  const MachineType type = dpi.machine_type;
1519  TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
1520    StreamBuilder m(this, type, type);
1521    m.Return(m.Projection(
1522        0, (m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm))));
1523    Stream s = m.Build();
1524    ASSERT_EQ(1U, s.size());
1525    EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
1526    ASSERT_EQ(2U, s[0]->InputCount());
1527    EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
1528    EXPECT_LE(1U, s[0]->OutputCount());
1529    EXPECT_EQ(kFlags_none, s[0]->flags_mode());
1530  }
1531}
1532
1533
1534TEST_P(InstructionSelectorOvfAddSubTest, BothParameter) {
1535  const MachInst2 dpi = GetParam();
1536  const MachineType type = dpi.machine_type;
1537  StreamBuilder m(this, type, type, type);
1538  Node* n = (m.*dpi.constructor)(m.Parameter(0), m.Parameter(1));
1539  m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n)));
1540  Stream s = m.Build();
1541  ASSERT_LE(1U, s.size());
1542  EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
1543  EXPECT_EQ(2U, s[0]->InputCount());
1544  EXPECT_EQ(2U, s[0]->OutputCount());
1545  EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1546  EXPECT_EQ(kOverflow, s[0]->flags_condition());
1547}
1548
1549
1550TEST_P(InstructionSelectorOvfAddSubTest, BothImmediateOnRight) {
1551  const MachInst2 dpi = GetParam();
1552  const MachineType type = dpi.machine_type;
1553  TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
1554    StreamBuilder m(this, type, type);
1555    Node* n = (m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm));
1556    m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n)));
1557    Stream s = m.Build();
1558    ASSERT_LE(1U, s.size());
1559    EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
1560    ASSERT_EQ(2U, s[0]->InputCount());
1561    EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
1562    EXPECT_EQ(2U, s[0]->OutputCount());
1563    EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1564    EXPECT_EQ(kOverflow, s[0]->flags_condition());
1565  }
1566}
1567
1568
1569TEST_P(InstructionSelectorOvfAddSubTest, BranchWithParameters) {
1570  const MachInst2 dpi = GetParam();
1571  const MachineType type = dpi.machine_type;
1572  StreamBuilder m(this, type, type, type);
1573  RawMachineLabel a, b;
1574  Node* n = (m.*dpi.constructor)(m.Parameter(0), m.Parameter(1));
1575  m.Branch(m.Projection(1, n), &a, &b);
1576  m.Bind(&a);
1577  m.Return(m.Int32Constant(0));
1578  m.Bind(&b);
1579  m.Return(m.Projection(0, n));
1580  Stream s = m.Build();
1581  ASSERT_EQ(1U, s.size());
1582  EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
1583  EXPECT_EQ(4U, s[0]->InputCount());
1584  EXPECT_EQ(1U, s[0]->OutputCount());
1585  EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
1586  EXPECT_EQ(kOverflow, s[0]->flags_condition());
1587}
1588
1589
1590TEST_P(InstructionSelectorOvfAddSubTest, BranchWithImmediateOnRight) {
1591  const MachInst2 dpi = GetParam();
1592  const MachineType type = dpi.machine_type;
1593  TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
1594    StreamBuilder m(this, type, type);
1595    RawMachineLabel a, b;
1596    Node* n = (m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm));
1597    m.Branch(m.Projection(1, n), &a, &b);
1598    m.Bind(&a);
1599    m.Return(m.Int32Constant(0));
1600    m.Bind(&b);
1601    m.Return(m.Projection(0, n));
1602    Stream s = m.Build();
1603    ASSERT_EQ(1U, s.size());
1604    EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
1605    ASSERT_EQ(4U, s[0]->InputCount());
1606    EXPECT_EQ(1U, s[0]->OutputCount());
1607    EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
1608    EXPECT_EQ(kOverflow, s[0]->flags_condition());
1609  }
1610}
1611
1612TEST_P(InstructionSelectorOvfAddSubTest, RORShift) {
1613  // ADD and SUB do not support ROR shifts, make sure we do not try
1614  // to merge them into the ADD/SUB instruction.
1615  const MachInst2 dpi = GetParam();
1616  const MachineType type = dpi.machine_type;
1617  auto rotate = &RawMachineAssembler::Word64Ror;
1618  ArchOpcode rotate_opcode = kArm64Ror;
1619  if (type == MachineType::Int32()) {
1620    rotate = &RawMachineAssembler::Word32Ror;
1621    rotate_opcode = kArm64Ror32;
1622  }
1623  TRACED_FORRANGE(int32_t, imm, -32, 63) {
1624    StreamBuilder m(this, type, type, type);
1625    Node* const p0 = m.Parameter(0);
1626    Node* const p1 = m.Parameter(1);
1627    Node* r = (m.*rotate)(p1, m.Int32Constant(imm));
1628    m.Return((m.*dpi.constructor)(p0, r));
1629    Stream s = m.Build();
1630    ASSERT_EQ(2U, s.size());
1631    EXPECT_EQ(rotate_opcode, s[0]->arch_opcode());
1632    EXPECT_EQ(dpi.arch_opcode, s[1]->arch_opcode());
1633  }
1634}
1635
1636INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1637                        InstructionSelectorOvfAddSubTest,
1638                        ::testing::ValuesIn(kOvfAddSubInstructions));
1639
1640
1641TEST_F(InstructionSelectorTest, OvfFlagAddImmediateOnLeft) {
1642  TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
1643    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
1644    m.Return(m.Projection(
1645        1, m.Int32AddWithOverflow(m.Int32Constant(imm), m.Parameter(0))));
1646    Stream s = m.Build();
1647
1648    ASSERT_EQ(1U, s.size());
1649    EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
1650    EXPECT_EQ(2U, s[0]->InputCount());
1651    EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
1652    EXPECT_LE(1U, s[0]->OutputCount());
1653    EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1654    EXPECT_EQ(kOverflow, s[0]->flags_condition());
1655  }
1656}
1657
1658
1659TEST_F(InstructionSelectorTest, OvfValAddImmediateOnLeft) {
1660  TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
1661    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
1662    m.Return(m.Projection(
1663        0, m.Int32AddWithOverflow(m.Int32Constant(imm), m.Parameter(0))));
1664    Stream s = m.Build();
1665
1666    ASSERT_EQ(1U, s.size());
1667    EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
1668    ASSERT_EQ(2U, s[0]->InputCount());
1669    EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
1670    EXPECT_LE(1U, s[0]->OutputCount());
1671    EXPECT_EQ(kFlags_none, s[0]->flags_mode());
1672  }
1673}
1674
1675
1676TEST_F(InstructionSelectorTest, OvfBothAddImmediateOnLeft) {
1677  TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
1678    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
1679    Node* n = m.Int32AddWithOverflow(m.Int32Constant(imm), m.Parameter(0));
1680    m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n)));
1681    Stream s = m.Build();
1682
1683    ASSERT_LE(1U, s.size());
1684    EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
1685    ASSERT_EQ(2U, s[0]->InputCount());
1686    EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
1687    EXPECT_EQ(2U, s[0]->OutputCount());
1688    EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1689    EXPECT_EQ(kOverflow, s[0]->flags_condition());
1690  }
1691}
1692
1693
1694TEST_F(InstructionSelectorTest, OvfBranchWithImmediateOnLeft) {
1695  TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
1696    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
1697    RawMachineLabel a, b;
1698    Node* n = m.Int32AddWithOverflow(m.Int32Constant(imm), m.Parameter(0));
1699    m.Branch(m.Projection(1, n), &a, &b);
1700    m.Bind(&a);
1701    m.Return(m.Int32Constant(0));
1702    m.Bind(&b);
1703    m.Return(m.Projection(0, n));
1704    Stream s = m.Build();
1705
1706    ASSERT_EQ(1U, s.size());
1707    EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
1708    ASSERT_EQ(4U, s[0]->InputCount());
1709    EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
1710    EXPECT_EQ(1U, s[0]->OutputCount());
1711    EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
1712    EXPECT_EQ(kOverflow, s[0]->flags_condition());
1713  }
1714}
1715
1716
1717// -----------------------------------------------------------------------------
1718// Shift instructions.
1719
1720
1721typedef InstructionSelectorTestWithParam<Shift> InstructionSelectorShiftTest;
1722
1723
1724TEST_P(InstructionSelectorShiftTest, Parameter) {
1725  const Shift shift = GetParam();
1726  const MachineType type = shift.mi.machine_type;
1727  StreamBuilder m(this, type, type, type);
1728  m.Return((m.*shift.mi.constructor)(m.Parameter(0), m.Parameter(1)));
1729  Stream s = m.Build();
1730  ASSERT_EQ(1U, s.size());
1731  EXPECT_EQ(shift.mi.arch_opcode, s[0]->arch_opcode());
1732  EXPECT_EQ(2U, s[0]->InputCount());
1733  EXPECT_EQ(1U, s[0]->OutputCount());
1734}
1735
1736
1737TEST_P(InstructionSelectorShiftTest, Immediate) {
1738  const Shift shift = GetParam();
1739  const MachineType type = shift.mi.machine_type;
1740  TRACED_FORRANGE(int32_t, imm, 0,
1741                  ((1 << ElementSizeLog2Of(type.representation())) * 8) - 1) {
1742    StreamBuilder m(this, type, type);
1743    m.Return((m.*shift.mi.constructor)(m.Parameter(0), m.Int32Constant(imm)));
1744    Stream s = m.Build();
1745    ASSERT_EQ(1U, s.size());
1746    EXPECT_EQ(shift.mi.arch_opcode, s[0]->arch_opcode());
1747    EXPECT_EQ(2U, s[0]->InputCount());
1748    EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
1749    EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
1750    EXPECT_EQ(1U, s[0]->OutputCount());
1751  }
1752}
1753
1754
1755INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorShiftTest,
1756                        ::testing::ValuesIn(kShiftInstructions));
1757
1758
1759TEST_F(InstructionSelectorTest, Word64ShlWithChangeInt32ToInt64) {
1760  TRACED_FORRANGE(int64_t, x, 32, 63) {
1761    StreamBuilder m(this, MachineType::Int64(), MachineType::Int32());
1762    Node* const p0 = m.Parameter(0);
1763    Node* const n = m.Word64Shl(m.ChangeInt32ToInt64(p0), m.Int64Constant(x));
1764    m.Return(n);
1765    Stream s = m.Build();
1766    ASSERT_EQ(1U, s.size());
1767    EXPECT_EQ(kArm64Lsl, s[0]->arch_opcode());
1768    ASSERT_EQ(2U, s[0]->InputCount());
1769    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1770    EXPECT_EQ(x, s.ToInt64(s[0]->InputAt(1)));
1771    ASSERT_EQ(1U, s[0]->OutputCount());
1772    EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1773  }
1774}
1775
1776
1777TEST_F(InstructionSelectorTest, Word64ShlWithChangeUint32ToUint64) {
1778  TRACED_FORRANGE(int64_t, x, 32, 63) {
1779    StreamBuilder m(this, MachineType::Int64(), MachineType::Uint32());
1780    Node* const p0 = m.Parameter(0);
1781    Node* const n = m.Word64Shl(m.ChangeUint32ToUint64(p0), m.Int64Constant(x));
1782    m.Return(n);
1783    Stream s = m.Build();
1784    ASSERT_EQ(1U, s.size());
1785    EXPECT_EQ(kArm64Lsl, s[0]->arch_opcode());
1786    ASSERT_EQ(2U, s[0]->InputCount());
1787    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1788    EXPECT_EQ(x, s.ToInt64(s[0]->InputAt(1)));
1789    ASSERT_EQ(1U, s[0]->OutputCount());
1790    EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1791  }
1792}
1793
1794
1795TEST_F(InstructionSelectorTest, TruncateInt64ToInt32WithWord64Sar) {
1796  StreamBuilder m(this, MachineType::Int32(), MachineType::Int64());
1797  Node* const p = m.Parameter(0);
1798  Node* const t = m.TruncateInt64ToInt32(m.Word64Sar(p, m.Int64Constant(32)));
1799  m.Return(t);
1800  Stream s = m.Build();
1801  ASSERT_EQ(1U, s.size());
1802  EXPECT_EQ(kArm64Lsr, s[0]->arch_opcode());
1803  ASSERT_EQ(2U, s[0]->InputCount());
1804  EXPECT_EQ(s.ToVreg(p), s.ToVreg(s[0]->InputAt(0)));
1805  EXPECT_EQ(32, s.ToInt64(s[0]->InputAt(1)));
1806  ASSERT_EQ(1U, s[0]->OutputCount());
1807  EXPECT_EQ(s.ToVreg(t), s.ToVreg(s[0]->OutputAt(0)));
1808}
1809
1810
1811TEST_F(InstructionSelectorTest, TruncateInt64ToInt32WithWord64Shr) {
1812  TRACED_FORRANGE(int64_t, x, 32, 63) {
1813    StreamBuilder m(this, MachineType::Int32(), MachineType::Int64());
1814    Node* const p = m.Parameter(0);
1815    Node* const t = m.TruncateInt64ToInt32(m.Word64Shr(p, m.Int64Constant(x)));
1816    m.Return(t);
1817    Stream s = m.Build();
1818    ASSERT_EQ(1U, s.size());
1819    EXPECT_EQ(kArm64Lsr, s[0]->arch_opcode());
1820    ASSERT_EQ(2U, s[0]->InputCount());
1821    EXPECT_EQ(s.ToVreg(p), s.ToVreg(s[0]->InputAt(0)));
1822    EXPECT_EQ(x, s.ToInt64(s[0]->InputAt(1)));
1823    ASSERT_EQ(1U, s[0]->OutputCount());
1824    EXPECT_EQ(s.ToVreg(t), s.ToVreg(s[0]->OutputAt(0)));
1825  }
1826}
1827
1828
1829// -----------------------------------------------------------------------------
1830// Mul and Div instructions.
1831
1832
1833typedef InstructionSelectorTestWithParam<MachInst2>
1834    InstructionSelectorMulDivTest;
1835
1836
1837TEST_P(InstructionSelectorMulDivTest, Parameter) {
1838  const MachInst2 dpi = GetParam();
1839  const MachineType type = dpi.machine_type;
1840  StreamBuilder m(this, type, type, type);
1841  m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)));
1842  Stream s = m.Build();
1843  ASSERT_EQ(1U, s.size());
1844  EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
1845  EXPECT_EQ(2U, s[0]->InputCount());
1846  EXPECT_EQ(1U, s[0]->OutputCount());
1847}
1848
1849
1850INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorMulDivTest,
1851                        ::testing::ValuesIn(kMulDivInstructions));
1852
1853
1854namespace {
1855
1856struct MulDPInst {
1857  const char* mul_constructor_name;
1858  Node* (RawMachineAssembler::*mul_constructor)(Node*, Node*);
1859  Node* (RawMachineAssembler::*add_constructor)(Node*, Node*);
1860  Node* (RawMachineAssembler::*sub_constructor)(Node*, Node*);
1861  ArchOpcode add_arch_opcode;
1862  ArchOpcode sub_arch_opcode;
1863  ArchOpcode neg_arch_opcode;
1864  MachineType machine_type;
1865};
1866
1867
1868std::ostream& operator<<(std::ostream& os, const MulDPInst& inst) {
1869  return os << inst.mul_constructor_name;
1870}
1871
1872}  // namespace
1873
1874
1875static const MulDPInst kMulDPInstructions[] = {
1876    {"Int32Mul", &RawMachineAssembler::Int32Mul, &RawMachineAssembler::Int32Add,
1877     &RawMachineAssembler::Int32Sub, kArm64Madd32, kArm64Msub32, kArm64Mneg32,
1878     MachineType::Int32()},
1879    {"Int64Mul", &RawMachineAssembler::Int64Mul, &RawMachineAssembler::Int64Add,
1880     &RawMachineAssembler::Int64Sub, kArm64Madd, kArm64Msub, kArm64Mneg,
1881     MachineType::Int64()}};
1882
1883
1884typedef InstructionSelectorTestWithParam<MulDPInst>
1885    InstructionSelectorIntDPWithIntMulTest;
1886
1887
1888TEST_P(InstructionSelectorIntDPWithIntMulTest, AddWithMul) {
1889  const MulDPInst mdpi = GetParam();
1890  const MachineType type = mdpi.machine_type;
1891  {
1892    StreamBuilder m(this, type, type, type, type);
1893    Node* n = (m.*mdpi.mul_constructor)(m.Parameter(1), m.Parameter(2));
1894    m.Return((m.*mdpi.add_constructor)(m.Parameter(0), n));
1895    Stream s = m.Build();
1896    ASSERT_EQ(1U, s.size());
1897    EXPECT_EQ(mdpi.add_arch_opcode, s[0]->arch_opcode());
1898    EXPECT_EQ(3U, s[0]->InputCount());
1899    EXPECT_EQ(1U, s[0]->OutputCount());
1900  }
1901  {
1902    StreamBuilder m(this, type, type, type, type);
1903    Node* n = (m.*mdpi.mul_constructor)(m.Parameter(0), m.Parameter(1));
1904    m.Return((m.*mdpi.add_constructor)(n, m.Parameter(2)));
1905    Stream s = m.Build();
1906    ASSERT_EQ(1U, s.size());
1907    EXPECT_EQ(mdpi.add_arch_opcode, s[0]->arch_opcode());
1908    EXPECT_EQ(3U, s[0]->InputCount());
1909    EXPECT_EQ(1U, s[0]->OutputCount());
1910  }
1911}
1912
1913
1914TEST_P(InstructionSelectorIntDPWithIntMulTest, SubWithMul) {
1915  const MulDPInst mdpi = GetParam();
1916  const MachineType type = mdpi.machine_type;
1917  {
1918    StreamBuilder m(this, type, type, type, type);
1919    Node* n = (m.*mdpi.mul_constructor)(m.Parameter(1), m.Parameter(2));
1920    m.Return((m.*mdpi.sub_constructor)(m.Parameter(0), n));
1921    Stream s = m.Build();
1922    ASSERT_EQ(1U, s.size());
1923    EXPECT_EQ(mdpi.sub_arch_opcode, s[0]->arch_opcode());
1924    EXPECT_EQ(3U, s[0]->InputCount());
1925    EXPECT_EQ(1U, s[0]->OutputCount());
1926  }
1927}
1928
1929
1930TEST_P(InstructionSelectorIntDPWithIntMulTest, NegativeMul) {
1931  const MulDPInst mdpi = GetParam();
1932  const MachineType type = mdpi.machine_type;
1933  {
1934    StreamBuilder m(this, type, type, type);
1935    Node* n =
1936        (m.*mdpi.sub_constructor)(BuildConstant(m, type, 0), m.Parameter(0));
1937    m.Return((m.*mdpi.mul_constructor)(n, m.Parameter(1)));
1938    Stream s = m.Build();
1939    ASSERT_EQ(1U, s.size());
1940    EXPECT_EQ(mdpi.neg_arch_opcode, s[0]->arch_opcode());
1941    EXPECT_EQ(2U, s[0]->InputCount());
1942    EXPECT_EQ(1U, s[0]->OutputCount());
1943  }
1944  {
1945    StreamBuilder m(this, type, type, type);
1946    Node* n =
1947        (m.*mdpi.sub_constructor)(BuildConstant(m, type, 0), m.Parameter(1));
1948    m.Return((m.*mdpi.mul_constructor)(m.Parameter(0), n));
1949    Stream s = m.Build();
1950    ASSERT_EQ(1U, s.size());
1951    EXPECT_EQ(mdpi.neg_arch_opcode, s[0]->arch_opcode());
1952    EXPECT_EQ(2U, s[0]->InputCount());
1953    EXPECT_EQ(1U, s[0]->OutputCount());
1954  }
1955}
1956
1957
1958INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1959                        InstructionSelectorIntDPWithIntMulTest,
1960                        ::testing::ValuesIn(kMulDPInstructions));
1961
1962
1963TEST_F(InstructionSelectorTest, Int32MulWithImmediate) {
1964  // x * (2^k + 1) -> x + (x << k)
1965  TRACED_FORRANGE(int32_t, k, 1, 30) {
1966    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
1967    m.Return(m.Int32Mul(m.Parameter(0), m.Int32Constant((1 << k) + 1)));
1968    Stream s = m.Build();
1969    ASSERT_EQ(1U, s.size());
1970    EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
1971    EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
1972    ASSERT_EQ(3U, s[0]->InputCount());
1973    EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
1974    EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2)));
1975    EXPECT_EQ(1U, s[0]->OutputCount());
1976  }
1977  // (2^k + 1) * x -> x + (x << k)
1978  TRACED_FORRANGE(int32_t, k, 1, 30) {
1979    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
1980    m.Return(m.Int32Mul(m.Int32Constant((1 << k) + 1), m.Parameter(0)));
1981    Stream s = m.Build();
1982    ASSERT_EQ(1U, s.size());
1983    EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
1984    EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
1985    ASSERT_EQ(3U, s[0]->InputCount());
1986    EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
1987    EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2)));
1988    EXPECT_EQ(1U, s[0]->OutputCount());
1989  }
1990  // x * (2^k + 1) + c -> x + (x << k) + c
1991  TRACED_FORRANGE(int32_t, k, 1, 30) {
1992    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
1993                    MachineType::Int32());
1994    m.Return(
1995        m.Int32Add(m.Int32Mul(m.Parameter(0), m.Int32Constant((1 << k) + 1)),
1996                   m.Parameter(1)));
1997    Stream s = m.Build();
1998    ASSERT_EQ(2U, s.size());
1999    EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
2000    EXPECT_EQ(kArm64Add32, s[1]->arch_opcode());
2001    EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
2002    ASSERT_EQ(3U, s[0]->InputCount());
2003    EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
2004    EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2)));
2005    EXPECT_EQ(1U, s[0]->OutputCount());
2006  }
2007  // (2^k + 1) * x + c -> x + (x << k) + c
2008  TRACED_FORRANGE(int32_t, k, 1, 30) {
2009    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2010                    MachineType::Int32());
2011    m.Return(
2012        m.Int32Add(m.Int32Mul(m.Int32Constant((1 << k) + 1), m.Parameter(0)),
2013                   m.Parameter(1)));
2014    Stream s = m.Build();
2015    ASSERT_EQ(2U, s.size());
2016    EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
2017    EXPECT_EQ(kArm64Add32, s[1]->arch_opcode());
2018    EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
2019    ASSERT_EQ(3U, s[0]->InputCount());
2020    EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
2021    EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2)));
2022    EXPECT_EQ(1U, s[0]->OutputCount());
2023  }
2024  // c + x * (2^k + 1) -> c + x + (x << k)
2025  TRACED_FORRANGE(int32_t, k, 1, 30) {
2026    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2027                    MachineType::Int32());
2028    m.Return(
2029        m.Int32Add(m.Parameter(0),
2030                   m.Int32Mul(m.Parameter(1), m.Int32Constant((1 << k) + 1))));
2031    Stream s = m.Build();
2032    ASSERT_EQ(2U, s.size());
2033    EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
2034    EXPECT_EQ(kArm64Add32, s[1]->arch_opcode());
2035    EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
2036    ASSERT_EQ(3U, s[0]->InputCount());
2037    EXPECT_EQ(s.ToVreg(s[0]->InputAt(1)), s.ToVreg(s[0]->InputAt(1)));
2038    EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2)));
2039    EXPECT_EQ(1U, s[0]->OutputCount());
2040  }
2041  // c + (2^k + 1) * x -> c + x + (x << k)
2042  TRACED_FORRANGE(int32_t, k, 1, 30) {
2043    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2044                    MachineType::Int32());
2045    m.Return(
2046        m.Int32Add(m.Parameter(0),
2047                   m.Int32Mul(m.Int32Constant((1 << k) + 1), m.Parameter(1))));
2048    Stream s = m.Build();
2049    ASSERT_EQ(2U, s.size());
2050    EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
2051    EXPECT_EQ(kArm64Add32, s[1]->arch_opcode());
2052    EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
2053    ASSERT_EQ(3U, s[0]->InputCount());
2054    EXPECT_EQ(s.ToVreg(s[0]->InputAt(1)), s.ToVreg(s[0]->InputAt(1)));
2055    EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2)));
2056    EXPECT_EQ(1U, s[0]->OutputCount());
2057  }
2058  // c - x * (2^k + 1) -> c - x + (x << k)
2059  TRACED_FORRANGE(int32_t, k, 1, 30) {
2060    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2061                    MachineType::Int32());
2062    m.Return(
2063        m.Int32Sub(m.Parameter(0),
2064                   m.Int32Mul(m.Parameter(1), m.Int32Constant((1 << k) + 1))));
2065    Stream s = m.Build();
2066    ASSERT_EQ(2U, s.size());
2067    EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
2068    EXPECT_EQ(kArm64Sub32, s[1]->arch_opcode());
2069    EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
2070    ASSERT_EQ(3U, s[0]->InputCount());
2071    EXPECT_EQ(s.ToVreg(s[0]->InputAt(1)), s.ToVreg(s[0]->InputAt(1)));
2072    EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2)));
2073    EXPECT_EQ(1U, s[0]->OutputCount());
2074  }
2075  // c - (2^k + 1) * x -> c - x + (x << k)
2076  TRACED_FORRANGE(int32_t, k, 1, 30) {
2077    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2078                    MachineType::Int32());
2079    m.Return(
2080        m.Int32Sub(m.Parameter(0),
2081                   m.Int32Mul(m.Int32Constant((1 << k) + 1), m.Parameter(1))));
2082    Stream s = m.Build();
2083    ASSERT_EQ(2U, s.size());
2084    EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
2085    EXPECT_EQ(kArm64Sub32, s[1]->arch_opcode());
2086    EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
2087    ASSERT_EQ(3U, s[0]->InputCount());
2088    EXPECT_EQ(s.ToVreg(s[0]->InputAt(1)), s.ToVreg(s[0]->InputAt(1)));
2089    EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2)));
2090    EXPECT_EQ(1U, s[0]->OutputCount());
2091  }
2092}
2093
2094
2095TEST_F(InstructionSelectorTest, Int64MulWithImmediate) {
2096  // x * (2^k + 1) -> x + (x << k)
2097  TRACED_FORRANGE(int64_t, k, 1, 62) {
2098    StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
2099    m.Return(m.Int64Mul(m.Parameter(0), m.Int64Constant((1L << k) + 1)));
2100    Stream s = m.Build();
2101    ASSERT_EQ(1U, s.size());
2102    EXPECT_EQ(kArm64Add, s[0]->arch_opcode());
2103    EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
2104    ASSERT_EQ(3U, s[0]->InputCount());
2105    EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
2106    EXPECT_EQ(k, s.ToInt64(s[0]->InputAt(2)));
2107    EXPECT_EQ(1U, s[0]->OutputCount());
2108  }
2109  // (2^k + 1) * x -> x + (x << k)
2110  TRACED_FORRANGE(int64_t, k, 1, 62) {
2111    StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
2112    m.Return(m.Int64Mul(m.Int64Constant((1L << k) + 1), m.Parameter(0)));
2113    Stream s = m.Build();
2114    ASSERT_EQ(1U, s.size());
2115    EXPECT_EQ(kArm64Add, s[0]->arch_opcode());
2116    EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
2117    ASSERT_EQ(3U, s[0]->InputCount());
2118    EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
2119    EXPECT_EQ(k, s.ToInt64(s[0]->InputAt(2)));
2120    EXPECT_EQ(1U, s[0]->OutputCount());
2121  }
2122  // x * (2^k + 1) + c -> x + (x << k) + c
2123  TRACED_FORRANGE(int64_t, k, 1, 62) {
2124    StreamBuilder m(this, MachineType::Int64(), MachineType::Int64(),
2125                    MachineType::Int64());
2126    m.Return(
2127        m.Int64Add(m.Int64Mul(m.Parameter(0), m.Int64Constant((1L << k) + 1)),
2128                   m.Parameter(1)));
2129    Stream s = m.Build();
2130    ASSERT_EQ(2U, s.size());
2131    EXPECT_EQ(kArm64Add, s[0]->arch_opcode());
2132    EXPECT_EQ(kArm64Add, s[1]->arch_opcode());
2133    EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
2134    ASSERT_EQ(3U, s[0]->InputCount());
2135    EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
2136    EXPECT_EQ(k, s.ToInt64(s[0]->InputAt(2)));
2137    EXPECT_EQ(1U, s[0]->OutputCount());
2138  }
2139  // (2^k + 1) * x + c -> x + (x << k) + c
2140  TRACED_FORRANGE(int64_t, k, 1, 62) {
2141    StreamBuilder m(this, MachineType::Int64(), MachineType::Int64(),
2142                    MachineType::Int64());
2143    m.Return(
2144        m.Int64Add(m.Int64Mul(m.Int64Constant((1L << k) + 1), m.Parameter(0)),
2145                   m.Parameter(1)));
2146    Stream s = m.Build();
2147    ASSERT_EQ(2U, s.size());
2148    EXPECT_EQ(kArm64Add, s[0]->arch_opcode());
2149    EXPECT_EQ(kArm64Add, s[1]->arch_opcode());
2150    EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
2151    ASSERT_EQ(3U, s[0]->InputCount());
2152    EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
2153    EXPECT_EQ(k, s.ToInt64(s[0]->InputAt(2)));
2154    EXPECT_EQ(1U, s[0]->OutputCount());
2155  }
2156  // c + x * (2^k + 1) -> c + x + (x << k)
2157  TRACED_FORRANGE(int64_t, k, 1, 62) {
2158    StreamBuilder m(this, MachineType::Int64(), MachineType::Int64(),
2159                    MachineType::Int64());
2160    m.Return(
2161        m.Int64Add(m.Parameter(0),
2162                   m.Int64Mul(m.Parameter(1), m.Int64Constant((1L << k) + 1))));
2163    Stream s = m.Build();
2164    ASSERT_EQ(2U, s.size());
2165    EXPECT_EQ(kArm64Add, s[0]->arch_opcode());
2166    EXPECT_EQ(kArm64Add, s[1]->arch_opcode());
2167    EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
2168    ASSERT_EQ(3U, s[0]->InputCount());
2169    EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
2170    EXPECT_EQ(k, s.ToInt64(s[0]->InputAt(2)));
2171    EXPECT_EQ(1U, s[0]->OutputCount());
2172  }
2173  // c + (2^k + 1) * x -> c + x + (x << k)
2174  TRACED_FORRANGE(int64_t, k, 1, 62) {
2175    StreamBuilder m(this, MachineType::Int64(), MachineType::Int64(),
2176                    MachineType::Int64());
2177    m.Return(
2178        m.Int64Add(m.Parameter(0),
2179                   m.Int64Mul(m.Int64Constant((1L << k) + 1), m.Parameter(1))));
2180    Stream s = m.Build();
2181    ASSERT_EQ(2U, s.size());
2182    EXPECT_EQ(kArm64Add, s[0]->arch_opcode());
2183    EXPECT_EQ(kArm64Add, s[1]->arch_opcode());
2184    EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
2185    ASSERT_EQ(3U, s[0]->InputCount());
2186    EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
2187    EXPECT_EQ(k, s.ToInt64(s[0]->InputAt(2)));
2188    EXPECT_EQ(1U, s[0]->OutputCount());
2189  }
2190  // c - x * (2^k + 1) -> c - x + (x << k)
2191  TRACED_FORRANGE(int64_t, k, 1, 62) {
2192    StreamBuilder m(this, MachineType::Int64(), MachineType::Int64(),
2193                    MachineType::Int64());
2194    m.Return(
2195        m.Int64Sub(m.Parameter(0),
2196                   m.Int64Mul(m.Parameter(1), m.Int64Constant((1L << k) + 1))));
2197    Stream s = m.Build();
2198    ASSERT_EQ(2U, s.size());
2199    EXPECT_EQ(kArm64Add, s[0]->arch_opcode());
2200    EXPECT_EQ(kArm64Sub, s[1]->arch_opcode());
2201    EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
2202    ASSERT_EQ(3U, s[0]->InputCount());
2203    EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
2204    EXPECT_EQ(k, s.ToInt64(s[0]->InputAt(2)));
2205    EXPECT_EQ(1U, s[0]->OutputCount());
2206  }
2207  // c - (2^k + 1) * x -> c - x + (x << k)
2208  TRACED_FORRANGE(int64_t, k, 1, 62) {
2209    StreamBuilder m(this, MachineType::Int64(), MachineType::Int64(),
2210                    MachineType::Int64());
2211    m.Return(
2212        m.Int64Sub(m.Parameter(0),
2213                   m.Int64Mul(m.Int64Constant((1L << k) + 1), m.Parameter(1))));
2214    Stream s = m.Build();
2215    ASSERT_EQ(2U, s.size());
2216    EXPECT_EQ(kArm64Add, s[0]->arch_opcode());
2217    EXPECT_EQ(kArm64Sub, s[1]->arch_opcode());
2218    EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
2219    ASSERT_EQ(3U, s[0]->InputCount());
2220    EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
2221    EXPECT_EQ(k, s.ToInt64(s[0]->InputAt(2)));
2222    EXPECT_EQ(1U, s[0]->OutputCount());
2223  }
2224}
2225
2226
2227// -----------------------------------------------------------------------------
2228// Floating point instructions.
2229
2230typedef InstructionSelectorTestWithParam<MachInst2>
2231    InstructionSelectorFPArithTest;
2232
2233
2234TEST_P(InstructionSelectorFPArithTest, Parameter) {
2235  const MachInst2 fpa = GetParam();
2236  StreamBuilder m(this, fpa.machine_type, fpa.machine_type, fpa.machine_type);
2237  m.Return((m.*fpa.constructor)(m.Parameter(0), m.Parameter(1)));
2238  Stream s = m.Build();
2239  ASSERT_EQ(1U, s.size());
2240  EXPECT_EQ(fpa.arch_opcode, s[0]->arch_opcode());
2241  EXPECT_EQ(2U, s[0]->InputCount());
2242  EXPECT_EQ(1U, s[0]->OutputCount());
2243}
2244
2245
2246INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorFPArithTest,
2247                        ::testing::ValuesIn(kFPArithInstructions));
2248
2249
2250typedef InstructionSelectorTestWithParam<FPCmp> InstructionSelectorFPCmpTest;
2251
2252
2253TEST_P(InstructionSelectorFPCmpTest, Parameter) {
2254  const FPCmp cmp = GetParam();
2255  StreamBuilder m(this, MachineType::Int32(), cmp.mi.machine_type,
2256                  cmp.mi.machine_type);
2257  m.Return((m.*cmp.mi.constructor)(m.Parameter(0), m.Parameter(1)));
2258  Stream s = m.Build();
2259  ASSERT_EQ(1U, s.size());
2260  EXPECT_EQ(cmp.mi.arch_opcode, s[0]->arch_opcode());
2261  EXPECT_EQ(2U, s[0]->InputCount());
2262  EXPECT_EQ(1U, s[0]->OutputCount());
2263  EXPECT_EQ(kFlags_set, s[0]->flags_mode());
2264  EXPECT_EQ(cmp.cond, s[0]->flags_condition());
2265}
2266
2267
2268TEST_P(InstructionSelectorFPCmpTest, WithImmediateZeroOnRight) {
2269  const FPCmp cmp = GetParam();
2270  StreamBuilder m(this, MachineType::Int32(), cmp.mi.machine_type);
2271  if (cmp.mi.machine_type == MachineType::Float64()) {
2272    m.Return((m.*cmp.mi.constructor)(m.Parameter(0), m.Float64Constant(0.0)));
2273  } else {
2274    m.Return((m.*cmp.mi.constructor)(m.Parameter(0), m.Float32Constant(0.0f)));
2275  }
2276  Stream s = m.Build();
2277  ASSERT_EQ(1U, s.size());
2278  EXPECT_EQ(cmp.mi.arch_opcode, s[0]->arch_opcode());
2279  EXPECT_EQ(2U, s[0]->InputCount());
2280  EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
2281  EXPECT_EQ(1U, s[0]->OutputCount());
2282  EXPECT_EQ(kFlags_set, s[0]->flags_mode());
2283  EXPECT_EQ(cmp.cond, s[0]->flags_condition());
2284}
2285
2286
2287TEST_P(InstructionSelectorFPCmpTest, WithImmediateZeroOnLeft) {
2288  const FPCmp cmp = GetParam();
2289  StreamBuilder m(this, MachineType::Int32(), cmp.mi.machine_type);
2290  if (cmp.mi.machine_type == MachineType::Float64()) {
2291    m.Return((m.*cmp.mi.constructor)(m.Float64Constant(0.0), m.Parameter(0)));
2292  } else {
2293    m.Return((m.*cmp.mi.constructor)(m.Float32Constant(0.0f), m.Parameter(0)));
2294  }
2295  Stream s = m.Build();
2296  ASSERT_EQ(1U, s.size());
2297  EXPECT_EQ(cmp.mi.arch_opcode, s[0]->arch_opcode());
2298  EXPECT_EQ(2U, s[0]->InputCount());
2299  EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
2300  EXPECT_EQ(1U, s[0]->OutputCount());
2301  EXPECT_EQ(kFlags_set, s[0]->flags_mode());
2302  EXPECT_EQ(cmp.commuted_cond, s[0]->flags_condition());
2303}
2304
2305
2306INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorFPCmpTest,
2307                        ::testing::ValuesIn(kFPCmpInstructions));
2308
2309
2310// -----------------------------------------------------------------------------
2311// Conversions.
2312
2313typedef InstructionSelectorTestWithParam<Conversion>
2314    InstructionSelectorConversionTest;
2315
2316
2317TEST_P(InstructionSelectorConversionTest, Parameter) {
2318  const Conversion conv = GetParam();
2319  StreamBuilder m(this, conv.mi.machine_type, conv.src_machine_type);
2320  m.Return((m.*conv.mi.constructor)(m.Parameter(0)));
2321  Stream s = m.Build();
2322  ASSERT_EQ(1U, s.size());
2323  EXPECT_EQ(conv.mi.arch_opcode, s[0]->arch_opcode());
2324  EXPECT_EQ(1U, s[0]->InputCount());
2325  EXPECT_EQ(1U, s[0]->OutputCount());
2326}
2327
2328
2329INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
2330                        InstructionSelectorConversionTest,
2331                        ::testing::ValuesIn(kConversionInstructions));
2332
2333typedef InstructionSelectorTestWithParam<MachInst2>
2334    InstructionSelectorElidedChangeUint32ToUint64Test;
2335
2336TEST_P(InstructionSelectorElidedChangeUint32ToUint64Test, Parameter) {
2337  const MachInst2 binop = GetParam();
2338  StreamBuilder m(this, MachineType::Uint64(), binop.machine_type,
2339                  binop.machine_type);
2340  m.Return(m.ChangeUint32ToUint64(
2341      (m.*binop.constructor)(m.Parameter(0), m.Parameter(1))));
2342  Stream s = m.Build();
2343  // Make sure the `ChangeUint32ToUint64` node turned into a no-op.
2344  ASSERT_EQ(1U, s.size());
2345  EXPECT_EQ(binop.arch_opcode, s[0]->arch_opcode());
2346  EXPECT_EQ(2U, s[0]->InputCount());
2347  EXPECT_EQ(1U, s[0]->OutputCount());
2348}
2349
2350INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
2351                        InstructionSelectorElidedChangeUint32ToUint64Test,
2352                        ::testing::ValuesIn(kCanElideChangeUint32ToUint64));
2353
2354TEST_F(InstructionSelectorTest, ChangeUint32ToUint64AfterLoad) {
2355  // For each case, make sure the `ChangeUint32ToUint64` node turned into a
2356  // no-op.
2357
2358  // Ldrb
2359  {
2360    StreamBuilder m(this, MachineType::Uint64(), MachineType::Pointer(),
2361                    MachineType::Int32());
2362    m.Return(m.ChangeUint32ToUint64(
2363        m.Load(MachineType::Uint8(), m.Parameter(0), m.Parameter(1))));
2364    Stream s = m.Build();
2365    ASSERT_EQ(1U, s.size());
2366    EXPECT_EQ(kArm64Ldrb, s[0]->arch_opcode());
2367    EXPECT_EQ(kMode_MRR, s[0]->addressing_mode());
2368    EXPECT_EQ(2U, s[0]->InputCount());
2369    EXPECT_EQ(1U, s[0]->OutputCount());
2370  }
2371  // Ldrh
2372  {
2373    StreamBuilder m(this, MachineType::Uint64(), MachineType::Pointer(),
2374                    MachineType::Int32());
2375    m.Return(m.ChangeUint32ToUint64(
2376        m.Load(MachineType::Uint16(), m.Parameter(0), m.Parameter(1))));
2377    Stream s = m.Build();
2378    ASSERT_EQ(1U, s.size());
2379    EXPECT_EQ(kArm64Ldrh, s[0]->arch_opcode());
2380    EXPECT_EQ(kMode_MRR, s[0]->addressing_mode());
2381    EXPECT_EQ(2U, s[0]->InputCount());
2382    EXPECT_EQ(1U, s[0]->OutputCount());
2383  }
2384  // LdrW
2385  {
2386    StreamBuilder m(this, MachineType::Uint64(), MachineType::Pointer(),
2387                    MachineType::Int32());
2388    m.Return(m.ChangeUint32ToUint64(
2389        m.Load(MachineType::Uint32(), m.Parameter(0), m.Parameter(1))));
2390    Stream s = m.Build();
2391    ASSERT_EQ(1U, s.size());
2392    EXPECT_EQ(kArm64LdrW, s[0]->arch_opcode());
2393    EXPECT_EQ(kMode_MRR, s[0]->addressing_mode());
2394    EXPECT_EQ(2U, s[0]->InputCount());
2395    EXPECT_EQ(1U, s[0]->OutputCount());
2396  }
2397}
2398
2399// -----------------------------------------------------------------------------
2400// Memory access instructions.
2401
2402
2403namespace {
2404
2405struct MemoryAccess {
2406  MachineType type;
2407  ArchOpcode ldr_opcode;
2408  ArchOpcode str_opcode;
2409  const int32_t immediates[20];
2410};
2411
2412
2413std::ostream& operator<<(std::ostream& os, const MemoryAccess& memacc) {
2414  return os << memacc.type;
2415}
2416
2417}  // namespace
2418
2419
2420static const MemoryAccess kMemoryAccesses[] = {
2421    {MachineType::Int8(),
2422     kArm64Ldrsb,
2423     kArm64Strb,
2424     {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 257, 258, 1000, 1001, 2121,
2425      2442, 4093, 4094, 4095}},
2426    {MachineType::Uint8(),
2427     kArm64Ldrb,
2428     kArm64Strb,
2429     {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 257, 258, 1000, 1001, 2121,
2430      2442, 4093, 4094, 4095}},
2431    {MachineType::Int16(),
2432     kArm64Ldrsh,
2433     kArm64Strh,
2434     {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 258, 260, 4096, 4098, 4100,
2435      4242, 6786, 8188, 8190}},
2436    {MachineType::Uint16(),
2437     kArm64Ldrh,
2438     kArm64Strh,
2439     {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 258, 260, 4096, 4098, 4100,
2440      4242, 6786, 8188, 8190}},
2441    {MachineType::Int32(),
2442     kArm64LdrW,
2443     kArm64StrW,
2444     {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 260, 4096, 4100, 8192, 8196,
2445      3276, 3280, 16376, 16380}},
2446    {MachineType::Uint32(),
2447     kArm64LdrW,
2448     kArm64StrW,
2449     {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 260, 4096, 4100, 8192, 8196,
2450      3276, 3280, 16376, 16380}},
2451    {MachineType::Int64(),
2452     kArm64Ldr,
2453     kArm64Str,
2454     {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 264, 4096, 4104, 8192, 8200,
2455      16384, 16392, 32752, 32760}},
2456    {MachineType::Uint64(),
2457     kArm64Ldr,
2458     kArm64Str,
2459     {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 264, 4096, 4104, 8192, 8200,
2460      16384, 16392, 32752, 32760}},
2461    {MachineType::Float32(),
2462     kArm64LdrS,
2463     kArm64StrS,
2464     {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 260, 4096, 4100, 8192, 8196,
2465      3276, 3280, 16376, 16380}},
2466    {MachineType::Float64(),
2467     kArm64LdrD,
2468     kArm64StrD,
2469     {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 264, 4096, 4104, 8192, 8200,
2470      16384, 16392, 32752, 32760}}};
2471
2472
2473typedef InstructionSelectorTestWithParam<MemoryAccess>
2474    InstructionSelectorMemoryAccessTest;
2475
2476
2477TEST_P(InstructionSelectorMemoryAccessTest, LoadWithParameters) {
2478  const MemoryAccess memacc = GetParam();
2479  StreamBuilder m(this, memacc.type, MachineType::Pointer(),
2480                  MachineType::Int32());
2481  m.Return(m.Load(memacc.type, m.Parameter(0), m.Parameter(1)));
2482  Stream s = m.Build();
2483  ASSERT_EQ(1U, s.size());
2484  EXPECT_EQ(memacc.ldr_opcode, s[0]->arch_opcode());
2485  EXPECT_EQ(kMode_MRR, s[0]->addressing_mode());
2486  EXPECT_EQ(2U, s[0]->InputCount());
2487  EXPECT_EQ(1U, s[0]->OutputCount());
2488}
2489
2490
2491TEST_P(InstructionSelectorMemoryAccessTest, LoadWithImmediateIndex) {
2492  const MemoryAccess memacc = GetParam();
2493  TRACED_FOREACH(int32_t, index, memacc.immediates) {
2494    StreamBuilder m(this, memacc.type, MachineType::Pointer());
2495    m.Return(m.Load(memacc.type, m.Parameter(0), m.Int32Constant(index)));
2496    Stream s = m.Build();
2497    ASSERT_EQ(1U, s.size());
2498    EXPECT_EQ(memacc.ldr_opcode, s[0]->arch_opcode());
2499    EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
2500    EXPECT_EQ(2U, s[0]->InputCount());
2501    ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
2502    EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1)));
2503    ASSERT_EQ(1U, s[0]->OutputCount());
2504  }
2505}
2506
2507
2508TEST_P(InstructionSelectorMemoryAccessTest, StoreWithParameters) {
2509  const MemoryAccess memacc = GetParam();
2510  StreamBuilder m(this, MachineType::Int32(), MachineType::Pointer(),
2511                  MachineType::Int32(), memacc.type);
2512  m.Store(memacc.type.representation(), m.Parameter(0), m.Parameter(1),
2513          m.Parameter(2), kNoWriteBarrier);
2514  m.Return(m.Int32Constant(0));
2515  Stream s = m.Build();
2516  ASSERT_EQ(1U, s.size());
2517  EXPECT_EQ(memacc.str_opcode, s[0]->arch_opcode());
2518  EXPECT_EQ(kMode_MRR, s[0]->addressing_mode());
2519  EXPECT_EQ(3U, s[0]->InputCount());
2520  EXPECT_EQ(0U, s[0]->OutputCount());
2521}
2522
2523
2524TEST_P(InstructionSelectorMemoryAccessTest, StoreWithImmediateIndex) {
2525  const MemoryAccess memacc = GetParam();
2526  TRACED_FOREACH(int32_t, index, memacc.immediates) {
2527    StreamBuilder m(this, MachineType::Int32(), MachineType::Pointer(),
2528                    memacc.type);
2529    m.Store(memacc.type.representation(), m.Parameter(0),
2530            m.Int32Constant(index), m.Parameter(1), kNoWriteBarrier);
2531    m.Return(m.Int32Constant(0));
2532    Stream s = m.Build();
2533    ASSERT_EQ(1U, s.size());
2534    EXPECT_EQ(memacc.str_opcode, s[0]->arch_opcode());
2535    EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
2536    ASSERT_EQ(3U, s[0]->InputCount());
2537    ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(2)->kind());
2538    EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(2)));
2539    EXPECT_EQ(0U, s[0]->OutputCount());
2540  }
2541}
2542
2543TEST_P(InstructionSelectorMemoryAccessTest, StoreZero) {
2544  const MemoryAccess memacc = GetParam();
2545  TRACED_FOREACH(int32_t, index, memacc.immediates) {
2546    StreamBuilder m(this, MachineType::Int32(), MachineType::Pointer());
2547    m.Store(memacc.type.representation(), m.Parameter(0),
2548            m.Int32Constant(index), m.Int32Constant(0), kNoWriteBarrier);
2549    m.Return(m.Int32Constant(0));
2550    Stream s = m.Build();
2551    ASSERT_EQ(1U, s.size());
2552    EXPECT_EQ(memacc.str_opcode, s[0]->arch_opcode());
2553    EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
2554    ASSERT_EQ(3U, s[0]->InputCount());
2555    ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(2)->kind());
2556    EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(2)));
2557    ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(0)->kind());
2558    EXPECT_EQ(0, s.ToInt64(s[0]->InputAt(0)));
2559    EXPECT_EQ(0U, s[0]->OutputCount());
2560  }
2561}
2562
2563TEST_P(InstructionSelectorMemoryAccessTest, LoadWithShiftedIndex) {
2564  const MemoryAccess memacc = GetParam();
2565  TRACED_FORRANGE(int, immediate_shift, 0, 4) {
2566    // 32 bit shift
2567    {
2568      StreamBuilder m(this, memacc.type, MachineType::Pointer(),
2569                      MachineType::Int32());
2570      Node* const index =
2571          m.Word32Shl(m.Parameter(1), m.Int32Constant(immediate_shift));
2572      m.Return(m.Load(memacc.type, m.Parameter(0), index));
2573      Stream s = m.Build();
2574      if (immediate_shift == ElementSizeLog2Of(memacc.type.representation())) {
2575        ASSERT_EQ(1U, s.size());
2576        EXPECT_EQ(memacc.ldr_opcode, s[0]->arch_opcode());
2577        EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
2578        EXPECT_EQ(3U, s[0]->InputCount());
2579        EXPECT_EQ(1U, s[0]->OutputCount());
2580      } else {
2581        // Make sure we haven't merged the shift into the load instruction.
2582        ASSERT_NE(1U, s.size());
2583        EXPECT_NE(memacc.ldr_opcode, s[0]->arch_opcode());
2584        EXPECT_NE(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
2585      }
2586    }
2587    // 64 bit shift
2588    {
2589      StreamBuilder m(this, memacc.type, MachineType::Pointer(),
2590                      MachineType::Int64());
2591      Node* const index =
2592          m.Word64Shl(m.Parameter(1), m.Int64Constant(immediate_shift));
2593      m.Return(m.Load(memacc.type, m.Parameter(0), index));
2594      Stream s = m.Build();
2595      if (immediate_shift == ElementSizeLog2Of(memacc.type.representation())) {
2596        ASSERT_EQ(1U, s.size());
2597        EXPECT_EQ(memacc.ldr_opcode, s[0]->arch_opcode());
2598        EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
2599        EXPECT_EQ(3U, s[0]->InputCount());
2600        EXPECT_EQ(1U, s[0]->OutputCount());
2601      } else {
2602        // Make sure we haven't merged the shift into the load instruction.
2603        ASSERT_NE(1U, s.size());
2604        EXPECT_NE(memacc.ldr_opcode, s[0]->arch_opcode());
2605        EXPECT_NE(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
2606      }
2607    }
2608  }
2609}
2610
2611TEST_P(InstructionSelectorMemoryAccessTest, StoreWithShiftedIndex) {
2612  const MemoryAccess memacc = GetParam();
2613  TRACED_FORRANGE(int, immediate_shift, 0, 4) {
2614    // 32 bit shift
2615    {
2616      StreamBuilder m(this, MachineType::Int32(), MachineType::Pointer(),
2617                      MachineType::Int32(), memacc.type);
2618      Node* const index =
2619          m.Word32Shl(m.Parameter(1), m.Int32Constant(immediate_shift));
2620      m.Store(memacc.type.representation(), m.Parameter(0), index,
2621              m.Parameter(2), kNoWriteBarrier);
2622      m.Return(m.Int32Constant(0));
2623      Stream s = m.Build();
2624      if (immediate_shift == ElementSizeLog2Of(memacc.type.representation())) {
2625        ASSERT_EQ(1U, s.size());
2626        EXPECT_EQ(memacc.str_opcode, s[0]->arch_opcode());
2627        EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
2628        EXPECT_EQ(4U, s[0]->InputCount());
2629        EXPECT_EQ(0U, s[0]->OutputCount());
2630      } else {
2631        // Make sure we haven't merged the shift into the store instruction.
2632        ASSERT_NE(1U, s.size());
2633        EXPECT_NE(memacc.str_opcode, s[0]->arch_opcode());
2634        EXPECT_NE(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
2635      }
2636    }
2637    // 64 bit shift
2638    {
2639      StreamBuilder m(this, MachineType::Int64(), MachineType::Pointer(),
2640                      MachineType::Int64(), memacc.type);
2641      Node* const index =
2642          m.Word64Shl(m.Parameter(1), m.Int64Constant(immediate_shift));
2643      m.Store(memacc.type.representation(), m.Parameter(0), index,
2644              m.Parameter(2), kNoWriteBarrier);
2645      m.Return(m.Int64Constant(0));
2646      Stream s = m.Build();
2647      if (immediate_shift == ElementSizeLog2Of(memacc.type.representation())) {
2648        ASSERT_EQ(1U, s.size());
2649        EXPECT_EQ(memacc.str_opcode, s[0]->arch_opcode());
2650        EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
2651        EXPECT_EQ(4U, s[0]->InputCount());
2652        EXPECT_EQ(0U, s[0]->OutputCount());
2653      } else {
2654        // Make sure we haven't merged the shift into the store instruction.
2655        ASSERT_NE(1U, s.size());
2656        EXPECT_NE(memacc.str_opcode, s[0]->arch_opcode());
2657        EXPECT_NE(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
2658      }
2659    }
2660  }
2661}
2662
2663INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
2664                        InstructionSelectorMemoryAccessTest,
2665                        ::testing::ValuesIn(kMemoryAccesses));
2666
2667
2668// -----------------------------------------------------------------------------
2669// Comparison instructions.
2670
2671static const MachInst2 kComparisonInstructions[] = {
2672    {&RawMachineAssembler::Word32Equal, "Word32Equal", kArm64Cmp32,
2673     MachineType::Int32()},
2674    {&RawMachineAssembler::Word64Equal, "Word64Equal", kArm64Cmp,
2675     MachineType::Int64()},
2676};
2677
2678
2679typedef InstructionSelectorTestWithParam<MachInst2>
2680    InstructionSelectorComparisonTest;
2681
2682
2683TEST_P(InstructionSelectorComparisonTest, WithParameters) {
2684  const MachInst2 cmp = GetParam();
2685  const MachineType type = cmp.machine_type;
2686  StreamBuilder m(this, type, type, type);
2687  m.Return((m.*cmp.constructor)(m.Parameter(0), m.Parameter(1)));
2688  Stream s = m.Build();
2689  ASSERT_EQ(1U, s.size());
2690  EXPECT_EQ(cmp.arch_opcode, s[0]->arch_opcode());
2691  EXPECT_EQ(2U, s[0]->InputCount());
2692  EXPECT_EQ(1U, s[0]->OutputCount());
2693  EXPECT_EQ(kFlags_set, s[0]->flags_mode());
2694  EXPECT_EQ(kEqual, s[0]->flags_condition());
2695}
2696
2697
2698TEST_P(InstructionSelectorComparisonTest, WithImmediate) {
2699  const MachInst2 cmp = GetParam();
2700  const MachineType type = cmp.machine_type;
2701  TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
2702    // Compare with 0 are turned into tst instruction.
2703    if (imm == 0) continue;
2704    StreamBuilder m(this, type, type);
2705    m.Return((m.*cmp.constructor)(m.Parameter(0), BuildConstant(m, type, imm)));
2706    Stream s = m.Build();
2707    ASSERT_EQ(1U, s.size());
2708    EXPECT_EQ(cmp.arch_opcode, s[0]->arch_opcode());
2709    ASSERT_EQ(2U, s[0]->InputCount());
2710    ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
2711    EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(1)));
2712    EXPECT_EQ(1U, s[0]->OutputCount());
2713    EXPECT_EQ(kFlags_set, s[0]->flags_mode());
2714    EXPECT_EQ(kEqual, s[0]->flags_condition());
2715  }
2716  TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
2717    // Compare with 0 are turned into tst instruction.
2718    if (imm == 0) continue;
2719    StreamBuilder m(this, type, type);
2720    m.Return((m.*cmp.constructor)(BuildConstant(m, type, imm), m.Parameter(0)));
2721    Stream s = m.Build();
2722    ASSERT_EQ(1U, s.size());
2723    EXPECT_EQ(cmp.arch_opcode, s[0]->arch_opcode());
2724    ASSERT_EQ(2U, s[0]->InputCount());
2725    ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
2726    EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(1)));
2727    EXPECT_EQ(1U, s[0]->OutputCount());
2728    EXPECT_EQ(kFlags_set, s[0]->flags_mode());
2729    EXPECT_EQ(kEqual, s[0]->flags_condition());
2730  }
2731}
2732
2733INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
2734                        InstructionSelectorComparisonTest,
2735                        ::testing::ValuesIn(kComparisonInstructions));
2736
2737
2738TEST_F(InstructionSelectorTest, Word32EqualWithZero) {
2739  {
2740    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2741    m.Return(m.Word32Equal(m.Parameter(0), m.Int32Constant(0)));
2742    Stream s = m.Build();
2743    ASSERT_EQ(1U, s.size());
2744    EXPECT_EQ(kArm64Tst32, s[0]->arch_opcode());
2745    ASSERT_EQ(2U, s[0]->InputCount());
2746    EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
2747    EXPECT_EQ(1U, s[0]->OutputCount());
2748    EXPECT_EQ(kFlags_set, s[0]->flags_mode());
2749    EXPECT_EQ(kEqual, s[0]->flags_condition());
2750  }
2751  {
2752    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2753    m.Return(m.Word32Equal(m.Int32Constant(0), m.Parameter(0)));
2754    Stream s = m.Build();
2755    ASSERT_EQ(1U, s.size());
2756    EXPECT_EQ(kArm64Tst32, s[0]->arch_opcode());
2757    ASSERT_EQ(2U, s[0]->InputCount());
2758    EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
2759    EXPECT_EQ(1U, s[0]->OutputCount());
2760    EXPECT_EQ(kFlags_set, s[0]->flags_mode());
2761    EXPECT_EQ(kEqual, s[0]->flags_condition());
2762  }
2763}
2764
2765
2766TEST_F(InstructionSelectorTest, Word64EqualWithZero) {
2767  {
2768    StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
2769    m.Return(m.Word64Equal(m.Parameter(0), m.Int64Constant(0)));
2770    Stream s = m.Build();
2771    ASSERT_EQ(1U, s.size());
2772    EXPECT_EQ(kArm64Tst, s[0]->arch_opcode());
2773    ASSERT_EQ(2U, s[0]->InputCount());
2774    EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
2775    EXPECT_EQ(1U, s[0]->OutputCount());
2776    EXPECT_EQ(kFlags_set, s[0]->flags_mode());
2777    EXPECT_EQ(kEqual, s[0]->flags_condition());
2778  }
2779  {
2780    StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
2781    m.Return(m.Word64Equal(m.Int64Constant(0), m.Parameter(0)));
2782    Stream s = m.Build();
2783    ASSERT_EQ(1U, s.size());
2784    EXPECT_EQ(kArm64Tst, s[0]->arch_opcode());
2785    ASSERT_EQ(2U, s[0]->InputCount());
2786    EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
2787    EXPECT_EQ(1U, s[0]->OutputCount());
2788    EXPECT_EQ(kFlags_set, s[0]->flags_mode());
2789    EXPECT_EQ(kEqual, s[0]->flags_condition());
2790  }
2791}
2792
2793
2794TEST_F(InstructionSelectorTest, Word32EqualWithWord32Shift) {
2795  TRACED_FOREACH(Shift, shift, kShiftInstructions) {
2796    // Skip non 32-bit shifts or ror operations.
2797    if (shift.mi.machine_type != MachineType::Int32() ||
2798        shift.mi.arch_opcode == kArm64Ror32) {
2799      continue;
2800    }
2801
2802    TRACED_FORRANGE(int32_t, imm, -32, 63) {
2803      StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2804                      MachineType::Int32());
2805      Node* const p0 = m.Parameter(0);
2806      Node* const p1 = m.Parameter(1);
2807      Node* r = (m.*shift.mi.constructor)(p1, m.Int32Constant(imm));
2808      m.Return(m.Word32Equal(p0, r));
2809      Stream s = m.Build();
2810      ASSERT_EQ(1U, s.size());
2811      EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode());
2812      EXPECT_EQ(shift.mode, s[0]->addressing_mode());
2813      ASSERT_EQ(3U, s[0]->InputCount());
2814      EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
2815      EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
2816      EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2)));
2817      ASSERT_EQ(1U, s[0]->OutputCount());
2818    }
2819    TRACED_FORRANGE(int32_t, imm, -32, 63) {
2820      StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2821                      MachineType::Int32());
2822      Node* const p0 = m.Parameter(0);
2823      Node* const p1 = m.Parameter(1);
2824      Node* r = (m.*shift.mi.constructor)(p1, m.Int32Constant(imm));
2825      m.Return(m.Word32Equal(r, p0));
2826      Stream s = m.Build();
2827      ASSERT_EQ(1U, s.size());
2828      EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode());
2829      EXPECT_EQ(shift.mode, s[0]->addressing_mode());
2830      ASSERT_EQ(3U, s[0]->InputCount());
2831      EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
2832      EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
2833      EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2)));
2834      ASSERT_EQ(1U, s[0]->OutputCount());
2835    }
2836  }
2837}
2838
2839
2840TEST_F(InstructionSelectorTest, Word32EqualWithUnsignedExtendByte) {
2841  {
2842    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2843                    MachineType::Int32());
2844    Node* const p0 = m.Parameter(0);
2845    Node* const p1 = m.Parameter(1);
2846    Node* r = m.Word32And(p1, m.Int32Constant(0xff));
2847    m.Return(m.Word32Equal(p0, r));
2848    Stream s = m.Build();
2849    ASSERT_EQ(1U, s.size());
2850    EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode());
2851    EXPECT_EQ(kMode_Operand2_R_UXTB, s[0]->addressing_mode());
2852    ASSERT_EQ(2U, s[0]->InputCount());
2853    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
2854    EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
2855    ASSERT_EQ(1U, s[0]->OutputCount());
2856  }
2857  {
2858    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2859                    MachineType::Int32());
2860    Node* const p0 = m.Parameter(0);
2861    Node* const p1 = m.Parameter(1);
2862    Node* r = m.Word32And(p1, m.Int32Constant(0xff));
2863    m.Return(m.Word32Equal(r, p0));
2864    Stream s = m.Build();
2865    ASSERT_EQ(1U, s.size());
2866    EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode());
2867    EXPECT_EQ(kMode_Operand2_R_UXTB, s[0]->addressing_mode());
2868    ASSERT_EQ(2U, s[0]->InputCount());
2869    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
2870    EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
2871    ASSERT_EQ(1U, s[0]->OutputCount());
2872  }
2873}
2874
2875
2876TEST_F(InstructionSelectorTest, Word32EqualWithUnsignedExtendHalfword) {
2877  {
2878    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2879                    MachineType::Int32());
2880    Node* const p0 = m.Parameter(0);
2881    Node* const p1 = m.Parameter(1);
2882    Node* r = m.Word32And(p1, m.Int32Constant(0xffff));
2883    m.Return(m.Word32Equal(p0, r));
2884    Stream s = m.Build();
2885    ASSERT_EQ(1U, s.size());
2886    EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode());
2887    EXPECT_EQ(kMode_Operand2_R_UXTH, s[0]->addressing_mode());
2888    ASSERT_EQ(2U, s[0]->InputCount());
2889    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
2890    EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
2891    ASSERT_EQ(1U, s[0]->OutputCount());
2892  }
2893  {
2894    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2895                    MachineType::Int32());
2896    Node* const p0 = m.Parameter(0);
2897    Node* const p1 = m.Parameter(1);
2898    Node* r = m.Word32And(p1, m.Int32Constant(0xffff));
2899    m.Return(m.Word32Equal(r, p0));
2900    Stream s = m.Build();
2901    ASSERT_EQ(1U, s.size());
2902    EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode());
2903    EXPECT_EQ(kMode_Operand2_R_UXTH, s[0]->addressing_mode());
2904    ASSERT_EQ(2U, s[0]->InputCount());
2905    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
2906    EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
2907    ASSERT_EQ(1U, s[0]->OutputCount());
2908  }
2909}
2910
2911
2912TEST_F(InstructionSelectorTest, Word32EqualWithSignedExtendByte) {
2913  {
2914    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2915                    MachineType::Int32());
2916    Node* const p0 = m.Parameter(0);
2917    Node* const p1 = m.Parameter(1);
2918    Node* r =
2919        m.Word32Sar(m.Word32Shl(p1, m.Int32Constant(24)), m.Int32Constant(24));
2920    m.Return(m.Word32Equal(p0, r));
2921    Stream s = m.Build();
2922    ASSERT_EQ(1U, s.size());
2923    EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode());
2924    EXPECT_EQ(kMode_Operand2_R_SXTB, s[0]->addressing_mode());
2925    ASSERT_EQ(2U, s[0]->InputCount());
2926    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
2927    EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
2928    ASSERT_EQ(1U, s[0]->OutputCount());
2929  }
2930  {
2931    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2932                    MachineType::Int32());
2933    Node* const p0 = m.Parameter(0);
2934    Node* const p1 = m.Parameter(1);
2935    Node* r =
2936        m.Word32Sar(m.Word32Shl(p1, m.Int32Constant(24)), m.Int32Constant(24));
2937    m.Return(m.Word32Equal(r, p0));
2938    Stream s = m.Build();
2939    ASSERT_EQ(1U, s.size());
2940    EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode());
2941    EXPECT_EQ(kMode_Operand2_R_SXTB, s[0]->addressing_mode());
2942    ASSERT_EQ(2U, s[0]->InputCount());
2943    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
2944    EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
2945    ASSERT_EQ(1U, s[0]->OutputCount());
2946  }
2947}
2948
2949
2950TEST_F(InstructionSelectorTest, Word32EqualWithSignedExtendHalfword) {
2951  {
2952    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2953                    MachineType::Int32());
2954    Node* const p0 = m.Parameter(0);
2955    Node* const p1 = m.Parameter(1);
2956    Node* r =
2957        m.Word32Sar(m.Word32Shl(p1, m.Int32Constant(16)), m.Int32Constant(16));
2958    m.Return(m.Word32Equal(p0, r));
2959    Stream s = m.Build();
2960    ASSERT_EQ(1U, s.size());
2961    EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode());
2962    EXPECT_EQ(kMode_Operand2_R_SXTH, s[0]->addressing_mode());
2963    ASSERT_EQ(2U, s[0]->InputCount());
2964    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
2965    EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
2966    ASSERT_EQ(1U, s[0]->OutputCount());
2967  }
2968  {
2969    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2970                    MachineType::Int32());
2971    Node* const p0 = m.Parameter(0);
2972    Node* const p1 = m.Parameter(1);
2973    Node* r =
2974        m.Word32Sar(m.Word32Shl(p1, m.Int32Constant(16)), m.Int32Constant(16));
2975    m.Return(m.Word32Equal(r, p0));
2976    Stream s = m.Build();
2977    ASSERT_EQ(1U, s.size());
2978    EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode());
2979    EXPECT_EQ(kMode_Operand2_R_SXTH, s[0]->addressing_mode());
2980    ASSERT_EQ(2U, s[0]->InputCount());
2981    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
2982    EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
2983    ASSERT_EQ(1U, s[0]->OutputCount());
2984  }
2985}
2986
2987
2988TEST_F(InstructionSelectorTest, Word32EqualZeroWithWord32Equal) {
2989  {
2990    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2991                    MachineType::Int32());
2992    Node* const p0 = m.Parameter(0);
2993    Node* const p1 = m.Parameter(1);
2994    m.Return(m.Word32Equal(m.Word32Equal(p0, p1), m.Int32Constant(0)));
2995    Stream s = m.Build();
2996    ASSERT_EQ(1U, s.size());
2997    EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode());
2998    ASSERT_EQ(2U, s[0]->InputCount());
2999    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
3000    EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
3001    EXPECT_EQ(1U, s[0]->OutputCount());
3002    EXPECT_EQ(kFlags_set, s[0]->flags_mode());
3003    EXPECT_EQ(kNotEqual, s[0]->flags_condition());
3004  }
3005  {
3006    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
3007                    MachineType::Int32());
3008    Node* const p0 = m.Parameter(0);
3009    Node* const p1 = m.Parameter(1);
3010    m.Return(m.Word32Equal(m.Int32Constant(0), m.Word32Equal(p0, p1)));
3011    Stream s = m.Build();
3012    ASSERT_EQ(1U, s.size());
3013    EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode());
3014    ASSERT_EQ(2U, s[0]->InputCount());
3015    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
3016    EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
3017    EXPECT_EQ(1U, s[0]->OutputCount());
3018    EXPECT_EQ(kFlags_set, s[0]->flags_mode());
3019    EXPECT_EQ(kNotEqual, s[0]->flags_condition());
3020  }
3021}
3022
3023namespace {
3024
3025struct IntegerCmp {
3026  MachInst2 mi;
3027  FlagsCondition cond;
3028  FlagsCondition commuted_cond;
3029};
3030
3031
3032std::ostream& operator<<(std::ostream& os, const IntegerCmp& cmp) {
3033  return os << cmp.mi;
3034}
3035
3036
3037// ARM64 32-bit integer comparison instructions.
3038const IntegerCmp kIntegerCmpInstructions[] = {
3039    {{&RawMachineAssembler::Word32Equal, "Word32Equal", kArm64Cmp32,
3040      MachineType::Int32()},
3041     kEqual,
3042     kEqual},
3043    {{&RawMachineAssembler::Int32LessThan, "Int32LessThan", kArm64Cmp32,
3044      MachineType::Int32()},
3045     kSignedLessThan,
3046     kSignedGreaterThan},
3047    {{&RawMachineAssembler::Int32LessThanOrEqual, "Int32LessThanOrEqual",
3048      kArm64Cmp32, MachineType::Int32()},
3049     kSignedLessThanOrEqual,
3050     kSignedGreaterThanOrEqual},
3051    {{&RawMachineAssembler::Uint32LessThan, "Uint32LessThan", kArm64Cmp32,
3052      MachineType::Uint32()},
3053     kUnsignedLessThan,
3054     kUnsignedGreaterThan},
3055    {{&RawMachineAssembler::Uint32LessThanOrEqual, "Uint32LessThanOrEqual",
3056      kArm64Cmp32, MachineType::Uint32()},
3057     kUnsignedLessThanOrEqual,
3058     kUnsignedGreaterThanOrEqual}};
3059
3060}  // namespace
3061
3062
3063TEST_F(InstructionSelectorTest, Word32CompareNegateWithWord32Shift) {
3064  TRACED_FOREACH(IntegerCmp, cmp, kIntegerCmpInstructions) {
3065    TRACED_FOREACH(Shift, shift, kShiftInstructions) {
3066      // Test 32-bit operations. Ignore ROR shifts, as compare-negate does not
3067      // support them.
3068      if (shift.mi.machine_type != MachineType::Int32() ||
3069          shift.mi.arch_opcode == kArm64Ror32) {
3070        continue;
3071      }
3072
3073      TRACED_FORRANGE(int32_t, imm, -32, 63) {
3074        StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
3075                        MachineType::Int32());
3076        Node* const p0 = m.Parameter(0);
3077        Node* const p1 = m.Parameter(1);
3078        Node* r = (m.*shift.mi.constructor)(p1, m.Int32Constant(imm));
3079        m.Return(
3080            (m.*cmp.mi.constructor)(p0, m.Int32Sub(m.Int32Constant(0), r)));
3081        Stream s = m.Build();
3082        ASSERT_EQ(1U, s.size());
3083        EXPECT_EQ(kArm64Cmn32, s[0]->arch_opcode());
3084        EXPECT_EQ(3U, s[0]->InputCount());
3085        EXPECT_EQ(shift.mode, s[0]->addressing_mode());
3086        EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2)));
3087        EXPECT_EQ(1U, s[0]->OutputCount());
3088        EXPECT_EQ(kFlags_set, s[0]->flags_mode());
3089        EXPECT_EQ(cmp.cond, s[0]->flags_condition());
3090      }
3091    }
3092  }
3093}
3094
3095TEST_F(InstructionSelectorTest, CmpWithImmediateOnLeft) {
3096  TRACED_FOREACH(IntegerCmp, cmp, kIntegerCmpInstructions) {
3097    TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
3098      // kEqual and kNotEqual trigger the cbz/cbnz optimization, which
3099      // is tested elsewhere.
3100      if (cmp.cond == kEqual || cmp.cond == kNotEqual) continue;
3101      StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
3102      Node* const p0 = m.Parameter(0);
3103      RawMachineLabel a, b;
3104      m.Branch((m.*cmp.mi.constructor)(m.Int32Constant(imm), p0), &a, &b);
3105      m.Bind(&a);
3106      m.Return(m.Int32Constant(1));
3107      m.Bind(&b);
3108      m.Return(m.Int32Constant(0));
3109      Stream s = m.Build();
3110      ASSERT_EQ(1U, s.size());
3111      EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode());
3112      ASSERT_LE(2U, s[0]->InputCount());
3113      EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
3114      EXPECT_EQ(cmp.commuted_cond, s[0]->flags_condition());
3115      EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
3116    }
3117  }
3118}
3119
3120TEST_F(InstructionSelectorTest, CmnWithImmediateOnLeft) {
3121  TRACED_FOREACH(IntegerCmp, cmp, kIntegerCmpInstructions) {
3122    TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
3123      // kEqual and kNotEqual trigger the cbz/cbnz optimization, which
3124      // is tested elsewhere.
3125      if (cmp.cond == kEqual || cmp.cond == kNotEqual) continue;
3126      StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
3127      Node* sub = m.Int32Sub(m.Int32Constant(0), m.Parameter(0));
3128      RawMachineLabel a, b;
3129      m.Branch((m.*cmp.mi.constructor)(m.Int32Constant(imm), sub), &a, &b);
3130      m.Bind(&a);
3131      m.Return(m.Int32Constant(1));
3132      m.Bind(&b);
3133      m.Return(m.Int32Constant(0));
3134      Stream s = m.Build();
3135      ASSERT_EQ(1U, s.size());
3136      EXPECT_EQ(kArm64Cmn32, s[0]->arch_opcode());
3137      ASSERT_LE(2U, s[0]->InputCount());
3138      EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
3139      EXPECT_EQ(cmp.cond, s[0]->flags_condition());
3140      EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
3141    }
3142  }
3143}
3144
3145TEST_F(InstructionSelectorTest, CmpSignedExtendByteOnLeft) {
3146  TRACED_FOREACH(IntegerCmp, cmp, kIntegerCmpInstructions) {
3147    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
3148                    MachineType::Int32());
3149    Node* extend = m.Word32Sar(m.Word32Shl(m.Parameter(0), m.Int32Constant(24)),
3150                               m.Int32Constant(24));
3151    m.Return((m.*cmp.mi.constructor)(extend, m.Parameter(1)));
3152    Stream s = m.Build();
3153    ASSERT_EQ(1U, s.size());
3154    EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode());
3155    EXPECT_EQ(kFlags_set, s[0]->flags_mode());
3156    EXPECT_EQ(cmp.commuted_cond, s[0]->flags_condition());
3157    EXPECT_EQ(kMode_Operand2_R_SXTB, s[0]->addressing_mode());
3158  }
3159}
3160
3161TEST_F(InstructionSelectorTest, CmnSignedExtendByteOnLeft) {
3162  TRACED_FOREACH(IntegerCmp, cmp, kIntegerCmpInstructions) {
3163    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
3164                    MachineType::Int32());
3165    Node* sub = m.Int32Sub(m.Int32Constant(0), m.Parameter(0));
3166    Node* extend = m.Word32Sar(m.Word32Shl(m.Parameter(0), m.Int32Constant(24)),
3167                               m.Int32Constant(24));
3168    m.Return((m.*cmp.mi.constructor)(extend, sub));
3169    Stream s = m.Build();
3170    ASSERT_EQ(1U, s.size());
3171    EXPECT_EQ(kArm64Cmn32, s[0]->arch_opcode());
3172    EXPECT_EQ(kFlags_set, s[0]->flags_mode());
3173    EXPECT_EQ(cmp.cond, s[0]->flags_condition());
3174    EXPECT_EQ(kMode_Operand2_R_SXTB, s[0]->addressing_mode());
3175  }
3176}
3177
3178TEST_F(InstructionSelectorTest, CmpShiftByImmediateOnLeft) {
3179  TRACED_FOREACH(IntegerCmp, cmp, kIntegerCmpInstructions) {
3180    TRACED_FOREACH(Shift, shift, kShiftInstructions) {
3181      // Only test relevant shifted operands.
3182      if (shift.mi.machine_type != MachineType::Int32()) continue;
3183
3184      // The available shift operand range is `0 <= imm < 32`, but we also test
3185      // that immediates outside this range are handled properly (modulo-32).
3186      TRACED_FORRANGE(int, imm, -32, 63) {
3187        StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
3188                        MachineType::Int32());
3189        m.Return((m.*cmp.mi.constructor)(
3190            (m.*shift.mi.constructor)(m.Parameter(1), m.Int32Constant(imm)),
3191            m.Parameter(0)));
3192        Stream s = m.Build();
3193        // Cmp does not support ROR shifts.
3194        if (shift.mi.arch_opcode == kArm64Ror32) {
3195          ASSERT_EQ(2U, s.size());
3196          continue;
3197        }
3198        ASSERT_EQ(1U, s.size());
3199        EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode());
3200        EXPECT_EQ(shift.mode, s[0]->addressing_mode());
3201        EXPECT_EQ(3U, s[0]->InputCount());
3202        EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(2)));
3203        EXPECT_EQ(1U, s[0]->OutputCount());
3204        EXPECT_EQ(kFlags_set, s[0]->flags_mode());
3205        EXPECT_EQ(cmp.commuted_cond, s[0]->flags_condition());
3206      }
3207    }
3208  }
3209}
3210
3211TEST_F(InstructionSelectorTest, CmnShiftByImmediateOnLeft) {
3212  TRACED_FOREACH(IntegerCmp, cmp, kIntegerCmpInstructions) {
3213    TRACED_FOREACH(Shift, shift, kShiftInstructions) {
3214      // Only test relevant shifted operands.
3215      if (shift.mi.machine_type != MachineType::Int32()) continue;
3216
3217      // The available shift operand range is `0 <= imm < 32`, but we also test
3218      // that immediates outside this range are handled properly (modulo-32).
3219      TRACED_FORRANGE(int, imm, -32, 63) {
3220        StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
3221                        MachineType::Int32());
3222        Node* sub = m.Int32Sub(m.Int32Constant(0), m.Parameter(0));
3223        m.Return((m.*cmp.mi.constructor)(
3224            (m.*shift.mi.constructor)(m.Parameter(1), m.Int32Constant(imm)),
3225            sub));
3226        Stream s = m.Build();
3227        // Cmn does not support ROR shifts.
3228        if (shift.mi.arch_opcode == kArm64Ror32) {
3229          ASSERT_EQ(2U, s.size());
3230          continue;
3231        }
3232        ASSERT_EQ(1U, s.size());
3233        EXPECT_EQ(kArm64Cmn32, s[0]->arch_opcode());
3234        EXPECT_EQ(shift.mode, s[0]->addressing_mode());
3235        EXPECT_EQ(3U, s[0]->InputCount());
3236        EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(2)));
3237        EXPECT_EQ(1U, s[0]->OutputCount());
3238        EXPECT_EQ(kFlags_set, s[0]->flags_mode());
3239        EXPECT_EQ(cmp.cond, s[0]->flags_condition());
3240      }
3241    }
3242  }
3243}
3244
3245
3246// -----------------------------------------------------------------------------
3247// Miscellaneous
3248
3249
3250static const MachInst2 kLogicalWithNotRHSs[] = {
3251    {&RawMachineAssembler::Word32And, "Word32And", kArm64Bic32,
3252     MachineType::Int32()},
3253    {&RawMachineAssembler::Word64And, "Word64And", kArm64Bic,
3254     MachineType::Int64()},
3255    {&RawMachineAssembler::Word32Or, "Word32Or", kArm64Orn32,
3256     MachineType::Int32()},
3257    {&RawMachineAssembler::Word64Or, "Word64Or", kArm64Orn,
3258     MachineType::Int64()},
3259    {&RawMachineAssembler::Word32Xor, "Word32Xor", kArm64Eon32,
3260     MachineType::Int32()},
3261    {&RawMachineAssembler::Word64Xor, "Word64Xor", kArm64Eon,
3262     MachineType::Int64()}};
3263
3264
3265typedef InstructionSelectorTestWithParam<MachInst2>
3266    InstructionSelectorLogicalWithNotRHSTest;
3267
3268
3269TEST_P(InstructionSelectorLogicalWithNotRHSTest, Parameter) {
3270  const MachInst2 inst = GetParam();
3271  const MachineType type = inst.machine_type;
3272  // Test cases where RHS is Xor(x, -1).
3273  {
3274    StreamBuilder m(this, type, type, type);
3275    if (type == MachineType::Int32()) {
3276      m.Return((m.*inst.constructor)(
3277          m.Parameter(0), m.Word32Xor(m.Parameter(1), m.Int32Constant(-1))));
3278    } else {
3279      ASSERT_EQ(MachineType::Int64(), type);
3280      m.Return((m.*inst.constructor)(
3281          m.Parameter(0), m.Word64Xor(m.Parameter(1), m.Int64Constant(-1))));
3282    }
3283    Stream s = m.Build();
3284    ASSERT_EQ(1U, s.size());
3285    EXPECT_EQ(inst.arch_opcode, s[0]->arch_opcode());
3286    EXPECT_EQ(2U, s[0]->InputCount());
3287    EXPECT_EQ(1U, s[0]->OutputCount());
3288  }
3289  {
3290    StreamBuilder m(this, type, type, type);
3291    if (type == MachineType::Int32()) {
3292      m.Return((m.*inst.constructor)(
3293          m.Word32Xor(m.Parameter(0), m.Int32Constant(-1)), m.Parameter(1)));
3294    } else {
3295      ASSERT_EQ(MachineType::Int64(), type);
3296      m.Return((m.*inst.constructor)(
3297          m.Word64Xor(m.Parameter(0), m.Int64Constant(-1)), m.Parameter(1)));
3298    }
3299    Stream s = m.Build();
3300    ASSERT_EQ(1U, s.size());
3301    EXPECT_EQ(inst.arch_opcode, s[0]->arch_opcode());
3302    EXPECT_EQ(2U, s[0]->InputCount());
3303    EXPECT_EQ(1U, s[0]->OutputCount());
3304  }
3305  // Test cases where RHS is Not(x).
3306  {
3307    StreamBuilder m(this, type, type, type);
3308    if (type == MachineType::Int32()) {
3309      m.Return(
3310          (m.*inst.constructor)(m.Parameter(0), m.Word32Not(m.Parameter(1))));
3311    } else {
3312      ASSERT_EQ(MachineType::Int64(), type);
3313      m.Return(
3314          (m.*inst.constructor)(m.Parameter(0), m.Word64Not(m.Parameter(1))));
3315    }
3316    Stream s = m.Build();
3317    ASSERT_EQ(1U, s.size());
3318    EXPECT_EQ(inst.arch_opcode, s[0]->arch_opcode());
3319    EXPECT_EQ(2U, s[0]->InputCount());
3320    EXPECT_EQ(1U, s[0]->OutputCount());
3321  }
3322  {
3323    StreamBuilder m(this, type, type, type);
3324    if (type == MachineType::Int32()) {
3325      m.Return(
3326          (m.*inst.constructor)(m.Word32Not(m.Parameter(0)), m.Parameter(1)));
3327    } else {
3328      ASSERT_EQ(MachineType::Int64(), type);
3329      m.Return(
3330          (m.*inst.constructor)(m.Word64Not(m.Parameter(0)), m.Parameter(1)));
3331    }
3332    Stream s = m.Build();
3333    ASSERT_EQ(1U, s.size());
3334    EXPECT_EQ(inst.arch_opcode, s[0]->arch_opcode());
3335    EXPECT_EQ(2U, s[0]->InputCount());
3336    EXPECT_EQ(1U, s[0]->OutputCount());
3337  }
3338}
3339
3340
3341INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
3342                        InstructionSelectorLogicalWithNotRHSTest,
3343                        ::testing::ValuesIn(kLogicalWithNotRHSs));
3344
3345
3346TEST_F(InstructionSelectorTest, Word32NotWithParameter) {
3347  StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
3348  m.Return(m.Word32Not(m.Parameter(0)));
3349  Stream s = m.Build();
3350  ASSERT_EQ(1U, s.size());
3351  EXPECT_EQ(kArm64Not32, s[0]->arch_opcode());
3352  EXPECT_EQ(1U, s[0]->InputCount());
3353  EXPECT_EQ(1U, s[0]->OutputCount());
3354}
3355
3356
3357TEST_F(InstructionSelectorTest, Word64NotWithParameter) {
3358  StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
3359  m.Return(m.Word64Not(m.Parameter(0)));
3360  Stream s = m.Build();
3361  ASSERT_EQ(1U, s.size());
3362  EXPECT_EQ(kArm64Not, s[0]->arch_opcode());
3363  EXPECT_EQ(1U, s[0]->InputCount());
3364  EXPECT_EQ(1U, s[0]->OutputCount());
3365}
3366
3367
3368TEST_F(InstructionSelectorTest, Word32XorMinusOneWithParameter) {
3369  {
3370    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
3371    m.Return(m.Word32Xor(m.Parameter(0), m.Int32Constant(-1)));
3372    Stream s = m.Build();
3373    ASSERT_EQ(1U, s.size());
3374    EXPECT_EQ(kArm64Not32, s[0]->arch_opcode());
3375    EXPECT_EQ(1U, s[0]->InputCount());
3376    EXPECT_EQ(1U, s[0]->OutputCount());
3377  }
3378  {
3379    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
3380    m.Return(m.Word32Xor(m.Int32Constant(-1), m.Parameter(0)));
3381    Stream s = m.Build();
3382    ASSERT_EQ(1U, s.size());
3383    EXPECT_EQ(kArm64Not32, s[0]->arch_opcode());
3384    EXPECT_EQ(1U, s[0]->InputCount());
3385    EXPECT_EQ(1U, s[0]->OutputCount());
3386  }
3387}
3388
3389
3390TEST_F(InstructionSelectorTest, Word64XorMinusOneWithParameter) {
3391  {
3392    StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
3393    m.Return(m.Word64Xor(m.Parameter(0), m.Int64Constant(-1)));
3394    Stream s = m.Build();
3395    ASSERT_EQ(1U, s.size());
3396    EXPECT_EQ(kArm64Not, s[0]->arch_opcode());
3397    EXPECT_EQ(1U, s[0]->InputCount());
3398    EXPECT_EQ(1U, s[0]->OutputCount());
3399  }
3400  {
3401    StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
3402    m.Return(m.Word64Xor(m.Int64Constant(-1), m.Parameter(0)));
3403    Stream s = m.Build();
3404    ASSERT_EQ(1U, s.size());
3405    EXPECT_EQ(kArm64Not, s[0]->arch_opcode());
3406    EXPECT_EQ(1U, s[0]->InputCount());
3407    EXPECT_EQ(1U, s[0]->OutputCount());
3408  }
3409}
3410
3411
3412TEST_F(InstructionSelectorTest, Word32ShrWithWord32AndWithImmediate) {
3413  // The available shift operand range is `0 <= imm < 32`, but we also test
3414  // that immediates outside this range are handled properly (modulo-32).
3415  TRACED_FORRANGE(int32_t, shift, -32, 63) {
3416    int32_t lsb = shift & 0x1f;
3417    TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) {
3418      uint32_t jnk = rng()->NextInt();
3419      jnk = (lsb > 0) ? (jnk >> (32 - lsb)) : 0;
3420      uint32_t msk = ((0xffffffffu >> (32 - width)) << lsb) | jnk;
3421      StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
3422      m.Return(m.Word32Shr(m.Word32And(m.Parameter(0), m.Int32Constant(msk)),
3423                           m.Int32Constant(shift)));
3424      Stream s = m.Build();
3425      ASSERT_EQ(1U, s.size());
3426      EXPECT_EQ(kArm64Ubfx32, s[0]->arch_opcode());
3427      ASSERT_EQ(3U, s[0]->InputCount());
3428      EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
3429      EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
3430    }
3431  }
3432  TRACED_FORRANGE(int32_t, shift, -32, 63) {
3433    int32_t lsb = shift & 0x1f;
3434    TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) {
3435      uint32_t jnk = rng()->NextInt();
3436      jnk = (lsb > 0) ? (jnk >> (32 - lsb)) : 0;
3437      uint32_t msk = ((0xffffffffu >> (32 - width)) << lsb) | jnk;
3438      StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
3439      m.Return(m.Word32Shr(m.Word32And(m.Int32Constant(msk), m.Parameter(0)),
3440                           m.Int32Constant(shift)));
3441      Stream s = m.Build();
3442      ASSERT_EQ(1U, s.size());
3443      EXPECT_EQ(kArm64Ubfx32, s[0]->arch_opcode());
3444      ASSERT_EQ(3U, s[0]->InputCount());
3445      EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
3446      EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
3447    }
3448  }
3449}
3450
3451
3452TEST_F(InstructionSelectorTest, Word64ShrWithWord64AndWithImmediate) {
3453  // The available shift operand range is `0 <= imm < 64`, but we also test
3454  // that immediates outside this range are handled properly (modulo-64).
3455  TRACED_FORRANGE(int32_t, shift, -64, 127) {
3456    int32_t lsb = shift & 0x3f;
3457    TRACED_FORRANGE(int32_t, width, 1, 64 - lsb) {
3458      uint64_t jnk = rng()->NextInt64();
3459      jnk = (lsb > 0) ? (jnk >> (64 - lsb)) : 0;
3460      uint64_t msk =
3461          ((V8_UINT64_C(0xffffffffffffffff) >> (64 - width)) << lsb) | jnk;
3462      StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
3463      m.Return(m.Word64Shr(m.Word64And(m.Parameter(0), m.Int64Constant(msk)),
3464                           m.Int64Constant(shift)));
3465      Stream s = m.Build();
3466      ASSERT_EQ(1U, s.size());
3467      EXPECT_EQ(kArm64Ubfx, s[0]->arch_opcode());
3468      ASSERT_EQ(3U, s[0]->InputCount());
3469      EXPECT_EQ(lsb, s.ToInt64(s[0]->InputAt(1)));
3470      EXPECT_EQ(width, s.ToInt64(s[0]->InputAt(2)));
3471    }
3472  }
3473  TRACED_FORRANGE(int32_t, shift, -64, 127) {
3474    int32_t lsb = shift & 0x3f;
3475    TRACED_FORRANGE(int32_t, width, 1, 64 - lsb) {
3476      uint64_t jnk = rng()->NextInt64();
3477      jnk = (lsb > 0) ? (jnk >> (64 - lsb)) : 0;
3478      uint64_t msk =
3479          ((V8_UINT64_C(0xffffffffffffffff) >> (64 - width)) << lsb) | jnk;
3480      StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
3481      m.Return(m.Word64Shr(m.Word64And(m.Int64Constant(msk), m.Parameter(0)),
3482                           m.Int64Constant(shift)));
3483      Stream s = m.Build();
3484      ASSERT_EQ(1U, s.size());
3485      EXPECT_EQ(kArm64Ubfx, s[0]->arch_opcode());
3486      ASSERT_EQ(3U, s[0]->InputCount());
3487      EXPECT_EQ(lsb, s.ToInt64(s[0]->InputAt(1)));
3488      EXPECT_EQ(width, s.ToInt64(s[0]->InputAt(2)));
3489    }
3490  }
3491}
3492
3493
3494TEST_F(InstructionSelectorTest, Word32AndWithImmediateWithWord32Shr) {
3495  // The available shift operand range is `0 <= imm < 32`, but we also test
3496  // that immediates outside this range are handled properly (modulo-32).
3497  TRACED_FORRANGE(int32_t, shift, -32, 63) {
3498    int32_t lsb = shift & 0x1f;
3499    TRACED_FORRANGE(int32_t, width, 1, 31) {
3500      uint32_t msk = (1 << width) - 1;
3501      StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
3502      m.Return(m.Word32And(m.Word32Shr(m.Parameter(0), m.Int32Constant(shift)),
3503                           m.Int32Constant(msk)));
3504      Stream s = m.Build();
3505      ASSERT_EQ(1U, s.size());
3506      EXPECT_EQ(kArm64Ubfx32, s[0]->arch_opcode());
3507      ASSERT_EQ(3U, s[0]->InputCount());
3508      EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
3509      int32_t actual_width = (lsb + width > 32) ? (32 - lsb) : width;
3510      EXPECT_EQ(actual_width, s.ToInt32(s[0]->InputAt(2)));
3511    }
3512  }
3513  TRACED_FORRANGE(int32_t, shift, -32, 63) {
3514    int32_t lsb = shift & 0x1f;
3515    TRACED_FORRANGE(int32_t, width, 1, 31) {
3516      uint32_t msk = (1 << width) - 1;
3517      StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
3518      m.Return(
3519          m.Word32And(m.Int32Constant(msk),
3520                      m.Word32Shr(m.Parameter(0), m.Int32Constant(shift))));
3521      Stream s = m.Build();
3522      ASSERT_EQ(1U, s.size());
3523      EXPECT_EQ(kArm64Ubfx32, s[0]->arch_opcode());
3524      ASSERT_EQ(3U, s[0]->InputCount());
3525      EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
3526      int32_t actual_width = (lsb + width > 32) ? (32 - lsb) : width;
3527      EXPECT_EQ(actual_width, s.ToInt32(s[0]->InputAt(2)));
3528    }
3529  }
3530}
3531
3532
3533TEST_F(InstructionSelectorTest, Word64AndWithImmediateWithWord64Shr) {
3534  // The available shift operand range is `0 <= imm < 64`, but we also test
3535  // that immediates outside this range are handled properly (modulo-64).
3536  TRACED_FORRANGE(int64_t, shift, -64, 127) {
3537    int64_t lsb = shift & 0x3f;
3538    TRACED_FORRANGE(int64_t, width, 1, 63) {
3539      uint64_t msk = (V8_UINT64_C(1) << width) - 1;
3540      StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
3541      m.Return(m.Word64And(m.Word64Shr(m.Parameter(0), m.Int64Constant(shift)),
3542                           m.Int64Constant(msk)));
3543      Stream s = m.Build();
3544      ASSERT_EQ(1U, s.size());
3545      EXPECT_EQ(kArm64Ubfx, s[0]->arch_opcode());
3546      ASSERT_EQ(3U, s[0]->InputCount());
3547      EXPECT_EQ(lsb, s.ToInt64(s[0]->InputAt(1)));
3548      int64_t actual_width = (lsb + width > 64) ? (64 - lsb) : width;
3549      EXPECT_EQ(actual_width, s.ToInt64(s[0]->InputAt(2)));
3550    }
3551  }
3552  TRACED_FORRANGE(int64_t, shift, -64, 127) {
3553    int64_t lsb = shift & 0x3f;
3554    TRACED_FORRANGE(int64_t, width, 1, 63) {
3555      uint64_t msk = (V8_UINT64_C(1) << width) - 1;
3556      StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
3557      m.Return(
3558          m.Word64And(m.Int64Constant(msk),
3559                      m.Word64Shr(m.Parameter(0), m.Int64Constant(shift))));
3560      Stream s = m.Build();
3561      ASSERT_EQ(1U, s.size());
3562      EXPECT_EQ(kArm64Ubfx, s[0]->arch_opcode());
3563      ASSERT_EQ(3U, s[0]->InputCount());
3564      EXPECT_EQ(lsb, s.ToInt64(s[0]->InputAt(1)));
3565      int64_t actual_width = (lsb + width > 64) ? (64 - lsb) : width;
3566      EXPECT_EQ(actual_width, s.ToInt64(s[0]->InputAt(2)));
3567    }
3568  }
3569}
3570
3571
3572TEST_F(InstructionSelectorTest, Int32MulHighWithParameters) {
3573  StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
3574                  MachineType::Int32());
3575  Node* const p0 = m.Parameter(0);
3576  Node* const p1 = m.Parameter(1);
3577  Node* const n = m.Int32MulHigh(p0, p1);
3578  m.Return(n);
3579  Stream s = m.Build();
3580  ASSERT_EQ(2U, s.size());
3581  EXPECT_EQ(kArm64Smull, s[0]->arch_opcode());
3582  ASSERT_EQ(2U, s[0]->InputCount());
3583  EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
3584  EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
3585  ASSERT_EQ(1U, s[0]->OutputCount());
3586  EXPECT_EQ(kArm64Asr, s[1]->arch_opcode());
3587  ASSERT_EQ(2U, s[1]->InputCount());
3588  EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(0)));
3589  EXPECT_EQ(32, s.ToInt64(s[1]->InputAt(1)));
3590  ASSERT_EQ(1U, s[1]->OutputCount());
3591  EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[1]->Output()));
3592}
3593
3594
3595TEST_F(InstructionSelectorTest, Int32MulHighWithSar) {
3596  TRACED_FORRANGE(int32_t, shift, -32, 63) {
3597    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
3598                    MachineType::Int32());
3599    Node* const p0 = m.Parameter(0);
3600    Node* const p1 = m.Parameter(1);
3601    Node* const n = m.Word32Sar(m.Int32MulHigh(p0, p1), m.Int32Constant(shift));
3602    m.Return(n);
3603    Stream s = m.Build();
3604    ASSERT_EQ(2U, s.size());
3605    EXPECT_EQ(kArm64Smull, s[0]->arch_opcode());
3606    ASSERT_EQ(2U, s[0]->InputCount());
3607    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
3608    EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
3609    ASSERT_EQ(1U, s[0]->OutputCount());
3610    EXPECT_EQ(kArm64Asr, s[1]->arch_opcode());
3611    ASSERT_EQ(2U, s[1]->InputCount());
3612    EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(0)));
3613    EXPECT_EQ((shift & 0x1f) + 32, s.ToInt64(s[1]->InputAt(1)));
3614    ASSERT_EQ(1U, s[1]->OutputCount());
3615    EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[1]->Output()));
3616  }
3617}
3618
3619
3620TEST_F(InstructionSelectorTest, Int32MulHighWithAdd) {
3621  StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
3622                  MachineType::Int32());
3623  Node* const p0 = m.Parameter(0);
3624  Node* const p1 = m.Parameter(1);
3625  Node* const a = m.Int32Add(m.Int32MulHigh(p0, p1), p0);
3626  // Test only one shift constant here, as we're only interested in it being a
3627  // 32-bit operation; the shift amount is irrelevant.
3628  Node* const n = m.Word32Sar(a, m.Int32Constant(1));
3629  m.Return(n);
3630  Stream s = m.Build();
3631  ASSERT_EQ(3U, s.size());
3632  EXPECT_EQ(kArm64Smull, s[0]->arch_opcode());
3633  ASSERT_EQ(2U, s[0]->InputCount());
3634  EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
3635  EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
3636  ASSERT_EQ(1U, s[0]->OutputCount());
3637  EXPECT_EQ(kArm64Add, s[1]->arch_opcode());
3638  EXPECT_EQ(kMode_Operand2_R_ASR_I, s[1]->addressing_mode());
3639  ASSERT_EQ(3U, s[1]->InputCount());
3640  EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[1]->InputAt(0)));
3641  EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(1)));
3642  EXPECT_EQ(32, s.ToInt64(s[1]->InputAt(2)));
3643  ASSERT_EQ(1U, s[1]->OutputCount());
3644  EXPECT_EQ(kArm64Asr32, s[2]->arch_opcode());
3645  ASSERT_EQ(2U, s[2]->InputCount());
3646  EXPECT_EQ(s.ToVreg(s[1]->Output()), s.ToVreg(s[2]->InputAt(0)));
3647  EXPECT_EQ(1, s.ToInt64(s[2]->InputAt(1)));
3648  ASSERT_EQ(1U, s[2]->OutputCount());
3649  EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[2]->Output()));
3650}
3651
3652
3653TEST_F(InstructionSelectorTest, Uint32MulHighWithShr) {
3654  TRACED_FORRANGE(int32_t, shift, -32, 63) {
3655    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
3656                    MachineType::Int32());
3657    Node* const p0 = m.Parameter(0);
3658    Node* const p1 = m.Parameter(1);
3659    Node* const n =
3660        m.Word32Shr(m.Uint32MulHigh(p0, p1), m.Int32Constant(shift));
3661    m.Return(n);
3662    Stream s = m.Build();
3663    ASSERT_EQ(2U, s.size());
3664    EXPECT_EQ(kArm64Umull, s[0]->arch_opcode());
3665    ASSERT_EQ(2U, s[0]->InputCount());
3666    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
3667    EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
3668    ASSERT_EQ(1U, s[0]->OutputCount());
3669    EXPECT_EQ(kArm64Lsr, s[1]->arch_opcode());
3670    ASSERT_EQ(2U, s[1]->InputCount());
3671    EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(0)));
3672    EXPECT_EQ((shift & 0x1f) + 32, s.ToInt64(s[1]->InputAt(1)));
3673    ASSERT_EQ(1U, s[1]->OutputCount());
3674    EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[1]->Output()));
3675  }
3676}
3677
3678
3679TEST_F(InstructionSelectorTest, Word32SarWithWord32Shl) {
3680  TRACED_FORRANGE(int32_t, shift, 1, 31) {
3681    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
3682    Node* const p0 = m.Parameter(0);
3683    Node* const r = m.Word32Sar(m.Word32Shl(p0, m.Int32Constant(shift)),
3684                                m.Int32Constant(shift));
3685    m.Return(r);
3686    Stream s = m.Build();
3687    ASSERT_EQ(1U, s.size());
3688    EXPECT_EQ(kArm64Sbfx32, s[0]->arch_opcode());
3689    ASSERT_EQ(3U, s[0]->InputCount());
3690    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
3691    ASSERT_EQ(1U, s[0]->OutputCount());
3692    EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
3693  }
3694  TRACED_FORRANGE(int32_t, shift, 1, 31) {
3695    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
3696    Node* const p0 = m.Parameter(0);
3697    Node* const r = m.Word32Sar(m.Word32Shl(p0, m.Int32Constant(shift + 32)),
3698                                m.Int32Constant(shift + 64));
3699    m.Return(r);
3700    Stream s = m.Build();
3701    ASSERT_EQ(1U, s.size());
3702    EXPECT_EQ(kArm64Sbfx32, s[0]->arch_opcode());
3703    ASSERT_EQ(3U, s[0]->InputCount());
3704    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
3705    ASSERT_EQ(1U, s[0]->OutputCount());
3706    EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
3707  }
3708}
3709
3710
3711TEST_F(InstructionSelectorTest, Word32ShrWithWord32Shl) {
3712  TRACED_FORRANGE(int32_t, shift, 1, 31) {
3713    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
3714    Node* const p0 = m.Parameter(0);
3715    Node* const r = m.Word32Shr(m.Word32Shl(p0, m.Int32Constant(shift)),
3716                                m.Int32Constant(shift));
3717    m.Return(r);
3718    Stream s = m.Build();
3719    ASSERT_EQ(1U, s.size());
3720    EXPECT_EQ(kArm64Ubfx32, s[0]->arch_opcode());
3721    ASSERT_EQ(3U, s[0]->InputCount());
3722    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
3723    ASSERT_EQ(1U, s[0]->OutputCount());
3724    EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
3725  }
3726  TRACED_FORRANGE(int32_t, shift, 1, 31) {
3727    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
3728    Node* const p0 = m.Parameter(0);
3729    Node* const r = m.Word32Shr(m.Word32Shl(p0, m.Int32Constant(shift + 32)),
3730                                m.Int32Constant(shift + 64));
3731    m.Return(r);
3732    Stream s = m.Build();
3733    ASSERT_EQ(1U, s.size());
3734    EXPECT_EQ(kArm64Ubfx32, s[0]->arch_opcode());
3735    ASSERT_EQ(3U, s[0]->InputCount());
3736    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
3737    ASSERT_EQ(1U, s[0]->OutputCount());
3738    EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
3739  }
3740}
3741
3742
3743TEST_F(InstructionSelectorTest, Word32ShlWithWord32And) {
3744  TRACED_FORRANGE(int32_t, shift, 1, 30) {
3745    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
3746    Node* const p0 = m.Parameter(0);
3747    Node* const r =
3748        m.Word32Shl(m.Word32And(p0, m.Int32Constant((1 << (31 - shift)) - 1)),
3749                    m.Int32Constant(shift));
3750    m.Return(r);
3751    Stream s = m.Build();
3752    ASSERT_EQ(1U, s.size());
3753    EXPECT_EQ(kArm64Ubfiz32, s[0]->arch_opcode());
3754    ASSERT_EQ(3U, s[0]->InputCount());
3755    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
3756    ASSERT_EQ(1U, s[0]->OutputCount());
3757    EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
3758  }
3759  TRACED_FORRANGE(int32_t, shift, 0, 30) {
3760    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
3761    Node* const p0 = m.Parameter(0);
3762    Node* const r =
3763        m.Word32Shl(m.Word32And(p0, m.Int32Constant((1 << (31 - shift)) - 1)),
3764                    m.Int32Constant(shift + 1));
3765    m.Return(r);
3766    Stream s = m.Build();
3767    ASSERT_EQ(1U, s.size());
3768    EXPECT_EQ(kArm64Lsl32, s[0]->arch_opcode());
3769    ASSERT_EQ(2U, s[0]->InputCount());
3770    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
3771    ASSERT_EQ(1U, s[0]->OutputCount());
3772    EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
3773  }
3774}
3775
3776
3777TEST_F(InstructionSelectorTest, Word32Clz) {
3778  StreamBuilder m(this, MachineType::Uint32(), MachineType::Uint32());
3779  Node* const p0 = m.Parameter(0);
3780  Node* const n = m.Word32Clz(p0);
3781  m.Return(n);
3782  Stream s = m.Build();
3783  ASSERT_EQ(1U, s.size());
3784  EXPECT_EQ(kArm64Clz32, s[0]->arch_opcode());
3785  ASSERT_EQ(1U, s[0]->InputCount());
3786  EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
3787  ASSERT_EQ(1U, s[0]->OutputCount());
3788  EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
3789}
3790
3791
3792TEST_F(InstructionSelectorTest, Float32Abs) {
3793  StreamBuilder m(this, MachineType::Float32(), MachineType::Float32());
3794  Node* const p0 = m.Parameter(0);
3795  Node* const n = m.Float32Abs(p0);
3796  m.Return(n);
3797  Stream s = m.Build();
3798  ASSERT_EQ(1U, s.size());
3799  EXPECT_EQ(kArm64Float32Abs, s[0]->arch_opcode());
3800  ASSERT_EQ(1U, s[0]->InputCount());
3801  EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
3802  ASSERT_EQ(1U, s[0]->OutputCount());
3803  EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
3804}
3805
3806
3807TEST_F(InstructionSelectorTest, Float64Abs) {
3808  StreamBuilder m(this, MachineType::Float64(), MachineType::Float64());
3809  Node* const p0 = m.Parameter(0);
3810  Node* const n = m.Float64Abs(p0);
3811  m.Return(n);
3812  Stream s = m.Build();
3813  ASSERT_EQ(1U, s.size());
3814  EXPECT_EQ(kArm64Float64Abs, s[0]->arch_opcode());
3815  ASSERT_EQ(1U, s[0]->InputCount());
3816  EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
3817  ASSERT_EQ(1U, s[0]->OutputCount());
3818  EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
3819}
3820
3821
3822TEST_F(InstructionSelectorTest, Float64SubWithMinusZero) {
3823  StreamBuilder m(this, MachineType::Float64(), MachineType::Float64());
3824  Node* const p0 = m.Parameter(0);
3825  Node* const n = m.Float64Sub(m.Float64Constant(-0.0), p0);
3826  m.Return(n);
3827  Stream s = m.Build();
3828  ASSERT_EQ(1U, s.size());
3829  EXPECT_EQ(kArm64Float64Neg, s[0]->arch_opcode());
3830  ASSERT_EQ(1U, s[0]->InputCount());
3831  EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
3832  ASSERT_EQ(1U, s[0]->OutputCount());
3833  EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
3834}
3835
3836
3837TEST_F(InstructionSelectorTest, Float32Max) {
3838  StreamBuilder m(this, MachineType::Float32(), MachineType::Float32(),
3839                  MachineType::Float32());
3840  Node* const p0 = m.Parameter(0);
3841  Node* const p1 = m.Parameter(1);
3842  Node* const n = m.Float32Max(p0, p1);
3843  m.Return(n);
3844  Stream s = m.Build();
3845  // Float32Max is `(b < a) ? a : b`.
3846  ASSERT_EQ(1U, s.size());
3847  EXPECT_EQ(kArm64Float32Max, s[0]->arch_opcode());
3848  ASSERT_EQ(2U, s[0]->InputCount());
3849  EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
3850  EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
3851  ASSERT_EQ(1U, s[0]->OutputCount());
3852  EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
3853}
3854
3855
3856TEST_F(InstructionSelectorTest, Float32Min) {
3857  StreamBuilder m(this, MachineType::Float32(), MachineType::Float32(),
3858                  MachineType::Float32());
3859  Node* const p0 = m.Parameter(0);
3860  Node* const p1 = m.Parameter(1);
3861  Node* const n = m.Float32Min(p0, p1);
3862  m.Return(n);
3863  Stream s = m.Build();
3864  // Float32Min is `(a < b) ? a : b`.
3865  ASSERT_EQ(1U, s.size());
3866  EXPECT_EQ(kArm64Float32Min, s[0]->arch_opcode());
3867  ASSERT_EQ(2U, s[0]->InputCount());
3868  EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
3869  EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
3870  ASSERT_EQ(1U, s[0]->OutputCount());
3871  EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
3872}
3873
3874
3875TEST_F(InstructionSelectorTest, Float64Max) {
3876  StreamBuilder m(this, MachineType::Float64(), MachineType::Float64(),
3877                  MachineType::Float64());
3878  Node* const p0 = m.Parameter(0);
3879  Node* const p1 = m.Parameter(1);
3880  Node* const n = m.Float64Max(p0, p1);
3881  m.Return(n);
3882  Stream s = m.Build();
3883  // Float64Max is `(b < a) ? a : b`.
3884  ASSERT_EQ(1U, s.size());
3885  EXPECT_EQ(kArm64Float64Max, s[0]->arch_opcode());
3886  ASSERT_EQ(2U, s[0]->InputCount());
3887  EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
3888  EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
3889  ASSERT_EQ(1U, s[0]->OutputCount());
3890  EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
3891}
3892
3893
3894TEST_F(InstructionSelectorTest, Float64Min) {
3895  StreamBuilder m(this, MachineType::Float64(), MachineType::Float64(),
3896                  MachineType::Float64());
3897  Node* const p0 = m.Parameter(0);
3898  Node* const p1 = m.Parameter(1);
3899  Node* const n = m.Float64Min(p0, p1);
3900  m.Return(n);
3901  Stream s = m.Build();
3902  // Float64Min is `(a < b) ? a : b`.
3903  ASSERT_EQ(1U, s.size());
3904  EXPECT_EQ(kArm64Float64Min, s[0]->arch_opcode());
3905  ASSERT_EQ(2U, s[0]->InputCount());
3906  EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
3907  EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
3908  ASSERT_EQ(1U, s[0]->OutputCount());
3909  EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
3910}
3911
3912TEST_F(InstructionSelectorTest, Float32Neg) {
3913  StreamBuilder m(this, MachineType::Float32(), MachineType::Float32());
3914  Node* const p0 = m.Parameter(0);
3915  // Don't use m.Float32Neg() as that generates an explicit sub.
3916  Node* const n = m.AddNode(m.machine()->Float32Neg().op(), m.Parameter(0));
3917  m.Return(n);
3918  Stream s = m.Build();
3919  ASSERT_EQ(1U, s.size());
3920  EXPECT_EQ(kArm64Float32Neg, s[0]->arch_opcode());
3921  ASSERT_EQ(1U, s[0]->InputCount());
3922  EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
3923  ASSERT_EQ(1U, s[0]->OutputCount());
3924  EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
3925}
3926
3927TEST_F(InstructionSelectorTest, Float64Neg) {
3928  StreamBuilder m(this, MachineType::Float64(), MachineType::Float64());
3929  Node* const p0 = m.Parameter(0);
3930  // Don't use m.Float64Neg() as that generates an explicit sub.
3931  Node* const n = m.AddNode(m.machine()->Float64Neg().op(), m.Parameter(0));
3932  m.Return(n);
3933  Stream s = m.Build();
3934  ASSERT_EQ(1U, s.size());
3935  EXPECT_EQ(kArm64Float64Neg, s[0]->arch_opcode());
3936  ASSERT_EQ(1U, s[0]->InputCount());
3937  EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
3938  ASSERT_EQ(1U, s[0]->OutputCount());
3939  EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
3940}
3941
3942}  // namespace compiler
3943}  // namespace internal
3944}  // namespace v8
3945