| OLD | NEW | 
|---|
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 | 4 | 
| 5 #include "test/unittests/compiler/instruction-selector-unittest.h" | 5 #include "test/unittests/compiler/instruction-selector-unittest.h" | 
| 6 | 6 | 
| 7 namespace v8 { | 7 namespace v8 { | 
| 8 namespace internal { | 8 namespace internal { | 
| 9 namespace compiler { | 9 namespace compiler { | 
| 10 | 10 | 
| 11 namespace { | 11 namespace { | 
| 12 | 12 | 
| 13 // Immediates (random subset). | 13 // Immediates (random subset). | 
| 14 const int32_t kImmediates[] = {kMinInt, -42, -1,   0,      1,          2, | 14 const int32_t kImmediates[] = {kMinInt, -42, -1,   0,      1,          2, | 
| 15                                3,       4,   5,    6,      7,          8, | 15                                3,       4,   5,    6,      7,          8, | 
| 16                                16,      42,  0xff, 0xffff, 0x0f0f0f0f, kMaxInt}; | 16                                16,      42,  0xff, 0xffff, 0x0f0f0f0f, kMaxInt}; | 
| 17 | 17 | 
| 18 }  // namespace | 18 }  // namespace | 
| 19 | 19 | 
| 20 | 20 | 
| 21 TEST_F(InstructionSelectorTest, Int32AddWithParameter) { | 21 TEST_F(InstructionSelectorTest, Int32AddWithParameter) { | 
| 22   StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); | 22   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), | 
|  | 23                   MachineType::Int32()); | 
| 23   m.Return(m.Int32Add(m.Parameter(0), m.Parameter(1))); | 24   m.Return(m.Int32Add(m.Parameter(0), m.Parameter(1))); | 
| 24   Stream s = m.Build(); | 25   Stream s = m.Build(); | 
| 25   ASSERT_EQ(1U, s.size()); | 26   ASSERT_EQ(1U, s.size()); | 
| 26   EXPECT_EQ(kIA32Lea, s[0]->arch_opcode()); | 27   EXPECT_EQ(kIA32Lea, s[0]->arch_opcode()); | 
| 27 } | 28 } | 
| 28 | 29 | 
| 29 | 30 | 
| 30 TEST_F(InstructionSelectorTest, Int32AddWithImmediate) { | 31 TEST_F(InstructionSelectorTest, Int32AddWithImmediate) { | 
| 31   TRACED_FOREACH(int32_t, imm, kImmediates) { | 32   TRACED_FOREACH(int32_t, imm, kImmediates) { | 
| 32     { | 33     { | 
| 33       StreamBuilder m(this, kMachInt32, kMachInt32); | 34       StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); | 
| 34       m.Return(m.Int32Add(m.Parameter(0), m.Int32Constant(imm))); | 35       m.Return(m.Int32Add(m.Parameter(0), m.Int32Constant(imm))); | 
| 35       Stream s = m.Build(); | 36       Stream s = m.Build(); | 
| 36       ASSERT_EQ(1U, s.size()); | 37       ASSERT_EQ(1U, s.size()); | 
| 37       EXPECT_EQ(kIA32Lea, s[0]->arch_opcode()); | 38       EXPECT_EQ(kIA32Lea, s[0]->arch_opcode()); | 
| 38       if (imm == 0) { | 39       if (imm == 0) { | 
| 39         ASSERT_EQ(1U, s[0]->InputCount()); | 40         ASSERT_EQ(1U, s[0]->InputCount()); | 
| 40       } else { | 41       } else { | 
| 41         ASSERT_EQ(2U, s[0]->InputCount()); | 42         ASSERT_EQ(2U, s[0]->InputCount()); | 
| 42         EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); | 43         EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); | 
| 43       } | 44       } | 
| 44     } | 45     } | 
| 45     { | 46     { | 
| 46       StreamBuilder m(this, kMachInt32, kMachInt32); | 47       StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); | 
| 47       m.Return(m.Int32Add(m.Int32Constant(imm), m.Parameter(0))); | 48       m.Return(m.Int32Add(m.Int32Constant(imm), m.Parameter(0))); | 
| 48       Stream s = m.Build(); | 49       Stream s = m.Build(); | 
| 49       ASSERT_EQ(1U, s.size()); | 50       ASSERT_EQ(1U, s.size()); | 
| 50       EXPECT_EQ(kIA32Lea, s[0]->arch_opcode()); | 51       EXPECT_EQ(kIA32Lea, s[0]->arch_opcode()); | 
| 51       if (imm == 0) { | 52       if (imm == 0) { | 
| 52         ASSERT_EQ(1U, s[0]->InputCount()); | 53         ASSERT_EQ(1U, s[0]->InputCount()); | 
| 53       } else { | 54       } else { | 
| 54         ASSERT_EQ(2U, s[0]->InputCount()); | 55         ASSERT_EQ(2U, s[0]->InputCount()); | 
| 55         EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); | 56         EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); | 
| 56       } | 57       } | 
| 57     } | 58     } | 
| 58   } | 59   } | 
| 59 } | 60 } | 
| 60 | 61 | 
| 61 | 62 | 
| 62 TEST_F(InstructionSelectorTest, Int32SubWithParameter) { | 63 TEST_F(InstructionSelectorTest, Int32SubWithParameter) { | 
| 63   StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); | 64   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), | 
|  | 65                   MachineType::Int32()); | 
| 64   m.Return(m.Int32Sub(m.Parameter(0), m.Parameter(1))); | 66   m.Return(m.Int32Sub(m.Parameter(0), m.Parameter(1))); | 
| 65   Stream s = m.Build(); | 67   Stream s = m.Build(); | 
| 66   ASSERT_EQ(1U, s.size()); | 68   ASSERT_EQ(1U, s.size()); | 
| 67   EXPECT_EQ(kIA32Sub, s[0]->arch_opcode()); | 69   EXPECT_EQ(kIA32Sub, s[0]->arch_opcode()); | 
| 68   EXPECT_EQ(1U, s[0]->OutputCount()); | 70   EXPECT_EQ(1U, s[0]->OutputCount()); | 
| 69 } | 71 } | 
| 70 | 72 | 
| 71 | 73 | 
| 72 TEST_F(InstructionSelectorTest, Int32SubWithImmediate) { | 74 TEST_F(InstructionSelectorTest, Int32SubWithImmediate) { | 
| 73   TRACED_FOREACH(int32_t, imm, kImmediates) { | 75   TRACED_FOREACH(int32_t, imm, kImmediates) { | 
| 74     StreamBuilder m(this, kMachInt32, kMachInt32); | 76     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); | 
| 75     m.Return(m.Int32Sub(m.Parameter(0), m.Int32Constant(imm))); | 77     m.Return(m.Int32Sub(m.Parameter(0), m.Int32Constant(imm))); | 
| 76     Stream s = m.Build(); | 78     Stream s = m.Build(); | 
| 77     ASSERT_EQ(1U, s.size()); | 79     ASSERT_EQ(1U, s.size()); | 
| 78     EXPECT_EQ(kIA32Sub, s[0]->arch_opcode()); | 80     EXPECT_EQ(kIA32Sub, s[0]->arch_opcode()); | 
| 79     ASSERT_EQ(2U, s[0]->InputCount()); | 81     ASSERT_EQ(2U, s[0]->InputCount()); | 
| 80     EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); | 82     EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); | 
| 81   } | 83   } | 
| 82 } | 84 } | 
| 83 | 85 | 
| 84 | 86 | 
| 85 // ----------------------------------------------------------------------------- | 87 // ----------------------------------------------------------------------------- | 
| 86 // Conversions. | 88 // Conversions. | 
| 87 | 89 | 
| 88 | 90 | 
| 89 TEST_F(InstructionSelectorTest, ChangeFloat32ToFloat64WithParameter) { | 91 TEST_F(InstructionSelectorTest, ChangeFloat32ToFloat64WithParameter) { | 
| 90   StreamBuilder m(this, kMachFloat32, kMachFloat64); | 92   StreamBuilder m(this, MachineType::Float32(), MachineType::Float64()); | 
| 91   m.Return(m.ChangeFloat32ToFloat64(m.Parameter(0))); | 93   m.Return(m.ChangeFloat32ToFloat64(m.Parameter(0))); | 
| 92   Stream s = m.Build(); | 94   Stream s = m.Build(); | 
| 93   ASSERT_EQ(1U, s.size()); | 95   ASSERT_EQ(1U, s.size()); | 
| 94   EXPECT_EQ(kSSEFloat32ToFloat64, s[0]->arch_opcode()); | 96   EXPECT_EQ(kSSEFloat32ToFloat64, s[0]->arch_opcode()); | 
| 95   EXPECT_EQ(1U, s[0]->InputCount()); | 97   EXPECT_EQ(1U, s[0]->InputCount()); | 
| 96   EXPECT_EQ(1U, s[0]->OutputCount()); | 98   EXPECT_EQ(1U, s[0]->OutputCount()); | 
| 97 } | 99 } | 
| 98 | 100 | 
| 99 | 101 | 
| 100 TEST_F(InstructionSelectorTest, TruncateFloat64ToFloat32WithParameter) { | 102 TEST_F(InstructionSelectorTest, TruncateFloat64ToFloat32WithParameter) { | 
| 101   StreamBuilder m(this, kMachFloat64, kMachFloat32); | 103   StreamBuilder m(this, MachineType::Float64(), MachineType::Float32()); | 
| 102   m.Return(m.TruncateFloat64ToFloat32(m.Parameter(0))); | 104   m.Return(m.TruncateFloat64ToFloat32(m.Parameter(0))); | 
| 103   Stream s = m.Build(); | 105   Stream s = m.Build(); | 
| 104   ASSERT_EQ(1U, s.size()); | 106   ASSERT_EQ(1U, s.size()); | 
| 105   EXPECT_EQ(kSSEFloat64ToFloat32, s[0]->arch_opcode()); | 107   EXPECT_EQ(kSSEFloat64ToFloat32, s[0]->arch_opcode()); | 
| 106   EXPECT_EQ(1U, s[0]->InputCount()); | 108   EXPECT_EQ(1U, s[0]->InputCount()); | 
| 107   EXPECT_EQ(1U, s[0]->OutputCount()); | 109   EXPECT_EQ(1U, s[0]->OutputCount()); | 
| 108 } | 110 } | 
| 109 | 111 | 
| 110 | 112 | 
| 111 // ----------------------------------------------------------------------------- | 113 // ----------------------------------------------------------------------------- | 
| 112 // Better left operand for commutative binops | 114 // Better left operand for commutative binops | 
| 113 | 115 | 
| 114 | 116 | 
| 115 TEST_F(InstructionSelectorTest, BetterLeftOperandTestAddBinop) { | 117 TEST_F(InstructionSelectorTest, BetterLeftOperandTestAddBinop) { | 
| 116   StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); | 118   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), | 
|  | 119                   MachineType::Int32()); | 
| 117   Node* param1 = m.Parameter(0); | 120   Node* param1 = m.Parameter(0); | 
| 118   Node* param2 = m.Parameter(1); | 121   Node* param2 = m.Parameter(1); | 
| 119   Node* add = m.Int32Add(param1, param2); | 122   Node* add = m.Int32Add(param1, param2); | 
| 120   m.Return(m.Int32Add(add, param1)); | 123   m.Return(m.Int32Add(add, param1)); | 
| 121   Stream s = m.Build(); | 124   Stream s = m.Build(); | 
| 122   ASSERT_EQ(2U, s.size()); | 125   ASSERT_EQ(2U, s.size()); | 
| 123   EXPECT_EQ(kIA32Lea, s[0]->arch_opcode()); | 126   EXPECT_EQ(kIA32Lea, s[0]->arch_opcode()); | 
| 124   ASSERT_EQ(2U, s[0]->InputCount()); | 127   ASSERT_EQ(2U, s[0]->InputCount()); | 
| 125   ASSERT_TRUE(s[0]->InputAt(0)->IsUnallocated()); | 128   ASSERT_TRUE(s[0]->InputAt(0)->IsUnallocated()); | 
| 126   EXPECT_EQ(s.ToVreg(param1), s.ToVreg(s[0]->InputAt(0))); | 129   EXPECT_EQ(s.ToVreg(param1), s.ToVreg(s[0]->InputAt(0))); | 
| 127   EXPECT_EQ(s.ToVreg(param2), s.ToVreg(s[0]->InputAt(1))); | 130   EXPECT_EQ(s.ToVreg(param2), s.ToVreg(s[0]->InputAt(1))); | 
| 128   ASSERT_EQ(2U, s[1]->InputCount()); | 131   ASSERT_EQ(2U, s[1]->InputCount()); | 
| 129   EXPECT_EQ(s.ToVreg(param1), s.ToVreg(s[0]->InputAt(0))); | 132   EXPECT_EQ(s.ToVreg(param1), s.ToVreg(s[0]->InputAt(0))); | 
| 130 } | 133 } | 
| 131 | 134 | 
| 132 | 135 | 
| 133 TEST_F(InstructionSelectorTest, BetterLeftOperandTestMulBinop) { | 136 TEST_F(InstructionSelectorTest, BetterLeftOperandTestMulBinop) { | 
| 134   StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); | 137   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), | 
|  | 138                   MachineType::Int32()); | 
| 135   Node* param1 = m.Parameter(0); | 139   Node* param1 = m.Parameter(0); | 
| 136   Node* param2 = m.Parameter(1); | 140   Node* param2 = m.Parameter(1); | 
| 137   Node* mul = m.Int32Mul(param1, param2); | 141   Node* mul = m.Int32Mul(param1, param2); | 
| 138   m.Return(m.Int32Mul(mul, param1)); | 142   m.Return(m.Int32Mul(mul, param1)); | 
| 139   Stream s = m.Build(); | 143   Stream s = m.Build(); | 
| 140   ASSERT_EQ(2U, s.size()); | 144   ASSERT_EQ(2U, s.size()); | 
| 141   EXPECT_EQ(kIA32Imul, s[0]->arch_opcode()); | 145   EXPECT_EQ(kIA32Imul, s[0]->arch_opcode()); | 
| 142   ASSERT_EQ(2U, s[0]->InputCount()); | 146   ASSERT_EQ(2U, s[0]->InputCount()); | 
| 143   ASSERT_TRUE(s[0]->InputAt(0)->IsUnallocated()); | 147   ASSERT_TRUE(s[0]->InputAt(0)->IsUnallocated()); | 
| 144   EXPECT_EQ(s.ToVreg(param2), s.ToVreg(s[0]->InputAt(0))); | 148   EXPECT_EQ(s.ToVreg(param2), s.ToVreg(s[0]->InputAt(0))); | 
| 145   EXPECT_EQ(s.ToVreg(param1), s.ToVreg(s[0]->InputAt(1))); | 149   EXPECT_EQ(s.ToVreg(param1), s.ToVreg(s[0]->InputAt(1))); | 
| 146 } | 150 } | 
| 147 | 151 | 
| 148 | 152 | 
| 149 // ----------------------------------------------------------------------------- | 153 // ----------------------------------------------------------------------------- | 
| 150 // Conversions. | 154 // Conversions. | 
| 151 | 155 | 
| 152 | 156 | 
| 153 TEST_F(InstructionSelectorTest, ChangeUint32ToFloat64WithParameter) { | 157 TEST_F(InstructionSelectorTest, ChangeUint32ToFloat64WithParameter) { | 
| 154   StreamBuilder m(this, kMachFloat64, kMachUint32); | 158   StreamBuilder m(this, MachineType::Float64(), MachineType::Uint32()); | 
| 155   m.Return(m.ChangeUint32ToFloat64(m.Parameter(0))); | 159   m.Return(m.ChangeUint32ToFloat64(m.Parameter(0))); | 
| 156   Stream s = m.Build(); | 160   Stream s = m.Build(); | 
| 157   ASSERT_EQ(1U, s.size()); | 161   ASSERT_EQ(1U, s.size()); | 
| 158   EXPECT_EQ(kSSEUint32ToFloat64, s[0]->arch_opcode()); | 162   EXPECT_EQ(kSSEUint32ToFloat64, s[0]->arch_opcode()); | 
| 159 } | 163 } | 
| 160 | 164 | 
| 161 | 165 | 
| 162 // ----------------------------------------------------------------------------- | 166 // ----------------------------------------------------------------------------- | 
| 163 // Loads and stores | 167 // Loads and stores | 
| 164 | 168 | 
| 165 | 169 | 
| 166 namespace { | 170 namespace { | 
| 167 | 171 | 
| 168 struct MemoryAccess { | 172 struct MemoryAccess { | 
| 169   MachineType type; | 173   MachineType type; | 
| 170   ArchOpcode load_opcode; | 174   ArchOpcode load_opcode; | 
| 171   ArchOpcode store_opcode; | 175   ArchOpcode store_opcode; | 
| 172 }; | 176 }; | 
| 173 | 177 | 
| 174 | 178 | 
| 175 std::ostream& operator<<(std::ostream& os, const MemoryAccess& memacc) { | 179 std::ostream& operator<<(std::ostream& os, const MemoryAccess& memacc) { | 
| 176   return os << memacc.type; | 180   return os << memacc.type; | 
| 177 } | 181 } | 
| 178 | 182 | 
| 179 | 183 | 
| 180 static const MemoryAccess kMemoryAccesses[] = { | 184 static const MemoryAccess kMemoryAccesses[] = { | 
| 181     {kMachInt8, kIA32Movsxbl, kIA32Movb}, | 185     {MachineType::Int8(), kIA32Movsxbl, kIA32Movb}, | 
| 182     {kMachUint8, kIA32Movzxbl, kIA32Movb}, | 186     {MachineType::Uint8(), kIA32Movzxbl, kIA32Movb}, | 
| 183     {kMachInt16, kIA32Movsxwl, kIA32Movw}, | 187     {MachineType::Int16(), kIA32Movsxwl, kIA32Movw}, | 
| 184     {kMachUint16, kIA32Movzxwl, kIA32Movw}, | 188     {MachineType::Uint16(), kIA32Movzxwl, kIA32Movw}, | 
| 185     {kMachInt32, kIA32Movl, kIA32Movl}, | 189     {MachineType::Int32(), kIA32Movl, kIA32Movl}, | 
| 186     {kMachUint32, kIA32Movl, kIA32Movl}, | 190     {MachineType::Uint32(), kIA32Movl, kIA32Movl}, | 
| 187     {kMachFloat32, kIA32Movss, kIA32Movss}, | 191     {MachineType::Float32(), kIA32Movss, kIA32Movss}, | 
| 188     {kMachFloat64, kIA32Movsd, kIA32Movsd}}; | 192     {MachineType::Float64(), kIA32Movsd, kIA32Movsd}}; | 
| 189 | 193 | 
| 190 }  // namespace | 194 }  // namespace | 
| 191 | 195 | 
| 192 | 196 | 
| 193 typedef InstructionSelectorTestWithParam<MemoryAccess> | 197 typedef InstructionSelectorTestWithParam<MemoryAccess> | 
| 194     InstructionSelectorMemoryAccessTest; | 198     InstructionSelectorMemoryAccessTest; | 
| 195 | 199 | 
| 196 | 200 | 
| 197 TEST_P(InstructionSelectorMemoryAccessTest, LoadWithParameters) { | 201 TEST_P(InstructionSelectorMemoryAccessTest, LoadWithParameters) { | 
| 198   const MemoryAccess memacc = GetParam(); | 202   const MemoryAccess memacc = GetParam(); | 
| 199   StreamBuilder m(this, memacc.type, kMachPtr, kMachInt32); | 203   StreamBuilder m(this, memacc.type, MachineType::Pointer(), | 
|  | 204                   MachineType::Int32()); | 
| 200   m.Return(m.Load(memacc.type, m.Parameter(0), m.Parameter(1))); | 205   m.Return(m.Load(memacc.type, m.Parameter(0), m.Parameter(1))); | 
| 201   Stream s = m.Build(); | 206   Stream s = m.Build(); | 
| 202   ASSERT_EQ(1U, s.size()); | 207   ASSERT_EQ(1U, s.size()); | 
| 203   EXPECT_EQ(memacc.load_opcode, s[0]->arch_opcode()); | 208   EXPECT_EQ(memacc.load_opcode, s[0]->arch_opcode()); | 
| 204   EXPECT_EQ(2U, s[0]->InputCount()); | 209   EXPECT_EQ(2U, s[0]->InputCount()); | 
| 205   EXPECT_EQ(1U, s[0]->OutputCount()); | 210   EXPECT_EQ(1U, s[0]->OutputCount()); | 
| 206 } | 211 } | 
| 207 | 212 | 
| 208 | 213 | 
| 209 TEST_P(InstructionSelectorMemoryAccessTest, LoadWithImmediateBase) { | 214 TEST_P(InstructionSelectorMemoryAccessTest, LoadWithImmediateBase) { | 
| 210   const MemoryAccess memacc = GetParam(); | 215   const MemoryAccess memacc = GetParam(); | 
| 211   TRACED_FOREACH(int32_t, base, kImmediates) { | 216   TRACED_FOREACH(int32_t, base, kImmediates) { | 
| 212     StreamBuilder m(this, memacc.type, kMachPtr); | 217     StreamBuilder m(this, memacc.type, MachineType::Pointer()); | 
| 213     m.Return(m.Load(memacc.type, m.Int32Constant(base), m.Parameter(0))); | 218     m.Return(m.Load(memacc.type, m.Int32Constant(base), m.Parameter(0))); | 
| 214     Stream s = m.Build(); | 219     Stream s = m.Build(); | 
| 215     ASSERT_EQ(1U, s.size()); | 220     ASSERT_EQ(1U, s.size()); | 
| 216     EXPECT_EQ(memacc.load_opcode, s[0]->arch_opcode()); | 221     EXPECT_EQ(memacc.load_opcode, s[0]->arch_opcode()); | 
| 217     if (base == 0) { | 222     if (base == 0) { | 
| 218       ASSERT_EQ(1U, s[0]->InputCount()); | 223       ASSERT_EQ(1U, s[0]->InputCount()); | 
| 219     } else { | 224     } else { | 
| 220       ASSERT_EQ(2U, s[0]->InputCount()); | 225       ASSERT_EQ(2U, s[0]->InputCount()); | 
| 221       ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind()); | 226       ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind()); | 
| 222       EXPECT_EQ(base, s.ToInt32(s[0]->InputAt(1))); | 227       EXPECT_EQ(base, s.ToInt32(s[0]->InputAt(1))); | 
| 223     } | 228     } | 
| 224     EXPECT_EQ(1U, s[0]->OutputCount()); | 229     EXPECT_EQ(1U, s[0]->OutputCount()); | 
| 225   } | 230   } | 
| 226 } | 231 } | 
| 227 | 232 | 
| 228 | 233 | 
| 229 TEST_P(InstructionSelectorMemoryAccessTest, LoadWithImmediateIndex) { | 234 TEST_P(InstructionSelectorMemoryAccessTest, LoadWithImmediateIndex) { | 
| 230   const MemoryAccess memacc = GetParam(); | 235   const MemoryAccess memacc = GetParam(); | 
| 231   TRACED_FOREACH(int32_t, index, kImmediates) { | 236   TRACED_FOREACH(int32_t, index, kImmediates) { | 
| 232     StreamBuilder m(this, memacc.type, kMachPtr); | 237     StreamBuilder m(this, memacc.type, MachineType::Pointer()); | 
| 233     m.Return(m.Load(memacc.type, m.Parameter(0), m.Int32Constant(index))); | 238     m.Return(m.Load(memacc.type, m.Parameter(0), m.Int32Constant(index))); | 
| 234     Stream s = m.Build(); | 239     Stream s = m.Build(); | 
| 235     ASSERT_EQ(1U, s.size()); | 240     ASSERT_EQ(1U, s.size()); | 
| 236     EXPECT_EQ(memacc.load_opcode, s[0]->arch_opcode()); | 241     EXPECT_EQ(memacc.load_opcode, s[0]->arch_opcode()); | 
| 237     if (index == 0) { | 242     if (index == 0) { | 
| 238       ASSERT_EQ(1U, s[0]->InputCount()); | 243       ASSERT_EQ(1U, s[0]->InputCount()); | 
| 239     } else { | 244     } else { | 
| 240       ASSERT_EQ(2U, s[0]->InputCount()); | 245       ASSERT_EQ(2U, s[0]->InputCount()); | 
| 241       ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind()); | 246       ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind()); | 
| 242       EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1))); | 247       EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1))); | 
| 243     } | 248     } | 
| 244     EXPECT_EQ(1U, s[0]->OutputCount()); | 249     EXPECT_EQ(1U, s[0]->OutputCount()); | 
| 245   } | 250   } | 
| 246 } | 251 } | 
| 247 | 252 | 
| 248 | 253 | 
| 249 TEST_P(InstructionSelectorMemoryAccessTest, StoreWithParameters) { | 254 TEST_P(InstructionSelectorMemoryAccessTest, StoreWithParameters) { | 
| 250   const MemoryAccess memacc = GetParam(); | 255   const MemoryAccess memacc = GetParam(); | 
| 251   StreamBuilder m(this, kMachInt32, kMachPtr, kMachInt32, memacc.type); | 256   StreamBuilder m(this, MachineType::Int32(), MachineType::Pointer(), | 
|  | 257                   MachineType::Int32(), memacc.type); | 
| 252   m.Store(memacc.type, m.Parameter(0), m.Parameter(1), m.Parameter(2), | 258   m.Store(memacc.type, m.Parameter(0), m.Parameter(1), m.Parameter(2), | 
| 253           kNoWriteBarrier); | 259           kNoWriteBarrier); | 
| 254   m.Return(m.Int32Constant(0)); | 260   m.Return(m.Int32Constant(0)); | 
| 255   Stream s = m.Build(); | 261   Stream s = m.Build(); | 
| 256   ASSERT_EQ(1U, s.size()); | 262   ASSERT_EQ(1U, s.size()); | 
| 257   EXPECT_EQ(memacc.store_opcode, s[0]->arch_opcode()); | 263   EXPECT_EQ(memacc.store_opcode, s[0]->arch_opcode()); | 
| 258   EXPECT_EQ(3U, s[0]->InputCount()); | 264   EXPECT_EQ(3U, s[0]->InputCount()); | 
| 259   EXPECT_EQ(0U, s[0]->OutputCount()); | 265   EXPECT_EQ(0U, s[0]->OutputCount()); | 
| 260 } | 266 } | 
| 261 | 267 | 
| 262 | 268 | 
| 263 TEST_P(InstructionSelectorMemoryAccessTest, StoreWithImmediateBase) { | 269 TEST_P(InstructionSelectorMemoryAccessTest, StoreWithImmediateBase) { | 
| 264   const MemoryAccess memacc = GetParam(); | 270   const MemoryAccess memacc = GetParam(); | 
| 265   TRACED_FOREACH(int32_t, base, kImmediates) { | 271   TRACED_FOREACH(int32_t, base, kImmediates) { | 
| 266     StreamBuilder m(this, kMachInt32, kMachInt32, memacc.type); | 272     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), | 
|  | 273                     memacc.type); | 
| 267     m.Store(memacc.type, m.Int32Constant(base), m.Parameter(0), m.Parameter(1), | 274     m.Store(memacc.type, m.Int32Constant(base), m.Parameter(0), m.Parameter(1), | 
| 268             kNoWriteBarrier); | 275             kNoWriteBarrier); | 
| 269     m.Return(m.Int32Constant(0)); | 276     m.Return(m.Int32Constant(0)); | 
| 270     Stream s = m.Build(); | 277     Stream s = m.Build(); | 
| 271     ASSERT_EQ(1U, s.size()); | 278     ASSERT_EQ(1U, s.size()); | 
| 272     EXPECT_EQ(memacc.store_opcode, s[0]->arch_opcode()); | 279     EXPECT_EQ(memacc.store_opcode, s[0]->arch_opcode()); | 
| 273     if (base == 0) { | 280     if (base == 0) { | 
| 274       ASSERT_EQ(2U, s[0]->InputCount()); | 281       ASSERT_EQ(2U, s[0]->InputCount()); | 
| 275     } else { | 282     } else { | 
| 276       ASSERT_EQ(3U, s[0]->InputCount()); | 283       ASSERT_EQ(3U, s[0]->InputCount()); | 
| 277       ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind()); | 284       ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind()); | 
| 278       EXPECT_EQ(base, s.ToInt32(s[0]->InputAt(1))); | 285       EXPECT_EQ(base, s.ToInt32(s[0]->InputAt(1))); | 
| 279     } | 286     } | 
| 280     EXPECT_EQ(0U, s[0]->OutputCount()); | 287     EXPECT_EQ(0U, s[0]->OutputCount()); | 
| 281   } | 288   } | 
| 282 } | 289 } | 
| 283 | 290 | 
| 284 | 291 | 
| 285 TEST_P(InstructionSelectorMemoryAccessTest, StoreWithImmediateIndex) { | 292 TEST_P(InstructionSelectorMemoryAccessTest, StoreWithImmediateIndex) { | 
| 286   const MemoryAccess memacc = GetParam(); | 293   const MemoryAccess memacc = GetParam(); | 
| 287   TRACED_FOREACH(int32_t, index, kImmediates) { | 294   TRACED_FOREACH(int32_t, index, kImmediates) { | 
| 288     StreamBuilder m(this, kMachInt32, kMachPtr, memacc.type); | 295     StreamBuilder m(this, MachineType::Int32(), MachineType::Pointer(), | 
|  | 296                     memacc.type); | 
| 289     m.Store(memacc.type, m.Parameter(0), m.Int32Constant(index), m.Parameter(1), | 297     m.Store(memacc.type, m.Parameter(0), m.Int32Constant(index), m.Parameter(1), | 
| 290             kNoWriteBarrier); | 298             kNoWriteBarrier); | 
| 291     m.Return(m.Int32Constant(0)); | 299     m.Return(m.Int32Constant(0)); | 
| 292     Stream s = m.Build(); | 300     Stream s = m.Build(); | 
| 293     ASSERT_EQ(1U, s.size()); | 301     ASSERT_EQ(1U, s.size()); | 
| 294     EXPECT_EQ(memacc.store_opcode, s[0]->arch_opcode()); | 302     EXPECT_EQ(memacc.store_opcode, s[0]->arch_opcode()); | 
| 295     if (index == 0) { | 303     if (index == 0) { | 
| 296       ASSERT_EQ(2U, s[0]->InputCount()); | 304       ASSERT_EQ(2U, s[0]->InputCount()); | 
| 297     } else { | 305     } else { | 
| 298       ASSERT_EQ(3U, s[0]->InputCount()); | 306       ASSERT_EQ(3U, s[0]->InputCount()); | 
| (...skipping 14 matching lines...) Expand all  Loading... | 
| 313 // AddressingMode for loads and stores. | 321 // AddressingMode for loads and stores. | 
| 314 | 322 | 
| 315 | 323 | 
| 316 class AddressingModeUnitTest : public InstructionSelectorTest { | 324 class AddressingModeUnitTest : public InstructionSelectorTest { | 
| 317  public: | 325  public: | 
| 318   AddressingModeUnitTest() : m(NULL) { Reset(); } | 326   AddressingModeUnitTest() : m(NULL) { Reset(); } | 
| 319   ~AddressingModeUnitTest() { delete m; } | 327   ~AddressingModeUnitTest() { delete m; } | 
| 320 | 328 | 
| 321   void Run(Node* base, Node* load_index, Node* store_index, | 329   void Run(Node* base, Node* load_index, Node* store_index, | 
| 322            AddressingMode mode) { | 330            AddressingMode mode) { | 
| 323     Node* load = m->Load(kMachInt32, base, load_index); | 331     Node* load = m->Load(MachineType::Int32(), base, load_index); | 
| 324     m->Store(kMachInt32, base, store_index, load, kNoWriteBarrier); | 332     m->Store(MachineType::Int32(), base, store_index, load, kNoWriteBarrier); | 
| 325     m->Return(m->Int32Constant(0)); | 333     m->Return(m->Int32Constant(0)); | 
| 326     Stream s = m->Build(); | 334     Stream s = m->Build(); | 
| 327     ASSERT_EQ(2U, s.size()); | 335     ASSERT_EQ(2U, s.size()); | 
| 328     EXPECT_EQ(mode, s[0]->addressing_mode()); | 336     EXPECT_EQ(mode, s[0]->addressing_mode()); | 
| 329     EXPECT_EQ(mode, s[1]->addressing_mode()); | 337     EXPECT_EQ(mode, s[1]->addressing_mode()); | 
| 330   } | 338   } | 
| 331 | 339 | 
| 332   Node* zero; | 340   Node* zero; | 
| 333   Node* null_ptr; | 341   Node* null_ptr; | 
| 334   Node* non_zero; | 342   Node* non_zero; | 
| 335   Node* base_reg;   // opaque value to generate base as register | 343   Node* base_reg;   // opaque value to generate base as register | 
| 336   Node* index_reg;  // opaque value to generate index as register | 344   Node* index_reg;  // opaque value to generate index as register | 
| 337   Node* scales[4]; | 345   Node* scales[4]; | 
| 338   StreamBuilder* m; | 346   StreamBuilder* m; | 
| 339 | 347 | 
| 340   void Reset() { | 348   void Reset() { | 
| 341     delete m; | 349     delete m; | 
| 342     m = new StreamBuilder(this, kMachInt32, kMachInt32, kMachInt32); | 350     m = new StreamBuilder(this, MachineType::Int32(), MachineType::Int32(), | 
|  | 351                           MachineType::Int32()); | 
| 343     zero = m->Int32Constant(0); | 352     zero = m->Int32Constant(0); | 
| 344     null_ptr = m->Int32Constant(0); | 353     null_ptr = m->Int32Constant(0); | 
| 345     non_zero = m->Int32Constant(127); | 354     non_zero = m->Int32Constant(127); | 
| 346     base_reg = m->Parameter(0); | 355     base_reg = m->Parameter(0); | 
| 347     index_reg = m->Parameter(0); | 356     index_reg = m->Parameter(0); | 
| 348 | 357 | 
| 349     scales[0] = m->Int32Constant(1); | 358     scales[0] = m->Int32Constant(1); | 
| 350     scales[1] = m->Int32Constant(2); | 359     scales[1] = m->Int32Constant(2); | 
| 351     scales[2] = m->Int32Constant(4); | 360     scales[2] = m->Int32Constant(4); | 
| 352     scales[3] = m->Int32Constant(8); | 361     scales[3] = m->Int32Constant(8); | 
| (...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 558       return kMode_MRI; | 567       return kMode_MRI; | 
| 559     default: | 568     default: | 
| 560       UNREACHABLE(); | 569       UNREACHABLE(); | 
| 561       return kMode_None; | 570       return kMode_None; | 
| 562   } | 571   } | 
| 563 } | 572 } | 
| 564 | 573 | 
| 565 | 574 | 
| 566 TEST_P(InstructionSelectorMultTest, Mult32) { | 575 TEST_P(InstructionSelectorMultTest, Mult32) { | 
| 567   const MultParam m_param = GetParam(); | 576   const MultParam m_param = GetParam(); | 
| 568   StreamBuilder m(this, kMachInt32, kMachInt32); | 577   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); | 
| 569   Node* param = m.Parameter(0); | 578   Node* param = m.Parameter(0); | 
| 570   Node* mult = m.Int32Mul(param, m.Int32Constant(m_param.value)); | 579   Node* mult = m.Int32Mul(param, m.Int32Constant(m_param.value)); | 
| 571   m.Return(mult); | 580   m.Return(mult); | 
| 572   Stream s = m.Build(); | 581   Stream s = m.Build(); | 
| 573   ASSERT_EQ(1U, s.size()); | 582   ASSERT_EQ(1U, s.size()); | 
| 574   EXPECT_EQ(m_param.addressing_mode, s[0]->addressing_mode()); | 583   EXPECT_EQ(m_param.addressing_mode, s[0]->addressing_mode()); | 
| 575   if (m_param.lea_expected) { | 584   if (m_param.lea_expected) { | 
| 576     EXPECT_EQ(kIA32Lea, s[0]->arch_opcode()); | 585     EXPECT_EQ(kIA32Lea, s[0]->arch_opcode()); | 
| 577     ASSERT_EQ(InputCountForLea(s[0]->addressing_mode()), s[0]->InputCount()); | 586     ASSERT_EQ(InputCountForLea(s[0]->addressing_mode()), s[0]->InputCount()); | 
| 578   } else { | 587   } else { | 
| 579     EXPECT_EQ(kIA32Imul, s[0]->arch_opcode()); | 588     EXPECT_EQ(kIA32Imul, s[0]->arch_opcode()); | 
| 580     ASSERT_EQ(2U, s[0]->InputCount()); | 589     ASSERT_EQ(2U, s[0]->InputCount()); | 
| 581   } | 590   } | 
| 582   EXPECT_EQ(s.ToVreg(param), s.ToVreg(s[0]->InputAt(0))); | 591   EXPECT_EQ(s.ToVreg(param), s.ToVreg(s[0]->InputAt(0))); | 
| 583 } | 592 } | 
| 584 | 593 | 
| 585 | 594 | 
| 586 TEST_P(InstructionSelectorMultTest, MultAdd32) { | 595 TEST_P(InstructionSelectorMultTest, MultAdd32) { | 
| 587   TRACED_FOREACH(int32_t, imm, kImmediates) { | 596   TRACED_FOREACH(int32_t, imm, kImmediates) { | 
| 588     const MultParam m_param = GetParam(); | 597     const MultParam m_param = GetParam(); | 
| 589     StreamBuilder m(this, kMachInt32, kMachInt32); | 598     StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); | 
| 590     Node* param = m.Parameter(0); | 599     Node* param = m.Parameter(0); | 
| 591     Node* mult = m.Int32Add(m.Int32Mul(param, m.Int32Constant(m_param.value)), | 600     Node* mult = m.Int32Add(m.Int32Mul(param, m.Int32Constant(m_param.value)), | 
| 592                             m.Int32Constant(imm)); | 601                             m.Int32Constant(imm)); | 
| 593     m.Return(mult); | 602     m.Return(mult); | 
| 594     Stream s = m.Build(); | 603     Stream s = m.Build(); | 
| 595     if (m_param.lea_expected) { | 604     if (m_param.lea_expected) { | 
| 596       ASSERT_EQ(1U, s.size()); | 605       ASSERT_EQ(1U, s.size()); | 
| 597       EXPECT_EQ(kIA32Lea, s[0]->arch_opcode()); | 606       EXPECT_EQ(kIA32Lea, s[0]->arch_opcode()); | 
| 598       EXPECT_EQ(AddressingModeForAddMult(imm, m_param), | 607       EXPECT_EQ(AddressingModeForAddMult(imm, m_param), | 
| 599                 s[0]->addressing_mode()); | 608                 s[0]->addressing_mode()); | 
| (...skipping 11 matching lines...) Expand all  Loading... | 
| 611     } | 620     } | 
| 612   } | 621   } | 
| 613 } | 622 } | 
| 614 | 623 | 
| 615 | 624 | 
| 616 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorMultTest, | 625 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorMultTest, | 
| 617                         ::testing::ValuesIn(kMultParams)); | 626                         ::testing::ValuesIn(kMultParams)); | 
| 618 | 627 | 
| 619 | 628 | 
| 620 TEST_F(InstructionSelectorTest, Int32MulHigh) { | 629 TEST_F(InstructionSelectorTest, Int32MulHigh) { | 
| 621   StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); | 630   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), | 
|  | 631                   MachineType::Int32()); | 
| 622   Node* const p0 = m.Parameter(0); | 632   Node* const p0 = m.Parameter(0); | 
| 623   Node* const p1 = m.Parameter(1); | 633   Node* const p1 = m.Parameter(1); | 
| 624   Node* const n = m.Int32MulHigh(p0, p1); | 634   Node* const n = m.Int32MulHigh(p0, p1); | 
| 625   m.Return(n); | 635   m.Return(n); | 
| 626   Stream s = m.Build(); | 636   Stream s = m.Build(); | 
| 627   ASSERT_EQ(1U, s.size()); | 637   ASSERT_EQ(1U, s.size()); | 
| 628   EXPECT_EQ(kIA32ImulHigh, s[0]->arch_opcode()); | 638   EXPECT_EQ(kIA32ImulHigh, s[0]->arch_opcode()); | 
| 629   ASSERT_EQ(2U, s[0]->InputCount()); | 639   ASSERT_EQ(2U, s[0]->InputCount()); | 
| 630   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); | 640   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); | 
| 631   EXPECT_TRUE(s.IsFixed(s[0]->InputAt(0), eax)); | 641   EXPECT_TRUE(s.IsFixed(s[0]->InputAt(0), eax)); | 
| 632   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1))); | 642   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1))); | 
| 633   EXPECT_TRUE(!s.IsUsedAtStart(s[0]->InputAt(1))); | 643   EXPECT_TRUE(!s.IsUsedAtStart(s[0]->InputAt(1))); | 
| 634   ASSERT_EQ(1U, s[0]->OutputCount()); | 644   ASSERT_EQ(1U, s[0]->OutputCount()); | 
| 635   EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); | 645   EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); | 
| 636   EXPECT_TRUE(s.IsFixed(s[0]->OutputAt(0), edx)); | 646   EXPECT_TRUE(s.IsFixed(s[0]->OutputAt(0), edx)); | 
| 637 } | 647 } | 
| 638 | 648 | 
| 639 | 649 | 
| 640 // ----------------------------------------------------------------------------- | 650 // ----------------------------------------------------------------------------- | 
| 641 // Floating point operations. | 651 // Floating point operations. | 
| 642 | 652 | 
| 643 | 653 | 
| 644 TEST_F(InstructionSelectorTest, Float32Abs) { | 654 TEST_F(InstructionSelectorTest, Float32Abs) { | 
| 645   { | 655   { | 
| 646     StreamBuilder m(this, kMachFloat32, kMachFloat32); | 656     StreamBuilder m(this, MachineType::Float32(), MachineType::Float32()); | 
| 647     Node* const p0 = m.Parameter(0); | 657     Node* const p0 = m.Parameter(0); | 
| 648     Node* const n = m.Float32Abs(p0); | 658     Node* const n = m.Float32Abs(p0); | 
| 649     m.Return(n); | 659     m.Return(n); | 
| 650     Stream s = m.Build(); | 660     Stream s = m.Build(); | 
| 651     ASSERT_EQ(1U, s.size()); | 661     ASSERT_EQ(1U, s.size()); | 
| 652     EXPECT_EQ(kSSEFloat32Abs, s[0]->arch_opcode()); | 662     EXPECT_EQ(kSSEFloat32Abs, s[0]->arch_opcode()); | 
| 653     ASSERT_EQ(1U, s[0]->InputCount()); | 663     ASSERT_EQ(1U, s[0]->InputCount()); | 
| 654     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); | 664     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); | 
| 655     ASSERT_EQ(1U, s[0]->OutputCount()); | 665     ASSERT_EQ(1U, s[0]->OutputCount()); | 
| 656     EXPECT_TRUE(s.IsSameAsFirst(s[0]->Output())); | 666     EXPECT_TRUE(s.IsSameAsFirst(s[0]->Output())); | 
| 657     EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); | 667     EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); | 
| 658     EXPECT_EQ(kFlags_none, s[0]->flags_mode()); | 668     EXPECT_EQ(kFlags_none, s[0]->flags_mode()); | 
| 659   } | 669   } | 
| 660   { | 670   { | 
| 661     StreamBuilder m(this, kMachFloat32, kMachFloat32); | 671     StreamBuilder m(this, MachineType::Float32(), MachineType::Float32()); | 
| 662     Node* const p0 = m.Parameter(0); | 672     Node* const p0 = m.Parameter(0); | 
| 663     Node* const n = m.Float32Abs(p0); | 673     Node* const n = m.Float32Abs(p0); | 
| 664     m.Return(n); | 674     m.Return(n); | 
| 665     Stream s = m.Build(AVX); | 675     Stream s = m.Build(AVX); | 
| 666     ASSERT_EQ(1U, s.size()); | 676     ASSERT_EQ(1U, s.size()); | 
| 667     EXPECT_EQ(kAVXFloat32Abs, s[0]->arch_opcode()); | 677     EXPECT_EQ(kAVXFloat32Abs, s[0]->arch_opcode()); | 
| 668     ASSERT_EQ(1U, s[0]->InputCount()); | 678     ASSERT_EQ(1U, s[0]->InputCount()); | 
| 669     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); | 679     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); | 
| 670     ASSERT_EQ(1U, s[0]->OutputCount()); | 680     ASSERT_EQ(1U, s[0]->OutputCount()); | 
| 671     EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); | 681     EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); | 
| 672     EXPECT_EQ(kFlags_none, s[0]->flags_mode()); | 682     EXPECT_EQ(kFlags_none, s[0]->flags_mode()); | 
| 673   } | 683   } | 
| 674 } | 684 } | 
| 675 | 685 | 
| 676 | 686 | 
| 677 TEST_F(InstructionSelectorTest, Float64Abs) { | 687 TEST_F(InstructionSelectorTest, Float64Abs) { | 
| 678   { | 688   { | 
| 679     StreamBuilder m(this, kMachFloat64, kMachFloat64); | 689     StreamBuilder m(this, MachineType::Float64(), MachineType::Float64()); | 
| 680     Node* const p0 = m.Parameter(0); | 690     Node* const p0 = m.Parameter(0); | 
| 681     Node* const n = m.Float64Abs(p0); | 691     Node* const n = m.Float64Abs(p0); | 
| 682     m.Return(n); | 692     m.Return(n); | 
| 683     Stream s = m.Build(); | 693     Stream s = m.Build(); | 
| 684     ASSERT_EQ(1U, s.size()); | 694     ASSERT_EQ(1U, s.size()); | 
| 685     EXPECT_EQ(kSSEFloat64Abs, s[0]->arch_opcode()); | 695     EXPECT_EQ(kSSEFloat64Abs, s[0]->arch_opcode()); | 
| 686     ASSERT_EQ(1U, s[0]->InputCount()); | 696     ASSERT_EQ(1U, s[0]->InputCount()); | 
| 687     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); | 697     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); | 
| 688     ASSERT_EQ(1U, s[0]->OutputCount()); | 698     ASSERT_EQ(1U, s[0]->OutputCount()); | 
| 689     EXPECT_TRUE(s.IsSameAsFirst(s[0]->Output())); | 699     EXPECT_TRUE(s.IsSameAsFirst(s[0]->Output())); | 
| 690     EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); | 700     EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); | 
| 691     EXPECT_EQ(kFlags_none, s[0]->flags_mode()); | 701     EXPECT_EQ(kFlags_none, s[0]->flags_mode()); | 
| 692   } | 702   } | 
| 693   { | 703   { | 
| 694     StreamBuilder m(this, kMachFloat64, kMachFloat64); | 704     StreamBuilder m(this, MachineType::Float64(), MachineType::Float64()); | 
| 695     Node* const p0 = m.Parameter(0); | 705     Node* const p0 = m.Parameter(0); | 
| 696     Node* const n = m.Float64Abs(p0); | 706     Node* const n = m.Float64Abs(p0); | 
| 697     m.Return(n); | 707     m.Return(n); | 
| 698     Stream s = m.Build(AVX); | 708     Stream s = m.Build(AVX); | 
| 699     ASSERT_EQ(1U, s.size()); | 709     ASSERT_EQ(1U, s.size()); | 
| 700     EXPECT_EQ(kAVXFloat64Abs, s[0]->arch_opcode()); | 710     EXPECT_EQ(kAVXFloat64Abs, s[0]->arch_opcode()); | 
| 701     ASSERT_EQ(1U, s[0]->InputCount()); | 711     ASSERT_EQ(1U, s[0]->InputCount()); | 
| 702     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); | 712     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); | 
| 703     ASSERT_EQ(1U, s[0]->OutputCount()); | 713     ASSERT_EQ(1U, s[0]->OutputCount()); | 
| 704     EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); | 714     EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); | 
| 705     EXPECT_EQ(kFlags_none, s[0]->flags_mode()); | 715     EXPECT_EQ(kFlags_none, s[0]->flags_mode()); | 
| 706   } | 716   } | 
| 707 } | 717 } | 
| 708 | 718 | 
| 709 | 719 | 
| 710 TEST_F(InstructionSelectorTest, Float64BinopArithmetic) { | 720 TEST_F(InstructionSelectorTest, Float64BinopArithmetic) { | 
| 711   { | 721   { | 
| 712     StreamBuilder m(this, kMachFloat64, kMachFloat64, kMachFloat64); | 722     StreamBuilder m(this, MachineType::Float64(), MachineType::Float64(), | 
|  | 723                     MachineType::Float64()); | 
| 713     Node* add = m.Float64Add(m.Parameter(0), m.Parameter(1)); | 724     Node* add = m.Float64Add(m.Parameter(0), m.Parameter(1)); | 
| 714     Node* mul = m.Float64Mul(add, m.Parameter(1)); | 725     Node* mul = m.Float64Mul(add, m.Parameter(1)); | 
| 715     Node* sub = m.Float64Sub(mul, add); | 726     Node* sub = m.Float64Sub(mul, add); | 
| 716     Node* ret = m.Float64Div(mul, sub); | 727     Node* ret = m.Float64Div(mul, sub); | 
| 717     m.Return(ret); | 728     m.Return(ret); | 
| 718     Stream s = m.Build(AVX); | 729     Stream s = m.Build(AVX); | 
| 719     ASSERT_EQ(4U, s.size()); | 730     ASSERT_EQ(4U, s.size()); | 
| 720     EXPECT_EQ(kAVXFloat64Add, s[0]->arch_opcode()); | 731     EXPECT_EQ(kAVXFloat64Add, s[0]->arch_opcode()); | 
| 721     EXPECT_EQ(kAVXFloat64Mul, s[1]->arch_opcode()); | 732     EXPECT_EQ(kAVXFloat64Mul, s[1]->arch_opcode()); | 
| 722     EXPECT_EQ(kAVXFloat64Sub, s[2]->arch_opcode()); | 733     EXPECT_EQ(kAVXFloat64Sub, s[2]->arch_opcode()); | 
| 723     EXPECT_EQ(kAVXFloat64Div, s[3]->arch_opcode()); | 734     EXPECT_EQ(kAVXFloat64Div, s[3]->arch_opcode()); | 
| 724   } | 735   } | 
| 725   { | 736   { | 
| 726     StreamBuilder m(this, kMachFloat64, kMachFloat64, kMachFloat64); | 737     StreamBuilder m(this, MachineType::Float64(), MachineType::Float64(), | 
|  | 738                     MachineType::Float64()); | 
| 727     Node* add = m.Float64Add(m.Parameter(0), m.Parameter(1)); | 739     Node* add = m.Float64Add(m.Parameter(0), m.Parameter(1)); | 
| 728     Node* mul = m.Float64Mul(add, m.Parameter(1)); | 740     Node* mul = m.Float64Mul(add, m.Parameter(1)); | 
| 729     Node* sub = m.Float64Sub(mul, add); | 741     Node* sub = m.Float64Sub(mul, add); | 
| 730     Node* ret = m.Float64Div(mul, sub); | 742     Node* ret = m.Float64Div(mul, sub); | 
| 731     m.Return(ret); | 743     m.Return(ret); | 
| 732     Stream s = m.Build(); | 744     Stream s = m.Build(); | 
| 733     ASSERT_EQ(4U, s.size()); | 745     ASSERT_EQ(4U, s.size()); | 
| 734     EXPECT_EQ(kSSEFloat64Add, s[0]->arch_opcode()); | 746     EXPECT_EQ(kSSEFloat64Add, s[0]->arch_opcode()); | 
| 735     EXPECT_EQ(kSSEFloat64Mul, s[1]->arch_opcode()); | 747     EXPECT_EQ(kSSEFloat64Mul, s[1]->arch_opcode()); | 
| 736     EXPECT_EQ(kSSEFloat64Sub, s[2]->arch_opcode()); | 748     EXPECT_EQ(kSSEFloat64Sub, s[2]->arch_opcode()); | 
| 737     EXPECT_EQ(kSSEFloat64Div, s[3]->arch_opcode()); | 749     EXPECT_EQ(kSSEFloat64Div, s[3]->arch_opcode()); | 
| 738   } | 750   } | 
| 739 } | 751 } | 
| 740 | 752 | 
| 741 | 753 | 
| 742 TEST_F(InstructionSelectorTest, Float32SubWithMinusZeroAndParameter) { | 754 TEST_F(InstructionSelectorTest, Float32SubWithMinusZeroAndParameter) { | 
| 743   { | 755   { | 
| 744     StreamBuilder m(this, kMachFloat32, kMachFloat32); | 756     StreamBuilder m(this, MachineType::Float32(), MachineType::Float32()); | 
| 745     Node* const p0 = m.Parameter(0); | 757     Node* const p0 = m.Parameter(0); | 
| 746     Node* const n = m.Float32Sub(m.Float32Constant(-0.0f), p0); | 758     Node* const n = m.Float32Sub(m.Float32Constant(-0.0f), p0); | 
| 747     m.Return(n); | 759     m.Return(n); | 
| 748     Stream s = m.Build(); | 760     Stream s = m.Build(); | 
| 749     ASSERT_EQ(1U, s.size()); | 761     ASSERT_EQ(1U, s.size()); | 
| 750     EXPECT_EQ(kSSEFloat32Neg, s[0]->arch_opcode()); | 762     EXPECT_EQ(kSSEFloat32Neg, s[0]->arch_opcode()); | 
| 751     ASSERT_EQ(1U, s[0]->InputCount()); | 763     ASSERT_EQ(1U, s[0]->InputCount()); | 
| 752     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); | 764     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); | 
| 753     ASSERT_EQ(1U, s[0]->OutputCount()); | 765     ASSERT_EQ(1U, s[0]->OutputCount()); | 
| 754     EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); | 766     EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); | 
| 755     EXPECT_EQ(kFlags_none, s[0]->flags_mode()); | 767     EXPECT_EQ(kFlags_none, s[0]->flags_mode()); | 
| 756   } | 768   } | 
| 757   { | 769   { | 
| 758     StreamBuilder m(this, kMachFloat32, kMachFloat32); | 770     StreamBuilder m(this, MachineType::Float32(), MachineType::Float32()); | 
| 759     Node* const p0 = m.Parameter(0); | 771     Node* const p0 = m.Parameter(0); | 
| 760     Node* const n = m.Float32Sub(m.Float32Constant(-0.0f), p0); | 772     Node* const n = m.Float32Sub(m.Float32Constant(-0.0f), p0); | 
| 761     m.Return(n); | 773     m.Return(n); | 
| 762     Stream s = m.Build(AVX); | 774     Stream s = m.Build(AVX); | 
| 763     ASSERT_EQ(1U, s.size()); | 775     ASSERT_EQ(1U, s.size()); | 
| 764     EXPECT_EQ(kAVXFloat32Neg, s[0]->arch_opcode()); | 776     EXPECT_EQ(kAVXFloat32Neg, s[0]->arch_opcode()); | 
| 765     ASSERT_EQ(1U, s[0]->InputCount()); | 777     ASSERT_EQ(1U, s[0]->InputCount()); | 
| 766     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); | 778     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); | 
| 767     ASSERT_EQ(1U, s[0]->OutputCount()); | 779     ASSERT_EQ(1U, s[0]->OutputCount()); | 
| 768     EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); | 780     EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); | 
| 769     EXPECT_EQ(kFlags_none, s[0]->flags_mode()); | 781     EXPECT_EQ(kFlags_none, s[0]->flags_mode()); | 
| 770   } | 782   } | 
| 771 } | 783 } | 
| 772 | 784 | 
| 773 | 785 | 
| 774 TEST_F(InstructionSelectorTest, Float64SubWithMinusZeroAndParameter) { | 786 TEST_F(InstructionSelectorTest, Float64SubWithMinusZeroAndParameter) { | 
| 775   { | 787   { | 
| 776     StreamBuilder m(this, kMachFloat64, kMachFloat64); | 788     StreamBuilder m(this, MachineType::Float64(), MachineType::Float64()); | 
| 777     Node* const p0 = m.Parameter(0); | 789     Node* const p0 = m.Parameter(0); | 
| 778     Node* const n = m.Float64Sub(m.Float64Constant(-0.0), p0); | 790     Node* const n = m.Float64Sub(m.Float64Constant(-0.0), p0); | 
| 779     m.Return(n); | 791     m.Return(n); | 
| 780     Stream s = m.Build(); | 792     Stream s = m.Build(); | 
| 781     ASSERT_EQ(1U, s.size()); | 793     ASSERT_EQ(1U, s.size()); | 
| 782     EXPECT_EQ(kSSEFloat64Neg, s[0]->arch_opcode()); | 794     EXPECT_EQ(kSSEFloat64Neg, s[0]->arch_opcode()); | 
| 783     ASSERT_EQ(1U, s[0]->InputCount()); | 795     ASSERT_EQ(1U, s[0]->InputCount()); | 
| 784     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); | 796     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); | 
| 785     ASSERT_EQ(1U, s[0]->OutputCount()); | 797     ASSERT_EQ(1U, s[0]->OutputCount()); | 
| 786     EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); | 798     EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); | 
| 787     EXPECT_EQ(kFlags_none, s[0]->flags_mode()); | 799     EXPECT_EQ(kFlags_none, s[0]->flags_mode()); | 
| 788   } | 800   } | 
| 789   { | 801   { | 
| 790     StreamBuilder m(this, kMachFloat64, kMachFloat64); | 802     StreamBuilder m(this, MachineType::Float64(), MachineType::Float64()); | 
| 791     Node* const p0 = m.Parameter(0); | 803     Node* const p0 = m.Parameter(0); | 
| 792     Node* const n = m.Float64Sub(m.Float64Constant(-0.0), p0); | 804     Node* const n = m.Float64Sub(m.Float64Constant(-0.0), p0); | 
| 793     m.Return(n); | 805     m.Return(n); | 
| 794     Stream s = m.Build(AVX); | 806     Stream s = m.Build(AVX); | 
| 795     ASSERT_EQ(1U, s.size()); | 807     ASSERT_EQ(1U, s.size()); | 
| 796     EXPECT_EQ(kAVXFloat64Neg, s[0]->arch_opcode()); | 808     EXPECT_EQ(kAVXFloat64Neg, s[0]->arch_opcode()); | 
| 797     ASSERT_EQ(1U, s[0]->InputCount()); | 809     ASSERT_EQ(1U, s[0]->InputCount()); | 
| 798     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); | 810     EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); | 
| 799     ASSERT_EQ(1U, s[0]->OutputCount()); | 811     ASSERT_EQ(1U, s[0]->OutputCount()); | 
| 800     EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); | 812     EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); | 
| 801     EXPECT_EQ(kFlags_none, s[0]->flags_mode()); | 813     EXPECT_EQ(kFlags_none, s[0]->flags_mode()); | 
| 802   } | 814   } | 
| 803 } | 815 } | 
| 804 | 816 | 
| 805 | 817 | 
| 806 // ----------------------------------------------------------------------------- | 818 // ----------------------------------------------------------------------------- | 
| 807 // Miscellaneous. | 819 // Miscellaneous. | 
| 808 | 820 | 
| 809 | 821 | 
| 810 TEST_F(InstructionSelectorTest, Uint32LessThanWithLoadAndLoadStackPointer) { | 822 TEST_F(InstructionSelectorTest, Uint32LessThanWithLoadAndLoadStackPointer) { | 
| 811   StreamBuilder m(this, kMachBool); | 823   StreamBuilder m(this, MachineType::Bool()); | 
| 812   Node* const sl = m.Load( | 824   Node* const sl = m.Load( | 
| 813       kMachPtr, | 825       MachineType::Pointer(), | 
| 814       m.ExternalConstant(ExternalReference::address_of_stack_limit(isolate()))); | 826       m.ExternalConstant(ExternalReference::address_of_stack_limit(isolate()))); | 
| 815   Node* const sp = m.LoadStackPointer(); | 827   Node* const sp = m.LoadStackPointer(); | 
| 816   Node* const n = m.Uint32LessThan(sl, sp); | 828   Node* const n = m.Uint32LessThan(sl, sp); | 
| 817   m.Return(n); | 829   m.Return(n); | 
| 818   Stream s = m.Build(); | 830   Stream s = m.Build(); | 
| 819   ASSERT_EQ(1U, s.size()); | 831   ASSERT_EQ(1U, s.size()); | 
| 820   EXPECT_EQ(kIA32StackCheck, s[0]->arch_opcode()); | 832   EXPECT_EQ(kIA32StackCheck, s[0]->arch_opcode()); | 
| 821   ASSERT_EQ(0U, s[0]->InputCount()); | 833   ASSERT_EQ(0U, s[0]->InputCount()); | 
| 822   ASSERT_EQ(1U, s[0]->OutputCount()); | 834   ASSERT_EQ(1U, s[0]->OutputCount()); | 
| 823   EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); | 835   EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); | 
| 824   EXPECT_EQ(kFlags_set, s[0]->flags_mode()); | 836   EXPECT_EQ(kFlags_set, s[0]->flags_mode()); | 
| 825   EXPECT_EQ(kUnsignedGreaterThan, s[0]->flags_condition()); | 837   EXPECT_EQ(kUnsignedGreaterThan, s[0]->flags_condition()); | 
| 826 } | 838 } | 
| 827 | 839 | 
| 828 | 840 | 
| 829 TEST_F(InstructionSelectorTest, Word32Clz) { | 841 TEST_F(InstructionSelectorTest, Word32Clz) { | 
| 830   StreamBuilder m(this, kMachUint32, kMachUint32); | 842   StreamBuilder m(this, MachineType::Uint32(), MachineType::Uint32()); | 
| 831   Node* const p0 = m.Parameter(0); | 843   Node* const p0 = m.Parameter(0); | 
| 832   Node* const n = m.Word32Clz(p0); | 844   Node* const n = m.Word32Clz(p0); | 
| 833   m.Return(n); | 845   m.Return(n); | 
| 834   Stream s = m.Build(); | 846   Stream s = m.Build(); | 
| 835   ASSERT_EQ(1U, s.size()); | 847   ASSERT_EQ(1U, s.size()); | 
| 836   EXPECT_EQ(kIA32Lzcnt, s[0]->arch_opcode()); | 848   EXPECT_EQ(kIA32Lzcnt, s[0]->arch_opcode()); | 
| 837   ASSERT_EQ(1U, s[0]->InputCount()); | 849   ASSERT_EQ(1U, s[0]->InputCount()); | 
| 838   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); | 850   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); | 
| 839   ASSERT_EQ(1U, s[0]->OutputCount()); | 851   ASSERT_EQ(1U, s[0]->OutputCount()); | 
| 840   EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); | 852   EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); | 
| 841 } | 853 } | 
| 842 | 854 | 
| 843 }  // namespace compiler | 855 }  // namespace compiler | 
| 844 }  // namespace internal | 856 }  // namespace internal | 
| 845 }  // namespace v8 | 857 }  // namespace v8 | 
| OLD | NEW | 
|---|