Chromium Code Reviews

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: Remove manual specification of prefer/overlap. Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff |
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 VariablesMetadata *VMetadata = Func->getVMetadata();
30 const InstDefList &Defs = VMetadata->getDefinitions(Var);
31 for (size_t i = 0; i < Defs.size(); ++i) {
32 if (Item.range().overlaps(Defs[i]->getNumber()))
33 return true;
34 }
35 return false;
36 }
37
38 } // end of anonymous namespace
39
24 // Implements the linear-scan algorithm. Based on "Linear Scan 40 // Implements the linear-scan algorithm. Based on "Linear Scan
25 // Register Allocation in the Context of SSA Form and Register 41 // Register Allocation in the Context of SSA Form and Register
26 // Constraints" by Hanspeter Mössenböck and Michael Pfeiffer, 42 // Constraints" by Hanspeter Mössenböck and Michael Pfeiffer,
27 // ftp://ftp.ssw.uni-linz.ac.at/pub/Papers/Moe02.PDF . This 43 // ftp://ftp.ssw.uni-linz.ac.at/pub/Papers/Moe02.PDF . This
28 // implementation is modified to take affinity into account and allow 44 // implementation is modified to take affinity into account and allow
29 // two interfering variables to share the same register in certain 45 // two interfering variables to share the same register in certain
30 // cases. 46 // cases.
31 // 47 //
32 // Requires running Cfg::liveness(Liveness_Intervals) in 48 // Requires running Cfg::liveness(Liveness_Intervals) in
33 // preparation. Results are assigned to Variable::RegNum for each 49 // preparation. Results are assigned to Variable::RegNum for each
34 // Variable. 50 // Variable.
35 void LinearScan::scan(const llvm::SmallBitVector &RegMaskFull) { 51 void LinearScan::scan(const llvm::SmallBitVector &RegMaskFull) {
36 assert(RegMaskFull.any()); // Sanity check 52 assert(RegMaskFull.any()); // Sanity check
37 Unhandled.clear(); 53 Unhandled.clear();
38 Handled.clear(); 54 Handled.clear();
39 Inactive.clear(); 55 Inactive.clear();
40 Active.clear(); 56 Active.clear();
41 Ostream &Str = Func->getContext()->getStrDump(); 57 Ostream &Str = Func->getContext()->getStrDump();
42 Func->resetCurrentNode(); 58 Func->resetCurrentNode();
59 VariablesMetadata *VMetadata = Func->getVMetadata();
43 60
44 // Gather the live ranges of all variables and add them to the 61 // 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 62 // Unhandled set. TODO: Unhandled is a set<> which is based on a
46 // balanced binary tree, so inserting live ranges for N variables is 63 // 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 64 // O(N log N) complexity. N may be proportional to the number of
48 // instructions, thanks to temporary generation during lowering. As 65 // instructions, thanks to temporary generation during lowering. As
49 // a result, it may be useful to design a better data structure for 66 // a result, it may be useful to design a better data structure for
50 // storing Func->getVariables(). 67 // storing Func->getVariables().
51 const VarList &Vars = Func->getVariables(); 68 const VarList &Vars = Func->getVariables();
52 for (VarList::const_iterator I = Vars.begin(), E = Vars.end(); I != E; ++I) { 69 for (VarList::const_iterator I = Vars.begin(), E = Vars.end(); I != E; ++I) {
(...skipping 125 matching lines...)
178 } 195 }
179 } 196 }
180 197
181 // Calculate available registers into Free[]. 198 // Calculate available registers into Free[].
182 llvm::SmallBitVector Free = RegMask; 199 llvm::SmallBitVector Free = RegMask;
183 for (SizeT i = 0; i < RegMask.size(); ++i) { 200 for (SizeT i = 0; i < RegMask.size(); ++i) {
184 if (RegUses[i] > 0) 201 if (RegUses[i] > 0)
185 Free[i] = false; 202 Free[i] = false;
186 } 203 }
187 204
205 // Infer register preference and allowable overlap. Only form a
206 // preference when the current Variable has an unambiguous "first"
207 // definition. The preference is some source Variable of the
208 // defining instruction that either is assigned a register that is
209 // currently free, or that is assigned a register that is not free
210 // but overlap is allowed. Overlap is allowed when the Variable
211 // under consideration is single-definition, and its definition is
212 // a simple assignment - i.e., the register gets copied/aliased
213 // but is never modified. Furthermore, overlap is only allowed
214 // when preferred Variable definition instructions do not appear
215 // within the current Variable's live range.
216 Variable *Prefer = NULL;
217 bool AllowedToOverlap = false;
218 if (const Inst *DefInst = VMetadata->getSingleDefinition(Cur.Var)) {
jvoung (off chromium) 2014/09/25 16:42:11 Was this meant to be getFirstDefinition() (based o
Jim Stichnoth 2014/09/25 18:13:55 Yeah, fixed.
219 assert(DefInst->getDest() == Cur.Var);
220 bool IsAssign = DefInst->isSimpleAssign();
221 bool IsSingleDef = !VMetadata->isMultiDef(Cur.Var);
222 for (SizeT i = 0; i < DefInst->getSrcSize(); ++i) {
223 if (Variable *SrcVar = llvm::dyn_cast<Variable>(DefInst->getSrc(i))) {
224 // The NoConflictingDefs condition is supposed to accurately
225 // represent this requirement: "overlap is only allowed when
226 // preferred Variable definition instructions do not appear
227 // within the current Variable's live range."
228 bool NoConflictingDefs = !overlapsDefs(Func, Cur, SrcVar);
229 int32_t SrcReg = SrcVar->getRegNumTmp();
230 if (SrcReg != Variable::NoRegister && RegMask[SrcReg]) {
jvoung (off chromium) 2014/09/25 16:42:11 Would it be better to check SrcReg != Variable::No
Jim Stichnoth 2014/09/25 18:13:55 Yes. That should be fixed in the latest patchset.
231 AllowedToOverlap = IsSingleDef && NoConflictingDefs && IsAssign;
232 if (AllowedToOverlap || Free[SrcReg])
jvoung (off chromium) 2014/09/25 16:42:11 Similar, would it be cheaper to check for Free[Src
Jim Stichnoth 2014/09/25 18:13:55 Hmm, I think you're right. The logs do show a lot
233 Prefer = SrcVar;
234 }
235 }
236 }
237 }
238 if (Func->getContext()->isVerbose(IceV_LinearScan)) {
239 if (Prefer) {
240 Str << "Initial Prefer=" << *Prefer << " R=" << Prefer->getRegNumTmp()
241 << " LIVE=" << Prefer->getLiveRange()
242 << " Overlap=" << AllowedToOverlap << "\n";
243 }
244 }
245
188 // Remove registers from the Free[] list where an Inactive range 246 // Remove registers from the Free[] list where an Inactive range
189 // overlaps with the current range. 247 // overlaps with the current range.
190 for (UnorderedRanges::const_iterator I = Inactive.begin(), 248 for (UnorderedRanges::const_iterator I = Inactive.begin(),
191 E = Inactive.end(); 249 E = Inactive.end();
192 I != E; ++I) { 250 I != E; ++I) {
193 LiveRangeWrapper Item = *I; 251 LiveRangeWrapper Item = *I;
194 if (Item.overlaps(Cur)) { 252 if (Item.overlaps(Cur)) {
195 int32_t RegNum = Item.Var->getRegNumTmp(); 253 int32_t RegNum = Item.Var->getRegNumTmp();
196 // Don't assert(Free[RegNum]) because in theory (though 254 // Don't assert(Free[RegNum]) because in theory (though
197 // probably never in practice) there could be two inactive 255 // probably never in practice) there could be two inactive
198 // variables that were allowed marked with 256 // variables that were allowed marked with
199 // AllowRegisterOverlap. 257 // AllowRegisterOverlap.
200 Free[RegNum] = false; 258 Free[RegNum] = false;
259 // If there is a variable on the inactive list, which is not
260 // Prefer, and overlaps with Cur, and shares Prefer's
261 // register, then disallow overlap.
262 if (AllowedToOverlap && Item.Var != Prefer &&
263 RegNum == Prefer->getRegNumTmp() && Item.overlaps(Cur)) {
264 AllowedToOverlap = false;
265 if (Func->getContext()->isVerbose(IceV_LinearScan)) {
266 Str << "Disabling Overlap due to Inactive " << *Item.Var
267 << " LIVE=" << Item.Var->getLiveRange() << "\n";
268 }
269 }
201 } 270 }
202 } 271 }
203 272
273 // Disable AllowOverlap if the preferred register is already used
274 // in an Active range (which by definition overlaps) that is not
275 // Prefer. TODO(stichnot): Actually only disable AllowOverlap if
276 // an Active variable with the preferred register has a definition
277 // within the current variable's live range.
278
279 // If there is a variable on the active list, which is not Prefer,
280 // and shares Prefer's register, and has a definition within Cur's
281 // live range, then disallow overlap.
282 for (UnorderedRanges::iterator I = Active.begin(), E = Active.end();
283 AllowedToOverlap && I != E; ++I) {
284 LiveRangeWrapper Item = *I;
285 int32_t RegNum = Item.Var->getRegNumTmp();
286 if (Item.Var != Prefer && RegNum == Prefer->getRegNumTmp() &&
287 overlapsDefs(Func, Cur, Item.Var)) {
288 AllowedToOverlap = false;
289 if (Func->getContext()->isVerbose(IceV_LinearScan)) {
290 Str << "Disabling Overlap due to Active " << *Item.Var
291 << " LIVE=" << Item.Var->getLiveRange() << "\n";
292 }
293 }
294 }
295
204 // Remove registers from the Free[] list where an Unhandled range 296 // Remove registers from the Free[] list where an Unhandled range
205 // overlaps with the current range and is precolored. 297 // overlaps with the current range and is precolored.
206 // Cur.endsBefore(*I) is an early exit check that turns a 298 // Cur.endsBefore(*I) is an early exit check that turns a
207 // guaranteed O(N^2) algorithm into expected linear complexity. 299 // guaranteed O(N^2) algorithm into expected linear complexity.
208 llvm::SmallBitVector PrecoloredUnhandled(RegMask.size()); 300 llvm::SmallBitVector PrecoloredUnhandled(RegMask.size());
209 for (OrderedRanges::const_iterator I = Unhandled.begin(), 301 for (OrderedRanges::const_iterator I = Unhandled.begin(),
210 E = Unhandled.end(); 302 E = Unhandled.end();
211 I != E && !Cur.endsBefore(*I); ++I) { 303 I != E && !Cur.endsBefore(*I); ++I) {
212 LiveRangeWrapper Item = *I; 304 LiveRangeWrapper Item = *I;
213 if (Item.Var->hasReg() && Item.overlaps(Cur)) { 305 if (Item.Var->hasReg() && Item.overlaps(Cur)) {
214 Free[Item.Var->getRegNum()] = false; // Note: getRegNum not getRegNumTmp 306 Free[Item.Var->getRegNum()] = false; // Note: getRegNum not getRegNumTmp
215 PrecoloredUnhandled[Item.Var->getRegNum()] = true; 307 PrecoloredUnhandled[Item.Var->getRegNum()] = true;
308 // Disallow overlap if the preferred register is one of these
309 // precolored unhandled overlapping ranges.
310 if (AllowedToOverlap && Prefer &&
jvoung (off chromium) 2014/09/25 16:42:11 nit: I think technically, the "&& Prefer" check is
Jim Stichnoth 2014/09/25 18:13:54 Done. I think I originally had that just to be ab
311 Item.Var->getRegNum() == Prefer->getRegNumTmp() &&
312 Cur.overlaps(Item)) {
313 AllowedToOverlap = false;
314 if (Func->getContext()->isVerbose(IceV_LinearScan)) {
315 Str << "Disabling Overlap due to UnhandledPrecolored " << *Item.Var
316 << " LIVE=" << Item.Var->getLiveRange() << "\n";
317 }
318 }
216 } 319 }
217 } 320 }
218 321
219 // Print info about physical register availability. 322 // Print info about physical register availability.
220 if (Func->getContext()->isVerbose(IceV_LinearScan)) { 323 if (Func->getContext()->isVerbose(IceV_LinearScan)) {
221 for (SizeT i = 0; i < RegMask.size(); ++i) { 324 for (SizeT i = 0; i < RegMask.size(); ++i) {
222 if (RegMask[i]) { 325 if (RegMask[i]) {
223 Str << Func->getTarget()->getRegName(i, IceType_i32) 326 Str << Func->getTarget()->getRegName(i, IceType_i32)
224 << "(U=" << RegUses[i] << ",F=" << Free[i] 327 << "(U=" << RegUses[i] << ",F=" << Free[i]
225 << ",P=" << PrecoloredUnhandled[i] << ") "; 328 << ",P=" << PrecoloredUnhandled[i] << ") ";
226 } 329 }
227 } 330 }
228 Str << "\n"; 331 Str << "\n";
229 } 332 }
230 333
231 Variable *Prefer = Cur.Var->getPreferredRegister(); 334 int32_t PreferReg = Variable::NoRegister;
232 int32_t PreferReg = Prefer && Prefer->hasRegTmp() ? Prefer->getRegNumTmp() 335 if (Prefer && Prefer->hasRegTmp())
233 : Variable::NoRegister; 336 PreferReg = Prefer->getRegNumTmp();
234 bool AllowedToOverlap = Cur.Var->getRegisterOverlap() &&
235 PreferReg != Variable::NoRegister &&
236 RegMask[PreferReg] &&
237 !PrecoloredUnhandled[PreferReg];
jvoung (off chromium) 2014/09/25 16:42:11 It now seems like PrecoloredUnhandled is no longer
Jim Stichnoth 2014/09/25 18:13:54 True. It's worth keeping for the diagnostics, so
238 if (PreferReg != Variable::NoRegister && 337 if (PreferReg != Variable::NoRegister &&
239 (AllowedToOverlap || Free[PreferReg])) { 338 (AllowedToOverlap || Free[PreferReg])) {
240 // First choice: a preferred register that is either free or is 339 // First choice: a preferred register that is either free or is
241 // allowed to overlap with its linked variable. 340 // allowed to overlap with its linked variable.
242 Cur.Var->setRegNumTmp(PreferReg); 341 Cur.Var->setRegNumTmp(PreferReg);
243 if (Func->getContext()->isVerbose(IceV_LinearScan)) { 342 if (Func->getContext()->isVerbose(IceV_LinearScan)) {
244 Str << "Preferring "; 343 Str << "Preferring ";
245 Cur.dump(Func); 344 Cur.dump(Func);
246 Str << "\n"; 345 Str << "\n";
247 } 346 }
(...skipping 221 matching lines...)
469 } 568 }
470 Str << "++++++ Inactive:\n"; 569 Str << "++++++ Inactive:\n";
471 for (UnorderedRanges::const_iterator I = Inactive.begin(), E = Inactive.end(); 570 for (UnorderedRanges::const_iterator I = Inactive.begin(), E = Inactive.end();
472 I != E; ++I) { 571 I != E; ++I) {
473 I->dump(Func); 572 I->dump(Func);
474 Str << "\n"; 573 Str << "\n";
475 } 574 }
476 } 575 }
477 576
478 } // end of namespace Ice 577 } // end of namespace Ice
OLDNEW

Powered by Google App Engine