Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1005)

Side by Side Diff: src/IceRegAlloc.cpp

Issue 733643005: Subzero: Use the linear-scan register allocator for Om1 as well. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Update/fix some comments Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/IceRegAlloc.h ('k') | src/IceTargetLowering.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 //===- subzero/src/IceRegAlloc.cpp - Linear-scan implementation -----------===// 1 //===- subzero/src/IceRegAlloc.cpp - Linear-scan implementation -----------===//
2 // 2 //
3 // The Subzero Code Generator 3 // The Subzero Code Generator
4 // 4 //
5 // This file is distributed under the University of Illinois Open Source 5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details. 6 // License. See LICENSE.TXT for details.
7 // 7 //
8 //===----------------------------------------------------------------------===// 8 //===----------------------------------------------------------------------===//
9 // 9 //
10 // This file implements the LinearScan class, which performs the 10 // This file implements the LinearScan class, which performs the
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
66 const static size_t BufLen = 30; 66 const static size_t BufLen = 30;
67 char buf[BufLen]; 67 char buf[BufLen];
68 snprintf(buf, BufLen, "%2d", Var->getRegNumTmp()); 68 snprintf(buf, BufLen, "%2d", Var->getRegNumTmp());
69 Str << "R=" << buf << " V="; 69 Str << "R=" << buf << " V=";
70 Var->dump(Func); 70 Var->dump(Func);
71 Str << " Range=" << Var->getLiveRange(); 71 Str << " Range=" << Var->getLiveRange();
72 } 72 }
73 73
74 } // end of anonymous namespace 74 } // end of anonymous namespace
75 75
76 void LinearScan::initForGlobalAlloc() { 76 // Prepare for full register allocation of all variables. We depend
77 // on liveness analysis to have calculated live ranges.
78 void LinearScan::initForGlobal() {
77 TimerMarker T(TimerStack::TT_initUnhandled, Func); 79 TimerMarker T(TimerStack::TT_initUnhandled, Func);
78 Unhandled.clear(); 80 FindPreference = true;
79 UnhandledPrecolored.clear(); 81 FindOverlap = true;
80 Handled.clear(); 82 const VarList &Vars = Func->getVariables();
81 Inactive.clear(); 83 Unhandled.reserve(Vars.size());
82 Active.clear();
83 // Gather the live ranges of all variables and add them to the 84 // Gather the live ranges of all variables and add them to the
84 // Unhandled set. 85 // Unhandled set.
85 const VarList &Vars = Func->getVariables();
86 Unhandled.reserve(Vars.size());
87 for (Variable *Var : Vars) { 86 for (Variable *Var : Vars) {
88 // Explicitly don't consider zero-weight variables, which are 87 // Explicitly don't consider zero-weight variables, which are
89 // meant to be spill slots. 88 // meant to be spill slots.
90 if (Var->getWeight() == RegWeight::Zero) 89 if (Var->getWeight() == RegWeight::Zero)
91 continue; 90 continue;
92 // Don't bother if the variable has a null live range, which means 91 // Don't bother if the variable has a null live range, which means
93 // it was never referenced. 92 // it was never referenced.
94 if (Var->getLiveRange().isEmpty()) 93 if (Var->getLiveRange().isEmpty())
95 continue; 94 continue;
96 Var->untrimLiveRange(); 95 Var->untrimLiveRange();
97 Unhandled.push_back(Var); 96 Unhandled.push_back(Var);
98 if (Var->hasReg()) { 97 if (Var->hasReg()) {
99 Var->setRegNumTmp(Var->getRegNum()); 98 Var->setRegNumTmp(Var->getRegNum());
100 Var->setLiveRangeInfiniteWeight(); 99 Var->setLiveRangeInfiniteWeight();
101 UnhandledPrecolored.push_back(Var); 100 UnhandledPrecolored.push_back(Var);
102 } 101 }
103 } 102 }
103
104 // Build the (ordered) list of FakeKill instruction numbers.
105 Kills.clear();
106 for (CfgNode *Node : Func->getNodes()) {
107 for (auto I = Node->getInsts().begin(), E = Node->getInsts().end(); I != E;
108 ++I) {
109 if (auto Kill = llvm::dyn_cast<InstFakeKill>(I)) {
110 if (!Kill->isDeleted() && !Kill->getLinked()->isDeleted())
111 Kills.push_back(I->getNumber());
112 }
113 }
114 }
115 }
116
117 // Prepare for very simple register allocation of only infinite-weight
118 // Variables while respecting pre-colored Variables. Some properties
119 // we take advantage of:
120 //
121 // * Live ranges of interest consist of a single segment.
122 //
123 // * Live ranges of interest never span a call instruction.
124 //
125 // * Phi instructions are not considered because either phis have
126 // already been lowered, or they don't contain any pre-colored or
127 // infinite-weight Variables.
128 //
129 // * We don't need to renumber instructions before computing live
130 // ranges because all the high-level ICE instructions are deleted
131 // prior to lowering, and the low-level instructions are added in
132 // monotonically increasing order.
133 //
134 // * There are no opportunities for register preference or allowing
135 // overlap.
136 //
137 // Some properties we aren't (yet) taking advantage of:
138 //
139 // * Because live ranges are a single segment, the Unhandled set will
140 // always be empty, and the live range trimming operation is
141 // unnecessary.
142 //
143 // * Calculating overlap of single-segment live ranges could be
144 // optimized a bit.
145 void LinearScan::initForInfOnly() {
146 TimerMarker T(TimerStack::TT_initUnhandled, Func);
147 FindPreference = false;
148 FindOverlap = false;
149 SizeT NumVars = 0;
150 const VarList &Vars = Func->getVariables();
151
152 // Iterate across all instructions and record the begin and end of
153 // the live range for each variable that is pre-colored or infinite
154 // weight.
155 std::vector<InstNumberT> LRBegin(Vars.size(), Inst::NumberSentinel);
156 std::vector<InstNumberT> LREnd(Vars.size(), Inst::NumberSentinel);
157 for (CfgNode *Node : Func->getNodes()) {
158 for (auto Inst = Node->getInsts().begin(), E = Node->getInsts().end();
159 Inst != E; ++Inst) {
160 if (Inst->isDeleted())
161 continue;
162 if (const Variable *Var = Inst->getDest()) {
163 if (Var->hasReg() || Var->getWeight() == RegWeight::Inf) {
164 if (LRBegin[Var->getIndex()] == Inst::NumberSentinel) {
165 LRBegin[Var->getIndex()] = Inst->getNumber();
166 ++NumVars;
167 }
168 }
169 }
170 for (SizeT I = 0; I < Inst->getSrcSize(); ++I) {
171 Operand *Src = Inst->getSrc(I);
172 SizeT NumVars = Src->getNumVars();
173 for (SizeT J = 0; J < NumVars; ++J) {
174 const Variable *Var = Src->getVar(J);
175 if (Var->hasReg() || Var->getWeight() == RegWeight::Inf)
176 LREnd[Var->getIndex()] = Inst->getNumber();
177 }
178 }
179 }
180 }
181
182 Unhandled.reserve(NumVars);
183 for (SizeT i = 0; i < Vars.size(); ++i) {
184 Variable *Var = Vars[i];
185 if (LRBegin[i] != Inst::NumberSentinel) {
186 assert(LREnd[i] != Inst::NumberSentinel);
187 Unhandled.push_back(Var);
188 Var->resetLiveRange();
189 const uint32_t WeightDelta = 1;
190 Var->addLiveRange(LRBegin[i], LREnd[i], WeightDelta);
191 Var->untrimLiveRange();
192 if (Var->hasReg()) {
193 Var->setRegNumTmp(Var->getRegNum());
194 Var->setLiveRangeInfiniteWeight();
195 UnhandledPrecolored.push_back(Var);
196 }
197 --NumVars;
198 }
199 }
200 // This isn't actually a fatal condition, but it would be nice to
201 // know if we somehow pre-calculated Unhandled's size wrong.
202 assert(NumVars == 0);
203
204 // Don't build up the list of Kills because we know that no
205 // infinite-weight Variable has a live range spanning a call.
206 Kills.clear();
207 }
208
209 void LinearScan::init(RegAllocKind Kind) {
210 Unhandled.clear();
211 UnhandledPrecolored.clear();
212 Handled.clear();
213 Inactive.clear();
214 Active.clear();
215
216 switch (Kind) {
217 case RAK_Global:
218 initForGlobal();
219 break;
220 case RAK_InfOnly:
221 initForInfOnly();
222 break;
223 }
224
104 struct CompareRanges { 225 struct CompareRanges {
105 bool operator()(const Variable *L, const Variable *R) { 226 bool operator()(const Variable *L, const Variable *R) {
106 InstNumberT Lstart = L->getLiveRange().getStart(); 227 InstNumberT Lstart = L->getLiveRange().getStart();
107 InstNumberT Rstart = R->getLiveRange().getStart(); 228 InstNumberT Rstart = R->getLiveRange().getStart();
108 if (Lstart == Rstart) 229 if (Lstart == Rstart)
109 return L->getIndex() < R->getIndex(); 230 return L->getIndex() < R->getIndex();
110 return Lstart < Rstart; 231 return Lstart < Rstart;
111 } 232 }
112 }; 233 };
113 // Do a reverse sort so that erasing elements (from the end) is fast. 234 // Do a reverse sort so that erasing elements (from the end) is fast.
114 std::sort(Unhandled.rbegin(), Unhandled.rend(), CompareRanges()); 235 std::sort(Unhandled.rbegin(), Unhandled.rend(), CompareRanges());
115 std::sort(UnhandledPrecolored.rbegin(), UnhandledPrecolored.rend(), 236 std::sort(UnhandledPrecolored.rbegin(), UnhandledPrecolored.rend(),
116 CompareRanges()); 237 CompareRanges());
117
118 // Build the (ordered) list of FakeKill instruction numbers.
119 Kills.clear();
120 for (CfgNode *Node : Func->getNodes()) {
121 for (auto I = Node->getInsts().begin(), E = Node->getInsts().end(); I != E;
122 ++I) {
123 if (I->isDeleted())
124 continue;
125 if (auto Kill = llvm::dyn_cast<InstFakeKill>(I)) {
126 if (!Kill->getLinked()->isDeleted())
127 Kills.push_back(I->getNumber());
128 }
129 }
130 }
131 } 238 }
132 239
133 // Implements the linear-scan algorithm. Based on "Linear Scan 240 // Implements the linear-scan algorithm. Based on "Linear Scan
134 // Register Allocation in the Context of SSA Form and Register 241 // Register Allocation in the Context of SSA Form and Register
135 // Constraints" by Hanspeter Mössenböck and Michael Pfeiffer, 242 // Constraints" by Hanspeter Mössenböck and Michael Pfeiffer,
136 // ftp://ftp.ssw.uni-linz.ac.at/pub/Papers/Moe02.PDF . This 243 // ftp://ftp.ssw.uni-linz.ac.at/pub/Papers/Moe02.PDF . This
137 // implementation is modified to take affinity into account and allow 244 // implementation is modified to take affinity into account and allow
138 // two interfering variables to share the same register in certain 245 // two interfering variables to share the same register in certain
139 // cases. 246 // cases.
140 // 247 //
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
285 // currently free, or that is assigned a register that is not free 392 // currently free, or that is assigned a register that is not free
286 // but overlap is allowed. Overlap is allowed when the Variable 393 // but overlap is allowed. Overlap is allowed when the Variable
287 // under consideration is single-definition, and its definition is 394 // under consideration is single-definition, and its definition is
288 // a simple assignment - i.e., the register gets copied/aliased 395 // a simple assignment - i.e., the register gets copied/aliased
289 // but is never modified. Furthermore, overlap is only allowed 396 // but is never modified. Furthermore, overlap is only allowed
290 // when preferred Variable definition instructions do not appear 397 // when preferred Variable definition instructions do not appear
291 // within the current Variable's live range. 398 // within the current Variable's live range.
292 Variable *Prefer = NULL; 399 Variable *Prefer = NULL;
293 int32_t PreferReg = Variable::NoRegister; 400 int32_t PreferReg = Variable::NoRegister;
294 bool AllowOverlap = false; 401 bool AllowOverlap = false;
295 if (const Inst *DefInst = VMetadata->getFirstDefinition(Cur)) { 402 if (FindPreference) {
296 assert(DefInst->getDest() == Cur); 403 if (const Inst *DefInst = VMetadata->getFirstDefinition(Cur)) {
297 bool IsAssign = DefInst->isSimpleAssign(); 404 assert(DefInst->getDest() == Cur);
298 bool IsSingleDef = !VMetadata->isMultiDef(Cur); 405 bool IsAssign = DefInst->isSimpleAssign();
299 for (SizeT i = 0; i < DefInst->getSrcSize(); ++i) { 406 bool IsSingleDef = !VMetadata->isMultiDef(Cur);
300 // TODO(stichnot): Iterate through the actual Variables of the 407 for (SizeT i = 0; i < DefInst->getSrcSize(); ++i) {
301 // instruction, not just the source operands. This could 408 // TODO(stichnot): Iterate through the actual Variables of the
302 // capture Load instructions, including address mode 409 // instruction, not just the source operands. This could
303 // optimization, for Prefer (but not for AllowOverlap). 410 // capture Load instructions, including address mode
304 if (Variable *SrcVar = llvm::dyn_cast<Variable>(DefInst->getSrc(i))) { 411 // optimization, for Prefer (but not for AllowOverlap).
305 int32_t SrcReg = SrcVar->getRegNumTmp(); 412 if (Variable *SrcVar = llvm::dyn_cast<Variable>(DefInst->getSrc(i))) {
306 // Only consider source variables that have (so far) been 413 int32_t SrcReg = SrcVar->getRegNumTmp();
307 // assigned a register. That register must be one in the 414 // Only consider source variables that have (so far) been
308 // RegMask set, e.g. don't try to prefer the stack pointer 415 // assigned a register. That register must be one in the
309 // as a result of the stacksave intrinsic. 416 // RegMask set, e.g. don't try to prefer the stack pointer
310 if (SrcVar->hasRegTmp() && RegMask[SrcReg]) { 417 // as a result of the stacksave intrinsic.
311 if (!Free[SrcReg]) { 418 if (SrcVar->hasRegTmp() && RegMask[SrcReg]) {
312 // Don't bother trying to enable AllowOverlap if the 419 if (FindOverlap && !Free[SrcReg]) {
313 // register is already free. 420 // Don't bother trying to enable AllowOverlap if the
314 AllowOverlap = 421 // register is already free.
315 IsSingleDef && IsAssign && !overlapsDefs(Func, Cur, SrcVar); 422 AllowOverlap =
316 } 423 IsSingleDef && IsAssign && !overlapsDefs(Func, Cur, SrcVar);
317 if (AllowOverlap || Free[SrcReg]) { 424 }
318 Prefer = SrcVar; 425 if (AllowOverlap || Free[SrcReg]) {
319 PreferReg = SrcReg; 426 Prefer = SrcVar;
427 PreferReg = SrcReg;
428 }
320 } 429 }
321 } 430 }
322 } 431 }
323 } 432 if (Verbose && Prefer) {
324 } 433 Str << "Initial Prefer=" << *Prefer << " R=" << PreferReg
325 if (Verbose) { 434 << " LIVE=" << Prefer->getLiveRange()
326 if (Prefer) { 435 << " Overlap=" << AllowOverlap << "\n";
327 Str << "Initial Prefer=" << *Prefer << " R=" << PreferReg 436 }
328 << " LIVE=" << Prefer->getLiveRange() << " Overlap=" << AllowOverlap
329 << "\n";
330 } 437 }
331 } 438 }
332 439
333 // Remove registers from the Free[] list where an Inactive range 440 // Remove registers from the Free[] list where an Inactive range
334 // overlaps with the current range. 441 // overlaps with the current range.
335 for (const Variable *Item : Inactive) { 442 for (const Variable *Item : Inactive) {
336 if (Item->rangeOverlaps(Cur)) { 443 if (Item->rangeOverlaps(Cur)) {
337 int32_t RegNum = Item->getRegNumTmp(); 444 int32_t RegNum = Item->getRegNumTmp();
338 // Don't assert(Free[RegNum]) because in theory (though 445 // Don't assert(Free[RegNum]) because in theory (though
339 // probably never in practice) there could be two inactive 446 // probably never in practice) there could be two inactive
340 // variables that were marked with AllowOverlap. 447 // variables that were marked with AllowOverlap.
341 Free[RegNum] = false; 448 Free[RegNum] = false;
342 // Disable AllowOverlap if an Inactive variable, which is not 449 // Disable AllowOverlap if an Inactive variable, which is not
343 // Prefer, shares Prefer's register, and has a definition 450 // Prefer, shares Prefer's register, and has a definition
344 // within Cur's live range. 451 // within Cur's live range.
345 if (AllowOverlap && Item != Prefer && RegNum == PreferReg && 452 if (AllowOverlap && Item != Prefer && RegNum == PreferReg &&
346 overlapsDefs(Func, Cur, Item)) { 453 overlapsDefs(Func, Cur, Item)) {
347 AllowOverlap = false; 454 AllowOverlap = false;
348 dumpDisableOverlap(Func, Item, "Inactive"); 455 dumpDisableOverlap(Func, Item, "Inactive");
349 } 456 }
350 } 457 }
351 } 458 }
352 459
353 // Disable AllowOverlap if an Active variable, which is not 460 // Disable AllowOverlap if an Active variable, which is not
354 // Prefer, shares Prefer's register, and has a definition within 461 // Prefer, shares Prefer's register, and has a definition within
355 // Cur's live range. 462 // Cur's live range.
356 for (const Variable *Item : Active) { 463 if (AllowOverlap) {
357 int32_t RegNum = Item->getRegNumTmp(); 464 for (const Variable *Item : Active) {
358 if (Item != Prefer && RegNum == PreferReg && 465 int32_t RegNum = Item->getRegNumTmp();
359 overlapsDefs(Func, Cur, Item)) { 466 if (Item != Prefer && RegNum == PreferReg &&
360 AllowOverlap = false; 467 overlapsDefs(Func, Cur, Item)) {
361 dumpDisableOverlap(Func, Item, "Active"); 468 AllowOverlap = false;
469 dumpDisableOverlap(Func, Item, "Active");
470 }
362 } 471 }
363 } 472 }
364 473
365 std::vector<RegWeight> Weights(RegMask.size()); 474 std::vector<RegWeight> Weights(RegMask.size());
366 475
367 // Remove registers from the Free[] list where an Unhandled 476 // Remove registers from the Free[] list where an Unhandled
368 // precolored range overlaps with the current range, and set those 477 // precolored range overlaps with the current range, and set those
369 // registers to infinite weight so that they aren't candidates for 478 // registers to infinite weight so that they aren't candidates for
370 // eviction. Cur->rangeEndsBefore(Item) is an early exit check 479 // eviction. Cur->rangeEndsBefore(Item) is an early exit check
371 // that turns a guaranteed O(N^2) algorithm into expected linear 480 // that turns a guaranteed O(N^2) algorithm into expected linear
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after
603 Str << "\n"; 712 Str << "\n";
604 } 713 }
605 Str << "++++++ Inactive:\n"; 714 Str << "++++++ Inactive:\n";
606 for (const Variable *Item : Inactive) { 715 for (const Variable *Item : Inactive) {
607 dumpLiveRange(Item, Func); 716 dumpLiveRange(Item, Func);
608 Str << "\n"; 717 Str << "\n";
609 } 718 }
610 } 719 }
611 720
612 } // end of namespace Ice 721 } // end of namespace Ice
OLDNEW
« no previous file with comments | « src/IceRegAlloc.h ('k') | src/IceTargetLowering.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698