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