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
16*af732203SDimitry 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"
23*af732203SDimitry Andric #include "llvm/IR/PassManager.h"
24480093f4SDimitry Andric #include "llvm/InitializePasses.h"
250b57cec5SDimitry Andric #include "llvm/Pass.h"
260b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h"
270b57cec5SDimitry Andric #include "llvm/Transforms/IPO.h"
280b57cec5SDimitry Andric #include "llvm/Transforms/Scalar.h"
290b57cec5SDimitry Andric #include "llvm/Transforms/Utils.h"
300b57cec5SDimitry Andric #include "llvm/Transforms/Utils/BasicBlockUtils.h"
310b57cec5SDimitry Andric #include "llvm/Transforms/Utils/CodeExtractor.h"
320b57cec5SDimitry Andric #include <fstream>
330b57cec5SDimitry Andric #include <set>
340b57cec5SDimitry Andric using namespace llvm;
350b57cec5SDimitry Andric
360b57cec5SDimitry Andric #define DEBUG_TYPE "loop-extract"
370b57cec5SDimitry Andric
380b57cec5SDimitry Andric STATISTIC(NumExtracted, "Number of loops extracted");
390b57cec5SDimitry Andric
400b57cec5SDimitry Andric namespace {
41*af732203SDimitry Andric struct LoopExtractorLegacyPass : public ModulePass {
420b57cec5SDimitry Andric static char ID; // Pass identification, replacement for typeid
435ffd83dbSDimitry Andric
440b57cec5SDimitry Andric unsigned NumLoops;
450b57cec5SDimitry Andric
LoopExtractorLegacyPass__anonb854274f0111::LoopExtractorLegacyPass46*af732203SDimitry Andric explicit LoopExtractorLegacyPass(unsigned NumLoops = ~0)
47*af732203SDimitry Andric : ModulePass(ID), NumLoops(NumLoops) {
48*af732203SDimitry Andric initializeLoopExtractorLegacyPassPass(*PassRegistry::getPassRegistry());
490b57cec5SDimitry Andric }
500b57cec5SDimitry Andric
515ffd83dbSDimitry Andric bool runOnModule(Module &M) override;
520b57cec5SDimitry Andric
getAnalysisUsage__anonb854274f0111::LoopExtractorLegacyPass530b57cec5SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override {
540b57cec5SDimitry Andric AU.addRequiredID(BreakCriticalEdgesID);
550b57cec5SDimitry Andric AU.addRequired<DominatorTreeWrapperPass>();
560b57cec5SDimitry Andric AU.addRequired<LoopInfoWrapperPass>();
575ffd83dbSDimitry Andric AU.addPreserved<LoopInfoWrapperPass>();
585ffd83dbSDimitry Andric AU.addRequiredID(LoopSimplifyID);
590b57cec5SDimitry Andric AU.addUsedIfAvailable<AssumptionCacheTracker>();
600b57cec5SDimitry Andric }
610b57cec5SDimitry Andric };
620b57cec5SDimitry Andric
63*af732203SDimitry Andric struct LoopExtractor {
LoopExtractor__anonb854274f0111::LoopExtractor64*af732203SDimitry Andric explicit LoopExtractor(
65*af732203SDimitry Andric unsigned NumLoops,
66*af732203SDimitry Andric function_ref<DominatorTree &(Function &)> LookupDomTree,
67*af732203SDimitry Andric function_ref<LoopInfo &(Function &)> LookupLoopInfo,
68*af732203SDimitry Andric function_ref<AssumptionCache *(Function &)> LookupAssumptionCache)
69*af732203SDimitry Andric : NumLoops(NumLoops), LookupDomTree(LookupDomTree),
70*af732203SDimitry Andric LookupLoopInfo(LookupLoopInfo),
71*af732203SDimitry Andric LookupAssumptionCache(LookupAssumptionCache) {}
72*af732203SDimitry Andric bool runOnModule(Module &M);
73*af732203SDimitry Andric
74*af732203SDimitry Andric private:
75*af732203SDimitry Andric // The number of natural loops to extract from the program into functions.
76*af732203SDimitry Andric unsigned NumLoops;
77*af732203SDimitry Andric
78*af732203SDimitry Andric function_ref<DominatorTree &(Function &)> LookupDomTree;
79*af732203SDimitry Andric function_ref<LoopInfo &(Function &)> LookupLoopInfo;
80*af732203SDimitry Andric function_ref<AssumptionCache *(Function &)> LookupAssumptionCache;
81*af732203SDimitry Andric
82*af732203SDimitry Andric bool runOnFunction(Function &F);
83*af732203SDimitry Andric
84*af732203SDimitry Andric bool extractLoops(Loop::iterator From, Loop::iterator To, LoopInfo &LI,
85*af732203SDimitry Andric DominatorTree &DT);
86*af732203SDimitry Andric bool extractLoop(Loop *L, LoopInfo &LI, DominatorTree &DT);
87*af732203SDimitry Andric };
88*af732203SDimitry Andric } // namespace
89*af732203SDimitry Andric
90*af732203SDimitry Andric char LoopExtractorLegacyPass::ID = 0;
91*af732203SDimitry Andric INITIALIZE_PASS_BEGIN(LoopExtractorLegacyPass, "loop-extract",
920b57cec5SDimitry Andric "Extract loops into new functions", false, false)
930b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(BreakCriticalEdges)
940b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
955ffd83dbSDimitry Andric INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)
965ffd83dbSDimitry Andric INITIALIZE_PASS_DEPENDENCY(LoopSimplify)
97*af732203SDimitry Andric INITIALIZE_PASS_END(LoopExtractorLegacyPass, "loop-extract",
980b57cec5SDimitry Andric "Extract loops into new functions", false, false)
990b57cec5SDimitry Andric
1000b57cec5SDimitry Andric namespace {
1010b57cec5SDimitry Andric /// SingleLoopExtractor - For bugpoint.
102*af732203SDimitry Andric struct SingleLoopExtractor : public LoopExtractorLegacyPass {
1030b57cec5SDimitry Andric static char ID; // Pass identification, replacement for typeid
SingleLoopExtractor__anonb854274f0211::SingleLoopExtractor104*af732203SDimitry Andric SingleLoopExtractor() : LoopExtractorLegacyPass(1) {}
1050b57cec5SDimitry Andric };
1060b57cec5SDimitry Andric } // End anonymous namespace
1070b57cec5SDimitry Andric
1080b57cec5SDimitry Andric char SingleLoopExtractor::ID = 0;
1090b57cec5SDimitry Andric INITIALIZE_PASS(SingleLoopExtractor, "loop-extract-single",
1100b57cec5SDimitry Andric "Extract at most one loop into a new function", false, false)
1110b57cec5SDimitry Andric
1120b57cec5SDimitry Andric // createLoopExtractorPass - This pass extracts all natural loops from the
1130b57cec5SDimitry Andric // program into a function if it can.
1140b57cec5SDimitry Andric //
createLoopExtractorPass()115*af732203SDimitry Andric Pass *llvm::createLoopExtractorPass() { return new LoopExtractorLegacyPass(); }
1160b57cec5SDimitry Andric
runOnModule(Module & M)117*af732203SDimitry Andric bool LoopExtractorLegacyPass::runOnModule(Module &M) {
1185ffd83dbSDimitry Andric if (skipModule(M))
1190b57cec5SDimitry Andric return false;
1200b57cec5SDimitry Andric
121*af732203SDimitry Andric bool Changed = false;
122*af732203SDimitry Andric auto LookupDomTree = [this](Function &F) -> DominatorTree & {
123*af732203SDimitry Andric return this->getAnalysis<DominatorTreeWrapperPass>(F).getDomTree();
124*af732203SDimitry Andric };
125*af732203SDimitry Andric auto LookupLoopInfo = [this, &Changed](Function &F) -> LoopInfo & {
126*af732203SDimitry Andric return this->getAnalysis<LoopInfoWrapperPass>(F, &Changed).getLoopInfo();
127*af732203SDimitry Andric };
128*af732203SDimitry Andric auto LookupACT = [this](Function &F) -> AssumptionCache * {
129*af732203SDimitry Andric if (auto *ACT = this->getAnalysisIfAvailable<AssumptionCacheTracker>())
130*af732203SDimitry Andric return ACT->lookupAssumptionCache(F);
131*af732203SDimitry Andric return nullptr;
132*af732203SDimitry Andric };
133*af732203SDimitry Andric return LoopExtractor(NumLoops, LookupDomTree, LookupLoopInfo, LookupACT)
134*af732203SDimitry Andric .runOnModule(M) ||
135*af732203SDimitry Andric Changed;
136*af732203SDimitry Andric }
137*af732203SDimitry Andric
runOnModule(Module & M)138*af732203SDimitry Andric bool LoopExtractor::runOnModule(Module &M) {
1395ffd83dbSDimitry Andric if (M.empty())
1400b57cec5SDimitry Andric return false;
1410b57cec5SDimitry Andric
1425ffd83dbSDimitry Andric if (!NumLoops)
1430b57cec5SDimitry Andric return false;
1440b57cec5SDimitry Andric
1450b57cec5SDimitry Andric bool Changed = false;
1460b57cec5SDimitry Andric
1475ffd83dbSDimitry Andric // The end of the function list may change (new functions will be added at the
1485ffd83dbSDimitry Andric // end), so we run from the first to the current last.
1495ffd83dbSDimitry Andric auto I = M.begin(), E = --M.end();
1505ffd83dbSDimitry Andric while (true) {
1515ffd83dbSDimitry Andric Function &F = *I;
1525ffd83dbSDimitry Andric
1535ffd83dbSDimitry Andric Changed |= runOnFunction(F);
1545ffd83dbSDimitry Andric if (!NumLoops)
1555ffd83dbSDimitry Andric break;
1565ffd83dbSDimitry Andric
1575ffd83dbSDimitry Andric // If this is the last function.
1585ffd83dbSDimitry Andric if (I == E)
1595ffd83dbSDimitry Andric break;
1605ffd83dbSDimitry Andric
1615ffd83dbSDimitry Andric ++I;
1625ffd83dbSDimitry Andric }
1635ffd83dbSDimitry Andric return Changed;
1645ffd83dbSDimitry Andric }
1655ffd83dbSDimitry Andric
runOnFunction(Function & F)1665ffd83dbSDimitry Andric bool LoopExtractor::runOnFunction(Function &F) {
1675ffd83dbSDimitry Andric // Do not modify `optnone` functions.
1685ffd83dbSDimitry Andric if (F.hasOptNone())
1695ffd83dbSDimitry Andric return false;
1705ffd83dbSDimitry Andric
1715ffd83dbSDimitry Andric if (F.empty())
1725ffd83dbSDimitry Andric return false;
1735ffd83dbSDimitry Andric
1745ffd83dbSDimitry Andric bool Changed = false;
175*af732203SDimitry Andric LoopInfo &LI = LookupLoopInfo(F);
1765ffd83dbSDimitry Andric
1775ffd83dbSDimitry Andric // If there are no loops in the function.
1785ffd83dbSDimitry Andric if (LI.empty())
1795ffd83dbSDimitry Andric return Changed;
1805ffd83dbSDimitry Andric
181*af732203SDimitry Andric DominatorTree &DT = LookupDomTree(F);
1825ffd83dbSDimitry Andric
1830b57cec5SDimitry Andric // If there is more than one top-level loop in this function, extract all of
1845ffd83dbSDimitry Andric // the loops.
1855ffd83dbSDimitry Andric if (std::next(LI.begin()) != LI.end())
1865ffd83dbSDimitry Andric return Changed | extractLoops(LI.begin(), LI.end(), LI, DT);
1875ffd83dbSDimitry Andric
1885ffd83dbSDimitry Andric // Otherwise there is exactly one top-level loop.
1895ffd83dbSDimitry Andric Loop *TLL = *LI.begin();
1905ffd83dbSDimitry Andric
1915ffd83dbSDimitry Andric // If the loop is in LoopSimplify form, then extract it only if this function
1925ffd83dbSDimitry Andric // is more than a minimal wrapper around the loop.
1935ffd83dbSDimitry Andric if (TLL->isLoopSimplifyForm()) {
1940b57cec5SDimitry Andric bool ShouldExtractLoop = false;
1950b57cec5SDimitry Andric
1960b57cec5SDimitry Andric // Extract the loop if the entry block doesn't branch to the loop header.
1975ffd83dbSDimitry Andric Instruction *EntryTI = F.getEntryBlock().getTerminator();
1980b57cec5SDimitry Andric if (!isa<BranchInst>(EntryTI) ||
1990b57cec5SDimitry Andric !cast<BranchInst>(EntryTI)->isUnconditional() ||
2005ffd83dbSDimitry Andric EntryTI->getSuccessor(0) != TLL->getHeader()) {
2010b57cec5SDimitry Andric ShouldExtractLoop = true;
2020b57cec5SDimitry Andric } else {
2030b57cec5SDimitry Andric // Check to see if any exits from the loop are more than just return
2040b57cec5SDimitry Andric // blocks.
2050b57cec5SDimitry Andric SmallVector<BasicBlock *, 8> ExitBlocks;
2065ffd83dbSDimitry Andric TLL->getExitBlocks(ExitBlocks);
2075ffd83dbSDimitry Andric for (auto *ExitBlock : ExitBlocks)
2085ffd83dbSDimitry Andric if (!isa<ReturnInst>(ExitBlock->getTerminator())) {
2090b57cec5SDimitry Andric ShouldExtractLoop = true;
2100b57cec5SDimitry Andric break;
2110b57cec5SDimitry Andric }
2120b57cec5SDimitry Andric }
2130b57cec5SDimitry Andric
2145ffd83dbSDimitry Andric if (ShouldExtractLoop)
2155ffd83dbSDimitry Andric return Changed | extractLoop(TLL, LI, DT);
2160b57cec5SDimitry Andric }
2170b57cec5SDimitry Andric
2185ffd83dbSDimitry Andric // Okay, this function is a minimal container around the specified loop.
2195ffd83dbSDimitry Andric // If we extract the loop, we will continue to just keep extracting it
2205ffd83dbSDimitry Andric // infinitely... so don't extract it. However, if the loop contains any
2215ffd83dbSDimitry Andric // sub-loops, extract them.
2225ffd83dbSDimitry Andric return Changed | extractLoops(TLL->begin(), TLL->end(), LI, DT);
2235ffd83dbSDimitry Andric }
2245ffd83dbSDimitry Andric
extractLoops(Loop::iterator From,Loop::iterator To,LoopInfo & LI,DominatorTree & DT)2255ffd83dbSDimitry Andric bool LoopExtractor::extractLoops(Loop::iterator From, Loop::iterator To,
2265ffd83dbSDimitry Andric LoopInfo &LI, DominatorTree &DT) {
2275ffd83dbSDimitry Andric bool Changed = false;
2285ffd83dbSDimitry Andric SmallVector<Loop *, 8> Loops;
2295ffd83dbSDimitry Andric
2305ffd83dbSDimitry Andric // Save the list of loops, as it may change.
2315ffd83dbSDimitry Andric Loops.assign(From, To);
2325ffd83dbSDimitry Andric for (Loop *L : Loops) {
2335ffd83dbSDimitry Andric // If LoopSimplify form is not available, stay out of trouble.
2345ffd83dbSDimitry Andric if (!L->isLoopSimplifyForm())
2355ffd83dbSDimitry Andric continue;
2365ffd83dbSDimitry Andric
2375ffd83dbSDimitry Andric Changed |= extractLoop(L, LI, DT);
2385ffd83dbSDimitry Andric if (!NumLoops)
2395ffd83dbSDimitry Andric break;
2405ffd83dbSDimitry Andric }
2415ffd83dbSDimitry Andric return Changed;
2425ffd83dbSDimitry Andric }
2435ffd83dbSDimitry Andric
extractLoop(Loop * L,LoopInfo & LI,DominatorTree & DT)2445ffd83dbSDimitry Andric bool LoopExtractor::extractLoop(Loop *L, LoopInfo &LI, DominatorTree &DT) {
2455ffd83dbSDimitry Andric assert(NumLoops != 0);
2468bcb0991SDimitry Andric Function &Func = *L->getHeader()->getParent();
247*af732203SDimitry Andric AssumptionCache *AC = LookupAssumptionCache(Func);
2488bcb0991SDimitry Andric CodeExtractorAnalysisCache CEAC(Func);
2490b57cec5SDimitry Andric CodeExtractor Extractor(DT, *L, false, nullptr, nullptr, AC);
2505ffd83dbSDimitry Andric if (Extractor.extractCodeRegion(CEAC)) {
2510b57cec5SDimitry Andric LI.erase(L);
2525ffd83dbSDimitry Andric --NumLoops;
2530b57cec5SDimitry Andric ++NumExtracted;
2545ffd83dbSDimitry Andric return true;
2550b57cec5SDimitry Andric }
2565ffd83dbSDimitry Andric return false;
2570b57cec5SDimitry Andric }
2580b57cec5SDimitry Andric
2590b57cec5SDimitry Andric // createSingleLoopExtractorPass - This pass extracts one natural loop from the
2600b57cec5SDimitry Andric // program into a function if it can. This is used by bugpoint.
2610b57cec5SDimitry Andric //
createSingleLoopExtractorPass()2620b57cec5SDimitry Andric Pass *llvm::createSingleLoopExtractorPass() {
2630b57cec5SDimitry Andric return new SingleLoopExtractor();
2640b57cec5SDimitry Andric }
265*af732203SDimitry Andric
run(Module & M,ModuleAnalysisManager & AM)266*af732203SDimitry Andric PreservedAnalyses LoopExtractorPass::run(Module &M, ModuleAnalysisManager &AM) {
267*af732203SDimitry Andric auto &FAM = AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
268*af732203SDimitry Andric auto LookupDomTree = [&FAM](Function &F) -> DominatorTree & {
269*af732203SDimitry Andric return FAM.getResult<DominatorTreeAnalysis>(F);
270*af732203SDimitry Andric };
271*af732203SDimitry Andric auto LookupLoopInfo = [&FAM](Function &F) -> LoopInfo & {
272*af732203SDimitry Andric return FAM.getResult<LoopAnalysis>(F);
273*af732203SDimitry Andric };
274*af732203SDimitry Andric auto LookupAssumptionCache = [&FAM](Function &F) -> AssumptionCache * {
275*af732203SDimitry Andric return FAM.getCachedResult<AssumptionAnalysis>(F);
276*af732203SDimitry Andric };
277*af732203SDimitry Andric if (!LoopExtractor(NumLoops, LookupDomTree, LookupLoopInfo,
278*af732203SDimitry Andric LookupAssumptionCache)
279*af732203SDimitry Andric .runOnModule(M))
280*af732203SDimitry Andric return PreservedAnalyses::all();
281*af732203SDimitry Andric
282*af732203SDimitry Andric PreservedAnalyses PA;
283*af732203SDimitry Andric PA.preserve<LoopAnalysis>();
284*af732203SDimitry Andric return PA;
285*af732203SDimitry Andric }
286