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 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 @@ -16,10 +16,11 @@ #include "llvm/Passes/PassBuilder.h" #include "llvm/Passes/PassPlugin.h" #include "llvm/Support/raw_ostream.h" +#include 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(); @@ -40,7 +41,20 @@ 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 + int64_t LoopDepth; + LoopDepth = LI.getLoopDepth(&BB); + if (MaxLoopDepth < LoopDepth) + MaxLoopDepth = LoopDepth; + } + for (Loop *L : LI) { + ++TopLevelLoopCount; } } @@ -50,7 +64,18 @@ << BlocksReachedFromConditionalInstruction << "\n" << "Uses: " << Uses << "\n" << "DirectCallsToDefinedFunctions: " << DirectCallsToDefinedFunctions - << "\n\n"; + << "\n" + << "LoadInstCount: " << LoadInstCount << "\n" + << "StoreInstCount: " << StoreInstCount << "\n" + << "MaxLoopDepth: " << MaxLoopDepth << "\n" + << "TopLevelLoopCount: " << TopLevelLoopCount << "\n\n"; +} + +FunctionPropertiesInfo::FunctionPropertiesInfo() = default; + +FunctionPropertiesInfo::FunctionPropertiesInfo(const Function &F, + const LoopInfo &LI) { + analyze(F, LI); } AnalysisKey FunctionPropertiesAnalysis::Key; @@ -58,7 +83,7 @@ FunctionPropertiesInfo FunctionPropertiesAnalysis::run(Function &F, FunctionAnalysisManager &FAM) { FunctionPropertiesInfo FPI; - FPI.analyze(F); + FPI.analyze(F, FAM.getResult(F)); return FPI; } 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,26 +8,41 @@ #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" #include "llvm/Support/SourceMgr.h" #include "gtest/gtest.h" +#include 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); + } -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 +67,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