mirror of
https://github.com/RPCSX/llvm.git
synced 2026-01-31 01:05:23 +01:00
This never made a lot of sense. They've been invalidated for one IR unit but they aren't really preserved in any normal sense. It seemed like it would be an elegant way of communicating to outer IR units that pass managers and adaptors had already handled invalidation, but we've since ended up adding sets that model this more clearly: we're now using the 'AllAnalysesOn<IRUnitT>' set to handle cases where the trick of "preserving" invalidated analyses didn't work. This patch moves to rely on that technique exclusively and removes the cumbersome API aspect of updating the preserved set when doing invalidation. This in turn will simplify a *number* of upcoming patches. This has a side benefit of exposing a number of places where we were failing to mark the 'AllAnalysesOn<IRUnitT>' set as preserved. This patch fixes those, and with those fixes shouldn't change any observable behavior. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@288023 91177308-0d34-0410-b5e6-96231b3b80d8
128 lines
5.0 KiB
C++
128 lines
5.0 KiB
C++
//===- LoopPassManager.h - Loop pass management -----------------*- C++ -*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
/// \file
|
|
///
|
|
/// This header provides classes for managing passes over loops in LLVM IR.
|
|
///
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef LLVM_ANALYSIS_LOOPPASSMANAGER_H
|
|
#define LLVM_ANALYSIS_LOOPPASSMANAGER_H
|
|
|
|
#include "llvm/ADT/STLExtras.h"
|
|
#include "llvm/Analysis/LoopInfo.h"
|
|
#include "llvm/IR/PassManager.h"
|
|
|
|
namespace llvm {
|
|
|
|
extern template class PassManager<Loop>;
|
|
/// \brief The loop pass manager.
|
|
///
|
|
/// See the documentation for the PassManager template for details. It runs a
|
|
/// sequency of loop passes over each loop that the manager is run over. This
|
|
/// typedef serves as a convenient way to refer to this construct.
|
|
typedef PassManager<Loop> LoopPassManager;
|
|
|
|
extern template class AnalysisManager<Loop>;
|
|
/// \brief The loop analysis manager.
|
|
///
|
|
/// See the documentation for the AnalysisManager template for detail
|
|
/// documentation. This typedef serves as a convenient way to refer to this
|
|
/// construct in the adaptors and proxies used to integrate this into the larger
|
|
/// pass manager infrastructure.
|
|
typedef AnalysisManager<Loop> LoopAnalysisManager;
|
|
|
|
extern template class InnerAnalysisManagerProxy<LoopAnalysisManager, Function>;
|
|
/// A proxy from a \c LoopAnalysisManager to a \c Function.
|
|
typedef InnerAnalysisManagerProxy<LoopAnalysisManager, Function>
|
|
LoopAnalysisManagerFunctionProxy;
|
|
|
|
extern template class OuterAnalysisManagerProxy<FunctionAnalysisManager, Loop>;
|
|
/// A proxy from a \c FunctionAnalysisManager to a \c Loop.
|
|
typedef OuterAnalysisManagerProxy<FunctionAnalysisManager, Loop>
|
|
FunctionAnalysisManagerLoopProxy;
|
|
|
|
/// Returns the minimum set of Analyses that all loop passes must preserve.
|
|
PreservedAnalyses getLoopPassPreservedAnalyses();
|
|
|
|
/// \brief Adaptor that maps from a function to its loops.
|
|
///
|
|
/// Designed to allow composition of a LoopPass(Manager) and a
|
|
/// FunctionPassManager. Note that if this pass is constructed with a \c
|
|
/// FunctionAnalysisManager it will run the \c LoopAnalysisManagerFunctionProxy
|
|
/// analysis prior to running the loop passes over the function to enable a \c
|
|
/// LoopAnalysisManager to be used within this run safely.
|
|
template <typename LoopPassT>
|
|
class FunctionToLoopPassAdaptor
|
|
: public PassInfoMixin<FunctionToLoopPassAdaptor<LoopPassT>> {
|
|
public:
|
|
explicit FunctionToLoopPassAdaptor(LoopPassT Pass)
|
|
: Pass(std::move(Pass)) {}
|
|
|
|
/// \brief Runs the loop passes across every loop in the function.
|
|
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) {
|
|
// Setup the loop analysis manager from its proxy.
|
|
LoopAnalysisManager &LAM =
|
|
AM.getResult<LoopAnalysisManagerFunctionProxy>(F).getManager();
|
|
// Get the loop structure for this function
|
|
LoopInfo &LI = AM.getResult<LoopAnalysis>(F);
|
|
|
|
PreservedAnalyses PA = PreservedAnalyses::all();
|
|
|
|
// We want to visit the loops in reverse post-order. We'll build the stack
|
|
// of loops to visit in Loops by first walking the loops in pre-order.
|
|
SmallVector<Loop *, 2> Loops;
|
|
SmallVector<Loop *, 2> WorkList(LI.begin(), LI.end());
|
|
while (!WorkList.empty()) {
|
|
Loop *L = WorkList.pop_back_val();
|
|
WorkList.insert(WorkList.end(), L->begin(), L->end());
|
|
Loops.push_back(L);
|
|
}
|
|
|
|
// Now pop each element off of the stack to visit the loops in reverse
|
|
// post-order.
|
|
for (auto *L : reverse(Loops)) {
|
|
PreservedAnalyses PassPA = Pass.run(*L, LAM);
|
|
assert(PassPA.preserved(getLoopPassPreservedAnalyses()) &&
|
|
"Loop passes must preserve all relevant analyses");
|
|
|
|
// We know that the loop pass couldn't have invalidated any other loop's
|
|
// analyses (that's the contract of a loop pass), so directly handle the
|
|
// loop analysis manager's invalidation here.
|
|
LAM.invalidate(*L, PassPA);
|
|
|
|
// Then intersect the preserved set so that invalidation of module
|
|
// analyses will eventually occur when the module pass completes.
|
|
PA.intersect(std::move(PassPA));
|
|
}
|
|
|
|
// By definition we preserve the proxy. We also preserve all analyses on
|
|
// Loops. This precludes *any* invalidation of loop analyses by the proxy,
|
|
// but that's OK because we've taken care to invalidate analyses in the
|
|
// loop analysis manager incrementally above.
|
|
PA.preserve<AllAnalysesOn<Loop>>();
|
|
PA.preserve<LoopAnalysisManagerFunctionProxy>();
|
|
return PA;
|
|
}
|
|
|
|
private:
|
|
LoopPassT Pass;
|
|
};
|
|
|
|
/// \brief A function to deduce a loop pass type and wrap it in the templated
|
|
/// adaptor.
|
|
template <typename LoopPassT>
|
|
FunctionToLoopPassAdaptor<LoopPassT>
|
|
createFunctionToLoopPassAdaptor(LoopPassT Pass) {
|
|
return FunctionToLoopPassAdaptor<LoopPassT>(std::move(Pass));
|
|
}
|
|
}
|
|
|
|
#endif // LLVM_ANALYSIS_LOOPPASSMANAGER_H
|