[llvm] aad3641 - [FunctionPropertiesAnalysis] Add CFG and call properties
Aiden Grossman via llvm-commits
llvm-commits at lists.llvm.org
Fri Aug 25 15:02:48 PDT 2023
Author: Aiden Grossman
Date: 2023-08-25T15:02:09-07:00
New Revision: aad3641e80de0de149135e7ee1b5cf585c79b187
URL: https://github.com/llvm/llvm-project/commit/aad3641e80de0de149135e7ee1b5cf585c79b187
DIFF: https://github.com/llvm/llvm-project/commit/aad3641e80de0de149135e7ee1b5cf585c79b187.diff
LOG: [FunctionPropertiesAnalysis] Add CFG and call properties
This patch adds in a couple more properties related to call instructions
and the CFG within the function that should expose a little bit more
about the characteristics of the function.
Reviewed By: jdoerfert
Differential Revision: https://reviews.llvm.org/D158681
Added:
Modified:
llvm/include/llvm/Analysis/FunctionPropertiesAnalysis.h
llvm/lib/Analysis/FunctionPropertiesAnalysis.cpp
llvm/test/Analysis/FunctionPropertiesAnalysis/matmul.ll
llvm/unittests/Analysis/FunctionPropertiesAnalysisTest.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/Analysis/FunctionPropertiesAnalysis.h b/llvm/include/llvm/Analysis/FunctionPropertiesAnalysis.h
index bce390be6dc7a0..310c369d9d4811 100644
--- a/llvm/include/llvm/Analysis/FunctionPropertiesAnalysis.h
+++ b/llvm/include/llvm/Analysis/FunctionPropertiesAnalysis.h
@@ -117,6 +117,24 @@ class FunctionPropertiesInfo {
int64_t InlineAsmOperandCount = 0;
int64_t ArgumentOperandCount = 0;
int64_t UnknownOperandCount = 0;
+
+ // Additional CFG Properties
+ int64_t CriticalEdgeCount = 0;
+ int64_t ControlFlowEdgeCount = 0;
+ int64_t UnconditionalBranchCount = 0;
+
+ // Call related instructions
+ int64_t IntrinsicCount = 0;
+ int64_t DirectCallCount = 0;
+ int64_t IndirectCallCount = 0;
+ int64_t CallReturnsIntegerCount = 0;
+ int64_t CallReturnsFloatCount = 0;
+ int64_t CallReturnsPointerCount = 0;
+ int64_t CallReturnsVectorIntCount = 0;
+ int64_t CallReturnsVectorFloatCount = 0;
+ int64_t CallReturnsVectorPointerCount = 0;
+ int64_t CallWithManyArgumentsCount = 0;
+ int64_t CallWithPointerArgumentCount = 0;
};
// Analysis pass
diff --git a/llvm/lib/Analysis/FunctionPropertiesAnalysis.cpp b/llvm/lib/Analysis/FunctionPropertiesAnalysis.cpp
index 55d5312b106606..97c54943ab6db6 100644
--- a/llvm/lib/Analysis/FunctionPropertiesAnalysis.cpp
+++ b/llvm/lib/Analysis/FunctionPropertiesAnalysis.cpp
@@ -19,6 +19,7 @@
#include "llvm/IR/Constants.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/Instructions.h"
+#include "llvm/IR/IntrinsicInst.h"
#include "llvm/Support/CommandLine.h"
#include <deque>
@@ -38,6 +39,11 @@ cl::opt<unsigned> MediumBasicBlockInstructionThreshold(
cl::desc("The minimum number of instructions a basic block should contain "
"before being considered medium-sized."));
+cl::opt<unsigned> CallWithManyArgumentsThreshold(
+ "call-with-many-arguments-threshold", cl::Hidden, cl::init(4),
+ cl::desc("The minimum number of arguments a function call must have before "
+ "it is considered having many arguments."));
+
namespace {
int64_t getNrBlocksFromCond(const BasicBlock &BB) {
int64_t Ret = 0;
@@ -103,6 +109,23 @@ void FunctionPropertiesInfo::updateForBB(const BasicBlock &BB,
else
SmallBasicBlocks += Direction;
+ // Calculate critical edges by looking through all successors of a basic
+ // block that has multiple successors and finding ones that have multiple
+ // predecessors, which represent critical edges.
+ if (SuccessorCount > 1) {
+ for (const auto *Successor : successors(&BB)) {
+ if (pred_size(Successor) > 1)
+ CriticalEdgeCount += Direction;
+ }
+ }
+
+ ControlFlowEdgeCount += Direction * SuccessorCount;
+
+ if (const auto *BI = dyn_cast<BranchInst>(BB.getTerminator())) {
+ if (!BI->isConditional())
+ UnconditionalBranchCount += Direction;
+ }
+
for (const Instruction &I : BB.instructionsWithoutDebug()) {
if (I.isCast())
CastInstructionCount += Direction;
@@ -112,6 +135,41 @@ void FunctionPropertiesInfo::updateForBB(const BasicBlock &BB,
else if (I.getType()->isIntegerTy())
IntegerInstructionCount += Direction;
+ if (isa<IntrinsicInst>(I))
+ ++IntrinsicCount;
+
+ if (const auto *Call = dyn_cast<CallInst>(&I)) {
+ if (Call->isIndirectCall())
+ IndirectCallCount += Direction;
+ else
+ DirectCallCount += Direction;
+
+ if (Call->getType()->isIntegerTy())
+ CallReturnsIntegerCount += Direction;
+ else if (Call->getType()->isFloatingPointTy())
+ CallReturnsFloatCount += Direction;
+ else if (Call->getType()->isPointerTy())
+ CallReturnsPointerCount += Direction;
+ else if (Call->getType()->isVectorTy()) {
+ if (Call->getType()->getScalarType()->isIntegerTy())
+ CallReturnsVectorIntCount += Direction;
+ else if (Call->getType()->getScalarType()->isFloatingPointTy())
+ CallReturnsVectorFloatCount += Direction;
+ else if (Call->getType()->getScalarType()->isPointerTy())
+ CallReturnsVectorPointerCount += Direction;
+ }
+
+ if (Call->arg_size() > CallWithManyArgumentsThreshold)
+ CallWithManyArgumentsCount += Direction;
+
+ for (const auto &Arg : Call->args()) {
+ if (Arg->getType()->isPointerTy()) {
+ CallWithPointerArgumentCount += Direction;
+ break;
+ }
+ }
+ }
+
#define COUNT_OPERAND(OPTYPE) \
if (isa<OPTYPE>(Operand)) { \
OPTYPE##OperandCount += Direction; \
@@ -209,6 +267,20 @@ void FunctionPropertiesInfo::print(raw_ostream &OS) const {
PRINT_PROPERTY(InlineAsmOperandCount)
PRINT_PROPERTY(ArgumentOperandCount)
PRINT_PROPERTY(UnknownOperandCount)
+ PRINT_PROPERTY(CriticalEdgeCount)
+ PRINT_PROPERTY(ControlFlowEdgeCount)
+ PRINT_PROPERTY(UnconditionalBranchCount)
+ PRINT_PROPERTY(IntrinsicCount)
+ PRINT_PROPERTY(DirectCallCount)
+ PRINT_PROPERTY(IndirectCallCount)
+ PRINT_PROPERTY(CallReturnsIntegerCount)
+ PRINT_PROPERTY(CallReturnsFloatCount)
+ PRINT_PROPERTY(CallReturnsPointerCount)
+ PRINT_PROPERTY(CallReturnsVectorIntCount)
+ PRINT_PROPERTY(CallReturnsVectorFloatCount)
+ PRINT_PROPERTY(CallReturnsVectorPointerCount)
+ PRINT_PROPERTY(CallWithManyArgumentsCount)
+ PRINT_PROPERTY(CallWithPointerArgumentCount)
}
#undef PRINT_PROPERTY
diff --git a/llvm/test/Analysis/FunctionPropertiesAnalysis/matmul.ll b/llvm/test/Analysis/FunctionPropertiesAnalysis/matmul.ll
index 49b15e938080dc..500cbbc7622bfd 100644
--- a/llvm/test/Analysis/FunctionPropertiesAnalysis/matmul.ll
+++ b/llvm/test/Analysis/FunctionPropertiesAnalysis/matmul.ll
@@ -57,6 +57,19 @@ entry:
; DETAILED-PROPERTIES-DAG: InlineAsmOperandCount: 0
; DETAILED-PROPERTIES-DAG: ArgumentOperandCount: 0
; DETAILED-PROPERTIES-DAG: UnknownOperandCount: 0
+; DETAILED-PROPERTIES-DAG: CriticalEdgeCount: 0
+; DETAILED-PROPERTIES-DAG: ControlFlowEdgeCount: 0
+; DETAILED-PROPERTIES-DAG: UnconditionalBranchCount: 0
+; DETAILED-PROPERTIES-DAG: DirectCallCount: 1
+; DETAILED-PROPERTIES-DAG: IndirectCallCount: 0
+; DETAILED-PROPERTIES-DAG: CallReturnsIntegerCount: 0
+; DETAILED-PROPERTIES-DAG: CallReturnsFloatCount: 0
+; DETAILED-PROPERTIES-DAG: CallReturnsPointerCount: 0
+; DETAILED-PROPERTIES-DAG: CallReturnsVectorIntCount: 0
+; DETAILED-PROPERTIES-DAG: CallReturnsVectorFloatCount: 0
+; DETAILED-PROPERTIES-DAG: CallReturnsVectorPointerCount: 0
+; DETAILED-PROPERTIES-DAG: CallWithManyArgumentsCount: 0
+; DETAILED-PROPERTIES-DAG: CallWithPointerArgumentCount: 1
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':
@@ -201,4 +214,17 @@ for.end26: ; preds = %for.cond
; DETAILED-PROPERTIES-DAG: InlineAsmOperandCount: 0
; DETAILED-PROPERTIES-DAG: ArgumentOperandCount: 3
; DETAILED-PROPERTIES-DAG: UnknownOperandCount: 0
+; DETAILED-PROPERTIES-DAG: DirectCallCount: 0
+; DETAILED-PROPERTIES-DAG: IndirectCallCount: 0
+; DETAILED-PROPERTIES-DAG: CriticalEdgeCount: 0
+; DETAILED-PROPERTIES-DAG: ControlFlowEdgeCount: 15
+; DETAILED-PROPERTIES-DAG: UnconditionalBranchCount: 9
+; DETAILED-PROPERTIES-DAG: CallReturnsIntegerCount: 0
+; DETAILED-PROPERTIES-DAG: CallReturnsFloatCount: 0
+; DETAILED-PROPERTIES-DAG: CallReturnsPointerCount: 0
+; DETAILED-PROPERTIES-DAG: CallReturnsVectorIntCount: 0
+; DETAILED-PROPERTIES-DAG: CallReturnsVectorFloatCount: 0
+; DETAILED-PROPERTIES-DAG: CallReturnsVectorPointerCount: 0
+; DETAILED-PROPERTIES-DAG: CallWithManyArgumentsCount: 0
+; DETAILED-PROPERTIES-DAG: CallWithPointerArgumentCount: 0
diff --git a/llvm/unittests/Analysis/FunctionPropertiesAnalysisTest.cpp b/llvm/unittests/Analysis/FunctionPropertiesAnalysisTest.cpp
index 39c0d05911e2ea..f5f4a54ae08316 100644
--- a/llvm/unittests/Analysis/FunctionPropertiesAnalysisTest.cpp
+++ b/llvm/unittests/Analysis/FunctionPropertiesAnalysisTest.cpp
@@ -146,6 +146,17 @@ define internal i32 @top() {
EXPECT_EQ(DetailedBranchesFeatures.InlineAsmOperandCount, 0);
EXPECT_EQ(DetailedBranchesFeatures.ArgumentOperandCount, 3);
EXPECT_EQ(DetailedBranchesFeatures.UnknownOperandCount, 0);
+ EXPECT_EQ(DetailedBranchesFeatures.CriticalEdgeCount, 0);
+ EXPECT_EQ(DetailedBranchesFeatures.ControlFlowEdgeCount, 4);
+ EXPECT_EQ(DetailedBranchesFeatures.UnconditionalBranchCount, 2);
+ EXPECT_EQ(DetailedBranchesFeatures.IntrinsicCount, 0);
+ EXPECT_EQ(DetailedBranchesFeatures.DirectCallCount, 2);
+ EXPECT_EQ(DetailedBranchesFeatures.IndirectCallCount, 0);
+ EXPECT_EQ(DetailedBranchesFeatures.CallReturnsIntegerCount, 2);
+ EXPECT_EQ(DetailedBranchesFeatures.CallReturnsFloatCount, 0);
+ EXPECT_EQ(DetailedBranchesFeatures.CallReturnsPointerCount, 0);
+ EXPECT_EQ(DetailedBranchesFeatures.CallWithManyArgumentsCount, 0);
+ EXPECT_EQ(DetailedBranchesFeatures.CallWithPointerArgumentCount, 0);
EnableDetailedFunctionProperties.setValue(false);
}
@@ -186,6 +197,17 @@ define i64 @f1() {
EXPECT_EQ(DetailedF1Properties.InlineAsmOperandCount, 0);
EXPECT_EQ(DetailedF1Properties.ArgumentOperandCount, 0);
EXPECT_EQ(DetailedF1Properties.UnknownOperandCount, 0);
+ EXPECT_EQ(DetailedF1Properties.CriticalEdgeCount, 0);
+ EXPECT_EQ(DetailedF1Properties.ControlFlowEdgeCount, 2);
+ EXPECT_EQ(DetailedF1Properties.UnconditionalBranchCount, 0);
+ EXPECT_EQ(DetailedF1Properties.IntrinsicCount, 0);
+ EXPECT_EQ(DetailedF1Properties.DirectCallCount, 0);
+ EXPECT_EQ(DetailedF1Properties.IndirectCallCount, 0);
+ EXPECT_EQ(DetailedF1Properties.CallReturnsIntegerCount, 0);
+ EXPECT_EQ(DetailedF1Properties.CallReturnsFloatCount, 0);
+ EXPECT_EQ(DetailedF1Properties.CallReturnsPointerCount, 0);
+ EXPECT_EQ(DetailedF1Properties.CallWithManyArgumentsCount, 0);
+ EXPECT_EQ(DetailedF1Properties.CallWithPointerArgumentCount, 0);
EnableDetailedFunctionProperties.setValue(false);
}
@@ -850,6 +872,130 @@ define i64 @f1(i64 %e) {
EXPECT_EQ(DetailedF1Properties.InlineAsmOperandCount, 1);
EXPECT_EQ(DetailedF1Properties.ArgumentOperandCount, 1);
EXPECT_EQ(DetailedF1Properties.UnknownOperandCount, 0);
+ EXPECT_EQ(DetailedF1Properties.CriticalEdgeCount, 0);
+ EXPECT_EQ(DetailedF1Properties.ControlFlowEdgeCount, 0);
+ EXPECT_EQ(DetailedF1Properties.UnconditionalBranchCount, 0);
+ EXPECT_EQ(DetailedF1Properties.IntrinsicCount, 0);
+ EXPECT_EQ(DetailedF1Properties.DirectCallCount, 1);
+ EXPECT_EQ(DetailedF1Properties.IndirectCallCount, 0);
+ EXPECT_EQ(DetailedF1Properties.CallReturnsIntegerCount, 1);
+ EXPECT_EQ(DetailedF1Properties.CallReturnsFloatCount, 0);
+ EXPECT_EQ(DetailedF1Properties.CallReturnsPointerCount, 0);
+ EXPECT_EQ(DetailedF1Properties.CallWithManyArgumentsCount, 0);
+ EXPECT_EQ(DetailedF1Properties.CallWithPointerArgumentCount, 0);
+ EnableDetailedFunctionProperties.setValue(false);
+}
+
+TEST_F(FunctionPropertiesAnalysisTest, IntrinsicCount) {
+ LLVMContext C;
+ std::unique_ptr<Module> M = makeLLVMModule(C,
+ R"IR(
+define float @f1(float %a) {
+ %b = call float @llvm.cos.f32(float %a)
+ ret float %b
+}
+declare float @llvm.cos.f32(float)
+)IR");
+
+ Function *F1 = M->getFunction("f1");
+ EnableDetailedFunctionProperties.setValue(true);
+ FunctionPropertiesInfo DetailedF1Properties = buildFPI(*F1);
+ EXPECT_EQ(DetailedF1Properties.IntrinsicCount, 1);
+ EXPECT_EQ(DetailedF1Properties.DirectCallCount, 1);
+ EXPECT_EQ(DetailedF1Properties.IndirectCallCount, 0);
+ EXPECT_EQ(DetailedF1Properties.CallReturnsIntegerCount, 0);
+ EXPECT_EQ(DetailedF1Properties.CallReturnsFloatCount, 1);
+ EXPECT_EQ(DetailedF1Properties.CallReturnsPointerCount, 0);
+ EXPECT_EQ(DetailedF1Properties.CallWithManyArgumentsCount, 0);
+ EXPECT_EQ(DetailedF1Properties.CallWithPointerArgumentCount, 0);
+ EnableDetailedFunctionProperties.setValue(false);
+}
+
+TEST_F(FunctionPropertiesAnalysisTest, FunctionCallMetrics) {
+ LLVMContext C;
+ std::unique_ptr<Module> M = makeLLVMModule(C,
+ R"IR(
+define i64 @f1(i64 %a) {
+ %b = call i64 @f2(i64 %a, i64 %a, i64 %a, i64 %a, i64 %a)
+ %c = call ptr @f3()
+ call void @f4(ptr %c)
+ %d = call float @f5()
+ %e = call i64 %c(i64 %b)
+ ret i64 %b
+}
+
+declare i64 @f2(i64,i64,i64,i64,i64)
+declare ptr @f3()
+declare void @f4(ptr)
+declare float @f5()
+)IR");
+
+ Function *F1 = M->getFunction("f1");
+ EnableDetailedFunctionProperties.setValue(true);
+ FunctionPropertiesInfo DetailedF1Properties = buildFPI(*F1);
+ EXPECT_EQ(DetailedF1Properties.IntrinsicCount, 0);
+ EXPECT_EQ(DetailedF1Properties.DirectCallCount, 4);
+ EXPECT_EQ(DetailedF1Properties.IndirectCallCount, 1);
+ EXPECT_EQ(DetailedF1Properties.CallReturnsIntegerCount, 2);
+ EXPECT_EQ(DetailedF1Properties.CallReturnsFloatCount, 1);
+ EXPECT_EQ(DetailedF1Properties.CallReturnsPointerCount, 1);
+ EXPECT_EQ(DetailedF1Properties.CallWithManyArgumentsCount, 1);
+ EXPECT_EQ(DetailedF1Properties.CallWithPointerArgumentCount, 1);
+ EnableDetailedFunctionProperties.setValue(false);
+}
+
+TEST_F(FunctionPropertiesAnalysisTest, CriticalEdge) {
+ LLVMContext C;
+ std::unique_ptr<Module> M = makeLLVMModule(C,
+ R"IR(
+define i64 @f1(i64 %a) {
+ %b = icmp eq i64 %a, 1
+ br i1 %b, label %TopBlock1, label %TopBlock2
+TopBlock1:
+ %c = add i64 %a, 1
+ %e = icmp eq i64 %c, 2
+ br i1 %e, label %BottomBlock1, label %BottomBlock2
+TopBlock2:
+ %d = add i64 %a, 2
+ br label %BottomBlock2
+BottomBlock1:
+ ret i64 0
+BottomBlock2:
+ %f = phi i64 [ %c, %TopBlock1 ], [ %d, %TopBlock2 ]
+ ret i64 %f
+}
+)IR");
+
+ Function *F1 = M->getFunction("f1");
+ EnableDetailedFunctionProperties.setValue(true);
+ FunctionPropertiesInfo DetailedF1Properties = buildFPI(*F1);
+ EXPECT_EQ(DetailedF1Properties.CriticalEdgeCount, 1);
+ EnableDetailedFunctionProperties.setValue(false);
+}
+
+
+TEST_F(FunctionPropertiesAnalysisTest, FunctionReturnVectors) {
+ LLVMContext C;
+ std::unique_ptr<Module> M = makeLLVMModule(C,
+ R"IR(
+define <4 x i64> @f1(<4 x i64> %a) {
+ %b = call <4 x i64> @f2()
+ %c = call <4 x float> @f3()
+ %d = call <4 x ptr> @f4()
+ ret <4 x i64> %b
+}
+
+declare <4 x i64> @f2()
+declare <4 x float> @f3()
+declare <4 x ptr> @f4()
+)IR");
+
+ Function *F1 = M->getFunction("f1");
+ EnableDetailedFunctionProperties.setValue(true);
+ FunctionPropertiesInfo DetailedF1Properties = buildFPI(*F1);
+ EXPECT_EQ(DetailedF1Properties.CallReturnsVectorIntCount, 1);
+ EXPECT_EQ(DetailedF1Properties.CallReturnsVectorFloatCount, 1);
+ EXPECT_EQ(DetailedF1Properties.CallReturnsVectorPointerCount, 1);
EnableDetailedFunctionProperties.setValue(false);
}
} // end anonymous namespace
More information about the llvm-commits
mailing list