123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127 |
- //===---- ScopInliner.cpp - Polyhedral based inliner ----------------------===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- //
- // Take a SCC and:
- // 1. If it has more than one component, bail out (contains cycles)
- // 2. If it has just one component, and if the function is entirely a scop,
- // inline it.
- //
- //===----------------------------------------------------------------------===//
- #include "polly/LinkAllPasses.h"
- #include "polly/ScopDetection.h"
- #include "llvm/Analysis/CallGraph.h"
- #include "llvm/Analysis/CallGraphSCCPass.h"
- #include "llvm/IR/PassManager.h"
- #include "llvm/Passes/PassBuilder.h"
- #include "llvm/Transforms/IPO/AlwaysInliner.h"
- #define DEBUG_TYPE "polly-scop-inliner"
- using namespace llvm;
- using namespace polly;
- namespace {
- class ScopInliner : public CallGraphSCCPass {
- using llvm::Pass::doInitialization;
- public:
- static char ID;
- ScopInliner() : CallGraphSCCPass(ID) {}
- bool doInitialization(CallGraph &CG) override {
- if (!polly::PollyAllowFullFunction) {
- report_fatal_error(
- "Aborting from ScopInliner because it only makes sense to run with "
- "-polly-allow-full-function. "
- "The heurtistic for ScopInliner checks that the full function is a "
- "Scop, which happens if and only if polly-allow-full-function is "
- " enabled. "
- " If not, the entry block is not included in the Scop");
- }
- return true;
- }
- bool runOnSCC(CallGraphSCC &SCC) override {
- // We do not try to inline non-trivial SCCs because this would lead to
- // "infinite" inlining if we are not careful.
- if (SCC.size() > 1)
- return false;
- assert(SCC.size() == 1 && "found empty SCC");
- Function *F = (*SCC.begin())->getFunction();
- // If the function is a nullptr, or the function is a declaration.
- if (!F)
- return false;
- if (F->isDeclaration()) {
- LLVM_DEBUG(dbgs() << "Skipping " << F->getName()
- << "because it is a declaration.\n");
- return false;
- }
- PassBuilder PB;
- // Populate analysis managers and register Polly-specific analyses.
- LoopAnalysisManager LAM;
- FunctionAnalysisManager FAM;
- CGSCCAnalysisManager CGAM;
- ModuleAnalysisManager MAM;
- FAM.registerPass([] { return ScopAnalysis(); });
- PB.registerModuleAnalyses(MAM);
- PB.registerCGSCCAnalyses(CGAM);
- PB.registerFunctionAnalyses(FAM);
- PB.registerLoopAnalyses(LAM);
- PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
- RegionInfo &RI = FAM.getResult<RegionInfoAnalysis>(*F);
- ScopDetection &SD = FAM.getResult<ScopAnalysis>(*F);
- const bool HasScopAsTopLevelRegion =
- SD.ValidRegions.contains(RI.getTopLevelRegion());
- bool Changed = false;
- if (HasScopAsTopLevelRegion) {
- LLVM_DEBUG(dbgs() << "Skipping " << F->getName()
- << " has scop as top level region");
- F->addFnAttr(llvm::Attribute::AlwaysInline);
- ModulePassManager MPM;
- MPM.addPass(AlwaysInlinerPass());
- Module *M = F->getParent();
- assert(M && "Function has illegal module");
- PreservedAnalyses PA = MPM.run(*M, MAM);
- if (!PA.areAllPreserved())
- Changed = true;
- } else {
- LLVM_DEBUG(dbgs() << F->getName()
- << " does NOT have scop as top level region\n");
- }
- return Changed;
- };
- void getAnalysisUsage(AnalysisUsage &AU) const override {
- CallGraphSCCPass::getAnalysisUsage(AU);
- }
- };
- } // namespace
- char ScopInliner::ID;
- Pass *polly::createScopInlinerPass() {
- ScopInliner *pass = new ScopInliner();
- return pass;
- }
- INITIALIZE_PASS_BEGIN(
- ScopInliner, "polly-scop-inliner",
- "inline functions based on how much of the function is a scop.", false,
- false)
- INITIALIZE_PASS_END(
- ScopInliner, "polly-scop-inliner",
- "inline functions based on how much of the function is a scop.", false,
- false)
|