@@ -268,3 +268,171 @@ define void @foo(ptr %ptrA, float %val, ptr %ptrB) {
268
268
}
269
269
EXPECT_EQ (Cnt, 0u );
270
270
}
271
+
272
+ TEST_F (SeedBundleTest, ConsecutiveStores) {
273
+ // Where "Consecutive" means the stores address consecutive locations in
274
+ // memory, but not in program order. Check to see that the collector puts them
275
+ // in the proper order for vectorization.
276
+ parseIR (C, R"IR(
277
+ define void @foo(ptr noalias %ptr, float %val) {
278
+ bb:
279
+ %ptr0 = getelementptr float, ptr %ptr, i32 0
280
+ %ptr1 = getelementptr float, ptr %ptr, i32 1
281
+ %ptr2 = getelementptr float, ptr %ptr, i32 2
282
+ %ptr3 = getelementptr float, ptr %ptr, i32 3
283
+ store float %val, ptr %ptr0
284
+ store float %val, ptr %ptr2
285
+ store float %val, ptr %ptr1
286
+ store float %val, ptr %ptr3
287
+ ret void
288
+ }
289
+ )IR" );
290
+ Function &LLVMF = *M->getFunction (" foo" );
291
+ DominatorTree DT (LLVMF);
292
+ TargetLibraryInfoImpl TLII;
293
+ TargetLibraryInfo TLI (TLII);
294
+ DataLayout DL (M->getDataLayout ());
295
+ LoopInfo LI (DT);
296
+ AssumptionCache AC (LLVMF);
297
+ ScalarEvolution SE (LLVMF, TLI, AC, DT, LI);
298
+
299
+ sandboxir::Context Ctx (C);
300
+ auto &F = *Ctx.createFunction (&LLVMF);
301
+ auto BB = F.begin ();
302
+ sandboxir::SeedCollector SC (&*BB, SE);
303
+
304
+ // Find the stores
305
+ auto It = std::next (BB->begin (), 4 );
306
+ // StX with X as the order by offset in memory
307
+ auto *St0 = &*It++;
308
+ auto *St2 = &*It++;
309
+ auto *St1 = &*It++;
310
+ auto *St3 = &*It++;
311
+
312
+ auto StoreSeedsRange = SC.getStoreSeeds ();
313
+ auto &SB = *StoreSeedsRange.begin ();
314
+ // Expect just one vector of store seeds
315
+ EXPECT_EQ (range_size (StoreSeedsRange), 1u );
316
+ EXPECT_THAT (SB, testing::ElementsAre (St0, St1, St2, St3));
317
+ }
318
+
319
+ TEST_F (SeedBundleTest, StoresWithGaps) {
320
+ parseIR (C, R"IR(
321
+ define void @foo(ptr noalias %ptr, float %val) {
322
+ bb:
323
+ %ptr0 = getelementptr float, ptr %ptr, i32 0
324
+ %ptr1 = getelementptr float, ptr %ptr, i32 3
325
+ %ptr2 = getelementptr float, ptr %ptr, i32 5
326
+ %ptr3 = getelementptr float, ptr %ptr, i32 7
327
+ store float %val, ptr %ptr0
328
+ store float %val, ptr %ptr2
329
+ store float %val, ptr %ptr1
330
+ store float %val, ptr %ptr3
331
+ ret void
332
+ }
333
+ )IR" );
334
+ Function &LLVMF = *M->getFunction (" foo" );
335
+ DominatorTree DT (LLVMF);
336
+ TargetLibraryInfoImpl TLII;
337
+ TargetLibraryInfo TLI (TLII);
338
+ DataLayout DL (M->getDataLayout ());
339
+ LoopInfo LI (DT);
340
+ AssumptionCache AC (LLVMF);
341
+ ScalarEvolution SE (LLVMF, TLI, AC, DT, LI);
342
+
343
+ sandboxir::Context Ctx (C);
344
+ auto &F = *Ctx.createFunction (&LLVMF);
345
+ auto BB = F.begin ();
346
+ sandboxir::SeedCollector SC (&*BB, SE);
347
+
348
+ // Find the stores
349
+ auto It = std::next (BB->begin (), 4 );
350
+ // StX with X as the order by offset in memory
351
+ auto *St0 = &*It++;
352
+ auto *St2 = &*It++;
353
+ auto *St1 = &*It++;
354
+ auto *St3 = &*It++;
355
+
356
+ auto StoreSeedsRange = SC.getStoreSeeds ();
357
+ auto &SB = *StoreSeedsRange.begin ();
358
+ // Expect just one vector of store seeds
359
+ EXPECT_EQ (range_size (StoreSeedsRange), 1u );
360
+ EXPECT_THAT (SB, testing::ElementsAre (St0, St1, St2, St3));
361
+ }
362
+
363
+ TEST_F (SeedBundleTest, VectorStores) {
364
+ parseIR (C, R"IR(
365
+ define void @foo(ptr noalias %ptr, <2 x float> %val) {
366
+ bb:
367
+ %ptr0 = getelementptr float, ptr %ptr, i32 0
368
+ %ptr1 = getelementptr float, ptr %ptr, i32 1
369
+ store <2 x float> %val, ptr %ptr1
370
+ store <2 x float> %val, ptr %ptr0
371
+ ret void
372
+ }
373
+ )IR" );
374
+ Function &LLVMF = *M->getFunction (" foo" );
375
+ DominatorTree DT (LLVMF);
376
+ TargetLibraryInfoImpl TLII;
377
+ TargetLibraryInfo TLI (TLII);
378
+ DataLayout DL (M->getDataLayout ());
379
+ LoopInfo LI (DT);
380
+ AssumptionCache AC (LLVMF);
381
+ ScalarEvolution SE (LLVMF, TLI, AC, DT, LI);
382
+
383
+ sandboxir::Context Ctx (C);
384
+ auto &F = *Ctx.createFunction (&LLVMF);
385
+ auto BB = F.begin ();
386
+ sandboxir::SeedCollector SC (&*BB, SE);
387
+
388
+ // Find the stores
389
+ auto It = std::next (BB->begin (), 2 );
390
+ // StX with X as the order by offset in memory
391
+ auto *St1 = &*It++;
392
+ auto *St0 = &*It++;
393
+
394
+ auto StoreSeedsRange = SC.getStoreSeeds ();
395
+ EXPECT_EQ (range_size (StoreSeedsRange), 1u );
396
+ auto &SB = *StoreSeedsRange.begin ();
397
+ EXPECT_THAT (SB, testing::ElementsAre (St0, St1));
398
+ }
399
+
400
+ TEST_F (SeedBundleTest, MixedScalarVectors) {
401
+ parseIR (C, R"IR(
402
+ define void @foo(ptr noalias %ptr, float %v, <2 x float> %val) {
403
+ bb:
404
+ %ptr0 = getelementptr float, ptr %ptr, i32 0
405
+ %ptr1 = getelementptr float, ptr %ptr, i32 1
406
+ %ptr3 = getelementptr float, ptr %ptr, i32 3
407
+ store float %v, ptr %ptr0
408
+ store float %v, ptr %ptr3
409
+ store <2 x float> %val, ptr %ptr1
410
+ ret void
411
+ }
412
+ )IR" );
413
+ Function &LLVMF = *M->getFunction (" foo" );
414
+ DominatorTree DT (LLVMF);
415
+ TargetLibraryInfoImpl TLII;
416
+ TargetLibraryInfo TLI (TLII);
417
+ DataLayout DL (M->getDataLayout ());
418
+ LoopInfo LI (DT);
419
+ AssumptionCache AC (LLVMF);
420
+ ScalarEvolution SE (LLVMF, TLI, AC, DT, LI);
421
+
422
+ sandboxir::Context Ctx (C);
423
+ auto &F = *Ctx.createFunction (&LLVMF);
424
+ auto BB = F.begin ();
425
+ sandboxir::SeedCollector SC (&*BB, SE);
426
+
427
+ // Find the stores
428
+ auto It = std::next (BB->begin (), 3 );
429
+ // StX with X as the order by offset in memory
430
+ auto *St0 = &*It++;
431
+ auto *St3 = &*It++;
432
+ auto *St1 = &*It++;
433
+
434
+ auto StoreSeedsRange = SC.getStoreSeeds ();
435
+ EXPECT_EQ (range_size (StoreSeedsRange), 1u );
436
+ auto &SB = *StoreSeedsRange.begin ();
437
+ EXPECT_THAT (SB, testing::ElementsAre (St0, St1, St3));
438
+ }
0 commit comments