Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions llvm/include/llvm/SandboxIR/PassManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,28 @@
#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 {

class RegionPassManager;

class BottomUpVec final : public FunctionPass {
bool Change = false;
LegalityAnalysis Legality;
void vectorizeRec(ArrayRef<Value *> Bndl);
void tryVectorize(ArrayRef<Value *> Seeds);

// Used to build a RegionPass pipeline to be run on Regions created by the
// bottom-up vectorization pass. Owns the sub-passes.
PassRegistry PR;

// The PM containing the pipeline of region passes.
RegionPassManager RPM;

public:
BottomUpVec() : FunctionPass("bottom-up-vec") {}
BottomUpVec();
bool runOnFunction(Function &F) final;
};

Expand Down
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@
#ifndef LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_SANDBOXVECTORIZER_H
#define LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_SANDBOXVECTORIZER_H

#include <memory>

#include "llvm/IR/PassManager.h"
#include "llvm/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.h"

namespace llvm {

Expand All @@ -17,10 +20,13 @@ class TargetTransformInfo;
class SandboxVectorizerPass : public PassInfoMixin<SandboxVectorizerPass> {
TargetTransformInfo *TTI = nullptr;

public:
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
// The main vectorizer pass.
sandboxir::BottomUpVec BottomUpVecPass;

bool runImpl(Function &F);

public:
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
};

} // namespace llvm
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,69 @@
#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 {

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.
static const char *DefaultPipelineMagicStr = "*";

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."));

static void registerAllRegionPasses(sandboxir::PassRegistry &PR) {
PR.registerPass(std::make_unique<sandboxir::NullPass>());
}

/// Adds to `RPM` a sequence of passes described by `Pipeline` from the `PR`
/// pass registry.
static void parseAndCreatePassPipeline(RegionPassManager &RPM, PassRegistry &PR,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this function going to be used for non RegionPasses too? If not, should it be a member function of RPM?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It could be a member of RPM. The moral equivalent of this function for FunctionPassManager is currently a member function of PassRegistry:

class PassRegistry {
  ...
  FunctionPassManager &parseAndCreatePassPipeline(StringRef Pipeline);
};

If we change PassRegistry::parseAndCreatePassPipeline to get the pass manager as an argument rather than creating it inside the function, I think we could easily make it generic to avoid duplicating the pipeline parsing code:

class PassRegistry {
  ...
  template <typename PassManagerType>
  void parseAndCreatePassPipeline(PassManagerType &PM, StringRef Pipeline);
};

What do you think?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(and maybe change the Create part of the parseAndCreatePassPipeline name to something that better describes the new behavior)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm then perhaps we should deprecate the PassRegistry in favor of a PassManager that owns the passes?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We still need something to hold the mapping between names and passes so we can dynamically create pass pipelines based on the flag value. Right now the PassRegistry is that something. What are you proposing exactly?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see why we need a parsePassPipeline() in more than one place. Is the PassRegistry's parsePassPipeline() still being used after this patch?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the PassRegistry's parsePassPipeline() still being used after this patch?

As it is, no. That's why I proposed templatizing it so we can create pipelines of sandbox IR function passes, region passes, etc with a single parsing function. In the future, if there is more than one sandbox IR function pass, we'll probably want to create arbitrary pipelines out of them too. But I can also just delete that member function if we think we aren't going to need it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah templatizing it is fine, we can do it when needed.

But I can also just delete that member function if we think we aren't going to need it.

That's what I was thinking of. It seems that we are not going to need it.

Also if the PassRegistry's role ends up being just a mapping from name to pass class, then we could use a .def file.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about this?

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;

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));
}
}

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) {
// TODO: Add default passes to RPM.
} else {
// Create the user-defined pipeline.
parseAndCreatePassPipeline(RPM, 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) {
Expand All @@ -34,8 +93,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()) {
Expand All @@ -53,14 +110,23 @@ 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) {
// 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);
}
return Change;
}

} // namespace llvm::sandboxir
Original file line number Diff line number Diff line change
Expand Up @@ -9,27 +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"

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."));

PreservedAnalyses SandboxVectorizerPass::run(Function &F,
FunctionAnalysisManager &AM) {
TTI = &AM.getResult<TargetIRAnalysis>(F);
Expand All @@ -56,31 +42,8 @@ bool SandboxVectorizerPass::runImpl(Function &LLVMF) {
return false;
}

// Create SandboxIR for LLVMF and run BottomUpVec on it.
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());
return false;
}

// Run the pass pipeline.
bool Change = PM->runOnFunction(F);
return Change;
return BottomUpVecPass.runOnFunction(F);
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
8 changes: 4 additions & 4 deletions llvm/test/Transforms/SandboxVectorizer/user_pass_pipeline.ll
Original file line number Diff line number Diff line change
@@ -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
}
Loading