[llvm] 98ef93e - [llvm] Add function feature extraction analysis
Mircea Trofin via llvm-commits
llvm-commits at lists.llvm.org
Wed May 27 13:39:20 PDT 2020
Author: Mircea Trofin
Date: 2020-05-27T13:38:50-07:00
New Revision: 98ef93eabd768e51aa58c7623a9fe220ab471715
URL: https://github.com/llvm/llvm-project/commit/98ef93eabd768e51aa58c7623a9fe220ab471715
DIFF: https://github.com/llvm/llvm-project/commit/98ef93eabd768e51aa58c7623a9fe220ab471715.diff
LOG: [llvm] Add function feature extraction analysis
Summary:
This patch introduces an analysis pass to extract function features,
which will be needed by the ML InlineAdvisor.
RFC: http://lists.llvm.org/pipermail/llvm-dev/2020-April/140763.html
Reviewers: davidxl, dblaikie, jdoerfert
Subscribers: mgorny, hiraditya, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D80579
Added:
llvm/include/llvm/Analysis/ML/InlineFeaturesAnalysis.h
llvm/lib/Analysis/ML/CMakeLists.txt
llvm/lib/Analysis/ML/InlineFeaturesAnalysis.cpp
llvm/unittests/Analysis/ML/CMakeLists.txt
llvm/unittests/Analysis/ML/InlineFeaturesAnalysisTest.cpp
Modified:
llvm/lib/Analysis/CMakeLists.txt
llvm/lib/Passes/PassBuilder.cpp
llvm/lib/Passes/PassRegistry.def
llvm/unittests/Analysis/CMakeLists.txt
Removed:
################################################################################
diff --git a/llvm/include/llvm/Analysis/ML/InlineFeaturesAnalysis.h b/llvm/include/llvm/Analysis/ML/InlineFeaturesAnalysis.h
new file mode 100644
index 000000000000..694cae34bc75
--- /dev/null
+++ b/llvm/include/llvm/Analysis/ML/InlineFeaturesAnalysis.h
@@ -0,0 +1,37 @@
+#ifndef LLVM_INLINEFEATURESANALYSIS_H_
+#define LLVM_INLINEFEATURESANALYSIS_H_
+
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+class Function;
+
+class InlineFeaturesAnalysis
+ : public AnalysisInfoMixin<InlineFeaturesAnalysis> {
+public:
+ static AnalysisKey Key;
+ struct Result {
+ /// Number of basic blocks
+ int64_t BasicBlockCount = 0;
+
+ /// Number of blocks reached from a conditional instruction, or that are
+ /// 'cases' of a SwitchInstr.
+ // FIXME: We may want to replace this with a more meaningful metric, like
+ // number of conditionally executed blocks:
+ // 'if (a) s();' would be counted here as 2 blocks, just like
+ // 'if (a) s(); else s2(); s3();' would.
+ int64_t BlocksReachedFromConditionalInstruction = 0;
+
+ /// Number of uses of this function, plus 1 if the function is callable
+ /// outside the module.
+ int64_t Uses = 0;
+
+ /// Number of direct calls made from this function to other functions
+ /// defined in this module.
+ int64_t DirectCallsToDefinedFunctions = 0;
+ };
+ Result run(const Function &F, FunctionAnalysisManager &FAM);
+};
+
+} // namespace llvm
+#endif // LLVM_INLINEFEATURESANALYSIS_H_
\ No newline at end of file
diff --git a/llvm/lib/Analysis/CMakeLists.txt b/llvm/lib/Analysis/CMakeLists.txt
index 7ae053f59d1a..8fa832faec4c 100644
--- a/llvm/lib/Analysis/CMakeLists.txt
+++ b/llvm/lib/Analysis/CMakeLists.txt
@@ -1,3 +1,5 @@
+add_subdirectory(ML)
+
add_llvm_component_library(LLVMAnalysis
AliasAnalysis.cpp
AliasAnalysisEvaluator.cpp
@@ -106,4 +108,9 @@ add_llvm_component_library(LLVMAnalysis
DEPENDS
intrinsics_gen
+ LLVMMLPolicies
+
+
+ LINK_LIBS
+ LLVMMLPolicies
)
diff --git a/llvm/lib/Analysis/ML/CMakeLists.txt b/llvm/lib/Analysis/ML/CMakeLists.txt
new file mode 100644
index 000000000000..05039a95ba73
--- /dev/null
+++ b/llvm/lib/Analysis/ML/CMakeLists.txt
@@ -0,0 +1,9 @@
+set (SOURCES InlineFeaturesAnalysis.cpp)
+
+add_llvm_library(LLVMMLPolicies STATIC
+ ${SOURCES}
+
+ DEPENDS
+ intrinsics_gen
+
+ )
diff --git a/llvm/lib/Analysis/ML/InlineFeaturesAnalysis.cpp b/llvm/lib/Analysis/ML/InlineFeaturesAnalysis.cpp
new file mode 100644
index 000000000000..d81e9b3aaf62
--- /dev/null
+++ b/llvm/lib/Analysis/ML/InlineFeaturesAnalysis.cpp
@@ -0,0 +1,28 @@
+#include "llvm/Analysis/ML/InlineFeaturesAnalysis.h"
+#include "llvm/IR/Instructions.h"
+
+using namespace llvm;
+
+AnalysisKey InlineFeaturesAnalysis::Key;
+
+InlineFeaturesAnalysis::Result
+InlineFeaturesAnalysis::run(const Function &F, FunctionAnalysisManager &FAM) {
+ Result Ret;
+ Ret.Uses = ((!F.hasLocalLinkage()) ? 1 : 0) + F.getNumUses();
+ for (const auto &BB : F) {
+ ++Ret.BasicBlockCount;
+ if (const auto *BI = dyn_cast<BranchInst>(BB.getTerminator())) {
+ if (BI->isConditional())
+ Ret.BlocksReachedFromConditionalInstruction += BI->getNumSuccessors();
+ } else if (const auto *SI = dyn_cast<SwitchInst>(BB.getTerminator()))
+ Ret.BlocksReachedFromConditionalInstruction +=
+ (SI->getNumCases() + (nullptr != SI->getDefaultDest()));
+ for (const auto &I : BB)
+ if (auto *CS = dyn_cast<CallBase>(&I)) {
+ const auto *Callee = CS->getCalledFunction();
+ if (Callee && !Callee->isIntrinsic() && !Callee->isDeclaration())
+ ++Ret.DirectCallsToDefinedFunctions;
+ }
+ }
+ return Ret;
+}
\ No newline at end of file
diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp
index 014ef836e2c3..0999f7872d12 100644
--- a/llvm/lib/Passes/PassBuilder.cpp
+++ b/llvm/lib/Passes/PassBuilder.cpp
@@ -40,6 +40,7 @@
#include "llvm/Analysis/LoopCacheAnalysis.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/LoopNestAnalysis.h"
+#include "llvm/Analysis/ML/InlineFeaturesAnalysis.h"
#include "llvm/Analysis/MemoryDependenceAnalysis.h"
#include "llvm/Analysis/MemorySSA.h"
#include "llvm/Analysis/ModuleSummaryAnalysis.h"
diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def
index 03c4379f2468..dd75a418925b 100644
--- a/llvm/lib/Passes/PassRegistry.def
+++ b/llvm/lib/Passes/PassRegistry.def
@@ -134,6 +134,7 @@ FUNCTION_ANALYSIS("domfrontier", DominanceFrontierAnalysis())
FUNCTION_ANALYSIS("loops", LoopAnalysis())
FUNCTION_ANALYSIS("lazy-value-info", LazyValueAnalysis())
FUNCTION_ANALYSIS("da", DependenceAnalysis())
+FUNCTION_ANALYSIS("inliner-features", InlineFeaturesAnalysis())
FUNCTION_ANALYSIS("memdep", MemoryDependenceAnalysis())
FUNCTION_ANALYSIS("memoryssa", MemorySSAAnalysis())
FUNCTION_ANALYSIS("phi-values", PhiValuesAnalysis())
diff --git a/llvm/unittests/Analysis/CMakeLists.txt b/llvm/unittests/Analysis/CMakeLists.txt
index f344d6c7bc25..6cc14d124b15 100644
--- a/llvm/unittests/Analysis/CMakeLists.txt
+++ b/llvm/unittests/Analysis/CMakeLists.txt
@@ -41,3 +41,5 @@ add_llvm_unittest(AnalysisTests
ValueTrackingTest.cpp
VectorUtilsTest.cpp
)
+
+add_subdirectory(ML)
\ No newline at end of file
diff --git a/llvm/unittests/Analysis/ML/CMakeLists.txt b/llvm/unittests/Analysis/ML/CMakeLists.txt
new file mode 100644
index 000000000000..8d1c90312ad0
--- /dev/null
+++ b/llvm/unittests/Analysis/ML/CMakeLists.txt
@@ -0,0 +1,12 @@
+set(LLVM_LINK_COMPONENTS
+ Analysis
+ AsmParser
+ Core
+ MLPolicies
+ Support
+ TransformUtils
+ )
+
+add_llvm_unittest(MLAnalysisTests
+ InlineFeaturesAnalysisTest.cpp
+ )
diff --git a/llvm/unittests/Analysis/ML/InlineFeaturesAnalysisTest.cpp b/llvm/unittests/Analysis/ML/InlineFeaturesAnalysisTest.cpp
new file mode 100644
index 000000000000..4dfc0bd153f7
--- /dev/null
+++ b/llvm/unittests/Analysis/ML/InlineFeaturesAnalysisTest.cpp
@@ -0,0 +1,77 @@
+//===- InlineFeaturesAnalysisTest.cpp - inline features unit tests --------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Analysis/ML/InlineFeaturesAnalysis.h"
+#include "llvm/AsmParser/Parser.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"
+
+using namespace llvm;
+
+static std::unique_ptr<Module> parseIR(LLVMContext &C, const char *IR) {
+ SMDiagnostic Err;
+ std::unique_ptr<Module> Mod = parseAssemblyString(IR, Err, C);
+ if (!Mod)
+ Err.print("MLAnalysisTests", errs());
+ return Mod;
+}
+
+TEST(InlineFeaturesTest, BasicTest) {
+ LLVMContext C;
+ std::unique_ptr<Module> M = parseIR(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)
+declare i32 @f2(i32)
+
+define i32 @branches(i32) {
+ %cond = icmp slt i32 %0, 3
+ br i1 %cond, label %then, label %else
+
+then:
+ %ret.1 = call i32 @f1(i32 %0)
+ br label %last.block
+
+else:
+ %ret.2 = call i32 @f2(i32 %0)
+ br label %last.block
+
+last.block:
+ %ret = phi i32 [%ret.1, %then], [%ret.2, %else]
+ ret i32 %ret
+}
+
+define internal i32 @top() {
+ %1 = call i32 @branches(i32 2)
+ %2 = call i32 @f1(i32 %1)
+ ret i32 %2
+}
+)IR");
+
+ FunctionAnalysisManager FAM;
+ InlineFeaturesAnalysis FA;
+
+ auto BranchesFeatures = FA.run(*M->getFunction("branches"), FAM);
+ 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);
+
+ auto TopFeatures = FA.run(*M->getFunction("top"), FAM);
+ EXPECT_EQ(TopFeatures.BasicBlockCount, 1);
+ EXPECT_EQ(TopFeatures.BlocksReachedFromConditionalInstruction, 0);
+ EXPECT_EQ(TopFeatures.DirectCallsToDefinedFunctions, 1);
+ EXPECT_EQ(TopFeatures.Uses, 0);
+}
More information about the llvm-commits
mailing list