72#define DEBUG_TYPE "function-attrs"
74STATISTIC(NumMemoryAttr,
"Number of functions with improved memory attribute");
75STATISTIC(NumCapturesNone,
"Number of arguments marked captures(none)");
76STATISTIC(NumCapturesPartial,
"Number of arguments marked with captures "
77 "attribute other than captures(none)");
78STATISTIC(NumReturned,
"Number of arguments marked returned");
79STATISTIC(NumReadNoneArg,
"Number of arguments marked readnone");
80STATISTIC(NumReadOnlyArg,
"Number of arguments marked readonly");
81STATISTIC(NumWriteOnlyArg,
"Number of arguments marked writeonly");
82STATISTIC(NumNoAlias,
"Number of function returns marked noalias");
83STATISTIC(NumNonNullReturn,
"Number of function returns marked nonnull");
84STATISTIC(NumNoUndefReturn,
"Number of function returns marked noundef");
85STATISTIC(NumNoRecurse,
"Number of functions marked as norecurse");
86STATISTIC(NumNoUnwind,
"Number of functions marked as nounwind");
87STATISTIC(NumNoFree,
"Number of functions marked as nofree");
88STATISTIC(NumNoFreeArg,
"Number of arguments marked as nofree");
89STATISTIC(NumWillReturn,
"Number of functions marked as willreturn");
90STATISTIC(NumNoSync,
"Number of functions marked as nosync");
91STATISTIC(NumCold,
"Number of functions marked as cold");
94 "Number of functions marked as norecurse during thinlink");
96 "Number of functions marked as nounwind during thinlink");
100 cl::desc(
"Try to propagate nonnull and nofpclass argument attributes from "
101 "callsites to caller functions."));
105 cl::desc(
"Stop inferring nounwind attribute during function-attrs pass"));
109 cl::desc(
"Stop inferring nofree attribute during function-attrs pass"));
113 cl::desc(
"Don't propagate function-attrs in thinLTO"));
119 ++NumCapturesPartial;
153 if (!Arg->getType()->isPtrOrPtrVectorTy())
174static std::pair<MemoryEffects, MemoryEffects>
176 const SCCNodeSet &SCCNodes) {
202 if (
F.getAttributes().hasAttrSomewhere(Attribute::InAlloca) ||
203 F.getAttributes().hasAttrSomewhere(Attribute::Preallocated))
216 if (
Call && !
Call->hasOperandBundles() &&
Call->getCalledFunction() &&
217 SCCNodes.count(
Call->getCalledFunction())) {
225 if ((ME & OrigME) == OrigME)
242 AddNonArgMemoryEffects(CallME);
264 AddNonArgMemoryEffects(InstME);
268 return {OrigME & ME, RecursiveArgME};
277template <
typename AARGetterT>
288 auto [FnME, FnRecursiveArgME] =
291 RecursiveArgME |= FnRecursiveArgME;
305 if (NewME != OldME) {
307 F->setMemoryEffects(NewME);
311 A.removeAttr(Attribute::Writable);
325 auto [It, Inserted] = CachedPrevailingSummary.
try_emplace(VI);
372 for (
const auto &GVS : VI.getSummaryList()) {
378 if (!FS || FS->fflags().HasUnknownCall)
381 const auto &
Linkage = GVS->linkage();
386 <<
"ThinLTO FunctionAttrs: Multiple Local Linkage, bailing on "
388 << VI.name() <<
" from " << FS->modulePath() <<
". Previous module "
389 <<
Local->modulePath() <<
"\n");
394 assert(IsPrevailing(VI.getGUID(), GVS.get()) || GVS->wasPromoted());
401 if (IsPrevailing(VI.getGUID(), GVS.get())) {
411 auto &CPS = CachedPrevailingSummary[VI];
415 }
else if (Prevailing) {
435 auto PropagateAttributes = [&](std::vector<ValueInfo> &SCCNodes) {
438 InferredFlags.
NoRecurse = (SCCNodes.size() == 1);
441 for (
auto &V : SCCNodes) {
452 for (
const auto &Callee : CallerSummary->
calls()) {
454 Callee.first, CachedPrevailingSummary, IsPrevailing);
472 for (
auto &V : SCCNodes) {
474 LLVM_DEBUG(
dbgs() <<
"ThinLTO FunctionAttrs: Propagated NoRecurse to "
475 << V.name() <<
"\n");
476 ++NumThinLinkNoRecurse;
480 LLVM_DEBUG(
dbgs() <<
"ThinLTO FunctionAttrs: Propagated NoUnwind to "
481 << V.name() <<
"\n");
482 ++NumThinLinkNoUnwind;
485 for (
const auto &S : V.getSummaryList()) {
501 std::vector<ValueInfo> Nodes(*
I);
502 PropagateAttributes(Nodes);
512struct ArgumentGraphNode {
523 using ArgumentMapTy = std::map<Argument *, ArgumentGraphNode>;
525 ArgumentMapTy ArgumentMap;
533 ArgumentGraphNode SyntheticRoot;
536 ArgumentGraph() { SyntheticRoot.Definition =
nullptr; }
540 iterator
begin() {
return SyntheticRoot.Uses.begin(); }
541 iterator
end() {
return SyntheticRoot.Uses.end(); }
542 ArgumentGraphNode *getEntryNode() {
return &SyntheticRoot; }
544 ArgumentGraphNode *operator[](Argument *
A) {
545 ArgumentGraphNode &
Node = ArgumentMap[
A];
547 SyntheticRoot.Uses.push_back(&Node);
556 ArgumentUsesTracker(
const SCCNodeSet &SCCNodes) : SCCNodes(SCCNodes) {}
560 Action captured(
const Use *U, UseCaptureInfo UseCI)
override {
561 if (updateCaptureInfo(U, UseCI.
UseCC)) {
570 return ContinueIgnoringReturn;
581 CI |= CaptureInfo(
CC);
586 if (!
F || !
F->hasExactDefinition() || !SCCNodes.count(
F)) {
587 CI |= CaptureInfo(
CC);
601 CI |= CaptureInfo(
CC);
605 if (UseIndex >=
F->arg_size()) {
606 assert(
F->isVarArg() &&
"More params than args in non-varargs call");
607 CI |= CaptureInfo(
CC);
613 Uses.push_back(&*std::next(
F->arg_begin(), UseIndex));
623 const SCCNodeSet &SCCNodes;
631 std::optional<int64_t> Offset;
638struct ArgumentAccessInfo {
639 enum class AccessType : uint8_t {
Write, WriteWithSideEffect,
Read,
Unknown };
640 AccessType ArgAccessType;
641 ConstantRangeList AccessRanges;
645struct UsesPerBlockInfo {
646 SmallDenseMap<Instruction *, ArgumentAccessInfo, 4> Insts;
647 bool HasWrites =
false;
648 bool HasUnknownAccess =
false;
652struct ArgumentUsesSummary {
653 bool HasAnyWrite =
false;
654 bool HasWriteOutsideEntryBB =
false;
655 SmallDenseMap<const BasicBlock *, UsesPerBlockInfo, 16> UsesPerBlock;
658ArgumentAccessInfo getArgumentAccessInfo(
const Instruction *
I,
659 const ArgumentUse &ArgUse,
661 auto GetTypeAccessRange =
663 std::optional<int64_t>
Offset) -> std::optional<ConstantRange> {
677 auto GetConstantIntRange =
679 std::optional<int64_t>
Offset) -> std::optional<ConstantRange> {
681 if (ConstantLength &&
Offset) {
682 int64_t
Len = ConstantLength->getSExtValue();
700 if (
SI->isSimple() && &
SI->getOperandUse(1) == ArgUse.U) {
705 if (
auto TypeAccessRange =
706 GetTypeAccessRange(
SI->getAccessType(), ArgUse.Offset))
707 AccessRanges.
insert(*TypeAccessRange);
708 return {ArgumentAccessInfo::AccessType::Write, std::move(AccessRanges)};
711 if (LI->isSimple()) {
712 assert(&LI->getOperandUse(0) == ArgUse.U);
716 if (
auto TypeAccessRange =
717 GetTypeAccessRange(LI->getAccessType(), ArgUse.Offset))
718 return {ArgumentAccessInfo::AccessType::Read, {*TypeAccessRange}};
721 if (!MemSet->isVolatile()) {
723 if (
auto AccessRange =
724 GetConstantIntRange(MemSet->getLength(), ArgUse.Offset))
725 AccessRanges.
insert(*AccessRange);
726 return {ArgumentAccessInfo::AccessType::Write, AccessRanges};
729 if (!MTI->isVolatile()) {
730 if (&MTI->getOperandUse(0) == ArgUse.U) {
732 if (
auto AccessRange =
733 GetConstantIntRange(MTI->getLength(), ArgUse.Offset))
734 AccessRanges.
insert(*AccessRange);
735 return {ArgumentAccessInfo::AccessType::Write, AccessRanges};
736 }
else if (&MTI->getOperandUse(1) == ArgUse.U) {
737 if (
auto AccessRange =
738 GetConstantIntRange(MTI->getLength(), ArgUse.Offset))
739 return {ArgumentAccessInfo::AccessType::Read, {*AccessRange}};
746 bool IsInitialize = CB->
paramHasAttr(ArgNo, Attribute::Initializes);
747 if (IsInitialize && ArgUse.Offset) {
751 ? ArgumentAccessInfo::AccessType::Write
752 : ArgumentAccessInfo::AccessType::WriteWithSideEffect;
758 CR.getUpper() + *ArgUse.Offset));
759 return {
Access, AccessRanges};
764 return {ArgumentAccessInfo::AccessType::Unknown, {}};
769 auto &
DL =
F.getDataLayout();
771 DL.getIndexSizeInBits(
A.getType()->getPointerAddressSpace());
772 ArgumentUsesSummary
Result;
776 for (
Use &U :
A.uses())
782 auto *BB =
I->getParent();
783 auto &BBInfo =
Result.UsesPerBlock[BB];
784 auto [It,
Inserted] = BBInfo.Insts.try_emplace(
I);
785 auto &IInfo = It->second;
790 IInfo = {ArgumentAccessInfo::AccessType::Unknown, {}};
791 BBInfo.HasUnknownAccess =
true;
795 IInfo = std::move(Info);
796 BBInfo.HasUnknownAccess |=
797 IInfo.ArgAccessType == ArgumentAccessInfo::AccessType::Unknown;
799 (IInfo.ArgAccessType == ArgumentAccessInfo::AccessType::Write ||
800 IInfo.ArgAccessType ==
801 ArgumentAccessInfo::AccessType::WriteWithSideEffect) &&
802 !IInfo.AccessRanges.empty();
803 BBInfo.HasWrites |= InfoHasWrites;
804 return InfoHasWrites;
809 while (!Worklist.
empty()) {
811 User *U = ArgUse.U->getUser();
815 std::optional<int64_t> NewOffset = std::nullopt;
819 NewOffset = *ArgUse.Offset +
Offset.getSExtValue();
821 for (
Use &U :
GEP->uses())
827 bool HasWrite = UpdateUseInfo(
I, getArgumentAccessInfo(
I, ArgUse,
DL));
829 Result.HasAnyWrite |= HasWrite;
831 if (HasWrite &&
I->getParent() != &EntryBB)
832 Result.HasWriteOutsideEntryBB =
true;
888 if (
A->hasInAllocaAttr() ||
A->hasPreallocatedAttr())
893 for (
Use &U :
A->uses()) {
898 while (!Worklist.
empty()) {
924 for (
Use &UU :
I->uses())
925 if (Visited.
insert(&UU).second)
946 SCCNodes.
count(
F->getArg(UseIndex)))
969 Props.
IsRead |=
I->mayReadFromMemory();
970 Props.
IsWrite |=
I->mayWriteToMemory();
985 if (!
F->hasExactDefinition())
988 if (
F->getReturnType()->isVoidTy())
992 if (
F->getAttributes().hasAttrSomewhere(Attribute::Returned))
995 auto FindRetArg = [&]() ->
Argument * {
1003 if (!RetVal || RetVal->getType() !=
F->getReturnType())
1008 else if (RetArg != RetVal)
1015 if (
Argument *RetArg = FindRetArg()) {
1016 RetArg->addAttr(Attribute::Returned);
1044 for (
auto &CSArg : CalledFunc->args()) {
1045 unsigned ArgNo = CSArg.getArgNo();
1050 if (CSArg.hasNonNullAttr(
false)) {
1054 if (!FArg->hasNonNullAttr()) {
1055 FArg->addAttr(Attribute::NonNull);
1063 if ((CSNoFPClass | ArgNoFPClass) != ArgNoFPClass) {
1065 FArg->getContext(), CSNoFPClass | ArgNoFPClass));
1080 assert(
A &&
"Argument must not be null.");
1083 if (!Props.
IsFree && !
A->hasAttribute(Attribute::NoFree) &&
1084 !
A->hasAttribute(Attribute::NoFreeObj)) {
1086 A->addAttr(Attribute::NoFree);
1095 Attr = Attribute::ReadOnly;
1097 Attr = Attribute::WriteOnly;
1099 Attr = Attribute::ReadNone;
1102 if (
A->hasAttribute(Attr))
1107 A->removeAttr(Attribute::WriteOnly);
1108 A->removeAttr(Attribute::ReadOnly);
1109 A->removeAttr(Attribute::ReadNone);
1111 if (Attr == Attribute::ReadNone || Attr == Attribute::ReadOnly)
1112 A->removeAttr(Attribute::Writable);
1114 if (Attr == Attribute::ReadOnly)
1116 else if (Attr == Attribute::WriteOnly)
1124 auto ArgumentUses = collectArgumentUsesPerBlock(
A,
F);
1126 if (!ArgumentUses.HasAnyWrite)
1129 auto &UsesPerBlock = ArgumentUses.UsesPerBlock;
1138 auto UPB = UsesPerBlock.find(BB);
1145 if (UPB == UsesPerBlock.end() || !UPB->second.HasUnknownAccess) {
1146 bool HasAddedSuccessor =
false;
1148 if (
auto SuccI = Initialized.
find(Succ); SuccI != Initialized.
end()) {
1149 if (HasAddedSuccessor) {
1152 CRL = SuccI->second;
1153 HasAddedSuccessor =
true;
1162 if (UPB != UsesPerBlock.end()) {
1166 sort(Insts, [](std::pair<Instruction *, ArgumentAccessInfo> &
LHS,
1167 std::pair<Instruction *, ArgumentAccessInfo> &
RHS) {
1168 return LHS.first->comesBefore(
RHS.first);
1173 for (
auto &[
_, Info] :
reverse(Insts)) {
1174 if (Info.ArgAccessType == ArgumentAccessInfo::AccessType::Unknown ||
1175 Info.ArgAccessType ==
1176 ArgumentAccessInfo::AccessType::WriteWithSideEffect)
1178 if (!Info.AccessRanges.empty()) {
1179 if (Info.ArgAccessType == ArgumentAccessInfo::AccessType::Write ||
1180 Info.ArgAccessType ==
1181 ArgumentAccessInfo::AccessType::WriteWithSideEffect) {
1184 assert(Info.ArgAccessType == ArgumentAccessInfo::AccessType::Read);
1185 for (
const auto &ReadRange : Info.AccessRanges)
1197 bool OnlyScanEntryBlock = !ArgumentUses.HasWriteOutsideEntryBB;
1198 if (!OnlyScanEntryBlock)
1199 if (
auto EntryUPB = UsesPerBlock.find(&EntryBB);
1200 EntryUPB != UsesPerBlock.end())
1201 OnlyScanEntryBlock = EntryUPB->second.HasUnknownAccess;
1202 if (OnlyScanEntryBlock) {
1203 EntryCRL = VisitBlock(&EntryBB);
1204 if (EntryCRL.
empty())
1215 Initialized[BB] = CRL;
1218 auto EntryCRLI = Initialized.
find(&EntryBB);
1219 if (EntryCRLI == Initialized.
end())
1222 EntryCRL = EntryCRLI->second;
1226 "should have bailed already if EntryCRL is empty");
1228 if (
A.hasAttribute(Attribute::Initializes)) {
1230 A.getAttribute(Attribute::Initializes).getValueAsConstantRangeList();
1231 if (PreviousCRL == EntryCRL)
1233 EntryCRL = EntryCRL.
unionWith(PreviousCRL);
1245 bool SkipInitializes) {
1248 auto DetermineAccessAttrsForSingleton = [](
Argument *
A) {
1260 if (!
F->hasExactDefinition())
1268 if (
F->onlyReadsMemory() &&
F->doesNotThrow() &&
F->willReturn() &&
1269 F->getReturnType()->isVoidTy()) {
1271 if (
A.getType()->isPointerTy() && !
A.hasNoCaptureAttr()) {
1282 if (!
A.getType()->isPointerTy())
1284 bool HasNonLocalUses =
false;
1285 CaptureInfo OrigCI =
A.getAttributes().getCaptureInfo();
1287 ArgumentUsesTracker Tracker(SCCNodes);
1290 if (NewCI != OrigCI) {
1291 if (Tracker.Uses.empty()) {
1300 ArgumentGraphNode *
Node = AG[&
A];
1303 Node->Uses.push_back(AG[
Use]);
1305 HasNonLocalUses =
true;
1311 if (!HasNonLocalUses && !
A.onlyReadsMemory()) {
1316 if (DetermineAccessAttrsForSingleton(&
A))
1319 if (!SkipInitializes && !
A.onlyReadsMemory()) {
1334 const std::vector<ArgumentGraphNode *> &ArgumentSCC = *
I;
1335 if (ArgumentSCC.size() == 1) {
1336 if (!ArgumentSCC[0]->Definition)
1340 if (ArgumentSCC[0]->
Uses.size() == 1 &&
1341 ArgumentSCC[0]->Uses[0] == ArgumentSCC[0]) {
1342 Argument *
A = ArgumentSCC[0]->Definition;
1343 CaptureInfo OrigCI =
A->getAttributes().getCaptureInfo();
1345 if (NewCI != OrigCI) {
1352 if (DetermineAccessAttrsForSingleton(
A))
1361 for (ArgumentGraphNode *
I : ArgumentSCC) {
1362 ArgumentSCCNodes.
insert(
I->Definition);
1369 for (ArgumentGraphNode *
N : ArgumentSCC) {
1370 for (ArgumentGraphNode *
Use :
N->Uses) {
1372 if (ArgumentSCCNodes.
count(
A))
1382 for (ArgumentGraphNode *
N : ArgumentSCC) {
1384 CaptureInfo OrigCI =
A->getAttributes().getCaptureInfo();
1386 if (NewCI != OrigCI) {
1397 for (ArgumentGraphNode *
N : ArgumentSCC) {
1398 if (DetermineAccessAttrsForSingleton(
N->Definition))
1399 Changed.insert(
N->Definition->getParent());
1416 for (ArgumentGraphNode *
N : ArgumentSCC) {
1424 for (ArgumentGraphNode *
N : ArgumentSCC) {
1441 FlowsToReturn.
insert(Ret->getReturnValue());
1443 for (
unsigned i = 0; i != FlowsToReturn.
size(); ++i) {
1444 Value *RetVal = FlowsToReturn[i];
1457 switch (RVI->getOpcode()) {
1459 case Instruction::BitCast:
1460 case Instruction::GetElementPtr:
1461 case Instruction::AddrSpaceCast:
1462 FlowsToReturn.
insert(RVI->getOperand(0));
1464 case Instruction::Select: {
1466 FlowsToReturn.
insert(
SI->getTrueValue());
1467 FlowsToReturn.
insert(
SI->getFalseValue());
1470 case Instruction::PHI: {
1477 case Instruction::Alloca:
1479 case Instruction::Call:
1480 case Instruction::Invoke: {
1510 if (
F->returnDoesNotAlias())
1516 if (!
F->hasExactDefinition())
1521 if (!
F->getReturnType()->isPointerTy())
1529 if (
F->returnDoesNotAlias() ||
1530 !
F->getReturnType()->isPointerTy())
1533 F->setReturnDoesNotAlias();
1547 bool &Speculative) {
1548 assert(
F->getReturnType()->isPointerTy() &&
1549 "nonnull only meaningful on pointer types");
1550 Speculative =
false;
1555 FlowsToReturn.
insert(Ret->getReturnValue());
1557 auto &
DL =
F->getDataLayout();
1559 for (
unsigned i = 0; i != FlowsToReturn.
size(); ++i) {
1560 Value *RetVal = FlowsToReturn[i];
1573 case Instruction::BitCast:
1574 case Instruction::AddrSpaceCast:
1577 case Instruction::GetElementPtr:
1583 case Instruction::Select: {
1585 FlowsToReturn.
insert(
SI->getTrueValue());
1586 FlowsToReturn.
insert(
SI->getFalseValue());
1589 case Instruction::PHI: {
1595 case Instruction::Call:
1596 case Instruction::Invoke: {
1601 if (Callee && SCCNodes.count(Callee)) {
1621 bool SCCReturnsNonNull =
true;
1627 if (
F->getAttributes().hasRetAttr(Attribute::NonNull))
1633 if (!
F->hasExactDefinition())
1638 if (!
F->getReturnType()->isPointerTy())
1641 bool Speculative =
false;
1647 <<
" as nonnull\n");
1648 F->addRetAttr(Attribute::NonNull);
1656 SCCReturnsNonNull =
false;
1659 if (SCCReturnsNonNull) {
1661 if (
F->getAttributes().hasRetAttr(Attribute::NonNull) ||
1662 !
F->getReturnType()->isPointerTy())
1665 LLVM_DEBUG(
dbgs() <<
"SCC marking " <<
F->getName() <<
" as nonnull\n");
1666 F->addRetAttr(Attribute::NonNull);
1681 if (Attrs.hasRetAttr(Attribute::NoUndef))
1687 if (!
F->hasExactDefinition())
1693 if (
F->hasFnAttribute(Attribute::SanitizeMemory))
1696 if (
F->getReturnType()->isVoidTy())
1703 Value *RetVal = Ret->getReturnValue();
1710 if (Attrs.hasRetAttr(Attribute::NonNull) &&
1718 Attribute Attr = Attrs.getRetAttr(Attribute::Range);
1725 FPClassTest AttrFPClass = Attrs.getRetNoFPClass();
1726 if (AttrFPClass !=
fcNone) {
1734 F->addRetAttr(Attribute::NoUndef);
1749class AttributeInferer {
1752 struct InferenceDescriptor {
1758 std::function<bool(
const Function &)> SkipFunction;
1761 std::function<bool(Instruction &)> InstrBreaksAttribute;
1764 std::function<void(
Function &)> SetAttribute;
1767 Attribute::AttrKind AKind;
1771 bool RequiresExactDefinition;
1773 InferenceDescriptor(Attribute::AttrKind AK,
1774 std::function<
bool(
const Function &)> SkipFunc,
1775 std::function<
bool(Instruction &)> InstrScan,
1776 std::function<
void(
Function &)> SetAttr,
1778 : SkipFunction(SkipFunc), InstrBreaksAttribute(InstrScan),
1779 SetAttribute(SetAttr), AKind(AK),
1780 RequiresExactDefinition(ReqExactDef) {}
1787 void registerAttrInference(InferenceDescriptor AttrInference) {
1788 InferenceDescriptors.push_back(AttrInference);
1791 void run(
const SCCNodeSet &SCCNodes, SmallPtrSet<Function *, 8> &
Changed);
1796void AttributeInferer::run(
const SCCNodeSet &SCCNodes,
1805 if (InferInSCC.
empty())
1810 if (
ID.SkipFunction(*
F))
1815 return F->isDeclaration() ||
1816 (
ID.RequiresExactDefinition && !
F->hasExactDefinition());
1823 InferInSCC, std::back_inserter(InferInThisFunc),
1824 [
F](
const InferenceDescriptor &ID) {
return !
ID.SkipFunction(*
F); });
1826 if (InferInThisFunc.empty())
1831 llvm::erase_if(InferInThisFunc, [&](
const InferenceDescriptor &ID) {
1832 if (!
ID.InstrBreaksAttribute(
I))
1837 return D.AKind ==
ID.AKind;
1843 if (InferInThisFunc.empty())
1848 if (InferInSCC.
empty())
1856 for (
auto &ID : InferInSCC) {
1857 if (
ID.SkipFunction(*
F))
1860 ID.SetAttribute(*
F);
1864struct SCCNodesResult {
1865 SCCNodeSet SCCNodes;
1872 const SCCNodeSet &SCCNodes) {
1882 if (!
I.mayThrow(
true))
1885 if (
Function *Callee = CI->getCalledFunction()) {
1889 if (SCCNodes.contains(Callee))
1902 return I.maySynchronize();
1910 if (SCCNodes.contains(Callee))
1917 if (!
I.maySynchronize())
1924 if (SCCNodes.contains(Callee))
1935 AttributeInferer AI;
1942 AI.registerAttrInference(AttributeInferer::InferenceDescriptor{
1943 Attribute::Convergent,
1945 [](
const Function &
F) {
return !
F.isConvergent(); },
1951 LLVM_DEBUG(
dbgs() <<
"Removing convergent attr from fn " <<
F.getName()
1953 F.setNotConvergent();
1966 AttributeInferer AI;
1974 AI.registerAttrInference(AttributeInferer::InferenceDescriptor{
1975 Attribute::NoUnwind,
1977 [](
const Function &
F) {
return F.doesNotThrow(); },
1984 <<
"Adding nounwind attr to fn " <<
F.getName() <<
"\n");
1985 F.setDoesNotThrow();
1997 AI.registerAttrInference(AttributeInferer::InferenceDescriptor{
2000 [](
const Function &
F) {
return F.doesNotFreeMemory(); },
2007 <<
"Adding nofree attr to fn " <<
F.getName() <<
"\n");
2008 F.setDoesNotFreeMemory();
2013 AI.registerAttrInference(AttributeInferer::InferenceDescriptor{
2016 [](
const Function &
F) {
return F.hasNoSync(); },
2023 <<
"Adding nosync attr to fn " <<
F.getName() <<
"\n");
2041 bool AnyFunctionsAddressIsTaken =
true) {
2042 for (
const auto &BB :
F) {
2043 for (
const auto &
I : BB) {
2046 if (!Callee || Callee == &
F)
2049 if (Callee->doesNotRecurse())
2052 if (!AnyFunctionsAddressIsTaken ||
2053 (Callee->isDeclaration() &&
2054 Callee->hasFnAttribute(Attribute::NoCallback)))
2068 if (SCCNodes.size() != 1)
2072 if (!
F || !
F->hasExactDefinition() ||
F->doesNotRecurse())
2078 F->setDoesNotRecurse();
2088 if (!
F || !
F->hasExactDefinition() ||
F->hasFnAttribute(Attribute::Naked) ||
2093 F->setDoesNotReturn();
2101 ColdPaths[&
F.front()] =
false;
2105 while (!Jobs.
empty()) {
2116 ColdPaths[BB] =
true;
2133 auto [Iter, Inserted] = ColdPaths.
try_emplace(Succ,
false);
2149 if (!
F || !
F->hasExactDefinition() ||
F->hasFnAttribute(Attribute::Naked) ||
2150 F->hasFnAttribute(Attribute::Cold) ||
F->hasFnAttribute(Attribute::Hot))
2155 F->addFnAttr(Attribute::Cold);
2167 if (!
F.hasExactDefinition())
2171 if (
F.mustProgress() &&
F.onlyReadsMemory())
2175 if (
F.isDeclaration())
2182 if (!Backedges.
empty())
2188 return I.willReturn();
2208 if (!
F ||
F->hasOptNone() ||
F->hasFnAttribute(Attribute::Naked) ||
2209 F->isPresplitCoroutine()) {
2214 Res.SCCNodes.insert(
F);
2219template <
typename AARGetterT>
2220static SmallPtrSet<Function *, 8>
2222 bool ArgAttrsOnly) {
2226 if (Nodes.SCCNodes.empty())
2270 bool ArgAttrsOnly =
false;
2271 if (
C.size() == 1 && SkipNonRecursive) {
2274 ArgAttrsOnly =
true;
2288 Functions.push_back(&
N.getFunction());
2291 auto ChangedFunctions =
2293 if (ChangedFunctions.empty())
2307 for (
auto *U :
Changed->users()) {
2310 FAM.invalidate(*
Call->getFunction(), FuncPA);
2325 static_cast<PassInfoMixin<PostOrderFunctionAttrsPass> *
>(
this)->
printPipeline(
2326 OS, MapClassName2PassName);
2327 if (SkipNonRecursive)
2328 OS <<
"<skip-non-recursive-function-attrs>";
2332 if (
F.doesNotRecurse())
2338 assert(!
F.isDeclaration() &&
"Cannot deduce norecurse without a definition!");
2339 assert(
F.hasInternalLinkage() &&
2340 "Can only do top-down deduction for internal linkage functions!");
2350 for (
auto &U :
F.uses()) {
2353 !CB->
getParent()->getParent()->doesNotRecurse())
2356 F.setDoesNotRecurse();
2362 assert(!
F.isDeclaration() &&
"Cannot deduce nofpclass without a definition!");
2363 unsigned NumArgs =
F.arg_size();
2368 for (
User *U :
F.users()) {
2374 for (
unsigned I = 0;
I != NumArgs; ++
I) {
2379 ArgsNoFPClass[
I] &= ~Cst->classify();
2387 if (RetNoFPClass !=
fcNone) {
2388 FPClassTest OldAttr =
F.getAttributes().getRetNoFPClass();
2389 if (OldAttr != RetNoFPClass) {
2395 for (
unsigned I = 0;
I != NumArgs; ++
I) {
2397 if (ArgNoFPClass ==
fcNone)
2400 if (OldAttr == ArgNoFPClass)
2423 if (SCC.size() != 1)
2425 Function &
F = SCC.begin()->getFunction();
2426 if (!
F.isDeclaration() &&
F.hasInternalLinkage() && !
F.use_empty())
2459 bool AnyFunctionsAddressIsTaken =
false;
2461 if (
F.isDeclaration() ||
F.doesNotRecurse())
2463 if (!
F.hasLocalLinkage() ||
F.hasAddressTaken()) {
2464 AnyFunctionsAddressIsTaken =
true;
2489 if (!
F.hasExactDefinition() ||
F.doesNotRecurse())
2496 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< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
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 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.
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.
bool isKnownNever(FPClassMask Mask) const
Return true if it's known this can never be one of the mask entries.
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.
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)
PointerTypeMap run(const Module &M)
Compute the PointerTypeMap for the 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.
@ Unknown
Not known to have no common set bits.
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.
LLVM_ABI const Value * getUnderlyingObjectAggressive(const Value *V, bool MustPreserveProvenance=false)
Like getUnderlyingObject(), but will try harder to find a single underlying object.
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 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...
bool capturesAnything(CaptureComponents CC)
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
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
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.