IROutliner.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===- IROutliner.h - Extract similar IR regions into functions ------------==//
  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. // The interface file for the IROutliner which is used by the IROutliner Pass.
  16. //
  17. // The outliner uses the IRSimilarityIdentifier to identify the similar regions
  18. // of code. It evaluates each set of IRSimilarityCandidates with an estimate of
  19. // whether it will provide code size reduction. Each region is extracted using
  20. // the code extractor. These extracted functions are consolidated into a single
  21. // function and called from the extracted call site.
  22. //
  23. // For example:
  24. // \code
  25. // %1 = add i32 %a, %b
  26. // %2 = add i32 %b, %a
  27. // %3 = add i32 %b, %a
  28. // %4 = add i32 %a, %b
  29. // \endcode
  30. // would become function
  31. // \code
  32. // define internal void outlined_ir_function(i32 %0, i32 %1) {
  33. // %1 = add i32 %0, %1
  34. // %2 = add i32 %1, %0
  35. // ret void
  36. // }
  37. // \endcode
  38. // with calls:
  39. // \code
  40. // call void outlined_ir_function(i32 %a, i32 %b)
  41. // call void outlined_ir_function(i32 %b, i32 %a)
  42. // \endcode
  43. //
  44. //===----------------------------------------------------------------------===//
  45. #ifndef LLVM_TRANSFORMS_IPO_IROUTLINER_H
  46. #define LLVM_TRANSFORMS_IPO_IROUTLINER_H
  47. #include "llvm/Analysis/IRSimilarityIdentifier.h"
  48. #include "llvm/IR/PassManager.h"
  49. #include "llvm/IR/ValueMap.h"
  50. #include "llvm/Support/InstructionCost.h"
  51. #include "llvm/Transforms/Utils/CodeExtractor.h"
  52. #include <set>
  53. struct OutlinableGroup;
  54. namespace llvm {
  55. using namespace IRSimilarity;
  56. class Module;
  57. class TargetTransformInfo;
  58. class OptimizationRemarkEmitter;
  59. /// The OutlinableRegion holds all the information for a specific region, or
  60. /// sequence of instructions. This includes what values need to be hoisted to
  61. /// arguments from the extracted function, inputs and outputs to the region, and
  62. /// mapping from the extracted function arguments to overall function arguments.
  63. struct OutlinableRegion {
  64. /// Describes the region of code.
  65. IRSimilarityCandidate *Candidate = nullptr;
  66. /// If this region is outlined, the front and back IRInstructionData could
  67. /// potentially become invalidated if the only new instruction is a call.
  68. /// This ensures that we replace in the instruction in the IRInstructionData.
  69. IRInstructionData *NewFront = nullptr;
  70. IRInstructionData *NewBack = nullptr;
  71. /// The number of extracted inputs from the CodeExtractor.
  72. unsigned NumExtractedInputs = 0;
  73. /// The corresponding BasicBlock with the appropriate stores for this
  74. /// OutlinableRegion in the overall function.
  75. unsigned OutputBlockNum = -1;
  76. /// Mapping the extracted argument number to the argument number in the
  77. /// overall function. Since there will be inputs, such as elevated constants
  78. /// that are not the same in each region in a SimilarityGroup, or values that
  79. /// cannot be sunk into the extracted section in every region, we must keep
  80. /// track of which extracted argument maps to which overall argument.
  81. DenseMap<unsigned, unsigned> ExtractedArgToAgg;
  82. DenseMap<unsigned, unsigned> AggArgToExtracted;
  83. /// Marks whether we need to change the order of the arguments when mapping
  84. /// the old extracted function call to the new aggregate outlined function
  85. /// call.
  86. bool ChangedArgOrder = false;
  87. /// Marks whether this region ends in a branch, there is special handling
  88. /// required for the following basic blocks in this case.
  89. bool EndsInBranch = false;
  90. /// The PHIBlocks with their corresponding return block based on the return
  91. /// value as the key.
  92. DenseMap<Value *, BasicBlock *> PHIBlocks;
  93. /// Mapping of the argument number in the deduplicated function
  94. /// to a given constant, which is used when creating the arguments to the call
  95. /// to the newly created deduplicated function. This is handled separately
  96. /// since the CodeExtractor does not recognize constants.
  97. DenseMap<unsigned, Constant *> AggArgToConstant;
  98. /// The global value numbers that are used as outputs for this section. Once
  99. /// extracted, each output will be stored to an output register. This
  100. /// documents the global value numbers that are used in this pattern.
  101. SmallVector<unsigned, 4> GVNStores;
  102. /// Used to create an outlined function.
  103. CodeExtractor *CE = nullptr;
  104. /// The call site of the extracted region.
  105. CallInst *Call = nullptr;
  106. /// The function for the extracted region.
  107. Function *ExtractedFunction = nullptr;
  108. /// Flag for whether we have split out the IRSimilarityCanidate. That is,
  109. /// make the region contained the IRSimilarityCandidate its own BasicBlock.
  110. bool CandidateSplit = false;
  111. /// Flag for whether we should not consider this region for extraction.
  112. bool IgnoreRegion = false;
  113. /// The BasicBlock that is before the start of the region BasicBlock,
  114. /// only defined when the region has been split.
  115. BasicBlock *PrevBB = nullptr;
  116. /// The BasicBlock that contains the starting instruction of the region.
  117. BasicBlock *StartBB = nullptr;
  118. /// The BasicBlock that contains the ending instruction of the region.
  119. BasicBlock *EndBB = nullptr;
  120. /// The BasicBlock that is after the start of the region BasicBlock,
  121. /// only defined when the region has been split.
  122. BasicBlock *FollowBB = nullptr;
  123. /// The Outlinable Group that contains this region and structurally similar
  124. /// regions to this region.
  125. OutlinableGroup *Parent = nullptr;
  126. OutlinableRegion(IRSimilarityCandidate &C, OutlinableGroup &Group)
  127. : Candidate(&C), Parent(&Group) {
  128. StartBB = C.getStartBB();
  129. EndBB = C.getEndBB();
  130. }
  131. /// For the contained region, split the parent BasicBlock at the starting and
  132. /// ending instructions of the contained IRSimilarityCandidate.
  133. void splitCandidate();
  134. /// For the contained region, reattach the BasicBlock at the starting and
  135. /// ending instructions of the contained IRSimilarityCandidate, or if the
  136. /// function has been extracted, the start and end of the BasicBlock
  137. /// containing the called function.
  138. void reattachCandidate();
  139. /// Find a corresponding value for \p V in similar OutlinableRegion \p Other.
  140. ///
  141. /// \param Other [in] - The OutlinableRegion to find the corresponding Value
  142. /// in.
  143. /// \param V [in] - The Value to look for in the other region.
  144. /// \return The corresponding Value to \p V if it exists, otherwise nullptr.
  145. Value *findCorrespondingValueIn(const OutlinableRegion &Other, Value *V);
  146. /// Get the size of the code removed from the region.
  147. ///
  148. /// \param [in] TTI - The TargetTransformInfo for the parent function.
  149. /// \returns the code size of the region
  150. InstructionCost getBenefit(TargetTransformInfo &TTI);
  151. };
  152. /// This class is a pass that identifies similarity in a Module, extracts
  153. /// instances of the similarity, and then consolidating the similar regions
  154. /// in an effort to reduce code size. It uses the IRSimilarityIdentifier pass
  155. /// to identify the similar regions of code, and then extracts the similar
  156. /// sections into a single function. See the above for an example as to
  157. /// how code is extracted and consolidated into a single function.
  158. class IROutliner {
  159. public:
  160. IROutliner(function_ref<TargetTransformInfo &(Function &)> GTTI,
  161. function_ref<IRSimilarityIdentifier &(Module &)> GIRSI,
  162. function_ref<OptimizationRemarkEmitter &(Function &)> GORE)
  163. : getTTI(GTTI), getIRSI(GIRSI), getORE(GORE) {
  164. // Check that the DenseMap implementation has not changed.
  165. assert(DenseMapInfo<unsigned>::getEmptyKey() == (unsigned)-1 &&
  166. "DenseMapInfo<unsigned>'s empty key isn't -1!");
  167. assert(DenseMapInfo<unsigned>::getTombstoneKey() == (unsigned)-2 &&
  168. "DenseMapInfo<unsigned>'s tombstone key isn't -2!");
  169. }
  170. bool run(Module &M);
  171. private:
  172. /// Find repeated similar code sequences in \p M and outline them into new
  173. /// Functions.
  174. ///
  175. /// \param [in] M - The module to outline from.
  176. /// \returns The number of Functions created.
  177. unsigned doOutline(Module &M);
  178. /// Check whether an OutlinableRegion is incompatible with code already
  179. /// outlined. OutlinableRegions are incomptaible when there are overlapping
  180. /// instructions, or code that has not been recorded has been added to the
  181. /// instructions.
  182. ///
  183. /// \param [in] Region - The OutlinableRegion to check for conflicts with
  184. /// already outlined code.
  185. /// \returns whether the region can safely be outlined.
  186. bool isCompatibleWithAlreadyOutlinedCode(const OutlinableRegion &Region);
  187. /// Remove all the IRSimilarityCandidates from \p CandidateVec that have
  188. /// instructions contained in a previously outlined region and put the
  189. /// remaining regions in \p CurrentGroup.
  190. ///
  191. /// \param [in] CandidateVec - List of similarity candidates for regions with
  192. /// the same similarity structure.
  193. /// \param [in,out] CurrentGroup - Contains the potential sections to
  194. /// be outlined.
  195. void
  196. pruneIncompatibleRegions(std::vector<IRSimilarityCandidate> &CandidateVec,
  197. OutlinableGroup &CurrentGroup);
  198. /// Create the function based on the overall types found in the current
  199. /// regions being outlined.
  200. ///
  201. /// \param M - The module to outline from.
  202. /// \param [in,out] CG - The OutlinableGroup for the regions to be outlined.
  203. /// \param [in] FunctionNameSuffix - How many functions have we previously
  204. /// created.
  205. /// \returns the newly created function.
  206. Function *createFunction(Module &M, OutlinableGroup &CG,
  207. unsigned FunctionNameSuffix);
  208. /// Identify the needed extracted inputs in a section, and add to the overall
  209. /// function if needed.
  210. ///
  211. /// \param [in] M - The module to outline from.
  212. /// \param [in,out] Region - The region to be extracted.
  213. /// \param [in] NotSame - The global value numbers of the Values in the region
  214. /// that do not have the same Constant in each strucutrally similar region.
  215. void findAddInputsOutputs(Module &M, OutlinableRegion &Region,
  216. DenseSet<unsigned> &NotSame);
  217. /// Find the number of instructions that will be removed by extracting the
  218. /// OutlinableRegions in \p CurrentGroup.
  219. ///
  220. /// \param [in] CurrentGroup - The collection of OutlinableRegions to be
  221. /// analyzed.
  222. /// \returns the number of outlined instructions across all regions.
  223. InstructionCost findBenefitFromAllRegions(OutlinableGroup &CurrentGroup);
  224. /// Find the number of instructions that will be added by reloading arguments.
  225. ///
  226. /// \param [in] CurrentGroup - The collection of OutlinableRegions to be
  227. /// analyzed.
  228. /// \returns the number of added reload instructions across all regions.
  229. InstructionCost findCostOutputReloads(OutlinableGroup &CurrentGroup);
  230. /// Find the cost and the benefit of \p CurrentGroup and save it back to
  231. /// \p CurrentGroup.
  232. ///
  233. /// \param [in] M - The module being analyzed
  234. /// \param [in,out] CurrentGroup - The overall outlined section
  235. void findCostBenefit(Module &M, OutlinableGroup &CurrentGroup);
  236. /// Update the output mapping based on the load instruction, and the outputs
  237. /// of the extracted function.
  238. ///
  239. /// \param Region - The region extracted
  240. /// \param Outputs - The outputs from the extracted function.
  241. /// \param LI - The load instruction used to update the mapping.
  242. void updateOutputMapping(OutlinableRegion &Region,
  243. ArrayRef<Value *> Outputs, LoadInst *LI);
  244. /// Extract \p Region into its own function.
  245. ///
  246. /// \param [in] Region - The region to be extracted into its own function.
  247. /// \returns True if it was successfully outlined.
  248. bool extractSection(OutlinableRegion &Region);
  249. /// For the similarities found, and the extracted sections, create a single
  250. /// outlined function with appropriate output blocks as necessary.
  251. ///
  252. /// \param [in] M - The module to outline from
  253. /// \param [in] CurrentGroup - The set of extracted sections to consolidate.
  254. /// \param [in,out] FuncsToRemove - List of functions to remove from the
  255. /// module after outlining is completed.
  256. /// \param [in,out] OutlinedFunctionNum - the number of new outlined
  257. /// functions.
  258. void deduplicateExtractedSections(Module &M, OutlinableGroup &CurrentGroup,
  259. std::vector<Function *> &FuncsToRemove,
  260. unsigned &OutlinedFunctionNum);
  261. /// If true, enables us to outline from functions that have LinkOnceFromODR
  262. /// linkages.
  263. bool OutlineFromLinkODRs = false;
  264. /// If false, we do not worry if the cost is greater than the benefit. This
  265. /// is for debugging and testing, so that we can test small cases to ensure
  266. /// that the outlining is being done correctly.
  267. bool CostModel = true;
  268. /// The set of outlined Instructions, identified by their location in the
  269. /// sequential ordering of instructions in a Module.
  270. DenseSet<unsigned> Outlined;
  271. /// TargetTransformInfo lambda for target specific information.
  272. function_ref<TargetTransformInfo &(Function &)> getTTI;
  273. /// A mapping from newly created reloaded output values to the original value.
  274. /// If an value is replace by an output from an outlined region, this maps
  275. /// that Value, back to its original Value.
  276. DenseMap<Value *, Value *> OutputMappings;
  277. /// IRSimilarityIdentifier lambda to retrieve IRSimilarityIdentifier.
  278. function_ref<IRSimilarityIdentifier &(Module &)> getIRSI;
  279. /// The optimization remark emitter for the pass.
  280. function_ref<OptimizationRemarkEmitter &(Function &)> getORE;
  281. /// The memory allocator used to allocate the CodeExtractors.
  282. SpecificBumpPtrAllocator<CodeExtractor> ExtractorAllocator;
  283. /// The memory allocator used to allocate the OutlinableRegions.
  284. SpecificBumpPtrAllocator<OutlinableRegion> RegionAllocator;
  285. /// The memory allocator used to allocate new IRInstructionData.
  286. SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
  287. /// Custom InstVisitor to classify different instructions for whether it can
  288. /// be analyzed for similarity. This is needed as there may be instruction we
  289. /// can identify as having similarity, but are more complicated to outline.
  290. struct InstructionAllowed : public InstVisitor<InstructionAllowed, bool> {
  291. InstructionAllowed() = default;
  292. bool visitBranchInst(BranchInst &BI) { return EnableBranches; }
  293. bool visitPHINode(PHINode &PN) { return EnableBranches; }
  294. // TODO: Handle allocas.
  295. bool visitAllocaInst(AllocaInst &AI) { return false; }
  296. // VAArg instructions are not allowed since this could cause difficulty when
  297. // differentiating between different sets of variable instructions in
  298. // the deduplicated outlined regions.
  299. bool visitVAArgInst(VAArgInst &VI) { return false; }
  300. // We exclude all exception handling cases since they are so context
  301. // dependent.
  302. bool visitLandingPadInst(LandingPadInst &LPI) { return false; }
  303. bool visitFuncletPadInst(FuncletPadInst &FPI) { return false; }
  304. // DebugInfo should be included in the regions, but should not be
  305. // analyzed for similarity as it has no bearing on the outcome of the
  306. // program.
  307. bool visitDbgInfoIntrinsic(DbgInfoIntrinsic &DII) { return true; }
  308. // TODO: Handle specific intrinsics individually from those that can be
  309. // handled.
  310. bool IntrinsicInst(IntrinsicInst &II) { return EnableIntrinsics; }
  311. // We only handle CallInsts that are not indirect, since we cannot guarantee
  312. // that they have a name in these cases.
  313. bool visitCallInst(CallInst &CI) {
  314. Function *F = CI.getCalledFunction();
  315. bool IsIndirectCall = CI.isIndirectCall();
  316. if (IsIndirectCall && !EnableIndirectCalls)
  317. return false;
  318. if (!F && !IsIndirectCall)
  319. return false;
  320. // Returning twice can cause issues with the state of the function call
  321. // that were not expected when the function was used, so we do not include
  322. // the call in outlined functions.
  323. if (CI.canReturnTwice())
  324. return false;
  325. return true;
  326. }
  327. // TODO: Handle FreezeInsts. Since a frozen value could be frozen inside
  328. // the outlined region, and then returned as an output, this will have to be
  329. // handled differently.
  330. bool visitFreezeInst(FreezeInst &CI) { return false; }
  331. // TODO: We do not current handle similarity that changes the control flow.
  332. bool visitInvokeInst(InvokeInst &II) { return false; }
  333. // TODO: We do not current handle similarity that changes the control flow.
  334. bool visitCallBrInst(CallBrInst &CBI) { return false; }
  335. // TODO: Handle interblock similarity.
  336. bool visitTerminator(Instruction &I) { return false; }
  337. bool visitInstruction(Instruction &I) { return true; }
  338. // The flag variable that marks whether we should allow branch instructions
  339. // to be outlined.
  340. bool EnableBranches = false;
  341. // The flag variable that marks whether we should allow indirect calls
  342. // to be outlined.
  343. bool EnableIndirectCalls = true;
  344. // The flag variable that marks whether we should allow intrinsics
  345. // instructions to be outlined.
  346. bool EnableIntrinsics = false;
  347. };
  348. /// A InstVisitor used to exclude certain instructions from being outlined.
  349. InstructionAllowed InstructionClassifier;
  350. };
  351. /// Pass to outline similar regions.
  352. class IROutlinerPass : public PassInfoMixin<IROutlinerPass> {
  353. public:
  354. PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
  355. };
  356. } // end namespace llvm
  357. #endif // LLVM_TRANSFORMS_IPO_IROUTLINER_H
  358. #ifdef __GNUC__
  359. #pragma GCC diagnostic pop
  360. #endif