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
21using namespace llvm;
22
23static 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
38char RegAllocPriorityAdvisorAnalysisLegacy::ID = 0;
39INITIALIZE_PASS(RegAllocPriorityAdvisorAnalysisLegacy, "regalloc-priority",
40 "Regalloc priority policy", false, true)
41
42namespace {
43
44class DefaultPriorityAdvisorProvider final
45 : public RegAllocPriorityAdvisorProvider {
46public:
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
66class DummyPriorityAdvisorProvider final
67 : public RegAllocPriorityAdvisorProvider {
68public:
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
83class DefaultPriorityAdvisorAnalysisLegacy final
84 : public RegAllocPriorityAdvisorAnalysisLegacy {
85public:
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
95private:
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
110class DummyPriorityAdvisorAnalysis final
111 : public RegAllocPriorityAdvisorAnalysisLegacy {
112public:
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
122private:
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
136void 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
161AnalysisKey RegAllocPriorityAdvisorAnalysis::Key;
162
163RegAllocPriorityAdvisorAnalysis::Result
164RegAllocPriorityAdvisorAnalysis::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
172template <>
173Pass *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
196StringRef 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
210RegAllocPriorityAdvisor::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