Back to home page

EIC code displayed by LXR

 
 

    


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