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