Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions llvm/include/llvm/Analysis/FunctionPropertiesAnalysis.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,11 @@ class FunctionPropertiesInfo {
int64_t CriticalEdgeCount = 0;
int64_t ControlFlowEdgeCount = 0;
int64_t UnconditionalBranchCount = 0;
int64_t ConditionalBranchCount = 0;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we use FunctionProperties.def here as well?

int64_t BranchInstructionCount = 0;
int64_t BranchSuccessorCount = 0;
int64_t SwitchInstructionCount = 0;
int64_t SwitchSuccessorCount = 0;

// Call related instructions
int64_t IntrinsicCount = 0;
Expand Down Expand Up @@ -179,6 +184,12 @@ class FunctionPropertiesPrinterPass
static bool isRequired() { return true; }
};

/// Statistics pass for the FunctionPropertiesAnalysis results.
struct FunctionPropertiesStatisticsPass
: PassInfoMixin<FunctionPropertiesStatisticsPass> {
PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM);
};

/// Correctly update FunctionPropertiesInfo post-inlining. A
/// FunctionPropertiesUpdater keeps the state necessary for tracking the changes
/// llvm::InlineFunction makes. The idea is that inlining will at most modify
Expand Down
105 changes: 105 additions & 0 deletions llvm/include/llvm/IR/FunctionProperties.def
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
//===-- llvm/FunctionProperties.def - File that describes Function Properties
//
// 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
//
//===----------------------------------------------------------------------===//
//
// This file contains descriptions of the various LLVM function properties. This
// is used as a central place for enumerating the different function properties
// and should eventually be the place to put comments about the function
// properties.
//
//===----------------------------------------------------------------------===//

// NOTE: NO INCLUDE GUARD DESIRED!

// Provide definitions of macros so that users of this file do not have to
// define everything to use it.
//

// Basic/Standard Properties
#ifndef FUNCTION_PROPERTY
#define FUNCTION_PROPERTY(Name, Description)
#endif

// Detailed Properties (only processed if DETAILED_FUNCTION_PROPERTY is defined)
#ifndef DETAILED_FUNCTION_PROPERTY
#define DETAILED_FUNCTION_PROPERTY(Name, Description)
#endif

FUNCTION_PROPERTY(BasicBlockCount, "Number of basic blocks")
FUNCTION_PROPERTY(BlocksReachedFromConditionalInstruction,
"Number of blocks reached from a conditional instruction, or "
"that are 'cases' of a SwitchInstr")
FUNCTION_PROPERTY(Uses, "Number of uses of this function, plus 1 if the "
"function is callable outside the module")
FUNCTION_PROPERTY(DirectCallsToDefinedFunctions,
"Number of direct calls made from this function to other "
"functions defined in this module")
FUNCTION_PROPERTY(LoadInstCount, "Load Instruction Count")
FUNCTION_PROPERTY(StoreInstCount, "Store Instruction Count")
FUNCTION_PROPERTY(MaxLoopDepth, "Maximum Loop Depth in the Function")
FUNCTION_PROPERTY(TopLevelLoopCount,
"Number of Top Level Loops in the Function")
FUNCTION_PROPERTY(TotalInstructionCount,
"Number of instructions (of all types)")
DETAILED_FUNCTION_PROPERTY(BasicBlocksWithSingleSuccessor,
"Basic blocks with one successors")
DETAILED_FUNCTION_PROPERTY(BasicBlocksWithTwoSuccessors,
"Basic blocks with two successors")
DETAILED_FUNCTION_PROPERTY(BasicBlocksWithMoreThanTwoSuccessors,
"Basic blocks with more than two successors")
DETAILED_FUNCTION_PROPERTY(BasicBlocksWithSinglePredecessor,
"Basic blocks with one predecessors")
DETAILED_FUNCTION_PROPERTY(BasicBlocksWithTwoPredecessors,
"Basic blocks with two predecessors")
DETAILED_FUNCTION_PROPERTY(BasicBlocksWithMoreThanTwoPredecessors,
"Basic blocks with more than two predecessors")
DETAILED_FUNCTION_PROPERTY(BigBasicBlocks, "Number of big basic blocks")
DETAILED_FUNCTION_PROPERTY(MediumBasicBlocks, "Number of medium basic blocks")
DETAILED_FUNCTION_PROPERTY(SmallBasicBlocks, "Number of small basic blocks")
DETAILED_FUNCTION_PROPERTY(CastInstructionCount,
"The number of cast instructions inside the function")
DETAILED_FUNCTION_PROPERTY(
FloatingPointInstructionCount,
"The number of floating point instructions inside the function")
DETAILED_FUNCTION_PROPERTY(IntegerInstructionCount,
"The number of integer instructions inside the function")
DETAILED_FUNCTION_PROPERTY(ConstantIntOperandCount, "Constant Int Operand Count")
DETAILED_FUNCTION_PROPERTY(ConstantFPOperandCount, "Constant FP Operand Count")
DETAILED_FUNCTION_PROPERTY(ConstantOperandCount, "Constant Operand Count")
DETAILED_FUNCTION_PROPERTY(InstructionOperandCount, "Instruction Operand Count")
DETAILED_FUNCTION_PROPERTY(BasicBlockOperandCount, "Basic Block Operand Count")
DETAILED_FUNCTION_PROPERTY(GlobalValueOperandCount, "Global Value Operand Count")
DETAILED_FUNCTION_PROPERTY(InlineAsmOperandCount, "Inline Asm Operand Count")
DETAILED_FUNCTION_PROPERTY(ArgumentOperandCount, "Argument Operand Count")
DETAILED_FUNCTION_PROPERTY(UnknownOperandCount, "Unknown Operand Count")
DETAILED_FUNCTION_PROPERTY(CriticalEdgeCount, "Critical Edge Count")
DETAILED_FUNCTION_PROPERTY(ControlFlowEdgeCount, "Number of basic block successors")
DETAILED_FUNCTION_PROPERTY(UnconditionalBranchCount,
"Number of unconditional branch instructions")
DETAILED_FUNCTION_PROPERTY(ConditionalBranchCount,
"Number of conditional branch instructions")
DETAILED_FUNCTION_PROPERTY(BranchInstructionCount, "Number of branch instructions")
DETAILED_FUNCTION_PROPERTY(BranchSuccessorCount, "Number of branch successors")
DETAILED_FUNCTION_PROPERTY(SwitchInstructionCount, "Number of switch instructions")
DETAILED_FUNCTION_PROPERTY(SwitchSuccessorCount, "Number of switch successors")
DETAILED_FUNCTION_PROPERTY(IntrinsicCount, "Intrinsic Count")
DETAILED_FUNCTION_PROPERTY(DirectCallCount, "Direct Call Count")
DETAILED_FUNCTION_PROPERTY(IndirectCallCount, "Indirect Call Count")
DETAILED_FUNCTION_PROPERTY(CallReturnsIntegerCount, "Call Returns Integer Count")
DETAILED_FUNCTION_PROPERTY(CallReturnsFloatCount, "Call Returns Float Count")
DETAILED_FUNCTION_PROPERTY(CallReturnsPointerCount, "Call Returns Pointer Count")
DETAILED_FUNCTION_PROPERTY(CallReturnsVectorIntCount, "Call Returns Vector Int Count")
DETAILED_FUNCTION_PROPERTY(CallReturnsVectorFloatCount,
"Call Returns Vector Float Count")
DETAILED_FUNCTION_PROPERTY(CallReturnsVectorPointerCount,
"Call Returns Vector Pointer Count")
DETAILED_FUNCTION_PROPERTY(CallWithManyArgumentsCount, "Call With Many Arguments Count")
DETAILED_FUNCTION_PROPERTY(CallWithPointerArgumentCount,
"Call With Pointer Argument Count")

#undef FUNCTION_PROPERTY
#undef DETAILED_FUNCTION_PROPERTY
95 changes: 45 additions & 50 deletions llvm/lib/Analysis/FunctionPropertiesAnalysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "llvm/Analysis/FunctionPropertiesAnalysis.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/IR/CFG.h"
#include "llvm/IR/Constants.h"
Expand All @@ -26,6 +27,14 @@

using namespace llvm;

#define DEBUG_TYPE "func-properties-stats"

#define FUNCTION_PROPERTY(Name, Description) \
STATISTIC(Total##Name, Description);
#define DETAILED_FUNCTION_PROPERTY(Name, Description) \
STATISTIC(Total##Name, Description);
#include "llvm/IR/FunctionProperties.def"

namespace llvm {
LLVM_ABI cl::opt<bool> EnableDetailedFunctionProperties(
"enable-detailed-function-properties", cl::Hidden, cl::init(false),
Expand Down Expand Up @@ -124,9 +133,19 @@ void FunctionPropertiesInfo::updateForBB(const BasicBlock &BB,

ControlFlowEdgeCount += Direction * SuccessorCount;

if (const auto *BI = dyn_cast<BranchInst>(BB.getTerminator())) {
if (!BI->isConditional())
const Instruction *TI = BB.getTerminator();
const int64_t InstructionSuccessorCount = TI->getNumSuccessors();
if (isa<BranchInst>(TI)) {
BranchInstructionCount += Direction;
BranchSuccessorCount += Direction * InstructionSuccessorCount;
const auto *BI = dyn_cast<BranchInst>(TI);
if (BI->isConditional())
ConditionalBranchCount += Direction;
else
UnconditionalBranchCount += Direction;
} else if (isa<SwitchInst>(TI)) {
SwitchInstructionCount += Direction;
SwitchSuccessorCount += Direction * InstructionSuccessorCount;
}

for (const Instruction &I : BB.instructionsWithoutDebug()) {
Expand Down Expand Up @@ -325,57 +344,17 @@ bool FunctionPropertiesInfo::operator==(
}

void FunctionPropertiesInfo::print(raw_ostream &OS) const {
#define PRINT_PROPERTY(PROP_NAME) OS << #PROP_NAME ": " << PROP_NAME << "\n";

PRINT_PROPERTY(BasicBlockCount)
PRINT_PROPERTY(BlocksReachedFromConditionalInstruction)
PRINT_PROPERTY(Uses)
PRINT_PROPERTY(DirectCallsToDefinedFunctions)
PRINT_PROPERTY(LoadInstCount)
PRINT_PROPERTY(StoreInstCount)
PRINT_PROPERTY(MaxLoopDepth)
PRINT_PROPERTY(TopLevelLoopCount)
PRINT_PROPERTY(TotalInstructionCount)
#define FUNCTION_PROPERTY(Name, Description) OS << #Name ": " << Name << "\n";

if (EnableDetailedFunctionProperties) {
PRINT_PROPERTY(BasicBlocksWithSingleSuccessor)
PRINT_PROPERTY(BasicBlocksWithTwoSuccessors)
PRINT_PROPERTY(BasicBlocksWithMoreThanTwoSuccessors)
PRINT_PROPERTY(BasicBlocksWithSinglePredecessor)
PRINT_PROPERTY(BasicBlocksWithTwoPredecessors)
PRINT_PROPERTY(BasicBlocksWithMoreThanTwoPredecessors)
PRINT_PROPERTY(BigBasicBlocks)
PRINT_PROPERTY(MediumBasicBlocks)
PRINT_PROPERTY(SmallBasicBlocks)
PRINT_PROPERTY(CastInstructionCount)
PRINT_PROPERTY(FloatingPointInstructionCount)
PRINT_PROPERTY(IntegerInstructionCount)
PRINT_PROPERTY(ConstantIntOperandCount)
PRINT_PROPERTY(ConstantFPOperandCount)
PRINT_PROPERTY(ConstantOperandCount)
PRINT_PROPERTY(InstructionOperandCount)
PRINT_PROPERTY(BasicBlockOperandCount)
PRINT_PROPERTY(GlobalValueOperandCount)
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)
#define DETAILED_FUNCTION_PROPERTY(Name, Description) \
if (EnableDetailedFunctionProperties) { \
OS << #Name ": " << Name << "\n"; \
}

#undef PRINT_PROPERTY
#include "llvm/IR/FunctionProperties.def"

#undef FUNCTION_PROPERTY
#undef DETAILED_FUNCTION_PROPERTY

OS << "\n";
}
Expand All @@ -396,6 +375,22 @@ FunctionPropertiesPrinterPass::run(Function &F, FunctionAnalysisManager &AM) {
return PreservedAnalyses::all();
}

PreservedAnalyses
FunctionPropertiesStatisticsPass::run(Function &F,
FunctionAnalysisManager &FAM) {
LLVM_DEBUG(dbgs() << "STATSCOUNT: running on function " << F.getName()
<< "\n");
auto &AnalysisResults = FAM.getResult<FunctionPropertiesAnalysis>(F);

#define FUNCTION_PROPERTY(Name, Description) \
Total##Name += AnalysisResults.Name;
#define DETAILED_FUNCTION_PROPERTY(Name, Description) \
Total##Name += AnalysisResults.Name;
#include "llvm/IR/FunctionProperties.def"

return PreservedAnalyses::all();
}

FunctionPropertiesUpdater::FunctionPropertiesUpdater(
FunctionPropertiesInfo &FPI, CallBase &CB)
: FPI(FPI), CallSiteBB(*CB.getParent()), Caller(*CallSiteBB.getParent()) {
Expand Down
8 changes: 6 additions & 2 deletions llvm/lib/Passes/PassBuilderPipelines.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "llvm/Analysis/BasicAliasAnalysis.h"
#include "llvm/Analysis/CGSCCPassManager.h"
#include "llvm/Analysis/CtxProfAnalysis.h"
#include "llvm/Analysis/FunctionPropertiesAnalysis.h"
#include "llvm/Analysis/GlobalsModRef.h"
#include "llvm/Analysis/InlineAdvisor.h"
#include "llvm/Analysis/InstCount.h"
Expand Down Expand Up @@ -412,9 +413,12 @@ void PassBuilder::invokePipelineEarlySimplificationEPCallbacks(
// Helper to add AnnotationRemarksPass.
static void addAnnotationRemarksPass(ModulePassManager &MPM) {
MPM.addPass(createModuleToFunctionPassAdaptor(AnnotationRemarksPass()));
// Count the types of instructions used
if (AreStatisticsEnabled())
// Count the stats for InstCount and FunctionPropertiesAnalysis
if (AreStatisticsEnabled()) {
MPM.addPass(createModuleToFunctionPassAdaptor(InstCountPass()));
MPM.addPass(
createModuleToFunctionPassAdaptor(FunctionPropertiesStatisticsPass()));
}
}

// Helper to check if the current compilation phase is preparing for LTO
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Passes/PassRegistry.def
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,7 @@ FUNCTION_PASS("fix-irreducible", FixIrreduciblePass())
FUNCTION_PASS("flatten-cfg", FlattenCFGPass())
FUNCTION_PASS("float2int", Float2IntPass())
FUNCTION_PASS("free-machine-function", FreeMachineFunctionPass())
FUNCTION_PASS("func-properties-stats", FunctionPropertiesStatisticsPass())
FUNCTION_PASS("gc-lowering", GCLoweringPass())
FUNCTION_PASS("guard-widening", GuardWideningPass())
FUNCTION_PASS("gvn-hoist", GVNHoistPass())
Expand Down
70 changes: 70 additions & 0 deletions llvm/test/Other/functionpropertiesanalysis.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
; Testing with all of the below run lines that the pass gets added to the appropriate pipelines
; REQUIRES: asserts
; RUN: opt -stats -enable-detailed-function-properties -disable-output -passes=func-properties-stats < %s 2>&1 | FileCheck %s
; RUN: opt -stats -enable-detailed-function-properties -disable-output -passes='thinlto<O3>'< %s 2>&1 | FileCheck %s
; RUN: opt -stats -enable-detailed-function-properties -disable-output -passes='thinlto-pre-link<O2>' < %s 2>&1 | FileCheck %s
; RUN: opt -stats -enable-detailed-function-properties -disable-output -passes='lto<O1>' < %s 2>&1 | FileCheck %s
; RUN: opt -stats -enable-detailed-function-properties -disable-output -O3 < %s 2>&1 | FileCheck %s
; RUN: opt -stats -enable-detailed-function-properties -disable-output -O0 < %s 2>&1 | FileCheck %s

; CHECK-DAG: 10 func-properties-stats - Number of basic blocks
; CHECK-DAG: 8 func-properties-stats - Number of branch instructions
; CHECK-DAG: 10 func-properties-stats - Number of branch successors
; CHECK-DAG: 2 func-properties-stats - Number of conditional branch instructions
; CHECK-DAG: 6 func-properties-stats - Number of unconditional branch instructions
; CHECK-DAG: 18 func-properties-stats - Number of instructions (of all types)
; CHECK-DAG: 14 func-properties-stats - Number of basic block successors
; CHECK-DAG: 1 func-properties-stats - Number of switch instructions
; CHECK-DAG: 4 func-properties-stats - Number of switch successors


define void @foo(i32 %i, i32 %j, i32 %n) {
entry:
%cmp = icmp slt i32 %i, %j
br i1 %cmp, label %if.then, label %if.end

if.then:
call void @f()
br label %if.end

if.end:
switch i32 %i, label %sw.default [
i32 1, label %sw.bb
i32 2, label %sw.bb1
i32 3, label %sw.bb1
]

sw.bb:
call void @g()
br label %sw.epilog

sw.bb1:
call void @h()
br label %sw.epilog

sw.default:
call void @k()
br label %sw.epilog

sw.epilog:
%cmp2 = icmp sgt i32 %i, %n
br i1 %cmp2, label %if.then3, label %if.else

if.then3:
call void @l()
br label %if.end4

if.else:
call void @m()
br label %if.end4

if.end4:
ret void
}

declare void @f()
declare void @g()
declare void @h()
declare void @k()
declare void @l()
declare void @m()