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

Side by Side Diff: src/IceRegAlloc.cpp

Issue 807293003: Subzero: Randomize register assignment. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Add a TODO Created 6 years 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/IceRegAlloc.h ('k') | src/IceTargetLowering.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
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
134 // * We don't need to renumber instructions before computing live 134 // * We don't need to renumber instructions before computing live
135 // ranges because all the high-level ICE instructions are deleted 135 // ranges because all the high-level ICE instructions are deleted
136 // prior to lowering, and the low-level instructions are added in 136 // prior to lowering, and the low-level instructions are added in
137 // monotonically increasing order. 137 // monotonically increasing order.
138 // 138 //
139 // * There are no opportunities for register preference or allowing 139 // * There are no opportunities for register preference or allowing
140 // overlap. 140 // overlap.
141 // 141 //
142 // Some properties we aren't (yet) taking advantage of: 142 // Some properties we aren't (yet) taking advantage of:
143 // 143 //
144 // * Because live ranges are a single segment, the Unhandled set will 144 // * Because live ranges are a single segment, the Inactive set will
145 // always be empty, and the live range trimming operation is 145 // always be empty, and the live range trimming operation is
146 // unnecessary. 146 // unnecessary.
147 // 147 //
148 // * Calculating overlap of single-segment live ranges could be 148 // * Calculating overlap of single-segment live ranges could be
149 // optimized a bit. 149 // optimized a bit.
150 void LinearScan::initForInfOnly() { 150 void LinearScan::initForInfOnly() {
151 TimerMarker T(TimerStack::TT_initUnhandled, Func); 151 TimerMarker T(TimerStack::TT_initUnhandled, Func);
152 FindPreference = false; 152 FindPreference = false;
153 FindOverlap = false; 153 FindOverlap = false;
154 SizeT NumVars = 0; 154 SizeT NumVars = 0;
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
251 // Register Allocation in the Context of SSA Form and Register 251 // Register Allocation in the Context of SSA Form and Register
252 // Constraints" by Hanspeter Mössenböck and Michael Pfeiffer, 252 // Constraints" by Hanspeter Mössenböck and Michael Pfeiffer,
253 // ftp://ftp.ssw.uni-linz.ac.at/pub/Papers/Moe02.PDF . This 253 // ftp://ftp.ssw.uni-linz.ac.at/pub/Papers/Moe02.PDF . This
254 // implementation is modified to take affinity into account and allow 254 // implementation is modified to take affinity into account and allow
255 // two interfering variables to share the same register in certain 255 // two interfering variables to share the same register in certain
256 // cases. 256 // cases.
257 // 257 //
258 // Requires running Cfg::liveness(Liveness_Intervals) in 258 // Requires running Cfg::liveness(Liveness_Intervals) in
259 // preparation. Results are assigned to Variable::RegNum for each 259 // preparation. Results are assigned to Variable::RegNum for each
260 // Variable. 260 // Variable.
261 void LinearScan::scan(const llvm::SmallBitVector &RegMaskFull) { 261 void LinearScan::scan(const llvm::SmallBitVector &RegMaskFull,
262 bool Randomized) {
262 TimerMarker T(TimerStack::TT_linearScan, Func); 263 TimerMarker T(TimerStack::TT_linearScan, Func);
263 assert(RegMaskFull.any()); // Sanity check 264 assert(RegMaskFull.any()); // Sanity check
264 Ostream &Str = Func->getContext()->getStrDump(); 265 Ostream &Str = Func->getContext()->getStrDump();
265 const bool Verbose = 266 const bool Verbose =
266 ALLOW_DUMP && Func->getContext()->isVerbose(IceV_LinearScan); 267 ALLOW_DUMP && Func->getContext()->isVerbose(IceV_LinearScan);
267 Func->resetCurrentNode(); 268 Func->resetCurrentNode();
268 VariablesMetadata *VMetadata = Func->getVMetadata(); 269 VariablesMetadata *VMetadata = Func->getVMetadata();
270 const size_t NumRegisters = RegMaskFull.size();
271 llvm::SmallBitVector PreDefinedRegisters(NumRegisters);
272 if (Randomized) {
273 for (Variable *Var : UnhandledPrecolored) {
274 PreDefinedRegisters[Var->getRegNum()] = true;
275 }
276 }
269 277
270 // Build a LiveRange representing the Kills list. 278 // Build a LiveRange representing the Kills list.
271 LiveRange KillsRange(Kills); 279 LiveRange KillsRange(Kills);
272 KillsRange.untrim(); 280 KillsRange.untrim();
273 281
274 // RegUses[I] is the number of live ranges (variables) that register 282 // RegUses[I] is the number of live ranges (variables) that register
275 // I is currently assigned to. It can be greater than 1 as a result 283 // I is currently assigned to. It can be greater than 1 as a result
276 // of AllowOverlap inference below. 284 // of AllowOverlap inference below.
277 std::vector<int> RegUses(RegMaskFull.size()); 285 std::vector<int> RegUses(NumRegisters);
278 // Unhandled is already set to all ranges in increasing order of 286 // Unhandled is already set to all ranges in increasing order of
279 // start points. 287 // start points.
280 assert(Active.empty()); 288 assert(Active.empty());
281 assert(Inactive.empty()); 289 assert(Inactive.empty());
282 assert(Handled.empty()); 290 assert(Handled.empty());
283 const TargetLowering::RegSetMask RegsInclude = 291 const TargetLowering::RegSetMask RegsInclude =
284 TargetLowering::RegSet_CallerSave; 292 TargetLowering::RegSet_CallerSave;
285 const TargetLowering::RegSetMask RegsExclude = TargetLowering::RegSet_None; 293 const TargetLowering::RegSetMask RegsExclude = TargetLowering::RegSet_None;
286 const llvm::SmallBitVector KillsMask = 294 const llvm::SmallBitVector KillsMask =
287 Func->getTarget()->getRegisterSet(RegsInclude, RegsExclude); 295 Func->getTarget()->getRegisterSet(RegsInclude, RegsExclude);
(...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after
655 } 663 }
656 // Move anything Active or Inactive to Handled for easier handling. 664 // Move anything Active or Inactive to Handled for easier handling.
657 for (Variable *I : Active) 665 for (Variable *I : Active)
658 Handled.push_back(I); 666 Handled.push_back(I);
659 Active.clear(); 667 Active.clear();
660 for (Variable *I : Inactive) 668 for (Variable *I : Inactive)
661 Handled.push_back(I); 669 Handled.push_back(I);
662 Inactive.clear(); 670 Inactive.clear();
663 dump(Func); 671 dump(Func);
664 672
665 // Finish up by assigning RegNumTmp->RegNum for each Variable. 673 // TODO(stichnot): Statically choose the size based on the target
674 // being compiled.
675 const size_t REGS_SIZE = 32;
676 llvm::SmallVector<int32_t, REGS_SIZE> Permutation(NumRegisters);
677 if (Randomized) {
678 Func->getTarget()->makeRandomRegisterPermutation(
679 Permutation, PreDefinedRegisters | ~RegMaskFull);
680 }
681
682 // Finish up by assigning RegNumTmp->RegNum (or a random permutation
683 // thereof) for each Variable.
666 for (Variable *Item : Handled) { 684 for (Variable *Item : Handled) {
667 int32_t RegNum = Item->getRegNumTmp(); 685 int32_t RegNum = Item->getRegNumTmp();
686 int32_t AssignedRegNum = RegNum;
687
688 if (Randomized && Item->hasRegTmp() && !Item->hasReg()) {
689 AssignedRegNum = Permutation[RegNum];
690 }
668 if (Verbose) { 691 if (Verbose) {
669 if (!Item->hasRegTmp()) { 692 if (!Item->hasRegTmp()) {
670 Str << "Not assigning "; 693 Str << "Not assigning ";
671 Item->dump(Func); 694 Item->dump(Func);
672 Str << "\n"; 695 Str << "\n";
673 } else { 696 } else {
674 Str << (RegNum == Item->getRegNum() ? "Reassigning " : "Assigning ") 697 Str << (AssignedRegNum == Item->getRegNum() ? "Reassigning "
675 << Func->getTarget()->getRegName(RegNum, IceType_i32) << "(r" 698 : "Assigning ")
676 << RegNum << ") to "; 699 << Func->getTarget()->getRegName(AssignedRegNum, IceType_i32)
700 << "(r" << AssignedRegNum << ") to ";
677 Item->dump(Func); 701 Item->dump(Func);
678 Str << "\n"; 702 Str << "\n";
679 } 703 }
680 } 704 }
681 Item->setRegNum(Item->getRegNumTmp()); 705 Item->setRegNum(AssignedRegNum);
682 } 706 }
683 707
684 // TODO: Consider running register allocation one more time, with 708 // TODO: Consider running register allocation one more time, with
685 // infinite registers, for two reasons. First, evicted live ranges 709 // infinite registers, for two reasons. First, evicted live ranges
686 // get a second chance for a register. Second, it allows coalescing 710 // get a second chance for a register. Second, it allows coalescing
687 // of stack slots. If there is no time budget for the second 711 // of stack slots. If there is no time budget for the second
688 // register allocation run, each unallocated variable just gets its 712 // register allocation run, each unallocated variable just gets its
689 // own slot. 713 // own slot.
690 // 714 //
691 // Another idea for coalescing stack slots is to initialize the 715 // Another idea for coalescing stack slots is to initialize the
(...skipping 27 matching lines...) Expand all
719 Str << "\n"; 743 Str << "\n";
720 } 744 }
721 Str << "++++++ Inactive:\n"; 745 Str << "++++++ Inactive:\n";
722 for (const Variable *Item : Inactive) { 746 for (const Variable *Item : Inactive) {
723 dumpLiveRange(Item, Func); 747 dumpLiveRange(Item, Func);
724 Str << "\n"; 748 Str << "\n";
725 } 749 }
726 } 750 }
727 751
728 } // end of namespace Ice 752 } // end of namespace Ice
OLDNEW
« no previous file with comments | « src/IceRegAlloc.h ('k') | src/IceTargetLowering.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698