Coverage Report

Created: 2019-07-24 05:18

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