diff --git a/llvm/include/llvm/Transforms/IPO/IROutliner.h b/llvm/include/llvm/Transforms/IPO/IROutliner.h --- a/llvm/include/llvm/Transforms/IPO/IROutliner.h +++ b/llvm/include/llvm/Transforms/IPO/IROutliner.h @@ -48,14 +48,13 @@ #include "llvm/Transforms/Utils/CodeExtractor.h" #include -struct OutlinableGroup; - namespace llvm { using namespace IRSimilarity; class Module; class TargetTransformInfo; class OptimizationRemarkEmitter; +struct OutlinableGroup; /// The OutlinableRegion holds all the information for a specific region, or /// sequence of instructions. This includes what values need to be hoisted to @@ -159,6 +158,73 @@ InstructionCost getBenefit(TargetTransformInfo &TTI); }; +/// The OutlinableGroup holds all the overarching information for outlining +/// a set of regions that are structurally similar to one another, such as the +/// types of the overall function, the output blocks, the sets of stores needed +/// and a list of the different regions. This information is used in the +/// deduplication of extracted regions with the same structure. +struct OutlinableGroup { + /// The sections that could be outlined + std::vector Regions; + + /// The argument types for the function created as the overall function to + /// replace the extracted function for each region. + std::vector ArgumentTypes; + /// The FunctionType for the overall function. + FunctionType *OutlinedFunctionType = nullptr; + /// The Function for the collective overall function. + Function *OutlinedFunction = nullptr; + + /// Flag for whether we should not consider this group of OutlinableRegions + /// for extraction. + bool IgnoreGroup = false; + + /// The return block for the overall function. + BasicBlock *EndBB = nullptr; + + /// A set containing the different GVN store sets needed. Each array contains + /// a sorted list of the different values that need to be stored into output + /// registers. + DenseSet> OutputGVNCombinations; + + /// Flag for whether the \ref ArgumentTypes have been defined after the + /// extraction of the first region. + bool InputTypesSet = false; + + /// The number of input values in \ref ArgumentTypes. Anything after this + /// index in ArgumentTypes is an output argument. + unsigned NumAggregateInputs = 0; + + /// The mapping of the canonical numbering of the values in outlined sections + /// to specific arguments. + DenseMap CanonicalNumberToAggArg; + + /// The number of instructions that will be outlined by extracting \ref + /// Regions. + InstructionCost Benefit = 0; + /// The number of added instructions needed for the outlining of the \ref + /// Regions. + InstructionCost Cost = 0; + + /// The argument that needs to be marked with the swifterr attribute. If not + /// needed, there is no value. + Optional SwiftErrorArgument; + + /// For the \ref Regions, we look at every Value. If it is a constant, + /// we check whether it is the same in Region. + /// + /// \param [in,out] NotSame contains the global value numbers where the + /// constant is not always the same, and must be passed in as an argument. + void findSameConstants(DenseSet &NotSame); + + /// For the regions, look at each set of GVN stores needed and account for + /// each combination. Add an argument to the argument types if there is + /// more than one combination. + /// + /// \param [in] M - The module we are outlining from. + void collectGVNStoreSets(Module &M); +}; + /// This class is a pass that identifies similarity in a Module, extracts /// instances of the similarity, and then consolidating the similar regions /// in an effort to reduce code size. It uses the IRSimilarityIdentifier pass @@ -181,6 +247,17 @@ /// \returns The number of Functions created. unsigned doOutline(Module &M); + /// Remove all the IRSimilarityCandidates from \p CandidateVec that have + /// instructions contained in a previously outlined region and put the + /// remaining regions in \p CurrentGroup. + /// + /// \param [in] CandidateVec - List of similarity candidates for regions with + /// the same similarity structure. + /// \param [in,out] CurrentGroup - Contains the potential sections to + /// be outlined. + bool + compatibleWithOutlined(OutlinableRegion &Region); + /// Remove all the IRSimilarityCandidates from \p CandidateVec that have /// instructions contained in a previously outlined region and put the /// remaining regions in \p CurrentGroup. @@ -294,6 +371,9 @@ /// The memory allocator used to allocate the CodeExtractors. SpecificBumpPtrAllocator ExtractorAllocator; + /// The memory allocator used to allocate the OutlinableGroups. + SpecificBumpPtrAllocator GroupAllocator; + /// The memory allocator used to allocate the OutlinableRegions. SpecificBumpPtrAllocator RegionAllocator; diff --git a/llvm/lib/Transforms/IPO/IROutliner.cpp b/llvm/lib/Transforms/IPO/IROutliner.cpp --- a/llvm/lib/Transforms/IPO/IROutliner.cpp +++ b/llvm/lib/Transforms/IPO/IROutliner.cpp @@ -50,73 +50,6 @@ cl::desc("Debug option to outline greedily, without restriction that " "calculated benefit outweighs cost")); -/// The OutlinableGroup holds all the overarching information for outlining -/// a set of regions that are structurally similar to one another, such as the -/// types of the overall function, the output blocks, the sets of stores needed -/// and a list of the different regions. This information is used in the -/// deduplication of extracted regions with the same structure. -struct OutlinableGroup { - /// The sections that could be outlined - std::vector Regions; - - /// The argument types for the function created as the overall function to - /// replace the extracted function for each region. - std::vector ArgumentTypes; - /// The FunctionType for the overall function. - FunctionType *OutlinedFunctionType = nullptr; - /// The Function for the collective overall function. - Function *OutlinedFunction = nullptr; - - /// Flag for whether we should not consider this group of OutlinableRegions - /// for extraction. - bool IgnoreGroup = false; - - /// The return block for the overall function. - BasicBlock *EndBB = nullptr; - - /// A set containing the different GVN store sets needed. Each array contains - /// a sorted list of the different values that need to be stored into output - /// registers. - DenseSet> OutputGVNCombinations; - - /// Flag for whether the \ref ArgumentTypes have been defined after the - /// extraction of the first region. - bool InputTypesSet = false; - - /// The number of input values in \ref ArgumentTypes. Anything after this - /// index in ArgumentTypes is an output argument. - unsigned NumAggregateInputs = 0; - - /// The mapping of the canonical numbering of the values in outlined sections - /// to specific arguments. - DenseMap CanonicalNumberToAggArg; - - /// The number of instructions that will be outlined by extracting \ref - /// Regions. - InstructionCost Benefit = 0; - /// The number of added instructions needed for the outlining of the \ref - /// Regions. - InstructionCost Cost = 0; - - /// The argument that needs to be marked with the swifterr attribute. If not - /// needed, there is no value. - Optional SwiftErrorArgument; - - /// For the \ref Regions, we look at every Value. If it is a constant, - /// we check whether it is the same in Region. - /// - /// \param [in,out] NotSame contains the global value numbers where the - /// constant is not always the same, and must be passed in as an argument. - void findSameConstants(DenseSet &NotSame); - - /// For the regions, look at each set of GVN stores needed and account for - /// each combination. Add an argument to the argument types if there is - /// more than one combination. - /// - /// \param [in] M - The module we are outlining from. - void collectGVNStoreSets(Module &M); -}; - /// Move the contents of \p SourceBB to before the last instruction of \p /// TargetBB. /// \param SourceBB - the BasicBlock to pull Instructions from. @@ -133,6 +66,7 @@ void OutlinableRegion::splitCandidate() { assert(!CandidateSplit && "Candidate already split!"); + if (Candidate->end()->Inst != Candidate->backInstruction()->getNextNonDebugInstruction()) return; @@ -1336,6 +1270,47 @@ OutlinedFunctionNum++; } +bool IROutliner::compatibleWithOutlined(OutlinableRegion &Region) { + IRSimilarityCandidate *IRSC = Region.Candidate; + unsigned StartIdx = IRSC->getStartIdx(); + unsigned EndIdx = IRSC->getEndIdx(); + + for (unsigned Idx = StartIdx; Idx <= EndIdx; Idx++) + if (Outlined.contains(Idx)) { + return false; + } + + if (Region.Candidate->end()->Inst != + Region.Candidate->backInstruction()->getNextNonDebugInstruction()) { + IRInstructionDataList *IDL = Region.Candidate->front()->IDL; + Instruction *NewEndInst = + Region.Candidate->backInstruction()->getNextNonDebugInstruction(); + IRInstructionData *NewEndIRID = new (InstDataAllocator.Allocate()) + IRInstructionData(*NewEndInst, + InstructionClassifier.visit(*NewEndInst), *IDL); + + // Insert the first IRInstructionData of the new region after the + // last IRInstructionData of the IRSimilarityCandidate. + IDL->insert(Region.Candidate->end(), *NewEndIRID); + } + + bool BadInst = any_of(*IRSC, [this](IRInstructionData &ID) { + // We check if there is a discrepancy between the InstructionDataList + // and the actual next instruction in the module. If there is, it means + // that an extra instruction was added, likely by the CodeExtractor. + + // Since we do not have any similarity data about this particular + // instruction, we cannot confidently outline it, and must discard this + // candidate. + if (std::next(ID.getIterator())->Inst != + ID.Inst->getNextNonDebugInstruction()) + return true; + return !this->InstructionClassifier.visit(ID.Inst); + }); + + return !BadInst; +} + void IROutliner::pruneIncompatibleRegions( std::vector &CandidateVec, OutlinableGroup &CurrentGroup) { @@ -1661,33 +1636,35 @@ }); DenseSet NotSame; - std::vector FuncsToRemove; + std::vector NegativeCostGroups; + std::vector OutlinedRegions; // Iterate over the possible sets of similarity. for (SimilarityGroup &CandidateVec : SimilarityCandidates) { - OutlinableGroup CurrentGroup; + OutlinableGroup *CurrentGroup = + new (GroupAllocator.Allocate()) OutlinableGroup; // Remove entries that were previously outlined - pruneIncompatibleRegions(CandidateVec, CurrentGroup); + pruneIncompatibleRegions(CandidateVec, *CurrentGroup); // We pruned the number of regions to 0 to 1, meaning that it's not worth // trying to outlined since there is no compatible similar instance of this // code. - if (CurrentGroup.Regions.size() < 2) + if (CurrentGroup->Regions.size() < 2) continue; // Determine if there are any values that are the same constant throughout // each section in the set. NotSame.clear(); - CurrentGroup.findSameConstants(NotSame); + CurrentGroup->findSameConstants(NotSame); - if (CurrentGroup.IgnoreGroup) + if (CurrentGroup->IgnoreGroup) continue; // Create a CodeExtractor for each outlinable region. Identify inputs and // outputs for each section using the code extractor and create the argument // types for the Aggregate Outlining Function. - std::vector OutlinedRegions; - for (OutlinableRegion *OS : CurrentGroup.Regions) { + OutlinedRegions.clear(); + for (OutlinableRegion *OS : CurrentGroup->Regions) { // Break the outlinable region out of its parent BasicBlock into its own // BasicBlocks (see function implementation). OS->splitCandidate(); @@ -1705,34 +1682,34 @@ OS->reattachCandidate(); } - CurrentGroup.Regions = std::move(OutlinedRegions); + CurrentGroup->Regions = std::move(OutlinedRegions); - if (CurrentGroup.Regions.empty()) + if (CurrentGroup->Regions.empty()) continue; - CurrentGroup.collectGVNStoreSets(M); + CurrentGroup->collectGVNStoreSets(M); if (CostModel) - findCostBenefit(M, CurrentGroup); + findCostBenefit(M, *CurrentGroup); // If we are adhering to the cost model, reattach all the candidates - if (CurrentGroup.Cost >= CurrentGroup.Benefit && CostModel) { - for (OutlinableRegion *OS : CurrentGroup.Regions) + if (CurrentGroup->Cost >= CurrentGroup->Benefit && CostModel) { + for (OutlinableRegion *OS : CurrentGroup->Regions) OS->reattachCandidate(); OptimizationRemarkEmitter &ORE = getORE( - *CurrentGroup.Regions[0]->Candidate->getFunction()); + *CurrentGroup->Regions[0]->Candidate->getFunction()); ORE.emit([&]() { - IRSimilarityCandidate *C = CurrentGroup.Regions[0]->Candidate; + IRSimilarityCandidate *C = CurrentGroup->Regions[0]->Candidate; OptimizationRemarkMissed R(DEBUG_TYPE, "WouldNotDecreaseSize", C->frontInstruction()); R << "did not outline " - << ore::NV(std::to_string(CurrentGroup.Regions.size())) + << ore::NV(std::to_string(CurrentGroup->Regions.size())) << " regions due to estimated increase of " << ore::NV("InstructionIncrease", - CurrentGroup.Cost - CurrentGroup.Benefit) + CurrentGroup->Cost - CurrentGroup->Benefit) << " instructions at locations "; interleave( - CurrentGroup.Regions.begin(), CurrentGroup.Regions.end(), + CurrentGroup->Regions.begin(), CurrentGroup->Regions.end(), [&R](OutlinableRegion *Region) { R << ore::NV( "DebugLoc", @@ -1744,12 +1721,51 @@ continue; } + NegativeCostGroups.push_back(CurrentGroup); + for (OutlinableRegion *OS : CurrentGroup->Regions) + OS->reattachCandidate(); + } + + ExtractorAllocator.DestroyAll(); + + if (NegativeCostGroups.size() > 1) + llvm::stable_sort(NegativeCostGroups, + [](const OutlinableGroup *LHS, + const OutlinableGroup *RHS) { + return LHS->Benefit - LHS->Cost > RHS->Benefit - RHS->Cost; + }); + + std::vector FuncsToRemove; + for (OutlinableGroup *CG : NegativeCostGroups) { + OutlinableGroup &CurrentGroup = *CG; + + OutlinedRegions.clear(); + for (OutlinableRegion *Region : CurrentGroup.Regions) { + if(!compatibleWithOutlined(*Region)) + continue; + Region->splitCandidate(); + if (!Region->CandidateSplit) + continue; + OutlinedRegions.push_back(Region); + } + + CurrentGroup.Regions = std::move(OutlinedRegions); + if (CurrentGroup.Regions.size() < 2) { + for (OutlinableRegion *R : CurrentGroup.Regions) + R->reattachCandidate(); + continue; + } + LLVM_DEBUG(dbgs() << "Outlining regions with cost " << CurrentGroup.Cost << " and benefit " << CurrentGroup.Benefit << "\n"); // Create functions out of all the sections, and mark them as outlined. OutlinedRegions.clear(); for (OutlinableRegion *OS : CurrentGroup.Regions) { + std::vector BE = {OS->StartBB}; + OS->CE = new (ExtractorAllocator.Allocate()) + CodeExtractor(BE, nullptr, false, nullptr, nullptr, nullptr, false, + false, "outlined"); bool FunctionOutlined = extractSection(*OS); if (FunctionOutlined) { unsigned StartIdx = OS->Candidate->getStartIdx(); @@ -1767,9 +1783,6 @@ CurrentGroup.Regions = std::move(OutlinedRegions); - if (CurrentGroup.Regions.empty()) - continue; - OptimizationRemarkEmitter &ORE = getORE(*CurrentGroup.Regions[0]->Call->getFunction()); ORE.emit([&]() { diff --git a/llvm/test/Transforms/IROutliner/opt-remarks.ll b/llvm/test/Transforms/IROutliner/opt-remarks.ll --- a/llvm/test/Transforms/IROutliner/opt-remarks.ll +++ b/llvm/test/Transforms/IROutliner/opt-remarks.ll @@ -7,16 +7,25 @@ ; CHECK: remark: :0:0: did not outline 2 regions due to estimated increase of 12 instructions at locations ; CHECK-NEXT: remark: :0:0: did not outline 2 regions due to estimated increase of 5 instructions at locations -; CHECK-NEXT: remark: :0:0: outlined 2 regions with decrease of 2 instructions at locations +; CHECK-NEXT: remark: :0:0: did not outline 2 regions due to estimated increase of 0 instructions at locations ; CHECK-NEXT: remark: :0:0: did not outline 2 regions due to estimated increase of 10 instructions at locations +; CHECK-NEXT: remark: :0:0: did not outline 2 regions due to estimated increase of 1 instructions at locations ; CHECK-NEXT: remark: :0:0: did not outline 2 regions due to estimated increase of 11 instructions at locations ; CHECK-NEXT: remark: :0:0: did not outline 2 regions due to estimated increase of 12 instructions at locations +; CHECK-NEXT: remark: :0:0: did not outline 2 regions due to estimated increase of 2 instructions at locations +; CHECK-NEXT: remark: :0:0: did not outline 2 regions due to estimated increase of 3 instructions at locations ; CHECK-NEXT: remark: :0:0: did not outline 2 regions due to estimated increase of 13 instructions at locations +; CHECK-NEXT: remark: :0:0: did not outline 2 regions due to estimated increase of 4 instructions at locations ; CHECK-NEXT: remark: :0:0: did not outline 2 regions due to estimated increase of 14 instructions at locations +; CHECK-NEXT: remark: :0:0: did not outline 2 regions due to estimated increase of 5 instructions at locations ; CHECK-NEXT: remark: :0:0: did not outline 2 regions due to estimated increase of 10 instructions at locations ; CHECK-NEXT: remark: :0:0: did not outline 2 regions due to estimated increase of 11 instructions at locations +; CHECK-NEXT: remark: :0:0: did not outline 2 regions due to estimated increase of 6 instructions at locations +; CHECK-NEXT: remark: :0:0: did not outline 2 regions due to estimated increase of 7 instructions at locations ; CHECK-NEXT: remark: :0:0: did not outline 2 regions due to estimated increase of 17 instructions at locations ; CHECK-NEXT: remark: :0:0: did not outline 2 regions due to estimated increase of 13 instructions at locations +; CHECK-NEXT: remark: :0:0: did not outline 2 regions due to estimated increase of 8 instructions at locations +; CHECK-NEXT: remark: :0:0: outlined 2 regions with decrease of 2 instructions at locations ; YAML: --- !Missed ; YAML-NEXT: Pass: iroutliner @@ -46,15 +55,15 @@ ; YAML-NEXT: - String: ' ' ; YAML-NEXT: - DebugLoc: '' ; YAML-NEXT: ... -; YAML-NEXT: --- !Passed +; YAML-NEXT: --- !Missed ; YAML-NEXT: Pass: iroutliner -; YAML-NEXT: Name: Outlined -; YAML-NEXT: Function: function3.outlined +; YAML-NEXT: Name: WouldNotDecreaseSize +; YAML-NEXT: Function: function3 ; YAML-NEXT: Args: -; YAML-NEXT: - String: 'outlined ' +; YAML-NEXT: - String: 'did not outline ' ; YAML-NEXT: - String: '2' -; YAML-NEXT: - String: ' regions with decrease of ' -; YAML-NEXT: - Benefit: '2' +; YAML-NEXT: - String: ' regions due to estimated increase of ' +; YAML-NEXT: - InstructionIncrease: '0' ; YAML-NEXT: - String: ' instructions at locations ' ; YAML-NEXT: - DebugLoc: '' ; YAML-NEXT: - String: ' ' @@ -77,6 +86,20 @@ ; YAML-NEXT: --- !Missed ; YAML-NEXT: Pass: iroutliner ; YAML-NEXT: Name: WouldNotDecreaseSize +; YAML-NEXT: Function: function3 +; YAML-NEXT: Args: +; YAML-NEXT: - String: 'did not outline ' +; YAML-NEXT: - String: '2' +; YAML-NEXT: - String: ' regions due to estimated increase of ' +; YAML-NEXT: - InstructionIncrease: '1' +; YAML-NEXT: - String: ' instructions at locations ' +; YAML-NEXT: - DebugLoc: '' +; YAML-NEXT: - String: ' ' +; YAML-NEXT: - DebugLoc: '' +; YAML-NEXT: ... +; YAML-NEXT: --- !Missed +; YAML-NEXT: Pass: iroutliner +; YAML-NEXT: Name: WouldNotDecreaseSize ; YAML-NEXT: Function: function1 ; YAML-NEXT: Args: ; YAML-NEXT: - String: 'did not outline ' @@ -105,6 +128,34 @@ ; YAML-NEXT: --- !Missed ; YAML-NEXT: Pass: iroutliner ; YAML-NEXT: Name: WouldNotDecreaseSize +; YAML-NEXT: Function: function3 +; YAML-NEXT: Args: +; YAML-NEXT: - String: 'did not outline ' +; YAML-NEXT: - String: '2' +; YAML-NEXT: - String: ' regions due to estimated increase of ' +; YAML-NEXT: - InstructionIncrease: '2' +; YAML-NEXT: - String: ' instructions at locations ' +; YAML-NEXT: - DebugLoc: '' +; YAML-NEXT: - String: ' ' +; YAML-NEXT: - DebugLoc: '' +; YAML-NEXT: ... +; YAML-NEXT: --- !Missed +; YAML-NEXT: Pass: iroutliner +; YAML-NEXT: Name: WouldNotDecreaseSize +; YAML-NEXT: Function: function3 +; YAML-NEXT: Args: +; YAML-NEXT: - String: 'did not outline ' +; YAML-NEXT: - String: '2' +; YAML-NEXT: - String: ' regions due to estimated increase of ' +; YAML-NEXT: - InstructionIncrease: '3' +; YAML-NEXT: - String: ' instructions at locations ' +; YAML-NEXT: - DebugLoc: '' +; YAML-NEXT: - String: ' ' +; YAML-NEXT: - DebugLoc: '' +; YAML-NEXT: ... +; YAML-NEXT: --- !Missed +; YAML-NEXT: Pass: iroutliner +; YAML-NEXT: Name: WouldNotDecreaseSize ; YAML-NEXT: Function: function1 ; YAML-NEXT: Args: ; YAML-NEXT: - String: 'did not outline ' @@ -119,6 +170,20 @@ ; YAML-NEXT: --- !Missed ; YAML-NEXT: Pass: iroutliner ; YAML-NEXT: Name: WouldNotDecreaseSize +; YAML-NEXT: Function: function3 +; YAML-NEXT: Args: +; YAML-NEXT: - String: 'did not outline ' +; YAML-NEXT: - String: '2' +; YAML-NEXT: - String: ' regions due to estimated increase of ' +; YAML-NEXT: - InstructionIncrease: '4' +; YAML-NEXT: - String: ' instructions at locations ' +; YAML-NEXT: - DebugLoc: '' +; YAML-NEXT: - String: ' ' +; YAML-NEXT: - DebugLoc: '' +; YAML-NEXT: ... +; YAML-NEXT: --- !Missed +; YAML-NEXT: Pass: iroutliner +; YAML-NEXT: Name: WouldNotDecreaseSize ; YAML-NEXT: Function: function1 ; YAML-NEXT: Args: ; YAML-NEXT: - String: 'did not outline ' @@ -133,6 +198,20 @@ ; YAML-NEXT: --- !Missed ; YAML-NEXT: Pass: iroutliner ; YAML-NEXT: Name: WouldNotDecreaseSize +; YAML-NEXT: Function: function3 +; YAML-NEXT: Args: +; YAML-NEXT: - String: 'did not outline ' +; YAML-NEXT: - String: '2' +; YAML-NEXT: - String: ' regions due to estimated increase of ' +; YAML-NEXT: - InstructionIncrease: '5' +; YAML-NEXT: - String: ' instructions at locations ' +; YAML-NEXT: - DebugLoc: '' +; YAML-NEXT: - String: ' ' +; YAML-NEXT: - DebugLoc: '' +; YAML-NEXT: ... +; YAML-NEXT: --- !Missed +; YAML-NEXT: Pass: iroutliner +; YAML-NEXT: Name: WouldNotDecreaseSize ; YAML-NEXT: Function: function1 ; YAML-NEXT: Args: ; YAML-NEXT: - String: 'did not outline ' @@ -161,6 +240,34 @@ ; YAML-NEXT: --- !Missed ; YAML-NEXT: Pass: iroutliner ; YAML-NEXT: Name: WouldNotDecreaseSize +; YAML-NEXT: Function: function3 +; YAML-NEXT: Args: +; YAML-NEXT: - String: 'did not outline ' +; YAML-NEXT: - String: '2' +; YAML-NEXT: - String: ' regions due to estimated increase of ' +; YAML-NEXT: - InstructionIncrease: '6' +; YAML-NEXT: - String: ' instructions at locations ' +; YAML-NEXT: - DebugLoc: '' +; YAML-NEXT: - String: ' ' +; YAML-NEXT: - DebugLoc: '' +; YAML-NEXT: ... +; YAML-NEXT: --- !Missed +; YAML-NEXT: Pass: iroutliner +; YAML-NEXT: Name: WouldNotDecreaseSize +; YAML-NEXT: Function: function3 +; YAML-NEXT: Args: +; YAML-NEXT: - String: 'did not outline ' +; YAML-NEXT: - String: '2' +; YAML-NEXT: - String: ' regions due to estimated increase of ' +; YAML-NEXT: - InstructionIncrease: '7' +; YAML-NEXT: - String: ' instructions at locations ' +; YAML-NEXT: - DebugLoc: '' +; YAML-NEXT: - String: ' ' +; YAML-NEXT: - DebugLoc: '' +; YAML-NEXT: ... +; YAML-NEXT: --- !Missed +; YAML-NEXT: Pass: iroutliner +; YAML-NEXT: Name: WouldNotDecreaseSize ; YAML-NEXT: Function: function1 ; YAML-NEXT: Args: ; YAML-NEXT: - String: 'did not outline ' @@ -186,6 +293,34 @@ ; YAML-NEXT: - String: ' ' ; YAML-NEXT: - DebugLoc: '' ; YAML-NEXT: ... +; YAML-NEXT: --- !Missed +; YAML-NEXT: Pass: iroutliner +; YAML-NEXT: Name: WouldNotDecreaseSize +; YAML-NEXT: Function: function3 +; YAML-NEXT: Args: +; YAML-NEXT: - String: 'did not outline ' +; YAML-NEXT: - String: '2' +; YAML-NEXT: - String: ' regions due to estimated increase of ' +; YAML-NEXT: - InstructionIncrease: '8' +; YAML-NEXT: - String: ' instructions at locations ' +; YAML-NEXT: - DebugLoc: '' +; YAML-NEXT: - String: ' ' +; YAML-NEXT: - DebugLoc: '' +; YAML-NEXT: ... +; YAML-NEXT: --- !Passed +; YAML-NEXT: Pass: iroutliner +; YAML-NEXT: Name: Outlined +; YAML-NEXT: Function: function3.outlined +; YAML-NEXT: Args: +; YAML-NEXT: - String: 'outlined ' +; YAML-NEXT: - String: '2' +; YAML-NEXT: - String: ' regions with decrease of ' +; YAML-NEXT: - Benefit: '2' +; YAML-NEXT: - String: ' instructions at locations ' +; YAML-NEXT: - DebugLoc: '' +; YAML-NEXT: - String: ' ' +; YAML-NEXT: - DebugLoc: '' +; YAML-NEXT: ... define void @function1() #0 { entry: diff --git a/llvm/test/Transforms/IROutliner/outlining-bitcasts.ll b/llvm/test/Transforms/IROutliner/outlining-bitcasts.ll --- a/llvm/test/Transforms/IROutliner/outlining-bitcasts.ll +++ b/llvm/test/Transforms/IROutliner/outlining-bitcasts.ll @@ -100,7 +100,10 @@ ; CHECK-LABEL: @outline_bitcast_base2( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[D:%.*]] = alloca i32, align 4 -; CHECK-NEXT: call void @outlined_ir_func_1(i32* [[D]], i32 [[A:%.*]], i32 [[B:%.*]], i32 [[C:%.*]]) +; CHECK-NEXT: [[X:%.*]] = bitcast i32* [[D]] to i8* +; CHECK-NEXT: [[AL:%.*]] = add i32 [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[BL:%.*]] = add i32 [[B]], [[A]] +; CHECK-NEXT: [[CL:%.*]] = add i32 [[B]], [[C:%.*]] ; CHECK-NEXT: [[BUFFER:%.*]] = mul i32 [[A]], [[B]] ; CHECK-NEXT: [[Y:%.*]] = bitcast i32* [[D]] to i8* ; CHECK-NEXT: [[AM:%.*]] = add i32 [[A]], [[B]] @@ -113,7 +116,11 @@ ; CHECK-NEXT: ret void ; ; -; CHECK: @outlined_ir_func_0(i32* [[TMP0:%.*]], i32* [[TMP1:%.*]], i32* [[TMP2:%.*]], i32* [[TMP3:%.*]]) +; CHECK-LABEL: @outlined_ir_func_0( +; CHECK-NEXT: newFuncRoot: +; CHECK-NEXT: br label [[ENTRY_TO_OUTLINE:%.*]] +; CHECK: entry_after_outline.exitStub: +; CHECK-NEXT: ret void ; CHECK: entry_to_outline: ; CHECK-NEXT: store i32 2, i32* [[TMP0:%.*]], align 4 ; CHECK-NEXT: store i32 3, i32* [[TMP1:%.*]], align 4 @@ -124,12 +131,3 @@ ; CHECK-NEXT: [[CL:%.*]] = load i32, i32* [[TMP2]], align 4 ; CHECK-NEXT: br label [[ENTRY_AFTER_OUTLINE_EXITSTUB:%.*]] ; -; -; CHECK: @outlined_ir_func_1(i32* [[TMP0:%.*]], i32 [[TMP1:%.*]], i32 [[TMP2:%.*]], i32 [[TMP3:%.*]]) -; CHECK: entry_to_outline: -; CHECK-NEXT: [[X:%.*]] = bitcast i32* [[TMP0]] to i8* -; CHECK-NEXT: [[AL:%.*]] = add i32 [[TMP1]], [[TMP2]] -; CHECK-NEXT: [[BL:%.*]] = add i32 [[TMP2]], [[TMP1]] -; CHECK-NEXT: [[CL:%.*]] = add i32 [[TMP2]], [[TMP3]] -; CHECK-NEXT: br label [[ENTRY_AFTER_OUTLINE_EXITSTUB:%.*]] -;