|
|
|||
File indexing completed on 2026-05-10 08:44:40
0001 //===- IROutliner.h - Extract similar IR regions into functions --*- C++ -*-==// 0002 // 0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 0004 // See https://llvm.org/LICENSE.txt for license information. 0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 0006 // 0007 //===----------------------------------------------------------------------===// 0008 // 0009 // \file 0010 // The interface file for the IROutliner which is used by the IROutliner Pass. 0011 // 0012 // The outliner uses the IRSimilarityIdentifier to identify the similar regions 0013 // of code. It evaluates each set of IRSimilarityCandidates with an estimate of 0014 // whether it will provide code size reduction. Each region is extracted using 0015 // the code extractor. These extracted functions are consolidated into a single 0016 // function and called from the extracted call site. 0017 // 0018 // For example: 0019 // \code 0020 // %1 = add i32 %a, %b 0021 // %2 = add i32 %b, %a 0022 // %3 = add i32 %b, %a 0023 // %4 = add i32 %a, %b 0024 // \endcode 0025 // would become function 0026 // \code 0027 // define internal void outlined_ir_function(i32 %0, i32 %1) { 0028 // %1 = add i32 %0, %1 0029 // %2 = add i32 %1, %0 0030 // ret void 0031 // } 0032 // \endcode 0033 // with calls: 0034 // \code 0035 // call void outlined_ir_function(i32 %a, i32 %b) 0036 // call void outlined_ir_function(i32 %b, i32 %a) 0037 // \endcode 0038 // 0039 //===----------------------------------------------------------------------===// 0040 0041 #ifndef LLVM_TRANSFORMS_IPO_IROUTLINER_H 0042 #define LLVM_TRANSFORMS_IPO_IROUTLINER_H 0043 0044 #include "llvm/Analysis/IRSimilarityIdentifier.h" 0045 #include "llvm/IR/PassManager.h" 0046 #include "llvm/Support/InstructionCost.h" 0047 #include "llvm/Transforms/Utils/CodeExtractor.h" 0048 0049 struct OutlinableGroup; 0050 0051 namespace llvm { 0052 using namespace CallingConv; 0053 using namespace IRSimilarity; 0054 0055 class Module; 0056 class TargetTransformInfo; 0057 class OptimizationRemarkEmitter; 0058 0059 /// The OutlinableRegion holds all the information for a specific region, or 0060 /// sequence of instructions. This includes what values need to be hoisted to 0061 /// arguments from the extracted function, inputs and outputs to the region, and 0062 /// mapping from the extracted function arguments to overall function arguments. 0063 struct OutlinableRegion { 0064 /// Describes the region of code. 0065 IRSimilarityCandidate *Candidate = nullptr; 0066 0067 /// If this region is outlined, the front and back IRInstructionData could 0068 /// potentially become invalidated if the only new instruction is a call. 0069 /// This ensures that we replace in the instruction in the IRInstructionData. 0070 IRInstructionData *NewFront = nullptr; 0071 IRInstructionData *NewBack = nullptr; 0072 0073 /// The number of extracted inputs from the CodeExtractor. 0074 unsigned NumExtractedInputs = 0; 0075 0076 /// The corresponding BasicBlock with the appropriate stores for this 0077 /// OutlinableRegion in the overall function. 0078 unsigned OutputBlockNum = -1; 0079 0080 /// Mapping the extracted argument number to the argument number in the 0081 /// overall function. Since there will be inputs, such as elevated constants 0082 /// that are not the same in each region in a SimilarityGroup, or values that 0083 /// cannot be sunk into the extracted section in every region, we must keep 0084 /// track of which extracted argument maps to which overall argument. 0085 DenseMap<unsigned, unsigned> ExtractedArgToAgg; 0086 DenseMap<unsigned, unsigned> AggArgToExtracted; 0087 0088 /// Values in the outlined functions will often be replaced by arguments. When 0089 /// finding corresponding values from one region to another, the found value 0090 /// will be the value the argument previously replaced. This structure maps 0091 /// any replaced values for the region to the aggregate aggregate argument 0092 /// in the overall function. 0093 DenseMap<Value *, Value *> RemappedArguments; 0094 0095 /// Marks whether we need to change the order of the arguments when mapping 0096 /// the old extracted function call to the new aggregate outlined function 0097 /// call. 0098 bool ChangedArgOrder = false; 0099 0100 /// Marks whether this region ends in a branch, there is special handling 0101 /// required for the following basic blocks in this case. 0102 bool EndsInBranch = false; 0103 0104 /// The PHIBlocks with their corresponding return block based on the return 0105 /// value as the key. 0106 DenseMap<Value *, BasicBlock *> PHIBlocks; 0107 0108 /// Mapping of the argument number in the deduplicated function 0109 /// to a given constant, which is used when creating the arguments to the call 0110 /// to the newly created deduplicated function. This is handled separately 0111 /// since the CodeExtractor does not recognize constants. 0112 DenseMap<unsigned, Constant *> AggArgToConstant; 0113 0114 /// The global value numbers that are used as outputs for this section. Once 0115 /// extracted, each output will be stored to an output register. This 0116 /// documents the global value numbers that are used in this pattern. 0117 SmallVector<unsigned, 4> GVNStores; 0118 0119 /// Used to create an outlined function. 0120 CodeExtractor *CE = nullptr; 0121 0122 /// The call site of the extracted region. 0123 CallInst *Call = nullptr; 0124 0125 /// The function for the extracted region. 0126 Function *ExtractedFunction = nullptr; 0127 0128 /// Flag for whether we have split out the IRSimilarityCanidate. That is, 0129 /// make the region contained the IRSimilarityCandidate its own BasicBlock. 0130 bool CandidateSplit = false; 0131 0132 /// Flag for whether we should not consider this region for extraction. 0133 bool IgnoreRegion = false; 0134 0135 /// The BasicBlock that is before the start of the region BasicBlock, 0136 /// only defined when the region has been split. 0137 BasicBlock *PrevBB = nullptr; 0138 0139 /// The BasicBlock that contains the starting instruction of the region. 0140 BasicBlock *StartBB = nullptr; 0141 0142 /// The BasicBlock that contains the ending instruction of the region. 0143 BasicBlock *EndBB = nullptr; 0144 0145 /// The BasicBlock that is after the start of the region BasicBlock, 0146 /// only defined when the region has been split. 0147 BasicBlock *FollowBB = nullptr; 0148 0149 /// The Outlinable Group that contains this region and structurally similar 0150 /// regions to this region. 0151 OutlinableGroup *Parent = nullptr; 0152 0153 OutlinableRegion(IRSimilarityCandidate &C, OutlinableGroup &Group) 0154 : Candidate(&C), Parent(&Group) { 0155 StartBB = C.getStartBB(); 0156 EndBB = C.getEndBB(); 0157 } 0158 0159 /// For the contained region, split the parent BasicBlock at the starting and 0160 /// ending instructions of the contained IRSimilarityCandidate. 0161 void splitCandidate(); 0162 0163 /// For the contained region, reattach the BasicBlock at the starting and 0164 /// ending instructions of the contained IRSimilarityCandidate, or if the 0165 /// function has been extracted, the start and end of the BasicBlock 0166 /// containing the called function. 0167 void reattachCandidate(); 0168 0169 /// Find a corresponding value for \p V in similar OutlinableRegion \p Other. 0170 /// 0171 /// \param Other [in] - The OutlinableRegion to find the corresponding Value 0172 /// in. 0173 /// \param V [in] - The Value to look for in the other region. 0174 /// \return The corresponding Value to \p V if it exists, otherwise nullptr. 0175 Value *findCorrespondingValueIn(const OutlinableRegion &Other, Value *V); 0176 0177 /// Find a corresponding BasicBlock for \p BB in similar OutlinableRegion \p Other. 0178 /// 0179 /// \param Other [in] - The OutlinableRegion to find the corresponding 0180 /// BasicBlock in. 0181 /// \param BB [in] - The BasicBlock to look for in the other region. 0182 /// \return The corresponding Value to \p V if it exists, otherwise nullptr. 0183 BasicBlock *findCorrespondingBlockIn(const OutlinableRegion &Other, 0184 BasicBlock *BB); 0185 0186 /// Get the size of the code removed from the region. 0187 /// 0188 /// \param [in] TTI - The TargetTransformInfo for the parent function. 0189 /// \returns the code size of the region 0190 InstructionCost getBenefit(TargetTransformInfo &TTI); 0191 }; 0192 0193 /// This class is a pass that identifies similarity in a Module, extracts 0194 /// instances of the similarity, and then consolidating the similar regions 0195 /// in an effort to reduce code size. It uses the IRSimilarityIdentifier pass 0196 /// to identify the similar regions of code, and then extracts the similar 0197 /// sections into a single function. See the above for an example as to 0198 /// how code is extracted and consolidated into a single function. 0199 class IROutliner { 0200 public: 0201 IROutliner(function_ref<TargetTransformInfo &(Function &)> GTTI, 0202 function_ref<IRSimilarityIdentifier &(Module &)> GIRSI, 0203 function_ref<OptimizationRemarkEmitter &(Function &)> GORE) 0204 : getTTI(GTTI), getIRSI(GIRSI), getORE(GORE) { 0205 0206 // Check that the DenseMap implementation has not changed. 0207 assert(DenseMapInfo<unsigned>::getEmptyKey() == (unsigned)-1 && 0208 "DenseMapInfo<unsigned>'s empty key isn't -1!"); 0209 assert(DenseMapInfo<unsigned>::getTombstoneKey() == (unsigned)-2 && 0210 "DenseMapInfo<unsigned>'s tombstone key isn't -2!"); 0211 } 0212 bool run(Module &M); 0213 0214 private: 0215 /// Find repeated similar code sequences in \p M and outline them into new 0216 /// Functions. 0217 /// 0218 /// \param [in] M - The module to outline from. 0219 /// \returns The number of Functions created. 0220 unsigned doOutline(Module &M); 0221 0222 /// Check whether an OutlinableRegion is incompatible with code already 0223 /// outlined. OutlinableRegions are incomptaible when there are overlapping 0224 /// instructions, or code that has not been recorded has been added to the 0225 /// instructions. 0226 /// 0227 /// \param [in] Region - The OutlinableRegion to check for conflicts with 0228 /// already outlined code. 0229 /// \returns whether the region can safely be outlined. 0230 bool isCompatibleWithAlreadyOutlinedCode(const OutlinableRegion &Region); 0231 0232 /// Remove all the IRSimilarityCandidates from \p CandidateVec that have 0233 /// instructions contained in a previously outlined region and put the 0234 /// remaining regions in \p CurrentGroup. 0235 /// 0236 /// \param [in] CandidateVec - List of similarity candidates for regions with 0237 /// the same similarity structure. 0238 /// \param [in,out] CurrentGroup - Contains the potential sections to 0239 /// be outlined. 0240 void 0241 pruneIncompatibleRegions(std::vector<IRSimilarityCandidate> &CandidateVec, 0242 OutlinableGroup &CurrentGroup); 0243 0244 /// Create the function based on the overall types found in the current 0245 /// regions being outlined. 0246 /// 0247 /// \param M - The module to outline from. 0248 /// \param [in,out] CG - The OutlinableGroup for the regions to be outlined. 0249 /// \param [in] FunctionNameSuffix - How many functions have we previously 0250 /// created. 0251 /// \returns the newly created function. 0252 Function *createFunction(Module &M, OutlinableGroup &CG, 0253 unsigned FunctionNameSuffix); 0254 0255 /// Identify the needed extracted inputs in a section, and add to the overall 0256 /// function if needed. 0257 /// 0258 /// \param [in] M - The module to outline from. 0259 /// \param [in,out] Region - The region to be extracted. 0260 /// \param [in] NotSame - The global value numbers of the Values in the region 0261 /// that do not have the same Constant in each strucutrally similar region. 0262 void findAddInputsOutputs(Module &M, OutlinableRegion &Region, 0263 DenseSet<unsigned> &NotSame); 0264 0265 /// Find the number of instructions that will be removed by extracting the 0266 /// OutlinableRegions in \p CurrentGroup. 0267 /// 0268 /// \param [in] CurrentGroup - The collection of OutlinableRegions to be 0269 /// analyzed. 0270 /// \returns the number of outlined instructions across all regions. 0271 InstructionCost findBenefitFromAllRegions(OutlinableGroup &CurrentGroup); 0272 0273 /// Find the number of instructions that will be added by reloading arguments. 0274 /// 0275 /// \param [in] CurrentGroup - The collection of OutlinableRegions to be 0276 /// analyzed. 0277 /// \returns the number of added reload instructions across all regions. 0278 InstructionCost findCostOutputReloads(OutlinableGroup &CurrentGroup); 0279 0280 /// Find the cost and the benefit of \p CurrentGroup and save it back to 0281 /// \p CurrentGroup. 0282 /// 0283 /// \param [in] M - The module being analyzed 0284 /// \param [in,out] CurrentGroup - The overall outlined section 0285 void findCostBenefit(Module &M, OutlinableGroup &CurrentGroup); 0286 0287 /// Update the output mapping based on the load instruction, and the outputs 0288 /// of the extracted function. 0289 /// 0290 /// \param Region - The region extracted 0291 /// \param Outputs - The outputs from the extracted function. 0292 /// \param LI - The load instruction used to update the mapping. 0293 void updateOutputMapping(OutlinableRegion &Region, 0294 ArrayRef<Value *> Outputs, LoadInst *LI); 0295 0296 /// Extract \p Region into its own function. 0297 /// 0298 /// \param [in] Region - The region to be extracted into its own function. 0299 /// \returns True if it was successfully outlined. 0300 bool extractSection(OutlinableRegion &Region); 0301 0302 /// For the similarities found, and the extracted sections, create a single 0303 /// outlined function with appropriate output blocks as necessary. 0304 /// 0305 /// \param [in] M - The module to outline from 0306 /// \param [in] CurrentGroup - The set of extracted sections to consolidate. 0307 /// \param [in,out] FuncsToRemove - List of functions to remove from the 0308 /// module after outlining is completed. 0309 /// \param [in,out] OutlinedFunctionNum - the number of new outlined 0310 /// functions. 0311 void deduplicateExtractedSections(Module &M, OutlinableGroup &CurrentGroup, 0312 std::vector<Function *> &FuncsToRemove, 0313 unsigned &OutlinedFunctionNum); 0314 0315 /// If true, enables us to outline from functions that have LinkOnceFromODR 0316 /// linkages. 0317 bool OutlineFromLinkODRs = false; 0318 0319 /// If false, we do not worry if the cost is greater than the benefit. This 0320 /// is for debugging and testing, so that we can test small cases to ensure 0321 /// that the outlining is being done correctly. 0322 bool CostModel = true; 0323 0324 /// The set of outlined Instructions, identified by their location in the 0325 /// sequential ordering of instructions in a Module. 0326 DenseSet<unsigned> Outlined; 0327 0328 /// TargetTransformInfo lambda for target specific information. 0329 function_ref<TargetTransformInfo &(Function &)> getTTI; 0330 0331 /// A mapping from newly created reloaded output values to the original value. 0332 /// If an value is replace by an output from an outlined region, this maps 0333 /// that Value, back to its original Value. 0334 DenseMap<Value *, Value *> OutputMappings; 0335 0336 /// IRSimilarityIdentifier lambda to retrieve IRSimilarityIdentifier. 0337 function_ref<IRSimilarityIdentifier &(Module &)> getIRSI; 0338 0339 /// The optimization remark emitter for the pass. 0340 function_ref<OptimizationRemarkEmitter &(Function &)> getORE; 0341 0342 /// The memory allocator used to allocate the CodeExtractors. 0343 SpecificBumpPtrAllocator<CodeExtractor> ExtractorAllocator; 0344 0345 /// The memory allocator used to allocate the OutlinableRegions. 0346 SpecificBumpPtrAllocator<OutlinableRegion> RegionAllocator; 0347 0348 /// The memory allocator used to allocate new IRInstructionData. 0349 SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator; 0350 0351 /// Custom InstVisitor to classify different instructions for whether it can 0352 /// be analyzed for similarity. This is needed as there may be instruction we 0353 /// can identify as having similarity, but are more complicated to outline. 0354 struct InstructionAllowed : public InstVisitor<InstructionAllowed, bool> { 0355 InstructionAllowed() = default; 0356 0357 bool visitBranchInst(BranchInst &BI) { return EnableBranches; } 0358 bool visitPHINode(PHINode &PN) { return EnableBranches; } 0359 // TODO: Handle allocas. 0360 bool visitAllocaInst(AllocaInst &AI) { return false; } 0361 // VAArg instructions are not allowed since this could cause difficulty when 0362 // differentiating between different sets of variable instructions in 0363 // the deduplicated outlined regions. 0364 bool visitVAArgInst(VAArgInst &VI) { return false; } 0365 // We exclude all exception handling cases since they are so context 0366 // dependent. 0367 bool visitLandingPadInst(LandingPadInst &LPI) { return false; } 0368 bool visitFuncletPadInst(FuncletPadInst &FPI) { return false; } 0369 // DebugInfo should be included in the regions, but should not be 0370 // analyzed for similarity as it has no bearing on the outcome of the 0371 // program. 0372 bool visitDbgInfoIntrinsic(DbgInfoIntrinsic &DII) { return true; } 0373 // TODO: Handle specific intrinsics individually from those that can be 0374 // handled. 0375 bool IntrinsicInst(IntrinsicInst &II) { return EnableIntrinsics; } 0376 // We only handle CallInsts that are not indirect, since we cannot guarantee 0377 // that they have a name in these cases. 0378 bool visitCallInst(CallInst &CI) { 0379 Function *F = CI.getCalledFunction(); 0380 bool IsIndirectCall = CI.isIndirectCall(); 0381 if (IsIndirectCall && !EnableIndirectCalls) 0382 return false; 0383 if (!F && !IsIndirectCall) 0384 return false; 0385 // Returning twice can cause issues with the state of the function call 0386 // that were not expected when the function was used, so we do not include 0387 // the call in outlined functions. 0388 if (CI.canReturnTwice()) 0389 return false; 0390 // TODO: Update the outliner to capture whether the outlined function 0391 // needs these extra attributes. 0392 0393 // Functions marked with the swifttailcc and tailcc calling conventions 0394 // require special handling when outlining musttail functions. The 0395 // calling convention must be passed down to the outlined function as 0396 // well. Further, there is special handling for musttail calls as well, 0397 // requiring a return call directly after. For now, the outliner does not 0398 // support this. 0399 bool IsTailCC = CI.getCallingConv() == CallingConv::SwiftTail || 0400 CI.getCallingConv() == CallingConv::Tail; 0401 if (IsTailCC && !EnableMustTailCalls) 0402 return false; 0403 if (CI.isMustTailCall() && !EnableMustTailCalls) 0404 return false; 0405 // The outliner can only handle musttail items if it is also accompanied 0406 // by the tailcc or swifttailcc calling convention. 0407 if (CI.isMustTailCall() && !IsTailCC) 0408 return false; 0409 return true; 0410 } 0411 // TODO: Handle FreezeInsts. Since a frozen value could be frozen inside 0412 // the outlined region, and then returned as an output, this will have to be 0413 // handled differently. 0414 bool visitFreezeInst(FreezeInst &CI) { return false; } 0415 // TODO: We do not current handle similarity that changes the control flow. 0416 bool visitInvokeInst(InvokeInst &II) { return false; } 0417 // TODO: We do not current handle similarity that changes the control flow. 0418 bool visitCallBrInst(CallBrInst &CBI) { return false; } 0419 // TODO: Handle interblock similarity. 0420 bool visitTerminator(Instruction &I) { return false; } 0421 bool visitInstruction(Instruction &I) { return true; } 0422 0423 // The flag variable that marks whether we should allow branch instructions 0424 // to be outlined. 0425 bool EnableBranches = false; 0426 0427 // The flag variable that marks whether we should allow indirect calls 0428 // to be outlined. 0429 bool EnableIndirectCalls = true; 0430 0431 // The flag variable that marks whether we should allow intrinsics 0432 // instructions to be outlined. 0433 bool EnableIntrinsics = false; 0434 0435 // The flag variable that marks whether we should allow musttail calls. 0436 bool EnableMustTailCalls = false; 0437 }; 0438 0439 /// A InstVisitor used to exclude certain instructions from being outlined. 0440 InstructionAllowed InstructionClassifier; 0441 }; 0442 0443 /// Pass to outline similar regions. 0444 class IROutlinerPass : public PassInfoMixin<IROutlinerPass> { 0445 public: 0446 PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); 0447 }; 0448 0449 } // end namespace llvm 0450 0451 #endif // LLVM_TRANSFORMS_IPO_IROUTLINER_H
| [ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
|
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
|