54#include "llvm/IR/IntrinsicsAMDGPU.h"
55#include "llvm/IR/IntrinsicsNVPTX.h"
82#define DEBUG_TYPE "attributor"
86 cl::desc(
"Manifest Attributor internal string attributes."),
99 cl::desc(
"Maximum number of potential values to be "
100 "tracked for each position."),
105 "attributor-max-potential-values-iterations",
cl::Hidden,
107 "Maximum number of iterations we keep dismantling potential values."),
110STATISTIC(NumAAs,
"Number of abstract attributes created");
111STATISTIC(NumIndirectCallsPromoted,
"Number of indirect calls promoted");
126#define BUILD_STAT_MSG_IR_ATTR(TYPE, NAME) \
127 ("Number of " #TYPE " marked '" #NAME "'")
128#define BUILD_STAT_NAME(NAME, TYPE) NumIR##TYPE##_##NAME
129#define STATS_DECL_(NAME, MSG) STATISTIC(NAME, MSG);
130#define STATS_DECL(NAME, TYPE, MSG) \
131 STATS_DECL_(BUILD_STAT_NAME(NAME, TYPE), MSG);
132#define STATS_TRACK(NAME, TYPE) ++(BUILD_STAT_NAME(NAME, TYPE));
133#define STATS_DECLTRACK(NAME, TYPE, MSG) \
134 {STATS_DECL(NAME, TYPE, MSG) STATS_TRACK(NAME, TYPE)}
135#define STATS_DECLTRACK_ARG_ATTR(NAME) \
136 STATS_DECLTRACK(NAME, Arguments, BUILD_STAT_MSG_IR_ATTR(arguments, NAME))
137#define STATS_DECLTRACK_CSARG_ATTR(NAME) \
138 STATS_DECLTRACK(NAME, CSArguments, \
139 BUILD_STAT_MSG_IR_ATTR(call site arguments, NAME))
140#define STATS_DECLTRACK_FN_ATTR(NAME) \
141 STATS_DECLTRACK(NAME, Function, BUILD_STAT_MSG_IR_ATTR(functions, NAME))
142#define STATS_DECLTRACK_CS_ATTR(NAME) \
143 STATS_DECLTRACK(NAME, CS, BUILD_STAT_MSG_IR_ATTR(call site, NAME))
144#define STATS_DECLTRACK_FNRET_ATTR(NAME) \
145 STATS_DECLTRACK(NAME, FunctionReturn, \
146 BUILD_STAT_MSG_IR_ATTR(function returns, NAME))
147#define STATS_DECLTRACK_CSRET_ATTR(NAME) \
148 STATS_DECLTRACK(NAME, CSReturn, \
149 BUILD_STAT_MSG_IR_ATTR(call site returns, NAME))
150#define STATS_DECLTRACK_FLOATING_ATTR(NAME) \
151 STATS_DECLTRACK(NAME, Floating, \
152 ("Number of floating values known to be '" #NAME "'"))
157#define PIPE_OPERATOR(CLASS) \
158 raw_ostream &operator<<(raw_ostream &OS, const CLASS &AA) { \
159 return OS << static_cast<const AbstractAttribute &>(AA); \
216 bool HeaderOnly,
Cycle **CPtr =
nullptr) {
219 auto *BB =
I->getParent();
225 return !HeaderOnly || BB ==
C->getHeader();
236 if (
DL.getTypeSizeInBits(Ty) !=
DL.getTypeAllocSizeInBits(Ty))
261 StartPos +=
DL.getTypeAllocSizeInBits(ElTy);
271 bool AllowVolatile) {
272 if (!AllowVolatile &&
I->isVolatile())
276 return LI->getPointerOperand();
280 return SI->getPointerOperand();
284 return CXI->getPointerOperand();
288 return RMWI->getPointerOperand();
310 bool GetMinOffset,
bool AllowNonInbounds,
311 bool UseAssumed =
false) {
313 auto AttributorAnalysis = [&](
Value &V,
APInt &ROffset) ->
bool {
320 if (!ValueConstantRangeAA)
324 if (
Range.isFullSet())
330 ROffset =
Range.getSignedMin();
332 ROffset =
Range.getSignedMax();
343 const Value *Ptr, int64_t &BytesOffset,
348 true, AllowNonInbounds);
356template <
typename AAType,
typename StateType =
typename AAType::StateType,
358 bool RecurseForSelectAndPHI =
true>
360 Attributor &
A,
const AAType &QueryingAA, StateType &S,
362 LLVM_DEBUG(
dbgs() <<
"[Attributor] Clamp return value states for "
363 << QueryingAA <<
" into " << S <<
"\n");
365 assert((QueryingAA.getIRPosition().getPositionKind() ==
367 QueryingAA.getIRPosition().getPositionKind() ==
369 "Can only clamp returned value states for a function returned or call "
370 "site returned position!");
374 std::optional<StateType>
T;
377 auto CheckReturnValue = [&](
Value &RV) ->
bool {
391 <<
" AA: " <<
AA->getAsStr(&
A) <<
" @ " << RVPos <<
"\n");
392 const StateType &AAS =
AA->getState();
394 T = StateType::getBestState(AAS);
396 LLVM_DEBUG(
dbgs() <<
"[Attributor] AA State: " << AAS <<
" RV State: " <<
T
398 return T->isValidState();
401 if (!
A.checkForAllReturnedValues(CheckReturnValue, QueryingAA,
403 RecurseForSelectAndPHI))
404 S.indicatePessimisticFixpoint();
411template <
typename AAType,
typename BaseType,
412 typename StateType =
typename BaseType::StateType,
413 bool PropagateCallBaseContext =
false,
415 bool RecurseForSelectAndPHI =
true>
416struct AAReturnedFromReturnedValues :
public BaseType {
417 AAReturnedFromReturnedValues(
const IRPosition &IRP, Attributor &
A)
422 StateType S(StateType::getBestState(this->getState()));
424 RecurseForSelectAndPHI>(
426 PropagateCallBaseContext ? this->getCallBaseContext() : nullptr);
435template <
typename AAType,
typename StateType =
typename AAType::StateType,
437static void clampCallSiteArgumentStates(
Attributor &
A,
const AAType &QueryingAA,
439 LLVM_DEBUG(
dbgs() <<
"[Attributor] Clamp call site argument states for "
440 << QueryingAA <<
" into " << S <<
"\n");
442 assert(QueryingAA.getIRPosition().getPositionKind() ==
444 "Can only clamp call site argument states for an argument position!");
448 std::optional<StateType>
T;
451 unsigned ArgNo = QueryingAA.getIRPosition().getCallSiteArgNo();
471 LLVM_DEBUG(
dbgs() <<
"[Attributor] ACS: " << *ACS.getInstruction()
472 <<
" AA: " <<
AA->getAsStr(&
A) <<
" @" << ACSArgPos
474 const StateType &AAS =
AA->getState();
476 T = StateType::getBestState(AAS);
478 LLVM_DEBUG(
dbgs() <<
"[Attributor] AA State: " << AAS <<
" CSA State: " <<
T
480 return T->isValidState();
483 bool UsedAssumedInformation =
false;
484 if (!
A.checkForAllCallSites(CallSiteCheck, QueryingAA,
true,
485 UsedAssumedInformation))
486 S.indicatePessimisticFixpoint();
493template <
typename AAType,
typename BaseType,
494 typename StateType =
typename AAType::StateType,
496bool getArgumentStateFromCallBaseContext(
Attributor &
A,
500 "Expected an 'argument' position !");
506 assert(ArgNo >= 0 &&
"Invalid Arg No!");
520 const StateType &CBArgumentState =
521 static_cast<const StateType &
>(
AA->getState());
523 LLVM_DEBUG(
dbgs() <<
"[Attributor] Briding Call site context to argument"
524 <<
"Position:" << Pos <<
"CB Arg state:" << CBArgumentState
528 State ^= CBArgumentState;
533template <
typename AAType,
typename BaseType,
534 typename StateType =
typename AAType::StateType,
535 bool BridgeCallBaseContext =
false,
537struct AAArgumentFromCallSiteArguments :
public BaseType {
538 AAArgumentFromCallSiteArguments(
const IRPosition &IRP, Attributor &
A)
543 StateType S = StateType::getBestState(this->getState());
545 if (BridgeCallBaseContext) {
547 getArgumentStateFromCallBaseContext<AAType,
BaseType, StateType,
549 A, *
this, this->getIRPosition(), S);
553 clampCallSiteArgumentStates<AAType, StateType, IRAttributeKind>(
A, *
this,
563template <
typename AAType,
typename BaseType,
564 typename StateType =
typename BaseType::StateType,
565 bool IntroduceCallBaseContext =
false,
567struct AACalleeToCallSite :
public BaseType {
568 AACalleeToCallSite(
const IRPosition &IRP, Attributor &
A) :
BaseType(IRP,
A) {}
572 auto IRPKind = this->getIRPosition().getPositionKind();
575 "Can only wrap function returned positions for call site "
576 "returned positions!");
577 auto &S = this->getState();
580 if (IntroduceCallBaseContext)
581 LLVM_DEBUG(
dbgs() <<
"[Attributor] Introducing call base context:" << CB
586 for (
const Function *Callee : Callees) {
590 IntroduceCallBaseContext ? &CB :
nullptr)
592 *
Callee, IntroduceCallBaseContext ? &CB : nullptr);
594 if (Attribute::isEnumAttrKind(IRAttributeKind)) {
597 A,
this, FnPos, DepClassTy::REQUIRED, IsKnown))
603 A.getAAFor<AAType>(*
this, FnPos, DepClassTy::REQUIRED);
607 if (S.isAtFixpoint())
608 return S.isValidState();
612 if (!
A.checkForAllCallees(CalleePred, *
this, CB))
613 return S.indicatePessimisticFixpoint();
619template <
class AAType,
typename StateType =
typename AAType::StateType>
625 auto EIt = Explorer.
begin(CtxI), EEnd = Explorer.
end(CtxI);
626 for (
unsigned u = 0;
u <
Uses.size(); ++
u) {
630 if (Found &&
AA.followUseInMBEC(
A, U, UserI, State))
645template <
class AAType,
typename StateType =
typename AAType::StateType>
646static void followUsesInMBEC(AAType &
AA,
Attributor &
A, StateType &S,
648 const Value &Val =
AA.getIRPosition().getAssociatedValue();
653 A.getInfoCache().getMustBeExecutedContextExplorer();
659 for (
const Use &U : Val.
uses())
662 followUsesInContext<AAType>(
AA,
A, *Explorer, &CtxI,
Uses, S);
664 if (S.isAtFixpoint())
708 StateType ParentState;
712 ParentState.indicateOptimisticFixpoint();
714 for (
const BasicBlock *BB : Br->successors()) {
715 StateType ChildState;
717 size_t BeforeSize =
Uses.size();
718 followUsesInContext(
AA,
A, *Explorer, &BB->front(),
Uses, ChildState);
721 for (
auto It =
Uses.begin() + BeforeSize; It !=
Uses.end();)
724 ParentState &= ChildState;
784 R.indicatePessimisticFixpoint();
801 BS.indicateOptimisticFixpoint();
807 BS.indicatePessimisticFixpoint();
877 template <
typename F>
884 if (!
Range.mayOverlap(ItRange))
886 bool IsExact =
Range == ItRange && !
Range.offsetOrSizeAreUnknown();
887 for (
auto Index : It.getSecond()) {
897 template <
typename F>
908 for (
unsigned Index : LocalList->getSecond()) {
911 if (
Range.offsetAndSizeAreUnknown())
927 RemoteI = RemoteI ? RemoteI : &
I;
931 bool AccExists =
false;
933 for (
auto Index : LocalList) {
935 if (
A.getLocalInst() == &
I) {
944 <<
"[AAPointerInfo] Inserting access in new offset bins\n";);
946 for (
auto Key : ToAdd) {
953 AccessList.emplace_back(&
I, RemoteI, Ranges, Content, Kind, Ty);
955 "New Access should have been at AccIndex");
956 LocalList.push_back(AccIndex);
965 auto Before = Current;
967 if (Current == Before)
970 auto &ExistingRanges = Before.getRanges();
971 auto &NewRanges = Current.getRanges();
978 <<
"[AAPointerInfo] Removing access from old offset bins\n";);
985 "Expected bin to actually contain the Access.");
1007struct AAPointerInfoImpl
1008 :
public StateWrapper<AA::PointerInfo::State, AAPointerInfo> {
1013 const std::string getAsStr(
Attributor *
A)
const override {
1014 return std::string(
"PointerInfo ") +
1015 (isValidState() ? (std::string(
"#") +
1016 std::to_string(OffsetBins.size()) +
" bins")
1021 [](int64_t O) {
return std::to_string(O); }),
1029 return AAPointerInfo::manifest(
A);
1032 const_bin_iterator
begin()
const override {
return State::begin(); }
1033 const_bin_iterator
end()
const override {
return State::end(); }
1034 int64_t numOffsetBins()
const override {
return State::numOffsetBins(); }
1035 bool reachesReturn()
const override {
1036 return !ReturnedOffsets.isUnassigned();
1038 void addReturnedOffsetsTo(OffsetInfo &OI)
const override {
1039 if (ReturnedOffsets.isUnknown()) {
1044 OffsetInfo MergedOI;
1045 for (
auto Offset : ReturnedOffsets) {
1046 OffsetInfo TmpOI = OI;
1048 MergedOI.merge(TmpOI);
1050 OI = std::move(MergedOI);
1053 ChangeStatus setReachesReturn(
const OffsetInfo &ReachedReturnedOffsets) {
1054 if (ReturnedOffsets.isUnknown())
1055 return ChangeStatus::UNCHANGED;
1056 if (ReachedReturnedOffsets.isUnknown()) {
1057 ReturnedOffsets.setUnknown();
1058 return ChangeStatus::CHANGED;
1060 if (ReturnedOffsets.merge(ReachedReturnedOffsets))
1061 return ChangeStatus::CHANGED;
1062 return ChangeStatus::UNCHANGED;
1065 bool forallInterferingAccesses(
1067 function_ref<
bool(
const AAPointerInfo::Access &,
bool)> CB)
1069 return State::forallInterferingAccesses(
Range, CB);
1072 bool forallInterferingAccesses(
1073 Attributor &
A,
const AbstractAttribute &QueryingAA, Instruction &
I,
1074 bool FindInterferingWrites,
bool FindInterferingReads,
1075 function_ref<
bool(
const Access &,
bool)> UserCB,
bool &HasBeenWrittenTo,
1077 function_ref<
bool(
const Access &)> SkipCB)
const override {
1078 HasBeenWrittenTo =
false;
1080 SmallPtrSet<const Access *, 8> DominatingWrites;
1088 const auto *ExecDomainAA =
A.lookupAAFor<AAExecutionDomain>(
1090 bool AllInSameNoSyncFn = IsAssumedNoSync;
1091 bool InstIsExecutedByInitialThreadOnly =
1092 ExecDomainAA && ExecDomainAA->isExecutedByInitialThreadOnly(
I);
1099 bool InstIsExecutedInAlignedRegion =
1100 FindInterferingReads && ExecDomainAA &&
1101 ExecDomainAA->isExecutedInAlignedRegion(
A,
I);
1103 if (InstIsExecutedInAlignedRegion || InstIsExecutedByInitialThreadOnly)
1104 A.recordDependence(*ExecDomainAA, QueryingAA, DepClassTy::OPTIONAL);
1106 InformationCache &InfoCache =
A.getInfoCache();
1107 bool IsThreadLocalObj =
1116 auto CanIgnoreThreadingForInst = [&](
const Instruction &
I) ->
bool {
1117 if (IsThreadLocalObj || AllInSameNoSyncFn)
1119 const auto *FnExecDomainAA =
1120 I.getFunction() == &
Scope
1122 :
A.lookupAAFor<AAExecutionDomain>(
1125 if (!FnExecDomainAA)
1127 if (InstIsExecutedInAlignedRegion ||
1128 (FindInterferingWrites &&
1129 FnExecDomainAA->isExecutedInAlignedRegion(
A,
I))) {
1130 A.recordDependence(*FnExecDomainAA, QueryingAA, DepClassTy::OPTIONAL);
1133 if (InstIsExecutedByInitialThreadOnly &&
1134 FnExecDomainAA->isExecutedByInitialThreadOnly(
I)) {
1135 A.recordDependence(*FnExecDomainAA, QueryingAA, DepClassTy::OPTIONAL);
1144 auto CanIgnoreThreading = [&](
const Access &Acc) ->
bool {
1145 return CanIgnoreThreadingForInst(*Acc.getRemoteInst()) ||
1146 (Acc.getRemoteInst() != Acc.getLocalInst() &&
1147 CanIgnoreThreadingForInst(*Acc.getLocalInst()));
1151 bool IsKnownNoRecurse;
1159 bool InstInKernel =
A.getInfoCache().isKernel(Scope);
1160 bool ObjHasKernelLifetime =
false;
1161 const bool UseDominanceReasoning =
1162 FindInterferingWrites && IsKnownNoRecurse;
1163 const DominatorTree *DT =
1172 unsigned VAS =
V->getType()->getPointerAddressSpace();
1183 std::function<bool(
const Function &)> IsLiveInCalleeCB;
1188 const Function *AIFn = AI->getFunction();
1189 ObjHasKernelLifetime =
A.getInfoCache().isKernel(*AIFn);
1190 bool IsKnownNoRecurse;
1193 IsKnownNoRecurse)) {
1194 IsLiveInCalleeCB = [AIFn](
const Function &Fn) {
return AIFn != &Fn; };
1199 ObjHasKernelLifetime = HasKernelLifetime(GV, *GV->getParent());
1200 if (ObjHasKernelLifetime)
1201 IsLiveInCalleeCB = [&
A](
const Function &Fn) {
1202 return !
A.getInfoCache().isKernel(Fn);
1210 auto AccessCB = [&](
const Access &Acc,
bool Exact) {
1211 Function *AccScope = Acc.getRemoteInst()->getFunction();
1212 bool AccInSameScope = AccScope == &
Scope;
1216 if (InstInKernel && ObjHasKernelLifetime && !AccInSameScope &&
1217 A.getInfoCache().isKernel(*AccScope))
1220 if (Exact && Acc.isMustAccess() && Acc.getRemoteInst() != &
I) {
1221 if (Acc.isWrite() || (
isa<LoadInst>(
I) && Acc.isWriteOrAssumption()))
1222 ExclusionSet.
insert(Acc.getRemoteInst());
1225 if ((!FindInterferingWrites || !Acc.isWriteOrAssumption()) &&
1226 (!FindInterferingReads || !Acc.isRead()))
1229 bool Dominates = FindInterferingWrites && DT && Exact &&
1230 Acc.isMustAccess() && AccInSameScope &&
1233 DominatingWrites.
insert(&Acc);
1237 AllInSameNoSyncFn &= Acc.getRemoteInst()->getFunction() == &
Scope;
1239 InterferingAccesses.
push_back({&Acc, Exact});
1242 if (!State::forallInterferingAccesses(
I, AccessCB,
Range))
1245 HasBeenWrittenTo = !DominatingWrites.
empty();
1249 for (
const Access *Acc : DominatingWrites) {
1250 if (!LeastDominatingWriteInst) {
1251 LeastDominatingWriteInst = Acc->getRemoteInst();
1252 }
else if (DT->
dominates(LeastDominatingWriteInst,
1253 Acc->getRemoteInst())) {
1254 LeastDominatingWriteInst = Acc->getRemoteInst();
1259 auto CanSkipAccess = [&](
const Access &Acc,
bool Exact) {
1260 if (SkipCB && SkipCB(Acc))
1262 if (!CanIgnoreThreading(Acc))
1268 bool ReadChecked = !FindInterferingReads;
1269 bool WriteChecked = !FindInterferingWrites;
1275 &ExclusionSet, IsLiveInCalleeCB))
1280 if (!WriteChecked) {
1282 &ExclusionSet, IsLiveInCalleeCB))
1283 WriteChecked =
true;
1297 if (!WriteChecked && HasBeenWrittenTo &&
1298 Acc.getRemoteInst()->getFunction() != &Scope) {
1300 const auto *FnReachabilityAA =
A.getAAFor<AAInterFnReachability>(
1302 if (FnReachabilityAA) {
1308 if (!FnReachabilityAA->instructionCanReach(
1309 A, *LeastDominatingWriteInst,
1310 *Acc.getRemoteInst()->getFunction(), &ExclusionSet))
1311 WriteChecked =
true;
1318 if (ReadChecked && WriteChecked)
1321 if (!DT || !UseDominanceReasoning)
1323 if (!DominatingWrites.count(&Acc))
1325 return LeastDominatingWriteInst != Acc.getRemoteInst();
1330 for (
auto &It : InterferingAccesses) {
1331 if ((!AllInSameNoSyncFn && !IsThreadLocalObj && !ExecDomainAA) ||
1332 !CanSkipAccess(*It.first, It.second)) {
1333 if (!UserCB(*It.first, It.second))
1341 const AAPointerInfo &OtherAA,
1343 using namespace AA::PointerInfo;
1345 return indicatePessimisticFixpoint();
1348 const auto &OtherAAImpl =
static_cast<const AAPointerInfoImpl &
>(OtherAA);
1349 bool IsByval = OtherAAImpl.getAssociatedArgument()->hasByValAttr();
1350 Changed |= setReachesReturn(OtherAAImpl.ReturnedOffsets);
1353 const auto &State = OtherAAImpl.getState();
1354 for (
const auto &It : State) {
1355 for (
auto Index : It.getSecond()) {
1356 const auto &RAcc = State.getAccess(Index);
1357 if (IsByval && !RAcc.isRead())
1359 bool UsedAssumedInformation =
false;
1361 auto Content =
A.translateArgumentToCallSiteContent(
1362 RAcc.getContent(), CB, *
this, UsedAssumedInformation);
1363 AK =
AccessKind(AK & (IsByval ? AccessKind::AK_R : AccessKind::AK_RW));
1364 AK =
AccessKind(AK | (RAcc.isMayAccess() ? AK_MAY : AK_MUST));
1366 Changed |= addAccess(
A, RAcc.getRanges(), CB, Content, AK,
1367 RAcc.getType(), RAcc.getRemoteInst());
1373 ChangeStatus translateAndAddState(Attributor &
A,
const AAPointerInfo &OtherAA,
1374 const OffsetInfo &Offsets, CallBase &CB,
1376 using namespace AA::PointerInfo;
1378 return indicatePessimisticFixpoint();
1380 const auto &OtherAAImpl =
static_cast<const AAPointerInfoImpl &
>(OtherAA);
1384 const auto &State = OtherAAImpl.getState();
1385 for (
const auto &It : State) {
1386 for (
auto Index : It.getSecond()) {
1387 const auto &RAcc = State.getAccess(Index);
1388 if (!IsMustAcc && RAcc.isAssumption())
1390 for (
auto Offset : Offsets) {
1394 if (!NewRanges.isUnknown()) {
1395 NewRanges.addToAllOffsets(Offset);
1400 Changed |= addAccess(
A, NewRanges, CB, RAcc.getContent(), AK,
1401 RAcc.getType(), RAcc.getRemoteInst());
1410 void trackPointerInfoStatistics(
const IRPosition &IRP)
const {}
1413 void dumpState(raw_ostream &O) {
1414 for (
auto &It : OffsetBins) {
1415 O <<
"[" << It.first.Offset <<
"-" << It.first.Offset + It.first.Size
1416 <<
"] : " << It.getSecond().size() <<
"\n";
1417 for (
auto AccIndex : It.getSecond()) {
1418 auto &Acc = AccessList[AccIndex];
1419 O <<
" - " << Acc.getKind() <<
" - " << *Acc.getLocalInst() <<
"\n";
1420 if (Acc.getLocalInst() != Acc.getRemoteInst())
1421 O <<
" --> " << *Acc.getRemoteInst()
1423 if (!Acc.isWrittenValueYetUndetermined()) {
1425 O <<
" - c: func " << Acc.getWrittenValue()->getName()
1427 else if (Acc.getWrittenValue())
1428 O <<
" - c: " << *Acc.getWrittenValue() <<
"\n";
1430 O <<
" - c: <unknown>\n";
1437struct AAPointerInfoFloating :
public AAPointerInfoImpl {
1439 AAPointerInfoFloating(
const IRPosition &IRP, Attributor &
A)
1440 : AAPointerInfoImpl(IRP,
A) {}
1443 bool handleAccess(Attributor &
A, Instruction &
I,
1444 std::optional<Value *> Content,
AccessKind Kind,
1447 using namespace AA::PointerInfo;
1449 const DataLayout &
DL =
A.getDataLayout();
1450 TypeSize AccessSize =
DL.getTypeStoreSize(&Ty);
1459 if (!VT || VT->getElementCount().isScalable() ||
1461 (*Content)->getType() != VT ||
1462 DL.getTypeStoreSize(VT->getElementType()).isScalable()) {
1473 int64_t ElementSize =
DL.getTypeStoreSize(ElementType).getFixedValue();
1478 for (
int i = 0, e = VT->getElementCount().getFixedValue(); i != e; ++i) {
1480 ConstContent, ConstantInt::get(
Int32Ty, i));
1487 for (
auto &ElementOffset : ElementOffsets)
1488 ElementOffset += ElementSize;
1501 bool collectConstantsForGEP(Attributor &
A,
const DataLayout &
DL,
1502 OffsetInfo &UsrOI,
const OffsetInfo &PtrOI,
1503 const GEPOperator *
GEP);
1506 void trackStatistics()
const override {
1507 AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());
1511bool AAPointerInfoFloating::collectConstantsForGEP(Attributor &
A,
1512 const DataLayout &
DL,
1514 const OffsetInfo &PtrOI,
1515 const GEPOperator *
GEP) {
1516 unsigned BitWidth =
DL.getIndexTypeSizeInBits(
GEP->getType());
1517 SmallMapVector<Value *, APInt, 4> VariableOffsets;
1520 assert(!UsrOI.isUnknown() && !PtrOI.isUnknown() &&
1521 "Don't look for constant values if the offset has already been "
1522 "determined to be unknown.");
1524 if (!
GEP->collectOffset(
DL,
BitWidth, VariableOffsets, ConstantOffset)) {
1530 << (VariableOffsets.
empty() ?
"" :
"not") <<
" constant "
1534 Union.addToAll(ConstantOffset.getSExtValue());
1539 for (
const auto &VI : VariableOffsets) {
1540 auto *PotentialConstantsAA =
A.getAAFor<AAPotentialConstantValues>(
1542 if (!PotentialConstantsAA || !PotentialConstantsAA->isValidState()) {
1548 if (PotentialConstantsAA->undefIsContained())
1555 auto &AssumedSet = PotentialConstantsAA->getAssumedSet();
1556 if (AssumedSet.empty())
1560 for (
const auto &ConstOffset : AssumedSet) {
1561 auto CopyPerOffset =
Union;
1562 CopyPerOffset.addToAll(ConstOffset.getSExtValue() *
1563 VI.second.getZExtValue());
1564 Product.merge(CopyPerOffset);
1569 UsrOI = std::move(Union);
1573ChangeStatus AAPointerInfoFloating::updateImpl(Attributor &
A) {
1574 using namespace AA::PointerInfo;
1576 const DataLayout &
DL =
A.getDataLayout();
1577 Value &AssociatedValue = getAssociatedValue();
1579 DenseMap<Value *, OffsetInfo> OffsetInfoMap;
1580 OffsetInfoMap[&AssociatedValue].
insert(0);
1582 auto HandlePassthroughUser = [&](
Value *Usr,
Value *CurPtr,
bool &Follow) {
1593 "CurPtr does not exist in the map!");
1595 auto &UsrOI = OffsetInfoMap[Usr];
1596 auto &PtrOI = OffsetInfoMap[CurPtr];
1597 assert(!PtrOI.isUnassigned() &&
1598 "Cannot pass through if the input Ptr was not visited!");
1604 auto UsePred = [&](
const Use &
U,
bool &Follow) ->
bool {
1606 User *Usr =
U.getUser();
1607 LLVM_DEBUG(
dbgs() <<
"[AAPointerInfo] Analyze " << *CurPtr <<
" in " << *Usr
1610 "The current pointer offset should have been seeded!");
1611 assert(!OffsetInfoMap[CurPtr].isUnassigned() &&
1612 "Current pointer should be assigned");
1616 return HandlePassthroughUser(Usr, CurPtr, Follow);
1618 LLVM_DEBUG(
dbgs() <<
"[AAPointerInfo] Unhandled constant user " << *CE
1626 auto &UsrOI = OffsetInfoMap[Usr];
1627 auto &PtrOI = OffsetInfoMap[CurPtr];
1629 if (UsrOI.isUnknown())
1632 if (PtrOI.isUnknown()) {
1638 Follow = collectConstantsForGEP(
A,
DL, UsrOI, PtrOI,
GEP);
1644 return HandlePassthroughUser(Usr, CurPtr, Follow);
1649 if (RI->getFunction() == getAssociatedFunction()) {
1650 auto &PtrOI = OffsetInfoMap[CurPtr];
1651 Changed |= setReachesReturn(PtrOI);
1664 auto &UsrOI = PhiIt->second;
1665 auto &PtrOI = OffsetInfoMap[CurPtr];
1669 if (PtrOI.isUnknown()) {
1670 LLVM_DEBUG(
dbgs() <<
"[AAPointerInfo] PHI operand offset unknown "
1671 << *CurPtr <<
" in " << *
PHI <<
"\n");
1672 Follow = !UsrOI.isUnknown();
1678 if (UsrOI == PtrOI) {
1679 assert(!PtrOI.isUnassigned() &&
1680 "Cannot assign if the current Ptr was not visited!");
1681 LLVM_DEBUG(
dbgs() <<
"[AAPointerInfo] PHI is invariant (so far)");
1691 auto It = OffsetInfoMap.
find(CurPtrBase);
1692 if (It == OffsetInfoMap.
end()) {
1693 LLVM_DEBUG(
dbgs() <<
"[AAPointerInfo] PHI operand is too complex "
1694 << *CurPtr <<
" in " << *
PHI
1695 <<
" (base: " << *CurPtrBase <<
")\n");
1709 A.getInfoCache().getAnalysisResultForFunction<CycleAnalysis>(
1710 *
PHI->getFunction());
1712 auto BaseOI = It->getSecond();
1713 BaseOI.addToAll(
Offset.getZExtValue());
1714 if (IsFirstPHIUser || BaseOI == UsrOI) {
1715 LLVM_DEBUG(
dbgs() <<
"[AAPointerInfo] PHI is invariant " << *CurPtr
1716 <<
" in " << *Usr <<
"\n");
1717 return HandlePassthroughUser(Usr, CurPtr, Follow);
1721 dbgs() <<
"[AAPointerInfo] PHI operand pointer offset mismatch "
1722 << *CurPtr <<
" in " << *
PHI <<
"\n");
1741 if (!handleAccess(
A, *LoadI,
nullptr, AK,
1742 OffsetInfoMap[CurPtr].Offsets,
Changed,
1748 return II->isAssumeLikeIntrinsic();
1759 }
while (FromI && FromI != ToI);
1764 auto IsValidAssume = [&](IntrinsicInst &IntrI) {
1765 if (IntrI.getIntrinsicID() != Intrinsic::assume)
1768 if (IntrI.getParent() == BB) {
1769 if (IsImpactedInRange(LoadI->getNextNode(), &IntrI))
1775 if ((*PredIt) != BB)
1780 if (SuccBB == IntrBB)
1786 if (IsImpactedInRange(LoadI->getNextNode(), BB->
getTerminator()))
1788 if (IsImpactedInRange(&IntrBB->
front(), &IntrI))
1794 std::pair<Value *, IntrinsicInst *> Assumption;
1795 for (
const Use &LoadU : LoadI->uses()) {
1797 if (!CmpI->isEquality() || !CmpI->isTrueWhenEqual())
1799 for (
const Use &CmpU : CmpI->uses()) {
1801 if (!IsValidAssume(*IntrI))
1803 int Idx = CmpI->getOperandUse(0) == LoadU;
1804 Assumption = {CmpI->getOperand(Idx), IntrI};
1809 if (Assumption.first)
1814 if (!Assumption.first || !Assumption.second)
1818 << *Assumption.second <<
": " << *LoadI
1819 <<
" == " << *Assumption.first <<
"\n");
1820 bool UsedAssumedInformation =
false;
1821 std::optional<Value *> Content =
nullptr;
1822 if (Assumption.first)
1824 A.getAssumedSimplified(*Assumption.first, *
this,
1826 return handleAccess(
1827 A, *Assumption.second, Content, AccessKind::AK_ASSUMPTION,
1828 OffsetInfoMap[CurPtr].Offsets,
Changed, *LoadI->getType());
1833 for (
auto *OtherOp : OtherOps) {
1834 if (OtherOp == CurPtr) {
1837 <<
"[AAPointerInfo] Escaping use in store like instruction " <<
I
1849 bool UsedAssumedInformation =
false;
1850 std::optional<Value *> Content =
nullptr;
1852 Content =
A.getAssumedSimplified(
1854 return handleAccess(
A,
I, Content, AK, OffsetInfoMap[CurPtr].Offsets,
1859 return HandleStoreLike(*StoreI, StoreI->getValueOperand(),
1860 *StoreI->getValueOperand()->getType(),
1861 {StoreI->getValueOperand()}, AccessKind::AK_W);
1863 return HandleStoreLike(*RMWI,
nullptr, *RMWI->getValOperand()->getType(),
1864 {RMWI->getValOperand()}, AccessKind::AK_RW);
1866 return HandleStoreLike(
1867 *CXI,
nullptr, *CXI->getNewValOperand()->getType(),
1868 {CXI->getCompareOperand(), CXI->getNewValOperand()},
1875 A.getInfoCache().getTargetLibraryInfoForFunction(*CB->
getFunction());
1880 const auto *CSArgPI =
A.getAAFor<AAPointerInfo>(
1886 Changed = translateAndAddState(
A, *CSArgPI, OffsetInfoMap[CurPtr], *CB,
1889 if (!CSArgPI->reachesReturn())
1890 return isValidState();
1893 if (!Callee ||
Callee->arg_size() <= ArgNo)
1895 bool UsedAssumedInformation =
false;
1896 auto ReturnedValue =
A.getAssumedSimplified(
1901 auto *Arg =
Callee->getArg(ArgNo);
1902 if (ReturnedArg && Arg != ReturnedArg)
1904 bool IsRetMustAcc = IsArgMustAcc && (ReturnedArg == Arg);
1905 const auto *CSRetPI =
A.getAAFor<AAPointerInfo>(
1909 OffsetInfo OI = OffsetInfoMap[CurPtr];
1910 CSArgPI->addReturnedOffsetsTo(OI);
1912 translateAndAddState(
A, *CSRetPI, OI, *CB, IsRetMustAcc) |
Changed;
1913 return isValidState();
1915 LLVM_DEBUG(
dbgs() <<
"[AAPointerInfo] Call user not handled " << *CB
1920 LLVM_DEBUG(
dbgs() <<
"[AAPointerInfo] User not handled " << *Usr <<
"\n");
1923 auto EquivalentUseCB = [&](
const Use &OldU,
const Use &NewU) {
1924 assert(OffsetInfoMap.
count(OldU) &&
"Old use should be known already!");
1925 assert(!OffsetInfoMap[OldU].isUnassigned() &&
"Old use should be assinged");
1926 if (OffsetInfoMap.
count(NewU)) {
1928 if (!(OffsetInfoMap[NewU] == OffsetInfoMap[OldU])) {
1929 dbgs() <<
"[AAPointerInfo] Equivalent use callback failed: "
1930 << OffsetInfoMap[NewU] <<
" vs " << OffsetInfoMap[OldU]
1934 return OffsetInfoMap[NewU] == OffsetInfoMap[OldU];
1937 return HandlePassthroughUser(NewU.get(), OldU.
get(), Unused);
1939 if (!
A.checkForAllUses(UsePred, *
this, AssociatedValue,
1941 true, EquivalentUseCB)) {
1942 LLVM_DEBUG(
dbgs() <<
"[AAPointerInfo] Check for all uses failed, abort!\n");
1943 return indicatePessimisticFixpoint();
1947 dbgs() <<
"Accesses by bin after update:\n";
1954struct AAPointerInfoReturned final : AAPointerInfoImpl {
1955 AAPointerInfoReturned(
const IRPosition &IRP, Attributor &
A)
1956 : AAPointerInfoImpl(IRP,
A) {}
1960 return indicatePessimisticFixpoint();
1964 void trackStatistics()
const override {
1965 AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());
1969struct AAPointerInfoArgument final : AAPointerInfoFloating {
1970 AAPointerInfoArgument(
const IRPosition &IRP, Attributor &
A)
1971 : AAPointerInfoFloating(IRP,
A) {}
1974 void trackStatistics()
const override {
1975 AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());
1979struct AAPointerInfoCallSiteArgument final : AAPointerInfoFloating {
1980 AAPointerInfoCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
1981 : AAPointerInfoFloating(IRP,
A) {}
1985 using namespace AA::PointerInfo;
1991 if (
auto Length =
MI->getLengthInBytes())
1992 LengthVal =
Length->getSExtValue();
1993 unsigned ArgNo = getIRPosition().getCallSiteArgNo();
1996 LLVM_DEBUG(
dbgs() <<
"[AAPointerInfo] Unhandled memory intrinsic "
1998 return indicatePessimisticFixpoint();
2001 ArgNo == 0 ? AccessKind::AK_MUST_WRITE : AccessKind::AK_MUST_READ;
2003 Changed | addAccess(
A, {0, LengthVal}, *
MI,
nullptr,
Kind,
nullptr);
2006 dbgs() <<
"Accesses by bin after update:\n";
2017 Argument *Arg = getAssociatedArgument();
2021 A.getAAFor<AAPointerInfo>(*
this, ArgPos, DepClassTy::REQUIRED);
2022 if (ArgAA && ArgAA->getState().isValidState())
2023 return translateAndAddStateFromCallee(
A, *ArgAA,
2026 return indicatePessimisticFixpoint();
2029 bool IsKnownNoCapture;
2031 A,
this, getIRPosition(), DepClassTy::OPTIONAL, IsKnownNoCapture))
2032 return indicatePessimisticFixpoint();
2034 bool IsKnown =
false;
2036 return ChangeStatus::UNCHANGED;
2039 ReadOnly ? AccessKind::AK_MAY_READ : AccessKind::AK_MAY_READ_WRITE;
2045 void trackStatistics()
const override {
2046 AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());
2050struct AAPointerInfoCallSiteReturned final : AAPointerInfoFloating {
2051 AAPointerInfoCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
2052 : AAPointerInfoFloating(IRP,
A) {}
2055 void trackStatistics()
const override {
2056 AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());
2064struct AANoUnwindImpl : AANoUnwind {
2065 AANoUnwindImpl(
const IRPosition &IRP, Attributor &
A) : AANoUnwind(IRP,
A) {}
2071 A,
nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));
2075 const std::string getAsStr(Attributor *
A)
const override {
2076 return getAssumed() ?
"nounwind" :
"may-unwind";
2082 (unsigned)Instruction::Invoke, (
unsigned)Instruction::CallBr,
2083 (unsigned)Instruction::Call, (
unsigned)Instruction::CleanupRet,
2084 (unsigned)Instruction::CatchSwitch, (
unsigned)Instruction::Resume};
2087 if (!
I.mayThrow(
true))
2091 bool IsKnownNoUnwind;
2099 bool UsedAssumedInformation =
false;
2100 if (!
A.checkForAllInstructions(CheckForNoUnwind, *
this, Opcodes,
2101 UsedAssumedInformation))
2102 return indicatePessimisticFixpoint();
2104 return ChangeStatus::UNCHANGED;
2108struct AANoUnwindFunction final :
public AANoUnwindImpl {
2109 AANoUnwindFunction(
const IRPosition &IRP, Attributor &
A)
2110 : AANoUnwindImpl(IRP,
A) {}
2117struct AANoUnwindCallSite final
2118 : AACalleeToCallSite<AANoUnwind, AANoUnwindImpl> {
2119 AANoUnwindCallSite(
const IRPosition &IRP, Attributor &
A)
2120 : AACalleeToCallSite<AANoUnwind, AANoUnwindImpl>(IRP,
A) {}
2131 case Intrinsic::nvvm_barrier_cta_sync_aligned_all:
2132 case Intrinsic::nvvm_barrier_cta_sync_aligned_count:
2133 case Intrinsic::nvvm_barrier_cta_red_and_aligned_all:
2134 case Intrinsic::nvvm_barrier_cta_red_and_aligned_count:
2135 case Intrinsic::nvvm_barrier_cta_red_or_aligned_all:
2136 case Intrinsic::nvvm_barrier_cta_red_or_aligned_count:
2137 case Intrinsic::nvvm_barrier_cta_red_popc_aligned_all:
2138 case Intrinsic::nvvm_barrier_cta_red_popc_aligned_count:
2140 case Intrinsic::amdgcn_s_barrier:
2141 if (ExecutedAligned)
2164 switch (
I->getOpcode()) {
2165 case Instruction::AtomicRMW:
2168 case Instruction::Store:
2171 case Instruction::Load:
2176 "New atomic operations need to be known in the attributor.");
2195 const std::string getAsStr(Attributor *
A)
const override {
2196 return getAssumed() ?
"nosync" :
"may-sync";
2212 if (
I.mayReadOrWriteMemory())
2226 bool UsedAssumedInformation =
false;
2227 if (!
A.checkForAllReadWriteInstructions(CheckRWInstForNoSync, *
this,
2228 UsedAssumedInformation) ||
2229 !
A.checkForAllCallLikeInstructions(CheckForNoSync, *
this,
2230 UsedAssumedInformation))
2231 return indicatePessimisticFixpoint();
2236struct AANoSyncFunction final :
public AANoSyncImpl {
2237 AANoSyncFunction(
const IRPosition &IRP, Attributor &
A)
2238 : AANoSyncImpl(IRP,
A) {}
2245struct AANoSyncCallSite final : AACalleeToCallSite<AANoSync, AANoSyncImpl> {
2246 AANoSyncCallSite(
const IRPosition &IRP, Attributor &
A)
2247 : AACalleeToCallSite<AANoSync, AANoSyncImpl>(IRP,
A) {}
2257struct AANoFreeImpl :
public AANoFree {
2258 AANoFreeImpl(
const IRPosition &IRP, Attributor &
A) : AANoFree(IRP,
A) {}
2264 DepClassTy::NONE, IsKnown));
2282 bool UsedAssumedInformation =
false;
2283 if (!
A.checkForAllReadWriteInstructions(CheckForNoFree, *
this,
2284 UsedAssumedInformation) ||
2285 !
A.checkForAllCallLikeInstructions(CheckForNoFree, *
this,
2286 UsedAssumedInformation))
2287 return indicatePessimisticFixpoint();
2289 return ChangeStatus::UNCHANGED;
2293 const std::string getAsStr(Attributor *
A)
const override {
2294 return getAssumed() ?
"nofree" :
"may-free";
2298struct AANoFreeFunction final :
public AANoFreeImpl {
2299 AANoFreeFunction(
const IRPosition &IRP, Attributor &
A)
2300 : AANoFreeImpl(IRP,
A) {}
2307struct AANoFreeCallSite final : AACalleeToCallSite<AANoFree, AANoFreeImpl> {
2308 AANoFreeCallSite(
const IRPosition &IRP, Attributor &
A)
2309 : AACalleeToCallSite<AANoFree, AANoFreeImpl>(IRP,
A) {}
2316struct AANoFreeFloating : AANoFreeImpl {
2317 AANoFreeFloating(
const IRPosition &IRP, Attributor &
A)
2318 : AANoFreeImpl(IRP,
A) {}
2325 const IRPosition &IRP = getIRPosition();
2330 DepClassTy::OPTIONAL, IsKnown))
2331 return ChangeStatus::UNCHANGED;
2333 Value &AssociatedValue = getIRPosition().getAssociatedValue();
2334 auto Pred = [&](
const Use &
U,
bool &Follow) ->
bool {
2349 DepClassTy::REQUIRED, IsKnown))
2352 const AANoCapture *NoCaptureAA =
nullptr;
2355 DepClassTy::REQUIRED, IsKnown,
2356 false, &NoCaptureAA)) {
2381 if (!
A.checkForAllUses(Pred, *
this, AssociatedValue))
2382 return indicatePessimisticFixpoint();
2384 return ChangeStatus::UNCHANGED;
2389struct AANoFreeArgument final : AANoFreeFloating {
2390 AANoFreeArgument(
const IRPosition &IRP, Attributor &
A)
2391 : AANoFreeFloating(IRP,
A) {}
2398struct AANoFreeCallSiteArgument final : AANoFreeFloating {
2399 AANoFreeCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
2400 : AANoFreeFloating(IRP,
A) {}
2408 Argument *Arg = getAssociatedArgument();
2410 return indicatePessimisticFixpoint();
2414 DepClassTy::REQUIRED, IsKnown))
2415 return ChangeStatus::UNCHANGED;
2416 return indicatePessimisticFixpoint();
2424struct AANoFreeReturned final : AANoFreeFloating {
2425 AANoFreeReturned(
const IRPosition &IRP, Attributor &
A)
2426 : AANoFreeFloating(IRP,
A) {
2441 void trackStatistics()
const override {}
2445struct AANoFreeCallSiteReturned final : AANoFreeFloating {
2446 AANoFreeCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
2447 : AANoFreeFloating(IRP,
A) {}
2450 return ChangeStatus::UNCHANGED;
2461 bool IgnoreSubsumingPositions) {
2463 AttrKinds.
push_back(Attribute::NonNull);
2466 AttrKinds.
push_back(Attribute::Dereferenceable);
2467 if (
A.hasAttr(IRP, AttrKinds, IgnoreSubsumingPositions, Attribute::NonNull))
2474 if (!Fn->isDeclaration()) {
2484 bool UsedAssumedInformation =
false;
2485 if (!
A.checkForAllInstructions(
2487 Worklist.push_back({*cast<ReturnInst>(I).getReturnValue(), &I});
2491 UsedAssumedInformation,
false,
true))
2503 Attribute::NonNull)});
2508static int64_t getKnownNonNullAndDerefBytesForUse(
2509 Attributor &
A,
const AbstractAttribute &QueryingAA,
Value &AssociatedValue,
2510 const Use *U,
const Instruction *
I,
bool &IsNonNull,
bool &TrackUse) {
2513 const Value *UseV =
U->get();
2534 const DataLayout &
DL =
A.getInfoCache().getDL();
2538 U, {Attribute::NonNull, Attribute::Dereferenceable})) {
2555 bool IsKnownNonNull;
2558 IsNonNull |= IsKnownNonNull;
2561 return DerefAA ? DerefAA->getKnownDereferenceableBytes() : 0;
2565 if (!Loc || Loc->Ptr != UseV || !Loc->Size.isPrecise() ||
2566 Loc->Size.isScalable() ||
I->isVolatile())
2572 if (
Base &&
Base == &AssociatedValue) {
2573 int64_t DerefBytes = Loc->Size.getValue() +
Offset;
2575 return std::max(int64_t(0), DerefBytes);
2582 int64_t DerefBytes = Loc->Size.getValue();
2584 return std::max(int64_t(0), DerefBytes);
2590struct AANonNullImpl : AANonNull {
2591 AANonNullImpl(
const IRPosition &IRP, Attributor &
A) : AANonNull(IRP,
A) {}
2595 Value &
V = *getAssociatedValue().stripPointerCasts();
2597 indicatePessimisticFixpoint();
2601 if (Instruction *CtxI = getCtxI())
2602 followUsesInMBEC(*
this,
A, getState(), *CtxI);
2606 bool followUseInMBEC(Attributor &
A,
const Use *U,
const Instruction *
I,
2607 AANonNull::StateType &State) {
2608 bool IsNonNull =
false;
2609 bool TrackUse =
false;
2610 getKnownNonNullAndDerefBytesForUse(
A, *
this, getAssociatedValue(), U,
I,
2611 IsNonNull, TrackUse);
2612 State.setKnown(IsNonNull);
2617 const std::string getAsStr(Attributor *
A)
const override {
2618 return getAssumed() ?
"nonnull" :
"may-null";
2623struct AANonNullFloating :
public AANonNullImpl {
2624 AANonNullFloating(
const IRPosition &IRP, Attributor &
A)
2625 : AANonNullImpl(IRP,
A) {}
2629 auto CheckIRP = [&](
const IRPosition &IRP) {
2630 bool IsKnownNonNull;
2632 A, *
this, IRP, DepClassTy::OPTIONAL, IsKnownNonNull);
2636 bool UsedAssumedInformation =
false;
2637 Value *AssociatedValue = &getAssociatedValue();
2639 if (!
A.getAssumedSimplifiedValues(getIRPosition(), *
this, Values,
2644 Values.
size() != 1 || Values.
front().getValue() != AssociatedValue;
2650 return AA::hasAssumedIRAttr<Attribute::NonNull>(
2651 A, this, IRPosition::value(*Op), DepClassTy::OPTIONAL,
2654 return ChangeStatus::UNCHANGED;
2658 DepClassTy::OPTIONAL, IsKnown) &&
2661 DepClassTy::OPTIONAL, IsKnown))
2662 return ChangeStatus::UNCHANGED;
2669 if (AVIRP == getIRPosition() || !CheckIRP(AVIRP))
2670 return indicatePessimisticFixpoint();
2671 return ChangeStatus::UNCHANGED;
2674 for (
const auto &VAC : Values)
2676 return indicatePessimisticFixpoint();
2678 return ChangeStatus::UNCHANGED;
2686struct AANonNullReturned final
2687 : AAReturnedFromReturnedValues<AANonNull, AANonNull, AANonNull::StateType,
2688 false, AANonNull::IRAttributeKind, false> {
2689 AANonNullReturned(
const IRPosition &IRP, Attributor &
A)
2690 : AAReturnedFromReturnedValues<AANonNull, AANonNull, AANonNull::StateType,
2695 const std::string getAsStr(Attributor *
A)
const override {
2696 return getAssumed() ?
"nonnull" :
"may-null";
2704struct AANonNullArgument final
2705 : AAArgumentFromCallSiteArguments<AANonNull, AANonNullImpl> {
2706 AANonNullArgument(
const IRPosition &IRP, Attributor &
A)
2707 : AAArgumentFromCallSiteArguments<AANonNull, AANonNullImpl>(IRP,
A) {}
2713struct AANonNullCallSiteArgument final : AANonNullFloating {
2714 AANonNullCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
2715 : AANonNullFloating(IRP,
A) {}
2722struct AANonNullCallSiteReturned final
2723 : AACalleeToCallSite<AANonNull, AANonNullImpl> {
2724 AANonNullCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
2725 : AACalleeToCallSite<AANonNull, AANonNullImpl>(IRP,
A) {}
2734struct AAMustProgressImpl :
public AAMustProgress {
2735 AAMustProgressImpl(
const IRPosition &IRP, Attributor &
A)
2736 : AAMustProgress(IRP,
A) {}
2742 A,
nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));
2747 const std::string getAsStr(Attributor *
A)
const override {
2748 return getAssumed() ?
"mustprogress" :
"may-not-progress";
2752struct AAMustProgressFunction final : AAMustProgressImpl {
2753 AAMustProgressFunction(
const IRPosition &IRP, Attributor &
A)
2754 : AAMustProgressImpl(IRP,
A) {}
2760 A,
this, getIRPosition(), DepClassTy::OPTIONAL, IsKnown)) {
2762 return indicateOptimisticFixpoint();
2763 return ChangeStatus::UNCHANGED;
2766 auto CheckForMustProgress = [&](AbstractCallSite ACS) {
2768 bool IsKnownMustProgress;
2770 A,
this, IPos, DepClassTy::REQUIRED, IsKnownMustProgress,
2774 bool AllCallSitesKnown =
true;
2775 if (!
A.checkForAllCallSites(CheckForMustProgress, *
this,
2778 return indicatePessimisticFixpoint();
2780 return ChangeStatus::UNCHANGED;
2784 void trackStatistics()
const override {
2790struct AAMustProgressCallSite final : AAMustProgressImpl {
2791 AAMustProgressCallSite(
const IRPosition &IRP, Attributor &
A)
2792 : AAMustProgressImpl(IRP,
A) {}
2801 bool IsKnownMustProgress;
2803 A,
this, FnPos, DepClassTy::REQUIRED, IsKnownMustProgress))
2804 return indicatePessimisticFixpoint();
2805 return ChangeStatus::UNCHANGED;
2809 void trackStatistics()
const override {
2818struct AANoRecurseImpl :
public AANoRecurse {
2819 AANoRecurseImpl(
const IRPosition &IRP, Attributor &
A) : AANoRecurse(IRP,
A) {}
2825 A,
nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));
2830 const std::string getAsStr(Attributor *
A)
const override {
2831 return getAssumed() ?
"norecurse" :
"may-recurse";
2835struct AANoRecurseFunction final : AANoRecurseImpl {
2836 AANoRecurseFunction(
const IRPosition &IRP, Attributor &
A)
2837 : AANoRecurseImpl(IRP,
A) {}
2843 auto CallSitePred = [&](AbstractCallSite ACS) {
2844 bool IsKnownNoRecurse;
2848 DepClassTy::NONE, IsKnownNoRecurse))
2850 return IsKnownNoRecurse;
2852 bool UsedAssumedInformation =
false;
2853 if (
A.checkForAllCallSites(CallSitePred, *
this,
true,
2854 UsedAssumedInformation)) {
2860 if (!UsedAssumedInformation)
2861 indicateOptimisticFixpoint();
2862 return ChangeStatus::UNCHANGED;
2865 const AAInterFnReachability *EdgeReachability =
2866 A.getAAFor<AAInterFnReachability>(*
this, getIRPosition(),
2867 DepClassTy::REQUIRED);
2868 if (EdgeReachability && EdgeReachability->
canReach(
A, *getAnchorScope()))
2869 return indicatePessimisticFixpoint();
2870 return ChangeStatus::UNCHANGED;
2877struct AANoRecurseCallSite final
2878 : AACalleeToCallSite<AANoRecurse, AANoRecurseImpl> {
2879 AANoRecurseCallSite(
const IRPosition &IRP, Attributor &
A)
2880 : AACalleeToCallSite<AANoRecurse, AANoRecurseImpl>(IRP,
A) {}
2890struct AANonConvergentImpl :
public AANonConvergent {
2891 AANonConvergentImpl(
const IRPosition &IRP, Attributor &
A)
2892 : AANonConvergent(IRP,
A) {}
2895 const std::string getAsStr(Attributor *
A)
const override {
2896 return getAssumed() ?
"non-convergent" :
"may-be-convergent";
2900struct AANonConvergentFunction final : AANonConvergentImpl {
2901 AANonConvergentFunction(
const IRPosition &IRP, Attributor &
A)
2902 : AANonConvergentImpl(IRP,
A) {}
2908 auto CalleeIsNotConvergent = [&](
Instruction &Inst) {
2911 if (!Callee ||
Callee->isIntrinsic()) {
2914 if (
Callee->isDeclaration()) {
2915 return !
Callee->hasFnAttribute(Attribute::Convergent);
2917 const auto *ConvergentAA =
A.getAAFor<AANonConvergent>(
2919 return ConvergentAA && ConvergentAA->isAssumedNotConvergent();
2922 bool UsedAssumedInformation =
false;
2923 if (!
A.checkForAllCallLikeInstructions(CalleeIsNotConvergent, *
this,
2924 UsedAssumedInformation)) {
2925 return indicatePessimisticFixpoint();
2927 return ChangeStatus::UNCHANGED;
2931 if (isKnownNotConvergent() &&
2932 A.hasAttr(getIRPosition(), Attribute::Convergent)) {
2933 A.removeAttrs(getIRPosition(), {Attribute::Convergent});
2934 return ChangeStatus::CHANGED;
2936 return ChangeStatus::UNCHANGED;
2946struct AAUndefinedBehaviorImpl :
public AAUndefinedBehavior {
2947 AAUndefinedBehaviorImpl(
const IRPosition &IRP, Attributor &
A)
2948 : AAUndefinedBehavior(IRP,
A) {}
2953 const size_t UBPrevSize = KnownUBInsts.size();
2954 const size_t NoUBPrevSize = AssumedNoUBInsts.size();
2962 if (AssumedNoUBInsts.count(&
I) || KnownUBInsts.count(&
I))
2971 "Expected pointer operand of memory accessing instruction");
2975 std::optional<Value *> SimplifiedPtrOp =
2976 stopOnUndefOrAssumed(
A, PtrOp, &
I);
2977 if (!SimplifiedPtrOp || !*SimplifiedPtrOp)
2979 const Value *PtrOpVal = *SimplifiedPtrOp;
2985 AssumedNoUBInsts.insert(&
I);
2997 AssumedNoUBInsts.insert(&
I);
2999 KnownUBInsts.insert(&
I);
3008 if (AssumedNoUBInsts.count(&
I) || KnownUBInsts.count(&
I))
3016 std::optional<Value *> SimplifiedCond =
3017 stopOnUndefOrAssumed(
A, BrInst->getCondition(), BrInst);
3018 if (!SimplifiedCond || !*SimplifiedCond)
3020 AssumedNoUBInsts.insert(&
I);
3028 if (AssumedNoUBInsts.count(&
I) || KnownUBInsts.count(&
I))
3037 for (
unsigned idx = 0; idx < CB.
arg_size(); idx++) {
3043 if (idx >=
Callee->arg_size())
3055 bool IsKnownNoUndef;
3057 A,
this, CalleeArgumentIRP, DepClassTy::NONE, IsKnownNoUndef);
3058 if (!IsKnownNoUndef)
3060 bool UsedAssumedInformation =
false;
3061 std::optional<Value *> SimplifiedVal =
3064 if (UsedAssumedInformation)
3066 if (SimplifiedVal && !*SimplifiedVal)
3069 KnownUBInsts.insert(&
I);
3075 bool IsKnownNonNull;
3077 A,
this, CalleeArgumentIRP, DepClassTy::NONE, IsKnownNonNull);
3079 KnownUBInsts.insert(&
I);
3088 std::optional<Value *> SimplifiedRetValue =
3089 stopOnUndefOrAssumed(
A, RI.getReturnValue(), &
I);
3090 if (!SimplifiedRetValue || !*SimplifiedRetValue)
3108 bool IsKnownNonNull;
3113 KnownUBInsts.insert(&
I);
3119 bool UsedAssumedInformation =
false;
3120 A.checkForAllInstructions(InspectMemAccessInstForUB, *
this,
3121 {Instruction::Load, Instruction::Store,
3122 Instruction::AtomicCmpXchg,
3123 Instruction::AtomicRMW},
3124 UsedAssumedInformation,
3126 A.checkForAllInstructions(InspectBrInstForUB, *
this, {Instruction::CondBr},
3127 UsedAssumedInformation,
3129 A.checkForAllCallLikeInstructions(InspectCallSiteForUB, *
this,
3130 UsedAssumedInformation);
3134 if (!getAnchorScope()->getReturnType()->isVoidTy()) {
3136 if (!
A.isAssumedDead(ReturnIRP,
this,
nullptr, UsedAssumedInformation)) {
3137 bool IsKnownNoUndef;
3139 A,
this, ReturnIRP, DepClassTy::NONE, IsKnownNoUndef);
3141 A.checkForAllInstructions(InspectReturnInstForUB, *
this,
3142 {Instruction::Ret}, UsedAssumedInformation,
3147 if (NoUBPrevSize != AssumedNoUBInsts.size() ||
3148 UBPrevSize != KnownUBInsts.size())
3149 return ChangeStatus::CHANGED;
3150 return ChangeStatus::UNCHANGED;
3153 bool isKnownToCauseUB(Instruction *
I)
const override {
3154 return KnownUBInsts.count(
I);
3157 bool isAssumedToCauseUB(Instruction *
I)
const override {
3164 switch (
I->getOpcode()) {
3165 case Instruction::Load:
3166 case Instruction::Store:
3167 case Instruction::AtomicCmpXchg:
3168 case Instruction::AtomicRMW:
3169 case Instruction::CondBr:
3170 return !AssumedNoUBInsts.count(
I);
3178 if (KnownUBInsts.empty())
3179 return ChangeStatus::UNCHANGED;
3180 for (Instruction *
I : KnownUBInsts)
3181 A.changeToUnreachableAfterManifest(
I);
3182 return ChangeStatus::CHANGED;
3186 const std::string getAsStr(Attributor *
A)
const override {
3187 return getAssumed() ?
"undefined-behavior" :
"no-ub";
3215 SmallPtrSet<Instruction *, 8> KnownUBInsts;
3219 SmallPtrSet<Instruction *, 8> AssumedNoUBInsts;
3230 std::optional<Value *> stopOnUndefOrAssumed(Attributor &
A,
Value *V,
3232 bool UsedAssumedInformation =
false;
3233 std::optional<Value *> SimplifiedV =
3236 if (!UsedAssumedInformation) {
3241 KnownUBInsts.insert(
I);
3242 return std::nullopt;
3249 KnownUBInsts.insert(
I);
3250 return std::nullopt;
3256struct AAUndefinedBehaviorFunction final : AAUndefinedBehaviorImpl {
3257 AAUndefinedBehaviorFunction(
const IRPosition &IRP, Attributor &
A)
3258 : AAUndefinedBehaviorImpl(IRP,
A) {}
3261 void trackStatistics()
const override {
3262 STATS_DECL(UndefinedBehaviorInstruction, Instruction,
3263 "Number of instructions known to have UB");
3265 KnownUBInsts.size();
3276static bool mayContainUnboundedCycle(Function &
F, Attributor &
A) {
3277 ScalarEvolution *SE =
3278 A.getInfoCache().getAnalysisResultForFunction<ScalarEvolutionAnalysis>(
F);
3279 LoopInfo *LI =
A.getInfoCache().getAnalysisResultForFunction<LoopAnalysis>(
F);
3285 for (scc_iterator<Function *> SCCI =
scc_begin(&
F); !SCCI.isAtEnd(); ++SCCI)
3286 if (SCCI.hasCycle())
3296 for (
auto *L : LI->getLoopsInPreorder()) {
3303struct AAWillReturnImpl :
public AAWillReturn {
3304 AAWillReturnImpl(
const IRPosition &IRP, Attributor &
A)
3305 : AAWillReturn(IRP,
A) {}
3311 A,
nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));
3316 bool isImpliedByMustprogressAndReadonly(Attributor &
A,
bool KnownOnly) {
3317 if (!
A.hasAttr(getIRPosition(), {Attribute::MustProgress}))
3322 return IsKnown || !KnownOnly;
3328 if (isImpliedByMustprogressAndReadonly(
A,
false))
3329 return ChangeStatus::UNCHANGED;
3335 A,
this, IPos, DepClassTy::REQUIRED, IsKnown)) {
3341 bool IsKnownNoRecurse;
3343 A,
this, IPos, DepClassTy::REQUIRED, IsKnownNoRecurse);
3346 bool UsedAssumedInformation =
false;
3347 if (!
A.checkForAllCallLikeInstructions(CheckForWillReturn, *
this,
3348 UsedAssumedInformation))
3349 return indicatePessimisticFixpoint();
3353 return !
I.isVolatile();
3355 if (!
A.checkForAllInstructions(CheckForVolatile, *
this,
3356 {Instruction::Load, Instruction::Store,
3357 Instruction::AtomicCmpXchg,
3358 Instruction::AtomicRMW},
3359 UsedAssumedInformation))
3360 return indicatePessimisticFixpoint();
3362 return ChangeStatus::UNCHANGED;
3366 const std::string getAsStr(Attributor *
A)
const override {
3367 return getAssumed() ?
"willreturn" :
"may-noreturn";
3371struct AAWillReturnFunction final : AAWillReturnImpl {
3372 AAWillReturnFunction(
const IRPosition &IRP, Attributor &
A)
3373 : AAWillReturnImpl(IRP,
A) {}
3377 AAWillReturnImpl::initialize(
A);
3380 assert(
F &&
"Did expect an anchor function");
3381 if (
F->isDeclaration() || mayContainUnboundedCycle(*
F,
A))
3382 indicatePessimisticFixpoint();
3390struct AAWillReturnCallSite final
3391 : AACalleeToCallSite<AAWillReturn, AAWillReturnImpl> {
3392 AAWillReturnCallSite(
const IRPosition &IRP, Attributor &
A)
3393 : AACalleeToCallSite<AAWillReturn, AAWillReturnImpl>(IRP,
A) {}
3397 if (isImpliedByMustprogressAndReadonly(
A,
false))
3398 return ChangeStatus::UNCHANGED;
3400 return AACalleeToCallSite::updateImpl(
A);
3422 const ToTy *
To =
nullptr;
3449 if (!ES || ES->
empty()) {
3450 ExclusionSet = nullptr;
3451 }
else if (MakeUnique) {
3452 ExclusionSet =
A.getInfoCache().getOrCreateUniqueBlockExecutionSet(ES);
3470 if (!PairDMI::isEqual({LHS->From, LHS->To}, {RHS->From, RHS->To}))
3472 return InstSetDMI::isEqual(LHS->ExclusionSet, RHS->ExclusionSet);
3480template <
typename BaseTy,
typename ToTy>
3481struct CachedReachabilityAA :
public BaseTy {
3482 using RQITy = ReachabilityQueryInfo<ToTy>;
3484 CachedReachabilityAA(
const IRPosition &IRP, Attributor &
A) : BaseTy(IRP,
A) {}
3487 bool isQueryAA()
const override {
return true; }
3492 for (
unsigned u = 0, e = QueryVector.size(); u < e; ++u) {
3493 RQITy *RQI = QueryVector[
u];
3494 if (RQI->Result == RQITy::Reachable::No &&
3496 Changed = ChangeStatus::CHANGED;
3502 bool IsTemporaryRQI) = 0;
3504 bool rememberResult(Attributor &
A,
typename RQITy::Reachable Result,
3505 RQITy &RQI,
bool UsedExclusionSet,
bool IsTemporaryRQI) {
3510 QueryCache.erase(&RQI);
3516 if (Result == RQITy::Reachable::Yes || !UsedExclusionSet) {
3517 RQITy PlainRQI(RQI.From, RQI.To);
3518 if (!QueryCache.count(&PlainRQI)) {
3519 RQITy *RQIPtr =
new (
A.Allocator) RQITy(RQI.From, RQI.To);
3521 QueryVector.push_back(RQIPtr);
3522 QueryCache.insert(RQIPtr);
3527 if (IsTemporaryRQI && Result != RQITy::Reachable::Yes && UsedExclusionSet) {
3528 assert((!RQI.ExclusionSet || !RQI.ExclusionSet->empty()) &&
3529 "Did not expect empty set!");
3530 RQITy *RQIPtr =
new (
A.Allocator)
3531 RQITy(
A, *RQI.From, *RQI.To, RQI.ExclusionSet,
true);
3532 assert(RQIPtr->Result == RQITy::Reachable::No &&
"Already reachable?");
3534 assert(!QueryCache.count(RQIPtr));
3535 QueryVector.push_back(RQIPtr);
3536 QueryCache.insert(RQIPtr);
3539 if (Result == RQITy::Reachable::No && IsTemporaryRQI)
3540 A.registerForUpdate(*
this);
3541 return Result == RQITy::Reachable::Yes;
3544 const std::string getAsStr(Attributor *
A)
const override {
3546 return "#queries(" + std::to_string(QueryVector.size()) +
")";
3549 bool checkQueryCache(Attributor &
A, RQITy &StackRQI,
3550 typename RQITy::Reachable &Result) {
3551 if (!this->getState().isValidState()) {
3552 Result = RQITy::Reachable::Yes;
3558 if (StackRQI.ExclusionSet) {
3559 RQITy PlainRQI(StackRQI.From, StackRQI.To);
3560 auto It = QueryCache.find(&PlainRQI);
3561 if (It != QueryCache.end() && (*It)->Result == RQITy::Reachable::No) {
3562 Result = RQITy::Reachable::No;
3567 auto It = QueryCache.find(&StackRQI);
3568 if (It != QueryCache.end()) {
3575 QueryCache.insert(&StackRQI);
3581 DenseSet<RQITy *> QueryCache;
3584struct AAIntraFnReachabilityFunction final
3585 :
public CachedReachabilityAA<AAIntraFnReachability, Instruction> {
3586 using Base = CachedReachabilityAA<AAIntraFnReachability, Instruction>;
3587 AAIntraFnReachabilityFunction(
const IRPosition &IRP, Attributor &
A)
3589 DT =
A.getInfoCache().getAnalysisResultForFunction<DominatorTreeAnalysis>(
3593 bool isAssumedReachable(
3594 Attributor &
A,
const Instruction &From,
const Instruction &To,
3596 auto *NonConstThis =
const_cast<AAIntraFnReachabilityFunction *
>(
this);
3600 RQITy StackRQI(
A, From, To, ExclusionSet,
false);
3602 if (!NonConstThis->checkQueryCache(
A, StackRQI, Result))
3603 return NonConstThis->isReachableImpl(
A, StackRQI,
3605 return Result == RQITy::Reachable::Yes;
3612 A.getAAFor<AAIsDead>(*
this, getIRPosition(), DepClassTy::OPTIONAL);
3615 [&](
const auto &DeadEdge) {
3616 return LivenessAA->isEdgeDead(DeadEdge.first,
3620 return LivenessAA->isAssumedDead(BB);
3622 return ChangeStatus::UNCHANGED;
3626 return Base::updateImpl(
A);
3630 bool IsTemporaryRQI)
override {
3632 bool UsedExclusionSet =
false;
3637 while (IP && IP != &To) {
3638 if (ExclusionSet && IP != Origin && ExclusionSet->
count(IP)) {
3639 UsedExclusionSet =
true;
3647 const BasicBlock *FromBB = RQI.From->getParent();
3648 const BasicBlock *ToBB = RQI.To->getParent();
3650 "Not an intra-procedural query!");
3654 if (FromBB == ToBB &&
3655 WillReachInBlock(*RQI.From, *RQI.To, RQI.ExclusionSet))
3656 return rememberResult(
A, RQITy::Reachable::Yes, RQI, UsedExclusionSet,
3661 if (!WillReachInBlock(ToBB->
front(), *RQI.To, RQI.ExclusionSet))
3662 return rememberResult(
A, RQITy::Reachable::No, RQI, UsedExclusionSet,
3666 SmallPtrSet<const BasicBlock *, 16> ExclusionBlocks;
3667 if (RQI.ExclusionSet)
3668 for (
auto *
I : *RQI.ExclusionSet)
3669 if (
I->getFunction() == Fn)
3670 ExclusionBlocks.
insert(
I->getParent());
3673 if (ExclusionBlocks.
count(FromBB) &&
3676 return rememberResult(
A, RQITy::Reachable::No, RQI,
true, IsTemporaryRQI);
3679 A.getAAFor<AAIsDead>(*
this, getIRPosition(), DepClassTy::OPTIONAL);
3680 if (LivenessAA && LivenessAA->isAssumedDead(ToBB)) {
3681 DeadBlocks.insert(ToBB);
3682 return rememberResult(
A, RQITy::Reachable::No, RQI, UsedExclusionSet,
3686 SmallPtrSet<const BasicBlock *, 16> Visited;
3690 DenseSet<std::pair<const BasicBlock *, const BasicBlock *>> LocalDeadEdges;
3691 while (!Worklist.
empty()) {
3693 if (!Visited.
insert(BB).second)
3695 for (
const BasicBlock *SuccBB :
successors(BB)) {
3696 if (LivenessAA && LivenessAA->isEdgeDead(BB, SuccBB)) {
3697 LocalDeadEdges.
insert({BB, SuccBB});
3702 return rememberResult(
A, RQITy::Reachable::Yes, RQI, UsedExclusionSet,
3705 return rememberResult(
A, RQITy::Reachable::Yes, RQI, UsedExclusionSet,
3708 if (ExclusionBlocks.
count(SuccBB)) {
3709 UsedExclusionSet =
true;
3716 DeadEdges.insert_range(LocalDeadEdges);
3717 return rememberResult(
A, RQITy::Reachable::No, RQI, UsedExclusionSet,
3722 void trackStatistics()
const override {}
3727 DenseSet<const BasicBlock *> DeadBlocks;
3731 DenseSet<std::pair<const BasicBlock *, const BasicBlock *>> DeadEdges;
3734 const DominatorTree *DT =
nullptr;
3742 bool IgnoreSubsumingPositions) {
3743 assert(ImpliedAttributeKind == Attribute::NoAlias &&
3744 "Unexpected attribute kind");
3750 IgnoreSubsumingPositions =
true;
3761 if (
A.hasAttr(IRP, {Attribute::ByVal, Attribute::NoAlias},
3762 IgnoreSubsumingPositions, Attribute::NoAlias))
3772 "Noalias is a pointer attribute");
3775 const std::string getAsStr(
Attributor *
A)
const override {
3776 return getAssumed() ?
"noalias" :
"may-alias";
3781struct AANoAliasFloating final : AANoAliasImpl {
3782 AANoAliasFloating(
const IRPosition &IRP, Attributor &
A)
3783 : AANoAliasImpl(IRP,
A) {}
3788 return indicatePessimisticFixpoint();
3792 void trackStatistics()
const override {
3798struct AANoAliasArgument final
3799 : AAArgumentFromCallSiteArguments<AANoAlias, AANoAliasImpl> {
3800 using Base = AAArgumentFromCallSiteArguments<AANoAlias, AANoAliasImpl>;
3801 AANoAliasArgument(
const IRPosition &IRP, Attributor &
A) :
Base(IRP,
A) {}
3814 DepClassTy::OPTIONAL, IsKnownNoSycn))
3815 return Base::updateImpl(
A);
3820 return Base::updateImpl(
A);
3824 bool UsedAssumedInformation =
false;
3825 if (
A.checkForAllCallSites(
3826 [](AbstractCallSite ACS) { return !ACS.isCallbackCall(); }, *
this,
3827 true, UsedAssumedInformation))
3828 return Base::updateImpl(
A);
3836 return indicatePessimisticFixpoint();
3843struct AANoAliasCallSiteArgument final : AANoAliasImpl {
3844 AANoAliasCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
3845 : AANoAliasImpl(IRP,
A) {}
3849 bool mayAliasWithArgument(Attributor &
A, AAResults *&AAR,
3850 const AAMemoryBehavior &MemBehaviorAA,
3851 const CallBase &CB,
unsigned OtherArgNo) {
3853 if (this->getCalleeArgNo() == (
int)OtherArgNo)
3861 auto *CBArgMemBehaviorAA =
A.getAAFor<AAMemoryBehavior>(
3865 if (CBArgMemBehaviorAA && CBArgMemBehaviorAA->isAssumedReadNone()) {
3866 A.recordDependence(*CBArgMemBehaviorAA, *
this, DepClassTy::OPTIONAL);
3873 if (CBArgMemBehaviorAA && CBArgMemBehaviorAA->isAssumedReadOnly() &&
3875 A.recordDependence(MemBehaviorAA, *
this, DepClassTy::OPTIONAL);
3876 A.recordDependence(*CBArgMemBehaviorAA, *
this, DepClassTy::OPTIONAL);
3882 AAR =
A.getInfoCache().getAnalysisResultForFunction<AAManager>(
3886 bool IsAliasing = !AAR || !AAR->
isNoAlias(&getAssociatedValue(), ArgOp);
3888 "callsite arguments: "
3889 << getAssociatedValue() <<
" " << *ArgOp <<
" => "
3890 << (IsAliasing ?
"" :
"no-") <<
"alias \n");
3895 bool isKnownNoAliasDueToNoAliasPreservation(
3896 Attributor &
A, AAResults *&AAR,
const AAMemoryBehavior &MemBehaviorAA) {
3909 auto UsePred = [&](
const Use &
U,
bool &Follow) ->
bool {
3925 bool IsKnownNoCapture;
3928 DepClassTy::OPTIONAL, IsKnownNoCapture))
3934 A, *UserI, *getCtxI(), *
this,
nullptr,
3935 [ScopeFn](
const Function &Fn) {
return &Fn != ScopeFn; }))
3950 LLVM_DEBUG(
dbgs() <<
"[AANoAliasCSArg] Unknown user: " << *UserI <<
"\n");
3954 bool IsKnownNoCapture;
3955 const AANoCapture *NoCaptureAA =
nullptr;
3957 A,
this, VIRP, DepClassTy::NONE, IsKnownNoCapture,
false, &NoCaptureAA);
3958 if (!IsAssumedNoCapture &&
3960 if (!
A.checkForAllUses(UsePred, *
this, getAssociatedValue())) {
3962 dbgs() <<
"[AANoAliasCSArg] " << getAssociatedValue()
3963 <<
" cannot be noalias as it is potentially captured\n");
3968 A.recordDependence(*NoCaptureAA, *
this, DepClassTy::OPTIONAL);
3974 for (
unsigned OtherArgNo = 0; OtherArgNo < CB.
arg_size(); OtherArgNo++)
3975 if (mayAliasWithArgument(
A, AAR, MemBehaviorAA, CB, OtherArgNo))
3985 auto *MemBehaviorAA =
3986 A.getAAFor<AAMemoryBehavior>(*
this, getIRPosition(), DepClassTy::NONE);
3988 A.recordDependence(*MemBehaviorAA, *
this, DepClassTy::OPTIONAL);
3989 return ChangeStatus::UNCHANGED;
3992 bool IsKnownNoAlias;
3995 A,
this, VIRP, DepClassTy::REQUIRED, IsKnownNoAlias)) {
3997 <<
" is not no-alias at the definition\n");
3998 return indicatePessimisticFixpoint();
4001 AAResults *AAR =
nullptr;
4002 if (MemBehaviorAA &&
4003 isKnownNoAliasDueToNoAliasPreservation(
A, AAR, *MemBehaviorAA)) {
4005 dbgs() <<
"[AANoAlias] No-Alias deduced via no-alias preservation\n");
4006 return ChangeStatus::UNCHANGED;
4009 return indicatePessimisticFixpoint();
4017struct AANoAliasReturned final : AANoAliasImpl {
4018 AANoAliasReturned(
const IRPosition &IRP, Attributor &
A)
4019 : AANoAliasImpl(IRP,
A) {}
4024 auto CheckReturnValue = [&](
Value &RV) ->
bool {
4035 bool IsKnownNoAlias;
4037 A,
this, RVPos, DepClassTy::REQUIRED, IsKnownNoAlias))
4040 bool IsKnownNoCapture;
4041 const AANoCapture *NoCaptureAA =
nullptr;
4043 A,
this, RVPos, DepClassTy::REQUIRED, IsKnownNoCapture,
false,
4045 return IsAssumedNoCapture ||
4049 if (!
A.checkForAllReturnedValues(CheckReturnValue, *
this))
4050 return indicatePessimisticFixpoint();
4052 return ChangeStatus::UNCHANGED;
4060struct AANoAliasCallSiteReturned final
4061 : AACalleeToCallSite<AANoAlias, AANoAliasImpl> {
4062 AANoAliasCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
4063 : AACalleeToCallSite<AANoAlias, AANoAliasImpl>(IRP,
A) {}
4073struct AAIsDeadValueImpl :
public AAIsDead {
4074 AAIsDeadValueImpl(
const IRPosition &IRP, Attributor &
A) : AAIsDead(IRP,
A) {}
4077 bool isAssumedDead()
const override {
return isAssumed(IS_DEAD); }
4080 bool isKnownDead()
const override {
return isKnown(IS_DEAD); }
4083 bool isAssumedDead(
const BasicBlock *BB)
const override {
return false; }
4086 bool isKnownDead(
const BasicBlock *BB)
const override {
return false; }
4089 bool isAssumedDead(
const Instruction *
I)
const override {
4090 return I == getCtxI() && isAssumedDead();
4094 bool isKnownDead(
const Instruction *
I)
const override {
4095 return isAssumedDead(
I) && isKnownDead();
4099 const std::string getAsStr(Attributor *
A)
const override {
4100 return isAssumedDead() ?
"assumed-dead" :
"assumed-live";
4104 bool areAllUsesAssumedDead(Attributor &
A,
Value &V) {
4106 if (
V.getType()->isVoidTy() ||
V.use_empty())
4112 if (!
A.isRunOn(*
I->getFunction()))
4114 bool UsedAssumedInformation =
false;
4115 std::optional<Constant *>
C =
4116 A.getAssumedConstant(V, *
this, UsedAssumedInformation);
4121 auto UsePred = [&](
const Use &
U,
bool &Follow) {
return false; };
4126 return A.checkForAllUses(UsePred, *
this, V,
false,
4127 DepClassTy::REQUIRED,
4132 bool isAssumedSideEffectFree(Attributor &
A, Instruction *
I) {
4136 if (!
I->isTerminator() && !
I->mayHaveSideEffects())
4145 bool IsKnownNoUnwind;
4147 A,
this, CallIRP, DepClassTy::OPTIONAL, IsKnownNoUnwind))
4155struct AAIsDeadFloating :
public AAIsDeadValueImpl {
4156 AAIsDeadFloating(
const IRPosition &IRP, Attributor &
A)
4157 : AAIsDeadValueImpl(IRP,
A) {}
4161 AAIsDeadValueImpl::initialize(
A);
4164 indicatePessimisticFixpoint();
4169 if (!isAssumedSideEffectFree(
A,
I)) {
4171 indicatePessimisticFixpoint();
4173 removeAssumedBits(HAS_NO_EFFECT);
4177 bool isDeadFence(Attributor &
A, FenceInst &FI) {
4178 const auto *ExecDomainAA =
A.lookupAAFor<AAExecutionDomain>(
4180 if (!ExecDomainAA || !ExecDomainAA->isNoOpFence(FI))
4182 A.recordDependence(*ExecDomainAA, *
this, DepClassTy::OPTIONAL);
4186 bool isDeadStore(Attributor &
A, StoreInst &SI,
4187 SmallSetVector<Instruction *, 8> *AssumeOnlyInst =
nullptr) {
4189 if (
SI.isVolatile())
4195 bool UsedAssumedInformation =
false;
4196 if (!AssumeOnlyInst) {
4197 PotentialCopies.clear();
4199 UsedAssumedInformation)) {
4202 <<
"[AAIsDead] Could not determine potential copies of store!\n");
4206 LLVM_DEBUG(
dbgs() <<
"[AAIsDead] Store has " << PotentialCopies.size()
4207 <<
" potential copies.\n");
4209 InformationCache &InfoCache =
A.getInfoCache();
4212 UsedAssumedInformation))
4216 auto &UserI = cast<Instruction>(*U.getUser());
4217 if (InfoCache.isOnlyUsedByAssume(UserI)) {
4219 AssumeOnlyInst->insert(&UserI);
4222 return A.isAssumedDead(U,
this,
nullptr, UsedAssumedInformation);
4228 <<
" is assumed live!\n");
4234 const std::string getAsStr(Attributor *
A)
const override {
4238 return "assumed-dead-store";
4241 return "assumed-dead-fence";
4242 return AAIsDeadValueImpl::getAsStr(
A);
4249 if (!isDeadStore(
A, *SI))
4250 return indicatePessimisticFixpoint();
4252 if (!isDeadFence(
A, *FI))
4253 return indicatePessimisticFixpoint();
4255 if (!isAssumedSideEffectFree(
A,
I))
4256 return indicatePessimisticFixpoint();
4257 if (!areAllUsesAssumedDead(
A, getAssociatedValue()))
4258 return indicatePessimisticFixpoint();
4263 bool isRemovableStore()
const override {
4264 return isAssumed(IS_REMOVABLE) &&
isa<StoreInst>(&getAssociatedValue());
4269 Value &
V = getAssociatedValue();
4276 SmallSetVector<Instruction *, 8> AssumeOnlyInst;
4277 bool IsDead = isDeadStore(
A, *SI, &AssumeOnlyInst);
4280 A.deleteAfterManifest(*
I);
4281 for (
size_t i = 0; i < AssumeOnlyInst.
size(); ++i) {
4283 for (
auto *Usr : AOI->
users())
4285 A.deleteAfterManifest(*AOI);
4291 A.deleteAfterManifest(*FI);
4295 A.deleteAfterManifest(*
I);
4303 void trackStatistics()
const override {
4309 SmallSetVector<Value *, 4> PotentialCopies;
4312struct AAIsDeadArgument :
public AAIsDeadFloating {
4313 AAIsDeadArgument(
const IRPosition &IRP, Attributor &
A)
4314 : AAIsDeadFloating(IRP,
A) {}
4318 Argument &Arg = *getAssociatedArgument();
4319 if (
A.isValidFunctionSignatureRewrite(Arg, {}))
4320 if (
A.registerFunctionSignatureRewrite(
4324 return ChangeStatus::CHANGED;
4326 return ChangeStatus::UNCHANGED;
4333struct AAIsDeadCallSiteArgument :
public AAIsDeadValueImpl {
4334 AAIsDeadCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
4335 : AAIsDeadValueImpl(IRP,
A) {}
4339 AAIsDeadValueImpl::initialize(
A);
4341 indicatePessimisticFixpoint();
4350 Argument *Arg = getAssociatedArgument();
4352 return indicatePessimisticFixpoint();
4354 auto *ArgAA =
A.getAAFor<AAIsDead>(*
this, ArgPos, DepClassTy::REQUIRED);
4356 return indicatePessimisticFixpoint();
4365 "Expected undef values to be filtered out!");
4367 if (
A.changeUseAfterManifest(U, UV))
4368 return ChangeStatus::CHANGED;
4369 return ChangeStatus::UNCHANGED;
4376struct AAIsDeadCallSiteReturned :
public AAIsDeadFloating {
4377 AAIsDeadCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
4378 : AAIsDeadFloating(IRP,
A) {}
4381 bool isAssumedDead()
const override {
4382 return AAIsDeadFloating::isAssumedDead() && IsAssumedSideEffectFree;
4387 AAIsDeadFloating::initialize(
A);
4389 indicatePessimisticFixpoint();
4394 IsAssumedSideEffectFree = isAssumedSideEffectFree(
A, getCtxI());
4400 if (IsAssumedSideEffectFree && !isAssumedSideEffectFree(
A, getCtxI())) {
4401 IsAssumedSideEffectFree =
false;
4402 Changed = ChangeStatus::CHANGED;
4404 if (!areAllUsesAssumedDead(
A, getAssociatedValue()))
4405 return indicatePessimisticFixpoint();
4410 void trackStatistics()
const override {
4411 if (IsAssumedSideEffectFree)
4418 const std::string getAsStr(Attributor *
A)
const override {
4419 return isAssumedDead()
4421 : (getAssumed() ?
"assumed-dead-users" :
"assumed-live");
4425 bool IsAssumedSideEffectFree =
true;
4428struct AAIsDeadReturned :
public AAIsDeadValueImpl {
4429 AAIsDeadReturned(
const IRPosition &IRP, Attributor &
A)
4430 : AAIsDeadValueImpl(IRP,
A) {}
4435 bool UsedAssumedInformation =
false;
4436 A.checkForAllInstructions([](Instruction &) {
return true; }, *
this,
4437 {Instruction::Ret}, UsedAssumedInformation);
4439 auto PredForCallSite = [&](AbstractCallSite ACS) {
4440 if (ACS.isCallbackCall() || !ACS.getInstruction())
4442 return areAllUsesAssumedDead(
A, *ACS.getInstruction());
4445 if (!
A.checkForAllCallSites(PredForCallSite, *
this,
true,
4446 UsedAssumedInformation))
4447 return indicatePessimisticFixpoint();
4449 return ChangeStatus::UNCHANGED;
4455 bool AnyChange =
false;
4456 UndefValue &UV = *
UndefValue::get(getAssociatedFunction()->getReturnType());
4463 bool UsedAssumedInformation =
false;
4464 A.checkForAllInstructions(RetInstPred, *
this, {Instruction::Ret},
4465 UsedAssumedInformation);
4466 return AnyChange ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
4473struct AAIsDeadFunction :
public AAIsDead {
4474 AAIsDeadFunction(
const IRPosition &IRP, Attributor &
A) : AAIsDead(IRP,
A) {}
4479 assert(
F &&
"Did expect an anchor function");
4480 if (!isAssumedDeadInternalFunction(
A)) {
4481 ToBeExploredFrom.insert(&
F->getEntryBlock().front());
4482 assumeLive(
A,
F->getEntryBlock());
4486 bool isAssumedDeadInternalFunction(Attributor &
A) {
4487 if (!getAnchorScope()->hasLocalLinkage())
4489 bool UsedAssumedInformation =
false;
4490 return A.checkForAllCallSites([](AbstractCallSite) {
return false; }, *
this,
4491 true, UsedAssumedInformation);
4495 const std::string getAsStr(Attributor *
A)
const override {
4496 return "Live[#BB " + std::to_string(AssumedLiveBlocks.size()) +
"/" +
4497 std::to_string(getAnchorScope()->
size()) +
"][#TBEP " +
4498 std::to_string(ToBeExploredFrom.size()) +
"][#KDE " +
4499 std::to_string(KnownDeadEnds.size()) +
"]";
4504 assert(getState().isValidState() &&
4505 "Attempted to manifest an invalid state!");
4510 if (AssumedLiveBlocks.empty()) {
4511 A.deleteAfterManifest(
F);
4512 return ChangeStatus::CHANGED;
4518 bool Invoke2CallAllowed = !mayCatchAsynchronousExceptions(
F);
4520 KnownDeadEnds.set_union(ToBeExploredFrom);
4521 for (
const Instruction *DeadEndI : KnownDeadEnds) {
4525 bool IsKnownNoReturn;
4533 A.registerInvokeWithDeadSuccessor(
const_cast<InvokeInst &
>(*
II));
4535 A.changeToUnreachableAfterManifest(
4536 const_cast<Instruction *
>(DeadEndI->getNextNode()));
4537 HasChanged = ChangeStatus::CHANGED;
4540 STATS_DECL(AAIsDead, BasicBlock,
"Number of dead basic blocks deleted.");
4541 for (BasicBlock &BB :
F)
4542 if (!AssumedLiveBlocks.count(&BB)) {
4543 A.deleteAfterManifest(BB);
4545 HasChanged = ChangeStatus::CHANGED;
4554 bool isEdgeDead(
const BasicBlock *From,
const BasicBlock *To)
const override {
4557 "Used AAIsDead of the wrong function");
4558 return isValidState() && !AssumedLiveEdges.count(std::make_pair(From, To));
4562 void trackStatistics()
const override {}
4565 bool isAssumedDead()
const override {
return false; }
4568 bool isKnownDead()
const override {
return false; }
4571 bool isAssumedDead(
const BasicBlock *BB)
const override {
4573 "BB must be in the same anchor scope function.");
4577 return !AssumedLiveBlocks.count(BB);
4581 bool isKnownDead(
const BasicBlock *BB)
const override {
4582 return getKnown() && isAssumedDead(BB);
4586 bool isAssumedDead(
const Instruction *
I)
const override {
4587 assert(
I->getParent()->getParent() == getAnchorScope() &&
4588 "Instruction must be in the same anchor scope function.");
4595 if (!AssumedLiveBlocks.count(
I->getParent()))
4601 if (KnownDeadEnds.count(PrevI) || ToBeExploredFrom.count(PrevI))
4609 bool isKnownDead(
const Instruction *
I)
const override {
4610 return getKnown() && isAssumedDead(
I);
4615 bool assumeLive(Attributor &
A,
const BasicBlock &BB) {
4616 if (!AssumedLiveBlocks.insert(&BB).second)
4623 for (
const Instruction &
I : BB)
4626 if (
F->hasLocalLinkage())
4627 A.markLiveInternalFunction(*
F);
4633 SmallSetVector<const Instruction *, 8> ToBeExploredFrom;
4636 SmallSetVector<const Instruction *, 8> KnownDeadEnds;
4639 DenseSet<std::pair<const BasicBlock *, const BasicBlock *>> AssumedLiveEdges;
4642 DenseSet<const BasicBlock *> AssumedLiveBlocks;
4646identifyAliveSuccessors(Attributor &
A,
const CallBase &CB,
4647 AbstractAttribute &AA,
4648 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4651 bool IsKnownNoReturn;
4654 return !IsKnownNoReturn;
4663identifyAliveSuccessors(Attributor &
A,
const InvokeInst &
II,
4664 AbstractAttribute &AA,
4665 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4666 bool UsedAssumedInformation =
4672 if (AAIsDeadFunction::mayCatchAsynchronousExceptions(*
II.getFunction())) {
4673 AliveSuccessors.
push_back(&
II.getUnwindDest()->front());
4677 bool IsKnownNoUnwind;
4680 UsedAssumedInformation |= !IsKnownNoUnwind;
4682 AliveSuccessors.
push_back(&
II.getUnwindDest()->front());
4685 return UsedAssumedInformation;
4689identifyAliveSuccessors(Attributor &,
const UncondBrInst &BI,
4690 AbstractAttribute &,
4691 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4697identifyAliveSuccessors(Attributor &
A,
const CondBrInst &BI,
4698 AbstractAttribute &AA,
4699 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4700 bool UsedAssumedInformation =
false;
4701 std::optional<Constant *>
C =
4702 A.getAssumedConstant(*BI.
getCondition(), AA, UsedAssumedInformation);
4712 UsedAssumedInformation =
false;
4714 return UsedAssumedInformation;
4718identifyAliveSuccessors(Attributor &
A,
const SwitchInst &SI,
4719 AbstractAttribute &AA,
4720 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4721 bool UsedAssumedInformation =
false;
4725 UsedAssumedInformation)) {
4727 for (
const BasicBlock *SuccBB :
successors(
SI.getParent()))
4732 if (Values.
empty() ||
4733 (Values.
size() == 1 &&
4736 return UsedAssumedInformation;
4739 Type &Ty = *
SI.getCondition()->getType();
4740 SmallPtrSet<ConstantInt *, 8>
Constants;
4741 auto CheckForConstantInt = [&](
Value *
V) {
4749 if (!
all_of(Values, [&](AA::ValueAndContext &VAC) {
4750 return CheckForConstantInt(VAC.
getValue());
4752 for (
const BasicBlock *SuccBB :
successors(
SI.getParent()))
4754 return UsedAssumedInformation;
4757 unsigned MatchedCases = 0;
4758 for (
const auto &CaseIt :
SI.cases()) {
4759 if (
Constants.count(CaseIt.getCaseValue())) {
4761 AliveSuccessors.
push_back(&CaseIt.getCaseSuccessor()->front());
4768 AliveSuccessors.
push_back(&
SI.getDefaultDest()->front());
4769 return UsedAssumedInformation;
4775 if (AssumedLiveBlocks.empty()) {
4776 if (isAssumedDeadInternalFunction(
A))
4780 ToBeExploredFrom.insert(&
F->getEntryBlock().front());
4781 assumeLive(
A,
F->getEntryBlock());
4785 LLVM_DEBUG(
dbgs() <<
"[AAIsDead] Live [" << AssumedLiveBlocks.size() <<
"/"
4786 << getAnchorScope()->
size() <<
"] BBs and "
4787 << ToBeExploredFrom.size() <<
" exploration points and "
4788 << KnownDeadEnds.size() <<
" known dead ends\n");
4793 ToBeExploredFrom.end());
4794 decltype(ToBeExploredFrom) NewToBeExploredFrom;
4797 while (!Worklist.
empty()) {
4804 I =
I->getNextNode();
4806 AliveSuccessors.
clear();
4808 bool UsedAssumedInformation =
false;
4809 switch (
I->getOpcode()) {
4813 "Expected non-terminators to be handled already!");
4814 for (
const BasicBlock *SuccBB :
successors(
I->getParent()))
4817 case Instruction::Call:
4819 *
this, AliveSuccessors);
4821 case Instruction::Invoke:
4823 *
this, AliveSuccessors);
4825 case Instruction::UncondBr:
4826 UsedAssumedInformation = identifyAliveSuccessors(
4829 case Instruction::CondBr:
4831 *
this, AliveSuccessors);
4833 case Instruction::Switch:
4835 *
this, AliveSuccessors);
4839 if (UsedAssumedInformation) {
4840 NewToBeExploredFrom.insert(
I);
4841 }
else if (AliveSuccessors.
empty() ||
4842 (
I->isTerminator() &&
4843 AliveSuccessors.
size() <
I->getNumSuccessors())) {
4844 if (KnownDeadEnds.insert(
I))
4849 << AliveSuccessors.
size() <<
" UsedAssumedInformation: "
4850 << UsedAssumedInformation <<
"\n");
4852 for (
const Instruction *AliveSuccessor : AliveSuccessors) {
4853 if (!
I->isTerminator()) {
4854 assert(AliveSuccessors.size() == 1 &&
4855 "Non-terminator expected to have a single successor!");
4859 auto Edge = std::make_pair(
I->getParent(), AliveSuccessor->getParent());
4860 if (AssumedLiveEdges.insert(
Edge).second)
4862 if (assumeLive(
A, *AliveSuccessor->getParent()))
4869 if (NewToBeExploredFrom.size() != ToBeExploredFrom.size() ||
4870 llvm::any_of(NewToBeExploredFrom, [&](
const Instruction *
I) {
4871 return !ToBeExploredFrom.count(I);
4874 ToBeExploredFrom = std::move(NewToBeExploredFrom);
4883 if (ToBeExploredFrom.empty() &&
4884 getAnchorScope()->
size() == AssumedLiveBlocks.size() &&
4885 llvm::all_of(KnownDeadEnds, [](
const Instruction *DeadEndI) {
4886 return DeadEndI->isTerminator() && DeadEndI->getNumSuccessors() == 0;
4888 return indicatePessimisticFixpoint();
4893struct AAIsDeadCallSite final : AAIsDeadFunction {
4894 AAIsDeadCallSite(
const IRPosition &IRP, Attributor &
A)
4895 : AAIsDeadFunction(IRP,
A) {}
4904 "supported for call sites yet!");
4909 return indicatePessimisticFixpoint();
4913 void trackStatistics()
const override {}
4920struct AADereferenceableImpl : AADereferenceable {
4921 AADereferenceableImpl(
const IRPosition &IRP, Attributor &
A)
4922 : AADereferenceable(IRP,
A) {}
4923 using StateType = DerefState;
4927 Value &
V = *getAssociatedValue().stripPointerCasts();
4929 A.getAttrs(getIRPosition(),
4930 {Attribute::Dereferenceable, Attribute::DereferenceableOrNull},
4933 takeKnownDerefBytesMaximum(Attr.getValueAsInt());
4936 bool IsKnownNonNull;
4938 A,
this, getIRPosition(), DepClassTy::OPTIONAL, IsKnownNonNull);
4940 bool CanBeNull, CanBeFreed;
4941 takeKnownDerefBytesMaximum(
V.getPointerDereferenceableBytes(
4942 A.getDataLayout(), CanBeNull, CanBeFreed));
4944 if (Instruction *CtxI = getCtxI())
4945 followUsesInMBEC(*
this,
A, getState(), *CtxI);
4950 StateType &getState()
override {
return *
this; }
4951 const StateType &getState()
const override {
return *
this; }
4955 void addAccessedBytesForUse(Attributor &
A,
const Use *U,
const Instruction *
I,
4956 DerefState &State) {
4957 const Value *UseV =
U->get();
4962 if (!Loc || Loc->Ptr != UseV || !Loc->Size.isPrecise() ||
I->isVolatile())
4967 Loc->Ptr,
Offset,
A.getDataLayout(),
true);
4968 if (
Base &&
Base == &getAssociatedValue())
4969 State.addAccessedBytes(
Offset, Loc->Size.getValue());
4973 bool followUseInMBEC(Attributor &
A,
const Use *U,
const Instruction *
I,
4974 AADereferenceable::StateType &State) {
4975 bool IsNonNull =
false;
4976 bool TrackUse =
false;
4977 int64_t DerefBytes = getKnownNonNullAndDerefBytesForUse(
4978 A, *
this, getAssociatedValue(), U,
I, IsNonNull, TrackUse);
4979 LLVM_DEBUG(
dbgs() <<
"[AADereferenceable] Deref bytes: " << DerefBytes
4980 <<
" for instruction " << *
I <<
"\n");
4982 addAccessedBytesForUse(
A, U,
I, State);
4983 State.takeKnownDerefBytesMaximum(DerefBytes);
4990 bool IsKnownNonNull;
4992 A,
this, getIRPosition(), DepClassTy::NONE, IsKnownNonNull);
4993 if (IsAssumedNonNull &&
4994 A.hasAttr(getIRPosition(), Attribute::DereferenceableOrNull)) {
4995 A.removeAttrs(getIRPosition(), {Attribute::DereferenceableOrNull});
4996 return ChangeStatus::CHANGED;
5001 void getDeducedAttributes(Attributor &
A, LLVMContext &Ctx,
5002 SmallVectorImpl<Attribute> &Attrs)
const override {
5004 bool IsKnownNonNull;
5006 A,
this, getIRPosition(), DepClassTy::NONE, IsKnownNonNull);
5007 if (IsAssumedNonNull)
5008 Attrs.emplace_back(Attribute::getWithDereferenceableBytes(
5009 Ctx, getAssumedDereferenceableBytes()));
5011 Attrs.emplace_back(Attribute::getWithDereferenceableOrNullBytes(
5012 Ctx, getAssumedDereferenceableBytes()));
5016 const std::string getAsStr(Attributor *
A)
const override {
5017 if (!getAssumedDereferenceableBytes())
5018 return "unknown-dereferenceable";
5019 bool IsKnownNonNull;
5020 bool IsAssumedNonNull =
false;
5023 *
A,
this, getIRPosition(), DepClassTy::NONE, IsKnownNonNull);
5024 return std::string(
"dereferenceable") +
5025 (IsAssumedNonNull ?
"" :
"_or_null") +
5026 (isAssumedGlobal() ?
"_globally" :
"") +
"<" +
5027 std::to_string(getKnownDereferenceableBytes()) +
"-" +
5028 std::to_string(getAssumedDereferenceableBytes()) +
">" +
5029 (!
A ?
" [non-null is unknown]" :
"");
5034struct AADereferenceableFloating : AADereferenceableImpl {
5035 AADereferenceableFloating(
const IRPosition &IRP, Attributor &
A)
5036 : AADereferenceableImpl(IRP,
A) {}
5041 bool UsedAssumedInformation =
false;
5043 if (!
A.getAssumedSimplifiedValues(getIRPosition(), *
this, Values,
5045 Values.
push_back({getAssociatedValue(), getCtxI()});
5048 Stripped = Values.
size() != 1 ||
5049 Values.
front().getValue() != &getAssociatedValue();
5052 const DataLayout &
DL =
A.getDataLayout();
5055 auto VisitValueCB = [&](
const Value &
V) ->
bool {
5057 DL.getIndexSizeInBits(
V.getType()->getPointerAddressSpace());
5058 APInt
Offset(IdxWidth, 0);
5063 const auto *AA =
A.getAAFor<AADereferenceable>(
5065 int64_t DerefBytes = 0;
5066 if (!AA || (!Stripped &&
this == AA)) {
5069 bool CanBeNull, CanBeFreed;
5071 Base->getPointerDereferenceableBytes(
DL, CanBeNull, CanBeFreed);
5072 T.GlobalState.indicatePessimisticFixpoint();
5075 DerefBytes =
DS.DerefBytesState.getAssumed();
5076 T.GlobalState &=
DS.GlobalState;
5082 int64_t OffsetSExt =
Offset.getSExtValue();
5086 T.takeAssumedDerefBytesMinimum(
5087 std::max(int64_t(0), DerefBytes - OffsetSExt));
5092 T.takeKnownDerefBytesMaximum(
5093 std::max(int64_t(0), DerefBytes - OffsetSExt));
5094 T.indicatePessimisticFixpoint();
5095 }
else if (OffsetSExt > 0) {
5101 T.indicatePessimisticFixpoint();
5105 return T.isValidState();
5108 for (
const auto &VAC : Values)
5109 if (!VisitValueCB(*VAC.
getValue()))
5110 return indicatePessimisticFixpoint();
5116 void trackStatistics()
const override {
5122struct AADereferenceableReturned final
5123 : AAReturnedFromReturnedValues<AADereferenceable, AADereferenceableImpl> {
5125 AAReturnedFromReturnedValues<AADereferenceable, AADereferenceableImpl>;
5126 AADereferenceableReturned(
const IRPosition &IRP, Attributor &
A)
5130 void trackStatistics()
const override {
5136struct AADereferenceableArgument final
5137 : AAArgumentFromCallSiteArguments<AADereferenceable,
5138 AADereferenceableImpl> {
5140 AAArgumentFromCallSiteArguments<AADereferenceable, AADereferenceableImpl>;
5141 AADereferenceableArgument(
const IRPosition &IRP, Attributor &
A)
5145 void trackStatistics()
const override {
5151struct AADereferenceableCallSiteArgument final : AADereferenceableFloating {
5152 AADereferenceableCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
5153 : AADereferenceableFloating(IRP,
A) {}
5156 void trackStatistics()
const override {
5162struct AADereferenceableCallSiteReturned final
5163 : AACalleeToCallSite<AADereferenceable, AADereferenceableImpl> {
5164 using Base = AACalleeToCallSite<AADereferenceable, AADereferenceableImpl>;
5165 AADereferenceableCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
5169 void trackStatistics()
const override {
5179static unsigned getKnownAlignForUse(Attributor &
A, AAAlign &QueryingAA,
5180 Value &AssociatedValue,
const Use *U,
5181 const Instruction *
I,
bool &TrackUse) {
5190 if (
GEP->hasAllConstantIndices())
5195 switch (
II->getIntrinsicID()) {
5196 case Intrinsic::ptrmask: {
5198 const auto *ConstVals =
A.getAAFor<AAPotentialConstantValues>(
5200 const auto *AlignAA =
A.getAAFor<AAAlign>(
5202 if (ConstVals && ConstVals->isValidState() && ConstVals->isAtFixpoint()) {
5203 unsigned ShiftValue = std::min(ConstVals->getAssumedMinTrailingZeros(),
5205 Align ConstAlign(UINT64_C(1) << ShiftValue);
5206 if (ConstAlign >= AlignAA->getKnownAlign())
5207 return Align(1).value();
5210 return AlignAA->getKnownAlign().
value();
5213 case Intrinsic::amdgcn_make_buffer_rsrc: {
5214 const auto *AlignAA =
A.getAAFor<AAAlign>(
5217 return AlignAA->getKnownAlign().
value();
5235 MA = MaybeAlign(AlignAA->getKnownAlign());
5238 const DataLayout &
DL =
A.getDataLayout();
5239 const Value *UseV =
U->get();
5241 if (
SI->getPointerOperand() == UseV)
5242 MA =
SI->getAlign();
5244 if (LI->getPointerOperand() == UseV)
5245 MA = LI->getAlign();
5247 if (AI->getPointerOperand() == UseV)
5248 MA = AI->getAlign();
5250 if (AI->getPointerOperand() == UseV)
5251 MA = AI->getAlign();
5257 unsigned Alignment = MA->value();
5261 if (
Base == &AssociatedValue) {
5266 uint32_t
gcd = std::gcd(uint32_t(
abs((int32_t)
Offset)), Alignment);
5274struct AAAlignImpl : AAAlign {
5275 AAAlignImpl(
const IRPosition &IRP, Attributor &
A) : AAAlign(IRP,
A) {}
5280 A.getAttrs(getIRPosition(), {Attribute::Alignment},
Attrs);
5282 takeKnownMaximum(Attr.getValueAsInt());
5284 Value &
V = *getAssociatedValue().stripPointerCasts();
5285 takeKnownMaximum(
V.getPointerAlignment(
A.getDataLayout()).value());
5287 if (Instruction *CtxI = getCtxI())
5288 followUsesInMBEC(*
this,
A, getState(), *CtxI);
5296 Value &AssociatedValue = getAssociatedValue();
5298 return ChangeStatus::UNCHANGED;
5300 for (
const Use &U : AssociatedValue.
uses()) {
5302 if (
SI->getPointerOperand() == &AssociatedValue)
5303 if (
SI->getAlign() < getAssumedAlign()) {
5305 "Number of times alignment added to a store");
5306 SI->setAlignment(getAssumedAlign());
5307 InstrChanged = ChangeStatus::CHANGED;
5310 if (LI->getPointerOperand() == &AssociatedValue)
5311 if (LI->getAlign() < getAssumedAlign()) {
5312 LI->setAlignment(getAssumedAlign());
5314 "Number of times alignment added to a load");
5315 InstrChanged = ChangeStatus::CHANGED;
5318 if (RMW->getPointerOperand() == &AssociatedValue) {
5319 if (RMW->getAlign() < getAssumedAlign()) {
5321 "Number of times alignment added to atomicrmw");
5323 RMW->setAlignment(getAssumedAlign());
5324 InstrChanged = ChangeStatus::CHANGED;
5328 if (CAS->getPointerOperand() == &AssociatedValue) {
5329 if (CAS->getAlign() < getAssumedAlign()) {
5331 "Number of times alignment added to cmpxchg");
5332 CAS->setAlignment(getAssumedAlign());
5333 InstrChanged = ChangeStatus::CHANGED;
5341 Align InheritAlign =
5342 getAssociatedValue().getPointerAlignment(
A.getDataLayout());
5343 if (InheritAlign >= getAssumedAlign())
5344 return InstrChanged;
5345 return Changed | InstrChanged;
5353 void getDeducedAttributes(Attributor &
A, LLVMContext &Ctx,
5354 SmallVectorImpl<Attribute> &Attrs)
const override {
5355 if (getAssumedAlign() > 1)
5357 Attribute::getWithAlignment(Ctx,
Align(getAssumedAlign())));
5361 bool followUseInMBEC(Attributor &
A,
const Use *U,
const Instruction *
I,
5362 AAAlign::StateType &State) {
5363 bool TrackUse =
false;
5365 unsigned int KnownAlign =
5366 getKnownAlignForUse(
A, *
this, getAssociatedValue(), U,
I, TrackUse);
5367 State.takeKnownMaximum(KnownAlign);
5373 const std::string getAsStr(Attributor *
A)
const override {
5374 return "align<" + std::to_string(getKnownAlign().value()) +
"-" +
5375 std::to_string(getAssumedAlign().value()) +
">";
5380struct AAAlignFloating : AAAlignImpl {
5381 AAAlignFloating(
const IRPosition &IRP, Attributor &
A) : AAAlignImpl(IRP,
A) {}
5385 const DataLayout &
DL =
A.getDataLayout();
5388 bool UsedAssumedInformation =
false;
5390 if (!
A.getAssumedSimplifiedValues(getIRPosition(), *
this, Values,
5392 Values.
push_back({getAssociatedValue(), getCtxI()});
5395 Stripped = Values.
size() != 1 ||
5396 Values.
front().getValue() != &getAssociatedValue();
5400 auto VisitValueCB = [&](
Value &
V) ->
bool {
5404 DepClassTy::REQUIRED);
5405 if (!AA || (!Stripped &&
this == AA)) {
5407 unsigned Alignment = 1;
5420 Alignment =
V.getPointerAlignment(
DL).value();
5423 T.takeKnownMaximum(Alignment);
5424 T.indicatePessimisticFixpoint();
5427 const AAAlign::StateType &
DS = AA->
getState();
5430 return T.isValidState();
5433 for (
const auto &VAC : Values) {
5434 if (!VisitValueCB(*VAC.
getValue()))
5435 return indicatePessimisticFixpoint();
5448struct AAAlignReturned final
5449 : AAReturnedFromReturnedValues<AAAlign, AAAlignImpl> {
5450 using Base = AAReturnedFromReturnedValues<AAAlign, AAAlignImpl>;
5451 AAAlignReturned(
const IRPosition &IRP, Attributor &
A) :
Base(IRP,
A) {}
5458struct AAAlignArgument final
5459 : AAArgumentFromCallSiteArguments<AAAlign, AAAlignImpl> {
5460 using Base = AAArgumentFromCallSiteArguments<AAAlign, AAAlignImpl>;
5461 AAAlignArgument(
const IRPosition &IRP, Attributor &
A) :
Base(IRP,
A) {}
5468 if (
A.getInfoCache().isInvolvedInMustTailCall(*getAssociatedArgument()))
5469 return ChangeStatus::UNCHANGED;
5470 return Base::manifest(
A);
5477struct AAAlignCallSiteArgument final : AAAlignFloating {
5478 AAAlignCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
5479 : AAAlignFloating(IRP,
A) {}
5486 if (Argument *Arg = getAssociatedArgument())
5487 if (
A.getInfoCache().isInvolvedInMustTailCall(*Arg))
5488 return ChangeStatus::UNCHANGED;
5490 Align InheritAlign =
5491 getAssociatedValue().getPointerAlignment(
A.getDataLayout());
5492 if (InheritAlign >= getAssumedAlign())
5493 Changed = ChangeStatus::UNCHANGED;
5500 if (Argument *Arg = getAssociatedArgument()) {
5503 const auto *ArgAlignAA =
A.getAAFor<AAAlign>(
5506 takeKnownMaximum(ArgAlignAA->getKnownAlign().value());
5516struct AAAlignCallSiteReturned final
5517 : AACalleeToCallSite<AAAlign, AAAlignImpl> {
5518 using Base = AACalleeToCallSite<AAAlign, AAAlignImpl>;
5519 AAAlignCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
5525 switch (
II->getIntrinsicID()) {
5526 case Intrinsic::ptrmask: {
5530 const auto *ConstVals =
A.getAAFor<AAPotentialConstantValues>(
5532 if (ConstVals && ConstVals->isValidState()) {
5533 unsigned ShiftValue =
5534 std::min(ConstVals->getAssumedMinTrailingZeros(),
5535 Value::MaxAlignmentExponent);
5536 Alignment =
Align(UINT64_C(1) << ShiftValue);
5540 const auto *AlignAA =
5542 DepClassTy::REQUIRED);
5544 Alignment = std::max(AlignAA->getAssumedAlign(), Alignment);
5551 std::min(this->getAssumedAlign(), Alignment).value());
5557 case Intrinsic::amdgcn_make_buffer_rsrc: {
5558 const auto *AlignAA =
5560 DepClassTy::REQUIRED);
5563 this->getState(), AlignAA->getAssumedAlign().
value());
5570 return Base::updateImpl(
A);
5579struct AANoReturnImpl :
public AANoReturn {
5580 AANoReturnImpl(
const IRPosition &IRP, Attributor &
A) : AANoReturn(IRP,
A) {}
5586 A,
nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));
5591 const std::string getAsStr(Attributor *
A)
const override {
5592 return getAssumed() ?
"noreturn" :
"may-return";
5597 auto CheckForNoReturn = [](
Instruction &) {
return false; };
5598 bool UsedAssumedInformation =
false;
5599 if (!
A.checkForAllInstructions(CheckForNoReturn, *
this,
5600 {(unsigned)Instruction::Ret},
5601 UsedAssumedInformation))
5602 return indicatePessimisticFixpoint();
5603 return ChangeStatus::UNCHANGED;
5607struct AANoReturnFunction final : AANoReturnImpl {
5608 AANoReturnFunction(
const IRPosition &IRP, Attributor &
A)
5609 : AANoReturnImpl(IRP,
A) {}
5616struct AANoReturnCallSite final
5617 : AACalleeToCallSite<AANoReturn, AANoReturnImpl> {
5618 AANoReturnCallSite(
const IRPosition &IRP, Attributor &
A)
5619 : AACalleeToCallSite<AANoReturn, AANoReturnImpl>(IRP,
A) {}
5630struct AAInstanceInfoImpl :
public AAInstanceInfo {
5631 AAInstanceInfoImpl(
const IRPosition &IRP, Attributor &
A)
5632 : AAInstanceInfo(IRP,
A) {}
5636 Value &
V = getAssociatedValue();
5638 if (
C->isThreadDependent())
5639 indicatePessimisticFixpoint();
5641 indicateOptimisticFixpoint();
5647 indicateOptimisticFixpoint();
5652 A.getInfoCache().getAnalysisResultForFunction<CycleAnalysis>(
5655 indicatePessimisticFixpoint();
5665 Value &
V = getAssociatedValue();
5668 Scope =
I->getFunction();
5671 if (!
Scope->hasLocalLinkage())
5675 return indicateOptimisticFixpoint();
5677 bool IsKnownNoRecurse;
5683 auto UsePred = [&](
const Use &
U,
bool &Follow) {
5698 if (!Callee || !
Callee->hasLocalLinkage())
5702 const auto *ArgInstanceInfoAA =
A.getAAFor<AAInstanceInfo>(
5704 DepClassTy::OPTIONAL);
5705 if (!ArgInstanceInfoAA ||
5706 !ArgInstanceInfoAA->isAssumedUniqueForAnalysis())
5711 A, *CB, *Scope, *
this,
nullptr,
5712 [Scope](
const Function &Fn) {
return &Fn !=
Scope; }))
5719 auto EquivalentUseCB = [&](
const Use &OldU,
const Use &NewU) {
5721 auto *Ptr =
SI->getPointerOperand()->stripPointerCasts();
5729 if (!
A.checkForAllUses(UsePred, *
this, V,
true,
5730 DepClassTy::OPTIONAL,
5731 true, EquivalentUseCB))
5732 return indicatePessimisticFixpoint();
5738 const std::string getAsStr(Attributor *
A)
const override {
5739 return isAssumedUniqueForAnalysis() ?
"<unique [fAa]>" :
"<unknown>";
5743 void trackStatistics()
const override {}
5747struct AAInstanceInfoFloating : AAInstanceInfoImpl {
5748 AAInstanceInfoFloating(
const IRPosition &IRP, Attributor &
A)
5749 : AAInstanceInfoImpl(IRP,
A) {}
5753struct AAInstanceInfoArgument final : AAInstanceInfoFloating {
5754 AAInstanceInfoArgument(
const IRPosition &IRP, Attributor &
A)
5755 : AAInstanceInfoFloating(IRP,
A) {}
5759struct AAInstanceInfoCallSiteArgument final : AAInstanceInfoImpl {
5760 AAInstanceInfoCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
5761 : AAInstanceInfoImpl(IRP,
A) {}
5769 Argument *Arg = getAssociatedArgument();
5771 return indicatePessimisticFixpoint();
5774 A.getAAFor<AAInstanceInfo>(*
this, ArgPos, DepClassTy::REQUIRED);
5776 return indicatePessimisticFixpoint();
5782struct AAInstanceInfoReturned final : AAInstanceInfoImpl {
5783 AAInstanceInfoReturned(
const IRPosition &IRP, Attributor &
A)
5784 : AAInstanceInfoImpl(IRP,
A) {
5800struct AAInstanceInfoCallSiteReturned final : AAInstanceInfoFloating {
5801 AAInstanceInfoCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
5802 : AAInstanceInfoFloating(IRP,
A) {}
5809 bool IgnoreSubsumingPositions) {
5810 assert(ImpliedAttributeKind == Attribute::Captures &&
5811 "Unexpected attribute kind");
5821 V.getType()->getPointerAddressSpace() == 0)) {
5826 A.getAttrs(IRP, {Attribute::Captures}, Attrs,
5836 {Attribute::Captures, Attribute::ByVal}, Attrs,
5874 bool NoThrow =
F.doesNotThrow();
5875 bool IsVoidReturn =
F.getReturnType()->isVoidTy();
5876 if (
ReadOnly && NoThrow && IsVoidReturn) {
5889 if (NoThrow && IsVoidReturn)
5894 if (!NoThrow || ArgNo < 0 ||
5895 !
F.getAttributes().hasAttrSomewhere(Attribute::Returned))
5898 for (
unsigned U = 0, E =
F.arg_size(); U < E; ++U)
5899 if (
F.hasParamAttribute(U, Attribute::Returned)) {
5900 if (U ==
unsigned(ArgNo))
5927 void getDeducedAttributes(Attributor &
A, LLVMContext &Ctx,
5928 SmallVectorImpl<Attribute> &Attrs)
const override {
5929 if (!isAssumedNoCaptureMaybeReturned())
5932 if (isArgumentPosition()) {
5933 if (isAssumedNoCapture())
5934 Attrs.emplace_back(Attribute::get(Ctx, Attribute::Captures));
5936 Attrs.emplace_back(Attribute::get(Ctx,
"no-capture-maybe-returned"));
5941 const std::string getAsStr(Attributor *
A)
const override {
5942 if (isKnownNoCapture())
5943 return "known not-captured";
5944 if (isAssumedNoCapture())
5945 return "assumed not-captured";
5946 if (isKnownNoCaptureMaybeReturned())
5947 return "known not-captured-maybe-returned";
5948 if (isAssumedNoCaptureMaybeReturned())
5949 return "assumed not-captured-maybe-returned";
5950 return "assumed-captured";
5955 bool checkUse(Attributor &
A, AANoCapture::StateType &State,
const Use &U,
5958 LLVM_DEBUG(
dbgs() <<
"[AANoCapture] Check use: " << *
U.get() <<
" in "
5964 return isCapturedIn(State,
true,
true,
5971 return isCapturedIn(State,
true,
true,
5977 return isCapturedIn(State,
false,
false,
5979 return isCapturedIn(State,
true,
true,
5987 return isCapturedIn(State,
true,
true,
5994 bool IsKnownNoCapture;
5995 const AANoCapture *ArgNoCaptureAA =
nullptr;
5997 A,
this, CSArgPos, DepClassTy::REQUIRED, IsKnownNoCapture,
false,
5999 if (IsAssumedNoCapture)
6000 return isCapturedIn(State,
false,
false,
6004 return isCapturedIn(State,
false,
false,
6009 return isCapturedIn(State,
true,
true,
6016 static bool isCapturedIn(AANoCapture::StateType &State,
bool CapturedInMem,
6017 bool CapturedInInt,
bool CapturedInRet) {
6018 LLVM_DEBUG(
dbgs() <<
" - captures [Mem " << CapturedInMem <<
"|Int "
6019 << CapturedInInt <<
"|Ret " << CapturedInRet <<
"]\n");
6031 const IRPosition &IRP = getIRPosition();
6035 return indicatePessimisticFixpoint();
6042 return indicatePessimisticFixpoint();
6050 T.addKnownBits(NOT_CAPTURED_IN_MEM);
6052 addKnownBits(NOT_CAPTURED_IN_MEM);
6059 auto CheckReturnedArgs = [&](
bool &UsedAssumedInformation) {
6063 UsedAssumedInformation))
6065 bool SeenConstant =
false;
6066 for (
const AA::ValueAndContext &VAC : Values) {
6070 SeenConstant =
true;
6072 VAC.
getValue() == getAssociatedArgument())
6078 bool IsKnownNoUnwind;
6081 bool IsVoidTy =
F->getReturnType()->isVoidTy();
6082 bool UsedAssumedInformation =
false;
6083 if (IsVoidTy || CheckReturnedArgs(UsedAssumedInformation)) {
6084 T.addKnownBits(NOT_CAPTURED_IN_RET);
6085 if (
T.isKnown(NOT_CAPTURED_IN_MEM))
6087 if (IsKnownNoUnwind && (IsVoidTy || !UsedAssumedInformation)) {
6088 addKnownBits(NOT_CAPTURED_IN_RET);
6089 if (isKnown(NOT_CAPTURED_IN_MEM))
6090 return indicateOptimisticFixpoint();
6095 auto UseCheck = [&](
const Use &
U,
bool &Follow) ->
bool {
6104 return checkUse(
A,
T, U, Follow);
6107 if (!
A.checkForAllUses(UseCheck, *
this, *V))
6108 return indicatePessimisticFixpoint();
6111 auto Assumed = S.getAssumed();
6112 S.intersectAssumedBits(
T.getAssumed());
6113 if (!isAssumedNoCaptureMaybeReturned())
6114 return indicatePessimisticFixpoint();
6120struct AANoCaptureArgument final : AANoCaptureImpl {
6121 AANoCaptureArgument(
const IRPosition &IRP, Attributor &
A)
6122 : AANoCaptureImpl(IRP,
A) {}
6129struct AANoCaptureCallSiteArgument final : AANoCaptureImpl {
6130 AANoCaptureCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
6131 : AANoCaptureImpl(IRP,
A) {}
6139 Argument *Arg = getAssociatedArgument();
6141 return indicatePessimisticFixpoint();
6143 bool IsKnownNoCapture;
6144 const AANoCapture *ArgAA =
nullptr;
6146 A,
this, ArgPos, DepClassTy::REQUIRED, IsKnownNoCapture,
false,
6148 return ChangeStatus::UNCHANGED;
6150 return indicatePessimisticFixpoint();
6155 void trackStatistics()
const override {
6161struct AANoCaptureFloating final : AANoCaptureImpl {
6162 AANoCaptureFloating(
const IRPosition &IRP, Attributor &
A)
6163 : AANoCaptureImpl(IRP,
A) {}
6166 void trackStatistics()
const override {
6172struct AANoCaptureReturned final : AANoCaptureImpl {
6173 AANoCaptureReturned(
const IRPosition &IRP, Attributor &
A)
6174 : AANoCaptureImpl(IRP,
A) {
6189 void trackStatistics()
const override {}
6193struct AANoCaptureCallSiteReturned final : AANoCaptureImpl {
6194 AANoCaptureCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
6195 : AANoCaptureImpl(IRP,
A) {}
6201 determineFunctionCaptureCapabilities(getIRPosition(), *
F, *
this);
6205 void trackStatistics()
const override {
6222 dbgs() <<
"[ValueSimplify] is assumed to be "
6225 dbgs() <<
"[ValueSimplify] is assumed to be <none>\n";
6237 if (getAssociatedValue().
getType()->isVoidTy())
6238 indicatePessimisticFixpoint();
6239 if (
A.hasSimplificationCallback(getIRPosition()))
6240 indicatePessimisticFixpoint();
6244 const std::string getAsStr(Attributor *
A)
const override {
6246 dbgs() <<
"SAV: " << (bool)SimplifiedAssociatedValue <<
" ";
6247 if (SimplifiedAssociatedValue && *SimplifiedAssociatedValue)
6248 dbgs() <<
"SAV: " << **SimplifiedAssociatedValue <<
" ";
6250 return isValidState() ? (isAtFixpoint() ?
"simplified" :
"maybe-simple")
6255 void trackStatistics()
const override {}
6258 std::optional<Value *>
6259 getAssumedSimplifiedValue(Attributor &
A)
const override {
6260 return SimplifiedAssociatedValue;
6267 static Value *ensureType(Attributor &
A,
Value &V,
Type &Ty, Instruction *CtxI,
6271 if (CtxI &&
V.getType()->canLosslesslyBitCastTo(&Ty))
6273 : BitCastInst::CreatePointerBitCastOrAddrSpaceCast(
6282 static Value *reproduceInst(Attributor &
A,
6283 const AbstractAttribute &QueryingAA,
6284 Instruction &
I,
Type &Ty, Instruction *CtxI,
6286 assert(CtxI &&
"Cannot reproduce an instruction without context!");
6287 if (
Check && (
I.mayReadFromMemory() ||
6292 Value *NewOp = reproduceValue(
A, QueryingAA, *
Op, Ty, CtxI,
Check, VMap);
6294 assert(
Check &&
"Manifest of new value unexpectedly failed!");
6316 static Value *reproduceValue(Attributor &
A,
6317 const AbstractAttribute &QueryingAA,
Value &V,
6318 Type &Ty, Instruction *CtxI,
bool Check,
6320 if (
const auto &NewV = VMap.
lookup(&V))
6322 bool UsedAssumedInformation =
false;
6323 std::optional<Value *> SimpleV =
A.getAssumedSimplified(
6325 if (!SimpleV.has_value())
6329 EffectiveV = *SimpleV;
6334 return ensureType(
A, *EffectiveV, Ty, CtxI,
Check);
6336 if (
Value *NewV = reproduceInst(
A, QueryingAA, *
I, Ty, CtxI,
Check, VMap))
6337 return ensureType(
A, *NewV, Ty, CtxI,
Check);
6343 Value *manifestReplacementValue(Attributor &
A, Instruction *CtxI)
const {
6344 Value *NewV = SimplifiedAssociatedValue
6345 ? *SimplifiedAssociatedValue
6347 if (NewV && NewV != &getAssociatedValue()) {
6351 if (reproduceValue(
A, *
this, *NewV, *getAssociatedType(), CtxI,
6353 return reproduceValue(
A, *
this, *NewV, *getAssociatedType(), CtxI,
6361 bool checkAndUpdate(Attributor &
A,
const AbstractAttribute &QueryingAA,
6362 const IRPosition &IRP,
bool Simplify =
true) {
6363 bool UsedAssumedInformation =
false;
6366 QueryingValueSimplified =
A.getAssumedSimplified(
6368 return unionAssumed(QueryingValueSimplified);
6372 template <
typename AAType>
bool askSimplifiedValueFor(Attributor &
A) {
6373 if (!getAssociatedValue().
getType()->isIntegerTy())
6378 A.getAAFor<AAType>(*
this, getIRPosition(), DepClassTy::NONE);
6382 std::optional<Constant *> COpt = AA->getAssumedConstant(
A);
6385 SimplifiedAssociatedValue = std::nullopt;
6386 A.recordDependence(*AA, *
this, DepClassTy::OPTIONAL);
6389 if (
auto *
C = *COpt) {
6390 SimplifiedAssociatedValue =
C;
6391 A.recordDependence(*AA, *
this, DepClassTy::OPTIONAL);
6397 bool askSimplifiedValueForOtherAAs(Attributor &
A) {
6398 if (askSimplifiedValueFor<AAValueConstantRange>(
A))
6400 if (askSimplifiedValueFor<AAPotentialConstantValues>(
A))
6408 for (
auto &U : getAssociatedValue().uses()) {
6413 IP =
PHI->getIncomingBlock(U)->getTerminator();
6414 if (
auto *NewV = manifestReplacementValue(
A, IP)) {
6416 <<
" -> " << *NewV <<
" :: " << *
this <<
"\n");
6417 if (
A.changeUseAfterManifest(U, *NewV))
6418 Changed = ChangeStatus::CHANGED;
6422 return Changed | AAValueSimplify::manifest(
A);
6427 SimplifiedAssociatedValue = &getAssociatedValue();
6428 return AAValueSimplify::indicatePessimisticFixpoint();
6432struct AAValueSimplifyArgument final : AAValueSimplifyImpl {
6433 AAValueSimplifyArgument(
const IRPosition &IRP, Attributor &
A)
6434 : AAValueSimplifyImpl(IRP,
A) {}
6437 AAValueSimplifyImpl::initialize(
A);
6438 if (
A.hasAttr(getIRPosition(),
6439 {Attribute::InAlloca, Attribute::Preallocated,
6440 Attribute::StructRet, Attribute::Nest, Attribute::ByVal},
6442 indicatePessimisticFixpoint();
6449 Argument *Arg = getAssociatedArgument();
6455 return indicatePessimisticFixpoint();
6458 auto Before = SimplifiedAssociatedValue;
6460 auto PredForCallSite = [&](AbstractCallSite ACS) {
6461 const IRPosition &ACSArgPos =
6472 bool UsedAssumedInformation =
false;
6473 std::optional<Constant *> SimpleArgOp =
6474 A.getAssumedConstant(ACSArgPos, *
this, UsedAssumedInformation);
6481 return unionAssumed(*SimpleArgOp);
6486 bool UsedAssumedInformation =
false;
6487 if (hasCallBaseContext() &&
6488 getCallBaseContext()->getCalledOperand() == Arg->
getParent())
6490 AbstractCallSite(&getCallBaseContext()->getCalledOperandUse()));
6492 Success =
A.checkForAllCallSites(PredForCallSite, *
this,
true,
6493 UsedAssumedInformation);
6496 if (!askSimplifiedValueForOtherAAs(
A))
6497 return indicatePessimisticFixpoint();
6500 return Before == SimplifiedAssociatedValue ? ChangeStatus::UNCHANGED
6501 : ChangeStatus ::CHANGED;
6505 void trackStatistics()
const override {
6510struct AAValueSimplifyReturned : AAValueSimplifyImpl {
6511 AAValueSimplifyReturned(
const IRPosition &IRP, Attributor &
A)
6512 : AAValueSimplifyImpl(IRP,
A) {}
6515 std::optional<Value *>
6516 getAssumedSimplifiedValue(Attributor &
A)
const override {
6517 if (!isValidState())
6519 return SimplifiedAssociatedValue;
6524 auto Before = SimplifiedAssociatedValue;
6528 return checkAndUpdate(
6533 bool UsedAssumedInformation =
false;
6534 if (!
A.checkForAllInstructions(ReturnInstCB, *
this, {Instruction::Ret},
6535 UsedAssumedInformation))
6536 if (!askSimplifiedValueForOtherAAs(
A))
6537 return indicatePessimisticFixpoint();
6540 return Before == SimplifiedAssociatedValue ? ChangeStatus::UNCHANGED
6541 : ChangeStatus ::CHANGED;
6547 return ChangeStatus::UNCHANGED;
6551 void trackStatistics()
const override {
6556struct AAValueSimplifyFloating : AAValueSimplifyImpl {
6557 AAValueSimplifyFloating(
const IRPosition &IRP, Attributor &
A)
6558 : AAValueSimplifyImpl(IRP,
A) {}
6562 AAValueSimplifyImpl::initialize(
A);
6563 Value &
V = getAnchorValue();
6567 indicatePessimisticFixpoint();
6572 auto Before = SimplifiedAssociatedValue;
6573 if (!askSimplifiedValueForOtherAAs(
A))
6574 return indicatePessimisticFixpoint();
6577 return Before == SimplifiedAssociatedValue ? ChangeStatus::UNCHANGED
6578 : ChangeStatus ::CHANGED;
6582 void trackStatistics()
const override {
6587struct AAValueSimplifyFunction : AAValueSimplifyImpl {
6588 AAValueSimplifyFunction(
const IRPosition &IRP, Attributor &
A)
6589 : AAValueSimplifyImpl(IRP,
A) {}
6593 SimplifiedAssociatedValue =
nullptr;
6594 indicateOptimisticFixpoint();
6599 "AAValueSimplify(Function|CallSite)::updateImpl will not be called");
6602 void trackStatistics()
const override {
6607struct AAValueSimplifyCallSite : AAValueSimplifyFunction {
6608 AAValueSimplifyCallSite(
const IRPosition &IRP, Attributor &
A)
6609 : AAValueSimplifyFunction(IRP,
A) {}
6611 void trackStatistics()
const override {
6616struct AAValueSimplifyCallSiteReturned : AAValueSimplifyImpl {
6617 AAValueSimplifyCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
6618 : AAValueSimplifyImpl(IRP,
A) {}
6621 AAValueSimplifyImpl::initialize(
A);
6622 Function *Fn = getAssociatedFunction();
6623 assert(Fn &&
"Did expect an associted function");
6624 for (Argument &Arg : Fn->
args()) {
6629 checkAndUpdate(
A, *
this, IRP))
6630 indicateOptimisticFixpoint();
6632 indicatePessimisticFixpoint();
6640 return indicatePessimisticFixpoint();
6643 void trackStatistics()
const override {
6648struct AAValueSimplifyCallSiteArgument : AAValueSimplifyFloating {
6649 AAValueSimplifyCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
6650 : AAValueSimplifyFloating(IRP,
A) {}
6656 auto *FloatAA =
A.lookupAAFor<AAValueSimplify>(
6658 if (FloatAA && FloatAA->getState().isValidState())
6661 if (
auto *NewV = manifestReplacementValue(
A, getCtxI())) {
6663 ->getArgOperandUse(getCallSiteArgNo());
6664 if (
A.changeUseAfterManifest(U, *NewV))
6665 Changed = ChangeStatus::CHANGED;
6668 return Changed | AAValueSimplify::manifest(
A);
6671 void trackStatistics()
const override {
6679struct AAHeapToStackFunction final :
public AAHeapToStack {
6681 static bool isGlobalizedLocal(
const CallBase &CB) {
6683 return A.
isValid() &&
A.getValueAsString() ==
"__kmpc_alloc_shared";
6686 struct AllocationInfo {
6691 bool IsGlobalizedLocal =
false;
6698 } Status = STACK_DUE_TO_USE;
6702 bool HasPotentiallyFreeingUnknownUses =
false;
6706 bool MoveAllocaIntoEntry =
true;
6709 SmallSetVector<CallBase *, 1> PotentialFreeCalls{};
6712 struct DeallocationInfo {
6720 bool MightFreeUnknownObjects =
false;
6723 SmallSetVector<CallBase *, 1> PotentialAllocationCalls{};
6726 AAHeapToStackFunction(
const IRPosition &IRP, Attributor &
A)
6727 : AAHeapToStack(IRP,
A) {}
6729 ~AAHeapToStackFunction()
override {
6732 for (
auto &It : AllocationInfos)
6733 It.second->~AllocationInfo();
6734 for (
auto &It : DeallocationInfos)
6735 It.second->~DeallocationInfo();
6739 AAHeapToStack::initialize(
A);
6742 const auto *TLI =
A.getInfoCache().getTargetLibraryInfoForFunction(*
F);
6749 DeallocationInfos[CB] =
new (
A.Allocator) DeallocationInfo{CB, FreedOp};
6756 auto *I8Ty = Type::getInt8Ty(CB->
getParent()->getContext());
6758 AllocationInfo *AI =
new (
A.Allocator) AllocationInfo{CB};
6759 AllocationInfos[CB] = AI;
6760 AI->IsGlobalizedLocal = isGlobalizedLocal(*CB);
6766 bool UsedAssumedInformation =
false;
6767 bool Success =
A.checkForAllCallLikeInstructions(
6768 AllocationIdentifierCB, *
this, UsedAssumedInformation,
6772 assert(
Success &&
"Did not expect the call base visit callback to fail!");
6775 [](
const IRPosition &,
const AbstractAttribute *,
6776 bool &) -> std::optional<Value *> {
return nullptr; };
6777 for (
const auto &It : AllocationInfos)
6780 for (
const auto &It : DeallocationInfos)
6785 const std::string getAsStr(Attributor *
A)
const override {
6786 unsigned NumH2SMallocs = 0, NumInvalidMallocs = 0;
6787 for (
const auto &It : AllocationInfos) {
6788 if (It.second->Status == AllocationInfo::INVALID)
6789 ++NumInvalidMallocs;
6793 return "[H2S] Mallocs Good/Bad: " + std::to_string(NumH2SMallocs) +
"/" +
6794 std::to_string(NumInvalidMallocs);
6798 void trackStatistics()
const override {
6800 MallocCalls, Function,
6801 "Number of malloc/calloc/aligned_alloc calls converted to allocas");
6802 for (
const auto &It : AllocationInfos)
6803 if (It.second->Status != AllocationInfo::INVALID)
6807 bool isAssumedHeapToStack(
const CallBase &CB)
const override {
6809 if (AllocationInfo *AI =
6810 AllocationInfos.lookup(
const_cast<CallBase *
>(&CB)))
6811 return AI->Status != AllocationInfo::INVALID;
6815 bool isAssumedHeapToStackRemovedFree(CallBase &CB)
const override {
6816 if (!isValidState())
6819 for (
const auto &It : AllocationInfos) {
6820 AllocationInfo &AI = *It.second;
6821 if (AI.Status == AllocationInfo::INVALID)
6824 if (AI.PotentialFreeCalls.count(&CB))
6832 assert(getState().isValidState() &&
6833 "Attempted to manifest an invalid state!");
6837 const auto *TLI =
A.getInfoCache().getTargetLibraryInfoForFunction(*
F);
6839 for (
auto &It : AllocationInfos) {
6840 AllocationInfo &AI = *It.second;
6841 if (AI.Status == AllocationInfo::INVALID)
6844 for (CallBase *FreeCall : AI.PotentialFreeCalls) {
6845 LLVM_DEBUG(
dbgs() <<
"H2S: Removing free call: " << *FreeCall <<
"\n");
6846 A.deleteAfterManifest(*FreeCall);
6847 HasChanged = ChangeStatus::CHANGED;
6850 LLVM_DEBUG(
dbgs() <<
"H2S: Removing malloc-like call: " << *AI.CB
6853 auto Remark = [&](OptimizationRemark
OR) {
6854 if (AI.IsGlobalizedLocal)
6855 return OR <<
"Moving globalized variable to the stack.";
6856 return OR <<
"Moving memory allocation from the heap to the stack.";
6858 if (AI.IsGlobalizedLocal)
6859 A.emitRemark<OptimizationRemark>(AI.CB,
"OMP110",
Remark);
6861 A.emitRemark<OptimizationRemark>(AI.CB,
"HeapToStack",
Remark);
6863 const DataLayout &
DL =
A.getInfoCache().getDL();
6865 std::optional<APInt> SizeAPI =
getSize(
A, *
this, AI);
6867 Size = ConstantInt::get(AI.CB->getContext(), *SizeAPI);
6869 LLVMContext &Ctx = AI.CB->getContext();
6870 ObjectSizeOpts Opts;
6871 ObjectSizeOffsetEvaluator Eval(
DL, TLI, Ctx, Opts);
6872 SizeOffsetValue SizeOffsetPair = Eval.compute(AI.CB);
6879 ?
F->getEntryBlock().begin()
6880 : AI.CB->getIterator();
6883 if (MaybeAlign RetAlign = AI.CB->getRetAlign())
6884 Alignment = std::max(Alignment, *RetAlign);
6886 std::optional<APInt> AlignmentAPI = getAPInt(
A, *
this, *Align);
6887 assert(AlignmentAPI && AlignmentAPI->getZExtValue() > 0 &&
6888 "Expected an alignment during manifest!");
6890 std::max(Alignment,
assumeAligned(AlignmentAPI->getZExtValue()));
6894 unsigned AS =
DL.getAllocaAddrSpace();
6896 new AllocaInst(Type::getInt8Ty(
F->getContext()), AS,
Size, Alignment,
6897 AI.CB->getName() +
".h2s", IP);
6899 if (Alloca->
getType() != AI.CB->getType())
6900 Alloca = BitCastInst::CreatePointerBitCastOrAddrSpaceCast(
6901 Alloca, AI.CB->getType(),
"malloc_cast", AI.CB->getIterator());
6903 auto *I8Ty = Type::getInt8Ty(
F->getContext());
6906 "Must be able to materialize initial memory state of allocation");
6911 auto *NBB =
II->getNormalDest();
6913 A.deleteAfterManifest(*AI.CB);
6915 A.deleteAfterManifest(*AI.CB);
6924 Builder.CreateMemSet(Alloca, InitVal,
Size, std::nullopt);
6926 HasChanged = ChangeStatus::CHANGED;
6932 std::optional<APInt> getAPInt(Attributor &
A,
const AbstractAttribute &AA,
6934 bool UsedAssumedInformation =
false;
6935 std::optional<Constant *> SimpleV =
6936 A.getAssumedConstant(V, AA, UsedAssumedInformation);
6938 return APInt(64, 0);
6940 return CI->getValue();
6941 return std::nullopt;
6944 std::optional<APInt>
getSize(Attributor &
A,
const AbstractAttribute &AA,
6945 AllocationInfo &AI) {
6946 auto Mapper = [&](
const Value *
V) ->
const Value * {
6947 bool UsedAssumedInformation =
false;
6948 if (std::optional<Constant *> SimpleV =
6949 A.getAssumedConstant(*V, AA, UsedAssumedInformation))
6956 const auto *TLI =
A.getInfoCache().getTargetLibraryInfoForFunction(*
F);
6962 MapVector<CallBase *, AllocationInfo *> AllocationInfos;
6966 MapVector<CallBase *, DeallocationInfo *> DeallocationInfos;
6971ChangeStatus AAHeapToStackFunction::updateImpl(Attributor &
A) {
6974 const auto *TLI =
A.getInfoCache().getTargetLibraryInfoForFunction(*
F);
6976 const auto *LivenessAA =
6979 MustBeExecutedContextExplorer *Explorer =
6980 A.getInfoCache().getMustBeExecutedContextExplorer();
6982 bool StackIsAccessibleByOtherThreads =
6983 A.getInfoCache().stackIsAccessibleByOtherThreads();
6986 A.getInfoCache().getAnalysisResultForFunction<LoopAnalysis>(*F);
6987 std::optional<bool> MayContainIrreducibleControl;
6989 if (&
F->getEntryBlock() == &BB)
6991 if (!MayContainIrreducibleControl.has_value())
6993 if (*MayContainIrreducibleControl)
7002 bool HasUpdatedFrees =
false;
7004 auto UpdateFrees = [&]() {
7005 HasUpdatedFrees =
true;
7007 for (
auto &It : DeallocationInfos) {
7008 DeallocationInfo &DI = *It.second;
7011 if (DI.MightFreeUnknownObjects)
7015 bool UsedAssumedInformation =
false;
7016 if (
A.isAssumedDead(*DI.CB,
this, LivenessAA, UsedAssumedInformation,
7023 LLVM_DEBUG(
dbgs() <<
"[H2S] Unknown underlying object for free!\n");
7024 DI.MightFreeUnknownObjects =
true;
7037 DI.MightFreeUnknownObjects =
true;
7041 AllocationInfo *AI = AllocationInfos.lookup(ObjCB);
7043 LLVM_DEBUG(
dbgs() <<
"[H2S] Free of a non-allocation object: " << *Obj
7045 DI.MightFreeUnknownObjects =
true;
7049 DI.PotentialAllocationCalls.insert(ObjCB);
7053 auto FreeCheck = [&](AllocationInfo &AI) {
7057 if (!StackIsAccessibleByOtherThreads) {
7062 dbgs() <<
"[H2S] found an escaping use, stack is not accessible by "
7063 "other threads and function is not nosync:\n");
7067 if (!HasUpdatedFrees)
7071 if (AI.PotentialFreeCalls.size() != 1) {
7073 << AI.PotentialFreeCalls.size() <<
"\n");
7076 CallBase *UniqueFree = *AI.PotentialFreeCalls.begin();
7077 DeallocationInfo *DI = DeallocationInfos.lookup(UniqueFree);
7080 dbgs() <<
"[H2S] unique free call was not known as deallocation call "
7081 << *UniqueFree <<
"\n");
7084 if (DI->MightFreeUnknownObjects) {
7086 dbgs() <<
"[H2S] unique free call might free unknown allocations\n");
7089 if (DI->PotentialAllocationCalls.empty())
7091 if (DI->PotentialAllocationCalls.size() > 1) {
7093 << DI->PotentialAllocationCalls.size()
7094 <<
" different allocations\n");
7097 if (*DI->PotentialAllocationCalls.begin() != AI.CB) {
7100 <<
"[H2S] unique free call not known to free this allocation but "
7101 << **DI->PotentialAllocationCalls.begin() <<
"\n");
7106 if (!AI.IsGlobalizedLocal) {
7108 if (!Explorer || !Explorer->findInContextOf(UniqueFree, CtxI)) {
7109 LLVM_DEBUG(
dbgs() <<
"[H2S] unique free call might not be executed "
7110 "with the allocation "
7111 << *UniqueFree <<
"\n");
7118 auto UsesCheck = [&](AllocationInfo &AI) {
7119 bool ValidUsesOnly =
true;
7121 auto Pred = [&](
const Use &
U,
bool &Follow) ->
bool {
7126 if (
SI->getValueOperand() ==
U.get()) {
7128 <<
"[H2S] escaping store to memory: " << *UserI <<
"\n");
7129 ValidUsesOnly =
false;
7138 if (DeallocationInfos.count(CB)) {
7139 AI.PotentialFreeCalls.insert(CB);
7146 bool IsKnownNoCapture;
7155 if (!IsAssumedNoCapture ||
7156 (!AI.IsGlobalizedLocal && !IsAssumedNoFree)) {
7157 AI.HasPotentiallyFreeingUnknownUses |= !IsAssumedNoFree;
7160 auto Remark = [&](OptimizationRemarkMissed ORM) {
7162 <<
"Could not move globalized variable to the stack. "
7163 "Variable is potentially captured in call. Mark "
7164 "parameter as `__attribute__((noescape))` to override.";
7167 if (ValidUsesOnly && AI.IsGlobalizedLocal)
7168 A.emitRemark<OptimizationRemarkMissed>(CB,
"OMP113",
Remark);
7171 ValidUsesOnly =
false;
7184 ValidUsesOnly =
false;
7187 if (!
A.checkForAllUses(Pred, *
this, *AI.CB,
false,
7189 [&](
const Use &OldU,
const Use &NewU) {
7190 auto *SI = dyn_cast<StoreInst>(OldU.getUser());
7191 return !SI || StackIsAccessibleByOtherThreads ||
7192 AA::isAssumedThreadLocalObject(
7193 A, *SI->getPointerOperand(), *this);
7196 return ValidUsesOnly;
7201 for (
auto &It : AllocationInfos) {
7202 AllocationInfo &AI = *It.second;
7203 if (AI.Status == AllocationInfo::INVALID)
7207 std::optional<APInt> APAlign = getAPInt(
A, *
this, *Align);
7211 LLVM_DEBUG(
dbgs() <<
"[H2S] Unknown allocation alignment: " << *AI.CB
7213 AI.Status = AllocationInfo::INVALID;
7218 !APAlign->isPowerOf2()) {
7219 LLVM_DEBUG(
dbgs() <<
"[H2S] Invalid allocation alignment: " << APAlign
7221 AI.Status = AllocationInfo::INVALID;
7232 dbgs() <<
"[H2S] Unknown allocation size: " << *AI.CB <<
"\n";
7234 dbgs() <<
"[H2S] Allocation size too large: " << *AI.CB <<
" vs. "
7238 AI.Status = AllocationInfo::INVALID;
7244 switch (AI.Status) {
7245 case AllocationInfo::STACK_DUE_TO_USE:
7248 AI.Status = AllocationInfo::STACK_DUE_TO_FREE;
7250 case AllocationInfo::STACK_DUE_TO_FREE:
7253 AI.Status = AllocationInfo::INVALID;
7256 case AllocationInfo::INVALID:
7263 bool IsGlobalizedLocal = AI.IsGlobalizedLocal;
7264 if (AI.MoveAllocaIntoEntry &&
7265 (!
Size.has_value() ||
7266 (!IsGlobalizedLocal && IsInLoop(*AI.CB->getParent()))))
7267 AI.MoveAllocaIntoEntry =
false;
7276struct AAPrivatizablePtrImpl :
public AAPrivatizablePtr {
7277 AAPrivatizablePtrImpl(
const IRPosition &IRP, Attributor &
A)
7278 : AAPrivatizablePtr(IRP,
A), PrivatizableType(std::nullopt) {}
7281 AAPrivatizablePtr::indicatePessimisticFixpoint();
7282 PrivatizableType =
nullptr;
7283 return ChangeStatus::CHANGED;
7289 virtual std::optional<Type *> identifyPrivatizableType(Attributor &
A) = 0;
7293 std::optional<Type *> combineTypes(std::optional<Type *> T0,
7294 std::optional<Type *>
T1) {
7304 std::optional<Type *> getPrivatizableType()
const override {
7305 return PrivatizableType;
7308 const std::string getAsStr(Attributor *
A)
const override {
7309 return isAssumedPrivatizablePtr() ?
"[priv]" :
"[no-priv]";
7313 std::optional<Type *> PrivatizableType;
7318struct AAPrivatizablePtrArgument final :
public AAPrivatizablePtrImpl {
7319 AAPrivatizablePtrArgument(
const IRPosition &IRP, Attributor &
A)
7320 : AAPrivatizablePtrImpl(IRP,
A) {}
7323 std::optional<Type *> identifyPrivatizableType(Attributor &
A)
override {
7326 bool UsedAssumedInformation =
false;
7328 A.getAttrs(getIRPosition(), {Attribute::ByVal},
Attrs,
7330 if (!
Attrs.empty() &&
7331 A.checkForAllCallSites([](AbstractCallSite ACS) { return true; }, *
this,
7332 true, UsedAssumedInformation))
7333 return Attrs[0].getValueAsType();
7335 std::optional<Type *> Ty;
7336 unsigned ArgNo = getIRPosition().getCallSiteArgNo();
7344 auto CallSiteCheck = [&](AbstractCallSite ACS) {
7353 A.getAAFor<AAPrivatizablePtr>(*
this, ACSArgPos, DepClassTy::REQUIRED);
7356 std::optional<Type *> CSTy = PrivCSArgAA->getPrivatizableType();
7359 dbgs() <<
"[AAPrivatizablePtr] ACSPos: " << ACSArgPos <<
", CSTy: ";
7363 dbgs() <<
"<nullptr>";
7368 Ty = combineTypes(Ty, CSTy);
7371 dbgs() <<
" : New Type: ";
7373 (*Ty)->print(
dbgs());
7375 dbgs() <<
"<nullptr>";
7384 if (!
A.checkForAllCallSites(CallSiteCheck, *
this,
true,
7385 UsedAssumedInformation))
7392 PrivatizableType = identifyPrivatizableType(
A);
7393 if (!PrivatizableType)
7394 return ChangeStatus::UNCHANGED;
7395 if (!*PrivatizableType)
7396 return indicatePessimisticFixpoint();
7401 DepClassTy::OPTIONAL);
7404 if (!
A.hasAttr(getIRPosition(), Attribute::ByVal) &&
7407 return indicatePessimisticFixpoint();
7413 identifyReplacementTypes(*PrivatizableType, ReplacementTypes);
7417 Function &Fn = *getIRPosition().getAnchorScope();
7419 A.getInfoCache().getAnalysisResultForFunction<TargetIRAnalysis>(Fn);
7421 LLVM_DEBUG(
dbgs() <<
"[AAPrivatizablePtr] Missing TTI for function "
7423 return indicatePessimisticFixpoint();
7426 auto CallSiteCheck = [&](AbstractCallSite ACS) {
7433 bool UsedAssumedInformation =
false;
7434 if (!
A.checkForAllCallSites(CallSiteCheck, *
this,
true,
7435 UsedAssumedInformation)) {
7437 dbgs() <<
"[AAPrivatizablePtr] ABI incompatibility detected for "
7439 return indicatePessimisticFixpoint();
7443 Argument *Arg = getAssociatedArgument();
7444 if (!
A.isValidFunctionSignatureRewrite(*Arg, ReplacementTypes)) {
7446 return indicatePessimisticFixpoint();
7453 auto IsCompatiblePrivArgOfCallback = [&](CallBase &CB) {
7456 for (
const Use *U : CallbackUses) {
7457 AbstractCallSite CBACS(U);
7458 assert(CBACS && CBACS.isCallbackCall());
7459 for (Argument &CBArg : CBACS.getCalledFunction()->args()) {
7460 int CBArgNo = CBACS.getCallArgOperandNo(CBArg);
7464 <<
"[AAPrivatizablePtr] Argument " << *Arg
7465 <<
"check if can be privatized in the context of its parent ("
7467 <<
")\n[AAPrivatizablePtr] because it is an argument in a "
7469 << CBArgNo <<
"@" << CBACS.getCalledFunction()->getName()
7470 <<
")\n[AAPrivatizablePtr] " << CBArg <<
" : "
7471 << CBACS.getCallArgOperand(CBArg) <<
" vs "
7473 <<
"[AAPrivatizablePtr] " << CBArg <<
" : "
7474 << CBACS.getCallArgOperandNo(CBArg) <<
" vs " << ArgNo <<
"\n";
7477 if (CBArgNo !=
int(ArgNo))
7479 const auto *CBArgPrivAA =
A.getAAFor<AAPrivatizablePtr>(
7481 if (CBArgPrivAA && CBArgPrivAA->isValidState()) {
7482 auto CBArgPrivTy = CBArgPrivAA->getPrivatizableType();
7485 if (*CBArgPrivTy == PrivatizableType)
7490 dbgs() <<
"[AAPrivatizablePtr] Argument " << *Arg
7491 <<
" cannot be privatized in the context of its parent ("
7493 <<
")\n[AAPrivatizablePtr] because it is an argument in a "
7495 << CBArgNo <<
"@" << CBACS.getCalledFunction()->getName()
7496 <<
").\n[AAPrivatizablePtr] for which the argument "
7497 "privatization is not compatible.\n";
7507 auto IsCompatiblePrivArgOfDirectCS = [&](AbstractCallSite ACS) {
7511 "Expected a direct call operand for callback call operand");
7516 dbgs() <<
"[AAPrivatizablePtr] Argument " << *Arg
7517 <<
" check if be privatized in the context of its parent ("
7519 <<
")\n[AAPrivatizablePtr] because it is an argument in a "
7521 << DCArgNo <<
"@" << DCCallee->
getName() <<
").\n";
7524 if (
unsigned(DCArgNo) < DCCallee->
arg_size()) {
7525 const auto *DCArgPrivAA =
A.getAAFor<AAPrivatizablePtr>(
7527 DepClassTy::REQUIRED);
7528 if (DCArgPrivAA && DCArgPrivAA->isValidState()) {
7529 auto DCArgPrivTy = DCArgPrivAA->getPrivatizableType();
7532 if (*DCArgPrivTy == PrivatizableType)
7538 dbgs() <<
"[AAPrivatizablePtr] Argument " << *Arg
7539 <<
" cannot be privatized in the context of its parent ("
7541 <<
")\n[AAPrivatizablePtr] because it is an argument in a "
7544 <<
").\n[AAPrivatizablePtr] for which the argument "
7545 "privatization is not compatible.\n";
7553 auto IsCompatiblePrivArgOfOtherCallSite = [&](AbstractCallSite ACS) {
7557 return IsCompatiblePrivArgOfDirectCS(ACS);
7561 if (!
A.checkForAllCallSites(IsCompatiblePrivArgOfOtherCallSite, *
this,
true,
7562 UsedAssumedInformation))
7563 return indicatePessimisticFixpoint();
7565 return ChangeStatus::UNCHANGED;
7571 identifyReplacementTypes(
Type *PrivType,
7572 SmallVectorImpl<Type *> &ReplacementTypes) {
7575 assert(PrivType &&
"Expected privatizable type!");
7579 for (
unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++)
7580 ReplacementTypes.
push_back(PrivStructType->getElementType(u));
7582 ReplacementTypes.
append(PrivArrayType->getNumElements(),
7583 PrivArrayType->getElementType());
7592 static void createInitialization(
Type *PrivType,
Value &
Base, Function &
F,
7594 assert(PrivType &&
"Expected privatizable type!");
7597 const DataLayout &
DL =
F.getDataLayout();
7601 const StructLayout *PrivStructLayout =
DL.getStructLayout(PrivStructType);
7602 for (
unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++) {
7605 new StoreInst(
F.getArg(ArgNo + u), Ptr, IP);
7608 Type *PointeeTy = PrivArrayType->getElementType();
7609 uint64_t PointeeTySize =
DL.getTypeStoreSize(PointeeTy);
7610 for (
unsigned u = 0, e = PrivArrayType->getNumElements(); u < e; u++) {
7612 new StoreInst(
F.getArg(ArgNo + u), Ptr, IP);
7615 new StoreInst(
F.getArg(ArgNo), &
Base, IP);
7621 void createReplacementValues(Align Alignment,
Type *PrivType,
7623 SmallVectorImpl<Value *> &ReplacementValues) {
7625 assert(PrivType &&
"Expected privatizable type!");
7633 const StructLayout *PrivStructLayout =
DL.getStructLayout(PrivStructType);
7634 for (
unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++) {
7635 Type *PointeeTy = PrivStructType->getElementType(u);
7638 LoadInst *
L =
new LoadInst(PointeeTy, Ptr,
"", IP->
getIterator());
7639 L->setAlignment(Alignment);
7643 Type *PointeeTy = PrivArrayType->getElementType();
7644 uint64_t PointeeTySize =
DL.getTypeStoreSize(PointeeTy);
7645 for (
unsigned u = 0, e = PrivArrayType->getNumElements(); u < e; u++) {
7647 LoadInst *
L =
new LoadInst(PointeeTy, Ptr,
"", IP->
getIterator());
7648 L->setAlignment(Alignment);
7653 L->setAlignment(Alignment);
7660 if (!PrivatizableType)
7661 return ChangeStatus::UNCHANGED;
7662 assert(*PrivatizableType &&
"Expected privatizable type!");
7668 bool UsedAssumedInformation =
false;
7669 if (!
A.checkForAllInstructions(
7670 [&](Instruction &
I) {
7671 CallInst &CI = cast<CallInst>(I);
7672 if (CI.isTailCall())
7673 TailCalls.push_back(&CI);
7676 *
this, {Instruction::Call}, UsedAssumedInformation))
7677 return ChangeStatus::UNCHANGED;
7679 Argument *Arg = getAssociatedArgument();
7682 const auto *AlignAA =
7689 [=](
const Attributor::ArgumentReplacementInfo &ARI,
7691 BasicBlock &EntryBB = ReplacementFn.getEntryBlock();
7693 const DataLayout &
DL = IP->getDataLayout();
7694 unsigned AS =
DL.getAllocaAddrSpace();
7695 Instruction *AI =
new AllocaInst(*PrivatizableType, AS,
7696 Arg->
getName() +
".priv", IP);
7697 createInitialization(*PrivatizableType, *AI, ReplacementFn,
7698 ArgIt->getArgNo(), IP);
7701 AI = BitCastInst::CreatePointerBitCastOrAddrSpaceCast(
7705 for (CallInst *CI : TailCalls)
7706 CI->setTailCall(
false);
7713 [=](
const Attributor::ArgumentReplacementInfo &ARI,
7714 AbstractCallSite ACS, SmallVectorImpl<Value *> &NewArgOperands) {
7717 createReplacementValues(
7718 AlignAA ? AlignAA->getAssumedAlign() :
Align(0),
7719 *PrivatizableType, ACS,
7727 identifyReplacementTypes(*PrivatizableType, ReplacementTypes);
7730 if (
A.registerFunctionSignatureRewrite(*Arg, ReplacementTypes,
7731 std::move(FnRepairCB),
7732 std::move(ACSRepairCB)))
7733 return ChangeStatus::CHANGED;
7734 return ChangeStatus::UNCHANGED;
7738 void trackStatistics()
const override {
7743struct AAPrivatizablePtrFloating :
public AAPrivatizablePtrImpl {
7744 AAPrivatizablePtrFloating(
const IRPosition &IRP, Attributor &
A)
7745 : AAPrivatizablePtrImpl(IRP,
A) {}
7750 indicatePessimisticFixpoint();
7755 "updateImpl will not be called");
7759 std::optional<Type *> identifyPrivatizableType(Attributor &
A)
override {
7762 LLVM_DEBUG(
dbgs() <<
"[AAPrivatizablePtr] No underlying object found!\n");
7769 return AI->getAllocatedType();
7771 auto *PrivArgAA =
A.getAAFor<AAPrivatizablePtr>(
7773 if (PrivArgAA && PrivArgAA->isAssumedPrivatizablePtr())
7774 return PrivArgAA->getPrivatizableType();
7777 LLVM_DEBUG(
dbgs() <<
"[AAPrivatizablePtr] Underlying object neither valid "
7778 "alloca nor privatizable argument: "
7784 void trackStatistics()
const override {
7789struct AAPrivatizablePtrCallSiteArgument final
7790 :
public AAPrivatizablePtrFloating {
7791 AAPrivatizablePtrCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
7792 : AAPrivatizablePtrFloating(IRP,
A) {}
7796 if (
A.hasAttr(getIRPosition(), Attribute::ByVal))
7797 indicateOptimisticFixpoint();
7802 PrivatizableType = identifyPrivatizableType(
A);
7803 if (!PrivatizableType)
7804 return ChangeStatus::UNCHANGED;
7805 if (!*PrivatizableType)
7806 return indicatePessimisticFixpoint();
7808 const IRPosition &IRP = getIRPosition();
7809 bool IsKnownNoCapture;
7811 A,
this, IRP, DepClassTy::REQUIRED, IsKnownNoCapture);
7812 if (!IsAssumedNoCapture) {
7813 LLVM_DEBUG(
dbgs() <<
"[AAPrivatizablePtr] pointer might be captured!\n");
7814 return indicatePessimisticFixpoint();
7817 bool IsKnownNoAlias;
7819 A,
this, IRP, DepClassTy::REQUIRED, IsKnownNoAlias)) {
7820 LLVM_DEBUG(
dbgs() <<
"[AAPrivatizablePtr] pointer might alias!\n");
7821 return indicatePessimisticFixpoint();
7826 LLVM_DEBUG(
dbgs() <<
"[AAPrivatizablePtr] pointer is written!\n");
7827 return indicatePessimisticFixpoint();
7830 return ChangeStatus::UNCHANGED;
7834 void trackStatistics()
const override {
7839struct AAPrivatizablePtrCallSiteReturned final
7840 :
public AAPrivatizablePtrFloating {
7841 AAPrivatizablePtrCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
7842 : AAPrivatizablePtrFloating(IRP,
A) {}
7847 indicatePessimisticFixpoint();
7851 void trackStatistics()
const override {
7856struct AAPrivatizablePtrReturned final :
public AAPrivatizablePtrFloating {
7857 AAPrivatizablePtrReturned(
const IRPosition &IRP, Attributor &
A)
7858 : AAPrivatizablePtrFloating(IRP,
A) {}
7863 indicatePessimisticFixpoint();
7867 void trackStatistics()
const override {
7877struct AAMemoryBehaviorImpl :
public AAMemoryBehavior {
7878 AAMemoryBehaviorImpl(
const IRPosition &IRP, Attributor &
A)
7879 : AAMemoryBehavior(IRP,
A) {}
7883 intersectAssumedBits(BEST_STATE);
7884 getKnownStateFromValue(
A, getIRPosition(), getState());
7885 AAMemoryBehavior::initialize(
A);
7889 static void getKnownStateFromValue(Attributor &
A,
const IRPosition &IRP,
7890 BitIntegerState &State,
7891 bool IgnoreSubsumingPositions =
false) {
7893 A.getAttrs(IRP, AttrKinds, Attrs, IgnoreSubsumingPositions);
7895 switch (Attr.getKindAsEnum()) {
7896 case Attribute::ReadNone:
7899 case Attribute::ReadOnly:
7902 case Attribute::WriteOnly:
7911 if (!
I->mayReadFromMemory())
7913 if (!
I->mayWriteToMemory())
7919 void getDeducedAttributes(Attributor &
A, LLVMContext &Ctx,
7920 SmallVectorImpl<Attribute> &Attrs)
const override {
7923 Attrs.push_back(Attribute::get(Ctx, Attribute::ReadNone));
7925 Attrs.push_back(Attribute::get(Ctx, Attribute::ReadOnly));
7926 else if (isAssumedWriteOnly())
7927 Attrs.push_back(Attribute::get(Ctx, Attribute::WriteOnly));
7933 const IRPosition &IRP = getIRPosition();
7935 if (
A.hasAttr(IRP, Attribute::ReadNone,
7937 return ChangeStatus::UNCHANGED;
7946 return ChangeStatus::UNCHANGED;
7949 A.removeAttrs(IRP, AttrKinds);
7952 A.removeAttrs(IRP, Attribute::Writable);
7959 const std::string getAsStr(Attributor *
A)
const override {
7964 if (isAssumedWriteOnly())
7966 return "may-read/write";
7970 static const Attribute::AttrKind AttrKinds[3];
7974 Attribute::ReadNone, Attribute::ReadOnly, Attribute::WriteOnly};
7977struct AAMemoryBehaviorFloating : AAMemoryBehaviorImpl {
7978 AAMemoryBehaviorFloating(
const IRPosition &IRP, Attributor &
A)
7979 : AAMemoryBehaviorImpl(IRP,
A) {}
7985 void trackStatistics()
const override {
7990 else if (isAssumedWriteOnly())
7997 bool followUsersOfUseIn(Attributor &
A,
const Use &U,
7998 const Instruction *UserI);
8001 void analyzeUseIn(Attributor &
A,
const Use &U,
const Instruction *UserI);
8005struct AAMemoryBehaviorArgument : AAMemoryBehaviorFloating {
8006 AAMemoryBehaviorArgument(
const IRPosition &IRP, Attributor &
A)
8007 : AAMemoryBehaviorFloating(IRP,
A) {}
8011 intersectAssumedBits(BEST_STATE);
8012 const IRPosition &IRP = getIRPosition();
8016 bool HasByVal =
A.hasAttr(IRP, {Attribute::ByVal},
8018 getKnownStateFromValue(
A, IRP, getState(),
8025 return ChangeStatus::UNCHANGED;
8029 if (
A.hasAttr(getIRPosition(),
8030 {Attribute::InAlloca, Attribute::Preallocated})) {
8031 removeKnownBits(NO_WRITES);
8032 removeAssumedBits(NO_WRITES);
8034 A.removeAttrs(getIRPosition(), AttrKinds);
8035 return AAMemoryBehaviorFloating::manifest(
A);
8039 void trackStatistics()
const override {
8044 else if (isAssumedWriteOnly())
8049struct AAMemoryBehaviorCallSiteArgument final : AAMemoryBehaviorArgument {
8050 AAMemoryBehaviorCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
8051 : AAMemoryBehaviorArgument(IRP,
A) {}
8057 Argument *Arg = getAssociatedArgument();
8059 indicatePessimisticFixpoint();
8063 addKnownBits(NO_WRITES);
8064 removeKnownBits(NO_READS);
8065 removeAssumedBits(NO_READS);
8067 AAMemoryBehaviorArgument::initialize(
A);
8068 if (getAssociatedFunction()->isDeclaration())
8069 indicatePessimisticFixpoint();
8078 Argument *Arg = getAssociatedArgument();
8081 A.getAAFor<AAMemoryBehavior>(*
this, ArgPos, DepClassTy::REQUIRED);
8083 return indicatePessimisticFixpoint();
8088 void trackStatistics()
const override {
8093 else if (isAssumedWriteOnly())
8099struct AAMemoryBehaviorCallSiteReturned final : AAMemoryBehaviorFloating {
8100 AAMemoryBehaviorCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
8101 : AAMemoryBehaviorFloating(IRP,
A) {}
8105 AAMemoryBehaviorImpl::initialize(
A);
8110 return ChangeStatus::UNCHANGED;
8114 void trackStatistics()
const override {}
8118struct AAMemoryBehaviorFunction final :
public AAMemoryBehaviorImpl {
8119 AAMemoryBehaviorFunction(
const IRPosition &IRP, Attributor &
A)
8120 : AAMemoryBehaviorImpl(IRP,
A) {}
8136 else if (isAssumedWriteOnly())
8139 A.removeAttrs(getIRPosition(), AttrKinds);
8142 for (Argument &Arg :
F.args())
8144 return A.manifestAttrs(getIRPosition(),
8145 Attribute::getWithMemoryEffects(
F.getContext(), ME));
8149 void trackStatistics()
const override {
8154 else if (isAssumedWriteOnly())
8160struct AAMemoryBehaviorCallSite final
8161 : AACalleeToCallSite<AAMemoryBehavior, AAMemoryBehaviorImpl> {
8162 AAMemoryBehaviorCallSite(
const IRPosition &IRP, Attributor &
A)
8163 : AACalleeToCallSite<AAMemoryBehavior, AAMemoryBehaviorImpl>(IRP,
A) {}
8174 else if (isAssumedWriteOnly())
8177 A.removeAttrs(getIRPosition(), AttrKinds);
8180 for (Use &U : CB.
args())
8182 Attribute::Writable);
8183 return A.manifestAttrs(
8184 getIRPosition(), Attribute::getWithMemoryEffects(CB.
getContext(), ME));
8188 void trackStatistics()
const override {
8193 else if (isAssumedWriteOnly())
8198ChangeStatus AAMemoryBehaviorFunction::updateImpl(Attributor &
A) {
8201 auto AssumedState = getAssumed();
8208 const auto *MemBehaviorAA =
A.getAAFor<AAMemoryBehavior>(
8210 if (MemBehaviorAA) {
8211 intersectAssumedBits(MemBehaviorAA->
getAssumed());
8212 return !isAtFixpoint();
8217 if (
I.mayReadFromMemory())
8218 removeAssumedBits(NO_READS);
8219 if (
I.mayWriteToMemory())
8220 removeAssumedBits(NO_WRITES);
8221 return !isAtFixpoint();
8224 bool UsedAssumedInformation =
false;
8225 if (!
A.checkForAllReadWriteInstructions(CheckRWInst, *
this,
8226 UsedAssumedInformation))
8227 return indicatePessimisticFixpoint();
8233ChangeStatus AAMemoryBehaviorFloating::updateImpl(Attributor &
A) {
8235 const IRPosition &IRP = getIRPosition();
8246 const auto *FnMemAA =
8249 FnMemAssumedState = FnMemAA->getAssumed();
8250 S.addKnownBits(FnMemAA->getKnown());
8251 if ((S.getAssumed() & FnMemAA->getAssumed()) == S.getAssumed())
8257 auto AssumedState = S.getAssumed();
8263 bool IsKnownNoCapture;
8264 const AANoCapture *ArgNoCaptureAA =
nullptr;
8269 if (!IsAssumedNoCapture &&
8271 S.intersectAssumedBits(FnMemAssumedState);
8277 auto UsePred = [&](
const Use &
U,
bool &Follow) ->
bool {
8279 LLVM_DEBUG(
dbgs() <<
"[AAMemoryBehavior] Use: " << *U <<
" in " << *UserI
8287 Follow = followUsersOfUseIn(
A, U, UserI);
8291 analyzeUseIn(
A, U, UserI);
8293 return !isAtFixpoint();
8296 if (!
A.checkForAllUses(UsePred, *
this, getAssociatedValue()))
8297 return indicatePessimisticFixpoint();
8303bool AAMemoryBehaviorFloating::followUsersOfUseIn(Attributor &
A,
const Use &U,
8304 const Instruction *UserI) {
8322 if (
U.get()->getType()->isPointerTy()) {
8324 bool IsKnownNoCapture;
8333void AAMemoryBehaviorFloating::analyzeUseIn(Attributor &
A,
const Use &U,
8334 const Instruction *UserI) {
8341 case Instruction::Load:
8343 removeAssumedBits(NO_READS);
8346 case Instruction::Store:
8351 removeAssumedBits(NO_WRITES);
8353 indicatePessimisticFixpoint();
8356 case Instruction::Call:
8357 case Instruction::CallBr:
8358 case Instruction::Invoke: {
8365 indicatePessimisticFixpoint();
8372 removeAssumedBits(NO_READS);
8379 if (
U.get()->getType()->isPointerTy())
8383 const auto *MemBehaviorAA =
8389 intersectAssumedBits(MemBehaviorAA->
getAssumed());
8397 removeAssumedBits(NO_READS);
8399 removeAssumedBits(NO_WRITES);
8411 return "all memory";
8414 std::string S =
"memory:";
8420 S +=
"internal global,";
8422 S +=
"external global,";
8426 S +=
"inaccessible,";
8440 AccessKind2Accesses.fill(
nullptr);
8443 ~AAMemoryLocationImpl()
override {
8446 for (AccessSet *AS : AccessKind2Accesses)
8453 intersectAssumedBits(BEST_STATE);
8454 getKnownStateFromValue(
A, getIRPosition(), getState());
8455 AAMemoryLocation::initialize(
A);
8459 static void getKnownStateFromValue(Attributor &
A,
const IRPosition &IRP,
8460 BitIntegerState &State,
8461 bool IgnoreSubsumingPositions =
false) {
8470 bool UseArgMemOnly =
true;
8472 if (AnchorFn &&
A.isRunOn(*AnchorFn))
8476 A.getAttrs(IRP, {Attribute::Memory},
Attrs, IgnoreSubsumingPositions);
8485 State.
addKnownBits(inverseLocation(NO_INACCESSIBLE_MEM,
true,
true));
8490 State.
addKnownBits(inverseLocation(NO_ARGUMENT_MEM,
true,
true));
8494 A.manifestAttrs(IRP,
8495 Attribute::getWithMemoryEffects(
8504 NO_INACCESSIBLE_MEM | NO_ARGUMENT_MEM,
true,
true));
8508 A.manifestAttrs(IRP,
8509 Attribute::getWithMemoryEffects(
8519 void getDeducedAttributes(Attributor &
A, LLVMContext &Ctx,
8520 SmallVectorImpl<Attribute> &Attrs)
const override {
8527 else if (isAssumedInaccessibleMemOnly())
8528 Attrs.push_back(Attribute::getWithMemoryEffects(
8530 else if (isAssumedArgMemOnly())
8533 else if (isAssumedInaccessibleOrArgMemOnly())
8534 Attrs.push_back(Attribute::getWithMemoryEffects(
8544 const IRPosition &IRP = getIRPosition();
8548 if (DeducedAttrs.
size() != 1)
8549 return ChangeStatus::UNCHANGED;
8552 return A.manifestAttrs(IRP, Attribute::getWithMemoryEffects(
8557 bool checkForAllAccessesToMemoryKind(
8559 MemoryLocationsKind)>
8561 MemoryLocationsKind RequestedMLK)
const override {
8562 if (!isValidState())
8565 MemoryLocationsKind AssumedMLK = getAssumedNotAccessedLocation();
8566 if (AssumedMLK == NO_LOCATIONS)
8570 for (MemoryLocationsKind CurMLK = 1; CurMLK < NO_LOCATIONS;
8571 CurMLK *= 2, ++Idx) {
8572 if (CurMLK & RequestedMLK)
8575 if (
const AccessSet *
Accesses = AccessKind2Accesses[Idx])
8576 for (
const AccessInfo &AI : *
Accesses)
8577 if (!Pred(AI.I, AI.Ptr, AI.Kind, CurMLK))
8590 MemoryLocationsKind KnownMLK = getKnown();
8592 for (MemoryLocationsKind CurMLK = 1; CurMLK < NO_LOCATIONS; CurMLK *= 2)
8593 if (!(CurMLK & KnownMLK))
8594 updateStateAndAccessesMap(getState(), CurMLK,
I,
nullptr,
Changed,
8595 getAccessKindFromInst(
I));
8596 return AAMemoryLocation::indicatePessimisticFixpoint();
8616 bool operator()(
const AccessInfo &
LHS,
const AccessInfo &
RHS)
const {
8620 return LHS.Ptr <
RHS.Ptr;
8621 if (
LHS.Kind !=
RHS.Kind)
8622 return LHS.Kind <
RHS.Kind;
8629 using AccessSet = SmallSet<AccessInfo, 2, AccessInfo>;
8630 std::array<AccessSet *, llvm::ConstantLog2<VALID_STATE>()>
8631 AccessKind2Accesses;
8636 categorizeArgumentPointerLocations(Attributor &
A, CallBase &CB,
8637 AAMemoryLocation::StateType &AccessedLocs,
8642 categorizeAccessedLocations(Attributor &
A, Instruction &
I,
bool &
Changed);
8645 AccessKind getAccessKindFromInst(
const Instruction *
I) {
8648 AK =
I->mayReadFromMemory() ? READ :
NONE;
8657 void updateStateAndAccessesMap(AAMemoryLocation::StateType &State,
8658 MemoryLocationsKind MLK,
const Instruction *
I,
8667 if (MLK == NO_UNKOWN_MEM)
8669 State.removeAssumedBits(MLK);
8674 void categorizePtrValue(Attributor &
A,
const Instruction &
I,
const Value &Ptr,
8675 AAMemoryLocation::StateType &State,
bool &
Changed,
8676 unsigned AccessAS = 0);
8682void AAMemoryLocationImpl::categorizePtrValue(
8683 Attributor &
A,
const Instruction &
I,
const Value &Ptr,
8685 LLVM_DEBUG(
dbgs() <<
"[AAMemoryLocation] Categorize pointer locations for "
8690 unsigned ObjectAS =
Obj.getType()->getPointerAddressSpace();
8692 MemoryLocationsKind MLK = NO_LOCATIONS;
8712 MLK = NO_ARGUMENT_MEM;
8718 if (GVar->isConstant())
8721 if (GV->hasLocalLinkage())
8722 MLK = NO_GLOBAL_INTERNAL_MEM;
8724 MLK = NO_GLOBAL_EXTERNAL_MEM;
8732 bool IsKnownNoAlias;
8736 MLK = NO_MALLOCED_MEM;
8738 MLK = NO_UNKOWN_MEM;
8740 MLK = NO_UNKOWN_MEM;
8743 assert(MLK != NO_LOCATIONS &&
"No location specified!");
8744 LLVM_DEBUG(
dbgs() <<
"[AAMemoryLocation] Ptr value can be categorized: "
8745 << Obj <<
" -> " << getMemoryLocationsAsStr(MLK) <<
"\n");
8747 getAccessKindFromInst(&
I));
8752 const auto *AA =
A.getAAFor<AAUnderlyingObjects>(
8756 dbgs() <<
"[AAMemoryLocation] Pointer locations not categorized\n");
8757 updateStateAndAccessesMap(
State, NO_UNKOWN_MEM, &
I,
nullptr,
Changed,
8758 getAccessKindFromInst(&
I));
8763 dbgs() <<
"[AAMemoryLocation] Accessed locations with pointer locations: "
8767void AAMemoryLocationImpl::categorizeArgumentPointerLocations(
8770 for (
unsigned ArgNo = 0,
E = CB.
arg_size(); ArgNo <
E; ++ArgNo) {
8779 const auto *ArgOpMemLocationAA =
8782 if (ArgOpMemLocationAA && ArgOpMemLocationAA->isAssumedReadNone())
8787 categorizePtrValue(
A, CB, *ArgOp, AccessedLocs,
Changed);
8792AAMemoryLocationImpl::categorizeAccessedLocations(Attributor &
A, Instruction &
I,
8794 LLVM_DEBUG(
dbgs() <<
"[AAMemoryLocation] Categorize accessed locations for "
8798 AccessedLocs.intersectAssumedBits(NO_LOCATIONS);
8803 const auto *CBMemLocationAA =
A.getAAFor<AAMemoryLocation>(
8806 <<
" [" << CBMemLocationAA <<
"]\n");
8807 if (!CBMemLocationAA) {
8808 updateStateAndAccessesMap(AccessedLocs, NO_UNKOWN_MEM, &
I,
nullptr,
8809 Changed, getAccessKindFromInst(&
I));
8810 return NO_UNKOWN_MEM;
8813 if (CBMemLocationAA->isAssumedReadNone())
8814 return NO_LOCATIONS;
8816 if (CBMemLocationAA->isAssumedInaccessibleMemOnly()) {
8817 updateStateAndAccessesMap(AccessedLocs, NO_INACCESSIBLE_MEM, &
I,
nullptr,
8818 Changed, getAccessKindFromInst(&
I));
8819 return AccessedLocs.getAssumed();
8822 uint32_t CBAssumedNotAccessedLocs =
8823 CBMemLocationAA->getAssumedNotAccessedLocation();
8826 uint32_t CBAssumedNotAccessedLocsNoArgMem =
8827 CBAssumedNotAccessedLocs | NO_ARGUMENT_MEM | NO_GLOBAL_MEM;
8829 for (MemoryLocationsKind CurMLK = 1; CurMLK < NO_LOCATIONS; CurMLK *= 2) {
8830 if (CBAssumedNotAccessedLocsNoArgMem & CurMLK)
8832 updateStateAndAccessesMap(AccessedLocs, CurMLK, &
I,
nullptr,
Changed,
8833 getAccessKindFromInst(&
I));
8838 bool HasGlobalAccesses = ((~CBAssumedNotAccessedLocs) & NO_GLOBAL_MEM);
8839 if (HasGlobalAccesses) {
8842 updateStateAndAccessesMap(AccessedLocs, MLK, &
I, Ptr,
Changed,
8843 getAccessKindFromInst(&
I));
8846 if (!CBMemLocationAA->checkForAllAccessesToMemoryKind(
8847 AccessPred, inverseLocation(NO_GLOBAL_MEM,
false,
false)))
8848 return AccessedLocs.getWorstState();
8852 dbgs() <<
"[AAMemoryLocation] Accessed state before argument handling: "
8853 << getMemoryLocationsAsStr(AccessedLocs.getAssumed()) <<
"\n");
8856 bool HasArgAccesses = ((~CBAssumedNotAccessedLocs) & NO_ARGUMENT_MEM);
8858 categorizeArgumentPointerLocations(
A, *CB, AccessedLocs,
Changed);
8861 dbgs() <<
"[AAMemoryLocation] Accessed state after argument handling: "
8862 << getMemoryLocationsAsStr(AccessedLocs.getAssumed()) <<
"\n");
8864 return AccessedLocs.getAssumed();
8869 dbgs() <<
"[AAMemoryLocation] Categorize memory access with pointer: "
8870 <<
I <<
" [" << *Ptr <<
"]\n");
8871 categorizePtrValue(
A,
I, *Ptr, AccessedLocs,
Changed,
8872 Ptr->getType()->getPointerAddressSpace());
8873 return AccessedLocs.getAssumed();
8876 LLVM_DEBUG(
dbgs() <<
"[AAMemoryLocation] Failed to categorize instruction: "
8878 updateStateAndAccessesMap(AccessedLocs, NO_UNKOWN_MEM, &
I,
nullptr,
Changed,
8879 getAccessKindFromInst(&
I));
8880 return AccessedLocs.getAssumed();
8884struct AAMemoryLocationFunction final :
public AAMemoryLocationImpl {
8885 AAMemoryLocationFunction(
const IRPosition &IRP, Attributor &
A)
8886 : AAMemoryLocationImpl(IRP,
A) {}
8891 const auto *MemBehaviorAA =
8892 A.getAAFor<AAMemoryBehavior>(*
this, getIRPosition(), DepClassTy::NONE);
8895 return indicateOptimisticFixpoint();
8897 "AAMemoryLocation was not read-none but AAMemoryBehavior was!");
8898 A.recordDependence(*MemBehaviorAA, *
this, DepClassTy::OPTIONAL);
8899 return ChangeStatus::UNCHANGED;
8903 auto AssumedState = getAssumed();
8907 MemoryLocationsKind MLK = categorizeAccessedLocations(
A,
I,
Changed);
8908 LLVM_DEBUG(
dbgs() <<
"[AAMemoryLocation] Accessed locations for " <<
I
8909 <<
": " << getMemoryLocationsAsStr(MLK) <<
"\n");
8910 removeAssumedBits(inverseLocation(MLK,
false,
false));
8913 return getAssumedNotAccessedLocation() != VALID_STATE;
8916 bool UsedAssumedInformation =
false;
8917 if (!
A.checkForAllReadWriteInstructions(CheckRWInst, *
this,
8918 UsedAssumedInformation))
8919 return indicatePessimisticFixpoint();
8921 Changed |= AssumedState != getAssumed();
8922 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
8926 void trackStatistics()
const override {
8929 else if (isAssumedArgMemOnly())
8931 else if (isAssumedInaccessibleMemOnly())
8933 else if (isAssumedInaccessibleOrArgMemOnly())
8939struct AAMemoryLocationCallSite final : AAMemoryLocationImpl {
8940 AAMemoryLocationCallSite(
const IRPosition &IRP, Attributor &
A)
8941 : AAMemoryLocationImpl(IRP,
A) {}
8952 A.getAAFor<AAMemoryLocation>(*
this, FnPos, DepClassTy::REQUIRED);
8954 return indicatePessimisticFixpoint();
8958 updateStateAndAccessesMap(getState(), MLK,
I, Ptr,
Changed,
8959 getAccessKindFromInst(
I));
8962 if (!FnAA->checkForAllAccessesToMemoryKind(AccessPred, ALL_LOCATIONS))
8963 return indicatePessimisticFixpoint();
8964 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
8968 void trackStatistics()
const override {
8978struct AADenormalFPMathImpl :
public AADenormalFPMath {
8979 AADenormalFPMathImpl(
const IRPosition &IRP, Attributor &
A)
8980 : AADenormalFPMath(IRP,
A) {}
8982 const std::string getAsStr(Attributor *
A)
const override {
8983 std::string Str(
"AADenormalFPMath[");
8984 raw_string_ostream OS(Str);
8986 DenormalState Known = getKnown();
8987 if (Known.Mode.isValid())
8988 OS <<
"denormal-fp-math=" << Known.Mode;
8992 if (Known.ModeF32.isValid())
8993 OS <<
" denormal-fp-math-f32=" << Known.ModeF32;
8999struct AADenormalFPMathFunction final : AADenormalFPMathImpl {
9000 AADenormalFPMathFunction(
const IRPosition &IRP, Attributor &
A)
9001 : AADenormalFPMathImpl(IRP,
A) {}
9005 DenormalFPEnv DenormEnv =
F->getDenormalFPEnv();
9015 auto CheckCallSite = [=, &Change, &
A](AbstractCallSite CS) {
9018 <<
"->" << getAssociatedFunction()->
getName() <<
'\n');
9020 const auto *CallerInfo =
A.getAAFor<AADenormalFPMath>(
9026 CallerInfo->getState());
9030 bool AllCallSitesKnown =
true;
9031 if (!
A.checkForAllCallSites(CheckCallSite, *
this,
true, AllCallSitesKnown))
9032 return indicatePessimisticFixpoint();
9034 if (Change == ChangeStatus::CHANGED && isModeFixed())
9040 LLVMContext &Ctx = getAssociatedFunction()->getContext();
9046 DenormalFPEnv KnownEnv(Known.Mode, Known.ModeF32);
9049 AttrToRemove.
push_back(Attribute::DenormalFPEnv);
9052 Ctx, Attribute::DenormalFPEnv,
9053 DenormalFPEnv(Known.Mode, Known.ModeF32).toIntValue()));
9056 auto &IRP = getIRPosition();
9059 return A.removeAttrs(IRP, AttrToRemove) |
9060 A.manifestAttrs(IRP, AttrToAdd,
true);
9063 void trackStatistics()
const override {
9072struct AAValueConstantRangeImpl : AAValueConstantRange {
9073 using StateType = IntegerRangeState;
9074 AAValueConstantRangeImpl(
const IRPosition &IRP, Attributor &
A)
9075 : AAValueConstantRange(IRP,
A) {}
9079 if (
A.hasSimplificationCallback(getIRPosition())) {
9080 indicatePessimisticFixpoint();
9085 intersectKnown(getConstantRangeFromSCEV(
A, getCtxI()));
9088 intersectKnown(getConstantRangeFromLVI(
A, getCtxI()));
9092 const std::string getAsStr(Attributor *
A)
const override {
9094 llvm::raw_string_ostream OS(Str);
9096 getKnown().print(OS);
9098 getAssumed().print(OS);
9105 const SCEV *getSCEV(Attributor &
A,
const Instruction *
I =
nullptr)
const {
9106 if (!getAnchorScope())
9109 ScalarEvolution *SE =
9110 A.getInfoCache().getAnalysisResultForFunction<ScalarEvolutionAnalysis>(
9113 LoopInfo *LI =
A.getInfoCache().getAnalysisResultForFunction<LoopAnalysis>(
9119 const SCEV *S = SE->
getSCEV(&getAssociatedValue());
9128 ConstantRange getConstantRangeFromSCEV(Attributor &
A,
9129 const Instruction *
I =
nullptr)
const {
9130 if (!getAnchorScope())
9133 ScalarEvolution *SE =
9134 A.getInfoCache().getAnalysisResultForFunction<ScalarEvolutionAnalysis>(
9137 const SCEV *S = getSCEV(
A,
I);
9147 getConstantRangeFromLVI(Attributor &
A,
9148 const Instruction *CtxI =
nullptr)
const {
9149 if (!getAnchorScope())
9152 LazyValueInfo *LVI =
9153 A.getInfoCache().getAnalysisResultForFunction<LazyValueAnalysis>(
9168 bool isValidCtxInstructionForOutsideAnalysis(Attributor &
A,
9169 const Instruction *CtxI,
9170 bool AllowAACtxI)
const {
9171 if (!CtxI || (!AllowAACtxI && CtxI == getCtxI()))
9183 InformationCache &InfoCache =
A.getInfoCache();
9184 const DominatorTree *DT =
9195 getKnownConstantRange(Attributor &
A,
9196 const Instruction *CtxI =
nullptr)
const override {
9197 if (!isValidCtxInstructionForOutsideAnalysis(
A, CtxI,
9201 ConstantRange LVIR = getConstantRangeFromLVI(
A, CtxI);
9202 ConstantRange SCEVR = getConstantRangeFromSCEV(
A, CtxI);
9203 return getKnown().intersectWith(SCEVR).intersectWith(LVIR);
9208 getAssumedConstantRange(Attributor &
A,
9209 const Instruction *CtxI =
nullptr)
const override {
9214 if (!isValidCtxInstructionForOutsideAnalysis(
A, CtxI,
9216 return getAssumed();
9218 ConstantRange LVIR = getConstantRangeFromLVI(
A, CtxI);
9219 ConstantRange SCEVR = getConstantRangeFromSCEV(
A, CtxI);
9220 return getAssumed().intersectWith(SCEVR).intersectWith(LVIR);
9225 getMDNodeForConstantRange(
Type *Ty, LLVMContext &Ctx,
9226 const ConstantRange &AssumedConstantRange) {
9228 Ty, AssumedConstantRange.
getLower())),
9230 Ty, AssumedConstantRange.
getUpper()))};
9235 static bool isBetterRange(
const ConstantRange &Assumed,
9236 const Instruction &
I) {
9240 std::optional<ConstantRange> Known;
9244 }
else if (MDNode *KnownRanges =
I.getMetadata(LLVMContext::MD_range)) {
9250 if (KnownRanges->getNumOperands() > 2)
9253 ConstantInt *
Lower =
9255 ConstantInt *
Upper =
9258 Known.emplace(
Lower->getValue(),
Upper->getValue());
9260 return !Known || (*Known != Assumed && Known->contains(Assumed));
9265 setRangeMetadataIfisBetterRange(Instruction *
I,
9266 const ConstantRange &AssumedConstantRange) {
9267 if (isBetterRange(AssumedConstantRange, *
I)) {
9268 I->setMetadata(LLVMContext::MD_range,
9269 getMDNodeForConstantRange(
I->getType(),
I->getContext(),
9270 AssumedConstantRange));
9277 setRangeRetAttrIfisBetterRange(Attributor &
A,
const IRPosition &IRP,
9279 const ConstantRange &AssumedConstantRange) {
9280 if (isBetterRange(AssumedConstantRange, *
I)) {
9281 A.manifestAttrs(IRP,
9282 Attribute::get(
I->getContext(), Attribute::Range,
9283 AssumedConstantRange),
9293 ConstantRange AssumedConstantRange = getAssumedConstantRange(
A);
9296 auto &
V = getAssociatedValue();
9300 assert(
I == getCtxI() &&
"Should not annotate an instruction which is "
9301 "not the context instruction");
9303 if (setRangeMetadataIfisBetterRange(
I, AssumedConstantRange))
9304 Changed = ChangeStatus::CHANGED;
9306 if (setRangeRetAttrIfisBetterRange(
A, getIRPosition(),
I,
9307 AssumedConstantRange))
9308 Changed = ChangeStatus::CHANGED;
9316struct AAValueConstantRangeArgument final
9317 : AAArgumentFromCallSiteArguments<
9318 AAValueConstantRange, AAValueConstantRangeImpl, IntegerRangeState,
9320 using Base = AAArgumentFromCallSiteArguments<
9321 AAValueConstantRange, AAValueConstantRangeImpl, IntegerRangeState,
9323 AAValueConstantRangeArgument(
const IRPosition &IRP, Attributor &
A)
9327 void trackStatistics()
const override {
9332struct AAValueConstantRangeReturned
9333 : AAReturnedFromReturnedValues<AAValueConstantRange,
9334 AAValueConstantRangeImpl,
9335 AAValueConstantRangeImpl::StateType,
9338 AAReturnedFromReturnedValues<AAValueConstantRange,
9339 AAValueConstantRangeImpl,
9340 AAValueConstantRangeImpl::StateType,
9342 AAValueConstantRangeReturned(
const IRPosition &IRP, Attributor &
A)
9347 if (!
A.isFunctionIPOAmendable(*getAssociatedFunction()))
9348 indicatePessimisticFixpoint();
9352 void trackStatistics()
const override {
9357struct AAValueConstantRangeFloating : AAValueConstantRangeImpl {
9358 AAValueConstantRangeFloating(
const IRPosition &IRP, Attributor &
A)
9359 : AAValueConstantRangeImpl(IRP,
A) {}
9363 AAValueConstantRangeImpl::initialize(
A);
9367 Value &
V = getAssociatedValue();
9370 unionAssumed(ConstantRange(
C->getValue()));
9371 indicateOptimisticFixpoint();
9377 unionAssumed(ConstantRange(APInt(
getBitWidth(), 0)));
9378 indicateOptimisticFixpoint();
9390 if (
auto *RangeMD = LI->getMetadata(LLVMContext::MD_range)) {
9401 indicatePessimisticFixpoint();
9404 << getAssociatedValue() <<
"\n");
9407 bool calculateBinaryOperator(
9408 Attributor &
A, BinaryOperator *BinOp, IntegerRangeState &
T,
9409 const Instruction *CtxI,
9410 SmallVectorImpl<const AAValueConstantRange *> &QuerriedAAs) {
9415 bool UsedAssumedInformation =
false;
9416 const auto &SimplifiedLHS =
A.getAssumedSimplified(
9419 if (!SimplifiedLHS.has_value())
9421 if (!*SimplifiedLHS)
9423 LHS = *SimplifiedLHS;
9425 const auto &SimplifiedRHS =
A.getAssumedSimplified(
9428 if (!SimplifiedRHS.has_value())
9430 if (!*SimplifiedRHS)
9432 RHS = *SimplifiedRHS;
9438 auto *LHSAA =
A.getAAFor<AAValueConstantRange>(
9440 DepClassTy::REQUIRED);
9444 auto LHSAARange = LHSAA->getAssumedConstantRange(
A, CtxI);
9446 auto *RHSAA =
A.getAAFor<AAValueConstantRange>(
9448 DepClassTy::REQUIRED);
9452 auto RHSAARange = RHSAA->getAssumedConstantRange(
A, CtxI);
9454 auto AssumedRange = LHSAARange.binaryOp(BinOp->
getOpcode(), RHSAARange);
9456 T.unionAssumed(AssumedRange);
9460 return T.isValidState();
9463 bool calculateCastInst(
9464 Attributor &
A, CastInst *CastI, IntegerRangeState &
T,
9465 const Instruction *CtxI,
9466 SmallVectorImpl<const AAValueConstantRange *> &QuerriedAAs) {
9472 bool UsedAssumedInformation =
false;
9473 const auto &SimplifiedOpV =
A.getAssumedSimplified(
9476 if (!SimplifiedOpV.has_value())
9478 if (!*SimplifiedOpV)
9480 OpV = *SimplifiedOpV;
9485 auto *OpAA =
A.getAAFor<AAValueConstantRange>(
9487 DepClassTy::REQUIRED);
9491 T.unionAssumed(OpAA->getAssumed().castOp(CastI->
getOpcode(),
9493 return T.isValidState();
9497 calculateCmpInst(Attributor &
A, CmpInst *CmpI, IntegerRangeState &
T,
9498 const Instruction *CtxI,
9499 SmallVectorImpl<const AAValueConstantRange *> &QuerriedAAs) {
9504 bool UsedAssumedInformation =
false;
9505 const auto &SimplifiedLHS =
A.getAssumedSimplified(
9508 if (!SimplifiedLHS.has_value())
9510 if (!*SimplifiedLHS)
9512 LHS = *SimplifiedLHS;
9514 const auto &SimplifiedRHS =
A.getAssumedSimplified(
9517 if (!SimplifiedRHS.has_value())
9519 if (!*SimplifiedRHS)
9521 RHS = *SimplifiedRHS;
9527 auto *LHSAA =
A.getAAFor<AAValueConstantRange>(
9529 DepClassTy::REQUIRED);
9533 auto *RHSAA =
A.getAAFor<AAValueConstantRange>(
9535 DepClassTy::REQUIRED);
9539 auto LHSAARange = LHSAA->getAssumedConstantRange(
A, CtxI);
9540 auto RHSAARange = RHSAA->getAssumedConstantRange(
A, CtxI);
9543 if (LHSAARange.isEmptySet() || RHSAARange.isEmptySet())
9546 bool MustTrue =
false, MustFalse =
false;
9548 auto AllowedRegion =
9551 if (AllowedRegion.intersectWith(LHSAARange).isEmptySet())
9557 assert((!MustTrue || !MustFalse) &&
9558 "Either MustTrue or MustFalse should be false!");
9561 T.unionAssumed(ConstantRange(APInt( 1, 1)));
9563 T.unionAssumed(ConstantRange(APInt( 1, 0)));
9565 T.unionAssumed(ConstantRange( 1,
true));
9567 LLVM_DEBUG(
dbgs() <<
"[AAValueConstantRange] " << *CmpI <<
" after "
9568 << (MustTrue ?
"true" : (MustFalse ?
"false" :
"unknown"))
9569 <<
": " <<
T <<
"\n\t" << *LHSAA <<
"\t<op>\n\t"
9573 return T.isValidState();
9585 bool UsedAssumedInformation =
false;
9586 const auto &SimplifiedOpV =
A.getAssumedSimplified(
9589 if (!SimplifiedOpV.has_value())
9591 if (!*SimplifiedOpV)
9593 Value *VPtr = *SimplifiedOpV;
9596 const auto *AA =
A.getAAFor<AAValueConstantRange>(
9598 DepClassTy::REQUIRED);
9602 T.unionAssumed(AA->getAssumedConstantRange(
A, CtxI));
9606 return T.isValidState();
9611 if (!calculateBinaryOperator(
A, BinOp,
T, CtxI, QuerriedAAs))
9614 if (!calculateCmpInst(
A, CmpI,
T, CtxI, QuerriedAAs))
9617 if (!calculateCastInst(
A, CastI,
T, CtxI, QuerriedAAs))
9623 T.indicatePessimisticFixpoint();
9630 for (
const AAValueConstantRange *QueriedAA : QuerriedAAs) {
9631 if (QueriedAA !=
this)
9634 if (
T.getAssumed() == getState().getAssumed())
9636 T.indicatePessimisticFixpoint();
9639 return T.isValidState();
9642 if (!VisitValueCB(getAssociatedValue(), getCtxI()))
9643 return indicatePessimisticFixpoint();
9648 return ChangeStatus::UNCHANGED;
9649 if (++NumChanges > MaxNumChanges) {
9650 LLVM_DEBUG(
dbgs() <<
"[AAValueConstantRange] performed " << NumChanges
9651 <<
" but only " << MaxNumChanges
9652 <<
" are allowed to avoid cyclic reasoning.");
9653 return indicatePessimisticFixpoint();
9655 return ChangeStatus::CHANGED;
9659 void trackStatistics()
const override {
9668 static constexpr int MaxNumChanges = 5;
9671struct AAValueConstantRangeFunction : AAValueConstantRangeImpl {
9672 AAValueConstantRangeFunction(
const IRPosition &IRP, Attributor &
A)
9673 : AAValueConstantRangeImpl(IRP,
A) {}
9677 llvm_unreachable(
"AAValueConstantRange(Function|CallSite)::updateImpl will "
9685struct AAValueConstantRangeCallSite : AAValueConstantRangeFunction {
9686 AAValueConstantRangeCallSite(
const IRPosition &IRP, Attributor &
A)
9687 : AAValueConstantRangeFunction(IRP,
A) {}
9693struct AAValueConstantRangeCallSiteReturned
9694 : AACalleeToCallSite<AAValueConstantRange, AAValueConstantRangeImpl,
9695 AAValueConstantRangeImpl::StateType,
9697 AAValueConstantRangeCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
9698 : AACalleeToCallSite<AAValueConstantRange, AAValueConstantRangeImpl,
9699 AAValueConstantRangeImpl::StateType,
9706 if (std::optional<ConstantRange>
Range = CI->getRange())
9707 intersectKnown(*
Range);
9710 AAValueConstantRangeImpl::initialize(
A);
9714 void trackStatistics()
const override {
9718struct AAValueConstantRangeCallSiteArgument : AAValueConstantRangeFloating {
9719 AAValueConstantRangeCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
9720 : AAValueConstantRangeFloating(IRP,
A) {}
9724 return ChangeStatus::UNCHANGED;
9728 void trackStatistics()
const override {
9737struct AAPotentialConstantValuesImpl : AAPotentialConstantValues {
9740 AAPotentialConstantValuesImpl(
const IRPosition &IRP, Attributor &
A)
9741 : AAPotentialConstantValues(IRP,
A) {}
9745 if (
A.hasSimplificationCallback(getIRPosition()))
9746 indicatePessimisticFixpoint();
9748 AAPotentialConstantValues::initialize(
A);
9751 bool fillSetWithConstantValues(Attributor &
A,
const IRPosition &IRP, SetTy &S,
9752 bool &ContainsUndef,
bool ForSelf) {
9754 bool UsedAssumedInformation =
false;
9756 UsedAssumedInformation)) {
9763 auto *PotentialValuesAA =
A.getAAFor<AAPotentialConstantValues>(
9764 *
this, IRP, DepClassTy::REQUIRED);
9765 if (!PotentialValuesAA || !PotentialValuesAA->getState().isValidState())
9767 ContainsUndef = PotentialValuesAA->getState().undefIsContained();
9768 S = PotentialValuesAA->getState().getAssumedSet();
9775 ContainsUndef =
false;
9776 for (
auto &It : Values) {
9778 ContainsUndef =
true;
9784 S.insert(CI->getValue());
9786 ContainsUndef &= S.empty();
9792 const std::string getAsStr(Attributor *
A)
const override {
9794 llvm::raw_string_ostream OS(Str);
9801 return indicatePessimisticFixpoint();
9805struct AAPotentialConstantValuesArgument final
9806 : AAArgumentFromCallSiteArguments<AAPotentialConstantValues,
9807 AAPotentialConstantValuesImpl,
9808 PotentialConstantIntValuesState> {
9809 using Base = AAArgumentFromCallSiteArguments<AAPotentialConstantValues,
9810 AAPotentialConstantValuesImpl,
9812 AAPotentialConstantValuesArgument(
const IRPosition &IRP, Attributor &
A)
9816 void trackStatistics()
const override {
9821struct AAPotentialConstantValuesReturned
9822 : AAReturnedFromReturnedValues<AAPotentialConstantValues,
9823 AAPotentialConstantValuesImpl> {
9824 using Base = AAReturnedFromReturnedValues<AAPotentialConstantValues,
9825 AAPotentialConstantValuesImpl>;
9826 AAPotentialConstantValuesReturned(
const IRPosition &IRP, Attributor &
A)
9830 if (!
A.isFunctionIPOAmendable(*getAssociatedFunction()))
9831 indicatePessimisticFixpoint();
9832 Base::initialize(
A);
9836 void trackStatistics()
const override {
9841struct AAPotentialConstantValuesFloating : AAPotentialConstantValuesImpl {
9842 AAPotentialConstantValuesFloating(
const IRPosition &IRP, Attributor &
A)
9843 : AAPotentialConstantValuesImpl(IRP,
A) {}
9847 AAPotentialConstantValuesImpl::initialize(
A);
9851 Value &
V = getAssociatedValue();
9854 unionAssumed(
C->getValue());
9855 indicateOptimisticFixpoint();
9860 unionAssumedWithUndef();
9861 indicateOptimisticFixpoint();
9871 indicatePessimisticFixpoint();
9874 << getAssociatedValue() <<
"\n");
9877 static bool calculateICmpInst(
const ICmpInst *ICI,
const APInt &
LHS,
9882 static APInt calculateCastInst(
const CastInst *CI,
const APInt &Src,
9883 uint32_t ResultBitWidth) {
9888 case Instruction::Trunc:
9889 return Src.trunc(ResultBitWidth);
9890 case Instruction::SExt:
9891 return Src.sext(ResultBitWidth);
9892 case Instruction::ZExt:
9893 return Src.zext(ResultBitWidth);
9894 case Instruction::BitCast:
9899 static APInt calculateBinaryOperator(
const BinaryOperator *BinOp,
9900 const APInt &
LHS,
const APInt &
RHS,
9901 bool &SkipOperation,
bool &Unsupported) {
9908 switch (BinOpcode) {
9912 case Instruction::Add:
9914 case Instruction::Sub:
9916 case Instruction::Mul:
9918 case Instruction::UDiv:
9920 SkipOperation =
true;
9924 case Instruction::SDiv:
9926 SkipOperation =
true;
9930 case Instruction::URem:
9932 SkipOperation =
true;
9936 case Instruction::SRem:
9938 SkipOperation =
true;
9942 case Instruction::Shl:
9944 case Instruction::LShr:
9946 case Instruction::AShr:
9948 case Instruction::And:
9950 case Instruction::Or:
9952 case Instruction::Xor:
9957 bool calculateBinaryOperatorAndTakeUnion(
const BinaryOperator *BinOp,
9958 const APInt &
LHS,
const APInt &
RHS) {
9959 bool SkipOperation =
false;
9962 calculateBinaryOperator(BinOp,
LHS,
RHS, SkipOperation, Unsupported);
9967 unionAssumed(Result);
9968 return isValidState();
9971 ChangeStatus updateWithICmpInst(Attributor &
A, ICmpInst *ICI) {
9972 auto AssumedBefore = getAssumed();
9976 bool LHSContainsUndef =
false, RHSContainsUndef =
false;
9977 SetTy LHSAAPVS, RHSAAPVS;
9979 LHSContainsUndef,
false) ||
9981 RHSContainsUndef,
false))
9982 return indicatePessimisticFixpoint();
9985 bool MaybeTrue =
false, MaybeFalse =
false;
9987 if (LHSContainsUndef && RHSContainsUndef) {
9990 unionAssumedWithUndef();
9991 }
else if (LHSContainsUndef) {
9992 for (
const APInt &R : RHSAAPVS) {
9993 bool CmpResult = calculateICmpInst(ICI, Zero, R);
9994 MaybeTrue |= CmpResult;
9995 MaybeFalse |= !CmpResult;
9996 if (MaybeTrue & MaybeFalse)
9997 return indicatePessimisticFixpoint();
9999 }
else if (RHSContainsUndef) {
10000 for (
const APInt &L : LHSAAPVS) {
10001 bool CmpResult = calculateICmpInst(ICI, L, Zero);
10002 MaybeTrue |= CmpResult;
10003 MaybeFalse |= !CmpResult;
10004 if (MaybeTrue & MaybeFalse)
10005 return indicatePessimisticFixpoint();
10008 for (
const APInt &L : LHSAAPVS) {
10009 for (
const APInt &R : RHSAAPVS) {
10010 bool CmpResult = calculateICmpInst(ICI, L, R);
10011 MaybeTrue |= CmpResult;
10012 MaybeFalse |= !CmpResult;
10013 if (MaybeTrue & MaybeFalse)
10014 return indicatePessimisticFixpoint();
10019 unionAssumed(APInt( 1, 1));
10021 unionAssumed(APInt( 1, 0));
10022 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10023 : ChangeStatus::CHANGED;
10026 ChangeStatus updateWithSelectInst(Attributor &
A, SelectInst *SI) {
10027 auto AssumedBefore = getAssumed();
10031 bool UsedAssumedInformation =
false;
10032 std::optional<Constant *>
C =
A.getAssumedConstant(
10033 *
SI->getCondition(), *
this, UsedAssumedInformation);
10036 bool OnlyLeft =
false, OnlyRight =
false;
10037 if (
C && *
C && (*C)->isOneValue())
10039 else if (
C && *
C && (*C)->isNullValue())
10042 bool LHSContainsUndef =
false, RHSContainsUndef =
false;
10043 SetTy LHSAAPVS, RHSAAPVS;
10046 LHSContainsUndef,
false))
10047 return indicatePessimisticFixpoint();
10051 RHSContainsUndef,
false))
10052 return indicatePessimisticFixpoint();
10054 if (OnlyLeft || OnlyRight) {
10056 auto *OpAA = OnlyLeft ? &LHSAAPVS : &RHSAAPVS;
10057 auto Undef = OnlyLeft ? LHSContainsUndef : RHSContainsUndef;
10060 unionAssumedWithUndef();
10062 for (
const auto &It : *OpAA)
10066 }
else if (LHSContainsUndef && RHSContainsUndef) {
10068 unionAssumedWithUndef();
10070 for (
const auto &It : LHSAAPVS)
10072 for (
const auto &It : RHSAAPVS)
10075 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10076 : ChangeStatus::CHANGED;
10079 ChangeStatus updateWithCastInst(Attributor &
A, CastInst *CI) {
10080 auto AssumedBefore = getAssumed();
10082 return indicatePessimisticFixpoint();
10087 bool SrcContainsUndef =
false;
10090 SrcContainsUndef,
false))
10091 return indicatePessimisticFixpoint();
10093 if (SrcContainsUndef)
10094 unionAssumedWithUndef();
10096 for (
const APInt &S : SrcPVS) {
10097 APInt
T = calculateCastInst(CI, S, ResultBitWidth);
10101 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10102 : ChangeStatus::CHANGED;
10105 ChangeStatus updateWithBinaryOperator(Attributor &
A, BinaryOperator *BinOp) {
10106 auto AssumedBefore = getAssumed();
10110 bool LHSContainsUndef =
false, RHSContainsUndef =
false;
10111 SetTy LHSAAPVS, RHSAAPVS;
10113 LHSContainsUndef,
false) ||
10115 RHSContainsUndef,
false))
10116 return indicatePessimisticFixpoint();
10121 if (LHSContainsUndef && RHSContainsUndef) {
10122 if (!calculateBinaryOperatorAndTakeUnion(BinOp, Zero, Zero))
10123 return indicatePessimisticFixpoint();
10124 }
else if (LHSContainsUndef) {
10125 for (
const APInt &R : RHSAAPVS) {
10126 if (!calculateBinaryOperatorAndTakeUnion(BinOp, Zero, R))
10127 return indicatePessimisticFixpoint();
10129 }
else if (RHSContainsUndef) {
10130 for (
const APInt &L : LHSAAPVS) {
10131 if (!calculateBinaryOperatorAndTakeUnion(BinOp, L, Zero))
10132 return indicatePessimisticFixpoint();
10135 for (
const APInt &L : LHSAAPVS) {
10136 for (
const APInt &R : RHSAAPVS) {
10137 if (!calculateBinaryOperatorAndTakeUnion(BinOp, L, R))
10138 return indicatePessimisticFixpoint();
10142 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10143 : ChangeStatus::CHANGED;
10146 ChangeStatus updateWithInstruction(Attributor &
A, Instruction *Inst) {
10147 auto AssumedBefore = getAssumed();
10149 bool ContainsUndef;
10151 ContainsUndef,
true))
10152 return indicatePessimisticFixpoint();
10153 if (ContainsUndef) {
10154 unionAssumedWithUndef();
10156 for (
const auto &It : Incoming)
10159 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10160 : ChangeStatus::CHANGED;
10165 Value &
V = getAssociatedValue();
10169 return updateWithICmpInst(
A, ICI);
10172 return updateWithSelectInst(
A, SI);
10175 return updateWithCastInst(
A, CI);
10178 return updateWithBinaryOperator(
A, BinOp);
10181 return updateWithInstruction(
A,
I);
10183 return indicatePessimisticFixpoint();
10187 void trackStatistics()
const override {
10192struct AAPotentialConstantValuesFunction : AAPotentialConstantValuesImpl {
10193 AAPotentialConstantValuesFunction(
const IRPosition &IRP, Attributor &
A)
10194 : AAPotentialConstantValuesImpl(IRP,
A) {}
10199 "AAPotentialConstantValues(Function|CallSite)::updateImpl will "
10204 void trackStatistics()
const override {
10209struct AAPotentialConstantValuesCallSite : AAPotentialConstantValuesFunction {
10210 AAPotentialConstantValuesCallSite(
const IRPosition &IRP, Attributor &
A)
10211 : AAPotentialConstantValuesFunction(IRP,
A) {}
10214 void trackStatistics()
const override {
10219struct AAPotentialConstantValuesCallSiteReturned
10220 : AACalleeToCallSite<AAPotentialConstantValues,
10221 AAPotentialConstantValuesImpl> {
10222 AAPotentialConstantValuesCallSiteReturned(
const IRPosition &IRP,
10224 : AACalleeToCallSite<AAPotentialConstantValues,
10225 AAPotentialConstantValuesImpl>(IRP,
A) {}
10228 void trackStatistics()
const override {
10233struct AAPotentialConstantValuesCallSiteArgument
10234 : AAPotentialConstantValuesFloating {
10235 AAPotentialConstantValuesCallSiteArgument(
const IRPosition &IRP,
10237 : AAPotentialConstantValuesFloating(IRP,
A) {}
10241 AAPotentialConstantValuesImpl::initialize(
A);
10242 if (isAtFixpoint())
10245 Value &
V = getAssociatedValue();
10248 unionAssumed(
C->getValue());
10249 indicateOptimisticFixpoint();
10254 unionAssumedWithUndef();
10255 indicateOptimisticFixpoint();
10262 Value &
V = getAssociatedValue();
10263 auto AssumedBefore = getAssumed();
10264 auto *AA =
A.getAAFor<AAPotentialConstantValues>(
10267 return indicatePessimisticFixpoint();
10268 const auto &S = AA->getAssumed();
10270 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10271 : ChangeStatus::CHANGED;
10275 void trackStatistics()
const override {
10284 bool IgnoreSubsumingPositions) {
10285 assert(ImpliedAttributeKind == Attribute::NoUndef &&
10286 "Unexpected attribute kind");
10287 if (
A.hasAttr(IRP, {Attribute::NoUndef}, IgnoreSubsumingPositions,
10288 Attribute::NoUndef))
10308 Value &V = getAssociatedValue();
10310 indicatePessimisticFixpoint();
10311 assert(!isImpliedByIR(
A, getIRPosition(), Attribute::NoUndef));
10315 bool followUseInMBEC(Attributor &
A,
const Use *U,
const Instruction *
I,
10316 AANoUndef::StateType &State) {
10317 const Value *UseV =
U->get();
10318 const DominatorTree *DT =
nullptr;
10319 AssumptionCache *AC =
nullptr;
10320 InformationCache &InfoCache =
A.getInfoCache();
10321 if (Function *
F = getAnchorScope()) {
10326 bool TrackUse =
false;
10335 const std::string getAsStr(Attributor *
A)
const override {
10336 return getAssumed() ?
"noundef" :
"may-undef-or-poison";
10343 bool UsedAssumedInformation =
false;
10344 if (
A.isAssumedDead(getIRPosition(),
nullptr,
nullptr,
10345 UsedAssumedInformation))
10346 return ChangeStatus::UNCHANGED;
10350 if (!
A.getAssumedSimplified(getIRPosition(), *
this, UsedAssumedInformation,
10353 return ChangeStatus::UNCHANGED;
10354 return AANoUndef::manifest(
A);
10358struct AANoUndefFloating :
public AANoUndefImpl {
10359 AANoUndefFloating(
const IRPosition &IRP, Attributor &
A)
10360 : AANoUndefImpl(IRP,
A) {}
10364 AANoUndefImpl::initialize(
A);
10365 if (!getState().isAtFixpoint() && getAnchorScope() &&
10366 !getAnchorScope()->isDeclaration())
10367 if (Instruction *CtxI = getCtxI())
10368 followUsesInMBEC(*
this,
A, getState(), *CtxI);
10373 auto VisitValueCB = [&](
const IRPosition &IRP) ->
bool {
10374 bool IsKnownNoUndef;
10376 A,
this, IRP, DepClassTy::REQUIRED, IsKnownNoUndef);
10380 bool UsedAssumedInformation =
false;
10381 Value *AssociatedValue = &getAssociatedValue();
10383 if (!
A.getAssumedSimplifiedValues(getIRPosition(), *
this, Values,
10388 Values.
size() != 1 || Values.
front().getValue() != AssociatedValue;
10396 if (AVIRP == getIRPosition() || !VisitValueCB(AVIRP))
10397 return indicatePessimisticFixpoint();
10398 return ChangeStatus::UNCHANGED;
10401 for (
const auto &VAC : Values)
10403 return indicatePessimisticFixpoint();
10405 return ChangeStatus::UNCHANGED;
10412struct AANoUndefReturned final
10413 : AAReturnedFromReturnedValues<AANoUndef, AANoUndefImpl> {
10414 AANoUndefReturned(
const IRPosition &IRP, Attributor &
A)
10415 : AAReturnedFromReturnedValues<AANoUndef, AANoUndefImpl>(IRP,
A) {}
10421struct AANoUndefArgument final
10422 : AAArgumentFromCallSiteArguments<AANoUndef, AANoUndefImpl> {
10423 AANoUndefArgument(
const IRPosition &IRP, Attributor &
A)
10424 : AAArgumentFromCallSiteArguments<AANoUndef, AANoUndefImpl>(IRP,
A) {}
10430struct AANoUndefCallSiteArgument final : AANoUndefFloating {
10431 AANoUndefCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
10432 : AANoUndefFloating(IRP,
A) {}
10438struct AANoUndefCallSiteReturned final
10439 : AACalleeToCallSite<AANoUndef, AANoUndefImpl> {
10440 AANoUndefCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
10441 : AACalleeToCallSite<AANoUndef, AANoUndefImpl>(IRP,
A) {}
10449struct AANoFPClassImpl : AANoFPClass {
10450 AANoFPClassImpl(
const IRPosition &IRP, Attributor &
A) : AANoFPClass(IRP,
A) {}
10453 const IRPosition &IRP = getIRPosition();
10457 indicateOptimisticFixpoint();
10462 A.getAttrs(getIRPosition(), {Attribute::NoFPClass},
Attrs,
false);
10463 for (
const auto &Attr : Attrs) {
10470 const DataLayout &
DL =
A.getDataLayout();
10471 InformationCache &InfoCache =
A.getInfoCache();
10473 const DominatorTree *DT =
nullptr;
10474 AssumptionCache *AC =
nullptr;
10475 const TargetLibraryInfo *TLI =
nullptr;
10479 if (!
F->isDeclaration()) {
10486 SimplifyQuery Q(
DL, TLI, DT, AC, CtxI);
10493 followUsesInMBEC(*
this,
A, getState(), *CtxI);
10497 bool followUseInMBEC(Attributor &
A,
const Use *U,
const Instruction *
I,
10498 AANoFPClass::StateType &State) {
10509 if (
auto *NoFPAA =
A.getAAFor<AANoFPClass>(*
this, IRP, DepClassTy::NONE))
10510 State.addKnownBits(NoFPAA->getState().getKnown());
10514 const std::string getAsStr(Attributor *
A)
const override {
10515 std::string
Result =
"nofpclass";
10516 raw_string_ostream OS(Result);
10517 OS << getKnownNoFPClass() <<
'/' << getAssumedNoFPClass();
10521 void getDeducedAttributes(Attributor &
A, LLVMContext &Ctx,
10522 SmallVectorImpl<Attribute> &Attrs)
const override {
10523 Attrs.emplace_back(Attribute::getWithNoFPClass(Ctx, getAssumedNoFPClass()));
10527struct AANoFPClassFloating :
public AANoFPClassImpl {
10528 AANoFPClassFloating(
const IRPosition &IRP, Attributor &
A)
10529 : AANoFPClassImpl(IRP,
A) {}
10534 bool UsedAssumedInformation =
false;
10535 if (!
A.getAssumedSimplifiedValues(getIRPosition(), *
this, Values,
10537 Values.
push_back({getAssociatedValue(), getCtxI()});
10543 DepClassTy::REQUIRED);
10544 if (!AA ||
this == AA) {
10545 T.indicatePessimisticFixpoint();
10547 const AANoFPClass::StateType &S =
10548 static_cast<const AANoFPClass::StateType &
>(AA->
getState());
10551 return T.isValidState();
10554 for (
const auto &VAC : Values)
10556 return indicatePessimisticFixpoint();
10562 void trackStatistics()
const override {
10567struct AANoFPClassReturned final
10568 : AAReturnedFromReturnedValues<AANoFPClass, AANoFPClassImpl,
10569 AANoFPClassImpl::StateType, false,
10570 Attribute::None, false> {
10571 AANoFPClassReturned(
const IRPosition &IRP, Attributor &
A)
10572 : AAReturnedFromReturnedValues<AANoFPClass, AANoFPClassImpl,
10573 AANoFPClassImpl::StateType,
false,
10577 void trackStatistics()
const override {
10582struct AANoFPClassArgument final
10583 : AAArgumentFromCallSiteArguments<AANoFPClass, AANoFPClassImpl> {
10584 AANoFPClassArgument(
const IRPosition &IRP, Attributor &
A)
10585 : AAArgumentFromCallSiteArguments<AANoFPClass, AANoFPClassImpl>(IRP,
A) {}
10591struct AANoFPClassCallSiteArgument final : AANoFPClassFloating {
10592 AANoFPClassCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
10593 : AANoFPClassFloating(IRP,
A) {}
10596 void trackStatistics()
const override {
10601struct AANoFPClassCallSiteReturned final
10602 : AACalleeToCallSite<AANoFPClass, AANoFPClassImpl> {
10603 AANoFPClassCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
10604 : AACalleeToCallSite<AANoFPClass, AANoFPClassImpl>(IRP,
A) {}
10607 void trackStatistics()
const override {
10612struct AACallEdgesImpl :
public AACallEdges {
10613 AACallEdgesImpl(
const IRPosition &IRP, Attributor &
A) : AACallEdges(IRP,
A) {}
10615 const SetVector<Function *> &getOptimisticEdges()
const override {
10616 return CalledFunctions;
10619 bool hasUnknownCallee()
const override {
return HasUnknownCallee; }
10621 bool hasNonAsmUnknownCallee()
const override {
10622 return HasUnknownCalleeNonAsm;
10625 const std::string getAsStr(Attributor *
A)
const override {
10626 return "CallEdges[" + std::to_string(HasUnknownCallee) +
"," +
10627 std::to_string(CalledFunctions.size()) +
"]";
10630 void trackStatistics()
const override {}
10633 void addCalledFunction(Function *Fn,
ChangeStatus &Change) {
10634 if (CalledFunctions.insert(Fn)) {
10635 Change = ChangeStatus::CHANGED;
10641 void setHasUnknownCallee(
bool NonAsm,
ChangeStatus &Change) {
10642 if (!HasUnknownCallee)
10643 Change = ChangeStatus::CHANGED;
10644 if (NonAsm && !HasUnknownCalleeNonAsm)
10645 Change = ChangeStatus::CHANGED;
10646 HasUnknownCalleeNonAsm |= NonAsm;
10647 HasUnknownCallee =
true;
10652 SetVector<Function *> CalledFunctions;
10655 bool HasUnknownCallee =
false;
10658 bool HasUnknownCalleeNonAsm =
false;
10661struct AACallEdgesCallSite :
public AACallEdgesImpl {
10662 AACallEdgesCallSite(
const IRPosition &IRP, Attributor &
A)
10663 : AACallEdgesImpl(IRP,
A) {}
10670 addCalledFunction(Fn, Change);
10672 LLVM_DEBUG(
dbgs() <<
"[AACallEdges] Unrecognized value: " << V <<
"\n");
10673 setHasUnknownCallee(
true, Change);
10684 VisitValue(*V, CtxI);
10688 bool UsedAssumedInformation =
false;
10694 for (
auto &VAC : Values)
10701 if (
IA->hasSideEffects() &&
10704 setHasUnknownCallee(
false, Change);
10710 if (
auto *IndirectCallAA =
A.getAAFor<AAIndirectCallInfo>(
10711 *
this, getIRPosition(), DepClassTy::OPTIONAL))
10712 if (IndirectCallAA->foreachCallee(
10713 [&](Function *Fn) { return VisitValue(*Fn, CB); }))
10722 for (
const Use *U : CallbackUses)
10723 ProcessCalledOperand(
U->get(), CB);
10729struct AACallEdgesFunction :
public AACallEdgesImpl {
10730 AACallEdgesFunction(
const IRPosition &IRP, Attributor &
A)
10731 : AACallEdgesImpl(IRP,
A) {}
10740 auto *CBEdges =
A.getAAFor<AACallEdges>(
10744 if (CBEdges->hasNonAsmUnknownCallee())
10745 setHasUnknownCallee(
true, Change);
10746 if (CBEdges->hasUnknownCallee())
10747 setHasUnknownCallee(
false, Change);
10749 for (Function *
F : CBEdges->getOptimisticEdges())
10750 addCalledFunction(
F, Change);
10756 bool UsedAssumedInformation =
false;
10757 if (!
A.checkForAllCallLikeInstructions(ProcessCallInst, *
this,
10758 UsedAssumedInformation,
10762 setHasUnknownCallee(
true, Change);
10771struct AAInterFnReachabilityFunction
10772 :
public CachedReachabilityAA<AAInterFnReachability, Function> {
10773 using Base = CachedReachabilityAA<AAInterFnReachability, Function>;
10774 AAInterFnReachabilityFunction(
const IRPosition &IRP, Attributor &
A)
10777 bool instructionCanReach(
10778 Attributor &
A,
const Instruction &From,
const Function &To,
10781 auto *NonConstThis =
const_cast<AAInterFnReachabilityFunction *
>(
this);
10783 RQITy StackRQI(
A, From, To, ExclusionSet,
false);
10784 RQITy::Reachable
Result;
10785 if (!NonConstThis->checkQueryCache(
A, StackRQI, Result))
10786 return NonConstThis->isReachableImpl(
A, StackRQI,
10788 return Result == RQITy::Reachable::Yes;
10792 bool IsTemporaryRQI)
override {
10794 &RQI.From->getFunction()->getEntryBlock().front();
10795 if (EntryI != RQI.From &&
10796 !instructionCanReach(
A, *EntryI, *RQI.To,
nullptr))
10797 return rememberResult(
A, RQITy::Reachable::No, RQI,
false,
10800 auto CheckReachableCallBase = [&](CallBase *CB) {
10801 auto *CBEdges =
A.getAAFor<AACallEdges>(
10803 if (!CBEdges || !CBEdges->getState().isValidState())
10806 if (CBEdges->hasUnknownCallee())
10809 for (Function *Fn : CBEdges->getOptimisticEdges()) {
10820 if (Fn == getAnchorScope()) {
10821 if (EntryI == RQI.From)
10826 const AAInterFnReachability *InterFnReachability =
10828 DepClassTy::OPTIONAL);
10831 if (!InterFnReachability ||
10839 const auto *IntraFnReachability =
A.getAAFor<AAIntraFnReachability>(
10841 DepClassTy::OPTIONAL);
10849 return IntraFnReachability && !IntraFnReachability->isAssumedReachable(
10850 A, *RQI.From, CBInst, RQI.ExclusionSet);
10853 bool UsedExclusionSet =
true;
10854 bool UsedAssumedInformation =
false;
10855 if (!
A.checkForAllCallLikeInstructions(CheckCallBase, *
this,
10856 UsedAssumedInformation,
10858 return rememberResult(
A, RQITy::Reachable::Yes, RQI, UsedExclusionSet,
10861 return rememberResult(
A, RQITy::Reachable::No, RQI, UsedExclusionSet,
10865 void trackStatistics()
const override {}
10869template <
typename AAType>
10870static std::optional<Constant *>
10873 if (!Ty.isIntegerTy())
10881 std::optional<Constant *> COpt =
AA->getAssumedConstant(
A);
10883 if (!COpt.has_value()) {
10885 return std::nullopt;
10887 if (
auto *
C = *COpt) {
10898 std::optional<Value *> V;
10899 for (
auto &It : Values) {
10901 if (V.has_value() && !*V)
10904 if (!V.has_value())
10918 if (
A.hasSimplificationCallback(getIRPosition())) {
10919 indicatePessimisticFixpoint();
10922 Value *Stripped = getAssociatedValue().stripPointerCasts();
10924 addValue(
A, getState(), *Stripped, getCtxI(),
AA::AnyScope,
10926 indicateOptimisticFixpoint();
10929 AAPotentialValues::initialize(
A);
10933 const std::string getAsStr(Attributor *
A)
const override {
10935 llvm::raw_string_ostream OS(Str);
10940 template <
typename AAType>
10941 static std::optional<Value *> askOtherAA(Attributor &
A,
10942 const AbstractAttribute &AA,
10943 const IRPosition &IRP,
Type &Ty) {
10948 return std::nullopt;
10955 virtual void addValue(Attributor &
A, StateType &State,
Value &V,
10957 Function *AnchorScope)
const {
10961 for (
const auto &U : CB->
args()) {
10971 Type &Ty = *getAssociatedType();
10972 std::optional<Value *> SimpleV =
10973 askOtherAA<AAValueConstantRange>(
A, *
this, ValIRP, Ty);
10974 if (SimpleV.has_value() && !*SimpleV) {
10975 auto *PotentialConstantsAA =
A.getAAFor<AAPotentialConstantValues>(
10976 *
this, ValIRP, DepClassTy::OPTIONAL);
10977 if (PotentialConstantsAA && PotentialConstantsAA->isValidState()) {
10978 for (
const auto &It : PotentialConstantsAA->getAssumedSet())
10979 State.unionAssumed({{*ConstantInt::get(&Ty, It),
nullptr}, S});
10980 if (PotentialConstantsAA->undefIsContained())
10985 if (!SimpleV.has_value())
10997 State.unionAssumed({{*VPtr, CtxI}, S});
11003 AA::ValueAndContext
I;
11007 return II.I ==
I &&
II.S == S;
11010 return std::tie(
I, S) < std::tie(
II.I,
II.S);
11014 bool recurseForValue(Attributor &
A,
const IRPosition &IRP,
AA::ValueScope S) {
11015 SmallMapVector<AA::ValueAndContext, int, 8> ValueScopeMap;
11020 bool UsedAssumedInformation =
false;
11022 if (!
A.getAssumedSimplifiedValues(IRP,
this, Values, CS,
11023 UsedAssumedInformation))
11026 for (
auto &It : Values)
11027 ValueScopeMap[It] += CS;
11029 for (
auto &It : ValueScopeMap)
11030 addValue(
A, getState(), *It.first.getValue(), It.first.getCtxI(),
11036 void giveUpOnIntraprocedural(Attributor &
A) {
11037 auto NewS = StateType::getBestState(getState());
11038 for (
const auto &It : getAssumedSet()) {
11041 addValue(
A, NewS, *It.first.getValue(), It.first.getCtxI(),
11044 assert(!undefIsContained() &&
"Undef should be an explicit value!");
11052 getState() = StateType::getBestState(getState());
11053 getState().unionAssumed({{getAssociatedValue(), getCtxI()},
AA::AnyScope});
11054 AAPotentialValues::indicateOptimisticFixpoint();
11055 return ChangeStatus::CHANGED;
11060 return indicatePessimisticFixpoint();
11068 if (!getAssumedSimplifiedValues(
A, Values, S))
11070 Value &OldV = getAssociatedValue();
11073 Value *NewV = getSingleValue(
A, *
this, getIRPosition(), Values);
11074 if (!NewV || NewV == &OldV)
11079 if (
A.changeAfterManifest(getIRPosition(), *NewV))
11080 return ChangeStatus::CHANGED;
11082 return ChangeStatus::UNCHANGED;
11085 bool getAssumedSimplifiedValues(
11086 Attributor &
A, SmallVectorImpl<AA::ValueAndContext> &Values,
11087 AA::ValueScope S,
bool RecurseForSelectAndPHI =
false)
const override {
11088 if (!isValidState())
11090 bool UsedAssumedInformation =
false;
11091 for (
const auto &It : getAssumedSet())
11092 if (It.second & S) {
11093 if (RecurseForSelectAndPHI && (
isa<PHINode>(It.first.getValue()) ||
11095 if (
A.getAssumedSimplifiedValues(
11097 this, Values, S, UsedAssumedInformation))
11102 assert(!undefIsContained() &&
"Undef should be an explicit value!");
11107struct AAPotentialValuesFloating : AAPotentialValuesImpl {
11108 AAPotentialValuesFloating(
const IRPosition &IRP, Attributor &
A)
11109 : AAPotentialValuesImpl(IRP,
A) {}
11113 auto AssumedBefore = getAssumed();
11115 genericValueTraversal(
A, &getAssociatedValue());
11117 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
11118 : ChangeStatus::CHANGED;
11122 struct LivenessInfo {
11123 const AAIsDead *LivenessAA =
nullptr;
11124 bool AnyDead =
false;
11134 SmallVectorImpl<ItemInfo> &Worklist) {
11137 bool UsedAssumedInformation =
false;
11139 auto GetSimplifiedValues = [&](
Value &
V,
11141 if (!
A.getAssumedSimplifiedValues(
11145 Values.
push_back(AA::ValueAndContext{
V,
II.I.getCtxI()});
11147 return Values.
empty();
11149 if (GetSimplifiedValues(*
LHS, LHSValues))
11151 if (GetSimplifiedValues(*
RHS, RHSValues))
11156 InformationCache &InfoCache =
A.getInfoCache();
11163 F ?
A.getInfoCache().getTargetLibraryInfoForFunction(*
F) :
nullptr;
11168 const DataLayout &
DL =
A.getDataLayout();
11169 SimplifyQuery Q(
DL, TLI, DT, AC, CmpI);
11171 auto CheckPair = [&](
Value &LHSV,
Value &RHSV) {
11174 nullptr,
II.S, getAnchorScope());
11180 if (&LHSV == &RHSV &&
11182 Constant *NewV = ConstantInt::get(Type::getInt1Ty(Ctx),
11184 addValue(
A, getState(), *NewV,
nullptr,
II.S,
11191 if (TypedLHS && TypedRHS) {
11193 if (NewV && NewV != &Cmp) {
11194 addValue(
A, getState(), *NewV,
nullptr,
II.S,
11206 if (!LHSIsNull && !RHSIsNull)
11212 assert((LHSIsNull || RHSIsNull) &&
11213 "Expected nullptr versus non-nullptr comparison at this point");
11216 unsigned PtrIdx = LHSIsNull;
11217 bool IsKnownNonNull;
11220 DepClassTy::REQUIRED, IsKnownNonNull);
11221 if (!IsAssumedNonNull)
11227 addValue(
A, getState(), *NewV,
nullptr,
II.S,
11232 for (
auto &LHSValue : LHSValues)
11233 for (
auto &RHSValue : RHSValues)
11234 if (!CheckPair(*LHSValue.getValue(), *RHSValue.getValue()))
11239 bool handleSelectInst(Attributor &
A, SelectInst &SI, ItemInfo
II,
11240 SmallVectorImpl<ItemInfo> &Worklist) {
11242 bool UsedAssumedInformation =
false;
11244 std::optional<Constant *>
C =
11245 A.getAssumedConstant(*
SI.getCondition(), *
this, UsedAssumedInformation);
11246 bool NoValueYet = !
C.has_value();
11254 }
else if (&SI == &getAssociatedValue()) {
11259 std::optional<Value *> SimpleV =
A.getAssumedSimplified(
11261 if (!SimpleV.has_value())
11264 addValue(
A, getState(), **SimpleV, CtxI,
II.S, getAnchorScope());
11272 bool handleLoadInst(Attributor &
A, LoadInst &LI, ItemInfo
II,
11273 SmallVectorImpl<ItemInfo> &Worklist) {
11274 SmallSetVector<Value *, 4> PotentialCopies;
11275 SmallSetVector<Instruction *, 4> PotentialValueOrigins;
11276 bool UsedAssumedInformation =
false;
11278 PotentialValueOrigins, *
this,
11279 UsedAssumedInformation,
11281 LLVM_DEBUG(
dbgs() <<
"[AAPotentialValues] Failed to get potentially "
11282 "loaded values for load instruction "
11290 InformationCache &InfoCache =
A.getInfoCache();
11292 if (!
llvm::all_of(PotentialValueOrigins, [&](Instruction *
I) {
11296 return A.isAssumedDead(
SI->getOperandUse(0),
this,
11298 UsedAssumedInformation,
11300 return A.isAssumedDead(*
I,
this,
nullptr,
11301 UsedAssumedInformation,
11304 LLVM_DEBUG(
dbgs() <<
"[AAPotentialValues] Load is onl used by assumes "
11305 "and we cannot delete all the stores: "
11316 bool AllLocal = ScopeIsLocal;
11321 if (!DynamicallyUnique) {
11322 LLVM_DEBUG(
dbgs() <<
"[AAPotentialValues] Not all potentially loaded "
11323 "values are dynamically unique: "
11328 for (
auto *PotentialCopy : PotentialCopies) {
11330 Worklist.
push_back({{*PotentialCopy, CtxI},
II.S});
11335 if (!AllLocal && ScopeIsLocal)
11340 bool handlePHINode(
11341 Attributor &
A, PHINode &
PHI, ItemInfo
II,
11342 SmallVectorImpl<ItemInfo> &Worklist,
11343 SmallMapVector<const Function *, LivenessInfo, 4> &LivenessAAs) {
11344 auto GetLivenessInfo = [&](
const Function &
F) -> LivenessInfo & {
11345 LivenessInfo &LI = LivenessAAs[&
F];
11346 if (!LI.LivenessAA)
11352 if (&
PHI == &getAssociatedValue()) {
11353 LivenessInfo &LI = GetLivenessInfo(*
PHI.getFunction());
11355 A.getInfoCache().getAnalysisResultForFunction<CycleAnalysis>(
11356 *
PHI.getFunction());
11360 for (
unsigned u = 0, e =
PHI.getNumIncomingValues(); u < e; u++) {
11362 if (LI.LivenessAA &&
11363 LI.LivenessAA->isEdgeDead(IncomingBB,
PHI.getParent())) {
11382 bool UsedAssumedInformation =
false;
11383 std::optional<Value *> SimpleV =
A.getAssumedSimplified(
11385 if (!SimpleV.has_value())
11389 addValue(
A, getState(), **SimpleV, &
PHI,
II.S, getAnchorScope());
11396 bool handleGenericInst(Attributor &
A, Instruction &
I, ItemInfo
II,
11397 SmallVectorImpl<ItemInfo> &Worklist) {
11398 bool SomeSimplified =
false;
11399 bool UsedAssumedInformation =
false;
11401 SmallVector<Value *, 8> NewOps(
I.getNumOperands());
11404 const auto &SimplifiedOp =
A.getAssumedSimplified(
11409 if (!SimplifiedOp.has_value())
11413 NewOps[Idx] = *SimplifiedOp;
11417 SomeSimplified |= (NewOps[Idx] !=
Op);
11423 if (!SomeSimplified)
11426 InformationCache &InfoCache =
A.getInfoCache();
11430 const auto *TLI =
A.getInfoCache().getTargetLibraryInfoForFunction(*
F);
11433 const DataLayout &
DL =
I.getDataLayout();
11434 SimplifyQuery Q(
DL, TLI, DT, AC, &
I);
11436 if (!NewV || NewV == &
I)
11439 LLVM_DEBUG(
dbgs() <<
"Generic inst " <<
I <<
" assumed simplified to "
11446 Attributor &
A, Instruction &
I, ItemInfo
II,
11447 SmallVectorImpl<ItemInfo> &Worklist,
11448 SmallMapVector<const Function *, LivenessInfo, 4> &LivenessAAs) {
11451 CI->getPredicate(),
II, Worklist);
11453 switch (
I.getOpcode()) {
11454 case Instruction::Select:
11456 case Instruction::PHI:
11458 case Instruction::Load:
11461 return handleGenericInst(
A,
I,
II, Worklist);
11466 void genericValueTraversal(Attributor &
A,
Value *InitialV) {
11467 SmallMapVector<const Function *, LivenessInfo, 4> LivenessAAs;
11469 SmallSet<ItemInfo, 16> Visited;
11488 LLVM_DEBUG(
dbgs() <<
"Generic value traversal reached iteration limit: "
11489 << Iteration <<
"!\n");
11490 addValue(
A, getState(), *V, CtxI, S, getAnchorScope());
11496 Value *NewV =
nullptr;
11497 if (
V->getType()->isPointerTy()) {
11503 for (Argument &Arg :
Callee->args())
11510 if (NewV && NewV != V) {
11511 Worklist.
push_back({{*NewV, CtxI}, S});
11525 if (V == InitialV && CtxI == getCtxI()) {
11526 indicatePessimisticFixpoint();
11530 addValue(
A, getState(), *V, CtxI, S, getAnchorScope());
11531 }
while (!Worklist.
empty());
11535 for (
auto &It : LivenessAAs)
11536 if (It.second.AnyDead)
11537 A.recordDependence(*It.second.LivenessAA, *
this, DepClassTy::OPTIONAL);
11541 void trackStatistics()
const override {
11546struct AAPotentialValuesArgument final : AAPotentialValuesImpl {
11547 using Base = AAPotentialValuesImpl;
11548 AAPotentialValuesArgument(
const IRPosition &IRP, Attributor &
A)
11555 indicatePessimisticFixpoint();
11560 auto AssumedBefore = getAssumed();
11562 unsigned ArgNo = getCalleeArgNo();
11564 bool UsedAssumedInformation =
false;
11566 auto CallSitePred = [&](AbstractCallSite ACS) {
11568 if (CSArgIRP.getPositionKind() == IRP_INVALID)
11571 if (!
A.getAssumedSimplifiedValues(CSArgIRP,
this, Values,
11573 UsedAssumedInformation))
11576 return isValidState();
11579 if (!
A.checkForAllCallSites(CallSitePred, *
this,
11581 UsedAssumedInformation))
11582 return indicatePessimisticFixpoint();
11584 Function *Fn = getAssociatedFunction();
11585 bool AnyNonLocal =
false;
11586 for (
auto &It : Values) {
11588 addValue(
A, getState(), *It.getValue(), It.getCtxI(),
AA::AnyScope,
11593 return indicatePessimisticFixpoint();
11597 addValue(
A, getState(), *It.getValue(), It.getCtxI(),
AA::AnyScope,
11603 AnyNonLocal =
true;
11605 assert(!undefIsContained() &&
"Undef should be an explicit value!");
11607 giveUpOnIntraprocedural(
A);
11609 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
11610 : ChangeStatus::CHANGED;
11614 void trackStatistics()
const override {
11619struct AAPotentialValuesReturned :
public AAPotentialValuesFloating {
11620 using Base = AAPotentialValuesFloating;
11621 AAPotentialValuesReturned(
const IRPosition &IRP, Attributor &
A)
11627 if (!
F ||
F->isDeclaration() ||
F->getReturnType()->isVoidTy()) {
11628 indicatePessimisticFixpoint();
11632 for (Argument &Arg :
F->args())
11635 ReturnedArg = &Arg;
11638 if (!
A.isFunctionIPOAmendable(*
F) ||
11639 A.hasSimplificationCallback(getIRPosition())) {
11641 indicatePessimisticFixpoint();
11643 indicateOptimisticFixpoint();
11649 auto AssumedBefore = getAssumed();
11650 bool UsedAssumedInformation =
false;
11653 Function *AnchorScope = getAnchorScope();
11659 UsedAssumedInformation,
11665 bool AllInterAreIntra =
false;
11668 llvm::all_of(Values, [&](
const AA::ValueAndContext &VAC) {
11672 for (
const AA::ValueAndContext &VAC : Values) {
11673 addValue(
A, getState(), *VAC.
getValue(),
11677 if (AllInterAreIntra)
11684 HandleReturnedValue(*ReturnedArg,
nullptr,
true);
11687 bool AddValues =
true;
11690 addValue(
A, getState(), *RetI.getOperand(0), &RetI,
AA::AnyScope,
11694 return HandleReturnedValue(*RetI.getOperand(0), &RetI, AddValues);
11697 if (!
A.checkForAllInstructions(RetInstPred, *
this, {Instruction::Ret},
11698 UsedAssumedInformation,
11700 return indicatePessimisticFixpoint();
11703 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
11704 : ChangeStatus::CHANGED;
11709 return ChangeStatus::UNCHANGED;
11711 if (!getAssumedSimplifiedValues(
A, Values, AA::ValueScope::Intraprocedural,
11713 return ChangeStatus::UNCHANGED;
11714 Value *NewVal = getSingleValue(
A, *
this, getIRPosition(), Values);
11716 return ChangeStatus::UNCHANGED;
11721 "Number of function with unique return");
11724 {Attribute::get(Arg->
getContext(), Attribute::Returned)});
11729 Value *RetOp = RetI.getOperand(0);
11733 if (
A.changeUseAfterManifest(RetI.getOperandUse(0), *NewVal))
11734 Changed = ChangeStatus::CHANGED;
11737 bool UsedAssumedInformation =
false;
11738 (void)
A.checkForAllInstructions(RetInstPred, *
this, {Instruction::Ret},
11739 UsedAssumedInformation,
11745 return AAPotentialValues::indicatePessimisticFixpoint();
11749 void trackStatistics()
const override{
11756struct AAPotentialValuesFunction : AAPotentialValuesImpl {
11757 AAPotentialValuesFunction(
const IRPosition &IRP, Attributor &
A)
11758 : AAPotentialValuesImpl(IRP,
A) {}
11767 void trackStatistics()
const override {
11772struct AAPotentialValuesCallSite : AAPotentialValuesFunction {
11773 AAPotentialValuesCallSite(
const IRPosition &IRP, Attributor &
A)
11774 : AAPotentialValuesFunction(IRP,
A) {}
11777 void trackStatistics()
const override {
11782struct AAPotentialValuesCallSiteReturned : AAPotentialValuesImpl {
11783 AAPotentialValuesCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
11784 : AAPotentialValuesImpl(IRP,
A) {}
11788 auto AssumedBefore = getAssumed();
11792 return indicatePessimisticFixpoint();
11794 bool UsedAssumedInformation =
false;
11798 UsedAssumedInformation))
11799 return indicatePessimisticFixpoint();
11806 Values, S, UsedAssumedInformation))
11809 for (
auto &It : Values) {
11810 Value *
V = It.getValue();
11811 std::optional<Value *> CallerV =
A.translateArgumentToCallSiteContent(
11812 V, *CB, *
this, UsedAssumedInformation);
11813 if (!CallerV.has_value()) {
11817 V = *CallerV ? *CallerV :
V;
11823 giveUpOnIntraprocedural(
A);
11826 addValue(
A, getState(), *V, CB, S, getAnchorScope());
11831 return indicatePessimisticFixpoint();
11833 return indicatePessimisticFixpoint();
11834 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
11835 : ChangeStatus::CHANGED;
11839 return AAPotentialValues::indicatePessimisticFixpoint();
11843 void trackStatistics()
const override {
11848struct AAPotentialValuesCallSiteArgument : AAPotentialValuesFloating {
11849 AAPotentialValuesCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
11850 : AAPotentialValuesFloating(IRP,
A) {}
11853 void trackStatistics()
const override {
11861struct AAAssumptionInfoImpl :
public AAAssumptionInfo {
11862 AAAssumptionInfoImpl(
const IRPosition &IRP, Attributor &
A,
11863 const DenseSet<StringRef> &Known)
11864 : AAAssumptionInfo(IRP,
A, Known) {}
11869 if (getKnown().isUniversal())
11870 return ChangeStatus::UNCHANGED;
11872 const IRPosition &IRP = getIRPosition();
11874 getAssumed().getSet().
end());
11876 return A.manifestAttrs(IRP,
11883 bool hasAssumption(
const StringRef Assumption)
const override {
11884 return isValidState() && setContains(Assumption);
11888 const std::string getAsStr(Attributor *
A)
const override {
11889 const SetContents &Known = getKnown();
11890 const SetContents &Assumed = getAssumed();
11894 const std::string KnownStr =
llvm::join(Set,
",");
11896 std::string AssumedStr =
"Universal";
11897 if (!Assumed.isUniversal()) {
11898 Set.assign(Assumed.getSet().begin(), Assumed.getSet().end());
11901 return "Known [" + KnownStr +
"]," +
" Assumed [" + AssumedStr +
"]";
11916struct AAAssumptionInfoFunction final : AAAssumptionInfoImpl {
11917 AAAssumptionInfoFunction(
const IRPosition &IRP, Attributor &
A)
11918 : AAAssumptionInfoImpl(IRP,
A,
11925 auto CallSitePred = [&](AbstractCallSite ACS) {
11926 const auto *AssumptionAA =
A.getAAFor<AAAssumptionInfo>(
11928 DepClassTy::REQUIRED);
11932 Changed |= getIntersection(AssumptionAA->getAssumed());
11933 return !getAssumed().empty() || !getKnown().empty();
11936 bool UsedAssumedInformation =
false;
11941 if (!
A.checkForAllCallSites(CallSitePred, *
this,
true,
11942 UsedAssumedInformation))
11943 return indicatePessimisticFixpoint();
11945 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
11948 void trackStatistics()
const override {}
11952struct AAAssumptionInfoCallSite final : AAAssumptionInfoImpl {
11954 AAAssumptionInfoCallSite(
const IRPosition &IRP, Attributor &
A)
11955 : AAAssumptionInfoImpl(IRP,
A, getInitialAssumptions(IRP)) {}
11960 A.getAAFor<AAAssumptionInfo>(*
this, FnPos, DepClassTy::REQUIRED);
11966 auto *AssumptionAA =
11967 A.getAAFor<AAAssumptionInfo>(*
this, FnPos, DepClassTy::REQUIRED);
11969 return indicatePessimisticFixpoint();
11970 bool Changed = getIntersection(AssumptionAA->getAssumed());
11971 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
11975 void trackStatistics()
const override {}
11980 DenseSet<StringRef> getInitialAssumptions(
const IRPosition &IRP) {
11987 return Assumptions;
12002struct AAUnderlyingObjectsImpl
12008 const std::string getAsStr(
Attributor *
A)
const override {
12009 if (!isValidState())
12010 return "<invalid>";
12013 OS <<
"underlying objects: inter " << InterAssumedUnderlyingObjects.size()
12014 <<
" objects, intra " << IntraAssumedUnderlyingObjects.size()
12016 if (!InterAssumedUnderlyingObjects.empty()) {
12017 OS <<
"inter objects:\n";
12018 for (
auto *Obj : InterAssumedUnderlyingObjects)
12019 OS << *Obj <<
'\n';
12021 if (!IntraAssumedUnderlyingObjects.empty()) {
12022 OS <<
"intra objects:\n";
12023 for (
auto *Obj : IntraAssumedUnderlyingObjects)
12024 OS << *
Obj <<
'\n';
12030 void trackStatistics()
const override {}
12034 auto &Ptr = getAssociatedValue();
12036 bool UsedAssumedInformation =
false;
12037 auto DoUpdate = [&](SmallSetVector<Value *, 8> &UnderlyingObjects,
12039 SmallPtrSet<Value *, 8> SeenObjects;
12043 Scope, UsedAssumedInformation))
12044 return UnderlyingObjects.
insert(&Ptr);
12048 for (
unsigned I = 0;
I < Values.
size(); ++
I) {
12049 auto &VAC = Values[
I];
12052 if (!SeenObjects.
insert(UO ? UO : Obj).second)
12054 if (UO && UO != Obj) {
12060 const auto *OtherAA =
A.getAAFor<AAUnderlyingObjects>(
12062 auto Pred = [&](
Value &
V) {
12070 if (!OtherAA || !OtherAA->forallUnderlyingObjects(Pred, Scope))
12072 "The forall call should not return false at this position");
12078 Changed |= handleIndirect(
A, *Obj, UnderlyingObjects, Scope,
12079 UsedAssumedInformation);
12085 for (
unsigned u = 0, e =
PHI->getNumIncomingValues(); u < e; u++) {
12087 handleIndirect(
A, *
PHI->getIncomingValue(u), UnderlyingObjects,
12088 Scope, UsedAssumedInformation);
12102 if (!UsedAssumedInformation)
12103 indicateOptimisticFixpoint();
12104 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
12107 bool forallUnderlyingObjects(
12108 function_ref<
bool(
Value &)> Pred,
12110 if (!isValidState())
12111 return Pred(getAssociatedValue());
12114 ? IntraAssumedUnderlyingObjects
12115 : InterAssumedUnderlyingObjects;
12116 for (
Value *Obj : AssumedUnderlyingObjects)
12126 bool handleIndirect(Attributor &
A,
Value &V,
12127 SmallSetVector<Value *, 8> &UnderlyingObjects,
12130 const auto *AA =
A.getAAFor<AAUnderlyingObjects>(
12132 auto Pred = [&](
Value &
V) {
12136 if (!AA || !AA->forallUnderlyingObjects(Pred, Scope))
12138 "The forall call should not return false at this position");
12144 SmallSetVector<Value *, 8> IntraAssumedUnderlyingObjects;
12146 SmallSetVector<Value *, 8> InterAssumedUnderlyingObjects;
12149struct AAUnderlyingObjectsFloating final : AAUnderlyingObjectsImpl {
12150 AAUnderlyingObjectsFloating(
const IRPosition &IRP, Attributor &
A)
12151 : AAUnderlyingObjectsImpl(IRP,
A) {}
12154struct AAUnderlyingObjectsArgument final : AAUnderlyingObjectsImpl {
12155 AAUnderlyingObjectsArgument(
const IRPosition &IRP, Attributor &
A)
12156 : AAUnderlyingObjectsImpl(IRP,
A) {}
12159struct AAUnderlyingObjectsCallSite final : AAUnderlyingObjectsImpl {
12160 AAUnderlyingObjectsCallSite(
const IRPosition &IRP, Attributor &
A)
12161 : AAUnderlyingObjectsImpl(IRP,
A) {}
12164struct AAUnderlyingObjectsCallSiteArgument final : AAUnderlyingObjectsImpl {
12165 AAUnderlyingObjectsCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
12166 : AAUnderlyingObjectsImpl(IRP,
A) {}
12169struct AAUnderlyingObjectsReturned final : AAUnderlyingObjectsImpl {
12170 AAUnderlyingObjectsReturned(
const IRPosition &IRP, Attributor &
A)
12171 : AAUnderlyingObjectsImpl(IRP,
A) {}
12174struct AAUnderlyingObjectsCallSiteReturned final : AAUnderlyingObjectsImpl {
12175 AAUnderlyingObjectsCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
12176 : AAUnderlyingObjectsImpl(IRP,
A) {}
12179struct AAUnderlyingObjectsFunction final : AAUnderlyingObjectsImpl {
12180 AAUnderlyingObjectsFunction(
const IRPosition &IRP, Attributor &
A)
12181 : AAUnderlyingObjectsImpl(IRP,
A) {}
12187struct AAGlobalValueInfoFloating :
public AAGlobalValueInfo {
12188 AAGlobalValueInfoFloating(
const IRPosition &IRP, Attributor &
A)
12189 : AAGlobalValueInfo(IRP,
A) {}
12194 bool checkUse(Attributor &
A,
const Use &U,
bool &Follow,
12195 SmallVectorImpl<const Value *> &Worklist) {
12202 LLVM_DEBUG(
dbgs() <<
"[AAGlobalValueInfo] Check use: " << *
U.get() <<
" in "
12203 << *UInst <<
"\n");
12206 int Idx = &
Cmp->getOperandUse(0) == &
U;
12209 return U == &getAnchorValue();
12214 auto CallSitePred = [&](AbstractCallSite ACS) {
12215 Worklist.
push_back(ACS.getInstruction());
12218 bool UsedAssumedInformation =
false;
12220 if (!
A.checkForAllCallSites(CallSitePred, *UInst->
getFunction(),
12222 UsedAssumedInformation))
12240 if (!Fn || !
A.isFunctionIPOAmendable(*Fn))
12249 unsigned NumUsesBefore =
Uses.size();
12251 SmallPtrSet<const Value *, 8> Visited;
12255 auto UsePred = [&](
const Use &
U,
bool &Follow) ->
bool {
12263 return checkUse(
A, U, Follow, Worklist);
12265 auto EquivalentUseCB = [&](
const Use &OldU,
const Use &NewU) {
12266 Uses.insert(&OldU);
12270 while (!Worklist.
empty()) {
12272 if (!Visited.
insert(V).second)
12274 if (!
A.checkForAllUses(UsePred, *
this, *V,
12276 DepClassTy::OPTIONAL,
12277 true, EquivalentUseCB)) {
12278 return indicatePessimisticFixpoint();
12282 return Uses.size() == NumUsesBefore ? ChangeStatus::UNCHANGED
12283 : ChangeStatus::CHANGED;
12286 bool isPotentialUse(
const Use &U)
const override {
12287 return !isValidState() ||
Uses.contains(&U);
12292 return ChangeStatus::UNCHANGED;
12296 const std::string getAsStr(Attributor *
A)
const override {
12297 return "[" + std::to_string(
Uses.size()) +
" uses]";
12300 void trackStatistics()
const override {
12306 SmallPtrSet<const Use *, 8>
Uses;
12312struct AAIndirectCallInfoCallSite :
public AAIndirectCallInfo {
12313 AAIndirectCallInfoCallSite(
const IRPosition &IRP, Attributor &
A)
12314 : AAIndirectCallInfo(IRP,
A) {}
12318 auto *MD = getCtxI()->getMetadata(LLVMContext::MD_callees);
12319 if (!MD && !
A.isClosedWorldModule())
12323 for (
const auto &
Op : MD->operands())
12325 PotentialCallees.insert(Callee);
12326 }
else if (
A.isClosedWorldModule()) {
12328 A.getInfoCache().getIndirectlyCallableFunctions(
A);
12329 PotentialCallees.insert_range(IndirectlyCallableFunctions);
12332 if (PotentialCallees.empty())
12333 indicateOptimisticFixpoint();
12341 SmallSetVector<Function *, 4> AssumedCalleesNow;
12342 bool AllCalleesKnownNow = AllCalleesKnown;
12344 auto CheckPotentialCalleeUse = [&](
Function &PotentialCallee,
12345 bool &UsedAssumedInformation) {
12346 const auto *GIAA =
A.getAAFor<AAGlobalValueInfo>(
12348 if (!GIAA || GIAA->isPotentialUse(CalleeUse))
12350 UsedAssumedInformation = !GIAA->isAtFixpoint();
12354 auto AddPotentialCallees = [&]() {
12355 for (
auto *PotentialCallee : PotentialCallees) {
12356 bool UsedAssumedInformation =
false;
12357 if (CheckPotentialCalleeUse(*PotentialCallee, UsedAssumedInformation))
12358 AssumedCalleesNow.
insert(PotentialCallee);
12364 bool UsedAssumedInformation =
false;
12367 AA::ValueScope::AnyScope,
12368 UsedAssumedInformation)) {
12369 if (PotentialCallees.empty())
12370 return indicatePessimisticFixpoint();
12371 AddPotentialCallees();
12376 auto CheckPotentialCallee = [&](
Function &Fn) {
12377 if (!PotentialCallees.empty() && !PotentialCallees.count(&Fn))
12380 auto &CachedResult = FilterResults[&Fn];
12381 if (CachedResult.has_value())
12382 return CachedResult.value();
12384 bool UsedAssumedInformation =
false;
12385 if (!CheckPotentialCalleeUse(Fn, UsedAssumedInformation)) {
12386 if (!UsedAssumedInformation)
12387 CachedResult =
false;
12396 for (
int I = NumCBArgs;
I < NumFnArgs; ++
I) {
12397 bool IsKnown =
false;
12400 DepClassTy::OPTIONAL, IsKnown)) {
12402 CachedResult =
false;
12407 CachedResult =
true;
12413 for (
auto &VAC : Values) {
12421 if (CheckPotentialCallee(*VACFn))
12422 AssumedCalleesNow.
insert(VACFn);
12425 if (!PotentialCallees.empty()) {
12426 AddPotentialCallees();
12429 AllCalleesKnownNow =
false;
12432 if (AssumedCalleesNow == AssumedCallees &&
12433 AllCalleesKnown == AllCalleesKnownNow)
12434 return ChangeStatus::UNCHANGED;
12436 std::swap(AssumedCallees, AssumedCalleesNow);
12437 AllCalleesKnown = AllCalleesKnownNow;
12438 return ChangeStatus::CHANGED;
12444 if (!AllCalleesKnown && AssumedCallees.empty())
12445 return ChangeStatus::UNCHANGED;
12448 bool UsedAssumedInformation =
false;
12449 if (
A.isAssumedDead(*CB,
this,
nullptr,
12450 UsedAssumedInformation))
12451 return ChangeStatus::UNCHANGED;
12455 if (
FP->getType()->getPointerAddressSpace())
12456 FP =
new AddrSpaceCastInst(
FP, PointerType::get(
FP->getContext(), 0),
12466 if (AssumedCallees.empty()) {
12467 assert(AllCalleesKnown &&
12468 "Expected all callees to be known if there are none.");
12469 A.changeToUnreachableAfterManifest(CB);
12470 return ChangeStatus::CHANGED;
12474 if (AllCalleesKnown && AssumedCallees.size() == 1) {
12475 auto *NewCallee = AssumedCallees.front();
12478 NumIndirectCallsPromoted++;
12479 return ChangeStatus::CHANGED;
12486 A.deleteAfterManifest(*CB);
12487 return ChangeStatus::CHANGED;
12497 bool SpecializedForAnyCallees =
false;
12498 bool SpecializedForAllCallees = AllCalleesKnown;
12499 ICmpInst *LastCmp =
nullptr;
12502 for (Function *NewCallee : AssumedCallees) {
12503 if (!
A.shouldSpecializeCallSiteForCallee(*
this, *CB, *NewCallee,
12504 AssumedCallees.size())) {
12505 SkippedAssumedCallees.
push_back(NewCallee);
12506 SpecializedForAllCallees =
false;
12509 SpecializedForAnyCallees =
true;
12515 A.registerManifestAddedBasicBlock(*ThenTI->
getParent());
12516 A.registerManifestAddedBasicBlock(*IP->getParent());
12522 A.registerManifestAddedBasicBlock(*ElseBB);
12524 SplitTI->replaceUsesOfWith(CBBB, ElseBB);
12529 CastInst *RetBC =
nullptr;
12530 CallInst *NewCall =
nullptr;
12535 NumIndirectCallsPromoted++;
12543 auto AttachCalleeMetadata = [&](CallBase &IndirectCB) {
12544 if (!AllCalleesKnown)
12545 return ChangeStatus::UNCHANGED;
12546 MDBuilder MDB(IndirectCB.getContext());
12547 MDNode *Callees = MDB.createCallees(SkippedAssumedCallees);
12548 IndirectCB.setMetadata(LLVMContext::MD_callees, Callees);
12549 return ChangeStatus::CHANGED;
12552 if (!SpecializedForAnyCallees)
12553 return AttachCalleeMetadata(*CB);
12556 if (SpecializedForAllCallees) {
12559 new UnreachableInst(IP->getContext(), IP);
12560 IP->eraseFromParent();
12563 CBClone->setName(CB->
getName());
12564 CBClone->insertBefore(*IP->getParent(), IP);
12565 NewCalls.
push_back({CBClone,
nullptr});
12566 AttachCalleeMetadata(*CBClone);
12573 CB->
getParent()->getFirstInsertionPt());
12574 for (
auto &It : NewCalls) {
12575 CallBase *NewCall = It.first;
12576 Instruction *CallRet = It.second ? It.second : It.first;
12588 A.deleteAfterManifest(*CB);
12589 Changed = ChangeStatus::CHANGED;
12595 const std::string getAsStr(Attributor *
A)
const override {
12596 return std::string(AllCalleesKnown ?
"eliminate" :
"specialize") +
12597 " indirect call site with " + std::to_string(AssumedCallees.size()) +
12601 void trackStatistics()
const override {
12602 if (AllCalleesKnown) {
12604 Eliminated, CallSites,
12605 "Number of indirect call sites eliminated via specialization")
12608 "Number of indirect call sites specialized")
12612 bool foreachCallee(function_ref<
bool(Function *)> CB)
const override {
12613 return isValidState() && AllCalleesKnown &&
all_of(AssumedCallees, CB);
12618 DenseMap<Function *, std::optional<bool>> FilterResults;
12622 SmallSetVector<Function *, 4> PotentialCallees;
12626 SmallSetVector<Function *, 4> AssumedCallees;
12630 bool AllCalleesKnown =
true;
12637struct AAInvariantLoadPointerImpl
12638 :
public StateWrapper<BitIntegerState<uint8_t, 15>,
12639 AAInvariantLoadPointer> {
12643 IS_NOALIAS = 1 << 0,
12646 IS_NOEFFECT = 1 << 1,
12648 IS_LOCALLY_INVARIANT = 1 << 2,
12650 IS_LOCALLY_CONSTRAINED = 1 << 3,
12652 IS_BEST_STATE = IS_NOALIAS | IS_NOEFFECT | IS_LOCALLY_INVARIANT |
12653 IS_LOCALLY_CONSTRAINED,
12655 static_assert(getBestState() == IS_BEST_STATE,
"Unexpected best state");
12658 StateWrapper<BitIntegerState<uint8_t, 15>, AAInvariantLoadPointer>;
12662 AAInvariantLoadPointerImpl(
const IRPosition &IRP, Attributor &
A)
12665 bool isKnownInvariant()
const final {
12666 return isKnownLocallyInvariant() && isKnown(IS_LOCALLY_CONSTRAINED);
12669 bool isKnownLocallyInvariant()
const final {
12670 if (isKnown(IS_LOCALLY_INVARIANT))
12672 return isKnown(IS_NOALIAS | IS_NOEFFECT);
12675 bool isAssumedInvariant()
const final {
12676 return isAssumedLocallyInvariant() && isAssumed(IS_LOCALLY_CONSTRAINED);
12679 bool isAssumedLocallyInvariant()
const final {
12680 if (isAssumed(IS_LOCALLY_INVARIANT))
12682 return isAssumed(IS_NOALIAS | IS_NOEFFECT);
12689 if (requiresNoAlias() && !isAssumed(IS_NOALIAS))
12690 return indicatePessimisticFixpoint();
12694 Changed |= updateLocalInvariance(
A);
12700 if (!isKnownInvariant())
12701 return ChangeStatus::UNCHANGED;
12704 const Value *Ptr = &getAssociatedValue();
12705 const auto TagInvariantLoads = [&](
const Use &
U,
bool &) {
12706 if (
U.get() != Ptr)
12714 if (!
A.isRunOn(
I->getFunction()))
12717 if (
I->hasMetadata(LLVMContext::MD_invariant_load))
12721 LI->setMetadata(LLVMContext::MD_invariant_load,
12723 Changed = ChangeStatus::CHANGED;
12728 (void)
A.checkForAllUses(TagInvariantLoads, *
this, *Ptr);
12733 const std::string getAsStr(Attributor *)
const override {
12734 if (isKnownInvariant())
12735 return "load-invariant pointer";
12736 return "non-invariant pointer";
12740 void trackStatistics()
const override {}
12744 bool requiresNoAlias()
const {
12745 switch (getPositionKind()) {
12751 case IRP_CALL_SITE:
12753 case IRP_CALL_SITE_RETURNED: {
12758 case IRP_ARGUMENT: {
12759 const Function *
F = getAssociatedFunction();
12760 assert(
F &&
"no associated function for argument");
12766 bool isExternal()
const {
12767 const Function *
F = getAssociatedFunction();
12771 getPositionKind() != IRP_CALL_SITE_RETURNED;
12775 if (isKnown(IS_NOALIAS) || !isAssumed(IS_NOALIAS))
12776 return ChangeStatus::UNCHANGED;
12779 if (
const auto *ANoAlias =
A.getOrCreateAAFor<AANoAlias>(
12780 getIRPosition(),
this, DepClassTy::REQUIRED)) {
12781 if (ANoAlias->isKnownNoAlias()) {
12782 addKnownBits(IS_NOALIAS);
12783 return ChangeStatus::CHANGED;
12786 if (!ANoAlias->isAssumedNoAlias()) {
12787 removeAssumedBits(IS_NOALIAS);
12788 return ChangeStatus::CHANGED;
12791 return ChangeStatus::UNCHANGED;
12796 if (
const Argument *Arg = getAssociatedArgument()) {
12798 addKnownBits(IS_NOALIAS);
12799 return ChangeStatus::UNCHANGED;
12804 removeAssumedBits(IS_NOALIAS);
12805 return ChangeStatus::CHANGED;
12808 return ChangeStatus::UNCHANGED;
12812 if (isKnown(IS_NOEFFECT) || !isAssumed(IS_NOEFFECT))
12813 return ChangeStatus::UNCHANGED;
12815 if (!getAssociatedFunction())
12816 return indicatePessimisticFixpoint();
12819 return indicatePessimisticFixpoint();
12821 const auto HasNoEffectLoads = [&](
const Use &
U,
bool &) {
12823 return !LI || !LI->mayHaveSideEffects();
12825 if (!
A.checkForAllUses(HasNoEffectLoads, *
this, getAssociatedValue()))
12826 return indicatePessimisticFixpoint();
12828 if (
const auto *AMemoryBehavior =
A.getOrCreateAAFor<AAMemoryBehavior>(
12829 getIRPosition(),
this, DepClassTy::REQUIRED)) {
12832 if (!AMemoryBehavior->isAssumedReadOnly())
12833 return indicatePessimisticFixpoint();
12835 if (AMemoryBehavior->isKnownReadOnly()) {
12836 addKnownBits(IS_NOEFFECT);
12837 return ChangeStatus::UNCHANGED;
12840 return ChangeStatus::UNCHANGED;
12843 if (
const Argument *Arg = getAssociatedArgument()) {
12845 addKnownBits(IS_NOEFFECT);
12846 return ChangeStatus::UNCHANGED;
12851 return indicatePessimisticFixpoint();
12854 return ChangeStatus::UNCHANGED;
12858 if (isKnown(IS_LOCALLY_INVARIANT) || !isAssumed(IS_LOCALLY_INVARIANT))
12859 return ChangeStatus::UNCHANGED;
12862 const auto *AUO =
A.getOrCreateAAFor<AAUnderlyingObjects>(
12863 getIRPosition(),
this, DepClassTy::REQUIRED);
12865 return ChangeStatus::UNCHANGED;
12867 bool UsedAssumedInformation =
false;
12868 const auto IsLocallyInvariantLoadIfPointer = [&](
const Value &
V) {
12869 if (!
V.getType()->isPointerTy())
12871 const auto *IsInvariantLoadPointer =
12873 DepClassTy::REQUIRED);
12875 if (!IsInvariantLoadPointer)
12878 if (IsInvariantLoadPointer->isKnownLocallyInvariant())
12880 if (!IsInvariantLoadPointer->isAssumedLocallyInvariant())
12883 UsedAssumedInformation =
true;
12886 if (!AUO->forallUnderlyingObjects(IsLocallyInvariantLoadIfPointer))
12887 return indicatePessimisticFixpoint();
12893 if (!IsLocallyInvariantLoadIfPointer(*Arg))
12894 return indicatePessimisticFixpoint();
12899 if (!UsedAssumedInformation) {
12901 addKnownBits(IS_LOCALLY_INVARIANT);
12902 return ChangeStatus::CHANGED;
12905 return ChangeStatus::UNCHANGED;
12909struct AAInvariantLoadPointerFloating final : AAInvariantLoadPointerImpl {
12910 AAInvariantLoadPointerFloating(
const IRPosition &IRP, Attributor &
A)
12911 : AAInvariantLoadPointerImpl(IRP,
A) {}
12914struct AAInvariantLoadPointerReturned final : AAInvariantLoadPointerImpl {
12915 AAInvariantLoadPointerReturned(
const IRPosition &IRP, Attributor &
A)
12916 : AAInvariantLoadPointerImpl(IRP,
A) {}
12919 removeAssumedBits(IS_LOCALLY_CONSTRAINED);
12923struct AAInvariantLoadPointerCallSiteReturned final
12924 : AAInvariantLoadPointerImpl {
12925 AAInvariantLoadPointerCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
12926 : AAInvariantLoadPointerImpl(IRP,
A) {}
12929 const Function *
F = getAssociatedFunction();
12930 assert(
F &&
"no associated function for return from call");
12932 if (!
F->isDeclaration() && !
F->isIntrinsic())
12933 return AAInvariantLoadPointerImpl::initialize(
A);
12938 return AAInvariantLoadPointerImpl::initialize(
A);
12940 if (
F->onlyReadsMemory() &&
F->hasNoSync())
12941 return AAInvariantLoadPointerImpl::initialize(
A);
12945 indicatePessimisticFixpoint();
12949struct AAInvariantLoadPointerArgument final : AAInvariantLoadPointerImpl {
12950 AAInvariantLoadPointerArgument(
const IRPosition &IRP, Attributor &
A)
12951 : AAInvariantLoadPointerImpl(IRP,
A) {}
12954 const Function *
F = getAssociatedFunction();
12955 assert(
F &&
"no associated function for argument");
12958 addKnownBits(IS_LOCALLY_CONSTRAINED);
12962 if (!
F->hasLocalLinkage())
12963 removeAssumedBits(IS_LOCALLY_CONSTRAINED);
12967struct AAInvariantLoadPointerCallSiteArgument final
12968 : AAInvariantLoadPointerImpl {
12969 AAInvariantLoadPointerCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
12970 : AAInvariantLoadPointerImpl(IRP,
A) {}
12977template <
typename InstType>
12978static bool makeChange(Attributor &
A, InstType *MemInst,
const Use &U,
12979 Value *OriginalValue, PointerType *NewPtrTy,
12980 bool UseOriginalValue) {
12981 if (
U.getOperandNo() != InstType::getPointerOperandIndex())
12984 if (MemInst->isVolatile()) {
12985 auto *
TTI =
A.getInfoCache().getAnalysisResultForFunction<TargetIRAnalysis>(
12986 *MemInst->getFunction());
12987 unsigned NewAS = NewPtrTy->getPointerAddressSpace();
12992 if (UseOriginalValue) {
12993 A.changeUseAfterManifest(
const_cast<Use &
>(U), *OriginalValue);
12997 Instruction *CastInst =
new AddrSpaceCastInst(OriginalValue, NewPtrTy);
12999 A.changeUseAfterManifest(
const_cast<Use &
>(U), *CastInst);
13003struct AAAddressSpaceImpl :
public AAAddressSpace {
13004 AAAddressSpaceImpl(
const IRPosition &IRP, Attributor &
A)
13005 : AAAddressSpace(IRP,
A) {}
13008 assert(isValidState() &&
"the AA is invalid");
13009 return AssumedAddressSpace;
13014 assert(getAssociatedType()->isPtrOrPtrVectorTy() &&
13015 "Associated value is not a pointer");
13017 if (!
A.getInfoCache().getFlatAddressSpace().has_value()) {
13018 indicatePessimisticFixpoint();
13022 unsigned FlatAS =
A.getInfoCache().getFlatAddressSpace().value();
13023 unsigned AS = getAssociatedType()->getPointerAddressSpace();
13024 if (AS != FlatAS) {
13025 [[maybe_unused]]
bool R = takeAddressSpace(AS);
13026 assert(R &&
"The take should happen");
13027 indicateOptimisticFixpoint();
13032 uint32_t OldAddressSpace = AssumedAddressSpace;
13033 unsigned FlatAS =
A.getInfoCache().getFlatAddressSpace().value();
13035 auto CheckAddressSpace = [&](
Value &
Obj) {
13041 unsigned ObjAS =
Obj.getType()->getPointerAddressSpace();
13042 if (ObjAS != FlatAS)
13043 return takeAddressSpace(ObjAS);
13057 A.getInfoCache().getAnalysisResultForFunction<TargetIRAnalysis>(*F);
13059 if (AssumedAS != ~0U)
13060 return takeAddressSpace(AssumedAS);
13064 return takeAddressSpace(FlatAS);
13067 auto *AUO =
A.getOrCreateAAFor<AAUnderlyingObjects>(getIRPosition(),
this,
13068 DepClassTy::REQUIRED);
13069 if (!AUO->forallUnderlyingObjects(CheckAddressSpace))
13070 return indicatePessimisticFixpoint();
13072 return OldAddressSpace == AssumedAddressSpace ? ChangeStatus::UNCHANGED
13073 : ChangeStatus::CHANGED;
13080 if (NewAS == InvalidAddressSpace ||
13082 return ChangeStatus::UNCHANGED;
13084 unsigned FlatAS =
A.getInfoCache().getFlatAddressSpace().value();
13086 Value *AssociatedValue = &getAssociatedValue();
13087 Value *OriginalValue = peelAddrspacecast(AssociatedValue, FlatAS);
13090 PointerType::get(getAssociatedType()->
getContext(), NewAS);
13091 bool UseOriginalValue =
13096 auto Pred = [&](
const Use &
U,
bool &) {
13097 if (
U.get() != AssociatedValue)
13108 makeChange(
A, LI, U, OriginalValue, NewPtrTy, UseOriginalValue);
13111 makeChange(
A, SI, U, OriginalValue, NewPtrTy, UseOriginalValue);
13114 makeChange(
A, RMW, U, OriginalValue, NewPtrTy, UseOriginalValue);
13117 makeChange(
A, CmpX, U, OriginalValue, NewPtrTy, UseOriginalValue);
13124 (void)
A.checkForAllUses(Pred, *
this, getAssociatedValue(),
13127 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
13131 const std::string getAsStr(Attributor *
A)
const override {
13132 if (!isValidState())
13133 return "addrspace(<invalid>)";
13134 return "addrspace(" +
13135 (AssumedAddressSpace == InvalidAddressSpace
13137 : std::to_string(AssumedAddressSpace)) +
13142 uint32_t AssumedAddressSpace = InvalidAddressSpace;
13144 bool takeAddressSpace(uint32_t AS) {
13145 if (AssumedAddressSpace == InvalidAddressSpace) {
13146 AssumedAddressSpace = AS;
13149 return AssumedAddressSpace == AS;
13152 static Value *peelAddrspacecast(
Value *V,
unsigned FlatAS) {
13154 assert(
I->getSrcAddressSpace() != FlatAS &&
13155 "there should not be flat AS -> non-flat AS");
13156 return I->getPointerOperand();
13159 if (
C->getOpcode() == Instruction::AddrSpaceCast) {
13160 assert(
C->getOperand(0)->getType()->getPointerAddressSpace() !=
13162 "there should not be flat AS -> non-flat AS X");
13163 return C->getOperand(0);
13169struct AAAddressSpaceFloating final : AAAddressSpaceImpl {
13170 AAAddressSpaceFloating(
const IRPosition &IRP, Attributor &
A)
13171 : AAAddressSpaceImpl(IRP,
A) {}
13173 void trackStatistics()
const override {
13178struct AAAddressSpaceReturned final : AAAddressSpaceImpl {
13179 AAAddressSpaceReturned(
const IRPosition &IRP, Attributor &
A)
13180 : AAAddressSpaceImpl(IRP,
A) {}
13186 (void)indicatePessimisticFixpoint();
13189 void trackStatistics()
const override {
13194struct AAAddressSpaceCallSiteReturned final : AAAddressSpaceImpl {
13195 AAAddressSpaceCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
13196 : AAAddressSpaceImpl(IRP,
A) {}
13198 void trackStatistics()
const override {
13203struct AAAddressSpaceArgument final : AAAddressSpaceImpl {
13204 AAAddressSpaceArgument(
const IRPosition &IRP, Attributor &
A)
13205 : AAAddressSpaceImpl(IRP,
A) {}
13210struct AAAddressSpaceCallSiteArgument final : AAAddressSpaceImpl {
13211 AAAddressSpaceCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
13212 : AAAddressSpaceImpl(IRP,
A) {}
13218 (void)indicatePessimisticFixpoint();
13221 void trackStatistics()
const override {
13236struct AANoAliasAddrSpaceImpl :
public AANoAliasAddrSpace {
13237 AANoAliasAddrSpaceImpl(
const IRPosition &IRP, Attributor &
A)
13238 : AANoAliasAddrSpace(IRP,
A) {}
13241 assert(getAssociatedType()->isPtrOrPtrVectorTy() &&
13242 "Associated value is not a pointer");
13246 std::optional<unsigned> FlatAS =
A.getInfoCache().getFlatAddressSpace();
13247 if (!FlatAS.has_value()) {
13248 indicatePessimisticFixpoint();
13254 unsigned AS = getAssociatedType()->getPointerAddressSpace();
13255 if (AS != *FlatAS) {
13257 indicateOptimisticFixpoint();
13262 unsigned FlatAS =
A.getInfoCache().getFlatAddressSpace().value();
13263 uint32_t OldAssumed = getAssumed();
13265 auto CheckAddressSpace = [&](
Value &
Obj) {
13269 unsigned AS =
Obj.getType()->getPointerAddressSpace();
13273 removeAS(
Obj.getType()->getPointerAddressSpace());
13277 const AAUnderlyingObjects *AUO =
A.getOrCreateAAFor<AAUnderlyingObjects>(
13278 getIRPosition(),
this, DepClassTy::REQUIRED);
13280 return indicatePessimisticFixpoint();
13282 return OldAssumed == getAssumed() ? ChangeStatus::UNCHANGED
13283 : ChangeStatus::CHANGED;
13288 unsigned FlatAS =
A.getInfoCache().getFlatAddressSpace().value();
13290 unsigned AS = getAssociatedType()->getPointerAddressSpace();
13291 if (AS != FlatAS ||
Map.empty())
13292 return ChangeStatus::UNCHANGED;
13294 LLVMContext &Ctx = getAssociatedValue().getContext();
13295 MDNode *NoAliasASNode =
nullptr;
13296 MDBuilder MDB(Ctx);
13298 for (RangeMap::const_iterator
I =
Map.begin();
I !=
Map.end();
I++) {
13301 unsigned Upper =
I.stop();
13302 unsigned Lower =
I.start();
13303 if (!NoAliasASNode) {
13304 NoAliasASNode = MDB.createRange(APInt(32,
Lower), APInt(32,
Upper + 1));
13307 MDNode *ASRange = MDB.createRange(APInt(32,
Lower), APInt(32,
Upper + 1));
13311 Value *AssociatedValue = &getAssociatedValue();
13314 auto AddNoAliasAttr = [&](
const Use &
U,
bool &) {
13315 if (
U.get() != AssociatedValue)
13318 if (!Inst || Inst->
hasMetadata(LLVMContext::MD_noalias_addrspace))
13325 Inst->
setMetadata(LLVMContext::MD_noalias_addrspace, NoAliasASNode);
13329 (void)
A.checkForAllUses(AddNoAliasAttr, *
this, *AssociatedValue,
13331 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
13335 const std::string getAsStr(Attributor *
A)
const override {
13336 if (!isValidState())
13337 return "<invalid>";
13339 raw_string_ostream OS(Str);
13340 OS <<
"CanNotBeAddrSpace(";
13341 for (RangeMap::const_iterator
I =
Map.begin();
I !=
Map.end();
I++) {
13342 unsigned Upper =
I.stop();
13343 unsigned Lower =
I.start();
13344 OS <<
' ' <<
'[' <<
Upper <<
',' <<
Lower + 1 <<
')';
13351 void removeAS(
unsigned AS) {
13352 RangeMap::iterator
I =
Map.find(AS);
13354 if (
I !=
Map.end()) {
13355 unsigned Upper =
I.stop();
13356 unsigned Lower =
I.start();
13360 if (AS != ~((
unsigned)0) && AS + 1 <=
Upper)
13362 if (AS != 0 &&
Lower <= AS - 1)
13367 void resetASRanges(Attributor &
A) {
13369 Map.insert(0,
A.getInfoCache().getMaxAddrSpace(),
true);
13373struct AANoAliasAddrSpaceFloating final : AANoAliasAddrSpaceImpl {
13374 AANoAliasAddrSpaceFloating(
const IRPosition &IRP, Attributor &
A)
13375 : AANoAliasAddrSpaceImpl(IRP,
A) {}
13377 void trackStatistics()
const override {
13382struct AANoAliasAddrSpaceReturned final : AANoAliasAddrSpaceImpl {
13383 AANoAliasAddrSpaceReturned(
const IRPosition &IRP, Attributor &
A)
13384 : AANoAliasAddrSpaceImpl(IRP,
A) {}
13386 void trackStatistics()
const override {
13391struct AANoAliasAddrSpaceCallSiteReturned final : AANoAliasAddrSpaceImpl {
13392 AANoAliasAddrSpaceCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
13393 : AANoAliasAddrSpaceImpl(IRP,
A) {}
13395 void trackStatistics()
const override {
13400struct AANoAliasAddrSpaceArgument final : AANoAliasAddrSpaceImpl {
13401 AANoAliasAddrSpaceArgument(
const IRPosition &IRP, Attributor &
A)
13402 : AANoAliasAddrSpaceImpl(IRP,
A) {}
13404 void trackStatistics()
const override {
13409struct AANoAliasAddrSpaceCallSiteArgument final : AANoAliasAddrSpaceImpl {
13410 AANoAliasAddrSpaceCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
13411 : AANoAliasAddrSpaceImpl(IRP,
A) {}
13413 void trackStatistics()
const override {
13420struct AAAllocationInfoImpl :
public AAAllocationInfo {
13421 AAAllocationInfoImpl(
const IRPosition &IRP, Attributor &
A)
13422 : AAAllocationInfo(IRP,
A) {}
13424 std::optional<TypeSize> getAllocatedSize()
const override {
13425 assert(isValidState() &&
"the AA is invalid");
13426 return AssumedAllocatedSize;
13429 std::optional<TypeSize> findInitialAllocationSize(Instruction *
I,
13430 const DataLayout &
DL) {
13433 switch (
I->getOpcode()) {
13434 case Instruction::Alloca: {
13439 return std::nullopt;
13445 const IRPosition &IRP = getIRPosition();
13450 return indicatePessimisticFixpoint();
13452 bool IsKnownNoCapture;
13454 A,
this, IRP, DepClassTy::OPTIONAL, IsKnownNoCapture))
13455 return indicatePessimisticFixpoint();
13457 const AAPointerInfo *PI =
13458 A.getOrCreateAAFor<AAPointerInfo>(IRP, *
this, DepClassTy::REQUIRED);
13461 return indicatePessimisticFixpoint();
13464 return indicatePessimisticFixpoint();
13466 const DataLayout &
DL =
A.getDataLayout();
13467 const auto AllocationSize = findInitialAllocationSize(
I,
DL);
13470 if (!AllocationSize)
13471 return indicatePessimisticFixpoint();
13475 if (*AllocationSize == 0)
13476 return indicatePessimisticFixpoint();
13482 return indicatePessimisticFixpoint();
13484 if (BinSize == 0) {
13485 auto NewAllocationSize = std::make_optional<TypeSize>(0,
false);
13486 if (!changeAllocationSize(NewAllocationSize))
13487 return ChangeStatus::UNCHANGED;
13488 return ChangeStatus::CHANGED;
13492 const auto &It = PI->
begin();
13495 if (It->first.Offset != 0)
13496 return indicatePessimisticFixpoint();
13498 uint64_t SizeOfBin = It->first.Offset + It->first.Size;
13500 if (SizeOfBin >= *AllocationSize)
13501 return indicatePessimisticFixpoint();
13503 auto NewAllocationSize = std::make_optional<TypeSize>(SizeOfBin * 8,
false);
13505 if (!changeAllocationSize(NewAllocationSize))
13506 return ChangeStatus::UNCHANGED;
13508 return ChangeStatus::CHANGED;
13514 assert(isValidState() &&
13515 "Manifest should only be called if the state is valid.");
13519 auto FixedAllocatedSizeInBits = getAllocatedSize()->getFixedValue();
13521 unsigned long NumBytesToAllocate = (FixedAllocatedSizeInBits + 7) / 8;
13523 switch (
I->getOpcode()) {
13525 case Instruction::Alloca: {
13529 Type *CharType = Type::getInt8Ty(
I->getContext());
13531 auto *NumBytesToValue =
13532 ConstantInt::get(
I->getContext(), APInt(32, NumBytesToAllocate));
13535 insertPt = std::next(insertPt);
13536 AllocaInst *NewAllocaInst =
13541 return ChangeStatus::CHANGED;
13549 return ChangeStatus::UNCHANGED;
13553 const std::string getAsStr(Attributor *
A)
const override {
13554 if (!isValidState())
13555 return "allocationinfo(<invalid>)";
13556 return "allocationinfo(" +
13557 (AssumedAllocatedSize == HasNoAllocationSize
13559 : std::to_string(AssumedAllocatedSize->getFixedValue())) +
13564 std::optional<TypeSize> AssumedAllocatedSize = HasNoAllocationSize;
13568 bool changeAllocationSize(std::optional<TypeSize>
Size) {
13569 if (AssumedAllocatedSize == HasNoAllocationSize ||
13570 AssumedAllocatedSize !=
Size) {
13571 AssumedAllocatedSize =
Size;
13578struct AAAllocationInfoFloating : AAAllocationInfoImpl {
13579 AAAllocationInfoFloating(
const IRPosition &IRP, Attributor &
A)
13580 : AAAllocationInfoImpl(IRP,
A) {}
13582 void trackStatistics()
const override {
13587struct AAAllocationInfoReturned : AAAllocationInfoImpl {
13588 AAAllocationInfoReturned(
const IRPosition &IRP, Attributor &
A)
13589 : AAAllocationInfoImpl(IRP,
A) {}
13595 (void)indicatePessimisticFixpoint();
13598 void trackStatistics()
const override {
13603struct AAAllocationInfoCallSiteReturned : AAAllocationInfoImpl {
13604 AAAllocationInfoCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
13605 : AAAllocationInfoImpl(IRP,
A) {}
13607 void trackStatistics()
const override {
13612struct AAAllocationInfoArgument : AAAllocationInfoImpl {
13613 AAAllocationInfoArgument(
const IRPosition &IRP, Attributor &
A)
13614 : AAAllocationInfoImpl(IRP,
A) {}
13616 void trackStatistics()
const override {
13621struct AAAllocationInfoCallSiteArgument : AAAllocationInfoImpl {
13622 AAAllocationInfoCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
13623 : AAAllocationInfoImpl(IRP,
A) {}
13628 (void)indicatePessimisticFixpoint();
13631 void trackStatistics()
const override {
13680#define SWITCH_PK_INV(CLASS, PK, POS_NAME) \
13681 case IRPosition::PK: \
13682 llvm_unreachable("Cannot create " #CLASS " for a " POS_NAME " position!");
13684#define SWITCH_PK_CREATE(CLASS, IRP, PK, SUFFIX) \
13685 case IRPosition::PK: \
13686 AA = new (A.Allocator) CLASS##SUFFIX(IRP, A); \
13690#define CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13691 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13692 CLASS *AA = nullptr; \
13693 switch (IRP.getPositionKind()) { \
13694 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13695 SWITCH_PK_INV(CLASS, IRP_FLOAT, "floating") \
13696 SWITCH_PK_INV(CLASS, IRP_ARGUMENT, "argument") \
13697 SWITCH_PK_INV(CLASS, IRP_RETURNED, "returned") \
13698 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_RETURNED, "call site returned") \
13699 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_ARGUMENT, "call site argument") \
13700 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
13701 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE, CallSite) \
13706#define CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13707 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13708 CLASS *AA = nullptr; \
13709 switch (IRP.getPositionKind()) { \
13710 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13711 SWITCH_PK_INV(CLASS, IRP_FUNCTION, "function") \
13712 SWITCH_PK_INV(CLASS, IRP_CALL_SITE, "call site") \
13713 SWITCH_PK_CREATE(CLASS, IRP, IRP_FLOAT, Floating) \
13714 SWITCH_PK_CREATE(CLASS, IRP, IRP_ARGUMENT, Argument) \
13715 SWITCH_PK_CREATE(CLASS, IRP, IRP_RETURNED, Returned) \
13716 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_RETURNED, CallSiteReturned) \
13717 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_ARGUMENT, CallSiteArgument) \
13722#define CREATE_ABSTRACT_ATTRIBUTE_FOR_ONE_POSITION(POS, SUFFIX, CLASS) \
13723 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13724 CLASS *AA = nullptr; \
13725 switch (IRP.getPositionKind()) { \
13726 SWITCH_PK_CREATE(CLASS, IRP, POS, SUFFIX) \
13728 llvm_unreachable("Cannot create " #CLASS " for position otherthan " #POS \
13734#define CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13735 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13736 CLASS *AA = nullptr; \
13737 switch (IRP.getPositionKind()) { \
13738 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13739 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
13740 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE, CallSite) \
13741 SWITCH_PK_CREATE(CLASS, IRP, IRP_FLOAT, Floating) \
13742 SWITCH_PK_CREATE(CLASS, IRP, IRP_ARGUMENT, Argument) \
13743 SWITCH_PK_CREATE(CLASS, IRP, IRP_RETURNED, Returned) \
13744 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_RETURNED, CallSiteReturned) \
13745 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_ARGUMENT, CallSiteArgument) \
13750#define CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13751 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13752 CLASS *AA = nullptr; \
13753 switch (IRP.getPositionKind()) { \
13754 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13755 SWITCH_PK_INV(CLASS, IRP_ARGUMENT, "argument") \
13756 SWITCH_PK_INV(CLASS, IRP_FLOAT, "floating") \
13757 SWITCH_PK_INV(CLASS, IRP_RETURNED, "returned") \
13758 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_RETURNED, "call site returned") \
13759 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_ARGUMENT, "call site argument") \
13760 SWITCH_PK_INV(CLASS, IRP_CALL_SITE, "call site") \
13761 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
13766#define CREATE_NON_RET_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13767 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13768 CLASS *AA = nullptr; \
13769 switch (IRP.getPositionKind()) { \
13770 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13771 SWITCH_PK_INV(CLASS, IRP_RETURNED, "returned") \
13772 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
13773 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE, CallSite) \
13774 SWITCH_PK_CREATE(CLASS, IRP, IRP_FLOAT, Floating) \
13775 SWITCH_PK_CREATE(CLASS, IRP, IRP_ARGUMENT, Argument) \
13776 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_RETURNED, CallSiteReturned) \
13777 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_ARGUMENT, CallSiteArgument) \
13829#undef CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION
13830#undef CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION
13831#undef CREATE_NON_RET_ABSTRACT_ATTRIBUTE_FOR_POSITION
13832#undef CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION
13833#undef CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION
13834#undef CREATE_ABSTRACT_ATTRIBUTE_FOR_ONE_POSITION
13835#undef SWITCH_PK_CREATE
13836#undef SWITCH_PK_INV
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU Register Bank Select
This file implements a class to represent arbitrary precision integral constant values and operations...
ReachingDefInfo InstSet & ToRemove
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Function Alias Analysis false
This file contains the simple types necessary to represent the attributes associated with functions a...
#define STATS_DECLTRACK(NAME, TYPE, MSG)
static std::optional< Constant * > askForAssumedConstant(Attributor &A, const AbstractAttribute &QueryingAA, const IRPosition &IRP, Type &Ty)
static cl::opt< unsigned, true > MaxPotentialValues("attributor-max-potential-values", cl::Hidden, cl::desc("Maximum number of potential values to be " "tracked for each position."), cl::location(llvm::PotentialConstantIntValuesState::MaxPotentialValues), cl::init(7))
static void clampReturnedValueStates(Attributor &A, const AAType &QueryingAA, StateType &S, const IRPosition::CallBaseContext *CBContext=nullptr)
Clamp the information known for all returned values of a function (identified by QueryingAA) into S.
#define STATS_DECLTRACK_FN_ATTR(NAME)
#define CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS)
static cl::opt< int > MaxPotentialValuesIterations("attributor-max-potential-values-iterations", cl::Hidden, cl::desc("Maximum number of iterations we keep dismantling potential values."), cl::init(64))
#define STATS_DECLTRACK_CS_ATTR(NAME)
#define PIPE_OPERATOR(CLASS)
static bool mayBeInCycle(const CycleInfo *CI, const Instruction *I, bool HeaderOnly, Cycle **CPtr=nullptr)
#define STATS_DECLTRACK_ARG_ATTR(NAME)
static const Value * stripAndAccumulateOffsets(Attributor &A, const AbstractAttribute &QueryingAA, const Value *Val, const DataLayout &DL, APInt &Offset, bool GetMinOffset, bool AllowNonInbounds, bool UseAssumed=false)
#define STATS_DECLTRACK_CSRET_ATTR(NAME)
static cl::opt< bool > ManifestInternal("attributor-manifest-internal", cl::Hidden, cl::desc("Manifest Attributor internal string attributes."), cl::init(false))
static Value * constructPointer(Value *Ptr, int64_t Offset, IRBuilder< NoFolder > &IRB)
Helper function to create a pointer based on Ptr, and advanced by Offset bytes.
#define CREATE_NON_RET_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS)
#define BUILD_STAT_NAME(NAME, TYPE)
static bool isDenselyPacked(Type *Ty, const DataLayout &DL)
Checks if a type could have padding bytes.
#define CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS)
static const Value * getMinimalBaseOfPointer(Attributor &A, const AbstractAttribute &QueryingAA, const Value *Ptr, int64_t &BytesOffset, const DataLayout &DL, bool AllowNonInbounds=false)
#define STATS_DECLTRACK_FNRET_ATTR(NAME)
#define STATS_DECLTRACK_CSARG_ATTR(NAME)
#define CREATE_ABSTRACT_ATTRIBUTE_FOR_ONE_POSITION(POS, SUFFIX, CLASS)
#define CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS)
static cl::opt< int > MaxHeapToStackSize("max-heap-to-stack-size", cl::init(128), cl::Hidden)
#define CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS)
#define STATS_DECLTRACK_FLOATING_ATTR(NAME)
#define STATS_DECL(NAME, TYPE, MSG)
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static bool isReachableImpl(SmallVectorImpl< BasicBlock * > &Worklist, const StopSetT &StopSet, const SmallPtrSetImpl< BasicBlock * > *ExclusionSet, const DominatorTree *DT, const LoopInfo *LI, const CycleInfo *CI)
This file contains the declarations for the subclasses of Constant, which represent the different fla...
This file declares an analysis pass that computes CycleInfo for LLVM IR, specialized from GenericCycl...
static uint64_t align(uint64_t Size)
DXIL Forward Handle Accesses
This file defines DenseMapInfo traits for DenseMap.
Machine Check Debug Module
This file implements a map that provides insertion order iteration.
static unsigned getAddressSpace(const Value *V, unsigned MaxLookup)
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
uint64_t IntrinsicInst * II
static StringRef getName(Value *V)
dot regions Print regions of function to dot true view regions View regions of function(with no function bodies)"
Remove Loads Into Fake Uses
This builds on the llvm/ADT/GraphTraits.h file to find the strongly connected components (SCCs) of a ...
std::pair< BasicBlock *, BasicBlock * > Edge
BaseType
A given derived pointer can have multiple base pointers through phi/selects.
This file defines generic set operations that may be used on set's of different types,...
This file implements a set that has insertion order iteration characteristics.
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static SymbolRef::Type getType(const Symbol *Sym)
static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, const llvm::StringTable &StandardNames, VectorLibrary VecLib)
Initialize the set of available library functions based on the specified target triple.
static unsigned getBitWidth(Type *Ty, const DataLayout &DL)
Returns the bitwidth of the given scalar or pointer type.
static unsigned getSize(unsigned Kind)
LLVM_ABI AACallGraphNode * operator*() const
bool isNoAlias(const MemoryLocation &LocA, const MemoryLocation &LocB)
A trivial helper function to check to see if the specified pointers are no-alias.
Class for arbitrary precision integers.
int64_t getSExtValue() const
Get sign extended value.
CallBase * getInstruction() const
Return the underlying instruction.
bool isCallbackCall() const
Return true if this ACS represents a callback call.
bool isDirectCall() const
Return true if this ACS represents a direct call.
static LLVM_ABI void getCallbackUses(const CallBase &CB, SmallVectorImpl< const Use * > &CallbackUses)
Add operand uses of CB that represent callback uses into CallbackUses.
int getCallArgOperandNo(Argument &Arg) const
Return the operand index of the underlying instruction associated with Arg.
Align getAlign() const
Return the alignment of the memory that is being allocated by the instruction.
unsigned getAddressSpace() const
Return the address space for the allocation.
LLVM_ABI std::optional< TypeSize > getAllocationSize(const DataLayout &DL) const
Get allocation size in bytes.
This class represents an incoming formal argument to a Function.
LLVM_ABI bool hasNoAliasAttr() const
Return true if this argument has the noalias attribute.
LLVM_ABI bool onlyReadsMemory() const
Return true if this argument has the readonly or readnone attribute.
LLVM_ABI bool hasPointeeInMemoryValueAttr() const
Return true if this argument has the byval, sret, inalloca, preallocated, or byref attribute.
LLVM_ABI bool hasReturnedAttr() const
Return true if this argument has the returned attribute.
LLVM_ABI bool hasByValAttr() const
Return true if this argument has the byval attribute.
const Function * getParent() const
unsigned getArgNo() const
Return the index of this formal argument in its containing function.
A function analysis which provides an AssumptionCache.
A cache of @llvm.assume calls within a function.
Functions, function parameters, and return types can have attributes to indicate how they should be t...
static LLVM_ABI Attribute get(LLVMContext &Context, AttrKind Kind, uint64_t Val=0)
Return a uniquified Attribute object.
LLVM_ABI FPClassTest getNoFPClass() const
Return the FPClassTest for nofpclass.
LLVM_ABI Attribute::AttrKind getKindAsEnum() const
Return the attribute's kind as an enum (Attribute::AttrKind).
LLVM_ABI MemoryEffects getMemoryEffects() const
Returns memory effects.
AttrKind
This enumeration lists the attributes that can be associated with parameters, function results,...
static LLVM_ABI Attribute getWithCaptureInfo(LLVMContext &Context, CaptureInfo CI)
static bool isEnumAttrKind(AttrKind Kind)
bool isValid() const
Return true if the attribute is any kind of attribute.
LLVM_ABI CaptureInfo getCaptureInfo() const
Returns information from captures attribute.
LLVM Basic Block Representation.
LLVM_ABI const_iterator getFirstInsertionPt() const
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
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
InstListType::iterator iterator
Instruction iterators...
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
BinaryOps getOpcode() const
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
LLVM_ABI bool isMustTailCall() const
Tests if this call site must be tail call optimized.
LLVM_ABI bool isIndirectCall() const
Return true if the callsite is an indirect call.
bool isCallee(Value::const_user_iterator UI) const
Determine whether the passed iterator points to the callee operand's Use.
Value * getCalledOperand() const
const Use & getCalledOperandUse() const
Attribute getFnAttr(StringRef Kind) const
Get the attribute of a given kind for the function.
const Use & getArgOperandUse(unsigned i) const
Wrappers for getting the Use of a call argument.
LLVM_ABI std::optional< ConstantRange > getRange() const
If this return value has a range attribute, return the value range of the argument.
Value * getArgOperand(unsigned i) const
bool isBundleOperand(unsigned Idx) const
Return true if the operand at index Idx is a bundle operand.
bool isConvergent() const
Determine if the invoke is convergent.
FunctionType * getFunctionType() const
LLVM_ABI Intrinsic::ID getIntrinsicID() const
Returns the intrinsic ID of the intrinsic called or Intrinsic::not_intrinsic if the called function i...
iterator_range< User::op_iterator > args()
Iteration adapter for range-for loops.
unsigned getArgOperandNo(const Use *U) const
Given a use for a arg operand, get the arg operand number that corresponds to it.
unsigned arg_size() const
bool isArgOperand(const Use *U) const
LLVM_ABI Function * getCaller()
Helper to get the caller (the parent function).
static CallInst * Create(FunctionType *Ty, Value *F, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
static CaptureInfo none()
Create CaptureInfo that does not capture any components of the pointer.
Instruction::CastOps getOpcode() const
Return the opcode of this CastInst.
LLVM_ABI bool isIntegerCast() const
There are several places where we need to know if a cast instruction only deals with integer source a...
Type * getDestTy() const
Return the destination type, as a convenience.
bool isEquality() const
Determine if this is an equals/not equals predicate.
bool isFalseWhenEqual() const
This is just a convenience.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
bool isTrueWhenEqual() const
This is just a convenience.
Predicate getPredicate() const
Return the predicate for this instruction.
Conditional Branch instruction.
Value * getCondition() const
BasicBlock * getSuccessor(unsigned i) const
static LLVM_ABI Constant * getExtractElement(Constant *Vec, Constant *Idx, Type *OnlyIfReducedTy=nullptr)
static LLVM_ABI ConstantInt * getTrue(LLVMContext &Context)
This class represents a range of values.
const APInt & getLower() const
Return the lower value for this range.
LLVM_ABI bool isFullSet() const
Return true if this set contains all of the elements possible for this data-type.
LLVM_ABI bool isEmptySet() const
Return true if this set contains no members.
bool isSingleElement() const
Return true if this set contains exactly one member.
static LLVM_ABI ConstantRange makeAllowedICmpRegion(CmpInst::Predicate Pred, const ConstantRange &Other)
Produce the smallest range such that all values that may satisfy the given predicate with any value c...
const APInt & getUpper() const
Return the upper value for this range.
A parsed version of the target data layout string in and methods for querying it.
iterator find(const_arg_type_t< KeyT > Val)
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
bool contains(const_arg_type_t< KeyT > Val) const
Return true if the specified key is in the map, false otherwise.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Analysis pass which computes a DominatorTree.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
LLVM_ABI bool dominates(const BasicBlock *BB, const Use &U) const
Return true if the (end of the) basic block BB dominates the use U.
const BasicBlock & getEntryBlock() const
iterator_range< arg_iterator > args()
const Function & getFunction() const
Argument * getArg(unsigned i) const
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
CycleT * getCycle(const BlockT *Block) const
Find the innermost cycle containing a given block.
LLVM_ABI bool isDeclaration() const
Return true if the primary definition of this global value is outside of the current translation unit...
bool hasLocalLinkage() const
static LLVM_ABI bool compare(const APInt &LHS, const APInt &RHS, ICmpInst::Predicate Pred)
Return result of LHS Pred RHS comparison.
Value * CreatePtrAdd(Value *Ptr, Value *Offset, const Twine &Name="", GEPNoWrapFlags NW=GEPNoWrapFlags::none())
ConstantInt * getInt64(uint64_t C)
Get a constant 64-bit value.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
LLVM_ABI Instruction * clone() const
Create a copy of 'this' instruction that is identical in all ways except the following:
LLVM_ABI bool isLifetimeStartOrEnd() const LLVM_READONLY
Return true if the instruction is a llvm.lifetime.start or llvm.lifetime.end marker.
bool mayReadOrWriteMemory() const
Return true if this instruction may read or write memory.
LLVM_ABI bool mayWriteToMemory() const LLVM_READONLY
Return true if this instruction may modify memory.
bool hasMetadata() const
Return true if this instruction has any metadata attached to it.
LLVM_ABI void insertBefore(InstListType::iterator InsertPos)
Insert an unlinked instruction into a basic block immediately before the specified position.
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 BasicBlock * getSuccessor(unsigned Idx) const LLVM_READONLY
Return the specified successor. This instruction must be a terminator.
LLVM_ABI bool mayHaveSideEffects() const LLVM_READONLY
Return true if the instruction may have side effects.
bool isTerminator() const
LLVM_ABI bool mayReadFromMemory() const LLVM_READONLY
Return true if this instruction may read memory.
LLVM_ABI void setMetadata(unsigned KindID, MDNode *Node)
Set the metadata of the specified kind to the specified node.
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
This is an important class for using LLVM in a threaded context.
LLVM_ABI ConstantRange getConstantRange(Value *V, Instruction *CxtI, bool UndefAllowed)
Return the ConstantRange constraint that is known to hold for the specified value at the specified in...
LoopT * getLoopFor(const BlockT *BB) const
Return the inner most loop that BB lives in.
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
static LLVM_ABI MDNode * getMostGenericRange(MDNode *A, MDNode *B)
static MemoryEffectsBase readOnly()
bool doesNotAccessMemory() const
Whether this function accesses no memory.
static MemoryEffectsBase argMemOnly(ModRefInfo MR=ModRefInfo::ModRef)
static MemoryEffectsBase inaccessibleMemOnly(ModRefInfo MR=ModRefInfo::ModRef)
bool onlyAccessesInaccessibleMem() const
Whether this function only (at most) accesses inaccessible memory.
ModRefInfo getModRef(Location Loc) const
Get ModRefInfo for the given Location.
bool onlyAccessesArgPointees() const
Whether this function only (at most) accesses argument memory.
bool onlyReadsMemory() const
Whether this function only (at most) reads memory.
static MemoryEffectsBase writeOnly()
static MemoryEffectsBase inaccessibleOrArgMemOnly(ModRefInfo MR=ModRefInfo::ModRef)
static MemoryEffectsBase none()
bool onlyAccessesInaccessibleOrArgMem() const
Whether this function only (at most) accesses argument and inaccessible memory.
static MemoryEffectsBase unknown()
static LLVM_ABI std::optional< MemoryLocation > getOrNone(const Instruction *Inst)
static SizeOffsetValue unknown()
static PHINode * Create(Type *Ty, unsigned NumReservedValues, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
Constructors - NumReservedValues is a hint for the number of incoming edges that this phi node will h...
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
Value * getReturnValue() const
Convenience accessor. Returns null if there is no return value.
LLVM_ABI const SCEV * getSCEVAtScope(const SCEV *S, const Loop *L)
Return a SCEV expression for the specified value at the specified scope in the program.
LLVM_ABI const SCEV * getSCEV(Value *V)
Return a SCEV expression for the full generality of the specified expression.
LLVM_ABI unsigned getSmallConstantMaxTripCount(const Loop *L, SmallVectorImpl< const SCEVPredicate * > *Predicates=nullptr)
Returns the upper bound of the loop trip count as a normal unsigned value.
ConstantRange getUnsignedRange(const SCEV *S)
Determine the unsigned range for a particular SCEV.
A vector that has set insertion semantics.
size_type size() const
Determine the number of elements in the SetVector.
bool insert(const value_type &X)
Insert a new element into the SetVector.
bool erase(PtrType Ptr)
Remove pointer from the set.
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.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
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.
Used to lazily calculate structure layout information for a target machine, based on the DataLayout s...
TypeSize getElementOffset(unsigned Idx) const
TypeSize getElementOffsetInBits(unsigned Idx) const
Class to represent struct types.
unsigned getNumElements() const
Random access to the elements.
Type * getElementType(unsigned N) const
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM_ABI unsigned getIntegerBitWidth() const
bool isPointerTy() const
True if this is an instance of PointerType.
LLVM_ABI unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
bool isPtrOrPtrVectorTy() const
Return true if this is a pointer type or a vector of pointer types.
bool isIntegerTy() const
True if this is an instance of IntegerType.
bool isVoidTy() const
Return true if this is 'void'.
static UncondBrInst * Create(BasicBlock *Target, InsertPosition InsertBefore=nullptr)
BasicBlock * getSuccessor(unsigned i=0) const
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.
User * getUser() const
Returns the User that contains this Use.
const Use & getOperandUse(unsigned i) const
LLVM_ABI bool isDroppable() const
A droppable user is a user for which uses can be dropped without affecting correctness and should be ...
LLVM_ABI bool replaceUsesOfWith(Value *From, Value *To)
Replace uses of one Value with another.
Value * getOperand(unsigned i) const
unsigned getNumOperands() const
ValueT lookup(const KeyT &Val) const
lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
static constexpr uint64_t MaximumAlignment
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.
iterator_range< user_iterator > users()
LLVM_ABI const Value * stripAndAccumulateConstantOffsets(const DataLayout &DL, APInt &Offset, bool AllowNonInbounds, bool AllowInvariantGroup=false, function_ref< bool(Value &Value, APInt &Offset)> ExternalAnalysis=nullptr, bool LookThroughIntToPtr=false) const
Accumulate the constant offset this value has compared to a base pointer.
static constexpr unsigned MaxAlignmentExponent
The maximum alignment for instructions.
iterator_range< use_iterator > uses()
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
std::pair< iterator, bool > insert(const ValueT &V)
constexpr ScalarTy getFixedValue() const
constexpr bool isScalable() const
Returns whether the quantity is scaled by a runtime quantity (vscale).
const ParentTy * getParent() const
self_iterator getIterator()
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
SetVector< Function * >::iterator I
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.
raw_ostream & operator<<(raw_ostream &OS, const RangeTy &R)
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 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...
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).
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 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 Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char Attrs[]
Key for Kernel::Metadata::mAttrs.
@ C
The default llvm calling convention, compatible with C.
@ BasicBlock
Various leaf nodes.
@ Unsupported
This operation is completely unsupported on the target.
@ SingleThread
Synchronized with respect to signal handlers executing in the same thread.
@ CE
Windows NT (Windows on ARM)
@ Valid
The data is already valid.
initializer< Ty > init(const Ty &Val)
LocationClass< Ty > location(Ty &L)
unsigned combineHashValue(unsigned a, unsigned b)
Simplistic combination of 32-bit hash values into 32-bit hash values.
ElementType
The element type of an SRV or UAV resource.
Scope
Defines the scope in which this symbol should be visible: Default – Visible in the public interface o...
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > dyn_extract_or_null(Y &&MD)
Extract a Value from Metadata, if any, allowing null.
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > extract(Y &&MD)
Extract a Value from Metadata.
@ User
could "use" a pointer
NodeAddr< UseNode * > Use
Context & getContext() const
friend class Instruction
Iterator for Instructions in a `BasicBlock.
LLVM_ABI iterator begin() const
This is an optimization pass for GlobalISel generic memory operations.
bool operator<(int64_t V1, const APSInt &V2)
FunctionAddr VTableAddr Value
LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt gcd(const DynamicAPInt &A, const DynamicAPInt &B)
LLVM_ABI KnownFPClass computeKnownFPClass(const Value *V, const APInt &DemandedElts, FPClassTest InterestedClasses, const SimplifyQuery &SQ, unsigned Depth=0)
Determine which floating-point classes are valid for V, and return them in KnownFPClass bit sets.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI bool isLegalToPromote(const CallBase &CB, Function *Callee, const char **FailureReason=nullptr)
Return true if the given indirect call site can be made to call Callee.
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,...
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
@ Undef
Value of the register doesn't matter.
auto pred_end(const MachineBasicBlock *BB)
unsigned getPointerAddressSpace(const Type *T)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
FunctionAddr VTableAddr uintptr_t uintptr_t Int32Ty
auto successors(const MachineBasicBlock *BB)
LLVM_ABI bool isRemovableAlloc(const CallBase *V, const TargetLibraryInfo *TLI)
Return true if this is a call to an allocation function that does not have side effects that we are r...
APFloat abs(APFloat X)
Returns the absolute value of the argument.
LLVM_ABI raw_fd_ostream & outs()
This returns a reference to a raw_fd_ostream for standard output.
LLVM_ABI Value * getAllocAlignment(const CallBase *V, const TargetLibraryInfo *TLI)
Gets the alignment argument for an aligned_alloc-like function, using either built-in knowledge based...
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 ...
LLVM_ABI Value * simplifyInstructionWithOperands(Instruction *I, ArrayRef< Value * > NewOps, const SimplifyQuery &Q)
Like simplifyInstruction but the operands of I are replaced with NewOps.
Value * GetPointerBaseWithConstantOffset(Value *Ptr, int64_t &Offset, const DataLayout &DL, bool AllowNonInbounds=true)
Analyze the specified pointer to see if it can be expressed as a base pointer plus a constant offset.
scc_iterator< T > scc_begin(const T &G)
Construct the begin iterator for a deduced graph type T.
LLVM_ABI bool isIntrinsicReturningPointerAliasingArgumentWithoutCapturing(const CallBase *Call, bool MustPreserveOffset)
{launder,strip}.invariant.group returns pointer that aliases its argument, and it only captures point...
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="")
LLVM_ABI bool isSafeToSpeculativelyExecute(const Instruction *I, const Instruction *CtxI=nullptr, AssumptionCache *AC=nullptr, const DominatorTree *DT=nullptr, const TargetLibraryInfo *TLI=nullptr, bool UseVariableInfo=true, bool IgnoreUBImplyingAttrs=true)
Return true if the instruction does not have any effects besides calculating the result and does not ...
bool isa_and_nonnull(const Y &Val)
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
LLVM_ABI ConstantRange getConstantRangeFromMetadata(const MDNode &RangeMD)
Parse out a conservative ConstantRange from !range metadata.
auto map_range(ContainerTy &&C, FuncTy F)
Return a range that applies F to the elements of C.
const Value * getPointerOperand(const Value *V)
A helper function that returns the pointer operand of a load, store or GEP instruction.
LLVM_ABI Value * simplifyInstruction(Instruction *I, const SimplifyQuery &Q)
See if we can compute a simplified version of this instruction.
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.
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
PotentialValuesState< std::pair< AA::ValueAndContext, AA::ValueScope > > PotentialLLVMValuesState
void sort(IteratorTy Start, IteratorTy End)
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.
bool isPointerTy(const Type *T)
LLVM_ABI bool wouldInstructionBeTriviallyDead(const Instruction *I, const TargetLibraryInfo *TLI=nullptr)
Return true if the result produced by the instruction would have no side effects if it was not used.
bool set_union(S1Ty &S1, const S2Ty &S2)
set_union(A, B) - Compute A := A u B, return whether A changed.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
LLVM_ABI CallBase & promoteCall(CallBase &CB, Function *Callee, CastInst **RetBitCast=nullptr)
Promote the given indirect call site to unconditionally call Callee.
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ABI bool hasAssumption(const Function &F, const KnownAssumptionString &AssumptionStr)
Return true if F has the assumption AssumptionStr attached.
LLVM_ABI RetainedKnowledge getKnowledgeFromUse(const Use *U, ArrayRef< Attribute::AttrKind > AttrKinds)
Return a valid Knowledge associated to the Use U if its Attribute kind is in AttrKinds.
@ Success
The lock was released successfully.
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
LLVM_ABI bool isKnownNonZero(const Value *V, const SimplifyQuery &Q, unsigned Depth=0)
Return true if the given value is known to be non-zero when defined.
AtomicOrdering
Atomic ordering for LLVM's memory model.
PotentialValuesState< APInt > PotentialConstantIntValuesState
std::string join(IteratorT Begin, IteratorT End, StringRef Separator)
Joins the strings in the range [Begin, End), adding Separator between the elements.
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
InterleavedRange< Range > interleaved_array(const Range &R, StringRef Separator=", ")
Output range R as an array of interleaved elements.
ChangeStatus clampStateAndIndicateChange< DerefState >(DerefState &S, const DerefState &R)
void RemapInstruction(Instruction *I, ValueToValueMapTy &VM, RemapFlags Flags=RF_None, ValueMapTypeRemapper *TypeMapper=nullptr, ValueMaterializer *Materializer=nullptr, const MetadataPredicate *IdentityMD=nullptr)
Convert the instruction operands from referencing the current values into those specified by VM.
DWARFExpression::Operation Op
LLVM_ABI bool isGuaranteedNotToBeUndefOrPoison(const Value *V, AssumptionCache *AC=nullptr, const Instruction *CtxI=nullptr, const DominatorTree *DT=nullptr, unsigned Depth=0)
Return true if this function can prove that V does not have undef bits and is never poison.
ArrayRef(const T &OneElt) -> ArrayRef< T >
LLVM_ABI Value * getFreedOperand(const CallBase *CB, const TargetLibraryInfo *TLI)
If this if a call to a free function, return the freed operand.
ChangeStatus clampStateAndIndicateChange(StateType &S, const StateType &R)
Helper function to clamp a state S of type StateType with the information in R and indicate/return if...
constexpr unsigned BitWidth
ValueMap< const Value *, WeakTrackingVH > ValueToValueMapTy
auto pred_begin(const MachineBasicBlock *BB)
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
iterator_range< pointer_iterator< WrappedIteratorT > > make_pointer_range(RangeT &&Range)
LLVM_ABI std::optional< APInt > getAllocSize(const CallBase *CB, const TargetLibraryInfo *TLI, function_ref< const Value *(const Value *)> Mapper=[](const Value *V) { return V;})
Return the size of the requested allocation.
LLVM_ABI DenseSet< StringRef > getAssumptions(const Function &F)
Return the set of all assumptions for the function F.
Align assumeAligned(uint64_t Value)
Treats the value 0 as a 1, so Align is always at least 1.
LLVM_ABI Instruction * SplitBlockAndInsertIfThen(Value *Cond, BasicBlock::iterator SplitBefore, bool Unreachable, MDNode *BranchWeights=nullptr, DomTreeUpdater *DTU=nullptr, LoopInfo *LI=nullptr, BasicBlock *ThenBlock=nullptr)
Split the containing block at the specified instruction - everything before SplitBefore stays in the ...
@ 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.
LLVM_ABI UseCaptureInfo DetermineUseCaptureKind(const Use &U, const Value *Base)
Determine what kind of capture behaviour U may exhibit.
LLVM_ABI Value * simplifyCmpInst(CmpPredicate Predicate, Value *LHS, Value *RHS, const SimplifyQuery &Q)
Given operands for a CmpInst, fold the result or return null.
LLVM_ABI bool mayContainIrreducibleControl(const Function &F, const LoopInfo *LI)
BumpPtrAllocatorImpl<> BumpPtrAllocator
The standard BumpPtrAllocator which just uses the default template parameters.
T bit_floor(T Value)
Returns the largest integral power of two no greater than Value if Value is nonzero.
LLVM_ABI const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
bool capturesNothing(CaptureComponents CC)
LLVM_ABI bool isIdentifiedObject(const Value *V)
Return true if this pointer refers to a distinct and identifiable object.
bool capturesAnyProvenance(CaptureComponents CC)
constexpr StringRef AssumptionAttrKey
The key we use for assumption attributes.
constexpr bool isCallableCC(CallingConv::ID CC)
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
A type to track pointer/struct usage and accesses for AAPointerInfo.
bool forallInterferingAccesses(AA::RangeTy Range, F CB) const
See AAPointerInfo::forallInterferingAccesses.
AAPointerInfo::const_bin_iterator end() const
ChangeStatus addAccess(Attributor &A, const AAPointerInfo::RangeList &Ranges, Instruction &I, std::optional< Value * > Content, AAPointerInfo::AccessKind Kind, Type *Ty, Instruction *RemoteI=nullptr)
Add a new Access to the state at offset Offset and with size Size.
DenseMap< const Instruction *, SmallVector< unsigned > > RemoteIMap
AAPointerInfo::const_bin_iterator begin() const
AAPointerInfo::OffsetInfo ReturnedOffsets
Flag to determine if the underlying pointer is reaching a return statement in the associated function...
State & operator=(State &&R)
State(State &&SIS)=default
const AAPointerInfo::Access & getAccess(unsigned Index) const
SmallVector< AAPointerInfo::Access > AccessList
bool isAtFixpoint() const override
See AbstractState::isAtFixpoint().
bool forallInterferingAccesses(Instruction &I, F CB, AA::RangeTy &Range) const
See AAPointerInfo::forallInterferingAccesses.
static State getWorstState(const State &SIS)
Return the worst possible representable state.
int64_t numOffsetBins() const
AAPointerInfo::OffsetBinsTy OffsetBins
ChangeStatus indicateOptimisticFixpoint() override
See AbstractState::indicateOptimisticFixpoint().
State & operator=(const State &R)
ChangeStatus indicatePessimisticFixpoint() override
See AbstractState::indicatePessimisticFixpoint().
const State & getAssumed() const
static State getBestState(const State &SIS)
Return the best possible representable state.
bool isValidState() const override
See AbstractState::isValidState().
----------------—AAIntraFnReachability Attribute-----------------------—
ReachabilityQueryInfo(const ReachabilityQueryInfo &RQI)
unsigned Hash
Precomputed hash for this RQI.
const Instruction * From
Start here,.
Reachable Result
and remember if it worked:
ReachabilityQueryInfo(const Instruction *From, const ToTy *To)
ReachabilityQueryInfo(Attributor &A, const Instruction &From, const ToTy &To, const AA::InstExclusionSetTy *ES, bool MakeUnique)
Constructor replacement to ensure unique and stable sets are used for the cache.
const ToTy * To
reach this place,
const AA::InstExclusionSetTy * ExclusionSet
without going through any of these instructions,
unsigned computeHashValue() const
An abstract interface for address space information.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for all align attributes.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
Align getKnownAlign() const
Return known alignment.
static LLVM_ABI const char ID
An abstract attribute for getting assumption information.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract state for querying live call edges.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract Attribute for specializing "dynamic" components of denormal_fpenv to a known denormal mod...
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for all dereferenceable attribute.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for llvm::GlobalValue information interference.
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)
An abstract interface for indirect call information interference.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface to track if a value leaves it's defining function instance.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract Attribute for computing reachability between functions.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
bool canReach(Attributor &A, const Function &Fn) const
If the function represented by this possition can reach Fn.
virtual bool instructionCanReach(Attributor &A, const Instruction &Inst, const Function &Fn, const AA::InstExclusionSetTy *ExclusionSet=nullptr) const =0
Can Inst reach Fn.
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 identifying pointers from which loads can be marked invariant.
static LLVM_ABI const char ID
Unique ID (due to the unique address).
An abstract interface for liveness abstract attribute.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for memory access kind related attributes (readnone/readonly/writeonly).
bool isAssumedReadOnly() const
Return true if we assume that the underlying value is not accessed (=written) in its respective scope...
bool isKnownReadNone() const
Return true if we know that the underlying value is not read or accessed in its respective scope.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
bool isAssumedReadNone() const
Return true if we assume that the underlying value is not read or accessed in its respective scope.
An abstract interface for all memory location attributes (readnone/argmemonly/inaccessiblememonly/ina...
static LLVM_ABI std::string getMemoryLocationsAsStr(MemoryLocationsKind MLK)
Return the locations encoded by MLK as a readable string.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
StateType::base_t MemoryLocationsKind
An abstract interface for all nonnull attributes.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for potential address space information.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for all noalias attributes.
static LLVM_ABI bool isImpliedByIR(Attributor &A, const IRPosition &IRP, Attribute::AttrKind ImpliedAttributeKind, bool IgnoreSubsumingPositions=false)
See IRAttribute::isImpliedByIR.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for all nocapture attributes.
@ NO_CAPTURE_MAYBE_RETURNED
If we do not capture the value in memory or through integers we can only communicate it back as a der...
@ NO_CAPTURE
If we do not capture the value in memory, through integers, or as a derived pointer we know it is not...
static LLVM_ABI const char ID
Unique ID (due to the unique address)
bool isAssumedNoCaptureMaybeReturned() const
Return true if we assume that the underlying value is not captured in its respective scope but we all...
static LLVM_ABI bool isImpliedByIR(Attributor &A, const IRPosition &IRP, Attribute::AttrKind ImpliedAttributeKind, bool IgnoreSubsumingPositions=false)
See IRAttribute::isImpliedByIR.
static LLVM_ABI void determineFunctionCaptureCapabilities(const IRPosition &IRP, const Function &F, BitIntegerState &State)
Update State according to the capture capabilities of F for position IRP.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An AbstractAttribute for nofree.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract attribute for norecurse.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An AbstractAttribute for noreturn.
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 isAlignedBarrier(const CallBase &CB, bool ExecutedAligned)
Helper function to determine if CB is an aligned (GPU) barrier.
static LLVM_ABI bool isNonRelaxedAtomic(const Instruction *I)
Helper function used to determine whether an instruction is non-relaxed atomic.
An abstract interface for all noundef attributes.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
static LLVM_ABI bool isImpliedByIR(Attributor &A, const IRPosition &IRP, Attribute::AttrKind ImpliedAttributeKind, bool IgnoreSubsumingPositions=false)
See IRAttribute::isImpliedByIR.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract Attribute for determining the necessity of the convergent attribute.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for all nonnull attributes.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
static LLVM_ABI bool isImpliedByIR(Attributor &A, const IRPosition &IRP, Attribute::AttrKind ImpliedAttributeKind, bool IgnoreSubsumingPositions=false)
See AbstractAttribute::isImpliedByIR(...).
A helper containing a list of offsets computed for a Use.
A container for a list of ranges.
static void set_difference(const RangeList &L, const RangeList &R, RangeList &D)
Copy ranges from L that are not in R, into D.
An abstract interface for struct information.
virtual bool reachesReturn() const =0
OffsetBinsTy::const_iterator const_bin_iterator
virtual const_bin_iterator begin() const =0
DenseMap< AA::RangeTy, SmallSet< unsigned, 4 > > OffsetBinsTy
static LLVM_ABI const char ID
Unique ID (due to the unique address)
virtual int64_t numOffsetBins() const =0
An abstract interface for potential values analysis.
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 Value * getSingleValue(Attributor &A, const AbstractAttribute &AA, const IRPosition &IRP, SmallVectorImpl< AA::ValueAndContext > &Values)
Extract the single value in Values if any.
An abstract interface for privatizability.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract attribute for undefined behavior.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract attribute for getting all assumption underlying objects.
virtual bool forallUnderlyingObjects(function_ref< bool(Value &)> Pred, AA::ValueScope Scope=AA::Interprocedural) const =0
Check Pred on all underlying objects in Scope collected so far.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for range value analysis.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for value simplify abstract attribute.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract attribute for willreturn.
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...
static constexpr int64_t Unknown
static RangeTy getUnknown()
const Instruction * getCtxI() const
Base struct for all "concrete attribute" deductions.
void print(raw_ostream &OS) const
Helper functions, for debug purposes only.
virtual StateType & getState()=0
Return the internal abstract state for inspection.
An interface to query the internal state of an abstract attribute.
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.
Helper for AA::PointerInfo::Access DenseMap/Set usage ignoring everythign but the instruction.
static unsigned getHashValue(const Access &A)
AAPointerInfo::Access Access
DenseMapInfo< Instruction * > Base
static bool isEqual(const Access &LHS, const Access &RHS)
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
std::function< void( const ArgumentReplacementInfo &, Function &, Function::arg_iterator)> CalleeRepairCBTy
Callee repair callback type.
const Argument & getReplacedArg() const
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.
std::function< std::optional< Value * >( const IRPosition &, const AbstractAttribute *, bool &)> SimplifictionCallbackTy
Register CB as a simplification callback.
Specialization of the integer state for a bit-wise encoding.
BitIntegerState & addKnownBits(base_t Bits)
Add the bits in BitsEncoding to the "known bits".
Simple wrapper for a single bit (boolean) state.
static constexpr DenormalFPEnv getDefault()
static unsigned getHashValue(const Access &A)
AAPointerInfo::Access Access
static bool isEqual(const Access &LHS, const Access &RHS)
static bool isEqual(const AA::RangeTy &A, const AA::RangeTy B)
static unsigned getHashValue(const AA::RangeTy &Range)
DenseMapInfo< std::pair< const Instruction *, const ToTy * > > PairDMI
static bool isEqual(const ReachabilityQueryInfo< ToTy > *LHS, const ReachabilityQueryInfo< ToTy > *RHS)
DenseMapInfo< const AA::InstExclusionSetTy * > InstSetDMI
static unsigned getHashValue(const ReachabilityQueryInfo< ToTy > *RQI)
An information struct used to provide DenseMap with the various necessary components for a given valu...
State for dereferenceable attribute.
IncIntegerState DerefBytesState
State representing for dereferenceable bytes.
ChangeStatus manifest(Attributor &A) override
See AbstractAttribute::manifest(...).
Helper to describe and deal with positions in the LLVM-IR.
Function * getAssociatedFunction() const
Return the associated function, if any.
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.
int getCalleeArgNo() const
Return the callee argument number of the associated value if it is an argument or call site argument,...
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.
@ 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_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.
Type * getAssociatedType() const
Return the type this abstract attribute is associated with.
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.
int getCallSiteArgNo() const
Return the call site argument number of the associated value if it is an argument or call site argume...
static const IRPosition function_scope(const IRPosition &IRP, const CallBaseContext *CBContext=nullptr)
Create a position with function scope matching the "context" of IRP.
Kind getPositionKind() const
Return the associated position kind.
bool isArgumentPosition() const
Return true if the position is an argument or call site argument.
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.
ConstantRange getKnown() const
Return the known state encoding.
ConstantRange getAssumed() const
Return the assumed state encoding.
base_t getAssumed() const
Return the assumed state encoding.
static constexpr base_t getWorstState()
Helper that allows to insert a new assumption string in the known assumption set by creating a (stati...
FPClassTest KnownFPClasses
Floating-point classes the value could be one of.
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 checkForAllContext(const Instruction *PP, function_ref< bool(const Instruction *)> Pred)
}
static unsigned MaxPotentialValues
Helper to tie a abstract state implementation to an abstract attribute.
StateType & getState() override
See AbstractAttribute::getState(...).
bool isPassthrough() const
CaptureComponents ResultCC
Components captured by the return value of the user of this Use.
LLVM_ABI bool unionAssumed(std::optional< Value * > Other)
Merge Other into the currently assumed simplified value.
std::optional< Value * > SimplifiedAssociatedValue
An assumed simplified value.
Type * Ty
The type of the original value.