30#define DEBUG_TYPE "func-properties-stats"
32#define FUNCTION_PROPERTY(Name, Description) \
33 STATISTIC(Total##Name, Description);
34#define DETAILED_FUNCTION_PROPERTY(Name, Description) \
35 STATISTIC(Total##Name, Description);
36#include "llvm/IR/FunctionProperties.def"
41 cl::desc(
"Whether or not to compute detailed function properties."));
45 cl::desc(
"The minimum number of instructions a basic block should contain "
46 "before being considered big."));
50 cl::desc(
"The minimum number of instructions a basic block should contain "
51 "before being considered medium-sized."));
56 cl::desc(
"The minimum number of arguments a function call must have before "
57 "it is considered having many arguments."));
60int64_t getNumBlocksFromCond(
const BasicBlock &BB) {
63 if (BI->isConditional())
64 Ret += BI->getNumSuccessors();
66 Ret += (
SI->getNumCases() + (
nullptr !=
SI->getDefaultDest()));
72 return ((!
F.hasLocalLinkage()) ? 1 : 0) +
F.getNumUses();
76void FunctionPropertiesInfo::reIncludeBB(
const BasicBlock &BB) {
80void FunctionPropertiesInfo::updateForBB(
const BasicBlock &BB,
86 for (
const auto &
I : BB) {
88 const auto *
Callee = CS->getCalledFunction();
89 if (Callee && !
Callee->isIntrinsic() && !
Callee->isDeclaration())
92 if (
I.getOpcode() == Instruction::Load) {
94 }
else if (
I.getOpcode() == Instruction::Store) {
101 unsigned SuccessorCount =
succ_size(&BB);
102 if (SuccessorCount == 1)
104 else if (SuccessorCount == 2)
106 else if (SuccessorCount > 2)
109 unsigned PredecessorCount =
pred_size(&BB);
110 if (PredecessorCount == 1)
112 else if (PredecessorCount == 2)
114 else if (PredecessorCount > 2)
127 if (SuccessorCount > 1) {
142 if (BI->isConditional())
151 for (
const Instruction &
I : BB.instructionsWithoutDebug()) {
155 if (
I.getType()->isFloatTy())
157 else if (
I.getType()->isIntegerTy())
187 for (
const auto &Arg :
Call->
args()) {
188 if (Arg->getType()->isPointerTy()) {
195#define COUNT_OPERAND(OPTYPE) \
196 if (isa<OPTYPE>(Operand)) { \
197 OPTYPE##OperandCount += Direction; \
201 for (
unsigned int OperandIndex = 0; OperandIndex <
I.getNumOperands();
203 Value *Operand =
I.getOperand(OperandIndex);
227 *BB.getParent(), *IR2VecVocab);
229 BB.getContext().emitError(
"Error creating IR2Vec embeddings");
232 const auto &BBEmbedding = Embedder->getBBVector(BB);
236 FunctionEmbedding -= BBEmbedding;
238 FunctionEmbedding += BBEmbedding;
242void FunctionPropertiesInfo::updateAggregateStats(
const Function &
F,
248 std::deque<const Loop *> Worklist;
250 while (!Worklist.empty()) {
251 const auto *
L = Worklist.front();
253 std::max(
MaxLoopDepth,
static_cast<int64_t
>(
L->getLoopDepth()));
254 Worklist.pop_front();
265 .getCachedResult<IR2VecVocabAnalysis>(*
F.getParent());
275 if (Vocabulary && Vocabulary->
isValid()) {
276 FPI.IR2VecVocab = Vocabulary;
279 for (
const auto &BB :
F)
282 FPI.updateAggregateStats(
F, LI);
340 if (!FunctionEmbedding.approximatelyEquals(FPI.FunctionEmbedding))
347#define FUNCTION_PROPERTY(Name, Description) OS << #Name ": " << Name << "\n";
349#define DETAILED_FUNCTION_PROPERTY(Name, Description) \
350 if (EnableDetailedFunctionProperties) { \
351 OS << #Name ": " << Name << "\n"; \
354#include "llvm/IR/FunctionProperties.def"
356#undef FUNCTION_PROPERTY
357#undef DETAILED_FUNCTION_PROPERTY
371 OS <<
"Printing analysis results of CFA for function "
372 <<
"'" <<
F.getName() <<
"':"
385#define FUNCTION_PROPERTY(Name, Description) \
386 Total##Name += AnalysisResults.Name;
387#define DETAILED_FUNCTION_PROPERTY(Name, Description) \
388 Total##Name += AnalysisResults.Name;
389#include "llvm/IR/FunctionProperties.def"
404 LikelyToChangeBBs.
insert(&CallSiteBB);
407 LikelyToChangeBBs.
insert(&*Caller.begin());
416 CallUsers.erase(&CallSiteBB);
422 Successors.insert_range(
successors(&CallSiteBB));
431 if (Inserted.insert(Succ).second)
432 DomTreeUpdates.emplace_back(DominatorTree::UpdateKind::Delete,
446 const auto *UnwindDest =
II->getUnwindDest();
447 Successors.insert_range(
successors(UnwindDest));
450 if (Inserted.insert(Succ).second)
451 DomTreeUpdates.emplace_back(DominatorTree::UpdateKind::Delete,
461 Successors.erase(&CallSiteBB);
469 for (
const auto *BB : LikelyToChangeBBs)
470 FPI.updateForBB(*BB, -1);
473DominatorTree &FunctionPropertiesUpdater::getUpdatedDominatorTree(
482 if (Inserted.insert(Succ).second)
483 FinalDomTreeUpdates.push_back({DominatorTree::UpdateKind::Insert,
489 for (
auto &Upd : DomTreeUpdates)
491 FinalDomTreeUpdates.push_back(Upd);
493 DT.applyUpdates(FinalDomTreeUpdates);
494#ifdef EXPENSIVE_CHECKS
495 assert(DT.verify(DominatorTree::VerificationLevel::Full));
527 auto &DT = getUpdatedDominatorTree(
FAM);
529 if (&CallSiteBB != &*Caller.begin())
530 Reinclude.
insert(&*Caller.begin());
536 for (
const auto *Succ : Successors)
537 if (DT.isReachableFromEntry(Succ))
546 const auto IncludeSuccessorsMark = Reinclude.
size();
547 bool CSInsertion = Reinclude.
insert(&CallSiteBB);
550 for (
size_t I = 0;
I < Reinclude.
size(); ++
I) {
551 const auto *BB = Reinclude[
I];
552 FPI.reIncludeBB(*BB);
553 if (
I >= IncludeSuccessorsMark)
561 const auto AlreadyExcludedMark = Unreachable.
size();
562 for (
size_t I = 0;
I < Unreachable.
size(); ++
I) {
563 const auto *U = Unreachable[
I];
564 if (
I >= AlreadyExcludedMark)
565 FPI.updateForBB(*U, -1);
567 if (!DT.isReachableFromEntry(Succ))
572 FPI.updateAggregateStats(Caller, LI);
573#ifdef EXPENSIVE_CHECKS
578bool FunctionPropertiesUpdater::isUpdateValid(
Function &
F,
582 DominatorTree::VerificationLevel::Full))
587 .getCachedResult<IR2VecVocabAnalysis>(*
F.getParent());
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static const Function * getParent(const Value *V)
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static 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."))
#define COUNT_OPERAND(OPTYPE)
This file provides various utilities for inspecting and working with the control flow graph in LLVM I...
Loop::LoopBounds::Direction Direction
uint64_t IntrinsicInst * II
FunctionAnalysisManager FAM
This file implements a set that has insertion order iteration characteristics.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
LLVM Basic Block Representation.
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
LLVM_ABI bool isIndirectCall() const
Return true if the callsite is an indirect call.
iterator_range< User::op_iterator > args()
Iteration adapter for range-for loops.
unsigned arg_size() const
Implements a dense probed hash-table based set.
Analysis pass which computes a DominatorTree.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
LLVM_ABI bool isReachableFromEntry(const Use &U) const
Provide an overload for a Use.
static LLVM_ABI AnalysisKey Key
LLVM_ABI FunctionPropertiesInfo run(Function &F, FunctionAnalysisManager &FAM)
int64_t BasicBlocksWithMoreThanTwoSuccessors
int64_t BasicBlocksWithSinglePredecessor
int64_t CallReturnsVectorPointerCount
int64_t CallReturnsPointerCount
int64_t CallWithManyArgumentsCount
int64_t CallReturnsVectorIntCount
int64_t CallReturnsVectorFloatCount
int64_t BranchSuccessorCount
int64_t CastInstructionCount
int64_t BasicBlockCount
Number of basic blocks.
int64_t CriticalEdgeCount
int64_t Uses
Number of uses of this function, plus 1 if the function is callable outside the module.
int64_t InlineAsmOperandCount
int64_t ConstantFPOperandCount
int64_t BasicBlocksWithTwoSuccessors
int64_t InstructionOperandCount
int64_t CallWithPointerArgumentCount
int64_t FloatingPointInstructionCount
int64_t TopLevelLoopCount
int64_t CallReturnsIntegerCount
int64_t BlocksReachedFromConditionalInstruction
Number of blocks reached from a conditional instruction, or that are 'cases' of a SwitchInstr.
int64_t ConditionalBranchCount
int64_t GlobalValueOperandCount
int64_t UnconditionalBranchCount
int64_t ArgumentOperandCount
int64_t BasicBlocksWithSingleSuccessor
LLVM_ABI bool operator==(const FunctionPropertiesInfo &FPI) const
int64_t BasicBlockOperandCount
int64_t ControlFlowEdgeCount
int64_t SwitchInstructionCount
int64_t BranchInstructionCount
int64_t BasicBlocksWithTwoPredecessors
int64_t MediumBasicBlocks
int64_t IntegerInstructionCount
static LLVM_ABI FunctionPropertiesInfo getFunctionPropertiesInfo(const Function &F, const DominatorTree &DT, const LoopInfo &LI, const ir2vec::Vocabulary *Vocabulary)
int64_t CallReturnsFloatCount
LLVM_ABI void print(raw_ostream &OS) const
int64_t SwitchSuccessorCount
int64_t TotalInstructionCount
int64_t BasicBlocksWithMoreThanTwoPredecessors
int64_t ConstantOperandCount
int64_t ConstantIntOperandCount
int64_t UnknownOperandCount
int64_t DirectCallsToDefinedFunctions
Number of direct calls made from this function to other functions defined in this module.
int64_t IndirectCallCount
LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
LLVM_ABI FunctionPropertiesUpdater(FunctionPropertiesInfo &FPI, CallBase &CB)
LLVM_ABI void finish(FunctionAnalysisManager &FAM) const
LLVM_ABI unsigned getNumSuccessors() const LLVM_READONLY
Return the number of successors that this instruction has.
Analysis pass that exposes the LoopInfo for a function.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
A vector that has set insertion semantics.
size_type size() const
Determine the number of elements in the SetVector.
void insert_range(Range &&R)
bool insert(const value_type &X)
Insert a new element into the SetVector.
void insert_range(Range &&R)
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
bool isVectorTy() const
True if this is an instance of VectorType.
bool isPointerTy() const
True if this is an instance of PointerType.
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
bool isIntegerTy() const
True if this is an instance of IntegerType.
Type * getType() const
All values are typed, get the type of this value.
iterator_range< user_iterator > users()
static LLVM_ABI std::unique_ptr< Embedder > create(IR2VecKind Mode, const Function &F, const Vocabulary &Vocab)
Factory method to create an Embedder object.
Class for storing and accessing the IR2Vec vocabulary.
LLVM_ABI unsigned getDimension() const
LLVM_ABI bool isValid() const
This class implements an extremely fast bulk output stream that can only output to a stream.
initializer< Ty > init(const Ty &Val)
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST=nullptr, unsigned DynamicVGPRBlockSize=0)
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
auto successors(const MachineBasicBlock *BB)
OuterAnalysisManagerProxy< ModuleAnalysisManager, Function > ModuleAnalysisManagerFunctionProxy
Provide the ModuleAnalysisManager to Function proxy.
LLVM_ABI cl::opt< bool > EnableDetailedFunctionProperties("enable-detailed-function-properties", cl::Hidden, cl::init(false), cl::desc("Whether or not to compute detailed function properties."))
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
auto pred_size(const MachineBasicBlock *BB)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
auto succ_size(const MachineBasicBlock *BB)
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
static cl::opt< unsigned > BigBasicBlockInstructionThreshold("big-basic-block-instruction-threshold", cl::Hidden, cl::init(500), cl::desc("The minimum number of instructions a basic block should contain " "before being considered big."))
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
static cl::opt< unsigned > MediumBasicBlockInstructionThreshold("medium-basic-block-instruction-threshold", cl::Hidden, cl::init(15), cl::desc("The minimum number of instructions a basic block should contain " "before being considered medium-sized."))
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
A special type used by analysis passes to provide an address that identifies that particular analysis...
PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM)
Embedding is a datatype that wraps std::vector<double>.