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