[llvm] [SandboxIR] Add RegionPass/RegionPassManager (PR #110933)

Jorge Gorbe Moya via llvm-commits llvm-commits at lists.llvm.org
Wed Oct 2 15:25:19 PDT 2024


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

>From f9ebd0c7c0f59fd5f951f9bdbf05285b38faa817 Mon Sep 17 00:00:00 2001
From: Jorge Gorbe Moya <jgorbe at google.com>
Date: Wed, 2 Oct 2024 15:05:11 -0700
Subject: [PATCH 1/2] [SandboxIR] Add RegionPass/RegionPassManager

These classes mirror the existing FunctionPass/FunctionPassManager,
and will be used by the sandbox vectorizer to run a pipeline of
region passes.
---
 llvm/include/llvm/SandboxIR/Pass.h        |   9 ++
 llvm/include/llvm/SandboxIR/PassManager.h |   7 ++
 llvm/lib/SandboxIR/PassManager.cpp        |  10 ++
 llvm/unittests/SandboxIR/PassTest.cpp     | 124 ++++++++++++++++++++++
 4 files changed, 150 insertions(+)

diff --git a/llvm/include/llvm/SandboxIR/Pass.h b/llvm/include/llvm/SandboxIR/Pass.h
index 34776e3529e5c6..19fe4a10755774 100644
--- a/llvm/include/llvm/SandboxIR/Pass.h
+++ b/llvm/include/llvm/SandboxIR/Pass.h
@@ -15,6 +15,7 @@
 namespace llvm::sandboxir {
 
 class Function;
+class Region;
 
 /// The base class of a Sandbox IR Pass.
 class Pass {
@@ -52,6 +53,14 @@ class FunctionPass : public Pass {
   virtual bool runOnFunction(Function &F) = 0;
 };
 
+/// A pass that runs on a sandbox::Region.
+class RegionPass : public Pass {
+public:
+  RegionPass(StringRef Name) : Pass(Name) {}
+  /// \Returns true if it modifies \p R.
+  virtual bool runOnRegion(Region &R) = 0;
+};
+
 } // namespace llvm::sandboxir
 
 #endif // LLVM_SANDBOXIR_PASS_H
diff --git a/llvm/include/llvm/SandboxIR/PassManager.h b/llvm/include/llvm/SandboxIR/PassManager.h
index 98b56ba08c4eb6..68169fda380f1c 100644
--- a/llvm/include/llvm/SandboxIR/PassManager.h
+++ b/llvm/include/llvm/SandboxIR/PassManager.h
@@ -73,6 +73,13 @@ class FunctionPassManager final
   bool runOnFunction(Function &F) final;
 };
 
+class RegionPassManager final
+    : public PassManager<RegionPass, RegionPass> {
+public:
+  RegionPassManager(StringRef Name) : PassManager(Name) {}
+  bool runOnRegion(Region &R) final;
+};
+
 /// Owns the passes and provides an API to get a pass by its name.
 class PassRegistry {
   SmallVector<std::unique_ptr<Pass>, 8> Passes;
diff --git a/llvm/lib/SandboxIR/PassManager.cpp b/llvm/lib/SandboxIR/PassManager.cpp
index 4168420a01ce2f..95bc5e56bb3ec9 100644
--- a/llvm/lib/SandboxIR/PassManager.cpp
+++ b/llvm/lib/SandboxIR/PassManager.cpp
@@ -20,6 +20,16 @@ bool FunctionPassManager::runOnFunction(Function &F) {
   return Change;
 }
 
+bool RegionPassManager::runOnRegion(Region &R) {
+  bool Change = false;
+  for (RegionPass *Pass : Passes) {
+    Change |= Pass->runOnRegion(R);
+    // TODO: run the verifier.
+  }
+  // TODO: Check ChangeAll against hashes before/after.
+  return Change;
+}
+
 FunctionPassManager &
 PassRegistry::parseAndCreatePassPipeline(StringRef Pipeline) {
   static constexpr const char EndToken = '\0';
diff --git a/llvm/unittests/SandboxIR/PassTest.cpp b/llvm/unittests/SandboxIR/PassTest.cpp
index 10fe59b654a2ec..b380ae9fd475ab 100644
--- a/llvm/unittests/SandboxIR/PassTest.cpp
+++ b/llvm/unittests/SandboxIR/PassTest.cpp
@@ -13,6 +13,7 @@
 #include "llvm/SandboxIR/Context.h"
 #include "llvm/SandboxIR/Function.h"
 #include "llvm/SandboxIR/PassManager.h"
+#include "llvm/SandboxIR/Region.h"
 #include "llvm/Support/SourceMgr.h"
 #include "gtest/gtest.h"
 
@@ -86,6 +87,68 @@ define void @foo() {
 #endif
 }
 
+TEST_F(PassTest, RegionPass) {
+  auto *F = parseFunction(R"IR(
+define i8 @foo(i8 %v0, i8 %v1) {
+  %t0 = add i8 %v0, 1
+  %t1 = add i8 %t0, %v1, !sandboxvec !0
+  %t2 = add i8 %t1, %v1, !sandboxvec !0
+  ret i8 %t1
+}
+
+!0 = distinct !{!"sandboxregion"}
+)IR",
+                          "foo");
+
+  class TestPass final : public RegionPass {
+    unsigned &InstCount;
+
+  public:
+    TestPass(unsigned &InstCount)
+        : RegionPass("test-pass"), InstCount(InstCount) {}
+    bool runOnRegion(Region &R) final {
+      for ([[maybe_unused]] auto &Inst : R) {
+        ++InstCount;
+      }
+      return false;
+    }
+  };
+  unsigned InstCount = 0;
+  TestPass TPass(InstCount);
+  // Check getName(),
+  EXPECT_EQ(TPass.getName(), "test-pass");
+  // Check runOnRegion();
+  llvm::SmallVector<std::unique_ptr<Region>> Regions =
+      Region::createRegionsFromMD(*F);
+  ASSERT_EQ(Regions.size(), 1u);
+  TPass.runOnRegion(*Regions[0]);
+  EXPECT_EQ(InstCount, 2u);
+#ifndef NDEBUG
+  {
+    // Check print().
+    std::string Buff;
+    llvm::raw_string_ostream SS(Buff);
+    TPass.print(SS);
+    EXPECT_EQ(Buff, "test-pass");
+  }
+  {
+    // Check operator<<().
+    std::string Buff;
+    llvm::raw_string_ostream SS(Buff);
+    SS << TPass;
+    EXPECT_EQ(Buff, "test-pass");
+  }
+  // Check pass name assertions.
+  class TestNamePass final : public RegionPass {
+  public:
+    TestNamePass(llvm::StringRef Name) : RegionPass(Name) {}
+    bool runOnRegion(Region &F) { return false; }
+  };
+  EXPECT_DEATH(TestNamePass("white space"), ".*whitespace.*");
+  EXPECT_DEATH(TestNamePass("-dash"), ".*start with.*");
+#endif
+}
+
 TEST_F(PassTest, FunctionPassManager) {
   auto *F = parseFunction(R"IR(
 define void @foo() {
@@ -136,6 +199,67 @@ define void @foo() {
 #endif // NDEBUG
 }
 
+TEST_F(PassTest, RegionPassManager) {
+  auto *F = parseFunction(R"IR(
+define i8 @foo(i8 %v0, i8 %v1) {
+  %t0 = add i8 %v0, 1
+  %t1 = add i8 %t0, %v1, !sandboxvec !0
+  %t2 = add i8 %t1, %v1, !sandboxvec !0
+  ret i8 %t1
+}
+
+!0 = distinct !{!"sandboxregion"}
+)IR",
+                          "foo");
+
+  class TestPass1 final : public RegionPass {
+    unsigned &InstCount;
+
+  public:
+    TestPass1(unsigned &InstCount)
+        : RegionPass("test-pass1"), InstCount(InstCount) {}
+    bool runOnRegion(Region &R) final {
+      for ([[maybe_unused]] auto &Inst : R)
+        ++InstCount;
+      return false;
+    }
+  };
+  class TestPass2 final : public RegionPass {
+    unsigned &InstCount;
+
+  public:
+    TestPass2(unsigned &InstCount)
+        : RegionPass("test-pass2"), InstCount(InstCount) {}
+    bool runOnRegion(Region &R) final {
+      for ([[maybe_unused]] auto &Inst : R)
+        ++InstCount;
+      return false;
+    }
+  };
+  unsigned InstCount1 = 0;
+  unsigned InstCount2 = 0;
+  TestPass1 TPass1(InstCount1);
+  TestPass2 TPass2(InstCount2);
+
+  RegionPassManager RPM("test-rpm");
+  RPM.addPass(&TPass1);
+  RPM.addPass(&TPass2);
+  // Check runOnRegion().
+  llvm::SmallVector<std::unique_ptr<Region>> Regions =
+      Region::createRegionsFromMD(*F);
+  ASSERT_EQ(Regions.size(), 1u);
+  RPM.runOnRegion(*Regions[0]);
+  EXPECT_EQ(InstCount1, 2u);
+  EXPECT_EQ(InstCount2, 2u);
+#ifndef NDEBUG
+  // Check dump().
+  std::string Buff;
+  llvm::raw_string_ostream SS(Buff);
+  RPM.print(SS);
+  EXPECT_EQ(Buff, "test-rpm(test-pass1,test-pass2)");
+#endif // NDEBUG
+}
+
 TEST_F(PassTest, PassRegistry) {
   class TestPass1 final : public FunctionPass {
   public:

>From 796819dec86b5cf031fb8cca78a419a58a20372e Mon Sep 17 00:00:00 2001
From: Jorge Gorbe Moya <jgorbe at google.com>
Date: Wed, 2 Oct 2024 15:25:04 -0700
Subject: [PATCH 2/2] clang-format

---
 llvm/include/llvm/SandboxIR/PassManager.h | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/llvm/include/llvm/SandboxIR/PassManager.h b/llvm/include/llvm/SandboxIR/PassManager.h
index 68169fda380f1c..54192c6bf1333b 100644
--- a/llvm/include/llvm/SandboxIR/PassManager.h
+++ b/llvm/include/llvm/SandboxIR/PassManager.h
@@ -73,8 +73,7 @@ class FunctionPassManager final
   bool runOnFunction(Function &F) final;
 };
 
-class RegionPassManager final
-    : public PassManager<RegionPass, RegionPass> {
+class RegionPassManager final : public PassManager<RegionPass, RegionPass> {
 public:
   RegionPassManager(StringRef Name) : PassManager(Name) {}
   bool runOnRegion(Region &R) final;



More information about the llvm-commits mailing list