[llvm] [SandboxVectorizer] Add MemSeed bundle types (PR #111584)

via llvm-commits llvm-commits at lists.llvm.org
Tue Oct 8 13:44:42 PDT 2024


https://github.com/Sterling-Augustine created https://github.com/llvm/llvm-project/pull/111584

None

>From 5bc9ea6eeebf89c57c5e5fe41466d8bc90597593 Mon Sep 17 00:00:00 2001
From: Sterling Augustine <saugustine at google.com>
Date: Tue, 8 Oct 2024 13:43:10 -0700
Subject: [PATCH] [SandboxVectorizer] Add MemSeed bundle types

---
 .../SandboxVectorizer/SeedCollector.h         | 30 ++++++++
 .../SandboxVectorizer/SeedCollectorTest.cpp   | 73 +++++++++++++++++++
 2 files changed, 103 insertions(+)

diff --git a/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/SeedCollector.h b/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/SeedCollector.h
index 460e3f675fa797..5b6fff05d2137e 100644
--- a/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/SeedCollector.h
+++ b/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/SeedCollector.h
@@ -123,5 +123,35 @@ class SeedBundle {
   }
 #endif // NDEBUG
 };
+
+template <typename LoadOrStoreT> class MemSeedBundle : public SeedBundle {
+public:
+  explicit MemSeedBundle(SmallVector<Instruction *> &&SV, ScalarEvolution &SE)
+      : SeedBundle(std::move(SV)) {
+    assert(all_of(Seeds, [](auto *S) { return isa<LoadOrStoreT>(S); }) &&
+           "Expected Load or Store instructions!");
+    auto Cmp = [&SE](Instruction *I0, Instruction *I1) {
+      return Utils::atLowerAddress(cast<LoadOrStoreT>(I0),
+                                   cast<LoadOrStoreT>(I1), SE);
+    };
+    std::sort(Seeds.begin(), Seeds.end(), Cmp);
+  }
+  explicit MemSeedBundle(LoadOrStoreT *MemI) : SeedBundle(MemI) {
+    assert(isa<LoadOrStoreT>(MemI) && "Expected Load or Store!");
+  }
+  void insert(sandboxir::Instruction *I, ScalarEvolution &SE) {
+    assert(isa<LoadOrStoreT>(I) && "Expected a Store or a Load!");
+    auto Cmp = [&SE](Instruction *I0, Instruction *I1) {
+      return Utils::atLowerAddress(cast<LoadOrStoreT>(I0),
+                                   cast<LoadOrStoreT>(I1), SE);
+    };
+    // Find the first element after I in mem. Then insert I before it.
+    insertAt(std::upper_bound(begin(), end(), I, Cmp), I);
+  }
+};
+
+using StoreSeedBundle = MemSeedBundle<sandboxir::StoreInst>;
+using LoadSeedBundle = MemSeedBundle<sandboxir::LoadInst>;
+
 } // namespace llvm::sandboxir
 #endif // LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_SEEDCOLLECTOR_H
diff --git a/llvm/unittests/Transforms/Vectorize/SandboxVectorizer/SeedCollectorTest.cpp b/llvm/unittests/Transforms/Vectorize/SandboxVectorizer/SeedCollectorTest.cpp
index 36400afeaf4c59..dd41b0a6605095 100644
--- a/llvm/unittests/Transforms/Vectorize/SandboxVectorizer/SeedCollectorTest.cpp
+++ b/llvm/unittests/Transforms/Vectorize/SandboxVectorizer/SeedCollectorTest.cpp
@@ -7,7 +7,13 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/Transforms/Vectorize/SandboxVectorizer/SeedCollector.h"
+#include "llvm/Analysis/AliasAnalysis.h"
+#include "llvm/Analysis/AssumptionCache.h"
+#include "llvm/Analysis/BasicAliasAnalysis.h"
+#include "llvm/Analysis/LoopInfo.h"
+#include "llvm/Analysis/TargetLibraryInfo.h"
 #include "llvm/AsmParser/Parser.h"
+#include "llvm/IR/Dominators.h"
 #include "llvm/SandboxIR/Function.h"
 #include "llvm/SandboxIR/Instruction.h"
 #include "llvm/Support/SourceMgr.h"
@@ -26,6 +32,12 @@ struct SeedBundleTest : public testing::Test {
     if (!M)
       Err.print("LegalityTest", errs());
   }
+  BasicBlock *getBasicBlockByName(Function &F, StringRef Name) {
+    for (BasicBlock &BB : F)
+      if (BB.getName() == Name)
+        return &BB;
+    llvm_unreachable("Expected to find basic block!");
+  }
 };
 
 TEST_F(SeedBundleTest, SeedBundle) {
@@ -123,3 +135,64 @@ define void @foo(float %v0, i32 %i0, i16 %i1, i8 %i2) {
                              /* ForcePowerOf2 */ true);
   EXPECT_EQ(Slice4.size(), 0u);
 }
+
+TEST_F(SeedBundleTest, MemSeedBundle) {
+  parseIR(C, R"IR(
+define void @foo(ptr %ptrA, float %val, ptr %ptr) {
+bb:
+  %gep0 = getelementptr float, ptr %ptr, i32 0
+  %gep1 = getelementptr float, ptr %ptr, i32 1
+  %gep2 = getelementptr float, ptr %ptr, i32 3
+  %gep3 = getelementptr float, ptr %ptr, i32 4
+  store float %val, ptr %gep0
+  store float %val, ptr %gep1
+  store float %val, ptr %gep2
+  store float %val, ptr %gep3
+
+  load float, ptr %gep0
+  load float, ptr %gep1
+  load float, ptr %gep2
+  load float, ptr %gep3
+
+  ret void
+}
+)IR");
+  Function &LLVMF = *M->getFunction("foo");
+
+  DominatorTree DT(LLVMF);
+  TargetLibraryInfoImpl TLII;
+  TargetLibraryInfo TLI(TLII);
+  DataLayout DL(M->getDataLayout());
+  LoopInfo LI(DT);
+  AssumptionCache AC(LLVMF);
+  ScalarEvolution SE(LLVMF, TLI, AC, DT, LI);
+
+  sandboxir::Context Ctx(C);
+  auto &F = *Ctx.createFunction(&LLVMF);
+  auto *BB = &*F.begin();
+  auto It = std::next(BB->begin(), 4);
+  auto *S0 = cast<sandboxir::StoreInst>(&*It++);
+  auto *S1 = cast<sandboxir::StoreInst>(&*It++);
+  auto *S2 = cast<sandboxir::StoreInst>(&*It++);
+  auto *S3 = cast<sandboxir::StoreInst>(&*It++);
+
+  // Single instruction constructor; test insert out of memory order
+  sandboxir::StoreSeedBundle SB(S3);
+  SB.insert(S1, SE);
+  SB.insert(S2, SE);
+  SB.insert(S0, SE);
+  EXPECT_THAT(SB, testing::ElementsAre(S0, S1, S2, S3));
+
+  // Instruction list constructor; test list out of order
+  auto *L0 = cast<sandboxir::LoadInst>(&*It++);
+  auto *L1 = cast<sandboxir::LoadInst>(&*It++);
+  auto *L2 = cast<sandboxir::LoadInst>(&*It++);
+  auto *L3 = cast<sandboxir::LoadInst>(&*It++);
+  SmallVector<sandboxir::Instruction *> Loads;
+  Loads.push_back(L1);
+  Loads.push_back(L3);
+  Loads.push_back(L2);
+  Loads.push_back(L0);
+  sandboxir::LoadSeedBundle LB(std::move(Loads), SE);
+  EXPECT_THAT(LB, testing::ElementsAre(L0, L1, L2, L3));
+}



More information about the llvm-commits mailing list