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 not 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#endif
151 break;
152 case RegAllocPriorityAdvisorProvider::AdvisorMode::Release:
153 Provider.reset(p: createReleaseModePriorityAdvisorProvider());
154 break;
155 }
156 // The requested advisor may not be supported by this build.
157 if (!Provider)
158 Provider.reset(
159 p: new DefaultPriorityAdvisorProvider(/*NotAsRequested=*/true, Ctx));
160}
161
162AnalysisKey RegAllocPriorityAdvisorAnalysis::Key;
163
164RegAllocPriorityAdvisorAnalysis::Result
165RegAllocPriorityAdvisorAnalysis::run(MachineFunction &MF,
166 MachineFunctionAnalysisManager &MFAM) {
167 // Lazily initialize the provider.
168 initializeProvider(Ctx&: MF.getFunction().getContext());
169 // The requiring analysis will construct the advisor.
170 return Result{.Provider: Provider.get()};
171}
172
173template <>
174Pass *llvm::callDefaultCtor<RegAllocPriorityAdvisorAnalysisLegacy>() {
175 Pass *Ret = nullptr;
176 switch (Mode) {
177 case RegAllocPriorityAdvisorProvider::AdvisorMode::Default:
178 Ret = new DefaultPriorityAdvisorAnalysisLegacy(/*NotAsRequested*/ false);
179 break;
180 case RegAllocPriorityAdvisorProvider::AdvisorMode::Development:
181#if defined(LLVM_HAVE_TFLITE)
182 Ret = createDevelopmentModePriorityAdvisorAnalysis();
183#endif
184 break;
185 case RegAllocPriorityAdvisorProvider::AdvisorMode::Release:
186 Ret = createReleaseModePriorityAdvisorAnalysis();
187 break;
188 case RegAllocPriorityAdvisorProvider::AdvisorMode::Dummy:
189 Ret = new DummyPriorityAdvisorAnalysis();
190 break;
191 }
192 if (Ret)
193 return Ret;
194 return new DefaultPriorityAdvisorAnalysisLegacy(/*NotAsRequested*/ true);
195}
196
197StringRef RegAllocPriorityAdvisorAnalysisLegacy::getPassName() const {
198 switch (getAdvisorMode()) {
199 case AdvisorMode::Default:
200 return "Default Regalloc Priority Advisor";
201 case AdvisorMode::Release:
202 return "Release mode Regalloc Priority Advisor";
203 case AdvisorMode::Development:
204 return "Development mode Regalloc Priority Advisor";
205 case AdvisorMode::Dummy:
206 return "Dummy Regalloc Priority Advisor";
207 }
208 llvm_unreachable("Unknown advisor kind");
209}
210
211RegAllocPriorityAdvisor::RegAllocPriorityAdvisor(const MachineFunction &MF,
212 const RAGreedy &RA,
213 SlotIndexes *const Indexes)
214 : RA(RA), LIS(RA.getLiveIntervals()), VRM(RA.getVirtRegMap()),
215 MRI(&VRM->getRegInfo()), TRI(MF.getSubtarget().getRegisterInfo()),
216 RegClassInfo(RA.getRegClassInfo()), Indexes(Indexes),
217 RegClassPriorityTrumpsGlobalness(
218 RA.getRegClassPriorityTrumpsGlobalness()),
219 ReverseLocalAssignment(RA.getReverseLocalAssignment()) {}
220