[llvm] [SandboxIR] PassManager (PR #107932)

via llvm-commits llvm-commits at lists.llvm.org
Mon Sep 9 15:52:39 PDT 2024


https://github.com/vporpo created https://github.com/llvm/llvm-project/pull/107932

This patch implements a simple pass manager for Sandbox IR.

>From 79f1dca510f474ebdba0fd935c7a99eb46c5b53c Mon Sep 17 00:00:00 2001
From: Vasileios Porpodas <vporpodas at google.com>
Date: Fri, 6 Sep 2024 12:21:08 -0700
Subject: [PATCH] [SandboxIR] PassManager

This patch implements a simple pass manager for Sandbox IR.
---
 llvm/include/llvm/SandboxIR/Pass.h        |  4 +-
 llvm/include/llvm/SandboxIR/PassManager.h | 74 +++++++++++++++++++++++
 llvm/lib/SandboxIR/CMakeLists.txt         |  1 +
 llvm/lib/SandboxIR/PassManager.cpp        | 22 +++++++
 llvm/unittests/SandboxIR/PassTest.cpp     | 51 ++++++++++++++++
 5 files changed, 150 insertions(+), 2 deletions(-)
 create mode 100644 llvm/include/llvm/SandboxIR/PassManager.h
 create mode 100644 llvm/lib/SandboxIR/PassManager.cpp

diff --git a/llvm/include/llvm/SandboxIR/Pass.h b/llvm/include/llvm/SandboxIR/Pass.h
index d659e968392132..caf1c70a841477 100644
--- a/llvm/include/llvm/SandboxIR/Pass.h
+++ b/llvm/include/llvm/SandboxIR/Pass.h
@@ -37,8 +37,8 @@ class Pass {
     Pass.print(OS);
     return OS;
   }
-  void print(raw_ostream &OS) const { OS << Name; }
-  LLVM_DUMP_METHOD void dump() const;
+  virtual void print(raw_ostream &OS) const { OS << Name; }
+  LLVM_DUMP_METHOD virtual void dump() const;
 #endif
 };
 
diff --git a/llvm/include/llvm/SandboxIR/PassManager.h b/llvm/include/llvm/SandboxIR/PassManager.h
new file mode 100644
index 00000000000000..eba72a310aa072
--- /dev/null
+++ b/llvm/include/llvm/SandboxIR/PassManager.h
@@ -0,0 +1,74 @@
+//===- PassManager.h --------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Registers and executes the Sandbox IR passes.
+//
+// The pass manager contains an ordered sequence of passes that it runs in
+// order. The passes are not owned by the pass manager because a pass may be
+// inserted multiple times in one or more pass managers.
+// Note that in this design a pass manager is also a pass. So a pass manager
+// runs when it is it's turn to run in its parent pass-manager pass pipeline.
+//
+
+#ifndef LLVM_SANDBOXIR_PASSMANAGER_H
+#define LLVM_SANDBOXIR_PASSMANAGER_H
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/SandboxIR/Pass.h"
+#include "llvm/Support/Debug.h"
+
+namespace llvm::sandboxir {
+
+class Value;
+
+/// Base class.
+template <typename ParentPass, typename ContainedPass>
+class PassManager : public ParentPass {
+protected:
+  /// The list of passes that this pass manager will run.
+  SmallVector<ContainedPass *> Passes;
+
+  PassManager(StringRef Name) : ParentPass(Name) {}
+  PassManager(const PassManager &) = delete;
+  virtual ~PassManager() = default;
+  PassManager &operator=(const PassManager &) = delete;
+
+public:
+  /// Adds \p Pass to the pass pipeline.
+  void addPass(ContainedPass *Pass) {
+    // TODO: Check that Pass's class type works with this PassManager type.
+    Passes.push_back(Pass);
+  }
+#ifndef NDEBUG
+  void print(raw_ostream &OS) const override {
+    OS << this->getName();
+    OS << "(";
+    for (auto [Idx, Pass] : enumerate(Passes)) {
+      OS << Pass->getName();
+      if (Idx + 1 != Passes.size())
+        OS << ",";
+    }
+    OS << ")";
+  }
+  LLVM_DUMP_METHOD void dump() const override {
+    print(dbgs());
+    dbgs() << "\n";
+  }
+#endif
+};
+
+class FunctionPassManager final
+    : public PassManager<FunctionPass, FunctionPass> {
+public:
+  FunctionPassManager(StringRef Name) : PassManager(Name) {}
+  bool runOnFunction(Function &F) final;
+};
+
+} // namespace llvm::sandboxir
+
+#endif // LLVM_SANDBOXIR_PASSMANAGER_H
diff --git a/llvm/lib/SandboxIR/CMakeLists.txt b/llvm/lib/SandboxIR/CMakeLists.txt
index 2f047944e0335e..03474be0c7b80a 100644
--- a/llvm/lib/SandboxIR/CMakeLists.txt
+++ b/llvm/lib/SandboxIR/CMakeLists.txt
@@ -1,5 +1,6 @@
 add_llvm_component_library(LLVMSandboxIR
   Pass.cpp
+  PassManager.cpp
   SandboxIR.cpp
   Tracker.cpp
   Type.cpp
diff --git a/llvm/lib/SandboxIR/PassManager.cpp b/llvm/lib/SandboxIR/PassManager.cpp
new file mode 100644
index 00000000000000..d10f3926f7bcdb
--- /dev/null
+++ b/llvm/lib/SandboxIR/PassManager.cpp
@@ -0,0 +1,22 @@
+//===- PassManager.cpp - Runs a pipeline of Sandbox IR passes -------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/SandboxIR/PassManager.h"
+#include "llvm/SandboxIR/SandboxIR.h"
+
+using namespace llvm::sandboxir;
+
+bool FunctionPassManager::runOnFunction(Function &F) {
+  bool Change = false;
+  for (FunctionPass *Pass : Passes) {
+    Change |= Pass->runOnFunction(F);
+    // TODO: run the verifier.
+  }
+  // TODO: Check ChangeAll against hashes before/after.
+  return Change;
+}
diff --git a/llvm/unittests/SandboxIR/PassTest.cpp b/llvm/unittests/SandboxIR/PassTest.cpp
index 65992d8cb95ee1..8e080128b15b34 100644
--- a/llvm/unittests/SandboxIR/PassTest.cpp
+++ b/llvm/unittests/SandboxIR/PassTest.cpp
@@ -9,6 +9,7 @@
 #include "llvm/SandboxIR/Pass.h"
 #include "llvm/AsmParser/Parser.h"
 #include "llvm/IR/Module.h"
+#include "llvm/SandboxIR/PassManager.h"
 #include "llvm/SandboxIR/SandboxIR.h"
 #include "llvm/Support/SourceMgr.h"
 #include "gtest/gtest.h"
@@ -82,3 +83,53 @@ define void @foo() {
   EXPECT_DEATH(TestNamePass("-dash"), ".*start with.*");
 #endif
 }
+
+TEST_F(PassTest, FunctionPassManager) {
+  auto *F = parseFunction(R"IR(
+define void @foo() {
+  ret void
+}
+)IR",
+                          "foo");
+  class TestPass1 final : public FunctionPass {
+    unsigned &BBCnt;
+
+  public:
+    TestPass1(unsigned &BBCnt) : FunctionPass("test-pass1"), BBCnt(BBCnt) {}
+    bool runOnFunction(Function &F) final {
+      for ([[maybe_unused]] auto &BB : F)
+        ++BBCnt;
+      return false;
+    }
+  };
+  class TestPass2 final : public FunctionPass {
+    unsigned &BBCnt;
+
+  public:
+    TestPass2(unsigned &BBCnt) : FunctionPass("test-pass2"), BBCnt(BBCnt) {}
+    bool runOnFunction(Function &F) final {
+      for ([[maybe_unused]] auto &BB : F)
+        ++BBCnt;
+      return false;
+    }
+  };
+  unsigned BBCnt1 = 0;
+  unsigned BBCnt2 = 0;
+  TestPass1 TPass1(BBCnt1);
+  TestPass2 TPass2(BBCnt2);
+
+  FunctionPassManager FPM("test-fpm");
+  FPM.addPass(&TPass1);
+  FPM.addPass(&TPass2);
+  // Check runOnFunction().
+  FPM.runOnFunction(*F);
+  EXPECT_EQ(BBCnt1, 1u);
+  EXPECT_EQ(BBCnt2, 1u);
+#ifndef NDEBUG
+  // Check dump().
+  std::string Buff;
+  llvm::raw_string_ostream SS(Buff);
+  FPM.print(SS);
+  EXPECT_EQ(Buff, "test-fpm(test-pass1,test-pass2)");
+#endif // NDEBUG
+}



More information about the llvm-commits mailing list