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 |
17 | |
18 | #include "llvm/IR/PassManager.h" |
19 | #include "llvm/Transforms/Scalar/LoopPassManager.h" |
20 | |
21 | namespace 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. |
26 | template <typename MarkerTy> struct { |
27 | struct { |
28 | bool (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 (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. |
57 | template <typename MarkerTy> |
58 | class |
59 | : public PassInfoMixin<ExtraFunctionPassManager<MarkerTy>> { |
60 | FunctionPassManager ; |
61 | |
62 | public: |
63 | template <typename PassT> void (PassT &&Pass) { |
64 | InnerFPM.addPass(std::move(Pass)); |
65 | } |
66 | |
67 | PreservedAnalyses (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 () { 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. |
81 | template <typename MarkerTy> |
82 | class |
83 | : public PassInfoMixin<ExtraLoopPassManager<MarkerTy>> { |
84 | LoopPassManager ; |
85 | |
86 | public: |
87 | template <typename PassT> void (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 () { return true; } |
101 | }; |
102 | |
103 | } // namespace llvm |
104 | |
105 | #endif // LLVM_TRANSFORMS_UTILS_EXTRAPASSMANAGER_H |
106 | |