Home | History | Annotate | Download | only in arm64
      1 // Copyright 2014 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "test/unittests/compiler/instruction-selector-unittest.h"
      6 
      7 namespace v8 {
      8 namespace internal {
      9 namespace compiler {
     10 
     11 namespace {
     12 
     13 template <typename T>
     14 struct MachInst {
     15   T constructor;
     16   const char* constructor_name;
     17   ArchOpcode arch_opcode;
     18   MachineType machine_type;
     19 };
     20 
     21 typedef MachInst<Node* (RawMachineAssembler::*)(Node*)> MachInst1;
     22 typedef MachInst<Node* (RawMachineAssembler::*)(Node*, Node*)> MachInst2;
     23 
     24 
     25 template <typename T>
     26 std::ostream& operator<<(std::ostream& os, const MachInst<T>& mi) {
     27   return os << mi.constructor_name;
     28 }
     29 
     30 
     31 struct Shift {
     32   MachInst2 mi;
     33   AddressingMode mode;
     34 };
     35 
     36 
     37 std::ostream& operator<<(std::ostream& os, const Shift& shift) {
     38   return os << shift.mi;
     39 }
     40 
     41 
     42 // Helper to build Int32Constant or Int64Constant depending on the given
     43 // machine type.
     44 Node* BuildConstant(InstructionSelectorTest::StreamBuilder& m, MachineType type,
     45                     int64_t value) {
     46   switch (type.representation()) {
     47     case MachineRepresentation::kWord32:
     48       return m.Int32Constant(static_cast<int32_t>(value));
     49       break;
     50 
     51     case MachineRepresentation::kWord64:
     52       return m.Int64Constant(value);
     53       break;
     54 
     55     default:
     56       UNIMPLEMENTED();
     57   }
     58   return NULL;
     59 }
     60 
     61 
     62 // ARM64 logical instructions.
     63 const MachInst2 kLogicalInstructions[] = {
     64     {&RawMachineAssembler::Word32And, "Word32And", kArm64And32,
     65      MachineType::Int32()},
     66     {&RawMachineAssembler::Word64And, "Word64And", kArm64And,
     67      MachineType::Int64()},
     68     {&RawMachineAssembler::Word32Or, "Word32Or", kArm64Or32,
     69      MachineType::Int32()},
     70     {&RawMachineAssembler::Word64Or, "Word64Or", kArm64Or,
     71      MachineType::Int64()},
     72     {&RawMachineAssembler::Word32Xor, "Word32Xor", kArm64Eor32,
     73      MachineType::Int32()},
     74     {&RawMachineAssembler::Word64Xor, "Word64Xor", kArm64Eor,
     75      MachineType::Int64()}};
     76 
     77 
     78 // ARM64 logical immediates: contiguous set bits, rotated about a power of two
     79 // sized block. The block is then duplicated across the word. Below is a random
     80 // subset of the 32-bit immediates.
     81 const uint32_t kLogical32Immediates[] = {
     82     0x00000002, 0x00000003, 0x00000070, 0x00000080, 0x00000100, 0x000001c0,
     83     0x00000300, 0x000007e0, 0x00003ffc, 0x00007fc0, 0x0003c000, 0x0003f000,
     84     0x0003ffc0, 0x0003fff8, 0x0007ff00, 0x0007ffe0, 0x000e0000, 0x001e0000,
     85     0x001ffffc, 0x003f0000, 0x003f8000, 0x00780000, 0x007fc000, 0x00ff0000,
     86     0x01800000, 0x01800180, 0x01f801f8, 0x03fe0000, 0x03ffffc0, 0x03fffffc,
     87     0x06000000, 0x07fc0000, 0x07ffc000, 0x07ffffc0, 0x07ffffe0, 0x0ffe0ffe,
     88     0x0ffff800, 0x0ffffff0, 0x0fffffff, 0x18001800, 0x1f001f00, 0x1f801f80,
     89     0x30303030, 0x3ff03ff0, 0x3ff83ff8, 0x3fff0000, 0x3fff8000, 0x3fffffc0,
     90     0x70007000, 0x7f7f7f7f, 0x7fc00000, 0x7fffffc0, 0x8000001f, 0x800001ff,
     91     0x81818181, 0x9fff9fff, 0xc00007ff, 0xc0ffffff, 0xdddddddd, 0xe00001ff,
     92     0xe00003ff, 0xe007ffff, 0xefffefff, 0xf000003f, 0xf001f001, 0xf3fff3ff,
     93     0xf800001f, 0xf80fffff, 0xf87ff87f, 0xfbfbfbfb, 0xfc00001f, 0xfc0000ff,
     94     0xfc0001ff, 0xfc03fc03, 0xfe0001ff, 0xff000001, 0xff03ff03, 0xff800000,
     95     0xff800fff, 0xff801fff, 0xff87ffff, 0xffc0003f, 0xffc007ff, 0xffcfffcf,
     96     0xffe00003, 0xffe1ffff, 0xfff0001f, 0xfff07fff, 0xfff80007, 0xfff87fff,
     97     0xfffc00ff, 0xfffe07ff, 0xffff00ff, 0xffffc001, 0xfffff007, 0xfffff3ff,
     98     0xfffff807, 0xfffff9ff, 0xfffffc0f, 0xfffffeff};
     99 
    100 
    101 // Random subset of 64-bit logical immediates.
    102 const uint64_t kLogical64Immediates[] = {
    103     0x0000000000000001, 0x0000000000000002, 0x0000000000000003,
    104     0x0000000000000070, 0x0000000000000080, 0x0000000000000100,
    105     0x00000000000001c0, 0x0000000000000300, 0x0000000000000600,
    106     0x00000000000007e0, 0x0000000000003ffc, 0x0000000000007fc0,
    107     0x0000000600000000, 0x0000003ffffffffc, 0x000000f000000000,
    108     0x000001f800000000, 0x0003fc0000000000, 0x0003fc000003fc00,
    109     0x0003ffffffc00000, 0x0003ffffffffffc0, 0x0006000000060000,
    110     0x003ffffffffc0000, 0x0180018001800180, 0x01f801f801f801f8,
    111     0x0600000000000000, 0x1000000010000000, 0x1000100010001000,
    112     0x1010101010101010, 0x1111111111111111, 0x1f001f001f001f00,
    113     0x1f1f1f1f1f1f1f1f, 0x1ffffffffffffffe, 0x3ffc3ffc3ffc3ffc,
    114     0x5555555555555555, 0x7f7f7f7f7f7f7f7f, 0x8000000000000000,
    115     0x8000001f8000001f, 0x8181818181818181, 0x9999999999999999,
    116     0x9fff9fff9fff9fff, 0xaaaaaaaaaaaaaaaa, 0xdddddddddddddddd,
    117     0xe0000000000001ff, 0xf800000000000000, 0xf8000000000001ff,
    118     0xf807f807f807f807, 0xfefefefefefefefe, 0xfffefffefffefffe,
    119     0xfffff807fffff807, 0xfffff9fffffff9ff, 0xfffffc0ffffffc0f,
    120     0xfffffc0fffffffff, 0xfffffefffffffeff, 0xfffffeffffffffff,
    121     0xffffff8000000000, 0xfffffffefffffffe, 0xffffffffefffffff,
    122     0xfffffffff9ffffff, 0xffffffffff800000, 0xffffffffffffc0ff,
    123     0xfffffffffffffffe};
    124 
    125 
    126 // ARM64 arithmetic instructions.
    127 struct AddSub {
    128   MachInst2 mi;
    129   ArchOpcode negate_arch_opcode;
    130 };
    131 
    132 
    133 std::ostream& operator<<(std::ostream& os, const AddSub& op) {
    134   return os << op.mi;
    135 }
    136 
    137 
    138 const AddSub kAddSubInstructions[] = {
    139     {{&RawMachineAssembler::Int32Add, "Int32Add", kArm64Add32,
    140       MachineType::Int32()},
    141      kArm64Sub32},
    142     {{&RawMachineAssembler::Int64Add, "Int64Add", kArm64Add,
    143       MachineType::Int64()},
    144      kArm64Sub},
    145     {{&RawMachineAssembler::Int32Sub, "Int32Sub", kArm64Sub32,
    146       MachineType::Int32()},
    147      kArm64Add32},
    148     {{&RawMachineAssembler::Int64Sub, "Int64Sub", kArm64Sub,
    149       MachineType::Int64()},
    150      kArm64Add}};
    151 
    152 
    153 // ARM64 Add/Sub immediates: 12-bit immediate optionally shifted by 12.
    154 // Below is a combination of a random subset and some edge values.
    155 const int32_t kAddSubImmediates[] = {
    156     0,        1,        69,       493,      599,      701,      719,
    157     768,      818,      842,      945,      1246,     1286,     1429,
    158     1669,     2171,     2179,     2182,     2254,     2334,     2338,
    159     2343,     2396,     2449,     2610,     2732,     2855,     2876,
    160     2944,     3377,     3458,     3475,     3476,     3540,     3574,
    161     3601,     3813,     3871,     3917,     4095,     4096,     16384,
    162     364544,   462848,   970752,   1523712,  1863680,  2363392,  3219456,
    163     3280896,  4247552,  4526080,  4575232,  4960256,  5505024,  5894144,
    164     6004736,  6193152,  6385664,  6795264,  7114752,  7233536,  7348224,
    165     7499776,  7573504,  7729152,  8634368,  8937472,  9465856,  10354688,
    166     10682368, 11059200, 11460608, 13168640, 13176832, 14336000, 15028224,
    167     15597568, 15892480, 16773120};
    168 
    169 
    170 // ARM64 flag setting data processing instructions.
    171 const MachInst2 kDPFlagSetInstructions[] = {
    172     {&RawMachineAssembler::Word32And, "Word32And", kArm64Tst32,
    173      MachineType::Int32()},
    174     {&RawMachineAssembler::Int32Add, "Int32Add", kArm64Cmn32,
    175      MachineType::Int32()},
    176     {&RawMachineAssembler::Int32Sub, "Int32Sub", kArm64Cmp32,
    177      MachineType::Int32()},
    178     {&RawMachineAssembler::Word64And, "Word64And", kArm64Tst,
    179      MachineType::Int64()}};
    180 
    181 
    182 // ARM64 arithmetic with overflow instructions.
    183 const MachInst2 kOvfAddSubInstructions[] = {
    184     {&RawMachineAssembler::Int32AddWithOverflow, "Int32AddWithOverflow",
    185      kArm64Add32, MachineType::Int32()},
    186     {&RawMachineAssembler::Int32SubWithOverflow, "Int32SubWithOverflow",
    187      kArm64Sub32, MachineType::Int32()},
    188     {&RawMachineAssembler::Int64AddWithOverflow, "Int64AddWithOverflow",
    189      kArm64Add, MachineType::Int64()},
    190     {&RawMachineAssembler::Int64SubWithOverflow, "Int64SubWithOverflow",
    191      kArm64Sub, MachineType::Int64()}};
    192 
    193 // ARM64 shift instructions.
    194 const Shift kShiftInstructions[] = {
    195     {{&RawMachineAssembler::Word32Shl, "Word32Shl", kArm64Lsl32,
    196       MachineType::Int32()},
    197      kMode_Operand2_R_LSL_I},
    198     {{&RawMachineAssembler::Word64Shl, "Word64Shl", kArm64Lsl,
    199       MachineType::Int64()},
    200      kMode_Operand2_R_LSL_I},
    201     {{&RawMachineAssembler::Word32Shr, "Word32Shr", kArm64Lsr32,
    202       MachineType::Int32()},
    203      kMode_Operand2_R_LSR_I},
    204     {{&RawMachineAssembler::Word64Shr, "Word64Shr", kArm64Lsr,
    205       MachineType::Int64()},
    206      kMode_Operand2_R_LSR_I},
    207     {{&RawMachineAssembler::Word32Sar, "Word32Sar", kArm64Asr32,
    208       MachineType::Int32()},
    209      kMode_Operand2_R_ASR_I},
    210     {{&RawMachineAssembler::Word64Sar, "Word64Sar", kArm64Asr,
    211       MachineType::Int64()},
    212      kMode_Operand2_R_ASR_I},
    213     {{&RawMachineAssembler::Word32Ror, "Word32Ror", kArm64Ror32,
    214       MachineType::Int32()},
    215      kMode_Operand2_R_ROR_I},
    216     {{&RawMachineAssembler::Word64Ror, "Word64Ror", kArm64Ror,
    217       MachineType::Int64()},
    218      kMode_Operand2_R_ROR_I}};
    219 
    220 
    221 // ARM64 Mul/Div instructions.
    222 const MachInst2 kMulDivInstructions[] = {
    223     {&RawMachineAssembler::Int32Mul, "Int32Mul", kArm64Mul32,
    224      MachineType::Int32()},
    225     {&RawMachineAssembler::Int64Mul, "Int64Mul", kArm64Mul,
    226      MachineType::Int64()},
    227     {&RawMachineAssembler::Int32Div, "Int32Div", kArm64Idiv32,
    228      MachineType::Int32()},
    229     {&RawMachineAssembler::Int64Div, "Int64Div", kArm64Idiv,
    230      MachineType::Int64()},
    231     {&RawMachineAssembler::Uint32Div, "Uint32Div", kArm64Udiv32,
    232      MachineType::Int32()},
    233     {&RawMachineAssembler::Uint64Div, "Uint64Div", kArm64Udiv,
    234      MachineType::Int64()}};
    235 
    236 
    237 // ARM64 FP arithmetic instructions.
    238 const MachInst2 kFPArithInstructions[] = {
    239     {&RawMachineAssembler::Float64Add, "Float64Add", kArm64Float64Add,
    240      MachineType::Float64()},
    241     {&RawMachineAssembler::Float64Sub, "Float64Sub", kArm64Float64Sub,
    242      MachineType::Float64()},
    243     {&RawMachineAssembler::Float64Mul, "Float64Mul", kArm64Float64Mul,
    244      MachineType::Float64()},
    245     {&RawMachineAssembler::Float64Div, "Float64Div", kArm64Float64Div,
    246      MachineType::Float64()}};
    247 
    248 
    249 struct FPCmp {
    250   MachInst2 mi;
    251   FlagsCondition cond;
    252   FlagsCondition commuted_cond;
    253 };
    254 
    255 
    256 std::ostream& operator<<(std::ostream& os, const FPCmp& cmp) {
    257   return os << cmp.mi;
    258 }
    259 
    260 
    261 // ARM64 FP comparison instructions.
    262 const FPCmp kFPCmpInstructions[] = {
    263     {{&RawMachineAssembler::Float64Equal, "Float64Equal", kArm64Float64Cmp,
    264       MachineType::Float64()},
    265      kEqual,
    266      kEqual},
    267     {{&RawMachineAssembler::Float64LessThan, "Float64LessThan",
    268       kArm64Float64Cmp, MachineType::Float64()},
    269      kFloatLessThan,
    270      kFloatGreaterThan},
    271     {{&RawMachineAssembler::Float64LessThanOrEqual, "Float64LessThanOrEqual",
    272       kArm64Float64Cmp, MachineType::Float64()},
    273      kFloatLessThanOrEqual,
    274      kFloatGreaterThanOrEqual},
    275     {{&RawMachineAssembler::Float32Equal, "Float32Equal", kArm64Float32Cmp,
    276       MachineType::Float32()},
    277      kEqual,
    278      kEqual},
    279     {{&RawMachineAssembler::Float32LessThan, "Float32LessThan",
    280       kArm64Float32Cmp, MachineType::Float32()},
    281      kFloatLessThan,
    282      kFloatGreaterThan},
    283     {{&RawMachineAssembler::Float32LessThanOrEqual, "Float32LessThanOrEqual",
    284       kArm64Float32Cmp, MachineType::Float32()},
    285      kFloatLessThanOrEqual,
    286      kFloatGreaterThanOrEqual}};
    287 
    288 
    289 struct Conversion {
    290   // The machine_type field in MachInst1 represents the destination type.
    291   MachInst1 mi;
    292   MachineType src_machine_type;
    293 };
    294 
    295 
    296 std::ostream& operator<<(std::ostream& os, const Conversion& conv) {
    297   return os << conv.mi;
    298 }
    299 
    300 
    301 // ARM64 type conversion instructions.
    302 const Conversion kConversionInstructions[] = {
    303     {{&RawMachineAssembler::ChangeFloat32ToFloat64, "ChangeFloat32ToFloat64",
    304       kArm64Float32ToFloat64, MachineType::Float64()},
    305      MachineType::Float32()},
    306     {{&RawMachineAssembler::TruncateFloat64ToFloat32,
    307       "TruncateFloat64ToFloat32", kArm64Float64ToFloat32,
    308       MachineType::Float32()},
    309      MachineType::Float64()},
    310     {{&RawMachineAssembler::ChangeInt32ToInt64, "ChangeInt32ToInt64",
    311       kArm64Sxtw, MachineType::Int64()},
    312      MachineType::Int32()},
    313     {{&RawMachineAssembler::ChangeUint32ToUint64, "ChangeUint32ToUint64",
    314       kArm64Mov32, MachineType::Uint64()},
    315      MachineType::Uint32()},
    316     {{&RawMachineAssembler::TruncateInt64ToInt32, "TruncateInt64ToInt32",
    317       kArm64Mov32, MachineType::Int32()},
    318      MachineType::Int64()},
    319     {{&RawMachineAssembler::ChangeInt32ToFloat64, "ChangeInt32ToFloat64",
    320       kArm64Int32ToFloat64, MachineType::Float64()},
    321      MachineType::Int32()},
    322     {{&RawMachineAssembler::ChangeUint32ToFloat64, "ChangeUint32ToFloat64",
    323       kArm64Uint32ToFloat64, MachineType::Float64()},
    324      MachineType::Uint32()},
    325     {{&RawMachineAssembler::ChangeFloat64ToInt32, "ChangeFloat64ToInt32",
    326       kArm64Float64ToInt32, MachineType::Int32()},
    327      MachineType::Float64()},
    328     {{&RawMachineAssembler::ChangeFloat64ToUint32, "ChangeFloat64ToUint32",
    329       kArm64Float64ToUint32, MachineType::Uint32()},
    330      MachineType::Float64()}};
    331 
    332 // ARM64 instructions that clear the top 32 bits of the destination.
    333 const MachInst2 kCanElideChangeUint32ToUint64[] = {
    334     {&RawMachineAssembler::Word32And, "Word32And", kArm64And32,
    335      MachineType::Uint32()},
    336     {&RawMachineAssembler::Word32Or, "Word32Or", kArm64Or32,
    337      MachineType::Uint32()},
    338     {&RawMachineAssembler::Word32Xor, "Word32Xor", kArm64Eor32,
    339      MachineType::Uint32()},
    340     {&RawMachineAssembler::Word32Shl, "Word32Shl", kArm64Lsl32,
    341      MachineType::Uint32()},
    342     {&RawMachineAssembler::Word32Shr, "Word32Shr", kArm64Lsr32,
    343      MachineType::Uint32()},
    344     {&RawMachineAssembler::Word32Sar, "Word32Sar", kArm64Asr32,
    345      MachineType::Uint32()},
    346     {&RawMachineAssembler::Word32Ror, "Word32Ror", kArm64Ror32,
    347      MachineType::Uint32()},
    348     {&RawMachineAssembler::Word32Equal, "Word32Equal", kArm64Cmp32,
    349      MachineType::Uint32()},
    350     {&RawMachineAssembler::Int32Add, "Int32Add", kArm64Add32,
    351      MachineType::Int32()},
    352     {&RawMachineAssembler::Int32AddWithOverflow, "Int32AddWithOverflow",
    353      kArm64Add32, MachineType::Int32()},
    354     {&RawMachineAssembler::Int32Sub, "Int32Sub", kArm64Sub32,
    355      MachineType::Int32()},
    356     {&RawMachineAssembler::Int32SubWithOverflow, "Int32SubWithOverflow",
    357      kArm64Sub32, MachineType::Int32()},
    358     {&RawMachineAssembler::Int32Mul, "Int32Mul", kArm64Mul32,
    359      MachineType::Int32()},
    360     {&RawMachineAssembler::Int32Div, "Int32Div", kArm64Idiv32,
    361      MachineType::Int32()},
    362     {&RawMachineAssembler::Int32Mod, "Int32Mod", kArm64Imod32,
    363      MachineType::Int32()},
    364     {&RawMachineAssembler::Int32LessThan, "Int32LessThan", kArm64Cmp32,
    365      MachineType::Int32()},
    366     {&RawMachineAssembler::Int32LessThanOrEqual, "Int32LessThanOrEqual",
    367      kArm64Cmp32, MachineType::Int32()},
    368     {&RawMachineAssembler::Uint32Div, "Uint32Div", kArm64Udiv32,
    369      MachineType::Uint32()},
    370     {&RawMachineAssembler::Uint32LessThan, "Uint32LessThan", kArm64Cmp32,
    371      MachineType::Uint32()},
    372     {&RawMachineAssembler::Uint32LessThanOrEqual, "Uint32LessThanOrEqual",
    373      kArm64Cmp32, MachineType::Uint32()},
    374     {&RawMachineAssembler::Uint32Mod, "Uint32Mod", kArm64Umod32,
    375      MachineType::Uint32()},
    376 };
    377 
    378 }  // namespace
    379 
    380 
    381 // -----------------------------------------------------------------------------
    382 // Logical instructions.
    383 
    384 
    385 typedef InstructionSelectorTestWithParam<MachInst2>
    386     InstructionSelectorLogicalTest;
    387 
    388 
    389 TEST_P(InstructionSelectorLogicalTest, Parameter) {
    390   const MachInst2 dpi = GetParam();
    391   const MachineType type = dpi.machine_type;
    392   StreamBuilder m(this, type, type, type);
    393   m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)));
    394   Stream s = m.Build();
    395   ASSERT_EQ(1U, s.size());
    396   EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
    397   EXPECT_EQ(2U, s[0]->InputCount());
    398   EXPECT_EQ(1U, s[0]->OutputCount());
    399 }
    400 
    401 
    402 TEST_P(InstructionSelectorLogicalTest, Immediate) {
    403   const MachInst2 dpi = GetParam();
    404   const MachineType type = dpi.machine_type;
    405   // TODO(all): Add support for testing 64-bit immediates.
    406   if (type == MachineType::Int32()) {
    407     // Immediate on the right.
    408     TRACED_FOREACH(int32_t, imm, kLogical32Immediates) {
    409       StreamBuilder m(this, type, type);
    410       m.Return((m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm)));
    411       Stream s = m.Build();
    412       ASSERT_EQ(1U, s.size());
    413       EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
    414       ASSERT_EQ(2U, s[0]->InputCount());
    415       EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
    416       EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
    417       EXPECT_EQ(1U, s[0]->OutputCount());
    418     }
    419 
    420     // Immediate on the left; all logical ops should commute.
    421     TRACED_FOREACH(int32_t, imm, kLogical32Immediates) {
    422       StreamBuilder m(this, type, type);
    423       m.Return((m.*dpi.constructor)(m.Int32Constant(imm), m.Parameter(0)));
    424       Stream s = m.Build();
    425       ASSERT_EQ(1U, s.size());
    426       EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
    427       ASSERT_EQ(2U, s[0]->InputCount());
    428       EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
    429       EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
    430       EXPECT_EQ(1U, s[0]->OutputCount());
    431     }
    432   }
    433 }
    434 
    435 
    436 TEST_P(InstructionSelectorLogicalTest, ShiftByImmediate) {
    437   const MachInst2 dpi = GetParam();
    438   const MachineType type = dpi.machine_type;
    439   TRACED_FOREACH(Shift, shift, kShiftInstructions) {
    440     // Only test 64-bit shifted operands with 64-bit instructions.
    441     if (shift.mi.machine_type != type) continue;
    442 
    443     TRACED_FORRANGE(int, imm, 0, ((type == MachineType::Int32()) ? 31 : 63)) {
    444       StreamBuilder m(this, type, type, type);
    445       m.Return((m.*dpi.constructor)(
    446           m.Parameter(0),
    447           (m.*shift.mi.constructor)(m.Parameter(1),
    448                                     BuildConstant(m, type, imm))));
    449       Stream s = m.Build();
    450       ASSERT_EQ(1U, s.size());
    451       EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
    452       EXPECT_EQ(shift.mode, s[0]->addressing_mode());
    453       EXPECT_EQ(3U, s[0]->InputCount());
    454       EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(2)));
    455       EXPECT_EQ(1U, s[0]->OutputCount());
    456     }
    457 
    458     TRACED_FORRANGE(int, imm, 0, ((type == MachineType::Int32()) ? 31 : 63)) {
    459       StreamBuilder m(this, type, type, type);
    460       m.Return((m.*dpi.constructor)(
    461           (m.*shift.mi.constructor)(m.Parameter(1),
    462                                     BuildConstant(m, type, imm)),
    463           m.Parameter(0)));
    464       Stream s = m.Build();
    465       ASSERT_EQ(1U, s.size());
    466       EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
    467       EXPECT_EQ(shift.mode, s[0]->addressing_mode());
    468       EXPECT_EQ(3U, s[0]->InputCount());
    469       EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(2)));
    470       EXPECT_EQ(1U, s[0]->OutputCount());
    471     }
    472   }
    473 }
    474 
    475 
    476 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorLogicalTest,
    477                         ::testing::ValuesIn(kLogicalInstructions));
    478 
    479 
    480 // -----------------------------------------------------------------------------
    481 // Add and Sub instructions.
    482 
    483 typedef InstructionSelectorTestWithParam<AddSub> InstructionSelectorAddSubTest;
    484 
    485 
    486 TEST_P(InstructionSelectorAddSubTest, Parameter) {
    487   const AddSub dpi = GetParam();
    488   const MachineType type = dpi.mi.machine_type;
    489   StreamBuilder m(this, type, type, type);
    490   m.Return((m.*dpi.mi.constructor)(m.Parameter(0), m.Parameter(1)));
    491   Stream s = m.Build();
    492   ASSERT_EQ(1U, s.size());
    493   EXPECT_EQ(dpi.mi.arch_opcode, s[0]->arch_opcode());
    494   EXPECT_EQ(2U, s[0]->InputCount());
    495   EXPECT_EQ(1U, s[0]->OutputCount());
    496 }
    497 
    498 
    499 TEST_P(InstructionSelectorAddSubTest, ImmediateOnRight) {
    500   const AddSub dpi = GetParam();
    501   const MachineType type = dpi.mi.machine_type;
    502   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
    503     StreamBuilder m(this, type, type);
    504     m.Return(
    505         (m.*dpi.mi.constructor)(m.Parameter(0), BuildConstant(m, type, imm)));
    506     Stream s = m.Build();
    507     ASSERT_EQ(1U, s.size());
    508     EXPECT_EQ(dpi.mi.arch_opcode, s[0]->arch_opcode());
    509     ASSERT_EQ(2U, s[0]->InputCount());
    510     EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
    511     EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(1)));
    512     EXPECT_EQ(1U, s[0]->OutputCount());
    513   }
    514 }
    515 
    516 
    517 TEST_P(InstructionSelectorAddSubTest, NegImmediateOnRight) {
    518   const AddSub dpi = GetParam();
    519   const MachineType type = dpi.mi.machine_type;
    520   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
    521     if (imm == 0) continue;
    522     StreamBuilder m(this, type, type);
    523     m.Return(
    524         (m.*dpi.mi.constructor)(m.Parameter(0), BuildConstant(m, type, -imm)));
    525     Stream s = m.Build();
    526     ASSERT_EQ(1U, s.size());
    527     EXPECT_EQ(dpi.negate_arch_opcode, s[0]->arch_opcode());
    528     ASSERT_EQ(2U, s[0]->InputCount());
    529     ASSERT_TRUE(s[0]->InputAt(1)->IsImmediate());
    530     EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
    531     EXPECT_EQ(1U, s[0]->OutputCount());
    532   }
    533 }
    534 
    535 
    536 TEST_P(InstructionSelectorAddSubTest, ShiftByImmediateOnRight) {
    537   const AddSub dpi = GetParam();
    538   const MachineType type = dpi.mi.machine_type;
    539   TRACED_FOREACH(Shift, shift, kShiftInstructions) {
    540     // Only test 64-bit shifted operands with 64-bit instructions.
    541     if (shift.mi.machine_type != type) continue;
    542 
    543     if ((shift.mi.arch_opcode == kArm64Ror32) ||
    544         (shift.mi.arch_opcode == kArm64Ror)) {
    545       // Not supported by add/sub instructions.
    546       continue;
    547     }
    548 
    549     TRACED_FORRANGE(int, imm, 0, ((type == MachineType::Int32()) ? 31 : 63)) {
    550       StreamBuilder m(this, type, type, type);
    551       m.Return((m.*dpi.mi.constructor)(
    552           m.Parameter(0),
    553           (m.*shift.mi.constructor)(m.Parameter(1),
    554                                     BuildConstant(m, type, imm))));
    555       Stream s = m.Build();
    556       ASSERT_EQ(1U, s.size());
    557       EXPECT_EQ(dpi.mi.arch_opcode, s[0]->arch_opcode());
    558       EXPECT_EQ(shift.mode, s[0]->addressing_mode());
    559       EXPECT_EQ(3U, s[0]->InputCount());
    560       EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(2)));
    561       EXPECT_EQ(1U, s[0]->OutputCount());
    562     }
    563   }
    564 }
    565 
    566 
    567 TEST_P(InstructionSelectorAddSubTest, UnsignedExtendByte) {
    568   const AddSub dpi = GetParam();
    569   const MachineType type = dpi.mi.machine_type;
    570   StreamBuilder m(this, type, type, type);
    571   m.Return((m.*dpi.mi.constructor)(
    572       m.Parameter(0), m.Word32And(m.Parameter(1), m.Int32Constant(0xff))));
    573   Stream s = m.Build();
    574   ASSERT_EQ(1U, s.size());
    575   EXPECT_EQ(dpi.mi.arch_opcode, s[0]->arch_opcode());
    576   EXPECT_EQ(kMode_Operand2_R_UXTB, s[0]->addressing_mode());
    577   ASSERT_EQ(2U, s[0]->InputCount());
    578   ASSERT_EQ(1U, s[0]->OutputCount());
    579 }
    580 
    581 
    582 TEST_P(InstructionSelectorAddSubTest, UnsignedExtendHalfword) {
    583   const AddSub dpi = GetParam();
    584   const MachineType type = dpi.mi.machine_type;
    585   StreamBuilder m(this, type, type, type);
    586   m.Return((m.*dpi.mi.constructor)(
    587       m.Parameter(0), m.Word32And(m.Parameter(1), m.Int32Constant(0xffff))));
    588   Stream s = m.Build();
    589   ASSERT_EQ(1U, s.size());
    590   EXPECT_EQ(dpi.mi.arch_opcode, s[0]->arch_opcode());
    591   EXPECT_EQ(kMode_Operand2_R_UXTH, s[0]->addressing_mode());
    592   ASSERT_EQ(2U, s[0]->InputCount());
    593   ASSERT_EQ(1U, s[0]->OutputCount());
    594 }
    595 
    596 
    597 TEST_P(InstructionSelectorAddSubTest, SignedExtendByte) {
    598   const AddSub dpi = GetParam();
    599   const MachineType type = dpi.mi.machine_type;
    600   StreamBuilder m(this, type, type, type);
    601   m.Return((m.*dpi.mi.constructor)(
    602       m.Parameter(0),
    603       m.Word32Sar(m.Word32Shl(m.Parameter(1), m.Int32Constant(24)),
    604                   m.Int32Constant(24))));
    605   Stream s = m.Build();
    606   ASSERT_EQ(1U, s.size());
    607   EXPECT_EQ(dpi.mi.arch_opcode, s[0]->arch_opcode());
    608   EXPECT_EQ(kMode_Operand2_R_SXTB, s[0]->addressing_mode());
    609   ASSERT_EQ(2U, s[0]->InputCount());
    610   ASSERT_EQ(1U, s[0]->OutputCount());
    611 }
    612 
    613 
    614 TEST_P(InstructionSelectorAddSubTest, SignedExtendHalfword) {
    615   const AddSub dpi = GetParam();
    616   const MachineType type = dpi.mi.machine_type;
    617   StreamBuilder m(this, type, type, type);
    618   m.Return((m.*dpi.mi.constructor)(
    619       m.Parameter(0),
    620       m.Word32Sar(m.Word32Shl(m.Parameter(1), m.Int32Constant(16)),
    621                   m.Int32Constant(16))));
    622   Stream s = m.Build();
    623   ASSERT_EQ(1U, s.size());
    624   EXPECT_EQ(dpi.mi.arch_opcode, s[0]->arch_opcode());
    625   EXPECT_EQ(kMode_Operand2_R_SXTH, s[0]->addressing_mode());
    626   ASSERT_EQ(2U, s[0]->InputCount());
    627   ASSERT_EQ(1U, s[0]->OutputCount());
    628 }
    629 
    630 
    631 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorAddSubTest,
    632                         ::testing::ValuesIn(kAddSubInstructions));
    633 
    634 
    635 TEST_F(InstructionSelectorTest, AddImmediateOnLeft) {
    636   {
    637     // 32-bit add.
    638     TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
    639       StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
    640       m.Return(m.Int32Add(m.Int32Constant(imm), m.Parameter(0)));
    641       Stream s = m.Build();
    642       ASSERT_EQ(1U, s.size());
    643       EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
    644       ASSERT_EQ(2U, s[0]->InputCount());
    645       EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
    646       EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
    647       EXPECT_EQ(1U, s[0]->OutputCount());
    648     }
    649   }
    650   {
    651     // 64-bit add.
    652     TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
    653       StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
    654       m.Return(m.Int64Add(m.Int64Constant(imm), m.Parameter(0)));
    655       Stream s = m.Build();
    656       ASSERT_EQ(1U, s.size());
    657       EXPECT_EQ(kArm64Add, s[0]->arch_opcode());
    658       ASSERT_EQ(2U, s[0]->InputCount());
    659       EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
    660       EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(1)));
    661       EXPECT_EQ(1U, s[0]->OutputCount());
    662     }
    663   }
    664 }
    665 
    666 
    667 TEST_F(InstructionSelectorTest, SubZeroOnLeft) {
    668   {
    669     // 32-bit subtract.
    670     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
    671                     MachineType::Int32());
    672     m.Return(m.Int32Sub(m.Int32Constant(0), m.Parameter(0)));
    673     Stream s = m.Build();
    674 
    675     ASSERT_EQ(1U, s.size());
    676     EXPECT_EQ(kArm64Sub32, s[0]->arch_opcode());
    677     ASSERT_EQ(2U, s[0]->InputCount());
    678     EXPECT_TRUE(s[0]->InputAt(0)->IsImmediate());
    679     EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(0)));
    680     EXPECT_EQ(1U, s[0]->OutputCount());
    681   }
    682   {
    683     // 64-bit subtract.
    684     StreamBuilder m(this, MachineType::Int64(), MachineType::Int64(),
    685                     MachineType::Int64());
    686     m.Return(m.Int64Sub(m.Int64Constant(0), m.Parameter(0)));
    687     Stream s = m.Build();
    688 
    689     ASSERT_EQ(1U, s.size());
    690     EXPECT_EQ(kArm64Sub, s[0]->arch_opcode());
    691     ASSERT_EQ(2U, s[0]->InputCount());
    692     EXPECT_TRUE(s[0]->InputAt(0)->IsImmediate());
    693     EXPECT_EQ(0, s.ToInt64(s[0]->InputAt(0)));
    694     EXPECT_EQ(1U, s[0]->OutputCount());
    695   }
    696 }
    697 
    698 
    699 TEST_F(InstructionSelectorTest, SubZeroOnLeftWithShift) {
    700   TRACED_FOREACH(Shift, shift, kShiftInstructions) {
    701     {
    702       // Test 32-bit operations. Ignore ROR shifts, as subtract does not
    703       // support them.
    704       if ((shift.mi.machine_type != MachineType::Int32()) ||
    705           (shift.mi.arch_opcode == kArm64Ror32) ||
    706           (shift.mi.arch_opcode == kArm64Ror))
    707         continue;
    708 
    709       TRACED_FORRANGE(int, imm, -32, 63) {
    710         StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
    711                         MachineType::Int32());
    712         m.Return(m.Int32Sub(
    713             m.Int32Constant(0),
    714             (m.*shift.mi.constructor)(m.Parameter(1), m.Int32Constant(imm))));
    715         Stream s = m.Build();
    716 
    717         ASSERT_EQ(1U, s.size());
    718         EXPECT_EQ(kArm64Sub32, s[0]->arch_opcode());
    719         ASSERT_EQ(3U, s[0]->InputCount());
    720         EXPECT_TRUE(s[0]->InputAt(0)->IsImmediate());
    721         EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(0)));
    722         EXPECT_EQ(shift.mode, s[0]->addressing_mode());
    723         EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2)));
    724         EXPECT_EQ(1U, s[0]->OutputCount());
    725       }
    726     }
    727     {
    728       // Test 64-bit operations. Ignore ROR shifts, as subtract does not
    729       // support them.
    730       if ((shift.mi.machine_type != MachineType::Int64()) ||
    731           (shift.mi.arch_opcode == kArm64Ror32) ||
    732           (shift.mi.arch_opcode == kArm64Ror))
    733         continue;
    734 
    735       TRACED_FORRANGE(int, imm, -32, 127) {
    736         StreamBuilder m(this, MachineType::Int64(), MachineType::Int64(),
    737                         MachineType::Int64());
    738         m.Return(m.Int64Sub(
    739             m.Int64Constant(0),
    740             (m.*shift.mi.constructor)(m.Parameter(1), m.Int64Constant(imm))));
    741         Stream s = m.Build();
    742 
    743         ASSERT_EQ(1U, s.size());
    744         EXPECT_EQ(kArm64Sub, s[0]->arch_opcode());
    745         ASSERT_EQ(3U, s[0]->InputCount());
    746         EXPECT_TRUE(s[0]->InputAt(0)->IsImmediate());
    747         EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(0)));
    748         EXPECT_EQ(shift.mode, s[0]->addressing_mode());
    749         EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2)));
    750         EXPECT_EQ(1U, s[0]->OutputCount());
    751       }
    752     }
    753   }
    754 }
    755 
    756 
    757 TEST_F(InstructionSelectorTest, AddNegImmediateOnLeft) {
    758   {
    759     // 32-bit add.
    760     TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
    761       if (imm == 0) continue;
    762       StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
    763       m.Return(m.Int32Add(m.Int32Constant(-imm), m.Parameter(0)));
    764       Stream s = m.Build();
    765 
    766       ASSERT_EQ(1U, s.size());
    767       EXPECT_EQ(kArm64Sub32, s[0]->arch_opcode());
    768       ASSERT_EQ(2U, s[0]->InputCount());
    769       ASSERT_TRUE(s[0]->InputAt(1)->IsImmediate());
    770       EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
    771       EXPECT_EQ(1U, s[0]->OutputCount());
    772     }
    773   }
    774   {
    775     // 64-bit add.
    776     TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
    777       if (imm == 0) continue;
    778       StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
    779       m.Return(m.Int64Add(m.Int64Constant(-imm), m.Parameter(0)));
    780       Stream s = m.Build();
    781 
    782       ASSERT_EQ(1U, s.size());
    783       EXPECT_EQ(kArm64Sub, s[0]->arch_opcode());
    784       ASSERT_EQ(2U, s[0]->InputCount());
    785       ASSERT_TRUE(s[0]->InputAt(1)->IsImmediate());
    786       EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(1)));
    787       EXPECT_EQ(1U, s[0]->OutputCount());
    788     }
    789   }
    790 }
    791 
    792 
    793 TEST_F(InstructionSelectorTest, AddShiftByImmediateOnLeft) {
    794   // 32-bit add.
    795   TRACED_FOREACH(Shift, shift, kShiftInstructions) {
    796     // Only test relevant shifted operands.
    797     if (shift.mi.machine_type != MachineType::Int32()) continue;
    798     if (shift.mi.arch_opcode == kArm64Ror32) continue;
    799 
    800     // The available shift operand range is `0 <= imm < 32`, but we also test
    801     // that immediates outside this range are handled properly (modulo-32).
    802     TRACED_FORRANGE(int, imm, -32, 63) {
    803       StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
    804                       MachineType::Int32());
    805       m.Return((m.Int32Add)(
    806           (m.*shift.mi.constructor)(m.Parameter(1), m.Int32Constant(imm)),
    807           m.Parameter(0)));
    808       Stream s = m.Build();
    809       ASSERT_EQ(1U, s.size());
    810       EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
    811       EXPECT_EQ(shift.mode, s[0]->addressing_mode());
    812       EXPECT_EQ(3U, s[0]->InputCount());
    813       EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(2)));
    814       EXPECT_EQ(1U, s[0]->OutputCount());
    815     }
    816   }
    817 
    818   // 64-bit add.
    819   TRACED_FOREACH(Shift, shift, kShiftInstructions) {
    820     // Only test relevant shifted operands.
    821     if (shift.mi.machine_type != MachineType::Int64()) continue;
    822     if (shift.mi.arch_opcode == kArm64Ror) continue;
    823 
    824     // The available shift operand range is `0 <= imm < 64`, but we also test
    825     // that immediates outside this range are handled properly (modulo-64).
    826     TRACED_FORRANGE(int, imm, -64, 127) {
    827       StreamBuilder m(this, MachineType::Int64(), MachineType::Int64(),
    828                       MachineType::Int64());
    829       m.Return((m.Int64Add)(
    830           (m.*shift.mi.constructor)(m.Parameter(1), m.Int64Constant(imm)),
    831           m.Parameter(0)));
    832       Stream s = m.Build();
    833       ASSERT_EQ(1U, s.size());
    834       EXPECT_EQ(kArm64Add, s[0]->arch_opcode());
    835       EXPECT_EQ(shift.mode, s[0]->addressing_mode());
    836       EXPECT_EQ(3U, s[0]->InputCount());
    837       EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(2)));
    838       EXPECT_EQ(1U, s[0]->OutputCount());
    839     }
    840   }
    841 }
    842 
    843 
    844 TEST_F(InstructionSelectorTest, AddUnsignedExtendByteOnLeft) {
    845   {
    846     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
    847                     MachineType::Int32());
    848     m.Return(m.Int32Add(m.Word32And(m.Parameter(0), m.Int32Constant(0xff)),
    849                         m.Parameter(1)));
    850     Stream s = m.Build();
    851     ASSERT_EQ(1U, s.size());
    852     EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
    853     EXPECT_EQ(kMode_Operand2_R_UXTB, s[0]->addressing_mode());
    854     ASSERT_EQ(2U, s[0]->InputCount());
    855     ASSERT_EQ(1U, s[0]->OutputCount());
    856   }
    857   {
    858     StreamBuilder m(this, MachineType::Int64(), MachineType::Int32(),
    859                     MachineType::Int64());
    860     m.Return(m.Int64Add(m.Word32And(m.Parameter(0), m.Int32Constant(0xff)),
    861                         m.Parameter(1)));
    862     Stream s = m.Build();
    863     ASSERT_EQ(1U, s.size());
    864     EXPECT_EQ(kArm64Add, s[0]->arch_opcode());
    865     EXPECT_EQ(kMode_Operand2_R_UXTB, s[0]->addressing_mode());
    866     ASSERT_EQ(2U, s[0]->InputCount());
    867     ASSERT_EQ(1U, s[0]->OutputCount());
    868   }
    869 }
    870 
    871 
    872 TEST_F(InstructionSelectorTest, AddUnsignedExtendHalfwordOnLeft) {
    873   {
    874     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
    875                     MachineType::Int32());
    876     m.Return(m.Int32Add(m.Word32And(m.Parameter(0), m.Int32Constant(0xffff)),
    877                         m.Parameter(1)));
    878     Stream s = m.Build();
    879     ASSERT_EQ(1U, s.size());
    880     EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
    881     EXPECT_EQ(kMode_Operand2_R_UXTH, s[0]->addressing_mode());
    882     ASSERT_EQ(2U, s[0]->InputCount());
    883     ASSERT_EQ(1U, s[0]->OutputCount());
    884   }
    885   {
    886     StreamBuilder m(this, MachineType::Int64(), MachineType::Int32(),
    887                     MachineType::Int64());
    888     m.Return(m.Int64Add(m.Word32And(m.Parameter(0), m.Int32Constant(0xffff)),
    889                         m.Parameter(1)));
    890     Stream s = m.Build();
    891     ASSERT_EQ(1U, s.size());
    892     EXPECT_EQ(kArm64Add, s[0]->arch_opcode());
    893     EXPECT_EQ(kMode_Operand2_R_UXTH, s[0]->addressing_mode());
    894     ASSERT_EQ(2U, s[0]->InputCount());
    895     ASSERT_EQ(1U, s[0]->OutputCount());
    896   }
    897 }
    898 
    899 
    900 TEST_F(InstructionSelectorTest, AddSignedExtendByteOnLeft) {
    901   {
    902     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
    903                     MachineType::Int32());
    904     m.Return(
    905         m.Int32Add(m.Word32Sar(m.Word32Shl(m.Parameter(0), m.Int32Constant(24)),
    906                                m.Int32Constant(24)),
    907                    m.Parameter(1)));
    908     Stream s = m.Build();
    909     ASSERT_EQ(1U, s.size());
    910     EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
    911     EXPECT_EQ(kMode_Operand2_R_SXTB, s[0]->addressing_mode());
    912     ASSERT_EQ(2U, s[0]->InputCount());
    913     ASSERT_EQ(1U, s[0]->OutputCount());
    914   }
    915   {
    916     StreamBuilder m(this, MachineType::Int64(), MachineType::Int32(),
    917                     MachineType::Int64());
    918     m.Return(
    919         m.Int64Add(m.Word32Sar(m.Word32Shl(m.Parameter(0), m.Int32Constant(24)),
    920                                m.Int32Constant(24)),
    921                    m.Parameter(1)));
    922     Stream s = m.Build();
    923     ASSERT_EQ(1U, s.size());
    924     EXPECT_EQ(kArm64Add, s[0]->arch_opcode());
    925     EXPECT_EQ(kMode_Operand2_R_SXTB, s[0]->addressing_mode());
    926     ASSERT_EQ(2U, s[0]->InputCount());
    927     ASSERT_EQ(1U, s[0]->OutputCount());
    928   }
    929 }
    930 
    931 
    932 TEST_F(InstructionSelectorTest, AddSignedExtendHalfwordOnLeft) {
    933   {
    934     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
    935                     MachineType::Int32());
    936     m.Return(
    937         m.Int32Add(m.Word32Sar(m.Word32Shl(m.Parameter(0), m.Int32Constant(16)),
    938                                m.Int32Constant(16)),
    939                    m.Parameter(1)));
    940     Stream s = m.Build();
    941     ASSERT_EQ(1U, s.size());
    942     EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
    943     EXPECT_EQ(kMode_Operand2_R_SXTH, s[0]->addressing_mode());
    944     ASSERT_EQ(2U, s[0]->InputCount());
    945     ASSERT_EQ(1U, s[0]->OutputCount());
    946   }
    947   {
    948     StreamBuilder m(this, MachineType::Int64(), MachineType::Int32(),
    949                     MachineType::Int64());
    950     m.Return(
    951         m.Int64Add(m.Word32Sar(m.Word32Shl(m.Parameter(0), m.Int32Constant(16)),
    952                                m.Int32Constant(16)),
    953                    m.Parameter(1)));
    954     Stream s = m.Build();
    955     ASSERT_EQ(1U, s.size());
    956     EXPECT_EQ(kArm64Add, s[0]->arch_opcode());
    957     EXPECT_EQ(kMode_Operand2_R_SXTH, s[0]->addressing_mode());
    958     ASSERT_EQ(2U, s[0]->InputCount());
    959     ASSERT_EQ(1U, s[0]->OutputCount());
    960   }
    961 }
    962 
    963 
    964 // -----------------------------------------------------------------------------
    965 // Data processing controlled branches.
    966 
    967 
    968 typedef InstructionSelectorTestWithParam<MachInst2>
    969     InstructionSelectorDPFlagSetTest;
    970 
    971 
    972 TEST_P(InstructionSelectorDPFlagSetTest, BranchWithParameters) {
    973   const MachInst2 dpi = GetParam();
    974   const MachineType type = dpi.machine_type;
    975   StreamBuilder m(this, type, type, type);
    976   RawMachineLabel a, b;
    977   m.Branch((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)), &a, &b);
    978   m.Bind(&a);
    979   m.Return(m.Int32Constant(1));
    980   m.Bind(&b);
    981   m.Return(m.Int32Constant(0));
    982   Stream s = m.Build();
    983   ASSERT_EQ(1U, s.size());
    984   EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
    985   EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
    986   EXPECT_EQ(kNotEqual, s[0]->flags_condition());
    987 }
    988 
    989 
    990 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
    991                         InstructionSelectorDPFlagSetTest,
    992                         ::testing::ValuesIn(kDPFlagSetInstructions));
    993 
    994 
    995 TEST_F(InstructionSelectorTest, Word32AndBranchWithImmediateOnRight) {
    996   TRACED_FOREACH(int32_t, imm, kLogical32Immediates) {
    997     // Skip the cases where the instruction selector would use tbz/tbnz.
    998     if (base::bits::CountPopulation32(imm) == 1) continue;
    999 
   1000     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
   1001     RawMachineLabel a, b;
   1002     m.Branch(m.Word32And(m.Parameter(0), m.Int32Constant(imm)), &a, &b);
   1003     m.Bind(&a);
   1004     m.Return(m.Int32Constant(1));
   1005     m.Bind(&b);
   1006     m.Return(m.Int32Constant(0));
   1007     Stream s = m.Build();
   1008     ASSERT_EQ(1U, s.size());
   1009     EXPECT_EQ(kArm64Tst32, s[0]->arch_opcode());
   1010     EXPECT_EQ(4U, s[0]->InputCount());
   1011     EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
   1012     EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
   1013     EXPECT_EQ(kNotEqual, s[0]->flags_condition());
   1014   }
   1015 }
   1016 
   1017 
   1018 TEST_F(InstructionSelectorTest, Word64AndBranchWithImmediateOnRight) {
   1019   TRACED_FOREACH(int64_t, imm, kLogical64Immediates) {
   1020     // Skip the cases where the instruction selector would use tbz/tbnz.
   1021     if (base::bits::CountPopulation64(imm) == 1) continue;
   1022 
   1023     StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
   1024     RawMachineLabel a, b;
   1025     m.Branch(m.Word64And(m.Parameter(0), m.Int64Constant(imm)), &a, &b);
   1026     m.Bind(&a);
   1027     m.Return(m.Int32Constant(1));
   1028     m.Bind(&b);
   1029     m.Return(m.Int32Constant(0));
   1030     Stream s = m.Build();
   1031     ASSERT_EQ(1U, s.size());
   1032     EXPECT_EQ(kArm64Tst, s[0]->arch_opcode());
   1033     EXPECT_EQ(4U, s[0]->InputCount());
   1034     EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
   1035     EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
   1036     EXPECT_EQ(kNotEqual, s[0]->flags_condition());
   1037   }
   1038 }
   1039 
   1040 
   1041 TEST_F(InstructionSelectorTest, AddBranchWithImmediateOnRight) {
   1042   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
   1043     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
   1044     RawMachineLabel a, b;
   1045     m.Branch(m.Int32Add(m.Parameter(0), m.Int32Constant(imm)), &a, &b);
   1046     m.Bind(&a);
   1047     m.Return(m.Int32Constant(1));
   1048     m.Bind(&b);
   1049     m.Return(m.Int32Constant(0));
   1050     Stream s = m.Build();
   1051     ASSERT_EQ(1U, s.size());
   1052     EXPECT_EQ(kArm64Cmn32, s[0]->arch_opcode());
   1053     EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
   1054     EXPECT_EQ(kNotEqual, s[0]->flags_condition());
   1055   }
   1056 }
   1057 
   1058 
   1059 TEST_F(InstructionSelectorTest, SubBranchWithImmediateOnRight) {
   1060   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
   1061     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
   1062     RawMachineLabel a, b;
   1063     m.Branch(m.Int32Sub(m.Parameter(0), m.Int32Constant(imm)), &a, &b);
   1064     m.Bind(&a);
   1065     m.Return(m.Int32Constant(1));
   1066     m.Bind(&b);
   1067     m.Return(m.Int32Constant(0));
   1068     Stream s = m.Build();
   1069     ASSERT_EQ(1U, s.size());
   1070     EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode());
   1071     EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
   1072     EXPECT_EQ(kNotEqual, s[0]->flags_condition());
   1073   }
   1074 }
   1075 
   1076 
   1077 TEST_F(InstructionSelectorTest, Word32AndBranchWithImmediateOnLeft) {
   1078   TRACED_FOREACH(int32_t, imm, kLogical32Immediates) {
   1079     // Skip the cases where the instruction selector would use tbz/tbnz.
   1080     if (base::bits::CountPopulation32(imm) == 1) continue;
   1081 
   1082     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
   1083     RawMachineLabel a, b;
   1084     m.Branch(m.Word32And(m.Int32Constant(imm), m.Parameter(0)), &a, &b);
   1085     m.Bind(&a);
   1086     m.Return(m.Int32Constant(1));
   1087     m.Bind(&b);
   1088     m.Return(m.Int32Constant(0));
   1089     Stream s = m.Build();
   1090     ASSERT_EQ(1U, s.size());
   1091     EXPECT_EQ(kArm64Tst32, s[0]->arch_opcode());
   1092     EXPECT_EQ(4U, s[0]->InputCount());
   1093     EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
   1094     ASSERT_LE(1U, s[0]->InputCount());
   1095     EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
   1096     EXPECT_EQ(kNotEqual, s[0]->flags_condition());
   1097   }
   1098 }
   1099 
   1100 
   1101 TEST_F(InstructionSelectorTest, Word64AndBranchWithImmediateOnLeft) {
   1102   TRACED_FOREACH(int64_t, imm, kLogical64Immediates) {
   1103     // Skip the cases where the instruction selector would use tbz/tbnz.
   1104     if (base::bits::CountPopulation64(imm) == 1) continue;
   1105 
   1106     StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
   1107     RawMachineLabel a, b;
   1108     m.Branch(m.Word64And(m.Int64Constant(imm), m.Parameter(0)), &a, &b);
   1109     m.Bind(&a);
   1110     m.Return(m.Int32Constant(1));
   1111     m.Bind(&b);
   1112     m.Return(m.Int32Constant(0));
   1113     Stream s = m.Build();
   1114     ASSERT_EQ(1U, s.size());
   1115     EXPECT_EQ(kArm64Tst, s[0]->arch_opcode());
   1116     EXPECT_EQ(4U, s[0]->InputCount());
   1117     EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
   1118     ASSERT_LE(1U, s[0]->InputCount());
   1119     EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
   1120     EXPECT_EQ(kNotEqual, s[0]->flags_condition());
   1121   }
   1122 }
   1123 
   1124 
   1125 TEST_F(InstructionSelectorTest, AddBranchWithImmediateOnLeft) {
   1126   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
   1127     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
   1128     RawMachineLabel a, b;
   1129     m.Branch(m.Int32Add(m.Int32Constant(imm), m.Parameter(0)), &a, &b);
   1130     m.Bind(&a);
   1131     m.Return(m.Int32Constant(1));
   1132     m.Bind(&b);
   1133     m.Return(m.Int32Constant(0));
   1134     Stream s = m.Build();
   1135     ASSERT_EQ(1U, s.size());
   1136     EXPECT_EQ(kArm64Cmn32, s[0]->arch_opcode());
   1137     ASSERT_LE(1U, s[0]->InputCount());
   1138     EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
   1139     EXPECT_EQ(kNotEqual, s[0]->flags_condition());
   1140   }
   1141 }
   1142 
   1143 
   1144 TEST_F(InstructionSelectorTest, Word32AndBranchWithOneBitMaskOnRight) {
   1145   TRACED_FORRANGE(int, bit, 0, 31) {
   1146     uint32_t mask = 1 << bit;
   1147     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
   1148     RawMachineLabel a, b;
   1149     m.Branch(m.Word32And(m.Parameter(0), m.Int32Constant(mask)), &a, &b);
   1150     m.Bind(&a);
   1151     m.Return(m.Int32Constant(1));
   1152     m.Bind(&b);
   1153     m.Return(m.Int32Constant(0));
   1154     Stream s = m.Build();
   1155     ASSERT_EQ(1U, s.size());
   1156     EXPECT_EQ(kArm64TestAndBranch32, s[0]->arch_opcode());
   1157     EXPECT_EQ(kNotEqual, s[0]->flags_condition());
   1158     EXPECT_EQ(4U, s[0]->InputCount());
   1159     EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
   1160     EXPECT_EQ(bit, s.ToInt32(s[0]->InputAt(1)));
   1161   }
   1162 
   1163   TRACED_FORRANGE(int, bit, 0, 31) {
   1164     uint32_t mask = 1 << bit;
   1165     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
   1166     RawMachineLabel a, b;
   1167     m.Branch(
   1168         m.Word32BinaryNot(m.Word32And(m.Parameter(0), m.Int32Constant(mask))),
   1169         &a, &b);
   1170     m.Bind(&a);
   1171     m.Return(m.Int32Constant(1));
   1172     m.Bind(&b);
   1173     m.Return(m.Int32Constant(0));
   1174     Stream s = m.Build();
   1175     ASSERT_EQ(1U, s.size());
   1176     EXPECT_EQ(kArm64TestAndBranch32, s[0]->arch_opcode());
   1177     EXPECT_EQ(kEqual, s[0]->flags_condition());
   1178     EXPECT_EQ(4U, s[0]->InputCount());
   1179     EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
   1180     EXPECT_EQ(bit, s.ToInt32(s[0]->InputAt(1)));
   1181   }
   1182 }
   1183 
   1184 TEST_F(InstructionSelectorTest, Word32AndBranchWithOneBitMaskOnLeft) {
   1185   TRACED_FORRANGE(int, bit, 0, 31) {
   1186     uint32_t mask = 1 << bit;
   1187     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
   1188     RawMachineLabel a, b;
   1189     m.Branch(m.Word32And(m.Int32Constant(mask), m.Parameter(0)), &a, &b);
   1190     m.Bind(&a);
   1191     m.Return(m.Int32Constant(1));
   1192     m.Bind(&b);
   1193     m.Return(m.Int32Constant(0));
   1194     Stream s = m.Build();
   1195     ASSERT_EQ(1U, s.size());
   1196     EXPECT_EQ(kArm64TestAndBranch32, s[0]->arch_opcode());
   1197     EXPECT_EQ(kNotEqual, s[0]->flags_condition());
   1198     EXPECT_EQ(4U, s[0]->InputCount());
   1199     EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
   1200     EXPECT_EQ(bit, s.ToInt32(s[0]->InputAt(1)));
   1201   }
   1202 
   1203   TRACED_FORRANGE(int, bit, 0, 31) {
   1204     uint32_t mask = 1 << bit;
   1205     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
   1206     RawMachineLabel a, b;
   1207     m.Branch(
   1208         m.Word32BinaryNot(m.Word32And(m.Int32Constant(mask), m.Parameter(0))),
   1209         &a, &b);
   1210     m.Bind(&a);
   1211     m.Return(m.Int32Constant(1));
   1212     m.Bind(&b);
   1213     m.Return(m.Int32Constant(0));
   1214     Stream s = m.Build();
   1215     ASSERT_EQ(1U, s.size());
   1216     EXPECT_EQ(kArm64TestAndBranch32, s[0]->arch_opcode());
   1217     EXPECT_EQ(kEqual, s[0]->flags_condition());
   1218     EXPECT_EQ(4U, s[0]->InputCount());
   1219     EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
   1220     EXPECT_EQ(bit, s.ToInt32(s[0]->InputAt(1)));
   1221   }
   1222 }
   1223 
   1224 
   1225 TEST_F(InstructionSelectorTest, Word64AndBranchWithOneBitMaskOnRight) {
   1226   TRACED_FORRANGE(int, bit, 0, 63) {
   1227     uint64_t mask = 1L << bit;
   1228     StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
   1229     RawMachineLabel a, b;
   1230     m.Branch(m.Word64And(m.Parameter(0), m.Int64Constant(mask)), &a, &b);
   1231     m.Bind(&a);
   1232     m.Return(m.Int32Constant(1));
   1233     m.Bind(&b);
   1234     m.Return(m.Int32Constant(0));
   1235     Stream s = m.Build();
   1236     ASSERT_EQ(1U, s.size());
   1237     EXPECT_EQ(kArm64TestAndBranch, s[0]->arch_opcode());
   1238     EXPECT_EQ(kNotEqual, s[0]->flags_condition());
   1239     EXPECT_EQ(4U, s[0]->InputCount());
   1240     EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
   1241     EXPECT_EQ(bit, s.ToInt64(s[0]->InputAt(1)));
   1242   }
   1243 }
   1244 
   1245 
   1246 TEST_F(InstructionSelectorTest, Word64AndBranchWithOneBitMaskOnLeft) {
   1247   TRACED_FORRANGE(int, bit, 0, 63) {
   1248     uint64_t mask = 1L << bit;
   1249     StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
   1250     RawMachineLabel a, b;
   1251     m.Branch(m.Word64And(m.Int64Constant(mask), m.Parameter(0)), &a, &b);
   1252     m.Bind(&a);
   1253     m.Return(m.Int32Constant(1));
   1254     m.Bind(&b);
   1255     m.Return(m.Int32Constant(0));
   1256     Stream s = m.Build();
   1257     ASSERT_EQ(1U, s.size());
   1258     EXPECT_EQ(kArm64TestAndBranch, s[0]->arch_opcode());
   1259     EXPECT_EQ(kNotEqual, s[0]->flags_condition());
   1260     EXPECT_EQ(4U, s[0]->InputCount());
   1261     EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
   1262     EXPECT_EQ(bit, s.ToInt64(s[0]->InputAt(1)));
   1263   }
   1264 }
   1265 
   1266 TEST_F(InstructionSelectorTest, Word32EqualZeroAndBranchWithOneBitMask) {
   1267   TRACED_FORRANGE(int, bit, 0, 31) {
   1268     uint32_t mask = 1 << bit;
   1269     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
   1270     RawMachineLabel a, b;
   1271     m.Branch(m.Word32Equal(m.Word32And(m.Int32Constant(mask), m.Parameter(0)),
   1272                            m.Int32Constant(0)),
   1273              &a, &b);
   1274     m.Bind(&a);
   1275     m.Return(m.Int32Constant(1));
   1276     m.Bind(&b);
   1277     m.Return(m.Int32Constant(0));
   1278     Stream s = m.Build();
   1279     ASSERT_EQ(1U, s.size());
   1280     EXPECT_EQ(kArm64TestAndBranch32, s[0]->arch_opcode());
   1281     EXPECT_EQ(kEqual, s[0]->flags_condition());
   1282     EXPECT_EQ(4U, s[0]->InputCount());
   1283     EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
   1284     EXPECT_EQ(bit, s.ToInt32(s[0]->InputAt(1)));
   1285   }
   1286 
   1287   TRACED_FORRANGE(int, bit, 0, 31) {
   1288     uint32_t mask = 1 << bit;
   1289     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
   1290     RawMachineLabel a, b;
   1291     m.Branch(
   1292         m.Word32NotEqual(m.Word32And(m.Int32Constant(mask), m.Parameter(0)),
   1293                          m.Int32Constant(0)),
   1294         &a, &b);
   1295     m.Bind(&a);
   1296     m.Return(m.Int32Constant(1));
   1297     m.Bind(&b);
   1298     m.Return(m.Int32Constant(0));
   1299     Stream s = m.Build();
   1300     ASSERT_EQ(1U, s.size());
   1301     EXPECT_EQ(kArm64TestAndBranch32, s[0]->arch_opcode());
   1302     EXPECT_EQ(kNotEqual, s[0]->flags_condition());
   1303     EXPECT_EQ(4U, s[0]->InputCount());
   1304     EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
   1305     EXPECT_EQ(bit, s.ToInt32(s[0]->InputAt(1)));
   1306   }
   1307 }
   1308 
   1309 TEST_F(InstructionSelectorTest, Word64EqualZeroAndBranchWithOneBitMask) {
   1310   TRACED_FORRANGE(int, bit, 0, 63) {
   1311     uint64_t mask = V8_UINT64_C(1) << bit;
   1312     StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
   1313     RawMachineLabel a, b;
   1314     m.Branch(m.Word64Equal(m.Word64And(m.Int64Constant(mask), m.Parameter(0)),
   1315                            m.Int64Constant(0)),
   1316              &a, &b);
   1317     m.Bind(&a);
   1318     m.Return(m.Int64Constant(1));
   1319     m.Bind(&b);
   1320     m.Return(m.Int64Constant(0));
   1321     Stream s = m.Build();
   1322     ASSERT_EQ(1U, s.size());
   1323     EXPECT_EQ(kArm64TestAndBranch, s[0]->arch_opcode());
   1324     EXPECT_EQ(kEqual, s[0]->flags_condition());
   1325     EXPECT_EQ(4U, s[0]->InputCount());
   1326     EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
   1327     EXPECT_EQ(bit, s.ToInt64(s[0]->InputAt(1)));
   1328   }
   1329 
   1330   TRACED_FORRANGE(int, bit, 0, 63) {
   1331     uint64_t mask = V8_UINT64_C(1) << bit;
   1332     StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
   1333     RawMachineLabel a, b;
   1334     m.Branch(
   1335         m.Word64NotEqual(m.Word64And(m.Int64Constant(mask), m.Parameter(0)),
   1336                          m.Int64Constant(0)),
   1337         &a, &b);
   1338     m.Bind(&a);
   1339     m.Return(m.Int64Constant(1));
   1340     m.Bind(&b);
   1341     m.Return(m.Int64Constant(0));
   1342     Stream s = m.Build();
   1343     ASSERT_EQ(1U, s.size());
   1344     EXPECT_EQ(kArm64TestAndBranch, s[0]->arch_opcode());
   1345     EXPECT_EQ(kNotEqual, s[0]->flags_condition());
   1346     EXPECT_EQ(4U, s[0]->InputCount());
   1347     EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
   1348     EXPECT_EQ(bit, s.ToInt64(s[0]->InputAt(1)));
   1349   }
   1350 }
   1351 
   1352 TEST_F(InstructionSelectorTest, CompareAgainstZeroAndBranch) {
   1353   {
   1354     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
   1355     RawMachineLabel a, b;
   1356     Node* p0 = m.Parameter(0);
   1357     m.Branch(p0, &a, &b);
   1358     m.Bind(&a);
   1359     m.Return(m.Int32Constant(1));
   1360     m.Bind(&b);
   1361     m.Return(m.Int32Constant(0));
   1362     Stream s = m.Build();
   1363     ASSERT_EQ(1U, s.size());
   1364     EXPECT_EQ(kArm64CompareAndBranch32, s[0]->arch_opcode());
   1365     EXPECT_EQ(kNotEqual, s[0]->flags_condition());
   1366     EXPECT_EQ(3U, s[0]->InputCount());
   1367     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
   1368   }
   1369 
   1370   {
   1371     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
   1372     RawMachineLabel a, b;
   1373     Node* p0 = m.Parameter(0);
   1374     m.Branch(m.Word32BinaryNot(p0), &a, &b);
   1375     m.Bind(&a);
   1376     m.Return(m.Int32Constant(1));
   1377     m.Bind(&b);
   1378     m.Return(m.Int32Constant(0));
   1379     Stream s = m.Build();
   1380     ASSERT_EQ(1U, s.size());
   1381     EXPECT_EQ(kArm64CompareAndBranch32, s[0]->arch_opcode());
   1382     EXPECT_EQ(kEqual, s[0]->flags_condition());
   1383     EXPECT_EQ(3U, s[0]->InputCount());
   1384     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
   1385   }
   1386 }
   1387 
   1388 TEST_F(InstructionSelectorTest, EqualZeroAndBranch) {
   1389   {
   1390     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
   1391     RawMachineLabel a, b;
   1392     Node* p0 = m.Parameter(0);
   1393     m.Branch(m.Word32Equal(p0, m.Int32Constant(0)), &a, &b);
   1394     m.Bind(&a);
   1395     m.Return(m.Int32Constant(1));
   1396     m.Bind(&b);
   1397     m.Return(m.Int32Constant(0));
   1398     Stream s = m.Build();
   1399     ASSERT_EQ(1U, s.size());
   1400     EXPECT_EQ(kArm64CompareAndBranch32, s[0]->arch_opcode());
   1401     EXPECT_EQ(kEqual, s[0]->flags_condition());
   1402     EXPECT_EQ(3U, s[0]->InputCount());
   1403     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
   1404   }
   1405 
   1406   {
   1407     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
   1408     RawMachineLabel a, b;
   1409     Node* p0 = m.Parameter(0);
   1410     m.Branch(m.Word32NotEqual(p0, m.Int32Constant(0)), &a, &b);
   1411     m.Bind(&a);
   1412     m.Return(m.Int32Constant(1));
   1413     m.Bind(&b);
   1414     m.Return(m.Int32Constant(0));
   1415     Stream s = m.Build();
   1416     ASSERT_EQ(1U, s.size());
   1417     EXPECT_EQ(kArm64CompareAndBranch32, s[0]->arch_opcode());
   1418     EXPECT_EQ(kNotEqual, s[0]->flags_condition());
   1419     EXPECT_EQ(3U, s[0]->InputCount());
   1420     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
   1421   }
   1422 
   1423   {
   1424     StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
   1425     RawMachineLabel a, b;
   1426     Node* p0 = m.Parameter(0);
   1427     m.Branch(m.Word64Equal(p0, m.Int64Constant(0)), &a, &b);
   1428     m.Bind(&a);
   1429     m.Return(m.Int64Constant(1));
   1430     m.Bind(&b);
   1431     m.Return(m.Int64Constant(0));
   1432     Stream s = m.Build();
   1433     ASSERT_EQ(1U, s.size());
   1434     EXPECT_EQ(kArm64CompareAndBranch, s[0]->arch_opcode());
   1435     EXPECT_EQ(kEqual, s[0]->flags_condition());
   1436     EXPECT_EQ(3U, s[0]->InputCount());
   1437     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
   1438   }
   1439 
   1440   {
   1441     StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
   1442     RawMachineLabel a, b;
   1443     Node* p0 = m.Parameter(0);
   1444     m.Branch(m.Word64NotEqual(p0, m.Int64Constant(0)), &a, &b);
   1445     m.Bind(&a);
   1446     m.Return(m.Int64Constant(1));
   1447     m.Bind(&b);
   1448     m.Return(m.Int64Constant(0));
   1449     Stream s = m.Build();
   1450     ASSERT_EQ(1U, s.size());
   1451     EXPECT_EQ(kArm64CompareAndBranch, s[0]->arch_opcode());
   1452     EXPECT_EQ(kNotEqual, s[0]->flags_condition());
   1453     EXPECT_EQ(3U, s[0]->InputCount());
   1454     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
   1455   }
   1456 }
   1457 
   1458 // -----------------------------------------------------------------------------
   1459 // Add and subtract instructions with overflow.
   1460 
   1461 
   1462 typedef InstructionSelectorTestWithParam<MachInst2>
   1463     InstructionSelectorOvfAddSubTest;
   1464 
   1465 
   1466 TEST_P(InstructionSelectorOvfAddSubTest, OvfParameter) {
   1467   const MachInst2 dpi = GetParam();
   1468   const MachineType type = dpi.machine_type;
   1469   StreamBuilder m(this, type, type, type);
   1470   m.Return(
   1471       m.Projection(1, (m.*dpi.constructor)(m.Parameter(0), m.Parameter(1))));
   1472   Stream s = m.Build();
   1473   ASSERT_EQ(1U, s.size());
   1474   EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
   1475   EXPECT_EQ(2U, s[0]->InputCount());
   1476   EXPECT_LE(1U, s[0]->OutputCount());
   1477   EXPECT_EQ(kFlags_set, s[0]->flags_mode());
   1478   EXPECT_EQ(kOverflow, s[0]->flags_condition());
   1479 }
   1480 
   1481 
   1482 TEST_P(InstructionSelectorOvfAddSubTest, OvfImmediateOnRight) {
   1483   const MachInst2 dpi = GetParam();
   1484   const MachineType type = dpi.machine_type;
   1485   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
   1486     StreamBuilder m(this, type, type);
   1487     m.Return(m.Projection(
   1488         1, (m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm))));
   1489     Stream s = m.Build();
   1490     ASSERT_EQ(1U, s.size());
   1491     EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
   1492     ASSERT_EQ(2U, s[0]->InputCount());
   1493     EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
   1494     EXPECT_LE(1U, s[0]->OutputCount());
   1495     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
   1496     EXPECT_EQ(kOverflow, s[0]->flags_condition());
   1497   }
   1498 }
   1499 
   1500 
   1501 TEST_P(InstructionSelectorOvfAddSubTest, ValParameter) {
   1502   const MachInst2 dpi = GetParam();
   1503   const MachineType type = dpi.machine_type;
   1504   StreamBuilder m(this, type, type, type);
   1505   m.Return(
   1506       m.Projection(0, (m.*dpi.constructor)(m.Parameter(0), m.Parameter(1))));
   1507   Stream s = m.Build();
   1508   ASSERT_EQ(1U, s.size());
   1509   EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
   1510   EXPECT_EQ(2U, s[0]->InputCount());
   1511   EXPECT_LE(1U, s[0]->OutputCount());
   1512   EXPECT_EQ(kFlags_none, s[0]->flags_mode());
   1513 }
   1514 
   1515 
   1516 TEST_P(InstructionSelectorOvfAddSubTest, ValImmediateOnRight) {
   1517   const MachInst2 dpi = GetParam();
   1518   const MachineType type = dpi.machine_type;
   1519   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
   1520     StreamBuilder m(this, type, type);
   1521     m.Return(m.Projection(
   1522         0, (m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm))));
   1523     Stream s = m.Build();
   1524     ASSERT_EQ(1U, s.size());
   1525     EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
   1526     ASSERT_EQ(2U, s[0]->InputCount());
   1527     EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
   1528     EXPECT_LE(1U, s[0]->OutputCount());
   1529     EXPECT_EQ(kFlags_none, s[0]->flags_mode());
   1530   }
   1531 }
   1532 
   1533 
   1534 TEST_P(InstructionSelectorOvfAddSubTest, BothParameter) {
   1535   const MachInst2 dpi = GetParam();
   1536   const MachineType type = dpi.machine_type;
   1537   StreamBuilder m(this, type, type, type);
   1538   Node* n = (m.*dpi.constructor)(m.Parameter(0), m.Parameter(1));
   1539   m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n)));
   1540   Stream s = m.Build();
   1541   ASSERT_LE(1U, s.size());
   1542   EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
   1543   EXPECT_EQ(2U, s[0]->InputCount());
   1544   EXPECT_EQ(2U, s[0]->OutputCount());
   1545   EXPECT_EQ(kFlags_set, s[0]->flags_mode());
   1546   EXPECT_EQ(kOverflow, s[0]->flags_condition());
   1547 }
   1548 
   1549 
   1550 TEST_P(InstructionSelectorOvfAddSubTest, BothImmediateOnRight) {
   1551   const MachInst2 dpi = GetParam();
   1552   const MachineType type = dpi.machine_type;
   1553   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
   1554     StreamBuilder m(this, type, type);
   1555     Node* n = (m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm));
   1556     m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n)));
   1557     Stream s = m.Build();
   1558     ASSERT_LE(1U, s.size());
   1559     EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
   1560     ASSERT_EQ(2U, s[0]->InputCount());
   1561     EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
   1562     EXPECT_EQ(2U, s[0]->OutputCount());
   1563     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
   1564     EXPECT_EQ(kOverflow, s[0]->flags_condition());
   1565   }
   1566 }
   1567 
   1568 
   1569 TEST_P(InstructionSelectorOvfAddSubTest, BranchWithParameters) {
   1570   const MachInst2 dpi = GetParam();
   1571   const MachineType type = dpi.machine_type;
   1572   StreamBuilder m(this, type, type, type);
   1573   RawMachineLabel a, b;
   1574   Node* n = (m.*dpi.constructor)(m.Parameter(0), m.Parameter(1));
   1575   m.Branch(m.Projection(1, n), &a, &b);
   1576   m.Bind(&a);
   1577   m.Return(m.Int32Constant(0));
   1578   m.Bind(&b);
   1579   m.Return(m.Projection(0, n));
   1580   Stream s = m.Build();
   1581   ASSERT_EQ(1U, s.size());
   1582   EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
   1583   EXPECT_EQ(4U, s[0]->InputCount());
   1584   EXPECT_EQ(1U, s[0]->OutputCount());
   1585   EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
   1586   EXPECT_EQ(kOverflow, s[0]->flags_condition());
   1587 }
   1588 
   1589 
   1590 TEST_P(InstructionSelectorOvfAddSubTest, BranchWithImmediateOnRight) {
   1591   const MachInst2 dpi = GetParam();
   1592   const MachineType type = dpi.machine_type;
   1593   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
   1594     StreamBuilder m(this, type, type);
   1595     RawMachineLabel a, b;
   1596     Node* n = (m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm));
   1597     m.Branch(m.Projection(1, n), &a, &b);
   1598     m.Bind(&a);
   1599     m.Return(m.Int32Constant(0));
   1600     m.Bind(&b);
   1601     m.Return(m.Projection(0, n));
   1602     Stream s = m.Build();
   1603     ASSERT_EQ(1U, s.size());
   1604     EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
   1605     ASSERT_EQ(4U, s[0]->InputCount());
   1606     EXPECT_EQ(1U, s[0]->OutputCount());
   1607     EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
   1608     EXPECT_EQ(kOverflow, s[0]->flags_condition());
   1609   }
   1610 }
   1611 
   1612 TEST_P(InstructionSelectorOvfAddSubTest, RORShift) {
   1613   // ADD and SUB do not support ROR shifts, make sure we do not try
   1614   // to merge them into the ADD/SUB instruction.
   1615   const MachInst2 dpi = GetParam();
   1616   const MachineType type = dpi.machine_type;
   1617   auto rotate = &RawMachineAssembler::Word64Ror;
   1618   ArchOpcode rotate_opcode = kArm64Ror;
   1619   if (type == MachineType::Int32()) {
   1620     rotate = &RawMachineAssembler::Word32Ror;
   1621     rotate_opcode = kArm64Ror32;
   1622   }
   1623   TRACED_FORRANGE(int32_t, imm, -32, 63) {
   1624     StreamBuilder m(this, type, type, type);
   1625     Node* const p0 = m.Parameter(0);
   1626     Node* const p1 = m.Parameter(1);
   1627     Node* r = (m.*rotate)(p1, m.Int32Constant(imm));
   1628     m.Return((m.*dpi.constructor)(p0, r));
   1629     Stream s = m.Build();
   1630     ASSERT_EQ(2U, s.size());
   1631     EXPECT_EQ(rotate_opcode, s[0]->arch_opcode());
   1632     EXPECT_EQ(dpi.arch_opcode, s[1]->arch_opcode());
   1633   }
   1634 }
   1635 
   1636 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
   1637                         InstructionSelectorOvfAddSubTest,
   1638                         ::testing::ValuesIn(kOvfAddSubInstructions));
   1639 
   1640 
   1641 TEST_F(InstructionSelectorTest, OvfFlagAddImmediateOnLeft) {
   1642   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
   1643     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
   1644     m.Return(m.Projection(
   1645         1, m.Int32AddWithOverflow(m.Int32Constant(imm), m.Parameter(0))));
   1646     Stream s = m.Build();
   1647 
   1648     ASSERT_EQ(1U, s.size());
   1649     EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
   1650     EXPECT_EQ(2U, s[0]->InputCount());
   1651     EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
   1652     EXPECT_LE(1U, s[0]->OutputCount());
   1653     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
   1654     EXPECT_EQ(kOverflow, s[0]->flags_condition());
   1655   }
   1656 }
   1657 
   1658 
   1659 TEST_F(InstructionSelectorTest, OvfValAddImmediateOnLeft) {
   1660   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
   1661     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
   1662     m.Return(m.Projection(
   1663         0, m.Int32AddWithOverflow(m.Int32Constant(imm), m.Parameter(0))));
   1664     Stream s = m.Build();
   1665 
   1666     ASSERT_EQ(1U, s.size());
   1667     EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
   1668     ASSERT_EQ(2U, s[0]->InputCount());
   1669     EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
   1670     EXPECT_LE(1U, s[0]->OutputCount());
   1671     EXPECT_EQ(kFlags_none, s[0]->flags_mode());
   1672   }
   1673 }
   1674 
   1675 
   1676 TEST_F(InstructionSelectorTest, OvfBothAddImmediateOnLeft) {
   1677   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
   1678     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
   1679     Node* n = m.Int32AddWithOverflow(m.Int32Constant(imm), m.Parameter(0));
   1680     m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n)));
   1681     Stream s = m.Build();
   1682 
   1683     ASSERT_LE(1U, s.size());
   1684     EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
   1685     ASSERT_EQ(2U, s[0]->InputCount());
   1686     EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
   1687     EXPECT_EQ(2U, s[0]->OutputCount());
   1688     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
   1689     EXPECT_EQ(kOverflow, s[0]->flags_condition());
   1690   }
   1691 }
   1692 
   1693 
   1694 TEST_F(InstructionSelectorTest, OvfBranchWithImmediateOnLeft) {
   1695   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
   1696     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
   1697     RawMachineLabel a, b;
   1698     Node* n = m.Int32AddWithOverflow(m.Int32Constant(imm), m.Parameter(0));
   1699     m.Branch(m.Projection(1, n), &a, &b);
   1700     m.Bind(&a);
   1701     m.Return(m.Int32Constant(0));
   1702     m.Bind(&b);
   1703     m.Return(m.Projection(0, n));
   1704     Stream s = m.Build();
   1705 
   1706     ASSERT_EQ(1U, s.size());
   1707     EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
   1708     ASSERT_EQ(4U, s[0]->InputCount());
   1709     EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
   1710     EXPECT_EQ(1U, s[0]->OutputCount());
   1711     EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
   1712     EXPECT_EQ(kOverflow, s[0]->flags_condition());
   1713   }
   1714 }
   1715 
   1716 
   1717 // -----------------------------------------------------------------------------
   1718 // Shift instructions.
   1719 
   1720 
   1721 typedef InstructionSelectorTestWithParam<Shift> InstructionSelectorShiftTest;
   1722 
   1723 
   1724 TEST_P(InstructionSelectorShiftTest, Parameter) {
   1725   const Shift shift = GetParam();
   1726   const MachineType type = shift.mi.machine_type;
   1727   StreamBuilder m(this, type, type, type);
   1728   m.Return((m.*shift.mi.constructor)(m.Parameter(0), m.Parameter(1)));
   1729   Stream s = m.Build();
   1730   ASSERT_EQ(1U, s.size());
   1731   EXPECT_EQ(shift.mi.arch_opcode, s[0]->arch_opcode());
   1732   EXPECT_EQ(2U, s[0]->InputCount());
   1733   EXPECT_EQ(1U, s[0]->OutputCount());
   1734 }
   1735 
   1736 
   1737 TEST_P(InstructionSelectorShiftTest, Immediate) {
   1738   const Shift shift = GetParam();
   1739   const MachineType type = shift.mi.machine_type;
   1740   TRACED_FORRANGE(int32_t, imm, 0,
   1741                   ((1 << ElementSizeLog2Of(type.representation())) * 8) - 1) {
   1742     StreamBuilder m(this, type, type);
   1743     m.Return((m.*shift.mi.constructor)(m.Parameter(0), m.Int32Constant(imm)));
   1744     Stream s = m.Build();
   1745     ASSERT_EQ(1U, s.size());
   1746     EXPECT_EQ(shift.mi.arch_opcode, s[0]->arch_opcode());
   1747     EXPECT_EQ(2U, s[0]->InputCount());
   1748     EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
   1749     EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
   1750     EXPECT_EQ(1U, s[0]->OutputCount());
   1751   }
   1752 }
   1753 
   1754 
   1755 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorShiftTest,
   1756                         ::testing::ValuesIn(kShiftInstructions));
   1757 
   1758 
   1759 TEST_F(InstructionSelectorTest, Word64ShlWithChangeInt32ToInt64) {
   1760   TRACED_FORRANGE(int64_t, x, 32, 63) {
   1761     StreamBuilder m(this, MachineType::Int64(), MachineType::Int32());
   1762     Node* const p0 = m.Parameter(0);
   1763     Node* const n = m.Word64Shl(m.ChangeInt32ToInt64(p0), m.Int64Constant(x));
   1764     m.Return(n);
   1765     Stream s = m.Build();
   1766     ASSERT_EQ(1U, s.size());
   1767     EXPECT_EQ(kArm64Lsl, s[0]->arch_opcode());
   1768     ASSERT_EQ(2U, s[0]->InputCount());
   1769     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
   1770     EXPECT_EQ(x, s.ToInt64(s[0]->InputAt(1)));
   1771     ASSERT_EQ(1U, s[0]->OutputCount());
   1772     EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
   1773   }
   1774 }
   1775 
   1776 
   1777 TEST_F(InstructionSelectorTest, Word64ShlWithChangeUint32ToUint64) {
   1778   TRACED_FORRANGE(int64_t, x, 32, 63) {
   1779     StreamBuilder m(this, MachineType::Int64(), MachineType::Uint32());
   1780     Node* const p0 = m.Parameter(0);
   1781     Node* const n = m.Word64Shl(m.ChangeUint32ToUint64(p0), m.Int64Constant(x));
   1782     m.Return(n);
   1783     Stream s = m.Build();
   1784     ASSERT_EQ(1U, s.size());
   1785     EXPECT_EQ(kArm64Lsl, s[0]->arch_opcode());
   1786     ASSERT_EQ(2U, s[0]->InputCount());
   1787     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
   1788     EXPECT_EQ(x, s.ToInt64(s[0]->InputAt(1)));
   1789     ASSERT_EQ(1U, s[0]->OutputCount());
   1790     EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
   1791   }
   1792 }
   1793 
   1794 
   1795 TEST_F(InstructionSelectorTest, TruncateInt64ToInt32WithWord64Sar) {
   1796   StreamBuilder m(this, MachineType::Int32(), MachineType::Int64());
   1797   Node* const p = m.Parameter(0);
   1798   Node* const t = m.TruncateInt64ToInt32(m.Word64Sar(p, m.Int64Constant(32)));
   1799   m.Return(t);
   1800   Stream s = m.Build();
   1801   ASSERT_EQ(1U, s.size());
   1802   EXPECT_EQ(kArm64Lsr, s[0]->arch_opcode());
   1803   ASSERT_EQ(2U, s[0]->InputCount());
   1804   EXPECT_EQ(s.ToVreg(p), s.ToVreg(s[0]->InputAt(0)));
   1805   EXPECT_EQ(32, s.ToInt64(s[0]->InputAt(1)));
   1806   ASSERT_EQ(1U, s[0]->OutputCount());
   1807   EXPECT_EQ(s.ToVreg(t), s.ToVreg(s[0]->OutputAt(0)));
   1808 }
   1809 
   1810 
   1811 TEST_F(InstructionSelectorTest, TruncateInt64ToInt32WithWord64Shr) {
   1812   TRACED_FORRANGE(int64_t, x, 32, 63) {
   1813     StreamBuilder m(this, MachineType::Int32(), MachineType::Int64());
   1814     Node* const p = m.Parameter(0);
   1815     Node* const t = m.TruncateInt64ToInt32(m.Word64Shr(p, m.Int64Constant(x)));
   1816     m.Return(t);
   1817     Stream s = m.Build();
   1818     ASSERT_EQ(1U, s.size());
   1819     EXPECT_EQ(kArm64Lsr, s[0]->arch_opcode());
   1820     ASSERT_EQ(2U, s[0]->InputCount());
   1821     EXPECT_EQ(s.ToVreg(p), s.ToVreg(s[0]->InputAt(0)));
   1822     EXPECT_EQ(x, s.ToInt64(s[0]->InputAt(1)));
   1823     ASSERT_EQ(1U, s[0]->OutputCount());
   1824     EXPECT_EQ(s.ToVreg(t), s.ToVreg(s[0]->OutputAt(0)));
   1825   }
   1826 }
   1827 
   1828 
   1829 // -----------------------------------------------------------------------------
   1830 // Mul and Div instructions.
   1831 
   1832 
   1833 typedef InstructionSelectorTestWithParam<MachInst2>
   1834     InstructionSelectorMulDivTest;
   1835 
   1836 
   1837 TEST_P(InstructionSelectorMulDivTest, Parameter) {
   1838   const MachInst2 dpi = GetParam();
   1839   const MachineType type = dpi.machine_type;
   1840   StreamBuilder m(this, type, type, type);
   1841   m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)));
   1842   Stream s = m.Build();
   1843   ASSERT_EQ(1U, s.size());
   1844   EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
   1845   EXPECT_EQ(2U, s[0]->InputCount());
   1846   EXPECT_EQ(1U, s[0]->OutputCount());
   1847 }
   1848 
   1849 
   1850 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorMulDivTest,
   1851                         ::testing::ValuesIn(kMulDivInstructions));
   1852 
   1853 
   1854 namespace {
   1855 
   1856 struct MulDPInst {
   1857   const char* mul_constructor_name;
   1858   Node* (RawMachineAssembler::*mul_constructor)(Node*, Node*);
   1859   Node* (RawMachineAssembler::*add_constructor)(Node*, Node*);
   1860   Node* (RawMachineAssembler::*sub_constructor)(Node*, Node*);
   1861   ArchOpcode add_arch_opcode;
   1862   ArchOpcode sub_arch_opcode;
   1863   ArchOpcode neg_arch_opcode;
   1864   MachineType machine_type;
   1865 };
   1866 
   1867 
   1868 std::ostream& operator<<(std::ostream& os, const MulDPInst& inst) {
   1869   return os << inst.mul_constructor_name;
   1870 }
   1871 
   1872 }  // namespace
   1873 
   1874 
   1875 static const MulDPInst kMulDPInstructions[] = {
   1876     {"Int32Mul", &RawMachineAssembler::Int32Mul, &RawMachineAssembler::Int32Add,
   1877      &RawMachineAssembler::Int32Sub, kArm64Madd32, kArm64Msub32, kArm64Mneg32,
   1878      MachineType::Int32()},
   1879     {"Int64Mul", &RawMachineAssembler::Int64Mul, &RawMachineAssembler::Int64Add,
   1880      &RawMachineAssembler::Int64Sub, kArm64Madd, kArm64Msub, kArm64Mneg,
   1881      MachineType::Int64()}};
   1882 
   1883 
   1884 typedef InstructionSelectorTestWithParam<MulDPInst>
   1885     InstructionSelectorIntDPWithIntMulTest;
   1886 
   1887 
   1888 TEST_P(InstructionSelectorIntDPWithIntMulTest, AddWithMul) {
   1889   const MulDPInst mdpi = GetParam();
   1890   const MachineType type = mdpi.machine_type;
   1891   {
   1892     StreamBuilder m(this, type, type, type, type);
   1893     Node* n = (m.*mdpi.mul_constructor)(m.Parameter(1), m.Parameter(2));
   1894     m.Return((m.*mdpi.add_constructor)(m.Parameter(0), n));
   1895     Stream s = m.Build();
   1896     ASSERT_EQ(1U, s.size());
   1897     EXPECT_EQ(mdpi.add_arch_opcode, s[0]->arch_opcode());
   1898     EXPECT_EQ(3U, s[0]->InputCount());
   1899     EXPECT_EQ(1U, s[0]->OutputCount());
   1900   }
   1901   {
   1902     StreamBuilder m(this, type, type, type, type);
   1903     Node* n = (m.*mdpi.mul_constructor)(m.Parameter(0), m.Parameter(1));
   1904     m.Return((m.*mdpi.add_constructor)(n, m.Parameter(2)));
   1905     Stream s = m.Build();
   1906     ASSERT_EQ(1U, s.size());
   1907     EXPECT_EQ(mdpi.add_arch_opcode, s[0]->arch_opcode());
   1908     EXPECT_EQ(3U, s[0]->InputCount());
   1909     EXPECT_EQ(1U, s[0]->OutputCount());
   1910   }
   1911 }
   1912 
   1913 
   1914 TEST_P(InstructionSelectorIntDPWithIntMulTest, SubWithMul) {
   1915   const MulDPInst mdpi = GetParam();
   1916   const MachineType type = mdpi.machine_type;
   1917   {
   1918     StreamBuilder m(this, type, type, type, type);
   1919     Node* n = (m.*mdpi.mul_constructor)(m.Parameter(1), m.Parameter(2));
   1920     m.Return((m.*mdpi.sub_constructor)(m.Parameter(0), n));
   1921     Stream s = m.Build();
   1922     ASSERT_EQ(1U, s.size());
   1923     EXPECT_EQ(mdpi.sub_arch_opcode, s[0]->arch_opcode());
   1924     EXPECT_EQ(3U, s[0]->InputCount());
   1925     EXPECT_EQ(1U, s[0]->OutputCount());
   1926   }
   1927 }
   1928 
   1929 
   1930 TEST_P(InstructionSelectorIntDPWithIntMulTest, NegativeMul) {
   1931   const MulDPInst mdpi = GetParam();
   1932   const MachineType type = mdpi.machine_type;
   1933   {
   1934     StreamBuilder m(this, type, type, type);
   1935     Node* n =
   1936         (m.*mdpi.sub_constructor)(BuildConstant(m, type, 0), m.Parameter(0));
   1937     m.Return((m.*mdpi.mul_constructor)(n, m.Parameter(1)));
   1938     Stream s = m.Build();
   1939     ASSERT_EQ(1U, s.size());
   1940     EXPECT_EQ(mdpi.neg_arch_opcode, s[0]->arch_opcode());
   1941     EXPECT_EQ(2U, s[0]->InputCount());
   1942     EXPECT_EQ(1U, s[0]->OutputCount());
   1943   }
   1944   {
   1945     StreamBuilder m(this, type, type, type);
   1946     Node* n =
   1947         (m.*mdpi.sub_constructor)(BuildConstant(m, type, 0), m.Parameter(1));
   1948     m.Return((m.*mdpi.mul_constructor)(m.Parameter(0), n));
   1949     Stream s = m.Build();
   1950     ASSERT_EQ(1U, s.size());
   1951     EXPECT_EQ(mdpi.neg_arch_opcode, s[0]->arch_opcode());
   1952     EXPECT_EQ(2U, s[0]->InputCount());
   1953     EXPECT_EQ(1U, s[0]->OutputCount());
   1954   }
   1955 }
   1956 
   1957 
   1958 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
   1959                         InstructionSelectorIntDPWithIntMulTest,
   1960                         ::testing::ValuesIn(kMulDPInstructions));
   1961 
   1962 
   1963 TEST_F(InstructionSelectorTest, Int32MulWithImmediate) {
   1964   // x * (2^k + 1) -> x + (x << k)
   1965   TRACED_FORRANGE(int32_t, k, 1, 30) {
   1966     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
   1967     m.Return(m.Int32Mul(m.Parameter(0), m.Int32Constant((1 << k) + 1)));
   1968     Stream s = m.Build();
   1969     ASSERT_EQ(1U, s.size());
   1970     EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
   1971     EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
   1972     ASSERT_EQ(3U, s[0]->InputCount());
   1973     EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
   1974     EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2)));
   1975     EXPECT_EQ(1U, s[0]->OutputCount());
   1976   }
   1977   // (2^k + 1) * x -> x + (x << k)
   1978   TRACED_FORRANGE(int32_t, k, 1, 30) {
   1979     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
   1980     m.Return(m.Int32Mul(m.Int32Constant((1 << k) + 1), m.Parameter(0)));
   1981     Stream s = m.Build();
   1982     ASSERT_EQ(1U, s.size());
   1983     EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
   1984     EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
   1985     ASSERT_EQ(3U, s[0]->InputCount());
   1986     EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
   1987     EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2)));
   1988     EXPECT_EQ(1U, s[0]->OutputCount());
   1989   }
   1990   // x * (2^k + 1) + c -> x + (x << k) + c
   1991   TRACED_FORRANGE(int32_t, k, 1, 30) {
   1992     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
   1993                     MachineType::Int32());
   1994     m.Return(
   1995         m.Int32Add(m.Int32Mul(m.Parameter(0), m.Int32Constant((1 << k) + 1)),
   1996                    m.Parameter(1)));
   1997     Stream s = m.Build();
   1998     ASSERT_EQ(2U, s.size());
   1999     EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
   2000     EXPECT_EQ(kArm64Add32, s[1]->arch_opcode());
   2001     EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
   2002     ASSERT_EQ(3U, s[0]->InputCount());
   2003     EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
   2004     EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2)));
   2005     EXPECT_EQ(1U, s[0]->OutputCount());
   2006   }
   2007   // (2^k + 1) * x + c -> x + (x << k) + c
   2008   TRACED_FORRANGE(int32_t, k, 1, 30) {
   2009     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
   2010                     MachineType::Int32());
   2011     m.Return(
   2012         m.Int32Add(m.Int32Mul(m.Int32Constant((1 << k) + 1), m.Parameter(0)),
   2013                    m.Parameter(1)));
   2014     Stream s = m.Build();
   2015     ASSERT_EQ(2U, s.size());
   2016     EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
   2017     EXPECT_EQ(kArm64Add32, s[1]->arch_opcode());
   2018     EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
   2019     ASSERT_EQ(3U, s[0]->InputCount());
   2020     EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
   2021     EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2)));
   2022     EXPECT_EQ(1U, s[0]->OutputCount());
   2023   }
   2024   // c + x * (2^k + 1) -> c + x + (x << k)
   2025   TRACED_FORRANGE(int32_t, k, 1, 30) {
   2026     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
   2027                     MachineType::Int32());
   2028     m.Return(
   2029         m.Int32Add(m.Parameter(0),
   2030                    m.Int32Mul(m.Parameter(1), m.Int32Constant((1 << k) + 1))));
   2031     Stream s = m.Build();
   2032     ASSERT_EQ(2U, s.size());
   2033     EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
   2034     EXPECT_EQ(kArm64Add32, s[1]->arch_opcode());
   2035     EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
   2036     ASSERT_EQ(3U, s[0]->InputCount());
   2037     EXPECT_EQ(s.ToVreg(s[0]->InputAt(1)), s.ToVreg(s[0]->InputAt(1)));
   2038     EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2)));
   2039     EXPECT_EQ(1U, s[0]->OutputCount());
   2040   }
   2041   // c + (2^k + 1) * x -> c + x + (x << k)
   2042   TRACED_FORRANGE(int32_t, k, 1, 30) {
   2043     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
   2044                     MachineType::Int32());
   2045     m.Return(
   2046         m.Int32Add(m.Parameter(0),
   2047                    m.Int32Mul(m.Int32Constant((1 << k) + 1), m.Parameter(1))));
   2048     Stream s = m.Build();
   2049     ASSERT_EQ(2U, s.size());
   2050     EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
   2051     EXPECT_EQ(kArm64Add32, s[1]->arch_opcode());
   2052     EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
   2053     ASSERT_EQ(3U, s[0]->InputCount());
   2054     EXPECT_EQ(s.ToVreg(s[0]->InputAt(1)), s.ToVreg(s[0]->InputAt(1)));
   2055     EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2)));
   2056     EXPECT_EQ(1U, s[0]->OutputCount());
   2057   }
   2058   // c - x * (2^k + 1) -> c - x + (x << k)
   2059   TRACED_FORRANGE(int32_t, k, 1, 30) {
   2060     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
   2061                     MachineType::Int32());
   2062     m.Return(
   2063         m.Int32Sub(m.Parameter(0),
   2064                    m.Int32Mul(m.Parameter(1), m.Int32Constant((1 << k) + 1))));
   2065     Stream s = m.Build();
   2066     ASSERT_EQ(2U, s.size());
   2067     EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
   2068     EXPECT_EQ(kArm64Sub32, s[1]->arch_opcode());
   2069     EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
   2070     ASSERT_EQ(3U, s[0]->InputCount());
   2071     EXPECT_EQ(s.ToVreg(s[0]->InputAt(1)), s.ToVreg(s[0]->InputAt(1)));
   2072     EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2)));
   2073     EXPECT_EQ(1U, s[0]->OutputCount());
   2074   }
   2075   // c - (2^k + 1) * x -> c - x + (x << k)
   2076   TRACED_FORRANGE(int32_t, k, 1, 30) {
   2077     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
   2078                     MachineType::Int32());
   2079     m.Return(
   2080         m.Int32Sub(m.Parameter(0),
   2081                    m.Int32Mul(m.Int32Constant((1 << k) + 1), m.Parameter(1))));
   2082     Stream s = m.Build();
   2083     ASSERT_EQ(2U, s.size());
   2084     EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
   2085     EXPECT_EQ(kArm64Sub32, s[1]->arch_opcode());
   2086     EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
   2087     ASSERT_EQ(3U, s[0]->InputCount());
   2088     EXPECT_EQ(s.ToVreg(s[0]->InputAt(1)), s.ToVreg(s[0]->InputAt(1)));
   2089     EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2)));
   2090     EXPECT_EQ(1U, s[0]->OutputCount());
   2091   }
   2092 }
   2093 
   2094 
   2095 TEST_F(InstructionSelectorTest, Int64MulWithImmediate) {
   2096   // x * (2^k + 1) -> x + (x << k)
   2097   TRACED_FORRANGE(int64_t, k, 1, 62) {
   2098     StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
   2099     m.Return(m.Int64Mul(m.Parameter(0), m.Int64Constant((1L << k) + 1)));
   2100     Stream s = m.Build();
   2101     ASSERT_EQ(1U, s.size());
   2102     EXPECT_EQ(kArm64Add, s[0]->arch_opcode());
   2103     EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
   2104     ASSERT_EQ(3U, s[0]->InputCount());
   2105     EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
   2106     EXPECT_EQ(k, s.ToInt64(s[0]->InputAt(2)));
   2107     EXPECT_EQ(1U, s[0]->OutputCount());
   2108   }
   2109   // (2^k + 1) * x -> x + (x << k)
   2110   TRACED_FORRANGE(int64_t, k, 1, 62) {
   2111     StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
   2112     m.Return(m.Int64Mul(m.Int64Constant((1L << k) + 1), m.Parameter(0)));
   2113     Stream s = m.Build();
   2114     ASSERT_EQ(1U, s.size());
   2115     EXPECT_EQ(kArm64Add, s[0]->arch_opcode());
   2116     EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
   2117     ASSERT_EQ(3U, s[0]->InputCount());
   2118     EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
   2119     EXPECT_EQ(k, s.ToInt64(s[0]->InputAt(2)));
   2120     EXPECT_EQ(1U, s[0]->OutputCount());
   2121   }
   2122   // x * (2^k + 1) + c -> x + (x << k) + c
   2123   TRACED_FORRANGE(int64_t, k, 1, 62) {
   2124     StreamBuilder m(this, MachineType::Int64(), MachineType::Int64(),
   2125                     MachineType::Int64());
   2126     m.Return(
   2127         m.Int64Add(m.Int64Mul(m.Parameter(0), m.Int64Constant((1L << k) + 1)),
   2128                    m.Parameter(1)));
   2129     Stream s = m.Build();
   2130     ASSERT_EQ(2U, s.size());
   2131     EXPECT_EQ(kArm64Add, s[0]->arch_opcode());
   2132     EXPECT_EQ(kArm64Add, s[1]->arch_opcode());
   2133     EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
   2134     ASSERT_EQ(3U, s[0]->InputCount());
   2135     EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
   2136     EXPECT_EQ(k, s.ToInt64(s[0]->InputAt(2)));
   2137     EXPECT_EQ(1U, s[0]->OutputCount());
   2138   }
   2139   // (2^k + 1) * x + c -> x + (x << k) + c
   2140   TRACED_FORRANGE(int64_t, k, 1, 62) {
   2141     StreamBuilder m(this, MachineType::Int64(), MachineType::Int64(),
   2142                     MachineType::Int64());
   2143     m.Return(
   2144         m.Int64Add(m.Int64Mul(m.Int64Constant((1L << k) + 1), m.Parameter(0)),
   2145                    m.Parameter(1)));
   2146     Stream s = m.Build();
   2147     ASSERT_EQ(2U, s.size());
   2148     EXPECT_EQ(kArm64Add, s[0]->arch_opcode());
   2149     EXPECT_EQ(kArm64Add, s[1]->arch_opcode());
   2150     EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
   2151     ASSERT_EQ(3U, s[0]->InputCount());
   2152     EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
   2153     EXPECT_EQ(k, s.ToInt64(s[0]->InputAt(2)));
   2154     EXPECT_EQ(1U, s[0]->OutputCount());
   2155   }
   2156   // c + x * (2^k + 1) -> c + x + (x << k)
   2157   TRACED_FORRANGE(int64_t, k, 1, 62) {
   2158     StreamBuilder m(this, MachineType::Int64(), MachineType::Int64(),
   2159                     MachineType::Int64());
   2160     m.Return(
   2161         m.Int64Add(m.Parameter(0),
   2162                    m.Int64Mul(m.Parameter(1), m.Int64Constant((1L << k) + 1))));
   2163     Stream s = m.Build();
   2164     ASSERT_EQ(2U, s.size());
   2165     EXPECT_EQ(kArm64Add, s[0]->arch_opcode());
   2166     EXPECT_EQ(kArm64Add, s[1]->arch_opcode());
   2167     EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
   2168     ASSERT_EQ(3U, s[0]->InputCount());
   2169     EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
   2170     EXPECT_EQ(k, s.ToInt64(s[0]->InputAt(2)));
   2171     EXPECT_EQ(1U, s[0]->OutputCount());
   2172   }
   2173   // c + (2^k + 1) * x -> c + x + (x << k)
   2174   TRACED_FORRANGE(int64_t, k, 1, 62) {
   2175     StreamBuilder m(this, MachineType::Int64(), MachineType::Int64(),
   2176                     MachineType::Int64());
   2177     m.Return(
   2178         m.Int64Add(m.Parameter(0),
   2179                    m.Int64Mul(m.Int64Constant((1L << k) + 1), m.Parameter(1))));
   2180     Stream s = m.Build();
   2181     ASSERT_EQ(2U, s.size());
   2182     EXPECT_EQ(kArm64Add, s[0]->arch_opcode());
   2183     EXPECT_EQ(kArm64Add, s[1]->arch_opcode());
   2184     EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
   2185     ASSERT_EQ(3U, s[0]->InputCount());
   2186     EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
   2187     EXPECT_EQ(k, s.ToInt64(s[0]->InputAt(2)));
   2188     EXPECT_EQ(1U, s[0]->OutputCount());
   2189   }
   2190   // c - x * (2^k + 1) -> c - x + (x << k)
   2191   TRACED_FORRANGE(int64_t, k, 1, 62) {
   2192     StreamBuilder m(this, MachineType::Int64(), MachineType::Int64(),
   2193                     MachineType::Int64());
   2194     m.Return(
   2195         m.Int64Sub(m.Parameter(0),
   2196                    m.Int64Mul(m.Parameter(1), m.Int64Constant((1L << k) + 1))));
   2197     Stream s = m.Build();
   2198     ASSERT_EQ(2U, s.size());
   2199     EXPECT_EQ(kArm64Add, s[0]->arch_opcode());
   2200     EXPECT_EQ(kArm64Sub, s[1]->arch_opcode());
   2201     EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
   2202     ASSERT_EQ(3U, s[0]->InputCount());
   2203     EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
   2204     EXPECT_EQ(k, s.ToInt64(s[0]->InputAt(2)));
   2205     EXPECT_EQ(1U, s[0]->OutputCount());
   2206   }
   2207   // c - (2^k + 1) * x -> c - x + (x << k)
   2208   TRACED_FORRANGE(int64_t, k, 1, 62) {
   2209     StreamBuilder m(this, MachineType::Int64(), MachineType::Int64(),
   2210                     MachineType::Int64());
   2211     m.Return(
   2212         m.Int64Sub(m.Parameter(0),
   2213                    m.Int64Mul(m.Int64Constant((1L << k) + 1), m.Parameter(1))));
   2214     Stream s = m.Build();
   2215     ASSERT_EQ(2U, s.size());
   2216     EXPECT_EQ(kArm64Add, s[0]->arch_opcode());
   2217     EXPECT_EQ(kArm64Sub, s[1]->arch_opcode());
   2218     EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
   2219     ASSERT_EQ(3U, s[0]->InputCount());
   2220     EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
   2221     EXPECT_EQ(k, s.ToInt64(s[0]->InputAt(2)));
   2222     EXPECT_EQ(1U, s[0]->OutputCount());
   2223   }
   2224 }
   2225 
   2226 
   2227 // -----------------------------------------------------------------------------
   2228 // Floating point instructions.
   2229 
   2230 typedef InstructionSelectorTestWithParam<MachInst2>
   2231     InstructionSelectorFPArithTest;
   2232 
   2233 
   2234 TEST_P(InstructionSelectorFPArithTest, Parameter) {
   2235   const MachInst2 fpa = GetParam();
   2236   StreamBuilder m(this, fpa.machine_type, fpa.machine_type, fpa.machine_type);
   2237   m.Return((m.*fpa.constructor)(m.Parameter(0), m.Parameter(1)));
   2238   Stream s = m.Build();
   2239   ASSERT_EQ(1U, s.size());
   2240   EXPECT_EQ(fpa.arch_opcode, s[0]->arch_opcode());
   2241   EXPECT_EQ(2U, s[0]->InputCount());
   2242   EXPECT_EQ(1U, s[0]->OutputCount());
   2243 }
   2244 
   2245 
   2246 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorFPArithTest,
   2247                         ::testing::ValuesIn(kFPArithInstructions));
   2248 
   2249 
   2250 typedef InstructionSelectorTestWithParam<FPCmp> InstructionSelectorFPCmpTest;
   2251 
   2252 
   2253 TEST_P(InstructionSelectorFPCmpTest, Parameter) {
   2254   const FPCmp cmp = GetParam();
   2255   StreamBuilder m(this, MachineType::Int32(), cmp.mi.machine_type,
   2256                   cmp.mi.machine_type);
   2257   m.Return((m.*cmp.mi.constructor)(m.Parameter(0), m.Parameter(1)));
   2258   Stream s = m.Build();
   2259   ASSERT_EQ(1U, s.size());
   2260   EXPECT_EQ(cmp.mi.arch_opcode, s[0]->arch_opcode());
   2261   EXPECT_EQ(2U, s[0]->InputCount());
   2262   EXPECT_EQ(1U, s[0]->OutputCount());
   2263   EXPECT_EQ(kFlags_set, s[0]->flags_mode());
   2264   EXPECT_EQ(cmp.cond, s[0]->flags_condition());
   2265 }
   2266 
   2267 
   2268 TEST_P(InstructionSelectorFPCmpTest, WithImmediateZeroOnRight) {
   2269   const FPCmp cmp = GetParam();
   2270   StreamBuilder m(this, MachineType::Int32(), cmp.mi.machine_type);
   2271   if (cmp.mi.machine_type == MachineType::Float64()) {
   2272     m.Return((m.*cmp.mi.constructor)(m.Parameter(0), m.Float64Constant(0.0)));
   2273   } else {
   2274     m.Return((m.*cmp.mi.constructor)(m.Parameter(0), m.Float32Constant(0.0f)));
   2275   }
   2276   Stream s = m.Build();
   2277   ASSERT_EQ(1U, s.size());
   2278   EXPECT_EQ(cmp.mi.arch_opcode, s[0]->arch_opcode());
   2279   EXPECT_EQ(2U, s[0]->InputCount());
   2280   EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
   2281   EXPECT_EQ(1U, s[0]->OutputCount());
   2282   EXPECT_EQ(kFlags_set, s[0]->flags_mode());
   2283   EXPECT_EQ(cmp.cond, s[0]->flags_condition());
   2284 }
   2285 
   2286 
   2287 TEST_P(InstructionSelectorFPCmpTest, WithImmediateZeroOnLeft) {
   2288   const FPCmp cmp = GetParam();
   2289   StreamBuilder m(this, MachineType::Int32(), cmp.mi.machine_type);
   2290   if (cmp.mi.machine_type == MachineType::Float64()) {
   2291     m.Return((m.*cmp.mi.constructor)(m.Float64Constant(0.0), m.Parameter(0)));
   2292   } else {
   2293     m.Return((m.*cmp.mi.constructor)(m.Float32Constant(0.0f), m.Parameter(0)));
   2294   }
   2295   Stream s = m.Build();
   2296   ASSERT_EQ(1U, s.size());
   2297   EXPECT_EQ(cmp.mi.arch_opcode, s[0]->arch_opcode());
   2298   EXPECT_EQ(2U, s[0]->InputCount());
   2299   EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
   2300   EXPECT_EQ(1U, s[0]->OutputCount());
   2301   EXPECT_EQ(kFlags_set, s[0]->flags_mode());
   2302   EXPECT_EQ(cmp.commuted_cond, s[0]->flags_condition());
   2303 }
   2304 
   2305 
   2306 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorFPCmpTest,
   2307                         ::testing::ValuesIn(kFPCmpInstructions));
   2308 
   2309 
   2310 // -----------------------------------------------------------------------------
   2311 // Conversions.
   2312 
   2313 typedef InstructionSelectorTestWithParam<Conversion>
   2314     InstructionSelectorConversionTest;
   2315 
   2316 
   2317 TEST_P(InstructionSelectorConversionTest, Parameter) {
   2318   const Conversion conv = GetParam();
   2319   StreamBuilder m(this, conv.mi.machine_type, conv.src_machine_type);
   2320   m.Return((m.*conv.mi.constructor)(m.Parameter(0)));
   2321   Stream s = m.Build();
   2322   ASSERT_EQ(1U, s.size());
   2323   EXPECT_EQ(conv.mi.arch_opcode, s[0]->arch_opcode());
   2324   EXPECT_EQ(1U, s[0]->InputCount());
   2325   EXPECT_EQ(1U, s[0]->OutputCount());
   2326 }
   2327 
   2328 
   2329 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
   2330                         InstructionSelectorConversionTest,
   2331                         ::testing::ValuesIn(kConversionInstructions));
   2332 
   2333 typedef InstructionSelectorTestWithParam<MachInst2>
   2334     InstructionSelectorElidedChangeUint32ToUint64Test;
   2335 
   2336 TEST_P(InstructionSelectorElidedChangeUint32ToUint64Test, Parameter) {
   2337   const MachInst2 binop = GetParam();
   2338   StreamBuilder m(this, MachineType::Uint64(), binop.machine_type,
   2339                   binop.machine_type);
   2340   m.Return(m.ChangeUint32ToUint64(
   2341       (m.*binop.constructor)(m.Parameter(0), m.Parameter(1))));
   2342   Stream s = m.Build();
   2343   // Make sure the `ChangeUint32ToUint64` node turned into a no-op.
   2344   ASSERT_EQ(1U, s.size());
   2345   EXPECT_EQ(binop.arch_opcode, s[0]->arch_opcode());
   2346   EXPECT_EQ(2U, s[0]->InputCount());
   2347   EXPECT_EQ(1U, s[0]->OutputCount());
   2348 }
   2349 
   2350 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
   2351                         InstructionSelectorElidedChangeUint32ToUint64Test,
   2352                         ::testing::ValuesIn(kCanElideChangeUint32ToUint64));
   2353 
   2354 TEST_F(InstructionSelectorTest, ChangeUint32ToUint64AfterLoad) {
   2355   // For each case, make sure the `ChangeUint32ToUint64` node turned into a
   2356   // no-op.
   2357 
   2358   // Ldrb
   2359   {
   2360     StreamBuilder m(this, MachineType::Uint64(), MachineType::Pointer(),
   2361                     MachineType::Int32());
   2362     m.Return(m.ChangeUint32ToUint64(
   2363         m.Load(MachineType::Uint8(), m.Parameter(0), m.Parameter(1))));
   2364     Stream s = m.Build();
   2365     ASSERT_EQ(1U, s.size());
   2366     EXPECT_EQ(kArm64Ldrb, s[0]->arch_opcode());
   2367     EXPECT_EQ(kMode_MRR, s[0]->addressing_mode());
   2368     EXPECT_EQ(2U, s[0]->InputCount());
   2369     EXPECT_EQ(1U, s[0]->OutputCount());
   2370   }
   2371   // Ldrh
   2372   {
   2373     StreamBuilder m(this, MachineType::Uint64(), MachineType::Pointer(),
   2374                     MachineType::Int32());
   2375     m.Return(m.ChangeUint32ToUint64(
   2376         m.Load(MachineType::Uint16(), m.Parameter(0), m.Parameter(1))));
   2377     Stream s = m.Build();
   2378     ASSERT_EQ(1U, s.size());
   2379     EXPECT_EQ(kArm64Ldrh, s[0]->arch_opcode());
   2380     EXPECT_EQ(kMode_MRR, s[0]->addressing_mode());
   2381     EXPECT_EQ(2U, s[0]->InputCount());
   2382     EXPECT_EQ(1U, s[0]->OutputCount());
   2383   }
   2384   // LdrW
   2385   {
   2386     StreamBuilder m(this, MachineType::Uint64(), MachineType::Pointer(),
   2387                     MachineType::Int32());
   2388     m.Return(m.ChangeUint32ToUint64(
   2389         m.Load(MachineType::Uint32(), m.Parameter(0), m.Parameter(1))));
   2390     Stream s = m.Build();
   2391     ASSERT_EQ(1U, s.size());
   2392     EXPECT_EQ(kArm64LdrW, s[0]->arch_opcode());
   2393     EXPECT_EQ(kMode_MRR, s[0]->addressing_mode());
   2394     EXPECT_EQ(2U, s[0]->InputCount());
   2395     EXPECT_EQ(1U, s[0]->OutputCount());
   2396   }
   2397 }
   2398 
   2399 // -----------------------------------------------------------------------------
   2400 // Memory access instructions.
   2401 
   2402 
   2403 namespace {
   2404 
   2405 struct MemoryAccess {
   2406   MachineType type;
   2407   ArchOpcode ldr_opcode;
   2408   ArchOpcode str_opcode;
   2409   const int32_t immediates[20];
   2410 };
   2411 
   2412 
   2413 std::ostream& operator<<(std::ostream& os, const MemoryAccess& memacc) {
   2414   return os << memacc.type;
   2415 }
   2416 
   2417 }  // namespace
   2418 
   2419 
   2420 static const MemoryAccess kMemoryAccesses[] = {
   2421     {MachineType::Int8(),
   2422      kArm64Ldrsb,
   2423      kArm64Strb,
   2424      {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 257, 258, 1000, 1001, 2121,
   2425       2442, 4093, 4094, 4095}},
   2426     {MachineType::Uint8(),
   2427      kArm64Ldrb,
   2428      kArm64Strb,
   2429      {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 257, 258, 1000, 1001, 2121,
   2430       2442, 4093, 4094, 4095}},
   2431     {MachineType::Int16(),
   2432      kArm64Ldrsh,
   2433      kArm64Strh,
   2434      {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 258, 260, 4096, 4098, 4100,
   2435       4242, 6786, 8188, 8190}},
   2436     {MachineType::Uint16(),
   2437      kArm64Ldrh,
   2438      kArm64Strh,
   2439      {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 258, 260, 4096, 4098, 4100,
   2440       4242, 6786, 8188, 8190}},
   2441     {MachineType::Int32(),
   2442      kArm64LdrW,
   2443      kArm64StrW,
   2444      {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 260, 4096, 4100, 8192, 8196,
   2445       3276, 3280, 16376, 16380}},
   2446     {MachineType::Uint32(),
   2447      kArm64LdrW,
   2448      kArm64StrW,
   2449      {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 260, 4096, 4100, 8192, 8196,
   2450       3276, 3280, 16376, 16380}},
   2451     {MachineType::Int64(),
   2452      kArm64Ldr,
   2453      kArm64Str,
   2454      {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 264, 4096, 4104, 8192, 8200,
   2455       16384, 16392, 32752, 32760}},
   2456     {MachineType::Uint64(),
   2457      kArm64Ldr,
   2458      kArm64Str,
   2459      {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 264, 4096, 4104, 8192, 8200,
   2460       16384, 16392, 32752, 32760}},
   2461     {MachineType::Float32(),
   2462      kArm64LdrS,
   2463      kArm64StrS,
   2464      {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 260, 4096, 4100, 8192, 8196,
   2465       3276, 3280, 16376, 16380}},
   2466     {MachineType::Float64(),
   2467      kArm64LdrD,
   2468      kArm64StrD,
   2469      {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 264, 4096, 4104, 8192, 8200,
   2470       16384, 16392, 32752, 32760}}};
   2471 
   2472 
   2473 typedef InstructionSelectorTestWithParam<MemoryAccess>
   2474     InstructionSelectorMemoryAccessTest;
   2475 
   2476 
   2477 TEST_P(InstructionSelectorMemoryAccessTest, LoadWithParameters) {
   2478   const MemoryAccess memacc = GetParam();
   2479   StreamBuilder m(this, memacc.type, MachineType::Pointer(),
   2480                   MachineType::Int32());
   2481   m.Return(m.Load(memacc.type, m.Parameter(0), m.Parameter(1)));
   2482   Stream s = m.Build();
   2483   ASSERT_EQ(1U, s.size());
   2484   EXPECT_EQ(memacc.ldr_opcode, s[0]->arch_opcode());
   2485   EXPECT_EQ(kMode_MRR, s[0]->addressing_mode());
   2486   EXPECT_EQ(2U, s[0]->InputCount());
   2487   EXPECT_EQ(1U, s[0]->OutputCount());
   2488 }
   2489 
   2490 
   2491 TEST_P(InstructionSelectorMemoryAccessTest, LoadWithImmediateIndex) {
   2492   const MemoryAccess memacc = GetParam();
   2493   TRACED_FOREACH(int32_t, index, memacc.immediates) {
   2494     StreamBuilder m(this, memacc.type, MachineType::Pointer());
   2495     m.Return(m.Load(memacc.type, m.Parameter(0), m.Int32Constant(index)));
   2496     Stream s = m.Build();
   2497     ASSERT_EQ(1U, s.size());
   2498     EXPECT_EQ(memacc.ldr_opcode, s[0]->arch_opcode());
   2499     EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
   2500     EXPECT_EQ(2U, s[0]->InputCount());
   2501     ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
   2502     EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1)));
   2503     ASSERT_EQ(1U, s[0]->OutputCount());
   2504   }
   2505 }
   2506 
   2507 
   2508 TEST_P(InstructionSelectorMemoryAccessTest, StoreWithParameters) {
   2509   const MemoryAccess memacc = GetParam();
   2510   StreamBuilder m(this, MachineType::Int32(), MachineType::Pointer(),
   2511                   MachineType::Int32(), memacc.type);
   2512   m.Store(memacc.type.representation(), m.Parameter(0), m.Parameter(1),
   2513           m.Parameter(2), kNoWriteBarrier);
   2514   m.Return(m.Int32Constant(0));
   2515   Stream s = m.Build();
   2516   ASSERT_EQ(1U, s.size());
   2517   EXPECT_EQ(memacc.str_opcode, s[0]->arch_opcode());
   2518   EXPECT_EQ(kMode_MRR, s[0]->addressing_mode());
   2519   EXPECT_EQ(3U, s[0]->InputCount());
   2520   EXPECT_EQ(0U, s[0]->OutputCount());
   2521 }
   2522 
   2523 
   2524 TEST_P(InstructionSelectorMemoryAccessTest, StoreWithImmediateIndex) {
   2525   const MemoryAccess memacc = GetParam();
   2526   TRACED_FOREACH(int32_t, index, memacc.immediates) {
   2527     StreamBuilder m(this, MachineType::Int32(), MachineType::Pointer(),
   2528                     memacc.type);
   2529     m.Store(memacc.type.representation(), m.Parameter(0),
   2530             m.Int32Constant(index), m.Parameter(1), kNoWriteBarrier);
   2531     m.Return(m.Int32Constant(0));
   2532     Stream s = m.Build();
   2533     ASSERT_EQ(1U, s.size());
   2534     EXPECT_EQ(memacc.str_opcode, s[0]->arch_opcode());
   2535     EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
   2536     ASSERT_EQ(3U, s[0]->InputCount());
   2537     ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(2)->kind());
   2538     EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(2)));
   2539     EXPECT_EQ(0U, s[0]->OutputCount());
   2540   }
   2541 }
   2542 
   2543 TEST_P(InstructionSelectorMemoryAccessTest, StoreZero) {
   2544   const MemoryAccess memacc = GetParam();
   2545   TRACED_FOREACH(int32_t, index, memacc.immediates) {
   2546     StreamBuilder m(this, MachineType::Int32(), MachineType::Pointer());
   2547     m.Store(memacc.type.representation(), m.Parameter(0),
   2548             m.Int32Constant(index), m.Int32Constant(0), kNoWriteBarrier);
   2549     m.Return(m.Int32Constant(0));
   2550     Stream s = m.Build();
   2551     ASSERT_EQ(1U, s.size());
   2552     EXPECT_EQ(memacc.str_opcode, s[0]->arch_opcode());
   2553     EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
   2554     ASSERT_EQ(3U, s[0]->InputCount());
   2555     ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(2)->kind());
   2556     EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(2)));
   2557     ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(0)->kind());
   2558     EXPECT_EQ(0, s.ToInt64(s[0]->InputAt(0)));
   2559     EXPECT_EQ(0U, s[0]->OutputCount());
   2560   }
   2561 }
   2562 
   2563 TEST_P(InstructionSelectorMemoryAccessTest, LoadWithShiftedIndex) {
   2564   const MemoryAccess memacc = GetParam();
   2565   TRACED_FORRANGE(int, immediate_shift, 0, 4) {
   2566     // 32 bit shift
   2567     {
   2568       StreamBuilder m(this, memacc.type, MachineType::Pointer(),
   2569                       MachineType::Int32());
   2570       Node* const index =
   2571           m.Word32Shl(m.Parameter(1), m.Int32Constant(immediate_shift));
   2572       m.Return(m.Load(memacc.type, m.Parameter(0), index));
   2573       Stream s = m.Build();
   2574       if (immediate_shift == ElementSizeLog2Of(memacc.type.representation())) {
   2575         ASSERT_EQ(1U, s.size());
   2576         EXPECT_EQ(memacc.ldr_opcode, s[0]->arch_opcode());
   2577         EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
   2578         EXPECT_EQ(3U, s[0]->InputCount());
   2579         EXPECT_EQ(1U, s[0]->OutputCount());
   2580       } else {
   2581         // Make sure we haven't merged the shift into the load instruction.
   2582         ASSERT_NE(1U, s.size());
   2583         EXPECT_NE(memacc.ldr_opcode, s[0]->arch_opcode());
   2584         EXPECT_NE(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
   2585       }
   2586     }
   2587     // 64 bit shift
   2588     {
   2589       StreamBuilder m(this, memacc.type, MachineType::Pointer(),
   2590                       MachineType::Int64());
   2591       Node* const index =
   2592           m.Word64Shl(m.Parameter(1), m.Int64Constant(immediate_shift));
   2593       m.Return(m.Load(memacc.type, m.Parameter(0), index));
   2594       Stream s = m.Build();
   2595       if (immediate_shift == ElementSizeLog2Of(memacc.type.representation())) {
   2596         ASSERT_EQ(1U, s.size());
   2597         EXPECT_EQ(memacc.ldr_opcode, s[0]->arch_opcode());
   2598         EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
   2599         EXPECT_EQ(3U, s[0]->InputCount());
   2600         EXPECT_EQ(1U, s[0]->OutputCount());
   2601       } else {
   2602         // Make sure we haven't merged the shift into the load instruction.
   2603         ASSERT_NE(1U, s.size());
   2604         EXPECT_NE(memacc.ldr_opcode, s[0]->arch_opcode());
   2605         EXPECT_NE(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
   2606       }
   2607     }
   2608   }
   2609 }
   2610 
   2611 TEST_P(InstructionSelectorMemoryAccessTest, StoreWithShiftedIndex) {
   2612   const MemoryAccess memacc = GetParam();
   2613   TRACED_FORRANGE(int, immediate_shift, 0, 4) {
   2614     // 32 bit shift
   2615     {
   2616       StreamBuilder m(this, MachineType::Int32(), MachineType::Pointer(),
   2617                       MachineType::Int32(), memacc.type);
   2618       Node* const index =
   2619           m.Word32Shl(m.Parameter(1), m.Int32Constant(immediate_shift));
   2620       m.Store(memacc.type.representation(), m.Parameter(0), index,
   2621               m.Parameter(2), kNoWriteBarrier);
   2622       m.Return(m.Int32Constant(0));
   2623       Stream s = m.Build();
   2624       if (immediate_shift == ElementSizeLog2Of(memacc.type.representation())) {
   2625         ASSERT_EQ(1U, s.size());
   2626         EXPECT_EQ(memacc.str_opcode, s[0]->arch_opcode());
   2627         EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
   2628         EXPECT_EQ(4U, s[0]->InputCount());
   2629         EXPECT_EQ(0U, s[0]->OutputCount());
   2630       } else {
   2631         // Make sure we haven't merged the shift into the store instruction.
   2632         ASSERT_NE(1U, s.size());
   2633         EXPECT_NE(memacc.str_opcode, s[0]->arch_opcode());
   2634         EXPECT_NE(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
   2635       }
   2636     }
   2637     // 64 bit shift
   2638     {
   2639       StreamBuilder m(this, MachineType::Int64(), MachineType::Pointer(),
   2640                       MachineType::Int64(), memacc.type);
   2641       Node* const index =
   2642           m.Word64Shl(m.Parameter(1), m.Int64Constant(immediate_shift));
   2643       m.Store(memacc.type.representation(), m.Parameter(0), index,
   2644               m.Parameter(2), kNoWriteBarrier);
   2645       m.Return(m.Int64Constant(0));
   2646       Stream s = m.Build();
   2647       if (immediate_shift == ElementSizeLog2Of(memacc.type.representation())) {
   2648         ASSERT_EQ(1U, s.size());
   2649         EXPECT_EQ(memacc.str_opcode, s[0]->arch_opcode());
   2650         EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
   2651         EXPECT_EQ(4U, s[0]->InputCount());
   2652         EXPECT_EQ(0U, s[0]->OutputCount());
   2653       } else {
   2654         // Make sure we haven't merged the shift into the store instruction.
   2655         ASSERT_NE(1U, s.size());
   2656         EXPECT_NE(memacc.str_opcode, s[0]->arch_opcode());
   2657         EXPECT_NE(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
   2658       }
   2659     }
   2660   }
   2661 }
   2662 
   2663 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
   2664                         InstructionSelectorMemoryAccessTest,
   2665                         ::testing::ValuesIn(kMemoryAccesses));
   2666 
   2667 
   2668 // -----------------------------------------------------------------------------
   2669 // Comparison instructions.
   2670 
   2671 static const MachInst2 kComparisonInstructions[] = {
   2672     {&RawMachineAssembler::Word32Equal, "Word32Equal", kArm64Cmp32,
   2673      MachineType::Int32()},
   2674     {&RawMachineAssembler::Word64Equal, "Word64Equal", kArm64Cmp,
   2675      MachineType::Int64()},
   2676 };
   2677 
   2678 
   2679 typedef InstructionSelectorTestWithParam<MachInst2>
   2680     InstructionSelectorComparisonTest;
   2681 
   2682 
   2683 TEST_P(InstructionSelectorComparisonTest, WithParameters) {
   2684   const MachInst2 cmp = GetParam();
   2685   const MachineType type = cmp.machine_type;
   2686   StreamBuilder m(this, type, type, type);
   2687   m.Return((m.*cmp.constructor)(m.Parameter(0), m.Parameter(1)));
   2688   Stream s = m.Build();
   2689   ASSERT_EQ(1U, s.size());
   2690   EXPECT_EQ(cmp.arch_opcode, s[0]->arch_opcode());
   2691   EXPECT_EQ(2U, s[0]->InputCount());
   2692   EXPECT_EQ(1U, s[0]->OutputCount());
   2693   EXPECT_EQ(kFlags_set, s[0]->flags_mode());
   2694   EXPECT_EQ(kEqual, s[0]->flags_condition());
   2695 }
   2696 
   2697 
   2698 TEST_P(InstructionSelectorComparisonTest, WithImmediate) {
   2699   const MachInst2 cmp = GetParam();
   2700   const MachineType type = cmp.machine_type;
   2701   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
   2702     // Compare with 0 are turned into tst instruction.
   2703     if (imm == 0) continue;
   2704     StreamBuilder m(this, type, type);
   2705     m.Return((m.*cmp.constructor)(m.Parameter(0), BuildConstant(m, type, imm)));
   2706     Stream s = m.Build();
   2707     ASSERT_EQ(1U, s.size());
   2708     EXPECT_EQ(cmp.arch_opcode, s[0]->arch_opcode());
   2709     ASSERT_EQ(2U, s[0]->InputCount());
   2710     ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
   2711     EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(1)));
   2712     EXPECT_EQ(1U, s[0]->OutputCount());
   2713     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
   2714     EXPECT_EQ(kEqual, s[0]->flags_condition());
   2715   }
   2716   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
   2717     // Compare with 0 are turned into tst instruction.
   2718     if (imm == 0) continue;
   2719     StreamBuilder m(this, type, type);
   2720     m.Return((m.*cmp.constructor)(BuildConstant(m, type, imm), m.Parameter(0)));
   2721     Stream s = m.Build();
   2722     ASSERT_EQ(1U, s.size());
   2723     EXPECT_EQ(cmp.arch_opcode, s[0]->arch_opcode());
   2724     ASSERT_EQ(2U, s[0]->InputCount());
   2725     ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
   2726     EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(1)));
   2727     EXPECT_EQ(1U, s[0]->OutputCount());
   2728     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
   2729     EXPECT_EQ(kEqual, s[0]->flags_condition());
   2730   }
   2731 }
   2732 
   2733 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
   2734                         InstructionSelectorComparisonTest,
   2735                         ::testing::ValuesIn(kComparisonInstructions));
   2736 
   2737 
   2738 TEST_F(InstructionSelectorTest, Word32EqualWithZero) {
   2739   {
   2740     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
   2741     m.Return(m.Word32Equal(m.Parameter(0), m.Int32Constant(0)));
   2742     Stream s = m.Build();
   2743     ASSERT_EQ(1U, s.size());
   2744     EXPECT_EQ(kArm64Tst32, s[0]->arch_opcode());
   2745     ASSERT_EQ(2U, s[0]->InputCount());
   2746     EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
   2747     EXPECT_EQ(1U, s[0]->OutputCount());
   2748     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
   2749     EXPECT_EQ(kEqual, s[0]->flags_condition());
   2750   }
   2751   {
   2752     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
   2753     m.Return(m.Word32Equal(m.Int32Constant(0), m.Parameter(0)));
   2754     Stream s = m.Build();
   2755     ASSERT_EQ(1U, s.size());
   2756     EXPECT_EQ(kArm64Tst32, s[0]->arch_opcode());
   2757     ASSERT_EQ(2U, s[0]->InputCount());
   2758     EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
   2759     EXPECT_EQ(1U, s[0]->OutputCount());
   2760     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
   2761     EXPECT_EQ(kEqual, s[0]->flags_condition());
   2762   }
   2763 }
   2764 
   2765 
   2766 TEST_F(InstructionSelectorTest, Word64EqualWithZero) {
   2767   {
   2768     StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
   2769     m.Return(m.Word64Equal(m.Parameter(0), m.Int64Constant(0)));
   2770     Stream s = m.Build();
   2771     ASSERT_EQ(1U, s.size());
   2772     EXPECT_EQ(kArm64Tst, s[0]->arch_opcode());
   2773     ASSERT_EQ(2U, s[0]->InputCount());
   2774     EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
   2775     EXPECT_EQ(1U, s[0]->OutputCount());
   2776     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
   2777     EXPECT_EQ(kEqual, s[0]->flags_condition());
   2778   }
   2779   {
   2780     StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
   2781     m.Return(m.Word64Equal(m.Int64Constant(0), m.Parameter(0)));
   2782     Stream s = m.Build();
   2783     ASSERT_EQ(1U, s.size());
   2784     EXPECT_EQ(kArm64Tst, s[0]->arch_opcode());
   2785     ASSERT_EQ(2U, s[0]->InputCount());
   2786     EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
   2787     EXPECT_EQ(1U, s[0]->OutputCount());
   2788     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
   2789     EXPECT_EQ(kEqual, s[0]->flags_condition());
   2790   }
   2791 }
   2792 
   2793 
   2794 TEST_F(InstructionSelectorTest, Word32EqualWithWord32Shift) {
   2795   TRACED_FOREACH(Shift, shift, kShiftInstructions) {
   2796     // Skip non 32-bit shifts or ror operations.
   2797     if (shift.mi.machine_type != MachineType::Int32() ||
   2798         shift.mi.arch_opcode == kArm64Ror32) {
   2799       continue;
   2800     }
   2801 
   2802     TRACED_FORRANGE(int32_t, imm, -32, 63) {
   2803       StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
   2804                       MachineType::Int32());
   2805       Node* const p0 = m.Parameter(0);
   2806       Node* const p1 = m.Parameter(1);
   2807       Node* r = (m.*shift.mi.constructor)(p1, m.Int32Constant(imm));
   2808       m.Return(m.Word32Equal(p0, r));
   2809       Stream s = m.Build();
   2810       ASSERT_EQ(1U, s.size());
   2811       EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode());
   2812       EXPECT_EQ(shift.mode, s[0]->addressing_mode());
   2813       ASSERT_EQ(3U, s[0]->InputCount());
   2814       EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
   2815       EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
   2816       EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2)));
   2817       ASSERT_EQ(1U, s[0]->OutputCount());
   2818     }
   2819     TRACED_FORRANGE(int32_t, imm, -32, 63) {
   2820       StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
   2821                       MachineType::Int32());
   2822       Node* const p0 = m.Parameter(0);
   2823       Node* const p1 = m.Parameter(1);
   2824       Node* r = (m.*shift.mi.constructor)(p1, m.Int32Constant(imm));
   2825       m.Return(m.Word32Equal(r, p0));
   2826       Stream s = m.Build();
   2827       ASSERT_EQ(1U, s.size());
   2828       EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode());
   2829       EXPECT_EQ(shift.mode, s[0]->addressing_mode());
   2830       ASSERT_EQ(3U, s[0]->InputCount());
   2831       EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
   2832       EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
   2833       EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2)));
   2834       ASSERT_EQ(1U, s[0]->OutputCount());
   2835     }
   2836   }
   2837 }
   2838 
   2839 
   2840 TEST_F(InstructionSelectorTest, Word32EqualWithUnsignedExtendByte) {
   2841   {
   2842     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
   2843                     MachineType::Int32());
   2844     Node* const p0 = m.Parameter(0);
   2845     Node* const p1 = m.Parameter(1);
   2846     Node* r = m.Word32And(p1, m.Int32Constant(0xff));
   2847     m.Return(m.Word32Equal(p0, r));
   2848     Stream s = m.Build();
   2849     ASSERT_EQ(1U, s.size());
   2850     EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode());
   2851     EXPECT_EQ(kMode_Operand2_R_UXTB, s[0]->addressing_mode());
   2852     ASSERT_EQ(2U, s[0]->InputCount());
   2853     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
   2854     EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
   2855     ASSERT_EQ(1U, s[0]->OutputCount());
   2856   }
   2857   {
   2858     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
   2859                     MachineType::Int32());
   2860     Node* const p0 = m.Parameter(0);
   2861     Node* const p1 = m.Parameter(1);
   2862     Node* r = m.Word32And(p1, m.Int32Constant(0xff));
   2863     m.Return(m.Word32Equal(r, p0));
   2864     Stream s = m.Build();
   2865     ASSERT_EQ(1U, s.size());
   2866     EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode());
   2867     EXPECT_EQ(kMode_Operand2_R_UXTB, s[0]->addressing_mode());
   2868     ASSERT_EQ(2U, s[0]->InputCount());
   2869     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
   2870     EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
   2871     ASSERT_EQ(1U, s[0]->OutputCount());
   2872   }
   2873 }
   2874 
   2875 
   2876 TEST_F(InstructionSelectorTest, Word32EqualWithUnsignedExtendHalfword) {
   2877   {
   2878     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
   2879                     MachineType::Int32());
   2880     Node* const p0 = m.Parameter(0);
   2881     Node* const p1 = m.Parameter(1);
   2882     Node* r = m.Word32And(p1, m.Int32Constant(0xffff));
   2883     m.Return(m.Word32Equal(p0, r));
   2884     Stream s = m.Build();
   2885     ASSERT_EQ(1U, s.size());
   2886     EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode());
   2887     EXPECT_EQ(kMode_Operand2_R_UXTH, s[0]->addressing_mode());
   2888     ASSERT_EQ(2U, s[0]->InputCount());
   2889     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
   2890     EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
   2891     ASSERT_EQ(1U, s[0]->OutputCount());
   2892   }
   2893   {
   2894     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
   2895                     MachineType::Int32());
   2896     Node* const p0 = m.Parameter(0);
   2897     Node* const p1 = m.Parameter(1);
   2898     Node* r = m.Word32And(p1, m.Int32Constant(0xffff));
   2899     m.Return(m.Word32Equal(r, p0));
   2900     Stream s = m.Build();
   2901     ASSERT_EQ(1U, s.size());
   2902     EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode());
   2903     EXPECT_EQ(kMode_Operand2_R_UXTH, s[0]->addressing_mode());
   2904     ASSERT_EQ(2U, s[0]->InputCount());
   2905     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
   2906     EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
   2907     ASSERT_EQ(1U, s[0]->OutputCount());
   2908   }
   2909 }
   2910 
   2911 
   2912 TEST_F(InstructionSelectorTest, Word32EqualWithSignedExtendByte) {
   2913   {
   2914     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
   2915                     MachineType::Int32());
   2916     Node* const p0 = m.Parameter(0);
   2917     Node* const p1 = m.Parameter(1);
   2918     Node* r =
   2919         m.Word32Sar(m.Word32Shl(p1, m.Int32Constant(24)), m.Int32Constant(24));
   2920     m.Return(m.Word32Equal(p0, r));
   2921     Stream s = m.Build();
   2922     ASSERT_EQ(1U, s.size());
   2923     EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode());
   2924     EXPECT_EQ(kMode_Operand2_R_SXTB, s[0]->addressing_mode());
   2925     ASSERT_EQ(2U, s[0]->InputCount());
   2926     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
   2927     EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
   2928     ASSERT_EQ(1U, s[0]->OutputCount());
   2929   }
   2930   {
   2931     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
   2932                     MachineType::Int32());
   2933     Node* const p0 = m.Parameter(0);
   2934     Node* const p1 = m.Parameter(1);
   2935     Node* r =
   2936         m.Word32Sar(m.Word32Shl(p1, m.Int32Constant(24)), m.Int32Constant(24));
   2937     m.Return(m.Word32Equal(r, p0));
   2938     Stream s = m.Build();
   2939     ASSERT_EQ(1U, s.size());
   2940     EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode());
   2941     EXPECT_EQ(kMode_Operand2_R_SXTB, s[0]->addressing_mode());
   2942     ASSERT_EQ(2U, s[0]->InputCount());
   2943     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
   2944     EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
   2945     ASSERT_EQ(1U, s[0]->OutputCount());
   2946   }
   2947 }
   2948 
   2949 
   2950 TEST_F(InstructionSelectorTest, Word32EqualWithSignedExtendHalfword) {
   2951   {
   2952     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
   2953                     MachineType::Int32());
   2954     Node* const p0 = m.Parameter(0);
   2955     Node* const p1 = m.Parameter(1);
   2956     Node* r =
   2957         m.Word32Sar(m.Word32Shl(p1, m.Int32Constant(16)), m.Int32Constant(16));
   2958     m.Return(m.Word32Equal(p0, r));
   2959     Stream s = m.Build();
   2960     ASSERT_EQ(1U, s.size());
   2961     EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode());
   2962     EXPECT_EQ(kMode_Operand2_R_SXTH, s[0]->addressing_mode());
   2963     ASSERT_EQ(2U, s[0]->InputCount());
   2964     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
   2965     EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
   2966     ASSERT_EQ(1U, s[0]->OutputCount());
   2967   }
   2968   {
   2969     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
   2970                     MachineType::Int32());
   2971     Node* const p0 = m.Parameter(0);
   2972     Node* const p1 = m.Parameter(1);
   2973     Node* r =
   2974         m.Word32Sar(m.Word32Shl(p1, m.Int32Constant(16)), m.Int32Constant(16));
   2975     m.Return(m.Word32Equal(r, p0));
   2976     Stream s = m.Build();
   2977     ASSERT_EQ(1U, s.size());
   2978     EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode());
   2979     EXPECT_EQ(kMode_Operand2_R_SXTH, s[0]->addressing_mode());
   2980     ASSERT_EQ(2U, s[0]->InputCount());
   2981     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
   2982     EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
   2983     ASSERT_EQ(1U, s[0]->OutputCount());
   2984   }
   2985 }
   2986 
   2987 
   2988 TEST_F(InstructionSelectorTest, Word32EqualZeroWithWord32Equal) {
   2989   {
   2990     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
   2991                     MachineType::Int32());
   2992     Node* const p0 = m.Parameter(0);
   2993     Node* const p1 = m.Parameter(1);
   2994     m.Return(m.Word32Equal(m.Word32Equal(p0, p1), m.Int32Constant(0)));
   2995     Stream s = m.Build();
   2996     ASSERT_EQ(1U, s.size());
   2997     EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode());
   2998     ASSERT_EQ(2U, s[0]->InputCount());
   2999     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
   3000     EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
   3001     EXPECT_EQ(1U, s[0]->OutputCount());
   3002     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
   3003     EXPECT_EQ(kNotEqual, s[0]->flags_condition());
   3004   }
   3005   {
   3006     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
   3007                     MachineType::Int32());
   3008     Node* const p0 = m.Parameter(0);
   3009     Node* const p1 = m.Parameter(1);
   3010     m.Return(m.Word32Equal(m.Int32Constant(0), m.Word32Equal(p0, p1)));
   3011     Stream s = m.Build();
   3012     ASSERT_EQ(1U, s.size());
   3013     EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode());
   3014     ASSERT_EQ(2U, s[0]->InputCount());
   3015     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
   3016     EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
   3017     EXPECT_EQ(1U, s[0]->OutputCount());
   3018     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
   3019     EXPECT_EQ(kNotEqual, s[0]->flags_condition());
   3020   }
   3021 }
   3022 
   3023 namespace {
   3024 
   3025 struct IntegerCmp {
   3026   MachInst2 mi;
   3027   FlagsCondition cond;
   3028   FlagsCondition commuted_cond;
   3029 };
   3030 
   3031 
   3032 std::ostream& operator<<(std::ostream& os, const IntegerCmp& cmp) {
   3033   return os << cmp.mi;
   3034 }
   3035 
   3036 
   3037 // ARM64 32-bit integer comparison instructions.
   3038 const IntegerCmp kIntegerCmpInstructions[] = {
   3039     {{&RawMachineAssembler::Word32Equal, "Word32Equal", kArm64Cmp32,
   3040       MachineType::Int32()},
   3041      kEqual,
   3042      kEqual},
   3043     {{&RawMachineAssembler::Int32LessThan, "Int32LessThan", kArm64Cmp32,
   3044       MachineType::Int32()},
   3045      kSignedLessThan,
   3046      kSignedGreaterThan},
   3047     {{&RawMachineAssembler::Int32LessThanOrEqual, "Int32LessThanOrEqual",
   3048       kArm64Cmp32, MachineType::Int32()},
   3049      kSignedLessThanOrEqual,
   3050      kSignedGreaterThanOrEqual},
   3051     {{&RawMachineAssembler::Uint32LessThan, "Uint32LessThan", kArm64Cmp32,
   3052       MachineType::Uint32()},
   3053      kUnsignedLessThan,
   3054      kUnsignedGreaterThan},
   3055     {{&RawMachineAssembler::Uint32LessThanOrEqual, "Uint32LessThanOrEqual",
   3056       kArm64Cmp32, MachineType::Uint32()},
   3057      kUnsignedLessThanOrEqual,
   3058      kUnsignedGreaterThanOrEqual}};
   3059 
   3060 }  // namespace
   3061 
   3062 
   3063 TEST_F(InstructionSelectorTest, Word32CompareNegateWithWord32Shift) {
   3064   TRACED_FOREACH(IntegerCmp, cmp, kIntegerCmpInstructions) {
   3065     TRACED_FOREACH(Shift, shift, kShiftInstructions) {
   3066       // Test 32-bit operations. Ignore ROR shifts, as compare-negate does not
   3067       // support them.
   3068       if (shift.mi.machine_type != MachineType::Int32() ||
   3069           shift.mi.arch_opcode == kArm64Ror32) {
   3070         continue;
   3071       }
   3072 
   3073       TRACED_FORRANGE(int32_t, imm, -32, 63) {
   3074         StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
   3075                         MachineType::Int32());
   3076         Node* const p0 = m.Parameter(0);
   3077         Node* const p1 = m.Parameter(1);
   3078         Node* r = (m.*shift.mi.constructor)(p1, m.Int32Constant(imm));
   3079         m.Return(
   3080             (m.*cmp.mi.constructor)(p0, m.Int32Sub(m.Int32Constant(0), r)));
   3081         Stream s = m.Build();
   3082         ASSERT_EQ(1U, s.size());
   3083         EXPECT_EQ(kArm64Cmn32, s[0]->arch_opcode());
   3084         EXPECT_EQ(3U, s[0]->InputCount());
   3085         EXPECT_EQ(shift.mode, s[0]->addressing_mode());
   3086         EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2)));
   3087         EXPECT_EQ(1U, s[0]->OutputCount());
   3088         EXPECT_EQ(kFlags_set, s[0]->flags_mode());
   3089         EXPECT_EQ(cmp.cond, s[0]->flags_condition());
   3090       }
   3091     }
   3092   }
   3093 }
   3094 
   3095 TEST_F(InstructionSelectorTest, CmpWithImmediateOnLeft) {
   3096   TRACED_FOREACH(IntegerCmp, cmp, kIntegerCmpInstructions) {
   3097     TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
   3098       // kEqual and kNotEqual trigger the cbz/cbnz optimization, which
   3099       // is tested elsewhere.
   3100       if (cmp.cond == kEqual || cmp.cond == kNotEqual) continue;
   3101       StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
   3102       Node* const p0 = m.Parameter(0);
   3103       RawMachineLabel a, b;
   3104       m.Branch((m.*cmp.mi.constructor)(m.Int32Constant(imm), p0), &a, &b);
   3105       m.Bind(&a);
   3106       m.Return(m.Int32Constant(1));
   3107       m.Bind(&b);
   3108       m.Return(m.Int32Constant(0));
   3109       Stream s = m.Build();
   3110       ASSERT_EQ(1U, s.size());
   3111       EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode());
   3112       ASSERT_LE(2U, s[0]->InputCount());
   3113       EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
   3114       EXPECT_EQ(cmp.commuted_cond, s[0]->flags_condition());
   3115       EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
   3116     }
   3117   }
   3118 }
   3119 
   3120 TEST_F(InstructionSelectorTest, CmnWithImmediateOnLeft) {
   3121   TRACED_FOREACH(IntegerCmp, cmp, kIntegerCmpInstructions) {
   3122     TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
   3123       // kEqual and kNotEqual trigger the cbz/cbnz optimization, which
   3124       // is tested elsewhere.
   3125       if (cmp.cond == kEqual || cmp.cond == kNotEqual) continue;
   3126       StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
   3127       Node* sub = m.Int32Sub(m.Int32Constant(0), m.Parameter(0));
   3128       RawMachineLabel a, b;
   3129       m.Branch((m.*cmp.mi.constructor)(m.Int32Constant(imm), sub), &a, &b);
   3130       m.Bind(&a);
   3131       m.Return(m.Int32Constant(1));
   3132       m.Bind(&b);
   3133       m.Return(m.Int32Constant(0));
   3134       Stream s = m.Build();
   3135       ASSERT_EQ(1U, s.size());
   3136       EXPECT_EQ(kArm64Cmn32, s[0]->arch_opcode());
   3137       ASSERT_LE(2U, s[0]->InputCount());
   3138       EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
   3139       EXPECT_EQ(cmp.cond, s[0]->flags_condition());
   3140       EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
   3141     }
   3142   }
   3143 }
   3144 
   3145 TEST_F(InstructionSelectorTest, CmpSignedExtendByteOnLeft) {
   3146   TRACED_FOREACH(IntegerCmp, cmp, kIntegerCmpInstructions) {
   3147     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
   3148                     MachineType::Int32());
   3149     Node* extend = m.Word32Sar(m.Word32Shl(m.Parameter(0), m.Int32Constant(24)),
   3150                                m.Int32Constant(24));
   3151     m.Return((m.*cmp.mi.constructor)(extend, m.Parameter(1)));
   3152     Stream s = m.Build();
   3153     ASSERT_EQ(1U, s.size());
   3154     EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode());
   3155     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
   3156     EXPECT_EQ(cmp.commuted_cond, s[0]->flags_condition());
   3157     EXPECT_EQ(kMode_Operand2_R_SXTB, s[0]->addressing_mode());
   3158   }
   3159 }
   3160 
   3161 TEST_F(InstructionSelectorTest, CmnSignedExtendByteOnLeft) {
   3162   TRACED_FOREACH(IntegerCmp, cmp, kIntegerCmpInstructions) {
   3163     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
   3164                     MachineType::Int32());
   3165     Node* sub = m.Int32Sub(m.Int32Constant(0), m.Parameter(0));
   3166     Node* extend = m.Word32Sar(m.Word32Shl(m.Parameter(0), m.Int32Constant(24)),
   3167                                m.Int32Constant(24));
   3168     m.Return((m.*cmp.mi.constructor)(extend, sub));
   3169     Stream s = m.Build();
   3170     ASSERT_EQ(1U, s.size());
   3171     EXPECT_EQ(kArm64Cmn32, s[0]->arch_opcode());
   3172     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
   3173     EXPECT_EQ(cmp.cond, s[0]->flags_condition());
   3174     EXPECT_EQ(kMode_Operand2_R_SXTB, s[0]->addressing_mode());
   3175   }
   3176 }
   3177 
   3178 TEST_F(InstructionSelectorTest, CmpShiftByImmediateOnLeft) {
   3179   TRACED_FOREACH(IntegerCmp, cmp, kIntegerCmpInstructions) {
   3180     TRACED_FOREACH(Shift, shift, kShiftInstructions) {
   3181       // Only test relevant shifted operands.
   3182       if (shift.mi.machine_type != MachineType::Int32()) continue;
   3183 
   3184       // The available shift operand range is `0 <= imm < 32`, but we also test
   3185       // that immediates outside this range are handled properly (modulo-32).
   3186       TRACED_FORRANGE(int, imm, -32, 63) {
   3187         StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
   3188                         MachineType::Int32());
   3189         m.Return((m.*cmp.mi.constructor)(
   3190             (m.*shift.mi.constructor)(m.Parameter(1), m.Int32Constant(imm)),
   3191             m.Parameter(0)));
   3192         Stream s = m.Build();
   3193         // Cmp does not support ROR shifts.
   3194         if (shift.mi.arch_opcode == kArm64Ror32) {
   3195           ASSERT_EQ(2U, s.size());
   3196           continue;
   3197         }
   3198         ASSERT_EQ(1U, s.size());
   3199         EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode());
   3200         EXPECT_EQ(shift.mode, s[0]->addressing_mode());
   3201         EXPECT_EQ(3U, s[0]->InputCount());
   3202         EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(2)));
   3203         EXPECT_EQ(1U, s[0]->OutputCount());
   3204         EXPECT_EQ(kFlags_set, s[0]->flags_mode());
   3205         EXPECT_EQ(cmp.commuted_cond, s[0]->flags_condition());
   3206       }
   3207     }
   3208   }
   3209 }
   3210 
   3211 TEST_F(InstructionSelectorTest, CmnShiftByImmediateOnLeft) {
   3212   TRACED_FOREACH(IntegerCmp, cmp, kIntegerCmpInstructions) {
   3213     TRACED_FOREACH(Shift, shift, kShiftInstructions) {
   3214       // Only test relevant shifted operands.
   3215       if (shift.mi.machine_type != MachineType::Int32()) continue;
   3216 
   3217       // The available shift operand range is `0 <= imm < 32`, but we also test
   3218       // that immediates outside this range are handled properly (modulo-32).
   3219       TRACED_FORRANGE(int, imm, -32, 63) {
   3220         StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
   3221                         MachineType::Int32());
   3222         Node* sub = m.Int32Sub(m.Int32Constant(0), m.Parameter(0));
   3223         m.Return((m.*cmp.mi.constructor)(
   3224             (m.*shift.mi.constructor)(m.Parameter(1), m.Int32Constant(imm)),
   3225             sub));
   3226         Stream s = m.Build();
   3227         // Cmn does not support ROR shifts.
   3228         if (shift.mi.arch_opcode == kArm64Ror32) {
   3229           ASSERT_EQ(2U, s.size());
   3230           continue;
   3231         }
   3232         ASSERT_EQ(1U, s.size());
   3233         EXPECT_EQ(kArm64Cmn32, s[0]->arch_opcode());
   3234         EXPECT_EQ(shift.mode, s[0]->addressing_mode());
   3235         EXPECT_EQ(3U, s[0]->InputCount());
   3236         EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(2)));
   3237         EXPECT_EQ(1U, s[0]->OutputCount());
   3238         EXPECT_EQ(kFlags_set, s[0]->flags_mode());
   3239         EXPECT_EQ(cmp.cond, s[0]->flags_condition());
   3240       }
   3241     }
   3242   }
   3243 }
   3244 
   3245 
   3246 // -----------------------------------------------------------------------------
   3247 // Miscellaneous
   3248 
   3249 
   3250 static const MachInst2 kLogicalWithNotRHSs[] = {
   3251     {&RawMachineAssembler::Word32And, "Word32And", kArm64Bic32,
   3252      MachineType::Int32()},
   3253     {&RawMachineAssembler::Word64And, "Word64And", kArm64Bic,
   3254      MachineType::Int64()},
   3255     {&RawMachineAssembler::Word32Or, "Word32Or", kArm64Orn32,
   3256      MachineType::Int32()},
   3257     {&RawMachineAssembler::Word64Or, "Word64Or", kArm64Orn,
   3258      MachineType::Int64()},
   3259     {&RawMachineAssembler::Word32Xor, "Word32Xor", kArm64Eon32,
   3260      MachineType::Int32()},
   3261     {&RawMachineAssembler::Word64Xor, "Word64Xor", kArm64Eon,
   3262      MachineType::Int64()}};
   3263 
   3264 
   3265 typedef InstructionSelectorTestWithParam<MachInst2>
   3266     InstructionSelectorLogicalWithNotRHSTest;
   3267 
   3268 
   3269 TEST_P(InstructionSelectorLogicalWithNotRHSTest, Parameter) {
   3270   const MachInst2 inst = GetParam();
   3271   const MachineType type = inst.machine_type;
   3272   // Test cases where RHS is Xor(x, -1).
   3273   {
   3274     StreamBuilder m(this, type, type, type);
   3275     if (type == MachineType::Int32()) {
   3276       m.Return((m.*inst.constructor)(
   3277           m.Parameter(0), m.Word32Xor(m.Parameter(1), m.Int32Constant(-1))));
   3278     } else {
   3279       ASSERT_EQ(MachineType::Int64(), type);
   3280       m.Return((m.*inst.constructor)(
   3281           m.Parameter(0), m.Word64Xor(m.Parameter(1), m.Int64Constant(-1))));
   3282     }
   3283     Stream s = m.Build();
   3284     ASSERT_EQ(1U, s.size());
   3285     EXPECT_EQ(inst.arch_opcode, s[0]->arch_opcode());
   3286     EXPECT_EQ(2U, s[0]->InputCount());
   3287     EXPECT_EQ(1U, s[0]->OutputCount());
   3288   }
   3289   {
   3290     StreamBuilder m(this, type, type, type);
   3291     if (type == MachineType::Int32()) {
   3292       m.Return((m.*inst.constructor)(
   3293           m.Word32Xor(m.Parameter(0), m.Int32Constant(-1)), m.Parameter(1)));
   3294     } else {
   3295       ASSERT_EQ(MachineType::Int64(), type);
   3296       m.Return((m.*inst.constructor)(
   3297           m.Word64Xor(m.Parameter(0), m.Int64Constant(-1)), m.Parameter(1)));
   3298     }
   3299     Stream s = m.Build();
   3300     ASSERT_EQ(1U, s.size());
   3301     EXPECT_EQ(inst.arch_opcode, s[0]->arch_opcode());
   3302     EXPECT_EQ(2U, s[0]->InputCount());
   3303     EXPECT_EQ(1U, s[0]->OutputCount());
   3304   }
   3305   // Test cases where RHS is Not(x).
   3306   {
   3307     StreamBuilder m(this, type, type, type);
   3308     if (type == MachineType::Int32()) {
   3309       m.Return(
   3310           (m.*inst.constructor)(m.Parameter(0), m.Word32Not(m.Parameter(1))));
   3311     } else {
   3312       ASSERT_EQ(MachineType::Int64(), type);
   3313       m.Return(
   3314           (m.*inst.constructor)(m.Parameter(0), m.Word64Not(m.Parameter(1))));
   3315     }
   3316     Stream s = m.Build();
   3317     ASSERT_EQ(1U, s.size());
   3318     EXPECT_EQ(inst.arch_opcode, s[0]->arch_opcode());
   3319     EXPECT_EQ(2U, s[0]->InputCount());
   3320     EXPECT_EQ(1U, s[0]->OutputCount());
   3321   }
   3322   {
   3323     StreamBuilder m(this, type, type, type);
   3324     if (type == MachineType::Int32()) {
   3325       m.Return(
   3326           (m.*inst.constructor)(m.Word32Not(m.Parameter(0)), m.Parameter(1)));
   3327     } else {
   3328       ASSERT_EQ(MachineType::Int64(), type);
   3329       m.Return(
   3330           (m.*inst.constructor)(m.Word64Not(m.Parameter(0)), m.Parameter(1)));
   3331     }
   3332     Stream s = m.Build();
   3333     ASSERT_EQ(1U, s.size());
   3334     EXPECT_EQ(inst.arch_opcode, s[0]->arch_opcode());
   3335     EXPECT_EQ(2U, s[0]->InputCount());
   3336     EXPECT_EQ(1U, s[0]->OutputCount());
   3337   }
   3338 }
   3339 
   3340 
   3341 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
   3342                         InstructionSelectorLogicalWithNotRHSTest,
   3343                         ::testing::ValuesIn(kLogicalWithNotRHSs));
   3344 
   3345 
   3346 TEST_F(InstructionSelectorTest, Word32NotWithParameter) {
   3347   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
   3348   m.Return(m.Word32Not(m.Parameter(0)));
   3349   Stream s = m.Build();
   3350   ASSERT_EQ(1U, s.size());
   3351   EXPECT_EQ(kArm64Not32, s[0]->arch_opcode());
   3352   EXPECT_EQ(1U, s[0]->InputCount());
   3353   EXPECT_EQ(1U, s[0]->OutputCount());
   3354 }
   3355 
   3356 
   3357 TEST_F(InstructionSelectorTest, Word64NotWithParameter) {
   3358   StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
   3359   m.Return(m.Word64Not(m.Parameter(0)));
   3360   Stream s = m.Build();
   3361   ASSERT_EQ(1U, s.size());
   3362   EXPECT_EQ(kArm64Not, s[0]->arch_opcode());
   3363   EXPECT_EQ(1U, s[0]->InputCount());
   3364   EXPECT_EQ(1U, s[0]->OutputCount());
   3365 }
   3366 
   3367 
   3368 TEST_F(InstructionSelectorTest, Word32XorMinusOneWithParameter) {
   3369   {
   3370     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
   3371     m.Return(m.Word32Xor(m.Parameter(0), m.Int32Constant(-1)));
   3372     Stream s = m.Build();
   3373     ASSERT_EQ(1U, s.size());
   3374     EXPECT_EQ(kArm64Not32, s[0]->arch_opcode());
   3375     EXPECT_EQ(1U, s[0]->InputCount());
   3376     EXPECT_EQ(1U, s[0]->OutputCount());
   3377   }
   3378   {
   3379     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
   3380     m.Return(m.Word32Xor(m.Int32Constant(-1), m.Parameter(0)));
   3381     Stream s = m.Build();
   3382     ASSERT_EQ(1U, s.size());
   3383     EXPECT_EQ(kArm64Not32, s[0]->arch_opcode());
   3384     EXPECT_EQ(1U, s[0]->InputCount());
   3385     EXPECT_EQ(1U, s[0]->OutputCount());
   3386   }
   3387 }
   3388 
   3389 
   3390 TEST_F(InstructionSelectorTest, Word64XorMinusOneWithParameter) {
   3391   {
   3392     StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
   3393     m.Return(m.Word64Xor(m.Parameter(0), m.Int64Constant(-1)));
   3394     Stream s = m.Build();
   3395     ASSERT_EQ(1U, s.size());
   3396     EXPECT_EQ(kArm64Not, s[0]->arch_opcode());
   3397     EXPECT_EQ(1U, s[0]->InputCount());
   3398     EXPECT_EQ(1U, s[0]->OutputCount());
   3399   }
   3400   {
   3401     StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
   3402     m.Return(m.Word64Xor(m.Int64Constant(-1), m.Parameter(0)));
   3403     Stream s = m.Build();
   3404     ASSERT_EQ(1U, s.size());
   3405     EXPECT_EQ(kArm64Not, s[0]->arch_opcode());
   3406     EXPECT_EQ(1U, s[0]->InputCount());
   3407     EXPECT_EQ(1U, s[0]->OutputCount());
   3408   }
   3409 }
   3410 
   3411 
   3412 TEST_F(InstructionSelectorTest, Word32ShrWithWord32AndWithImmediate) {
   3413   // The available shift operand range is `0 <= imm < 32`, but we also test
   3414   // that immediates outside this range are handled properly (modulo-32).
   3415   TRACED_FORRANGE(int32_t, shift, -32, 63) {
   3416     int32_t lsb = shift & 0x1f;
   3417     TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) {
   3418       uint32_t jnk = rng()->NextInt();
   3419       jnk = (lsb > 0) ? (jnk >> (32 - lsb)) : 0;
   3420       uint32_t msk = ((0xffffffffu >> (32 - width)) << lsb) | jnk;
   3421       StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
   3422       m.Return(m.Word32Shr(m.Word32And(m.Parameter(0), m.Int32Constant(msk)),
   3423                            m.Int32Constant(shift)));
   3424       Stream s = m.Build();
   3425       ASSERT_EQ(1U, s.size());
   3426       EXPECT_EQ(kArm64Ubfx32, s[0]->arch_opcode());
   3427       ASSERT_EQ(3U, s[0]->InputCount());
   3428       EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
   3429       EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
   3430     }
   3431   }
   3432   TRACED_FORRANGE(int32_t, shift, -32, 63) {
   3433     int32_t lsb = shift & 0x1f;
   3434     TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) {
   3435       uint32_t jnk = rng()->NextInt();
   3436       jnk = (lsb > 0) ? (jnk >> (32 - lsb)) : 0;
   3437       uint32_t msk = ((0xffffffffu >> (32 - width)) << lsb) | jnk;
   3438       StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
   3439       m.Return(m.Word32Shr(m.Word32And(m.Int32Constant(msk), m.Parameter(0)),
   3440                            m.Int32Constant(shift)));
   3441       Stream s = m.Build();
   3442       ASSERT_EQ(1U, s.size());
   3443       EXPECT_EQ(kArm64Ubfx32, s[0]->arch_opcode());
   3444       ASSERT_EQ(3U, s[0]->InputCount());
   3445       EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
   3446       EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2)));
   3447     }
   3448   }
   3449 }
   3450 
   3451 
   3452 TEST_F(InstructionSelectorTest, Word64ShrWithWord64AndWithImmediate) {
   3453   // The available shift operand range is `0 <= imm < 64`, but we also test
   3454   // that immediates outside this range are handled properly (modulo-64).
   3455   TRACED_FORRANGE(int32_t, shift, -64, 127) {
   3456     int32_t lsb = shift & 0x3f;
   3457     TRACED_FORRANGE(int32_t, width, 1, 64 - lsb) {
   3458       uint64_t jnk = rng()->NextInt64();
   3459       jnk = (lsb > 0) ? (jnk >> (64 - lsb)) : 0;
   3460       uint64_t msk =
   3461           ((V8_UINT64_C(0xffffffffffffffff) >> (64 - width)) << lsb) | jnk;
   3462       StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
   3463       m.Return(m.Word64Shr(m.Word64And(m.Parameter(0), m.Int64Constant(msk)),
   3464                            m.Int64Constant(shift)));
   3465       Stream s = m.Build();
   3466       ASSERT_EQ(1U, s.size());
   3467       EXPECT_EQ(kArm64Ubfx, s[0]->arch_opcode());
   3468       ASSERT_EQ(3U, s[0]->InputCount());
   3469       EXPECT_EQ(lsb, s.ToInt64(s[0]->InputAt(1)));
   3470       EXPECT_EQ(width, s.ToInt64(s[0]->InputAt(2)));
   3471     }
   3472   }
   3473   TRACED_FORRANGE(int32_t, shift, -64, 127) {
   3474     int32_t lsb = shift & 0x3f;
   3475     TRACED_FORRANGE(int32_t, width, 1, 64 - lsb) {
   3476       uint64_t jnk = rng()->NextInt64();
   3477       jnk = (lsb > 0) ? (jnk >> (64 - lsb)) : 0;
   3478       uint64_t msk =
   3479           ((V8_UINT64_C(0xffffffffffffffff) >> (64 - width)) << lsb) | jnk;
   3480       StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
   3481       m.Return(m.Word64Shr(m.Word64And(m.Int64Constant(msk), m.Parameter(0)),
   3482                            m.Int64Constant(shift)));
   3483       Stream s = m.Build();
   3484       ASSERT_EQ(1U, s.size());
   3485       EXPECT_EQ(kArm64Ubfx, s[0]->arch_opcode());
   3486       ASSERT_EQ(3U, s[0]->InputCount());
   3487       EXPECT_EQ(lsb, s.ToInt64(s[0]->InputAt(1)));
   3488       EXPECT_EQ(width, s.ToInt64(s[0]->InputAt(2)));
   3489     }
   3490   }
   3491 }
   3492 
   3493 
   3494 TEST_F(InstructionSelectorTest, Word32AndWithImmediateWithWord32Shr) {
   3495   // The available shift operand range is `0 <= imm < 32`, but we also test
   3496   // that immediates outside this range are handled properly (modulo-32).
   3497   TRACED_FORRANGE(int32_t, shift, -32, 63) {
   3498     int32_t lsb = shift & 0x1f;
   3499     TRACED_FORRANGE(int32_t, width, 1, 31) {
   3500       uint32_t msk = (1 << width) - 1;
   3501       StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
   3502       m.Return(m.Word32And(m.Word32Shr(m.Parameter(0), m.Int32Constant(shift)),
   3503                            m.Int32Constant(msk)));
   3504       Stream s = m.Build();
   3505       ASSERT_EQ(1U, s.size());
   3506       EXPECT_EQ(kArm64Ubfx32, s[0]->arch_opcode());
   3507       ASSERT_EQ(3U, s[0]->InputCount());
   3508       EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
   3509       int32_t actual_width = (lsb + width > 32) ? (32 - lsb) : width;
   3510       EXPECT_EQ(actual_width, s.ToInt32(s[0]->InputAt(2)));
   3511     }
   3512   }
   3513   TRACED_FORRANGE(int32_t, shift, -32, 63) {
   3514     int32_t lsb = shift & 0x1f;
   3515     TRACED_FORRANGE(int32_t, width, 1, 31) {
   3516       uint32_t msk = (1 << width) - 1;
   3517       StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
   3518       m.Return(
   3519           m.Word32And(m.Int32Constant(msk),
   3520                       m.Word32Shr(m.Parameter(0), m.Int32Constant(shift))));
   3521       Stream s = m.Build();
   3522       ASSERT_EQ(1U, s.size());
   3523       EXPECT_EQ(kArm64Ubfx32, s[0]->arch_opcode());
   3524       ASSERT_EQ(3U, s[0]->InputCount());
   3525       EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1)));
   3526       int32_t actual_width = (lsb + width > 32) ? (32 - lsb) : width;
   3527       EXPECT_EQ(actual_width, s.ToInt32(s[0]->InputAt(2)));
   3528     }
   3529   }
   3530 }
   3531 
   3532 
   3533 TEST_F(InstructionSelectorTest, Word64AndWithImmediateWithWord64Shr) {
   3534   // The available shift operand range is `0 <= imm < 64`, but we also test
   3535   // that immediates outside this range are handled properly (modulo-64).
   3536   TRACED_FORRANGE(int64_t, shift, -64, 127) {
   3537     int64_t lsb = shift & 0x3f;
   3538     TRACED_FORRANGE(int64_t, width, 1, 63) {
   3539       uint64_t msk = (V8_UINT64_C(1) << width) - 1;
   3540       StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
   3541       m.Return(m.Word64And(m.Word64Shr(m.Parameter(0), m.Int64Constant(shift)),
   3542                            m.Int64Constant(msk)));
   3543       Stream s = m.Build();
   3544       ASSERT_EQ(1U, s.size());
   3545       EXPECT_EQ(kArm64Ubfx, s[0]->arch_opcode());
   3546       ASSERT_EQ(3U, s[0]->InputCount());
   3547       EXPECT_EQ(lsb, s.ToInt64(s[0]->InputAt(1)));
   3548       int64_t actual_width = (lsb + width > 64) ? (64 - lsb) : width;
   3549       EXPECT_EQ(actual_width, s.ToInt64(s[0]->InputAt(2)));
   3550     }
   3551   }
   3552   TRACED_FORRANGE(int64_t, shift, -64, 127) {
   3553     int64_t lsb = shift & 0x3f;
   3554     TRACED_FORRANGE(int64_t, width, 1, 63) {
   3555       uint64_t msk = (V8_UINT64_C(1) << width) - 1;
   3556       StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
   3557       m.Return(
   3558           m.Word64And(m.Int64Constant(msk),
   3559                       m.Word64Shr(m.Parameter(0), m.Int64Constant(shift))));
   3560       Stream s = m.Build();
   3561       ASSERT_EQ(1U, s.size());
   3562       EXPECT_EQ(kArm64Ubfx, s[0]->arch_opcode());
   3563       ASSERT_EQ(3U, s[0]->InputCount());
   3564       EXPECT_EQ(lsb, s.ToInt64(s[0]->InputAt(1)));
   3565       int64_t actual_width = (lsb + width > 64) ? (64 - lsb) : width;
   3566       EXPECT_EQ(actual_width, s.ToInt64(s[0]->InputAt(2)));
   3567     }
   3568   }
   3569 }
   3570 
   3571 
   3572 TEST_F(InstructionSelectorTest, Int32MulHighWithParameters) {
   3573   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
   3574                   MachineType::Int32());
   3575   Node* const p0 = m.Parameter(0);
   3576   Node* const p1 = m.Parameter(1);
   3577   Node* const n = m.Int32MulHigh(p0, p1);
   3578   m.Return(n);
   3579   Stream s = m.Build();
   3580   ASSERT_EQ(2U, s.size());
   3581   EXPECT_EQ(kArm64Smull, s[0]->arch_opcode());
   3582   ASSERT_EQ(2U, s[0]->InputCount());
   3583   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
   3584   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
   3585   ASSERT_EQ(1U, s[0]->OutputCount());
   3586   EXPECT_EQ(kArm64Asr, s[1]->arch_opcode());
   3587   ASSERT_EQ(2U, s[1]->InputCount());
   3588   EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(0)));
   3589   EXPECT_EQ(32, s.ToInt64(s[1]->InputAt(1)));
   3590   ASSERT_EQ(1U, s[1]->OutputCount());
   3591   EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[1]->Output()));
   3592 }
   3593 
   3594 
   3595 TEST_F(InstructionSelectorTest, Int32MulHighWithSar) {
   3596   TRACED_FORRANGE(int32_t, shift, -32, 63) {
   3597     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
   3598                     MachineType::Int32());
   3599     Node* const p0 = m.Parameter(0);
   3600     Node* const p1 = m.Parameter(1);
   3601     Node* const n = m.Word32Sar(m.Int32MulHigh(p0, p1), m.Int32Constant(shift));
   3602     m.Return(n);
   3603     Stream s = m.Build();
   3604     ASSERT_EQ(2U, s.size());
   3605     EXPECT_EQ(kArm64Smull, s[0]->arch_opcode());
   3606     ASSERT_EQ(2U, s[0]->InputCount());
   3607     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
   3608     EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
   3609     ASSERT_EQ(1U, s[0]->OutputCount());
   3610     EXPECT_EQ(kArm64Asr, s[1]->arch_opcode());
   3611     ASSERT_EQ(2U, s[1]->InputCount());
   3612     EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(0)));
   3613     EXPECT_EQ((shift & 0x1f) + 32, s.ToInt64(s[1]->InputAt(1)));
   3614     ASSERT_EQ(1U, s[1]->OutputCount());
   3615     EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[1]->Output()));
   3616   }
   3617 }
   3618 
   3619 
   3620 TEST_F(InstructionSelectorTest, Int32MulHighWithAdd) {
   3621   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
   3622                   MachineType::Int32());
   3623   Node* const p0 = m.Parameter(0);
   3624   Node* const p1 = m.Parameter(1);
   3625   Node* const a = m.Int32Add(m.Int32MulHigh(p0, p1), p0);
   3626   // Test only one shift constant here, as we're only interested in it being a
   3627   // 32-bit operation; the shift amount is irrelevant.
   3628   Node* const n = m.Word32Sar(a, m.Int32Constant(1));
   3629   m.Return(n);
   3630   Stream s = m.Build();
   3631   ASSERT_EQ(3U, s.size());
   3632   EXPECT_EQ(kArm64Smull, s[0]->arch_opcode());
   3633   ASSERT_EQ(2U, s[0]->InputCount());
   3634   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
   3635   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
   3636   ASSERT_EQ(1U, s[0]->OutputCount());
   3637   EXPECT_EQ(kArm64Add, s[1]->arch_opcode());
   3638   EXPECT_EQ(kMode_Operand2_R_ASR_I, s[1]->addressing_mode());
   3639   ASSERT_EQ(3U, s[1]->InputCount());
   3640   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[1]->InputAt(0)));
   3641   EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(1)));
   3642   EXPECT_EQ(32, s.ToInt64(s[1]->InputAt(2)));
   3643   ASSERT_EQ(1U, s[1]->OutputCount());
   3644   EXPECT_EQ(kArm64Asr32, s[2]->arch_opcode());
   3645   ASSERT_EQ(2U, s[2]->InputCount());
   3646   EXPECT_EQ(s.ToVreg(s[1]->Output()), s.ToVreg(s[2]->InputAt(0)));
   3647   EXPECT_EQ(1, s.ToInt64(s[2]->InputAt(1)));
   3648   ASSERT_EQ(1U, s[2]->OutputCount());
   3649   EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[2]->Output()));
   3650 }
   3651 
   3652 
   3653 TEST_F(InstructionSelectorTest, Uint32MulHighWithShr) {
   3654   TRACED_FORRANGE(int32_t, shift, -32, 63) {
   3655     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
   3656                     MachineType::Int32());
   3657     Node* const p0 = m.Parameter(0);
   3658     Node* const p1 = m.Parameter(1);
   3659     Node* const n =
   3660         m.Word32Shr(m.Uint32MulHigh(p0, p1), m.Int32Constant(shift));
   3661     m.Return(n);
   3662     Stream s = m.Build();
   3663     ASSERT_EQ(2U, s.size());
   3664     EXPECT_EQ(kArm64Umull, s[0]->arch_opcode());
   3665     ASSERT_EQ(2U, s[0]->InputCount());
   3666     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
   3667     EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
   3668     ASSERT_EQ(1U, s[0]->OutputCount());
   3669     EXPECT_EQ(kArm64Lsr, s[1]->arch_opcode());
   3670     ASSERT_EQ(2U, s[1]->InputCount());
   3671     EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(0)));
   3672     EXPECT_EQ((shift & 0x1f) + 32, s.ToInt64(s[1]->InputAt(1)));
   3673     ASSERT_EQ(1U, s[1]->OutputCount());
   3674     EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[1]->Output()));
   3675   }
   3676 }
   3677 
   3678 
   3679 TEST_F(InstructionSelectorTest, Word32SarWithWord32Shl) {
   3680   TRACED_FORRANGE(int32_t, shift, 1, 31) {
   3681     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
   3682     Node* const p0 = m.Parameter(0);
   3683     Node* const r = m.Word32Sar(m.Word32Shl(p0, m.Int32Constant(shift)),
   3684                                 m.Int32Constant(shift));
   3685     m.Return(r);
   3686     Stream s = m.Build();
   3687     ASSERT_EQ(1U, s.size());
   3688     EXPECT_EQ(kArm64Sbfx32, s[0]->arch_opcode());
   3689     ASSERT_EQ(3U, s[0]->InputCount());
   3690     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
   3691     ASSERT_EQ(1U, s[0]->OutputCount());
   3692     EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
   3693   }
   3694   TRACED_FORRANGE(int32_t, shift, 1, 31) {
   3695     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
   3696     Node* const p0 = m.Parameter(0);
   3697     Node* const r = m.Word32Sar(m.Word32Shl(p0, m.Int32Constant(shift + 32)),
   3698                                 m.Int32Constant(shift + 64));
   3699     m.Return(r);
   3700     Stream s = m.Build();
   3701     ASSERT_EQ(1U, s.size());
   3702     EXPECT_EQ(kArm64Sbfx32, s[0]->arch_opcode());
   3703     ASSERT_EQ(3U, s[0]->InputCount());
   3704     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
   3705     ASSERT_EQ(1U, s[0]->OutputCount());
   3706     EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
   3707   }
   3708 }
   3709 
   3710 
   3711 TEST_F(InstructionSelectorTest, Word32ShrWithWord32Shl) {
   3712   TRACED_FORRANGE(int32_t, shift, 1, 31) {
   3713     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
   3714     Node* const p0 = m.Parameter(0);
   3715     Node* const r = m.Word32Shr(m.Word32Shl(p0, m.Int32Constant(shift)),
   3716                                 m.Int32Constant(shift));
   3717     m.Return(r);
   3718     Stream s = m.Build();
   3719     ASSERT_EQ(1U, s.size());
   3720     EXPECT_EQ(kArm64Ubfx32, s[0]->arch_opcode());
   3721     ASSERT_EQ(3U, s[0]->InputCount());
   3722     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
   3723     ASSERT_EQ(1U, s[0]->OutputCount());
   3724     EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
   3725   }
   3726   TRACED_FORRANGE(int32_t, shift, 1, 31) {
   3727     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
   3728     Node* const p0 = m.Parameter(0);
   3729     Node* const r = m.Word32Shr(m.Word32Shl(p0, m.Int32Constant(shift + 32)),
   3730                                 m.Int32Constant(shift + 64));
   3731     m.Return(r);
   3732     Stream s = m.Build();
   3733     ASSERT_EQ(1U, s.size());
   3734     EXPECT_EQ(kArm64Ubfx32, s[0]->arch_opcode());
   3735     ASSERT_EQ(3U, s[0]->InputCount());
   3736     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
   3737     ASSERT_EQ(1U, s[0]->OutputCount());
   3738     EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
   3739   }
   3740 }
   3741 
   3742 
   3743 TEST_F(InstructionSelectorTest, Word32ShlWithWord32And) {
   3744   TRACED_FORRANGE(int32_t, shift, 1, 30) {
   3745     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
   3746     Node* const p0 = m.Parameter(0);
   3747     Node* const r =
   3748         m.Word32Shl(m.Word32And(p0, m.Int32Constant((1 << (31 - shift)) - 1)),
   3749                     m.Int32Constant(shift));
   3750     m.Return(r);
   3751     Stream s = m.Build();
   3752     ASSERT_EQ(1U, s.size());
   3753     EXPECT_EQ(kArm64Ubfiz32, s[0]->arch_opcode());
   3754     ASSERT_EQ(3U, s[0]->InputCount());
   3755     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
   3756     ASSERT_EQ(1U, s[0]->OutputCount());
   3757     EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
   3758   }
   3759   TRACED_FORRANGE(int32_t, shift, 0, 30) {
   3760     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
   3761     Node* const p0 = m.Parameter(0);
   3762     Node* const r =
   3763         m.Word32Shl(m.Word32And(p0, m.Int32Constant((1 << (31 - shift)) - 1)),
   3764                     m.Int32Constant(shift + 1));
   3765     m.Return(r);
   3766     Stream s = m.Build();
   3767     ASSERT_EQ(1U, s.size());
   3768     EXPECT_EQ(kArm64Lsl32, s[0]->arch_opcode());
   3769     ASSERT_EQ(2U, s[0]->InputCount());
   3770     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
   3771     ASSERT_EQ(1U, s[0]->OutputCount());
   3772     EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
   3773   }
   3774 }
   3775 
   3776 
   3777 TEST_F(InstructionSelectorTest, Word32Clz) {
   3778   StreamBuilder m(this, MachineType::Uint32(), MachineType::Uint32());
   3779   Node* const p0 = m.Parameter(0);
   3780   Node* const n = m.Word32Clz(p0);
   3781   m.Return(n);
   3782   Stream s = m.Build();
   3783   ASSERT_EQ(1U, s.size());
   3784   EXPECT_EQ(kArm64Clz32, s[0]->arch_opcode());
   3785   ASSERT_EQ(1U, s[0]->InputCount());
   3786   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
   3787   ASSERT_EQ(1U, s[0]->OutputCount());
   3788   EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
   3789 }
   3790 
   3791 
   3792 TEST_F(InstructionSelectorTest, Float32Abs) {
   3793   StreamBuilder m(this, MachineType::Float32(), MachineType::Float32());
   3794   Node* const p0 = m.Parameter(0);
   3795   Node* const n = m.Float32Abs(p0);
   3796   m.Return(n);
   3797   Stream s = m.Build();
   3798   ASSERT_EQ(1U, s.size());
   3799   EXPECT_EQ(kArm64Float32Abs, s[0]->arch_opcode());
   3800   ASSERT_EQ(1U, s[0]->InputCount());
   3801   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
   3802   ASSERT_EQ(1U, s[0]->OutputCount());
   3803   EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
   3804 }
   3805 
   3806 
   3807 TEST_F(InstructionSelectorTest, Float64Abs) {
   3808   StreamBuilder m(this, MachineType::Float64(), MachineType::Float64());
   3809   Node* const p0 = m.Parameter(0);
   3810   Node* const n = m.Float64Abs(p0);
   3811   m.Return(n);
   3812   Stream s = m.Build();
   3813   ASSERT_EQ(1U, s.size());
   3814   EXPECT_EQ(kArm64Float64Abs, s[0]->arch_opcode());
   3815   ASSERT_EQ(1U, s[0]->InputCount());
   3816   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
   3817   ASSERT_EQ(1U, s[0]->OutputCount());
   3818   EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
   3819 }
   3820 
   3821 
   3822 TEST_F(InstructionSelectorTest, Float64SubWithMinusZero) {
   3823   StreamBuilder m(this, MachineType::Float64(), MachineType::Float64());
   3824   Node* const p0 = m.Parameter(0);
   3825   Node* const n = m.Float64Sub(m.Float64Constant(-0.0), p0);
   3826   m.Return(n);
   3827   Stream s = m.Build();
   3828   ASSERT_EQ(1U, s.size());
   3829   EXPECT_EQ(kArm64Float64Neg, s[0]->arch_opcode());
   3830   ASSERT_EQ(1U, s[0]->InputCount());
   3831   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
   3832   ASSERT_EQ(1U, s[0]->OutputCount());
   3833   EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
   3834 }
   3835 
   3836 
   3837 TEST_F(InstructionSelectorTest, Float32Max) {
   3838   StreamBuilder m(this, MachineType::Float32(), MachineType::Float32(),
   3839                   MachineType::Float32());
   3840   Node* const p0 = m.Parameter(0);
   3841   Node* const p1 = m.Parameter(1);
   3842   Node* const n = m.Float32Max(p0, p1);
   3843   m.Return(n);
   3844   Stream s = m.Build();
   3845   // Float32Max is `(b < a) ? a : b`.
   3846   ASSERT_EQ(1U, s.size());
   3847   EXPECT_EQ(kArm64Float32Max, s[0]->arch_opcode());
   3848   ASSERT_EQ(2U, s[0]->InputCount());
   3849   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
   3850   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
   3851   ASSERT_EQ(1U, s[0]->OutputCount());
   3852   EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
   3853 }
   3854 
   3855 
   3856 TEST_F(InstructionSelectorTest, Float32Min) {
   3857   StreamBuilder m(this, MachineType::Float32(), MachineType::Float32(),
   3858                   MachineType::Float32());
   3859   Node* const p0 = m.Parameter(0);
   3860   Node* const p1 = m.Parameter(1);
   3861   Node* const n = m.Float32Min(p0, p1);
   3862   m.Return(n);
   3863   Stream s = m.Build();
   3864   // Float32Min is `(a < b) ? a : b`.
   3865   ASSERT_EQ(1U, s.size());
   3866   EXPECT_EQ(kArm64Float32Min, s[0]->arch_opcode());
   3867   ASSERT_EQ(2U, s[0]->InputCount());
   3868   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
   3869   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
   3870   ASSERT_EQ(1U, s[0]->OutputCount());
   3871   EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
   3872 }
   3873 
   3874 
   3875 TEST_F(InstructionSelectorTest, Float64Max) {
   3876   StreamBuilder m(this, MachineType::Float64(), MachineType::Float64(),
   3877                   MachineType::Float64());
   3878   Node* const p0 = m.Parameter(0);
   3879   Node* const p1 = m.Parameter(1);
   3880   Node* const n = m.Float64Max(p0, p1);
   3881   m.Return(n);
   3882   Stream s = m.Build();
   3883   // Float64Max is `(b < a) ? a : b`.
   3884   ASSERT_EQ(1U, s.size());
   3885   EXPECT_EQ(kArm64Float64Max, s[0]->arch_opcode());
   3886   ASSERT_EQ(2U, s[0]->InputCount());
   3887   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
   3888   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
   3889   ASSERT_EQ(1U, s[0]->OutputCount());
   3890   EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
   3891 }
   3892 
   3893 
   3894 TEST_F(InstructionSelectorTest, Float64Min) {
   3895   StreamBuilder m(this, MachineType::Float64(), MachineType::Float64(),
   3896                   MachineType::Float64());
   3897   Node* const p0 = m.Parameter(0);
   3898   Node* const p1 = m.Parameter(1);
   3899   Node* const n = m.Float64Min(p0, p1);
   3900   m.Return(n);
   3901   Stream s = m.Build();
   3902   // Float64Min is `(a < b) ? a : b`.
   3903   ASSERT_EQ(1U, s.size());
   3904   EXPECT_EQ(kArm64Float64Min, s[0]->arch_opcode());
   3905   ASSERT_EQ(2U, s[0]->InputCount());
   3906   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
   3907   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
   3908   ASSERT_EQ(1U, s[0]->OutputCount());
   3909   EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
   3910 }
   3911 
   3912 TEST_F(InstructionSelectorTest, Float32Neg) {
   3913   StreamBuilder m(this, MachineType::Float32(), MachineType::Float32());
   3914   Node* const p0 = m.Parameter(0);
   3915   // Don't use m.Float32Neg() as that generates an explicit sub.
   3916   Node* const n = m.AddNode(m.machine()->Float32Neg().op(), m.Parameter(0));
   3917   m.Return(n);
   3918   Stream s = m.Build();
   3919   ASSERT_EQ(1U, s.size());
   3920   EXPECT_EQ(kArm64Float32Neg, s[0]->arch_opcode());
   3921   ASSERT_EQ(1U, s[0]->InputCount());
   3922   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
   3923   ASSERT_EQ(1U, s[0]->OutputCount());
   3924   EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
   3925 }
   3926 
   3927 TEST_F(InstructionSelectorTest, Float64Neg) {
   3928   StreamBuilder m(this, MachineType::Float64(), MachineType::Float64());
   3929   Node* const p0 = m.Parameter(0);
   3930   // Don't use m.Float64Neg() as that generates an explicit sub.
   3931   Node* const n = m.AddNode(m.machine()->Float64Neg().op(), m.Parameter(0));
   3932   m.Return(n);
   3933   Stream s = m.Build();
   3934   ASSERT_EQ(1U, s.size());
   3935   EXPECT_EQ(kArm64Float64Neg, s[0]->arch_opcode());
   3936   ASSERT_EQ(1U, s[0]->InputCount());
   3937   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
   3938   ASSERT_EQ(1U, s[0]->OutputCount());
   3939   EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
   3940 }
   3941 
   3942 }  // namespace compiler
   3943 }  // namespace internal
   3944 }  // namespace v8
   3945