Skip to content

Commit 5364e1c

Browse files
committed
Support eraseIf in pass manager
1 parent f1ac334 commit 5364e1c

File tree

8 files changed

+150
-0
lines changed

8 files changed

+150
-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: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,21 @@ 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+
(*I)->eraseIf(Pred);
226+
bool IsSpecial = (*I)->name().ends_with("PassAdaptor") ||
227+
(*I)->name().contains("PassManager");
228+
bool PredResult = Pred((*I)->name());
229+
if ((!IsSpecial && PredResult) || (IsSpecial && (*I)->isEmpty()))
230+
I = Passes.erase(I);
231+
else
232+
++I;
233+
}
234+
}
235+
221236
protected:
222237
using PassConceptT =
223238
detail::PassConcept<IRUnitT, AnalysisManagerT, ExtraArgTs...>;
@@ -836,6 +851,10 @@ class ModuleToFunctionPassAdaptor
836851

837852
static bool isRequired() { return true; }
838853

854+
bool isEmpty() const { return Pass == nullptr; }
855+
856+
void eraseIf(function_ref<bool(StringRef)> Pred);
857+
839858
private:
840859
std::unique_ptr<PassConceptT> Pass;
841860
bool EagerlyInvalidate;

llvm/include/llvm/IR/PassManagerInternal.h

Lines changed: 35 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,34 @@ 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+
else
149+
return false;
150+
}
151+
117152
PassT Pass;
118153
};
119154

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
@@ -578,6 +578,17 @@ PreservedAnalyses CGSCCToFunctionPassAdaptor::run(LazyCallGraph::SCC &C,
578578
return PA;
579579
}
580580

581+
void CGSCCToFunctionPassAdaptor::eraseIf(function_ref<bool(StringRef)> Pred) {
582+
StringRef PassName = Pass->name();
583+
if (PassName.contains("PassManager") || PassName.ends_with("PassAdaptor")) {
584+
Pass->eraseIf(Pred);
585+
if (Pass->isEmpty())
586+
Pass.reset();
587+
} else if (Pred(PassName)) {
588+
Pass.reset();
589+
}
590+
}
591+
581592
bool CGSCCAnalysisManagerModuleProxy::Result::invalidate(
582593
Module &M, const PreservedAnalyses &PA,
583594
ModuleAnalysisManager::Invalidator &Inv) {
@@ -753,6 +764,18 @@ bool FunctionAnalysisManagerCGSCCProxy::Result::invalidate(
753764
return false;
754765
}
755766

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

758781
/// 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: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,39 @@ void PassManager<Loop, LoopAnalysisManager, LoopStandardAnalysisResults &,
6363
}
6464
}
6565

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

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

0 commit comments

Comments
 (0)