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."));
185 return L == ChangeStatus::CHANGED ? L : R;
192 return L == ChangeStatus::UNCHANGED ? L : R;
208 if (
const auto *CB = dyn_cast<CallBase>(&
I)) {
209 if (CB->hasFnAttr(Attribute::NoSync))
213 if (!CB->isConvergent() && !CB->mayReadOrWriteMemory())
220 return AA::hasAssumedIRAttr<Attribute::NoSync>(
222 DepClassTy::OPTIONAL, IsKnownNoSync);
225 if (!
I.mayReadOrWriteMemory())
232 const Value &V,
bool ForAnalysisOnly) {
234 if (!ForAnalysisOnly)
247 auto *GV = dyn_cast<GlobalVariable>(&Obj);
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();
283 if (isa<Constant>(V))
285 if (
auto *
I = dyn_cast<Instruction>(&V))
286 return I->getFunction() == Scope;
287 if (
auto *
A = dyn_cast<Argument>(&V))
288 return A->getParent() == Scope;
294 if (isa<Constant>(VAC.getValue()) || VAC.getValue() == VAC.getCtxI())
300 if (
auto *
A = dyn_cast<Argument>(VAC.getValue()))
301 return A->getParent() == Scope;
302 if (
auto *
I = dyn_cast<Instruction>(VAC.getValue())) {
303 if (
I->getFunction() == Scope) {
309 if (CtxI &&
I->getParent() == CtxI->
getParent())
312 [&](
const Instruction &AfterI) { return &AfterI == CtxI; });
319 if (V.getType() == &Ty)
321 if (isa<PoisonValue>(V))
323 if (isa<UndefValue>(V))
325 if (
auto *
C = dyn_cast<Constant>(&V)) {
340std::optional<Value *>
342 const std::optional<Value *> &
B,
355 Ty = (*A)->getType();
356 if (isa_and_nonnull<UndefValue>(*
A))
358 if (isa<UndefValue>(*
B))
365template <
bool IsLoad,
typename Ty>
371 LLVM_DEBUG(
dbgs() <<
"Trying to determine the potential copies of " <<
I
372 <<
" (only exact: " << OnlyExact <<
")\n";);
383 A.getInfoCache().getTargetLibraryInfoForFunction(*
I.getFunction());
385 auto Pred = [&](
Value &Obj) {
387 if (isa<UndefValue>(&Obj))
389 if (isa<ConstantPointerNull>(&Obj)) {
393 Ptr.getType()->getPointerAddressSpace()) &&
394 A.getAssumedSimplified(
Ptr, QueryingAA, UsedAssumedInformation,
398 dbgs() <<
"Underlying object is a valid nullptr, giving up.\n";);
402 if (!isa<AllocaInst>(&Obj) && !isa<GlobalVariable>(&Obj) &&
404 LLVM_DEBUG(
dbgs() <<
"Underlying object is not supported yet: " << Obj
408 if (
auto *GV = dyn_cast<GlobalVariable>(&Obj))
409 if (!GV->hasLocalLinkage() &&
410 !(GV->isConstant() && GV->hasInitializer())) {
412 "linkage, not supported yet: "
417 bool NullOnly =
true;
418 bool NullRequired =
false;
419 auto CheckForNullOnlyAndUndef = [&](std::optional<Value *> V,
421 if (!V || *V ==
nullptr)
423 else if (isa<UndefValue>(*V))
425 else if (isa<Constant>(*V) && cast<Constant>(*V)->isNullValue())
426 NullRequired = !IsExact;
435 LLVM_DEBUG(
dbgs() <<
"Underlying object written but stored value "
436 "cannot be converted to read type: "
449 if (PotentialValueOrigins && !isa<AssumeInst>(Acc.
getRemoteInst()))
453 if (NewCopies.
count(V)) {
458 if (
Value *V = AdjustWrittenValueType(Acc, *SI->getValueOperand()))
459 if (NewCopies.
count(V)) {
472 CheckForNullOnlyAndUndef(Acc.
getContent(), IsExact);
473 if (OnlyExact && !IsExact && !NullOnly &&
479 if (NullRequired && !NullOnly) {
480 LLVM_DEBUG(
dbgs() <<
"Required all `null` accesses due to non exact "
481 "one, however found non-null one: "
486 assert(isa<LoadInst>(
I) &&
"Expected load or store instruction only!");
492 if (PotentialValueOrigins)
498 LLVM_DEBUG(
dbgs() <<
"Underlying object written through a non-store "
499 "instruction not supported yet: "
503 Value *V = AdjustWrittenValueType(Acc, *SI->getValueOperand());
507 if (PotentialValueOrigins)
508 NewCopyOrigins.
insert(SI);
510 assert(isa<StoreInst>(
I) &&
"Expected load or store instruction only!");
512 if (!LI && OnlyExact) {
514 "instruction not supported yet: "
525 bool HasBeenWrittenTo =
false;
530 if (!PI || !PI->forallInterferingAccesses(
533 !IsLoad, CheckAccess,
534 HasBeenWrittenTo,
Range, SkipCB)) {
537 <<
"Failed to verify all interfering accesses for underlying object: "
542 if (IsLoad && !HasBeenWrittenTo && !
Range.isUnassigned()) {
545 A, QueryingAA, Obj, *
I.getType(), TLI,
DL, &
Range);
547 LLVM_DEBUG(
dbgs() <<
"Could not determine required initial value of "
548 "underlying object, abort!\n");
551 CheckForNullOnlyAndUndef(InitialValue,
true);
552 if (NullRequired && !NullOnly) {
553 LLVM_DEBUG(
dbgs() <<
"Non exact access but initial value that is not "
554 "null or undef, abort!\n");
558 NewCopies.
insert(InitialValue);
559 if (PotentialValueOrigins)
560 NewCopyOrigins.
insert(
nullptr);
570 if (!AAUO || !AAUO->forallUnderlyingObjects(Pred)) {
572 dbgs() <<
"Underlying objects stored into could not be determined\n";);
579 for (
const auto *PI : PIs) {
580 if (!PI->getState().isAtFixpoint())
581 UsedAssumedInformation =
true;
582 A.recordDependence(*PI, QueryingAA, DepClassTy::OPTIONAL);
585 if (PotentialValueOrigins)
597 A, LI, PotentialValues, &PotentialValueOrigins, QueryingAA,
598 UsedAssumedInformation, OnlyExact);
606 A, SI, PotentialCopies,
nullptr, QueryingAA, UsedAssumedInformation,
612 bool RequireReadNone,
bool &IsKnown) {
613 if (RequireReadNone) {
614 if (AA::hasAssumedIRAttr<Attribute::ReadNone>(
615 A, &QueryingAA, IRP, DepClassTy::OPTIONAL, IsKnown,
618 }
else if (AA::hasAssumedIRAttr<Attribute::ReadOnly>(
619 A, &QueryingAA, IRP, DepClassTy::OPTIONAL, IsKnown,
625 const auto *MemLocAA =
627 if (MemLocAA && MemLocAA->isAssumedReadNone()) {
628 IsKnown = MemLocAA->isKnownReadNone();
630 A.recordDependence(*MemLocAA, QueryingAA, DepClassTy::OPTIONAL);
635 const auto *MemBehaviorAA =
638 (MemBehaviorAA->isAssumedReadNone() ||
639 (!RequireReadNone && MemBehaviorAA->isAssumedReadOnly()))) {
640 IsKnown = RequireReadNone ? MemBehaviorAA->isKnownReadNone()
641 : MemBehaviorAA->isKnownReadOnly();
643 A.recordDependence(*MemBehaviorAA, QueryingAA, DepClassTy::OPTIONAL);
666 std::function<
bool(
const Function &
F)> GoBackwardsCB) {
668 dbgs() <<
"[AA] isPotentiallyReachable @" << ToFn.
getName() <<
" from "
669 << FromI <<
" [GBCB: " <<
bool(GoBackwardsCB) <<
"][#ExS: "
670 << (ExclusionSet ? std::to_string(ExclusionSet->
size()) :
"none")
673 for (
auto *ES : *ExclusionSet)
674 dbgs() << *ES <<
"\n";
682 if (GoBackwardsCB && &ToFn != FromI.
getFunction() &&
683 !GoBackwardsCB(*FromI.
getFunction()) &&
A.getInfoCache().isKernel(ToFn) &&
685 LLVM_DEBUG(
dbgs() <<
"[AA] assume kernel cannot be reached from within the "
686 "module; success\n";);
695 if (!GoBackwardsCB && !ExclusionSet) {
697 <<
" is not checked backwards and does not have an "
698 "exclusion set, abort\n");
706 while (!Worklist.
empty()) {
708 if (!Visited.
insert(CurFromI).second)
712 if (FromFn == &ToFn) {
715 LLVM_DEBUG(
dbgs() <<
"[AA] check " << *ToI <<
" from " << *CurFromI
716 <<
" intraprocedurally\n");
719 bool Result = !ReachabilityAA || ReachabilityAA->isAssumedReachable(
720 A, *CurFromI, *ToI, ExclusionSet);
722 << (Result ?
"can potentially " :
"cannot ") <<
"reach "
723 << *ToI <<
" [Intra]\n");
733 Result = !ToReachabilityAA || ToReachabilityAA->isAssumedReachable(
734 A, EntryI, *ToI, ExclusionSet);
736 <<
" " << (Result ?
"can potentially " :
"cannot ")
737 <<
"reach @" << *ToI <<
" [ToFn]\n");
745 Result = !FnReachabilityAA || FnReachabilityAA->instructionCanReach(
746 A, *CurFromI, ToFn, ExclusionSet);
748 <<
" " << (Result ?
"can potentially " :
"cannot ")
749 <<
"reach @" << ToFn.
getName() <<
" [FromFn]\n");
758 bool Result = !ReachabilityAA || ReachabilityAA->isAssumedReachable(
759 A, *CurFromI, Ret, ExclusionSet);
761 << (Result ?
"can potentially " :
"cannot ") <<
"reach "
762 << Ret <<
" [Intra]\n");
767 bool UsedAssumedInformation =
false;
768 if (
A.checkForAllInstructions(ReturnInstCB, FromFn, &QueryingAA,
769 {Instruction::Ret}, UsedAssumedInformation)) {
774 if (!GoBackwardsCB) {
776 <<
" is not checked backwards, abort\n");
782 if (!GoBackwardsCB(*FromFn))
789 CallBase *CB = ACS.getInstruction();
793 if (isa<InvokeInst>(CB))
801 Result = !
A.checkForAllCallSites(CheckCallSite, *FromFn,
803 &QueryingAA, UsedAssumedInformation);
805 LLVM_DEBUG(
dbgs() <<
"[AA] stepping back to call sites from " << *CurFromI
806 <<
" in @" << FromFn->
getName()
807 <<
" failed, give up\n");
811 LLVM_DEBUG(
dbgs() <<
"[AA] stepped back to call sites from " << *CurFromI
812 <<
" in @" << FromFn->
getName()
813 <<
" worklist size is: " << Worklist.
size() <<
"\n");
822 std::function<
bool(
const Function &
F)> GoBackwardsCB) {
824 return ::isPotentiallyReachable(
A, FromI, &ToI, *ToFn, QueryingAA,
825 ExclusionSet, GoBackwardsCB);
832 std::function<
bool(
const Function &
F)> GoBackwardsCB) {
833 return ::isPotentiallyReachable(
A, FromI,
nullptr, ToFn, QueryingAA,
834 ExclusionSet, GoBackwardsCB);
839 if (isa<UndefValue>(Obj))
841 if (isa<AllocaInst>(Obj)) {
845 dbgs() <<
"[AA] Object '" << Obj
846 <<
"' is thread local; stack objects are thread local.\n");
849 bool IsKnownNoCapture;
850 bool IsAssumedNoCapture = AA::hasAssumedIRAttr<Attribute::Captures>(
854 << (IsAssumedNoCapture ?
"" :
"not") <<
" thread local; "
855 << (IsAssumedNoCapture ?
"non-" :
"")
856 <<
"captured stack object.\n");
857 return IsAssumedNoCapture;
859 if (
auto *GV = dyn_cast<GlobalVariable>(&Obj)) {
860 if (GV->isConstant()) {
862 <<
"' is thread local; constant global\n");
865 if (GV->isThreadLocal()) {
867 <<
"' is thread local; thread local global\n");
872 if (
A.getInfoCache().targetIsGPU()) {
874 (
int)AA::GPUAddressSpace::Local) {
876 <<
"' is thread local; GPU local memory\n");
880 (
int)AA::GPUAddressSpace::Constant) {
882 <<
"' is thread local; GPU constant memory\n");
887 LLVM_DEBUG(
dbgs() <<
"[AA] Object '" << Obj <<
"' is not thread local\n");
893 if (!
I.mayHaveSideEffects() && !
I.mayReadFromMemory())
898 auto AddLocationPtr = [&](std::optional<MemoryLocation> Loc) {
899 if (!Loc || !Loc->Ptr) {
901 dbgs() <<
"[AA] Access to unknown location; -> requires barriers\n");
930 auto Pred = [&](
Value &Obj) {
934 <<
"'; -> requires barrier\n");
940 if (!UnderlyingObjsAA || !UnderlyingObjsAA->forallUnderlyingObjects(Pred))
965 AB.addAttribute(Kind);
979 if (!ForceReplace && Kind == Attribute::Memory) {
983 AB.addMemoryAttr(ME);
990 AB.addAttribute(Attr);
997 AB.addAttribute(Attr);
1018 std::optional<Argument *> CBCandidateArg;
1022 for (
const Use *U : CallbackUses) {
1036 "ACS mapped into var-args arguments!");
1037 if (CBCandidateArg) {
1038 CBCandidateArg =
nullptr;
1046 if (CBCandidateArg && *CBCandidateArg)
1047 return *CBCandidateArg;
1051 auto *Callee = dyn_cast_if_present<Function>(CB.getCalledOperand());
1052 if (Callee && Callee->arg_size() >
unsigned(ArgNo))
1053 return Callee->getArg(ArgNo);
1067 LLVM_DEBUG(
dbgs() <<
"[Attributor] Update " << HasChanged <<
" " << *
this
1077 InfoCache(InfoCache), Configuration(Configuration) {
1081 if (Fn->hasAddressTaken(
nullptr,
1087 InfoCache.IndirectlyCallableFunctions.push_back(Fn);
1094 "Did expect a valid position!");
1111 unsigned AttrsSize = Attrs.size();
1114 for (
const auto &It : A2K)
1117 return AttrsSize != Attrs.size();
1120template <
typename DescTy>
1126 if (AttrDescs.
empty())
1138 auto It = AttrsMap.find(AttrListAnchor);
1139 if (It == AttrsMap.end())
1142 AL = It->getSecond();
1151 for (
const DescTy &AttrDesc : AttrDescs)
1152 if (CB(AttrDesc, AS, AM, AB))
1158 AL = AL.removeAttributesAtIndex(Ctx, AttrIdx, AM);
1159 AL = AL.addAttributesAtIndex(Ctx, AttrIdx, AB);
1160 AttrsMap[AttrListAnchor] = AL;
1166 bool IgnoreSubsumingPositions,
1168 bool Implied =
false;
1169 bool HasAttr =
false;
1172 if (AttrSet.hasAttribute(Kind)) {
1173 Implied |= Kind != ImpliedAttributeKind;
1179 updateAttrMap<Attribute::AttrKind>(EquivIRP, AttrKinds, HasAttrCB);
1185 if (IgnoreSubsumingPositions)
1202 ImpliedAttributeKind)});
1209 bool IgnoreSubsumingPositions) {
1213 if (AttrSet.hasAttribute(Kind))
1214 Attrs.push_back(AttrSet.getAttribute(Kind));
1218 updateAttrMap<Attribute::AttrKind>(EquivIRP, AttrKinds, CollectAttrCB);
1222 if (IgnoreSubsumingPositions)
1233 if (!AttrSet.hasAttribute(Kind))
1235 AM.addAttribute(Kind);
1238 return updateAttrMap<Attribute::AttrKind>(IRP, AttrKinds, RemoveAttrCB);
1245 if (!AttrSet.hasAttribute(Attr))
1247 AM.addAttribute(Attr);
1251 return updateAttrMap<StringRef>(IRP, Attrs, RemoveAttrCB);
1256 bool ForceReplace) {
1262 return updateAttrMap<Attribute>(IRP, Attrs, AddAttrCB);
1270 IRPositions.emplace_back(IRP);
1274 auto CanIgnoreOperandBundles = [](
const CallBase &CB) {
1275 return (isa<IntrinsicInst>(CB) &&
1276 cast<IntrinsicInst>(CB).getIntrinsicID() == Intrinsic ::assume);
1290 assert(CB &&
"Expected call site!");
1293 if (!CB->hasOperandBundles() || CanIgnoreOperandBundles(*CB))
1294 if (
auto *Callee = dyn_cast_if_present<Function>(CB->getCalledOperand()))
1298 assert(CB &&
"Expected call site!");
1301 if (!CB->hasOperandBundles() || CanIgnoreOperandBundles(*CB)) {
1303 dyn_cast_if_present<Function>(CB->getCalledOperand())) {
1306 for (
const Argument &Arg : Callee->args())
1307 if (Arg.hasReturnedAttr()) {
1308 IRPositions.emplace_back(
1310 IRPositions.emplace_back(
1319 assert(CB &&
"Expected call site!");
1322 if (!CB->hasOperandBundles() || CanIgnoreOperandBundles(*CB)) {
1323 auto *Callee = dyn_cast_if_present<Function>(CB->getCalledOperand());
1336void IRPosition::verify() {
1337#ifdef EXPENSIVE_CHECKS
1340 assert((CBContext ==
nullptr) &&
1341 "Invalid position must not have CallBaseContext!");
1343 "Expected a nullptr for an invalid position!");
1347 "Expected specialized kind for argument values!");
1350 assert(isa<Function>(getAsValuePtr()) &&
1351 "Expected function for a 'returned' position!");
1353 "Associated value mismatch!");
1356 assert((CBContext ==
nullptr) &&
1357 "'call site returned' position must not have CallBaseContext!");
1358 assert((isa<CallBase>(getAsValuePtr())) &&
1359 "Expected call base for 'call site returned' position!");
1361 "Associated value mismatch!");
1364 assert((CBContext ==
nullptr) &&
1365 "'call site function' position must not have CallBaseContext!");
1366 assert((isa<CallBase>(getAsValuePtr())) &&
1367 "Expected call base for 'call site function' position!");
1369 "Associated value mismatch!");
1372 assert(isa<Function>(getAsValuePtr()) &&
1373 "Expected function for a 'function' position!");
1375 "Associated value mismatch!");
1378 assert(isa<Argument>(getAsValuePtr()) &&
1379 "Expected argument for a 'argument' position!");
1381 "Associated value mismatch!");
1384 assert((CBContext ==
nullptr) &&
1385 "'call site argument' position must not have CallBaseContext!");
1386 Use *U = getAsUsePtr();
1388 assert(U &&
"Expected use for a 'call site argument' position!");
1389 assert(isa<CallBase>(U->getUser()) &&
1390 "Expected call base user for a 'call site argument' position!");
1391 assert(cast<CallBase>(U->getUser())->isArgOperand(U) &&
1392 "Expected call base argument operand for a 'call site argument' "
1394 assert(cast<CallBase>(U->getUser())->getArgOperandNo(U) ==
1396 "Argument number mismatch!");
1404std::optional<Constant *>
1407 bool &UsedAssumedInformation) {
1411 for (
auto &CB : SimplificationCallbacks.lookup(IRP)) {
1412 std::optional<Value *> SimplifiedV = CB(IRP, &AA, UsedAssumedInformation);
1414 return std::nullopt;
1415 if (isa_and_nonnull<Constant>(*SimplifiedV))
1416 return cast<Constant>(*SimplifiedV);
1424 UsedAssumedInformation)) {
1426 return std::nullopt;
1427 if (
auto *
C = dyn_cast_or_null<Constant>(
1440 for (
auto &CB : SimplificationCallbacks.lookup(IRP))
1441 return CB(IRP, AA, UsedAssumedInformation);
1447 return std::nullopt;
1460 bool &UsedAssumedInformation,
bool RecurseForSelectAndPHI) {
1464 while (!Worklist.
empty()) {
1470 int NV = Values.
size();
1471 const auto &SimplificationCBs = SimplificationCallbacks.lookup(IRP);
1472 for (
const auto &CB : SimplificationCBs) {
1473 std::optional<Value *> CBResult = CB(IRP, AA, UsedAssumedInformation);
1474 if (!CBResult.has_value())
1476 Value *V = *CBResult;
1485 if (SimplificationCBs.empty()) {
1488 const auto *PotentialValuesAA =
1490 if (PotentialValuesAA &&
1491 PotentialValuesAA->getAssumedSimplifiedValues(*
this, Values, S)) {
1492 UsedAssumedInformation |= !PotentialValuesAA->isAtFixpoint();
1501 if (!RecurseForSelectAndPHI)
1504 for (
int I = NV, E = Values.
size();
I < E; ++
I) {
1505 Value *V = Values[
I].getValue();
1506 if (!isa<PHINode>(V) && !isa<SelectInst>(V))
1508 if (!Seen.
insert(V).second)
1511 Values[
I] = Values[E - 1];
1525 bool &UsedAssumedInformation) {
1528 if (*V ==
nullptr || isa<Constant>(*V))
1530 if (
auto *Arg = dyn_cast<Argument>(*V))
1533 if (!Arg->hasPointeeInMemoryValueAttr())
1543 for (
auto &It : AAMap) {
1551 bool &UsedAssumedInformation,
1552 bool CheckBBLivenessOnly,
DepClassTy DepClass) {
1558 return isAssumedDead(IRP, &AA, FnLivenessAA, UsedAssumedInformation,
1559 CheckBBLivenessOnly, DepClass);
1565 bool &UsedAssumedInformation,
1566 bool CheckBBLivenessOnly,
DepClassTy DepClass) {
1569 Instruction *UserI = dyn_cast<Instruction>(U.getUser());
1572 UsedAssumedInformation, CheckBBLivenessOnly, DepClass);
1574 if (
auto *CB = dyn_cast<CallBase>(UserI)) {
1577 if (CB->isArgOperand(&U)) {
1581 UsedAssumedInformation, CheckBBLivenessOnly,
1584 }
else if (
ReturnInst *RI = dyn_cast<ReturnInst>(UserI)) {
1587 UsedAssumedInformation, CheckBBLivenessOnly, DepClass);
1588 }
else if (
PHINode *
PHI = dyn_cast<PHINode>(UserI)) {
1591 UsedAssumedInformation, CheckBBLivenessOnly, DepClass);
1592 }
else if (
StoreInst *SI = dyn_cast<StoreInst>(UserI)) {
1593 if (!CheckBBLivenessOnly && SI->getPointerOperand() != U.get()) {
1601 UsedAssumedInformation =
true;
1608 UsedAssumedInformation, CheckBBLivenessOnly, DepClass);
1614 bool &UsedAssumedInformation,
1615 bool CheckBBLivenessOnly,
DepClassTy DepClass,
1616 bool CheckForDeadStore) {
1622 if (ManifestAddedBlocks.contains(
I.getParent()))
1631 if (!FnLivenessAA || QueryingAA == FnLivenessAA)
1635 if (CheckBBLivenessOnly ? FnLivenessAA->
isAssumedDead(
I.getParent())
1640 UsedAssumedInformation =
true;
1644 if (CheckBBLivenessOnly)
1652 if (!IsDeadAA || QueryingAA == IsDeadAA)
1659 UsedAssumedInformation =
true;
1667 UsedAssumedInformation =
true;
1677 bool &UsedAssumedInformation,
1678 bool CheckBBLivenessOnly,
DepClassTy DepClass) {
1690 isAssumedDead(*CtxI, QueryingAA, FnLivenessAA, UsedAssumedInformation,
1695 if (CheckBBLivenessOnly)
1701 IsDeadAA = getOrCreateAAFor<AAIsDead>(
1708 if (!IsDeadAA || QueryingAA == IsDeadAA)
1715 UsedAssumedInformation =
true;
1734 if (!FnLivenessAA || QueryingAA == FnLivenessAA)
1750 return Pred(Callee);
1752 const auto *CallEdgesAA = getAAFor<AACallEdges>(
1754 if (!CallEdgesAA || CallEdgesAA->hasUnknownCallee())
1757 const auto &Callees = CallEdgesAA->getOptimisticEdges();
1758 return Pred(Callees.getArrayRef());
1762 return isa<PHINode>(Usr) || !isa<Instruction>(Usr);
1768 bool CheckBBLivenessOnly,
DepClassTy LivenessDepClass,
1769 bool IgnoreDroppableUses,
1774 if (!CB(*
this, &QueryingAA))
1777 if (isa<ConstantData>(V))
1788 auto AddUsers = [&](
const Value &V,
const Use *OldUse) {
1789 for (
const Use &UU : V.uses()) {
1790 if (OldUse && EquivalentUseCB && !EquivalentUseCB(*OldUse, UU)) {
1792 "rejected by the equivalence call back: "
1802 AddUsers(V,
nullptr);
1805 <<
" initial uses to check\n");
1808 const auto *LivenessAA =
1813 while (!Worklist.
empty()) {
1818 if (
auto *Fn = dyn_cast<Function>(U->getUser()))
1819 dbgs() <<
"[Attributor] Check use: " << **U <<
" in " << Fn->getName()
1822 dbgs() <<
"[Attributor] Check use: " << **U <<
" in " << *U->getUser()
1825 bool UsedAssumedInformation =
false;
1826 if (
isAssumedDead(*U, &QueryingAA, LivenessAA, UsedAssumedInformation,
1827 CheckBBLivenessOnly, LivenessDepClass)) {
1829 dbgs() <<
"[Attributor] Dead use, skip!\n");
1832 if (IgnoreDroppableUses && U->getUser()->isDroppable()) {
1834 dbgs() <<
"[Attributor] Droppable user, skip!\n");
1838 if (
auto *SI = dyn_cast<StoreInst>(U->getUser())) {
1839 if (&SI->getOperandUse(0) == U) {
1840 if (!Visited.
insert(U).second)
1844 *
this, *SI, PotentialCopies, QueryingAA, UsedAssumedInformation,
1848 <<
"[Attributor] Value is stored, continue with "
1849 << PotentialCopies.
size()
1850 <<
" potential copies instead!\n");
1851 for (
Value *PotentialCopy : PotentialCopies)
1852 if (!AddUsers(*PotentialCopy, U))
1859 bool Follow =
false;
1860 if (!Pred(*U, Follow))
1865 User &Usr = *U->getUser();
1866 AddUsers(Usr,
nullptr);
1874 bool RequireAllCallSites,
1875 bool &UsedAssumedInformation) {
1881 if (!AssociatedFunction) {
1882 LLVM_DEBUG(
dbgs() <<
"[Attributor] No function associated with " << IRP
1888 &QueryingAA, UsedAssumedInformation);
1893 bool RequireAllCallSites,
1895 bool &UsedAssumedInformation,
1896 bool CheckPotentiallyDead) {
1900 <<
"[Attributor] Function " << Fn.
getName()
1901 <<
" has no internal linkage, hence not all call sites are known\n");
1906 if (!CB(*
this, QueryingAA))
1910 for (
unsigned u = 0; u <
Uses.size(); ++u) {
1913 if (
auto *Fn = dyn_cast<Function>(U))
1914 dbgs() <<
"[Attributor] Check use: " << Fn->
getName() <<
" in "
1915 << *U.getUser() <<
"\n";
1917 dbgs() <<
"[Attributor] Check use: " << *U <<
" in " << *U.getUser()
1920 if (!CheckPotentiallyDead &&
1921 isAssumedDead(U, QueryingAA,
nullptr, UsedAssumedInformation,
1924 dbgs() <<
"[Attributor] Dead use, skip!\n");
1927 if (
ConstantExpr *CE = dyn_cast<ConstantExpr>(U.getUser())) {
1928 if (CE->isCast() && CE->getType()->isPointerTy()) {
1930 dbgs() <<
"[Attributor] Use, is constant cast expression, add "
1931 << CE->getNumUses() <<
" uses of that expression instead!\n";
1933 for (
const Use &CEU : CE->uses())
1934 Uses.push_back(&CEU);
1942 <<
" has non call site use " << *U.get() <<
" in "
1943 << *U.getUser() <<
"\n");
1947 const Use *EffectiveUse =
1950 if (!RequireAllCallSites) {
1951 LLVM_DEBUG(
dbgs() <<
"[Attributor] User " << *EffectiveUse->getUser()
1952 <<
" is not a call of " << Fn.
getName()
1956 LLVM_DEBUG(
dbgs() <<
"[Attributor] User " << *EffectiveUse->getUser()
1957 <<
" is an invalid use of " << Fn.
getName() <<
"\n");
1965 unsigned MinArgsParams =
1967 for (
unsigned u = 0; u < MinArgsParams; ++u) {
1971 dbgs() <<
"[Attributor] Call site / callee argument type mismatch ["
1972 << u <<
"@" << Fn.
getName() <<
": "
1982 LLVM_DEBUG(
dbgs() <<
"[Attributor] Call site callback failed for "
1990bool Attributor::shouldPropagateCallBaseContext(
const IRPosition &IRP) {
2000 bool RecurseForSelectAndPHI) {
2004 if (!AssociatedFunction)
2007 bool UsedAssumedInformation =
false;
2011 UsedAssumedInformation, RecurseForSelectAndPHI))
2015 return Pred(*VAC.getValue());
2023 bool &UsedAssumedInformation,
bool CheckBBLivenessOnly =
false,
2024 bool CheckPotentiallyDead =
false) {
2025 for (
unsigned Opcode : Opcodes) {
2027 auto *Insts = OpcodeInstMap.
lookup(Opcode);
2033 if (
A && !CheckPotentiallyDead &&
2035 UsedAssumedInformation, CheckBBLivenessOnly)) {
2037 dbgs() <<
"[Attributor] Instruction " << *
I
2038 <<
" is potentially dead, skip!\n";);
2053 bool &UsedAssumedInformation,
2054 bool CheckBBLivenessOnly,
2055 bool CheckPotentiallyDead) {
2061 const auto *LivenessAA =
2062 CheckPotentiallyDead && QueryingAA
2068 LivenessAA, Opcodes, UsedAssumedInformation,
2069 CheckBBLivenessOnly, CheckPotentiallyDead))
2078 bool &UsedAssumedInformation,
2079 bool CheckBBLivenessOnly,
2080 bool CheckPotentiallyDead) {
2084 UsedAssumedInformation, CheckBBLivenessOnly,
2085 CheckPotentiallyDead);
2090 bool &UsedAssumedInformation) {
2093 const Function *AssociatedFunction =
2095 if (!AssociatedFunction)
2099 const auto *LivenessAA =
2106 UsedAssumedInformation))
2116void Attributor::runTillFixpoint() {
2120 <<
" abstract attributes.\n");
2125 unsigned IterationCounter = 1;
2126 unsigned MaxIterations =
2136 LLVM_DEBUG(
dbgs() <<
"\n\n[Attributor] #Iteration: " << IterationCounter
2137 <<
", Worklist size: " << Worklist.
size() <<
"\n");
2142 for (
unsigned u = 0; u < InvalidAAs.
size(); ++u) {
2147 dbgs() <<
"[Attributor] InvalidAA: " << *InvalidAA
2148 <<
" has " << InvalidAA->
Deps.
size()
2149 <<
" required & optional dependences\n");
2150 for (
auto &DepIt : InvalidAA->
Deps) {
2154 dbgs() <<
" - recompute: " << *DepAA);
2159 <<
" - invalidate: " << *DepAA);
2163 InvalidAAs.
insert(DepAA);
2173 for (
auto &DepIt : ChangedAA->Deps)
2174 Worklist.
insert(cast<AbstractAttribute>(DepIt.getPointer()));
2175 ChangedAA->Deps.clear();
2178 LLVM_DEBUG(
dbgs() <<
"[Attributor] #Iteration: " << IterationCounter
2179 <<
", Worklist+Dependent size: " << Worklist.
size()
2189 const auto &AAState = AA->getState();
2190 if (!AAState.isAtFixpoint())
2192 ChangedAAs.push_back(AA);
2196 if (!AAState.isValidState())
2208 Worklist.insert_range(ChangedAAs);
2209 Worklist.insert_range(QueryAAsAwaitingUpdate);
2210 QueryAAsAwaitingUpdate.clear();
2212 }
while (!Worklist.empty() && (IterationCounter++ < MaxIterations));
2214 if (IterationCounter > MaxIterations && !Functions.
empty()) {
2216 return ORM <<
"Attributor did not reach a fixpoint after "
2217 <<
ore::NV(
"Iterations", MaxIterations) <<
" iterations.";
2220 emitRemark<OptimizationRemarkMissed>(
F,
"FixedPoint",
Remark);
2223 LLVM_DEBUG(
dbgs() <<
"\n[Attributor] Fixpoint iteration done after: "
2224 << IterationCounter <<
"/" << MaxIterations
2225 <<
" iterations\n");
2233 for (
unsigned u = 0;
u < ChangedAAs.size();
u++) {
2235 if (!Visited.
insert(ChangedAA).second)
2242 NumAttributesTimedOut++;
2245 for (
auto &DepIt : ChangedAA->
Deps)
2246 ChangedAAs.push_back(cast<AbstractAttribute>(DepIt.getPointer()));
2251 if (!Visited.
empty())
2252 dbgs() <<
"\n[Attributor] Finalized " << Visited.
size()
2253 <<
" abstract attributes.\n";
2259 "Non-query AAs should not be required to register for updates!");
2260 QueryAAsAwaitingUpdate.insert(&AA);
2267 unsigned NumManifested = 0;
2268 unsigned NumAtFixpoint = 0;
2292 bool UsedAssumedInformation =
false;
2304 LLVM_DEBUG(
dbgs() <<
"[Attributor] Manifest " << LocalChange <<
" : " << *AA
2307 ManifestChange = ManifestChange | LocalChange;
2313 (void)NumManifested;
2314 (void)NumAtFixpoint;
2315 LLVM_DEBUG(
dbgs() <<
"\n[Attributor] Manifested " << NumManifested
2316 <<
" arguments while " << NumAtFixpoint
2317 <<
" were in a valid fixpoint state\n");
2319 NumAttributesManifested += NumManifested;
2320 NumAttributesValidFixpoint += NumAtFixpoint;
2325 for (
unsigned u = 0; u < NumFinalAAs; ++u)
2329 errs() <<
"Unexpected abstract attribute: "
2330 << cast<AbstractAttribute>(DepIt->getPointer()) <<
" :: "
2331 << cast<AbstractAttribute>(DepIt->getPointer())
2333 .getAssociatedValue()
2337 "remain unchanged!");
2340 for (
auto &It : AttrsMap) {
2343 isa<Function>(It.getFirst())
2349 return ManifestChange;
2352void Attributor::identifyDeadInternalFunctions() {
2373 if (
F->hasLocalLinkage() && (
isModulePass() || !TLI->getLibFunc(*
F, LF)))
2377 bool FoundLiveInternal =
true;
2378 while (FoundLiveInternal) {
2379 FoundLiveInternal =
false;
2384 bool UsedAssumedInformation =
false;
2388 return ToBeDeletedFunctions.count(Callee) ||
2389 (Functions.count(Callee) &&
Callee->hasLocalLinkage() &&
2390 !LiveInternalFns.
count(Callee));
2392 *
F,
true,
nullptr, UsedAssumedInformation)) {
2398 FoundLiveInternal =
true;
2404 ToBeDeletedFunctions.insert(
F);
2411 << ToBeDeletedFunctions.size() <<
" functions and "
2412 << ToBeDeletedBlocks.size() <<
" blocks and "
2413 << ToBeDeletedInsts.size() <<
" instructions and "
2414 << ToBeChangedValues.size() <<
" values and "
2415 << ToBeChangedUses.size() <<
" uses. To insert "
2416 << ToBeChangedToUnreachableInsts.size()
2417 <<
" unreachables.\n"
2418 <<
"Preserve manifest added " << ManifestAddedBlocks.size()
2424 auto ReplaceUse = [&](
Use *
U,
Value *NewV) {
2429 const auto &
Entry = ToBeChangedValues.lookup(NewV);
2432 NewV = get<0>(Entry);
2437 "Cannot replace an instruction outside the current SCC!");
2441 if (
auto *RI = dyn_cast_or_null<ReturnInst>(
I)) {
2443 if (CI->isMustTailCall() && !ToBeDeletedInsts.count(CI))
2447 if (!isa<Argument>(NewV))
2448 for (
auto &Arg : RI->getFunction()->args())
2449 Arg.removeAttr(Attribute::Returned);
2453 <<
" instead of " << *OldV <<
"\n");
2457 CGModifiedFunctions.insert(
I->getFunction());
2458 if (!isa<PHINode>(
I) && !ToBeDeletedInsts.count(
I) &&
2462 if (isa<UndefValue>(NewV) && isa<CallBase>(
U->getUser())) {
2463 auto *CB = cast<CallBase>(
U->getUser());
2464 if (CB->isArgOperand(U)) {
2465 unsigned Idx = CB->getArgOperandNo(U);
2466 CB->removeParamAttr(
Idx, Attribute::NoUndef);
2467 auto *
Callee = dyn_cast_if_present<Function>(CB->getCalledOperand());
2469 Callee->removeParamAttr(
Idx, Attribute::NoUndef);
2472 if (isa<Constant>(NewV) && isa<BranchInst>(
U->getUser())) {
2474 if (isa<UndefValue>(NewV)) {
2475 ToBeChangedToUnreachableInsts.insert(UserI);
2482 for (
auto &It : ToBeChangedUses) {
2484 Value *NewV = It.second;
2485 ReplaceUse(U, NewV);
2489 for (
auto &It : ToBeChangedValues) {
2490 Value *OldV = It.first;
2491 auto [NewV,
Done] = It.second;
2493 for (
auto &U : OldV->
uses())
2494 if (
Done || !
U.getUser()->isDroppable())
2497 if (
auto *
I = dyn_cast<Instruction>(
U->getUser()))
2500 ReplaceUse(U, NewV);
2504 for (
const auto &V : InvokeWithDeadSuccessor)
2505 if (
InvokeInst *
II = dyn_cast_or_null<InvokeInst>(V)) {
2507 "Cannot replace an invoke outside the current SCC!");
2508 bool UnwindBBIsDead =
II->hasFnAttr(Attribute::NoUnwind);
2509 bool NormalBBIsDead =
II->hasFnAttr(Attribute::NoReturn);
2510 bool Invoke2CallAllowed =
2512 assert((UnwindBBIsDead || NormalBBIsDead) &&
2513 "Invoke does not have dead successors!");
2516 if (UnwindBBIsDead) {
2518 if (Invoke2CallAllowed) {
2523 ToBeChangedToUnreachableInsts.insert(NormalNextIP);
2525 assert(NormalBBIsDead &&
"Broken invariant!");
2528 ToBeChangedToUnreachableInsts.insert(&NormalDestBB->
front());
2533 "Cannot replace a terminator outside the current SCC!");
2534 CGModifiedFunctions.insert(
I->getFunction());
2537 for (
const auto &V : ToBeChangedToUnreachableInsts)
2538 if (
Instruction *
I = dyn_cast_or_null<Instruction>(V)) {
2542 "Cannot replace an instruction outside the current SCC!");
2543 CGModifiedFunctions.insert(
I->getFunction());
2547 for (
const auto &V : ToBeDeletedInsts) {
2548 if (
Instruction *
I = dyn_cast_or_null<Instruction>(V)) {
2549 assert((!isa<CallBase>(
I) || isa<IntrinsicInst>(
I) ||
2551 "Cannot delete an instruction outside the current SCC!");
2552 I->dropDroppableUses();
2553 CGModifiedFunctions.insert(
I->getFunction());
2554 if (!
I->getType()->isVoidTy())
2559 I->eraseFromParent();
2566 dbgs() <<
"[Attributor] DeadInsts size: " << DeadInsts.
size() <<
"\n";
2567 for (
auto &
I : DeadInsts)
2569 dbgs() <<
" - " << *
I <<
"\n";
2574 if (
unsigned NumDeadBlocks = ToBeDeletedBlocks.size()) {
2576 ToBeDeletedBBs.
reserve(NumDeadBlocks);
2579 "Cannot delete a block outside the current SCC!");
2580 CGModifiedFunctions.insert(BB->
getParent());
2582 if (ManifestAddedBlocks.contains(BB))
2592 identifyDeadInternalFunctions();
2595 ChangeStatus ManifestChange = rewriteFunctionSignatures(CGModifiedFunctions);
2597 for (
Function *Fn : CGModifiedFunctions)
2598 if (!ToBeDeletedFunctions.count(Fn) && Functions.count(Fn))
2601 for (
Function *Fn : ToBeDeletedFunctions) {
2602 if (!Functions.count(Fn))
2607 if (!ToBeChangedUses.empty())
2610 if (!ToBeChangedToUnreachableInsts.empty())
2613 if (!ToBeDeletedFunctions.empty())
2616 if (!ToBeDeletedBlocks.empty())
2619 if (!ToBeDeletedInsts.empty())
2622 if (!InvokeWithDeadSuccessor.empty())
2625 if (!DeadInsts.empty())
2628 NumFnDeleted += ToBeDeletedFunctions.size();
2630 LLVM_DEBUG(
dbgs() <<
"[Attributor] Deleted " << ToBeDeletedFunctions.size()
2631 <<
" functions after manifest.\n");
2633#ifdef EXPENSIVE_CHECKS
2635 if (ToBeDeletedFunctions.count(
F))
2641 return ManifestChange;
2651 Phase = AttributorPhase::UPDATE;
2664 Phase = AttributorPhase::MANIFEST;
2667 Phase = AttributorPhase::CLEANUP;
2673 return ManifestChange | CleanupChange;
2681 assert(Phase == AttributorPhase::UPDATE &&
2682 "We can update AA only in the update stage!");
2685 DependenceVector DV;
2686 DependenceStack.push_back(&DV);
2690 bool UsedAssumedInformation =
false;
2702 RerunCS = AA.
update(*
this);
2708 AAState.indicateOptimisticFixpoint();
2711 if (!AAState.isAtFixpoint())
2712 rememberDependences();
2716 DependenceVector *PoppedDV = DependenceStack.pop_back_val();
2718 assert(PoppedDV == &DV &&
"Inconsistent usage of the dependence stack!");
2724 assert(!
F.isDeclaration() &&
"Cannot create a wrapper around a declaration!");
2733 M.getFunctionList().insert(
F.getIterator(),
Wrapper);
2738 assert(
F.use_empty() &&
"Uses remained after wrapper was created!");
2743 F.setComdat(
nullptr);
2747 F.getAllMetadata(MDs);
2748 for (
auto MDIt : MDs)
2749 Wrapper->addMetadata(MDIt.first, *MDIt.second);
2750 Wrapper->setAttributes(
F.getAttributes());
2758 Args.push_back(&Arg);
2759 Arg.setName((FArgIt++)->
getName());
2767 NumFnShallowWrappersCreated++;
2771 if (
F.isDeclaration() ||
F.hasLocalLinkage() ||
2787 return InternalizedFns[&
F];
2805 F->getName() +
".internalized");
2808 for (
auto &Arg :
F->args()) {
2810 NewFArgIt->setName(ArgName);
2811 VMap[&Arg] = &(*NewFArgIt++);
2826 F->getAllMetadata(MDs);
2827 for (
auto MDIt : MDs)
2831 M.getFunctionList().insert(
F->getIterator(), Copied);
2839 auto &InternalizedFn = FnMap[
F];
2840 auto IsNotInternalized = [&](
Use &U) ->
bool {
2841 if (
auto *CB = dyn_cast<CallBase>(U.getUser()))
2842 return !FnMap.
lookup(CB->getCaller());
2845 F->replaceUsesWithIf(InternalizedFn, IsNotInternalized);
2866 if (cast<CallBase>(ACS.
getInstruction())->getCalledOperand()->getType() !=
2877 LLVM_DEBUG(
dbgs() <<
"[Attributor] Cannot rewrite var-args functions\n");
2888 dbgs() <<
"[Attributor] Cannot rewrite due to complex attribute\n");
2893 bool UsedAssumedInformation =
false;
2895 UsedAssumedInformation,
2897 LLVM_DEBUG(
dbgs() <<
"[Attributor] Cannot rewrite all call sites\n");
2902 if (
auto *CI = dyn_cast<CallInst>(&
I))
2903 return !CI->isMustTailCall();
2911 nullptr, {Instruction::Call},
2912 UsedAssumedInformation)) {
2913 LLVM_DEBUG(
dbgs() <<
"[Attributor] Cannot rewrite due to instructions\n");
2924 LLVM_DEBUG(
dbgs() <<
"[Attributor] Register new rewrite of " << Arg <<
" in "
2926 << ReplacementTypes.
size() <<
" replacements\n");
2928 "Cannot register an invalid rewrite");
2932 ArgumentReplacementMap[Fn];
2938 std::unique_ptr<ArgumentReplacementInfo> &ARI = ARIs[Arg.
getArgNo()];
2939 if (ARI && ARI->getNumReplacementArgs() <= ReplacementTypes.
size()) {
2940 LLVM_DEBUG(
dbgs() <<
"[Attributor] Existing rewrite is preferred\n");
2948 LLVM_DEBUG(
dbgs() <<
"[Attributor] Register new rewrite of " << Arg <<
" in "
2950 << ReplacementTypes.
size() <<
" replacements\n");
2954 std::move(CalleeRepairCB),
2955 std::move(ACSRepairCB)));
2976 for (
auto &It : ArgumentReplacementMap) {
2980 if (!Functions.count(OldFn) || ToBeDeletedFunctions.count(OldFn))
2993 if (
const std::unique_ptr<ArgumentReplacementInfo> &ARI =
2994 ARIs[Arg.getArgNo()]) {
2995 NewArgumentTypes.
append(ARI->ReplacementTypes.begin(),
2996 ARI->ReplacementTypes.end());
2997 NewArgumentAttributes.
append(ARI->getNumReplacementArgs(),
3000 NewArgumentTypes.
push_back(Arg.getType());
3007 for (
auto *
I : NewArgumentTypes)
3008 if (
auto *VT = dyn_cast<llvm::VectorType>(
I))
3009 LargestVectorWidth =
3010 std::max(LargestVectorWidth,
3011 VT->getPrimitiveSizeInBits().getKnownMinValue());
3022 << *NewFnTy <<
"\n");
3027 Functions.insert(NewFn);
3041 NewArgumentAttributes));
3050 return !
T->isPtrOrPtrVectorTy() ||
3073 for (
unsigned OldArgNum = 0; OldArgNum < ARIs.
size(); ++OldArgNum) {
3074 unsigned NewFirstArgNum = NewArgOperands.
size();
3075 (void)NewFirstArgNum;
3076 if (
const std::unique_ptr<ArgumentReplacementInfo> &ARI =
3078 if (ARI->ACSRepairCB)
3079 ARI->ACSRepairCB(*ARI, ACS, NewArgOperands);
3080 assert(ARI->getNumReplacementArgs() + NewFirstArgNum ==
3081 NewArgOperands.
size() &&
3082 "ACS repair callback did not provide as many operand as new "
3083 "types were registered!");
3085 NewArgOperandAttributes.
append(ARI->ReplacementTypes.size(),
3094 assert(NewArgOperands.
size() == NewArgOperandAttributes.
size() &&
3095 "Mismatch # argument operands vs. # argument operand attributes!");
3097 "Mismatch # argument operands vs. # function arguments!");
3106 II->getUnwindDest(), NewArgOperands,
3111 NewCI->setTailCallKind(cast<CallInst>(OldCB)->getTailCallKind());
3116 NewCB->
copyMetadata(*OldCB, {LLVMContext::MD_prof, LLVMContext::MD_dbg});
3121 OldCallAttributeList.
getRetAttrs(), NewArgOperandAttributes));
3124 LargestVectorWidth);
3126 CallSitePairs.
push_back({OldCB, NewCB});
3131 bool UsedAssumedInformation =
false;
3133 true,
nullptr, UsedAssumedInformation,
3136 assert(
Success &&
"Assumed call site replacement to succeed!");
3141 for (
unsigned OldArgNum = 0; OldArgNum < ARIs.
size();
3142 ++OldArgNum, ++OldFnArgIt) {
3143 if (
const std::unique_ptr<ArgumentReplacementInfo> &ARI =
3145 if (ARI->CalleeRepairCB)
3146 ARI->CalleeRepairCB(*ARI, *NewFn, NewFnArgIt);
3147 if (ARI->ReplacementTypes.empty())
3150 NewFnArgIt += ARI->ReplacementTypes.size();
3152 NewFnArgIt->
takeName(&*OldFnArgIt);
3159 for (
auto &CallSitePair : CallSitePairs) {
3160 CallBase &OldCB = *CallSitePair.first;
3161 CallBase &NewCB = *CallSitePair.second;
3163 "Cannot handle call sites with different types!");
3174 if (ModifiedFns.
remove(OldFn))
3175 ModifiedFns.
insert(NewFn);
3183void InformationCache::initializeInformationCache(
const Function &CF,
3190 FI.IsKernel =
F.hasFnAttribute(
"kernel");
3201 auto AddToAssumeUsesMap = [&](
const Value &
V) ->
void {
3203 if (
auto *
I = dyn_cast<Instruction>(&V))
3205 while (!Worklist.
empty()) {
3207 std::optional<short> &NumUses = AssumeUsesMap[
I];
3209 NumUses =
I->getNumUses();
3210 NumUses = *NumUses - 1;
3213 AssumeOnlyValues.insert(
I);
3214 for (
const Value *
Op :
I->operands())
3215 if (
auto *OpI = dyn_cast<Instruction>(
Op))
3221 bool IsInterestingOpcode =
false;
3228 switch (
I.getOpcode()) {
3231 "New call base instruction type needs to be known in the "
3234 case Instruction::Call:
3238 if (
auto *Assume = dyn_cast<AssumeInst>(&
I)) {
3239 AssumeOnlyValues.insert(Assume);
3241 AddToAssumeUsesMap(*
Assume->getArgOperand(0));
3242 }
else if (cast<CallInst>(
I).isMustTailCall()) {
3243 FI.ContainsMustTailCall =
true;
3244 if (
auto *Callee = dyn_cast_if_present<Function>(
3245 cast<CallInst>(
I).getCalledOperand()))
3246 getFunctionInfo(*Callee).CalledViaMustTail =
true;
3249 case Instruction::CallBr:
3250 case Instruction::Invoke:
3251 case Instruction::CleanupRet:
3252 case Instruction::CatchSwitch:
3253 case Instruction::AtomicRMW:
3254 case Instruction::AtomicCmpXchg:
3255 case Instruction::Br:
3256 case Instruction::Resume:
3257 case Instruction::Ret:
3258 case Instruction::Load:
3260 case Instruction::Store:
3262 case Instruction::Alloca:
3263 case Instruction::AddrSpaceCast:
3264 IsInterestingOpcode =
true;
3266 if (IsInterestingOpcode) {
3267 auto *&Insts = FI.OpcodeInstMap[
I.getOpcode()];
3272 if (
I.mayReadOrWriteMemory())
3273 FI.RWInsts.push_back(&
I);
3276 if (
F.hasFnAttribute(Attribute::AlwaysInline) &&
3278 InlineableFunctions.insert(&
F);
3281InformationCache::FunctionInfo::~FunctionInfo() {
3284 for (
auto &It : OpcodeInstMap)
3285 It.getSecond()->~InstructionVectorTy();
3290 assert(
A.isClosedWorldModule() &&
"Cannot see all indirect callees!");
3291 return IndirectlyCallableFunctions;
3295 if (TargetTriple.
isGPU())
3297 return std::nullopt;
3308 if (DependenceStack.empty())
3312 DependenceStack.back()->push_back({&FromAA, &ToAA, DepClass});
3315void Attributor::rememberDependences() {
3316 assert(!DependenceStack.empty() &&
"No dependences to remember!");
3318 for (DepInfo &DI : *DependenceStack.back()) {
3321 "Expected required or optional dependence (1 bit)!");
3328template <Attribute::AttrKind AK,
typename AAType>
3330 bool SkipHasAttrCheck) {
3332 if (SkipHasAttrCheck || !
Attrs.hasAttribute(AK))
3336 getOrCreateAAFor<AAType>(IRP);
3340 if (!VisitedFunctions.insert(&
F).second)
3342 if (
F.isDeclaration())
3348 InformationCache::FunctionInfo &FI = InfoCache.getFunctionInfo(
F);
3350 for (
const Use &U :
F.uses())
3351 if (
const auto *CB = dyn_cast<CallBase>(U.getUser()))
3352 if (CB->isCallee(&U) && CB->isMustTailCall())
3353 FI.CalledViaMustTail =
true;
3358 auto Attrs =
F.getAttributes();
3359 auto FnAttrs = Attrs.getFnAttrs();
3364 getOrCreateAAFor<AAIsDead>(FPos);
3368 getOrCreateAAFor<AAUndefinedBehavior>(FPos);
3372 getOrCreateAAFor<AAHeapToStack>(FPos);
3375 checkAndQueryIRAttr<Attribute::MustProgress, AAMustProgress>(FPos, FnAttrs);
3378 checkAndQueryIRAttr<Attribute::NoFree, AANoFree>(FPos, FnAttrs);
3381 checkAndQueryIRAttr<Attribute::WillReturn, AAWillReturn>(FPos, FnAttrs);
3384 checkAndQueryIRAttr<Attribute::NoSync, AANoSync>(FPos, FnAttrs);
3389 if (IsIPOAmendable) {
3392 checkAndQueryIRAttr<Attribute::NoUnwind, AANoUnwind>(FPos, FnAttrs);
3395 checkAndQueryIRAttr<Attribute::NoReturn, AANoReturn>(FPos, FnAttrs);
3398 checkAndQueryIRAttr<Attribute::NoRecurse, AANoRecurse>(FPos, FnAttrs);
3401 if (Attrs.hasFnAttr(Attribute::Convergent))
3402 getOrCreateAAFor<AANonConvergent>(FPos);
3405 getOrCreateAAFor<AAMemoryBehavior>(FPos);
3408 getOrCreateAAFor<AAMemoryLocation>(FPos);
3411 getOrCreateAAFor<AAAssumptionInfo>(FPos);
3419 getOrCreateAAFor<AADenormalFPMath>(FPos);
3422 Type *ReturnType =
F.getReturnType();
3423 if (!ReturnType->isVoidTy()) {
3428 getOrCreateAAFor<AAIsDead>(RetPos);
3431 bool UsedAssumedInformation =
false;
3436 checkAndQueryIRAttr<Attribute::NoUndef, AANoUndef>(RetPos, RetAttrs);
3438 if (ReturnType->isPointerTy()) {
3441 getOrCreateAAFor<AAAlign>(RetPos);
3444 checkAndQueryIRAttr<Attribute::NonNull, AANonNull>(RetPos, RetAttrs);
3447 checkAndQueryIRAttr<Attribute::NoAlias, AANoAlias>(RetPos, RetAttrs);
3451 getOrCreateAAFor<AADereferenceable>(RetPos);
3453 getOrCreateAAFor<AANoFPClass>(RetPos);
3460 auto ArgNo = Arg.getArgNo();
3463 if (!IsIPOAmendable) {
3464 if (Arg.getType()->isPointerTy())
3466 checkAndQueryIRAttr<Attribute::NoFree, AANoFree>(ArgPos, ArgAttrs);
3473 bool UsedAssumedInformation =
false;
3478 getOrCreateAAFor<AAIsDead>(ArgPos);
3481 checkAndQueryIRAttr<Attribute::NoUndef, AANoUndef>(ArgPos, ArgAttrs);
3483 if (Arg.getType()->isPointerTy()) {
3485 checkAndQueryIRAttr<Attribute::NonNull, AANonNull>(ArgPos, ArgAttrs);
3488 checkAndQueryIRAttr<Attribute::NoAlias, AANoAlias>(ArgPos, ArgAttrs);
3491 getOrCreateAAFor<AADereferenceable>(ArgPos);
3494 getOrCreateAAFor<AAAlign>(ArgPos);
3497 checkAndQueryIRAttr<Attribute::Captures, AANoCapture>(
3498 ArgPos, ArgAttrs,
true);
3502 getOrCreateAAFor<AAMemoryBehavior>(ArgPos);
3505 checkAndQueryIRAttr<Attribute::NoFree, AANoFree>(ArgPos, ArgAttrs);
3509 getOrCreateAAFor<AAPrivatizablePtr>(ArgPos);
3511 getOrCreateAAFor<AANoFPClass>(ArgPos);
3516 auto &CB = cast<CallBase>(
I);
3522 getOrCreateAAFor<AAIsDead>(CBInstPos);
3524 Function *Callee = dyn_cast_if_present<Function>(CB.getCalledOperand());
3528 getOrCreateAAFor<AAIndirectCallInfo>(CBFnPos);
3533 getOrCreateAAFor<AAAssumptionInfo>(CBFnPos);
3538 !Callee->hasMetadata(LLVMContext::MD_callback))
3541 if (!Callee->getReturnType()->isVoidTy() && !CB.use_empty()) {
3543 bool UsedAssumedInformation =
false;
3548 getOrCreateAAFor<AANoFPClass>(CBInstPos);
3552 for (
int I = 0, E = CB.arg_size();
I < E; ++
I) {
3558 getOrCreateAAFor<AAIsDead>(CBArgPos);
3563 bool UsedAssumedInformation =
false;
3568 checkAndQueryIRAttr<Attribute::NoUndef, AANoUndef>(CBArgPos, CBArgAttrs);
3570 Type *ArgTy = CB.getArgOperand(
I)->getType();
3574 getOrCreateAAFor<AANoFPClass>(CBArgPos);
3580 checkAndQueryIRAttr<Attribute::NonNull, AANonNull>(CBArgPos, CBArgAttrs);
3583 checkAndQueryIRAttr<Attribute::Captures, AANoCapture>(
3584 CBArgPos, CBArgAttrs,
true);
3587 checkAndQueryIRAttr<Attribute::NoAlias, AANoAlias>(CBArgPos, CBArgAttrs);
3590 getOrCreateAAFor<AADereferenceable>(CBArgPos);
3593 getOrCreateAAFor<AAAlign>(CBArgPos);
3598 getOrCreateAAFor<AAMemoryBehavior>(CBArgPos);
3601 checkAndQueryIRAttr<Attribute::NoFree, AANoFree>(CBArgPos, CBArgAttrs);
3607 [[maybe_unused]]
bool Success;
3608 bool UsedAssumedInformation =
false;
3610 nullptr, OpcodeInstMap, CallSitePred,
nullptr,
nullptr,
3611 {(
unsigned)Instruction::Invoke, (
unsigned)Instruction::CallBr,
3613 UsedAssumedInformation);
3614 assert(
Success &&
"Expected the check call to be successful!");
3617 if (
auto *LI = dyn_cast<LoadInst>(&
I)) {
3622 getOrCreateAAFor<AAInvariantLoadPointer>(
3624 getOrCreateAAFor<AAAddressSpace>(
3627 auto &SI = cast<StoreInst>(
I);
3632 getOrCreateAAFor<AAAddressSpace>(
3638 nullptr, OpcodeInstMap, LoadStorePred,
nullptr,
nullptr,
3639 {(
unsigned)Instruction::Load, (
unsigned)Instruction::Store},
3640 UsedAssumedInformation);
3641 assert(
Success &&
"Expected the check call to be successful!");
3644 auto AAAllocationInfoPred = [&](
Instruction &
I) ->
bool {
3650 nullptr, OpcodeInstMap, AAAllocationInfoPred,
nullptr,
nullptr,
3651 {(
unsigned)Instruction::Alloca}, UsedAssumedInformation);
3652 assert(
Success &&
"Expected the check call to be successful!");
3675 return OS <<
"fn_ret";
3677 return OS <<
"cs_ret";
3685 return OS <<
"cs_arg";
3707 return OS << static_cast<const AbstractState &>(S);
3721 OS <<
"set-state(< {";
3737 OS <<
"set-state(< {";
3742 if (
auto *
F = dyn_cast<Function>(It.first.getValue()))
3743 OS <<
"@" <<
F->getName() <<
"[" << int(It.second) <<
"], ";
3745 OS << *It.first.getValue() <<
"[" << int(It.second) <<
"], ";
3758 OS <<
"] for CtxI ";
3765 OS <<
"<<null inst>>";
3774 for (
const auto &DepAA :
Deps) {
3775 auto *AA = DepAA.getPointer();
3792 OS <<
" [ <unknown> ]";
3806 bool DeleteFns,
bool IsModulePass) {
3807 if (Functions.
empty())
3811 dbgs() <<
"[Attributor] Run on module with " << Functions.
size()
3820 AC.IsModulePass = IsModulePass;
3821 AC.DeleteFns = DeleteFns;
3825 IndirectCalleeTrackingMap;
3827 AC.IndirectCalleeSpecializationCallback =
3832 auto &Set = IndirectCalleeTrackingMap[&CB];
3834 Set = std::make_unique<SmallPtrSet<Function *, 8>>();
3836 return Set->contains(&Callee);
3837 Set->insert(&Callee);
3847 if (!
A.isFunctionIPOAmendable(*
F))
3855 unsigned FunSize = Functions.
size();
3856 for (
unsigned u = 0; u < FunSize; u++) {
3858 if (!
F->isDeclaration() && !
F->isDefinitionExact() && !
F->use_empty() &&
3861 assert(NewF &&
"Could not internalize function.");
3866 for (
const Use &U : NewF->
uses())
3867 if (
CallBase *CB = dyn_cast<CallBase>(U.getUser())) {
3868 auto *CallerF = CB->getCaller();
3876 if (
F->hasExactDefinition())
3877 NumFnWithExactDefinition++;
3879 NumFnWithoutExactDefinition++;
3884 if (
F->hasLocalLinkage()) {
3886 const auto *CB = dyn_cast<CallBase>(U.getUser());
3887 return CB && CB->isCallee(&U) &&
3888 Functions.count(const_cast<Function *>(CB->getCaller()));
3895 A.identifyDefaultAbstractAttributes(*
F);
3901 <<
" functions, result: " << Changed <<
".\n");
3910 bool IsModulePass) {
3911 if (Functions.
empty())
3915 dbgs() <<
"[AttributorLight] Run on module with " << Functions.
size()
3924 AC.IsModulePass = IsModulePass;
3925 AC.DeleteFns =
false;
3932 AC.Allowed = &Allowed;
3933 AC.UseLiveness =
false;
3938 if (
F->hasExactDefinition())
3939 NumFnWithExactDefinition++;
3941 NumFnWithoutExactDefinition++;
3946 if (AC.UseLiveness &&
F->hasLocalLinkage()) {
3948 const auto *CB = dyn_cast<CallBase>(U.getUser());
3949 return CB && CB->isCallee(&U) &&
3950 Functions.count(const_cast<Function *>(CB->getCaller()));
3957 A.identifyDefaultAbstractAttributes(*
F);
3968 for (
Function *Changed :
A.getModifiedFunctions()) {
3974 for (
auto *U : Changed->users()) {
3975 if (
auto *Call = dyn_cast<CallBase>(U)) {
3976 if (Call->getCalledFunction() == Changed)
3983 <<
" functions, result: " << Changed <<
".\n");
3990 static std::atomic<int> CallTimes;
3996 Prefix =
"dep_graph";
3997 std::string Filename =
3998 Prefix +
"_" + std::to_string(CallTimes.load()) +
".dot";
4000 outs() <<
"Dependency graph dump to " << Filename <<
".\n";
4013 cast<AbstractAttribute>(DepAA.getPointer())->printWithDeps(
outs());
4046 Functions.
insert(&
N.getFunction());
4048 if (Functions.
empty())
4102 Functions.
insert(&
N.getFunction());
4104 if (Functions.
empty())
4159 std::string AAString;
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 isPotentiallyReachable(Attributor &A, const Instruction &FromI, const Instruction *ToI, const Function &ToFn, const AbstractAttribute &QueryingAA, const AA::InstExclusionSetTy *ExclusionSet, std::function< bool(const Function &F)> GoBackwardsCB)
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< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
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...
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
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
static bool isSimple(Instruction *I)
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.
static Function * getFunction(FunctionType *Ty, const Twine &Name, Module *M)
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 <a particular IR unit>" (e....
A container for analyses that lazily runs them and caches their results.
void invalidate(IRUnitT &IR, const PreservedAnalyses &PA)
Invalidate cached analyses for an IR unit.
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.
LLVM_ABI AttributeSet getFnAttrs() const
The function attributes are returned.
static LLVM_ABI AttributeList get(LLVMContext &C, ArrayRef< std::pair< unsigned, Attribute > > Attrs)
Create an AttributeList with the specified parameters in it.
LLVM_ABI AttributeSet getRetAttrs() const
The attributes for the ret value are returned.
LLVM_ABI bool hasAttrSomewhere(Attribute::AttrKind Kind, unsigned *Index=nullptr) const
Return true if the specified attribute is set for at least one parameter or for the return value.
bool hasParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) const
Return true if the attribute exists for the given argument.
LLVM_ABI AttributeSet getParamAttrs(unsigned ArgNo) const
The attributes for the argument or parameter at the given index are returned.
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.
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 Instruction & front() const
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
LLVM_ABI const BasicBlock * getUniquePredecessor() const
Return the predecessor of this block if it has a unique predecessor block.
const Function * getParent() const
Return the enclosing method, or null if none.
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...
Allocate memory in an ever growing pool, as if by bump-pointer.
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 removeFunction(Function &Fn)
Remove Fn from the call graph.
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.
This class represents an Operation in the Expression.
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.
LLVM_ABI bool dominates(const BasicBlock *BB, const Use &U) const
Return true if the (end of the) basic block BB dominates the use U.
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).
An analysis over an "outer" IR unit that provides access to an analysis manager over an "inner" IR un...
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)
Create MemoryEffectsBase that can only access argument memory.
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
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.
const value_type & front() const
Return the first element of the SetVector.
const value_type & back() const
Return the last element of 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.
bool empty() const
Determine if the SetVector is empty or not.
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.
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.
bool isGPU() const
Test whether the target triple is for a GPU.
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
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 isFloatingPointTy() const
Return true if this is one of the floating-point types.
bool isPtrOrPtrVectorTy() const
Return true if this is a pointer type or a vector of pointer types.
bool isIntegerTy() const
True if this is an instance of IntegerType.
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.
Value handle that is nullable, but tries to track the Value.
int getNumOccurrences() const
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
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.
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.
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.
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.
LLVM_ABI bool isNoFPClassCompatibleType(Type *Ty)
Returns true if this is a type legal for the 'nofpclass' attribute.
LLVM_ABI void updateMinLegalVectorWidthAttr(Function &Fn, uint64_t Width)
Update min-legal-vector-width if it is in Attribute and less than Width.
@ C
The default llvm calling convention, compatible with C.
initializer< Ty > init(const Ty &Val)
LocationClass< Ty > location(Ty &L)
@ Assume
Do not drop type tests (default).
DiagnosticInfoOptimizationBase::Argument NV
@ 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.
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,...
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.
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.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
LLVM_ABI bool isNoAliasCall(const Value *V)
Return true if this pointer is returned by a noalias function.
raw_ostream & WriteGraph(raw_ostream &O, const GraphType &G, bool ShortNames=false, const Twine &Title="")
LLVM_ABI InlineResult isInlineViable(Function &Callee)
Check if it is mechanically possible to inline the function Callee, based on the contents of the func...
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...
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.
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.
@ 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...
bool operator&=(SparseBitVector< ElementSize > *LHS, const SparseBitVector< ElementSize > &RHS)
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)
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.
APInt operator|(APInt a, const APInt &b)
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.
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.
static LLVM_ABI const fltSemantics & IEEEsingle() LLVM_READNONE
Base struct for all "concrete attribute" deductions.
ChangeStatus update(Attributor &A)
Hook for the Attributor to trigger an update of the internal state.
virtual ChangeStatus manifest(Attributor &A)
Hook for the Attributor to trigger the manifestation of the information represented by the abstract a...
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 ~AbstractAttribute()=default
Virtual destructor.
virtual const std::string getAsStr(Attributor *A) const =0
This function should return the "summarized" assumed state as string.
virtual bool isQueryAA() const
A query AA is always scheduled as long as we do updates because it does lazy computation that cannot ...
virtual ChangeStatus updateImpl(Attributor &A)=0
The actual update/transfer function which has to be implemented by the derived classes.
virtual void trackStatistics() const =0
Hook to enable custom statistic tracking, called after manifest that resulted in a change if statisti...
virtual StringRef getName() const =0
This function should return the name of the AbstractAttribute.
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.
virtual ChangeStatus indicateOptimisticFixpoint()=0
Indicate that the abstract state should converge to the optimistic 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.
bool UseLiveness
Flag to determine if we should skip all liveness checks early on.
std::optional< unsigned > MaxFixpointIterations
Maximum number of iterations to run until fixpoint.
DenseSet< const char * > * Allowed
If not null, a set limiting the attribute opportunities.
bool RewriteSignatures
Flag to determine if we rewrite function signatures.
bool DeleteFns
Flag to determine if we can delete functions or keep dead ones around.
bool IsClosedWorldModule
Flag to indicate if the entire world is contained in this module, that is, no outside functions exist...
CallGraphUpdater & CGUpdater
Helper to update an underlying call graph and to delete functions.
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 &, AbstractCallSite, SmallVectorImpl< Value * > &)> ACSRepairCBTy
Abstract call site (ACS) repair callback type.
std::function< void(const ArgumentReplacementInfo &, Function &, Function::arg_iterator)> CalleeRepairCBTy
Callee 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.
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.
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.
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.
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.
std::function< bool(Attributor &, const AbstractAttribute *)> VirtualUseCallbackTy
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)
DOTGraphTraits - Template class that can be specialized to customize how graphs are converted to 'dot...
DefaultDOTGraphTraits - This class provides the default implementations of all of the DOTGraphTraits ...
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)
static ChildIteratorType child_end(NodeRef N)
static NodeRef getEntryNode(AADepGraphNode *DGN)
static ChildIteratorType child_begin(NodeRef N)
AADepGraphNode::DepSetTy::iterator ChildEdgeIteratorType
static NodeRef getEntryNode(AADepGraph *DG)
static nodes_iterator nodes_begin(AADepGraph *DG)
static nodes_iterator nodes_end(AADepGraph *DG)
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.