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

Side by Side Diff: src/IceRegAlloc.cpp

Issue 2172313002: Subzero : Live Range Splitting after initial Register Allocation (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Cleanup Created 4 years, 4 months 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
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 /// \file 10 /// \file
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
106 // analysis to have calculated live ranges. 106 // analysis to have calculated live ranges.
107 void LinearScan::initForGlobal() { 107 void LinearScan::initForGlobal() {
108 TimerMarker T(TimerStack::TT_initUnhandled, Func); 108 TimerMarker T(TimerStack::TT_initUnhandled, Func);
109 FindPreference = true; 109 FindPreference = true;
110 // For full register allocation, normally we want to enable FindOverlap 110 // For full register allocation, normally we want to enable FindOverlap
111 // (meaning we look for opportunities for two overlapping live ranges to 111 // (meaning we look for opportunities for two overlapping live ranges to
112 // safely share the same register). However, we disable it for phi-lowering 112 // safely share the same register). However, we disable it for phi-lowering
113 // register allocation since no overlap opportunities should be available and 113 // register allocation since no overlap opportunities should be available and
114 // it's more expensive to look for opportunities. 114 // it's more expensive to look for opportunities.
115 FindOverlap = (Kind != RAK_Phi); 115 FindOverlap = (Kind != RAK_Phi);
116 const VarList &Vars = Func->getVariables();
117 Unhandled.reserve(Vars.size()); 116 Unhandled.reserve(Vars.size());
118 UnhandledPrecolored.reserve(Vars.size()); 117 UnhandledPrecolored.reserve(Vars.size());
119 // Gather the live ranges of all variables and add them to the Unhandled set. 118 // Gather the live ranges of all variables and add them to the Unhandled set.
120 for (Variable *Var : Vars) { 119 for (Variable *Var : Vars) {
121 // Don't consider rematerializable variables. 120 // Don't consider rematerializable variables.
122 if (Var->isRematerializable()) 121 if (Var->isRematerializable())
123 continue; 122 continue;
124 // Explicitly don't consider zero-weight variables, which are meant to be 123 // Explicitly don't consider zero-weight variables, which are meant to be
125 // spill slots. 124 // spill slots.
126 if (Var->mustNotHaveReg()) 125 if (Var->mustNotHaveReg())
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
161 const DefUseErrorList &DefsWithoutUses, 160 const DefUseErrorList &DefsWithoutUses,
162 const DefUseErrorList &UsesBeforeDefs, 161 const DefUseErrorList &UsesBeforeDefs,
163 const CfgVector<InstNumberT> &LRBegin, 162 const CfgVector<InstNumberT> &LRBegin,
164 const CfgVector<InstNumberT> &LREnd) const { 163 const CfgVector<InstNumberT> &LREnd) const {
165 if (DefsWithoutUses.empty() && UsesBeforeDefs.empty()) 164 if (DefsWithoutUses.empty() && UsesBeforeDefs.empty())
166 return true; 165 return true;
167 166
168 if (!BuildDefs::dump()) 167 if (!BuildDefs::dump())
169 return false; 168 return false;
170 169
171 const VarList &Vars = Func->getVariables();
172 OstreamLocker L(Ctx); 170 OstreamLocker L(Ctx);
173 Ostream &Str = Ctx->getStrDump(); 171 Ostream &Str = Ctx->getStrDump();
174 for (SizeT VarNum : DefsWithoutUses) { 172 for (SizeT VarNum : DefsWithoutUses) {
175 Variable *Var = Vars[VarNum]; 173 Variable *Var = Vars[VarNum];
176 Str << "LR def without use, instruction " << LRBegin[VarNum] 174 Str << "LR def without use, instruction " << LRBegin[VarNum]
177 << ", variable " << Var->getName() << "\n"; 175 << ", variable " << Var->getName() << "\n";
178 } 176 }
179 for (SizeT VarNum : UsesBeforeDefs) { 177 for (SizeT VarNum : UsesBeforeDefs) {
180 Variable *Var = Vars[VarNum]; 178 Variable *Var = Vars[VarNum];
181 Str << "LR use before def, instruction " << LREnd[VarNum] << ", variable " 179 Str << "LR use before def, instruction " << LREnd[VarNum] << ", variable "
(...skipping 23 matching lines...) Expand all
205 // 203 //
206 // * Because live ranges are a single segment, the Inactive set will always be 204 // * Because live ranges are a single segment, the Inactive set will always be
207 // empty, and the live range trimming operation is unnecessary. 205 // empty, and the live range trimming operation is unnecessary.
208 // 206 //
209 // * Calculating overlap of single-segment live ranges could be optimized a bit. 207 // * Calculating overlap of single-segment live ranges could be optimized a bit.
210 void LinearScan::initForInfOnly() { 208 void LinearScan::initForInfOnly() {
211 TimerMarker T(TimerStack::TT_initUnhandled, Func); 209 TimerMarker T(TimerStack::TT_initUnhandled, Func);
212 FindPreference = false; 210 FindPreference = false;
213 FindOverlap = false; 211 FindOverlap = false;
214 SizeT NumVars = 0; 212 SizeT NumVars = 0;
215 const VarList &Vars = Func->getVariables();
216 213
217 // Iterate across all instructions and record the begin and end of the live 214 // Iterate across all instructions and record the begin and end of the live
218 // range for each variable that is pre-colored or infinite weight. 215 // range for each variable that is pre-colored or infinite weight.
219 CfgVector<InstNumberT> LRBegin(Vars.size(), Inst::NumberSentinel); 216 CfgVector<InstNumberT> LRBegin(Vars.size(), Inst::NumberSentinel);
220 CfgVector<InstNumberT> LREnd(Vars.size(), Inst::NumberSentinel); 217 CfgVector<InstNumberT> LREnd(Vars.size(), Inst::NumberSentinel);
221 DefUseErrorList DefsWithoutUses, UsesBeforeDefs; 218 DefUseErrorList DefsWithoutUses, UsesBeforeDefs;
222 for (CfgNode *Node : Func->getNodes()) { 219 for (CfgNode *Node : Func->getNodes()) {
223 for (Inst &Instr : Node->getInsts()) { 220 for (Inst &Instr : Node->getInsts()) {
224 if (Instr.isDeleted()) 221 if (Instr.isDeleted())
225 continue; 222 continue;
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
318 UnhandledPrecolored.push_back(Var); 315 UnhandledPrecolored.push_back(Var);
319 Unhandled.push_back(Var); 316 Unhandled.push_back(Var);
320 } 317 }
321 } 318 }
322 for (Variable *Var : Evicted) { 319 for (Variable *Var : Evicted) {
323 Var->untrimLiveRange(); 320 Var->untrimLiveRange();
324 Unhandled.push_back(Var); 321 Unhandled.push_back(Var);
325 } 322 }
326 } 323 }
327 324
328 void LinearScan::init(RegAllocKind Kind) { 325 void LinearScan::init(RegAllocKind Kind, CfgSet<Variable *> ExtraVars,
326 CfgSet<Variable *> ExcludeVars) {
329 this->Kind = Kind; 327 this->Kind = Kind;
330 Unhandled.clear(); 328 Unhandled.clear();
331 UnhandledPrecolored.clear(); 329 UnhandledPrecolored.clear();
332 Handled.clear(); 330 Handled.clear();
333 Inactive.clear(); 331 Inactive.clear();
334 Active.clear(); 332 Active.clear();
333 Vars.clear();
Jim Stichnoth 2016/07/29 17:04:07 You may want to do something like: Vars.reserve
manasijm 2016/08/01 22:20:04 Done.
334 for (auto *Var : Func->getVariables()) {
335 if (ExcludeVars.find(Var) == ExcludeVars.end())
Jim Stichnoth 2016/07/29 17:04:07 I haven't studied the code that manages ExtraVars
336 Vars.push_back(Var);
Jim Stichnoth 2016/07/29 17:04:07 I think we prefer emplace_back() instead of push_b
manasijm 2016/08/01 22:20:04 Done.
337 }
338 for (auto *ExtraVar : ExtraVars) {
Jim Stichnoth 2016/07/29 17:04:07 You might be able to do something more compact lik
manasijm 2016/08/01 22:20:04 Acknowledged.
339 Vars.push_back(ExtraVar);
340 }
335 341
336 SizeT NumRegs = Target->getNumRegisters(); 342 SizeT NumRegs = Target->getNumRegisters();
337 RegAliases.resize(NumRegs); 343 RegAliases.resize(NumRegs);
338 for (SizeT Reg = 0; Reg < NumRegs; ++Reg) { 344 for (SizeT Reg = 0; Reg < NumRegs; ++Reg) {
339 RegAliases[Reg] = &Target->getAliasesForRegister(RegNumT::fromInt(Reg)); 345 RegAliases[Reg] = &Target->getAliasesForRegister(RegNumT::fromInt(Reg));
340 } 346 }
341 347
342 switch (Kind) { 348 switch (Kind) {
343 case RAK_Unknown: 349 case RAK_Unknown:
344 llvm::report_fatal_error("Invalid RAK_Unknown"); 350 llvm::report_fatal_error("Invalid RAK_Unknown");
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
457 // Move Item from Active to Inactive list. 463 // Move Item from Active to Inactive list.
458 dumpLiveRangeTrace("Inactivating ", Item); 464 dumpLiveRangeTrace("Inactivating ", Item);
459 moveItem(Active, Index, Inactive); 465 moveItem(Active, Index, Inactive);
460 Moved = true; 466 Moved = true;
461 } 467 }
462 if (Moved) { 468 if (Moved) {
463 // Decrement Item from RegUses[]. 469 // Decrement Item from RegUses[].
464 assert(Item->hasRegTmp()); 470 assert(Item->hasRegTmp());
465 const auto &Aliases = *RegAliases[Item->getRegNumTmp()]; 471 const auto &Aliases = *RegAliases[Item->getRegNumTmp()];
466 for (RegNumT RegAlias : RegNumBVIter(Aliases)) { 472 for (RegNumT RegAlias : RegNumBVIter(Aliases)) {
467 --RegUses[RegAlias]; 473 if (SplittingMode) {
468 assert(RegUses[RegAlias] >= 0); 474 if (RegUses[RegAlias] > 0)
Jim Stichnoth 2016/07/29 17:04:07 This seems really suspicious, and I can't work out
manasijm 2016/08/01 22:20:04 Should have removed it before submitting. Thanks
475 --RegUses[RegAlias];
476 } else {
477 --RegUses[RegAlias];
478 assert(RegUses[RegAlias] >= 0);
479 }
469 } 480 }
470 } 481 }
471 } 482 }
472 } 483 }
473 484
474 void LinearScan::handleInactiveRangeExpiredOrReactivated(const Variable *Cur) { 485 void LinearScan::handleInactiveRangeExpiredOrReactivated(const Variable *Cur) {
475 for (SizeT I = Inactive.size(); I > 0; --I) { 486 for (SizeT I = Inactive.size(); I > 0; --I) {
476 const SizeT Index = I - 1; 487 const SizeT Index = I - 1;
477 Variable *Item = Inactive[Index]; 488 Variable *Item = Inactive[Index];
478 Item->trimLiveRange(Cur->getLiveRange().getStart()); 489 Item->trimLiveRange(Cur->getLiveRange().getStart());
(...skipping 476 matching lines...) Expand 10 before | Expand all | Expand 10 after
955 // First choice: a preferred register that is either free or is allowed to 966 // First choice: a preferred register that is either free or is allowed to
956 // overlap with its linked variable. 967 // overlap with its linked variable.
957 allocatePreferredRegister(Iter); 968 allocatePreferredRegister(Iter);
958 } else if (Iter.Free.any()) { 969 } else if (Iter.Free.any()) {
959 // Second choice: any free register. 970 // Second choice: any free register.
960 constexpr bool Filtered = true; 971 constexpr bool Filtered = true;
961 allocateFreeRegister(Iter, Filtered); 972 allocateFreeRegister(Iter, Filtered);
962 } else { 973 } else {
963 // Fallback: there are no free registers, so we look for the lowest-weight 974 // Fallback: there are no free registers, so we look for the lowest-weight
964 // register and see if Cur has higher weight. 975 // register and see if Cur has higher weight.
965 handleNoFreeRegisters(Iter); 976 if (!SplittingMode)
manasijm 2016/08/01 22:20:04 This turned out to be unnecessary too.
977 handleNoFreeRegisters(Iter);
966 } 978 }
967 dump(Func); 979 dump(Func);
968 } 980 }
969 981
970 // Move anything Active or Inactive to Handled for easier handling. 982 // Move anything Active or Inactive to Handled for easier handling.
971 Handled.insert(Handled.end(), Active.begin(), Active.end()); 983 Handled.insert(Handled.end(), Active.begin(), Active.end());
972 Active.clear(); 984 Active.clear();
973 Handled.insert(Handled.end(), Inactive.begin(), Inactive.end()); 985 Handled.insert(Handled.end(), Inactive.begin(), Inactive.end());
974 Inactive.clear(); 986 Inactive.clear();
975 dump(Func); 987 dump(Func);
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
1018 Str << "\n"; 1030 Str << "\n";
1019 } 1031 }
1020 Str << "++++++ Inactive:\n"; 1032 Str << "++++++ Inactive:\n";
1021 for (const Variable *Item : Inactive) { 1033 for (const Variable *Item : Inactive) {
1022 dumpLiveRange(Item, Func); 1034 dumpLiveRange(Item, Func);
1023 Str << "\n"; 1035 Str << "\n";
1024 } 1036 }
1025 } 1037 }
1026 1038
1027 } // end of namespace Ice 1039 } // end of namespace Ice
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698