@@ -268,3 +268,171 @@ define void @foo(ptr %ptrA, float %val, ptr %ptrB) {
268268 }
269269 EXPECT_EQ (Cnt, 0u );
270270}
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