1 | //===- RegAllocPriorityAdvisor.cpp - live ranges priority advisor ---------===// |
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 | // |
9 | // Implementation of the default priority advisor and of the Analysis pass. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #include "llvm/CodeGen/RegAllocPriorityAdvisor.h" |
14 | #include "RegAllocGreedy.h" |
15 | #include "llvm/CodeGen/MachineFunction.h" |
16 | #include "llvm/CodeGen/VirtRegMap.h" |
17 | #include "llvm/IR/Module.h" |
18 | #include "llvm/InitializePasses.h" |
19 | #include "llvm/Pass.h" |
20 | |
21 | using namespace llvm; |
22 | |
23 | static cl::opt<RegAllocPriorityAdvisorProvider::AdvisorMode> Mode( |
24 | "regalloc-enable-priority-advisor" , cl::Hidden, |
25 | cl::init(Val: RegAllocPriorityAdvisorProvider::AdvisorMode::Default), |
26 | cl::desc("Enable regalloc advisor mode" ), |
27 | cl::values( |
28 | clEnumValN(RegAllocPriorityAdvisorProvider::AdvisorMode::Default, |
29 | "default" , "Default" ), |
30 | clEnumValN(RegAllocPriorityAdvisorProvider::AdvisorMode::Release, |
31 | "release" , "precompiled" ), |
32 | clEnumValN(RegAllocPriorityAdvisorProvider::AdvisorMode::Development, |
33 | "development" , "for training" ), |
34 | clEnumValN( |
35 | RegAllocPriorityAdvisorProvider::AdvisorMode::Dummy, "dummy" , |
36 | "prioritize low virtual register numbers for test and debug" ))); |
37 | |
38 | char RegAllocPriorityAdvisorAnalysisLegacy::ID = 0; |
39 | INITIALIZE_PASS(RegAllocPriorityAdvisorAnalysisLegacy, "regalloc-priority" , |
40 | "Regalloc priority policy" , false, true) |
41 | |
42 | namespace { |
43 | |
44 | class DefaultPriorityAdvisorProvider final |
45 | : public RegAllocPriorityAdvisorProvider { |
46 | public: |
47 | DefaultPriorityAdvisorProvider(bool NotAsRequested, LLVMContext &Ctx) |
48 | : RegAllocPriorityAdvisorProvider(AdvisorMode::Default) { |
49 | if (NotAsRequested) |
50 | Ctx.emitError(ErrorStr: "Requested regalloc priority advisor analysis " |
51 | "could be created. Using default" ); |
52 | } |
53 | |
54 | // support for isa<> and dyn_cast. |
55 | static bool classof(const RegAllocPriorityAdvisorProvider *R) { |
56 | return R->getAdvisorMode() == AdvisorMode::Default; |
57 | } |
58 | |
59 | std::unique_ptr<RegAllocPriorityAdvisor> |
60 | getAdvisor(const MachineFunction &MF, const RAGreedy &RA, |
61 | SlotIndexes &SI) override { |
62 | return std::make_unique<DefaultPriorityAdvisor>(args: MF, args: RA, args: &SI); |
63 | } |
64 | }; |
65 | |
66 | class DummyPriorityAdvisorProvider final |
67 | : public RegAllocPriorityAdvisorProvider { |
68 | public: |
69 | DummyPriorityAdvisorProvider() |
70 | : RegAllocPriorityAdvisorProvider(AdvisorMode::Dummy) {} |
71 | |
72 | static bool classof(const RegAllocPriorityAdvisorProvider *R) { |
73 | return R->getAdvisorMode() == AdvisorMode::Dummy; |
74 | } |
75 | |
76 | std::unique_ptr<RegAllocPriorityAdvisor> |
77 | getAdvisor(const MachineFunction &MF, const RAGreedy &RA, |
78 | SlotIndexes &SI) override { |
79 | return std::make_unique<DummyPriorityAdvisor>(args: MF, args: RA, args: &SI); |
80 | } |
81 | }; |
82 | |
83 | class DefaultPriorityAdvisorAnalysisLegacy final |
84 | : public RegAllocPriorityAdvisorAnalysisLegacy { |
85 | public: |
86 | DefaultPriorityAdvisorAnalysisLegacy(bool NotAsRequested) |
87 | : RegAllocPriorityAdvisorAnalysisLegacy(AdvisorMode::Default), |
88 | NotAsRequested(NotAsRequested) {} |
89 | |
90 | // support for isa<> and dyn_cast. |
91 | static bool classof(const RegAllocPriorityAdvisorAnalysisLegacy *R) { |
92 | return R->getAdvisorMode() == AdvisorMode::Default; |
93 | } |
94 | |
95 | private: |
96 | void getAnalysisUsage(AnalysisUsage &AU) const override { |
97 | AU.addRequired<SlotIndexesWrapperPass>(); |
98 | RegAllocPriorityAdvisorAnalysisLegacy::getAnalysisUsage(AU); |
99 | } |
100 | |
101 | bool doInitialization(Module &M) override { |
102 | Provider.reset( |
103 | p: new DefaultPriorityAdvisorProvider(NotAsRequested, M.getContext())); |
104 | return false; |
105 | } |
106 | |
107 | const bool NotAsRequested; |
108 | }; |
109 | |
110 | class DummyPriorityAdvisorAnalysis final |
111 | : public RegAllocPriorityAdvisorAnalysisLegacy { |
112 | public: |
113 | using RegAllocPriorityAdvisorAnalysisLegacy::AdvisorMode; |
114 | DummyPriorityAdvisorAnalysis() |
115 | : RegAllocPriorityAdvisorAnalysisLegacy(AdvisorMode::Dummy) {} |
116 | |
117 | // support for isa<> and dyn_cast. |
118 | static bool classof(const RegAllocPriorityAdvisorAnalysisLegacy *R) { |
119 | return R->getAdvisorMode() == AdvisorMode::Dummy; |
120 | } |
121 | |
122 | private: |
123 | void getAnalysisUsage(AnalysisUsage &AU) const override { |
124 | AU.addRequired<SlotIndexesWrapperPass>(); |
125 | RegAllocPriorityAdvisorAnalysisLegacy::getAnalysisUsage(AU); |
126 | } |
127 | |
128 | bool doInitialization(Module &M) override { |
129 | Provider.reset(p: new DummyPriorityAdvisorProvider()); |
130 | return false; |
131 | } |
132 | }; |
133 | |
134 | } // namespace |
135 | |
136 | void RegAllocPriorityAdvisorAnalysis::initializeProvider(LLVMContext &Ctx) { |
137 | if (Provider) |
138 | return; |
139 | switch (Mode) { |
140 | case RegAllocPriorityAdvisorProvider::AdvisorMode::Dummy: |
141 | Provider.reset(p: new DummyPriorityAdvisorProvider()); |
142 | return; |
143 | case RegAllocPriorityAdvisorProvider::AdvisorMode::Default: |
144 | Provider.reset( |
145 | p: new DefaultPriorityAdvisorProvider(/*NotAsRequested=*/false, Ctx)); |
146 | return; |
147 | case RegAllocPriorityAdvisorProvider::AdvisorMode::Development: |
148 | #if defined(LLVM_HAVE_TFLITE) |
149 | Provider.reset(createDevelopmentModePriorityAdvisorProvider(Ctx)); |
150 | #else |
151 | Provider.reset( |
152 | p: new DefaultPriorityAdvisorProvider(/*NotAsRequested=*/true, Ctx)); |
153 | #endif |
154 | return; |
155 | case RegAllocPriorityAdvisorProvider::AdvisorMode::Release: |
156 | Provider.reset(p: createReleaseModePriorityAdvisorProvider()); |
157 | return; |
158 | } |
159 | } |
160 | |
161 | AnalysisKey RegAllocPriorityAdvisorAnalysis::Key; |
162 | |
163 | RegAllocPriorityAdvisorAnalysis::Result |
164 | RegAllocPriorityAdvisorAnalysis::run(MachineFunction &MF, |
165 | MachineFunctionAnalysisManager &MFAM) { |
166 | // Lazily initialize the provider. |
167 | initializeProvider(Ctx&: MF.getFunction().getContext()); |
168 | // The requiring analysis will construct the advisor. |
169 | return Result{.Provider: Provider.get()}; |
170 | } |
171 | |
172 | template <> |
173 | Pass *llvm::callDefaultCtor<RegAllocPriorityAdvisorAnalysisLegacy>() { |
174 | Pass *Ret = nullptr; |
175 | switch (Mode) { |
176 | case RegAllocPriorityAdvisorProvider::AdvisorMode::Default: |
177 | Ret = new DefaultPriorityAdvisorAnalysisLegacy(/*NotAsRequested*/ false); |
178 | break; |
179 | case RegAllocPriorityAdvisorProvider::AdvisorMode::Development: |
180 | #if defined(LLVM_HAVE_TFLITE) |
181 | Ret = createDevelopmentModePriorityAdvisorAnalysis(); |
182 | #endif |
183 | break; |
184 | case RegAllocPriorityAdvisorProvider::AdvisorMode::Release: |
185 | Ret = createReleaseModePriorityAdvisorAnalysis(); |
186 | break; |
187 | case RegAllocPriorityAdvisorProvider::AdvisorMode::Dummy: |
188 | Ret = new DummyPriorityAdvisorAnalysis(); |
189 | break; |
190 | } |
191 | if (Ret) |
192 | return Ret; |
193 | return new DefaultPriorityAdvisorAnalysisLegacy(/*NotAsRequested*/ true); |
194 | } |
195 | |
196 | StringRef RegAllocPriorityAdvisorAnalysisLegacy::getPassName() const { |
197 | switch (getAdvisorMode()) { |
198 | case AdvisorMode::Default: |
199 | return "Default Regalloc Priority Advisor" ; |
200 | case AdvisorMode::Release: |
201 | return "Release mode Regalloc Priority Advisor" ; |
202 | case AdvisorMode::Development: |
203 | return "Development mode Regalloc Priority Advisor" ; |
204 | case AdvisorMode::Dummy: |
205 | return "Dummy Regalloc Priority Advisor" ; |
206 | } |
207 | llvm_unreachable("Unknown advisor kind" ); |
208 | } |
209 | |
210 | RegAllocPriorityAdvisor::RegAllocPriorityAdvisor(const MachineFunction &MF, |
211 | const RAGreedy &RA, |
212 | SlotIndexes *const Indexes) |
213 | : RA(RA), LIS(RA.getLiveIntervals()), VRM(RA.getVirtRegMap()), |
214 | MRI(&VRM->getRegInfo()), TRI(MF.getSubtarget().getRegisterInfo()), |
215 | RegClassInfo(RA.getRegClassInfo()), Indexes(Indexes), |
216 | RegClassPriorityTrumpsGlobalness( |
217 | RA.getRegClassPriorityTrumpsGlobalness()), |
218 | ReverseLocalAssignment(RA.getReverseLocalAssignment()) {} |
219 | |