LCOV - code coverage report
Current view: top level - test/unittests/compiler/x64 - instruction-selector-x64-unittest.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 1160 1160 100.0 %
Date: 2019-01-20 Functions: 173 252 68.7 %

          Line data    Source code
       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/backend/instruction-selector-unittest.h"
       6             : 
       7             : #include "src/compiler/node-matchers.h"
       8             : #include "src/objects-inl.h"
       9             : 
      10             : namespace v8 {
      11             : namespace internal {
      12             : namespace compiler {
      13             : 
      14             : // -----------------------------------------------------------------------------
      15             : // Conversions.
      16             : 
      17             : 
      18       15128 : TEST_F(InstructionSelectorTest, ChangeFloat32ToFloat64WithParameter) {
      19           1 :   StreamBuilder m(this, MachineType::Float32(), MachineType::Float64());
      20           1 :   m.Return(m.ChangeFloat32ToFloat64(m.Parameter(0)));
      21           1 :   Stream s = m.Build();
      22           3 :   ASSERT_EQ(1U, s.size());
      23           3 :   EXPECT_EQ(kSSEFloat32ToFloat64, s[0]->arch_opcode());
      24           3 :   EXPECT_EQ(1U, s[0]->InputCount());
      25           3 :   EXPECT_EQ(1U, s[0]->OutputCount());
      26             : }
      27             : 
      28             : 
      29       15128 : TEST_F(InstructionSelectorTest, ChangeInt32ToInt64WithParameter) {
      30           1 :   StreamBuilder m(this, MachineType::Int64(), MachineType::Int32());
      31           1 :   m.Return(m.ChangeInt32ToInt64(m.Parameter(0)));
      32           1 :   Stream s = m.Build();
      33           3 :   ASSERT_EQ(1U, s.size());
      34           3 :   EXPECT_EQ(kX64Movsxlq, s[0]->arch_opcode());
      35             : }
      36             : 
      37       15128 : TEST_F(InstructionSelectorTest, ChangeUint32ToFloat64WithParameter) {
      38           1 :   StreamBuilder m(this, MachineType::Float64(), MachineType::Uint32());
      39           1 :   m.Return(m.ChangeUint32ToFloat64(m.Parameter(0)));
      40           1 :   Stream s = m.Build();
      41           3 :   ASSERT_EQ(1U, s.size());
      42           3 :   EXPECT_EQ(kSSEUint32ToFloat64, s[0]->arch_opcode());
      43             : }
      44             : 
      45             : 
      46       15128 : TEST_F(InstructionSelectorTest, ChangeUint32ToUint64WithParameter) {
      47           1 :   StreamBuilder m(this, MachineType::Uint64(), MachineType::Uint32());
      48           1 :   m.Return(m.ChangeUint32ToUint64(m.Parameter(0)));
      49           1 :   Stream s = m.Build();
      50           3 :   ASSERT_EQ(1U, s.size());
      51           3 :   EXPECT_EQ(kX64Movl, s[0]->arch_opcode());
      52             : }
      53             : 
      54             : 
      55       15128 : TEST_F(InstructionSelectorTest, TruncateFloat64ToFloat32WithParameter) {
      56           1 :   StreamBuilder m(this, MachineType::Float64(), MachineType::Float32());
      57           1 :   m.Return(m.TruncateFloat64ToFloat32(m.Parameter(0)));
      58           1 :   Stream s = m.Build();
      59           3 :   ASSERT_EQ(1U, s.size());
      60           3 :   EXPECT_EQ(kSSEFloat64ToFloat32, s[0]->arch_opcode());
      61           3 :   EXPECT_EQ(1U, s[0]->InputCount());
      62           3 :   EXPECT_EQ(1U, s[0]->OutputCount());
      63             : }
      64             : 
      65             : 
      66       15128 : TEST_F(InstructionSelectorTest, TruncateInt64ToInt32WithParameter) {
      67           1 :   StreamBuilder m(this, MachineType::Int32(), MachineType::Int64());
      68           1 :   m.Return(m.TruncateInt64ToInt32(m.Parameter(0)));
      69           1 :   Stream s = m.Build();
      70           3 :   ASSERT_EQ(1U, s.size());
      71           3 :   EXPECT_EQ(kX64Movl, s[0]->arch_opcode());
      72             : }
      73             : 
      74             : namespace {
      75             : struct LoadWithToInt64Extension {
      76             :   MachineType type;
      77             :   ArchOpcode expected_opcode;
      78             : };
      79             : 
      80             : std::ostream& operator<<(std::ostream& os,
      81             :                          const LoadWithToInt64Extension& i32toi64) {
      82       15125 :   return os << i32toi64.type;
      83             : }
      84             : 
      85             : static const LoadWithToInt64Extension kLoadWithToInt64Extensions[] = {
      86             :     {MachineType::Int8(), kX64Movsxbq},
      87             :     {MachineType::Uint8(), kX64Movzxbq},
      88             :     {MachineType::Int16(), kX64Movsxwq},
      89             :     {MachineType::Uint16(), kX64Movzxwq},
      90             :     {MachineType::Int32(), kX64Movsxlq}};
      91             : 
      92             : }  // namespace
      93             : 
      94             : typedef InstructionSelectorTestWithParam<LoadWithToInt64Extension>
      95             :     InstructionSelectorChangeInt32ToInt64Test;
      96             : 
      97       18170 : TEST_P(InstructionSelectorChangeInt32ToInt64Test, ChangeInt32ToInt64WithLoad) {
      98           5 :   const LoadWithToInt64Extension extension = GetParam();
      99           5 :   StreamBuilder m(this, MachineType::Int64(), MachineType::Pointer());
     100           5 :   m.Return(m.ChangeInt32ToInt64(m.Load(extension.type, m.Parameter(0))));
     101           5 :   Stream s = m.Build();
     102          15 :   ASSERT_EQ(1U, s.size());
     103          15 :   EXPECT_EQ(extension.expected_opcode, s[0]->arch_opcode());
     104             : }
     105             : 
     106       36300 : INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
     107             :                         InstructionSelectorChangeInt32ToInt64Test,
     108             :                         ::testing::ValuesIn(kLoadWithToInt64Extensions));
     109             : 
     110             : // -----------------------------------------------------------------------------
     111             : // Loads and stores
     112             : 
     113             : 
     114             : namespace {
     115             : 
     116             : struct MemoryAccess {
     117             :   MachineType type;
     118             :   ArchOpcode load_opcode;
     119             :   ArchOpcode store_opcode;
     120             : };
     121             : 
     122             : 
     123             : std::ostream& operator<<(std::ostream& os, const MemoryAccess& memacc) {
     124       60500 :   return os << memacc.type;
     125             : }
     126             : 
     127             : 
     128             : static const MemoryAccess kMemoryAccesses[] = {
     129             :     {MachineType::Int8(), kX64Movsxbl, kX64Movb},
     130             :     {MachineType::Uint8(), kX64Movzxbl, kX64Movb},
     131             :     {MachineType::Int16(), kX64Movsxwl, kX64Movw},
     132             :     {MachineType::Uint16(), kX64Movzxwl, kX64Movw},
     133             :     {MachineType::Int32(), kX64Movl, kX64Movl},
     134             :     {MachineType::Uint32(), kX64Movl, kX64Movl},
     135             :     {MachineType::Int64(), kX64Movq, kX64Movq},
     136             :     {MachineType::Uint64(), kX64Movq, kX64Movq},
     137             :     {MachineType::Float32(), kX64Movss, kX64Movss},
     138             :     {MachineType::Float64(), kX64Movsd, kX64Movsd}};
     139             : 
     140             : }  // namespace
     141             : 
     142             : 
     143             : typedef InstructionSelectorTestWithParam<MemoryAccess>
     144             :     InstructionSelectorMemoryAccessTest;
     145             : 
     146             : 
     147       18190 : TEST_P(InstructionSelectorMemoryAccessTest, LoadWithParameters) {
     148          10 :   const MemoryAccess memacc = GetParam();
     149             :   StreamBuilder m(this, memacc.type, MachineType::Pointer(),
     150          10 :                   MachineType::Int32());
     151          10 :   m.Return(m.Load(memacc.type, m.Parameter(0), m.Parameter(1)));
     152          10 :   Stream s = m.Build();
     153          30 :   ASSERT_EQ(1U, s.size());
     154          30 :   EXPECT_EQ(memacc.load_opcode, s[0]->arch_opcode());
     155          30 :   EXPECT_EQ(2U, s[0]->InputCount());
     156          30 :   EXPECT_EQ(1U, s[0]->OutputCount());
     157             : }
     158             : 
     159             : 
     160       18190 : TEST_P(InstructionSelectorMemoryAccessTest, StoreWithParameters) {
     161          10 :   const MemoryAccess memacc = GetParam();
     162             :   StreamBuilder m(this, MachineType::Int32(), MachineType::Pointer(),
     163          10 :                   MachineType::Int32(), memacc.type);
     164             :   m.Store(memacc.type.representation(), m.Parameter(0), m.Parameter(1),
     165          10 :           m.Parameter(2), kNoWriteBarrier);
     166          10 :   m.Return(m.Int32Constant(0));
     167          10 :   Stream s = m.Build();
     168          30 :   ASSERT_EQ(1U, s.size());
     169          30 :   EXPECT_EQ(memacc.store_opcode, s[0]->arch_opcode());
     170          30 :   EXPECT_EQ(3U, s[0]->InputCount());
     171          30 :   EXPECT_EQ(0U, s[0]->OutputCount());
     172             : }
     173             : 
     174             : 
     175       87725 : INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
     176             :                         InstructionSelectorMemoryAccessTest,
     177             :                         ::testing::ValuesIn(kMemoryAccesses));
     178             : 
     179             : 
     180             : // -----------------------------------------------------------------------------
     181             : // ChangeUint32ToUint64.
     182             : 
     183             : 
     184             : namespace {
     185             : 
     186             : typedef Node* (RawMachineAssembler::*Constructor)(Node*, Node*);
     187             : 
     188             : 
     189             : struct BinaryOperation {
     190             :   Constructor constructor;
     191             :   const char* constructor_name;
     192             : };
     193             : 
     194             : 
     195             : std::ostream& operator<<(std::ostream& os, const BinaryOperation& bop) {
     196       60500 :   return os << bop.constructor_name;
     197             : }
     198             : 
     199             : 
     200             : const BinaryOperation kWord32BinaryOperations[] = {
     201             :     {&RawMachineAssembler::Word32And, "Word32And"},
     202             :     {&RawMachineAssembler::Word32Or, "Word32Or"},
     203             :     {&RawMachineAssembler::Word32Xor, "Word32Xor"},
     204             :     {&RawMachineAssembler::Word32Shl, "Word32Shl"},
     205             :     {&RawMachineAssembler::Word32Shr, "Word32Shr"},
     206             :     {&RawMachineAssembler::Word32Sar, "Word32Sar"},
     207             :     {&RawMachineAssembler::Word32Ror, "Word32Ror"},
     208             :     {&RawMachineAssembler::Word32Equal, "Word32Equal"},
     209             :     {&RawMachineAssembler::Int32Add, "Int32Add"},
     210             :     {&RawMachineAssembler::Int32Sub, "Int32Sub"},
     211             :     {&RawMachineAssembler::Int32Mul, "Int32Mul"},
     212             :     {&RawMachineAssembler::Int32MulHigh, "Int32MulHigh"},
     213             :     {&RawMachineAssembler::Int32Div, "Int32Div"},
     214             :     {&RawMachineAssembler::Int32LessThan, "Int32LessThan"},
     215             :     {&RawMachineAssembler::Int32LessThanOrEqual, "Int32LessThanOrEqual"},
     216             :     {&RawMachineAssembler::Int32Mod, "Int32Mod"},
     217             :     {&RawMachineAssembler::Uint32Div, "Uint32Div"},
     218             :     {&RawMachineAssembler::Uint32LessThan, "Uint32LessThan"},
     219             :     {&RawMachineAssembler::Uint32LessThanOrEqual, "Uint32LessThanOrEqual"},
     220             :     {&RawMachineAssembler::Uint32Mod, "Uint32Mod"}};
     221             : 
     222             : }  // namespace
     223             : 
     224             : 
     225             : typedef InstructionSelectorTestWithParam<BinaryOperation>
     226             :     InstructionSelectorChangeUint32ToUint64Test;
     227             : 
     228             : 
     229       18230 : TEST_P(InstructionSelectorChangeUint32ToUint64Test, ChangeUint32ToUint64) {
     230          20 :   const BinaryOperation& bop = GetParam();
     231             :   StreamBuilder m(this, MachineType::Uint64(), MachineType::Int32(),
     232          20 :                   MachineType::Int32());
     233          20 :   Node* const p0 = m.Parameter(0);
     234          20 :   Node* const p1 = m.Parameter(1);
     235          20 :   m.Return(m.ChangeUint32ToUint64((m.*bop.constructor)(p0, p1)));
     236          20 :   Stream s = m.Build();
     237          60 :   ASSERT_EQ(1U, s.size());
     238             : }
     239             : 
     240             : 
     241       81675 : INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
     242             :                         InstructionSelectorChangeUint32ToUint64Test,
     243             :                         ::testing::ValuesIn(kWord32BinaryOperations));
     244             : 
     245             : // -----------------------------------------------------------------------------
     246             : // CanElideChangeUint32ToUint64
     247             : 
     248             : namespace {
     249             : 
     250             : template <typename T>
     251             : struct MachInst {
     252             :   T constructor;
     253             :   const char* constructor_name;
     254             :   ArchOpcode arch_opcode;
     255             :   MachineType machine_type;
     256             : };
     257             : 
     258             : typedef MachInst<Node* (RawMachineAssembler::*)(Node*, Node*)> MachInst2;
     259             : 
     260             : // X64 instructions that clear the top 32 bits of the destination.
     261             : const MachInst2 kCanElideChangeUint32ToUint64[] = {
     262             :     {&RawMachineAssembler::Word32And, "Word32And", kX64And32,
     263             :      MachineType::Uint32()},
     264             :     {&RawMachineAssembler::Word32Or, "Word32Or", kX64Or32,
     265             :      MachineType::Uint32()},
     266             :     {&RawMachineAssembler::Word32Xor, "Word32Xor", kX64Xor32,
     267             :      MachineType::Uint32()},
     268             :     {&RawMachineAssembler::Word32Shl, "Word32Shl", kX64Shl32,
     269             :      MachineType::Uint32()},
     270             :     {&RawMachineAssembler::Word32Shr, "Word32Shr", kX64Shr32,
     271             :      MachineType::Uint32()},
     272             :     {&RawMachineAssembler::Word32Sar, "Word32Sar", kX64Sar32,
     273             :      MachineType::Uint32()},
     274             :     {&RawMachineAssembler::Word32Ror, "Word32Ror", kX64Ror32,
     275             :      MachineType::Uint32()},
     276             :     {&RawMachineAssembler::Word32Equal, "Word32Equal", kX64Cmp32,
     277             :      MachineType::Uint32()},
     278             :     {&RawMachineAssembler::Int32Add, "Int32Add", kX64Lea32,
     279             :      MachineType::Int32()},
     280             :     {&RawMachineAssembler::Int32Sub, "Int32Sub", kX64Sub32,
     281             :      MachineType::Int32()},
     282             :     {&RawMachineAssembler::Int32Mul, "Int32Mul", kX64Imul32,
     283             :      MachineType::Int32()},
     284             :     {&RawMachineAssembler::Int32MulHigh, "Int32MulHigh", kX64ImulHigh32,
     285             :      MachineType::Int32()},
     286             :     {&RawMachineAssembler::Int32Div, "Int32Div", kX64Idiv32,
     287             :      MachineType::Int32()},
     288             :     {&RawMachineAssembler::Int32LessThan, "Int32LessThan", kX64Cmp32,
     289             :      MachineType::Int32()},
     290             :     {&RawMachineAssembler::Int32LessThanOrEqual, "Int32LessThanOrEqual",
     291             :      kX64Cmp32, MachineType::Int32()},
     292             :     {&RawMachineAssembler::Int32Mod, "Int32Mod", kX64Idiv32,
     293             :      MachineType::Int32()},
     294             :     {&RawMachineAssembler::Uint32Div, "Uint32Div", kX64Udiv32,
     295             :      MachineType::Uint32()},
     296             :     {&RawMachineAssembler::Uint32LessThan, "Uint32LessThan", kX64Cmp32,
     297             :      MachineType::Uint32()},
     298             :     {&RawMachineAssembler::Uint32LessThanOrEqual, "Uint32LessThanOrEqual",
     299             :      kX64Cmp32, MachineType::Uint32()},
     300             :     {&RawMachineAssembler::Uint32Mod, "Uint32Mod", kX64Udiv32,
     301             :      MachineType::Uint32()},
     302             : };
     303             : 
     304             : }  // namespace
     305             : 
     306             : typedef InstructionSelectorTestWithParam<MachInst2>
     307             :     InstructionSelectorElidedChangeUint32ToUint64Test;
     308             : 
     309       18230 : TEST_P(InstructionSelectorElidedChangeUint32ToUint64Test, Parameter) {
     310          20 :   const MachInst2 binop = GetParam();
     311             :   StreamBuilder m(this, MachineType::Uint64(), binop.machine_type,
     312          20 :                   binop.machine_type);
     313             :   m.Return(m.ChangeUint32ToUint64(
     314          20 :       (m.*binop.constructor)(m.Parameter(0), m.Parameter(1))));
     315          20 :   Stream s = m.Build();
     316             :   // Make sure the `ChangeUint32ToUint64` node turned into a no-op.
     317          60 :   ASSERT_EQ(1U, s.size());
     318          60 :   EXPECT_EQ(binop.arch_opcode, s[0]->arch_opcode());
     319          60 :   EXPECT_EQ(2U, s[0]->InputCount());
     320          60 :   EXPECT_EQ(1U, s[0]->OutputCount());
     321             : }
     322             : 
     323       81675 : INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
     324             :                         InstructionSelectorElidedChangeUint32ToUint64Test,
     325             :                         ::testing::ValuesIn(kCanElideChangeUint32ToUint64));
     326             : 
     327             : // ChangeUint32ToUint64AfterLoad
     328       15128 : TEST_F(InstructionSelectorTest, ChangeUint32ToUint64AfterLoad) {
     329             :   // For each case, make sure the `ChangeUint32ToUint64` node turned into a
     330             :   // no-op.
     331             : 
     332             :   // movzxbl
     333             :   {
     334             :     StreamBuilder m(this, MachineType::Uint64(), MachineType::Pointer(),
     335           1 :                     MachineType::Int32());
     336             :     m.Return(m.ChangeUint32ToUint64(
     337           1 :         m.Load(MachineType::Uint8(), m.Parameter(0), m.Parameter(1))));
     338           1 :     Stream s = m.Build();
     339           2 :     ASSERT_EQ(1U, s.size());
     340           3 :     EXPECT_EQ(kX64Movzxbl, s[0]->arch_opcode());
     341           3 :     EXPECT_EQ(kMode_MR1, s[0]->addressing_mode());
     342           3 :     EXPECT_EQ(2U, s[0]->InputCount());
     343           3 :     EXPECT_EQ(1U, s[0]->OutputCount());
     344             :   }
     345             :   // movsxbl
     346             :   {
     347             :     StreamBuilder m(this, MachineType::Uint64(), MachineType::Pointer(),
     348           1 :                     MachineType::Int32());
     349             :     m.Return(m.ChangeUint32ToUint64(
     350           1 :         m.Load(MachineType::Int8(), m.Parameter(0), m.Parameter(1))));
     351           1 :     Stream s = m.Build();
     352           2 :     ASSERT_EQ(1U, s.size());
     353           3 :     EXPECT_EQ(kX64Movsxbl, s[0]->arch_opcode());
     354           3 :     EXPECT_EQ(kMode_MR1, s[0]->addressing_mode());
     355           3 :     EXPECT_EQ(2U, s[0]->InputCount());
     356           3 :     EXPECT_EQ(1U, s[0]->OutputCount());
     357             :   }
     358             :   // movzxwl
     359             :   {
     360             :     StreamBuilder m(this, MachineType::Uint64(), MachineType::Pointer(),
     361           1 :                     MachineType::Int32());
     362             :     m.Return(m.ChangeUint32ToUint64(
     363           1 :         m.Load(MachineType::Uint16(), m.Parameter(0), m.Parameter(1))));
     364           1 :     Stream s = m.Build();
     365           2 :     ASSERT_EQ(1U, s.size());
     366           3 :     EXPECT_EQ(kX64Movzxwl, s[0]->arch_opcode());
     367           3 :     EXPECT_EQ(kMode_MR1, s[0]->addressing_mode());
     368           3 :     EXPECT_EQ(2U, s[0]->InputCount());
     369           2 :     EXPECT_EQ(1U, s[0]->OutputCount());
     370             :   }
     371             :   // movsxwl
     372             :   {
     373             :     StreamBuilder m(this, MachineType::Uint64(), MachineType::Pointer(),
     374           1 :                     MachineType::Int32());
     375             :     m.Return(m.ChangeUint32ToUint64(
     376           1 :         m.Load(MachineType::Int16(), m.Parameter(0), m.Parameter(1))));
     377           1 :     Stream s = m.Build();
     378           2 :     ASSERT_EQ(1U, s.size());
     379           3 :     EXPECT_EQ(kX64Movsxwl, s[0]->arch_opcode());
     380           3 :     EXPECT_EQ(kMode_MR1, s[0]->addressing_mode());
     381           3 :     EXPECT_EQ(2U, s[0]->InputCount());
     382           3 :     EXPECT_EQ(1U, s[0]->OutputCount());
     383             :   }
     384             : }
     385             : 
     386             : // -----------------------------------------------------------------------------
     387             : // TruncateInt64ToInt32.
     388             : 
     389             : 
     390       15128 : TEST_F(InstructionSelectorTest, TruncateInt64ToInt32WithWord64Sar) {
     391           1 :   StreamBuilder m(this, MachineType::Int32(), MachineType::Int64());
     392           1 :   Node* const p = m.Parameter(0);
     393           1 :   Node* const t = m.TruncateInt64ToInt32(m.Word64Sar(p, m.Int64Constant(32)));
     394           1 :   m.Return(t);
     395           1 :   Stream s = m.Build();
     396           2 :   ASSERT_EQ(1U, s.size());
     397           3 :   EXPECT_EQ(kX64Shr, s[0]->arch_opcode());
     398           3 :   ASSERT_EQ(2U, s[0]->InputCount());
     399           3 :   EXPECT_EQ(s.ToVreg(p), s.ToVreg(s[0]->InputAt(0)));
     400           4 :   EXPECT_EQ(32, s.ToInt32(s[0]->InputAt(1)));
     401           3 :   ASSERT_EQ(1U, s[0]->OutputCount());
     402           2 :   EXPECT_TRUE(s.IsSameAsFirst(s[0]->OutputAt(0)));
     403           2 :   EXPECT_EQ(s.ToVreg(t), s.ToVreg(s[0]->OutputAt(0)));
     404             : }
     405             : 
     406             : 
     407       15128 : TEST_F(InstructionSelectorTest, TruncateInt64ToInt32WithWord64Shr) {
     408           1 :   StreamBuilder m(this, MachineType::Int32(), MachineType::Int64());
     409           1 :   Node* const p = m.Parameter(0);
     410           1 :   Node* const t = m.TruncateInt64ToInt32(m.Word64Shr(p, m.Int64Constant(32)));
     411           1 :   m.Return(t);
     412           1 :   Stream s = m.Build();
     413           2 :   ASSERT_EQ(1U, s.size());
     414           3 :   EXPECT_EQ(kX64Shr, s[0]->arch_opcode());
     415           3 :   ASSERT_EQ(2U, s[0]->InputCount());
     416           3 :   EXPECT_EQ(s.ToVreg(p), s.ToVreg(s[0]->InputAt(0)));
     417           4 :   EXPECT_EQ(32, s.ToInt32(s[0]->InputAt(1)));
     418           3 :   ASSERT_EQ(1U, s[0]->OutputCount());
     419           2 :   EXPECT_TRUE(s.IsSameAsFirst(s[0]->OutputAt(0)));
     420           2 :   EXPECT_EQ(s.ToVreg(t), s.ToVreg(s[0]->OutputAt(0)));
     421             : }
     422             : 
     423             : 
     424             : // -----------------------------------------------------------------------------
     425             : // Addition.
     426             : 
     427             : 
     428       15128 : TEST_F(InstructionSelectorTest, Int32AddWithInt32ParametersLea) {
     429             :   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
     430           1 :                   MachineType::Int32());
     431           1 :   Node* const p0 = m.Parameter(0);
     432           1 :   Node* const p1 = m.Parameter(1);
     433           1 :   Node* const a0 = m.Int32Add(p0, p1);
     434             :   // Additional uses of input to add chooses lea
     435           1 :   Node* const a1 = m.Int32Div(p0, p1);
     436           1 :   m.Return(m.Int32Div(a0, a1));
     437           1 :   Stream s = m.Build();
     438           2 :   ASSERT_EQ(3U, s.size());
     439           3 :   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
     440           3 :   ASSERT_EQ(2U, s[0]->InputCount());
     441           3 :   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
     442           3 :   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
     443             : }
     444             : 
     445             : 
     446       15128 : TEST_F(InstructionSelectorTest, Int32AddConstantAsLeaSingle) {
     447           1 :   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
     448           1 :   Node* const p0 = m.Parameter(0);
     449           1 :   Node* const c0 = m.Int32Constant(15);
     450             :   // If one of the add's operands is only used once, use an "leal", even though
     451             :   // an "addl" could be used. The "leal" has proven faster--out best guess is
     452             :   // that it gives the register allocation more freedom and it doesn't set
     453             :   // flags, reducing pressure in the CPU's pipeline. If we're lucky with
     454             :   // register allocation, then code generation will select an "addl" later for
     455             :   // the cases that have been measured to be faster.
     456           1 :   Node* const v0 = m.Int32Add(p0, c0);
     457           1 :   m.Return(v0);
     458           1 :   Stream s = m.Build();
     459           2 :   ASSERT_EQ(1U, s.size());
     460           3 :   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
     461           3 :   EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
     462           3 :   ASSERT_EQ(2U, s[0]->InputCount());
     463           3 :   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
     464           3 :   EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
     465             : }
     466             : 
     467             : 
     468       15128 : TEST_F(InstructionSelectorTest, Int32AddConstantAsAdd) {
     469           1 :   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
     470           1 :   Node* const p0 = m.Parameter(0);
     471           1 :   Node* const c0 = m.Int32Constant(1);
     472             :   // If there is only a single use of an add's input and the immediate constant
     473             :   // for the add is 1, don't use an inc. It is much slower on modern Intel
     474             :   // architectures.
     475           1 :   m.Return(m.Int32Add(p0, c0));
     476           1 :   Stream s = m.Build();
     477           2 :   ASSERT_EQ(1U, s.size());
     478           3 :   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
     479           3 :   EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
     480           3 :   ASSERT_EQ(2U, s[0]->InputCount());
     481           3 :   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
     482           3 :   EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
     483             : }
     484             : 
     485             : 
     486       15128 : TEST_F(InstructionSelectorTest, Int32AddConstantAsLeaDouble) {
     487           1 :   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
     488           1 :   Node* const p0 = m.Parameter(0);
     489           1 :   Node* const c0 = m.Int32Constant(15);
     490             :   // A second use of an add's input uses lea
     491           1 :   Node* const a0 = m.Int32Add(p0, c0);
     492           1 :   m.Return(m.Int32Div(a0, p0));
     493           1 :   Stream s = m.Build();
     494           2 :   ASSERT_EQ(2U, s.size());
     495           3 :   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
     496           3 :   EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
     497           3 :   ASSERT_EQ(2U, s[0]->InputCount());
     498           3 :   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
     499           3 :   EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
     500             : }
     501             : 
     502             : 
     503       15128 : TEST_F(InstructionSelectorTest, Int32AddCommutedConstantAsLeaSingle) {
     504           1 :   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
     505           1 :   Node* const p0 = m.Parameter(0);
     506           1 :   Node* const c0 = m.Int32Constant(15);
     507             :   // If one of the add's operands is only used once, use an "leal", even though
     508             :   // an "addl" could be used. The "leal" has proven faster--out best guess is
     509             :   // that it gives the register allocation more freedom and it doesn't set
     510             :   // flags, reducing pressure in the CPU's pipeline. If we're lucky with
     511             :   // register allocation, then code generation will select an "addl" later for
     512             :   // the cases that have been measured to be faster.
     513           1 :   m.Return(m.Int32Add(c0, p0));
     514           1 :   Stream s = m.Build();
     515           2 :   ASSERT_EQ(1U, s.size());
     516           3 :   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
     517           3 :   EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
     518           3 :   ASSERT_EQ(2U, s[0]->InputCount());
     519           3 :   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
     520           3 :   EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
     521             : }
     522             : 
     523             : 
     524       15128 : TEST_F(InstructionSelectorTest, Int32AddCommutedConstantAsLeaDouble) {
     525           1 :   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
     526           1 :   Node* const p0 = m.Parameter(0);
     527           1 :   Node* const c0 = m.Int32Constant(15);
     528             :   // A second use of an add's input uses lea
     529           1 :   Node* const a0 = m.Int32Add(c0, p0);
     530             :   USE(a0);
     531           1 :   m.Return(m.Int32Div(a0, p0));
     532           1 :   Stream s = m.Build();
     533           2 :   ASSERT_EQ(2U, s.size());
     534           3 :   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
     535           3 :   EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
     536           3 :   ASSERT_EQ(2U, s[0]->InputCount());
     537           3 :   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
     538           3 :   EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
     539             : }
     540             : 
     541             : 
     542       15128 : TEST_F(InstructionSelectorTest, Int32AddSimpleAsAdd) {
     543             :   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
     544           1 :                   MachineType::Int32());
     545           1 :   Node* const p0 = m.Parameter(0);
     546           1 :   Node* const p1 = m.Parameter(1);
     547             :   // If one of the add's operands is only used once, use an "leal", even though
     548             :   // an "addl" could be used. The "leal" has proven faster--out best guess is
     549             :   // that it gives the register allocation more freedom and it doesn't set
     550             :   // flags, reducing pressure in the CPU's pipeline. If we're lucky with
     551             :   // register allocation, then code generation will select an "addl" later for
     552             :   // the cases that have been measured to be faster.
     553           1 :   m.Return(m.Int32Add(p0, p1));
     554           1 :   Stream s = m.Build();
     555           2 :   ASSERT_EQ(1U, s.size());
     556           3 :   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
     557           3 :   EXPECT_EQ(kMode_MR1, s[0]->addressing_mode());
     558           3 :   ASSERT_EQ(2U, s[0]->InputCount());
     559           3 :   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
     560           3 :   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
     561             : }
     562             : 
     563             : 
     564       15128 : TEST_F(InstructionSelectorTest, Int32AddSimpleAsLea) {
     565             :   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
     566           1 :                   MachineType::Int32());
     567           1 :   Node* const p0 = m.Parameter(0);
     568           1 :   Node* const p1 = m.Parameter(1);
     569             :   // If all of of the add's operands are used multiple times, use an "leal".
     570           1 :   Node* const v1 = m.Int32Add(p0, p1);
     571           1 :   m.Return(m.Int32Add(m.Int32Add(v1, p1), p0));
     572           1 :   Stream s = m.Build();
     573           2 :   ASSERT_EQ(3U, s.size());
     574           3 :   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
     575           3 :   EXPECT_EQ(kMode_MR1, s[0]->addressing_mode());
     576           3 :   ASSERT_EQ(2U, s[0]->InputCount());
     577           3 :   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
     578           3 :   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
     579             : }
     580             : 
     581             : 
     582       15128 : TEST_F(InstructionSelectorTest, Int32AddScaled2Mul) {
     583             :   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
     584           1 :                   MachineType::Int32());
     585           1 :   Node* const p0 = m.Parameter(0);
     586           1 :   Node* const p1 = m.Parameter(1);
     587           1 :   Node* const s0 = m.Int32Mul(p1, m.Int32Constant(2));
     588           1 :   m.Return(m.Int32Add(p0, s0));
     589           1 :   Stream s = m.Build();
     590           2 :   ASSERT_EQ(1U, s.size());
     591           3 :   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
     592           3 :   EXPECT_EQ(kMode_MR2, s[0]->addressing_mode());
     593           3 :   ASSERT_EQ(2U, s[0]->InputCount());
     594           3 :   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
     595           3 :   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
     596             : }
     597             : 
     598             : 
     599       15128 : TEST_F(InstructionSelectorTest, Int32AddCommutedScaled2Mul) {
     600             :   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
     601           1 :                   MachineType::Int32());
     602           1 :   Node* const p0 = m.Parameter(0);
     603           1 :   Node* const p1 = m.Parameter(1);
     604           1 :   Node* const s0 = m.Int32Mul(p1, m.Int32Constant(2));
     605           1 :   m.Return(m.Int32Add(s0, p0));
     606           1 :   Stream s = m.Build();
     607           2 :   ASSERT_EQ(1U, s.size());
     608           3 :   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
     609           3 :   EXPECT_EQ(kMode_MR2, s[0]->addressing_mode());
     610           3 :   ASSERT_EQ(2U, s[0]->InputCount());
     611           3 :   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
     612           3 :   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
     613             : }
     614             : 
     615             : 
     616       15128 : TEST_F(InstructionSelectorTest, Int32AddScaled2Shl) {
     617             :   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
     618           1 :                   MachineType::Int32());
     619           1 :   Node* const p0 = m.Parameter(0);
     620           1 :   Node* const p1 = m.Parameter(1);
     621           1 :   Node* const s0 = m.Word32Shl(p1, m.Int32Constant(1));
     622           1 :   m.Return(m.Int32Add(p0, s0));
     623           1 :   Stream s = m.Build();
     624           2 :   ASSERT_EQ(1U, s.size());
     625           3 :   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
     626           3 :   EXPECT_EQ(kMode_MR2, s[0]->addressing_mode());
     627           3 :   ASSERT_EQ(2U, s[0]->InputCount());
     628           3 :   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
     629           3 :   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
     630             : }
     631             : 
     632             : 
     633       15128 : TEST_F(InstructionSelectorTest, Int32AddCommutedScaled2Shl) {
     634             :   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
     635           1 :                   MachineType::Int32());
     636           1 :   Node* const p0 = m.Parameter(0);
     637           1 :   Node* const p1 = m.Parameter(1);
     638           1 :   Node* const s0 = m.Word32Shl(p1, m.Int32Constant(1));
     639           1 :   m.Return(m.Int32Add(s0, p0));
     640           1 :   Stream s = m.Build();
     641           2 :   ASSERT_EQ(1U, s.size());
     642           3 :   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
     643           3 :   EXPECT_EQ(kMode_MR2, s[0]->addressing_mode());
     644           3 :   ASSERT_EQ(2U, s[0]->InputCount());
     645           3 :   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
     646           3 :   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
     647             : }
     648             : 
     649             : 
     650       15128 : TEST_F(InstructionSelectorTest, Int32AddScaled4Mul) {
     651             :   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
     652           1 :                   MachineType::Int32());
     653           1 :   Node* const p0 = m.Parameter(0);
     654           1 :   Node* const p1 = m.Parameter(1);
     655           1 :   Node* const s0 = m.Int32Mul(p1, m.Int32Constant(4));
     656           1 :   m.Return(m.Int32Add(p0, s0));
     657           1 :   Stream s = m.Build();
     658           2 :   ASSERT_EQ(1U, s.size());
     659           3 :   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
     660           3 :   EXPECT_EQ(kMode_MR4, s[0]->addressing_mode());
     661           3 :   ASSERT_EQ(2U, s[0]->InputCount());
     662           3 :   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
     663           3 :   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
     664             : }
     665             : 
     666             : 
     667       15128 : TEST_F(InstructionSelectorTest, Int32AddScaled4Shl) {
     668             :   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
     669           1 :                   MachineType::Int32());
     670           1 :   Node* const p0 = m.Parameter(0);
     671           1 :   Node* const p1 = m.Parameter(1);
     672           1 :   Node* const s0 = m.Word32Shl(p1, m.Int32Constant(2));
     673           1 :   m.Return(m.Int32Add(p0, s0));
     674           1 :   Stream s = m.Build();
     675           2 :   ASSERT_EQ(1U, s.size());
     676           3 :   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
     677           3 :   EXPECT_EQ(kMode_MR4, s[0]->addressing_mode());
     678           3 :   ASSERT_EQ(2U, s[0]->InputCount());
     679           3 :   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
     680           3 :   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
     681             : }
     682             : 
     683             : 
     684       15128 : TEST_F(InstructionSelectorTest, Int32AddScaled8Mul) {
     685             :   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
     686           1 :                   MachineType::Int32());
     687           1 :   Node* const p0 = m.Parameter(0);
     688           1 :   Node* const p1 = m.Parameter(1);
     689           1 :   Node* const s0 = m.Int32Mul(p1, m.Int32Constant(8));
     690           1 :   m.Return(m.Int32Add(p0, s0));
     691           1 :   Stream s = m.Build();
     692           2 :   ASSERT_EQ(1U, s.size());
     693           3 :   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
     694           3 :   EXPECT_EQ(kMode_MR8, s[0]->addressing_mode());
     695           3 :   ASSERT_EQ(2U, s[0]->InputCount());
     696           3 :   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
     697           3 :   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
     698             : }
     699             : 
     700             : 
     701       15128 : TEST_F(InstructionSelectorTest, Int32AddScaled8Shl) {
     702             :   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
     703           1 :                   MachineType::Int32());
     704           1 :   Node* const p0 = m.Parameter(0);
     705           1 :   Node* const p1 = m.Parameter(1);
     706           1 :   Node* const s0 = m.Word32Shl(p1, m.Int32Constant(3));
     707           1 :   m.Return(m.Int32Add(p0, s0));
     708           1 :   Stream s = m.Build();
     709           2 :   ASSERT_EQ(1U, s.size());
     710           3 :   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
     711           3 :   EXPECT_EQ(kMode_MR8, s[0]->addressing_mode());
     712           3 :   ASSERT_EQ(2U, s[0]->InputCount());
     713           3 :   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
     714           3 :   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
     715             : }
     716             : 
     717             : 
     718       15128 : TEST_F(InstructionSelectorTest, Int32AddScaled2MulWithConstant) {
     719             :   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
     720           1 :                   MachineType::Int32());
     721           1 :   Node* const p0 = m.Parameter(0);
     722           1 :   Node* const p1 = m.Parameter(1);
     723           1 :   Node* const s0 = m.Int32Mul(p1, m.Int32Constant(2));
     724           1 :   Node* const c0 = m.Int32Constant(15);
     725           1 :   m.Return(m.Int32Add(c0, m.Int32Add(p0, s0)));
     726           1 :   Stream s = m.Build();
     727           2 :   ASSERT_EQ(1U, s.size());
     728           3 :   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
     729           3 :   EXPECT_EQ(kMode_MR2I, s[0]->addressing_mode());
     730           3 :   ASSERT_EQ(3U, s[0]->InputCount());
     731           3 :   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
     732           3 :   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
     733           3 :   EXPECT_TRUE(s[0]->InputAt(2)->IsImmediate());
     734             : }
     735             : 
     736             : 
     737       15128 : TEST_F(InstructionSelectorTest, Int32AddScaled2MulWithConstantShuffle1) {
     738             :   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
     739           1 :                   MachineType::Int32());
     740           1 :   Node* const p0 = m.Parameter(0);
     741           1 :   Node* const p1 = m.Parameter(1);
     742           1 :   Node* const s0 = m.Int32Mul(p1, m.Int32Constant(2));
     743           1 :   Node* const c0 = m.Int32Constant(15);
     744           1 :   m.Return(m.Int32Add(p0, m.Int32Add(s0, c0)));
     745           1 :   Stream s = m.Build();
     746           2 :   ASSERT_EQ(1U, s.size());
     747           3 :   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
     748           3 :   EXPECT_EQ(kMode_MR2I, s[0]->addressing_mode());
     749           3 :   ASSERT_EQ(3U, s[0]->InputCount());
     750           3 :   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
     751           3 :   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
     752           3 :   EXPECT_TRUE(s[0]->InputAt(2)->IsImmediate());
     753             : }
     754             : 
     755             : 
     756       15128 : TEST_F(InstructionSelectorTest, Int32AddScaled2MulWithConstantShuffle2) {
     757             :   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
     758           1 :                   MachineType::Int32());
     759           1 :   Node* const p0 = m.Parameter(0);
     760           1 :   Node* const p1 = m.Parameter(1);
     761           1 :   Node* const s0 = m.Int32Mul(p1, m.Int32Constant(2));
     762           1 :   Node* const c0 = m.Int32Constant(15);
     763           1 :   m.Return(m.Int32Add(s0, m.Int32Add(c0, p0)));
     764           1 :   Stream s = m.Build();
     765           2 :   ASSERT_EQ(1U, s.size());
     766           3 :   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
     767           3 :   EXPECT_EQ(kMode_MR2I, s[0]->addressing_mode());
     768           3 :   ASSERT_EQ(3U, s[0]->InputCount());
     769           3 :   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
     770           3 :   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
     771           3 :   EXPECT_TRUE(s[0]->InputAt(2)->IsImmediate());
     772             : }
     773             : 
     774             : 
     775       15128 : TEST_F(InstructionSelectorTest, Int32AddScaled2MulWithConstantShuffle3) {
     776             :   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
     777           1 :                   MachineType::Int32());
     778           1 :   Node* const p0 = m.Parameter(0);
     779           1 :   Node* const p1 = m.Parameter(1);
     780           1 :   Node* const s0 = m.Int32Mul(p1, m.Int32Constant(2));
     781           1 :   Node* const c0 = m.Int32Constant(15);
     782           1 :   m.Return(m.Int32Add(m.Int32Add(s0, c0), p0));
     783           1 :   Stream s = m.Build();
     784           2 :   ASSERT_EQ(1U, s.size());
     785           3 :   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
     786           3 :   EXPECT_EQ(kMode_MR2I, s[0]->addressing_mode());
     787           3 :   ASSERT_EQ(3U, s[0]->InputCount());
     788           3 :   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
     789           3 :   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
     790           3 :   EXPECT_TRUE(s[0]->InputAt(2)->IsImmediate());
     791             : }
     792             : 
     793             : 
     794       15128 : TEST_F(InstructionSelectorTest, Int32AddScaled2MulWithConstantShuffle4) {
     795             :   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
     796           1 :                   MachineType::Int32());
     797           1 :   Node* const p0 = m.Parameter(0);
     798           1 :   Node* const p1 = m.Parameter(1);
     799           1 :   Node* const s0 = m.Int32Mul(p1, m.Int32Constant(2));
     800           1 :   Node* const c0 = m.Int32Constant(15);
     801           1 :   m.Return(m.Int32Add(m.Int32Add(c0, p0), s0));
     802           1 :   Stream s = m.Build();
     803           2 :   ASSERT_EQ(1U, s.size());
     804           3 :   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
     805           3 :   EXPECT_EQ(kMode_MR2I, s[0]->addressing_mode());
     806           3 :   ASSERT_EQ(3U, s[0]->InputCount());
     807           3 :   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
     808           3 :   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
     809           3 :   EXPECT_TRUE(s[0]->InputAt(2)->IsImmediate());
     810             : }
     811             : 
     812             : 
     813       15128 : TEST_F(InstructionSelectorTest, Int32AddScaled2MulWithConstantShuffle5) {
     814             :   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
     815           1 :                   MachineType::Int32());
     816           1 :   Node* const p0 = m.Parameter(0);
     817           1 :   Node* const p1 = m.Parameter(1);
     818           1 :   Node* const s0 = m.Int32Mul(p1, m.Int32Constant(2));
     819           1 :   Node* const c0 = m.Int32Constant(15);
     820           1 :   m.Return(m.Int32Add(m.Int32Add(p0, s0), c0));
     821           1 :   Stream s = m.Build();
     822           2 :   ASSERT_EQ(1U, s.size());
     823           3 :   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
     824           3 :   EXPECT_EQ(kMode_MR2I, s[0]->addressing_mode());
     825           3 :   ASSERT_EQ(3U, s[0]->InputCount());
     826           3 :   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
     827           3 :   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
     828           3 :   EXPECT_TRUE(s[0]->InputAt(2)->IsImmediate());
     829             : }
     830             : 
     831             : 
     832       15128 : TEST_F(InstructionSelectorTest, Int32AddScaled2ShlWithConstant) {
     833             :   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
     834           1 :                   MachineType::Int32());
     835           1 :   Node* const p0 = m.Parameter(0);
     836           1 :   Node* const p1 = m.Parameter(1);
     837           1 :   Node* const s0 = m.Word32Shl(p1, m.Int32Constant(1));
     838           1 :   Node* const c0 = m.Int32Constant(15);
     839           1 :   m.Return(m.Int32Add(c0, m.Int32Add(p0, s0)));
     840           1 :   Stream s = m.Build();
     841           2 :   ASSERT_EQ(1U, s.size());
     842           3 :   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
     843           3 :   EXPECT_EQ(kMode_MR2I, s[0]->addressing_mode());
     844           3 :   ASSERT_EQ(3U, s[0]->InputCount());
     845           3 :   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
     846           3 :   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
     847           3 :   EXPECT_TRUE(s[0]->InputAt(2)->IsImmediate());
     848             : }
     849             : 
     850             : 
     851       15128 : TEST_F(InstructionSelectorTest, Int32AddScaled4MulWithConstant) {
     852             :   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
     853           1 :                   MachineType::Int32());
     854           1 :   Node* const p0 = m.Parameter(0);
     855           1 :   Node* const p1 = m.Parameter(1);
     856           1 :   Node* const s0 = m.Int32Mul(p1, m.Int32Constant(4));
     857           1 :   Node* const c0 = m.Int32Constant(15);
     858           1 :   m.Return(m.Int32Add(c0, m.Int32Add(p0, s0)));
     859           1 :   Stream s = m.Build();
     860           2 :   ASSERT_EQ(1U, s.size());
     861           3 :   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
     862           3 :   EXPECT_EQ(kMode_MR4I, s[0]->addressing_mode());
     863           3 :   ASSERT_EQ(3U, s[0]->InputCount());
     864           3 :   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
     865           3 :   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
     866           3 :   EXPECT_TRUE(s[0]->InputAt(2)->IsImmediate());
     867             : }
     868             : 
     869             : 
     870       15128 : TEST_F(InstructionSelectorTest, Int32AddScaled4ShlWithConstant) {
     871             :   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
     872           1 :                   MachineType::Int32());
     873           1 :   Node* const p0 = m.Parameter(0);
     874           1 :   Node* const p1 = m.Parameter(1);
     875           1 :   Node* const s0 = m.Word32Shl(p1, m.Int32Constant(2));
     876           1 :   Node* const c0 = m.Int32Constant(15);
     877           1 :   m.Return(m.Int32Add(c0, m.Int32Add(p0, s0)));
     878           1 :   Stream s = m.Build();
     879           2 :   ASSERT_EQ(1U, s.size());
     880           3 :   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
     881           3 :   EXPECT_EQ(kMode_MR4I, s[0]->addressing_mode());
     882           3 :   ASSERT_EQ(3U, s[0]->InputCount());
     883           3 :   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
     884           3 :   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
     885           3 :   EXPECT_TRUE(s[0]->InputAt(2)->IsImmediate());
     886             : }
     887             : 
     888             : 
     889       15128 : TEST_F(InstructionSelectorTest, Int32AddScaled8MulWithConstant) {
     890             :   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
     891           1 :                   MachineType::Int32());
     892           1 :   Node* const p0 = m.Parameter(0);
     893           1 :   Node* const p1 = m.Parameter(1);
     894           1 :   Node* const s0 = m.Int32Mul(p1, m.Int32Constant(8));
     895           1 :   Node* const c0 = m.Int32Constant(15);
     896           1 :   m.Return(m.Int32Add(c0, m.Int32Add(p0, s0)));
     897           1 :   Stream s = m.Build();
     898           2 :   ASSERT_EQ(1U, s.size());
     899           3 :   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
     900           3 :   EXPECT_EQ(kMode_MR8I, s[0]->addressing_mode());
     901           3 :   ASSERT_EQ(3U, s[0]->InputCount());
     902           3 :   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
     903           3 :   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
     904           3 :   EXPECT_TRUE(s[0]->InputAt(2)->IsImmediate());
     905             : }
     906             : 
     907             : 
     908       15128 : TEST_F(InstructionSelectorTest, Int32AddScaled8ShlWithConstant) {
     909             :   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
     910           1 :                   MachineType::Int32());
     911           1 :   Node* const p0 = m.Parameter(0);
     912           1 :   Node* const p1 = m.Parameter(1);
     913           1 :   Node* const s0 = m.Word32Shl(p1, m.Int32Constant(3));
     914           1 :   Node* const c0 = m.Int32Constant(15);
     915           1 :   m.Return(m.Int32Add(c0, m.Int32Add(p0, s0)));
     916           1 :   Stream s = m.Build();
     917           2 :   ASSERT_EQ(1U, s.size());
     918           3 :   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
     919           3 :   EXPECT_EQ(kMode_MR8I, s[0]->addressing_mode());
     920           3 :   ASSERT_EQ(3U, s[0]->InputCount());
     921           3 :   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
     922           3 :   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
     923           3 :   EXPECT_TRUE(s[0]->InputAt(2)->IsImmediate());
     924             : }
     925             : 
     926             : 
     927       15128 : TEST_F(InstructionSelectorTest, Int32SubConstantAsSub) {
     928           1 :   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
     929           1 :   Node* const p0 = m.Parameter(0);
     930           1 :   Node* const c0 = m.Int32Constant(-1);
     931             :   // If there is only a single use of on of the sub's non-constant input, use a
     932             :   // "subl" instruction.
     933           1 :   m.Return(m.Int32Sub(p0, c0));
     934           1 :   Stream s = m.Build();
     935           2 :   ASSERT_EQ(1U, s.size());
     936           3 :   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
     937           3 :   EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
     938           3 :   ASSERT_EQ(2U, s[0]->InputCount());
     939           3 :   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
     940           3 :   EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
     941             : }
     942             : 
     943             : 
     944       15128 : TEST_F(InstructionSelectorTest, Int32SubConstantAsLea) {
     945           1 :   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
     946           1 :   Node* const p0 = m.Parameter(0);
     947           1 :   Node* const c0 = m.Int32Constant(-1);
     948             :   // If there are multiple uses of on of the sub's non-constant input, use a
     949             :   // "leal" instruction.
     950           1 :   Node* const v0 = m.Int32Sub(p0, c0);
     951           1 :   m.Return(m.Int32Div(p0, v0));
     952           1 :   Stream s = m.Build();
     953           2 :   ASSERT_EQ(2U, s.size());
     954           3 :   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
     955           3 :   EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
     956           3 :   ASSERT_EQ(2U, s[0]->InputCount());
     957           3 :   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
     958           3 :   EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
     959             : }
     960             : 
     961             : 
     962       15128 : TEST_F(InstructionSelectorTest, Int32AddScaled2Other) {
     963             :   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
     964           1 :                   MachineType::Int32(), MachineType::Int32());
     965           1 :   Node* const p0 = m.Parameter(0);
     966           1 :   Node* const p1 = m.Parameter(1);
     967           1 :   Node* const p2 = m.Parameter(2);
     968           1 :   Node* const s0 = m.Int32Mul(p1, m.Int32Constant(2));
     969           1 :   Node* const a0 = m.Int32Add(s0, p2);
     970           1 :   Node* const a1 = m.Int32Add(p0, a0);
     971           1 :   m.Return(a1);
     972           1 :   Stream s = m.Build();
     973           2 :   ASSERT_EQ(2U, s.size());
     974           3 :   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
     975           3 :   EXPECT_EQ(kMode_MR2, s[0]->addressing_mode());
     976           3 :   ASSERT_EQ(2U, s[0]->InputCount());
     977           3 :   EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(0)));
     978           3 :   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
     979           2 :   EXPECT_EQ(s.ToVreg(a0), s.ToVreg(s[0]->OutputAt(0)));
     980           3 :   ASSERT_EQ(2U, s[1]->InputCount());
     981           3 :   EXPECT_EQ(kX64Lea32, s[1]->arch_opcode());
     982           3 :   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[1]->InputAt(0)));
     983           3 :   EXPECT_EQ(s.ToVreg(a0), s.ToVreg(s[1]->InputAt(1)));
     984           2 :   EXPECT_EQ(s.ToVreg(a1), s.ToVreg(s[1]->OutputAt(0)));
     985             : }
     986             : 
     987             : 
     988             : // -----------------------------------------------------------------------------
     989             : // Multiplication.
     990             : 
     991             : 
     992       15128 : TEST_F(InstructionSelectorTest, Int32MulWithInt32MulWithParameters) {
     993             :   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
     994           1 :                   MachineType::Int32());
     995           1 :   Node* const p0 = m.Parameter(0);
     996           1 :   Node* const p1 = m.Parameter(1);
     997           1 :   Node* const m0 = m.Int32Mul(p0, p1);
     998           1 :   m.Return(m.Int32Mul(m0, p0));
     999           1 :   Stream s = m.Build();
    1000           2 :   ASSERT_EQ(2U, s.size());
    1001           3 :   EXPECT_EQ(kX64Imul32, s[0]->arch_opcode());
    1002           3 :   ASSERT_EQ(2U, s[0]->InputCount());
    1003           3 :   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(0)));
    1004           3 :   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1)));
    1005           3 :   ASSERT_EQ(1U, s[0]->OutputCount());
    1006           2 :   EXPECT_EQ(s.ToVreg(m0), s.ToVreg(s[0]->OutputAt(0)));
    1007           3 :   EXPECT_EQ(kX64Imul32, s[1]->arch_opcode());
    1008           3 :   ASSERT_EQ(2U, s[1]->InputCount());
    1009           3 :   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[1]->InputAt(0)));
    1010           3 :   EXPECT_EQ(s.ToVreg(m0), s.ToVreg(s[1]->InputAt(1)));
    1011             : }
    1012             : 
    1013             : 
    1014       15128 : TEST_F(InstructionSelectorTest, Int32MulHigh) {
    1015             :   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
    1016           1 :                   MachineType::Int32());
    1017           1 :   Node* const p0 = m.Parameter(0);
    1018           1 :   Node* const p1 = m.Parameter(1);
    1019           1 :   Node* const n = m.Int32MulHigh(p0, p1);
    1020           1 :   m.Return(n);
    1021           1 :   Stream s = m.Build();
    1022           2 :   ASSERT_EQ(1U, s.size());
    1023           3 :   EXPECT_EQ(kX64ImulHigh32, s[0]->arch_opcode());
    1024           3 :   ASSERT_EQ(2U, s[0]->InputCount());
    1025           3 :   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
    1026           3 :   EXPECT_TRUE(s.IsFixed(s[0]->InputAt(0), rax));
    1027           3 :   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
    1028           3 :   EXPECT_TRUE(!s.IsUsedAtStart(s[0]->InputAt(1)));
    1029           2 :   ASSERT_LE(1U, s[0]->OutputCount());
    1030           2 :   EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
    1031           2 :   EXPECT_TRUE(s.IsFixed(s[0]->OutputAt(0), rdx));
    1032             : }
    1033             : 
    1034             : 
    1035       15128 : TEST_F(InstructionSelectorTest, Uint32MulHigh) {
    1036             :   StreamBuilder m(this, MachineType::Uint32(), MachineType::Uint32(),
    1037           1 :                   MachineType::Uint32());
    1038           1 :   Node* const p0 = m.Parameter(0);
    1039           1 :   Node* const p1 = m.Parameter(1);
    1040           1 :   Node* const n = m.Uint32MulHigh(p0, p1);
    1041           1 :   m.Return(n);
    1042           1 :   Stream s = m.Build();
    1043           2 :   ASSERT_EQ(1U, s.size());
    1044           3 :   EXPECT_EQ(kX64UmulHigh32, s[0]->arch_opcode());
    1045           3 :   ASSERT_EQ(2U, s[0]->InputCount());
    1046           3 :   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
    1047           3 :   EXPECT_TRUE(s.IsFixed(s[0]->InputAt(0), rax));
    1048           3 :   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
    1049           3 :   EXPECT_TRUE(!s.IsUsedAtStart(s[0]->InputAt(1)));
    1050           2 :   ASSERT_LE(1U, s[0]->OutputCount());
    1051           2 :   EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
    1052           2 :   EXPECT_TRUE(s.IsFixed(s[0]->OutputAt(0), rdx));
    1053             : }
    1054             : 
    1055             : 
    1056       15128 : TEST_F(InstructionSelectorTest, Int32Mul2BecomesLea) {
    1057             :   StreamBuilder m(this, MachineType::Uint32(), MachineType::Uint32(),
    1058           1 :                   MachineType::Uint32());
    1059           1 :   Node* const p0 = m.Parameter(0);
    1060           1 :   Node* const c1 = m.Int32Constant(2);
    1061           1 :   Node* const n = m.Int32Mul(p0, c1);
    1062           1 :   m.Return(n);
    1063           1 :   Stream s = m.Build();
    1064           2 :   ASSERT_EQ(1U, s.size());
    1065           3 :   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
    1066           3 :   EXPECT_EQ(kMode_MR1, s[0]->addressing_mode());
    1067           3 :   ASSERT_EQ(2U, s[0]->InputCount());
    1068           3 :   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
    1069           3 :   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1)));
    1070             : }
    1071             : 
    1072             : 
    1073       15128 : TEST_F(InstructionSelectorTest, Int32Mul3BecomesLea) {
    1074             :   StreamBuilder m(this, MachineType::Uint32(), MachineType::Uint32(),
    1075           1 :                   MachineType::Uint32());
    1076           1 :   Node* const p0 = m.Parameter(0);
    1077           1 :   Node* const c1 = m.Int32Constant(3);
    1078           1 :   Node* const n = m.Int32Mul(p0, c1);
    1079           1 :   m.Return(n);
    1080           1 :   Stream s = m.Build();
    1081           2 :   ASSERT_EQ(1U, s.size());
    1082           3 :   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
    1083           3 :   EXPECT_EQ(kMode_MR2, s[0]->addressing_mode());
    1084           3 :   ASSERT_EQ(2U, s[0]->InputCount());
    1085           3 :   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
    1086           3 :   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1)));
    1087             : }
    1088             : 
    1089             : 
    1090       15128 : TEST_F(InstructionSelectorTest, Int32Mul4BecomesLea) {
    1091             :   StreamBuilder m(this, MachineType::Uint32(), MachineType::Uint32(),
    1092           1 :                   MachineType::Uint32());
    1093           1 :   Node* const p0 = m.Parameter(0);
    1094           1 :   Node* const c1 = m.Int32Constant(4);
    1095           1 :   Node* const n = m.Int32Mul(p0, c1);
    1096           1 :   m.Return(n);
    1097           1 :   Stream s = m.Build();
    1098           2 :   ASSERT_EQ(1U, s.size());
    1099           3 :   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
    1100           3 :   EXPECT_EQ(kMode_M4, s[0]->addressing_mode());
    1101           3 :   ASSERT_EQ(1U, s[0]->InputCount());
    1102           3 :   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
    1103             : }
    1104             : 
    1105             : 
    1106       15128 : TEST_F(InstructionSelectorTest, Int32Mul5BecomesLea) {
    1107             :   StreamBuilder m(this, MachineType::Uint32(), MachineType::Uint32(),
    1108           1 :                   MachineType::Uint32());
    1109           1 :   Node* const p0 = m.Parameter(0);
    1110           1 :   Node* const c1 = m.Int32Constant(5);
    1111           1 :   Node* const n = m.Int32Mul(p0, c1);
    1112           1 :   m.Return(n);
    1113           1 :   Stream s = m.Build();
    1114           2 :   ASSERT_EQ(1U, s.size());
    1115           3 :   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
    1116           3 :   EXPECT_EQ(kMode_MR4, s[0]->addressing_mode());
    1117           3 :   ASSERT_EQ(2U, s[0]->InputCount());
    1118           3 :   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
    1119           3 :   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1)));
    1120             : }
    1121             : 
    1122             : 
    1123       15128 : TEST_F(InstructionSelectorTest, Int32Mul8BecomesLea) {
    1124             :   StreamBuilder m(this, MachineType::Uint32(), MachineType::Uint32(),
    1125           1 :                   MachineType::Uint32());
    1126           1 :   Node* const p0 = m.Parameter(0);
    1127           1 :   Node* const c1 = m.Int32Constant(8);
    1128           1 :   Node* const n = m.Int32Mul(p0, c1);
    1129           1 :   m.Return(n);
    1130           1 :   Stream s = m.Build();
    1131           2 :   ASSERT_EQ(1U, s.size());
    1132           3 :   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
    1133           3 :   EXPECT_EQ(kMode_M8, s[0]->addressing_mode());
    1134           3 :   ASSERT_EQ(1U, s[0]->InputCount());
    1135           3 :   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
    1136             : }
    1137             : 
    1138             : 
    1139       15128 : TEST_F(InstructionSelectorTest, Int32Mul9BecomesLea) {
    1140             :   StreamBuilder m(this, MachineType::Uint32(), MachineType::Uint32(),
    1141           1 :                   MachineType::Uint32());
    1142           1 :   Node* const p0 = m.Parameter(0);
    1143           1 :   Node* const c1 = m.Int32Constant(9);
    1144           1 :   Node* const n = m.Int32Mul(p0, c1);
    1145           1 :   m.Return(n);
    1146           1 :   Stream s = m.Build();
    1147           2 :   ASSERT_EQ(1U, s.size());
    1148           3 :   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
    1149           3 :   EXPECT_EQ(kMode_MR8, s[0]->addressing_mode());
    1150           3 :   ASSERT_EQ(2U, s[0]->InputCount());
    1151           3 :   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
    1152           3 :   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1)));
    1153             : }
    1154             : 
    1155             : 
    1156             : // -----------------------------------------------------------------------------
    1157             : // Word32Shl.
    1158             : 
    1159             : 
    1160       15128 : TEST_F(InstructionSelectorTest, Int32Shl1BecomesLea) {
    1161             :   StreamBuilder m(this, MachineType::Uint32(), MachineType::Uint32(),
    1162           1 :                   MachineType::Uint32());
    1163           1 :   Node* const p0 = m.Parameter(0);
    1164           1 :   Node* const c1 = m.Int32Constant(1);
    1165           1 :   Node* const n = m.Word32Shl(p0, c1);
    1166           1 :   m.Return(n);
    1167           1 :   Stream s = m.Build();
    1168           2 :   ASSERT_EQ(1U, s.size());
    1169           3 :   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
    1170           3 :   EXPECT_EQ(kMode_MR1, s[0]->addressing_mode());
    1171           3 :   ASSERT_EQ(2U, s[0]->InputCount());
    1172           3 :   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
    1173           3 :   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1)));
    1174             : }
    1175             : 
    1176             : 
    1177       15128 : TEST_F(InstructionSelectorTest, Int32Shl2BecomesLea) {
    1178             :   StreamBuilder m(this, MachineType::Uint32(), MachineType::Uint32(),
    1179           1 :                   MachineType::Uint32());
    1180           1 :   Node* const p0 = m.Parameter(0);
    1181           1 :   Node* const c1 = m.Int32Constant(2);
    1182           1 :   Node* const n = m.Word32Shl(p0, c1);
    1183           1 :   m.Return(n);
    1184           1 :   Stream s = m.Build();
    1185           2 :   ASSERT_EQ(1U, s.size());
    1186           3 :   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
    1187           3 :   EXPECT_EQ(kMode_M4, s[0]->addressing_mode());
    1188           3 :   ASSERT_EQ(1U, s[0]->InputCount());
    1189           3 :   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
    1190             : }
    1191             : 
    1192             : 
    1193       15128 : TEST_F(InstructionSelectorTest, Int32Shl4BecomesLea) {
    1194             :   StreamBuilder m(this, MachineType::Uint32(), MachineType::Uint32(),
    1195           1 :                   MachineType::Uint32());
    1196           1 :   Node* const p0 = m.Parameter(0);
    1197           1 :   Node* const c1 = m.Int32Constant(3);
    1198           1 :   Node* const n = m.Word32Shl(p0, c1);
    1199           1 :   m.Return(n);
    1200           1 :   Stream s = m.Build();
    1201           2 :   ASSERT_EQ(1U, s.size());
    1202           3 :   EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
    1203           3 :   EXPECT_EQ(kMode_M8, s[0]->addressing_mode());
    1204           3 :   ASSERT_EQ(1U, s[0]->InputCount());
    1205           3 :   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
    1206             : }
    1207             : 
    1208             : // -----------------------------------------------------------------------------
    1209             : // Binops with a memory operand.
    1210             : 
    1211       15128 : TEST_F(InstructionSelectorTest, LoadCmp32) {
    1212             :   {
    1213             :     // Word32Equal(Load[Int8](p0, p1), Int32Constant(0)) -> cmpb [p0,p1], 0
    1214             :     StreamBuilder m(this, MachineType::Int32(), MachineType::Int64(),
    1215           1 :                     MachineType::Int64());
    1216           1 :     Node* const p0 = m.Parameter(0);
    1217           1 :     Node* const p1 = m.Parameter(1);
    1218             :     m.Return(
    1219           1 :         m.Word32Equal(m.Load(MachineType::Int8(), p0, p1), m.Int32Constant(0)));
    1220           1 :     Stream s = m.Build();
    1221           2 :     ASSERT_EQ(1U, s.size());
    1222           3 :     EXPECT_EQ(kX64Cmp8, s[0]->arch_opcode());
    1223           3 :     EXPECT_EQ(kMode_MR1, s[0]->addressing_mode());
    1224           3 :     ASSERT_EQ(3U, s[0]->InputCount());
    1225           3 :     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
    1226           3 :     EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
    1227           3 :     EXPECT_TRUE(s[0]->InputAt(2)->IsImmediate());
    1228             :   }
    1229             :   {
    1230             :     // Word32Equal(Load[Uint8](p0, p1), Int32Constant(0)) -> cmpb [p0,p1], 0
    1231             :     StreamBuilder m(this, MachineType::Int32(), MachineType::Int64(),
    1232           1 :                     MachineType::Int64());
    1233           1 :     Node* const p0 = m.Parameter(0);
    1234           1 :     Node* const p1 = m.Parameter(1);
    1235             :     m.Return(m.Word32Equal(m.Load(MachineType::Uint8(), p0, p1),
    1236           1 :                            m.Int32Constant(0)));
    1237           1 :     Stream s = m.Build();
    1238           2 :     ASSERT_EQ(1U, s.size());
    1239           3 :     EXPECT_EQ(kX64Cmp8, s[0]->arch_opcode());
    1240           3 :     EXPECT_EQ(kMode_MR1, s[0]->addressing_mode());
    1241           3 :     ASSERT_EQ(3U, s[0]->InputCount());
    1242           3 :     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
    1243           3 :     EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
    1244           3 :     EXPECT_TRUE(s[0]->InputAt(2)->IsImmediate());
    1245             :   }
    1246             :   {
    1247             :     // Word32Equal(Load[Int16](p0, p1), Int32Constant(0)) -> cmpw [p0,p1], 0
    1248             :     StreamBuilder m(this, MachineType::Int32(), MachineType::Int64(),
    1249           1 :                     MachineType::Int64());
    1250           1 :     Node* const p0 = m.Parameter(0);
    1251           1 :     Node* const p1 = m.Parameter(1);
    1252             :     m.Return(m.Word32Equal(m.Load(MachineType::Int16(), p0, p1),
    1253           1 :                            m.Int32Constant(0)));
    1254           1 :     Stream s = m.Build();
    1255           2 :     ASSERT_EQ(1U, s.size());
    1256           3 :     EXPECT_EQ(kX64Cmp16, s[0]->arch_opcode());
    1257           3 :     EXPECT_EQ(kMode_MR1, s[0]->addressing_mode());
    1258           3 :     ASSERT_EQ(3U, s[0]->InputCount());
    1259           3 :     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
    1260           3 :     EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
    1261           3 :     EXPECT_TRUE(s[0]->InputAt(2)->IsImmediate());
    1262             :   }
    1263             :   {
    1264             :     // Word32Equal(Load[Uint16](p0, p1), Int32Constant(0)) -> cmpw [p0,p1], 0
    1265             :     StreamBuilder m(this, MachineType::Int32(), MachineType::Int64(),
    1266           1 :                     MachineType::Int64());
    1267           1 :     Node* const p0 = m.Parameter(0);
    1268           1 :     Node* const p1 = m.Parameter(1);
    1269             :     m.Return(m.Word32Equal(m.Load(MachineType::Uint16(), p0, p1),
    1270           1 :                            m.Int32Constant(0)));
    1271           1 :     Stream s = m.Build();
    1272           2 :     ASSERT_EQ(1U, s.size());
    1273           3 :     EXPECT_EQ(kX64Cmp16, s[0]->arch_opcode());
    1274           3 :     EXPECT_EQ(kMode_MR1, s[0]->addressing_mode());
    1275           3 :     ASSERT_EQ(3U, s[0]->InputCount());
    1276           3 :     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
    1277           3 :     EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
    1278           3 :     EXPECT_TRUE(s[0]->InputAt(2)->IsImmediate());
    1279             :   }
    1280             :   {
    1281             :     // Word32Equal(Load[Int32](p0, p1), Int32Constant(0)) -> cmpl [p0,p1], 0
    1282             :     StreamBuilder m(this, MachineType::Int32(), MachineType::Int64(),
    1283           1 :                     MachineType::Int64());
    1284           1 :     Node* const p0 = m.Parameter(0);
    1285           1 :     Node* const p1 = m.Parameter(1);
    1286             :     m.Return(m.Word32Equal(m.Load(MachineType::Int32(), p0, p1),
    1287           1 :                            m.Int32Constant(0)));
    1288           1 :     Stream s = m.Build();
    1289           2 :     ASSERT_EQ(1U, s.size());
    1290           3 :     EXPECT_EQ(kX64Cmp32, s[0]->arch_opcode());
    1291           3 :     EXPECT_EQ(kMode_MR1, s[0]->addressing_mode());
    1292           3 :     ASSERT_EQ(3U, s[0]->InputCount());
    1293           3 :     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
    1294           3 :     EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
    1295           3 :     EXPECT_TRUE(s[0]->InputAt(2)->IsImmediate());
    1296             :   }
    1297             :   {
    1298             :     // Word32Equal(Load[Uint32](p0, p1), Int32Constant(0)) -> cmpl [p0,p1], 0
    1299             :     StreamBuilder m(this, MachineType::Int32(), MachineType::Int64(),
    1300           1 :                     MachineType::Int64());
    1301           1 :     Node* const p0 = m.Parameter(0);
    1302           1 :     Node* const p1 = m.Parameter(1);
    1303             :     m.Return(m.Word32Equal(m.Load(MachineType::Uint32(), p0, p1),
    1304           1 :                            m.Int32Constant(0)));
    1305           1 :     Stream s = m.Build();
    1306           2 :     ASSERT_EQ(1U, s.size());
    1307           3 :     EXPECT_EQ(kX64Cmp32, s[0]->arch_opcode());
    1308           3 :     EXPECT_EQ(kMode_MR1, s[0]->addressing_mode());
    1309           3 :     ASSERT_EQ(3U, s[0]->InputCount());
    1310           3 :     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
    1311           3 :     EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
    1312           3 :     EXPECT_TRUE(s[0]->InputAt(2)->IsImmediate());
    1313             :   }
    1314             : }
    1315             : 
    1316       15128 : TEST_F(InstructionSelectorTest, LoadAnd32) {
    1317             :   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
    1318           1 :                   MachineType::Int32());
    1319           1 :   Node* const p0 = m.Parameter(0);
    1320           1 :   Node* const p1 = m.Parameter(1);
    1321             :   m.Return(
    1322           1 :       m.Word32And(p0, m.Load(MachineType::Int32(), p1, m.Int32Constant(127))));
    1323           1 :   Stream s = m.Build();
    1324           2 :   ASSERT_EQ(1U, s.size());
    1325           3 :   EXPECT_EQ(kX64And32, s[0]->arch_opcode());
    1326           3 :   ASSERT_EQ(3U, s[0]->InputCount());
    1327           3 :   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
    1328           3 :   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
    1329             : }
    1330             : 
    1331       15128 : TEST_F(InstructionSelectorTest, LoadOr32) {
    1332             :   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
    1333           1 :                   MachineType::Int32());
    1334           1 :   Node* const p0 = m.Parameter(0);
    1335           1 :   Node* const p1 = m.Parameter(1);
    1336             :   m.Return(
    1337           1 :       m.Word32Or(p0, m.Load(MachineType::Int32(), p1, m.Int32Constant(127))));
    1338           1 :   Stream s = m.Build();
    1339           2 :   ASSERT_EQ(1U, s.size());
    1340           3 :   EXPECT_EQ(kX64Or32, s[0]->arch_opcode());
    1341           3 :   ASSERT_EQ(3U, s[0]->InputCount());
    1342           3 :   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
    1343           3 :   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
    1344             : }
    1345             : 
    1346       15128 : TEST_F(InstructionSelectorTest, LoadXor32) {
    1347             :   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
    1348           1 :                   MachineType::Int32());
    1349           1 :   Node* const p0 = m.Parameter(0);
    1350           1 :   Node* const p1 = m.Parameter(1);
    1351             :   m.Return(
    1352           1 :       m.Word32Xor(p0, m.Load(MachineType::Int32(), p1, m.Int32Constant(127))));
    1353           1 :   Stream s = m.Build();
    1354           2 :   ASSERT_EQ(1U, s.size());
    1355           3 :   EXPECT_EQ(kX64Xor32, s[0]->arch_opcode());
    1356           3 :   ASSERT_EQ(3U, s[0]->InputCount());
    1357           3 :   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
    1358           3 :   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
    1359             : }
    1360             : 
    1361       15128 : TEST_F(InstructionSelectorTest, LoadAdd32) {
    1362             :   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
    1363           1 :                   MachineType::Int32());
    1364           1 :   Node* const p0 = m.Parameter(0);
    1365           1 :   Node* const p1 = m.Parameter(1);
    1366             :   m.Return(
    1367           1 :       m.Int32Add(p0, m.Load(MachineType::Int32(), p1, m.Int32Constant(127))));
    1368           1 :   Stream s = m.Build();
    1369             :   // Use lea instead of add, so memory operand is invalid.
    1370           3 :   ASSERT_EQ(2U, s.size());
    1371           3 :   EXPECT_EQ(kX64Movl, s[0]->arch_opcode());
    1372           3 :   EXPECT_EQ(kX64Lea32, s[1]->arch_opcode());
    1373             : }
    1374             : 
    1375       15128 : TEST_F(InstructionSelectorTest, LoadSub32) {
    1376             :   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
    1377           1 :                   MachineType::Int32());
    1378           1 :   Node* const p0 = m.Parameter(0);
    1379           1 :   Node* const p1 = m.Parameter(1);
    1380             :   m.Return(
    1381           1 :       m.Int32Sub(p0, m.Load(MachineType::Int32(), p1, m.Int32Constant(127))));
    1382           1 :   Stream s = m.Build();
    1383           2 :   ASSERT_EQ(1U, s.size());
    1384           3 :   EXPECT_EQ(kX64Sub32, s[0]->arch_opcode());
    1385           3 :   ASSERT_EQ(3U, s[0]->InputCount());
    1386           3 :   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
    1387           3 :   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
    1388             : }
    1389             : 
    1390       15128 : TEST_F(InstructionSelectorTest, LoadAnd64) {
    1391             :   StreamBuilder m(this, MachineType::Int64(), MachineType::Int64(),
    1392           1 :                   MachineType::Int64());
    1393           1 :   Node* const p0 = m.Parameter(0);
    1394           1 :   Node* const p1 = m.Parameter(1);
    1395             :   m.Return(
    1396           1 :       m.Word64And(p0, m.Load(MachineType::Int64(), p1, m.Int32Constant(127))));
    1397           1 :   Stream s = m.Build();
    1398           2 :   ASSERT_EQ(1U, s.size());
    1399           3 :   EXPECT_EQ(kX64And, s[0]->arch_opcode());
    1400           3 :   ASSERT_EQ(3U, s[0]->InputCount());
    1401           3 :   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
    1402           3 :   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
    1403             : }
    1404             : 
    1405       15128 : TEST_F(InstructionSelectorTest, LoadOr64) {
    1406             :   StreamBuilder m(this, MachineType::Int64(), MachineType::Int64(),
    1407           1 :                   MachineType::Int64());
    1408           1 :   Node* const p0 = m.Parameter(0);
    1409           1 :   Node* const p1 = m.Parameter(1);
    1410             :   m.Return(
    1411           1 :       m.Word64Or(p0, m.Load(MachineType::Int64(), p1, m.Int32Constant(127))));
    1412           1 :   Stream s = m.Build();
    1413           2 :   ASSERT_EQ(1U, s.size());
    1414           3 :   EXPECT_EQ(kX64Or, s[0]->arch_opcode());
    1415           3 :   ASSERT_EQ(3U, s[0]->InputCount());
    1416           3 :   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
    1417           3 :   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
    1418             : }
    1419             : 
    1420       15128 : TEST_F(InstructionSelectorTest, LoadXor64) {
    1421             :   StreamBuilder m(this, MachineType::Int64(), MachineType::Int64(),
    1422           1 :                   MachineType::Int64());
    1423           1 :   Node* const p0 = m.Parameter(0);
    1424           1 :   Node* const p1 = m.Parameter(1);
    1425             :   m.Return(
    1426           1 :       m.Word64Xor(p0, m.Load(MachineType::Int64(), p1, m.Int32Constant(127))));
    1427           1 :   Stream s = m.Build();
    1428           2 :   ASSERT_EQ(1U, s.size());
    1429           3 :   EXPECT_EQ(kX64Xor, s[0]->arch_opcode());
    1430           3 :   ASSERT_EQ(3U, s[0]->InputCount());
    1431           3 :   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
    1432           3 :   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
    1433             : }
    1434             : 
    1435       15128 : TEST_F(InstructionSelectorTest, LoadAdd64) {
    1436             :   StreamBuilder m(this, MachineType::Int64(), MachineType::Int64(),
    1437           1 :                   MachineType::Int64());
    1438           1 :   Node* const p0 = m.Parameter(0);
    1439           1 :   Node* const p1 = m.Parameter(1);
    1440             :   m.Return(
    1441           1 :       m.Int64Add(p0, m.Load(MachineType::Int64(), p1, m.Int32Constant(127))));
    1442           1 :   Stream s = m.Build();
    1443             :   // Use lea instead of add, so memory operand is invalid.
    1444           3 :   ASSERT_EQ(2U, s.size());
    1445           3 :   EXPECT_EQ(kX64Movq, s[0]->arch_opcode());
    1446           3 :   EXPECT_EQ(kX64Lea, s[1]->arch_opcode());
    1447             : }
    1448             : 
    1449       15128 : TEST_F(InstructionSelectorTest, LoadSub64) {
    1450             :   StreamBuilder m(this, MachineType::Int64(), MachineType::Int64(),
    1451           1 :                   MachineType::Int64());
    1452           1 :   Node* const p0 = m.Parameter(0);
    1453           1 :   Node* const p1 = m.Parameter(1);
    1454             :   m.Return(
    1455           1 :       m.Int64Sub(p0, m.Load(MachineType::Int64(), p1, m.Int32Constant(127))));
    1456           1 :   Stream s = m.Build();
    1457           2 :   ASSERT_EQ(1U, s.size());
    1458           3 :   EXPECT_EQ(kX64Sub, s[0]->arch_opcode());
    1459           3 :   ASSERT_EQ(3U, s[0]->InputCount());
    1460           3 :   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
    1461           3 :   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
    1462             : }
    1463             : 
    1464             : // -----------------------------------------------------------------------------
    1465             : // Floating point operations.
    1466             : 
    1467       15128 : TEST_F(InstructionSelectorTest, Float32Abs) {
    1468             :   {
    1469           1 :     StreamBuilder m(this, MachineType::Float32(), MachineType::Float32());
    1470           1 :     Node* const p0 = m.Parameter(0);
    1471           1 :     Node* const n = m.Float32Abs(p0);
    1472           1 :     m.Return(n);
    1473           1 :     Stream s = m.Build();
    1474           2 :     ASSERT_EQ(1U, s.size());
    1475           3 :     EXPECT_EQ(kSSEFloat32Abs, s[0]->arch_opcode());
    1476           3 :     ASSERT_EQ(1U, s[0]->InputCount());
    1477           3 :     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
    1478           3 :     ASSERT_EQ(1U, s[0]->OutputCount());
    1479           2 :     EXPECT_TRUE(s.IsSameAsFirst(s[0]->Output()));
    1480           2 :     EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
    1481           3 :     EXPECT_EQ(kFlags_none, s[0]->flags_mode());
    1482             :   }
    1483             :   {
    1484           1 :     StreamBuilder m(this, MachineType::Float32(), MachineType::Float32());
    1485           1 :     Node* const p0 = m.Parameter(0);
    1486           1 :     Node* const n = m.Float32Abs(p0);
    1487           1 :     m.Return(n);
    1488           1 :     Stream s = m.Build(AVX);
    1489           2 :     ASSERT_EQ(1U, s.size());
    1490           3 :     EXPECT_EQ(kAVXFloat32Abs, s[0]->arch_opcode());
    1491           3 :     ASSERT_EQ(1U, s[0]->InputCount());
    1492           3 :     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
    1493           3 :     ASSERT_EQ(1U, s[0]->OutputCount());
    1494           2 :     EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
    1495           3 :     EXPECT_EQ(kFlags_none, s[0]->flags_mode());
    1496             :   }
    1497             : }
    1498             : 
    1499             : 
    1500       15128 : TEST_F(InstructionSelectorTest, Float64Abs) {
    1501             :   {
    1502           1 :     StreamBuilder m(this, MachineType::Float64(), MachineType::Float64());
    1503           1 :     Node* const p0 = m.Parameter(0);
    1504           1 :     Node* const n = m.Float64Abs(p0);
    1505           1 :     m.Return(n);
    1506           1 :     Stream s = m.Build();
    1507           2 :     ASSERT_EQ(1U, s.size());
    1508           3 :     EXPECT_EQ(kSSEFloat64Abs, s[0]->arch_opcode());
    1509           3 :     ASSERT_EQ(1U, s[0]->InputCount());
    1510           3 :     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
    1511           3 :     ASSERT_EQ(1U, s[0]->OutputCount());
    1512           2 :     EXPECT_TRUE(s.IsSameAsFirst(s[0]->Output()));
    1513           2 :     EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
    1514           3 :     EXPECT_EQ(kFlags_none, s[0]->flags_mode());
    1515             :   }
    1516             :   {
    1517           1 :     StreamBuilder m(this, MachineType::Float64(), MachineType::Float64());
    1518           1 :     Node* const p0 = m.Parameter(0);
    1519           1 :     Node* const n = m.Float64Abs(p0);
    1520           1 :     m.Return(n);
    1521           1 :     Stream s = m.Build(AVX);
    1522           2 :     ASSERT_EQ(1U, s.size());
    1523           3 :     EXPECT_EQ(kAVXFloat64Abs, s[0]->arch_opcode());
    1524           3 :     ASSERT_EQ(1U, s[0]->InputCount());
    1525           3 :     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
    1526           3 :     ASSERT_EQ(1U, s[0]->OutputCount());
    1527           2 :     EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
    1528           3 :     EXPECT_EQ(kFlags_none, s[0]->flags_mode());
    1529             :   }
    1530             : }
    1531             : 
    1532             : 
    1533       15128 : TEST_F(InstructionSelectorTest, Float64BinopArithmetic) {
    1534             :   {
    1535             :     StreamBuilder m(this, MachineType::Float64(), MachineType::Float64(),
    1536           1 :                     MachineType::Float64());
    1537           1 :     Node* add = m.Float64Add(m.Parameter(0), m.Parameter(1));
    1538           1 :     Node* mul = m.Float64Mul(add, m.Parameter(1));
    1539           1 :     Node* sub = m.Float64Sub(mul, add);
    1540           1 :     Node* ret = m.Float64Div(mul, sub);
    1541           1 :     m.Return(ret);
    1542           1 :     Stream s = m.Build(AVX);
    1543           2 :     ASSERT_EQ(4U, s.size());
    1544           3 :     EXPECT_EQ(kAVXFloat64Add, s[0]->arch_opcode());
    1545           3 :     EXPECT_EQ(kAVXFloat64Mul, s[1]->arch_opcode());
    1546           3 :     EXPECT_EQ(kAVXFloat64Sub, s[2]->arch_opcode());
    1547           3 :     EXPECT_EQ(kAVXFloat64Div, s[3]->arch_opcode());
    1548             :   }
    1549             :   {
    1550             :     StreamBuilder m(this, MachineType::Float64(), MachineType::Float64(),
    1551           1 :                     MachineType::Float64());
    1552           1 :     Node* add = m.Float64Add(m.Parameter(0), m.Parameter(1));
    1553           1 :     Node* mul = m.Float64Mul(add, m.Parameter(1));
    1554           1 :     Node* sub = m.Float64Sub(mul, add);
    1555           1 :     Node* ret = m.Float64Div(mul, sub);
    1556           1 :     m.Return(ret);
    1557           1 :     Stream s = m.Build();
    1558           2 :     ASSERT_EQ(4U, s.size());
    1559           3 :     EXPECT_EQ(kSSEFloat64Add, s[0]->arch_opcode());
    1560           3 :     EXPECT_EQ(kSSEFloat64Mul, s[1]->arch_opcode());
    1561           3 :     EXPECT_EQ(kSSEFloat64Sub, s[2]->arch_opcode());
    1562           3 :     EXPECT_EQ(kSSEFloat64Div, s[3]->arch_opcode());
    1563             :   }
    1564             : }
    1565             : 
    1566             : // -----------------------------------------------------------------------------
    1567             : // Miscellaneous.
    1568             : 
    1569             : 
    1570       15128 : TEST_F(InstructionSelectorTest, Word64ShlWithChangeInt32ToInt64) {
    1571         225 :   TRACED_FORRANGE(int64_t, x, 32, 63) {
    1572          32 :     StreamBuilder m(this, MachineType::Int64(), MachineType::Int32());
    1573          32 :     Node* const p0 = m.Parameter(0);
    1574          32 :     Node* const n = m.Word64Shl(m.ChangeInt32ToInt64(p0), m.Int64Constant(x));
    1575          32 :     m.Return(n);
    1576          32 :     Stream s = m.Build();
    1577          64 :     ASSERT_EQ(1U, s.size());
    1578          96 :     EXPECT_EQ(kX64Shl, s[0]->arch_opcode());
    1579          96 :     ASSERT_EQ(2U, s[0]->InputCount());
    1580          96 :     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
    1581         128 :     EXPECT_EQ(x, s.ToInt32(s[0]->InputAt(1)));
    1582          96 :     ASSERT_EQ(1U, s[0]->OutputCount());
    1583          64 :     EXPECT_TRUE(s.IsSameAsFirst(s[0]->Output()));
    1584          64 :     EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
    1585          32 :   }
    1586             : }
    1587             : 
    1588             : 
    1589       15128 : TEST_F(InstructionSelectorTest, Word64ShlWithChangeUint32ToUint64) {
    1590         225 :   TRACED_FORRANGE(int64_t, x, 32, 63) {
    1591          32 :     StreamBuilder m(this, MachineType::Int64(), MachineType::Uint32());
    1592          32 :     Node* const p0 = m.Parameter(0);
    1593          32 :     Node* const n = m.Word64Shl(m.ChangeUint32ToUint64(p0), m.Int64Constant(x));
    1594          32 :     m.Return(n);
    1595          32 :     Stream s = m.Build();
    1596          64 :     ASSERT_EQ(1U, s.size());
    1597          96 :     EXPECT_EQ(kX64Shl, s[0]->arch_opcode());
    1598          96 :     ASSERT_EQ(2U, s[0]->InputCount());
    1599          96 :     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
    1600         128 :     EXPECT_EQ(x, s.ToInt32(s[0]->InputAt(1)));
    1601          96 :     ASSERT_EQ(1U, s[0]->OutputCount());
    1602          64 :     EXPECT_TRUE(s.IsSameAsFirst(s[0]->Output()));
    1603          64 :     EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
    1604          32 :   }
    1605             : }
    1606             : 
    1607       15128 : TEST_F(InstructionSelectorTest, Word32AndWith0xFF) {
    1608             :   {
    1609           1 :     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
    1610           1 :     Node* const p0 = m.Parameter(0);
    1611           1 :     Node* const n = m.Word32And(p0, m.Int32Constant(0xFF));
    1612           1 :     m.Return(n);
    1613           1 :     Stream s = m.Build();
    1614           2 :     ASSERT_EQ(1U, s.size());
    1615           3 :     EXPECT_EQ(kX64Movzxbl, s[0]->arch_opcode());
    1616           3 :     ASSERT_EQ(1U, s[0]->InputCount());
    1617           3 :     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
    1618           3 :     ASSERT_EQ(1U, s[0]->OutputCount());
    1619           2 :     EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
    1620             :   }
    1621             :   {
    1622           1 :     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
    1623           1 :     Node* const p0 = m.Parameter(0);
    1624           1 :     Node* const n = m.Word32And(m.Int32Constant(0xFF), p0);
    1625           1 :     m.Return(n);
    1626           1 :     Stream s = m.Build();
    1627           2 :     ASSERT_EQ(1U, s.size());
    1628           3 :     EXPECT_EQ(kX64Movzxbl, s[0]->arch_opcode());
    1629           3 :     ASSERT_EQ(1U, s[0]->InputCount());
    1630           3 :     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
    1631           3 :     ASSERT_EQ(1U, s[0]->OutputCount());
    1632           2 :     EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
    1633             :   }
    1634             : }
    1635             : 
    1636       15128 : TEST_F(InstructionSelectorTest, Word32AndWith0xFFFF) {
    1637             :   {
    1638           1 :     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
    1639           1 :     Node* const p0 = m.Parameter(0);
    1640           1 :     Node* const n = m.Word32And(p0, m.Int32Constant(0xFFFF));
    1641           1 :     m.Return(n);
    1642           1 :     Stream s = m.Build();
    1643           2 :     ASSERT_EQ(1U, s.size());
    1644           3 :     EXPECT_EQ(kX64Movzxwl, s[0]->arch_opcode());
    1645           3 :     ASSERT_EQ(1U, s[0]->InputCount());
    1646           3 :     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
    1647           3 :     ASSERT_EQ(1U, s[0]->OutputCount());
    1648           2 :     EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
    1649             :   }
    1650             :   {
    1651           1 :     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
    1652           1 :     Node* const p0 = m.Parameter(0);
    1653           1 :     Node* const n = m.Word32And(m.Int32Constant(0xFFFF), p0);
    1654           1 :     m.Return(n);
    1655           1 :     Stream s = m.Build();
    1656           2 :     ASSERT_EQ(1U, s.size());
    1657           3 :     EXPECT_EQ(kX64Movzxwl, s[0]->arch_opcode());
    1658           3 :     ASSERT_EQ(1U, s[0]->InputCount());
    1659           3 :     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
    1660           3 :     ASSERT_EQ(1U, s[0]->OutputCount());
    1661           2 :     EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
    1662             :   }
    1663             : }
    1664             : 
    1665             : 
    1666       15128 : TEST_F(InstructionSelectorTest, Word32Clz) {
    1667           1 :   StreamBuilder m(this, MachineType::Uint32(), MachineType::Uint32());
    1668           1 :   Node* const p0 = m.Parameter(0);
    1669           1 :   Node* const n = m.Word32Clz(p0);
    1670           1 :   m.Return(n);
    1671           1 :   Stream s = m.Build();
    1672           2 :   ASSERT_EQ(1U, s.size());
    1673           3 :   EXPECT_EQ(kX64Lzcnt32, s[0]->arch_opcode());
    1674           3 :   ASSERT_EQ(1U, s[0]->InputCount());
    1675           3 :   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
    1676           3 :   ASSERT_EQ(1U, s[0]->OutputCount());
    1677           2 :   EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
    1678             : }
    1679             : 
    1680       15128 : TEST_F(InstructionSelectorTest, LoadAndWord64ShiftRight32) {
    1681             :   {
    1682           1 :     StreamBuilder m(this, MachineType::Uint64(), MachineType::Uint32());
    1683           1 :     Node* const p0 = m.Parameter(0);
    1684           1 :     Node* const load = m.Load(MachineType::Uint64(), p0);
    1685           1 :     Node* const shift = m.Word64Shr(load, m.Int32Constant(32));
    1686           1 :     m.Return(shift);
    1687           1 :     Stream s = m.Build();
    1688           2 :     ASSERT_EQ(1U, s.size());
    1689           3 :     EXPECT_EQ(kX64Movl, s[0]->arch_opcode());
    1690           3 :     ASSERT_EQ(2U, s[0]->InputCount());
    1691           3 :     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
    1692           4 :     EXPECT_EQ(4, s.ToInt32(s[0]->InputAt(1)));
    1693           3 :     ASSERT_EQ(1U, s[0]->OutputCount());
    1694           2 :     EXPECT_EQ(s.ToVreg(shift), s.ToVreg(s[0]->Output()));
    1695             :   }
    1696             :   {
    1697           1 :     StreamBuilder m(this, MachineType::Int64(), MachineType::Int32());
    1698           1 :     Node* const p0 = m.Parameter(0);
    1699           1 :     Node* const load = m.Load(MachineType::Int64(), p0);
    1700           1 :     Node* const shift = m.Word64Sar(load, m.Int32Constant(32));
    1701           1 :     m.Return(shift);
    1702           1 :     Stream s = m.Build();
    1703           2 :     ASSERT_EQ(1U, s.size());
    1704           3 :     EXPECT_EQ(kX64Movsxlq, s[0]->arch_opcode());
    1705           3 :     ASSERT_EQ(2U, s[0]->InputCount());
    1706           3 :     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
    1707           4 :     EXPECT_EQ(4, s.ToInt32(s[0]->InputAt(1)));
    1708           3 :     ASSERT_EQ(1U, s[0]->OutputCount());
    1709           2 :     EXPECT_EQ(s.ToVreg(shift), s.ToVreg(s[0]->Output()));
    1710             :   }
    1711             :   {
    1712           1 :     StreamBuilder m(this, MachineType::Int64(), MachineType::Int32());
    1713           1 :     Node* const p0 = m.Parameter(0);
    1714           1 :     Node* const load = m.Load(MachineType::Int64(), p0);
    1715           1 :     Node* const shift = m.Word64Sar(load, m.Int32Constant(32));
    1716           1 :     Node* const truncate = m.TruncateInt64ToInt32(shift);
    1717           1 :     m.Return(truncate);
    1718           1 :     Stream s = m.Build();
    1719           2 :     ASSERT_EQ(1U, s.size());
    1720           3 :     EXPECT_EQ(kX64Movl, s[0]->arch_opcode());
    1721           3 :     ASSERT_EQ(2U, s[0]->InputCount());
    1722           3 :     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
    1723           4 :     EXPECT_EQ(4, s.ToInt32(s[0]->InputAt(1)));
    1724           3 :     ASSERT_EQ(1U, s[0]->OutputCount());
    1725           2 :     EXPECT_EQ(s.ToVreg(shift), s.ToVreg(s[0]->Output()));
    1726             :   }
    1727             : }
    1728             : 
    1729       15128 : TEST_F(InstructionSelectorTest, SpeculationFence) {
    1730           1 :   StreamBuilder m(this, MachineType::Int32());
    1731           1 :   m.SpeculationFence();
    1732           1 :   m.Return(m.Int32Constant(0));
    1733           1 :   Stream s = m.Build();
    1734           3 :   ASSERT_EQ(1U, s.size());
    1735           3 :   EXPECT_EQ(kLFence, s[0]->arch_opcode());
    1736             : }
    1737             : 
    1738       15128 : TEST_F(InstructionSelectorTest, StackCheck0) {
    1739             :   ExternalReference js_stack_limit =
    1740           1 :       ExternalReference::Create(isolate()->stack_guard()->address_of_jslimit());
    1741           1 :   StreamBuilder m(this, MachineType::Int32());
    1742           1 :   Node* const sp = m.LoadStackPointer();
    1743             :   Node* const stack_limit =
    1744           1 :       m.Load(MachineType::Pointer(), m.ExternalConstant(js_stack_limit));
    1745             :   Node* const interrupt = m.UintPtrLessThan(sp, stack_limit);
    1746             : 
    1747           1 :   RawMachineLabel if_true, if_false;
    1748           1 :   m.Branch(interrupt, &if_true, &if_false);
    1749             : 
    1750           1 :   m.Bind(&if_true);
    1751           1 :   m.Return(m.Int32Constant(1));
    1752             : 
    1753           1 :   m.Bind(&if_false);
    1754           1 :   m.Return(m.Int32Constant(0));
    1755             : 
    1756           1 :   Stream s = m.Build();
    1757             : 
    1758           3 :   ASSERT_EQ(1U, s.size());
    1759           3 :   EXPECT_EQ(kX64Cmp, s[0]->arch_opcode());
    1760           3 :   EXPECT_EQ(4U, s[0]->InputCount());
    1761           3 :   EXPECT_EQ(0U, s[0]->OutputCount());
    1762             : }
    1763             : 
    1764       15128 : TEST_F(InstructionSelectorTest, StackCheck1) {
    1765             :   ExternalReference js_stack_limit =
    1766           1 :       ExternalReference::Create(isolate()->stack_guard()->address_of_jslimit());
    1767           1 :   StreamBuilder m(this, MachineType::Int32());
    1768           1 :   Node* const sp = m.LoadStackPointer();
    1769             :   Node* const stack_limit =
    1770           1 :       m.Load(MachineType::Pointer(), m.ExternalConstant(js_stack_limit));
    1771             :   Node* const sp_within_limit = m.UintPtrLessThan(stack_limit, sp);
    1772             : 
    1773           1 :   RawMachineLabel if_true, if_false;
    1774           1 :   m.Branch(sp_within_limit, &if_true, &if_false);
    1775             : 
    1776           1 :   m.Bind(&if_true);
    1777           1 :   m.Return(m.Int32Constant(1));
    1778             : 
    1779           1 :   m.Bind(&if_false);
    1780           1 :   m.Return(m.Int32Constant(0));
    1781             : 
    1782           1 :   Stream s = m.Build();
    1783             : 
    1784           3 :   ASSERT_EQ(1U, s.size());
    1785           3 :   EXPECT_EQ(kX64StackCheck, s[0]->arch_opcode());
    1786           3 :   EXPECT_EQ(2U, s[0]->InputCount());
    1787           3 :   EXPECT_EQ(0U, s[0]->OutputCount());
    1788             : }
    1789             : 
    1790             : }  // namespace compiler
    1791             : }  // namespace internal
    1792        9075 : }  // namespace v8

Generated by: LCOV version 1.10