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/LinkAllPasses.h" 17 #include "polly/ScopDetection.h" 18 #include "llvm/Analysis/CallGraph.h" 19 #include "llvm/Analysis/CallGraphSCCPass.h" 20 #include "llvm/IR/PassManager.h" 21 #include "llvm/Passes/PassBuilder.h" 22 #include "llvm/Transforms/IPO/AlwaysInliner.h" 23 24 #define DEBUG_TYPE "polly-scop-inliner" 25 26 using namespace polly; 27 extern bool polly::PollyAllowFullFunction; 28 29 namespace { 30 class ScopInliner : public CallGraphSCCPass { 31 using llvm::Pass::doInitialization; 32 33 public: 34 static char ID; 35 36 ScopInliner() : CallGraphSCCPass(ID) {} 37 38 bool doInitialization(CallGraph &CG) override { 39 if (!polly::PollyAllowFullFunction) { 40 report_fatal_error( 41 "Aborting from ScopInliner because it only makes sense to run with " 42 "-polly-allow-full-function. " 43 "The heurtistic for ScopInliner checks that the full function is a " 44 "Scop, which happens if and only if polly-allow-full-function is " 45 " enabled. " 46 " If not, the entry block is not included in the Scop"); 47 } 48 return true; 49 } 50 51 bool runOnSCC(CallGraphSCC &SCC) override { 52 // We do not try to inline non-trivial SCCs because this would lead to 53 // "infinite" inlining if we are not careful. 54 if (SCC.size() > 1) 55 return false; 56 assert(SCC.size() == 1 && "found empty SCC"); 57 Function *F = (*SCC.begin())->getFunction(); 58 59 // If the function is a nullptr, or the function is a declaration. 60 if (!F) 61 return false; 62 if (F->isDeclaration()) { 63 LLVM_DEBUG(dbgs() << "Skipping " << F->getName() 64 << "because it is a declaration.\n"); 65 return false; 66 } 67 68 PassBuilder PB; 69 FunctionAnalysisManager FAM; 70 FAM.registerPass([] { return ScopAnalysis(); }); 71 PB.registerFunctionAnalyses(FAM); 72 73 RegionInfo &RI = FAM.getResult<RegionInfoAnalysis>(*F); 74 ScopDetection &SD = FAM.getResult<ScopAnalysis>(*F); 75 76 const bool HasScopAsTopLevelRegion = 77 SD.ValidRegions.count(RI.getTopLevelRegion()) > 0; 78 79 if (HasScopAsTopLevelRegion) { 80 LLVM_DEBUG(dbgs() << "Skipping " << F->getName() 81 << " has scop as top level region"); 82 F->addFnAttr(llvm::Attribute::AlwaysInline); 83 84 ModuleAnalysisManager MAM; 85 PB.registerModuleAnalyses(MAM); 86 MAM.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM); }); 87 ModulePassManager MPM; 88 MPM.addPass(AlwaysInlinerPass()); 89 Module *M = F->getParent(); 90 assert(M && "Function has illegal module"); 91 MPM.run(*M, MAM); 92 } else { 93 LLVM_DEBUG(dbgs() << F->getName() 94 << " does NOT have scop as top level region\n"); 95 } 96 97 return false; 98 }; 99 100 void getAnalysisUsage(AnalysisUsage &AU) const override { 101 CallGraphSCCPass::getAnalysisUsage(AU); 102 } 103 }; 104 } // namespace 105 char ScopInliner::ID; 106 107 Pass *polly::createScopInlinerPass() { 108 ScopInliner *pass = new ScopInliner(); 109 return pass; 110 } 111 112 INITIALIZE_PASS_BEGIN( 113 ScopInliner, "polly-scop-inliner", 114 "inline functions based on how much of the function is a scop.", false, 115 false) 116 INITIALIZE_PASS_END( 117 ScopInliner, "polly-scop-inliner", 118 "inline functions based on how much of the function is a scop.", false, 119 false) 120