MachineOutliner.h 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===---- MachineOutliner.h - Outliner data structures ------*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. ///
  14. /// \file
  15. /// Contains all data structures shared between the outliner implemented in
  16. /// MachineOutliner.cpp and target implementations of the outliner.
  17. ///
  18. //===----------------------------------------------------------------------===//
  19. #ifndef LLVM_CODEGEN_MACHINEOUTLINER_H
  20. #define LLVM_CODEGEN_MACHINEOUTLINER_H
  21. #include "llvm/CodeGen/LiveRegUnits.h"
  22. #include "llvm/CodeGen/MachineFunction.h"
  23. #include "llvm/CodeGen/MachineRegisterInfo.h"
  24. #include <initializer_list>
  25. namespace llvm {
  26. namespace outliner {
  27. /// Represents how an instruction should be mapped by the outliner.
  28. /// \p Legal instructions are those which are safe to outline.
  29. /// \p LegalTerminator instructions are safe to outline, but only as the
  30. /// last instruction in a sequence.
  31. /// \p Illegal instructions are those which cannot be outlined.
  32. /// \p Invisible instructions are instructions which can be outlined, but
  33. /// shouldn't actually impact the outlining result.
  34. enum InstrType { Legal, LegalTerminator, Illegal, Invisible };
  35. /// An individual sequence of instructions to be replaced with a call to
  36. /// an outlined function.
  37. struct Candidate {
  38. private:
  39. /// The start index of this \p Candidate in the instruction list.
  40. unsigned StartIdx = 0;
  41. /// The number of instructions in this \p Candidate.
  42. unsigned Len = 0;
  43. // The first instruction in this \p Candidate.
  44. MachineBasicBlock::iterator FirstInst;
  45. // The last instruction in this \p Candidate.
  46. MachineBasicBlock::iterator LastInst;
  47. // The basic block that contains this Candidate.
  48. MachineBasicBlock *MBB = nullptr;
  49. /// Cost of calling an outlined function from this point as defined by the
  50. /// target.
  51. unsigned CallOverhead = 0;
  52. /// Liveness information for this Candidate. Tracks from the end of the
  53. /// block containing this Candidate to the beginning of its sequence.
  54. ///
  55. /// Optional. Can be used to fine-tune the cost model, or fine-tune legality
  56. /// decisions.
  57. LiveRegUnits FromEndOfBlockToStartOfSeq;
  58. /// Liveness information restricted to this Candidate's instruction sequence.
  59. ///
  60. /// Optional. Can be used to fine-tune the cost model, or fine-tune legality
  61. /// decisions.
  62. LiveRegUnits InSeq;
  63. /// True if FromEndOfBlockToStartOfSeq has been initialized.
  64. bool FromEndOfBlockToStartOfSeqWasSet = false;
  65. /// True if InSeq has been initialized.
  66. bool InSeqWasSet = false;
  67. /// Populate FromEndOfBlockToStartOfSeq with liveness information.
  68. void initFromEndOfBlockToStartOfSeq(const TargetRegisterInfo &TRI) {
  69. assert(MBB->getParent()->getRegInfo().tracksLiveness() &&
  70. "Candidate's Machine Function must track liveness");
  71. // Only initialize once.
  72. if (FromEndOfBlockToStartOfSeqWasSet)
  73. return;
  74. FromEndOfBlockToStartOfSeqWasSet = true;
  75. FromEndOfBlockToStartOfSeq.init(TRI);
  76. FromEndOfBlockToStartOfSeq.addLiveOuts(*MBB);
  77. // Compute liveness from the end of the block up to the beginning of the
  78. // outlining candidate.
  79. for (auto &MI : make_range(MBB->rbegin(),
  80. (MachineBasicBlock::reverse_iterator)front()))
  81. FromEndOfBlockToStartOfSeq.stepBackward(MI);
  82. }
  83. /// Populate InSeq with liveness information.
  84. void initInSeq(const TargetRegisterInfo &TRI) {
  85. assert(MBB->getParent()->getRegInfo().tracksLiveness() &&
  86. "Candidate's Machine Function must track liveness");
  87. // Only initialize once.
  88. if (InSeqWasSet)
  89. return;
  90. InSeqWasSet = true;
  91. InSeq.init(TRI);
  92. for (auto &MI : make_range(front(), std::next(back())))
  93. InSeq.accumulate(MI);
  94. }
  95. public:
  96. /// The index of this \p Candidate's \p OutlinedFunction in the list of
  97. /// \p OutlinedFunctions.
  98. unsigned FunctionIdx = 0;
  99. /// Identifier denoting the instructions to emit to call an outlined function
  100. /// from this point. Defined by the target.
  101. unsigned CallConstructionID = 0;
  102. /// Target-specific flags for this Candidate's MBB.
  103. unsigned Flags = 0x0;
  104. /// Return the number of instructions in this Candidate.
  105. unsigned getLength() const { return Len; }
  106. /// Return the start index of this candidate.
  107. unsigned getStartIdx() const { return StartIdx; }
  108. /// Return the end index of this candidate.
  109. unsigned getEndIdx() const { return StartIdx + Len - 1; }
  110. /// Set the CallConstructionID and CallOverhead of this candidate to CID and
  111. /// CO respectively.
  112. void setCallInfo(unsigned CID, unsigned CO) {
  113. CallConstructionID = CID;
  114. CallOverhead = CO;
  115. }
  116. /// Returns the call overhead of this candidate if it is in the list.
  117. unsigned getCallOverhead() const { return CallOverhead; }
  118. MachineBasicBlock::iterator &front() { return FirstInst; }
  119. MachineBasicBlock::iterator &back() { return LastInst; }
  120. MachineFunction *getMF() const { return MBB->getParent(); }
  121. MachineBasicBlock *getMBB() const { return MBB; }
  122. /// \returns True if \p Reg is available from the end of the block to the
  123. /// beginning of the sequence.
  124. ///
  125. /// This query considers the following range:
  126. ///
  127. /// in_seq_1
  128. /// in_seq_2
  129. /// ...
  130. /// in_seq_n
  131. /// not_in_seq_1
  132. /// ...
  133. /// <end of block>
  134. bool isAvailableAcrossAndOutOfSeq(Register Reg,
  135. const TargetRegisterInfo &TRI) {
  136. if (!FromEndOfBlockToStartOfSeqWasSet)
  137. initFromEndOfBlockToStartOfSeq(TRI);
  138. return FromEndOfBlockToStartOfSeq.available(Reg);
  139. }
  140. /// \returns True if `isAvailableAcrossAndOutOfSeq` fails for any register
  141. /// in \p Regs.
  142. bool isAnyUnavailableAcrossOrOutOfSeq(std::initializer_list<Register> Regs,
  143. const TargetRegisterInfo &TRI) {
  144. if (!FromEndOfBlockToStartOfSeqWasSet)
  145. initFromEndOfBlockToStartOfSeq(TRI);
  146. return any_of(Regs, [&](Register Reg) {
  147. return !FromEndOfBlockToStartOfSeq.available(Reg);
  148. });
  149. }
  150. /// \returns True if \p Reg is available within the sequence itself.
  151. ///
  152. /// This query considers the following range:
  153. ///
  154. /// in_seq_1
  155. /// in_seq_2
  156. /// ...
  157. /// in_seq_n
  158. bool isAvailableInsideSeq(Register Reg, const TargetRegisterInfo &TRI) {
  159. if (!InSeqWasSet)
  160. initInSeq(TRI);
  161. return InSeq.available(Reg);
  162. }
  163. /// The number of instructions that would be saved by outlining every
  164. /// candidate of this type.
  165. ///
  166. /// This is a fixed value which is not updated during the candidate pruning
  167. /// process. It is only used for deciding which candidate to keep if two
  168. /// candidates overlap. The true benefit is stored in the OutlinedFunction
  169. /// for some given candidate.
  170. unsigned Benefit = 0;
  171. Candidate(unsigned StartIdx, unsigned Len,
  172. MachineBasicBlock::iterator &FirstInst,
  173. MachineBasicBlock::iterator &LastInst, MachineBasicBlock *MBB,
  174. unsigned FunctionIdx, unsigned Flags)
  175. : StartIdx(StartIdx), Len(Len), FirstInst(FirstInst), LastInst(LastInst),
  176. MBB(MBB), FunctionIdx(FunctionIdx), Flags(Flags) {}
  177. Candidate() = default;
  178. /// Used to ensure that \p Candidates are outlined in an order that
  179. /// preserves the start and end indices of other \p Candidates.
  180. bool operator<(const Candidate &RHS) const {
  181. return getStartIdx() > RHS.getStartIdx();
  182. }
  183. };
  184. /// The information necessary to create an outlined function for some
  185. /// class of candidate.
  186. struct OutlinedFunction {
  187. public:
  188. std::vector<Candidate> Candidates;
  189. /// The actual outlined function created.
  190. /// This is initialized after we go through and create the actual function.
  191. MachineFunction *MF = nullptr;
  192. /// Represents the size of a sequence in bytes. (Some instructions vary
  193. /// widely in size, so just counting the instructions isn't very useful.)
  194. unsigned SequenceSize = 0;
  195. /// Target-defined overhead of constructing a frame for this function.
  196. unsigned FrameOverhead = 0;
  197. /// Target-defined identifier for constructing a frame for this function.
  198. unsigned FrameConstructionID = 0;
  199. /// Return the number of candidates for this \p OutlinedFunction.
  200. unsigned getOccurrenceCount() const { return Candidates.size(); }
  201. /// Return the number of bytes it would take to outline this
  202. /// function.
  203. unsigned getOutliningCost() const {
  204. unsigned CallOverhead = 0;
  205. for (const Candidate &C : Candidates)
  206. CallOverhead += C.getCallOverhead();
  207. return CallOverhead + SequenceSize + FrameOverhead;
  208. }
  209. /// Return the size in bytes of the unoutlined sequences.
  210. unsigned getNotOutlinedCost() const {
  211. return getOccurrenceCount() * SequenceSize;
  212. }
  213. /// Return the number of instructions that would be saved by outlining
  214. /// this function.
  215. unsigned getBenefit() const {
  216. unsigned NotOutlinedCost = getNotOutlinedCost();
  217. unsigned OutlinedCost = getOutliningCost();
  218. return (NotOutlinedCost < OutlinedCost) ? 0
  219. : NotOutlinedCost - OutlinedCost;
  220. }
  221. /// Return the number of instructions in this sequence.
  222. unsigned getNumInstrs() const { return Candidates[0].getLength(); }
  223. OutlinedFunction(std::vector<Candidate> &Candidates, unsigned SequenceSize,
  224. unsigned FrameOverhead, unsigned FrameConstructionID)
  225. : Candidates(Candidates), SequenceSize(SequenceSize),
  226. FrameOverhead(FrameOverhead), FrameConstructionID(FrameConstructionID) {
  227. const unsigned B = getBenefit();
  228. for (Candidate &C : Candidates)
  229. C.Benefit = B;
  230. }
  231. OutlinedFunction() = default;
  232. };
  233. } // namespace outliner
  234. } // namespace llvm
  235. #endif
  236. #ifdef __GNUC__
  237. #pragma GCC diagnostic pop
  238. #endif