Author: Andrew Litteken Date: 2020-11-27T19:55:57-06:00 New Revision: a8a43b63388f4d348eaa1f1017d6ab3be89b4945
URL: https://github.com/llvm/llvm-project/commit/a8a43b63388f4d348eaa1f1017d6ab3be89b4945 DIFF: https://github.com/llvm/llvm-project/commit/a8a43b63388f4d348eaa1f1017d6ab3be89b4945.diff LOG: Revert "[IRSim][IROutliner] Adding the extraction basics for the IROutliner." Reverting commit due to address sanitizer errors. > Extracting the similar regions is the first step in the IROutliner. > > Using the IRSimilarityIdentifier, we collect the SimilarityGroups and > sort them by how many instructions will be removed. Each > IRSimilarityCandidate is used to define an OutlinableRegion. Each > region is ordered by their occurrence in the Module and the regions that > are not compatible with previously outlined regions are discarded. > > Each region is then extracted with the CodeExtractor into its own > function. > > We test that correctly extract in: > test/Transforms/IROutliner/extraction.ll > test/Transforms/IROutliner/address-taken.ll > test/Transforms/IROutliner/outlining-same-globals.ll > test/Transforms/IROutliner/outlining-same-constants.ll > test/Transforms/IROutliner/outlining-different-structure.ll > > Reviewers: paquette, jroelofs, yroux > > Differential Revision: https://reviews.llvm.org/D86975 This reverts commit bf899e891387d07dfd12de195ce2a16f62afd5e0. Added: Modified: llvm/include/llvm/InitializePasses.h llvm/include/llvm/Transforms/IPO.h llvm/lib/Passes/PassBuilder.cpp llvm/lib/Passes/PassRegistry.def llvm/lib/Transforms/IPO/CMakeLists.txt llvm/lib/Transforms/IPO/IPO.cpp llvm/lib/Transforms/IPO/PassManagerBuilder.cpp Removed: llvm/include/llvm/Transforms/IPO/IROutliner.h llvm/lib/Transforms/IPO/IROutliner.cpp llvm/test/Transforms/IROutliner/extraction.ll llvm/test/Transforms/IROutliner/outlining-address-taken.ll llvm/test/Transforms/IROutliner/outlining-different-structure.ll llvm/test/Transforms/IROutliner/outlining-same-constants.ll llvm/test/Transforms/IROutliner/outlining-same-globals.ll ################################################################################ diff --git a/llvm/include/llvm/InitializePasses.h b/llvm/include/llvm/InitializePasses.h index 0ec87fb09e49..0d0eaf0bca83 100644 --- a/llvm/include/llvm/InitializePasses.h +++ b/llvm/include/llvm/InitializePasses.h @@ -183,7 +183,6 @@ void initializeHotColdSplittingLegacyPassPass(PassRegistry&); void initializeHWAddressSanitizerLegacyPassPass(PassRegistry &); void initializeIPSCCPLegacyPassPass(PassRegistry&); void initializeIRCELegacyPassPass(PassRegistry&); -void initializeIROutlinerLegacyPassPass(PassRegistry&); void initializeIRSimilarityIdentifierWrapperPassPass(PassRegistry&); void initializeIRTranslatorPass(PassRegistry&); void initializeIVUsersWrapperPassPass(PassRegistry&); diff --git a/llvm/include/llvm/Transforms/IPO.h b/llvm/include/llvm/Transforms/IPO.h index af357181597a..1918ad76a270 100644 --- a/llvm/include/llvm/Transforms/IPO.h +++ b/llvm/include/llvm/Transforms/IPO.h @@ -215,11 +215,6 @@ ModulePass *createMergeFunctionsPass(); /// function(s). ModulePass *createHotColdSplittingPass(); -//===----------------------------------------------------------------------===// -/// createIROutlinerPass - This pass finds similar code regions and factors -/// those regions out into functions. -ModulePass *createIROutlinerPass(); - //===----------------------------------------------------------------------===// /// createPartialInliningPass - This pass inlines parts of functions. /// diff --git a/llvm/include/llvm/Transforms/IPO/IROutliner.h b/llvm/include/llvm/Transforms/IPO/IROutliner.h deleted file mode 100644 index dd169602f004..000000000000 --- a/llvm/include/llvm/Transforms/IPO/IROutliner.h +++ /dev/null @@ -1,186 +0,0 @@ -//===- IROutliner.h - Extract similar IR regions into functions ------------==// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// \file -// The interface file for the IROutliner which is used by the IROutliner Pass. -// -// The outliner uses the IRSimilarityIdentifier to identify the similar regions -// of code. It evaluates each set of IRSimilarityCandidates with an estimate of -// whether it will provide code size reduction. Each region is extracted using -// the code extractor. These extracted functions are consolidated into a single -// function and called from the extracted call site. -// -// For example: -// \code -// %1 = add i32 %a, %b -// %2 = add i32 %b, %a -// %3 = add i32 %b, %a -// %4 = add i32 %a, %b -// \endcode -// would become function -// \code -// define internal void outlined_ir_function(i32 %0, i32 %1) { -// %1 = add i32 %0, %1 -// %2 = add i32 %1, %0 -// ret void -// } -// \endcode -// with calls: -// \code -// call void outlined_ir_function(i32 %a, i32 %b) -// call void outlined_ir_function(i32 %b, i32 %a) -// \endcode -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TRANSFORMS_IPO_IROUTLINER_H -#define LLVM_TRANSFORMS_IPO_IROUTLINER_H - -#include "llvm/Analysis/IRSimilarityIdentifier.h" -#include "llvm/IR/PassManager.h" -#include "llvm/IR/ValueMap.h" -#include "llvm/Transforms/Utils/CodeExtractor.h" -#include <set> - -struct OutlinableGroup; - -namespace llvm { -using namespace IRSimilarity; - -class Module; -class TargetTransformInfo; -class OptimizationRemarkEmitter; - -/// The OutlinableRegion holds all the information for a specific region, or -/// sequence of instructions. This includes what values need to be hoisted to -/// arguments from the extracted function, inputs and outputs to the region, and -/// mapping from the extracted function arguments to overall function arguments. -struct OutlinableRegion { - /// Describes the region of code. - IRSimilarityCandidate *Candidate; - - /// If this region is outlined, the front and back IRInstructionData could - /// potentially become invalidated if the only new instruction is a call. - /// This ensures that we replace in the instruction in the IRInstructionData. - IRInstructionData *NewFront = nullptr; - IRInstructionData *NewBack = nullptr; - - /// Used to create an outlined function. - CodeExtractor *CE = nullptr; - - /// The call site of the extracted region. - CallInst *Call = nullptr; - - /// The function for the extracted region. - Function *ExtractedFunction = nullptr; - - /// Flag for whether we have split out the IRSimilarityCanidate. That is, - /// make the region contained the IRSimilarityCandidate its own BasicBlock. - bool CandidateSplit = false; - - /// Flag for whether we should not consider this region for extraction. - bool IgnoreRegion = false; - - /// The BasicBlock that is before the start of the region BasicBlock, - /// only defined when the region has been split. - BasicBlock *PrevBB = nullptr; - - /// The BasicBlock that contains the starting instruction of the region. - BasicBlock *StartBB = nullptr; - - /// The BasicBlock that contains the ending instruction of the region. - BasicBlock *EndBB = nullptr; - - /// The BasicBlock that is after the start of the region BasicBlock, - /// only defined when the region has been split. - BasicBlock *FollowBB = nullptr; - - /// The Outlinable Group that contains this region and structurally similar - /// regions to this region. - OutlinableGroup *Parent = nullptr; - - OutlinableRegion(IRSimilarityCandidate &C, OutlinableGroup &Group) - : Candidate(&C), Parent(&Group) { - StartBB = C.getStartBB(); - EndBB = C.getEndBB(); - } - - /// For the contained region, split the parent BasicBlock at the starting and - /// ending instructions of the contained IRSimilarityCandidate. - void splitCandidate(); - - /// For the contained region, reattach the BasicBlock at the starting and - /// ending instructions of the contained IRSimilarityCandidate, or if the - /// function has been extracted, the start and end of the BasicBlock - /// containing the called function. - void reattachCandidate(); -}; - -/// 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 -/// to identify the similar regions of code, and then extracts the similar -/// sections into a single function. See the above for an example as to -/// how code is extracted and consolidated into a single function. -class IROutliner { -public: - IROutliner(function_ref<TargetTransformInfo &(Function &)> GTTI, - function_ref<IRSimilarityIdentifier &(Module &)> GIRSI) - : getTTI(GTTI), getIRSI(GIRSI) {} - bool run(Module &M); - -private: - /// Find repeated similar code sequences in \p M and outline them into new - /// Functions. - /// - /// \param [in] M - The module to outline from. - /// \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. - void - pruneIncompatibleRegions(std::vector<IRSimilarityCandidate> &CandidateVec, - OutlinableGroup &CurrentGroup); - - /// Extract \p Region into its own function. - /// - /// \param [in] Region - The region to be extracted into its own function. - /// \returns True if it was successfully outlined. - bool extractSection(OutlinableRegion &Region); - - /// The set of outlined Instructions, identified by their location in the - /// sequential ordering of instructions in a Module. - DenseSet<unsigned> Outlined; - - /// TargetTransformInfo lambda for target specific information. - function_ref<TargetTransformInfo &(Function &)> getTTI; - - /// IRSimilarityIdentifier lambda to retrieve IRSimilarityIdentifier. - function_ref<IRSimilarityIdentifier &(Module &)> getIRSI; - - /// The memory allocator used to allocate the OutlinableRegions and - /// CodeExtractors. - BumpPtrAllocator OutlinerAllocator; -}; - -/// Pass to outline similar regions. -class IROutlinerPass : public PassInfoMixin<IROutlinerPass> { -public: - PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); -}; - -} // end namespace llvm - -#endif // LLVM_TRANSFORMS_IPO_IROUTLINER_H diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp index 528f40b1de85..2a9b0c1e4f6b 100644 --- a/llvm/lib/Passes/PassBuilder.cpp +++ b/llvm/lib/Passes/PassBuilder.cpp @@ -103,7 +103,6 @@ #include "llvm/Transforms/IPO/InferFunctionAttrs.h" #include "llvm/Transforms/IPO/Inliner.h" #include "llvm/Transforms/IPO/Internalize.h" -#include "llvm/Transforms/IPO/IROutliner.h" #include "llvm/Transforms/IPO/LoopExtractor.h" #include "llvm/Transforms/IPO/LowerTypeTests.h" #include "llvm/Transforms/IPO/MergeFunctions.h" @@ -280,7 +279,6 @@ extern cl::opt<bool> EnableConstraintElimination; extern cl::opt<bool> EnableGVNHoist; extern cl::opt<bool> EnableGVNSink; extern cl::opt<bool> EnableHotColdSplit; -extern cl::opt<bool> EnableIROutliner; extern cl::opt<bool> EnableOrderFileInstrumentation; extern cl::opt<bool> EnableCHR; extern cl::opt<bool> EnableUnrollAndJam; @@ -1258,13 +1256,6 @@ PassBuilder::buildModuleOptimizationPipeline(OptimizationLevel Level, if (EnableHotColdSplit && !LTOPreLink) MPM.addPass(HotColdSplittingPass()); - // Search the code for similar regions of code. If enough similar regions can - // be found where extracting the regions into their own function will decrease - // the size of the program, we extract the regions, a deduplicate the - // structurally similar regions. - if (EnableIROutliner) - MPM.addPass(IROutlinerPass()); - // LoopSink pass sinks instructions hoisted by LICM, which serves as a // canonicalization pass that enables other optimizations. As a result, // LoopSink pass needs to be a very late IR pass to avoid undoing LICM diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def index c9bc0553ebcb..7f0f51ad0977 100644 --- a/llvm/lib/Passes/PassRegistry.def +++ b/llvm/lib/Passes/PassRegistry.def @@ -68,7 +68,6 @@ MODULE_PASS("instrprof", InstrProfiling()) MODULE_PASS("internalize", InternalizePass()) MODULE_PASS("invalidate<all>", InvalidateAllAnalysesPass()) MODULE_PASS("ipsccp", IPSCCPPass()) -MODULE_PASS("iroutliner", IROutlinerPass()) MODULE_PASS("print-ir-similarity", IRSimilarityAnalysisPrinterPass(dbgs())) MODULE_PASS("loop-extract", LoopExtractorPass()) MODULE_PASS("lowertypetests", LowerTypeTestsPass()) diff --git a/llvm/lib/Transforms/IPO/CMakeLists.txt b/llvm/lib/Transforms/IPO/CMakeLists.txt index 840c1aabecbb..66e772c61b0a 100644 --- a/llvm/lib/Transforms/IPO/CMakeLists.txt +++ b/llvm/lib/Transforms/IPO/CMakeLists.txt @@ -20,7 +20,6 @@ add_llvm_component_library(LLVMipo GlobalSplit.cpp HotColdSplitting.cpp IPO.cpp - IROutliner.cpp InferFunctionAttrs.cpp InlineSimple.cpp Inliner.cpp diff --git a/llvm/lib/Transforms/IPO/IPO.cpp b/llvm/lib/Transforms/IPO/IPO.cpp index f4c12dd7f4cd..52c4d3229bb7 100644 --- a/llvm/lib/Transforms/IPO/IPO.cpp +++ b/llvm/lib/Transforms/IPO/IPO.cpp @@ -36,7 +36,6 @@ void llvm::initializeIPO(PassRegistry &Registry) { initializeGlobalOptLegacyPassPass(Registry); initializeGlobalSplitPass(Registry); initializeHotColdSplittingLegacyPassPass(Registry); - initializeIROutlinerLegacyPassPass(Registry); initializeAlwaysInlinerLegacyPassPass(Registry); initializeSimpleInlinerPass(Registry); initializeInferFunctionAttrsLegacyPassPass(Registry); diff --git a/llvm/lib/Transforms/IPO/IROutliner.cpp b/llvm/lib/Transforms/IPO/IROutliner.cpp deleted file mode 100644 index f5fdad76df9b..000000000000 --- a/llvm/lib/Transforms/IPO/IROutliner.cpp +++ /dev/null @@ -1,369 +0,0 @@ -//===- IROutliner.cpp -- Outline Similar Regions ----------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -/// -/// \file -// Implementation for the IROutliner which is used by the IROutliner Pass. -// -//===----------------------------------------------------------------------===// - -#include "llvm/Transforms/IPO/IROutliner.h" -#include "llvm/Analysis/IRSimilarityIdentifier.h" -#include "llvm/Analysis/TargetTransformInfo.h" -#include "llvm/IR/Attributes.h" -#include "llvm/IR/PassManager.h" -#include "llvm/InitializePasses.h" -#include "llvm/Pass.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Transforms/IPO.h" -#include <map> -#include <set> -#include <vector> - -#define DEBUG_TYPE "iroutliner" - -using namespace llvm; -using namespace IRSimilarity; - -/// 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 diff erent 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<OutlinableRegion *> Regions; - - /// Flag for whether we should not consider this group of OutlinableRegions - /// for extraction. - bool IgnoreGroup = false; -}; - -/// Move the contents of \p SourceBB to before the last instruction of \p -/// TargetBB. -/// \param SourceBB - the BasicBlock to pull Instructions from. -/// \param TargetBB - the BasicBlock to put Instruction into. -static void moveBBContents(BasicBlock &SourceBB, BasicBlock &TargetBB) { - BasicBlock::iterator BBCurr, BBEnd, BBNext; - for (BBCurr = SourceBB.begin(), BBEnd = SourceBB.end(); BBCurr != BBEnd; - BBCurr = BBNext) { - BBNext = std::next(BBCurr); - BBCurr->moveBefore(TargetBB, TargetBB.end()); - } -} - -void OutlinableRegion::splitCandidate() { - assert(!CandidateSplit && "Candidate already split!"); - - Instruction *StartInst = (*Candidate->begin()).Inst; - Instruction *EndInst = (*Candidate->end()).Inst; - assert(StartInst && EndInst && "Expected a start and end instruction?"); - StartBB = StartInst->getParent(); - PrevBB = StartBB; - - // The basic block gets split like so: - // block: block: - // inst1 inst1 - // inst2 inst2 - // region1 br block_to_outline - // region2 block_to_outline: - // region3 -> region1 - // region4 region2 - // inst3 region3 - // inst4 region4 - // br block_after_outline - // block_after_outline: - // inst3 - // inst4 - - std::string OriginalName = PrevBB->getName().str(); - - StartBB = PrevBB->splitBasicBlock(StartInst, OriginalName + "_to_outline"); - - // This is the case for the inner block since we do not have to include - // multiple blocks. - EndBB = StartBB; - FollowBB = EndBB->splitBasicBlock(EndInst, OriginalName + "_after_outline"); - - CandidateSplit = true; -} - -void OutlinableRegion::reattachCandidate() { - assert(CandidateSplit && "Candidate is not split!"); - - // The basic block gets reattached like so: - // block: block: - // inst1 inst1 - // inst2 inst2 - // br block_to_outline region1 - // block_to_outline: -> region2 - // region1 region3 - // region2 region4 - // region3 inst3 - // region4 inst4 - // br block_after_outline - // block_after_outline: - // inst3 - // inst4 - assert(StartBB != nullptr && "StartBB for Candidate is not defined!"); - assert(FollowBB != nullptr && "StartBB for Candidate is not defined!"); - - // StartBB should only have one predecessor since we put an unconditional - // branch at the end of PrevBB when we split the BasicBlock. - PrevBB = StartBB->getSinglePredecessor(); - assert(PrevBB != nullptr && - "No Predecessor for the region start basic block!"); - - assert(PrevBB->getTerminator() && "Terminator removed from PrevBB!"); - assert(EndBB->getTerminator() && "Terminator removed from EndBB!"); - PrevBB->getTerminator()->eraseFromParent(); - EndBB->getTerminator()->eraseFromParent(); - - moveBBContents(*StartBB, *PrevBB); - - BasicBlock *PlacementBB = PrevBB; - if (StartBB != EndBB) - PlacementBB = EndBB; - moveBBContents(*FollowBB, *PlacementBB); - - PrevBB->replaceSuccessorsPhiUsesWith(StartBB, PrevBB); - PrevBB->replaceSuccessorsPhiUsesWith(FollowBB, PlacementBB); - StartBB->eraseFromParent(); - FollowBB->eraseFromParent(); - - // Make sure to save changes back to the StartBB. - StartBB = PrevBB; - EndBB = nullptr; - PrevBB = nullptr; - FollowBB = nullptr; - - CandidateSplit = false; -} - -void IROutliner::pruneIncompatibleRegions( - std::vector<IRSimilarityCandidate> &CandidateVec, - OutlinableGroup &CurrentGroup) { - bool PreviouslyOutlined; - - // Sort from beginning to end, so the IRSimilarityCandidates are in order. - stable_sort(CandidateVec, [](const IRSimilarityCandidate &LHS, - const IRSimilarityCandidate &RHS) { - return LHS.getStartIdx() < RHS.getStartIdx(); - }); - - unsigned CurrentEndIdx = 0; - for (IRSimilarityCandidate &IRSC : CandidateVec) { - PreviouslyOutlined = false; - unsigned StartIdx = IRSC.getStartIdx(); - unsigned EndIdx = IRSC.getEndIdx(); - - for (unsigned Idx = StartIdx; Idx <= EndIdx; Idx++) - if (Outlined.find(Idx) != Outlined.end()) { - PreviouslyOutlined = true; - break; - } - - if (PreviouslyOutlined) - continue; - - // TODO: If in the future we can outline across BasicBlocks, we will need to - // check all BasicBlocks contained in the region. - if (IRSC.getStartBB()->hasAddressTaken()) - continue; - - // Greedily prune out any regions that will overlap with already chosen - // regions. - if (CurrentEndIdx != 0 && StartIdx <= CurrentEndIdx) - continue; - - OutlinableRegion *OS = new (OutlinerAllocator.Allocate<OutlinableRegion>()) - OutlinableRegion(IRSC, CurrentGroup); - CurrentGroup.Regions.push_back(OS); - - CurrentEndIdx = EndIdx; - } -} - -bool IROutliner::extractSection(OutlinableRegion &Region) { - assert(Region.StartBB != nullptr && - "StartBB for the OutlinableRegion is nullptr!"); - assert(Region.FollowBB != nullptr && - "StartBB for the OutlinableRegion is nullptr!"); - Function *OrigF = Region.StartBB->getParent(); - CodeExtractorAnalysisCache CEAC(*OrigF); - Region.ExtractedFunction = Region.CE->extractCodeRegion(CEAC); - - // If the extraction was successful, find the BasicBlock, and reassign the - // OutlinableRegion blocks - if (!Region.ExtractedFunction) { - LLVM_DEBUG(dbgs() << "CodeExtractor failed to outline " << Region.StartBB - << "\n"); - Region.reattachCandidate(); - return false; - } - - BasicBlock *RewrittenBB = Region.FollowBB->getSinglePredecessor(); - Region.StartBB = RewrittenBB; - Region.EndBB = RewrittenBB; - - // The sequences of outlinable regions has now changed. We must fix the - // IRInstructionDataList for consistency. Although they may not be illegal - // instructions, they should not be compared with anything else as they - // should not be outlined in this round. So marking these as illegal is - // allowed. - IRInstructionDataList *IDL = Region.Candidate->front()->IDL; - Region.NewFront = new (OutlinerAllocator.Allocate<IRInstructionData>()) - IRInstructionData(*RewrittenBB->begin(), false, *IDL); - Region.NewBack = new (OutlinerAllocator.Allocate<IRInstructionData>()) - IRInstructionData(*std::prev(std::prev(RewrittenBB->end())), false, *IDL); - - // Insert the first IRInstructionData of the new region in front of the - // first IRInstructionData of the IRSimilarityCandidate. - IDL->insert(Region.Candidate->begin(), *Region.NewFront); - // Insert the first IRInstructionData of the new region after the - // last IRInstructionData of the IRSimilarityCandidate. - IDL->insert(Region.Candidate->end(), *Region.NewBack); - // Remove the IRInstructionData from the IRSimilarityCandidate. - IDL->erase(Region.Candidate->begin(), std::prev(Region.Candidate->end())); - - assert(RewrittenBB != nullptr && - "Could not find a predecessor after extraction!"); - - // Iterate over the new set of instructions to find the new call - // instruction. - for (Instruction &I : *RewrittenBB) - if (CallInst *CI = dyn_cast<CallInst>(&I)) - if (Region.ExtractedFunction == CI->getCalledFunction()) { - Region.Call = CI; - break; - } - Region.reattachCandidate(); - return true; -} - -unsigned IROutliner::doOutline(Module &M) { - // Find the possibile similarity sections. - IRSimilarityIdentifier &Identifier = getIRSI(M); - SimilarityGroupList &SimilarityCandidates = *Identifier.getSimilarity(); - - // Sort them by size of extracted sections - unsigned OutlinedFunctionNum = 0; - // If we only have one SimilarityGroup in SimilarityCandidates, we do not have - // to sort them by the potential number of instructions to be outlined - if (SimilarityCandidates.size() > 1) - llvm::stable_sort(SimilarityCandidates, - [](const std::vector<IRSimilarityCandidate> &LHS, - const std::vector<IRSimilarityCandidate> &RHS) { - return LHS[0].getLength() * LHS.size() > - RHS[0].getLength() * RHS.size(); - }); - - // Iterate over the possible sets of similarity. - for (SimilarityGroup &CandidateVec : SimilarityCandidates) { - OutlinableGroup CurrentGroup; - - // Remove entries that were previously outlined - 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) - continue; - - // Create a CodeExtractor for each outlinable region. - for (OutlinableRegion *OS : CurrentGroup.Regions) { - // Break the outlinable region out of its parent BasicBlock into its own - // BasicBlocks (see function implementation). - OS->splitCandidate(); - std::vector<BasicBlock *> BE = {OS->StartBB}; - OS->CE = new (OutlinerAllocator.Allocate<CodeExtractor>()) - CodeExtractor(BE, nullptr, false, nullptr, nullptr, nullptr, false, - false, "outlined"); - } - - // Create functions out of all the sections, and mark them as outlined - std::vector<OutlinableRegion *> OutlinedRegions; - for (OutlinableRegion *OS : CurrentGroup.Regions) { - OutlinedFunctionNum++; - bool FunctionOutlined = extractSection(*OS); - if (FunctionOutlined) { - unsigned StartIdx = OS->Candidate->getStartIdx(); - unsigned EndIdx = OS->Candidate->getEndIdx(); - for (unsigned Idx = StartIdx; Idx <= EndIdx; Idx++) - Outlined.insert(Idx); - - OutlinedRegions.push_back(OS); - } - } - - CurrentGroup.Regions = std::move(OutlinedRegions); - } - - return OutlinedFunctionNum; -} - -bool IROutliner::run(Module &M) { return doOutline(M) > 0; } - -// Pass Manager Boilerplate -class IROutlinerLegacyPass : public ModulePass { -public: - static char ID; - IROutlinerLegacyPass() : ModulePass(ID) { - initializeIROutlinerLegacyPassPass(*PassRegistry::getPassRegistry()); - } - - void getAnalysisUsage(AnalysisUsage &AU) const override { - AU.addRequired<TargetTransformInfoWrapperPass>(); - AU.addRequired<IRSimilarityIdentifierWrapperPass>(); - } - - bool runOnModule(Module &M) override; -}; - -bool IROutlinerLegacyPass::runOnModule(Module &M) { - if (skipModule(M)) - return false; - - auto GTTI = [this](Function &F) -> TargetTransformInfo & { - return this->getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F); - }; - - auto GIRSI = [this](Module &) -> IRSimilarityIdentifier & { - return this->getAnalysis<IRSimilarityIdentifierWrapperPass>().getIRSI(); - }; - - return IROutliner(GTTI, GIRSI).run(M); -} - -PreservedAnalyses IROutlinerPass::run(Module &M, ModuleAnalysisManager &AM) { - auto &FAM = AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager(); - - std::function<TargetTransformInfo &(Function &)> GTTI = - [&FAM](Function &F) -> TargetTransformInfo & { - return FAM.getResult<TargetIRAnalysis>(F); - }; - - std::function<IRSimilarityIdentifier &(Module &)> GIRSI = - [&AM](Module &M) -> IRSimilarityIdentifier & { - return AM.getResult<IRSimilarityAnalysis>(M); - }; - - if (IROutliner(GTTI, GIRSI).run(M)) - return PreservedAnalyses::none(); - return PreservedAnalyses::all(); -} - -char IROutlinerLegacyPass::ID = 0; -INITIALIZE_PASS_BEGIN(IROutlinerLegacyPass, "iroutliner", "IR Outliner", false, - false) -INITIALIZE_PASS_DEPENDENCY(IRSimilarityIdentifierWrapperPass) -INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass) -INITIALIZE_PASS_END(IROutlinerLegacyPass, "iroutliner", "IR Outliner", false, - false) - -ModulePass *llvm::createIROutlinerPass() { return new IROutlinerLegacyPass(); } diff --git a/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp b/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp index 14a265215e2f..e03015f8b0aa 100644 --- a/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp +++ b/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp @@ -107,9 +107,6 @@ static cl::opt<bool> cl::opt<bool> EnableHotColdSplit("hot-cold-split", cl::init(false), cl::ZeroOrMore, cl::desc("Enable hot-cold splitting pass")); -cl::opt<bool> EnableIROutliner("ir-outliner", cl::init(false), cl::Hidden, - cl::desc("Enable ir outliner pass")); - static cl::opt<bool> UseLoopVersioningLICM( "enable-loop-versioning-licm", cl::init(false), cl::Hidden, cl::desc("Enable the experimental Loop Versioning LICM pass")); @@ -876,9 +873,6 @@ void PassManagerBuilder::populateModulePassManager( if (EnableHotColdSplit && !(PrepareForLTO || PrepareForThinLTO)) MPM.add(createHotColdSplittingPass()); - if (EnableIROutliner) - MPM.add(createIROutlinerPass()); - if (MergeFunctions) MPM.add(createMergeFunctionsPass()); diff --git a/llvm/test/Transforms/IROutliner/extraction.ll b/llvm/test/Transforms/IROutliner/extraction.ll deleted file mode 100644 index ec0f0ea4854e..000000000000 --- a/llvm/test/Transforms/IROutliner/extraction.ll +++ /dev/null @@ -1,127 +0,0 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -; RUN: opt -S -verify -iroutliner < %s | FileCheck %s - -; This test makes sure we are extracting the found similarity sections -; correctly at the call site. - -define void @extract1() { -; CHECK-LABEL: @extract1( -; CHECK-NEXT: entry: -; 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: ret void -; -entry: - %a = alloca i32, align 4 - %b = alloca i32, align 4 - %c = alloca i32, align 4 - store i32 2, i32* %a, align 4 - store i32 3, i32* %b, align 4 - store i32 4, i32* %c, align 4 - %al = load i32, i32* %a - %bl = load i32, i32* %b - %cl = load i32, i32* %c - ret void -} - -define void @extract2() { -; CHECK-LABEL: @extract2( -; CHECK-NEXT: entry: -; 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: ret void -; -entry: - %a = alloca i32, align 4 - %b = alloca i32, align 4 - %c = alloca i32, align 4 - store i32 2, i32* %a, align 4 - store i32 3, i32* %b, align 4 - store i32 4, i32* %c, align 4 - %al = load i32, i32* %a - %bl = load i32, i32* %b - %cl = load i32, i32* %c - ret void -} - -define void @extract_outs1() #0 { -; CHECK-LABEL: @extract_outs1( -; CHECK-NEXT: entry: -; CHECK-NEXT: [[DOTLOC:%.*]] = alloca i32, align 4 -; CHECK-NEXT: [[ADD_LOC:%.*]] = alloca i32, align 4 -; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 -; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4 -; CHECK-NEXT: [[OUTPUT:%.*]] = alloca i32, align 4 -; CHECK-NEXT: [[RESULT:%.*]] = alloca i32, align 4 -; CHECK-NEXT: [[LT_CAST:%.*]] = bitcast i32* [[ADD_LOC]] to i8* -; CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 -1, i8* [[LT_CAST]]) -; CHECK-NEXT: [[LT_CAST1:%.*]] = bitcast i32* [[DOTLOC]] to i8* -; CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 -1, i8* [[LT_CAST1]]) -; CHECK-NEXT: call void @extract_outs1.outlined(i32* [[A]], i32* [[B]], i32* [[OUTPUT]], i32* [[ADD_LOC]], i32* [[DOTLOC]]) -; CHECK-NEXT: [[ADD_RELOAD:%.*]] = load i32, i32* [[ADD_LOC]], align 4 -; CHECK-NEXT: [[DOTRELOAD:%.*]] = load i32, i32* [[DOTLOC]], align 4 -; CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 -1, i8* [[LT_CAST]]) -; CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 -1, i8* [[LT_CAST1]]) -; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[OUTPUT]], align 4 -; CHECK-NEXT: call void @extract_outs1.outlined.1(i32 [[DOTRELOAD]], i32 [[ADD_RELOAD]], i32* [[RESULT]]) -; CHECK-NEXT: ret void -; -entry: - %a = alloca i32, align 4 - %b = alloca i32, align 4 - %output = alloca i32, align 4 - %result = alloca i32, align 4 - store i32 2, i32* %a, align 4 - store i32 3, i32* %b, align 4 - %0 = load i32, i32* %a, align 4 - %1 = load i32, i32* %b, align 4 - %add = add i32 %0, %1 - store i32 %add, i32* %output, align 4 - %2 = load i32, i32* %output, align 4 - %3 = load i32, i32* %output, align 4 - %mul = mul i32 %2, %add - store i32 %mul, i32* %result, align 4 - ret void -} - -define void @extract_outs2() #0 { -; CHECK-LABEL: @extract_outs2( -; CHECK-NEXT: entry: -; CHECK-NEXT: [[DOTLOC:%.*]] = alloca i32, align 4 -; CHECK-NEXT: [[ADD_LOC:%.*]] = alloca i32, align 4 -; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 -; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4 -; CHECK-NEXT: [[OUTPUT:%.*]] = alloca i32, align 4 -; CHECK-NEXT: [[RESULT:%.*]] = alloca i32, align 4 -; CHECK-NEXT: [[LT_CAST:%.*]] = bitcast i32* [[ADD_LOC]] to i8* -; CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 -1, i8* [[LT_CAST]]) -; CHECK-NEXT: [[LT_CAST1:%.*]] = bitcast i32* [[DOTLOC]] to i8* -; CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 -1, i8* [[LT_CAST1]]) -; CHECK-NEXT: call void @extract_outs2.outlined(i32* [[A]], i32* [[B]], i32* [[OUTPUT]], i32* [[ADD_LOC]], i32* [[DOTLOC]]) -; CHECK-NEXT: [[ADD_RELOAD:%.*]] = load i32, i32* [[ADD_LOC]], align 4 -; CHECK-NEXT: [[DOTRELOAD:%.*]] = load i32, i32* [[DOTLOC]], align 4 -; CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 -1, i8* [[LT_CAST]]) -; CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 -1, i8* [[LT_CAST1]]) -; CHECK-NEXT: call void @extract_outs2.outlined.2(i32 [[DOTRELOAD]], i32 [[ADD_RELOAD]], i32* [[RESULT]]) -; CHECK-NEXT: ret void -; -entry: - %a = alloca i32, align 4 - %b = alloca i32, align 4 - %output = alloca i32, align 4 - %result = alloca i32, align 4 - store i32 2, i32* %a, align 4 - store i32 3, i32* %b, align 4 - %0 = load i32, i32* %a, align 4 - %1 = load i32, i32* %b, align 4 - %add = add i32 %0, %1 - store i32 %add, i32* %output, align 4 - %2 = load i32, i32* %output, align 4 - %mul = mul i32 %2, %add - store i32 %mul, i32* %result, align 4 - ret void -} diff --git a/llvm/test/Transforms/IROutliner/outlining-address-taken.ll b/llvm/test/Transforms/IROutliner/outlining-address-taken.ll deleted file mode 100644 index dbae8e8230d6..000000000000 --- a/llvm/test/Transforms/IROutliner/outlining-address-taken.ll +++ /dev/null @@ -1,91 +0,0 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -; RUN: opt -S -verify -iroutliner < %s | FileCheck %s - -; This test shows that we do not outline from basic blocks with their address -; taken. - -@ba1 = constant i8* blockaddress (@dontoutline, %new_block) - -define void @outline_1() { -; CHECK-LABEL: @outline_1( -; CHECK-NEXT: entry: -; 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: ret void -; -entry: - %a = alloca i32, align 4 - %b = alloca i32, align 4 - %c = alloca i32, align 4 - store i32 2, i32* %a, align 4 - store i32 3, i32* %b, align 4 - store i32 4, i32* %c, align 4 - %al = load i32, i32* %a - %bl = load i32, i32* %b - %cl = load i32, i32* %c - ret void -} - -define void @outline_2() { -; CHECK-LABEL: @outline_2( -; CHECK-NEXT: entry: -; 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: ret void -; -entry: - %a = alloca i32, align 4 - %b = alloca i32, align 4 - %c = alloca i32, align 4 - store i32 2, i32* %a, align 4 - store i32 3, i32* %b, align 4 - store i32 4, i32* %c, align 4 - %al = load i32, i32* %a - %bl = load i32, i32* %b - %cl = load i32, i32* %c - ret void -} - -define void @dontoutline() { -; CHECK-LABEL: @dontoutline( -; CHECK-NEXT: entry: -; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 -; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4 -; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4 -; CHECK-NEXT: br label [[NEW_BLOCK:%.*]] -; CHECK: new_block: -; 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: [[AL:%.*]] = load i32, i32* [[A]], align 4 -; CHECK-NEXT: [[BL:%.*]] = load i32, i32* [[B]], align 4 -; CHECK-NEXT: [[CL:%.*]] = load i32, i32* [[C]], align 4 -; CHECK-NEXT: ret void -; -entry: - %a = alloca i32, align 4 - %b = alloca i32, align 4 - %c = alloca i32, align 4 - br label %new_block -new_block: - store i32 2, i32* %a, align 4 - store i32 3, i32* %b, align 4 - store i32 4, i32* %c, align 4 - %al = load i32, i32* %a - %bl = load i32, i32* %b - %cl = load i32, i32* %c - ret void -} - -; CHECK: define internal void @[[FUNCTION_2]](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 -; CHECK-NEXT: store i32 4, i32* [[ARG2]], align 4 -; CHECK-NEXT: [[AL:%.*]] = load i32, i32* [[ARG0]], align 4 -; CHECK-NEXT: [[BL:%.*]] = load i32, i32* [[ARG1]], align 4 -; CHECK-NEXT: [[CL:%.*]] = load i32, i32* [[ARG2]], align 4 diff --git a/llvm/test/Transforms/IROutliner/outlining- diff erent-structure.ll b/llvm/test/Transforms/IROutliner/outlining- diff erent-structure.ll deleted file mode 100644 index bb4af26bf990..000000000000 --- a/llvm/test/Transforms/IROutliner/outlining- diff erent-structure.ll +++ /dev/null @@ -1,68 +0,0 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -; RUN: opt -S -verify -iroutliner < %s | FileCheck %s - -; This is a negative case to show that when we have the same set of -; instructions, but in a diff erent order, they are not outlined in the same way. -; In this case, the arguments passed into the function are in a diff erent order. - -define void @outline_constants1() { -; CHECK-LABEL: @outline_constants1( -; CHECK-NEXT: entry: -; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 -; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4 -; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4 -; 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_0:.*]](i32* [[A]], i32* [[C]], i32* [[B]]) -; CHECK-NEXT: ret void -; -entry: - %a = alloca i32, align 4 - %b = alloca i32, align 4 - %c = alloca i32, align 4 - store i32 2, i32* %a, align 4 - store i32 3, i32* %b, align 4 - store i32 4, i32* %c, align 4 - %al = load i32, i32* %a - %cl = load i32, i32* %c - %bl = load i32, i32* %b - ret void -} - -define void @outline_constants2() { -; CHECK-LABEL: @outline_constants2( -; CHECK-NEXT: entry: -; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 -; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4 -; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4 -; 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: ret void -; -entry: - %a = alloca i32, align 4 - %b = alloca i32, align 4 - %c = alloca i32, align 4 - store i32 2, i32* %a, align 4 - store i32 3, i32* %b, align 4 - store i32 4, i32* %c, align 4 - %al = load i32, i32* %a - %bl = load i32, i32* %b - %cl = load i32, i32* %c - ret void -} - -; CHECK: define internal void @[[FUNCTION_0]](i32* [[ARG0:%.*]], i32* [[ARG1:%.*]], i32* [[ARG2:%.*]]) -; CHECK: entry_to_outline: -; CHECK-NEXT: [[AL:%.*]] = load i32, i32* [[ARG0]], align 4 -; CHECK-NEXT: [[BL:%.*]] = load i32, i32* [[ARG1]], align 4 -; CHECK-NEXT: [[CL:%.*]] = load i32, i32* [[ARG2]], align 4 - -; CHECK: define internal void @[[FUNCTION_1]](i32* [[ARG0:%.*]], i32* [[ARG1:%.*]], i32* [[ARG2:%.*]]) -; CHECK: entry_to_outline: -; CHECK-NEXT: [[AL:%.*]] = load i32, i32* [[ARG0]], align 4 -; CHECK-NEXT: [[BL:%.*]] = load i32, i32* [[ARG1]], align 4 -; CHECK-NEXT: [[CL:%.*]] = load i32, i32* [[ARG2]], align 4 diff --git a/llvm/test/Transforms/IROutliner/outlining-same-constants.ll b/llvm/test/Transforms/IROutliner/outlining-same-constants.ll deleted file mode 100644 index e6228abc3d28..000000000000 --- a/llvm/test/Transforms/IROutliner/outlining-same-constants.ll +++ /dev/null @@ -1,67 +0,0 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -; RUN: opt -S -verify -iroutliner < %s | FileCheck %s - -; This test looks at the constants in the regions, and if it they are the -; same it outlines them as constants rather than elevating them to arguments. - -define void @outline_constants1() { -; CHECK-LABEL: @outline_constants1( -; CHECK-NEXT: entry: -; 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_0:.*]](i32* [[A]], i32* [[B]], i32* [[C]]) -; CHECK-NEXT: ret void -; -entry: - %a = alloca i32, align 4 - %b = alloca i32, align 4 - %c = alloca i32, align 4 - store i32 2, i32* %a, align 4 - store i32 3, i32* %b, align 4 - store i32 4, i32* %c, align 4 - %al = load i32, i32* %a - %bl = load i32, i32* %b - %cl = load i32, i32* %c - ret void -} - -define void @outline_constants2() { -; CHECK-LABEL: @outline_constants2( -; CHECK-NEXT: entry: -; 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: ret void -; -entry: - %a = alloca i32, align 4 - %b = alloca i32, align 4 - %c = alloca i32, align 4 - store i32 2, i32* %a, align 4 - store i32 3, i32* %b, align 4 - store i32 4, i32* %c, align 4 - %al = load i32, i32* %a - %bl = load i32, i32* %b - %cl = load i32, i32* %c - ret void -} - -; CHECK: define internal void @[[FUNCTION_0]](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 -; CHECK-NEXT: store i32 4, i32* [[ARG2]], align 4 -; CHECK-NEXT: [[AL:%.*]] = load i32, i32* [[ARG0]], align 4 -; CHECK-NEXT: [[BL:%.*]] = load i32, i32* [[ARG1]], align 4 -; CHECK-NEXT: [[CL:%.*]] = load i32, i32* [[ARG2]], align 4 - -; 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 -; CHECK-NEXT: store i32 4, i32* [[ARG2]], align 4 -; CHECK-NEXT: [[AL:%.*]] = load i32, i32* [[ARG0]], align 4 -; CHECK-NEXT: [[BL:%.*]] = load i32, i32* [[ARG1]], align 4 -; CHECK-NEXT: [[CL:%.*]] = load i32, i32* [[ARG2]], align 4 diff --git a/llvm/test/Transforms/IROutliner/outlining-same-globals.ll b/llvm/test/Transforms/IROutliner/outlining-same-globals.ll deleted file mode 100644 index 9e28cc919010..000000000000 --- a/llvm/test/Transforms/IROutliner/outlining-same-globals.ll +++ /dev/null @@ -1,48 +0,0 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -; RUN: opt -S -verify -iroutliner < %s | FileCheck %s - -@global1 = global i32 1, align 4 -@global2 = global i32 2, align 4 - -; This test looks at the globals in the regions, and if it they are the -; same it outlines the region without elevating the globals to arguments. - -define void @outline_globals1() { -; CHECK-LABEL: @outline_globals1( -; CHECK-NEXT: entry: -; CHECK-NEXT: call void @[[FUNCTION_0:.*]]() -; CHECK-NEXT: ret void -; -entry: - %0 = load i32, i32* @global1 - %1 = load i32, i32* @global2 - %2 = add i32 %0, %1 - ret void -} - -define void @outline_globals2() { -; CHECK-LABEL: @outline_globals2( -; CHECK-NEXT: entry: -; CHECK-NEXT: call void @[[FUNCTION_1:.*]]() -; CHECK-NEXT: ret void -; -entry: - %0 = load i32, i32* @global1 - %1 = load i32, i32* @global2 - %2 = add i32 %0, %1 - 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: 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]] - _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits