Polly 24.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/Passes/PassBuilder.h"
25#include "llvm/Transforms/IPO/AlwaysInliner.h"
26
28#define DEBUG_TYPE "polly-scop-inliner"
29
30using namespace llvm;
31using namespace polly;
32
33namespace {
34
35/// Inliner implementation that works with both, LPM (using SCC_t=CallGraph) and
36/// NPM (using SCC_t=LazyCallGraph::SCC)
37template <typename SCC_t>
38bool runScopInlinerImpl(Function *F, SCC_t &SCC,
39 IntrusiveRefCntPtr<vfs::FileSystem> FS) {
40 // We do not try to inline non-trivial SCCs because this would lead to
41 // "infinite" inlining if we are not careful.
42 if (SCC.size() > 1)
43 return false;
44 assert(SCC.size() == 1 && "found empty SCC");
45
46 // If the function is a nullptr, or the function is a declaration.
47 if (!F)
48 return false;
49 if (F->isDeclaration()) {
50 POLLY_DEBUG(dbgs() << "Skipping " << F->getName()
51 << "because it is a declaration.\n");
52 return false;
53 }
54
55 PassBuilder PB(F->getContext(), /*TM=*/nullptr, /*PTO=*/std::nullopt,
56 /*PGOOpt=*/{},
57 /*PIC=*/nullptr, std::move(FS));
58 // Populate analysis managers and register Polly-specific analyses.
59 LoopAnalysisManager LAM;
60 FunctionAnalysisManager FAM;
61 CGSCCAnalysisManager CGAM;
62 ModuleAnalysisManager MAM;
63 PB.registerModuleAnalyses(MAM);
64 PB.registerCGSCCAnalyses(CGAM);
65 PB.registerFunctionAnalyses(FAM);
66 PB.registerLoopAnalyses(LAM);
67 PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
68
69 auto &DT = FAM.getResult<DominatorTreeAnalysis>(*F);
70 auto &SE = FAM.getResult<ScalarEvolutionAnalysis>(*F);
71 auto &LI = FAM.getResult<LoopAnalysis>(*F);
72 auto &RI = FAM.getResult<RegionInfoAnalysis>(*F);
73 auto &AA = FAM.getResult<AAManager>(*F);
74 auto &ORE = FAM.getResult<OptimizationRemarkEmitterAnalysis>(*F);
75 ScopDetection SD(DT, SE, LI, RI, AA, ORE);
76 SD.detect(*F);
77
78 const bool HasScopAsTopLevelRegion =
79 SD.ValidRegions.contains(RI.getTopLevelRegion());
80
81 bool Changed = false;
82 if (HasScopAsTopLevelRegion) {
83 POLLY_DEBUG(dbgs() << "Skipping " << F->getName()
84 << " has scop as top level region");
85 F->addFnAttr(llvm::Attribute::AlwaysInline);
86
87 ModulePassManager MPM;
88 MPM.addPass(AlwaysInlinerPass());
89 Module *M = F->getParent();
90 assert(M && "Function has illegal module");
91 PreservedAnalyses PA = MPM.run(*M, MAM);
92 if (!PA.areAllPreserved())
93 Changed = true;
94 } else {
95 POLLY_DEBUG(dbgs() << F->getName()
96 << " does NOT have scop as top level region\n");
97 }
98
99 return Changed;
100}
101} // namespace
102
103polly::ScopInlinerPass::ScopInlinerPass(IntrusiveRefCntPtr<vfs::FileSystem> FS)
104 : FS(std::move(FS)) {
106 report_fatal_error(
107 "Aborting from ScopInliner because it only makes sense to run with "
108 "-polly-allow-full-function. "
109 "The heurtistic for ScopInliner checks that the full function is a "
110 "Scop, which happens if and only if polly-allow-full-function is "
111 " enabled. "
112 " If not, the entry block is not included in the Scop");
113 }
114}
115
116PreservedAnalyses polly::ScopInlinerPass::run(llvm::LazyCallGraph::SCC &SCC,
117 llvm::CGSCCAnalysisManager &AM,
118 llvm::LazyCallGraph &CG,
119 llvm::CGSCCUpdateResult &UR) {
120 Function *F = &SCC.begin()->getFunction();
121 bool Changed = runScopInlinerImpl(F, SCC, FS);
122 return Changed ? PreservedAnalyses::none() : PreservedAnalyses::all();
123}
#define POLLY_DEBUG(X)
Definition PollyDebug.h:23
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)
ScopInlinerPass(llvm::IntrusiveRefCntPtr< llvm::vfs::FileSystem > FS)
llvm::IntrusiveRefCntPtr< llvm::vfs::FileSystem > FS
Definition ScopInliner.h:20
#define assert(exp)
bool PollyAllowFullFunction