mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-26 23:24:34 +00:00
Pulled CodeMetrics out of InlineCost.h and made it a bit more general, so it can be reused from PartialSpecializationCost
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@105725 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
72
include/llvm/Analysis/CodeMetrics.h
Normal file
72
include/llvm/Analysis/CodeMetrics.h
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
//===- CodeMetrics.h - Measures the weight of a function---------*- C++ -*-===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// This file implements various weight measurements for a function, helping
|
||||||
|
// the Inliner and PartialSpecialization decide whether to duplicate its
|
||||||
|
// contents.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef LLVM_ANALYSIS_CODEMETRICS_H
|
||||||
|
#define LLVM_ANALYSIS_CODEMETRICS_H
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
// CodeMetrics - Calculate size and a few similar metrics for a set of
|
||||||
|
// basic blocks.
|
||||||
|
struct CodeMetrics {
|
||||||
|
/// NeverInline - True if this callee should never be inlined into a
|
||||||
|
/// caller.
|
||||||
|
// bool NeverInline;
|
||||||
|
|
||||||
|
// True if this function contains a call to setjmp or _setjmp
|
||||||
|
bool callsSetJmp;
|
||||||
|
|
||||||
|
// True if this function calls itself
|
||||||
|
bool isRecursive;
|
||||||
|
|
||||||
|
// True if this function contains one or more indirect branches
|
||||||
|
bool containsIndirectBr;
|
||||||
|
|
||||||
|
/// usesDynamicAlloca - True if this function calls alloca (in the C sense).
|
||||||
|
bool usesDynamicAlloca;
|
||||||
|
|
||||||
|
/// NumInsts, NumBlocks - Keep track of how large each function is, which
|
||||||
|
/// is used to estimate the code size cost of inlining it.
|
||||||
|
unsigned NumInsts, NumBlocks;
|
||||||
|
|
||||||
|
/// NumBBInsts - Keeps track of basic block code size estimates.
|
||||||
|
DenseMap<const BasicBlock *, unsigned> NumBBInsts;
|
||||||
|
|
||||||
|
/// NumCalls - Keep track of the number of calls to 'big' functions.
|
||||||
|
unsigned NumCalls;
|
||||||
|
|
||||||
|
/// NumVectorInsts - Keep track of how many instructions produce vector
|
||||||
|
/// values. The inliner is being more aggressive with inlining vector
|
||||||
|
/// kernels.
|
||||||
|
unsigned NumVectorInsts;
|
||||||
|
|
||||||
|
/// NumRets - Keep track of how many Ret instructions the block contains.
|
||||||
|
unsigned NumRets;
|
||||||
|
|
||||||
|
CodeMetrics() : callsSetJmp(false), isRecursive(false),
|
||||||
|
containsIndirectBr(false), usesDynamicAlloca(false),
|
||||||
|
NumInsts(0), NumBlocks(0), NumCalls(0), NumVectorInsts(0),
|
||||||
|
NumRets(0) {}
|
||||||
|
|
||||||
|
/// analyzeBasicBlock - Add information about the specified basic block
|
||||||
|
/// to the current structure.
|
||||||
|
void analyzeBasicBlock(const BasicBlock *BB);
|
||||||
|
|
||||||
|
/// analyzeFunction - Add information about the specified function
|
||||||
|
/// to the current structure.
|
||||||
|
void analyzeFunction(Function *F);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -19,6 +19,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include "llvm/ADT/DenseMap.h"
|
#include "llvm/ADT/DenseMap.h"
|
||||||
#include "llvm/ADT/ValueMap.h"
|
#include "llvm/ADT/ValueMap.h"
|
||||||
|
#include "llvm/Analysis/CodeMetrics.h"
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
|
||||||
@ -29,46 +30,6 @@ namespace llvm {
|
|||||||
template<class PtrType, unsigned SmallSize>
|
template<class PtrType, unsigned SmallSize>
|
||||||
class SmallPtrSet;
|
class SmallPtrSet;
|
||||||
|
|
||||||
// CodeMetrics - Calculate size and a few similar metrics for a set of
|
|
||||||
// basic blocks.
|
|
||||||
struct CodeMetrics {
|
|
||||||
/// NeverInline - True if this callee should never be inlined into a
|
|
||||||
/// caller.
|
|
||||||
bool NeverInline;
|
|
||||||
|
|
||||||
/// usesDynamicAlloca - True if this function calls alloca (in the C sense).
|
|
||||||
bool usesDynamicAlloca;
|
|
||||||
|
|
||||||
/// NumInsts, NumBlocks - Keep track of how large each function is, which
|
|
||||||
/// is used to estimate the code size cost of inlining it.
|
|
||||||
unsigned NumInsts, NumBlocks;
|
|
||||||
|
|
||||||
/// NumBBInsts - Keeps track of basic block code size estimates.
|
|
||||||
DenseMap<const BasicBlock *, unsigned> NumBBInsts;
|
|
||||||
|
|
||||||
/// NumCalls - Keep track of the number of calls to 'big' functions.
|
|
||||||
unsigned NumCalls;
|
|
||||||
|
|
||||||
/// NumVectorInsts - Keep track of how many instructions produce vector
|
|
||||||
/// values. The inliner is being more aggressive with inlining vector
|
|
||||||
/// kernels.
|
|
||||||
unsigned NumVectorInsts;
|
|
||||||
|
|
||||||
/// NumRets - Keep track of how many Ret instructions the block contains.
|
|
||||||
unsigned NumRets;
|
|
||||||
|
|
||||||
CodeMetrics() : NeverInline(false), usesDynamicAlloca(false), NumInsts(0),
|
|
||||||
NumBlocks(0), NumCalls(0), NumVectorInsts(0), NumRets(0) {}
|
|
||||||
|
|
||||||
/// analyzeBasicBlock - Add information about the specified basic block
|
|
||||||
/// to the current structure.
|
|
||||||
void analyzeBasicBlock(const BasicBlock *BB);
|
|
||||||
|
|
||||||
/// analyzeFunction - Add information about the specified function
|
|
||||||
/// to the current structure.
|
|
||||||
void analyzeFunction(Function *F);
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace InlineConstants {
|
namespace InlineConstants {
|
||||||
// Various magic constants used to adjust heuristics.
|
// Various magic constants used to adjust heuristics.
|
||||||
const int InstrCost = 5;
|
const int InstrCost = 5;
|
||||||
@ -163,6 +124,10 @@ namespace llvm {
|
|||||||
/// analyzeFunction - Add information about the specified function
|
/// analyzeFunction - Add information about the specified function
|
||||||
/// to the current structure.
|
/// to the current structure.
|
||||||
void analyzeFunction(Function *F);
|
void analyzeFunction(Function *F);
|
||||||
|
|
||||||
|
/// NeverInline - Returns true if the function should never be
|
||||||
|
/// inlined into any caller.
|
||||||
|
bool NeverInline();
|
||||||
};
|
};
|
||||||
|
|
||||||
// The Function* for a function can be changed (by ArgumentPromotion);
|
// The Function* for a function can be changed (by ArgumentPromotion);
|
||||||
|
@ -162,14 +162,14 @@ void CodeMetrics::analyzeBasicBlock(const BasicBlock *BB) {
|
|||||||
if (Function *F = CS.getCalledFunction()) {
|
if (Function *F = CS.getCalledFunction()) {
|
||||||
if (F->isDeclaration() &&
|
if (F->isDeclaration() &&
|
||||||
(F->getName() == "setjmp" || F->getName() == "_setjmp"))
|
(F->getName() == "setjmp" || F->getName() == "_setjmp"))
|
||||||
NeverInline = true;
|
callsSetJmp = true;
|
||||||
|
|
||||||
// If this call is to function itself, then the function is recursive.
|
// If this call is to function itself, then the function is recursive.
|
||||||
// Inlining it into other functions is a bad idea, because this is
|
// Inlining it into other functions is a bad idea, because this is
|
||||||
// basically just a form of loop peeling, and our metrics aren't useful
|
// basically just a form of loop peeling, and our metrics aren't useful
|
||||||
// for that case.
|
// for that case.
|
||||||
if (F == BB->getParent())
|
if (F == BB->getParent())
|
||||||
NeverInline = true;
|
isRecursive = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isa<IntrinsicInst>(II) && !callIsSmall(CS.getCalledFunction())) {
|
if (!isa<IntrinsicInst>(II) && !callIsSmall(CS.getCalledFunction())) {
|
||||||
@ -220,7 +220,7 @@ void CodeMetrics::analyzeBasicBlock(const BasicBlock *BB) {
|
|||||||
// jump would jump from the inlined copy of the function into the original
|
// jump would jump from the inlined copy of the function into the original
|
||||||
// function which is extremely undefined behavior.
|
// function which is extremely undefined behavior.
|
||||||
if (isa<IndirectBrInst>(BB->getTerminator()))
|
if (isa<IndirectBrInst>(BB->getTerminator()))
|
||||||
NeverInline = true;
|
containsIndirectBr = true;
|
||||||
|
|
||||||
// Remember NumInsts for this BB.
|
// Remember NumInsts for this BB.
|
||||||
NumBBInsts[BB] = NumInsts - NumInstsBeforeThisBB;
|
NumBBInsts[BB] = NumInsts - NumInstsBeforeThisBB;
|
||||||
@ -247,7 +247,7 @@ void InlineCostAnalyzer::FunctionInfo::analyzeFunction(Function *F) {
|
|||||||
|
|
||||||
// Don't bother calculating argument weights if we are never going to inline
|
// Don't bother calculating argument weights if we are never going to inline
|
||||||
// the function anyway.
|
// the function anyway.
|
||||||
if (Metrics.NeverInline)
|
if (NeverInline())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Check out all of the arguments to the function, figuring out how much
|
// Check out all of the arguments to the function, figuring out how much
|
||||||
@ -258,6 +258,14 @@ void InlineCostAnalyzer::FunctionInfo::analyzeFunction(Function *F) {
|
|||||||
CountCodeReductionForAlloca(I)));
|
CountCodeReductionForAlloca(I)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// NeverInline - returns true if the function should never be inlined into
|
||||||
|
/// any caller
|
||||||
|
bool InlineCostAnalyzer::FunctionInfo::NeverInline()
|
||||||
|
{
|
||||||
|
return (Metrics.callsSetJmp || Metrics.isRecursive ||
|
||||||
|
Metrics.containsIndirectBr);
|
||||||
|
|
||||||
|
}
|
||||||
// getInlineCost - The heuristic used to determine if we should inline the
|
// getInlineCost - The heuristic used to determine if we should inline the
|
||||||
// function call or not.
|
// function call or not.
|
||||||
//
|
//
|
||||||
@ -315,7 +323,7 @@ InlineCost InlineCostAnalyzer::getInlineCost(CallSite CS,
|
|||||||
CalleeFI->analyzeFunction(Callee);
|
CalleeFI->analyzeFunction(Callee);
|
||||||
|
|
||||||
// If we should never inline this, return a huge cost.
|
// If we should never inline this, return a huge cost.
|
||||||
if (CalleeFI->Metrics.NeverInline)
|
if (CalleeFI->NeverInline())
|
||||||
return InlineCost::getNever();
|
return InlineCost::getNever();
|
||||||
|
|
||||||
// FIXME: It would be nice to kill off CalleeFI->NeverInline. Then we
|
// FIXME: It would be nice to kill off CalleeFI->NeverInline. Then we
|
||||||
@ -444,9 +452,14 @@ InlineCostAnalyzer::growCachedCostInfo(Function *Caller, Function *Callee) {
|
|||||||
|
|
||||||
// Since CalleeMetrics were already calculated, we know that the CallerMetrics
|
// Since CalleeMetrics were already calculated, we know that the CallerMetrics
|
||||||
// reference isn't invalidated: both were in the DenseMap.
|
// reference isn't invalidated: both were in the DenseMap.
|
||||||
CallerMetrics.NeverInline |= CalleeMetrics.NeverInline;
|
|
||||||
CallerMetrics.usesDynamicAlloca |= CalleeMetrics.usesDynamicAlloca;
|
CallerMetrics.usesDynamicAlloca |= CalleeMetrics.usesDynamicAlloca;
|
||||||
|
|
||||||
|
// FIXME: If any of these three are true for the callee, the callee was
|
||||||
|
// not inlined into the caller, so I think they're redundant here.
|
||||||
|
CallerMetrics.callsSetJmp |= CalleeMetrics.callsSetJmp;
|
||||||
|
CallerMetrics.isRecursive |= CalleeMetrics.isRecursive;
|
||||||
|
CallerMetrics.containsIndirectBr |= CalleeMetrics.containsIndirectBr;
|
||||||
|
|
||||||
CallerMetrics.NumInsts += CalleeMetrics.NumInsts;
|
CallerMetrics.NumInsts += CalleeMetrics.NumInsts;
|
||||||
CallerMetrics.NumBlocks += CalleeMetrics.NumBlocks;
|
CallerMetrics.NumBlocks += CalleeMetrics.NumBlocks;
|
||||||
CallerMetrics.NumCalls += CalleeMetrics.NumCalls;
|
CallerMetrics.NumCalls += CalleeMetrics.NumCalls;
|
||||||
|
@ -445,7 +445,7 @@ bool LoopUnswitch::UnswitchIfProfitable(Value *LoopCond, Constant *Val) {
|
|||||||
// This is a very ad-hoc heuristic.
|
// This is a very ad-hoc heuristic.
|
||||||
if (Metrics.NumInsts > Threshold ||
|
if (Metrics.NumInsts > Threshold ||
|
||||||
Metrics.NumBlocks * 5 > Threshold ||
|
Metrics.NumBlocks * 5 > Threshold ||
|
||||||
Metrics.NeverInline) {
|
Metrics.containsIndirectBr || Metrics.isRecursive) {
|
||||||
DEBUG(dbgs() << "NOT unswitching loop %"
|
DEBUG(dbgs() << "NOT unswitching loop %"
|
||||||
<< currentLoop->getHeader()->getName() << ", cost too high: "
|
<< currentLoop->getHeader()->getName() << ", cost too high: "
|
||||||
<< currentLoop->getBlocks().size() << "\n");
|
<< currentLoop->getBlocks().size() << "\n");
|
||||||
|
Reference in New Issue
Block a user