//=- FunctionPropertiesAnalysis.h - Function Properties Analysis --*- C++ -*-=// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file defines the FunctionPropertiesInfo and FunctionPropertiesAnalysis // classes used to extract function properties. // //===----------------------------------------------------------------------===// #ifndef LLVM_ANALYSIS_FUNCTIONPROPERTIESANALYSIS_H #define LLVM_ANALYSIS_FUNCTIONPROPERTIESANALYSIS_H #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/iterator_range.h" #include "llvm/IR/InstrTypes.h" #include "llvm/IR/PassManager.h" namespace llvm { class DominatorTree; class Function; class LoopInfo; class FunctionPropertiesInfo { friend class FunctionPropertiesUpdater; void updateForBB(const BasicBlock &BB, int64_t Direction); void updateAggregateStats(const Function &F, const LoopInfo &LI); void reIncludeBB(const BasicBlock &BB); public: static FunctionPropertiesInfo getFunctionPropertiesInfo(const Function &F, const DominatorTree &DT, const LoopInfo &LI); static FunctionPropertiesInfo getFunctionPropertiesInfo(Function &F, FunctionAnalysisManager &FAM); bool operator==(const FunctionPropertiesInfo &FPI) const { return std::memcmp(this, &FPI, sizeof(FunctionPropertiesInfo)) == 0; } bool operator!=(const FunctionPropertiesInfo &FPI) const { return !(*this == FPI); } void print(raw_ostream &OS) const; /// Number of basic blocks int64_t BasicBlockCount = 0; /// Number of blocks reached from a conditional instruction, or that are /// 'cases' of a SwitchInstr. // FIXME: We may want to replace this with a more meaningful metric, like // number of conditionally executed blocks: // 'if (a) s();' would be counted here as 2 blocks, just like // 'if (a) s(); else s2(); s3();' would. int64_t BlocksReachedFromConditionalInstruction = 0; /// Number of uses of this function, plus 1 if the function is callable /// outside the module. int64_t Uses = 0; /// Number of direct calls made from this function to other functions /// defined in this module. int64_t DirectCallsToDefinedFunctions = 0; // Load Instruction Count int64_t LoadInstCount = 0; // Store Instruction Count int64_t StoreInstCount = 0; // Maximum Loop Depth in the Function int64_t MaxLoopDepth = 0; // Number of Top Level Loops in the Function int64_t TopLevelLoopCount = 0; // All non-debug instructions int64_t TotalInstructionCount = 0; }; // Analysis pass class FunctionPropertiesAnalysis : public AnalysisInfoMixin { public: static AnalysisKey Key; using Result = const FunctionPropertiesInfo; FunctionPropertiesInfo run(Function &F, FunctionAnalysisManager &FAM); }; /// Printer pass for the FunctionPropertiesAnalysis results. class FunctionPropertiesPrinterPass : public PassInfoMixin { raw_ostream &OS; public: explicit FunctionPropertiesPrinterPass(raw_ostream &OS) : OS(OS) {} PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); }; /// Correctly update FunctionPropertiesInfo post-inlining. A /// FunctionPropertiesUpdater keeps the state necessary for tracking the changes /// llvm::InlineFunction makes. The idea is that inlining will at most modify /// a few BBs of the Caller (maybe the entry BB and definitely the callsite BB) /// and potentially affect exception handling BBs in the case of invoke /// inlining. class FunctionPropertiesUpdater { public: FunctionPropertiesUpdater(FunctionPropertiesInfo &FPI, CallBase &CB); void finish(FunctionAnalysisManager &FAM) const; bool finishAndTest(FunctionAnalysisManager &FAM) const { finish(FAM); return isUpdateValid(Caller, FPI, FAM); } private: FunctionPropertiesInfo &FPI; BasicBlock &CallSiteBB; Function &Caller; static bool isUpdateValid(Function &F, const FunctionPropertiesInfo &FPI, FunctionAnalysisManager &FAM); DenseSet Successors; }; } // namespace llvm #endif // LLVM_ANALYSIS_FUNCTIONPROPERTIESANALYSIS_H