Index: llvm/include/llvm/Analysis/ML/FunctionPropertiesAnalysis.h =================================================================== --- llvm/include/llvm/Analysis/ML/FunctionPropertiesAnalysis.h +++ llvm/include/llvm/Analysis/ML/FunctionPropertiesAnalysis.h @@ -14,6 +14,7 @@ #ifndef LLVM_FUNCTIONPROPERTIESANALYSIS_H_ #define LLVM_FUNCTIONPROPERTIESANALYSIS_H_ +#include "llvm/Analysis/LoopInfo.h" #include "llvm/IR/PassManager.h" namespace llvm { @@ -21,6 +22,11 @@ class FunctionPropertiesInfo { public: + static FunctionPropertiesInfo getFunctionPropertiesInfo(const Function &F, + const LoopInfo &LI); + + void print(raw_ostream &OS) const; + /// Number of basic blocks int64_t BasicBlockCount = 0; @@ -40,9 +46,17 @@ /// defined in this module. int64_t DirectCallsToDefinedFunctions = 0; - static FunctionPropertiesInfo getFunctionPropertiesInfo(const Function &F); + // Load Instruction Count + int64_t LoadInstCount = 0; - void print(raw_ostream &OS) const; + // 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; }; // Analysis pass Index: llvm/lib/Analysis/ML/FunctionPropertiesAnalysis.cpp =================================================================== --- llvm/lib/Analysis/ML/FunctionPropertiesAnalysis.cpp +++ llvm/lib/Analysis/ML/FunctionPropertiesAnalysis.cpp @@ -20,7 +20,8 @@ using namespace llvm; FunctionPropertiesInfo -FunctionPropertiesInfo::getFunctionPropertiesInfo(const Function &F) { +FunctionPropertiesInfo::getFunctionPropertiesInfo(const Function &F, + const LoopInfo &LI) { FunctionPropertiesInfo FPI; @@ -43,7 +44,20 @@ if (Callee && !Callee->isIntrinsic() && !Callee->isDeclaration()) ++FPI.DirectCallsToDefinedFunctions; } + if (I.getOpcode() == Instruction::Load) { + ++FPI.LoadInstCount; + } else if (I.getOpcode() == Instruction::Store) { + ++FPI.StoreInstCount; + } } + // Loop Depth of the Basic Block + int64_t LoopDepth; + LoopDepth = LI.getLoopDepth(&BB); + if (FPI.MaxLoopDepth < LoopDepth) + FPI.MaxLoopDepth = LoopDepth; + } + for (Loop *L : LI) { + ++FPI.TopLevelLoopCount; } return FPI; } @@ -54,14 +68,19 @@ << BlocksReachedFromConditionalInstruction << "\n" << "Uses: " << Uses << "\n" << "DirectCallsToDefinedFunctions: " << DirectCallsToDefinedFunctions - << "\n\n"; + << "\n" + << "LoadInstCount: " << LoadInstCount << "\n" + << "StoreInstCount: " << StoreInstCount << "\n" + << "MaxLoopDepth: " << MaxLoopDepth << "\n" + << "TopLevelLoopCount: " << TopLevelLoopCount << "\n\n"; } AnalysisKey FunctionPropertiesAnalysis::Key; FunctionPropertiesInfo FunctionPropertiesAnalysis::run(Function &F, FunctionAnalysisManager &FAM) { - return FunctionPropertiesInfo::getFunctionPropertiesInfo(F); + return FunctionPropertiesInfo::getFunctionPropertiesInfo( + F, FAM.getResult(F)); } PreservedAnalyses Index: llvm/test/Analysis/ML/FunctionPropertiesAnalysis/matmul.ll =================================================================== --- llvm/test/Analysis/ML/FunctionPropertiesAnalysis/matmul.ll +++ llvm/test/Analysis/ML/FunctionPropertiesAnalysis/matmul.ll @@ -21,6 +21,10 @@ ; CHECK-DAG: BlocksReachedFromConditionalInstruction: 0 ; CHECK-DAG: Uses: 1 ; CHECK-DAG: DirectCallsToDefinedFunctions: 1 +; CHECK-DAG: LoadInstCount: 0 +; CHECK-DAG: StoreInstCount: 1 +; CHECK-DAG: MaxLoopDepth: 0 +; CHECK-DAG: TopLevelLoopCount: 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': @@ -130,3 +134,7 @@ ; CHECK-DAG: BlocksReachedFromConditionalInstruction: 6 ; CHECK-DAG: Uses: 2 ; CHECK-DAG: DirectCallsToDefinedFunctions: 0 +; CHECK-DAG: LoadInstCount: 21 +; CHECK-DAG: StoreInstCount: 11 +; CHECK-DAG: MaxLoopDepth: 3 +; CHECK-DAG: TopLevelLoopCount: 1 Index: llvm/unittests/Analysis/ML/FunctionPropertiesAnalysisTest.cpp =================================================================== --- llvm/unittests/Analysis/ML/FunctionPropertiesAnalysisTest.cpp +++ llvm/unittests/Analysis/ML/FunctionPropertiesAnalysisTest.cpp @@ -8,6 +8,7 @@ #include "llvm/Analysis/ML/FunctionPropertiesAnalysis.h" #include "llvm/AsmParser/Parser.h" +#include "llvm/IR/Dominators.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" @@ -15,19 +16,32 @@ #include "gtest/gtest.h" using namespace llvm; +namespace { -static std::unique_ptr parseIR(LLVMContext &C, const char *IR) { - SMDiagnostic Err; - std::unique_ptr Mod = parseAssemblyString(IR, Err, C); - if (!Mod) - Err.print("MLAnalysisTests", errs()); - return Mod; -} +class FunctionPropertiesAnalysisTest : public testing::Test { +protected: + std::unique_ptr DT; + std::unique_ptr LI; + + FunctionPropertiesInfo buildFPI(Function &F) { + DT.reset(new DominatorTree(F)); + LI.reset(new LoopInfo(*DT)); + return FunctionPropertiesInfo::getFunctionPropertiesInfo(F, *LI); + } -TEST(FunctionPropertiesTest, BasicTest) { + std::unique_ptr makeLLVMModule(LLVMContext &C, const char *IR) { + SMDiagnostic Err; + std::unique_ptr Mod = parseAssemblyString(IR, Err, C); + if (!Mod) + Err.print("MLAnalysisTests", errs()); + return Mod; + } +}; + +TEST_F(FunctionPropertiesAnalysisTest, BasicTest) { LLVMContext C; - std::unique_ptr M = parseIR(C, - R"IR( + std::unique_ptr M = makeLLVMModule(C, + R"IR( target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-pc-linux-gnu" declare i32 @f1(i32) @@ -52,20 +66,28 @@ } )IR"); - FunctionAnalysisManager FAM; - FunctionPropertiesAnalysis FPA; - - auto BranchesFeatures = FPA.run(*M->getFunction("branches"), FAM); + Function *BranchesFunction = M->getFunction("branches"); + FunctionPropertiesInfo BranchesFeatures = buildFPI(*BranchesFunction); EXPECT_EQ(BranchesFeatures.BasicBlockCount, 4); EXPECT_EQ(BranchesFeatures.BlocksReachedFromConditionalInstruction, 2); - EXPECT_EQ(BranchesFeatures.DirectCallsToDefinedFunctions, 0); // 2 Users: top is one. The other is added because @branches is not internal, // so it may have external callers. EXPECT_EQ(BranchesFeatures.Uses, 2); + EXPECT_EQ(BranchesFeatures.DirectCallsToDefinedFunctions, 0); + EXPECT_EQ(BranchesFeatures.LoadInstCount, 0); + EXPECT_EQ(BranchesFeatures.StoreInstCount, 0); + EXPECT_EQ(BranchesFeatures.MaxLoopDepth, 0); + EXPECT_EQ(BranchesFeatures.TopLevelLoopCount, 0); - auto TopFeatures = FPA.run(*M->getFunction("top"), FAM); + Function *TopFunction = M->getFunction("top"); + FunctionPropertiesInfo TopFeatures = buildFPI(*TopFunction); EXPECT_EQ(TopFeatures.BasicBlockCount, 1); EXPECT_EQ(TopFeatures.BlocksReachedFromConditionalInstruction, 0); - EXPECT_EQ(TopFeatures.DirectCallsToDefinedFunctions, 1); EXPECT_EQ(TopFeatures.Uses, 0); + EXPECT_EQ(TopFeatures.DirectCallsToDefinedFunctions, 1); + EXPECT_EQ(BranchesFeatures.LoadInstCount, 0); + EXPECT_EQ(BranchesFeatures.StoreInstCount, 0); + EXPECT_EQ(BranchesFeatures.MaxLoopDepth, 0); + EXPECT_EQ(BranchesFeatures.TopLevelLoopCount, 0); } +} // end anonymous namespace