#include "llvm/Transforms/IPO/FunctionSpecialization.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/CodeMetrics.h"
#include "llvm/Analysis/ConstantFolding.h"
#include "llvm/Analysis/InlineCost.h"
#include "llvm/Analysis/InstructionSimplify.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/Analysis/ValueLattice.h"
#include "llvm/Analysis/ValueLatticeUtils.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/Transforms/Scalar/SCCP.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/Transforms/Utils/SCCPSolver.h"
#include "llvm/Transforms/Utils/SizeOpts.h"
#include <cmath>
usingnamespacellvm;
#define DEBUG_TYPE …
STATISTIC(NumSpecsCreated, "Number of specializations created");
static cl::opt<bool> ForceSpecialization(
"force-specialization", cl::init(false), cl::Hidden, cl::desc(
"Force function specialization for every call site with a constant "
"argument"));
static cl::opt<unsigned> MaxClones(
"funcspec-max-clones", cl::init(3), cl::Hidden, cl::desc(
"The maximum number of clones allowed for a single function "
"specialization"));
static cl::opt<unsigned>
MaxDiscoveryIterations("funcspec-max-discovery-iterations", cl::init(100),
cl::Hidden,
cl::desc("The maximum number of iterations allowed "
"when searching for transitive "
"phis"));
static cl::opt<unsigned> MaxIncomingPhiValues(
"funcspec-max-incoming-phi-values", cl::init(8), cl::Hidden,
cl::desc("The maximum number of incoming values a PHI node can have to be "
"considered during the specialization bonus estimation"));
static cl::opt<unsigned> MaxBlockPredecessors(
"funcspec-max-block-predecessors", cl::init(2), cl::Hidden, cl::desc(
"The maximum number of predecessors a basic block can have to be "
"considered during the estimation of dead code"));
static cl::opt<unsigned> MinFunctionSize(
"funcspec-min-function-size", cl::init(300), cl::Hidden, cl::desc(
"Don't specialize functions that have less than this number of "
"instructions"));
static cl::opt<unsigned> MaxCodeSizeGrowth(
"funcspec-max-codesize-growth", cl::init(3), cl::Hidden, cl::desc(
"Maximum codesize growth allowed per function"));
static cl::opt<unsigned> MinCodeSizeSavings(
"funcspec-min-codesize-savings", cl::init(20), cl::Hidden, cl::desc(
"Reject specializations whose codesize savings are less than this"
"much percent of the original function size"));
static cl::opt<unsigned> MinLatencySavings(
"funcspec-min-latency-savings", cl::init(40), cl::Hidden,
cl::desc("Reject specializations whose latency savings are less than this"
"much percent of the original function size"));
static cl::opt<unsigned> MinInliningBonus(
"funcspec-min-inlining-bonus", cl::init(300), cl::Hidden, cl::desc(
"Reject specializations whose inlining bonus is less than this"
"much percent of the original function size"));
static cl::opt<bool> SpecializeOnAddress(
"funcspec-on-address", cl::init(false), cl::Hidden, cl::desc(
"Enable function specialization on the address of global values"));
static cl::opt<bool> SpecializeLiteralConstant(
"funcspec-for-literal-constant", cl::init(false), cl::Hidden, cl::desc(
"Enable specialization of functions that take a literal constant as an "
"argument"));
bool InstCostVisitor::canEliminateSuccessor(BasicBlock *BB, BasicBlock *Succ,
DenseSet<BasicBlock *> &DeadBlocks) { … }
Cost InstCostVisitor::estimateBasicBlocks(
SmallVectorImpl<BasicBlock *> &WorkList) { … }
static Constant *findConstantFor(Value *V, ConstMap &KnownConstants) { … }
Bonus InstCostVisitor::getBonusFromPendingPHIs() { … }
Bonus InstCostVisitor::getSpecializationBonus(Argument *A, Constant *C) { … }
Bonus InstCostVisitor::getUserBonus(Instruction *User, Value *Use, Constant *C) { … }
Cost InstCostVisitor::estimateSwitchInst(SwitchInst &I) { … }
Cost InstCostVisitor::estimateBranchInst(BranchInst &I) { … }
bool InstCostVisitor::discoverTransitivelyIncomingValues(
Constant *Const, PHINode *Root, DenseSet<PHINode *> &TransitivePHIs) { … }
Constant *InstCostVisitor::visitPHINode(PHINode &I) { … }
Constant *InstCostVisitor::visitFreezeInst(FreezeInst &I) { … }
Constant *InstCostVisitor::visitCallBase(CallBase &I) { … }
Constant *InstCostVisitor::visitLoadInst(LoadInst &I) { … }
Constant *InstCostVisitor::visitGetElementPtrInst(GetElementPtrInst &I) { … }
Constant *InstCostVisitor::visitSelectInst(SelectInst &I) { … }
Constant *InstCostVisitor::visitCastInst(CastInst &I) { … }
Constant *InstCostVisitor::visitCmpInst(CmpInst &I) { … }
Constant *InstCostVisitor::visitUnaryOperator(UnaryOperator &I) { … }
Constant *InstCostVisitor::visitBinaryOperator(BinaryOperator &I) { … }
Constant *FunctionSpecializer::getPromotableAlloca(AllocaInst *Alloca,
CallInst *Call) { … }
Constant *FunctionSpecializer::getConstantStackValue(CallInst *Call,
Value *Val) { … }
void FunctionSpecializer::promoteConstantStackValues(Function *F) { … }
static void removeSSACopy(Function &F) { … }
void FunctionSpecializer::cleanUpSSA() { … }
template <> struct llvm::DenseMapInfo<SpecSig> { … };
FunctionSpecializer::~FunctionSpecializer() { … }
bool FunctionSpecializer::run() { … }
void FunctionSpecializer::removeDeadFunctions() { … }
static Function *cloneCandidateFunction(Function *F, unsigned NSpecs) { … }
bool FunctionSpecializer::findSpecializations(Function *F, unsigned FuncSize,
SmallVectorImpl<Spec> &AllSpecs,
SpecMap &SM) { … }
bool FunctionSpecializer::isCandidateFunction(Function *F) { … }
Function *FunctionSpecializer::createSpecialization(Function *F,
const SpecSig &S) { … }
unsigned FunctionSpecializer::getInliningBonus(Argument *A, Constant *C) { … }
bool FunctionSpecializer::isArgumentInteresting(Argument *A) { … }
Constant *FunctionSpecializer::getCandidateConstant(Value *V) { … }
void FunctionSpecializer::updateCallSites(Function *F, const Spec *Begin,
const Spec *End) { … }