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 <limits>
6 
7 #include "src/common/globals.h"
8 #include "src/compiler/machine-operator.h"
9 #include "src/compiler/node-matchers.h"
10 #include "src/objects/objects-inl.h"
11 #include "test/unittests/compiler/backend/instruction-selector-unittest.h"
12 
13 #if V8_ENABLE_WEBASSEMBLY
14 #include "src/wasm/simd-shuffle.h"
15 #endif  // V8_ENABLE_WEBASSEMBLY
16 
17 namespace v8 {
18 namespace internal {
19 namespace compiler {
20 
21 // -----------------------------------------------------------------------------
22 // Conversions.
23 
24 
TEST_F(InstructionSelectorTest,ChangeFloat32ToFloat64WithParameter)25 TEST_F(InstructionSelectorTest, ChangeFloat32ToFloat64WithParameter) {
26   StreamBuilder m(this, MachineType::Float32(), MachineType::Float64());
27   m.Return(m.ChangeFloat32ToFloat64(m.Parameter(0)));
28   Stream s = m.Build();
29   ASSERT_EQ(1U, s.size());
30   EXPECT_EQ(kSSEFloat32ToFloat64, s[0]->arch_opcode());
31   EXPECT_EQ(1U, s[0]->InputCount());
32   EXPECT_EQ(1U, s[0]->OutputCount());
33 }
34 
35 
TEST_F(InstructionSelectorTest,ChangeInt32ToInt64WithParameter)36 TEST_F(InstructionSelectorTest, ChangeInt32ToInt64WithParameter) {
37   StreamBuilder m(this, MachineType::Int64(), MachineType::Int32());
38   m.Return(m.ChangeInt32ToInt64(m.Parameter(0)));
39   Stream s = m.Build();
40   ASSERT_EQ(1U, s.size());
41   EXPECT_EQ(kX64Movsxlq, s[0]->arch_opcode());
42 }
43 
TEST_F(InstructionSelectorTest,ChangeUint32ToFloat64WithParameter)44 TEST_F(InstructionSelectorTest, ChangeUint32ToFloat64WithParameter) {
45   StreamBuilder m(this, MachineType::Float64(), MachineType::Uint32());
46   m.Return(m.ChangeUint32ToFloat64(m.Parameter(0)));
47   Stream s = m.Build();
48   ASSERT_EQ(1U, s.size());
49   EXPECT_EQ(kSSEUint32ToFloat64, s[0]->arch_opcode());
50 }
51 
52 
TEST_F(InstructionSelectorTest,ChangeUint32ToUint64WithParameter)53 TEST_F(InstructionSelectorTest, ChangeUint32ToUint64WithParameter) {
54   StreamBuilder m(this, MachineType::Uint64(), MachineType::Uint32());
55   m.Return(m.ChangeUint32ToUint64(m.Parameter(0)));
56   Stream s = m.Build();
57   ASSERT_EQ(1U, s.size());
58   EXPECT_EQ(kX64Movl, s[0]->arch_opcode());
59 }
60 
61 
TEST_F(InstructionSelectorTest,TruncateFloat64ToFloat32WithParameter)62 TEST_F(InstructionSelectorTest, TruncateFloat64ToFloat32WithParameter) {
63   StreamBuilder m(this, MachineType::Float64(), MachineType::Float32());
64   m.Return(m.TruncateFloat64ToFloat32(m.Parameter(0)));
65   Stream s = m.Build();
66   ASSERT_EQ(1U, s.size());
67   EXPECT_EQ(kSSEFloat64ToFloat32, s[0]->arch_opcode());
68   EXPECT_EQ(1U, s[0]->InputCount());
69   EXPECT_EQ(1U, s[0]->OutputCount());
70 }
71 
72 
TEST_F(InstructionSelectorTest,TruncateInt64ToInt32WithParameter)73 TEST_F(InstructionSelectorTest, TruncateInt64ToInt32WithParameter) {
74   StreamBuilder m(this, MachineType::Int32(), MachineType::Int64());
75   m.Return(m.TruncateInt64ToInt32(m.Parameter(0)));
76   Stream s = m.Build();
77   ASSERT_EQ(1U, s.size());
78   EXPECT_EQ(kX64Movl, s[0]->arch_opcode());
79 }
80 
TEST_F(InstructionSelectorTest,SelectWord32)81 TEST_F(InstructionSelectorTest, SelectWord32) {
82   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
83                   MachineType::Int32());
84   Node* cond = m.Int32Constant(1);
85   m.Return(m.Word32Select(cond, m.Parameter(0), m.Parameter(1)));
86   Stream s = m.Build();
87   EXPECT_EQ(kX64Cmp32, s[0]->arch_opcode());
88   EXPECT_EQ(4U, s[0]->InputCount());
89   EXPECT_EQ(1U, s[0]->OutputCount());
90   EXPECT_EQ(kFlags_select, s[0]->flags_mode());
91   EXPECT_EQ(kNotEqual, s[0]->flags_condition());
92   EXPECT_TRUE(s.IsSameAsInput(s[0]->Output(), 2));
93 }
94 
TEST_F(InstructionSelectorTest,SelectWord64)95 TEST_F(InstructionSelectorTest, SelectWord64) {
96   StreamBuilder m(this, MachineType::Int64(), MachineType::Int64(),
97                   MachineType::Int64());
98   Node* cond = m.Int32Constant(1);
99   m.Return(m.Word64Select(cond, m.Parameter(0), m.Parameter(1)));
100   Stream s = m.Build();
101   EXPECT_EQ(kX64Cmp32, s[0]->arch_opcode());
102   EXPECT_EQ(4U, s[0]->InputCount());
103   EXPECT_EQ(1U, s[0]->OutputCount());
104   EXPECT_EQ(kFlags_select, s[0]->flags_mode());
105   EXPECT_EQ(kNotEqual, s[0]->flags_condition());
106   EXPECT_TRUE(s.IsSameAsInput(s[0]->Output(), 2));
107 }
108 
109 namespace {
110 struct LoadWithToInt64Extension {
111   MachineType type;
112   ArchOpcode expected_opcode;
113 };
114 
operator <<(std::ostream & os,const LoadWithToInt64Extension & i32toi64)115 std::ostream& operator<<(std::ostream& os,
116                          const LoadWithToInt64Extension& i32toi64) {
117   return os << i32toi64.type;
118 }
119 
120 static const LoadWithToInt64Extension kLoadWithToInt64Extensions[] = {
121     {MachineType::Int8(), kX64Movsxbq},
122     {MachineType::Uint8(), kX64Movzxbq},
123     {MachineType::Int16(), kX64Movsxwq},
124     {MachineType::Uint16(), kX64Movzxwq},
125     {MachineType::Int32(), kX64Movsxlq}};
126 
127 // The parameterized test that use the following type are intentionally part
128 // of the anonymous namespace. The issue here is that the type parameter is
129 // using a type that is in the anonymous namespace, but the class generated by
130 // TEST_P is not. This will cause GCC to generate a -Wsubobject-linkage warning.
131 //
132 // In this case there will only be single translation unit and the warning
133 // about subobject-linkage can be avoided by placing the class generated
134 // by TEST_P in the anoynmous namespace as well.
135 using InstructionSelectorChangeInt32ToInt64Test =
136     InstructionSelectorTestWithParam<LoadWithToInt64Extension>;
137 
TEST_P(InstructionSelectorChangeInt32ToInt64Test,ChangeInt32ToInt64WithLoad)138 TEST_P(InstructionSelectorChangeInt32ToInt64Test, ChangeInt32ToInt64WithLoad) {
139   const LoadWithToInt64Extension extension = GetParam();
140   StreamBuilder m(this, MachineType::Int64(), MachineType::Pointer());
141   m.Return(m.ChangeInt32ToInt64(m.Load(extension.type, m.Parameter(0))));
142   Stream s = m.Build();
143   ASSERT_EQ(1U, s.size());
144   EXPECT_EQ(extension.expected_opcode, s[0]->arch_opcode());
145 }
146 
147 }  // namespace
148 
149 INSTANTIATE_TEST_SUITE_P(InstructionSelectorTest,
150                          InstructionSelectorChangeInt32ToInt64Test,
151                          ::testing::ValuesIn(kLoadWithToInt64Extensions));
152 
153 // -----------------------------------------------------------------------------
154 // Loads and stores
155 
156 
157 namespace {
158 
159 struct MemoryAccess {
160   MachineType type;
161   ArchOpcode load_opcode;
162   ArchOpcode store_opcode;
163 };
164 
165 
operator <<(std::ostream & os,const MemoryAccess & memacc)166 std::ostream& operator<<(std::ostream& os, const MemoryAccess& memacc) {
167   return os << memacc.type;
168 }
169 
170 
171 static const MemoryAccess kMemoryAccesses[] = {
172     {MachineType::Int8(), kX64Movsxbl, kX64Movb},
173     {MachineType::Uint8(), kX64Movzxbl, kX64Movb},
174     {MachineType::Int16(), kX64Movsxwl, kX64Movw},
175     {MachineType::Uint16(), kX64Movzxwl, kX64Movw},
176     {MachineType::Int32(), kX64Movl, kX64Movl},
177     {MachineType::Uint32(), kX64Movl, kX64Movl},
178     {MachineType::Int64(), kX64Movq, kX64Movq},
179     {MachineType::Uint64(), kX64Movq, kX64Movq},
180     {MachineType::Float32(), kX64Movss, kX64Movss},
181     {MachineType::Float64(), kX64Movsd, kX64Movsd}};
182 
183 // The parameterized test that use the following type are intentionally part
184 // of the anonymous namespace. The issue here is that the type parameter is
185 // using a type that is in the anonymous namespace, but the class generated by
186 // TEST_P is not. This will cause GCC to generate a -Wsubobject-linkage warning.
187 //
188 // In this case there will only be single translation unit and the warning
189 // about subobject-linkage can be avoided by placing the class generated
190 // by TEST_P in the anoynmous namespace as well.
191 using InstructionSelectorMemoryAccessTest =
192     InstructionSelectorTestWithParam<MemoryAccess>;
193 
TEST_P(InstructionSelectorMemoryAccessTest,LoadWithParameters)194 TEST_P(InstructionSelectorMemoryAccessTest, LoadWithParameters) {
195   const MemoryAccess memacc = GetParam();
196   StreamBuilder m(this, memacc.type, MachineType::Pointer(),
197                   MachineType::Int32());
198   m.Return(m.Load(memacc.type, m.Parameter(0), m.Parameter(1)));
199   Stream s = m.Build();
200   ASSERT_EQ(1U, s.size());
201   EXPECT_EQ(memacc.load_opcode, s[0]->arch_opcode());
202   EXPECT_EQ(2U, s[0]->InputCount());
203   EXPECT_EQ(1U, s[0]->OutputCount());
204 }
205 
206 
TEST_P(InstructionSelectorMemoryAccessTest,StoreWithParameters)207 TEST_P(InstructionSelectorMemoryAccessTest, StoreWithParameters) {
208   const MemoryAccess memacc = GetParam();
209   StreamBuilder m(this, MachineType::Int32(), MachineType::Pointer(),
210                   MachineType::Int32(), memacc.type);
211   m.Store(memacc.type.representation(), m.Parameter(0), m.Parameter(1),
212           m.Parameter(2), kNoWriteBarrier);
213   m.Return(m.Int32Constant(0));
214   Stream s = m.Build();
215   ASSERT_EQ(1U, s.size());
216   EXPECT_EQ(memacc.store_opcode, s[0]->arch_opcode());
217   EXPECT_EQ(3U, s[0]->InputCount());
218   EXPECT_EQ(0U, s[0]->OutputCount());
219 }
220 
221 }  // namespace
222 
223 INSTANTIATE_TEST_SUITE_P(InstructionSelectorTest,
224                          InstructionSelectorMemoryAccessTest,
225                          ::testing::ValuesIn(kMemoryAccesses));
226 
227 // -----------------------------------------------------------------------------
228 // ChangeUint32ToUint64.
229 
230 
231 namespace {
232 
233 using Constructor = Node* (RawMachineAssembler::*)(Node*, Node*);
234 
235 struct BinaryOperation {
236   Constructor constructor;
237   const char* constructor_name;
238 };
239 
240 
operator <<(std::ostream & os,const BinaryOperation & bop)241 std::ostream& operator<<(std::ostream& os, const BinaryOperation& bop) {
242   return os << bop.constructor_name;
243 }
244 
245 
246 const BinaryOperation kWord32BinaryOperations[] = {
247     {&RawMachineAssembler::Word32And, "Word32And"},
248     {&RawMachineAssembler::Word32Or, "Word32Or"},
249     {&RawMachineAssembler::Word32Xor, "Word32Xor"},
250     {&RawMachineAssembler::Word32Shl, "Word32Shl"},
251     {&RawMachineAssembler::Word32Shr, "Word32Shr"},
252     {&RawMachineAssembler::Word32Sar, "Word32Sar"},
253     {&RawMachineAssembler::Word32Ror, "Word32Ror"},
254     {&RawMachineAssembler::Word32Equal, "Word32Equal"},
255     {&RawMachineAssembler::Int32Add, "Int32Add"},
256     {&RawMachineAssembler::Int32Sub, "Int32Sub"},
257     {&RawMachineAssembler::Int32Mul, "Int32Mul"},
258     {&RawMachineAssembler::Int32MulHigh, "Int32MulHigh"},
259     {&RawMachineAssembler::Int32Div, "Int32Div"},
260     {&RawMachineAssembler::Int32LessThan, "Int32LessThan"},
261     {&RawMachineAssembler::Int32LessThanOrEqual, "Int32LessThanOrEqual"},
262     {&RawMachineAssembler::Int32Mod, "Int32Mod"},
263     {&RawMachineAssembler::Uint32Div, "Uint32Div"},
264     {&RawMachineAssembler::Uint32LessThan, "Uint32LessThan"},
265     {&RawMachineAssembler::Uint32LessThanOrEqual, "Uint32LessThanOrEqual"},
266     {&RawMachineAssembler::Uint32Mod, "Uint32Mod"}};
267 
268 // The parameterized test that use the following type are intentionally part
269 // of the anonymous namespace. The issue here is that the type parameter is
270 // using a type that is in the anonymous namespace, but the class generated by
271 // TEST_P is not. This will cause GCC to generate a -Wsubobject-linkage warning.
272 //
273 // In this case there will only be single translation unit and the warning
274 // about subobject-linkage can be avoided by placing the class generated
275 // by TEST_P in the anoynmous namespace as well.
276 using InstructionSelectorChangeUint32ToUint64Test =
277     InstructionSelectorTestWithParam<BinaryOperation>;
278 
TEST_P(InstructionSelectorChangeUint32ToUint64Test,ChangeUint32ToUint64)279 TEST_P(InstructionSelectorChangeUint32ToUint64Test, ChangeUint32ToUint64) {
280   const BinaryOperation& bop = GetParam();
281   StreamBuilder m(this, MachineType::Uint64(), MachineType::Int32(),
282                   MachineType::Int32());
283   Node* const p0 = m.Parameter(0);
284   Node* const p1 = m.Parameter(1);
285   m.Return(m.ChangeUint32ToUint64((m.*bop.constructor)(p0, p1)));
286   Stream s = m.Build();
287   ASSERT_EQ(1U, s.size());
288 }
289 
290 }  // namespace
291 
292 INSTANTIATE_TEST_SUITE_P(InstructionSelectorTest,
293                          InstructionSelectorChangeUint32ToUint64Test,
294                          ::testing::ValuesIn(kWord32BinaryOperations));
295 
296 // -----------------------------------------------------------------------------
297 // CanElideChangeUint32ToUint64
298 
299 namespace {
300 
301 template <typename T>
302 struct MachInst {
303   T constructor;
304   const char* constructor_name;
305   ArchOpcode arch_opcode;
306   MachineType machine_type;
307 };
308 
309 using MachInst2 = MachInst<Node* (RawMachineAssembler::*)(Node*, Node*)>;
310 
311 // X64 instructions that clear the top 32 bits of the destination.
312 const MachInst2 kCanElideChangeUint32ToUint64[] = {
313     {&RawMachineAssembler::Word32And, "Word32And", kX64And32,
314      MachineType::Uint32()},
315     {&RawMachineAssembler::Word32Or, "Word32Or", kX64Or32,
316      MachineType::Uint32()},
317     {&RawMachineAssembler::Word32Xor, "Word32Xor", kX64Xor32,
318      MachineType::Uint32()},
319     {&RawMachineAssembler::Word32Shl, "Word32Shl", kX64Shl32,
320      MachineType::Uint32()},
321     {&RawMachineAssembler::Word32Shr, "Word32Shr", kX64Shr32,
322      MachineType::Uint32()},
323     {&RawMachineAssembler::Word32Sar, "Word32Sar", kX64Sar32,
324      MachineType::Uint32()},
325     {&RawMachineAssembler::Word32Ror, "Word32Ror", kX64Ror32,
326      MachineType::Uint32()},
327     {&RawMachineAssembler::Word32Equal, "Word32Equal", kX64Cmp32,
328      MachineType::Uint32()},
329     {&RawMachineAssembler::Int32Add, "Int32Add", kX64Lea32,
330      MachineType::Int32()},
331     {&RawMachineAssembler::Int32Sub, "Int32Sub", kX64Sub32,
332      MachineType::Int32()},
333     {&RawMachineAssembler::Int32Mul, "Int32Mul", kX64Imul32,
334      MachineType::Int32()},
335     {&RawMachineAssembler::Int32MulHigh, "Int32MulHigh", kX64ImulHigh32,
336      MachineType::Int32()},
337     {&RawMachineAssembler::Int32Div, "Int32Div", kX64Idiv32,
338      MachineType::Int32()},
339     {&RawMachineAssembler::Int32LessThan, "Int32LessThan", kX64Cmp32,
340      MachineType::Int32()},
341     {&RawMachineAssembler::Int32LessThanOrEqual, "Int32LessThanOrEqual",
342      kX64Cmp32, MachineType::Int32()},
343     {&RawMachineAssembler::Int32Mod, "Int32Mod", kX64Idiv32,
344      MachineType::Int32()},
345     {&RawMachineAssembler::Uint32Div, "Uint32Div", kX64Udiv32,
346      MachineType::Uint32()},
347     {&RawMachineAssembler::Uint32LessThan, "Uint32LessThan", kX64Cmp32,
348      MachineType::Uint32()},
349     {&RawMachineAssembler::Uint32LessThanOrEqual, "Uint32LessThanOrEqual",
350      kX64Cmp32, MachineType::Uint32()},
351     {&RawMachineAssembler::Uint32Mod, "Uint32Mod", kX64Udiv32,
352      MachineType::Uint32()},
353 };
354 
355 // The parameterized test that use the following type are intentionally part
356 // of the anonymous namespace. The issue here is that the type parameter is
357 // using a type that is in the anonymous namespace, but the class generated by
358 // TEST_P is not. This will cause GCC to generate a -Wsubobject-linkage warning.
359 //
360 // In this case there will only be single translation unit and the warning
361 // about subobject-linkage can be avoided by placing the class generated
362 // by TEST_P in the anoynmous namespace as well.
363 using InstructionSelectorElidedChangeUint32ToUint64Test =
364     InstructionSelectorTestWithParam<MachInst2>;
365 
TEST_P(InstructionSelectorElidedChangeUint32ToUint64Test,Parameter)366 TEST_P(InstructionSelectorElidedChangeUint32ToUint64Test, Parameter) {
367   const MachInst2 binop = GetParam();
368   StreamBuilder m(this, MachineType::Uint64(), binop.machine_type,
369                   binop.machine_type);
370   m.Return(m.ChangeUint32ToUint64(
371       (m.*binop.constructor)(m.Parameter(0), m.Parameter(1))));
372   Stream s = m.Build();
373   // Make sure the `ChangeUint32ToUint64` node turned into a no-op.
374   ASSERT_EQ(1U, s.size());
375   EXPECT_EQ(binop.arch_opcode, s[0]->arch_opcode());
376   EXPECT_EQ(2U, s[0]->InputCount());
377   EXPECT_EQ(1U, s[0]->OutputCount());
378 }
379 
380 }  // namespace
381 
382 INSTANTIATE_TEST_SUITE_P(InstructionSelectorTest,
383                          InstructionSelectorElidedChangeUint32ToUint64Test,
384                          ::testing::ValuesIn(kCanElideChangeUint32ToUint64));
385 
386 // ChangeUint32ToUint64AfterLoad
TEST_F(InstructionSelectorTest,ChangeUint32ToUint64AfterLoad)387 TEST_F(InstructionSelectorTest, ChangeUint32ToUint64AfterLoad) {
388   // For each case, make sure the `ChangeUint32ToUint64` node turned into a
389   // no-op.
390 
391   // movzxbl
392   {
393     StreamBuilder m(this, MachineType::Uint64(), MachineType::Pointer(),
394                     MachineType::Int32());
395     m.Return(m.ChangeUint32ToUint64(
396         m.Load(MachineType::Uint8(), m.Parameter(0), m.Parameter(1))));
397     Stream s = m.Build();
398     ASSERT_EQ(1U, s.size());
399     EXPECT_EQ(kX64Movzxbl, s[0]->arch_opcode());
400     EXPECT_EQ(kMode_MR1, s[0]->addressing_mode());
401     EXPECT_EQ(2U, s[0]->InputCount());
402     EXPECT_EQ(1U, s[0]->OutputCount());
403   }
404   // movsxbl
405   {
406     StreamBuilder m(this, MachineType::Uint64(), MachineType::Pointer(),
407                     MachineType::Int32());
408     m.Return(m.ChangeUint32ToUint64(
409         m.Load(MachineType::Int8(), m.Parameter(0), m.Parameter(1))));
410     Stream s = m.Build();
411     ASSERT_EQ(1U, s.size());
412     EXPECT_EQ(kX64Movsxbl, s[0]->arch_opcode());
413     EXPECT_EQ(kMode_MR1, s[0]->addressing_mode());
414     EXPECT_EQ(2U, s[0]->InputCount());
415     EXPECT_EQ(1U, s[0]->OutputCount());
416   }
417   // movzxwl
418   {
419     StreamBuilder m(this, MachineType::Uint64(), MachineType::Pointer(),
420                     MachineType::Int32());
421     m.Return(m.ChangeUint32ToUint64(
422         m.Load(MachineType::Uint16(), m.Parameter(0), m.Parameter(1))));
423     Stream s = m.Build();
424     ASSERT_EQ(1U, s.size());
425     EXPECT_EQ(kX64Movzxwl, s[0]->arch_opcode());
426     EXPECT_EQ(kMode_MR1, s[0]->addressing_mode());
427     EXPECT_EQ(2U, s[0]->InputCount());
428     EXPECT_EQ(1U, s[0]->OutputCount());
429   }
430   // movsxwl
431   {
432     StreamBuilder m(this, MachineType::Uint64(), MachineType::Pointer(),
433                     MachineType::Int32());
434     m.Return(m.ChangeUint32ToUint64(
435         m.Load(MachineType::Int16(), m.Parameter(0), m.Parameter(1))));
436     Stream s = m.Build();
437     ASSERT_EQ(1U, s.size());
438     EXPECT_EQ(kX64Movsxwl, s[0]->arch_opcode());
439     EXPECT_EQ(kMode_MR1, s[0]->addressing_mode());
440     EXPECT_EQ(2U, s[0]->InputCount());
441     EXPECT_EQ(1U, s[0]->OutputCount());
442   }
443 }
444 
445 // -----------------------------------------------------------------------------
446 // TruncateInt64ToInt32.
447 
448 
TEST_F(InstructionSelectorTest,TruncateInt64ToInt32WithWord64Sar)449 TEST_F(InstructionSelectorTest, TruncateInt64ToInt32WithWord64Sar) {
450   StreamBuilder m(this, MachineType::Int32(), MachineType::Int64());
451   Node* const p = m.Parameter(0);
452   Node* const t = m.TruncateInt64ToInt32(m.Word64Sar(p, m.Int64Constant(32)));
453   m.Return(t);
454   Stream s = m.Build();
455   ASSERT_EQ(1U, s.size());
456   EXPECT_EQ(kX64Shr, s[0]->arch_opcode());
457   ASSERT_EQ(2U, s[0]->InputCount());
458   EXPECT_EQ(s.ToVreg(p), s.ToVreg(s[0]->InputAt(0)));
459   EXPECT_EQ(32, s.ToInt32(s[0]->InputAt(1)));
460   ASSERT_EQ(1U, s[0]->OutputCount());
461   EXPECT_TRUE(s.IsSameAsFirst(s[0]->OutputAt(0)));
462   EXPECT_EQ(s.ToVreg(t), s.ToVreg(s[0]->OutputAt(0)));
463 }
464 
465 
TEST_F(InstructionSelectorTest,TruncateInt64ToInt32WithWord64Shr)466 TEST_F(InstructionSelectorTest, TruncateInt64ToInt32WithWord64Shr) {
467   StreamBuilder m(this, MachineType::Int32(), MachineType::Int64());
468   Node* const p = m.Parameter(0);
469   Node* const t = m.TruncateInt64ToInt32(m.Word64Shr(p, m.Int64Constant(32)));
470   m.Return(t);
471   Stream s = m.Build();
472   ASSERT_EQ(1U, s.size());
473   EXPECT_EQ(kX64Shr, s[0]->arch_opcode());
474   ASSERT_EQ(2U, s[0]->InputCount());
475   EXPECT_EQ(s.ToVreg(p), s.ToVreg(s[0]->InputAt(0)));
476   EXPECT_EQ(32, s.ToInt32(s[0]->InputAt(1)));
477   ASSERT_EQ(1U, s[0]->OutputCount());
478   EXPECT_TRUE(s.IsSameAsFirst(s[0]->OutputAt(0)));
479   EXPECT_EQ(s.ToVreg(t), s.ToVreg(s[0]->OutputAt(0)));
480 }
481 
482 
483 // -----------------------------------------------------------------------------
484 // Addition.
485 
486 
TEST_F(InstructionSelectorTest,Int32AddWithInt32ParametersLea)487 TEST_F(InstructionSelectorTest, Int32AddWithInt32ParametersLea) {
488   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
489                   MachineType::Int32());
490   Node* const p0 = m.Parameter(0);
491   Node* const p1 = m.Parameter(1);
492   Node* const a0 = m.Int32Add(p0, p1);
493   // Additional uses of input to add chooses lea
494   Node* const a1 = m.Int32Div(p0, p1);
495   m.Return(m.Int32Div(a0, a1));
496   Stream s = m.Build();
497   ASSERT_EQ(3U, s.size());
498   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
499   ASSERT_EQ(2U, s[0]->InputCount());
500   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
501   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
502 }
503 
504 
TEST_F(InstructionSelectorTest,Int32AddConstantAsLeaSingle)505 TEST_F(InstructionSelectorTest, Int32AddConstantAsLeaSingle) {
506   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
507   Node* const p0 = m.Parameter(0);
508   Node* const c0 = m.Int32Constant(15);
509   // If one of the add's operands is only used once, use an "leal", even though
510   // an "addl" could be used. The "leal" has proven faster--out best guess is
511   // that it gives the register allocation more freedom and it doesn't set
512   // flags, reducing pressure in the CPU's pipeline. If we're lucky with
513   // register allocation, then code generation will select an "addl" later for
514   // the cases that have been measured to be faster.
515   Node* const v0 = m.Int32Add(p0, c0);
516   m.Return(v0);
517   Stream s = m.Build();
518   ASSERT_EQ(1U, s.size());
519   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
520   EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
521   ASSERT_EQ(2U, s[0]->InputCount());
522   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
523   EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
524 }
525 
526 
TEST_F(InstructionSelectorTest,Int32AddConstantAsAdd)527 TEST_F(InstructionSelectorTest, Int32AddConstantAsAdd) {
528   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
529   Node* const p0 = m.Parameter(0);
530   Node* const c0 = m.Int32Constant(1);
531   // If there is only a single use of an add's input and the immediate constant
532   // for the add is 1, don't use an inc. It is much slower on modern Intel
533   // architectures.
534   m.Return(m.Int32Add(p0, c0));
535   Stream s = m.Build();
536   ASSERT_EQ(1U, s.size());
537   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
538   EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
539   ASSERT_EQ(2U, s[0]->InputCount());
540   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
541   EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
542 }
543 
544 
TEST_F(InstructionSelectorTest,Int32AddConstantAsLeaDouble)545 TEST_F(InstructionSelectorTest, Int32AddConstantAsLeaDouble) {
546   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
547   Node* const p0 = m.Parameter(0);
548   Node* const c0 = m.Int32Constant(15);
549   // A second use of an add's input uses lea
550   Node* const a0 = m.Int32Add(p0, c0);
551   m.Return(m.Int32Div(a0, p0));
552   Stream s = m.Build();
553   ASSERT_EQ(2U, s.size());
554   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
555   EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
556   ASSERT_EQ(2U, s[0]->InputCount());
557   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
558   EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
559 }
560 
561 
TEST_F(InstructionSelectorTest,Int32AddCommutedConstantAsLeaSingle)562 TEST_F(InstructionSelectorTest, Int32AddCommutedConstantAsLeaSingle) {
563   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
564   Node* const p0 = m.Parameter(0);
565   Node* const c0 = m.Int32Constant(15);
566   // If one of the add's operands is only used once, use an "leal", even though
567   // an "addl" could be used. The "leal" has proven faster--out best guess is
568   // that it gives the register allocation more freedom and it doesn't set
569   // flags, reducing pressure in the CPU's pipeline. If we're lucky with
570   // register allocation, then code generation will select an "addl" later for
571   // the cases that have been measured to be faster.
572   m.Return(m.Int32Add(c0, p0));
573   Stream s = m.Build();
574   ASSERT_EQ(1U, s.size());
575   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
576   EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
577   ASSERT_EQ(2U, s[0]->InputCount());
578   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
579   EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
580 }
581 
582 
TEST_F(InstructionSelectorTest,Int32AddCommutedConstantAsLeaDouble)583 TEST_F(InstructionSelectorTest, Int32AddCommutedConstantAsLeaDouble) {
584   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
585   Node* const p0 = m.Parameter(0);
586   Node* const c0 = m.Int32Constant(15);
587   // A second use of an add's input uses lea
588   Node* const a0 = m.Int32Add(c0, p0);
589   USE(a0);
590   m.Return(m.Int32Div(a0, p0));
591   Stream s = m.Build();
592   ASSERT_EQ(2U, s.size());
593   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
594   EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
595   ASSERT_EQ(2U, s[0]->InputCount());
596   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
597   EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
598 }
599 
600 
TEST_F(InstructionSelectorTest,Int32AddSimpleAsAdd)601 TEST_F(InstructionSelectorTest, Int32AddSimpleAsAdd) {
602   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
603                   MachineType::Int32());
604   Node* const p0 = m.Parameter(0);
605   Node* const p1 = m.Parameter(1);
606   // If one of the add's operands is only used once, use an "leal", even though
607   // an "addl" could be used. The "leal" has proven faster--out best guess is
608   // that it gives the register allocation more freedom and it doesn't set
609   // flags, reducing pressure in the CPU's pipeline. If we're lucky with
610   // register allocation, then code generation will select an "addl" later for
611   // the cases that have been measured to be faster.
612   m.Return(m.Int32Add(p0, p1));
613   Stream s = m.Build();
614   ASSERT_EQ(1U, s.size());
615   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
616   EXPECT_EQ(kMode_MR1, s[0]->addressing_mode());
617   ASSERT_EQ(2U, s[0]->InputCount());
618   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
619   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
620 }
621 
622 
TEST_F(InstructionSelectorTest,Int32AddSimpleAsLea)623 TEST_F(InstructionSelectorTest, Int32AddSimpleAsLea) {
624   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
625                   MachineType::Int32());
626   Node* const p0 = m.Parameter(0);
627   Node* const p1 = m.Parameter(1);
628   // If all of of the add's operands are used multiple times, use an "leal".
629   Node* const v1 = m.Int32Add(p0, p1);
630   m.Return(m.Int32Add(m.Int32Add(v1, p1), p0));
631   Stream s = m.Build();
632   ASSERT_EQ(3U, s.size());
633   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
634   EXPECT_EQ(kMode_MR1, s[0]->addressing_mode());
635   ASSERT_EQ(2U, s[0]->InputCount());
636   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
637   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
638 }
639 
640 
TEST_F(InstructionSelectorTest,Int32AddScaled2Mul)641 TEST_F(InstructionSelectorTest, Int32AddScaled2Mul) {
642   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
643                   MachineType::Int32());
644   Node* const p0 = m.Parameter(0);
645   Node* const p1 = m.Parameter(1);
646   Node* const s0 = m.Int32Mul(p1, m.Int32Constant(2));
647   m.Return(m.Int32Add(p0, s0));
648   Stream s = m.Build();
649   ASSERT_EQ(1U, s.size());
650   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
651   EXPECT_EQ(kMode_MR2, s[0]->addressing_mode());
652   ASSERT_EQ(2U, s[0]->InputCount());
653   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
654   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
655 }
656 
657 
TEST_F(InstructionSelectorTest,Int32AddCommutedScaled2Mul)658 TEST_F(InstructionSelectorTest, Int32AddCommutedScaled2Mul) {
659   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
660                   MachineType::Int32());
661   Node* const p0 = m.Parameter(0);
662   Node* const p1 = m.Parameter(1);
663   Node* const s0 = m.Int32Mul(p1, m.Int32Constant(2));
664   m.Return(m.Int32Add(s0, p0));
665   Stream s = m.Build();
666   ASSERT_EQ(1U, s.size());
667   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
668   EXPECT_EQ(kMode_MR2, s[0]->addressing_mode());
669   ASSERT_EQ(2U, 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 }
673 
674 
TEST_F(InstructionSelectorTest,Int32AddScaled2Shl)675 TEST_F(InstructionSelectorTest, Int32AddScaled2Shl) {
676   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
677                   MachineType::Int32());
678   Node* const p0 = m.Parameter(0);
679   Node* const p1 = m.Parameter(1);
680   Node* const s0 = m.Word32Shl(p1, m.Int32Constant(1));
681   m.Return(m.Int32Add(p0, s0));
682   Stream s = m.Build();
683   ASSERT_EQ(1U, s.size());
684   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
685   EXPECT_EQ(kMode_MR2, s[0]->addressing_mode());
686   ASSERT_EQ(2U, s[0]->InputCount());
687   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
688   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
689 }
690 
691 
TEST_F(InstructionSelectorTest,Int32AddCommutedScaled2Shl)692 TEST_F(InstructionSelectorTest, Int32AddCommutedScaled2Shl) {
693   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
694                   MachineType::Int32());
695   Node* const p0 = m.Parameter(0);
696   Node* const p1 = m.Parameter(1);
697   Node* const s0 = m.Word32Shl(p1, m.Int32Constant(1));
698   m.Return(m.Int32Add(s0, p0));
699   Stream s = m.Build();
700   ASSERT_EQ(1U, s.size());
701   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
702   EXPECT_EQ(kMode_MR2, s[0]->addressing_mode());
703   ASSERT_EQ(2U, s[0]->InputCount());
704   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
705   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
706 }
707 
708 
TEST_F(InstructionSelectorTest,Int32AddScaled4Mul)709 TEST_F(InstructionSelectorTest, Int32AddScaled4Mul) {
710   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
711                   MachineType::Int32());
712   Node* const p0 = m.Parameter(0);
713   Node* const p1 = m.Parameter(1);
714   Node* const s0 = m.Int32Mul(p1, m.Int32Constant(4));
715   m.Return(m.Int32Add(p0, s0));
716   Stream s = m.Build();
717   ASSERT_EQ(1U, s.size());
718   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
719   EXPECT_EQ(kMode_MR4, s[0]->addressing_mode());
720   ASSERT_EQ(2U, s[0]->InputCount());
721   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
722   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
723 }
724 
725 
TEST_F(InstructionSelectorTest,Int32AddScaled4Shl)726 TEST_F(InstructionSelectorTest, Int32AddScaled4Shl) {
727   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
728                   MachineType::Int32());
729   Node* const p0 = m.Parameter(0);
730   Node* const p1 = m.Parameter(1);
731   Node* const s0 = m.Word32Shl(p1, m.Int32Constant(2));
732   m.Return(m.Int32Add(p0, s0));
733   Stream s = m.Build();
734   ASSERT_EQ(1U, s.size());
735   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
736   EXPECT_EQ(kMode_MR4, s[0]->addressing_mode());
737   ASSERT_EQ(2U, s[0]->InputCount());
738   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
739   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
740 }
741 
742 
TEST_F(InstructionSelectorTest,Int32AddScaled8Mul)743 TEST_F(InstructionSelectorTest, Int32AddScaled8Mul) {
744   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
745                   MachineType::Int32());
746   Node* const p0 = m.Parameter(0);
747   Node* const p1 = m.Parameter(1);
748   Node* const s0 = m.Int32Mul(p1, m.Int32Constant(8));
749   m.Return(m.Int32Add(p0, s0));
750   Stream s = m.Build();
751   ASSERT_EQ(1U, s.size());
752   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
753   EXPECT_EQ(kMode_MR8, s[0]->addressing_mode());
754   ASSERT_EQ(2U, s[0]->InputCount());
755   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
756   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
757 }
758 
759 
TEST_F(InstructionSelectorTest,Int32AddScaled8Shl)760 TEST_F(InstructionSelectorTest, Int32AddScaled8Shl) {
761   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
762                   MachineType::Int32());
763   Node* const p0 = m.Parameter(0);
764   Node* const p1 = m.Parameter(1);
765   Node* const s0 = m.Word32Shl(p1, m.Int32Constant(3));
766   m.Return(m.Int32Add(p0, s0));
767   Stream s = m.Build();
768   ASSERT_EQ(1U, s.size());
769   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
770   EXPECT_EQ(kMode_MR8, s[0]->addressing_mode());
771   ASSERT_EQ(2U, s[0]->InputCount());
772   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
773   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
774 }
775 
776 
TEST_F(InstructionSelectorTest,Int32AddScaled2MulWithConstant)777 TEST_F(InstructionSelectorTest, Int32AddScaled2MulWithConstant) {
778   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
779                   MachineType::Int32());
780   Node* const p0 = m.Parameter(0);
781   Node* const p1 = m.Parameter(1);
782   Node* const s0 = m.Int32Mul(p1, m.Int32Constant(2));
783   Node* const c0 = m.Int32Constant(15);
784   m.Return(m.Int32Add(c0, m.Int32Add(p0, s0)));
785   Stream s = m.Build();
786   ASSERT_EQ(1U, s.size());
787   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
788   EXPECT_EQ(kMode_MR2I, s[0]->addressing_mode());
789   ASSERT_EQ(3U, s[0]->InputCount());
790   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
791   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
792   EXPECT_TRUE(s[0]->InputAt(2)->IsImmediate());
793 }
794 
795 
TEST_F(InstructionSelectorTest,Int32AddScaled2MulWithConstantShuffle1)796 TEST_F(InstructionSelectorTest, Int32AddScaled2MulWithConstantShuffle1) {
797   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
798                   MachineType::Int32());
799   Node* const p0 = m.Parameter(0);
800   Node* const p1 = m.Parameter(1);
801   Node* const s0 = m.Int32Mul(p1, m.Int32Constant(2));
802   Node* const c0 = m.Int32Constant(15);
803   m.Return(m.Int32Add(p0, m.Int32Add(s0, c0)));
804   Stream s = m.Build();
805   ASSERT_EQ(1U, s.size());
806   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
807   EXPECT_EQ(kMode_MR2I, s[0]->addressing_mode());
808   ASSERT_EQ(3U, s[0]->InputCount());
809   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
810   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
811   EXPECT_TRUE(s[0]->InputAt(2)->IsImmediate());
812 }
813 
814 
TEST_F(InstructionSelectorTest,Int32AddScaled2MulWithConstantShuffle2)815 TEST_F(InstructionSelectorTest, Int32AddScaled2MulWithConstantShuffle2) {
816   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
817                   MachineType::Int32());
818   Node* const p0 = m.Parameter(0);
819   Node* const p1 = m.Parameter(1);
820   Node* const s0 = m.Int32Mul(p1, m.Int32Constant(2));
821   Node* const c0 = m.Int32Constant(15);
822   m.Return(m.Int32Add(s0, m.Int32Add(c0, p0)));
823   Stream s = m.Build();
824   ASSERT_EQ(1U, s.size());
825   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
826   EXPECT_EQ(kMode_MR2I, s[0]->addressing_mode());
827   ASSERT_EQ(3U, s[0]->InputCount());
828   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
829   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
830   EXPECT_TRUE(s[0]->InputAt(2)->IsImmediate());
831 }
832 
833 
TEST_F(InstructionSelectorTest,Int32AddScaled2MulWithConstantShuffle3)834 TEST_F(InstructionSelectorTest, Int32AddScaled2MulWithConstantShuffle3) {
835   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
836                   MachineType::Int32());
837   Node* const p0 = m.Parameter(0);
838   Node* const p1 = m.Parameter(1);
839   Node* const s0 = m.Int32Mul(p1, m.Int32Constant(2));
840   Node* const c0 = m.Int32Constant(15);
841   m.Return(m.Int32Add(m.Int32Add(s0, c0), p0));
842   Stream s = m.Build();
843   ASSERT_EQ(1U, s.size());
844   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
845   EXPECT_EQ(kMode_MR2I, s[0]->addressing_mode());
846   ASSERT_EQ(3U, s[0]->InputCount());
847   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
848   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
849   EXPECT_TRUE(s[0]->InputAt(2)->IsImmediate());
850 }
851 
852 
TEST_F(InstructionSelectorTest,Int32AddScaled2MulWithConstantShuffle4)853 TEST_F(InstructionSelectorTest, Int32AddScaled2MulWithConstantShuffle4) {
854   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
855                   MachineType::Int32());
856   Node* const p0 = m.Parameter(0);
857   Node* const p1 = m.Parameter(1);
858   Node* const s0 = m.Int32Mul(p1, m.Int32Constant(2));
859   Node* const c0 = m.Int32Constant(15);
860   m.Return(m.Int32Add(m.Int32Add(c0, p0), s0));
861   Stream s = m.Build();
862   ASSERT_EQ(1U, s.size());
863   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
864   EXPECT_EQ(kMode_MR2I, s[0]->addressing_mode());
865   ASSERT_EQ(3U, s[0]->InputCount());
866   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
867   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
868   EXPECT_TRUE(s[0]->InputAt(2)->IsImmediate());
869 }
870 
871 
TEST_F(InstructionSelectorTest,Int32AddScaled2MulWithConstantShuffle5)872 TEST_F(InstructionSelectorTest, Int32AddScaled2MulWithConstantShuffle5) {
873   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
874                   MachineType::Int32());
875   Node* const p0 = m.Parameter(0);
876   Node* const p1 = m.Parameter(1);
877   Node* const s0 = m.Int32Mul(p1, m.Int32Constant(2));
878   Node* const c0 = m.Int32Constant(15);
879   m.Return(m.Int32Add(m.Int32Add(p0, s0), c0));
880   Stream s = m.Build();
881   ASSERT_EQ(1U, s.size());
882   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
883   EXPECT_EQ(kMode_MR2I, s[0]->addressing_mode());
884   ASSERT_EQ(3U, s[0]->InputCount());
885   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
886   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
887   EXPECT_TRUE(s[0]->InputAt(2)->IsImmediate());
888 }
889 
890 
TEST_F(InstructionSelectorTest,Int32AddScaled2ShlWithConstant)891 TEST_F(InstructionSelectorTest, Int32AddScaled2ShlWithConstant) {
892   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
893                   MachineType::Int32());
894   Node* const p0 = m.Parameter(0);
895   Node* const p1 = m.Parameter(1);
896   Node* const s0 = m.Word32Shl(p1, m.Int32Constant(1));
897   Node* const c0 = m.Int32Constant(15);
898   m.Return(m.Int32Add(c0, m.Int32Add(p0, s0)));
899   Stream s = m.Build();
900   ASSERT_EQ(1U, s.size());
901   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
902   EXPECT_EQ(kMode_MR2I, s[0]->addressing_mode());
903   ASSERT_EQ(3U, s[0]->InputCount());
904   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
905   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
906   EXPECT_TRUE(s[0]->InputAt(2)->IsImmediate());
907 }
908 
909 
TEST_F(InstructionSelectorTest,Int32AddScaled4MulWithConstant)910 TEST_F(InstructionSelectorTest, Int32AddScaled4MulWithConstant) {
911   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
912                   MachineType::Int32());
913   Node* const p0 = m.Parameter(0);
914   Node* const p1 = m.Parameter(1);
915   Node* const s0 = m.Int32Mul(p1, m.Int32Constant(4));
916   Node* const c0 = m.Int32Constant(15);
917   m.Return(m.Int32Add(c0, m.Int32Add(p0, s0)));
918   Stream s = m.Build();
919   ASSERT_EQ(1U, s.size());
920   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
921   EXPECT_EQ(kMode_MR4I, s[0]->addressing_mode());
922   ASSERT_EQ(3U, s[0]->InputCount());
923   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
924   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
925   EXPECT_TRUE(s[0]->InputAt(2)->IsImmediate());
926 }
927 
928 
TEST_F(InstructionSelectorTest,Int32AddScaled4ShlWithConstant)929 TEST_F(InstructionSelectorTest, Int32AddScaled4ShlWithConstant) {
930   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
931                   MachineType::Int32());
932   Node* const p0 = m.Parameter(0);
933   Node* const p1 = m.Parameter(1);
934   Node* const s0 = m.Word32Shl(p1, m.Int32Constant(2));
935   Node* const c0 = m.Int32Constant(15);
936   m.Return(m.Int32Add(c0, m.Int32Add(p0, s0)));
937   Stream s = m.Build();
938   ASSERT_EQ(1U, s.size());
939   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
940   EXPECT_EQ(kMode_MR4I, s[0]->addressing_mode());
941   ASSERT_EQ(3U, s[0]->InputCount());
942   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
943   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
944   EXPECT_TRUE(s[0]->InputAt(2)->IsImmediate());
945 }
946 
947 
TEST_F(InstructionSelectorTest,Int32AddScaled8MulWithConstant)948 TEST_F(InstructionSelectorTest, Int32AddScaled8MulWithConstant) {
949   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
950                   MachineType::Int32());
951   Node* const p0 = m.Parameter(0);
952   Node* const p1 = m.Parameter(1);
953   Node* const s0 = m.Int32Mul(p1, m.Int32Constant(8));
954   Node* const c0 = m.Int32Constant(15);
955   m.Return(m.Int32Add(c0, m.Int32Add(p0, s0)));
956   Stream s = m.Build();
957   ASSERT_EQ(1U, s.size());
958   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
959   EXPECT_EQ(kMode_MR8I, s[0]->addressing_mode());
960   ASSERT_EQ(3U, s[0]->InputCount());
961   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
962   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
963   EXPECT_TRUE(s[0]->InputAt(2)->IsImmediate());
964 }
965 
966 
TEST_F(InstructionSelectorTest,Int32AddScaled8ShlWithConstant)967 TEST_F(InstructionSelectorTest, Int32AddScaled8ShlWithConstant) {
968   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
969                   MachineType::Int32());
970   Node* const p0 = m.Parameter(0);
971   Node* const p1 = m.Parameter(1);
972   Node* const s0 = m.Word32Shl(p1, m.Int32Constant(3));
973   Node* const c0 = m.Int32Constant(15);
974   m.Return(m.Int32Add(c0, m.Int32Add(p0, s0)));
975   Stream s = m.Build();
976   ASSERT_EQ(1U, s.size());
977   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
978   EXPECT_EQ(kMode_MR8I, s[0]->addressing_mode());
979   ASSERT_EQ(3U, s[0]->InputCount());
980   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
981   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
982   EXPECT_TRUE(s[0]->InputAt(2)->IsImmediate());
983 }
984 
985 
TEST_F(InstructionSelectorTest,Int32SubConstantAsSub)986 TEST_F(InstructionSelectorTest, Int32SubConstantAsSub) {
987   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
988   Node* const p0 = m.Parameter(0);
989   Node* const c0 = m.Int32Constant(-1);
990   // If there is only a single use of on of the sub's non-constant input, use a
991   // "subl" instruction.
992   m.Return(m.Int32Sub(p0, c0));
993   Stream s = m.Build();
994   ASSERT_EQ(1U, s.size());
995   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
996   EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
997   ASSERT_EQ(2U, s[0]->InputCount());
998   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
999   EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
1000 }
1001 
1002 
TEST_F(InstructionSelectorTest,Int32SubConstantAsLea)1003 TEST_F(InstructionSelectorTest, Int32SubConstantAsLea) {
1004   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
1005   Node* const p0 = m.Parameter(0);
1006   Node* const c0 = m.Int32Constant(-1);
1007   // If there are multiple uses of on of the sub's non-constant input, use a
1008   // "leal" instruction.
1009   Node* const v0 = m.Int32Sub(p0, c0);
1010   m.Return(m.Int32Div(p0, v0));
1011   Stream s = m.Build();
1012   ASSERT_EQ(2U, s.size());
1013   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
1014   EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
1015   ASSERT_EQ(2U, s[0]->InputCount());
1016   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1017   EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
1018 }
1019 
1020 
TEST_F(InstructionSelectorTest,Int32AddScaled2Other)1021 TEST_F(InstructionSelectorTest, Int32AddScaled2Other) {
1022   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
1023                   MachineType::Int32(), MachineType::Int32());
1024   Node* const p0 = m.Parameter(0);
1025   Node* const p1 = m.Parameter(1);
1026   Node* const p2 = m.Parameter(2);
1027   Node* const s0 = m.Int32Mul(p1, m.Int32Constant(2));
1028   Node* const a0 = m.Int32Add(s0, p2);
1029   Node* const a1 = m.Int32Add(p0, a0);
1030   m.Return(a1);
1031   Stream s = m.Build();
1032   ASSERT_EQ(2U, s.size());
1033   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
1034   EXPECT_EQ(kMode_MR2, s[0]->addressing_mode());
1035   ASSERT_EQ(2U, s[0]->InputCount());
1036   EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(0)));
1037   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
1038   EXPECT_EQ(s.ToVreg(a0), s.ToVreg(s[0]->OutputAt(0)));
1039   ASSERT_EQ(2U, s[1]->InputCount());
1040   EXPECT_EQ(kX64Lea32, s[1]->arch_opcode());
1041   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[1]->InputAt(0)));
1042   EXPECT_EQ(s.ToVreg(a0), s.ToVreg(s[1]->InputAt(1)));
1043   EXPECT_EQ(s.ToVreg(a1), s.ToVreg(s[1]->OutputAt(0)));
1044 }
1045 
TEST_F(InstructionSelectorTest,Int32AddMinNegativeDisplacement)1046 TEST_F(InstructionSelectorTest, Int32AddMinNegativeDisplacement) {
1047   // This test case is simplified from a Wasm fuzz test in
1048   // https://crbug.com/1091892. The key here is that we match on a
1049   // sequence like: Int32Add(Int32Sub(-524288, -2147483648), -26048), which
1050   // matches on an EmitLea, with -2147483648 as the displacement. Since we
1051   // have a Int32Sub node, it sets kNegativeDisplacement, and later we try to
1052   // negate -2147483648, which overflows.
1053   StreamBuilder m(this, MachineType::Int32());
1054   Node* const c0 = m.Int32Constant(-524288);
1055   Node* const c1 = m.Int32Constant(std::numeric_limits<int32_t>::min());
1056   Node* const c2 = m.Int32Constant(-26048);
1057   Node* const a0 = m.Int32Sub(c0, c1);
1058   Node* const a1 = m.Int32Add(a0, c2);
1059   m.Return(a1);
1060   Stream s = m.Build();
1061   ASSERT_EQ(2U, s.size());
1062 
1063   EXPECT_EQ(kX64Sub32, s[0]->arch_opcode());
1064   ASSERT_EQ(2U, s[0]->InputCount());
1065   EXPECT_EQ(kMode_None, s[0]->addressing_mode());
1066   EXPECT_EQ(s.ToVreg(c0), s.ToVreg(s[0]->InputAt(0)));
1067   EXPECT_EQ(s.ToVreg(c1), s.ToVreg(s[0]->InputAt(1)));
1068   EXPECT_EQ(s.ToVreg(a0), s.ToVreg(s[0]->OutputAt(0)));
1069 
1070   EXPECT_EQ(kX64Add32, s[1]->arch_opcode());
1071   ASSERT_EQ(2U, s[1]->InputCount());
1072   EXPECT_EQ(kMode_None, s[1]->addressing_mode());
1073   EXPECT_EQ(s.ToVreg(a0), s.ToVreg(s[1]->InputAt(0)));
1074   EXPECT_TRUE(s[1]->InputAt(1)->IsImmediate());
1075   EXPECT_EQ(s.ToVreg(a1), s.ToVreg(s[1]->OutputAt(0)));
1076 }
1077 
1078 // -----------------------------------------------------------------------------
1079 // Multiplication.
1080 
1081 
TEST_F(InstructionSelectorTest,Int32MulWithInt32MulWithParameters)1082 TEST_F(InstructionSelectorTest, Int32MulWithInt32MulWithParameters) {
1083   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
1084                   MachineType::Int32());
1085   Node* const p0 = m.Parameter(0);
1086   Node* const p1 = m.Parameter(1);
1087   Node* const m0 = m.Int32Mul(p0, p1);
1088   m.Return(m.Int32Mul(m0, p0));
1089   Stream s = m.Build();
1090   ASSERT_EQ(2U, s.size());
1091   EXPECT_EQ(kX64Imul32, s[0]->arch_opcode());
1092   ASSERT_EQ(2U, s[0]->InputCount());
1093   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(0)));
1094   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1)));
1095   ASSERT_EQ(1U, s[0]->OutputCount());
1096   EXPECT_EQ(s.ToVreg(m0), s.ToVreg(s[0]->OutputAt(0)));
1097   EXPECT_EQ(kX64Imul32, s[1]->arch_opcode());
1098   ASSERT_EQ(2U, s[1]->InputCount());
1099   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[1]->InputAt(0)));
1100   EXPECT_EQ(s.ToVreg(m0), s.ToVreg(s[1]->InputAt(1)));
1101 }
1102 
1103 
TEST_F(InstructionSelectorTest,Int32MulHigh)1104 TEST_F(InstructionSelectorTest, Int32MulHigh) {
1105   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
1106                   MachineType::Int32());
1107   Node* const p0 = m.Parameter(0);
1108   Node* const p1 = m.Parameter(1);
1109   Node* const n = m.Int32MulHigh(p0, p1);
1110   m.Return(n);
1111   Stream s = m.Build();
1112   ASSERT_EQ(1U, s.size());
1113   EXPECT_EQ(kX64ImulHigh32, s[0]->arch_opcode());
1114   ASSERT_EQ(2U, s[0]->InputCount());
1115   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1116   EXPECT_TRUE(s.IsFixed(s[0]->InputAt(0), rax));
1117   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
1118   EXPECT_TRUE(!s.IsUsedAtStart(s[0]->InputAt(1)));
1119   ASSERT_LE(1U, s[0]->OutputCount());
1120   EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1121   EXPECT_TRUE(s.IsFixed(s[0]->OutputAt(0), rdx));
1122 }
1123 
1124 
TEST_F(InstructionSelectorTest,Uint32MulHigh)1125 TEST_F(InstructionSelectorTest, Uint32MulHigh) {
1126   StreamBuilder m(this, MachineType::Uint32(), MachineType::Uint32(),
1127                   MachineType::Uint32());
1128   Node* const p0 = m.Parameter(0);
1129   Node* const p1 = m.Parameter(1);
1130   Node* const n = m.Uint32MulHigh(p0, p1);
1131   m.Return(n);
1132   Stream s = m.Build();
1133   ASSERT_EQ(1U, s.size());
1134   EXPECT_EQ(kX64UmulHigh32, s[0]->arch_opcode());
1135   ASSERT_EQ(2U, s[0]->InputCount());
1136   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1137   EXPECT_TRUE(s.IsFixed(s[0]->InputAt(0), rax));
1138   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
1139   EXPECT_TRUE(!s.IsUsedAtStart(s[0]->InputAt(1)));
1140   ASSERT_LE(1U, s[0]->OutputCount());
1141   EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1142   EXPECT_TRUE(s.IsFixed(s[0]->OutputAt(0), rdx));
1143 }
1144 
1145 
TEST_F(InstructionSelectorTest,Int32Mul2BecomesLea)1146 TEST_F(InstructionSelectorTest, Int32Mul2BecomesLea) {
1147   StreamBuilder m(this, MachineType::Uint32(), MachineType::Uint32(),
1148                   MachineType::Uint32());
1149   Node* const p0 = m.Parameter(0);
1150   Node* const c1 = m.Int32Constant(2);
1151   Node* const n = m.Int32Mul(p0, c1);
1152   m.Return(n);
1153   Stream s = m.Build();
1154   ASSERT_EQ(1U, s.size());
1155   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
1156   EXPECT_EQ(kMode_MR1, s[0]->addressing_mode());
1157   ASSERT_EQ(2U, s[0]->InputCount());
1158   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1159   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1)));
1160 }
1161 
1162 
TEST_F(InstructionSelectorTest,Int32Mul3BecomesLea)1163 TEST_F(InstructionSelectorTest, Int32Mul3BecomesLea) {
1164   StreamBuilder m(this, MachineType::Uint32(), MachineType::Uint32(),
1165                   MachineType::Uint32());
1166   Node* const p0 = m.Parameter(0);
1167   Node* const c1 = m.Int32Constant(3);
1168   Node* const n = m.Int32Mul(p0, c1);
1169   m.Return(n);
1170   Stream s = m.Build();
1171   ASSERT_EQ(1U, s.size());
1172   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
1173   EXPECT_EQ(kMode_MR2, s[0]->addressing_mode());
1174   ASSERT_EQ(2U, s[0]->InputCount());
1175   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1176   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1)));
1177 }
1178 
1179 
TEST_F(InstructionSelectorTest,Int32Mul4BecomesLea)1180 TEST_F(InstructionSelectorTest, Int32Mul4BecomesLea) {
1181   StreamBuilder m(this, MachineType::Uint32(), MachineType::Uint32(),
1182                   MachineType::Uint32());
1183   Node* const p0 = m.Parameter(0);
1184   Node* const c1 = m.Int32Constant(4);
1185   Node* const n = m.Int32Mul(p0, c1);
1186   m.Return(n);
1187   Stream s = m.Build();
1188   ASSERT_EQ(1U, s.size());
1189   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
1190   EXPECT_EQ(kMode_M4, s[0]->addressing_mode());
1191   ASSERT_EQ(1U, s[0]->InputCount());
1192   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1193 }
1194 
1195 
TEST_F(InstructionSelectorTest,Int32Mul5BecomesLea)1196 TEST_F(InstructionSelectorTest, Int32Mul5BecomesLea) {
1197   StreamBuilder m(this, MachineType::Uint32(), MachineType::Uint32(),
1198                   MachineType::Uint32());
1199   Node* const p0 = m.Parameter(0);
1200   Node* const c1 = m.Int32Constant(5);
1201   Node* const n = m.Int32Mul(p0, c1);
1202   m.Return(n);
1203   Stream s = m.Build();
1204   ASSERT_EQ(1U, s.size());
1205   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
1206   EXPECT_EQ(kMode_MR4, s[0]->addressing_mode());
1207   ASSERT_EQ(2U, s[0]->InputCount());
1208   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1209   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1)));
1210 }
1211 
1212 
TEST_F(InstructionSelectorTest,Int32Mul8BecomesLea)1213 TEST_F(InstructionSelectorTest, Int32Mul8BecomesLea) {
1214   StreamBuilder m(this, MachineType::Uint32(), MachineType::Uint32(),
1215                   MachineType::Uint32());
1216   Node* const p0 = m.Parameter(0);
1217   Node* const c1 = m.Int32Constant(8);
1218   Node* const n = m.Int32Mul(p0, c1);
1219   m.Return(n);
1220   Stream s = m.Build();
1221   ASSERT_EQ(1U, s.size());
1222   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
1223   EXPECT_EQ(kMode_M8, s[0]->addressing_mode());
1224   ASSERT_EQ(1U, s[0]->InputCount());
1225   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1226 }
1227 
1228 
TEST_F(InstructionSelectorTest,Int32Mul9BecomesLea)1229 TEST_F(InstructionSelectorTest, Int32Mul9BecomesLea) {
1230   StreamBuilder m(this, MachineType::Uint32(), MachineType::Uint32(),
1231                   MachineType::Uint32());
1232   Node* const p0 = m.Parameter(0);
1233   Node* const c1 = m.Int32Constant(9);
1234   Node* const n = m.Int32Mul(p0, c1);
1235   m.Return(n);
1236   Stream s = m.Build();
1237   ASSERT_EQ(1U, s.size());
1238   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
1239   EXPECT_EQ(kMode_MR8, s[0]->addressing_mode());
1240   ASSERT_EQ(2U, s[0]->InputCount());
1241   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1242   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1)));
1243 }
1244 
1245 
1246 // -----------------------------------------------------------------------------
1247 // Word32Shl.
1248 
1249 
TEST_F(InstructionSelectorTest,Int32Shl1BecomesLea)1250 TEST_F(InstructionSelectorTest, Int32Shl1BecomesLea) {
1251   StreamBuilder m(this, MachineType::Uint32(), MachineType::Uint32(),
1252                   MachineType::Uint32());
1253   Node* const p0 = m.Parameter(0);
1254   Node* const c1 = m.Int32Constant(1);
1255   Node* const n = m.Word32Shl(p0, c1);
1256   m.Return(n);
1257   Stream s = m.Build();
1258   ASSERT_EQ(1U, s.size());
1259   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
1260   EXPECT_EQ(kMode_MR1, s[0]->addressing_mode());
1261   ASSERT_EQ(2U, s[0]->InputCount());
1262   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1263   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1)));
1264 }
1265 
1266 
TEST_F(InstructionSelectorTest,Int32Shl2BecomesLea)1267 TEST_F(InstructionSelectorTest, Int32Shl2BecomesLea) {
1268   StreamBuilder m(this, MachineType::Uint32(), MachineType::Uint32(),
1269                   MachineType::Uint32());
1270   Node* const p0 = m.Parameter(0);
1271   Node* const c1 = m.Int32Constant(2);
1272   Node* const n = m.Word32Shl(p0, c1);
1273   m.Return(n);
1274   Stream s = m.Build();
1275   ASSERT_EQ(1U, s.size());
1276   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
1277   EXPECT_EQ(kMode_M4, s[0]->addressing_mode());
1278   ASSERT_EQ(1U, s[0]->InputCount());
1279   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1280 }
1281 
1282 
TEST_F(InstructionSelectorTest,Int32Shl4BecomesLea)1283 TEST_F(InstructionSelectorTest, Int32Shl4BecomesLea) {
1284   StreamBuilder m(this, MachineType::Uint32(), MachineType::Uint32(),
1285                   MachineType::Uint32());
1286   Node* const p0 = m.Parameter(0);
1287   Node* const c1 = m.Int32Constant(3);
1288   Node* const n = m.Word32Shl(p0, c1);
1289   m.Return(n);
1290   Stream s = m.Build();
1291   ASSERT_EQ(1U, s.size());
1292   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
1293   EXPECT_EQ(kMode_M8, s[0]->addressing_mode());
1294   ASSERT_EQ(1U, s[0]->InputCount());
1295   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1296 }
1297 
1298 // -----------------------------------------------------------------------------
1299 // Binops with a memory operand.
1300 
TEST_F(InstructionSelectorTest,LoadCmp32)1301 TEST_F(InstructionSelectorTest, LoadCmp32) {
1302   {
1303     // Word32Equal(Load[Int8](p0, p1), Int32Constant(0)) -> cmpb [p0,p1], 0
1304     StreamBuilder m(this, MachineType::Int32(), MachineType::Int64(),
1305                     MachineType::Int64());
1306     Node* const p0 = m.Parameter(0);
1307     Node* const p1 = m.Parameter(1);
1308     m.Return(
1309         m.Word32Equal(m.Load(MachineType::Int8(), p0, p1), m.Int32Constant(0)));
1310     Stream s = m.Build();
1311     ASSERT_EQ(1U, s.size());
1312     EXPECT_EQ(kX64Cmp8, s[0]->arch_opcode());
1313     EXPECT_EQ(kMode_MR1, s[0]->addressing_mode());
1314     ASSERT_EQ(3U, s[0]->InputCount());
1315     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1316     EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
1317     EXPECT_TRUE(s[0]->InputAt(2)->IsImmediate());
1318   }
1319   {
1320     // Word32Equal(LoadImmutable[Int8](p0, p1), Int32Constant(0)) ->
1321     //  cmpb [p0,p1], 0
1322     StreamBuilder m(this, MachineType::Int32(), MachineType::Int64(),
1323                     MachineType::Int64());
1324     Node* const p0 = m.Parameter(0);
1325     Node* const p1 = m.Parameter(1);
1326     m.Return(m.Word32Equal(m.LoadImmutable(MachineType::Int8(), p0, p1),
1327                            m.Int32Constant(0)));
1328     Stream s = m.Build();
1329     ASSERT_EQ(1U, s.size());
1330     EXPECT_EQ(kX64Cmp8, s[0]->arch_opcode());
1331     EXPECT_EQ(kMode_MR1, s[0]->addressing_mode());
1332     ASSERT_EQ(3U, s[0]->InputCount());
1333     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1334     EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
1335     EXPECT_TRUE(s[0]->InputAt(2)->IsImmediate());
1336   }
1337   {
1338     // Word32Equal(Load[Uint8](p0, p1), Int32Constant(0)) -> cmpb [p0,p1], 0
1339     StreamBuilder m(this, MachineType::Int32(), MachineType::Int64(),
1340                     MachineType::Int64());
1341     Node* const p0 = m.Parameter(0);
1342     Node* const p1 = m.Parameter(1);
1343     m.Return(m.Word32Equal(m.Load(MachineType::Uint8(), p0, p1),
1344                            m.Int32Constant(0)));
1345     Stream s = m.Build();
1346     ASSERT_EQ(1U, s.size());
1347     EXPECT_EQ(kX64Cmp8, s[0]->arch_opcode());
1348     EXPECT_EQ(kMode_MR1, s[0]->addressing_mode());
1349     ASSERT_EQ(3U, s[0]->InputCount());
1350     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1351     EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
1352     EXPECT_TRUE(s[0]->InputAt(2)->IsImmediate());
1353   }
1354   {
1355     // Word32Equal(Load[Int16](p0, p1), Int32Constant(0)) -> cmpw [p0,p1], 0
1356     StreamBuilder m(this, MachineType::Int32(), MachineType::Int64(),
1357                     MachineType::Int64());
1358     Node* const p0 = m.Parameter(0);
1359     Node* const p1 = m.Parameter(1);
1360     m.Return(m.Word32Equal(m.Load(MachineType::Int16(), p0, p1),
1361                            m.Int32Constant(0)));
1362     Stream s = m.Build();
1363     ASSERT_EQ(1U, s.size());
1364     EXPECT_EQ(kX64Cmp16, s[0]->arch_opcode());
1365     EXPECT_EQ(kMode_MR1, s[0]->addressing_mode());
1366     ASSERT_EQ(3U, s[0]->InputCount());
1367     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1368     EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
1369     EXPECT_TRUE(s[0]->InputAt(2)->IsImmediate());
1370   }
1371   {
1372     // Word32Equal(Load[Uint16](p0, p1), Int32Constant(0)) -> cmpw [p0,p1], 0
1373     StreamBuilder m(this, MachineType::Int32(), MachineType::Int64(),
1374                     MachineType::Int64());
1375     Node* const p0 = m.Parameter(0);
1376     Node* const p1 = m.Parameter(1);
1377     m.Return(m.Word32Equal(m.Load(MachineType::Uint16(), p0, p1),
1378                            m.Int32Constant(0)));
1379     Stream s = m.Build();
1380     ASSERT_EQ(1U, s.size());
1381     EXPECT_EQ(kX64Cmp16, s[0]->arch_opcode());
1382     EXPECT_EQ(kMode_MR1, s[0]->addressing_mode());
1383     ASSERT_EQ(3U, s[0]->InputCount());
1384     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1385     EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
1386     EXPECT_TRUE(s[0]->InputAt(2)->IsImmediate());
1387   }
1388   {
1389     // Word32Equal(Load[Int32](p0, p1), Int32Constant(0)) -> cmpl [p0,p1], 0
1390     StreamBuilder m(this, MachineType::Int32(), MachineType::Int64(),
1391                     MachineType::Int64());
1392     Node* const p0 = m.Parameter(0);
1393     Node* const p1 = m.Parameter(1);
1394     m.Return(m.Word32Equal(m.Load(MachineType::Int32(), p0, p1),
1395                            m.Int32Constant(0)));
1396     Stream s = m.Build();
1397     ASSERT_EQ(1U, s.size());
1398     EXPECT_EQ(kX64Cmp32, s[0]->arch_opcode());
1399     EXPECT_EQ(kMode_MR1, s[0]->addressing_mode());
1400     ASSERT_EQ(3U, s[0]->InputCount());
1401     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1402     EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
1403     EXPECT_TRUE(s[0]->InputAt(2)->IsImmediate());
1404   }
1405   {
1406     // Word32Equal(Load[Uint32](p0, p1), Int32Constant(0)) -> cmpl [p0,p1], 0
1407     StreamBuilder m(this, MachineType::Int32(), MachineType::Int64(),
1408                     MachineType::Int64());
1409     Node* const p0 = m.Parameter(0);
1410     Node* const p1 = m.Parameter(1);
1411     m.Return(m.Word32Equal(m.Load(MachineType::Uint32(), p0, p1),
1412                            m.Int32Constant(0)));
1413     Stream s = m.Build();
1414     ASSERT_EQ(1U, s.size());
1415     EXPECT_EQ(kX64Cmp32, s[0]->arch_opcode());
1416     EXPECT_EQ(kMode_MR1, s[0]->addressing_mode());
1417     ASSERT_EQ(3U, s[0]->InputCount());
1418     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1419     EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
1420     EXPECT_TRUE(s[0]->InputAt(2)->IsImmediate());
1421   }
1422 }
1423 
TEST_F(InstructionSelectorTest,LoadAnd32)1424 TEST_F(InstructionSelectorTest, LoadAnd32) {
1425   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
1426                   MachineType::Int32());
1427   Node* const p0 = m.Parameter(0);
1428   Node* const p1 = m.Parameter(1);
1429   m.Return(
1430       m.Word32And(p0, m.Load(MachineType::Int32(), p1, m.Int32Constant(127))));
1431   Stream s = m.Build();
1432   ASSERT_EQ(1U, s.size());
1433   EXPECT_EQ(kX64And32, s[0]->arch_opcode());
1434   ASSERT_EQ(3U, s[0]->InputCount());
1435   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1436   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
1437 }
1438 
TEST_F(InstructionSelectorTest,LoadOr32)1439 TEST_F(InstructionSelectorTest, LoadOr32) {
1440   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
1441                   MachineType::Int32());
1442   Node* const p0 = m.Parameter(0);
1443   Node* const p1 = m.Parameter(1);
1444   m.Return(
1445       m.Word32Or(p0, m.Load(MachineType::Int32(), p1, m.Int32Constant(127))));
1446   Stream s = m.Build();
1447   ASSERT_EQ(1U, s.size());
1448   EXPECT_EQ(kX64Or32, s[0]->arch_opcode());
1449   ASSERT_EQ(3U, s[0]->InputCount());
1450   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1451   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
1452 }
1453 
TEST_F(InstructionSelectorTest,LoadXor32)1454 TEST_F(InstructionSelectorTest, LoadXor32) {
1455   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
1456                   MachineType::Int32());
1457   Node* const p0 = m.Parameter(0);
1458   Node* const p1 = m.Parameter(1);
1459   m.Return(
1460       m.Word32Xor(p0, m.Load(MachineType::Int32(), p1, m.Int32Constant(127))));
1461   Stream s = m.Build();
1462   ASSERT_EQ(1U, s.size());
1463   EXPECT_EQ(kX64Xor32, s[0]->arch_opcode());
1464   ASSERT_EQ(3U, s[0]->InputCount());
1465   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1466   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
1467 }
1468 
TEST_F(InstructionSelectorTest,LoadAdd32)1469 TEST_F(InstructionSelectorTest, LoadAdd32) {
1470   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
1471                   MachineType::Int32());
1472   Node* const p0 = m.Parameter(0);
1473   Node* const p1 = m.Parameter(1);
1474   m.Return(
1475       m.Int32Add(p0, m.Load(MachineType::Int32(), p1, m.Int32Constant(127))));
1476   Stream s = m.Build();
1477   // Use lea instead of add, so memory operand is invalid.
1478   ASSERT_EQ(2U, s.size());
1479   EXPECT_EQ(kX64Movl, s[0]->arch_opcode());
1480   EXPECT_EQ(kX64Lea32, s[1]->arch_opcode());
1481 }
1482 
TEST_F(InstructionSelectorTest,LoadSub32)1483 TEST_F(InstructionSelectorTest, LoadSub32) {
1484   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
1485                   MachineType::Int32());
1486   Node* const p0 = m.Parameter(0);
1487   Node* const p1 = m.Parameter(1);
1488   m.Return(
1489       m.Int32Sub(p0, m.Load(MachineType::Int32(), p1, m.Int32Constant(127))));
1490   Stream s = m.Build();
1491   ASSERT_EQ(1U, s.size());
1492   EXPECT_EQ(kX64Sub32, s[0]->arch_opcode());
1493   ASSERT_EQ(3U, s[0]->InputCount());
1494   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1495   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
1496 }
1497 
TEST_F(InstructionSelectorTest,LoadAnd64)1498 TEST_F(InstructionSelectorTest, LoadAnd64) {
1499   StreamBuilder m(this, MachineType::Int64(), MachineType::Int64(),
1500                   MachineType::Int64());
1501   Node* const p0 = m.Parameter(0);
1502   Node* const p1 = m.Parameter(1);
1503   m.Return(
1504       m.Word64And(p0, m.Load(MachineType::Int64(), p1, m.Int32Constant(127))));
1505   Stream s = m.Build();
1506   ASSERT_EQ(1U, s.size());
1507   EXPECT_EQ(kX64And, s[0]->arch_opcode());
1508   ASSERT_EQ(3U, s[0]->InputCount());
1509   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1510   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
1511 }
1512 
TEST_F(InstructionSelectorTest,LoadOr64)1513 TEST_F(InstructionSelectorTest, LoadOr64) {
1514   StreamBuilder m(this, MachineType::Int64(), MachineType::Int64(),
1515                   MachineType::Int64());
1516   Node* const p0 = m.Parameter(0);
1517   Node* const p1 = m.Parameter(1);
1518   m.Return(
1519       m.Word64Or(p0, m.Load(MachineType::Int64(), p1, m.Int32Constant(127))));
1520   Stream s = m.Build();
1521   ASSERT_EQ(1U, s.size());
1522   EXPECT_EQ(kX64Or, s[0]->arch_opcode());
1523   ASSERT_EQ(3U, s[0]->InputCount());
1524   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1525   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
1526 }
1527 
TEST_F(InstructionSelectorTest,LoadXor64)1528 TEST_F(InstructionSelectorTest, LoadXor64) {
1529   StreamBuilder m(this, MachineType::Int64(), MachineType::Int64(),
1530                   MachineType::Int64());
1531   Node* const p0 = m.Parameter(0);
1532   Node* const p1 = m.Parameter(1);
1533   m.Return(
1534       m.Word64Xor(p0, m.Load(MachineType::Int64(), p1, m.Int32Constant(127))));
1535   Stream s = m.Build();
1536   ASSERT_EQ(1U, s.size());
1537   EXPECT_EQ(kX64Xor, s[0]->arch_opcode());
1538   ASSERT_EQ(3U, s[0]->InputCount());
1539   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1540   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
1541 }
1542 
TEST_F(InstructionSelectorTest,LoadAdd64)1543 TEST_F(InstructionSelectorTest, LoadAdd64) {
1544   StreamBuilder m(this, MachineType::Int64(), MachineType::Int64(),
1545                   MachineType::Int64());
1546   Node* const p0 = m.Parameter(0);
1547   Node* const p1 = m.Parameter(1);
1548   m.Return(
1549       m.Int64Add(p0, m.Load(MachineType::Int64(), p1, m.Int32Constant(127))));
1550   Stream s = m.Build();
1551   // Use lea instead of add, so memory operand is invalid.
1552   ASSERT_EQ(2U, s.size());
1553   EXPECT_EQ(kX64Movq, s[0]->arch_opcode());
1554   EXPECT_EQ(kX64Lea, s[1]->arch_opcode());
1555 }
1556 
TEST_F(InstructionSelectorTest,LoadSub64)1557 TEST_F(InstructionSelectorTest, LoadSub64) {
1558   StreamBuilder m(this, MachineType::Int64(), MachineType::Int64(),
1559                   MachineType::Int64());
1560   Node* const p0 = m.Parameter(0);
1561   Node* const p1 = m.Parameter(1);
1562   m.Return(
1563       m.Int64Sub(p0, m.Load(MachineType::Int64(), p1, m.Int32Constant(127))));
1564   Stream s = m.Build();
1565   ASSERT_EQ(1U, s.size());
1566   EXPECT_EQ(kX64Sub, s[0]->arch_opcode());
1567   ASSERT_EQ(3U, s[0]->InputCount());
1568   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1569   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
1570 }
1571 
1572 // -----------------------------------------------------------------------------
1573 // Floating point operations.
1574 
TEST_F(InstructionSelectorTest,Float32Abs)1575 TEST_F(InstructionSelectorTest, Float32Abs) {
1576   {
1577     StreamBuilder m(this, MachineType::Float32(), MachineType::Float32());
1578     Node* const p0 = m.Parameter(0);
1579     Node* const n = m.Float32Abs(p0);
1580     m.Return(n);
1581     Stream s = m.Build();
1582     ASSERT_EQ(1U, s.size());
1583     EXPECT_EQ(kX64Float32Abs, s[0]->arch_opcode());
1584     ASSERT_EQ(1U, s[0]->InputCount());
1585     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1586     ASSERT_EQ(1U, s[0]->OutputCount());
1587     EXPECT_TRUE(s.IsSameAsFirst(s[0]->Output()));
1588     EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1589     EXPECT_EQ(kFlags_none, s[0]->flags_mode());
1590   }
1591   {
1592     StreamBuilder m(this, MachineType::Float32(), MachineType::Float32());
1593     Node* const p0 = m.Parameter(0);
1594     Node* const n = m.Float32Abs(p0);
1595     m.Return(n);
1596     Stream s = m.Build(AVX);
1597     ASSERT_EQ(1U, s.size());
1598     EXPECT_EQ(kX64Float32Abs, s[0]->arch_opcode());
1599     ASSERT_EQ(1U, s[0]->InputCount());
1600     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1601     ASSERT_EQ(1U, s[0]->OutputCount());
1602     EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1603     EXPECT_EQ(kFlags_none, s[0]->flags_mode());
1604   }
1605 }
1606 
1607 
TEST_F(InstructionSelectorTest,Float64Abs)1608 TEST_F(InstructionSelectorTest, Float64Abs) {
1609   {
1610     StreamBuilder m(this, MachineType::Float64(), MachineType::Float64());
1611     Node* const p0 = m.Parameter(0);
1612     Node* const n = m.Float64Abs(p0);
1613     m.Return(n);
1614     Stream s = m.Build();
1615     ASSERT_EQ(1U, s.size());
1616     EXPECT_EQ(kX64Float64Abs, s[0]->arch_opcode());
1617     ASSERT_EQ(1U, s[0]->InputCount());
1618     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1619     ASSERT_EQ(1U, s[0]->OutputCount());
1620     EXPECT_TRUE(s.IsSameAsFirst(s[0]->Output()));
1621     EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1622     EXPECT_EQ(kFlags_none, s[0]->flags_mode());
1623   }
1624   {
1625     StreamBuilder m(this, MachineType::Float64(), MachineType::Float64());
1626     Node* const p0 = m.Parameter(0);
1627     Node* const n = m.Float64Abs(p0);
1628     m.Return(n);
1629     Stream s = m.Build(AVX);
1630     ASSERT_EQ(1U, s.size());
1631     EXPECT_EQ(kX64Float64Abs, s[0]->arch_opcode());
1632     ASSERT_EQ(1U, s[0]->InputCount());
1633     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1634     ASSERT_EQ(1U, s[0]->OutputCount());
1635     EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1636     EXPECT_EQ(kFlags_none, s[0]->flags_mode());
1637   }
1638 }
1639 
1640 
TEST_F(InstructionSelectorTest,Float64BinopArithmetic)1641 TEST_F(InstructionSelectorTest, Float64BinopArithmetic) {
1642   {
1643     StreamBuilder m(this, MachineType::Float64(), MachineType::Float64(),
1644                     MachineType::Float64());
1645     Node* add = m.Float64Add(m.Parameter(0), m.Parameter(1));
1646     Node* mul = m.Float64Mul(add, m.Parameter(1));
1647     Node* sub = m.Float64Sub(mul, add);
1648     Node* ret = m.Float64Div(mul, sub);
1649     m.Return(ret);
1650     Stream s = m.Build(AVX);
1651     ASSERT_EQ(4U, s.size());
1652     EXPECT_EQ(kAVXFloat64Add, s[0]->arch_opcode());
1653     EXPECT_EQ(kAVXFloat64Mul, s[1]->arch_opcode());
1654     EXPECT_EQ(kAVXFloat64Sub, s[2]->arch_opcode());
1655     EXPECT_EQ(kAVXFloat64Div, s[3]->arch_opcode());
1656   }
1657   {
1658     StreamBuilder m(this, MachineType::Float64(), MachineType::Float64(),
1659                     MachineType::Float64());
1660     Node* add = m.Float64Add(m.Parameter(0), m.Parameter(1));
1661     Node* mul = m.Float64Mul(add, m.Parameter(1));
1662     Node* sub = m.Float64Sub(mul, add);
1663     Node* ret = m.Float64Div(mul, sub);
1664     m.Return(ret);
1665     Stream s = m.Build();
1666     ASSERT_EQ(4U, s.size());
1667     EXPECT_EQ(kSSEFloat64Add, s[0]->arch_opcode());
1668     EXPECT_EQ(kSSEFloat64Mul, s[1]->arch_opcode());
1669     EXPECT_EQ(kSSEFloat64Sub, s[2]->arch_opcode());
1670     EXPECT_EQ(kSSEFloat64Div, s[3]->arch_opcode());
1671   }
1672 }
1673 
TEST_F(InstructionSelectorTest,Float32BinopArithmeticWithLoad)1674 TEST_F(InstructionSelectorTest, Float32BinopArithmeticWithLoad) {
1675   {
1676     StreamBuilder m(this, MachineType::Float32(), MachineType::Float32(),
1677                     MachineType::Int64(), MachineType::Int64());
1678     Node* const p0 = m.Parameter(0);
1679     Node* const p1 = m.Parameter(1);
1680     Node* const p2 = m.Parameter(2);
1681     Node* add = m.Float32Add(
1682         p0, m.Load(MachineType::Float32(), p1, m.Int32Constant(127)));
1683     Node* sub = m.Float32Sub(
1684         add, m.Load(MachineType::Float32(), p1, m.Int32Constant(127)));
1685     Node* ret = m.Float32Mul(
1686         m.Load(MachineType::Float32(), p2, m.Int32Constant(127)), sub);
1687     m.Return(ret);
1688     Stream s = m.Build(AVX);
1689     ASSERT_EQ(3U, s.size());
1690     EXPECT_EQ(kAVXFloat32Add, s[0]->arch_opcode());
1691     ASSERT_EQ(3U, s[0]->InputCount());
1692     EXPECT_EQ(kAVXFloat32Sub, s[1]->arch_opcode());
1693     ASSERT_EQ(3U, s[1]->InputCount());
1694     EXPECT_EQ(kAVXFloat32Mul, s[2]->arch_opcode());
1695     ASSERT_EQ(3U, s[2]->InputCount());
1696     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1697     EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
1698     EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[2]->InputAt(1)));
1699   }
1700   {
1701     StreamBuilder m(this, MachineType::Float32(), MachineType::Float32(),
1702                     MachineType::Int64(), MachineType::Int64());
1703     Node* const p0 = m.Parameter(0);
1704     Node* const p1 = m.Parameter(1);
1705     Node* const p2 = m.Parameter(2);
1706     Node* add = m.Float32Add(
1707         p0, m.Load(MachineType::Float32(), p1, m.Int32Constant(127)));
1708     Node* sub = m.Float32Sub(
1709         add, m.Load(MachineType::Float32(), p1, m.Int32Constant(127)));
1710     Node* ret = m.Float32Mul(
1711         m.Load(MachineType::Float32(), p2, m.Int32Constant(127)), sub);
1712     m.Return(ret);
1713     Stream s = m.Build();
1714     ASSERT_EQ(3U, s.size());
1715     EXPECT_EQ(kSSEFloat32Add, s[0]->arch_opcode());
1716     ASSERT_EQ(3U, s[0]->InputCount());
1717     EXPECT_EQ(kSSEFloat32Sub, s[1]->arch_opcode());
1718     ASSERT_EQ(3U, s[1]->InputCount());
1719     EXPECT_EQ(kSSEFloat32Mul, s[2]->arch_opcode());
1720     ASSERT_EQ(3U, s[2]->InputCount());
1721     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1722     EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
1723     EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[2]->InputAt(1)));
1724   }
1725 }
1726 
TEST_F(InstructionSelectorTest,Float64BinopArithmeticWithLoad)1727 TEST_F(InstructionSelectorTest, Float64BinopArithmeticWithLoad) {
1728   {
1729     StreamBuilder m(this, MachineType::Float64(), MachineType::Float64(),
1730                     MachineType::Int64(), MachineType::Int64());
1731     Node* const p0 = m.Parameter(0);
1732     Node* const p1 = m.Parameter(1);
1733     Node* const p2 = m.Parameter(2);
1734     Node* add = m.Float64Add(
1735         p0, m.Load(MachineType::Float64(), p1, m.Int32Constant(127)));
1736     Node* sub = m.Float64Sub(
1737         add, m.Load(MachineType::Float64(), p1, m.Int32Constant(127)));
1738     Node* ret = m.Float64Mul(
1739         m.Load(MachineType::Float64(), p2, m.Int32Constant(127)), sub);
1740     m.Return(ret);
1741     Stream s = m.Build(AVX);
1742     ASSERT_EQ(3U, s.size());
1743     EXPECT_EQ(kAVXFloat64Add, s[0]->arch_opcode());
1744     ASSERT_EQ(3U, s[0]->InputCount());
1745     EXPECT_EQ(kAVXFloat64Sub, s[1]->arch_opcode());
1746     ASSERT_EQ(3U, s[1]->InputCount());
1747     EXPECT_EQ(kAVXFloat64Mul, s[2]->arch_opcode());
1748     ASSERT_EQ(3U, s[2]->InputCount());
1749     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1750     EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
1751     EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[2]->InputAt(1)));
1752   }
1753   {
1754     StreamBuilder m(this, MachineType::Float64(), MachineType::Float64(),
1755                     MachineType::Int64(), MachineType::Int64());
1756     Node* const p0 = m.Parameter(0);
1757     Node* const p1 = m.Parameter(1);
1758     Node* const p2 = m.Parameter(2);
1759     Node* add = m.Float64Add(
1760         p0, m.Load(MachineType::Float64(), p1, m.Int32Constant(127)));
1761     Node* sub = m.Float64Sub(
1762         add, m.Load(MachineType::Float64(), p1, m.Int32Constant(127)));
1763     Node* ret = m.Float64Mul(
1764         m.Load(MachineType::Float64(), p2, m.Int32Constant(127)), sub);
1765     m.Return(ret);
1766     Stream s = m.Build();
1767     ASSERT_EQ(3U, s.size());
1768     EXPECT_EQ(kSSEFloat64Add, s[0]->arch_opcode());
1769     ASSERT_EQ(3U, s[0]->InputCount());
1770     EXPECT_EQ(kSSEFloat64Sub, s[1]->arch_opcode());
1771     ASSERT_EQ(3U, s[1]->InputCount());
1772     EXPECT_EQ(kSSEFloat64Mul, s[2]->arch_opcode());
1773     ASSERT_EQ(3U, s[2]->InputCount());
1774     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1775     EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
1776     EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[2]->InputAt(1)));
1777   }
1778 }
1779 
1780 // -----------------------------------------------------------------------------
1781 // Miscellaneous.
1782 
1783 
TEST_F(InstructionSelectorTest,Word64ShlWithChangeInt32ToInt64)1784 TEST_F(InstructionSelectorTest, Word64ShlWithChangeInt32ToInt64) {
1785   TRACED_FORRANGE(int64_t, x, 32, 63) {
1786     StreamBuilder m(this, MachineType::Int64(), MachineType::Int32());
1787     Node* const p0 = m.Parameter(0);
1788     Node* const n = m.Word64Shl(m.ChangeInt32ToInt64(p0), m.Int64Constant(x));
1789     m.Return(n);
1790     Stream s = m.Build();
1791     ASSERT_EQ(1U, s.size());
1792     EXPECT_EQ(kX64Shl, s[0]->arch_opcode());
1793     ASSERT_EQ(2U, s[0]->InputCount());
1794     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1795     EXPECT_EQ(x, s.ToInt32(s[0]->InputAt(1)));
1796     ASSERT_EQ(1U, s[0]->OutputCount());
1797     EXPECT_TRUE(s.IsSameAsFirst(s[0]->Output()));
1798     EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1799   }
1800 }
1801 
1802 
TEST_F(InstructionSelectorTest,Word64ShlWithChangeUint32ToUint64)1803 TEST_F(InstructionSelectorTest, Word64ShlWithChangeUint32ToUint64) {
1804   TRACED_FORRANGE(int64_t, x, 32, 63) {
1805     StreamBuilder m(this, MachineType::Int64(), MachineType::Uint32());
1806     Node* const p0 = m.Parameter(0);
1807     Node* const n = m.Word64Shl(m.ChangeUint32ToUint64(p0), m.Int64Constant(x));
1808     m.Return(n);
1809     Stream s = m.Build();
1810     ASSERT_EQ(1U, s.size());
1811     EXPECT_EQ(kX64Shl, s[0]->arch_opcode());
1812     ASSERT_EQ(2U, s[0]->InputCount());
1813     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1814     EXPECT_EQ(x, s.ToInt32(s[0]->InputAt(1)));
1815     ASSERT_EQ(1U, s[0]->OutputCount());
1816     EXPECT_TRUE(s.IsSameAsFirst(s[0]->Output()));
1817     EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1818   }
1819 }
1820 
TEST_F(InstructionSelectorTest,Word32AndWith0xFF)1821 TEST_F(InstructionSelectorTest, Word32AndWith0xFF) {
1822   {
1823     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
1824     Node* const p0 = m.Parameter(0);
1825     Node* const n = m.Word32And(p0, m.Int32Constant(0xFF));
1826     m.Return(n);
1827     Stream s = m.Build();
1828     ASSERT_EQ(1U, s.size());
1829     EXPECT_EQ(kX64Movzxbl, s[0]->arch_opcode());
1830     ASSERT_EQ(1U, s[0]->InputCount());
1831     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1832     ASSERT_EQ(1U, s[0]->OutputCount());
1833     EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1834   }
1835   {
1836     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
1837     Node* const p0 = m.Parameter(0);
1838     Node* const n = m.Word32And(m.Int32Constant(0xFF), p0);
1839     m.Return(n);
1840     Stream s = m.Build();
1841     ASSERT_EQ(1U, s.size());
1842     EXPECT_EQ(kX64Movzxbl, s[0]->arch_opcode());
1843     ASSERT_EQ(1U, s[0]->InputCount());
1844     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1845     ASSERT_EQ(1U, s[0]->OutputCount());
1846     EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1847   }
1848 }
1849 
TEST_F(InstructionSelectorTest,Word32AndWith0xFFFF)1850 TEST_F(InstructionSelectorTest, Word32AndWith0xFFFF) {
1851   {
1852     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
1853     Node* const p0 = m.Parameter(0);
1854     Node* const n = m.Word32And(p0, m.Int32Constant(0xFFFF));
1855     m.Return(n);
1856     Stream s = m.Build();
1857     ASSERT_EQ(1U, s.size());
1858     EXPECT_EQ(kX64Movzxwl, s[0]->arch_opcode());
1859     ASSERT_EQ(1U, s[0]->InputCount());
1860     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1861     ASSERT_EQ(1U, s[0]->OutputCount());
1862     EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1863   }
1864   {
1865     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
1866     Node* const p0 = m.Parameter(0);
1867     Node* const n = m.Word32And(m.Int32Constant(0xFFFF), p0);
1868     m.Return(n);
1869     Stream s = m.Build();
1870     ASSERT_EQ(1U, s.size());
1871     EXPECT_EQ(kX64Movzxwl, s[0]->arch_opcode());
1872     ASSERT_EQ(1U, s[0]->InputCount());
1873     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1874     ASSERT_EQ(1U, s[0]->OutputCount());
1875     EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1876   }
1877 }
1878 
1879 
TEST_F(InstructionSelectorTest,Word32Clz)1880 TEST_F(InstructionSelectorTest, Word32Clz) {
1881   StreamBuilder m(this, MachineType::Uint32(), MachineType::Uint32());
1882   Node* const p0 = m.Parameter(0);
1883   Node* const n = m.Word32Clz(p0);
1884   m.Return(n);
1885   Stream s = m.Build();
1886   ASSERT_EQ(1U, s.size());
1887   EXPECT_EQ(kX64Lzcnt32, s[0]->arch_opcode());
1888   ASSERT_EQ(1U, s[0]->InputCount());
1889   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1890   ASSERT_EQ(1U, s[0]->OutputCount());
1891   EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
1892 }
1893 
TEST_F(InstructionSelectorTest,LoadAndWord64ShiftRight32)1894 TEST_F(InstructionSelectorTest, LoadAndWord64ShiftRight32) {
1895   {
1896     StreamBuilder m(this, MachineType::Uint64(), MachineType::Uint32());
1897     Node* const p0 = m.Parameter(0);
1898     Node* const load = m.Load(MachineType::Uint64(), p0);
1899     Node* const shift = m.Word64Shr(load, m.Int32Constant(32));
1900     m.Return(shift);
1901     Stream s = m.Build();
1902     ASSERT_EQ(1U, s.size());
1903     EXPECT_EQ(kX64Movl, s[0]->arch_opcode());
1904     ASSERT_EQ(2U, s[0]->InputCount());
1905     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1906     EXPECT_EQ(4, s.ToInt32(s[0]->InputAt(1)));
1907     ASSERT_EQ(1U, s[0]->OutputCount());
1908     EXPECT_EQ(s.ToVreg(shift), s.ToVreg(s[0]->Output()));
1909   }
1910   {
1911     StreamBuilder m(this, MachineType::Int64(), MachineType::Int32());
1912     Node* const p0 = m.Parameter(0);
1913     Node* const load = m.Load(MachineType::Int64(), p0);
1914     Node* const shift = m.Word64Sar(load, m.Int32Constant(32));
1915     m.Return(shift);
1916     Stream s = m.Build();
1917     ASSERT_EQ(1U, s.size());
1918     EXPECT_EQ(kX64Movsxlq, s[0]->arch_opcode());
1919     ASSERT_EQ(2U, s[0]->InputCount());
1920     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1921     EXPECT_EQ(4, s.ToInt32(s[0]->InputAt(1)));
1922     ASSERT_EQ(1U, s[0]->OutputCount());
1923     EXPECT_EQ(s.ToVreg(shift), s.ToVreg(s[0]->Output()));
1924   }
1925   {
1926     StreamBuilder m(this, MachineType::Int64(), MachineType::Int32());
1927     Node* const p0 = m.Parameter(0);
1928     Node* const load = m.Load(MachineType::Int64(), p0);
1929     Node* const shift = m.Word64Sar(load, m.Int32Constant(32));
1930     Node* const truncate = m.TruncateInt64ToInt32(shift);
1931     m.Return(truncate);
1932     Stream s = m.Build();
1933     ASSERT_EQ(1U, s.size());
1934     EXPECT_EQ(kX64Movl, s[0]->arch_opcode());
1935     ASSERT_EQ(2U, s[0]->InputCount());
1936     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
1937     EXPECT_EQ(4, s.ToInt32(s[0]->InputAt(1)));
1938     ASSERT_EQ(1U, s[0]->OutputCount());
1939     EXPECT_EQ(s.ToVreg(shift), s.ToVreg(s[0]->Output()));
1940   }
1941 }
1942 
1943 // -----------------------------------------------------------------------------
1944 // SIMD.
1945 
TEST_F(InstructionSelectorTest,SIMDSplatZero)1946 TEST_F(InstructionSelectorTest, SIMDSplatZero) {
1947   // Test optimization for splat of contant 0.
1948   // {i8x16,i16x8,i32x4,i64x2}.splat(const(0)) -> v128.zero().
1949   // Optimizations for f32x4.splat and f64x2.splat not implemented since it
1950   // doesn't improve the codegen as much (same number of instructions).
1951   {
1952     StreamBuilder m(this, MachineType::Simd128());
1953     Node* const splat = m.I64x2Splat(m.Int64Constant(0));
1954     m.Return(splat);
1955     Stream s = m.Build();
1956     ASSERT_EQ(1U, s.size());
1957     EXPECT_EQ(kX64S128Zero, s[0]->arch_opcode());
1958     ASSERT_EQ(0U, s[0]->InputCount());
1959     EXPECT_EQ(1U, s[0]->OutputCount());
1960   }
1961   {
1962     StreamBuilder m(this, MachineType::Simd128());
1963     Node* const splat = m.I32x4Splat(m.Int32Constant(0));
1964     m.Return(splat);
1965     Stream s = m.Build();
1966     ASSERT_EQ(1U, s.size());
1967     EXPECT_EQ(kX64S128Zero, s[0]->arch_opcode());
1968     ASSERT_EQ(0U, s[0]->InputCount());
1969     EXPECT_EQ(1U, s[0]->OutputCount());
1970   }
1971   {
1972     StreamBuilder m(this, MachineType::Simd128());
1973     Node* const splat = m.I16x8Splat(m.Int32Constant(0));
1974     m.Return(splat);
1975     Stream s = m.Build();
1976     ASSERT_EQ(1U, s.size());
1977     EXPECT_EQ(kX64S128Zero, s[0]->arch_opcode());
1978     ASSERT_EQ(0U, s[0]->InputCount());
1979     EXPECT_EQ(1U, s[0]->OutputCount());
1980   }
1981   {
1982     StreamBuilder m(this, MachineType::Simd128());
1983     Node* const splat = m.I8x16Splat(m.Int32Constant(0));
1984     m.Return(splat);
1985     Stream s = m.Build();
1986     ASSERT_EQ(1U, s.size());
1987     EXPECT_EQ(kX64S128Zero, s[0]->arch_opcode());
1988     ASSERT_EQ(0U, s[0]->InputCount());
1989     EXPECT_EQ(1U, s[0]->OutputCount());
1990   }
1991 }
1992 
1993 #if V8_ENABLE_WEBASSEMBLY
1994 struct ArchShuffle {
1995   uint8_t shuffle[kSimd128Size];
1996   ArchOpcode arch_opcode;
1997   size_t input_count;
1998 };
1999 
2000 static constexpr ArchShuffle kArchShuffles[] = {
2001     // These are architecture specific shuffles defined in
2002     // instruction-selecor-x64.cc arch_shuffles.
2003     {
2004         {0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, 20, 21, 22, 23},
2005         kX64S64x2UnpackLow,
2006         2,
2007     },
2008     {
2009         {8, 9, 10, 11, 12, 13, 14, 15, 24, 25, 26, 27, 28, 29, 30, 31},
2010         kX64S64x2UnpackHigh,
2011         2,
2012     },
2013     {
2014         {0, 1, 2, 3, 16, 17, 18, 19, 4, 5, 6, 7, 20, 21, 22, 23},
2015         kX64S32x4UnpackLow,
2016         2,
2017     },
2018     {
2019         {8, 9, 10, 11, 24, 25, 26, 27, 12, 13, 14, 15, 28, 29, 30, 31},
2020         kX64S32x4UnpackHigh,
2021         2,
2022     },
2023     {
2024         {0, 1, 16, 17, 2, 3, 18, 19, 4, 5, 20, 21, 6, 7, 22, 23},
2025         kX64S16x8UnpackLow,
2026         2,
2027     },
2028     {
2029         {8, 9, 24, 25, 10, 11, 26, 27, 12, 13, 28, 29, 14, 15, 30, 31},
2030         kX64S16x8UnpackHigh,
2031         2,
2032     },
2033     {
2034         {0, 16, 1, 17, 2, 18, 3, 19, 4, 20, 5, 21, 6, 22, 7, 23},
2035         kX64S8x16UnpackLow,
2036         2,
2037     },
2038     {
2039         {8, 24, 9, 25, 10, 26, 11, 27, 12, 28, 13, 29, 14, 30, 15, 31},
2040         kX64S8x16UnpackHigh,
2041         2,
2042     },
2043     {
2044         {0, 1, 4, 5, 8, 9, 12, 13, 16, 17, 20, 21, 24, 25, 28, 29},
2045         kX64S16x8UnzipLow,
2046         2,
2047     },
2048     {
2049         {2, 3, 6, 7, 10, 11, 14, 15, 18, 19, 22, 23, 26, 27, 30, 31},
2050         kX64S16x8UnzipHigh,
2051         2,
2052     },
2053     {
2054         {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30},
2055         kX64S8x16UnzipLow,
2056         2,
2057     },
2058     {
2059         {1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31},
2060         kX64S8x16UnzipHigh,
2061         2,
2062     },
2063     {
2064         {0, 16, 2, 18, 4, 20, 6, 22, 8, 24, 10, 26, 12, 28, 14, 30},
2065         kX64S8x16TransposeLow,
2066         2,
2067     },
2068     {
2069         {1, 17, 3, 19, 5, 21, 7, 23, 9, 25, 11, 27, 13, 29, 15, 31},
2070         kX64S8x16TransposeHigh,
2071         2,
2072     },
2073     {
2074         {7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8},
2075         kX64S8x8Reverse,
2076         1,
2077     },
2078     {
2079         {3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12},
2080         kX64S8x4Reverse,
2081         1,
2082     },
2083     {
2084         {1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 13, 12, 15, 14},
2085         kX64S8x2Reverse,
2086         1,
2087     },
2088     // These are matched by TryMatchConcat && TryMatch32x4Rotate.
2089     {
2090         {4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3},
2091         kX64S32x4Rotate,
2092         2,
2093     },
2094     {
2095         {8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7},
2096         kX64S32x4Rotate,
2097         2,
2098     },
2099     {
2100         {12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11},
2101         kX64S32x4Rotate,
2102         2,
2103     },
2104     // These are matched by TryMatchConcat && !TryMatch32x4Rotate.
2105     {
2106         {3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2},
2107         kX64S8x16Alignr,
2108         3,
2109     },
2110     {
2111         {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1},
2112         kX64S8x16Alignr,
2113         3,
2114     },
2115     {
2116         {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17},
2117         kX64S8x16Alignr,
2118         3,
2119     },
2120     // These are matched by TryMatch32x4Shuffle && is_swizzle.
2121     {
2122         {0, 1, 2, 3, 8, 9, 10, 11, 4, 5, 6, 7, 12, 13, 14, 15},
2123         kX64S32x4Swizzle,
2124         2,
2125     },
2126     {
2127         {0, 1, 2, 3, 4, 5, 6, 7, 12, 13, 14, 15, 8, 9, 10, 11},
2128         kX64S32x4Swizzle,
2129         2,
2130     },
2131     // These are matched by TryMatch32x4Shuffle && !is_swizzle && TryMatchBlend.
2132     {
2133         {0, 1, 2, 3, 20, 21, 22, 23, 8, 9, 10, 11, 28, 29, 30, 31},
2134         kX64S16x8Blend,
2135         3,
2136     },
2137     {
2138         {16, 17, 18, 19, 4, 5, 6, 7, 24, 25, 26, 27, 12, 13, 14, 15},
2139         kX64S16x8Blend,
2140         3,
2141     },
2142     // These are matched by TryMatch32x4Shuffle && !is_swizzle &&
2143     // TryMatchShufps.
2144     {
2145         {0, 1, 2, 3, 8, 9, 10, 11, 28, 29, 30, 31, 28, 29, 30, 31},
2146         kX64Shufps,
2147         3,
2148     },
2149     {
2150         {8, 9, 10, 11, 0, 1, 2, 3, 28, 29, 30, 31, 28, 29, 30, 31},
2151         kX64Shufps,
2152         3,
2153     },
2154     // These are matched by TryMatch32x4Shuffle && !is_swizzle.
2155     {
2156         {28, 29, 30, 31, 0, 1, 2, 3, 28, 29, 30, 31, 28, 29, 30, 31},
2157         kX64S32x4Shuffle,
2158         4,
2159     },
2160     // These are matched by TryMatch16x8Shuffle && TryMatchBlend.
2161     {
2162         {16, 17, 2, 3, 4, 5, 6, 7, 24, 25, 26, 27, 12, 13, 14, 15},
2163         kX64S16x8Blend,
2164         3,
2165     },
2166     // These are matched by TryMatch16x8Shuffle && TryMatchSplat<8>.
2167     {
2168         {2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3},
2169         kX64S16x8Dup,
2170         2,
2171     },
2172     // These are matched by TryMatch16x8Shuffle && TryMatch16x8HalfShuffle.
2173     {
2174         {6, 7, 4, 5, 2, 3, 0, 1, 14, 15, 12, 13, 10, 11, 8, 9},
2175         kX64S16x8HalfShuffle1,
2176         3,
2177     },
2178     {
2179         {6, 7, 4, 5, 2, 3, 0, 1, 30, 31, 28, 29, 26, 27, 24, 25},
2180         kX64S16x8HalfShuffle2,
2181         5,
2182     },
2183     // These are matched by TryMatchSplat<16>.
2184     {
2185         {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
2186         kX64S8x16Dup,
2187         2,
2188     },
2189     // Generic shuffle that only uses 1 input.
2190     {
2191         {1, 15, 2, 14, 3, 13, 4, 12, 5, 11, 6, 10, 7, 9, 8},
2192         kX64I8x16Shuffle,
2193         5,
2194     },
2195     // Generic shuffle that uses both input.
2196     {
2197         {1, 31, 2, 14, 3, 13, 4, 12, 5, 11, 6, 10, 7, 9, 8},
2198         kX64I8x16Shuffle,
2199         6,
2200     },
2201 };
2202 
2203 using InstructionSelectorSIMDArchShuffleTest =
2204     InstructionSelectorTestWithParam<ArchShuffle>;
2205 
TEST_P(InstructionSelectorSIMDArchShuffleTest,SIMDArchShuffle)2206 TEST_P(InstructionSelectorSIMDArchShuffleTest, SIMDArchShuffle) {
2207   MachineType type = MachineType::Simd128();
2208   {
2209     // Tests various shuffle optimizations
2210     StreamBuilder m(this, type, type, type);
2211     auto param = GetParam();
2212     auto shuffle = param.shuffle;
2213     const Operator* op = m.machine()->I8x16Shuffle(shuffle);
2214     Node* n = m.AddNode(op, m.Parameter(0), m.Parameter(1));
2215     m.Return(n);
2216     Stream s = m.Build();
2217     ASSERT_EQ(1U, s.size());
2218     EXPECT_EQ(param.arch_opcode, s[0]->arch_opcode());
2219     ASSERT_EQ(param.input_count, s[0]->InputCount());
2220     EXPECT_EQ(1U, s[0]->OutputCount());
2221   }
2222 }
2223 
2224 INSTANTIATE_TEST_SUITE_P(InstructionSelectorTest,
2225                          InstructionSelectorSIMDArchShuffleTest,
2226                          ::testing::ValuesIn(kArchShuffles));
2227 #endif  // V8_ENABLE_WEBASSEMBLY
2228 
2229 struct SwizzleConstants {
2230   uint8_t shuffle[kSimd128Size];
2231   bool omit_add;
2232 };
2233 
2234 static constexpr SwizzleConstants kSwizzleConstants[] = {
2235     {
2236         // all lanes < kSimd128Size
2237         {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
2238         true,
2239     },
2240     {
2241         // lanes that are >= kSimd128Size have top bit set
2242         {12, 13, 14, 15, 0x90, 0x91, 0x92, 0x93, 0xA0, 0xA1, 0xA2, 0xA3, 0xFC,
2243          0xFD, 0xFE, 0xFF},
2244         true,
2245     },
2246     {
2247         {12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27},
2248         false,
2249     },
2250 };
2251 
2252 using InstructionSelectorSIMDSwizzleConstantTest =
2253     InstructionSelectorTestWithParam<SwizzleConstants>;
2254 
TEST_P(InstructionSelectorSIMDSwizzleConstantTest,SimdSwizzleConstant)2255 TEST_P(InstructionSelectorSIMDSwizzleConstantTest, SimdSwizzleConstant) {
2256   // Test optimization of swizzle with constant indices.
2257   auto param = GetParam();
2258   StreamBuilder m(this, MachineType::Simd128(), MachineType::Simd128());
2259   Node* const c = m.S128Const(param.shuffle);
2260   Node* swizzle = m.AddNode(m.machine()->I8x16Swizzle(), m.Parameter(0), c);
2261   m.Return(swizzle);
2262   Stream s = m.Build();
2263   ASSERT_EQ(2U, s.size());
2264   ASSERT_EQ(kX64I8x16Swizzle, s[1]->arch_opcode());
2265   ASSERT_EQ(param.omit_add, s[1]->misc());
2266   ASSERT_EQ(1U, s[0]->OutputCount());
2267 }
2268 
2269 INSTANTIATE_TEST_SUITE_P(InstructionSelectorTest,
2270                          InstructionSelectorSIMDSwizzleConstantTest,
2271                          ::testing::ValuesIn(kSwizzleConstants));
2272 
TEST_F(InstructionSelectorTest,F64x2PromoteLowF32x4WithS128Load64Zero)2273 TEST_F(InstructionSelectorTest, F64x2PromoteLowF32x4WithS128Load64Zero) {
2274   StreamBuilder m(this, MachineType::Simd128(), MachineType::Int32());
2275   Node* const load =
2276       m.AddNode(m.machine()->LoadTransform(MemoryAccessKind::kProtected,
2277                                            LoadTransformation::kS128Load64Zero),
2278                 m.Int32Constant(2), m.Parameter(0));
2279   Node* const promote = m.AddNode(m.machine()->F64x2PromoteLowF32x4(), load);
2280   m.Return(promote);
2281   Stream s = m.Build();
2282   ASSERT_EQ(1U, s.size());
2283   ASSERT_EQ(kX64F64x2PromoteLowF32x4, s[0]->arch_opcode());
2284   ASSERT_EQ(kMode_MRI, s[0]->addressing_mode());
2285   EXPECT_EQ(2U, s[0]->InputCount());
2286   EXPECT_EQ(1U, s[0]->OutputCount());
2287 }
2288 
2289 }  // namespace compiler
2290 }  // namespace internal
2291 }  // namespace v8
2292