RegAllocEvictionAdvisor.h 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. //===- RegAllocEvictionAdvisor.h - Interference resolution ------*- 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. #ifndef LLVM_CODEGEN_REGALLOCEVICTIONADVISOR_H
  9. #define LLVM_CODEGEN_REGALLOCEVICTIONADVISOR_H
  10. #include "llvm/ADT/ArrayRef.h"
  11. #include "llvm/ADT/SmallSet.h"
  12. #include "llvm/ADT/StringRef.h"
  13. #include "llvm/CodeGen/Register.h"
  14. #include "llvm/Config/llvm-config.h"
  15. #include "llvm/MC/MCRegister.h"
  16. #include "llvm/Pass.h"
  17. namespace llvm {
  18. class AllocationOrder;
  19. class LiveInterval;
  20. class LiveIntervals;
  21. class LiveRegMatrix;
  22. class MachineFunction;
  23. class MachineRegisterInfo;
  24. class RegisterClassInfo;
  25. class TargetRegisterInfo;
  26. class VirtRegMap;
  27. using SmallVirtRegSet = SmallSet<Register, 16>;
  28. // Live ranges pass through a number of stages as we try to allocate them.
  29. // Some of the stages may also create new live ranges:
  30. //
  31. // - Region splitting.
  32. // - Per-block splitting.
  33. // - Local splitting.
  34. // - Spilling.
  35. //
  36. // Ranges produced by one of the stages skip the previous stages when they are
  37. // dequeued. This improves performance because we can skip interference checks
  38. // that are unlikely to give any results. It also guarantees that the live
  39. // range splitting algorithm terminates, something that is otherwise hard to
  40. // ensure.
  41. enum LiveRangeStage {
  42. /// Newly created live range that has never been queued.
  43. RS_New,
  44. /// Only attempt assignment and eviction. Then requeue as RS_Split.
  45. RS_Assign,
  46. /// Attempt live range splitting if assignment is impossible.
  47. RS_Split,
  48. /// Attempt more aggressive live range splitting that is guaranteed to make
  49. /// progress. This is used for split products that may not be making
  50. /// progress.
  51. RS_Split2,
  52. /// Live range will be spilled. No more splitting will be attempted.
  53. RS_Spill,
  54. /// Live range is in memory. Because of other evictions, it might get moved
  55. /// in a register in the end.
  56. RS_Memory,
  57. /// There is nothing more we can do to this live range. Abort compilation
  58. /// if it can't be assigned.
  59. RS_Done
  60. };
  61. /// Cost of evicting interference - used by default advisor, and the eviction
  62. /// chain heuristic in RegAllocGreedy.
  63. // FIXME: this can be probably made an implementation detail of the default
  64. // advisor, if the eviction chain logic can be refactored.
  65. struct EvictionCost {
  66. unsigned BrokenHints = 0; ///< Total number of broken hints.
  67. float MaxWeight = 0; ///< Maximum spill weight evicted.
  68. EvictionCost() = default;
  69. bool isMax() const { return BrokenHints == ~0u; }
  70. void setMax() { BrokenHints = ~0u; }
  71. void setBrokenHints(unsigned NHints) { BrokenHints = NHints; }
  72. bool operator<(const EvictionCost &O) const {
  73. return std::tie(BrokenHints, MaxWeight) <
  74. std::tie(O.BrokenHints, O.MaxWeight);
  75. }
  76. };
  77. /// Interface to the eviction advisor, which is responsible for making a
  78. /// decision as to which live ranges should be evicted (if any).
  79. class RAGreedy;
  80. class RegAllocEvictionAdvisor {
  81. public:
  82. RegAllocEvictionAdvisor(const RegAllocEvictionAdvisor &) = delete;
  83. RegAllocEvictionAdvisor(RegAllocEvictionAdvisor &&) = delete;
  84. virtual ~RegAllocEvictionAdvisor() = default;
  85. /// Find a physical register that can be freed by evicting the FixedRegisters,
  86. /// or return NoRegister. The eviction decision is assumed to be correct (i.e.
  87. /// no fixed live ranges are evicted) and profitable.
  88. virtual MCRegister tryFindEvictionCandidate(
  89. const LiveInterval &VirtReg, const AllocationOrder &Order,
  90. uint8_t CostPerUseLimit, const SmallVirtRegSet &FixedRegisters) const = 0;
  91. /// Find out if we can evict the live ranges occupying the given PhysReg,
  92. /// which is a hint (preferred register) for VirtReg.
  93. virtual bool
  94. canEvictHintInterference(const LiveInterval &VirtReg, MCRegister PhysReg,
  95. const SmallVirtRegSet &FixedRegisters) const = 0;
  96. /// Returns true if the given \p PhysReg is a callee saved register and has
  97. /// not been used for allocation yet.
  98. bool isUnusedCalleeSavedReg(MCRegister PhysReg) const;
  99. protected:
  100. RegAllocEvictionAdvisor(const MachineFunction &MF, const RAGreedy &RA);
  101. Register canReassign(const LiveInterval &VirtReg, Register PrevReg) const;
  102. // Get the upper limit of elements in the given Order we need to analize.
  103. // TODO: is this heuristic, we could consider learning it.
  104. std::optional<unsigned> getOrderLimit(const LiveInterval &VirtReg,
  105. const AllocationOrder &Order,
  106. unsigned CostPerUseLimit) const;
  107. // Determine if it's worth trying to allocate this reg, given the
  108. // CostPerUseLimit
  109. // TODO: this is a heuristic component we could consider learning, too.
  110. bool canAllocatePhysReg(unsigned CostPerUseLimit, MCRegister PhysReg) const;
  111. const MachineFunction &MF;
  112. const RAGreedy &RA;
  113. LiveRegMatrix *const Matrix;
  114. LiveIntervals *const LIS;
  115. VirtRegMap *const VRM;
  116. MachineRegisterInfo *const MRI;
  117. const TargetRegisterInfo *const TRI;
  118. const RegisterClassInfo &RegClassInfo;
  119. const ArrayRef<uint8_t> RegCosts;
  120. /// Run or not the local reassignment heuristic. This information is
  121. /// obtained from the TargetSubtargetInfo.
  122. const bool EnableLocalReassign;
  123. };
  124. /// ImmutableAnalysis abstraction for fetching the Eviction Advisor. We model it
  125. /// as an analysis to decouple the user from the implementation insofar as
  126. /// dependencies on other analyses goes. The motivation for it being an
  127. /// immutable pass is twofold:
  128. /// - in the ML implementation case, the evaluator is stateless but (especially
  129. /// in the development mode) expensive to set up. With an immutable pass, we set
  130. /// it up once.
  131. /// - in the 'development' mode ML case, we want to capture the training log
  132. /// during allocation (this is a log of features encountered and decisions
  133. /// made), and then measure a score, potentially a few steps after allocation
  134. /// completes. So we need the properties of an immutable pass to keep the logger
  135. /// state around until we can make that measurement.
  136. ///
  137. /// Because we need to offer additional services in 'development' mode, the
  138. /// implementations of this analysis need to implement RTTI support.
  139. class RegAllocEvictionAdvisorAnalysis : public ImmutablePass {
  140. public:
  141. enum class AdvisorMode : int { Default, Release, Development };
  142. RegAllocEvictionAdvisorAnalysis(AdvisorMode Mode)
  143. : ImmutablePass(ID), Mode(Mode){};
  144. static char ID;
  145. /// Get an advisor for the given context (i.e. machine function, etc)
  146. virtual std::unique_ptr<RegAllocEvictionAdvisor>
  147. getAdvisor(const MachineFunction &MF, const RAGreedy &RA) = 0;
  148. AdvisorMode getAdvisorMode() const { return Mode; }
  149. virtual void logRewardIfNeeded(const MachineFunction &MF,
  150. llvm::function_ref<float()> GetReward){};
  151. protected:
  152. // This analysis preserves everything, and subclasses may have additional
  153. // requirements.
  154. void getAnalysisUsage(AnalysisUsage &AU) const override {
  155. AU.setPreservesAll();
  156. }
  157. private:
  158. StringRef getPassName() const override;
  159. const AdvisorMode Mode;
  160. };
  161. /// Specialization for the API used by the analysis infrastructure to create
  162. /// an instance of the eviction advisor.
  163. template <> Pass *callDefaultCtor<RegAllocEvictionAdvisorAnalysis>();
  164. RegAllocEvictionAdvisorAnalysis *createReleaseModeAdvisor();
  165. RegAllocEvictionAdvisorAnalysis *createDevelopmentModeAdvisor();
  166. // TODO: move to RegAllocEvictionAdvisor.cpp when we move implementation
  167. // out of RegAllocGreedy.cpp
  168. class DefaultEvictionAdvisor : public RegAllocEvictionAdvisor {
  169. public:
  170. DefaultEvictionAdvisor(const MachineFunction &MF, const RAGreedy &RA)
  171. : RegAllocEvictionAdvisor(MF, RA) {}
  172. private:
  173. MCRegister tryFindEvictionCandidate(const LiveInterval &,
  174. const AllocationOrder &, uint8_t,
  175. const SmallVirtRegSet &) const override;
  176. bool canEvictHintInterference(const LiveInterval &, MCRegister,
  177. const SmallVirtRegSet &) const override;
  178. bool canEvictInterferenceBasedOnCost(const LiveInterval &, MCRegister, bool,
  179. EvictionCost &,
  180. const SmallVirtRegSet &) const;
  181. bool shouldEvict(const LiveInterval &A, bool, const LiveInterval &B,
  182. bool) const;
  183. };
  184. } // namespace llvm
  185. #endif // LLVM_CODEGEN_REGALLOCEVICTIONADVISOR_H