[llvm] [SandboxVectorizer] Use sbvec-passes flag to create a pipeline of Region passes after BottomUpVec. (PR #111223)

Jorge Gorbe Moya via llvm-commits llvm-commits at lists.llvm.org
Mon Oct 7 14:37:35 PDT 2024


https://github.com/slackito updated https://github.com/llvm/llvm-project/pull/111223

>From 1c1145af0b06bfe5e4b91610adc2b7c61ae8b17c Mon Sep 17 00:00:00 2001
From: Jorge Gorbe Moya <jgorbe at google.com>
Date: Fri, 4 Oct 2024 16:26:31 -0700
Subject: [PATCH 1/4] [SandboxVectorizer] Use sbvec-passes flag to create a
 pipeline of Region passes after BottomUpVec.

The main change is that the main SandboxVectorizer pass no longer has a
pipeline of function passes. Now it consists of a BottomUpVec pass and
a pipeline of region passes after it.

BottomUpVec now takes a RegionPassManager as an argument to the
constructor. This argument is currently stored and not used, but the
idea is that after BottomUpVec vectorizes a region of a function, we'll
run successive optimization passes on that region.

I've also moved creation of the pass pipeline out of the `run` method to
the SandboxVectorizer constructor.
---
 .../SandboxVectorizer/Passes/BottomUpVec.h    |  7 +-
 .../SandboxVectorizer/Passes/NullPass.h       | 19 +++++
 .../SandboxVectorizer/SandboxVectorizer.h     | 19 ++++-
 .../SandboxVectorizer/Passes/BottomUpVec.cpp  |  2 +
 .../SandboxVectorizer/SandboxVectorizer.cpp   | 80 +++++++++++++------
 .../default_pass_pipeline.ll                  |  3 +-
 .../SandboxVectorizer/user_pass_pipeline.ll   |  8 +-
 7 files changed, 106 insertions(+), 32 deletions(-)
 create mode 100644 llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/Passes/NullPass.h

diff --git a/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.h b/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.h
index a2108f07c28e50..e3a35b09d0e296 100644
--- a/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.h
+++ b/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.h
@@ -19,14 +19,19 @@
 
 namespace llvm::sandboxir {
 
+class RegionPassManager;
+
 class BottomUpVec final : public FunctionPass {
   bool Change = false;
   LegalityAnalysis Legality;
   void vectorizeRec(ArrayRef<Value *> Bndl);
   void tryVectorize(ArrayRef<Value *> Seeds);
 
+  [[maybe_unused]] RegionPassManager *RPM;
+
 public:
-  BottomUpVec() : FunctionPass("bottom-up-vec") {}
+  BottomUpVec(RegionPassManager *RPM)
+      : FunctionPass("bottom-up-vec"), RPM(RPM) {}
   bool runOnFunction(Function &F) final;
 };
 
diff --git a/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/Passes/NullPass.h b/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/Passes/NullPass.h
new file mode 100644
index 00000000000000..75b9f42520156c
--- /dev/null
+++ b/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/Passes/NullPass.h
@@ -0,0 +1,19 @@
+#ifndef LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_PASSES_NULLPASS_H
+#define LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_PASSES_NULLPASS_H
+
+#include "llvm/SandboxIR/Pass.h"
+
+namespace llvm::sandboxir {
+
+class Region;
+
+/// A Region pass that does nothing, for use as a placeholder in tests.
+class NullPass final : public RegionPass {
+public:
+  NullPass() : RegionPass("null") {}
+  bool runOnRegion(Region &R) final { return false; }
+};
+
+} // namespace llvm::sandboxir
+
+#endif // LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_PASSES_NULLPASS_H
diff --git a/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizer.h b/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizer.h
index dd9f02d3272643..4547217773cd01 100644
--- a/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizer.h
+++ b/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizer.h
@@ -8,7 +8,11 @@
 #ifndef LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_SANDBOXVECTORIZER_H
 #define LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_SANDBOXVECTORIZER_H
 
+#include <memory>
+
 #include "llvm/IR/PassManager.h"
+#include "llvm/SandboxIR/PassManager.h"
+#include "llvm/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.h"
 
 namespace llvm {
 
@@ -17,10 +21,21 @@ class TargetTransformInfo;
 class SandboxVectorizerPass : public PassInfoMixin<SandboxVectorizerPass> {
   TargetTransformInfo *TTI = nullptr;
 
-public:
-  PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
+  // Used to build a RegionPass pipeline to be run on Regions created by the
+  // bottom-up vectorization pass.
+  sandboxir::PassRegistry PR;
+
+  // The main vectorizer pass.
+  std::unique_ptr<sandboxir::BottomUpVec> BottomUpVecPass;
+
+  // The PM containing the pipeline of region passes. It's owned by the pass
+  // registry.
+  sandboxir::RegionPassManager *RPM;
 
   bool runImpl(Function &F);
+public:
+  SandboxVectorizerPass();
+  PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
 };
 
 } // namespace llvm
diff --git a/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.cpp b/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.cpp
index c59abd09d43629..69ddfaf7784eae 100644
--- a/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.cpp
+++ b/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.cpp
@@ -59,6 +59,8 @@ bool BottomUpVec::runOnFunction(Function &F) {
     // TODO: Replace with proper SeedCollector function.
     auto Seeds = collectSeeds(BB);
     // TODO: Slice Seeds into smaller chunks.
+    // TODO: If vectorization succeeds, run the RegionPassManager on the
+    // resulting region.
     if (Seeds.size() >= 2)
       tryVectorize(Seeds);
   }
diff --git a/llvm/lib/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizer.cpp
index 80afcb499a2c22..1192cc5d9bb243 100644
--- a/llvm/lib/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizer.cpp
@@ -12,6 +12,7 @@
 #include "llvm/SandboxIR/PassManager.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.h"
+#include "llvm/Transforms/Vectorize/SandboxVectorizer/Passes/NullPass.h"
 
 using namespace llvm;
 
@@ -30,6 +31,57 @@ cl::opt<std::string> UserDefinedPassPipeline(
     cl::desc("Comma-separated list of vectorizer passes. If not set "
              "we run the predefined pipeline."));
 
+static void registerAllRegionPasses(sandboxir::PassRegistry &PR) {
+  PR.registerPass(std::make_unique<sandboxir::NullPass>());
+}
+
+static sandboxir::RegionPassManager &
+parseAndCreatePassPipeline(sandboxir::PassRegistry &PR, StringRef Pipeline) {
+  static constexpr const char EndToken = '\0';
+  // Add EndToken to the end to ease parsing.
+  std::string PipelineStr = std::string(Pipeline) + EndToken;
+  int FlagBeginIdx = 0;
+  auto &RPM = static_cast<sandboxir::RegionPassManager &>(
+      PR.registerPass(std::make_unique<sandboxir::RegionPassManager>("rpm")));
+
+  for (auto [Idx, C] : enumerate(PipelineStr)) {
+    // Keep moving Idx until we find the end of the pass name.
+    bool FoundDelim = C == EndToken || C == PR.PassDelimToken;
+    if (!FoundDelim)
+      continue;
+    unsigned Sz = Idx - FlagBeginIdx;
+    std::string PassName(&PipelineStr[FlagBeginIdx], Sz);
+    FlagBeginIdx = Idx + 1;
+
+    // Get the pass that corresponds to PassName and add it to the pass manager.
+    auto *Pass = PR.getPassByName(PassName);
+    if (Pass == nullptr) {
+      errs() << "Pass '" << PassName << "' not registered!\n";
+      exit(1);
+    }
+    // TODO: Add a type check here. The downcast is correct as long as
+    // registerAllRegionPasses only registers regions passes.
+    RPM.addPass(static_cast<sandboxir::RegionPass *>(Pass));
+  }
+  return RPM;
+}
+
+SandboxVectorizerPass::SandboxVectorizerPass() {
+  registerAllRegionPasses(PR);
+
+  // Create a pipeline to be run on each Region created by BottomUpVec.
+  if (UserDefinedPassPipeline == DefaultPipelineMagicStr) {
+    // Create the default pass pipeline.
+    RPM = &static_cast<sandboxir::RegionPassManager &>(PR.registerPass(
+        std::make_unique<sandboxir::FunctionPassManager>("rpm")));
+    // TODO: Add passes to the default pipeline.
+  } else {
+    // Create the user-defined pipeline.
+    RPM = &parseAndCreatePassPipeline(PR, UserDefinedPassPipeline);
+  }
+  BottomUpVecPass = std::make_unique<sandboxir::BottomUpVec>(RPM);
+}
+
 PreservedAnalyses SandboxVectorizerPass::run(Function &F,
                                              FunctionAnalysisManager &AM) {
   TTI = &AM.getResult<TargetIRAnalysis>(F);
@@ -56,31 +108,13 @@ bool SandboxVectorizerPass::runImpl(Function &LLVMF) {
     return false;
   }
 
-  sandboxir::Context Ctx(LLVMF.getContext());
-  // Create SandboxIR for `LLVMF`.
-  sandboxir::Function &F = *Ctx.createFunction(&LLVMF);
-  // Create the passes and register them with the PassRegistry.
-  sandboxir::PassRegistry PR;
-  auto &BottomUpVecPass = static_cast<sandboxir::FunctionPass &>(
-      PR.registerPass(std::make_unique<sandboxir::BottomUpVec>()));
-
-  sandboxir::FunctionPassManager *PM = nullptr;
-  if (UserDefinedPassPipeline == DefaultPipelineMagicStr) {
-    // Create the default pass pipeline.
-    PM = &static_cast<sandboxir::FunctionPassManager &>(PR.registerPass(
-        std::make_unique<sandboxir::FunctionPassManager>("pm")));
-    PM->addPass(&BottomUpVecPass);
-  } else {
-    // Create the user-defined pipeline.
-    PM = &PR.parseAndCreatePassPipeline(UserDefinedPassPipeline);
-  }
-
   if (PrintPassPipeline) {
-    PM->printPipeline(outs());
+    RPM->printPipeline(outs());
     return false;
   }
 
-  // Run the pass pipeline.
-  bool Change = PM->runOnFunction(F);
-  return Change;
+  // Create SandboxIR for LLVMF and run BottomUpVec on it.
+  sandboxir::Context Ctx(LLVMF.getContext());
+  sandboxir::Function &F = *Ctx.createFunction(&LLVMF);
+  return BottomUpVecPass->runOnFunction(F);
 }
diff --git a/llvm/test/Transforms/SandboxVectorizer/default_pass_pipeline.ll b/llvm/test/Transforms/SandboxVectorizer/default_pass_pipeline.ll
index 5ccd64d9f487a3..86bfbee6364788 100644
--- a/llvm/test/Transforms/SandboxVectorizer/default_pass_pipeline.ll
+++ b/llvm/test/Transforms/SandboxVectorizer/default_pass_pipeline.ll
@@ -4,8 +4,7 @@
 
 ; This checks the default pass pipeline for the sandbox vectorizer.
 define void @pipeline() {
-; CHECK: pm
-; CHECK: bottom-up-vec
+; CHECK: rpm
 ; CHECK-EMPTY:
   ret void
 }
diff --git a/llvm/test/Transforms/SandboxVectorizer/user_pass_pipeline.ll b/llvm/test/Transforms/SandboxVectorizer/user_pass_pipeline.ll
index 2879fbba1b9c00..2e6dab0aa29c74 100644
--- a/llvm/test/Transforms/SandboxVectorizer/user_pass_pipeline.ll
+++ b/llvm/test/Transforms/SandboxVectorizer/user_pass_pipeline.ll
@@ -1,12 +1,12 @@
-; RUN: opt -passes=sandbox-vectorizer -sbvec-print-pass-pipeline -sbvec-passes=bottom-up-vec,bottom-up-vec %s -disable-output | FileCheck %s
+; RUN: opt -passes=sandbox-vectorizer -sbvec-print-pass-pipeline -sbvec-passes=null,null %s -disable-output | FileCheck %s
 
 ; !!!WARNING!!! This won't get updated by update_test_checks.py !
 
 ; This checks the user defined pass pipeline.
 define void @pipeline() {
-; CHECK: pm
-; CHECK: bottom-up-vec
-; CHECK: bottom-up-vec
+; CHECK: rpm
+; CHECK: null
+; CHECK: null
 ; CHECK-EMPTY:
   ret void
 }

>From 674c91eded47b264299a877e10ea94b50887e3a5 Mon Sep 17 00:00:00 2001
From: Jorge Gorbe Moya <jgorbe at google.com>
Date: Fri, 4 Oct 2024 17:58:44 -0700
Subject: [PATCH 2/4] clang-format

---
 .../Transforms/Vectorize/SandboxVectorizer/SandboxVectorizer.h   | 1 +
 1 file changed, 1 insertion(+)

diff --git a/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizer.h b/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizer.h
index 4547217773cd01..81c2a5e67cbbd7 100644
--- a/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizer.h
+++ b/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizer.h
@@ -33,6 +33,7 @@ class SandboxVectorizerPass : public PassInfoMixin<SandboxVectorizerPass> {
   sandboxir::RegionPassManager *RPM;
 
   bool runImpl(Function &F);
+
 public:
   SandboxVectorizerPass();
   PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);

>From ee3e3d3e7754e81977428dd6db87249f45b9a6cb Mon Sep 17 00:00:00 2001
From: Jorge Gorbe Moya <jgorbe at google.com>
Date: Mon, 7 Oct 2024 12:25:18 -0700
Subject: [PATCH 3/4] Moved the region pass pipeline to BottomUpVec.

Everything related to the pass pipeline is now in BottomUpVec.cpp,
including pipeline creation and printing and the flags to control it.

I have also changed the `BottomUpVecPass` in `SandboxVectorizer` from
a `unique_ptr` to a plain old member, as I don't think we need that
level of indirection for anything.
---
 .../SandboxVectorizer/Passes/BottomUpVec.h    | 12 ++-
 .../SandboxVectorizer/SandboxVectorizer.h     | 12 +--
 .../SandboxVectorizer/Passes/BottomUpVec.cpp  | 76 ++++++++++++++++++-
 .../SandboxVectorizer/SandboxVectorizer.cpp   | 73 +-----------------
 4 files changed, 83 insertions(+), 90 deletions(-)

diff --git a/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.h b/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.h
index e3a35b09d0e296..13e85f8a033235 100644
--- a/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.h
+++ b/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.h
@@ -15,6 +15,7 @@
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/SandboxIR/Constant.h"
 #include "llvm/SandboxIR/Pass.h"
+#include "llvm/SandboxIR/PassManager.h"
 #include "llvm/Transforms/Vectorize/SandboxVectorizer/Legality.h"
 
 namespace llvm::sandboxir {
@@ -27,11 +28,16 @@ class BottomUpVec final : public FunctionPass {
   void vectorizeRec(ArrayRef<Value *> Bndl);
   void tryVectorize(ArrayRef<Value *> Seeds);
 
-  [[maybe_unused]] RegionPassManager *RPM;
+  // Used to build a RegionPass pipeline to be run on Regions created by the
+  // bottom-up vectorization pass.
+  PassRegistry PR;
+
+  // The PM containing the pipeline of region passes. It's owned by the pass
+  // registry.
+  RegionPassManager *RPM;
 
 public:
-  BottomUpVec(RegionPassManager *RPM)
-      : FunctionPass("bottom-up-vec"), RPM(RPM) {}
+  BottomUpVec();
   bool runOnFunction(Function &F) final;
 };
 
diff --git a/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizer.h b/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizer.h
index 81c2a5e67cbbd7..1dcd976bf751c5 100644
--- a/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizer.h
+++ b/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizer.h
@@ -11,7 +11,6 @@
 #include <memory>
 
 #include "llvm/IR/PassManager.h"
-#include "llvm/SandboxIR/PassManager.h"
 #include "llvm/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.h"
 
 namespace llvm {
@@ -21,21 +20,12 @@ class TargetTransformInfo;
 class SandboxVectorizerPass : public PassInfoMixin<SandboxVectorizerPass> {
   TargetTransformInfo *TTI = nullptr;
 
-  // Used to build a RegionPass pipeline to be run on Regions created by the
-  // bottom-up vectorization pass.
-  sandboxir::PassRegistry PR;
-
   // The main vectorizer pass.
-  std::unique_ptr<sandboxir::BottomUpVec> BottomUpVecPass;
-
-  // The PM containing the pipeline of region passes. It's owned by the pass
-  // registry.
-  sandboxir::RegionPassManager *RPM;
+  sandboxir::BottomUpVec BottomUpVecPass;
 
   bool runImpl(Function &F);
 
 public:
-  SandboxVectorizerPass();
   PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
 };
 
diff --git a/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.cpp b/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.cpp
index 69ddfaf7784eae..a87341c59e1f7b 100644
--- a/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.cpp
+++ b/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.cpp
@@ -10,10 +10,73 @@
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/SandboxIR/Function.h"
 #include "llvm/SandboxIR/Instruction.h"
-
-using namespace llvm::sandboxir;
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Transforms/Vectorize/SandboxVectorizer/Passes/NullPass.h"
 
 namespace llvm::sandboxir {
+
+cl::opt<bool>
+    PrintPassPipeline("sbvec-print-pass-pipeline", cl::init(false), cl::Hidden,
+                      cl::desc("Prints the pass pipeline and returns."));
+
+/// A magic string for the default pass pipeline.
+const char *DefaultPipelineMagicStr = "*";
+
+cl::opt<std::string> UserDefinedPassPipeline(
+    "sbvec-passes", cl::init(DefaultPipelineMagicStr), cl::Hidden,
+    cl::desc("Comma-separated list of vectorizer passes. If not set "
+             "we run the predefined pipeline."));
+
+static void registerAllRegionPasses(sandboxir::PassRegistry &PR) {
+  PR.registerPass(std::make_unique<sandboxir::NullPass>());
+}
+
+static sandboxir::RegionPassManager &
+parseAndCreatePassPipeline(sandboxir::PassRegistry &PR, StringRef Pipeline) {
+  static constexpr const char EndToken = '\0';
+  // Add EndToken to the end to ease parsing.
+  std::string PipelineStr = std::string(Pipeline) + EndToken;
+  int FlagBeginIdx = 0;
+  auto &RPM = static_cast<sandboxir::RegionPassManager &>(
+      PR.registerPass(std::make_unique<sandboxir::RegionPassManager>("rpm")));
+
+  for (auto [Idx, C] : enumerate(PipelineStr)) {
+    // Keep moving Idx until we find the end of the pass name.
+    bool FoundDelim = C == EndToken || C == PR.PassDelimToken;
+    if (!FoundDelim)
+      continue;
+    unsigned Sz = Idx - FlagBeginIdx;
+    std::string PassName(&PipelineStr[FlagBeginIdx], Sz);
+    FlagBeginIdx = Idx + 1;
+
+    // Get the pass that corresponds to PassName and add it to the pass manager.
+    auto *Pass = PR.getPassByName(PassName);
+    if (Pass == nullptr) {
+      errs() << "Pass '" << PassName << "' not registered!\n";
+      exit(1);
+    }
+    // TODO: Add a type check here. The downcast is correct as long as
+    // registerAllRegionPasses only registers regions passes.
+    RPM.addPass(static_cast<sandboxir::RegionPass *>(Pass));
+  }
+  return RPM;
+}
+
+BottomUpVec::BottomUpVec() : FunctionPass("bottom-up-vec") {
+  registerAllRegionPasses(PR);
+
+  // Create a pipeline to be run on each Region created by BottomUpVec.
+  if (UserDefinedPassPipeline == DefaultPipelineMagicStr) {
+    // Create the default pass pipeline.
+    RPM = &static_cast<sandboxir::RegionPassManager &>(PR.registerPass(
+        std::make_unique<sandboxir::FunctionPassManager>("rpm")));
+    // TODO: Add passes to the default pipeline.
+  } else {
+    // Create the user-defined pipeline.
+    RPM = &parseAndCreatePassPipeline(PR, UserDefinedPassPipeline);
+  }
+}
+
 // TODO: This is a temporary function that returns some seeds.
 //       Replace this with SeedCollector's function when it lands.
 static llvm::SmallVector<Value *, 4> collectSeeds(BasicBlock &BB) {
@@ -34,8 +97,6 @@ static SmallVector<Value *, 4> getOperand(ArrayRef<Value *> Bndl,
   return Operands;
 }
 
-} // namespace llvm::sandboxir
-
 void BottomUpVec::vectorizeRec(ArrayRef<Value *> Bndl) {
   auto LegalityRes = Legality.canVectorize(Bndl);
   switch (LegalityRes.getSubclassID()) {
@@ -53,6 +114,11 @@ void BottomUpVec::vectorizeRec(ArrayRef<Value *> Bndl) {
 void BottomUpVec::tryVectorize(ArrayRef<Value *> Bndl) { vectorizeRec(Bndl); }
 
 bool BottomUpVec::runOnFunction(Function &F) {
+  if (PrintPassPipeline) {
+    RPM->printPipeline(outs());
+    return false;
+  }
+
   Change = false;
   // TODO: Start from innermost BBs first
   for (auto &BB : F) {
@@ -66,3 +132,5 @@ bool BottomUpVec::runOnFunction(Function &F) {
   }
   return Change;
 }
+
+} // namespace llvm::sandboxir
diff --git a/llvm/lib/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizer.cpp
index 1192cc5d9bb243..cbaf2b6288d928 100644
--- a/llvm/lib/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizer.cpp
@@ -9,79 +9,13 @@
 #include "llvm/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizer.h"
 #include "llvm/Analysis/TargetTransformInfo.h"
 #include "llvm/SandboxIR/Constant.h"
-#include "llvm/SandboxIR/PassManager.h"
-#include "llvm/Support/CommandLine.h"
 #include "llvm/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.h"
-#include "llvm/Transforms/Vectorize/SandboxVectorizer/Passes/NullPass.h"
 
 using namespace llvm;
 
 #define SV_NAME "sandbox-vectorizer"
 #define DEBUG_TYPE SV_NAME
 
-cl::opt<bool>
-    PrintPassPipeline("sbvec-print-pass-pipeline", cl::init(false), cl::Hidden,
-                      cl::desc("Prints the pass pipeline and returns."));
-
-/// A magic string for the default pass pipeline.
-const char *DefaultPipelineMagicStr = "*";
-
-cl::opt<std::string> UserDefinedPassPipeline(
-    "sbvec-passes", cl::init(DefaultPipelineMagicStr), cl::Hidden,
-    cl::desc("Comma-separated list of vectorizer passes. If not set "
-             "we run the predefined pipeline."));
-
-static void registerAllRegionPasses(sandboxir::PassRegistry &PR) {
-  PR.registerPass(std::make_unique<sandboxir::NullPass>());
-}
-
-static sandboxir::RegionPassManager &
-parseAndCreatePassPipeline(sandboxir::PassRegistry &PR, StringRef Pipeline) {
-  static constexpr const char EndToken = '\0';
-  // Add EndToken to the end to ease parsing.
-  std::string PipelineStr = std::string(Pipeline) + EndToken;
-  int FlagBeginIdx = 0;
-  auto &RPM = static_cast<sandboxir::RegionPassManager &>(
-      PR.registerPass(std::make_unique<sandboxir::RegionPassManager>("rpm")));
-
-  for (auto [Idx, C] : enumerate(PipelineStr)) {
-    // Keep moving Idx until we find the end of the pass name.
-    bool FoundDelim = C == EndToken || C == PR.PassDelimToken;
-    if (!FoundDelim)
-      continue;
-    unsigned Sz = Idx - FlagBeginIdx;
-    std::string PassName(&PipelineStr[FlagBeginIdx], Sz);
-    FlagBeginIdx = Idx + 1;
-
-    // Get the pass that corresponds to PassName and add it to the pass manager.
-    auto *Pass = PR.getPassByName(PassName);
-    if (Pass == nullptr) {
-      errs() << "Pass '" << PassName << "' not registered!\n";
-      exit(1);
-    }
-    // TODO: Add a type check here. The downcast is correct as long as
-    // registerAllRegionPasses only registers regions passes.
-    RPM.addPass(static_cast<sandboxir::RegionPass *>(Pass));
-  }
-  return RPM;
-}
-
-SandboxVectorizerPass::SandboxVectorizerPass() {
-  registerAllRegionPasses(PR);
-
-  // Create a pipeline to be run on each Region created by BottomUpVec.
-  if (UserDefinedPassPipeline == DefaultPipelineMagicStr) {
-    // Create the default pass pipeline.
-    RPM = &static_cast<sandboxir::RegionPassManager &>(PR.registerPass(
-        std::make_unique<sandboxir::FunctionPassManager>("rpm")));
-    // TODO: Add passes to the default pipeline.
-  } else {
-    // Create the user-defined pipeline.
-    RPM = &parseAndCreatePassPipeline(PR, UserDefinedPassPipeline);
-  }
-  BottomUpVecPass = std::make_unique<sandboxir::BottomUpVec>(RPM);
-}
-
 PreservedAnalyses SandboxVectorizerPass::run(Function &F,
                                              FunctionAnalysisManager &AM) {
   TTI = &AM.getResult<TargetIRAnalysis>(F);
@@ -108,13 +42,8 @@ bool SandboxVectorizerPass::runImpl(Function &LLVMF) {
     return false;
   }
 
-  if (PrintPassPipeline) {
-    RPM->printPipeline(outs());
-    return false;
-  }
-
   // Create SandboxIR for LLVMF and run BottomUpVec on it.
   sandboxir::Context Ctx(LLVMF.getContext());
   sandboxir::Function &F = *Ctx.createFunction(&LLVMF);
-  return BottomUpVecPass->runOnFunction(F);
+  return BottomUpVecPass.runOnFunction(F);
 }

>From 4b4c0630581fb5e3be4bbe9d603f7825b4e48cc2 Mon Sep 17 00:00:00 2001
From: Jorge Gorbe Moya <jgorbe at google.com>
Date: Mon, 7 Oct 2024 14:35:42 -0700
Subject: [PATCH 4/4] Make BottomUpVec own its RegionPassManager.

Also made some flag-related globals static.
---
 llvm/include/llvm/SandboxIR/PassManager.h     |  1 +
 .../SandboxVectorizer/Passes/BottomUpVec.h    |  7 +++--
 .../SandboxVectorizer/Passes/BottomUpVec.cpp  | 26 ++++++++-----------
 3 files changed, 15 insertions(+), 19 deletions(-)

diff --git a/llvm/include/llvm/SandboxIR/PassManager.h b/llvm/include/llvm/SandboxIR/PassManager.h
index 54192c6bf1333b..c14fc1c6d3dba5 100644
--- a/llvm/include/llvm/SandboxIR/PassManager.h
+++ b/llvm/include/llvm/SandboxIR/PassManager.h
@@ -36,6 +36,7 @@ class PassManager : public ParentPass {
 
   PassManager(StringRef Name) : ParentPass(Name) {}
   PassManager(const PassManager &) = delete;
+  PassManager(PassManager &&) = default;
   virtual ~PassManager() = default;
   PassManager &operator=(const PassManager &) = delete;
 
diff --git a/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.h b/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.h
index 13e85f8a033235..ae06a85b2b819e 100644
--- a/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.h
+++ b/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.h
@@ -29,12 +29,11 @@ class BottomUpVec final : public FunctionPass {
   void tryVectorize(ArrayRef<Value *> Seeds);
 
   // Used to build a RegionPass pipeline to be run on Regions created by the
-  // bottom-up vectorization pass.
+  // bottom-up vectorization pass. Owns the sub-passes.
   PassRegistry PR;
 
-  // The PM containing the pipeline of region passes. It's owned by the pass
-  // registry.
-  RegionPassManager *RPM;
+  // The PM containing the pipeline of region passes.
+  RegionPassManager RPM;
 
 public:
   BottomUpVec();
diff --git a/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.cpp b/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.cpp
index a87341c59e1f7b..5c9b7639008b76 100644
--- a/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.cpp
+++ b/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.cpp
@@ -15,14 +15,14 @@
 
 namespace llvm::sandboxir {
 
-cl::opt<bool>
+static cl::opt<bool>
     PrintPassPipeline("sbvec-print-pass-pipeline", cl::init(false), cl::Hidden,
                       cl::desc("Prints the pass pipeline and returns."));
 
 /// A magic string for the default pass pipeline.
-const char *DefaultPipelineMagicStr = "*";
+static const char *DefaultPipelineMagicStr = "*";
 
-cl::opt<std::string> UserDefinedPassPipeline(
+static cl::opt<std::string> UserDefinedPassPipeline(
     "sbvec-passes", cl::init(DefaultPipelineMagicStr), cl::Hidden,
     cl::desc("Comma-separated list of vectorizer passes. If not set "
              "we run the predefined pipeline."));
@@ -31,14 +31,14 @@ static void registerAllRegionPasses(sandboxir::PassRegistry &PR) {
   PR.registerPass(std::make_unique<sandboxir::NullPass>());
 }
 
-static sandboxir::RegionPassManager &
-parseAndCreatePassPipeline(sandboxir::PassRegistry &PR, StringRef Pipeline) {
+/// Adds to `RPM` a sequence of passes described by `Pipeline` from the `PR`
+/// pass registry.
+static void parseAndCreatePassPipeline(RegionPassManager &RPM, PassRegistry &PR,
+                                       StringRef Pipeline) {
   static constexpr const char EndToken = '\0';
   // Add EndToken to the end to ease parsing.
   std::string PipelineStr = std::string(Pipeline) + EndToken;
   int FlagBeginIdx = 0;
-  auto &RPM = static_cast<sandboxir::RegionPassManager &>(
-      PR.registerPass(std::make_unique<sandboxir::RegionPassManager>("rpm")));
 
   for (auto [Idx, C] : enumerate(PipelineStr)) {
     // Keep moving Idx until we find the end of the pass name.
@@ -59,21 +59,17 @@ parseAndCreatePassPipeline(sandboxir::PassRegistry &PR, StringRef Pipeline) {
     // registerAllRegionPasses only registers regions passes.
     RPM.addPass(static_cast<sandboxir::RegionPass *>(Pass));
   }
-  return RPM;
 }
 
-BottomUpVec::BottomUpVec() : FunctionPass("bottom-up-vec") {
+BottomUpVec::BottomUpVec() : FunctionPass("bottom-up-vec"), RPM("rpm") {
   registerAllRegionPasses(PR);
 
   // Create a pipeline to be run on each Region created by BottomUpVec.
   if (UserDefinedPassPipeline == DefaultPipelineMagicStr) {
-    // Create the default pass pipeline.
-    RPM = &static_cast<sandboxir::RegionPassManager &>(PR.registerPass(
-        std::make_unique<sandboxir::FunctionPassManager>("rpm")));
-    // TODO: Add passes to the default pipeline.
+    // TODO: Add default passes to RPM.
   } else {
     // Create the user-defined pipeline.
-    RPM = &parseAndCreatePassPipeline(PR, UserDefinedPassPipeline);
+    parseAndCreatePassPipeline(RPM, PR, UserDefinedPassPipeline);
   }
 }
 
@@ -115,7 +111,7 @@ void BottomUpVec::tryVectorize(ArrayRef<Value *> Bndl) { vectorizeRec(Bndl); }
 
 bool BottomUpVec::runOnFunction(Function &F) {
   if (PrintPassPipeline) {
-    RPM->printPipeline(outs());
+    RPM.printPipeline(outs());
     return false;
   }
 



More information about the llvm-commits mailing list