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 /// \file | 10 /// \file |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |