xref: /freebsd-src/contrib/llvm-project/llvm/lib/Transforms/IPO/LoopExtractor.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
10b57cec5SDimitry Andric //===- LoopExtractor.cpp - Extract each loop into a new function ----------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // A pass wrapper around the ExtractLoop() scalar transformation to extract each
100b57cec5SDimitry Andric // top-level loop into its own new function. If the loop is the ONLY loop in a
110b57cec5SDimitry Andric // given function, it is not touched. This is a pass most useful for debugging
120b57cec5SDimitry Andric // via bugpoint.
130b57cec5SDimitry Andric //
140b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
150b57cec5SDimitry Andric 
16e8d8bef9SDimitry Andric #include "llvm/Transforms/IPO/LoopExtractor.h"
170b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h"
180b57cec5SDimitry Andric #include "llvm/Analysis/AssumptionCache.h"
195ffd83dbSDimitry Andric #include "llvm/Analysis/LoopInfo.h"
200b57cec5SDimitry Andric #include "llvm/IR/Dominators.h"
210b57cec5SDimitry Andric #include "llvm/IR/Instructions.h"
220b57cec5SDimitry Andric #include "llvm/IR/Module.h"
23e8d8bef9SDimitry Andric #include "llvm/IR/PassManager.h"
24480093f4SDimitry Andric #include "llvm/InitializePasses.h"
250b57cec5SDimitry Andric #include "llvm/Pass.h"
260b57cec5SDimitry Andric #include "llvm/Transforms/IPO.h"
270b57cec5SDimitry Andric #include "llvm/Transforms/Utils.h"
280b57cec5SDimitry Andric #include "llvm/Transforms/Utils/CodeExtractor.h"
290b57cec5SDimitry Andric using namespace llvm;
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric #define DEBUG_TYPE "loop-extract"
320b57cec5SDimitry Andric 
330b57cec5SDimitry Andric STATISTIC(NumExtracted, "Number of loops extracted");
340b57cec5SDimitry Andric 
350b57cec5SDimitry Andric namespace {
36e8d8bef9SDimitry Andric struct LoopExtractorLegacyPass : public ModulePass {
370b57cec5SDimitry Andric   static char ID; // Pass identification, replacement for typeid
385ffd83dbSDimitry Andric 
390b57cec5SDimitry Andric   unsigned NumLoops;
400b57cec5SDimitry Andric 
LoopExtractorLegacyPass__anon50bfbc6d0111::LoopExtractorLegacyPass41e8d8bef9SDimitry Andric   explicit LoopExtractorLegacyPass(unsigned NumLoops = ~0)
42e8d8bef9SDimitry Andric       : ModulePass(ID), NumLoops(NumLoops) {
43e8d8bef9SDimitry Andric     initializeLoopExtractorLegacyPassPass(*PassRegistry::getPassRegistry());
440b57cec5SDimitry Andric   }
450b57cec5SDimitry Andric 
465ffd83dbSDimitry Andric   bool runOnModule(Module &M) override;
470b57cec5SDimitry Andric 
getAnalysisUsage__anon50bfbc6d0111::LoopExtractorLegacyPass480b57cec5SDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override {
490b57cec5SDimitry Andric     AU.addRequiredID(BreakCriticalEdgesID);
500b57cec5SDimitry Andric     AU.addRequired<DominatorTreeWrapperPass>();
510b57cec5SDimitry Andric     AU.addRequired<LoopInfoWrapperPass>();
525ffd83dbSDimitry Andric     AU.addPreserved<LoopInfoWrapperPass>();
535ffd83dbSDimitry Andric     AU.addRequiredID(LoopSimplifyID);
540b57cec5SDimitry Andric     AU.addUsedIfAvailable<AssumptionCacheTracker>();
550b57cec5SDimitry Andric   }
560b57cec5SDimitry Andric };
570b57cec5SDimitry Andric 
58e8d8bef9SDimitry Andric struct LoopExtractor {
LoopExtractor__anon50bfbc6d0111::LoopExtractor59e8d8bef9SDimitry Andric   explicit LoopExtractor(
60e8d8bef9SDimitry Andric       unsigned NumLoops,
61e8d8bef9SDimitry Andric       function_ref<DominatorTree &(Function &)> LookupDomTree,
62e8d8bef9SDimitry Andric       function_ref<LoopInfo &(Function &)> LookupLoopInfo,
63e8d8bef9SDimitry Andric       function_ref<AssumptionCache *(Function &)> LookupAssumptionCache)
64e8d8bef9SDimitry Andric       : NumLoops(NumLoops), LookupDomTree(LookupDomTree),
65e8d8bef9SDimitry Andric         LookupLoopInfo(LookupLoopInfo),
66e8d8bef9SDimitry Andric         LookupAssumptionCache(LookupAssumptionCache) {}
67e8d8bef9SDimitry Andric   bool runOnModule(Module &M);
68e8d8bef9SDimitry Andric 
69e8d8bef9SDimitry Andric private:
70e8d8bef9SDimitry Andric   // The number of natural loops to extract from the program into functions.
71e8d8bef9SDimitry Andric   unsigned NumLoops;
72e8d8bef9SDimitry Andric 
73e8d8bef9SDimitry Andric   function_ref<DominatorTree &(Function &)> LookupDomTree;
74e8d8bef9SDimitry Andric   function_ref<LoopInfo &(Function &)> LookupLoopInfo;
75e8d8bef9SDimitry Andric   function_ref<AssumptionCache *(Function &)> LookupAssumptionCache;
76e8d8bef9SDimitry Andric 
77e8d8bef9SDimitry Andric   bool runOnFunction(Function &F);
78e8d8bef9SDimitry Andric 
79e8d8bef9SDimitry Andric   bool extractLoops(Loop::iterator From, Loop::iterator To, LoopInfo &LI,
80e8d8bef9SDimitry Andric                     DominatorTree &DT);
81e8d8bef9SDimitry Andric   bool extractLoop(Loop *L, LoopInfo &LI, DominatorTree &DT);
82e8d8bef9SDimitry Andric };
83e8d8bef9SDimitry Andric } // namespace
84e8d8bef9SDimitry Andric 
85e8d8bef9SDimitry Andric char LoopExtractorLegacyPass::ID = 0;
86e8d8bef9SDimitry Andric INITIALIZE_PASS_BEGIN(LoopExtractorLegacyPass, "loop-extract",
870b57cec5SDimitry Andric                       "Extract loops into new functions", false, false)
880b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(BreakCriticalEdges)
890b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
905ffd83dbSDimitry Andric INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)
915ffd83dbSDimitry Andric INITIALIZE_PASS_DEPENDENCY(LoopSimplify)
92e8d8bef9SDimitry Andric INITIALIZE_PASS_END(LoopExtractorLegacyPass, "loop-extract",
930b57cec5SDimitry Andric                     "Extract loops into new functions", false, false)
940b57cec5SDimitry Andric 
950b57cec5SDimitry Andric namespace {
960b57cec5SDimitry Andric   /// SingleLoopExtractor - For bugpoint.
97e8d8bef9SDimitry Andric struct SingleLoopExtractor : public LoopExtractorLegacyPass {
980b57cec5SDimitry Andric   static char ID; // Pass identification, replacement for typeid
SingleLoopExtractor__anon50bfbc6d0211::SingleLoopExtractor99e8d8bef9SDimitry Andric   SingleLoopExtractor() : LoopExtractorLegacyPass(1) {}
1000b57cec5SDimitry Andric };
1010b57cec5SDimitry Andric } // End anonymous namespace
1020b57cec5SDimitry Andric 
1030b57cec5SDimitry Andric char SingleLoopExtractor::ID = 0;
1040b57cec5SDimitry Andric INITIALIZE_PASS(SingleLoopExtractor, "loop-extract-single",
1050b57cec5SDimitry Andric                 "Extract at most one loop into a new function", false, false)
1060b57cec5SDimitry Andric 
1070b57cec5SDimitry Andric // createLoopExtractorPass - This pass extracts all natural loops from the
1080b57cec5SDimitry Andric // program into a function if it can.
1090b57cec5SDimitry Andric //
createLoopExtractorPass()110e8d8bef9SDimitry Andric Pass *llvm::createLoopExtractorPass() { return new LoopExtractorLegacyPass(); }
1110b57cec5SDimitry Andric 
runOnModule(Module & M)112e8d8bef9SDimitry Andric bool LoopExtractorLegacyPass::runOnModule(Module &M) {
1135ffd83dbSDimitry Andric   if (skipModule(M))
1140b57cec5SDimitry Andric     return false;
1150b57cec5SDimitry Andric 
116e8d8bef9SDimitry Andric   bool Changed = false;
117e8d8bef9SDimitry Andric   auto LookupDomTree = [this](Function &F) -> DominatorTree & {
118e8d8bef9SDimitry Andric     return this->getAnalysis<DominatorTreeWrapperPass>(F).getDomTree();
119e8d8bef9SDimitry Andric   };
120e8d8bef9SDimitry Andric   auto LookupLoopInfo = [this, &Changed](Function &F) -> LoopInfo & {
121e8d8bef9SDimitry Andric     return this->getAnalysis<LoopInfoWrapperPass>(F, &Changed).getLoopInfo();
122e8d8bef9SDimitry Andric   };
123e8d8bef9SDimitry Andric   auto LookupACT = [this](Function &F) -> AssumptionCache * {
124e8d8bef9SDimitry Andric     if (auto *ACT = this->getAnalysisIfAvailable<AssumptionCacheTracker>())
125e8d8bef9SDimitry Andric       return ACT->lookupAssumptionCache(F);
126e8d8bef9SDimitry Andric     return nullptr;
127e8d8bef9SDimitry Andric   };
128e8d8bef9SDimitry Andric   return LoopExtractor(NumLoops, LookupDomTree, LookupLoopInfo, LookupACT)
129e8d8bef9SDimitry Andric              .runOnModule(M) ||
130e8d8bef9SDimitry Andric          Changed;
131e8d8bef9SDimitry Andric }
132e8d8bef9SDimitry Andric 
runOnModule(Module & M)133e8d8bef9SDimitry Andric bool LoopExtractor::runOnModule(Module &M) {
1345ffd83dbSDimitry Andric   if (M.empty())
1350b57cec5SDimitry Andric     return false;
1360b57cec5SDimitry Andric 
1375ffd83dbSDimitry Andric   if (!NumLoops)
1380b57cec5SDimitry Andric     return false;
1390b57cec5SDimitry Andric 
1400b57cec5SDimitry Andric   bool Changed = false;
1410b57cec5SDimitry Andric 
1425ffd83dbSDimitry Andric   // The end of the function list may change (new functions will be added at the
1435ffd83dbSDimitry Andric   // end), so we run from the first to the current last.
1445ffd83dbSDimitry Andric   auto I = M.begin(), E = --M.end();
1455ffd83dbSDimitry Andric   while (true) {
1465ffd83dbSDimitry Andric     Function &F = *I;
1475ffd83dbSDimitry Andric 
1485ffd83dbSDimitry Andric     Changed |= runOnFunction(F);
1495ffd83dbSDimitry Andric     if (!NumLoops)
1505ffd83dbSDimitry Andric       break;
1515ffd83dbSDimitry Andric 
1525ffd83dbSDimitry Andric     // If this is the last function.
1535ffd83dbSDimitry Andric     if (I == E)
1545ffd83dbSDimitry Andric       break;
1555ffd83dbSDimitry Andric 
1565ffd83dbSDimitry Andric     ++I;
1575ffd83dbSDimitry Andric   }
1585ffd83dbSDimitry Andric   return Changed;
1595ffd83dbSDimitry Andric }
1605ffd83dbSDimitry Andric 
runOnFunction(Function & F)1615ffd83dbSDimitry Andric bool LoopExtractor::runOnFunction(Function &F) {
1625ffd83dbSDimitry Andric   // Do not modify `optnone` functions.
1635ffd83dbSDimitry Andric   if (F.hasOptNone())
1645ffd83dbSDimitry Andric     return false;
1655ffd83dbSDimitry Andric 
1665ffd83dbSDimitry Andric   if (F.empty())
1675ffd83dbSDimitry Andric     return false;
1685ffd83dbSDimitry Andric 
1695ffd83dbSDimitry Andric   bool Changed = false;
170e8d8bef9SDimitry Andric   LoopInfo &LI = LookupLoopInfo(F);
1715ffd83dbSDimitry Andric 
1725ffd83dbSDimitry Andric   // If there are no loops in the function.
1735ffd83dbSDimitry Andric   if (LI.empty())
1745ffd83dbSDimitry Andric     return Changed;
1755ffd83dbSDimitry Andric 
176e8d8bef9SDimitry Andric   DominatorTree &DT = LookupDomTree(F);
1775ffd83dbSDimitry Andric 
1780b57cec5SDimitry Andric   // If there is more than one top-level loop in this function, extract all of
1795ffd83dbSDimitry Andric   // the loops.
1805ffd83dbSDimitry Andric   if (std::next(LI.begin()) != LI.end())
1815ffd83dbSDimitry Andric     return Changed | extractLoops(LI.begin(), LI.end(), LI, DT);
1825ffd83dbSDimitry Andric 
1835ffd83dbSDimitry Andric   // Otherwise there is exactly one top-level loop.
1845ffd83dbSDimitry Andric   Loop *TLL = *LI.begin();
1855ffd83dbSDimitry Andric 
1865ffd83dbSDimitry Andric   // If the loop is in LoopSimplify form, then extract it only if this function
1875ffd83dbSDimitry Andric   // is more than a minimal wrapper around the loop.
1885ffd83dbSDimitry Andric   if (TLL->isLoopSimplifyForm()) {
1890b57cec5SDimitry Andric     bool ShouldExtractLoop = false;
1900b57cec5SDimitry Andric 
1910b57cec5SDimitry Andric     // Extract the loop if the entry block doesn't branch to the loop header.
1925ffd83dbSDimitry Andric     Instruction *EntryTI = F.getEntryBlock().getTerminator();
1930b57cec5SDimitry Andric     if (!isa<BranchInst>(EntryTI) ||
1940b57cec5SDimitry Andric         !cast<BranchInst>(EntryTI)->isUnconditional() ||
1955ffd83dbSDimitry Andric         EntryTI->getSuccessor(0) != TLL->getHeader()) {
1960b57cec5SDimitry Andric       ShouldExtractLoop = true;
1970b57cec5SDimitry Andric     } else {
1980b57cec5SDimitry Andric       // Check to see if any exits from the loop are more than just return
1990b57cec5SDimitry Andric       // blocks.
2000b57cec5SDimitry Andric       SmallVector<BasicBlock *, 8> ExitBlocks;
2015ffd83dbSDimitry Andric       TLL->getExitBlocks(ExitBlocks);
2025ffd83dbSDimitry Andric       for (auto *ExitBlock : ExitBlocks)
2035ffd83dbSDimitry Andric         if (!isa<ReturnInst>(ExitBlock->getTerminator())) {
2040b57cec5SDimitry Andric           ShouldExtractLoop = true;
2050b57cec5SDimitry Andric           break;
2060b57cec5SDimitry Andric         }
2070b57cec5SDimitry Andric     }
2080b57cec5SDimitry Andric 
2095ffd83dbSDimitry Andric     if (ShouldExtractLoop)
2105ffd83dbSDimitry Andric       return Changed | extractLoop(TLL, LI, DT);
2110b57cec5SDimitry Andric   }
2120b57cec5SDimitry Andric 
2135ffd83dbSDimitry Andric   // Okay, this function is a minimal container around the specified loop.
2145ffd83dbSDimitry Andric   // If we extract the loop, we will continue to just keep extracting it
2155ffd83dbSDimitry Andric   // infinitely... so don't extract it. However, if the loop contains any
2165ffd83dbSDimitry Andric   // sub-loops, extract them.
2175ffd83dbSDimitry Andric   return Changed | extractLoops(TLL->begin(), TLL->end(), LI, DT);
2185ffd83dbSDimitry Andric }
2195ffd83dbSDimitry Andric 
extractLoops(Loop::iterator From,Loop::iterator To,LoopInfo & LI,DominatorTree & DT)2205ffd83dbSDimitry Andric bool LoopExtractor::extractLoops(Loop::iterator From, Loop::iterator To,
2215ffd83dbSDimitry Andric                                  LoopInfo &LI, DominatorTree &DT) {
2225ffd83dbSDimitry Andric   bool Changed = false;
2235ffd83dbSDimitry Andric   SmallVector<Loop *, 8> Loops;
2245ffd83dbSDimitry Andric 
2255ffd83dbSDimitry Andric   // Save the list of loops, as it may change.
2265ffd83dbSDimitry Andric   Loops.assign(From, To);
2275ffd83dbSDimitry Andric   for (Loop *L : Loops) {
2285ffd83dbSDimitry Andric     // If LoopSimplify form is not available, stay out of trouble.
2295ffd83dbSDimitry Andric     if (!L->isLoopSimplifyForm())
2305ffd83dbSDimitry Andric       continue;
2315ffd83dbSDimitry Andric 
2325ffd83dbSDimitry Andric     Changed |= extractLoop(L, LI, DT);
2335ffd83dbSDimitry Andric     if (!NumLoops)
2345ffd83dbSDimitry Andric       break;
2355ffd83dbSDimitry Andric   }
2365ffd83dbSDimitry Andric   return Changed;
2375ffd83dbSDimitry Andric }
2385ffd83dbSDimitry Andric 
extractLoop(Loop * L,LoopInfo & LI,DominatorTree & DT)2395ffd83dbSDimitry Andric bool LoopExtractor::extractLoop(Loop *L, LoopInfo &LI, DominatorTree &DT) {
2405ffd83dbSDimitry Andric   assert(NumLoops != 0);
2418bcb0991SDimitry Andric   Function &Func = *L->getHeader()->getParent();
242e8d8bef9SDimitry Andric   AssumptionCache *AC = LookupAssumptionCache(Func);
2438bcb0991SDimitry Andric   CodeExtractorAnalysisCache CEAC(Func);
2440b57cec5SDimitry Andric   CodeExtractor Extractor(DT, *L, false, nullptr, nullptr, AC);
2455ffd83dbSDimitry Andric   if (Extractor.extractCodeRegion(CEAC)) {
2460b57cec5SDimitry Andric     LI.erase(L);
2475ffd83dbSDimitry Andric     --NumLoops;
2480b57cec5SDimitry Andric     ++NumExtracted;
2495ffd83dbSDimitry Andric     return true;
2500b57cec5SDimitry Andric   }
2515ffd83dbSDimitry Andric   return false;
2520b57cec5SDimitry Andric }
2530b57cec5SDimitry Andric 
2540b57cec5SDimitry Andric // createSingleLoopExtractorPass - This pass extracts one natural loop from the
2550b57cec5SDimitry Andric // program into a function if it can.  This is used by bugpoint.
2560b57cec5SDimitry Andric //
createSingleLoopExtractorPass()2570b57cec5SDimitry Andric Pass *llvm::createSingleLoopExtractorPass() {
2580b57cec5SDimitry Andric   return new SingleLoopExtractor();
2590b57cec5SDimitry Andric }
260e8d8bef9SDimitry Andric 
run(Module & M,ModuleAnalysisManager & AM)261e8d8bef9SDimitry Andric PreservedAnalyses LoopExtractorPass::run(Module &M, ModuleAnalysisManager &AM) {
262e8d8bef9SDimitry Andric   auto &FAM = AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
263e8d8bef9SDimitry Andric   auto LookupDomTree = [&FAM](Function &F) -> DominatorTree & {
264e8d8bef9SDimitry Andric     return FAM.getResult<DominatorTreeAnalysis>(F);
265e8d8bef9SDimitry Andric   };
266e8d8bef9SDimitry Andric   auto LookupLoopInfo = [&FAM](Function &F) -> LoopInfo & {
267e8d8bef9SDimitry Andric     return FAM.getResult<LoopAnalysis>(F);
268e8d8bef9SDimitry Andric   };
269e8d8bef9SDimitry Andric   auto LookupAssumptionCache = [&FAM](Function &F) -> AssumptionCache * {
270e8d8bef9SDimitry Andric     return FAM.getCachedResult<AssumptionAnalysis>(F);
271e8d8bef9SDimitry Andric   };
272e8d8bef9SDimitry Andric   if (!LoopExtractor(NumLoops, LookupDomTree, LookupLoopInfo,
273e8d8bef9SDimitry Andric                      LookupAssumptionCache)
274e8d8bef9SDimitry Andric            .runOnModule(M))
275e8d8bef9SDimitry Andric     return PreservedAnalyses::all();
276e8d8bef9SDimitry Andric 
277e8d8bef9SDimitry Andric   PreservedAnalyses PA;
278e8d8bef9SDimitry Andric   PA.preserve<LoopAnalysis>();
279e8d8bef9SDimitry Andric   return PA;
280e8d8bef9SDimitry Andric }
281349cc55cSDimitry Andric 
printPipeline(raw_ostream & OS,function_ref<StringRef (StringRef)> MapClassName2PassName)282349cc55cSDimitry Andric void LoopExtractorPass::printPipeline(
283349cc55cSDimitry Andric     raw_ostream &OS, function_ref<StringRef(StringRef)> MapClassName2PassName) {
284349cc55cSDimitry Andric   static_cast<PassInfoMixin<LoopExtractorPass> *>(this)->printPipeline(
285349cc55cSDimitry Andric       OS, MapClassName2PassName);
286*06c3fb27SDimitry Andric   OS << '<';
287349cc55cSDimitry Andric   if (NumLoops == 1)
288349cc55cSDimitry Andric     OS << "single";
289*06c3fb27SDimitry Andric   OS << '>';
290349cc55cSDimitry Andric }
291