27#define DEBUG_TYPE "function-specialization"
29STATISTIC(NumSpecsCreated,
"Number of specializations created");
36 "Force function specialization for every call site with a constant "
41 "The maximum number of clones allowed for a single function "
47 cl::desc(
"The maximum number of iterations allowed "
48 "when searching for transitive "
53 cl::desc(
"The maximum number of incoming values a PHI node can have to be "
54 "considered during the specialization bonus estimation"));
58 "The maximum number of predecessors a basic block can have to be "
59 "considered during the estimation of dead code"));
63 cl::desc(
"Don't specialize functions that have less than this number of "
68 "Maximum codesize growth allowed per function"));
72 cl::desc(
"Reject specializations whose codesize savings are less than this "
73 "much percent of the original function size"));
77 cl::desc(
"Reject specializations whose latency savings are less than this "
78 "much percent of the original function size"));
82 cl::desc(
"Reject specializations whose inlining bonus is less than this "
83 "much percent of the original function size"));
87 "Enable function specialization on the address of global values"));
92 "Enable specialization of functions that take a literal constant as an "
99bool InstCostVisitor::canEliminateSuccessor(
BasicBlock *BB,
114Cost InstCostVisitor::estimateBasicBlocks(
118 while (!WorkList.
empty()) {
124 assert(Solver.isBlockExecutable(BB) &&
"BB already found dead by IPSCCP!");
125 if (!DeadBlocks.insert(BB).second)
128 for (Instruction &
I : *BB) {
130 if (KnownConstants.contains(&
I))
136 <<
" for user " <<
I <<
"\n");
152 if (
auto *
C = Solver.getConstantOrNull(V))
154 return KnownConstants.lookup(V);
159 while (!PendingPHIs.empty()) {
163 CodeSize += getCodeSizeSavingsForUser(Phi);
170 LLVM_DEBUG(
dbgs() <<
"FnSpecialization: Analysing bonus for constant: "
171 <<
C->getNameOrAsOperand() <<
"\n");
173 for (
auto *U :
A->users())
176 CodeSize += getCodeSizeSavingsForUser(UI,
A,
C);
178 LLVM_DEBUG(
dbgs() <<
"FnSpecialization: Accumulated bonus {CodeSize = "
179 <<
CodeSize <<
"} for argument " << *
A <<
"\n");
196 auto &BFI = GetBFI(*F);
197 Cost TotalLatency = 0;
199 for (
auto Pair : KnownConstants) {
204 uint64_t Weight = BFI.getBlockFreq(
I->getParent()).getFrequency() /
205 BFI.getEntryFreq().getFrequency();
211 <<
"} for instruction " << *
I <<
"\n");
227 : KnownConstants.end();
243 KnownConstants.insert({
User,
C});
248 <<
"} for user " << *User <<
"\n");
250 for (
auto *U :
User->users())
253 CodeSize += getCodeSizeSavingsForUser(UI, User,
C);
259 assert(LastVisited != KnownConstants.end() &&
"Invalid iterator!");
261 if (
I.getCondition() != LastVisited->first)
268 BasicBlock *Succ =
I.findCaseValue(
C)->getCaseSuccessor();
273 for (
const auto &Case :
I.cases()) {
276 canEliminateSuccessor(
I.getParent(), BB))
280 return estimateBasicBlocks(WorkList);
284 assert(LastVisited != KnownConstants.end() &&
"Invalid iterator!");
286 if (
I.getCondition() != LastVisited->first)
289 BasicBlock *Succ =
I.getSuccessor(LastVisited->second->isOneValue());
296 return estimateBasicBlocks(WorkList);
299bool InstCostVisitor::discoverTransitivelyIncomingValues(
306 while (!WorkList.
empty()) {
313 if (!TransitivePHIs.
insert(PN).second)
324 if (Constant *
C = findConstantFor(V)) {
347 bool Inserted = VisitedPHIs.insert(&
I).second;
349 bool HaveSeenIncomingPHI =
false;
351 for (
unsigned Idx = 0,
E =
I.getNumIncomingValues(); Idx !=
E; ++Idx) {
352 Value *
V =
I.getIncomingValue(Idx);
359 if (Constant *
C = findConstantFor(V)) {
371 PendingPHIs.push_back(&
I);
377 HaveSeenIncomingPHI =
true;
388 if (!HaveSeenIncomingPHI)
391 DenseSet<PHINode *> TransitivePHIs;
392 if (!discoverTransitivelyIncomingValues(Const, &
I, TransitivePHIs))
399 assert(LastVisited != KnownConstants.end() &&
"Invalid iterator!");
402 return LastVisited->second;
407 assert(LastVisited != KnownConstants.end() &&
"Invalid iterator!");
414 Operands.
reserve(
I.getNumOperands());
416 for (
unsigned Idx = 0,
E =
I.getNumOperands() - 1; Idx !=
E; ++Idx) {
431 assert(LastVisited != KnownConstants.end() &&
"Invalid iterator!");
440 Operands.
reserve(
I.getNumOperands());
442 for (
unsigned Idx = 0,
E =
I.getNumOperands(); Idx !=
E; ++Idx) {
455 assert(LastVisited != KnownConstants.end() &&
"Invalid iterator!");
457 if (
I.getCondition() == LastVisited->first) {
458 Value *
V = LastVisited->second->isZeroValue() ?
I.getFalseValue()
460 return findConstantFor(V);
462 if (Constant *Condition = findConstantFor(
I.getCondition()))
463 if ((
I.getTrueValue() == LastVisited->first && Condition->isOneValue()) ||
464 (
I.getFalseValue() == LastVisited->first && Condition->isZeroValue()))
465 return LastVisited->second;
475 assert(LastVisited != KnownConstants.end() &&
"Invalid iterator!");
478 bool ConstOnRHS =
I.getOperand(1) == LastVisited->first;
479 Value *
V = ConstOnRHS ?
I.getOperand(0) :
I.getOperand(1);
491 const ValueLatticeElement &OtherLV = Solver.getLatticeValueFor(V);
492 auto &V1State = ConstOnRHS ? OtherLV : ConstLV;
493 auto &V2State = ConstOnRHS ? ConstLV : OtherLV;
494 return V1State.
getCompare(
I.getPredicate(),
I.getType(), V2State, DL);
498 assert(LastVisited != KnownConstants.end() &&
"Invalid iterator!");
504 assert(LastVisited != KnownConstants.end() &&
"Invalid iterator!");
506 bool ConstOnRHS =
I.getOperand(1) == LastVisited->first;
507 Value *
V = ConstOnRHS ?
I.getOperand(0) :
I.getOperand(1);
510 Value *ConstVal = LastVisited->second;
516 simplifyBinOp(
I.getOpcode(), ConstVal, OtherVal, SimplifyQuery(DL)));
521 Value *StoreValue =
nullptr;
522 for (
auto *User : Alloca->
users()) {
530 if (StoreValue ||
Store->isVolatile())
532 StoreValue =
Store->getValueOperand();
542 return getCandidateConstant(StoreValue);
557 if (!
C || !
C->getType()->isIntegerTy())
585void FunctionSpecializer::promoteConstantStackValues(
Function *
F) {
586 for (User *U :
F->users()) {
603 auto *ConstVal = getConstantStackValue(
Call, ArgOp);
607 Value *GV =
new GlobalVariable(M, ConstVal->
getType(),
true,
609 "specialized.arg." + Twine(++NGlobals));
621 if (!BC || BC->getType() != BC->getOperand(0)->getType())
623 Inst.replaceAllUsesWith(BC->getOperand(0));
624 Inst.eraseFromParent();
630void FunctionSpecializer::cleanUpSSA() {
631 for (Function *
F : Specializations)
652 if (NumSpecsCreated > 0)
653 dbgs() <<
"FnSpecialization: Created " << NumSpecsCreated
654 <<
" specializations in module " << M.getName() <<
"\n");
656 removeDeadFunctions();
664 int64_t
Value =
C.getValue();
666 assert(
Value >= 0 &&
"CodeSize and Latency cannot be negative");
669 return static_cast<unsigned>(
Value);
680 unsigned NumCandidates = 0;
682 if (!isCandidateFunction(&
F))
685 auto [It, Inserted] = FunctionMetrics.try_emplace(&
F);
692 Metrics.analyzeBasicBlock(&BB, GetTTI(
F), EphValues);
697 const bool RequireMinSize =
715 int64_t Sz =
Metrics.NumInsts.getValue();
716 assert(Sz > 0 &&
"CodeSize should be positive");
718 unsigned FuncSize =
static_cast<unsigned>(Sz);
721 <<
F.getName() <<
" is " << FuncSize <<
"\n");
723 if (Inserted &&
Metrics.isRecursive)
724 promoteConstantStackValues(&
F);
726 if (!findSpecializations(&
F, FuncSize, AllSpecs, SM)) {
728 dbgs() <<
"FnSpecialization: No possible specializations found for "
729 <<
F.getName() <<
"\n");
736 if (!NumCandidates) {
739 <<
"FnSpecialization: No possible specializations found in module\n");
746 auto CompareScore = [&AllSpecs](
unsigned I,
unsigned J) {
747 if (AllSpecs[
I].Score != AllSpecs[J].Score)
748 return AllSpecs[
I].Score > AllSpecs[J].Score;
751 const unsigned NSpecs =
752 std::min(NumCandidates *
MaxClones,
unsigned(AllSpecs.
size()));
754 std::iota(BestSpecs.
begin(), BestSpecs.
begin() + NSpecs, 0);
755 if (AllSpecs.
size() > NSpecs) {
756 LLVM_DEBUG(
dbgs() <<
"FnSpecialization: Number of candidates exceed "
757 <<
"the maximum number of clones threshold.\n"
758 <<
"FnSpecialization: Specializing the "
760 <<
" most profitable candidates.\n");
761 std::make_heap(BestSpecs.
begin(), BestSpecs.
begin() + NSpecs, CompareScore);
762 for (
unsigned I = NSpecs,
N = AllSpecs.
size();
I <
N; ++
I) {
763 BestSpecs[NSpecs] =
I;
764 std::push_heap(BestSpecs.
begin(), BestSpecs.
end(), CompareScore);
765 std::pop_heap(BestSpecs.
begin(), BestSpecs.
end(), CompareScore);
769 LLVM_DEBUG(
dbgs() <<
"FnSpecialization: List of specializations \n";
770 for (
unsigned I = 0;
I < NSpecs; ++
I) {
771 const Spec &S = AllSpecs[BestSpecs[
I]];
772 dbgs() <<
"FnSpecialization: Function " << S.
F->
getName()
773 <<
" , score " << S.
Score <<
"\n";
775 dbgs() <<
"FnSpecialization: FormalArg = "
784 for (
unsigned I = 0;
I < NSpecs; ++
I) {
785 Spec &S = AllSpecs[BestSpecs[
I]];
791 S.
Clone = createSpecialization(S.
F, S.
Sig);
797 <<
" to call " << Clone->
getName() <<
"\n");
799 auto &BFI = GetBFI(*
Call->getFunction());
800 std::optional<uint64_t>
Count =
801 BFI.getBlockProfileCount(
Call->getParent());
803 std::optional<llvm::Function::ProfileCount> MaybeCloneCount =
805 if (MaybeCloneCount) {
808 if (std::optional<llvm::Function::ProfileCount> MaybeOriginalCount =
810 uint64_t OriginalCount = MaybeOriginalCount->getCount();
811 if (OriginalCount >= *
Count) {
824 OriginalFuncs.insert(S.
F);
827 Solver.solveWhileResolvedUndefsIn(Clones);
833 auto [Begin, End] = SM[
F];
834 updateCallSites(
F, AllSpecs.
begin() + Begin, AllSpecs.
begin() + End);
838 if (
F->getReturnType()->isVoidTy())
840 if (
F->getReturnType()->isStructTy()) {
842 if (!Solver.isStructLatticeConstant(
F, STy))
845 auto It = Solver.getTrackedRetVals().find(
F);
846 assert(It != Solver.getTrackedRetVals().end() &&
847 "Return value ought to be tracked");
851 for (
User *U :
F->users()) {
854 if (CS->getCalledFunction() !=
F)
856 Solver.resetLatticeValueFor(CS);
862 Solver.solveWhileResolvedUndefs();
865 if (FunctionMetrics[
F].isRecursive)
866 promoteConstantStackValues(
F);
871void FunctionSpecializer::removeDeadFunctions() {
874 <<
F->getName() <<
"\n");
876 FAM->clear(*
F,
F->getName());
882 "User of dead function must be call or invoke");
887 F->eraseFromParent();
889 DeadFunctions.clear();
897 Clone->
setName(
F->getName() +
".specialized." +
Twine(NSpecs));
902bool FunctionSpecializer::findSpecializations(
Function *
F,
unsigned FuncSize,
908 DenseMap<SpecSig, unsigned> UniqueSpecs;
912 for (Argument &Arg :
F->args())
913 if (isArgumentInteresting(&Arg))
914 Args.push_back(&Arg);
919 for (User *U :
F->users()) {
925 if (CS.getCalledFunction() !=
F)
930 if (CS.hasFnAttr(Attribute::MinSize))
935 if (!Solver.isBlockExecutable(CS.
getParent()))
941 for (Argument *
A : Args) {
942 Constant *
C = getCandidateConstant(CS.getArgOperand(
A->getArgNo()));
945 LLVM_DEBUG(
dbgs() <<
"FnSpecialization: Found interesting argument "
946 <<
A->getName() <<
" : " <<
C->getNameOrAsOperand()
955 if (
auto It = UniqueSpecs.
find(S); It != UniqueSpecs.
end()) {
964 const unsigned Index = It->second;
971 for (ArgInfo &
A : S.
Args) {
973 Score += getInliningBonus(
A.Formal,
A.Actual);
978 unsigned SpecSize = FuncSize - CodeSizeSavings;
980 auto IsProfitable = [&]() ->
bool {
986 dbgs() <<
"FnSpecialization: Specialization bonus {Inlining = "
987 << Score <<
" (" << (Score * 100 / FuncSize) <<
"%)}\n");
994 dbgs() <<
"FnSpecialization: Specialization bonus {CodeSize = "
995 << CodeSizeSavings <<
" ("
996 << (CodeSizeSavings * 100 / FuncSize) <<
"%)}\n");
1003 unsigned LatencySavings =
1007 dbgs() <<
"FnSpecialization: Specialization bonus {Latency = "
1008 << LatencySavings <<
" ("
1009 << (LatencySavings * 100 / FuncSize) <<
"%)}\n");
1018 Score += std::max(CodeSizeSavings, LatencySavings);
1023 if (!IsProfitable())
1029 Spec.CallSites.push_back(&CS);
1030 const unsigned Index = AllSpecs.
size() - 1;
1031 UniqueSpecs[S] =
Index;
1032 if (
auto [It, Inserted] = SM.try_emplace(
F, Index, Index + 1); !Inserted)
1033 It->second.second =
Index + 1;
1037 return !UniqueSpecs.
empty();
1040bool FunctionSpecializer::isCandidateFunction(
Function *
F) {
1041 if (
F->isDeclaration() ||
F->arg_empty())
1044 if (
F->hasFnAttribute(Attribute::NoDuplicate))
1048 if (Specializations.contains(
F))
1057 if (!Solver.isBlockExecutable(&
F->getEntryBlock()))
1061 if (
F->hasFnAttribute(Attribute::AlwaysInline))
1064 LLVM_DEBUG(
dbgs() <<
"FnSpecialization: Try function: " <<
F->getName()
1083 Solver.setLatticeValueForSpecializationArguments(Clone, S.
Args);
1084 Solver.markBlockExecutable(&Clone->
front());
1085 Solver.addArgumentTrackedFunction(Clone);
1086 Solver.addTrackedFunction(Clone);
1089 Specializations.insert(Clone);
1101 if (!CalledFunction)
1105 auto &CalleeTTI = (GetTTI)(*CalledFunction);
1112 int InliningBonus = 0;
1113 for (User *U :
A->users()) {
1117 if (CS->getCalledOperand() !=
A)
1134 getInlineCost(*CS, CalledFunction, Params, CalleeTTI, GetAC, GetTLI);
1139 InliningBonus += Params.DefaultThreshold;
1143 LLVM_DEBUG(
dbgs() <<
"FnSpecialization: Inlining bonus " << InliningBonus
1144 <<
" for user " << *U <<
"\n");
1147 return InliningBonus > 0 ?
static_cast<unsigned>(InliningBonus) : 0;
1152bool FunctionSpecializer::isArgumentInteresting(
Argument *
A) {
1154 if (
A->user_empty())
1157 Type *Ty =
A->getType();
1164 if (
A->hasByValAttr() && !
A->getParent()->onlyReadsMemory())
1168 if (!Solver.isArgumentTrackedFunction(
A->getParent()))
1176 : SCCPSolver::isOverdefined(Solver.getLatticeValueFor(
A));
1180 dbgs() <<
"FnSpecialization: Found interesting parameter "
1181 <<
A->getNameOrAsOperand() <<
"\n";
1183 dbgs() <<
"FnSpecialization: Nothing to do, parameter "
1184 <<
A->getNameOrAsOperand() <<
" is already constant\n";
1186 return IsOverdefined;
1191Constant *FunctionSpecializer::getCandidateConstant(
Value *V) {
1199 C = Solver.getConstantOrNull(V);
1203 if (
C &&
C->getType()->isPointerTy() && !
C->isNullValue())
1211void FunctionSpecializer::updateCallSites(
Function *
F,
const Spec *Begin,
1215 for (User *U :
F->users())
1217 CS && CS->getCalledFunction() ==
F &&
1218 Solver.isBlockExecutable(CS->
getParent()))
1221 unsigned NCallsLeft = ToUpdate.
size();
1222 for (CallBase *CS : ToUpdate) {
1226 const Spec *BestSpec =
nullptr;
1227 for (
const Spec &S :
make_range(Begin, End)) {
1228 if (!S.Clone || (BestSpec && S.Score <= BestSpec->
Score))
1231 if (
any_of(S.Sig.
Args, [CS,
this](
const ArgInfo &Arg) {
1232 unsigned ArgNo = Arg.Formal->getArgNo();
1233 return getCandidateConstant(CS->getArgOperand(ArgNo)) != Arg.Actual;
1243 CS->setCalledFunction(BestSpec->
Clone);
1244 ShouldDecrementCount =
true;
1247 if (ShouldDecrementCount)
1255 if (NCallsLeft == 0 && Solver.isArgumentTrackedFunction(
F) &&
1256 !
F->hasAddressTaken()) {
1257 Solver.markFunctionUnreachable(
F);
1258 DeadFunctions.insert(
F);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static Function * cloneCandidateFunction(Function *F, unsigned NSpecs)
Clone the function F and remove the ssa_copy intrinsics added by the SCCPSolver in the cloned version...
static void removeSSACopy(Function &F)
static unsigned getCostValue(const Cost &C)
Get the unsigned Value of given Cost object.
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
FunctionAnalysisManager FAM
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
an instruction to allocate memory on the stack
This class represents an incoming formal argument to a Function.
LLVM Basic Block Representation.
Conditional or Unconditional Branch instruction.
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
bool onlyReadsMemory(unsigned OpNo) const
Value * getArgOperand(unsigned i) const
void setArgOperand(unsigned i, Value *v)
iterator_range< User::op_iterator > args()
Iteration adapter for range-for loops.
unsigned getArgOperandNo(const Use *U) const
Given a use for a arg operand, get the arg operand number that corresponds to it.
This class represents a function call, abstracting a target machine's calling convention.
This is the base class for all instructions that perform data casts.
This class is the base class for the comparison instructions.
This is an important base class in LLVM.
iterator find(const_arg_type_t< KeyT > Val)
bool contains(const_arg_type_t< KeyT > Val) const
Return true if the specified key is in the map, false otherwise.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Implements a dense probed hash-table based set.
This class represents a freeze function that returns random concrete value if an operand is either a ...
LLVM_ABI ~FunctionSpecializer()
LLVM_ABI bool run()
Attempt to specialize functions in the module to enable constant propagation across function boundari...
InstCostVisitor getInstCostVisitorFor(Function *F)
FunctionType * getFunctionType() const
Returns the FunctionType for me.
const BasicBlock & front() const
std::optional< ProfileCount > getEntryCount(bool AllowSynthetic=false) const
Get the entry count for this function.
void setEntryCount(ProfileCount Count, const DenseSet< GlobalValue::GUID > *Imports=nullptr)
Set the entry count for this function.
an instruction for type-safe pointer arithmetic to access elements of arrays and structs
void setLinkage(LinkageTypes LT)
@ InternalLinkage
Rename collisions when linking (static functions).
int getCostDelta() const
Get the cost delta from the threshold for inlining.
LLVM_ABI Cost getLatencySavingsForKnownConstants()
Compute the latency savings from replacing all arguments with constants for a specialization candidat...
LLVM_ABI Cost getCodeSizeSavingsForArg(Argument *A, Constant *C)
Compute the codesize savings for replacing argument A with constant C.
LLVM_ABI Cost getCodeSizeSavingsFromPendingPHIs()
bool isBlockExecutable(BasicBlock *BB) const
void visit(Iterator Start, Iterator End)
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
LLVM_ABI const Function * getFunction() const
Return the function this instruction belongs to.
An instruction for reading from memory.
BasicBlock * getIncomingBlock(unsigned i) const
Return incoming basic block number i.
Value * getIncomingValue(unsigned i) const
Return incoming value number x.
unsigned getNumIncomingValues() const
Return the number of incoming edges.
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
static LLVM_ABI bool isOverdefined(const ValueLatticeElement &LV)
This class represents the LLVM 'select' instruction.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
void reserve(size_type N)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
bool isPointerTy() const
True if this is an instance of PointerType.
bool isStructTy() const
True if this is an instance of StructType.
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.
A Use represents the edge between a Value definition and its users.
LLVM_ABI Constant * getCompare(CmpInst::Predicate Pred, Type *Ty, const ValueLatticeElement &Other, const DataLayout &DL) const
true, false or undef constants, or nullptr if the comparison cannot be evaluated.
static ValueLatticeElement get(Constant *C)
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI void setName(const Twine &Name)
Change the name of the value.
LLVM_ABI std::string getNameOrAsOperand() const
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
iterator_range< user_iterator > users()
LLVM_ABI const Value * stripPointerCasts() const
Strip off pointer casts, all-zero GEPs and address space casts.
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
std::pair< iterator, bool > insert(const ValueT &V)
const ParentTy * getParent() const
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
@ C
The default llvm calling convention, compatible with C.
@ BasicBlock
Various leaf nodes.
const int IndirectCallThreshold
initializer< Ty > init(const Ty &Val)
@ User
could "use" a pointer
This is an optimization pass for GlobalISel generic memory operations.
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"))
FunctionAddr VTableAddr Value
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
hash_code hash_value(const FixedPointSemantics &Val)
static cl::opt< bool > SpecializeOnAddress("funcspec-on-address", cl::init(false), cl::Hidden, cl::desc("Enable function specialization on the address of global values"))
LLVM_ABI bool canConstantFoldCallTo(const CallBase *Call, const Function *F)
canConstantFoldCallTo - Return true if its even possible to fold a call to the specified function.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
auto successors(const MachineBasicBlock *BB)
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< bool > SpecializeLiteralConstant("funcspec-for-literal-constant", cl::init(true), cl::Hidden, cl::desc("Enable specialization of functions that take a literal constant as an " "argument"))
DenseMap< Function *, std::pair< unsigned, unsigned > > SpecMap
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
LLVM_ABI bool shouldOptimizeForSize(const MachineFunction *MF, ProfileSummaryInfo *PSI, const MachineBlockFrequencyInfo *BFI, PGSOQueryType QueryType=PGSOQueryType::Other)
Returns true if machine function MF is suggested to be size-optimized based on the profile.
LLVM_ABI Constant * ConstantFoldCompareInstOperands(unsigned Predicate, Constant *LHS, Constant *RHS, const DataLayout &DL, const TargetLibraryInfo *TLI=nullptr, const Instruction *I=nullptr)
Attempt to constant fold a compare instruction (icmp/fcmp) with the specified operands.
static cl::opt< unsigned > MaxCodeSizeGrowth("funcspec-max-codesize-growth", cl::init(3), cl::Hidden, cl::desc("Maximum codesize growth allowed per function"))
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
static cl::opt< unsigned > MinLatencySavings("funcspec-min-latency-savings", cl::init(20), cl::Hidden, cl::desc("Reject specializations whose latency savings are less than this " "much percent of the original function size"))
LLVM_ABI Constant * ConstantFoldCall(const CallBase *Call, Function *F, ArrayRef< Constant * > Operands, const TargetLibraryInfo *TLI=nullptr, bool AllowNonDeterministic=true)
ConstantFoldCall - Attempt to constant fold a call to the specified function with the specified argum...
static cl::opt< unsigned > MinFunctionSize("funcspec-min-function-size", cl::init(500), cl::Hidden, cl::desc("Don't specialize functions that have less than this number of " "instructions"))
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"))
auto dyn_cast_or_null(const Y &Val)
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI Constant * ConstantFoldUnaryOpOperand(unsigned Opcode, Constant *Op, const DataLayout &DL)
Attempt to constant fold a unary operation with the specified operand.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
FunctionAddr VTableAddr Count
LLVM_ABI Constant * ConstantFoldCastOperand(unsigned Opcode, Constant *C, Type *DestTy, const DataLayout &DL)
Attempt to constant fold a cast with the specified operand.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
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...
LLVM_ABI InlineCost getInlineCost(CallBase &Call, const InlineParams &Params, TargetTransformInfo &CalleeTTI, function_ref< AssumptionCache &(Function &)> GetAssumptionCache, function_ref< const TargetLibraryInfo &(Function &)> GetTLI, function_ref< BlockFrequencyInfo &(Function &)> GetBFI=nullptr, ProfileSummaryInfo *PSI=nullptr, OptimizationRemarkEmitter *ORE=nullptr, function_ref< EphemeralValuesCache &(Function &)> GetEphValuesCache=nullptr)
Get an InlineCost object representing the cost of inlining this callsite.
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"))
LLVM_ABI Value * simplifyBinOp(unsigned Opcode, Value *LHS, Value *RHS, const SimplifyQuery &Q)
Given operands for a BinaryOperator, fold the result or return null.
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 > 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"))
LLVM_ABI bool isGuaranteedNotToBeUndefOrPoison(const Value *V, AssumptionCache *AC=nullptr, const Instruction *CtxI=nullptr, const DominatorTree *DT=nullptr, unsigned Depth=0)
Return true if this function can prove that V does not have undef bits and is never poison.
ArrayRef(const T &OneElt) -> ArrayRef< T >
LLVM_ABI InlineParams getInlineParams()
Generate the parameters to tune the inline cost analysis based only on the commandline options.
ValueMap< const Value *, WeakTrackingVH > ValueToValueMapTy
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
auto predecessors(const MachineBasicBlock *BB)
cl::opt< bool > ProfcheckDisableMetadataFixes("profcheck-disable-metadata-fixes", cl::Hidden, cl::init(false), cl::desc("Disable metadata propagation fixes discovered through Issue #147390"))
LLVM_ABI Constant * ConstantFoldLoadFromConstPtr(Constant *C, Type *Ty, APInt Offset, const DataLayout &DL)
Return the value that a load from C with offset Offset would produce if it is constant and determinab...
LLVM_ABI Constant * ConstantFoldInstOperands(const Instruction *I, ArrayRef< Constant * > Ops, const DataLayout &DL, const TargetLibraryInfo *TLI=nullptr, bool AllowNonDeterministic=true)
ConstantFoldInstOperands - Attempt to constant fold an instruction with the specified operands.
LLVM_ABI const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
LLVM_ABI Function * CloneFunction(Function *F, ValueToValueMapTy &VMap, ClonedCodeInfo *CodeInfo=nullptr)
Return a copy of the specified function and add it to that function's module.
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"))
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Helper struct shared between Function Specialization and SCCP Solver.
Utility to calculate the size and a few similar metrics for a set of basic blocks.
static LLVM_ABI void collectEphemeralValues(const Loop *L, AssumptionCache *AC, SmallPtrSetImpl< const Value * > &EphValues)
Collect a loop's ephemeral values (those used only by an assume or similar intrinsics in the loop).
static unsigned getHashValue(const SpecSig &S)
static bool isEqual(const SpecSig &LHS, const SpecSig &RHS)
static SpecSig getEmptyKey()
static SpecSig getTombstoneKey()
An information struct used to provide DenseMap with the various necessary components for a given valu...
SmallVector< ArgInfo, 4 > Args
SmallVector< CallBase * > CallSites