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