Index: llvm/include/llvm/Analysis/ML/FunctionPropertiesAnalysis.h =================================================================== --- llvm/include/llvm/Analysis/ML/FunctionPropertiesAnalysis.h +++ llvm/include/llvm/Analysis/ML/FunctionPropertiesAnalysis.h @@ -21,6 +21,13 @@ class FunctionPropertiesInfo{ public: + FunctionPropertiesInfo(); + FunctionPropertiesInfo(const Function &F, const LoopInfo &LI); + + void analyze(const Function &F, const LoopInfo &LI); + + void print(raw_ostream &OS) const; + /// Number of basic blocks int64_t BasicBlockCount = 0; @@ -40,9 +47,17 @@ /// defined in this module. int64_t DirectCallsToDefinedFunctions = 0; - void analyze(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 Loops in the Function + int64_t LoopCount = 0; }; //Analysis pass Index: llvm/lib/Analysis/ML/FunctionPropertiesAnalysis.cpp =================================================================== --- llvm/lib/Analysis/ML/FunctionPropertiesAnalysis.cpp +++ llvm/lib/Analysis/ML/FunctionPropertiesAnalysis.cpp @@ -11,6 +11,7 @@ // //===----------------------------------------------------------------------===// +#include #include "llvm/Analysis/ML/FunctionPropertiesAnalysis.h" #include "llvm/IR/Instructions.h" #include "llvm/Passes/PassBuilder.h" @@ -19,9 +20,11 @@ using namespace llvm; -void FunctionPropertiesInfo::analyze(const Function &F) { +void FunctionPropertiesInfo::analyze(const Function &F, + const LoopInfo &LI) { Uses = ((!F.hasLocalLinkage()) ? 1 : 0) + F.getNumUses(); + int64_t LoopDepth; for (const auto &BB : F) { ++BasicBlockCount; @@ -40,7 +43,19 @@ if (Callee && !Callee->isIntrinsic() && !Callee->isDeclaration()) ++DirectCallsToDefinedFunctions; } + if (I.getOpcode() == Instruction::Load) { + ++LoadInstCount; + }else if (I.getOpcode() == Instruction::Store) { + ++StoreInstCount; + } } + //Loop Depth of the Basic Block + LoopDepth = LI.getLoopDepth(&BB); + if (MaxLoopDepth < LoopDepth) + MaxLoopDepth = LoopDepth; + } + for( LoopInfo::iterator li = LI.begin(), le=LI.end(); li != le; ++li) { + ++LoopCount; } } @@ -48,18 +63,28 @@ OS << "BasicBlockCount: " << BasicBlockCount << "\n" << "BlocksReachedFromConditionalInstruction: " << BlocksReachedFromConditionalInstruction << "\n" << "Uses: " << Uses << "\n" - << "DirectCallsToDefinedFunctions: " << DirectCallsToDefinedFunctions << "\n\n"; + << "DirectCallsToDefinedFunctions: " << DirectCallsToDefinedFunctions << "\n" + << "LoadInstCount: " << LoadInstCount << "\n" + << "StoreInstCount: " << StoreInstCount << "\n" + << "MaxLoopDepth: " << MaxLoopDepth << "\n" + << "LoopCount: " << LoopCount << "\n\n"; +} + +FunctionPropertiesInfo::FunctionPropertiesInfo() = default; + +FunctionPropertiesInfo::FunctionPropertiesInfo(const Function &F, + const LoopInfo &LI) { + analyze(F, LI); } AnalysisKey FunctionPropertiesAnalysis::Key; FunctionPropertiesInfo FunctionPropertiesAnalysis::run(Function &F, FunctionAnalysisManager &FAM) { FunctionPropertiesInfo FPI; - FPI.analyze(F); + FPI.analyze(F, FAM.getResult(F)); return FPI; } - PreservedAnalyses FunctionPropertiesPrinterPass::run(Function &F, FunctionAnalysisManager &AM) { OS << "Printing analysis results of CFA for function " << "'" << F.getName() << "':" @@ -67,3 +92,4 @@ AM.getResult(F).print(OS); return PreservedAnalyses::all(); } + 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: LoopCount: 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': @@ -129,4 +133,8 @@ ; CHECK-DAG: BasicBlockCount: 13 ; CHECK-DAG: BlocksReachedFromConditionalInstruction: 6 ; CHECK-DAG: Uses: 2 -; CHECK-DAG: DirectCallsToDefinedFunctions: 0 \ No newline at end of file +; CHECK-DAG: DirectCallsToDefinedFunctions: 0 +; CHECK-DAG: LoadInstCount: 21 +; CHECK-DAG: StoreInstCount: 11 +; CHECK-DAG: MaxLoopDepth: 3 +; CHECK-DAG: LoopCount: 1 Index: llvm/unittests/Analysis/ML/FunctionPropertiesAnalysisTest.cpp =================================================================== --- llvm/unittests/Analysis/ML/FunctionPropertiesAnalysisTest.cpp +++ llvm/unittests/Analysis/ML/FunctionPropertiesAnalysisTest.cpp @@ -6,8 +6,10 @@ // //===----------------------------------------------------------------------===// +#include #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,18 +17,31 @@ #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(F, *LI); + } + + 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(FunctionPropertiesTest, BasicTest) { +TEST_F(FunctionPropertiesAnalysisTest, BasicTest) { LLVMContext C; - std::unique_ptr M = parseIR(C, + 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" @@ -58,20 +73,29 @@ } )IR"); - FunctionAnalysisManager FAM; - FunctionPropertiesAnalysis FA; - - auto BranchesFeatures = FA.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, + // 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.LoopCount, 0); - auto TopFeatures = FA.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.LoopCount, 0); } + +} // end anonymous namespace \ No newline at end of file