Add NoOpLoopNestPass and LOOPNEST_PASS macro
Having a NoOpLoopNestPass can ensure that only outermost loop is invoked for a LoopNestPass with a lit test. There are some existing passes that are implemented as LoopNestPass, but they are still using LOOP_PASS macro. It would be easier to identify LoopNestPasses with a LOOPNEST_PASS macro. Differential Revision: https://reviews.llvm.org/D113185
This commit is contained in:
parent
085accea3c
commit
93421108d2
|
@ -319,6 +319,15 @@ public:
|
|||
static StringRef name() { return "NoOpFunctionAnalysis"; }
|
||||
};
|
||||
|
||||
/// No-op loop nest pass which does nothing.
|
||||
struct NoOpLoopNestPass : PassInfoMixin<NoOpLoopNestPass> {
|
||||
PreservedAnalyses run(LoopNest &L, LoopAnalysisManager &,
|
||||
LoopStandardAnalysisResults &, LPMUpdater &) {
|
||||
return PreservedAnalyses::all();
|
||||
}
|
||||
static StringRef name() { return "NoOpLoopNestPass"; }
|
||||
};
|
||||
|
||||
/// No-op loop pass which does nothing.
|
||||
struct NoOpLoopPass : PassInfoMixin<NoOpLoopPass> {
|
||||
PreservedAnalyses run(Loop &L, LoopAnalysisManager &,
|
||||
|
@ -378,6 +387,8 @@ PassBuilder::PassBuilder(TargetMachine *TM, PipelineTuningOptions PTO,
|
|||
PIC->addClassToPassName(CLASS, NAME);
|
||||
#define FUNCTION_ANALYSIS(NAME, CREATE_PASS) \
|
||||
PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME);
|
||||
#define LOOPNEST_PASS(NAME, CREATE_PASS) \
|
||||
PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME);
|
||||
#define LOOP_PASS(NAME, CREATE_PASS) \
|
||||
PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME);
|
||||
#define LOOP_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \
|
||||
|
@ -907,6 +918,28 @@ static bool isFunctionPassName(StringRef Name, CallbacksT &Callbacks) {
|
|||
return callbacksAcceptPassName<FunctionPassManager>(Name, Callbacks);
|
||||
}
|
||||
|
||||
template <typename CallbacksT>
|
||||
static bool isLoopNestPassName(StringRef Name, CallbacksT &Callbacks,
|
||||
bool &UseMemorySSA) {
|
||||
UseMemorySSA = false;
|
||||
|
||||
// Explicitly handle custom-parsed pass names.
|
||||
if (parseRepeatPassName(Name))
|
||||
return true;
|
||||
|
||||
if (Name == "lnicm") {
|
||||
UseMemorySSA = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
#define LOOPNEST_PASS(NAME, CREATE_PASS) \
|
||||
if (Name == NAME) \
|
||||
return true;
|
||||
#include "PassRegistry.def"
|
||||
|
||||
return callbacksAcceptPassName<LoopPassManager>(Name, Callbacks);
|
||||
}
|
||||
|
||||
template <typename CallbacksT>
|
||||
static bool isLoopPassName(StringRef Name, CallbacksT &Callbacks,
|
||||
bool &UseMemorySSA) {
|
||||
|
@ -1140,6 +1173,12 @@ Error PassBuilder::parseModulePass(ModulePassManager &MPM,
|
|||
MPM.addPass(createModuleToFunctionPassAdaptor(CREATE_PASS(Params.get()))); \
|
||||
return Error::success(); \
|
||||
}
|
||||
#define LOOPNEST_PASS(NAME, CREATE_PASS) \
|
||||
if (Name == NAME) { \
|
||||
MPM.addPass(createModuleToFunctionPassAdaptor( \
|
||||
createFunctionToLoopPassAdaptor(CREATE_PASS, false, false))); \
|
||||
return Error::success(); \
|
||||
}
|
||||
#define LOOP_PASS(NAME, CREATE_PASS) \
|
||||
if (Name == NAME) { \
|
||||
MPM.addPass(createModuleToFunctionPassAdaptor( \
|
||||
|
@ -1256,6 +1295,12 @@ Error PassBuilder::parseCGSCCPass(CGSCCPassManager &CGPM,
|
|||
CGPM.addPass(createCGSCCToFunctionPassAdaptor(CREATE_PASS(Params.get()))); \
|
||||
return Error::success(); \
|
||||
}
|
||||
#define LOOPNEST_PASS(NAME, CREATE_PASS) \
|
||||
if (Name == NAME) { \
|
||||
CGPM.addPass(createCGSCCToFunctionPassAdaptor( \
|
||||
createFunctionToLoopPassAdaptor(CREATE_PASS, false, false))); \
|
||||
return Error::success(); \
|
||||
}
|
||||
#define LOOP_PASS(NAME, CREATE_PASS) \
|
||||
if (Name == NAME) { \
|
||||
CGPM.addPass(createCGSCCToFunctionPassAdaptor( \
|
||||
|
@ -1360,6 +1405,11 @@ Error PassBuilder::parseFunctionPass(FunctionPassManager &FPM,
|
|||
// bool UseMemorySSA = !("canon-freeze" || "loop-predication" ||
|
||||
// "guard-widening");
|
||||
// The risk is that it may become obsolete if we're not careful.
|
||||
#define LOOPNEST_PASS(NAME, CREATE_PASS) \
|
||||
if (Name == NAME) { \
|
||||
FPM.addPass(createFunctionToLoopPassAdaptor(CREATE_PASS, false, false)); \
|
||||
return Error::success(); \
|
||||
}
|
||||
#define LOOP_PASS(NAME, CREATE_PASS) \
|
||||
if (Name == NAME) { \
|
||||
FPM.addPass(createFunctionToLoopPassAdaptor(CREATE_PASS, false, false)); \
|
||||
|
@ -1418,6 +1468,11 @@ Error PassBuilder::parseLoopPass(LoopPassManager &LPM,
|
|||
}
|
||||
|
||||
// Now expand the basic registered passes from the .inc file.
|
||||
#define LOOPNEST_PASS(NAME, CREATE_PASS) \
|
||||
if (Name == NAME) { \
|
||||
LPM.addPass(CREATE_PASS); \
|
||||
return Error::success(); \
|
||||
}
|
||||
#define LOOP_PASS(NAME, CREATE_PASS) \
|
||||
if (Name == NAME) { \
|
||||
LPM.addPass(CREATE_PASS); \
|
||||
|
@ -1545,6 +1600,10 @@ Error PassBuilder::parsePassPipeline(ModulePassManager &MPM,
|
|||
} else if (isFunctionPassName(FirstName,
|
||||
FunctionPipelineParsingCallbacks)) {
|
||||
Pipeline = {{"function", std::move(*Pipeline)}};
|
||||
} else if (isLoopNestPassName(FirstName, LoopPipelineParsingCallbacks,
|
||||
UseMemorySSA)) {
|
||||
Pipeline = {{"function", {{UseMemorySSA ? "loop-mssa" : "loop",
|
||||
std::move(*Pipeline)}}}};
|
||||
} else if (isLoopPassName(FirstName, LoopPipelineParsingCallbacks,
|
||||
UseMemorySSA)) {
|
||||
Pipeline = {{"function", {{UseMemorySSA ? "loop-mssa" : "loop",
|
||||
|
@ -1739,6 +1798,10 @@ void PassBuilder::printPassNames(raw_ostream &OS) {
|
|||
|
||||
OS << "Function alias analyses:\n";
|
||||
#define FUNCTION_ALIAS_ANALYSIS(NAME, CREATE_PASS) printPassName(NAME, OS);
|
||||
#include "PassRegistry.def"
|
||||
|
||||
OS << "LoopNest passes:\n";
|
||||
#define LOOPNEST_PASS(NAME, CREATE_PASS) printPassName(NAME, OS);
|
||||
#include "PassRegistry.def"
|
||||
|
||||
OS << "Loop passes:\n";
|
||||
|
|
|
@ -452,6 +452,16 @@ FUNCTION_PASS_WITH_PARAMS("print<stack-lifetime>",
|
|||
"may;must")
|
||||
#undef FUNCTION_PASS_WITH_PARAMS
|
||||
|
||||
#ifndef LOOPNEST_PASS
|
||||
#define LOOPNEST_PASS(NAME, CREATE_PASS)
|
||||
#endif
|
||||
LOOPNEST_PASS("lnicm", LNICMPass())
|
||||
LOOPNEST_PASS("loop-flatten", LoopFlattenPass())
|
||||
LOOPNEST_PASS("loop-interchange", LoopInterchangePass())
|
||||
LOOPNEST_PASS("loop-unroll-and-jam", LoopUnrollAndJamPass())
|
||||
LOOPNEST_PASS("no-op-loopnest", NoOpLoopNestPass())
|
||||
#undef LOOPNEST_PASS
|
||||
|
||||
#ifndef LOOP_ANALYSIS
|
||||
#define LOOP_ANALYSIS(NAME, CREATE_PASS)
|
||||
#endif
|
||||
|
@ -469,11 +479,8 @@ LOOP_PASS("canon-freeze", CanonicalizeFreezeInLoopsPass())
|
|||
LOOP_PASS("dot-ddg", DDGDotPrinterPass())
|
||||
LOOP_PASS("invalidate<all>", InvalidateAllAnalysesPass())
|
||||
LOOP_PASS("licm", LICMPass())
|
||||
LOOP_PASS("lnicm", LNICMPass())
|
||||
LOOP_PASS("loop-flatten", LoopFlattenPass())
|
||||
LOOP_PASS("loop-idiom", LoopIdiomRecognizePass())
|
||||
LOOP_PASS("loop-instsimplify", LoopInstSimplifyPass())
|
||||
LOOP_PASS("loop-interchange", LoopInterchangePass())
|
||||
LOOP_PASS("loop-rotate", LoopRotatePass())
|
||||
LOOP_PASS("no-op-loop", NoOpLoopPass())
|
||||
LOOP_PASS("print", PrintLoopPass(dbgs()))
|
||||
|
@ -481,7 +488,6 @@ LOOP_PASS("loop-deletion", LoopDeletionPass())
|
|||
LOOP_PASS("loop-simplifycfg", LoopSimplifyCFGPass())
|
||||
LOOP_PASS("loop-reduce", LoopStrengthReducePass())
|
||||
LOOP_PASS("indvars", IndVarSimplifyPass())
|
||||
LOOP_PASS("loop-unroll-and-jam", LoopUnrollAndJamPass())
|
||||
LOOP_PASS("loop-unroll-full", LoopFullUnrollPass())
|
||||
LOOP_PASS("print-access-info", LoopAccessInfoPrinterPass(dbgs()))
|
||||
LOOP_PASS("print<ddg>", DDGAnalysisPrinterPass(dbgs()))
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
; RUN: opt -disable-output -debug-pass-manager \
|
||||
; RUN: -passes='no-op-loopnest' %s 2>&1 \
|
||||
; RUN: | FileCheck %s
|
||||
|
||||
; @f()
|
||||
; / \
|
||||
; loop.0 loop.1
|
||||
; / \ \
|
||||
; loop.0.0 loop.0.1 loop.1.0
|
||||
;
|
||||
; CHECK: Running pass: NoOpLoopNestPass on Loop at depth 1 containing: %loop.0<header><exiting>,%loop.0.0,%loop.0.1,%loop.0.1.preheader,%loop.0.loopexit<latch>,%loop.0.0.preheader
|
||||
; CHECK: Running pass: NoOpLoopNestPass on Loop at depth 1 containing: %loop.1<header>,%loop.1.bb1,%loop.1.bb2<exiting>,%loop.1.0,%loop.1.0.preheader,%loop.1.loopexit,%loop.1.backedge<latch>
|
||||
; CHECK-NOT: Running pass: NoOpLoopNestPass on Loop at depth 2
|
||||
|
||||
define void @f() {
|
||||
entry:
|
||||
br label %loop.0
|
||||
loop.0:
|
||||
br i1 undef, label %loop.0.0, label %loop.1
|
||||
loop.0.0:
|
||||
br i1 undef, label %loop.0.0, label %loop.0.1
|
||||
loop.0.1:
|
||||
br i1 undef, label %loop.0.1, label %loop.0
|
||||
loop.1:
|
||||
br i1 undef, label %loop.1, label %loop.1.bb1
|
||||
loop.1.bb1:
|
||||
br i1 undef, label %loop.1, label %loop.1.bb2
|
||||
loop.1.bb2:
|
||||
br i1 undef, label %end, label %loop.1.0
|
||||
loop.1.0:
|
||||
br i1 undef, label %loop.1.0, label %loop.1
|
||||
end:
|
||||
ret void
|
||||
}
|
|
@ -18,6 +18,8 @@
|
|||
; CHECK: no-op-function
|
||||
; CHECK: Function alias analyses:
|
||||
; CHECK: basic-aa
|
||||
; CHECK: LoopNest passes:
|
||||
; CHECK: no-op-loopnest
|
||||
; CHECK: Loop passes:
|
||||
; CHECK: no-op-loop
|
||||
; CHECK: Loop passes with params:
|
||||
|
|
Loading…
Reference in New Issue