1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-21 03:53:04 +02:00
llvm-mirror/include/llvm/Analysis/LoopPassManager.h
Justin Bogner 7c792839af PM: Check that loop passes preserve a basic set of analyses
A loop pass that didn't preserve this entire set of passes wouldn't
play well with other loop passes, since these are generally a basic
requirement to do any interesting transformations to a loop.

Adds a helper to get the set of analyses a loop pass should preserve,
and checks that any loop pass we run satisfies the requirement.

llvm-svn: 268444
2016-05-03 21:35:08 +00:00

143 lines
5.6 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)) {}
// We have to explicitly define all the special member functions because MSVC
// refuses to generate them.
FunctionToLoopPassAdaptor(const FunctionToLoopPassAdaptor &Arg)
: Pass(Arg.Pass) {}
FunctionToLoopPassAdaptor(FunctionToLoopPassAdaptor &&Arg)
: Pass(std::move(Arg.Pass)) {}
friend void swap(FunctionToLoopPassAdaptor &LHS,
FunctionToLoopPassAdaptor &RHS) {
using std::swap;
swap(LHS.Pass, RHS.Pass);
}
FunctionToLoopPassAdaptor &operator=(FunctionToLoopPassAdaptor RHS) {
swap(*this, RHS);
return *this;
}
/// \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. Also, update the
// preserved analyses to reflect that once invalidated these can again
// be preserved.
PassPA = LAM.invalidate(*L, std::move(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. 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<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