xref: /freebsd-src/contrib/llvm-project/llvm/lib/CodeGen/MachinePassManager.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1e8d8bef9SDimitry Andric //===---------- MachinePassManager.cpp ------------------------------------===//
2e8d8bef9SDimitry Andric //
3e8d8bef9SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e8d8bef9SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e8d8bef9SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e8d8bef9SDimitry Andric //
7e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===//
8e8d8bef9SDimitry Andric //
9e8d8bef9SDimitry Andric // This file contains the pass management machinery for machine functions.
10e8d8bef9SDimitry Andric //
11e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===//
12e8d8bef9SDimitry Andric 
13e8d8bef9SDimitry Andric #include "llvm/CodeGen/MachinePassManager.h"
14e8d8bef9SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
15*0fca6ea1SDimitry Andric #include "llvm/CodeGen/MachineFunctionAnalysis.h"
16e8d8bef9SDimitry Andric #include "llvm/CodeGen/MachineModuleInfo.h"
17e8d8bef9SDimitry Andric #include "llvm/IR/PassManagerImpl.h"
18e8d8bef9SDimitry Andric 
19e8d8bef9SDimitry Andric using namespace llvm;
20e8d8bef9SDimitry Andric 
21*0fca6ea1SDimitry Andric AnalysisKey FunctionAnalysisManagerMachineFunctionProxy::Key;
22*0fca6ea1SDimitry Andric 
23e8d8bef9SDimitry Andric namespace llvm {
24e8d8bef9SDimitry Andric template class AnalysisManager<MachineFunction>;
25e8d8bef9SDimitry Andric template class PassManager<MachineFunction>;
26*0fca6ea1SDimitry Andric template class InnerAnalysisManagerProxy<MachineFunctionAnalysisManager,
27*0fca6ea1SDimitry Andric                                          Module>;
28*0fca6ea1SDimitry Andric template class InnerAnalysisManagerProxy<MachineFunctionAnalysisManager,
29*0fca6ea1SDimitry Andric                                          Function>;
30*0fca6ea1SDimitry Andric template class OuterAnalysisManagerProxy<ModuleAnalysisManager,
31*0fca6ea1SDimitry Andric                                          MachineFunction>;
32*0fca6ea1SDimitry Andric } // namespace llvm
33e8d8bef9SDimitry Andric 
34*0fca6ea1SDimitry Andric bool FunctionAnalysisManagerMachineFunctionProxy::Result::invalidate(
35*0fca6ea1SDimitry Andric     MachineFunction &IR, const PreservedAnalyses &PA,
36*0fca6ea1SDimitry Andric     MachineFunctionAnalysisManager::Invalidator &Inv) {
37*0fca6ea1SDimitry Andric   // MachineFunction passes should not invalidate Function analyses.
38*0fca6ea1SDimitry Andric   // TODO: verify that PA doesn't invalidate Function analyses.
39*0fca6ea1SDimitry Andric   return false;
40e8d8bef9SDimitry Andric }
41e8d8bef9SDimitry Andric 
42*0fca6ea1SDimitry Andric template <>
43*0fca6ea1SDimitry Andric bool MachineFunctionAnalysisManagerModuleProxy::Result::invalidate(
44*0fca6ea1SDimitry Andric     Module &M, const PreservedAnalyses &PA,
45*0fca6ea1SDimitry Andric     ModuleAnalysisManager::Invalidator &Inv) {
46*0fca6ea1SDimitry Andric   // If literally everything is preserved, we're done.
47*0fca6ea1SDimitry Andric   if (PA.areAllPreserved())
48*0fca6ea1SDimitry Andric     return false; // This is still a valid proxy.
49*0fca6ea1SDimitry Andric 
50*0fca6ea1SDimitry Andric   // If this proxy isn't marked as preserved, then even if the result remains
51*0fca6ea1SDimitry Andric   // valid, the key itself may no longer be valid, so we clear everything.
52*0fca6ea1SDimitry Andric   //
53*0fca6ea1SDimitry Andric   // Note that in order to preserve this proxy, a module pass must ensure that
54*0fca6ea1SDimitry Andric   // the MFAM has been completely updated to handle the deletion of functions.
55*0fca6ea1SDimitry Andric   // Specifically, any MFAM-cached results for those functions need to have been
56*0fca6ea1SDimitry Andric   // forcibly cleared. When preserved, this proxy will only invalidate results
57*0fca6ea1SDimitry Andric   // cached on functions *still in the module* at the end of the module pass.
58*0fca6ea1SDimitry Andric   auto PAC = PA.getChecker<MachineFunctionAnalysisManagerModuleProxy>();
59*0fca6ea1SDimitry Andric   if (!PAC.preserved() && !PAC.preservedSet<AllAnalysesOn<Module>>()) {
60*0fca6ea1SDimitry Andric     InnerAM->clear();
61*0fca6ea1SDimitry Andric     return true;
62e8d8bef9SDimitry Andric   }
63e8d8bef9SDimitry Andric 
64*0fca6ea1SDimitry Andric   // FIXME: be more precise, see
65*0fca6ea1SDimitry Andric   // FunctionAnalysisManagerModuleProxy::Result::invalidate.
66*0fca6ea1SDimitry Andric   if (!PA.allAnalysesInSetPreserved<AllAnalysesOn<MachineFunction>>()) {
67*0fca6ea1SDimitry Andric     InnerAM->clear();
68*0fca6ea1SDimitry Andric     return true;
69e8d8bef9SDimitry Andric   }
70e8d8bef9SDimitry Andric 
71*0fca6ea1SDimitry Andric   // Return false to indicate that this result is still a valid proxy.
72*0fca6ea1SDimitry Andric   return false;
73*0fca6ea1SDimitry Andric }
74e8d8bef9SDimitry Andric 
75*0fca6ea1SDimitry Andric template <>
76*0fca6ea1SDimitry Andric bool MachineFunctionAnalysisManagerFunctionProxy::Result::invalidate(
77*0fca6ea1SDimitry Andric     Function &F, const PreservedAnalyses &PA,
78*0fca6ea1SDimitry Andric     FunctionAnalysisManager::Invalidator &Inv) {
79*0fca6ea1SDimitry Andric   // If literally everything is preserved, we're done.
80*0fca6ea1SDimitry Andric   if (PA.areAllPreserved())
81*0fca6ea1SDimitry Andric     return false; // This is still a valid proxy.
82e8d8bef9SDimitry Andric 
83*0fca6ea1SDimitry Andric   // If this proxy isn't marked as preserved, then even if the result remains
84*0fca6ea1SDimitry Andric   // valid, the key itself may no longer be valid, so we clear everything.
85*0fca6ea1SDimitry Andric   //
86*0fca6ea1SDimitry Andric   // Note that in order to preserve this proxy, a module pass must ensure that
87*0fca6ea1SDimitry Andric   // the MFAM has been completely updated to handle the deletion of functions.
88*0fca6ea1SDimitry Andric   // Specifically, any MFAM-cached results for those functions need to have been
89*0fca6ea1SDimitry Andric   // forcibly cleared. When preserved, this proxy will only invalidate results
90*0fca6ea1SDimitry Andric   // cached on functions *still in the module* at the end of the module pass.
91*0fca6ea1SDimitry Andric   auto PAC = PA.getChecker<MachineFunctionAnalysisManagerFunctionProxy>();
92*0fca6ea1SDimitry Andric   if (!PAC.preserved() && !PAC.preservedSet<AllAnalysesOn<Function>>()) {
93*0fca6ea1SDimitry Andric     InnerAM->clear();
94*0fca6ea1SDimitry Andric     return true;
95*0fca6ea1SDimitry Andric   }
96e8d8bef9SDimitry Andric 
97*0fca6ea1SDimitry Andric   // FIXME: be more precise, see
98*0fca6ea1SDimitry Andric   // FunctionAnalysisManagerModuleProxy::Result::invalidate.
99*0fca6ea1SDimitry Andric   if (!PA.allAnalysesInSetPreserved<AllAnalysesOn<MachineFunction>>()) {
100*0fca6ea1SDimitry Andric     InnerAM->clear();
101*0fca6ea1SDimitry Andric     return true;
102*0fca6ea1SDimitry Andric   }
103*0fca6ea1SDimitry Andric 
104*0fca6ea1SDimitry Andric   // Return false to indicate that this result is still a valid proxy.
105*0fca6ea1SDimitry Andric   return false;
106*0fca6ea1SDimitry Andric }
107*0fca6ea1SDimitry Andric 
108*0fca6ea1SDimitry Andric PreservedAnalyses
109*0fca6ea1SDimitry Andric FunctionToMachineFunctionPassAdaptor::run(Function &F,
110*0fca6ea1SDimitry Andric                                           FunctionAnalysisManager &FAM) {
111*0fca6ea1SDimitry Andric   MachineFunctionAnalysisManager &MFAM =
112*0fca6ea1SDimitry Andric       FAM.getResult<MachineFunctionAnalysisManagerFunctionProxy>(F)
113*0fca6ea1SDimitry Andric           .getManager();
114*0fca6ea1SDimitry Andric   PassInstrumentation PI = FAM.getResult<PassInstrumentationAnalysis>(F);
115*0fca6ea1SDimitry Andric   PreservedAnalyses PA = PreservedAnalyses::all();
116e8d8bef9SDimitry Andric   // Do not codegen any 'available_externally' functions at all, they have
117e8d8bef9SDimitry Andric   // definitions outside the translation unit.
118*0fca6ea1SDimitry Andric   if (F.isDeclaration() || F.hasAvailableExternallyLinkage())
119*0fca6ea1SDimitry Andric     return PreservedAnalyses::all();
120e8d8bef9SDimitry Andric 
121*0fca6ea1SDimitry Andric   MachineFunction &MF = FAM.getResult<MachineFunctionAnalysis>(F).getMF();
122e8d8bef9SDimitry Andric 
123*0fca6ea1SDimitry Andric   if (!PI.runBeforePass<MachineFunction>(*Pass, MF))
124*0fca6ea1SDimitry Andric     return PreservedAnalyses::all();
125*0fca6ea1SDimitry Andric   PreservedAnalyses PassPA = Pass->run(MF, MFAM);
126e8d8bef9SDimitry Andric   MFAM.invalidate(MF, PassPA);
127*0fca6ea1SDimitry Andric   PI.runAfterPass(*Pass, MF, PassPA);
128*0fca6ea1SDimitry Andric   PA.intersect(std::move(PassPA));
129e8d8bef9SDimitry Andric 
130*0fca6ea1SDimitry Andric   return PA;
131e8d8bef9SDimitry Andric }
132e8d8bef9SDimitry Andric 
133*0fca6ea1SDimitry Andric void FunctionToMachineFunctionPassAdaptor::printPipeline(
134*0fca6ea1SDimitry Andric     raw_ostream &OS, function_ref<StringRef(StringRef)> MapClassName2PassName) {
135*0fca6ea1SDimitry Andric   OS << "machine-function(";
136*0fca6ea1SDimitry Andric   Pass->printPipeline(OS, MapClassName2PassName);
137*0fca6ea1SDimitry Andric   OS << ')';
138e8d8bef9SDimitry Andric }
139e8d8bef9SDimitry Andric 
140*0fca6ea1SDimitry Andric template <>
141*0fca6ea1SDimitry Andric PreservedAnalyses
142*0fca6ea1SDimitry Andric PassManager<MachineFunction>::run(MachineFunction &MF,
143*0fca6ea1SDimitry Andric                                   AnalysisManager<MachineFunction> &MFAM) {
144*0fca6ea1SDimitry Andric   PassInstrumentation PI = MFAM.getResult<PassInstrumentationAnalysis>(MF);
145*0fca6ea1SDimitry Andric   PreservedAnalyses PA = PreservedAnalyses::all();
146*0fca6ea1SDimitry Andric   for (auto &Pass : Passes) {
147*0fca6ea1SDimitry Andric     if (!PI.runBeforePass<MachineFunction>(*Pass, MF))
148*0fca6ea1SDimitry Andric       continue;
149*0fca6ea1SDimitry Andric 
150*0fca6ea1SDimitry Andric     PreservedAnalyses PassPA = Pass->run(MF, MFAM);
151*0fca6ea1SDimitry Andric     MFAM.invalidate(MF, PassPA);
152*0fca6ea1SDimitry Andric     PI.runAfterPass(*Pass, MF, PassPA);
153*0fca6ea1SDimitry Andric     PA.intersect(std::move(PassPA));
154*0fca6ea1SDimitry Andric   }
155*0fca6ea1SDimitry Andric   return PA;
156*0fca6ea1SDimitry Andric }
157*0fca6ea1SDimitry Andric 
158*0fca6ea1SDimitry Andric PreservedAnalyses llvm::getMachineFunctionPassPreservedAnalyses() {
159*0fca6ea1SDimitry Andric   PreservedAnalyses PA;
160*0fca6ea1SDimitry Andric   // Machine function passes are not allowed to modify the LLVM
161*0fca6ea1SDimitry Andric   // representation, therefore we should preserve all IR analyses.
162*0fca6ea1SDimitry Andric   PA.template preserveSet<AllAnalysesOn<Module>>();
163*0fca6ea1SDimitry Andric   PA.template preserveSet<AllAnalysesOn<Function>>();
164*0fca6ea1SDimitry Andric   return PA;
165*0fca6ea1SDimitry Andric }
166