diff --git a/llvm/include/llvm/Analysis/FunctionPropertiesAnalysis.h b/llvm/include/llvm/Analysis/FunctionPropertiesAnalysis.h --- a/llvm/include/llvm/Analysis/FunctionPropertiesAnalysis.h +++ b/llvm/include/llvm/Analysis/FunctionPropertiesAnalysis.h @@ -81,31 +81,62 @@ // All non-debug instructions int64_t TotalInstructionCount = 0; + + // Basic blocks grouped by number of successors. + int64_t BasicBlocksWithSingleSuccessor = 0; + int64_t BasicBlocksWithTwoSuccessors = 0; + int64_t BasicBlocksWithMoreThanTwoSuccessors = 0; + + // Basic blocks grouped by number of predecessors. + int64_t BasicBlocksWithSinglePredecessor = 0; + int64_t BasicBlocksWithTwoPredecessors = 0; + int64_t BasicBlocksWithMoreThanTwoPredecessors = 0; + + // Basic blocks grouped by size as determined by the number of non-debug + // instructions that they contain. + int64_t BigBasicBlocks = 0; + int64_t MediumBasicBlocks = 0; + int64_t SmallBasicBlocks = 0; + + // The number of cast instructions inside the function. + int64_t CastInstructionCount = 0; + + // The number of floating point instructions inside the function. + int64_t FloatingPointInstructionCount = 0; + + // The number of integer instructions inside the function. + int64_t IntegerInstructionCount = 0; + + // The number of integer constant operands inside the function. + int64_t IntegerConstantCount = 0; + + // The number of floating point constant operands inside the function. + int64_t FloatingPointConstantCount = 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 diff --git a/llvm/lib/Analysis/FunctionPropertiesAnalysis.cpp b/llvm/lib/Analysis/FunctionPropertiesAnalysis.cpp --- a/llvm/lib/Analysis/FunctionPropertiesAnalysis.cpp +++ b/llvm/lib/Analysis/FunctionPropertiesAnalysis.cpp @@ -18,10 +18,25 @@ #include "llvm/IR/CFG.h" #include "llvm/IR/Dominators.h" #include "llvm/IR/Instructions.h" +#include "llvm/Support/CommandLine.h" #include using namespace llvm; +cl::opt EnableDetailedFunctionProperties( + "enable-detailed-function-properties", cl::Hidden, cl::init(false), + cl::desc("Whether or not to compute detailed function properties.")); + +cl::opt BigBasicBlockInstructionThreshold( + "big-basic-block-instruction-threshold", cl::Hidden, cl::init(500), + cl::desc("The minimum number of instructions a basic block should contain " + "before being considered big.")); + +cl::opt MediumBasicBlockInstructionThreshold( + "medium-basic-block-instruction-threshold", cl::Hidden, cl::init(15), + cl::desc("The minimum number of instructions a basic block should contain " + "before being considered medium-sized.")); + namespace { int64_t getNrBlocksFromCond(const BasicBlock &BB) { int64_t Ret = 0; @@ -62,11 +77,57 @@ } } TotalInstructionCount += Direction * BB.sizeWithoutDebug(); + + if (EnableDetailedFunctionProperties) { + unsigned SuccessorCount = succ_size(&BB); + if (SuccessorCount == 1) + BasicBlocksWithSingleSuccessor += Direction; + else if (SuccessorCount == 2) + BasicBlocksWithTwoSuccessors += Direction; + else if (SuccessorCount > 2) + BasicBlocksWithMoreThanTwoSuccessors += Direction; + + unsigned PredecessorCount = succ_size(&BB); + if (PredecessorCount == 1) + BasicBlocksWithSinglePredecessor += Direction; + else if (PredecessorCount == 2) + BasicBlocksWithTwoPredecessors += Direction; + else if (PredecessorCount > 2) + BasicBlocksWithMoreThanTwoPredecessors += Direction; + + if (TotalInstructionCount > BigBasicBlockInstructionThreshold) + BigBasicBlocks += Direction; + else if (TotalInstructionCount > MediumBasicBlockInstructionThreshold) + MediumBasicBlocks += Direction; + else + SmallBasicBlocks += Direction; + + for (const Instruction &I : BB) { + if (I.isCast()) + CastInstructionCount += Direction; + + if (I.getType()->isFloatTy()) + FloatingPointInstructionCount += Direction; + else if (I.getType()->isIntegerTy()) + IntegerInstructionCount += Direction; + + for (unsigned int OperandIndex = 0; OperandIndex < I.getNumOperands(); + ++OperandIndex) { + if (const Constant *C = + dyn_cast(I.getOperand(OperandIndex))) { + if (C->getType()->isIntegerTy()) + IntegerConstantCount += 1; + else if (C->getType()->isFloatTy()) + FloatingPointConstantCount += 1; + } + } + } + } } void FunctionPropertiesInfo::updateAggregateStats(const Function &F, const LoopInfo &LI) { Uses = getUses(F); TopLevelLoopCount = llvm::size(LI); MaxLoopDepth = 0; @@ -109,16 +170,40 @@ << "StoreInstCount: " << StoreInstCount << "\n" << "MaxLoopDepth: " << MaxLoopDepth << "\n" << "TopLevelLoopCount: " << TopLevelLoopCount << "\n" - << "TotalInstructionCount: " << TotalInstructionCount << "\n\n"; + << "TotalInstructionCount: " << TotalInstructionCount << "\n"; + if (EnableDetailedFunctionProperties) { + OS << "BasicBlocksWithSingleSuccessor: " << BasicBlocksWithSingleSuccessor + << "\n" + << "BasicBlocksWithTwoSuccessors: " << BasicBlocksWithTwoSuccessors + << "\n" + << "BasicBlocksWithMoreThanTwoSuccessors: " + << BasicBlocksWithMoreThanTwoSuccessors << "\n" + << "BasicBlocksWithSinglePredecessor: " + << BasicBlocksWithSinglePredecessor << "\n" + << "BasicBlocksWithTwoPredecessors: " << BasicBlocksWithTwoPredecessors + << "\n" + << "BasicBlocksWithMoreThanTwoPredecessors: " + << BasicBlocksWithMoreThanTwoPredecessors << "\n" + << "BigBasicBlocks: " << BigBasicBlocks << "\n" + << "MediumBasicBlocks: " << MediumBasicBlocks << "\n" + << "SmallBasicBlocks: " << SmallBasicBlocks << "\n" + << "CastInstructionCount: " << CastInstructionCount << "\n" + << "FloatingPointInstructionCount: " << FloatingPointInstructionCount + << "\n" + << "IntegerInstructionCount: " << IntegerInstructionCount << "\n" + << "IntegerConstantCount: " << IntegerConstantCount << "\n" + << "FloatingPointConstantCount: " << FloatingPointConstantCount << "\n"; + } + OS << "\n"; } AnalysisKey FunctionPropertiesAnalysis::Key; FunctionPropertiesInfo FunctionPropertiesAnalysis::run(Function &F, FunctionAnalysisManager &FAM) { return FunctionPropertiesInfo::getFunctionPropertiesInfo(F, FAM); } PreservedAnalyses FunctionPropertiesPrinterPass::run(Function &F, FunctionAnalysisManager &AM) { OS << "Printing analysis results of CFA for function " @@ -258,4 +343,4 @@ LoopInfo LI(DT); auto Fresh = FunctionPropertiesInfo::getFunctionPropertiesInfo(F, DT, LI); return FPI == Fresh; -} \ No newline at end of file +} diff --git a/llvm/unittests/Analysis/FunctionPropertiesAnalysisTest.cpp b/llvm/unittests/Analysis/FunctionPropertiesAnalysisTest.cpp --- a/llvm/unittests/Analysis/FunctionPropertiesAnalysisTest.cpp +++ b/llvm/unittests/Analysis/FunctionPropertiesAnalysisTest.cpp @@ -24,8 +24,13 @@ #include using namespace llvm; + +extern cl::opt EnableDetailedFunctionProperties; +extern cl::opt BigBasicBlockInstructionThreshold; +extern cl::opt MediumBasicBlockInstrutionThreshold; + namespace { class FunctionPropertiesAnalysisTest : public testing::Test { public: FunctionPropertiesAnalysisTest() { @@ -117,8 +122,22 @@ EXPECT_EQ(BranchesFeatures.StoreInstCount, 0); EXPECT_EQ(BranchesFeatures.MaxLoopDepth, 0); EXPECT_EQ(BranchesFeatures.TopLevelLoopCount, 0); + + EnableDetailedFunctionProperties.setValue(true); + FunctionPropertiesInfo DetailedBranchesFeatures = buildFPI(*BranchesFunction); + EXPECT_EQ(DetailedBranchesFeatures.BasicBlocksWithSingleSuccessor, 2); + EXPECT_EQ(DetailedBranchesFeatures.BasicBlocksWithTwoSuccessors, 1); + EXPECT_EQ(DetailedBranchesFeatures.BasicBlocksWithMoreThanTwoSuccessors, 0); + EXPECT_EQ(DetailedBranchesFeatures.BasicBlocksWithSinglePredecessor, 2); + EXPECT_EQ(DetailedBranchesFeatures.BasicBlocksWithTwoPredecessors, 1); + EXPECT_EQ(DetailedBranchesFeatures.BasicBlocksWithMoreThanTwoPredecessors, 0); + EXPECT_EQ(DetailedBranchesFeatures.CastInstructionCount, 0); + EXPECT_EQ(DetailedBranchesFeatures.FloatingPointInstructionCount, 0); + EXPECT_EQ(DetailedBranchesFeatures.IntegerInstructionCount, 4); + EXPECT_EQ(DetailedBranchesFeatures.IntegerConstantCount, 1); + EXPECT_EQ(DetailedBranchesFeatures.FloatingPointConstantCount, 0); } TEST_F(FunctionPropertiesAnalysisTest, InlineSameBBSimple) { LLVMContext C; std::unique_ptr M = makeLLVMModule(C,