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

Side by Side Diff: src/IceRegAlloc.cpp

Issue 597003004: Subzero: Automatically infer regalloc preferences and overlap. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Code review changes Created 6 years, 2 months 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/IceOperand.cpp ('k') | src/IceTargetLoweringX8632.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
11 // linear-scan register allocation after liveness analysis has been 11 // linear-scan register allocation after liveness analysis has been
12 // performed. 12 // performed.
13 // 13 //
14 //===----------------------------------------------------------------------===// 14 //===----------------------------------------------------------------------===//
15 15
16 #include "IceCfg.h" 16 #include "IceCfg.h"
17 #include "IceInst.h" 17 #include "IceInst.h"
18 #include "IceOperand.h" 18 #include "IceOperand.h"
19 #include "IceRegAlloc.h" 19 #include "IceRegAlloc.h"
20 #include "IceTargetLowering.h" 20 #include "IceTargetLowering.h"
21 21
22 namespace Ice { 22 namespace Ice {
23 23
24 namespace {
25
26 // Returns true if Var has any definitions within Item's live range.
27 bool overlapsDefs(const Cfg *Func, const LiveRangeWrapper &Item,
28 const Variable *Var) {
29 const InstDefList &Defs = Func->getVMetadata()->getDefinitions(Var);
30 for (size_t i = 0; i < Defs.size(); ++i) {
31 if (Item.range().overlaps(Defs[i]->getNumber()))
32 return true;
33 }
34 return false;
35 }
36
37 void dumpDisableOverlap(const Cfg *Func, const Variable *Var,
38 const char *Reason) {
39 if (Func->getContext()->isVerbose(IceV_LinearScan)) {
40 Ostream &Str = Func->getContext()->getStrDump();
41 Str << "Disabling Overlap due to " << Reason << " " << *Var
42 << " LIVE=" << Var->getLiveRange() << " Defs=";
43 const InstDefList &Defs = Func->getVMetadata()->getDefinitions(Var);
44 for (size_t i = 0; i < Defs.size(); ++i) {
45 if (i > 0)
46 Str << ",";
47 Str << Defs[i]->getNumber();
48 }
49 Str << "\n";
50 }
51 }
52
53 } // end of anonymous namespace
54
24 // Implements the linear-scan algorithm. Based on "Linear Scan 55 // Implements the linear-scan algorithm. Based on "Linear Scan
25 // Register Allocation in the Context of SSA Form and Register 56 // Register Allocation in the Context of SSA Form and Register
26 // Constraints" by Hanspeter Mössenböck and Michael Pfeiffer, 57 // Constraints" by Hanspeter Mössenböck and Michael Pfeiffer,
27 // ftp://ftp.ssw.uni-linz.ac.at/pub/Papers/Moe02.PDF . This 58 // ftp://ftp.ssw.uni-linz.ac.at/pub/Papers/Moe02.PDF . This
28 // implementation is modified to take affinity into account and allow 59 // implementation is modified to take affinity into account and allow
29 // two interfering variables to share the same register in certain 60 // two interfering variables to share the same register in certain
30 // cases. 61 // cases.
31 // 62 //
32 // Requires running Cfg::liveness(Liveness_Intervals) in 63 // Requires running Cfg::liveness(Liveness_Intervals) in
33 // preparation. Results are assigned to Variable::RegNum for each 64 // preparation. Results are assigned to Variable::RegNum for each
34 // Variable. 65 // Variable.
35 void LinearScan::scan(const llvm::SmallBitVector &RegMaskFull) { 66 void LinearScan::scan(const llvm::SmallBitVector &RegMaskFull) {
36 assert(RegMaskFull.any()); // Sanity check 67 assert(RegMaskFull.any()); // Sanity check
37 Unhandled.clear(); 68 Unhandled.clear();
38 Handled.clear(); 69 Handled.clear();
39 Inactive.clear(); 70 Inactive.clear();
40 Active.clear(); 71 Active.clear();
41 Ostream &Str = Func->getContext()->getStrDump(); 72 Ostream &Str = Func->getContext()->getStrDump();
42 Func->resetCurrentNode(); 73 Func->resetCurrentNode();
74 VariablesMetadata *VMetadata = Func->getVMetadata();
43 75
44 // Gather the live ranges of all variables and add them to the 76 // Gather the live ranges of all variables and add them to the
45 // Unhandled set. TODO: Unhandled is a set<> which is based on a 77 // Unhandled set. TODO: Unhandled is a set<> which is based on a
46 // balanced binary tree, so inserting live ranges for N variables is 78 // balanced binary tree, so inserting live ranges for N variables is
47 // O(N log N) complexity. N may be proportional to the number of 79 // O(N log N) complexity. N may be proportional to the number of
48 // instructions, thanks to temporary generation during lowering. As 80 // instructions, thanks to temporary generation during lowering. As
49 // a result, it may be useful to design a better data structure for 81 // a result, it may be useful to design a better data structure for
50 // storing Func->getVariables(). 82 // storing Func->getVariables().
51 const VarList &Vars = Func->getVariables(); 83 const VarList &Vars = Func->getVariables();
52 for (VarList::const_iterator I = Vars.begin(), E = Vars.end(); I != E; ++I) { 84 for (VarList::const_iterator I = Vars.begin(), E = Vars.end(); I != E; ++I) {
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
178 } 210 }
179 } 211 }
180 212
181 // Calculate available registers into Free[]. 213 // Calculate available registers into Free[].
182 llvm::SmallBitVector Free = RegMask; 214 llvm::SmallBitVector Free = RegMask;
183 for (SizeT i = 0; i < RegMask.size(); ++i) { 215 for (SizeT i = 0; i < RegMask.size(); ++i) {
184 if (RegUses[i] > 0) 216 if (RegUses[i] > 0)
185 Free[i] = false; 217 Free[i] = false;
186 } 218 }
187 219
220 // Infer register preference and allowable overlap. Only form a
221 // preference when the current Variable has an unambiguous "first"
222 // definition. The preference is some source Variable of the
223 // defining instruction that either is assigned a register that is
224 // currently free, or that is assigned a register that is not free
225 // but overlap is allowed. Overlap is allowed when the Variable
226 // under consideration is single-definition, and its definition is
227 // a simple assignment - i.e., the register gets copied/aliased
228 // but is never modified. Furthermore, overlap is only allowed
229 // when preferred Variable definition instructions do not appear
230 // within the current Variable's live range.
231 Variable *Prefer = NULL;
232 int32_t PreferReg = Variable::NoRegister;
233 bool AllowOverlap = false;
234 if (const Inst *DefInst = VMetadata->getFirstDefinition(Cur.Var)) {
235 assert(DefInst->getDest() == Cur.Var);
236 bool IsAssign = DefInst->isSimpleAssign();
237 bool IsSingleDef = !VMetadata->isMultiDef(Cur.Var);
238 for (SizeT i = 0; i < DefInst->getSrcSize(); ++i) {
239 // TODO(stichnot): Iterate through the actual Variables of the
240 // instruction, not just the source operands. This could
241 // capture Load instructions, including address mode
242 // optimization, for Prefer (but not for AllowOverlap).
243 if (Variable *SrcVar = llvm::dyn_cast<Variable>(DefInst->getSrc(i))) {
244 int32_t SrcReg = SrcVar->getRegNumTmp();
245 // Only consider source variables that have (so far) been
246 // assigned a register. That register must be one in the
247 // RegMask set, e.g. don't try to prefer the stack pointer
248 // as a result of the stacksave intrinsic.
249 if (SrcVar->hasRegTmp() && RegMask[SrcReg]) {
250 if (!Free[SrcReg]) {
251 // Don't bother trying to enable AllowOverlap if the
252 // register is already free.
253 AllowOverlap =
254 IsSingleDef && IsAssign && !overlapsDefs(Func, Cur, SrcVar);
255 }
256 if (AllowOverlap || Free[SrcReg]) {
257 Prefer = SrcVar;
258 PreferReg = SrcReg;
259 }
260 }
261 }
262 }
263 }
264 if (Func->getContext()->isVerbose(IceV_LinearScan)) {
265 if (Prefer) {
266 Str << "Initial Prefer=" << *Prefer << " R=" << PreferReg
267 << " LIVE=" << Prefer->getLiveRange() << " Overlap=" << AllowOverlap
268 << "\n";
269 }
270 }
271
188 // Remove registers from the Free[] list where an Inactive range 272 // Remove registers from the Free[] list where an Inactive range
189 // overlaps with the current range. 273 // overlaps with the current range.
190 for (UnorderedRanges::const_iterator I = Inactive.begin(), 274 for (UnorderedRanges::const_iterator I = Inactive.begin(),
191 E = Inactive.end(); 275 E = Inactive.end();
192 I != E; ++I) { 276 I != E; ++I) {
193 LiveRangeWrapper Item = *I; 277 LiveRangeWrapper Item = *I;
194 if (Item.overlaps(Cur)) { 278 if (Item.overlaps(Cur)) {
195 int32_t RegNum = Item.Var->getRegNumTmp(); 279 int32_t RegNum = Item.Var->getRegNumTmp();
196 // Don't assert(Free[RegNum]) because in theory (though 280 // Don't assert(Free[RegNum]) because in theory (though
197 // probably never in practice) there could be two inactive 281 // probably never in practice) there could be two inactive
198 // variables that were allowed marked with 282 // variables that were allowed marked with
199 // AllowRegisterOverlap. 283 // AllowRegisterOverlap.
200 Free[RegNum] = false; 284 Free[RegNum] = false;
285 // Disable AllowOverlap if an Inactive variable, which is not
286 // Prefer, shares Prefer's register, and has a definition
287 // within Cur's live range.
288 if (AllowOverlap && Item.Var != Prefer && RegNum == PreferReg &&
289 overlapsDefs(Func, Cur, Item.Var)) {
290 AllowOverlap = false;
291 dumpDisableOverlap(Func, Item.Var, "Inactive");
292 }
201 } 293 }
202 } 294 }
203 295
296 // Disable AllowOverlap if an Active variable, which is not
297 // Prefer, shares Prefer's register, and has a definition within
298 // Cur's live range.
299 for (UnorderedRanges::iterator I = Active.begin(), E = Active.end();
300 AllowOverlap && I != E; ++I) {
301 LiveRangeWrapper Item = *I;
302 int32_t RegNum = Item.Var->getRegNumTmp();
303 if (Item.Var != Prefer && RegNum == PreferReg &&
304 overlapsDefs(Func, Cur, Item.Var)) {
305 AllowOverlap = false;
306 dumpDisableOverlap(Func, Item.Var, "Active");
307 }
308 }
309
204 // Remove registers from the Free[] list where an Unhandled range 310 // Remove registers from the Free[] list where an Unhandled range
205 // overlaps with the current range and is precolored. 311 // overlaps with the current range and is precolored.
206 // Cur.endsBefore(*I) is an early exit check that turns a 312 // Cur.endsBefore(*I) is an early exit check that turns a
207 // guaranteed O(N^2) algorithm into expected linear complexity. 313 // guaranteed O(N^2) algorithm into expected linear complexity.
208 llvm::SmallBitVector PrecoloredUnhandled(RegMask.size()); 314 llvm::SmallBitVector PrecoloredUnhandled(RegMask.size());
315 // Note: PrecoloredUnhandled is only used for dumping.
209 for (OrderedRanges::const_iterator I = Unhandled.begin(), 316 for (OrderedRanges::const_iterator I = Unhandled.begin(),
210 E = Unhandled.end(); 317 E = Unhandled.end();
211 I != E && !Cur.endsBefore(*I); ++I) { 318 I != E && !Cur.endsBefore(*I); ++I) {
212 LiveRangeWrapper Item = *I; 319 LiveRangeWrapper Item = *I;
213 if (Item.Var->hasReg() && Item.overlaps(Cur)) { 320 if (Item.Var->hasReg() && Item.overlaps(Cur)) {
214 Free[Item.Var->getRegNum()] = false; // Note: getRegNum not getRegNumTmp 321 int32_t ItemReg = Item.Var->getRegNum(); // Note: not getRegNumTmp()
215 PrecoloredUnhandled[Item.Var->getRegNum()] = true; 322 Free[ItemReg] = false;
323 PrecoloredUnhandled[ItemReg] = true;
324 // Disable AllowOverlap if the preferred register is one of
325 // these precolored unhandled overlapping ranges.
326 if (AllowOverlap && ItemReg == PreferReg) {
327 AllowOverlap = false;
328 dumpDisableOverlap(Func, Item.Var, "PrecoloredUnhandled");
329 }
216 } 330 }
217 } 331 }
218 332
219 // Print info about physical register availability. 333 // Print info about physical register availability.
220 if (Func->getContext()->isVerbose(IceV_LinearScan)) { 334 if (Func->getContext()->isVerbose(IceV_LinearScan)) {
221 for (SizeT i = 0; i < RegMask.size(); ++i) { 335 for (SizeT i = 0; i < RegMask.size(); ++i) {
222 if (RegMask[i]) { 336 if (RegMask[i]) {
223 Str << Func->getTarget()->getRegName(i, IceType_i32) 337 Str << Func->getTarget()->getRegName(i, IceType_i32)
224 << "(U=" << RegUses[i] << ",F=" << Free[i] 338 << "(U=" << RegUses[i] << ",F=" << Free[i]
225 << ",P=" << PrecoloredUnhandled[i] << ") "; 339 << ",P=" << PrecoloredUnhandled[i] << ") ";
226 } 340 }
227 } 341 }
228 Str << "\n"; 342 Str << "\n";
229 } 343 }
230 344
231 Variable *Prefer = Cur.Var->getPreferredRegister(); 345 if (Prefer && (AllowOverlap || Free[PreferReg])) {
232 int32_t PreferReg = Prefer && Prefer->hasRegTmp() ? Prefer->getRegNumTmp()
233 : Variable::NoRegister;
234 bool AllowedToOverlap = Cur.Var->getRegisterOverlap() &&
235 PreferReg != Variable::NoRegister &&
236 RegMask[PreferReg] &&
237 !PrecoloredUnhandled[PreferReg];
238 if (PreferReg != Variable::NoRegister &&
239 (AllowedToOverlap || Free[PreferReg])) {
240 // First choice: a preferred register that is either free or is 346 // First choice: a preferred register that is either free or is
241 // allowed to overlap with its linked variable. 347 // allowed to overlap with its linked variable.
242 Cur.Var->setRegNumTmp(PreferReg); 348 Cur.Var->setRegNumTmp(PreferReg);
243 if (Func->getContext()->isVerbose(IceV_LinearScan)) { 349 if (Func->getContext()->isVerbose(IceV_LinearScan)) {
244 Str << "Preferring "; 350 Str << "Preferring ";
245 Cur.dump(Func); 351 Cur.dump(Func);
246 Str << "\n"; 352 Str << "\n";
247 } 353 }
248 assert(RegUses[PreferReg] >= 0); 354 assert(RegUses[PreferReg] >= 0);
249 ++RegUses[PreferReg]; 355 ++RegUses[PreferReg];
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after
469 } 575 }
470 Str << "++++++ Inactive:\n"; 576 Str << "++++++ Inactive:\n";
471 for (UnorderedRanges::const_iterator I = Inactive.begin(), E = Inactive.end(); 577 for (UnorderedRanges::const_iterator I = Inactive.begin(), E = Inactive.end();
472 I != E; ++I) { 578 I != E; ++I) {
473 I->dump(Func); 579 I->dump(Func);
474 Str << "\n"; 580 Str << "\n";
475 } 581 }
476 } 582 }
477 583
478 } // end of namespace Ice 584 } // end of namespace Ice
OLDNEW
« no previous file with comments | « src/IceOperand.cpp ('k') | src/IceTargetLoweringX8632.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698