Skip to content

Commit d93ded0

Browse files
committed
Support eraseIf in pass manager
1 parent 3f9d02a commit d93ded0

File tree

8 files changed

+156
-0
lines changed

8 files changed

+156
-0
lines changed

llvm/include/llvm/Analysis/CGSCCPassManager.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,10 @@ class ModuleToPostOrderCGSCCPassAdaptor
346346

347347
static bool isRequired() { return true; }
348348

349+
bool isEmpty() const { return Pass == nullptr; }
350+
351+
void eraseIf(function_ref<bool(StringRef)> Pred);
352+
349353
private:
350354
std::unique_ptr<PassConceptT> Pass;
351355
};
@@ -488,6 +492,8 @@ class CGSCCToFunctionPassAdaptor
488492

489493
static bool isRequired() { return true; }
490494

495+
void eraseIf(function_ref<bool(StringRef)> Pred);
496+
491497
private:
492498
std::unique_ptr<PassConceptT> Pass;
493499
bool EagerlyInvalidate;

llvm/include/llvm/CodeGen/MachinePassManager.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,10 @@ class FunctionToMachineFunctionPassAdaptor
207207

208208
static bool isRequired() { return true; }
209209

210+
bool isEmpty() const { return Pass == nullptr; }
211+
212+
void eraseIf(function_ref<bool(StringRef)> Pred);
213+
210214
private:
211215
std::unique_ptr<PassConceptT> Pass;
212216
};

llvm/include/llvm/IR/PassManager.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,22 @@ class PassManager : public PassInfoMixin<
218218

219219
static bool isRequired() { return true; }
220220

221+
/// Erase all passes that satisfy the predicate \p Pred.
222+
/// For internal use only!
223+
void eraseIf(function_ref<bool(StringRef)> Pred) {
224+
for (auto I = Passes.begin(); I != Passes.end();) {
225+
auto &P = *I;
226+
P->eraseIf(Pred);
227+
bool IsSpecial = P->name().ends_with("PassAdaptor") ||
228+
P->name().contains("PassManager");
229+
bool PredResult = Pred(P->name());
230+
if ((!IsSpecial && PredResult) || (IsSpecial && P->isEmpty()))
231+
I = Passes.erase(I);
232+
else
233+
++I;
234+
}
235+
}
236+
221237
protected:
222238
using PassConceptT =
223239
detail::PassConcept<IRUnitT, AnalysisManagerT, ExtraArgTs...>;
@@ -836,6 +852,10 @@ class ModuleToFunctionPassAdaptor
836852

837853
static bool isRequired() { return true; }
838854

855+
bool isEmpty() const { return Pass == nullptr; }
856+
857+
void eraseIf(function_ref<bool(StringRef)> Pred);
858+
839859
private:
840860
std::unique_ptr<PassConceptT> Pass;
841861
bool EagerlyInvalidate;

llvm/include/llvm/IR/PassManagerInternal.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,13 @@ struct PassConcept {
5959
/// To opt-in, pass should implement `static bool isRequired()`. It's no-op
6060
/// to have `isRequired` always return false since that is the default.
6161
virtual bool isRequired() const = 0;
62+
63+
/// Polymorphic method to refurbish pass pipeline.
64+
virtual void eraseIf(function_ref<bool(StringRef)> Pred) = 0;
65+
66+
/// There may be some empty PassManager after erasing,
67+
/// use it to remove them.
68+
virtual bool isEmpty() const = 0;
6269
};
6370

6471
/// A template wrapper used to implement the polymorphic API.
@@ -114,6 +121,33 @@ struct PassModel : PassConcept<IRUnitT, AnalysisManagerT, ExtraArgTs...> {
114121

115122
bool isRequired() const override { return passIsRequiredImpl<PassT>(); }
116123

124+
template <typename T>
125+
using has_erase_if_t = decltype(std::declval<T &>().eraseIf(
126+
std::declval<function_ref<bool(StringRef)>>()));
127+
128+
template <typename T>
129+
std::enable_if_t<is_detected<has_erase_if_t, T>::value>
130+
eraseIfImpl(function_ref<bool(StringRef)> Pred) {
131+
Pass.eraseIf(Pred);
132+
}
133+
134+
template <typename T>
135+
std::enable_if_t<!is_detected<has_erase_if_t, T>::value>
136+
eraseIfImpl(function_ref<bool(StringRef)>) {}
137+
138+
void eraseIf(function_ref<bool(StringRef)> Pred) override {
139+
eraseIfImpl<PassT>(Pred);
140+
}
141+
142+
template <typename T>
143+
using has_is_empty_t = decltype(std::declval<T &>().isEmpty());
144+
145+
bool isEmpty() const override {
146+
if constexpr (is_detected<has_is_empty_t, PassT>::value)
147+
return Pass.isEmpty();
148+
return false;
149+
}
150+
117151
PassT Pass;
118152
};
119153

llvm/include/llvm/Transforms/Scalar/LoopPassManager.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,10 @@ class PassManager<Loop, LoopAnalysisManager, LoopStandardAnalysisResults &,
134134

135135
static bool isRequired() { return true; }
136136

137+
/// Erase all passes that satisfy the predicate \p Pred.
138+
/// For internal use only!
139+
void eraseIf(function_ref<bool(StringRef)> Pred);
140+
137141
size_t getNumLoopPasses() const { return LoopPasses.size(); }
138142
size_t getNumLoopNestPasses() const { return LoopNestPasses.size(); }
139143

@@ -425,6 +429,10 @@ class FunctionToLoopPassAdaptor
425429

426430
static bool isRequired() { return true; }
427431

432+
bool isEmpty() const { return Pass == nullptr; }
433+
434+
void eraseIf(function_ref<bool(StringRef)> Pred);
435+
428436
bool isLoopNestMode() const { return LoopNestMode; }
429437

430438
private:

llvm/lib/Analysis/CGSCCPassManager.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -576,6 +576,17 @@ PreservedAnalyses CGSCCToFunctionPassAdaptor::run(LazyCallGraph::SCC &C,
576576
return PA;
577577
}
578578

579+
void CGSCCToFunctionPassAdaptor::eraseIf(function_ref<bool(StringRef)> Pred) {
580+
StringRef PassName = Pass->name();
581+
if (PassName.contains("PassManager") || PassName.ends_with("PassAdaptor")) {
582+
Pass->eraseIf(Pred);
583+
if (Pass->isEmpty())
584+
Pass.reset();
585+
} else if (Pred(PassName)) {
586+
Pass.reset();
587+
}
588+
}
589+
579590
bool CGSCCAnalysisManagerModuleProxy::Result::invalidate(
580591
Module &M, const PreservedAnalyses &PA,
581592
ModuleAnalysisManager::Invalidator &Inv) {
@@ -751,6 +762,18 @@ bool FunctionAnalysisManagerCGSCCProxy::Result::invalidate(
751762
return false;
752763
}
753764

765+
void ModuleToPostOrderCGSCCPassAdaptor::eraseIf(
766+
function_ref<bool(StringRef)> Pred) {
767+
StringRef PassName = Pass->name();
768+
if (PassName.contains("PassManager") || PassName.ends_with("PassAdaptor")) {
769+
Pass->eraseIf(Pred);
770+
if (Pass->isEmpty())
771+
Pass.reset();
772+
} else if (Pred(PassName)) {
773+
Pass.reset();
774+
}
775+
}
776+
754777
} // end namespace llvm
755778

756779
/// When a new SCC is created for the graph we first update the

llvm/lib/IR/PassManager.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,17 @@ PreservedAnalyses ModuleToFunctionPassAdaptor::run(Module &M,
145145
return PA;
146146
}
147147

148+
void ModuleToFunctionPassAdaptor::eraseIf(function_ref<bool(StringRef)> Pred) {
149+
StringRef PassName = Pass->name();
150+
if (PassName.contains("PassManager") || PassName.ends_with("PassAdaptor")) {
151+
Pass->eraseIf(Pred);
152+
if (Pass->isEmpty())
153+
Pass.reset();
154+
} else if (Pred(PassName)) {
155+
Pass.reset();
156+
}
157+
}
158+
148159
template <>
149160
void llvm::printIRUnitNameForStackTrace<Module>(raw_ostream &OS,
150161
const Module &IR) {

llvm/lib/Transforms/Scalar/LoopPassManager.cpp

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,45 @@ void PassManager<Loop, LoopAnalysisManager, LoopStandardAnalysisResults &,
6262
}
6363
}
6464

65+
void PassManager<Loop, LoopAnalysisManager, LoopStandardAnalysisResults &,
66+
LPMUpdater &>::eraseIf(function_ref<bool(StringRef)> Pred) {
67+
assert(LoopPasses.size() + LoopNestPasses.size() == IsLoopNestPass.size() &&
68+
"Wrong precondition!");
69+
70+
std::vector<char> IsLoopNestPassVec(
71+
static_cast<size_t>(IsLoopNestPass.size()));
72+
for (unsigned Idx = 0, Sz = IsLoopNestPass.size(); Idx != Sz; ++Idx)
73+
IsLoopNestPassVec[Idx] = IsLoopNestPass[Idx];
74+
75+
auto ILP = LoopPasses.begin();
76+
auto ILNP = LoopNestPasses.begin();
77+
for (auto I = IsLoopNestPassVec.begin(); I != IsLoopNestPassVec.end();) {
78+
if (*I) {
79+
if (Pred((*ILNP)->name())) {
80+
I = IsLoopNestPassVec.erase(I);
81+
ILNP = LoopNestPasses.erase(ILNP);
82+
continue;
83+
}
84+
++ILNP;
85+
} else {
86+
if (Pred((*ILP)->name())) {
87+
I = IsLoopNestPassVec.erase(I);
88+
ILP = LoopPasses.erase(ILP);
89+
continue;
90+
}
91+
++ILP;
92+
}
93+
++I;
94+
}
95+
96+
IsLoopNestPass.clear();
97+
for (const auto I : IsLoopNestPassVec)
98+
IsLoopNestPass.push_back(I);
99+
100+
assert(LoopPasses.size() + LoopNestPasses.size() == IsLoopNestPass.size() &&
101+
"Wrong postcondition!");
102+
}
103+
65104
// Run both loop passes and loop-nest passes on top-level loop \p L.
66105
PreservedAnalyses
67106
LoopPassManager::runWithLoopNestPasses(Loop &L, LoopAnalysisManager &AM,
@@ -359,6 +398,17 @@ PreservedAnalyses FunctionToLoopPassAdaptor::run(Function &F,
359398
return PA;
360399
}
361400

401+
void FunctionToLoopPassAdaptor::eraseIf(function_ref<bool(StringRef)> Pred) {
402+
StringRef PassName = Pass->name();
403+
if (PassName.contains("PassManager") || PassName.ends_with("PassAdaptor")) {
404+
Pass->eraseIf(Pred);
405+
if (Pass->isEmpty())
406+
Pass.reset();
407+
} else if (Pred(PassName)) {
408+
Pass.reset();
409+
}
410+
}
411+
362412
PrintLoopPass::PrintLoopPass() : OS(dbgs()) {}
363413
PrintLoopPass::PrintLoopPass(raw_ostream &OS, const std::string &Banner)
364414
: OS(OS), Banner(Banner) {}

0 commit comments

Comments
 (0)