| 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 |