| 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 "IceCfgNode.h" | 17 #include "IceCfgNode.h" |
| 18 #include "IceInst.h" | 18 #include "IceInst.h" |
| 19 #include "IceOperand.h" | 19 #include "IceOperand.h" |
| 20 #include "IceRegAlloc.h" | 20 #include "IceRegAlloc.h" |
| 21 #include "IceTargetLowering.h" | 21 #include "IceTargetLowering.h" |
| 22 | 22 |
| 23 namespace Ice { | 23 namespace Ice { |
| 24 | 24 |
| 25 namespace { | 25 namespace { |
| 26 | 26 |
| 27 // TODO(stichnot): Statically choose the size based on the target |
| 28 // being compiled. |
| 29 const size_t REGS_SIZE = 32; |
| 30 |
| 27 // Returns true if Var has any definitions within Item's live range. | 31 // Returns true if Var has any definitions within Item's live range. |
| 28 // TODO(stichnot): Consider trimming the Definitions list similar to | 32 // TODO(stichnot): Consider trimming the Definitions list similar to |
| 29 // how the live ranges are trimmed, since all the overlapsDefs() tests | 33 // how the live ranges are trimmed, since all the overlapsDefs() tests |
| 30 // are whether some variable's definitions overlap Cur, and trimming | 34 // are whether some variable's definitions overlap Cur, and trimming |
| 31 // is with respect Cur.start. Initial tests show no measurable | 35 // is with respect Cur.start. Initial tests show no measurable |
| 32 // performance difference, so we'll keep the code simple for now. | 36 // performance difference, so we'll keep the code simple for now. |
| 33 bool overlapsDefs(const Cfg *Func, const Variable *Item, const Variable *Var) { | 37 bool overlapsDefs(const Cfg *Func, const Variable *Item, const Variable *Var) { |
| 34 const bool UseTrimmed = true; | 38 const bool UseTrimmed = true; |
| 35 VariablesMetadata *VMetadata = Func->getVMetadata(); | 39 VariablesMetadata *VMetadata = Func->getVMetadata(); |
| 36 if (const Inst *FirstDef = VMetadata->getFirstDefinition(Var)) | 40 if (const Inst *FirstDef = VMetadata->getFirstDefinition(Var)) |
| (...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 273 } | 277 } |
| 274 } | 278 } |
| 275 | 279 |
| 276 // Build a LiveRange representing the Kills list. | 280 // Build a LiveRange representing the Kills list. |
| 277 LiveRange KillsRange(Kills); | 281 LiveRange KillsRange(Kills); |
| 278 KillsRange.untrim(); | 282 KillsRange.untrim(); |
| 279 | 283 |
| 280 // RegUses[I] is the number of live ranges (variables) that register | 284 // RegUses[I] is the number of live ranges (variables) that register |
| 281 // I is currently assigned to. It can be greater than 1 as a result | 285 // I is currently assigned to. It can be greater than 1 as a result |
| 282 // of AllowOverlap inference below. | 286 // of AllowOverlap inference below. |
| 283 std::vector<int> RegUses(NumRegisters); | 287 llvm::SmallVector<int, REGS_SIZE> RegUses(NumRegisters); |
| 284 // Unhandled is already set to all ranges in increasing order of | 288 // Unhandled is already set to all ranges in increasing order of |
| 285 // start points. | 289 // start points. |
| 286 assert(Active.empty()); | 290 assert(Active.empty()); |
| 287 assert(Inactive.empty()); | 291 assert(Inactive.empty()); |
| 288 assert(Handled.empty()); | 292 assert(Handled.empty()); |
| 289 const TargetLowering::RegSetMask RegsInclude = | 293 const TargetLowering::RegSetMask RegsInclude = |
| 290 TargetLowering::RegSet_CallerSave; | 294 TargetLowering::RegSet_CallerSave; |
| 291 const TargetLowering::RegSetMask RegsExclude = TargetLowering::RegSet_None; | 295 const TargetLowering::RegSetMask RegsExclude = TargetLowering::RegSet_None; |
| 292 const llvm::SmallBitVector KillsMask = | 296 const llvm::SmallBitVector KillsMask = |
| 293 Func->getTarget()->getRegisterSet(RegsInclude, RegsExclude); | 297 Func->getTarget()->getRegisterSet(RegsInclude, RegsExclude); |
| (...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 477 for (const Variable *Item : Active) { | 481 for (const Variable *Item : Active) { |
| 478 int32_t RegNum = Item->getRegNumTmp(); | 482 int32_t RegNum = Item->getRegNumTmp(); |
| 479 if (Item != Prefer && RegNum == PreferReg && | 483 if (Item != Prefer && RegNum == PreferReg && |
| 480 overlapsDefs(Func, Cur, Item)) { | 484 overlapsDefs(Func, Cur, Item)) { |
| 481 AllowOverlap = false; | 485 AllowOverlap = false; |
| 482 dumpDisableOverlap(Func, Item, "Active"); | 486 dumpDisableOverlap(Func, Item, "Active"); |
| 483 } | 487 } |
| 484 } | 488 } |
| 485 } | 489 } |
| 486 | 490 |
| 487 std::vector<RegWeight> Weights(RegMask.size()); | 491 llvm::SmallVector<RegWeight, REGS_SIZE> Weights(RegMask.size()); |
| 488 | 492 |
| 489 // Remove registers from the Free[] list where an Unhandled | 493 // Remove registers from the Free[] list where an Unhandled |
| 490 // precolored range overlaps with the current range, and set those | 494 // precolored range overlaps with the current range, and set those |
| 491 // registers to infinite weight so that they aren't candidates for | 495 // registers to infinite weight so that they aren't candidates for |
| 492 // eviction. Cur->rangeEndsBefore(Item) is an early exit check | 496 // eviction. Cur->rangeEndsBefore(Item) is an early exit check |
| 493 // that turns a guaranteed O(N^2) algorithm into expected linear | 497 // that turns a guaranteed O(N^2) algorithm into expected linear |
| 494 // complexity. | 498 // complexity. |
| 495 llvm::SmallBitVector PrecoloredUnhandledMask(RegMask.size()); | 499 llvm::SmallBitVector PrecoloredUnhandledMask(RegMask.size()); |
| 496 // Note: PrecoloredUnhandledMask is only used for dumping. | 500 // Note: PrecoloredUnhandledMask is only used for dumping. |
| 497 for (Variable *Item : reverse_range(UnhandledPrecolored)) { | 501 for (Variable *Item : reverse_range(UnhandledPrecolored)) { |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 659 } | 663 } |
| 660 // Move anything Active or Inactive to Handled for easier handling. | 664 // Move anything Active or Inactive to Handled for easier handling. |
| 661 for (Variable *I : Active) | 665 for (Variable *I : Active) |
| 662 Handled.push_back(I); | 666 Handled.push_back(I); |
| 663 Active.clear(); | 667 Active.clear(); |
| 664 for (Variable *I : Inactive) | 668 for (Variable *I : Inactive) |
| 665 Handled.push_back(I); | 669 Handled.push_back(I); |
| 666 Inactive.clear(); | 670 Inactive.clear(); |
| 667 dump(Func); | 671 dump(Func); |
| 668 | 672 |
| 669 // TODO(stichnot): Statically choose the size based on the target | |
| 670 // being compiled. | |
| 671 const size_t REGS_SIZE = 32; | |
| 672 llvm::SmallVector<int32_t, REGS_SIZE> Permutation(NumRegisters); | 673 llvm::SmallVector<int32_t, REGS_SIZE> Permutation(NumRegisters); |
| 673 if (Randomized) { | 674 if (Randomized) { |
| 674 Func->getTarget()->makeRandomRegisterPermutation( | 675 Func->getTarget()->makeRandomRegisterPermutation( |
| 675 Permutation, PreDefinedRegisters | ~RegMaskFull); | 676 Permutation, PreDefinedRegisters | ~RegMaskFull); |
| 676 } | 677 } |
| 677 | 678 |
| 678 // Finish up by assigning RegNumTmp->RegNum (or a random permutation | 679 // Finish up by assigning RegNumTmp->RegNum (or a random permutation |
| 679 // thereof) for each Variable. | 680 // thereof) for each Variable. |
| 680 for (Variable *Item : Handled) { | 681 for (Variable *Item : Handled) { |
| 681 int32_t RegNum = Item->getRegNumTmp(); | 682 int32_t RegNum = Item->getRegNumTmp(); |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 739 Str << "\n"; | 740 Str << "\n"; |
| 740 } | 741 } |
| 741 Str << "++++++ Inactive:\n"; | 742 Str << "++++++ Inactive:\n"; |
| 742 for (const Variable *Item : Inactive) { | 743 for (const Variable *Item : Inactive) { |
| 743 dumpLiveRange(Item, Func); | 744 dumpLiveRange(Item, Func); |
| 744 Str << "\n"; | 745 Str << "\n"; |
| 745 } | 746 } |
| 746 } | 747 } |
| 747 | 748 |
| 748 } // end of namespace Ice | 749 } // end of namespace Ice |
| OLD | NEW |