1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "test/unittests/compiler/instruction-selector-unittest.h"
6
7 #include "src/compiler/node-matchers.h"
8
9 namespace v8 {
10 namespace internal {
11 namespace compiler {
12
13 // -----------------------------------------------------------------------------
14 // Conversions.
15
16
TEST_F(InstructionSelectorTest,ChangeFloat32ToFloat64WithParameter)17 TEST_F(InstructionSelectorTest, ChangeFloat32ToFloat64WithParameter) {
18 StreamBuilder m(this, MachineType::Float32(), MachineType::Float64());
19 m.Return(m.ChangeFloat32ToFloat64(m.Parameter(0)));
20 Stream s = m.Build();
21 ASSERT_EQ(1U, s.size());
22 EXPECT_EQ(kSSEFloat32ToFloat64, s[0]->arch_opcode());
23 EXPECT_EQ(1U, s[0]->InputCount());
24 EXPECT_EQ(1U, s[0]->OutputCount());
25 }
26
27
TEST_F(InstructionSelectorTest,ChangeInt32ToInt64WithParameter)28 TEST_F(InstructionSelectorTest, ChangeInt32ToInt64WithParameter) {
29 StreamBuilder m(this, MachineType::Int64(), MachineType::Int32());
30 m.Return(m.ChangeInt32ToInt64(m.Parameter(0)));
31 Stream s = m.Build();
32 ASSERT_EQ(1U, s.size());
33 EXPECT_EQ(kX64Movsxlq, s[0]->arch_opcode());
34 }
35
36
TEST_F(InstructionSelectorTest,ChangeUint32ToFloat64WithParameter)37 TEST_F(InstructionSelectorTest, ChangeUint32ToFloat64WithParameter) {
38 StreamBuilder m(this, MachineType::Float64(), MachineType::Uint32());
39 m.Return(m.ChangeUint32ToFloat64(m.Parameter(0)));
40 Stream s = m.Build();
41 ASSERT_EQ(1U, s.size());
42 EXPECT_EQ(kSSEUint32ToFloat64, s[0]->arch_opcode());
43 }
44
45
TEST_F(InstructionSelectorTest,ChangeUint32ToUint64WithParameter)46 TEST_F(InstructionSelectorTest, ChangeUint32ToUint64WithParameter) {
47 StreamBuilder m(this, MachineType::Uint64(), MachineType::Uint32());
48 m.Return(m.ChangeUint32ToUint64(m.Parameter(0)));
49 Stream s = m.Build();
50 ASSERT_EQ(1U, s.size());
51 EXPECT_EQ(kX64Movl, s[0]->arch_opcode());
52 }
53
54
TEST_F(InstructionSelectorTest,TruncateFloat64ToFloat32WithParameter)55 TEST_F(InstructionSelectorTest, TruncateFloat64ToFloat32WithParameter) {
56 StreamBuilder m(this, MachineType::Float64(), MachineType::Float32());
57 m.Return(m.TruncateFloat64ToFloat32(m.Parameter(0)));
58 Stream s = m.Build();
59 ASSERT_EQ(1U, s.size());
60 EXPECT_EQ(kSSEFloat64ToFloat32, s[0]->arch_opcode());
61 EXPECT_EQ(1U, s[0]->InputCount());
62 EXPECT_EQ(1U, s[0]->OutputCount());
63 }
64
65
TEST_F(InstructionSelectorTest,TruncateInt64ToInt32WithParameter)66 TEST_F(InstructionSelectorTest, TruncateInt64ToInt32WithParameter) {
67 StreamBuilder m(this, MachineType::Int32(), MachineType::Int64());
68 m.Return(m.TruncateInt64ToInt32(m.Parameter(0)));
69 Stream s = m.Build();
70 ASSERT_EQ(1U, s.size());
71 EXPECT_EQ(kX64Movl, s[0]->arch_opcode());
72 }
73
74
75 // -----------------------------------------------------------------------------
76 // Loads and stores
77
78
79 namespace {
80
81 struct MemoryAccess {
82 MachineType type;
83 ArchOpcode load_opcode;
84 ArchOpcode store_opcode;
85 };
86
87
operator <<(std::ostream & os,const MemoryAccess & memacc)88 std::ostream& operator<<(std::ostream& os, const MemoryAccess& memacc) {
89 return os << memacc.type;
90 }
91
92
93 static const MemoryAccess kMemoryAccesses[] = {
94 {MachineType::Int8(), kX64Movsxbl, kX64Movb},
95 {MachineType::Uint8(), kX64Movzxbl, kX64Movb},
96 {MachineType::Int16(), kX64Movsxwl, kX64Movw},
97 {MachineType::Uint16(), kX64Movzxwl, kX64Movw},
98 {MachineType::Int32(), kX64Movl, kX64Movl},
99 {MachineType::Uint32(), kX64Movl, kX64Movl},
100 {MachineType::Int64(), kX64Movq, kX64Movq},
101 {MachineType::Uint64(), kX64Movq, kX64Movq},
102 {MachineType::Float32(), kX64Movss, kX64Movss},
103 {MachineType::Float64(), kX64Movsd, kX64Movsd}};
104
105 } // namespace
106
107
108 typedef InstructionSelectorTestWithParam<MemoryAccess>
109 InstructionSelectorMemoryAccessTest;
110
111
TEST_P(InstructionSelectorMemoryAccessTest,LoadWithParameters)112 TEST_P(InstructionSelectorMemoryAccessTest, LoadWithParameters) {
113 const MemoryAccess memacc = GetParam();
114 StreamBuilder m(this, memacc.type, MachineType::Pointer(),
115 MachineType::Int32());
116 m.Return(m.Load(memacc.type, m.Parameter(0), m.Parameter(1)));
117 Stream s = m.Build();
118 ASSERT_EQ(1U, s.size());
119 EXPECT_EQ(memacc.load_opcode, s[0]->arch_opcode());
120 EXPECT_EQ(2U, s[0]->InputCount());
121 EXPECT_EQ(1U, s[0]->OutputCount());
122 }
123
124
TEST_P(InstructionSelectorMemoryAccessTest,StoreWithParameters)125 TEST_P(InstructionSelectorMemoryAccessTest, StoreWithParameters) {
126 const MemoryAccess memacc = GetParam();
127 StreamBuilder m(this, MachineType::Int32(), MachineType::Pointer(),
128 MachineType::Int32(), memacc.type);
129 m.Store(memacc.type.representation(), m.Parameter(0), m.Parameter(1),
130 m.Parameter(2), kNoWriteBarrier);
131 m.Return(m.Int32Constant(0));
132 Stream s = m.Build();
133 ASSERT_EQ(1U, s.size());
134 EXPECT_EQ(memacc.store_opcode, s[0]->arch_opcode());
135 EXPECT_EQ(3U, s[0]->InputCount());
136 EXPECT_EQ(0U, s[0]->OutputCount());
137 }
138
139
140 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
141 InstructionSelectorMemoryAccessTest,
142 ::testing::ValuesIn(kMemoryAccesses));
143
144
145 // -----------------------------------------------------------------------------
146 // ChangeUint32ToUint64.
147
148
149 namespace {
150
151 typedef Node* (RawMachineAssembler::*Constructor)(Node*, Node*);
152
153
154 struct BinaryOperation {
155 Constructor constructor;
156 const char* constructor_name;
157 };
158
159
operator <<(std::ostream & os,const BinaryOperation & bop)160 std::ostream& operator<<(std::ostream& os, const BinaryOperation& bop) {
161 return os << bop.constructor_name;
162 }
163
164
165 const BinaryOperation kWord32BinaryOperations[] = {
166 {&RawMachineAssembler::Word32And, "Word32And"},
167 {&RawMachineAssembler::Word32Or, "Word32Or"},
168 {&RawMachineAssembler::Word32Xor, "Word32Xor"},
169 {&RawMachineAssembler::Word32Shl, "Word32Shl"},
170 {&RawMachineAssembler::Word32Shr, "Word32Shr"},
171 {&RawMachineAssembler::Word32Sar, "Word32Sar"},
172 {&RawMachineAssembler::Word32Ror, "Word32Ror"},
173 {&RawMachineAssembler::Word32Equal, "Word32Equal"},
174 {&RawMachineAssembler::Int32Add, "Int32Add"},
175 {&RawMachineAssembler::Int32Sub, "Int32Sub"},
176 {&RawMachineAssembler::Int32Mul, "Int32Mul"},
177 {&RawMachineAssembler::Int32MulHigh, "Int32MulHigh"},
178 {&RawMachineAssembler::Int32Div, "Int32Div"},
179 {&RawMachineAssembler::Int32LessThan, "Int32LessThan"},
180 {&RawMachineAssembler::Int32LessThanOrEqual, "Int32LessThanOrEqual"},
181 {&RawMachineAssembler::Int32Mod, "Int32Mod"},
182 {&RawMachineAssembler::Uint32Div, "Uint32Div"},
183 {&RawMachineAssembler::Uint32LessThan, "Uint32LessThan"},
184 {&RawMachineAssembler::Uint32LessThanOrEqual, "Uint32LessThanOrEqual"},
185 {&RawMachineAssembler::Uint32Mod, "Uint32Mod"}};
186
187 } // namespace
188
189
190 typedef InstructionSelectorTestWithParam<BinaryOperation>
191 InstructionSelectorChangeUint32ToUint64Test;
192
193
TEST_P(InstructionSelectorChangeUint32ToUint64Test,ChangeUint32ToUint64)194 TEST_P(InstructionSelectorChangeUint32ToUint64Test, ChangeUint32ToUint64) {
195 const BinaryOperation& bop = GetParam();
196 StreamBuilder m(this, MachineType::Uint64(), MachineType::Int32(),
197 MachineType::Int32());
198 Node* const p0 = m.Parameter(0);
199 Node* const p1 = m.Parameter(1);
200 m.Return(m.ChangeUint32ToUint64((m.*bop.constructor)(p0, p1)));
201 Stream s = m.Build();
202 ASSERT_EQ(1U, s.size());
203 }
204
205
206 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
207 InstructionSelectorChangeUint32ToUint64Test,
208 ::testing::ValuesIn(kWord32BinaryOperations));
209
210
211 // -----------------------------------------------------------------------------
212 // TruncateInt64ToInt32.
213
214
TEST_F(InstructionSelectorTest,TruncateInt64ToInt32WithWord64Sar)215 TEST_F(InstructionSelectorTest, TruncateInt64ToInt32WithWord64Sar) {
216 StreamBuilder m(this, MachineType::Int32(), MachineType::Int64());
217 Node* const p = m.Parameter(0);
218 Node* const t = m.TruncateInt64ToInt32(m.Word64Sar(p, m.Int64Constant(32)));
219 m.Return(t);
220 Stream s = m.Build();
221 ASSERT_EQ(1U, s.size());
222 EXPECT_EQ(kX64Shr, s[0]->arch_opcode());
223 ASSERT_EQ(2U, s[0]->InputCount());
224 EXPECT_EQ(s.ToVreg(p), s.ToVreg(s[0]->InputAt(0)));
225 EXPECT_EQ(32, s.ToInt32(s[0]->InputAt(1)));
226 ASSERT_EQ(1U, s[0]->OutputCount());
227 EXPECT_TRUE(s.IsSameAsFirst(s[0]->OutputAt(0)));
228 EXPECT_EQ(s.ToVreg(t), s.ToVreg(s[0]->OutputAt(0)));
229 }
230
231
TEST_F(InstructionSelectorTest,TruncateInt64ToInt32WithWord64Shr)232 TEST_F(InstructionSelectorTest, TruncateInt64ToInt32WithWord64Shr) {
233 StreamBuilder m(this, MachineType::Int32(), MachineType::Int64());
234 Node* const p = m.Parameter(0);
235 Node* const t = m.TruncateInt64ToInt32(m.Word64Shr(p, m.Int64Constant(32)));
236 m.Return(t);
237 Stream s = m.Build();
238 ASSERT_EQ(1U, s.size());
239 EXPECT_EQ(kX64Shr, s[0]->arch_opcode());
240 ASSERT_EQ(2U, s[0]->InputCount());
241 EXPECT_EQ(s.ToVreg(p), s.ToVreg(s[0]->InputAt(0)));
242 EXPECT_EQ(32, s.ToInt32(s[0]->InputAt(1)));
243 ASSERT_EQ(1U, s[0]->OutputCount());
244 EXPECT_TRUE(s.IsSameAsFirst(s[0]->OutputAt(0)));
245 EXPECT_EQ(s.ToVreg(t), s.ToVreg(s[0]->OutputAt(0)));
246 }
247
248
249 // -----------------------------------------------------------------------------
250 // Addition.
251
252
TEST_F(InstructionSelectorTest,Int32AddWithInt32ParametersLea)253 TEST_F(InstructionSelectorTest, Int32AddWithInt32ParametersLea) {
254 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
255 MachineType::Int32());
256 Node* const p0 = m.Parameter(0);
257 Node* const p1 = m.Parameter(1);
258 Node* const a0 = m.Int32Add(p0, p1);
259 // Additional uses of input to add chooses lea
260 Node* const a1 = m.Int32Div(p0, p1);
261 m.Return(m.Int32Div(a0, a1));
262 Stream s = m.Build();
263 ASSERT_EQ(3U, s.size());
264 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
265 ASSERT_EQ(2U, s[0]->InputCount());
266 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
267 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
268 }
269
270
TEST_F(InstructionSelectorTest,Int32AddConstantAsLeaSingle)271 TEST_F(InstructionSelectorTest, Int32AddConstantAsLeaSingle) {
272 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
273 Node* const p0 = m.Parameter(0);
274 Node* const c0 = m.Int32Constant(15);
275 // If one of the add's operands is only used once, use an "leal", even though
276 // an "addl" could be used. The "leal" has proven faster--out best guess is
277 // that it gives the register allocation more freedom and it doesn't set
278 // flags, reducing pressure in the CPU's pipeline. If we're lucky with
279 // register allocation, then code generation will select an "addl" later for
280 // the cases that have been measured to be faster.
281 Node* const v0 = m.Int32Add(p0, c0);
282 m.Return(v0);
283 Stream s = m.Build();
284 ASSERT_EQ(1U, s.size());
285 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
286 EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
287 ASSERT_EQ(2U, s[0]->InputCount());
288 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
289 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
290 }
291
292
TEST_F(InstructionSelectorTest,Int32AddConstantAsAdd)293 TEST_F(InstructionSelectorTest, Int32AddConstantAsAdd) {
294 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
295 Node* const p0 = m.Parameter(0);
296 Node* const c0 = m.Int32Constant(1);
297 // If there is only a single use of an add's input and the immediate constant
298 // for the add is 1, don't use an inc. It is much slower on modern Intel
299 // architectures.
300 m.Return(m.Int32Add(p0, c0));
301 Stream s = m.Build();
302 ASSERT_EQ(1U, s.size());
303 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
304 EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
305 ASSERT_EQ(2U, s[0]->InputCount());
306 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
307 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
308 }
309
310
TEST_F(InstructionSelectorTest,Int32AddConstantAsLeaDouble)311 TEST_F(InstructionSelectorTest, Int32AddConstantAsLeaDouble) {
312 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
313 Node* const p0 = m.Parameter(0);
314 Node* const c0 = m.Int32Constant(15);
315 // A second use of an add's input uses lea
316 Node* const a0 = m.Int32Add(p0, c0);
317 m.Return(m.Int32Div(a0, p0));
318 Stream s = m.Build();
319 ASSERT_EQ(2U, s.size());
320 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
321 EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
322 ASSERT_EQ(2U, s[0]->InputCount());
323 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
324 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
325 }
326
327
TEST_F(InstructionSelectorTest,Int32AddCommutedConstantAsLeaSingle)328 TEST_F(InstructionSelectorTest, Int32AddCommutedConstantAsLeaSingle) {
329 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
330 Node* const p0 = m.Parameter(0);
331 Node* const c0 = m.Int32Constant(15);
332 // If one of the add's operands is only used once, use an "leal", even though
333 // an "addl" could be used. The "leal" has proven faster--out best guess is
334 // that it gives the register allocation more freedom and it doesn't set
335 // flags, reducing pressure in the CPU's pipeline. If we're lucky with
336 // register allocation, then code generation will select an "addl" later for
337 // the cases that have been measured to be faster.
338 m.Return(m.Int32Add(c0, p0));
339 Stream s = m.Build();
340 ASSERT_EQ(1U, s.size());
341 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
342 EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
343 ASSERT_EQ(2U, s[0]->InputCount());
344 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
345 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
346 }
347
348
TEST_F(InstructionSelectorTest,Int32AddCommutedConstantAsLeaDouble)349 TEST_F(InstructionSelectorTest, Int32AddCommutedConstantAsLeaDouble) {
350 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
351 Node* const p0 = m.Parameter(0);
352 Node* const c0 = m.Int32Constant(15);
353 // A second use of an add's input uses lea
354 Node* const a0 = m.Int32Add(c0, p0);
355 USE(a0);
356 m.Return(m.Int32Div(a0, p0));
357 Stream s = m.Build();
358 ASSERT_EQ(2U, s.size());
359 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
360 EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
361 ASSERT_EQ(2U, s[0]->InputCount());
362 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
363 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
364 }
365
366
TEST_F(InstructionSelectorTest,Int32AddSimpleAsAdd)367 TEST_F(InstructionSelectorTest, Int32AddSimpleAsAdd) {
368 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
369 MachineType::Int32());
370 Node* const p0 = m.Parameter(0);
371 Node* const p1 = m.Parameter(1);
372 // If one of the add's operands is only used once, use an "leal", even though
373 // an "addl" could be used. The "leal" has proven faster--out best guess is
374 // that it gives the register allocation more freedom and it doesn't set
375 // flags, reducing pressure in the CPU's pipeline. If we're lucky with
376 // register allocation, then code generation will select an "addl" later for
377 // the cases that have been measured to be faster.
378 m.Return(m.Int32Add(p0, p1));
379 Stream s = m.Build();
380 ASSERT_EQ(1U, s.size());
381 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
382 EXPECT_EQ(kMode_MR1, s[0]->addressing_mode());
383 ASSERT_EQ(2U, s[0]->InputCount());
384 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
385 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
386 }
387
388
TEST_F(InstructionSelectorTest,Int32AddSimpleAsLea)389 TEST_F(InstructionSelectorTest, Int32AddSimpleAsLea) {
390 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
391 MachineType::Int32());
392 Node* const p0 = m.Parameter(0);
393 Node* const p1 = m.Parameter(1);
394 // If all of of the add's operands are used multiple times, use an "leal".
395 Node* const v1 = m.Int32Add(p0, p1);
396 m.Return(m.Int32Add(m.Int32Add(v1, p1), p0));
397 Stream s = m.Build();
398 ASSERT_EQ(3U, s.size());
399 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
400 EXPECT_EQ(kMode_MR1, s[0]->addressing_mode());
401 ASSERT_EQ(2U, s[0]->InputCount());
402 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
403 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
404 }
405
406
TEST_F(InstructionSelectorTest,Int32AddScaled2Mul)407 TEST_F(InstructionSelectorTest, Int32AddScaled2Mul) {
408 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
409 MachineType::Int32());
410 Node* const p0 = m.Parameter(0);
411 Node* const p1 = m.Parameter(1);
412 Node* const s0 = m.Int32Mul(p1, m.Int32Constant(2));
413 m.Return(m.Int32Add(p0, s0));
414 Stream s = m.Build();
415 ASSERT_EQ(1U, s.size());
416 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
417 EXPECT_EQ(kMode_MR2, s[0]->addressing_mode());
418 ASSERT_EQ(2U, s[0]->InputCount());
419 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
420 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
421 }
422
423
TEST_F(InstructionSelectorTest,Int32AddCommutedScaled2Mul)424 TEST_F(InstructionSelectorTest, Int32AddCommutedScaled2Mul) {
425 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
426 MachineType::Int32());
427 Node* const p0 = m.Parameter(0);
428 Node* const p1 = m.Parameter(1);
429 Node* const s0 = m.Int32Mul(p1, m.Int32Constant(2));
430 m.Return(m.Int32Add(s0, p0));
431 Stream s = m.Build();
432 ASSERT_EQ(1U, s.size());
433 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
434 EXPECT_EQ(kMode_MR2, s[0]->addressing_mode());
435 ASSERT_EQ(2U, s[0]->InputCount());
436 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
437 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
438 }
439
440
TEST_F(InstructionSelectorTest,Int32AddScaled2Shl)441 TEST_F(InstructionSelectorTest, Int32AddScaled2Shl) {
442 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
443 MachineType::Int32());
444 Node* const p0 = m.Parameter(0);
445 Node* const p1 = m.Parameter(1);
446 Node* const s0 = m.Word32Shl(p1, m.Int32Constant(1));
447 m.Return(m.Int32Add(p0, s0));
448 Stream s = m.Build();
449 ASSERT_EQ(1U, s.size());
450 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
451 EXPECT_EQ(kMode_MR2, s[0]->addressing_mode());
452 ASSERT_EQ(2U, s[0]->InputCount());
453 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
454 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
455 }
456
457
TEST_F(InstructionSelectorTest,Int32AddCommutedScaled2Shl)458 TEST_F(InstructionSelectorTest, Int32AddCommutedScaled2Shl) {
459 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
460 MachineType::Int32());
461 Node* const p0 = m.Parameter(0);
462 Node* const p1 = m.Parameter(1);
463 Node* const s0 = m.Word32Shl(p1, m.Int32Constant(1));
464 m.Return(m.Int32Add(s0, p0));
465 Stream s = m.Build();
466 ASSERT_EQ(1U, s.size());
467 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
468 EXPECT_EQ(kMode_MR2, s[0]->addressing_mode());
469 ASSERT_EQ(2U, s[0]->InputCount());
470 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
471 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
472 }
473
474
TEST_F(InstructionSelectorTest,Int32AddScaled4Mul)475 TEST_F(InstructionSelectorTest, Int32AddScaled4Mul) {
476 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
477 MachineType::Int32());
478 Node* const p0 = m.Parameter(0);
479 Node* const p1 = m.Parameter(1);
480 Node* const s0 = m.Int32Mul(p1, m.Int32Constant(4));
481 m.Return(m.Int32Add(p0, s0));
482 Stream s = m.Build();
483 ASSERT_EQ(1U, s.size());
484 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
485 EXPECT_EQ(kMode_MR4, s[0]->addressing_mode());
486 ASSERT_EQ(2U, s[0]->InputCount());
487 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
488 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
489 }
490
491
TEST_F(InstructionSelectorTest,Int32AddScaled4Shl)492 TEST_F(InstructionSelectorTest, Int32AddScaled4Shl) {
493 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
494 MachineType::Int32());
495 Node* const p0 = m.Parameter(0);
496 Node* const p1 = m.Parameter(1);
497 Node* const s0 = m.Word32Shl(p1, m.Int32Constant(2));
498 m.Return(m.Int32Add(p0, s0));
499 Stream s = m.Build();
500 ASSERT_EQ(1U, s.size());
501 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
502 EXPECT_EQ(kMode_MR4, s[0]->addressing_mode());
503 ASSERT_EQ(2U, s[0]->InputCount());
504 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
505 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
506 }
507
508
TEST_F(InstructionSelectorTest,Int32AddScaled8Mul)509 TEST_F(InstructionSelectorTest, Int32AddScaled8Mul) {
510 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
511 MachineType::Int32());
512 Node* const p0 = m.Parameter(0);
513 Node* const p1 = m.Parameter(1);
514 Node* const s0 = m.Int32Mul(p1, m.Int32Constant(8));
515 m.Return(m.Int32Add(p0, s0));
516 Stream s = m.Build();
517 ASSERT_EQ(1U, s.size());
518 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
519 EXPECT_EQ(kMode_MR8, s[0]->addressing_mode());
520 ASSERT_EQ(2U, s[0]->InputCount());
521 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
522 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
523 }
524
525
TEST_F(InstructionSelectorTest,Int32AddScaled8Shl)526 TEST_F(InstructionSelectorTest, Int32AddScaled8Shl) {
527 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
528 MachineType::Int32());
529 Node* const p0 = m.Parameter(0);
530 Node* const p1 = m.Parameter(1);
531 Node* const s0 = m.Word32Shl(p1, m.Int32Constant(3));
532 m.Return(m.Int32Add(p0, s0));
533 Stream s = m.Build();
534 ASSERT_EQ(1U, s.size());
535 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
536 EXPECT_EQ(kMode_MR8, s[0]->addressing_mode());
537 ASSERT_EQ(2U, s[0]->InputCount());
538 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
539 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
540 }
541
542
TEST_F(InstructionSelectorTest,Int32AddScaled2MulWithConstant)543 TEST_F(InstructionSelectorTest, Int32AddScaled2MulWithConstant) {
544 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
545 MachineType::Int32());
546 Node* const p0 = m.Parameter(0);
547 Node* const p1 = m.Parameter(1);
548 Node* const s0 = m.Int32Mul(p1, m.Int32Constant(2));
549 Node* const c0 = m.Int32Constant(15);
550 m.Return(m.Int32Add(c0, m.Int32Add(p0, s0)));
551 Stream s = m.Build();
552 ASSERT_EQ(1U, s.size());
553 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
554 EXPECT_EQ(kMode_MR2I, s[0]->addressing_mode());
555 ASSERT_EQ(3U, s[0]->InputCount());
556 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
557 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
558 EXPECT_TRUE(s[0]->InputAt(2)->IsImmediate());
559 }
560
561
TEST_F(InstructionSelectorTest,Int32AddScaled2MulWithConstantShuffle1)562 TEST_F(InstructionSelectorTest, Int32AddScaled2MulWithConstantShuffle1) {
563 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
564 MachineType::Int32());
565 Node* const p0 = m.Parameter(0);
566 Node* const p1 = m.Parameter(1);
567 Node* const s0 = m.Int32Mul(p1, m.Int32Constant(2));
568 Node* const c0 = m.Int32Constant(15);
569 m.Return(m.Int32Add(p0, m.Int32Add(s0, c0)));
570 Stream s = m.Build();
571 ASSERT_EQ(1U, s.size());
572 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
573 EXPECT_EQ(kMode_MR2I, s[0]->addressing_mode());
574 ASSERT_EQ(3U, s[0]->InputCount());
575 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
576 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
577 EXPECT_TRUE(s[0]->InputAt(2)->IsImmediate());
578 }
579
580
TEST_F(InstructionSelectorTest,Int32AddScaled2MulWithConstantShuffle2)581 TEST_F(InstructionSelectorTest, Int32AddScaled2MulWithConstantShuffle2) {
582 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
583 MachineType::Int32());
584 Node* const p0 = m.Parameter(0);
585 Node* const p1 = m.Parameter(1);
586 Node* const s0 = m.Int32Mul(p1, m.Int32Constant(2));
587 Node* const c0 = m.Int32Constant(15);
588 m.Return(m.Int32Add(s0, m.Int32Add(c0, p0)));
589 Stream s = m.Build();
590 ASSERT_EQ(1U, s.size());
591 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
592 EXPECT_EQ(kMode_MR2I, s[0]->addressing_mode());
593 ASSERT_EQ(3U, s[0]->InputCount());
594 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
595 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
596 EXPECT_TRUE(s[0]->InputAt(2)->IsImmediate());
597 }
598
599
TEST_F(InstructionSelectorTest,Int32AddScaled2MulWithConstantShuffle3)600 TEST_F(InstructionSelectorTest, Int32AddScaled2MulWithConstantShuffle3) {
601 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
602 MachineType::Int32());
603 Node* const p0 = m.Parameter(0);
604 Node* const p1 = m.Parameter(1);
605 Node* const s0 = m.Int32Mul(p1, m.Int32Constant(2));
606 Node* const c0 = m.Int32Constant(15);
607 m.Return(m.Int32Add(m.Int32Add(s0, c0), p0));
608 Stream s = m.Build();
609 ASSERT_EQ(1U, s.size());
610 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
611 EXPECT_EQ(kMode_MR2I, s[0]->addressing_mode());
612 ASSERT_EQ(3U, s[0]->InputCount());
613 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
614 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
615 EXPECT_TRUE(s[0]->InputAt(2)->IsImmediate());
616 }
617
618
TEST_F(InstructionSelectorTest,Int32AddScaled2MulWithConstantShuffle4)619 TEST_F(InstructionSelectorTest, Int32AddScaled2MulWithConstantShuffle4) {
620 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
621 MachineType::Int32());
622 Node* const p0 = m.Parameter(0);
623 Node* const p1 = m.Parameter(1);
624 Node* const s0 = m.Int32Mul(p1, m.Int32Constant(2));
625 Node* const c0 = m.Int32Constant(15);
626 m.Return(m.Int32Add(m.Int32Add(c0, p0), s0));
627 Stream s = m.Build();
628 ASSERT_EQ(1U, s.size());
629 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
630 EXPECT_EQ(kMode_MR2I, s[0]->addressing_mode());
631 ASSERT_EQ(3U, s[0]->InputCount());
632 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
633 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
634 EXPECT_TRUE(s[0]->InputAt(2)->IsImmediate());
635 }
636
637
TEST_F(InstructionSelectorTest,Int32AddScaled2MulWithConstantShuffle5)638 TEST_F(InstructionSelectorTest, Int32AddScaled2MulWithConstantShuffle5) {
639 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
640 MachineType::Int32());
641 Node* const p0 = m.Parameter(0);
642 Node* const p1 = m.Parameter(1);
643 Node* const s0 = m.Int32Mul(p1, m.Int32Constant(2));
644 Node* const c0 = m.Int32Constant(15);
645 m.Return(m.Int32Add(m.Int32Add(p0, s0), c0));
646 Stream s = m.Build();
647 ASSERT_EQ(1U, s.size());
648 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
649 EXPECT_EQ(kMode_MR2I, s[0]->addressing_mode());
650 ASSERT_EQ(3U, s[0]->InputCount());
651 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
652 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
653 EXPECT_TRUE(s[0]->InputAt(2)->IsImmediate());
654 }
655
656
TEST_F(InstructionSelectorTest,Int32AddScaled2ShlWithConstant)657 TEST_F(InstructionSelectorTest, Int32AddScaled2ShlWithConstant) {
658 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
659 MachineType::Int32());
660 Node* const p0 = m.Parameter(0);
661 Node* const p1 = m.Parameter(1);
662 Node* const s0 = m.Word32Shl(p1, m.Int32Constant(1));
663 Node* const c0 = m.Int32Constant(15);
664 m.Return(m.Int32Add(c0, m.Int32Add(p0, s0)));
665 Stream s = m.Build();
666 ASSERT_EQ(1U, s.size());
667 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
668 EXPECT_EQ(kMode_MR2I, s[0]->addressing_mode());
669 ASSERT_EQ(3U, s[0]->InputCount());
670 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
671 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
672 EXPECT_TRUE(s[0]->InputAt(2)->IsImmediate());
673 }
674
675
TEST_F(InstructionSelectorTest,Int32AddScaled4MulWithConstant)676 TEST_F(InstructionSelectorTest, Int32AddScaled4MulWithConstant) {
677 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
678 MachineType::Int32());
679 Node* const p0 = m.Parameter(0);
680 Node* const p1 = m.Parameter(1);
681 Node* const s0 = m.Int32Mul(p1, m.Int32Constant(4));
682 Node* const c0 = m.Int32Constant(15);
683 m.Return(m.Int32Add(c0, m.Int32Add(p0, s0)));
684 Stream s = m.Build();
685 ASSERT_EQ(1U, s.size());
686 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
687 EXPECT_EQ(kMode_MR4I, s[0]->addressing_mode());
688 ASSERT_EQ(3U, s[0]->InputCount());
689 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
690 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
691 EXPECT_TRUE(s[0]->InputAt(2)->IsImmediate());
692 }
693
694
TEST_F(InstructionSelectorTest,Int32AddScaled4ShlWithConstant)695 TEST_F(InstructionSelectorTest, Int32AddScaled4ShlWithConstant) {
696 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
697 MachineType::Int32());
698 Node* const p0 = m.Parameter(0);
699 Node* const p1 = m.Parameter(1);
700 Node* const s0 = m.Word32Shl(p1, m.Int32Constant(2));
701 Node* const c0 = m.Int32Constant(15);
702 m.Return(m.Int32Add(c0, m.Int32Add(p0, s0)));
703 Stream s = m.Build();
704 ASSERT_EQ(1U, s.size());
705 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
706 EXPECT_EQ(kMode_MR4I, s[0]->addressing_mode());
707 ASSERT_EQ(3U, s[0]->InputCount());
708 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
709 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
710 EXPECT_TRUE(s[0]->InputAt(2)->IsImmediate());
711 }
712
713
TEST_F(InstructionSelectorTest,Int32AddScaled8MulWithConstant)714 TEST_F(InstructionSelectorTest, Int32AddScaled8MulWithConstant) {
715 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
716 MachineType::Int32());
717 Node* const p0 = m.Parameter(0);
718 Node* const p1 = m.Parameter(1);
719 Node* const s0 = m.Int32Mul(p1, m.Int32Constant(8));
720 Node* const c0 = m.Int32Constant(15);
721 m.Return(m.Int32Add(c0, m.Int32Add(p0, s0)));
722 Stream s = m.Build();
723 ASSERT_EQ(1U, s.size());
724 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
725 EXPECT_EQ(kMode_MR8I, s[0]->addressing_mode());
726 ASSERT_EQ(3U, s[0]->InputCount());
727 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
728 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
729 EXPECT_TRUE(s[0]->InputAt(2)->IsImmediate());
730 }
731
732
TEST_F(InstructionSelectorTest,Int32AddScaled8ShlWithConstant)733 TEST_F(InstructionSelectorTest, Int32AddScaled8ShlWithConstant) {
734 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
735 MachineType::Int32());
736 Node* const p0 = m.Parameter(0);
737 Node* const p1 = m.Parameter(1);
738 Node* const s0 = m.Word32Shl(p1, m.Int32Constant(3));
739 Node* const c0 = m.Int32Constant(15);
740 m.Return(m.Int32Add(c0, m.Int32Add(p0, s0)));
741 Stream s = m.Build();
742 ASSERT_EQ(1U, s.size());
743 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
744 EXPECT_EQ(kMode_MR8I, s[0]->addressing_mode());
745 ASSERT_EQ(3U, s[0]->InputCount());
746 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
747 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
748 EXPECT_TRUE(s[0]->InputAt(2)->IsImmediate());
749 }
750
751
TEST_F(InstructionSelectorTest,Int32SubConstantAsSub)752 TEST_F(InstructionSelectorTest, Int32SubConstantAsSub) {
753 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
754 Node* const p0 = m.Parameter(0);
755 Node* const c0 = m.Int32Constant(-1);
756 // If there is only a single use of on of the sub's non-constant input, use a
757 // "subl" instruction.
758 m.Return(m.Int32Sub(p0, c0));
759 Stream s = m.Build();
760 ASSERT_EQ(1U, s.size());
761 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
762 EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
763 ASSERT_EQ(2U, s[0]->InputCount());
764 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
765 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
766 }
767
768
TEST_F(InstructionSelectorTest,Int32SubConstantAsLea)769 TEST_F(InstructionSelectorTest, Int32SubConstantAsLea) {
770 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
771 Node* const p0 = m.Parameter(0);
772 Node* const c0 = m.Int32Constant(-1);
773 // If there are multiple uses of on of the sub's non-constant input, use a
774 // "leal" instruction.
775 Node* const v0 = m.Int32Sub(p0, c0);
776 m.Return(m.Int32Div(p0, v0));
777 Stream s = m.Build();
778 ASSERT_EQ(2U, s.size());
779 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
780 EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
781 ASSERT_EQ(2U, s[0]->InputCount());
782 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
783 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
784 }
785
786
TEST_F(InstructionSelectorTest,Int32AddScaled2Other)787 TEST_F(InstructionSelectorTest, Int32AddScaled2Other) {
788 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
789 MachineType::Int32(), MachineType::Int32());
790 Node* const p0 = m.Parameter(0);
791 Node* const p1 = m.Parameter(1);
792 Node* const p2 = m.Parameter(2);
793 Node* const s0 = m.Int32Mul(p1, m.Int32Constant(2));
794 Node* const a0 = m.Int32Add(s0, p2);
795 Node* const a1 = m.Int32Add(p0, a0);
796 m.Return(a1);
797 Stream s = m.Build();
798 ASSERT_EQ(2U, s.size());
799 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
800 EXPECT_EQ(kMode_MR2, s[0]->addressing_mode());
801 ASSERT_EQ(2U, s[0]->InputCount());
802 EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(0)));
803 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
804 EXPECT_EQ(s.ToVreg(a0), s.ToVreg(s[0]->OutputAt(0)));
805 ASSERT_EQ(2U, s[1]->InputCount());
806 EXPECT_EQ(kX64Lea32, s[1]->arch_opcode());
807 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[1]->InputAt(0)));
808 EXPECT_EQ(s.ToVreg(a0), s.ToVreg(s[1]->InputAt(1)));
809 EXPECT_EQ(s.ToVreg(a1), s.ToVreg(s[1]->OutputAt(0)));
810 }
811
812
813 // -----------------------------------------------------------------------------
814 // Multiplication.
815
816
TEST_F(InstructionSelectorTest,Int32MulWithInt32MulWithParameters)817 TEST_F(InstructionSelectorTest, Int32MulWithInt32MulWithParameters) {
818 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
819 MachineType::Int32());
820 Node* const p0 = m.Parameter(0);
821 Node* const p1 = m.Parameter(1);
822 Node* const m0 = m.Int32Mul(p0, p1);
823 m.Return(m.Int32Mul(m0, p0));
824 Stream s = m.Build();
825 ASSERT_EQ(2U, s.size());
826 EXPECT_EQ(kX64Imul32, s[0]->arch_opcode());
827 ASSERT_EQ(2U, s[0]->InputCount());
828 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(0)));
829 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1)));
830 ASSERT_EQ(1U, s[0]->OutputCount());
831 EXPECT_EQ(s.ToVreg(m0), s.ToVreg(s[0]->OutputAt(0)));
832 EXPECT_EQ(kX64Imul32, s[1]->arch_opcode());
833 ASSERT_EQ(2U, s[1]->InputCount());
834 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[1]->InputAt(0)));
835 EXPECT_EQ(s.ToVreg(m0), s.ToVreg(s[1]->InputAt(1)));
836 }
837
838
TEST_F(InstructionSelectorTest,Int32MulHigh)839 TEST_F(InstructionSelectorTest, Int32MulHigh) {
840 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
841 MachineType::Int32());
842 Node* const p0 = m.Parameter(0);
843 Node* const p1 = m.Parameter(1);
844 Node* const n = m.Int32MulHigh(p0, p1);
845 m.Return(n);
846 Stream s = m.Build();
847 ASSERT_EQ(1U, s.size());
848 EXPECT_EQ(kX64ImulHigh32, s[0]->arch_opcode());
849 ASSERT_EQ(2U, s[0]->InputCount());
850 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
851 EXPECT_TRUE(s.IsFixed(s[0]->InputAt(0), rax));
852 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
853 EXPECT_TRUE(!s.IsUsedAtStart(s[0]->InputAt(1)));
854 ASSERT_LE(1U, s[0]->OutputCount());
855 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
856 EXPECT_TRUE(s.IsFixed(s[0]->OutputAt(0), rdx));
857 }
858
859
TEST_F(InstructionSelectorTest,Uint32MulHigh)860 TEST_F(InstructionSelectorTest, Uint32MulHigh) {
861 StreamBuilder m(this, MachineType::Uint32(), MachineType::Uint32(),
862 MachineType::Uint32());
863 Node* const p0 = m.Parameter(0);
864 Node* const p1 = m.Parameter(1);
865 Node* const n = m.Uint32MulHigh(p0, p1);
866 m.Return(n);
867 Stream s = m.Build();
868 ASSERT_EQ(1U, s.size());
869 EXPECT_EQ(kX64UmulHigh32, s[0]->arch_opcode());
870 ASSERT_EQ(2U, s[0]->InputCount());
871 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
872 EXPECT_TRUE(s.IsFixed(s[0]->InputAt(0), rax));
873 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
874 EXPECT_TRUE(!s.IsUsedAtStart(s[0]->InputAt(1)));
875 ASSERT_LE(1U, s[0]->OutputCount());
876 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
877 EXPECT_TRUE(s.IsFixed(s[0]->OutputAt(0), rdx));
878 }
879
880
TEST_F(InstructionSelectorTest,Int32Mul2BecomesLea)881 TEST_F(InstructionSelectorTest, Int32Mul2BecomesLea) {
882 StreamBuilder m(this, MachineType::Uint32(), MachineType::Uint32(),
883 MachineType::Uint32());
884 Node* const p0 = m.Parameter(0);
885 Node* const c1 = m.Int32Constant(2);
886 Node* const n = m.Int32Mul(p0, c1);
887 m.Return(n);
888 Stream s = m.Build();
889 ASSERT_EQ(1U, s.size());
890 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
891 EXPECT_EQ(kMode_MR1, s[0]->addressing_mode());
892 ASSERT_EQ(2U, s[0]->InputCount());
893 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
894 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1)));
895 }
896
897
TEST_F(InstructionSelectorTest,Int32Mul3BecomesLea)898 TEST_F(InstructionSelectorTest, Int32Mul3BecomesLea) {
899 StreamBuilder m(this, MachineType::Uint32(), MachineType::Uint32(),
900 MachineType::Uint32());
901 Node* const p0 = m.Parameter(0);
902 Node* const c1 = m.Int32Constant(3);
903 Node* const n = m.Int32Mul(p0, c1);
904 m.Return(n);
905 Stream s = m.Build();
906 ASSERT_EQ(1U, s.size());
907 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
908 EXPECT_EQ(kMode_MR2, s[0]->addressing_mode());
909 ASSERT_EQ(2U, s[0]->InputCount());
910 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
911 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1)));
912 }
913
914
TEST_F(InstructionSelectorTest,Int32Mul4BecomesLea)915 TEST_F(InstructionSelectorTest, Int32Mul4BecomesLea) {
916 StreamBuilder m(this, MachineType::Uint32(), MachineType::Uint32(),
917 MachineType::Uint32());
918 Node* const p0 = m.Parameter(0);
919 Node* const c1 = m.Int32Constant(4);
920 Node* const n = m.Int32Mul(p0, c1);
921 m.Return(n);
922 Stream s = m.Build();
923 ASSERT_EQ(1U, s.size());
924 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
925 EXPECT_EQ(kMode_M4, s[0]->addressing_mode());
926 ASSERT_EQ(1U, s[0]->InputCount());
927 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
928 }
929
930
TEST_F(InstructionSelectorTest,Int32Mul5BecomesLea)931 TEST_F(InstructionSelectorTest, Int32Mul5BecomesLea) {
932 StreamBuilder m(this, MachineType::Uint32(), MachineType::Uint32(),
933 MachineType::Uint32());
934 Node* const p0 = m.Parameter(0);
935 Node* const c1 = m.Int32Constant(5);
936 Node* const n = m.Int32Mul(p0, c1);
937 m.Return(n);
938 Stream s = m.Build();
939 ASSERT_EQ(1U, s.size());
940 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
941 EXPECT_EQ(kMode_MR4, s[0]->addressing_mode());
942 ASSERT_EQ(2U, s[0]->InputCount());
943 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
944 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1)));
945 }
946
947
TEST_F(InstructionSelectorTest,Int32Mul8BecomesLea)948 TEST_F(InstructionSelectorTest, Int32Mul8BecomesLea) {
949 StreamBuilder m(this, MachineType::Uint32(), MachineType::Uint32(),
950 MachineType::Uint32());
951 Node* const p0 = m.Parameter(0);
952 Node* const c1 = m.Int32Constant(8);
953 Node* const n = m.Int32Mul(p0, c1);
954 m.Return(n);
955 Stream s = m.Build();
956 ASSERT_EQ(1U, s.size());
957 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
958 EXPECT_EQ(kMode_M8, s[0]->addressing_mode());
959 ASSERT_EQ(1U, s[0]->InputCount());
960 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
961 }
962
963
TEST_F(InstructionSelectorTest,Int32Mul9BecomesLea)964 TEST_F(InstructionSelectorTest, Int32Mul9BecomesLea) {
965 StreamBuilder m(this, MachineType::Uint32(), MachineType::Uint32(),
966 MachineType::Uint32());
967 Node* const p0 = m.Parameter(0);
968 Node* const c1 = m.Int32Constant(9);
969 Node* const n = m.Int32Mul(p0, c1);
970 m.Return(n);
971 Stream s = m.Build();
972 ASSERT_EQ(1U, s.size());
973 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
974 EXPECT_EQ(kMode_MR8, s[0]->addressing_mode());
975 ASSERT_EQ(2U, s[0]->InputCount());
976 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
977 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1)));
978 }
979
980
981 // -----------------------------------------------------------------------------
982 // Word32Shl.
983
984
TEST_F(InstructionSelectorTest,Int32Shl1BecomesLea)985 TEST_F(InstructionSelectorTest, Int32Shl1BecomesLea) {
986 StreamBuilder m(this, MachineType::Uint32(), MachineType::Uint32(),
987 MachineType::Uint32());
988 Node* const p0 = m.Parameter(0);
989 Node* const c1 = m.Int32Constant(1);
990 Node* const n = m.Word32Shl(p0, c1);
991 m.Return(n);
992 Stream s = m.Build();
993 ASSERT_EQ(1U, s.size());
994 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
995 EXPECT_EQ(kMode_MR1, s[0]->addressing_mode());
996 ASSERT_EQ(2U, s[0]->InputCount());
997 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
998 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1)));
999 }
1000
1001
TEST_F(InstructionSelectorTest,Int32Shl2BecomesLea)1002 TEST_F(InstructionSelectorTest, Int32Shl2BecomesLea) {
1003 StreamBuilder m(this, MachineType::Uint32(), MachineType::Uint32(),
1004 MachineType::Uint32());
1005 Node* const p0 = m.Parameter(0);
1006 Node* const c1 = m.Int32Constant(2);
1007 Node* const n = m.Word32Shl(p0, c1);
1008 m.Return(n);
1009 Stream s = m.Build();
1010 ASSERT_EQ(1U, s.size());
1011 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
1012 EXPECT_EQ(kMode_M4, s[0]->addressing_mode());
1013 ASSERT_EQ(1U, s[0]->InputCount());
1014 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1015 }
1016
1017
TEST_F(InstructionSelectorTest,Int32Shl4BecomesLea)1018 TEST_F(InstructionSelectorTest, Int32Shl4BecomesLea) {
1019 StreamBuilder m(this, MachineType::Uint32(), MachineType::Uint32(),
1020 MachineType::Uint32());
1021 Node* const p0 = m.Parameter(0);
1022 Node* const c1 = m.Int32Constant(3);
1023 Node* const n = m.Word32Shl(p0, c1);
1024 m.Return(n);
1025 Stream s = m.Build();
1026 ASSERT_EQ(1U, s.size());
1027 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
1028 EXPECT_EQ(kMode_M8, s[0]->addressing_mode());
1029 ASSERT_EQ(1U, s[0]->InputCount());
1030 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1031 }
1032
1033
1034 // -----------------------------------------------------------------------------
1035 // Floating point operations.
1036
1037
TEST_F(InstructionSelectorTest,Float32Abs)1038 TEST_F(InstructionSelectorTest, Float32Abs) {
1039 {
1040 StreamBuilder m(this, MachineType::Float32(), MachineType::Float32());
1041 Node* const p0 = m.Parameter(0);
1042 Node* const n = m.Float32Abs(p0);
1043 m.Return(n);
1044 Stream s = m.Build();
1045 ASSERT_EQ(1U, s.size());
1046 EXPECT_EQ(kSSEFloat32Abs, s[0]->arch_opcode());
1047 ASSERT_EQ(1U, s[0]->InputCount());
1048 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1049 ASSERT_EQ(1U, s[0]->OutputCount());
1050 EXPECT_TRUE(s.IsSameAsFirst(s[0]->Output()));
1051 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1052 EXPECT_EQ(kFlags_none, s[0]->flags_mode());
1053 }
1054 {
1055 StreamBuilder m(this, MachineType::Float32(), MachineType::Float32());
1056 Node* const p0 = m.Parameter(0);
1057 Node* const n = m.Float32Abs(p0);
1058 m.Return(n);
1059 Stream s = m.Build(AVX);
1060 ASSERT_EQ(1U, s.size());
1061 EXPECT_EQ(kAVXFloat32Abs, s[0]->arch_opcode());
1062 ASSERT_EQ(1U, s[0]->InputCount());
1063 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1064 ASSERT_EQ(1U, s[0]->OutputCount());
1065 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1066 EXPECT_EQ(kFlags_none, s[0]->flags_mode());
1067 }
1068 }
1069
1070
TEST_F(InstructionSelectorTest,Float64Abs)1071 TEST_F(InstructionSelectorTest, Float64Abs) {
1072 {
1073 StreamBuilder m(this, MachineType::Float64(), MachineType::Float64());
1074 Node* const p0 = m.Parameter(0);
1075 Node* const n = m.Float64Abs(p0);
1076 m.Return(n);
1077 Stream s = m.Build();
1078 ASSERT_EQ(1U, s.size());
1079 EXPECT_EQ(kSSEFloat64Abs, s[0]->arch_opcode());
1080 ASSERT_EQ(1U, s[0]->InputCount());
1081 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1082 ASSERT_EQ(1U, s[0]->OutputCount());
1083 EXPECT_TRUE(s.IsSameAsFirst(s[0]->Output()));
1084 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1085 EXPECT_EQ(kFlags_none, s[0]->flags_mode());
1086 }
1087 {
1088 StreamBuilder m(this, MachineType::Float64(), MachineType::Float64());
1089 Node* const p0 = m.Parameter(0);
1090 Node* const n = m.Float64Abs(p0);
1091 m.Return(n);
1092 Stream s = m.Build(AVX);
1093 ASSERT_EQ(1U, s.size());
1094 EXPECT_EQ(kAVXFloat64Abs, s[0]->arch_opcode());
1095 ASSERT_EQ(1U, s[0]->InputCount());
1096 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1097 ASSERT_EQ(1U, s[0]->OutputCount());
1098 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1099 EXPECT_EQ(kFlags_none, s[0]->flags_mode());
1100 }
1101 }
1102
1103
TEST_F(InstructionSelectorTest,Float64BinopArithmetic)1104 TEST_F(InstructionSelectorTest, Float64BinopArithmetic) {
1105 {
1106 StreamBuilder m(this, MachineType::Float64(), MachineType::Float64(),
1107 MachineType::Float64());
1108 Node* add = m.Float64Add(m.Parameter(0), m.Parameter(1));
1109 Node* mul = m.Float64Mul(add, m.Parameter(1));
1110 Node* sub = m.Float64Sub(mul, add);
1111 Node* ret = m.Float64Div(mul, sub);
1112 m.Return(ret);
1113 Stream s = m.Build(AVX);
1114 ASSERT_EQ(4U, s.size());
1115 EXPECT_EQ(kAVXFloat64Add, s[0]->arch_opcode());
1116 EXPECT_EQ(kAVXFloat64Mul, s[1]->arch_opcode());
1117 EXPECT_EQ(kAVXFloat64Sub, s[2]->arch_opcode());
1118 EXPECT_EQ(kAVXFloat64Div, s[3]->arch_opcode());
1119 }
1120 {
1121 StreamBuilder m(this, MachineType::Float64(), MachineType::Float64(),
1122 MachineType::Float64());
1123 Node* add = m.Float64Add(m.Parameter(0), m.Parameter(1));
1124 Node* mul = m.Float64Mul(add, m.Parameter(1));
1125 Node* sub = m.Float64Sub(mul, add);
1126 Node* ret = m.Float64Div(mul, sub);
1127 m.Return(ret);
1128 Stream s = m.Build();
1129 ASSERT_EQ(4U, s.size());
1130 EXPECT_EQ(kSSEFloat64Add, s[0]->arch_opcode());
1131 EXPECT_EQ(kSSEFloat64Mul, s[1]->arch_opcode());
1132 EXPECT_EQ(kSSEFloat64Sub, s[2]->arch_opcode());
1133 EXPECT_EQ(kSSEFloat64Div, s[3]->arch_opcode());
1134 }
1135 }
1136
1137
TEST_F(InstructionSelectorTest,Float32SubWithMinusZeroAndParameter)1138 TEST_F(InstructionSelectorTest, Float32SubWithMinusZeroAndParameter) {
1139 {
1140 StreamBuilder m(this, MachineType::Float32(), MachineType::Float32());
1141 Node* const p0 = m.Parameter(0);
1142 Node* const n = m.Float32Sub(m.Float32Constant(-0.0f), p0);
1143 m.Return(n);
1144 Stream s = m.Build();
1145 ASSERT_EQ(1U, s.size());
1146 EXPECT_EQ(kSSEFloat32Neg, s[0]->arch_opcode());
1147 ASSERT_EQ(1U, s[0]->InputCount());
1148 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1149 ASSERT_EQ(1U, s[0]->OutputCount());
1150 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1151 EXPECT_EQ(kFlags_none, s[0]->flags_mode());
1152 }
1153 {
1154 StreamBuilder m(this, MachineType::Float32(), MachineType::Float32());
1155 Node* const p0 = m.Parameter(0);
1156 Node* const n = m.Float32Sub(m.Float32Constant(-0.0f), p0);
1157 m.Return(n);
1158 Stream s = m.Build(AVX);
1159 ASSERT_EQ(1U, s.size());
1160 EXPECT_EQ(kAVXFloat32Neg, s[0]->arch_opcode());
1161 ASSERT_EQ(1U, s[0]->InputCount());
1162 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1163 ASSERT_EQ(1U, s[0]->OutputCount());
1164 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1165 EXPECT_EQ(kFlags_none, s[0]->flags_mode());
1166 }
1167 }
1168
1169
TEST_F(InstructionSelectorTest,Float64SubWithMinusZeroAndParameter)1170 TEST_F(InstructionSelectorTest, Float64SubWithMinusZeroAndParameter) {
1171 {
1172 StreamBuilder m(this, MachineType::Float64(), MachineType::Float64());
1173 Node* const p0 = m.Parameter(0);
1174 Node* const n = m.Float64Sub(m.Float64Constant(-0.0), p0);
1175 m.Return(n);
1176 Stream s = m.Build();
1177 ASSERT_EQ(1U, s.size());
1178 EXPECT_EQ(kSSEFloat64Neg, s[0]->arch_opcode());
1179 ASSERT_EQ(1U, s[0]->InputCount());
1180 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1181 ASSERT_EQ(1U, s[0]->OutputCount());
1182 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1183 EXPECT_EQ(kFlags_none, s[0]->flags_mode());
1184 }
1185 {
1186 StreamBuilder m(this, MachineType::Float64(), MachineType::Float64());
1187 Node* const p0 = m.Parameter(0);
1188 Node* const n = m.Float64Sub(m.Float64Constant(-0.0), p0);
1189 m.Return(n);
1190 Stream s = m.Build(AVX);
1191 ASSERT_EQ(1U, s.size());
1192 EXPECT_EQ(kAVXFloat64Neg, s[0]->arch_opcode());
1193 ASSERT_EQ(1U, s[0]->InputCount());
1194 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1195 ASSERT_EQ(1U, s[0]->OutputCount());
1196 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1197 EXPECT_EQ(kFlags_none, s[0]->flags_mode());
1198 }
1199 }
1200
1201
1202 // -----------------------------------------------------------------------------
1203 // Miscellaneous.
1204
1205
TEST_F(InstructionSelectorTest,Uint64LessThanWithLoadAndLoadStackPointer)1206 TEST_F(InstructionSelectorTest, Uint64LessThanWithLoadAndLoadStackPointer) {
1207 StreamBuilder m(this, MachineType::Bool());
1208 Node* const sl = m.Load(
1209 MachineType::Pointer(),
1210 m.ExternalConstant(ExternalReference::address_of_stack_limit(isolate())));
1211 Node* const sp = m.LoadStackPointer();
1212 Node* const n = m.Uint64LessThan(sl, sp);
1213 m.Return(n);
1214 Stream s = m.Build();
1215 ASSERT_EQ(1U, s.size());
1216 EXPECT_EQ(kX64StackCheck, s[0]->arch_opcode());
1217 ASSERT_EQ(0U, s[0]->InputCount());
1218 ASSERT_EQ(1U, s[0]->OutputCount());
1219 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1220 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
1221 EXPECT_EQ(kUnsignedGreaterThan, s[0]->flags_condition());
1222 }
1223
1224
TEST_F(InstructionSelectorTest,Word64ShlWithChangeInt32ToInt64)1225 TEST_F(InstructionSelectorTest, Word64ShlWithChangeInt32ToInt64) {
1226 TRACED_FORRANGE(int64_t, x, 32, 63) {
1227 StreamBuilder m(this, MachineType::Int64(), MachineType::Int32());
1228 Node* const p0 = m.Parameter(0);
1229 Node* const n = m.Word64Shl(m.ChangeInt32ToInt64(p0), m.Int64Constant(x));
1230 m.Return(n);
1231 Stream s = m.Build();
1232 ASSERT_EQ(1U, s.size());
1233 EXPECT_EQ(kX64Shl, s[0]->arch_opcode());
1234 ASSERT_EQ(2U, s[0]->InputCount());
1235 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1236 EXPECT_EQ(x, s.ToInt32(s[0]->InputAt(1)));
1237 ASSERT_EQ(1U, s[0]->OutputCount());
1238 EXPECT_TRUE(s.IsSameAsFirst(s[0]->Output()));
1239 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1240 }
1241 }
1242
1243
TEST_F(InstructionSelectorTest,Word64ShlWithChangeUint32ToUint64)1244 TEST_F(InstructionSelectorTest, Word64ShlWithChangeUint32ToUint64) {
1245 TRACED_FORRANGE(int64_t, x, 32, 63) {
1246 StreamBuilder m(this, MachineType::Int64(), MachineType::Uint32());
1247 Node* const p0 = m.Parameter(0);
1248 Node* const n = m.Word64Shl(m.ChangeUint32ToUint64(p0), m.Int64Constant(x));
1249 m.Return(n);
1250 Stream s = m.Build();
1251 ASSERT_EQ(1U, s.size());
1252 EXPECT_EQ(kX64Shl, s[0]->arch_opcode());
1253 ASSERT_EQ(2U, s[0]->InputCount());
1254 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1255 EXPECT_EQ(x, s.ToInt32(s[0]->InputAt(1)));
1256 ASSERT_EQ(1U, s[0]->OutputCount());
1257 EXPECT_TRUE(s.IsSameAsFirst(s[0]->Output()));
1258 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1259 }
1260 }
1261
1262
TEST_F(InstructionSelectorTest,Word32AndWith0xff)1263 TEST_F(InstructionSelectorTest, Word32AndWith0xff) {
1264 {
1265 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
1266 Node* const p0 = m.Parameter(0);
1267 Node* const n = m.Word32And(p0, m.Int32Constant(0xff));
1268 m.Return(n);
1269 Stream s = m.Build();
1270 ASSERT_EQ(1U, s.size());
1271 EXPECT_EQ(kX64Movzxbl, s[0]->arch_opcode());
1272 ASSERT_EQ(1U, s[0]->InputCount());
1273 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1274 ASSERT_EQ(1U, s[0]->OutputCount());
1275 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1276 }
1277 {
1278 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
1279 Node* const p0 = m.Parameter(0);
1280 Node* const n = m.Word32And(m.Int32Constant(0xff), p0);
1281 m.Return(n);
1282 Stream s = m.Build();
1283 ASSERT_EQ(1U, s.size());
1284 EXPECT_EQ(kX64Movzxbl, s[0]->arch_opcode());
1285 ASSERT_EQ(1U, s[0]->InputCount());
1286 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1287 ASSERT_EQ(1U, s[0]->OutputCount());
1288 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1289 }
1290 }
1291
1292
TEST_F(InstructionSelectorTest,Word32AndWith0xffff)1293 TEST_F(InstructionSelectorTest, Word32AndWith0xffff) {
1294 {
1295 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
1296 Node* const p0 = m.Parameter(0);
1297 Node* const n = m.Word32And(p0, m.Int32Constant(0xffff));
1298 m.Return(n);
1299 Stream s = m.Build();
1300 ASSERT_EQ(1U, s.size());
1301 EXPECT_EQ(kX64Movzxwl, s[0]->arch_opcode());
1302 ASSERT_EQ(1U, s[0]->InputCount());
1303 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1304 ASSERT_EQ(1U, s[0]->OutputCount());
1305 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1306 }
1307 {
1308 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
1309 Node* const p0 = m.Parameter(0);
1310 Node* const n = m.Word32And(m.Int32Constant(0xffff), p0);
1311 m.Return(n);
1312 Stream s = m.Build();
1313 ASSERT_EQ(1U, s.size());
1314 EXPECT_EQ(kX64Movzxwl, s[0]->arch_opcode());
1315 ASSERT_EQ(1U, s[0]->InputCount());
1316 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1317 ASSERT_EQ(1U, s[0]->OutputCount());
1318 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1319 }
1320 }
1321
1322
TEST_F(InstructionSelectorTest,Word32Clz)1323 TEST_F(InstructionSelectorTest, Word32Clz) {
1324 StreamBuilder m(this, MachineType::Uint32(), MachineType::Uint32());
1325 Node* const p0 = m.Parameter(0);
1326 Node* const n = m.Word32Clz(p0);
1327 m.Return(n);
1328 Stream s = m.Build();
1329 ASSERT_EQ(1U, s.size());
1330 EXPECT_EQ(kX64Lzcnt32, s[0]->arch_opcode());
1331 ASSERT_EQ(1U, s[0]->InputCount());
1332 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1333 ASSERT_EQ(1U, s[0]->OutputCount());
1334 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1335 }
1336
1337 } // namespace compiler
1338 } // namespace internal
1339 } // namespace v8
1340