Index: llvm/include/llvm/Analysis/FunctionPropertiesAnalysis.h =================================================================== --- llvm/include/llvm/Analysis/FunctionPropertiesAnalysis.h +++ llvm/include/llvm/Analysis/FunctionPropertiesAnalysis.h @@ -82,5 +82,102 @@ PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); }; +class DetailedFunctionPropertiesInfo { +public: + static DetailedFunctionPropertiesInfo + getDetailedFunctionPropertiesInfo(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) \ +private: \ + int64_t OPCODE##InstCount = 0; \ + void set##OPCODE##InstCount(int64_t value) { OPCODE##InstCount = value; } \ + void increment##OPCODE##InstCount() { ++OPCODE##InstCount; } \ + \ +public: \ + int64_t get##OPCODE##InstCount() const { return OPCODE##InstCount; } + +#include "llvm/IR/Instruction.def" + +#define DEFINE_FEATURE_VARIABLE(NAME) \ +private: \ + int64_t NAME = 0; \ + void increment##NAME() { ++NAME; } \ + void set##NAME(int64_t value) { NAME = value; } \ + \ +public: \ + int64_t get##NAME() const { return NAME; } + + // Number of Basic Blocks. + DEFINE_FEATURE_VARIABLE(BasicBlockCount); + + /// Number of Basic Blocks with specific successors. + DEFINE_FEATURE_VARIABLE(BasicBlockWithSingleSuccessor); + DEFINE_FEATURE_VARIABLE(BasicBlockWithTwoSuccessors); + DEFINE_FEATURE_VARIABLE(BasicBlockWithMoreThanTwoSuccessors); + + /// Number of Basic Blocks with specific predecessors. + DEFINE_FEATURE_VARIABLE(BasicBlockWithSinglePredecessor); + DEFINE_FEATURE_VARIABLE(BasicBlockWithTwoPredecessors); + DEFINE_FEATURE_VARIABLE(BasicBlockWithMoreThanTwoPredecessors); + + // Number of basic blocks with more than 500 instructions. + DEFINE_FEATURE_VARIABLE(BigBasicBlock); + + // Number of basic blocks with 15 ~ 500 instructions. + DEFINE_FEATURE_VARIABLE(MediumBasicBlock); + + // Number of basic blocks with less than 15 instructions. + DEFINE_FEATURE_VARIABLE(SmallBasicBlock); + + /// Number of Cast-like Instruction Count in the Function. + DEFINE_FEATURE_VARIABLE(CastInstCount); + + /// Number of Floating Point Instruction Count. + DEFINE_FEATURE_VARIABLE(FloatingPointInstCount); + + /// Number of Integer Instruction Count. + DEFINE_FEATURE_VARIABLE(IntegerInstCount); + + /// Number of Occurences of Constants. + DEFINE_FEATURE_VARIABLE(IntegerConstantOccurrences); + DEFINE_FEATURE_VARIABLE(FloatingConstantOccurrences); + /// Maximum Loop Depth in the Function. + DEFINE_FEATURE_VARIABLE(MaxLoopDepth); + + /// Number of Top Level Loops in the Function. + DEFINE_FEATURE_VARIABLE(TopLevelLoopCount); +#undef DEFINE_FEATURE_VARIABLE +}; + +// Analysis pass +class DetailedFunctionPropertiesAnalysis + : public AnalysisInfoMixin { + +public: + static AnalysisKey Key; + + using Result = DetailedFunctionPropertiesInfo; + + Result run(Function &F, FunctionAnalysisManager &FAM); +}; + +/// Printer pass for the DetailedFunctionPropertiesAnalysis results. +class DetailedFunctionPropertiesPrinterPass + : public PassInfoMixin { + raw_ostream &OS; + +public: + explicit DetailedFunctionPropertiesPrinterPass(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,141 @@ AM.getResult(F).print(OS); return PreservedAnalyses::all(); } + +DetailedFunctionPropertiesInfo +DetailedFunctionPropertiesInfo::getDetailedFunctionPropertiesInfo( + const Function &F, const LoopInfo &LI) { + class InstCount : public InstVisitor { + friend class InstVisitor; + +#define HANDLE_INST(N, OPCODE, CLASS) \ + void visit##OPCODE(CLASS &) { FPI.increment##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); + } + + DetailedFunctionPropertiesInfo &FPI; + + public: + InstCount(DetailedFunctionPropertiesInfo &FPI) : FPI(FPI) {} + }; + + DetailedFunctionPropertiesInfo FPI; + InstCount IC(FPI); + + for (const auto &BB : F) { + FPI.incrementBasicBlockCount(); + + unsigned SuccSize = succ_size(&BB); + unsigned PredSize = pred_size(&BB); + if (SuccSize == 1) + FPI.incrementBasicBlockWithSingleSuccessor(); + else if (SuccSize == 2) + FPI.incrementBasicBlockWithTwoSuccessors(); + else if (SuccSize > 2) + FPI.incrementBasicBlockWithMoreThanTwoSuccessors(); + + if (PredSize == 1) + FPI.incrementBasicBlockWithSinglePredecessor(); + else if (PredSize == 2) + FPI.incrementBasicBlockWithTwoPredecessors(); + else if (PredSize > 2) + FPI.incrementBasicBlockWithMoreThanTwoPredecessors(); + + if (BB.size() > 500) + FPI.incrementBigBasicBlock(); + else if (BB.size() >= 15) + FPI.incrementMediumBasicBlock(); + else + FPI.incrementSmallBasicBlock(); + + for (const auto &I : BB) { + if (I.getType()->isFloatTy()) + FPI.incrementFloatingPointInstCount(); + else if (I.getType()->isIntegerTy()) + FPI.incrementIntegerInstCount(); + + for (unsigned int i = 0; i < I.getNumOperands(); i++) + if (auto *C = dyn_cast(I.getOperand(i))) { + if (C->getType()->isIntegerTy()) + FPI.incrementIntegerConstantOccurrences(); + else if (C->getType()->isFloatTy()) + FPI.incrementFloatingConstantOccurrences(); + } + + if (I.isCast()) + FPI.incrementCastInstCount(); + IC.visit(const_cast(&I)); + } + } + + for (const auto &BB : F) { + int LoopDepth = LI.getLoopDepth(&BB); + if (FPI.getMaxLoopDepth() < LoopDepth) + FPI.setMaxLoopDepth(LoopDepth); + } + + FPI.setTopLevelLoopCount(llvm::size(LI)); + return FPI; +} + +AnalysisKey DetailedFunctionPropertiesAnalysis::Key; + +DetailedFunctionPropertiesInfo +DetailedFunctionPropertiesAnalysis::run(Function &F, + FunctionAnalysisManager &FAM) { + return DetailedFunctionPropertiesInfo::getDetailedFunctionPropertiesInfo( + F, FAM.getResult(F)); +} + +void DetailedFunctionPropertiesInfo::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 +DetailedFunctionPropertiesPrinterPass::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("detailed-func-properties", + DetailedFunctionPropertiesAnalysis()) FUNCTION_ANALYSIS("loops", LoopAnalysis()) FUNCTION_ANALYSIS("lazy-value-info", LazyValueAnalysis()) FUNCTION_ANALYSIS("da", DependenceAnalysis()) @@ -293,6 +295,8 @@ FUNCTION_PASS("print", DemandedBitsPrinterPass(dbgs())) FUNCTION_PASS("print", DominanceFrontierPrinterPass(dbgs())) FUNCTION_PASS("print", FunctionPropertiesPrinterPass(dbgs())) +FUNCTION_PASS("print", + DetailedFunctionPropertiesPrinterPass(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); } + DetailedFunctionPropertiesInfo buildDetailedFPI(Function &F) { + DT.reset(new DominatorTree(F)); + LI.reset(new LoopInfo(*DT)); + return DetailedFunctionPropertiesInfo::getDetailedFunctionPropertiesInfo( + 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); + + DetailedFunctionPropertiesInfo DetailedFeatures = + buildDetailedFPI(*BranchesFunction); + EXPECT_EQ(DetailedFeatures.getBasicBlockCount(), 4); + EXPECT_EQ(DetailedFeatures.getBasicBlockWithSingleSuccessor(), 2); + EXPECT_EQ(DetailedFeatures.getBasicBlockWithTwoSuccessors(), 1); + EXPECT_EQ(DetailedFeatures.getBasicBlockWithSinglePredecessor(), 2); + EXPECT_EQ(DetailedFeatures.getSmallBasicBlock(), 4); + EXPECT_EQ(DetailedFeatures.getIntegerInstCount(), 4); + EXPECT_EQ(DetailedFeatures.getIntegerConstantOccurrences(), 1); + EXPECT_EQ(DetailedFeatures.getRetInstCount(), 1); + EXPECT_EQ(DetailedFeatures.getBrInstCount(), 3); + EXPECT_EQ(DetailedFeatures.getICmpInstCount(), 1); + EXPECT_EQ(DetailedFeatures.getPHIInstCount(), 1); + EXPECT_EQ(DetailedFeatures.getCallInstCount(), 2); } } // end anonymous namespace \ No newline at end of file