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

via llvm-commits llvm-commits at lists.llvm.org
Wed Oct 2 16:32:06 PDT 2024


Author: Jorge Gorbe Moya
Date: 2024-10-02T16:32:02-07:00
New Revision: f35c213c816c9dd40d8ed4c3d155030bfd3e75e6

URL: https://github.com/llvm/llvm-project/commit/f35c213c816c9dd40d8ed4c3d155030bfd3e75e6
DIFF: https://github.com/llvm/llvm-project/commit/f35c213c816c9dd40d8ed4c3d155030bfd3e75e6.diff

LOG: [SandboxIR] Add RegionPass/RegionPassManager (#110933)

These classes mirror the existing FunctionPass/FunctionPassManager, and
will be used by the sandbox vectorizer to run a pipeline of region
passes.

Added: 
    

Modified: 
    llvm/include/llvm/SandboxIR/Pass.h
    llvm/include/llvm/SandboxIR/PassManager.h
    llvm/lib/SandboxIR/PassManager.cpp
    llvm/unittests/SandboxIR/PassTest.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/SandboxIR/Pass.h b/llvm/include/llvm/SandboxIR/Pass.h
index 34776e3529e5c6..211f10f5d57c5c 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 {
@@ -24,6 +25,7 @@ class Pass {
   const std::string Name;
 
 public:
+  /// \p Name can't contain any spaces or start with '-'.
   Pass(StringRef Name) : Name(Name) {
     assert(!Name.contains(' ') &&
            "A pass name should not contain whitespaces!");
@@ -47,11 +49,21 @@ class Pass {
 /// A pass that runs on a sandbox::Function.
 class FunctionPass : public Pass {
 public:
+  /// \p Name can't contain any spaces or start with '-'.
   FunctionPass(StringRef Name) : Pass(Name) {}
   /// \Returns true if it modifies \p F.
   virtual bool runOnFunction(Function &F) = 0;
 };
 
+/// A pass that runs on a sandbox::Region.
+class RegionPass : public Pass {
+public:
+  /// \p Name can't contain any spaces or start with '-'.
+  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..54192c6bf1333b 100644
--- a/llvm/include/llvm/SandboxIR/PassManager.h
+++ b/llvm/include/llvm/SandboxIR/PassManager.h
@@ -73,6 +73,12 @@ 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:


        


More information about the llvm-commits mailing list