Polly 22.0.0git
ScopInliner.cpp
Go to the documentation of this file.
1//===---- ScopInliner.cpp - Polyhedral based inliner ----------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Take a SCC and:
10// 1. If it has more than one component, bail out (contains cycles)
11// 2. If it has just one component, and if the function is entirely a scop,
12// inline it.
13//
14//===----------------------------------------------------------------------===//
15
16#include "polly/ScopInliner.h"
17#include "polly/ScopDetection.h"
18#include "polly/ScopInliner.h"
19#include "llvm/Analysis/CallGraph.h"
20#include "llvm/Analysis/CallGraphSCCPass.h"
21#include "llvm/Analysis/OptimizationRemarkEmitter.h"
22#include "llvm/Analysis/RegionInfo.h"
23#include "llvm/IR/Dominators.h"
24#include "llvm/IR/PassManager.h"
25#include "llvm/Passes/PassBuilder.h"
26#include "llvm/Transforms/IPO/AlwaysInliner.h"
27
29#define DEBUG_TYPE "polly-scop-inliner"
30
31using namespace llvm;
32using namespace polly;
33
34namespace {
35
36/// Inliner implementation that works with both, LPM (using SCC_t=CallGraph) and
37/// NPM (using SCC_t=LazyCallGraph::SCC)
38template <typename SCC_t> bool runScopInlinerImpl(Function *F, SCC_t &SCC) {
39 // We do not try to inline non-trivial SCCs because this would lead to
40 // "infinite" inlining if we are not careful.
41 if (SCC.size() > 1)
42 return false;
43 assert(SCC.size() == 1 && "found empty SCC");
44
45 // If the function is a nullptr, or the function is a declaration.
46 if (!F)
47 return false;
48 if (F->isDeclaration()) {
49 POLLY_DEBUG(dbgs() << "Skipping " << F->getName()
50 << "because it is a declaration.\n");
51 return false;
52 }
53
54 PassBuilder PB;
55 // Populate analysis managers and register Polly-specific analyses.
56 LoopAnalysisManager LAM;
57 FunctionAnalysisManager FAM;
58 CGSCCAnalysisManager CGAM;
59 ModuleAnalysisManager MAM;
60 PB.registerModuleAnalyses(MAM);
61 PB.registerCGSCCAnalyses(CGAM);
62 PB.registerFunctionAnalyses(FAM);
63 PB.registerLoopAnalyses(LAM);
64 PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
65
66 auto &DT = FAM.getResult<DominatorTreeAnalysis>(*F);
67 auto &SE = FAM.getResult<ScalarEvolutionAnalysis>(*F);
68 auto &LI = FAM.getResult<LoopAnalysis>(*F);
69 auto &RI = FAM.getResult<RegionInfoAnalysis>(*F);
70 auto &AA = FAM.getResult<AAManager>(*F);
71 auto &ORE = FAM.getResult<OptimizationRemarkEmitterAnalysis>(*F);
72 ScopDetection SD(DT, SE, LI, RI, AA, ORE);
73 SD.detect(*F);
74
75 const bool HasScopAsTopLevelRegion =
76 SD.ValidRegions.contains(RI.getTopLevelRegion());
77
78 bool Changed = false;
79 if (HasScopAsTopLevelRegion) {
80 POLLY_DEBUG(dbgs() << "Skipping " << F->getName()
81 << " has scop as top level region");
82 F->addFnAttr(llvm::Attribute::AlwaysInline);
83
84 ModulePassManager MPM;
85 MPM.addPass(AlwaysInlinerPass());
86 Module *M = F->getParent();
87 assert(M && "Function has illegal module");
88 PreservedAnalyses PA = MPM.run(*M, MAM);
89 if (!PA.areAllPreserved())
90 Changed = true;
91 } else {
92 POLLY_DEBUG(dbgs() << F->getName()
93 << " does NOT have scop as top level region\n");
94 }
95
96 return Changed;
97}
98
99class ScopInlinerWrapperPass final : public CallGraphSCCPass {
100 using llvm::Pass::doInitialization;
101
102public:
103 static char ID;
104
105 ScopInlinerWrapperPass() : CallGraphSCCPass(ID) {}
106
107 bool doInitialization(CallGraph &CG) override {
109 report_fatal_error(
110 "Aborting from ScopInliner because it only makes sense to run with "
111 "-polly-allow-full-function. "
112 "The heurtistic for ScopInliner checks that the full function is a "
113 "Scop, which happens if and only if polly-allow-full-function is "
114 " enabled. "
115 " If not, the entry block is not included in the Scop");
116 }
117 return true;
118 }
119
120 bool runOnSCC(CallGraphSCC &SCC) override {
121 Function *F = (*SCC.begin())->getFunction();
122 return runScopInlinerImpl(F, SCC);
123 };
124
125 void getAnalysisUsage(AnalysisUsage &AU) const override {
126 CallGraphSCCPass::getAnalysisUsage(AU);
127 }
128};
129} // namespace
130char ScopInlinerWrapperPass::ID;
131
133 ScopInlinerWrapperPass *pass = new ScopInlinerWrapperPass();
134 return pass;
135}
136
138 ScopInlinerWrapperPass, "polly-scop-inliner",
139 "inline functions based on how much of the function is a scop.", false,
140 false)
142 ScopInlinerWrapperPass, "polly-scop-inliner",
143 "inline functions based on how much of the function is a scop.", false,
144 false)
145
148 report_fatal_error(
149 "Aborting from ScopInliner because it only makes sense to run with "
150 "-polly-allow-full-function. "
151 "The heurtistic for ScopInliner checks that the full function is a "
152 "Scop, which happens if and only if polly-allow-full-function is "
153 " enabled. "
154 " If not, the entry block is not included in the Scop");
155 }
156}
157
158PreservedAnalyses polly::ScopInlinerPass::run(llvm::LazyCallGraph::SCC &SCC,
159 llvm::CGSCCAnalysisManager &AM,
160 llvm::LazyCallGraph &CG,
161 llvm::CGSCCUpdateResult &UR) {
162 Function *F = &SCC.begin()->getFunction();
163 bool Changed = runScopInlinerImpl(F, SCC);
164 return Changed ? PreservedAnalyses::none() : PreservedAnalyses::all();
165}
INITIALIZE_PASS_END(DependenceInfo, "polly-dependences", "Polly - Calculate dependences", false, false) namespace
polly dump Polly Dump Function
polly dump Polly Dump Module
#define POLLY_DEBUG(X)
Definition PollyDebug.h:23
static RegisterPass< ScopPrinterWrapperPass > M("dot-scops", "Polly - Print Scops of function")
INITIALIZE_PASS_BEGIN(ScopInlinerWrapperPass, "polly-scop-inliner", "inline functions based on how much of the function is a scop.", false, false) INITIALIZE_PASS_END(ScopInlinerWrapperPass
Pass to detect the maximal static control parts (Scops) of a function.
void detect(Function &F)
llvm::PreservedAnalyses run(llvm::LazyCallGraph::SCC &C, llvm::CGSCCAnalysisManager &AM, llvm::LazyCallGraph &CG, llvm::CGSCCUpdateResult &UR)
#define assert(exp)
bool PollyAllowFullFunction
llvm::Pass * createScopInlinerWrapperPass()