Home | History | Annotate | Download | only in ia32
      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 "src/compiler/instruction-selector-unittest.h"
      6 
      7 namespace v8 {
      8 namespace internal {
      9 namespace compiler {
     10 
     11 namespace {
     12 
     13 // Immediates (random subset).
     14 static const int32_t kImmediates[] = {
     15     kMinInt, -42, -1, 0,  1,  2,    3,      4,          5,
     16     6,       7,   8,  16, 42, 0xff, 0xffff, 0x0f0f0f0f, kMaxInt};
     17 
     18 }  // namespace
     19 
     20 
     21 TEST_F(InstructionSelectorTest, Int32AddWithParameter) {
     22   StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
     23   m.Return(m.Int32Add(m.Parameter(0), m.Parameter(1)));
     24   Stream s = m.Build();
     25   ASSERT_EQ(1U, s.size());
     26   EXPECT_EQ(kIA32Add, s[0]->arch_opcode());
     27 }
     28 
     29 
     30 TEST_F(InstructionSelectorTest, Int32AddWithImmediate) {
     31   TRACED_FOREACH(int32_t, imm, kImmediates) {
     32     {
     33       StreamBuilder m(this, kMachInt32, kMachInt32);
     34       m.Return(m.Int32Add(m.Parameter(0), m.Int32Constant(imm)));
     35       Stream s = m.Build();
     36       ASSERT_EQ(1U, s.size());
     37       EXPECT_EQ(kIA32Add, s[0]->arch_opcode());
     38       ASSERT_EQ(2U, s[0]->InputCount());
     39       EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
     40     }
     41     {
     42       StreamBuilder m(this, kMachInt32, kMachInt32);
     43       m.Return(m.Int32Add(m.Int32Constant(imm), m.Parameter(0)));
     44       Stream s = m.Build();
     45       ASSERT_EQ(1U, s.size());
     46       EXPECT_EQ(kIA32Add, s[0]->arch_opcode());
     47       ASSERT_EQ(2U, s[0]->InputCount());
     48       EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
     49     }
     50   }
     51 }
     52 
     53 
     54 TEST_F(InstructionSelectorTest, Int32SubWithParameter) {
     55   StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
     56   m.Return(m.Int32Sub(m.Parameter(0), m.Parameter(1)));
     57   Stream s = m.Build();
     58   ASSERT_EQ(1U, s.size());
     59   EXPECT_EQ(kIA32Sub, s[0]->arch_opcode());
     60   EXPECT_EQ(1U, s[0]->OutputCount());
     61 }
     62 
     63 
     64 TEST_F(InstructionSelectorTest, Int32SubWithImmediate) {
     65   TRACED_FOREACH(int32_t, imm, kImmediates) {
     66     StreamBuilder m(this, kMachInt32, kMachInt32);
     67     m.Return(m.Int32Sub(m.Parameter(0), m.Int32Constant(imm)));
     68     Stream s = m.Build();
     69     ASSERT_EQ(1U, s.size());
     70     EXPECT_EQ(kIA32Sub, s[0]->arch_opcode());
     71     ASSERT_EQ(2U, s[0]->InputCount());
     72     EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
     73   }
     74 }
     75 
     76 
     77 // -----------------------------------------------------------------------------
     78 // Loads and stores
     79 
     80 namespace {
     81 
     82 struct MemoryAccess {
     83   MachineType type;
     84   ArchOpcode load_opcode;
     85   ArchOpcode store_opcode;
     86 };
     87 
     88 
     89 std::ostream& operator<<(std::ostream& os, const MemoryAccess& memacc) {
     90   OStringStream ost;
     91   ost << memacc.type;
     92   return os << ost.c_str();
     93 }
     94 
     95 
     96 static const MemoryAccess kMemoryAccesses[] = {
     97     {kMachInt8, kIA32Movsxbl, kIA32Movb},
     98     {kMachUint8, kIA32Movzxbl, kIA32Movb},
     99     {kMachInt16, kIA32Movsxwl, kIA32Movw},
    100     {kMachUint16, kIA32Movzxwl, kIA32Movw},
    101     {kMachInt32, kIA32Movl, kIA32Movl},
    102     {kMachUint32, kIA32Movl, kIA32Movl},
    103     {kMachFloat32, kIA32Movss, kIA32Movss},
    104     {kMachFloat64, kIA32Movsd, kIA32Movsd}};
    105 
    106 }  // namespace
    107 
    108 
    109 typedef InstructionSelectorTestWithParam<MemoryAccess>
    110     InstructionSelectorMemoryAccessTest;
    111 
    112 
    113 TEST_P(InstructionSelectorMemoryAccessTest, LoadWithParameters) {
    114   const MemoryAccess memacc = GetParam();
    115   StreamBuilder m(this, memacc.type, kMachPtr, kMachInt32);
    116   m.Return(m.Load(memacc.type, m.Parameter(0), m.Parameter(1)));
    117   Stream s = m.Build();
    118   ASSERT_EQ(1U, s.size());
    119   EXPECT_EQ(memacc.load_opcode, s[0]->arch_opcode());
    120   EXPECT_EQ(2U, s[0]->InputCount());
    121   EXPECT_EQ(1U, s[0]->OutputCount());
    122 }
    123 
    124 
    125 TEST_P(InstructionSelectorMemoryAccessTest, LoadWithImmediateBase) {
    126   const MemoryAccess memacc = GetParam();
    127   TRACED_FOREACH(int32_t, base, kImmediates) {
    128     StreamBuilder m(this, memacc.type, kMachPtr);
    129     m.Return(m.Load(memacc.type, m.Int32Constant(base), m.Parameter(0)));
    130     Stream s = m.Build();
    131     ASSERT_EQ(1U, s.size());
    132     EXPECT_EQ(memacc.load_opcode, s[0]->arch_opcode());
    133     ASSERT_EQ(2U, s[0]->InputCount());
    134     ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
    135     EXPECT_EQ(base, s.ToInt32(s[0]->InputAt(1)));
    136     EXPECT_EQ(1U, s[0]->OutputCount());
    137   }
    138 }
    139 
    140 
    141 TEST_P(InstructionSelectorMemoryAccessTest, LoadWithImmediateIndex) {
    142   const MemoryAccess memacc = GetParam();
    143   TRACED_FOREACH(int32_t, index, kImmediates) {
    144     StreamBuilder m(this, memacc.type, kMachPtr);
    145     m.Return(m.Load(memacc.type, m.Parameter(0), m.Int32Constant(index)));
    146     Stream s = m.Build();
    147     ASSERT_EQ(1U, s.size());
    148     EXPECT_EQ(memacc.load_opcode, s[0]->arch_opcode());
    149     ASSERT_EQ(2U, s[0]->InputCount());
    150     ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
    151     EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1)));
    152     EXPECT_EQ(1U, s[0]->OutputCount());
    153   }
    154 }
    155 
    156 
    157 TEST_P(InstructionSelectorMemoryAccessTest, StoreWithParameters) {
    158   const MemoryAccess memacc = GetParam();
    159   StreamBuilder m(this, kMachInt32, kMachPtr, kMachInt32, memacc.type);
    160   m.Store(memacc.type, m.Parameter(0), m.Parameter(1), m.Parameter(2));
    161   m.Return(m.Int32Constant(0));
    162   Stream s = m.Build();
    163   ASSERT_EQ(1U, s.size());
    164   EXPECT_EQ(memacc.store_opcode, s[0]->arch_opcode());
    165   EXPECT_EQ(3U, s[0]->InputCount());
    166   EXPECT_EQ(0U, s[0]->OutputCount());
    167 }
    168 
    169 
    170 TEST_P(InstructionSelectorMemoryAccessTest, StoreWithImmediateBase) {
    171   const MemoryAccess memacc = GetParam();
    172   TRACED_FOREACH(int32_t, base, kImmediates) {
    173     StreamBuilder m(this, kMachInt32, kMachInt32, memacc.type);
    174     m.Store(memacc.type, m.Int32Constant(base), m.Parameter(0), m.Parameter(1));
    175     m.Return(m.Int32Constant(0));
    176     Stream s = m.Build();
    177     ASSERT_EQ(1U, s.size());
    178     EXPECT_EQ(memacc.store_opcode, s[0]->arch_opcode());
    179     ASSERT_EQ(3U, s[0]->InputCount());
    180     ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
    181     EXPECT_EQ(base, s.ToInt32(s[0]->InputAt(1)));
    182     EXPECT_EQ(0U, s[0]->OutputCount());
    183   }
    184 }
    185 
    186 
    187 TEST_P(InstructionSelectorMemoryAccessTest, StoreWithImmediateIndex) {
    188   const MemoryAccess memacc = GetParam();
    189   TRACED_FOREACH(int32_t, index, kImmediates) {
    190     StreamBuilder m(this, kMachInt32, kMachPtr, memacc.type);
    191     m.Store(memacc.type, m.Parameter(0), m.Int32Constant(index),
    192             m.Parameter(1));
    193     m.Return(m.Int32Constant(0));
    194     Stream s = m.Build();
    195     ASSERT_EQ(1U, s.size());
    196     EXPECT_EQ(memacc.store_opcode, s[0]->arch_opcode());
    197     ASSERT_EQ(3U, s[0]->InputCount());
    198     ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
    199     EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1)));
    200     EXPECT_EQ(0U, s[0]->OutputCount());
    201   }
    202 }
    203 
    204 
    205 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
    206                         InstructionSelectorMemoryAccessTest,
    207                         ::testing::ValuesIn(kMemoryAccesses));
    208 
    209 }  // namespace compiler
    210 }  // namespace internal
    211 }  // namespace v8
    212