Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,29 @@
#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.
PassRegistry PR;

// The PM containing the pipeline of region passes. It's owned by the pass
// registry.
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,73 @@
#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 {

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(
Copy link
Contributor

Choose a reason for hiding this comment

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

this can be static/anonymous namespace

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

static sandboxir::RegionPassManager &
parseAndCreatePassPipeline(sandboxir::PassRegistry &PR, 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;
auto &RPM = static_cast<sandboxir::RegionPassManager &>(
PR.registerPass(std::make_unique<sandboxir::RegionPassManager>("rpm")));

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

BottomUpVec::BottomUpVec() : FunctionPass("bottom-up-vec") {
registerAllRegionPasses(PR);

// Create a pipeline to be run on each Region created by BottomUpVec.
if (UserDefinedPassPipeline == DefaultPipelineMagicStr) {
// Create the default pass pipeline.
RPM = &static_cast<sandboxir::RegionPassManager &>(PR.registerPass(
std::make_unique<sandboxir::FunctionPassManager>("rpm")));
// TODO: Add passes to the default pipeline.
} else {
// Create the user-defined pipeline.
RPM = &parseAndCreatePassPipeline(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 +97,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 +114,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