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

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

Powered by Google App Engine
This is Rietveld 408576698