26#define DEBUG_TYPE "function-specialization"
28STATISTIC(NumSpecsCreated,
"Number of specializations created");
35 "Force function specialization for every call site with a constant "
40 "The maximum number of clones allowed for a single function "
46 cl::desc(
"The maximum number of iterations allowed "
47 "when searching for transitive "
52 cl::desc(
"The maximum number of incoming values a PHI node can have to be "
53 "considered during the specialization bonus estimation"));
57 "The maximum number of predecessors a basic block can have to be "
58 "considered during the estimation of dead code"));
62 cl::desc(
"Don't specialize functions that have less than this number of "
67 "Maximum codesize growth allowed per function"));
71 cl::desc(
"Reject specializations whose codesize savings are less than this "
72 "much percent of the original function size"));
76 cl::desc(
"Reject specializations whose latency savings are less than this "
77 "much percent of the original function size"));
81 cl::desc(
"Reject specializations whose inlining bonus is less than this "
82 "much percent of the original function size"));
86 "Enable function specialization on the address of global values"));
91 "Enable specialization of functions that take a literal constant as an "
96bool InstCostVisitor::canEliminateSuccessor(
BasicBlock *BB,
111Cost InstCostVisitor::estimateBasicBlocks(
115 while (!WorkList.
empty()) {
121 assert(Solver.isBlockExecutable(BB) &&
"BB already found dead by IPSCCP!");
122 if (!DeadBlocks.insert(BB).second)
125 for (Instruction &
I : *BB) {
127 if (KnownConstants.contains(&
I))
133 <<
" for user " <<
I <<
"\n");
149 if (
auto *
C = Solver.getConstantOrNull(V))
151 return KnownConstants.lookup(V);
156 while (!PendingPHIs.empty()) {
160 CodeSize += getCodeSizeSavingsForUser(Phi);
167 LLVM_DEBUG(
dbgs() <<
"FnSpecialization: Analysing bonus for constant: "
168 <<
C->getNameOrAsOperand() <<
"\n");
170 for (
auto *U :
A->users())
173 CodeSize += getCodeSizeSavingsForUser(UI,
A,
C);
175 LLVM_DEBUG(
dbgs() <<
"FnSpecialization: Accumulated bonus {CodeSize = "
176 <<
CodeSize <<
"} for argument " << *
A <<
"\n");
193 auto &BFI = GetBFI(*F);
194 Cost TotalLatency = 0;
196 for (
auto Pair : KnownConstants) {
201 uint64_t Weight = BFI.getBlockFreq(
I->getParent()).getFrequency() /
202 BFI.getEntryFreq().getFrequency();
208 <<
"} for instruction " << *
I <<
"\n");
224 : KnownConstants.end();
240 KnownConstants.insert({
User,
C});
245 <<
"} for user " << *User <<
"\n");
247 for (
auto *U :
User->users())
250 CodeSize += getCodeSizeSavingsForUser(UI, User,
C);
256 assert(LastVisited != KnownConstants.end() &&
"Invalid iterator!");
258 if (
I.getCondition() != LastVisited->first)
265 BasicBlock *Succ =
I.findCaseValue(
C)->getCaseSuccessor();
270 for (
const auto &Case :
I.cases()) {
273 canEliminateSuccessor(
I.getParent(), BB))
277 return estimateBasicBlocks(WorkList);
281 assert(LastVisited != KnownConstants.end() &&
"Invalid iterator!");
283 if (
I.getCondition() != LastVisited->first)
286 BasicBlock *Succ =
I.getSuccessor(LastVisited->second->isOneValue());
293 return estimateBasicBlocks(WorkList);
296bool InstCostVisitor::discoverTransitivelyIncomingValues(
303 while (!WorkList.
empty()) {
310 if (!TransitivePHIs.
insert(PN).second)
321 if (Constant *
C = findConstantFor(V)) {
344 bool Inserted = VisitedPHIs.insert(&
I).second;
346 bool HaveSeenIncomingPHI =
false;
348 for (
unsigned Idx = 0,
E =
I.getNumIncomingValues(); Idx !=
E; ++Idx) {
349 Value *
V =
I.getIncomingValue(Idx);
356 if (Constant *
C = findConstantFor(V)) {
368 PendingPHIs.push_back(&
I);
374 HaveSeenIncomingPHI =
true;
385 if (!HaveSeenIncomingPHI)
388 DenseSet<PHINode *> TransitivePHIs;
389 if (!discoverTransitivelyIncomingValues(Const, &
I, TransitivePHIs))
396 assert(LastVisited != KnownConstants.end() &&
"Invalid iterator!");
399 return LastVisited->second;
404 assert(LastVisited != KnownConstants.end() &&
"Invalid iterator!");
413 for (
unsigned Idx = 0,
E =
I.getNumOperands() - 1; Idx !=
E; ++Idx) {
428 assert(LastVisited != KnownConstants.end() &&
"Invalid iterator!");
439 for (
unsigned Idx = 0,
E =
I.getNumOperands(); Idx !=
E; ++Idx) {
452 assert(LastVisited != KnownConstants.end() &&
"Invalid iterator!");
454 if (
I.getCondition() == LastVisited->first) {
455 Value *
V = LastVisited->second->isNullValue() ?
I.getFalseValue()
457 return findConstantFor(V);
459 if (Constant *Condition = findConstantFor(
I.getCondition()))
460 if ((
I.getTrueValue() == LastVisited->first && Condition->isOneValue()) ||
461 (
I.getFalseValue() == LastVisited->first && Condition->isNullValue()))
462 return LastVisited->second;
472 assert(LastVisited != KnownConstants.end() &&
"Invalid iterator!");
475 bool ConstOnRHS =
I.getOperand(1) == LastVisited->first;
476 Value *
V = ConstOnRHS ?
I.getOperand(0) :
I.getOperand(1);
488 const ValueLatticeElement &OtherLV = Solver.getLatticeValueFor(V);
489 auto &V1State = ConstOnRHS ? OtherLV : ConstLV;
490 auto &V2State = ConstOnRHS ? ConstLV : OtherLV;
491 return V1State.
getCompare(
I.getPredicate(),
I.getType(), V2State, DL);
495 assert(LastVisited != KnownConstants.end() &&
"Invalid iterator!");
501 assert(LastVisited != KnownConstants.end() &&
"Invalid iterator!");
503 bool ConstOnRHS =
I.getOperand(1) == LastVisited->first;
504 Value *
V = ConstOnRHS ?
I.getOperand(0) :
I.getOperand(1);
507 Value *ConstVal = LastVisited->second;
513 simplifyBinOp(
I.getOpcode(), ConstVal, OtherVal, SimplifyQuery(DL)));
518 Value *StoreValue =
nullptr;
519 for (
auto *User : Alloca->
users()) {
527 if (StoreValue ||
Store->isVolatile())
529 StoreValue =
Store->getValueOperand();
539 return getCandidateConstant(StoreValue);
554 if (!
C || !
C->getType()->isIntegerTy())
582void FunctionSpecializer::promoteConstantStackValues(
Function *
F) {
583 for (User *U :
F->users()) {
600 auto *ConstVal = getConstantStackValue(
Call, ArgOp);
604 Value *GV =
new GlobalVariable(M, ConstVal->
getType(),
true,
606 "specialized.arg." + Twine(++NGlobals));
618 if (!BC || BC->getType() != BC->getOperand(0)->getType())
620 Inst.replaceAllUsesWith(BC->getOperand(0));
621 Inst.eraseFromParent();
627void FunctionSpecializer::cleanUpSSA() {
644 if (NumSpecsCreated > 0)
645 dbgs() <<
"FnSpecialization: Created " << NumSpecsCreated
646 <<
" specializations in module " << M.getName() <<
"\n");
648 removeDeadFunctions();
656 int64_t
Value =
C.getValue();
658 assert(
Value >= 0 &&
"CodeSize and Latency cannot be negative");
661 return static_cast<unsigned>(
Value);
672 unsigned NumCandidates = 0;
674 if (!isCandidateFunction(&
F))
677 auto [It, Inserted] = FunctionMetrics.try_emplace(&
F);
684 Metrics.analyzeBasicBlock(&BB, GetTTI(
F), EphValues);
689 const bool RequireMinSize =
707 int64_t Sz =
Metrics.NumInsts.getValue();
708 assert(Sz > 0 &&
"CodeSize should be positive");
710 unsigned FuncSize =
static_cast<unsigned>(Sz);
713 <<
F.getName() <<
" is " << FuncSize <<
"\n");
715 if (Inserted &&
Metrics.isRecursive)
716 promoteConstantStackValues(&
F);
718 if (!findSpecializations(&
F, FuncSize, AllSpecs, SM)) {
720 dbgs() <<
"FnSpecialization: No possible specializations found for "
721 <<
F.getName() <<
"\n");
728 if (!NumCandidates) {
731 <<
"FnSpecialization: No possible specializations found in module\n");
738 auto CompareScore = [&AllSpecs](
unsigned I,
unsigned J) {
739 if (AllSpecs[
I].Score != AllSpecs[J].Score)
740 return AllSpecs[
I].Score > AllSpecs[J].Score;
743 const unsigned NSpecs =
744 std::min(NumCandidates *
MaxClones,
unsigned(AllSpecs.
size()));
746 std::iota(BestSpecs.
begin(), BestSpecs.
begin() + NSpecs, 0);
747 if (AllSpecs.
size() > NSpecs) {
748 LLVM_DEBUG(
dbgs() <<
"FnSpecialization: Number of candidates exceed "
749 <<
"the maximum number of clones threshold.\n"
750 <<
"FnSpecialization: Specializing the "
752 <<
" most profitable candidates.\n");
753 std::make_heap(BestSpecs.
begin(), BestSpecs.
begin() + NSpecs, CompareScore);
754 for (
unsigned I = NSpecs,
N = AllSpecs.
size();
I <
N; ++
I) {
755 BestSpecs[NSpecs] =
I;
756 std::push_heap(BestSpecs.
begin(), BestSpecs.
end(), CompareScore);
757 std::pop_heap(BestSpecs.
begin(), BestSpecs.
end(), CompareScore);
761 LLVM_DEBUG(
dbgs() <<
"FnSpecialization: List of specializations \n";
762 for (
unsigned I = 0;
I < NSpecs; ++
I) {
763 const Spec &S = AllSpecs[BestSpecs[
I]];
764 dbgs() <<
"FnSpecialization: Function " << S.
F->
getName()
765 <<
" , score " << S.
Score <<
"\n";
767 dbgs() <<
"FnSpecialization: FormalArg = "
776 for (
unsigned I = 0;
I < NSpecs; ++
I) {
777 Spec &S = AllSpecs[BestSpecs[
I]];
783 S.
Clone = createSpecialization(S.
F, S.
Sig);
789 <<
" to call " << Clone->
getName() <<
"\n");
791 auto &BFI = GetBFI(*
Call->getFunction());
792 std::optional<uint64_t>
Count =
793 BFI.getBlockProfileCount(
Call->getParent());
795 std::optional<uint64_t> MaybeCloneCount = Clone->
getEntryCount();
796 if (MaybeCloneCount) {
797 uint64_t CallCount = *
Count + *MaybeCloneCount;
799 if (std::optional<uint64_t> MaybeOriginalCount =
801 uint64_t OriginalCount = *MaybeOriginalCount;
802 if (OriginalCount >= *
Count) {
815 OriginalFuncs.insert(S.
F);
818 Solver.solveWhileResolvedUndefsIn(Clones);
824 auto [Begin, End] = SM[
F];
825 updateCallSites(
F, AllSpecs.
begin() + Begin, AllSpecs.
begin() + End);
829 if (
F->getReturnType()->isVoidTy())
831 if (
F->getReturnType()->isStructTy()) {
833 if (!Solver.isStructLatticeConstant(
F, STy))
836 auto It = Solver.getTrackedRetVals().find(
F);
837 assert(It != Solver.getTrackedRetVals().end() &&
838 "Return value ought to be tracked");
842 for (
User *U :
F->users()) {
845 if (CS->getCalledFunction() !=
F)
847 Solver.resetLatticeValueFor(CS);
853 Solver.solveWhileResolvedUndefs();
856 if (FunctionMetrics[
F].isRecursive)
857 promoteConstantStackValues(
F);
862void FunctionSpecializer::removeDeadFunctions() {
865 <<
F->getName() <<
"\n");
867 FAM->clear(*
F,
F->getName());
873 "User of dead function must be call or invoke");
878 F->eraseFromParent();
880 DeadFunctions.clear();
888 Clone->
setName(
F->getName() +
".specialized." +
Twine(NSpecs));
893bool FunctionSpecializer::findSpecializations(
Function *
F,
unsigned FuncSize,
899 DenseMap<SpecSig, unsigned> UniqueSpecs;
903 for (Argument &Arg :
F->args())
904 if (isArgumentInteresting(&Arg))
905 Args.push_back(&Arg);
910 for (User *U :
F->users()) {
916 if (CS.getCalledFunction() !=
F)
921 if (CS.hasFnAttr(Attribute::MinSize))
926 if (!Solver.isBlockExecutable(CS.
getParent()))
932 for (Argument *
A : Args) {
933 Constant *
C = getCandidateConstant(CS.getArgOperand(
A->getArgNo()));
936 LLVM_DEBUG(
dbgs() <<
"FnSpecialization: Found interesting argument "
937 <<
A->getName() <<
" : " <<
C->getNameOrAsOperand()
946 if (
auto It = UniqueSpecs.
find(S); It != UniqueSpecs.
end()) {
955 const unsigned Index = It->second;
962 for (ArgInfo &
A : S.
Args) {
964 Score += getInliningBonus(
A.Formal,
A.Actual);
969 unsigned SpecSize = FuncSize - CodeSizeSavings;
971 auto IsProfitable = [&]() ->
bool {
977 dbgs() <<
"FnSpecialization: Specialization bonus {Inlining = "
978 << Score <<
" (" << (Score * 100 / FuncSize) <<
"%)}\n");
985 dbgs() <<
"FnSpecialization: Specialization bonus {CodeSize = "
986 << CodeSizeSavings <<
" ("
987 << (CodeSizeSavings * 100 / FuncSize) <<
"%)}\n");
994 unsigned LatencySavings =
998 dbgs() <<
"FnSpecialization: Specialization bonus {Latency = "
999 << LatencySavings <<
" ("
1000 << (LatencySavings * 100 / FuncSize) <<
"%)}\n");
1009 Score += std::max(CodeSizeSavings, LatencySavings);
1014 if (!IsProfitable())
1020 Spec.CallSites.push_back(&CS);
1021 const unsigned Index = AllSpecs.
size() - 1;
1022 UniqueSpecs[S] =
Index;
1023 if (
auto [It, Inserted] = SM.try_emplace(
F, Index, Index + 1); !Inserted)
1024 It->second.second =
Index + 1;
1028 return !UniqueSpecs.
empty();
1031bool FunctionSpecializer::isCandidateFunction(
Function *
F) {
1032 if (
F->isDeclaration() ||
F->arg_empty())
1035 if (
F->isInterposable())
1038 if (
F->hasFnAttribute(Attribute::NoDuplicate))
1041 if (
F->hasOptSize())
1045 if (Specializations.contains(
F))
1054 if (!Solver.isBlockExecutable(&
F->getEntryBlock()))
1058 if (
F->hasFnAttribute(Attribute::AlwaysInline))
1061 LLVM_DEBUG(
dbgs() <<
"FnSpecialization: Try function: " <<
F->getName()
1074 if (
F->getEntryCount())
1080 Solver.setLatticeValueForSpecializationArguments(Clone, S.
Args);
1081 Solver.markBlockExecutable(&Clone->
front());
1082 Solver.addArgumentTrackedFunction(Clone);
1083 Solver.addTrackedFunction(Clone);
1086 Specializations.insert(Clone);
1098 if (!CalledFunction)
1102 auto &CalleeTTI = (GetTTI)(*CalledFunction);
1109 int InliningBonus = 0;
1110 for (User *U :
A->users()) {
1114 if (CS->getCalledOperand() !=
A)
1131 getInlineCost(*CS, CalledFunction, Params, CalleeTTI, GetAC, GetTLI);
1136 InliningBonus += Params.DefaultThreshold;
1140 LLVM_DEBUG(
dbgs() <<
"FnSpecialization: Inlining bonus " << InliningBonus
1141 <<
" for user " << *U <<
"\n");
1144 return InliningBonus > 0 ?
static_cast<unsigned>(InliningBonus) : 0;
1149bool FunctionSpecializer::isArgumentInteresting(
Argument *
A) {
1151 if (
A->user_empty())
1154 Type *Ty =
A->getType();
1161 if (
A->hasByValAttr() && !
A->getParent()->onlyReadsMemory())
1165 if (!Solver.isArgumentTrackedFunction(
A->getParent()))
1173 : SCCPSolver::isOverdefined(Solver.getLatticeValueFor(
A));
1177 dbgs() <<
"FnSpecialization: Found interesting parameter "
1178 <<
A->getNameOrAsOperand() <<
"\n";
1180 dbgs() <<
"FnSpecialization: Nothing to do, parameter "
1181 <<
A->getNameOrAsOperand() <<
" is already constant\n";
1183 return IsOverdefined;
1188Constant *FunctionSpecializer::getCandidateConstant(
Value *V) {
1196 C = Solver.getConstantOrNull(V);
1200 if (
C &&
C->getType()->isPointerTy() && !
C->isNullValue())
1208void FunctionSpecializer::updateCallSites(
Function *
F,
const Spec *Begin,
1212 for (User *U :
F->users())
1214 CS && CS->getCalledFunction() ==
F &&
1215 Solver.isBlockExecutable(CS->
getParent()))
1218 unsigned NCallsLeft = ToUpdate.
size();
1219 for (CallBase *CS : ToUpdate) {
1223 const Spec *BestSpec =
nullptr;
1224 for (
const Spec &S :
make_range(Begin, End)) {
1225 if (!S.Clone || (BestSpec && S.Score <= BestSpec->
Score))
1228 if (
any_of(S.Sig.
Args, [CS,
this](
const ArgInfo &Arg) {
1229 unsigned ArgNo = Arg.Formal->getArgNo();
1230 return getCandidateConstant(CS->getArgOperand(ArgNo)) != Arg.Actual;
1240 CS->setCalledFunction(BestSpec->
Clone);
1241 ShouldDecrementCount =
true;
1244 if (ShouldDecrementCount)
1252 if (NCallsLeft == 0 && Solver.isArgumentTrackedFunction(
F) &&
1253 !
F->hasAddressTaken()) {
1254 Solver.markFunctionUnreachable(
F);
1255 DeadFunctions.insert(
F);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
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.
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.
Conditional Branch instruction.
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< uint64_t > getEntryCount() const
Get the entry count for this function.
void setEntryCount(uint64_t 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.
iterator_range< user_iterator > users()
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 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.
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.
@ 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"))
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"))
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
auto successors(const MachineBasicBlock *BB)
@ Store
The extracted value is stored (ExtractElement only).
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...
LLVM_ABI bool canConstantFoldCallTo(const CallBase *Call, const Function *F, const TargetLibraryInfo *TLI=nullptr)
canConstantFoldCallTo - Return true if its even possible to fold a call to the specified function.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
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.
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"))
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
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)
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)
An information struct used to provide DenseMap with the various necessary components for a given valu...
SmallVector< ArgInfo, 4 > Args
SmallVector< CallBase * > CallSites