|
22 | 22 |
|
23 | 23 | using namespace llvm;
|
24 | 24 |
|
| 25 | +// TODO: gcc-10 has a bug that causes the below line not to compile due to some |
| 26 | +// macro-magic in gunit in combination with a class with pure-virtual |
| 27 | +// function. Once gcc-10 is no longer supported, replace this function with |
| 28 | +// something like the following: |
| 29 | +// |
| 30 | +// EXPECT_THAT(SB, testing::ElementsAre(St0, St1, St2, St3)); |
| 31 | +static void |
| 32 | +ExpectThatElementsAre(sandboxir::SeedBundle &SR, |
| 33 | + llvm::ArrayRef<sandboxir::Instruction *> Contents) { |
| 34 | + EXPECT_EQ(range_size(SR), Contents.size()); |
| 35 | + auto CI = Contents.begin(); |
| 36 | + if (range_size(SR) == Contents.size()) |
| 37 | + for (auto &S : SR) |
| 38 | + EXPECT_EQ(S, *CI++); |
| 39 | +} |
| 40 | + |
25 | 41 | struct SeedBundleTest : public testing::Test {
|
26 | 42 | LLVMContext C;
|
27 | 43 | std::unique_ptr<Module> M;
|
@@ -268,3 +284,171 @@ define void @foo(ptr %ptrA, float %val, ptr %ptrB) {
|
268 | 284 | }
|
269 | 285 | EXPECT_EQ(Cnt, 0u);
|
270 | 286 | }
|
| 287 | + |
| 288 | +TEST_F(SeedBundleTest, ConsecutiveStores) { |
| 289 | + // Where "Consecutive" means the stores address consecutive locations in |
| 290 | + // memory, but not in program order. Check to see that the collector puts them |
| 291 | + // in the proper order for vectorization. |
| 292 | + parseIR(C, R"IR( |
| 293 | +define void @foo(ptr noalias %ptr, float %val) { |
| 294 | +bb: |
| 295 | + %ptr0 = getelementptr float, ptr %ptr, i32 0 |
| 296 | + %ptr1 = getelementptr float, ptr %ptr, i32 1 |
| 297 | + %ptr2 = getelementptr float, ptr %ptr, i32 2 |
| 298 | + %ptr3 = getelementptr float, ptr %ptr, i32 3 |
| 299 | + store float %val, ptr %ptr0 |
| 300 | + store float %val, ptr %ptr2 |
| 301 | + store float %val, ptr %ptr1 |
| 302 | + store float %val, ptr %ptr3 |
| 303 | + ret void |
| 304 | +} |
| 305 | +)IR"); |
| 306 | + Function &LLVMF = *M->getFunction("foo"); |
| 307 | + DominatorTree DT(LLVMF); |
| 308 | + TargetLibraryInfoImpl TLII; |
| 309 | + TargetLibraryInfo TLI(TLII); |
| 310 | + DataLayout DL(M->getDataLayout()); |
| 311 | + LoopInfo LI(DT); |
| 312 | + AssumptionCache AC(LLVMF); |
| 313 | + ScalarEvolution SE(LLVMF, TLI, AC, DT, LI); |
| 314 | + |
| 315 | + sandboxir::Context Ctx(C); |
| 316 | + auto &F = *Ctx.createFunction(&LLVMF); |
| 317 | + auto BB = F.begin(); |
| 318 | + sandboxir::SeedCollector SC(&*BB, SE); |
| 319 | + |
| 320 | + // Find the stores |
| 321 | + auto It = std::next(BB->begin(), 4); |
| 322 | + // StX with X as the order by offset in memory |
| 323 | + auto *St0 = &*It++; |
| 324 | + auto *St2 = &*It++; |
| 325 | + auto *St1 = &*It++; |
| 326 | + auto *St3 = &*It++; |
| 327 | + |
| 328 | + auto StoreSeedsRange = SC.getStoreSeeds(); |
| 329 | + auto &SB = *StoreSeedsRange.begin(); |
| 330 | + // Expect just one vector of store seeds |
| 331 | + EXPECT_EQ(range_size(StoreSeedsRange), 1u); |
| 332 | + ExpectThatElementsAre(SB, {St0, St1, St2, St3}); |
| 333 | +} |
| 334 | + |
| 335 | +TEST_F(SeedBundleTest, StoresWithGaps) { |
| 336 | + parseIR(C, R"IR( |
| 337 | +define void @foo(ptr noalias %ptr, float %val) { |
| 338 | +bb: |
| 339 | + %ptr0 = getelementptr float, ptr %ptr, i32 0 |
| 340 | + %ptr1 = getelementptr float, ptr %ptr, i32 3 |
| 341 | + %ptr2 = getelementptr float, ptr %ptr, i32 5 |
| 342 | + %ptr3 = getelementptr float, ptr %ptr, i32 7 |
| 343 | + store float %val, ptr %ptr0 |
| 344 | + store float %val, ptr %ptr2 |
| 345 | + store float %val, ptr %ptr1 |
| 346 | + store float %val, ptr %ptr3 |
| 347 | + ret void |
| 348 | +} |
| 349 | +)IR"); |
| 350 | + Function &LLVMF = *M->getFunction("foo"); |
| 351 | + DominatorTree DT(LLVMF); |
| 352 | + TargetLibraryInfoImpl TLII; |
| 353 | + TargetLibraryInfo TLI(TLII); |
| 354 | + DataLayout DL(M->getDataLayout()); |
| 355 | + LoopInfo LI(DT); |
| 356 | + AssumptionCache AC(LLVMF); |
| 357 | + ScalarEvolution SE(LLVMF, TLI, AC, DT, LI); |
| 358 | + |
| 359 | + sandboxir::Context Ctx(C); |
| 360 | + auto &F = *Ctx.createFunction(&LLVMF); |
| 361 | + auto BB = F.begin(); |
| 362 | + sandboxir::SeedCollector SC(&*BB, SE); |
| 363 | + |
| 364 | + // Find the stores |
| 365 | + auto It = std::next(BB->begin(), 4); |
| 366 | + // StX with X as the order by offset in memory |
| 367 | + auto *St0 = &*It++; |
| 368 | + auto *St2 = &*It++; |
| 369 | + auto *St1 = &*It++; |
| 370 | + auto *St3 = &*It++; |
| 371 | + |
| 372 | + auto StoreSeedsRange = SC.getStoreSeeds(); |
| 373 | + auto &SB = *StoreSeedsRange.begin(); |
| 374 | + // Expect just one vector of store seeds |
| 375 | + EXPECT_EQ(range_size(StoreSeedsRange), 1u); |
| 376 | + ExpectThatElementsAre(SB, {St0, St1, St2, St3}); |
| 377 | +} |
| 378 | + |
| 379 | +TEST_F(SeedBundleTest, VectorStores) { |
| 380 | + parseIR(C, R"IR( |
| 381 | +define void @foo(ptr noalias %ptr, <2 x float> %val) { |
| 382 | +bb: |
| 383 | + %ptr0 = getelementptr float, ptr %ptr, i32 0 |
| 384 | + %ptr1 = getelementptr float, ptr %ptr, i32 1 |
| 385 | + store <2 x float> %val, ptr %ptr1 |
| 386 | + store <2 x float> %val, ptr %ptr0 |
| 387 | + ret void |
| 388 | +} |
| 389 | +)IR"); |
| 390 | + Function &LLVMF = *M->getFunction("foo"); |
| 391 | + DominatorTree DT(LLVMF); |
| 392 | + TargetLibraryInfoImpl TLII; |
| 393 | + TargetLibraryInfo TLI(TLII); |
| 394 | + DataLayout DL(M->getDataLayout()); |
| 395 | + LoopInfo LI(DT); |
| 396 | + AssumptionCache AC(LLVMF); |
| 397 | + ScalarEvolution SE(LLVMF, TLI, AC, DT, LI); |
| 398 | + |
| 399 | + sandboxir::Context Ctx(C); |
| 400 | + auto &F = *Ctx.createFunction(&LLVMF); |
| 401 | + auto BB = F.begin(); |
| 402 | + sandboxir::SeedCollector SC(&*BB, SE); |
| 403 | + |
| 404 | + // Find the stores |
| 405 | + auto It = std::next(BB->begin(), 2); |
| 406 | + // StX with X as the order by offset in memory |
| 407 | + auto *St1 = &*It++; |
| 408 | + auto *St0 = &*It++; |
| 409 | + |
| 410 | + auto StoreSeedsRange = SC.getStoreSeeds(); |
| 411 | + EXPECT_EQ(range_size(StoreSeedsRange), 1u); |
| 412 | + auto &SB = *StoreSeedsRange.begin(); |
| 413 | + ExpectThatElementsAre(SB, {St0, St1}); |
| 414 | +} |
| 415 | + |
| 416 | +TEST_F(SeedBundleTest, MixedScalarVectors) { |
| 417 | + parseIR(C, R"IR( |
| 418 | +define void @foo(ptr noalias %ptr, float %v, <2 x float> %val) { |
| 419 | +bb: |
| 420 | + %ptr0 = getelementptr float, ptr %ptr, i32 0 |
| 421 | + %ptr1 = getelementptr float, ptr %ptr, i32 1 |
| 422 | + %ptr3 = getelementptr float, ptr %ptr, i32 3 |
| 423 | + store float %v, ptr %ptr0 |
| 424 | + store float %v, ptr %ptr3 |
| 425 | + store <2 x float> %val, ptr %ptr1 |
| 426 | + ret void |
| 427 | +} |
| 428 | +)IR"); |
| 429 | + Function &LLVMF = *M->getFunction("foo"); |
| 430 | + DominatorTree DT(LLVMF); |
| 431 | + TargetLibraryInfoImpl TLII; |
| 432 | + TargetLibraryInfo TLI(TLII); |
| 433 | + DataLayout DL(M->getDataLayout()); |
| 434 | + LoopInfo LI(DT); |
| 435 | + AssumptionCache AC(LLVMF); |
| 436 | + ScalarEvolution SE(LLVMF, TLI, AC, DT, LI); |
| 437 | + |
| 438 | + sandboxir::Context Ctx(C); |
| 439 | + auto &F = *Ctx.createFunction(&LLVMF); |
| 440 | + auto BB = F.begin(); |
| 441 | + sandboxir::SeedCollector SC(&*BB, SE); |
| 442 | + |
| 443 | + // Find the stores |
| 444 | + auto It = std::next(BB->begin(), 3); |
| 445 | + // StX with X as the order by offset in memory |
| 446 | + auto *St0 = &*It++; |
| 447 | + auto *St3 = &*It++; |
| 448 | + auto *St1 = &*It++; |
| 449 | + |
| 450 | + auto StoreSeedsRange = SC.getStoreSeeds(); |
| 451 | + EXPECT_EQ(range_size(StoreSeedsRange), 1u); |
| 452 | + auto &SB = *StoreSeedsRange.begin(); |
| 453 | + ExpectThatElementsAre(SB, {St0, St1, St3}); |
| 454 | +} |
0 commit comments