55#ifdef EXPENSIVE_CHECKS
65#define DEBUG_TYPE "attributor"
66#define VERBOSE_DEBUG_TYPE DEBUG_TYPE "-verbose"
69 "Determine what attributes are manifested in the IR");
71STATISTIC(NumFnDeleted,
"Number of function deleted");
73 "Number of functions with exact definitions");
75 "Number of functions without exact definitions");
76STATISTIC(NumFnShallowWrappersCreated,
"Number of shallow wrappers created");
78 "Number of abstract attributes timed out before fixpoint");
80 "Number of abstract attributes in a valid fixpoint state");
82 "Number of abstract attributes manifested in IR");
94 cl::desc(
"Maximal number of fixpoint iterations."),
100 cl::desc(
"Maximal number of callees specialized for "
105 "attributor-max-initialization-chain-length",
cl::Hidden,
107 "Maximal number of chained initializations (to avoid stack overflows)"),
113 cl::desc(
"Annotate call sites of function declarations."),
cl::init(
false));
120 cl::desc(
"Allow the Attributor to create shallow "
121 "wrappers for non-exact definitions."),
126 cl::desc(
"Allow the Attributor to use IP information "
127 "derived from non-exact functions via cloning"),
134 cl::desc(
"Comma separated list of attribute names that are "
135 "allowed to be seeded."),
139 "attributor-function-seed-allow-list",
cl::Hidden,
140 cl::desc(
"Comma separated list of function names that are "
141 "allowed to be seeded."),
147 cl::desc(
"Dump the dependency graph to dot files."),
151 "attributor-depgraph-dot-filename-prefix",
cl::Hidden,
152 cl::desc(
"The prefix used for the CallGraph dot file names."));
155 cl::desc(
"View the dependency graph."),
159 cl::desc(
"Print attribute dependencies"),
163 "attributor-enable-call-site-specific-deduction",
cl::Hidden,
164 cl::desc(
"Allow the Attributor to do call site specific analysis"),
169 cl::desc(
"Print Attributor's internal call graph"),
174 cl::desc(
"Try to simplify all loads."),
179 cl::desc(
"Should a closed world be assumed, or not. Default if not set."));
202enum class NVPTXAMDGPUAddressSpace :
unsigned {
211enum class SPIRVAddressSpace :
unsigned {
230 return AS ==
static_cast<unsigned>(SPIRVAddressSpace::Generic);
232 return AS ==
static_cast<unsigned>(NVPTXAMDGPUAddressSpace::Generic);
240 return AS ==
static_cast<unsigned>(SPIRVAddressSpace::Global);
242 return AS ==
static_cast<unsigned>(NVPTXAMDGPUAddressSpace::Global);
250 return AS ==
static_cast<unsigned>(SPIRVAddressSpace::Shared);
252 return AS ==
static_cast<unsigned>(NVPTXAMDGPUAddressSpace::Shared);
260 return AS ==
static_cast<unsigned>(SPIRVAddressSpace::Constant);
262 return AS ==
static_cast<unsigned>(NVPTXAMDGPUAddressSpace::Constant);
270 return AS ==
static_cast<unsigned>(SPIRVAddressSpace::Local);
272 return AS ==
static_cast<unsigned>(NVPTXAMDGPUAddressSpace::Local);
279 if (CB->hasFnAttr(Attribute::NoSync))
283 if (!CB->isConvergent() && !CB->mayReadOrWriteMemory())
295 if (!
I.mayReadOrWriteMemory())
302 const Value &V,
bool ForAnalysisOnly) {
304 if (!ForAnalysisOnly)
321 bool UsedAssumedInformation =
false;
323 if (
A.hasGlobalVariableSimplificationCallback(*GV)) {
324 auto AssumedGV =
A.getAssumedInitializerFromCallBack(
325 *GV, &QueryingAA, UsedAssumedInformation);
326 Initializer = *AssumedGV;
330 if (!GV->hasLocalLinkage()) {
333 if (!GV->hasDefinitiveInitializer() || !GV->isConstant())
338 assert(!GV->hasLocalLinkage() || GV->hasInitializer());
341 Initializer = GV->getInitializer();
345 int64_t StorageSize =
DL.getTypeStoreSize(&Ty);
346 if (StorageSize != RangePtr->
Size)
359 return I->getFunction() == Scope;
361 return A->getParent() == Scope;
374 return A->getParent() == Scope;
376 if (
I->getFunction() == Scope) {
380 return DT->dominates(
I, CtxI);
382 if (CtxI &&
I->getParent() == CtxI->
getParent())
385 [&](
const Instruction &AfterI) { return &AfterI == CtxI; });
392 if (V.getType() == &Ty)
399 if (
C->isNullValue() && !Ty.isPtrOrPtrVectorTy())
401 if (
C->getType()->isPointerTy() && Ty.isPointerTy())
403 if (
C->getType()->getPrimitiveSizeInBits() >= Ty.getPrimitiveSizeInBits()) {
404 if (
C->getType()->isIntegerTy() && Ty.isIntegerTy())
406 if (
C->getType()->isFloatingPointTy() && Ty.isFloatingPointTy())
413std::optional<Value *>
415 const std::optional<Value *> &
B,
428 Ty = (*A)->getType();
438template <
bool IsLoad,
typename Ty>
444 LLVM_DEBUG(
dbgs() <<
"Trying to determine the potential copies of " <<
I
445 <<
" (only exact: " << OnlyExact <<
")\n";);
447 Value &Ptr = *
I.getPointerOperand();
456 A.getInfoCache().getTargetLibraryInfoForFunction(*
I.getFunction());
458 auto Pred = [&](
Value &Obj) {
466 Ptr.getType()->getPointerAddressSpace()) &&
467 A.getAssumedSimplified(Ptr, QueryingAA, UsedAssumedInformation,
471 dbgs() <<
"Underlying object is a valid nullptr, giving up.\n";);
477 LLVM_DEBUG(
dbgs() <<
"Underlying object is not supported yet: " << Obj
482 if (!GV->hasLocalLinkage() &&
483 !(GV->isConstant() && GV->hasInitializer())) {
485 "linkage, not supported yet: "
490 bool NullOnly =
true;
491 bool NullRequired =
false;
492 auto CheckForNullOnlyAndUndef = [&](std::optional<Value *> V,
494 if (!V || *V ==
nullptr)
499 NullRequired = !IsExact;
508 LLVM_DEBUG(
dbgs() <<
"Underlying object written but stored value "
509 "cannot be converted to read type: "
526 if (NewCopies.
count(V)) {
531 if (
Value *V = AdjustWrittenValueType(Acc, *
SI->getValueOperand()))
532 if (NewCopies.
count(V)) {
545 CheckForNullOnlyAndUndef(Acc.
getContent(), IsExact);
546 if (OnlyExact && !IsExact && !NullOnly &&
552 if (NullRequired && !NullOnly) {
553 LLVM_DEBUG(
dbgs() <<
"Required all `null` accesses due to non exact "
554 "one, however found non-null one: "
565 if (PotentialValueOrigins)
571 LLVM_DEBUG(
dbgs() <<
"Underlying object written through a non-store "
572 "instruction not supported yet: "
576 Value *V = AdjustWrittenValueType(Acc, *
SI->getValueOperand());
580 if (PotentialValueOrigins)
585 if (!LI && OnlyExact) {
587 "instruction not supported yet: "
598 bool HasBeenWrittenTo =
false;
603 if (!PI || !PI->forallInterferingAccesses(
606 !IsLoad, CheckAccess,
607 HasBeenWrittenTo,
Range, SkipCB)) {
610 <<
"Failed to verify all interfering accesses for underlying object: "
615 if (IsLoad && !HasBeenWrittenTo && !
Range.isUnassigned()) {
618 A, QueryingAA, Obj, *
I.getType(), TLI,
DL, &
Range);
620 LLVM_DEBUG(
dbgs() <<
"Could not determine required initial value of "
621 "underlying object, abort!\n");
624 CheckForNullOnlyAndUndef(InitialValue,
true);
625 if (NullRequired && !NullOnly) {
626 LLVM_DEBUG(
dbgs() <<
"Non exact access but initial value that is not "
627 "null or undef, abort!\n");
631 NewCopies.
insert(InitialValue);
632 if (PotentialValueOrigins)
633 NewCopyOrigins.
insert(
nullptr);
643 if (!AAUO || !AAUO->forallUnderlyingObjects(Pred)) {
645 dbgs() <<
"Underlying objects stored into could not be determined\n";);
652 for (
const auto *PI : PIs) {
653 if (!PI->getState().isAtFixpoint())
654 UsedAssumedInformation =
true;
658 if (PotentialValueOrigins)
670 A, LI, PotentialValues, &PotentialValueOrigins, QueryingAA,
671 UsedAssumedInformation, OnlyExact);
679 A,
SI, PotentialCopies,
nullptr, QueryingAA, UsedAssumedInformation,
685 bool RequireReadNone,
bool &IsKnown) {
686 if (RequireReadNone) {
698 const auto *MemLocAA =
700 if (MemLocAA && MemLocAA->isAssumedReadNone()) {
701 IsKnown = MemLocAA->isKnownReadNone();
708 const auto *MemBehaviorAA =
711 (MemBehaviorAA->isAssumedReadNone() ||
712 (!RequireReadNone && MemBehaviorAA->isAssumedReadOnly()))) {
713 IsKnown = RequireReadNone ? MemBehaviorAA->isKnownReadNone()
714 : MemBehaviorAA->isKnownReadOnly();
739 std::function<
bool(
const Function &
F)> GoBackwardsCB) {
741 dbgs() <<
"[AA] isPotentiallyReachable @" << ToFn.
getName() <<
" from "
742 << FromI <<
" [GBCB: " <<
bool(GoBackwardsCB) <<
"][#ExS: "
743 << (ExclusionSet ? std::to_string(ExclusionSet->
size()) :
"none")
746 for (
auto *ES : *ExclusionSet)
747 dbgs() << *ES <<
"\n";
755 if (GoBackwardsCB && &ToFn != FromI.
getFunction() &&
756 !GoBackwardsCB(*FromI.
getFunction()) &&
A.getInfoCache().isKernel(ToFn) &&
758 LLVM_DEBUG(
dbgs() <<
"[AA] assume kernel cannot be reached from within the "
759 "module; success\n";);
768 if (!GoBackwardsCB && !ExclusionSet) {
770 <<
" is not checked backwards and does not have an "
771 "exclusion set, abort\n");
779 while (!Worklist.
empty()) {
781 if (!Visited.
insert(CurFromI).second)
785 if (FromFn == &ToFn) {
788 LLVM_DEBUG(
dbgs() <<
"[AA] check " << *ToI <<
" from " << *CurFromI
789 <<
" intraprocedurally\n");
792 bool Result = !ReachabilityAA || ReachabilityAA->isAssumedReachable(
793 A, *CurFromI, *ToI, ExclusionSet);
795 << (Result ?
"can potentially " :
"cannot ") <<
"reach "
796 << *ToI <<
" [Intra]\n");
806 Result = !ToReachabilityAA || ToReachabilityAA->isAssumedReachable(
807 A, EntryI, *ToI, ExclusionSet);
809 <<
" " << (Result ?
"can potentially " :
"cannot ")
810 <<
"reach @" << *ToI <<
" [ToFn]\n");
818 Result = !FnReachabilityAA || FnReachabilityAA->instructionCanReach(
819 A, *CurFromI, ToFn, ExclusionSet);
821 <<
" " << (Result ?
"can potentially " :
"cannot ")
822 <<
"reach @" << ToFn.
getName() <<
" [FromFn]\n");
831 bool Result = !ReachabilityAA || ReachabilityAA->isAssumedReachable(
832 A, *CurFromI, Ret, ExclusionSet);
834 << (Result ?
"can potentially " :
"cannot ") <<
"reach "
835 << Ret <<
" [Intra]\n");
840 bool UsedAssumedInformation =
false;
841 if (
A.checkForAllInstructions(ReturnInstCB, FromFn, &QueryingAA,
842 {Instruction::Ret}, UsedAssumedInformation)) {
847 if (!GoBackwardsCB) {
849 <<
" is not checked backwards, abort\n");
855 if (!GoBackwardsCB(*FromFn))
862 CallBase *CB = ACS.getInstruction();
874 Result = !
A.checkForAllCallSites(CheckCallSite, *FromFn,
876 &QueryingAA, UsedAssumedInformation);
878 LLVM_DEBUG(
dbgs() <<
"[AA] stepping back to call sites from " << *CurFromI
879 <<
" in @" << FromFn->
getName()
880 <<
" failed, give up\n");
884 LLVM_DEBUG(
dbgs() <<
"[AA] stepped back to call sites from " << *CurFromI
885 <<
" in @" << FromFn->
getName()
886 <<
" worklist size is: " << Worklist.
size() <<
"\n");
895 std::function<
bool(
const Function &
F)> GoBackwardsCB) {
897 return ::isPotentiallyReachable(
A, FromI, &ToI, *ToFn, QueryingAA,
898 ExclusionSet, GoBackwardsCB);
905 std::function<
bool(
const Function &
F)> GoBackwardsCB) {
906 return ::isPotentiallyReachable(
A, FromI,
nullptr, ToFn, QueryingAA,
907 ExclusionSet, GoBackwardsCB);
918 dbgs() <<
"[AA] Object '" << Obj
919 <<
"' is thread local; stack objects are thread local.\n");
922 bool IsKnownNoCapture;
927 << (IsAssumedNoCapture ?
"" :
"not") <<
" thread local; "
928 << (IsAssumedNoCapture ?
"non-" :
"")
929 <<
"captured stack object.\n");
930 return IsAssumedNoCapture;
933 if (GV->isConstant()) {
935 <<
"' is thread local; constant global\n");
938 if (GV->isThreadLocal()) {
940 <<
"' is thread local; thread local global\n");
945 if (
A.getInfoCache().IsTargetGPU()) {
947 Obj.getType()->getPointerAddressSpace())) {
949 <<
"' is thread local; GPU local memory\n");
953 A.getInfoCache().getModule(),
954 Obj.getType()->getPointerAddressSpace())) {
956 <<
"' is thread local; GPU constant memory\n");
961 LLVM_DEBUG(
dbgs() <<
"[AA] Object '" << Obj <<
"' is not thread local\n");
967 if (!
I.mayHaveSideEffects() && !
I.mayReadFromMemory())
972 auto AddLocationPtr = [&](std::optional<MemoryLocation>
Loc) {
975 dbgs() <<
"[AA] Access to unknown location; -> requires barriers\n");
998 for (
const Value *Ptr : Ptrs) {
1004 auto Pred = [&](
Value &Obj) {
1007 LLVM_DEBUG(
dbgs() <<
"[AA] Access to '" << Obj <<
"' via '" << *Ptr
1008 <<
"'; -> requires barrier\n");
1014 if (!UnderlyingObjsAA || !UnderlyingObjsAA->forallUnderlyingObjects(Pred))
1039 AB.addAttribute(Kind);
1053 if (!ForceReplace && Kind == Attribute::Memory) {
1057 AB.addMemoryAttr(ME);
1064 AB.addAttribute(Attr);
1071 AB.addAttribute(Attr);
1092 std::optional<Argument *> CBCandidateArg;
1096 for (
const Use *U : CallbackUses) {
1110 "ACS mapped into var-args arguments!");
1111 if (CBCandidateArg) {
1112 CBCandidateArg =
nullptr;
1120 if (CBCandidateArg && *CBCandidateArg)
1121 return *CBCandidateArg;
1126 if (Callee && Callee->arg_size() >
unsigned(ArgNo))
1127 return Callee->getArg(ArgNo);
1141 LLVM_DEBUG(
dbgs() <<
"[Attributor] Update " << HasChanged <<
" " << *
this
1151 InfoCache(InfoCache), Configuration(Configuration) {
1155 if (Fn->hasAddressTaken(
nullptr,
1161 InfoCache.IndirectlyCallableFunctions.push_back(Fn);
1168 "Did expect a valid position!");
1185 unsigned AttrsSize = Attrs.size();
1188 for (
const auto &It : A2K)
1191 return AttrsSize != Attrs.size();
1194template <
typename DescTy>
1200 if (AttrDescs.
empty())
1212 auto It = AttrsMap.find(AttrListAnchor);
1213 if (It == AttrsMap.end())
1216 AL = It->getSecond();
1222 AttrBuilder AB(Ctx);
1225 for (
const DescTy &AttrDesc : AttrDescs)
1226 if (CB(AttrDesc, AS, AM, AB))
1232 AL = AL.removeAttributesAtIndex(Ctx, AttrIdx, AM);
1233 AL = AL.addAttributesAtIndex(Ctx, AttrIdx, AB);
1234 AttrsMap[AttrListAnchor] = AL;
1240 bool IgnoreSubsumingPositions,
1242 bool Implied =
false;
1243 bool HasAttr =
false;
1246 if (AttrSet.hasAttribute(Kind)) {
1247 Implied |= Kind != ImpliedAttributeKind;
1253 updateAttrMap<Attribute::AttrKind>(EquivIRP, AttrKinds, HasAttrCB);
1259 if (IgnoreSubsumingPositions)
1276 ImpliedAttributeKind)});
1283 bool IgnoreSubsumingPositions) {
1287 if (AttrSet.hasAttribute(Kind))
1288 Attrs.push_back(AttrSet.getAttribute(Kind));
1292 updateAttrMap<Attribute::AttrKind>(EquivIRP, AttrKinds, CollectAttrCB);
1296 if (IgnoreSubsumingPositions)
1307 if (!AttrSet.hasAttribute(Kind))
1309 AM.addAttribute(Kind);
1312 return updateAttrMap<Attribute::AttrKind>(IRP, AttrKinds, RemoveAttrCB);
1319 if (!AttrSet.hasAttribute(Attr))
1321 AM.addAttribute(Attr);
1325 return updateAttrMap<StringRef>(IRP, Attrs, RemoveAttrCB);
1330 bool ForceReplace) {
1336 return updateAttrMap<Attribute>(IRP, Attrs, AddAttrCB);
1344 IRPositions.emplace_back(IRP);
1348 auto CanIgnoreOperandBundles = [](
const CallBase &CB) {
1364 assert(CB &&
"Expected call site!");
1367 if (!CB->hasOperandBundles() || CanIgnoreOperandBundles(*CB))
1372 assert(CB &&
"Expected call site!");
1375 if (!CB->hasOperandBundles() || CanIgnoreOperandBundles(*CB)) {
1380 for (
const Argument &Arg : Callee->args())
1381 if (Arg.hasReturnedAttr()) {
1382 IRPositions.emplace_back(
1384 IRPositions.emplace_back(
1393 assert(CB &&
"Expected call site!");
1396 if (!CB->hasOperandBundles() || CanIgnoreOperandBundles(*CB)) {
1410void IRPosition::verify() {
1411#ifdef EXPENSIVE_CHECKS
1414 assert((CBContext ==
nullptr) &&
1415 "Invalid position must not have CallBaseContext!");
1417 "Expected a nullptr for an invalid position!");
1421 "Expected specialized kind for argument values!");
1425 "Expected function for a 'returned' position!");
1427 "Associated value mismatch!");
1430 assert((CBContext ==
nullptr) &&
1431 "'call site returned' position must not have CallBaseContext!");
1433 "Expected call base for 'call site returned' position!");
1435 "Associated value mismatch!");
1438 assert((CBContext ==
nullptr) &&
1439 "'call site function' position must not have CallBaseContext!");
1441 "Expected call base for 'call site function' position!");
1443 "Associated value mismatch!");
1447 "Expected function for a 'function' position!");
1449 "Associated value mismatch!");
1453 "Expected argument for a 'argument' position!");
1455 "Associated value mismatch!");
1458 assert((CBContext ==
nullptr) &&
1459 "'call site argument' position must not have CallBaseContext!");
1460 Use *U = getAsUsePtr();
1462 assert(U &&
"Expected use for a 'call site argument' position!");
1464 "Expected call base user for a 'call site argument' position!");
1466 "Expected call base argument operand for a 'call site argument' "
1470 "Argument number mismatch!");
1478std::optional<Constant *>
1481 bool &UsedAssumedInformation) {
1485 for (
auto &CB : SimplificationCallbacks.lookup(IRP)) {
1486 std::optional<Value *> SimplifiedV = CB(IRP, &
AA, UsedAssumedInformation);
1488 return std::nullopt;
1498 UsedAssumedInformation)) {
1500 return std::nullopt;
1514 for (
auto &CB : SimplificationCallbacks.lookup(IRP))
1515 return CB(IRP,
AA, UsedAssumedInformation);
1521 return std::nullopt;
1534 bool &UsedAssumedInformation,
bool RecurseForSelectAndPHI) {
1538 while (!Worklist.
empty()) {
1544 int NV = Values.
size();
1545 const auto &SimplificationCBs = SimplificationCallbacks.lookup(IRP);
1546 for (
const auto &CB : SimplificationCBs) {
1547 std::optional<Value *> CBResult = CB(IRP,
AA, UsedAssumedInformation);
1548 if (!CBResult.has_value())
1550 Value *V = *CBResult;
1559 if (SimplificationCBs.empty()) {
1562 const auto *PotentialValuesAA =
1564 if (PotentialValuesAA &&
1565 PotentialValuesAA->getAssumedSimplifiedValues(*
this, Values, S)) {
1566 UsedAssumedInformation |= !PotentialValuesAA->isAtFixpoint();
1575 if (!RecurseForSelectAndPHI)
1578 for (
int I = NV, E = Values.
size();
I < E; ++
I) {
1579 Value *V = Values[
I].getValue();
1582 if (!Seen.
insert(V).second)
1585 Values[
I] = Values[E - 1];
1599 bool &UsedAssumedInformation) {
1607 if (!Arg->hasPointeeInMemoryValueAttr())
1617 for (
auto &It : AAMap) {
1619 AA->~AbstractAttribute();
1625 bool &UsedAssumedInformation,
1626 bool CheckBBLivenessOnly,
DepClassTy DepClass) {
1627 if (!Configuration.UseLiveness)
1633 CheckBBLivenessOnly, DepClass);
1639 bool &UsedAssumedInformation,
1640 bool CheckBBLivenessOnly,
DepClassTy DepClass) {
1641 if (!Configuration.UseLiveness)
1646 UsedAssumedInformation, CheckBBLivenessOnly, DepClass);
1651 if (CB->isArgOperand(&U)) {
1655 UsedAssumedInformation, CheckBBLivenessOnly,
1661 UsedAssumedInformation, CheckBBLivenessOnly, DepClass);
1665 UsedAssumedInformation, CheckBBLivenessOnly, DepClass);
1667 if (!CheckBBLivenessOnly &&
SI->getPointerOperand() != U.get()) {
1675 UsedAssumedInformation =
true;
1682 UsedAssumedInformation, CheckBBLivenessOnly, DepClass);
1688 bool &UsedAssumedInformation,
1689 bool CheckBBLivenessOnly,
DepClassTy DepClass,
1690 bool CheckForDeadStore) {
1691 if (!Configuration.UseLiveness)
1696 if (ManifestAddedBlocks.contains(
I.getParent()))
1705 if (!FnLivenessAA || QueryingAA == FnLivenessAA)
1709 if (CheckBBLivenessOnly ? FnLivenessAA->
isAssumedDead(
I.getParent())
1714 UsedAssumedInformation =
true;
1718 if (CheckBBLivenessOnly)
1726 if (!IsDeadAA || QueryingAA == IsDeadAA)
1733 UsedAssumedInformation =
true;
1741 UsedAssumedInformation =
true;
1751 bool &UsedAssumedInformation,
1752 bool CheckBBLivenessOnly,
DepClassTy DepClass) {
1753 if (!Configuration.UseLiveness)
1764 isAssumedDead(*CtxI, QueryingAA, FnLivenessAA, UsedAssumedInformation,
1769 if (CheckBBLivenessOnly)
1782 if (!IsDeadAA || QueryingAA == IsDeadAA)
1789 UsedAssumedInformation =
true;
1800 if (!Configuration.UseLiveness)
1808 if (!FnLivenessAA || QueryingAA == FnLivenessAA)
1824 return Pred(Callee);
1828 if (!CallEdgesAA || CallEdgesAA->hasUnknownCallee())
1831 const auto &Callees = CallEdgesAA->getOptimisticEdges();
1832 return Pred(Callees.getArrayRef());
1842 bool CheckBBLivenessOnly,
DepClassTy LivenessDepClass,
1843 bool IgnoreDroppableUses,
1848 if (!CB(*
this, &QueryingAA))
1862 auto AddUsers = [&](
const Value &V,
const Use *OldUse) {
1863 for (
const Use &UU : V.uses()) {
1864 if (OldUse && EquivalentUseCB && !EquivalentUseCB(*OldUse, UU)) {
1866 "rejected by the equivalence call back: "
1876 AddUsers(V,
nullptr);
1879 <<
" initial uses to check\n");
1882 const auto *LivenessAA =
1887 while (!Worklist.
empty()) {
1893 dbgs() <<
"[Attributor] Check use: " << **U <<
" in " << Fn->getName()
1896 dbgs() <<
"[Attributor] Check use: " << **U <<
" in " << *U->getUser()
1899 bool UsedAssumedInformation =
false;
1900 if (
isAssumedDead(*U, &QueryingAA, LivenessAA, UsedAssumedInformation,
1901 CheckBBLivenessOnly, LivenessDepClass)) {
1903 dbgs() <<
"[Attributor] Dead use, skip!\n");
1906 if (IgnoreDroppableUses && U->getUser()->isDroppable()) {
1908 dbgs() <<
"[Attributor] Droppable user, skip!\n");
1913 if (&
SI->getOperandUse(0) == U) {
1914 if (!Visited.
insert(U).second)
1918 *
this, *
SI, PotentialCopies, QueryingAA, UsedAssumedInformation,
1922 <<
"[Attributor] Value is stored, continue with "
1923 << PotentialCopies.
size()
1924 <<
" potential copies instead!\n");
1925 for (
Value *PotentialCopy : PotentialCopies)
1926 if (!AddUsers(*PotentialCopy, U))
1933 bool Follow =
false;
1934 if (!Pred(*U, Follow))
1939 User &Usr = *U->getUser();
1940 AddUsers(Usr,
nullptr);
1948 bool RequireAllCallSites,
1949 bool &UsedAssumedInformation) {
1955 if (!AssociatedFunction) {
1956 LLVM_DEBUG(
dbgs() <<
"[Attributor] No function associated with " << IRP
1962 &QueryingAA, UsedAssumedInformation);
1967 bool RequireAllCallSites,
1969 bool &UsedAssumedInformation,
1970 bool CheckPotentiallyDead) {
1974 <<
"[Attributor] Function " << Fn.
getName()
1975 <<
" has no internal linkage, hence not all call sites are known\n");
1980 if (!CB(*
this, QueryingAA))
1984 for (
unsigned u = 0; u <
Uses.size(); ++u) {
1988 dbgs() <<
"[Attributor] Check use: " << Fn->
getName() <<
" in "
1989 << *U.getUser() <<
"\n";
1991 dbgs() <<
"[Attributor] Check use: " << *U <<
" in " << *U.getUser()
1994 if (!CheckPotentiallyDead &&
1995 isAssumedDead(U, QueryingAA,
nullptr, UsedAssumedInformation,
1998 dbgs() <<
"[Attributor] Dead use, skip!\n");
2002 if (CE->isCast() && CE->getType()->isPointerTy()) {
2004 dbgs() <<
"[Attributor] Use, is constant cast expression, add "
2005 << CE->getNumUses() <<
" uses of that expression instead!\n";
2007 for (
const Use &CEU : CE->uses())
2008 Uses.push_back(&CEU);
2016 <<
" has non call site use " << *U.get() <<
" in "
2017 << *U.getUser() <<
"\n");
2021 const Use *EffectiveUse =
2024 if (!RequireAllCallSites) {
2025 LLVM_DEBUG(
dbgs() <<
"[Attributor] User " << *EffectiveUse->getUser()
2026 <<
" is not a call of " << Fn.
getName()
2030 LLVM_DEBUG(
dbgs() <<
"[Attributor] User " << *EffectiveUse->getUser()
2031 <<
" is an invalid use of " << Fn.
getName() <<
"\n");
2039 unsigned MinArgsParams =
2041 for (
unsigned u = 0; u < MinArgsParams; ++u) {
2045 dbgs() <<
"[Attributor] Call site / callee argument type mismatch ["
2046 << u <<
"@" << Fn.
getName() <<
": "
2056 LLVM_DEBUG(
dbgs() <<
"[Attributor] Call site callback failed for "
2064bool Attributor::shouldPropagateCallBaseContext(
const IRPosition &IRP) {
2074 bool RecurseForSelectAndPHI) {
2078 if (!AssociatedFunction)
2081 bool UsedAssumedInformation =
false;
2085 UsedAssumedInformation, RecurseForSelectAndPHI))
2097 bool &UsedAssumedInformation,
bool CheckBBLivenessOnly =
false,
2098 bool CheckPotentiallyDead =
false) {
2099 for (
unsigned Opcode : Opcodes) {
2101 auto *Insts = OpcodeInstMap.
lookup(Opcode);
2107 if (
A && !CheckPotentiallyDead &&
2109 UsedAssumedInformation, CheckBBLivenessOnly)) {
2111 dbgs() <<
"[Attributor] Instruction " << *
I
2112 <<
" is potentially dead, skip!\n";);
2127 bool &UsedAssumedInformation,
2128 bool CheckBBLivenessOnly,
2129 bool CheckPotentiallyDead) {
2135 const auto *LivenessAA =
2136 CheckPotentiallyDead && QueryingAA
2140 auto &OpcodeInstMap = InfoCache.getOpcodeInstMapForFunction(*Fn);
2142 LivenessAA, Opcodes, UsedAssumedInformation,
2143 CheckBBLivenessOnly, CheckPotentiallyDead))
2152 bool &UsedAssumedInformation,
2153 bool CheckBBLivenessOnly,
2154 bool CheckPotentiallyDead) {
2158 UsedAssumedInformation, CheckBBLivenessOnly,
2159 CheckPotentiallyDead);
2164 bool &UsedAssumedInformation) {
2167 const Function *AssociatedFunction =
2169 if (!AssociatedFunction)
2173 const auto *LivenessAA =
2177 InfoCache.getReadOrWriteInstsForFunction(*AssociatedFunction)) {
2180 UsedAssumedInformation))
2190void Attributor::runTillFixpoint() {
2194 <<
" abstract attributes.\n");
2199 unsigned IterationCounter = 1;
2200 unsigned MaxIterations =
2210 LLVM_DEBUG(
dbgs() <<
"\n\n[Attributor] #Iteration: " << IterationCounter
2211 <<
", Worklist size: " << Worklist.
size() <<
"\n");
2216 for (
unsigned u = 0; u < InvalidAAs.
size(); ++u) {
2221 dbgs() <<
"[Attributor] InvalidAA: " << *InvalidAA
2222 <<
" has " << InvalidAA->
Deps.
size()
2223 <<
" required & optional dependences\n");
2224 for (
auto &DepIt : InvalidAA->
Deps) {
2228 dbgs() <<
" - recompute: " << *DepAA);
2233 <<
" - invalidate: " << *DepAA);
2237 InvalidAAs.
insert(DepAA);
2246 for (AbstractAttribute *ChangedAA : ChangedAAs) {
2247 for (
auto &DepIt : ChangedAA->Deps)
2249 ChangedAA->Deps.clear();
2252 LLVM_DEBUG(
dbgs() <<
"[Attributor] #Iteration: " << IterationCounter
2253 <<
", Worklist+Dependent size: " << Worklist.
size()
2262 for (AbstractAttribute *AA : Worklist) {
2263 const auto &AAState = AA->getState();
2264 if (!AAState.isAtFixpoint())
2266 ChangedAAs.push_back(AA);
2270 if (!AAState.isValidState())
2276 ChangedAAs.append(DG.SyntheticRoot.begin() + NumAAs,
2277 DG.SyntheticRoot.end());
2282 Worklist.insert_range(ChangedAAs);
2283 Worklist.insert_range(QueryAAsAwaitingUpdate);
2284 QueryAAsAwaitingUpdate.clear();
2286 }
while (!Worklist.empty() && (IterationCounter++ < MaxIterations));
2288 if (IterationCounter > MaxIterations && !Functions.empty()) {
2289 auto Remark = [&](OptimizationRemarkMissed ORM) {
2290 return ORM <<
"Attributor did not reach a fixpoint after "
2291 <<
ore::NV(
"Iterations", MaxIterations) <<
" iterations.";
2297 LLVM_DEBUG(
dbgs() <<
"\n[Attributor] Fixpoint iteration done after: "
2298 << IterationCounter <<
"/" << MaxIterations
2299 <<
" iterations\n");
2306 SmallPtrSet<AbstractAttribute *, 32> Visited;
2307 for (
unsigned u = 0;
u < ChangedAAs.size();
u++) {
2308 AbstractAttribute *ChangedAA = ChangedAAs[
u];
2309 if (!Visited.
insert(ChangedAA).second)
2312 AbstractState &State = ChangedAA->
getState();
2316 NumAttributesTimedOut++;
2319 for (
auto &DepIt : ChangedAA->
Deps)
2325 if (!Visited.
empty())
2326 dbgs() <<
"\n[Attributor] Finalized " << Visited.
size()
2327 <<
" abstract attributes.\n";
2333 "Non-query AAs should not be required to register for updates!");
2334 QueryAAsAwaitingUpdate.insert(&
AA);
2341 unsigned NumManifested = 0;
2342 unsigned NumAtFixpoint = 0;
2352 if (!State.isAtFixpoint())
2353 State.indicateOptimisticFixpoint();
2356 if (
AA->hasCallBaseContext())
2359 if (!State.isValidState())
2362 if (
AA->getCtxI() && !
isRunOn(*
AA->getAnchorScope()))
2366 bool UsedAssumedInformation =
false;
2377 AA->trackStatistics();
2378 LLVM_DEBUG(
dbgs() <<
"[Attributor] Manifest " << LocalChange <<
" : " << *
AA
2381 ManifestChange = ManifestChange | LocalChange;
2387 (void)NumManifested;
2388 (void)NumAtFixpoint;
2389 LLVM_DEBUG(
dbgs() <<
"\n[Attributor] Manifested " << NumManifested
2390 <<
" arguments while " << NumAtFixpoint
2391 <<
" were in a valid fixpoint state\n");
2393 NumAttributesManifested += NumManifested;
2394 NumAttributesValidFixpoint += NumAtFixpoint;
2399 for (
unsigned u = 0; u < NumFinalAAs; ++u)
2403 errs() <<
"Unexpected abstract attribute: "
2407 .getAssociatedValue()
2411 "remain unchanged!");
2414 for (
auto &It : AttrsMap) {
2415 AttributeList &
AL = It.getSecond();
2416 const IRPosition &IRP =
2419 : IRPosition::callsite_function(*
cast<CallBase>(It.getFirst()));
2423 return ManifestChange;
2426void Attributor::identifyDeadInternalFunctions() {
2428 if (!Configuration.DeleteFns)
2446 for (Function *
F : Functions)
2447 if (
F->hasLocalLinkage() && (
isModulePass() || !TLI->getLibFunc(*
F, LF)))
2450 SmallPtrSet<Function *, 8> LiveInternalFns;
2451 bool FoundLiveInternal =
true;
2452 while (FoundLiveInternal) {
2453 FoundLiveInternal =
false;
2454 for (Function *&
F : InternalFns) {
2458 bool UsedAssumedInformation =
false;
2460 [&](AbstractCallSite ACS) {
2462 return ToBeDeletedFunctions.count(Callee) ||
2463 (Functions.count(Callee) &&
Callee->hasLocalLinkage() &&
2464 !LiveInternalFns.
count(Callee));
2466 *
F,
true,
nullptr, UsedAssumedInformation)) {
2472 FoundLiveInternal =
true;
2476 for (Function *
F : InternalFns)
2478 ToBeDeletedFunctions.insert(
F);
2482 TimeTraceScope TimeScope(
"Attributor::cleanupIR");
2485 << ToBeDeletedFunctions.size() <<
" functions and "
2486 << ToBeDeletedBlocks.size() <<
" blocks and "
2487 << ToBeDeletedInsts.size() <<
" instructions and "
2488 << ToBeChangedValues.size() <<
" values and "
2489 << ToBeChangedUses.size() <<
" uses. To insert "
2490 << ToBeChangedToUnreachableInsts.size()
2491 <<
" unreachables.\n"
2492 <<
"Preserve manifest added " << ManifestAddedBlocks.size()
2498 auto ReplaceUse = [&](
Use *
U,
Value *NewV) {
2503 const auto &
Entry = ToBeChangedValues.lookup(NewV);
2511 "Cannot replace an instruction outside the current SCC!");
2517 if (CI->isMustTailCall() && !ToBeDeletedInsts.count(CI))
2522 for (
auto &Arg : RI->getFunction()->args())
2523 Arg.removeAttr(Attribute::Returned);
2527 <<
" instead of " << *OldV <<
"\n");
2531 CGModifiedFunctions.insert(
I->getFunction());
2538 if (CB->isArgOperand(U)) {
2539 unsigned Idx = CB->getArgOperandNo(U);
2540 CB->removeParamAttr(Idx, Attribute::NoUndef);
2542 if (Callee &&
Callee->arg_size() > Idx)
2543 Callee->removeParamAttr(Idx, Attribute::NoUndef);
2549 ToBeChangedToUnreachableInsts.insert(UserI);
2556 for (
auto &It : ToBeChangedUses) {
2558 Value *NewV = It.second;
2559 ReplaceUse(U, NewV);
2563 for (
auto &It : ToBeChangedValues) {
2564 Value *OldV = It.first;
2565 auto [NewV,
Done] = It.second;
2567 for (
auto &U : OldV->
uses())
2568 if (
Done || !
U.getUser()->isDroppable())
2570 for (Use *U :
Uses) {
2574 ReplaceUse(U, NewV);
2578 for (
const auto &V : InvokeWithDeadSuccessor)
2581 "Cannot replace an invoke outside the current SCC!");
2582 bool UnwindBBIsDead =
II->hasFnAttr(Attribute::NoUnwind);
2583 bool NormalBBIsDead =
II->hasFnAttr(Attribute::NoReturn);
2584 bool Invoke2CallAllowed =
2586 assert((UnwindBBIsDead || NormalBBIsDead) &&
2587 "Invoke does not have dead successors!");
2590 if (UnwindBBIsDead) {
2592 if (Invoke2CallAllowed) {
2597 ToBeChangedToUnreachableInsts.insert(NormalNextIP);
2599 assert(NormalBBIsDead &&
"Broken invariant!");
2602 ToBeChangedToUnreachableInsts.insert(&NormalDestBB->
front());
2605 for (Instruction *
I : TerminatorsToFold) {
2607 "Cannot replace a terminator outside the current SCC!");
2608 CGModifiedFunctions.insert(
I->getFunction());
2611 for (
const auto &V : ToBeChangedToUnreachableInsts)
2616 "Cannot replace an instruction outside the current SCC!");
2617 CGModifiedFunctions.insert(
I->getFunction());
2621 for (
const auto &V : ToBeDeletedInsts) {
2625 "Cannot delete an instruction outside the current SCC!");
2626 I->dropDroppableUses();
2627 CGModifiedFunctions.insert(
I->getFunction());
2628 if (!
I->getType()->isVoidTy())
2633 I->eraseFromParent();
2640 dbgs() <<
"[Attributor] DeadInsts size: " << DeadInsts.
size() <<
"\n";
2641 for (
auto &
I : DeadInsts)
2643 dbgs() <<
" - " << *
I <<
"\n";
2648 if (
unsigned NumDeadBlocks = ToBeDeletedBlocks.size()) {
2649 SmallVector<BasicBlock *, 8> ToBeDeletedBBs;
2650 ToBeDeletedBBs.
reserve(NumDeadBlocks);
2651 for (BasicBlock *BB : ToBeDeletedBlocks) {
2653 "Cannot delete a block outside the current SCC!");
2654 CGModifiedFunctions.insert(BB->
getParent());
2656 if (ManifestAddedBlocks.contains(BB))
2666 identifyDeadInternalFunctions();
2669 ChangeStatus ManifestChange = rewriteFunctionSignatures(CGModifiedFunctions);
2671 for (Function *Fn : CGModifiedFunctions)
2672 if (!ToBeDeletedFunctions.count(Fn) && Functions.count(Fn))
2673 Configuration.CGUpdater.reanalyzeFunction(*Fn);
2675 for (Function *Fn : ToBeDeletedFunctions) {
2676 if (!Functions.count(Fn))
2678 Configuration.CGUpdater.removeFunction(*Fn);
2681 if (!ToBeChangedUses.empty())
2684 if (!ToBeChangedToUnreachableInsts.empty())
2687 if (!ToBeDeletedFunctions.empty())
2690 if (!ToBeDeletedBlocks.empty())
2693 if (!ToBeDeletedInsts.empty())
2696 if (!InvokeWithDeadSuccessor.empty())
2699 if (!DeadInsts.empty())
2702 NumFnDeleted += ToBeDeletedFunctions.size();
2704 LLVM_DEBUG(
dbgs() <<
"[Attributor] Deleted " << ToBeDeletedFunctions.size()
2705 <<
" functions after manifest.\n");
2707#ifdef EXPENSIVE_CHECKS
2708 for (Function *
F : Functions) {
2709 if (ToBeDeletedFunctions.count(
F))
2715 return ManifestChange;
2720 AttributorCallGraph ACallGraph(*
this);
2725 Phase = AttributorPhase::UPDATE;
2738 Phase = AttributorPhase::MANIFEST;
2741 Phase = AttributorPhase::CLEANUP;
2747 return ManifestChange | CleanupChange;
2752 return AA.getName().str() +
2753 std::to_string(
AA.getIRPosition().getPositionKind());
2756 "We can update AA only in the update stage!");
2759 DependenceVector DV;
2760 DependenceStack.push_back(&DV);
2762 auto &AAState =
AA.getState();
2764 bool UsedAssumedInformation =
false;
2767 CS =
AA.update(*
this);
2769 if (!
AA.isQueryAA() && DV.empty() && !
AA.getState().isAtFixpoint()) {
2776 RerunCS =
AA.update(*
this);
2782 AAState.indicateOptimisticFixpoint();
2785 if (!AAState.isAtFixpoint())
2786 rememberDependences();
2790 DependenceVector *PoppedDV = DependenceStack.pop_back_val();
2792 assert(PoppedDV == &DV &&
"Inconsistent usage of the dependence stack!");
2798 assert(!
F.isDeclaration() &&
"Cannot create a wrapper around a declaration!");
2807 M.getFunctionList().insert(
F.getIterator(),
Wrapper);
2812 assert(
F.use_empty() &&
"Uses remained after wrapper was created!");
2817 F.setComdat(
nullptr);
2821 F.getAllMetadata(MDs);
2822 for (
auto MDIt : MDs)
2823 Wrapper->addMetadata(MDIt.first, *MDIt.second);
2824 Wrapper->setAttributes(
F.getAttributes());
2832 Args.push_back(&Arg);
2833 Arg.setName((FArgIt++)->
getName());
2841 NumFnShallowWrappersCreated++;
2845 if (
F.isDeclaration() ||
F.hasLocalLinkage() ||
2861 return InternalizedFns[&
F];
2879 F->getName() +
".internalized");
2882 for (
auto &Arg :
F->args()) {
2883 auto ArgName = Arg.getName();
2884 NewFArgIt->setName(ArgName);
2885 VMap[&Arg] = &(*NewFArgIt++);
2900 F->getAllMetadata(MDs);
2901 for (
auto MDIt : MDs)
2905 M.getFunctionList().insert(
F->getIterator(), Copied);
2913 auto &InternalizedFn = FnMap[
F];
2914 auto IsNotInternalized = [&](
Use &U) ->
bool {
2916 return !FnMap.
lookup(CB->getCaller());
2919 F->replaceUsesWithIf(InternalizedFn, IsNotInternalized);
2928 if (!Configuration.RewriteSignatures)
2951 LLVM_DEBUG(
dbgs() <<
"[Attributor] Cannot rewrite var-args functions\n");
2957 if (FnAttributeList.hasAttrSomewhere(Attribute::Nest) ||
2958 FnAttributeList.hasAttrSomewhere(Attribute::StructRet) ||
2959 FnAttributeList.hasAttrSomewhere(Attribute::InAlloca) ||
2960 FnAttributeList.hasAttrSomewhere(Attribute::Preallocated)) {
2962 dbgs() <<
"[Attributor] Cannot rewrite due to complex attribute\n");
2967 bool UsedAssumedInformation =
false;
2969 UsedAssumedInformation,
2971 LLVM_DEBUG(
dbgs() <<
"[Attributor] Cannot rewrite all call sites\n");
2977 return !CI->isMustTailCall();
2983 auto &OpcodeInstMap = InfoCache.getOpcodeInstMapForFunction(*Fn);
2985 nullptr, {Instruction::Call},
2986 UsedAssumedInformation)) {
2987 LLVM_DEBUG(
dbgs() <<
"[Attributor] Cannot rewrite due to instructions\n");
2998 LLVM_DEBUG(
dbgs() <<
"[Attributor] Register new rewrite of " << Arg <<
" in "
3000 << ReplacementTypes.
size() <<
" replacements\n");
3002 "Cannot register an invalid rewrite");
3006 ArgumentReplacementMap[Fn];
3012 std::unique_ptr<ArgumentReplacementInfo> &ARI = ARIs[Arg.
getArgNo()];
3013 if (ARI && ARI->getNumReplacementArgs() <= ReplacementTypes.
size()) {
3014 LLVM_DEBUG(
dbgs() <<
"[Attributor] Existing rewrite is preferred\n");
3022 LLVM_DEBUG(
dbgs() <<
"[Attributor] Register new rewrite of " << Arg <<
" in "
3024 << ReplacementTypes.
size() <<
" replacements\n");
3028 std::move(CalleeRepairCB),
3029 std::move(ACSRepairCB)));
3050 for (
auto &It : ArgumentReplacementMap) {
3054 if (!Functions.count(OldFn) || ToBeDeletedFunctions.count(OldFn))
3067 if (
const std::unique_ptr<ArgumentReplacementInfo> &ARI =
3068 ARIs[Arg.getArgNo()]) {
3069 NewArgumentTypes.
append(ARI->ReplacementTypes.begin(),
3070 ARI->ReplacementTypes.end());
3071 NewArgumentAttributes.
append(ARI->getNumReplacementArgs(),
3074 NewArgumentTypes.
push_back(Arg.getType());
3076 OldFnAttributeList.getParamAttrs(Arg.getArgNo()));
3080 uint64_t LargestVectorWidth = 0;
3081 for (
auto *
I : NewArgumentTypes)
3083 LargestVectorWidth =
3084 std::max(LargestVectorWidth,
3085 VT->getPrimitiveSizeInBits().getKnownMinValue());
3088 Type *RetTy = OldFnTy->getReturnType();
3091 FunctionType *NewFnTy =
3096 << *NewFnTy <<
"\n");
3101 Functions.insert(NewFn);
3114 Ctx, OldFnAttributeList.getFnAttrs(), OldFnAttributeList.getRetAttrs(),
3115 NewArgumentAttributes));
3116 AttributeFuncs::updateMinLegalVectorWidthAttr(*NewFn, LargestVectorWidth);
3124 return !
T->isPtrOrPtrVectorTy() ||
3140 auto CallSiteReplacementCreator = [&](AbstractCallSite ACS) {
3142 const AttributeList &OldCallAttributeList = OldCB->
getAttributes();
3145 SmallVector<Value *, 16> NewArgOperands;
3147 for (
unsigned OldArgNum = 0; OldArgNum < ARIs.
size(); ++OldArgNum) {
3148 unsigned NewFirstArgNum = NewArgOperands.
size();
3149 (void)NewFirstArgNum;
3150 if (
const std::unique_ptr<ArgumentReplacementInfo> &ARI =
3152 if (ARI->ACSRepairCB)
3153 ARI->ACSRepairCB(*ARI, ACS, NewArgOperands);
3154 assert(ARI->getNumReplacementArgs() + NewFirstArgNum ==
3155 NewArgOperands.
size() &&
3156 "ACS repair callback did not provide as many operand as new "
3157 "types were registered!");
3159 NewArgOperandAttributes.
append(ARI->ReplacementTypes.size(),
3164 OldCallAttributeList.getParamAttrs(OldArgNum));
3168 assert(NewArgOperands.
size() == NewArgOperandAttributes.
size() &&
3169 "Mismatch # argument operands vs. # argument operand attributes!");
3171 "Mismatch # argument operands vs. # function arguments!");
3180 II->getUnwindDest(), NewArgOperands,
3185 NewCI->setTailCallKind(
cast<CallInst>(OldCB)->getTailCallKind());
3190 NewCB->
copyMetadata(*OldCB, {LLVMContext::MD_prof, LLVMContext::MD_dbg});
3194 Ctx, OldCallAttributeList.getFnAttrs(),
3195 OldCallAttributeList.getRetAttrs(), NewArgOperandAttributes));
3197 AttributeFuncs::updateMinLegalVectorWidthAttr(*NewCB->
getCaller(),
3198 LargestVectorWidth);
3200 CallSitePairs.
push_back({OldCB, NewCB});
3205 bool UsedAssumedInformation =
false;
3207 true,
nullptr, UsedAssumedInformation,
3210 assert(
Success &&
"Assumed call site replacement to succeed!");
3215 for (
unsigned OldArgNum = 0; OldArgNum < ARIs.
size();
3216 ++OldArgNum, ++OldFnArgIt) {
3217 if (
const std::unique_ptr<ArgumentReplacementInfo> &ARI =
3219 if (ARI->CalleeRepairCB)
3220 ARI->CalleeRepairCB(*ARI, *NewFn, NewFnArgIt);
3221 if (ARI->ReplacementTypes.empty())
3224 NewFnArgIt += ARI->ReplacementTypes.size();
3226 NewFnArgIt->
takeName(&*OldFnArgIt);
3233 for (
auto &CallSitePair : CallSitePairs) {
3234 CallBase &OldCB = *CallSitePair.first;
3235 CallBase &NewCB = *CallSitePair.second;
3237 "Cannot handle call sites with different types!");
3244 Configuration.CGUpdater.replaceFunctionWith(*OldFn, *NewFn);
3248 if (ModifiedFns.
remove(OldFn))
3249 ModifiedFns.
insert(NewFn);
3257void InformationCache::initializeInformationCache(
const Function &CF,
3264 FI.IsKernel =
F.hasFnAttribute(
"kernel");
3270 DenseMap<const Value *, std::optional<short>> AssumeUsesMap;
3275 auto AddToAssumeUsesMap = [&](
const Value &
V) ->
void {
3276 SmallVector<const Instruction *> Worklist;
3279 while (!Worklist.
empty()) {
3281 std::optional<short> &NumUses = AssumeUsesMap[
I];
3283 NumUses =
I->getNumUses();
3284 NumUses = *NumUses - 1;
3287 AssumeOnlyValues.insert(
I);
3288 for (
const Value *
Op :
I->operands())
3295 bool IsInterestingOpcode =
false;
3302 switch (
I.getOpcode()) {
3305 "New call base instruction type needs to be known in the "
3308 case Instruction::Call:
3313 AssumeOnlyValues.insert(Assume);
3315 AddToAssumeUsesMap(*
Assume->getArgOperand(0));
3317 FI.ContainsMustTailCall =
true;
3320 getFunctionInfo(*Callee).CalledViaMustTail =
true;
3323 case Instruction::CallBr:
3324 case Instruction::Invoke:
3325 case Instruction::CleanupRet:
3326 case Instruction::CatchSwitch:
3327 case Instruction::AtomicRMW:
3328 case Instruction::AtomicCmpXchg:
3329 case Instruction::UncondBr:
3330 case Instruction::CondBr:
3331 case Instruction::Resume:
3332 case Instruction::Ret:
3333 case Instruction::Load:
3335 case Instruction::Store:
3337 case Instruction::Alloca:
3338 case Instruction::AddrSpaceCast:
3339 IsInterestingOpcode =
true;
3341 if (IsInterestingOpcode) {
3342 auto *&Insts = FI.OpcodeInstMap[
I.getOpcode()];
3347 if (
I.mayReadOrWriteMemory())
3348 FI.RWInsts.push_back(&
I);
3351 if (
F.hasFnAttribute(Attribute::AlwaysInline) &&
3353 InlineableFunctions.insert(&
F);
3356InformationCache::FunctionInfo::~FunctionInfo() {
3359 for (
auto &It : OpcodeInstMap)
3360 It.getSecond()->~InstructionVectorTy();
3365 assert(
A.isClosedWorldModule() &&
"Cannot see all indirect callees!");
3366 return IndirectlyCallableFunctions;
3372 return std::nullopt;
3383 if (DependenceStack.empty())
3387 DependenceStack.back()->push_back({&FromAA, &ToAA, DepClass});
3390void Attributor::rememberDependences() {
3391 assert(!DependenceStack.empty() &&
"No dependences to remember!");
3393 for (DepInfo &DI : *DependenceStack.back()) {
3396 "Expected required or optional dependence (1 bit)!");
3403template <Attribute::AttrKind AK,
typename AAType>
3404void Attributor::checkAndQueryIRAttr(
const IRPosition &IRP, AttributeSet Attrs,
3405 bool SkipHasAttrCheck) {
3407 if (SkipHasAttrCheck || !
Attrs.hasAttribute(AK))
3408 if (!Configuration.Allowed || Configuration.Allowed->count(&AAType::ID))
3411 getOrCreateAAFor<AAType>(IRP);
3417 if (!VisitedFunctions.insert(&
F).second)
3423 InformationCache::FunctionInfo &FI = InfoCache.getFunctionInfo(
F);
3425 for (
const Use &U :
F.uses())
3427 if (CB->isCallee(&U) && CB->isMustTailCall())
3428 FI.CalledViaMustTail =
true;
3433 auto Attrs =
F.getAttributes();
3434 auto FnAttrs = Attrs.getFnAttrs();
3450 checkAndQueryIRAttr<Attribute::MustProgress, AAMustProgress>(FPos, FnAttrs);
3453 checkAndQueryIRAttr<Attribute::NoFree, AANoFree>(FPos, FnAttrs);
3456 checkAndQueryIRAttr<Attribute::WillReturn, AAWillReturn>(FPos, FnAttrs);
3459 checkAndQueryIRAttr<Attribute::NoSync, AANoSync>(FPos, FnAttrs);
3464 if (IsIPOAmendable) {
3467 checkAndQueryIRAttr<Attribute::NoUnwind, AANoUnwind>(FPos, FnAttrs);
3470 checkAndQueryIRAttr<Attribute::NoReturn, AANoReturn>(FPos, FnAttrs);
3473 checkAndQueryIRAttr<Attribute::NoRecurse, AANoRecurse>(FPos, FnAttrs);
3476 if (Attrs.hasFnAttr(Attribute::Convergent))
3497 Type *ReturnType =
F.getReturnType();
3498 if (!ReturnType->isVoidTy()) {
3506 bool UsedAssumedInformation =
false;
3511 checkAndQueryIRAttr<Attribute::NoUndef, AANoUndef>(RetPos, RetAttrs);
3513 if (ReturnType->isPointerTy()) {
3519 checkAndQueryIRAttr<Attribute::NonNull, AANonNull>(RetPos, RetAttrs);
3522 checkAndQueryIRAttr<Attribute::NoAlias, AANoAlias>(RetPos, RetAttrs);
3527 }
else if (AttributeFuncs::isNoFPClassCompatibleType(ReturnType)) {
3535 auto ArgNo = Arg.getArgNo();
3538 if (!IsIPOAmendable) {
3539 if (Arg.getType()->isPointerTy())
3541 checkAndQueryIRAttr<Attribute::NoFree, AANoFree>(ArgPos, ArgAttrs);
3548 bool UsedAssumedInformation =
false;
3556 checkAndQueryIRAttr<Attribute::NoUndef, AANoUndef>(ArgPos, ArgAttrs);
3558 if (Arg.getType()->isPointerTy()) {
3560 checkAndQueryIRAttr<Attribute::NonNull, AANonNull>(ArgPos, ArgAttrs);
3563 checkAndQueryIRAttr<Attribute::NoAlias, AANoAlias>(ArgPos, ArgAttrs);
3572 checkAndQueryIRAttr<Attribute::Captures, AANoCapture>(
3573 ArgPos, ArgAttrs,
true);
3580 checkAndQueryIRAttr<Attribute::NoFree, AANoFree>(ArgPos, ArgAttrs);
3585 }
else if (AttributeFuncs::isNoFPClassCompatibleType(Arg.getType())) {
3613 !Callee->hasMetadata(LLVMContext::MD_callback))
3616 if (!Callee->getReturnType()->isVoidTy() && !CB.use_empty()) {
3618 bool UsedAssumedInformation =
false;
3622 if (AttributeFuncs::isNoFPClassCompatibleType(Callee->getReturnType()))
3626 const AttributeList &CBAttrs = CBFnPos.
getAttrList();
3627 for (
int I = 0, E = CB.arg_size();
I < E; ++
I) {
3638 bool UsedAssumedInformation =
false;
3643 checkAndQueryIRAttr<Attribute::NoUndef, AANoUndef>(CBArgPos, CBArgAttrs);
3645 Type *ArgTy = CB.getArgOperand(
I)->getType();
3648 if (AttributeFuncs::isNoFPClassCompatibleType(ArgTy))
3655 checkAndQueryIRAttr<Attribute::NonNull, AANonNull>(CBArgPos, CBArgAttrs);
3658 checkAndQueryIRAttr<Attribute::Captures, AANoCapture>(
3659 CBArgPos, CBArgAttrs,
true);
3662 checkAndQueryIRAttr<Attribute::NoAlias, AANoAlias>(CBArgPos, CBArgAttrs);
3672 if (!CBAttrs.hasParamAttr(
I, Attribute::ReadNone))
3676 checkAndQueryIRAttr<Attribute::NoFree, AANoFree>(CBArgPos, CBArgAttrs);
3681 auto &OpcodeInstMap = InfoCache.getOpcodeInstMapForFunction(
F);
3682 [[maybe_unused]]
bool Success;
3683 bool UsedAssumedInformation =
false;
3685 nullptr, OpcodeInstMap, CallSitePred,
nullptr,
nullptr,
3686 {(
unsigned)Instruction::Invoke, (
unsigned)Instruction::CallBr,
3688 UsedAssumedInformation);
3689 assert(
Success &&
"Expected the check call to be successful!");
3713 nullptr, OpcodeInstMap, LoadStorePred,
nullptr,
nullptr,
3714 {(
unsigned)Instruction::Load, (
unsigned)Instruction::Store},
3715 UsedAssumedInformation);
3716 assert(
Success &&
"Expected the check call to be successful!");
3719 auto AAAllocationInfoPred = [&](
Instruction &
I) ->
bool {
3725 nullptr, OpcodeInstMap, AAAllocationInfoPred,
nullptr,
nullptr,
3726 {(
unsigned)Instruction::Alloca}, UsedAssumedInformation);
3727 assert(
Success &&
"Expected the check call to be successful!");
3733 return isModulePass() && Configuration.IsClosedWorldModule;
3750 return OS <<
"fn_ret";
3752 return OS <<
"cs_ret";
3760 return OS <<
"cs_arg";
3782 return OS << static_cast<const AbstractState &>(S);
3796 OS <<
"set-state(< {";
3812 OS <<
"set-state(< {";
3818 OS <<
"@" <<
F->getName() <<
"[" << int(It.second) <<
"], ";
3820 OS << *It.first.getValue() <<
"[" << int(It.second) <<
"], ";
3833 OS <<
"] for CtxI ";
3840 OS <<
"<<null inst>>";
3849 for (
const auto &DepAA :
Deps) {
3850 auto *
AA = DepAA.getPointer();
3867 OS <<
" [ <unknown> ]";
3881 bool DeleteFns,
bool IsModulePass) {
3882 if (Functions.empty())
3886 dbgs() <<
"[Attributor] Run on module with " << Functions.size()
3895 AC.IsModulePass = IsModulePass;
3896 AC.DeleteFns = DeleteFns;
3900 IndirectCalleeTrackingMap;
3902 AC.IndirectCalleeSpecializationCallback =
3907 auto &Set = IndirectCalleeTrackingMap[&CB];
3909 Set = std::make_unique<SmallPtrSet<Function *, 8>>();
3911 return Set->contains(&Callee);
3912 Set->insert(&Callee);
3922 if (!
A.isFunctionIPOAmendable(*
F))
3930 unsigned FunSize = Functions.size();
3931 for (
unsigned u = 0; u < FunSize; u++) {
3933 if (!
F->isDeclaration() && !
F->isDefinitionExact() && !
F->use_empty() &&
3936 assert(NewF &&
"Could not internalize function.");
3937 Functions.insert(NewF);
3941 for (
const Use &U : NewF->
uses())
3943 auto *CallerF = CB->getCaller();
3951 if (
F->isDeclaration())
3954 if (
F->hasExactDefinition())
3955 NumFnWithExactDefinition++;
3957 NumFnWithoutExactDefinition++;
3962 if (
F->hasLocalLinkage()) {
3964 const auto *CB = dyn_cast<CallBase>(U.getUser());
3965 return CB && CB->isCallee(&U) &&
3966 Functions.count(const_cast<Function *>(CB->getCaller()));
3973 A.identifyDefaultAbstractAttributes(*
F);
3978 LLVM_DEBUG(
dbgs() <<
"[Attributor] Done with " << Functions.size()
3979 <<
" functions, result: " <<
Changed <<
".\n");
3988 bool IsModulePass) {
3989 if (Functions.empty())
3993 dbgs() <<
"[AttributorLight] Run on module with " << Functions.size()
4002 AC.IsModulePass = IsModulePass;
4003 AC.DeleteFns =
false;
4011 AC.Allowed = &Allowed;
4012 AC.UseLiveness =
false;
4017 if (
F->isDeclaration())
4020 if (
F->hasExactDefinition())
4021 NumFnWithExactDefinition++;
4023 NumFnWithoutExactDefinition++;
4028 if (AC.UseLiveness &&
F->hasLocalLinkage()) {
4030 const auto *CB = dyn_cast<CallBase>(U.getUser());
4031 return CB && CB->isCallee(&U) &&
4032 Functions.count(const_cast<Function *>(CB->getCaller()));
4039 A.identifyDefaultAbstractAttributes(*
F);
4056 for (
auto *U :
Changed->users()) {
4059 FAM.invalidate(*
Call->getFunction(), FuncPA);
4064 LLVM_DEBUG(
dbgs() <<
"[Attributor] Done with " << Functions.size()
4065 <<
" functions, result: " <<
Changed <<
".\n");
4072 static std::atomic<int> CallTimes;
4078 Prefix =
"dep_graph";
4080 Prefix +
"_" + std::to_string(CallTimes.load()) +
".dot";
4082 outs() <<
"Dependency graph dump to " <<
Filename <<
".\n";
4128 Functions.
insert(&
N.getFunction());
4130 if (Functions.empty())
4133 Module &M = *Functions.back()->getParent();
4184 Functions.
insert(&
N.getFunction());
4186 if (Functions.empty())
4189 Module &M = *Functions.back()->getParent();
4241 std::string AAString;
aarch64 falkor hwpf fix Falkor HW Prefetch Fix Late Phase
static unsigned getIntrinsicID(const SDNode *N)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
amdgpu aa AMDGPU Address space based Alias Analysis Wrapper
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Expand Atomic instructions
This file contains the simple types necessary to represent the attributes associated with functions a...
static cl::opt< bool > AllowShallowWrappers("attributor-allow-shallow-wrappers", cl::Hidden, cl::desc("Allow the Attributor to create shallow " "wrappers for non-exact definitions."), cl::init(false))
bool canMarkAsVisited(const User *Usr)
#define VERBOSE_DEBUG_TYPE
static cl::opt< bool > EnableHeapToStack("enable-heap-to-stack-conversion", cl::init(true), cl::Hidden)
static cl::list< std::string > SeedAllowList("attributor-seed-allow-list", cl::Hidden, cl::desc("Comma separated list of attribute names that are " "allowed to be seeded."), cl::CommaSeparated)
static bool runAttributorOnFunctions(InformationCache &InfoCache, SetVector< Function * > &Functions, AnalysisGetter &AG, CallGraphUpdater &CGUpdater, bool DeleteFns, bool IsModulePass)
}
static bool getPotentialCopiesOfMemoryValue(Attributor &A, Ty &I, SmallSetVector< Value *, 4 > &PotentialCopies, SmallSetVector< Instruction *, 4 > *PotentialValueOrigins, const AbstractAttribute &QueryingAA, bool &UsedAssumedInformation, bool OnlyExact)
static bool runAttributorLightOnFunctions(InformationCache &InfoCache, SetVector< Function * > &Functions, AnalysisGetter &AG, CallGraphUpdater &CGUpdater, FunctionAnalysisManager &FAM, bool IsModulePass)
static cl::opt< unsigned, true > MaxInitializationChainLengthX("attributor-max-initialization-chain-length", cl::Hidden, cl::desc("Maximal number of chained initializations (to avoid stack overflows)"), cl::location(MaxInitializationChainLength), cl::init(1024))
static cl::opt< unsigned > MaxSpecializationPerCB("attributor-max-specializations-per-call-base", cl::Hidden, cl::desc("Maximal number of callees specialized for " "a call base"), cl::init(UINT32_MAX))
static cl::opt< bool > SimplifyAllLoads("attributor-simplify-all-loads", cl::Hidden, cl::desc("Try to simplify all loads."), cl::init(true))
static bool addIfNotExistent(LLVMContext &Ctx, const Attribute &Attr, AttributeSet AttrSet, bool ForceReplace, AttrBuilder &AB)
Return true if the information provided by Attr was added to the attribute set AttrSet.
static cl::opt< bool > ViewDepGraph("attributor-view-dep-graph", cl::Hidden, cl::desc("View the dependency graph."), cl::init(false))
static bool isEqualOrWorse(const Attribute &New, const Attribute &Old)
Return true if New is equal or worse than Old.
static cl::opt< bool > AllowDeepWrapper("attributor-allow-deep-wrappers", cl::Hidden, cl::desc("Allow the Attributor to use IP information " "derived from non-exact functions via cloning"), cl::init(false))
static cl::opt< bool > DumpDepGraph("attributor-dump-dep-graph", cl::Hidden, cl::desc("Dump the dependency graph to dot files."), cl::init(false))
static cl::opt< bool > PrintCallGraph("attributor-print-call-graph", cl::Hidden, cl::desc("Print Attributor's internal call graph"), cl::init(false))
static bool checkForAllInstructionsImpl(Attributor *A, InformationCache::OpcodeInstMapTy &OpcodeInstMap, function_ref< bool(Instruction &)> Pred, const AbstractAttribute *QueryingAA, const AAIsDead *LivenessAA, ArrayRef< unsigned > Opcodes, bool &UsedAssumedInformation, bool CheckBBLivenessOnly=false, bool CheckPotentiallyDead=false)
static cl::opt< bool > PrintDependencies("attributor-print-dep", cl::Hidden, cl::desc("Print attribute dependencies"), cl::init(false))
static bool isAssumedReadOnlyOrReadNone(Attributor &A, const IRPosition &IRP, const AbstractAttribute &QueryingAA, bool RequireReadNone, bool &IsKnown)
static cl::opt< std::string > DepGraphDotFileNamePrefix("attributor-depgraph-dot-filename-prefix", cl::Hidden, cl::desc("The prefix used for the CallGraph dot file names."))
static cl::opt< bool > AnnotateDeclarationCallSites("attributor-annotate-decl-cs", cl::Hidden, cl::desc("Annotate call sites of function declarations."), cl::init(false))
static cl::opt< unsigned > SetFixpointIterations("attributor-max-iterations", cl::Hidden, cl::desc("Maximal number of fixpoint iterations."), cl::init(32))
static cl::list< std::string > FunctionSeedAllowList("attributor-function-seed-allow-list", cl::Hidden, cl::desc("Comma separated list of function names that are " "allowed to be seeded."), cl::CommaSeparated)
static cl::opt< bool > EnableCallSiteSpecific("attributor-enable-call-site-specific-deduction", cl::Hidden, cl::desc("Allow the Attributor to do call site specific analysis"), cl::init(false))
static cl::opt< bool > CloseWorldAssumption("attributor-assume-closed-world", cl::Hidden, cl::desc("Should a closed world be assumed, or not. Default if not set."))
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
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 provides an implementation of debug counters.
#define DEBUG_COUNTER(VARNAME, COUNTERNAME, DESC)
Contains a collection of routines for determining if a given instruction is guaranteed to execute if ...
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
uint64_t IntrinsicInst * II
static constexpr StringLiteral Filename
FunctionAnalysisManager FAM
This file defines the PointerIntPair class.
static StringRef getName(Value *V)
Remove Loads Into Fake Uses
This file defines the SmallPtrSet class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
#define DEBUG_WITH_TYPE(TYPE,...)
DEBUG_WITH_TYPE macro - This macro should be used by passes to emit debug information.
void print(OutputBuffer &OB) const
static const fltSemantics & IEEEsingle()
Class for arbitrary precision integers.
CallBase * getInstruction() const
Return the underlying instruction.
bool isCallbackCall() const
Return true if this ACS represents a callback call.
const Use & getCalleeUseForCallback() const
Return the use of the callee value in the underlying instruction.
static LLVM_ABI void getCallbackUses(const CallBase &CB, SmallVectorImpl< const Use * > &CallbackUses)
Add operand uses of CB that represent callback uses into CallbackUses.
bool isCallee(Value::const_user_iterator UI) const
Return true if UI is the use that defines the callee of this ACS.
Value * getCallArgOperand(Argument &Arg) const
Return the operand of the underlying instruction associated with Arg.
int getCallArgOperandNo(Argument &Arg) const
Return the operand index of the underlying instruction associated with Arg.
unsigned getNumArgOperands() const
Return the number of parameters of the callee.
Function * getCalledFunction() const
Return the function being called if this is a direct call, otherwise return null (if it's an indirect...
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.
const Function * getParent() const
unsigned getArgNo() const
Return the index of this formal argument in its containing function.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
bool empty() const
empty - Check if the array is empty.
This class stores enough information to efficiently remove some attributes from an existing AttrBuild...
This class holds the attributes for a particular argument, parameter, function, or return value.
LLVM_ABI MemoryEffects getMemoryEffects() const
LLVM_ABI bool hasAttribute(Attribute::AttrKind Kind) const
Return true if the attribute exists in this set.
LLVM_ABI Attribute getAttribute(Attribute::AttrKind Kind) const
Return the attribute object.
Functions, function parameters, and return types can have attributes to indicate how they should be t...
LLVM_ABI bool isStringAttribute() const
Return true if the attribute is a string (target-dependent) attribute.
LLVM_ABI bool isEnumAttribute() const
Return true if the attribute is an Attribute::AttrKind type.
LLVM_ABI bool isIntAttribute() const
Return true if the attribute is an integer attribute.
LLVM_ABI uint64_t getValueAsInt() const
Return the attribute's value as an integer.
LLVM_ABI bool isConstantRangeAttribute() const
Return true if the attribute is a ConstantRange attribute.
LLVM_ABI StringRef getKindAsString() const
Return the attribute's kind as a string.
static LLVM_ABI Attribute get(LLVMContext &Context, AttrKind Kind, uint64_t Val=0)
Return a uniquified Attribute object.
LLVM_ABI Attribute::AttrKind getKindAsEnum() const
Return the attribute's kind as an enum (Attribute::AttrKind).
LLVM_ABI MemoryEffects getMemoryEffects() const
Returns memory effects.
LLVM_ABI StringRef getValueAsString() const
Return the attribute's value as a string.
AttrKind
This enumeration lists the attributes that can be associated with parameters, function results,...
@ None
No attributes have been set.
LLVM Basic Block Representation.
const Function * getParent() const
Return the enclosing method, or null if none.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
const Instruction & front() const
LLVM_ABI const BasicBlock * getUniquePredecessor() const
Return the predecessor of this block if it has a unique predecessor block.
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...
void setCallingConv(CallingConv::ID CC)
void addFnAttr(Attribute::AttrKind Kind)
Adds the attribute to the function.
LLVM_ABI void getOperandBundlesAsDefs(SmallVectorImpl< OperandBundleDef > &Defs) const
Return the list of operand bundles attached to this instruction as a vector of OperandBundleDefs.
CallingConv::ID getCallingConv() const
LLVM_ABI bool isMustTailCall() const
Tests if this call site must be tail call optimized.
Value * getCalledOperand() const
void setAttributes(AttributeList A)
Set the attributes for this call.
unsigned arg_size() const
AttributeList getAttributes() const
Return the attributes for this call.
LLVM_ABI Function * getCaller()
Helper to get the caller (the parent function).
Wrapper to unify "old style" CallGraph and "new style" LazyCallGraph.
LLVM_ABI void replaceFunctionWith(Function &OldFn, Function &NewFn)
Replace OldFn in the call graph (and SCC) with NewFn.
LLVM_ABI void reanalyzeFunction(Function &Fn)
After an CGSCC pass changes a function in ways that affect the call graph, this method can be called ...
void initialize(LazyCallGraph &LCG, LazyCallGraph::SCC &SCC, CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR)
Initializers for usage outside of a CGSCC pass, inside a CGSCC pass in the old and new pass manager (...
This class represents a function call, abstracting a target machine's calling convention.
static CallInst * Create(FunctionType *Ty, Value *F, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
void setTailCall(bool IsTc=true)
A constant value that is initialized with an expression using other constant values.
static LLVM_ABI Constant * getPointerCast(Constant *C, Type *Ty)
Create a BitCast, AddrSpaceCast, or a PtrToInt cast constant expression.
static LLVM_ABI Constant * getTrunc(Constant *C, Type *Ty, bool OnlyIfReduced=false)
LLVM_ABI void print(raw_ostream &OS) const
Print out the bounds to a stream.
This is an important base class in LLVM.
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
A parsed version of the target data layout string in and methods for querying it.
static bool shouldExecute(CounterInfo &Counter)
ValueT lookup(const_arg_type_t< KeyT > Val) const
lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...
Implements a dense probed hash-table based set.
Analysis pass which computes a DominatorTree.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
A proxy from a FunctionAnalysisManager to an SCC.
Class to represent function types.
static LLVM_ABI FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
void setSubprogram(DISubprogram *SP)
Set the attached subprogram.
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
void splice(Function::iterator ToIt, Function *FromF)
Transfer all blocks from FromF to this function at ToIt.
const BasicBlock & getEntryBlock() const
FunctionType * getFunctionType() const
Returns the FunctionType for me.
iterator_range< arg_iterator > args()
DISubprogram * getSubprogram() const
Get the attached subprogram.
MemoryEffects getMemoryEffects() const
bool hasParamAttribute(unsigned ArgNo, Attribute::AttrKind Kind) const
check if an attributes is in the list of attributes.
AttributeList getAttributes() const
Return the attribute list for this Function.
void setAttributes(AttributeList Attrs)
Set the attribute list for this Function.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Type * getReturnType() const
Returns the type of the ret val.
void setMemoryEffects(MemoryEffects ME)
Argument * getArg(unsigned i) const
bool isVarArg() const
isVarArg - Return true if this function takes a variable number of arguments.
void copyAttributesFrom(const Function *Src)
copyAttributesFrom - copy all additional attributes (those not needed to create a Function) from the ...
bool hasMetadata() const
Return true if this GlobalObject has any metadata attached to it.
LLVM_ABI void addMetadata(unsigned KindID, MDNode &MD)
Add a metadata attachment.
LLVM_ABI bool isDeclaration() const
Return true if the primary definition of this global value is outside of the current translation unit...
LinkageTypes getLinkage() const
bool hasLocalLinkage() const
void setLinkage(LinkageTypes LT)
unsigned getAddressSpace() const
Module * getParent()
Get the module that this global value is contained inside of...
void setDSOLocal(bool Local)
PointerType * getType() const
Global values are always pointers.
@ DefaultVisibility
The GV is visible.
void setVisibility(VisibilityTypes V)
static bool isInterposableLinkage(LinkageTypes Linkage)
Whether the definition of this global may be replaced by something non-equivalent at link time.
@ PrivateLinkage
Like Internal, but omit from symbol table.
@ InternalLinkage
Rename collisions when linking (static functions).
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
LLVM_ABI const Function * getFunction() const
Return the function this instruction belongs to.
LLVM_ABI void copyMetadata(const Instruction &SrcInst, ArrayRef< unsigned > WL=ArrayRef< unsigned >())
Copy metadata from SrcInst to this instruction.
static InvokeInst * Create(FunctionType *Ty, Value *Func, BasicBlock *IfNormal, BasicBlock *IfException, ArrayRef< Value * > Args, const Twine &NameStr, InsertPosition InsertBefore=nullptr)
This is an important class for using LLVM in a threaded context.
A node in the call graph.
An SCC of the call graph.
A lazily constructed view of the call graph of a module.
An instruction for reading from memory.
This is the common base class for memset/memcpy/memmove.
This class wraps the llvm.memcpy/memmove intrinsics.
static MemoryEffectsBase argMemOnly(ModRefInfo MR=ModRefInfo::ModRef)
bool doesAccessArgPointees() const
Whether this function may access argument memory.
static LLVM_ABI MemoryLocation getForSource(const MemTransferInst *MTI)
Return a location representing the source of a memory transfer.
static LLVM_ABI MemoryLocation getForDest(const MemIntrinsic *MI)
Return a location representing the destination of a memory set or transfer.
static LLVM_ABI std::optional< MemoryLocation > getOrNone(const Instruction *Inst)
A Module instance is used to store all the information related to an LLVM module.
const FunctionListType & getFunctionList() const
Get the Module's list of functions (constant).
PointerIntPair - This class implements a pair of a pointer and small integer.
void * getOpaqueValue() const
PointerTy getPointer() const
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
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.
static ReturnInst * Create(LLVMContext &C, Value *retVal=nullptr, InsertPosition InsertBefore=nullptr)
A vector that has set insertion semantics.
ArrayRef< value_type > getArrayRef() const
bool remove(const value_type &X)
Remove an item from the set vector.
size_type size() const
Determine the number of elements in the SetVector.
void insert_range(Range &&R)
size_type count(const_arg_type key) const
Count the number of elements of a given key in the SetVector.
typename vector_type::const_iterator iterator
void clear()
Completely clear the SetVector.
iterator begin()
Get an iterator to the beginning of the SetVector.
bool insert(const value_type &X)
Insert a new element into the SetVector.
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
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.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void reserve(size_type N)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
StringRef - Represent a constant reference to a string, i.e.
A visitor class for IR positions.
LLVM_ABI SubsumingPositionIterator(const IRPosition &IRP)
Provides information about what library functions are available for the current target.
The TimeTraceScope is a helper class to call the begin and end functions of the time trace profiler.
Triple - Helper class for working with autoconf configuration names.
The instances of the Type class are immutable: once they are created, they are never changed.
bool isPointerTy() const
True if this is an instance of PointerType.
bool isVoidTy() const
Return true if this is 'void'.
static LLVM_ABI UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
A Use represents the edge between a Value definition and its users.
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
LLVMContext & getContext() const
All values hold a context through their type.
LLVM_ABI const Value * stripPointerCasts() const
Strip off pointer casts, all-zero GEPs and address space casts.
iterator_range< use_iterator > uses()
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
LLVM_ABI void takeName(Value *V)
Transfer the name from V to this value.
An efficient, type-erasing, non-owning reference to a callable.
const ParentTy * getParent() const
self_iterator getIterator()
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
iterator insert(iterator where, pointer New)
A raw_ostream that writes to a file descriptor.
This class implements an extremely fast bulk output stream that can only output to a stream.
A raw_ostream that writes to an std::string.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Abstract Attribute helper functions.
LLVM_ABI bool isAssumedReadNone(Attributor &A, const IRPosition &IRP, const AbstractAttribute &QueryingAA, bool &IsKnown)
Return true if IRP is readnone.
LLVM_ABI bool isAssumedReadOnly(Attributor &A, const IRPosition &IRP, const AbstractAttribute &QueryingAA, bool &IsKnown)
Return true if IRP is readonly.
LLVM_ABI std::optional< Value * > combineOptionalValuesInAAValueLatice(const std::optional< Value * > &A, const std::optional< Value * > &B, Type *Ty)
Return the combination of A and B such that the result is a possible value of both.
LLVM_ABI bool isValidAtPosition(const ValueAndContext &VAC, InformationCache &InfoCache)
Return true if the value of VAC is a valid at the position of VAC, that is a constant,...
LLVM_ABI bool isAssumedThreadLocalObject(Attributor &A, Value &Obj, const AbstractAttribute &QueryingAA)
Return true if Obj is assumed to be a thread local object.
LLVM_ABI bool isGPUConstantAddressSpace(const Module &M, unsigned AS)
Check if the given address space AS corresponds to a GPU constant address space for the target triple...
LLVM_ABI bool isGPUGenericAddressSpace(const Module &M, unsigned AS)
Check if the given address space AS corresponds to a GPU generic address space for the target triple ...
LLVM_ABI bool isDynamicallyUnique(Attributor &A, const AbstractAttribute &QueryingAA, const Value &V, bool ForAnalysisOnly=true)
Return true if V is dynamically unique, that is, there are no two "instances" of V at runtime with di...
LLVM_ABI bool getPotentialCopiesOfStoredValue(Attributor &A, StoreInst &SI, SmallSetVector< Value *, 4 > &PotentialCopies, const AbstractAttribute &QueryingAA, bool &UsedAssumedInformation, bool OnlyExact=false)
Collect all potential values of the one stored by SI into PotentialCopies.
LLVM_ABI bool isGPUSharedAddressSpace(const Module &M, unsigned AS)
Check if the given address space AS corresponds to a GPU shared address space for the target triple i...
LLVM_ABI bool isGPULocalAddressSpace(const Module &M, unsigned AS)
Check if the given address space AS corresponds to a GPU local/private address space for the target t...
LLVM_ABI bool isPotentiallyAffectedByBarrier(Attributor &A, const Instruction &I, const AbstractAttribute &QueryingAA)
Return true if I is potentially affected by a barrier.
SmallPtrSet< Instruction *, 4 > InstExclusionSetTy
LLVM_ABI bool isGPU(const Module &M)
Return true iff M target a GPU (and we can use GPU AS reasoning).
LLVM_ABI Constant * getInitialValueForObj(Attributor &A, const AbstractAttribute &QueryingAA, Value &Obj, Type &Ty, const TargetLibraryInfo *TLI, const DataLayout &DL, RangeTy *RangePtr=nullptr)
Return the initial value of Obj with type Ty if that is a constant.
ValueScope
Flags to distinguish intra-procedural queries from potentially inter-procedural queries.
LLVM_ABI bool isValidInScope(const Value &V, const Function *Scope)
Return true if V is a valid value in Scope, that is a constant or an instruction/argument of Scope.
LLVM_ABI bool isGPUGlobalAddressSpace(const Module &M, unsigned AS)
Check if the given address space AS corresponds to a GPU global address space for the target triple i...
LLVM_ABI bool isPotentiallyReachable(Attributor &A, const Instruction &FromI, const Instruction &ToI, const AbstractAttribute &QueryingAA, const AA::InstExclusionSetTy *ExclusionSet=nullptr, std::function< bool(const Function &F)> GoBackwardsCB=nullptr)
Return true if ToI is potentially reachable from FromI without running into any instruction in Exclus...
LLVM_ABI bool isNoSyncInst(Attributor &A, const Instruction &I, const AbstractAttribute &QueryingAA)
Return true if I is a nosync instruction.
bool hasAssumedIRAttr(Attributor &A, const AbstractAttribute *QueryingAA, const IRPosition &IRP, DepClassTy DepClass, bool &IsKnown, bool IgnoreSubsumingPositions=false, const AAType **AAPtr=nullptr)
Helper to avoid creating an AA for IR Attributes that might already be set.
LLVM_ABI bool getPotentiallyLoadedValues(Attributor &A, LoadInst &LI, SmallSetVector< Value *, 4 > &PotentialValues, SmallSetVector< Instruction *, 4 > &PotentialValueOrigins, const AbstractAttribute &QueryingAA, bool &UsedAssumedInformation, bool OnlyExact=false)
Collect all potential values LI could read into PotentialValues.
LLVM_ABI Value * getWithType(Value &V, Type &Ty)
Try to convert V to type Ty without introducing new instructions.
constexpr char Attrs[]
Key for Kernel::Metadata::mAttrs.
@ C
The default llvm calling convention, compatible with C.
@ BasicBlock
Various leaf nodes.
initializer< Ty > init(const Ty &Val)
LocationClass< Ty > location(Ty &L)
DiagnosticInfoOptimizationBase::Argument NV
NodeAddr< UseNode * > Use
friend class Instruction
Iterator for Instructions in a `BasicBlock.
@ OF_TextWithCRLF
The file should be opened in text mode and use a carriage linefeed '\r '.
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
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 Constant * getInitialValueOfAllocation(const Value *V, const TargetLibraryInfo *TLI, Type *Ty)
If this is a call to an allocation function that initializes memory to a fixed value,...
Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST=nullptr, unsigned DynamicVGPRBlockSize=0)
LLVM_ABI bool RecursivelyDeleteTriviallyDeadInstructions(Value *V, const TargetLibraryInfo *TLI=nullptr, MemorySSAUpdater *MSSAU=nullptr, std::function< void(Value *)> AboutToDeleteCallback=std::function< void(Value *)>())
If the specified value is a trivially dead instruction, delete it.
LLVM_ABI unsigned MaxInitializationChainLength
The value passed to the line option that defines the maximal initialization chain length.
LLVM_ABI bool ConstantFoldTerminator(BasicBlock *BB, bool DeleteDeadConditions=false, const TargetLibraryInfo *TLI=nullptr, DomTreeUpdater *DTU=nullptr)
If a terminator instruction is predicated on a constant value, convert it into an unconditional branc...
APInt operator&(APInt a, const APInt &b)
LLVM_ABI void detachDeadBlocks(ArrayRef< BasicBlock * > BBs, SmallVectorImpl< DominatorTree::UpdateType > *Updates, bool KeepOneInputPHIs=false)
Replace contents of every block in BBs with single unreachable instruction.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
DenseMap< AssumeInst *, MinMax > Assume2KnowledgeMap
A mapping from intrinsics (=llvm.assume calls) to a value range (=knowledge) that is encoded in them.
LLVM_ABI bool verifyFunction(const Function &F, raw_ostream *OS=nullptr)
Check a function for errors, useful for use when debugging a pass.
LLVM_ABI CallInst * changeToCall(InvokeInst *II, DomTreeUpdater *DTU=nullptr)
This function converts the specified invoke into a normal call.
LLVM_ABI raw_fd_ostream & outs()
This returns a reference to a raw_fd_ostream for standard output.
auto dyn_cast_if_present(const Y &Val)
dyn_cast_if_present<X> - Functionally identical to dyn_cast, except that a null (or none in the case ...
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
InnerAnalysisManagerProxy< FunctionAnalysisManager, Module > FunctionAnalysisManagerModuleProxy
Provide the FunctionAnalysisManager to Module proxy.
LLVM_ABI bool isNoAliasCall(const Value *V)
Return true if this pointer is returned by a noalias function.
MemoryEffectsBase< IRMemLocation > MemoryEffects
Summary of how a function affects memory in the program.
raw_ostream & WriteGraph(raw_ostream &O, const GraphType &G, bool ShortNames=false, const Twine &Title="")
bool isa_and_nonnull(const Y &Val)
AnalysisManager< LazyCallGraph::SCC, LazyCallGraph & > CGSCCAnalysisManager
The CGSCC analysis manager.
LLVM_ABI InlineResult isInlineViable(Function &Callee)
Check if it is mechanically possible to inline the function Callee, based on the contents of the func...
auto dyn_cast_or_null(const Y &Val)
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI bool isInstructionTriviallyDead(Instruction *I, const TargetLibraryInfo *TLI=nullptr)
Return true if the result produced by the instruction is not used, and the instruction will return.
LLVM_ABI Constant * ConstantFoldLoadFromUniformValue(Constant *C, Type *Ty, const DataLayout &DL)
If C is a uniform value where all bits are the same (either all zero, all ones, all undef or all pois...
PotentialValuesState< std::pair< AA::ValueAndContext, AA::ValueScope > > PotentialLLVMValuesState
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
LLVM_ABI bool NullPointerIsDefined(const Function *F, unsigned AS=0)
Check whether null pointer dereferencing is considered undefined behavior for a given function or an ...
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI bool AreStatisticsEnabled()
Check if statistics are enabled.
LLVM_ABI Constant * ConstantFoldLoadFromConst(Constant *C, Type *Ty, const APInt &Offset, const DataLayout &DL)
Extract value of C at the given Offset reinterpreted as Ty.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
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...
@ Success
The lock was released successfully.
LLVM_ABI unsigned changeToUnreachable(Instruction *I, bool PreserveLCSSA=false, DomTreeUpdater *DTU=nullptr, MemorySSAUpdater *MSSAU=nullptr)
Insert an unreachable instruction before the specified instruction, making it and the rest of the cod...
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
@ Global
Append to llvm.global_dtors.
LLVM_ABI BasicBlock * SplitBlockPredecessors(BasicBlock *BB, ArrayRef< BasicBlock * > Preds, const char *Suffix, DominatorTree *DT, LoopInfo *LI=nullptr, MemorySSAUpdater *MSSAU=nullptr, bool PreserveLCSSA=false)
This method introduces at least one new basic block into the function and moves some of the predecess...
PotentialValuesState< APInt > PotentialConstantIntValuesState
bool operator&=(SparseBitVector< ElementSize > *LHS, const SparseBitVector< ElementSize > &RHS)
LLVM_ABI bool isPotentiallyReachable(const Instruction *From, const Instruction *To, const SmallPtrSetImpl< BasicBlock * > *ExclusionSet=nullptr, const DominatorTree *DT=nullptr, const LoopInfo *LI=nullptr, const CycleInfo *CI=nullptr)
Determine whether instruction 'To' is reachable from 'From', without passing through any blocks in Ex...
DWARFExpression::Operation Op
void ViewGraph(const GraphType &G, const Twine &Name, bool ShortNames=false, const Twine &Title="", GraphProgram::Name Program=GraphProgram::DOT)
ViewGraph - Emit a dot graph, run 'dot', run gv on the postscript file, then cleanup.
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
ArrayRef(const T &OneElt) -> ArrayRef< T >
ValueMap< const Value *, WeakTrackingVH > ValueToValueMapTy
LLVM_ABI void CloneFunctionInto(Function *NewFunc, const Function *OldFunc, ValueToValueMapTy &VMap, CloneFunctionChangeType Changes, SmallVectorImpl< ReturnInst * > &Returns, const char *NameSuffix="", ClonedCodeInfo *CodeInfo=nullptr, ValueMapTypeRemapper *TypeMapper=nullptr, ValueMaterializer *Materializer=nullptr)
Clone OldFunc into NewFunc, transforming the old arguments into references to VMap values.
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...
iterator_range< pointer_iterator< WrappedIteratorT > > make_pointer_range(RangeT &&Range)
LLVM_ABI bool isAllocationFn(const Value *V, const TargetLibraryInfo *TLI)
Tests if a value is a call or invoke to a library function that allocates or reallocates memory (eith...
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
LLVM_ABI void fillMapFromAssume(AssumeInst &Assume, RetainedKnowledgeMap &Result)
Insert into the map all the informations contained in the operand bundles of the llvm....
bool operator|=(SparseBitVector< ElementSize > &LHS, const SparseBitVector< ElementSize > *RHS)
LLVM_ABI Constant * ConstantFoldCastInstruction(unsigned opcode, Constant *V, Type *DestTy)
@ OPTIONAL
The target may be valid if the source is not.
@ NONE
Do not track a dependence between source and target.
@ REQUIRED
The target cannot be valid if the source is not.
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
APInt operator|(APInt a, const APInt &b)
BumpPtrAllocatorImpl<> BumpPtrAllocator
The standard BumpPtrAllocator which just uses the default template parameters.
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
static LLVM_ABI const char ID
Unique ID (due to the unique address)
DepSetTy Deps
Set of dependency graph nodes which should be updated if this one is updated.
PointerIntPair< AADepGraphNode *, 1 > DepTy
The data structure for the dependency graph.
LLVM_ABI void viewGraph()
AADepGraphNode SyntheticRoot
There is no root node for the dependency graph.
LLVM_ABI void print()
Print dependency graph.
LLVM_ABI void dumpGraph()
Dump graph to file.
AADepGraphNode * GetEntryNode()
An abstract interface to track if a value leaves it's defining function instance.
bool isAssumedUniqueForAnalysis() const
Return true if we assume that the underlying value is unique in its scope wrt.
An abstract Attribute for computing reachability between functions.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface to determine reachability of point A to B.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for liveness abstract attribute.
virtual bool isKnownDead() const =0
Returns true if the underlying value is known dead.
virtual bool isAssumedDead() const =0
The query functions are protected such that other attributes need to go through the Attributor interf...
virtual bool isRemovableStore() const
Return true if the underlying value is a store that is known to be removable.
static bool mayCatchAsynchronousExceptions(const Function &F)
Determine if F might catch asynchronous exceptions.
An abstract interface for memory access kind related attributes (readnone/readonly/writeonly).
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for all memory location attributes (readnone/argmemonly/inaccessiblememonly/ina...
static LLVM_ABI const char ID
Unique ID (due to the unique address)
static LLVM_ABI const char ID
Unique ID (due to the unique address)
static LLVM_ABI const char ID
Unique ID (due to the unique address)
static LLVM_ABI const char ID
Unique ID (due to the unique address)
static LLVM_ABI const char ID
Unique ID (due to the unique address)
static LLVM_ABI const char ID
Unique ID (due to the unique address)
static LLVM_ABI const char ID
Unique ID (due to the unique address)
static LLVM_ABI const char ID
Unique ID (due to the unique address)
static LLVM_ABI bool isNonRelaxedAtomic(const Instruction *I)
Helper function used to determine whether an instruction is non-relaxed atomic.
static LLVM_ABI bool isNoSyncIntrinsic(const Instruction *I)
Helper function specific for intrinsics which are potentially volatile.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
static LLVM_ABI const char ID
Unique ID (due to the unique address)
bool isWrittenValueUnknown() const
Return true if the value written cannot be determined at all.
std::optional< Value * > getContent() const
Return the written value which can be llvm::null if it is not yet determined.
bool isWriteOrAssumption() const
Return true if this is a write access.
bool isRead() const
Return true if this is a read access.
Value * getWrittenValue() const
Return the value writen, if any.
Instruction * getLocalInst() const
Return the instruction that causes the access with respect to the local scope of the associated attri...
Instruction * getRemoteInst() const
Return the actual instruction that causes the access.
bool isWrittenValueYetUndetermined() const
Return true if the value written is not known yet.
AccessKind getKind() const
Return the access kind.
An abstract interface for struct information.
static LLVM_ABI Value * getSingleValue(Attributor &A, const AbstractAttribute &AA, const IRPosition &IRP, SmallVectorImpl< AA::ValueAndContext > &Values)
Extract the single value in Values if any.
An abstract attribute for getting all assumption underlying objects.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
static LLVM_ABI const char ID
Unique ID (due to the unique address)
Helper to represent an access offset and size, with logic to deal with uncertainty and check for over...
bool offsetOrSizeAreUnknown() const
Return true if offset or size are unknown.
const Instruction * getCtxI() const
Base struct for all "concrete attribute" deductions.
ChangeStatus update(Attributor &A)
Hook for the Attributor to trigger an update of the internal state.
friend struct Attributor
}
virtual void printWithDeps(raw_ostream &OS) const
void print(raw_ostream &OS) const
Helper functions, for debug purposes only.
virtual StateType & getState()=0
Return the internal abstract state for inspection.
virtual const std::string getAsStr(Attributor *A) const =0
This function should return the "summarized" assumed state as string.
virtual ChangeStatus updateImpl(Attributor &A)=0
The actual update/transfer function which has to be implemented by the derived classes.
const IRPosition & getIRPosition() const
Return an IR position, see struct IRPosition.
An interface to query the internal state of an abstract attribute.
virtual ChangeStatus indicatePessimisticFixpoint()=0
Indicate that the abstract state should converge to the pessimistic state.
virtual bool isAtFixpoint() const =0
Return if this abstract state is fixed, thus does not need to be updated if information changes as it...
virtual bool isValidState() const =0
Return if this abstract state is in a valid state.
Wrapper for FunctionAnalysisManager.
LLVM_ABI PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG, CGSCCUpdateResult &UR)
void populateAll() const
Force populate the entire call graph.
Configuration for the Attributor.
std::optional< unsigned > MaxFixpointIterations
Maximum number of iterations to run until fixpoint.
LLVM_ABI PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG, CGSCCUpdateResult &UR)
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
Helper struct used in the communication between an abstract attribute (AA) that wants to change the s...
std::function< void( const ArgumentReplacementInfo &, Function &, Function::arg_iterator)> CalleeRepairCBTy
Callee repair callback type.
std::function< void(const ArgumentReplacementInfo &, AbstractCallSite, SmallVectorImpl< Value * > &)> ACSRepairCBTy
Abstract call site (ACS) repair callback type.
The fixpoint analysis framework that orchestrates the attribute deduction.
LLVM_ABI bool registerFunctionSignatureRewrite(Argument &Arg, ArrayRef< Type * > ReplacementTypes, ArgumentReplacementInfo::CalleeRepairCBTy &&CalleeRepairCB, ArgumentReplacementInfo::ACSRepairCBTy &&ACSRepairCB)
Register a rewrite for a function signature.
LLVM_ABI bool checkForAllCallees(function_ref< bool(ArrayRef< const Function * > Callees)> Pred, const AbstractAttribute &QueryingAA, const CallBase &CB)
Check Pred on all potential Callees of CB.
bool isModulePass() const
Return true if this is a module pass, false otherwise.
LLVM_ABI bool isValidFunctionSignatureRewrite(Argument &Arg, ArrayRef< Type * > ReplacementTypes)
Check if we can rewrite a function signature.
static LLVM_ABI bool isInternalizable(Function &F)
Returns true if the function F can be internalized.
LLVM_ABI ChangeStatus removeAttrs(const IRPosition &IRP, ArrayRef< Attribute::AttrKind > AttrKinds)
Remove all AttrKinds attached to IRP.
void emitRemark(Instruction *I, StringRef RemarkName, RemarkCallBack &&RemarkCB) const
Emit a remark generically.
bool isRunOn(Function &Fn) const
Return true if we derive attributes for Fn.
LLVM_ABI bool isAssumedDead(const AbstractAttribute &AA, const AAIsDead *LivenessAA, bool &UsedAssumedInformation, bool CheckBBLivenessOnly=false, DepClassTy DepClass=DepClassTy::OPTIONAL)
Return true if AA (or its context instruction) is assumed dead.
LLVM_ABI bool checkForAllInstructions(function_ref< bool(Instruction &)> Pred, const Function *Fn, const AbstractAttribute *QueryingAA, ArrayRef< unsigned > Opcodes, bool &UsedAssumedInformation, bool CheckBBLivenessOnly=false, bool CheckPotentiallyDead=false)
Check Pred on all instructions in Fn with an opcode present in Opcodes.
LLVM_ABI void recordDependence(const AbstractAttribute &FromAA, const AbstractAttribute &ToAA, DepClassTy DepClass)
Explicitly record a dependence from FromAA to ToAA, that is if FromAA changes ToAA should be updated ...
static LLVM_ABI void createShallowWrapper(Function &F)
Create a shallow wrapper for F such that F has internal linkage afterwards.
const AAType * getAAFor(const AbstractAttribute &QueryingAA, const IRPosition &IRP, DepClassTy DepClass)
Lookup an abstract attribute of type AAType at position IRP.
std::optional< Value * > getAssumedSimplified(const IRPosition &IRP, const AbstractAttribute &AA, bool &UsedAssumedInformation, AA::ValueScope S)
If V is assumed simplified, return it, if it is unclear yet, return std::nullopt, otherwise return nu...
static LLVM_ABI Function * internalizeFunction(Function &F, bool Force=false)
Make another copy of the function F such that the copied version has internal linkage afterwards and ...
bool isFunctionIPOAmendable(const Function &F)
Determine whether the function F is IPO amendable.
const AAType * getOrCreateAAFor(IRPosition IRP, const AbstractAttribute *QueryingAA, DepClassTy DepClass, bool ForceUpdate=false, bool UpdateAfterInit=true)
The version of getAAFor that allows to omit a querying abstract attribute.
LLVM_ABI bool checkForAllReadWriteInstructions(function_ref< bool(Instruction &)> Pred, AbstractAttribute &QueryingAA, bool &UsedAssumedInformation)
Check Pred on all Read/Write instructions.
LLVM_ABI bool checkForAllReturnedValues(function_ref< bool(Value &)> Pred, const AbstractAttribute &QueryingAA, AA::ValueScope S=AA::ValueScope::Intraprocedural, bool RecurseForSelectAndPHI=true)
Check Pred on all values potentially returned by the function associated with QueryingAA.
LLVM_ABI bool isClosedWorldModule() const
Return true if the module contains the whole world, thus, no outside functions exist.
LLVM_ABI std::optional< Constant * > getAssumedConstant(const IRPosition &IRP, const AbstractAttribute &AA, bool &UsedAssumedInformation)
If IRP is assumed to be a constant, return it, if it is unclear yet, return std::nullopt,...
LLVM_ABI Attributor(SetVector< Function * > &Functions, InformationCache &InfoCache, AttributorConfig Configuration)
Constructor.
LLVM_ABI void getAttrs(const IRPosition &IRP, ArrayRef< Attribute::AttrKind > AKs, SmallVectorImpl< Attribute > &Attrs, bool IgnoreSubsumingPositions=false)
Return the attributes of any kind in AKs existing in the IR at a position that will affect this one.
InformationCache & getInfoCache()
Return the internal information cache.
LLVM_ABI std::optional< Value * > translateArgumentToCallSiteContent(std::optional< Value * > V, CallBase &CB, const AbstractAttribute &AA, bool &UsedAssumedInformation)
Translate V from the callee context into the call site context.
LLVM_ABI bool checkForAllUses(function_ref< bool(const Use &, bool &)> Pred, const AbstractAttribute &QueryingAA, const Value &V, bool CheckBBLivenessOnly=false, DepClassTy LivenessDepClass=DepClassTy::OPTIONAL, bool IgnoreDroppableUses=true, function_ref< bool(const Use &OldU, const Use &NewU)> EquivalentUseCB=nullptr)
Check Pred on all (transitive) uses of V.
LLVM_ABI ChangeStatus manifestAttrs(const IRPosition &IRP, ArrayRef< Attribute > DeducedAttrs, bool ForceReplace=false)
Attach DeducedAttrs to IRP, if ForceReplace is set we do this even if the same attribute kind was alr...
LLVM_ABI bool hasAttr(const IRPosition &IRP, ArrayRef< Attribute::AttrKind > AKs, bool IgnoreSubsumingPositions=false, Attribute::AttrKind ImpliedAttributeKind=Attribute::None)
Return true if any kind in AKs existing in the IR at a position that will affect this one.
LLVM_ABI void registerForUpdate(AbstractAttribute &AA)
Allows a query AA to request an update if a new query was received.
std::function< bool(Attributor &, const AbstractAttribute *)> VirtualUseCallbackTy
LLVM_ABI void identifyDefaultAbstractAttributes(Function &F)
Determine opportunities to derive 'default' attributes in F and create abstract attribute objects for...
LLVM_ABI bool getAssumedSimplifiedValues(const IRPosition &IRP, const AbstractAttribute *AA, SmallVectorImpl< AA::ValueAndContext > &Values, AA::ValueScope S, bool &UsedAssumedInformation, bool RecurseForSelectAndPHI=true)
Try to simplify IRP and in the scope S.
BumpPtrAllocator & Allocator
The allocator used to allocate memory, e.g. for AbstractAttributes.
LLVM_ABI ChangeStatus run()
Run the analyses until a fixpoint is reached or enforced (timeout).
static LLVM_ABI bool internalizeFunctions(SmallPtrSetImpl< Function * > &FnSet, DenseMap< Function *, Function * > &FnMap)
Make copies of each function in the set FnSet such that the copied version has internal linkage after...
LLVM_ABI bool checkForAllCallSites(function_ref< bool(AbstractCallSite)> Pred, const AbstractAttribute &QueryingAA, bool RequireAllCallSites, bool &UsedAssumedInformation)
Check Pred on all function call sites.
LLVM_ABI bool getAttrsFromAssumes(const IRPosition &IRP, Attribute::AttrKind AK, SmallVectorImpl< Attribute > &Attrs)
Return the attributes of kind AK existing in the IR as operand bundles of an llvm....
bool isKnown(base_t BitsEncoding=BestState) const
Return true if the bits set in BitsEncoding are "known bits".
Support structure for SCC passes to communicate updates the call graph back to the CGSCC pass manager...
static std::string getNodeLabel(const AADepGraphNode *Node, const AADepGraph *DG)
DOTGraphTraits(bool isSimple=false)
DefaultDOTGraphTraits(bool simple=false)
Represent subnormal handling kind for floating point instruction inputs and outputs.
@ Dynamic
Denormals have unknown treatment.
An information struct used to provide DenseMap with the various necessary components for a given valu...
static NodeRef DepGetVal(const DepTy &DT)
PointerIntPair< AADepGraphNode *, 1 > DepTy
static ChildIteratorType child_end(NodeRef N)
static NodeRef getEntryNode(AADepGraphNode *DGN)
mapped_iterator< AADepGraphNode::DepSetTy::iterator, decltype(&DepGetVal)> ChildIteratorType
PointerIntPair< AADepGraphNode *, 1 > EdgeRef
static ChildIteratorType child_begin(NodeRef N)
AADepGraphNode::DepSetTy::iterator ChildEdgeIteratorType
static NodeRef getEntryNode(AADepGraph *DG)
mapped_iterator< AADepGraphNode::DepSetTy::iterator, decltype(&DepGetVal)> nodes_iterator
static nodes_iterator nodes_begin(AADepGraph *DG)
static nodes_iterator nodes_end(AADepGraph *DG)
typename AADepGraph *::UnknownGraphTypeError NodeRef
Helper to describe and deal with positions in the LLVM-IR.
Function * getAssociatedFunction() const
Return the associated function, if any.
void setAttrList(const AttributeList &AttrList) const
Update the attributes associated with this function or call site scope.
unsigned getAttrIdx() const
Return the index in the attribute list for this position.
bool hasCallBaseContext() const
Check if the position has any call base context.
static const IRPosition callsite_returned(const CallBase &CB)
Create a position describing the returned value of CB.
static const IRPosition returned(const Function &F, const CallBaseContext *CBContext=nullptr)
Create a position describing the returned value of F.
LLVM_ABI Argument * getAssociatedArgument() const
Return the associated argument, if any.
static const IRPosition value(const Value &V, const CallBaseContext *CBContext=nullptr)
Create a position describing the value of V.
AttributeList getAttrList() const
Return the attributes associated with this function or call site scope.
static const IRPosition inst(const Instruction &I, const CallBaseContext *CBContext=nullptr)
Create a position describing the instruction I.
static const IRPosition callsite_argument(const CallBase &CB, unsigned ArgNo)
Create a position describing the argument of CB at position ArgNo.
static LLVM_ABI const IRPosition TombstoneKey
Kind
The positions we distinguish in the IR.
@ IRP_ARGUMENT
An attribute for a function argument.
@ IRP_RETURNED
An attribute for the function return value.
@ IRP_CALL_SITE
An attribute for a call site (function scope).
@ IRP_CALL_SITE_RETURNED
An attribute for a call site return value.
@ IRP_FUNCTION
An attribute for a function (scope).
@ IRP_FLOAT
A position that is not associated with a spot suitable for attributes.
@ IRP_CALL_SITE_ARGUMENT
An attribute for a call site argument.
@ IRP_INVALID
An invalid position.
Instruction * getCtxI() const
Return the context instruction, if any.
static const IRPosition argument(const Argument &Arg, const CallBaseContext *CBContext=nullptr)
Create a position describing the argument Arg.
static LLVM_ABI const IRPosition EmptyKey
Special DenseMap key values.
static const IRPosition function(const Function &F, const CallBaseContext *CBContext=nullptr)
Create a position describing the function scope of F.
const CallBaseContext * getCallBaseContext() const
Get the call base context from the position.
Value & getAssociatedValue() const
Return the value this abstract attribute is associated with.
Value & getAnchorValue() const
Return the value this abstract attribute is anchored with.
Value * getAttrListAnchor() const
Return the value attributes are attached to.
int getCallSiteArgNo() const
Return the call site argument number of the associated value if it is an argument or call site argume...
Kind getPositionKind() const
Return the associated position kind.
static const IRPosition callsite_function(const CallBase &CB)
Create a position describing the function scope of CB.
Function * getAnchorScope() const
Return the Function surrounding the anchor value.
State for an integer range.
ConstantRange getKnown() const
Return the known state encoding.
ConstantRange getAssumed() const
Return the assumed state encoding.
uint32_t getBitWidth() const
Return associated values' bit width.
A "must be executed context" for a given program point PP is the set of instructions,...
iterator & end()
Return an universal end iterator.
bool findInContextOf(const Instruction *I, const Instruction *PP)
Helper to look for I in the context of PP.
iterator & begin(const Instruction *PP)
Return an iterator to explore the context around PP.
bool undefIsContained() const
Returns whether this state contains an undef value or not.
bool isValidState() const override
See AbstractState::isValidState(...)
const SetTy & getAssumedSet() const
Return this set.