71#define DEBUG_TYPE "function-attrs"
73STATISTIC(NumMemoryAttr,
"Number of functions with improved memory attribute");
74STATISTIC(NumNoCapture,
"Number of arguments marked nocapture");
75STATISTIC(NumReturned,
"Number of arguments marked returned");
76STATISTIC(NumReadNoneArg,
"Number of arguments marked readnone");
77STATISTIC(NumReadOnlyArg,
"Number of arguments marked readonly");
78STATISTIC(NumWriteOnlyArg,
"Number of arguments marked writeonly");
79STATISTIC(NumNoAlias,
"Number of function returns marked noalias");
80STATISTIC(NumNonNullReturn,
"Number of function returns marked nonnull");
81STATISTIC(NumNoUndefReturn,
"Number of function returns marked noundef");
82STATISTIC(NumNoRecurse,
"Number of functions marked as norecurse");
83STATISTIC(NumNoUnwind,
"Number of functions marked as nounwind");
84STATISTIC(NumNoFree,
"Number of functions marked as nofree");
85STATISTIC(NumWillReturn,
"Number of functions marked as willreturn");
86STATISTIC(NumNoSync,
"Number of functions marked as nosync");
87STATISTIC(NumCold,
"Number of functions marked as cold");
90 "Number of functions marked as norecurse during thinlink");
92 "Number of functions marked as nounwind during thinlink");
96 cl::desc(
"Try to propagate nonnull argument attributes from callsites to "
97 "caller functions."));
101 cl::desc(
"Stop inferring nounwind attribute during function-attrs pass"));
105 cl::desc(
"Stop inferring nofree attribute during function-attrs pass"));
109 cl::desc(
"Don't propagate function-attrs in thinLTO"));
125 if (isa<AllocaInst>(UO))
127 if (isa<Argument>(UO)) {
140 for (
const Value *Arg : Call->args()) {
141 if (!Arg->getType()->isPtrOrPtrVectorTy())
162static std::pair<MemoryEffects, MemoryEffects>
164 const SCCNodeSet &SCCNodes) {
178 if (
F.getAttributes().hasAttrSomewhere(Attribute::InAlloca) ||
179 F.getAttributes().hasAttrSomewhere(Attribute::Preallocated))
186 if (
auto *Call = dyn_cast<CallBase>(&
I)) {
192 if (!Call->hasOperandBundles() && Call->getCalledFunction() &&
193 SCCNodes.count(Call->getCalledFunction())) {
196 addArgLocs(RecursiveArgME, Call, ModRefInfo::ModRef, AAR);
210 if (isa<PseudoProbeInst>(
I))
224 if (ArgMR != ModRefInfo::NoModRef)
230 if (
I.mayWriteToMemory())
231 MR |= ModRefInfo::Mod;
232 if (
I.mayReadFromMemory())
233 MR |= ModRefInfo::Ref;
234 if (MR == ModRefInfo::NoModRef)
252 return {OrigME & ME, RecursiveArgME};
261template <
typename AARGetterT>
272 auto [FnME, FnRecursiveArgME] =
275 RecursiveArgME |= FnRecursiveArgME;
283 if (ArgMR != ModRefInfo::NoModRef)
289 if (NewME != OldME) {
291 F->setMemoryEffects(NewME);
295 A.removeAttr(Attribute::Writable);
309 if (CachedPrevailingSummary.
count(VI))
310 return CachedPrevailingSummary[VI];
352 CachedPrevailingSummary[VI] =
nullptr;
356 for (
const auto &GVS : VI.getSummaryList()) {
362 if (!FS || FS->fflags().HasUnknownCall)
365 const auto &Linkage = GVS->linkage();
370 <<
"ThinLTO FunctionAttrs: Multiple Local Linkage, bailing on "
372 << VI.name() <<
" from " << FS->modulePath() <<
". Previous module "
373 <<
Local->modulePath() <<
"\n");
378 assert(IsPrevailing(VI.getGUID(), GVS.get()));
385 if (IsPrevailing(VI.getGUID(), GVS.get())) {
397 CachedPrevailingSummary[VI] =
Local;
398 }
else if (Prevailing) {
400 CachedPrevailingSummary[VI] = Prevailing;
403 return CachedPrevailingSummary[VI];
416 bool Changed =
false;
418 auto PropagateAttributes = [&](std::vector<ValueInfo> &SCCNodes) {
421 InferredFlags.
NoRecurse = (SCCNodes.size() == 1);
424 for (
auto &V : SCCNodes) {
435 for (
const auto &Callee : CallerSummary->
calls()) {
437 Callee.first, CachedPrevailingSummary, IsPrevailing);
455 for (
auto &V : SCCNodes) {
457 LLVM_DEBUG(
dbgs() <<
"ThinLTO FunctionAttrs: Propagated NoRecurse to "
458 << V.name() <<
"\n");
459 ++NumThinLinkNoRecurse;
463 LLVM_DEBUG(
dbgs() <<
"ThinLTO FunctionAttrs: Propagated NoUnwind to "
464 << V.name() <<
"\n");
465 ++NumThinLinkNoUnwind;
468 for (
const auto &S : V.getSummaryList()) {
469 if (
auto *FS = dyn_cast<FunctionSummary>(S.get())) {
484 std::vector<ValueInfo> Nodes(*
I);
485 PropagateAttributes(Nodes);
495struct ArgumentGraphNode {
503 using ArgumentMapTy = std::map<Argument *, ArgumentGraphNode>;
505 ArgumentMapTy ArgumentMap;
513 ArgumentGraphNode SyntheticRoot;
516 ArgumentGraph() { SyntheticRoot.Definition =
nullptr; }
520 iterator
begin() {
return SyntheticRoot.Uses.begin(); }
521 iterator
end() {
return SyntheticRoot.Uses.end(); }
522 ArgumentGraphNode *getEntryNode() {
return &SyntheticRoot; }
524 ArgumentGraphNode *operator[](
Argument *
A) {
525 ArgumentGraphNode &
Node = ArgumentMap[
A];
527 SyntheticRoot.Uses.push_back(&
Node);
536 ArgumentUsesTracker(
const SCCNodeSet &SCCNodes) : SCCNodes(SCCNodes) {}
541 CallBase *CB = dyn_cast<CallBase>(
U->getUser());
548 if (!
F || !
F->hasExactDefinition() || !SCCNodes.count(
F)) {
567 if (UseIndex >=
F->arg_size()) {
568 assert(
F->isVarArg() &&
"More params than args in non-varargs call");
573 Uses.push_back(&*std::next(
F->arg_begin(), UseIndex));
578 bool Captured =
false;
583 const SCCNodeSet &SCCNodes;
591 std::optional<int64_t>
Offset;
598struct ArgumentAccessInfo {
600 AccessType ArgAccessType;
605struct UsesPerBlockInfo {
607 bool HasWrites =
false;
608 bool HasUnknownAccess =
false;
612struct ArgumentUsesSummary {
613 bool HasAnyWrite =
false;
614 bool HasWriteOutsideEntryBB =
false;
618ArgumentAccessInfo getArgmentAccessInfo(
const Instruction *
I,
619 const ArgumentUse &ArgUse,
621 auto GetTypeAccessRange =
623 std::optional<int64_t>
Offset) -> std::optional<ConstantRange> {
632 auto GetConstantIntRange =
634 std::optional<int64_t>
Offset) -> std::optional<ConstantRange> {
635 auto *ConstantLength = dyn_cast<ConstantInt>(
Length);
636 if (ConstantLength &&
Offset &&
637 ConstantLength->getValue().isStrictlyPositive()) {
640 APInt(64, *
Offset + ConstantLength->getSExtValue(),
true));
644 if (
auto *SI = dyn_cast<StoreInst>(
I)) {
645 if (
SI->isSimple() && &
SI->getOperandUse(1) == ArgUse.U) {
650 if (
auto TypeAccessRange =
651 GetTypeAccessRange(
SI->getAccessType(), ArgUse.Offset))
652 AccessRanges.
insert(*TypeAccessRange);
653 return {ArgumentAccessInfo::AccessType::Write, std::move(AccessRanges)};
655 }
else if (
auto *LI = dyn_cast<LoadInst>(
I)) {
656 if (LI->isSimple()) {
657 assert(&LI->getOperandUse(0) == ArgUse.U);
661 if (
auto TypeAccessRange =
662 GetTypeAccessRange(LI->getAccessType(), ArgUse.Offset))
663 return {ArgumentAccessInfo::AccessType::Read, {*TypeAccessRange}};
665 }
else if (
auto *MemSet = dyn_cast<MemSetInst>(
I)) {
666 if (!MemSet->isVolatile()) {
668 if (
auto AccessRange =
669 GetConstantIntRange(MemSet->getLength(), ArgUse.Offset))
670 AccessRanges.
insert(*AccessRange);
671 return {ArgumentAccessInfo::AccessType::Write, AccessRanges};
673 }
else if (
auto *MTI = dyn_cast<MemTransferInst>(
I)) {
674 if (!MTI->isVolatile()) {
675 if (&MTI->getOperandUse(0) == ArgUse.U) {
677 if (
auto AccessRange =
678 GetConstantIntRange(MTI->getLength(), ArgUse.Offset))
679 AccessRanges.
insert(*AccessRange);
680 return {ArgumentAccessInfo::AccessType::Write, AccessRanges};
681 }
else if (&MTI->getOperandUse(1) == ArgUse.U) {
682 if (
auto AccessRange =
683 GetConstantIntRange(MTI->getLength(), ArgUse.Offset))
684 return {ArgumentAccessInfo::AccessType::Read, {*AccessRange}};
687 }
else if (
auto *CB = dyn_cast<CallBase>(
I)) {
691 bool IsInitialize = CB->
paramHasAttr(ArgNo, Attribute::Initializes);
692 if (IsInitialize && ArgUse.Offset) {
696 ? ArgumentAccessInfo::AccessType::Write
697 : ArgumentAccessInfo::AccessType::WriteWithSideEffect;
703 CR.getUpper() + *ArgUse.Offset));
704 return {
Access, AccessRanges};
709 return {ArgumentAccessInfo::AccessType::Unknown, {}};
714 auto &
DL =
F.getParent()->getDataLayout();
716 DL.getIndexSizeInBits(
A.getType()->getPointerAddressSpace());
717 ArgumentUsesSummary
Result;
721 for (
Use &U :
A.uses())
727 auto *BB =
I->getParent();
728 auto &BBInfo =
Result.UsesPerBlock[BB];
729 bool AlreadyVisitedInst = BBInfo.Insts.contains(
I);
730 auto &IInfo = BBInfo.Insts[
I];
734 if (AlreadyVisitedInst) {
735 IInfo = {ArgumentAccessInfo::AccessType::Unknown, {}};
736 BBInfo.HasUnknownAccess =
true;
740 IInfo = std::move(Info);
741 BBInfo.HasUnknownAccess |=
742 IInfo.ArgAccessType == ArgumentAccessInfo::AccessType::Unknown;
744 (IInfo.ArgAccessType == ArgumentAccessInfo::AccessType::Write ||
745 IInfo.ArgAccessType ==
746 ArgumentAccessInfo::AccessType::WriteWithSideEffect) &&
747 !IInfo.AccessRanges.empty();
748 BBInfo.HasWrites |= InfoHasWrites;
749 return InfoHasWrites;
754 while (!Worklist.
empty()) {
756 User *
U = ArgUse.U->getUser();
759 if (
auto *
GEP = dyn_cast<GEPOperator>(U)) {
760 std::optional<int64_t> NewOffset = std::nullopt;
764 NewOffset = *ArgUse.Offset +
Offset.getSExtValue();
766 for (
Use &U :
GEP->uses())
771 auto *
I = cast<Instruction>(U);
772 bool HasWrite = UpdateUseInfo(
I, getArgmentAccessInfo(
I, ArgUse,
DL));
774 Result.HasAnyWrite |= HasWrite;
776 if (HasWrite &&
I->getParent() != &EntryBB)
777 Result.HasWriteOutsideEntryBB =
true;
816 if (
A->hasInAllocaAttr() ||
A->hasPreallocatedAttr())
820 bool IsWrite =
false;
822 for (
Use &U :
A->uses()) {
827 while (!Worklist.
empty()) {
828 if (IsWrite && IsRead)
835 switch (
I->getOpcode()) {
836 case Instruction::BitCast:
837 case Instruction::GetElementPtr:
838 case Instruction::PHI:
839 case Instruction::Select:
840 case Instruction::AddrSpaceCast:
842 for (
Use &UU :
I->uses())
843 if (Visited.
insert(&UU).second)
847 case Instruction::Call:
848 case Instruction::Invoke: {
867 if (Visited.
insert(&UU).second)
877 if (!
I->getType()->isVoidTy())
878 for (
Use &UU :
I->uses())
879 if (Visited.
insert(&UU).second)
889 SCCNodes.
count(
F->getArg(UseIndex)))
910 case Instruction::Load:
913 if (cast<LoadInst>(
I)->isVolatile())
919 case Instruction::Store:
920 if (cast<StoreInst>(
I)->getValueOperand() == *U)
926 if (cast<StoreInst>(
I)->isVolatile())
932 case Instruction::ICmp:
933 case Instruction::Ret:
941 if (IsWrite && IsRead)
944 return Attribute::ReadOnly;
946 return Attribute::WriteOnly;
948 return Attribute::ReadNone;
959 if (!
F->hasExactDefinition())
962 if (
F->getReturnType()->isVoidTy())
966 if (
F->getAttributes().hasAttrSomewhere(Attribute::Returned))
969 auto FindRetArg = [&]() ->
Argument * {
972 if (
auto *Ret = dyn_cast<ReturnInst>(BB.getTerminator())) {
976 dyn_cast<Argument>(Ret->getReturnValue()->stripPointerCasts());
977 if (!RetVal || RetVal->getType() !=
F->getReturnType())
982 else if (RetArg != RetVal)
989 if (
Argument *RetArg = FindRetArg()) {
990 RetArg->
addAttr(Attribute::Returned);
1005 bool Changed =
false;
1016 if (
auto *CB = dyn_cast<CallBase>(&
I)) {
1018 for (
auto &CSArg : CalledFunc->args()) {
1019 if (!CSArg.hasNonNullAttr(
false))
1025 auto *FArg = dyn_cast<Argument>(CB->
getArgOperand(CSArg.getArgNo()));
1026 if (FArg && !FArg->hasNonNullAttr()) {
1027 FArg->addAttr(Attribute::NonNull);
1041 assert((R == Attribute::ReadOnly || R == Attribute::ReadNone ||
1042 R == Attribute::WriteOnly)
1043 &&
"Must be an access attribute.");
1044 assert(
A &&
"Argument must not be null.");
1047 if (
A->hasAttribute(R))
1052 A->removeAttr(Attribute::WriteOnly);
1053 A->removeAttr(Attribute::ReadOnly);
1054 A->removeAttr(Attribute::ReadNone);
1056 if (R == Attribute::ReadNone || R == Attribute::ReadOnly)
1057 A->removeAttr(Attribute::Writable);
1059 if (R == Attribute::ReadOnly)
1061 else if (R == Attribute::WriteOnly)
1069 auto ArgumentUses = collectArgumentUsesPerBlock(
A,
F);
1071 if (!ArgumentUses.HasAnyWrite)
1074 auto &UsesPerBlock = ArgumentUses.UsesPerBlock;
1083 auto UPB = UsesPerBlock.find(BB);
1090 if (UPB == UsesPerBlock.end() || !UPB->second.HasUnknownAccess) {
1091 bool HasAddedSuccessor =
false;
1093 if (
auto SuccI = Initialized.
find(Succ); SuccI != Initialized.
end()) {
1094 if (HasAddedSuccessor) {
1097 CRL = SuccI->second;
1098 HasAddedSuccessor =
true;
1107 if (UPB != UsesPerBlock.end()) {
1111 sort(Insts, [](std::pair<Instruction *, ArgumentAccessInfo> &
LHS,
1112 std::pair<Instruction *, ArgumentAccessInfo> &
RHS) {
1113 return LHS.first->comesBefore(
RHS.first);
1119 if (
Info.ArgAccessType == ArgumentAccessInfo::AccessType::Unknown ||
1120 Info.ArgAccessType ==
1121 ArgumentAccessInfo::AccessType::WriteWithSideEffect)
1123 if (!
Info.AccessRanges.empty()) {
1124 if (
Info.ArgAccessType == ArgumentAccessInfo::AccessType::Write ||
1125 Info.ArgAccessType ==
1126 ArgumentAccessInfo::AccessType::WriteWithSideEffect) {
1129 assert(
Info.ArgAccessType == ArgumentAccessInfo::AccessType::Read);
1130 for (
const auto &ReadRange :
Info.AccessRanges)
1142 bool OnlyScanEntryBlock = !ArgumentUses.HasWriteOutsideEntryBB;
1143 if (!OnlyScanEntryBlock)
1144 if (
auto EntryUPB = UsesPerBlock.find(&EntryBB);
1145 EntryUPB != UsesPerBlock.end())
1146 OnlyScanEntryBlock = EntryUPB->second.HasUnknownAccess;
1147 if (OnlyScanEntryBlock) {
1148 EntryCRL = VisitBlock(&EntryBB);
1149 if (EntryCRL.
empty())
1160 Initialized[BB] = CRL;
1163 auto EntryCRLI = Initialized.
find(&EntryBB);
1164 if (EntryCRLI == Initialized.
end())
1167 EntryCRL = EntryCRLI->second;
1171 "should have bailed already if EntryCRL is empty");
1173 if (
A.hasAttribute(Attribute::Initializes)) {
1175 A.getAttribute(Attribute::Initializes).getValueAsConstantRangeList();
1176 if (PreviousCRL == EntryCRL)
1178 EntryCRL = EntryCRL.
unionWith(PreviousCRL);
1190 bool SkipInitializes) {
1199 if (!
F->hasExactDefinition())
1207 if (
F->onlyReadsMemory() &&
F->doesNotThrow() &&
1208 F->getReturnType()->isVoidTy()) {
1210 if (
A.getType()->isPointerTy() && !
A.hasNoCaptureAttr()) {
1221 if (!
A.getType()->isPointerTy())
1223 bool HasNonLocalUses =
false;
1224 if (!
A.hasNoCaptureAttr()) {
1225 ArgumentUsesTracker Tracker(SCCNodes);
1227 if (!Tracker.Captured) {
1228 if (Tracker.Uses.empty()) {
1238 ArgumentGraphNode *
Node = AG[&
A];
1240 Node->Uses.push_back(AG[
Use]);
1242 HasNonLocalUses =
true;
1248 if (!HasNonLocalUses && !
A.onlyReadsMemory()) {
1260 if (!SkipInitializes && !
A.onlyReadsMemory()) {
1275 const std::vector<ArgumentGraphNode *> &ArgumentSCC = *
I;
1276 if (ArgumentSCC.size() == 1) {
1277 if (!ArgumentSCC[0]->Definition)
1281 if (ArgumentSCC[0]->
Uses.size() == 1 &&
1282 ArgumentSCC[0]->Uses[0] == ArgumentSCC[0]) {
1283 Argument *
A = ArgumentSCC[0]->Definition;
1287 Changed.
insert(
A->getParent());
1302 for (ArgumentGraphNode *
I : ArgumentSCC) {
1303 ArgumentSCCNodes.
insert(
I->Definition);
1306 bool SCCCaptured =
false;
1307 for (ArgumentGraphNode *
N : ArgumentSCC) {
1308 for (ArgumentGraphNode *
Use :
N->Uses) {
1310 if (
A->hasNoCaptureAttr() || ArgumentSCCNodes.
count(
A))
1321 for (ArgumentGraphNode *
N : ArgumentSCC) {
1326 Changed.
insert(
A->getParent());
1343 if (
A == Attribute::ReadNone)
1345 if (
B == Attribute::ReadNone)
1351 for (ArgumentGraphNode *
N : ArgumentSCC) {
1354 AccessAttr = meetAccessAttr(AccessAttr, K);
1360 for (ArgumentGraphNode *
N : ArgumentSCC) {
1363 Changed.
insert(
A->getParent());
1376 if (
ReturnInst *Ret = dyn_cast<ReturnInst>(BB.getTerminator()))
1377 FlowsToReturn.
insert(Ret->getReturnValue());
1379 for (
unsigned i = 0; i != FlowsToReturn.
size(); ++i) {
1380 Value *RetVal = FlowsToReturn[i];
1382 if (
Constant *
C = dyn_cast<Constant>(RetVal)) {
1383 if (!
C->isNullValue() && !isa<UndefValue>(
C))
1389 if (isa<Argument>(RetVal))
1392 if (
Instruction *RVI = dyn_cast<Instruction>(RetVal))
1393 switch (RVI->getOpcode()) {
1395 case Instruction::BitCast:
1396 case Instruction::GetElementPtr:
1397 case Instruction::AddrSpaceCast:
1398 FlowsToReturn.
insert(RVI->getOperand(0));
1400 case Instruction::Select: {
1402 FlowsToReturn.
insert(SI->getTrueValue());
1403 FlowsToReturn.
insert(SI->getFalseValue());
1406 case Instruction::PHI: {
1407 PHINode *PN = cast<PHINode>(RVI);
1409 FlowsToReturn.
insert(IncValue);
1414 case Instruction::Alloca:
1416 case Instruction::Call:
1417 case Instruction::Invoke: {
1418 CallBase &CB = cast<CallBase>(*RVI);
1443 if (
F->returnDoesNotAlias())
1449 if (!
F->hasExactDefinition())
1454 if (!
F->getReturnType()->isPointerTy())
1462 if (
F->returnDoesNotAlias() ||
1463 !
F->getReturnType()->isPointerTy())
1466 F->setReturnDoesNotAlias();
1480 bool &Speculative) {
1481 assert(
F->getReturnType()->isPointerTy() &&
1482 "nonnull only meaningful on pointer types");
1483 Speculative =
false;
1487 if (
auto *Ret = dyn_cast<ReturnInst>(BB.getTerminator()))
1488 FlowsToReturn.
insert(Ret->getReturnValue());
1490 auto &
DL =
F->getDataLayout();
1492 for (
unsigned i = 0; i != FlowsToReturn.
size(); ++i) {
1493 Value *RetVal = FlowsToReturn[i];
1506 case Instruction::BitCast:
1507 case Instruction::AddrSpaceCast:
1510 case Instruction::GetElementPtr:
1511 if (cast<GEPOperator>(RVI)->isInBounds()) {
1516 case Instruction::Select: {
1518 FlowsToReturn.
insert(SI->getTrueValue());
1519 FlowsToReturn.
insert(SI->getFalseValue());
1522 case Instruction::PHI: {
1523 PHINode *PN = cast<PHINode>(RVI);
1528 case Instruction::Call:
1529 case Instruction::Invoke: {
1530 CallBase &CB = cast<CallBase>(*RVI);
1534 if (Callee && SCCNodes.count(Callee)) {
1554 bool SCCReturnsNonNull =
true;
1560 if (
F->getAttributes().hasRetAttr(Attribute::NonNull))
1566 if (!
F->hasExactDefinition())
1571 if (!
F->getReturnType()->isPointerTy())
1574 bool Speculative =
false;
1580 <<
" as nonnull\n");
1581 F->addRetAttr(Attribute::NonNull);
1589 SCCReturnsNonNull =
false;
1592 if (SCCReturnsNonNull) {
1594 if (
F->getAttributes().hasRetAttr(Attribute::NonNull) ||
1595 !
F->getReturnType()->isPointerTy())
1598 LLVM_DEBUG(
dbgs() <<
"SCC marking " <<
F->getName() <<
" as nonnull\n");
1599 F->addRetAttr(Attribute::NonNull);
1614 if (Attrs.hasRetAttr(Attribute::NoUndef))
1620 if (!
F->hasExactDefinition())
1626 if (
F->hasFnAttribute(Attribute::SanitizeMemory))
1629 if (
F->getReturnType()->isVoidTy())
1636 Value *RetVal = Ret->getReturnValue();
1637 if (!isGuaranteedNotToBeUndefOrPoison(RetVal))
1643 if (Attrs.hasRetAttr(Attribute::NonNull) &&
1644 !isKnownNonZero(RetVal, DL))
1647 if (MaybeAlign Align = Attrs.getRetAlignment())
1648 if (RetVal->getPointerAlignment(DL) < *Align)
1651 Attribute Attr = Attrs.getRetAttr(Attribute::Range);
1652 if (Attr.isValid() &&
1653 !Attr.getRange().contains(
1654 computeConstantRange(RetVal, false)))
1659 F->addRetAttr(Attribute::NoUndef);
1674class AttributeInferer {
1677 struct InferenceDescriptor {
1689 std::function<void(
Function &)> SetAttribute;
1696 bool RequiresExactDefinition;
1699 std::function<
bool(
const Function &)> SkipFunc,
1701 std::function<
void(
Function &)> SetAttr,
1703 : SkipFunction(SkipFunc), InstrBreaksAttribute(InstrScan),
1704 SetAttribute(SetAttr), AKind(AK),
1705 RequiresExactDefinition(ReqExactDef) {}
1712 void registerAttrInference(InferenceDescriptor AttrInference) {
1713 InferenceDescriptors.
push_back(AttrInference);
1721void AttributeInferer::run(
const SCCNodeSet &SCCNodes,
1730 if (InferInSCC.
empty())
1735 if (
ID.SkipFunction(*
F))
1740 return F->isDeclaration() ||
1741 (
ID.RequiresExactDefinition && !
F->hasExactDefinition());
1748 InferInSCC, std::back_inserter(InferInThisFunc),
1749 [
F](
const InferenceDescriptor &
ID) {
return !
ID.SkipFunction(*
F); });
1751 if (InferInThisFunc.empty())
1757 if (!
ID.InstrBreaksAttribute(
I))
1762 return D.AKind == ID.AKind;
1768 if (InferInThisFunc.empty())
1773 if (InferInSCC.
empty())
1781 for (
auto &
ID : InferInSCC) {
1782 if (
ID.SkipFunction(*
F))
1785 ID.SetAttribute(*
F);
1789struct SCCNodesResult {
1790 SCCNodeSet SCCNodes;
1791 bool HasUnknownCall;
1798 const SCCNodeSet &SCCNodes) {
1799 const CallBase *CB = dyn_cast<CallBase>(&
I);
1808 if (!
I.mayThrow(
true))
1810 if (
const auto *CI = dyn_cast<CallInst>(&
I)) {
1811 if (
Function *Callee = CI->getCalledFunction()) {
1815 if (SCCNodes.contains(Callee))
1833 if (SCCNodes.contains(Callee))
1848 if (
auto *FI = dyn_cast<FenceInst>(
I))
1851 else if (isa<AtomicCmpXchgInst>(
I) || isa<AtomicRMWInst>(
I))
1853 else if (
auto *SI = dyn_cast<StoreInst>(
I))
1854 return !SI->isUnordered();
1855 else if (
auto *LI = dyn_cast<LoadInst>(
I))
1856 return !LI->isUnordered();
1871 auto *CB = dyn_cast<CallBase>(&
I);
1882 if (
auto *
MI = dyn_cast<MemIntrinsic>(&
I))
1883 if (!
MI->isVolatile())
1888 if (SCCNodes.contains(Callee))
1899 AttributeInferer AI;
1906 AI.registerAttrInference(AttributeInferer::InferenceDescriptor{
1907 Attribute::Convergent,
1909 [](
const Function &
F) {
return !
F.isConvergent(); },
1915 LLVM_DEBUG(
dbgs() <<
"Removing convergent attr from fn " <<
F.getName()
1917 F.setNotConvergent();
1921 AI.run(SCCNodes, Changed);
1930 AttributeInferer AI;
1938 AI.registerAttrInference(AttributeInferer::InferenceDescriptor{
1939 Attribute::NoUnwind,
1941 [](
const Function &
F) {
return F.doesNotThrow(); },
1948 <<
"Adding nounwind attr to fn " <<
F.getName() <<
"\n");
1949 F.setDoesNotThrow();
1961 AI.registerAttrInference(AttributeInferer::InferenceDescriptor{
1964 [](
const Function &
F) {
return F.doesNotFreeMemory(); },
1971 <<
"Adding nofree attr to fn " <<
F.getName() <<
"\n");
1972 F.setDoesNotFreeMemory();
1977 AI.registerAttrInference(AttributeInferer::InferenceDescriptor{
1980 [](
const Function &
F) {
return F.hasNoSync(); },
1987 <<
"Adding nosync attr to fn " <<
F.getName() <<
"\n");
1994 AI.run(SCCNodes, Changed);
2002 if (SCCNodes.size() != 1)
2006 if (!
F || !
F->hasExactDefinition() ||
F->doesNotRecurse())
2013 for (
auto &
I : BB.instructionsWithoutDebug())
2014 if (
auto *CB = dyn_cast<CallBase>(&
I)) {
2016 if (!Callee || Callee ==
F ||
2017 (!Callee->doesNotRecurse() &&
2018 !(Callee->isDeclaration() &&
2019 Callee->hasFnAttribute(Attribute::NoCallback))))
2027 F->setDoesNotRecurse();
2033 if (
auto *CB = dyn_cast<CallBase>(&
I))
2034 return CB->
hasFnAttr(Attribute::NoReturn);
2059 if (Visited.
insert(Succ).second)
2061 }
while (!Worklist.
empty());
2071 if (!
F || !
F->hasExactDefinition() ||
F->hasFnAttribute(Attribute::Naked) ||
2076 F->setDoesNotReturn();
2084 ColdPaths[&
F.front()] =
false;
2088 while (!Jobs.
empty()) {
2095 if (
auto *CB = dyn_cast<CallBase>(&
I))
2099 ColdPaths[BB] =
true;
2116 auto [Iter, Inserted] = ColdPaths.
try_emplace(Succ,
false);
2132 if (!
F || !
F->hasExactDefinition() ||
F->hasFnAttribute(Attribute::Naked) ||
2133 F->hasFnAttribute(Attribute::Cold) ||
F->hasFnAttribute(Attribute::Hot))
2138 F->addFnAttr(Attribute::Cold);
2150 if (!
F.hasExactDefinition())
2154 if (
F.mustProgress() &&
F.onlyReadsMemory())
2158 if (
F.isDeclaration())
2165 if (!Backedges.
empty())
2171 return I.willReturn();
2190 Res.HasUnknownCall =
false;
2192 if (!
F ||
F->hasOptNone() ||
F->hasFnAttribute(Attribute::Naked) ||
2193 F->isPresplitCoroutine()) {
2196 Res.HasUnknownCall =
true;
2203 if (!Res.HasUnknownCall) {
2205 if (
auto *CB = dyn_cast<CallBase>(&
I)) {
2207 Res.HasUnknownCall =
true;
2213 Res.SCCNodes.insert(
F);
2218template <
typename AARGetterT>
2221 bool ArgAttrsOnly) {
2225 if (Nodes.SCCNodes.empty())
2248 if (!Nodes.HasUnknownCall) {
2274 bool ArgAttrsOnly =
false;
2275 if (
C.size() == 1 && SkipNonRecursive) {
2278 ArgAttrsOnly =
true;
2295 auto ChangedFunctions =
2297 if (ChangedFunctions.empty())
2305 for (
Function *Changed : ChangedFunctions) {
2311 for (
auto *U : Changed->users()) {
2312 if (
auto *Call = dyn_cast<CallBase>(U)) {
2313 if (Call->getCalledFunction() == Changed)
2330 OS, MapClassName2PassName);
2331 if (SkipNonRecursive)
2332 OS <<
"<skip-non-recursive-function-attrs>";
2335template <
typename AARGetterT>
2349 assert(!
F.isDeclaration() &&
"Cannot deduce norecurse without a definition!");
2351 "This function has already been deduced as norecurs!");
2352 assert(
F.hasInternalLinkage() &&
2353 "Can only do top-down deduction for internal linkage functions!");
2363 for (
auto &U :
F.uses()) {
2364 auto *
I = dyn_cast<Instruction>(U.getUser());
2369 !CB->
getParent()->getParent()->doesNotRecurse())
2372 F.setDoesNotRecurse();
2390 if (SCC.size() != 1)
2392 Function &
F = SCC.begin()->getFunction();
2393 if (!
F.isDeclaration() && !
F.doesNotRecurse() &&
F.hasInternalLinkage())
2397 bool Changed =
false;
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Expand Atomic instructions
This file contains the simple types necessary to represent the attributes associated with functions a...
This is the interface for LLVM's primary stateless and local alias analysis.
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
This header provides classes for managing passes over SCCs of the call graph.
Analysis containing CSE Info
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...
This file defines the DenseMap class.
static bool runImpl(Function &F, const TargetLowering &TLI)
static void addNoReturnAttrs(const SCCNodeSet &SCCNodes, SmallSet< Function *, 8 > &Changed)
static Attribute::AttrKind determinePointerAccessAttrs(Argument *A, const SmallPtrSet< Argument *, 8 > &SCCNodes)
Returns Attribute::None, Attribute::ReadOnly or Attribute::ReadNone.
static cl::opt< bool > DisableNoFreeInference("disable-nofree-inference", cl::Hidden, cl::desc("Stop inferring nofree attribute during function-attrs pass"))
static bool inferInitializes(Argument &A, Function &F)
static bool allPathsGoThroughCold(Function &F)
static bool addAccessAttr(Argument *A, Attribute::AttrKind R)
static FunctionSummary * calculatePrevailingSummary(ValueInfo VI, DenseMap< ValueInfo, FunctionSummary * > &CachedPrevailingSummary, function_ref< bool(GlobalValue::GUID, const GlobalValueSummary *)> IsPrevailing)
static bool addArgumentAttrsFromCallsites(Function &F)
If a callsite has arguments that are also arguments to the parent function, try to propagate attribut...
static void addNoUndefAttrs(const SCCNodeSet &SCCNodes, SmallSet< Function *, 8 > &Changed)
Deduce noundef attributes for the SCC.
static bool isOrderedAtomic(Instruction *I)
static void addArgLocs(MemoryEffects &ME, const CallBase *Call, ModRefInfo ArgMR, AAResults &AAR)
static bool isFunctionMallocLike(Function *F, const SCCNodeSet &SCCNodes)
Tests whether a function is "malloc-like".
static bool canReturn(Function &F)
static void addArgumentAttrs(const SCCNodeSet &SCCNodes, SmallSet< Function *, 8 > &Changed, bool SkipInitializes)
Deduce nocapture attributes for the SCC.
static cl::opt< bool > DisableNoUnwindInference("disable-nounwind-inference", cl::Hidden, cl::desc("Stop inferring nounwind attribute during function-attrs pass"))
static void inferAttrsFromFunctionBodies(const SCCNodeSet &SCCNodes, SmallSet< Function *, 8 > &Changed)
Infer attributes from all functions in the SCC by scanning every instruction for compliance to the at...
static std::pair< MemoryEffects, MemoryEffects > checkFunctionMemoryAccess(Function &F, bool ThisBody, AAResults &AAR, const SCCNodeSet &SCCNodes)
Returns the memory access attribute for function F using AAR for AA results, where SCCNodes is the cu...
static bool InstrBreaksNonThrowing(Instruction &I, const SCCNodeSet &SCCNodes)
Helper for NoUnwind inference predicate InstrBreaksAttribute.
static bool basicBlockCanReturn(BasicBlock &BB)
static void addColdAttrs(const SCCNodeSet &SCCNodes, SmallSet< Function *, 8 > &Changed)
static bool isReturnNonNull(Function *F, const SCCNodeSet &SCCNodes, bool &Speculative)
Tests whether this function is known to not return null.
static cl::opt< bool > EnableNonnullArgPropagation("enable-nonnull-arg-prop", cl::init(true), cl::Hidden, cl::desc("Try to propagate nonnull argument attributes from callsites to " "caller functions."))
static void addMemoryAttrs(const SCCNodeSet &SCCNodes, AARGetterT &&AARGetter, SmallSet< Function *, 8 > &Changed)
Deduce readonly/readnone/writeonly attributes for the SCC.
static void addNoRecurseAttrs(const SCCNodeSet &SCCNodes, SmallSet< Function *, 8 > &Changed)
static void inferConvergent(const SCCNodeSet &SCCNodes, SmallSet< Function *, 8 > &Changed)
Attempt to remove convergent function attribute when possible.
static bool InstrBreaksNoSync(Instruction &I, const SCCNodeSet &SCCNodes)
static bool deduceFunctionAttributeInRPO(Module &M, LazyCallGraph &CG)
static SmallSet< Function *, 8 > deriveAttrsInPostOrder(ArrayRef< Function * > Functions, AARGetterT &&AARGetter, bool ArgAttrsOnly)
static bool InstrBreaksNoFree(Instruction &I, const SCCNodeSet &SCCNodes)
Helper for NoFree inference predicate InstrBreaksAttribute.
static void addNoAliasAttrs(const SCCNodeSet &SCCNodes, SmallSet< Function *, 8 > &Changed)
Deduce noalias attributes for the SCC.
static bool addNoRecurseAttrsTopDown(Function &F)
static bool instructionDoesNotReturn(Instruction &I)
static void addWillReturn(const SCCNodeSet &SCCNodes, SmallSet< Function *, 8 > &Changed)
static void addLocAccess(MemoryEffects &ME, const MemoryLocation &Loc, ModRefInfo MR, AAResults &AAR)
static cl::opt< bool > DisableThinLTOPropagation("disable-thinlto-funcattrs", cl::init(true), cl::Hidden, cl::desc("Don't propagate function-attrs in thinLTO"))
static SCCNodesResult createSCCNodeSet(ArrayRef< Function * > Functions)
static bool InstrBreaksNonConvergent(Instruction &I, const SCCNodeSet &SCCNodes)
Helper for non-Convergent inference predicate InstrBreaksAttribute.
static void addArgumentReturnedAttrs(const SCCNodeSet &SCCNodes, SmallSet< Function *, 8 > &Changed)
Deduce returned attributes for the SCC.
static bool functionWillReturn(const Function &F)
static void addNonNullAttrs(const SCCNodeSet &SCCNodes, SmallSet< Function *, 8 > &Changed)
Deduce nonnull attributes for the SCC.
Provides passes for computing function attributes based on interprocedural analyses.
This header defines various interfaces for pass management in LLVM.
This defines the Use class.
Implements a lazy call graph analysis and related passes for the new pass manager.
This file provides utility analysis objects describing memory locations.
ModuleSummaryIndex.h This file contains the declarations the classes that hold the module index and s...
FunctionAnalysisManager FAM
This file builds on the ADT/GraphTraits.h file to build a generic graph post order iterator.
Remove Loads Into Fake Uses
This builds on the llvm/ADT/GraphTraits.h file to find the strongly connected components (SCCs) of a ...
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file implements a set that has insertion order iteration characteristics.
This file defines the SmallPtrSet class.
This file defines the SmallSet class.
This file defines the SmallVector class.
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.
ModRefInfo getModRefInfoMask(const MemoryLocation &Loc, bool IgnoreLocals=false)
Returns a bitmask that should be unconditionally applied to the ModRef info of a memory location.
MemoryEffects getMemoryEffects(const CallBase *Call)
Return the behavior of the given call site.
Class for arbitrary precision integers.
This templated class represents "all analyses that operate over <a particular IR unit>" (e....
A container for analyses that lazily runs them and caches their results.
void invalidate(IRUnitT &IR, const PreservedAnalyses &PA)
Invalidate cached analyses for an IR unit.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
This class represents an incoming formal argument to a Function.
void addAttr(Attribute::AttrKind Kind)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
static Attribute get(LLVMContext &Context, AttrKind Kind, uint64_t Val=0)
Return a uniquified Attribute object.
ArrayRef< ConstantRange > getValueAsConstantRangeList() const
Return the attribute's value as a ConstantRange array.
AttrKind
This enumeration lists the attributes that can be associated with parameters, function results,...
@ None
No attributes have been set.
static Attribute getWithCaptureInfo(LLVMContext &Context, CaptureInfo CI)
LLVM Basic Block Representation.
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...
Represents analyses that only rely on functions' control flow.
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
MemoryEffects getMemoryEffects() const
bool doesNotCapture(unsigned OpNo) const
Determine whether this data operand is not captured.
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
bool doesNotAccessMemory(unsigned OpNo) const
bool hasFnAttr(Attribute::AttrKind Kind) const
Determine whether this call has the given attribute.
bool hasRetAttr(Attribute::AttrKind Kind) const
Determine whether the return value has the given attribute.
unsigned getDataOperandNo(Value::const_user_iterator UI) const
Given a value use iterator, return the data operand corresponding to it.
bool paramHasAttr(unsigned ArgNo, Attribute::AttrKind Kind) const
Determine whether the argument or parameter has the given attribute.
Attribute getParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) const
Get the attribute of a given kind from a given arg.
bool dataOperandHasImpliedAttr(unsigned i, Attribute::AttrKind Kind) const
Return true if the data operand at index i has the attribute A.
bool isByValArgument(unsigned ArgNo) const
Determine whether this argument is passed by value.
bool onlyWritesMemory(unsigned OpNo) const
bool isCallee(Value::const_user_iterator UI) const
Determine whether the passed iterator points to the callee operand's Use.
bool onlyReadsMemory(unsigned OpNo) const
Value * getArgOperand(unsigned i) const
bool isConvergent() const
Determine if the invoke is convergent.
unsigned getArgOperandNo(const Use *U) const
Given a use for a arg operand, get the arg operand number that corresponds to it.
unsigned arg_size() const
bool isArgOperand(const Use *U) const
bool hasOperandBundles() const
Return true if this User has any operand bundles.
A node in the call graph for a module.
CallGraphSCC - This is a single SCC that a CallGraphSCCPass is run on.
static CaptureInfo none()
Create CaptureInfo that does not capture any components of the pointer.
This class represents a list of constant ranges.
void subtract(const ConstantRange &SubRange)
void insert(const ConstantRange &NewRange)
Insert a new range to Ranges and keep the list ordered.
bool empty() const
Return true if this list contains no members.
ArrayRef< ConstantRange > rangesRef() const
ConstantRangeList intersectWith(const ConstantRangeList &CRL) const
Return the range list that results from the intersection of this ConstantRangeList with another Const...
ConstantRangeList unionWith(const ConstantRangeList &CRL) const
Return the range list that results from the union of this ConstantRangeList with another ConstantRang...
This class represents a range of values.
This is an important base class in LLVM.
A parsed version of the target data layout string in and methods for querying it.
iterator find(const_arg_type_t< KeyT > Val)
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
A proxy from a FunctionAnalysisManager to an SCC.
Function summary information to aid decisions and implementation of importing.
ArrayRef< EdgeTy > calls() const
Return the list of <CalleeValueInfo, CalleeInfo> pairs.
FFlags fflags() const
Get function summary flags.
Function and variable summary information to aid decisions and implementation of importing.
static bool isWeakAnyLinkage(LinkageTypes Linkage)
static bool isLinkOnceAnyLinkage(LinkageTypes Linkage)
static bool isLocalLinkage(LinkageTypes Linkage)
static bool isWeakODRLinkage(LinkageTypes Linkage)
static bool isAvailableExternallyLinkage(LinkageTypes Linkage)
static bool isExternalLinkage(LinkageTypes Linkage)
static bool isLinkOnceODRLinkage(LinkageTypes Linkage)
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
An analysis pass which computes the call graph for a module.
A node in the call graph.
A RefSCC of the call graph.
An SCC of the call graph.
A lazily constructed view of the call graph of a module.
iterator_range< postorder_ref_scc_iterator > postorder_ref_sccs()
MemoryEffectsBase getWithoutLoc(Location Loc) const
Get new MemoryEffectsBase with NoModRef on the given Loc.
bool doesNotAccessMemory() const
Whether this function accesses no memory.
static MemoryEffectsBase argMemOnly(ModRefInfo MR=ModRefInfo::ModRef)
Create MemoryEffectsBase that can only access argument memory.
static MemoryEffectsBase inaccessibleMemOnly(ModRefInfo MR=ModRefInfo::ModRef)
Create MemoryEffectsBase that can only access inaccessible memory.
ModRefInfo getModRef(Location Loc) const
Get ModRefInfo for the given Location.
static MemoryEffectsBase none()
Create MemoryEffectsBase that cannot read or write any memory.
static MemoryEffectsBase unknown()
Create MemoryEffectsBase that can read and write any memory.
Representation for a specific memory location.
static MemoryLocation getBeforeOrAfter(const Value *Ptr, const AAMDNodes &AATags=AAMDNodes())
Return a location that may access any location before or after Ptr, while remaining within the underl...
const Value * Ptr
The address of the start of the location.
static std::optional< MemoryLocation > getOrNone(const Instruction *Inst)
Class to hold module path string table and global value map, and encapsulate methods for operating on...
A Module instance is used to store all the information related to an LLVM module.
op_range incoming_values()
Value * getIncomingValue(unsigned i) const
Return incoming value number x.
unsigned getNumIncomingValues() const
Return the number of incoming edges.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
void preserveSet()
Mark an analysis set as preserved.
void preserve()
Mark an analysis as preserved.
Return a value (possibly void), from a function.
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
This class represents the LLVM 'select' instruction.
size_type size() const
Determine the number of elements in the SetVector.
bool insert(const value_type &X)
Insert a new element into the SetVector.
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.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
A SetVector that performs no allocations if smaller than a certain size.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
typename SuperClass::iterator iterator
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
The instances of the Type class are immutable: once they are created, they are never changed.
A Use represents the edge between a Value definition and its users.
Value * getOperand(unsigned i) const
LLVM Value Representation.
iterator_range< use_iterator > uses()
constexpr ScalarTy getFixedValue() const
constexpr bool isScalable() const
Returns whether the quantity is scaled by a runtime quantity (vscale).
An efficient, type-erasing, non-owning reference to a callable.
const ParentTy * getParent() const
This class implements an extremely fast bulk output stream that can only output to a stream.
Enumerate the SCCs of a directed graph in reverse topological order of the SCC DAG.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ C
The default llvm calling convention, compatible with C.
@ SingleThread
Synchronized with respect to signal handlers executing in the same thread.
initializer< Ty > init(const Ty &Val)
PointerTypeMap run(const Module &M)
Compute the PointerTypeMap for the module M.
constexpr uint64_t PointerSize
aarch64 pointer size.
const_iterator begin(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Get begin iterator over path.
const_iterator end(StringRef path LLVM_LIFETIME_BOUND)
Get end iterator over path.
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.
MemoryEffects computeFunctionBodyMemoryAccess(Function &F, AAResults &AAR)
Returns the memory access properties of this copy of the function.
auto successors(const MachineBasicBlock *BB)
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
scc_iterator< T > scc_begin(const T &G)
Construct the begin iterator for a deduced graph type T.
iterator_range< po_iterator< T > > post_order(const T &G)
bool thinLTOPropagateFunctionAttrs(ModuleSummaryIndex &Index, function_ref< bool(GlobalValue::GUID, const GlobalValueSummary *)> isPrevailing)
Propagate function attributes for function summaries along the index's callgraph during thinlink.
OutputIt copy_if(R &&Range, OutputIt Out, UnaryPredicate P)
Provide wrappers to std::copy_if which take ranges instead of having to pass begin/end explicitly.
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
auto reverse(ContainerTy &&C)
bool isIntrinsicReturningPointerAliasingArgumentWithoutCapturing(const CallBase *Call, bool MustPreserveNullness)
{launder,strip}.invariant.group returns pointer that aliases its argument, and it only captures point...
bool isModSet(const ModRefInfo MRI)
void sort(IteratorTy Start, IteratorTy End)
MemoryEffectsBase< IRMemLocation > MemoryEffects
Summary of how a function affects memory in the program.
bool PointerMayBeCaptured(const Value *V, bool ReturnCaptures, bool StoreCaptures, unsigned MaxUsesToExplore=0)
PointerMayBeCaptured - Return true if this pointer value may be captured by the enclosing function (w...
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
bool isKnownNonZero(const Value *V, const SimplifyQuery &Q, unsigned Depth=0)
Return true if the given value is known to be non-zero when defined.
ModRefInfo
Flags indicating whether a memory access modifies or references memory.
@ ArgMem
Access to memory via argument pointers.
const Value * getUnderlyingObjectAggressive(const Value *V)
Like getUnderlyingObject(), but will try harder to find a single underlying object.
bool isGuaranteedToTransferExecutionToSuccessor(const Instruction *I)
Return true if this function can prove that the instruction I will always transfer execution to one o...
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
bool inferAttributesFromOthers(Function &F)
If we can infer one attribute from another on the declaration of a function, explicitly materialize t...
bool isNoModRef(const ModRefInfo MRI)
void FindFunctionBackedges(const Function &F, SmallVectorImpl< std::pair< const BasicBlock *, const BasicBlock * > > &Result)
Analyze the specified function to find all of the loop backedges in the function and return them.
bool isIdentifiedObject(const Value *V)
Return true if this pointer refers to a distinct and identifiable object.
bool isRefSet(const ModRefInfo MRI)
Support structure for SCC passes to communicate updates the call graph back to the CGSCC pass manager...
This callback is used in conjunction with PointerMayBeCaptured.
virtual void tooManyUses()=0
tooManyUses - The depth of traversal has breached a limit.
virtual bool captured(const Use *U)=0
captured - Information about the pointer was captured by the user of use U.
Flags specific to function summaries.
SmallVectorImpl< ArgumentGraphNode * >::iterator ChildIteratorType
static ChildIteratorType child_begin(NodeRef N)
static ChildIteratorType child_end(NodeRef N)
ArgumentGraphNode * NodeRef
static NodeRef getEntryNode(NodeRef A)
static ChildIteratorType nodes_end(ArgumentGraph *AG)
static NodeRef getEntryNode(ArgumentGraph *AG)
static ChildIteratorType nodes_begin(ArgumentGraph *AG)
A CRTP mix-in to automatically provide informational APIs needed for passes.
PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG, CGSCCUpdateResult &UR)
void printPipeline(raw_ostream &OS, function_ref< StringRef(StringRef)> MapClassName2PassName)
Struct that holds a reference to a particular GUID in a global value summary.