
Problem: Right now, our "Running pass" is not accurate when passes are wrapped in adaptor because adaptor is never skipped and a pass could be skipped. The other problem is that "Running pass" for a adaptor is before any "Running pass" of passes/analyses it depends on. (for example, FunctionToLoopPassAdaptor). So the order of printing is not the actual order. Solution: Doing things like PassManager::Debuglogging is very intrusive because we need to specify Debuglogging whenever adaptor is created. (Actually, right now we're not specifying Debuglogging for some sub-PassManagers. Check PassBuilder) This patch move debug logging for pass as a PassInstrument callback. We could be sure that all running passes are logged and in the correct order. This could also be used to implement hierarchy pass logging in legacy PM. We could also move logging of pass manager to this if we want. The test fixes looks messy. It includes changes: - Remove PassInstrumentationAnalysis - Remove PassAdaptor - If a PassAdaptor is for a real pass, the pass is added - Pass reorder (to the correct order), related to PassAdaptor - Add missing passes (due to Debuglogging not passed down) Reviewed By: asbirlea, aeubanks Differential Revision: https://reviews.llvm.org/D84774
108 lines
3.9 KiB
C++
108 lines
3.9 KiB
C++
//===- LoopPassManager.cpp - Loop pass management -------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/Support/TimeProfiler.h"
|
|
#include "llvm/Transforms/Scalar/LoopPassManager.h"
|
|
#include "llvm/Analysis/LoopInfo.h"
|
|
|
|
using namespace llvm;
|
|
|
|
// Explicit template instantiations and specialization defininitions for core
|
|
// template typedefs.
|
|
namespace llvm {
|
|
template class PassManager<Loop, LoopAnalysisManager,
|
|
LoopStandardAnalysisResults &, LPMUpdater &>;
|
|
|
|
/// Explicitly specialize the pass manager's run method to handle loop nest
|
|
/// structure updates.
|
|
template <>
|
|
PreservedAnalyses
|
|
PassManager<Loop, LoopAnalysisManager, LoopStandardAnalysisResults &,
|
|
LPMUpdater &>::run(Loop &L, LoopAnalysisManager &AM,
|
|
LoopStandardAnalysisResults &AR, LPMUpdater &U) {
|
|
PreservedAnalyses PA = PreservedAnalyses::all();
|
|
|
|
if (DebugLogging)
|
|
dbgs() << "Starting Loop pass manager run.\n";
|
|
|
|
// Request PassInstrumentation from analysis manager, will use it to run
|
|
// instrumenting callbacks for the passes later.
|
|
PassInstrumentation PI = AM.getResult<PassInstrumentationAnalysis>(L, AR);
|
|
for (auto &Pass : Passes) {
|
|
// Check the PassInstrumentation's BeforePass callbacks before running the
|
|
// pass, skip its execution completely if asked to (callback returns false).
|
|
if (!PI.runBeforePass<Loop>(*Pass, L))
|
|
continue;
|
|
|
|
PreservedAnalyses PassPA;
|
|
{
|
|
TimeTraceScope TimeScope(Pass->name(), L.getName());
|
|
PassPA = Pass->run(L, AM, AR, U);
|
|
}
|
|
|
|
// do not pass deleted Loop into the instrumentation
|
|
if (U.skipCurrentLoop())
|
|
PI.runAfterPassInvalidated<Loop>(*Pass);
|
|
else
|
|
PI.runAfterPass<Loop>(*Pass, L);
|
|
|
|
// If the loop was deleted, abort the run and return to the outer walk.
|
|
if (U.skipCurrentLoop()) {
|
|
PA.intersect(std::move(PassPA));
|
|
break;
|
|
}
|
|
|
|
#ifndef NDEBUG
|
|
// Verify the loop structure and LCSSA form before visiting the loop.
|
|
L.verifyLoop();
|
|
assert(L.isRecursivelyLCSSAForm(AR.DT, AR.LI) &&
|
|
"Loops must remain in LCSSA form!");
|
|
#endif
|
|
|
|
// Update the analysis manager as each pass runs and potentially
|
|
// invalidates analyses.
|
|
AM.invalidate(L, PassPA);
|
|
|
|
// Finally, we intersect the final preserved analyses to compute the
|
|
// aggregate preserved set for this pass manager.
|
|
PA.intersect(std::move(PassPA));
|
|
|
|
// FIXME: Historically, the pass managers all called the LLVM context's
|
|
// yield function here. We don't have a generic way to acquire the
|
|
// context and it isn't yet clear what the right pattern is for yielding
|
|
// in the new pass manager so it is currently omitted.
|
|
// ...getContext().yield();
|
|
}
|
|
|
|
// Invalidation for the current loop should be handled above, and other loop
|
|
// analysis results shouldn't be impacted by runs over this loop. Therefore,
|
|
// the remaining analysis results in the AnalysisManager are preserved. We
|
|
// mark this with a set so that we don't need to inspect each one
|
|
// individually.
|
|
// FIXME: This isn't correct! This loop and all nested loops' analyses should
|
|
// be preserved, but unrolling should invalidate the parent loop's analyses.
|
|
PA.preserveSet<AllAnalysesOn<Loop>>();
|
|
|
|
if (DebugLogging)
|
|
dbgs() << "Finished Loop pass manager run.\n";
|
|
|
|
return PA;
|
|
}
|
|
}
|
|
|
|
PrintLoopPass::PrintLoopPass() : OS(dbgs()) {}
|
|
PrintLoopPass::PrintLoopPass(raw_ostream &OS, const std::string &Banner)
|
|
: OS(OS), Banner(Banner) {}
|
|
|
|
PreservedAnalyses PrintLoopPass::run(Loop &L, LoopAnalysisManager &,
|
|
LoopStandardAnalysisResults &,
|
|
LPMUpdater &) {
|
|
printLoop(L, OS, Banner);
|
|
return PreservedAnalyses::all();
|
|
}
|