OLD | NEW |
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 14 matching lines...) Expand all Loading... |
25 // Register Allocation in the Context of SSA Form and Register | 25 // Register Allocation in the Context of SSA Form and Register |
26 // Constraints" by Hanspeter Mössenböck and Michael Pfeiffer, | 26 // Constraints" by Hanspeter Mössenböck and Michael Pfeiffer, |
27 // ftp://ftp.ssw.uni-linz.ac.at/pub/Papers/Moe02.PDF . This | 27 // ftp://ftp.ssw.uni-linz.ac.at/pub/Papers/Moe02.PDF . This |
28 // implementation is modified to take affinity into account and allow | 28 // implementation is modified to take affinity into account and allow |
29 // two interfering variables to share the same register in certain | 29 // two interfering variables to share the same register in certain |
30 // cases. | 30 // cases. |
31 // | 31 // |
32 // Requires running Cfg::liveness(Liveness_RangesFull) in | 32 // Requires running Cfg::liveness(Liveness_RangesFull) in |
33 // preparation. Results are assigned to Variable::RegNum for each | 33 // preparation. Results are assigned to Variable::RegNum for each |
34 // Variable. | 34 // Variable. |
35 void LinearScan::scan(const llvm::SmallBitVector &RegMaskFull) { | 35 void LinearScan::scan(const llvm::SmallBitVector &RegMaskFull, |
| 36 bool Randomized) { |
36 assert(RegMaskFull.any()); // Sanity check | 37 assert(RegMaskFull.any()); // Sanity check |
37 Unhandled.clear(); | 38 Unhandled.clear(); |
38 Handled.clear(); | 39 Handled.clear(); |
39 Inactive.clear(); | 40 Inactive.clear(); |
40 Active.clear(); | 41 Active.clear(); |
41 Ostream &Str = Func->getContext()->getStrDump(); | 42 Ostream &Str = Func->getContext()->getStrDump(); |
42 Func->setCurrentNode(NULL); | 43 Func->setCurrentNode(NULL); |
| 44 const size_t NumRegisters = RegMaskFull.size(); |
| 45 llvm::SmallBitVector PreDefinedRegisters(NumRegisters); |
43 | 46 |
44 // Gather the live ranges of all variables and add them to the | 47 // 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 | 48 // Unhandled set. TODO: Unhandled is a set<> which is based on a |
46 // balanced binary tree, so inserting live ranges for N variables is | 49 // 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 | 50 // O(N log N) complexity. N may be proportional to the number of |
48 // instructions, thanks to temporary generation during lowering. As | 51 // instructions, thanks to temporary generation during lowering. As |
49 // a result, it may be useful to design a better data structure for | 52 // a result, it may be useful to design a better data structure for |
50 // storing Func->getVariables(). | 53 // storing Func->getVariables(). |
51 const VarList &Vars = Func->getVariables(); | 54 const VarList &Vars = Func->getVariables(); |
52 for (VarList::const_iterator I = Vars.begin(), E = Vars.end(); I != E; ++I) { | 55 for (VarList::const_iterator I = Vars.begin(), E = Vars.end(); I != E; ++I) { |
53 Variable *Var = *I; | 56 Variable *Var = *I; |
54 // Explicitly don't consider zero-weight variables, which are | 57 // Explicitly don't consider zero-weight variables, which are |
55 // meant to be spill slots. | 58 // meant to be spill slots. |
56 if (Var->getWeight() == RegWeight::Zero) | 59 if (Var->getWeight() == RegWeight::Zero) |
57 continue; | 60 continue; |
58 // Don't bother if the variable has a null live range, which means | 61 // Don't bother if the variable has a null live range, which means |
59 // it was never referenced. | 62 // it was never referenced. |
60 if (Var->getLiveRange().isEmpty()) | 63 if (Var->getLiveRange().isEmpty()) |
61 continue; | 64 continue; |
62 Unhandled.insert(LiveRangeWrapper(Var)); | 65 Unhandled.insert(LiveRangeWrapper(Var)); |
63 if (Var->hasReg()) { | 66 if (Var->hasReg()) { |
64 Var->setRegNumTmp(Var->getRegNum()); | 67 int32_t RegNum = Var->getRegNum(); |
| 68 Var->setRegNumTmp(RegNum); |
65 Var->setLiveRangeInfiniteWeight(); | 69 Var->setLiveRangeInfiniteWeight(); |
| 70 if (Var->getIsArg() || Var->getDefinition()) { |
| 71 PreDefinedRegisters[RegNum] = true; |
| 72 } |
66 } | 73 } |
67 } | 74 } |
68 | 75 |
69 // RegUses[I] is the number of live ranges (variables) that register | 76 // RegUses[I] is the number of live ranges (variables) that register |
70 // I is currently assigned to. It can be greater than 1 as a result | 77 // I is currently assigned to. It can be greater than 1 as a result |
71 // of Variable::AllowRegisterOverlap. | 78 // of Variable::AllowRegisterOverlap. |
72 std::vector<int> RegUses(RegMaskFull.size()); | 79 std::vector<int> RegUses(NumRegisters); |
73 // Unhandled is already set to all ranges in increasing order of | 80 // Unhandled is already set to all ranges in increasing order of |
74 // start points. | 81 // start points. |
75 assert(Active.empty()); | 82 assert(Active.empty()); |
76 assert(Inactive.empty()); | 83 assert(Inactive.empty()); |
77 assert(Handled.empty()); | 84 assert(Handled.empty()); |
78 UnorderedRanges::iterator Next; | 85 UnorderedRanges::iterator Next; |
79 | 86 |
80 while (!Unhandled.empty()) { | 87 while (!Unhandled.empty()) { |
81 LiveRangeWrapper Cur = *Unhandled.begin(); | 88 LiveRangeWrapper Cur = *Unhandled.begin(); |
82 Unhandled.erase(Unhandled.begin()); | 89 Unhandled.erase(Unhandled.begin()); |
(...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
390 } | 397 } |
391 for (UnorderedRanges::iterator I = Inactive.begin(), E = Inactive.end(); | 398 for (UnorderedRanges::iterator I = Inactive.begin(), E = Inactive.end(); |
392 I != E; I = Next) { | 399 I != E; I = Next) { |
393 Next = I; | 400 Next = I; |
394 ++Next; | 401 ++Next; |
395 Handled.push_back(*I); | 402 Handled.push_back(*I); |
396 Inactive.erase(I); | 403 Inactive.erase(I); |
397 } | 404 } |
398 dump(Func); | 405 dump(Func); |
399 | 406 |
400 // Finish up by assigning RegNumTmp->RegNum for each Variable. | 407 // TODO: Statically choose the size based on the target being |
| 408 // compiled. |
| 409 const size_t REGS_SIZE = 32; |
| 410 llvm::SmallVector<int32_t, REGS_SIZE> Permutation(NumRegisters); |
| 411 if (Randomized) { |
| 412 Func->getTarget()->makeRandomRegisterPermutation( |
| 413 Permutation, PreDefinedRegisters | ~RegMaskFull); |
| 414 } |
| 415 |
| 416 // Finish up by assigning RegNumTmp->RegNum (or a random permutation |
| 417 // thereof) for each Variable. |
401 for (UnorderedRanges::const_iterator I = Handled.begin(), E = Handled.end(); | 418 for (UnorderedRanges::const_iterator I = Handled.begin(), E = Handled.end(); |
402 I != E; ++I) { | 419 I != E; ++I) { |
403 LiveRangeWrapper Item = *I; | 420 Variable *Var = I->Var; |
404 int32_t RegNum = Item.Var->getRegNumTmp(); | 421 int32_t RegNum = Var->getRegNumTmp(); |
| 422 int32_t AssignedRegNum = RegNum; |
| 423 |
| 424 if (Randomized && Var->hasRegTmp() && !Var->hasReg()) { |
| 425 AssignedRegNum = Permutation[RegNum]; |
| 426 } |
405 if (Func->getContext()->isVerbose(IceV_LinearScan)) { | 427 if (Func->getContext()->isVerbose(IceV_LinearScan)) { |
406 if (!Item.Var->hasRegTmp()) { | 428 if (!Var->hasRegTmp()) { |
407 Str << "Not assigning "; | 429 Str << "Not assigning "; |
408 Item.Var->dump(Func); | 430 Var->dump(Func); |
409 Str << "\n"; | 431 Str << "\n"; |
410 } else { | 432 } else { |
411 Str << (RegNum == Item.Var->getRegNum() ? "Reassigning " : "Assigning ") | 433 Str << (RegNum == Var->getRegNum() ? "Reassigning " : "Assigning ") |
412 << Func->getTarget()->getRegName(RegNum, IceType_i32) << "(r" | 434 << Func->getTarget()->getRegName(AssignedRegNum, IceType_i32) |
413 << RegNum << ") to "; | 435 << "(r" << AssignedRegNum << ") to "; |
414 Item.Var->dump(Func); | 436 Var->dump(Func); |
415 Str << "\n"; | 437 Str << "\n"; |
416 } | 438 } |
417 } | 439 } |
418 Item.Var->setRegNum(Item.Var->getRegNumTmp()); | 440 Var->setRegNum(AssignedRegNum); |
419 } | 441 } |
420 | 442 |
421 // TODO: Consider running register allocation one more time, with | 443 // TODO: Consider running register allocation one more time, with |
422 // infinite registers, for two reasons. First, evicted live ranges | 444 // infinite registers, for two reasons. First, evicted live ranges |
423 // get a second chance for a register. Second, it allows coalescing | 445 // get a second chance for a register. Second, it allows coalescing |
424 // of stack slots. If there is no time budget for the second | 446 // of stack slots. If there is no time budget for the second |
425 // register allocation run, each unallocated variable just gets its | 447 // register allocation run, each unallocated variable just gets its |
426 // own slot. | 448 // own slot. |
427 // | 449 // |
428 // Another idea for coalescing stack slots is to initialize the | 450 // Another idea for coalescing stack slots is to initialize the |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
468 } | 490 } |
469 Str << "++++++ Inactive:\n"; | 491 Str << "++++++ Inactive:\n"; |
470 for (UnorderedRanges::const_iterator I = Inactive.begin(), E = Inactive.end(); | 492 for (UnorderedRanges::const_iterator I = Inactive.begin(), E = Inactive.end(); |
471 I != E; ++I) { | 493 I != E; ++I) { |
472 I->dump(Func); | 494 I->dump(Func); |
473 Str << "\n"; | 495 Str << "\n"; |
474 } | 496 } |
475 } | 497 } |
476 | 498 |
477 } // end of namespace Ice | 499 } // end of namespace Ice |
OLD | NEW |