xref: /freebsd/contrib/llvm-project/llvm/include/llvm/Analysis/FunctionPropertiesAnalysis.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
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/DenseSet.h"
18 #include "llvm/Analysis/IR2Vec.h"
19 #include "llvm/IR/Dominators.h"
20 #include "llvm/IR/PassManager.h"
21 #include "llvm/Support/Compiler.h"
22 
23 namespace llvm {
24 class BasicBlock;
25 class CallBase;
26 class DominatorTree;
27 class Function;
28 class LoopInfo;
29 
30 class FunctionPropertiesInfo {
31   friend class FunctionPropertiesUpdater;
32   void updateForBB(const BasicBlock &BB, int64_t Direction);
33   void updateAggregateStats(const Function &F, const LoopInfo &LI);
34   void reIncludeBB(const BasicBlock &BB);
35 
36   ir2vec::Embedding FunctionEmbedding = ir2vec::Embedding(0.0);
37   const ir2vec::Vocabulary *IR2VecVocab = nullptr;
38 
39 public:
40   LLVM_ABI static FunctionPropertiesInfo
41   getFunctionPropertiesInfo(const Function &F, const DominatorTree &DT,
42                             const LoopInfo &LI,
43                             const ir2vec::Vocabulary *Vocabulary);
44 
45   LLVM_ABI static FunctionPropertiesInfo
46   getFunctionPropertiesInfo(Function &F, FunctionAnalysisManager &FAM);
47 
48   LLVM_ABI bool operator==(const FunctionPropertiesInfo &FPI) const;
49 
50   bool operator!=(const FunctionPropertiesInfo &FPI) const {
51     return !(*this == FPI);
52   }
53 
54   LLVM_ABI void print(raw_ostream &OS) const;
55 
56   /// Number of basic blocks
57   int64_t BasicBlockCount = 0;
58 
59   /// Number of blocks reached from a conditional instruction, or that are
60   /// 'cases' of a SwitchInstr.
61   // FIXME: We may want to replace this with a more meaningful metric, like
62   // number of conditionally executed blocks:
63   // 'if (a) s();' would be counted here as 2 blocks, just like
64   // 'if (a) s(); else s2(); s3();' would.
65   int64_t BlocksReachedFromConditionalInstruction = 0;
66 
67   /// Number of uses of this function, plus 1 if the function is callable
68   /// outside the module.
69   int64_t Uses = 0;
70 
71   /// Number of direct calls made from this function to other functions
72   /// defined in this module.
73   int64_t DirectCallsToDefinedFunctions = 0;
74 
75   // Load Instruction Count
76   int64_t LoadInstCount = 0;
77 
78   // Store Instruction Count
79   int64_t StoreInstCount = 0;
80 
81   // Maximum Loop Depth in the Function
82   int64_t MaxLoopDepth = 0;
83 
84   // Number of Top Level Loops in the Function
85   int64_t TopLevelLoopCount = 0;
86 
87   // All non-debug instructions
88   int64_t TotalInstructionCount = 0;
89 
90   // Basic blocks grouped by number of successors.
91   int64_t BasicBlocksWithSingleSuccessor = 0;
92   int64_t BasicBlocksWithTwoSuccessors = 0;
93   int64_t BasicBlocksWithMoreThanTwoSuccessors = 0;
94 
95   // Basic blocks grouped by number of predecessors.
96   int64_t BasicBlocksWithSinglePredecessor = 0;
97   int64_t BasicBlocksWithTwoPredecessors = 0;
98   int64_t BasicBlocksWithMoreThanTwoPredecessors = 0;
99 
100   // Basic blocks grouped by size as determined by the number of non-debug
101   // instructions that they contain.
102   int64_t BigBasicBlocks = 0;
103   int64_t MediumBasicBlocks = 0;
104   int64_t SmallBasicBlocks = 0;
105 
106   // The number of cast instructions inside the function.
107   int64_t CastInstructionCount = 0;
108 
109   // The number of floating point instructions inside the function.
110   int64_t FloatingPointInstructionCount = 0;
111 
112   // The number of integer instructions inside the function.
113   int64_t IntegerInstructionCount = 0;
114 
115   // Operand type couns
116   int64_t ConstantIntOperandCount = 0;
117   int64_t ConstantFPOperandCount = 0;
118   int64_t ConstantOperandCount = 0;
119   int64_t InstructionOperandCount = 0;
120   int64_t BasicBlockOperandCount = 0;
121   int64_t GlobalValueOperandCount = 0;
122   int64_t InlineAsmOperandCount = 0;
123   int64_t ArgumentOperandCount = 0;
124   int64_t UnknownOperandCount = 0;
125 
126   // Additional CFG Properties
127   int64_t CriticalEdgeCount = 0;
128   int64_t ControlFlowEdgeCount = 0;
129   int64_t UnconditionalBranchCount = 0;
130 
131   // Call related instructions
132   int64_t IntrinsicCount = 0;
133   int64_t DirectCallCount = 0;
134   int64_t IndirectCallCount = 0;
135   int64_t CallReturnsIntegerCount = 0;
136   int64_t CallReturnsFloatCount = 0;
137   int64_t CallReturnsPointerCount = 0;
138   int64_t CallReturnsVectorIntCount = 0;
139   int64_t CallReturnsVectorFloatCount = 0;
140   int64_t CallReturnsVectorPointerCount = 0;
141   int64_t CallWithManyArgumentsCount = 0;
142   int64_t CallWithPointerArgumentCount = 0;
143 
getFunctionEmbedding()144   const ir2vec::Embedding &getFunctionEmbedding() const {
145     return FunctionEmbedding;
146   }
147 
getIR2VecVocab()148   const ir2vec::Vocabulary *getIR2VecVocab() const { return IR2VecVocab; }
149 
150   // Helper intended to be useful for unittests
setFunctionEmbeddingForTest(const ir2vec::Embedding & Embedding)151   void setFunctionEmbeddingForTest(const ir2vec::Embedding &Embedding) {
152     FunctionEmbedding = Embedding;
153   }
154 };
155 
156 // Analysis pass
157 class FunctionPropertiesAnalysis
158     : public AnalysisInfoMixin<FunctionPropertiesAnalysis> {
159 
160 public:
161   LLVM_ABI static AnalysisKey Key;
162 
163   using Result = const FunctionPropertiesInfo;
164 
165   LLVM_ABI FunctionPropertiesInfo run(Function &F,
166                                       FunctionAnalysisManager &FAM);
167 };
168 
169 /// Printer pass for the FunctionPropertiesAnalysis results.
170 class FunctionPropertiesPrinterPass
171     : public PassInfoMixin<FunctionPropertiesPrinterPass> {
172   raw_ostream &OS;
173 
174 public:
FunctionPropertiesPrinterPass(raw_ostream & OS)175   explicit FunctionPropertiesPrinterPass(raw_ostream &OS) : OS(OS) {}
176 
177   LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
178 
isRequired()179   static bool isRequired() { return true; }
180 };
181 
182 /// Correctly update FunctionPropertiesInfo post-inlining. A
183 /// FunctionPropertiesUpdater keeps the state necessary for tracking the changes
184 /// llvm::InlineFunction makes. The idea is that inlining will at most modify
185 /// a few BBs of the Caller (maybe the entry BB and definitely the callsite BB)
186 /// and potentially affect exception handling BBs in the case of invoke
187 /// inlining.
188 class FunctionPropertiesUpdater {
189 public:
190   LLVM_ABI FunctionPropertiesUpdater(FunctionPropertiesInfo &FPI, CallBase &CB);
191 
192   LLVM_ABI void finish(FunctionAnalysisManager &FAM) const;
finishAndTest(FunctionAnalysisManager & FAM)193   bool finishAndTest(FunctionAnalysisManager &FAM) const {
194     finish(FAM);
195     return isUpdateValid(Caller, FPI, FAM);
196   }
197 
198 private:
199   FunctionPropertiesInfo &FPI;
200   BasicBlock &CallSiteBB;
201   Function &Caller;
202 
203   LLVM_ABI static bool isUpdateValid(Function &F,
204                                      const FunctionPropertiesInfo &FPI,
205                                      FunctionAnalysisManager &FAM);
206 
207   DominatorTree &getUpdatedDominatorTree(FunctionAnalysisManager &FAM) const;
208 
209   DenseSet<const BasicBlock *> Successors;
210   DenseSet<const BasicBlock *> CallUsers;
211 
212   // Edges we might potentially need to remove from the dominator tree.
213   SmallVector<DominatorTree::UpdateType, 2> DomTreeUpdates;
214 };
215 } // namespace llvm
216 #endif // LLVM_ANALYSIS_FUNCTIONPROPERTIESANALYSIS_H
217