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 <list>
6 
7 #include "src/compiler/instruction-selector-unittest.h"
8 
9 namespace v8 {
10 namespace internal {
11 namespace compiler {
12 
13 namespace {
14 
15 typedef RawMachineAssembler::Label MLabel;
16 
17 template <typename T>
18 struct MachInst {
19   T constructor;
20   const char* constructor_name;
21   ArchOpcode arch_opcode;
22   MachineType machine_type;
23 };
24 
25 typedef MachInst<Node* (RawMachineAssembler::*)(Node*)> MachInst1;
26 typedef MachInst<Node* (RawMachineAssembler::*)(Node*, Node*)> MachInst2;
27 
28 
29 template <typename T>
operator <<(std::ostream & os,const MachInst<T> & mi)30 std::ostream& operator<<(std::ostream& os, const MachInst<T>& mi) {
31   return os << mi.constructor_name;
32 }
33 
34 
35 // Helper to build Int32Constant or Int64Constant depending on the given
36 // machine type.
BuildConstant(InstructionSelectorTest::StreamBuilder & m,MachineType type,int64_t value)37 Node* BuildConstant(InstructionSelectorTest::StreamBuilder& m, MachineType type,
38                     int64_t value) {
39   switch (type) {
40     case kMachInt32:
41       return m.Int32Constant(value);
42       break;
43 
44     case kMachInt64:
45       return m.Int64Constant(value);
46       break;
47 
48     default:
49       UNIMPLEMENTED();
50   }
51   return NULL;
52 }
53 
54 
55 // ARM64 logical instructions.
56 static const MachInst2 kLogicalInstructions[] = {
57     {&RawMachineAssembler::Word32And, "Word32And", kArm64And32, kMachInt32},
58     {&RawMachineAssembler::Word64And, "Word64And", kArm64And, kMachInt64},
59     {&RawMachineAssembler::Word32Or, "Word32Or", kArm64Or32, kMachInt32},
60     {&RawMachineAssembler::Word64Or, "Word64Or", kArm64Or, kMachInt64},
61     {&RawMachineAssembler::Word32Xor, "Word32Xor", kArm64Xor32, kMachInt32},
62     {&RawMachineAssembler::Word64Xor, "Word64Xor", kArm64Xor, kMachInt64}};
63 
64 
65 // ARM64 logical immediates: contiguous set bits, rotated about a power of two
66 // sized block. The block is then duplicated across the word. Below is a random
67 // subset of the 32-bit immediates.
68 static const uint32_t kLogicalImmediates[] = {
69     0x00000002, 0x00000003, 0x00000070, 0x00000080, 0x00000100, 0x000001c0,
70     0x00000300, 0x000007e0, 0x00003ffc, 0x00007fc0, 0x0003c000, 0x0003f000,
71     0x0003ffc0, 0x0003fff8, 0x0007ff00, 0x0007ffe0, 0x000e0000, 0x001e0000,
72     0x001ffffc, 0x003f0000, 0x003f8000, 0x00780000, 0x007fc000, 0x00ff0000,
73     0x01800000, 0x01800180, 0x01f801f8, 0x03fe0000, 0x03ffffc0, 0x03fffffc,
74     0x06000000, 0x07fc0000, 0x07ffc000, 0x07ffffc0, 0x07ffffe0, 0x0ffe0ffe,
75     0x0ffff800, 0x0ffffff0, 0x0fffffff, 0x18001800, 0x1f001f00, 0x1f801f80,
76     0x30303030, 0x3ff03ff0, 0x3ff83ff8, 0x3fff0000, 0x3fff8000, 0x3fffffc0,
77     0x70007000, 0x7f7f7f7f, 0x7fc00000, 0x7fffffc0, 0x8000001f, 0x800001ff,
78     0x81818181, 0x9fff9fff, 0xc00007ff, 0xc0ffffff, 0xdddddddd, 0xe00001ff,
79     0xe00003ff, 0xe007ffff, 0xefffefff, 0xf000003f, 0xf001f001, 0xf3fff3ff,
80     0xf800001f, 0xf80fffff, 0xf87ff87f, 0xfbfbfbfb, 0xfc00001f, 0xfc0000ff,
81     0xfc0001ff, 0xfc03fc03, 0xfe0001ff, 0xff000001, 0xff03ff03, 0xff800000,
82     0xff800fff, 0xff801fff, 0xff87ffff, 0xffc0003f, 0xffc007ff, 0xffcfffcf,
83     0xffe00003, 0xffe1ffff, 0xfff0001f, 0xfff07fff, 0xfff80007, 0xfff87fff,
84     0xfffc00ff, 0xfffe07ff, 0xffff00ff, 0xffffc001, 0xfffff007, 0xfffff3ff,
85     0xfffff807, 0xfffff9ff, 0xfffffc0f, 0xfffffeff};
86 
87 
88 // ARM64 arithmetic instructions.
89 static const MachInst2 kAddSubInstructions[] = {
90     {&RawMachineAssembler::Int32Add, "Int32Add", kArm64Add32, kMachInt32},
91     {&RawMachineAssembler::Int64Add, "Int64Add", kArm64Add, kMachInt64},
92     {&RawMachineAssembler::Int32Sub, "Int32Sub", kArm64Sub32, kMachInt32},
93     {&RawMachineAssembler::Int64Sub, "Int64Sub", kArm64Sub, kMachInt64}};
94 
95 
96 // ARM64 Add/Sub immediates: 12-bit immediate optionally shifted by 12.
97 // Below is a combination of a random subset and some edge values.
98 static const int32_t kAddSubImmediates[] = {
99     0,        1,        69,       493,      599,      701,      719,
100     768,      818,      842,      945,      1246,     1286,     1429,
101     1669,     2171,     2179,     2182,     2254,     2334,     2338,
102     2343,     2396,     2449,     2610,     2732,     2855,     2876,
103     2944,     3377,     3458,     3475,     3476,     3540,     3574,
104     3601,     3813,     3871,     3917,     4095,     4096,     16384,
105     364544,   462848,   970752,   1523712,  1863680,  2363392,  3219456,
106     3280896,  4247552,  4526080,  4575232,  4960256,  5505024,  5894144,
107     6004736,  6193152,  6385664,  6795264,  7114752,  7233536,  7348224,
108     7499776,  7573504,  7729152,  8634368,  8937472,  9465856,  10354688,
109     10682368, 11059200, 11460608, 13168640, 13176832, 14336000, 15028224,
110     15597568, 15892480, 16773120};
111 
112 
113 // ARM64 flag setting data processing instructions.
114 static const MachInst2 kDPFlagSetInstructions[] = {
115     {&RawMachineAssembler::Word32And, "Word32And", kArm64Tst32, kMachInt32},
116     {&RawMachineAssembler::Int32Add, "Int32Add", kArm64Cmn32, kMachInt32},
117     {&RawMachineAssembler::Int32Sub, "Int32Sub", kArm64Cmp32, kMachInt32}};
118 
119 
120 // ARM64 arithmetic with overflow instructions.
121 static const MachInst2 kOvfAddSubInstructions[] = {
122     {&RawMachineAssembler::Int32AddWithOverflow, "Int32AddWithOverflow",
123      kArm64Add32, kMachInt32},
124     {&RawMachineAssembler::Int32SubWithOverflow, "Int32SubWithOverflow",
125      kArm64Sub32, kMachInt32}};
126 
127 
128 // ARM64 shift instructions.
129 static const MachInst2 kShiftInstructions[] = {
130     {&RawMachineAssembler::Word32Shl, "Word32Shl", kArm64Shl32, kMachInt32},
131     {&RawMachineAssembler::Word64Shl, "Word64Shl", kArm64Shl, kMachInt64},
132     {&RawMachineAssembler::Word32Shr, "Word32Shr", kArm64Shr32, kMachInt32},
133     {&RawMachineAssembler::Word64Shr, "Word64Shr", kArm64Shr, kMachInt64},
134     {&RawMachineAssembler::Word32Sar, "Word32Sar", kArm64Sar32, kMachInt32},
135     {&RawMachineAssembler::Word64Sar, "Word64Sar", kArm64Sar, kMachInt64},
136     {&RawMachineAssembler::Word32Ror, "Word32Ror", kArm64Ror32, kMachInt32},
137     {&RawMachineAssembler::Word64Ror, "Word64Ror", kArm64Ror, kMachInt64}};
138 
139 
140 // ARM64 Mul/Div instructions.
141 static const MachInst2 kMulDivInstructions[] = {
142     {&RawMachineAssembler::Int32Mul, "Int32Mul", kArm64Mul32, kMachInt32},
143     {&RawMachineAssembler::Int64Mul, "Int64Mul", kArm64Mul, kMachInt64},
144     {&RawMachineAssembler::Int32Div, "Int32Div", kArm64Idiv32, kMachInt32},
145     {&RawMachineAssembler::Int64Div, "Int64Div", kArm64Idiv, kMachInt64},
146     {&RawMachineAssembler::Int32UDiv, "Int32UDiv", kArm64Udiv32, kMachInt32},
147     {&RawMachineAssembler::Int64UDiv, "Int64UDiv", kArm64Udiv, kMachInt64}};
148 
149 
150 // ARM64 FP arithmetic instructions.
151 static const MachInst2 kFPArithInstructions[] = {
152     {&RawMachineAssembler::Float64Add, "Float64Add", kArm64Float64Add,
153      kMachFloat64},
154     {&RawMachineAssembler::Float64Sub, "Float64Sub", kArm64Float64Sub,
155      kMachFloat64},
156     {&RawMachineAssembler::Float64Mul, "Float64Mul", kArm64Float64Mul,
157      kMachFloat64},
158     {&RawMachineAssembler::Float64Div, "Float64Div", kArm64Float64Div,
159      kMachFloat64}};
160 
161 
162 struct FPCmp {
163   MachInst2 mi;
164   FlagsCondition cond;
165 };
166 
167 
operator <<(std::ostream & os,const FPCmp & cmp)168 std::ostream& operator<<(std::ostream& os, const FPCmp& cmp) {
169   return os << cmp.mi;
170 }
171 
172 
173 // ARM64 FP comparison instructions.
174 static const FPCmp kFPCmpInstructions[] = {
175     {{&RawMachineAssembler::Float64Equal, "Float64Equal", kArm64Float64Cmp,
176       kMachFloat64},
177      kUnorderedEqual},
178     {{&RawMachineAssembler::Float64LessThan, "Float64LessThan",
179       kArm64Float64Cmp, kMachFloat64},
180      kUnorderedLessThan},
181     {{&RawMachineAssembler::Float64LessThanOrEqual, "Float64LessThanOrEqual",
182       kArm64Float64Cmp, kMachFloat64},
183      kUnorderedLessThanOrEqual}};
184 
185 
186 struct Conversion {
187   // The machine_type field in MachInst1 represents the destination type.
188   MachInst1 mi;
189   MachineType src_machine_type;
190 };
191 
192 
operator <<(std::ostream & os,const Conversion & conv)193 std::ostream& operator<<(std::ostream& os, const Conversion& conv) {
194   return os << conv.mi;
195 }
196 
197 
198 // ARM64 type conversion instructions.
199 static const Conversion kConversionInstructions[] = {
200     {{&RawMachineAssembler::ChangeInt32ToInt64, "ChangeInt32ToInt64",
201       kArm64Sxtw, kMachInt64},
202      kMachInt32},
203     {{&RawMachineAssembler::ChangeUint32ToUint64, "ChangeUint32ToUint64",
204       kArm64Mov32, kMachUint64},
205      kMachUint32},
206     {{&RawMachineAssembler::TruncateInt64ToInt32, "TruncateInt64ToInt32",
207       kArm64Mov32, kMachInt32},
208      kMachInt64},
209     {{&RawMachineAssembler::ChangeInt32ToFloat64, "ChangeInt32ToFloat64",
210       kArm64Int32ToFloat64, kMachFloat64},
211      kMachInt32},
212     {{&RawMachineAssembler::ChangeUint32ToFloat64, "ChangeUint32ToFloat64",
213       kArm64Uint32ToFloat64, kMachFloat64},
214      kMachUint32},
215     {{&RawMachineAssembler::ChangeFloat64ToInt32, "ChangeFloat64ToInt32",
216       kArm64Float64ToInt32, kMachInt32},
217      kMachFloat64},
218     {{&RawMachineAssembler::ChangeFloat64ToUint32, "ChangeFloat64ToUint32",
219       kArm64Float64ToUint32, kMachUint32},
220      kMachFloat64}};
221 
222 }  // namespace
223 
224 
225 // -----------------------------------------------------------------------------
226 // Logical instructions.
227 
228 
229 typedef InstructionSelectorTestWithParam<MachInst2>
230     InstructionSelectorLogicalTest;
231 
232 
TEST_P(InstructionSelectorLogicalTest,Parameter)233 TEST_P(InstructionSelectorLogicalTest, Parameter) {
234   const MachInst2 dpi = GetParam();
235   const MachineType type = dpi.machine_type;
236   StreamBuilder m(this, type, type, type);
237   m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)));
238   Stream s = m.Build();
239   ASSERT_EQ(1U, s.size());
240   EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
241   EXPECT_EQ(2U, s[0]->InputCount());
242   EXPECT_EQ(1U, s[0]->OutputCount());
243 }
244 
245 
TEST_P(InstructionSelectorLogicalTest,Immediate)246 TEST_P(InstructionSelectorLogicalTest, Immediate) {
247   const MachInst2 dpi = GetParam();
248   const MachineType type = dpi.machine_type;
249   // TODO(all): Add support for testing 64-bit immediates.
250   if (type == kMachInt32) {
251     // Immediate on the right.
252     TRACED_FOREACH(int32_t, imm, kLogicalImmediates) {
253       StreamBuilder m(this, type, type);
254       m.Return((m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm)));
255       Stream s = m.Build();
256       ASSERT_EQ(1U, s.size());
257       EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
258       ASSERT_EQ(2U, s[0]->InputCount());
259       EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
260       EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
261       EXPECT_EQ(1U, s[0]->OutputCount());
262     }
263 
264     // Immediate on the left; all logical ops should commute.
265     TRACED_FOREACH(int32_t, imm, kLogicalImmediates) {
266       StreamBuilder m(this, type, type);
267       m.Return((m.*dpi.constructor)(m.Int32Constant(imm), m.Parameter(0)));
268       Stream s = m.Build();
269       ASSERT_EQ(1U, s.size());
270       EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
271       ASSERT_EQ(2U, s[0]->InputCount());
272       EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
273       EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
274       EXPECT_EQ(1U, s[0]->OutputCount());
275     }
276   }
277 }
278 
279 
280 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorLogicalTest,
281                         ::testing::ValuesIn(kLogicalInstructions));
282 
283 
284 // -----------------------------------------------------------------------------
285 // Add and Sub instructions.
286 
287 typedef InstructionSelectorTestWithParam<MachInst2>
288     InstructionSelectorAddSubTest;
289 
290 
TEST_P(InstructionSelectorAddSubTest,Parameter)291 TEST_P(InstructionSelectorAddSubTest, Parameter) {
292   const MachInst2 dpi = GetParam();
293   const MachineType type = dpi.machine_type;
294   StreamBuilder m(this, type, type, type);
295   m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)));
296   Stream s = m.Build();
297   ASSERT_EQ(1U, s.size());
298   EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
299   EXPECT_EQ(2U, s[0]->InputCount());
300   EXPECT_EQ(1U, s[0]->OutputCount());
301 }
302 
303 
TEST_P(InstructionSelectorAddSubTest,ImmediateOnRight)304 TEST_P(InstructionSelectorAddSubTest, ImmediateOnRight) {
305   const MachInst2 dpi = GetParam();
306   const MachineType type = dpi.machine_type;
307   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
308     StreamBuilder m(this, type, type);
309     m.Return((m.*dpi.constructor)(m.Parameter(0), BuildConstant(m, type, imm)));
310     Stream s = m.Build();
311     ASSERT_EQ(1U, s.size());
312     EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
313     ASSERT_EQ(2U, s[0]->InputCount());
314     EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
315     EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(1)));
316     EXPECT_EQ(1U, s[0]->OutputCount());
317   }
318 }
319 
320 
TEST_P(InstructionSelectorAddSubTest,ImmediateOnLeft)321 TEST_P(InstructionSelectorAddSubTest, ImmediateOnLeft) {
322   const MachInst2 dpi = GetParam();
323   const MachineType type = dpi.machine_type;
324 
325   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
326     StreamBuilder m(this, type, type);
327     m.Return((m.*dpi.constructor)(BuildConstant(m, type, imm), m.Parameter(0)));
328     Stream s = m.Build();
329 
330     // Add can support an immediate on the left by commuting, but Sub can't
331     // commute. We test zero-on-left Sub later.
332     if (strstr(dpi.constructor_name, "Add") != NULL) {
333       ASSERT_EQ(1U, s.size());
334       EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
335       ASSERT_EQ(2U, s[0]->InputCount());
336       EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
337       EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(1)));
338       EXPECT_EQ(1U, s[0]->OutputCount());
339     }
340   }
341 }
342 
343 
344 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorAddSubTest,
345                         ::testing::ValuesIn(kAddSubInstructions));
346 
347 
TEST_F(InstructionSelectorTest,SubZeroOnLeft)348 TEST_F(InstructionSelectorTest, SubZeroOnLeft) {
349   // Subtraction with zero on the left maps to Neg.
350   {
351     // 32-bit subtract.
352     StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
353     m.Return(m.Int32Sub(m.Int32Constant(0), m.Parameter(0)));
354     Stream s = m.Build();
355 
356     ASSERT_EQ(1U, s.size());
357     EXPECT_EQ(kArm64Neg32, s[0]->arch_opcode());
358     EXPECT_EQ(1U, s[0]->InputCount());
359     EXPECT_EQ(1U, s[0]->OutputCount());
360   }
361   {
362     // 64-bit subtract.
363     StreamBuilder m(this, kMachInt64, kMachInt64, kMachInt64);
364     m.Return(m.Int64Sub(m.Int64Constant(0), m.Parameter(0)));
365     Stream s = m.Build();
366 
367     ASSERT_EQ(1U, s.size());
368     EXPECT_EQ(kArm64Neg, s[0]->arch_opcode());
369     EXPECT_EQ(1U, s[0]->InputCount());
370     EXPECT_EQ(1U, s[0]->OutputCount());
371   }
372 }
373 
374 
375 // -----------------------------------------------------------------------------
376 // Data processing controlled branches.
377 
378 
379 typedef InstructionSelectorTestWithParam<MachInst2>
380     InstructionSelectorDPFlagSetTest;
381 
382 
TEST_P(InstructionSelectorDPFlagSetTest,BranchWithParameters)383 TEST_P(InstructionSelectorDPFlagSetTest, BranchWithParameters) {
384   const MachInst2 dpi = GetParam();
385   const MachineType type = dpi.machine_type;
386   StreamBuilder m(this, type, type, type);
387   MLabel a, b;
388   m.Branch((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)), &a, &b);
389   m.Bind(&a);
390   m.Return(m.Int32Constant(1));
391   m.Bind(&b);
392   m.Return(m.Int32Constant(0));
393   Stream s = m.Build();
394   ASSERT_EQ(1U, s.size());
395   EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
396   EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
397   EXPECT_EQ(kNotEqual, s[0]->flags_condition());
398 }
399 
400 
401 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
402                         InstructionSelectorDPFlagSetTest,
403                         ::testing::ValuesIn(kDPFlagSetInstructions));
404 
405 
TEST_F(InstructionSelectorTest,AndBranchWithImmediateOnRight)406 TEST_F(InstructionSelectorTest, AndBranchWithImmediateOnRight) {
407   TRACED_FOREACH(int32_t, imm, kLogicalImmediates) {
408     StreamBuilder m(this, kMachInt32, kMachInt32);
409     MLabel a, b;
410     m.Branch(m.Word32And(m.Parameter(0), m.Int32Constant(imm)), &a, &b);
411     m.Bind(&a);
412     m.Return(m.Int32Constant(1));
413     m.Bind(&b);
414     m.Return(m.Int32Constant(0));
415     Stream s = m.Build();
416     ASSERT_EQ(1U, s.size());
417     EXPECT_EQ(kArm64Tst32, s[0]->arch_opcode());
418     EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
419     EXPECT_EQ(kNotEqual, s[0]->flags_condition());
420   }
421 }
422 
423 
TEST_F(InstructionSelectorTest,AddBranchWithImmediateOnRight)424 TEST_F(InstructionSelectorTest, AddBranchWithImmediateOnRight) {
425   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
426     StreamBuilder m(this, kMachInt32, kMachInt32);
427     MLabel a, b;
428     m.Branch(m.Int32Add(m.Parameter(0), m.Int32Constant(imm)), &a, &b);
429     m.Bind(&a);
430     m.Return(m.Int32Constant(1));
431     m.Bind(&b);
432     m.Return(m.Int32Constant(0));
433     Stream s = m.Build();
434     ASSERT_EQ(1U, s.size());
435     EXPECT_EQ(kArm64Cmn32, s[0]->arch_opcode());
436     EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
437     EXPECT_EQ(kNotEqual, s[0]->flags_condition());
438   }
439 }
440 
441 
TEST_F(InstructionSelectorTest,SubBranchWithImmediateOnRight)442 TEST_F(InstructionSelectorTest, SubBranchWithImmediateOnRight) {
443   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
444     StreamBuilder m(this, kMachInt32, kMachInt32);
445     MLabel a, b;
446     m.Branch(m.Int32Sub(m.Parameter(0), m.Int32Constant(imm)), &a, &b);
447     m.Bind(&a);
448     m.Return(m.Int32Constant(1));
449     m.Bind(&b);
450     m.Return(m.Int32Constant(0));
451     Stream s = m.Build();
452     ASSERT_EQ(1U, s.size());
453     EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode());
454     EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
455     EXPECT_EQ(kNotEqual, s[0]->flags_condition());
456   }
457 }
458 
459 
TEST_F(InstructionSelectorTest,AndBranchWithImmediateOnLeft)460 TEST_F(InstructionSelectorTest, AndBranchWithImmediateOnLeft) {
461   TRACED_FOREACH(int32_t, imm, kLogicalImmediates) {
462     StreamBuilder m(this, kMachInt32, kMachInt32);
463     MLabel a, b;
464     m.Branch(m.Word32And(m.Int32Constant(imm), m.Parameter(0)), &a, &b);
465     m.Bind(&a);
466     m.Return(m.Int32Constant(1));
467     m.Bind(&b);
468     m.Return(m.Int32Constant(0));
469     Stream s = m.Build();
470     ASSERT_EQ(1U, s.size());
471     EXPECT_EQ(kArm64Tst32, s[0]->arch_opcode());
472     ASSERT_LE(1U, s[0]->InputCount());
473     EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
474     EXPECT_EQ(kNotEqual, s[0]->flags_condition());
475   }
476 }
477 
478 
TEST_F(InstructionSelectorTest,AddBranchWithImmediateOnLeft)479 TEST_F(InstructionSelectorTest, AddBranchWithImmediateOnLeft) {
480   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
481     StreamBuilder m(this, kMachInt32, kMachInt32);
482     MLabel a, b;
483     m.Branch(m.Int32Add(m.Int32Constant(imm), m.Parameter(0)), &a, &b);
484     m.Bind(&a);
485     m.Return(m.Int32Constant(1));
486     m.Bind(&b);
487     m.Return(m.Int32Constant(0));
488     Stream s = m.Build();
489     ASSERT_EQ(1U, s.size());
490     EXPECT_EQ(kArm64Cmn32, s[0]->arch_opcode());
491     ASSERT_LE(1U, s[0]->InputCount());
492     EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
493     EXPECT_EQ(kNotEqual, s[0]->flags_condition());
494   }
495 }
496 
497 
498 // -----------------------------------------------------------------------------
499 // Add and subtract instructions with overflow.
500 
501 
502 typedef InstructionSelectorTestWithParam<MachInst2>
503     InstructionSelectorOvfAddSubTest;
504 
505 
TEST_P(InstructionSelectorOvfAddSubTest,OvfParameter)506 TEST_P(InstructionSelectorOvfAddSubTest, OvfParameter) {
507   const MachInst2 dpi = GetParam();
508   const MachineType type = dpi.machine_type;
509   StreamBuilder m(this, type, type, type);
510   m.Return(
511       m.Projection(1, (m.*dpi.constructor)(m.Parameter(0), m.Parameter(1))));
512   Stream s = m.Build();
513   ASSERT_EQ(1U, s.size());
514   EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
515   EXPECT_EQ(2U, s[0]->InputCount());
516   EXPECT_LE(1U, s[0]->OutputCount());
517   EXPECT_EQ(kFlags_set, s[0]->flags_mode());
518   EXPECT_EQ(kOverflow, s[0]->flags_condition());
519 }
520 
521 
TEST_P(InstructionSelectorOvfAddSubTest,OvfImmediateOnRight)522 TEST_P(InstructionSelectorOvfAddSubTest, OvfImmediateOnRight) {
523   const MachInst2 dpi = GetParam();
524   const MachineType type = dpi.machine_type;
525   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
526     StreamBuilder m(this, type, type);
527     m.Return(m.Projection(
528         1, (m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm))));
529     Stream s = m.Build();
530     ASSERT_EQ(1U, s.size());
531     EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
532     ASSERT_EQ(2U, s[0]->InputCount());
533     EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
534     EXPECT_LE(1U, s[0]->OutputCount());
535     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
536     EXPECT_EQ(kOverflow, s[0]->flags_condition());
537   }
538 }
539 
540 
TEST_P(InstructionSelectorOvfAddSubTest,ValParameter)541 TEST_P(InstructionSelectorOvfAddSubTest, ValParameter) {
542   const MachInst2 dpi = GetParam();
543   const MachineType type = dpi.machine_type;
544   StreamBuilder m(this, type, type, type);
545   m.Return(
546       m.Projection(0, (m.*dpi.constructor)(m.Parameter(0), m.Parameter(1))));
547   Stream s = m.Build();
548   ASSERT_EQ(1U, s.size());
549   EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
550   EXPECT_EQ(2U, s[0]->InputCount());
551   EXPECT_LE(1U, s[0]->OutputCount());
552   EXPECT_EQ(kFlags_none, s[0]->flags_mode());
553 }
554 
555 
TEST_P(InstructionSelectorOvfAddSubTest,ValImmediateOnRight)556 TEST_P(InstructionSelectorOvfAddSubTest, ValImmediateOnRight) {
557   const MachInst2 dpi = GetParam();
558   const MachineType type = dpi.machine_type;
559   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
560     StreamBuilder m(this, type, type);
561     m.Return(m.Projection(
562         0, (m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm))));
563     Stream s = m.Build();
564     ASSERT_EQ(1U, s.size());
565     EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
566     ASSERT_EQ(2U, s[0]->InputCount());
567     EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
568     EXPECT_LE(1U, s[0]->OutputCount());
569     EXPECT_EQ(kFlags_none, s[0]->flags_mode());
570   }
571 }
572 
573 
TEST_P(InstructionSelectorOvfAddSubTest,BothParameter)574 TEST_P(InstructionSelectorOvfAddSubTest, BothParameter) {
575   const MachInst2 dpi = GetParam();
576   const MachineType type = dpi.machine_type;
577   StreamBuilder m(this, type, type, type);
578   Node* n = (m.*dpi.constructor)(m.Parameter(0), m.Parameter(1));
579   m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n)));
580   Stream s = m.Build();
581   ASSERT_LE(1U, s.size());
582   EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
583   EXPECT_EQ(2U, s[0]->InputCount());
584   EXPECT_EQ(2U, s[0]->OutputCount());
585   EXPECT_EQ(kFlags_set, s[0]->flags_mode());
586   EXPECT_EQ(kOverflow, s[0]->flags_condition());
587 }
588 
589 
TEST_P(InstructionSelectorOvfAddSubTest,BothImmediateOnRight)590 TEST_P(InstructionSelectorOvfAddSubTest, BothImmediateOnRight) {
591   const MachInst2 dpi = GetParam();
592   const MachineType type = dpi.machine_type;
593   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
594     StreamBuilder m(this, type, type);
595     Node* n = (m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm));
596     m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n)));
597     Stream s = m.Build();
598     ASSERT_LE(1U, s.size());
599     EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
600     ASSERT_EQ(2U, s[0]->InputCount());
601     EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
602     EXPECT_EQ(2U, s[0]->OutputCount());
603     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
604     EXPECT_EQ(kOverflow, s[0]->flags_condition());
605   }
606 }
607 
608 
TEST_P(InstructionSelectorOvfAddSubTest,BranchWithParameters)609 TEST_P(InstructionSelectorOvfAddSubTest, BranchWithParameters) {
610   const MachInst2 dpi = GetParam();
611   const MachineType type = dpi.machine_type;
612   StreamBuilder m(this, type, type, type);
613   MLabel a, b;
614   Node* n = (m.*dpi.constructor)(m.Parameter(0), m.Parameter(1));
615   m.Branch(m.Projection(1, n), &a, &b);
616   m.Bind(&a);
617   m.Return(m.Int32Constant(0));
618   m.Bind(&b);
619   m.Return(m.Projection(0, n));
620   Stream s = m.Build();
621   ASSERT_EQ(1U, s.size());
622   EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
623   EXPECT_EQ(4U, s[0]->InputCount());
624   EXPECT_EQ(1U, s[0]->OutputCount());
625   EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
626   EXPECT_EQ(kOverflow, s[0]->flags_condition());
627 }
628 
629 
TEST_P(InstructionSelectorOvfAddSubTest,BranchWithImmediateOnRight)630 TEST_P(InstructionSelectorOvfAddSubTest, BranchWithImmediateOnRight) {
631   const MachInst2 dpi = GetParam();
632   const MachineType type = dpi.machine_type;
633   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
634     StreamBuilder m(this, type, type);
635     MLabel a, b;
636     Node* n = (m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm));
637     m.Branch(m.Projection(1, n), &a, &b);
638     m.Bind(&a);
639     m.Return(m.Int32Constant(0));
640     m.Bind(&b);
641     m.Return(m.Projection(0, n));
642     Stream s = m.Build();
643     ASSERT_EQ(1U, s.size());
644     EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
645     ASSERT_EQ(4U, s[0]->InputCount());
646     EXPECT_EQ(1U, s[0]->OutputCount());
647     EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
648     EXPECT_EQ(kOverflow, s[0]->flags_condition());
649   }
650 }
651 
652 
653 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
654                         InstructionSelectorOvfAddSubTest,
655                         ::testing::ValuesIn(kOvfAddSubInstructions));
656 
657 
TEST_F(InstructionSelectorTest,OvfFlagAddImmediateOnLeft)658 TEST_F(InstructionSelectorTest, OvfFlagAddImmediateOnLeft) {
659   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
660     StreamBuilder m(this, kMachInt32, kMachInt32);
661     m.Return(m.Projection(
662         1, m.Int32AddWithOverflow(m.Int32Constant(imm), m.Parameter(0))));
663     Stream s = m.Build();
664 
665     ASSERT_EQ(1U, s.size());
666     EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
667     EXPECT_EQ(2U, s[0]->InputCount());
668     EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
669     EXPECT_LE(1U, s[0]->OutputCount());
670     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
671     EXPECT_EQ(kOverflow, s[0]->flags_condition());
672   }
673 }
674 
675 
TEST_F(InstructionSelectorTest,OvfValAddImmediateOnLeft)676 TEST_F(InstructionSelectorTest, OvfValAddImmediateOnLeft) {
677   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
678     StreamBuilder m(this, kMachInt32, kMachInt32);
679     m.Return(m.Projection(
680         0, m.Int32AddWithOverflow(m.Int32Constant(imm), m.Parameter(0))));
681     Stream s = m.Build();
682 
683     ASSERT_EQ(1U, s.size());
684     EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
685     ASSERT_EQ(2U, s[0]->InputCount());
686     EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
687     EXPECT_LE(1U, s[0]->OutputCount());
688     EXPECT_EQ(kFlags_none, s[0]->flags_mode());
689   }
690 }
691 
692 
TEST_F(InstructionSelectorTest,OvfBothAddImmediateOnLeft)693 TEST_F(InstructionSelectorTest, OvfBothAddImmediateOnLeft) {
694   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
695     StreamBuilder m(this, kMachInt32, kMachInt32);
696     Node* n = m.Int32AddWithOverflow(m.Int32Constant(imm), m.Parameter(0));
697     m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n)));
698     Stream s = m.Build();
699 
700     ASSERT_LE(1U, s.size());
701     EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
702     ASSERT_EQ(2U, s[0]->InputCount());
703     EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
704     EXPECT_EQ(2U, s[0]->OutputCount());
705     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
706     EXPECT_EQ(kOverflow, s[0]->flags_condition());
707   }
708 }
709 
710 
TEST_F(InstructionSelectorTest,OvfBranchWithImmediateOnLeft)711 TEST_F(InstructionSelectorTest, OvfBranchWithImmediateOnLeft) {
712   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
713     StreamBuilder m(this, kMachInt32, kMachInt32);
714     MLabel a, b;
715     Node* n = m.Int32AddWithOverflow(m.Int32Constant(imm), m.Parameter(0));
716     m.Branch(m.Projection(1, n), &a, &b);
717     m.Bind(&a);
718     m.Return(m.Int32Constant(0));
719     m.Bind(&b);
720     m.Return(m.Projection(0, n));
721     Stream s = m.Build();
722 
723     ASSERT_EQ(1U, s.size());
724     EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
725     ASSERT_EQ(4U, s[0]->InputCount());
726     EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
727     EXPECT_EQ(1U, s[0]->OutputCount());
728     EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
729     EXPECT_EQ(kOverflow, s[0]->flags_condition());
730   }
731 }
732 
733 
734 // -----------------------------------------------------------------------------
735 // Shift instructions.
736 
737 
738 typedef InstructionSelectorTestWithParam<MachInst2>
739     InstructionSelectorShiftTest;
740 
741 
TEST_P(InstructionSelectorShiftTest,Parameter)742 TEST_P(InstructionSelectorShiftTest, Parameter) {
743   const MachInst2 dpi = GetParam();
744   const MachineType type = dpi.machine_type;
745   StreamBuilder m(this, type, type, type);
746   m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)));
747   Stream s = m.Build();
748   ASSERT_EQ(1U, s.size());
749   EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
750   EXPECT_EQ(2U, s[0]->InputCount());
751   EXPECT_EQ(1U, s[0]->OutputCount());
752 }
753 
754 
TEST_P(InstructionSelectorShiftTest,Immediate)755 TEST_P(InstructionSelectorShiftTest, Immediate) {
756   const MachInst2 dpi = GetParam();
757   const MachineType type = dpi.machine_type;
758   TRACED_FORRANGE(int32_t, imm, 0, (ElementSizeOf(type) * 8) - 1) {
759     StreamBuilder m(this, type, type);
760     m.Return((m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm)));
761     Stream s = m.Build();
762     ASSERT_EQ(1U, s.size());
763     EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
764     EXPECT_EQ(2U, s[0]->InputCount());
765     EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
766     EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
767     EXPECT_EQ(1U, s[0]->OutputCount());
768   }
769 }
770 
771 
772 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorShiftTest,
773                         ::testing::ValuesIn(kShiftInstructions));
774 
775 
776 // -----------------------------------------------------------------------------
777 // Mul and Div instructions.
778 
779 
780 typedef InstructionSelectorTestWithParam<MachInst2>
781     InstructionSelectorMulDivTest;
782 
783 
TEST_P(InstructionSelectorMulDivTest,Parameter)784 TEST_P(InstructionSelectorMulDivTest, Parameter) {
785   const MachInst2 dpi = GetParam();
786   const MachineType type = dpi.machine_type;
787   StreamBuilder m(this, type, type, type);
788   m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)));
789   Stream s = m.Build();
790   ASSERT_EQ(1U, s.size());
791   EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
792   EXPECT_EQ(2U, s[0]->InputCount());
793   EXPECT_EQ(1U, s[0]->OutputCount());
794 }
795 
796 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorMulDivTest,
797                         ::testing::ValuesIn(kMulDivInstructions));
798 
799 
800 // -----------------------------------------------------------------------------
801 // Floating point instructions.
802 
803 typedef InstructionSelectorTestWithParam<MachInst2>
804     InstructionSelectorFPArithTest;
805 
806 
TEST_P(InstructionSelectorFPArithTest,Parameter)807 TEST_P(InstructionSelectorFPArithTest, Parameter) {
808   const MachInst2 fpa = GetParam();
809   StreamBuilder m(this, fpa.machine_type, fpa.machine_type, fpa.machine_type);
810   m.Return((m.*fpa.constructor)(m.Parameter(0), m.Parameter(1)));
811   Stream s = m.Build();
812   ASSERT_EQ(1U, s.size());
813   EXPECT_EQ(fpa.arch_opcode, s[0]->arch_opcode());
814   EXPECT_EQ(2U, s[0]->InputCount());
815   EXPECT_EQ(1U, s[0]->OutputCount());
816 }
817 
818 
819 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorFPArithTest,
820                         ::testing::ValuesIn(kFPArithInstructions));
821 
822 
823 typedef InstructionSelectorTestWithParam<FPCmp> InstructionSelectorFPCmpTest;
824 
825 
TEST_P(InstructionSelectorFPCmpTest,Parameter)826 TEST_P(InstructionSelectorFPCmpTest, Parameter) {
827   const FPCmp cmp = GetParam();
828   StreamBuilder m(this, kMachInt32, cmp.mi.machine_type, cmp.mi.machine_type);
829   m.Return((m.*cmp.mi.constructor)(m.Parameter(0), m.Parameter(1)));
830   Stream s = m.Build();
831   ASSERT_EQ(1U, s.size());
832   EXPECT_EQ(cmp.mi.arch_opcode, s[0]->arch_opcode());
833   EXPECT_EQ(2U, s[0]->InputCount());
834   EXPECT_EQ(1U, s[0]->OutputCount());
835   EXPECT_EQ(kFlags_set, s[0]->flags_mode());
836   EXPECT_EQ(cmp.cond, s[0]->flags_condition());
837 }
838 
839 
840 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorFPCmpTest,
841                         ::testing::ValuesIn(kFPCmpInstructions));
842 
843 
844 // -----------------------------------------------------------------------------
845 // Conversions.
846 
847 typedef InstructionSelectorTestWithParam<Conversion>
848     InstructionSelectorConversionTest;
849 
850 
TEST_P(InstructionSelectorConversionTest,Parameter)851 TEST_P(InstructionSelectorConversionTest, Parameter) {
852   const Conversion conv = GetParam();
853   StreamBuilder m(this, conv.mi.machine_type, conv.src_machine_type);
854   m.Return((m.*conv.mi.constructor)(m.Parameter(0)));
855   Stream s = m.Build();
856   ASSERT_EQ(1U, s.size());
857   EXPECT_EQ(conv.mi.arch_opcode, s[0]->arch_opcode());
858   EXPECT_EQ(1U, s[0]->InputCount());
859   EXPECT_EQ(1U, s[0]->OutputCount());
860 }
861 
862 
863 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
864                         InstructionSelectorConversionTest,
865                         ::testing::ValuesIn(kConversionInstructions));
866 
867 
868 // -----------------------------------------------------------------------------
869 // Memory access instructions.
870 
871 
872 namespace {
873 
874 struct MemoryAccess {
875   MachineType type;
876   ArchOpcode ldr_opcode;
877   ArchOpcode str_opcode;
878   const int32_t immediates[20];
879 };
880 
881 
operator <<(std::ostream & os,const MemoryAccess & memacc)882 std::ostream& operator<<(std::ostream& os, const MemoryAccess& memacc) {
883   OStringStream ost;
884   ost << memacc.type;
885   return os << ost.c_str();
886 }
887 
888 }  // namespace
889 
890 
891 static const MemoryAccess kMemoryAccesses[] = {
892     {kMachInt8, kArm64Ldrsb, kArm64Strb,
893      {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 257, 258, 1000, 1001,
894       2121, 2442, 4093, 4094, 4095}},
895     {kMachUint8, kArm64Ldrb, kArm64Strb,
896      {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 257, 258, 1000, 1001,
897       2121, 2442, 4093, 4094, 4095}},
898     {kMachInt16, kArm64Ldrsh, kArm64Strh,
899      {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 258, 260, 4096, 4098,
900       4100, 4242, 6786, 8188, 8190}},
901     {kMachUint16, kArm64Ldrh, kArm64Strh,
902      {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 258, 260, 4096, 4098,
903       4100, 4242, 6786, 8188, 8190}},
904     {kMachInt32, kArm64LdrW, kArm64StrW,
905      {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 260, 4096, 4100, 8192,
906       8196, 3276, 3280, 16376, 16380}},
907     {kMachUint32, kArm64LdrW, kArm64StrW,
908      {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 260, 4096, 4100, 8192,
909       8196, 3276, 3280, 16376, 16380}},
910     {kMachInt64, kArm64Ldr, kArm64Str,
911      {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 264, 4096, 4104, 8192,
912       8200, 16384, 16392, 32752, 32760}},
913     {kMachUint64, kArm64Ldr, kArm64Str,
914      {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 264, 4096, 4104, 8192,
915       8200, 16384, 16392, 32752, 32760}},
916     {kMachFloat32, kArm64LdrS, kArm64StrS,
917      {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 260, 4096, 4100, 8192,
918       8196, 3276, 3280, 16376, 16380}},
919     {kMachFloat64, kArm64LdrD, kArm64StrD,
920      {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 264, 4096, 4104, 8192,
921       8200, 16384, 16392, 32752, 32760}}};
922 
923 
924 typedef InstructionSelectorTestWithParam<MemoryAccess>
925     InstructionSelectorMemoryAccessTest;
926 
927 
TEST_P(InstructionSelectorMemoryAccessTest,LoadWithParameters)928 TEST_P(InstructionSelectorMemoryAccessTest, LoadWithParameters) {
929   const MemoryAccess memacc = GetParam();
930   StreamBuilder m(this, memacc.type, kMachPtr, kMachInt32);
931   m.Return(m.Load(memacc.type, m.Parameter(0), m.Parameter(1)));
932   Stream s = m.Build();
933   ASSERT_EQ(1U, s.size());
934   EXPECT_EQ(memacc.ldr_opcode, s[0]->arch_opcode());
935   EXPECT_EQ(kMode_MRR, s[0]->addressing_mode());
936   EXPECT_EQ(2U, s[0]->InputCount());
937   EXPECT_EQ(1U, s[0]->OutputCount());
938 }
939 
940 
TEST_P(InstructionSelectorMemoryAccessTest,LoadWithImmediateIndex)941 TEST_P(InstructionSelectorMemoryAccessTest, LoadWithImmediateIndex) {
942   const MemoryAccess memacc = GetParam();
943   TRACED_FOREACH(int32_t, index, memacc.immediates) {
944     StreamBuilder m(this, memacc.type, kMachPtr);
945     m.Return(m.Load(memacc.type, m.Parameter(0), m.Int32Constant(index)));
946     Stream s = m.Build();
947     ASSERT_EQ(1U, s.size());
948     EXPECT_EQ(memacc.ldr_opcode, s[0]->arch_opcode());
949     EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
950     EXPECT_EQ(2U, s[0]->InputCount());
951     ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
952     EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1)));
953     ASSERT_EQ(1U, s[0]->OutputCount());
954   }
955 }
956 
957 
TEST_P(InstructionSelectorMemoryAccessTest,StoreWithParameters)958 TEST_P(InstructionSelectorMemoryAccessTest, StoreWithParameters) {
959   const MemoryAccess memacc = GetParam();
960   StreamBuilder m(this, kMachInt32, kMachPtr, kMachInt32, memacc.type);
961   m.Store(memacc.type, m.Parameter(0), m.Parameter(1), m.Parameter(2));
962   m.Return(m.Int32Constant(0));
963   Stream s = m.Build();
964   ASSERT_EQ(1U, s.size());
965   EXPECT_EQ(memacc.str_opcode, s[0]->arch_opcode());
966   EXPECT_EQ(kMode_MRR, s[0]->addressing_mode());
967   EXPECT_EQ(3U, s[0]->InputCount());
968   EXPECT_EQ(0U, s[0]->OutputCount());
969 }
970 
971 
TEST_P(InstructionSelectorMemoryAccessTest,StoreWithImmediateIndex)972 TEST_P(InstructionSelectorMemoryAccessTest, StoreWithImmediateIndex) {
973   const MemoryAccess memacc = GetParam();
974   TRACED_FOREACH(int32_t, index, memacc.immediates) {
975     StreamBuilder m(this, kMachInt32, kMachPtr, memacc.type);
976     m.Store(memacc.type, m.Parameter(0), m.Int32Constant(index),
977             m.Parameter(1));
978     m.Return(m.Int32Constant(0));
979     Stream s = m.Build();
980     ASSERT_EQ(1U, s.size());
981     EXPECT_EQ(memacc.str_opcode, s[0]->arch_opcode());
982     EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
983     ASSERT_EQ(3U, s[0]->InputCount());
984     ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
985     EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1)));
986     EXPECT_EQ(0U, s[0]->OutputCount());
987   }
988 }
989 
990 
991 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
992                         InstructionSelectorMemoryAccessTest,
993                         ::testing::ValuesIn(kMemoryAccesses));
994 
995 
996 // -----------------------------------------------------------------------------
997 // Comparison instructions.
998 
999 static const MachInst2 kComparisonInstructions[] = {
1000     {&RawMachineAssembler::Word32Equal, "Word32Equal", kArm64Cmp32, kMachInt32},
1001     {&RawMachineAssembler::Word64Equal, "Word64Equal", kArm64Cmp, kMachInt64},
1002 };
1003 
1004 
1005 typedef InstructionSelectorTestWithParam<MachInst2>
1006     InstructionSelectorComparisonTest;
1007 
1008 
TEST_P(InstructionSelectorComparisonTest,WithParameters)1009 TEST_P(InstructionSelectorComparisonTest, WithParameters) {
1010   const MachInst2 cmp = GetParam();
1011   const MachineType type = cmp.machine_type;
1012   StreamBuilder m(this, type, type, type);
1013   m.Return((m.*cmp.constructor)(m.Parameter(0), m.Parameter(1)));
1014   Stream s = m.Build();
1015   ASSERT_EQ(1U, s.size());
1016   EXPECT_EQ(cmp.arch_opcode, s[0]->arch_opcode());
1017   EXPECT_EQ(2U, s[0]->InputCount());
1018   EXPECT_EQ(1U, s[0]->OutputCount());
1019   EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1020   EXPECT_EQ(kEqual, s[0]->flags_condition());
1021 }
1022 
1023 
TEST_P(InstructionSelectorComparisonTest,WithImmediate)1024 TEST_P(InstructionSelectorComparisonTest, WithImmediate) {
1025   const MachInst2 cmp = GetParam();
1026   const MachineType type = cmp.machine_type;
1027   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
1028     // Compare with 0 are turned into tst instruction.
1029     if (imm == 0) continue;
1030     StreamBuilder m(this, type, type);
1031     m.Return((m.*cmp.constructor)(m.Parameter(0), BuildConstant(m, type, imm)));
1032     Stream s = m.Build();
1033     ASSERT_EQ(1U, s.size());
1034     EXPECT_EQ(cmp.arch_opcode, s[0]->arch_opcode());
1035     ASSERT_EQ(2U, s[0]->InputCount());
1036     ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
1037     EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(1)));
1038     EXPECT_EQ(1U, s[0]->OutputCount());
1039     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1040     EXPECT_EQ(kEqual, s[0]->flags_condition());
1041   }
1042   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
1043     // Compare with 0 are turned into tst instruction.
1044     if (imm == 0) continue;
1045     StreamBuilder m(this, type, type);
1046     m.Return((m.*cmp.constructor)(m.Parameter(0), BuildConstant(m, type, imm)));
1047     Stream s = m.Build();
1048     ASSERT_EQ(1U, s.size());
1049     EXPECT_EQ(cmp.arch_opcode, s[0]->arch_opcode());
1050     ASSERT_EQ(2U, s[0]->InputCount());
1051     ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
1052     EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(1)));
1053     EXPECT_EQ(1U, s[0]->OutputCount());
1054     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1055     EXPECT_EQ(kEqual, s[0]->flags_condition());
1056   }
1057 }
1058 
1059 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1060                         InstructionSelectorComparisonTest,
1061                         ::testing::ValuesIn(kComparisonInstructions));
1062 
1063 
TEST_F(InstructionSelectorTest,Word32EqualWithZero)1064 TEST_F(InstructionSelectorTest, Word32EqualWithZero) {
1065   {
1066     StreamBuilder m(this, kMachInt32, kMachInt32);
1067     m.Return(m.Word32Equal(m.Parameter(0), m.Int32Constant(0)));
1068     Stream s = m.Build();
1069     ASSERT_EQ(1U, s.size());
1070     EXPECT_EQ(kArm64Tst32, s[0]->arch_opcode());
1071     ASSERT_EQ(2U, s[0]->InputCount());
1072     EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
1073     EXPECT_EQ(1U, s[0]->OutputCount());
1074     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1075     EXPECT_EQ(kEqual, s[0]->flags_condition());
1076   }
1077   {
1078     StreamBuilder m(this, kMachInt32, kMachInt32);
1079     m.Return(m.Word32Equal(m.Int32Constant(0), m.Parameter(0)));
1080     Stream s = m.Build();
1081     ASSERT_EQ(1U, s.size());
1082     EXPECT_EQ(kArm64Tst32, s[0]->arch_opcode());
1083     ASSERT_EQ(2U, s[0]->InputCount());
1084     EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
1085     EXPECT_EQ(1U, s[0]->OutputCount());
1086     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1087     EXPECT_EQ(kEqual, s[0]->flags_condition());
1088   }
1089 }
1090 
1091 
TEST_F(InstructionSelectorTest,Word64EqualWithZero)1092 TEST_F(InstructionSelectorTest, Word64EqualWithZero) {
1093   {
1094     StreamBuilder m(this, kMachInt64, kMachInt64);
1095     m.Return(m.Word64Equal(m.Parameter(0), m.Int64Constant(0)));
1096     Stream s = m.Build();
1097     ASSERT_EQ(1U, s.size());
1098     EXPECT_EQ(kArm64Tst, s[0]->arch_opcode());
1099     ASSERT_EQ(2U, s[0]->InputCount());
1100     EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
1101     EXPECT_EQ(1U, s[0]->OutputCount());
1102     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1103     EXPECT_EQ(kEqual, s[0]->flags_condition());
1104   }
1105   {
1106     StreamBuilder m(this, kMachInt64, kMachInt64);
1107     m.Return(m.Word64Equal(m.Int64Constant(0), m.Parameter(0)));
1108     Stream s = m.Build();
1109     ASSERT_EQ(1U, s.size());
1110     EXPECT_EQ(kArm64Tst, s[0]->arch_opcode());
1111     ASSERT_EQ(2U, s[0]->InputCount());
1112     EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
1113     EXPECT_EQ(1U, s[0]->OutputCount());
1114     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1115     EXPECT_EQ(kEqual, s[0]->flags_condition());
1116   }
1117 }
1118 
1119 }  // namespace compiler
1120 }  // namespace internal
1121 }  // namespace v8
1122