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