51#ifdef EXPENSIVE_CHECKS
61#define DEBUG_TYPE "attributor"
62#define VERBOSE_DEBUG_TYPE DEBUG_TYPE "-verbose"
65 "Determine what attributes are manifested in the IR");
67STATISTIC(NumFnDeleted,
"Number of function deleted");
69 "Number of functions with exact definitions");
71 "Number of functions without exact definitions");
72STATISTIC(NumFnShallowWrappersCreated,
"Number of shallow wrappers created");
74 "Number of abstract attributes timed out before fixpoint");
76 "Number of abstract attributes in a valid fixpoint state");
78 "Number of abstract attributes manifested in IR");
90 cl::desc(
"Maximal number of fixpoint iterations."),
94 "attributor-max-initialization-chain-length",
cl::Hidden,
96 "Maximal number of chained initializations (to avoid stack overflows)"),
101 "attributor-max-iterations-verify",
cl::Hidden,
102 cl::desc(
"Verify that max-iterations is a tight bound for a fixpoint"),
107 cl::desc(
"Annotate call sites of function declarations."),
cl::init(
false));
114 cl::desc(
"Allow the Attributor to create shallow "
115 "wrappers for non-exact definitions."),
120 cl::desc(
"Allow the Attributor to use IP information "
121 "derived from non-exact functions via cloning"),
128 cl::desc(
"Comma seperated list of attribute names that are "
129 "allowed to be seeded."),
133 "attributor-function-seed-allow-list",
cl::Hidden,
134 cl::desc(
"Comma seperated list of function names that are "
135 "allowed to be seeded."),
141 cl::desc(
"Dump the dependency graph to dot files."),
145 "attributor-depgraph-dot-filename-prefix",
cl::Hidden,
146 cl::desc(
"The prefix used for the CallGraph dot file names."));
149 cl::desc(
"View the dependency graph."),
153 cl::desc(
"Print attribute dependencies"),
157 "attributor-enable-call-site-specific-deduction",
cl::Hidden,
158 cl::desc(
"Allow the Attributor to do call site specific analysis"),
163 cl::desc(
"Print Attributor's internal call graph"),
168 cl::desc(
"Try to simplify all loads."),
175 return L == ChangeStatus::CHANGED ? L : R;
182 return L == ChangeStatus::UNCHANGED ? L : R;
193 if (
const auto *CB = dyn_cast<CallBase>(&
I)) {
194 if (CB->hasFnAttr(Attribute::NoSync))
198 if (!CB->isConvergent() && !CB->mayReadOrWriteMemory())
204 const auto &NoSyncAA =
A.getAAFor<
AANoSync>(
209 if (!
I.mayReadOrWriteMemory())
216 const Value &V,
bool ForAnalysisOnly) {
218 if (!ForAnalysisOnly)
229 if (isa<AllocaInst>(Obj))
233 auto *GV = dyn_cast<GlobalVariable>(&Obj);
236 if (!GV->hasLocalLinkage() && !(GV->isConstant() && GV->hasInitializer()))
238 if (!GV->hasInitializer())
250 if (isa<Constant>(V))
252 if (
auto *
I = dyn_cast<Instruction>(&V))
253 return I->getFunction() == Scope;
254 if (
auto *
A = dyn_cast<Argument>(&V))
255 return A->getParent() == Scope;
267 if (
auto *
A = dyn_cast<Argument>(VAC.
getValue()))
268 return A->getParent() == Scope;
269 if (
auto *
I = dyn_cast<Instruction>(VAC.
getValue())) {
270 if (
I->getFunction() == Scope) {
274 return DT->dominates(
I, CtxI);
276 if (CtxI &&
I->getParent() == CtxI->
getParent())
279 [&](
const Instruction &AfterI) { return &AfterI == CtxI; });
286 if (V.getType() == &Ty)
288 if (isa<PoisonValue>(V))
290 if (isa<UndefValue>(V))
292 if (
auto *
C = dyn_cast<Constant>(&V)) {
293 if (
C->isNullValue())
307std::optional<Value *>
309 const std::optional<Value *> &
B,
322 Ty = (*A)->getType();
323 if (isa_and_nonnull<UndefValue>(*
A))
325 if (isa<UndefValue>(*
B))
332template <
bool IsLoad,
typename Ty>
338 LLVM_DEBUG(
dbgs() <<
"Trying to determine the potential copies of " <<
I
339 <<
" (only exact: " << OnlyExact <<
")\n";);
350 A.getInfoCache().getTargetLibraryInfoForFunction(*
I.getFunction());
352 auto Pred = [&](
Value &Obj) {
354 if (isa<UndefValue>(&Obj))
356 if (isa<ConstantPointerNull>(&Obj)) {
360 Ptr.getType()->getPointerAddressSpace()) &&
361 A.getAssumedSimplified(
Ptr, QueryingAA, UsedAssumedInformation,
365 dbgs() <<
"Underlying object is a valid nullptr, giving up.\n";);
369 if (!isa<AllocaInst>(&Obj) && !isa<GlobalVariable>(&Obj) &&
371 LLVM_DEBUG(
dbgs() <<
"Underlying object is not supported yet: " << Obj
375 if (
auto *GV = dyn_cast<GlobalVariable>(&Obj))
376 if (!GV->hasLocalLinkage() &&
377 !(GV->isConstant() && GV->hasInitializer())) {
379 "linkage, not supported yet: "
384 bool NullOnly =
true;
385 bool NullRequired =
false;
386 auto CheckForNullOnlyAndUndef = [&](std::optional<Value *> V,
388 if (!V || *V ==
nullptr)
390 else if (isa<UndefValue>(*V))
392 else if (isa<Constant>(*V) && cast<Constant>(*V)->isNullValue())
393 NullRequired = !IsExact;
402 LLVM_DEBUG(
dbgs() <<
"Underlying object written but stored value "
403 "cannot be converted to read type: "
415 CheckForNullOnlyAndUndef(Acc.
getContent(), IsExact);
416 if (OnlyExact && !IsExact && !NullOnly &&
422 if (NullRequired && !NullOnly) {
423 LLVM_DEBUG(
dbgs() <<
"Required all `null` accesses due to non exact "
424 "one, however found non-null one: "
429 assert(isa<LoadInst>(
I) &&
"Expected load or store instruction only!");
440 LLVM_DEBUG(
dbgs() <<
"Underlying object written through a non-store "
441 "instruction not supported yet: "
445 Value *V = AdjustWrittenValueType(Acc, *
SI->getValueOperand());
451 assert(isa<StoreInst>(
I) &&
"Expected load or store instruction only!");
453 if (!LI && OnlyExact) {
455 "instruction not supported yet: "
466 bool HasBeenWrittenTo =
false;
471 if (!PI.forallInterferingAccesses(
A, QueryingAA,
I,
474 CheckAccess, HasBeenWrittenTo, Range)) {
477 <<
"Failed to verify all interfering accesses for underlying object: "
482 if (IsLoad && !HasBeenWrittenTo && !Range.isUnassigned()) {
484 Value *InitialValue =
487 LLVM_DEBUG(
dbgs() <<
"Could not determine required initial value of "
488 "underlying object, abort!\n");
491 CheckForNullOnlyAndUndef(InitialValue,
true);
492 if (NullRequired && !NullOnly) {
493 LLVM_DEBUG(
dbgs() <<
"Non exact access but initial value that is not "
494 "null or undef, abort!\n");
509 if (!AAUO.forallUnderlyingObjects(Pred)) {
511 dbgs() <<
"Underlying objects stored into could not be determined\n";);
518 for (
const auto *PI : PIs) {
519 if (!PI->getState().isAtFixpoint())
520 UsedAssumedInformation =
true;
521 A.recordDependence(*PI, QueryingAA, DepClassTy::OPTIONAL);
524 PotentialValueOrigins.
insert(NewCopyOrigins.
begin(), NewCopyOrigins.
end());
535 A, LI, PotentialValues, PotentialValueOrigins, QueryingAA,
536 UsedAssumedInformation, OnlyExact);
545 A,
SI, PotentialCopies, PotentialValueOrigins, QueryingAA,
546 UsedAssumedInformation, OnlyExact);
551 bool RequireReadNone,
bool &IsKnown) {
555 const auto &MemLocAA =
557 if (MemLocAA.isAssumedReadNone()) {
558 IsKnown = MemLocAA.isKnownReadNone();
560 A.recordDependence(MemLocAA, QueryingAA, DepClassTy::OPTIONAL);
565 const auto &MemBehaviorAA =
567 if (MemBehaviorAA.isAssumedReadNone() ||
568 (!RequireReadNone && MemBehaviorAA.isAssumedReadOnly())) {
569 IsKnown = RequireReadNone ? MemBehaviorAA.isKnownReadNone()
570 : MemBehaviorAA.isKnownReadOnly();
572 A.recordDependence(MemBehaviorAA, QueryingAA, DepClassTy::OPTIONAL);
595 std::function<
bool(
const Function &
F)> GoBackwardsCB) {
597 dbgs() <<
"[AA] isPotentiallyReachable @" << ToFn.
getName() <<
" from "
598 << FromI <<
" [GBCB: " <<
bool(GoBackwardsCB) <<
"][#ExS: "
599 << (ExclusionSet ? std::to_string(ExclusionSet->
size()) :
"none")
602 for (
auto *ES : *ExclusionSet)
603 dbgs() << *ES <<
"\n";
611 if (GoBackwardsCB && &ToFn != FromI.
getFunction() &&
614 LLVM_DEBUG(
dbgs() <<
"[AA] assume kernel cannot be reached from within the "
615 "module; success\n";);
624 if (!GoBackwardsCB && !ExclusionSet) {
626 <<
" is not checked backwards and does not have an "
627 "exclusion set, abort\n");
635 while (!Worklist.
empty()) {
637 if (!Visited.
insert(CurFromI).second)
641 if (FromFn == &ToFn) {
644 LLVM_DEBUG(
dbgs() <<
"[AA] check " << *ToI <<
" from " << *CurFromI
645 <<
" intraprocedurally\n");
649 ReachabilityAA.isAssumedReachable(
A, *CurFromI, *ToI, ExclusionSet);
651 << (Result ?
"can potentially " :
"cannot ") <<
"reach "
652 << *ToI <<
" [Intra]\n");
663 ToReachabilityAA.isAssumedReachable(
A, EntryI, *ToI, ExclusionSet);
665 <<
" " << (Result ?
"can potentially " :
"cannot ")
666 <<
"reach @" << *ToI <<
" [ToFn]\n");
674 Result = FnReachabilityAA.instructionCanReach(
A, *CurFromI, ToFn,
677 <<
" " << (Result ?
"can potentially " :
"cannot ")
678 <<
"reach @" << ToFn.
getName() <<
" [FromFn]\n");
688 ReachabilityAA.isAssumedReachable(
A, *CurFromI, Ret, ExclusionSet);
690 << (Result ?
"can potentially " :
"cannot ") <<
"reach "
691 << Ret <<
" [Intra]\n");
696 bool UsedAssumedInformation =
false;
697 if (
A.checkForAllInstructions(ReturnInstCB, FromFn, QueryingAA,
698 {Instruction::Ret}, UsedAssumedInformation)) {
703 if (!GoBackwardsCB) {
705 <<
" is not checked backwards, abort\n");
711 if (!GoBackwardsCB(*FromFn))
718 CallBase *CB = ACS.getInstruction();
722 if (isa<InvokeInst>(CB))
730 Result = !
A.checkForAllCallSites(CheckCallSite, *FromFn,
732 &QueryingAA, UsedAssumedInformation);
734 LLVM_DEBUG(
dbgs() <<
"[AA] stepping back to call sites from " << *CurFromI
735 <<
" in @" << FromFn->
getName()
736 <<
" failed, give up\n");
740 LLVM_DEBUG(
dbgs() <<
"[AA] stepped back to call sites from " << *CurFromI
741 <<
" in @" << FromFn->
getName()
742 <<
" worklist size is: " << Worklist.
size() <<
"\n");
751 std::function<
bool(
const Function &
F)> GoBackwardsCB) {
753 return ::isPotentiallyReachable(
A, FromI, &ToI, *ToFn, QueryingAA,
754 ExclusionSet, GoBackwardsCB);
761 std::function<
bool(
const Function &
F)> GoBackwardsCB) {
762 return ::isPotentiallyReachable(
A, FromI,
nullptr, ToFn, QueryingAA,
763 ExclusionSet, GoBackwardsCB);
768 if (isa<UndefValue>(Obj))
770 if (isa<AllocaInst>(Obj)) {
774 dbgs() <<
"[AA] Object '" << Obj
775 <<
"' is thread local; stack objects are thread local.\n");
781 << (NoCaptureAA.isAssumedNoCapture() ?
"" :
"not")
783 << (NoCaptureAA.isAssumedNoCapture() ?
"non-" :
"")
784 <<
"captured stack object.\n");
785 return NoCaptureAA.isAssumedNoCapture();
787 if (
auto *GV = dyn_cast<GlobalVariable>(&Obj)) {
788 if (GV->isConstant()) {
790 <<
"' is thread local; constant global\n");
793 if (GV->isThreadLocal()) {
795 <<
"' is thread local; thread local global\n");
800 if (
A.getInfoCache().targetIsGPU()) {
802 (
int)AA::GPUAddressSpace::Local) {
804 <<
"' is thread local; GPU local memory\n");
808 (
int)AA::GPUAddressSpace::Constant) {
810 <<
"' is thread local; GPU constant memory\n");
815 LLVM_DEBUG(
dbgs() <<
"[AA] Object '" << Obj <<
"' is not thread local\n");
821 if (!
I.mayHaveSideEffects() && !
I.mayReadFromMemory())
826 auto AddLocationPtr = [&](std::optional<MemoryLocation> Loc) {
827 if (!Loc || !Loc->Ptr) {
829 dbgs() <<
"[AA] Access to unknown location; -> requires barriers\n");
858 auto Pred = [&](
Value &Obj) {
862 <<
"'; -> requires barrier\n");
868 if (!UnderlyingObjsAA.forallUnderlyingObjects(Pred))
887 bool ForceReplace =
false) {
891 if (Attrs.hasAttributeAtIndex(AttrIdx, Kind))
895 Attrs = Attrs.addAttributeAtIndex(Ctx, AttrIdx, Attr);
900 if (Attrs.hasAttributeAtIndex(AttrIdx, Kind))
904 Attrs = Attrs.addAttributeAtIndex(Ctx, AttrIdx, Attr);
909 if (Attrs.hasAttributeAtIndex(AttrIdx, Kind))
913 Attrs = Attrs.removeAttributeAtIndex(Ctx, AttrIdx, Kind);
914 Attrs = Attrs.addAttributeAtIndex(Ctx, AttrIdx, Attr);
935 std::optional<Argument *> CBCandidateArg;
939 for (
const Use *U : CallbackUses) {
953 "ACS mapped into var-args arguments!");
954 if (CBCandidateArg) {
955 CBCandidateArg =
nullptr;
963 if (CBCandidateArg && *CBCandidateArg)
964 return *CBCandidateArg;
970 return Callee->getArg(ArgNo);
984 LLVM_DEBUG(
dbgs() <<
"[Attributor] Update " << HasChanged <<
" " << *
this
1020 for (
const Attribute &Attr : DeducedAttrs) {
1054 IRPositions.emplace_back(IRP);
1058 auto CanIgnoreOperandBundles = [](
const CallBase &CB) {
1059 return (isa<IntrinsicInst>(CB) &&
1060 cast<IntrinsicInst>(CB).getIntrinsicID() == Intrinsic ::assume);
1074 assert(CB &&
"Expected call site!");
1077 if (!CB->hasOperandBundles() || CanIgnoreOperandBundles(*CB))
1082 assert(CB &&
"Expected call site!");
1085 if (!CB->hasOperandBundles() || CanIgnoreOperandBundles(*CB)) {
1090 if (
Arg.hasReturnedAttr()) {
1091 IRPositions.emplace_back(
1093 IRPositions.emplace_back(
1102 assert(CB &&
"Expected call site!");
1105 if (!CB->hasOperandBundles() || CanIgnoreOperandBundles(*CB)) {
1120 bool IgnoreSubsumingPositions,
Attributor *
A)
const {
1124 if (EquivIRP.getAttrsFromIRAttr(AK, Attrs))
1129 if (IgnoreSubsumingPositions)
1134 if (getAttrsFromAssumes(AK, Attrs, *
A))
1141 bool IgnoreSubsumingPositions,
Attributor *
A)
const {
1144 EquivIRP.getAttrsFromIRAttr(AK, Attrs);
1148 if (IgnoreSubsumingPositions)
1153 getAttrsFromAssumes(AK, Attrs, *
A);
1180 A.getInfoCache().getKnowledgeMap().lookup({&AssociatedValue, AK});
1188 unsigned AttrsSize =
Attrs.size();
1190 A.getInfoCache().getMustBeExecutedContextExplorer();
1192 for (
const auto &It : A2K)
1195 return AttrsSize !=
Attrs.size();
1198void IRPosition::verify() {
1199#ifdef EXPENSIVE_CHECKS
1202 assert((CBContext ==
nullptr) &&
1203 "Invalid position must not have CallBaseContext!");
1205 "Expected a nullptr for an invalid position!");
1209 "Expected specialized kind for argument values!");
1212 assert(isa<Function>(getAsValuePtr()) &&
1213 "Expected function for a 'returned' position!");
1215 "Associated value mismatch!");
1218 assert((CBContext ==
nullptr) &&
1219 "'call site returned' position must not have CallBaseContext!");
1220 assert((isa<CallBase>(getAsValuePtr())) &&
1221 "Expected call base for 'call site returned' position!");
1223 "Associated value mismatch!");
1226 assert((CBContext ==
nullptr) &&
1227 "'call site function' position must not have CallBaseContext!");
1228 assert((isa<CallBase>(getAsValuePtr())) &&
1229 "Expected call base for 'call site function' position!");
1231 "Associated value mismatch!");
1234 assert(isa<Function>(getAsValuePtr()) &&
1235 "Expected function for a 'function' position!");
1237 "Associated value mismatch!");
1240 assert(isa<Argument>(getAsValuePtr()) &&
1241 "Expected argument for a 'argument' position!");
1243 "Associated value mismatch!");
1246 assert((CBContext ==
nullptr) &&
1247 "'call site argument' position must not have CallBaseContext!");
1248 Use *
U = getAsUsePtr();
1250 assert(U &&
"Expected use for a 'call site argument' position!");
1251 assert(isa<CallBase>(
U->getUser()) &&
1252 "Expected call base user for a 'call site argument' position!");
1253 assert(cast<CallBase>(
U->getUser())->isArgOperand(U) &&
1254 "Expected call base argument operand for a 'call site argument' "
1256 assert(cast<CallBase>(
U->getUser())->getArgOperandNo(U) ==
1258 "Argument number mismatch!");
1266std::optional<Constant *>
1269 bool &UsedAssumedInformation) {
1273 for (
auto &CB : SimplificationCallbacks.lookup(IRP)) {
1274 std::optional<Value *> SimplifiedV = CB(IRP, &AA, UsedAssumedInformation);
1276 return std::nullopt;
1277 if (isa_and_nonnull<Constant>(*SimplifiedV))
1278 return cast<Constant>(*SimplifiedV);
1286 UsedAssumedInformation)) {
1288 return std::nullopt;
1289 if (
auto *
C = dyn_cast_or_null<Constant>(
1302 for (
auto &CB : SimplificationCallbacks.lookup(IRP))
1303 return CB(IRP, AA, UsedAssumedInformation);
1309 return std::nullopt;
1322 bool &UsedAssumedInformation) {
1326 const auto &SimplificationCBs = SimplificationCallbacks.lookup(IRP);
1327 for (
const auto &CB : SimplificationCBs) {
1328 std::optional<Value *> CBResult = CB(IRP, AA, UsedAssumedInformation);
1329 if (!CBResult.has_value())
1331 Value *V = *CBResult;
1340 if (!SimplificationCBs.empty())
1344 const auto &PotentialValuesAA =
1346 if (!PotentialValuesAA.getAssumedSimplifiedValues(*
this, Values, S))
1348 UsedAssumedInformation |= !PotentialValuesAA.isAtFixpoint();
1354 bool &UsedAssumedInformation) {
1357 if (*V ==
nullptr || isa<Constant>(*V))
1359 if (
auto *
Arg = dyn_cast<Argument>(*V))
1361 if (!
Arg->hasPointeeInMemoryValueAttr())
1371 for (
auto &It : AAMap) {
1379 bool &UsedAssumedInformation,
1380 bool CheckBBLivenessOnly,
DepClassTy DepClass) {
1384 return isAssumedDead(IRP, &AA, FnLivenessAA, UsedAssumedInformation,
1385 CheckBBLivenessOnly, DepClass);
1391 bool &UsedAssumedInformation,
1392 bool CheckBBLivenessOnly,
DepClassTy DepClass) {
1393 Instruction *UserI = dyn_cast<Instruction>(U.getUser());
1396 UsedAssumedInformation, CheckBBLivenessOnly, DepClass);
1398 if (
auto *CB = dyn_cast<CallBase>(UserI)) {
1401 if (CB->isArgOperand(&U)) {
1405 UsedAssumedInformation, CheckBBLivenessOnly,
1408 }
else if (
ReturnInst *RI = dyn_cast<ReturnInst>(UserI)) {
1411 UsedAssumedInformation, CheckBBLivenessOnly, DepClass);
1412 }
else if (
PHINode *
PHI = dyn_cast<PHINode>(UserI)) {
1415 UsedAssumedInformation, CheckBBLivenessOnly, DepClass);
1416 }
else if (
StoreInst *
SI = dyn_cast<StoreInst>(UserI)) {
1417 if (!CheckBBLivenessOnly &&
SI->getPointerOperand() != U.get()) {
1425 UsedAssumedInformation =
true;
1432 UsedAssumedInformation, CheckBBLivenessOnly, DepClass);
1438 bool &UsedAssumedInformation,
1439 bool CheckBBLivenessOnly,
DepClassTy DepClass,
1440 bool CheckForDeadStore) {
1444 if (ManifestAddedBlocks.contains(
I.getParent()))
1453 if (QueryingAA == FnLivenessAA)
1457 if (CheckBBLivenessOnly ? FnLivenessAA->
isAssumedDead(
I.getParent())
1462 UsedAssumedInformation =
true;
1466 if (CheckBBLivenessOnly)
1474 if (QueryingAA == &IsDeadAA)
1481 UsedAssumedInformation =
true;
1489 UsedAssumedInformation =
true;
1499 bool &UsedAssumedInformation,
1500 bool CheckBBLivenessOnly,
DepClassTy DepClass) {
1510 isAssumedDead(*CtxI, QueryingAA, FnLivenessAA, UsedAssumedInformation,
1515 if (CheckBBLivenessOnly)
1521 IsDeadAA = &getOrCreateAAFor<AAIsDead>(
1528 if (QueryingAA == IsDeadAA)
1535 UsedAssumedInformation =
true;
1552 if (QueryingAA == FnLivenessAA)
1567 bool CheckBBLivenessOnly,
DepClassTy LivenessDepClass,
1568 bool IgnoreDroppableUses,
1573 if (!CB(*
this, &QueryingAA))
1584 auto AddUsers = [&](
const Value &V,
const Use *OldUse) {
1585 for (
const Use &UU : V.uses()) {
1586 if (OldUse && EquivalentUseCB && !EquivalentUseCB(*OldUse, UU)) {
1588 "rejected by the equivalence call back: "
1598 AddUsers(V,
nullptr);
1601 <<
" initial uses to check\n");
1604 const auto *LivenessAA =
1609 while (!Worklist.
empty()) {
1611 if (isa<PHINode>(U->getUser()) && !Visited.
insert(U).second)
1614 if (
auto *Fn = dyn_cast<Function>(U->getUser()))
1615 dbgs() <<
"[Attributor] Check use: " << **U <<
" in " << Fn->getName()
1618 dbgs() <<
"[Attributor] Check use: " << **U <<
" in " << *U->getUser()
1621 bool UsedAssumedInformation =
false;
1622 if (
isAssumedDead(*U, &QueryingAA, LivenessAA, UsedAssumedInformation,
1623 CheckBBLivenessOnly, LivenessDepClass)) {
1625 dbgs() <<
"[Attributor] Dead use, skip!\n");
1628 if (IgnoreDroppableUses && U->getUser()->isDroppable()) {
1630 dbgs() <<
"[Attributor] Droppable user, skip!\n");
1634 if (
auto *
SI = dyn_cast<StoreInst>(U->getUser())) {
1635 if (&
SI->getOperandUse(0) == U) {
1636 if (!Visited.
insert(U).second)
1640 *
this, *
SI, PotentialCopies, QueryingAA, UsedAssumedInformation,
1644 <<
"[Attributor] Value is stored, continue with "
1645 << PotentialCopies.
size()
1646 <<
" potential copies instead!\n");
1647 for (
Value *PotentialCopy : PotentialCopies)
1648 if (!AddUsers(*PotentialCopy, U))
1655 bool Follow =
false;
1656 if (!Pred(*U, Follow))
1661 User &Usr = *U->getUser();
1662 AddUsers(Usr,
nullptr);
1664 auto *RI = dyn_cast<ReturnInst>(&Usr);
1670 return AddUsers(*ACS.getInstruction(), U);
1673 &QueryingAA, UsedAssumedInformation)) {
1674 LLVM_DEBUG(
dbgs() <<
"[Attributor] Could not follow return instruction "
1675 "to all call sites: "
1686 bool RequireAllCallSites,
1687 bool &UsedAssumedInformation) {
1693 if (!AssociatedFunction) {
1694 LLVM_DEBUG(
dbgs() <<
"[Attributor] No function associated with " << IRP
1700 &QueryingAA, UsedAssumedInformation);
1705 bool RequireAllCallSites,
1707 bool &UsedAssumedInformation,
1708 bool CheckPotentiallyDead) {
1712 <<
"[Attributor] Function " << Fn.
getName()
1713 <<
" has no internal linkage, hence not all call sites are known\n");
1718 if (!CB(*
this, QueryingAA))
1722 for (
unsigned u = 0; u <
Uses.size(); ++u) {
1725 if (
auto *Fn = dyn_cast<Function>(U))
1726 dbgs() <<
"[Attributor] Check use: " << Fn->
getName() <<
" in "
1727 << *U.getUser() <<
"\n";
1729 dbgs() <<
"[Attributor] Check use: " << *U <<
" in " << *U.getUser()
1732 if (!CheckPotentiallyDead &&
1733 isAssumedDead(U, QueryingAA,
nullptr, UsedAssumedInformation,
1736 dbgs() <<
"[Attributor] Dead use, skip!\n");
1739 if (
ConstantExpr *CE = dyn_cast<ConstantExpr>(U.getUser())) {
1740 if (CE->isCast() && CE->getType()->isPointerTy()) {
1742 dbgs() <<
"[Attributor] Use, is constant cast expression, add "
1743 << CE->getNumUses() <<
" uses of that expression instead!\n";
1745 for (
const Use &CEU : CE->uses())
1746 Uses.push_back(&CEU);
1754 <<
" has non call site use " << *U.get() <<
" in "
1755 << *U.getUser() <<
"\n");
1757 if (isa<BlockAddress>(U.getUser()))
1762 const Use *EffectiveUse =
1765 if (!RequireAllCallSites) {
1766 LLVM_DEBUG(
dbgs() <<
"[Attributor] User " << *EffectiveUse->getUser()
1767 <<
" is not a call of " << Fn.
getName()
1771 LLVM_DEBUG(
dbgs() <<
"[Attributor] User " << *EffectiveUse->getUser()
1772 <<
" is an invalid use of " << Fn.
getName() <<
"\n");
1780 unsigned MinArgsParams =
1782 for (
unsigned u = 0; u < MinArgsParams; ++u) {
1786 dbgs() <<
"[Attributor] Call site / callee argument type mismatch ["
1787 << u <<
"@" << Fn.
getName() <<
": "
1797 LLVM_DEBUG(
dbgs() <<
"[Attributor] Call site callback failed for "
1805bool Attributor::shouldPropagateCallBaseContext(
const IRPosition &IRP) {
1820 if (!AssociatedFunction)
1827 const auto &AARetVal =
1829 if (!AARetVal.getState().isValidState())
1832 return AARetVal.checkForAllReturnedValuesAndReturnInsts(Pred);
1840 if (!AssociatedFunction)
1846 const auto &AARetVal =
1848 if (!AARetVal.getState().isValidState())
1851 return AARetVal.checkForAllReturnedValuesAndReturnInsts(
1861 bool &UsedAssumedInformation,
bool CheckBBLivenessOnly =
false,
1862 bool CheckPotentiallyDead =
false) {
1863 for (
unsigned Opcode : Opcodes) {
1865 auto *Insts = OpcodeInstMap.
lookup(Opcode);
1871 if (
A && !CheckPotentiallyDead &&
1873 UsedAssumedInformation, CheckBBLivenessOnly)) {
1875 dbgs() <<
"[Attributor] Instruction " << *
I
1876 <<
" is potentially dead, skip!\n";);
1891 bool &UsedAssumedInformation,
1892 bool CheckBBLivenessOnly,
1893 bool CheckPotentiallyDead) {
1900 const auto *LivenessAA =
1901 CheckPotentiallyDead
1907 LivenessAA, Opcodes, UsedAssumedInformation,
1908 CheckBBLivenessOnly, CheckPotentiallyDead))
1917 bool &UsedAssumedInformation,
1918 bool CheckBBLivenessOnly,
1919 bool CheckPotentiallyDead) {
1923 UsedAssumedInformation, CheckBBLivenessOnly,
1924 CheckPotentiallyDead);
1929 bool &UsedAssumedInformation) {
1931 const Function *AssociatedFunction =
1933 if (!AssociatedFunction)
1938 const auto &LivenessAA =
1945 UsedAssumedInformation))
1955void Attributor::runTillFixpoint() {
1959 <<
" abstract attributes.\n");
1964 unsigned IterationCounter = 1;
1965 unsigned MaxIterations =
1975 LLVM_DEBUG(
dbgs() <<
"\n\n[Attributor] #Iteration: " << IterationCounter
1976 <<
", Worklist size: " << Worklist.
size() <<
"\n");
1981 for (
unsigned u = 0; u < InvalidAAs.
size(); ++u) {
1986 dbgs() <<
"[Attributor] InvalidAA: " << *InvalidAA
1987 <<
" has " << InvalidAA->
Deps.
size()
1988 <<
" required & optional dependences\n");
1989 for (
auto &DepIt : InvalidAA->
Deps) {
1993 dbgs() <<
" - recompute: " << *DepAA);
1998 <<
" - invalidate: " << *DepAA);
2002 InvalidAAs.
insert(DepAA);
2012 for (
auto &DepIt : ChangedAA->Deps)
2013 Worklist.
insert(cast<AbstractAttribute>(DepIt.getPointer()));
2014 ChangedAA->Deps.clear();
2017 LLVM_DEBUG(
dbgs() <<
"[Attributor] #Iteration: " << IterationCounter
2018 <<
", Worklist+Dependent size: " << Worklist.
size()
2028 const auto &AAState = AA->getState();
2029 if (!AAState.isAtFixpoint())
2031 ChangedAAs.push_back(AA);
2035 if (!AAState.isValidState())
2047 Worklist.insert(ChangedAAs.begin(), ChangedAAs.end());
2048 Worklist.insert(QueryAAsAwaitingUpdate.begin(),
2049 QueryAAsAwaitingUpdate.end());
2050 QueryAAsAwaitingUpdate.clear();
2052 }
while (!Worklist.empty() &&
2055 if (IterationCounter > MaxIterations && !Functions.
empty()) {
2057 return ORM <<
"Attributor did not reach a fixpoint after "
2058 <<
ore::NV(
"Iterations", MaxIterations) <<
" iterations.";
2061 emitRemark<OptimizationRemarkMissed>(
F,
"FixedPoint",
Remark);
2064 LLVM_DEBUG(
dbgs() <<
"\n[Attributor] Fixpoint iteration done after: "
2065 << IterationCounter <<
"/" << MaxIterations
2066 <<
" iterations\n");
2074 for (
unsigned u = 0;
u < ChangedAAs.size();
u++) {
2076 if (!Visited.
insert(ChangedAA).second)
2083 NumAttributesTimedOut++;
2086 for (
auto &DepIt : ChangedAA->
Deps)
2087 ChangedAAs.push_back(cast<AbstractAttribute>(DepIt.getPointer()));
2092 if (!Visited.
empty())
2093 dbgs() <<
"\n[Attributor] Finalized " << Visited.
size()
2094 <<
" abstract attributes.\n";
2098 errs() <<
"\n[Attributor] Fixpoint iteration done after: "
2099 << IterationCounter <<
"/" << MaxIterations <<
" iterations\n";
2100 llvm_unreachable(
"The fixpoint was not reached with exactly the number of "
2101 "specified iterations!");
2107 "Non-query AAs should not be required to register for updates!");
2108 QueryAAsAwaitingUpdate.insert(&AA);
2115 unsigned NumManifested = 0;
2116 unsigned NumAtFixpoint = 0;
2140 bool UsedAssumedInformation =
false;
2152 LLVM_DEBUG(
dbgs() <<
"[Attributor] Manifest " << LocalChange <<
" : " << *AA
2155 ManifestChange = ManifestChange | LocalChange;
2161 (void)NumManifested;
2162 (void)NumAtFixpoint;
2163 LLVM_DEBUG(
dbgs() <<
"\n[Attributor] Manifested " << NumManifested
2164 <<
" arguments while " << NumAtFixpoint
2165 <<
" were in a valid fixpoint state\n");
2167 NumAttributesManifested += NumManifested;
2168 NumAttributesValidFixpoint += NumAtFixpoint;
2173 for (
unsigned u = 0; u < NumFinalAAs; ++u)
2177 errs() <<
"Unexpected abstract attribute: "
2178 << cast<AbstractAttribute>(DepIt->getPointer()) <<
" :: "
2179 << cast<AbstractAttribute>(DepIt->getPointer())
2181 .getAssociatedValue()
2185 "remain unchanged!");
2187 return ManifestChange;
2190void Attributor::identifyDeadInternalFunctions() {
2211 if (
F->hasLocalLinkage() && (
isModulePass() || !TLI->getLibFunc(*
F, LF)))
2215 bool FoundLiveInternal =
true;
2216 while (FoundLiveInternal) {
2217 FoundLiveInternal =
false;
2218 for (
unsigned u = 0, e = InternalFns.
size(); u < e; ++u) {
2223 bool UsedAssumedInformation =
false;
2227 return ToBeDeletedFunctions.count(
Callee) ||
2228 (Functions.count(
Callee) &&
Callee->hasLocalLinkage() &&
2231 *
F,
true,
nullptr, UsedAssumedInformation)) {
2236 InternalFns[
u] =
nullptr;
2237 FoundLiveInternal =
true;
2241 for (
unsigned u = 0, e = InternalFns.
size(); u < e; ++u)
2243 ToBeDeletedFunctions.insert(
F);
2250 << ToBeDeletedFunctions.size() <<
" functions and "
2251 << ToBeDeletedBlocks.size() <<
" blocks and "
2252 << ToBeDeletedInsts.size() <<
" instructions and "
2253 << ToBeChangedValues.size() <<
" values and "
2254 << ToBeChangedUses.size() <<
" uses. To insert "
2255 << ToBeChangedToUnreachableInsts.size()
2256 <<
" unreachables.\n"
2257 <<
"Preserve manifest added " << ManifestAddedBlocks.size()
2263 auto ReplaceUse = [&](
Use *
U,
Value *NewV) {
2268 const auto &Entry = ToBeChangedValues.lookup(NewV);
2271 NewV = get<0>(Entry);
2276 "Cannot replace an instruction outside the current SCC!");
2280 if (
auto *RI = dyn_cast_or_null<ReturnInst>(
I)) {
2282 if (CI->isMustTailCall() && !ToBeDeletedInsts.count(CI))
2286 if (!isa<Argument>(NewV))
2287 for (
auto &
Arg : RI->getFunction()->args())
2288 Arg.removeAttr(Attribute::Returned);
2292 <<
" instead of " << *OldV <<
"\n");
2296 CGModifiedFunctions.insert(
I->getFunction());
2297 if (!isa<PHINode>(
I) && !ToBeDeletedInsts.count(
I) &&
2301 if (isa<UndefValue>(NewV) && isa<CallBase>(
U->getUser())) {
2302 auto *CB = cast<CallBase>(
U->getUser());
2303 if (CB->isArgOperand(U)) {
2304 unsigned Idx = CB->getArgOperandNo(U);
2305 CB->removeParamAttr(
Idx, Attribute::NoUndef);
2306 Function *Fn = CB->getCalledFunction();
2311 if (isa<Constant>(NewV) && isa<BranchInst>(
U->getUser())) {
2313 if (isa<UndefValue>(NewV)) {
2314 ToBeChangedToUnreachableInsts.insert(UserI);
2321 for (
auto &It : ToBeChangedUses) {
2323 Value *NewV = It.second;
2324 ReplaceUse(U, NewV);
2328 for (
auto &It : ToBeChangedValues) {
2329 Value *OldV = It.first;
2330 auto [NewV,
Done] = It.second;
2332 for (
auto &U : OldV->
uses())
2333 if (
Done || !
U.getUser()->isDroppable())
2336 if (
auto *
I = dyn_cast<Instruction>(
U->getUser()))
2339 ReplaceUse(U, NewV);
2343 for (
const auto &V : InvokeWithDeadSuccessor)
2344 if (
InvokeInst *II = dyn_cast_or_null<InvokeInst>(V)) {
2346 "Cannot replace an invoke outside the current SCC!");
2347 bool UnwindBBIsDead = II->hasFnAttr(Attribute::NoUnwind);
2348 bool NormalBBIsDead = II->hasFnAttr(Attribute::NoReturn);
2349 bool Invoke2CallAllowed =
2351 assert((UnwindBBIsDead || NormalBBIsDead) &&
2352 "Invoke does not have dead successors!");
2354 BasicBlock *NormalDestBB = II->getNormalDest();
2355 if (UnwindBBIsDead) {
2357 if (Invoke2CallAllowed) {
2362 ToBeChangedToUnreachableInsts.insert(NormalNextIP);
2364 assert(NormalBBIsDead &&
"Broken invariant!");
2367 ToBeChangedToUnreachableInsts.insert(&NormalDestBB->
front());
2372 "Cannot replace a terminator outside the current SCC!");
2373 CGModifiedFunctions.insert(
I->getFunction());
2376 for (
const auto &V : ToBeChangedToUnreachableInsts)
2377 if (
Instruction *
I = dyn_cast_or_null<Instruction>(V)) {
2381 "Cannot replace an instruction outside the current SCC!");
2382 CGModifiedFunctions.insert(
I->getFunction());
2386 for (
const auto &V : ToBeDeletedInsts) {
2387 if (
Instruction *
I = dyn_cast_or_null<Instruction>(V)) {
2388 if (
auto *CB = dyn_cast<CallBase>(
I)) {
2390 "Cannot delete an instruction outside the current SCC!");
2391 if (!isa<IntrinsicInst>(CB))
2394 I->dropDroppableUses();
2395 CGModifiedFunctions.insert(
I->getFunction());
2396 if (!
I->getType()->isVoidTy())
2401 I->eraseFromParent();
2408 dbgs() <<
"[Attributor] DeadInsts size: " << DeadInsts.
size() <<
"\n";
2409 for (
auto &
I : DeadInsts)
2411 dbgs() <<
" - " << *
I <<
"\n";
2416 if (
unsigned NumDeadBlocks = ToBeDeletedBlocks.size()) {
2418 ToBeDeletedBBs.
reserve(NumDeadBlocks);
2421 "Cannot delete a block outside the current SCC!");
2422 CGModifiedFunctions.insert(BB->
getParent());
2424 if (ManifestAddedBlocks.contains(BB))
2434 identifyDeadInternalFunctions();
2437 ChangeStatus ManifestChange = rewriteFunctionSignatures(CGModifiedFunctions);
2439 for (
Function *Fn : CGModifiedFunctions)
2440 if (!ToBeDeletedFunctions.count(Fn) && Functions.count(Fn))
2443 for (
Function *Fn : ToBeDeletedFunctions) {
2444 if (!Functions.count(Fn))
2449 if (!ToBeChangedUses.empty())
2452 if (!ToBeChangedToUnreachableInsts.empty())
2455 if (!ToBeDeletedFunctions.empty())
2458 if (!ToBeDeletedBlocks.empty())
2461 if (!ToBeDeletedInsts.empty())
2464 if (!InvokeWithDeadSuccessor.empty())
2467 if (!DeadInsts.empty())
2470 NumFnDeleted += ToBeDeletedFunctions.size();
2472 LLVM_DEBUG(
dbgs() <<
"[Attributor] Deleted " << ToBeDeletedFunctions.size()
2473 <<
" functions after manifest.\n");
2475#ifdef EXPENSIVE_CHECKS
2477 if (ToBeDeletedFunctions.count(
F))
2483 return ManifestChange;
2493 Phase = AttributorPhase::UPDATE;
2506 Phase = AttributorPhase::MANIFEST;
2509 Phase = AttributorPhase::CLEANUP;
2515 return ManifestChange | CleanupChange;
2522 assert(Phase == AttributorPhase::UPDATE &&
2523 "We can update AA only in the update stage!");
2526 DependenceVector DV;
2527 DependenceStack.push_back(&DV);
2531 bool UsedAssumedInformation =
false;
2543 RerunCS = AA.
update(*
this);
2549 AAState.indicateOptimisticFixpoint();
2552 if (!AAState.isAtFixpoint())
2553 rememberDependences();
2557 DependenceVector *PoppedDV = DependenceStack.pop_back_val();
2559 assert(PoppedDV == &DV &&
"Inconsistent usage of the dependence stack!");
2565 assert(!
F.isDeclaration() &&
"Cannot create a wrapper around a declaration!");
2574 M.getFunctionList().insert(
F.getIterator(),
Wrapper);
2579 assert(
F.use_empty() &&
"Uses remained after wrapper was created!");
2584 F.setComdat(
nullptr);
2588 F.getAllMetadata(MDs);
2589 for (
auto MDIt : MDs)
2590 Wrapper->addMetadata(MDIt.first, *MDIt.second);
2591 Wrapper->setAttributes(
F.getAttributes());
2599 Args.push_back(&
Arg);
2608 NumFnShallowWrappersCreated++;
2612 if (
F.isDeclaration() ||
F.hasLocalLinkage() ||
2628 return InternalizedFns[&
F];
2646 F->getName() +
".internalized");
2649 for (
auto &
Arg :
F->args()) {
2650 auto ArgName =
Arg.getName();
2651 NewFArgIt->setName(ArgName);
2652 VMap[&
Arg] = &(*NewFArgIt++);
2667 F->getAllMetadata(MDs);
2668 for (
auto MDIt : MDs)
2672 M.getFunctionList().insert(
F->getIterator(), Copied);
2680 auto &InternalizedFn = FnMap[
F];
2681 auto IsNotInternalized = [&](
Use &U) ->
bool {
2682 if (
auto *CB = dyn_cast<CallBase>(U.getUser()))
2683 return !FnMap.
lookup(CB->getCaller());
2686 F->replaceUsesWithIf(InternalizedFn, IsNotInternalized);
2715 LLVM_DEBUG(
dbgs() <<
"[Attributor] Cannot rewrite var-args functions\n");
2726 dbgs() <<
"[Attributor] Cannot rewrite due to complex attribute\n");
2731 bool UsedAssumedInformation =
false;
2733 UsedAssumedInformation)) {
2734 LLVM_DEBUG(
dbgs() <<
"[Attributor] Cannot rewrite all call sites\n");
2739 if (
auto *CI = dyn_cast<CallInst>(&
I))
2740 return !CI->isMustTailCall();
2748 nullptr, {Instruction::Call},
2749 UsedAssumedInformation)) {
2750 LLVM_DEBUG(
dbgs() <<
"[Attributor] Cannot rewrite due to instructions\n");
2762 <<
Arg.getParent()->getName() <<
" with "
2763 << ReplacementTypes.
size() <<
" replacements\n");
2765 "Cannot register an invalid rewrite");
2769 ArgumentReplacementMap[Fn];
2775 std::unique_ptr<ArgumentReplacementInfo> &ARI = ARIs[
Arg.getArgNo()];
2776 if (ARI && ARI->getNumReplacementArgs() <= ReplacementTypes.
size()) {
2777 LLVM_DEBUG(
dbgs() <<
"[Attributor] Existing rewrite is preferred\n");
2786 <<
Arg.getParent()->getName() <<
" with "
2787 << ReplacementTypes.
size() <<
" replacements\n");
2791 std::move(CalleeRepairCB),
2792 std::move(ACSRepairCB)));
2813 for (
auto &It : ArgumentReplacementMap) {
2817 if (!Functions.count(OldFn) || ToBeDeletedFunctions.count(OldFn))
2830 if (
const std::unique_ptr<ArgumentReplacementInfo> &ARI =
2831 ARIs[
Arg.getArgNo()]) {
2832 NewArgumentTypes.
append(ARI->ReplacementTypes.begin(),
2833 ARI->ReplacementTypes.end());
2834 NewArgumentAttributes.
append(ARI->getNumReplacementArgs(),
2844 for (
auto *
I : NewArgumentTypes)
2845 if (
auto *VT = dyn_cast<llvm::VectorType>(
I))
2846 LargestVectorWidth =
2847 std::max(LargestVectorWidth,
2848 VT->getPrimitiveSizeInBits().getKnownMinValue());
2859 << *NewFnTy <<
"\n");
2864 Functions.insert(NewFn);
2878 NewArgumentAttributes));
2889 if (
auto *BA = dyn_cast<BlockAddress>(U))
2891 for (
auto *BA : BlockAddresses)
2906 for (
unsigned OldArgNum = 0; OldArgNum < ARIs.
size(); ++OldArgNum) {
2907 unsigned NewFirstArgNum = NewArgOperands.
size();
2908 (void)NewFirstArgNum;
2909 if (
const std::unique_ptr<ArgumentReplacementInfo> &ARI =
2911 if (ARI->ACSRepairCB)
2912 ARI->ACSRepairCB(*ARI, ACS, NewArgOperands);
2913 assert(ARI->getNumReplacementArgs() + NewFirstArgNum ==
2914 NewArgOperands.
size() &&
2915 "ACS repair callback did not provide as many operand as new "
2916 "types were registered!");
2918 NewArgOperandAttributes.
append(ARI->ReplacementTypes.size(),
2927 assert(NewArgOperands.
size() == NewArgOperandAttributes.
size() &&
2928 "Mismatch # argument operands vs. # argument operand attributes!");
2930 "Mismatch # argument operands vs. # function arguments!");
2937 if (
InvokeInst *II = dyn_cast<InvokeInst>(OldCB)) {
2940 NewArgOperands, OperandBundleDefs,
"", OldCB);
2944 NewCI->setTailCallKind(cast<CallInst>(OldCB)->getTailCallKind());
2949 NewCB->
copyMetadata(*OldCB, {LLVMContext::MD_prof, LLVMContext::MD_dbg});
2954 OldCallAttributeList.
getRetAttrs(), NewArgOperandAttributes));
2957 LargestVectorWidth);
2959 CallSitePairs.
push_back({OldCB, NewCB});
2964 bool UsedAssumedInformation =
false;
2966 true,
nullptr, UsedAssumedInformation,
2969 assert(
Success &&
"Assumed call site replacement to succeed!");
2974 for (
unsigned OldArgNum = 0; OldArgNum < ARIs.
size();
2975 ++OldArgNum, ++OldFnArgIt) {
2976 if (
const std::unique_ptr<ArgumentReplacementInfo> &ARI =
2978 if (ARI->CalleeRepairCB)
2979 ARI->CalleeRepairCB(*ARI, *NewFn, NewFnArgIt);
2980 if (ARI->ReplacementTypes.empty())
2983 NewFnArgIt += ARI->ReplacementTypes.size();
2985 NewFnArgIt->
takeName(&*OldFnArgIt);
2992 for (
auto &CallSitePair : CallSitePairs) {
2993 CallBase &OldCB = *CallSitePair.first;
2994 CallBase &NewCB = *CallSitePair.second;
2996 "Cannot handle call sites with different types!");
3008 if (ModifiedFns.
remove(OldFn))
3009 ModifiedFns.
insert(NewFn);
3017void InformationCache::initializeInformationCache(
const Function &CF,
3033 auto AddToAssumeUsesMap = [&](
const Value &
V) ->
void {
3035 if (
auto *
I = dyn_cast<Instruction>(&V))
3037 while (!Worklist.
empty()) {
3039 std::optional<short> &NumUses = AssumeUsesMap[
I];
3041 NumUses =
I->getNumUses();
3042 NumUses = *NumUses - 1;
3045 AssumeOnlyValues.insert(
I);
3046 for (
const Value *Op :
I->operands())
3047 if (
auto *OpI = dyn_cast<Instruction>(Op))
3053 bool IsInterestingOpcode =
false;
3060 switch (
I.getOpcode()) {
3063 "New call base instruction type needs to be known in the "
3066 case Instruction::Call:
3070 if (
auto *Assume = dyn_cast<AssumeInst>(&
I)) {
3071 AssumeOnlyValues.insert(Assume);
3073 AddToAssumeUsesMap(*Assume->getArgOperand(0));
3075 FI.ContainsMustTailCall =
true;
3077 getFunctionInfo(*Callee).CalledViaMustTail =
true;
3080 case Instruction::CallBr:
3081 case Instruction::Invoke:
3082 case Instruction::CleanupRet:
3083 case Instruction::CatchSwitch:
3084 case Instruction::AtomicRMW:
3085 case Instruction::AtomicCmpXchg:
3086 case Instruction::Br:
3087 case Instruction::Resume:
3088 case Instruction::Ret:
3089 case Instruction::Load:
3091 case Instruction::Store:
3093 case Instruction::Alloca:
3094 case Instruction::AddrSpaceCast:
3095 IsInterestingOpcode =
true;
3097 if (IsInterestingOpcode) {
3098 auto *&Insts = FI.OpcodeInstMap[
I.getOpcode()];
3103 if (
I.mayReadOrWriteMemory())
3104 FI.RWInsts.push_back(&
I);
3107 if (
F.hasFnAttribute(Attribute::AlwaysInline) &&
3109 InlineableFunctions.insert(&
F);
3116InformationCache::FunctionInfo::~FunctionInfo() {
3119 for (
auto &It : OpcodeInstMap)
3120 It.getSecond()->~InstructionVectorTy();
3131 if (DependenceStack.empty())
3135 DependenceStack.back()->push_back({&FromAA, &ToAA, DepClass});
3138void Attributor::rememberDependences() {
3139 assert(!DependenceStack.empty() &&
"No dependences to remember!");
3141 for (DepInfo &DI : *DependenceStack.back()) {
3144 "Expected required or optional dependence (1 bit)!");
3152 if (!VisitedFunctions.insert(&
F).second)
3154 if (
F.isDeclaration())
3160 InformationCache::FunctionInfo &FI = InfoCache.getFunctionInfo(
F);
3162 for (
const Use &U :
F.uses())
3163 if (
const auto *CB = dyn_cast<CallBase>(U.getUser()))
3164 if (CB->isCallee(&U) && CB->isMustTailCall())
3165 FI.CalledViaMustTail =
true;
3173 getOrCreateAAFor<AAIsDead>(FPos);
3176 getOrCreateAAFor<AAWillReturn>(FPos);
3179 getOrCreateAAFor<AAUndefinedBehavior>(FPos);
3182 getOrCreateAAFor<AANoUnwind>(FPos);
3185 getOrCreateAAFor<AANoSync>(FPos);
3188 getOrCreateAAFor<AANoFree>(FPos);
3191 getOrCreateAAFor<AANoReturn>(FPos);
3194 getOrCreateAAFor<AANoRecurse>(FPos);
3197 getOrCreateAAFor<AAMemoryBehavior>(FPos);
3200 getOrCreateAAFor<AAMemoryLocation>(FPos);
3203 getOrCreateAAFor<AAAssumptionInfo>(FPos);
3207 getOrCreateAAFor<AAHeapToStack>(FPos);
3210 Type *ReturnType =
F.getReturnType();
3211 if (!ReturnType->isVoidTy()) {
3214 getOrCreateAAFor<AAReturnedValues>(FPos);
3219 getOrCreateAAFor<AAIsDead>(RetPos);
3222 bool UsedAssumedInformation =
false;
3227 getOrCreateAAFor<AANoUndef>(RetPos);
3229 if (ReturnType->isPointerTy()) {
3232 getOrCreateAAFor<AAAlign>(RetPos);
3235 getOrCreateAAFor<AANonNull>(RetPos);
3238 getOrCreateAAFor<AANoAlias>(RetPos);
3242 getOrCreateAAFor<AADereferenceable>(RetPos);
3244 getOrCreateAAFor<AANoFPClass>(RetPos);
3254 bool UsedAssumedInformation =
false;
3259 getOrCreateAAFor<AAIsDead>(ArgPos);
3262 getOrCreateAAFor<AANoUndef>(ArgPos);
3264 if (
Arg.getType()->isPointerTy()) {
3266 getOrCreateAAFor<AANonNull>(ArgPos);
3269 getOrCreateAAFor<AANoAlias>(ArgPos);
3272 getOrCreateAAFor<AADereferenceable>(ArgPos);
3275 getOrCreateAAFor<AAAlign>(ArgPos);
3278 getOrCreateAAFor<AANoCapture>(ArgPos);
3282 getOrCreateAAFor<AAMemoryBehavior>(ArgPos);
3285 getOrCreateAAFor<AANoFree>(ArgPos);
3288 getOrCreateAAFor<AAPrivatizablePtr>(ArgPos);
3290 getOrCreateAAFor<AANoFPClass>(ArgPos);
3295 auto &CB = cast<CallBase>(
I);
3301 getOrCreateAAFor<AAIsDead>(CBInstPos);
3310 getOrCreateAAFor<AAAssumptionInfo>(CBFnPos);
3315 !
Callee->hasMetadata(LLVMContext::MD_callback))
3318 if (!
Callee->getReturnType()->isVoidTy() && !CB.use_empty()) {
3320 bool UsedAssumedInformation =
false;
3325 getOrCreateAAFor<AANoFPClass>(CBInstPos);
3328 for (
int I = 0,
E = CB.arg_size();
I <
E; ++
I) {
3333 getOrCreateAAFor<AAIsDead>(CBArgPos);
3338 bool UsedAssumedInformation =
false;
3343 getOrCreateAAFor<AANoUndef>(CBArgPos);
3345 Type *ArgTy = CB.getArgOperand(
I)->getType();
3349 getOrCreateAAFor<AANoFPClass>(CBArgPos);
3355 getOrCreateAAFor<AANonNull>(CBArgPos);
3358 getOrCreateAAFor<AANoCapture>(CBArgPos);
3361 getOrCreateAAFor<AANoAlias>(CBArgPos);
3364 getOrCreateAAFor<AADereferenceable>(CBArgPos);
3367 getOrCreateAAFor<AAAlign>(CBArgPos);
3371 getOrCreateAAFor<AAMemoryBehavior>(CBArgPos);
3374 getOrCreateAAFor<AANoFree>(CBArgPos);
3381 bool UsedAssumedInformation =
false;
3383 nullptr, OpcodeInstMap, CallSitePred,
nullptr,
nullptr,
3384 {(
unsigned)Instruction::Invoke, (
unsigned)Instruction::CallBr,
3386 UsedAssumedInformation);
3388 assert(
Success &&
"Expected the check call to be successful!");
3391 if (isa<LoadInst>(
I)) {
3392 getOrCreateAAFor<AAAlign>(
3398 auto &
SI = cast<StoreInst>(
I);
3407 nullptr, OpcodeInstMap, LoadStorePred,
nullptr,
nullptr,
3408 {(
unsigned)Instruction::Load, (
unsigned)Instruction::Store},
3409 UsedAssumedInformation);
3411 assert(
Success &&
"Expected the check call to be successful!");
3428 return OS <<
"fn_ret";
3430 return OS <<
"cs_ret";
3438 return OS <<
"cs_arg";
3460 return OS << static_cast<const AbstractState &>(S);
3474 OS <<
"set-state(< {";
3490 OS <<
"set-state(< {";
3495 if (
auto *
F = dyn_cast<Function>(It.first.getValue()))
3496 OS <<
"@" <<
F->getName() <<
"[" << int(It.second) <<
"], ";
3498 OS << *It.first.getValue() <<
"[" << int(It.second) <<
"], ";
3511 OS <<
"] for CtxI ";
3518 OS <<
"<<null inst>>";
3527 for (
const auto &DepAA :
Deps) {
3528 auto *AA = DepAA.getPointer();
3545 OS <<
" [ <unknown> ]";
3559 bool DeleteFns,
bool IsModulePass) {
3560 if (Functions.
empty())
3564 dbgs() <<
"[Attributor] Run on module with " << Functions.
size()
3573 AC.IsModulePass = IsModulePass;
3574 AC.DeleteFns = DeleteFns;
3580 if (!
A.isFunctionIPOAmendable(*
F))
3588 unsigned FunSize = Functions.
size();
3589 for (
unsigned u = 0; u < FunSize; u++) {
3591 if (!
F->isDeclaration() && !
F->isDefinitionExact() &&
F->getNumUses() &&
3594 assert(NewF &&
"Could not internalize function.");
3599 for (
const Use &U : NewF->
uses())
3600 if (
CallBase *CB = dyn_cast<CallBase>(U.getUser())) {
3601 auto *CallerF = CB->getCaller();
3609 if (
F->hasExactDefinition())
3610 NumFnWithExactDefinition++;
3612 NumFnWithoutExactDefinition++;
3617 if (
F->hasLocalLinkage()) {
3619 const auto *CB = dyn_cast<CallBase>(U.getUser());
3620 return CB && CB->isCallee(&U) &&
3621 Functions.count(const_cast<Function *>(CB->getCaller()));
3628 A.identifyDefaultAbstractAttributes(*
F);
3634 <<
" functions, result: " << Changed <<
".\n");
3641 static std::atomic<int> CallTimes;
3647 Prefix =
"dep_graph";
3648 std::string Filename =
3649 Prefix +
"_" + std::to_string(CallTimes.load()) +
".dot";
3651 outs() <<
"Dependency graph dump to " << Filename <<
".\n";
3664 cast<AbstractAttribute>(DepAA.getPointer())->printWithDeps(
outs());
3697 Functions.
insert(&
N.getFunction());
3699 if (Functions.
empty())
3754 std::string AAString;
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
amdgpu aa AMDGPU Address space based Alias Analysis Wrapper
amdgpu Simplify well known AMD library false FunctionCallee Callee
amdgpu Simplify well known AMD library false FunctionCallee Value * Arg
SmallPtrSet< MachineInstr *, 2 > Uses
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))
static cl::opt< bool > VerifyMaxFixpointIterations("attributor-max-iterations-verify", cl::Hidden, cl::desc("Verify that max-iterations is a tight bound for a fixpoint"), cl::init(false))
static bool checkForAllInstructionsImpl(Attributor *A, InformationCache::OpcodeInstMapTy &OpcodeInstMap, function_ref< bool(Instruction &)> Pred, const AbstractAttribute *QueryingAA, const AAIsDead *LivenessAA, const ArrayRef< unsigned > &Opcodes, bool &UsedAssumedInformation, bool CheckBBLivenessOnly=false, bool CheckPotentiallyDead=false)
#define VERBOSE_DEBUG_TYPE
static cl::opt< bool > EnableHeapToStack("enable-heap-to-stack-conversion", cl::init(true), cl::Hidden)
static bool runAttributorOnFunctions(InformationCache &InfoCache, SetVector< Function * > &Functions, AnalysisGetter &AG, CallGraphUpdater &CGUpdater, bool DeleteFns, bool IsModulePass)
}
static bool isPotentiallyReachable(Attributor &A, const Instruction &FromI, const Instruction *ToI, const Function &ToFn, const AbstractAttribute &QueryingAA, const AA::InstExclusionSetTy *ExclusionSet, std::function< bool(const Function &F)> GoBackwardsCB)
static bool getPotentialCopiesOfMemoryValue(Attributor &A, Ty &I, SmallSetVector< Value *, 4 > &PotentialCopies, SmallSetVector< Instruction *, 4 > &PotentialValueOrigins, const AbstractAttribute &QueryingAA, bool &UsedAssumedInformation, bool OnlyExact)
static cl::list< std::string > FunctionSeedAllowList("attributor-function-seed-allow-list", cl::Hidden, cl::desc("Comma seperated list of function names that are " "allowed to be seeded."), cl::CommaSeparated)
static 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< bool > SimplifyAllLoads("attributor-simplify-all-loads", cl::Hidden, cl::desc("Try to simplify all loads."), cl::init(true))
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 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 bool addIfNotExistent(LLVMContext &Ctx, const Attribute &Attr, AttributeList &Attrs, int AttrIdx, bool ForceReplace=false)
Return true if the information provided by Attr was added to the attribute list Attrs.
static cl::opt< unsigned > SetFixpointIterations("attributor-max-iterations", cl::Hidden, cl::desc("Maximal number of fixpoint iterations."), cl::init(32))
static cl::list< std::string > SeedAllowList("attributor-seed-allow-list", cl::Hidden, cl::desc("Comma seperated list of attribute names that are " "allowed to be seeded."), cl::CommaSeparated)
static cl::opt< bool > EnableCallSiteSpecific("attributor-enable-call-site-specific-deduction", cl::Hidden, cl::desc("Allow the Attributor to do call site specific analysis"), cl::init(false))
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file provides interfaces used to build and manipulate a call graph, which is a very useful tool ...
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
This file provides an implementation of debug counters.
#define DEBUG_COUNTER(VARNAME, COUNTERNAME, DESC)
#define DEBUG_WITH_TYPE(TYPE, X)
DEBUG_WITH_TYPE macro - This macro should be used by passes to emit debug information.
static Function * getFunction(Constant *C)
static bool isMustTailCall(Value *V)
static const Function * getCalledFunction(const Value *V, bool &IsNoBuiltin)
print must be executed print the must be executed context for all instructions
Contains a collection of routines for determining if a given instruction is guaranteed to execute if ...
FunctionAnalysisManager FAM
This file defines the PointerIntPair class.
static StringRef getName(Value *V)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static bool isSimple(Instruction *I)
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
A manager for alias analyses.
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.
Value * getCalledOperand() const
Return the pointer to function that is being called.
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...
A container for analyses that lazily runs them and caches their results.
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.
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 hasAttributeAtIndex(unsigned Index, Attribute::AttrKind Kind) const
Return true if the attribute exists at the given index.
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.
Attribute getAttributeAtIndex(unsigned Index, Attribute::AttrKind Kind) const
Return the attribute object that exists at the given index.
AttributeSet getAttributes(unsigned Index) const
The attributes for the specified index are returned.
AttributeSet getParamAttrs(unsigned ArgNo) const
The attributes for the argument or parameter at the given index are returned.
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).
AttrKind
This enumeration lists the attributes that can be associated with parameters, function results,...
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.
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.
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
CallingConv::ID getCallingConv() const
bool isMustTailCall() const
Tests if this call site must be tail call optimized.
void setAttributes(AttributeList A)
Set the parameter attributes for this call.
AttributeList getAttributes() const
Return the parameter attributes for this call.
Function * getCaller()
Helper to get the caller (the parent function).
Wrapper to unify "old style" CallGraph and "new style" LazyCallGraph.
void removeFunction(Function &Fn)
Remove Fn from the call graph.
void removeCallSite(CallBase &CS)
Remove the call site CS from the call graph.
void replaceFunctionWith(Function &OldFn, Function &NewFn)
Replace OldFn in the call graph (and SCC) with NewFn.
void reanalyzeFunction(Function &Fn)
After an CGSCC pass changes a function in ways that affect the call graph, this method can be called ...
bool replaceCallSite(CallBase &OldCS, CallBase &NewCS)
Replace OldCS with the new call site NewCS.
void initialize(CallGraph &CG, CallGraphSCC &SCC)
Initializers for usage outside of a CGSCC pass, inside a CGSCC pass in the old and new pass manager (...
This class represents a function call, abstracting a target machine's calling convention.
void setTailCall(bool IsTc=true)
static CallInst * Create(FunctionType *Ty, Value *F, const Twine &NameStr="", Instruction *InsertBefore=nullptr)
A constant value that is initialized with an expression using other constant values.
static Constant * getPointerCast(Constant *C, Type *Ty)
Create a BitCast, AddrSpaceCast, or a PtrToInt cast constant expression.
static Constant * getFPTrunc(Constant *C, Type *Ty, bool OnlyIfReduced=false)
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.
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...
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
void removeParamAttr(unsigned ArgNo, Attribute::AttrKind Kind)
removes the attribute from the list of attributes.
FunctionType * getFunctionType() const
Returns the FunctionType for me.
iterator_range< arg_iterator > args()
DISubprogram * getSubprogram() const
Get the attached subprogram.
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.
Argument * getArg(unsigned i) const
bool isVarArg() const
isVarArg - Return true if this function takes a variable number of arguments.
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
void copyAttributesFrom(const Function *Src)
copyAttributesFrom - copy all additional attributes (those not needed to create a Function) from the ...
bool hasMetadata() const
Return true if this value has any metadata attached to it.
void addMetadata(unsigned KindID, MDNode &MD)
Add a metadata attachment.
bool isDeclaration() const
Return true if the primary definition of this global value is outside of the current translation unit...
LinkageTypes getLinkage() const
bool hasLocalLinkage() const
void setLinkage(LinkageTypes LT)
unsigned getAddressSpace() const
Module * getParent()
Get the module that this global value is contained inside of...
void setDSOLocal(bool Local)
PointerType * getType() const
Global values are always pointers.
@ DefaultVisibility
The GV is visible.
void setVisibility(VisibilityTypes V)
static bool isInterposableLinkage(LinkageTypes Linkage)
Whether the definition of this global may be replaced by something non-equivalent at link time.
@ PrivateLinkage
Like Internal, but omit from symbol table.
@ InternalLinkage
Rename collisions when linking (static functions).
An analysis over an "outer" IR unit that provides access to an analysis manager over an "inner" IR un...
const BasicBlock * getParent() const
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',...
SymbolTableList< Instruction >::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
void copyMetadata(const Instruction &SrcInst, ArrayRef< unsigned > WL=ArrayRef< unsigned >())
Copy metadata from SrcInst to this instruction.
static InvokeInst * Create(FunctionType *Ty, Value *Func, BasicBlock *IfNormal, BasicBlock *IfException, ArrayRef< Value * > Args, const Twine &NameStr, Instruction *InsertBefore=nullptr)
This is an important class for using LLVM in a threaded context.
A node in the call graph.
An SCC of the call graph.
A lazily constructed view of the call graph of a module.
An instruction for reading from memory.
This is the common base class for memset/memcpy/memmove.
This class wraps the llvm.memcpy/memmove intrinsics.
static 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 preserve()
Mark an analysis as preserved.
Return a value (possibly void), from a function.
static ReturnInst * Create(LLVMContext &C, Value *retVal=nullptr, Instruction *InsertBefore=nullptr)
A vector that has set insertion semantics.
size_type size() const
Determine the number of elements in the SetVector.
size_type count(const key_type &key) const
Count the number of elements of a given key in the SetVector.
bool remove(const value_type &X)
Remove an item from the set vector.
ArrayRef< T > getArrayRef() const
bool insert(const value_type &X)
Insert a new element into the SetVector.
const T & front() const
Return the first element of the SetVector.
void clear()
Completely clear the SetVector.
bool empty() const
Determine if the SetVector is empty or not.
const T & back() const
Return the last element of the SetVector.
typename vector_type::const_iterator iterator
iterator begin()
Get an iterator to the beginning of 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 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.
An efficient, type-erasing, non-owning reference to a callable.
self_iterator getIterator()
iterator insert(iterator where, pointer New)
A raw_ostream that writes to a file descriptor.
This class implements an extremely fast bulk output stream that can only output to a stream.
A raw_ostream that writes to an std::string.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
bool isAssumedReadNone(Attributor &A, const IRPosition &IRP, const AbstractAttribute &QueryingAA, bool &IsKnown)
Return true if IRP is readnone.
bool isAssumedReadOnly(Attributor &A, const IRPosition &IRP, const AbstractAttribute &QueryingAA, bool &IsKnown)
Return true if IRP is readonly.
std::optional< Value * > combineOptionalValuesInAAValueLatice(const std::optional< Value * > &A, const std::optional< Value * > &B, Type *Ty)
Return the combination of A and B such that the result is a possible value of both.
bool isValidAtPosition(const ValueAndContext &VAC, InformationCache &InfoCache)
Return true if the value of VAC is a valid at the position of VAC, that is a constant,...
bool isAssumedThreadLocalObject(Attributor &A, Value &Obj, const AbstractAttribute &QueryingAA)
Return true if Obj is assumed to be a thread local object.
Constant * getInitialValueForObj(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.
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.
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="")
const Value * getPointerOperand(const Value *V)
A helper function that returns the pointer operand of a load, store or GEP instruction.
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.
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...
Constant * ConstantFoldLoadFromUniformValue(Constant *C, Type *Ty)
If C is a uniform value where all bits are the same (either all zero, all ones, all undef or all pois...
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.
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)
@ 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)
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.
An abstract interface to determine reachability of point A to B.
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).
An abstract interface for all memory location attributes (readnone/argmemonly/inaccessiblememonly/ina...
An abstract interface for all nocapture attributes.
bool isAssumedNoSync() const
Returns true if "nosync" is assumed.
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.
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.
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.
const Instruction * getCtxI() const
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
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() const =0
This function should return the "summarized" assumed state as string.
void print(raw_ostream &OS) const override
Helper functions, for debug purposes only.
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.
Analysis::Result * getAnalysis(const Function &F)
PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG, CGSCCUpdateResult &UR)
void populateAll() const
Force populate the entire call graph.
Configuration for the Attributor.
std::optional< unsigned > MaxFixpointIterations
Maximum number of iterations to run until fixpoint.
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.
CallGraphUpdater & CGUpdater
Helper to update an underlying call graph and to delete functions.
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 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.
bool checkForAllInstructions(function_ref< bool(Instruction &)> Pred, const Function *Fn, const AbstractAttribute &QueryingAA, const ArrayRef< unsigned > &Opcodes, bool &UsedAssumedInformation, bool CheckBBLivenessOnly=false, bool CheckPotentiallyDead=false)
Check Pred on all instructions in Fn with an opcode present in Opcodes.
static bool isInternalizable(Function &F)
Returns true if the function F can be internalized.
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.
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.
bool checkForAllReturnedValuesAndReturnInsts(function_ref< bool(Value &, const SmallSetVector< ReturnInst *, 4 > &)> Pred, const AbstractAttribute &QueryingAA)
Check Pred on all values potentially returned by F.
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 checkForAllReadWriteInstructions(function_ref< bool(Instruction &)> Pred, AbstractAttribute &QueryingAA, bool &UsedAssumedInformation)
Check Pred on all Read/Write instructions.
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,...
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 checkForAllReturnedValues(function_ref< bool(Value &)> Pred, const AbstractAttribute &QueryingAA)
Check Pred on all values potentially returned by the function associated with QueryingAA.
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.
void registerForUpdate(AbstractAttribute &AA)
Allows a query AA to request an update if a new query was received.
bool getAssumedSimplifiedValues(const IRPosition &IRP, const AbstractAttribute *AA, SmallVectorImpl< AA::ValueAndContext > &Values, AA::ValueScope S, bool &UsedAssumedInformation)
Try to simplify IRP and in the scope S.
void identifyDefaultAbstractAttributes(Function &F)
Determine opportunities to derive 'default' attributes in F and create abstract attribute objects for...
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 isKnown(base_t BitsEncoding) 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 ...
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)
static ChangeStatus manifestAttrs(Attributor &A, const IRPosition &IRP, const ArrayRef< Attribute > &DeducedAttrs, bool ForceReplace=false)
Helper to describe and deal with positions in the LLVM-IR.
Function * getAssociatedFunction() const
Return the associated function, if any.
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)
Crea