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->hasOperandBundles() &&
Call->getCalledFunction() &&
217 SCCNodes.count(
Call->getCalledFunction())) {
237 AddNonArgMemoryEffects(CallME);
259 AddNonArgMemoryEffects(InstME);
263 return {OrigME & ME, RecursiveArgME};
272template <
typename AARGetterT>
283 auto [FnME, FnRecursiveArgME] =
286 RecursiveArgME |= FnRecursiveArgME;
300 if (NewME != OldME) {
302 F->setMemoryEffects(NewME);
306 A.removeAttr(Attribute::Writable);
320 auto [It, Inserted] = CachedPrevailingSummary.
try_emplace(VI);
367 for (
const auto &GVS : VI.getSummaryList()) {
373 if (!FS || FS->fflags().HasUnknownCall)
376 const auto &
Linkage = GVS->linkage();
381 <<
"ThinLTO FunctionAttrs: Multiple Local Linkage, bailing on "
383 << VI.name() <<
" from " << FS->modulePath() <<
". Previous module "
384 <<
Local->modulePath() <<
"\n");
389 assert(IsPrevailing(VI.getGUID(), GVS.get()) || GVS->wasPromoted());
396 if (IsPrevailing(VI.getGUID(), GVS.get())) {
406 auto &CPS = CachedPrevailingSummary[VI];
410 }
else if (Prevailing) {
430 auto PropagateAttributes = [&](std::vector<ValueInfo> &SCCNodes) {
433 InferredFlags.
NoRecurse = (SCCNodes.size() == 1);
436 for (
auto &V : SCCNodes) {
447 for (
const auto &Callee : CallerSummary->
calls()) {
449 Callee.first, CachedPrevailingSummary, IsPrevailing);
467 for (
auto &V : SCCNodes) {
469 LLVM_DEBUG(
dbgs() <<
"ThinLTO FunctionAttrs: Propagated NoRecurse to "
470 << V.name() <<
"\n");
471 ++NumThinLinkNoRecurse;
475 LLVM_DEBUG(
dbgs() <<
"ThinLTO FunctionAttrs: Propagated NoUnwind to "
476 << V.name() <<
"\n");
477 ++NumThinLinkNoUnwind;
480 for (
const auto &S : V.getSummaryList()) {
496 std::vector<ValueInfo> Nodes(*
I);
497 PropagateAttributes(Nodes);
507struct ArgumentGraphNode {
518 using ArgumentMapTy = std::map<Argument *, ArgumentGraphNode>;
520 ArgumentMapTy ArgumentMap;
528 ArgumentGraphNode SyntheticRoot;
531 ArgumentGraph() { SyntheticRoot.Definition =
nullptr; }
535 iterator
begin() {
return SyntheticRoot.Uses.begin(); }
536 iterator
end() {
return SyntheticRoot.Uses.end(); }
537 ArgumentGraphNode *getEntryNode() {
return &SyntheticRoot; }
539 ArgumentGraphNode *operator[](Argument *
A) {
540 ArgumentGraphNode &
Node = ArgumentMap[
A];
542 SyntheticRoot.Uses.push_back(&Node);
551 ArgumentUsesTracker(
const SCCNodeSet &SCCNodes) : SCCNodes(SCCNodes) {}
555 Action captured(
const Use *U, UseCaptureInfo UseCI)
override {
556 if (updateCaptureInfo(U, UseCI.
UseCC)) {
565 return ContinueIgnoringReturn;
576 CI |= CaptureInfo(CC);
581 if (!
F || !
F->hasExactDefinition() || !SCCNodes.count(
F)) {
582 CI |= CaptureInfo(CC);
596 CI |= CaptureInfo(CC);
600 if (UseIndex >=
F->arg_size()) {
601 assert(
F->isVarArg() &&
"More params than args in non-varargs call");
602 CI |= CaptureInfo(CC);
608 Uses.push_back(&*std::next(
F->arg_begin(), UseIndex));
618 const SCCNodeSet &SCCNodes;
626 std::optional<int64_t> Offset;
633struct ArgumentAccessInfo {
634 enum class AccessType : uint8_t {
Write, WriteWithSideEffect,
Read,
Unknown };
635 AccessType ArgAccessType;
636 ConstantRangeList AccessRanges;
640struct UsesPerBlockInfo {
641 SmallDenseMap<Instruction *, ArgumentAccessInfo, 4> Insts;
642 bool HasWrites =
false;
643 bool HasUnknownAccess =
false;
647struct ArgumentUsesSummary {
648 bool HasAnyWrite =
false;
649 bool HasWriteOutsideEntryBB =
false;
650 SmallDenseMap<const BasicBlock *, UsesPerBlockInfo, 16> UsesPerBlock;
653ArgumentAccessInfo getArgumentAccessInfo(
const Instruction *
I,
654 const ArgumentUse &ArgUse,
656 auto GetTypeAccessRange =
658 std::optional<int64_t>
Offset) -> std::optional<ConstantRange> {
672 auto GetConstantIntRange =
674 std::optional<int64_t>
Offset) -> std::optional<ConstantRange> {
676 if (ConstantLength &&
Offset) {
677 int64_t
Len = ConstantLength->getSExtValue();
695 if (
SI->isSimple() && &
SI->getOperandUse(1) == ArgUse.U) {
700 if (
auto TypeAccessRange =
701 GetTypeAccessRange(
SI->getAccessType(), ArgUse.Offset))
702 AccessRanges.
insert(*TypeAccessRange);
703 return {ArgumentAccessInfo::AccessType::Write, std::move(AccessRanges)};
706 if (LI->isSimple()) {
707 assert(&LI->getOperandUse(0) == ArgUse.U);
711 if (
auto TypeAccessRange =
712 GetTypeAccessRange(LI->getAccessType(), ArgUse.Offset))
713 return {ArgumentAccessInfo::AccessType::Read, {*TypeAccessRange}};
716 if (!MemSet->isVolatile()) {
718 if (
auto AccessRange =
719 GetConstantIntRange(MemSet->getLength(), ArgUse.Offset))
720 AccessRanges.
insert(*AccessRange);
721 return {ArgumentAccessInfo::AccessType::Write, AccessRanges};
724 if (!MTI->isVolatile()) {
725 if (&MTI->getOperandUse(0) == ArgUse.U) {
727 if (
auto AccessRange =
728 GetConstantIntRange(MTI->getLength(), ArgUse.Offset))
729 AccessRanges.
insert(*AccessRange);
730 return {ArgumentAccessInfo::AccessType::Write, AccessRanges};
731 }
else if (&MTI->getOperandUse(1) == ArgUse.U) {
732 if (
auto AccessRange =
733 GetConstantIntRange(MTI->getLength(), ArgUse.Offset))
734 return {ArgumentAccessInfo::AccessType::Read, {*AccessRange}};
741 bool IsInitialize = CB->
paramHasAttr(ArgNo, Attribute::Initializes);
742 if (IsInitialize && ArgUse.Offset) {
746 ? ArgumentAccessInfo::AccessType::Write
747 : ArgumentAccessInfo::AccessType::WriteWithSideEffect;
753 CR.getUpper() + *ArgUse.Offset));
754 return {
Access, AccessRanges};
759 return {ArgumentAccessInfo::AccessType::Unknown, {}};
764 auto &
DL =
F.getParent()->getDataLayout();
766 DL.getIndexSizeInBits(
A.getType()->getPointerAddressSpace());
767 ArgumentUsesSummary
Result;
771 for (
Use &U :
A.uses())
777 auto *BB =
I->getParent();
778 auto &BBInfo =
Result.UsesPerBlock[BB];
779 auto [It,
Inserted] = BBInfo.Insts.try_emplace(
I);
780 auto &IInfo = It->second;
785 IInfo = {ArgumentAccessInfo::AccessType::Unknown, {}};
786 BBInfo.HasUnknownAccess =
true;
790 IInfo = std::move(Info);
791 BBInfo.HasUnknownAccess |=
792 IInfo.ArgAccessType == ArgumentAccessInfo::AccessType::Unknown;
794 (IInfo.ArgAccessType == ArgumentAccessInfo::AccessType::Write ||
795 IInfo.ArgAccessType ==
796 ArgumentAccessInfo::AccessType::WriteWithSideEffect) &&
797 !IInfo.AccessRanges.empty();
798 BBInfo.HasWrites |= InfoHasWrites;
799 return InfoHasWrites;
804 while (!Worklist.
empty()) {
806 User *U = ArgUse.U->getUser();
810 std::optional<int64_t> NewOffset = std::nullopt;
814 NewOffset = *ArgUse.Offset +
Offset.getSExtValue();
816 for (
Use &U :
GEP->uses())
822 bool HasWrite = UpdateUseInfo(
I, getArgumentAccessInfo(
I, ArgUse,
DL));
824 Result.HasAnyWrite |= HasWrite;
826 if (HasWrite &&
I->getParent() != &EntryBB)
827 Result.HasWriteOutsideEntryBB =
true;
883 if (
A->hasInAllocaAttr() ||
A->hasPreallocatedAttr())
888 for (
Use &U :
A->uses()) {
893 while (!Worklist.
empty()) {
919 for (
Use &UU :
I->uses())
920 if (Visited.
insert(&UU).second)
941 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) &&
1079 !
A->hasAttribute(Attribute::NoFreeObj)) {
1081 A->addAttr(Attribute::NoFree);
1090 Attr = Attribute::ReadOnly;
1092 Attr = Attribute::WriteOnly;
1094 Attr = Attribute::ReadNone;
1097 if (
A->hasAttribute(Attr))
1102 A->removeAttr(Attribute::WriteOnly);
1103 A->removeAttr(Attribute::ReadOnly);
1104 A->removeAttr(Attribute::ReadNone);
1106 if (Attr == Attribute::ReadNone || Attr == Attribute::ReadOnly)
1107 A->removeAttr(Attribute::Writable);
1109 if (Attr == Attribute::ReadOnly)
1111 else if (Attr == Attribute::WriteOnly)
1119 auto ArgumentUses = collectArgumentUsesPerBlock(
A,
F);
1121 if (!ArgumentUses.HasAnyWrite)
1124 auto &UsesPerBlock = ArgumentUses.UsesPerBlock;
1133 auto UPB = UsesPerBlock.find(BB);
1140 if (UPB == UsesPerBlock.end() || !UPB->second.HasUnknownAccess) {
1141 bool HasAddedSuccessor =
false;
1143 if (
auto SuccI = Initialized.
find(Succ); SuccI != Initialized.
end()) {
1144 if (HasAddedSuccessor) {
1147 CRL = SuccI->second;
1148 HasAddedSuccessor =
true;
1157 if (UPB != UsesPerBlock.end()) {
1161 sort(Insts, [](std::pair<Instruction *, ArgumentAccessInfo> &
LHS,
1162 std::pair<Instruction *, ArgumentAccessInfo> &
RHS) {
1163 return LHS.first->comesBefore(
RHS.first);
1168 for (
auto &[
_, Info] :
reverse(Insts)) {
1169 if (Info.ArgAccessType == ArgumentAccessInfo::AccessType::Unknown ||
1170 Info.ArgAccessType ==
1171 ArgumentAccessInfo::AccessType::WriteWithSideEffect)
1173 if (!Info.AccessRanges.empty()) {
1174 if (Info.ArgAccessType == ArgumentAccessInfo::AccessType::Write ||
1175 Info.ArgAccessType ==
1176 ArgumentAccessInfo::AccessType::WriteWithSideEffect) {
1179 assert(Info.ArgAccessType == ArgumentAccessInfo::AccessType::Read);
1180 for (
const auto &ReadRange : Info.AccessRanges)
1192 bool OnlyScanEntryBlock = !ArgumentUses.HasWriteOutsideEntryBB;
1193 if (!OnlyScanEntryBlock)
1194 if (
auto EntryUPB = UsesPerBlock.find(&EntryBB);
1195 EntryUPB != UsesPerBlock.end())
1196 OnlyScanEntryBlock = EntryUPB->second.HasUnknownAccess;
1197 if (OnlyScanEntryBlock) {
1198 EntryCRL = VisitBlock(&EntryBB);
1199 if (EntryCRL.
empty())
1210 Initialized[BB] = CRL;
1213 auto EntryCRLI = Initialized.
find(&EntryBB);
1214 if (EntryCRLI == Initialized.
end())
1217 EntryCRL = EntryCRLI->second;
1221 "should have bailed already if EntryCRL is empty");
1223 if (
A.hasAttribute(Attribute::Initializes)) {
1225 A.getAttribute(Attribute::Initializes).getValueAsConstantRangeList();
1226 if (PreviousCRL == EntryCRL)
1228 EntryCRL = EntryCRL.
unionWith(PreviousCRL);
1240 bool SkipInitializes) {
1243 auto DetermineAccessAttrsForSingleton = [](
Argument *
A) {
1255 if (!
F->hasExactDefinition())
1263 if (
F->onlyReadsMemory() &&
F->doesNotThrow() &&
F->willReturn() &&
1264 F->getReturnType()->isVoidTy()) {
1266 if (
A.getType()->isPointerTy() && !
A.hasNoCaptureAttr()) {
1277 if (!
A.getType()->isPointerTy())
1279 bool HasNonLocalUses =
false;
1280 CaptureInfo OrigCI =
A.getAttributes().getCaptureInfo();
1282 ArgumentUsesTracker Tracker(SCCNodes);
1285 if (NewCI != OrigCI) {
1286 if (Tracker.Uses.empty()) {
1295 ArgumentGraphNode *
Node = AG[&
A];
1298 Node->Uses.push_back(AG[
Use]);
1300 HasNonLocalUses =
true;
1306 if (!HasNonLocalUses && !
A.onlyReadsMemory()) {
1311 if (DetermineAccessAttrsForSingleton(&
A))
1314 if (!SkipInitializes && !
A.onlyReadsMemory()) {
1329 const std::vector<ArgumentGraphNode *> &ArgumentSCC = *
I;
1330 if (ArgumentSCC.size() == 1) {
1331 if (!ArgumentSCC[0]->Definition)
1335 if (ArgumentSCC[0]->
Uses.size() == 1 &&
1336 ArgumentSCC[0]->Uses[0] == ArgumentSCC[0]) {
1337 Argument *
A = ArgumentSCC[0]->Definition;
1338 CaptureInfo OrigCI =
A->getAttributes().getCaptureInfo();
1340 if (NewCI != OrigCI) {
1347 if (DetermineAccessAttrsForSingleton(
A))
1356 for (ArgumentGraphNode *
I : ArgumentSCC) {
1357 ArgumentSCCNodes.
insert(
I->Definition);
1364 for (ArgumentGraphNode *
N : ArgumentSCC) {
1365 for (ArgumentGraphNode *
Use :
N->Uses) {
1367 if (ArgumentSCCNodes.
count(
A))
1378 for (ArgumentGraphNode *
N : ArgumentSCC) {
1380 CaptureInfo OrigCI =
A->getAttributes().getCaptureInfo();
1382 if (NewCI != OrigCI) {
1393 for (ArgumentGraphNode *
N : ArgumentSCC) {
1394 if (DetermineAccessAttrsForSingleton(
N->Definition))
1395 Changed.insert(
N->Definition->getParent());
1412 for (ArgumentGraphNode *
N : ArgumentSCC) {
1420 for (ArgumentGraphNode *
N : ArgumentSCC) {
1437 FlowsToReturn.
insert(Ret->getReturnValue());
1439 for (
unsigned i = 0; i != FlowsToReturn.
size(); ++i) {
1440 Value *RetVal = FlowsToReturn[i];
1453 switch (RVI->getOpcode()) {
1455 case Instruction::BitCast:
1456 case Instruction::GetElementPtr:
1457 case Instruction::AddrSpaceCast:
1458 FlowsToReturn.
insert(RVI->getOperand(0));
1460 case Instruction::Select: {
1462 FlowsToReturn.
insert(
SI->getTrueValue());
1463 FlowsToReturn.
insert(
SI->getFalseValue());
1466 case Instruction::PHI: {
1473 case Instruction::Alloca:
1475 case Instruction::Call:
1476 case Instruction::Invoke: {
1502 if (
F->returnDoesNotAlias())
1508 if (!
F->hasExactDefinition())
1513 if (!
F->getReturnType()->isPointerTy())
1521 if (
F->returnDoesNotAlias() ||
1522 !
F->getReturnType()->isPointerTy())
1525 F->setReturnDoesNotAlias();
1539 bool &Speculative) {
1540 assert(
F->getReturnType()->isPointerTy() &&
1541 "nonnull only meaningful on pointer types");
1542 Speculative =
false;
1547 FlowsToReturn.
insert(Ret->getReturnValue());
1549 auto &
DL =
F->getDataLayout();
1551 for (
unsigned i = 0; i != FlowsToReturn.
size(); ++i) {
1552 Value *RetVal = FlowsToReturn[i];
1565 case Instruction::BitCast:
1566 case Instruction::AddrSpaceCast:
1569 case Instruction::GetElementPtr:
1575 case Instruction::Select: {
1577 FlowsToReturn.
insert(
SI->getTrueValue());
1578 FlowsToReturn.
insert(
SI->getFalseValue());
1581 case Instruction::PHI: {
1587 case Instruction::Call:
1588 case Instruction::Invoke: {
1593 if (Callee && SCCNodes.count(Callee)) {
1613 bool SCCReturnsNonNull =
true;
1619 if (
F->getAttributes().hasRetAttr(Attribute::NonNull))
1625 if (!
F->hasExactDefinition())
1630 if (!
F->getReturnType()->isPointerTy())
1633 bool Speculative =
false;
1639 <<
" as nonnull\n");
1640 F->addRetAttr(Attribute::NonNull);
1648 SCCReturnsNonNull =
false;
1651 if (SCCReturnsNonNull) {
1653 if (
F->getAttributes().hasRetAttr(Attribute::NonNull) ||
1654 !
F->getReturnType()->isPointerTy())
1657 LLVM_DEBUG(
dbgs() <<
"SCC marking " <<
F->getName() <<
" as nonnull\n");
1658 F->addRetAttr(Attribute::NonNull);
1672 AttributeList Attrs =
F->getAttributes();
1673 if (Attrs.hasRetAttr(Attribute::NoUndef))
1679 if (!
F->hasExactDefinition())
1685 if (
F->hasFnAttribute(Attribute::SanitizeMemory))
1688 if (
F->getReturnType()->isVoidTy())
1695 Value *RetVal = Ret->getReturnValue();
1702 if (Attrs.hasRetAttr(Attribute::NonNull) &&
1710 Attribute Attr = Attrs.getRetAttr(Attribute::Range);
1717 FPClassTest AttrFPClass = Attrs.getRetNoFPClass();
1718 if (AttrFPClass !=
fcNone) {
1726 F->addRetAttr(Attribute::NoUndef);
1741class AttributeInferer {
1744 struct InferenceDescriptor {
1750 std::function<bool(
const Function &)> SkipFunction;
1753 std::function<bool(Instruction &)> InstrBreaksAttribute;
1756 std::function<void(
Function &)> SetAttribute;
1759 Attribute::AttrKind AKind;
1763 bool RequiresExactDefinition;
1765 InferenceDescriptor(Attribute::AttrKind AK,
1766 std::function<
bool(
const Function &)> SkipFunc,
1767 std::function<
bool(Instruction &)> InstrScan,
1768 std::function<
void(
Function &)> SetAttr,
1770 : SkipFunction(SkipFunc), InstrBreaksAttribute(InstrScan),
1771 SetAttribute(SetAttr), AKind(AK),
1772 RequiresExactDefinition(ReqExactDef) {}
1779 void registerAttrInference(InferenceDescriptor AttrInference) {
1780 InferenceDescriptors.push_back(AttrInference);
1783 void run(
const SCCNodeSet &SCCNodes, SmallPtrSet<Function *, 8> &
Changed);
1788void AttributeInferer::run(
const SCCNodeSet &SCCNodes,
1797 if (InferInSCC.
empty())
1802 if (
ID.SkipFunction(*
F))
1807 return F->isDeclaration() ||
1808 (
ID.RequiresExactDefinition && !
F->hasExactDefinition());
1815 InferInSCC, std::back_inserter(InferInThisFunc),
1816 [
F](
const InferenceDescriptor &ID) {
return !
ID.SkipFunction(*
F); });
1818 if (InferInThisFunc.empty())
1823 llvm::erase_if(InferInThisFunc, [&](
const InferenceDescriptor &ID) {
1824 if (!
ID.InstrBreaksAttribute(
I))
1829 return D.AKind ==
ID.AKind;
1835 if (InferInThisFunc.empty())
1840 if (InferInSCC.
empty())
1848 for (
auto &ID : InferInSCC) {
1849 if (
ID.SkipFunction(*
F))
1852 ID.SetAttribute(*
F);
1856struct SCCNodesResult {
1857 SCCNodeSet SCCNodes;
1864 const SCCNodeSet &SCCNodes) {
1874 if (!
I.mayThrow(
true))
1877 if (
Function *Callee = CI->getCalledFunction()) {
1881 if (SCCNodes.contains(Callee))
1894 return I.maySynchronize();
1902 if (SCCNodes.contains(Callee))
1909 if (!
I.maySynchronize())
1916 if (SCCNodes.contains(Callee))
1927 AttributeInferer AI;
1934 AI.registerAttrInference(AttributeInferer::InferenceDescriptor{
1935 Attribute::Convergent,
1937 [](
const Function &
F) {
return !
F.isConvergent(); },
1943 LLVM_DEBUG(
dbgs() <<
"Removing convergent attr from fn " <<
F.getName()
1945 F.setNotConvergent();
1958 AttributeInferer AI;
1966 AI.registerAttrInference(AttributeInferer::InferenceDescriptor{
1967 Attribute::NoUnwind,
1969 [](
const Function &
F) {
return F.doesNotThrow(); },
1976 <<
"Adding nounwind attr to fn " <<
F.getName() <<
"\n");
1977 F.setDoesNotThrow();
1989 AI.registerAttrInference(AttributeInferer::InferenceDescriptor{
1992 [](
const Function &
F) {
return F.doesNotFreeMemory(); },
1999 <<
"Adding nofree attr to fn " <<
F.getName() <<
"\n");
2000 F.setDoesNotFreeMemory();
2005 AI.registerAttrInference(AttributeInferer::InferenceDescriptor{
2008 [](
const Function &
F) {
return F.hasNoSync(); },
2015 <<
"Adding nosync attr to fn " <<
F.getName() <<
"\n");
2033 bool AnyFunctionsAddressIsTaken =
true) {
2034 for (
const auto &BB :
F) {
2035 for (
const auto &
I : BB) {
2038 if (!Callee || Callee == &
F)
2041 if (Callee->doesNotRecurse())
2044 if (!AnyFunctionsAddressIsTaken ||
2045 (Callee->isDeclaration() &&
2046 Callee->hasFnAttribute(Attribute::NoCallback)))
2060 if (SCCNodes.size() != 1)
2064 if (!
F || !
F->hasExactDefinition() ||
F->doesNotRecurse())
2070 F->setDoesNotRecurse();
2080 if (!
F || !
F->hasExactDefinition() ||
F->hasFnAttribute(Attribute::Naked) ||
2085 F->setDoesNotReturn();
2093 ColdPaths[&
F.front()] =
false;
2097 while (!Jobs.
empty()) {
2108 ColdPaths[BB] =
true;
2125 auto [Iter, Inserted] = ColdPaths.
try_emplace(Succ,
false);
2141 if (!
F || !
F->hasExactDefinition() ||
F->hasFnAttribute(Attribute::Naked) ||
2142 F->hasFnAttribute(Attribute::Cold) ||
F->hasFnAttribute(Attribute::Hot))
2147 F->addFnAttr(Attribute::Cold);
2159 if (!
F.hasExactDefinition())
2163 if (
F.mustProgress() &&
F.onlyReadsMemory())
2167 if (
F.isDeclaration())
2174 if (!Backedges.
empty())
2180 return I.willReturn();
2200 if (!
F ||
F->hasOptNone() ||
F->hasFnAttribute(Attribute::Naked) ||
2201 F->isPresplitCoroutine()) {
2206 Res.SCCNodes.insert(
F);
2211template <
typename AARGetterT>
2212static SmallPtrSet<Function *, 8>
2214 bool ArgAttrsOnly) {
2218 if (Nodes.SCCNodes.empty())
2262 bool ArgAttrsOnly =
false;
2263 if (
C.size() == 1 && SkipNonRecursive) {
2266 ArgAttrsOnly =
true;
2280 Functions.push_back(&
N.getFunction());
2283 auto ChangedFunctions =
2285 if (ChangedFunctions.empty())
2299 for (
auto *U :
Changed->users()) {
2302 FAM.invalidate(*
Call->getFunction(), FuncPA);
2317 static_cast<PassInfoMixin<PostOrderFunctionAttrsPass> *
>(
this)->
printPipeline(
2318 OS, MapClassName2PassName);
2319 if (SkipNonRecursive)
2320 OS <<
"<skip-non-recursive-function-attrs>";
2324 if (
F.doesNotRecurse())
2330 assert(!
F.isDeclaration() &&
"Cannot deduce norecurse without a definition!");
2331 assert(
F.hasInternalLinkage() &&
2332 "Can only do top-down deduction for internal linkage functions!");
2342 for (
auto &U :
F.uses()) {
2345 !CB->
getParent()->getParent()->doesNotRecurse())
2348 F.setDoesNotRecurse();
2354 assert(!
F.isDeclaration() &&
"Cannot deduce nofpclass without a definition!");
2355 unsigned NumArgs =
F.arg_size();
2360 for (
User *U :
F.users()) {
2366 for (
unsigned I = 0;
I != NumArgs; ++
I) {
2371 ArgsNoFPClass[
I] &= ~Cst->classify();
2379 if (RetNoFPClass !=
fcNone) {
2380 FPClassTest OldAttr =
F.getAttributes().getRetNoFPClass();
2381 if (OldAttr != RetNoFPClass) {
2387 for (
unsigned I = 0;
I != NumArgs; ++
I) {
2389 if (ArgNoFPClass ==
fcNone)
2392 if (OldAttr == ArgNoFPClass)
2415 if (SCC.size() != 1)
2417 Function &
F = SCC.begin()->getFunction();
2418 if (!
F.isDeclaration() &&
F.hasInternalLinkage() && !
F.use_empty())
2451 bool AnyFunctionsAddressIsTaken =
false;
2453 if (
F.isDeclaration() ||
F.doesNotRecurse())
2455 if (!
F.hasLocalLinkage() ||
F.hasAddressTaken()) {
2456 AnyFunctionsAddressIsTaken =
true;
2481 if (!
F.hasExactDefinition() ||
F.doesNotRecurse())
2488 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.
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)
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.
@ 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.
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.
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.