1//===- ExtraFunctionPassManager.h - Run Optimizations on Demand -*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8/// \file
9///
10/// This file provides a pass manager that only runs its passes if the
11/// provided marker analysis has been preserved, together with a class to
12/// define such a marker analysis.
13//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_TRANSFORMS_UTILS_EXTRAPASSMANAGER_H
16#define LLVM_TRANSFORMS_UTILS_EXTRAPASSMANAGER_H
17
18#include "llvm/IR/PassManager.h"
19#include "llvm/Transforms/Scalar/LoopPassManager.h"
20
21namespace llvm {
22
23/// A marker analysis to determine if extra passes should be run on demand.
24/// Passes requesting extra transformations to run need to request and preserve
25/// this analysis.
26template <typename MarkerTy> struct ShouldRunExtraPasses {
27 struct Result {
28 bool invalidate(Function &F, const PreservedAnalyses &PA,
29 FunctionAnalysisManager::Invalidator &) {
30 // Check whether the analysis has been explicitly invalidated. Otherwise,
31 // it remains preserved.
32 auto PAC = PA.getChecker<MarkerTy>();
33 return !PAC.preservedWhenStateless();
34 }
35
36 bool invalidate(Loop &L, const PreservedAnalyses &PA,
37 LoopAnalysisManager::Invalidator &) {
38 // Check whether the analysis has been explicitly invalidated. Otherwise,
39 // it remains preserved.
40 auto PAC = PA.getChecker<MarkerTy>();
41 return !PAC.preservedWhenStateless();
42 }
43 };
44
45 Result run(Function &F, FunctionAnalysisManager &FAM) { return Result(); }
46
47 Result run(Loop &L, LoopAnalysisManager &AM,
48 LoopStandardAnalysisResults &AR) {
49 return Result();
50 }
51};
52
53/// A pass manager to run a set of extra function passes if the
54/// ShouldRunExtraPasses marker analysis is present. This allows passes to
55/// request additional transformations on demand. An example is extra
56/// simplifications after loop-vectorization, if runtime checks have been added.
57template <typename MarkerTy>
58class ExtraFunctionPassManager
59 : public PassInfoMixin<ExtraFunctionPassManager<MarkerTy>> {
60 FunctionPassManager InnerFPM;
61
62public:
63 template <typename PassT> void addPass(PassT &&Pass) {
64 InnerFPM.addPass(std::move(Pass));
65 }
66
67 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) {
68 auto PA = PreservedAnalyses::all();
69 if (AM.getCachedResult<MarkerTy>(F))
70 PA.intersect(Arg: InnerFPM.run(IR&: F, AM));
71 PA.abandon<MarkerTy>();
72 return PA;
73 }
74
75 static bool isRequired() { return true; }
76};
77
78/// A pass manager to run a set of extra loop passes if the MarkerTy analysis is
79/// present. This allows passes to request additional transformations on demand.
80/// An example is doing additional runs of SimpleLoopUnswitch.
81template <typename MarkerTy>
82class ExtraLoopPassManager
83 : public PassInfoMixin<ExtraLoopPassManager<MarkerTy>> {
84 LoopPassManager InnerLPM;
85
86public:
87 template <typename PassT> void addPass(PassT &&Pass) {
88 InnerLPM.addPass(std::move(Pass));
89 }
90
91 PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM,
92 LoopStandardAnalysisResults &AR, LPMUpdater &U) {
93 auto PA = PreservedAnalyses::all();
94 if (AM.getCachedResult<MarkerTy>(L))
95 PA.intersect(Arg: InnerLPM.run(L, AM, AR, U));
96 PA.abandon<MarkerTy>();
97 return PA;
98 }
99
100 static bool isRequired() { return true; }
101};
102
103} // namespace llvm
104
105#endif // LLVM_TRANSFORMS_UTILS_EXTRAPASSMANAGER_H
106