52#ifdef EXPENSIVE_CHECKS
62#define DEBUG_TYPE "attributor"
63#define VERBOSE_DEBUG_TYPE DEBUG_TYPE "-verbose"
66 "Determine what attributes are manifested in the IR");
68STATISTIC(NumFnDeleted,
"Number of function deleted");
70 "Number of functions with exact definitions");
72 "Number of functions without exact definitions");
73STATISTIC(NumFnShallowWrappersCreated,
"Number of shallow wrappers created");
75 "Number of abstract attributes timed out before fixpoint");
77 "Number of abstract attributes in a valid fixpoint state");
79 "Number of abstract attributes manifested in IR");
91 cl::desc(
"Maximal number of fixpoint iterations."),
95 "attributor-max-initialization-chain-length",
cl::Hidden,
97 "Maximal number of chained initializations (to avoid stack overflows)"),
102 "attributor-max-iterations-verify",
cl::Hidden,
103 cl::desc(
"Verify that max-iterations is a tight bound for a fixpoint"),
108 cl::desc(
"Annotate call sites of function declarations."),
cl::init(
false));
115 cl::desc(
"Allow the Attributor to create shallow "
116 "wrappers for non-exact definitions."),
121 cl::desc(
"Allow the Attributor to use IP information "
122 "derived from non-exact functions via cloning"),
129 cl::desc(
"Comma seperated list of attribute names that are "
130 "allowed to be seeded."),
134 "attributor-function-seed-allow-list",
cl::Hidden,
135 cl::desc(
"Comma seperated list of function names that are "
136 "allowed to be seeded."),
142 cl::desc(
"Dump the dependency graph to dot files."),
146 "attributor-depgraph-dot-filename-prefix",
cl::Hidden,
147 cl::desc(
"The prefix used for the CallGraph dot file names."));
150 cl::desc(
"View the dependency graph."),
154 cl::desc(
"Print attribute dependencies"),
158 "attributor-enable-call-site-specific-deduction",
cl::Hidden,
159 cl::desc(
"Allow the Attributor to do call site specific analysis"),
164 cl::desc(
"Print Attributor's internal call graph"),
169 cl::desc(
"Try to simplify all loads."),
176 return L == ChangeStatus::CHANGED ? L : R;
183 return L == ChangeStatus::UNCHANGED ? L : R;
194 if (
const auto *CB = dyn_cast<CallBase>(&
I)) {
195 if (CB->hasFnAttr(Attribute::NoSync))
199 if (!CB->isConvergent() && !CB->mayReadOrWriteMemory())
205 const auto &NoSyncAA =
A.getAAFor<
AANoSync>(
210 if (!
I.mayReadOrWriteMemory())
217 const Value &V,
bool ForAnalysisOnly) {
219 if (!ForAnalysisOnly)
230 if (isa<AllocaInst>(Obj))
234 auto *GV = dyn_cast<GlobalVariable>(&Obj);
237 if (!GV->hasLocalLinkage() && !(GV->isConstant() && GV->hasInitializer()))
239 if (!GV->hasInitializer())
251 if (isa<Constant>(V))
253 if (
auto *
I = dyn_cast<Instruction>(&V))
254 return I->getFunction() == Scope;
255 if (
auto *
A = dyn_cast<Argument>(&V))
256 return A->getParent() == Scope;
268 if (
auto *
A = dyn_cast<Argument>(VAC.
getValue()))
269 return A->getParent() == Scope;
270 if (
auto *
I = dyn_cast<Instruction>(VAC.
getValue())) {
271 if (
I->getFunction() == Scope) {
275 return DT->dominates(
I, CtxI);
277 if (CtxI &&
I->getParent() == CtxI->
getParent())
280 [&](
const Instruction &AfterI) { return &AfterI == CtxI; });
289 if (isa<PoisonValue>(V))
291 if (isa<UndefValue>(V))
293 if (
auto *
C = dyn_cast<Constant>(&V)) {
294 if (
C->isNullValue())
308std::optional<Value *>
310 const std::optional<Value *> &
B,
323 Ty = (*A)->getType();
324 if (isa_and_nonnull<UndefValue>(*
A))
326 if (isa<UndefValue>(*
B))
333template <
bool IsLoad,
typename Ty>
339 LLVM_DEBUG(
dbgs() <<
"Trying to determine the potential copies of " <<
I
340 <<
" (only exact: " << OnlyExact <<
")\n";);
351 A.getInfoCache().getTargetLibraryInfoForFunction(*
I.getFunction());
353 auto Pred = [&](
Value &Obj) {
355 if (isa<UndefValue>(&Obj))
357 if (isa<ConstantPointerNull>(&Obj)) {
361 Ptr.getType()->getPointerAddressSpace()) &&
362 A.getAssumedSimplified(
Ptr, QueryingAA, UsedAssumedInformation,
366 dbgs() <<
"Underlying object is a valid nullptr, giving up.\n";);
370 if (!isa<AllocaInst>(&Obj) && !isa<GlobalVariable>(&Obj) &&
372 LLVM_DEBUG(
dbgs() <<
"Underlying object is not supported yet: " << Obj
376 if (
auto *GV = dyn_cast<GlobalVariable>(&Obj))
377 if (!GV->hasLocalLinkage() &&
378 !(GV->isConstant() && GV->hasInitializer())) {
380 "linkage, not supported yet: "
385 bool NullOnly =
true;
386 bool NullRequired =
false;
387 auto CheckForNullOnlyAndUndef = [&](std::optional<Value *> V,
389 if (!V || *V ==
nullptr)
391 else if (isa<UndefValue>(*V))
393 else if (isa<Constant>(*V) && cast<Constant>(*V)->isNullValue())
394 NullRequired = !IsExact;
404 CheckForNullOnlyAndUndef(Acc.
getContent(), IsExact);
405 if (OnlyExact && !IsExact && !NullOnly &&
411 if (NullRequired && !NullOnly) {
412 LLVM_DEBUG(
dbgs() <<
"Required all `null` accesses due to non exact "
413 "one, however found non-null one: "
418 assert(isa<LoadInst>(
I) &&
"Expected load or store instruction only!");
426 LLVM_DEBUG(
dbgs() <<
"Underlying object written through a non-store "
427 "instruction not supported yet: "
434 assert(isa<StoreInst>(
I) &&
"Expected load or store instruction only!");
436 if (!LI && OnlyExact) {
438 "instruction not supported yet: "
449 bool HasBeenWrittenTo =
false;
454 if (!PI.forallInterferingAccesses(
A, QueryingAA,
I, CheckAccess,
455 HasBeenWrittenTo, Range)) {
458 <<
"Failed to verify all interfering accesses for underlying object: "
463 if (IsLoad && !HasBeenWrittenTo && !Range.isUnassigned()) {
465 Value *InitialValue =
468 LLVM_DEBUG(
dbgs() <<
"Could not determine required initial value of "
469 "underlying object, abort!\n");
472 CheckForNullOnlyAndUndef(InitialValue,
true);
473 if (NullRequired && !NullOnly) {
474 LLVM_DEBUG(
dbgs() <<
"Non exact access but initial value that is not "
475 "null or undef, abort!\n");
490 if (!AAUO.forallUnderlyingObjects(Pred)) {
492 dbgs() <<
"Underlying objects stored into could not be determined\n";);
499 for (
const auto *PI : PIs) {
500 if (!PI->getState().isAtFixpoint())
501 UsedAssumedInformation =
true;
502 A.recordDependence(*PI, QueryingAA, DepClassTy::OPTIONAL);
505 PotentialValueOrigins.
insert(NewCopyOrigins.
begin(), NewCopyOrigins.
end());
516 A, LI, PotentialValues, PotentialValueOrigins, QueryingAA,
517 UsedAssumedInformation, OnlyExact);
526 A,
SI, PotentialCopies, PotentialValueOrigins, QueryingAA,
527 UsedAssumedInformation, OnlyExact);
532 bool RequireReadNone,
bool &IsKnown) {
536 const auto &MemLocAA =
538 if (MemLocAA.isAssumedReadNone()) {
539 IsKnown = MemLocAA.isKnownReadNone();
541 A.recordDependence(MemLocAA, QueryingAA, DepClassTy::OPTIONAL);
546 const auto &MemBehaviorAA =
548 if (MemBehaviorAA.isAssumedReadNone() ||
549 (!RequireReadNone && MemBehaviorAA.isAssumedReadOnly())) {
550 IsKnown = RequireReadNone ? MemBehaviorAA.isKnownReadNone()
551 : MemBehaviorAA.isKnownReadOnly();
553 A.recordDependence(MemBehaviorAA, QueryingAA, DepClassTy::OPTIONAL);
576 std::function<
bool(
const Function &
F)> GoBackwardsCB) {
578 dbgs() <<
"[AA] isPotentiallyReachable @" << ToFn.
getName() <<
" from "
579 << FromI <<
" [GBCB: " <<
bool(GoBackwardsCB) <<
"][#ExS: "
580 << (ExclusionSet ? std::to_string(ExclusionSet->
size()) :
"none")
583 for (
auto *ES : *ExclusionSet)
584 dbgs() << *ES <<
"\n";
592 if (!GoBackwardsCB && !ExclusionSet) {
594 <<
" is not checked backwards and does not have an "
595 "exclusion set, abort\n");
603 while (!Worklist.
empty()) {
605 if (!Visited.
insert(CurFromI).second)
609 if (FromFn == &ToFn) {
612 LLVM_DEBUG(
dbgs() <<
"[AA] check " << *ToI <<
" from " << *CurFromI
613 <<
" intraprocedurally\n");
617 ReachabilityAA.isAssumedReachable(
A, *CurFromI, *ToI, ExclusionSet);
619 << (Result ?
"can potentially " :
"cannot ") <<
"reach "
620 << *ToI <<
" [Intra]\n");
631 ToReachabilityAA.isAssumedReachable(
A, EntryI, *ToI, ExclusionSet);
633 <<
" " << (Result ?
"can potentially " :
"cannot ")
634 <<
"reach @" << *ToI <<
" [ToFn]\n");
642 Result = FnReachabilityAA.instructionCanReach(
A, *CurFromI, ToFn,
645 <<
" " << (Result ?
"can potentially " :
"cannot ")
646 <<
"reach @" << ToFn.
getName() <<
" [FromFn]\n");
656 ReachabilityAA.isAssumedReachable(
A, *CurFromI, Ret, ExclusionSet);
658 << (Result ?
"can potentially " :
"cannot ") <<
"reach "
659 << Ret <<
" [Intra]\n");
664 bool UsedAssumedInformation =
false;
665 if (
A.checkForAllInstructions(ReturnInstCB, FromFn, QueryingAA,
666 {Instruction::Ret}, UsedAssumedInformation)) {
671 if (!GoBackwardsCB) {
673 <<
" is not checked backwards, abort\n");
679 if (!GoBackwardsCB(*FromFn))
686 CallBase *CB = ACS.getInstruction();
690 if (isa<InvokeInst>(CB))
698 Result = !
A.checkForAllCallSites(CheckCallSite, *FromFn,
700 &QueryingAA, UsedAssumedInformation);
702 LLVM_DEBUG(
dbgs() <<
"[AA] stepping back to call sites from " << *CurFromI
703 <<
" in @" << FromFn->
getName()
704 <<
" failed, give up\n");
708 LLVM_DEBUG(
dbgs() <<
"[AA] stepped back to call sites from " << *CurFromI
709 <<
" in @" << FromFn->
getName()
710 <<
" worklist size is: " << Worklist.
size() <<
"\n");
719 std::function<
bool(
const Function &
F)> GoBackwardsCB) {
721 return ::isPotentiallyReachable(
A, FromI, &ToI, *ToFn, QueryingAA,
722 ExclusionSet, GoBackwardsCB);
729 std::function<
bool(
const Function &
F)> GoBackwardsCB) {
730 return ::isPotentiallyReachable(
A, FromI,
nullptr, ToFn, QueryingAA,
731 ExclusionSet, GoBackwardsCB);
736 if (isa<UndefValue>(Obj))
738 if (isa<AllocaInst>(Obj)) {
742 dbgs() <<
"[AA] Object '" << Obj
743 <<
"' is thread local; stack objects are thread local.\n");
749 << (NoCaptureAA.isAssumedNoCapture() ?
"" :
"not")
751 << (NoCaptureAA.isAssumedNoCapture() ?
"non-" :
"")
752 <<
"captured stack object.\n");
753 return NoCaptureAA.isAssumedNoCapture();
755 if (
auto *GV = dyn_cast<GlobalVariable>(&Obj)) {
756 if (GV->isConstant()) {
758 <<
"' is thread local; constant global\n");
761 if (GV->isThreadLocal()) {
763 <<
"' is thread local; thread local global\n");
768 if (
A.getInfoCache().targetIsGPU()) {
770 (
int)AA::GPUAddressSpace::Local) {
772 <<
"' is thread local; GPU local memory\n");
776 (
int)AA::GPUAddressSpace::Constant) {
778 <<
"' is thread local; GPU constant memory\n");
783 LLVM_DEBUG(
dbgs() <<
"[AA] Object '" << Obj <<
"' is not thread local\n");
789 if (!
I.mayHaveSideEffects() && !
I.mayReadFromMemory())
794 auto AddLocationPtr = [&](std::optional<MemoryLocation> Loc) {
795 if (!Loc || !Loc->Ptr) {
797 dbgs() <<
"[AA] Access to unknown location; -> requires barriers\n");
826 auto Pred = [&](
Value &Obj) {
830 <<
"'; -> requires barrier\n");
836 if (!UnderlyingObjsAA.forallUnderlyingObjects(Pred))
855 bool ForceReplace =
false) {
859 if (Attrs.hasAttributeAtIndex(AttrIdx, Kind))
863 Attrs = Attrs.addAttributeAtIndex(Ctx, AttrIdx, Attr);
868 if (Attrs.hasAttributeAtIndex(AttrIdx, Kind))
872 Attrs = Attrs.addAttributeAtIndex(Ctx, AttrIdx, Attr);
877 if (Attrs.hasAttributeAtIndex(AttrIdx, Kind))
881 Attrs = Attrs.removeAttributeAtIndex(Ctx, AttrIdx, Kind);
882 Attrs = Attrs.addAttributeAtIndex(Ctx, AttrIdx, Attr);
903 std::optional<Argument *> CBCandidateArg;
907 for (
const Use *U : CallbackUses) {
921 "ACS mapped into var-args arguments!");
922 if (CBCandidateArg) {
923 CBCandidateArg =
nullptr;
931 if (CBCandidateArg && *CBCandidateArg)
932 return *CBCandidateArg;
938 return Callee->getArg(ArgNo);
952 LLVM_DEBUG(
dbgs() <<
"[Attributor] Update " << HasChanged <<
" " << *
this
988 for (
const Attribute &Attr : DeducedAttrs) {
1022 IRPositions.emplace_back(IRP);
1026 auto CanIgnoreOperandBundles = [](
const CallBase &CB) {
1027 return (isa<IntrinsicInst>(CB) &&
1028 cast<IntrinsicInst>(CB).getIntrinsicID() == Intrinsic ::assume);
1042 assert(CB &&
"Expected call site!");
1045 if (!CB->hasOperandBundles() || CanIgnoreOperandBundles(*CB))
1050 assert(CB &&
"Expected call site!");
1053 if (!CB->hasOperandBundles() || CanIgnoreOperandBundles(*CB)) {
1058 if (
Arg.hasReturnedAttr()) {
1059 IRPositions.emplace_back(
1061 IRPositions.emplace_back(
1070 assert(CB &&
"Expected call site!");
1073 if (!CB->hasOperandBundles() || CanIgnoreOperandBundles(*CB)) {
1088 bool IgnoreSubsumingPositions,
Attributor *
A)
const {
1092 if (EquivIRP.getAttrsFromIRAttr(AK, Attrs))
1097 if (IgnoreSubsumingPositions)
1102 if (getAttrsFromAssumes(AK, Attrs, *
A))
1109 bool IgnoreSubsumingPositions,
Attributor *
A)
const {
1112 EquivIRP.getAttrsFromIRAttr(AK, Attrs);
1116 if (IgnoreSubsumingPositions)
1121 getAttrsFromAssumes(AK, Attrs, *
A);
1148 A.getInfoCache().getKnowledgeMap().lookup({&AssociatedValue, AK});
1156 unsigned AttrsSize =
Attrs.size();
1158 A.getInfoCache().getMustBeExecutedContextExplorer();
1160 for (
const auto &It : A2K)
1163 return AttrsSize !=
Attrs.size();
1166void IRPosition::verify() {
1167#ifdef EXPENSIVE_CHECKS
1170 assert((CBContext ==
nullptr) &&
1171 "Invalid position must not have CallBaseContext!");
1173 "Expected a nullptr for an invalid position!");
1177 "Expected specialized kind for argument values!");
1180 assert(isa<Function>(getAsValuePtr()) &&
1181 "Expected function for a 'returned' position!");
1183 "Associated value mismatch!");
1186 assert((CBContext ==
nullptr) &&
1187 "'call site returned' position must not have CallBaseContext!");
1188 assert((isa<CallBase>(getAsValuePtr())) &&
1189 "Expected call base for 'call site returned' position!");
1191 "Associated value mismatch!");
1194 assert((CBContext ==
nullptr) &&
1195 "'call site function' position must not have CallBaseContext!");
1196 assert((isa<CallBase>(getAsValuePtr())) &&
1197 "Expected call base for 'call site function' position!");
1199 "Associated value mismatch!");
1202 assert(isa<Function>(getAsValuePtr()) &&
1203 "Expected function for a 'function' position!");
1205 "Associated value mismatch!");
1208 assert(isa<Argument>(getAsValuePtr()) &&
1209 "Expected argument for a 'argument' position!");
1211 "Associated value mismatch!");
1214 assert((CBContext ==
nullptr) &&
1215 "'call site argument' position must not have CallBaseContext!");
1216 Use *U = getAsUsePtr();
1218 assert(U &&
"Expected use for a 'call site argument' position!");
1219 assert(isa<CallBase>(U->getUser()) &&
1220 "Expected call base user for a 'call site argument' position!");
1221 assert(cast<CallBase>(U->getUser())->isArgOperand(U) &&
1222 "Expected call base argument operand for a 'call site argument' "
1224 assert(cast<CallBase>(U->getUser())->getArgOperandNo(U) ==
1226 "Argument number mismatch!");
1234std::optional<Constant *>
1237 bool &UsedAssumedInformation) {
1241 for (
auto &CB : SimplificationCallbacks.lookup(IRP)) {
1242 std::optional<Value *> SimplifiedV = CB(IRP, &AA, UsedAssumedInformation);
1244 return std::nullopt;
1245 if (isa_and_nonnull<Constant>(*SimplifiedV))
1246 return cast<Constant>(*SimplifiedV);
1254 UsedAssumedInformation)) {
1256 return std::nullopt;
1257 if (
auto *
C = dyn_cast_or_null<Constant>(
1270 for (
auto &CB : SimplificationCallbacks.lookup(IRP))
1271 return CB(IRP, AA, UsedAssumedInformation);
1277 return std::nullopt;
1290 bool &UsedAssumedInformation) {
1294 const auto &SimplificationCBs = SimplificationCallbacks.lookup(IRP);
1295 for (
const auto &CB : SimplificationCBs) {
1296 std::optional<Value *> CBResult = CB(IRP, AA, UsedAssumedInformation);
1297 if (!CBResult.has_value())
1299 Value *V = *CBResult;
1308 if (!SimplificationCBs.empty())
1312 const auto &PotentialValuesAA =
1314 if (!PotentialValuesAA.getAssumedSimplifiedValues(*
this, Values, S))
1316 UsedAssumedInformation |= !PotentialValuesAA.isAtFixpoint();
1322 bool &UsedAssumedInformation) {
1325 if (*V ==
nullptr || isa<Constant>(*V))
1327 if (
auto *
Arg = dyn_cast<Argument>(*V))
1329 if (!
Arg->hasPointeeInMemoryValueAttr())
1339 for (
auto &It : AAMap) {
1347 bool &UsedAssumedInformation,
1348 bool CheckBBLivenessOnly,
DepClassTy DepClass) {
1352 return isAssumedDead(IRP, &AA, FnLivenessAA, UsedAssumedInformation,
1353 CheckBBLivenessOnly, DepClass);
1359 bool &UsedAssumedInformation,
1360 bool CheckBBLivenessOnly,
DepClassTy DepClass) {
1364 UsedAssumedInformation, CheckBBLivenessOnly, DepClass);
1366 if (
auto *CB = dyn_cast<CallBase>(UserI)) {
1369 if (CB->isArgOperand(&U)) {
1373 UsedAssumedInformation, CheckBBLivenessOnly,
1376 }
else if (
ReturnInst *RI = dyn_cast<ReturnInst>(UserI)) {
1379 UsedAssumedInformation, CheckBBLivenessOnly, DepClass);
1380 }
else if (
PHINode *
PHI = dyn_cast<PHINode>(UserI)) {
1383 UsedAssumedInformation, CheckBBLivenessOnly, DepClass);
1384 }
else if (
StoreInst *
SI = dyn_cast<StoreInst>(UserI)) {
1385 if (!CheckBBLivenessOnly &&
SI->getPointerOperand() != U.
get()) {
1393 UsedAssumedInformation =
true;
1400 UsedAssumedInformation, CheckBBLivenessOnly, DepClass);
1406 bool &UsedAssumedInformation,
1407 bool CheckBBLivenessOnly,
DepClassTy DepClass,
1408 bool CheckForDeadStore) {
1412 if (ManifestAddedBlocks.contains(
I.getParent()))
1421 if (QueryingAA == FnLivenessAA)
1425 if (CheckBBLivenessOnly ? FnLivenessAA->
isAssumedDead(
I.getParent())
1430 UsedAssumedInformation =
true;
1434 if (CheckBBLivenessOnly)
1442 if (QueryingAA == &IsDeadAA)
1449 UsedAssumedInformation =
true;
1457 UsedAssumedInformation =
true;
1467 bool &UsedAssumedInformation,
1468 bool CheckBBLivenessOnly,
DepClassTy DepClass) {
1478 isAssumedDead(*CtxI, QueryingAA, FnLivenessAA, UsedAssumedInformation,
1483 if (CheckBBLivenessOnly)
1489 IsDeadAA = &getOrCreateAAFor<AAIsDead>(
1496 if (QueryingAA == IsDeadAA)
1503 UsedAssumedInformation =
true;
1520 if (QueryingAA == FnLivenessAA)
1535 bool CheckBBLivenessOnly,
DepClassTy LivenessDepClass,
1536 bool IgnoreDroppableUses,
1541 if (!CB(*
this, &QueryingAA))
1552 auto AddUsers = [&](
const Value &V,
const Use *OldUse) {
1553 for (
const Use &UU : V.
uses()) {
1554 if (OldUse && EquivalentUseCB && !EquivalentUseCB(*OldUse, UU)) {
1556 "rejected by the equivalence call back: "
1566 AddUsers(V,
nullptr);
1569 <<
" initial uses to check\n");
1572 const auto *LivenessAA =
1577 while (!Worklist.
empty()) {
1579 if (isa<PHINode>(U->getUser()) && !Visited.
insert(U).second)
1582 if (
auto *Fn = dyn_cast<Function>(U->getUser()))
1583 dbgs() <<
"[Attributor] Check use: " << **U <<
" in " << Fn->
getName()
1586 dbgs() <<
"[Attributor] Check use: " << **U <<
" in " << *U->getUser()
1589 bool UsedAssumedInformation =
false;
1590 if (
isAssumedDead(*U, &QueryingAA, LivenessAA, UsedAssumedInformation,
1591 CheckBBLivenessOnly, LivenessDepClass)) {
1593 dbgs() <<
"[Attributor] Dead use, skip!\n");
1596 if (IgnoreDroppableUses && U->getUser()->isDroppable()) {
1598 dbgs() <<
"[Attributor] Droppable user, skip!\n");
1602 if (
auto *
SI = dyn_cast<StoreInst>(U->getUser())) {
1603 if (&
SI->getOperandUse(0) == U) {
1604 if (!Visited.
insert(U).second)
1608 *
this, *
SI, PotentialCopies, QueryingAA, UsedAssumedInformation,
1612 <<
"[Attributor] Value is stored, continue with "
1613 << PotentialCopies.
size()
1614 <<
" potential copies instead!\n");
1615 for (
Value *PotentialCopy : PotentialCopies)
1616 if (!AddUsers(*PotentialCopy, U))
1623 bool Follow =
false;
1624 if (!Pred(*U, Follow))
1629 User &Usr = *U->getUser();
1630 AddUsers(Usr,
nullptr);
1632 auto *RI = dyn_cast<ReturnInst>(&Usr);
1638 return AddUsers(*ACS.getInstruction(), U);
1641 &QueryingAA, UsedAssumedInformation)) {
1642 LLVM_DEBUG(
dbgs() <<
"[Attributor] Could not follow return instruction "
1643 "to all call sites: "
1654 bool RequireAllCallSites,
1655 bool &UsedAssumedInformation) {
1661 if (!AssociatedFunction) {
1662 LLVM_DEBUG(
dbgs() <<
"[Attributor] No function associated with " << IRP
1668 &QueryingAA, UsedAssumedInformation);
1673 bool RequireAllCallSites,
1675 bool &UsedAssumedInformation,
1676 bool CheckPotentiallyDead) {
1680 <<
"[Attributor] Function " << Fn.
getName()
1681 <<
" has no internal linkage, hence not all call sites are known\n");
1686 if (!CB(*
this, QueryingAA))
1690 for (
unsigned u = 0; u <
Uses.size(); ++u) {
1693 if (
auto *Fn = dyn_cast<Function>(U))
1694 dbgs() <<
"[Attributor] Check use: " << Fn->
getName() <<
" in "
1697 dbgs() <<
"[Attributor] Check use: " << *U <<
" in " << *U.
getUser()
1700 if (!CheckPotentiallyDead &&
1701 isAssumedDead(U, QueryingAA,
nullptr, UsedAssumedInformation,
1704 dbgs() <<
"[Attributor] Dead use, skip!\n");
1708 if (CE->isCast() && CE->getType()->isPointerTy()) {
1710 dbgs() <<
"[Attributor] Use, is constant cast expression, add "
1711 << CE->getNumUses() <<
" uses of that expression instead!\n";
1713 for (
const Use &CEU : CE->uses())
1714 Uses.push_back(&CEU);
1722 <<
" has non call site use " << *U.
get() <<
" in "
1725 if (isa<BlockAddress>(U.
getUser()))
1730 const Use *EffectiveUse =
1733 if (!RequireAllCallSites) {
1734 LLVM_DEBUG(
dbgs() <<
"[Attributor] User " << *EffectiveUse->getUser()
1735 <<
" is not a call of " << Fn.
getName()
1739 LLVM_DEBUG(
dbgs() <<
"[Attributor] User " << *EffectiveUse->getUser()
1740 <<
" is an invalid use of " << Fn.
getName() <<
"\n");
1748 unsigned MinArgsParams =
1750 for (
unsigned u = 0; u < MinArgsParams; ++u) {
1754 dbgs() <<
"[Attributor] Call site / callee argument type mismatch ["
1755 << u <<
"@" << Fn.
getName() <<
": "
1765 LLVM_DEBUG(
dbgs() <<
"[Attributor] Call site callback failed for "
1773bool Attributor::shouldPropagateCallBaseContext(
const IRPosition &IRP) {
1788 if (!AssociatedFunction)
1795 const auto &AARetVal =
1797 if (!AARetVal.getState().isValidState())
1800 return AARetVal.checkForAllReturnedValuesAndReturnInsts(Pred);
1808 if (!AssociatedFunction)
1814 const auto &AARetVal =
1816 if (!AARetVal.getState().isValidState())
1819 return AARetVal.checkForAllReturnedValuesAndReturnInsts(
1829 bool &UsedAssumedInformation,
bool CheckBBLivenessOnly =
false,
1830 bool CheckPotentiallyDead =
false) {
1831 for (
unsigned Opcode : Opcodes) {
1833 auto *Insts = OpcodeInstMap.
lookup(Opcode);
1839 if (
A && !CheckPotentiallyDead &&
1841 UsedAssumedInformation, CheckBBLivenessOnly)) {
1843 dbgs() <<
"[Attributor] Instruction " << *
I
1844 <<
" is potentially dead, skip!\n";);
1859 bool &UsedAssumedInformation,
1860 bool CheckBBLivenessOnly,
1861 bool CheckPotentiallyDead) {
1868 const auto *LivenessAA =
1869 (CheckBBLivenessOnly || CheckPotentiallyDead)
1875 LivenessAA, Opcodes, UsedAssumedInformation,
1876 CheckBBLivenessOnly, CheckPotentiallyDead))
1885 bool &UsedAssumedInformation,
1886 bool CheckBBLivenessOnly,
1887 bool CheckPotentiallyDead) {
1891 UsedAssumedInformation, CheckBBLivenessOnly,
1892 CheckPotentiallyDead);
1897 bool &UsedAssumedInformation) {
1899 const Function *AssociatedFunction =
1901 if (!AssociatedFunction)
1906 const auto &LivenessAA =
1913 UsedAssumedInformation))
1923void Attributor::runTillFixpoint() {
1927 <<
" abstract attributes.\n");
1932 unsigned IterationCounter = 1;
1933 unsigned MaxIterations =
1943 LLVM_DEBUG(
dbgs() <<
"\n\n[Attributor] #Iteration: " << IterationCounter
1944 <<
", Worklist size: " << Worklist.
size() <<
"\n");
1949 for (
unsigned u = 0; u < InvalidAAs.
size(); ++u) {
1954 dbgs() <<
"[Attributor] InvalidAA: " << *InvalidAA
1955 <<
" has " << InvalidAA->
Deps.size()
1956 <<
" required & optional dependences\n");
1957 while (!InvalidAA->
Deps.empty()) {
1958 const auto &Dep = InvalidAA->
Deps.back();
1959 InvalidAA->
Deps.pop_back();
1963 dbgs() <<
" - recompute: " << *DepAA);
1968 <<
" - invalidate: " << *DepAA);
1972 InvalidAAs.
insert(DepAA);
1981 while (!ChangedAA->Deps.empty()) {
1983 cast<AbstractAttribute>(ChangedAA->Deps.back().getPointer()));
1984 ChangedAA->Deps.pop_back();
1987 LLVM_DEBUG(
dbgs() <<
"[Attributor] #Iteration: " << IterationCounter
1988 <<
", Worklist+Dependent size: " << Worklist.
size()
1998 const auto &AAState = AA->getState();
1999 if (!AAState.isAtFixpoint())
2001 ChangedAAs.push_back(AA);
2005 if (!AAState.isValidState())
2017 Worklist.insert(ChangedAAs.begin(), ChangedAAs.end());
2018 Worklist.insert(QueryAAsAwaitingUpdate.begin(),
2019 QueryAAsAwaitingUpdate.end());
2020 QueryAAsAwaitingUpdate.clear();
2022 }
while (!Worklist.empty() &&
2025 if (IterationCounter > MaxIterations && !Functions.
empty()) {
2027 return ORM <<
"Attributor did not reach a fixpoint after "
2028 <<
ore::NV(
"Iterations", MaxIterations) <<
" iterations.";
2031 emitRemark<OptimizationRemarkMissed>(
F,
"FixedPoint",
Remark);
2034 LLVM_DEBUG(
dbgs() <<
"\n[Attributor] Fixpoint iteration done after: "
2035 << IterationCounter <<
"/" << MaxIterations
2036 <<
" iterations\n");
2044 for (
unsigned u = 0; u < ChangedAAs.size(); u++) {
2046 if (!Visited.
insert(ChangedAA).second)
2053 NumAttributesTimedOut++;
2056 while (!ChangedAA->
Deps.empty()) {
2057 ChangedAAs.push_back(
2058 cast<AbstractAttribute>(ChangedAA->
Deps.back().getPointer()));
2059 ChangedAA->
Deps.pop_back();
2064 if (!Visited.
empty())
2065 dbgs() <<
"\n[Attributor] Finalized " << Visited.
size()
2066 <<
" abstract attributes.\n";
2070 errs() <<
"\n[Attributor] Fixpoint iteration done after: "
2071 << IterationCounter <<
"/" << MaxIterations <<
" iterations\n";
2072 llvm_unreachable(
"The fixpoint was not reached with exactly the number of "
2073 "specified iterations!");
2079 "Non-query AAs should not be required to register for updates!");
2080 QueryAAsAwaitingUpdate.insert(&AA);
2087 unsigned NumManifested = 0;
2088 unsigned NumAtFixpoint = 0;
2112 bool UsedAssumedInformation =
false;
2124 LLVM_DEBUG(
dbgs() <<
"[Attributor] Manifest " << LocalChange <<
" : " << *AA
2127 ManifestChange = ManifestChange | LocalChange;
2133 (void)NumManifested;
2134 (void)NumAtFixpoint;
2135 LLVM_DEBUG(
dbgs() <<
"\n[Attributor] Manifested " << NumManifested
2136 <<
" arguments while " << NumAtFixpoint
2137 <<
" were in a valid fixpoint state\n");
2139 NumAttributesManifested += NumManifested;
2140 NumAttributesValidFixpoint += NumAtFixpoint;
2145 errs() <<
"Unexpected abstract attribute: "
2150 .getAssociatedValue()
2153 "remain unchanged!");
2155 return ManifestChange;
2158void Attributor::identifyDeadInternalFunctions() {
2179 if (
F->hasLocalLinkage() && (
isModulePass() || !TLI->getLibFunc(*
F, LF)))
2183 bool FoundLiveInternal =
true;
2184 while (FoundLiveInternal) {
2185 FoundLiveInternal =
false;
2186 for (
unsigned u = 0, e = InternalFns.
size(); u < e; ++u) {
2191 bool UsedAssumedInformation =
false;
2195 return ToBeDeletedFunctions.count(
Callee) ||
2196 (Functions.count(
Callee) &&
Callee->hasLocalLinkage() &&
2199 *
F,
true,
nullptr, UsedAssumedInformation)) {
2204 InternalFns[u] =
nullptr;
2205 FoundLiveInternal =
true;
2209 for (
unsigned u = 0, e = InternalFns.
size(); u < e; ++u)
2211 ToBeDeletedFunctions.insert(
F);
2218 << ToBeDeletedFunctions.size() <<
" functions and "
2219 << ToBeDeletedBlocks.size() <<
" blocks and "
2220 << ToBeDeletedInsts.size() <<
" instructions and "
2221 << ToBeChangedValues.size() <<
" values and "
2222 << ToBeChangedUses.size() <<
" uses. To insert "
2223 << ToBeChangedToUnreachableInsts.size()
2224 <<
" unreachables.\n"
2225 <<
"Preserve manifest added " << ManifestAddedBlocks.size()
2231 auto ReplaceUse = [&](
Use *U,
Value *NewV) {
2232 Value *OldV = U->get();
2236 const auto &Entry = ToBeChangedValues.lookup(NewV);
2239 NewV = get<0>(Entry);
2244 "Cannot replace an instruction outside the current SCC!");
2248 if (
auto *RI = dyn_cast_or_null<ReturnInst>(
I)) {
2250 if (CI->isMustTailCall() && !ToBeDeletedInsts.count(CI))
2254 if (!isa<Argument>(NewV))
2255 for (
auto &
Arg : RI->getFunction()->args())
2256 Arg.removeAttr(Attribute::Returned);
2260 <<
" instead of " << *OldV <<
"\n");
2264 CGModifiedFunctions.insert(
I->getFunction());
2265 if (!isa<PHINode>(
I) && !ToBeDeletedInsts.count(
I) &&
2269 if (isa<UndefValue>(NewV) && isa<CallBase>(U->getUser())) {
2270 auto *CB = cast<CallBase>(U->getUser());
2271 if (CB->isArgOperand(U)) {
2272 unsigned Idx = CB->getArgOperandNo(U);
2273 CB->removeParamAttr(
Idx, Attribute::NoUndef);
2274 Function *Fn = CB->getCalledFunction();
2279 if (isa<Constant>(NewV) && isa<BranchInst>(U->getUser())) {
2280 Instruction *UserI = cast<Instruction>(U->getUser());
2281 if (isa<UndefValue>(NewV)) {
2282 ToBeChangedToUnreachableInsts.insert(UserI);
2289 for (
auto &It : ToBeChangedUses) {
2291 Value *NewV = It.second;
2292 ReplaceUse(U, NewV);
2296 for (
auto &It : ToBeChangedValues) {
2297 Value *OldV = It.first;
2298 auto [NewV,
Done] = It.second;
2300 for (
auto &U : OldV->
uses())
2304 if (
auto *
I = dyn_cast<Instruction>(U->getUser()))
2307 ReplaceUse(U, NewV);
2311 for (
const auto &V : InvokeWithDeadSuccessor)
2312 if (
InvokeInst *II = dyn_cast_or_null<InvokeInst>(V)) {
2314 "Cannot replace an invoke outside the current SCC!");
2315 bool UnwindBBIsDead = II->hasFnAttr(Attribute::NoUnwind);
2316 bool NormalBBIsDead = II->hasFnAttr(Attribute::NoReturn);
2317 bool Invoke2CallAllowed =
2319 assert((UnwindBBIsDead || NormalBBIsDead) &&
2320 "Invoke does not have dead successors!");
2322 BasicBlock *NormalDestBB = II->getNormalDest();
2323 if (UnwindBBIsDead) {
2325 if (Invoke2CallAllowed) {
2330 ToBeChangedToUnreachableInsts.insert(NormalNextIP);
2332 assert(NormalBBIsDead &&
"Broken invariant!");
2335 ToBeChangedToUnreachableInsts.insert(&NormalDestBB->
front());
2340 "Cannot replace a terminator outside the current SCC!");
2341 CGModifiedFunctions.insert(
I->getFunction());
2344 for (
const auto &V : ToBeChangedToUnreachableInsts)
2345 if (
Instruction *
I = dyn_cast_or_null<Instruction>(V)) {
2349 "Cannot replace an instruction outside the current SCC!");
2350 CGModifiedFunctions.insert(
I->getFunction());
2354 for (
const auto &V : ToBeDeletedInsts) {
2355 if (
Instruction *
I = dyn_cast_or_null<Instruction>(V)) {
2356 if (
auto *CB = dyn_cast<CallBase>(
I)) {
2358 "Cannot delete an instruction outside the current SCC!");
2359 if (!isa<IntrinsicInst>(CB))
2362 I->dropDroppableUses();
2363 CGModifiedFunctions.insert(
I->getFunction());
2364 if (!
I->getType()->isVoidTy())
2369 I->eraseFromParent();
2376 dbgs() <<
"[Attributor] DeadInsts size: " << DeadInsts.
size() <<
"\n";
2377 for (
auto &
I : DeadInsts)
2379 dbgs() <<
" - " << *
I <<
"\n";
2384 if (
unsigned NumDeadBlocks = ToBeDeletedBlocks.size()) {
2386 ToBeDeletedBBs.
reserve(NumDeadBlocks);
2389 "Cannot delete a block outside the current SCC!");
2390 CGModifiedFunctions.insert(BB->
getParent());
2392 if (ManifestAddedBlocks.contains(BB))
2402 identifyDeadInternalFunctions();
2405 ChangeStatus ManifestChange = rewriteFunctionSignatures(CGModifiedFunctions);
2407 for (
Function *Fn : CGModifiedFunctions)
2408 if (!ToBeDeletedFunctions.count(Fn) && Functions.count(Fn))
2411 for (
Function *Fn : ToBeDeletedFunctions) {
2412 if (!Functions.count(Fn))
2417 if (!ToBeChangedUses.empty())
2420 if (!ToBeChangedToUnreachableInsts.empty())
2423 if (!ToBeDeletedFunctions.empty())
2426 if (!ToBeDeletedBlocks.empty())
2429 if (!ToBeDeletedInsts.empty())
2432 if (!InvokeWithDeadSuccessor.empty())
2435 if (!DeadInsts.empty())
2438 NumFnDeleted += ToBeDeletedFunctions.size();
2440 LLVM_DEBUG(
dbgs() <<
"[Attributor] Deleted " << ToBeDeletedFunctions.size()
2441 <<
" functions after manifest.\n");
2443#ifdef EXPENSIVE_CHECKS
2445 if (ToBeDeletedFunctions.count(
F))
2451 return ManifestChange;
2461 Phase = AttributorPhase::UPDATE;
2474 Phase = AttributorPhase::MANIFEST;
2477 Phase = AttributorPhase::CLEANUP;
2483 return ManifestChange | CleanupChange;
2490 assert(Phase == AttributorPhase::UPDATE &&
2491 "We can update AA only in the update stage!");
2494 DependenceVector DV;
2495 DependenceStack.push_back(&DV);
2499 bool UsedAssumedInformation =
false;
2511 RerunCS = AA.
update(*
this);
2517 AAState.indicateOptimisticFixpoint();
2520 if (!AAState.isAtFixpoint())
2521 rememberDependences();
2525 DependenceVector *PoppedDV = DependenceStack.pop_back_val();
2527 assert(PoppedDV == &DV &&
"Inconsistent usage of the dependence stack!");
2533 assert(!
F.isDeclaration() &&
"Cannot create a wrapper around a declaration!");
2542 M.getFunctionList().insert(
F.getIterator(),
Wrapper);
2547 assert(
F.use_empty() &&
"Uses remained after wrapper was created!");
2552 F.setComdat(
nullptr);
2556 F.getAllMetadata(MDs);
2557 for (
auto MDIt : MDs)
2558 Wrapper->addMetadata(MDIt.first, *MDIt.second);
2559 Wrapper->setAttributes(
F.getAttributes());
2567 Args.push_back(&
Arg);
2576 NumFnShallowWrappersCreated++;
2580 if (
F.isDeclaration() ||
F.hasLocalLinkage() ||
2596 return InternalizedFns[&
F];
2614 F->getName() +
".internalized");
2617 for (
auto &
Arg :
F->args()) {
2618 auto ArgName =
Arg.getName();
2619 NewFArgIt->setName(ArgName);
2620 VMap[&
Arg] = &(*NewFArgIt++);
2635 F->getAllMetadata(MDs);
2636 for (
auto MDIt : MDs)
2640 M.getFunctionList().insert(
F->getIterator(), Copied);
2648 auto &InternalizedFn = FnMap[
F];
2649 auto IsNotInternalized = [&](
Use &U) ->
bool {
2650 if (
auto *CB = dyn_cast<CallBase>(U.
getUser()))
2651 return !FnMap.
lookup(CB->getCaller());
2654 F->replaceUsesWithIf(InternalizedFn, IsNotInternalized);
2683 LLVM_DEBUG(
dbgs() <<
"[Attributor] Cannot rewrite var-args functions\n");
2694 dbgs() <<
"[Attributor] Cannot rewrite due to complex attribute\n");
2699 bool UsedAssumedInformation =
false;
2701 UsedAssumedInformation)) {
2702 LLVM_DEBUG(
dbgs() <<
"[Attributor] Cannot rewrite all call sites\n");
2707 if (
auto *CI = dyn_cast<CallInst>(&
I))
2708 return !CI->isMustTailCall();
2716 nullptr, {Instruction::Call},
2717 UsedAssumedInformation)) {
2718 LLVM_DEBUG(
dbgs() <<
"[Attributor] Cannot rewrite due to instructions\n");
2730 <<
Arg.getParent()->getName() <<
" with "
2731 << ReplacementTypes.
size() <<
" replacements\n");
2733 "Cannot register an invalid rewrite");
2737 ArgumentReplacementMap[Fn];
2743 std::unique_ptr<ArgumentReplacementInfo> &ARI = ARIs[
Arg.getArgNo()];
2744 if (ARI && ARI->getNumReplacementArgs() <= ReplacementTypes.
size()) {
2745 LLVM_DEBUG(
dbgs() <<
"[Attributor] Existing rewrite is preferred\n");
2754 <<
Arg.getParent()->getName() <<
" with "
2755 << ReplacementTypes.
size() <<
" replacements\n");
2759 std::move(CalleeRepairCB),
2760 std::move(ACSRepairCB)));
2781 for (
auto &It : ArgumentReplacementMap) {
2785 if (!Functions.count(OldFn) || ToBeDeletedFunctions.count(OldFn))
2798 if (
const std::unique_ptr<ArgumentReplacementInfo> &ARI =
2799 ARIs[
Arg.getArgNo()]) {
2800 NewArgumentTypes.
append(ARI->ReplacementTypes.begin(),
2801 ARI->ReplacementTypes.end());
2802 NewArgumentAttributes.
append(ARI->getNumReplacementArgs(),
2812 for (
auto *
I : NewArgumentTypes)
2813 if (
auto *VT = dyn_cast<llvm::VectorType>(
I))
2814 LargestVectorWidth =
2815 std::max(LargestVectorWidth,
2816 VT->getPrimitiveSizeInBits().getKnownMinValue());
2827 << *NewFnTy <<
"\n");
2832 Functions.insert(NewFn);
2846 NewArgumentAttributes));
2857 if (
auto *BA = dyn_cast<BlockAddress>(U))
2859 for (
auto *BA : BlockAddresses)
2874 for (
unsigned OldArgNum = 0; OldArgNum < ARIs.
size(); ++OldArgNum) {
2875 unsigned NewFirstArgNum = NewArgOperands.
size();
2876 (void)NewFirstArgNum;
2877 if (
const std::unique_ptr<ArgumentReplacementInfo> &ARI =
2879 if (ARI->ACSRepairCB)
2880 ARI->ACSRepairCB(*ARI, ACS, NewArgOperands);
2881 assert(ARI->getNumReplacementArgs() + NewFirstArgNum ==
2882 NewArgOperands.
size() &&
2883 "ACS repair callback did not provide as many operand as new "
2884 "types were registered!");
2886 NewArgOperandAttributes.
append(ARI->ReplacementTypes.size(),
2895 assert(NewArgOperands.
size() == NewArgOperandAttributes.
size() &&
2896 "Mismatch # argument operands vs. # argument operand attributes!");
2898 "Mismatch # argument operands vs. # function arguments!");
2905 if (
InvokeInst *II = dyn_cast<InvokeInst>(OldCB)) {
2908 NewArgOperands, OperandBundleDefs,
"", OldCB);
2912 NewCI->setTailCallKind(cast<CallInst>(OldCB)->getTailCallKind());
2917 NewCB->
copyMetadata(*OldCB, {LLVMContext::MD_prof, LLVMContext::MD_dbg});
2922 OldCallAttributeList.
getRetAttrs(), NewArgOperandAttributes));
2925 LargestVectorWidth);
2927 CallSitePairs.
push_back({OldCB, NewCB});
2932 bool UsedAssumedInformation =
false;
2934 true,
nullptr, UsedAssumedInformation,
2937 assert(
Success &&
"Assumed call site replacement to succeed!");
2942 for (
unsigned OldArgNum = 0; OldArgNum < ARIs.
size();
2943 ++OldArgNum, ++OldFnArgIt) {
2944 if (
const std::unique_ptr<ArgumentReplacementInfo> &ARI =
2946 if (ARI->CalleeRepairCB)
2947 ARI->CalleeRepairCB(*ARI, *NewFn, NewFnArgIt);
2948 if (ARI->ReplacementTypes.empty())
2951 NewFnArgIt += ARI->ReplacementTypes.size();
2953 NewFnArgIt->
takeName(&*OldFnArgIt);
2960 for (
auto &CallSitePair : CallSitePairs) {
2961 CallBase &OldCB = *CallSitePair.first;
2962 CallBase &NewCB = *CallSitePair.second;
2964 "Cannot handle call sites with different types!");
2976 if (ModifiedFns.
remove(OldFn))
2977 ModifiedFns.
insert(NewFn);
2985void InformationCache::initializeInformationCache(
const Function &CF,
3001 auto AddToAssumeUsesMap = [&](
const Value &V) ->
void {
3003 if (
auto *
I = dyn_cast<Instruction>(&V))
3005 while (!Worklist.
empty()) {
3007 std::optional<short> &NumUses = AssumeUsesMap[
I];
3009 NumUses =
I->getNumUses();
3010 NumUses = *NumUses - 1;
3013 AssumeOnlyValues.insert(
I);
3014 for (
const Value *Op :
I->operands())
3015 if (
auto *OpI = dyn_cast<Instruction>(Op))
3021 bool IsInterestingOpcode =
false;
3028 switch (
I.getOpcode()) {
3031 "New call base instruction type needs to be known in the "
3034 case Instruction::Call:
3038 if (
auto *Assume = dyn_cast<AssumeInst>(&
I)) {
3039 AssumeOnlyValues.insert(Assume);
3041 AddToAssumeUsesMap(*Assume->getArgOperand(0));
3043 FI.ContainsMustTailCall =
true;
3045 getFunctionInfo(*Callee).CalledViaMustTail =
true;
3048 case Instruction::CallBr:
3049 case Instruction::Invoke:
3050 case Instruction::CleanupRet:
3051 case Instruction::CatchSwitch:
3052 case Instruction::AtomicRMW:
3053 case Instruction::AtomicCmpXchg:
3054 case Instruction::Br:
3055 case Instruction::Resume:
3056 case Instruction::Ret:
3057 case Instruction::Load:
3059 case Instruction::Store:
3061 case Instruction::Alloca:
3062 case Instruction::AddrSpaceCast:
3063 IsInterestingOpcode =
true;
3065 if (IsInterestingOpcode) {
3066 auto *&Insts = FI.OpcodeInstMap[
I.getOpcode()];
3071 if (
I.mayReadOrWriteMemory())
3072 FI.RWInsts.push_back(&
I);
3075 if (
F.hasFnAttribute(Attribute::AlwaysInline) &&
3077 InlineableFunctions.insert(&
F);
3084InformationCache::FunctionInfo::~FunctionInfo() {
3087 for (
auto &It : OpcodeInstMap)
3088 It.getSecond()->~InstructionVectorTy();
3099 if (DependenceStack.empty())
3103 DependenceStack.back()->push_back({&FromAA, &ToAA, DepClass});
3106void Attributor::rememberDependences() {
3107 assert(!DependenceStack.empty() &&
"No dependences to remember!");
3109 for (DepInfo &DI : *DependenceStack.back()) {
3112 "Expected required or optional dependence (1 bit)!");
3120 if (!VisitedFunctions.insert(&
F).second)
3122 if (
F.isDeclaration())
3128 InformationCache::FunctionInfo &FI = InfoCache.getFunctionInfo(
F);
3130 for (
const Use &U :
F.uses())
3131 if (
const auto *CB = dyn_cast<CallBase>(U.
getUser()))
3132 if (CB->isCallee(&U) && CB->isMustTailCall())
3133 FI.CalledViaMustTail =
true;
3141 getOrCreateAAFor<AAIsDead>(FPos);
3144 getOrCreateAAFor<AAWillReturn>(FPos);
3147 getOrCreateAAFor<AAUndefinedBehavior>(FPos);
3150 getOrCreateAAFor<AANoUnwind>(FPos);
3153 getOrCreateAAFor<AANoSync>(FPos);
3156 getOrCreateAAFor<AANoFree>(FPos);
3159 getOrCreateAAFor<AANoReturn>(FPos);
3162 getOrCreateAAFor<AANoRecurse>(FPos);
3165 getOrCreateAAFor<AAMemoryBehavior>(FPos);
3168 getOrCreateAAFor<AAMemoryLocation>(FPos);
3171 getOrCreateAAFor<AAAssumptionInfo>(FPos);
3175 getOrCreateAAFor<AAHeapToStack>(FPos);
3178 Type *ReturnType =
F.getReturnType();
3179 if (!ReturnType->isVoidTy()) {
3182 getOrCreateAAFor<AAReturnedValues>(FPos);
3187 getOrCreateAAFor<AAIsDead>(RetPos);
3190 bool UsedAssumedInformation =
false;
3195 getOrCreateAAFor<AANoUndef>(RetPos);
3197 if (ReturnType->isPointerTy()) {
3200 getOrCreateAAFor<AAAlign>(RetPos);
3203 getOrCreateAAFor<AANonNull>(RetPos);
3206 getOrCreateAAFor<AANoAlias>(RetPos);
3210 getOrCreateAAFor<AADereferenceable>(RetPos);
3220 bool UsedAssumedInformation =
false;
3225 getOrCreateAAFor<AAIsDead>(ArgPos);
3228 getOrCreateAAFor<AANoUndef>(ArgPos);
3230 if (
Arg.getType()->isPointerTy()) {
3232 getOrCreateAAFor<AANonNull>(ArgPos);
3235 getOrCreateAAFor<AANoAlias>(ArgPos);
3238 getOrCreateAAFor<AADereferenceable>(ArgPos);
3241 getOrCreateAAFor<AAAlign>(ArgPos);
3244 getOrCreateAAFor<AANoCapture>(ArgPos);
3248 getOrCreateAAFor<AAMemoryBehavior>(ArgPos);
3251 getOrCreateAAFor<AANoFree>(ArgPos);
3254 getOrCreateAAFor<AAPrivatizablePtr>(ArgPos);
3259 auto &CB = cast<CallBase>(
I);
3265 getOrCreateAAFor<AAIsDead>(CBInstPos);
3274 getOrCreateAAFor<AAAssumptionInfo>(CBFnPos);
3279 !
Callee->hasMetadata(LLVMContext::MD_callback))
3282 if (!
Callee->getReturnType()->isVoidTy() && !CB.use_empty()) {
3285 bool UsedAssumedInformation =
false;
3290 for (
int I = 0,
E = CB.arg_size();
I <
E; ++
I) {
3295 getOrCreateAAFor<AAIsDead>(CBArgPos);
3300 bool UsedAssumedInformation =
false;
3305 getOrCreateAAFor<AANoUndef>(CBArgPos);
3307 if (!CB.getArgOperand(
I)->getType()->isPointerTy())
3311 getOrCreateAAFor<AANonNull>(CBArgPos);
3314 getOrCreateAAFor<AANoCapture>(CBArgPos);
3317 getOrCreateAAFor<AANoAlias>(CBArgPos);
3320 getOrCreateAAFor<AADereferenceable>(CBArgPos);
3323 getOrCreateAAFor<AAAlign>(CBArgPos);
3327 getOrCreateAAFor<AAMemoryBehavior>(CBArgPos);
3330 getOrCreateAAFor<AANoFree>(CBArgPos);
3337 bool UsedAssumedInformation =
false;
3339 nullptr, OpcodeInstMap, CallSitePred,
nullptr,
nullptr,
3340 {(
unsigned)Instruction::Invoke, (
unsigned)Instruction::CallBr,
3342 UsedAssumedInformation);
3344 assert(
Success &&
"Expected the check call to be successful!");
3347 if (isa<LoadInst>(
I)) {
3348 getOrCreateAAFor<AAAlign>(
3354 auto &
SI = cast<StoreInst>(
I);
3363 nullptr, OpcodeInstMap, LoadStorePred,
nullptr,
nullptr,
3364 {(
unsigned)Instruction::Load, (
unsigned)Instruction::Store},
3365 UsedAssumedInformation);
3367 assert(
Success &&
"Expected the check call to be successful!");
3384 return OS <<
"fn_ret";
3386 return OS <<
"cs_ret";
3394 return OS <<
"cs_arg";
3416 return OS << static_cast<const AbstractState &>(S);
3430 OS <<
"set-state(< {";
3446 OS <<
"set-state(< {";
3451 if (
auto *
F = dyn_cast<Function>(It.first.getValue()))
3452 OS <<
"@" <<
F->getName() <<
"[" << int(It.second) <<
"], ";
3454 OS << *It.first.getValue() <<
"[" << int(It.second) <<
"], ";
3467 OS <<
"] for CtxI ";
3474 OS <<
"<<null inst>>";
3483 for (
const auto &DepAA :
Deps) {
3484 auto *AA = DepAA.getPointer();
3501 OS <<
" [ <unknown> ]";
3515 bool DeleteFns,
bool IsModulePass) {
3516 if (Functions.
empty())
3520 dbgs() <<
"[Attributor] Run on module with " << Functions.
size()
3529 AC.IsModulePass = IsModulePass;
3530 AC.DeleteFns = DeleteFns;
3536 if (!
A.isFunctionIPOAmendable(*
F))
3544 unsigned FunSize = Functions.
size();
3545 for (
unsigned u = 0; u < FunSize; u++) {
3547 if (!
F->isDeclaration() && !
F->isDefinitionExact() &&
F->getNumUses() &&
3550 assert(NewF &&
"Could not internalize function.");
3555 for (
const Use &U : NewF->
uses())
3557 auto *CallerF = CB->getCaller();
3565 if (
F->hasExactDefinition())
3566 NumFnWithExactDefinition++;
3568 NumFnWithoutExactDefinition++;
3573 if (
F->hasLocalLinkage()) {
3575 const auto *CB = dyn_cast<CallBase>(U.getUser());
3576 return CB && CB->isCallee(&U) &&
3577 Functions.count(const_cast<Function *>(CB->getCaller()));
3584 A.identifyDefaultAbstractAttributes(*
F);
3590 <<
" functions, result: " << Changed <<
".\n");
3597 static std::atomic<int> CallTimes;
3603 Prefix =
"dep_graph";
3604 std::string Filename =
3605 Prefix +
"_" + std::to_string(CallTimes.load()) +
".dot";
3607 outs() <<
"Dependency graph dump to " << Filename <<
".\n";
3620 cast<AbstractAttribute>(DepAA.getPointer())->printWithDeps(
outs());
3653 Functions.
insert(&
N.getFunction());
3655 if (Functions.
empty())
3710 std::string AAString;
3721struct AttributorLegacyPass :
public ModulePass {
3728 bool runOnModule(
Module &M)
override {
3768 if (Functions.
empty())
3794 return new AttributorCGSCCLegacyPass();
3797char AttributorLegacyPass::ID = 0;
3798char AttributorCGSCCLegacyPass::ID = 0;
3801 "Deduce and propagate attributes",
false,
false)
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)
Deduce and propagate attributes
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))
Deduce and propagate false attributor cgscc
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)
modulo schedule Modulo Schedule test pass
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
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
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.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
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).
A node in the call graph for a module.
void getAnalysisUsage(AnalysisUsage &Info) const override
getAnalysisUsage - For this class, we declare that we require and preserve the call graph.
CallGraphSCC - This is a single SCC that a CallGraphSCCPass is run on.
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 (...
The ModulePass which wraps up a CallGraph and the logic to build it.
The basic data container for the call graph of a Module of IR.
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.
const Function & getFunction() const
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.
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)
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
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).
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
Pass interface - Implemented by all 'passes'.
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.
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.
User * getUser() const
Returns the User that contains this Use.
bool isDroppable() const
A droppable user is a user for which uses can be dropped without affecting correctness and should be ...
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.
void updateMinLegalVectorWidthAttr(Function &Fn, uint64_t Width)
Update min-legal-vector-width if it is in Attribute and less than Width.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ 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.
void initializeAttributorLegacyPassPass(PassRegistry &)
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...
void initializeAttributorCGSCCLegacyPassPass(PassRegistry &)
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.
Pass * createAttributorCGSCCLegacyPass()
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)
Wrapper function around std::find to detect if an element exists in a container.
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)
Pass * createAttributorLegacyPass()
TinyPtrVector< DepTy > 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.