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 llvm; 27 using namespace polly; 28 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 LLVM_DEBUG(dbgs() << "Skipping " << F->getName() 66 << "because it is a declaration.\n"); 67 return false; 68 } 69 70 PassBuilder PB; 71 // Populate analysis managers and register Polly-specific analyses. 72 LoopAnalysisManager LAM; 73 FunctionAnalysisManager FAM; 74 CGSCCAnalysisManager CGAM; 75 ModuleAnalysisManager MAM; 76 FAM.registerPass([] { return ScopAnalysis(); }); 77 PB.registerModuleAnalyses(MAM); 78 PB.registerCGSCCAnalyses(CGAM); 79 PB.registerFunctionAnalyses(FAM); 80 PB.registerLoopAnalyses(LAM); 81 PB.crossRegisterProxies(LAM, FAM, CGAM, MAM); 82 83 RegionInfo &RI = FAM.getResult<RegionInfoAnalysis>(*F); 84 ScopDetection &SD = FAM.getResult<ScopAnalysis>(*F); 85 86 const bool HasScopAsTopLevelRegion = 87 SD.ValidRegions.count(RI.getTopLevelRegion()) > 0; 88 89 bool Changed = false; 90 if (HasScopAsTopLevelRegion) { 91 LLVM_DEBUG(dbgs() << "Skipping " << F->getName() 92 << " has scop as top level region"); 93 F->addFnAttr(llvm::Attribute::AlwaysInline); 94 95 ModulePassManager MPM; 96 MPM.addPass(AlwaysInlinerPass()); 97 Module *M = F->getParent(); 98 assert(M && "Function has illegal module"); 99 PreservedAnalyses PA = MPM.run(*M, MAM); 100 if (!PA.areAllPreserved()) 101 Changed = true; 102 } else { 103 LLVM_DEBUG(dbgs() << F->getName() 104 << " does NOT have scop as top level region\n"); 105 } 106 107 return Changed; 108 }; 109 110 void getAnalysisUsage(AnalysisUsage &AU) const override { 111 CallGraphSCCPass::getAnalysisUsage(AU); 112 } 113 }; 114 } // namespace 115 char ScopInliner::ID; 116 117 Pass *polly::createScopInlinerPass() { 118 ScopInliner *pass = new ScopInliner(); 119 return pass; 120 } 121 122 INITIALIZE_PASS_BEGIN( 123 ScopInliner, "polly-scop-inliner", 124 "inline functions based on how much of the function is a scop.", false, 125 false) 126 INITIALIZE_PASS_END( 127 ScopInliner, "polly-scop-inliner", 128 "inline functions based on how much of the function is a scop.", false, 129 false) 130