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 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 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 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 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 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 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 const MachInst2 kOvfAddSubInstructions[] = {
172 {&RawMachineAssembler::Int32AddWithOverflow, "Int32AddWithOverflow",
173 kArm64Add32, kMachInt32},
174 {&RawMachineAssembler::Int32SubWithOverflow, "Int32SubWithOverflow",
175 kArm64Sub32, kMachInt32}};
178 // ARM64 shift instructions.
179 const Shift kShiftInstructions[] = {
180 {{&RawMachineAssembler::Word32Shl, "Word32Shl", kArm64Lsl32, kMachInt32},
181 kMode_Operand2_R_LSL_I},
182 {{&RawMachineAssembler::Word64Shl, "Word64Shl", kArm64Lsl, kMachInt64},
183 kMode_Operand2_R_LSL_I},
184 {{&RawMachineAssembler::Word32Shr, "Word32Shr", kArm64Lsr32, kMachInt32},
185 kMode_Operand2_R_LSR_I},
186 {{&RawMachineAssembler::Word64Shr, "Word64Shr", kArm64Lsr, kMachInt64},
187 kMode_Operand2_R_LSR_I},
188 {{&RawMachineAssembler::Word32Sar, "Word32Sar", kArm64Asr32, kMachInt32},
189 kMode_Operand2_R_ASR_I},
190 {{&RawMachineAssembler::Word64Sar, "Word64Sar", kArm64Asr, kMachInt64},
191 kMode_Operand2_R_ASR_I},
192 {{&RawMachineAssembler::Word32Ror, "Word32Ror", kArm64Ror32, kMachInt32},
193 kMode_Operand2_R_ROR_I},
194 {{&RawMachineAssembler::Word64Ror, "Word64Ror", kArm64Ror, kMachInt64},
195 kMode_Operand2_R_ROR_I}};
198 // ARM64 Mul/Div instructions.
199 const MachInst2 kMulDivInstructions[] = {
200 {&RawMachineAssembler::Int32Mul, "Int32Mul", kArm64Mul32, kMachInt32},
201 {&RawMachineAssembler::Int64Mul, "Int64Mul", kArm64Mul, kMachInt64},
202 {&RawMachineAssembler::Int32Div, "Int32Div", kArm64Idiv32, kMachInt32},
203 {&RawMachineAssembler::Int64Div, "Int64Div", kArm64Idiv, kMachInt64},
204 {&RawMachineAssembler::Uint32Div, "Uint32Div", kArm64Udiv32, kMachInt32},
205 {&RawMachineAssembler::Uint64Div, "Uint64Div", kArm64Udiv, kMachInt64}};
208 // ARM64 FP arithmetic instructions.
209 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 const FPCmp kFPCmpInstructions[] = {
233 {{&RawMachineAssembler::Float64Equal, "Float64Equal", kArm64Float64Cmp,
236 {{&RawMachineAssembler::Float64LessThan, "Float64LessThan",
237 kArm64Float64Cmp, kMachFloat64},
239 {{&RawMachineAssembler::Float64LessThanOrEqual, "Float64LessThanOrEqual",
240 kArm64Float64Cmp, kMachFloat64},
241 kUnsignedLessThanOrEqual}};
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 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 TEST_P(InstructionSelectorAddSubTest, ExtendByte) {
476 const AddSub dpi = GetParam();
477 const MachineType type = dpi.mi.machine_type;
478 StreamBuilder m(this, type, type, type);
479 m.Return((m.*dpi.mi.constructor)(
480 m.Parameter(0), m.Word32And(m.Parameter(1), m.Int32Constant(0xff))));
481 Stream s = m.Build();
482 ASSERT_EQ(1U, s.size());
483 EXPECT_EQ(dpi.mi.arch_opcode, s[0]->arch_opcode());
484 EXPECT_EQ(kMode_Operand2_R_UXTB, s[0]->addressing_mode());
485 ASSERT_EQ(2U, s[0]->InputCount());
486 ASSERT_EQ(1U, s[0]->OutputCount());
490 TEST_P(InstructionSelectorAddSubTest, ExtendHalfword) {
491 const AddSub dpi = GetParam();
492 const MachineType type = dpi.mi.machine_type;
493 StreamBuilder m(this, type, type, type);
494 m.Return((m.*dpi.mi.constructor)(
495 m.Parameter(0), m.Word32And(m.Parameter(1), m.Int32Constant(0xffff))));
496 Stream s = m.Build();
497 ASSERT_EQ(1U, s.size());
498 EXPECT_EQ(dpi.mi.arch_opcode, s[0]->arch_opcode());
499 EXPECT_EQ(kMode_Operand2_R_UXTH, s[0]->addressing_mode());
500 ASSERT_EQ(2U, s[0]->InputCount());
501 ASSERT_EQ(1U, s[0]->OutputCount());
505 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorAddSubTest,
506 ::testing::ValuesIn(kAddSubInstructions));
509 TEST_F(InstructionSelectorTest, AddImmediateOnLeft) {
512 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
513 StreamBuilder m(this, kMachInt32, kMachInt32);
514 m.Return(m.Int32Add(m.Int32Constant(imm), m.Parameter(0)));
515 Stream s = m.Build();
516 ASSERT_EQ(1U, s.size());
517 EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
518 ASSERT_EQ(2U, s[0]->InputCount());
519 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
520 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
521 EXPECT_EQ(1U, s[0]->OutputCount());
526 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
527 StreamBuilder m(this, kMachInt64, kMachInt64);
528 m.Return(m.Int64Add(m.Int64Constant(imm), m.Parameter(0)));
529 Stream s = m.Build();
530 ASSERT_EQ(1U, s.size());
531 EXPECT_EQ(kArm64Add, s[0]->arch_opcode());
532 ASSERT_EQ(2U, s[0]->InputCount());
533 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
534 EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(1)));
535 EXPECT_EQ(1U, s[0]->OutputCount());
541 TEST_F(InstructionSelectorTest, SubZeroOnLeft) {
542 // Subtraction with zero on the left maps to Neg.
545 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
546 m.Return(m.Int32Sub(m.Int32Constant(0), m.Parameter(0)));
547 Stream s = m.Build();
549 ASSERT_EQ(1U, s.size());
550 EXPECT_EQ(kArm64Neg32, s[0]->arch_opcode());
551 EXPECT_EQ(1U, s[0]->InputCount());
552 EXPECT_EQ(1U, s[0]->OutputCount());
556 StreamBuilder m(this, kMachInt64, kMachInt64, kMachInt64);
557 m.Return(m.Int64Sub(m.Int64Constant(0), m.Parameter(0)));
558 Stream s = m.Build();
560 ASSERT_EQ(1U, s.size());
561 EXPECT_EQ(kArm64Neg, s[0]->arch_opcode());
562 EXPECT_EQ(1U, s[0]->InputCount());
563 EXPECT_EQ(1U, s[0]->OutputCount());
568 TEST_F(InstructionSelectorTest, AddNegImmediateOnLeft) {
571 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
572 if (imm == 0) continue;
573 StreamBuilder m(this, kMachInt32, kMachInt32);
574 m.Return(m.Int32Add(m.Int32Constant(-imm), m.Parameter(0)));
575 Stream s = m.Build();
577 ASSERT_EQ(1U, s.size());
578 EXPECT_EQ(kArm64Sub32, s[0]->arch_opcode());
579 ASSERT_EQ(2U, s[0]->InputCount());
580 ASSERT_TRUE(s[0]->InputAt(1)->IsImmediate());
581 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
582 EXPECT_EQ(1U, s[0]->OutputCount());
587 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
588 if (imm == 0) continue;
589 StreamBuilder m(this, kMachInt64, kMachInt64);
590 m.Return(m.Int64Add(m.Int64Constant(-imm), m.Parameter(0)));
591 Stream s = m.Build();
593 ASSERT_EQ(1U, s.size());
594 EXPECT_EQ(kArm64Sub, s[0]->arch_opcode());
595 ASSERT_EQ(2U, s[0]->InputCount());
596 ASSERT_TRUE(s[0]->InputAt(1)->IsImmediate());
597 EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(1)));
598 EXPECT_EQ(1U, s[0]->OutputCount());
604 TEST_F(InstructionSelectorTest, AddShiftByImmediateOnLeft) {
606 TRACED_FOREACH(Shift, shift, kShiftInstructions) {
607 // Only test relevant shifted operands.
608 if (shift.mi.machine_type != kMachInt32) continue;
609 if (shift.mi.arch_opcode == kArm64Ror32) continue;
611 TRACED_FORRANGE(int, imm, 0, 31) {
612 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
613 m.Return((m.Int32Add)(
614 (m.*shift.mi.constructor)(m.Parameter(1), m.Int32Constant(imm)),
616 Stream s = m.Build();
617 ASSERT_EQ(1U, s.size());
618 EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
619 EXPECT_EQ(shift.mode, s[0]->addressing_mode());
620 EXPECT_EQ(3U, s[0]->InputCount());
621 EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(2)));
622 EXPECT_EQ(1U, s[0]->OutputCount());
627 TRACED_FOREACH(Shift, shift, kShiftInstructions) {
628 // Only test relevant shifted operands.
629 if (shift.mi.machine_type != kMachInt64) continue;
630 if (shift.mi.arch_opcode == kArm64Ror) continue;
632 TRACED_FORRANGE(int, imm, 0, 63) {
633 StreamBuilder m(this, kMachInt64, kMachInt64, kMachInt64);
634 m.Return((m.Int64Add)(
635 (m.*shift.mi.constructor)(m.Parameter(1), m.Int64Constant(imm)),
637 Stream s = m.Build();
638 ASSERT_EQ(1U, s.size());
639 EXPECT_EQ(kArm64Add, s[0]->arch_opcode());
640 EXPECT_EQ(shift.mode, s[0]->addressing_mode());
641 EXPECT_EQ(3U, s[0]->InputCount());
642 EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(2)));
643 EXPECT_EQ(1U, s[0]->OutputCount());
649 TEST_F(InstructionSelectorTest, AddExtendByteOnLeft) {
651 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
652 m.Return(m.Int32Add(m.Word32And(m.Parameter(0), m.Int32Constant(0xff)),
654 Stream s = m.Build();
655 ASSERT_EQ(1U, s.size());
656 EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
657 EXPECT_EQ(kMode_Operand2_R_UXTB, s[0]->addressing_mode());
658 ASSERT_EQ(2U, s[0]->InputCount());
659 ASSERT_EQ(1U, s[0]->OutputCount());
662 StreamBuilder m(this, kMachInt64, kMachInt32, kMachInt64);
663 m.Return(m.Int64Add(m.Word32And(m.Parameter(0), m.Int32Constant(0xff)),
665 Stream s = m.Build();
666 ASSERT_EQ(1U, s.size());
667 EXPECT_EQ(kArm64Add, s[0]->arch_opcode());
668 EXPECT_EQ(kMode_Operand2_R_UXTB, s[0]->addressing_mode());
669 ASSERT_EQ(2U, s[0]->InputCount());
670 ASSERT_EQ(1U, s[0]->OutputCount());
675 TEST_F(InstructionSelectorTest, AddExtendHalfwordOnLeft) {
677 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
678 m.Return(m.Int32Add(m.Word32And(m.Parameter(0), m.Int32Constant(0xffff)),
680 Stream s = m.Build();
681 ASSERT_EQ(1U, s.size());
682 EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
683 EXPECT_EQ(kMode_Operand2_R_UXTH, s[0]->addressing_mode());
684 ASSERT_EQ(2U, s[0]->InputCount());
685 ASSERT_EQ(1U, s[0]->OutputCount());
688 StreamBuilder m(this, kMachInt64, kMachInt32, kMachInt64);
689 m.Return(m.Int64Add(m.Word32And(m.Parameter(0), m.Int32Constant(0xffff)),
691 Stream s = m.Build();
692 ASSERT_EQ(1U, s.size());
693 EXPECT_EQ(kArm64Add, s[0]->arch_opcode());
694 EXPECT_EQ(kMode_Operand2_R_UXTH, s[0]->addressing_mode());
695 ASSERT_EQ(2U, s[0]->InputCount());
696 ASSERT_EQ(1U, s[0]->OutputCount());
701 // -----------------------------------------------------------------------------
702 // Data processing controlled branches.
705 typedef InstructionSelectorTestWithParam<MachInst2>
706 InstructionSelectorDPFlagSetTest;
709 TEST_P(InstructionSelectorDPFlagSetTest, BranchWithParameters) {
710 const MachInst2 dpi = GetParam();
711 const MachineType type = dpi.machine_type;
712 StreamBuilder m(this, type, type, type);
714 m.Branch((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)), &a, &b);
716 m.Return(m.Int32Constant(1));
718 m.Return(m.Int32Constant(0));
719 Stream s = m.Build();
720 ASSERT_EQ(1U, s.size());
721 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
722 EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
723 EXPECT_EQ(kNotEqual, s[0]->flags_condition());
727 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
728 InstructionSelectorDPFlagSetTest,
729 ::testing::ValuesIn(kDPFlagSetInstructions));
732 TEST_F(InstructionSelectorTest, Word32AndBranchWithImmediateOnRight) {
733 TRACED_FOREACH(int32_t, imm, kLogical32Immediates) {
734 // Skip the cases where the instruction selector would use tbz/tbnz.
735 if (base::bits::CountPopulation32(imm) == 1) continue;
737 StreamBuilder m(this, kMachInt32, kMachInt32);
739 m.Branch(m.Word32And(m.Parameter(0), m.Int32Constant(imm)), &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 EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
750 EXPECT_EQ(kNotEqual, s[0]->flags_condition());
755 TEST_F(InstructionSelectorTest, Word64AndBranchWithImmediateOnRight) {
756 TRACED_FOREACH(int64_t, imm, kLogical64Immediates) {
757 // Skip the cases where the instruction selector would use tbz/tbnz.
758 if (base::bits::CountPopulation64(imm) == 1) continue;
760 StreamBuilder m(this, kMachInt64, kMachInt64);
762 m.Branch(m.Word64And(m.Parameter(0), m.Int64Constant(imm)), &a, &b);
764 m.Return(m.Int32Constant(1));
766 m.Return(m.Int32Constant(0));
767 Stream s = m.Build();
768 ASSERT_EQ(1U, s.size());
769 EXPECT_EQ(kArm64Tst, s[0]->arch_opcode());
770 EXPECT_EQ(4U, s[0]->InputCount());
771 EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
772 EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
773 EXPECT_EQ(kNotEqual, s[0]->flags_condition());
778 TEST_F(InstructionSelectorTest, AddBranchWithImmediateOnRight) {
779 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
780 StreamBuilder m(this, kMachInt32, kMachInt32);
782 m.Branch(m.Int32Add(m.Parameter(0), m.Int32Constant(imm)), &a, &b);
784 m.Return(m.Int32Constant(1));
786 m.Return(m.Int32Constant(0));
787 Stream s = m.Build();
788 ASSERT_EQ(1U, s.size());
789 EXPECT_EQ(kArm64Cmn32, s[0]->arch_opcode());
790 EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
791 EXPECT_EQ(kNotEqual, s[0]->flags_condition());
796 TEST_F(InstructionSelectorTest, SubBranchWithImmediateOnRight) {
797 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
798 StreamBuilder m(this, kMachInt32, kMachInt32);
800 m.Branch(m.Int32Sub(m.Parameter(0), m.Int32Constant(imm)), &a, &b);
802 m.Return(m.Int32Constant(1));
804 m.Return(m.Int32Constant(0));
805 Stream s = m.Build();
806 ASSERT_EQ(1U, s.size());
807 EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode());
808 EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
809 EXPECT_EQ(kNotEqual, s[0]->flags_condition());
814 TEST_F(InstructionSelectorTest, Word32AndBranchWithImmediateOnLeft) {
815 TRACED_FOREACH(int32_t, imm, kLogical32Immediates) {
816 // Skip the cases where the instruction selector would use tbz/tbnz.
817 if (base::bits::CountPopulation32(imm) == 1) continue;
819 StreamBuilder m(this, kMachInt32, kMachInt32);
821 m.Branch(m.Word32And(m.Int32Constant(imm), m.Parameter(0)), &a, &b);
823 m.Return(m.Int32Constant(1));
825 m.Return(m.Int32Constant(0));
826 Stream s = m.Build();
827 ASSERT_EQ(1U, s.size());
828 EXPECT_EQ(kArm64Tst32, s[0]->arch_opcode());
829 EXPECT_EQ(4U, s[0]->InputCount());
830 EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
831 ASSERT_LE(1U, s[0]->InputCount());
832 EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
833 EXPECT_EQ(kNotEqual, s[0]->flags_condition());
838 TEST_F(InstructionSelectorTest, Word64AndBranchWithImmediateOnLeft) {
839 TRACED_FOREACH(int64_t, imm, kLogical64Immediates) {
840 // Skip the cases where the instruction selector would use tbz/tbnz.
841 if (base::bits::CountPopulation64(imm) == 1) continue;
843 StreamBuilder m(this, kMachInt64, kMachInt64);
845 m.Branch(m.Word64And(m.Int64Constant(imm), m.Parameter(0)), &a, &b);
847 m.Return(m.Int32Constant(1));
849 m.Return(m.Int32Constant(0));
850 Stream s = m.Build();
851 ASSERT_EQ(1U, s.size());
852 EXPECT_EQ(kArm64Tst, s[0]->arch_opcode());
853 EXPECT_EQ(4U, s[0]->InputCount());
854 EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
855 ASSERT_LE(1U, s[0]->InputCount());
856 EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
857 EXPECT_EQ(kNotEqual, s[0]->flags_condition());
862 TEST_F(InstructionSelectorTest, AddBranchWithImmediateOnLeft) {
863 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
864 StreamBuilder m(this, kMachInt32, kMachInt32);
866 m.Branch(m.Int32Add(m.Int32Constant(imm), m.Parameter(0)), &a, &b);
868 m.Return(m.Int32Constant(1));
870 m.Return(m.Int32Constant(0));
871 Stream s = m.Build();
872 ASSERT_EQ(1U, s.size());
873 EXPECT_EQ(kArm64Cmn32, s[0]->arch_opcode());
874 ASSERT_LE(1U, s[0]->InputCount());
875 EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
876 EXPECT_EQ(kNotEqual, s[0]->flags_condition());
881 TEST_F(InstructionSelectorTest, Word32AndBranchWithOneBitMaskOnRight) {
882 TRACED_FORRANGE(int, bit, 0, 31) {
883 uint32_t mask = 1 << bit;
884 StreamBuilder m(this, kMachInt32, kMachInt32);
886 m.Branch(m.Word32And(m.Parameter(0), m.Int32Constant(mask)), &a, &b);
888 m.Return(m.Int32Constant(1));
890 m.Return(m.Int32Constant(0));
891 Stream s = m.Build();
892 ASSERT_EQ(1U, s.size());
893 EXPECT_EQ(kArm64TestAndBranch32, s[0]->arch_opcode());
894 EXPECT_EQ(kNotEqual, s[0]->flags_condition());
895 EXPECT_EQ(4U, s[0]->InputCount());
896 EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
897 EXPECT_EQ(bit, s.ToInt32(s[0]->InputAt(1)));
900 TRACED_FORRANGE(int, bit, 0, 31) {
901 uint32_t mask = 1 << bit;
902 StreamBuilder m(this, kMachInt32, kMachInt32);
905 m.Word32BinaryNot(m.Word32And(m.Parameter(0), m.Int32Constant(mask))),
908 m.Return(m.Int32Constant(1));
910 m.Return(m.Int32Constant(0));
911 Stream s = m.Build();
912 ASSERT_EQ(1U, s.size());
913 EXPECT_EQ(kArm64TestAndBranch32, s[0]->arch_opcode());
914 EXPECT_EQ(kEqual, s[0]->flags_condition());
915 EXPECT_EQ(4U, s[0]->InputCount());
916 EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
917 EXPECT_EQ(bit, s.ToInt32(s[0]->InputAt(1)));
922 TEST_F(InstructionSelectorTest, Word32AndBranchWithOneBitMaskOnLeft) {
923 TRACED_FORRANGE(int, bit, 0, 31) {
924 uint32_t mask = 1 << bit;
925 StreamBuilder m(this, kMachInt32, kMachInt32);
927 m.Branch(m.Word32And(m.Int32Constant(mask), m.Parameter(0)), &a, &b);
929 m.Return(m.Int32Constant(1));
931 m.Return(m.Int32Constant(0));
932 Stream s = m.Build();
933 ASSERT_EQ(1U, s.size());
934 EXPECT_EQ(kArm64TestAndBranch32, s[0]->arch_opcode());
935 EXPECT_EQ(kNotEqual, s[0]->flags_condition());
936 EXPECT_EQ(4U, s[0]->InputCount());
937 EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
938 EXPECT_EQ(bit, s.ToInt32(s[0]->InputAt(1)));
941 TRACED_FORRANGE(int, bit, 0, 31) {
942 uint32_t mask = 1 << bit;
943 StreamBuilder m(this, kMachInt32, kMachInt32);
946 m.Word32BinaryNot(m.Word32And(m.Int32Constant(mask), m.Parameter(0))),
949 m.Return(m.Int32Constant(1));
951 m.Return(m.Int32Constant(0));
952 Stream s = m.Build();
953 ASSERT_EQ(1U, s.size());
954 EXPECT_EQ(kArm64TestAndBranch32, s[0]->arch_opcode());
955 EXPECT_EQ(kEqual, s[0]->flags_condition());
956 EXPECT_EQ(4U, s[0]->InputCount());
957 EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
958 EXPECT_EQ(bit, s.ToInt32(s[0]->InputAt(1)));
963 TEST_F(InstructionSelectorTest, Word64AndBranchWithOneBitMaskOnRight) {
964 TRACED_FORRANGE(int, bit, 0, 63) {
965 uint64_t mask = 1L << bit;
966 StreamBuilder m(this, kMachInt64, kMachInt64);
968 m.Branch(m.Word64And(m.Parameter(0), m.Int64Constant(mask)), &a, &b);
970 m.Return(m.Int32Constant(1));
972 m.Return(m.Int32Constant(0));
973 Stream s = m.Build();
974 ASSERT_EQ(1U, s.size());
975 EXPECT_EQ(kArm64TestAndBranch, s[0]->arch_opcode());
976 EXPECT_EQ(kNotEqual, s[0]->flags_condition());
977 EXPECT_EQ(4U, s[0]->InputCount());
978 EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
979 EXPECT_EQ(bit, s.ToInt64(s[0]->InputAt(1)));
984 TEST_F(InstructionSelectorTest, Word64AndBranchWithOneBitMaskOnLeft) {
985 TRACED_FORRANGE(int, bit, 0, 63) {
986 uint64_t mask = 1L << bit;
987 StreamBuilder m(this, kMachInt64, kMachInt64);
989 m.Branch(m.Word64And(m.Int64Constant(mask), m.Parameter(0)), &a, &b);
991 m.Return(m.Int32Constant(1));
993 m.Return(m.Int32Constant(0));
994 Stream s = m.Build();
995 ASSERT_EQ(1U, s.size());
996 EXPECT_EQ(kArm64TestAndBranch, s[0]->arch_opcode());
997 EXPECT_EQ(kNotEqual, s[0]->flags_condition());
998 EXPECT_EQ(4U, s[0]->InputCount());
999 EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
1000 EXPECT_EQ(bit, s.ToInt64(s[0]->InputAt(1)));
1005 TEST_F(InstructionSelectorTest, CompareAgainstZeroAndBranch) {
1007 StreamBuilder m(this, kMachInt32, kMachInt32);
1009 Node* p0 = m.Parameter(0);
1010 m.Branch(p0, &a, &b);
1012 m.Return(m.Int32Constant(1));
1014 m.Return(m.Int32Constant(0));
1015 Stream s = m.Build();
1016 ASSERT_EQ(1U, s.size());
1017 EXPECT_EQ(kArm64CompareAndBranch32, s[0]->arch_opcode());
1018 EXPECT_EQ(kNotEqual, s[0]->flags_condition());
1019 EXPECT_EQ(3U, s[0]->InputCount());
1020 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1024 StreamBuilder m(this, kMachInt32, kMachInt32);
1026 Node* p0 = m.Parameter(0);
1027 m.Branch(m.Word32BinaryNot(p0), &a, &b);
1029 m.Return(m.Int32Constant(1));
1031 m.Return(m.Int32Constant(0));
1032 Stream s = m.Build();
1033 ASSERT_EQ(1U, s.size());
1034 EXPECT_EQ(kArm64CompareAndBranch32, s[0]->arch_opcode());
1035 EXPECT_EQ(kEqual, s[0]->flags_condition());
1036 EXPECT_EQ(3U, s[0]->InputCount());
1037 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1042 // -----------------------------------------------------------------------------
1043 // Add and subtract instructions with overflow.
1046 typedef InstructionSelectorTestWithParam<MachInst2>
1047 InstructionSelectorOvfAddSubTest;
1050 TEST_P(InstructionSelectorOvfAddSubTest, OvfParameter) {
1051 const MachInst2 dpi = GetParam();
1052 const MachineType type = dpi.machine_type;
1053 StreamBuilder m(this, type, type, type);
1055 m.Projection(1, (m.*dpi.constructor)(m.Parameter(0), m.Parameter(1))));
1056 Stream s = m.Build();
1057 ASSERT_EQ(1U, s.size());
1058 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
1059 EXPECT_EQ(2U, s[0]->InputCount());
1060 EXPECT_LE(1U, s[0]->OutputCount());
1061 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1062 EXPECT_EQ(kOverflow, s[0]->flags_condition());
1066 TEST_P(InstructionSelectorOvfAddSubTest, OvfImmediateOnRight) {
1067 const MachInst2 dpi = GetParam();
1068 const MachineType type = dpi.machine_type;
1069 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
1070 StreamBuilder m(this, type, type);
1071 m.Return(m.Projection(
1072 1, (m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm))));
1073 Stream s = m.Build();
1074 ASSERT_EQ(1U, s.size());
1075 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
1076 ASSERT_EQ(2U, s[0]->InputCount());
1077 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
1078 EXPECT_LE(1U, s[0]->OutputCount());
1079 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1080 EXPECT_EQ(kOverflow, s[0]->flags_condition());
1085 TEST_P(InstructionSelectorOvfAddSubTest, ValParameter) {
1086 const MachInst2 dpi = GetParam();
1087 const MachineType type = dpi.machine_type;
1088 StreamBuilder m(this, type, type, type);
1090 m.Projection(0, (m.*dpi.constructor)(m.Parameter(0), m.Parameter(1))));
1091 Stream s = m.Build();
1092 ASSERT_EQ(1U, s.size());
1093 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
1094 EXPECT_EQ(2U, s[0]->InputCount());
1095 EXPECT_LE(1U, s[0]->OutputCount());
1096 EXPECT_EQ(kFlags_none, s[0]->flags_mode());
1100 TEST_P(InstructionSelectorOvfAddSubTest, ValImmediateOnRight) {
1101 const MachInst2 dpi = GetParam();
1102 const MachineType type = dpi.machine_type;
1103 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
1104 StreamBuilder m(this, type, type);
1105 m.Return(m.Projection(
1106 0, (m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm))));
1107 Stream s = m.Build();
1108 ASSERT_EQ(1U, s.size());
1109 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
1110 ASSERT_EQ(2U, s[0]->InputCount());
1111 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
1112 EXPECT_LE(1U, s[0]->OutputCount());
1113 EXPECT_EQ(kFlags_none, s[0]->flags_mode());
1118 TEST_P(InstructionSelectorOvfAddSubTest, BothParameter) {
1119 const MachInst2 dpi = GetParam();
1120 const MachineType type = dpi.machine_type;
1121 StreamBuilder m(this, type, type, type);
1122 Node* n = (m.*dpi.constructor)(m.Parameter(0), m.Parameter(1));
1123 m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n)));
1124 Stream s = m.Build();
1125 ASSERT_LE(1U, s.size());
1126 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
1127 EXPECT_EQ(2U, s[0]->InputCount());
1128 EXPECT_EQ(2U, s[0]->OutputCount());
1129 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1130 EXPECT_EQ(kOverflow, s[0]->flags_condition());
1134 TEST_P(InstructionSelectorOvfAddSubTest, BothImmediateOnRight) {
1135 const MachInst2 dpi = GetParam();
1136 const MachineType type = dpi.machine_type;
1137 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
1138 StreamBuilder m(this, type, type);
1139 Node* n = (m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm));
1140 m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n)));
1141 Stream s = m.Build();
1142 ASSERT_LE(1U, s.size());
1143 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
1144 ASSERT_EQ(2U, s[0]->InputCount());
1145 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
1146 EXPECT_EQ(2U, s[0]->OutputCount());
1147 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1148 EXPECT_EQ(kOverflow, s[0]->flags_condition());
1153 TEST_P(InstructionSelectorOvfAddSubTest, BranchWithParameters) {
1154 const MachInst2 dpi = GetParam();
1155 const MachineType type = dpi.machine_type;
1156 StreamBuilder m(this, type, type, type);
1158 Node* n = (m.*dpi.constructor)(m.Parameter(0), m.Parameter(1));
1159 m.Branch(m.Projection(1, n), &a, &b);
1161 m.Return(m.Int32Constant(0));
1163 m.Return(m.Projection(0, n));
1164 Stream s = m.Build();
1165 ASSERT_EQ(1U, s.size());
1166 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
1167 EXPECT_EQ(4U, s[0]->InputCount());
1168 EXPECT_EQ(1U, s[0]->OutputCount());
1169 EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
1170 EXPECT_EQ(kOverflow, s[0]->flags_condition());
1174 TEST_P(InstructionSelectorOvfAddSubTest, BranchWithImmediateOnRight) {
1175 const MachInst2 dpi = GetParam();
1176 const MachineType type = dpi.machine_type;
1177 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
1178 StreamBuilder m(this, type, type);
1180 Node* n = (m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm));
1181 m.Branch(m.Projection(1, n), &a, &b);
1183 m.Return(m.Int32Constant(0));
1185 m.Return(m.Projection(0, n));
1186 Stream s = m.Build();
1187 ASSERT_EQ(1U, s.size());
1188 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
1189 ASSERT_EQ(4U, s[0]->InputCount());
1190 EXPECT_EQ(1U, s[0]->OutputCount());
1191 EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
1192 EXPECT_EQ(kOverflow, s[0]->flags_condition());
1197 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1198 InstructionSelectorOvfAddSubTest,
1199 ::testing::ValuesIn(kOvfAddSubInstructions));
1202 TEST_F(InstructionSelectorTest, OvfFlagAddImmediateOnLeft) {
1203 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
1204 StreamBuilder m(this, kMachInt32, kMachInt32);
1205 m.Return(m.Projection(
1206 1, m.Int32AddWithOverflow(m.Int32Constant(imm), m.Parameter(0))));
1207 Stream s = m.Build();
1209 ASSERT_EQ(1U, s.size());
1210 EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
1211 EXPECT_EQ(2U, s[0]->InputCount());
1212 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
1213 EXPECT_LE(1U, s[0]->OutputCount());
1214 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1215 EXPECT_EQ(kOverflow, s[0]->flags_condition());
1220 TEST_F(InstructionSelectorTest, OvfValAddImmediateOnLeft) {
1221 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
1222 StreamBuilder m(this, kMachInt32, kMachInt32);
1223 m.Return(m.Projection(
1224 0, m.Int32AddWithOverflow(m.Int32Constant(imm), m.Parameter(0))));
1225 Stream s = m.Build();
1227 ASSERT_EQ(1U, s.size());
1228 EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
1229 ASSERT_EQ(2U, s[0]->InputCount());
1230 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
1231 EXPECT_LE(1U, s[0]->OutputCount());
1232 EXPECT_EQ(kFlags_none, s[0]->flags_mode());
1237 TEST_F(InstructionSelectorTest, OvfBothAddImmediateOnLeft) {
1238 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
1239 StreamBuilder m(this, kMachInt32, kMachInt32);
1240 Node* n = m.Int32AddWithOverflow(m.Int32Constant(imm), m.Parameter(0));
1241 m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n)));
1242 Stream s = m.Build();
1244 ASSERT_LE(1U, s.size());
1245 EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
1246 ASSERT_EQ(2U, s[0]->InputCount());
1247 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
1248 EXPECT_EQ(2U, s[0]->OutputCount());
1249 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1250 EXPECT_EQ(kOverflow, s[0]->flags_condition());
1255 TEST_F(InstructionSelectorTest, OvfBranchWithImmediateOnLeft) {
1256 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
1257 StreamBuilder m(this, kMachInt32, kMachInt32);
1259 Node* n = m.Int32AddWithOverflow(m.Int32Constant(imm), m.Parameter(0));
1260 m.Branch(m.Projection(1, n), &a, &b);
1262 m.Return(m.Int32Constant(0));
1264 m.Return(m.Projection(0, n));
1265 Stream s = m.Build();
1267 ASSERT_EQ(1U, s.size());
1268 EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
1269 ASSERT_EQ(4U, s[0]->InputCount());
1270 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
1271 EXPECT_EQ(1U, s[0]->OutputCount());
1272 EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
1273 EXPECT_EQ(kOverflow, s[0]->flags_condition());
1278 // -----------------------------------------------------------------------------
1279 // Shift instructions.
1282 typedef InstructionSelectorTestWithParam<Shift> InstructionSelectorShiftTest;
1285 TEST_P(InstructionSelectorShiftTest, Parameter) {
1286 const Shift shift = GetParam();
1287 const MachineType type = shift.mi.machine_type;
1288 StreamBuilder m(this, type, type, type);
1289 m.Return((m.*shift.mi.constructor)(m.Parameter(0), m.Parameter(1)));
1290 Stream s = m.Build();
1291 ASSERT_EQ(1U, s.size());
1292 EXPECT_EQ(shift.mi.arch_opcode, s[0]->arch_opcode());
1293 EXPECT_EQ(2U, s[0]->InputCount());
1294 EXPECT_EQ(1U, s[0]->OutputCount());
1298 TEST_P(InstructionSelectorShiftTest, Immediate) {
1299 const Shift shift = GetParam();
1300 const MachineType type = shift.mi.machine_type;
1301 TRACED_FORRANGE(int32_t, imm, 0, (ElementSizeOf(type) * 8) - 1) {
1302 StreamBuilder m(this, type, type);
1303 m.Return((m.*shift.mi.constructor)(m.Parameter(0), m.Int32Constant(imm)));
1304 Stream s = m.Build();
1305 ASSERT_EQ(1U, s.size());
1306 EXPECT_EQ(shift.mi.arch_opcode, s[0]->arch_opcode());
1307 EXPECT_EQ(2U, s[0]->InputCount());
1308 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
1309 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
1310 EXPECT_EQ(1U, s[0]->OutputCount());
1315 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorShiftTest,
1316 ::testing::ValuesIn(kShiftInstructions));
1319 TEST_F(InstructionSelectorTest, Word64ShlWithChangeInt32ToInt64) {
1320 TRACED_FORRANGE(int64_t, x, 32, 63) {
1321 StreamBuilder m(this, kMachInt64, kMachInt32);
1322 Node* const p0 = m.Parameter(0);
1323 Node* const n = m.Word64Shl(m.ChangeInt32ToInt64(p0), m.Int64Constant(x));
1325 Stream s = m.Build();
1326 ASSERT_EQ(1U, s.size());
1327 EXPECT_EQ(kArm64Lsl, s[0]->arch_opcode());
1328 ASSERT_EQ(2U, s[0]->InputCount());
1329 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1330 EXPECT_EQ(x, s.ToInt64(s[0]->InputAt(1)));
1331 ASSERT_EQ(1U, s[0]->OutputCount());
1332 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1337 TEST_F(InstructionSelectorTest, Word64ShlWithChangeUint32ToUint64) {
1338 TRACED_FORRANGE(int64_t, x, 32, 63) {
1339 StreamBuilder m(this, kMachInt64, kMachUint32);
1340 Node* const p0 = m.Parameter(0);
1341 Node* const n = m.Word64Shl(m.ChangeUint32ToUint64(p0), m.Int64Constant(x));
1343 Stream s = m.Build();
1344 ASSERT_EQ(1U, s.size());
1345 EXPECT_EQ(kArm64Lsl, s[0]->arch_opcode());
1346 ASSERT_EQ(2U, s[0]->InputCount());
1347 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1348 EXPECT_EQ(x, s.ToInt64(s[0]->InputAt(1)));
1349 ASSERT_EQ(1U, s[0]->OutputCount());
1350 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1355 TEST_F(InstructionSelectorTest, TruncateInt64ToInt32WithWord64Sar) {
1356 StreamBuilder m(this, kMachInt32, kMachInt64);
1357 Node* const p = m.Parameter(0);
1358 Node* const t = m.TruncateInt64ToInt32(m.Word64Sar(p, m.Int64Constant(32)));
1360 Stream s = m.Build();
1361 ASSERT_EQ(1U, s.size());
1362 EXPECT_EQ(kArm64Lsr, s[0]->arch_opcode());
1363 ASSERT_EQ(2U, s[0]->InputCount());
1364 EXPECT_EQ(s.ToVreg(p), s.ToVreg(s[0]->InputAt(0)));
1365 EXPECT_EQ(32, s.ToInt64(s[0]->InputAt(1)));
1366 ASSERT_EQ(1U, s[0]->OutputCount());
1367 EXPECT_EQ(s.ToVreg(t), s.ToVreg(s[0]->OutputAt(0)));
1371 TEST_F(InstructionSelectorTest, TruncateInt64ToInt32WithWord64Shr) {
1372 TRACED_FORRANGE(int64_t, x, 32, 63) {
1373 StreamBuilder m(this, kMachInt32, kMachInt64);
1374 Node* const p = m.Parameter(0);
1375 Node* const t = m.TruncateInt64ToInt32(m.Word64Shr(p, m.Int64Constant(x)));
1377 Stream s = m.Build();
1378 ASSERT_EQ(1U, s.size());
1379 EXPECT_EQ(kArm64Lsr, s[0]->arch_opcode());
1380 ASSERT_EQ(2U, s[0]->InputCount());
1381 EXPECT_EQ(s.ToVreg(p), s.ToVreg(s[0]->InputAt(0)));
1382 EXPECT_EQ(x, s.ToInt64(s[0]->InputAt(1)));
1383 ASSERT_EQ(1U, s[0]->OutputCount());
1384 EXPECT_EQ(s.ToVreg(t), s.ToVreg(s[0]->OutputAt(0)));
1389 // -----------------------------------------------------------------------------
1390 // Mul and Div instructions.
1393 typedef InstructionSelectorTestWithParam<MachInst2>
1394 InstructionSelectorMulDivTest;
1397 TEST_P(InstructionSelectorMulDivTest, Parameter) {
1398 const MachInst2 dpi = GetParam();
1399 const MachineType type = dpi.machine_type;
1400 StreamBuilder m(this, type, type, type);
1401 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)));
1402 Stream s = m.Build();
1403 ASSERT_EQ(1U, s.size());
1404 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
1405 EXPECT_EQ(2U, s[0]->InputCount());
1406 EXPECT_EQ(1U, s[0]->OutputCount());
1410 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorMulDivTest,
1411 ::testing::ValuesIn(kMulDivInstructions));
1417 const char* mul_constructor_name;
1418 Node* (RawMachineAssembler::*mul_constructor)(Node*, Node*);
1419 Node* (RawMachineAssembler::*add_constructor)(Node*, Node*);
1420 Node* (RawMachineAssembler::*sub_constructor)(Node*, Node*);
1421 ArchOpcode add_arch_opcode;
1422 ArchOpcode sub_arch_opcode;
1423 ArchOpcode neg_arch_opcode;
1424 MachineType machine_type;
1428 std::ostream& operator<<(std::ostream& os, const MulDPInst& inst) {
1429 return os << inst.mul_constructor_name;
1435 static const MulDPInst kMulDPInstructions[] = {
1436 {"Int32Mul", &RawMachineAssembler::Int32Mul, &RawMachineAssembler::Int32Add,
1437 &RawMachineAssembler::Int32Sub, kArm64Madd32, kArm64Msub32, kArm64Mneg32,
1439 {"Int64Mul", &RawMachineAssembler::Int64Mul, &RawMachineAssembler::Int64Add,
1440 &RawMachineAssembler::Int64Sub, kArm64Madd, kArm64Msub, kArm64Mneg,
1444 typedef InstructionSelectorTestWithParam<MulDPInst>
1445 InstructionSelectorIntDPWithIntMulTest;
1448 TEST_P(InstructionSelectorIntDPWithIntMulTest, AddWithMul) {
1449 const MulDPInst mdpi = GetParam();
1450 const MachineType type = mdpi.machine_type;
1452 StreamBuilder m(this, type, type, type, type);
1453 Node* n = (m.*mdpi.mul_constructor)(m.Parameter(1), m.Parameter(2));
1454 m.Return((m.*mdpi.add_constructor)(m.Parameter(0), n));
1455 Stream s = m.Build();
1456 ASSERT_EQ(1U, s.size());
1457 EXPECT_EQ(mdpi.add_arch_opcode, s[0]->arch_opcode());
1458 EXPECT_EQ(3U, s[0]->InputCount());
1459 EXPECT_EQ(1U, s[0]->OutputCount());
1462 StreamBuilder m(this, type, type, type, type);
1463 Node* n = (m.*mdpi.mul_constructor)(m.Parameter(0), m.Parameter(1));
1464 m.Return((m.*mdpi.add_constructor)(n, m.Parameter(2)));
1465 Stream s = m.Build();
1466 ASSERT_EQ(1U, s.size());
1467 EXPECT_EQ(mdpi.add_arch_opcode, s[0]->arch_opcode());
1468 EXPECT_EQ(3U, s[0]->InputCount());
1469 EXPECT_EQ(1U, s[0]->OutputCount());
1474 TEST_P(InstructionSelectorIntDPWithIntMulTest, SubWithMul) {
1475 const MulDPInst mdpi = GetParam();
1476 const MachineType type = mdpi.machine_type;
1478 StreamBuilder m(this, type, type, type, type);
1479 Node* n = (m.*mdpi.mul_constructor)(m.Parameter(1), m.Parameter(2));
1480 m.Return((m.*mdpi.sub_constructor)(m.Parameter(0), n));
1481 Stream s = m.Build();
1482 ASSERT_EQ(1U, s.size());
1483 EXPECT_EQ(mdpi.sub_arch_opcode, s[0]->arch_opcode());
1484 EXPECT_EQ(3U, s[0]->InputCount());
1485 EXPECT_EQ(1U, s[0]->OutputCount());
1490 TEST_P(InstructionSelectorIntDPWithIntMulTest, NegativeMul) {
1491 const MulDPInst mdpi = GetParam();
1492 const MachineType type = mdpi.machine_type;
1494 StreamBuilder m(this, type, type, type);
1496 (m.*mdpi.sub_constructor)(BuildConstant(m, type, 0), m.Parameter(0));
1497 m.Return((m.*mdpi.mul_constructor)(n, m.Parameter(1)));
1498 Stream s = m.Build();
1499 ASSERT_EQ(1U, s.size());
1500 EXPECT_EQ(mdpi.neg_arch_opcode, s[0]->arch_opcode());
1501 EXPECT_EQ(2U, s[0]->InputCount());
1502 EXPECT_EQ(1U, s[0]->OutputCount());
1505 StreamBuilder m(this, type, type, type);
1507 (m.*mdpi.sub_constructor)(BuildConstant(m, type, 0), m.Parameter(1));
1508 m.Return((m.*mdpi.mul_constructor)(m.Parameter(0), n));
1509 Stream s = m.Build();
1510 ASSERT_EQ(1U, s.size());
1511 EXPECT_EQ(mdpi.neg_arch_opcode, s[0]->arch_opcode());
1512 EXPECT_EQ(2U, s[0]->InputCount());
1513 EXPECT_EQ(1U, s[0]->OutputCount());
1518 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1519 InstructionSelectorIntDPWithIntMulTest,
1520 ::testing::ValuesIn(kMulDPInstructions));
1523 // -----------------------------------------------------------------------------
1524 // Floating point instructions.
1526 typedef InstructionSelectorTestWithParam<MachInst2>
1527 InstructionSelectorFPArithTest;
1530 TEST_P(InstructionSelectorFPArithTest, Parameter) {
1531 const MachInst2 fpa = GetParam();
1532 StreamBuilder m(this, fpa.machine_type, fpa.machine_type, fpa.machine_type);
1533 m.Return((m.*fpa.constructor)(m.Parameter(0), m.Parameter(1)));
1534 Stream s = m.Build();
1535 ASSERT_EQ(1U, s.size());
1536 EXPECT_EQ(fpa.arch_opcode, s[0]->arch_opcode());
1537 EXPECT_EQ(2U, s[0]->InputCount());
1538 EXPECT_EQ(1U, s[0]->OutputCount());
1542 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorFPArithTest,
1543 ::testing::ValuesIn(kFPArithInstructions));
1546 typedef InstructionSelectorTestWithParam<FPCmp> InstructionSelectorFPCmpTest;
1549 TEST_P(InstructionSelectorFPCmpTest, Parameter) {
1550 const FPCmp cmp = GetParam();
1551 StreamBuilder m(this, kMachInt32, cmp.mi.machine_type, cmp.mi.machine_type);
1552 m.Return((m.*cmp.mi.constructor)(m.Parameter(0), m.Parameter(1)));
1553 Stream s = m.Build();
1554 ASSERT_EQ(1U, s.size());
1555 EXPECT_EQ(cmp.mi.arch_opcode, s[0]->arch_opcode());
1556 EXPECT_EQ(2U, s[0]->InputCount());
1557 EXPECT_EQ(1U, s[0]->OutputCount());
1558 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1559 EXPECT_EQ(cmp.cond, s[0]->flags_condition());
1563 TEST_P(InstructionSelectorFPCmpTest, WithImmediateZeroOnRight) {
1564 const FPCmp cmp = GetParam();
1565 StreamBuilder m(this, kMachInt32, cmp.mi.machine_type);
1566 m.Return((m.*cmp.mi.constructor)(m.Parameter(0), m.Float64Constant(0.0)));
1567 Stream s = m.Build();
1568 ASSERT_EQ(1U, s.size());
1569 EXPECT_EQ(cmp.mi.arch_opcode, s[0]->arch_opcode());
1570 EXPECT_EQ(2U, s[0]->InputCount());
1571 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
1572 EXPECT_EQ(1U, s[0]->OutputCount());
1573 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1574 EXPECT_EQ(cmp.cond, s[0]->flags_condition());
1578 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorFPCmpTest,
1579 ::testing::ValuesIn(kFPCmpInstructions));
1582 TEST_F(InstructionSelectorTest, Float64EqualWithImmediateZeroOnLeft) {
1583 StreamBuilder m(this, kMachInt32, kMachFloat64);
1584 m.Return(m.Float64Equal(m.Float64Constant(0.0), m.Parameter(0)));
1585 Stream s = m.Build();
1586 ASSERT_EQ(1U, s.size());
1587 EXPECT_EQ(kArm64Float64Cmp, s[0]->arch_opcode());
1588 EXPECT_EQ(2U, s[0]->InputCount());
1589 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
1590 EXPECT_EQ(1U, s[0]->OutputCount());
1591 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1592 EXPECT_EQ(kEqual, s[0]->flags_condition());
1596 // -----------------------------------------------------------------------------
1599 typedef InstructionSelectorTestWithParam<Conversion>
1600 InstructionSelectorConversionTest;
1603 TEST_P(InstructionSelectorConversionTest, Parameter) {
1604 const Conversion conv = GetParam();
1605 StreamBuilder m(this, conv.mi.machine_type, conv.src_machine_type);
1606 m.Return((m.*conv.mi.constructor)(m.Parameter(0)));
1607 Stream s = m.Build();
1608 ASSERT_EQ(1U, s.size());
1609 EXPECT_EQ(conv.mi.arch_opcode, s[0]->arch_opcode());
1610 EXPECT_EQ(1U, s[0]->InputCount());
1611 EXPECT_EQ(1U, s[0]->OutputCount());
1615 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1616 InstructionSelectorConversionTest,
1617 ::testing::ValuesIn(kConversionInstructions));
1620 // -----------------------------------------------------------------------------
1621 // Memory access instructions.
1626 struct MemoryAccess {
1628 ArchOpcode ldr_opcode;
1629 ArchOpcode str_opcode;
1630 const int32_t immediates[20];
1634 std::ostream& operator<<(std::ostream& os, const MemoryAccess& memacc) {
1635 return os << memacc.type;
1641 static const MemoryAccess kMemoryAccesses[] = {
1645 {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 257, 258, 1000, 1001, 2121,
1646 2442, 4093, 4094, 4095}},
1650 {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 257, 258, 1000, 1001, 2121,
1651 2442, 4093, 4094, 4095}},
1655 {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 258, 260, 4096, 4098, 4100,
1656 4242, 6786, 8188, 8190}},
1660 {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 258, 260, 4096, 4098, 4100,
1661 4242, 6786, 8188, 8190}},
1665 {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 260, 4096, 4100, 8192, 8196,
1666 3276, 3280, 16376, 16380}},
1670 {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 260, 4096, 4100, 8192, 8196,
1671 3276, 3280, 16376, 16380}},
1675 {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 264, 4096, 4104, 8192, 8200,
1676 16384, 16392, 32752, 32760}},
1680 {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 264, 4096, 4104, 8192, 8200,
1681 16384, 16392, 32752, 32760}},
1685 {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 260, 4096, 4100, 8192, 8196,
1686 3276, 3280, 16376, 16380}},
1690 {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 264, 4096, 4104, 8192, 8200,
1691 16384, 16392, 32752, 32760}}};
1694 typedef InstructionSelectorTestWithParam<MemoryAccess>
1695 InstructionSelectorMemoryAccessTest;
1698 TEST_P(InstructionSelectorMemoryAccessTest, LoadWithParameters) {
1699 const MemoryAccess memacc = GetParam();
1700 StreamBuilder m(this, memacc.type, kMachPtr, kMachInt32);
1701 m.Return(m.Load(memacc.type, m.Parameter(0), m.Parameter(1)));
1702 Stream s = m.Build();
1703 ASSERT_EQ(1U, s.size());
1704 EXPECT_EQ(memacc.ldr_opcode, s[0]->arch_opcode());
1705 EXPECT_EQ(kMode_MRR, s[0]->addressing_mode());
1706 EXPECT_EQ(2U, s[0]->InputCount());
1707 EXPECT_EQ(1U, s[0]->OutputCount());
1711 TEST_P(InstructionSelectorMemoryAccessTest, LoadWithImmediateIndex) {
1712 const MemoryAccess memacc = GetParam();
1713 TRACED_FOREACH(int32_t, index, memacc.immediates) {
1714 StreamBuilder m(this, memacc.type, kMachPtr);
1715 m.Return(m.Load(memacc.type, m.Parameter(0), m.Int32Constant(index)));
1716 Stream s = m.Build();
1717 ASSERT_EQ(1U, s.size());
1718 EXPECT_EQ(memacc.ldr_opcode, s[0]->arch_opcode());
1719 EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
1720 EXPECT_EQ(2U, s[0]->InputCount());
1721 ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
1722 EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1)));
1723 ASSERT_EQ(1U, s[0]->OutputCount());
1728 TEST_P(InstructionSelectorMemoryAccessTest, StoreWithParameters) {
1729 const MemoryAccess memacc = GetParam();
1730 StreamBuilder m(this, kMachInt32, kMachPtr, kMachInt32, memacc.type);
1731 m.Store(memacc.type, m.Parameter(0), m.Parameter(1), m.Parameter(2));
1732 m.Return(m.Int32Constant(0));
1733 Stream s = m.Build();
1734 ASSERT_EQ(1U, s.size());
1735 EXPECT_EQ(memacc.str_opcode, s[0]->arch_opcode());
1736 EXPECT_EQ(kMode_MRR, s[0]->addressing_mode());
1737 EXPECT_EQ(3U, s[0]->InputCount());
1738 EXPECT_EQ(0U, s[0]->OutputCount());
1742 TEST_P(InstructionSelectorMemoryAccessTest, StoreWithImmediateIndex) {
1743 const MemoryAccess memacc = GetParam();
1744 TRACED_FOREACH(int32_t, index, memacc.immediates) {
1745 StreamBuilder m(this, kMachInt32, kMachPtr, memacc.type);
1746 m.Store(memacc.type, m.Parameter(0), m.Int32Constant(index),
1748 m.Return(m.Int32Constant(0));
1749 Stream s = m.Build();
1750 ASSERT_EQ(1U, s.size());
1751 EXPECT_EQ(memacc.str_opcode, s[0]->arch_opcode());
1752 EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
1753 ASSERT_EQ(3U, s[0]->InputCount());
1754 ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
1755 EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1)));
1756 EXPECT_EQ(0U, s[0]->OutputCount());
1761 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1762 InstructionSelectorMemoryAccessTest,
1763 ::testing::ValuesIn(kMemoryAccesses));
1766 // -----------------------------------------------------------------------------
1767 // Comparison instructions.
1769 static const MachInst2 kComparisonInstructions[] = {
1770 {&RawMachineAssembler::Word32Equal, "Word32Equal", kArm64Cmp32, kMachInt32},
1771 {&RawMachineAssembler::Word64Equal, "Word64Equal", kArm64Cmp, kMachInt64},
1775 typedef InstructionSelectorTestWithParam<MachInst2>
1776 InstructionSelectorComparisonTest;
1779 TEST_P(InstructionSelectorComparisonTest, WithParameters) {
1780 const MachInst2 cmp = GetParam();
1781 const MachineType type = cmp.machine_type;
1782 StreamBuilder m(this, type, type, type);
1783 m.Return((m.*cmp.constructor)(m.Parameter(0), m.Parameter(1)));
1784 Stream s = m.Build();
1785 ASSERT_EQ(1U, s.size());
1786 EXPECT_EQ(cmp.arch_opcode, s[0]->arch_opcode());
1787 EXPECT_EQ(2U, s[0]->InputCount());
1788 EXPECT_EQ(1U, s[0]->OutputCount());
1789 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1790 EXPECT_EQ(kEqual, s[0]->flags_condition());
1794 TEST_P(InstructionSelectorComparisonTest, WithImmediate) {
1795 const MachInst2 cmp = GetParam();
1796 const MachineType type = cmp.machine_type;
1797 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
1798 // Compare with 0 are turned into tst instruction.
1799 if (imm == 0) continue;
1800 StreamBuilder m(this, type, type);
1801 m.Return((m.*cmp.constructor)(m.Parameter(0), BuildConstant(m, type, imm)));
1802 Stream s = m.Build();
1803 ASSERT_EQ(1U, s.size());
1804 EXPECT_EQ(cmp.arch_opcode, s[0]->arch_opcode());
1805 ASSERT_EQ(2U, s[0]->InputCount());
1806 ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
1807 EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(1)));
1808 EXPECT_EQ(1U, s[0]->OutputCount());
1809 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1810 EXPECT_EQ(kEqual, s[0]->flags_condition());
1812 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
1813 // Compare with 0 are turned into tst instruction.
1814 if (imm == 0) continue;
1815 StreamBuilder m(this, type, type);
1816 m.Return((m.*cmp.constructor)(BuildConstant(m, type, imm), m.Parameter(0)));
1817 Stream s = m.Build();
1818 ASSERT_EQ(1U, s.size());
1819 EXPECT_EQ(cmp.arch_opcode, s[0]->arch_opcode());
1820 ASSERT_EQ(2U, s[0]->InputCount());
1821 ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
1822 EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(1)));
1823 EXPECT_EQ(1U, s[0]->OutputCount());
1824 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1825 EXPECT_EQ(kEqual, s[0]->flags_condition());
1829 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1830 InstructionSelectorComparisonTest,
1831 ::testing::ValuesIn(kComparisonInstructions));
1834 TEST_F(InstructionSelectorTest, Word32EqualWithZero) {
1836 StreamBuilder m(this, kMachInt32, kMachInt32);
1837 m.Return(m.Word32Equal(m.Parameter(0), m.Int32Constant(0)));
1838 Stream s = m.Build();
1839 ASSERT_EQ(1U, s.size());
1840 EXPECT_EQ(kArm64Tst32, s[0]->arch_opcode());
1841 ASSERT_EQ(2U, s[0]->InputCount());
1842 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
1843 EXPECT_EQ(1U, s[0]->OutputCount());
1844 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1845 EXPECT_EQ(kEqual, s[0]->flags_condition());
1848 StreamBuilder m(this, kMachInt32, kMachInt32);
1849 m.Return(m.Word32Equal(m.Int32Constant(0), m.Parameter(0)));
1850 Stream s = m.Build();
1851 ASSERT_EQ(1U, s.size());
1852 EXPECT_EQ(kArm64Tst32, s[0]->arch_opcode());
1853 ASSERT_EQ(2U, s[0]->InputCount());
1854 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
1855 EXPECT_EQ(1U, s[0]->OutputCount());
1856 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1857 EXPECT_EQ(kEqual, s[0]->flags_condition());
1862 TEST_F(InstructionSelectorTest, Word64EqualWithZero) {
1864 StreamBuilder m(this, kMachInt64, kMachInt64);
1865 m.Return(m.Word64Equal(m.Parameter(0), m.Int64Constant(0)));
1866 Stream s = m.Build();
1867 ASSERT_EQ(1U, s.size());
1868 EXPECT_EQ(kArm64Tst, s[0]->arch_opcode());
1869 ASSERT_EQ(2U, s[0]->InputCount());
1870 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
1871 EXPECT_EQ(1U, s[0]->OutputCount());
1872 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1873 EXPECT_EQ(kEqual, s[0]->flags_condition());
1876 StreamBuilder m(this, kMachInt64, kMachInt64);
1877 m.Return(m.Word64Equal(m.Int64Constant(0), m.Parameter(0)));
1878 Stream s = m.Build();
1879 ASSERT_EQ(1U, s.size());
1880 EXPECT_EQ(kArm64Tst, s[0]->arch_opcode());
1881 ASSERT_EQ(2U, s[0]->InputCount());
1882 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
1883 EXPECT_EQ(1U, s[0]->OutputCount());
1884 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1885 EXPECT_EQ(kEqual, s[0]->flags_condition());
1890 // -----------------------------------------------------------------------------
1894 static const MachInst2 kLogicalWithNotRHSs[] = {
1895 {&RawMachineAssembler::Word32And, "Word32And", kArm64Bic32, kMachInt32},
1896 {&RawMachineAssembler::Word64And, "Word64And", kArm64Bic, kMachInt64},
1897 {&RawMachineAssembler::Word32Or, "Word32Or", kArm64Orn32, kMachInt32},
1898 {&RawMachineAssembler::Word64Or, "Word64Or", kArm64Orn, kMachInt64},
1899 {&RawMachineAssembler::Word32Xor, "Word32Xor", kArm64Eon32, kMachInt32},
1900 {&RawMachineAssembler::Word64Xor, "Word64Xor", kArm64Eon, kMachInt64}};
1903 typedef InstructionSelectorTestWithParam<MachInst2>
1904 InstructionSelectorLogicalWithNotRHSTest;
1907 TEST_P(InstructionSelectorLogicalWithNotRHSTest, Parameter) {
1908 const MachInst2 inst = GetParam();
1909 const MachineType type = inst.machine_type;
1910 // Test cases where RHS is Xor(x, -1).
1912 StreamBuilder m(this, type, type, type);
1913 if (type == kMachInt32) {
1914 m.Return((m.*inst.constructor)(
1915 m.Parameter(0), m.Word32Xor(m.Parameter(1), m.Int32Constant(-1))));
1917 ASSERT_EQ(kMachInt64, type);
1918 m.Return((m.*inst.constructor)(
1919 m.Parameter(0), m.Word64Xor(m.Parameter(1), m.Int64Constant(-1))));
1921 Stream s = m.Build();
1922 ASSERT_EQ(1U, s.size());
1923 EXPECT_EQ(inst.arch_opcode, s[0]->arch_opcode());
1924 EXPECT_EQ(2U, s[0]->InputCount());
1925 EXPECT_EQ(1U, s[0]->OutputCount());
1928 StreamBuilder m(this, type, type, type);
1929 if (type == kMachInt32) {
1930 m.Return((m.*inst.constructor)(
1931 m.Word32Xor(m.Parameter(0), m.Int32Constant(-1)), m.Parameter(1)));
1933 ASSERT_EQ(kMachInt64, type);
1934 m.Return((m.*inst.constructor)(
1935 m.Word64Xor(m.Parameter(0), m.Int64Constant(-1)), m.Parameter(1)));
1937 Stream s = m.Build();
1938 ASSERT_EQ(1U, s.size());
1939 EXPECT_EQ(inst.arch_opcode, s[0]->arch_opcode());
1940 EXPECT_EQ(2U, s[0]->InputCount());
1941 EXPECT_EQ(1U, s[0]->OutputCount());
1943 // Test cases where RHS is Not(x).
1945 StreamBuilder m(this, type, type, type);
1946 if (type == kMachInt32) {
1948 (m.*inst.constructor)(m.Parameter(0), m.Word32Not(m.Parameter(1))));
1950 ASSERT_EQ(kMachInt64, type);
1952 (m.*inst.constructor)(m.Parameter(0), m.Word64Not(m.Parameter(1))));
1954 Stream s = m.Build();
1955 ASSERT_EQ(1U, s.size());
1956 EXPECT_EQ(inst.arch_opcode, s[0]->arch_opcode());
1957 EXPECT_EQ(2U, s[0]->InputCount());
1958 EXPECT_EQ(1U, s[0]->OutputCount());
1961 StreamBuilder m(this, type, type, type);
1962 if (type == kMachInt32) {
1964 (m.*inst.constructor)(m.Word32Not(m.Parameter(0)), m.Parameter(1)));
1966 ASSERT_EQ(kMachInt64, type);
1968 (m.*inst.constructor)(m.Word64Not(m.Parameter(0)), m.Parameter(1)));
1970 Stream s = m.Build();
1971 ASSERT_EQ(1U, s.size());
1972 EXPECT_EQ(inst.arch_opcode, s[0]->arch_opcode());
1973 EXPECT_EQ(2U, s[0]->InputCount());
1974 EXPECT_EQ(1U, s[0]->OutputCount());
1979 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
1980 InstructionSelectorLogicalWithNotRHSTest,
1981 ::testing::ValuesIn(kLogicalWithNotRHSs));
1984 TEST_F(InstructionSelectorTest, Word32NotWithParameter) {
1985 StreamBuilder m(this, kMachInt32, kMachInt32);
1986 m.Return(m.Word32Not(m.Parameter(0)));
1987 Stream s = m.Build();
1988 ASSERT_EQ(1U, s.size());
1989 EXPECT_EQ(kArm64Not32, s[0]->arch_opcode());
1990 EXPECT_EQ(1U, s[0]->InputCount());
1991 EXPECT_EQ(1U, s[0]->OutputCount());
1995 TEST_F(InstructionSelectorTest, Word64NotWithParameter) {
1996 StreamBuilder m(this, kMachInt64, kMachInt64);
1997 m.Return(m.Word64Not(m.Parameter(0)));
1998 Stream s = m.Build();
1999 ASSERT_EQ(1U, s.size());
2000 EXPECT_EQ(kArm64Not, s[0]->arch_opcode());
2001 EXPECT_EQ(1U, s[0]->InputCount());
2002 EXPECT_EQ(1U, s[0]->OutputCount());
2006 TEST_F(InstructionSelectorTest, Word32XorMinusOneWithParameter) {
2008 StreamBuilder m(this, kMachInt32, kMachInt32);
2009 m.Return(m.Word32Xor(m.Parameter(0), m.Int32Constant(-1)));
2010 Stream s = m.Build();
2011 ASSERT_EQ(1U, s.size());
2012 EXPECT_EQ(kArm64Not32, s[0]->arch_opcode());
2013 EXPECT_EQ(1U, s[0]->InputCount());
2014 EXPECT_EQ(1U, s[0]->OutputCount());
2017 StreamBuilder m(this, kMachInt32, kMachInt32);
2018 m.Return(m.Word32Xor(m.Int32Constant(-1), m.Parameter(0)));
2019 Stream s = m.Build();
2020 ASSERT_EQ(1U, s.size());
2021 EXPECT_EQ(kArm64Not32, s[0]->arch_opcode());
2022 EXPECT_EQ(1U, s[0]->InputCount());
2023 EXPECT_EQ(1U, s[0]->OutputCount());
2028 TEST_F(InstructionSelectorTest, Word64XorMinusOneWithParameter) {
2030 StreamBuilder m(this, kMachInt64, kMachInt64);
2031 m.Return(m.Word64Xor(m.Parameter(0), m.Int64Constant(-1)));
2032 Stream s = m.Build();
2033 ASSERT_EQ(1U, s.size());
2034 EXPECT_EQ(kArm64Not, s[0]->arch_opcode());
2035 EXPECT_EQ(1U, s[0]->InputCount());
2036 EXPECT_EQ(1U, s[0]->OutputCount());
2039 StreamBuilder m(this, kMachInt64, kMachInt64);
2040 m.Return(m.Word64Xor(m.Int64Constant(-1), m.Parameter(0)));
2041 Stream s = m.Build();
2042 ASSERT_EQ(1U, s.size());
2043 EXPECT_EQ(kArm64Not, s[0]->arch_opcode());
2044 EXPECT_EQ(1U, s[0]->InputCount());
2045 EXPECT_EQ(1U, s[0]->OutputCount());
2050 TEST_F(InstructionSelectorTest, Word32ShrWithWord32AndWithImmediate) {
2051 TRACED_FORRANGE(int32_t, lsb, 1, 31) {
2052 TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) {
2053 uint32_t jnk = rng()->NextInt();
2055 uint32_t msk = ((0xffffffffu >> (32 - width)) << lsb) | jnk;
2056 StreamBuilder m(this, kMachInt32, kMachInt32);
2057 m.Return(m.Word32Shr(m.Word32And(m.Parameter(0), m.Int32Constant(msk)),
2058 m.Int32Constant(lsb)));
2059 Stream s = m.Build();
2060 ASSERT_EQ(1U, s.size());
2061 EXPECT_EQ(kArm64Ubfx32, s[0]->arch_opcode());
2062 ASSERT_EQ(3U, s[0]->InputCount());
2063 EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
2064 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
2067 TRACED_FORRANGE(int32_t, lsb, 1, 31) {
2068 TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) {
2069 uint32_t jnk = rng()->NextInt();
2071 uint32_t msk = ((0xffffffffu >> (32 - width)) << lsb) | jnk;
2072 StreamBuilder m(this, kMachInt32, kMachInt32);
2073 m.Return(m.Word32Shr(m.Word32And(m.Int32Constant(msk), m.Parameter(0)),
2074 m.Int32Constant(lsb)));
2075 Stream s = m.Build();
2076 ASSERT_EQ(1U, s.size());
2077 EXPECT_EQ(kArm64Ubfx32, s[0]->arch_opcode());
2078 ASSERT_EQ(3U, s[0]->InputCount());
2079 EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
2080 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
2086 TEST_F(InstructionSelectorTest, Word64ShrWithWord64AndWithImmediate) {
2087 TRACED_FORRANGE(int32_t, lsb, 1, 63) {
2088 TRACED_FORRANGE(int32_t, width, 1, 64 - lsb) {
2089 uint64_t jnk = rng()->NextInt64();
2092 ((V8_UINT64_C(0xffffffffffffffff) >> (64 - width)) << lsb) | jnk;
2093 StreamBuilder m(this, kMachInt64, kMachInt64);
2094 m.Return(m.Word64Shr(m.Word64And(m.Parameter(0), m.Int64Constant(msk)),
2095 m.Int64Constant(lsb)));
2096 Stream s = m.Build();
2097 ASSERT_EQ(1U, s.size());
2098 EXPECT_EQ(kArm64Ubfx, s[0]->arch_opcode());
2099 ASSERT_EQ(3U, s[0]->InputCount());
2100 EXPECT_EQ(lsb, s.ToInt64(s[0]->InputAt(1)));
2101 EXPECT_EQ(width, s.ToInt64(s[0]->InputAt(2)));
2104 TRACED_FORRANGE(int32_t, lsb, 1, 63) {
2105 TRACED_FORRANGE(int32_t, width, 1, 64 - lsb) {
2106 uint64_t jnk = rng()->NextInt64();
2109 ((V8_UINT64_C(0xffffffffffffffff) >> (64 - width)) << lsb) | jnk;
2110 StreamBuilder m(this, kMachInt64, kMachInt64);
2111 m.Return(m.Word64Shr(m.Word64And(m.Int64Constant(msk), m.Parameter(0)),
2112 m.Int64Constant(lsb)));
2113 Stream s = m.Build();
2114 ASSERT_EQ(1U, s.size());
2115 EXPECT_EQ(kArm64Ubfx, s[0]->arch_opcode());
2116 ASSERT_EQ(3U, s[0]->InputCount());
2117 EXPECT_EQ(lsb, s.ToInt64(s[0]->InputAt(1)));
2118 EXPECT_EQ(width, s.ToInt64(s[0]->InputAt(2)));
2124 TEST_F(InstructionSelectorTest, Word32AndWithImmediateWithWord32Shr) {
2125 TRACED_FORRANGE(int32_t, lsb, 1, 31) {
2126 TRACED_FORRANGE(int32_t, width, 1, 31) {
2127 uint32_t msk = (1 << width) - 1;
2128 StreamBuilder m(this, kMachInt32, kMachInt32);
2129 m.Return(m.Word32And(m.Word32Shr(m.Parameter(0), m.Int32Constant(lsb)),
2130 m.Int32Constant(msk)));
2131 Stream s = m.Build();
2132 ASSERT_EQ(1U, s.size());
2133 EXPECT_EQ(kArm64Ubfx32, s[0]->arch_opcode());
2134 ASSERT_EQ(3U, s[0]->InputCount());
2135 EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
2136 int32_t actual_width = (lsb + width > 32) ? (32 - lsb) : width;
2137 EXPECT_EQ(actual_width, s.ToInt32(s[0]->InputAt(2)));
2140 TRACED_FORRANGE(int32_t, lsb, 1, 31) {
2141 TRACED_FORRANGE(int32_t, width, 1, 31) {
2142 uint32_t msk = (1 << width) - 1;
2143 StreamBuilder m(this, kMachInt32, kMachInt32);
2144 m.Return(m.Word32And(m.Int32Constant(msk),
2145 m.Word32Shr(m.Parameter(0), m.Int32Constant(lsb))));
2146 Stream s = m.Build();
2147 ASSERT_EQ(1U, s.size());
2148 EXPECT_EQ(kArm64Ubfx32, s[0]->arch_opcode());
2149 ASSERT_EQ(3U, s[0]->InputCount());
2150 EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
2151 int32_t actual_width = (lsb + width > 32) ? (32 - lsb) : width;
2152 EXPECT_EQ(actual_width, s.ToInt32(s[0]->InputAt(2)));
2158 TEST_F(InstructionSelectorTest, Word64AndWithImmediateWithWord64Shr) {
2159 TRACED_FORRANGE(int64_t, lsb, 1, 63) {
2160 TRACED_FORRANGE(int64_t, width, 1, 63) {
2161 uint64_t msk = (V8_UINT64_C(1) << width) - 1;
2162 StreamBuilder m(this, kMachInt64, kMachInt64);
2163 m.Return(m.Word64And(m.Word64Shr(m.Parameter(0), m.Int64Constant(lsb)),
2164 m.Int64Constant(msk)));
2165 Stream s = m.Build();
2166 ASSERT_EQ(1U, s.size());
2167 EXPECT_EQ(kArm64Ubfx, s[0]->arch_opcode());
2168 ASSERT_EQ(3U, s[0]->InputCount());
2169 EXPECT_EQ(lsb, s.ToInt64(s[0]->InputAt(1)));
2170 int64_t actual_width = (lsb + width > 64) ? (64 - lsb) : width;
2171 EXPECT_EQ(actual_width, s.ToInt64(s[0]->InputAt(2)));
2174 TRACED_FORRANGE(int64_t, lsb, 1, 63) {
2175 TRACED_FORRANGE(int64_t, width, 1, 63) {
2176 uint64_t msk = (V8_UINT64_C(1) << width) - 1;
2177 StreamBuilder m(this, kMachInt64, kMachInt64);
2178 m.Return(m.Word64And(m.Int64Constant(msk),
2179 m.Word64Shr(m.Parameter(0), m.Int64Constant(lsb))));
2180 Stream s = m.Build();
2181 ASSERT_EQ(1U, s.size());
2182 EXPECT_EQ(kArm64Ubfx, s[0]->arch_opcode());
2183 ASSERT_EQ(3U, s[0]->InputCount());
2184 EXPECT_EQ(lsb, s.ToInt64(s[0]->InputAt(1)));
2185 int64_t actual_width = (lsb + width > 64) ? (64 - lsb) : width;
2186 EXPECT_EQ(actual_width, s.ToInt64(s[0]->InputAt(2)));
2192 TEST_F(InstructionSelectorTest, Int32MulHighWithParameters) {
2193 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
2194 Node* const p0 = m.Parameter(0);
2195 Node* const p1 = m.Parameter(1);
2196 Node* const n = m.Int32MulHigh(p0, p1);
2198 Stream s = m.Build();
2199 ASSERT_EQ(2U, s.size());
2200 EXPECT_EQ(kArm64Smull, s[0]->arch_opcode());
2201 ASSERT_EQ(2U, s[0]->InputCount());
2202 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
2203 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
2204 ASSERT_EQ(1U, s[0]->OutputCount());
2205 EXPECT_EQ(kArm64Asr, s[1]->arch_opcode());
2206 ASSERT_EQ(2U, s[1]->InputCount());
2207 EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(0)));
2208 EXPECT_EQ(32, s.ToInt64(s[1]->InputAt(1)));
2209 ASSERT_EQ(1U, s[1]->OutputCount());
2210 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[1]->Output()));
2214 TEST_F(InstructionSelectorTest, Word32SarWithWord32Shl) {
2216 StreamBuilder m(this, kMachInt32, kMachInt32);
2217 Node* const p0 = m.Parameter(0);
2219 m.Word32Sar(m.Word32Shl(p0, m.Int32Constant(24)), m.Int32Constant(24));
2221 Stream s = m.Build();
2222 ASSERT_EQ(1U, s.size());
2223 EXPECT_EQ(kArm64Sxtb32, s[0]->arch_opcode());
2224 ASSERT_EQ(1U, s[0]->InputCount());
2225 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
2226 ASSERT_EQ(1U, s[0]->OutputCount());
2227 EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
2230 StreamBuilder m(this, kMachInt32, kMachInt32);
2231 Node* const p0 = m.Parameter(0);
2233 m.Word32Sar(m.Word32Shl(p0, m.Int32Constant(16)), m.Int32Constant(16));
2235 Stream s = m.Build();
2236 ASSERT_EQ(1U, s.size());
2237 EXPECT_EQ(kArm64Sxth32, s[0]->arch_opcode());
2238 ASSERT_EQ(1U, s[0]->InputCount());
2239 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
2240 ASSERT_EQ(1U, s[0]->OutputCount());
2241 EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
2246 TEST_F(InstructionSelectorTest, Word32Clz) {
2247 StreamBuilder m(this, kMachUint32, kMachUint32);
2248 Node* const p0 = m.Parameter(0);
2249 Node* const n = m.Word32Clz(p0);
2251 Stream s = m.Build();
2252 ASSERT_EQ(1U, s.size());
2253 EXPECT_EQ(kArm64Clz32, s[0]->arch_opcode());
2254 ASSERT_EQ(1U, s[0]->InputCount());
2255 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
2256 ASSERT_EQ(1U, s[0]->OutputCount());
2257 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
2260 } // namespace compiler
2261 } // namespace internal