1 //=- FunctionPropertiesAnalysis.h - Function Properties Analysis --*- C++ -*-=//
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 // This file defines the FunctionPropertiesInfo and FunctionPropertiesAnalysis
10 // classes used to extract function properties.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_ANALYSIS_FUNCTIONPROPERTIESANALYSIS_H
15 #define LLVM_ANALYSIS_FUNCTIONPROPERTIESANALYSIS_H
16 
17 #include "llvm/ADT/SmallPtrSet.h"
18 #include "llvm/ADT/iterator_range.h"
19 #include "llvm/IR/InstrTypes.h"
20 #include "llvm/IR/PassManager.h"
21 
22 namespace llvm {
23 class DominatorTree;
24 class Function;
25 class LoopInfo;
26 
27 class FunctionPropertiesInfo {
28   friend class FunctionPropertiesUpdater;
29   void updateForBB(const BasicBlock &BB, int64_t Direction);
30   void updateAggregateStats(const Function &F, const LoopInfo &LI);
31   void reIncludeBB(const BasicBlock &BB);
32 
33 public:
34   static FunctionPropertiesInfo
35   getFunctionPropertiesInfo(const Function &F, const DominatorTree &DT,
36                             const LoopInfo &LI);
37 
38   static FunctionPropertiesInfo
39   getFunctionPropertiesInfo(Function &F, FunctionAnalysisManager &FAM);
40 
41   bool operator==(const FunctionPropertiesInfo &FPI) const {
42     return std::memcmp(this, &FPI, sizeof(FunctionPropertiesInfo)) == 0;
43   }
44 
45   bool operator!=(const FunctionPropertiesInfo &FPI) const {
46     return !(*this == FPI);
47   }
48 
49   void print(raw_ostream &OS) const;
50 
51   /// Number of basic blocks
52   int64_t BasicBlockCount = 0;
53 
54   /// Number of blocks reached from a conditional instruction, or that are
55   /// 'cases' of a SwitchInstr.
56   // FIXME: We may want to replace this with a more meaningful metric, like
57   // number of conditionally executed blocks:
58   // 'if (a) s();' would be counted here as 2 blocks, just like
59   // 'if (a) s(); else s2(); s3();' would.
60   int64_t BlocksReachedFromConditionalInstruction = 0;
61 
62   /// Number of uses of this function, plus 1 if the function is callable
63   /// outside the module.
64   int64_t Uses = 0;
65 
66   /// Number of direct calls made from this function to other functions
67   /// defined in this module.
68   int64_t DirectCallsToDefinedFunctions = 0;
69 
70   // Load Instruction Count
71   int64_t LoadInstCount = 0;
72 
73   // Store Instruction Count
74   int64_t StoreInstCount = 0;
75 
76   // Maximum Loop Depth in the Function
77   int64_t MaxLoopDepth = 0;
78 
79   // Number of Top Level Loops in the Function
80   int64_t TopLevelLoopCount = 0;
81 
82   // All non-debug instructions
83   int64_t TotalInstructionCount = 0;
84 };
85 
86 // Analysis pass
87 class FunctionPropertiesAnalysis
88     : public AnalysisInfoMixin<FunctionPropertiesAnalysis> {
89 
90 public:
91   static AnalysisKey Key;
92 
93   using Result = const FunctionPropertiesInfo;
94 
95   FunctionPropertiesInfo run(Function &F, FunctionAnalysisManager &FAM);
96 };
97 
98 /// Printer pass for the FunctionPropertiesAnalysis results.
99 class FunctionPropertiesPrinterPass
100     : public PassInfoMixin<FunctionPropertiesPrinterPass> {
101   raw_ostream &OS;
102 
103 public:
104   explicit FunctionPropertiesPrinterPass(raw_ostream &OS) : OS(OS) {}
105 
106   PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
107 };
108 
109 /// Correctly update FunctionPropertiesInfo post-inlining. A
110 /// FunctionPropertiesUpdater keeps the state necessary for tracking the changes
111 /// llvm::InlineFunction makes. The idea is that inlining will at most modify
112 /// a few BBs of the Caller (maybe the entry BB and definitely the callsite BB)
113 /// and potentially affect exception handling BBs in the case of invoke
114 /// inlining.
115 class FunctionPropertiesUpdater {
116 public:
117   FunctionPropertiesUpdater(FunctionPropertiesInfo &FPI, CallBase &CB);
118 
119   void finish(FunctionAnalysisManager &FAM) const;
120   bool finishAndTest(FunctionAnalysisManager &FAM) const {
121     finish(FAM);
122     return isUpdateValid(Caller, FPI, FAM);
123   }
124 
125 private:
126   FunctionPropertiesInfo &FPI;
127   BasicBlock &CallSiteBB;
128   Function &Caller;
129 
130   static bool isUpdateValid(Function &F, const FunctionPropertiesInfo &FPI,
131                             FunctionAnalysisManager &FAM);
132 
133   DenseSet<const BasicBlock *> Successors;
134 };
135 } // namespace llvm
136 #endif // LLVM_ANALYSIS_FUNCTIONPROPERTIESANALYSIS_H
137