Index: llvm/include/llvm/Transforms/IPO/IROutliner.h =================================================================== --- llvm/include/llvm/Transforms/IPO/IROutliner.h +++ llvm/include/llvm/Transforms/IPO/IROutliner.h @@ -70,6 +70,17 @@ IRInstructionData *NewFront = nullptr; IRInstructionData *NewBack = nullptr; + /// The number of extracted inputs from the CodeExtractor. + unsigned NumExtractedInputs; + + /// Mapping the extracted argument number to the argument number in the + /// overall function. Since there will be inputs, such as elevated constants + /// that are not the same in each region in a SimilarityGroup, or values that + /// cannot be sunk into the extracted section in every region, we must keep + /// track of which extracted argument maps to which overall argument. + DenseMap ExtractedArgToAgg; + DenseMap AggArgToExtracted; + /// Used to create an outlined function. CodeExtractor *CE = nullptr; @@ -151,6 +162,17 @@ pruneIncompatibleRegions(std::vector &CandidateVec, OutlinableGroup &CurrentGroup); + /// Create the function based on the overall types found in the current + /// regions being outlined. + /// + /// \param M - The module to outline from. + /// \param [in,out] CG - The OutlinableGroup for the regions to be outlined. + /// \param [in] FunctionNameSuffix - How many functions have we previously + /// created. + /// \returns the newly created function. + Function *createFunction(Module &M, OutlinableGroup &CG, + unsigned FunctionNameSuffix); + /// Identify the needed extracted inputs in a section, and add to the overall /// function if needed. /// @@ -165,6 +187,19 @@ /// \returns True if it was successfully outlined. bool extractSection(OutlinableRegion &Region); + /// For the similarities found, and the extracted sections, create a single + /// outlined function with appropriate output blocks as necessary. + /// + /// \param [in] M - The module to outline from + /// \param [in] CurrentGroup - The set of extracted sections to consolidate. + /// \param [in,out] FuncsToRemove - List of functions to remove from the + /// module after outlining is completed. + /// \param [in,out] OutlinedFunctionNum - the number of new outlined + /// functions. + void deduplicateExtractedSections(Module &M, OutlinableGroup &CurrentGroup, + std::vector &FuncsToRemove, + unsigned &OutlinedFunctionNum); + /// The set of outlined Instructions, identified by their location in the /// sequential ordering of instructions in a Module. DenseSet Outlined; Index: llvm/lib/Transforms/IPO/IROutliner.cpp =================================================================== --- llvm/lib/Transforms/IPO/IROutliner.cpp +++ llvm/lib/Transforms/IPO/IROutliner.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Transforms/IPO/IROutliner.h" + #include "llvm/Analysis/IRSimilarityIdentifier.h" #include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/IR/Attributes.h" @@ -38,6 +39,22 @@ /// 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 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; + /// For the \ref Regions, we look at every Value. If it is a constant, /// we check whether it is the same in Region. /// @@ -167,13 +184,14 @@ GVNToConstant.insert(std::make_pair(GVN, CST)); // If it was found and is not equal, it is not the same. We do not // handle this case yet, and exit early. - if (Inserted || (GVNToConstantIt->second == CST)) return true; + if (Inserted || (GVNToConstantIt->second == CST)) + return true; return false; } -/// Find whether \p Region matches the global value numbering to Constant mapping -/// found so far. +/// Find whether \p Region matches the global value numbering to Constant +/// mapping found so far. /// /// \param Region - The OutlinableRegion we are checking for constants /// \param NotSame - The set of global value numbers that do not have the same @@ -182,8 +200,8 @@ /// Region and false if not static bool collectRegionsConstants(OutlinableRegion &Region, - DenseMap &GVNToConstant, - DenseSet &NotSame) { + DenseMap &GVNToConstant, + DenseSet &NotSame) { IRSimilarityCandidate &IRSC = *Region.Candidate; for (IRInstructionData &ID : IRSC) { @@ -232,6 +250,45 @@ }); } +Function *IROutliner::createFunction(Module &M, OutlinableGroup &Group, + unsigned FunctionNameSuffix) { + assert(!Group.OutlinedFunction && "Function is already defined!"); + + Group.OutlinedFunctionType = FunctionType::get( + Type::getVoidTy(M.getContext()), Group.ArgumentTypes, false); + + // These functions will only be called from within the same module, so + // we can set an internal linkage. + Group.OutlinedFunction = Function::Create( + Group.OutlinedFunctionType, GlobalValue::InternalLinkage, + "outlined_ir_func_" + std::to_string(FunctionNameSuffix), M); + + return Group.OutlinedFunction; +} + +/// Move each BasicBlock in \p Old to \p New. +/// +/// \param [in] Old - the function to move the basic blocks from. +/// \param [in] New - The function to move the basic blocks to. +/// \returns the first return block for the function in New. +static BasicBlock *moveFunctionData(Function &Old, Function &New) { + Function::iterator CurrBB, NextBB, FinalBB; + BasicBlock *NewEnd = nullptr; + std::vector DebugInsts; + for (CurrBB = Old.begin(), FinalBB = Old.end(); CurrBB != FinalBB; + CurrBB = NextBB) { + NextBB = std::next(CurrBB); + CurrBB->removeFromParent(); + CurrBB->insertInto(&New); + Instruction *I = CurrBB->getTerminator(); + if (ReturnInst *RI = dyn_cast(I)) + NewEnd = &(*CurrBB); + } + + assert(NewEnd && "No return instruction for new function?"); + return NewEnd; +} + /// Find the GVN for the inputs that have been found by the CodeExtractor, /// excluding the ones that will be removed by llvm.assumes as these will be /// removed by the CodeExtractor. @@ -240,8 +297,8 @@ /// analyzing. /// \param [in] CurrentInputs - The set of inputs found by the /// CodeExtractor. -/// \param [out] CurrentInputNumbers - The global value numbers for the extracted -/// arguments. +/// \param [out] CurrentInputNumbers - The global value numbers for the +/// extracted arguments. static void mapInputsToGVNs(IRSimilarityCandidate &IRSC, SetVector &CurrentInputs, std::vector &EndInputNumbers) { @@ -311,12 +368,182 @@ return true; } -bool IROutliner::findAddInputsOutputs( - Module &M, OutlinableRegion &Region) { +/// Look over the inputs and map each input argument to an argument in the +/// overall function for the regions. This creates a way to replace the +/// arguments of the extracted function, with the arguments of the new overall +/// function. +/// +/// \param [in,out] Region - The region of code to be analyzed. +/// \param [in] InputsGVNs - The global value numbering of the input values +/// collected. +/// \param [in] ArgInputs - The values of the arguments to the extracted +/// function. +static void +findExtractedInputToOverallInputMapping(OutlinableRegion &Region, + ArrayRef InputGVNs, + SetVector &ArgInputs) { + IRSimilarityCandidate &IRSC = *Region.Candidate; + OutlinableGroup &Group = *Region.Parent; + + // This counts the argument number in the overall function. + unsigned TypeIndex = 0; + + // This counts the argument number in the extracted function. + unsigned OriginalIndex = 0; + + // Find the mapping of the extracted arguments to the arguments for the + // overall function. + for (unsigned InputVal : InputGVNs) { + Value *Input = *IRSC.fromGVN(InputVal); + + if (!Group.InputTypesSet) + Group.ArgumentTypes.push_back(Input->getType()); + + // It is not a constant, check if it is a sunken alloca. If it is not, + // create the mapping from extracted to overall. If it is, create the + // mapping of the index to the value. + assert(ArgInputs.count(Input) && "Input cannot be found!"); + + Region.ExtractedArgToAgg.try_emplace(OriginalIndex, TypeIndex); + Region.AggArgToExtracted.try_emplace(TypeIndex, OriginalIndex); + OriginalIndex++; + TypeIndex++; + } + + // If we do not have definitions for the OutlinableGroup holding the region, + // set the length of the inputs here. We should have the same inputs for + // all of the different regions contained in the OutlinableGroup since they + // are all structurally similar to one another + if (!Group.InputTypesSet) { + Group.NumAggregateInputs = TypeIndex; + Group.InputTypesSet = true; + } + + Region.NumExtractedInputs = OriginalIndex; +} + +bool IROutliner::findAddInputsOutputs(Module &M, OutlinableRegion &Region) { std::vector Inputs; SetVector ArgInputs; - return getCodeExtractorArguments(Region, Inputs, ArgInputs); + if (!getCodeExtractorArguments(Region, Inputs, ArgInputs)) + return false; + + // Map the inputs found by the CodeExtractor to the arguments found for + // the overall function. + findExtractedInputToOverallInputMapping(Region, Inputs, ArgInputs); + + return true; +} + +/// Replace the extracted function in the Region with a call to the overall +/// function constructed from the deduplicated similar regions, replacing and +/// remapping the values passed to the extracted function as arguments to the +/// new arguments of the overall function. +/// +/// \param [in] M - The module to outline from. +/// \param [in] Region - The regions of extracted code to be replaced with a new +/// function. +/// \returns a call instruction with the replaced function. +CallInst *replaceCalledFunction(Module &M, OutlinableRegion &Region) { + OutlinableGroup &Group = *Region.Parent; + CallInst *Call = Region.Call; + assert(Call && "Call to replace is nullptr?"); + Function *AggFunc = Group.OutlinedFunction; + assert(AggFunc && "Function to replace with is nullptr?"); + + // If the arguments are the same size, there are not values that need to be + // made argument, or different output registers to handle. We can simply + // replace the called function in this case. + assert(AggFunc->arg_size() == Call->arg_size() && + "Can only replace calls with the same number of arguments!"); + + LLVM_DEBUG(dbgs() << "Replace call to " << *Call << " with call to " + << *AggFunc << " with same number of arguments\n"); + Call->setCalledFunction(AggFunc); + return Call; +} + +// Within an extracted function, replace the argument uses of the extracted +// region with the arguments of the function for an OutlinableGroup. +// +// \param OS [in] - The region of extracted code to be changed. +static void replaceArgumentUses(OutlinableRegion &Region) { + OutlinableGroup &Group = *Region.Parent; + assert(Region.ExtractedFunction && "Region has no extracted function?"); + + for (unsigned ArgIdx = 0; ArgIdx < Region.ExtractedFunction->arg_size(); + ArgIdx++) { + assert(Region.ExtractedArgToAgg.find(ArgIdx) != + Region.ExtractedArgToAgg.end() && + "No mapping from extracted to outlined?"); + unsigned AggArgIdx = Region.ExtractedArgToAgg.find(ArgIdx)->second; + Argument *AggArg = Group.OutlinedFunction->getArg(AggArgIdx); + Argument *Arg = Region.ExtractedFunction->getArg(ArgIdx); + // The argument is an input, so we can simply replace it with the overall + // argument value + LLVM_DEBUG(dbgs() << "Replacing uses of input " << *Arg << " in function " + << *Region.ExtractedFunction << " with " << *AggArg + << " in function " << *Group.OutlinedFunction << "\n"); + Arg->replaceAllUsesWith(AggArg); + } +} + +/// Fill the new function that will serve as the replacement function for all of +/// the extracted regions of a certain structure from the first region in the +/// list of regions. Replace this first region's extracted function with the +/// new overall function. +/// +/// \param M [in] - The module we are outlining from. +/// \param CurrentGroup [in] - The group of regions to be outlined. +/// \param FuncsToRemove [in,out] - Extracted functions to erase from module +/// once outlining is complete. +static void fillOverallFunction(Module &M, OutlinableGroup &CurrentGroup, + std::vector &FuncsToRemove) { + OutlinableRegion *CurrentOS = CurrentGroup.Regions[0]; + + // Move first extracted function's instructions into new function + LLVM_DEBUG(dbgs() << "Move instructions from " + << *CurrentOS->ExtractedFunction << " to instruction " + << *CurrentGroup.OutlinedFunction << "\n"); + moveFunctionData(*CurrentOS->ExtractedFunction, + *CurrentGroup.OutlinedFunction); + + // Transfer the attributes + CurrentGroup.OutlinedFunction->setAttributes( + CurrentOS->ExtractedFunction->getAttributes()); + + CurrentGroup.OutlinedFunction->addFnAttr(Attribute::OptimizeForSize); + CurrentGroup.OutlinedFunction->addFnAttr(Attribute::MinSize); + CurrentGroup.OutlinedFunction->addFnAttr(Attribute::NoDuplicate); + + replaceArgumentUses(*CurrentOS); + + // Replace the call to the extracted function with the outlined function. + CurrentOS->Call = replaceCalledFunction(M, *CurrentOS); + + // We only delete the extracted funcitons at the end since we may need to + // reference instructions contained in them for mapping purposes. + FuncsToRemove.push_back(CurrentOS->ExtractedFunction); +} + +void IROutliner::deduplicateExtractedSections( + Module &M, OutlinableGroup &CurrentGroup, + std::vector &FuncsToRemove, unsigned &OutlinedFunctionNum) { + createFunction(M, CurrentGroup, OutlinedFunctionNum); + + fillOverallFunction(M, CurrentGroup, FuncsToRemove); + + // Do the same for the other extracted functions + for (unsigned Idx = 1; Idx < CurrentGroup.Regions.size(); Idx++) { + OutlinableRegion *CurrentOS = CurrentGroup.Regions[Idx]; + + replaceArgumentUses(*CurrentOS); + CurrentOS->Call = replaceCalledFunction(M, *CurrentOS); + FuncsToRemove.push_back(CurrentOS->ExtractedFunction); + } + + OutlinedFunctionNum++; } void IROutliner::pruneIncompatibleRegions( @@ -448,6 +675,7 @@ RHS[0].getLength() * RHS.size(); }); + std::vector FuncsToRemove; // Iterate over the possible sets of similarity. for (SimilarityGroup &CandidateVec : SimilarityCandidates) { OutlinableGroup CurrentGroup; @@ -491,7 +719,6 @@ // Create functions out of all the sections, and mark them as outlined. std::vector OutlinedRegions; for (OutlinableRegion *OS : OutlinableRegions) { - OutlinedFunctionNum++; bool FunctionOutlined = extractSection(*OS); if (FunctionOutlined) { unsigned StartIdx = OS->Candidate->getStartIdx(); @@ -504,8 +731,17 @@ } CurrentGroup.Regions = std::move(OutlinedRegions); + + if (CurrentGroup.Regions.empty()) + continue; + + deduplicateExtractedSections(M, CurrentGroup, FuncsToRemove, + OutlinedFunctionNum); } + for (Function *F : FuncsToRemove) + F->eraseFromParent(); + return OutlinedFunctionNum; } Index: llvm/test/Transforms/IROutliner/extraction.ll =================================================================== --- llvm/test/Transforms/IROutliner/extraction.ll +++ llvm/test/Transforms/IROutliner/extraction.ll @@ -10,7 +10,7 @@ ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 ; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4 ; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4 -; CHECK-NEXT: call void @extract1.outlined(i32* [[A]], i32* [[B]], i32* [[C]]) +; CHECK-NEXT: call void @outlined_ir_func_0(i32* [[A]], i32* [[B]], i32* [[C]]) ; CHECK-NEXT: ret void ; entry: @@ -32,7 +32,7 @@ ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 ; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4 ; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4 -; CHECK-NEXT: call void @extract2.outlined(i32* [[A]], i32* [[B]], i32* [[C]]) +; CHECK-NEXT: call void @outlined_ir_func_0(i32* [[A]], i32* [[B]], i32* [[C]]) ; CHECK-NEXT: ret void ; entry: @@ -65,7 +65,7 @@ ; CHECK-NEXT: store i32 [[ADD]], i32* [[OUTPUT]], align 4 ; CHECK-NEXT: [[TMP2:%.*]] = load i32, i32* [[OUTPUT]], align 4 ; CHECK-NEXT: [[TMP3:%.*]] = load i32, i32* [[OUTPUT]], align 4 -; CHECK-NEXT: call void @extract_outs1.outlined(i32 [[TMP2]], i32 [[ADD]], i32* [[RESULT]]) +; CHECK-NEXT: call void @outlined_ir_func_1(i32 [[TMP2]], i32 [[ADD]], i32* [[RESULT]]) ; CHECK-NEXT: ret void ; entry: @@ -102,7 +102,7 @@ ; CHECK-NEXT: [[ADD:%.*]] = add i32 [[TMP0]], [[TMP1]] ; CHECK-NEXT: store i32 [[ADD]], i32* [[OUTPUT]], align 4 ; CHECK-NEXT: [[TMP2:%.*]] = load i32, i32* [[OUTPUT]], align 4 -; CHECK-NEXT: call void @extract_outs2.outlined(i32 [[TMP2]], i32 [[ADD]], i32* [[RESULT]]) +; CHECK-NEXT: call void @outlined_ir_func_1(i32 [[TMP2]], i32 [[ADD]], i32* [[RESULT]]) ; CHECK-NEXT: ret void ; entry: Index: llvm/test/Transforms/IROutliner/illegal-assumes.ll =================================================================== --- llvm/test/Transforms/IROutliner/illegal-assumes.ll +++ llvm/test/Transforms/IROutliner/illegal-assumes.ll @@ -14,9 +14,9 @@ ; CHECK-NEXT: store i1 true, i1* [[D]], align 4 ; CHECK-NEXT: [[DL:%.*]] = load i1, i1* [[D]], align 1 ; CHECK-NEXT: [[SPLIT_INST:%.*]] = sub i1 [[DL]], [[DL]] -; CHECK-NEXT: call void @outline_assumes.outlined(i32* [[A]], i32* [[B]], i32* [[C]]) +; CHECK-NEXT: call void @outlined_ir_func_0(i32* [[A]], i32* [[B]], i32* [[C]]) ; CHECK-NEXT: call void @llvm.assume(i1 [[DL]]) -; CHECK-NEXT: call void @outline_assumes.outlined.1(i32* [[A]], i32* [[B]], i32* [[C]]) +; CHECK-NEXT: call void @outlined_ir_func_1(i32* [[A]], i32* [[B]], i32* [[C]]) ; CHECK-NEXT: ret void ; entry: @@ -46,9 +46,9 @@ ; CHECK-NEXT: [[D:%.*]] = alloca i1, align 4 ; CHECK-NEXT: store i1 false, i1* [[D]], align 4 ; CHECK-NEXT: [[DL:%.*]] = load i1, i1* [[D]], align 1 -; CHECK-NEXT: call void @outline_assumes2.outlined(i32* [[A]], i32* [[B]], i32* [[C]]) +; CHECK-NEXT: call void @outlined_ir_func_0(i32* [[A]], i32* [[B]], i32* [[C]]) ; CHECK-NEXT: call void @llvm.assume(i1 [[DL]]) -; CHECK-NEXT: call void @outline_assumes2.outlined.2(i32* [[A]], i32* [[B]], i32* [[C]]) +; CHECK-NEXT: call void @outlined_ir_func_1(i32* [[A]], i32* [[B]], i32* [[C]]) ; CHECK-NEXT: ret void ; entry: @@ -78,9 +78,9 @@ ; CHECK-NEXT: store i1 true, i1* [[D]], align 4 ; CHECK-NEXT: [[DL:%.*]] = load i1, i1* [[D]], align 1 ; CHECK-NEXT: [[SPLIT_INST:%.*]] = add i1 [[DL]], [[DL]] -; CHECK-NEXT: call void @outline_assumes3.outlined(i32* [[A]], i32* [[B]], i32* [[C]]) +; CHECK-NEXT: call void @outlined_ir_func_0(i32* [[A]], i32* [[B]], i32* [[C]]) ; CHECK-NEXT: call void @llvm.assume(i1 [[DL]]) -; CHECK-NEXT: call void @outline_assumes3.outlined.3(i32* [[A]]) +; CHECK-NEXT: call void @outlined_ir_func_2(i32* [[A]]) ; CHECK-NEXT: ret void ; entry: @@ -110,9 +110,9 @@ ; CHECK-NEXT: store i1 false, i1* [[D]], align 4 ; CHECK-NEXT: [[DL:%.*]] = load i1, i1* [[D]], align 1 ; CHECK-NEXT: [[SPLIT_INST:%.*]] = add i1 [[DL]], [[DL]] -; CHECK-NEXT: call void @outline_assumes4.outlined(i32* [[A]], i32* [[B]], i32* [[C]]) +; CHECK-NEXT: call void @outlined_ir_func_0(i32* [[A]], i32* [[B]], i32* [[C]]) ; CHECK-NEXT: call void @llvm.assume(i1 [[DL]]) -; CHECK-NEXT: call void @outline_assumes4.outlined.4(i32* [[A]]) +; CHECK-NEXT: call void @outlined_ir_func_2(i32* [[A]]) ; CHECK-NEXT: ret void ; entry: Index: llvm/test/Transforms/IROutliner/illegal-branches.ll =================================================================== --- llvm/test/Transforms/IROutliner/illegal-branches.ll +++ llvm/test/Transforms/IROutliner/illegal-branches.ll @@ -10,7 +10,7 @@ ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 ; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4 ; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4 -; CHECK-NEXT: call void @function1.outlined(i32* [[A]], i32* [[B]], i32* [[C]]) +; CHECK-NEXT: call void @outlined_ir_func_0(i32* [[A]], i32* [[B]], i32* [[C]]) ; CHECK-NEXT: br label [[NEXT:%.*]] ; CHECK: next: ; CHECK-NEXT: ret void @@ -33,7 +33,7 @@ ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 ; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4 ; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4 -; CHECK-NEXT: call void @function2.outlined(i32* [[A]], i32* [[B]], i32* [[C]]) +; CHECK-NEXT: call void @outlined_ir_func_0(i32* [[A]], i32* [[B]], i32* [[C]]) ; CHECK-NEXT: br label [[NEXT:%.*]] ; CHECK: next: ; CHECK-NEXT: ret void Index: llvm/test/Transforms/IROutliner/illegal-callbr.ll =================================================================== --- llvm/test/Transforms/IROutliner/illegal-callbr.ll +++ llvm/test/Transforms/IROutliner/illegal-callbr.ll @@ -9,11 +9,11 @@ ; CHECK-LABEL: @function1( ; CHECK-NEXT: bb0: ; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[A:%.*]], 4 -; CHECK-NEXT: call void @function1.outlined(i32 [[B:%.*]]) +; CHECK-NEXT: call void @outlined_ir_func_0(i32 [[B:%.*]]) ; CHECK-NEXT: callbr void asm "xorl $0, $0 ; CHECK-NEXT: to label [[NORMAL:%.*]] [label %fail1] ; CHECK: normal: -; CHECK-NEXT: call void @function1.outlined.1(i32 [[B]]) +; CHECK-NEXT: call void @outlined_ir_func_0(i32 [[B]]) ; CHECK-NEXT: ret i32 0 ; CHECK: fail1: ; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[B]], 1 @@ -39,11 +39,11 @@ ; CHECK-LABEL: @function2( ; CHECK-NEXT: bb0: ; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[A:%.*]], 4 -; CHECK-NEXT: call void @function2.outlined(i32 [[B:%.*]]) +; CHECK-NEXT: call void @outlined_ir_func_0(i32 [[B:%.*]]) ; CHECK-NEXT: callbr void asm "xorl $0, $0 ; CHECK-NEXT: to label [[NORMAL:%.*]] [label %fail1] ; CHECK: normal: -; CHECK-NEXT: call void @function2.outlined.2(i32 [[B]]) +; CHECK-NEXT: call void @outlined_ir_func_0(i32 [[B]]) ; CHECK-NEXT: ret i32 0 ; CHECK: fail1: ; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[B]], 1 Index: llvm/test/Transforms/IROutliner/illegal-calls.ll =================================================================== --- llvm/test/Transforms/IROutliner/illegal-calls.ll +++ llvm/test/Transforms/IROutliner/illegal-calls.ll @@ -13,9 +13,9 @@ ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 ; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4 ; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4 -; CHECK-NEXT: call void @outline_constants1.outlined.1(i32* [[A]], i32* [[B]], i32* [[C]]) +; CHECK-NEXT: call void @outlined_ir_func_1(i32* [[A]], i32* [[B]], i32* [[C]]) ; CHECK-NEXT: call void @f1(i32* [[A]], i32* [[B]]) -; CHECK-NEXT: call void @outline_constants1.outlined(i32* [[A]], i32* [[B]], i32* [[C]]) +; CHECK-NEXT: call void @outlined_ir_func_0(i32* [[A]], i32* [[B]], i32* [[C]]) ; CHECK-NEXT: ret void ; entry: @@ -38,9 +38,9 @@ ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 ; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4 ; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4 -; CHECK-NEXT: call void @outline_constants2.outlined.2(i32* [[A]], i32* [[B]], i32* [[C]]) +; CHECK-NEXT: call void @outlined_ir_func_1(i32* [[A]], i32* [[B]], i32* [[C]]) ; CHECK-NEXT: call void @f1(i32* [[A]], i32* [[B]]) -; CHECK-NEXT: call void @outline_constants2.outlined(i32* [[A]], i32* [[B]], i32* [[C]]) +; CHECK-NEXT: call void @outlined_ir_func_0(i32* [[A]], i32* [[B]], i32* [[C]]) ; CHECK-NEXT: ret void ; entry: Index: llvm/test/Transforms/IROutliner/illegal-catchpad.ll =================================================================== --- llvm/test/Transforms/IROutliner/illegal-catchpad.ll +++ llvm/test/Transforms/IROutliner/illegal-catchpad.ll @@ -18,7 +18,7 @@ ; CHECK-NEXT: [[CS1:%.*]] = catchswitch within none [label %catchpad1] unwind to caller ; CHECK: catchpad1: ; CHECK-NEXT: [[TMP0:%.*]] = catchpad within [[CS1]] [] -; CHECK-NEXT: call void @function1.outlined(i32* [[A]], i32* [[B]]) +; CHECK-NEXT: call void @outlined_ir_func_0(i32* [[A]], i32* [[B]]) ; CHECK-NEXT: br label [[NORMAL]] ; CHECK: normal: ; CHECK-NEXT: ret void @@ -49,7 +49,7 @@ ; CHECK-NEXT: [[CS1:%.*]] = catchswitch within none [label %catchpad1] unwind to caller ; CHECK: catchpad1: ; CHECK-NEXT: [[TMP0:%.*]] = catchpad within [[CS1]] [] -; CHECK-NEXT: call void @function2.outlined(i32* [[A]], i32* [[B]]) +; CHECK-NEXT: call void @outlined_ir_func_0(i32* [[A]], i32* [[B]]) ; CHECK-NEXT: br label [[NORMAL]] ; CHECK: normal: ; CHECK-NEXT: ret void Index: llvm/test/Transforms/IROutliner/illegal-cleanup.ll =================================================================== --- llvm/test/Transforms/IROutliner/illegal-cleanup.ll +++ llvm/test/Transforms/IROutliner/illegal-cleanup.ll @@ -16,7 +16,7 @@ ; CHECK-NEXT: to label [[NORMAL:%.*]] unwind label [[EXCEPTION:%.*]] ; CHECK: exception: ; CHECK-NEXT: [[CLEAN:%.*]] = cleanuppad within none [] -; CHECK-NEXT: call void @function1.outlined(i32* [[A]], i32* [[B]]) +; CHECK-NEXT: call void @outlined_ir_func_0(i32* [[A]], i32* [[B]]) ; CHECK-NEXT: br label [[NORMAL]] ; CHECK: normal: ; CHECK-NEXT: ret void @@ -43,7 +43,7 @@ ; CHECK-NEXT: to label [[NORMAL:%.*]] unwind label [[EXCEPTION:%.*]] ; CHECK: exception: ; CHECK-NEXT: [[CLEAN:%.*]] = cleanuppad within none [] -; CHECK-NEXT: call void @function2.outlined(i32* [[A]], i32* [[B]]) +; CHECK-NEXT: call void @outlined_ir_func_0(i32* [[A]], i32* [[B]]) ; CHECK-NEXT: br label [[NORMAL]] ; CHECK: normal: ; CHECK-NEXT: ret void Index: llvm/test/Transforms/IROutliner/illegal-frozen.ll =================================================================== --- llvm/test/Transforms/IROutliner/illegal-frozen.ll +++ llvm/test/Transforms/IROutliner/illegal-frozen.ll @@ -10,7 +10,7 @@ ; CHECK-NEXT: br label [[FIRST:%.*]] ; CHECK: first: ; CHECK-NEXT: [[C:%.*]] = freeze i32* [[A:%.*]] -; CHECK-NEXT: call void @function1.outlined(i32* [[C]], i32* [[B:%.*]]) +; CHECK-NEXT: call void @outlined_ir_func_0(i32* [[C]], i32* [[B:%.*]]) ; CHECK-NEXT: ret void ; CHECK: next: ; CHECK-NEXT: br label [[FIRST]] @@ -32,7 +32,7 @@ ; CHECK-NEXT: br label [[FIRST:%.*]] ; CHECK: first: ; CHECK-NEXT: [[C:%.*]] = freeze i32* [[A:%.*]] -; CHECK-NEXT: call void @function2.outlined(i32* [[C]], i32* [[B:%.*]]) +; CHECK-NEXT: call void @outlined_ir_func_0(i32* [[C]], i32* [[B:%.*]]) ; CHECK-NEXT: ret void ; CHECK: next: ; CHECK-NEXT: br label [[FIRST]] Index: llvm/test/Transforms/IROutliner/illegal-gep.ll =================================================================== --- llvm/test/Transforms/IROutliner/illegal-gep.ll +++ llvm/test/Transforms/IROutliner/illegal-gep.ll @@ -12,7 +12,7 @@ ; CHECK-NEXT: entry: ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 ; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4 -; CHECK-NEXT: call void @function1.outlined(i32* [[A]], i32* [[B]]) +; CHECK-NEXT: call void @outlined_ir_func_0(i32* [[A]], i32* [[B]]) ; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT_ST:%.*]], %struct.ST* [[S:%.*]], i64 1 ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT_ST]], %struct.ST* [[S]], i64 [[T:%.*]] ; CHECK-NEXT: ret void @@ -32,7 +32,7 @@ ; CHECK-NEXT: entry: ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 ; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4 -; CHECK-NEXT: call void @function2.outlined(i32* [[A]], i32* [[B]]) +; CHECK-NEXT: call void @outlined_ir_func_0(i32* [[A]], i32* [[B]]) ; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT_ST:%.*]], %struct.ST* [[S:%.*]], i64 1 ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT_ST]], %struct.ST* [[S]], i64 [[T:%.*]] ; CHECK-NEXT: ret void Index: llvm/test/Transforms/IROutliner/illegal-invoke.ll =================================================================== --- llvm/test/Transforms/IROutliner/illegal-invoke.ll +++ llvm/test/Transforms/IROutliner/illegal-invoke.ll @@ -12,7 +12,7 @@ ; CHECK-NEXT: entry: ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 ; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4 -; CHECK-NEXT: call void @function1.outlined(i32* [[A]], i32* [[B]]) +; CHECK-NEXT: call void @outlined_ir_func_0(i32* [[A]], i32* [[B]]) ; CHECK-NEXT: invoke void @llvm.donothing() ; CHECK-NEXT: to label [[NORMAL:%.*]] unwind label [[EXCEPTION:%.*]] ; CHECK: exception: @@ -40,7 +40,7 @@ ; CHECK-NEXT: entry: ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 ; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4 -; CHECK-NEXT: call void @function2.outlined(i32* [[A]], i32* [[B]]) +; CHECK-NEXT: call void @outlined_ir_func_0(i32* [[A]], i32* [[B]]) ; CHECK-NEXT: invoke void @llvm.donothing() ; CHECK-NEXT: to label [[NORMAL:%.*]] unwind label [[EXCEPTION:%.*]] ; CHECK: exception: Index: llvm/test/Transforms/IROutliner/illegal-landingpad.ll =================================================================== --- llvm/test/Transforms/IROutliner/illegal-landingpad.ll +++ llvm/test/Transforms/IROutliner/illegal-landingpad.ll @@ -17,7 +17,7 @@ ; CHECK: exception: ; CHECK-NEXT: [[CLEANUP:%.*]] = landingpad i8 ; CHECK-NEXT: cleanup -; CHECK-NEXT: call void @function1.outlined(i32* [[A]], i32* [[B]]) +; CHECK-NEXT: call void @outlined_ir_func_0(i32* [[A]], i32* [[B]]) ; CHECK-NEXT: br label [[NORMAL]] ; CHECK: normal: ; CHECK-NEXT: ret void @@ -45,7 +45,7 @@ ; CHECK: exception: ; CHECK-NEXT: [[CLEANUP:%.*]] = landingpad i8 ; CHECK-NEXT: cleanup -; CHECK-NEXT: call void @function2.outlined(i32* [[A]], i32* [[B]]) +; CHECK-NEXT: call void @outlined_ir_func_0(i32* [[A]], i32* [[B]]) ; CHECK-NEXT: br label [[NORMAL]] ; CHECK: normal: ; CHECK-NEXT: ret void Index: llvm/test/Transforms/IROutliner/illegal-memset.ll =================================================================== --- llvm/test/Transforms/IROutliner/illegal-memset.ll +++ llvm/test/Transforms/IROutliner/illegal-memset.ll @@ -12,7 +12,7 @@ ; CHECK-NEXT: [[POOL:%.*]] = alloca [59 x i64], align 4 ; CHECK-NEXT: [[TMP:%.*]] = bitcast [59 x i64]* [[POOL]] to i8* ; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 4 [[TMP]], i8 0, i64 236, i1 false) -; CHECK-NEXT: call void @function1.outlined(i64 [[N:%.*]], i64 [[X:%.*]], i64 [[Z:%.*]]) +; CHECK-NEXT: call void @outlined_ir_func_0(i64 [[N:%.*]], i64 [[X:%.*]], i64 [[Z:%.*]]) ; CHECK-NEXT: ret i64 0 ; entry: @@ -31,7 +31,7 @@ ; CHECK-NEXT: [[POOL:%.*]] = alloca [59 x i64], align 4 ; CHECK-NEXT: [[TMP:%.*]] = bitcast [59 x i64]* [[POOL]] to i8* ; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 4 [[TMP]], i8 0, i64 236, i1 false) -; CHECK-NEXT: call void @function2.outlined(i64 [[N:%.*]], i64 [[X:%.*]], i64 [[Z:%.*]]) +; CHECK-NEXT: call void @outlined_ir_func_0(i64 [[N:%.*]], i64 [[X:%.*]], i64 [[Z:%.*]]) ; CHECK-NEXT: ret i64 0 ; entry: Index: llvm/test/Transforms/IROutliner/illegal-phi-nodes.ll =================================================================== --- llvm/test/Transforms/IROutliner/illegal-phi-nodes.ll +++ llvm/test/Transforms/IROutliner/illegal-phi-nodes.ll @@ -10,7 +10,7 @@ ; CHECK-NEXT: br label [[FIRST:%.*]] ; CHECK: first: ; CHECK-NEXT: [[TMP0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ 3, [[NEXT:%.*]] ] -; CHECK-NEXT: call void @function1.outlined(i32* [[A:%.*]], i32* [[B:%.*]]) +; CHECK-NEXT: call void @outlined_ir_func_0(i32* [[A:%.*]], i32* [[B:%.*]]) ; CHECK-NEXT: ret void ; CHECK: next: ; CHECK-NEXT: br label [[FIRST]] @@ -32,7 +32,7 @@ ; CHECK-NEXT: br label [[FIRST:%.*]] ; CHECK: first: ; CHECK-NEXT: [[TMP0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ 3, [[NEXT:%.*]] ] -; CHECK-NEXT: call void @function2.outlined(i32* [[A:%.*]], i32* [[B:%.*]]) +; CHECK-NEXT: call void @outlined_ir_func_0(i32* [[A:%.*]], i32* [[B:%.*]]) ; CHECK-NEXT: ret void ; CHECK: next: ; CHECK-NEXT: br label [[FIRST]] Index: llvm/test/Transforms/IROutliner/legal-debug.ll =================================================================== --- llvm/test/Transforms/IROutliner/legal-debug.ll +++ llvm/test/Transforms/IROutliner/legal-debug.ll @@ -13,7 +13,7 @@ ; CHECK-NEXT: call void @llvm.dbg.value(metadata i32* [[B]], [[META11:metadata !.*]], metadata !DIExpression()), [[DBG18]] ; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4, [[DBG19:!dbg !.*]] ; CHECK-NEXT: call void @llvm.dbg.value(metadata i32* [[C]], [[META12:metadata !.*]], metadata !DIExpression()), [[DBG19]] -; CHECK-NEXT: call void @function1.outlined(i32* [[A]], i32* [[B]], i32* [[C]]), [[DBG20:!dbg !.*]] +; CHECK-NEXT: call void @outlined_ir_func_0(i32* [[A]], i32* [[B]], i32* [[C]]), [[DBG20:!dbg !.*]] ; CHECK-NEXT: ret void, [[DBG21:!dbg !.*]] ; entry: @@ -44,7 +44,7 @@ ; CHECK-NEXT: call void @llvm.dbg.value(metadata i32* [[B]], [[META25:metadata !.*]], metadata !DIExpression()), [[DBG31]] ; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4, [[DBG32:!dbg !.*]] ; CHECK-NEXT: call void @llvm.dbg.value(metadata i32* [[C]], [[META26:metadata !.*]], metadata !DIExpression()), [[DBG32]] -; CHECK-NEXT: call void @function2.outlined(i32* [[A]], i32* [[B]], i32* [[C]]), [[DBG33:!dbg !.*]] +; CHECK-NEXT: call void @outlined_ir_func_0(i32* [[A]], i32* [[B]], i32* [[C]]), [[DBG33:!dbg !.*]] ; CHECK-NEXT: ret void, [[DBG34:!dbg !.*]] ; entry: Index: llvm/test/Transforms/IROutliner/outlining-address-taken.ll =================================================================== --- llvm/test/Transforms/IROutliner/outlining-address-taken.ll +++ llvm/test/Transforms/IROutliner/outlining-address-taken.ll @@ -34,7 +34,7 @@ ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 ; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4 ; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4 -; CHECK-NEXT: call void @[[FUNCTION_2:.*]](i32* [[A]], i32* [[B]], i32* [[C]]) +; CHECK-NEXT: call void @[[FUNCTION_1]](i32* [[A]], i32* [[B]], i32* [[C]]) ; CHECK-NEXT: ret void ; entry: @@ -81,7 +81,7 @@ ret void } -; CHECK: define internal void @[[FUNCTION_2]](i32* [[ARG0:%.*]], i32* [[ARG1:%.*]], i32* [[ARG2:%.*]]) +; CHECK: define internal void @[[FUNCTION_1]](i32* [[ARG0:%.*]], i32* [[ARG1:%.*]], i32* [[ARG2:%.*]]) ; CHECK: entry_to_outline: ; CHECK-NEXT: store i32 2, i32* [[ARG0]], align 4 ; CHECK-NEXT: store i32 3, i32* [[ARG1]], align 4 Index: llvm/test/Transforms/IROutliner/outlining-different-constants.ll =================================================================== --- llvm/test/Transforms/IROutliner/outlining-different-constants.ll +++ llvm/test/Transforms/IROutliner/outlining-different-constants.ll @@ -39,7 +39,7 @@ ; CHECK-NEXT: store i32 2, i32* [[A]], align 4 ; CHECK-NEXT: store i32 3, i32* [[B]], align 4 ; CHECK-NEXT: store i32 4, i32* [[C]], align 4 -; CHECK-NEXT: call void @[[FUNCTION_1:.*]](i32* [[A]], i32* [[B]], i32* [[C]]) +; CHECK-NEXT: call void @[[FUNCTION_0]](i32* [[A]], i32* [[B]], i32* [[C]]) ; CHECK-NEXT: ret void ; entry: Index: llvm/test/Transforms/IROutliner/outlining-different-structure.ll =================================================================== --- llvm/test/Transforms/IROutliner/outlining-different-structure.ll +++ llvm/test/Transforms/IROutliner/outlining-different-structure.ll @@ -39,7 +39,7 @@ ; CHECK-NEXT: store i32 2, i32* [[A]], align 4 ; CHECK-NEXT: store i32 3, i32* [[B]], align 4 ; CHECK-NEXT: store i32 4, i32* [[C]], align 4 -; CHECK-NEXT: call void @[[FUNCTION_1:.*]](i32* [[A]], i32* [[B]], i32* [[C]]) +; CHECK-NEXT: call void @[[FUNCTION_0]](i32* [[A]], i32* [[B]], i32* [[C]]) ; CHECK-NEXT: ret void ; entry: Index: llvm/test/Transforms/IROutliner/outlining-same-constants.ll =================================================================== --- llvm/test/Transforms/IROutliner/outlining-same-constants.ll +++ llvm/test/Transforms/IROutliner/outlining-same-constants.ll @@ -32,7 +32,7 @@ ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 ; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4 ; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4 -; CHECK-NEXT: call void @[[FUNCTION_1:.*]](i32* [[A]], i32* [[B]], i32* [[C]]) +; CHECK-NEXT: call void @[[FUNCTION_0]](i32* [[A]], i32* [[B]], i32* [[C]]) ; CHECK-NEXT: ret void ; entry: Index: llvm/test/Transforms/IROutliner/outlining-same-globals.ll =================================================================== --- llvm/test/Transforms/IROutliner/outlining-same-globals.ll +++ llvm/test/Transforms/IROutliner/outlining-same-globals.ll @@ -10,7 +10,7 @@ define void @outline_globals1() { ; CHECK-LABEL: @outline_globals1( ; CHECK-NEXT: entry: -; CHECK-NEXT: call void @[[FUNCTION_0:.*]]() +; CHECK-NEXT: call void @outlined_ir_func_0() ; CHECK-NEXT: ret void ; entry: @@ -23,7 +23,7 @@ define void @outline_globals2() { ; CHECK-LABEL: @outline_globals2( ; CHECK-NEXT: entry: -; CHECK-NEXT: call void @[[FUNCTION_1:.*]]() +; CHECK-NEXT: call void @outlined_ir_func_0() ; CHECK-NEXT: ret void ; entry: @@ -33,14 +33,7 @@ ret void } -; CHECK: define internal void @[[FUNCTION_0]]() -; CHECK: entry_to_outline: -; CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @global1, align 4 -; CHECK-NEXT: [[TMP2:%.*]] = load i32, i32* @global2, align 4 -; CHECK-NEXT: [[ADD:%.*]] = add i32 [[TMP1]], [[TMP2]] - - -; CHECK: define internal void @[[FUNCTION_1]]() +; CHECK: define internal void @outlined_ir_func_0() ; CHECK: entry_to_outline: ; CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @global1, align 4 ; CHECK-NEXT: [[TMP2:%.*]] = load i32, i32* @global2, align 4