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.
5 #include "test/unittests/compiler/instruction-selector-unittest.h"
13 typedef RawMachineAssembler::Label MLabel;
18 const char* constructor_name;
19 ArchOpcode arch_opcode;
20 MachineType machine_type;
23 typedef MachInst<Node* (RawMachineAssembler::*)(Node*)> MachInst1;
24 typedef MachInst<Node* (RawMachineAssembler::*)(Node*, Node*)> MachInst2;
28 std::ostream& operator<<(std::ostream& os, const MachInst<T>& mi) {
29 return os << mi.constructor_name;
39 std::ostream& operator<<(std::ostream& os, const Shift& shift) {
40 return os << shift.mi;
44 // Helper to build Int32Constant or Int64Constant depending on the given
46 Node* BuildConstant(InstructionSelectorTest::StreamBuilder& m, MachineType type,
50 return m.Int32Constant(value);
54 return m.Int64Constant(value);
64 // ARM64 logical instructions.
65 static const MachInst2 kLogicalInstructions[] = {
66 {&RawMachineAssembler::Word32And, "Word32And", kArm64And32, kMachInt32},
67 {&RawMachineAssembler::Word64And, "Word64And", kArm64And, kMachInt64},
68 {&RawMachineAssembler::Word32Or, "Word32Or", kArm64Or32, kMachInt32},
69 {&RawMachineAssembler::Word64Or, "Word64Or", kArm64Or, kMachInt64},
70 {&RawMachineAssembler::Word32Xor, "Word32Xor", kArm64Eor32, kMachInt32},
71 {&RawMachineAssembler::Word64Xor, "Word64Xor", kArm64Eor, kMachInt64}};
74 // ARM64 logical immediates: contiguous set bits, rotated about a power of two
75 // sized block. The block is then duplicated across the word. Below is a random
76 // subset of the 32-bit immediates.
77 static const uint32_t kLogical32Immediates[] = {
78 0x00000002, 0x00000003, 0x00000070, 0x00000080, 0x00000100, 0x000001c0,
79 0x00000300, 0x000007e0, 0x00003ffc, 0x00007fc0, 0x0003c000, 0x0003f000,
80 0x0003ffc0, 0x0003fff8, 0x0007ff00, 0x0007ffe0, 0x000e0000, 0x001e0000,
81 0x001ffffc, 0x003f0000, 0x003f8000, 0x00780000, 0x007fc000, 0x00ff0000,
82 0x01800000, 0x01800180, 0x01f801f8, 0x03fe0000, 0x03ffffc0, 0x03fffffc,
83 0x06000000, 0x07fc0000, 0x07ffc000, 0x07ffffc0, 0x07ffffe0, 0x0ffe0ffe,
84 0x0ffff800, 0x0ffffff0, 0x0fffffff, 0x18001800, 0x1f001f00, 0x1f801f80,
85 0x30303030, 0x3ff03ff0, 0x3ff83ff8, 0x3fff0000, 0x3fff8000, 0x3fffffc0,
86 0x70007000, 0x7f7f7f7f, 0x7fc00000, 0x7fffffc0, 0x8000001f, 0x800001ff,
87 0x81818181, 0x9fff9fff, 0xc00007ff, 0xc0ffffff, 0xdddddddd, 0xe00001ff,
88 0xe00003ff, 0xe007ffff, 0xefffefff, 0xf000003f, 0xf001f001, 0xf3fff3ff,
89 0xf800001f, 0xf80fffff, 0xf87ff87f, 0xfbfbfbfb, 0xfc00001f, 0xfc0000ff,
90 0xfc0001ff, 0xfc03fc03, 0xfe0001ff, 0xff000001, 0xff03ff03, 0xff800000,
91 0xff800fff, 0xff801fff, 0xff87ffff, 0xffc0003f, 0xffc007ff, 0xffcfffcf,
92 0xffe00003, 0xffe1ffff, 0xfff0001f, 0xfff07fff, 0xfff80007, 0xfff87fff,
93 0xfffc00ff, 0xfffe07ff, 0xffff00ff, 0xffffc001, 0xfffff007, 0xfffff3ff,
94 0xfffff807, 0xfffff9ff, 0xfffffc0f, 0xfffffeff};
97 // Random subset of 64-bit logical immediates.
98 static const uint64_t kLogical64Immediates[] = {
99 0x0000000000000001, 0x0000000000000002, 0x0000000000000003,
100 0x0000000000000070, 0x0000000000000080, 0x0000000000000100,
101 0x00000000000001c0, 0x0000000000000300, 0x0000000000000600,
102 0x00000000000007e0, 0x0000000000003ffc, 0x0000000000007fc0,
103 0x0000000600000000, 0x0000003ffffffffc, 0x000000f000000000,
104 0x000001f800000000, 0x0003fc0000000000, 0x0003fc000003fc00,
105 0x0003ffffffc00000, 0x0003ffffffffffc0, 0x0006000000060000,
106 0x003ffffffffc0000, 0x0180018001800180, 0x01f801f801f801f8,
107 0x0600000000000000, 0x1000000010000000, 0x1000100010001000,
108 0x1010101010101010, 0x1111111111111111, 0x1f001f001f001f00,
109 0x1f1f1f1f1f1f1f1f, 0x1ffffffffffffffe, 0x3ffc3ffc3ffc3ffc,
110 0x5555555555555555, 0x7f7f7f7f7f7f7f7f, 0x8000000000000000,
111 0x8000001f8000001f, 0x8181818181818181, 0x9999999999999999,
112 0x9fff9fff9fff9fff, 0xaaaaaaaaaaaaaaaa, 0xdddddddddddddddd,
113 0xe0000000000001ff, 0xf800000000000000, 0xf8000000000001ff,
114 0xf807f807f807f807, 0xfefefefefefefefe, 0xfffefffefffefffe,
115 0xfffff807fffff807, 0xfffff9fffffff9ff, 0xfffffc0ffffffc0f,
116 0xfffffc0fffffffff, 0xfffffefffffffeff, 0xfffffeffffffffff,
117 0xffffff8000000000, 0xfffffffefffffffe, 0xffffffffefffffff,
118 0xfffffffff9ffffff, 0xffffffffff800000, 0xffffffffffffc0ff,
122 // ARM64 arithmetic instructions.
125 ArchOpcode negate_arch_opcode;
129 std::ostream& operator<<(std::ostream& os, const AddSub& op) {
134 static const AddSub kAddSubInstructions[] = {
135 {{&RawMachineAssembler::Int32Add, "Int32Add", kArm64Add32, kMachInt32},
137 {{&RawMachineAssembler::Int64Add, "Int64Add", kArm64Add, kMachInt64},
139 {{&RawMachineAssembler::Int32Sub, "Int32Sub", kArm64Sub32, kMachInt32},
141 {{&RawMachineAssembler::Int64Sub, "Int64Sub", kArm64Sub, kMachInt64},
145 // ARM64 Add/Sub immediates: 12-bit immediate optionally shifted by 12.
146 // Below is a combination of a random subset and some edge values.
147 static const int32_t kAddSubImmediates[] = {
148 0, 1, 69, 493, 599, 701, 719,
149 768, 818, 842, 945, 1246, 1286, 1429,
150 1669, 2171, 2179, 2182, 2254, 2334, 2338,
151 2343, 2396, 2449, 2610, 2732, 2855, 2876,
152 2944, 3377, 3458, 3475, 3476, 3540, 3574,
153 3601, 3813, 3871, 3917, 4095, 4096, 16384,
154 364544, 462848, 970752, 1523712, 1863680, 2363392, 3219456,
155 3280896, 4247552, 4526080, 4575232, 4960256, 5505024, 5894144,
156 6004736, 6193152, 6385664, 6795264, 7114752, 7233536, 7348224,
157 7499776, 7573504, 7729152, 8634368, 8937472, 9465856, 10354688,
158 10682368, 11059200, 11460608, 13168640, 13176832, 14336000, 15028224,
159 15597568, 15892480, 16773120};
162 // ARM64 flag setting data processing instructions.
163 static const MachInst2 kDPFlagSetInstructions[] = {
164 {&RawMachineAssembler::Word32And, "Word32And", kArm64Tst32, kMachInt32},
165 {&RawMachineAssembler::Int32Add, "Int32Add", kArm64Cmn32, kMachInt32},
166 {&RawMachineAssembler::Int32Sub, "Int32Sub", kArm64Cmp32, kMachInt32},
167 {&RawMachineAssembler::Word64And, "Word64And", kArm64Tst, kMachInt64}};
170 // ARM64 arithmetic with overflow instructions.
171 static const MachInst2 kOvfAddSubInstructions[] = {
172 {&RawMachineAssembler::Int32AddWithOverflow, "Int32AddWithOverflow",
173 kArm64Add32, kMachInt32},
174 {&RawMachineAssembler::Int32SubWithOverflow, "Int32SubWithOverflow",
175 kArm64Sub32, kMachInt32}};
178 // ARM64 shift instructions.
179 static const Shift kShiftInstructions[] = {
180 {{&RawMachineAssembler::Word32Shl, "Word32Shl", kArm64Lsl32, kMachInt32},
181 kMode_Operand2_R_LSL_I},
182 {{&RawMachineAssembler::Word64Shl, "Word64Shl", kArm64Lsl, kMachInt64},
183 kMode_Operand2_R_LSL_I},
184 {{&RawMachineAssembler::Word32Shr, "Word32Shr", kArm64Lsr32, kMachInt32},
185 kMode_Operand2_R_LSR_I},
186 {{&RawMachineAssembler::Word64Shr, "Word64Shr", kArm64Lsr, kMachInt64},
187 kMode_Operand2_R_LSR_I},
188 {{&RawMachineAssembler::Word32Sar, "Word32Sar", kArm64Asr32, kMachInt32},
189 kMode_Operand2_R_ASR_I},
190 {{&RawMachineAssembler::Word64Sar, "Word64Sar", kArm64Asr, kMachInt64},
191 kMode_Operand2_R_ASR_I},
192 {{&RawMachineAssembler::Word32Ror, "Word32Ror", kArm64Ror32, kMachInt32},
193 kMode_Operand2_R_ROR_I},
194 {{&RawMachineAssembler::Word64Ror, "Word64Ror", kArm64Ror, kMachInt64},
195 kMode_Operand2_R_ROR_I}};
198 // ARM64 Mul/Div instructions.
199 static const MachInst2 kMulDivInstructions[] = {
200 {&RawMachineAssembler::Int32Mul, "Int32Mul", kArm64Mul32, kMachInt32},
201 {&RawMachineAssembler::Int64Mul, "Int64Mul", kArm64Mul, kMachInt64},
202 {&RawMachineAssembler::Int32Div, "Int32Div", kArm64Idiv32, kMachInt32},
203 {&RawMachineAssembler::Int64Div, "Int64Div", kArm64Idiv, kMachInt64},
204 {&RawMachineAssembler::Uint32Div, "Uint32Div", kArm64Udiv32, kMachInt32},
205 {&RawMachineAssembler::Uint64Div, "Uint64Div", kArm64Udiv, kMachInt64}};
208 // ARM64 FP arithmetic instructions.
209 static const MachInst2 kFPArithInstructions[] = {
210 {&RawMachineAssembler::Float64Add, "Float64Add", kArm64Float64Add,
212 {&RawMachineAssembler::Float64Sub, "Float64Sub", kArm64Float64Sub,
214 {&RawMachineAssembler::Float64Mul, "Float64Mul", kArm64Float64Mul,
216 {&RawMachineAssembler::Float64Div, "Float64Div", kArm64Float64Div,
226 std::ostream& operator<<(std::ostream& os, const FPCmp& cmp) {
231 // ARM64 FP comparison instructions.
232 static const FPCmp kFPCmpInstructions[] = {
233 {{&RawMachineAssembler::Float64Equal, "Float64Equal", kArm64Float64Cmp,
236 {{&RawMachineAssembler::Float64LessThan, "Float64LessThan",
237 kArm64Float64Cmp, kMachFloat64},
239 {{&RawMachineAssembler::Float64LessThanOrEqual, "Float64LessThanOrEqual",
240 kArm64Float64Cmp, kMachFloat64},
241 kUnorderedLessThanOrEqual}};
245 // The machine_type field in MachInst1 represents the destination type.
247 MachineType src_machine_type;
251 std::ostream& operator<<(std::ostream& os, const Conversion& conv) {
252 return os << conv.mi;
256 // ARM64 type conversion instructions.
257 static const Conversion kConversionInstructions[] = {
258 {{&RawMachineAssembler::ChangeFloat32ToFloat64, "ChangeFloat32ToFloat64",
259 kArm64Float32ToFloat64, kMachFloat64},
261 {{&RawMachineAssembler::TruncateFloat64ToFloat32,
262 "TruncateFloat64ToFloat32", kArm64Float64ToFloat32, kMachFloat32},
264 {{&RawMachineAssembler::ChangeInt32ToInt64, "ChangeInt32ToInt64",
265 kArm64Sxtw, kMachInt64},
267 {{&RawMachineAssembler::ChangeUint32ToUint64, "ChangeUint32ToUint64",
268 kArm64Mov32, kMachUint64},
270 {{&RawMachineAssembler::TruncateInt64ToInt32, "TruncateInt64ToInt32",
271 kArm64Mov32, kMachInt32},
273 {{&RawMachineAssembler::ChangeInt32ToFloat64, "ChangeInt32ToFloat64",
274 kArm64Int32ToFloat64, kMachFloat64},
276 {{&RawMachineAssembler::ChangeUint32ToFloat64, "ChangeUint32ToFloat64",
277 kArm64Uint32ToFloat64, kMachFloat64},
279 {{&RawMachineAssembler::ChangeFloat64ToInt32, "ChangeFloat64ToInt32",
280 kArm64Float64ToInt32, kMachInt32},
282 {{&RawMachineAssembler::ChangeFloat64ToUint32, "ChangeFloat64ToUint32",
283 kArm64Float64ToUint32, kMachUint32},
289 // -----------------------------------------------------------------------------
290 // Logical instructions.
293 typedef InstructionSelectorTestWithParam<MachInst2>
294 InstructionSelectorLogicalTest;
297 TEST_P(InstructionSelectorLogicalTest, Parameter) {
298 const MachInst2 dpi = GetParam();
299 const MachineType type = dpi.machine_type;
300 StreamBuilder m(this, type, type, type);
301 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)));
302 Stream s = m.Build();
303 ASSERT_EQ(1U, s.size());
304 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
305 EXPECT_EQ(2U, s[0]->InputCount());
306 EXPECT_EQ(1U, s[0]->OutputCount());
310 TEST_P(InstructionSelectorLogicalTest, Immediate) {
311 const MachInst2 dpi = GetParam();
312 const MachineType type = dpi.machine_type;
313 // TODO(all): Add support for testing 64-bit immediates.
314 if (type == kMachInt32) {
315 // Immediate on the right.
316 TRACED_FOREACH(int32_t, imm, kLogical32Immediates) {
317 StreamBuilder m(this, type, type);
318 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm)));
319 Stream s = m.Build();
320 ASSERT_EQ(1U, s.size());
321 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
322 ASSERT_EQ(2U, s[0]->InputCount());
323 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
324 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
325 EXPECT_EQ(1U, s[0]->OutputCount());
328 // Immediate on the left; all logical ops should commute.
329 TRACED_FOREACH(int32_t, imm, kLogical32Immediates) {
330 StreamBuilder m(this, type, type);
331 m.Return((m.*dpi.constructor)(m.Int32Constant(imm), m.Parameter(0)));
332 Stream s = m.Build();
333 ASSERT_EQ(1U, s.size());
334 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
335 ASSERT_EQ(2U, s[0]->InputCount());
336 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
337 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
338 EXPECT_EQ(1U, s[0]->OutputCount());
344 TEST_P(InstructionSelectorLogicalTest, ShiftByImmediate) {
345 const MachInst2 dpi = GetParam();
346 const MachineType type = dpi.machine_type;
347 TRACED_FOREACH(Shift, shift, kShiftInstructions) {
348 // Only test 64-bit shifted operands with 64-bit instructions.
349 if (shift.mi.machine_type != type) continue;
351 TRACED_FORRANGE(int, imm, 0, ((type == kMachInt32) ? 31 : 63)) {
352 StreamBuilder m(this, type, type, type);
353 m.Return((m.*dpi.constructor)(
355 (m.*shift.mi.constructor)(m.Parameter(1),
356 BuildConstant(m, type, imm))));
357 Stream s = m.Build();
358 ASSERT_EQ(1U, s.size());
359 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
360 EXPECT_EQ(shift.mode, s[0]->addressing_mode());
361 EXPECT_EQ(3U, s[0]->InputCount());
362 EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(2)));
363 EXPECT_EQ(1U, s[0]->OutputCount());
366 TRACED_FORRANGE(int, imm, 0, ((type == kMachInt32) ? 31 : 63)) {
367 StreamBuilder m(this, type, type, type);
368 m.Return((m.*dpi.constructor)(
369 (m.*shift.mi.constructor)(m.Parameter(1),
370 BuildConstant(m, type, imm)),
372 Stream s = m.Build();
373 ASSERT_EQ(1U, s.size());
374 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
375 EXPECT_EQ(shift.mode, s[0]->addressing_mode());
376 EXPECT_EQ(3U, s[0]->InputCount());
377 EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(2)));
378 EXPECT_EQ(1U, s[0]->OutputCount());
384 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorLogicalTest,
385 ::testing::ValuesIn(kLogicalInstructions));
388 // -----------------------------------------------------------------------------
389 // Add and Sub instructions.
391 typedef InstructionSelectorTestWithParam<AddSub> InstructionSelectorAddSubTest;
394 TEST_P(InstructionSelectorAddSubTest, Parameter) {
395 const AddSub dpi = GetParam();
396 const MachineType type = dpi.mi.machine_type;
397 StreamBuilder m(this, type, type, type);
398 m.Return((m.*dpi.mi.constructor)(m.Parameter(0), m.Parameter(1)));
399 Stream s = m.Build();
400 ASSERT_EQ(1U, s.size());
401 EXPECT_EQ(dpi.mi.arch_opcode, s[0]->arch_opcode());
402 EXPECT_EQ(2U, s[0]->InputCount());
403 EXPECT_EQ(1U, s[0]->OutputCount());
407 TEST_P(InstructionSelectorAddSubTest, ImmediateOnRight) {
408 const AddSub dpi = GetParam();
409 const MachineType type = dpi.mi.machine_type;
410 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
411 StreamBuilder m(this, type, type);
413 (m.*dpi.mi.constructor)(m.Parameter(0), BuildConstant(m, type, imm)));
414 Stream s = m.Build();
415 ASSERT_EQ(1U, s.size());
416 EXPECT_EQ(dpi.mi.arch_opcode, s[0]->arch_opcode());
417 ASSERT_EQ(2U, s[0]->InputCount());
418 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
419 EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(1)));
420 EXPECT_EQ(1U, s[0]->OutputCount());
425 TEST_P(InstructionSelectorAddSubTest, NegImmediateOnRight) {
426 const AddSub dpi = GetParam();
427 const MachineType type = dpi.mi.machine_type;
428 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
429 if (imm == 0) continue;
430 StreamBuilder m(this, type, type);
432 (m.*dpi.mi.constructor)(m.Parameter(0), BuildConstant(m, type, -imm)));
433 Stream s = m.Build();
434 ASSERT_EQ(1U, s.size());
435 EXPECT_EQ(dpi.negate_arch_opcode, s[0]->arch_opcode());
436 ASSERT_EQ(2U, s[0]->InputCount());
437 ASSERT_TRUE(s[0]->InputAt(1)->IsImmediate());
438 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
439 EXPECT_EQ(1U, s[0]->OutputCount());
444 TEST_P(InstructionSelectorAddSubTest, ShiftByImmediateOnRight) {
445 const AddSub dpi = GetParam();
446 const MachineType type = dpi.mi.machine_type;
447 TRACED_FOREACH(Shift, shift, kShiftInstructions) {
448 // Only test 64-bit shifted operands with 64-bit instructions.
449 if (shift.mi.machine_type != type) continue;
451 if ((shift.mi.arch_opcode == kArm64Ror32) ||
452 (shift.mi.arch_opcode == kArm64Ror)) {
453 // Not supported by add/sub instructions.
457 TRACED_FORRANGE(int, imm, 0, ((type == kMachInt32) ? 31 : 63)) {
458 StreamBuilder m(this, type, type, type);
459 m.Return((m.*dpi.mi.constructor)(
461 (m.*shift.mi.constructor)(m.Parameter(1),
462 BuildConstant(m, type, imm))));
463 Stream s = m.Build();
464 ASSERT_EQ(1U, s.size());
465 EXPECT_EQ(dpi.mi.arch_opcode, s[0]->arch_opcode());
466 EXPECT_EQ(shift.mode, s[0]->addressing_mode());
467 EXPECT_EQ(3U, s[0]->InputCount());
468 EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(2)));
469 EXPECT_EQ(1U, s[0]->OutputCount());
475 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorAddSubTest,
476 ::testing::ValuesIn(kAddSubInstructions));
479 TEST_F(InstructionSelectorTest, AddImmediateOnLeft) {
482 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
483 StreamBuilder m(this, kMachInt32, kMachInt32);
484 m.Return(m.Int32Add(m.Int32Constant(imm), m.Parameter(0)));
485 Stream s = m.Build();
486 ASSERT_EQ(1U, s.size());
487 EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
488 ASSERT_EQ(2U, s[0]->InputCount());
489 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
490 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
491 EXPECT_EQ(1U, s[0]->OutputCount());
496 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
497 StreamBuilder m(this, kMachInt64, kMachInt64);
498 m.Return(m.Int64Add(m.Int64Constant(imm), m.Parameter(0)));
499 Stream s = m.Build();
500 ASSERT_EQ(1U, s.size());
501 EXPECT_EQ(kArm64Add, s[0]->arch_opcode());
502 ASSERT_EQ(2U, s[0]->InputCount());
503 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
504 EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(1)));
505 EXPECT_EQ(1U, s[0]->OutputCount());
511 TEST_F(InstructionSelectorTest, SubZeroOnLeft) {
512 // Subtraction with zero on the left maps to Neg.
515 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
516 m.Return(m.Int32Sub(m.Int32Constant(0), m.Parameter(0)));
517 Stream s = m.Build();
519 ASSERT_EQ(1U, s.size());
520 EXPECT_EQ(kArm64Neg32, s[0]->arch_opcode());
521 EXPECT_EQ(1U, s[0]->InputCount());
522 EXPECT_EQ(1U, s[0]->OutputCount());
526 StreamBuilder m(this, kMachInt64, kMachInt64, kMachInt64);
527 m.Return(m.Int64Sub(m.Int64Constant(0), m.Parameter(0)));
528 Stream s = m.Build();
530 ASSERT_EQ(1U, s.size());
531 EXPECT_EQ(kArm64Neg, s[0]->arch_opcode());
532 EXPECT_EQ(1U, s[0]->InputCount());
533 EXPECT_EQ(1U, s[0]->OutputCount());
538 TEST_F(InstructionSelectorTest, AddNegImmediateOnLeft) {
541 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
542 if (imm == 0) continue;
543 StreamBuilder m(this, kMachInt32, kMachInt32);
544 m.Return(m.Int32Add(m.Int32Constant(-imm), m.Parameter(0)));
545 Stream s = m.Build();
547 ASSERT_EQ(1U, s.size());
548 EXPECT_EQ(kArm64Sub32, s[0]->arch_opcode());
549 ASSERT_EQ(2U, s[0]->InputCount());
550 ASSERT_TRUE(s[0]->InputAt(1)->IsImmediate());
551 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
552 EXPECT_EQ(1U, s[0]->OutputCount());
557 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
558 if (imm == 0) continue;
559 StreamBuilder m(this, kMachInt64, kMachInt64);
560 m.Return(m.Int64Add(m.Int64Constant(-imm), m.Parameter(0)));
561 Stream s = m.Build();
563 ASSERT_EQ(1U, s.size());
564 EXPECT_EQ(kArm64Sub, s[0]->arch_opcode());
565 ASSERT_EQ(2U, s[0]->InputCount());
566 ASSERT_TRUE(s[0]->InputAt(1)->IsImmediate());
567 EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(1)));
568 EXPECT_EQ(1U, s[0]->OutputCount());
574 TEST_F(InstructionSelectorTest, AddShiftByImmediateOnLeft) {
576 TRACED_FOREACH(Shift, shift, kShiftInstructions) {
577 // Only test relevant shifted operands.
578 if (shift.mi.machine_type != kMachInt32) continue;
579 if (shift.mi.arch_opcode == kArm64Ror32) continue;
581 TRACED_FORRANGE(int, imm, 0, 31) {
582 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
583 m.Return((m.Int32Add)(
584 (m.*shift.mi.constructor)(m.Parameter(1), m.Int32Constant(imm)),
586 Stream s = m.Build();
587 ASSERT_EQ(1U, s.size());
588 EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
589 EXPECT_EQ(shift.mode, s[0]->addressing_mode());
590 EXPECT_EQ(3U, s[0]->InputCount());
591 EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(2)));
592 EXPECT_EQ(1U, s[0]->OutputCount());
597 TRACED_FOREACH(Shift, shift, kShiftInstructions) {
598 // Only test relevant shifted operands.
599 if (shift.mi.machine_type != kMachInt64) continue;
600 if (shift.mi.arch_opcode == kArm64Ror) continue;
602 TRACED_FORRANGE(int, imm, 0, 63) {
603 StreamBuilder m(this, kMachInt64, kMachInt64, kMachInt64);
604 m.Return((m.Int64Add)(
605 (m.*shift.mi.constructor)(m.Parameter(1), m.Int64Constant(imm)),
607 Stream s = m.Build();
608 ASSERT_EQ(1U, s.size());
609 EXPECT_EQ(kArm64Add, s[0]->arch_opcode());
610 EXPECT_EQ(shift.mode, s[0]->addressing_mode());
611 EXPECT_EQ(3U, s[0]->InputCount());
612 EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(2)));
613 EXPECT_EQ(1U, s[0]->OutputCount());
619 // -----------------------------------------------------------------------------
620 // Data processing controlled branches.
623 typedef InstructionSelectorTestWithParam<MachInst2>
624 InstructionSelectorDPFlagSetTest;
627 TEST_P(InstructionSelectorDPFlagSetTest, BranchWithParameters) {
628 const MachInst2 dpi = GetParam();
629 const MachineType type = dpi.machine_type;
630 StreamBuilder m(this, type, type, type);
632 m.Branch((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)), &a, &b);
634 m.Return(m.Int32Constant(1));
636 m.Return(m.Int32Constant(0));
637 Stream s = m.Build();
638 ASSERT_EQ(1U, s.size());
639 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
640 EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
641 EXPECT_EQ(kNotEqual, s[0]->flags_condition());
645 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
646 InstructionSelectorDPFlagSetTest,
647 ::testing::ValuesIn(kDPFlagSetInstructions));
650 TEST_F(InstructionSelectorTest, Word32AndBranchWithImmediateOnRight) {
651 TRACED_FOREACH(int32_t, imm, kLogical32Immediates) {
652 // Skip the cases where the instruction selector would use tbz/tbnz.
653 if (base::bits::CountPopulation32(imm) == 1) continue;
655 StreamBuilder m(this, kMachInt32, kMachInt32);
657 m.Branch(m.Word32And(m.Parameter(0), m.Int32Constant(imm)), &a, &b);
659 m.Return(m.Int32Constant(1));
661 m.Return(m.Int32Constant(0));
662 Stream s = m.Build();
663 ASSERT_EQ(1U, s.size());
664 EXPECT_EQ(kArm64Tst32, s[0]->arch_opcode());
665 EXPECT_EQ(4U, s[0]->InputCount());
666 EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
667 EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
668 EXPECT_EQ(kNotEqual, s[0]->flags_condition());
673 TEST_F(InstructionSelectorTest, Word64AndBranchWithImmediateOnRight) {
674 TRACED_FOREACH(int64_t, imm, kLogical64Immediates) {
675 // Skip the cases where the instruction selector would use tbz/tbnz.
676 if (base::bits::CountPopulation64(imm) == 1) continue;
678 StreamBuilder m(this, kMachInt64, kMachInt64);
680 m.Branch(m.Word64And(m.Parameter(0), m.Int64Constant(imm)), &a, &b);
682 m.Return(m.Int32Constant(1));
684 m.Return(m.Int32Constant(0));
685 Stream s = m.Build();
686 ASSERT_EQ(1U, s.size());
687 EXPECT_EQ(kArm64Tst, s[0]->arch_opcode());
688 EXPECT_EQ(4U, s[0]->InputCount());
689 EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
690 EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
691 EXPECT_EQ(kNotEqual, s[0]->flags_condition());
696 TEST_F(InstructionSelectorTest, AddBranchWithImmediateOnRight) {
697 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
698 StreamBuilder m(this, kMachInt32, kMachInt32);
700 m.Branch(m.Int32Add(m.Parameter(0), m.Int32Constant(imm)), &a, &b);
702 m.Return(m.Int32Constant(1));
704 m.Return(m.Int32Constant(0));
705 Stream s = m.Build();
706 ASSERT_EQ(1U, s.size());
707 EXPECT_EQ(kArm64Cmn32, s[0]->arch_opcode());
708 EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
709 EXPECT_EQ(kNotEqual, s[0]->flags_condition());
714 TEST_F(InstructionSelectorTest, SubBranchWithImmediateOnRight) {
715 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
716 StreamBuilder m(this, kMachInt32, kMachInt32);
718 m.Branch(m.Int32Sub(m.Parameter(0), m.Int32Constant(imm)), &a, &b);
720 m.Return(m.Int32Constant(1));
722 m.Return(m.Int32Constant(0));
723 Stream s = m.Build();
724 ASSERT_EQ(1U, s.size());
725 EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode());
726 EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
727 EXPECT_EQ(kNotEqual, s[0]->flags_condition());
732 TEST_F(InstructionSelectorTest, Word32AndBranchWithImmediateOnLeft) {
733 TRACED_FOREACH(int32_t, imm, kLogical32Immediates) {
734 // Skip the cases where the instruction selector would use tbz/tbnz.
735 if (base::bits::CountPopulation32(imm) == 1) continue;
737 StreamBuilder m(this, kMachInt32, kMachInt32);
739 m.Branch(m.Word32And(m.Int32Constant(imm), m.Parameter(0)), &a, &b);
741 m.Return(m.Int32Constant(1));
743 m.Return(m.Int32Constant(0));
744 Stream s = m.Build();
745 ASSERT_EQ(1U, s.size());
746 EXPECT_EQ(kArm64Tst32, s[0]->arch_opcode());
747 EXPECT_EQ(4U, s[0]->InputCount());
748 EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
749 ASSERT_LE(1U, s[0]->InputCount());
750 EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
751 EXPECT_EQ(kNotEqual, s[0]->flags_condition());
756 TEST_F(InstructionSelectorTest, Word64AndBranchWithImmediateOnLeft) {
757 TRACED_FOREACH(int64_t, imm, kLogical64Immediates) {
758 // Skip the cases where the instruction selector would use tbz/tbnz.
759 if (base::bits::CountPopulation64(imm) == 1) continue;
761 StreamBuilder m(this, kMachInt64, kMachInt64);
763 m.Branch(m.Word64And(m.Int64Constant(imm), m.Parameter(0)), &a, &b);
765 m.Return(m.Int32Constant(1));
767 m.Return(m.Int32Constant(0));
768 Stream s = m.Build();
769 ASSERT_EQ(1U, s.size());
770 EXPECT_EQ(kArm64Tst, s[0]->arch_opcode());
771 EXPECT_EQ(4U, s[0]->InputCount());
772 EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
773 ASSERT_LE(1U, s[0]->InputCount());
774 EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
775 EXPECT_EQ(kNotEqual, s[0]->flags_condition());
780 TEST_F(InstructionSelectorTest, AddBranchWithImmediateOnLeft) {
781 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
782 StreamBuilder m(this, kMachInt32, kMachInt32);
784 m.Branch(m.Int32Add(m.Int32Constant(imm), m.Parameter(0)), &a, &b);
786 m.Return(m.Int32Constant(1));
788 m.Return(m.Int32Constant(0));
789 Stream s = m.Build();
790 ASSERT_EQ(1U, s.size());
791 EXPECT_EQ(kArm64Cmn32, s[0]->arch_opcode());
792 ASSERT_LE(1U, s[0]->InputCount());
793 EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
794 EXPECT_EQ(kNotEqual, s[0]->flags_condition());
799 TEST_F(InstructionSelectorTest, Word32AndBranchWithOneBitMaskOnRight) {
800 TRACED_FORRANGE(int, bit, 0, 31) {
801 uint32_t mask = 1 << bit;
802 StreamBuilder m(this, kMachInt32, kMachInt32);
804 m.Branch(m.Word32And(m.Parameter(0), m.Int32Constant(mask)), &a, &b);
806 m.Return(m.Int32Constant(1));
808 m.Return(m.Int32Constant(0));
809 Stream s = m.Build();
810 ASSERT_EQ(1U, s.size());
811 EXPECT_EQ(kArm64Tbnz32, s[0]->arch_opcode());
812 EXPECT_EQ(4U, s[0]->InputCount());
813 EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
814 EXPECT_EQ(bit, s.ToInt32(s[0]->InputAt(1)));
817 TRACED_FORRANGE(int, bit, 0, 31) {
818 uint32_t mask = 1 << bit;
819 StreamBuilder m(this, kMachInt32, kMachInt32);
822 m.Word32BinaryNot(m.Word32And(m.Parameter(0), m.Int32Constant(mask))),
825 m.Return(m.Int32Constant(1));
827 m.Return(m.Int32Constant(0));
828 Stream s = m.Build();
829 ASSERT_EQ(1U, s.size());
830 EXPECT_EQ(kArm64Tbz32, s[0]->arch_opcode());
831 EXPECT_EQ(4U, s[0]->InputCount());
832 EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
833 EXPECT_EQ(bit, s.ToInt32(s[0]->InputAt(1)));
838 TEST_F(InstructionSelectorTest, Word32AndBranchWithOneBitMaskOnLeft) {
839 TRACED_FORRANGE(int, bit, 0, 31) {
840 uint32_t mask = 1 << bit;
841 StreamBuilder m(this, kMachInt32, kMachInt32);
843 m.Branch(m.Word32And(m.Int32Constant(mask), m.Parameter(0)), &a, &b);
845 m.Return(m.Int32Constant(1));
847 m.Return(m.Int32Constant(0));
848 Stream s = m.Build();
849 ASSERT_EQ(1U, s.size());
850 EXPECT_EQ(kArm64Tbnz32, s[0]->arch_opcode());
851 EXPECT_EQ(4U, s[0]->InputCount());
852 EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
853 EXPECT_EQ(bit, s.ToInt32(s[0]->InputAt(1)));
856 TRACED_FORRANGE(int, bit, 0, 31) {
857 uint32_t mask = 1 << bit;
858 StreamBuilder m(this, kMachInt32, kMachInt32);
861 m.Word32BinaryNot(m.Word32And(m.Int32Constant(mask), m.Parameter(0))),
864 m.Return(m.Int32Constant(1));
866 m.Return(m.Int32Constant(0));
867 Stream s = m.Build();
868 ASSERT_EQ(1U, s.size());
869 EXPECT_EQ(kArm64Tbz32, s[0]->arch_opcode());
870 EXPECT_EQ(4U, s[0]->InputCount());
871 EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
872 EXPECT_EQ(bit, s.ToInt32(s[0]->InputAt(1)));
877 TEST_F(InstructionSelectorTest, Word64AndBranchWithOneBitMaskOnRight) {
878 TRACED_FORRANGE(int, bit, 0, 63) {
879 uint64_t mask = 1L << bit;
880 StreamBuilder m(this, kMachInt64, kMachInt64);
882 m.Branch(m.Word64And(m.Parameter(0), m.Int64Constant(mask)), &a, &b);
884 m.Return(m.Int32Constant(1));
886 m.Return(m.Int32Constant(0));
887 Stream s = m.Build();
888 ASSERT_EQ(1U, s.size());
889 EXPECT_EQ(kArm64Tbnz, s[0]->arch_opcode());
890 EXPECT_EQ(4U, s[0]->InputCount());
891 EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
892 EXPECT_EQ(bit, s.ToInt64(s[0]->InputAt(1)));
895 TRACED_FORRANGE(int, bit, 0, 63) {
896 uint64_t mask = 1L << bit;
897 StreamBuilder m(this, kMachInt64, kMachInt64);
900 m.Word64BinaryNot(m.Word64And(m.Parameter(0), m.Int64Constant(mask))),
903 m.Return(m.Int32Constant(1));
905 m.Return(m.Int32Constant(0));
906 Stream s = m.Build();
907 ASSERT_EQ(1U, s.size());
908 EXPECT_EQ(kArm64Tbz, s[0]->arch_opcode());
909 EXPECT_EQ(4U, s[0]->InputCount());
910 EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
911 EXPECT_EQ(bit, s.ToInt64(s[0]->InputAt(1)));
916 TEST_F(InstructionSelectorTest, Word64AndBranchWithOneBitMaskOnLeft) {
917 TRACED_FORRANGE(int, bit, 0, 63) {
918 uint64_t mask = 1L << bit;
919 StreamBuilder m(this, kMachInt64, kMachInt64);
921 m.Branch(m.Word64And(m.Int64Constant(mask), m.Parameter(0)), &a, &b);
923 m.Return(m.Int32Constant(1));
925 m.Return(m.Int32Constant(0));
926 Stream s = m.Build();
927 ASSERT_EQ(1U, s.size());
928 EXPECT_EQ(kArm64Tbnz, s[0]->arch_opcode());
929 EXPECT_EQ(4U, s[0]->InputCount());
930 EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
931 EXPECT_EQ(bit, s.ToInt64(s[0]->InputAt(1)));
934 TRACED_FORRANGE(int, bit, 0, 63) {
935 uint64_t mask = 1L << bit;
936 StreamBuilder m(this, kMachInt64, kMachInt64);
939 m.Word64BinaryNot(m.Word64And(m.Int64Constant(mask), m.Parameter(0))),
942 m.Return(m.Int32Constant(1));
944 m.Return(m.Int32Constant(0));
945 Stream s = m.Build();
946 ASSERT_EQ(1U, s.size());
947 EXPECT_EQ(kArm64Tbz, s[0]->arch_opcode());
948 EXPECT_EQ(4U, s[0]->InputCount());
949 EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
950 EXPECT_EQ(bit, s.ToInt64(s[0]->InputAt(1)));
955 // -----------------------------------------------------------------------------
956 // Add and subtract instructions with overflow.
959 typedef InstructionSelectorTestWithParam<MachInst2>
960 InstructionSelectorOvfAddSubTest;
963 TEST_P(InstructionSelectorOvfAddSubTest, OvfParameter) {
964 const MachInst2 dpi = GetParam();
965 const MachineType type = dpi.machine_type;
966 StreamBuilder m(this, type, type, type);
968 m.Projection(1, (m.*dpi.constructor)(m.Parameter(0), m.Parameter(1))));
969 Stream s = m.Build();
970 ASSERT_EQ(1U, s.size());
971 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
972 EXPECT_EQ(2U, s[0]->InputCount());
973 EXPECT_LE(1U, s[0]->OutputCount());
974 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
975 EXPECT_EQ(kOverflow, s[0]->flags_condition());
979 TEST_P(InstructionSelectorOvfAddSubTest, OvfImmediateOnRight) {
980 const MachInst2 dpi = GetParam();
981 const MachineType type = dpi.machine_type;
982 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
983 StreamBuilder m(this, type, type);
984 m.Return(m.Projection(
985 1, (m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm))));
986 Stream s = m.Build();
987 ASSERT_EQ(1U, s.size());
988 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
989 ASSERT_EQ(2U, s[0]->InputCount());
990 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
991 EXPECT_LE(1U, s[0]->OutputCount());
992 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
993 EXPECT_EQ(kOverflow, s[0]->flags_condition());
998 TEST_P(InstructionSelectorOvfAddSubTest, ValParameter) {
999 const MachInst2 dpi = GetParam();
1000 const MachineType type = dpi.machine_type;
1001 StreamBuilder m(this, type, type, type);
1003 m.Projection(0, (m.*dpi.constructor)(m.Parameter(0), m.Parameter(1))));
1004 Stream s = m.Build();
1005 ASSERT_EQ(1U, s.size());
1006 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
1007 EXPECT_EQ(2U, s[0]->InputCount());
1008 EXPECT_LE(1U, s[0]->OutputCount());
1009 EXPECT_EQ(kFlags_none, s[0]->flags_mode());
1013 TEST_P(InstructionSelectorOvfAddSubTest, ValImmediateOnRight) {
1014 const MachInst2 dpi = GetParam();
1015 const MachineType type = dpi.machine_type;
1016 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
1017 StreamBuilder m(this, type, type);
1018 m.Return(m.Projection(
1019 0, (m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm))));
1020 Stream s = m.Build();
1021 ASSERT_EQ(1U, s.size());
1022 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
1023 ASSERT_EQ(2U, s[0]->InputCount());
1024 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
1025 EXPECT_LE(1U, s[0]->OutputCount());
1026 EXPECT_EQ(kFlags_none, s[0]->flags_mode());
1031 TEST_P(InstructionSelectorOvfAddSubTest, BothParameter) {
1032 const MachInst2 dpi = GetParam();
1033 const MachineType type = dpi.machine_type;
1034 StreamBuilder m(this, type, type, type);
1035 Node* n = (m.*dpi.constructor)(m.Parameter(0), m.Parameter(1));
1036 m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n)));
1037 Stream s = m.Build();
1038 ASSERT_LE(1U, s.size());
1039 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
1040 EXPECT_EQ(2U, s[0]->InputCount());
1041 EXPECT_EQ(2U, s[0]->OutputCount());
1042 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1043 EXPECT_EQ(kOverflow, s[0]->flags_condition());
1047 TEST_P(InstructionSelectorOvfAddSubTest, BothImmediateOnRight) {
1048 const MachInst2 dpi = GetParam();
1049 const MachineType type = dpi.machine_type;
1050 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
1051 StreamBuilder m(this, type, type);
1052 Node* n = (m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm));
1053 m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n)));
1054 Stream s = m.Build();
1055 ASSERT_LE(1U, s.size());
1056 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
1057 ASSERT_EQ(2U, s[0]->InputCount());
1058 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
1059 EXPECT_EQ(2U, s[0]->OutputCount());
1060 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1061 EXPECT_EQ(kOverflow, s[0]->flags_condition());
1066 TEST_P(InstructionSelectorOvfAddSubTest, BranchWithParameters) {
1067 const MachInst2 dpi = GetParam();
1068 const MachineType type = dpi.machine_type;
1069 StreamBuilder m(this, type, type, type);
1071 Node* n = (m.*dpi.constructor)(m.Parameter(0), m.Parameter(1));
1072 m.Branch(m.Projection(1, n), &a, &b);
1074 m.Return(m.Int32Constant(0));
1076 m.Return(m.Projection(0, n));
1077 Stream s = m.Build();
1078 ASSERT_EQ(1U, s.size());
1079 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
1080 EXPECT_EQ(4U, s[0]->InputCount());
1081 EXPECT_EQ(1U, s[0]->OutputCount());
1082 EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
1083 EXPECT_EQ(kOverflow, s[0]->flags_condition());
1087 TEST_P(InstructionSelectorOvfAddSubTest, BranchWithImmediateOnRight) {
1088 const MachInst2 dpi = GetParam();
1089 const MachineType type = dpi.machine_type;
1090 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
1091 StreamBuilder m(this, type, type);
1093 Node* n = (m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm));
1094 m.Branch(m.Projection(1, n), &a, &b);
1096 m.Return(m.Int32Constant(0));
1098 m.Return(m.Projection(0, n));
1099 Stream s = m.Build();
1100 ASSERT_EQ(1U, s.size());
1101 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
1102 ASSERT_EQ(4U, s[0]->InputCount());
1103 EXPECT_EQ(1U, s[0]->OutputCount());
1104 EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
1105 EXPECT_EQ(kOverflow, s[0]->flags_condition());
1110 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1111 InstructionSelectorOvfAddSubTest,
1112 ::testing::ValuesIn(kOvfAddSubInstructions));
1115 TEST_F(InstructionSelectorTest, OvfFlagAddImmediateOnLeft) {
1116 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
1117 StreamBuilder m(this, kMachInt32, kMachInt32);
1118 m.Return(m.Projection(
1119 1, m.Int32AddWithOverflow(m.Int32Constant(imm), m.Parameter(0))));
1120 Stream s = m.Build();
1122 ASSERT_EQ(1U, s.size());
1123 EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
1124 EXPECT_EQ(2U, s[0]->InputCount());
1125 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
1126 EXPECT_LE(1U, s[0]->OutputCount());
1127 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1128 EXPECT_EQ(kOverflow, s[0]->flags_condition());
1133 TEST_F(InstructionSelectorTest, OvfValAddImmediateOnLeft) {
1134 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
1135 StreamBuilder m(this, kMachInt32, kMachInt32);
1136 m.Return(m.Projection(
1137 0, m.Int32AddWithOverflow(m.Int32Constant(imm), m.Parameter(0))));
1138 Stream s = m.Build();
1140 ASSERT_EQ(1U, s.size());
1141 EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
1142 ASSERT_EQ(2U, s[0]->InputCount());
1143 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
1144 EXPECT_LE(1U, s[0]->OutputCount());
1145 EXPECT_EQ(kFlags_none, s[0]->flags_mode());
1150 TEST_F(InstructionSelectorTest, OvfBothAddImmediateOnLeft) {
1151 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
1152 StreamBuilder m(this, kMachInt32, kMachInt32);
1153 Node* n = m.Int32AddWithOverflow(m.Int32Constant(imm), m.Parameter(0));
1154 m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n)));
1155 Stream s = m.Build();
1157 ASSERT_LE(1U, s.size());
1158 EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
1159 ASSERT_EQ(2U, s[0]->InputCount());
1160 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
1161 EXPECT_EQ(2U, s[0]->OutputCount());
1162 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1163 EXPECT_EQ(kOverflow, s[0]->flags_condition());
1168 TEST_F(InstructionSelectorTest, OvfBranchWithImmediateOnLeft) {
1169 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
1170 StreamBuilder m(this, kMachInt32, kMachInt32);
1172 Node* n = m.Int32AddWithOverflow(m.Int32Constant(imm), m.Parameter(0));
1173 m.Branch(m.Projection(1, n), &a, &b);
1175 m.Return(m.Int32Constant(0));
1177 m.Return(m.Projection(0, n));
1178 Stream s = m.Build();
1180 ASSERT_EQ(1U, s.size());
1181 EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
1182 ASSERT_EQ(4U, s[0]->InputCount());
1183 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
1184 EXPECT_EQ(1U, s[0]->OutputCount());
1185 EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
1186 EXPECT_EQ(kOverflow, s[0]->flags_condition());
1191 // -----------------------------------------------------------------------------
1192 // Shift instructions.
1195 typedef InstructionSelectorTestWithParam<Shift> InstructionSelectorShiftTest;
1198 TEST_P(InstructionSelectorShiftTest, Parameter) {
1199 const Shift shift = GetParam();
1200 const MachineType type = shift.mi.machine_type;
1201 StreamBuilder m(this, type, type, type);
1202 m.Return((m.*shift.mi.constructor)(m.Parameter(0), m.Parameter(1)));
1203 Stream s = m.Build();
1204 ASSERT_EQ(1U, s.size());
1205 EXPECT_EQ(shift.mi.arch_opcode, s[0]->arch_opcode());
1206 EXPECT_EQ(2U, s[0]->InputCount());
1207 EXPECT_EQ(1U, s[0]->OutputCount());
1211 TEST_P(InstructionSelectorShiftTest, Immediate) {
1212 const Shift shift = GetParam();
1213 const MachineType type = shift.mi.machine_type;
1214 TRACED_FORRANGE(int32_t, imm, 0, (ElementSizeOf(type) * 8) - 1) {
1215 StreamBuilder m(this, type, type);
1216 m.Return((m.*shift.mi.constructor)(m.Parameter(0), m.Int32Constant(imm)));
1217 Stream s = m.Build();
1218 ASSERT_EQ(1U, s.size());
1219 EXPECT_EQ(shift.mi.arch_opcode, s[0]->arch_opcode());
1220 EXPECT_EQ(2U, s[0]->InputCount());
1221 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
1222 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
1223 EXPECT_EQ(1U, s[0]->OutputCount());
1228 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorShiftTest,
1229 ::testing::ValuesIn(kShiftInstructions));
1232 // -----------------------------------------------------------------------------
1233 // Mul and Div instructions.
1236 typedef InstructionSelectorTestWithParam<MachInst2>
1237 InstructionSelectorMulDivTest;
1240 TEST_P(InstructionSelectorMulDivTest, Parameter) {
1241 const MachInst2 dpi = GetParam();
1242 const MachineType type = dpi.machine_type;
1243 StreamBuilder m(this, type, type, type);
1244 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)));
1245 Stream s = m.Build();
1246 ASSERT_EQ(1U, s.size());
1247 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
1248 EXPECT_EQ(2U, s[0]->InputCount());
1249 EXPECT_EQ(1U, s[0]->OutputCount());
1253 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorMulDivTest,
1254 ::testing::ValuesIn(kMulDivInstructions));
1260 const char* mul_constructor_name;
1261 Node* (RawMachineAssembler::*mul_constructor)(Node*, Node*);
1262 Node* (RawMachineAssembler::*add_constructor)(Node*, Node*);
1263 Node* (RawMachineAssembler::*sub_constructor)(Node*, Node*);
1264 ArchOpcode add_arch_opcode;
1265 ArchOpcode sub_arch_opcode;
1266 ArchOpcode neg_arch_opcode;
1267 MachineType machine_type;
1271 std::ostream& operator<<(std::ostream& os, const MulDPInst& inst) {
1272 return os << inst.mul_constructor_name;
1278 static const MulDPInst kMulDPInstructions[] = {
1279 {"Int32Mul", &RawMachineAssembler::Int32Mul, &RawMachineAssembler::Int32Add,
1280 &RawMachineAssembler::Int32Sub, kArm64Madd32, kArm64Msub32, kArm64Mneg32,
1282 {"Int64Mul", &RawMachineAssembler::Int64Mul, &RawMachineAssembler::Int64Add,
1283 &RawMachineAssembler::Int64Sub, kArm64Madd, kArm64Msub, kArm64Mneg,
1287 typedef InstructionSelectorTestWithParam<MulDPInst>
1288 InstructionSelectorIntDPWithIntMulTest;
1291 TEST_P(InstructionSelectorIntDPWithIntMulTest, AddWithMul) {
1292 const MulDPInst mdpi = GetParam();
1293 const MachineType type = mdpi.machine_type;
1295 StreamBuilder m(this, type, type, type, type);
1296 Node* n = (m.*mdpi.mul_constructor)(m.Parameter(1), m.Parameter(2));
1297 m.Return((m.*mdpi.add_constructor)(m.Parameter(0), n));
1298 Stream s = m.Build();
1299 ASSERT_EQ(1U, s.size());
1300 EXPECT_EQ(mdpi.add_arch_opcode, s[0]->arch_opcode());
1301 EXPECT_EQ(3U, s[0]->InputCount());
1302 EXPECT_EQ(1U, s[0]->OutputCount());
1305 StreamBuilder m(this, type, type, type, type);
1306 Node* n = (m.*mdpi.mul_constructor)(m.Parameter(0), m.Parameter(1));
1307 m.Return((m.*mdpi.add_constructor)(n, m.Parameter(2)));
1308 Stream s = m.Build();
1309 ASSERT_EQ(1U, s.size());
1310 EXPECT_EQ(mdpi.add_arch_opcode, s[0]->arch_opcode());
1311 EXPECT_EQ(3U, s[0]->InputCount());
1312 EXPECT_EQ(1U, s[0]->OutputCount());
1317 TEST_P(InstructionSelectorIntDPWithIntMulTest, SubWithMul) {
1318 const MulDPInst mdpi = GetParam();
1319 const MachineType type = mdpi.machine_type;
1321 StreamBuilder m(this, type, type, type, type);
1322 Node* n = (m.*mdpi.mul_constructor)(m.Parameter(1), m.Parameter(2));
1323 m.Return((m.*mdpi.sub_constructor)(m.Parameter(0), n));
1324 Stream s = m.Build();
1325 ASSERT_EQ(1U, s.size());
1326 EXPECT_EQ(mdpi.sub_arch_opcode, s[0]->arch_opcode());
1327 EXPECT_EQ(3U, s[0]->InputCount());
1328 EXPECT_EQ(1U, s[0]->OutputCount());
1333 TEST_P(InstructionSelectorIntDPWithIntMulTest, NegativeMul) {
1334 const MulDPInst mdpi = GetParam();
1335 const MachineType type = mdpi.machine_type;
1337 StreamBuilder m(this, type, type, type);
1339 (m.*mdpi.sub_constructor)(BuildConstant(m, type, 0), m.Parameter(0));
1340 m.Return((m.*mdpi.mul_constructor)(n, m.Parameter(1)));
1341 Stream s = m.Build();
1342 ASSERT_EQ(1U, s.size());
1343 EXPECT_EQ(mdpi.neg_arch_opcode, s[0]->arch_opcode());
1344 EXPECT_EQ(2U, s[0]->InputCount());
1345 EXPECT_EQ(1U, s[0]->OutputCount());
1348 StreamBuilder m(this, type, type, type);
1350 (m.*mdpi.sub_constructor)(BuildConstant(m, type, 0), m.Parameter(1));
1351 m.Return((m.*mdpi.mul_constructor)(m.Parameter(0), n));
1352 Stream s = m.Build();
1353 ASSERT_EQ(1U, s.size());
1354 EXPECT_EQ(mdpi.neg_arch_opcode, s[0]->arch_opcode());
1355 EXPECT_EQ(2U, s[0]->InputCount());
1356 EXPECT_EQ(1U, s[0]->OutputCount());
1361 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1362 InstructionSelectorIntDPWithIntMulTest,
1363 ::testing::ValuesIn(kMulDPInstructions));
1366 // -----------------------------------------------------------------------------
1367 // Floating point instructions.
1369 typedef InstructionSelectorTestWithParam<MachInst2>
1370 InstructionSelectorFPArithTest;
1373 TEST_P(InstructionSelectorFPArithTest, Parameter) {
1374 const MachInst2 fpa = GetParam();
1375 StreamBuilder m(this, fpa.machine_type, fpa.machine_type, fpa.machine_type);
1376 m.Return((m.*fpa.constructor)(m.Parameter(0), m.Parameter(1)));
1377 Stream s = m.Build();
1378 ASSERT_EQ(1U, s.size());
1379 EXPECT_EQ(fpa.arch_opcode, s[0]->arch_opcode());
1380 EXPECT_EQ(2U, s[0]->InputCount());
1381 EXPECT_EQ(1U, s[0]->OutputCount());
1385 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorFPArithTest,
1386 ::testing::ValuesIn(kFPArithInstructions));
1389 typedef InstructionSelectorTestWithParam<FPCmp> InstructionSelectorFPCmpTest;
1392 TEST_P(InstructionSelectorFPCmpTest, Parameter) {
1393 const FPCmp cmp = GetParam();
1394 StreamBuilder m(this, kMachInt32, cmp.mi.machine_type, cmp.mi.machine_type);
1395 m.Return((m.*cmp.mi.constructor)(m.Parameter(0), m.Parameter(1)));
1396 Stream s = m.Build();
1397 ASSERT_EQ(1U, s.size());
1398 EXPECT_EQ(cmp.mi.arch_opcode, s[0]->arch_opcode());
1399 EXPECT_EQ(2U, s[0]->InputCount());
1400 EXPECT_EQ(1U, s[0]->OutputCount());
1401 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1402 EXPECT_EQ(cmp.cond, s[0]->flags_condition());
1406 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorFPCmpTest,
1407 ::testing::ValuesIn(kFPCmpInstructions));
1410 // -----------------------------------------------------------------------------
1413 typedef InstructionSelectorTestWithParam<Conversion>
1414 InstructionSelectorConversionTest;
1417 TEST_P(InstructionSelectorConversionTest, Parameter) {
1418 const Conversion conv = GetParam();
1419 StreamBuilder m(this, conv.mi.machine_type, conv.src_machine_type);
1420 m.Return((m.*conv.mi.constructor)(m.Parameter(0)));
1421 Stream s = m.Build();
1422 ASSERT_EQ(1U, s.size());
1423 EXPECT_EQ(conv.mi.arch_opcode, s[0]->arch_opcode());
1424 EXPECT_EQ(1U, s[0]->InputCount());
1425 EXPECT_EQ(1U, s[0]->OutputCount());
1429 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1430 InstructionSelectorConversionTest,
1431 ::testing::ValuesIn(kConversionInstructions));
1434 // -----------------------------------------------------------------------------
1435 // Memory access instructions.
1440 struct MemoryAccess {
1442 ArchOpcode ldr_opcode;
1443 ArchOpcode str_opcode;
1444 const int32_t immediates[20];
1448 std::ostream& operator<<(std::ostream& os, const MemoryAccess& memacc) {
1449 return os << memacc.type;
1455 static const MemoryAccess kMemoryAccesses[] = {
1459 {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 257, 258, 1000, 1001, 2121,
1460 2442, 4093, 4094, 4095}},
1464 {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 257, 258, 1000, 1001, 2121,
1465 2442, 4093, 4094, 4095}},
1469 {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 258, 260, 4096, 4098, 4100,
1470 4242, 6786, 8188, 8190}},
1474 {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 258, 260, 4096, 4098, 4100,
1475 4242, 6786, 8188, 8190}},
1479 {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 260, 4096, 4100, 8192, 8196,
1480 3276, 3280, 16376, 16380}},
1484 {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 260, 4096, 4100, 8192, 8196,
1485 3276, 3280, 16376, 16380}},
1489 {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 264, 4096, 4104, 8192, 8200,
1490 16384, 16392, 32752, 32760}},
1494 {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 264, 4096, 4104, 8192, 8200,
1495 16384, 16392, 32752, 32760}},
1499 {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 260, 4096, 4100, 8192, 8196,
1500 3276, 3280, 16376, 16380}},
1504 {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 264, 4096, 4104, 8192, 8200,
1505 16384, 16392, 32752, 32760}}};
1508 typedef InstructionSelectorTestWithParam<MemoryAccess>
1509 InstructionSelectorMemoryAccessTest;
1512 TEST_P(InstructionSelectorMemoryAccessTest, LoadWithParameters) {
1513 const MemoryAccess memacc = GetParam();
1514 StreamBuilder m(this, memacc.type, kMachPtr, kMachInt32);
1515 m.Return(m.Load(memacc.type, m.Parameter(0), m.Parameter(1)));
1516 Stream s = m.Build();
1517 ASSERT_EQ(1U, s.size());
1518 EXPECT_EQ(memacc.ldr_opcode, s[0]->arch_opcode());
1519 EXPECT_EQ(kMode_MRR, s[0]->addressing_mode());
1520 EXPECT_EQ(2U, s[0]->InputCount());
1521 EXPECT_EQ(1U, s[0]->OutputCount());
1525 TEST_P(InstructionSelectorMemoryAccessTest, LoadWithImmediateIndex) {
1526 const MemoryAccess memacc = GetParam();
1527 TRACED_FOREACH(int32_t, index, memacc.immediates) {
1528 StreamBuilder m(this, memacc.type, kMachPtr);
1529 m.Return(m.Load(memacc.type, m.Parameter(0), m.Int32Constant(index)));
1530 Stream s = m.Build();
1531 ASSERT_EQ(1U, s.size());
1532 EXPECT_EQ(memacc.ldr_opcode, s[0]->arch_opcode());
1533 EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
1534 EXPECT_EQ(2U, s[0]->InputCount());
1535 ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
1536 EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1)));
1537 ASSERT_EQ(1U, s[0]->OutputCount());
1542 TEST_P(InstructionSelectorMemoryAccessTest, StoreWithParameters) {
1543 const MemoryAccess memacc = GetParam();
1544 StreamBuilder m(this, kMachInt32, kMachPtr, kMachInt32, memacc.type);
1545 m.Store(memacc.type, m.Parameter(0), m.Parameter(1), m.Parameter(2));
1546 m.Return(m.Int32Constant(0));
1547 Stream s = m.Build();
1548 ASSERT_EQ(1U, s.size());
1549 EXPECT_EQ(memacc.str_opcode, s[0]->arch_opcode());
1550 EXPECT_EQ(kMode_MRR, s[0]->addressing_mode());
1551 EXPECT_EQ(3U, s[0]->InputCount());
1552 EXPECT_EQ(0U, s[0]->OutputCount());
1556 TEST_P(InstructionSelectorMemoryAccessTest, StoreWithImmediateIndex) {
1557 const MemoryAccess memacc = GetParam();
1558 TRACED_FOREACH(int32_t, index, memacc.immediates) {
1559 StreamBuilder m(this, kMachInt32, kMachPtr, memacc.type);
1560 m.Store(memacc.type, m.Parameter(0), m.Int32Constant(index),
1562 m.Return(m.Int32Constant(0));
1563 Stream s = m.Build();
1564 ASSERT_EQ(1U, s.size());
1565 EXPECT_EQ(memacc.str_opcode, s[0]->arch_opcode());
1566 EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
1567 ASSERT_EQ(3U, s[0]->InputCount());
1568 ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
1569 EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1)));
1570 EXPECT_EQ(0U, s[0]->OutputCount());
1575 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1576 InstructionSelectorMemoryAccessTest,
1577 ::testing::ValuesIn(kMemoryAccesses));
1580 // -----------------------------------------------------------------------------
1581 // Comparison instructions.
1583 static const MachInst2 kComparisonInstructions[] = {
1584 {&RawMachineAssembler::Word32Equal, "Word32Equal", kArm64Cmp32, kMachInt32},
1585 {&RawMachineAssembler::Word64Equal, "Word64Equal", kArm64Cmp, kMachInt64},
1589 typedef InstructionSelectorTestWithParam<MachInst2>
1590 InstructionSelectorComparisonTest;
1593 TEST_P(InstructionSelectorComparisonTest, WithParameters) {
1594 const MachInst2 cmp = GetParam();
1595 const MachineType type = cmp.machine_type;
1596 StreamBuilder m(this, type, type, type);
1597 m.Return((m.*cmp.constructor)(m.Parameter(0), m.Parameter(1)));
1598 Stream s = m.Build();
1599 ASSERT_EQ(1U, s.size());
1600 EXPECT_EQ(cmp.arch_opcode, s[0]->arch_opcode());
1601 EXPECT_EQ(2U, s[0]->InputCount());
1602 EXPECT_EQ(1U, s[0]->OutputCount());
1603 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1604 EXPECT_EQ(kEqual, s[0]->flags_condition());
1608 TEST_P(InstructionSelectorComparisonTest, WithImmediate) {
1609 const MachInst2 cmp = GetParam();
1610 const MachineType type = cmp.machine_type;
1611 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
1612 // Compare with 0 are turned into tst instruction.
1613 if (imm == 0) continue;
1614 StreamBuilder m(this, type, type);
1615 m.Return((m.*cmp.constructor)(m.Parameter(0), BuildConstant(m, type, imm)));
1616 Stream s = m.Build();
1617 ASSERT_EQ(1U, s.size());
1618 EXPECT_EQ(cmp.arch_opcode, s[0]->arch_opcode());
1619 ASSERT_EQ(2U, s[0]->InputCount());
1620 ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
1621 EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(1)));
1622 EXPECT_EQ(1U, s[0]->OutputCount());
1623 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1624 EXPECT_EQ(kEqual, s[0]->flags_condition());
1626 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
1627 // Compare with 0 are turned into tst instruction.
1628 if (imm == 0) continue;
1629 StreamBuilder m(this, type, type);
1630 m.Return((m.*cmp.constructor)(BuildConstant(m, type, imm), m.Parameter(0)));
1631 Stream s = m.Build();
1632 ASSERT_EQ(1U, s.size());
1633 EXPECT_EQ(cmp.arch_opcode, s[0]->arch_opcode());
1634 ASSERT_EQ(2U, s[0]->InputCount());
1635 ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
1636 EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(1)));
1637 EXPECT_EQ(1U, s[0]->OutputCount());
1638 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1639 EXPECT_EQ(kEqual, s[0]->flags_condition());
1643 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1644 InstructionSelectorComparisonTest,
1645 ::testing::ValuesIn(kComparisonInstructions));
1648 TEST_F(InstructionSelectorTest, Word32EqualWithZero) {
1650 StreamBuilder m(this, kMachInt32, kMachInt32);
1651 m.Return(m.Word32Equal(m.Parameter(0), m.Int32Constant(0)));
1652 Stream s = m.Build();
1653 ASSERT_EQ(1U, s.size());
1654 EXPECT_EQ(kArm64Tst32, s[0]->arch_opcode());
1655 ASSERT_EQ(2U, s[0]->InputCount());
1656 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
1657 EXPECT_EQ(1U, s[0]->OutputCount());
1658 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1659 EXPECT_EQ(kEqual, s[0]->flags_condition());
1662 StreamBuilder m(this, kMachInt32, kMachInt32);
1663 m.Return(m.Word32Equal(m.Int32Constant(0), m.Parameter(0)));
1664 Stream s = m.Build();
1665 ASSERT_EQ(1U, s.size());
1666 EXPECT_EQ(kArm64Tst32, s[0]->arch_opcode());
1667 ASSERT_EQ(2U, s[0]->InputCount());
1668 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
1669 EXPECT_EQ(1U, s[0]->OutputCount());
1670 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1671 EXPECT_EQ(kEqual, s[0]->flags_condition());
1676 TEST_F(InstructionSelectorTest, Word64EqualWithZero) {
1678 StreamBuilder m(this, kMachInt64, kMachInt64);
1679 m.Return(m.Word64Equal(m.Parameter(0), m.Int64Constant(0)));
1680 Stream s = m.Build();
1681 ASSERT_EQ(1U, s.size());
1682 EXPECT_EQ(kArm64Tst, s[0]->arch_opcode());
1683 ASSERT_EQ(2U, s[0]->InputCount());
1684 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
1685 EXPECT_EQ(1U, s[0]->OutputCount());
1686 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1687 EXPECT_EQ(kEqual, s[0]->flags_condition());
1690 StreamBuilder m(this, kMachInt64, kMachInt64);
1691 m.Return(m.Word64Equal(m.Int64Constant(0), m.Parameter(0)));
1692 Stream s = m.Build();
1693 ASSERT_EQ(1U, s.size());
1694 EXPECT_EQ(kArm64Tst, s[0]->arch_opcode());
1695 ASSERT_EQ(2U, s[0]->InputCount());
1696 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
1697 EXPECT_EQ(1U, s[0]->OutputCount());
1698 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1699 EXPECT_EQ(kEqual, s[0]->flags_condition());
1704 // -----------------------------------------------------------------------------
1708 static const MachInst2 kLogicalWithNotRHSs[] = {
1709 {&RawMachineAssembler::Word32And, "Word32And", kArm64Bic32, kMachInt32},
1710 {&RawMachineAssembler::Word64And, "Word64And", kArm64Bic, kMachInt64},
1711 {&RawMachineAssembler::Word32Or, "Word32Or", kArm64Orn32, kMachInt32},
1712 {&RawMachineAssembler::Word64Or, "Word64Or", kArm64Orn, kMachInt64},
1713 {&RawMachineAssembler::Word32Xor, "Word32Xor", kArm64Eon32, kMachInt32},
1714 {&RawMachineAssembler::Word64Xor, "Word64Xor", kArm64Eon, kMachInt64}};
1717 typedef InstructionSelectorTestWithParam<MachInst2>
1718 InstructionSelectorLogicalWithNotRHSTest;
1721 TEST_P(InstructionSelectorLogicalWithNotRHSTest, Parameter) {
1722 const MachInst2 inst = GetParam();
1723 const MachineType type = inst.machine_type;
1724 // Test cases where RHS is Xor(x, -1).
1726 StreamBuilder m(this, type, type, type);
1727 if (type == kMachInt32) {
1728 m.Return((m.*inst.constructor)(
1729 m.Parameter(0), m.Word32Xor(m.Parameter(1), m.Int32Constant(-1))));
1731 ASSERT_EQ(kMachInt64, type);
1732 m.Return((m.*inst.constructor)(
1733 m.Parameter(0), m.Word64Xor(m.Parameter(1), m.Int64Constant(-1))));
1735 Stream s = m.Build();
1736 ASSERT_EQ(1U, s.size());
1737 EXPECT_EQ(inst.arch_opcode, s[0]->arch_opcode());
1738 EXPECT_EQ(2U, s[0]->InputCount());
1739 EXPECT_EQ(1U, s[0]->OutputCount());
1742 StreamBuilder m(this, type, type, type);
1743 if (type == kMachInt32) {
1744 m.Return((m.*inst.constructor)(
1745 m.Word32Xor(m.Parameter(0), m.Int32Constant(-1)), m.Parameter(1)));
1747 ASSERT_EQ(kMachInt64, type);
1748 m.Return((m.*inst.constructor)(
1749 m.Word64Xor(m.Parameter(0), m.Int64Constant(-1)), m.Parameter(1)));
1751 Stream s = m.Build();
1752 ASSERT_EQ(1U, s.size());
1753 EXPECT_EQ(inst.arch_opcode, s[0]->arch_opcode());
1754 EXPECT_EQ(2U, s[0]->InputCount());
1755 EXPECT_EQ(1U, s[0]->OutputCount());
1757 // Test cases where RHS is Not(x).
1759 StreamBuilder m(this, type, type, type);
1760 if (type == kMachInt32) {
1762 (m.*inst.constructor)(m.Parameter(0), m.Word32Not(m.Parameter(1))));
1764 ASSERT_EQ(kMachInt64, type);
1766 (m.*inst.constructor)(m.Parameter(0), m.Word64Not(m.Parameter(1))));
1768 Stream s = m.Build();
1769 ASSERT_EQ(1U, s.size());
1770 EXPECT_EQ(inst.arch_opcode, s[0]->arch_opcode());
1771 EXPECT_EQ(2U, s[0]->InputCount());
1772 EXPECT_EQ(1U, s[0]->OutputCount());
1775 StreamBuilder m(this, type, type, type);
1776 if (type == kMachInt32) {
1778 (m.*inst.constructor)(m.Word32Not(m.Parameter(0)), m.Parameter(1)));
1780 ASSERT_EQ(kMachInt64, type);
1782 (m.*inst.constructor)(m.Word64Not(m.Parameter(0)), m.Parameter(1)));
1784 Stream s = m.Build();
1785 ASSERT_EQ(1U, s.size());
1786 EXPECT_EQ(inst.arch_opcode, s[0]->arch_opcode());
1787 EXPECT_EQ(2U, s[0]->InputCount());
1788 EXPECT_EQ(1U, s[0]->OutputCount());
1793 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1794 InstructionSelectorLogicalWithNotRHSTest,
1795 ::testing::ValuesIn(kLogicalWithNotRHSs));
1798 TEST_F(InstructionSelectorTest, Word32NotWithParameter) {
1799 StreamBuilder m(this, kMachInt32, kMachInt32);
1800 m.Return(m.Word32Not(m.Parameter(0)));
1801 Stream s = m.Build();
1802 ASSERT_EQ(1U, s.size());
1803 EXPECT_EQ(kArm64Not32, s[0]->arch_opcode());
1804 EXPECT_EQ(1U, s[0]->InputCount());
1805 EXPECT_EQ(1U, s[0]->OutputCount());
1809 TEST_F(InstructionSelectorTest, Word64NotWithParameter) {
1810 StreamBuilder m(this, kMachInt64, kMachInt64);
1811 m.Return(m.Word64Not(m.Parameter(0)));
1812 Stream s = m.Build();
1813 ASSERT_EQ(1U, s.size());
1814 EXPECT_EQ(kArm64Not, s[0]->arch_opcode());
1815 EXPECT_EQ(1U, s[0]->InputCount());
1816 EXPECT_EQ(1U, s[0]->OutputCount());
1820 TEST_F(InstructionSelectorTest, Word32XorMinusOneWithParameter) {
1822 StreamBuilder m(this, kMachInt32, kMachInt32);
1823 m.Return(m.Word32Xor(m.Parameter(0), m.Int32Constant(-1)));
1824 Stream s = m.Build();
1825 ASSERT_EQ(1U, s.size());
1826 EXPECT_EQ(kArm64Not32, s[0]->arch_opcode());
1827 EXPECT_EQ(1U, s[0]->InputCount());
1828 EXPECT_EQ(1U, s[0]->OutputCount());
1831 StreamBuilder m(this, kMachInt32, kMachInt32);
1832 m.Return(m.Word32Xor(m.Int32Constant(-1), m.Parameter(0)));
1833 Stream s = m.Build();
1834 ASSERT_EQ(1U, s.size());
1835 EXPECT_EQ(kArm64Not32, s[0]->arch_opcode());
1836 EXPECT_EQ(1U, s[0]->InputCount());
1837 EXPECT_EQ(1U, s[0]->OutputCount());
1842 TEST_F(InstructionSelectorTest, Word64XorMinusOneWithParameter) {
1844 StreamBuilder m(this, kMachInt64, kMachInt64);
1845 m.Return(m.Word64Xor(m.Parameter(0), m.Int64Constant(-1)));
1846 Stream s = m.Build();
1847 ASSERT_EQ(1U, s.size());
1848 EXPECT_EQ(kArm64Not, s[0]->arch_opcode());
1849 EXPECT_EQ(1U, s[0]->InputCount());
1850 EXPECT_EQ(1U, s[0]->OutputCount());
1853 StreamBuilder m(this, kMachInt64, kMachInt64);
1854 m.Return(m.Word64Xor(m.Int64Constant(-1), m.Parameter(0)));
1855 Stream s = m.Build();
1856 ASSERT_EQ(1U, s.size());
1857 EXPECT_EQ(kArm64Not, s[0]->arch_opcode());
1858 EXPECT_EQ(1U, s[0]->InputCount());
1859 EXPECT_EQ(1U, s[0]->OutputCount());
1864 TEST_F(InstructionSelectorTest, Word32ShrWithWord32AndWithImmediate) {
1865 TRACED_FORRANGE(int32_t, lsb, 1, 31) {
1866 TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) {
1867 uint32_t jnk = rng()->NextInt();
1869 uint32_t msk = ((0xffffffffu >> (32 - width)) << lsb) | jnk;
1870 StreamBuilder m(this, kMachInt32, kMachInt32);
1871 m.Return(m.Word32Shr(m.Word32And(m.Parameter(0), m.Int32Constant(msk)),
1872 m.Int32Constant(lsb)));
1873 Stream s = m.Build();
1874 ASSERT_EQ(1U, s.size());
1875 EXPECT_EQ(kArm64Ubfx32, s[0]->arch_opcode());
1876 ASSERT_EQ(3U, s[0]->InputCount());
1877 EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
1878 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
1881 TRACED_FORRANGE(int32_t, lsb, 1, 31) {
1882 TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) {
1883 uint32_t jnk = rng()->NextInt();
1885 uint32_t msk = ((0xffffffffu >> (32 - width)) << lsb) | jnk;
1886 StreamBuilder m(this, kMachInt32, kMachInt32);
1887 m.Return(m.Word32Shr(m.Word32And(m.Int32Constant(msk), m.Parameter(0)),
1888 m.Int32Constant(lsb)));
1889 Stream s = m.Build();
1890 ASSERT_EQ(1U, s.size());
1891 EXPECT_EQ(kArm64Ubfx32, s[0]->arch_opcode());
1892 ASSERT_EQ(3U, s[0]->InputCount());
1893 EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
1894 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
1900 TEST_F(InstructionSelectorTest, Word64ShrWithWord64AndWithImmediate) {
1901 TRACED_FORRANGE(int32_t, lsb, 1, 63) {
1902 TRACED_FORRANGE(int32_t, width, 1, 64 - lsb) {
1903 uint64_t jnk = rng()->NextInt64();
1906 ((V8_UINT64_C(0xffffffffffffffff) >> (64 - width)) << lsb) | jnk;
1907 StreamBuilder m(this, kMachInt64, kMachInt64);
1908 m.Return(m.Word64Shr(m.Word64And(m.Parameter(0), m.Int64Constant(msk)),
1909 m.Int64Constant(lsb)));
1910 Stream s = m.Build();
1911 ASSERT_EQ(1U, s.size());
1912 EXPECT_EQ(kArm64Ubfx, s[0]->arch_opcode());
1913 ASSERT_EQ(3U, s[0]->InputCount());
1914 EXPECT_EQ(lsb, s.ToInt64(s[0]->InputAt(1)));
1915 EXPECT_EQ(width, s.ToInt64(s[0]->InputAt(2)));
1918 TRACED_FORRANGE(int32_t, lsb, 1, 63) {
1919 TRACED_FORRANGE(int32_t, width, 1, 64 - lsb) {
1920 uint64_t jnk = rng()->NextInt64();
1923 ((V8_UINT64_C(0xffffffffffffffff) >> (64 - width)) << lsb) | jnk;
1924 StreamBuilder m(this, kMachInt64, kMachInt64);
1925 m.Return(m.Word64Shr(m.Word64And(m.Int64Constant(msk), m.Parameter(0)),
1926 m.Int64Constant(lsb)));
1927 Stream s = m.Build();
1928 ASSERT_EQ(1U, s.size());
1929 EXPECT_EQ(kArm64Ubfx, s[0]->arch_opcode());
1930 ASSERT_EQ(3U, s[0]->InputCount());
1931 EXPECT_EQ(lsb, s.ToInt64(s[0]->InputAt(1)));
1932 EXPECT_EQ(width, s.ToInt64(s[0]->InputAt(2)));
1938 TEST_F(InstructionSelectorTest, Word32AndWithImmediateWithWord32Shr) {
1939 TRACED_FORRANGE(int32_t, lsb, 1, 31) {
1940 TRACED_FORRANGE(int32_t, width, 1, 31) {
1941 uint32_t msk = (1 << width) - 1;
1942 StreamBuilder m(this, kMachInt32, kMachInt32);
1943 m.Return(m.Word32And(m.Word32Shr(m.Parameter(0), m.Int32Constant(lsb)),
1944 m.Int32Constant(msk)));
1945 Stream s = m.Build();
1946 ASSERT_EQ(1U, s.size());
1947 EXPECT_EQ(kArm64Ubfx32, s[0]->arch_opcode());
1948 ASSERT_EQ(3U, s[0]->InputCount());
1949 EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
1950 int32_t actual_width = (lsb + width > 32) ? (32 - lsb) : width;
1951 EXPECT_EQ(actual_width, s.ToInt32(s[0]->InputAt(2)));
1954 TRACED_FORRANGE(int32_t, lsb, 1, 31) {
1955 TRACED_FORRANGE(int32_t, width, 1, 31) {
1956 uint32_t msk = (1 << width) - 1;
1957 StreamBuilder m(this, kMachInt32, kMachInt32);
1958 m.Return(m.Word32And(m.Int32Constant(msk),
1959 m.Word32Shr(m.Parameter(0), m.Int32Constant(lsb))));
1960 Stream s = m.Build();
1961 ASSERT_EQ(1U, s.size());
1962 EXPECT_EQ(kArm64Ubfx32, s[0]->arch_opcode());
1963 ASSERT_EQ(3U, s[0]->InputCount());
1964 EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
1965 int32_t actual_width = (lsb + width > 32) ? (32 - lsb) : width;
1966 EXPECT_EQ(actual_width, s.ToInt32(s[0]->InputAt(2)));
1972 TEST_F(InstructionSelectorTest, Word64AndWithImmediateWithWord64Shr) {
1973 TRACED_FORRANGE(int64_t, lsb, 1, 63) {
1974 TRACED_FORRANGE(int64_t, width, 1, 63) {
1975 uint64_t msk = (V8_UINT64_C(1) << width) - 1;
1976 StreamBuilder m(this, kMachInt64, kMachInt64);
1977 m.Return(m.Word64And(m.Word64Shr(m.Parameter(0), m.Int64Constant(lsb)),
1978 m.Int64Constant(msk)));
1979 Stream s = m.Build();
1980 ASSERT_EQ(1U, s.size());
1981 EXPECT_EQ(kArm64Ubfx, s[0]->arch_opcode());
1982 ASSERT_EQ(3U, s[0]->InputCount());
1983 EXPECT_EQ(lsb, s.ToInt64(s[0]->InputAt(1)));
1984 int64_t actual_width = (lsb + width > 64) ? (64 - lsb) : width;
1985 EXPECT_EQ(actual_width, s.ToInt64(s[0]->InputAt(2)));
1988 TRACED_FORRANGE(int64_t, lsb, 1, 63) {
1989 TRACED_FORRANGE(int64_t, width, 1, 63) {
1990 uint64_t msk = (V8_UINT64_C(1) << width) - 1;
1991 StreamBuilder m(this, kMachInt64, kMachInt64);
1992 m.Return(m.Word64And(m.Int64Constant(msk),
1993 m.Word64Shr(m.Parameter(0), m.Int64Constant(lsb))));
1994 Stream s = m.Build();
1995 ASSERT_EQ(1U, s.size());
1996 EXPECT_EQ(kArm64Ubfx, s[0]->arch_opcode());
1997 ASSERT_EQ(3U, s[0]->InputCount());
1998 EXPECT_EQ(lsb, s.ToInt64(s[0]->InputAt(1)));
1999 int64_t actual_width = (lsb + width > 64) ? (64 - lsb) : width;
2000 EXPECT_EQ(actual_width, s.ToInt64(s[0]->InputAt(2)));
2006 TEST_F(InstructionSelectorTest, Int32MulHighWithParameters) {
2007 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
2008 Node* const p0 = m.Parameter(0);
2009 Node* const p1 = m.Parameter(1);
2010 Node* const n = m.Int32MulHigh(p0, p1);
2012 Stream s = m.Build();
2013 ASSERT_EQ(2U, s.size());
2014 EXPECT_EQ(kArm64Smull, s[0]->arch_opcode());
2015 ASSERT_EQ(2U, s[0]->InputCount());
2016 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
2017 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
2018 ASSERT_EQ(1U, s[0]->OutputCount());
2019 EXPECT_EQ(kArm64Asr, s[1]->arch_opcode());
2020 ASSERT_EQ(2U, s[1]->InputCount());
2021 EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(0)));
2022 EXPECT_EQ(32, s.ToInt64(s[1]->InputAt(1)));
2023 ASSERT_EQ(1U, s[1]->OutputCount());
2024 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[1]->Output()));
2027 } // namespace compiler
2028 } // namespace internal