56#ifdef EXPENSIVE_CHECKS
66#define DEBUG_TYPE "attributor"
67#define VERBOSE_DEBUG_TYPE DEBUG_TYPE "-verbose"
70 "Determine what attributes are manifested in the IR");
72STATISTIC(NumFnDeleted,
"Number of function deleted");
74 "Number of functions with exact definitions");
76 "Number of functions without exact definitions");
77STATISTIC(NumFnShallowWrappersCreated,
"Number of shallow wrappers created");
79 "Number of abstract attributes timed out before fixpoint");
81 "Number of abstract attributes in a valid fixpoint state");
83 "Number of abstract attributes manifested in IR");
95 cl::desc(
"Maximal number of fixpoint iterations."),
101 cl::desc(
"Maximal number of callees specialized for "
106 "attributor-max-initialization-chain-length",
cl::Hidden,
108 "Maximal number of chained initializations (to avoid stack overflows)"),
114 cl::desc(
"Annotate call sites of function declarations."),
cl::init(
false));
121 cl::desc(
"Allow the Attributor to create shallow "
122 "wrappers for non-exact definitions."),
127 cl::desc(
"Allow the Attributor to use IP information "
128 "derived from non-exact functions via cloning"),
135 cl::desc(
"Comma seperated list of attribute names that are "
136 "allowed to be seeded."),
140 "attributor-function-seed-allow-list",
cl::Hidden,
141 cl::desc(
"Comma seperated list of function names that are "
142 "allowed to be seeded."),
148 cl::desc(
"Dump the dependency graph to dot files."),
152 "attributor-depgraph-dot-filename-prefix",
cl::Hidden,
153 cl::desc(
"The prefix used for the CallGraph dot file names."));
156 cl::desc(
"View the dependency graph."),
160 cl::desc(
"Print attribute dependencies"),
164 "attributor-enable-call-site-specific-deduction",
cl::Hidden,
165 cl::desc(
"Allow the Attributor to do call site specific analysis"),
170 cl::desc(
"Print Attributor's internal call graph"),
175 cl::desc(
"Try to simplify all loads."),
180 cl::desc(
"Should a closed world be assumed, or not. Default if not set."));
186 return L == ChangeStatus::CHANGED ? L : R;
193 return L == ChangeStatus::UNCHANGED ? L : R;
203 return T.isAMDGPU() ||
T.isNVPTX();
209 if (
const auto *CB = dyn_cast<CallBase>(&
I)) {
210 if (CB->hasFnAttr(Attribute::NoSync))
214 if (!CB->isConvergent() && !CB->mayReadOrWriteMemory())
221 return AA::hasAssumedIRAttr<Attribute::NoSync>(
223 DepClassTy::OPTIONAL, IsKnownNoSync);
226 if (!
I.mayReadOrWriteMemory())
233 const Value &V,
bool ForAnalysisOnly) {
235 if (!ForAnalysisOnly)
246 if (isa<AllocaInst>(Obj))
250 auto *GV = dyn_cast<GlobalVariable>(&Obj);
254 bool UsedAssumedInformation =
false;
256 if (
A.hasGlobalVariableSimplificationCallback(*GV)) {
257 auto AssumedGV =
A.getAssumedInitializerFromCallBack(
258 *GV, &QueryingAA, UsedAssumedInformation);
259 Initializer = *AssumedGV;
263 if (!GV->hasLocalLinkage() &&
264 (GV->isInterposable() || !(GV->isConstant() && GV->hasInitializer())))
266 if (!GV->hasInitializer())
270 Initializer = GV->getInitializer();
282 if (isa<Constant>(V))
284 if (
auto *
I = dyn_cast<Instruction>(&V))
285 return I->getFunction() == Scope;
286 if (
auto *
A = dyn_cast<Argument>(&V))
287 return A->getParent() == Scope;
299 if (
auto *
A = dyn_cast<Argument>(VAC.
getValue()))
300 return A->getParent() == Scope;
301 if (
auto *
I = dyn_cast<Instruction>(VAC.
getValue())) {
302 if (
I->getFunction() == Scope) {
306 return DT->dominates(
I, CtxI);
308 if (CtxI &&
I->getParent() == CtxI->
getParent())
311 [&](
const Instruction &AfterI) { return &AfterI == CtxI; });
318 if (V.getType() == &Ty)
320 if (isa<PoisonValue>(V))
322 if (isa<UndefValue>(V))
324 if (
auto *
C = dyn_cast<Constant>(&V)) {
325 if (
C->isNullValue())
339std::optional<Value *>
341 const std::optional<Value *> &
B,
354 Ty = (*A)->getType();
355 if (isa_and_nonnull<UndefValue>(*
A))
357 if (isa<UndefValue>(*
B))
364template <
bool IsLoad,
typename Ty>
370 LLVM_DEBUG(
dbgs() <<
"Trying to determine the potential copies of " <<
I
371 <<
" (only exact: " << OnlyExact <<
")\n";);
382 A.getInfoCache().getTargetLibraryInfoForFunction(*
I.getFunction());
384 auto Pred = [&](
Value &Obj) {
386 if (isa<UndefValue>(&Obj))
388 if (isa<ConstantPointerNull>(&Obj)) {
392 Ptr.getType()->getPointerAddressSpace()) &&
393 A.getAssumedSimplified(
Ptr, QueryingAA, UsedAssumedInformation,
397 dbgs() <<
"Underlying object is a valid nullptr, giving up.\n";);
401 if (!isa<AllocaInst>(&Obj) && !isa<GlobalVariable>(&Obj) &&
403 LLVM_DEBUG(
dbgs() <<
"Underlying object is not supported yet: " << Obj
407 if (
auto *GV = dyn_cast<GlobalVariable>(&Obj))
408 if (!GV->hasLocalLinkage() &&
409 !(GV->isConstant() && GV->hasInitializer())) {
411 "linkage, not supported yet: "
416 bool NullOnly =
true;
417 bool NullRequired =
false;
418 auto CheckForNullOnlyAndUndef = [&](std::optional<Value *> V,
420 if (!V || *V ==
nullptr)
422 else if (isa<UndefValue>(*V))
424 else if (isa<Constant>(*V) && cast<Constant>(*V)->isNullValue())
425 NullRequired = !IsExact;
434 LLVM_DEBUG(
dbgs() <<
"Underlying object written but stored value "
435 "cannot be converted to read type: "
448 if (PotentialValueOrigins && !isa<AssumeInst>(Acc.
getRemoteInst()))
452 if (NewCopies.
count(V)) {
457 if (
Value *V = AdjustWrittenValueType(Acc, *SI->getValueOperand()))
458 if (NewCopies.
count(V)) {
471 CheckForNullOnlyAndUndef(Acc.
getContent(), IsExact);
472 if (OnlyExact && !IsExact && !NullOnly &&
478 if (NullRequired && !NullOnly) {
479 LLVM_DEBUG(
dbgs() <<
"Required all `null` accesses due to non exact "
480 "one, however found non-null one: "
485 assert(isa<LoadInst>(
I) &&
"Expected load or store instruction only!");
491 if (PotentialValueOrigins)
497 LLVM_DEBUG(
dbgs() <<
"Underlying object written through a non-store "
498 "instruction not supported yet: "
502 Value *V = AdjustWrittenValueType(Acc, *SI->getValueOperand());
506 if (PotentialValueOrigins)
507 NewCopyOrigins.
insert(SI);
509 assert(isa<StoreInst>(
I) &&
"Expected load or store instruction only!");
511 if (!LI && OnlyExact) {
513 "instruction not supported yet: "
524 bool HasBeenWrittenTo =
false;
529 if (!PI || !PI->forallInterferingAccesses(
532 !IsLoad, CheckAccess,
533 HasBeenWrittenTo, Range, SkipCB)) {
536 <<
"Failed to verify all interfering accesses for underlying object: "
541 if (IsLoad && !HasBeenWrittenTo && !Range.isUnassigned()) {
544 A, QueryingAA, Obj, *
I.getType(), TLI,
DL, &Range);
546 LLVM_DEBUG(
dbgs() <<
"Could not determine required initial value of "
547 "underlying object, abort!\n");
550 CheckForNullOnlyAndUndef(InitialValue,
true);
551 if (NullRequired && !NullOnly) {
552 LLVM_DEBUG(
dbgs() <<
"Non exact access but initial value that is not "
553 "null or undef, abort!\n");
557 NewCopies.
insert(InitialValue);
558 if (PotentialValueOrigins)
559 NewCopyOrigins.
insert(
nullptr);
569 if (!AAUO || !AAUO->forallUnderlyingObjects(Pred)) {
571 dbgs() <<
"Underlying objects stored into could not be determined\n";);
578 for (
const auto *PI : PIs) {
579 if (!PI->getState().isAtFixpoint())
580 UsedAssumedInformation =
true;
581 A.recordDependence(*PI, QueryingAA, DepClassTy::OPTIONAL);
584 if (PotentialValueOrigins)
585 PotentialValueOrigins->
insert(NewCopyOrigins.
begin(), NewCopyOrigins.
end());
596 A, LI, PotentialValues, &PotentialValueOrigins, QueryingAA,
597 UsedAssumedInformation, OnlyExact);
605 A, SI, PotentialCopies,
nullptr, QueryingAA, UsedAssumedInformation,
611 bool RequireReadNone,
bool &IsKnown) {
612 if (RequireReadNone) {
613 if (AA::hasAssumedIRAttr<Attribute::ReadNone>(
614 A, &QueryingAA, IRP, DepClassTy::OPTIONAL, IsKnown,
617 }
else if (AA::hasAssumedIRAttr<Attribute::ReadOnly>(
618 A, &QueryingAA, IRP, DepClassTy::OPTIONAL, IsKnown,
624 const auto *MemLocAA =
626 if (MemLocAA && MemLocAA->isAssumedReadNone()) {
627 IsKnown = MemLocAA->isKnownReadNone();
629 A.recordDependence(*MemLocAA, QueryingAA, DepClassTy::OPTIONAL);
634 const auto *MemBehaviorAA =
637 (MemBehaviorAA->isAssumedReadNone() ||
638 (!RequireReadNone && MemBehaviorAA->isAssumedReadOnly()))) {
639 IsKnown = RequireReadNone ? MemBehaviorAA->isKnownReadNone()
640 : MemBehaviorAA->isKnownReadOnly();
642 A.recordDependence(*MemBehaviorAA, QueryingAA, DepClassTy::OPTIONAL);
665 std::function<
bool(
const Function &
F)> GoBackwardsCB) {
667 dbgs() <<
"[AA] isPotentiallyReachable @" << ToFn.
getName() <<
" from "
668 << FromI <<
" [GBCB: " <<
bool(GoBackwardsCB) <<
"][#ExS: "
669 << (ExclusionSet ? std::to_string(ExclusionSet->
size()) :
"none")
672 for (
auto *ES : *ExclusionSet)
673 dbgs() << *ES <<
"\n";
681 if (GoBackwardsCB && &ToFn != FromI.
getFunction() &&
684 LLVM_DEBUG(
dbgs() <<
"[AA] assume kernel cannot be reached from within the "
685 "module; success\n";);
694 if (!GoBackwardsCB && !ExclusionSet) {
696 <<
" is not checked backwards and does not have an "
697 "exclusion set, abort\n");
705 while (!Worklist.
empty()) {
707 if (!Visited.
insert(CurFromI).second)
711 if (FromFn == &ToFn) {
714 LLVM_DEBUG(
dbgs() <<
"[AA] check " << *ToI <<
" from " << *CurFromI
715 <<
" intraprocedurally\n");
718 bool Result = !ReachabilityAA || ReachabilityAA->isAssumedReachable(
719 A, *CurFromI, *ToI, ExclusionSet);
721 << (Result ?
"can potentially " :
"cannot ") <<
"reach "
722 << *ToI <<
" [Intra]\n");
732 Result = !ToReachabilityAA || ToReachabilityAA->isAssumedReachable(
733 A, EntryI, *ToI, ExclusionSet);
735 <<
" " << (Result ?
"can potentially " :
"cannot ")
736 <<
"reach @" << *ToI <<
" [ToFn]\n");
744 Result = !FnReachabilityAA || FnReachabilityAA->instructionCanReach(
745 A, *CurFromI, ToFn, ExclusionSet);
747 <<
" " << (Result ?
"can potentially " :
"cannot ")
748 <<
"reach @" << ToFn.
getName() <<
" [FromFn]\n");
757 bool Result = !ReachabilityAA || ReachabilityAA->isAssumedReachable(
758 A, *CurFromI, Ret, ExclusionSet);
760 << (Result ?
"can potentially " :
"cannot ") <<
"reach "
761 << Ret <<
" [Intra]\n");
766 bool UsedAssumedInformation =
false;
767 if (
A.checkForAllInstructions(ReturnInstCB, FromFn, &QueryingAA,
768 {Instruction::Ret}, UsedAssumedInformation)) {
773 if (!GoBackwardsCB) {
775 <<
" is not checked backwards, abort\n");
781 if (!GoBackwardsCB(*FromFn))
788 CallBase *CB = ACS.getInstruction();
792 if (isa<InvokeInst>(CB))
800 Result = !
A.checkForAllCallSites(CheckCallSite, *FromFn,
802 &QueryingAA, UsedAssumedInformation);
804 LLVM_DEBUG(
dbgs() <<
"[AA] stepping back to call sites from " << *CurFromI
805 <<
" in @" << FromFn->
getName()
806 <<
" failed, give up\n");
810 LLVM_DEBUG(
dbgs() <<
"[AA] stepped back to call sites from " << *CurFromI
811 <<
" in @" << FromFn->
getName()
812 <<
" worklist size is: " << Worklist.
size() <<
"\n");
821 std::function<
bool(
const Function &
F)> GoBackwardsCB) {
823 return ::isPotentiallyReachable(
A, FromI, &ToI, *ToFn, QueryingAA,
824 ExclusionSet, GoBackwardsCB);
831 std::function<
bool(
const Function &
F)> GoBackwardsCB) {
832 return ::isPotentiallyReachable(
A, FromI,
nullptr, ToFn, QueryingAA,
833 ExclusionSet, GoBackwardsCB);
838 if (isa<UndefValue>(Obj))
840 if (isa<AllocaInst>(Obj)) {
844 dbgs() <<
"[AA] Object '" << Obj
845 <<
"' is thread local; stack objects are thread local.\n");
848 bool IsKnownNoCapture;
849 bool IsAssumedNoCapture = AA::hasAssumedIRAttr<Attribute::NoCapture>(
853 << (IsAssumedNoCapture ?
"" :
"not") <<
" thread local; "
854 << (IsAssumedNoCapture ?
"non-" :
"")
855 <<
"captured stack object.\n");
856 return IsAssumedNoCapture;
858 if (
auto *GV = dyn_cast<GlobalVariable>(&Obj)) {
859 if (GV->isConstant()) {
861 <<
"' is thread local; constant global\n");
864 if (GV->isThreadLocal()) {
866 <<
"' is thread local; thread local global\n");
871 if (
A.getInfoCache().targetIsGPU()) {
873 (
int)AA::GPUAddressSpace::Local) {
875 <<
"' is thread local; GPU local memory\n");
879 (
int)AA::GPUAddressSpace::Constant) {
881 <<
"' is thread local; GPU constant memory\n");
886 LLVM_DEBUG(
dbgs() <<
"[AA] Object '" << Obj <<
"' is not thread local\n");
892 if (!
I.mayHaveSideEffects() && !
I.mayReadFromMemory())
897 auto AddLocationPtr = [&](std::optional<MemoryLocation> Loc) {
898 if (!Loc || !Loc->Ptr) {
900 dbgs() <<
"[AA] Access to unknown location; -> requires barriers\n");
929 auto Pred = [&](
Value &Obj) {
933 <<
"'; -> requires barrier\n");
939 if (!UnderlyingObjsAA || !UnderlyingObjsAA->forallUnderlyingObjects(Pred))
964 AB.addAttribute(Kind);
978 if (!ForceReplace && Kind == Attribute::Memory) {
982 AB.addMemoryAttr(ME);
989 AB.addAttribute(Attr);
1010 std::optional<Argument *> CBCandidateArg;
1014 for (
const Use *U : CallbackUses) {
1028 "ACS mapped into var-args arguments!");
1029 if (CBCandidateArg) {
1030 CBCandidateArg =
nullptr;
1038 if (CBCandidateArg && *CBCandidateArg)
1039 return *CBCandidateArg;
1043 auto *Callee = dyn_cast_if_present<Function>(CB.getCalledOperand());
1044 if (Callee && Callee->arg_size() >
unsigned(ArgNo))
1045 return Callee->getArg(ArgNo);
1059 LLVM_DEBUG(
dbgs() <<
"[Attributor] Update " << HasChanged <<
" " << *
this
1069 InfoCache(InfoCache), Configuration(Configuration) {
1073 if (Fn->hasAddressTaken(
nullptr,
1079 InfoCache.IndirectlyCallableFunctions.push_back(Fn);
1086 "Did expect a valid position!");
1103 unsigned AttrsSize = Attrs.size();
1106 for (
const auto &It : A2K)
1109 return AttrsSize != Attrs.size();
1112template <
typename DescTy>
1118 if (AttrDescs.
empty())
1130 auto It = AttrsMap.find(AttrListAnchor);
1131 if (It == AttrsMap.end())
1134 AL = It->getSecond();
1143 for (
const DescTy &AttrDesc : AttrDescs)
1144 if (CB(AttrDesc, AS, AM, AB))
1150 AL = AL.removeAttributesAtIndex(Ctx, AttrIdx, AM);
1151 AL = AL.addAttributesAtIndex(Ctx, AttrIdx, AB);
1152 AttrsMap[AttrListAnchor] = AL;
1158 bool IgnoreSubsumingPositions,
1160 bool Implied =
false;
1161 bool HasAttr =
false;
1164 if (AttrSet.hasAttribute(Kind)) {
1165 Implied |= Kind != ImpliedAttributeKind;
1171 updateAttrMap<Attribute::AttrKind>(EquivIRP, AttrKinds, HasAttrCB);
1177 if (IgnoreSubsumingPositions)
1194 ImpliedAttributeKind)});
1201 bool IgnoreSubsumingPositions) {
1205 if (AttrSet.hasAttribute(Kind))
1206 Attrs.push_back(AttrSet.getAttribute(Kind));
1210 updateAttrMap<Attribute::AttrKind>(EquivIRP, AttrKinds, CollectAttrCB);
1214 if (IgnoreSubsumingPositions)
1225 if (!AttrSet.hasAttribute(Kind))
1227 AM.addAttribute(Kind);
1230 return updateAttrMap<Attribute::AttrKind>(IRP, AttrKinds, RemoveAttrCB);
1237 if (!AttrSet.hasAttribute(Attr))
1239 AM.addAttribute(Attr);
1243 return updateAttrMap<StringRef>(IRP, Attrs, RemoveAttrCB);
1248 bool ForceReplace) {
1254 return updateAttrMap<Attribute>(IRP, Attrs, AddAttrCB);
1262 IRPositions.emplace_back(IRP);
1266 auto CanIgnoreOperandBundles = [](
const CallBase &CB) {
1267 return (isa<IntrinsicInst>(CB) &&
1268 cast<IntrinsicInst>(CB).getIntrinsicID() == Intrinsic ::assume);
1282 assert(CB &&
"Expected call site!");
1285 if (!CB->hasOperandBundles() || CanIgnoreOperandBundles(*CB))
1286 if (
auto *Callee = dyn_cast_if_present<Function>(CB->getCalledOperand()))
1290 assert(CB &&
"Expected call site!");
1293 if (!CB->hasOperandBundles() || CanIgnoreOperandBundles(*CB)) {
1295 dyn_cast_if_present<Function>(CB->getCalledOperand())) {
1298 for (
const Argument &Arg : Callee->args())
1299 if (Arg.hasReturnedAttr()) {
1300 IRPositions.emplace_back(
1302 IRPositions.emplace_back(
1311 assert(CB &&
"Expected call site!");
1314 if (!CB->hasOperandBundles() || CanIgnoreOperandBundles(*CB)) {
1315 auto *Callee = dyn_cast_if_present<Function>(CB->getCalledOperand());
1328void IRPosition::verify() {
1329#ifdef EXPENSIVE_CHECKS
1332 assert((CBContext ==
nullptr) &&
1333 "Invalid position must not have CallBaseContext!");
1335 "Expected a nullptr for an invalid position!");
1339 "Expected specialized kind for argument values!");
1342 assert(isa<Function>(getAsValuePtr()) &&
1343 "Expected function for a 'returned' position!");
1345 "Associated value mismatch!");
1348 assert((CBContext ==
nullptr) &&
1349 "'call site returned' position must not have CallBaseContext!");
1350 assert((isa<CallBase>(getAsValuePtr())) &&
1351 "Expected call base for 'call site returned' position!");
1353 "Associated value mismatch!");
1356 assert((CBContext ==
nullptr) &&
1357 "'call site function' position must not have CallBaseContext!");
1358 assert((isa<CallBase>(getAsValuePtr())) &&
1359 "Expected call base for 'call site function' position!");
1361 "Associated value mismatch!");
1364 assert(isa<Function>(getAsValuePtr()) &&
1365 "Expected function for a 'function' position!");
1367 "Associated value mismatch!");
1370 assert(isa<Argument>(getAsValuePtr()) &&
1371 "Expected argument for a 'argument' position!");
1373 "Associated value mismatch!");
1376 assert((CBContext ==
nullptr) &&
1377 "'call site argument' position must not have CallBaseContext!");
1378 Use *U = getAsUsePtr();
1380 assert(U &&
"Expected use for a 'call site argument' position!");
1381 assert(isa<CallBase>(U->getUser()) &&
1382 "Expected call base user for a 'call site argument' position!");
1383 assert(cast<CallBase>(U->getUser())->isArgOperand(U) &&
1384 "Expected call base argument operand for a 'call site argument' "
1386 assert(cast<CallBase>(U->getUser())->getArgOperandNo(U) ==
1388 "Argument number mismatch!");
1396std::optional<Constant *>
1399 bool &UsedAssumedInformation) {
1403 for (
auto &CB : SimplificationCallbacks.lookup(IRP)) {
1404 std::optional<Value *> SimplifiedV = CB(IRP, &AA, UsedAssumedInformation);
1406 return std::nullopt;
1407 if (isa_and_nonnull<Constant>(*SimplifiedV))
1408 return cast<Constant>(*SimplifiedV);
1416 UsedAssumedInformation)) {
1418 return std::nullopt;
1419 if (
auto *
C = dyn_cast_or_null<Constant>(
1432 for (
auto &CB : SimplificationCallbacks.lookup(IRP))
1433 return CB(IRP, AA, UsedAssumedInformation);
1439 return std::nullopt;
1452 bool &UsedAssumedInformation,
bool RecurseForSelectAndPHI) {
1456 while (!Worklist.
empty()) {
1462 int NV = Values.
size();
1463 const auto &SimplificationCBs = SimplificationCallbacks.lookup(IRP);
1464 for (
const auto &CB : SimplificationCBs) {
1465 std::optional<Value *> CBResult = CB(IRP, AA, UsedAssumedInformation);
1466 if (!CBResult.has_value())
1468 Value *V = *CBResult;
1477 if (SimplificationCBs.empty()) {
1480 const auto *PotentialValuesAA =
1482 if (PotentialValuesAA && PotentialValuesAA->getAssumedSimplifiedValues(*
this, Values, S)) {
1483 UsedAssumedInformation |= !PotentialValuesAA->isAtFixpoint();
1492 if (!RecurseForSelectAndPHI)
1495 for (
int I = NV,
E = Values.
size();
I <
E; ++
I) {
1496 Value *V = Values[
I].getValue();
1497 if (!isa<PHINode>(V) && !isa<SelectInst>(V))
1499 if (!Seen.
insert(V).second)
1502 Values[
I] = Values[
E - 1];
1516 bool &UsedAssumedInformation) {
1519 if (*V ==
nullptr || isa<Constant>(*V))
1521 if (
auto *Arg = dyn_cast<Argument>(*V))
1524 if (!Arg->hasPointeeInMemoryValueAttr())
1534 for (
auto &It : AAMap) {
1542 bool &UsedAssumedInformation,
1543 bool CheckBBLivenessOnly,
DepClassTy DepClass) {
1549 return isAssumedDead(IRP, &AA, FnLivenessAA, UsedAssumedInformation,
1550 CheckBBLivenessOnly, DepClass);
1556 bool &UsedAssumedInformation,
1557 bool CheckBBLivenessOnly,
DepClassTy DepClass) {
1560 Instruction *UserI = dyn_cast<Instruction>(U.getUser());
1563 UsedAssumedInformation, CheckBBLivenessOnly, DepClass);
1565 if (
auto *CB = dyn_cast<CallBase>(UserI)) {
1568 if (CB->isArgOperand(&U)) {
1572 UsedAssumedInformation, CheckBBLivenessOnly,
1575 }
else if (
ReturnInst *RI = dyn_cast<ReturnInst>(UserI)) {
1578 UsedAssumedInformation, CheckBBLivenessOnly, DepClass);
1579 }
else if (
PHINode *
PHI = dyn_cast<PHINode>(UserI)) {
1582 UsedAssumedInformation, CheckBBLivenessOnly, DepClass);
1583 }
else if (
StoreInst *SI = dyn_cast<StoreInst>(UserI)) {
1584 if (!CheckBBLivenessOnly && SI->getPointerOperand() != U.get()) {
1592 UsedAssumedInformation =
true;
1599 UsedAssumedInformation, CheckBBLivenessOnly, DepClass);
1605 bool &UsedAssumedInformation,
1606 bool CheckBBLivenessOnly,
DepClassTy DepClass,
1607 bool CheckForDeadStore) {
1613 if (ManifestAddedBlocks.contains(
I.getParent()))
1622 if (!FnLivenessAA || QueryingAA == FnLivenessAA)
1626 if (CheckBBLivenessOnly ? FnLivenessAA->
isAssumedDead(
I.getParent())
1631 UsedAssumedInformation =
true;
1635 if (CheckBBLivenessOnly)
1643 if (!IsDeadAA || QueryingAA == IsDeadAA)
1650 UsedAssumedInformation =
true;
1658 UsedAssumedInformation =
true;
1668 bool &UsedAssumedInformation,
1669 bool CheckBBLivenessOnly,
DepClassTy DepClass) {
1681 isAssumedDead(*CtxI, QueryingAA, FnLivenessAA, UsedAssumedInformation,
1686 if (CheckBBLivenessOnly)
1692 IsDeadAA = getOrCreateAAFor<AAIsDead>(
1699 if (!IsDeadAA || QueryingAA == IsDeadAA)
1706 UsedAssumedInformation =
true;
1725 if (!FnLivenessAA || QueryingAA == FnLivenessAA)
1741 return Pred(Callee);
1743 const auto *CallEdgesAA = getAAFor<AACallEdges>(
1745 if (!CallEdgesAA || CallEdgesAA->hasUnknownCallee())
1748 const auto &Callees = CallEdgesAA->getOptimisticEdges();
1749 return Pred(Callees.getArrayRef());
1755 bool CheckBBLivenessOnly,
DepClassTy LivenessDepClass,
1756 bool IgnoreDroppableUses,
1761 if (!CB(*
this, &QueryingAA))
1772 auto AddUsers = [&](
const Value &V,
const Use *OldUse) {
1773 for (
const Use &UU : V.uses()) {
1774 if (OldUse && EquivalentUseCB && !EquivalentUseCB(*OldUse, UU)) {
1776 "rejected by the equivalence call back: "
1786 AddUsers(V,
nullptr);
1789 <<
" initial uses to check\n");
1792 const auto *LivenessAA =
1797 while (!Worklist.
empty()) {
1799 if (isa<PHINode>(U->getUser()) && !Visited.
insert(U).second)
1802 if (
auto *Fn = dyn_cast<Function>(U->getUser()))
1803 dbgs() <<
"[Attributor] Check use: " << **U <<
" in " << Fn->getName()
1806 dbgs() <<
"[Attributor] Check use: " << **U <<
" in " << *U->getUser()
1809 bool UsedAssumedInformation =
false;
1810 if (
isAssumedDead(*U, &QueryingAA, LivenessAA, UsedAssumedInformation,
1811 CheckBBLivenessOnly, LivenessDepClass)) {
1813 dbgs() <<
"[Attributor] Dead use, skip!\n");
1816 if (IgnoreDroppableUses && U->getUser()->isDroppable()) {
1818 dbgs() <<
"[Attributor] Droppable user, skip!\n");
1822 if (
auto *SI = dyn_cast<StoreInst>(U->getUser())) {
1823 if (&SI->getOperandUse(0) == U) {
1824 if (!Visited.
insert(U).second)
1828 *
this, *SI, PotentialCopies, QueryingAA, UsedAssumedInformation,
1832 <<
"[Attributor] Value is stored, continue with "
1833 << PotentialCopies.
size()
1834 <<
" potential copies instead!\n");
1835 for (
Value *PotentialCopy : PotentialCopies)
1836 if (!AddUsers(*PotentialCopy, U))
1843 bool Follow =
false;
1844 if (!Pred(*U, Follow))
1849 User &Usr = *U->getUser();
1850 AddUsers(Usr,
nullptr);
1852 auto *RI = dyn_cast<ReturnInst>(&Usr);
1858 return AddUsers(*ACS.getInstruction(), U);
1861 &QueryingAA, UsedAssumedInformation)) {
1862 LLVM_DEBUG(
dbgs() <<
"[Attributor] Could not follow return instruction "
1863 "to all call sites: "
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");
1945 if (isa<BlockAddress>(U.getUser()))
1950 const Use *EffectiveUse =
1953 if (!RequireAllCallSites) {
1954 LLVM_DEBUG(
dbgs() <<
"[Attributor] User " << *EffectiveUse->getUser()
1955 <<
" is not a call of " << Fn.
getName()
1959 LLVM_DEBUG(
dbgs() <<
"[Attributor] User " << *EffectiveUse->getUser()
1960 <<
" is an invalid use of " << Fn.
getName() <<
"\n");
1968 unsigned MinArgsParams =
1970 for (
unsigned u = 0; u < MinArgsParams; ++u) {
1974 dbgs() <<
"[Attributor] Call site / callee argument type mismatch ["
1975 << u <<
"@" << Fn.
getName() <<
": "
1985 LLVM_DEBUG(
dbgs() <<
"[Attributor] Call site callback failed for "
1993bool Attributor::shouldPropagateCallBaseContext(
const IRPosition &IRP) {
2003 bool RecurseForSelectAndPHI) {
2007 if (!AssociatedFunction)
2010 bool UsedAssumedInformation =
false;
2014 UsedAssumedInformation, RecurseForSelectAndPHI))
2026 bool &UsedAssumedInformation,
bool CheckBBLivenessOnly =
false,
2027 bool CheckPotentiallyDead =
false) {
2028 for (
unsigned Opcode : Opcodes) {
2036 if (
A && !CheckPotentiallyDead &&
2038 UsedAssumedInformation, CheckBBLivenessOnly)) {
2040 dbgs() <<
"[Attributor] Instruction " << *
I
2041 <<
" is potentially dead, skip!\n";);
2056 bool &UsedAssumedInformation,
2057 bool CheckBBLivenessOnly,
2058 bool CheckPotentiallyDead) {
2064 const auto *LivenessAA =
2065 CheckPotentiallyDead && QueryingAA
2071 LivenessAA, Opcodes, UsedAssumedInformation,
2072 CheckBBLivenessOnly, CheckPotentiallyDead))
2081 bool &UsedAssumedInformation,
2082 bool CheckBBLivenessOnly,
2083 bool CheckPotentiallyDead) {
2087 UsedAssumedInformation, CheckBBLivenessOnly,
2088 CheckPotentiallyDead);
2093 bool &UsedAssumedInformation) {
2096 const Function *AssociatedFunction =
2098 if (!AssociatedFunction)
2102 const auto *LivenessAA =
2109 UsedAssumedInformation))
2119void Attributor::runTillFixpoint() {
2123 <<
" abstract attributes.\n");
2128 unsigned IterationCounter = 1;
2129 unsigned MaxIterations =
2139 LLVM_DEBUG(
dbgs() <<
"\n\n[Attributor] #Iteration: " << IterationCounter
2140 <<
", Worklist size: " << Worklist.
size() <<
"\n");
2145 for (
unsigned u = 0; u < InvalidAAs.
size(); ++u) {
2150 dbgs() <<
"[Attributor] InvalidAA: " << *InvalidAA
2151 <<
" has " << InvalidAA->
Deps.
size()
2152 <<
" required & optional dependences\n");
2153 for (
auto &DepIt : InvalidAA->
Deps) {
2157 dbgs() <<
" - recompute: " << *DepAA);
2162 <<
" - invalidate: " << *DepAA);
2166 InvalidAAs.
insert(DepAA);
2176 for (
auto &DepIt : ChangedAA->Deps)
2177 Worklist.
insert(cast<AbstractAttribute>(DepIt.getPointer()));
2178 ChangedAA->Deps.clear();
2181 LLVM_DEBUG(
dbgs() <<
"[Attributor] #Iteration: " << IterationCounter
2182 <<
", Worklist+Dependent size: " << Worklist.
size()
2192 const auto &AAState = AA->getState();
2193 if (!AAState.isAtFixpoint())
2195 ChangedAAs.push_back(AA);
2199 if (!AAState.isValidState())
2211 Worklist.insert(ChangedAAs.begin(), ChangedAAs.end());
2212 Worklist.insert(QueryAAsAwaitingUpdate.begin(),
2213 QueryAAsAwaitingUpdate.end());
2214 QueryAAsAwaitingUpdate.clear();
2216 }
while (!Worklist.empty() && (IterationCounter++ < MaxIterations));
2218 if (IterationCounter > MaxIterations && !Functions.
empty()) {
2220 return ORM <<
"Attributor did not reach a fixpoint after "
2221 <<
ore::NV(
"Iterations", MaxIterations) <<
" iterations.";
2224 emitRemark<OptimizationRemarkMissed>(
F,
"FixedPoint",
Remark);
2227 LLVM_DEBUG(
dbgs() <<
"\n[Attributor] Fixpoint iteration done after: "
2228 << IterationCounter <<
"/" << MaxIterations
2229 <<
" iterations\n");
2237 for (
unsigned u = 0;
u < ChangedAAs.size();
u++) {
2239 if (!Visited.
insert(ChangedAA).second)
2246 NumAttributesTimedOut++;
2249 for (
auto &DepIt : ChangedAA->
Deps)
2250 ChangedAAs.push_back(cast<AbstractAttribute>(DepIt.getPointer()));
2255 if (!Visited.
empty())
2256 dbgs() <<
"\n[Attributor] Finalized " << Visited.
size()
2257 <<
" abstract attributes.\n";
2263 "Non-query AAs should not be required to register for updates!");
2264 QueryAAsAwaitingUpdate.insert(&AA);
2271 unsigned NumManifested = 0;
2272 unsigned NumAtFixpoint = 0;
2296 bool UsedAssumedInformation =
false;
2308 LLVM_DEBUG(
dbgs() <<
"[Attributor] Manifest " << LocalChange <<
" : " << *AA
2311 ManifestChange = ManifestChange | LocalChange;
2317 (void)NumManifested;
2318 (void)NumAtFixpoint;
2319 LLVM_DEBUG(
dbgs() <<
"\n[Attributor] Manifested " << NumManifested
2320 <<
" arguments while " << NumAtFixpoint
2321 <<
" were in a valid fixpoint state\n");
2323 NumAttributesManifested += NumManifested;
2324 NumAttributesValidFixpoint += NumAtFixpoint;
2329 for (
unsigned u = 0; u < NumFinalAAs; ++u)
2333 errs() <<
"Unexpected abstract attribute: "
2334 << cast<AbstractAttribute>(DepIt->getPointer()) <<
" :: "
2335 << cast<AbstractAttribute>(DepIt->getPointer())
2337 .getAssociatedValue()
2341 "remain unchanged!");
2344 for (
auto &It : AttrsMap) {
2347 isa<Function>(It.getFirst())
2353 return ManifestChange;
2356void Attributor::identifyDeadInternalFunctions() {
2377 if (
F->hasLocalLinkage() && (
isModulePass() || !TLI->getLibFunc(*
F, LF)))
2381 bool FoundLiveInternal =
true;
2382 while (FoundLiveInternal) {
2383 FoundLiveInternal =
false;
2384 for (
unsigned u = 0, e = InternalFns.
size(); u < e; ++u) {
2389 bool UsedAssumedInformation =
false;
2393 return ToBeDeletedFunctions.count(Callee) ||
2394 (Functions.count(Callee) &&
Callee->hasLocalLinkage() &&
2395 !LiveInternalFns.
count(Callee));
2397 *
F,
true,
nullptr, UsedAssumedInformation)) {
2402 InternalFns[
u] =
nullptr;
2403 FoundLiveInternal =
true;
2407 for (
unsigned u = 0, e = InternalFns.
size(); u < e; ++u)
2409 ToBeDeletedFunctions.insert(
F);
2416 << ToBeDeletedFunctions.size() <<
" functions and "
2417 << ToBeDeletedBlocks.size() <<
" blocks and "
2418 << ToBeDeletedInsts.size() <<
" instructions and "
2419 << ToBeChangedValues.size() <<
" values and "
2420 << ToBeChangedUses.size() <<
" uses. To insert "
2421 << ToBeChangedToUnreachableInsts.size()
2422 <<
" unreachables.\n"
2423 <<
"Preserve manifest added " << ManifestAddedBlocks.size()
2429 auto ReplaceUse = [&](
Use *
U,
Value *NewV) {
2434 const auto &Entry = ToBeChangedValues.lookup(NewV);
2437 NewV = get<0>(Entry);
2442 "Cannot replace an instruction outside the current SCC!");
2446 if (
auto *RI = dyn_cast_or_null<ReturnInst>(
I)) {
2448 if (CI->isMustTailCall() && !ToBeDeletedInsts.count(CI))
2452 if (!isa<Argument>(NewV))
2453 for (
auto &Arg : RI->getFunction()->args())
2454 Arg.removeAttr(Attribute::Returned);
2458 <<
" instead of " << *OldV <<
"\n");
2462 CGModifiedFunctions.insert(
I->getFunction());
2463 if (!isa<PHINode>(
I) && !ToBeDeletedInsts.count(
I) &&
2467 if (isa<UndefValue>(NewV) && isa<CallBase>(
U->getUser())) {
2468 auto *CB = cast<CallBase>(
U->getUser());
2469 if (CB->isArgOperand(U)) {
2470 unsigned Idx = CB->getArgOperandNo(U);
2471 CB->removeParamAttr(
Idx, Attribute::NoUndef);
2472 auto *
Callee = dyn_cast_if_present<Function>(CB->getCalledOperand());
2474 Callee->removeParamAttr(
Idx, Attribute::NoUndef);
2477 if (isa<Constant>(NewV) && isa<BranchInst>(
U->getUser())) {
2479 if (isa<UndefValue>(NewV)) {
2480 ToBeChangedToUnreachableInsts.insert(UserI);
2487 for (
auto &It : ToBeChangedUses) {
2489 Value *NewV = It.second;
2490 ReplaceUse(U, NewV);
2494 for (
auto &It : ToBeChangedValues) {
2495 Value *OldV = It.first;
2496 auto [NewV,
Done] = It.second;
2498 for (
auto &U : OldV->
uses())
2499 if (
Done || !
U.getUser()->isDroppable())
2502 if (
auto *
I = dyn_cast<Instruction>(
U->getUser()))
2505 ReplaceUse(U, NewV);
2509 for (
const auto &V : InvokeWithDeadSuccessor)
2510 if (
InvokeInst *II = dyn_cast_or_null<InvokeInst>(V)) {
2512 "Cannot replace an invoke outside the current SCC!");
2513 bool UnwindBBIsDead = II->hasFnAttr(Attribute::NoUnwind);
2514 bool NormalBBIsDead = II->hasFnAttr(Attribute::NoReturn);
2515 bool Invoke2CallAllowed =
2517 assert((UnwindBBIsDead || NormalBBIsDead) &&
2518 "Invoke does not have dead successors!");
2520 BasicBlock *NormalDestBB = II->getNormalDest();
2521 if (UnwindBBIsDead) {
2523 if (Invoke2CallAllowed) {
2528 ToBeChangedToUnreachableInsts.insert(NormalNextIP);
2530 assert(NormalBBIsDead &&
"Broken invariant!");
2533 ToBeChangedToUnreachableInsts.insert(&NormalDestBB->
front());
2538 "Cannot replace a terminator outside the current SCC!");
2539 CGModifiedFunctions.insert(
I->getFunction());
2542 for (
const auto &V : ToBeChangedToUnreachableInsts)
2543 if (
Instruction *
I = dyn_cast_or_null<Instruction>(V)) {
2547 "Cannot replace an instruction outside the current SCC!");
2548 CGModifiedFunctions.insert(
I->getFunction());
2552 for (
const auto &V : ToBeDeletedInsts) {
2553 if (
Instruction *
I = dyn_cast_or_null<Instruction>(V)) {
2554 if (
auto *CB = dyn_cast<CallBase>(
I)) {
2556 "Cannot delete an instruction outside the current SCC!");
2557 if (!isa<IntrinsicInst>(CB))
2560 I->dropDroppableUses();
2561 CGModifiedFunctions.insert(
I->getFunction());
2562 if (!
I->getType()->isVoidTy())
2567 I->eraseFromParent();
2574 dbgs() <<
"[Attributor] DeadInsts size: " << DeadInsts.
size() <<
"\n";
2575 for (
auto &
I : DeadInsts)
2577 dbgs() <<
" - " << *
I <<
"\n";
2582 if (
unsigned NumDeadBlocks = ToBeDeletedBlocks.size()) {
2584 ToBeDeletedBBs.
reserve(NumDeadBlocks);
2587 "Cannot delete a block outside the current SCC!");
2588 CGModifiedFunctions.insert(BB->
getParent());
2590 if (ManifestAddedBlocks.contains(BB))
2600 identifyDeadInternalFunctions();
2603 ChangeStatus ManifestChange = rewriteFunctionSignatures(CGModifiedFunctions);
2605 for (
Function *Fn : CGModifiedFunctions)
2606 if (!ToBeDeletedFunctions.count(Fn) && Functions.count(Fn))
2609 for (
Function *Fn : ToBeDeletedFunctions) {
2610 if (!Functions.count(Fn))
2615 if (!ToBeChangedUses.empty())
2618 if (!ToBeChangedToUnreachableInsts.empty())
2621 if (!ToBeDeletedFunctions.empty())
2624 if (!ToBeDeletedBlocks.empty())
2627 if (!ToBeDeletedInsts.empty())
2630 if (!InvokeWithDeadSuccessor.empty())
2633 if (!DeadInsts.empty())
2636 NumFnDeleted += ToBeDeletedFunctions.size();
2638 LLVM_DEBUG(
dbgs() <<
"[Attributor] Deleted " << ToBeDeletedFunctions.size()
2639 <<
" functions after manifest.\n");
2641#ifdef EXPENSIVE_CHECKS
2643 if (ToBeDeletedFunctions.count(
F))
2649 return ManifestChange;
2659 Phase = AttributorPhase::UPDATE;
2672 Phase = AttributorPhase::MANIFEST;
2675 Phase = AttributorPhase::CLEANUP;
2681 return ManifestChange | CleanupChange;
2688 assert(Phase == AttributorPhase::UPDATE &&
2689 "We can update AA only in the update stage!");
2692 DependenceVector DV;
2693 DependenceStack.push_back(&DV);
2697 bool UsedAssumedInformation =
false;
2709 RerunCS = AA.
update(*
this);
2715 AAState.indicateOptimisticFixpoint();
2718 if (!AAState.isAtFixpoint())
2719 rememberDependences();
2723 DependenceVector *PoppedDV = DependenceStack.pop_back_val();
2725 assert(PoppedDV == &DV &&
"Inconsistent usage of the dependence stack!");
2731 assert(!
F.isDeclaration() &&
"Cannot create a wrapper around a declaration!");
2740 M.getFunctionList().insert(
F.getIterator(),
Wrapper);
2745 assert(
F.use_empty() &&
"Uses remained after wrapper was created!");
2750 F.setComdat(
nullptr);
2754 F.getAllMetadata(MDs);
2755 for (
auto MDIt : MDs)
2756 Wrapper->addMetadata(MDIt.first, *MDIt.second);
2757 Wrapper->setAttributes(
F.getAttributes());
2765 Args.push_back(&Arg);
2766 Arg.setName((FArgIt++)->
getName());
2774 NumFnShallowWrappersCreated++;
2778 if (
F.isDeclaration() ||
F.hasLocalLinkage() ||
2794 return InternalizedFns[&
F];
2812 F->getName() +
".internalized");
2815 for (
auto &Arg :
F->args()) {
2817 NewFArgIt->setName(ArgName);
2818 VMap[&Arg] = &(*NewFArgIt++);
2833 F->getAllMetadata(MDs);
2834 for (
auto MDIt : MDs)
2838 M.getFunctionList().insert(
F->getIterator(), Copied);
2846 auto &InternalizedFn = FnMap[
F];
2847 auto IsNotInternalized = [&](
Use &U) ->
bool {
2848 if (
auto *CB = dyn_cast<CallBase>(U.getUser()))
2849 return !FnMap.
lookup(CB->getCaller());
2852 F->replaceUsesWithIf(InternalizedFn, IsNotInternalized);
2873 if (cast<CallBase>(ACS.
getInstruction())->getCalledOperand()->getType() !=
2884 LLVM_DEBUG(
dbgs() <<
"[Attributor] Cannot rewrite var-args functions\n");
2895 dbgs() <<
"[Attributor] Cannot rewrite due to complex attribute\n");
2900 bool UsedAssumedInformation =
false;
2902 UsedAssumedInformation,
2904 LLVM_DEBUG(
dbgs() <<
"[Attributor] Cannot rewrite all call sites\n");
2909 if (
auto *CI = dyn_cast<CallInst>(&
I))
2910 return !CI->isMustTailCall();
2918 nullptr, {Instruction::Call},
2919 UsedAssumedInformation)) {
2920 LLVM_DEBUG(
dbgs() <<
"[Attributor] Cannot rewrite due to instructions\n");
2931 LLVM_DEBUG(
dbgs() <<
"[Attributor] Register new rewrite of " << Arg <<
" in "
2933 << ReplacementTypes.
size() <<
" replacements\n");
2935 "Cannot register an invalid rewrite");
2939 ArgumentReplacementMap[Fn];
2945 std::unique_ptr<ArgumentReplacementInfo> &ARI = ARIs[Arg.
getArgNo()];
2946 if (ARI && ARI->getNumReplacementArgs() <= ReplacementTypes.
size()) {
2947 LLVM_DEBUG(
dbgs() <<
"[Attributor] Existing rewrite is preferred\n");
2955 LLVM_DEBUG(
dbgs() <<
"[Attributor] Register new rewrite of " << Arg <<
" in "
2957 << ReplacementTypes.
size() <<
" replacements\n");
2961 std::move(CalleeRepairCB),
2962 std::move(ACSRepairCB)));
2983 for (
auto &It : ArgumentReplacementMap) {
2987 if (!Functions.count(OldFn) || ToBeDeletedFunctions.count(OldFn))
3000 if (
const std::unique_ptr<ArgumentReplacementInfo> &ARI =
3001 ARIs[Arg.getArgNo()]) {
3002 NewArgumentTypes.
append(ARI->ReplacementTypes.begin(),
3003 ARI->ReplacementTypes.end());
3004 NewArgumentAttributes.
append(ARI->getNumReplacementArgs(),
3007 NewArgumentTypes.
push_back(Arg.getType());
3014 for (
auto *
I : NewArgumentTypes)
3015 if (
auto *VT = dyn_cast<llvm::VectorType>(
I))
3016 LargestVectorWidth =
3017 std::max(LargestVectorWidth,
3018 VT->getPrimitiveSizeInBits().getKnownMinValue());
3029 << *NewFnTy <<
"\n");
3034 Functions.insert(NewFn);
3048 NewArgumentAttributes));
3057 return !
T->isPtrOrPtrVectorTy() ||
3071 if (
auto *BA = dyn_cast<BlockAddress>(U))
3073 for (
auto *BA : BlockAddresses)
3088 for (
unsigned OldArgNum = 0; OldArgNum < ARIs.
size(); ++OldArgNum) {
3089 unsigned NewFirstArgNum = NewArgOperands.
size();
3090 (void)NewFirstArgNum;
3091 if (
const std::unique_ptr<ArgumentReplacementInfo> &ARI =
3093 if (ARI->ACSRepairCB)
3094 ARI->ACSRepairCB(*ARI, ACS, NewArgOperands);
3095 assert(ARI->getNumReplacementArgs() + NewFirstArgNum ==
3096 NewArgOperands.
size() &&
3097 "ACS repair callback did not provide as many operand as new "
3098 "types were registered!");
3100 NewArgOperandAttributes.
append(ARI->ReplacementTypes.size(),
3109 assert(NewArgOperands.
size() == NewArgOperandAttributes.
size() &&
3110 "Mismatch # argument operands vs. # argument operand attributes!");
3112 "Mismatch # argument operands vs. # function arguments!");
3119 if (
InvokeInst *II = dyn_cast<InvokeInst>(OldCB)) {
3122 NewArgOperands, OperandBundleDefs,
"", OldCB);
3126 NewCI->setTailCallKind(cast<CallInst>(OldCB)->getTailCallKind());
3131 NewCB->
copyMetadata(*OldCB, {LLVMContext::MD_prof, LLVMContext::MD_dbg});
3136 OldCallAttributeList.
getRetAttrs(), NewArgOperandAttributes));
3139 LargestVectorWidth);
3141 CallSitePairs.
push_back({OldCB, NewCB});
3146 bool UsedAssumedInformation =
false;
3148 true,
nullptr, UsedAssumedInformation,
3151 assert(
Success &&
"Assumed call site replacement to succeed!");
3156 for (
unsigned OldArgNum = 0; OldArgNum < ARIs.
size();
3157 ++OldArgNum, ++OldFnArgIt) {
3158 if (
const std::unique_ptr<ArgumentReplacementInfo> &ARI =
3160 if (ARI->CalleeRepairCB)
3161 ARI->CalleeRepairCB(*ARI, *NewFn, NewFnArgIt);
3162 if (ARI->ReplacementTypes.empty())
3165 NewFnArgIt += ARI->ReplacementTypes.size();
3167 NewFnArgIt->
takeName(&*OldFnArgIt);
3174 for (
auto &CallSitePair : CallSitePairs) {
3175 CallBase &OldCB = *CallSitePair.first;
3176 CallBase &NewCB = *CallSitePair.second;
3178 "Cannot handle call sites with different types!");
3190 if (ModifiedFns.
remove(OldFn))
3191 ModifiedFns.
insert(NewFn);
3199void InformationCache::initializeInformationCache(
const Function &CF,
3215 auto AddToAssumeUsesMap = [&](
const Value &
V) ->
void {
3217 if (
auto *
I = dyn_cast<Instruction>(&V))
3219 while (!Worklist.
empty()) {
3221 std::optional<short> &NumUses = AssumeUsesMap[
I];
3223 NumUses =
I->getNumUses();
3224 NumUses = *NumUses - 1;
3227 AssumeOnlyValues.insert(
I);
3228 for (
const Value *
Op :
I->operands())
3229 if (
auto *OpI = dyn_cast<Instruction>(
Op))
3235 bool IsInterestingOpcode =
false;
3242 switch (
I.getOpcode()) {
3245 "New call base instruction type needs to be known in the "
3248 case Instruction::Call:
3252 if (
auto *Assume = dyn_cast<AssumeInst>(&
I)) {
3253 AssumeOnlyValues.insert(Assume);
3255 AddToAssumeUsesMap(*Assume->getArgOperand(0));
3256 }
else if (cast<CallInst>(
I).isMustTailCall()) {
3257 FI.ContainsMustTailCall =
true;
3258 if (
auto *Callee = dyn_cast_if_present<Function>(
3259 cast<CallInst>(
I).getCalledOperand()))
3260 getFunctionInfo(*Callee).CalledViaMustTail =
true;
3263 case Instruction::CallBr:
3264 case Instruction::Invoke:
3265 case Instruction::CleanupRet:
3266 case Instruction::CatchSwitch:
3267 case Instruction::AtomicRMW:
3268 case Instruction::AtomicCmpXchg:
3269 case Instruction::Br:
3270 case Instruction::Resume:
3271 case Instruction::Ret:
3272 case Instruction::Load:
3274 case Instruction::Store:
3276 case Instruction::Alloca:
3277 case Instruction::AddrSpaceCast:
3278 IsInterestingOpcode =
true;
3280 if (IsInterestingOpcode) {
3281 auto *&Insts = FI.OpcodeInstMap[
I.getOpcode()];
3286 if (
I.mayReadOrWriteMemory())
3287 FI.RWInsts.push_back(&
I);
3290 if (
F.hasFnAttribute(Attribute::AlwaysInline) &&
3292 InlineableFunctions.insert(&
F);
3295InformationCache::FunctionInfo::~FunctionInfo() {
3298 for (
auto &It : OpcodeInstMap)
3299 It.getSecond()->~InstructionVectorTy();
3304 assert(
A.isClosedWorldModule() &&
"Cannot see all indirect callees!");
3305 return IndirectlyCallableFunctions;
3316 if (DependenceStack.empty())
3320 DependenceStack.back()->push_back({&FromAA, &ToAA, DepClass});
3323void Attributor::rememberDependences() {
3324 assert(!DependenceStack.empty() &&
"No dependences to remember!");
3326 for (DepInfo &DI : *DependenceStack.back()) {
3329 "Expected required or optional dependence (1 bit)!");
3336template <Attribute::AttrKind AK,
typename AAType>
3337void Attributor::checkAndQueryIRAttr(
const IRPosition &IRP,
3340 if (!
Attrs.hasAttribute(AK))
3344 getOrCreateAAFor<AAType>(IRP);
3348 if (!VisitedFunctions.insert(&
F).second)
3350 if (
F.isDeclaration())
3356 InformationCache::FunctionInfo &FI = InfoCache.getFunctionInfo(
F);
3358 for (
const Use &U :
F.uses())
3359 if (
const auto *CB = dyn_cast<CallBase>(U.getUser()))
3360 if (CB->isCallee(&U) && CB->isMustTailCall())
3361 FI.CalledViaMustTail =
true;
3366 auto Attrs =
F.getAttributes();
3367 auto FnAttrs = Attrs.getFnAttrs();
3372 getOrCreateAAFor<AAIsDead>(FPos);
3376 getOrCreateAAFor<AAUndefinedBehavior>(FPos);
3380 getOrCreateAAFor<AAHeapToStack>(FPos);
3383 checkAndQueryIRAttr<Attribute::MustProgress, AAMustProgress>(FPos, FnAttrs);
3386 checkAndQueryIRAttr<Attribute::NoFree, AANoFree>(FPos, FnAttrs);
3389 checkAndQueryIRAttr<Attribute::WillReturn, AAWillReturn>(FPos, FnAttrs);
3392 checkAndQueryIRAttr<Attribute::NoSync, AANoSync>(FPos, FnAttrs);
3397 if (IsIPOAmendable) {
3400 checkAndQueryIRAttr<Attribute::NoUnwind, AANoUnwind>(FPos, FnAttrs);
3403 checkAndQueryIRAttr<Attribute::NoReturn, AANoReturn>(FPos, FnAttrs);
3406 checkAndQueryIRAttr<Attribute::NoRecurse, AANoRecurse>(FPos, FnAttrs);
3409 if (Attrs.hasFnAttr(Attribute::Convergent))
3410 getOrCreateAAFor<AANonConvergent>(FPos);
3413 getOrCreateAAFor<AAMemoryBehavior>(FPos);
3416 getOrCreateAAFor<AAMemoryLocation>(FPos);
3419 getOrCreateAAFor<AAAssumptionInfo>(FPos);
3427 getOrCreateAAFor<AADenormalFPMath>(FPos);
3430 Type *ReturnType =
F.getReturnType();
3431 if (!ReturnType->isVoidTy()) {
3436 getOrCreateAAFor<AAIsDead>(RetPos);
3439 bool UsedAssumedInformation =
false;
3444 checkAndQueryIRAttr<Attribute::NoUndef, AANoUndef>(RetPos, RetAttrs);
3446 if (ReturnType->isPointerTy()) {
3449 getOrCreateAAFor<AAAlign>(RetPos);
3452 checkAndQueryIRAttr<Attribute::NonNull, AANonNull>(RetPos, RetAttrs);
3455 checkAndQueryIRAttr<Attribute::NoAlias, AANoAlias>(RetPos, RetAttrs);
3459 getOrCreateAAFor<AADereferenceable>(RetPos);
3461 getOrCreateAAFor<AANoFPClass>(RetPos);
3468 auto ArgNo = Arg.getArgNo();
3471 if (!IsIPOAmendable) {
3472 if (Arg.getType()->isPointerTy())
3474 checkAndQueryIRAttr<Attribute::NoFree, AANoFree>(ArgPos, ArgAttrs);
3481 bool UsedAssumedInformation =
false;
3486 getOrCreateAAFor<AAIsDead>(ArgPos);
3489 checkAndQueryIRAttr<Attribute::NoUndef, AANoUndef>(ArgPos, ArgAttrs);
3491 if (Arg.getType()->isPointerTy()) {
3493 checkAndQueryIRAttr<Attribute::NonNull, AANonNull>(ArgPos, ArgAttrs);
3496 checkAndQueryIRAttr<Attribute::NoAlias, AANoAlias>(ArgPos, ArgAttrs);
3499 getOrCreateAAFor<AADereferenceable>(ArgPos);
3502 getOrCreateAAFor<AAAlign>(ArgPos);
3505 checkAndQueryIRAttr<Attribute::NoCapture, AANoCapture>(ArgPos, ArgAttrs);
3509 getOrCreateAAFor<AAMemoryBehavior>(ArgPos);
3512 checkAndQueryIRAttr<Attribute::NoFree, AANoFree>(ArgPos, ArgAttrs);
3516 getOrCreateAAFor<AAPrivatizablePtr>(ArgPos);
3518 getOrCreateAAFor<AANoFPClass>(ArgPos);
3523 auto &CB = cast<CallBase>(
I);
3529 getOrCreateAAFor<AAIsDead>(CBInstPos);
3531 Function *Callee = dyn_cast_if_present<Function>(CB.getCalledOperand());
3535 getOrCreateAAFor<AAIndirectCallInfo>(CBFnPos);
3540 getOrCreateAAFor<AAAssumptionInfo>(CBFnPos);
3545 !Callee->hasMetadata(LLVMContext::MD_callback))
3548 if (!Callee->getReturnType()->isVoidTy() && !CB.use_empty()) {
3550 bool UsedAssumedInformation =
false;
3555 getOrCreateAAFor<AANoFPClass>(CBInstPos);
3559 for (
int I = 0,
E = CB.arg_size();
I <
E; ++
I) {
3565 getOrCreateAAFor<AAIsDead>(CBArgPos);
3570 bool UsedAssumedInformation =
false;
3575 checkAndQueryIRAttr<Attribute::NoUndef, AANoUndef>(CBArgPos, CBArgAttrs);
3577 Type *ArgTy = CB.getArgOperand(
I)->getType();
3581 getOrCreateAAFor<AANoFPClass>(CBArgPos);
3587 checkAndQueryIRAttr<Attribute::NonNull, AANonNull>(CBArgPos, CBArgAttrs);
3590 checkAndQueryIRAttr<Attribute::NoCapture, AANoCapture>(CBArgPos,
3594 checkAndQueryIRAttr<Attribute::NoAlias, AANoAlias>(CBArgPos, CBArgAttrs);
3597 getOrCreateAAFor<AADereferenceable>(CBArgPos);
3600 getOrCreateAAFor<AAAlign>(CBArgPos);
3605 getOrCreateAAFor<AAMemoryBehavior>(CBArgPos);
3608 checkAndQueryIRAttr<Attribute::NoFree, AANoFree>(CBArgPos, CBArgAttrs);
3614 [[maybe_unused]]
bool Success;
3615 bool UsedAssumedInformation =
false;
3617 nullptr, OpcodeInstMap, CallSitePred,
nullptr,
nullptr,
3618 {(
unsigned)Instruction::Invoke, (
unsigned)Instruction::CallBr,
3620 UsedAssumedInformation);
3621 assert(
Success &&
"Expected the check call to be successful!");
3624 if (
auto *LI = dyn_cast<LoadInst>(&
I)) {
3629 getOrCreateAAFor<AAAddressSpace>(
3632 auto &SI = cast<StoreInst>(
I);
3637 getOrCreateAAFor<AAAddressSpace>(
3643 nullptr, OpcodeInstMap, LoadStorePred,
nullptr,
nullptr,
3644 {(
unsigned)Instruction::Load, (
unsigned)Instruction::Store},
3645 UsedAssumedInformation);
3646 assert(
Success &&
"Expected the check call to be successful!");
3649 auto AAAllocationInfoPred = [&](
Instruction &
I) ->
bool {
3655 nullptr, OpcodeInstMap, AAAllocationInfoPred,
nullptr,
nullptr,
3656 {(
unsigned)Instruction::Alloca}, UsedAssumedInformation);
3657 assert(
Success &&
"Expected the check call to be successful!");
3680 return OS <<
"fn_ret";
3682 return OS <<
"cs_ret";
3690 return OS <<
"cs_arg";
3712 return OS << static_cast<const AbstractState &>(S);
3726 OS <<
"set-state(< {";
3742 OS <<
"set-state(< {";
3747 if (
auto *
F = dyn_cast<Function>(It.first.getValue()))
3748 OS <<
"@" <<
F->getName() <<
"[" << int(It.second) <<
"], ";
3750 OS << *It.first.getValue() <<
"[" << int(It.second) <<
"], ";
3763 OS <<
"] for CtxI ";
3770 OS <<
"<<null inst>>";
3779 for (
const auto &DepAA :
Deps) {
3780 auto *AA = DepAA.getPointer();
3797 OS <<
" [ <unknown> ]";
3811 bool DeleteFns,
bool IsModulePass) {
3812 if (Functions.
empty())
3816 dbgs() <<
"[Attributor] Run on module with " << Functions.
size()
3825 AC.IsModulePass = IsModulePass;
3826 AC.DeleteFns = DeleteFns;
3830 IndirectCalleeTrackingMap;
3832 AC.IndirectCalleeSpecializationCallback =
3837 auto &Set = IndirectCalleeTrackingMap[&CB];
3839 Set = std::make_unique<SmallPtrSet<Function *, 8>>();
3842 Set->insert(&Callee);
3852 if (!
A.isFunctionIPOAmendable(*
F))
3860 unsigned FunSize = Functions.
size();
3861 for (
unsigned u = 0; u < FunSize; u++) {
3863 if (!
F->isDeclaration() && !
F->isDefinitionExact() &&
F->getNumUses() &&
3866 assert(NewF &&
"Could not internalize function.");
3871 for (
const Use &U : NewF->
uses())
3872 if (
CallBase *CB = dyn_cast<CallBase>(U.getUser())) {
3873 auto *CallerF = CB->getCaller();
3881 if (
F->hasExactDefinition())
3882 NumFnWithExactDefinition++;
3884 NumFnWithoutExactDefinition++;
3889 if (
F->hasLocalLinkage()) {
3891 const auto *CB = dyn_cast<CallBase>(U.getUser());
3892 return CB && CB->isCallee(&U) &&
3893 Functions.count(const_cast<Function *>(CB->getCaller()));
3900 A.identifyDefaultAbstractAttributes(*
F);
3906 <<
" functions, result: " << Changed <<
".\n");
3915 bool IsModulePass) {
3916 if (Functions.
empty())
3920 dbgs() <<
"[AttributorLight] Run on module with " << Functions.
size()
3929 AC.IsModulePass = IsModulePass;
3930 AC.DeleteFns =
false;
3937 AC.Allowed = &Allowed;
3938 AC.UseLiveness =
false;
3943 if (
F->hasExactDefinition())
3944 NumFnWithExactDefinition++;
3946 NumFnWithoutExactDefinition++;
3951 if (
F->hasLocalLinkage()) {
3953 const auto *CB = dyn_cast<CallBase>(U.getUser());
3954 return CB && CB->isCallee(&U) &&
3955 Functions.count(const_cast<Function *>(CB->getCaller()));
3962 A.identifyDefaultAbstractAttributes(*
F);
3973 for (
Function *Changed :
A.getModifiedFunctions()) {
3979 for (
auto *U : Changed->users()) {
3980 if (
auto *Call = dyn_cast<CallBase>(U)) {
3981 if (Call->getCalledFunction() == Changed)
3988 <<
" functions, result: " << Changed <<
".\n");
3995 static std::atomic<int> CallTimes;
4001 Prefix =
"dep_graph";
4002 std::string Filename =
4003 Prefix +
"_" + std::to_string(CallTimes.load()) +
".dot";
4005 outs() <<
"Dependency graph dump to " << Filename <<
".\n";
4018 cast<AbstractAttribute>(DepAA.getPointer())->printWithDeps(
outs());
4051 Functions.
insert(&
N.getFunction());
4053 if (Functions.
empty())
4107 Functions.
insert(&
N.getFunction());
4109 if (Functions.
empty())
4164 std::string AAString;
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
amdgpu aa AMDGPU Address space based Alias Analysis Wrapper
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))
#define VERBOSE_DEBUG_TYPE
static cl::opt< bool > EnableHeapToStack("enable-heap-to-stack-conversion", cl::init(true), cl::Hidden)
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 cl::list< std::string > FunctionSeedAllowList("attributor-function-seed-allow-list", cl::Hidden, cl::desc("Comma seperated list of function names that are " "allowed to be seeded."), cl::CommaSeparated)
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 > SeedAllowList("attributor-seed-allow-list", cl::Hidden, cl::desc("Comma seperated list of attribute 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")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file provides interfaces used to build and manipulate a call graph, which is a very useful tool ...
This file contains the declarations for the subclasses of Constant, which represent the different fla...
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)
#define DEBUG_WITH_TYPE(TYPE, X)
DEBUG_WITH_TYPE macro - This macro should be used by passes to emit debug information.
static Function * getFunction(Constant *C)
Rewrite Partial Register Uses
Select target instructions out of generic instructions
Contains a collection of routines for determining if a given instruction is guaranteed to execute if ...
FunctionAnalysisManager FAM
This file defines the PointerIntPair class.
static StringRef getName(Value *V)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
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)
static constexpr uint32_t Opcode
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 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.
AttributeSet getFnAttrs() const
The function attributes are returned.
static AttributeList get(LLVMContext &C, ArrayRef< std::pair< unsigned, Attribute > > Attrs)
Create an AttributeList with the specified parameters in it.
AttributeSet getRetAttrs() const
The attributes for the ret value are returned.
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.
AttributeSet getParamAttrs(unsigned ArgNo) const
The attributes for the argument or parameter at the given index are returned.
MemoryEffects getMemoryEffects() const
bool hasAttribute(Attribute::AttrKind Kind) const
Return true if the attribute exists in this set.
Attribute getAttribute(Attribute::AttrKind Kind) const
Return the attribute object.
bool isStringAttribute() const
Return true if the attribute is a string (target-dependent) attribute.
bool isEnumAttribute() const
Return true if the attribute is an Attribute::AttrKind type.
bool isIntAttribute() const
Return true if the attribute is an integer attribute.
uint64_t getValueAsInt() const
Return the attribute's value as an integer.
StringRef getKindAsString() const
Return the attribute's kind as a string.
static Attribute get(LLVMContext &Context, AttrKind Kind, uint64_t Val=0)
Return a uniquified Attribute object.
Attribute::AttrKind getKindAsEnum() const
Return the attribute's kind as an enum (Attribute::AttrKind).
MemoryEffects getMemoryEffects() const
Returns memory effects.
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.
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...
static BlockAddress * get(Function *F, BasicBlock *BB)
Return a BlockAddress for the specified function and basic block.
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.
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
bool isMustTailCall() const
Tests if this call site must be tail call optimized.
Value * getCalledOperand() const
void setAttributes(AttributeList A)
Set the parameter attributes for this call.
unsigned arg_size() const
AttributeList getAttributes() const
Return the parameter attributes for this call.
Function * getCaller()
Helper to get the caller (the parent function).
Wrapper to unify "old style" CallGraph and "new style" LazyCallGraph.
void removeFunction(Function &Fn)
Remove Fn from the call graph.
void removeCallSite(CallBase &CS)
Remove the call site CS from the call graph.
void replaceFunctionWith(Function &OldFn, Function &NewFn)
Replace OldFn in the call graph (and SCC) with NewFn.
void reanalyzeFunction(Function &Fn)
After an CGSCC pass changes a function in ways that affect the call graph, this method can be called ...
bool replaceCallSite(CallBase &OldCS, CallBase &NewCS)
Replace OldCS with the new call site NewCS.
void initialize(CallGraph &CG, CallGraphSCC &SCC)
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.
void setTailCall(bool IsTc=true)
static CallInst * Create(FunctionType *Ty, Value *F, const Twine &NameStr="", Instruction *InsertBefore=nullptr)
A constant value that is initialized with an expression using other constant values.
static Constant * getPointerCast(Constant *C, Type *Ty)
Create a BitCast, AddrSpaceCast, or a PtrToInt cast constant expression.
static Constant * getTrunc(Constant *C, Type *Ty, bool OnlyIfReduced=false)
void print(raw_ostream &OS) const
Print out the bounds to a stream.
This is an important base class in LLVM.
static 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...
bool contains(const_arg_type_t< KeyT > Val) const
Return true if the specified key is in the map, false otherwise.
Implements a dense probed hash-table based set.
Analysis pass which computes a DominatorTree.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
A proxy from a FunctionAnalysisManager to an SCC.
Class to represent function types.
static 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.
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
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.
void addMetadata(unsigned KindID, MDNode &MD)
Add a metadata attachment.
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...
const BasicBlock * getParent() const
InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
const Function * getFunction() const
Return the function this instruction belongs to.
const Instruction * getNextNonDebugInstruction(bool SkipPseudoOp=false) const
Return a pointer to the next non-debug instruction in the same basic block as 'this',...
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, Instruction *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 MemoryLocation getForSource(const MemTransferInst *MTI)
Return a location representing the source of a memory transfer.
static MemoryLocation getForDest(const MemIntrinsic *MI)
Return a location representing the destination of a memory set or transfer.
static std::optional< MemoryLocation > getOrNone(const Instruction *Inst)
A Module instance is used to store all the information related to an LLVM module.
const FunctionListType & getFunctionList() const
Get the Module's list of functions (constant).
PointerIntPair - This class implements a pair of a pointer and small integer.
void * getOpaqueValue() const
PointerTy getPointer() const
static 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.
void preserveSet()
Mark an analysis set as preserved.
void preserve()
Mark an analysis as preserved.
Return a value (possibly void), from a function.
static ReturnInst * Create(LLVMContext &C, Value *retVal=nullptr, Instruction *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.
typename vector_type::const_iterator iterator
iterator end()
Get an iterator to the end of the SetVector.
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.
SubsumingPositionIterator(const IRPosition &IRP)
Provides information about what library functions are available for the current target.
Triple - Helper class for working with autoconf configuration names.
The instances of the Type class are immutable: once they are created, they are never changed.
bool isPointerTy() const
True if this is an instance of PointerType.
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 isIntegerTy() const
True if this is an instance of IntegerType.
TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
bool isVoidTy() const
Return true if this is 'void'.
static 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.
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
iterator_range< user_iterator > users()
const Value * stripPointerCasts() const
Strip off pointer casts, all-zero GEPs and address space casts.
LLVMContext & getContext() const
All values hold a context through their type.
iterator_range< use_iterator > uses()
StringRef getName() const
Return a constant reference to the value's name.
void takeName(Value *V)
Transfer the name from V to this value.
Value handle that is nullable, but tries to track the Value.
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.
self_iterator getIterator()
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.
bool isAssumedReadNone(Attributor &A, const IRPosition &IRP, const AbstractAttribute &QueryingAA, bool &IsKnown)
Return true if IRP is readnone.
bool isAssumedReadOnly(Attributor &A, const IRPosition &IRP, const AbstractAttribute &QueryingAA, bool &IsKnown)
Return true if IRP is readonly.
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.
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,...
bool isAssumedThreadLocalObject(Attributor &A, Value &Obj, const AbstractAttribute &QueryingAA)
Return true if Obj is assumed to be a thread local object.
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...
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.
bool isPotentiallyAffectedByBarrier(Attributor &A, const Instruction &I, const AbstractAttribute &QueryingAA)
Return true if I is potentially affected by a barrier.
bool isGPU(const Module &M)
Return true iff M target a GPU (and we can use GPU AS reasoning).
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.
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.
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...
bool isNoSyncInst(Attributor &A, const Instruction &I, const AbstractAttribute &QueryingAA)
Return true if I is a nosync instruction.
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.
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.