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

Generated by: LCOV version 1.10