blob: 1478b0fd1b13a8c943d4135b56b5c4067ff2b7d3 [file] [log] [blame]
Jim Stichnothd97c7df2014-06-04 11:57:08 -07001//===- subzero/src/IceRegAlloc.cpp - Linear-scan implementation -----------===//
2//
3// The Subzero Code Generator
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the LinearScan class, which performs the
11// linear-scan register allocation after liveness analysis has been
12// performed.
13//
14//===----------------------------------------------------------------------===//
15
John Porto67f8de92015-06-25 10:14:17 -070016#include "IceRegAlloc.h"
17
Jim Stichnothd97c7df2014-06-04 11:57:08 -070018#include "IceCfg.h"
Jim Stichnoth87ff3a12014-11-14 10:27:29 -080019#include "IceCfgNode.h"
Jim Stichnothd97c7df2014-06-04 11:57:08 -070020#include "IceInst.h"
21#include "IceOperand.h"
Jim Stichnothd97c7df2014-06-04 11:57:08 -070022#include "IceTargetLowering.h"
23
24namespace Ice {
25
Jim Stichnothad403532014-09-25 12:44:17 -070026namespace {
27
Jim Stichnothe34d79d2015-01-12 09:00:50 -080028// TODO(stichnot): Statically choose the size based on the target
29// being compiled.
John Porto67f8de92015-06-25 10:14:17 -070030constexpr size_t REGS_SIZE = 32;
Jim Stichnothe34d79d2015-01-12 09:00:50 -080031
Jim Stichnothad403532014-09-25 12:44:17 -070032// Returns true if Var has any definitions within Item's live range.
Jim Stichnoth037fa1d2014-10-07 11:09:33 -070033// TODO(stichnot): Consider trimming the Definitions list similar to
34// how the live ranges are trimmed, since all the overlapsDefs() tests
35// are whether some variable's definitions overlap Cur, and trimming
36// is with respect Cur.start. Initial tests show no measurable
37// performance difference, so we'll keep the code simple for now.
Jim Stichnoth5ce0abb2014-10-15 10:16:54 -070038bool overlapsDefs(const Cfg *Func, const Variable *Item, const Variable *Var) {
Jim Stichnoth037fa1d2014-10-07 11:09:33 -070039 const bool UseTrimmed = true;
40 VariablesMetadata *VMetadata = Func->getVMetadata();
Jim Stichnoth877b04e2014-10-15 15:13:06 -070041 if (const Inst *FirstDef = VMetadata->getFirstDefinition(Var))
42 if (Item->getLiveRange().overlapsInst(FirstDef->getNumber(), UseTrimmed))
43 return true;
44 const InstDefList &Defs = VMetadata->getLatterDefinitions(Var);
Jim Stichnothad403532014-09-25 12:44:17 -070045 for (size_t i = 0; i < Defs.size(); ++i) {
Jim Stichnoth5ce0abb2014-10-15 10:16:54 -070046 if (Item->getLiveRange().overlapsInst(Defs[i]->getNumber(), UseTrimmed))
Jim Stichnothad403532014-09-25 12:44:17 -070047 return true;
48 }
49 return false;
50}
51
52void dumpDisableOverlap(const Cfg *Func, const Variable *Var,
53 const char *Reason) {
Jim Stichnoth20b71f52015-06-24 15:52:24 -070054 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -080055 return;
Jim Stichnothfa4efea2015-01-27 05:06:03 -080056 if (Func->isVerbose(IceV_LinearScan)) {
Jim Stichnoth037fa1d2014-10-07 11:09:33 -070057 VariablesMetadata *VMetadata = Func->getVMetadata();
Jim Stichnothad403532014-09-25 12:44:17 -070058 Ostream &Str = Func->getContext()->getStrDump();
59 Str << "Disabling Overlap due to " << Reason << " " << *Var
60 << " LIVE=" << Var->getLiveRange() << " Defs=";
Jim Stichnoth877b04e2014-10-15 15:13:06 -070061 if (const Inst *FirstDef = VMetadata->getFirstDefinition(Var))
62 Str << FirstDef->getNumber();
63 const InstDefList &Defs = VMetadata->getLatterDefinitions(Var);
Jim Stichnothad403532014-09-25 12:44:17 -070064 for (size_t i = 0; i < Defs.size(); ++i) {
Jim Stichnoth877b04e2014-10-15 15:13:06 -070065 Str << "," << Defs[i]->getNumber();
Jim Stichnothad403532014-09-25 12:44:17 -070066 }
67 Str << "\n";
68 }
69}
70
Jim Stichnoth5ce0abb2014-10-15 10:16:54 -070071void dumpLiveRange(const Variable *Var, const Cfg *Func) {
Jim Stichnoth20b71f52015-06-24 15:52:24 -070072 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -080073 return;
Jim Stichnoth5ce0abb2014-10-15 10:16:54 -070074 Ostream &Str = Func->getContext()->getStrDump();
75 const static size_t BufLen = 30;
76 char buf[BufLen];
77 snprintf(buf, BufLen, "%2d", Var->getRegNumTmp());
78 Str << "R=" << buf << " V=";
79 Var->dump(Func);
80 Str << " Range=" << Var->getLiveRange();
Jim Stichnothe22f8232014-10-13 16:20:59 -070081}
82
Jim Stichnothad403532014-09-25 12:44:17 -070083} // end of anonymous namespace
84
Jim Stichnoth70d0a052014-11-14 15:53:46 -080085// Prepare for full register allocation of all variables. We depend
86// on liveness analysis to have calculated live ranges.
87void LinearScan::initForGlobal() {
Jim Stichnoth87ff3a12014-11-14 10:27:29 -080088 TimerMarker T(TimerStack::TT_initUnhandled, Func);
Jim Stichnoth70d0a052014-11-14 15:53:46 -080089 FindPreference = true;
90 FindOverlap = true;
Jim Stichnoth87ff3a12014-11-14 10:27:29 -080091 const VarList &Vars = Func->getVariables();
92 Unhandled.reserve(Vars.size());
Jim Stichnoth4ead35a2014-12-03 20:30:34 -080093 UnhandledPrecolored.reserve(Vars.size());
Jim Stichnoth70d0a052014-11-14 15:53:46 -080094 // Gather the live ranges of all variables and add them to the
95 // Unhandled set.
Jim Stichnoth87ff3a12014-11-14 10:27:29 -080096 for (Variable *Var : Vars) {
97 // Explicitly don't consider zero-weight variables, which are
98 // meant to be spill slots.
Jim Stichnothc6ead202015-02-24 09:30:30 -080099 if (Var->getWeight().isZero())
Jim Stichnoth87ff3a12014-11-14 10:27:29 -0800100 continue;
101 // Don't bother if the variable has a null live range, which means
102 // it was never referenced.
103 if (Var->getLiveRange().isEmpty())
104 continue;
105 Var->untrimLiveRange();
106 Unhandled.push_back(Var);
107 if (Var->hasReg()) {
108 Var->setRegNumTmp(Var->getRegNum());
109 Var->setLiveRangeInfiniteWeight();
110 UnhandledPrecolored.push_back(Var);
111 }
112 }
Jim Stichnoth70d0a052014-11-14 15:53:46 -0800113
114 // Build the (ordered) list of FakeKill instruction numbers.
115 Kills.clear();
116 for (CfgNode *Node : Func->getNodes()) {
Jim Stichnoth29841e82014-12-23 12:26:24 -0800117 for (Inst &I : Node->getInsts()) {
118 if (auto Kill = llvm::dyn_cast<InstFakeKill>(&I)) {
Jim Stichnoth70d0a052014-11-14 15:53:46 -0800119 if (!Kill->isDeleted() && !Kill->getLinked()->isDeleted())
Jim Stichnoth29841e82014-12-23 12:26:24 -0800120 Kills.push_back(I.getNumber());
Jim Stichnoth70d0a052014-11-14 15:53:46 -0800121 }
122 }
123 }
124}
125
126// Prepare for very simple register allocation of only infinite-weight
127// Variables while respecting pre-colored Variables. Some properties
128// we take advantage of:
129//
130// * Live ranges of interest consist of a single segment.
131//
132// * Live ranges of interest never span a call instruction.
133//
134// * Phi instructions are not considered because either phis have
135// already been lowered, or they don't contain any pre-colored or
136// infinite-weight Variables.
137//
138// * We don't need to renumber instructions before computing live
139// ranges because all the high-level ICE instructions are deleted
140// prior to lowering, and the low-level instructions are added in
141// monotonically increasing order.
142//
143// * There are no opportunities for register preference or allowing
144// overlap.
145//
146// Some properties we aren't (yet) taking advantage of:
147//
Jim Stichnothe6d24782014-12-19 05:42:24 -0800148// * Because live ranges are a single segment, the Inactive set will
Jim Stichnoth70d0a052014-11-14 15:53:46 -0800149// always be empty, and the live range trimming operation is
150// unnecessary.
151//
152// * Calculating overlap of single-segment live ranges could be
153// optimized a bit.
154void LinearScan::initForInfOnly() {
155 TimerMarker T(TimerStack::TT_initUnhandled, Func);
156 FindPreference = false;
157 FindOverlap = false;
158 SizeT NumVars = 0;
159 const VarList &Vars = Func->getVariables();
160
161 // Iterate across all instructions and record the begin and end of
162 // the live range for each variable that is pre-colored or infinite
163 // weight.
164 std::vector<InstNumberT> LRBegin(Vars.size(), Inst::NumberSentinel);
165 std::vector<InstNumberT> LREnd(Vars.size(), Inst::NumberSentinel);
166 for (CfgNode *Node : Func->getNodes()) {
Jim Stichnoth29841e82014-12-23 12:26:24 -0800167 for (Inst &Inst : Node->getInsts()) {
168 if (Inst.isDeleted())
Jim Stichnoth70d0a052014-11-14 15:53:46 -0800169 continue;
Jim Stichnoth29841e82014-12-23 12:26:24 -0800170 if (const Variable *Var = Inst.getDest()) {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800171 if (Var->hasReg() || Var->getWeight().isInf()) {
Jim Stichnoth70d0a052014-11-14 15:53:46 -0800172 if (LRBegin[Var->getIndex()] == Inst::NumberSentinel) {
Jim Stichnoth29841e82014-12-23 12:26:24 -0800173 LRBegin[Var->getIndex()] = Inst.getNumber();
Jim Stichnoth70d0a052014-11-14 15:53:46 -0800174 ++NumVars;
175 }
176 }
177 }
Jim Stichnoth29841e82014-12-23 12:26:24 -0800178 for (SizeT I = 0; I < Inst.getSrcSize(); ++I) {
179 Operand *Src = Inst.getSrc(I);
Jim Stichnoth70d0a052014-11-14 15:53:46 -0800180 SizeT NumVars = Src->getNumVars();
181 for (SizeT J = 0; J < NumVars; ++J) {
182 const Variable *Var = Src->getVar(J);
Jim Stichnothc6ead202015-02-24 09:30:30 -0800183 if (Var->hasReg() || Var->getWeight().isInf())
Jim Stichnoth29841e82014-12-23 12:26:24 -0800184 LREnd[Var->getIndex()] = Inst.getNumber();
Jim Stichnoth70d0a052014-11-14 15:53:46 -0800185 }
186 }
187 }
188 }
189
190 Unhandled.reserve(NumVars);
Jim Stichnoth4ead35a2014-12-03 20:30:34 -0800191 UnhandledPrecolored.reserve(NumVars);
Jim Stichnoth70d0a052014-11-14 15:53:46 -0800192 for (SizeT i = 0; i < Vars.size(); ++i) {
193 Variable *Var = Vars[i];
194 if (LRBegin[i] != Inst::NumberSentinel) {
195 assert(LREnd[i] != Inst::NumberSentinel);
196 Unhandled.push_back(Var);
197 Var->resetLiveRange();
198 const uint32_t WeightDelta = 1;
199 Var->addLiveRange(LRBegin[i], LREnd[i], WeightDelta);
200 Var->untrimLiveRange();
201 if (Var->hasReg()) {
202 Var->setRegNumTmp(Var->getRegNum());
203 Var->setLiveRangeInfiniteWeight();
204 UnhandledPrecolored.push_back(Var);
205 }
206 --NumVars;
207 }
208 }
209 // This isn't actually a fatal condition, but it would be nice to
210 // know if we somehow pre-calculated Unhandled's size wrong.
211 assert(NumVars == 0);
212
213 // Don't build up the list of Kills because we know that no
214 // infinite-weight Variable has a live range spanning a call.
215 Kills.clear();
216}
217
218void LinearScan::init(RegAllocKind Kind) {
219 Unhandled.clear();
220 UnhandledPrecolored.clear();
221 Handled.clear();
222 Inactive.clear();
223 Active.clear();
224
225 switch (Kind) {
226 case RAK_Global:
227 initForGlobal();
228 break;
229 case RAK_InfOnly:
230 initForInfOnly();
231 break;
232 }
233
Jim Stichnoth87ff3a12014-11-14 10:27:29 -0800234 struct CompareRanges {
235 bool operator()(const Variable *L, const Variable *R) {
236 InstNumberT Lstart = L->getLiveRange().getStart();
237 InstNumberT Rstart = R->getLiveRange().getStart();
238 if (Lstart == Rstart)
239 return L->getIndex() < R->getIndex();
240 return Lstart < Rstart;
241 }
242 };
243 // Do a reverse sort so that erasing elements (from the end) is fast.
244 std::sort(Unhandled.rbegin(), Unhandled.rend(), CompareRanges());
245 std::sort(UnhandledPrecolored.rbegin(), UnhandledPrecolored.rend(),
246 CompareRanges());
Jim Stichnoth4ead35a2014-12-03 20:30:34 -0800247
248 Handled.reserve(Unhandled.size());
249 Inactive.reserve(Unhandled.size());
250 Active.reserve(Unhandled.size());
Jim Stichnoth87ff3a12014-11-14 10:27:29 -0800251}
252
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700253// Implements the linear-scan algorithm. Based on "Linear Scan
254// Register Allocation in the Context of SSA Form and Register
255// Constraints" by Hanspeter Mössenböck and Michael Pfeiffer,
256// ftp://ftp.ssw.uni-linz.ac.at/pub/Papers/Moe02.PDF . This
257// implementation is modified to take affinity into account and allow
258// two interfering variables to share the same register in certain
259// cases.
260//
Jim Stichnoth800dab22014-09-20 12:25:02 -0700261// Requires running Cfg::liveness(Liveness_Intervals) in
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700262// preparation. Results are assigned to Variable::RegNum for each
263// Variable.
Jim Stichnothe6d24782014-12-19 05:42:24 -0800264void LinearScan::scan(const llvm::SmallBitVector &RegMaskFull,
265 bool Randomized) {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700266 TimerMarker T(TimerStack::TT_linearScan, Func);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700267 assert(RegMaskFull.any()); // Sanity check
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800268 GlobalContext *Ctx = Func->getContext();
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700269 const bool Verbose = BuildDefs::dump() && Func->isVerbose(IceV_LinearScan);
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800270 if (Verbose)
271 Ctx->lockStr();
Jim Stichnoth800dab22014-09-20 12:25:02 -0700272 Func->resetCurrentNode();
Jim Stichnothad403532014-09-25 12:44:17 -0700273 VariablesMetadata *VMetadata = Func->getVMetadata();
Jim Stichnothe6d24782014-12-19 05:42:24 -0800274 const size_t NumRegisters = RegMaskFull.size();
275 llvm::SmallBitVector PreDefinedRegisters(NumRegisters);
276 if (Randomized) {
277 for (Variable *Var : UnhandledPrecolored) {
278 PreDefinedRegisters[Var->getRegNum()] = true;
279 }
280 }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700281
Jim Stichnoth87ff3a12014-11-14 10:27:29 -0800282 // Build a LiveRange representing the Kills list.
Jim Stichnoth2a7fcbb2014-12-04 11:45:03 -0800283 LiveRange KillsRange(Kills);
Jim Stichnoth87ff3a12014-11-14 10:27:29 -0800284 KillsRange.untrim();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700285
286 // RegUses[I] is the number of live ranges (variables) that register
287 // I is currently assigned to. It can be greater than 1 as a result
Jim Stichnothc4554d72014-09-30 16:49:38 -0700288 // of AllowOverlap inference below.
Jim Stichnothe34d79d2015-01-12 09:00:50 -0800289 llvm::SmallVector<int, REGS_SIZE> RegUses(NumRegisters);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700290 // Unhandled is already set to all ranges in increasing order of
291 // start points.
292 assert(Active.empty());
293 assert(Inactive.empty());
294 assert(Handled.empty());
Jim Stichnoth87ff3a12014-11-14 10:27:29 -0800295 const TargetLowering::RegSetMask RegsInclude =
296 TargetLowering::RegSet_CallerSave;
297 const TargetLowering::RegSetMask RegsExclude = TargetLowering::RegSet_None;
298 const llvm::SmallBitVector KillsMask =
299 Func->getTarget()->getRegisterSet(RegsInclude, RegsExclude);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700300
301 while (!Unhandled.empty()) {
Jim Stichnoth5ce0abb2014-10-15 10:16:54 -0700302 Variable *Cur = Unhandled.back();
Jim Stichnothe22f8232014-10-13 16:20:59 -0700303 Unhandled.pop_back();
Jim Stichnothc4554d72014-09-30 16:49:38 -0700304 if (Verbose) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800305 Ostream &Str = Ctx->getStrDump();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700306 Str << "\nConsidering ";
Jim Stichnoth5ce0abb2014-10-15 10:16:54 -0700307 dumpLiveRange(Cur, Func);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700308 Str << "\n";
309 }
310 const llvm::SmallBitVector RegMask =
Jim Stichnoth5ce0abb2014-10-15 10:16:54 -0700311 RegMaskFull & Func->getTarget()->getRegisterSetForType(Cur->getType());
Jim Stichnoth87ff3a12014-11-14 10:27:29 -0800312 KillsRange.trim(Cur->getLiveRange().getStart());
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700313
314 // Check for precolored ranges. If Cur is precolored, it
315 // definitely gets that register. Previously processed live
316 // ranges would have avoided that register due to it being
317 // precolored. Future processed live ranges won't evict that
318 // register because the live range has infinite weight.
Jim Stichnoth5ce0abb2014-10-15 10:16:54 -0700319 if (Cur->hasReg()) {
320 int32_t RegNum = Cur->getRegNum();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700321 // RegNumTmp should have already been set above.
Jim Stichnoth5ce0abb2014-10-15 10:16:54 -0700322 assert(Cur->getRegNumTmp() == RegNum);
Jim Stichnothc4554d72014-09-30 16:49:38 -0700323 if (Verbose) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800324 Ostream &Str = Ctx->getStrDump();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700325 Str << "Precoloring ";
Jim Stichnoth5ce0abb2014-10-15 10:16:54 -0700326 dumpLiveRange(Cur, Func);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700327 Str << "\n";
328 }
329 Active.push_back(Cur);
330 assert(RegUses[RegNum] >= 0);
331 ++RegUses[RegNum];
Jim Stichnoth541ba662014-10-02 12:58:21 -0700332 assert(!UnhandledPrecolored.empty());
Jim Stichnoth5ce0abb2014-10-15 10:16:54 -0700333 assert(UnhandledPrecolored.back() == Cur);
Jim Stichnothe22f8232014-10-13 16:20:59 -0700334 UnhandledPrecolored.pop_back();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700335 continue;
336 }
337
338 // Check for active ranges that have expired or become inactive.
Jim Stichnoth4ead35a2014-12-03 20:30:34 -0800339 for (SizeT I = Active.size(); I > 0; --I) {
340 const SizeT Index = I - 1;
341 Variable *Item = Active[Index];
Jim Stichnoth5ce0abb2014-10-15 10:16:54 -0700342 Item->trimLiveRange(Cur->getLiveRange().getStart());
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700343 bool Moved = false;
Jim Stichnoth5ce0abb2014-10-15 10:16:54 -0700344 if (Item->rangeEndsBefore(Cur)) {
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700345 // Move Item from Active to Handled list.
Jim Stichnothc4554d72014-09-30 16:49:38 -0700346 if (Verbose) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800347 Ostream &Str = Ctx->getStrDump();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700348 Str << "Expiring ";
Jim Stichnoth5ce0abb2014-10-15 10:16:54 -0700349 dumpLiveRange(Item, Func);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700350 Str << "\n";
351 }
Jim Stichnoth4ead35a2014-12-03 20:30:34 -0800352 moveItem(Active, Index, Handled);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700353 Moved = true;
Jim Stichnoth5ce0abb2014-10-15 10:16:54 -0700354 } else if (!Item->rangeOverlapsStart(Cur)) {
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700355 // Move Item from Active to Inactive list.
Jim Stichnothc4554d72014-09-30 16:49:38 -0700356 if (Verbose) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800357 Ostream &Str = Ctx->getStrDump();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700358 Str << "Inactivating ";
Jim Stichnoth5ce0abb2014-10-15 10:16:54 -0700359 dumpLiveRange(Item, Func);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700360 Str << "\n";
361 }
Jim Stichnoth4ead35a2014-12-03 20:30:34 -0800362 moveItem(Active, Index, Inactive);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700363 Moved = true;
364 }
365 if (Moved) {
366 // Decrement Item from RegUses[].
Jim Stichnoth5ce0abb2014-10-15 10:16:54 -0700367 assert(Item->hasRegTmp());
368 int32_t RegNum = Item->getRegNumTmp();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700369 --RegUses[RegNum];
370 assert(RegUses[RegNum] >= 0);
371 }
372 }
373
374 // Check for inactive ranges that have expired or reactivated.
Jim Stichnoth4ead35a2014-12-03 20:30:34 -0800375 for (SizeT I = Inactive.size(); I > 0; --I) {
376 const SizeT Index = I - 1;
377 Variable *Item = Inactive[Index];
Jim Stichnoth5ce0abb2014-10-15 10:16:54 -0700378 Item->trimLiveRange(Cur->getLiveRange().getStart());
Jim Stichnoth5ce0abb2014-10-15 10:16:54 -0700379 if (Item->rangeEndsBefore(Cur)) {
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700380 // Move Item from Inactive to Handled list.
Jim Stichnothc4554d72014-09-30 16:49:38 -0700381 if (Verbose) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800382 Ostream &Str = Ctx->getStrDump();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700383 Str << "Expiring ";
Jim Stichnoth5ce0abb2014-10-15 10:16:54 -0700384 dumpLiveRange(Item, Func);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700385 Str << "\n";
386 }
Jim Stichnoth4ead35a2014-12-03 20:30:34 -0800387 moveItem(Inactive, Index, Handled);
Jim Stichnoth5ce0abb2014-10-15 10:16:54 -0700388 } else if (Item->rangeOverlapsStart(Cur)) {
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700389 // Move Item from Inactive to Active list.
Jim Stichnothc4554d72014-09-30 16:49:38 -0700390 if (Verbose) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800391 Ostream &Str = Ctx->getStrDump();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700392 Str << "Reactivating ";
Jim Stichnoth5ce0abb2014-10-15 10:16:54 -0700393 dumpLiveRange(Item, Func);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700394 Str << "\n";
395 }
Jim Stichnoth4ead35a2014-12-03 20:30:34 -0800396 moveItem(Inactive, Index, Active);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700397 // Increment Item in RegUses[].
Jim Stichnoth5ce0abb2014-10-15 10:16:54 -0700398 assert(Item->hasRegTmp());
399 int32_t RegNum = Item->getRegNumTmp();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700400 assert(RegUses[RegNum] >= 0);
401 ++RegUses[RegNum];
402 }
403 }
404
405 // Calculate available registers into Free[].
406 llvm::SmallBitVector Free = RegMask;
407 for (SizeT i = 0; i < RegMask.size(); ++i) {
408 if (RegUses[i] > 0)
409 Free[i] = false;
410 }
411
Jim Stichnothad403532014-09-25 12:44:17 -0700412 // Infer register preference and allowable overlap. Only form a
413 // preference when the current Variable has an unambiguous "first"
414 // definition. The preference is some source Variable of the
415 // defining instruction that either is assigned a register that is
416 // currently free, or that is assigned a register that is not free
417 // but overlap is allowed. Overlap is allowed when the Variable
418 // under consideration is single-definition, and its definition is
419 // a simple assignment - i.e., the register gets copied/aliased
420 // but is never modified. Furthermore, overlap is only allowed
421 // when preferred Variable definition instructions do not appear
422 // within the current Variable's live range.
Jim Stichnothae953202014-12-20 06:17:49 -0800423 Variable *Prefer = nullptr;
Jim Stichnothad403532014-09-25 12:44:17 -0700424 int32_t PreferReg = Variable::NoRegister;
425 bool AllowOverlap = false;
Jim Stichnoth70d0a052014-11-14 15:53:46 -0800426 if (FindPreference) {
427 if (const Inst *DefInst = VMetadata->getFirstDefinition(Cur)) {
428 assert(DefInst->getDest() == Cur);
429 bool IsAssign = DefInst->isSimpleAssign();
430 bool IsSingleDef = !VMetadata->isMultiDef(Cur);
431 for (SizeT i = 0; i < DefInst->getSrcSize(); ++i) {
432 // TODO(stichnot): Iterate through the actual Variables of the
433 // instruction, not just the source operands. This could
434 // capture Load instructions, including address mode
435 // optimization, for Prefer (but not for AllowOverlap).
436 if (Variable *SrcVar = llvm::dyn_cast<Variable>(DefInst->getSrc(i))) {
437 int32_t SrcReg = SrcVar->getRegNumTmp();
438 // Only consider source variables that have (so far) been
439 // assigned a register. That register must be one in the
440 // RegMask set, e.g. don't try to prefer the stack pointer
441 // as a result of the stacksave intrinsic.
442 if (SrcVar->hasRegTmp() && RegMask[SrcReg]) {
443 if (FindOverlap && !Free[SrcReg]) {
444 // Don't bother trying to enable AllowOverlap if the
445 // register is already free.
446 AllowOverlap =
447 IsSingleDef && IsAssign && !overlapsDefs(Func, Cur, SrcVar);
448 }
449 if (AllowOverlap || Free[SrcReg]) {
450 Prefer = SrcVar;
451 PreferReg = SrcReg;
452 }
Jim Stichnothad403532014-09-25 12:44:17 -0700453 }
454 }
455 }
Jim Stichnoth70d0a052014-11-14 15:53:46 -0800456 if (Verbose && Prefer) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800457 Ostream &Str = Ctx->getStrDump();
Jim Stichnoth9a04c072014-12-11 15:51:42 -0800458 Str << "Initial Prefer=";
459 Prefer->dump(Func);
460 Str << " R=" << PreferReg << " LIVE=" << Prefer->getLiveRange()
Jim Stichnoth70d0a052014-11-14 15:53:46 -0800461 << " Overlap=" << AllowOverlap << "\n";
462 }
Jim Stichnothad403532014-09-25 12:44:17 -0700463 }
464 }
465
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700466 // Remove registers from the Free[] list where an Inactive range
467 // overlaps with the current range.
Jim Stichnoth5ce0abb2014-10-15 10:16:54 -0700468 for (const Variable *Item : Inactive) {
469 if (Item->rangeOverlaps(Cur)) {
470 int32_t RegNum = Item->getRegNumTmp();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700471 // Don't assert(Free[RegNum]) because in theory (though
472 // probably never in practice) there could be two inactive
Jim Stichnothc4554d72014-09-30 16:49:38 -0700473 // variables that were marked with AllowOverlap.
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700474 Free[RegNum] = false;
Jim Stichnothad403532014-09-25 12:44:17 -0700475 // Disable AllowOverlap if an Inactive variable, which is not
476 // Prefer, shares Prefer's register, and has a definition
477 // within Cur's live range.
Jim Stichnoth5ce0abb2014-10-15 10:16:54 -0700478 if (AllowOverlap && Item != Prefer && RegNum == PreferReg &&
479 overlapsDefs(Func, Cur, Item)) {
Jim Stichnothad403532014-09-25 12:44:17 -0700480 AllowOverlap = false;
Jim Stichnoth5ce0abb2014-10-15 10:16:54 -0700481 dumpDisableOverlap(Func, Item, "Inactive");
Jim Stichnothad403532014-09-25 12:44:17 -0700482 }
483 }
484 }
485
486 // Disable AllowOverlap if an Active variable, which is not
487 // Prefer, shares Prefer's register, and has a definition within
488 // Cur's live range.
Jim Stichnoth70d0a052014-11-14 15:53:46 -0800489 if (AllowOverlap) {
490 for (const Variable *Item : Active) {
491 int32_t RegNum = Item->getRegNumTmp();
492 if (Item != Prefer && RegNum == PreferReg &&
493 overlapsDefs(Func, Cur, Item)) {
494 AllowOverlap = false;
495 dumpDisableOverlap(Func, Item, "Active");
496 }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700497 }
498 }
499
Jim Stichnothe34d79d2015-01-12 09:00:50 -0800500 llvm::SmallVector<RegWeight, REGS_SIZE> Weights(RegMask.size());
Jim Stichnoth541ba662014-10-02 12:58:21 -0700501
502 // Remove registers from the Free[] list where an Unhandled
503 // precolored range overlaps with the current range, and set those
504 // registers to infinite weight so that they aren't candidates for
Jim Stichnoth5ce0abb2014-10-15 10:16:54 -0700505 // eviction. Cur->rangeEndsBefore(Item) is an early exit check
506 // that turns a guaranteed O(N^2) algorithm into expected linear
Jim Stichnoth541ba662014-10-02 12:58:21 -0700507 // complexity.
508 llvm::SmallBitVector PrecoloredUnhandledMask(RegMask.size());
509 // Note: PrecoloredUnhandledMask is only used for dumping.
Jim Stichnoth7e571362015-01-09 11:43:26 -0800510 for (Variable *Item : reverse_range(UnhandledPrecolored)) {
Jim Stichnoth5ce0abb2014-10-15 10:16:54 -0700511 assert(Item->hasReg());
512 if (Cur->rangeEndsBefore(Item))
Jim Stichnothf44f3712014-10-01 14:05:51 -0700513 break;
Jim Stichnoth5ce0abb2014-10-15 10:16:54 -0700514 if (Item->rangeOverlaps(Cur)) {
515 int32_t ItemReg = Item->getRegNum(); // Note: not getRegNumTmp()
Jim Stichnoth541ba662014-10-02 12:58:21 -0700516 Weights[ItemReg].setWeight(RegWeight::Inf);
Jim Stichnothad403532014-09-25 12:44:17 -0700517 Free[ItemReg] = false;
Jim Stichnoth541ba662014-10-02 12:58:21 -0700518 PrecoloredUnhandledMask[ItemReg] = true;
Jim Stichnothad403532014-09-25 12:44:17 -0700519 // Disable AllowOverlap if the preferred register is one of
520 // these precolored unhandled overlapping ranges.
521 if (AllowOverlap && ItemReg == PreferReg) {
522 AllowOverlap = false;
Jim Stichnoth5ce0abb2014-10-15 10:16:54 -0700523 dumpDisableOverlap(Func, Item, "PrecoloredUnhandled");
Jim Stichnothad403532014-09-25 12:44:17 -0700524 }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700525 }
526 }
527
Jim Stichnoth87ff3a12014-11-14 10:27:29 -0800528 // Remove scratch registers from the Free[] list, and mark their
529 // Weights[] as infinite, if KillsRange overlaps Cur's live range.
530 const bool UseTrimmed = true;
531 if (Cur->getLiveRange().overlaps(KillsRange, UseTrimmed)) {
532 Free.reset(KillsMask);
533 for (int i = KillsMask.find_first(); i != -1;
534 i = KillsMask.find_next(i)) {
535 Weights[i].setWeight(RegWeight::Inf);
536 if (PreferReg == i)
537 AllowOverlap = false;
538 }
539 }
540
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700541 // Print info about physical register availability.
Jim Stichnothc4554d72014-09-30 16:49:38 -0700542 if (Verbose) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800543 Ostream &Str = Ctx->getStrDump();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700544 for (SizeT i = 0; i < RegMask.size(); ++i) {
545 if (RegMask[i]) {
546 Str << Func->getTarget()->getRegName(i, IceType_i32)
Jim Stichnothca662e92014-07-10 15:32:36 -0700547 << "(U=" << RegUses[i] << ",F=" << Free[i]
Jim Stichnoth541ba662014-10-02 12:58:21 -0700548 << ",P=" << PrecoloredUnhandledMask[i] << ") ";
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700549 }
550 }
551 Str << "\n";
552 }
553
Jim Stichnothad403532014-09-25 12:44:17 -0700554 if (Prefer && (AllowOverlap || Free[PreferReg])) {
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700555 // First choice: a preferred register that is either free or is
556 // allowed to overlap with its linked variable.
Jim Stichnoth5ce0abb2014-10-15 10:16:54 -0700557 Cur->setRegNumTmp(PreferReg);
Jim Stichnothc4554d72014-09-30 16:49:38 -0700558 if (Verbose) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800559 Ostream &Str = Ctx->getStrDump();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700560 Str << "Preferring ";
Jim Stichnoth5ce0abb2014-10-15 10:16:54 -0700561 dumpLiveRange(Cur, Func);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700562 Str << "\n";
563 }
564 assert(RegUses[PreferReg] >= 0);
565 ++RegUses[PreferReg];
566 Active.push_back(Cur);
567 } else if (Free.any()) {
568 // Second choice: any free register. TODO: After explicit
569 // affinity is considered, is there a strategy better than just
570 // picking the lowest-numbered available register?
571 int32_t RegNum = Free.find_first();
Jim Stichnoth5ce0abb2014-10-15 10:16:54 -0700572 Cur->setRegNumTmp(RegNum);
Jim Stichnothc4554d72014-09-30 16:49:38 -0700573 if (Verbose) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800574 Ostream &Str = Ctx->getStrDump();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700575 Str << "Allocating ";
Jim Stichnoth5ce0abb2014-10-15 10:16:54 -0700576 dumpLiveRange(Cur, Func);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700577 Str << "\n";
578 }
579 assert(RegUses[RegNum] >= 0);
580 ++RegUses[RegNum];
581 Active.push_back(Cur);
582 } else {
583 // Fallback: there are no free registers, so we look for the
584 // lowest-weight register and see if Cur has higher weight.
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700585 // Check Active ranges.
Jim Stichnoth5ce0abb2014-10-15 10:16:54 -0700586 for (const Variable *Item : Active) {
587 assert(Item->rangeOverlaps(Cur));
588 int32_t RegNum = Item->getRegNumTmp();
589 assert(Item->hasRegTmp());
590 Weights[RegNum].addWeight(Item->getLiveRange().getWeight());
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700591 }
592 // Same as above, but check Inactive ranges instead of Active.
Jim Stichnoth5ce0abb2014-10-15 10:16:54 -0700593 for (const Variable *Item : Inactive) {
594 int32_t RegNum = Item->getRegNumTmp();
595 assert(Item->hasRegTmp());
596 if (Item->rangeOverlaps(Cur))
597 Weights[RegNum].addWeight(Item->getLiveRange().getWeight());
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700598 }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700599
600 // All the weights are now calculated. Find the register with
601 // smallest weight.
602 int32_t MinWeightIndex = RegMask.find_first();
603 // MinWeightIndex must be valid because of the initial
604 // RegMask.any() test.
605 assert(MinWeightIndex >= 0);
606 for (SizeT i = MinWeightIndex + 1; i < Weights.size(); ++i) {
607 if (RegMask[i] && Weights[i] < Weights[MinWeightIndex])
608 MinWeightIndex = i;
609 }
610
Jim Stichnoth5ce0abb2014-10-15 10:16:54 -0700611 if (Cur->getLiveRange().getWeight() <= Weights[MinWeightIndex]) {
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700612 // Cur doesn't have priority over any other live ranges, so
613 // don't allocate any register to it, and move it to the
614 // Handled state.
615 Handled.push_back(Cur);
Jim Stichnoth5ce0abb2014-10-15 10:16:54 -0700616 if (Cur->getLiveRange().getWeight().isInf()) {
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700617 Func->setError("Unable to find a physical register for an "
618 "infinite-weight live range");
619 }
620 } else {
621 // Evict all live ranges in Active that register number
622 // MinWeightIndex is assigned to.
Jim Stichnoth4ead35a2014-12-03 20:30:34 -0800623 for (SizeT I = Active.size(); I > 0; --I) {
624 const SizeT Index = I - 1;
625 Variable *Item = Active[Index];
Jim Stichnoth5ce0abb2014-10-15 10:16:54 -0700626 if (Item->getRegNumTmp() == MinWeightIndex) {
Jim Stichnothc4554d72014-09-30 16:49:38 -0700627 if (Verbose) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800628 Ostream &Str = Ctx->getStrDump();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700629 Str << "Evicting ";
Jim Stichnoth5ce0abb2014-10-15 10:16:54 -0700630 dumpLiveRange(Item, Func);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700631 Str << "\n";
632 }
633 --RegUses[MinWeightIndex];
634 assert(RegUses[MinWeightIndex] >= 0);
Jim Stichnoth5ce0abb2014-10-15 10:16:54 -0700635 Item->setRegNumTmp(Variable::NoRegister);
Jim Stichnoth4ead35a2014-12-03 20:30:34 -0800636 moveItem(Active, Index, Handled);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700637 }
638 }
639 // Do the same for Inactive.
Jim Stichnoth4ead35a2014-12-03 20:30:34 -0800640 for (SizeT I = Inactive.size(); I > 0; --I) {
641 const SizeT Index = I - 1;
642 Variable *Item = Inactive[Index];
Jim Stichnoth5ce0abb2014-10-15 10:16:54 -0700643 // Note: The Item->rangeOverlaps(Cur) clause is not part of the
Jim Stichnoth68e28192014-07-24 08:48:15 -0700644 // description of AssignMemLoc() in the original paper. But
645 // there doesn't seem to be any need to evict an inactive
646 // live range that doesn't overlap with the live range
647 // currently being considered. It's especially bad if we
648 // would end up evicting an infinite-weight but
649 // currently-inactive live range. The most common situation
650 // for this would be a scratch register kill set for call
651 // instructions.
Jim Stichnoth5ce0abb2014-10-15 10:16:54 -0700652 if (Item->getRegNumTmp() == MinWeightIndex &&
653 Item->rangeOverlaps(Cur)) {
Jim Stichnothc4554d72014-09-30 16:49:38 -0700654 if (Verbose) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800655 Ostream &Str = Ctx->getStrDump();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700656 Str << "Evicting ";
Jim Stichnoth5ce0abb2014-10-15 10:16:54 -0700657 dumpLiveRange(Item, Func);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700658 Str << "\n";
659 }
Jim Stichnoth5ce0abb2014-10-15 10:16:54 -0700660 Item->setRegNumTmp(Variable::NoRegister);
Jim Stichnoth4ead35a2014-12-03 20:30:34 -0800661 moveItem(Inactive, Index, Handled);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700662 }
663 }
664 // Assign the register to Cur.
Jim Stichnoth5ce0abb2014-10-15 10:16:54 -0700665 Cur->setRegNumTmp(MinWeightIndex);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700666 assert(RegUses[MinWeightIndex] >= 0);
667 ++RegUses[MinWeightIndex];
668 Active.push_back(Cur);
Jim Stichnothc4554d72014-09-30 16:49:38 -0700669 if (Verbose) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800670 Ostream &Str = Ctx->getStrDump();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700671 Str << "Allocating ";
Jim Stichnoth5ce0abb2014-10-15 10:16:54 -0700672 dumpLiveRange(Cur, Func);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700673 Str << "\n";
674 }
675 }
676 }
677 dump(Func);
678 }
679 // Move anything Active or Inactive to Handled for easier handling.
Jim Stichnoth5ce0abb2014-10-15 10:16:54 -0700680 for (Variable *I : Active)
Jim Stichnothf44f3712014-10-01 14:05:51 -0700681 Handled.push_back(I);
682 Active.clear();
Jim Stichnoth5ce0abb2014-10-15 10:16:54 -0700683 for (Variable *I : Inactive)
Jim Stichnothf44f3712014-10-01 14:05:51 -0700684 Handled.push_back(I);
685 Inactive.clear();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700686 dump(Func);
687
Jim Stichnothe6d24782014-12-19 05:42:24 -0800688 llvm::SmallVector<int32_t, REGS_SIZE> Permutation(NumRegisters);
689 if (Randomized) {
690 Func->getTarget()->makeRandomRegisterPermutation(
691 Permutation, PreDefinedRegisters | ~RegMaskFull);
692 }
693
694 // Finish up by assigning RegNumTmp->RegNum (or a random permutation
695 // thereof) for each Variable.
Jim Stichnoth5ce0abb2014-10-15 10:16:54 -0700696 for (Variable *Item : Handled) {
697 int32_t RegNum = Item->getRegNumTmp();
Jim Stichnothe6d24782014-12-19 05:42:24 -0800698 int32_t AssignedRegNum = RegNum;
699
700 if (Randomized && Item->hasRegTmp() && !Item->hasReg()) {
701 AssignedRegNum = Permutation[RegNum];
702 }
Jim Stichnothc4554d72014-09-30 16:49:38 -0700703 if (Verbose) {
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800704 Ostream &Str = Ctx->getStrDump();
Jim Stichnoth5ce0abb2014-10-15 10:16:54 -0700705 if (!Item->hasRegTmp()) {
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700706 Str << "Not assigning ";
Jim Stichnoth5ce0abb2014-10-15 10:16:54 -0700707 Item->dump(Func);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700708 Str << "\n";
709 } else {
Jim Stichnothe6d24782014-12-19 05:42:24 -0800710 Str << (AssignedRegNum == Item->getRegNum() ? "Reassigning "
711 : "Assigning ")
712 << Func->getTarget()->getRegName(AssignedRegNum, IceType_i32)
713 << "(r" << AssignedRegNum << ") to ";
Jim Stichnoth5ce0abb2014-10-15 10:16:54 -0700714 Item->dump(Func);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700715 Str << "\n";
716 }
717 }
Jim Stichnothe6d24782014-12-19 05:42:24 -0800718 Item->setRegNum(AssignedRegNum);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700719 }
720
721 // TODO: Consider running register allocation one more time, with
722 // infinite registers, for two reasons. First, evicted live ranges
723 // get a second chance for a register. Second, it allows coalescing
724 // of stack slots. If there is no time budget for the second
725 // register allocation run, each unallocated variable just gets its
726 // own slot.
727 //
728 // Another idea for coalescing stack slots is to initialize the
729 // Unhandled list with just the unallocated variables, saving time
730 // but not offering second-chance opportunities.
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800731
732 if (Verbose)
733 Ctx->unlockStr();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700734}
735
736// ======================== Dump routines ======================== //
737
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700738void LinearScan::dump(Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700739 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800740 return;
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800741 if (!Func->isVerbose(IceV_LinearScan))
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700742 return;
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800743 Ostream &Str = Func->getContext()->getStrDump();
Jim Stichnoth800dab22014-09-20 12:25:02 -0700744 Func->resetCurrentNode();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700745 Str << "**** Current regalloc state:\n";
746 Str << "++++++ Handled:\n";
Jim Stichnoth5ce0abb2014-10-15 10:16:54 -0700747 for (const Variable *Item : Handled) {
748 dumpLiveRange(Item, Func);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700749 Str << "\n";
750 }
751 Str << "++++++ Unhandled:\n";
Jim Stichnoth7e571362015-01-09 11:43:26 -0800752 for (const Variable *Item : reverse_range(Unhandled)) {
753 dumpLiveRange(Item, Func);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700754 Str << "\n";
755 }
756 Str << "++++++ Active:\n";
Jim Stichnoth5ce0abb2014-10-15 10:16:54 -0700757 for (const Variable *Item : Active) {
758 dumpLiveRange(Item, Func);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700759 Str << "\n";
760 }
761 Str << "++++++ Inactive:\n";
Jim Stichnoth5ce0abb2014-10-15 10:16:54 -0700762 for (const Variable *Item : Inactive) {
763 dumpLiveRange(Item, Func);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700764 Str << "\n";
765 }
766}
767
768} // end of namespace Ice