-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[SandboxVec] Implement Pass class #107617
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-llvm-transforms Author: vporpo (vporpo) ChangesThis patch implements the Pass base class and the FunctionPass sub-class that operate on Sandbox IR. Full diff: https://github.com/llvm/llvm-project/pull/107617.diff 6 Files Affected:
diff --git a/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/Pass.h b/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/Pass.h
new file mode 100644
index 00000000000000..fa45e4808c0f6f
--- /dev/null
+++ b/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/Pass.h
@@ -0,0 +1,83 @@
+//===- Pass.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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_PASS_H
+#define LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_PASS_H
+
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/raw_ostream.h"
+#include <string>
+
+namespace llvm::sandboxir {
+
+class Function;
+
+/// The base class of a Sandbox IR Pass.
+class Pass {
+public:
+ enum class ClassID : unsigned {
+ FunctionPass,
+ };
+ static const char *getSubclassIDStr(ClassID ID) {
+ switch (ID) {
+ case ClassID::FunctionPass:
+ return "FunctionPass";
+ }
+ llvm_unreachable("Unimplemented ID");
+ }
+
+protected:
+ /// The pass name.
+ const std::string Name;
+ /// The command-line flag used to specify that this pass should run.
+ const std::string Flag;
+ /// Used for isa/cast/dyn_cast.
+ ClassID SubclassID;
+
+public:
+ Pass(const std::string &Name, const std::string &Flag, ClassID SubclassID)
+ : Name(Name), Flag(Flag), SubclassID(SubclassID) {}
+ virtual ~Pass() {}
+ /// \Returns the name of the pass.
+ StringRef getName() const { return Name; }
+ /// \Returns the command-line flag used to enable the pass.
+ StringRef getFlag() const { return Flag; }
+ ClassID getSubclassID() const { return SubclassID; }
+#ifndef NDEBUG
+ friend raw_ostream &operator<<(raw_ostream &OS, const Pass &Pass) {
+ Pass.dump(OS);
+ return OS;
+ }
+ void dump(raw_ostream &OS) const { OS << Name << " " << Flag; }
+ LLVM_DUMP_METHOD void dump() const;
+#endif
+};
+
+/// A pass that runs on a sandbox::Function.
+class FunctionPass : public Pass {
+protected:
+ FunctionPass(const std::string &Name, const std::string &Flag, ClassID PassID)
+ : Pass(Name, Flag, PassID) {}
+
+public:
+ FunctionPass(const std::string &Name, const std::string &Flag)
+ : Pass(Name, Flag, ClassID::FunctionPass) {}
+ /// For isa/dyn_cast etc.
+ static bool classof(const Pass *From) {
+ switch (From->getSubclassID()) {
+ case ClassID::FunctionPass:
+ return true;
+ }
+ }
+ /// \Returns true if it modifies \p F.
+ virtual bool runOnFunction(Function &F) = 0;
+};
+
+} // namespace llvm::sandboxir
+
+#endif // LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_PASS_H
diff --git a/llvm/lib/Transforms/Vectorize/CMakeLists.txt b/llvm/lib/Transforms/Vectorize/CMakeLists.txt
index 649faad48d71e5..2406856d4eaf09 100644
--- a/llvm/lib/Transforms/Vectorize/CMakeLists.txt
+++ b/llvm/lib/Transforms/Vectorize/CMakeLists.txt
@@ -3,6 +3,7 @@ add_llvm_component_library(LLVMVectorize
LoopIdiomVectorize.cpp
LoopVectorizationLegality.cpp
LoopVectorize.cpp
+ SandboxVectorizer/Pass.cpp
SandboxVectorizer/SandboxVectorizer.cpp
SLPVectorizer.cpp
Vectorize.cpp
diff --git a/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Pass.cpp b/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Pass.cpp
new file mode 100644
index 00000000000000..686c75af5586fd
--- /dev/null
+++ b/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Pass.cpp
@@ -0,0 +1,19 @@
+//===- Pass.cpp - Passes that operate on Sandbox IR -----------------------===//
+//
+// 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/Transforms/Vectorize/SandboxVectorizer/Pass.h"
+#include "llvm/Support/Debug.h"
+
+using namespace llvm::sandboxir;
+
+#ifndef NDEBUG
+void Pass::dump() const {
+ dump(dbgs());
+ dbgs() << "\n";
+}
+#endif // NDEBUG
diff --git a/llvm/unittests/CMakeLists.txt b/llvm/unittests/CMakeLists.txt
index 911ede701982f6..e709cf161cf6ad 100644
--- a/llvm/unittests/CMakeLists.txt
+++ b/llvm/unittests/CMakeLists.txt
@@ -45,6 +45,7 @@ add_subdirectory(Remarks)
add_subdirectory(Passes)
add_subdirectory(ProfileData)
add_subdirectory(SandboxIR)
+add_subdirectory(SandboxVectorizer)
add_subdirectory(Support)
add_subdirectory(TableGen)
add_subdirectory(Target)
diff --git a/llvm/unittests/SandboxVectorizer/CMakeLists.txt b/llvm/unittests/SandboxVectorizer/CMakeLists.txt
new file mode 100644
index 00000000000000..6c32364ff412d6
--- /dev/null
+++ b/llvm/unittests/SandboxVectorizer/CMakeLists.txt
@@ -0,0 +1,9 @@
+set(LLVM_LINK_COMPONENTS
+ AsmParser
+ SandboxIR
+ Core
+ )
+
+add_llvm_unittest(SandboxVectorizerTests
+ PassTest.cpp
+ )
diff --git a/llvm/unittests/SandboxVectorizer/PassTest.cpp b/llvm/unittests/SandboxVectorizer/PassTest.cpp
new file mode 100644
index 00000000000000..7dff8830bd7bb5
--- /dev/null
+++ b/llvm/unittests/SandboxVectorizer/PassTest.cpp
@@ -0,0 +1,67 @@
+//===- PassesTest.cpp -----------------------------------------------------===//
+//
+// 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/Transforms/Vectorize/SandboxVectorizer/Pass.h"
+#include "llvm/AsmParser/Parser.h"
+#include "llvm/IR/Module.h"
+#include "llvm/SandboxIR/SandboxIR.h"
+#include "llvm/Support/SourceMgr.h"
+#include "gtest/gtest.h"
+
+using namespace llvm::sandboxir;
+
+struct PassTest : public testing::Test {
+ llvm::LLVMContext LLVMCtx;
+ std::unique_ptr<llvm::Module> LLVMM;
+ std::unique_ptr<Context> Ctx;
+
+ Function *parseFunction(const char *IR, const char *FuncName) {
+ llvm::SMDiagnostic Err;
+ LLVMM = parseAssemblyString(IR, Err, LLVMCtx);
+ if (!LLVMM)
+ Err.print("PassTest", llvm::errs());
+ Ctx = std::make_unique<Context>(LLVMCtx);
+ return Ctx->createFunction(LLVMM->getFunction(FuncName));
+ }
+};
+
+TEST_F(PassTest, FunctionPass) {
+ auto *F = parseFunction(R"IR(
+define void @foo() {
+ ret void
+}
+)IR",
+ "foo");
+ class TestPass final : public FunctionPass {
+ unsigned &BBCnt;
+
+ public:
+ TestPass(unsigned &BBCnt)
+ : FunctionPass("TestPass", "-test-pass"), BBCnt(BBCnt) {}
+ bool runOnFunction(Function &F) final {
+ for ([[maybe_unused]] auto &BB : F)
+ ++BBCnt;
+ return false;
+ }
+ };
+ unsigned BBCnt = 0;
+ TestPass TPass(BBCnt);
+ // Check getName(),
+ EXPECT_EQ(TPass.getName(), "TestPass");
+ // Check getFlag().
+ EXPECT_EQ(TPass.getFlag(), "-test-pass");
+ // Check getSubclassID().
+ EXPECT_EQ(TPass.getSubclassID(), Pass::ClassID::FunctionPass);
+ // Check getSubclassIDStr().
+ EXPECT_EQ(Pass::getSubclassIDStr(TPass.getSubclassID()), "FunctionPass");
+ // Check classof().
+ EXPECT_TRUE(llvm::isa<FunctionPass>(TPass));
+ // Check runOnFunction();
+ TPass.runOnFunction(*F);
+ EXPECT_EQ(BBCnt, 1u);
+}
|
Are they vectoriser specific? Alternative place them here: |
ClassID SubclassID; | ||
|
||
public: | ||
Pass(const std::string &Name, const std::string &Flag, ClassID SubclassID) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe that we moved from const std::string &
to llvm::StringRef
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
/// The pass name. | ||
const std::string Name; | ||
/// The command-line flag used to specify that this pass should run. | ||
const std::string Flag; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or SmallString.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The user could give arbitrarily large names/flags so isn't an std::string better? I mean, what size should I use?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is a wrapper around a SmallVector. It is just stack friendlier than std::string.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can just leave it as std::string.
They are not specific to the vectorizer. Yeah |
llvm/include/llvm/SandboxIR/Pass.h
Outdated
//===----------------------------------------------------------------------===// | ||
|
||
#ifndef LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_PASS_H | ||
#define LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_PASS_H |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still the old name.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch :)
llvm/include/llvm/SandboxIR/Pass.h
Outdated
Pass.dumpOS(OS); | ||
return OS; | ||
} | ||
void dumpOS(raw_ostream &OS) const { OS << Name << " " << Flag; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is usually named print
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
llvm/include/llvm/SandboxIR/Pass.h
Outdated
FunctionPass(StringRef Name, StringRef Flag) | ||
: Pass(Name, Flag, ClassID::FunctionPass) {} | ||
/// For isa/dyn_cast etc. | ||
static bool classof(const Pass *From) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we need isa/dyn_cast
support? can we just add function/region/block passes to a pass manager that only holds that type? following the new pass manager pass adaptor/manager model
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that would complicate things. I was thinking of a pass manager that hods Pass * objects.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the thing about the legacy and new pass managers is that they run a bunch of function passes on one function at a time, then move to the next. they don't just run one function pass on every function then move on to the next. this is important for data locality for compile times, although perhaps that's not as important here. it's also fits in with the call graph walk where you want to see simplified callees
if you want the above, you need some sort of scheduling, whether dynamically (legacy pass manager) or statically in the code via adaptors and managers (new pass manager)
if you don't want the above, then you shouldn't need isa/dyn_cast
, just have subclasses implement a virtual run()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Our pass manager will operate in a similar way: The top-level pass manager will visit the functions in some order and for each one of them it will call runOnFunction()
for all registered passes before moving to the next function. The pass order is fixed. One or more function passes will also be a Region pass manager and that will operate in a similar way: it will go over the regions and for each one of them will call runOnRegion()
for all registered region passes.
We could use a virtual run()
but if we want to keep the runOnFunction/Region()
names I think we need the isa/dyn_cast
stuff.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I modified the PassManager's code a bit and I think we can remove the casts, as you suggested. Each pass manager will contain a vector of passes of the subclass type.
llvm/include/llvm/SandboxIR/Pass.h
Outdated
/// The pass name. | ||
const std::string Name; | ||
/// The command-line flag used to specify that this pass should run. | ||
const std::string Flag; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I will drop the Flag
. Even though Name
could be used more of a description of the pass, I think we should simplify things for now and just use Name
for the command-line flag too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
didn't notice the first time, but I would have thought this would go in the SandboxVectorizer, not SandboxIR? why are you deciding to put this in SandboxIR?
@@ -0,0 +1,84 @@ | |||
//===- PassesTest.cpp -----------------------------------------------------===// |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: file name
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(otherwise this lgtm)
This patch implements the Pass base class and the FunctionPass sub-class that operate on Sandbox IR.
It was initially in SandboxVectorizer but the Pass and FunctionPass classes are not vectorizer specific so @tschuett suggested we move it to SandboxIR, which sounds reasonable. The Region that the vectorizer will use is specific to the vectorizer, so we can implement that within the SandboxVectorizer directory. |
oh I should have looked at the previous comments this doesn't really feel like part of SandboxIR but a layer on top that's fairly specific to the vectorizer (I'm guessing most LLVM IR passes that use SandboxIR probably aren't going to have sub-passes that use this pass infra). I would have kept it in SandboxVectorizer, but oh well |
Ideally I think these files should be in a top-level directory like |
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/146/builds/1115 Here is the relevant piece of the build log for the reference
|
This patch implements the Pass base class and the FunctionPass sub-class that operate on Sandbox IR.