Skip to content

Commit 0375bf8

Browse files
slackitoDanielCChen
authored andcommitted
[SandboxVec] Re-land "Use sbvec-passes flag to create a pipeline of Region passes after BottomUpVec. (llvm#111223)" (llvm#111772)
llvm#111223 was reverted because of a build failure with `-DBUILD_SHARED_LIBS=on`. The Passes component depends on Vectorizer (because PassBuilder needs to be able to instantiate SandboxVectorizerPass). This resulted in CMake doing this 1. when it builds lib/libLLVMVectorize.so.20.0git it adds lib/libLLVMSandboxIR.so.20.0git to the command line, because it's listed as a dependency (as expected) 2. when it's trying to build lib/libLLVMPasses.so.20.0git it adds lib/libLLVMVectorize.so.20.0git to the command line, because it's listed as a dependency (also as expected). But not libLLVMSandboxIR.so. When SandboxVectorizerPass has its ctors/dtors defined inline, this caused "undefined reference to vtable" linker errors. This change works around that by moving ctors/dtors out of line. Also fix a bazel build problem by adding the new `llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/PassRegistry.def` as a textual header in the Vectorizer target.
1 parent 01014e9 commit 0375bf8

File tree

12 files changed

+220
-180
lines changed

12 files changed

+220
-180
lines changed

llvm/include/llvm/SandboxIR/PassManager.h

Lines changed: 46 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
#ifndef LLVM_SANDBOXIR_PASSMANAGER_H
1919
#define LLVM_SANDBOXIR_PASSMANAGER_H
2020

21+
#include <memory>
22+
2123
#include "llvm/ADT/DenseMap.h"
2224
#include "llvm/ADT/STLExtras.h"
2325
#include "llvm/SandboxIR/Pass.h"
@@ -32,25 +34,65 @@ template <typename ParentPass, typename ContainedPass>
3234
class PassManager : public ParentPass {
3335
protected:
3436
/// The list of passes that this pass manager will run.
35-
SmallVector<ContainedPass *> Passes;
37+
SmallVector<std::unique_ptr<ContainedPass>> Passes;
3638

3739
PassManager(StringRef Name) : ParentPass(Name) {}
3840
PassManager(const PassManager &) = delete;
41+
PassManager(PassManager &&) = default;
3942
virtual ~PassManager() = default;
4043
PassManager &operator=(const PassManager &) = delete;
4144

4245
public:
4346
/// Adds \p Pass to the pass pipeline.
44-
void addPass(ContainedPass *Pass) {
47+
void addPass(std::unique_ptr<ContainedPass> Pass) {
4548
// TODO: Check that Pass's class type works with this PassManager type.
46-
Passes.push_back(Pass);
49+
Passes.push_back(std::move(Pass));
50+
}
51+
52+
using CreatePassFunc =
53+
std::function<std::unique_ptr<ContainedPass>(StringRef)>;
54+
55+
/// Parses \p Pipeline as a comma-separated sequence of pass names and sets
56+
/// the pass pipeline, using \p CreatePass to instantiate passes by name.
57+
///
58+
/// After calling this function, the PassManager contains only the specified
59+
/// pipeline, any previously added passes are cleared.
60+
void setPassPipeline(StringRef Pipeline, CreatePassFunc CreatePass) {
61+
static constexpr const char EndToken = '\0';
62+
static constexpr const char PassDelimToken = ',';
63+
64+
assert(Passes.empty() &&
65+
"setPassPipeline called on a non-empty sandboxir::PassManager");
66+
// Add EndToken to the end to ease parsing.
67+
std::string PipelineStr = std::string(Pipeline) + EndToken;
68+
int FlagBeginIdx = 0;
69+
70+
for (auto [Idx, C] : enumerate(PipelineStr)) {
71+
// Keep moving Idx until we find the end of the pass name.
72+
bool FoundDelim = C == EndToken || C == PassDelimToken;
73+
if (!FoundDelim)
74+
continue;
75+
unsigned Sz = Idx - FlagBeginIdx;
76+
std::string PassName(&PipelineStr[FlagBeginIdx], Sz);
77+
FlagBeginIdx = Idx + 1;
78+
79+
// Get the pass that corresponds to PassName and add it to the pass
80+
// manager.
81+
auto Pass = CreatePass(PassName);
82+
if (Pass == nullptr) {
83+
errs() << "Pass '" << PassName << "' not registered!\n";
84+
exit(1);
85+
}
86+
addPass(std::move(Pass));
87+
}
4788
}
89+
4890
#ifndef NDEBUG
4991
void print(raw_ostream &OS) const override {
5092
OS << this->getName();
5193
OS << "(";
5294
// TODO: This should call Pass->print(OS) because Pass may be a PM.
53-
interleave(Passes, OS, [&OS](auto *Pass) { OS << Pass->getName(); }, ",");
95+
interleave(Passes, OS, [&OS](auto &Pass) { OS << Pass->getName(); }, ",");
5496
OS << ")";
5597
}
5698
LLVM_DUMP_METHOD void dump() const override {
@@ -79,38 +121,6 @@ class RegionPassManager final : public PassManager<RegionPass, RegionPass> {
79121
bool runOnRegion(Region &R) final;
80122
};
81123

82-
/// Owns the passes and provides an API to get a pass by its name.
83-
class PassRegistry {
84-
SmallVector<std::unique_ptr<Pass>, 8> Passes;
85-
DenseMap<StringRef, Pass *> NameToPassMap;
86-
87-
public:
88-
static constexpr const char PassDelimToken = ',';
89-
PassRegistry() = default;
90-
/// Registers \p PassPtr and takes ownership.
91-
Pass &registerPass(std::unique_ptr<Pass> &&PassPtr) {
92-
auto &PassRef = *PassPtr.get();
93-
NameToPassMap[PassRef.getName()] = &PassRef;
94-
Passes.push_back(std::move(PassPtr));
95-
return PassRef;
96-
}
97-
/// \Returns the pass with name \p Name, or null if not registered.
98-
Pass *getPassByName(StringRef Name) const {
99-
auto It = NameToPassMap.find(Name);
100-
return It != NameToPassMap.end() ? It->second : nullptr;
101-
}
102-
/// Creates a pass pipeline and returns the first pass manager.
103-
FunctionPassManager &parseAndCreatePassPipeline(StringRef Pipeline);
104-
105-
#ifndef NDEBUG
106-
void print(raw_ostream &OS) const {
107-
for (const auto &PassPtr : Passes)
108-
OS << PassPtr->getName() << "\n";
109-
}
110-
LLVM_DUMP_METHOD void dump() const;
111-
#endif
112-
};
113-
114124
} // namespace llvm::sandboxir
115125

116126
#endif // LLVM_SANDBOXIR_PASSMANAGER_H

llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,24 @@
1515
#include "llvm/ADT/ArrayRef.h"
1616
#include "llvm/SandboxIR/Constant.h"
1717
#include "llvm/SandboxIR/Pass.h"
18+
#include "llvm/SandboxIR/PassManager.h"
1819
#include "llvm/Transforms/Vectorize/SandboxVectorizer/Legality.h"
1920

2021
namespace llvm::sandboxir {
2122

23+
class RegionPassManager;
24+
2225
class BottomUpVec final : public FunctionPass {
2326
bool Change = false;
2427
LegalityAnalysis Legality;
2528
void vectorizeRec(ArrayRef<Value *> Bndl);
2629
void tryVectorize(ArrayRef<Value *> Seeds);
2730

31+
// The PM containing the pipeline of region passes.
32+
RegionPassManager RPM;
33+
2834
public:
29-
BottomUpVec() : FunctionPass("bottom-up-vec") {}
35+
BottomUpVec();
3036
bool runOnFunction(Function &F) final;
3137
};
3238

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#ifndef LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_PASSES_NULLPASS_H
2+
#define LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_PASSES_NULLPASS_H
3+
4+
#include "llvm/SandboxIR/Pass.h"
5+
6+
namespace llvm::sandboxir {
7+
8+
class Region;
9+
10+
/// A Region pass that does nothing, for use as a placeholder in tests.
11+
class NullPass final : public RegionPass {
12+
public:
13+
NullPass() : RegionPass("null") {}
14+
bool runOnRegion(Region &R) final { return false; }
15+
};
16+
17+
} // namespace llvm::sandboxir
18+
19+
#endif // LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_PASSES_NULLPASS_H

llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizer.h

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@
88
#ifndef LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_SANDBOXVECTORIZER_H
99
#define LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_SANDBOXVECTORIZER_H
1010

11+
#include <memory>
12+
1113
#include "llvm/IR/PassManager.h"
14+
#include "llvm/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.h"
1215

1316
namespace llvm {
1417

@@ -17,10 +20,22 @@ class TargetTransformInfo;
1720
class SandboxVectorizerPass : public PassInfoMixin<SandboxVectorizerPass> {
1821
TargetTransformInfo *TTI = nullptr;
1922

20-
public:
21-
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
23+
// The main vectorizer pass.
24+
sandboxir::BottomUpVec BottomUpVecPass;
2225

2326
bool runImpl(Function &F);
27+
28+
public:
29+
// Make sure the constructors/destructors are out-of-line. This works around a
30+
// problem with -DBUILD_SHARED_LIBS=on where components that depend on the
31+
// Vectorizer component can't find the vtable for classes like
32+
// sandboxir::Pass. This way we don't have to make LLVMPasses add a direct
33+
// dependency on SandboxIR.
34+
SandboxVectorizerPass();
35+
SandboxVectorizerPass(SandboxVectorizerPass &&);
36+
~SandboxVectorizerPass();
37+
38+
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
2439
};
2540

2641
} // namespace llvm

llvm/lib/SandboxIR/PassManager.cpp

Lines changed: 4 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@
88

99
#include "llvm/SandboxIR/PassManager.h"
1010

11-
using namespace llvm::sandboxir;
11+
namespace llvm::sandboxir {
1212

1313
bool FunctionPassManager::runOnFunction(Function &F) {
1414
bool Change = false;
15-
for (FunctionPass *Pass : Passes) {
15+
for (auto &Pass : Passes) {
1616
Change |= Pass->runOnFunction(F);
1717
// TODO: run the verifier.
1818
}
@@ -22,48 +22,12 @@ bool FunctionPassManager::runOnFunction(Function &F) {
2222

2323
bool RegionPassManager::runOnRegion(Region &R) {
2424
bool Change = false;
25-
for (RegionPass *Pass : Passes) {
25+
for (auto &Pass : Passes) {
2626
Change |= Pass->runOnRegion(R);
2727
// TODO: run the verifier.
2828
}
2929
// TODO: Check ChangeAll against hashes before/after.
3030
return Change;
3131
}
3232

33-
FunctionPassManager &
34-
PassRegistry::parseAndCreatePassPipeline(StringRef Pipeline) {
35-
static constexpr const char EndToken = '\0';
36-
// Add EndToken to the end to ease parsing.
37-
std::string PipelineStr = std::string(Pipeline) + EndToken;
38-
int FlagBeginIdx = 0;
39-
// Start with a FunctionPassManager.
40-
auto &InitialPM = static_cast<FunctionPassManager &>(
41-
registerPass(std::make_unique<FunctionPassManager>("init-fpm")));
42-
43-
for (auto [Idx, C] : enumerate(PipelineStr)) {
44-
// Keep moving Idx until we find the end of the pass name.
45-
bool FoundDelim = C == EndToken || C == PassDelimToken;
46-
if (!FoundDelim)
47-
continue;
48-
unsigned Sz = Idx - FlagBeginIdx;
49-
std::string PassName(&PipelineStr[FlagBeginIdx], Sz);
50-
FlagBeginIdx = Idx + 1;
51-
52-
// Get the pass that corresponds to PassName and add it to the pass manager.
53-
auto *Pass = getPassByName(PassName);
54-
if (Pass == nullptr) {
55-
errs() << "Pass '" << PassName << "' not registered!\n";
56-
exit(1);
57-
}
58-
// TODO: This is safe for now, but would require proper upcasting once we
59-
// add more Pass sub-classes.
60-
InitialPM.addPass(static_cast<FunctionPass *>(Pass));
61-
}
62-
return InitialPM;
63-
}
64-
#ifndef NDEBUG
65-
void PassRegistry::dump() const {
66-
print(dbgs());
67-
dbgs() << "\n";
68-
}
69-
#endif // NDEBUG
33+
} // namespace llvm::sandboxir

llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.cpp

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,41 @@
1010
#include "llvm/ADT/SmallVector.h"
1111
#include "llvm/SandboxIR/Function.h"
1212
#include "llvm/SandboxIR/Instruction.h"
13-
14-
using namespace llvm::sandboxir;
13+
#include "llvm/Support/CommandLine.h"
14+
#include "llvm/Transforms/Vectorize/SandboxVectorizer/Passes/NullPass.h"
1515

1616
namespace llvm::sandboxir {
17+
18+
static cl::opt<bool>
19+
PrintPassPipeline("sbvec-print-pass-pipeline", cl::init(false), cl::Hidden,
20+
cl::desc("Prints the pass pipeline and returns."));
21+
22+
/// A magic string for the default pass pipeline.
23+
static const char *DefaultPipelineMagicStr = "*";
24+
25+
static cl::opt<std::string> UserDefinedPassPipeline(
26+
"sbvec-passes", cl::init(DefaultPipelineMagicStr), cl::Hidden,
27+
cl::desc("Comma-separated list of vectorizer passes. If not set "
28+
"we run the predefined pipeline."));
29+
30+
static std::unique_ptr<RegionPass> createRegionPass(StringRef Name) {
31+
#define REGION_PASS(NAME, CREATE_PASS) \
32+
if (Name == NAME) \
33+
return std::make_unique<decltype(CREATE_PASS)>(CREATE_PASS);
34+
#include "PassRegistry.def"
35+
return nullptr;
36+
}
37+
38+
BottomUpVec::BottomUpVec() : FunctionPass("bottom-up-vec"), RPM("rpm") {
39+
// Create a pipeline to be run on each Region created by BottomUpVec.
40+
if (UserDefinedPassPipeline == DefaultPipelineMagicStr) {
41+
// TODO: Add default passes to RPM.
42+
} else {
43+
// Create the user-defined pipeline.
44+
RPM.setPassPipeline(UserDefinedPassPipeline, createRegionPass);
45+
}
46+
}
47+
1748
// TODO: This is a temporary function that returns some seeds.
1849
// Replace this with SeedCollector's function when it lands.
1950
static llvm::SmallVector<Value *, 4> collectSeeds(BasicBlock &BB) {
@@ -34,8 +65,6 @@ static SmallVector<Value *, 4> getOperand(ArrayRef<Value *> Bndl,
3465
return Operands;
3566
}
3667

37-
} // namespace llvm::sandboxir
38-
3968
void BottomUpVec::vectorizeRec(ArrayRef<Value *> Bndl) {
4069
auto LegalityRes = Legality.canVectorize(Bndl);
4170
switch (LegalityRes.getSubclassID()) {
@@ -53,14 +82,23 @@ void BottomUpVec::vectorizeRec(ArrayRef<Value *> Bndl) {
5382
void BottomUpVec::tryVectorize(ArrayRef<Value *> Bndl) { vectorizeRec(Bndl); }
5483

5584
bool BottomUpVec::runOnFunction(Function &F) {
85+
if (PrintPassPipeline) {
86+
RPM.printPipeline(outs());
87+
return false;
88+
}
89+
5690
Change = false;
5791
// TODO: Start from innermost BBs first
5892
for (auto &BB : F) {
5993
// TODO: Replace with proper SeedCollector function.
6094
auto Seeds = collectSeeds(BB);
6195
// TODO: Slice Seeds into smaller chunks.
96+
// TODO: If vectorization succeeds, run the RegionPassManager on the
97+
// resulting region.
6298
if (Seeds.size() >= 2)
6399
tryVectorize(Seeds);
64100
}
65101
return Change;
66102
}
103+
104+
} // namespace llvm::sandboxir
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//===- PassRegistry.def - Registry of passes --------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This file is used as the registry of sub-passes that are part of the
10+
// SandboxVectorizer pass.
11+
//
12+
//===----------------------------------------------------------------------===//
13+
14+
// NOTE: NO INCLUDE GUARD DESIRED!
15+
16+
#ifndef REGION_PASS
17+
#define REGION_PASS(NAME, CREATE_PASS)
18+
#endif
19+
20+
REGION_PASS("null", NullPass())
21+
22+
#undef REGION_PASS

0 commit comments

Comments
 (0)