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 <list>
      6 
      7 #include "src/compiler/instruction-selector-unittest.h"
      8 
      9 namespace v8 {
     10 namespace internal {
     11 namespace compiler {
     12 
     13 namespace {
     14 
     15 typedef RawMachineAssembler::Label MLabel;
     16 
     17 template <typename T>
     18 struct MachInst {
     19   T constructor;
     20   const char* constructor_name;
     21   ArchOpcode arch_opcode;
     22   MachineType machine_type;
     23 };
     24 
     25 typedef MachInst<Node* (RawMachineAssembler::*)(Node*)> MachInst1;
     26 typedef MachInst<Node* (RawMachineAssembler::*)(Node*, Node*)> MachInst2;
     27 
     28 
     29 template <typename T>
     30 std::ostream& operator<<(std::ostream& os, const MachInst<T>& mi) {
     31   return os << mi.constructor_name;
     32 }
     33 
     34 
     35 // Helper to build Int32Constant or Int64Constant depending on the given
     36 // machine type.
     37 Node* BuildConstant(InstructionSelectorTest::StreamBuilder& m, MachineType type,
     38                     int64_t value) {
     39   switch (type) {
     40     case kMachInt32:
     41       return m.Int32Constant(value);
     42       break;
     43 
     44     case kMachInt64:
     45       return m.Int64Constant(value);
     46       break;
     47 
     48     default:
     49       UNIMPLEMENTED();
     50   }
     51   return NULL;
     52 }
     53 
     54 
     55 // ARM64 logical instructions.
     56 static const MachInst2 kLogicalInstructions[] = {
     57     {&RawMachineAssembler::Word32And, "Word32And", kArm64And32, kMachInt32},
     58     {&RawMachineAssembler::Word64And, "Word64And", kArm64And, kMachInt64},
     59     {&RawMachineAssembler::Word32Or, "Word32Or", kArm64Or32, kMachInt32},
     60     {&RawMachineAssembler::Word64Or, "Word64Or", kArm64Or, kMachInt64},
     61     {&RawMachineAssembler::Word32Xor, "Word32Xor", kArm64Xor32, kMachInt32},
     62     {&RawMachineAssembler::Word64Xor, "Word64Xor", kArm64Xor, kMachInt64}};
     63 
     64 
     65 // ARM64 logical immediates: contiguous set bits, rotated about a power of two
     66 // sized block. The block is then duplicated across the word. Below is a random
     67 // subset of the 32-bit immediates.
     68 static const uint32_t kLogicalImmediates[] = {
     69     0x00000002, 0x00000003, 0x00000070, 0x00000080, 0x00000100, 0x000001c0,
     70     0x00000300, 0x000007e0, 0x00003ffc, 0x00007fc0, 0x0003c000, 0x0003f000,
     71     0x0003ffc0, 0x0003fff8, 0x0007ff00, 0x0007ffe0, 0x000e0000, 0x001e0000,
     72     0x001ffffc, 0x003f0000, 0x003f8000, 0x00780000, 0x007fc000, 0x00ff0000,
     73     0x01800000, 0x01800180, 0x01f801f8, 0x03fe0000, 0x03ffffc0, 0x03fffffc,
     74     0x06000000, 0x07fc0000, 0x07ffc000, 0x07ffffc0, 0x07ffffe0, 0x0ffe0ffe,
     75     0x0ffff800, 0x0ffffff0, 0x0fffffff, 0x18001800, 0x1f001f00, 0x1f801f80,
     76     0x30303030, 0x3ff03ff0, 0x3ff83ff8, 0x3fff0000, 0x3fff8000, 0x3fffffc0,
     77     0x70007000, 0x7f7f7f7f, 0x7fc00000, 0x7fffffc0, 0x8000001f, 0x800001ff,
     78     0x81818181, 0x9fff9fff, 0xc00007ff, 0xc0ffffff, 0xdddddddd, 0xe00001ff,
     79     0xe00003ff, 0xe007ffff, 0xefffefff, 0xf000003f, 0xf001f001, 0xf3fff3ff,
     80     0xf800001f, 0xf80fffff, 0xf87ff87f, 0xfbfbfbfb, 0xfc00001f, 0xfc0000ff,
     81     0xfc0001ff, 0xfc03fc03, 0xfe0001ff, 0xff000001, 0xff03ff03, 0xff800000,
     82     0xff800fff, 0xff801fff, 0xff87ffff, 0xffc0003f, 0xffc007ff, 0xffcfffcf,
     83     0xffe00003, 0xffe1ffff, 0xfff0001f, 0xfff07fff, 0xfff80007, 0xfff87fff,
     84     0xfffc00ff, 0xfffe07ff, 0xffff00ff, 0xffffc001, 0xfffff007, 0xfffff3ff,
     85     0xfffff807, 0xfffff9ff, 0xfffffc0f, 0xfffffeff};
     86 
     87 
     88 // ARM64 arithmetic instructions.
     89 static const MachInst2 kAddSubInstructions[] = {
     90     {&RawMachineAssembler::Int32Add, "Int32Add", kArm64Add32, kMachInt32},
     91     {&RawMachineAssembler::Int64Add, "Int64Add", kArm64Add, kMachInt64},
     92     {&RawMachineAssembler::Int32Sub, "Int32Sub", kArm64Sub32, kMachInt32},
     93     {&RawMachineAssembler::Int64Sub, "Int64Sub", kArm64Sub, kMachInt64}};
     94 
     95 
     96 // ARM64 Add/Sub immediates: 12-bit immediate optionally shifted by 12.
     97 // Below is a combination of a random subset and some edge values.
     98 static const int32_t kAddSubImmediates[] = {
     99     0,        1,        69,       493,      599,      701,      719,
    100     768,      818,      842,      945,      1246,     1286,     1429,
    101     1669,     2171,     2179,     2182,     2254,     2334,     2338,
    102     2343,     2396,     2449,     2610,     2732,     2855,     2876,
    103     2944,     3377,     3458,     3475,     3476,     3540,     3574,
    104     3601,     3813,     3871,     3917,     4095,     4096,     16384,
    105     364544,   462848,   970752,   1523712,  1863680,  2363392,  3219456,
    106     3280896,  4247552,  4526080,  4575232,  4960256,  5505024,  5894144,
    107     6004736,  6193152,  6385664,  6795264,  7114752,  7233536,  7348224,
    108     7499776,  7573504,  7729152,  8634368,  8937472,  9465856,  10354688,
    109     10682368, 11059200, 11460608, 13168640, 13176832, 14336000, 15028224,
    110     15597568, 15892480, 16773120};
    111 
    112 
    113 // ARM64 flag setting data processing instructions.
    114 static const MachInst2 kDPFlagSetInstructions[] = {
    115     {&RawMachineAssembler::Word32And, "Word32And", kArm64Tst32, kMachInt32},
    116     {&RawMachineAssembler::Int32Add, "Int32Add", kArm64Cmn32, kMachInt32},
    117     {&RawMachineAssembler::Int32Sub, "Int32Sub", kArm64Cmp32, kMachInt32}};
    118 
    119 
    120 // ARM64 arithmetic with overflow instructions.
    121 static const MachInst2 kOvfAddSubInstructions[] = {
    122     {&RawMachineAssembler::Int32AddWithOverflow, "Int32AddWithOverflow",
    123      kArm64Add32, kMachInt32},
    124     {&RawMachineAssembler::Int32SubWithOverflow, "Int32SubWithOverflow",
    125      kArm64Sub32, kMachInt32}};
    126 
    127 
    128 // ARM64 shift instructions.
    129 static const MachInst2 kShiftInstructions[] = {
    130     {&RawMachineAssembler::Word32Shl, "Word32Shl", kArm64Shl32, kMachInt32},
    131     {&RawMachineAssembler::Word64Shl, "Word64Shl", kArm64Shl, kMachInt64},
    132     {&RawMachineAssembler::Word32Shr, "Word32Shr", kArm64Shr32, kMachInt32},
    133     {&RawMachineAssembler::Word64Shr, "Word64Shr", kArm64Shr, kMachInt64},
    134     {&RawMachineAssembler::Word32Sar, "Word32Sar", kArm64Sar32, kMachInt32},
    135     {&RawMachineAssembler::Word64Sar, "Word64Sar", kArm64Sar, kMachInt64},
    136     {&RawMachineAssembler::Word32Ror, "Word32Ror", kArm64Ror32, kMachInt32},
    137     {&RawMachineAssembler::Word64Ror, "Word64Ror", kArm64Ror, kMachInt64}};
    138 
    139 
    140 // ARM64 Mul/Div instructions.
    141 static const MachInst2 kMulDivInstructions[] = {
    142     {&RawMachineAssembler::Int32Mul, "Int32Mul", kArm64Mul32, kMachInt32},
    143     {&RawMachineAssembler::Int64Mul, "Int64Mul", kArm64Mul, kMachInt64},
    144     {&RawMachineAssembler::Int32Div, "Int32Div", kArm64Idiv32, kMachInt32},
    145     {&RawMachineAssembler::Int64Div, "Int64Div", kArm64Idiv, kMachInt64},
    146     {&RawMachineAssembler::Int32UDiv, "Int32UDiv", kArm64Udiv32, kMachInt32},
    147     {&RawMachineAssembler::Int64UDiv, "Int64UDiv", kArm64Udiv, kMachInt64}};
    148 
    149 
    150 // ARM64 FP arithmetic instructions.
    151 static const MachInst2 kFPArithInstructions[] = {
    152     {&RawMachineAssembler::Float64Add, "Float64Add", kArm64Float64Add,
    153      kMachFloat64},
    154     {&RawMachineAssembler::Float64Sub, "Float64Sub", kArm64Float64Sub,
    155      kMachFloat64},
    156     {&RawMachineAssembler::Float64Mul, "Float64Mul", kArm64Float64Mul,
    157      kMachFloat64},
    158     {&RawMachineAssembler::Float64Div, "Float64Div", kArm64Float64Div,
    159      kMachFloat64}};
    160 
    161 
    162 struct FPCmp {
    163   MachInst2 mi;
    164   FlagsCondition cond;
    165 };
    166 
    167 
    168 std::ostream& operator<<(std::ostream& os, const FPCmp& cmp) {
    169   return os << cmp.mi;
    170 }
    171 
    172 
    173 // ARM64 FP comparison instructions.
    174 static const FPCmp kFPCmpInstructions[] = {
    175     {{&RawMachineAssembler::Float64Equal, "Float64Equal", kArm64Float64Cmp,
    176       kMachFloat64},
    177      kUnorderedEqual},
    178     {{&RawMachineAssembler::Float64LessThan, "Float64LessThan",
    179       kArm64Float64Cmp, kMachFloat64},
    180      kUnorderedLessThan},
    181     {{&RawMachineAssembler::Float64LessThanOrEqual, "Float64LessThanOrEqual",
    182       kArm64Float64Cmp, kMachFloat64},
    183      kUnorderedLessThanOrEqual}};
    184 
    185 
    186 struct Conversion {
    187   // The machine_type field in MachInst1 represents the destination type.
    188   MachInst1 mi;
    189   MachineType src_machine_type;
    190 };
    191 
    192 
    193 std::ostream& operator<<(std::ostream& os, const Conversion& conv) {
    194   return os << conv.mi;
    195 }
    196 
    197 
    198 // ARM64 type conversion instructions.
    199 static const Conversion kConversionInstructions[] = {
    200     {{&RawMachineAssembler::ChangeInt32ToInt64, "ChangeInt32ToInt64",
    201       kArm64Sxtw, kMachInt64},
    202      kMachInt32},
    203     {{&RawMachineAssembler::ChangeUint32ToUint64, "ChangeUint32ToUint64",
    204       kArm64Mov32, kMachUint64},
    205      kMachUint32},
    206     {{&RawMachineAssembler::TruncateInt64ToInt32, "TruncateInt64ToInt32",
    207       kArm64Mov32, kMachInt32},
    208      kMachInt64},
    209     {{&RawMachineAssembler::ChangeInt32ToFloat64, "ChangeInt32ToFloat64",
    210       kArm64Int32ToFloat64, kMachFloat64},
    211      kMachInt32},
    212     {{&RawMachineAssembler::ChangeUint32ToFloat64, "ChangeUint32ToFloat64",
    213       kArm64Uint32ToFloat64, kMachFloat64},
    214      kMachUint32},
    215     {{&RawMachineAssembler::ChangeFloat64ToInt32, "ChangeFloat64ToInt32",
    216       kArm64Float64ToInt32, kMachInt32},
    217      kMachFloat64},
    218     {{&RawMachineAssembler::ChangeFloat64ToUint32, "ChangeFloat64ToUint32",
    219       kArm64Float64ToUint32, kMachUint32},
    220      kMachFloat64}};
    221 
    222 }  // namespace
    223 
    224 
    225 // -----------------------------------------------------------------------------
    226 // Logical instructions.
    227 
    228 
    229 typedef InstructionSelectorTestWithParam<MachInst2>
    230     InstructionSelectorLogicalTest;
    231 
    232 
    233 TEST_P(InstructionSelectorLogicalTest, Parameter) {
    234   const MachInst2 dpi = GetParam();
    235   const MachineType type = dpi.machine_type;
    236   StreamBuilder m(this, type, type, type);
    237   m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)));
    238   Stream s = m.Build();
    239   ASSERT_EQ(1U, s.size());
    240   EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
    241   EXPECT_EQ(2U, s[0]->InputCount());
    242   EXPECT_EQ(1U, s[0]->OutputCount());
    243 }
    244 
    245 
    246 TEST_P(InstructionSelectorLogicalTest, Immediate) {
    247   const MachInst2 dpi = GetParam();
    248   const MachineType type = dpi.machine_type;
    249   // TODO(all): Add support for testing 64-bit immediates.
    250   if (type == kMachInt32) {
    251     // Immediate on the right.
    252     TRACED_FOREACH(int32_t, imm, kLogicalImmediates) {
    253       StreamBuilder m(this, type, type);
    254       m.Return((m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm)));
    255       Stream s = m.Build();
    256       ASSERT_EQ(1U, s.size());
    257       EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
    258       ASSERT_EQ(2U, s[0]->InputCount());
    259       EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
    260       EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
    261       EXPECT_EQ(1U, s[0]->OutputCount());
    262     }
    263 
    264     // Immediate on the left; all logical ops should commute.
    265     TRACED_FOREACH(int32_t, imm, kLogicalImmediates) {
    266       StreamBuilder m(this, type, type);
    267       m.Return((m.*dpi.constructor)(m.Int32Constant(imm), m.Parameter(0)));
    268       Stream s = m.Build();
    269       ASSERT_EQ(1U, s.size());
    270       EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
    271       ASSERT_EQ(2U, s[0]->InputCount());
    272       EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
    273       EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
    274       EXPECT_EQ(1U, s[0]->OutputCount());
    275     }
    276   }
    277 }
    278 
    279 
    280 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorLogicalTest,
    281                         ::testing::ValuesIn(kLogicalInstructions));
    282 
    283 
    284 // -----------------------------------------------------------------------------
    285 // Add and Sub instructions.
    286 
    287 typedef InstructionSelectorTestWithParam<MachInst2>
    288     InstructionSelectorAddSubTest;
    289 
    290 
    291 TEST_P(InstructionSelectorAddSubTest, Parameter) {
    292   const MachInst2 dpi = GetParam();
    293   const MachineType type = dpi.machine_type;
    294   StreamBuilder m(this, type, type, type);
    295   m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)));
    296   Stream s = m.Build();
    297   ASSERT_EQ(1U, s.size());
    298   EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
    299   EXPECT_EQ(2U, s[0]->InputCount());
    300   EXPECT_EQ(1U, s[0]->OutputCount());
    301 }
    302 
    303 
    304 TEST_P(InstructionSelectorAddSubTest, ImmediateOnRight) {
    305   const MachInst2 dpi = GetParam();
    306   const MachineType type = dpi.machine_type;
    307   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
    308     StreamBuilder m(this, type, type);
    309     m.Return((m.*dpi.constructor)(m.Parameter(0), BuildConstant(m, type, imm)));
    310     Stream s = m.Build();
    311     ASSERT_EQ(1U, s.size());
    312     EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
    313     ASSERT_EQ(2U, s[0]->InputCount());
    314     EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
    315     EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(1)));
    316     EXPECT_EQ(1U, s[0]->OutputCount());
    317   }
    318 }
    319 
    320 
    321 TEST_P(InstructionSelectorAddSubTest, ImmediateOnLeft) {
    322   const MachInst2 dpi = GetParam();
    323   const MachineType type = dpi.machine_type;
    324 
    325   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
    326     StreamBuilder m(this, type, type);
    327     m.Return((m.*dpi.constructor)(BuildConstant(m, type, imm), m.Parameter(0)));
    328     Stream s = m.Build();
    329 
    330     // Add can support an immediate on the left by commuting, but Sub can't
    331     // commute. We test zero-on-left Sub later.
    332     if (strstr(dpi.constructor_name, "Add") != NULL) {
    333       ASSERT_EQ(1U, s.size());
    334       EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
    335       ASSERT_EQ(2U, s[0]->InputCount());
    336       EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
    337       EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(1)));
    338       EXPECT_EQ(1U, s[0]->OutputCount());
    339     }
    340   }
    341 }
    342 
    343 
    344 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorAddSubTest,
    345                         ::testing::ValuesIn(kAddSubInstructions));
    346 
    347 
    348 TEST_F(InstructionSelectorTest, SubZeroOnLeft) {
    349   // Subtraction with zero on the left maps to Neg.
    350   {
    351     // 32-bit subtract.
    352     StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
    353     m.Return(m.Int32Sub(m.Int32Constant(0), m.Parameter(0)));
    354     Stream s = m.Build();
    355 
    356     ASSERT_EQ(1U, s.size());
    357     EXPECT_EQ(kArm64Neg32, s[0]->arch_opcode());
    358     EXPECT_EQ(1U, s[0]->InputCount());
    359     EXPECT_EQ(1U, s[0]->OutputCount());
    360   }
    361   {
    362     // 64-bit subtract.
    363     StreamBuilder m(this, kMachInt64, kMachInt64, kMachInt64);
    364     m.Return(m.Int64Sub(m.Int64Constant(0), m.Parameter(0)));
    365     Stream s = m.Build();
    366 
    367     ASSERT_EQ(1U, s.size());
    368     EXPECT_EQ(kArm64Neg, s[0]->arch_opcode());
    369     EXPECT_EQ(1U, s[0]->InputCount());
    370     EXPECT_EQ(1U, s[0]->OutputCount());
    371   }
    372 }
    373 
    374 
    375 // -----------------------------------------------------------------------------
    376 // Data processing controlled branches.
    377 
    378 
    379 typedef InstructionSelectorTestWithParam<MachInst2>
    380     InstructionSelectorDPFlagSetTest;
    381 
    382 
    383 TEST_P(InstructionSelectorDPFlagSetTest, BranchWithParameters) {
    384   const MachInst2 dpi = GetParam();
    385   const MachineType type = dpi.machine_type;
    386   StreamBuilder m(this, type, type, type);
    387   MLabel a, b;
    388   m.Branch((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)), &a, &b);
    389   m.Bind(&a);
    390   m.Return(m.Int32Constant(1));
    391   m.Bind(&b);
    392   m.Return(m.Int32Constant(0));
    393   Stream s = m.Build();
    394   ASSERT_EQ(1U, s.size());
    395   EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
    396   EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
    397   EXPECT_EQ(kNotEqual, s[0]->flags_condition());
    398 }
    399 
    400 
    401 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
    402                         InstructionSelectorDPFlagSetTest,
    403                         ::testing::ValuesIn(kDPFlagSetInstructions));
    404 
    405 
    406 TEST_F(InstructionSelectorTest, AndBranchWithImmediateOnRight) {
    407   TRACED_FOREACH(int32_t, imm, kLogicalImmediates) {
    408     StreamBuilder m(this, kMachInt32, kMachInt32);
    409     MLabel a, b;
    410     m.Branch(m.Word32And(m.Parameter(0), m.Int32Constant(imm)), &a, &b);
    411     m.Bind(&a);
    412     m.Return(m.Int32Constant(1));
    413     m.Bind(&b);
    414     m.Return(m.Int32Constant(0));
    415     Stream s = m.Build();
    416     ASSERT_EQ(1U, s.size());
    417     EXPECT_EQ(kArm64Tst32, s[0]->arch_opcode());
    418     EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
    419     EXPECT_EQ(kNotEqual, s[0]->flags_condition());
    420   }
    421 }
    422 
    423 
    424 TEST_F(InstructionSelectorTest, AddBranchWithImmediateOnRight) {
    425   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
    426     StreamBuilder m(this, kMachInt32, kMachInt32);
    427     MLabel a, b;
    428     m.Branch(m.Int32Add(m.Parameter(0), m.Int32Constant(imm)), &a, &b);
    429     m.Bind(&a);
    430     m.Return(m.Int32Constant(1));
    431     m.Bind(&b);
    432     m.Return(m.Int32Constant(0));
    433     Stream s = m.Build();
    434     ASSERT_EQ(1U, s.size());
    435     EXPECT_EQ(kArm64Cmn32, s[0]->arch_opcode());
    436     EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
    437     EXPECT_EQ(kNotEqual, s[0]->flags_condition());
    438   }
    439 }
    440 
    441 
    442 TEST_F(InstructionSelectorTest, SubBranchWithImmediateOnRight) {
    443   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
    444     StreamBuilder m(this, kMachInt32, kMachInt32);
    445     MLabel a, b;
    446     m.Branch(m.Int32Sub(m.Parameter(0), m.Int32Constant(imm)), &a, &b);
    447     m.Bind(&a);
    448     m.Return(m.Int32Constant(1));
    449     m.Bind(&b);
    450     m.Return(m.Int32Constant(0));
    451     Stream s = m.Build();
    452     ASSERT_EQ(1U, s.size());
    453     EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode());
    454     EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
    455     EXPECT_EQ(kNotEqual, s[0]->flags_condition());
    456   }
    457 }
    458 
    459 
    460 TEST_F(InstructionSelectorTest, AndBranchWithImmediateOnLeft) {
    461   TRACED_FOREACH(int32_t, imm, kLogicalImmediates) {
    462     StreamBuilder m(this, kMachInt32, kMachInt32);
    463     MLabel a, b;
    464     m.Branch(m.Word32And(m.Int32Constant(imm), m.Parameter(0)), &a, &b);
    465     m.Bind(&a);
    466     m.Return(m.Int32Constant(1));
    467     m.Bind(&b);
    468     m.Return(m.Int32Constant(0));
    469     Stream s = m.Build();
    470     ASSERT_EQ(1U, s.size());
    471     EXPECT_EQ(kArm64Tst32, s[0]->arch_opcode());
    472     ASSERT_LE(1U, s[0]->InputCount());
    473     EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
    474     EXPECT_EQ(kNotEqual, s[0]->flags_condition());
    475   }
    476 }
    477 
    478 
    479 TEST_F(InstructionSelectorTest, AddBranchWithImmediateOnLeft) {
    480   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
    481     StreamBuilder m(this, kMachInt32, kMachInt32);
    482     MLabel a, b;
    483     m.Branch(m.Int32Add(m.Int32Constant(imm), m.Parameter(0)), &a, &b);
    484     m.Bind(&a);
    485     m.Return(m.Int32Constant(1));
    486     m.Bind(&b);
    487     m.Return(m.Int32Constant(0));
    488     Stream s = m.Build();
    489     ASSERT_EQ(1U, s.size());
    490     EXPECT_EQ(kArm64Cmn32, s[0]->arch_opcode());
    491     ASSERT_LE(1U, s[0]->InputCount());
    492     EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
    493     EXPECT_EQ(kNotEqual, s[0]->flags_condition());
    494   }
    495 }
    496 
    497 
    498 // -----------------------------------------------------------------------------
    499 // Add and subtract instructions with overflow.
    500 
    501 
    502 typedef InstructionSelectorTestWithParam<MachInst2>
    503     InstructionSelectorOvfAddSubTest;
    504 
    505 
    506 TEST_P(InstructionSelectorOvfAddSubTest, OvfParameter) {
    507   const MachInst2 dpi = GetParam();
    508   const MachineType type = dpi.machine_type;
    509   StreamBuilder m(this, type, type, type);
    510   m.Return(
    511       m.Projection(1, (m.*dpi.constructor)(m.Parameter(0), m.Parameter(1))));
    512   Stream s = m.Build();
    513   ASSERT_EQ(1U, s.size());
    514   EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
    515   EXPECT_EQ(2U, s[0]->InputCount());
    516   EXPECT_LE(1U, s[0]->OutputCount());
    517   EXPECT_EQ(kFlags_set, s[0]->flags_mode());
    518   EXPECT_EQ(kOverflow, s[0]->flags_condition());
    519 }
    520 
    521 
    522 TEST_P(InstructionSelectorOvfAddSubTest, OvfImmediateOnRight) {
    523   const MachInst2 dpi = GetParam();
    524   const MachineType type = dpi.machine_type;
    525   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
    526     StreamBuilder m(this, type, type);
    527     m.Return(m.Projection(
    528         1, (m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm))));
    529     Stream s = m.Build();
    530     ASSERT_EQ(1U, s.size());
    531     EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
    532     ASSERT_EQ(2U, s[0]->InputCount());
    533     EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
    534     EXPECT_LE(1U, s[0]->OutputCount());
    535     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
    536     EXPECT_EQ(kOverflow, s[0]->flags_condition());
    537   }
    538 }
    539 
    540 
    541 TEST_P(InstructionSelectorOvfAddSubTest, ValParameter) {
    542   const MachInst2 dpi = GetParam();
    543   const MachineType type = dpi.machine_type;
    544   StreamBuilder m(this, type, type, type);
    545   m.Return(
    546       m.Projection(0, (m.*dpi.constructor)(m.Parameter(0), m.Parameter(1))));
    547   Stream s = m.Build();
    548   ASSERT_EQ(1U, s.size());
    549   EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
    550   EXPECT_EQ(2U, s[0]->InputCount());
    551   EXPECT_LE(1U, s[0]->OutputCount());
    552   EXPECT_EQ(kFlags_none, s[0]->flags_mode());
    553 }
    554 
    555 
    556 TEST_P(InstructionSelectorOvfAddSubTest, ValImmediateOnRight) {
    557   const MachInst2 dpi = GetParam();
    558   const MachineType type = dpi.machine_type;
    559   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
    560     StreamBuilder m(this, type, type);
    561     m.Return(m.Projection(
    562         0, (m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm))));
    563     Stream s = m.Build();
    564     ASSERT_EQ(1U, s.size());
    565     EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
    566     ASSERT_EQ(2U, s[0]->InputCount());
    567     EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
    568     EXPECT_LE(1U, s[0]->OutputCount());
    569     EXPECT_EQ(kFlags_none, s[0]->flags_mode());
    570   }
    571 }
    572 
    573 
    574 TEST_P(InstructionSelectorOvfAddSubTest, BothParameter) {
    575   const MachInst2 dpi = GetParam();
    576   const MachineType type = dpi.machine_type;
    577   StreamBuilder m(this, type, type, type);
    578   Node* n = (m.*dpi.constructor)(m.Parameter(0), m.Parameter(1));
    579   m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n)));
    580   Stream s = m.Build();
    581   ASSERT_LE(1U, s.size());
    582   EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
    583   EXPECT_EQ(2U, s[0]->InputCount());
    584   EXPECT_EQ(2U, s[0]->OutputCount());
    585   EXPECT_EQ(kFlags_set, s[0]->flags_mode());
    586   EXPECT_EQ(kOverflow, s[0]->flags_condition());
    587 }
    588 
    589 
    590 TEST_P(InstructionSelectorOvfAddSubTest, BothImmediateOnRight) {
    591   const MachInst2 dpi = GetParam();
    592   const MachineType type = dpi.machine_type;
    593   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
    594     StreamBuilder m(this, type, type);
    595     Node* n = (m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm));
    596     m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n)));
    597     Stream s = m.Build();
    598     ASSERT_LE(1U, s.size());
    599     EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
    600     ASSERT_EQ(2U, s[0]->InputCount());
    601     EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
    602     EXPECT_EQ(2U, s[0]->OutputCount());
    603     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
    604     EXPECT_EQ(kOverflow, s[0]->flags_condition());
    605   }
    606 }
    607 
    608 
    609 TEST_P(InstructionSelectorOvfAddSubTest, BranchWithParameters) {
    610   const MachInst2 dpi = GetParam();
    611   const MachineType type = dpi.machine_type;
    612   StreamBuilder m(this, type, type, type);
    613   MLabel a, b;
    614   Node* n = (m.*dpi.constructor)(m.Parameter(0), m.Parameter(1));
    615   m.Branch(m.Projection(1, n), &a, &b);
    616   m.Bind(&a);
    617   m.Return(m.Int32Constant(0));
    618   m.Bind(&b);
    619   m.Return(m.Projection(0, n));
    620   Stream s = m.Build();
    621   ASSERT_EQ(1U, s.size());
    622   EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
    623   EXPECT_EQ(4U, s[0]->InputCount());
    624   EXPECT_EQ(1U, s[0]->OutputCount());
    625   EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
    626   EXPECT_EQ(kOverflow, s[0]->flags_condition());
    627 }
    628 
    629 
    630 TEST_P(InstructionSelectorOvfAddSubTest, BranchWithImmediateOnRight) {
    631   const MachInst2 dpi = GetParam();
    632   const MachineType type = dpi.machine_type;
    633   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
    634     StreamBuilder m(this, type, type);
    635     MLabel a, b;
    636     Node* n = (m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm));
    637     m.Branch(m.Projection(1, n), &a, &b);
    638     m.Bind(&a);
    639     m.Return(m.Int32Constant(0));
    640     m.Bind(&b);
    641     m.Return(m.Projection(0, n));
    642     Stream s = m.Build();
    643     ASSERT_EQ(1U, s.size());
    644     EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
    645     ASSERT_EQ(4U, s[0]->InputCount());
    646     EXPECT_EQ(1U, s[0]->OutputCount());
    647     EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
    648     EXPECT_EQ(kOverflow, s[0]->flags_condition());
    649   }
    650 }
    651 
    652 
    653 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
    654                         InstructionSelectorOvfAddSubTest,
    655                         ::testing::ValuesIn(kOvfAddSubInstructions));
    656 
    657 
    658 TEST_F(InstructionSelectorTest, OvfFlagAddImmediateOnLeft) {
    659   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
    660     StreamBuilder m(this, kMachInt32, kMachInt32);
    661     m.Return(m.Projection(
    662         1, m.Int32AddWithOverflow(m.Int32Constant(imm), m.Parameter(0))));
    663     Stream s = m.Build();
    664 
    665     ASSERT_EQ(1U, s.size());
    666     EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
    667     EXPECT_EQ(2U, s[0]->InputCount());
    668     EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
    669     EXPECT_LE(1U, s[0]->OutputCount());
    670     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
    671     EXPECT_EQ(kOverflow, s[0]->flags_condition());
    672   }
    673 }
    674 
    675 
    676 TEST_F(InstructionSelectorTest, OvfValAddImmediateOnLeft) {
    677   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
    678     StreamBuilder m(this, kMachInt32, kMachInt32);
    679     m.Return(m.Projection(
    680         0, m.Int32AddWithOverflow(m.Int32Constant(imm), m.Parameter(0))));
    681     Stream s = m.Build();
    682 
    683     ASSERT_EQ(1U, s.size());
    684     EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
    685     ASSERT_EQ(2U, s[0]->InputCount());
    686     EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
    687     EXPECT_LE(1U, s[0]->OutputCount());
    688     EXPECT_EQ(kFlags_none, s[0]->flags_mode());
    689   }
    690 }
    691 
    692 
    693 TEST_F(InstructionSelectorTest, OvfBothAddImmediateOnLeft) {
    694   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
    695     StreamBuilder m(this, kMachInt32, kMachInt32);
    696     Node* n = m.Int32AddWithOverflow(m.Int32Constant(imm), m.Parameter(0));
    697     m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n)));
    698     Stream s = m.Build();
    699 
    700     ASSERT_LE(1U, s.size());
    701     EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
    702     ASSERT_EQ(2U, s[0]->InputCount());
    703     EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
    704     EXPECT_EQ(2U, s[0]->OutputCount());
    705     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
    706     EXPECT_EQ(kOverflow, s[0]->flags_condition());
    707   }
    708 }
    709 
    710 
    711 TEST_F(InstructionSelectorTest, OvfBranchWithImmediateOnLeft) {
    712   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
    713     StreamBuilder m(this, kMachInt32, kMachInt32);
    714     MLabel a, b;
    715     Node* n = m.Int32AddWithOverflow(m.Int32Constant(imm), m.Parameter(0));
    716     m.Branch(m.Projection(1, n), &a, &b);
    717     m.Bind(&a);
    718     m.Return(m.Int32Constant(0));
    719     m.Bind(&b);
    720     m.Return(m.Projection(0, n));
    721     Stream s = m.Build();
    722 
    723     ASSERT_EQ(1U, s.size());
    724     EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
    725     ASSERT_EQ(4U, s[0]->InputCount());
    726     EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
    727     EXPECT_EQ(1U, s[0]->OutputCount());
    728     EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
    729     EXPECT_EQ(kOverflow, s[0]->flags_condition());
    730   }
    731 }
    732 
    733 
    734 // -----------------------------------------------------------------------------
    735 // Shift instructions.
    736 
    737 
    738 typedef InstructionSelectorTestWithParam<MachInst2>
    739     InstructionSelectorShiftTest;
    740 
    741 
    742 TEST_P(InstructionSelectorShiftTest, Parameter) {
    743   const MachInst2 dpi = GetParam();
    744   const MachineType type = dpi.machine_type;
    745   StreamBuilder m(this, type, type, type);
    746   m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)));
    747   Stream s = m.Build();
    748   ASSERT_EQ(1U, s.size());
    749   EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
    750   EXPECT_EQ(2U, s[0]->InputCount());
    751   EXPECT_EQ(1U, s[0]->OutputCount());
    752 }
    753 
    754 
    755 TEST_P(InstructionSelectorShiftTest, Immediate) {
    756   const MachInst2 dpi = GetParam();
    757   const MachineType type = dpi.machine_type;
    758   TRACED_FORRANGE(int32_t, imm, 0, (ElementSizeOf(type) * 8) - 1) {
    759     StreamBuilder m(this, type, type);
    760     m.Return((m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm)));
    761     Stream s = m.Build();
    762     ASSERT_EQ(1U, s.size());
    763     EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
    764     EXPECT_EQ(2U, s[0]->InputCount());
    765     EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
    766     EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
    767     EXPECT_EQ(1U, s[0]->OutputCount());
    768   }
    769 }
    770 
    771 
    772 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorShiftTest,
    773                         ::testing::ValuesIn(kShiftInstructions));
    774 
    775 
    776 // -----------------------------------------------------------------------------
    777 // Mul and Div instructions.
    778 
    779 
    780 typedef InstructionSelectorTestWithParam<MachInst2>
    781     InstructionSelectorMulDivTest;
    782 
    783 
    784 TEST_P(InstructionSelectorMulDivTest, Parameter) {
    785   const MachInst2 dpi = GetParam();
    786   const MachineType type = dpi.machine_type;
    787   StreamBuilder m(this, type, type, type);
    788   m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)));
    789   Stream s = m.Build();
    790   ASSERT_EQ(1U, s.size());
    791   EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
    792   EXPECT_EQ(2U, s[0]->InputCount());
    793   EXPECT_EQ(1U, s[0]->OutputCount());
    794 }
    795 
    796 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorMulDivTest,
    797                         ::testing::ValuesIn(kMulDivInstructions));
    798 
    799 
    800 // -----------------------------------------------------------------------------
    801 // Floating point instructions.
    802 
    803 typedef InstructionSelectorTestWithParam<MachInst2>
    804     InstructionSelectorFPArithTest;
    805 
    806 
    807 TEST_P(InstructionSelectorFPArithTest, Parameter) {
    808   const MachInst2 fpa = GetParam();
    809   StreamBuilder m(this, fpa.machine_type, fpa.machine_type, fpa.machine_type);
    810   m.Return((m.*fpa.constructor)(m.Parameter(0), m.Parameter(1)));
    811   Stream s = m.Build();
    812   ASSERT_EQ(1U, s.size());
    813   EXPECT_EQ(fpa.arch_opcode, s[0]->arch_opcode());
    814   EXPECT_EQ(2U, s[0]->InputCount());
    815   EXPECT_EQ(1U, s[0]->OutputCount());
    816 }
    817 
    818 
    819 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorFPArithTest,
    820                         ::testing::ValuesIn(kFPArithInstructions));
    821 
    822 
    823 typedef InstructionSelectorTestWithParam<FPCmp> InstructionSelectorFPCmpTest;
    824 
    825 
    826 TEST_P(InstructionSelectorFPCmpTest, Parameter) {
    827   const FPCmp cmp = GetParam();
    828   StreamBuilder m(this, kMachInt32, cmp.mi.machine_type, cmp.mi.machine_type);
    829   m.Return((m.*cmp.mi.constructor)(m.Parameter(0), m.Parameter(1)));
    830   Stream s = m.Build();
    831   ASSERT_EQ(1U, s.size());
    832   EXPECT_EQ(cmp.mi.arch_opcode, s[0]->arch_opcode());
    833   EXPECT_EQ(2U, s[0]->InputCount());
    834   EXPECT_EQ(1U, s[0]->OutputCount());
    835   EXPECT_EQ(kFlags_set, s[0]->flags_mode());
    836   EXPECT_EQ(cmp.cond, s[0]->flags_condition());
    837 }
    838 
    839 
    840 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorFPCmpTest,
    841                         ::testing::ValuesIn(kFPCmpInstructions));
    842 
    843 
    844 // -----------------------------------------------------------------------------
    845 // Conversions.
    846 
    847 typedef InstructionSelectorTestWithParam<Conversion>
    848     InstructionSelectorConversionTest;
    849 
    850 
    851 TEST_P(InstructionSelectorConversionTest, Parameter) {
    852   const Conversion conv = GetParam();
    853   StreamBuilder m(this, conv.mi.machine_type, conv.src_machine_type);
    854   m.Return((m.*conv.mi.constructor)(m.Parameter(0)));
    855   Stream s = m.Build();
    856   ASSERT_EQ(1U, s.size());
    857   EXPECT_EQ(conv.mi.arch_opcode, s[0]->arch_opcode());
    858   EXPECT_EQ(1U, s[0]->InputCount());
    859   EXPECT_EQ(1U, s[0]->OutputCount());
    860 }
    861 
    862 
    863 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
    864                         InstructionSelectorConversionTest,
    865                         ::testing::ValuesIn(kConversionInstructions));
    866 
    867 
    868 // -----------------------------------------------------------------------------
    869 // Memory access instructions.
    870 
    871 
    872 namespace {
    873 
    874 struct MemoryAccess {
    875   MachineType type;
    876   ArchOpcode ldr_opcode;
    877   ArchOpcode str_opcode;
    878   const int32_t immediates[20];
    879 };
    880 
    881 
    882 std::ostream& operator<<(std::ostream& os, const MemoryAccess& memacc) {
    883   OStringStream ost;
    884   ost << memacc.type;
    885   return os << ost.c_str();
    886 }
    887 
    888 }  // namespace
    889 
    890 
    891 static const MemoryAccess kMemoryAccesses[] = {
    892     {kMachInt8, kArm64Ldrsb, kArm64Strb,
    893      {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 257, 258, 1000, 1001,
    894       2121, 2442, 4093, 4094, 4095}},
    895     {kMachUint8, kArm64Ldrb, kArm64Strb,
    896      {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 257, 258, 1000, 1001,
    897       2121, 2442, 4093, 4094, 4095}},
    898     {kMachInt16, kArm64Ldrsh, kArm64Strh,
    899      {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 258, 260, 4096, 4098,
    900       4100, 4242, 6786, 8188, 8190}},
    901     {kMachUint16, kArm64Ldrh, kArm64Strh,
    902      {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 258, 260, 4096, 4098,
    903       4100, 4242, 6786, 8188, 8190}},
    904     {kMachInt32, kArm64LdrW, kArm64StrW,
    905      {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 260, 4096, 4100, 8192,
    906       8196, 3276, 3280, 16376, 16380}},
    907     {kMachUint32, kArm64LdrW, kArm64StrW,
    908      {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 260, 4096, 4100, 8192,
    909       8196, 3276, 3280, 16376, 16380}},
    910     {kMachInt64, kArm64Ldr, kArm64Str,
    911      {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 264, 4096, 4104, 8192,
    912       8200, 16384, 16392, 32752, 32760}},
    913     {kMachUint64, kArm64Ldr, kArm64Str,
    914      {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 264, 4096, 4104, 8192,
    915       8200, 16384, 16392, 32752, 32760}},
    916     {kMachFloat32, kArm64LdrS, kArm64StrS,
    917      {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 260, 4096, 4100, 8192,
    918       8196, 3276, 3280, 16376, 16380}},
    919     {kMachFloat64, kArm64LdrD, kArm64StrD,
    920      {-256, -255, -3, -2, -1, 0, 1, 2, 3, 255, 256, 264, 4096, 4104, 8192,
    921       8200, 16384, 16392, 32752, 32760}}};
    922 
    923 
    924 typedef InstructionSelectorTestWithParam<MemoryAccess>
    925     InstructionSelectorMemoryAccessTest;
    926 
    927 
    928 TEST_P(InstructionSelectorMemoryAccessTest, LoadWithParameters) {
    929   const MemoryAccess memacc = GetParam();
    930   StreamBuilder m(this, memacc.type, kMachPtr, kMachInt32);
    931   m.Return(m.Load(memacc.type, m.Parameter(0), m.Parameter(1)));
    932   Stream s = m.Build();
    933   ASSERT_EQ(1U, s.size());
    934   EXPECT_EQ(memacc.ldr_opcode, s[0]->arch_opcode());
    935   EXPECT_EQ(kMode_MRR, s[0]->addressing_mode());
    936   EXPECT_EQ(2U, s[0]->InputCount());
    937   EXPECT_EQ(1U, s[0]->OutputCount());
    938 }
    939 
    940 
    941 TEST_P(InstructionSelectorMemoryAccessTest, LoadWithImmediateIndex) {
    942   const MemoryAccess memacc = GetParam();
    943   TRACED_FOREACH(int32_t, index, memacc.immediates) {
    944     StreamBuilder m(this, memacc.type, kMachPtr);
    945     m.Return(m.Load(memacc.type, m.Parameter(0), m.Int32Constant(index)));
    946     Stream s = m.Build();
    947     ASSERT_EQ(1U, s.size());
    948     EXPECT_EQ(memacc.ldr_opcode, s[0]->arch_opcode());
    949     EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
    950     EXPECT_EQ(2U, s[0]->InputCount());
    951     ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
    952     EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1)));
    953     ASSERT_EQ(1U, s[0]->OutputCount());
    954   }
    955 }
    956 
    957 
    958 TEST_P(InstructionSelectorMemoryAccessTest, StoreWithParameters) {
    959   const MemoryAccess memacc = GetParam();
    960   StreamBuilder m(this, kMachInt32, kMachPtr, kMachInt32, memacc.type);
    961   m.Store(memacc.type, m.Parameter(0), m.Parameter(1), m.Parameter(2));
    962   m.Return(m.Int32Constant(0));
    963   Stream s = m.Build();
    964   ASSERT_EQ(1U, s.size());
    965   EXPECT_EQ(memacc.str_opcode, s[0]->arch_opcode());
    966   EXPECT_EQ(kMode_MRR, s[0]->addressing_mode());
    967   EXPECT_EQ(3U, s[0]->InputCount());
    968   EXPECT_EQ(0U, s[0]->OutputCount());
    969 }
    970 
    971 
    972 TEST_P(InstructionSelectorMemoryAccessTest, StoreWithImmediateIndex) {
    973   const MemoryAccess memacc = GetParam();
    974   TRACED_FOREACH(int32_t, index, memacc.immediates) {
    975     StreamBuilder m(this, kMachInt32, kMachPtr, memacc.type);
    976     m.Store(memacc.type, m.Parameter(0), m.Int32Constant(index),
    977             m.Parameter(1));
    978     m.Return(m.Int32Constant(0));
    979     Stream s = m.Build();
    980     ASSERT_EQ(1U, s.size());
    981     EXPECT_EQ(memacc.str_opcode, s[0]->arch_opcode());
    982     EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
    983     ASSERT_EQ(3U, s[0]->InputCount());
    984     ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
    985     EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1)));
    986     EXPECT_EQ(0U, s[0]->OutputCount());
    987   }
    988 }
    989 
    990 
    991 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
    992                         InstructionSelectorMemoryAccessTest,
    993                         ::testing::ValuesIn(kMemoryAccesses));
    994 
    995 
    996 // -----------------------------------------------------------------------------
    997 // Comparison instructions.
    998 
    999 static const MachInst2 kComparisonInstructions[] = {
   1000     {&RawMachineAssembler::Word32Equal, "Word32Equal", kArm64Cmp32, kMachInt32},
   1001     {&RawMachineAssembler::Word64Equal, "Word64Equal", kArm64Cmp, kMachInt64},
   1002 };
   1003 
   1004 
   1005 typedef InstructionSelectorTestWithParam<MachInst2>
   1006     InstructionSelectorComparisonTest;
   1007 
   1008 
   1009 TEST_P(InstructionSelectorComparisonTest, WithParameters) {
   1010   const MachInst2 cmp = GetParam();
   1011   const MachineType type = cmp.machine_type;
   1012   StreamBuilder m(this, type, type, type);
   1013   m.Return((m.*cmp.constructor)(m.Parameter(0), m.Parameter(1)));
   1014   Stream s = m.Build();
   1015   ASSERT_EQ(1U, s.size());
   1016   EXPECT_EQ(cmp.arch_opcode, s[0]->arch_opcode());
   1017   EXPECT_EQ(2U, s[0]->InputCount());
   1018   EXPECT_EQ(1U, s[0]->OutputCount());
   1019   EXPECT_EQ(kFlags_set, s[0]->flags_mode());
   1020   EXPECT_EQ(kEqual, s[0]->flags_condition());
   1021 }
   1022 
   1023 
   1024 TEST_P(InstructionSelectorComparisonTest, WithImmediate) {
   1025   const MachInst2 cmp = GetParam();
   1026   const MachineType type = cmp.machine_type;
   1027   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
   1028     // Compare with 0 are turned into tst instruction.
   1029     if (imm == 0) continue;
   1030     StreamBuilder m(this, type, type);
   1031     m.Return((m.*cmp.constructor)(m.Parameter(0), BuildConstant(m, type, imm)));
   1032     Stream s = m.Build();
   1033     ASSERT_EQ(1U, s.size());
   1034     EXPECT_EQ(cmp.arch_opcode, s[0]->arch_opcode());
   1035     ASSERT_EQ(2U, s[0]->InputCount());
   1036     ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
   1037     EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(1)));
   1038     EXPECT_EQ(1U, s[0]->OutputCount());
   1039     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
   1040     EXPECT_EQ(kEqual, s[0]->flags_condition());
   1041   }
   1042   TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
   1043     // Compare with 0 are turned into tst instruction.
   1044     if (imm == 0) continue;
   1045     StreamBuilder m(this, type, type);
   1046     m.Return((m.*cmp.constructor)(m.Parameter(0), BuildConstant(m, type, imm)));
   1047     Stream s = m.Build();
   1048     ASSERT_EQ(1U, s.size());
   1049     EXPECT_EQ(cmp.arch_opcode, s[0]->arch_opcode());
   1050     ASSERT_EQ(2U, s[0]->InputCount());
   1051     ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
   1052     EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(1)));
   1053     EXPECT_EQ(1U, s[0]->OutputCount());
   1054     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
   1055     EXPECT_EQ(kEqual, s[0]->flags_condition());
   1056   }
   1057 }
   1058 
   1059 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
   1060                         InstructionSelectorComparisonTest,
   1061                         ::testing::ValuesIn(kComparisonInstructions));
   1062 
   1063 
   1064 TEST_F(InstructionSelectorTest, Word32EqualWithZero) {
   1065   {
   1066     StreamBuilder m(this, kMachInt32, kMachInt32);
   1067     m.Return(m.Word32Equal(m.Parameter(0), m.Int32Constant(0)));
   1068     Stream s = m.Build();
   1069     ASSERT_EQ(1U, s.size());
   1070     EXPECT_EQ(kArm64Tst32, s[0]->arch_opcode());
   1071     ASSERT_EQ(2U, s[0]->InputCount());
   1072     EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
   1073     EXPECT_EQ(1U, s[0]->OutputCount());
   1074     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
   1075     EXPECT_EQ(kEqual, s[0]->flags_condition());
   1076   }
   1077   {
   1078     StreamBuilder m(this, kMachInt32, kMachInt32);
   1079     m.Return(m.Word32Equal(m.Int32Constant(0), m.Parameter(0)));
   1080     Stream s = m.Build();
   1081     ASSERT_EQ(1U, s.size());
   1082     EXPECT_EQ(kArm64Tst32, s[0]->arch_opcode());
   1083     ASSERT_EQ(2U, s[0]->InputCount());
   1084     EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
   1085     EXPECT_EQ(1U, s[0]->OutputCount());
   1086     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
   1087     EXPECT_EQ(kEqual, s[0]->flags_condition());
   1088   }
   1089 }
   1090 
   1091 
   1092 TEST_F(InstructionSelectorTest, Word64EqualWithZero) {
   1093   {
   1094     StreamBuilder m(this, kMachInt64, kMachInt64);
   1095     m.Return(m.Word64Equal(m.Parameter(0), m.Int64Constant(0)));
   1096     Stream s = m.Build();
   1097     ASSERT_EQ(1U, s.size());
   1098     EXPECT_EQ(kArm64Tst, s[0]->arch_opcode());
   1099     ASSERT_EQ(2U, s[0]->InputCount());
   1100     EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
   1101     EXPECT_EQ(1U, s[0]->OutputCount());
   1102     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
   1103     EXPECT_EQ(kEqual, s[0]->flags_condition());
   1104   }
   1105   {
   1106     StreamBuilder m(this, kMachInt64, kMachInt64);
   1107     m.Return(m.Word64Equal(m.Int64Constant(0), m.Parameter(0)));
   1108     Stream s = m.Build();
   1109     ASSERT_EQ(1U, s.size());
   1110     EXPECT_EQ(kArm64Tst, s[0]->arch_opcode());
   1111     ASSERT_EQ(2U, s[0]->InputCount());
   1112     EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
   1113     EXPECT_EQ(1U, s[0]->OutputCount());
   1114     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
   1115     EXPECT_EQ(kEqual, s[0]->flags_condition());
   1116   }
   1117 }
   1118 
   1119 }  // namespace compiler
   1120 }  // namespace internal
   1121 }  // namespace v8
   1122