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