RegAllocGreedy.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447
  1. //==- RegAllocGreedy.h ------- greedy register allocator ----------*-C++-*-==//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. // This file defines the RAGreedy function pass for register allocation in
  9. // optimized builds.
  10. //===----------------------------------------------------------------------===//
  11. #ifndef LLVM_CODEGEN_REGALLOCGREEDY_H_
  12. #define LLVM_CODEGEN_REGALLOCGREEDY_H_
  13. #include "InterferenceCache.h"
  14. #include "RegAllocBase.h"
  15. #include "RegAllocEvictionAdvisor.h"
  16. #include "RegAllocPriorityAdvisor.h"
  17. #include "SpillPlacement.h"
  18. #include "SplitKit.h"
  19. #include "llvm/ADT/ArrayRef.h"
  20. #include "llvm/ADT/BitVector.h"
  21. #include "llvm/ADT/DenseMap.h"
  22. #include "llvm/ADT/IndexedMap.h"
  23. #include "llvm/ADT/SetVector.h"
  24. #include "llvm/ADT/SmallPtrSet.h"
  25. #include "llvm/ADT/SmallVector.h"
  26. #include "llvm/ADT/StringRef.h"
  27. #include "llvm/CodeGen/CalcSpillWeights.h"
  28. #include "llvm/CodeGen/LiveInterval.h"
  29. #include "llvm/CodeGen/LiveRangeEdit.h"
  30. #include "llvm/CodeGen/MachineFunction.h"
  31. #include "llvm/CodeGen/MachineFunctionPass.h"
  32. #include "llvm/CodeGen/RegisterClassInfo.h"
  33. #include "llvm/CodeGen/Spiller.h"
  34. #include "llvm/CodeGen/TargetRegisterInfo.h"
  35. #include <algorithm>
  36. #include <cstdint>
  37. #include <memory>
  38. #include <queue>
  39. #include <utility>
  40. namespace llvm {
  41. class AllocationOrder;
  42. class AnalysisUsage;
  43. class EdgeBundles;
  44. class LiveDebugVariables;
  45. class LiveIntervals;
  46. class LiveRegMatrix;
  47. class MachineBasicBlock;
  48. class MachineBlockFrequencyInfo;
  49. class MachineDominatorTree;
  50. class MachineLoop;
  51. class MachineLoopInfo;
  52. class MachineOptimizationRemarkEmitter;
  53. class MachineOptimizationRemarkMissed;
  54. class SlotIndexes;
  55. class TargetInstrInfo;
  56. class VirtRegMap;
  57. class LLVM_LIBRARY_VISIBILITY RAGreedy : public MachineFunctionPass,
  58. public RegAllocBase,
  59. private LiveRangeEdit::Delegate {
  60. // Interface to eviction advisers
  61. public:
  62. /// Track allocation stage and eviction loop prevention during allocation.
  63. class ExtraRegInfo final {
  64. // RegInfo - Keep additional information about each live range.
  65. struct RegInfo {
  66. LiveRangeStage Stage = RS_New;
  67. // Cascade - Eviction loop prevention. See
  68. // canEvictInterferenceBasedOnCost().
  69. unsigned Cascade = 0;
  70. RegInfo() = default;
  71. };
  72. IndexedMap<RegInfo, VirtReg2IndexFunctor> Info;
  73. unsigned NextCascade = 1;
  74. public:
  75. ExtraRegInfo() {}
  76. ExtraRegInfo(const ExtraRegInfo &) = delete;
  77. LiveRangeStage getStage(Register Reg) const { return Info[Reg].Stage; }
  78. LiveRangeStage getStage(const LiveInterval &VirtReg) const {
  79. return getStage(VirtReg.reg());
  80. }
  81. void setStage(Register Reg, LiveRangeStage Stage) {
  82. Info.grow(Reg.id());
  83. Info[Reg].Stage = Stage;
  84. }
  85. void setStage(const LiveInterval &VirtReg, LiveRangeStage Stage) {
  86. setStage(VirtReg.reg(), Stage);
  87. }
  88. /// Return the current stage of the register, if present, otherwise
  89. /// initialize it and return that.
  90. LiveRangeStage getOrInitStage(Register Reg) {
  91. Info.grow(Reg.id());
  92. return getStage(Reg);
  93. }
  94. unsigned getCascade(Register Reg) const { return Info[Reg].Cascade; }
  95. void setCascade(Register Reg, unsigned Cascade) {
  96. Info.grow(Reg.id());
  97. Info[Reg].Cascade = Cascade;
  98. }
  99. unsigned getOrAssignNewCascade(Register Reg) {
  100. unsigned Cascade = getCascade(Reg);
  101. if (!Cascade) {
  102. Cascade = NextCascade++;
  103. setCascade(Reg, Cascade);
  104. }
  105. return Cascade;
  106. }
  107. unsigned getCascadeOrCurrentNext(Register Reg) const {
  108. unsigned Cascade = getCascade(Reg);
  109. if (!Cascade)
  110. Cascade = NextCascade;
  111. return Cascade;
  112. }
  113. template <typename Iterator>
  114. void setStage(Iterator Begin, Iterator End, LiveRangeStage NewStage) {
  115. for (; Begin != End; ++Begin) {
  116. Register Reg = *Begin;
  117. Info.grow(Reg.id());
  118. if (Info[Reg].Stage == RS_New)
  119. Info[Reg].Stage = NewStage;
  120. }
  121. }
  122. void LRE_DidCloneVirtReg(Register New, Register Old);
  123. };
  124. LiveRegMatrix *getInterferenceMatrix() const { return Matrix; }
  125. LiveIntervals *getLiveIntervals() const { return LIS; }
  126. VirtRegMap *getVirtRegMap() const { return VRM; }
  127. const RegisterClassInfo &getRegClassInfo() const { return RegClassInfo; }
  128. const ExtraRegInfo &getExtraInfo() const { return *ExtraInfo; }
  129. size_t getQueueSize() const { return Queue.size(); }
  130. // end (interface to eviction advisers)
  131. // Interface to priority advisers
  132. bool getRegClassPriorityTrumpsGlobalness() const {
  133. return RegClassPriorityTrumpsGlobalness;
  134. }
  135. bool getReverseLocalAssignment() const { return ReverseLocalAssignment; }
  136. // end (interface to priority advisers)
  137. private:
  138. // Convenient shortcuts.
  139. using PQueue = std::priority_queue<std::pair<unsigned, unsigned>>;
  140. using SmallLISet = SmallSetVector<const LiveInterval *, 4>;
  141. // We need to track all tentative recolorings so we can roll back any
  142. // successful and unsuccessful recoloring attempts.
  143. using RecoloringStack =
  144. SmallVector<std::pair<const LiveInterval *, MCRegister>, 8>;
  145. // context
  146. MachineFunction *MF;
  147. // Shortcuts to some useful interface.
  148. const TargetInstrInfo *TII;
  149. // analyses
  150. SlotIndexes *Indexes;
  151. MachineBlockFrequencyInfo *MBFI;
  152. MachineDominatorTree *DomTree;
  153. MachineLoopInfo *Loops;
  154. MachineOptimizationRemarkEmitter *ORE;
  155. EdgeBundles *Bundles;
  156. SpillPlacement *SpillPlacer;
  157. LiveDebugVariables *DebugVars;
  158. // state
  159. std::unique_ptr<Spiller> SpillerInstance;
  160. PQueue Queue;
  161. std::unique_ptr<VirtRegAuxInfo> VRAI;
  162. std::optional<ExtraRegInfo> ExtraInfo;
  163. std::unique_ptr<RegAllocEvictionAdvisor> EvictAdvisor;
  164. std::unique_ptr<RegAllocPriorityAdvisor> PriorityAdvisor;
  165. // Enum CutOffStage to keep a track whether the register allocation failed
  166. // because of the cutoffs encountered in last chance recoloring.
  167. // Note: This is used as bitmask. New value should be next power of 2.
  168. enum CutOffStage {
  169. // No cutoffs encountered
  170. CO_None = 0,
  171. // lcr-max-depth cutoff encountered
  172. CO_Depth = 1,
  173. // lcr-max-interf cutoff encountered
  174. CO_Interf = 2
  175. };
  176. uint8_t CutOffInfo;
  177. #ifndef NDEBUG
  178. static const char *const StageName[];
  179. #endif
  180. // splitting state.
  181. std::unique_ptr<SplitAnalysis> SA;
  182. std::unique_ptr<SplitEditor> SE;
  183. /// Cached per-block interference maps
  184. InterferenceCache IntfCache;
  185. /// All basic blocks where the current register has uses.
  186. SmallVector<SpillPlacement::BlockConstraint, 8> SplitConstraints;
  187. /// Global live range splitting candidate info.
  188. struct GlobalSplitCandidate {
  189. // Register intended for assignment, or 0.
  190. MCRegister PhysReg;
  191. // SplitKit interval index for this candidate.
  192. unsigned IntvIdx;
  193. // Interference for PhysReg.
  194. InterferenceCache::Cursor Intf;
  195. // Bundles where this candidate should be live.
  196. BitVector LiveBundles;
  197. SmallVector<unsigned, 8> ActiveBlocks;
  198. void reset(InterferenceCache &Cache, MCRegister Reg) {
  199. PhysReg = Reg;
  200. IntvIdx = 0;
  201. Intf.setPhysReg(Cache, Reg);
  202. LiveBundles.clear();
  203. ActiveBlocks.clear();
  204. }
  205. // Set B[I] = C for every live bundle where B[I] was NoCand.
  206. unsigned getBundles(SmallVectorImpl<unsigned> &B, unsigned C) {
  207. unsigned Count = 0;
  208. for (unsigned I : LiveBundles.set_bits())
  209. if (B[I] == NoCand) {
  210. B[I] = C;
  211. Count++;
  212. }
  213. return Count;
  214. }
  215. };
  216. /// Candidate info for each PhysReg in AllocationOrder.
  217. /// This vector never shrinks, but grows to the size of the largest register
  218. /// class.
  219. SmallVector<GlobalSplitCandidate, 32> GlobalCand;
  220. enum : unsigned { NoCand = ~0u };
  221. /// Candidate map. Each edge bundle is assigned to a GlobalCand entry, or to
  222. /// NoCand which indicates the stack interval.
  223. SmallVector<unsigned, 32> BundleCand;
  224. /// Callee-save register cost, calculated once per machine function.
  225. BlockFrequency CSRCost;
  226. /// Set of broken hints that may be reconciled later because of eviction.
  227. SmallSetVector<const LiveInterval *, 8> SetOfBrokenHints;
  228. /// The register cost values. This list will be recreated for each Machine
  229. /// Function
  230. ArrayRef<uint8_t> RegCosts;
  231. /// Flags for the live range priority calculation, determined once per
  232. /// machine function.
  233. bool RegClassPriorityTrumpsGlobalness;
  234. bool ReverseLocalAssignment;
  235. public:
  236. RAGreedy(const RegClassFilterFunc F = allocateAllRegClasses);
  237. /// Return the pass name.
  238. StringRef getPassName() const override { return "Greedy Register Allocator"; }
  239. /// RAGreedy analysis usage.
  240. void getAnalysisUsage(AnalysisUsage &AU) const override;
  241. void releaseMemory() override;
  242. Spiller &spiller() override { return *SpillerInstance; }
  243. void enqueueImpl(const LiveInterval *LI) override;
  244. const LiveInterval *dequeue() override;
  245. MCRegister selectOrSplit(const LiveInterval &,
  246. SmallVectorImpl<Register> &) override;
  247. void aboutToRemoveInterval(const LiveInterval &) override;
  248. /// Perform register allocation.
  249. bool runOnMachineFunction(MachineFunction &mf) override;
  250. MachineFunctionProperties getRequiredProperties() const override {
  251. return MachineFunctionProperties().set(
  252. MachineFunctionProperties::Property::NoPHIs);
  253. }
  254. MachineFunctionProperties getClearedProperties() const override {
  255. return MachineFunctionProperties().set(
  256. MachineFunctionProperties::Property::IsSSA);
  257. }
  258. static char ID;
  259. private:
  260. MCRegister selectOrSplitImpl(const LiveInterval &,
  261. SmallVectorImpl<Register> &, SmallVirtRegSet &,
  262. RecoloringStack &, unsigned = 0);
  263. bool LRE_CanEraseVirtReg(Register) override;
  264. void LRE_WillShrinkVirtReg(Register) override;
  265. void LRE_DidCloneVirtReg(Register, Register) override;
  266. void enqueue(PQueue &CurQueue, const LiveInterval *LI);
  267. const LiveInterval *dequeue(PQueue &CurQueue);
  268. bool hasVirtRegAlloc();
  269. BlockFrequency calcSpillCost();
  270. bool addSplitConstraints(InterferenceCache::Cursor, BlockFrequency &);
  271. bool addThroughConstraints(InterferenceCache::Cursor, ArrayRef<unsigned>);
  272. bool growRegion(GlobalSplitCandidate &Cand);
  273. BlockFrequency calcGlobalSplitCost(GlobalSplitCandidate &,
  274. const AllocationOrder &Order);
  275. bool calcCompactRegion(GlobalSplitCandidate &);
  276. void splitAroundRegion(LiveRangeEdit &, ArrayRef<unsigned>);
  277. void calcGapWeights(MCRegister, SmallVectorImpl<float> &);
  278. void evictInterference(const LiveInterval &, MCRegister,
  279. SmallVectorImpl<Register> &);
  280. bool mayRecolorAllInterferences(MCRegister PhysReg,
  281. const LiveInterval &VirtReg,
  282. SmallLISet &RecoloringCandidates,
  283. const SmallVirtRegSet &FixedRegisters);
  284. MCRegister tryAssign(const LiveInterval &, AllocationOrder &,
  285. SmallVectorImpl<Register> &, const SmallVirtRegSet &);
  286. MCRegister tryEvict(const LiveInterval &, AllocationOrder &,
  287. SmallVectorImpl<Register> &, uint8_t,
  288. const SmallVirtRegSet &);
  289. MCRegister tryRegionSplit(const LiveInterval &, AllocationOrder &,
  290. SmallVectorImpl<Register> &);
  291. /// Calculate cost of region splitting.
  292. unsigned calculateRegionSplitCost(const LiveInterval &VirtReg,
  293. AllocationOrder &Order,
  294. BlockFrequency &BestCost,
  295. unsigned &NumCands, bool IgnoreCSR);
  296. /// Perform region splitting.
  297. unsigned doRegionSplit(const LiveInterval &VirtReg, unsigned BestCand,
  298. bool HasCompact, SmallVectorImpl<Register> &NewVRegs);
  299. /// Check other options before using a callee-saved register for the first
  300. /// time.
  301. MCRegister tryAssignCSRFirstTime(const LiveInterval &VirtReg,
  302. AllocationOrder &Order, MCRegister PhysReg,
  303. uint8_t &CostPerUseLimit,
  304. SmallVectorImpl<Register> &NewVRegs);
  305. void initializeCSRCost();
  306. unsigned tryBlockSplit(const LiveInterval &, AllocationOrder &,
  307. SmallVectorImpl<Register> &);
  308. unsigned tryInstructionSplit(const LiveInterval &, AllocationOrder &,
  309. SmallVectorImpl<Register> &);
  310. unsigned tryLocalSplit(const LiveInterval &, AllocationOrder &,
  311. SmallVectorImpl<Register> &);
  312. unsigned trySplit(const LiveInterval &, AllocationOrder &,
  313. SmallVectorImpl<Register> &, const SmallVirtRegSet &);
  314. unsigned tryLastChanceRecoloring(const LiveInterval &, AllocationOrder &,
  315. SmallVectorImpl<Register> &,
  316. SmallVirtRegSet &, RecoloringStack &,
  317. unsigned);
  318. bool tryRecoloringCandidates(PQueue &, SmallVectorImpl<Register> &,
  319. SmallVirtRegSet &, RecoloringStack &, unsigned);
  320. void tryHintRecoloring(const LiveInterval &);
  321. void tryHintsRecoloring();
  322. /// Model the information carried by one end of a copy.
  323. struct HintInfo {
  324. /// The frequency of the copy.
  325. BlockFrequency Freq;
  326. /// The virtual register or physical register.
  327. Register Reg;
  328. /// Its currently assigned register.
  329. /// In case of a physical register Reg == PhysReg.
  330. MCRegister PhysReg;
  331. HintInfo(BlockFrequency Freq, Register Reg, MCRegister PhysReg)
  332. : Freq(Freq), Reg(Reg), PhysReg(PhysReg) {}
  333. };
  334. using HintsInfo = SmallVector<HintInfo, 4>;
  335. BlockFrequency getBrokenHintFreq(const HintsInfo &, MCRegister);
  336. void collectHintInfo(Register, HintsInfo &);
  337. /// Greedy RA statistic to remark.
  338. struct RAGreedyStats {
  339. unsigned Reloads = 0;
  340. unsigned FoldedReloads = 0;
  341. unsigned ZeroCostFoldedReloads = 0;
  342. unsigned Spills = 0;
  343. unsigned FoldedSpills = 0;
  344. unsigned Copies = 0;
  345. float ReloadsCost = 0.0f;
  346. float FoldedReloadsCost = 0.0f;
  347. float SpillsCost = 0.0f;
  348. float FoldedSpillsCost = 0.0f;
  349. float CopiesCost = 0.0f;
  350. bool isEmpty() {
  351. return !(Reloads || FoldedReloads || Spills || FoldedSpills ||
  352. ZeroCostFoldedReloads || Copies);
  353. }
  354. void add(RAGreedyStats other) {
  355. Reloads += other.Reloads;
  356. FoldedReloads += other.FoldedReloads;
  357. ZeroCostFoldedReloads += other.ZeroCostFoldedReloads;
  358. Spills += other.Spills;
  359. FoldedSpills += other.FoldedSpills;
  360. Copies += other.Copies;
  361. ReloadsCost += other.ReloadsCost;
  362. FoldedReloadsCost += other.FoldedReloadsCost;
  363. SpillsCost += other.SpillsCost;
  364. FoldedSpillsCost += other.FoldedSpillsCost;
  365. CopiesCost += other.CopiesCost;
  366. }
  367. void report(MachineOptimizationRemarkMissed &R);
  368. };
  369. /// Compute statistic for a basic block.
  370. RAGreedyStats computeStats(MachineBasicBlock &MBB);
  371. /// Compute and report statistic through a remark.
  372. RAGreedyStats reportStats(MachineLoop *L);
  373. /// Report the statistic for each loop.
  374. void reportStats();
  375. };
  376. } // namespace llvm
  377. #endif // #ifndef LLVM_CODEGEN_REGALLOCGREEDY_H_