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 separated list of attribute names that are "
136 "allowed to be seeded."),
140 "attributor-function-seed-allow-list",
cl::Hidden,
141 cl::desc(
"Comma separated 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;
293 if (isa<Constant>(VAC.getValue()) || VAC.getValue() == VAC.getCtxI())
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());
1753 return isa<PHINode>(Usr) || !isa<Instruction>(Usr);
1759 bool CheckBBLivenessOnly,
DepClassTy LivenessDepClass,
1760 bool IgnoreDroppableUses,
1765 if (!CB(*
this, &QueryingAA))
1776 auto AddUsers = [&](
const Value &V,
const Use *OldUse) {
1777 for (
const Use &UU : V.uses()) {
1778 if (OldUse && EquivalentUseCB && !EquivalentUseCB(*OldUse, UU)) {
1780 "rejected by the equivalence call back: "
1790 AddUsers(V,
nullptr);
1793 <<
" initial uses to check\n");
1796 const auto *LivenessAA =
1801 while (!Worklist.
empty()) {
1806 if (
auto *Fn = dyn_cast<Function>(U->getUser()))
1807 dbgs() <<
"[Attributor] Check use: " << **U <<
" in " << Fn->getName()
1810 dbgs() <<
"[Attributor] Check use: " << **U <<
" in " << *U->getUser()
1813 bool UsedAssumedInformation =
false;
1814 if (
isAssumedDead(*U, &QueryingAA, LivenessAA, UsedAssumedInformation,
1815 CheckBBLivenessOnly, LivenessDepClass)) {
1817 dbgs() <<
"[Attributor] Dead use, skip!\n");
1820 if (IgnoreDroppableUses && U->getUser()->isDroppable()) {
1822 dbgs() <<
"[Attributor] Droppable user, skip!\n");
1826 if (
auto *SI = dyn_cast<StoreInst>(U->getUser())) {
1827 if (&SI->getOperandUse(0) == U) {
1828 if (!Visited.
insert(U).second)
1832 *
this, *SI, PotentialCopies, QueryingAA, UsedAssumedInformation,
1836 <<
"[Attributor] Value is stored, continue with "
1837 << PotentialCopies.
size()
1838 <<
" potential copies instead!\n");
1839 for (
Value *PotentialCopy : PotentialCopies)
1840 if (!AddUsers(*PotentialCopy, U))
1847 bool Follow =
false;
1848 if (!Pred(*U, Follow))
1853 User &Usr = *U->getUser();
1854 AddUsers(Usr,
nullptr);
1856 auto *RI = dyn_cast<ReturnInst>(&Usr);
1862 return AddUsers(*ACS.getInstruction(), U);
1865 &QueryingAA, UsedAssumedInformation)) {
1866 LLVM_DEBUG(
dbgs() <<
"[Attributor] Could not follow return instruction "
1867 "to all call sites: "
1878 bool RequireAllCallSites,
1879 bool &UsedAssumedInformation) {
1885 if (!AssociatedFunction) {
1886 LLVM_DEBUG(
dbgs() <<
"[Attributor] No function associated with " << IRP
1892 &QueryingAA, UsedAssumedInformation);
1897 bool RequireAllCallSites,
1899 bool &UsedAssumedInformation,
1900 bool CheckPotentiallyDead) {
1904 <<
"[Attributor] Function " << Fn.
getName()
1905 <<
" has no internal linkage, hence not all call sites are known\n");
1910 if (!CB(*
this, QueryingAA))
1914 for (
unsigned u = 0; u <
Uses.size(); ++u) {
1917 if (
auto *Fn = dyn_cast<Function>(U))
1918 dbgs() <<
"[Attributor] Check use: " << Fn->
getName() <<
" in "
1919 << *U.getUser() <<
"\n";
1921 dbgs() <<
"[Attributor] Check use: " << *U <<
" in " << *U.getUser()
1924 if (!CheckPotentiallyDead &&
1925 isAssumedDead(U, QueryingAA,
nullptr, UsedAssumedInformation,
1928 dbgs() <<
"[Attributor] Dead use, skip!\n");
1931 if (
ConstantExpr *CE = dyn_cast<ConstantExpr>(U.getUser())) {
1932 if (CE->isCast() && CE->getType()->isPointerTy()) {
1934 dbgs() <<
"[Attributor] Use, is constant cast expression, add "
1935 << CE->getNumUses() <<
" uses of that expression instead!\n";
1937 for (
const Use &CEU : CE->uses())
1938 Uses.push_back(&CEU);
1946 <<
" has non call site use " << *U.get() <<
" in "
1947 << *U.getUser() <<
"\n");
1949 if (isa<BlockAddress>(U.getUser()))
1954 const Use *EffectiveUse =
1957 if (!RequireAllCallSites) {
1958 LLVM_DEBUG(
dbgs() <<
"[Attributor] User " << *EffectiveUse->getUser()
1959 <<
" is not a call of " << Fn.
getName()
1963 LLVM_DEBUG(
dbgs() <<
"[Attributor] User " << *EffectiveUse->getUser()
1964 <<
" is an invalid use of " << Fn.
getName() <<
"\n");
1972 unsigned MinArgsParams =
1974 for (
unsigned u = 0; u < MinArgsParams; ++u) {
1978 dbgs() <<
"[Attributor] Call site / callee argument type mismatch ["
1979 << u <<
"@" << Fn.
getName() <<
": "
1989 LLVM_DEBUG(
dbgs() <<
"[Attributor] Call site callback failed for "
1997bool Attributor::shouldPropagateCallBaseContext(
const IRPosition &IRP) {
2007 bool RecurseForSelectAndPHI) {
2011 if (!AssociatedFunction)
2014 bool UsedAssumedInformation =
false;
2018 UsedAssumedInformation, RecurseForSelectAndPHI))
2022 return Pred(*VAC.getValue());
2030 bool &UsedAssumedInformation,
bool CheckBBLivenessOnly =
false,
2031 bool CheckPotentiallyDead =
false) {
2032 for (
unsigned Opcode : Opcodes) {
2034 auto *Insts = OpcodeInstMap.
lookup(Opcode);
2040 if (
A && !CheckPotentiallyDead &&
2042 UsedAssumedInformation, CheckBBLivenessOnly)) {
2044 dbgs() <<
"[Attributor] Instruction " << *
I
2045 <<
" is potentially dead, skip!\n";);
2060 bool &UsedAssumedInformation,
2061 bool CheckBBLivenessOnly,
2062 bool CheckPotentiallyDead) {
2068 const auto *LivenessAA =
2069 CheckPotentiallyDead && QueryingAA
2075 LivenessAA, Opcodes, UsedAssumedInformation,
2076 CheckBBLivenessOnly, CheckPotentiallyDead))
2085 bool &UsedAssumedInformation,
2086 bool CheckBBLivenessOnly,
2087 bool CheckPotentiallyDead) {
2091 UsedAssumedInformation, CheckBBLivenessOnly,
2092 CheckPotentiallyDead);
2097 bool &UsedAssumedInformation) {
2100 const Function *AssociatedFunction =
2102 if (!AssociatedFunction)
2106 const auto *LivenessAA =
2113 UsedAssumedInformation))
2123void Attributor::runTillFixpoint() {
2127 <<
" abstract attributes.\n");
2132 unsigned IterationCounter = 1;
2133 unsigned MaxIterations =
2143 LLVM_DEBUG(
dbgs() <<
"\n\n[Attributor] #Iteration: " << IterationCounter
2144 <<
", Worklist size: " << Worklist.
size() <<
"\n");
2149 for (
unsigned u = 0; u < InvalidAAs.
size(); ++u) {
2154 dbgs() <<
"[Attributor] InvalidAA: " << *InvalidAA
2155 <<
" has " << InvalidAA->
Deps.
size()
2156 <<
" required & optional dependences\n");
2157 for (
auto &DepIt : InvalidAA->
Deps) {
2161 dbgs() <<
" - recompute: " << *DepAA);
2166 <<
" - invalidate: " << *DepAA);
2170 InvalidAAs.
insert(DepAA);
2180 for (
auto &DepIt : ChangedAA->Deps)
2181 Worklist.
insert(cast<AbstractAttribute>(DepIt.getPointer()));
2182 ChangedAA->Deps.clear();
2185 LLVM_DEBUG(
dbgs() <<
"[Attributor] #Iteration: " << IterationCounter
2186 <<
", Worklist+Dependent size: " << Worklist.
size()
2196 const auto &AAState = AA->getState();
2197 if (!AAState.isAtFixpoint())
2199 ChangedAAs.push_back(AA);
2203 if (!AAState.isValidState())
2215 Worklist.insert(ChangedAAs.begin(), ChangedAAs.end());
2216 Worklist.insert(QueryAAsAwaitingUpdate.begin(),
2217 QueryAAsAwaitingUpdate.end());
2218 QueryAAsAwaitingUpdate.clear();
2220 }
while (!Worklist.empty() && (IterationCounter++ < MaxIterations));
2222 if (IterationCounter > MaxIterations && !Functions.
empty()) {
2224 return ORM <<
"Attributor did not reach a fixpoint after "
2225 <<
ore::NV(
"Iterations", MaxIterations) <<
" iterations.";
2228 emitRemark<OptimizationRemarkMissed>(
F,
"FixedPoint",
Remark);
2231 LLVM_DEBUG(
dbgs() <<
"\n[Attributor] Fixpoint iteration done after: "
2232 << IterationCounter <<
"/" << MaxIterations
2233 <<
" iterations\n");
2241 for (
unsigned u = 0;
u < ChangedAAs.size();
u++) {
2243 if (!Visited.
insert(ChangedAA).second)
2250 NumAttributesTimedOut++;
2253 for (
auto &DepIt : ChangedAA->
Deps)
2254 ChangedAAs.push_back(cast<AbstractAttribute>(DepIt.getPointer()));
2259 if (!Visited.
empty())
2260 dbgs() <<
"\n[Attributor] Finalized " << Visited.
size()
2261 <<
" abstract attributes.\n";
2267 "Non-query AAs should not be required to register for updates!");
2268 QueryAAsAwaitingUpdate.insert(&AA);
2275 unsigned NumManifested = 0;
2276 unsigned NumAtFixpoint = 0;
2300 bool UsedAssumedInformation =
false;
2312 LLVM_DEBUG(
dbgs() <<
"[Attributor] Manifest " << LocalChange <<
" : " << *AA
2315 ManifestChange = ManifestChange | LocalChange;
2321 (void)NumManifested;
2322 (void)NumAtFixpoint;
2323 LLVM_DEBUG(
dbgs() <<
"\n[Attributor] Manifested " << NumManifested
2324 <<
" arguments while " << NumAtFixpoint
2325 <<
" were in a valid fixpoint state\n");
2327 NumAttributesManifested += NumManifested;
2328 NumAttributesValidFixpoint += NumAtFixpoint;
2333 for (
unsigned u = 0; u < NumFinalAAs; ++u)
2337 errs() <<
"Unexpected abstract attribute: "
2338 << cast<AbstractAttribute>(DepIt->getPointer()) <<
" :: "
2339 << cast<AbstractAttribute>(DepIt->getPointer())
2341 .getAssociatedValue()
2345 "remain unchanged!");
2348 for (
auto &It : AttrsMap) {
2351 isa<Function>(It.getFirst())
2357 return ManifestChange;
2360void Attributor::identifyDeadInternalFunctions() {
2381 if (
F->hasLocalLinkage() && (
isModulePass() || !TLI->getLibFunc(*
F, LF)))
2385 bool FoundLiveInternal =
true;
2386 while (FoundLiveInternal) {
2387 FoundLiveInternal =
false;
2392 bool UsedAssumedInformation =
false;
2396 return ToBeDeletedFunctions.count(Callee) ||
2397 (Functions.count(Callee) &&
Callee->hasLocalLinkage() &&
2398 !LiveInternalFns.
count(Callee));
2400 *
F,
true,
nullptr, UsedAssumedInformation)) {
2406 FoundLiveInternal =
true;
2412 ToBeDeletedFunctions.insert(
F);
2419 << ToBeDeletedFunctions.size() <<
" functions and "
2420 << ToBeDeletedBlocks.size() <<
" blocks and "
2421 << ToBeDeletedInsts.size() <<
" instructions and "
2422 << ToBeChangedValues.size() <<
" values and "
2423 << ToBeChangedUses.size() <<
" uses. To insert "
2424 << ToBeChangedToUnreachableInsts.size()
2425 <<
" unreachables.\n"
2426 <<
"Preserve manifest added " << ManifestAddedBlocks.size()
2432 auto ReplaceUse = [&](
Use *
U,
Value *NewV) {
2437 const auto &
Entry = ToBeChangedValues.lookup(NewV);
2440 NewV = get<0>(Entry);
2445 "Cannot replace an instruction outside the current SCC!");
2449 if (
auto *RI = dyn_cast_or_null<ReturnInst>(
I)) {
2451 if (CI->isMustTailCall() && !ToBeDeletedInsts.count(CI))
2455 if (!isa<Argument>(NewV))
2456 for (
auto &Arg : RI->getFunction()->args())
2457 Arg.removeAttr(Attribute::Returned);
2461 <<
" instead of " << *OldV <<
"\n");
2465 CGModifiedFunctions.insert(
I->getFunction());
2466 if (!isa<PHINode>(
I) && !ToBeDeletedInsts.count(
I) &&
2470 if (isa<UndefValue>(NewV) && isa<CallBase>(
U->getUser())) {
2471 auto *CB = cast<CallBase>(
U->getUser());
2472 if (CB->isArgOperand(U)) {
2473 unsigned Idx = CB->getArgOperandNo(U);
2474 CB->removeParamAttr(
Idx, Attribute::NoUndef);
2475 auto *
Callee = dyn_cast_if_present<Function>(CB->getCalledOperand());
2477 Callee->removeParamAttr(
Idx, Attribute::NoUndef);
2480 if (isa<Constant>(NewV) && isa<BranchInst>(
U->getUser())) {
2482 if (isa<UndefValue>(NewV)) {
2483 ToBeChangedToUnreachableInsts.insert(UserI);
2490 for (
auto &It : ToBeChangedUses) {
2492 Value *NewV = It.second;
2493 ReplaceUse(U, NewV);
2497 for (
auto &It : ToBeChangedValues) {
2498 Value *OldV = It.first;
2499 auto [NewV,
Done] = It.second;
2501 for (
auto &U : OldV->
uses())
2502 if (
Done || !
U.getUser()->isDroppable())
2505 if (
auto *
I = dyn_cast<Instruction>(
U->getUser()))
2508 ReplaceUse(U, NewV);
2512 for (
const auto &V : InvokeWithDeadSuccessor)
2513 if (
InvokeInst *
II = dyn_cast_or_null<InvokeInst>(V)) {
2515 "Cannot replace an invoke outside the current SCC!");
2516 bool UnwindBBIsDead =
II->hasFnAttr(Attribute::NoUnwind);
2517 bool NormalBBIsDead =
II->hasFnAttr(Attribute::NoReturn);
2518 bool Invoke2CallAllowed =
2520 assert((UnwindBBIsDead || NormalBBIsDead) &&
2521 "Invoke does not have dead successors!");
2524 if (UnwindBBIsDead) {
2526 if (Invoke2CallAllowed) {
2531 ToBeChangedToUnreachableInsts.insert(NormalNextIP);
2533 assert(NormalBBIsDead &&
"Broken invariant!");
2536 ToBeChangedToUnreachableInsts.insert(&NormalDestBB->
front());
2541 "Cannot replace a terminator outside the current SCC!");
2542 CGModifiedFunctions.insert(
I->getFunction());
2545 for (
const auto &V : ToBeChangedToUnreachableInsts)
2546 if (
Instruction *
I = dyn_cast_or_null<Instruction>(V)) {
2550 "Cannot replace an instruction outside the current SCC!");
2551 CGModifiedFunctions.insert(
I->getFunction());
2555 for (
const auto &V : ToBeDeletedInsts) {
2556 if (
Instruction *
I = dyn_cast_or_null<Instruction>(V)) {
2557 assert((!isa<CallBase>(
I) || isa<IntrinsicInst>(
I) ||
2559 "Cannot delete an instruction outside the current SCC!");
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);
2742 Wrapper->IsNewDbgInfoFormat = M.IsNewDbgInfoFormat;
2747 assert(
F.use_empty() &&
"Uses remained after wrapper was created!");
2752 F.setComdat(
nullptr);
2756 F.getAllMetadata(MDs);
2757 for (
auto MDIt : MDs)
2758 Wrapper->addMetadata(MDIt.first, *MDIt.second);
2759 Wrapper->setAttributes(
F.getAttributes());
2767 Args.push_back(&Arg);
2768 Arg.setName((FArgIt++)->
getName());
2776 NumFnShallowWrappersCreated++;
2780 if (
F.isDeclaration() ||
F.hasLocalLinkage() ||
2796 return InternalizedFns[&
F];
2814 F->getName() +
".internalized");
2817 for (
auto &Arg :
F->args()) {
2819 NewFArgIt->setName(ArgName);
2820 VMap[&Arg] = &(*NewFArgIt++);
2837 F->getAllMetadata(MDs);
2838 for (
auto MDIt : MDs)
2842 M.getFunctionList().insert(
F->getIterator(), Copied);
2850 auto &InternalizedFn = FnMap[
F];
2851 auto IsNotInternalized = [&](
Use &U) ->
bool {
2852 if (
auto *CB = dyn_cast<CallBase>(U.getUser()))
2853 return !FnMap.
lookup(CB->getCaller());
2856 F->replaceUsesWithIf(InternalizedFn, IsNotInternalized);
2877 if (cast<CallBase>(ACS.
getInstruction())->getCalledOperand()->getType() !=
2888 LLVM_DEBUG(
dbgs() <<
"[Attributor] Cannot rewrite var-args functions\n");
2899 dbgs() <<
"[Attributor] Cannot rewrite due to complex attribute\n");
2904 bool UsedAssumedInformation =
false;
2906 UsedAssumedInformation,
2908 LLVM_DEBUG(
dbgs() <<
"[Attributor] Cannot rewrite all call sites\n");
2913 if (
auto *CI = dyn_cast<CallInst>(&
I))
2914 return !CI->isMustTailCall();
2922 nullptr, {Instruction::Call},
2923 UsedAssumedInformation)) {
2924 LLVM_DEBUG(
dbgs() <<
"[Attributor] Cannot rewrite due to instructions\n");
2935 LLVM_DEBUG(
dbgs() <<
"[Attributor] Register new rewrite of " << Arg <<
" in "
2937 << ReplacementTypes.
size() <<
" replacements\n");
2939 "Cannot register an invalid rewrite");
2943 ArgumentReplacementMap[Fn];
2949 std::unique_ptr<ArgumentReplacementInfo> &ARI = ARIs[Arg.
getArgNo()];
2950 if (ARI && ARI->getNumReplacementArgs() <= ReplacementTypes.
size()) {
2951 LLVM_DEBUG(
dbgs() <<
"[Attributor] Existing rewrite is preferred\n");
2959 LLVM_DEBUG(
dbgs() <<
"[Attributor] Register new rewrite of " << Arg <<
" in "
2961 << ReplacementTypes.
size() <<
" replacements\n");
2965 std::move(CalleeRepairCB),
2966 std::move(ACSRepairCB)));
2987 for (
auto &It : ArgumentReplacementMap) {
2991 if (!Functions.count(OldFn) || ToBeDeletedFunctions.count(OldFn))
3004 if (
const std::unique_ptr<ArgumentReplacementInfo> &ARI =
3005 ARIs[Arg.getArgNo()]) {
3006 NewArgumentTypes.
append(ARI->ReplacementTypes.begin(),
3007 ARI->ReplacementTypes.end());
3008 NewArgumentAttributes.
append(ARI->getNumReplacementArgs(),
3011 NewArgumentTypes.
push_back(Arg.getType());
3018 for (
auto *
I : NewArgumentTypes)
3019 if (
auto *VT = dyn_cast<llvm::VectorType>(
I))
3020 LargestVectorWidth =
3021 std::max(LargestVectorWidth,
3022 VT->getPrimitiveSizeInBits().getKnownMinValue());
3033 << *NewFnTy <<
"\n");
3038 Functions.insert(NewFn);
3054 NewArgumentAttributes));
3063 return !
T->isPtrOrPtrVectorTy() ||
3077 if (
auto *BA = dyn_cast<BlockAddress>(U))
3079 for (
auto *BA : BlockAddresses)
3094 for (
unsigned OldArgNum = 0; OldArgNum < ARIs.
size(); ++OldArgNum) {
3095 unsigned NewFirstArgNum = NewArgOperands.
size();
3096 (void)NewFirstArgNum;
3097 if (
const std::unique_ptr<ArgumentReplacementInfo> &ARI =
3099 if (ARI->ACSRepairCB)
3100 ARI->ACSRepairCB(*ARI, ACS, NewArgOperands);
3101 assert(ARI->getNumReplacementArgs() + NewFirstArgNum ==
3102 NewArgOperands.
size() &&
3103 "ACS repair callback did not provide as many operand as new "
3104 "types were registered!");
3106 NewArgOperandAttributes.
append(ARI->ReplacementTypes.size(),
3115 assert(NewArgOperands.
size() == NewArgOperandAttributes.
size() &&
3116 "Mismatch # argument operands vs. # argument operand attributes!");
3118 "Mismatch # argument operands vs. # function arguments!");
3127 II->getUnwindDest(), NewArgOperands,
3132 NewCI->setTailCallKind(cast<CallInst>(OldCB)->getTailCallKind());
3137 NewCB->
copyMetadata(*OldCB, {LLVMContext::MD_prof, LLVMContext::MD_dbg});
3142 OldCallAttributeList.
getRetAttrs(), NewArgOperandAttributes));
3145 LargestVectorWidth);
3147 CallSitePairs.
push_back({OldCB, NewCB});
3152 bool UsedAssumedInformation =
false;
3154 true,
nullptr, UsedAssumedInformation,
3157 assert(
Success &&
"Assumed call site replacement to succeed!");
3162 for (
unsigned OldArgNum = 0; OldArgNum < ARIs.
size();
3163 ++OldArgNum, ++OldFnArgIt) {
3164 if (
const std::unique_ptr<ArgumentReplacementInfo> &ARI =
3166 if (ARI->CalleeRepairCB)
3167 ARI->CalleeRepairCB(*ARI, *NewFn, NewFnArgIt);
3168 if (ARI->ReplacementTypes.empty())
3171 NewFnArgIt += ARI->ReplacementTypes.size();
3173 NewFnArgIt->
takeName(&*OldFnArgIt);
3180 for (
auto &CallSitePair : CallSitePairs) {
3181 CallBase &OldCB = *CallSitePair.first;
3182 CallBase &NewCB = *CallSitePair.second;
3184 "Cannot handle call sites with different types!");
3195 if (ModifiedFns.
remove(OldFn))
3196 ModifiedFns.
insert(NewFn);
3204void InformationCache::initializeInformationCache(
const Function &CF,
3220 auto AddToAssumeUsesMap = [&](
const Value &
V) ->
void {
3222 if (
auto *
I = dyn_cast<Instruction>(&V))
3224 while (!Worklist.
empty()) {
3226 std::optional<short> &NumUses = AssumeUsesMap[
I];
3228 NumUses =
I->getNumUses();
3229 NumUses = *NumUses - 1;
3232 AssumeOnlyValues.insert(
I);
3233 for (
const Value *
Op :
I->operands())
3234 if (
auto *OpI = dyn_cast<Instruction>(
Op))
3240 bool IsInterestingOpcode =
false;
3247 switch (
I.getOpcode()) {
3250 "New call base instruction type needs to be known in the "
3253 case Instruction::Call:
3257 if (
auto *Assume = dyn_cast<AssumeInst>(&
I)) {
3258 AssumeOnlyValues.insert(Assume);
3260 AddToAssumeUsesMap(*Assume->getArgOperand(0));
3261 }
else if (cast<CallInst>(
I).isMustTailCall()) {
3262 FI.ContainsMustTailCall =
true;
3263 if (
auto *Callee = dyn_cast_if_present<Function>(
3264 cast<CallInst>(
I).getCalledOperand()))
3265 getFunctionInfo(*Callee).CalledViaMustTail =
true;
3268 case Instruction::CallBr:
3269 case Instruction::Invoke:
3270 case Instruction::CleanupRet:
3271 case Instruction::CatchSwitch:
3272 case Instruction::AtomicRMW:
3273 case Instruction::AtomicCmpXchg:
3274 case Instruction::Br:
3275 case Instruction::Resume:
3276 case Instruction::Ret:
3277 case Instruction::Load:
3279 case Instruction::Store:
3281 case Instruction::Alloca:
3282 case Instruction::AddrSpaceCast:
3283 IsInterestingOpcode =
true;
3285 if (IsInterestingOpcode) {
3286 auto *&Insts = FI.OpcodeInstMap[
I.getOpcode()];
3291 if (
I.mayReadOrWriteMemory())
3292 FI.RWInsts.push_back(&
I);
3295 if (
F.hasFnAttribute(Attribute::AlwaysInline) &&
3297 InlineableFunctions.insert(&
F);
3300InformationCache::FunctionInfo::~FunctionInfo() {
3303 for (
auto &It : OpcodeInstMap)
3304 It.getSecond()->~InstructionVectorTy();
3309 assert(
A.isClosedWorldModule() &&
"Cannot see all indirect callees!");
3310 return IndirectlyCallableFunctions;
3321 if (DependenceStack.empty())
3325 DependenceStack.back()->push_back({&FromAA, &ToAA, DepClass});
3328void Attributor::rememberDependences() {
3329 assert(!DependenceStack.empty() &&
"No dependences to remember!");
3331 for (DepInfo &DI : *DependenceStack.back()) {
3334 "Expected required or optional dependence (1 bit)!");
3341template <Attribute::AttrKind AK,
typename AAType>
3342void Attributor::checkAndQueryIRAttr(
const IRPosition &IRP,
3345 if (!
Attrs.hasAttribute(AK))
3349 getOrCreateAAFor<AAType>(IRP);
3353 if (!VisitedFunctions.insert(&
F).second)
3355 if (
F.isDeclaration())
3361 InformationCache::FunctionInfo &FI = InfoCache.getFunctionInfo(
F);
3363 for (
const Use &U :
F.uses())
3364 if (
const auto *CB = dyn_cast<CallBase>(U.getUser()))
3365 if (CB->isCallee(&U) && CB->isMustTailCall())
3366 FI.CalledViaMustTail =
true;
3371 auto Attrs =
F.getAttributes();
3372 auto FnAttrs = Attrs.getFnAttrs();
3377 getOrCreateAAFor<AAIsDead>(FPos);
3381 getOrCreateAAFor<AAUndefinedBehavior>(FPos);
3385 getOrCreateAAFor<AAHeapToStack>(FPos);
3388 checkAndQueryIRAttr<Attribute::MustProgress, AAMustProgress>(FPos, FnAttrs);
3391 checkAndQueryIRAttr<Attribute::NoFree, AANoFree>(FPos, FnAttrs);
3394 checkAndQueryIRAttr<Attribute::WillReturn, AAWillReturn>(FPos, FnAttrs);
3397 checkAndQueryIRAttr<Attribute::NoSync, AANoSync>(FPos, FnAttrs);
3402 if (IsIPOAmendable) {
3405 checkAndQueryIRAttr<Attribute::NoUnwind, AANoUnwind>(FPos, FnAttrs);
3408 checkAndQueryIRAttr<Attribute::NoReturn, AANoReturn>(FPos, FnAttrs);
3411 checkAndQueryIRAttr<Attribute::NoRecurse, AANoRecurse>(FPos, FnAttrs);
3414 if (Attrs.hasFnAttr(Attribute::Convergent))
3415 getOrCreateAAFor<AANonConvergent>(FPos);
3418 getOrCreateAAFor<AAMemoryBehavior>(FPos);
3421 getOrCreateAAFor<AAMemoryLocation>(FPos);
3424 getOrCreateAAFor<AAAssumptionInfo>(FPos);
3432 getOrCreateAAFor<AADenormalFPMath>(FPos);
3435 Type *ReturnType =
F.getReturnType();
3436 if (!ReturnType->isVoidTy()) {
3441 getOrCreateAAFor<AAIsDead>(RetPos);
3444 bool UsedAssumedInformation =
false;
3449 checkAndQueryIRAttr<Attribute::NoUndef, AANoUndef>(RetPos, RetAttrs);
3451 if (ReturnType->isPointerTy()) {
3454 getOrCreateAAFor<AAAlign>(RetPos);
3457 checkAndQueryIRAttr<Attribute::NonNull, AANonNull>(RetPos, RetAttrs);
3460 checkAndQueryIRAttr<Attribute::NoAlias, AANoAlias>(RetPos, RetAttrs);
3464 getOrCreateAAFor<AADereferenceable>(RetPos);
3466 getOrCreateAAFor<AANoFPClass>(RetPos);
3473 auto ArgNo = Arg.getArgNo();
3476 if (!IsIPOAmendable) {
3477 if (Arg.getType()->isPointerTy())
3479 checkAndQueryIRAttr<Attribute::NoFree, AANoFree>(ArgPos, ArgAttrs);
3486 bool UsedAssumedInformation =
false;
3491 getOrCreateAAFor<AAIsDead>(ArgPos);
3494 checkAndQueryIRAttr<Attribute::NoUndef, AANoUndef>(ArgPos, ArgAttrs);
3496 if (Arg.getType()->isPointerTy()) {
3498 checkAndQueryIRAttr<Attribute::NonNull, AANonNull>(ArgPos, ArgAttrs);
3501 checkAndQueryIRAttr<Attribute::NoAlias, AANoAlias>(ArgPos, ArgAttrs);
3504 getOrCreateAAFor<AADereferenceable>(ArgPos);
3507 getOrCreateAAFor<AAAlign>(ArgPos);
3510 checkAndQueryIRAttr<Attribute::NoCapture, AANoCapture>(ArgPos, ArgAttrs);
3514 getOrCreateAAFor<AAMemoryBehavior>(ArgPos);
3517 checkAndQueryIRAttr<Attribute::NoFree, AANoFree>(ArgPos, ArgAttrs);
3521 getOrCreateAAFor<AAPrivatizablePtr>(ArgPos);
3523 getOrCreateAAFor<AANoFPClass>(ArgPos);
3528 auto &CB = cast<CallBase>(
I);
3534 getOrCreateAAFor<AAIsDead>(CBInstPos);
3536 Function *Callee = dyn_cast_if_present<Function>(CB.getCalledOperand());
3540 getOrCreateAAFor<AAIndirectCallInfo>(CBFnPos);
3545 getOrCreateAAFor<AAAssumptionInfo>(CBFnPos);
3550 !Callee->hasMetadata(LLVMContext::MD_callback))
3553 if (!Callee->getReturnType()->isVoidTy() && !CB.use_empty()) {
3555 bool UsedAssumedInformation =
false;
3560 getOrCreateAAFor<AANoFPClass>(CBInstPos);
3564 for (
int I = 0, E = CB.arg_size();
I < E; ++
I) {
3570 getOrCreateAAFor<AAIsDead>(CBArgPos);
3575 bool UsedAssumedInformation =
false;
3580 checkAndQueryIRAttr<Attribute::NoUndef, AANoUndef>(CBArgPos, CBArgAttrs);
3582 Type *ArgTy = CB.getArgOperand(
I)->getType();
3586 getOrCreateAAFor<AANoFPClass>(CBArgPos);
3592 checkAndQueryIRAttr<Attribute::NonNull, AANonNull>(CBArgPos, CBArgAttrs);
3595 checkAndQueryIRAttr<Attribute::NoCapture, AANoCapture>(CBArgPos,
3599 checkAndQueryIRAttr<Attribute::NoAlias, AANoAlias>(CBArgPos, CBArgAttrs);
3602 getOrCreateAAFor<AADereferenceable>(CBArgPos);
3605 getOrCreateAAFor<AAAlign>(CBArgPos);
3610 getOrCreateAAFor<AAMemoryBehavior>(CBArgPos);
3613 checkAndQueryIRAttr<Attribute::NoFree, AANoFree>(CBArgPos, CBArgAttrs);
3619 [[maybe_unused]]
bool Success;
3620 bool UsedAssumedInformation =
false;
3622 nullptr, OpcodeInstMap, CallSitePred,
nullptr,
nullptr,
3623 {(
unsigned)Instruction::Invoke, (
unsigned)Instruction::CallBr,
3625 UsedAssumedInformation);
3626 assert(
Success &&
"Expected the check call to be successful!");
3629 if (
auto *LI = dyn_cast<LoadInst>(&
I)) {
3634 getOrCreateAAFor<AAAddressSpace>(
3637 auto &SI = cast<StoreInst>(
I);
3642 getOrCreateAAFor<AAAddressSpace>(
3648 nullptr, OpcodeInstMap, LoadStorePred,
nullptr,
nullptr,
3649 {(
unsigned)Instruction::Load, (
unsigned)Instruction::Store},
3650 UsedAssumedInformation);
3651 assert(
Success &&
"Expected the check call to be successful!");
3654 auto AAAllocationInfoPred = [&](
Instruction &
I) ->
bool {
3660 nullptr, OpcodeInstMap, AAAllocationInfoPred,
nullptr,
nullptr,
3661 {(
unsigned)Instruction::Alloca}, UsedAssumedInformation);
3662 assert(
Success &&
"Expected the check call to be successful!");
3685 return OS <<
"fn_ret";
3687 return OS <<
"cs_ret";
3695 return OS <<
"cs_arg";
3717 return OS << static_cast<const AbstractState &>(S);
3731 OS <<
"set-state(< {";
3747 OS <<
"set-state(< {";
3752 if (
auto *
F = dyn_cast<Function>(It.first.getValue()))
3753 OS <<
"@" <<
F->getName() <<
"[" << int(It.second) <<
"], ";
3755 OS << *It.first.getValue() <<
"[" << int(It.second) <<
"], ";
3768 OS <<
"] for CtxI ";
3775 OS <<
"<<null inst>>";
3784 for (
const auto &DepAA :
Deps) {
3785 auto *AA = DepAA.getPointer();
3802 OS <<
" [ <unknown> ]";
3816 bool DeleteFns,
bool IsModulePass) {
3817 if (Functions.
empty())
3821 dbgs() <<
"[Attributor] Run on module with " << Functions.
size()
3830 AC.IsModulePass = IsModulePass;
3831 AC.DeleteFns = DeleteFns;
3835 IndirectCalleeTrackingMap;
3837 AC.IndirectCalleeSpecializationCallback =
3842 auto &Set = IndirectCalleeTrackingMap[&CB];
3844 Set = std::make_unique<SmallPtrSet<Function *, 8>>();
3846 return Set->contains(&Callee);
3847 Set->insert(&Callee);
3857 if (!
A.isFunctionIPOAmendable(*
F))
3865 unsigned FunSize = Functions.
size();
3866 for (
unsigned u = 0; u < FunSize; u++) {
3868 if (!
F->isDeclaration() && !
F->isDefinitionExact() &&
F->getNumUses() &&
3871 assert(NewF &&
"Could not internalize function.");
3876 for (
const Use &U : NewF->
uses())
3877 if (
CallBase *CB = dyn_cast<CallBase>(U.getUser())) {
3878 auto *CallerF = CB->getCaller();
3886 if (
F->hasExactDefinition())
3887 NumFnWithExactDefinition++;
3889 NumFnWithoutExactDefinition++;
3894 if (
F->hasLocalLinkage()) {
3896 const auto *CB = dyn_cast<CallBase>(U.getUser());
3897 return CB && CB->isCallee(&U) &&
3898 Functions.count(const_cast<Function *>(CB->getCaller()));
3905 A.identifyDefaultAbstractAttributes(*
F);
3911 <<
" functions, result: " << Changed <<
".\n");
3920 bool IsModulePass) {
3921 if (Functions.
empty())
3925 dbgs() <<
"[AttributorLight] Run on module with " << Functions.
size()
3934 AC.IsModulePass = IsModulePass;
3935 AC.DeleteFns =
false;
3942 AC.Allowed = &Allowed;
3943 AC.UseLiveness =
false;
3948 if (
F->hasExactDefinition())
3949 NumFnWithExactDefinition++;
3951 NumFnWithoutExactDefinition++;
3956 if (AC.UseLiveness &&
F->hasLocalLinkage()) {
3958 const auto *CB = dyn_cast<CallBase>(U.getUser());
3959 return CB && CB->isCallee(&U) &&
3960 Functions.count(const_cast<Function *>(CB->getCaller()));
3967 A.identifyDefaultAbstractAttributes(*
F);
3978 for (
Function *Changed :
A.getModifiedFunctions()) {
3984 for (
auto *U : Changed->users()) {
3985 if (
auto *Call = dyn_cast<CallBase>(U)) {
3986 if (Call->getCalledFunction() == Changed)
3993 <<
" functions, result: " << Changed <<
".\n");
4000 static std::atomic<int> CallTimes;
4006 Prefix =
"dep_graph";
4007 std::string Filename =
4008 Prefix +
"_" + std::to_string(CallTimes.load()) +
".dot";
4010 outs() <<
"Dependency graph dump to " << Filename <<
".\n";
4023 cast<AbstractAttribute>(DepAA.getPointer())->printWithDeps(
outs());
4056 Functions.
insert(&
N.getFunction());
4058 if (Functions.
empty())
4112 Functions.
insert(&
N.getFunction());
4114 if (Functions.
empty())
4169 std::string AAString;
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)
#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
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)
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)
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 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 ...
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 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...
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.
bool IsNewDbgInfoFormat
Is this function using intrinsics to record the position of debugging information,...
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...
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, 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 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, 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.
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.
The TimeTraceScope is a helper class to call the begin and end functions of the time trace profiler.
Triple - Helper class for working with autoconf configuration names.
The instances of the Type class are immutable: once they are created, they are never changed.
bool isPointerTy() const
True if this is an instance of PointerType.
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.
const ParentTy * getParent() const
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.
bool isNoFPClassCompatibleType(Type *Ty)
Returns true if this is a type legal for the 'nofpclass' attribute.
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)
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.
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,...
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.
unsigned MaxInitializationChainLength
The value passed to the line option that defines the maximal initialization chain length.
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)
void detachDeadBlocks(ArrayRef< BasicBlock * > BBs, SmallVectorImpl< DominatorTree::UpdateType > *Updates, bool KeepOneInputPHIs=false)
Replace contents of every block in BBs with single unreachable instruction.
bool verifyFunction(const Function &F, raw_ostream *OS=nullptr)
Check a function for errors, useful for use when debugging a pass.
CallInst * changeToCall(InvokeInst *II, DomTreeUpdater *DTU=nullptr)
This function converts the specified invoke into a normal call.
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.
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="")
InlineResult isInlineViable(Function &Callee)
Minimal filter to detect invalid constructs for inlining.
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
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.
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...
bool NullPointerIsDefined(const Function *F, unsigned AS=0)
Check whether null pointer dereferencing is considered undefined behavior for a given function or an ...
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool AreStatisticsEnabled()
Check if statistics are enabled.
Constant * ConstantFoldLoadFromConst(Constant *C, Type *Ty, const APInt &Offset, const DataLayout &DL)
Extract value of C at the given Offset reinterpreted as Ty.
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...
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
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)
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)
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.
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)
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 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.
AADepGraphNode SyntheticRoot
There is no root node for the dependency graph.
void print()
Print dependency graph.
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 const char ID
Unique ID (due to the unique address)
An abstract interface to determine reachability of point A to B.
static 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 const char ID
Unique ID (due to the unique address)
An abstract interface for all memory location attributes (readnone/argmemonly/inaccessiblememonly/ina...
static const char ID
Unique ID (due to the unique address)
static const char ID
Unique ID (due to the unique address)
static const char ID
Unique ID (due to the unique address)
static const char ID
Unique ID (due to the unique address)
static const char ID
Unique ID (due to the unique address)
static const char ID
Unique ID (due to the unique address)
static const char ID
Unique ID (due to the unique address)
static const char ID
Unique ID (due to the unique address)
static bool isNonRelaxedAtomic(const Instruction *I)
Helper function used to determine whether an instruction is non-relaxed atomic.
static bool isNoSyncIntrinsic(const Instruction *I)
Helper function specific for intrinsics which are potentially volatile.
static const char ID
Unique ID (due to the unique address)
static 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 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 const char ID
Unique ID (due to the unique address)
static 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 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 const std::string getName() const =0
This function should return the name of the AbstractAttribute.
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...
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.
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.
PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG, CGSCCUpdateResult &UR)
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
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.
bool registerFunctionSignatureRewrite(Argument &Arg, ArrayRef< Type * > ReplacementTypes, ArgumentReplacementInfo::CalleeRepairCBTy &&CalleeRepairCB, ArgumentReplacementInfo::ACSRepairCBTy &&ACSRepairCB)
Register a rewrite for a function signature.
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.
bool isValidFunctionSignatureRewrite(Argument &Arg, ArrayRef< Type * > ReplacementTypes)
Check if we can rewrite a function signature.
static bool isInternalizable(Function &F)
Returns true if the function F can be internalized.
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.
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.
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.
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 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 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.
bool checkForAllReadWriteInstructions(function_ref< bool(Instruction &)> Pred, AbstractAttribute &QueryingAA, bool &UsedAssumedInformation)
Check Pred on all Read/Write instructions.
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.
bool isClosedWorldModule() const
Return true if the module contains the whole world, thus, no outside functions exist.
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,...
Attributor(SetVector< Function * > &Functions, InformationCache &InfoCache, AttributorConfig Configuration)
Constructor.
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.
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.
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.
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...
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.
void registerForUpdate(AbstractAttribute &AA)
Allows a query AA to request an update if a new query was received.
void identifyDefaultAbstractAttributes(Function &F)
Determine opportunities to derive 'default' attributes in F and create abstract attribute objects for...
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
ChangeStatus run()
Run the analyses until a fixpoint is reached or enforced (timeout).
static 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...
bool checkForAllCallSites(function_ref< bool(AbstractCallSite)> Pred, const AbstractAttribute &QueryingAA, bool RequireAllCallSites, bool &UsedAssumedInformation)
Check Pred on all function call sites.
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.
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 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 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.