28#define DEBUG_TYPE "function-specialization"
30STATISTIC(NumSpecsCreated,
"Number of specializations created");
34 "Force function specialization for every call site with a constant "
39 "The maximum number of clones allowed for a single function "
45 cl::desc(
"The maximum number of iterations allowed "
46 "when searching for transitive "
51 cl::desc(
"The maximum number of incoming values a PHI node can have to be "
52 "considered during the specialization bonus estimation"));
56 "The maximum number of predecessors a basic block can have to be "
57 "considered during the estimation of dead code"));
61 cl::desc(
"Don't specialize functions that have less than this number of "
66 "Maximum codesize growth allowed per function"));
70 "Reject specializations whose codesize savings are less than this"
71 "much percent of the original function size"));
75 cl::desc(
"Reject specializations whose latency savings are less than this"
76 "much percent of the original function size"));
80 "Reject specializations whose inlining bonus is less than this"
81 "much percent of the original function size"));
85 "Enable function specialization on the address of global values"));
90 "Enable specialization of functions that take a literal constant as an "
93bool InstCostVisitor::canEliminateSuccessor(
BasicBlock *BB,
108Cost InstCostVisitor::estimateBasicBlocks(
112 while (!WorkList.
empty()) {
119 if (!DeadBlocks.insert(BB).second)
130 <<
" for user " <<
I <<
"\n");
144 if (
auto *
C = dyn_cast<Constant>(V))
148 return KnownConstants.
lookup(V);
153 while (!PendingPHIs.empty()) {
157 CodeSize += getCodeSizeSavingsForUser(Phi);
164 LLVM_DEBUG(
dbgs() <<
"FnSpecialization: Analysing bonus for constant: "
165 <<
C->getNameOrAsOperand() <<
"\n");
167 for (
auto *U :
A->users())
168 if (
auto *UI = dyn_cast<Instruction>(U))
170 CodeSize += getCodeSizeSavingsForUser(UI,
A,
C);
172 LLVM_DEBUG(
dbgs() <<
"FnSpecialization: Accumulated bonus {CodeSize = "
173 << CodeSize <<
"} for argument " << *
A <<
"\n");
190 auto &BFI = GetBFI(*F);
191 Cost TotalLatency = 0;
193 for (
auto Pair : KnownConstants) {
198 uint64_t Weight = BFI.getBlockFreq(
I->getParent()).getFrequency() /
199 BFI.getEntryFreq().getFrequency();
205 <<
"} for instruction " << *
I <<
"\n");
221 : KnownConstants.
end();
224 if (
auto *
I = dyn_cast<SwitchInst>(
User)) {
225 CodeSize = estimateSwitchInst(*
I);
226 }
else if (
auto *
I = dyn_cast<BranchInst>(
User)) {
227 CodeSize = estimateBranchInst(*
I);
242 <<
"} for user " << *
User <<
"\n");
245 if (
auto *UI = dyn_cast<Instruction>(U))
247 CodeSize += getCodeSizeSavingsForUser(UI,
User,
C);
253 assert(LastVisited != KnownConstants.
end() &&
"Invalid iterator!");
255 if (
I.getCondition() != LastVisited->first)
258 auto *
C = dyn_cast<ConstantInt>(LastVisited->second);
262 BasicBlock *Succ =
I.findCaseValue(
C)->getCaseSuccessor();
267 for (
const auto &Case :
I.cases()) {
270 canEliminateSuccessor(
I.getParent(), BB))
274 return estimateBasicBlocks(WorkList);
278 assert(LastVisited != KnownConstants.
end() &&
"Invalid iterator!");
280 if (
I.getCondition() != LastVisited->first)
283 BasicBlock *Succ =
I.getSuccessor(LastVisited->second->isOneValue());
290 return estimateBasicBlocks(WorkList);
293bool InstCostVisitor::discoverTransitivelyIncomingValues(
300 while (!WorkList.
empty()) {
307 if (!TransitivePHIs.
insert(PN).second)
314 if (
auto *Inst = dyn_cast<Instruction>(V))
325 if (
auto *Phi = dyn_cast<PHINode>(V)) {
341 bool Inserted = VisitedPHIs.insert(&
I).second;
343 bool HaveSeenIncomingPHI =
false;
345 for (
unsigned Idx = 0, E =
I.getNumIncomingValues();
Idx != E; ++
Idx) {
349 if (
auto *Inst = dyn_cast<Instruction>(V))
365 PendingPHIs.push_back(&
I);
369 if (isa<PHINode>(V)) {
371 HaveSeenIncomingPHI =
true;
382 if (!HaveSeenIncomingPHI)
386 if (!discoverTransitivelyIncomingValues(Const, &
I, TransitivePHIs))
393 assert(LastVisited != KnownConstants.
end() &&
"Invalid iterator!");
396 return LastVisited->second;
401 assert(LastVisited != KnownConstants.
end() &&
"Invalid iterator!");
404 if (
auto *
II = dyn_cast<IntrinsicInst>(&
I);
405 II &&
II->getIntrinsicID() == Intrinsic::ssa_copy) {
406 return LastVisited->second;
416 for (
unsigned Idx = 0, E =
I.getNumOperands() - 1;
Idx != E; ++
Idx) {
429 assert(LastVisited != KnownConstants.
end() &&
"Invalid iterator!");
431 if (isa<ConstantPointerNull>(LastVisited->second))
440 for (
unsigned Idx = 0, E =
I.getNumOperands();
Idx != E; ++
Idx) {
453 assert(LastVisited != KnownConstants.
end() &&
"Invalid iterator!");
455 if (
I.getCondition() == LastVisited->first) {
456 Value *
V = LastVisited->second->isZeroValue() ?
I.getFalseValue()
458 return findConstantFor(V);
460 if (
Constant *Condition = findConstantFor(
I.getCondition()))
461 if ((
I.getTrueValue() == LastVisited->first && Condition->isOneValue()) ||
462 (
I.getFalseValue() == LastVisited->first && Condition->isZeroValue()))
463 return LastVisited->second;
473 assert(LastVisited != KnownConstants.
end() &&
"Invalid iterator!");
476 bool ConstOnRHS =
I.getOperand(1) == LastVisited->first;
477 Value *
V = ConstOnRHS ?
I.getOperand(0) :
I.getOperand(1);
490 auto &V1State = ConstOnRHS ? OtherLV : ConstLV;
491 auto &V2State = ConstOnRHS ? ConstLV : OtherLV;
492 return V1State.
getCompare(
I.getPredicate(),
I.getType(), V2State, DL);
496 assert(LastVisited != KnownConstants.
end() &&
"Invalid iterator!");
502 assert(LastVisited != KnownConstants.
end() &&
"Invalid iterator!");
504 bool ConstOnRHS =
I.getOperand(1) == LastVisited->first;
505 Value *
V = ConstOnRHS ?
I.getOperand(0) :
I.getOperand(1);
508 Value *ConstVal = LastVisited->second;
513 return dyn_cast_or_null<Constant>(
519 Value *StoreValue =
nullptr;
526 if (
auto *Store = dyn_cast<StoreInst>(
User)) {
528 if (StoreValue ||
Store->isVolatile())
530 StoreValue =
Store->getValueOperand();
540 return getCandidateConstant(StoreValue);
551 if (
auto *ConstVal = dyn_cast<ConstantInt>(Val))
553 auto *Alloca = dyn_cast<AllocaInst>(Val);
556 return getPromotableAlloca(Alloca, Call);
582void FunctionSpecializer::promoteConstantStackValues(
Function *
F) {
583 for (
User *U :
F->users()) {
585 auto *
Call = dyn_cast<CallInst>(U);
592 for (
const Use &U :
Call->args()) {
593 unsigned Idx =
Call->getArgOperandNo(&U);
600 auto *ConstVal = getConstantStackValue(Call, ArgOp);
606 "specialized.arg." +
Twine(++NGlobals));
617 auto *
II = dyn_cast<IntrinsicInst>(&Inst);
620 if (
II->getIntrinsicID() != Intrinsic::ssa_copy)
622 Inst.replaceAllUsesWith(
II->getOperand(0));
623 Inst.eraseFromParent();
629void FunctionSpecializer::cleanUpSSA() {
651 if (NumSpecsCreated > 0)
652 dbgs() <<
"FnSpecialization: Created " << NumSpecsCreated
653 <<
" specializations in module " << M.
getName() <<
"\n");
655 removeDeadFunctions();
663 int64_t
Value = *
C.getValue();
665 assert(
Value >= 0 &&
"CodeSize and Latency cannot be negative");
668 return static_cast<unsigned>(
Value);
679 unsigned NumCandidates = 0;
681 if (!isCandidateFunction(&
F))
684 auto [It, Inserted] = FunctionMetrics.try_emplace(&
F);
691 Metrics.analyzeBasicBlock(&BB, GetTTI(
F), EphValues);
696 const bool RequireMinSize =
714 int64_t Sz = *
Metrics.NumInsts.getValue();
715 assert(Sz > 0 &&
"CodeSize should be positive");
717 unsigned FuncSize =
static_cast<unsigned>(Sz);
720 <<
F.getName() <<
" is " << FuncSize <<
"\n");
722 if (Inserted &&
Metrics.isRecursive)
723 promoteConstantStackValues(&
F);
725 if (!findSpecializations(&
F, FuncSize, AllSpecs, SM)) {
727 dbgs() <<
"FnSpecialization: No possible specializations found for "
728 <<
F.getName() <<
"\n");
735 if (!NumCandidates) {
738 <<
"FnSpecialization: No possible specializations found in module\n");
745 auto CompareScore = [&AllSpecs](
unsigned I,
unsigned J) {
746 if (AllSpecs[
I].Score != AllSpecs[J].Score)
747 return AllSpecs[
I].Score > AllSpecs[J].Score;
750 const unsigned NSpecs =
751 std::min(NumCandidates *
MaxClones,
unsigned(AllSpecs.
size()));
753 std::iota(BestSpecs.
begin(), BestSpecs.
begin() + NSpecs, 0);
754 if (AllSpecs.
size() > NSpecs) {
755 LLVM_DEBUG(
dbgs() <<
"FnSpecialization: Number of candidates exceed "
756 <<
"the maximum number of clones threshold.\n"
757 <<
"FnSpecialization: Specializing the "
759 <<
" most profitable candidates.\n");
760 std::make_heap(BestSpecs.
begin(), BestSpecs.
begin() + NSpecs, CompareScore);
761 for (
unsigned I = NSpecs,
N = AllSpecs.
size();
I <
N; ++
I) {
762 BestSpecs[NSpecs] =
I;
763 std::push_heap(BestSpecs.
begin(), BestSpecs.
end(), CompareScore);
764 std::pop_heap(BestSpecs.
begin(), BestSpecs.
end(), CompareScore);
768 LLVM_DEBUG(
dbgs() <<
"FnSpecialization: List of specializations \n";
769 for (
unsigned I = 0;
I < NSpecs; ++
I) {
770 const Spec &S = AllSpecs[BestSpecs[
I]];
771 dbgs() <<
"FnSpecialization: Function " << S.
F->
getName()
772 <<
" , score " << S.
Score <<
"\n";
774 dbgs() <<
"FnSpecialization: FormalArg = "
783 for (
unsigned I = 0;
I < NSpecs; ++
I) {
784 Spec &S = AllSpecs[BestSpecs[
I]];
790 S.
Clone = createSpecialization(S.
F, S.
Sig);
796 Call->setCalledFunction(S.
Clone);
800 OriginalFuncs.insert(S.
F);
809 auto [Begin,
End] = SM[
F];
810 updateCallSites(
F, AllSpecs.
begin() + Begin, AllSpecs.
begin() +
End);
814 if (
F->getReturnType()->isVoidTy())
816 if (
F->getReturnType()->isStructTy()) {
817 auto *STy = cast<StructType>(
F->getReturnType());
823 "Return value ought to be tracked");
827 for (
User *U :
F->users()) {
828 if (
auto *CS = dyn_cast<CallBase>(U)) {
830 if (CS->getCalledFunction() !=
F)
841 if (FunctionMetrics[
F].isRecursive)
842 promoteConstantStackValues(
F);
847void FunctionSpecializer::removeDeadFunctions() {
850 <<
F->getName() <<
"\n");
853 F->eraseFromParent();
855 FullySpecialized.clear();
863 Clone->
setName(
F->getName() +
".specialized." +
Twine(NSpecs));
868bool FunctionSpecializer::findSpecializations(
Function *
F,
unsigned FuncSize,
879 if (isArgumentInteresting(&Arg))
880 Args.push_back(&Arg);
885 for (
User *U :
F->users()) {
886 if (!isa<CallInst>(U) && !isa<InvokeInst>(U))
888 auto &CS = *cast<CallBase>(U);
891 if (CS.getCalledFunction() !=
F)
896 if (CS.hasFnAttr(Attribute::MinSize))
908 Constant *
C = getCandidateConstant(CS.getArgOperand(
A->getArgNo()));
911 LLVM_DEBUG(
dbgs() <<
"FnSpecialization: Found interesting argument "
912 <<
A->getName() <<
" : " <<
C->getNameOrAsOperand()
921 if (
auto It = UniqueSpecs.
find(S); It != UniqueSpecs.
end()) {
928 if (CS.getFunction() ==
F)
930 const unsigned Index = It->second;
939 Score += getInliningBonus(
A.Formal,
A.Actual);
944 unsigned SpecSize = FuncSize - CodeSizeSavings;
946 auto IsProfitable = [&]() ->
bool {
952 dbgs() <<
"FnSpecialization: Specialization bonus {Inlining = "
953 << Score <<
" (" << (Score * 100 / FuncSize) <<
"%)}\n");
960 dbgs() <<
"FnSpecialization: Specialization bonus {CodeSize = "
961 << CodeSizeSavings <<
" ("
962 << (CodeSizeSavings * 100 / FuncSize) <<
"%)}\n");
969 unsigned LatencySavings =
973 dbgs() <<
"FnSpecialization: Specialization bonus {Latency = "
974 << LatencySavings <<
" ("
975 << (LatencySavings * 100 / FuncSize) <<
"%)}\n");
984 Score += std::max(CodeSizeSavings, LatencySavings);
994 if (CS.getFunction() !=
F)
996 const unsigned Index = AllSpecs.
size() - 1;
997 UniqueSpecs[S] =
Index;
998 if (
auto [It, Inserted] = SM.
try_emplace(
F, Index, Index + 1); !Inserted)
999 It->second.second =
Index + 1;
1003 return !UniqueSpecs.
empty();
1006bool FunctionSpecializer::isCandidateFunction(
Function *
F) {
1007 if (
F->isDeclaration() ||
F->arg_empty())
1010 if (
F->hasFnAttribute(Attribute::NoDuplicate))
1014 if (Specializations.contains(
F))
1027 if (
F->hasFnAttribute(Attribute::AlwaysInline))
1030 LLVM_DEBUG(
dbgs() <<
"FnSpecialization: Try function: " <<
F->getName()
1052 Specializations.insert(Clone);
1063 Function *CalledFunction = dyn_cast<Function>(
C->stripPointerCasts());
1064 if (!CalledFunction)
1068 auto &CalleeTTI = (GetTTI)(*CalledFunction);
1075 int InliningBonus = 0;
1076 for (
User *U :
A->users()) {
1077 if (!isa<CallInst>(U) && !isa<InvokeInst>(U))
1079 auto *CS = cast<CallBase>(U);
1080 if (CS->getCalledOperand() !=
A)
1097 getInlineCost(*CS, CalledFunction, Params, CalleeTTI, GetAC, GetTLI);
1102 InliningBonus += Params.DefaultThreshold;
1106 LLVM_DEBUG(
dbgs() <<
"FnSpecialization: Inlining bonus " << InliningBonus
1107 <<
" for user " << *U <<
"\n");
1110 return InliningBonus > 0 ?
static_cast<unsigned>(InliningBonus) : 0;
1115bool FunctionSpecializer::isArgumentInteresting(
Argument *
A) {
1117 if (
A->user_empty())
1120 Type *Ty =
A->getType();
1127 if (
A->hasByValAttr() && !
A->getParent()->onlyReadsMemory())
1139 :
SCCPSolver::isOverdefined(Solver.getLatticeValueFor(
A));
1143 dbgs() <<
"FnSpecialization: Found interesting parameter "
1144 <<
A->getNameOrAsOperand() <<
"\n";
1146 dbgs() <<
"FnSpecialization: Nothing to do, parameter "
1147 <<
A->getNameOrAsOperand() <<
" is already constant\n";
1149 return IsOverdefined;
1154Constant *FunctionSpecializer::getCandidateConstant(
Value *V) {
1155 if (isa<PoisonValue>(V))
1166 if (
C &&
C->getType()->isPointerTy() && !
C->isNullValue())
1174void FunctionSpecializer::updateCallSites(
Function *
F,
const Spec *Begin,
1178 for (
User *U :
F->users())
1179 if (
auto *CS = dyn_cast<CallBase>(U);
1180 CS && CS->getCalledFunction() ==
F &&
1184 unsigned NCallsLeft = ToUpdate.
size();
1186 bool ShouldDecrementCount = CS->getFunction() ==
F;
1189 const Spec *BestSpec =
nullptr;
1191 if (!S.Clone || (BestSpec && S.Score <= BestSpec->
Score))
1195 unsigned ArgNo = Arg.Formal->getArgNo();
1196 return getCandidateConstant(CS->getArgOperand(ArgNo)) != Arg.Actual;
1206 CS->setCalledFunction(BestSpec->
Clone);
1207 ShouldDecrementCount =
true;
1210 if (ShouldDecrementCount)
1218 FullySpecialized.insert(
F);
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
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 > 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 > 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 > 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< 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"))
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 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 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 > 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 > 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< 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< bool > SpecializeOnAddress("funcspec-on-address", cl::init(false), cl::Hidden, cl::desc("Enable function specialization on the address of global values"))
static unsigned getCostValue(const Cost &C)
Get the unsigned Value of given Cost object.
mir Rename Register Operands
uint64_t IntrinsicInst * II
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
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
Type * getAllocatedType() const
Return the type that is being allocated by the instruction.
void clear(IRUnitT &IR, llvm::StringRef Name)
Clear any cached analysis results for a single unit of IR.
This class represents an incoming formal argument to a Function.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
LLVM Basic Block Representation.
Conditional or Unconditional Branch instruction.
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
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.
ValueT lookup(const_arg_type_t< KeyT > Val) const
lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...
iterator find(const_arg_type_t< KeyT > Val)
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
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 ...
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
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).
Represents the cost of inlining a function.
int getCostDelta() const
Get the cost delta from the threshold for inlining.
Cost getLatencySavingsForKnownConstants()
Compute the latency savings from replacing all arguments with constants for a specialization candidat...
Cost getCodeSizeSavingsForArg(Argument *A, Constant *C)
Compute the codesize savings for replacing argument A with constant C.
Cost getCodeSizeSavingsFromPendingPHIs()
bool isBlockExecutable(BasicBlock *BB) const
void visit(Iterator Start, Iterator End)
An instruction for reading from memory.
StringRef getName() const
Get a short "name" for the module.
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.
SCCPSolver - This interface class is a general purpose solver for Sparse Conditional Constant Propaga...
void resetLatticeValueFor(CallBase *Call)
Invalidate the Lattice Value of Call and its users after specializing the call.
bool isStructLatticeConstant(Function *F, StructType *STy)
void addTrackedFunction(Function *F)
addTrackedFunction - If the SCCP solver is supposed to track calls into and out of the specified func...
void solveWhileResolvedUndefsIn(Module &M)
void addArgumentTrackedFunction(Function *F)
void solveWhileResolvedUndefs()
std::vector< ValueLatticeElement > getStructLatticeValueFor(Value *V) const
Constant * getConstantOrNull(Value *V) const
Return either a Constant or nullptr for a given Value.
const ValueLatticeElement & getLatticeValueFor(Value *V) const
bool isBlockExecutable(BasicBlock *BB) const
bool markBlockExecutable(BasicBlock *BB)
markBlockExecutable - This method can be used by clients to mark all of the blocks that are known to ...
void setLatticeValueForSpecializationArguments(Function *F, const SmallVectorImpl< ArgInfo > &Args)
Set the Lattice Value for the arguments of a specialization F.
const MapVector< Function *, ValueLatticeElement > & getTrackedRetVals() const
getTrackedRetVals - Get the inferred return value map.
static bool isOverdefined(const ValueLatticeElement &LV)
void markFunctionUnreachable(Function *F)
Mark all of the blocks in function F non-executable.
bool isArgumentTrackedFunction(Function *F)
Returns true if the given function is in the solver's set of argument-tracked functions.
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...
The instances of the Type class are immutable: once they are created, they are never changed.
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.
This class represents lattice values for constants.
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.
void setName(const Twine &Name)
Change the name of the value.
std::string getNameOrAsOperand() const
iterator_range< user_iterator > users()
const Value * stripPointerCasts() const
Strip off pointer casts, all-zero GEPs and address space casts.
StringRef getName() const
Return a constant reference to the value's name.
std::pair< iterator, bool > insert(const ValueT &V)
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
@ C
The default llvm calling convention, compatible with C.
const int IndirectCallThreshold
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
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)
bool canConstantFoldCallTo(const CallBase *Call, const Function *F)
canConstantFoldCallTo - Return true if its even possible to fold a call to the specified function.
auto successors(const MachineBasicBlock *BB)
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
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.
const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=6)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
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.
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...
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...
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)
Get an InlineCost object representing the cost of inlining this callsite.
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Constant * ConstantFoldUnaryOpOperand(unsigned Opcode, Constant *Op, const DataLayout &DL)
Attempt to constant fold a unary operation with the specified operand.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Constant * ConstantFoldInstOperands(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.
Constant * ConstantFoldCastOperand(unsigned Opcode, Constant *C, Type *DestTy, const DataLayout &DL)
Attempt to constant fold a cast with the specified operand.
Value * simplifyBinOp(unsigned Opcode, Value *LHS, Value *RHS, const SimplifyQuery &Q)
Given operands for a BinaryOperator, fold the result or return null.
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.
InlineParams getInlineParams()
Generate the parameters to tune the inline cost analysis based only on the commandline options.
auto predecessors(const MachineBasicBlock *BB)
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...
Function * CloneFunction(Function *F, ValueToValueMapTy &VMap, ClonedCodeInfo *CodeInfo=nullptr)
Return a copy of the specified function and add it to that function's module.
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 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