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,6 +81,37 @@ // 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 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,6 +77,52 @@ } } 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 = pred_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.instructionsWithoutDebug()) { + 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 += Direction; + else if (C->getType()->isFloatTy()) + FloatingPointConstantCount += Direction; + } + } + } + } } void FunctionPropertiesInfo::updateAggregateStats(const Function &F, @@ -109,7 +170,31 @@ << "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; @@ -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/test/Analysis/FunctionPropertiesAnalysis/matmul.ll b/llvm/test/Analysis/FunctionPropertiesAnalysis/matmul.ll --- a/llvm/test/Analysis/FunctionPropertiesAnalysis/matmul.ll +++ b/llvm/test/Analysis/FunctionPropertiesAnalysis/matmul.ll @@ -1,7 +1,9 @@ ; RUN: opt < %s -passes='print' -disable-output 2>&1 | FileCheck %s +; RUN: opt < %s -passes='print' -disable-output 2>&1 -enable-detailed-function-properties | FileCheck %s --check-prefix=DETAILED-PROPERTIES define i32 @main() { ; CHECK-DAG: Printing analysis results of CFA for function 'main': +; DETAILED-PROPERTIES-DAG: Printing analysis results of CFA for function 'main': entry: %retval = alloca i32, align 4 @@ -26,8 +28,32 @@ ; CHECK-DAG: MaxLoopDepth: 0 ; CHECK-DAG: TopLevelLoopCount: 0 +; DETAILED-PROPERTIES-DAG: BasicBlockCount: 1 +; DETAILED-PROPERTIES-DAG: BlocksReachedFromConditionalInstruction: 0 +; DETAILED-PROPERTIES-DAG: Uses: 1 +; DETAILED-PROPERTIES-DAG: DirectCallsToDefinedFunctions: 1 +; DETAILED-PROPERTIES-DAG: LoadInstCount: 0 +; DETAILED-PROPERTIES-DAG: StoreInstCount: 1 +; DETAILED-PROPERTIES-DAG: MaxLoopDepth: 0 +; DETAILED-PROPERTIES-DAG: TopLevelLoopCount: 0 +; DETAILED-PROPERTIES-DAG: BasicBlocksWithSingleSuccessor: 0 +; DETAILED-PROPERTIES-DAG: BasicBlocksWithTwoSuccessors: 0 +; DETAILED-PROPERTIES-DAG: BasicBlocksWithMoreThanTwoSuccessors: 0 +; DETAILED-PROPERTIES-DAG: BasicBlocksWithSinglePredecessor: 0 +; DETAILED-PROPERTIES-DAG: BasicBlocksWithTwoPredecessors: 0 +; DETAILED-PROPERTIES-DAG: BasicBlocksWithMoreThanTwoPredecessors: 0 +; DETAILED-PROPERTIES-DAG: BigBasicBlocks: 0 +; DETAILED-PROPERTIES-DAG: MediumBasicBlocks: 0 +; DETAILED-PROPERTIES-DAG: SmallBasicBlocks: 1 +; DETAILED-PROPERTIES-DAG: CastInstructionCount: 0 +; DETAILED-PROPERTIES-DAG: FloatingPointInstructionCount: 0 +; DETAILED-PROPERTIES-DAG: IntegerInstructionCount: 0 +; DETAILED-PROPERTIES-DAG: IntegerConstantCount: 14 +; DETAILED-PROPERTIES-DAG: FloatingPointConstantCount: 0 + define void @multiply([2 x i32]* %mat1, [2 x i32]* %mat2, [2 x i32]* %res) { ; CHECK-DAG: Printing analysis results of CFA for function 'multiply': +; DETAILED-PROPERTIES-DAG: Printing analysis results of CFA for function 'multiply': entry: %mat1.addr = alloca [2 x i32]*, align 8 %mat2.addr = alloca [2 x i32]*, align 8 @@ -137,4 +163,27 @@ ; CHECK-DAG: LoadInstCount: 21 ; CHECK-DAG: StoreInstCount: 11 ; CHECK-DAG: MaxLoopDepth: 3 -; CHECK-DAG: TopLevelLoopCount: 1 \ No newline at end of file +; CHECK-DAG: TopLevelLoopCount: 1 + +; DETAILED-PROPERTIES-DAG: BasicBlockCount: 13 +; DETAILED-PROPERTIES-DAG: BlocksReachedFromConditionalInstruction: 6 +; DETAILED-PROPERTIES-DAG: Uses: 2 +; DETAILED-PROPERTIES-DAG: DirectCallsToDefinedFunctions: 0 +; DETAILED-PROPERTIES-DAG: LoadInstCount: 21 +; DETAILED-PROPERTIES-DAG: StoreInstCount: 11 +; DETAILED-PROPERTIES-DAG: MaxLoopDepth: 3 +; DETAILED-PROPERTIES-DAG: TopLevelLoopCount: 1 +; DETAILED-PROPERTIES-DAG: BasicBlocksWithSingleSuccessor: 9 +; DETAILED-PROPERTIES-DAG: BasicBlocksWithTwoSuccessors: 3 +; DETAILED-PROPERTIES-DAG: BasicBlocksWithMoreThanTwoSuccessors: 0 +; DETAILED-PROPERTIES-DAG: BasicBlocksWithSinglePredecessor: 9 +; DETAILED-PROPERTIES-DAG: BasicBlocksWithTwoPredecessors: 3 +; DETAILED-PROPERTIES-DAG: BasicBlocksWithMoreThanTwoPredecessors: 0 +; DETAILED-PROPERTIES-DAG: BigBasicBlocks: 0 +; DETAILED-PROPERTIES-DAG: MediumBasicBlocks: 11 +; DETAILED-PROPERTIES-DAG: SmallBasicBlocks: 2 +; DETAILED-PROPERTIES-DAG: CastInstructionCount: 8 +; DETAILED-PROPERTIES-DAG: FloatingPointInstructionCount: 0 +; DETAILED-PROPERTIES-DAG: IntegerInstructionCount: 33 +; DETAILED-PROPERTIES-DAG: IntegerConstantCount: 20 +; DETAILED-PROPERTIES-DAG: FloatingPointConstantCount: 0 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,6 +24,11 @@ #include using namespace llvm; + +extern cl::opt EnableDetailedFunctionProperties; +extern cl::opt BigBasicBlockInstructionThreshold; +extern cl::opt MediumBasicBlockInstrutionThreshold; + namespace { class FunctionPropertiesAnalysisTest : public testing::Test { @@ -117,6 +122,57 @@ 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.BigBasicBlocks, 0); + EXPECT_EQ(DetailedBranchesFeatures.MediumBasicBlocks, 0); + EXPECT_EQ(DetailedBranchesFeatures.SmallBasicBlocks, 4); + 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); + EnableDetailedFunctionProperties.setValue(false); +} + +TEST_F(FunctionPropertiesAnalysisTest, DifferentPredecessorSuccessorCounts) { + LLVMContext C; + std::unique_ptr M = makeLLVMModule(C, + R"IR( +define i64 @f1() { + br i1 0, label %br1, label %finally +br1: + ret i64 0 +finally: + ret i64 3 +} +)IR"); + + Function *F1 = M->getFunction("f1"); + EnableDetailedFunctionProperties.setValue(true); + FunctionPropertiesInfo DetailedF1Properties = buildFPI(*F1); + EXPECT_EQ(DetailedF1Properties.BasicBlocksWithSingleSuccessor, 0); + EXPECT_EQ(DetailedF1Properties.BasicBlocksWithTwoSuccessors, 1); + EXPECT_EQ(DetailedF1Properties.BasicBlocksWithMoreThanTwoSuccessors, 0); + EXPECT_EQ(DetailedF1Properties.BasicBlocksWithSinglePredecessor, 2); + EXPECT_EQ(DetailedF1Properties.BasicBlocksWithTwoPredecessors, 0); + EXPECT_EQ(DetailedF1Properties.BasicBlocksWithMoreThanTwoPredecessors, 0); + EXPECT_EQ(DetailedF1Properties.BigBasicBlocks, 0); + EXPECT_EQ(DetailedF1Properties.MediumBasicBlocks, 0); + EXPECT_EQ(DetailedF1Properties.SmallBasicBlocks, 3); + EXPECT_EQ(DetailedF1Properties.CastInstructionCount, 0); + EXPECT_EQ(DetailedF1Properties.FloatingPointInstructionCount, 0); + EXPECT_EQ(DetailedF1Properties.IntegerInstructionCount, 0); + EXPECT_EQ(DetailedF1Properties.IntegerConstantCount, 3); + EXPECT_EQ(DetailedF1Properties.FloatingPointConstantCount, 0); + EnableDetailedFunctionProperties.setValue(false); } TEST_F(FunctionPropertiesAnalysisTest, InlineSameBBSimple) {