Skip to content

Commit ae1c1ed

Browse files
authored
[CodeGen] Allow CodeGenPassBuilder to add module pass after function pass (#77084)
In fact, there are several backends, e.g. AArch64, AMDGPU etc. add module pass after function pass, this patch removes this constraint. This patch also adds a simple unit test for `CodeGenPassBuilder`.
1 parent dc61ebb commit ae1c1ed

File tree

5 files changed

+253
-135
lines changed

5 files changed

+253
-135
lines changed

llvm/include/llvm/CodeGen/CodeGenPassBuilder.h

Lines changed: 22 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -175,45 +175,33 @@ template <typename DerivedT> class CodeGenPassBuilder {
175175
// Function object to maintain state while adding codegen IR passes.
176176
class AddIRPass {
177177
public:
178-
AddIRPass(ModulePassManager &MPM, bool DebugPM, bool Check = true)
179-
: MPM(MPM) {
180-
if (Check)
181-
AddingFunctionPasses = false;
182-
}
178+
AddIRPass(ModulePassManager &MPM) : MPM(MPM) {}
183179
~AddIRPass() {
184-
MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
185-
}
186-
187-
// Add Function Pass
188-
template <typename PassT>
189-
std::enable_if_t<is_detected<is_function_pass_t, PassT>::value>
190-
operator()(PassT &&Pass) {
191-
if (AddingFunctionPasses && !*AddingFunctionPasses)
192-
AddingFunctionPasses = true;
193-
FPM.addPass(std::forward<PassT>(Pass));
180+
if (!FPM.isEmpty())
181+
MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
194182
}
195183

196-
// Add Module Pass
197-
template <typename PassT>
198-
std::enable_if_t<is_detected<is_module_pass_t, PassT>::value &&
199-
!is_detected<is_function_pass_t, PassT>::value>
200-
operator()(PassT &&Pass) {
201-
assert((!AddingFunctionPasses || !*AddingFunctionPasses) &&
202-
"could not add module pass after adding function pass");
203-
MPM.addPass(std::forward<PassT>(Pass));
184+
template <typename PassT> void operator()(PassT &&Pass) {
185+
static_assert((is_detected<is_function_pass_t, PassT>::value ||
186+
is_detected<is_module_pass_t, PassT>::value) &&
187+
"Only module pass and function pass are supported.");
188+
189+
// Add Function Pass
190+
if constexpr (is_detected<is_function_pass_t, PassT>::value) {
191+
FPM.addPass(std::forward<PassT>(Pass));
192+
} else {
193+
// Add Module Pass
194+
if (!FPM.isEmpty()) {
195+
MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
196+
FPM = FunctionPassManager();
197+
}
198+
MPM.addPass(std::forward<PassT>(Pass));
199+
}
204200
}
205201

206202
private:
207203
ModulePassManager &MPM;
208204
FunctionPassManager FPM;
209-
// The codegen IR pipeline are mostly function passes with the exceptions of
210-
// a few loop and module passes. `AddingFunctionPasses` make sures that
211-
// we could only add module passes at the beginning of the pipeline. Once
212-
// we begin adding function passes, we could no longer add module passes.
213-
// This special-casing introduces less adaptor passes. If we have the need
214-
// of adding module passes after function passes, we could change the
215-
// implementation to accommodate that.
216-
std::optional<bool> AddingFunctionPasses;
217205
};
218206

219207
// Function object to maintain state while adding codegen machine passes.
@@ -488,7 +476,7 @@ Error CodeGenPassBuilder<Derived>::buildPipeline(
488476
ModulePassManager &MPM, MachineFunctionPassManager &MFPM,
489477
raw_pwrite_stream &Out, raw_pwrite_stream *DwoOut,
490478
CodeGenFileType FileType) const {
491-
AddIRPass addIRPass(MPM, Opt.DebugPM);
479+
AddIRPass addIRPass(MPM);
492480
// `ProfileSummaryInfo` is always valid.
493481
addIRPass(RequireAnalysisPass<ProfileSummaryAnalysis, Module>());
494482
addIRPass(RequireAnalysisPass<CollectorMetadataAnalysis, Module>());
@@ -627,8 +615,8 @@ void CodeGenPassBuilder<Derived>::addIRPasses(AddIRPass &addPass) const {
627615

628616
// Run loop strength reduction before anything else.
629617
if (getOptLevel() != CodeGenOptLevel::None && !Opt.DisableLSR) {
630-
addPass(createFunctionToLoopPassAdaptor(
631-
LoopStrengthReducePass(), /*UseMemorySSA*/ true, Opt.DebugPM));
618+
addPass(createFunctionToLoopPassAdaptor(LoopStrengthReducePass(),
619+
/*UseMemorySSA=*/true));
632620
// FIXME: use -stop-after so we could remove PrintLSR
633621
if (Opt.PrintLSR)
634622
addPass(PrintFunctionPass(dbgs(), "\n\n*** Code after LSR ***\n"));
@@ -647,9 +635,6 @@ void CodeGenPassBuilder<Derived>::addIRPasses(AddIRPass &addPass) const {
647635
// Run GC lowering passes for builtin collectors
648636
// TODO: add a pass insertion point here
649637
addPass(GCLoweringPass());
650-
// FIXME: `ShadowStackGCLoweringPass` now is a
651-
// module pass, so it will trigger assertion.
652-
// See comment of `AddingFunctionPasses`
653638
addPass(ShadowStackGCLoweringPass());
654639
addPass(LowerConstantIntrinsicsPass());
655640

llvm/include/llvm/Passes/PassBuilder.h

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -743,6 +743,90 @@ bool parseAnalysisUtilityPasses(
743743

744744
return false;
745745
}
746+
747+
// These are special since they are only for testing purposes.
748+
749+
/// No-op module pass which does nothing.
750+
struct NoOpModulePass : PassInfoMixin<NoOpModulePass> {
751+
PreservedAnalyses run(Module &M, ModuleAnalysisManager &) {
752+
return PreservedAnalyses::all();
753+
}
754+
};
755+
756+
/// No-op module analysis.
757+
class NoOpModuleAnalysis : public AnalysisInfoMixin<NoOpModuleAnalysis> {
758+
friend AnalysisInfoMixin<NoOpModuleAnalysis>;
759+
static AnalysisKey Key;
760+
761+
public:
762+
struct Result {};
763+
Result run(Module &, ModuleAnalysisManager &) { return Result(); }
764+
};
765+
766+
/// No-op CGSCC pass which does nothing.
767+
struct NoOpCGSCCPass : PassInfoMixin<NoOpCGSCCPass> {
768+
PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &,
769+
LazyCallGraph &, CGSCCUpdateResult &UR) {
770+
return PreservedAnalyses::all();
771+
}
772+
};
773+
774+
/// No-op CGSCC analysis.
775+
class NoOpCGSCCAnalysis : public AnalysisInfoMixin<NoOpCGSCCAnalysis> {
776+
friend AnalysisInfoMixin<NoOpCGSCCAnalysis>;
777+
static AnalysisKey Key;
778+
779+
public:
780+
struct Result {};
781+
Result run(LazyCallGraph::SCC &, CGSCCAnalysisManager &, LazyCallGraph &G) {
782+
return Result();
783+
}
784+
};
785+
786+
/// No-op function pass which does nothing.
787+
struct NoOpFunctionPass : PassInfoMixin<NoOpFunctionPass> {
788+
PreservedAnalyses run(Function &F, FunctionAnalysisManager &) {
789+
return PreservedAnalyses::all();
790+
}
791+
};
792+
793+
/// No-op function analysis.
794+
class NoOpFunctionAnalysis : public AnalysisInfoMixin<NoOpFunctionAnalysis> {
795+
friend AnalysisInfoMixin<NoOpFunctionAnalysis>;
796+
static AnalysisKey Key;
797+
798+
public:
799+
struct Result {};
800+
Result run(Function &, FunctionAnalysisManager &) { return Result(); }
801+
};
802+
803+
/// No-op loop nest pass which does nothing.
804+
struct NoOpLoopNestPass : PassInfoMixin<NoOpLoopNestPass> {
805+
PreservedAnalyses run(LoopNest &L, LoopAnalysisManager &,
806+
LoopStandardAnalysisResults &, LPMUpdater &) {
807+
return PreservedAnalyses::all();
808+
}
809+
};
810+
811+
/// No-op loop pass which does nothing.
812+
struct NoOpLoopPass : PassInfoMixin<NoOpLoopPass> {
813+
PreservedAnalyses run(Loop &L, LoopAnalysisManager &,
814+
LoopStandardAnalysisResults &, LPMUpdater &) {
815+
return PreservedAnalyses::all();
816+
}
817+
};
818+
819+
/// No-op loop analysis.
820+
class NoOpLoopAnalysis : public AnalysisInfoMixin<NoOpLoopAnalysis> {
821+
friend AnalysisInfoMixin<NoOpLoopAnalysis>;
822+
static AnalysisKey Key;
823+
824+
public:
825+
struct Result {};
826+
Result run(Loop &, LoopAnalysisManager &, LoopStandardAnalysisResults &) {
827+
return Result();
828+
}
829+
};
746830
}
747831

748832
#endif

llvm/lib/Passes/PassBuilder.cpp

Lines changed: 2 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -300,109 +300,13 @@ cl::opt<bool> PrintPipelinePasses(
300300
"(best-effort only)."));
301301
} // namespace llvm
302302

303-
namespace {
304-
305-
// The following passes/analyses have custom names, otherwise their name will
306-
// include `(anonymous namespace)`. These are special since they are only for
307-
// testing purposes and don't live in a header file.
308-
309-
/// No-op module pass which does nothing.
310-
struct NoOpModulePass : PassInfoMixin<NoOpModulePass> {
311-
PreservedAnalyses run(Module &M, ModuleAnalysisManager &) {
312-
return PreservedAnalyses::all();
313-
}
314-
315-
static StringRef name() { return "NoOpModulePass"; }
316-
};
317-
318-
/// No-op module analysis.
319-
class NoOpModuleAnalysis : public AnalysisInfoMixin<NoOpModuleAnalysis> {
320-
friend AnalysisInfoMixin<NoOpModuleAnalysis>;
321-
static AnalysisKey Key;
322-
323-
public:
324-
struct Result {};
325-
Result run(Module &, ModuleAnalysisManager &) { return Result(); }
326-
static StringRef name() { return "NoOpModuleAnalysis"; }
327-
};
328-
329-
/// No-op CGSCC pass which does nothing.
330-
struct NoOpCGSCCPass : PassInfoMixin<NoOpCGSCCPass> {
331-
PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &,
332-
LazyCallGraph &, CGSCCUpdateResult &UR) {
333-
return PreservedAnalyses::all();
334-
}
335-
static StringRef name() { return "NoOpCGSCCPass"; }
336-
};
337-
338-
/// No-op CGSCC analysis.
339-
class NoOpCGSCCAnalysis : public AnalysisInfoMixin<NoOpCGSCCAnalysis> {
340-
friend AnalysisInfoMixin<NoOpCGSCCAnalysis>;
341-
static AnalysisKey Key;
342-
343-
public:
344-
struct Result {};
345-
Result run(LazyCallGraph::SCC &, CGSCCAnalysisManager &, LazyCallGraph &G) {
346-
return Result();
347-
}
348-
static StringRef name() { return "NoOpCGSCCAnalysis"; }
349-
};
350-
351-
/// No-op function pass which does nothing.
352-
struct NoOpFunctionPass : PassInfoMixin<NoOpFunctionPass> {
353-
PreservedAnalyses run(Function &F, FunctionAnalysisManager &) {
354-
return PreservedAnalyses::all();
355-
}
356-
static StringRef name() { return "NoOpFunctionPass"; }
357-
};
358-
359-
/// No-op function analysis.
360-
class NoOpFunctionAnalysis : public AnalysisInfoMixin<NoOpFunctionAnalysis> {
361-
friend AnalysisInfoMixin<NoOpFunctionAnalysis>;
362-
static AnalysisKey Key;
363-
364-
public:
365-
struct Result {};
366-
Result run(Function &, FunctionAnalysisManager &) { return Result(); }
367-
static StringRef name() { return "NoOpFunctionAnalysis"; }
368-
};
369-
370-
/// No-op loop nest pass which does nothing.
371-
struct NoOpLoopNestPass : PassInfoMixin<NoOpLoopNestPass> {
372-
PreservedAnalyses run(LoopNest &L, LoopAnalysisManager &,
373-
LoopStandardAnalysisResults &, LPMUpdater &) {
374-
return PreservedAnalyses::all();
375-
}
376-
static StringRef name() { return "NoOpLoopNestPass"; }
377-
};
378-
379-
/// No-op loop pass which does nothing.
380-
struct NoOpLoopPass : PassInfoMixin<NoOpLoopPass> {
381-
PreservedAnalyses run(Loop &L, LoopAnalysisManager &,
382-
LoopStandardAnalysisResults &, LPMUpdater &) {
383-
return PreservedAnalyses::all();
384-
}
385-
static StringRef name() { return "NoOpLoopPass"; }
386-
};
387-
388-
/// No-op loop analysis.
389-
class NoOpLoopAnalysis : public AnalysisInfoMixin<NoOpLoopAnalysis> {
390-
friend AnalysisInfoMixin<NoOpLoopAnalysis>;
391-
static AnalysisKey Key;
392-
393-
public:
394-
struct Result {};
395-
Result run(Loop &, LoopAnalysisManager &, LoopStandardAnalysisResults &) {
396-
return Result();
397-
}
398-
static StringRef name() { return "NoOpLoopAnalysis"; }
399-
};
400-
401303
AnalysisKey NoOpModuleAnalysis::Key;
402304
AnalysisKey NoOpCGSCCAnalysis::Key;
403305
AnalysisKey NoOpFunctionAnalysis::Key;
404306
AnalysisKey NoOpLoopAnalysis::Key;
405307

308+
namespace {
309+
406310
/// Whether or not we should populate a PassInstrumentationCallbacks's class to
407311
/// pass name map.
408312
///

llvm/unittests/CodeGen/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,16 @@ set(LLVM_LINK_COMPONENTS
77
CodeGenTypes
88
Core
99
FileCheck
10+
IRPrinter
1011
MC
1112
MIRParser
1213
Passes
14+
ScalarOpts
1315
SelectionDAG
1416
Support
1517
Target
1618
TargetParser
19+
TransformUtils
1720
)
1821

1922
add_llvm_unittest(CodeGenTests
@@ -22,6 +25,7 @@ add_llvm_unittest(CodeGenTests
2225
AMDGPUMetadataTest.cpp
2326
AsmPrinterDwarfTest.cpp
2427
CCStateTest.cpp
28+
CodeGenPassBuilderTest.cpp
2529
DIEHashTest.cpp
2630
DIETest.cpp
2731
DwarfStringPoolEntryRefTest.cpp

0 commit comments

Comments
 (0)