55#ifdef EXPENSIVE_CHECKS
65#define DEBUG_TYPE "attributor"
66#define VERBOSE_DEBUG_TYPE DEBUG_TYPE "-verbose"
69 "Determine what attributes are manifested in the IR");
71STATISTIC(NumFnDeleted,
"Number of function deleted");
73 "Number of functions with exact definitions");
75 "Number of functions without exact definitions");
76STATISTIC(NumFnShallowWrappersCreated,
"Number of shallow wrappers created");
78 "Number of abstract attributes timed out before fixpoint");
80 "Number of abstract attributes in a valid fixpoint state");
82 "Number of abstract attributes manifested in IR");
94 cl::desc(
"Maximal number of fixpoint iterations."),
100 cl::desc(
"Maximal number of callees specialized for "
105 "attributor-max-initialization-chain-length",
cl::Hidden,
107 "Maximal number of chained initializations (to avoid stack overflows)"),
113 cl::desc(
"Annotate call sites of function declarations."),
cl::init(
false));
120 cl::desc(
"Allow the Attributor to create shallow "
121 "wrappers for non-exact definitions."),
126 cl::desc(
"Allow the Attributor to use IP information "
127 "derived from non-exact functions via cloning"),
134 cl::desc(
"Comma separated list of attribute names that are "
135 "allowed to be seeded."),
139 "attributor-function-seed-allow-list",
cl::Hidden,
140 cl::desc(
"Comma separated list of function names that are "
141 "allowed to be seeded."),
147 cl::desc(
"Dump the dependency graph to dot files."),
151 "attributor-depgraph-dot-filename-prefix",
cl::Hidden,
152 cl::desc(
"The prefix used for the CallGraph dot file names."));
155 cl::desc(
"View the dependency graph."),
159 cl::desc(
"Print attribute dependencies"),
163 "attributor-enable-call-site-specific-deduction",
cl::Hidden,
164 cl::desc(
"Allow the Attributor to do call site specific analysis"),
169 cl::desc(
"Print Attributor's internal call graph"),
174 cl::desc(
"Try to simplify all loads."),
179 cl::desc(
"Should a closed world be assumed, or not. Default if not set."));
209 if (CB->hasFnAttr(Attribute::NoSync))
213 if (!CB->isConvergent() && !CB->mayReadOrWriteMemory())
225 if (!
I.mayReadOrWriteMemory())
232 const Value &V,
bool ForAnalysisOnly) {
234 if (!ForAnalysisOnly)
251 bool UsedAssumedInformation =
false;
253 if (
A.hasGlobalVariableSimplificationCallback(*GV)) {
254 auto AssumedGV =
A.getAssumedInitializerFromCallBack(
255 *GV, &QueryingAA, UsedAssumedInformation);
256 Initializer = *AssumedGV;
260 if (!GV->hasLocalLinkage()) {
263 if (!GV->hasDefinitiveInitializer() || !GV->isConstant())
268 assert(!GV->hasLocalLinkage() || GV->hasInitializer());
271 Initializer = GV->getInitializer();
275 int64_t StorageSize =
DL.getTypeStoreSize(&Ty);
276 if (StorageSize != RangePtr->
Size)
289 return I->getFunction() == Scope;
291 return A->getParent() == Scope;
297 if (
isa<Constant>(VAC.getValue()) || VAC.getValue() == VAC.getCtxI())
304 return A->getParent() == Scope;
306 if (
I->getFunction() == Scope) {
310 return DT->dominates(
I, CtxI);
312 if (CtxI &&
I->getParent() == CtxI->
getParent())
315 [&](
const Instruction &AfterI) { return &AfterI == CtxI; });
322 if (V.getType() == &Ty)
329 if (
C->isNullValue() && !Ty.isPtrOrPtrVectorTy())
331 if (
C->getType()->isPointerTy() && Ty.isPointerTy())
333 if (
C->getType()->getPrimitiveSizeInBits() >= Ty.getPrimitiveSizeInBits()) {
334 if (
C->getType()->isIntegerTy() && Ty.isIntegerTy())
336 if (
C->getType()->isFloatingPointTy() && Ty.isFloatingPointTy())
343std::optional<Value *>
345 const std::optional<Value *> &
B,
358 Ty = (*A)->getType();
368template <
bool IsLoad,
typename Ty>
374 LLVM_DEBUG(
dbgs() <<
"Trying to determine the potential copies of " <<
I
375 <<
" (only exact: " << OnlyExact <<
")\n";);
386 A.getInfoCache().getTargetLibraryInfoForFunction(*
I.getFunction());
388 auto Pred = [&](
Value &Obj) {
396 Ptr.getType()->getPointerAddressSpace()) &&
397 A.getAssumedSimplified(
Ptr, QueryingAA, UsedAssumedInformation,
401 dbgs() <<
"Underlying object is a valid nullptr, giving up.\n";);
407 LLVM_DEBUG(
dbgs() <<
"Underlying object is not supported yet: " << Obj
412 if (!GV->hasLocalLinkage() &&
413 !(GV->isConstant() && GV->hasInitializer())) {
415 "linkage, not supported yet: "
420 bool NullOnly =
true;
421 bool NullRequired =
false;
422 auto CheckForNullOnlyAndUndef = [&](std::optional<Value *> V,
424 if (!V || *V ==
nullptr)
429 NullRequired = !IsExact;
438 LLVM_DEBUG(
dbgs() <<
"Underlying object written but stored value "
439 "cannot be converted to read type: "
456 if (NewCopies.
count(V)) {
461 if (
Value *V = AdjustWrittenValueType(Acc, *
SI->getValueOperand()))
462 if (NewCopies.
count(V)) {
475 CheckForNullOnlyAndUndef(Acc.
getContent(), IsExact);
476 if (OnlyExact && !IsExact && !NullOnly &&
482 if (NullRequired && !NullOnly) {
483 LLVM_DEBUG(
dbgs() <<
"Required all `null` accesses due to non exact "
484 "one, however found non-null one: "
495 if (PotentialValueOrigins)
501 LLVM_DEBUG(
dbgs() <<
"Underlying object written through a non-store "
502 "instruction not supported yet: "
506 Value *V = AdjustWrittenValueType(Acc, *
SI->getValueOperand());
510 if (PotentialValueOrigins)
515 if (!LI && OnlyExact) {
517 "instruction not supported yet: "
528 bool HasBeenWrittenTo =
false;
533 if (!PI || !PI->forallInterferingAccesses(
536 !IsLoad, CheckAccess,
537 HasBeenWrittenTo,
Range, SkipCB)) {
540 <<
"Failed to verify all interfering accesses for underlying object: "
545 if (IsLoad && !HasBeenWrittenTo && !
Range.isUnassigned()) {
548 A, QueryingAA, Obj, *
I.getType(), TLI,
DL, &
Range);
550 LLVM_DEBUG(
dbgs() <<
"Could not determine required initial value of "
551 "underlying object, abort!\n");
554 CheckForNullOnlyAndUndef(InitialValue,
true);
555 if (NullRequired && !NullOnly) {
556 LLVM_DEBUG(
dbgs() <<
"Non exact access but initial value that is not "
557 "null or undef, abort!\n");
561 NewCopies.
insert(InitialValue);
562 if (PotentialValueOrigins)
563 NewCopyOrigins.
insert(
nullptr);
573 if (!AAUO || !AAUO->forallUnderlyingObjects(Pred)) {
575 dbgs() <<
"Underlying objects stored into could not be determined\n";);
582 for (
const auto *PI : PIs) {
583 if (!PI->getState().isAtFixpoint())
584 UsedAssumedInformation =
true;
588 if (PotentialValueOrigins)
600 A, LI, PotentialValues, &PotentialValueOrigins, QueryingAA,
601 UsedAssumedInformation, OnlyExact);
609 A,
SI, PotentialCopies,
nullptr, QueryingAA, UsedAssumedInformation,
615 bool RequireReadNone,
bool &IsKnown) {
616 if (RequireReadNone) {
628 const auto *MemLocAA =
630 if (MemLocAA && MemLocAA->isAssumedReadNone()) {
631 IsKnown = MemLocAA->isKnownReadNone();
638 const auto *MemBehaviorAA =
641 (MemBehaviorAA->isAssumedReadNone() ||
642 (!RequireReadNone && MemBehaviorAA->isAssumedReadOnly()))) {
643 IsKnown = RequireReadNone ? MemBehaviorAA->isKnownReadNone()
644 : MemBehaviorAA->isKnownReadOnly();
669 std::function<
bool(
const Function &
F)> GoBackwardsCB) {
671 dbgs() <<
"[AA] isPotentiallyReachable @" << ToFn.
getName() <<
" from "
672 << FromI <<
" [GBCB: " <<
bool(GoBackwardsCB) <<
"][#ExS: "
673 << (ExclusionSet ? std::to_string(ExclusionSet->
size()) :
"none")
676 for (
auto *ES : *ExclusionSet)
677 dbgs() << *ES <<
"\n";
685 if (GoBackwardsCB && &ToFn != FromI.
getFunction() &&
686 !GoBackwardsCB(*FromI.
getFunction()) &&
A.getInfoCache().isKernel(ToFn) &&
688 LLVM_DEBUG(
dbgs() <<
"[AA] assume kernel cannot be reached from within the "
689 "module; success\n";);
698 if (!GoBackwardsCB && !ExclusionSet) {
700 <<
" is not checked backwards and does not have an "
701 "exclusion set, abort\n");
709 while (!Worklist.
empty()) {
711 if (!Visited.
insert(CurFromI).second)
715 if (FromFn == &ToFn) {
718 LLVM_DEBUG(
dbgs() <<
"[AA] check " << *ToI <<
" from " << *CurFromI
719 <<
" intraprocedurally\n");
722 bool Result = !ReachabilityAA || ReachabilityAA->isAssumedReachable(
723 A, *CurFromI, *ToI, ExclusionSet);
725 << (Result ?
"can potentially " :
"cannot ") <<
"reach "
726 << *ToI <<
" [Intra]\n");
736 Result = !ToReachabilityAA || ToReachabilityAA->isAssumedReachable(
737 A, EntryI, *ToI, ExclusionSet);
739 <<
" " << (Result ?
"can potentially " :
"cannot ")
740 <<
"reach @" << *ToI <<
" [ToFn]\n");
748 Result = !FnReachabilityAA || FnReachabilityAA->instructionCanReach(
749 A, *CurFromI, ToFn, ExclusionSet);
751 <<
" " << (Result ?
"can potentially " :
"cannot ")
752 <<
"reach @" << ToFn.
getName() <<
" [FromFn]\n");
761 bool Result = !ReachabilityAA || ReachabilityAA->isAssumedReachable(
762 A, *CurFromI, Ret, ExclusionSet);
764 << (Result ?
"can potentially " :
"cannot ") <<
"reach "
765 << Ret <<
" [Intra]\n");
770 bool UsedAssumedInformation =
false;
771 if (
A.checkForAllInstructions(ReturnInstCB, FromFn, &QueryingAA,
772 {Instruction::Ret}, UsedAssumedInformation)) {
777 if (!GoBackwardsCB) {
779 <<
" is not checked backwards, abort\n");
785 if (!GoBackwardsCB(*FromFn))
792 CallBase *CB = ACS.getInstruction();
804 Result = !
A.checkForAllCallSites(CheckCallSite, *FromFn,
806 &QueryingAA, UsedAssumedInformation);
808 LLVM_DEBUG(
dbgs() <<
"[AA] stepping back to call sites from " << *CurFromI
809 <<
" in @" << FromFn->
getName()
810 <<
" failed, give up\n");
814 LLVM_DEBUG(
dbgs() <<
"[AA] stepped back to call sites from " << *CurFromI
815 <<
" in @" << FromFn->
getName()
816 <<
" worklist size is: " << Worklist.
size() <<
"\n");
825 std::function<
bool(
const Function &
F)> GoBackwardsCB) {
827 return ::isPotentiallyReachable(
A, FromI, &ToI, *ToFn, QueryingAA,
828 ExclusionSet, GoBackwardsCB);
835 std::function<
bool(
const Function &
F)> GoBackwardsCB) {
836 return ::isPotentiallyReachable(
A, FromI,
nullptr, ToFn, QueryingAA,
837 ExclusionSet, GoBackwardsCB);
848 dbgs() <<
"[AA] Object '" << Obj
849 <<
"' is thread local; stack objects are thread local.\n");
852 bool IsKnownNoCapture;
857 << (IsAssumedNoCapture ?
"" :
"not") <<
" thread local; "
858 << (IsAssumedNoCapture ?
"non-" :
"")
859 <<
"captured stack object.\n");
860 return IsAssumedNoCapture;
863 if (GV->isConstant()) {
865 <<
"' is thread local; constant global\n");
868 if (GV->isThreadLocal()) {
870 <<
"' is thread local; thread local global\n");
875 if (
A.getInfoCache().targetIsGPU()) {
879 <<
"' is thread local; GPU local memory\n");
885 <<
"' is thread local; GPU constant memory\n");
890 LLVM_DEBUG(
dbgs() <<
"[AA] Object '" << Obj <<
"' is not thread local\n");
896 if (!
I.mayHaveSideEffects() && !
I.mayReadFromMemory())
901 auto AddLocationPtr = [&](std::optional<MemoryLocation>
Loc) {
904 dbgs() <<
"[AA] Access to unknown location; -> requires barriers\n");
933 auto Pred = [&](
Value &Obj) {
937 <<
"'; -> requires barrier\n");
943 if (!UnderlyingObjsAA || !UnderlyingObjsAA->forallUnderlyingObjects(Pred))
968 AB.addAttribute(Kind);
982 if (!ForceReplace && Kind == Attribute::Memory) {
986 AB.addMemoryAttr(ME);
993 AB.addAttribute(Attr);
1000 AB.addAttribute(Attr);
1021 std::optional<Argument *> CBCandidateArg;
1025 for (
const Use *U : CallbackUses) {
1039 "ACS mapped into var-args arguments!");
1040 if (CBCandidateArg) {
1041 CBCandidateArg =
nullptr;
1049 if (CBCandidateArg && *CBCandidateArg)
1050 return *CBCandidateArg;
1055 if (Callee && Callee->arg_size() >
unsigned(ArgNo))
1056 return Callee->getArg(ArgNo);
1070 LLVM_DEBUG(
dbgs() <<
"[Attributor] Update " << HasChanged <<
" " << *
this
1080 InfoCache(InfoCache), Configuration(Configuration) {
1084 if (Fn->hasAddressTaken(
nullptr,
1090 InfoCache.IndirectlyCallableFunctions.push_back(Fn);
1097 "Did expect a valid position!");
1114 unsigned AttrsSize = Attrs.size();
1117 for (
const auto &It : A2K)
1120 return AttrsSize != Attrs.size();
1123template <
typename DescTy>
1129 if (AttrDescs.
empty())
1141 auto It = AttrsMap.find(AttrListAnchor);
1142 if (It == AttrsMap.end())
1145 AL = It->getSecond();
1151 AttrBuilder AB(Ctx);
1154 for (
const DescTy &AttrDesc : AttrDescs)
1155 if (CB(AttrDesc, AS, AM, AB))
1161 AL = AL.removeAttributesAtIndex(Ctx, AttrIdx, AM);
1162 AL = AL.addAttributesAtIndex(Ctx, AttrIdx, AB);
1163 AttrsMap[AttrListAnchor] = AL;
1169 bool IgnoreSubsumingPositions,
1171 bool Implied =
false;
1172 bool HasAttr =
false;
1175 if (AttrSet.hasAttribute(Kind)) {
1176 Implied |= Kind != ImpliedAttributeKind;
1182 updateAttrMap<Attribute::AttrKind>(EquivIRP, AttrKinds, HasAttrCB);
1188 if (IgnoreSubsumingPositions)
1205 ImpliedAttributeKind)});
1212 bool IgnoreSubsumingPositions) {
1216 if (AttrSet.hasAttribute(Kind))
1217 Attrs.push_back(AttrSet.getAttribute(Kind));
1221 updateAttrMap<Attribute::AttrKind>(EquivIRP, AttrKinds, CollectAttrCB);
1225 if (IgnoreSubsumingPositions)
1236 if (!AttrSet.hasAttribute(Kind))
1238 AM.addAttribute(Kind);
1241 return updateAttrMap<Attribute::AttrKind>(IRP, AttrKinds, RemoveAttrCB);
1248 if (!AttrSet.hasAttribute(Attr))
1250 AM.addAttribute(Attr);
1254 return updateAttrMap<StringRef>(IRP, Attrs, RemoveAttrCB);
1259 bool ForceReplace) {
1265 return updateAttrMap<Attribute>(IRP, Attrs, AddAttrCB);
1273 IRPositions.emplace_back(IRP);
1277 auto CanIgnoreOperandBundles = [](
const CallBase &CB) {
1293 assert(CB &&
"Expected call site!");
1296 if (!CB->hasOperandBundles() || CanIgnoreOperandBundles(*CB))
1301 assert(CB &&
"Expected call site!");
1304 if (!CB->hasOperandBundles() || CanIgnoreOperandBundles(*CB)) {
1309 for (
const Argument &Arg : Callee->args())
1310 if (Arg.hasReturnedAttr()) {
1311 IRPositions.emplace_back(
1313 IRPositions.emplace_back(
1322 assert(CB &&
"Expected call site!");
1325 if (!CB->hasOperandBundles() || CanIgnoreOperandBundles(*CB)) {
1339void IRPosition::verify() {
1340#ifdef EXPENSIVE_CHECKS
1343 assert((CBContext ==
nullptr) &&
1344 "Invalid position must not have CallBaseContext!");
1346 "Expected a nullptr for an invalid position!");
1350 "Expected specialized kind for argument values!");
1354 "Expected function for a 'returned' position!");
1356 "Associated value mismatch!");
1359 assert((CBContext ==
nullptr) &&
1360 "'call site returned' position must not have CallBaseContext!");
1362 "Expected call base for 'call site returned' position!");
1364 "Associated value mismatch!");
1367 assert((CBContext ==
nullptr) &&
1368 "'call site function' position must not have CallBaseContext!");
1370 "Expected call base for 'call site function' position!");
1372 "Associated value mismatch!");
1376 "Expected function for a 'function' position!");
1378 "Associated value mismatch!");
1382 "Expected argument for a 'argument' position!");
1384 "Associated value mismatch!");
1387 assert((CBContext ==
nullptr) &&
1388 "'call site argument' position must not have CallBaseContext!");
1389 Use *U = getAsUsePtr();
1391 assert(U &&
"Expected use for a 'call site argument' position!");
1393 "Expected call base user for a 'call site argument' position!");
1395 "Expected call base argument operand for a 'call site argument' "
1399 "Argument number mismatch!");
1407std::optional<Constant *>
1410 bool &UsedAssumedInformation) {
1414 for (
auto &CB : SimplificationCallbacks.lookup(IRP)) {
1415 std::optional<Value *> SimplifiedV = CB(IRP, &
AA, UsedAssumedInformation);
1417 return std::nullopt;
1427 UsedAssumedInformation)) {
1429 return std::nullopt;
1443 for (
auto &CB : SimplificationCallbacks.lookup(IRP))
1444 return CB(IRP,
AA, UsedAssumedInformation);
1450 return std::nullopt;
1463 bool &UsedAssumedInformation,
bool RecurseForSelectAndPHI) {
1467 while (!Worklist.
empty()) {
1473 int NV = Values.
size();
1474 const auto &SimplificationCBs = SimplificationCallbacks.lookup(IRP);
1475 for (
const auto &CB : SimplificationCBs) {
1476 std::optional<Value *> CBResult = CB(IRP,
AA, UsedAssumedInformation);
1477 if (!CBResult.has_value())
1479 Value *V = *CBResult;
1488 if (SimplificationCBs.empty()) {
1491 const auto *PotentialValuesAA =
1493 if (PotentialValuesAA &&
1494 PotentialValuesAA->getAssumedSimplifiedValues(*
this, Values, S)) {
1495 UsedAssumedInformation |= !PotentialValuesAA->isAtFixpoint();
1504 if (!RecurseForSelectAndPHI)
1507 for (
int I = NV, E = Values.
size();
I < E; ++
I) {
1508 Value *V = Values[
I].getValue();
1511 if (!Seen.
insert(V).second)
1514 Values[
I] = Values[E - 1];
1528 bool &UsedAssumedInformation) {
1536 if (!Arg->hasPointeeInMemoryValueAttr())
1546 for (
auto &It : AAMap) {
1548 AA->~AbstractAttribute();
1554 bool &UsedAssumedInformation,
1555 bool CheckBBLivenessOnly,
DepClassTy DepClass) {
1556 if (!Configuration.UseLiveness)
1562 CheckBBLivenessOnly, DepClass);
1568 bool &UsedAssumedInformation,
1569 bool CheckBBLivenessOnly,
DepClassTy DepClass) {
1570 if (!Configuration.UseLiveness)
1575 UsedAssumedInformation, CheckBBLivenessOnly, DepClass);
1580 if (CB->isArgOperand(&U)) {
1584 UsedAssumedInformation, CheckBBLivenessOnly,
1590 UsedAssumedInformation, CheckBBLivenessOnly, DepClass);
1594 UsedAssumedInformation, CheckBBLivenessOnly, DepClass);
1596 if (!CheckBBLivenessOnly &&
SI->getPointerOperand() != U.get()) {
1604 UsedAssumedInformation =
true;
1611 UsedAssumedInformation, CheckBBLivenessOnly, DepClass);
1617 bool &UsedAssumedInformation,
1618 bool CheckBBLivenessOnly,
DepClassTy DepClass,
1619 bool CheckForDeadStore) {
1620 if (!Configuration.UseLiveness)
1625 if (ManifestAddedBlocks.contains(
I.getParent()))
1634 if (!FnLivenessAA || QueryingAA == FnLivenessAA)
1638 if (CheckBBLivenessOnly ? FnLivenessAA->
isAssumedDead(
I.getParent())
1643 UsedAssumedInformation =
true;
1647 if (CheckBBLivenessOnly)
1655 if (!IsDeadAA || QueryingAA == IsDeadAA)
1662 UsedAssumedInformation =
true;
1670 UsedAssumedInformation =
true;
1680 bool &UsedAssumedInformation,
1681 bool CheckBBLivenessOnly,
DepClassTy DepClass) {
1682 if (!Configuration.UseLiveness)
1693 isAssumedDead(*CtxI, QueryingAA, FnLivenessAA, UsedAssumedInformation,
1698 if (CheckBBLivenessOnly)
1711 if (!IsDeadAA || QueryingAA == IsDeadAA)
1718 UsedAssumedInformation =
true;
1729 if (!Configuration.UseLiveness)
1737 if (!FnLivenessAA || QueryingAA == FnLivenessAA)
1753 return Pred(Callee);
1757 if (!CallEdgesAA || CallEdgesAA->hasUnknownCallee())
1760 const auto &Callees = CallEdgesAA->getOptimisticEdges();
1761 return Pred(Callees.getArrayRef());
1771 bool CheckBBLivenessOnly,
DepClassTy LivenessDepClass,
1772 bool IgnoreDroppableUses,
1777 if (!CB(*
this, &QueryingAA))
1791 auto AddUsers = [&](
const Value &V,
const Use *OldUse) {
1792 for (
const Use &UU : V.uses()) {
1793 if (OldUse && EquivalentUseCB && !EquivalentUseCB(*OldUse, UU)) {
1795 "rejected by the equivalence call back: "
1805 AddUsers(V,
nullptr);
1808 <<
" initial uses to check\n");
1811 const auto *LivenessAA =
1816 while (!Worklist.
empty()) {
1822 dbgs() <<
"[Attributor] Check use: " << **U <<
" in " << Fn->getName()
1825 dbgs() <<
"[Attributor] Check use: " << **U <<
" in " << *U->getUser()
1828 bool UsedAssumedInformation =
false;
1829 if (
isAssumedDead(*U, &QueryingAA, LivenessAA, UsedAssumedInformation,
1830 CheckBBLivenessOnly, LivenessDepClass)) {
1832 dbgs() <<
"[Attributor] Dead use, skip!\n");
1835 if (IgnoreDroppableUses && U->getUser()->isDroppable()) {
1837 dbgs() <<
"[Attributor] Droppable user, skip!\n");
1842 if (&
SI->getOperandUse(0) == U) {
1843 if (!Visited.
insert(U).second)
1847 *
this, *
SI, PotentialCopies, QueryingAA, UsedAssumedInformation,
1851 <<
"[Attributor] Value is stored, continue with "
1852 << PotentialCopies.
size()
1853 <<
" potential copies instead!\n");
1854 for (
Value *PotentialCopy : PotentialCopies)
1855 if (!AddUsers(*PotentialCopy, U))
1862 bool Follow =
false;
1863 if (!Pred(*U, Follow))
1868 User &Usr = *U->getUser();
1869 AddUsers(Usr,
nullptr);
1877 bool RequireAllCallSites,
1878 bool &UsedAssumedInformation) {
1884 if (!AssociatedFunction) {
1885 LLVM_DEBUG(
dbgs() <<
"[Attributor] No function associated with " << IRP
1891 &QueryingAA, UsedAssumedInformation);
1896 bool RequireAllCallSites,
1898 bool &UsedAssumedInformation,
1899 bool CheckPotentiallyDead) {
1903 <<
"[Attributor] Function " << Fn.
getName()
1904 <<
" has no internal linkage, hence not all call sites are known\n");
1909 if (!CB(*
this, QueryingAA))
1913 for (
unsigned u = 0; u <
Uses.size(); ++u) {
1917 dbgs() <<
"[Attributor] Check use: " << Fn->
getName() <<
" in "
1918 << *U.getUser() <<
"\n";
1920 dbgs() <<
"[Attributor] Check use: " << *U <<
" in " << *U.getUser()
1923 if (!CheckPotentiallyDead &&
1924 isAssumedDead(U, QueryingAA,
nullptr, UsedAssumedInformation,
1927 dbgs() <<
"[Attributor] Dead use, skip!\n");
1931 if (CE->isCast() && CE->getType()->isPointerTy()) {
1933 dbgs() <<
"[Attributor] Use, is constant cast expression, add "
1934 << CE->getNumUses() <<
" uses of that expression instead!\n";
1936 for (
const Use &CEU : CE->uses())
1937 Uses.push_back(&CEU);
1945 <<
" has non call site use " << *U.get() <<
" in "
1946 << *U.getUser() <<
"\n");
1950 const Use *EffectiveUse =
1953 if (!RequireAllCallSites) {
1954 LLVM_DEBUG(
dbgs() <<
"[Attributor] User " << *EffectiveUse->getUser()
1955 <<
" is not a call of " << Fn.
getName()
1959 LLVM_DEBUG(
dbgs() <<
"[Attributor] User " << *EffectiveUse->getUser()
1960 <<
" is an invalid use of " << Fn.
getName() <<
"\n");
1968 unsigned MinArgsParams =
1970 for (
unsigned u = 0; u < MinArgsParams; ++u) {
1974 dbgs() <<
"[Attributor] Call site / callee argument type mismatch ["
1975 << u <<
"@" << Fn.
getName() <<
": "
1985 LLVM_DEBUG(
dbgs() <<
"[Attributor] Call site callback failed for "
1993bool Attributor::shouldPropagateCallBaseContext(
const IRPosition &IRP) {
2003 bool RecurseForSelectAndPHI) {
2007 if (!AssociatedFunction)
2010 bool UsedAssumedInformation =
false;
2014 UsedAssumedInformation, RecurseForSelectAndPHI))
2018 return Pred(*VAC.getValue());
2026 bool &UsedAssumedInformation,
bool CheckBBLivenessOnly =
false,
2027 bool CheckPotentiallyDead =
false) {
2028 for (
unsigned Opcode : Opcodes) {
2030 auto *Insts = OpcodeInstMap.
lookup(Opcode);
2036 if (
A && !CheckPotentiallyDead &&
2038 UsedAssumedInformation, CheckBBLivenessOnly)) {
2040 dbgs() <<
"[Attributor] Instruction " << *
I
2041 <<
" is potentially dead, skip!\n";);
2056 bool &UsedAssumedInformation,
2057 bool CheckBBLivenessOnly,
2058 bool CheckPotentiallyDead) {
2064 const auto *LivenessAA =
2065 CheckPotentiallyDead && QueryingAA
2069 auto &OpcodeInstMap = InfoCache.getOpcodeInstMapForFunction(*Fn);
2071 LivenessAA, Opcodes, UsedAssumedInformation,
2072 CheckBBLivenessOnly, CheckPotentiallyDead))
2081 bool &UsedAssumedInformation,
2082 bool CheckBBLivenessOnly,
2083 bool CheckPotentiallyDead) {
2087 UsedAssumedInformation, CheckBBLivenessOnly,
2088 CheckPotentiallyDead);
2093 bool &UsedAssumedInformation) {
2096 const Function *AssociatedFunction =
2098 if (!AssociatedFunction)
2102 const auto *LivenessAA =
2106 InfoCache.getReadOrWriteInstsForFunction(*AssociatedFunction)) {
2109 UsedAssumedInformation))
2119void Attributor::runTillFixpoint() {
2123 <<
" abstract attributes.\n");
2128 unsigned IterationCounter = 1;
2129 unsigned MaxIterations =
2139 LLVM_DEBUG(
dbgs() <<
"\n\n[Attributor] #Iteration: " << IterationCounter
2140 <<
", Worklist size: " << Worklist.
size() <<
"\n");
2145 for (
unsigned u = 0; u < InvalidAAs.
size(); ++u) {
2150 dbgs() <<
"[Attributor] InvalidAA: " << *InvalidAA
2151 <<
" has " << InvalidAA->
Deps.
size()
2152 <<
" required & optional dependences\n");
2153 for (
auto &DepIt : InvalidAA->
Deps) {
2157 dbgs() <<
" - recompute: " << *DepAA);
2162 <<
" - invalidate: " << *DepAA);
2166 InvalidAAs.
insert(DepAA);
2175 for (AbstractAttribute *ChangedAA : ChangedAAs) {
2176 for (
auto &DepIt : ChangedAA->Deps)
2178 ChangedAA->Deps.clear();
2181 LLVM_DEBUG(
dbgs() <<
"[Attributor] #Iteration: " << IterationCounter
2182 <<
", Worklist+Dependent size: " << Worklist.
size()
2191 for (AbstractAttribute *AA : Worklist) {
2192 const auto &AAState = AA->getState();
2193 if (!AAState.isAtFixpoint())
2195 ChangedAAs.push_back(AA);
2199 if (!AAState.isValidState())
2205 ChangedAAs.append(DG.SyntheticRoot.begin() + NumAAs,
2206 DG.SyntheticRoot.end());
2211 Worklist.insert_range(ChangedAAs);
2212 Worklist.insert_range(QueryAAsAwaitingUpdate);
2213 QueryAAsAwaitingUpdate.clear();
2215 }
while (!Worklist.empty() && (IterationCounter++ < MaxIterations));
2217 if (IterationCounter > MaxIterations && !Functions.empty()) {
2218 auto Remark = [&](OptimizationRemarkMissed ORM) {
2219 return ORM <<
"Attributor did not reach a fixpoint after "
2220 <<
ore::NV(
"Iterations", MaxIterations) <<
" iterations.";
2226 LLVM_DEBUG(
dbgs() <<
"\n[Attributor] Fixpoint iteration done after: "
2227 << IterationCounter <<
"/" << MaxIterations
2228 <<
" iterations\n");
2235 SmallPtrSet<AbstractAttribute *, 32> Visited;
2236 for (
unsigned u = 0;
u < ChangedAAs.size();
u++) {
2237 AbstractAttribute *ChangedAA = ChangedAAs[
u];
2238 if (!Visited.
insert(ChangedAA).second)
2241 AbstractState &State = ChangedAA->
getState();
2245 NumAttributesTimedOut++;
2248 for (
auto &DepIt : ChangedAA->
Deps)
2254 if (!Visited.
empty())
2255 dbgs() <<
"\n[Attributor] Finalized " << Visited.
size()
2256 <<
" abstract attributes.\n";
2262 "Non-query AAs should not be required to register for updates!");
2263 QueryAAsAwaitingUpdate.insert(&
AA);
2270 unsigned NumManifested = 0;
2271 unsigned NumAtFixpoint = 0;
2281 if (!State.isAtFixpoint())
2282 State.indicateOptimisticFixpoint();
2285 if (
AA->hasCallBaseContext())
2288 if (!State.isValidState())
2291 if (
AA->getCtxI() && !
isRunOn(*
AA->getAnchorScope()))
2295 bool UsedAssumedInformation =
false;
2306 AA->trackStatistics();
2307 LLVM_DEBUG(
dbgs() <<
"[Attributor] Manifest " << LocalChange <<
" : " << *
AA
2310 ManifestChange = ManifestChange | LocalChange;
2316 (void)NumManifested;
2317 (void)NumAtFixpoint;
2318 LLVM_DEBUG(
dbgs() <<
"\n[Attributor] Manifested " << NumManifested
2319 <<
" arguments while " << NumAtFixpoint
2320 <<
" were in a valid fixpoint state\n");
2322 NumAttributesManifested += NumManifested;
2323 NumAttributesValidFixpoint += NumAtFixpoint;
2328 for (
unsigned u = 0; u < NumFinalAAs; ++u)
2332 errs() <<
"Unexpected abstract attribute: "
2336 .getAssociatedValue()
2340 "remain unchanged!");
2343 for (
auto &It : AttrsMap) {
2344 AttributeList &
AL = It.getSecond();
2345 const IRPosition &IRP =
2348 : IRPosition::callsite_function(*
cast<CallBase>(It.getFirst()));
2352 return ManifestChange;
2355void Attributor::identifyDeadInternalFunctions() {
2357 if (!Configuration.DeleteFns)
2375 for (Function *
F : Functions)
2376 if (
F->hasLocalLinkage() && (
isModulePass() || !TLI->getLibFunc(*
F, LF)))
2379 SmallPtrSet<Function *, 8> LiveInternalFns;
2380 bool FoundLiveInternal =
true;
2381 while (FoundLiveInternal) {
2382 FoundLiveInternal =
false;
2383 for (Function *&
F : InternalFns) {
2387 bool UsedAssumedInformation =
false;
2389 [&](AbstractCallSite ACS) {
2391 return ToBeDeletedFunctions.count(Callee) ||
2392 (Functions.count(Callee) &&
Callee->hasLocalLinkage() &&
2393 !LiveInternalFns.
count(Callee));
2395 *
F,
true,
nullptr, UsedAssumedInformation)) {
2401 FoundLiveInternal =
true;
2405 for (Function *
F : InternalFns)
2407 ToBeDeletedFunctions.insert(
F);
2411 TimeTraceScope TimeScope(
"Attributor::cleanupIR");
2414 << ToBeDeletedFunctions.size() <<
" functions and "
2415 << ToBeDeletedBlocks.size() <<
" blocks and "
2416 << ToBeDeletedInsts.size() <<
" instructions and "
2417 << ToBeChangedValues.size() <<
" values and "
2418 << ToBeChangedUses.size() <<
" uses. To insert "
2419 << ToBeChangedToUnreachableInsts.size()
2420 <<
" unreachables.\n"
2421 <<
"Preserve manifest added " << ManifestAddedBlocks.size()
2427 auto ReplaceUse = [&](
Use *
U,
Value *NewV) {
2432 const auto &
Entry = ToBeChangedValues.lookup(NewV);
2440 "Cannot replace an instruction outside the current SCC!");
2446 if (CI->isMustTailCall() && !ToBeDeletedInsts.count(CI))
2451 for (
auto &Arg : RI->getFunction()->args())
2452 Arg.removeAttr(Attribute::Returned);
2456 <<
" instead of " << *OldV <<
"\n");
2460 CGModifiedFunctions.insert(
I->getFunction());
2467 if (CB->isArgOperand(U)) {
2468 unsigned Idx = CB->getArgOperandNo(U);
2469 CB->removeParamAttr(Idx, Attribute::NoUndef);
2471 if (Callee &&
Callee->arg_size() > Idx)
2472 Callee->removeParamAttr(Idx, Attribute::NoUndef);
2478 ToBeChangedToUnreachableInsts.insert(UserI);
2485 for (
auto &It : ToBeChangedUses) {
2487 Value *NewV = It.second;
2488 ReplaceUse(U, NewV);
2492 for (
auto &It : ToBeChangedValues) {
2493 Value *OldV = It.first;
2494 auto [NewV,
Done] = It.second;
2496 for (
auto &U : OldV->
uses())
2497 if (
Done || !
U.getUser()->isDroppable())
2499 for (Use *U :
Uses) {
2503 ReplaceUse(U, NewV);
2507 for (
const auto &V : InvokeWithDeadSuccessor)
2510 "Cannot replace an invoke outside the current SCC!");
2511 bool UnwindBBIsDead =
II->hasFnAttr(Attribute::NoUnwind);
2512 bool NormalBBIsDead =
II->hasFnAttr(Attribute::NoReturn);
2513 bool Invoke2CallAllowed =
2515 assert((UnwindBBIsDead || NormalBBIsDead) &&
2516 "Invoke does not have dead successors!");
2519 if (UnwindBBIsDead) {
2521 if (Invoke2CallAllowed) {
2526 ToBeChangedToUnreachableInsts.insert(NormalNextIP);
2528 assert(NormalBBIsDead &&
"Broken invariant!");
2531 ToBeChangedToUnreachableInsts.insert(&NormalDestBB->
front());
2534 for (Instruction *
I : TerminatorsToFold) {
2536 "Cannot replace a terminator outside the current SCC!");
2537 CGModifiedFunctions.insert(
I->getFunction());
2540 for (
const auto &V : ToBeChangedToUnreachableInsts)
2545 "Cannot replace an instruction outside the current SCC!");
2546 CGModifiedFunctions.insert(
I->getFunction());
2550 for (
const auto &V : ToBeDeletedInsts) {
2554 "Cannot delete an instruction outside the current SCC!");
2555 I->dropDroppableUses();
2556 CGModifiedFunctions.insert(
I->getFunction());
2557 if (!
I->getType()->isVoidTy())
2562 I->eraseFromParent();
2569 dbgs() <<
"[Attributor] DeadInsts size: " << DeadInsts.
size() <<
"\n";
2570 for (
auto &
I : DeadInsts)
2572 dbgs() <<
" - " << *
I <<
"\n";
2577 if (
unsigned NumDeadBlocks = ToBeDeletedBlocks.size()) {
2578 SmallVector<BasicBlock *, 8> ToBeDeletedBBs;
2579 ToBeDeletedBBs.
reserve(NumDeadBlocks);
2580 for (BasicBlock *BB : ToBeDeletedBlocks) {
2582 "Cannot delete a block outside the current SCC!");
2583 CGModifiedFunctions.insert(BB->
getParent());
2585 if (ManifestAddedBlocks.contains(BB))
2595 identifyDeadInternalFunctions();
2598 ChangeStatus ManifestChange = rewriteFunctionSignatures(CGModifiedFunctions);
2600 for (Function *Fn : CGModifiedFunctions)
2601 if (!ToBeDeletedFunctions.count(Fn) && Functions.count(Fn))
2602 Configuration.CGUpdater.reanalyzeFunction(*Fn);
2604 for (Function *Fn : ToBeDeletedFunctions) {
2605 if (!Functions.count(Fn))
2607 Configuration.CGUpdater.removeFunction(*Fn);
2610 if (!ToBeChangedUses.empty())
2613 if (!ToBeChangedToUnreachableInsts.empty())
2616 if (!ToBeDeletedFunctions.empty())
2619 if (!ToBeDeletedBlocks.empty())
2622 if (!ToBeDeletedInsts.empty())
2625 if (!InvokeWithDeadSuccessor.empty())
2628 if (!DeadInsts.empty())
2631 NumFnDeleted += ToBeDeletedFunctions.size();
2633 LLVM_DEBUG(
dbgs() <<
"[Attributor] Deleted " << ToBeDeletedFunctions.size()
2634 <<
" functions after manifest.\n");
2636#ifdef EXPENSIVE_CHECKS
2637 for (Function *
F : Functions) {
2638 if (ToBeDeletedFunctions.count(
F))
2644 return ManifestChange;
2649 AttributorCallGraph ACallGraph(*
this);
2654 Phase = AttributorPhase::UPDATE;
2667 Phase = AttributorPhase::MANIFEST;
2670 Phase = AttributorPhase::CLEANUP;
2676 return ManifestChange | CleanupChange;
2681 return AA.getName().str() +
2682 std::to_string(
AA.getIRPosition().getPositionKind());
2685 "We can update AA only in the update stage!");
2688 DependenceVector DV;
2689 DependenceStack.push_back(&DV);
2691 auto &AAState =
AA.getState();
2693 bool UsedAssumedInformation =
false;
2696 CS =
AA.update(*
this);
2698 if (!
AA.isQueryAA() && DV.empty() && !
AA.getState().isAtFixpoint()) {
2705 RerunCS =
AA.update(*
this);
2711 AAState.indicateOptimisticFixpoint();
2714 if (!AAState.isAtFixpoint())
2715 rememberDependences();
2719 DependenceVector *PoppedDV = DependenceStack.pop_back_val();
2721 assert(PoppedDV == &DV &&
"Inconsistent usage of the dependence stack!");
2727 assert(!
F.isDeclaration() &&
"Cannot create a wrapper around a declaration!");
2736 M.getFunctionList().insert(
F.getIterator(),
Wrapper);
2741 assert(
F.use_empty() &&
"Uses remained after wrapper was created!");
2746 F.setComdat(
nullptr);
2750 F.getAllMetadata(MDs);
2751 for (
auto MDIt : MDs)
2752 Wrapper->addMetadata(MDIt.first, *MDIt.second);
2753 Wrapper->setAttributes(
F.getAttributes());
2761 Args.push_back(&Arg);
2762 Arg.setName((FArgIt++)->
getName());
2770 NumFnShallowWrappersCreated++;
2774 if (
F.isDeclaration() ||
F.hasLocalLinkage() ||
2790 return InternalizedFns[&
F];
2808 F->getName() +
".internalized");
2811 for (
auto &Arg :
F->args()) {
2812 auto ArgName = Arg.getName();
2813 NewFArgIt->setName(ArgName);
2814 VMap[&Arg] = &(*NewFArgIt++);
2829 F->getAllMetadata(MDs);
2830 for (
auto MDIt : MDs)
2834 M.getFunctionList().insert(
F->getIterator(), Copied);
2842 auto &InternalizedFn = FnMap[
F];
2843 auto IsNotInternalized = [&](
Use &U) ->
bool {
2845 return !FnMap.
lookup(CB->getCaller());
2848 F->replaceUsesWithIf(InternalizedFn, IsNotInternalized);
2857 if (!Configuration.RewriteSignatures)
2880 LLVM_DEBUG(
dbgs() <<
"[Attributor] Cannot rewrite var-args functions\n");
2886 if (FnAttributeList.hasAttrSomewhere(Attribute::Nest) ||
2887 FnAttributeList.hasAttrSomewhere(Attribute::StructRet) ||
2888 FnAttributeList.hasAttrSomewhere(Attribute::InAlloca) ||
2889 FnAttributeList.hasAttrSomewhere(Attribute::Preallocated)) {
2891 dbgs() <<
"[Attributor] Cannot rewrite due to complex attribute\n");
2896 bool UsedAssumedInformation =
false;
2898 UsedAssumedInformation,
2900 LLVM_DEBUG(
dbgs() <<
"[Attributor] Cannot rewrite all call sites\n");
2906 return !CI->isMustTailCall();
2912 auto &OpcodeInstMap = InfoCache.getOpcodeInstMapForFunction(*Fn);
2914 nullptr, {Instruction::Call},
2915 UsedAssumedInformation)) {
2916 LLVM_DEBUG(
dbgs() <<
"[Attributor] Cannot rewrite due to instructions\n");
2927 LLVM_DEBUG(
dbgs() <<
"[Attributor] Register new rewrite of " << Arg <<
" in "
2929 << ReplacementTypes.
size() <<
" replacements\n");
2931 "Cannot register an invalid rewrite");
2935 ArgumentReplacementMap[Fn];
2941 std::unique_ptr<ArgumentReplacementInfo> &ARI = ARIs[Arg.
getArgNo()];
2942 if (ARI && ARI->getNumReplacementArgs() <= ReplacementTypes.
size()) {
2943 LLVM_DEBUG(
dbgs() <<
"[Attributor] Existing rewrite is preferred\n");
2951 LLVM_DEBUG(
dbgs() <<
"[Attributor] Register new rewrite of " << Arg <<
" in "
2953 << ReplacementTypes.
size() <<
" replacements\n");
2957 std::move(CalleeRepairCB),
2958 std::move(ACSRepairCB)));
2979 for (
auto &It : ArgumentReplacementMap) {
2983 if (!Functions.count(OldFn) || ToBeDeletedFunctions.count(OldFn))
2996 if (
const std::unique_ptr<ArgumentReplacementInfo> &ARI =
2997 ARIs[Arg.getArgNo()]) {
2998 NewArgumentTypes.
append(ARI->ReplacementTypes.begin(),
2999 ARI->ReplacementTypes.end());
3000 NewArgumentAttributes.
append(ARI->getNumReplacementArgs(),
3003 NewArgumentTypes.
push_back(Arg.getType());
3005 OldFnAttributeList.getParamAttrs(Arg.getArgNo()));
3009 uint64_t LargestVectorWidth = 0;
3010 for (
auto *
I : NewArgumentTypes)
3012 LargestVectorWidth =
3013 std::max(LargestVectorWidth,
3014 VT->getPrimitiveSizeInBits().getKnownMinValue());
3017 Type *RetTy = OldFnTy->getReturnType();
3020 FunctionType *NewFnTy =
3025 << *NewFnTy <<
"\n");
3030 Functions.insert(NewFn);
3043 Ctx, OldFnAttributeList.getFnAttrs(), OldFnAttributeList.getRetAttrs(),
3044 NewArgumentAttributes));
3045 AttributeFuncs::updateMinLegalVectorWidthAttr(*NewFn, LargestVectorWidth);
3053 return !
T->isPtrOrPtrVectorTy() ||
3069 auto CallSiteReplacementCreator = [&](AbstractCallSite ACS) {
3071 const AttributeList &OldCallAttributeList = OldCB->
getAttributes();
3074 SmallVector<Value *, 16> NewArgOperands;
3076 for (
unsigned OldArgNum = 0; OldArgNum < ARIs.
size(); ++OldArgNum) {
3077 unsigned NewFirstArgNum = NewArgOperands.
size();
3078 (void)NewFirstArgNum;
3079 if (
const std::unique_ptr<ArgumentReplacementInfo> &ARI =
3081 if (ARI->ACSRepairCB)
3082 ARI->ACSRepairCB(*ARI, ACS, NewArgOperands);
3083 assert(ARI->getNumReplacementArgs() + NewFirstArgNum ==
3084 NewArgOperands.
size() &&
3085 "ACS repair callback did not provide as many operand as new "
3086 "types were registered!");
3088 NewArgOperandAttributes.
append(ARI->ReplacementTypes.size(),
3093 OldCallAttributeList.getParamAttrs(OldArgNum));
3097 assert(NewArgOperands.
size() == NewArgOperandAttributes.
size() &&
3098 "Mismatch # argument operands vs. # argument operand attributes!");
3100 "Mismatch # argument operands vs. # function arguments!");
3109 II->getUnwindDest(), NewArgOperands,
3114 NewCI->setTailCallKind(
cast<CallInst>(OldCB)->getTailCallKind());
3119 NewCB->
copyMetadata(*OldCB, {LLVMContext::MD_prof, LLVMContext::MD_dbg});
3123 Ctx, OldCallAttributeList.getFnAttrs(),
3124 OldCallAttributeList.getRetAttrs(), NewArgOperandAttributes));
3126 AttributeFuncs::updateMinLegalVectorWidthAttr(*NewCB->
getCaller(),
3127 LargestVectorWidth);
3129 CallSitePairs.
push_back({OldCB, NewCB});
3134 bool UsedAssumedInformation =
false;
3136 true,
nullptr, UsedAssumedInformation,
3139 assert(
Success &&
"Assumed call site replacement to succeed!");
3144 for (
unsigned OldArgNum = 0; OldArgNum < ARIs.
size();
3145 ++OldArgNum, ++OldFnArgIt) {
3146 if (
const std::unique_ptr<ArgumentReplacementInfo> &ARI =
3148 if (ARI->CalleeRepairCB)
3149 ARI->CalleeRepairCB(*ARI, *NewFn, NewFnArgIt);
3150 if (ARI->ReplacementTypes.empty())
3153 NewFnArgIt += ARI->ReplacementTypes.size();
3155 NewFnArgIt->
takeName(&*OldFnArgIt);
3162 for (
auto &CallSitePair : CallSitePairs) {
3163 CallBase &OldCB = *CallSitePair.first;
3164 CallBase &NewCB = *CallSitePair.second;
3166 "Cannot handle call sites with different types!");
3173 Configuration.CGUpdater.replaceFunctionWith(*OldFn, *NewFn);
3177 if (ModifiedFns.
remove(OldFn))
3178 ModifiedFns.
insert(NewFn);
3186void InformationCache::initializeInformationCache(
const Function &CF,
3193 FI.IsKernel =
F.hasFnAttribute(
"kernel");
3199 DenseMap<const Value *, std::optional<short>> AssumeUsesMap;
3204 auto AddToAssumeUsesMap = [&](
const Value &
V) ->
void {
3205 SmallVector<const Instruction *> Worklist;
3208 while (!Worklist.
empty()) {
3210 std::optional<short> &NumUses = AssumeUsesMap[
I];
3212 NumUses =
I->getNumUses();
3213 NumUses = *NumUses - 1;
3216 AssumeOnlyValues.insert(
I);
3217 for (
const Value *
Op :
I->operands())
3224 bool IsInterestingOpcode =
false;
3231 switch (
I.getOpcode()) {
3234 "New call base instruction type needs to be known in the "
3237 case Instruction::Call:
3242 AssumeOnlyValues.insert(Assume);
3244 AddToAssumeUsesMap(*
Assume->getArgOperand(0));
3246 FI.ContainsMustTailCall =
true;
3249 getFunctionInfo(*Callee).CalledViaMustTail =
true;
3252 case Instruction::CallBr:
3253 case Instruction::Invoke:
3254 case Instruction::CleanupRet:
3255 case Instruction::CatchSwitch:
3256 case Instruction::AtomicRMW:
3257 case Instruction::AtomicCmpXchg:
3258 case Instruction::Br:
3259 case Instruction::Resume:
3260 case Instruction::Ret:
3261 case Instruction::Load:
3263 case Instruction::Store:
3265 case Instruction::Alloca:
3266 case Instruction::AddrSpaceCast:
3267 IsInterestingOpcode =
true;
3269 if (IsInterestingOpcode) {
3270 auto *&Insts = FI.OpcodeInstMap[
I.getOpcode()];
3275 if (
I.mayReadOrWriteMemory())
3276 FI.RWInsts.push_back(&
I);
3279 if (
F.hasFnAttribute(Attribute::AlwaysInline) &&
3281 InlineableFunctions.insert(&
F);
3284InformationCache::FunctionInfo::~FunctionInfo() {
3287 for (
auto &It : OpcodeInstMap)
3288 It.getSecond()->~InstructionVectorTy();
3293 assert(
A.isClosedWorldModule() &&
"Cannot see all indirect callees!");
3294 return IndirectlyCallableFunctions;
3298 if (TargetTriple.isGPU())
3300 return std::nullopt;
3311 if (DependenceStack.empty())
3315 DependenceStack.back()->push_back({&FromAA, &ToAA, DepClass});
3318void Attributor::rememberDependences() {
3319 assert(!DependenceStack.empty() &&
"No dependences to remember!");
3321 for (DepInfo &DI : *DependenceStack.back()) {
3324 "Expected required or optional dependence (1 bit)!");
3331template <Attribute::AttrKind AK,
typename AAType>
3332void Attributor::checkAndQueryIRAttr(
const IRPosition &IRP, AttributeSet Attrs,
3333 bool SkipHasAttrCheck) {
3335 if (SkipHasAttrCheck || !
Attrs.hasAttribute(AK))
3336 if (!Configuration.Allowed || Configuration.Allowed->count(&AAType::ID))
3339 getOrCreateAAFor<AAType>(IRP);
3343 if (!VisitedFunctions.insert(&
F).second)
3345 if (
F.isDeclaration())
3351 InformationCache::FunctionInfo &FI = InfoCache.getFunctionInfo(
F);
3353 for (
const Use &U :
F.uses())
3355 if (CB->isCallee(&U) && CB->isMustTailCall())
3356 FI.CalledViaMustTail =
true;
3361 auto Attrs =
F.getAttributes();
3362 auto FnAttrs = Attrs.getFnAttrs();
3378 checkAndQueryIRAttr<Attribute::MustProgress, AAMustProgress>(FPos, FnAttrs);
3381 checkAndQueryIRAttr<Attribute::NoFree, AANoFree>(FPos, FnAttrs);
3384 checkAndQueryIRAttr<Attribute::WillReturn, AAWillReturn>(FPos, FnAttrs);
3387 checkAndQueryIRAttr<Attribute::NoSync, AANoSync>(FPos, FnAttrs);
3392 if (IsIPOAmendable) {
3395 checkAndQueryIRAttr<Attribute::NoUnwind, AANoUnwind>(FPos, FnAttrs);
3398 checkAndQueryIRAttr<Attribute::NoReturn, AANoReturn>(FPos, FnAttrs);
3401 checkAndQueryIRAttr<Attribute::NoRecurse, AANoRecurse>(FPos, FnAttrs);
3404 if (Attrs.hasFnAttr(Attribute::Convergent))
3425 Type *ReturnType =
F.getReturnType();
3426 if (!ReturnType->isVoidTy()) {
3434 bool UsedAssumedInformation =
false;
3439 checkAndQueryIRAttr<Attribute::NoUndef, AANoUndef>(RetPos, RetAttrs);
3441 if (ReturnType->isPointerTy()) {
3447 checkAndQueryIRAttr<Attribute::NonNull, AANonNull>(RetPos, RetAttrs);
3450 checkAndQueryIRAttr<Attribute::NoAlias, AANoAlias>(RetPos, RetAttrs);
3455 }
else if (AttributeFuncs::isNoFPClassCompatibleType(ReturnType)) {
3463 auto ArgNo = Arg.getArgNo();
3466 if (!IsIPOAmendable) {
3467 if (Arg.getType()->isPointerTy())
3469 checkAndQueryIRAttr<Attribute::NoFree, AANoFree>(ArgPos, ArgAttrs);
3476 bool UsedAssumedInformation =
false;
3484 checkAndQueryIRAttr<Attribute::NoUndef, AANoUndef>(ArgPos, ArgAttrs);
3486 if (Arg.getType()->isPointerTy()) {
3488 checkAndQueryIRAttr<Attribute::NonNull, AANonNull>(ArgPos, ArgAttrs);
3491 checkAndQueryIRAttr<Attribute::NoAlias, AANoAlias>(ArgPos, ArgAttrs);
3500 checkAndQueryIRAttr<Attribute::Captures, AANoCapture>(
3501 ArgPos, ArgAttrs,
true);
3508 checkAndQueryIRAttr<Attribute::NoFree, AANoFree>(ArgPos, ArgAttrs);
3513 }
else if (AttributeFuncs::isNoFPClassCompatibleType(Arg.getType())) {
3541 !Callee->hasMetadata(LLVMContext::MD_callback))
3544 if (!Callee->getReturnType()->isVoidTy() && !CB.use_empty()) {
3546 bool UsedAssumedInformation =
false;
3550 if (AttributeFuncs::isNoFPClassCompatibleType(Callee->getReturnType()))
3554 const AttributeList &CBAttrs = CBFnPos.
getAttrList();
3555 for (
int I = 0, E = CB.arg_size();
I < E; ++
I) {
3566 bool UsedAssumedInformation =
false;
3571 checkAndQueryIRAttr<Attribute::NoUndef, AANoUndef>(CBArgPos, CBArgAttrs);
3573 Type *ArgTy = CB.getArgOperand(
I)->getType();
3576 if (AttributeFuncs::isNoFPClassCompatibleType(ArgTy))
3583 checkAndQueryIRAttr<Attribute::NonNull, AANonNull>(CBArgPos, CBArgAttrs);
3586 checkAndQueryIRAttr<Attribute::Captures, AANoCapture>(
3587 CBArgPos, CBArgAttrs,
true);
3590 checkAndQueryIRAttr<Attribute::NoAlias, AANoAlias>(CBArgPos, CBArgAttrs);
3600 if (!CBAttrs.hasParamAttr(
I, Attribute::ReadNone))
3604 checkAndQueryIRAttr<Attribute::NoFree, AANoFree>(CBArgPos, CBArgAttrs);
3609 auto &OpcodeInstMap = InfoCache.getOpcodeInstMapForFunction(
F);
3610 [[maybe_unused]]
bool Success;
3611 bool UsedAssumedInformation =
false;
3613 nullptr, OpcodeInstMap, CallSitePred,
nullptr,
nullptr,
3614 {(
unsigned)Instruction::Invoke, (
unsigned)Instruction::CallBr,
3616 UsedAssumedInformation);
3617 assert(
Success &&
"Expected the check call to be successful!");
3641 nullptr, OpcodeInstMap, LoadStorePred,
nullptr,
nullptr,
3642 {(
unsigned)Instruction::Load, (
unsigned)Instruction::Store},
3643 UsedAssumedInformation);
3644 assert(
Success &&
"Expected the check call to be successful!");
3647 auto AAAllocationInfoPred = [&](
Instruction &
I) ->
bool {
3653 nullptr, OpcodeInstMap, AAAllocationInfoPred,
nullptr,
nullptr,
3654 {(
unsigned)Instruction::Alloca}, UsedAssumedInformation);
3655 assert(
Success &&
"Expected the check call to be successful!");
3661 return isModulePass() && Configuration.IsClosedWorldModule;
3678 return OS <<
"fn_ret";
3680 return OS <<
"cs_ret";
3688 return OS <<
"cs_arg";
3710 return OS << static_cast<const AbstractState &>(S);
3724 OS <<
"set-state(< {";
3740 OS <<
"set-state(< {";
3746 OS <<
"@" <<
F->getName() <<
"[" << int(It.second) <<
"], ";
3748 OS << *It.first.getValue() <<
"[" << int(It.second) <<
"], ";
3761 OS <<
"] for CtxI ";
3768 OS <<
"<<null inst>>";
3777 for (
const auto &DepAA :
Deps) {
3778 auto *
AA = DepAA.getPointer();
3795 OS <<
" [ <unknown> ]";
3809 bool DeleteFns,
bool IsModulePass) {
3810 if (Functions.empty())
3814 dbgs() <<
"[Attributor] Run on module with " << Functions.size()
3823 AC.IsModulePass = IsModulePass;
3824 AC.DeleteFns = DeleteFns;
3828 IndirectCalleeTrackingMap;
3830 AC.IndirectCalleeSpecializationCallback =
3835 auto &Set = IndirectCalleeTrackingMap[&CB];
3837 Set = std::make_unique<SmallPtrSet<Function *, 8>>();
3839 return Set->contains(&Callee);
3840 Set->insert(&Callee);
3850 if (!
A.isFunctionIPOAmendable(*
F))
3858 unsigned FunSize = Functions.size();
3859 for (
unsigned u = 0; u < FunSize; u++) {
3861 if (!
F->isDeclaration() && !
F->isDefinitionExact() && !
F->use_empty() &&
3864 assert(NewF &&
"Could not internalize function.");
3865 Functions.insert(NewF);
3869 for (
const Use &U : NewF->
uses())
3871 auto *CallerF = CB->getCaller();
3879 if (
F->hasExactDefinition())
3880 NumFnWithExactDefinition++;
3882 NumFnWithoutExactDefinition++;
3887 if (
F->hasLocalLinkage()) {
3889 const auto *CB = dyn_cast<CallBase>(U.getUser());
3890 return CB && CB->isCallee(&U) &&
3891 Functions.count(const_cast<Function *>(CB->getCaller()));
3898 A.identifyDefaultAbstractAttributes(*
F);
3903 LLVM_DEBUG(
dbgs() <<
"[Attributor] Done with " << Functions.size()
3904 <<
" functions, result: " <<
Changed <<
".\n");
3913 bool IsModulePass) {
3914 if (Functions.empty())
3918 dbgs() <<
"[AttributorLight] Run on module with " << Functions.size()
3927 AC.IsModulePass = IsModulePass;
3928 AC.DeleteFns =
false;
3935 AC.Allowed = &Allowed;
3936 AC.UseLiveness =
false;
3941 if (
F->hasExactDefinition())
3942 NumFnWithExactDefinition++;
3944 NumFnWithoutExactDefinition++;
3949 if (AC.UseLiveness &&
F->hasLocalLinkage()) {
3951 const auto *CB = dyn_cast<CallBase>(U.getUser());
3952 return CB && CB->isCallee(&U) &&
3953 Functions.count(const_cast<Function *>(CB->getCaller()));
3960 A.identifyDefaultAbstractAttributes(*
F);
3977 for (
auto *U :
Changed->users()) {
3980 FAM.invalidate(*
Call->getFunction(), FuncPA);
3985 LLVM_DEBUG(
dbgs() <<
"[Attributor] Done with " << Functions.size()
3986 <<
" functions, result: " <<
Changed <<
".\n");
3993 static std::atomic<int> CallTimes;
3999 Prefix =
"dep_graph";
4000 std::string Filename =
4001 Prefix +
"_" + std::to_string(CallTimes.load()) +
".dot";
4003 outs() <<
"Dependency graph dump to " << Filename <<
".\n";
4049 Functions.
insert(&
N.getFunction());
4051 if (Functions.empty())
4054 Module &M = *Functions.back()->getParent();
4105 Functions.
insert(&
N.getFunction());
4107 if (Functions.empty())
4110 Module &M = *Functions.back()->getParent();
4162 std::string AAString;
aarch64 falkor hwpf fix Falkor HW Prefetch Fix Late Phase
static unsigned getIntrinsicID(const SDNode *N)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
amdgpu aa AMDGPU Address space based Alias Analysis Wrapper
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Expand Atomic instructions
This file contains the simple types necessary to represent the attributes associated with functions a...
static cl::opt< bool > AllowShallowWrappers("attributor-allow-shallow-wrappers", cl::Hidden, cl::desc("Allow the Attributor to create shallow " "wrappers for non-exact definitions."), cl::init(false))
bool canMarkAsVisited(const User *Usr)
#define VERBOSE_DEBUG_TYPE
static cl::opt< bool > EnableHeapToStack("enable-heap-to-stack-conversion", cl::init(true), cl::Hidden)
static cl::list< std::string > SeedAllowList("attributor-seed-allow-list", cl::Hidden, cl::desc("Comma separated list of attribute names that are " "allowed to be seeded."), cl::CommaSeparated)
static bool runAttributorOnFunctions(InformationCache &InfoCache, SetVector< Function * > &Functions, AnalysisGetter &AG, CallGraphUpdater &CGUpdater, bool DeleteFns, bool IsModulePass)
}
static bool getPotentialCopiesOfMemoryValue(Attributor &A, Ty &I, SmallSetVector< Value *, 4 > &PotentialCopies, SmallSetVector< Instruction *, 4 > *PotentialValueOrigins, const AbstractAttribute &QueryingAA, bool &UsedAssumedInformation, bool OnlyExact)
static bool runAttributorLightOnFunctions(InformationCache &InfoCache, SetVector< Function * > &Functions, AnalysisGetter &AG, CallGraphUpdater &CGUpdater, FunctionAnalysisManager &FAM, bool IsModulePass)
static cl::opt< unsigned, true > MaxInitializationChainLengthX("attributor-max-initialization-chain-length", cl::Hidden, cl::desc("Maximal number of chained initializations (to avoid stack overflows)"), cl::location(MaxInitializationChainLength), cl::init(1024))
static cl::opt< unsigned > MaxSpecializationPerCB("attributor-max-specializations-per-call-base", cl::Hidden, cl::desc("Maximal number of callees specialized for " "a call base"), cl::init(UINT32_MAX))
static cl::opt< bool > SimplifyAllLoads("attributor-simplify-all-loads", cl::Hidden, cl::desc("Try to simplify all loads."), cl::init(true))
static bool addIfNotExistent(LLVMContext &Ctx, const Attribute &Attr, AttributeSet AttrSet, bool ForceReplace, AttrBuilder &AB)
Return true if the information provided by Attr was added to the attribute set AttrSet.
static cl::opt< bool > ViewDepGraph("attributor-view-dep-graph", cl::Hidden, cl::desc("View the dependency graph."), cl::init(false))
static bool isEqualOrWorse(const Attribute &New, const Attribute &Old)
Return true if New is equal or worse than Old.
static cl::opt< bool > AllowDeepWrapper("attributor-allow-deep-wrappers", cl::Hidden, cl::desc("Allow the Attributor to use IP information " "derived from non-exact functions via cloning"), cl::init(false))
static cl::opt< bool > DumpDepGraph("attributor-dump-dep-graph", cl::Hidden, cl::desc("Dump the dependency graph to dot files."), cl::init(false))
static cl::opt< bool > PrintCallGraph("attributor-print-call-graph", cl::Hidden, cl::desc("Print Attributor's internal call graph"), cl::init(false))
static bool checkForAllInstructionsImpl(Attributor *A, InformationCache::OpcodeInstMapTy &OpcodeInstMap, function_ref< bool(Instruction &)> Pred, const AbstractAttribute *QueryingAA, const AAIsDead *LivenessAA, ArrayRef< unsigned > Opcodes, bool &UsedAssumedInformation, bool CheckBBLivenessOnly=false, bool CheckPotentiallyDead=false)
static cl::opt< bool > PrintDependencies("attributor-print-dep", cl::Hidden, cl::desc("Print attribute dependencies"), cl::init(false))
static bool isAssumedReadOnlyOrReadNone(Attributor &A, const IRPosition &IRP, const AbstractAttribute &QueryingAA, bool RequireReadNone, bool &IsKnown)
static cl::opt< std::string > DepGraphDotFileNamePrefix("attributor-depgraph-dot-filename-prefix", cl::Hidden, cl::desc("The prefix used for the CallGraph dot file names."))
static cl::opt< bool > AnnotateDeclarationCallSites("attributor-annotate-decl-cs", cl::Hidden, cl::desc("Annotate call sites of function declarations."), cl::init(false))
static cl::opt< unsigned > SetFixpointIterations("attributor-max-iterations", cl::Hidden, cl::desc("Maximal number of fixpoint iterations."), cl::init(32))
static cl::list< std::string > FunctionSeedAllowList("attributor-function-seed-allow-list", cl::Hidden, cl::desc("Comma separated list of function names that are " "allowed to be seeded."), cl::CommaSeparated)
static cl::opt< bool > EnableCallSiteSpecific("attributor-enable-call-site-specific-deduction", cl::Hidden, cl::desc("Allow the Attributor to do call site specific analysis"), cl::init(false))
static cl::opt< bool > CloseWorldAssumption("attributor-assume-closed-world", cl::Hidden, cl::desc("Should a closed world be assumed, or not. Default if not set."))
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This file provides interfaces used to build and manipulate a call graph, which is a very useful tool ...
This file contains the declarations for the subclasses of Constant, which represent the different fla...
This file provides an implementation of debug counters.
#define DEBUG_COUNTER(VARNAME, COUNTERNAME, DESC)
Contains a collection of routines for determining if a given instruction is guaranteed to execute if ...
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
uint64_t IntrinsicInst * II
FunctionAnalysisManager FAM
This file defines the PointerIntPair class.
static StringRef getName(Value *V)
Remove Loads Into Fake Uses
This file defines the SmallPtrSet class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
#define DEBUG_WITH_TYPE(TYPE,...)
DEBUG_WITH_TYPE macro - This macro should be used by passes to emit debug information.
void print(OutputBuffer &OB) const
static const fltSemantics & IEEEsingle()
Class for arbitrary precision integers.
CallBase * getInstruction() const
Return the underlying instruction.
bool isCallbackCall() const
Return true if this ACS represents a callback call.
const Use & getCalleeUseForCallback() const
Return the use of the callee value in the underlying instruction.
static LLVM_ABI void getCallbackUses(const CallBase &CB, SmallVectorImpl< const Use * > &CallbackUses)
Add operand uses of CB that represent callback uses into CallbackUses.
bool isCallee(Value::const_user_iterator UI) const
Return true if UI is the use that defines the callee of this ACS.
Value * getCallArgOperand(Argument &Arg) const
Return the operand of the underlying instruction associated with Arg.
int getCallArgOperandNo(Argument &Arg) const
Return the operand index of the underlying instruction associated with Arg.
unsigned getNumArgOperands() const
Return the number of parameters of the callee.
Function * getCalledFunction() const
Return the function being called if this is a direct call, otherwise return null (if it's an indirect...
This templated class represents "all analyses that operate over <aparticular IR unit>" (e....
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
This class represents an incoming formal argument to a Function.
const Function * getParent() const
unsigned getArgNo() const
Return the index of this formal argument in its containing function.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
bool empty() const
empty - Check if the array is empty.
This class stores enough information to efficiently remove some attributes from an existing AttrBuild...
This class holds the attributes for a particular argument, parameter, function, or return value.
LLVM_ABI MemoryEffects getMemoryEffects() const
LLVM_ABI bool hasAttribute(Attribute::AttrKind Kind) const
Return true if the attribute exists in this set.
LLVM_ABI Attribute getAttribute(Attribute::AttrKind Kind) const
Return the attribute object.
Functions, function parameters, and return types can have attributes to indicate how they should be t...
LLVM_ABI bool isStringAttribute() const
Return true if the attribute is a string (target-dependent) attribute.
LLVM_ABI bool isEnumAttribute() const
Return true if the attribute is an Attribute::AttrKind type.
LLVM_ABI bool isIntAttribute() const
Return true if the attribute is an integer attribute.
LLVM_ABI uint64_t getValueAsInt() const
Return the attribute's value as an integer.
LLVM_ABI bool isConstantRangeAttribute() const
Return true if the attribute is a ConstantRange attribute.
LLVM_ABI StringRef getKindAsString() const
Return the attribute's kind as a string.
static LLVM_ABI Attribute get(LLVMContext &Context, AttrKind Kind, uint64_t Val=0)
Return a uniquified Attribute object.
LLVM_ABI Attribute::AttrKind getKindAsEnum() const
Return the attribute's kind as an enum (Attribute::AttrKind).
LLVM_ABI MemoryEffects getMemoryEffects() const
Returns memory effects.
LLVM_ABI StringRef getValueAsString() const
Return the attribute's value as a string.
AttrKind
This enumeration lists the attributes that can be associated with parameters, function results,...
@ None
No attributes have been set.
LLVM Basic Block Representation.
const Function * getParent() const
Return the enclosing method, or null if none.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
const Instruction & front() const
LLVM_ABI const BasicBlock * getUniquePredecessor() const
Return the predecessor of this block if it has a unique predecessor block.
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
Represents analyses that only rely on functions' control flow.
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
void setCallingConv(CallingConv::ID CC)
void addFnAttr(Attribute::AttrKind Kind)
Adds the attribute to the function.
LLVM_ABI void getOperandBundlesAsDefs(SmallVectorImpl< OperandBundleDef > &Defs) const
Return the list of operand bundles attached to this instruction as a vector of OperandBundleDefs.
CallingConv::ID getCallingConv() const
LLVM_ABI bool isMustTailCall() const
Tests if this call site must be tail call optimized.
Value * getCalledOperand() const
void setAttributes(AttributeList A)
Set the attributes for this call.
unsigned arg_size() const
AttributeList getAttributes() const
Return the attributes for this call.
LLVM_ABI Function * getCaller()
Helper to get the caller (the parent function).
Wrapper to unify "old style" CallGraph and "new style" LazyCallGraph.
LLVM_ABI void replaceFunctionWith(Function &OldFn, Function &NewFn)
Replace OldFn in the call graph (and SCC) with NewFn.
LLVM_ABI void reanalyzeFunction(Function &Fn)
After an CGSCC pass changes a function in ways that affect the call graph, this method can be called ...
void initialize(LazyCallGraph &LCG, LazyCallGraph::SCC &SCC, CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR)
Initializers for usage outside of a CGSCC pass, inside a CGSCC pass in the old and new pass manager (...
This class represents a function call, abstracting a target machine's calling convention.
static CallInst * Create(FunctionType *Ty, Value *F, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
void setTailCall(bool IsTc=true)
A constant value that is initialized with an expression using other constant values.
static LLVM_ABI Constant * getPointerCast(Constant *C, Type *Ty)
Create a BitCast, AddrSpaceCast, or a PtrToInt cast constant expression.
static LLVM_ABI Constant * getTrunc(Constant *C, Type *Ty, bool OnlyIfReduced=false)
LLVM_ABI void print(raw_ostream &OS) const
Print out the bounds to a stream.
This is an important base class in LLVM.
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
A parsed version of the target data layout string in and methods for querying it.
static bool shouldExecute(unsigned CounterName)
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...
Implements a dense probed hash-table based set.
Analysis pass which computes a DominatorTree.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
A proxy from a FunctionAnalysisManager to an SCC.
Class to represent function types.
static LLVM_ABI FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
void setSubprogram(DISubprogram *SP)
Set the attached subprogram.
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
void splice(Function::iterator ToIt, Function *FromF)
Transfer all blocks from FromF to this function at ToIt.
const BasicBlock & getEntryBlock() const
FunctionType * getFunctionType() const
Returns the FunctionType for me.
iterator_range< arg_iterator > args()
DISubprogram * getSubprogram() const
Get the attached subprogram.
MemoryEffects getMemoryEffects() const
bool hasParamAttribute(unsigned ArgNo, Attribute::AttrKind Kind) const
check if an attributes is in the list of attributes.
AttributeList getAttributes() const
Return the attribute list for this Function.
void setAttributes(AttributeList Attrs)
Set the attribute list for this Function.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Type * getReturnType() const
Returns the type of the ret val.
void setMemoryEffects(MemoryEffects ME)
Argument * getArg(unsigned i) const
bool isVarArg() const
isVarArg - Return true if this function takes a variable number of arguments.
void copyAttributesFrom(const Function *Src)
copyAttributesFrom - copy all additional attributes (those not needed to create a Function) from the ...
bool hasMetadata() const
Return true if this value has any metadata attached to it.
LLVM_ABI void addMetadata(unsigned KindID, MDNode &MD)
Add a metadata attachment.
LLVM_ABI bool isDeclaration() const
Return true if the primary definition of this global value is outside of the current translation unit...
LinkageTypes getLinkage() const
bool hasLocalLinkage() const
void setLinkage(LinkageTypes LT)
unsigned getAddressSpace() const
Module * getParent()
Get the module that this global value is contained inside of...
void setDSOLocal(bool Local)
PointerType * getType() const
Global values are always pointers.
@ DefaultVisibility
The GV is visible.
void setVisibility(VisibilityTypes V)
static bool isInterposableLinkage(LinkageTypes Linkage)
Whether the definition of this global may be replaced by something non-equivalent at link time.
@ PrivateLinkage
Like Internal, but omit from symbol table.
@ InternalLinkage
Rename collisions when linking (static functions).
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.
LLVM_ABI void copyMetadata(const Instruction &SrcInst, ArrayRef< unsigned > WL=ArrayRef< unsigned >())
Copy metadata from SrcInst to this instruction.
static InvokeInst * Create(FunctionType *Ty, Value *Func, BasicBlock *IfNormal, BasicBlock *IfException, ArrayRef< Value * > Args, const Twine &NameStr, InsertPosition InsertBefore=nullptr)
This is an important class for using LLVM in a threaded context.
A node in the call graph.
An SCC of the call graph.
A lazily constructed view of the call graph of a module.
An instruction for reading from memory.
This is the common base class for memset/memcpy/memmove.
This class wraps the llvm.memcpy/memmove intrinsics.
static MemoryEffectsBase argMemOnly(ModRefInfo MR=ModRefInfo::ModRef)
bool doesAccessArgPointees() const
Whether this function may access argument memory.
static LLVM_ABI MemoryLocation getForSource(const MemTransferInst *MTI)
Return a location representing the source of a memory transfer.
static LLVM_ABI MemoryLocation getForDest(const MemIntrinsic *MI)
Return a location representing the destination of a memory set or transfer.
static LLVM_ABI std::optional< MemoryLocation > getOrNone(const Instruction *Inst)
A Module instance is used to store all the information related to an LLVM module.
const FunctionListType & getFunctionList() const
Get the Module's list of functions (constant).
PointerIntPair - This class implements a pair of a pointer and small integer.
void * getOpaqueValue() const
PointerTy getPointer() const
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
PreservedAnalyses & preserve()
Mark an analysis as preserved.
Return a value (possibly void), from a function.
static ReturnInst * Create(LLVMContext &C, Value *retVal=nullptr, InsertPosition InsertBefore=nullptr)
A vector that has set insertion semantics.
ArrayRef< value_type > getArrayRef() const
bool remove(const value_type &X)
Remove an item from the set vector.
size_type size() const
Determine the number of elements in the SetVector.
void insert_range(Range &&R)
typename vector_type::const_iterator iterator
void clear()
Completely clear the SetVector.
size_type count(const key_type &key) const
Count the number of elements of a given key in the SetVector.
iterator begin()
Get an iterator to the beginning of the SetVector.
bool insert(const value_type &X)
Insert a new element into the SetVector.
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
A SetVector that performs no allocations if smaller than a certain size.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void reserve(size_type N)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
StringRef - Represent a constant reference to a string, i.e.
A visitor class for IR positions.
LLVM_ABI SubsumingPositionIterator(const IRPosition &IRP)
Provides information about what library functions are available for the current target.
The TimeTraceScope is a helper class to call the begin and end functions of the time trace profiler.
Triple - Helper class for working with autoconf configuration names.
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.
LLVM_ABI unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
bool isVoidTy() const
Return true if this is 'void'.
static LLVM_ABI UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
A Use represents the edge between a Value definition and its users.
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
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 LLVMContext & getContext() const
All values hold a context through their type.
iterator_range< use_iterator > uses()
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
LLVM_ABI void takeName(Value *V)
Transfer the name from V to this value.
An efficient, type-erasing, non-owning reference to a callable.
const ParentTy * getParent() const
self_iterator getIterator()
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
iterator insert(iterator where, pointer New)
A raw_ostream that writes to a file descriptor.
This class implements an extremely fast bulk output stream that can only output to a stream.
A raw_ostream that writes to an std::string.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Abstract Attribute helper functions.
LLVM_ABI bool isAssumedReadNone(Attributor &A, const IRPosition &IRP, const AbstractAttribute &QueryingAA, bool &IsKnown)
Return true if IRP is readnone.
LLVM_ABI bool isAssumedReadOnly(Attributor &A, const IRPosition &IRP, const AbstractAttribute &QueryingAA, bool &IsKnown)
Return true if IRP is readonly.
LLVM_ABI std::optional< Value * > combineOptionalValuesInAAValueLatice(const std::optional< Value * > &A, const std::optional< Value * > &B, Type *Ty)
Return the combination of A and B such that the result is a possible value of both.
LLVM_ABI bool isValidAtPosition(const ValueAndContext &VAC, InformationCache &InfoCache)
Return true if the value of VAC is a valid at the position of VAC, that is a constant,...
LLVM_ABI bool isAssumedThreadLocalObject(Attributor &A, Value &Obj, const AbstractAttribute &QueryingAA)
Return true if Obj is assumed to be a thread local object.
LLVM_ABI bool isDynamicallyUnique(Attributor &A, const AbstractAttribute &QueryingAA, const Value &V, bool ForAnalysisOnly=true)
Return true if V is dynamically unique, that is, there are no two "instances" of V at runtime with di...
LLVM_ABI bool getPotentialCopiesOfStoredValue(Attributor &A, StoreInst &SI, SmallSetVector< Value *, 4 > &PotentialCopies, const AbstractAttribute &QueryingAA, bool &UsedAssumedInformation, bool OnlyExact=false)
Collect all potential values of the one stored by SI into PotentialCopies.
LLVM_ABI bool isPotentiallyAffectedByBarrier(Attributor &A, const Instruction &I, const AbstractAttribute &QueryingAA)
Return true if I is potentially affected by a barrier.
SmallPtrSet< Instruction *, 4 > InstExclusionSetTy
LLVM_ABI bool isGPU(const Module &M)
Return true iff M target a GPU (and we can use GPU AS reasoning).
LLVM_ABI Constant * getInitialValueForObj(Attributor &A, const AbstractAttribute &QueryingAA, Value &Obj, Type &Ty, const TargetLibraryInfo *TLI, const DataLayout &DL, RangeTy *RangePtr=nullptr)
Return the initial value of Obj with type Ty if that is a constant.
ValueScope
Flags to distinguish intra-procedural queries from potentially inter-procedural queries.
LLVM_ABI bool isValidInScope(const Value &V, const Function *Scope)
Return true if V is a valid value in Scope, that is a constant or an instruction/argument of Scope.
LLVM_ABI bool isPotentiallyReachable(Attributor &A, const Instruction &FromI, const Instruction &ToI, const AbstractAttribute &QueryingAA, const AA::InstExclusionSetTy *ExclusionSet=nullptr, std::function< bool(const Function &F)> GoBackwardsCB=nullptr)
Return true if ToI is potentially reachable from FromI without running into any instruction in Exclus...
LLVM_ABI bool isNoSyncInst(Attributor &A, const Instruction &I, const AbstractAttribute &QueryingAA)
Return true if I is a nosync instruction.
bool hasAssumedIRAttr(Attributor &A, const AbstractAttribute *QueryingAA, const IRPosition &IRP, DepClassTy DepClass, bool &IsKnown, bool IgnoreSubsumingPositions=false, const AAType **AAPtr=nullptr)
Helper to avoid creating an AA for IR Attributes that might already be set.
LLVM_ABI bool getPotentiallyLoadedValues(Attributor &A, LoadInst &LI, SmallSetVector< Value *, 4 > &PotentialValues, SmallSetVector< Instruction *, 4 > &PotentialValueOrigins, const AbstractAttribute &QueryingAA, bool &UsedAssumedInformation, bool OnlyExact=false)
Collect all potential values LI could read into PotentialValues.
LLVM_ABI Value * getWithType(Value &V, Type &Ty)
Try to convert V to type Ty without introducing new instructions.
constexpr char Attrs[]
Key for Kernel::Metadata::mAttrs.
@ C
The default llvm calling convention, compatible with C.
@ BasicBlock
Various leaf nodes.
initializer< Ty > init(const Ty &Val)
LocationClass< Ty > location(Ty &L)
@ Assume
Do not drop type tests (default).
DiagnosticInfoOptimizationBase::Argument NV
NodeAddr< UseNode * > Use
friend class Instruction
Iterator for Instructions in a `BasicBlock.
@ OF_TextWithCRLF
The file should be opened in text mode and use a carriage linefeed '\r '.
This is an optimization pass for GlobalISel generic memory operations.
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.
LLVM_ABI Constant * getInitialValueOfAllocation(const Value *V, const TargetLibraryInfo *TLI, Type *Ty)
If this is a call to an allocation function that initializes memory to a fixed value,...
Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST=nullptr, unsigned DynamicVGPRBlockSize=0)
LLVM_ABI bool RecursivelyDeleteTriviallyDeadInstructions(Value *V, const TargetLibraryInfo *TLI=nullptr, MemorySSAUpdater *MSSAU=nullptr, std::function< void(Value *)> AboutToDeleteCallback=std::function< void(Value *)>())
If the specified value is a trivially dead instruction, delete it.
LLVM_ABI unsigned MaxInitializationChainLength
The value passed to the line option that defines the maximal initialization chain length.
LLVM_ABI bool ConstantFoldTerminator(BasicBlock *BB, bool DeleteDeadConditions=false, const TargetLibraryInfo *TLI=nullptr, DomTreeUpdater *DTU=nullptr)
If a terminator instruction is predicated on a constant value, convert it into an unconditional branc...
APInt operator&(APInt a, const APInt &b)
LLVM_ABI void detachDeadBlocks(ArrayRef< BasicBlock * > BBs, SmallVectorImpl< DominatorTree::UpdateType > *Updates, bool KeepOneInputPHIs=false)
Replace contents of every block in BBs with single unreachable instruction.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
DenseMap< AssumeInst *, MinMax > Assume2KnowledgeMap
A mapping from intrinsics (=llvm.assume calls) to a value range (=knowledge) that is encoded in them.
LLVM_ABI bool verifyFunction(const Function &F, raw_ostream *OS=nullptr)
Check a function for errors, useful for use when debugging a pass.
LLVM_ABI CallInst * changeToCall(InvokeInst *II, DomTreeUpdater *DTU=nullptr)
This function converts the specified invoke into a normal call.
LLVM_ABI raw_fd_ostream & outs()
This returns a reference to a raw_fd_ostream for standard output.
auto dyn_cast_if_present(const Y &Val)
dyn_cast_if_present<X> - Functionally identical to dyn_cast, except that a null (or none in the case ...
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
InnerAnalysisManagerProxy< FunctionAnalysisManager, Module > FunctionAnalysisManagerModuleProxy
Provide the FunctionAnalysisManager to Module proxy.
LLVM_ABI bool isNoAliasCall(const Value *V)
Return true if this pointer is returned by a noalias function.
MemoryEffectsBase< IRMemLocation > MemoryEffects
Summary of how a function affects memory in the program.
raw_ostream & WriteGraph(raw_ostream &O, const GraphType &G, bool ShortNames=false, const Twine &Title="")
bool isa_and_nonnull(const Y &Val)
AnalysisManager< LazyCallGraph::SCC, LazyCallGraph & > CGSCCAnalysisManager
The CGSCC analysis manager.
LLVM_ABI InlineResult isInlineViable(Function &Callee)
Check if it is mechanically possible to inline the function Callee, based on the contents of the func...
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 bool isInstructionTriviallyDead(Instruction *I, const TargetLibraryInfo *TLI=nullptr)
Return true if the result produced by the instruction is not used, and the instruction will return.
LLVM_ABI Constant * ConstantFoldLoadFromUniformValue(Constant *C, Type *Ty, const DataLayout &DL)
If C is a uniform value where all bits are the same (either all zero, all ones, all undef or all pois...
PotentialValuesState< std::pair< AA::ValueAndContext, AA::ValueScope > > PotentialLLVMValuesState
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
LLVM_ABI bool NullPointerIsDefined(const Function *F, unsigned AS=0)
Check whether null pointer dereferencing is considered undefined behavior for a given function or an ...
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI bool AreStatisticsEnabled()
Check if statistics are enabled.
BumpPtrAllocatorImpl BumpPtrAllocator
The standard BumpPtrAllocator which just uses the default template parameters.
LLVM_ABI Constant * ConstantFoldLoadFromConst(Constant *C, Type *Ty, const APInt &Offset, const DataLayout &DL)
Extract value of C at the given Offset reinterpreted as Ty.
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...
@ Success
The lock was released successfully.
LLVM_ABI unsigned changeToUnreachable(Instruction *I, bool PreserveLCSSA=false, DomTreeUpdater *DTU=nullptr, MemorySSAUpdater *MSSAU=nullptr)
Insert an unreachable instruction before the specified instruction, making it and the rest of the cod...
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
LLVM_ABI BasicBlock * SplitBlockPredecessors(BasicBlock *BB, ArrayRef< BasicBlock * > Preds, const char *Suffix, DominatorTree *DT, LoopInfo *LI=nullptr, MemorySSAUpdater *MSSAU=nullptr, bool PreserveLCSSA=false)
This method introduces at least one new basic block into the function and moves some of the predecess...
PotentialValuesState< APInt > PotentialConstantIntValuesState
bool operator&=(SparseBitVector< ElementSize > *LHS, const SparseBitVector< ElementSize > &RHS)
DWARFExpression::Operation Op
void ViewGraph(const GraphType &G, const Twine &Name, bool ShortNames=false, const Twine &Title="", GraphProgram::Name Program=GraphProgram::DOT)
ViewGraph - Emit a dot graph, run 'dot', run gv on the postscript file, then cleanup.
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
ArrayRef(const T &OneElt) -> ArrayRef< T >
ValueMap< const Value *, WeakTrackingVH > ValueToValueMapTy
LLVM_ABI void CloneFunctionInto(Function *NewFunc, const Function *OldFunc, ValueToValueMapTy &VMap, CloneFunctionChangeType Changes, SmallVectorImpl< ReturnInst * > &Returns, const char *NameSuffix="", ClonedCodeInfo *CodeInfo=nullptr, ValueMapTypeRemapper *TypeMapper=nullptr, ValueMaterializer *Materializer=nullptr)
Clone OldFunc into NewFunc, transforming the old arguments into references to VMap values.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
iterator_range< pointer_iterator< WrappedIteratorT > > make_pointer_range(RangeT &&Range)
LLVM_ABI bool isAllocationFn(const Value *V, const TargetLibraryInfo *TLI)
Tests if a value is a call or invoke to a library function that allocates or reallocates memory (eith...
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
LLVM_ABI void fillMapFromAssume(AssumeInst &Assume, RetainedKnowledgeMap &Result)
Insert into the map all the informations contained in the operand bundles of the llvm....
bool operator|=(SparseBitVector< ElementSize > &LHS, const SparseBitVector< ElementSize > *RHS)
LLVM_ABI Constant * ConstantFoldCastInstruction(unsigned opcode, Constant *V, Type *DestTy)
@ OPTIONAL
The target may be valid if the source is not.
@ NONE
Do not track a dependence between source and target.
@ REQUIRED
The target cannot be valid if the source is not.
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
APInt operator|(APInt a, const APInt &b)
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
LLVM_ABI bool isPotentiallyReachable(const Instruction *From, const Instruction *To, const SmallPtrSetImpl< BasicBlock * > *ExclusionSet=nullptr, const DominatorTree *DT=nullptr, const LoopInfo *LI=nullptr)
Determine whether instruction 'To' is reachable from 'From', without passing through any blocks in Ex...
static LLVM_ABI const char ID
Unique ID (due to the unique address)
DepSetTy Deps
Set of dependency graph nodes which should be updated if this one is updated.
PointerIntPair< AADepGraphNode *, 1 > DepTy
The data structure for the dependency graph.
LLVM_ABI void viewGraph()
AADepGraphNode SyntheticRoot
There is no root node for the dependency graph.
LLVM_ABI void print()
Print dependency graph.
LLVM_ABI void dumpGraph()
Dump graph to file.
AADepGraphNode * GetEntryNode()
An abstract interface to track if a value leaves it's defining function instance.
bool isAssumedUniqueForAnalysis() const
Return true if we assume that the underlying value is unique in its scope wrt.
An abstract Attribute for computing reachability between functions.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface to determine reachability of point A to B.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for liveness abstract attribute.
virtual bool isKnownDead() const =0
Returns true if the underlying value is known dead.
virtual bool isAssumedDead() const =0
The query functions are protected such that other attributes need to go through the Attributor interf...
virtual bool isRemovableStore() const
Return true if the underlying value is a store that is known to be removable.
static bool mayCatchAsynchronousExceptions(const Function &F)
Determine if F might catch asynchronous exceptions.
An abstract interface for memory access kind related attributes (readnone/readonly/writeonly).
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for all memory location attributes (readnone/argmemonly/inaccessiblememonly/ina...
static LLVM_ABI const char ID
Unique ID (due to the unique address)
static LLVM_ABI const char ID
Unique ID (due to the unique address)
static LLVM_ABI const char ID
Unique ID (due to the unique address)
static LLVM_ABI const char ID
Unique ID (due to the unique address)
static LLVM_ABI const char ID
Unique ID (due to the unique address)
static LLVM_ABI const char ID
Unique ID (due to the unique address)
static LLVM_ABI const char ID
Unique ID (due to the unique address)
static LLVM_ABI const char ID
Unique ID (due to the unique address)
static LLVM_ABI bool isNonRelaxedAtomic(const Instruction *I)
Helper function used to determine whether an instruction is non-relaxed atomic.
static LLVM_ABI bool isNoSyncIntrinsic(const Instruction *I)
Helper function specific for intrinsics which are potentially volatile.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
static LLVM_ABI const char ID
Unique ID (due to the unique address)
bool isWrittenValueUnknown() const
Return true if the value written cannot be determined at all.
std::optional< Value * > getContent() const
Return the written value which can be llvm::null if it is not yet determined.
bool isWriteOrAssumption() const
Return true if this is a write access.
bool isRead() const
Return true if this is a read access.
Value * getWrittenValue() const
Return the value writen, if any.
Instruction * getLocalInst() const
Return the instruction that causes the access with respect to the local scope of the associated attri...
Instruction * getRemoteInst() const
Return the actual instruction that causes the access.
bool isWrittenValueYetUndetermined() const
Return true if the value written is not known yet.
AccessKind getKind() const
Return the access kind.
An abstract interface for struct information.
static LLVM_ABI Value * getSingleValue(Attributor &A, const AbstractAttribute &AA, const IRPosition &IRP, SmallVectorImpl< AA::ValueAndContext > &Values)
Extract the single value in Values if any.
An abstract attribute for getting all assumption underlying objects.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
static LLVM_ABI const char ID
Unique ID (due to the unique address)
Helper to represent an access offset and size, with logic to deal with uncertainty and check for over...
bool offsetOrSizeAreUnknown() const
Return true if offset or size are unknown.
Base struct for all "concrete attribute" deductions.
ChangeStatus update(Attributor &A)
Hook for the Attributor to trigger an update of the internal state.
friend struct Attributor
}
virtual void printWithDeps(raw_ostream &OS) const
void print(raw_ostream &OS) const
Helper functions, for debug purposes only.
virtual StateType & getState()=0
Return the internal abstract state for inspection.
virtual const std::string getAsStr(Attributor *A) const =0
This function should return the "summarized" assumed state as string.
virtual ChangeStatus updateImpl(Attributor &A)=0
The actual update/transfer function which has to be implemented by the derived classes.
const IRPosition & getIRPosition() const
Return an IR position, see struct IRPosition.
An interface to query the internal state of an abstract attribute.
virtual ChangeStatus indicatePessimisticFixpoint()=0
Indicate that the abstract state should converge to the pessimistic state.
virtual bool isAtFixpoint() const =0
Return if this abstract state is fixed, thus does not need to be updated if information changes as it...
virtual bool isValidState() const =0
Return if this abstract state is in a valid state.
Wrapper for FunctionAnalysisManager.
LLVM_ABI PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG, CGSCCUpdateResult &UR)
void populateAll() const
Force populate the entire call graph.
Configuration for the Attributor.
std::optional< unsigned > MaxFixpointIterations
Maximum number of iterations to run until fixpoint.
LLVM_ABI PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG, CGSCCUpdateResult &UR)
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
Helper struct used in the communication between an abstract attribute (AA) that wants to change the s...
std::function< void( const ArgumentReplacementInfo &, Function &, Function::arg_iterator)> CalleeRepairCBTy
Callee repair callback type.
std::function< void(const ArgumentReplacementInfo &, AbstractCallSite, SmallVectorImpl< Value * > &)> ACSRepairCBTy
Abstract call site (ACS) repair callback type.
The fixpoint analysis framework that orchestrates the attribute deduction.
LLVM_ABI bool registerFunctionSignatureRewrite(Argument &Arg, ArrayRef< Type * > ReplacementTypes, ArgumentReplacementInfo::CalleeRepairCBTy &&CalleeRepairCB, ArgumentReplacementInfo::ACSRepairCBTy &&ACSRepairCB)
Register a rewrite for a function signature.
LLVM_ABI bool checkForAllCallees(function_ref< bool(ArrayRef< const Function * > Callees)> Pred, const AbstractAttribute &QueryingAA, const CallBase &CB)
Check Pred on all potential Callees of CB.
bool isModulePass() const
Return true if this is a module pass, false otherwise.
LLVM_ABI bool isValidFunctionSignatureRewrite(Argument &Arg, ArrayRef< Type * > ReplacementTypes)
Check if we can rewrite a function signature.
static LLVM_ABI bool isInternalizable(Function &F)
Returns true if the function F can be internalized.
LLVM_ABI ChangeStatus removeAttrs(const IRPosition &IRP, ArrayRef< Attribute::AttrKind > AttrKinds)
Remove all AttrKinds attached to IRP.
void emitRemark(Instruction *I, StringRef RemarkName, RemarkCallBack &&RemarkCB) const
Emit a remark generically.
bool isRunOn(Function &Fn) const
Return true if we derive attributes for Fn.
LLVM_ABI bool isAssumedDead(const AbstractAttribute &AA, const AAIsDead *LivenessAA, bool &UsedAssumedInformation, bool CheckBBLivenessOnly=false, DepClassTy DepClass=DepClassTy::OPTIONAL)
Return true if AA (or its context instruction) is assumed dead.
LLVM_ABI bool checkForAllInstructions(function_ref< bool(Instruction &)> Pred, const Function *Fn, const AbstractAttribute *QueryingAA, ArrayRef< unsigned > Opcodes, bool &UsedAssumedInformation, bool CheckBBLivenessOnly=false, bool CheckPotentiallyDead=false)
Check Pred on all instructions in Fn with an opcode present in Opcodes.
LLVM_ABI void recordDependence(const AbstractAttribute &FromAA, const AbstractAttribute &ToAA, DepClassTy DepClass)
Explicitly record a dependence from FromAA to ToAA, that is if FromAA changes ToAA should be updated ...
static LLVM_ABI void createShallowWrapper(Function &F)
Create a shallow wrapper for F such that F has internal linkage afterwards.
const AAType * getAAFor(const AbstractAttribute &QueryingAA, const IRPosition &IRP, DepClassTy DepClass)
Lookup an abstract attribute of type AAType at position IRP.
std::optional< Value * > getAssumedSimplified(const IRPosition &IRP, const AbstractAttribute &AA, bool &UsedAssumedInformation, AA::ValueScope S)
If V is assumed simplified, return it, if it is unclear yet, return std::nullopt, otherwise return nu...
static LLVM_ABI Function * internalizeFunction(Function &F, bool Force=false)
Make another copy of the function F such that the copied version has internal linkage afterwards and ...
bool isFunctionIPOAmendable(const Function &F)
Determine whether the function F is IPO amendable.
const AAType * getOrCreateAAFor(IRPosition IRP, const AbstractAttribute *QueryingAA, DepClassTy DepClass, bool ForceUpdate=false, bool UpdateAfterInit=true)
The version of getAAFor that allows to omit a querying abstract attribute.
LLVM_ABI bool checkForAllReadWriteInstructions(function_ref< bool(Instruction &)> Pred, AbstractAttribute &QueryingAA, bool &UsedAssumedInformation)
Check Pred on all Read/Write instructions.
LLVM_ABI bool checkForAllReturnedValues(function_ref< bool(Value &)> Pred, const AbstractAttribute &QueryingAA, AA::ValueScope S=AA::ValueScope::Intraprocedural, bool RecurseForSelectAndPHI=true)
Check Pred on all values potentially returned by the function associated with QueryingAA.
LLVM_ABI bool isClosedWorldModule() const
Return true if the module contains the whole world, thus, no outside functions exist.
LLVM_ABI std::optional< Constant * > getAssumedConstant(const IRPosition &IRP, const AbstractAttribute &AA, bool &UsedAssumedInformation)
If IRP is assumed to be a constant, return it, if it is unclear yet, return std::nullopt,...
LLVM_ABI Attributor(SetVector< Function * > &Functions, InformationCache &InfoCache, AttributorConfig Configuration)
Constructor.
LLVM_ABI void getAttrs(const IRPosition &IRP, ArrayRef< Attribute::AttrKind > AKs, SmallVectorImpl< Attribute > &Attrs, bool IgnoreSubsumingPositions=false)
Return the attributes of any kind in AKs existing in the IR at a position that will affect this one.
InformationCache & getInfoCache()
Return the internal information cache.
LLVM_ABI std::optional< Value * > translateArgumentToCallSiteContent(std::optional< Value * > V, CallBase &CB, const AbstractAttribute &AA, bool &UsedAssumedInformation)
Translate V from the callee context into the call site context.
LLVM_ABI bool checkForAllUses(function_ref< bool(const Use &, bool &)> Pred, const AbstractAttribute &QueryingAA, const Value &V, bool CheckBBLivenessOnly=false, DepClassTy LivenessDepClass=DepClassTy::OPTIONAL, bool IgnoreDroppableUses=true, function_ref< bool(const Use &OldU, const Use &NewU)> EquivalentUseCB=nullptr)
Check Pred on all (transitive) uses of V.
LLVM_ABI ChangeStatus manifestAttrs(const IRPosition &IRP, ArrayRef< Attribute > DeducedAttrs, bool ForceReplace=false)
Attach DeducedAttrs to IRP, if ForceReplace is set we do this even if the same attribute kind was alr...
LLVM_ABI bool hasAttr(const IRPosition &IRP, ArrayRef< Attribute::AttrKind > AKs, bool IgnoreSubsumingPositions=false, Attribute::AttrKind ImpliedAttributeKind=Attribute::None)
Return true if any kind in AKs existing in the IR at a position that will affect this one.
LLVM_ABI void registerForUpdate(AbstractAttribute &AA)
Allows a query AA to request an update if a new query was received.
std::function< bool(Attributor &, const AbstractAttribute *)> VirtualUseCallbackTy
LLVM_ABI void identifyDefaultAbstractAttributes(Function &F)
Determine opportunities to derive 'default' attributes in F and create abstract attribute objects for...
LLVM_ABI bool getAssumedSimplifiedValues(const IRPosition &IRP, const AbstractAttribute *AA, SmallVectorImpl< AA::ValueAndContext > &Values, AA::ValueScope S, bool &UsedAssumedInformation, bool RecurseForSelectAndPHI=true)
Try to simplify IRP and in the scope S.
BumpPtrAllocator & Allocator
The allocator used to allocate memory, e.g. for AbstractAttributes.
LLVM_ABI ChangeStatus run()
Run the analyses until a fixpoint is reached or enforced (timeout).
static LLVM_ABI bool internalizeFunctions(SmallPtrSetImpl< Function * > &FnSet, DenseMap< Function *, Function * > &FnMap)
Make copies of each function in the set FnSet such that the copied version has internal linkage after...
LLVM_ABI bool checkForAllCallSites(function_ref< bool(AbstractCallSite)> Pred, const AbstractAttribute &QueryingAA, bool RequireAllCallSites, bool &UsedAssumedInformation)
Check Pred on all function call sites.
LLVM_ABI bool getAttrsFromAssumes(const IRPosition &IRP, Attribute::AttrKind AK, SmallVectorImpl< Attribute > &Attrs)
Return the attributes of kind AK existing in the IR as operand bundles of an llvm....
bool isKnown(base_t BitsEncoding=BestState) const
Return true if the bits set in BitsEncoding are "known bits".
Support structure for SCC passes to communicate updates the call graph back to the CGSCC pass manager...
static std::string getNodeLabel(const AADepGraphNode *Node, const AADepGraph *DG)
DOTGraphTraits(bool isSimple=false)
DefaultDOTGraphTraits(bool simple=false)
Represent subnormal handling kind for floating point instruction inputs and outputs.
@ Dynamic
Denormals have unknown treatment.
An information struct used to provide DenseMap with the various necessary components for a given valu...
static NodeRef DepGetVal(const DepTy &DT)
PointerIntPair< AADepGraphNode *, 1 > DepTy
static ChildIteratorType child_end(NodeRef N)
static NodeRef getEntryNode(AADepGraphNode *DGN)
mapped_iterator< AADepGraphNode::DepSetTy::iterator, decltype(&DepGetVal)> ChildIteratorType
PointerIntPair< AADepGraphNode *, 1 > EdgeRef
static ChildIteratorType child_begin(NodeRef N)
AADepGraphNode::DepSetTy::iterator ChildEdgeIteratorType
static NodeRef getEntryNode(AADepGraph *DG)
mapped_iterator< AADepGraphNode::DepSetTy::iterator, decltype(&DepGetVal)> nodes_iterator
static nodes_iterator nodes_begin(AADepGraph *DG)
static nodes_iterator nodes_end(AADepGraph *DG)
typename AADepGraph *::UnknownGraphTypeError NodeRef
Helper to describe and deal with positions in the LLVM-IR.
Function * getAssociatedFunction() const
Return the associated function, if any.
void setAttrList(const AttributeList &AttrList) const
Update the attributes associated with this function or call site scope.
unsigned getAttrIdx() const
Return the index in the attribute list for this position.
bool hasCallBaseContext() const
Check if the position has any call base context.
static const IRPosition callsite_returned(const CallBase &CB)
Create a position describing the returned value of CB.
static const IRPosition returned(const Function &F, const CallBaseContext *CBContext=nullptr)
Create a position describing the returned value of F.
LLVM_ABI Argument * getAssociatedArgument() const
Return the associated argument, if any.
static const IRPosition value(const Value &V, const CallBaseContext *CBContext=nullptr)
Create a position describing the value of V.
AttributeList getAttrList() const
Return the attributes associated with this function or call site scope.
static const IRPosition inst(const Instruction &I, const CallBaseContext *CBContext=nullptr)
Create a position describing the instruction I.
static const IRPosition callsite_argument(const CallBase &CB, unsigned ArgNo)
Create a position describing the argument of CB at position ArgNo.
static LLVM_ABI const IRPosition TombstoneKey
Kind
The positions we distinguish in the IR.
@ IRP_ARGUMENT
An attribute for a function argument.
@ IRP_RETURNED
An attribute for the function return value.
@ IRP_CALL_SITE
An attribute for a call site (function scope).
@ IRP_CALL_SITE_RETURNED
An attribute for a call site return value.
@ IRP_FUNCTION
An attribute for a function (scope).
@ IRP_FLOAT
A position that is not associated with a spot suitable for attributes.
@ IRP_CALL_SITE_ARGUMENT
An attribute for a call site argument.
@ IRP_INVALID
An invalid position.
Instruction * getCtxI() const
Return the context instruction, if any.
static const IRPosition argument(const Argument &Arg, const CallBaseContext *CBContext=nullptr)
Create a position describing the argument Arg.
static LLVM_ABI const IRPosition EmptyKey
Special DenseMap key values.
static const IRPosition function(const Function &F, const CallBaseContext *CBContext=nullptr)
Create a position describing the function scope of F.
const CallBaseContext * getCallBaseContext() const
Get the call base context from the position.
Value & getAssociatedValue() const
Return the value this abstract attribute is associated with.
Value & getAnchorValue() const
Return the value this abstract attribute is anchored with.
Value * getAttrListAnchor() const
Return the value attributes are attached to.
int getCallSiteArgNo() const
Return the call site argument number of the associated value if it is an argument or call site argume...
Kind getPositionKind() const
Return the associated position kind.
static const IRPosition callsite_function(const CallBase &CB)
Create a position describing the function scope of CB.
Function * getAnchorScope() const
Return the Function surrounding the anchor value.
State for an integer range.
ConstantRange getKnown() const
Return the known state encoding.
ConstantRange getAssumed() const
Return the assumed state encoding.
uint32_t getBitWidth() const
Return associated values' bit width.
A "must be executed context" for a given program point PP is the set of instructions,...
iterator & end()
Return an universal end iterator.
bool findInContextOf(const Instruction *I, const Instruction *PP)
Helper to look for I in the context of PP.
iterator & begin(const Instruction *PP)
Return an iterator to explore the context around PP.
bool undefIsContained() const
Returns whether this state contains an undef value or not.
bool isValidState() const override
See AbstractState::isValidState(...)
const SetTy & getAssumedSet() const
Return this set.