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