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