Index: llvm/include/llvm/Analysis/FunctionPropertiesAnalysis.h =================================================================== --- llvm/include/llvm/Analysis/FunctionPropertiesAnalysis.h +++ llvm/include/llvm/Analysis/FunctionPropertiesAnalysis.h @@ -82,5 +82,84 @@ PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); }; +class PreciseFunctionPropertiesInfo { +public: + static PreciseFunctionPropertiesInfo + getPreciseFunctionPropertiesInfo(const Function &F, const LoopInfo &LI); + + void print(raw_ostream &OS) const; + + void visitInstruction(Instruction &I) { + errs() << "Instruction Count does not know about " << I; + llvm_unreachable(nullptr); + } + +#define HANDLE_INST(N, OPCODE, CLASS) int64_t OPCODE##InstCount = 0; +#include "llvm/IR/Instruction.def" + + // Number of Basic Blocks. + int64_t BasicBlockCount = 0; + + /// Number of Basic Blocks with specific successors. + int64_t BasicBlockWithSingleSuccessor = 0; + int64_t BasicBlockWithTwoSuccessors = 0; + int64_t BasicBlockWithMoreThanTwoSuccessors = 0; + + /// Number of Basic Blocks with specific predecessors. + int64_t BasicBlockWithSinglePredecessor = 0; + int64_t BasicBlockWithTwoPredecessors = 0; + int64_t BasicBlockWithMoreThanTwoPredecessors = 0; + + // Number of basic blocks with more than 500 instructions. + int64_t BigBasicBlock = 0; + + // Number of basic blocks with 15 ~ 500 instructions. + int64_t MediumBasicBlock = 0; + + // Number of basic blocks with less than 15 instructions. + int64_t SmallBasicBlock = 0; + + /// Number of Cast-like Instruction Count in the Function. + int64_t CastInstCount = 0; + + /// Number of Floating Point Instruction Count. + int64_t FloatingPointInstCount = 0; + + /// Number of Integer Instruction Count. + int64_t IntegerInstCount = 0; + + /// Number of Occurences of Constants. + int64_t IntegerConstantOccurrences = 0; + int64_t FloatingConstantOccurrences = 0; + /// Maximum Loop Depth in the Function. + int64_t MaxLoopDepth = 0; + + /// Number of Top Level Loops in the Function. + int64_t TopLevelLoopCount = 0; +}; + +// Analysis pass +class PreciseFunctionPropertiesAnalysis + : public AnalysisInfoMixin { + +public: + static AnalysisKey Key; + + using Result = PreciseFunctionPropertiesInfo; + + Result run(Function &F, FunctionAnalysisManager &FAM); +}; + +/// Printer pass for the PreciseFunctionPropertiesAnalysis results. +class PreciseFunctionPropertiesPrinterPass + : public PassInfoMixin { + raw_ostream &OS; + +public: + explicit PreciseFunctionPropertiesPrinterPass(raw_ostream &OS) : OS(OS) {} + + PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); +}; + } // namespace llvm #endif // LLVM_ANALYSIS_FUNCTIONPROPERTIESANALYSIS_H Index: llvm/lib/Analysis/FunctionPropertiesAnalysis.cpp =================================================================== --- llvm/lib/Analysis/FunctionPropertiesAnalysis.cpp +++ llvm/lib/Analysis/FunctionPropertiesAnalysis.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Analysis/FunctionPropertiesAnalysis.h" +#include "llvm/IR/InstVisitor.h" #include "llvm/IR/Instructions.h" using namespace llvm; @@ -86,3 +87,144 @@ AM.getResult(F).print(OS); return PreservedAnalyses::all(); } + +namespace { +class InstCount : public InstVisitor { + friend class InstVisitor; + +#define HANDLE_INST(N, OPCODE, CLASS) \ + void visit##OPCODE(CLASS &) { ++FPI.OPCODE##InstCount; } + +#include "llvm/IR/Instruction.def" + + void visitInstruction(Instruction &I) { + errs() << "Instruction Count does not know about " << I; + llvm_unreachable(nullptr); + } + void visitFunction(Function &F) { + errs() << "Should never visit a function " << F; + llvm_unreachable(nullptr); + } + void visitBasicBlock(BasicBlock &BB) { + errs() << "Should never visit a basic block " << BB; + llvm_unreachable(nullptr); + } + + PreciseFunctionPropertiesInfo &FPI; + +public: + InstCount(PreciseFunctionPropertiesInfo &FPI) : FPI(FPI) {} +}; +} // namespace + +PreciseFunctionPropertiesInfo +PreciseFunctionPropertiesInfo::getPreciseFunctionPropertiesInfo( + const Function &F, const LoopInfo &LI) { + + PreciseFunctionPropertiesInfo FPI; + InstCount IC(FPI); + + for (const auto &BB : F) { + ++FPI.BasicBlockCount; + + unsigned SuccSize = succ_size(&BB); + unsigned PredSize = pred_size(&BB); + if (SuccSize == 1) + ++FPI.BasicBlockWithSingleSuccessor; + else if (SuccSize == 2) + ++FPI.BasicBlockWithTwoSuccessors; + else if (SuccSize > 2) + ++FPI.BasicBlockWithMoreThanTwoSuccessors; + + if (PredSize == 1) + ++FPI.BasicBlockWithSinglePredecessor; + else if (PredSize == 2) + ++FPI.BasicBlockWithTwoPredecessors; + else if (PredSize > 2) + ++FPI.BasicBlockWithMoreThanTwoPredecessors; + + if (BB.size() > 500) + ++FPI.BigBasicBlock; + else if (BB.size() >= 15) + ++FPI.MediumBasicBlock; + else + ++FPI.SmallBasicBlock; + + for (const auto &I : BB) { + if (I.getType()->isFloatTy()) + ++FPI.FloatingPointInstCount; + else if (I.getType()->isIntegerTy()) + ++FPI.IntegerInstCount; + + for (unsigned int i = 0; i < I.getNumOperands(); i++) + if (auto *C = dyn_cast(I.getOperand(i))) { + if (C->getType()->isIntegerTy()) + ++FPI.IntegerConstantOccurrences; + else if (C->getType()->isFloatTy()) + ++FPI.FloatingConstantOccurrences; + } + + if (I.isCast()) + ++FPI.CastInstCount; + IC.visit(const_cast(&I)); + } + } + + for (const auto &BB : F) { + int LoopDepth = LI.getLoopDepth(&BB); + if (FPI.MaxLoopDepth < LoopDepth) + FPI.MaxLoopDepth = LoopDepth; + } + + FPI.TopLevelLoopCount += llvm::size(LI); + return FPI; +} + +AnalysisKey PreciseFunctionPropertiesAnalysis::Key; + +PreciseFunctionPropertiesInfo +PreciseFunctionPropertiesAnalysis::run(Function &F, + FunctionAnalysisManager &FAM) { + return PreciseFunctionPropertiesInfo::getPreciseFunctionPropertiesInfo( + F, FAM.getResult(F)); +} + +void PreciseFunctionPropertiesInfo::print(raw_ostream &OS) const { + OS << "BasicBlockCount: " << BasicBlockCount << "\n" + << "BasicBlockWithSingleSuccessor: " << BasicBlockWithSingleSuccessor + << "\n" + << "BasicBlockWithTwoSuccessors: " << BasicBlockWithTwoSuccessors << "\n" + << "BasicBlockWithMoreThanTwoSuccessors: " + << BasicBlockWithMoreThanTwoSuccessors << "\n" + << "BasicBlockWithSinglePredecessor: " << BasicBlockWithSinglePredecessor + << "\n" + << "BasicBlockWithTwoPredecessors: " << BasicBlockWithTwoPredecessors + << "\n" + << "BasicBlockWithMoreThanTwoPredecessors: " + << BasicBlockWithMoreThanTwoPredecessors << "\n" + << "BigBasicBlock: " << BigBasicBlock << "\n" + << "MediumBasicBlock: " << MediumBasicBlock << "\n" + << "SmallBasicBlock: " << SmallBasicBlock << "\n" + << "CastInstCount: " << CastInstCount << "\n" + << "FloatingPointInstCount: " << FloatingPointInstCount << "\n" + << "IntegerInstCount: " << IntegerInstCount << "\n" + << "IntegerConstantOccurrences: " << IntegerConstantOccurrences << "\n" + << "FloatingConstantOccurrences: " << FloatingConstantOccurrences << "\n" + << "MaxLoopDepth: " << MaxLoopDepth << "\n" + << "TopLevelLoopCount: " << TopLevelLoopCount << "\n"; +#define HANDLE_INST(N, OPCODE, CLASS) \ + OS << #OPCODE << "InstCount" \ + << ": " << OPCODE##InstCount << "\n"; + +#include "llvm/IR/Instruction.def" +} + +PreservedAnalyses +PreciseFunctionPropertiesPrinterPass::run(Function &F, + FunctionAnalysisManager &AM) { + OS << "Printing analysis results of CFA for function " + << "'" << F.getName() << "':" + << "\n"; + AM.getResult(F).print(OS); + return PreservedAnalyses::all(); +} \ No newline at end of file Index: llvm/lib/Passes/PassRegistry.def =================================================================== --- llvm/lib/Passes/PassRegistry.def +++ llvm/lib/Passes/PassRegistry.def @@ -173,6 +173,8 @@ FUNCTION_ANALYSIS("demanded-bits", DemandedBitsAnalysis()) FUNCTION_ANALYSIS("domfrontier", DominanceFrontierAnalysis()) FUNCTION_ANALYSIS("func-properties", FunctionPropertiesAnalysis()) +FUNCTION_ANALYSIS("precise-func-properties", + PreciseFunctionPropertiesAnalysis()) FUNCTION_ANALYSIS("loops", LoopAnalysis()) FUNCTION_ANALYSIS("lazy-value-info", LazyValueAnalysis()) FUNCTION_ANALYSIS("da", DependenceAnalysis()) @@ -292,6 +294,8 @@ FUNCTION_PASS("print", DemandedBitsPrinterPass(dbgs())) FUNCTION_PASS("print", DominanceFrontierPrinterPass(dbgs())) FUNCTION_PASS("print", FunctionPropertiesPrinterPass(dbgs())) +FUNCTION_PASS("print", + PreciseFunctionPropertiesPrinterPass(dbgs())) FUNCTION_PASS("print", InlineCostAnnotationPrinterPass(dbgs())) FUNCTION_PASS("print", InlineSizeEstimatorAnalysisPrinterPass(dbgs())) Index: llvm/unittests/Analysis/FunctionPropertiesAnalysisTest.cpp =================================================================== --- llvm/unittests/Analysis/FunctionPropertiesAnalysisTest.cpp +++ llvm/unittests/Analysis/FunctionPropertiesAnalysisTest.cpp @@ -29,6 +29,13 @@ return FunctionPropertiesInfo::getFunctionPropertiesInfo(F, *LI); } + PreciseFunctionPropertiesInfo buildPreciseFPI(Function &F) { + DT.reset(new DominatorTree(F)); + LI.reset(new LoopInfo(*DT)); + return PreciseFunctionPropertiesInfo::getPreciseFunctionPropertiesInfo(F, + *LI); + } + std::unique_ptr makeLLVMModule(LLVMContext &C, const char *IR) { SMDiagnostic Err; std::unique_ptr Mod = parseAssemblyString(IR, Err, C); @@ -89,5 +96,20 @@ EXPECT_EQ(BranchesFeatures.StoreInstCount, 0); EXPECT_EQ(BranchesFeatures.MaxLoopDepth, 0); EXPECT_EQ(BranchesFeatures.TopLevelLoopCount, 0); + + PreciseFunctionPropertiesInfo PreciseFeatures = + buildPreciseFPI(*BranchesFunction); + EXPECT_EQ(PreciseFeatures.BasicBlockCount, 4); + EXPECT_EQ(PreciseFeatures.BasicBlockWithSingleSuccessor, 2); + EXPECT_EQ(PreciseFeatures.BasicBlockWithTwoSuccessors, 1); + EXPECT_EQ(PreciseFeatures.BasicBlockWithSinglePredecessor, 2); + EXPECT_EQ(PreciseFeatures.SmallBasicBlock, 4); + EXPECT_EQ(PreciseFeatures.IntegerInstCount, 4); + EXPECT_EQ(PreciseFeatures.IntegerConstantOccurrences, 1); + EXPECT_EQ(PreciseFeatures.RetInstCount, 1); + EXPECT_EQ(PreciseFeatures.BrInstCount, 3); + EXPECT_EQ(PreciseFeatures.ICmpInstCount, 1); + EXPECT_EQ(PreciseFeatures.PHIInstCount, 1); + EXPECT_EQ(PreciseFeatures.CallInstCount, 2); } } // end anonymous namespace \ No newline at end of file