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 "src/compiler/instruction-selector-unittest.h" | 5 #include "src/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 |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
182 | 182 |
183 | 183 |
184 TEST_P(InstructionSelectorMemoryAccessTest, LoadWithImmediateBase) { | 184 TEST_P(InstructionSelectorMemoryAccessTest, LoadWithImmediateBase) { |
185 const MemoryAccess memacc = GetParam(); | 185 const MemoryAccess memacc = GetParam(); |
186 TRACED_FOREACH(int32_t, base, kImmediates) { | 186 TRACED_FOREACH(int32_t, base, kImmediates) { |
187 StreamBuilder m(this, memacc.type, kMachPtr); | 187 StreamBuilder m(this, memacc.type, kMachPtr); |
188 m.Return(m.Load(memacc.type, m.Int32Constant(base), m.Parameter(0))); | 188 m.Return(m.Load(memacc.type, m.Int32Constant(base), m.Parameter(0))); |
189 Stream s = m.Build(); | 189 Stream s = m.Build(); |
190 ASSERT_EQ(1U, s.size()); | 190 ASSERT_EQ(1U, s.size()); |
191 EXPECT_EQ(memacc.load_opcode, s[0]->arch_opcode()); | 191 EXPECT_EQ(memacc.load_opcode, s[0]->arch_opcode()); |
| 192 if (base == 0) { |
| 193 ASSERT_EQ(1U, s[0]->InputCount()); |
| 194 } else { |
192 ASSERT_EQ(2U, s[0]->InputCount()); | 195 ASSERT_EQ(2U, s[0]->InputCount()); |
193 ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind()); | 196 ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind()); |
194 EXPECT_EQ(base, s.ToInt32(s[0]->InputAt(1))); | 197 EXPECT_EQ(base, s.ToInt32(s[0]->InputAt(1))); |
| 198 } |
195 EXPECT_EQ(1U, s[0]->OutputCount()); | 199 EXPECT_EQ(1U, s[0]->OutputCount()); |
196 } | 200 } |
197 } | 201 } |
198 | 202 |
199 | 203 |
200 TEST_P(InstructionSelectorMemoryAccessTest, LoadWithImmediateIndex) { | 204 TEST_P(InstructionSelectorMemoryAccessTest, LoadWithImmediateIndex) { |
201 const MemoryAccess memacc = GetParam(); | 205 const MemoryAccess memacc = GetParam(); |
202 TRACED_FOREACH(int32_t, index, kImmediates) { | 206 TRACED_FOREACH(int32_t, index, kImmediates) { |
203 StreamBuilder m(this, memacc.type, kMachPtr); | 207 StreamBuilder m(this, memacc.type, kMachPtr); |
204 m.Return(m.Load(memacc.type, m.Parameter(0), m.Int32Constant(index))); | 208 m.Return(m.Load(memacc.type, m.Parameter(0), m.Int32Constant(index))); |
205 Stream s = m.Build(); | 209 Stream s = m.Build(); |
206 ASSERT_EQ(1U, s.size()); | 210 ASSERT_EQ(1U, s.size()); |
207 EXPECT_EQ(memacc.load_opcode, s[0]->arch_opcode()); | 211 EXPECT_EQ(memacc.load_opcode, s[0]->arch_opcode()); |
| 212 if (index == 0) { |
| 213 ASSERT_EQ(1U, s[0]->InputCount()); |
| 214 } else { |
208 ASSERT_EQ(2U, s[0]->InputCount()); | 215 ASSERT_EQ(2U, s[0]->InputCount()); |
209 ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind()); | 216 ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind()); |
210 EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1))); | 217 EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1))); |
| 218 } |
211 EXPECT_EQ(1U, s[0]->OutputCount()); | 219 EXPECT_EQ(1U, s[0]->OutputCount()); |
212 } | 220 } |
213 } | 221 } |
214 | 222 |
215 | 223 |
216 TEST_P(InstructionSelectorMemoryAccessTest, StoreWithParameters) { | 224 TEST_P(InstructionSelectorMemoryAccessTest, StoreWithParameters) { |
217 const MemoryAccess memacc = GetParam(); | 225 const MemoryAccess memacc = GetParam(); |
218 StreamBuilder m(this, kMachInt32, kMachPtr, kMachInt32, memacc.type); | 226 StreamBuilder m(this, kMachInt32, kMachPtr, kMachInt32, memacc.type); |
219 m.Store(memacc.type, m.Parameter(0), m.Parameter(1), m.Parameter(2)); | 227 m.Store(memacc.type, m.Parameter(0), m.Parameter(1), m.Parameter(2)); |
220 m.Return(m.Int32Constant(0)); | 228 m.Return(m.Int32Constant(0)); |
221 Stream s = m.Build(); | 229 Stream s = m.Build(); |
222 ASSERT_EQ(1U, s.size()); | 230 ASSERT_EQ(1U, s.size()); |
223 EXPECT_EQ(memacc.store_opcode, s[0]->arch_opcode()); | 231 EXPECT_EQ(memacc.store_opcode, s[0]->arch_opcode()); |
224 EXPECT_EQ(3U, s[0]->InputCount()); | 232 EXPECT_EQ(3U, s[0]->InputCount()); |
225 EXPECT_EQ(0U, s[0]->OutputCount()); | 233 EXPECT_EQ(0U, s[0]->OutputCount()); |
226 } | 234 } |
227 | 235 |
228 | 236 |
229 TEST_P(InstructionSelectorMemoryAccessTest, StoreWithImmediateBase) { | 237 TEST_P(InstructionSelectorMemoryAccessTest, StoreWithImmediateBase) { |
230 const MemoryAccess memacc = GetParam(); | 238 const MemoryAccess memacc = GetParam(); |
231 TRACED_FOREACH(int32_t, base, kImmediates) { | 239 TRACED_FOREACH(int32_t, base, kImmediates) { |
232 StreamBuilder m(this, kMachInt32, kMachInt32, memacc.type); | 240 StreamBuilder m(this, kMachInt32, kMachInt32, memacc.type); |
233 m.Store(memacc.type, m.Int32Constant(base), m.Parameter(0), m.Parameter(1)); | 241 m.Store(memacc.type, m.Int32Constant(base), m.Parameter(0), m.Parameter(1)); |
234 m.Return(m.Int32Constant(0)); | 242 m.Return(m.Int32Constant(0)); |
235 Stream s = m.Build(); | 243 Stream s = m.Build(); |
236 ASSERT_EQ(1U, s.size()); | 244 ASSERT_EQ(1U, s.size()); |
237 EXPECT_EQ(memacc.store_opcode, s[0]->arch_opcode()); | 245 EXPECT_EQ(memacc.store_opcode, s[0]->arch_opcode()); |
| 246 if (base == 0) { |
| 247 ASSERT_EQ(2U, s[0]->InputCount()); |
| 248 } else { |
238 ASSERT_EQ(3U, s[0]->InputCount()); | 249 ASSERT_EQ(3U, s[0]->InputCount()); |
239 ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind()); | 250 ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind()); |
240 EXPECT_EQ(base, s.ToInt32(s[0]->InputAt(1))); | 251 EXPECT_EQ(base, s.ToInt32(s[0]->InputAt(1))); |
| 252 } |
241 EXPECT_EQ(0U, s[0]->OutputCount()); | 253 EXPECT_EQ(0U, s[0]->OutputCount()); |
242 } | 254 } |
243 } | 255 } |
244 | 256 |
245 | 257 |
246 TEST_P(InstructionSelectorMemoryAccessTest, StoreWithImmediateIndex) { | 258 TEST_P(InstructionSelectorMemoryAccessTest, StoreWithImmediateIndex) { |
247 const MemoryAccess memacc = GetParam(); | 259 const MemoryAccess memacc = GetParam(); |
248 TRACED_FOREACH(int32_t, index, kImmediates) { | 260 TRACED_FOREACH(int32_t, index, kImmediates) { |
249 StreamBuilder m(this, kMachInt32, kMachPtr, memacc.type); | 261 StreamBuilder m(this, kMachInt32, kMachPtr, memacc.type); |
250 m.Store(memacc.type, m.Parameter(0), m.Int32Constant(index), | 262 m.Store(memacc.type, m.Parameter(0), m.Int32Constant(index), |
251 m.Parameter(1)); | 263 m.Parameter(1)); |
252 m.Return(m.Int32Constant(0)); | 264 m.Return(m.Int32Constant(0)); |
253 Stream s = m.Build(); | 265 Stream s = m.Build(); |
254 ASSERT_EQ(1U, s.size()); | 266 ASSERT_EQ(1U, s.size()); |
255 EXPECT_EQ(memacc.store_opcode, s[0]->arch_opcode()); | 267 EXPECT_EQ(memacc.store_opcode, s[0]->arch_opcode()); |
256 ASSERT_EQ(3U, s[0]->InputCount()); | 268 if (index == 0) { |
257 ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind()); | 269 ASSERT_EQ(2U, s[0]->InputCount()); |
258 EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1))); | 270 } else { |
| 271 ASSERT_EQ(3U, s[0]->InputCount()); |
| 272 ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind()); |
| 273 EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1))); |
| 274 } |
259 EXPECT_EQ(0U, s[0]->OutputCount()); | 275 EXPECT_EQ(0U, s[0]->OutputCount()); |
260 } | 276 } |
261 } | 277 } |
262 | 278 |
263 | 279 |
264 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, | 280 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, |
265 InstructionSelectorMemoryAccessTest, | 281 InstructionSelectorMemoryAccessTest, |
266 ::testing::ValuesIn(kMemoryAccesses)); | 282 ::testing::ValuesIn(kMemoryAccesses)); |
267 | 283 |
| 284 |
| 285 // ----------------------------------------------------------------------------- |
| 286 // AddressingMode for loads and stores. |
| 287 |
| 288 class AddressingModeUnitTest : public InstructionSelectorTest { |
| 289 public: |
| 290 AddressingModeUnitTest() : m(NULL) { Reset(); } |
| 291 ~AddressingModeUnitTest() { delete m; } |
| 292 |
| 293 void Run(Node* base, Node* index, AddressingMode mode) { |
| 294 Node* load = m->Load(kMachInt32, base, index); |
| 295 m->Store(kMachInt32, base, index, load); |
| 296 m->Return(m->Int32Constant(0)); |
| 297 Stream s = m->Build(); |
| 298 ASSERT_EQ(2U, s.size()); |
| 299 EXPECT_EQ(mode, s[0]->addressing_mode()); |
| 300 EXPECT_EQ(mode, s[1]->addressing_mode()); |
| 301 } |
| 302 |
| 303 Node* zero; |
| 304 Node* null_ptr; |
| 305 Node* non_zero; |
| 306 Node* base_reg; // opaque value to generate base as register |
| 307 Node* index_reg; // opaque value to generate index as register |
| 308 Node* scales[4]; |
| 309 StreamBuilder* m; |
| 310 |
| 311 void Reset() { |
| 312 delete m; |
| 313 m = new StreamBuilder(this, kMachInt32, kMachInt32, kMachInt32); |
| 314 zero = m->Int32Constant(0); |
| 315 null_ptr = m->Int32Constant(0); |
| 316 non_zero = m->Int32Constant(127); |
| 317 base_reg = m->Parameter(0); |
| 318 index_reg = m->Parameter(0); |
| 319 |
| 320 scales[0] = m->Int32Constant(1); |
| 321 scales[1] = m->Int32Constant(2); |
| 322 scales[2] = m->Int32Constant(4); |
| 323 scales[3] = m->Int32Constant(8); |
| 324 } |
| 325 }; |
| 326 |
| 327 |
| 328 TEST_F(AddressingModeUnitTest, AddressingMode_MR) { |
| 329 Node* base = base_reg; |
| 330 Node* index = zero; |
| 331 Run(base, index, kMode_MR); |
| 332 } |
| 333 |
| 334 |
| 335 TEST_F(AddressingModeUnitTest, AddressingMode_MRI) { |
| 336 Node* base = base_reg; |
| 337 Node* index = non_zero; |
| 338 Run(base, index, kMode_MRI); |
| 339 } |
| 340 |
| 341 |
| 342 TEST_F(AddressingModeUnitTest, AddressingMode_MR1) { |
| 343 Node* base = base_reg; |
| 344 Node* index = index_reg; |
| 345 Run(base, index, kMode_MR1); |
| 346 } |
| 347 |
| 348 |
| 349 TEST_F(AddressingModeUnitTest, AddressingMode_MRN) { |
| 350 AddressingMode expected[] = {kMode_MR1, kMode_MR2, kMode_MR4, kMode_MR8}; |
| 351 for (size_t i = 0; i < arraysize(scales); ++i) { |
| 352 Reset(); |
| 353 Node* base = base_reg; |
| 354 Node* index = m->Int32Mul(index_reg, scales[i]); |
| 355 Run(base, index, expected[i]); |
| 356 } |
| 357 } |
| 358 |
| 359 |
| 360 TEST_F(AddressingModeUnitTest, AddressingMode_MR1I) { |
| 361 Node* base = base_reg; |
| 362 Node* index = m->Int32Add(index_reg, non_zero); |
| 363 Run(base, index, kMode_MR1I); |
| 364 } |
| 365 |
| 366 |
| 367 TEST_F(AddressingModeUnitTest, AddressingMode_MRNI) { |
| 368 AddressingMode expected[] = {kMode_MR1I, kMode_MR2I, kMode_MR4I, kMode_MR8I}; |
| 369 for (size_t i = 0; i < arraysize(scales); ++i) { |
| 370 Reset(); |
| 371 Node* base = base_reg; |
| 372 Node* index = m->Int32Add(m->Int32Mul(index_reg, scales[i]), non_zero); |
| 373 Run(base, index, expected[i]); |
| 374 } |
| 375 } |
| 376 |
| 377 |
| 378 TEST_F(AddressingModeUnitTest, AddressingMode_M1) { |
| 379 Node* base = null_ptr; |
| 380 Node* index = index_reg; |
| 381 Run(base, index, kMode_MR); |
| 382 } |
| 383 |
| 384 |
| 385 TEST_F(AddressingModeUnitTest, AddressingMode_MN) { |
| 386 AddressingMode expected[] = {kMode_MR, kMode_M2, kMode_M4, kMode_M8}; |
| 387 for (size_t i = 0; i < arraysize(scales); ++i) { |
| 388 Reset(); |
| 389 Node* base = null_ptr; |
| 390 Node* index = m->Int32Mul(index_reg, scales[i]); |
| 391 Run(base, index, expected[i]); |
| 392 } |
| 393 } |
| 394 |
| 395 |
| 396 TEST_F(AddressingModeUnitTest, AddressingMode_M1I) { |
| 397 Node* base = null_ptr; |
| 398 Node* index = m->Int32Add(index_reg, non_zero); |
| 399 Run(base, index, kMode_MRI); |
| 400 } |
| 401 |
| 402 |
| 403 TEST_F(AddressingModeUnitTest, AddressingMode_MNI) { |
| 404 AddressingMode expected[] = {kMode_MRI, kMode_M2I, kMode_M4I, kMode_M8I}; |
| 405 for (size_t i = 0; i < arraysize(scales); ++i) { |
| 406 Reset(); |
| 407 Node* base = null_ptr; |
| 408 Node* index = m->Int32Add(m->Int32Mul(index_reg, scales[i]), non_zero); |
| 409 Run(base, index, expected[i]); |
| 410 } |
| 411 } |
| 412 |
| 413 |
| 414 TEST_F(AddressingModeUnitTest, AddressingMode_MI) { |
| 415 Node* bases[] = {null_ptr, non_zero}; |
| 416 Node* indices[] = {zero, non_zero}; |
| 417 for (size_t i = 0; i < arraysize(bases); ++i) { |
| 418 for (size_t j = 0; j < arraysize(indices); ++j) { |
| 419 Reset(); |
| 420 Node* base = bases[i]; |
| 421 Node* index = indices[j]; |
| 422 Run(base, index, kMode_MI); |
| 423 } |
| 424 } |
| 425 } |
| 426 |
268 } // namespace compiler | 427 } // namespace compiler |
269 } // namespace internal | 428 } // namespace internal |
270 } // namespace v8 | 429 } // namespace v8 |
OLD | NEW |