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: {
1506 if (
F->returnDoesNotAlias())
1512 if (!
F->hasExactDefinition())
1517 if (!
F->getReturnType()->isPointerTy())
1525 if (
F->returnDoesNotAlias() ||
1526 !
F->getReturnType()->isPointerTy())
1529 F->setReturnDoesNotAlias();
1543 bool &Speculative) {
1544 assert(
F->getReturnType()->isPointerTy() &&
1545 "nonnull only meaningful on pointer types");
1546 Speculative =
false;
1551 FlowsToReturn.
insert(Ret->getReturnValue());
1553 auto &
DL =
F->getDataLayout();
1555 for (
unsigned i = 0; i != FlowsToReturn.
size(); ++i) {
1556 Value *RetVal = FlowsToReturn[i];
1569 case Instruction::BitCast:
1570 case Instruction::AddrSpaceCast:
1573 case Instruction::GetElementPtr:
1579 case Instruction::Select: {
1581 FlowsToReturn.
insert(
SI->getTrueValue());
1582 FlowsToReturn.
insert(
SI->getFalseValue());
1585 case Instruction::PHI: {
1591 case Instruction::Call:
1592 case Instruction::Invoke: {
1597 if (Callee && SCCNodes.count(Callee)) {
1617 bool SCCReturnsNonNull =
true;
1623 if (
F->getAttributes().hasRetAttr(Attribute::NonNull))
1629 if (!
F->hasExactDefinition())
1634 if (!
F->getReturnType()->isPointerTy())
1637 bool Speculative =
false;
1643 <<
" as nonnull\n");
1644 F->addRetAttr(Attribute::NonNull);
1652 SCCReturnsNonNull =
false;
1655 if (SCCReturnsNonNull) {
1657 if (
F->getAttributes().hasRetAttr(Attribute::NonNull) ||
1658 !
F->getReturnType()->isPointerTy())
1661 LLVM_DEBUG(
dbgs() <<
"SCC marking " <<
F->getName() <<
" as nonnull\n");
1662 F->addRetAttr(Attribute::NonNull);
1677 if (Attrs.hasRetAttr(Attribute::NoUndef))
1683 if (!
F->hasExactDefinition())
1689 if (
F->hasFnAttribute(Attribute::SanitizeMemory))
1692 if (
F->getReturnType()->isVoidTy())
1699 Value *RetVal = Ret->getReturnValue();
1706 if (Attrs.hasRetAttr(Attribute::NonNull) &&
1714 Attribute Attr = Attrs.getRetAttr(Attribute::Range);
1721 FPClassTest AttrFPClass = Attrs.getRetNoFPClass();
1722 if (AttrFPClass !=
fcNone) {
1730 F->addRetAttr(Attribute::NoUndef);
1745class AttributeInferer {
1748 struct InferenceDescriptor {
1754 std::function<bool(
const Function &)> SkipFunction;
1757 std::function<bool(Instruction &)> InstrBreaksAttribute;
1760 std::function<void(
Function &)> SetAttribute;
1763 Attribute::AttrKind AKind;
1767 bool RequiresExactDefinition;
1769 InferenceDescriptor(Attribute::AttrKind AK,
1770 std::function<
bool(
const Function &)> SkipFunc,
1771 std::function<
bool(Instruction &)> InstrScan,
1772 std::function<
void(
Function &)> SetAttr,
1774 : SkipFunction(SkipFunc), InstrBreaksAttribute(InstrScan),
1775 SetAttribute(SetAttr), AKind(AK),
1776 RequiresExactDefinition(ReqExactDef) {}
1783 void registerAttrInference(InferenceDescriptor AttrInference) {
1784 InferenceDescriptors.push_back(AttrInference);
1787 void run(
const SCCNodeSet &SCCNodes, SmallPtrSet<Function *, 8> &
Changed);
1792void AttributeInferer::run(
const SCCNodeSet &SCCNodes,
1801 if (InferInSCC.
empty())
1806 if (
ID.SkipFunction(*
F))
1811 return F->isDeclaration() ||
1812 (
ID.RequiresExactDefinition && !
F->hasExactDefinition());
1819 InferInSCC, std::back_inserter(InferInThisFunc),
1820 [
F](
const InferenceDescriptor &ID) {
return !
ID.SkipFunction(*
F); });
1822 if (InferInThisFunc.empty())
1827 llvm::erase_if(InferInThisFunc, [&](
const InferenceDescriptor &ID) {
1828 if (!
ID.InstrBreaksAttribute(
I))
1833 return D.AKind ==
ID.AKind;
1839 if (InferInThisFunc.empty())
1844 if (InferInSCC.
empty())
1852 for (
auto &ID : InferInSCC) {
1853 if (
ID.SkipFunction(*
F))
1856 ID.SetAttribute(*
F);
1860struct SCCNodesResult {
1861 SCCNodeSet SCCNodes;
1868 const SCCNodeSet &SCCNodes) {
1878 if (!
I.mayThrow(
true))
1881 if (
Function *Callee = CI->getCalledFunction()) {
1885 if (SCCNodes.contains(Callee))
1898 return I.maySynchronize();
1906 if (SCCNodes.contains(Callee))
1913 if (!
I.maySynchronize())
1920 if (SCCNodes.contains(Callee))
1931 AttributeInferer AI;
1938 AI.registerAttrInference(AttributeInferer::InferenceDescriptor{
1939 Attribute::Convergent,
1941 [](
const Function &
F) {
return !
F.isConvergent(); },
1947 LLVM_DEBUG(
dbgs() <<
"Removing convergent attr from fn " <<
F.getName()
1949 F.setNotConvergent();
1962 AttributeInferer AI;
1970 AI.registerAttrInference(AttributeInferer::InferenceDescriptor{
1971 Attribute::NoUnwind,
1973 [](
const Function &
F) {
return F.doesNotThrow(); },
1980 <<
"Adding nounwind attr to fn " <<
F.getName() <<
"\n");
1981 F.setDoesNotThrow();
1993 AI.registerAttrInference(AttributeInferer::InferenceDescriptor{
1996 [](
const Function &
F) {
return F.doesNotFreeMemory(); },
2003 <<
"Adding nofree attr to fn " <<
F.getName() <<
"\n");
2004 F.setDoesNotFreeMemory();
2009 AI.registerAttrInference(AttributeInferer::InferenceDescriptor{
2012 [](
const Function &
F) {
return F.hasNoSync(); },
2019 <<
"Adding nosync attr to fn " <<
F.getName() <<
"\n");
2037 bool AnyFunctionsAddressIsTaken =
true) {
2038 for (
const auto &BB :
F) {
2039 for (
const auto &
I : BB) {
2042 if (!Callee || Callee == &
F)
2045 if (Callee->doesNotRecurse())
2048 if (!AnyFunctionsAddressIsTaken ||
2049 (Callee->isDeclaration() &&
2050 Callee->hasFnAttribute(Attribute::NoCallback)))
2064 if (SCCNodes.size() != 1)
2068 if (!
F || !
F->hasExactDefinition() ||
F->doesNotRecurse())
2074 F->setDoesNotRecurse();
2084 if (!
F || !
F->hasExactDefinition() ||
F->hasFnAttribute(Attribute::Naked) ||
2089 F->setDoesNotReturn();
2097 ColdPaths[&
F.front()] =
false;
2101 while (!Jobs.
empty()) {
2112 ColdPaths[BB] =
true;
2129 auto [Iter, Inserted] = ColdPaths.
try_emplace(Succ,
false);
2145 if (!
F || !
F->hasExactDefinition() ||
F->hasFnAttribute(Attribute::Naked) ||
2146 F->hasFnAttribute(Attribute::Cold) ||
F->hasFnAttribute(Attribute::Hot))
2151 F->addFnAttr(Attribute::Cold);
2163 if (!
F.hasExactDefinition())
2167 if (
F.mustProgress() &&
F.onlyReadsMemory())
2171 if (
F.isDeclaration())
2178 if (!Backedges.
empty())
2184 return I.willReturn();
2204 if (!
F ||
F->hasOptNone() ||
F->hasFnAttribute(Attribute::Naked) ||
2205 F->isPresplitCoroutine()) {
2210 Res.SCCNodes.insert(
F);
2215template <
typename AARGetterT>
2216static SmallPtrSet<Function *, 8>
2218 bool ArgAttrsOnly) {
2222 if (Nodes.SCCNodes.empty())
2266 bool ArgAttrsOnly =
false;
2267 if (
C.size() == 1 && SkipNonRecursive) {
2270 ArgAttrsOnly =
true;
2284 Functions.push_back(&
N.getFunction());
2287 auto ChangedFunctions =
2289 if (ChangedFunctions.empty())
2303 for (
auto *U :
Changed->users()) {
2306 FAM.invalidate(*
Call->getFunction(), FuncPA);
2321 static_cast<PassInfoMixin<PostOrderFunctionAttrsPass> *
>(
this)->
printPipeline(
2322 OS, MapClassName2PassName);
2323 if (SkipNonRecursive)
2324 OS <<
"<skip-non-recursive-function-attrs>";
2328 if (
F.doesNotRecurse())
2334 assert(!
F.isDeclaration() &&
"Cannot deduce norecurse without a definition!");
2335 assert(
F.hasInternalLinkage() &&
2336 "Can only do top-down deduction for internal linkage functions!");
2346 for (
auto &U :
F.uses()) {
2349 !CB->
getParent()->getParent()->doesNotRecurse())
2352 F.setDoesNotRecurse();
2358 assert(!
F.isDeclaration() &&
"Cannot deduce nofpclass without a definition!");
2359 unsigned NumArgs =
F.arg_size();
2364 for (
User *U :
F.users()) {
2370 for (
unsigned I = 0;
I != NumArgs; ++
I) {
2375 ArgsNoFPClass[
I] &= ~Cst->classify();
2383 if (RetNoFPClass !=
fcNone) {
2384 FPClassTest OldAttr =
F.getAttributes().getRetNoFPClass();
2385 if (OldAttr != RetNoFPClass) {
2391 for (
unsigned I = 0;
I != NumArgs; ++
I) {
2393 if (ArgNoFPClass ==
fcNone)
2396 if (OldAttr == ArgNoFPClass)
2419 if (SCC.size() != 1)
2421 Function &
F = SCC.begin()->getFunction();
2422 if (!
F.isDeclaration() &&
F.hasInternalLinkage() && !
F.use_empty())
2455 bool AnyFunctionsAddressIsTaken =
false;
2457 if (
F.isDeclaration() ||
F.doesNotRecurse())
2459 if (!
F.hasLocalLinkage() ||
F.hasAddressTaken()) {
2460 AnyFunctionsAddressIsTaken =
true;
2485 if (!
F.hasExactDefinition() ||
F.doesNotRecurse())
2492 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)
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
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.