73#define DEBUG_TYPE "function-attrs"
75STATISTIC(NumMemoryAttr,
"Number of functions with improved memory attribute");
76STATISTIC(NumCapturesNone,
"Number of arguments marked captures(none)");
77STATISTIC(NumCapturesPartial,
"Number of arguments marked with captures "
78 "attribute other than captures(none)");
79STATISTIC(NumReturned,
"Number of arguments marked returned");
80STATISTIC(NumReadNoneArg,
"Number of arguments marked readnone");
81STATISTIC(NumReadOnlyArg,
"Number of arguments marked readonly");
82STATISTIC(NumWriteOnlyArg,
"Number of arguments marked writeonly");
83STATISTIC(NumNoAlias,
"Number of function returns marked noalias");
84STATISTIC(NumNonNullReturn,
"Number of function returns marked nonnull");
85STATISTIC(NumNoUndefReturn,
"Number of function returns marked noundef");
86STATISTIC(NumNoRecurse,
"Number of functions marked as norecurse");
87STATISTIC(NumNoUnwind,
"Number of functions marked as nounwind");
88STATISTIC(NumNoFree,
"Number of functions marked as nofree");
89STATISTIC(NumNoFreeArg,
"Number of arguments marked as nofree");
90STATISTIC(NumWillReturn,
"Number of functions marked as willreturn");
91STATISTIC(NumNoSync,
"Number of functions marked as nosync");
92STATISTIC(NumCold,
"Number of functions marked as cold");
95 "Number of functions marked as norecurse during thinlink");
97 "Number of functions marked as nounwind during thinlink");
101 cl::desc(
"Try to propagate nonnull and nofpclass argument attributes from "
102 "callsites to caller functions."));
106 cl::desc(
"Stop inferring nounwind attribute during function-attrs pass"));
110 cl::desc(
"Stop inferring nofree attribute during function-attrs pass"));
114 cl::desc(
"Don't propagate function-attrs in thinLTO"));
120 ++NumCapturesPartial;
154 if (!Arg->getType()->isPtrOrPtrVectorTy())
175static std::pair<MemoryEffects, MemoryEffects>
177 const SCCNodeSet &SCCNodes) {
203 if (
F.getAttributes().hasAttrSomewhere(Attribute::InAlloca) ||
204 F.getAttributes().hasAttrSomewhere(Attribute::Preallocated))
217 if (!
Call->hasOperandBundles() &&
Call->getCalledFunction() &&
218 SCCNodes.count(
Call->getCalledFunction())) {
238 AddNonArgMemoryEffects(CallME);
260 AddNonArgMemoryEffects(InstME);
264 return {OrigME & ME, RecursiveArgME};
273template <
typename AARGetterT>
284 auto [FnME, FnRecursiveArgME] =
287 RecursiveArgME |= FnRecursiveArgME;
301 if (NewME != OldME) {
303 F->setMemoryEffects(NewME);
307 A.removeAttr(Attribute::Writable);
321 auto [It, Inserted] = CachedPrevailingSummary.
try_emplace(VI);
368 for (
const auto &GVS : VI.getSummaryList()) {
374 if (!FS || FS->fflags().HasUnknownCall)
377 const auto &
Linkage = GVS->linkage();
382 <<
"ThinLTO FunctionAttrs: Multiple Local Linkage, bailing on "
384 << VI.name() <<
" from " << FS->modulePath() <<
". Previous module "
385 <<
Local->modulePath() <<
"\n");
390 assert(IsPrevailing(VI.getGUID(), GVS.get()) || GVS->wasPromoted());
397 if (IsPrevailing(VI.getGUID(), GVS.get())) {
407 auto &CPS = CachedPrevailingSummary[VI];
411 }
else if (Prevailing) {
431 auto PropagateAttributes = [&](std::vector<ValueInfo> &SCCNodes) {
434 InferredFlags.
NoRecurse = (SCCNodes.size() == 1);
437 for (
auto &V : SCCNodes) {
448 for (
const auto &Callee : CallerSummary->
calls()) {
450 Callee.first, CachedPrevailingSummary, IsPrevailing);
468 for (
auto &V : SCCNodes) {
470 LLVM_DEBUG(
dbgs() <<
"ThinLTO FunctionAttrs: Propagated NoRecurse to "
471 << V.name() <<
"\n");
472 ++NumThinLinkNoRecurse;
476 LLVM_DEBUG(
dbgs() <<
"ThinLTO FunctionAttrs: Propagated NoUnwind to "
477 << V.name() <<
"\n");
478 ++NumThinLinkNoUnwind;
481 for (
const auto &S : V.getSummaryList()) {
497 std::vector<ValueInfo> Nodes(*
I);
498 PropagateAttributes(Nodes);
508struct ArgumentGraphNode {
519 using ArgumentMapTy = std::map<Argument *, ArgumentGraphNode>;
521 ArgumentMapTy ArgumentMap;
529 ArgumentGraphNode SyntheticRoot;
532 ArgumentGraph() { SyntheticRoot.Definition =
nullptr; }
536 iterator
begin() {
return SyntheticRoot.Uses.begin(); }
537 iterator
end() {
return SyntheticRoot.Uses.end(); }
538 ArgumentGraphNode *getEntryNode() {
return &SyntheticRoot; }
540 ArgumentGraphNode *operator[](Argument *
A) {
541 ArgumentGraphNode &
Node = ArgumentMap[
A];
543 SyntheticRoot.Uses.push_back(&Node);
552 ArgumentUsesTracker(
const SCCNodeSet &SCCNodes) : SCCNodes(SCCNodes) {}
556 Action captured(
const Use *U, UseCaptureInfo UseCI)
override {
557 if (updateCaptureInfo(U, UseCI.
UseCC)) {
566 return ContinueIgnoringReturn;
577 CI |= CaptureInfo(CC);
582 if (!
F || !
F->hasExactDefinition() || !SCCNodes.count(
F)) {
583 CI |= CaptureInfo(CC);
597 CI |= CaptureInfo(CC);
601 if (UseIndex >=
F->arg_size()) {
602 assert(
F->isVarArg() &&
"More params than args in non-varargs call");
603 CI |= CaptureInfo(CC);
609 Uses.push_back(&*std::next(
F->arg_begin(), UseIndex));
619 const SCCNodeSet &SCCNodes;
627 std::optional<int64_t> Offset;
634struct ArgumentAccessInfo {
635 enum class AccessType : uint8_t {
Write, WriteWithSideEffect,
Read,
Unknown };
636 AccessType ArgAccessType;
637 ConstantRangeList AccessRanges;
641struct UsesPerBlockInfo {
642 SmallDenseMap<Instruction *, ArgumentAccessInfo, 4> Insts;
643 bool HasWrites =
false;
644 bool HasUnknownAccess =
false;
648struct ArgumentUsesSummary {
649 bool HasAnyWrite =
false;
650 bool HasWriteOutsideEntryBB =
false;
651 SmallDenseMap<const BasicBlock *, UsesPerBlockInfo, 16> UsesPerBlock;
654ArgumentAccessInfo getArgumentAccessInfo(
const Instruction *
I,
655 const ArgumentUse &ArgUse,
657 auto GetTypeAccessRange =
659 std::optional<int64_t>
Offset) -> std::optional<ConstantRange> {
673 auto GetConstantIntRange =
675 std::optional<int64_t>
Offset) -> std::optional<ConstantRange> {
677 if (ConstantLength &&
Offset) {
678 int64_t
Len = ConstantLength->getSExtValue();
696 if (
SI->isSimple() && &
SI->getOperandUse(1) == ArgUse.U) {
701 if (
auto TypeAccessRange =
702 GetTypeAccessRange(
SI->getAccessType(), ArgUse.Offset))
703 AccessRanges.
insert(*TypeAccessRange);
704 return {ArgumentAccessInfo::AccessType::Write, std::move(AccessRanges)};
707 if (LI->isSimple()) {
708 assert(&LI->getOperandUse(0) == ArgUse.U);
712 if (
auto TypeAccessRange =
713 GetTypeAccessRange(LI->getAccessType(), ArgUse.Offset))
714 return {ArgumentAccessInfo::AccessType::Read, {*TypeAccessRange}};
717 if (!MemSet->isVolatile()) {
719 if (
auto AccessRange =
720 GetConstantIntRange(MemSet->getLength(), ArgUse.Offset))
721 AccessRanges.
insert(*AccessRange);
722 return {ArgumentAccessInfo::AccessType::Write, AccessRanges};
725 if (!MTI->isVolatile()) {
726 if (&MTI->getOperandUse(0) == ArgUse.U) {
728 if (
auto AccessRange =
729 GetConstantIntRange(MTI->getLength(), ArgUse.Offset))
730 AccessRanges.
insert(*AccessRange);
731 return {ArgumentAccessInfo::AccessType::Write, AccessRanges};
732 }
else if (&MTI->getOperandUse(1) == ArgUse.U) {
733 if (
auto AccessRange =
734 GetConstantIntRange(MTI->getLength(), ArgUse.Offset))
735 return {ArgumentAccessInfo::AccessType::Read, {*AccessRange}};
742 bool IsInitialize = CB->
paramHasAttr(ArgNo, Attribute::Initializes);
743 if (IsInitialize && ArgUse.Offset) {
747 ? ArgumentAccessInfo::AccessType::Write
748 : ArgumentAccessInfo::AccessType::WriteWithSideEffect;
754 CR.getUpper() + *ArgUse.Offset));
755 return {
Access, AccessRanges};
760 return {ArgumentAccessInfo::AccessType::Unknown, {}};
765 auto &
DL =
F.getParent()->getDataLayout();
767 DL.getIndexSizeInBits(
A.getType()->getPointerAddressSpace());
768 ArgumentUsesSummary
Result;
772 for (
Use &U :
A.uses())
778 auto *BB =
I->getParent();
779 auto &BBInfo =
Result.UsesPerBlock[BB];
780 auto [It,
Inserted] = BBInfo.Insts.try_emplace(
I);
781 auto &IInfo = It->second;
786 IInfo = {ArgumentAccessInfo::AccessType::Unknown, {}};
787 BBInfo.HasUnknownAccess =
true;
791 IInfo = std::move(Info);
792 BBInfo.HasUnknownAccess |=
793 IInfo.ArgAccessType == ArgumentAccessInfo::AccessType::Unknown;
795 (IInfo.ArgAccessType == ArgumentAccessInfo::AccessType::Write ||
796 IInfo.ArgAccessType ==
797 ArgumentAccessInfo::AccessType::WriteWithSideEffect) &&
798 !IInfo.AccessRanges.empty();
799 BBInfo.HasWrites |= InfoHasWrites;
800 return InfoHasWrites;
805 while (!Worklist.
empty()) {
807 User *U = ArgUse.U->getUser();
811 std::optional<int64_t> NewOffset = std::nullopt;
815 NewOffset = *ArgUse.Offset +
Offset.getSExtValue();
817 for (
Use &U :
GEP->uses())
823 bool HasWrite = UpdateUseInfo(
I, getArgumentAccessInfo(
I, ArgUse,
DL));
825 Result.HasAnyWrite |= HasWrite;
827 if (HasWrite &&
I->getParent() != &EntryBB)
828 Result.HasWriteOutsideEntryBB =
true;
884 if (
A->hasInAllocaAttr() ||
A->hasPreallocatedAttr())
889 for (
Use &U :
A->uses()) {
894 while (!Worklist.
empty()) {
920 for (
Use &UU :
I->uses())
921 if (Visited.
insert(&UU).second)
942 SCCNodes.
count(
F->getArg(UseIndex)))
964 Props.
IsRead |=
I->mayReadFromMemory();
965 Props.
IsWrite |=
I->mayWriteToMemory();
980 if (!
F->hasExactDefinition())
983 if (
F->getReturnType()->isVoidTy())
987 if (
F->getAttributes().hasAttrSomewhere(Attribute::Returned))
990 auto FindRetArg = [&]() ->
Argument * {
998 if (!RetVal || RetVal->getType() !=
F->getReturnType())
1003 else if (RetArg != RetVal)
1010 if (
Argument *RetArg = FindRetArg()) {
1011 RetArg->addAttr(Attribute::Returned);
1039 for (
auto &CSArg : CalledFunc->args()) {
1040 unsigned ArgNo = CSArg.getArgNo();
1045 if (CSArg.hasNonNullAttr(
false)) {
1049 if (!FArg->hasNonNullAttr()) {
1050 FArg->addAttr(Attribute::NonNull);
1058 if ((CSNoFPClass | ArgNoFPClass) != ArgNoFPClass) {
1060 FArg->getContext(), CSNoFPClass | ArgNoFPClass));
1075 assert(
A &&
"Argument must not be null.");
1078 if (!Props.
IsFree && !
A->hasAttribute(Attribute::NoFree)) {
1080 A->addAttr(Attribute::NoFree);
1089 Attr = Attribute::ReadOnly;
1091 Attr = Attribute::WriteOnly;
1093 Attr = Attribute::ReadNone;
1096 if (
A->hasAttribute(Attr))
1101 A->removeAttr(Attribute::WriteOnly);
1102 A->removeAttr(Attribute::ReadOnly);
1103 A->removeAttr(Attribute::ReadNone);
1105 if (Attr == Attribute::ReadNone || Attr == Attribute::ReadOnly)
1106 A->removeAttr(Attribute::Writable);
1108 if (Attr == Attribute::ReadOnly)
1110 else if (Attr == Attribute::WriteOnly)
1118 auto ArgumentUses = collectArgumentUsesPerBlock(
A,
F);
1120 if (!ArgumentUses.HasAnyWrite)
1123 auto &UsesPerBlock = ArgumentUses.UsesPerBlock;
1132 auto UPB = UsesPerBlock.find(BB);
1139 if (UPB == UsesPerBlock.end() || !UPB->second.HasUnknownAccess) {
1140 bool HasAddedSuccessor =
false;
1142 if (
auto SuccI = Initialized.
find(Succ); SuccI != Initialized.
end()) {
1143 if (HasAddedSuccessor) {
1146 CRL = SuccI->second;
1147 HasAddedSuccessor =
true;
1156 if (UPB != UsesPerBlock.end()) {
1160 sort(Insts, [](std::pair<Instruction *, ArgumentAccessInfo> &
LHS,
1161 std::pair<Instruction *, ArgumentAccessInfo> &
RHS) {
1162 return LHS.first->comesBefore(
RHS.first);
1167 for (
auto &[
_, Info] :
reverse(Insts)) {
1168 if (Info.ArgAccessType == ArgumentAccessInfo::AccessType::Unknown ||
1169 Info.ArgAccessType ==
1170 ArgumentAccessInfo::AccessType::WriteWithSideEffect)
1172 if (!Info.AccessRanges.empty()) {
1173 if (Info.ArgAccessType == ArgumentAccessInfo::AccessType::Write ||
1174 Info.ArgAccessType ==
1175 ArgumentAccessInfo::AccessType::WriteWithSideEffect) {
1178 assert(Info.ArgAccessType == ArgumentAccessInfo::AccessType::Read);
1179 for (
const auto &ReadRange : Info.AccessRanges)
1191 bool OnlyScanEntryBlock = !ArgumentUses.HasWriteOutsideEntryBB;
1192 if (!OnlyScanEntryBlock)
1193 if (
auto EntryUPB = UsesPerBlock.find(&EntryBB);
1194 EntryUPB != UsesPerBlock.end())
1195 OnlyScanEntryBlock = EntryUPB->second.HasUnknownAccess;
1196 if (OnlyScanEntryBlock) {
1197 EntryCRL = VisitBlock(&EntryBB);
1198 if (EntryCRL.
empty())
1209 Initialized[BB] = CRL;
1212 auto EntryCRLI = Initialized.
find(&EntryBB);
1213 if (EntryCRLI == Initialized.
end())
1216 EntryCRL = EntryCRLI->second;
1220 "should have bailed already if EntryCRL is empty");
1222 if (
A.hasAttribute(Attribute::Initializes)) {
1224 A.getAttribute(Attribute::Initializes).getValueAsConstantRangeList();
1225 if (PreviousCRL == EntryCRL)
1227 EntryCRL = EntryCRL.
unionWith(PreviousCRL);
1239 bool SkipInitializes) {
1242 auto DetermineAccessAttrsForSingleton = [](
Argument *
A) {
1254 if (!
F->hasExactDefinition())
1262 if (
F->onlyReadsMemory() &&
F->doesNotThrow() &&
F->willReturn() &&
1263 F->getReturnType()->isVoidTy()) {
1265 if (
A.getType()->isPointerTy() && !
A.hasNoCaptureAttr()) {
1276 if (!
A.getType()->isPointerTy())
1278 bool HasNonLocalUses =
false;
1279 CaptureInfo OrigCI =
A.getAttributes().getCaptureInfo();
1281 ArgumentUsesTracker Tracker(SCCNodes);
1284 if (NewCI != OrigCI) {
1285 if (Tracker.Uses.empty()) {
1294 ArgumentGraphNode *
Node = AG[&
A];
1297 Node->Uses.push_back(AG[
Use]);
1299 HasNonLocalUses =
true;
1305 if (!HasNonLocalUses && !
A.onlyReadsMemory()) {
1310 if (DetermineAccessAttrsForSingleton(&
A))
1313 if (!SkipInitializes && !
A.onlyReadsMemory()) {
1328 const std::vector<ArgumentGraphNode *> &ArgumentSCC = *
I;
1329 if (ArgumentSCC.size() == 1) {
1330 if (!ArgumentSCC[0]->Definition)
1334 if (ArgumentSCC[0]->
Uses.size() == 1 &&
1335 ArgumentSCC[0]->Uses[0] == ArgumentSCC[0]) {
1336 Argument *
A = ArgumentSCC[0]->Definition;
1337 CaptureInfo OrigCI =
A->getAttributes().getCaptureInfo();
1339 if (NewCI != OrigCI) {
1346 if (DetermineAccessAttrsForSingleton(
A))
1355 for (ArgumentGraphNode *
I : ArgumentSCC) {
1356 ArgumentSCCNodes.
insert(
I->Definition);
1363 for (ArgumentGraphNode *
N : ArgumentSCC) {
1364 for (ArgumentGraphNode *
Use :
N->Uses) {
1366 if (ArgumentSCCNodes.
count(
A))
1377 for (ArgumentGraphNode *
N : ArgumentSCC) {
1379 CaptureInfo OrigCI =
A->getAttributes().getCaptureInfo();
1381 if (NewCI != OrigCI) {
1392 for (ArgumentGraphNode *
N : ArgumentSCC) {
1393 if (DetermineAccessAttrsForSingleton(
N->Definition))
1394 Changed.insert(
N->Definition->getParent());
1411 for (ArgumentGraphNode *
N : ArgumentSCC) {
1419 for (ArgumentGraphNode *
N : ArgumentSCC) {
1436 FlowsToReturn.
insert(Ret->getReturnValue());
1438 for (
unsigned i = 0; i != FlowsToReturn.
size(); ++i) {
1439 Value *RetVal = FlowsToReturn[i];
1452 switch (RVI->getOpcode()) {
1454 case Instruction::BitCast:
1455 case Instruction::GetElementPtr:
1456 case Instruction::AddrSpaceCast:
1457 FlowsToReturn.
insert(RVI->getOperand(0));
1459 case Instruction::Select: {
1461 FlowsToReturn.
insert(
SI->getTrueValue());
1462 FlowsToReturn.
insert(
SI->getFalseValue());
1465 case Instruction::PHI: {
1472 case Instruction::Alloca:
1474 case Instruction::Call:
1475 case Instruction::Invoke: {
1501 if (
F->returnDoesNotAlias())
1507 if (!
F->hasExactDefinition())
1512 if (!
F->getReturnType()->isPointerTy())
1520 if (
F->returnDoesNotAlias() ||
1521 !
F->getReturnType()->isPointerTy())
1524 F->setReturnDoesNotAlias();
1538 bool &Speculative) {
1539 assert(
F->getReturnType()->isPointerTy() &&
1540 "nonnull only meaningful on pointer types");
1541 Speculative =
false;
1546 FlowsToReturn.
insert(Ret->getReturnValue());
1548 auto &
DL =
F->getDataLayout();
1550 for (
unsigned i = 0; i != FlowsToReturn.
size(); ++i) {
1551 Value *RetVal = FlowsToReturn[i];
1564 case Instruction::BitCast:
1565 case Instruction::AddrSpaceCast:
1568 case Instruction::GetElementPtr:
1574 case Instruction::Select: {
1576 FlowsToReturn.
insert(
SI->getTrueValue());
1577 FlowsToReturn.
insert(
SI->getFalseValue());
1580 case Instruction::PHI: {
1586 case Instruction::Call:
1587 case Instruction::Invoke: {
1592 if (Callee && SCCNodes.count(Callee)) {
1612 bool SCCReturnsNonNull =
true;
1618 if (
F->getAttributes().hasRetAttr(Attribute::NonNull))
1624 if (!
F->hasExactDefinition())
1629 if (!
F->getReturnType()->isPointerTy())
1632 bool Speculative =
false;
1638 <<
" as nonnull\n");
1639 F->addRetAttr(Attribute::NonNull);
1647 SCCReturnsNonNull =
false;
1650 if (SCCReturnsNonNull) {
1652 if (
F->getAttributes().hasRetAttr(Attribute::NonNull) ||
1653 !
F->getReturnType()->isPointerTy())
1656 LLVM_DEBUG(
dbgs() <<
"SCC marking " <<
F->getName() <<
" as nonnull\n");
1657 F->addRetAttr(Attribute::NonNull);
1671 AttributeList Attrs =
F->getAttributes();
1672 if (Attrs.hasRetAttr(Attribute::NoUndef))
1678 if (!
F->hasExactDefinition())
1684 if (
F->hasFnAttribute(Attribute::SanitizeMemory))
1687 if (
F->getReturnType()->isVoidTy())
1694 Value *RetVal = Ret->getReturnValue();
1701 if (Attrs.hasRetAttr(Attribute::NonNull) &&
1709 Attribute Attr = Attrs.getRetAttr(Attribute::Range);
1716 FPClassTest AttrFPClass = Attrs.getRetNoFPClass();
1717 if (AttrFPClass !=
fcNone) {
1725 F->addRetAttr(Attribute::NoUndef);
1740class AttributeInferer {
1743 struct InferenceDescriptor {
1749 std::function<bool(
const Function &)> SkipFunction;
1752 std::function<bool(Instruction &)> InstrBreaksAttribute;
1755 std::function<void(Function &)> SetAttribute;
1758 Attribute::AttrKind AKind;
1762 bool RequiresExactDefinition;
1764 InferenceDescriptor(Attribute::AttrKind AK,
1765 std::function<
bool(
const Function &)> SkipFunc,
1766 std::function<
bool(Instruction &)> InstrScan,
1767 std::function<
void(Function &)> SetAttr,
1769 : SkipFunction(SkipFunc), InstrBreaksAttribute(InstrScan),
1770 SetAttribute(SetAttr), AKind(AK),
1771 RequiresExactDefinition(ReqExactDef) {}
1778 void registerAttrInference(InferenceDescriptor AttrInference) {
1779 InferenceDescriptors.push_back(AttrInference);
1782 void run(
const SCCNodeSet &SCCNodes, SmallPtrSet<Function *, 8> &
Changed);
1787void AttributeInferer::run(
const SCCNodeSet &SCCNodes,
1793 for (Function *
F : SCCNodes) {
1796 if (InferInSCC.
empty())
1801 if (
ID.SkipFunction(*
F))
1806 return F->isDeclaration() ||
1807 (
ID.RequiresExactDefinition && !
F->hasExactDefinition());
1814 InferInSCC, std::back_inserter(InferInThisFunc),
1815 [
F](
const InferenceDescriptor &
ID) {
return !
ID.SkipFunction(*
F); });
1817 if (InferInThisFunc.empty())
1823 if (!
ID.InstrBreaksAttribute(
I))
1828 return D.AKind ==
ID.AKind;
1834 if (InferInThisFunc.empty())
1839 if (InferInSCC.
empty())
1842 for (Function *
F : SCCNodes)
1847 for (
auto &
ID : InferInSCC) {
1848 if (
ID.SkipFunction(*
F))
1851 ID.SetAttribute(*
F);
1855struct SCCNodesResult {
1856 SCCNodeSet SCCNodes;
1863 const SCCNodeSet &SCCNodes) {
1873 if (!
I.mayThrow(
true))
1876 if (
Function *Callee = CI->getCalledFunction()) {
1880 if (SCCNodes.contains(Callee))
1893 return I.maySynchronize();
1901 if (SCCNodes.contains(Callee))
1908 if (!
I.maySynchronize())
1915 if (SCCNodes.contains(Callee))
1926 AttributeInferer AI;
1933 AI.registerAttrInference(AttributeInferer::InferenceDescriptor{
1934 Attribute::Convergent,
1936 [](
const Function &
F) {
return !
F.isConvergent(); },
1942 LLVM_DEBUG(
dbgs() <<
"Removing convergent attr from fn " <<
F.getName()
1944 F.setNotConvergent();
1957 AttributeInferer AI;
1965 AI.registerAttrInference(AttributeInferer::InferenceDescriptor{
1966 Attribute::NoUnwind,
1968 [](
const Function &
F) {
return F.doesNotThrow(); },
1975 <<
"Adding nounwind attr to fn " <<
F.getName() <<
"\n");
1976 F.setDoesNotThrow();
1988 AI.registerAttrInference(AttributeInferer::InferenceDescriptor{
1991 [](
const Function &
F) {
return F.doesNotFreeMemory(); },
1998 <<
"Adding nofree attr to fn " <<
F.getName() <<
"\n");
1999 F.setDoesNotFreeMemory();
2004 AI.registerAttrInference(AttributeInferer::InferenceDescriptor{
2007 [](
const Function &
F) {
return F.hasNoSync(); },
2014 <<
"Adding nosync attr to fn " <<
F.getName() <<
"\n");
2032 bool AnyFunctionsAddressIsTaken =
true) {
2033 for (
const auto &BB :
F) {
2034 for (
const auto &
I : BB) {
2037 if (!Callee || Callee == &
F)
2040 if (Callee->doesNotRecurse())
2043 if (!AnyFunctionsAddressIsTaken ||
2044 (Callee->isDeclaration() &&
2045 Callee->hasFnAttribute(Attribute::NoCallback)))
2059 if (SCCNodes.size() != 1)
2063 if (!
F || !
F->hasExactDefinition() ||
F->doesNotRecurse())
2069 F->setDoesNotRecurse();
2079 if (!
F || !
F->hasExactDefinition() ||
F->hasFnAttribute(Attribute::Naked) ||
2084 F->setDoesNotReturn();
2092 ColdPaths[&
F.front()] =
false;
2096 while (!Jobs.
empty()) {
2107 ColdPaths[BB] =
true;
2124 auto [Iter, Inserted] = ColdPaths.
try_emplace(Succ,
false);
2140 if (!
F || !
F->hasExactDefinition() ||
F->hasFnAttribute(Attribute::Naked) ||
2141 F->hasFnAttribute(Attribute::Cold) ||
F->hasFnAttribute(Attribute::Hot))
2146 F->addFnAttr(Attribute::Cold);
2158 if (!
F.hasExactDefinition())
2162 if (
F.mustProgress() &&
F.onlyReadsMemory())
2166 if (
F.isDeclaration())
2173 if (!Backedges.
empty())
2179 return I.willReturn();
2199 if (!
F ||
F->hasOptNone() ||
F->hasFnAttribute(Attribute::Naked) ||
2200 F->isPresplitCoroutine()) {
2205 Res.SCCNodes.insert(
F);
2210template <
typename AARGetterT>
2211static SmallPtrSet<Function *, 8>
2213 bool ArgAttrsOnly) {
2217 if (Nodes.SCCNodes.empty())
2261 bool ArgAttrsOnly =
false;
2262 if (
C.size() == 1 && SkipNonRecursive) {
2265 ArgAttrsOnly =
true;
2279 Functions.push_back(&
N.getFunction());
2282 auto ChangedFunctions =
2284 if (ChangedFunctions.empty())
2298 for (
auto *U :
Changed->users()) {
2301 FAM.invalidate(*
Call->getFunction(), FuncPA);
2317 OS, MapClassName2PassName);
2318 if (SkipNonRecursive)
2319 OS <<
"<skip-non-recursive-function-attrs>";
2322template <
typename AARGetterT>
2326 Functions.push_back(
I->getFunction());
2333 if (
F.doesNotRecurse())
2339 assert(!
F.isDeclaration() &&
"Cannot deduce norecurse without a definition!");
2340 assert(
F.hasInternalLinkage() &&
2341 "Can only do top-down deduction for internal linkage functions!");
2351 for (
auto &U :
F.uses()) {
2354 !CB->
getParent()->getParent()->doesNotRecurse())
2357 F.setDoesNotRecurse();
2363 assert(!
F.isDeclaration() &&
"Cannot deduce nofpclass without a definition!");
2364 unsigned NumArgs =
F.arg_size();
2369 for (
User *U :
F.users()) {
2375 for (
unsigned I = 0;
I != NumArgs; ++
I) {
2380 ArgsNoFPClass[
I] &= ~Cst->classify();
2388 if (RetNoFPClass !=
fcNone) {
2389 FPClassTest OldAttr =
F.getAttributes().getRetNoFPClass();
2390 if (OldAttr != RetNoFPClass) {
2396 for (
unsigned I = 0;
I != NumArgs; ++
I) {
2398 if (ArgNoFPClass ==
fcNone)
2401 if (OldAttr == ArgNoFPClass)
2424 if (SCC.size() != 1)
2426 Function &
F = SCC.begin()->getFunction();
2427 if (!
F.isDeclaration() &&
F.hasInternalLinkage() && !
F.use_empty())
2460 bool AnyFunctionsAddressIsTaken =
false;
2462 if (
F.isDeclaration() ||
F.doesNotRecurse())
2464 if (!
F.hasLocalLinkage() ||
F.hasAddressTaken()) {
2465 AnyFunctionsAddressIsTaken =
true;
2490 if (!
F.hasExactDefinition() ||
F.doesNotRecurse())
2497 F.setDoesNotRecurse();
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
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< 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.
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, const LibcallLoweringInfo &Libcalls, AssumptionCache *AC)
static SmallPtrSet< Function *, 8 > deriveAttrsInPostOrder(ArrayRef< Function * > Functions, AARGetterT &&AARGetter, bool ArgAttrsOnly)
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 FunctionSummary * calculatePrevailingSummary(ValueInfo VI, DenseMap< ValueInfo, FunctionSummary * > &CachedPrevailingSummary, function_ref< bool(GlobalValue::GUID, const GlobalValueSummary *)> IsPrevailing)
static void addMemoryAttrs(const SCCNodeSet &SCCNodes, AARGetterT &&AARGetter, SmallPtrSet< Function *, 8 > &Changed)
Deduce readonly/readnone/writeonly attributes for the SCC.
static bool addArgumentAttrsFromCallsites(Function &F)
If a callsite has arguments that are also arguments to the parent function, try to propagate attribut...
static void addCapturesStat(CaptureInfo CI)
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 void addColdAttrs(const SCCNodeSet &SCCNodes, SmallPtrSet< Function *, 8 > &Changed)
static bool mayHaveRecursiveCallee(Function &F, bool AnyFunctionsAddressIsTaken=true)
static void addNoReturnAttrs(const SCCNodeSet &SCCNodes, SmallPtrSet< Function *, 8 > &Changed)
static bool addNoFPClassAttrsTopDown(Function &F)
static cl::opt< bool > DisableNoUnwindInference("disable-nounwind-inference", cl::Hidden, cl::desc("Stop inferring nounwind attribute during function-attrs pass"))
static void addWillReturn(const SCCNodeSet &SCCNodes, SmallPtrSet< Function *, 8 > &Changed)
static void addNonNullAttrs(const SCCNodeSet &SCCNodes, SmallPtrSet< Function *, 8 > &Changed)
Deduce nonnull attributes for the SCC.
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 void inferAttrsFromFunctionBodies(const SCCNodeSet &SCCNodes, SmallPtrSet< Function *, 8 > &Changed)
Infer attributes from all functions in the SCC by scanning every instruction for compliance to the at...
static bool isReturnNonNull(Function *F, const SCCNodeSet &SCCNodes, bool &Speculative)
Tests whether this function is known to not return null.
static bool InstrBreaksNoSync(Instruction &I, const SCCNodeSet &SCCNodes)
static bool deduceFunctionAttributeInRPO(Module &M, LazyCallGraph &CG)
static ArgAccessProperties determinePointerAccessAttrs(Argument *A, const SmallPtrSet< Argument *, 8 > &SCCNodes)
Returns Attribute::None, Attribute::ReadOnly or Attribute::ReadNone.
static bool InstrBreaksNoFree(Instruction &I, const SCCNodeSet &SCCNodes)
Helper for NoFree inference predicate InstrBreaksAttribute.
static cl::opt< bool > EnablePoisonArgAttrPropagation("enable-poison-arg-attr-prop", cl::init(true), cl::Hidden, cl::desc("Try to propagate nonnull and nofpclass argument attributes from " "callsites to caller functions."))
static bool addAccessAttrs(Argument *A, ArgAccessProperties Props)
static void addNoAliasAttrs(const SCCNodeSet &SCCNodes, SmallPtrSet< Function *, 8 > &Changed)
Deduce noalias attributes for the SCC.
static bool addNoRecurseAttrsTopDown(Function &F)
static void addLocAccess(MemoryEffects &ME, const MemoryLocation &Loc, ModRefInfo MR, AAResults &AAR)
static void inferConvergent(const SCCNodeSet &SCCNodes, SmallPtrSet< Function *, 8 > &Changed)
Attempt to remove convergent function attribute when possible.
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 addArgumentAttrs(const SCCNodeSet &SCCNodes, SmallPtrSet< Function *, 8 > &Changed, bool SkipInitializes)
Deduce nocapture attributes for the SCC.
static void addNoRecurseAttrs(const SCCNodeSet &SCCNodes, SmallPtrSet< Function *, 8 > &Changed)
static bool functionWillReturn(const Function &F)
static void addNoUndefAttrs(const SCCNodeSet &SCCNodes, SmallPtrSet< Function *, 8 > &Changed)
Deduce noundef attributes for the SCC.
static void addArgumentReturnedAttrs(const SCCNodeSet &SCCNodes, SmallPtrSet< Function *, 8 > &Changed)
Deduce returned 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
ModuleAnalysisManager MAM
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 ...
This file implements a set that has insertion order iteration characteristics.
This file defines the SmallPtrSet 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.
LLVM_ABI ModRefInfo getModRefInfoMask(const MemoryLocation &Loc, bool IgnoreLocals=false)
Returns a bitmask that should be unconditionally applied to the ModRef info of a memory location.
LLVM_ABI 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 <aparticular IR unit>" (e....
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.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Functions, function parameters, and return types can have attributes to indicate how they should be t...
LLVM_ABI const ConstantRange & getRange() const
Returns the value of the range attribute.
static LLVM_ABI Attribute get(LLVMContext &Context, AttrKind Kind, uint64_t Val=0)
Return a uniquified Attribute object.
LLVM_ABI ArrayRef< ConstantRange > getValueAsConstantRangeList() const
Return the attribute's value as a ConstantRange array.
static LLVM_ABI Attribute getWithNoFPClass(LLVMContext &Context, FPClassTest Mask)
AttrKind
This enumeration lists the attributes that can be associated with parameters, function results,...
static LLVM_ABI Attribute getWithCaptureInfo(LLVMContext &Context, CaptureInfo CI)
bool isValid() const
Return true if the attribute is any kind of attribute.
LLVM Basic Block Representation.
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
Represents analyses that only rely on functions' control flow.
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
LLVM_ABI FPClassTest getParamNoFPClass(unsigned i) const
Extract a test mask for disallowed floating-point value classes for the parameter.
LLVM_ABI FPClassTest getRetNoFPClass() const
Extract a test mask for disallowed floating-point value classes for the return value.
LLVM_ABI 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 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.
LLVM_ABI 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 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.
Represents which components of the pointer may be captured in which location.
static CaptureInfo none()
Create CaptureInfo that does not capture any components of the pointer.
static CaptureInfo retOnly(CaptureComponents RetComponents=CaptureComponents::All)
Create CaptureInfo that may only capture via the return value.
static CaptureInfo all()
Create CaptureInfo that may capture all components of the pointer.
This class represents a list of constant ranges.
LLVM_ABI void subtract(const ConstantRange &SubRange)
LLVM_ABI 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
LLVM_ABI ConstantRangeList intersectWith(const ConstantRangeList &CRL) const
Return the range list that results from the intersection of this ConstantRangeList with another Const...
LLVM_ABI 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.
LLVM_ABI bool contains(const APInt &Val) const
Return true if the specified value is in the set.
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)
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)
uint64_t GUID
Declare a type to represent a global unique identifier for a global value.
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.
This is an important class for using LLVM in a threaded context.
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.
LLVM_ABI void buildRefSCCs()
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)
ModRefInfo getModRef(Location Loc) const
Get ModRefInfo for the given Location.
static MemoryEffectsBase none()
static MemoryEffectsBase unknown()
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...
static LLVM_ABI 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.
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM)
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.
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
PreservedAnalyses & preserve()
Mark an analysis as preserved.
Return a value (possibly void), from a function.
LLVM_ABI 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.
void insert_range(Range &&R)
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.
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.
static unsigned getPointerOperandIndex()
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.
LLVM_ABI Align getPointerAlignment(const DataLayout &DL) const
Returns an alignment of the pointer value.
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.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
bool match(Val *V, const Pattern &P)
ap_match< APFloat > m_APFloat(const APFloat *&Res)
Match a ConstantFP or splatted ConstantVector, binding the specified pointer to the contained APFloat...
initializer< Ty > init(const Ty &Val)
DXILDebugInfoMap run(Module &M)
constexpr uint64_t PointerSize
aarch64 pointer size.
NodeAddr< UseNode * > Use
NodeAddr< NodeBase * > Node
LLVM_ABI iterator begin() const
This is an optimization pass for GlobalISel generic memory operations.
@ Low
Lower the current thread's priority such that it does not affect foreground tasks significantly.
bool capturesReadProvenanceOnly(CaptureComponents CC)
LLVM_ABI KnownFPClass computeKnownFPClass(const Value *V, const APInt &DemandedElts, FPClassTest InterestedClasses, const SimplifyQuery &SQ, unsigned Depth=0)
Determine which floating-point classes are valid for V, and return them in KnownFPClass bit sets.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI MemoryEffects computeFunctionBodyMemoryAccess(Function &F, AAResults &AAR)
Returns the memory access properties of this copy of the function.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
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.
MemoryEffectsBase< IRMemLocation > MemoryEffects
Summary of how a function affects memory in the program.
LLVM_ABI 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.
AnalysisManager< LazyCallGraph::SCC, LazyCallGraph & > CGSCCAnalysisManager
The CGSCC analysis manager.
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 isModSet(const ModRefInfo MRI)
void sort(IteratorTy Start, IteratorTy End)
FPClassTest
Floating-point class tests, supported by 'is_fpclass' intrinsic.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
CaptureComponents
Components of the pointer that may be captured.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
auto post_order(const T &G)
Post-order traversal of a graph.
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ABI 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.
@ ModRef
The access may reference and may modify the value stored in memory.
@ NoModRef
The access neither references nor modifies the value stored in memory.
@ ArgMem
Access to memory via argument pointers.
LLVM_ABI const Value * getUnderlyingObjectAggressive(const Value *V)
Like getUnderlyingObject(), but will try harder to find a single underlying object.
LLVM_ABI bool PointerMayBeCaptured(const Value *V, bool ReturnCaptures, unsigned MaxUsesToExplore=0)
PointerMayBeCaptured - Return true if this pointer value may be captured by the enclosing function (w...
LLVM_ABI bool isGuaranteedNotToBeUndefOrPoison(const Value *V, AssumptionCache *AC=nullptr, const Instruction *CtxI=nullptr, const DominatorTree *DT=nullptr, unsigned Depth=0)
Return true if this function can prove that V does not have undef bits and is never poison.
LLVM_ABI bool isGuaranteedToTransferExecutionToSuccessor(const Instruction *I)
Return true if this function can prove that the instruction I will always transfer execution to one o...
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
LLVM_ABI bool inferAttributesFromOthers(Function &F)
If we can infer one attribute from another on the declaration of a function, explicitly materialize t...
LLVM_ABI UseCaptureInfo DetermineUseCaptureKind(const Use &U, const Value *Base)
Determine what kind of capture behaviour U may exhibit.
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
bool capturesAll(CaptureComponents CC)
bool capturesNothing(CaptureComponents CC)
bool isNoModRef(const ModRefInfo MRI)
LLVM_ABI 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.
LLVM_ABI bool isIdentifiedObject(const Value *V)
Return true if this pointer refers to a distinct and identifiable object.
bool capturesAnyProvenance(CaptureComponents CC)
bool isRefSet(const ModRefInfo MRI)
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
LLVM_ABI bool canReturn(const Function &F)
Return true if there is at least a path through which F can return, false if there is no such path.
LLVM_ABI ConstantRange computeConstantRange(const Value *V, bool ForSigned, const SimplifyQuery &SQ, unsigned Depth=0)
Determine the possible constant range of an integer or vector of integer value.
This struct is a compact representation of a valid (non-zero power of two) alignment.
static ArgAccessProperties all()
ArgAccessProperties & operator|=(const ArgAccessProperties &Other)
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.
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)
typename ArgumentGraph *::UnknownGraphTypeError NodeRef
bool isKnownNever(FPClassTest Mask) const
Return true if it's known this can never be one of the mask entries.
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
A CRTP mix-in to automatically provide informational APIs needed for passes.
LLVM_ABI PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG, CGSCCUpdateResult &UR)
LLVM_ABI void printPipeline(raw_ostream &OS, function_ref< StringRef(StringRef)> MapClassName2PassName)
Capture information for a specific Use.
CaptureComponents UseCC
Components captured by this use.
Struct that holds a reference to a particular GUID in a global value summary.