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())
670 if (Br->isConditional())
709 StateType ParentState;
713 ParentState.indicateOptimisticFixpoint();
715 for (
const BasicBlock *BB : Br->successors()) {
716 StateType ChildState;
718 size_t BeforeSize =
Uses.size();
719 followUsesInContext(
AA,
A, *Explorer, &BB->front(),
Uses, ChildState);
722 for (
auto It =
Uses.begin() + BeforeSize; It !=
Uses.end();)
725 ParentState &= ChildState;
799 R.indicatePessimisticFixpoint();
816 BS.indicateOptimisticFixpoint();
822 BS.indicatePessimisticFixpoint();
892 template <
typename F>
899 if (!
Range.mayOverlap(ItRange))
901 bool IsExact =
Range == ItRange && !
Range.offsetOrSizeAreUnknown();
902 for (
auto Index : It.getSecond()) {
912 template <
typename F>
923 for (
unsigned Index : LocalList->getSecond()) {
926 if (
Range.offsetAndSizeAreUnknown())
942 RemoteI = RemoteI ? RemoteI : &
I;
946 bool AccExists =
false;
948 for (
auto Index : LocalList) {
950 if (
A.getLocalInst() == &
I) {
959 <<
"[AAPointerInfo] Inserting access in new offset bins\n";);
961 for (
auto Key : ToAdd) {
968 AccessList.emplace_back(&
I, RemoteI, Ranges, Content, Kind, Ty);
970 "New Access should have been at AccIndex");
971 LocalList.push_back(AccIndex);
980 auto Before = Current;
982 if (Current == Before)
985 auto &ExistingRanges = Before.getRanges();
986 auto &NewRanges = Current.getRanges();
993 <<
"[AAPointerInfo] Removing access from old offset bins\n";);
1000 "Expected bin to actually contain the Access.");
1001 Bin.erase(AccIndex);
1022struct AAPointerInfoImpl
1023 :
public StateWrapper<AA::PointerInfo::State, AAPointerInfo> {
1028 const std::string getAsStr(
Attributor *
A)
const override {
1029 return std::string(
"PointerInfo ") +
1030 (isValidState() ? (std::string(
"#") +
1031 std::to_string(OffsetBins.size()) +
" bins")
1036 [](int64_t O) {
return std::to_string(O); }),
1044 return AAPointerInfo::manifest(
A);
1047 const_bin_iterator
begin()
const override {
return State::begin(); }
1048 const_bin_iterator
end()
const override {
return State::end(); }
1049 int64_t numOffsetBins()
const override {
return State::numOffsetBins(); }
1050 bool reachesReturn()
const override {
1051 return !ReturnedOffsets.isUnassigned();
1053 void addReturnedOffsetsTo(OffsetInfo &OI)
const override {
1054 if (ReturnedOffsets.isUnknown()) {
1059 OffsetInfo MergedOI;
1060 for (
auto Offset : ReturnedOffsets) {
1061 OffsetInfo TmpOI = OI;
1063 MergedOI.merge(TmpOI);
1065 OI = std::move(MergedOI);
1068 ChangeStatus setReachesReturn(
const OffsetInfo &ReachedReturnedOffsets) {
1069 if (ReturnedOffsets.isUnknown())
1070 return ChangeStatus::UNCHANGED;
1071 if (ReachedReturnedOffsets.isUnknown()) {
1072 ReturnedOffsets.setUnknown();
1073 return ChangeStatus::CHANGED;
1075 if (ReturnedOffsets.merge(ReachedReturnedOffsets))
1076 return ChangeStatus::CHANGED;
1077 return ChangeStatus::UNCHANGED;
1080 bool forallInterferingAccesses(
1082 function_ref<
bool(
const AAPointerInfo::Access &,
bool)> CB)
1084 return State::forallInterferingAccesses(
Range, CB);
1087 bool forallInterferingAccesses(
1088 Attributor &
A,
const AbstractAttribute &QueryingAA, Instruction &
I,
1089 bool FindInterferingWrites,
bool FindInterferingReads,
1090 function_ref<
bool(
const Access &,
bool)> UserCB,
bool &HasBeenWrittenTo,
1092 function_ref<
bool(
const Access &)> SkipCB)
const override {
1093 HasBeenWrittenTo =
false;
1095 SmallPtrSet<const Access *, 8> DominatingWrites;
1103 const auto *ExecDomainAA =
A.lookupAAFor<AAExecutionDomain>(
1105 bool AllInSameNoSyncFn = IsAssumedNoSync;
1106 bool InstIsExecutedByInitialThreadOnly =
1107 ExecDomainAA && ExecDomainAA->isExecutedByInitialThreadOnly(
I);
1114 bool InstIsExecutedInAlignedRegion =
1115 FindInterferingReads && ExecDomainAA &&
1116 ExecDomainAA->isExecutedInAlignedRegion(
A,
I);
1118 if (InstIsExecutedInAlignedRegion || InstIsExecutedByInitialThreadOnly)
1119 A.recordDependence(*ExecDomainAA, QueryingAA, DepClassTy::OPTIONAL);
1121 InformationCache &InfoCache =
A.getInfoCache();
1122 bool IsThreadLocalObj =
1131 auto CanIgnoreThreadingForInst = [&](
const Instruction &
I) ->
bool {
1132 if (IsThreadLocalObj || AllInSameNoSyncFn)
1134 const auto *FnExecDomainAA =
1135 I.getFunction() == &
Scope
1137 :
A.lookupAAFor<AAExecutionDomain>(
1140 if (!FnExecDomainAA)
1142 if (InstIsExecutedInAlignedRegion ||
1143 (FindInterferingWrites &&
1144 FnExecDomainAA->isExecutedInAlignedRegion(
A,
I))) {
1145 A.recordDependence(*FnExecDomainAA, QueryingAA, DepClassTy::OPTIONAL);
1148 if (InstIsExecutedByInitialThreadOnly &&
1149 FnExecDomainAA->isExecutedByInitialThreadOnly(
I)) {
1150 A.recordDependence(*FnExecDomainAA, QueryingAA, DepClassTy::OPTIONAL);
1159 auto CanIgnoreThreading = [&](
const Access &Acc) ->
bool {
1160 return CanIgnoreThreadingForInst(*Acc.getRemoteInst()) ||
1161 (Acc.getRemoteInst() != Acc.getLocalInst() &&
1162 CanIgnoreThreadingForInst(*Acc.getLocalInst()));
1166 bool IsKnownNoRecurse;
1174 bool InstInKernel =
A.getInfoCache().isKernel(Scope);
1175 bool ObjHasKernelLifetime =
false;
1176 const bool UseDominanceReasoning =
1177 FindInterferingWrites && IsKnownNoRecurse;
1178 const DominatorTree *DT =
1188 case AA::GPUAddressSpace::Shared:
1189 case AA::GPUAddressSpace::Constant:
1190 case AA::GPUAddressSpace::Local:
1202 std::function<bool(
const Function &)> IsLiveInCalleeCB;
1207 const Function *AIFn = AI->getFunction();
1208 ObjHasKernelLifetime =
A.getInfoCache().isKernel(*AIFn);
1209 bool IsKnownNoRecurse;
1212 IsKnownNoRecurse)) {
1213 IsLiveInCalleeCB = [AIFn](
const Function &Fn) {
return AIFn != &Fn; };
1218 ObjHasKernelLifetime = HasKernelLifetime(GV, *GV->getParent());
1219 if (ObjHasKernelLifetime)
1220 IsLiveInCalleeCB = [&
A](
const Function &Fn) {
1221 return !
A.getInfoCache().isKernel(Fn);
1229 auto AccessCB = [&](
const Access &Acc,
bool Exact) {
1230 Function *AccScope = Acc.getRemoteInst()->getFunction();
1231 bool AccInSameScope = AccScope == &
Scope;
1235 if (InstInKernel && ObjHasKernelLifetime && !AccInSameScope &&
1236 A.getInfoCache().isKernel(*AccScope))
1239 if (Exact && Acc.isMustAccess() && Acc.getRemoteInst() != &
I) {
1240 if (Acc.isWrite() || (
isa<LoadInst>(
I) && Acc.isWriteOrAssumption()))
1241 ExclusionSet.
insert(Acc.getRemoteInst());
1244 if ((!FindInterferingWrites || !Acc.isWriteOrAssumption()) &&
1245 (!FindInterferingReads || !Acc.isRead()))
1248 bool Dominates = FindInterferingWrites && DT && Exact &&
1249 Acc.isMustAccess() && AccInSameScope &&
1252 DominatingWrites.
insert(&Acc);
1256 AllInSameNoSyncFn &= Acc.getRemoteInst()->getFunction() == &
Scope;
1258 InterferingAccesses.
push_back({&Acc, Exact});
1261 if (!State::forallInterferingAccesses(
I, AccessCB,
Range))
1264 HasBeenWrittenTo = !DominatingWrites.
empty();
1268 for (
const Access *Acc : DominatingWrites) {
1269 if (!LeastDominatingWriteInst) {
1270 LeastDominatingWriteInst = Acc->getRemoteInst();
1271 }
else if (DT->
dominates(LeastDominatingWriteInst,
1272 Acc->getRemoteInst())) {
1273 LeastDominatingWriteInst = Acc->getRemoteInst();
1278 auto CanSkipAccess = [&](
const Access &Acc,
bool Exact) {
1279 if (SkipCB && SkipCB(Acc))
1281 if (!CanIgnoreThreading(Acc))
1287 bool ReadChecked = !FindInterferingReads;
1288 bool WriteChecked = !FindInterferingWrites;
1294 &ExclusionSet, IsLiveInCalleeCB))
1299 if (!WriteChecked) {
1301 &ExclusionSet, IsLiveInCalleeCB))
1302 WriteChecked =
true;
1316 if (!WriteChecked && HasBeenWrittenTo &&
1317 Acc.getRemoteInst()->getFunction() != &Scope) {
1319 const auto *FnReachabilityAA =
A.getAAFor<AAInterFnReachability>(
1321 if (FnReachabilityAA) {
1327 if (!FnReachabilityAA->instructionCanReach(
1328 A, *LeastDominatingWriteInst,
1329 *Acc.getRemoteInst()->getFunction(), &ExclusionSet))
1330 WriteChecked =
true;
1337 if (ReadChecked && WriteChecked)
1340 if (!DT || !UseDominanceReasoning)
1342 if (!DominatingWrites.count(&Acc))
1344 return LeastDominatingWriteInst != Acc.getRemoteInst();
1349 for (
auto &It : InterferingAccesses) {
1350 if ((!AllInSameNoSyncFn && !IsThreadLocalObj && !ExecDomainAA) ||
1351 !CanSkipAccess(*It.first, It.second)) {
1352 if (!UserCB(*It.first, It.second))
1360 const AAPointerInfo &OtherAA,
1362 using namespace AA::PointerInfo;
1364 return indicatePessimisticFixpoint();
1367 const auto &OtherAAImpl =
static_cast<const AAPointerInfoImpl &
>(OtherAA);
1368 bool IsByval = OtherAAImpl.getAssociatedArgument()->hasByValAttr();
1369 Changed |= setReachesReturn(OtherAAImpl.ReturnedOffsets);
1372 const auto &State = OtherAAImpl.getState();
1373 for (
const auto &It : State) {
1374 for (
auto Index : It.getSecond()) {
1375 const auto &RAcc = State.getAccess(Index);
1376 if (IsByval && !RAcc.isRead())
1378 bool UsedAssumedInformation =
false;
1380 auto Content =
A.translateArgumentToCallSiteContent(
1381 RAcc.getContent(), CB, *
this, UsedAssumedInformation);
1382 AK =
AccessKind(AK & (IsByval ? AccessKind::AK_R : AccessKind::AK_RW));
1383 AK =
AccessKind(AK | (RAcc.isMayAccess() ? AK_MAY : AK_MUST));
1385 Changed |= addAccess(
A, RAcc.getRanges(), CB, Content, AK,
1386 RAcc.getType(), RAcc.getRemoteInst());
1392 ChangeStatus translateAndAddState(Attributor &
A,
const AAPointerInfo &OtherAA,
1393 const OffsetInfo &Offsets, CallBase &CB,
1395 using namespace AA::PointerInfo;
1397 return indicatePessimisticFixpoint();
1399 const auto &OtherAAImpl =
static_cast<const AAPointerInfoImpl &
>(OtherAA);
1403 const auto &State = OtherAAImpl.getState();
1404 for (
const auto &It : State) {
1405 for (
auto Index : It.getSecond()) {
1406 const auto &RAcc = State.getAccess(Index);
1407 if (!IsMustAcc && RAcc.isAssumption())
1409 for (
auto Offset : Offsets) {
1413 if (!NewRanges.isUnknown()) {
1414 NewRanges.addToAllOffsets(Offset);
1419 Changed |= addAccess(
A, NewRanges, CB, RAcc.getContent(), AK,
1420 RAcc.getType(), RAcc.getRemoteInst());
1429 void trackPointerInfoStatistics(
const IRPosition &IRP)
const {}
1432 void dumpState(raw_ostream &O) {
1433 for (
auto &It : OffsetBins) {
1434 O <<
"[" << It.first.Offset <<
"-" << It.first.Offset + It.first.Size
1435 <<
"] : " << It.getSecond().size() <<
"\n";
1436 for (
auto AccIndex : It.getSecond()) {
1437 auto &Acc = AccessList[AccIndex];
1438 O <<
" - " << Acc.getKind() <<
" - " << *Acc.getLocalInst() <<
"\n";
1439 if (Acc.getLocalInst() != Acc.getRemoteInst())
1440 O <<
" --> " << *Acc.getRemoteInst()
1442 if (!Acc.isWrittenValueYetUndetermined()) {
1444 O <<
" - c: func " << Acc.getWrittenValue()->getName()
1446 else if (Acc.getWrittenValue())
1447 O <<
" - c: " << *Acc.getWrittenValue() <<
"\n";
1449 O <<
" - c: <unknown>\n";
1456struct AAPointerInfoFloating :
public AAPointerInfoImpl {
1458 AAPointerInfoFloating(
const IRPosition &IRP, Attributor &
A)
1459 : AAPointerInfoImpl(IRP,
A) {}
1462 bool handleAccess(Attributor &
A, Instruction &
I,
1463 std::optional<Value *> Content,
AccessKind Kind,
1466 using namespace AA::PointerInfo;
1468 const DataLayout &
DL =
A.getDataLayout();
1469 TypeSize AccessSize =
DL.getTypeStoreSize(&Ty);
1478 if (!VT || VT->getElementCount().isScalable() ||
1480 (*Content)->getType() != VT ||
1481 DL.getTypeStoreSize(VT->getElementType()).isScalable()) {
1492 int64_t ElementSize =
DL.getTypeStoreSize(ElementType).getFixedValue();
1497 for (
int i = 0, e = VT->getElementCount().getFixedValue(); i != e; ++i) {
1499 ConstContent, ConstantInt::get(
Int32Ty, i));
1506 for (
auto &ElementOffset : ElementOffsets)
1507 ElementOffset += ElementSize;
1520 bool collectConstantsForGEP(Attributor &
A,
const DataLayout &
DL,
1521 OffsetInfo &UsrOI,
const OffsetInfo &PtrOI,
1522 const GEPOperator *
GEP);
1525 void trackStatistics()
const override {
1526 AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());
1530bool AAPointerInfoFloating::collectConstantsForGEP(Attributor &
A,
1531 const DataLayout &
DL,
1533 const OffsetInfo &PtrOI,
1534 const GEPOperator *
GEP) {
1535 unsigned BitWidth =
DL.getIndexTypeSizeInBits(
GEP->getType());
1536 SmallMapVector<Value *, APInt, 4> VariableOffsets;
1539 assert(!UsrOI.isUnknown() && !PtrOI.isUnknown() &&
1540 "Don't look for constant values if the offset has already been "
1541 "determined to be unknown.");
1543 if (!
GEP->collectOffset(
DL,
BitWidth, VariableOffsets, ConstantOffset)) {
1549 << (VariableOffsets.
empty() ?
"" :
"not") <<
" constant "
1553 Union.addToAll(ConstantOffset.getSExtValue());
1558 for (
const auto &VI : VariableOffsets) {
1559 auto *PotentialConstantsAA =
A.getAAFor<AAPotentialConstantValues>(
1561 if (!PotentialConstantsAA || !PotentialConstantsAA->isValidState()) {
1567 if (PotentialConstantsAA->undefIsContained())
1574 auto &AssumedSet = PotentialConstantsAA->getAssumedSet();
1575 if (AssumedSet.empty())
1579 for (
const auto &ConstOffset : AssumedSet) {
1580 auto CopyPerOffset =
Union;
1581 CopyPerOffset.addToAll(ConstOffset.getSExtValue() *
1582 VI.second.getZExtValue());
1583 Product.merge(CopyPerOffset);
1588 UsrOI = std::move(Union);
1592ChangeStatus AAPointerInfoFloating::updateImpl(Attributor &
A) {
1593 using namespace AA::PointerInfo;
1595 const DataLayout &
DL =
A.getDataLayout();
1596 Value &AssociatedValue = getAssociatedValue();
1598 DenseMap<Value *, OffsetInfo> OffsetInfoMap;
1599 OffsetInfoMap[&AssociatedValue].
insert(0);
1601 auto HandlePassthroughUser = [&](
Value *Usr,
Value *CurPtr,
bool &Follow) {
1612 "CurPtr does not exist in the map!");
1614 auto &UsrOI = OffsetInfoMap[Usr];
1615 auto &PtrOI = OffsetInfoMap[CurPtr];
1616 assert(!PtrOI.isUnassigned() &&
1617 "Cannot pass through if the input Ptr was not visited!");
1623 auto UsePred = [&](
const Use &
U,
bool &Follow) ->
bool {
1625 User *Usr =
U.getUser();
1626 LLVM_DEBUG(
dbgs() <<
"[AAPointerInfo] Analyze " << *CurPtr <<
" in " << *Usr
1629 "The current pointer offset should have been seeded!");
1630 assert(!OffsetInfoMap[CurPtr].isUnassigned() &&
1631 "Current pointer should be assigned");
1635 return HandlePassthroughUser(Usr, CurPtr, Follow);
1637 LLVM_DEBUG(
dbgs() <<
"[AAPointerInfo] Unhandled constant user " << *CE
1645 auto &UsrOI = OffsetInfoMap[Usr];
1646 auto &PtrOI = OffsetInfoMap[CurPtr];
1648 if (UsrOI.isUnknown())
1651 if (PtrOI.isUnknown()) {
1657 Follow = collectConstantsForGEP(
A,
DL, UsrOI, PtrOI,
GEP);
1663 return HandlePassthroughUser(Usr, CurPtr, Follow);
1668 if (RI->getFunction() == getAssociatedFunction()) {
1669 auto &PtrOI = OffsetInfoMap[CurPtr];
1670 Changed |= setReachesReturn(PtrOI);
1683 auto &UsrOI = PhiIt->second;
1684 auto &PtrOI = OffsetInfoMap[CurPtr];
1688 if (PtrOI.isUnknown()) {
1689 LLVM_DEBUG(
dbgs() <<
"[AAPointerInfo] PHI operand offset unknown "
1690 << *CurPtr <<
" in " << *
PHI <<
"\n");
1691 Follow = !UsrOI.isUnknown();
1697 if (UsrOI == PtrOI) {
1698 assert(!PtrOI.isUnassigned() &&
1699 "Cannot assign if the current Ptr was not visited!");
1700 LLVM_DEBUG(
dbgs() <<
"[AAPointerInfo] PHI is invariant (so far)");
1710 auto It = OffsetInfoMap.
find(CurPtrBase);
1711 if (It == OffsetInfoMap.
end()) {
1712 LLVM_DEBUG(
dbgs() <<
"[AAPointerInfo] PHI operand is too complex "
1713 << *CurPtr <<
" in " << *
PHI
1714 <<
" (base: " << *CurPtrBase <<
")\n");
1728 A.getInfoCache().getAnalysisResultForFunction<CycleAnalysis>(
1729 *
PHI->getFunction());
1731 auto BaseOI = It->getSecond();
1732 BaseOI.addToAll(
Offset.getZExtValue());
1733 if (IsFirstPHIUser || BaseOI == UsrOI) {
1734 LLVM_DEBUG(
dbgs() <<
"[AAPointerInfo] PHI is invariant " << *CurPtr
1735 <<
" in " << *Usr <<
"\n");
1736 return HandlePassthroughUser(Usr, CurPtr, Follow);
1740 dbgs() <<
"[AAPointerInfo] PHI operand pointer offset mismatch "
1741 << *CurPtr <<
" in " << *
PHI <<
"\n");
1760 if (!handleAccess(
A, *LoadI,
nullptr, AK,
1761 OffsetInfoMap[CurPtr].Offsets,
Changed,
1767 return II->isAssumeLikeIntrinsic();
1778 }
while (FromI && FromI != ToI);
1783 auto IsValidAssume = [&](IntrinsicInst &IntrI) {
1784 if (IntrI.getIntrinsicID() != Intrinsic::assume)
1787 if (IntrI.getParent() == BB) {
1788 if (IsImpactedInRange(LoadI->getNextNode(), &IntrI))
1794 if ((*PredIt) != BB)
1799 if (SuccBB == IntrBB)
1805 if (IsImpactedInRange(LoadI->getNextNode(), BB->
getTerminator()))
1807 if (IsImpactedInRange(&IntrBB->
front(), &IntrI))
1813 std::pair<Value *, IntrinsicInst *> Assumption;
1814 for (
const Use &LoadU : LoadI->uses()) {
1816 if (!CmpI->isEquality() || !CmpI->isTrueWhenEqual())
1818 for (
const Use &CmpU : CmpI->uses()) {
1820 if (!IsValidAssume(*IntrI))
1822 int Idx = CmpI->getOperandUse(0) == LoadU;
1823 Assumption = {CmpI->getOperand(Idx), IntrI};
1828 if (Assumption.first)
1833 if (!Assumption.first || !Assumption.second)
1837 << *Assumption.second <<
": " << *LoadI
1838 <<
" == " << *Assumption.first <<
"\n");
1839 bool UsedAssumedInformation =
false;
1840 std::optional<Value *> Content =
nullptr;
1841 if (Assumption.first)
1843 A.getAssumedSimplified(*Assumption.first, *
this,
1845 return handleAccess(
1846 A, *Assumption.second, Content, AccessKind::AK_ASSUMPTION,
1847 OffsetInfoMap[CurPtr].Offsets,
Changed, *LoadI->getType());
1852 for (
auto *OtherOp : OtherOps) {
1853 if (OtherOp == CurPtr) {
1856 <<
"[AAPointerInfo] Escaping use in store like instruction " <<
I
1868 bool UsedAssumedInformation =
false;
1869 std::optional<Value *> Content =
nullptr;
1871 Content =
A.getAssumedSimplified(
1873 return handleAccess(
A,
I, Content, AK, OffsetInfoMap[CurPtr].Offsets,
1878 return HandleStoreLike(*StoreI, StoreI->getValueOperand(),
1879 *StoreI->getValueOperand()->getType(),
1880 {StoreI->getValueOperand()}, AccessKind::AK_W);
1882 return HandleStoreLike(*RMWI,
nullptr, *RMWI->getValOperand()->getType(),
1883 {RMWI->getValOperand()}, AccessKind::AK_RW);
1885 return HandleStoreLike(
1886 *CXI,
nullptr, *CXI->getNewValOperand()->getType(),
1887 {CXI->getCompareOperand(), CXI->getNewValOperand()},
1894 A.getInfoCache().getTargetLibraryInfoForFunction(*CB->
getFunction());
1899 const auto *CSArgPI =
A.getAAFor<AAPointerInfo>(
1905 Changed = translateAndAddState(
A, *CSArgPI, OffsetInfoMap[CurPtr], *CB,
1908 if (!CSArgPI->reachesReturn())
1909 return isValidState();
1912 if (!Callee ||
Callee->arg_size() <= ArgNo)
1914 bool UsedAssumedInformation =
false;
1915 auto ReturnedValue =
A.getAssumedSimplified(
1920 auto *Arg =
Callee->getArg(ArgNo);
1921 if (ReturnedArg && Arg != ReturnedArg)
1923 bool IsRetMustAcc = IsArgMustAcc && (ReturnedArg == Arg);
1924 const auto *CSRetPI =
A.getAAFor<AAPointerInfo>(
1928 OffsetInfo OI = OffsetInfoMap[CurPtr];
1929 CSArgPI->addReturnedOffsetsTo(OI);
1931 translateAndAddState(
A, *CSRetPI, OI, *CB, IsRetMustAcc) |
Changed;
1932 return isValidState();
1934 LLVM_DEBUG(
dbgs() <<
"[AAPointerInfo] Call user not handled " << *CB
1939 LLVM_DEBUG(
dbgs() <<
"[AAPointerInfo] User not handled " << *Usr <<
"\n");
1942 auto EquivalentUseCB = [&](
const Use &OldU,
const Use &NewU) {
1943 assert(OffsetInfoMap.
count(OldU) &&
"Old use should be known already!");
1944 assert(!OffsetInfoMap[OldU].isUnassigned() &&
"Old use should be assinged");
1945 if (OffsetInfoMap.
count(NewU)) {
1947 if (!(OffsetInfoMap[NewU] == OffsetInfoMap[OldU])) {
1948 dbgs() <<
"[AAPointerInfo] Equivalent use callback failed: "
1949 << OffsetInfoMap[NewU] <<
" vs " << OffsetInfoMap[OldU]
1953 return OffsetInfoMap[NewU] == OffsetInfoMap[OldU];
1956 return HandlePassthroughUser(NewU.get(), OldU.
get(), Unused);
1958 if (!
A.checkForAllUses(UsePred, *
this, AssociatedValue,
1960 true, EquivalentUseCB)) {
1961 LLVM_DEBUG(
dbgs() <<
"[AAPointerInfo] Check for all uses failed, abort!\n");
1962 return indicatePessimisticFixpoint();
1966 dbgs() <<
"Accesses by bin after update:\n";
1973struct AAPointerInfoReturned final : AAPointerInfoImpl {
1974 AAPointerInfoReturned(
const IRPosition &IRP, Attributor &
A)
1975 : AAPointerInfoImpl(IRP,
A) {}
1979 return indicatePessimisticFixpoint();
1983 void trackStatistics()
const override {
1984 AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());
1988struct AAPointerInfoArgument final : AAPointerInfoFloating {
1989 AAPointerInfoArgument(
const IRPosition &IRP, Attributor &
A)
1990 : AAPointerInfoFloating(IRP,
A) {}
1993 void trackStatistics()
const override {
1994 AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());
1998struct AAPointerInfoCallSiteArgument final : AAPointerInfoFloating {
1999 AAPointerInfoCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
2000 : AAPointerInfoFloating(IRP,
A) {}
2004 using namespace AA::PointerInfo;
2010 if (
auto Length =
MI->getLengthInBytes())
2011 LengthVal =
Length->getSExtValue();
2012 unsigned ArgNo = getIRPosition().getCallSiteArgNo();
2015 LLVM_DEBUG(
dbgs() <<
"[AAPointerInfo] Unhandled memory intrinsic "
2017 return indicatePessimisticFixpoint();
2020 ArgNo == 0 ? AccessKind::AK_MUST_WRITE : AccessKind::AK_MUST_READ;
2022 Changed | addAccess(
A, {0, LengthVal}, *
MI,
nullptr,
Kind,
nullptr);
2025 dbgs() <<
"Accesses by bin after update:\n";
2036 Argument *Arg = getAssociatedArgument();
2040 A.getAAFor<AAPointerInfo>(*
this, ArgPos, DepClassTy::REQUIRED);
2041 if (ArgAA && ArgAA->getState().isValidState())
2042 return translateAndAddStateFromCallee(
A, *ArgAA,
2045 return indicatePessimisticFixpoint();
2048 bool IsKnownNoCapture;
2050 A,
this, getIRPosition(), DepClassTy::OPTIONAL, IsKnownNoCapture))
2051 return indicatePessimisticFixpoint();
2053 bool IsKnown =
false;
2055 return ChangeStatus::UNCHANGED;
2058 ReadOnly ? AccessKind::AK_MAY_READ : AccessKind::AK_MAY_READ_WRITE;
2064 void trackStatistics()
const override {
2065 AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());
2069struct AAPointerInfoCallSiteReturned final : AAPointerInfoFloating {
2070 AAPointerInfoCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
2071 : AAPointerInfoFloating(IRP,
A) {}
2074 void trackStatistics()
const override {
2075 AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());
2083struct AANoUnwindImpl : AANoUnwind {
2084 AANoUnwindImpl(
const IRPosition &IRP, Attributor &
A) : AANoUnwind(IRP,
A) {}
2090 A,
nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));
2094 const std::string getAsStr(Attributor *
A)
const override {
2095 return getAssumed() ?
"nounwind" :
"may-unwind";
2101 (unsigned)Instruction::Invoke, (
unsigned)Instruction::CallBr,
2102 (unsigned)Instruction::Call, (
unsigned)Instruction::CleanupRet,
2103 (unsigned)Instruction::CatchSwitch, (
unsigned)Instruction::Resume};
2106 if (!
I.mayThrow(
true))
2110 bool IsKnownNoUnwind;
2118 bool UsedAssumedInformation =
false;
2119 if (!
A.checkForAllInstructions(CheckForNoUnwind, *
this, Opcodes,
2120 UsedAssumedInformation))
2121 return indicatePessimisticFixpoint();
2123 return ChangeStatus::UNCHANGED;
2127struct AANoUnwindFunction final :
public AANoUnwindImpl {
2128 AANoUnwindFunction(
const IRPosition &IRP, Attributor &
A)
2129 : AANoUnwindImpl(IRP,
A) {}
2136struct AANoUnwindCallSite final
2137 : AACalleeToCallSite<AANoUnwind, AANoUnwindImpl> {
2138 AANoUnwindCallSite(
const IRPosition &IRP, Attributor &
A)
2139 : AACalleeToCallSite<AANoUnwind, AANoUnwindImpl>(IRP,
A) {}
2150 case Intrinsic::nvvm_barrier_cta_sync_aligned_all:
2151 case Intrinsic::nvvm_barrier_cta_sync_aligned_count:
2152 case Intrinsic::nvvm_barrier_cta_red_and_aligned_all:
2153 case Intrinsic::nvvm_barrier_cta_red_and_aligned_count:
2154 case Intrinsic::nvvm_barrier_cta_red_or_aligned_all:
2155 case Intrinsic::nvvm_barrier_cta_red_or_aligned_count:
2156 case Intrinsic::nvvm_barrier_cta_red_popc_aligned_all:
2157 case Intrinsic::nvvm_barrier_cta_red_popc_aligned_count:
2159 case Intrinsic::amdgcn_s_barrier:
2160 if (ExecutedAligned)
2183 switch (
I->getOpcode()) {
2184 case Instruction::AtomicRMW:
2187 case Instruction::Store:
2190 case Instruction::Load:
2195 "New atomic operations need to be known in the attributor.");
2207 return !
MI->isVolatile();
2223 const std::string getAsStr(Attributor *
A)
const override {
2224 return getAssumed() ?
"nosync" :
"may-sync";
2240 if (
I.mayReadOrWriteMemory())
2254 bool UsedAssumedInformation =
false;
2255 if (!
A.checkForAllReadWriteInstructions(CheckRWInstForNoSync, *
this,
2256 UsedAssumedInformation) ||
2257 !
A.checkForAllCallLikeInstructions(CheckForNoSync, *
this,
2258 UsedAssumedInformation))
2259 return indicatePessimisticFixpoint();
2264struct AANoSyncFunction final :
public AANoSyncImpl {
2265 AANoSyncFunction(
const IRPosition &IRP, Attributor &
A)
2266 : AANoSyncImpl(IRP,
A) {}
2273struct AANoSyncCallSite final : AACalleeToCallSite<AANoSync, AANoSyncImpl> {
2274 AANoSyncCallSite(
const IRPosition &IRP, Attributor &
A)
2275 : AACalleeToCallSite<AANoSync, AANoSyncImpl>(IRP,
A) {}
2285struct AANoFreeImpl :
public AANoFree {
2286 AANoFreeImpl(
const IRPosition &IRP, Attributor &
A) : AANoFree(IRP,
A) {}
2292 DepClassTy::NONE, IsKnown));
2302 DepClassTy::REQUIRED, IsKnown);
2305 bool UsedAssumedInformation =
false;
2306 if (!
A.checkForAllCallLikeInstructions(CheckForNoFree, *
this,
2307 UsedAssumedInformation))
2308 return indicatePessimisticFixpoint();
2309 return ChangeStatus::UNCHANGED;
2313 const std::string getAsStr(Attributor *
A)
const override {
2314 return getAssumed() ?
"nofree" :
"may-free";
2318struct AANoFreeFunction final :
public AANoFreeImpl {
2319 AANoFreeFunction(
const IRPosition &IRP, Attributor &
A)
2320 : AANoFreeImpl(IRP,
A) {}
2327struct AANoFreeCallSite final : AACalleeToCallSite<AANoFree, AANoFreeImpl> {
2328 AANoFreeCallSite(
const IRPosition &IRP, Attributor &
A)
2329 : AACalleeToCallSite<AANoFree, AANoFreeImpl>(IRP,
A) {}
2336struct AANoFreeFloating : AANoFreeImpl {
2337 AANoFreeFloating(
const IRPosition &IRP, Attributor &
A)
2338 : AANoFreeImpl(IRP,
A) {}
2345 const IRPosition &IRP = getIRPosition();
2350 DepClassTy::OPTIONAL, IsKnown))
2351 return ChangeStatus::UNCHANGED;
2353 Value &AssociatedValue = getIRPosition().getAssociatedValue();
2354 auto Pred = [&](
const Use &
U,
bool &Follow) ->
bool {
2366 DepClassTy::REQUIRED, IsKnown);
2383 if (!
A.checkForAllUses(Pred, *
this, AssociatedValue))
2384 return indicatePessimisticFixpoint();
2386 return ChangeStatus::UNCHANGED;
2391struct AANoFreeArgument final : AANoFreeFloating {
2392 AANoFreeArgument(
const IRPosition &IRP, Attributor &
A)
2393 : AANoFreeFloating(IRP,
A) {}
2400struct AANoFreeCallSiteArgument final : AANoFreeFloating {
2401 AANoFreeCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
2402 : AANoFreeFloating(IRP,
A) {}
2410 Argument *Arg = getAssociatedArgument();
2412 return indicatePessimisticFixpoint();
2416 DepClassTy::REQUIRED, IsKnown))
2417 return ChangeStatus::UNCHANGED;
2418 return indicatePessimisticFixpoint();
2426struct AANoFreeReturned final : AANoFreeFloating {
2427 AANoFreeReturned(
const IRPosition &IRP, Attributor &
A)
2428 : AANoFreeFloating(IRP,
A) {
2443 void trackStatistics()
const override {}
2447struct AANoFreeCallSiteReturned final : AANoFreeFloating {
2448 AANoFreeCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
2449 : AANoFreeFloating(IRP,
A) {}
2452 return ChangeStatus::UNCHANGED;
2463 bool IgnoreSubsumingPositions) {
2465 AttrKinds.
push_back(Attribute::NonNull);
2468 AttrKinds.
push_back(Attribute::Dereferenceable);
2469 if (
A.hasAttr(IRP, AttrKinds, IgnoreSubsumingPositions, Attribute::NonNull))
2476 if (!Fn->isDeclaration()) {
2486 bool UsedAssumedInformation =
false;
2487 if (!
A.checkForAllInstructions(
2489 Worklist.push_back({*cast<ReturnInst>(I).getReturnValue(), &I});
2493 UsedAssumedInformation,
false,
true))
2505 Attribute::NonNull)});
2510static int64_t getKnownNonNullAndDerefBytesForUse(
2511 Attributor &
A,
const AbstractAttribute &QueryingAA,
Value &AssociatedValue,
2512 const Use *U,
const Instruction *
I,
bool &IsNonNull,
bool &TrackUse) {
2515 const Value *UseV =
U->get();
2536 const DataLayout &
DL =
A.getInfoCache().getDL();
2540 U, {Attribute::NonNull, Attribute::Dereferenceable})) {
2557 bool IsKnownNonNull;
2560 IsNonNull |= IsKnownNonNull;
2563 return DerefAA ? DerefAA->getKnownDereferenceableBytes() : 0;
2567 if (!Loc || Loc->Ptr != UseV || !Loc->Size.isPrecise() ||
2568 Loc->Size.isScalable() ||
I->isVolatile())
2574 if (
Base &&
Base == &AssociatedValue) {
2575 int64_t DerefBytes = Loc->Size.getValue() +
Offset;
2577 return std::max(int64_t(0), DerefBytes);
2584 int64_t DerefBytes = Loc->Size.getValue();
2586 return std::max(int64_t(0), DerefBytes);
2592struct AANonNullImpl : AANonNull {
2593 AANonNullImpl(
const IRPosition &IRP, Attributor &
A) : AANonNull(IRP,
A) {}
2597 Value &
V = *getAssociatedValue().stripPointerCasts();
2599 indicatePessimisticFixpoint();
2603 if (Instruction *CtxI = getCtxI())
2604 followUsesInMBEC(*
this,
A, getState(), *CtxI);
2608 bool followUseInMBEC(Attributor &
A,
const Use *U,
const Instruction *
I,
2609 AANonNull::StateType &State) {
2610 bool IsNonNull =
false;
2611 bool TrackUse =
false;
2612 getKnownNonNullAndDerefBytesForUse(
A, *
this, getAssociatedValue(), U,
I,
2613 IsNonNull, TrackUse);
2614 State.setKnown(IsNonNull);
2619 const std::string getAsStr(Attributor *
A)
const override {
2620 return getAssumed() ?
"nonnull" :
"may-null";
2625struct AANonNullFloating :
public AANonNullImpl {
2626 AANonNullFloating(
const IRPosition &IRP, Attributor &
A)
2627 : AANonNullImpl(IRP,
A) {}
2631 auto CheckIRP = [&](
const IRPosition &IRP) {
2632 bool IsKnownNonNull;
2634 A, *
this, IRP, DepClassTy::OPTIONAL, IsKnownNonNull);
2638 bool UsedAssumedInformation =
false;
2639 Value *AssociatedValue = &getAssociatedValue();
2641 if (!
A.getAssumedSimplifiedValues(getIRPosition(), *
this, Values,
2646 Values.
size() != 1 || Values.
front().getValue() != AssociatedValue;
2652 return AA::hasAssumedIRAttr<Attribute::NonNull>(
2653 A, this, IRPosition::value(*Op), DepClassTy::OPTIONAL,
2656 return ChangeStatus::UNCHANGED;
2660 DepClassTy::OPTIONAL, IsKnown) &&
2663 DepClassTy::OPTIONAL, IsKnown))
2664 return ChangeStatus::UNCHANGED;
2671 if (AVIRP == getIRPosition() || !CheckIRP(AVIRP))
2672 return indicatePessimisticFixpoint();
2673 return ChangeStatus::UNCHANGED;
2676 for (
const auto &VAC : Values)
2678 return indicatePessimisticFixpoint();
2680 return ChangeStatus::UNCHANGED;
2688struct AANonNullReturned final
2689 : AAReturnedFromReturnedValues<AANonNull, AANonNull, AANonNull::StateType,
2690 false, AANonNull::IRAttributeKind, false> {
2691 AANonNullReturned(
const IRPosition &IRP, Attributor &
A)
2692 : AAReturnedFromReturnedValues<AANonNull, AANonNull, AANonNull::StateType,
2697 const std::string getAsStr(Attributor *
A)
const override {
2698 return getAssumed() ?
"nonnull" :
"may-null";
2706struct AANonNullArgument final
2707 : AAArgumentFromCallSiteArguments<AANonNull, AANonNullImpl> {
2708 AANonNullArgument(
const IRPosition &IRP, Attributor &
A)
2709 : AAArgumentFromCallSiteArguments<AANonNull, AANonNullImpl>(IRP,
A) {}
2715struct AANonNullCallSiteArgument final : AANonNullFloating {
2716 AANonNullCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
2717 : AANonNullFloating(IRP,
A) {}
2724struct AANonNullCallSiteReturned final
2725 : AACalleeToCallSite<AANonNull, AANonNullImpl> {
2726 AANonNullCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
2727 : AACalleeToCallSite<AANonNull, AANonNullImpl>(IRP,
A) {}
2736struct AAMustProgressImpl :
public AAMustProgress {
2737 AAMustProgressImpl(
const IRPosition &IRP, Attributor &
A)
2738 : AAMustProgress(IRP,
A) {}
2744 A,
nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));
2749 const std::string getAsStr(Attributor *
A)
const override {
2750 return getAssumed() ?
"mustprogress" :
"may-not-progress";
2754struct AAMustProgressFunction final : AAMustProgressImpl {
2755 AAMustProgressFunction(
const IRPosition &IRP, Attributor &
A)
2756 : AAMustProgressImpl(IRP,
A) {}
2762 A,
this, getIRPosition(), DepClassTy::OPTIONAL, IsKnown)) {
2764 return indicateOptimisticFixpoint();
2765 return ChangeStatus::UNCHANGED;
2768 auto CheckForMustProgress = [&](AbstractCallSite ACS) {
2770 bool IsKnownMustProgress;
2772 A,
this, IPos, DepClassTy::REQUIRED, IsKnownMustProgress,
2776 bool AllCallSitesKnown =
true;
2777 if (!
A.checkForAllCallSites(CheckForMustProgress, *
this,
2780 return indicatePessimisticFixpoint();
2782 return ChangeStatus::UNCHANGED;
2786 void trackStatistics()
const override {
2792struct AAMustProgressCallSite final : AAMustProgressImpl {
2793 AAMustProgressCallSite(
const IRPosition &IRP, Attributor &
A)
2794 : AAMustProgressImpl(IRP,
A) {}
2803 bool IsKnownMustProgress;
2805 A,
this, FnPos, DepClassTy::REQUIRED, IsKnownMustProgress))
2806 return indicatePessimisticFixpoint();
2807 return ChangeStatus::UNCHANGED;
2811 void trackStatistics()
const override {
2820struct AANoRecurseImpl :
public AANoRecurse {
2821 AANoRecurseImpl(
const IRPosition &IRP, Attributor &
A) : AANoRecurse(IRP,
A) {}
2827 A,
nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));
2832 const std::string getAsStr(Attributor *
A)
const override {
2833 return getAssumed() ?
"norecurse" :
"may-recurse";
2837struct AANoRecurseFunction final : AANoRecurseImpl {
2838 AANoRecurseFunction(
const IRPosition &IRP, Attributor &
A)
2839 : AANoRecurseImpl(IRP,
A) {}
2845 auto CallSitePred = [&](AbstractCallSite ACS) {
2846 bool IsKnownNoRecurse;
2850 DepClassTy::NONE, IsKnownNoRecurse))
2852 return IsKnownNoRecurse;
2854 bool UsedAssumedInformation =
false;
2855 if (
A.checkForAllCallSites(CallSitePred, *
this,
true,
2856 UsedAssumedInformation)) {
2862 if (!UsedAssumedInformation)
2863 indicateOptimisticFixpoint();
2864 return ChangeStatus::UNCHANGED;
2867 const AAInterFnReachability *EdgeReachability =
2868 A.getAAFor<AAInterFnReachability>(*
this, getIRPosition(),
2869 DepClassTy::REQUIRED);
2870 if (EdgeReachability && EdgeReachability->
canReach(
A, *getAnchorScope()))
2871 return indicatePessimisticFixpoint();
2872 return ChangeStatus::UNCHANGED;
2879struct AANoRecurseCallSite final
2880 : AACalleeToCallSite<AANoRecurse, AANoRecurseImpl> {
2881 AANoRecurseCallSite(
const IRPosition &IRP, Attributor &
A)
2882 : AACalleeToCallSite<AANoRecurse, AANoRecurseImpl>(IRP,
A) {}
2892struct AANonConvergentImpl :
public AANonConvergent {
2893 AANonConvergentImpl(
const IRPosition &IRP, Attributor &
A)
2894 : AANonConvergent(IRP,
A) {}
2897 const std::string getAsStr(Attributor *
A)
const override {
2898 return getAssumed() ?
"non-convergent" :
"may-be-convergent";
2902struct AANonConvergentFunction final : AANonConvergentImpl {
2903 AANonConvergentFunction(
const IRPosition &IRP, Attributor &
A)
2904 : AANonConvergentImpl(IRP,
A) {}
2910 auto CalleeIsNotConvergent = [&](
Instruction &Inst) {
2913 if (!Callee ||
Callee->isIntrinsic()) {
2916 if (
Callee->isDeclaration()) {
2917 return !
Callee->hasFnAttribute(Attribute::Convergent);
2919 const auto *ConvergentAA =
A.getAAFor<AANonConvergent>(
2921 return ConvergentAA && ConvergentAA->isAssumedNotConvergent();
2924 bool UsedAssumedInformation =
false;
2925 if (!
A.checkForAllCallLikeInstructions(CalleeIsNotConvergent, *
this,
2926 UsedAssumedInformation)) {
2927 return indicatePessimisticFixpoint();
2929 return ChangeStatus::UNCHANGED;
2933 if (isKnownNotConvergent() &&
2934 A.hasAttr(getIRPosition(), Attribute::Convergent)) {
2935 A.removeAttrs(getIRPosition(), {Attribute::Convergent});
2936 return ChangeStatus::CHANGED;
2938 return ChangeStatus::UNCHANGED;
2948struct AAUndefinedBehaviorImpl :
public AAUndefinedBehavior {
2949 AAUndefinedBehaviorImpl(
const IRPosition &IRP, Attributor &
A)
2950 : AAUndefinedBehavior(IRP,
A) {}
2955 const size_t UBPrevSize = KnownUBInsts.size();
2956 const size_t NoUBPrevSize = AssumedNoUBInsts.size();
2960 if (
I.isVolatile() &&
I.mayWriteToMemory())
2964 if (AssumedNoUBInsts.count(&
I) || KnownUBInsts.count(&
I))
2973 "Expected pointer operand of memory accessing instruction");
2977 std::optional<Value *> SimplifiedPtrOp =
2978 stopOnUndefOrAssumed(
A, PtrOp, &
I);
2979 if (!SimplifiedPtrOp || !*SimplifiedPtrOp)
2981 const Value *PtrOpVal = *SimplifiedPtrOp;
2987 AssumedNoUBInsts.insert(&
I);
2999 AssumedNoUBInsts.insert(&
I);
3001 KnownUBInsts.insert(&
I);
3010 if (AssumedNoUBInsts.count(&
I) || KnownUBInsts.count(&
I))
3017 if (BrInst->isUnconditional())
3022 std::optional<Value *> SimplifiedCond =
3023 stopOnUndefOrAssumed(
A, BrInst->getCondition(), BrInst);
3024 if (!SimplifiedCond || !*SimplifiedCond)
3026 AssumedNoUBInsts.insert(&
I);
3034 if (AssumedNoUBInsts.count(&
I) || KnownUBInsts.count(&
I))
3043 for (
unsigned idx = 0; idx < CB.
arg_size(); idx++) {
3049 if (idx >=
Callee->arg_size())
3061 bool IsKnownNoUndef;
3063 A,
this, CalleeArgumentIRP, DepClassTy::NONE, IsKnownNoUndef);
3064 if (!IsKnownNoUndef)
3066 bool UsedAssumedInformation =
false;
3067 std::optional<Value *> SimplifiedVal =
3070 if (UsedAssumedInformation)
3072 if (SimplifiedVal && !*SimplifiedVal)
3075 KnownUBInsts.insert(&
I);
3081 bool IsKnownNonNull;
3083 A,
this, CalleeArgumentIRP, DepClassTy::NONE, IsKnownNonNull);
3085 KnownUBInsts.insert(&
I);
3094 std::optional<Value *> SimplifiedRetValue =
3095 stopOnUndefOrAssumed(
A, RI.getReturnValue(), &
I);
3096 if (!SimplifiedRetValue || !*SimplifiedRetValue)
3114 bool IsKnownNonNull;
3119 KnownUBInsts.insert(&
I);
3125 bool UsedAssumedInformation =
false;
3126 A.checkForAllInstructions(InspectMemAccessInstForUB, *
this,
3127 {Instruction::Load, Instruction::Store,
3128 Instruction::AtomicCmpXchg,
3129 Instruction::AtomicRMW},
3130 UsedAssumedInformation,
3132 A.checkForAllInstructions(InspectBrInstForUB, *
this, {Instruction::Br},
3133 UsedAssumedInformation,
3135 A.checkForAllCallLikeInstructions(InspectCallSiteForUB, *
this,
3136 UsedAssumedInformation);
3140 if (!getAnchorScope()->getReturnType()->isVoidTy()) {
3142 if (!
A.isAssumedDead(ReturnIRP,
this,
nullptr, UsedAssumedInformation)) {
3143 bool IsKnownNoUndef;
3145 A,
this, ReturnIRP, DepClassTy::NONE, IsKnownNoUndef);
3147 A.checkForAllInstructions(InspectReturnInstForUB, *
this,
3148 {Instruction::Ret}, UsedAssumedInformation,
3153 if (NoUBPrevSize != AssumedNoUBInsts.size() ||
3154 UBPrevSize != KnownUBInsts.size())
3155 return ChangeStatus::CHANGED;
3156 return ChangeStatus::UNCHANGED;
3159 bool isKnownToCauseUB(Instruction *
I)
const override {
3160 return KnownUBInsts.count(
I);
3163 bool isAssumedToCauseUB(Instruction *
I)
const override {
3170 switch (
I->getOpcode()) {
3171 case Instruction::Load:
3172 case Instruction::Store:
3173 case Instruction::AtomicCmpXchg:
3174 case Instruction::AtomicRMW:
3175 return !AssumedNoUBInsts.count(
I);
3176 case Instruction::Br: {
3178 if (BrInst->isUnconditional())
3180 return !AssumedNoUBInsts.count(
I);
3189 if (KnownUBInsts.empty())
3190 return ChangeStatus::UNCHANGED;
3191 for (Instruction *
I : KnownUBInsts)
3192 A.changeToUnreachableAfterManifest(
I);
3193 return ChangeStatus::CHANGED;
3197 const std::string getAsStr(Attributor *
A)
const override {
3198 return getAssumed() ?
"undefined-behavior" :
"no-ub";
3226 SmallPtrSet<Instruction *, 8> KnownUBInsts;
3230 SmallPtrSet<Instruction *, 8> AssumedNoUBInsts;
3241 std::optional<Value *> stopOnUndefOrAssumed(Attributor &
A,
Value *V,
3243 bool UsedAssumedInformation =
false;
3244 std::optional<Value *> SimplifiedV =
3247 if (!UsedAssumedInformation) {
3252 KnownUBInsts.insert(
I);
3253 return std::nullopt;
3260 KnownUBInsts.insert(
I);
3261 return std::nullopt;
3267struct AAUndefinedBehaviorFunction final : AAUndefinedBehaviorImpl {
3268 AAUndefinedBehaviorFunction(
const IRPosition &IRP, Attributor &
A)
3269 : AAUndefinedBehaviorImpl(IRP,
A) {}
3272 void trackStatistics()
const override {
3273 STATS_DECL(UndefinedBehaviorInstruction, Instruction,
3274 "Number of instructions known to have UB");
3276 KnownUBInsts.size();
3287static bool mayContainUnboundedCycle(Function &
F, Attributor &
A) {
3288 ScalarEvolution *SE =
3289 A.getInfoCache().getAnalysisResultForFunction<ScalarEvolutionAnalysis>(
F);
3290 LoopInfo *LI =
A.getInfoCache().getAnalysisResultForFunction<LoopAnalysis>(
F);
3296 for (scc_iterator<Function *> SCCI =
scc_begin(&
F); !SCCI.isAtEnd(); ++SCCI)
3297 if (SCCI.hasCycle())
3307 for (
auto *L : LI->getLoopsInPreorder()) {
3314struct AAWillReturnImpl :
public AAWillReturn {
3315 AAWillReturnImpl(
const IRPosition &IRP, Attributor &
A)
3316 : AAWillReturn(IRP,
A) {}
3322 A,
nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));
3327 bool isImpliedByMustprogressAndReadonly(Attributor &
A,
bool KnownOnly) {
3328 if (!
A.hasAttr(getIRPosition(), {Attribute::MustProgress}))
3333 return IsKnown || !KnownOnly;
3339 if (isImpliedByMustprogressAndReadonly(
A,
false))
3340 return ChangeStatus::UNCHANGED;
3346 A,
this, IPos, DepClassTy::REQUIRED, IsKnown)) {
3352 bool IsKnownNoRecurse;
3354 A,
this, IPos, DepClassTy::REQUIRED, IsKnownNoRecurse);
3357 bool UsedAssumedInformation =
false;
3358 if (!
A.checkForAllCallLikeInstructions(CheckForWillReturn, *
this,
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);
3477 if (!PairDMI::isEqual({LHS->From, LHS->To}, {RHS->From, RHS->To}))
3479 return InstSetDMI::isEqual(LHS->ExclusionSet, RHS->ExclusionSet);
3483#define DefineKeys(ToTy) \
3485 ReachabilityQueryInfo<ToTy> \
3486 DenseMapInfo<ReachabilityQueryInfo<ToTy> *>::EmptyKey = \
3487 ReachabilityQueryInfo<ToTy>( \
3488 DenseMapInfo<const Instruction *>::getEmptyKey(), \
3489 DenseMapInfo<const ToTy *>::getEmptyKey()); \
3491 ReachabilityQueryInfo<ToTy> \
3492 DenseMapInfo<ReachabilityQueryInfo<ToTy> *>::TombstoneKey = \
3493 ReachabilityQueryInfo<ToTy>( \
3494 DenseMapInfo<const Instruction *>::getTombstoneKey(), \
3495 DenseMapInfo<const ToTy *>::getTombstoneKey());
3504template <
typename BaseTy,
typename ToTy>
3505struct CachedReachabilityAA :
public BaseTy {
3506 using RQITy = ReachabilityQueryInfo<ToTy>;
3508 CachedReachabilityAA(
const IRPosition &IRP, Attributor &
A) : BaseTy(IRP,
A) {}
3511 bool isQueryAA()
const override {
return true; }
3516 for (
unsigned u = 0,
e = QueryVector.size();
u <
e; ++
u) {
3517 RQITy *RQI = QueryVector[
u];
3518 if (RQI->Result == RQITy::Reachable::No &&
3520 Changed = ChangeStatus::CHANGED;
3526 bool IsTemporaryRQI) = 0;
3528 bool rememberResult(Attributor &
A,
typename RQITy::Reachable
Result,
3529 RQITy &RQI,
bool UsedExclusionSet,
bool IsTemporaryRQI) {
3534 QueryCache.erase(&RQI);
3540 if (
Result == RQITy::Reachable::Yes || !UsedExclusionSet) {
3541 RQITy PlainRQI(RQI.From, RQI.To);
3542 if (!QueryCache.count(&PlainRQI)) {
3543 RQITy *RQIPtr =
new (
A.Allocator) RQITy(RQI.From, RQI.To);
3545 QueryVector.push_back(RQIPtr);
3546 QueryCache.insert(RQIPtr);
3551 if (IsTemporaryRQI &&
Result != RQITy::Reachable::Yes && UsedExclusionSet) {
3552 assert((!RQI.ExclusionSet || !RQI.ExclusionSet->empty()) &&
3553 "Did not expect empty set!");
3554 RQITy *RQIPtr =
new (
A.Allocator)
3555 RQITy(
A, *RQI.From, *RQI.To, RQI.ExclusionSet,
true);
3556 assert(RQIPtr->Result == RQITy::Reachable::No &&
"Already reachable?");
3558 assert(!QueryCache.count(RQIPtr));
3559 QueryVector.push_back(RQIPtr);
3560 QueryCache.insert(RQIPtr);
3563 if (
Result == RQITy::Reachable::No && IsTemporaryRQI)
3564 A.registerForUpdate(*
this);
3565 return Result == RQITy::Reachable::Yes;
3568 const std::string getAsStr(Attributor *
A)
const override {
3570 return "#queries(" + std::to_string(QueryVector.size()) +
")";
3573 bool checkQueryCache(Attributor &
A, RQITy &StackRQI,
3574 typename RQITy::Reachable &
Result) {
3575 if (!this->getState().isValidState()) {
3576 Result = RQITy::Reachable::Yes;
3582 if (StackRQI.ExclusionSet) {
3583 RQITy PlainRQI(StackRQI.From, StackRQI.To);
3584 auto It = QueryCache.find(&PlainRQI);
3585 if (It != QueryCache.end() && (*It)->Result == RQITy::Reachable::No) {
3586 Result = RQITy::Reachable::No;
3591 auto It = QueryCache.find(&StackRQI);
3592 if (It != QueryCache.end()) {
3599 QueryCache.insert(&StackRQI);
3605 DenseSet<RQITy *> QueryCache;
3608struct AAIntraFnReachabilityFunction final
3609 :
public CachedReachabilityAA<AAIntraFnReachability, Instruction> {
3610 using Base = CachedReachabilityAA<AAIntraFnReachability, Instruction>;
3611 AAIntraFnReachabilityFunction(
const IRPosition &IRP, Attributor &
A)
3613 DT =
A.getInfoCache().getAnalysisResultForFunction<DominatorTreeAnalysis>(
3617 bool isAssumedReachable(
3618 Attributor &
A,
const Instruction &From,
const Instruction &To,
3620 auto *NonConstThis =
const_cast<AAIntraFnReachabilityFunction *
>(
this);
3624 RQITy StackRQI(
A, From, To, ExclusionSet,
false);
3626 if (!NonConstThis->checkQueryCache(
A, StackRQI, Result))
3627 return NonConstThis->isReachableImpl(
A, StackRQI,
3629 return Result == RQITy::Reachable::Yes;
3636 A.getAAFor<AAIsDead>(*
this, getIRPosition(), DepClassTy::OPTIONAL);
3639 [&](
const auto &DeadEdge) {
3640 return LivenessAA->isEdgeDead(DeadEdge.first,
3644 return LivenessAA->isAssumedDead(BB);
3646 return ChangeStatus::UNCHANGED;
3650 return Base::updateImpl(
A);
3654 bool IsTemporaryRQI)
override {
3656 bool UsedExclusionSet =
false;
3661 while (IP && IP != &To) {
3662 if (ExclusionSet && IP != Origin && ExclusionSet->
count(IP)) {
3663 UsedExclusionSet =
true;
3671 const BasicBlock *FromBB = RQI.From->getParent();
3672 const BasicBlock *ToBB = RQI.To->getParent();
3674 "Not an intra-procedural query!");
3678 if (FromBB == ToBB &&
3679 WillReachInBlock(*RQI.From, *RQI.To, RQI.ExclusionSet))
3680 return rememberResult(
A, RQITy::Reachable::Yes, RQI, UsedExclusionSet,
3685 if (!WillReachInBlock(ToBB->
front(), *RQI.To, RQI.ExclusionSet))
3686 return rememberResult(
A, RQITy::Reachable::No, RQI, UsedExclusionSet,
3690 SmallPtrSet<const BasicBlock *, 16> ExclusionBlocks;
3691 if (RQI.ExclusionSet)
3692 for (
auto *
I : *RQI.ExclusionSet)
3693 if (
I->getFunction() == Fn)
3694 ExclusionBlocks.
insert(
I->getParent());
3697 if (ExclusionBlocks.
count(FromBB) &&
3700 return rememberResult(
A, RQITy::Reachable::No, RQI,
true, IsTemporaryRQI);
3703 A.getAAFor<AAIsDead>(*
this, getIRPosition(), DepClassTy::OPTIONAL);
3704 if (LivenessAA && LivenessAA->isAssumedDead(ToBB)) {
3705 DeadBlocks.insert(ToBB);
3706 return rememberResult(
A, RQITy::Reachable::No, RQI, UsedExclusionSet,
3710 SmallPtrSet<const BasicBlock *, 16> Visited;
3714 DenseSet<std::pair<const BasicBlock *, const BasicBlock *>> LocalDeadEdges;
3715 while (!Worklist.
empty()) {
3717 if (!Visited.
insert(BB).second)
3719 for (
const BasicBlock *SuccBB :
successors(BB)) {
3720 if (LivenessAA && LivenessAA->isEdgeDead(BB, SuccBB)) {
3721 LocalDeadEdges.
insert({BB, SuccBB});
3726 return rememberResult(
A, RQITy::Reachable::Yes, RQI, UsedExclusionSet,
3729 return rememberResult(
A, RQITy::Reachable::Yes, RQI, UsedExclusionSet,
3732 if (ExclusionBlocks.
count(SuccBB)) {
3733 UsedExclusionSet =
true;
3740 DeadEdges.insert_range(LocalDeadEdges);
3741 return rememberResult(
A, RQITy::Reachable::No, RQI, UsedExclusionSet,
3746 void trackStatistics()
const override {}
3751 DenseSet<const BasicBlock *> DeadBlocks;
3755 DenseSet<std::pair<const BasicBlock *, const BasicBlock *>> DeadEdges;
3758 const DominatorTree *DT =
nullptr;
3766 bool IgnoreSubsumingPositions) {
3767 assert(ImpliedAttributeKind == Attribute::NoAlias &&
3768 "Unexpected attribute kind");
3774 IgnoreSubsumingPositions =
true;
3785 if (
A.hasAttr(IRP, {Attribute::ByVal, Attribute::NoAlias},
3786 IgnoreSubsumingPositions, Attribute::NoAlias))
3796 "Noalias is a pointer attribute");
3799 const std::string getAsStr(
Attributor *
A)
const override {
3800 return getAssumed() ?
"noalias" :
"may-alias";
3805struct AANoAliasFloating final : AANoAliasImpl {
3806 AANoAliasFloating(
const IRPosition &IRP, Attributor &
A)
3807 : AANoAliasImpl(IRP,
A) {}
3812 return indicatePessimisticFixpoint();
3816 void trackStatistics()
const override {
3822struct AANoAliasArgument final
3823 : AAArgumentFromCallSiteArguments<AANoAlias, AANoAliasImpl> {
3824 using Base = AAArgumentFromCallSiteArguments<AANoAlias, AANoAliasImpl>;
3825 AANoAliasArgument(
const IRPosition &IRP, Attributor &
A) :
Base(IRP,
A) {}
3838 DepClassTy::OPTIONAL, IsKnownNoSycn))
3839 return Base::updateImpl(
A);
3844 return Base::updateImpl(
A);
3848 bool UsedAssumedInformation =
false;
3849 if (
A.checkForAllCallSites(
3850 [](AbstractCallSite ACS) { return !ACS.isCallbackCall(); }, *
this,
3851 true, UsedAssumedInformation))
3852 return Base::updateImpl(
A);
3860 return indicatePessimisticFixpoint();
3867struct AANoAliasCallSiteArgument final : AANoAliasImpl {
3868 AANoAliasCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
3869 : AANoAliasImpl(IRP,
A) {}
3873 bool mayAliasWithArgument(Attributor &
A, AAResults *&AAR,
3874 const AAMemoryBehavior &MemBehaviorAA,
3875 const CallBase &CB,
unsigned OtherArgNo) {
3877 if (this->getCalleeArgNo() == (
int)OtherArgNo)
3885 auto *CBArgMemBehaviorAA =
A.getAAFor<AAMemoryBehavior>(
3889 if (CBArgMemBehaviorAA && CBArgMemBehaviorAA->isAssumedReadNone()) {
3890 A.recordDependence(*CBArgMemBehaviorAA, *
this, DepClassTy::OPTIONAL);
3897 if (CBArgMemBehaviorAA && CBArgMemBehaviorAA->isAssumedReadOnly() &&
3899 A.recordDependence(MemBehaviorAA, *
this, DepClassTy::OPTIONAL);
3900 A.recordDependence(*CBArgMemBehaviorAA, *
this, DepClassTy::OPTIONAL);
3906 AAR =
A.getInfoCache().getAnalysisResultForFunction<AAManager>(
3910 bool IsAliasing = !AAR || !AAR->
isNoAlias(&getAssociatedValue(), ArgOp);
3912 "callsite arguments: "
3913 << getAssociatedValue() <<
" " << *ArgOp <<
" => "
3914 << (IsAliasing ?
"" :
"no-") <<
"alias \n");
3919 bool isKnownNoAliasDueToNoAliasPreservation(
3920 Attributor &
A, AAResults *&AAR,
const AAMemoryBehavior &MemBehaviorAA) {
3933 auto UsePred = [&](
const Use &
U,
bool &Follow) ->
bool {
3949 bool IsKnownNoCapture;
3952 DepClassTy::OPTIONAL, IsKnownNoCapture))
3958 A, *UserI, *getCtxI(), *
this,
nullptr,
3959 [ScopeFn](
const Function &Fn) {
return &Fn != ScopeFn; }))
3974 LLVM_DEBUG(
dbgs() <<
"[AANoAliasCSArg] Unknown user: " << *UserI <<
"\n");
3978 bool IsKnownNoCapture;
3979 const AANoCapture *NoCaptureAA =
nullptr;
3981 A,
this, VIRP, DepClassTy::NONE, IsKnownNoCapture,
false, &NoCaptureAA);
3982 if (!IsAssumedNoCapture &&
3984 if (!
A.checkForAllUses(UsePred, *
this, getAssociatedValue())) {
3986 dbgs() <<
"[AANoAliasCSArg] " << getAssociatedValue()
3987 <<
" cannot be noalias as it is potentially captured\n");
3992 A.recordDependence(*NoCaptureAA, *
this, DepClassTy::OPTIONAL);
3998 for (
unsigned OtherArgNo = 0; OtherArgNo < CB.
arg_size(); OtherArgNo++)
3999 if (mayAliasWithArgument(
A, AAR, MemBehaviorAA, CB, OtherArgNo))
4009 auto *MemBehaviorAA =
4010 A.getAAFor<AAMemoryBehavior>(*
this, getIRPosition(), DepClassTy::NONE);
4012 A.recordDependence(*MemBehaviorAA, *
this, DepClassTy::OPTIONAL);
4013 return ChangeStatus::UNCHANGED;
4016 bool IsKnownNoAlias;
4019 A,
this, VIRP, DepClassTy::REQUIRED, IsKnownNoAlias)) {
4021 <<
" is not no-alias at the definition\n");
4022 return indicatePessimisticFixpoint();
4025 AAResults *AAR =
nullptr;
4026 if (MemBehaviorAA &&
4027 isKnownNoAliasDueToNoAliasPreservation(
A, AAR, *MemBehaviorAA)) {
4029 dbgs() <<
"[AANoAlias] No-Alias deduced via no-alias preservation\n");
4030 return ChangeStatus::UNCHANGED;
4033 return indicatePessimisticFixpoint();
4041struct AANoAliasReturned final : AANoAliasImpl {
4042 AANoAliasReturned(
const IRPosition &IRP, Attributor &
A)
4043 : AANoAliasImpl(IRP,
A) {}
4048 auto CheckReturnValue = [&](
Value &RV) ->
bool {
4059 bool IsKnownNoAlias;
4061 A,
this, RVPos, DepClassTy::REQUIRED, IsKnownNoAlias))
4064 bool IsKnownNoCapture;
4065 const AANoCapture *NoCaptureAA =
nullptr;
4067 A,
this, RVPos, DepClassTy::REQUIRED, IsKnownNoCapture,
false,
4069 return IsAssumedNoCapture ||
4073 if (!
A.checkForAllReturnedValues(CheckReturnValue, *
this))
4074 return indicatePessimisticFixpoint();
4076 return ChangeStatus::UNCHANGED;
4084struct AANoAliasCallSiteReturned final
4085 : AACalleeToCallSite<AANoAlias, AANoAliasImpl> {
4086 AANoAliasCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
4087 : AACalleeToCallSite<AANoAlias, AANoAliasImpl>(IRP,
A) {}
4097struct AAIsDeadValueImpl :
public AAIsDead {
4098 AAIsDeadValueImpl(
const IRPosition &IRP, Attributor &
A) : AAIsDead(IRP,
A) {}
4101 bool isAssumedDead()
const override {
return isAssumed(IS_DEAD); }
4104 bool isKnownDead()
const override {
return isKnown(IS_DEAD); }
4107 bool isAssumedDead(
const BasicBlock *BB)
const override {
return false; }
4110 bool isKnownDead(
const BasicBlock *BB)
const override {
return false; }
4113 bool isAssumedDead(
const Instruction *
I)
const override {
4114 return I == getCtxI() && isAssumedDead();
4118 bool isKnownDead(
const Instruction *
I)
const override {
4119 return isAssumedDead(
I) && isKnownDead();
4123 const std::string getAsStr(Attributor *
A)
const override {
4124 return isAssumedDead() ?
"assumed-dead" :
"assumed-live";
4128 bool areAllUsesAssumedDead(Attributor &
A,
Value &V) {
4130 if (
V.getType()->isVoidTy() ||
V.use_empty())
4136 if (!
A.isRunOn(*
I->getFunction()))
4138 bool UsedAssumedInformation =
false;
4139 std::optional<Constant *>
C =
4140 A.getAssumedConstant(V, *
this, UsedAssumedInformation);
4145 auto UsePred = [&](
const Use &
U,
bool &Follow) {
return false; };
4150 return A.checkForAllUses(UsePred, *
this, V,
false,
4151 DepClassTy::REQUIRED,
4156 bool isAssumedSideEffectFree(Attributor &
A, Instruction *
I) {
4166 bool IsKnownNoUnwind;
4168 A,
this, CallIRP, DepClassTy::OPTIONAL, IsKnownNoUnwind))
4176struct AAIsDeadFloating :
public AAIsDeadValueImpl {
4177 AAIsDeadFloating(
const IRPosition &IRP, Attributor &
A)
4178 : AAIsDeadValueImpl(IRP,
A) {}
4182 AAIsDeadValueImpl::initialize(
A);
4185 indicatePessimisticFixpoint();
4190 if (!isAssumedSideEffectFree(
A,
I)) {
4192 indicatePessimisticFixpoint();
4194 removeAssumedBits(HAS_NO_EFFECT);
4198 bool isDeadFence(Attributor &
A, FenceInst &FI) {
4199 const auto *ExecDomainAA =
A.lookupAAFor<AAExecutionDomain>(
4201 if (!ExecDomainAA || !ExecDomainAA->isNoOpFence(FI))
4203 A.recordDependence(*ExecDomainAA, *
this, DepClassTy::OPTIONAL);
4207 bool isDeadStore(Attributor &
A, StoreInst &SI,
4208 SmallSetVector<Instruction *, 8> *AssumeOnlyInst =
nullptr) {
4210 if (
SI.isVolatile())
4216 bool UsedAssumedInformation =
false;
4217 if (!AssumeOnlyInst) {
4218 PotentialCopies.clear();
4220 UsedAssumedInformation)) {
4223 <<
"[AAIsDead] Could not determine potential copies of store!\n");
4227 LLVM_DEBUG(
dbgs() <<
"[AAIsDead] Store has " << PotentialCopies.size()
4228 <<
" potential copies.\n");
4230 InformationCache &InfoCache =
A.getInfoCache();
4233 UsedAssumedInformation))
4237 auto &UserI = cast<Instruction>(*U.getUser());
4238 if (InfoCache.isOnlyUsedByAssume(UserI)) {
4240 AssumeOnlyInst->insert(&UserI);
4243 return A.isAssumedDead(U,
this,
nullptr, UsedAssumedInformation);
4249 <<
" is assumed live!\n");
4255 const std::string getAsStr(Attributor *
A)
const override {
4259 return "assumed-dead-store";
4262 return "assumed-dead-fence";
4263 return AAIsDeadValueImpl::getAsStr(
A);
4270 if (!isDeadStore(
A, *SI))
4271 return indicatePessimisticFixpoint();
4273 if (!isDeadFence(
A, *FI))
4274 return indicatePessimisticFixpoint();
4276 if (!isAssumedSideEffectFree(
A,
I))
4277 return indicatePessimisticFixpoint();
4278 if (!areAllUsesAssumedDead(
A, getAssociatedValue()))
4279 return indicatePessimisticFixpoint();
4284 bool isRemovableStore()
const override {
4285 return isAssumed(IS_REMOVABLE) &&
isa<StoreInst>(&getAssociatedValue());
4290 Value &
V = getAssociatedValue();
4297 SmallSetVector<Instruction *, 8> AssumeOnlyInst;
4298 bool IsDead = isDeadStore(
A, *SI, &AssumeOnlyInst);
4301 A.deleteAfterManifest(*
I);
4302 for (
size_t i = 0; i < AssumeOnlyInst.
size(); ++i) {
4304 for (
auto *Usr : AOI->
users())
4306 A.deleteAfterManifest(*AOI);
4312 A.deleteAfterManifest(*FI);
4316 A.deleteAfterManifest(*
I);
4324 void trackStatistics()
const override {
4330 SmallSetVector<Value *, 4> PotentialCopies;
4333struct AAIsDeadArgument :
public AAIsDeadFloating {
4334 AAIsDeadArgument(
const IRPosition &IRP, Attributor &
A)
4335 : AAIsDeadFloating(IRP,
A) {}
4339 Argument &Arg = *getAssociatedArgument();
4340 if (
A.isValidFunctionSignatureRewrite(Arg, {}))
4341 if (
A.registerFunctionSignatureRewrite(
4345 return ChangeStatus::CHANGED;
4347 return ChangeStatus::UNCHANGED;
4354struct AAIsDeadCallSiteArgument :
public AAIsDeadValueImpl {
4355 AAIsDeadCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
4356 : AAIsDeadValueImpl(IRP,
A) {}
4360 AAIsDeadValueImpl::initialize(
A);
4362 indicatePessimisticFixpoint();
4371 Argument *Arg = getAssociatedArgument();
4373 return indicatePessimisticFixpoint();
4375 auto *ArgAA =
A.getAAFor<AAIsDead>(*
this, ArgPos, DepClassTy::REQUIRED);
4377 return indicatePessimisticFixpoint();
4386 "Expected undef values to be filtered out!");
4388 if (
A.changeUseAfterManifest(U, UV))
4389 return ChangeStatus::CHANGED;
4390 return ChangeStatus::UNCHANGED;
4397struct AAIsDeadCallSiteReturned :
public AAIsDeadFloating {
4398 AAIsDeadCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
4399 : AAIsDeadFloating(IRP,
A) {}
4402 bool isAssumedDead()
const override {
4403 return AAIsDeadFloating::isAssumedDead() && IsAssumedSideEffectFree;
4408 AAIsDeadFloating::initialize(
A);
4410 indicatePessimisticFixpoint();
4415 IsAssumedSideEffectFree = isAssumedSideEffectFree(
A, getCtxI());
4421 if (IsAssumedSideEffectFree && !isAssumedSideEffectFree(
A, getCtxI())) {
4422 IsAssumedSideEffectFree =
false;
4423 Changed = ChangeStatus::CHANGED;
4425 if (!areAllUsesAssumedDead(
A, getAssociatedValue()))
4426 return indicatePessimisticFixpoint();
4431 void trackStatistics()
const override {
4432 if (IsAssumedSideEffectFree)
4439 const std::string getAsStr(Attributor *
A)
const override {
4440 return isAssumedDead()
4442 : (getAssumed() ?
"assumed-dead-users" :
"assumed-live");
4446 bool IsAssumedSideEffectFree =
true;
4449struct AAIsDeadReturned :
public AAIsDeadValueImpl {
4450 AAIsDeadReturned(
const IRPosition &IRP, Attributor &
A)
4451 : AAIsDeadValueImpl(IRP,
A) {}
4456 bool UsedAssumedInformation =
false;
4457 A.checkForAllInstructions([](Instruction &) {
return true; }, *
this,
4458 {Instruction::Ret}, UsedAssumedInformation);
4460 auto PredForCallSite = [&](AbstractCallSite ACS) {
4461 if (ACS.isCallbackCall() || !ACS.getInstruction())
4463 return areAllUsesAssumedDead(
A, *ACS.getInstruction());
4466 if (!
A.checkForAllCallSites(PredForCallSite, *
this,
true,
4467 UsedAssumedInformation))
4468 return indicatePessimisticFixpoint();
4470 return ChangeStatus::UNCHANGED;
4476 bool AnyChange =
false;
4477 UndefValue &UV = *
UndefValue::get(getAssociatedFunction()->getReturnType());
4484 bool UsedAssumedInformation =
false;
4485 A.checkForAllInstructions(RetInstPred, *
this, {Instruction::Ret},
4486 UsedAssumedInformation);
4487 return AnyChange ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
4494struct AAIsDeadFunction :
public AAIsDead {
4495 AAIsDeadFunction(
const IRPosition &IRP, Attributor &
A) : AAIsDead(IRP,
A) {}
4500 assert(
F &&
"Did expect an anchor function");
4501 if (!isAssumedDeadInternalFunction(
A)) {
4502 ToBeExploredFrom.insert(&
F->getEntryBlock().front());
4503 assumeLive(
A,
F->getEntryBlock());
4507 bool isAssumedDeadInternalFunction(Attributor &
A) {
4508 if (!getAnchorScope()->hasLocalLinkage())
4510 bool UsedAssumedInformation =
false;
4511 return A.checkForAllCallSites([](AbstractCallSite) {
return false; }, *
this,
4512 true, UsedAssumedInformation);
4516 const std::string getAsStr(Attributor *
A)
const override {
4517 return "Live[#BB " + std::to_string(AssumedLiveBlocks.size()) +
"/" +
4518 std::to_string(getAnchorScope()->
size()) +
"][#TBEP " +
4519 std::to_string(ToBeExploredFrom.size()) +
"][#KDE " +
4520 std::to_string(KnownDeadEnds.size()) +
"]";
4525 assert(getState().isValidState() &&
4526 "Attempted to manifest an invalid state!");
4531 if (AssumedLiveBlocks.empty()) {
4532 A.deleteAfterManifest(
F);
4533 return ChangeStatus::CHANGED;
4539 bool Invoke2CallAllowed = !mayCatchAsynchronousExceptions(
F);
4541 KnownDeadEnds.set_union(ToBeExploredFrom);
4542 for (
const Instruction *DeadEndI : KnownDeadEnds) {
4546 bool IsKnownNoReturn;
4554 A.registerInvokeWithDeadSuccessor(
const_cast<InvokeInst &
>(*
II));
4556 A.changeToUnreachableAfterManifest(
4557 const_cast<Instruction *
>(DeadEndI->getNextNode()));
4558 HasChanged = ChangeStatus::CHANGED;
4561 STATS_DECL(AAIsDead, BasicBlock,
"Number of dead basic blocks deleted.");
4562 for (BasicBlock &BB :
F)
4563 if (!AssumedLiveBlocks.count(&BB)) {
4564 A.deleteAfterManifest(BB);
4566 HasChanged = ChangeStatus::CHANGED;
4575 bool isEdgeDead(
const BasicBlock *From,
const BasicBlock *To)
const override {
4578 "Used AAIsDead of the wrong function");
4579 return isValidState() && !AssumedLiveEdges.count(std::make_pair(From, To));
4583 void trackStatistics()
const override {}
4586 bool isAssumedDead()
const override {
return false; }
4589 bool isKnownDead()
const override {
return false; }
4592 bool isAssumedDead(
const BasicBlock *BB)
const override {
4594 "BB must be in the same anchor scope function.");
4598 return !AssumedLiveBlocks.count(BB);
4602 bool isKnownDead(
const BasicBlock *BB)
const override {
4603 return getKnown() && isAssumedDead(BB);
4607 bool isAssumedDead(
const Instruction *
I)
const override {
4608 assert(
I->getParent()->getParent() == getAnchorScope() &&
4609 "Instruction must be in the same anchor scope function.");
4616 if (!AssumedLiveBlocks.count(
I->getParent()))
4622 if (KnownDeadEnds.count(PrevI) || ToBeExploredFrom.count(PrevI))
4630 bool isKnownDead(
const Instruction *
I)
const override {
4631 return getKnown() && isAssumedDead(
I);
4636 bool assumeLive(Attributor &
A,
const BasicBlock &BB) {
4637 if (!AssumedLiveBlocks.insert(&BB).second)
4644 for (
const Instruction &
I : BB)
4647 if (
F->hasLocalLinkage())
4648 A.markLiveInternalFunction(*
F);
4654 SmallSetVector<const Instruction *, 8> ToBeExploredFrom;
4657 SmallSetVector<const Instruction *, 8> KnownDeadEnds;
4660 DenseSet<std::pair<const BasicBlock *, const BasicBlock *>> AssumedLiveEdges;
4663 DenseSet<const BasicBlock *> AssumedLiveBlocks;
4667identifyAliveSuccessors(Attributor &
A,
const CallBase &CB,
4668 AbstractAttribute &AA,
4669 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4672 bool IsKnownNoReturn;
4675 return !IsKnownNoReturn;
4684identifyAliveSuccessors(Attributor &
A,
const InvokeInst &
II,
4685 AbstractAttribute &AA,
4686 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4687 bool UsedAssumedInformation =
4693 if (AAIsDeadFunction::mayCatchAsynchronousExceptions(*
II.getFunction())) {
4694 AliveSuccessors.
push_back(&
II.getUnwindDest()->front());
4698 bool IsKnownNoUnwind;
4701 UsedAssumedInformation |= !IsKnownNoUnwind;
4703 AliveSuccessors.
push_back(&
II.getUnwindDest()->front());
4706 return UsedAssumedInformation;
4710identifyAliveSuccessors(Attributor &
A,
const BranchInst &BI,
4711 AbstractAttribute &AA,
4712 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4713 bool UsedAssumedInformation =
false;
4717 std::optional<Constant *>
C =
4718 A.getAssumedConstant(*BI.
getCondition(), AA, UsedAssumedInformation);
4728 UsedAssumedInformation =
false;
4731 return UsedAssumedInformation;
4735identifyAliveSuccessors(Attributor &
A,
const SwitchInst &SI,
4736 AbstractAttribute &AA,
4737 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4738 bool UsedAssumedInformation =
false;
4742 UsedAssumedInformation)) {
4744 for (
const BasicBlock *SuccBB :
successors(
SI.getParent()))
4749 if (Values.
empty() ||
4750 (Values.
size() == 1 &&
4753 return UsedAssumedInformation;
4756 Type &Ty = *
SI.getCondition()->getType();
4757 SmallPtrSet<ConstantInt *, 8>
Constants;
4758 auto CheckForConstantInt = [&](
Value *
V) {
4766 if (!
all_of(Values, [&](AA::ValueAndContext &VAC) {
4767 return CheckForConstantInt(VAC.
getValue());
4769 for (
const BasicBlock *SuccBB :
successors(
SI.getParent()))
4771 return UsedAssumedInformation;
4774 unsigned MatchedCases = 0;
4775 for (
const auto &CaseIt :
SI.cases()) {
4776 if (
Constants.count(CaseIt.getCaseValue())) {
4778 AliveSuccessors.
push_back(&CaseIt.getCaseSuccessor()->front());
4785 AliveSuccessors.
push_back(&
SI.getDefaultDest()->front());
4786 return UsedAssumedInformation;
4792 if (AssumedLiveBlocks.empty()) {
4793 if (isAssumedDeadInternalFunction(
A))
4797 ToBeExploredFrom.insert(&
F->getEntryBlock().front());
4798 assumeLive(
A,
F->getEntryBlock());
4802 LLVM_DEBUG(
dbgs() <<
"[AAIsDead] Live [" << AssumedLiveBlocks.size() <<
"/"
4803 << getAnchorScope()->
size() <<
"] BBs and "
4804 << ToBeExploredFrom.size() <<
" exploration points and "
4805 << KnownDeadEnds.size() <<
" known dead ends\n");
4810 ToBeExploredFrom.end());
4811 decltype(ToBeExploredFrom) NewToBeExploredFrom;
4814 while (!Worklist.
empty()) {
4821 I =
I->getNextNode();
4823 AliveSuccessors.
clear();
4825 bool UsedAssumedInformation =
false;
4826 switch (
I->getOpcode()) {
4830 "Expected non-terminators to be handled already!");
4831 for (
const BasicBlock *SuccBB :
successors(
I->getParent()))
4834 case Instruction::Call:
4836 *
this, AliveSuccessors);
4838 case Instruction::Invoke:
4840 *
this, AliveSuccessors);
4842 case Instruction::Br:
4844 *
this, AliveSuccessors);
4846 case Instruction::Switch:
4848 *
this, AliveSuccessors);
4852 if (UsedAssumedInformation) {
4853 NewToBeExploredFrom.insert(
I);
4854 }
else if (AliveSuccessors.
empty() ||
4855 (
I->isTerminator() &&
4856 AliveSuccessors.
size() <
I->getNumSuccessors())) {
4857 if (KnownDeadEnds.insert(
I))
4862 << AliveSuccessors.
size() <<
" UsedAssumedInformation: "
4863 << UsedAssumedInformation <<
"\n");
4865 for (
const Instruction *AliveSuccessor : AliveSuccessors) {
4866 if (!
I->isTerminator()) {
4867 assert(AliveSuccessors.size() == 1 &&
4868 "Non-terminator expected to have a single successor!");
4872 auto Edge = std::make_pair(
I->getParent(), AliveSuccessor->getParent());
4873 if (AssumedLiveEdges.insert(
Edge).second)
4875 if (assumeLive(
A, *AliveSuccessor->getParent()))
4882 if (NewToBeExploredFrom.size() != ToBeExploredFrom.size() ||
4883 llvm::any_of(NewToBeExploredFrom, [&](
const Instruction *
I) {
4884 return !ToBeExploredFrom.count(I);
4887 ToBeExploredFrom = std::move(NewToBeExploredFrom);
4896 if (ToBeExploredFrom.empty() &&
4897 getAnchorScope()->
size() == AssumedLiveBlocks.size() &&
4898 llvm::all_of(KnownDeadEnds, [](
const Instruction *DeadEndI) {
4899 return DeadEndI->isTerminator() && DeadEndI->getNumSuccessors() == 0;
4901 return indicatePessimisticFixpoint();
4906struct AAIsDeadCallSite final : AAIsDeadFunction {
4907 AAIsDeadCallSite(
const IRPosition &IRP, Attributor &
A)
4908 : AAIsDeadFunction(IRP,
A) {}
4917 "supported for call sites yet!");
4922 return indicatePessimisticFixpoint();
4926 void trackStatistics()
const override {}
4933struct AADereferenceableImpl : AADereferenceable {
4934 AADereferenceableImpl(
const IRPosition &IRP, Attributor &
A)
4935 : AADereferenceable(IRP,
A) {}
4936 using StateType = DerefState;
4940 Value &
V = *getAssociatedValue().stripPointerCasts();
4942 A.getAttrs(getIRPosition(),
4943 {Attribute::Dereferenceable, Attribute::DereferenceableOrNull},
4946 takeKnownDerefBytesMaximum(Attr.getValueAsInt());
4949 bool IsKnownNonNull;
4951 A,
this, getIRPosition(), DepClassTy::OPTIONAL, IsKnownNonNull);
4953 bool CanBeNull, CanBeFreed;
4954 takeKnownDerefBytesMaximum(
V.getPointerDereferenceableBytes(
4955 A.getDataLayout(), CanBeNull, CanBeFreed));
4957 if (Instruction *CtxI = getCtxI())
4958 followUsesInMBEC(*
this,
A, getState(), *CtxI);
4963 StateType &getState()
override {
return *
this; }
4964 const StateType &getState()
const override {
return *
this; }
4968 void addAccessedBytesForUse(Attributor &
A,
const Use *U,
const Instruction *
I,
4969 DerefState &State) {
4970 const Value *UseV =
U->get();
4975 if (!Loc || Loc->Ptr != UseV || !Loc->Size.isPrecise() ||
I->isVolatile())
4980 Loc->Ptr,
Offset,
A.getDataLayout(),
true);
4981 if (
Base &&
Base == &getAssociatedValue())
4982 State.addAccessedBytes(
Offset, Loc->Size.getValue());
4986 bool followUseInMBEC(Attributor &
A,
const Use *U,
const Instruction *
I,
4987 AADereferenceable::StateType &State) {
4988 bool IsNonNull =
false;
4989 bool TrackUse =
false;
4990 int64_t DerefBytes = getKnownNonNullAndDerefBytesForUse(
4991 A, *
this, getAssociatedValue(), U,
I, IsNonNull, TrackUse);
4992 LLVM_DEBUG(
dbgs() <<
"[AADereferenceable] Deref bytes: " << DerefBytes
4993 <<
" for instruction " << *
I <<
"\n");
4995 addAccessedBytesForUse(
A, U,
I, State);
4996 State.takeKnownDerefBytesMaximum(DerefBytes);
5003 bool IsKnownNonNull;
5005 A,
this, getIRPosition(), DepClassTy::NONE, IsKnownNonNull);
5006 if (IsAssumedNonNull &&
5007 A.hasAttr(getIRPosition(), Attribute::DereferenceableOrNull)) {
5008 A.removeAttrs(getIRPosition(), {Attribute::DereferenceableOrNull});
5009 return ChangeStatus::CHANGED;
5014 void getDeducedAttributes(Attributor &
A, LLVMContext &Ctx,
5015 SmallVectorImpl<Attribute> &Attrs)
const override {
5017 bool IsKnownNonNull;
5019 A,
this, getIRPosition(), DepClassTy::NONE, IsKnownNonNull);
5020 if (IsAssumedNonNull)
5021 Attrs.emplace_back(Attribute::getWithDereferenceableBytes(
5022 Ctx, getAssumedDereferenceableBytes()));
5024 Attrs.emplace_back(Attribute::getWithDereferenceableOrNullBytes(
5025 Ctx, getAssumedDereferenceableBytes()));
5029 const std::string getAsStr(Attributor *
A)
const override {
5030 if (!getAssumedDereferenceableBytes())
5031 return "unknown-dereferenceable";
5032 bool IsKnownNonNull;
5033 bool IsAssumedNonNull =
false;
5036 *
A,
this, getIRPosition(), DepClassTy::NONE, IsKnownNonNull);
5037 return std::string(
"dereferenceable") +
5038 (IsAssumedNonNull ?
"" :
"_or_null") +
5039 (isAssumedGlobal() ?
"_globally" :
"") +
"<" +
5040 std::to_string(getKnownDereferenceableBytes()) +
"-" +
5041 std::to_string(getAssumedDereferenceableBytes()) +
">" +
5042 (!
A ?
" [non-null is unknown]" :
"");
5047struct AADereferenceableFloating : AADereferenceableImpl {
5048 AADereferenceableFloating(
const IRPosition &IRP, Attributor &
A)
5049 : AADereferenceableImpl(IRP,
A) {}
5054 bool UsedAssumedInformation =
false;
5056 if (!
A.getAssumedSimplifiedValues(getIRPosition(), *
this, Values,
5058 Values.
push_back({getAssociatedValue(), getCtxI()});
5061 Stripped = Values.
size() != 1 ||
5062 Values.
front().getValue() != &getAssociatedValue();
5065 const DataLayout &
DL =
A.getDataLayout();
5068 auto VisitValueCB = [&](
const Value &
V) ->
bool {
5070 DL.getIndexSizeInBits(
V.getType()->getPointerAddressSpace());
5071 APInt
Offset(IdxWidth, 0);
5076 const auto *AA =
A.getAAFor<AADereferenceable>(
5078 int64_t DerefBytes = 0;
5079 if (!AA || (!Stripped &&
this == AA)) {
5082 bool CanBeNull, CanBeFreed;
5084 Base->getPointerDereferenceableBytes(
DL, CanBeNull, CanBeFreed);
5085 T.GlobalState.indicatePessimisticFixpoint();
5088 DerefBytes =
DS.DerefBytesState.getAssumed();
5089 T.GlobalState &=
DS.GlobalState;
5095 int64_t OffsetSExt =
Offset.getSExtValue();
5099 T.takeAssumedDerefBytesMinimum(
5100 std::max(int64_t(0), DerefBytes - OffsetSExt));
5105 T.takeKnownDerefBytesMaximum(
5106 std::max(int64_t(0), DerefBytes - OffsetSExt));
5107 T.indicatePessimisticFixpoint();
5108 }
else if (OffsetSExt > 0) {
5114 T.indicatePessimisticFixpoint();
5118 return T.isValidState();
5121 for (
const auto &VAC : Values)
5122 if (!VisitValueCB(*VAC.
getValue()))
5123 return indicatePessimisticFixpoint();
5129 void trackStatistics()
const override {
5135struct AADereferenceableReturned final
5136 : AAReturnedFromReturnedValues<AADereferenceable, AADereferenceableImpl> {
5138 AAReturnedFromReturnedValues<AADereferenceable, AADereferenceableImpl>;
5139 AADereferenceableReturned(
const IRPosition &IRP, Attributor &
A)
5143 void trackStatistics()
const override {
5149struct AADereferenceableArgument final
5150 : AAArgumentFromCallSiteArguments<AADereferenceable,
5151 AADereferenceableImpl> {
5153 AAArgumentFromCallSiteArguments<AADereferenceable, AADereferenceableImpl>;
5154 AADereferenceableArgument(
const IRPosition &IRP, Attributor &
A)
5158 void trackStatistics()
const override {
5164struct AADereferenceableCallSiteArgument final : AADereferenceableFloating {
5165 AADereferenceableCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
5166 : AADereferenceableFloating(IRP,
A) {}
5169 void trackStatistics()
const override {
5175struct AADereferenceableCallSiteReturned final
5176 : AACalleeToCallSite<AADereferenceable, AADereferenceableImpl> {
5177 using Base = AACalleeToCallSite<AADereferenceable, AADereferenceableImpl>;
5178 AADereferenceableCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
5182 void trackStatistics()
const override {
5192static unsigned getKnownAlignForUse(Attributor &
A, AAAlign &QueryingAA,
5193 Value &AssociatedValue,
const Use *U,
5194 const Instruction *
I,
bool &TrackUse) {
5203 if (
GEP->hasAllConstantIndices())
5208 switch (
II->getIntrinsicID()) {
5209 case Intrinsic::ptrmask: {
5211 const auto *ConstVals =
A.getAAFor<AAPotentialConstantValues>(
5213 const auto *AlignAA =
A.getAAFor<AAAlign>(
5215 if (ConstVals && ConstVals->isValidState() && ConstVals->isAtFixpoint()) {
5216 unsigned ShiftValue = std::min(ConstVals->getAssumedMinTrailingZeros(),
5218 Align ConstAlign(UINT64_C(1) << ShiftValue);
5219 if (ConstAlign >= AlignAA->getKnownAlign())
5220 return Align(1).value();
5223 return AlignAA->getKnownAlign().
value();
5226 case Intrinsic::amdgcn_make_buffer_rsrc: {
5227 const auto *AlignAA =
A.getAAFor<AAAlign>(
5230 return AlignAA->getKnownAlign().
value();
5248 MA = MaybeAlign(AlignAA->getKnownAlign());
5251 const DataLayout &
DL =
A.getDataLayout();
5252 const Value *UseV =
U->get();
5254 if (
SI->getPointerOperand() == UseV)
5255 MA =
SI->getAlign();
5257 if (LI->getPointerOperand() == UseV)
5258 MA = LI->getAlign();
5260 if (AI->getPointerOperand() == UseV)
5261 MA = AI->getAlign();
5263 if (AI->getPointerOperand() == UseV)
5264 MA = AI->getAlign();
5270 unsigned Alignment = MA->value();
5274 if (
Base == &AssociatedValue) {
5279 uint32_t
gcd = std::gcd(uint32_t(
abs((int32_t)
Offset)), Alignment);
5287struct AAAlignImpl : AAAlign {
5288 AAAlignImpl(
const IRPosition &IRP, Attributor &
A) : AAAlign(IRP,
A) {}
5293 A.getAttrs(getIRPosition(), {Attribute::Alignment},
Attrs);
5295 takeKnownMaximum(Attr.getValueAsInt());
5297 Value &
V = *getAssociatedValue().stripPointerCasts();
5298 takeKnownMaximum(
V.getPointerAlignment(
A.getDataLayout()).value());
5300 if (Instruction *CtxI = getCtxI())
5301 followUsesInMBEC(*
this,
A, getState(), *CtxI);
5309 Value &AssociatedValue = getAssociatedValue();
5311 return ChangeStatus::UNCHANGED;
5313 for (
const Use &U : AssociatedValue.
uses()) {
5315 if (
SI->getPointerOperand() == &AssociatedValue)
5316 if (
SI->getAlign() < getAssumedAlign()) {
5318 "Number of times alignment added to a store");
5319 SI->setAlignment(getAssumedAlign());
5320 InstrChanged = ChangeStatus::CHANGED;
5323 if (LI->getPointerOperand() == &AssociatedValue)
5324 if (LI->getAlign() < getAssumedAlign()) {
5325 LI->setAlignment(getAssumedAlign());
5327 "Number of times alignment added to a load");
5328 InstrChanged = ChangeStatus::CHANGED;
5331 if (RMW->getPointerOperand() == &AssociatedValue) {
5332 if (RMW->getAlign() < getAssumedAlign()) {
5334 "Number of times alignment added to atomicrmw");
5336 RMW->setAlignment(getAssumedAlign());
5337 InstrChanged = ChangeStatus::CHANGED;
5341 if (CAS->getPointerOperand() == &AssociatedValue) {
5342 if (CAS->getAlign() < getAssumedAlign()) {
5344 "Number of times alignment added to cmpxchg");
5345 CAS->setAlignment(getAssumedAlign());
5346 InstrChanged = ChangeStatus::CHANGED;
5354 Align InheritAlign =
5355 getAssociatedValue().getPointerAlignment(
A.getDataLayout());
5356 if (InheritAlign >= getAssumedAlign())
5357 return InstrChanged;
5358 return Changed | InstrChanged;
5366 void getDeducedAttributes(Attributor &
A, LLVMContext &Ctx,
5367 SmallVectorImpl<Attribute> &Attrs)
const override {
5368 if (getAssumedAlign() > 1)
5370 Attribute::getWithAlignment(Ctx,
Align(getAssumedAlign())));
5374 bool followUseInMBEC(Attributor &
A,
const Use *U,
const Instruction *
I,
5375 AAAlign::StateType &State) {
5376 bool TrackUse =
false;
5378 unsigned int KnownAlign =
5379 getKnownAlignForUse(
A, *
this, getAssociatedValue(), U,
I, TrackUse);
5380 State.takeKnownMaximum(KnownAlign);
5386 const std::string getAsStr(Attributor *
A)
const override {
5387 return "align<" + std::to_string(getKnownAlign().value()) +
"-" +
5388 std::to_string(getAssumedAlign().value()) +
">";
5393struct AAAlignFloating : AAAlignImpl {
5394 AAAlignFloating(
const IRPosition &IRP, Attributor &
A) : AAAlignImpl(IRP,
A) {}
5398 const DataLayout &
DL =
A.getDataLayout();
5401 bool UsedAssumedInformation =
false;
5403 if (!
A.getAssumedSimplifiedValues(getIRPosition(), *
this, Values,
5405 Values.
push_back({getAssociatedValue(), getCtxI()});
5408 Stripped = Values.
size() != 1 ||
5409 Values.
front().getValue() != &getAssociatedValue();
5413 auto VisitValueCB = [&](
Value &
V) ->
bool {
5417 DepClassTy::REQUIRED);
5418 if (!AA || (!Stripped &&
this == AA)) {
5420 unsigned Alignment = 1;
5433 Alignment =
V.getPointerAlignment(
DL).value();
5436 T.takeKnownMaximum(Alignment);
5437 T.indicatePessimisticFixpoint();
5440 const AAAlign::StateType &
DS = AA->
getState();
5443 return T.isValidState();
5446 for (
const auto &VAC : Values) {
5447 if (!VisitValueCB(*VAC.
getValue()))
5448 return indicatePessimisticFixpoint();
5461struct AAAlignReturned final
5462 : AAReturnedFromReturnedValues<AAAlign, AAAlignImpl> {
5463 using Base = AAReturnedFromReturnedValues<AAAlign, AAAlignImpl>;
5464 AAAlignReturned(
const IRPosition &IRP, Attributor &
A) :
Base(IRP,
A) {}
5471struct AAAlignArgument final
5472 : AAArgumentFromCallSiteArguments<AAAlign, AAAlignImpl> {
5473 using Base = AAArgumentFromCallSiteArguments<AAAlign, AAAlignImpl>;
5474 AAAlignArgument(
const IRPosition &IRP, Attributor &
A) :
Base(IRP,
A) {}
5481 if (
A.getInfoCache().isInvolvedInMustTailCall(*getAssociatedArgument()))
5482 return ChangeStatus::UNCHANGED;
5483 return Base::manifest(
A);
5490struct AAAlignCallSiteArgument final : AAAlignFloating {
5491 AAAlignCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
5492 : AAAlignFloating(IRP,
A) {}
5499 if (Argument *Arg = getAssociatedArgument())
5500 if (
A.getInfoCache().isInvolvedInMustTailCall(*Arg))
5501 return ChangeStatus::UNCHANGED;
5503 Align InheritAlign =
5504 getAssociatedValue().getPointerAlignment(
A.getDataLayout());
5505 if (InheritAlign >= getAssumedAlign())
5506 Changed = ChangeStatus::UNCHANGED;
5513 if (Argument *Arg = getAssociatedArgument()) {
5516 const auto *ArgAlignAA =
A.getAAFor<AAAlign>(
5519 takeKnownMaximum(ArgAlignAA->getKnownAlign().value());
5529struct AAAlignCallSiteReturned final
5530 : AACalleeToCallSite<AAAlign, AAAlignImpl> {
5531 using Base = AACalleeToCallSite<AAAlign, AAAlignImpl>;
5532 AAAlignCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
5538 switch (
II->getIntrinsicID()) {
5539 case Intrinsic::ptrmask: {
5543 const auto *ConstVals =
A.getAAFor<AAPotentialConstantValues>(
5545 if (ConstVals && ConstVals->isValidState()) {
5546 unsigned ShiftValue =
5547 std::min(ConstVals->getAssumedMinTrailingZeros(),
5548 Value::MaxAlignmentExponent);
5549 Alignment =
Align(UINT64_C(1) << ShiftValue);
5553 const auto *AlignAA =
5555 DepClassTy::REQUIRED);
5557 Alignment = std::max(AlignAA->getAssumedAlign(), Alignment);
5564 std::min(this->getAssumedAlign(), Alignment).value());
5570 case Intrinsic::amdgcn_make_buffer_rsrc: {
5571 const auto *AlignAA =
5573 DepClassTy::REQUIRED);
5576 this->getState(), AlignAA->getAssumedAlign().
value());
5583 return Base::updateImpl(
A);
5592struct AANoReturnImpl :
public AANoReturn {
5593 AANoReturnImpl(
const IRPosition &IRP, Attributor &
A) : AANoReturn(IRP,
A) {}
5599 A,
nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));
5604 const std::string getAsStr(Attributor *
A)
const override {
5605 return getAssumed() ?
"noreturn" :
"may-return";
5610 auto CheckForNoReturn = [](
Instruction &) {
return false; };
5611 bool UsedAssumedInformation =
false;
5612 if (!
A.checkForAllInstructions(CheckForNoReturn, *
this,
5613 {(unsigned)Instruction::Ret},
5614 UsedAssumedInformation))
5615 return indicatePessimisticFixpoint();
5616 return ChangeStatus::UNCHANGED;
5620struct AANoReturnFunction final : AANoReturnImpl {
5621 AANoReturnFunction(
const IRPosition &IRP, Attributor &
A)
5622 : AANoReturnImpl(IRP,
A) {}
5629struct AANoReturnCallSite final
5630 : AACalleeToCallSite<AANoReturn, AANoReturnImpl> {
5631 AANoReturnCallSite(
const IRPosition &IRP, Attributor &
A)
5632 : AACalleeToCallSite<AANoReturn, AANoReturnImpl>(IRP,
A) {}
5643struct AAInstanceInfoImpl :
public AAInstanceInfo {
5644 AAInstanceInfoImpl(
const IRPosition &IRP, Attributor &
A)
5645 : AAInstanceInfo(IRP,
A) {}
5649 Value &
V = getAssociatedValue();
5651 if (
C->isThreadDependent())
5652 indicatePessimisticFixpoint();
5654 indicateOptimisticFixpoint();
5660 indicateOptimisticFixpoint();
5665 A.getInfoCache().getAnalysisResultForFunction<CycleAnalysis>(
5668 indicatePessimisticFixpoint();
5678 Value &
V = getAssociatedValue();
5681 Scope =
I->getFunction();
5684 if (!
Scope->hasLocalLinkage())
5688 return indicateOptimisticFixpoint();
5690 bool IsKnownNoRecurse;
5696 auto UsePred = [&](
const Use &
U,
bool &Follow) {
5711 if (!Callee || !
Callee->hasLocalLinkage())
5715 const auto *ArgInstanceInfoAA =
A.getAAFor<AAInstanceInfo>(
5717 DepClassTy::OPTIONAL);
5718 if (!ArgInstanceInfoAA ||
5719 !ArgInstanceInfoAA->isAssumedUniqueForAnalysis())
5724 A, *CB, *Scope, *
this,
nullptr,
5725 [Scope](
const Function &Fn) {
return &Fn !=
Scope; }))
5732 auto EquivalentUseCB = [&](
const Use &OldU,
const Use &NewU) {
5734 auto *Ptr =
SI->getPointerOperand()->stripPointerCasts();
5742 if (!
A.checkForAllUses(UsePred, *
this, V,
true,
5743 DepClassTy::OPTIONAL,
5744 true, EquivalentUseCB))
5745 return indicatePessimisticFixpoint();
5751 const std::string getAsStr(Attributor *
A)
const override {
5752 return isAssumedUniqueForAnalysis() ?
"<unique [fAa]>" :
"<unknown>";
5756 void trackStatistics()
const override {}
5760struct AAInstanceInfoFloating : AAInstanceInfoImpl {
5761 AAInstanceInfoFloating(
const IRPosition &IRP, Attributor &
A)
5762 : AAInstanceInfoImpl(IRP,
A) {}
5766struct AAInstanceInfoArgument final : AAInstanceInfoFloating {
5767 AAInstanceInfoArgument(
const IRPosition &IRP, Attributor &
A)
5768 : AAInstanceInfoFloating(IRP,
A) {}
5772struct AAInstanceInfoCallSiteArgument final : AAInstanceInfoImpl {
5773 AAInstanceInfoCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
5774 : AAInstanceInfoImpl(IRP,
A) {}
5782 Argument *Arg = getAssociatedArgument();
5784 return indicatePessimisticFixpoint();
5787 A.getAAFor<AAInstanceInfo>(*
this, ArgPos, DepClassTy::REQUIRED);
5789 return indicatePessimisticFixpoint();
5795struct AAInstanceInfoReturned final : AAInstanceInfoImpl {
5796 AAInstanceInfoReturned(
const IRPosition &IRP, Attributor &
A)
5797 : AAInstanceInfoImpl(IRP,
A) {
5813struct AAInstanceInfoCallSiteReturned final : AAInstanceInfoFloating {
5814 AAInstanceInfoCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
5815 : AAInstanceInfoFloating(IRP,
A) {}
5822 bool IgnoreSubsumingPositions) {
5823 assert(ImpliedAttributeKind == Attribute::Captures &&
5824 "Unexpected attribute kind");
5834 V.getType()->getPointerAddressSpace() == 0)) {
5839 A.getAttrs(IRP, {Attribute::Captures}, Attrs,
5849 {Attribute::Captures, Attribute::ByVal}, Attrs,
5886 bool ReadOnly =
F.onlyReadsMemory();
5887 bool NoThrow =
F.doesNotThrow();
5888 bool IsVoidReturn =
F.getReturnType()->isVoidTy();
5889 if (ReadOnly && NoThrow && IsVoidReturn) {
5902 if (NoThrow && IsVoidReturn)
5907 if (!NoThrow || ArgNo < 0 ||
5908 !
F.getAttributes().hasAttrSomewhere(Attribute::Returned))
5911 for (
unsigned U = 0, E =
F.arg_size(); U < E; ++U)
5912 if (
F.hasParamAttribute(U, Attribute::Returned)) {
5913 if (U ==
unsigned(ArgNo))
5940 void getDeducedAttributes(Attributor &
A, LLVMContext &Ctx,
5941 SmallVectorImpl<Attribute> &Attrs)
const override {
5942 if (!isAssumedNoCaptureMaybeReturned())
5945 if (isArgumentPosition()) {
5946 if (isAssumedNoCapture())
5947 Attrs.emplace_back(Attribute::get(Ctx, Attribute::Captures));
5949 Attrs.emplace_back(Attribute::get(Ctx,
"no-capture-maybe-returned"));
5954 const std::string getAsStr(Attributor *
A)
const override {
5955 if (isKnownNoCapture())
5956 return "known not-captured";
5957 if (isAssumedNoCapture())
5958 return "assumed not-captured";
5959 if (isKnownNoCaptureMaybeReturned())
5960 return "known not-captured-maybe-returned";
5961 if (isAssumedNoCaptureMaybeReturned())
5962 return "assumed not-captured-maybe-returned";
5963 return "assumed-captured";
5968 bool checkUse(Attributor &
A, AANoCapture::StateType &State,
const Use &U,
5971 LLVM_DEBUG(
dbgs() <<
"[AANoCapture] Check use: " << *
U.get() <<
" in "
5977 return isCapturedIn(State,
true,
true,
5984 return isCapturedIn(State,
true,
true,
5990 return isCapturedIn(State,
false,
false,
5992 return isCapturedIn(State,
true,
true,
6000 return isCapturedIn(State,
true,
true,
6007 bool IsKnownNoCapture;
6008 const AANoCapture *ArgNoCaptureAA =
nullptr;
6010 A,
this, CSArgPos, DepClassTy::REQUIRED, IsKnownNoCapture,
false,
6012 if (IsAssumedNoCapture)
6013 return isCapturedIn(State,
false,
false,
6017 return isCapturedIn(State,
false,
false,
6022 return isCapturedIn(State,
true,
true,
6029 static bool isCapturedIn(AANoCapture::StateType &State,
bool CapturedInMem,
6030 bool CapturedInInt,
bool CapturedInRet) {
6031 LLVM_DEBUG(
dbgs() <<
" - captures [Mem " << CapturedInMem <<
"|Int "
6032 << CapturedInInt <<
"|Ret " << CapturedInRet <<
"]\n");
6044 const IRPosition &IRP = getIRPosition();
6048 return indicatePessimisticFixpoint();
6055 return indicatePessimisticFixpoint();
6063 T.addKnownBits(NOT_CAPTURED_IN_MEM);
6065 addKnownBits(NOT_CAPTURED_IN_MEM);
6072 auto CheckReturnedArgs = [&](
bool &UsedAssumedInformation) {
6076 UsedAssumedInformation))
6078 bool SeenConstant =
false;
6079 for (
const AA::ValueAndContext &VAC : Values) {
6083 SeenConstant =
true;
6085 VAC.
getValue() == getAssociatedArgument())
6091 bool IsKnownNoUnwind;
6094 bool IsVoidTy =
F->getReturnType()->isVoidTy();
6095 bool UsedAssumedInformation =
false;
6096 if (IsVoidTy || CheckReturnedArgs(UsedAssumedInformation)) {
6097 T.addKnownBits(NOT_CAPTURED_IN_RET);
6098 if (
T.isKnown(NOT_CAPTURED_IN_MEM))
6100 if (IsKnownNoUnwind && (IsVoidTy || !UsedAssumedInformation)) {
6101 addKnownBits(NOT_CAPTURED_IN_RET);
6102 if (isKnown(NOT_CAPTURED_IN_MEM))
6103 return indicateOptimisticFixpoint();
6108 auto UseCheck = [&](
const Use &
U,
bool &Follow) ->
bool {
6117 return checkUse(
A,
T, U, Follow);
6120 if (!
A.checkForAllUses(UseCheck, *
this, *V))
6121 return indicatePessimisticFixpoint();
6124 auto Assumed = S.getAssumed();
6125 S.intersectAssumedBits(
T.getAssumed());
6126 if (!isAssumedNoCaptureMaybeReturned())
6127 return indicatePessimisticFixpoint();
6133struct AANoCaptureArgument final : AANoCaptureImpl {
6134 AANoCaptureArgument(
const IRPosition &IRP, Attributor &
A)
6135 : AANoCaptureImpl(IRP,
A) {}
6142struct AANoCaptureCallSiteArgument final : AANoCaptureImpl {
6143 AANoCaptureCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
6144 : AANoCaptureImpl(IRP,
A) {}
6152 Argument *Arg = getAssociatedArgument();
6154 return indicatePessimisticFixpoint();
6156 bool IsKnownNoCapture;
6157 const AANoCapture *ArgAA =
nullptr;
6159 A,
this, ArgPos, DepClassTy::REQUIRED, IsKnownNoCapture,
false,
6161 return ChangeStatus::UNCHANGED;
6163 return indicatePessimisticFixpoint();
6168 void trackStatistics()
const override {
6174struct AANoCaptureFloating final : AANoCaptureImpl {
6175 AANoCaptureFloating(
const IRPosition &IRP, Attributor &
A)
6176 : AANoCaptureImpl(IRP,
A) {}
6179 void trackStatistics()
const override {
6185struct AANoCaptureReturned final : AANoCaptureImpl {
6186 AANoCaptureReturned(
const IRPosition &IRP, Attributor &
A)
6187 : AANoCaptureImpl(IRP,
A) {
6202 void trackStatistics()
const override {}
6206struct AANoCaptureCallSiteReturned final : AANoCaptureImpl {
6207 AANoCaptureCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
6208 : AANoCaptureImpl(IRP,
A) {}
6214 determineFunctionCaptureCapabilities(getIRPosition(), *
F, *
this);
6218 void trackStatistics()
const override {
6235 dbgs() <<
"[ValueSimplify] is assumed to be "
6238 dbgs() <<
"[ValueSimplify] is assumed to be <none>\n";
6250 if (getAssociatedValue().
getType()->isVoidTy())
6251 indicatePessimisticFixpoint();
6252 if (
A.hasSimplificationCallback(getIRPosition()))
6253 indicatePessimisticFixpoint();
6257 const std::string getAsStr(Attributor *
A)
const override {
6259 dbgs() <<
"SAV: " << (bool)SimplifiedAssociatedValue <<
" ";
6260 if (SimplifiedAssociatedValue && *SimplifiedAssociatedValue)
6261 dbgs() <<
"SAV: " << **SimplifiedAssociatedValue <<
" ";
6263 return isValidState() ? (isAtFixpoint() ?
"simplified" :
"maybe-simple")
6268 void trackStatistics()
const override {}
6271 std::optional<Value *>
6272 getAssumedSimplifiedValue(Attributor &
A)
const override {
6273 return SimplifiedAssociatedValue;
6280 static Value *ensureType(Attributor &
A,
Value &V,
Type &Ty, Instruction *CtxI,
6284 if (CtxI &&
V.getType()->canLosslesslyBitCastTo(&Ty))
6286 : BitCastInst::CreatePointerBitCastOrAddrSpaceCast(
6295 static Value *reproduceInst(Attributor &
A,
6296 const AbstractAttribute &QueryingAA,
6297 Instruction &
I,
Type &Ty, Instruction *CtxI,
6299 assert(CtxI &&
"Cannot reproduce an instruction without context!");
6300 if (
Check && (
I.mayReadFromMemory() ||
6305 Value *NewOp = reproduceValue(
A, QueryingAA, *
Op, Ty, CtxI,
Check, VMap);
6307 assert(
Check &&
"Manifest of new value unexpectedly failed!");
6329 static Value *reproduceValue(Attributor &
A,
6330 const AbstractAttribute &QueryingAA,
Value &V,
6331 Type &Ty, Instruction *CtxI,
bool Check,
6333 if (
const auto &NewV = VMap.
lookup(&V))
6335 bool UsedAssumedInformation =
false;
6336 std::optional<Value *> SimpleV =
A.getAssumedSimplified(
6338 if (!SimpleV.has_value())
6342 EffectiveV = *SimpleV;
6347 return ensureType(
A, *EffectiveV, Ty, CtxI,
Check);
6349 if (
Value *NewV = reproduceInst(
A, QueryingAA, *
I, Ty, CtxI,
Check, VMap))
6350 return ensureType(
A, *NewV, Ty, CtxI,
Check);
6356 Value *manifestReplacementValue(Attributor &
A, Instruction *CtxI)
const {
6357 Value *NewV = SimplifiedAssociatedValue
6358 ? *SimplifiedAssociatedValue
6360 if (NewV && NewV != &getAssociatedValue()) {
6364 if (reproduceValue(
A, *
this, *NewV, *getAssociatedType(), CtxI,
6366 return reproduceValue(
A, *
this, *NewV, *getAssociatedType(), CtxI,
6374 bool checkAndUpdate(Attributor &
A,
const AbstractAttribute &QueryingAA,
6375 const IRPosition &IRP,
bool Simplify =
true) {
6376 bool UsedAssumedInformation =
false;
6379 QueryingValueSimplified =
A.getAssumedSimplified(
6381 return unionAssumed(QueryingValueSimplified);
6385 template <
typename AAType>
bool askSimplifiedValueFor(Attributor &
A) {
6386 if (!getAssociatedValue().
getType()->isIntegerTy())
6391 A.getAAFor<AAType>(*
this, getIRPosition(), DepClassTy::NONE);
6395 std::optional<Constant *> COpt = AA->getAssumedConstant(
A);
6398 SimplifiedAssociatedValue = std::nullopt;
6399 A.recordDependence(*AA, *
this, DepClassTy::OPTIONAL);
6402 if (
auto *
C = *COpt) {
6403 SimplifiedAssociatedValue =
C;
6404 A.recordDependence(*AA, *
this, DepClassTy::OPTIONAL);
6410 bool askSimplifiedValueForOtherAAs(Attributor &
A) {
6411 if (askSimplifiedValueFor<AAValueConstantRange>(
A))
6413 if (askSimplifiedValueFor<AAPotentialConstantValues>(
A))
6421 for (
auto &U : getAssociatedValue().uses()) {
6426 IP =
PHI->getIncomingBlock(U)->getTerminator();
6427 if (
auto *NewV = manifestReplacementValue(
A, IP)) {
6429 <<
" -> " << *NewV <<
" :: " << *
this <<
"\n");
6430 if (
A.changeUseAfterManifest(U, *NewV))
6431 Changed = ChangeStatus::CHANGED;
6435 return Changed | AAValueSimplify::manifest(
A);
6440 SimplifiedAssociatedValue = &getAssociatedValue();
6441 return AAValueSimplify::indicatePessimisticFixpoint();
6445struct AAValueSimplifyArgument final : AAValueSimplifyImpl {
6446 AAValueSimplifyArgument(
const IRPosition &IRP, Attributor &
A)
6447 : AAValueSimplifyImpl(IRP,
A) {}
6450 AAValueSimplifyImpl::initialize(
A);
6451 if (
A.hasAttr(getIRPosition(),
6452 {Attribute::InAlloca, Attribute::Preallocated,
6453 Attribute::StructRet, Attribute::Nest, Attribute::ByVal},
6455 indicatePessimisticFixpoint();
6462 Argument *Arg = getAssociatedArgument();
6468 return indicatePessimisticFixpoint();
6471 auto Before = SimplifiedAssociatedValue;
6473 auto PredForCallSite = [&](AbstractCallSite ACS) {
6474 const IRPosition &ACSArgPos =
6485 bool UsedAssumedInformation =
false;
6486 std::optional<Constant *> SimpleArgOp =
6487 A.getAssumedConstant(ACSArgPos, *
this, UsedAssumedInformation);
6494 return unionAssumed(*SimpleArgOp);
6499 bool UsedAssumedInformation =
false;
6500 if (hasCallBaseContext() &&
6501 getCallBaseContext()->getCalledOperand() == Arg->
getParent())
6503 AbstractCallSite(&getCallBaseContext()->getCalledOperandUse()));
6505 Success =
A.checkForAllCallSites(PredForCallSite, *
this,
true,
6506 UsedAssumedInformation);
6509 if (!askSimplifiedValueForOtherAAs(
A))
6510 return indicatePessimisticFixpoint();
6513 return Before == SimplifiedAssociatedValue ? ChangeStatus::UNCHANGED
6514 : ChangeStatus ::CHANGED;
6518 void trackStatistics()
const override {
6523struct AAValueSimplifyReturned : AAValueSimplifyImpl {
6524 AAValueSimplifyReturned(
const IRPosition &IRP, Attributor &
A)
6525 : AAValueSimplifyImpl(IRP,
A) {}
6528 std::optional<Value *>
6529 getAssumedSimplifiedValue(Attributor &
A)
const override {
6530 if (!isValidState())
6532 return SimplifiedAssociatedValue;
6537 auto Before = SimplifiedAssociatedValue;
6541 return checkAndUpdate(
6546 bool UsedAssumedInformation =
false;
6547 if (!
A.checkForAllInstructions(ReturnInstCB, *
this, {Instruction::Ret},
6548 UsedAssumedInformation))
6549 if (!askSimplifiedValueForOtherAAs(
A))
6550 return indicatePessimisticFixpoint();
6553 return Before == SimplifiedAssociatedValue ? ChangeStatus::UNCHANGED
6554 : ChangeStatus ::CHANGED;
6560 return ChangeStatus::UNCHANGED;
6564 void trackStatistics()
const override {
6569struct AAValueSimplifyFloating : AAValueSimplifyImpl {
6570 AAValueSimplifyFloating(
const IRPosition &IRP, Attributor &
A)
6571 : AAValueSimplifyImpl(IRP,
A) {}
6575 AAValueSimplifyImpl::initialize(
A);
6576 Value &
V = getAnchorValue();
6580 indicatePessimisticFixpoint();
6585 auto Before = SimplifiedAssociatedValue;
6586 if (!askSimplifiedValueForOtherAAs(
A))
6587 return indicatePessimisticFixpoint();
6590 return Before == SimplifiedAssociatedValue ? ChangeStatus::UNCHANGED
6591 : ChangeStatus ::CHANGED;
6595 void trackStatistics()
const override {
6600struct AAValueSimplifyFunction : AAValueSimplifyImpl {
6601 AAValueSimplifyFunction(
const IRPosition &IRP, Attributor &
A)
6602 : AAValueSimplifyImpl(IRP,
A) {}
6606 SimplifiedAssociatedValue =
nullptr;
6607 indicateOptimisticFixpoint();
6612 "AAValueSimplify(Function|CallSite)::updateImpl will not be called");
6615 void trackStatistics()
const override {
6620struct AAValueSimplifyCallSite : AAValueSimplifyFunction {
6621 AAValueSimplifyCallSite(
const IRPosition &IRP, Attributor &
A)
6622 : AAValueSimplifyFunction(IRP,
A) {}
6624 void trackStatistics()
const override {
6629struct AAValueSimplifyCallSiteReturned : AAValueSimplifyImpl {
6630 AAValueSimplifyCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
6631 : AAValueSimplifyImpl(IRP,
A) {}
6634 AAValueSimplifyImpl::initialize(
A);
6635 Function *Fn = getAssociatedFunction();
6636 assert(Fn &&
"Did expect an associted function");
6637 for (Argument &Arg : Fn->
args()) {
6642 checkAndUpdate(
A, *
this, IRP))
6643 indicateOptimisticFixpoint();
6645 indicatePessimisticFixpoint();
6653 return indicatePessimisticFixpoint();
6656 void trackStatistics()
const override {
6661struct AAValueSimplifyCallSiteArgument : AAValueSimplifyFloating {
6662 AAValueSimplifyCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
6663 : AAValueSimplifyFloating(IRP,
A) {}
6669 auto *FloatAA =
A.lookupAAFor<AAValueSimplify>(
6671 if (FloatAA && FloatAA->getState().isValidState())
6674 if (
auto *NewV = manifestReplacementValue(
A, getCtxI())) {
6676 ->getArgOperandUse(getCallSiteArgNo());
6677 if (
A.changeUseAfterManifest(U, *NewV))
6678 Changed = ChangeStatus::CHANGED;
6681 return Changed | AAValueSimplify::manifest(
A);
6684 void trackStatistics()
const override {
6692struct AAHeapToStackFunction final :
public AAHeapToStack {
6694 struct AllocationInfo {
6699 LibFunc LibraryFunctionId = NotLibFunc;
6706 } Status = STACK_DUE_TO_USE;
6710 bool HasPotentiallyFreeingUnknownUses =
false;
6714 bool MoveAllocaIntoEntry =
true;
6717 SmallSetVector<CallBase *, 1> PotentialFreeCalls{};
6720 struct DeallocationInfo {
6728 bool MightFreeUnknownObjects =
false;
6731 SmallSetVector<CallBase *, 1> PotentialAllocationCalls{};
6734 AAHeapToStackFunction(
const IRPosition &IRP, Attributor &
A)
6735 : AAHeapToStack(IRP,
A) {}
6737 ~AAHeapToStackFunction()
override {
6740 for (
auto &It : AllocationInfos)
6741 It.second->~AllocationInfo();
6742 for (
auto &It : DeallocationInfos)
6743 It.second->~DeallocationInfo();
6747 AAHeapToStack::initialize(
A);
6750 const auto *TLI =
A.getInfoCache().getTargetLibraryInfoForFunction(*
F);
6757 DeallocationInfos[CB] =
new (
A.Allocator) DeallocationInfo{CB, FreedOp};
6764 auto *I8Ty = Type::getInt8Ty(CB->
getParent()->getContext());
6766 AllocationInfo *AI =
new (
A.Allocator) AllocationInfo{CB};
6767 AllocationInfos[CB] = AI;
6769 TLI->getLibFunc(*CB, AI->LibraryFunctionId);
6775 bool UsedAssumedInformation =
false;
6776 bool Success =
A.checkForAllCallLikeInstructions(
6777 AllocationIdentifierCB, *
this, UsedAssumedInformation,
6781 assert(
Success &&
"Did not expect the call base visit callback to fail!");
6784 [](
const IRPosition &,
const AbstractAttribute *,
6785 bool &) -> std::optional<Value *> {
return nullptr; };
6786 for (
const auto &It : AllocationInfos)
6789 for (
const auto &It : DeallocationInfos)
6794 const std::string getAsStr(Attributor *
A)
const override {
6795 unsigned NumH2SMallocs = 0, NumInvalidMallocs = 0;
6796 for (
const auto &It : AllocationInfos) {
6797 if (It.second->Status == AllocationInfo::INVALID)
6798 ++NumInvalidMallocs;
6802 return "[H2S] Mallocs Good/Bad: " + std::to_string(NumH2SMallocs) +
"/" +
6803 std::to_string(NumInvalidMallocs);
6807 void trackStatistics()
const override {
6809 MallocCalls, Function,
6810 "Number of malloc/calloc/aligned_alloc calls converted to allocas");
6811 for (
const auto &It : AllocationInfos)
6812 if (It.second->Status != AllocationInfo::INVALID)
6816 bool isAssumedHeapToStack(
const CallBase &CB)
const override {
6818 if (AllocationInfo *AI =
6819 AllocationInfos.lookup(
const_cast<CallBase *
>(&CB)))
6820 return AI->Status != AllocationInfo::INVALID;
6824 bool isAssumedHeapToStackRemovedFree(CallBase &CB)
const override {
6825 if (!isValidState())
6828 for (
const auto &It : AllocationInfos) {
6829 AllocationInfo &AI = *It.second;
6830 if (AI.Status == AllocationInfo::INVALID)
6833 if (AI.PotentialFreeCalls.count(&CB))
6841 assert(getState().isValidState() &&
6842 "Attempted to manifest an invalid state!");
6846 const auto *TLI =
A.getInfoCache().getTargetLibraryInfoForFunction(*
F);
6848 for (
auto &It : AllocationInfos) {
6849 AllocationInfo &AI = *It.second;
6850 if (AI.Status == AllocationInfo::INVALID)
6853 for (CallBase *FreeCall : AI.PotentialFreeCalls) {
6854 LLVM_DEBUG(
dbgs() <<
"H2S: Removing free call: " << *FreeCall <<
"\n");
6855 A.deleteAfterManifest(*FreeCall);
6856 HasChanged = ChangeStatus::CHANGED;
6859 LLVM_DEBUG(
dbgs() <<
"H2S: Removing malloc-like call: " << *AI.CB
6862 auto Remark = [&](OptimizationRemark
OR) {
6863 LibFunc IsAllocShared;
6864 if (TLI->getLibFunc(*AI.CB, IsAllocShared))
6865 if (IsAllocShared == LibFunc___kmpc_alloc_shared)
6866 return OR <<
"Moving globalized variable to the stack.";
6867 return OR <<
"Moving memory allocation from the heap to the stack.";
6869 if (AI.LibraryFunctionId == LibFunc___kmpc_alloc_shared)
6870 A.emitRemark<OptimizationRemark>(AI.CB,
"OMP110",
Remark);
6872 A.emitRemark<OptimizationRemark>(AI.CB,
"HeapToStack",
Remark);
6874 const DataLayout &
DL =
A.getInfoCache().getDL();
6876 std::optional<APInt> SizeAPI =
getSize(
A, *
this, AI);
6878 Size = ConstantInt::get(AI.CB->getContext(), *SizeAPI);
6880 LLVMContext &Ctx = AI.CB->getContext();
6881 ObjectSizeOpts Opts;
6882 ObjectSizeOffsetEvaluator Eval(
DL, TLI, Ctx, Opts);
6883 SizeOffsetValue SizeOffsetPair = Eval.compute(AI.CB);
6890 ?
F->getEntryBlock().begin()
6891 : AI.CB->getIterator();
6894 if (MaybeAlign RetAlign = AI.CB->getRetAlign())
6895 Alignment = std::max(Alignment, *RetAlign);
6897 std::optional<APInt> AlignmentAPI = getAPInt(
A, *
this, *Align);
6898 assert(AlignmentAPI && AlignmentAPI->getZExtValue() > 0 &&
6899 "Expected an alignment during manifest!");
6901 std::max(Alignment,
assumeAligned(AlignmentAPI->getZExtValue()));
6905 unsigned AS =
DL.getAllocaAddrSpace();
6907 new AllocaInst(Type::getInt8Ty(
F->getContext()), AS,
Size, Alignment,
6908 AI.CB->getName() +
".h2s", IP);
6910 if (Alloca->
getType() != AI.CB->getType())
6911 Alloca = BitCastInst::CreatePointerBitCastOrAddrSpaceCast(
6912 Alloca, AI.CB->getType(),
"malloc_cast", AI.CB->getIterator());
6914 auto *I8Ty = Type::getInt8Ty(
F->getContext());
6917 "Must be able to materialize initial memory state of allocation");
6922 auto *NBB =
II->getNormalDest();
6924 A.deleteAfterManifest(*AI.CB);
6926 A.deleteAfterManifest(*AI.CB);
6935 Builder.CreateMemSet(Alloca, InitVal,
Size, std::nullopt);
6937 HasChanged = ChangeStatus::CHANGED;
6943 std::optional<APInt> getAPInt(Attributor &
A,
const AbstractAttribute &AA,
6945 bool UsedAssumedInformation =
false;
6946 std::optional<Constant *> SimpleV =
6947 A.getAssumedConstant(V, AA, UsedAssumedInformation);
6949 return APInt(64, 0);
6951 return CI->getValue();
6952 return std::nullopt;
6955 std::optional<APInt>
getSize(Attributor &
A,
const AbstractAttribute &AA,
6956 AllocationInfo &AI) {
6957 auto Mapper = [&](
const Value *
V) ->
const Value * {
6958 bool UsedAssumedInformation =
false;
6959 if (std::optional<Constant *> SimpleV =
6960 A.getAssumedConstant(*V, AA, UsedAssumedInformation))
6967 const auto *TLI =
A.getInfoCache().getTargetLibraryInfoForFunction(*
F);
6973 MapVector<CallBase *, AllocationInfo *> AllocationInfos;
6977 MapVector<CallBase *, DeallocationInfo *> DeallocationInfos;
6982ChangeStatus AAHeapToStackFunction::updateImpl(Attributor &
A) {
6985 const auto *TLI =
A.getInfoCache().getTargetLibraryInfoForFunction(*
F);
6987 const auto *LivenessAA =
6990 MustBeExecutedContextExplorer *Explorer =
6991 A.getInfoCache().getMustBeExecutedContextExplorer();
6993 bool StackIsAccessibleByOtherThreads =
6994 A.getInfoCache().stackIsAccessibleByOtherThreads();
6997 A.getInfoCache().getAnalysisResultForFunction<LoopAnalysis>(*F);
6998 std::optional<bool> MayContainIrreducibleControl;
7000 if (&
F->getEntryBlock() == &BB)
7002 if (!MayContainIrreducibleControl.has_value())
7004 if (*MayContainIrreducibleControl)
7013 bool HasUpdatedFrees =
false;
7015 auto UpdateFrees = [&]() {
7016 HasUpdatedFrees =
true;
7018 for (
auto &It : DeallocationInfos) {
7019 DeallocationInfo &DI = *It.second;
7022 if (DI.MightFreeUnknownObjects)
7026 bool UsedAssumedInformation =
false;
7027 if (
A.isAssumedDead(*DI.CB,
this, LivenessAA, UsedAssumedInformation,
7034 LLVM_DEBUG(
dbgs() <<
"[H2S] Unknown underlying object for free!\n");
7035 DI.MightFreeUnknownObjects =
true;
7048 DI.MightFreeUnknownObjects =
true;
7052 AllocationInfo *AI = AllocationInfos.lookup(ObjCB);
7054 LLVM_DEBUG(
dbgs() <<
"[H2S] Free of a non-allocation object: " << *Obj
7056 DI.MightFreeUnknownObjects =
true;
7060 DI.PotentialAllocationCalls.insert(ObjCB);
7064 auto FreeCheck = [&](AllocationInfo &AI) {
7068 if (!StackIsAccessibleByOtherThreads) {
7073 dbgs() <<
"[H2S] found an escaping use, stack is not accessible by "
7074 "other threads and function is not nosync:\n");
7078 if (!HasUpdatedFrees)
7082 if (AI.PotentialFreeCalls.size() != 1) {
7084 << AI.PotentialFreeCalls.size() <<
"\n");
7087 CallBase *UniqueFree = *AI.PotentialFreeCalls.begin();
7088 DeallocationInfo *DI = DeallocationInfos.lookup(UniqueFree);
7091 dbgs() <<
"[H2S] unique free call was not known as deallocation call "
7092 << *UniqueFree <<
"\n");
7095 if (DI->MightFreeUnknownObjects) {
7097 dbgs() <<
"[H2S] unique free call might free unknown allocations\n");
7100 if (DI->PotentialAllocationCalls.empty())
7102 if (DI->PotentialAllocationCalls.size() > 1) {
7104 << DI->PotentialAllocationCalls.size()
7105 <<
" different allocations\n");
7108 if (*DI->PotentialAllocationCalls.begin() != AI.CB) {
7111 <<
"[H2S] unique free call not known to free this allocation but "
7112 << **DI->PotentialAllocationCalls.begin() <<
"\n");
7117 if (AI.LibraryFunctionId != LibFunc___kmpc_alloc_shared) {
7119 if (!Explorer || !Explorer->findInContextOf(UniqueFree, CtxI)) {
7120 LLVM_DEBUG(
dbgs() <<
"[H2S] unique free call might not be executed "
7121 "with the allocation "
7122 << *UniqueFree <<
"\n");
7129 auto UsesCheck = [&](AllocationInfo &AI) {
7130 bool ValidUsesOnly =
true;
7132 auto Pred = [&](
const Use &
U,
bool &Follow) ->
bool {
7137 if (
SI->getValueOperand() ==
U.get()) {
7139 <<
"[H2S] escaping store to memory: " << *UserI <<
"\n");
7140 ValidUsesOnly =
false;
7149 if (DeallocationInfos.count(CB)) {
7150 AI.PotentialFreeCalls.insert(CB);
7157 bool IsKnownNoCapture;
7166 if (!IsAssumedNoCapture ||
7167 (AI.LibraryFunctionId != LibFunc___kmpc_alloc_shared &&
7168 !IsAssumedNoFree)) {
7169 AI.HasPotentiallyFreeingUnknownUses |= !IsAssumedNoFree;
7172 auto Remark = [&](OptimizationRemarkMissed ORM) {
7174 <<
"Could not move globalized variable to the stack. "
7175 "Variable is potentially captured in call. Mark "
7176 "parameter as `__attribute__((noescape))` to override.";
7179 if (ValidUsesOnly &&
7180 AI.LibraryFunctionId == LibFunc___kmpc_alloc_shared)
7181 A.emitRemark<OptimizationRemarkMissed>(CB,
"OMP113",
Remark);
7184 ValidUsesOnly =
false;
7197 ValidUsesOnly =
false;
7200 if (!
A.checkForAllUses(Pred, *
this, *AI.CB,
false,
7202 [&](
const Use &OldU,
const Use &NewU) {
7203 auto *SI = dyn_cast<StoreInst>(OldU.getUser());
7204 return !SI || StackIsAccessibleByOtherThreads ||
7205 AA::isAssumedThreadLocalObject(
7206 A, *SI->getPointerOperand(), *this);
7209 return ValidUsesOnly;
7214 for (
auto &It : AllocationInfos) {
7215 AllocationInfo &AI = *It.second;
7216 if (AI.Status == AllocationInfo::INVALID)
7220 std::optional<APInt> APAlign = getAPInt(
A, *
this, *Align);
7224 LLVM_DEBUG(
dbgs() <<
"[H2S] Unknown allocation alignment: " << *AI.CB
7226 AI.Status = AllocationInfo::INVALID;
7231 !APAlign->isPowerOf2()) {
7232 LLVM_DEBUG(
dbgs() <<
"[H2S] Invalid allocation alignment: " << APAlign
7234 AI.Status = AllocationInfo::INVALID;
7241 if (AI.LibraryFunctionId != LibFunc___kmpc_alloc_shared &&
7246 dbgs() <<
"[H2S] Unknown allocation size: " << *AI.CB <<
"\n";
7248 dbgs() <<
"[H2S] Allocation size too large: " << *AI.CB <<
" vs. "
7252 AI.Status = AllocationInfo::INVALID;
7258 switch (AI.Status) {
7259 case AllocationInfo::STACK_DUE_TO_USE:
7262 AI.Status = AllocationInfo::STACK_DUE_TO_FREE;
7264 case AllocationInfo::STACK_DUE_TO_FREE:
7267 AI.Status = AllocationInfo::INVALID;
7270 case AllocationInfo::INVALID:
7277 bool IsGlobalizedLocal =
7278 AI.LibraryFunctionId == LibFunc___kmpc_alloc_shared;
7279 if (AI.MoveAllocaIntoEntry &&
7280 (!
Size.has_value() ||
7281 (!IsGlobalizedLocal && IsInLoop(*AI.CB->getParent()))))
7282 AI.MoveAllocaIntoEntry =
false;
7291struct AAPrivatizablePtrImpl :
public AAPrivatizablePtr {
7292 AAPrivatizablePtrImpl(
const IRPosition &IRP, Attributor &
A)
7293 : AAPrivatizablePtr(IRP,
A), PrivatizableType(std::nullopt) {}
7296 AAPrivatizablePtr::indicatePessimisticFixpoint();
7297 PrivatizableType =
nullptr;
7298 return ChangeStatus::CHANGED;
7304 virtual std::optional<Type *> identifyPrivatizableType(Attributor &
A) = 0;
7308 std::optional<Type *> combineTypes(std::optional<Type *> T0,
7309 std::optional<Type *>
T1) {
7319 std::optional<Type *> getPrivatizableType()
const override {
7320 return PrivatizableType;
7323 const std::string getAsStr(Attributor *
A)
const override {
7324 return isAssumedPrivatizablePtr() ?
"[priv]" :
"[no-priv]";
7328 std::optional<Type *> PrivatizableType;
7333struct AAPrivatizablePtrArgument final :
public AAPrivatizablePtrImpl {
7334 AAPrivatizablePtrArgument(
const IRPosition &IRP, Attributor &
A)
7335 : AAPrivatizablePtrImpl(IRP,
A) {}
7338 std::optional<Type *> identifyPrivatizableType(Attributor &
A)
override {
7341 bool UsedAssumedInformation =
false;
7343 A.getAttrs(getIRPosition(), {Attribute::ByVal},
Attrs,
7345 if (!
Attrs.empty() &&
7346 A.checkForAllCallSites([](AbstractCallSite ACS) { return true; }, *
this,
7347 true, UsedAssumedInformation))
7348 return Attrs[0].getValueAsType();
7350 std::optional<Type *> Ty;
7351 unsigned ArgNo = getIRPosition().getCallSiteArgNo();
7359 auto CallSiteCheck = [&](AbstractCallSite ACS) {
7368 A.getAAFor<AAPrivatizablePtr>(*
this, ACSArgPos, DepClassTy::REQUIRED);
7371 std::optional<Type *> CSTy = PrivCSArgAA->getPrivatizableType();
7374 dbgs() <<
"[AAPrivatizablePtr] ACSPos: " << ACSArgPos <<
", CSTy: ";
7378 dbgs() <<
"<nullptr>";
7383 Ty = combineTypes(Ty, CSTy);
7386 dbgs() <<
" : New Type: ";
7388 (*Ty)->print(
dbgs());
7390 dbgs() <<
"<nullptr>";
7399 if (!
A.checkForAllCallSites(CallSiteCheck, *
this,
true,
7400 UsedAssumedInformation))
7407 PrivatizableType = identifyPrivatizableType(
A);
7408 if (!PrivatizableType)
7409 return ChangeStatus::UNCHANGED;
7410 if (!*PrivatizableType)
7411 return indicatePessimisticFixpoint();
7416 DepClassTy::OPTIONAL);
7419 if (!
A.hasAttr(getIRPosition(), Attribute::ByVal) &&
7422 return indicatePessimisticFixpoint();
7428 identifyReplacementTypes(*PrivatizableType, ReplacementTypes);
7432 Function &Fn = *getIRPosition().getAnchorScope();
7434 A.getInfoCache().getAnalysisResultForFunction<TargetIRAnalysis>(Fn);
7436 LLVM_DEBUG(
dbgs() <<
"[AAPrivatizablePtr] Missing TTI for function "
7438 return indicatePessimisticFixpoint();
7441 auto CallSiteCheck = [&](AbstractCallSite ACS) {
7448 bool UsedAssumedInformation =
false;
7449 if (!
A.checkForAllCallSites(CallSiteCheck, *
this,
true,
7450 UsedAssumedInformation)) {
7452 dbgs() <<
"[AAPrivatizablePtr] ABI incompatibility detected for "
7454 return indicatePessimisticFixpoint();
7458 Argument *Arg = getAssociatedArgument();
7459 if (!
A.isValidFunctionSignatureRewrite(*Arg, ReplacementTypes)) {
7461 return indicatePessimisticFixpoint();
7468 auto IsCompatiblePrivArgOfCallback = [&](CallBase &CB) {
7471 for (
const Use *U : CallbackUses) {
7472 AbstractCallSite CBACS(U);
7473 assert(CBACS && CBACS.isCallbackCall());
7474 for (Argument &CBArg : CBACS.getCalledFunction()->args()) {
7475 int CBArgNo = CBACS.getCallArgOperandNo(CBArg);
7479 <<
"[AAPrivatizablePtr] Argument " << *Arg
7480 <<
"check if can be privatized in the context of its parent ("
7482 <<
")\n[AAPrivatizablePtr] because it is an argument in a "
7484 << CBArgNo <<
"@" << CBACS.getCalledFunction()->getName()
7485 <<
")\n[AAPrivatizablePtr] " << CBArg <<
" : "
7486 << CBACS.getCallArgOperand(CBArg) <<
" vs "
7488 <<
"[AAPrivatizablePtr] " << CBArg <<
" : "
7489 << CBACS.getCallArgOperandNo(CBArg) <<
" vs " << ArgNo <<
"\n";
7492 if (CBArgNo !=
int(ArgNo))
7494 const auto *CBArgPrivAA =
A.getAAFor<AAPrivatizablePtr>(
7496 if (CBArgPrivAA && CBArgPrivAA->isValidState()) {
7497 auto CBArgPrivTy = CBArgPrivAA->getPrivatizableType();
7500 if (*CBArgPrivTy == PrivatizableType)
7505 dbgs() <<
"[AAPrivatizablePtr] Argument " << *Arg
7506 <<
" cannot be privatized in the context of its parent ("
7508 <<
")\n[AAPrivatizablePtr] because it is an argument in a "
7510 << CBArgNo <<
"@" << CBACS.getCalledFunction()->getName()
7511 <<
").\n[AAPrivatizablePtr] for which the argument "
7512 "privatization is not compatible.\n";
7522 auto IsCompatiblePrivArgOfDirectCS = [&](AbstractCallSite ACS) {
7526 "Expected a direct call operand for callback call operand");
7531 dbgs() <<
"[AAPrivatizablePtr] Argument " << *Arg
7532 <<
" check if be privatized in the context of its parent ("
7534 <<
")\n[AAPrivatizablePtr] because it is an argument in a "
7536 << DCArgNo <<
"@" << DCCallee->
getName() <<
").\n";
7539 if (
unsigned(DCArgNo) < DCCallee->
arg_size()) {
7540 const auto *DCArgPrivAA =
A.getAAFor<AAPrivatizablePtr>(
7542 DepClassTy::REQUIRED);
7543 if (DCArgPrivAA && DCArgPrivAA->isValidState()) {
7544 auto DCArgPrivTy = DCArgPrivAA->getPrivatizableType();
7547 if (*DCArgPrivTy == PrivatizableType)
7553 dbgs() <<
"[AAPrivatizablePtr] Argument " << *Arg
7554 <<
" cannot be privatized in the context of its parent ("
7556 <<
")\n[AAPrivatizablePtr] because it is an argument in a "
7559 <<
").\n[AAPrivatizablePtr] for which the argument "
7560 "privatization is not compatible.\n";
7568 auto IsCompatiblePrivArgOfOtherCallSite = [&](AbstractCallSite ACS) {
7572 return IsCompatiblePrivArgOfDirectCS(ACS);
7576 if (!
A.checkForAllCallSites(IsCompatiblePrivArgOfOtherCallSite, *
this,
true,
7577 UsedAssumedInformation))
7578 return indicatePessimisticFixpoint();
7580 return ChangeStatus::UNCHANGED;
7586 identifyReplacementTypes(
Type *PrivType,
7587 SmallVectorImpl<Type *> &ReplacementTypes) {
7590 assert(PrivType &&
"Expected privatizable type!");
7594 for (
unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++)
7595 ReplacementTypes.
push_back(PrivStructType->getElementType(u));
7597 ReplacementTypes.
append(PrivArrayType->getNumElements(),
7598 PrivArrayType->getElementType());
7607 static void createInitialization(
Type *PrivType,
Value &
Base, Function &
F,
7609 assert(PrivType &&
"Expected privatizable type!");
7612 const DataLayout &
DL =
F.getDataLayout();
7616 const StructLayout *PrivStructLayout =
DL.getStructLayout(PrivStructType);
7617 for (
unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++) {
7620 new StoreInst(
F.getArg(ArgNo + u), Ptr, IP);
7623 Type *PointeeTy = PrivArrayType->getElementType();
7624 uint64_t PointeeTySize =
DL.getTypeStoreSize(PointeeTy);
7625 for (
unsigned u = 0, e = PrivArrayType->getNumElements(); u < e; u++) {
7627 new StoreInst(
F.getArg(ArgNo + u), Ptr, IP);
7630 new StoreInst(
F.getArg(ArgNo), &
Base, IP);
7636 void createReplacementValues(Align Alignment,
Type *PrivType,
7638 SmallVectorImpl<Value *> &ReplacementValues) {
7640 assert(PrivType &&
"Expected privatizable type!");
7648 const StructLayout *PrivStructLayout =
DL.getStructLayout(PrivStructType);
7649 for (
unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++) {
7650 Type *PointeeTy = PrivStructType->getElementType(u);
7653 LoadInst *
L =
new LoadInst(PointeeTy, Ptr,
"", IP->
getIterator());
7654 L->setAlignment(Alignment);
7658 Type *PointeeTy = PrivArrayType->getElementType();
7659 uint64_t PointeeTySize =
DL.getTypeStoreSize(PointeeTy);
7660 for (
unsigned u = 0, e = PrivArrayType->getNumElements(); u < e; u++) {
7662 LoadInst *
L =
new LoadInst(PointeeTy, Ptr,
"", IP->
getIterator());
7663 L->setAlignment(Alignment);
7668 L->setAlignment(Alignment);
7675 if (!PrivatizableType)
7676 return ChangeStatus::UNCHANGED;
7677 assert(*PrivatizableType &&
"Expected privatizable type!");
7683 bool UsedAssumedInformation =
false;
7684 if (!
A.checkForAllInstructions(
7685 [&](Instruction &
I) {
7686 CallInst &CI = cast<CallInst>(I);
7687 if (CI.isTailCall())
7688 TailCalls.push_back(&CI);
7691 *
this, {Instruction::Call}, UsedAssumedInformation))
7692 return ChangeStatus::UNCHANGED;
7694 Argument *Arg = getAssociatedArgument();
7697 const auto *AlignAA =
7704 [=](
const Attributor::ArgumentReplacementInfo &ARI,
7706 BasicBlock &EntryBB = ReplacementFn.getEntryBlock();
7708 const DataLayout &
DL = IP->getDataLayout();
7709 unsigned AS =
DL.getAllocaAddrSpace();
7710 Instruction *AI =
new AllocaInst(*PrivatizableType, AS,
7711 Arg->
getName() +
".priv", IP);
7712 createInitialization(*PrivatizableType, *AI, ReplacementFn,
7713 ArgIt->getArgNo(), IP);
7716 AI = BitCastInst::CreatePointerBitCastOrAddrSpaceCast(
7720 for (CallInst *CI : TailCalls)
7721 CI->setTailCall(
false);
7728 [=](
const Attributor::ArgumentReplacementInfo &ARI,
7729 AbstractCallSite ACS, SmallVectorImpl<Value *> &NewArgOperands) {
7732 createReplacementValues(
7733 AlignAA ? AlignAA->getAssumedAlign() :
Align(0),
7734 *PrivatizableType, ACS,
7742 identifyReplacementTypes(*PrivatizableType, ReplacementTypes);
7745 if (
A.registerFunctionSignatureRewrite(*Arg, ReplacementTypes,
7746 std::move(FnRepairCB),
7747 std::move(ACSRepairCB)))
7748 return ChangeStatus::CHANGED;
7749 return ChangeStatus::UNCHANGED;
7753 void trackStatistics()
const override {
7758struct AAPrivatizablePtrFloating :
public AAPrivatizablePtrImpl {
7759 AAPrivatizablePtrFloating(
const IRPosition &IRP, Attributor &
A)
7760 : AAPrivatizablePtrImpl(IRP,
A) {}
7765 indicatePessimisticFixpoint();
7770 "updateImpl will not be called");
7774 std::optional<Type *> identifyPrivatizableType(Attributor &
A)
override {
7777 LLVM_DEBUG(
dbgs() <<
"[AAPrivatizablePtr] No underlying object found!\n");
7784 return AI->getAllocatedType();
7786 auto *PrivArgAA =
A.getAAFor<AAPrivatizablePtr>(
7788 if (PrivArgAA && PrivArgAA->isAssumedPrivatizablePtr())
7789 return PrivArgAA->getPrivatizableType();
7792 LLVM_DEBUG(
dbgs() <<
"[AAPrivatizablePtr] Underlying object neither valid "
7793 "alloca nor privatizable argument: "
7799 void trackStatistics()
const override {
7804struct AAPrivatizablePtrCallSiteArgument final
7805 :
public AAPrivatizablePtrFloating {
7806 AAPrivatizablePtrCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
7807 : AAPrivatizablePtrFloating(IRP,
A) {}
7811 if (
A.hasAttr(getIRPosition(), Attribute::ByVal))
7812 indicateOptimisticFixpoint();
7817 PrivatizableType = identifyPrivatizableType(
A);
7818 if (!PrivatizableType)
7819 return ChangeStatus::UNCHANGED;
7820 if (!*PrivatizableType)
7821 return indicatePessimisticFixpoint();
7823 const IRPosition &IRP = getIRPosition();
7824 bool IsKnownNoCapture;
7826 A,
this, IRP, DepClassTy::REQUIRED, IsKnownNoCapture);
7827 if (!IsAssumedNoCapture) {
7828 LLVM_DEBUG(
dbgs() <<
"[AAPrivatizablePtr] pointer might be captured!\n");
7829 return indicatePessimisticFixpoint();
7832 bool IsKnownNoAlias;
7834 A,
this, IRP, DepClassTy::REQUIRED, IsKnownNoAlias)) {
7835 LLVM_DEBUG(
dbgs() <<
"[AAPrivatizablePtr] pointer might alias!\n");
7836 return indicatePessimisticFixpoint();
7841 LLVM_DEBUG(
dbgs() <<
"[AAPrivatizablePtr] pointer is written!\n");
7842 return indicatePessimisticFixpoint();
7845 return ChangeStatus::UNCHANGED;
7849 void trackStatistics()
const override {
7854struct AAPrivatizablePtrCallSiteReturned final
7855 :
public AAPrivatizablePtrFloating {
7856 AAPrivatizablePtrCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
7857 : AAPrivatizablePtrFloating(IRP,
A) {}
7862 indicatePessimisticFixpoint();
7866 void trackStatistics()
const override {
7871struct AAPrivatizablePtrReturned final :
public AAPrivatizablePtrFloating {
7872 AAPrivatizablePtrReturned(
const IRPosition &IRP, Attributor &
A)
7873 : AAPrivatizablePtrFloating(IRP,
A) {}
7878 indicatePessimisticFixpoint();
7882 void trackStatistics()
const override {
7892struct AAMemoryBehaviorImpl :
public AAMemoryBehavior {
7893 AAMemoryBehaviorImpl(
const IRPosition &IRP, Attributor &
A)
7894 : AAMemoryBehavior(IRP,
A) {}
7898 intersectAssumedBits(BEST_STATE);
7899 getKnownStateFromValue(
A, getIRPosition(), getState());
7900 AAMemoryBehavior::initialize(
A);
7904 static void getKnownStateFromValue(Attributor &
A,
const IRPosition &IRP,
7905 BitIntegerState &State,
7906 bool IgnoreSubsumingPositions =
false) {
7908 A.getAttrs(IRP, AttrKinds, Attrs, IgnoreSubsumingPositions);
7910 switch (Attr.getKindAsEnum()) {
7911 case Attribute::ReadNone:
7914 case Attribute::ReadOnly:
7917 case Attribute::WriteOnly:
7926 if (!
I->mayReadFromMemory())
7928 if (!
I->mayWriteToMemory())
7934 void getDeducedAttributes(Attributor &
A, LLVMContext &Ctx,
7935 SmallVectorImpl<Attribute> &Attrs)
const override {
7938 Attrs.push_back(Attribute::get(Ctx, Attribute::ReadNone));
7940 Attrs.push_back(Attribute::get(Ctx, Attribute::ReadOnly));
7941 else if (isAssumedWriteOnly())
7942 Attrs.push_back(Attribute::get(Ctx, Attribute::WriteOnly));
7948 const IRPosition &IRP = getIRPosition();
7950 if (
A.hasAttr(IRP, Attribute::ReadNone,
7952 return ChangeStatus::UNCHANGED;
7961 return ChangeStatus::UNCHANGED;
7964 A.removeAttrs(IRP, AttrKinds);
7967 A.removeAttrs(IRP, Attribute::Writable);
7974 const std::string getAsStr(Attributor *
A)
const override {
7979 if (isAssumedWriteOnly())
7981 return "may-read/write";
7985 static const Attribute::AttrKind AttrKinds[3];
7989 Attribute::ReadNone, Attribute::ReadOnly, Attribute::WriteOnly};
7992struct AAMemoryBehaviorFloating : AAMemoryBehaviorImpl {
7993 AAMemoryBehaviorFloating(
const IRPosition &IRP, Attributor &
A)
7994 : AAMemoryBehaviorImpl(IRP,
A) {}
8000 void trackStatistics()
const override {
8005 else if (isAssumedWriteOnly())
8012 bool followUsersOfUseIn(Attributor &
A,
const Use &U,
8013 const Instruction *UserI);
8016 void analyzeUseIn(Attributor &
A,
const Use &U,
const Instruction *UserI);
8020struct AAMemoryBehaviorArgument : AAMemoryBehaviorFloating {
8021 AAMemoryBehaviorArgument(
const IRPosition &IRP, Attributor &
A)
8022 : AAMemoryBehaviorFloating(IRP,
A) {}
8026 intersectAssumedBits(BEST_STATE);
8027 const IRPosition &IRP = getIRPosition();
8031 bool HasByVal =
A.hasAttr(IRP, {Attribute::ByVal},
8033 getKnownStateFromValue(
A, IRP, getState(),
8040 return ChangeStatus::UNCHANGED;
8044 if (
A.hasAttr(getIRPosition(),
8045 {Attribute::InAlloca, Attribute::Preallocated})) {
8046 removeKnownBits(NO_WRITES);
8047 removeAssumedBits(NO_WRITES);
8049 A.removeAttrs(getIRPosition(), AttrKinds);
8050 return AAMemoryBehaviorFloating::manifest(
A);
8054 void trackStatistics()
const override {
8059 else if (isAssumedWriteOnly())
8064struct AAMemoryBehaviorCallSiteArgument final : AAMemoryBehaviorArgument {
8065 AAMemoryBehaviorCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
8066 : AAMemoryBehaviorArgument(IRP,
A) {}
8072 Argument *Arg = getAssociatedArgument();
8074 indicatePessimisticFixpoint();
8078 addKnownBits(NO_WRITES);
8079 removeKnownBits(NO_READS);
8080 removeAssumedBits(NO_READS);
8082 AAMemoryBehaviorArgument::initialize(
A);
8083 if (getAssociatedFunction()->isDeclaration())
8084 indicatePessimisticFixpoint();
8093 Argument *Arg = getAssociatedArgument();
8096 A.getAAFor<AAMemoryBehavior>(*
this, ArgPos, DepClassTy::REQUIRED);
8098 return indicatePessimisticFixpoint();
8103 void trackStatistics()
const override {
8108 else if (isAssumedWriteOnly())
8114struct AAMemoryBehaviorCallSiteReturned final : AAMemoryBehaviorFloating {
8115 AAMemoryBehaviorCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
8116 : AAMemoryBehaviorFloating(IRP,
A) {}
8120 AAMemoryBehaviorImpl::initialize(
A);
8125 return ChangeStatus::UNCHANGED;
8129 void trackStatistics()
const override {}
8133struct AAMemoryBehaviorFunction final :
public AAMemoryBehaviorImpl {
8134 AAMemoryBehaviorFunction(
const IRPosition &IRP, Attributor &
A)
8135 : AAMemoryBehaviorImpl(IRP,
A) {}
8151 else if (isAssumedWriteOnly())
8154 A.removeAttrs(getIRPosition(), AttrKinds);
8157 for (Argument &Arg :
F.args())
8159 return A.manifestAttrs(getIRPosition(),
8160 Attribute::getWithMemoryEffects(
F.getContext(), ME));
8164 void trackStatistics()
const override {
8169 else if (isAssumedWriteOnly())
8175struct AAMemoryBehaviorCallSite final
8176 : AACalleeToCallSite<AAMemoryBehavior, AAMemoryBehaviorImpl> {
8177 AAMemoryBehaviorCallSite(
const IRPosition &IRP, Attributor &
A)
8178 : AACalleeToCallSite<AAMemoryBehavior, AAMemoryBehaviorImpl>(IRP,
A) {}
8189 else if (isAssumedWriteOnly())
8192 A.removeAttrs(getIRPosition(), AttrKinds);
8195 for (Use &U : CB.
args())
8197 Attribute::Writable);
8198 return A.manifestAttrs(
8199 getIRPosition(), Attribute::getWithMemoryEffects(CB.
getContext(), ME));
8203 void trackStatistics()
const override {
8208 else if (isAssumedWriteOnly())
8213ChangeStatus AAMemoryBehaviorFunction::updateImpl(Attributor &
A) {
8216 auto AssumedState = getAssumed();
8223 const auto *MemBehaviorAA =
A.getAAFor<AAMemoryBehavior>(
8225 if (MemBehaviorAA) {
8226 intersectAssumedBits(MemBehaviorAA->
getAssumed());
8227 return !isAtFixpoint();
8232 if (
I.mayReadFromMemory())
8233 removeAssumedBits(NO_READS);
8234 if (
I.mayWriteToMemory())
8235 removeAssumedBits(NO_WRITES);
8236 return !isAtFixpoint();
8239 bool UsedAssumedInformation =
false;
8240 if (!
A.checkForAllReadWriteInstructions(CheckRWInst, *
this,
8241 UsedAssumedInformation))
8242 return indicatePessimisticFixpoint();
8248ChangeStatus AAMemoryBehaviorFloating::updateImpl(Attributor &
A) {
8250 const IRPosition &IRP = getIRPosition();
8261 const auto *FnMemAA =
8264 FnMemAssumedState = FnMemAA->getAssumed();
8265 S.addKnownBits(FnMemAA->getKnown());
8266 if ((S.getAssumed() & FnMemAA->getAssumed()) == S.getAssumed())
8272 auto AssumedState = S.getAssumed();
8278 bool IsKnownNoCapture;
8279 const AANoCapture *ArgNoCaptureAA =
nullptr;
8284 if (!IsAssumedNoCapture &&
8286 S.intersectAssumedBits(FnMemAssumedState);
8292 auto UsePred = [&](
const Use &
U,
bool &Follow) ->
bool {
8294 LLVM_DEBUG(
dbgs() <<
"[AAMemoryBehavior] Use: " << *U <<
" in " << *UserI
8302 Follow = followUsersOfUseIn(
A, U, UserI);
8306 analyzeUseIn(
A, U, UserI);
8308 return !isAtFixpoint();
8311 if (!
A.checkForAllUses(UsePred, *
this, getAssociatedValue()))
8312 return indicatePessimisticFixpoint();
8318bool AAMemoryBehaviorFloating::followUsersOfUseIn(Attributor &
A,
const Use &U,
8319 const Instruction *UserI) {
8337 if (
U.get()->getType()->isPointerTy()) {
8339 bool IsKnownNoCapture;
8348void AAMemoryBehaviorFloating::analyzeUseIn(Attributor &
A,
const Use &U,
8349 const Instruction *UserI) {
8356 case Instruction::Load:
8358 removeAssumedBits(NO_READS);
8361 case Instruction::Store:
8366 removeAssumedBits(NO_WRITES);
8368 indicatePessimisticFixpoint();
8371 case Instruction::Call:
8372 case Instruction::CallBr:
8373 case Instruction::Invoke: {
8380 indicatePessimisticFixpoint();
8387 removeAssumedBits(NO_READS);
8394 if (
U.get()->getType()->isPointerTy())
8398 const auto *MemBehaviorAA =
8404 intersectAssumedBits(MemBehaviorAA->
getAssumed());
8412 removeAssumedBits(NO_READS);
8414 removeAssumedBits(NO_WRITES);
8426 return "all memory";
8429 std::string S =
"memory:";
8435 S +=
"internal global,";
8437 S +=
"external global,";
8441 S +=
"inaccessible,";
8455 AccessKind2Accesses.fill(
nullptr);
8458 ~AAMemoryLocationImpl()
override {
8461 for (AccessSet *AS : AccessKind2Accesses)
8468 intersectAssumedBits(BEST_STATE);
8469 getKnownStateFromValue(
A, getIRPosition(), getState());
8470 AAMemoryLocation::initialize(
A);
8474 static void getKnownStateFromValue(Attributor &
A,
const IRPosition &IRP,
8475 BitIntegerState &State,
8476 bool IgnoreSubsumingPositions =
false) {
8485 bool UseArgMemOnly =
true;
8487 if (AnchorFn &&
A.isRunOn(*AnchorFn))
8491 A.getAttrs(IRP, {Attribute::Memory},
Attrs, IgnoreSubsumingPositions);
8500 State.
addKnownBits(inverseLocation(NO_INACCESSIBLE_MEM,
true,
true));
8505 State.
addKnownBits(inverseLocation(NO_ARGUMENT_MEM,
true,
true));
8509 A.manifestAttrs(IRP,
8510 Attribute::getWithMemoryEffects(
8519 NO_INACCESSIBLE_MEM | NO_ARGUMENT_MEM,
true,
true));
8523 A.manifestAttrs(IRP,
8524 Attribute::getWithMemoryEffects(
8534 void getDeducedAttributes(Attributor &
A, LLVMContext &Ctx,
8535 SmallVectorImpl<Attribute> &Attrs)
const override {
8542 else if (isAssumedInaccessibleMemOnly())
8543 Attrs.push_back(Attribute::getWithMemoryEffects(
8545 else if (isAssumedArgMemOnly())
8548 else if (isAssumedInaccessibleOrArgMemOnly())
8549 Attrs.push_back(Attribute::getWithMemoryEffects(
8559 const IRPosition &IRP = getIRPosition();
8563 if (DeducedAttrs.
size() != 1)
8564 return ChangeStatus::UNCHANGED;
8567 return A.manifestAttrs(IRP, Attribute::getWithMemoryEffects(
8572 bool checkForAllAccessesToMemoryKind(
8574 MemoryLocationsKind)>
8576 MemoryLocationsKind RequestedMLK)
const override {
8577 if (!isValidState())
8580 MemoryLocationsKind AssumedMLK = getAssumedNotAccessedLocation();
8581 if (AssumedMLK == NO_LOCATIONS)
8585 for (MemoryLocationsKind CurMLK = 1; CurMLK < NO_LOCATIONS;
8586 CurMLK *= 2, ++Idx) {
8587 if (CurMLK & RequestedMLK)
8590 if (
const AccessSet *
Accesses = AccessKind2Accesses[Idx])
8591 for (
const AccessInfo &AI : *
Accesses)
8592 if (!Pred(AI.I, AI.Ptr, AI.Kind, CurMLK))
8605 MemoryLocationsKind KnownMLK = getKnown();
8607 for (MemoryLocationsKind CurMLK = 1; CurMLK < NO_LOCATIONS; CurMLK *= 2)
8608 if (!(CurMLK & KnownMLK))
8609 updateStateAndAccessesMap(getState(), CurMLK,
I,
nullptr,
Changed,
8610 getAccessKindFromInst(
I));
8611 return AAMemoryLocation::indicatePessimisticFixpoint();
8631 bool operator()(
const AccessInfo &
LHS,
const AccessInfo &
RHS)
const {
8635 return LHS.Ptr <
RHS.Ptr;
8636 if (
LHS.Kind !=
RHS.Kind)
8637 return LHS.Kind <
RHS.Kind;
8644 using AccessSet = SmallSet<AccessInfo, 2, AccessInfo>;
8645 std::array<AccessSet *, llvm::ConstantLog2<VALID_STATE>()>
8646 AccessKind2Accesses;
8651 categorizeArgumentPointerLocations(Attributor &
A, CallBase &CB,
8652 AAMemoryLocation::StateType &AccessedLocs,
8657 categorizeAccessedLocations(Attributor &
A, Instruction &
I,
bool &
Changed);
8660 AccessKind getAccessKindFromInst(
const Instruction *
I) {
8663 AK =
I->mayReadFromMemory() ? READ :
NONE;
8672 void updateStateAndAccessesMap(AAMemoryLocation::StateType &State,
8673 MemoryLocationsKind MLK,
const Instruction *
I,
8682 if (MLK == NO_UNKOWN_MEM)
8684 State.removeAssumedBits(MLK);
8689 void categorizePtrValue(Attributor &
A,
const Instruction &
I,
const Value &Ptr,
8690 AAMemoryLocation::StateType &State,
bool &
Changed,
8691 unsigned AccessAS = 0);
8697void AAMemoryLocationImpl::categorizePtrValue(
8698 Attributor &
A,
const Instruction &
I,
const Value &Ptr,
8700 LLVM_DEBUG(
dbgs() <<
"[AAMemoryLocation] Categorize pointer locations for "
8705 unsigned ObjectAS =
Obj.getType()->getPointerAddressSpace();
8707 MemoryLocationsKind MLK = NO_LOCATIONS;
8726 MLK = NO_ARGUMENT_MEM;
8732 if (GVar->isConstant())
8735 if (GV->hasLocalLinkage())
8736 MLK = NO_GLOBAL_INTERNAL_MEM;
8738 MLK = NO_GLOBAL_EXTERNAL_MEM;
8746 bool IsKnownNoAlias;
8750 MLK = NO_MALLOCED_MEM;
8752 MLK = NO_UNKOWN_MEM;
8754 MLK = NO_UNKOWN_MEM;
8757 assert(MLK != NO_LOCATIONS &&
"No location specified!");
8758 LLVM_DEBUG(
dbgs() <<
"[AAMemoryLocation] Ptr value can be categorized: "
8759 << Obj <<
" -> " << getMemoryLocationsAsStr(MLK) <<
"\n");
8761 getAccessKindFromInst(&
I));
8766 const auto *AA =
A.getAAFor<AAUnderlyingObjects>(
8770 dbgs() <<
"[AAMemoryLocation] Pointer locations not categorized\n");
8771 updateStateAndAccessesMap(
State, NO_UNKOWN_MEM, &
I,
nullptr,
Changed,
8772 getAccessKindFromInst(&
I));
8777 dbgs() <<
"[AAMemoryLocation] Accessed locations with pointer locations: "
8781void AAMemoryLocationImpl::categorizeArgumentPointerLocations(
8784 for (
unsigned ArgNo = 0,
E = CB.
arg_size(); ArgNo <
E; ++ArgNo) {
8793 const auto *ArgOpMemLocationAA =
8796 if (ArgOpMemLocationAA && ArgOpMemLocationAA->isAssumedReadNone())
8801 categorizePtrValue(
A, CB, *ArgOp, AccessedLocs,
Changed);
8806AAMemoryLocationImpl::categorizeAccessedLocations(Attributor &
A, Instruction &
I,
8808 LLVM_DEBUG(
dbgs() <<
"[AAMemoryLocation] Categorize accessed locations for "
8812 AccessedLocs.intersectAssumedBits(NO_LOCATIONS);
8817 const auto *CBMemLocationAA =
A.getAAFor<AAMemoryLocation>(
8820 <<
" [" << CBMemLocationAA <<
"]\n");
8821 if (!CBMemLocationAA) {
8822 updateStateAndAccessesMap(AccessedLocs, NO_UNKOWN_MEM, &
I,
nullptr,
8823 Changed, getAccessKindFromInst(&
I));
8824 return NO_UNKOWN_MEM;
8827 if (CBMemLocationAA->isAssumedReadNone())
8828 return NO_LOCATIONS;
8830 if (CBMemLocationAA->isAssumedInaccessibleMemOnly()) {
8831 updateStateAndAccessesMap(AccessedLocs, NO_INACCESSIBLE_MEM, &
I,
nullptr,
8832 Changed, getAccessKindFromInst(&
I));
8833 return AccessedLocs.getAssumed();
8836 uint32_t CBAssumedNotAccessedLocs =
8837 CBMemLocationAA->getAssumedNotAccessedLocation();
8840 uint32_t CBAssumedNotAccessedLocsNoArgMem =
8841 CBAssumedNotAccessedLocs | NO_ARGUMENT_MEM | NO_GLOBAL_MEM;
8843 for (MemoryLocationsKind CurMLK = 1; CurMLK < NO_LOCATIONS; CurMLK *= 2) {
8844 if (CBAssumedNotAccessedLocsNoArgMem & CurMLK)
8846 updateStateAndAccessesMap(AccessedLocs, CurMLK, &
I,
nullptr,
Changed,
8847 getAccessKindFromInst(&
I));
8852 bool HasGlobalAccesses = ((~CBAssumedNotAccessedLocs) & NO_GLOBAL_MEM);
8853 if (HasGlobalAccesses) {
8856 updateStateAndAccessesMap(AccessedLocs, MLK, &
I, Ptr,
Changed,
8857 getAccessKindFromInst(&
I));
8860 if (!CBMemLocationAA->checkForAllAccessesToMemoryKind(
8861 AccessPred, inverseLocation(NO_GLOBAL_MEM,
false,
false)))
8862 return AccessedLocs.getWorstState();
8866 dbgs() <<
"[AAMemoryLocation] Accessed state before argument handling: "
8867 << getMemoryLocationsAsStr(AccessedLocs.getAssumed()) <<
"\n");
8870 bool HasArgAccesses = ((~CBAssumedNotAccessedLocs) & NO_ARGUMENT_MEM);
8872 categorizeArgumentPointerLocations(
A, *CB, AccessedLocs,
Changed);
8875 dbgs() <<
"[AAMemoryLocation] Accessed state after argument handling: "
8876 << getMemoryLocationsAsStr(AccessedLocs.getAssumed()) <<
"\n");
8878 return AccessedLocs.getAssumed();
8883 dbgs() <<
"[AAMemoryLocation] Categorize memory access with pointer: "
8884 <<
I <<
" [" << *Ptr <<
"]\n");
8885 categorizePtrValue(
A,
I, *Ptr, AccessedLocs,
Changed,
8886 Ptr->getType()->getPointerAddressSpace());
8887 return AccessedLocs.getAssumed();
8890 LLVM_DEBUG(
dbgs() <<
"[AAMemoryLocation] Failed to categorize instruction: "
8892 updateStateAndAccessesMap(AccessedLocs, NO_UNKOWN_MEM, &
I,
nullptr,
Changed,
8893 getAccessKindFromInst(&
I));
8894 return AccessedLocs.getAssumed();
8898struct AAMemoryLocationFunction final :
public AAMemoryLocationImpl {
8899 AAMemoryLocationFunction(
const IRPosition &IRP, Attributor &
A)
8900 : AAMemoryLocationImpl(IRP,
A) {}
8905 const auto *MemBehaviorAA =
8906 A.getAAFor<AAMemoryBehavior>(*
this, getIRPosition(), DepClassTy::NONE);
8909 return indicateOptimisticFixpoint();
8911 "AAMemoryLocation was not read-none but AAMemoryBehavior was!");
8912 A.recordDependence(*MemBehaviorAA, *
this, DepClassTy::OPTIONAL);
8913 return ChangeStatus::UNCHANGED;
8917 auto AssumedState = getAssumed();
8921 MemoryLocationsKind MLK = categorizeAccessedLocations(
A,
I,
Changed);
8922 LLVM_DEBUG(
dbgs() <<
"[AAMemoryLocation] Accessed locations for " <<
I
8923 <<
": " << getMemoryLocationsAsStr(MLK) <<
"\n");
8924 removeAssumedBits(inverseLocation(MLK,
false,
false));
8927 return getAssumedNotAccessedLocation() != VALID_STATE;
8930 bool UsedAssumedInformation =
false;
8931 if (!
A.checkForAllReadWriteInstructions(CheckRWInst, *
this,
8932 UsedAssumedInformation))
8933 return indicatePessimisticFixpoint();
8935 Changed |= AssumedState != getAssumed();
8936 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
8940 void trackStatistics()
const override {
8943 else if (isAssumedArgMemOnly())
8945 else if (isAssumedInaccessibleMemOnly())
8947 else if (isAssumedInaccessibleOrArgMemOnly())
8953struct AAMemoryLocationCallSite final : AAMemoryLocationImpl {
8954 AAMemoryLocationCallSite(
const IRPosition &IRP, Attributor &
A)
8955 : AAMemoryLocationImpl(IRP,
A) {}
8966 A.getAAFor<AAMemoryLocation>(*
this, FnPos, DepClassTy::REQUIRED);
8968 return indicatePessimisticFixpoint();
8972 updateStateAndAccessesMap(getState(), MLK,
I, Ptr,
Changed,
8973 getAccessKindFromInst(
I));
8976 if (!FnAA->checkForAllAccessesToMemoryKind(AccessPred, ALL_LOCATIONS))
8977 return indicatePessimisticFixpoint();
8978 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
8982 void trackStatistics()
const override {
8992struct AADenormalFPMathImpl :
public AADenormalFPMath {
8993 AADenormalFPMathImpl(
const IRPosition &IRP, Attributor &
A)
8994 : AADenormalFPMath(IRP,
A) {}
8996 const std::string getAsStr(Attributor *
A)
const override {
8997 std::string Str(
"AADenormalFPMath[");
8998 raw_string_ostream OS(Str);
9000 DenormalState Known = getKnown();
9001 if (Known.Mode.isValid())
9002 OS <<
"denormal-fp-math=" << Known.Mode;
9006 if (Known.ModeF32.isValid())
9007 OS <<
" denormal-fp-math-f32=" << Known.ModeF32;
9013struct AADenormalFPMathFunction final : AADenormalFPMathImpl {
9014 AADenormalFPMathFunction(
const IRPosition &IRP, Attributor &
A)
9015 : AADenormalFPMathImpl(IRP,
A) {}
9019 DenormalFPEnv DenormEnv =
F->getDenormalFPEnv();
9029 auto CheckCallSite = [=, &Change, &
A](AbstractCallSite CS) {
9032 <<
"->" << getAssociatedFunction()->
getName() <<
'\n');
9034 const auto *CallerInfo =
A.getAAFor<AADenormalFPMath>(
9040 CallerInfo->getState());
9044 bool AllCallSitesKnown =
true;
9045 if (!
A.checkForAllCallSites(CheckCallSite, *
this,
true, AllCallSitesKnown))
9046 return indicatePessimisticFixpoint();
9048 if (Change == ChangeStatus::CHANGED && isModeFixed())
9054 LLVMContext &Ctx = getAssociatedFunction()->getContext();
9060 DenormalFPEnv KnownEnv(Known.Mode, Known.ModeF32);
9063 AttrToRemove.
push_back(Attribute::DenormalFPEnv);
9066 Ctx, Attribute::DenormalFPEnv,
9067 DenormalFPEnv(Known.Mode, Known.ModeF32).toIntValue()));
9070 auto &IRP = getIRPosition();
9073 return A.removeAttrs(IRP, AttrToRemove) |
9074 A.manifestAttrs(IRP, AttrToAdd,
true);
9077 void trackStatistics()
const override {
9086struct AAValueConstantRangeImpl : AAValueConstantRange {
9087 using StateType = IntegerRangeState;
9088 AAValueConstantRangeImpl(
const IRPosition &IRP, Attributor &
A)
9089 : AAValueConstantRange(IRP,
A) {}
9093 if (
A.hasSimplificationCallback(getIRPosition())) {
9094 indicatePessimisticFixpoint();
9099 intersectKnown(getConstantRangeFromSCEV(
A, getCtxI()));
9102 intersectKnown(getConstantRangeFromLVI(
A, getCtxI()));
9106 const std::string getAsStr(Attributor *
A)
const override {
9108 llvm::raw_string_ostream OS(Str);
9110 getKnown().print(OS);
9112 getAssumed().print(OS);
9119 const SCEV *getSCEV(Attributor &
A,
const Instruction *
I =
nullptr)
const {
9120 if (!getAnchorScope())
9123 ScalarEvolution *SE =
9124 A.getInfoCache().getAnalysisResultForFunction<ScalarEvolutionAnalysis>(
9127 LoopInfo *LI =
A.getInfoCache().getAnalysisResultForFunction<LoopAnalysis>(
9133 const SCEV *S = SE->
getSCEV(&getAssociatedValue());
9142 ConstantRange getConstantRangeFromSCEV(Attributor &
A,
9143 const Instruction *
I =
nullptr)
const {
9144 if (!getAnchorScope())
9147 ScalarEvolution *SE =
9148 A.getInfoCache().getAnalysisResultForFunction<ScalarEvolutionAnalysis>(
9151 const SCEV *S = getSCEV(
A,
I);
9161 getConstantRangeFromLVI(Attributor &
A,
9162 const Instruction *CtxI =
nullptr)
const {
9163 if (!getAnchorScope())
9166 LazyValueInfo *LVI =
9167 A.getInfoCache().getAnalysisResultForFunction<LazyValueAnalysis>(
9182 bool isValidCtxInstructionForOutsideAnalysis(Attributor &
A,
9183 const Instruction *CtxI,
9184 bool AllowAACtxI)
const {
9185 if (!CtxI || (!AllowAACtxI && CtxI == getCtxI()))
9197 InformationCache &InfoCache =
A.getInfoCache();
9198 const DominatorTree *DT =
9209 getKnownConstantRange(Attributor &
A,
9210 const Instruction *CtxI =
nullptr)
const override {
9211 if (!isValidCtxInstructionForOutsideAnalysis(
A, CtxI,
9215 ConstantRange LVIR = getConstantRangeFromLVI(
A, CtxI);
9216 ConstantRange SCEVR = getConstantRangeFromSCEV(
A, CtxI);
9217 return getKnown().intersectWith(SCEVR).intersectWith(LVIR);
9222 getAssumedConstantRange(Attributor &
A,
9223 const Instruction *CtxI =
nullptr)
const override {
9228 if (!isValidCtxInstructionForOutsideAnalysis(
A, CtxI,
9230 return getAssumed();
9232 ConstantRange LVIR = getConstantRangeFromLVI(
A, CtxI);
9233 ConstantRange SCEVR = getConstantRangeFromSCEV(
A, CtxI);
9234 return getAssumed().intersectWith(SCEVR).intersectWith(LVIR);
9239 getMDNodeForConstantRange(
Type *Ty, LLVMContext &Ctx,
9240 const ConstantRange &AssumedConstantRange) {
9242 Ty, AssumedConstantRange.
getLower())),
9244 Ty, AssumedConstantRange.
getUpper()))};
9249 static bool isBetterRange(
const ConstantRange &Assumed,
9250 const Instruction &
I) {
9254 std::optional<ConstantRange> Known;
9258 }
else if (MDNode *KnownRanges =
I.getMetadata(LLVMContext::MD_range)) {
9264 if (KnownRanges->getNumOperands() > 2)
9267 ConstantInt *
Lower =
9269 ConstantInt *
Upper =
9272 Known.emplace(
Lower->getValue(),
Upper->getValue());
9274 return !Known || (*Known != Assumed && Known->contains(Assumed));
9279 setRangeMetadataIfisBetterRange(Instruction *
I,
9280 const ConstantRange &AssumedConstantRange) {
9281 if (isBetterRange(AssumedConstantRange, *
I)) {
9282 I->setMetadata(LLVMContext::MD_range,
9283 getMDNodeForConstantRange(
I->getType(),
I->getContext(),
9284 AssumedConstantRange));
9291 setRangeRetAttrIfisBetterRange(Attributor &
A,
const IRPosition &IRP,
9293 const ConstantRange &AssumedConstantRange) {
9294 if (isBetterRange(AssumedConstantRange, *
I)) {
9295 A.manifestAttrs(IRP,
9296 Attribute::get(
I->getContext(), Attribute::Range,
9297 AssumedConstantRange),
9307 ConstantRange AssumedConstantRange = getAssumedConstantRange(
A);
9310 auto &
V = getAssociatedValue();
9314 assert(
I == getCtxI() &&
"Should not annotate an instruction which is "
9315 "not the context instruction");
9317 if (setRangeMetadataIfisBetterRange(
I, AssumedConstantRange))
9318 Changed = ChangeStatus::CHANGED;
9320 if (setRangeRetAttrIfisBetterRange(
A, getIRPosition(),
I,
9321 AssumedConstantRange))
9322 Changed = ChangeStatus::CHANGED;
9330struct AAValueConstantRangeArgument final
9331 : AAArgumentFromCallSiteArguments<
9332 AAValueConstantRange, AAValueConstantRangeImpl, IntegerRangeState,
9334 using Base = AAArgumentFromCallSiteArguments<
9335 AAValueConstantRange, AAValueConstantRangeImpl, IntegerRangeState,
9337 AAValueConstantRangeArgument(
const IRPosition &IRP, Attributor &
A)
9341 void trackStatistics()
const override {
9346struct AAValueConstantRangeReturned
9347 : AAReturnedFromReturnedValues<AAValueConstantRange,
9348 AAValueConstantRangeImpl,
9349 AAValueConstantRangeImpl::StateType,
9352 AAReturnedFromReturnedValues<AAValueConstantRange,
9353 AAValueConstantRangeImpl,
9354 AAValueConstantRangeImpl::StateType,
9356 AAValueConstantRangeReturned(
const IRPosition &IRP, Attributor &
A)
9361 if (!
A.isFunctionIPOAmendable(*getAssociatedFunction()))
9362 indicatePessimisticFixpoint();
9366 void trackStatistics()
const override {
9371struct AAValueConstantRangeFloating : AAValueConstantRangeImpl {
9372 AAValueConstantRangeFloating(
const IRPosition &IRP, Attributor &
A)
9373 : AAValueConstantRangeImpl(IRP,
A) {}
9377 AAValueConstantRangeImpl::initialize(
A);
9381 Value &
V = getAssociatedValue();
9384 unionAssumed(ConstantRange(
C->getValue()));
9385 indicateOptimisticFixpoint();
9391 unionAssumed(ConstantRange(APInt(
getBitWidth(), 0)));
9392 indicateOptimisticFixpoint();
9404 if (
auto *RangeMD = LI->getMetadata(LLVMContext::MD_range)) {
9415 indicatePessimisticFixpoint();
9418 << getAssociatedValue() <<
"\n");
9421 bool calculateBinaryOperator(
9422 Attributor &
A, BinaryOperator *BinOp, IntegerRangeState &
T,
9423 const Instruction *CtxI,
9424 SmallVectorImpl<const AAValueConstantRange *> &QuerriedAAs) {
9429 bool UsedAssumedInformation =
false;
9430 const auto &SimplifiedLHS =
A.getAssumedSimplified(
9433 if (!SimplifiedLHS.has_value())
9435 if (!*SimplifiedLHS)
9437 LHS = *SimplifiedLHS;
9439 const auto &SimplifiedRHS =
A.getAssumedSimplified(
9442 if (!SimplifiedRHS.has_value())
9444 if (!*SimplifiedRHS)
9446 RHS = *SimplifiedRHS;
9452 auto *LHSAA =
A.getAAFor<AAValueConstantRange>(
9454 DepClassTy::REQUIRED);
9458 auto LHSAARange = LHSAA->getAssumedConstantRange(
A, CtxI);
9460 auto *RHSAA =
A.getAAFor<AAValueConstantRange>(
9462 DepClassTy::REQUIRED);
9466 auto RHSAARange = RHSAA->getAssumedConstantRange(
A, CtxI);
9468 auto AssumedRange = LHSAARange.binaryOp(BinOp->
getOpcode(), RHSAARange);
9470 T.unionAssumed(AssumedRange);
9474 return T.isValidState();
9477 bool calculateCastInst(
9478 Attributor &
A, CastInst *CastI, IntegerRangeState &
T,
9479 const Instruction *CtxI,
9480 SmallVectorImpl<const AAValueConstantRange *> &QuerriedAAs) {
9486 bool UsedAssumedInformation =
false;
9487 const auto &SimplifiedOpV =
A.getAssumedSimplified(
9490 if (!SimplifiedOpV.has_value())
9492 if (!*SimplifiedOpV)
9494 OpV = *SimplifiedOpV;
9499 auto *OpAA =
A.getAAFor<AAValueConstantRange>(
9501 DepClassTy::REQUIRED);
9505 T.unionAssumed(OpAA->getAssumed().castOp(CastI->
getOpcode(),
9507 return T.isValidState();
9511 calculateCmpInst(Attributor &
A, CmpInst *CmpI, IntegerRangeState &
T,
9512 const Instruction *CtxI,
9513 SmallVectorImpl<const AAValueConstantRange *> &QuerriedAAs) {
9518 bool UsedAssumedInformation =
false;
9519 const auto &SimplifiedLHS =
A.getAssumedSimplified(
9522 if (!SimplifiedLHS.has_value())
9524 if (!*SimplifiedLHS)
9526 LHS = *SimplifiedLHS;
9528 const auto &SimplifiedRHS =
A.getAssumedSimplified(
9531 if (!SimplifiedRHS.has_value())
9533 if (!*SimplifiedRHS)
9535 RHS = *SimplifiedRHS;
9541 auto *LHSAA =
A.getAAFor<AAValueConstantRange>(
9543 DepClassTy::REQUIRED);
9547 auto *RHSAA =
A.getAAFor<AAValueConstantRange>(
9549 DepClassTy::REQUIRED);
9553 auto LHSAARange = LHSAA->getAssumedConstantRange(
A, CtxI);
9554 auto RHSAARange = RHSAA->getAssumedConstantRange(
A, CtxI);
9557 if (LHSAARange.isEmptySet() || RHSAARange.isEmptySet())
9560 bool MustTrue =
false, MustFalse =
false;
9562 auto AllowedRegion =
9565 if (AllowedRegion.intersectWith(LHSAARange).isEmptySet())
9571 assert((!MustTrue || !MustFalse) &&
9572 "Either MustTrue or MustFalse should be false!");
9575 T.unionAssumed(ConstantRange(APInt( 1, 1)));
9577 T.unionAssumed(ConstantRange(APInt( 1, 0)));
9579 T.unionAssumed(ConstantRange( 1,
true));
9581 LLVM_DEBUG(
dbgs() <<
"[AAValueConstantRange] " << *CmpI <<
" after "
9582 << (MustTrue ?
"true" : (MustFalse ?
"false" :
"unknown"))
9583 <<
": " <<
T <<
"\n\t" << *LHSAA <<
"\t<op>\n\t"
9587 return T.isValidState();
9599 bool UsedAssumedInformation =
false;
9600 const auto &SimplifiedOpV =
A.getAssumedSimplified(
9603 if (!SimplifiedOpV.has_value())
9605 if (!*SimplifiedOpV)
9607 Value *VPtr = *SimplifiedOpV;
9610 const auto *AA =
A.getAAFor<AAValueConstantRange>(
9612 DepClassTy::REQUIRED);
9616 T.unionAssumed(AA->getAssumedConstantRange(
A, CtxI));
9620 return T.isValidState();
9625 if (!calculateBinaryOperator(
A, BinOp,
T, CtxI, QuerriedAAs))
9628 if (!calculateCmpInst(
A, CmpI,
T, CtxI, QuerriedAAs))
9631 if (!calculateCastInst(
A, CastI,
T, CtxI, QuerriedAAs))
9637 T.indicatePessimisticFixpoint();
9644 for (
const AAValueConstantRange *QueriedAA : QuerriedAAs) {
9645 if (QueriedAA !=
this)
9648 if (
T.getAssumed() == getState().getAssumed())
9650 T.indicatePessimisticFixpoint();
9653 return T.isValidState();
9656 if (!VisitValueCB(getAssociatedValue(), getCtxI()))
9657 return indicatePessimisticFixpoint();
9662 return ChangeStatus::UNCHANGED;
9663 if (++NumChanges > MaxNumChanges) {
9664 LLVM_DEBUG(
dbgs() <<
"[AAValueConstantRange] performed " << NumChanges
9665 <<
" but only " << MaxNumChanges
9666 <<
" are allowed to avoid cyclic reasoning.");
9667 return indicatePessimisticFixpoint();
9669 return ChangeStatus::CHANGED;
9673 void trackStatistics()
const override {
9682 static constexpr int MaxNumChanges = 5;
9685struct AAValueConstantRangeFunction : AAValueConstantRangeImpl {
9686 AAValueConstantRangeFunction(
const IRPosition &IRP, Attributor &
A)
9687 : AAValueConstantRangeImpl(IRP,
A) {}
9691 llvm_unreachable(
"AAValueConstantRange(Function|CallSite)::updateImpl will "
9699struct AAValueConstantRangeCallSite : AAValueConstantRangeFunction {
9700 AAValueConstantRangeCallSite(
const IRPosition &IRP, Attributor &
A)
9701 : AAValueConstantRangeFunction(IRP,
A) {}
9707struct AAValueConstantRangeCallSiteReturned
9708 : AACalleeToCallSite<AAValueConstantRange, AAValueConstantRangeImpl,
9709 AAValueConstantRangeImpl::StateType,
9711 AAValueConstantRangeCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
9712 : AACalleeToCallSite<AAValueConstantRange, AAValueConstantRangeImpl,
9713 AAValueConstantRangeImpl::StateType,
9720 if (std::optional<ConstantRange>
Range = CI->getRange())
9721 intersectKnown(*
Range);
9724 AAValueConstantRangeImpl::initialize(
A);
9728 void trackStatistics()
const override {
9732struct AAValueConstantRangeCallSiteArgument : AAValueConstantRangeFloating {
9733 AAValueConstantRangeCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
9734 : AAValueConstantRangeFloating(IRP,
A) {}
9738 return ChangeStatus::UNCHANGED;
9742 void trackStatistics()
const override {
9751struct AAPotentialConstantValuesImpl : AAPotentialConstantValues {
9754 AAPotentialConstantValuesImpl(
const IRPosition &IRP, Attributor &
A)
9755 : AAPotentialConstantValues(IRP,
A) {}
9759 if (
A.hasSimplificationCallback(getIRPosition()))
9760 indicatePessimisticFixpoint();
9762 AAPotentialConstantValues::initialize(
A);
9765 bool fillSetWithConstantValues(Attributor &
A,
const IRPosition &IRP, SetTy &S,
9766 bool &ContainsUndef,
bool ForSelf) {
9768 bool UsedAssumedInformation =
false;
9770 UsedAssumedInformation)) {
9777 auto *PotentialValuesAA =
A.getAAFor<AAPotentialConstantValues>(
9778 *
this, IRP, DepClassTy::REQUIRED);
9779 if (!PotentialValuesAA || !PotentialValuesAA->getState().isValidState())
9781 ContainsUndef = PotentialValuesAA->getState().undefIsContained();
9782 S = PotentialValuesAA->getState().getAssumedSet();
9789 ContainsUndef =
false;
9790 for (
auto &It : Values) {
9792 ContainsUndef =
true;
9798 S.insert(CI->getValue());
9800 ContainsUndef &= S.empty();
9806 const std::string getAsStr(Attributor *
A)
const override {
9808 llvm::raw_string_ostream OS(Str);
9815 return indicatePessimisticFixpoint();
9819struct AAPotentialConstantValuesArgument final
9820 : AAArgumentFromCallSiteArguments<AAPotentialConstantValues,
9821 AAPotentialConstantValuesImpl,
9822 PotentialConstantIntValuesState> {
9823 using Base = AAArgumentFromCallSiteArguments<AAPotentialConstantValues,
9824 AAPotentialConstantValuesImpl,
9826 AAPotentialConstantValuesArgument(
const IRPosition &IRP, Attributor &
A)
9830 void trackStatistics()
const override {
9835struct AAPotentialConstantValuesReturned
9836 : AAReturnedFromReturnedValues<AAPotentialConstantValues,
9837 AAPotentialConstantValuesImpl> {
9838 using Base = AAReturnedFromReturnedValues<AAPotentialConstantValues,
9839 AAPotentialConstantValuesImpl>;
9840 AAPotentialConstantValuesReturned(
const IRPosition &IRP, Attributor &
A)
9844 if (!
A.isFunctionIPOAmendable(*getAssociatedFunction()))
9845 indicatePessimisticFixpoint();
9846 Base::initialize(
A);
9850 void trackStatistics()
const override {
9855struct AAPotentialConstantValuesFloating : AAPotentialConstantValuesImpl {
9856 AAPotentialConstantValuesFloating(
const IRPosition &IRP, Attributor &
A)
9857 : AAPotentialConstantValuesImpl(IRP,
A) {}
9861 AAPotentialConstantValuesImpl::initialize(
A);
9865 Value &
V = getAssociatedValue();
9868 unionAssumed(
C->getValue());
9869 indicateOptimisticFixpoint();
9874 unionAssumedWithUndef();
9875 indicateOptimisticFixpoint();
9885 indicatePessimisticFixpoint();
9888 << getAssociatedValue() <<
"\n");
9891 static bool calculateICmpInst(
const ICmpInst *ICI,
const APInt &
LHS,
9896 static APInt calculateCastInst(
const CastInst *CI,
const APInt &Src,
9897 uint32_t ResultBitWidth) {
9902 case Instruction::Trunc:
9903 return Src.trunc(ResultBitWidth);
9904 case Instruction::SExt:
9905 return Src.sext(ResultBitWidth);
9906 case Instruction::ZExt:
9907 return Src.zext(ResultBitWidth);
9908 case Instruction::BitCast:
9913 static APInt calculateBinaryOperator(
const BinaryOperator *BinOp,
9914 const APInt &
LHS,
const APInt &
RHS,
9915 bool &SkipOperation,
bool &Unsupported) {
9922 switch (BinOpcode) {
9926 case Instruction::Add:
9928 case Instruction::Sub:
9930 case Instruction::Mul:
9932 case Instruction::UDiv:
9934 SkipOperation =
true;
9938 case Instruction::SDiv:
9940 SkipOperation =
true;
9944 case Instruction::URem:
9946 SkipOperation =
true;
9950 case Instruction::SRem:
9952 SkipOperation =
true;
9956 case Instruction::Shl:
9958 case Instruction::LShr:
9960 case Instruction::AShr:
9962 case Instruction::And:
9964 case Instruction::Or:
9966 case Instruction::Xor:
9971 bool calculateBinaryOperatorAndTakeUnion(
const BinaryOperator *BinOp,
9972 const APInt &
LHS,
const APInt &
RHS) {
9973 bool SkipOperation =
false;
9976 calculateBinaryOperator(BinOp,
LHS,
RHS, SkipOperation, Unsupported);
9981 unionAssumed(Result);
9982 return isValidState();
9985 ChangeStatus updateWithICmpInst(Attributor &
A, ICmpInst *ICI) {
9986 auto AssumedBefore = getAssumed();
9990 bool LHSContainsUndef =
false, RHSContainsUndef =
false;
9991 SetTy LHSAAPVS, RHSAAPVS;
9993 LHSContainsUndef,
false) ||
9995 RHSContainsUndef,
false))
9996 return indicatePessimisticFixpoint();
9999 bool MaybeTrue =
false, MaybeFalse =
false;
10001 if (LHSContainsUndef && RHSContainsUndef) {
10004 unionAssumedWithUndef();
10005 }
else if (LHSContainsUndef) {
10006 for (
const APInt &R : RHSAAPVS) {
10007 bool CmpResult = calculateICmpInst(ICI, Zero, R);
10008 MaybeTrue |= CmpResult;
10009 MaybeFalse |= !CmpResult;
10010 if (MaybeTrue & MaybeFalse)
10011 return indicatePessimisticFixpoint();
10013 }
else if (RHSContainsUndef) {
10014 for (
const APInt &L : LHSAAPVS) {
10015 bool CmpResult = calculateICmpInst(ICI, L, Zero);
10016 MaybeTrue |= CmpResult;
10017 MaybeFalse |= !CmpResult;
10018 if (MaybeTrue & MaybeFalse)
10019 return indicatePessimisticFixpoint();
10022 for (
const APInt &L : LHSAAPVS) {
10023 for (
const APInt &R : RHSAAPVS) {
10024 bool CmpResult = calculateICmpInst(ICI, L, R);
10025 MaybeTrue |= CmpResult;
10026 MaybeFalse |= !CmpResult;
10027 if (MaybeTrue & MaybeFalse)
10028 return indicatePessimisticFixpoint();
10033 unionAssumed(APInt( 1, 1));
10035 unionAssumed(APInt( 1, 0));
10036 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10037 : ChangeStatus::CHANGED;
10040 ChangeStatus updateWithSelectInst(Attributor &
A, SelectInst *SI) {
10041 auto AssumedBefore = getAssumed();
10045 bool UsedAssumedInformation =
false;
10046 std::optional<Constant *>
C =
A.getAssumedConstant(
10047 *
SI->getCondition(), *
this, UsedAssumedInformation);
10050 bool OnlyLeft =
false, OnlyRight =
false;
10051 if (
C && *
C && (*C)->isOneValue())
10053 else if (
C && *
C && (*C)->isNullValue())
10056 bool LHSContainsUndef =
false, RHSContainsUndef =
false;
10057 SetTy LHSAAPVS, RHSAAPVS;
10060 LHSContainsUndef,
false))
10061 return indicatePessimisticFixpoint();
10065 RHSContainsUndef,
false))
10066 return indicatePessimisticFixpoint();
10068 if (OnlyLeft || OnlyRight) {
10070 auto *OpAA = OnlyLeft ? &LHSAAPVS : &RHSAAPVS;
10071 auto Undef = OnlyLeft ? LHSContainsUndef : RHSContainsUndef;
10074 unionAssumedWithUndef();
10076 for (
const auto &It : *OpAA)
10080 }
else if (LHSContainsUndef && RHSContainsUndef) {
10082 unionAssumedWithUndef();
10084 for (
const auto &It : LHSAAPVS)
10086 for (
const auto &It : RHSAAPVS)
10089 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10090 : ChangeStatus::CHANGED;
10093 ChangeStatus updateWithCastInst(Attributor &
A, CastInst *CI) {
10094 auto AssumedBefore = getAssumed();
10096 return indicatePessimisticFixpoint();
10101 bool SrcContainsUndef =
false;
10104 SrcContainsUndef,
false))
10105 return indicatePessimisticFixpoint();
10107 if (SrcContainsUndef)
10108 unionAssumedWithUndef();
10110 for (
const APInt &S : SrcPVS) {
10111 APInt
T = calculateCastInst(CI, S, ResultBitWidth);
10115 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10116 : ChangeStatus::CHANGED;
10119 ChangeStatus updateWithBinaryOperator(Attributor &
A, BinaryOperator *BinOp) {
10120 auto AssumedBefore = getAssumed();
10124 bool LHSContainsUndef =
false, RHSContainsUndef =
false;
10125 SetTy LHSAAPVS, RHSAAPVS;
10127 LHSContainsUndef,
false) ||
10129 RHSContainsUndef,
false))
10130 return indicatePessimisticFixpoint();
10135 if (LHSContainsUndef && RHSContainsUndef) {
10136 if (!calculateBinaryOperatorAndTakeUnion(BinOp, Zero, Zero))
10137 return indicatePessimisticFixpoint();
10138 }
else if (LHSContainsUndef) {
10139 for (
const APInt &R : RHSAAPVS) {
10140 if (!calculateBinaryOperatorAndTakeUnion(BinOp, Zero, R))
10141 return indicatePessimisticFixpoint();
10143 }
else if (RHSContainsUndef) {
10144 for (
const APInt &L : LHSAAPVS) {
10145 if (!calculateBinaryOperatorAndTakeUnion(BinOp, L, Zero))
10146 return indicatePessimisticFixpoint();
10149 for (
const APInt &L : LHSAAPVS) {
10150 for (
const APInt &R : RHSAAPVS) {
10151 if (!calculateBinaryOperatorAndTakeUnion(BinOp, L, R))
10152 return indicatePessimisticFixpoint();
10156 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10157 : ChangeStatus::CHANGED;
10160 ChangeStatus updateWithInstruction(Attributor &
A, Instruction *Inst) {
10161 auto AssumedBefore = getAssumed();
10163 bool ContainsUndef;
10165 ContainsUndef,
true))
10166 return indicatePessimisticFixpoint();
10167 if (ContainsUndef) {
10168 unionAssumedWithUndef();
10170 for (
const auto &It : Incoming)
10173 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10174 : ChangeStatus::CHANGED;
10179 Value &
V = getAssociatedValue();
10183 return updateWithICmpInst(
A, ICI);
10186 return updateWithSelectInst(
A, SI);
10189 return updateWithCastInst(
A, CI);
10192 return updateWithBinaryOperator(
A, BinOp);
10195 return updateWithInstruction(
A,
I);
10197 return indicatePessimisticFixpoint();
10201 void trackStatistics()
const override {
10206struct AAPotentialConstantValuesFunction : AAPotentialConstantValuesImpl {
10207 AAPotentialConstantValuesFunction(
const IRPosition &IRP, Attributor &
A)
10208 : AAPotentialConstantValuesImpl(IRP,
A) {}
10213 "AAPotentialConstantValues(Function|CallSite)::updateImpl will "
10218 void trackStatistics()
const override {
10223struct AAPotentialConstantValuesCallSite : AAPotentialConstantValuesFunction {
10224 AAPotentialConstantValuesCallSite(
const IRPosition &IRP, Attributor &
A)
10225 : AAPotentialConstantValuesFunction(IRP,
A) {}
10228 void trackStatistics()
const override {
10233struct AAPotentialConstantValuesCallSiteReturned
10234 : AACalleeToCallSite<AAPotentialConstantValues,
10235 AAPotentialConstantValuesImpl> {
10236 AAPotentialConstantValuesCallSiteReturned(
const IRPosition &IRP,
10238 : AACalleeToCallSite<AAPotentialConstantValues,
10239 AAPotentialConstantValuesImpl>(IRP,
A) {}
10242 void trackStatistics()
const override {
10247struct AAPotentialConstantValuesCallSiteArgument
10248 : AAPotentialConstantValuesFloating {
10249 AAPotentialConstantValuesCallSiteArgument(
const IRPosition &IRP,
10251 : AAPotentialConstantValuesFloating(IRP,
A) {}
10255 AAPotentialConstantValuesImpl::initialize(
A);
10256 if (isAtFixpoint())
10259 Value &
V = getAssociatedValue();
10262 unionAssumed(
C->getValue());
10263 indicateOptimisticFixpoint();
10268 unionAssumedWithUndef();
10269 indicateOptimisticFixpoint();
10276 Value &
V = getAssociatedValue();
10277 auto AssumedBefore = getAssumed();
10278 auto *AA =
A.getAAFor<AAPotentialConstantValues>(
10281 return indicatePessimisticFixpoint();
10282 const auto &S = AA->getAssumed();
10284 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10285 : ChangeStatus::CHANGED;
10289 void trackStatistics()
const override {
10298 bool IgnoreSubsumingPositions) {
10299 assert(ImpliedAttributeKind == Attribute::NoUndef &&
10300 "Unexpected attribute kind");
10301 if (
A.hasAttr(IRP, {Attribute::NoUndef}, IgnoreSubsumingPositions,
10302 Attribute::NoUndef))
10322 Value &V = getAssociatedValue();
10324 indicatePessimisticFixpoint();
10325 assert(!isImpliedByIR(
A, getIRPosition(), Attribute::NoUndef));
10329 bool followUseInMBEC(Attributor &
A,
const Use *U,
const Instruction *
I,
10330 AANoUndef::StateType &State) {
10331 const Value *UseV =
U->get();
10332 const DominatorTree *DT =
nullptr;
10333 AssumptionCache *AC =
nullptr;
10334 InformationCache &InfoCache =
A.getInfoCache();
10335 if (Function *
F = getAnchorScope()) {
10340 bool TrackUse =
false;
10349 const std::string getAsStr(Attributor *
A)
const override {
10350 return getAssumed() ?
"noundef" :
"may-undef-or-poison";
10357 bool UsedAssumedInformation =
false;
10358 if (
A.isAssumedDead(getIRPosition(),
nullptr,
nullptr,
10359 UsedAssumedInformation))
10360 return ChangeStatus::UNCHANGED;
10364 if (!
A.getAssumedSimplified(getIRPosition(), *
this, UsedAssumedInformation,
10367 return ChangeStatus::UNCHANGED;
10368 return AANoUndef::manifest(
A);
10372struct AANoUndefFloating :
public AANoUndefImpl {
10373 AANoUndefFloating(
const IRPosition &IRP, Attributor &
A)
10374 : AANoUndefImpl(IRP,
A) {}
10378 AANoUndefImpl::initialize(
A);
10379 if (!getState().isAtFixpoint() && getAnchorScope() &&
10380 !getAnchorScope()->isDeclaration())
10381 if (Instruction *CtxI = getCtxI())
10382 followUsesInMBEC(*
this,
A, getState(), *CtxI);
10387 auto VisitValueCB = [&](
const IRPosition &IRP) ->
bool {
10388 bool IsKnownNoUndef;
10390 A,
this, IRP, DepClassTy::REQUIRED, IsKnownNoUndef);
10394 bool UsedAssumedInformation =
false;
10395 Value *AssociatedValue = &getAssociatedValue();
10397 if (!
A.getAssumedSimplifiedValues(getIRPosition(), *
this, Values,
10402 Values.
size() != 1 || Values.
front().getValue() != AssociatedValue;
10410 if (AVIRP == getIRPosition() || !VisitValueCB(AVIRP))
10411 return indicatePessimisticFixpoint();
10412 return ChangeStatus::UNCHANGED;
10415 for (
const auto &VAC : Values)
10417 return indicatePessimisticFixpoint();
10419 return ChangeStatus::UNCHANGED;
10426struct AANoUndefReturned final
10427 : AAReturnedFromReturnedValues<AANoUndef, AANoUndefImpl> {
10428 AANoUndefReturned(
const IRPosition &IRP, Attributor &
A)
10429 : AAReturnedFromReturnedValues<AANoUndef, AANoUndefImpl>(IRP,
A) {}
10435struct AANoUndefArgument final
10436 : AAArgumentFromCallSiteArguments<AANoUndef, AANoUndefImpl> {
10437 AANoUndefArgument(
const IRPosition &IRP, Attributor &
A)
10438 : AAArgumentFromCallSiteArguments<AANoUndef, AANoUndefImpl>(IRP,
A) {}
10444struct AANoUndefCallSiteArgument final : AANoUndefFloating {
10445 AANoUndefCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
10446 : AANoUndefFloating(IRP,
A) {}
10452struct AANoUndefCallSiteReturned final
10453 : AACalleeToCallSite<AANoUndef, AANoUndefImpl> {
10454 AANoUndefCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
10455 : AACalleeToCallSite<AANoUndef, AANoUndefImpl>(IRP,
A) {}
10463struct AANoFPClassImpl : AANoFPClass {
10464 AANoFPClassImpl(
const IRPosition &IRP, Attributor &
A) : AANoFPClass(IRP,
A) {}
10467 const IRPosition &IRP = getIRPosition();
10471 indicateOptimisticFixpoint();
10476 A.getAttrs(getIRPosition(), {Attribute::NoFPClass},
Attrs,
false);
10477 for (
const auto &Attr : Attrs) {
10484 const DataLayout &
DL =
A.getDataLayout();
10485 InformationCache &InfoCache =
A.getInfoCache();
10487 const DominatorTree *DT =
nullptr;
10488 AssumptionCache *AC =
nullptr;
10489 const TargetLibraryInfo *TLI =
nullptr;
10493 if (!
F->isDeclaration()) {
10500 SimplifyQuery Q(
DL, TLI, DT, AC, CtxI);
10507 followUsesInMBEC(*
this,
A, getState(), *CtxI);
10511 bool followUseInMBEC(Attributor &
A,
const Use *U,
const Instruction *
I,
10512 AANoFPClass::StateType &State) {
10523 if (
auto *NoFPAA =
A.getAAFor<AANoFPClass>(*
this, IRP, DepClassTy::NONE))
10524 State.addKnownBits(NoFPAA->getState().getKnown());
10528 const std::string getAsStr(Attributor *
A)
const override {
10529 std::string
Result =
"nofpclass";
10530 raw_string_ostream OS(Result);
10531 OS << getKnownNoFPClass() <<
'/' << getAssumedNoFPClass();
10535 void getDeducedAttributes(Attributor &
A, LLVMContext &Ctx,
10536 SmallVectorImpl<Attribute> &Attrs)
const override {
10537 Attrs.emplace_back(Attribute::getWithNoFPClass(Ctx, getAssumedNoFPClass()));
10541struct AANoFPClassFloating :
public AANoFPClassImpl {
10542 AANoFPClassFloating(
const IRPosition &IRP, Attributor &
A)
10543 : AANoFPClassImpl(IRP,
A) {}
10548 bool UsedAssumedInformation =
false;
10549 if (!
A.getAssumedSimplifiedValues(getIRPosition(), *
this, Values,
10551 Values.
push_back({getAssociatedValue(), getCtxI()});
10557 DepClassTy::REQUIRED);
10558 if (!AA ||
this == AA) {
10559 T.indicatePessimisticFixpoint();
10561 const AANoFPClass::StateType &S =
10562 static_cast<const AANoFPClass::StateType &
>(AA->
getState());
10565 return T.isValidState();
10568 for (
const auto &VAC : Values)
10570 return indicatePessimisticFixpoint();
10576 void trackStatistics()
const override {
10581struct AANoFPClassReturned final
10582 : AAReturnedFromReturnedValues<AANoFPClass, AANoFPClassImpl,
10583 AANoFPClassImpl::StateType, false,
10584 Attribute::None, false> {
10585 AANoFPClassReturned(
const IRPosition &IRP, Attributor &
A)
10586 : AAReturnedFromReturnedValues<AANoFPClass, AANoFPClassImpl,
10587 AANoFPClassImpl::StateType,
false,
10591 void trackStatistics()
const override {
10596struct AANoFPClassArgument final
10597 : AAArgumentFromCallSiteArguments<AANoFPClass, AANoFPClassImpl> {
10598 AANoFPClassArgument(
const IRPosition &IRP, Attributor &
A)
10599 : AAArgumentFromCallSiteArguments<AANoFPClass, AANoFPClassImpl>(IRP,
A) {}
10605struct AANoFPClassCallSiteArgument final : AANoFPClassFloating {
10606 AANoFPClassCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
10607 : AANoFPClassFloating(IRP,
A) {}
10610 void trackStatistics()
const override {
10615struct AANoFPClassCallSiteReturned final
10616 : AACalleeToCallSite<AANoFPClass, AANoFPClassImpl> {
10617 AANoFPClassCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
10618 : AACalleeToCallSite<AANoFPClass, AANoFPClassImpl>(IRP,
A) {}
10621 void trackStatistics()
const override {
10626struct AACallEdgesImpl :
public AACallEdges {
10627 AACallEdgesImpl(
const IRPosition &IRP, Attributor &
A) : AACallEdges(IRP,
A) {}
10629 const SetVector<Function *> &getOptimisticEdges()
const override {
10630 return CalledFunctions;
10633 bool hasUnknownCallee()
const override {
return HasUnknownCallee; }
10635 bool hasNonAsmUnknownCallee()
const override {
10636 return HasUnknownCalleeNonAsm;
10639 const std::string getAsStr(Attributor *
A)
const override {
10640 return "CallEdges[" + std::to_string(HasUnknownCallee) +
"," +
10641 std::to_string(CalledFunctions.size()) +
"]";
10644 void trackStatistics()
const override {}
10647 void addCalledFunction(Function *Fn,
ChangeStatus &Change) {
10648 if (CalledFunctions.insert(Fn)) {
10649 Change = ChangeStatus::CHANGED;
10655 void setHasUnknownCallee(
bool NonAsm,
ChangeStatus &Change) {
10656 if (!HasUnknownCallee)
10657 Change = ChangeStatus::CHANGED;
10658 if (NonAsm && !HasUnknownCalleeNonAsm)
10659 Change = ChangeStatus::CHANGED;
10660 HasUnknownCalleeNonAsm |= NonAsm;
10661 HasUnknownCallee =
true;
10666 SetVector<Function *> CalledFunctions;
10669 bool HasUnknownCallee =
false;
10672 bool HasUnknownCalleeNonAsm =
false;
10675struct AACallEdgesCallSite :
public AACallEdgesImpl {
10676 AACallEdgesCallSite(
const IRPosition &IRP, Attributor &
A)
10677 : AACallEdgesImpl(IRP,
A) {}
10684 addCalledFunction(Fn, Change);
10686 LLVM_DEBUG(
dbgs() <<
"[AACallEdges] Unrecognized value: " << V <<
"\n");
10687 setHasUnknownCallee(
true, Change);
10698 VisitValue(*V, CtxI);
10702 bool UsedAssumedInformation =
false;
10708 for (
auto &VAC : Values)
10715 if (
IA->hasSideEffects() &&
10718 setHasUnknownCallee(
false, Change);
10724 if (
auto *IndirectCallAA =
A.getAAFor<AAIndirectCallInfo>(
10725 *
this, getIRPosition(), DepClassTy::OPTIONAL))
10726 if (IndirectCallAA->foreachCallee(
10727 [&](Function *Fn) { return VisitValue(*Fn, CB); }))
10736 for (
const Use *U : CallbackUses)
10737 ProcessCalledOperand(
U->get(), CB);
10743struct AACallEdgesFunction :
public AACallEdgesImpl {
10744 AACallEdgesFunction(
const IRPosition &IRP, Attributor &
A)
10745 : AACallEdgesImpl(IRP,
A) {}
10754 auto *CBEdges =
A.getAAFor<AACallEdges>(
10758 if (CBEdges->hasNonAsmUnknownCallee())
10759 setHasUnknownCallee(
true, Change);
10760 if (CBEdges->hasUnknownCallee())
10761 setHasUnknownCallee(
false, Change);
10763 for (Function *
F : CBEdges->getOptimisticEdges())
10764 addCalledFunction(
F, Change);
10770 bool UsedAssumedInformation =
false;
10771 if (!
A.checkForAllCallLikeInstructions(ProcessCallInst, *
this,
10772 UsedAssumedInformation,
10776 setHasUnknownCallee(
true, Change);
10785struct AAInterFnReachabilityFunction
10786 :
public CachedReachabilityAA<AAInterFnReachability, Function> {
10787 using Base = CachedReachabilityAA<AAInterFnReachability, Function>;
10788 AAInterFnReachabilityFunction(
const IRPosition &IRP, Attributor &
A)
10791 bool instructionCanReach(
10792 Attributor &
A,
const Instruction &From,
const Function &To,
10795 auto *NonConstThis =
const_cast<AAInterFnReachabilityFunction *
>(
this);
10797 RQITy StackRQI(
A, From, To, ExclusionSet,
false);
10798 RQITy::Reachable
Result;
10799 if (!NonConstThis->checkQueryCache(
A, StackRQI, Result))
10800 return NonConstThis->isReachableImpl(
A, StackRQI,
10802 return Result == RQITy::Reachable::Yes;
10806 bool IsTemporaryRQI)
override {
10808 &RQI.From->getFunction()->getEntryBlock().front();
10809 if (EntryI != RQI.From &&
10810 !instructionCanReach(
A, *EntryI, *RQI.To,
nullptr))
10811 return rememberResult(
A, RQITy::Reachable::No, RQI,
false,
10814 auto CheckReachableCallBase = [&](CallBase *CB) {
10815 auto *CBEdges =
A.getAAFor<AACallEdges>(
10817 if (!CBEdges || !CBEdges->getState().isValidState())
10820 if (CBEdges->hasUnknownCallee())
10823 for (Function *Fn : CBEdges->getOptimisticEdges()) {
10834 if (Fn == getAnchorScope()) {
10835 if (EntryI == RQI.From)
10840 const AAInterFnReachability *InterFnReachability =
10842 DepClassTy::OPTIONAL);
10845 if (!InterFnReachability ||
10853 const auto *IntraFnReachability =
A.getAAFor<AAIntraFnReachability>(
10855 DepClassTy::OPTIONAL);
10863 return IntraFnReachability && !IntraFnReachability->isAssumedReachable(
10864 A, *RQI.From, CBInst, RQI.ExclusionSet);
10867 bool UsedExclusionSet =
true;
10868 bool UsedAssumedInformation =
false;
10869 if (!
A.checkForAllCallLikeInstructions(CheckCallBase, *
this,
10870 UsedAssumedInformation,
10872 return rememberResult(
A, RQITy::Reachable::Yes, RQI, UsedExclusionSet,
10875 return rememberResult(
A, RQITy::Reachable::No, RQI, UsedExclusionSet,
10879 void trackStatistics()
const override {}
10883template <
typename AAType>
10884static std::optional<Constant *>
10887 if (!Ty.isIntegerTy())
10895 std::optional<Constant *> COpt =
AA->getAssumedConstant(
A);
10897 if (!COpt.has_value()) {
10899 return std::nullopt;
10901 if (
auto *
C = *COpt) {
10912 std::optional<Value *> V;
10913 for (
auto &It : Values) {
10915 if (V.has_value() && !*V)
10918 if (!V.has_value())
10932 if (
A.hasSimplificationCallback(getIRPosition())) {
10933 indicatePessimisticFixpoint();
10936 Value *Stripped = getAssociatedValue().stripPointerCasts();
10938 addValue(
A, getState(), *Stripped, getCtxI(),
AA::AnyScope,
10940 indicateOptimisticFixpoint();
10943 AAPotentialValues::initialize(
A);
10947 const std::string getAsStr(Attributor *
A)
const override {
10949 llvm::raw_string_ostream OS(Str);
10954 template <
typename AAType>
10955 static std::optional<Value *> askOtherAA(Attributor &
A,
10956 const AbstractAttribute &AA,
10957 const IRPosition &IRP,
Type &Ty) {
10962 return std::nullopt;
10969 virtual void addValue(Attributor &
A, StateType &State,
Value &V,
10971 Function *AnchorScope)
const {
10975 for (
const auto &U : CB->
args()) {
10985 Type &Ty = *getAssociatedType();
10986 std::optional<Value *> SimpleV =
10987 askOtherAA<AAValueConstantRange>(
A, *
this, ValIRP, Ty);
10988 if (SimpleV.has_value() && !*SimpleV) {
10989 auto *PotentialConstantsAA =
A.getAAFor<AAPotentialConstantValues>(
10990 *
this, ValIRP, DepClassTy::OPTIONAL);
10991 if (PotentialConstantsAA && PotentialConstantsAA->isValidState()) {
10992 for (
const auto &It : PotentialConstantsAA->getAssumedSet())
10993 State.unionAssumed({{*ConstantInt::get(&Ty, It),
nullptr}, S});
10994 if (PotentialConstantsAA->undefIsContained())
10999 if (!SimpleV.has_value())
11011 State.unionAssumed({{*VPtr, CtxI}, S});
11017 AA::ValueAndContext
I;
11021 return II.I ==
I &&
II.S == S;
11024 return std::tie(
I, S) < std::tie(
II.I,
II.S);
11028 bool recurseForValue(Attributor &
A,
const IRPosition &IRP,
AA::ValueScope S) {
11029 SmallMapVector<AA::ValueAndContext, int, 8> ValueScopeMap;
11034 bool UsedAssumedInformation =
false;
11036 if (!
A.getAssumedSimplifiedValues(IRP,
this, Values, CS,
11037 UsedAssumedInformation))
11040 for (
auto &It : Values)
11041 ValueScopeMap[It] += CS;
11043 for (
auto &It : ValueScopeMap)
11044 addValue(
A, getState(), *It.first.getValue(), It.first.getCtxI(),
11050 void giveUpOnIntraprocedural(Attributor &
A) {
11051 auto NewS = StateType::getBestState(getState());
11052 for (
const auto &It : getAssumedSet()) {
11055 addValue(
A, NewS, *It.first.getValue(), It.first.getCtxI(),
11058 assert(!undefIsContained() &&
"Undef should be an explicit value!");
11066 getState() = StateType::getBestState(getState());
11067 getState().unionAssumed({{getAssociatedValue(), getCtxI()},
AA::AnyScope});
11068 AAPotentialValues::indicateOptimisticFixpoint();
11069 return ChangeStatus::CHANGED;
11074 return indicatePessimisticFixpoint();
11082 if (!getAssumedSimplifiedValues(
A, Values, S))
11084 Value &OldV = getAssociatedValue();
11087 Value *NewV = getSingleValue(
A, *
this, getIRPosition(), Values);
11088 if (!NewV || NewV == &OldV)
11093 if (
A.changeAfterManifest(getIRPosition(), *NewV))
11094 return ChangeStatus::CHANGED;
11096 return ChangeStatus::UNCHANGED;
11099 bool getAssumedSimplifiedValues(
11100 Attributor &
A, SmallVectorImpl<AA::ValueAndContext> &Values,
11101 AA::ValueScope S,
bool RecurseForSelectAndPHI =
false)
const override {
11102 if (!isValidState())
11104 bool UsedAssumedInformation =
false;
11105 for (
const auto &It : getAssumedSet())
11106 if (It.second & S) {
11107 if (RecurseForSelectAndPHI && (
isa<PHINode>(It.first.getValue()) ||
11109 if (
A.getAssumedSimplifiedValues(
11111 this, Values, S, UsedAssumedInformation))
11116 assert(!undefIsContained() &&
"Undef should be an explicit value!");
11121struct AAPotentialValuesFloating : AAPotentialValuesImpl {
11122 AAPotentialValuesFloating(
const IRPosition &IRP, Attributor &
A)
11123 : AAPotentialValuesImpl(IRP,
A) {}
11127 auto AssumedBefore = getAssumed();
11129 genericValueTraversal(
A, &getAssociatedValue());
11131 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
11132 : ChangeStatus::CHANGED;
11136 struct LivenessInfo {
11137 const AAIsDead *LivenessAA =
nullptr;
11138 bool AnyDead =
false;
11148 SmallVectorImpl<ItemInfo> &Worklist) {
11151 bool UsedAssumedInformation =
false;
11153 auto GetSimplifiedValues = [&](
Value &
V,
11155 if (!
A.getAssumedSimplifiedValues(
11159 Values.
push_back(AA::ValueAndContext{
V,
II.I.getCtxI()});
11161 return Values.
empty();
11163 if (GetSimplifiedValues(*
LHS, LHSValues))
11165 if (GetSimplifiedValues(*
RHS, RHSValues))
11170 InformationCache &InfoCache =
A.getInfoCache();
11177 F ?
A.getInfoCache().getTargetLibraryInfoForFunction(*
F) :
nullptr;
11182 const DataLayout &
DL =
A.getDataLayout();
11183 SimplifyQuery Q(
DL, TLI, DT, AC, CmpI);
11185 auto CheckPair = [&](
Value &LHSV,
Value &RHSV) {
11188 nullptr,
II.S, getAnchorScope());
11194 if (&LHSV == &RHSV &&
11196 Constant *NewV = ConstantInt::get(Type::getInt1Ty(Ctx),
11198 addValue(
A, getState(), *NewV,
nullptr,
II.S,
11205 if (TypedLHS && TypedRHS) {
11207 if (NewV && NewV != &Cmp) {
11208 addValue(
A, getState(), *NewV,
nullptr,
II.S,
11220 if (!LHSIsNull && !RHSIsNull)
11226 assert((LHSIsNull || RHSIsNull) &&
11227 "Expected nullptr versus non-nullptr comparison at this point");
11230 unsigned PtrIdx = LHSIsNull;
11231 bool IsKnownNonNull;
11234 DepClassTy::REQUIRED, IsKnownNonNull);
11235 if (!IsAssumedNonNull)
11241 addValue(
A, getState(), *NewV,
nullptr,
II.S,
11246 for (
auto &LHSValue : LHSValues)
11247 for (
auto &RHSValue : RHSValues)
11248 if (!CheckPair(*LHSValue.getValue(), *RHSValue.getValue()))
11253 bool handleSelectInst(Attributor &
A, SelectInst &SI, ItemInfo
II,
11254 SmallVectorImpl<ItemInfo> &Worklist) {
11256 bool UsedAssumedInformation =
false;
11258 std::optional<Constant *>
C =
11259 A.getAssumedConstant(*
SI.getCondition(), *
this, UsedAssumedInformation);
11260 bool NoValueYet = !
C.has_value();
11268 }
else if (&SI == &getAssociatedValue()) {
11273 std::optional<Value *> SimpleV =
A.getAssumedSimplified(
11275 if (!SimpleV.has_value())
11278 addValue(
A, getState(), **SimpleV, CtxI,
II.S, getAnchorScope());
11286 bool handleLoadInst(Attributor &
A, LoadInst &LI, ItemInfo
II,
11287 SmallVectorImpl<ItemInfo> &Worklist) {
11288 SmallSetVector<Value *, 4> PotentialCopies;
11289 SmallSetVector<Instruction *, 4> PotentialValueOrigins;
11290 bool UsedAssumedInformation =
false;
11292 PotentialValueOrigins, *
this,
11293 UsedAssumedInformation,
11295 LLVM_DEBUG(
dbgs() <<
"[AAPotentialValues] Failed to get potentially "
11296 "loaded values for load instruction "
11304 InformationCache &InfoCache =
A.getInfoCache();
11306 if (!
llvm::all_of(PotentialValueOrigins, [&](Instruction *
I) {
11310 return A.isAssumedDead(
SI->getOperandUse(0),
this,
11312 UsedAssumedInformation,
11314 return A.isAssumedDead(*
I,
this,
nullptr,
11315 UsedAssumedInformation,
11318 LLVM_DEBUG(
dbgs() <<
"[AAPotentialValues] Load is onl used by assumes "
11319 "and we cannot delete all the stores: "
11330 bool AllLocal = ScopeIsLocal;
11335 if (!DynamicallyUnique) {
11336 LLVM_DEBUG(
dbgs() <<
"[AAPotentialValues] Not all potentially loaded "
11337 "values are dynamically unique: "
11342 for (
auto *PotentialCopy : PotentialCopies) {
11344 Worklist.
push_back({{*PotentialCopy, CtxI},
II.S});
11349 if (!AllLocal && ScopeIsLocal)
11354 bool handlePHINode(
11355 Attributor &
A, PHINode &
PHI, ItemInfo
II,
11356 SmallVectorImpl<ItemInfo> &Worklist,
11357 SmallMapVector<const Function *, LivenessInfo, 4> &LivenessAAs) {
11358 auto GetLivenessInfo = [&](
const Function &
F) -> LivenessInfo & {
11359 LivenessInfo &LI = LivenessAAs[&
F];
11360 if (!LI.LivenessAA)
11366 if (&
PHI == &getAssociatedValue()) {
11367 LivenessInfo &LI = GetLivenessInfo(*
PHI.getFunction());
11369 A.getInfoCache().getAnalysisResultForFunction<CycleAnalysis>(
11370 *
PHI.getFunction());
11374 for (
unsigned u = 0, e =
PHI.getNumIncomingValues(); u < e; u++) {
11376 if (LI.LivenessAA &&
11377 LI.LivenessAA->isEdgeDead(IncomingBB,
PHI.getParent())) {
11396 bool UsedAssumedInformation =
false;
11397 std::optional<Value *> SimpleV =
A.getAssumedSimplified(
11399 if (!SimpleV.has_value())
11403 addValue(
A, getState(), **SimpleV, &
PHI,
II.S, getAnchorScope());
11410 bool handleGenericInst(Attributor &
A, Instruction &
I, ItemInfo
II,
11411 SmallVectorImpl<ItemInfo> &Worklist) {
11412 bool SomeSimplified =
false;
11413 bool UsedAssumedInformation =
false;
11415 SmallVector<Value *, 8> NewOps(
I.getNumOperands());
11418 const auto &SimplifiedOp =
A.getAssumedSimplified(
11423 if (!SimplifiedOp.has_value())
11427 NewOps[Idx] = *SimplifiedOp;
11431 SomeSimplified |= (NewOps[Idx] !=
Op);
11437 if (!SomeSimplified)
11440 InformationCache &InfoCache =
A.getInfoCache();
11444 const auto *TLI =
A.getInfoCache().getTargetLibraryInfoForFunction(*
F);
11447 const DataLayout &
DL =
I.getDataLayout();
11448 SimplifyQuery Q(
DL, TLI, DT, AC, &
I);
11450 if (!NewV || NewV == &
I)
11453 LLVM_DEBUG(
dbgs() <<
"Generic inst " <<
I <<
" assumed simplified to "
11460 Attributor &
A, Instruction &
I, ItemInfo
II,
11461 SmallVectorImpl<ItemInfo> &Worklist,
11462 SmallMapVector<const Function *, LivenessInfo, 4> &LivenessAAs) {
11465 CI->getPredicate(),
II, Worklist);
11467 switch (
I.getOpcode()) {
11468 case Instruction::Select:
11470 case Instruction::PHI:
11472 case Instruction::Load:
11475 return handleGenericInst(
A,
I,
II, Worklist);
11480 void genericValueTraversal(Attributor &
A,
Value *InitialV) {
11481 SmallMapVector<const Function *, LivenessInfo, 4> LivenessAAs;
11483 SmallSet<ItemInfo, 16> Visited;
11502 LLVM_DEBUG(
dbgs() <<
"Generic value traversal reached iteration limit: "
11503 << Iteration <<
"!\n");
11504 addValue(
A, getState(), *V, CtxI, S, getAnchorScope());
11510 Value *NewV =
nullptr;
11511 if (
V->getType()->isPointerTy()) {
11517 for (Argument &Arg :
Callee->args())
11524 if (NewV && NewV != V) {
11525 Worklist.
push_back({{*NewV, CtxI}, S});
11539 if (V == InitialV && CtxI == getCtxI()) {
11540 indicatePessimisticFixpoint();
11544 addValue(
A, getState(), *V, CtxI, S, getAnchorScope());
11545 }
while (!Worklist.
empty());
11549 for (
auto &It : LivenessAAs)
11550 if (It.second.AnyDead)
11551 A.recordDependence(*It.second.LivenessAA, *
this, DepClassTy::OPTIONAL);
11555 void trackStatistics()
const override {
11560struct AAPotentialValuesArgument final : AAPotentialValuesImpl {
11561 using Base = AAPotentialValuesImpl;
11562 AAPotentialValuesArgument(
const IRPosition &IRP, Attributor &
A)
11569 indicatePessimisticFixpoint();
11574 auto AssumedBefore = getAssumed();
11576 unsigned ArgNo = getCalleeArgNo();
11578 bool UsedAssumedInformation =
false;
11580 auto CallSitePred = [&](AbstractCallSite ACS) {
11582 if (CSArgIRP.getPositionKind() == IRP_INVALID)
11585 if (!
A.getAssumedSimplifiedValues(CSArgIRP,
this, Values,
11587 UsedAssumedInformation))
11590 return isValidState();
11593 if (!
A.checkForAllCallSites(CallSitePred, *
this,
11595 UsedAssumedInformation))
11596 return indicatePessimisticFixpoint();
11598 Function *Fn = getAssociatedFunction();
11599 bool AnyNonLocal =
false;
11600 for (
auto &It : Values) {
11602 addValue(
A, getState(), *It.getValue(), It.getCtxI(),
AA::AnyScope,
11607 return indicatePessimisticFixpoint();
11611 addValue(
A, getState(), *It.getValue(), It.getCtxI(),
AA::AnyScope,
11617 AnyNonLocal =
true;
11619 assert(!undefIsContained() &&
"Undef should be an explicit value!");
11621 giveUpOnIntraprocedural(
A);
11623 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
11624 : ChangeStatus::CHANGED;
11628 void trackStatistics()
const override {
11633struct AAPotentialValuesReturned :
public AAPotentialValuesFloating {
11634 using Base = AAPotentialValuesFloating;
11635 AAPotentialValuesReturned(
const IRPosition &IRP, Attributor &
A)
11641 if (!
F ||
F->isDeclaration() ||
F->getReturnType()->isVoidTy()) {
11642 indicatePessimisticFixpoint();
11646 for (Argument &Arg :
F->args())
11649 ReturnedArg = &Arg;
11652 if (!
A.isFunctionIPOAmendable(*
F) ||
11653 A.hasSimplificationCallback(getIRPosition())) {
11655 indicatePessimisticFixpoint();
11657 indicateOptimisticFixpoint();
11663 auto AssumedBefore = getAssumed();
11664 bool UsedAssumedInformation =
false;
11667 Function *AnchorScope = getAnchorScope();
11673 UsedAssumedInformation,
11679 bool AllInterAreIntra =
false;
11682 llvm::all_of(Values, [&](
const AA::ValueAndContext &VAC) {
11686 for (
const AA::ValueAndContext &VAC : Values) {
11687 addValue(
A, getState(), *VAC.
getValue(),
11691 if (AllInterAreIntra)
11698 HandleReturnedValue(*ReturnedArg,
nullptr,
true);
11701 bool AddValues =
true;
11704 addValue(
A, getState(), *RetI.getOperand(0), &RetI,
AA::AnyScope,
11708 return HandleReturnedValue(*RetI.getOperand(0), &RetI, AddValues);
11711 if (!
A.checkForAllInstructions(RetInstPred, *
this, {Instruction::Ret},
11712 UsedAssumedInformation,
11714 return indicatePessimisticFixpoint();
11717 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
11718 : ChangeStatus::CHANGED;
11723 return ChangeStatus::UNCHANGED;
11725 if (!getAssumedSimplifiedValues(
A, Values, AA::ValueScope::Intraprocedural,
11727 return ChangeStatus::UNCHANGED;
11728 Value *NewVal = getSingleValue(
A, *
this, getIRPosition(), Values);
11730 return ChangeStatus::UNCHANGED;
11735 "Number of function with unique return");
11738 {Attribute::get(Arg->
getContext(), Attribute::Returned)});
11743 Value *RetOp = RetI.getOperand(0);
11747 if (
A.changeUseAfterManifest(RetI.getOperandUse(0), *NewVal))
11748 Changed = ChangeStatus::CHANGED;
11751 bool UsedAssumedInformation =
false;
11752 (void)
A.checkForAllInstructions(RetInstPred, *
this, {Instruction::Ret},
11753 UsedAssumedInformation,
11759 return AAPotentialValues::indicatePessimisticFixpoint();
11763 void trackStatistics()
const override{
11770struct AAPotentialValuesFunction : AAPotentialValuesImpl {
11771 AAPotentialValuesFunction(
const IRPosition &IRP, Attributor &
A)
11772 : AAPotentialValuesImpl(IRP,
A) {}
11781 void trackStatistics()
const override {
11786struct AAPotentialValuesCallSite : AAPotentialValuesFunction {
11787 AAPotentialValuesCallSite(
const IRPosition &IRP, Attributor &
A)
11788 : AAPotentialValuesFunction(IRP,
A) {}
11791 void trackStatistics()
const override {
11796struct AAPotentialValuesCallSiteReturned : AAPotentialValuesImpl {
11797 AAPotentialValuesCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
11798 : AAPotentialValuesImpl(IRP,
A) {}
11802 auto AssumedBefore = getAssumed();
11806 return indicatePessimisticFixpoint();
11808 bool UsedAssumedInformation =
false;
11812 UsedAssumedInformation))
11813 return indicatePessimisticFixpoint();
11820 Values, S, UsedAssumedInformation))
11823 for (
auto &It : Values) {
11824 Value *
V = It.getValue();
11825 std::optional<Value *> CallerV =
A.translateArgumentToCallSiteContent(
11826 V, *CB, *
this, UsedAssumedInformation);
11827 if (!CallerV.has_value()) {
11831 V = *CallerV ? *CallerV :
V;
11837 giveUpOnIntraprocedural(
A);
11840 addValue(
A, getState(), *V, CB, S, getAnchorScope());
11845 return indicatePessimisticFixpoint();
11847 return indicatePessimisticFixpoint();
11848 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
11849 : ChangeStatus::CHANGED;
11853 return AAPotentialValues::indicatePessimisticFixpoint();
11857 void trackStatistics()
const override {
11862struct AAPotentialValuesCallSiteArgument : AAPotentialValuesFloating {
11863 AAPotentialValuesCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
11864 : AAPotentialValuesFloating(IRP,
A) {}
11867 void trackStatistics()
const override {
11875struct AAAssumptionInfoImpl :
public AAAssumptionInfo {
11876 AAAssumptionInfoImpl(
const IRPosition &IRP, Attributor &
A,
11877 const DenseSet<StringRef> &Known)
11878 : AAAssumptionInfo(IRP,
A, Known) {}
11883 if (getKnown().isUniversal())
11884 return ChangeStatus::UNCHANGED;
11886 const IRPosition &IRP = getIRPosition();
11888 getAssumed().getSet().
end());
11890 return A.manifestAttrs(IRP,
11897 bool hasAssumption(
const StringRef Assumption)
const override {
11898 return isValidState() && setContains(Assumption);
11902 const std::string getAsStr(Attributor *
A)
const override {
11903 const SetContents &Known = getKnown();
11904 const SetContents &Assumed = getAssumed();
11908 const std::string KnownStr =
llvm::join(Set,
",");
11910 std::string AssumedStr =
"Universal";
11911 if (!Assumed.isUniversal()) {
11912 Set.assign(Assumed.getSet().begin(), Assumed.getSet().end());
11915 return "Known [" + KnownStr +
"]," +
" Assumed [" + AssumedStr +
"]";
11930struct AAAssumptionInfoFunction final : AAAssumptionInfoImpl {
11931 AAAssumptionInfoFunction(
const IRPosition &IRP, Attributor &
A)
11932 : AAAssumptionInfoImpl(IRP,
A,
11939 auto CallSitePred = [&](AbstractCallSite ACS) {
11940 const auto *AssumptionAA =
A.getAAFor<AAAssumptionInfo>(
11942 DepClassTy::REQUIRED);
11946 Changed |= getIntersection(AssumptionAA->getAssumed());
11947 return !getAssumed().empty() || !getKnown().empty();
11950 bool UsedAssumedInformation =
false;
11955 if (!
A.checkForAllCallSites(CallSitePred, *
this,
true,
11956 UsedAssumedInformation))
11957 return indicatePessimisticFixpoint();
11959 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
11962 void trackStatistics()
const override {}
11966struct AAAssumptionInfoCallSite final : AAAssumptionInfoImpl {
11968 AAAssumptionInfoCallSite(
const IRPosition &IRP, Attributor &
A)
11969 : AAAssumptionInfoImpl(IRP,
A, getInitialAssumptions(IRP)) {}
11974 A.getAAFor<AAAssumptionInfo>(*
this, FnPos, DepClassTy::REQUIRED);
11980 auto *AssumptionAA =
11981 A.getAAFor<AAAssumptionInfo>(*
this, FnPos, DepClassTy::REQUIRED);
11983 return indicatePessimisticFixpoint();
11984 bool Changed = getIntersection(AssumptionAA->getAssumed());
11985 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
11989 void trackStatistics()
const override {}
11994 DenseSet<StringRef> getInitialAssumptions(
const IRPosition &IRP) {
12001 return Assumptions;
12016struct AAUnderlyingObjectsImpl
12022 const std::string getAsStr(
Attributor *
A)
const override {
12023 if (!isValidState())
12024 return "<invalid>";
12027 OS <<
"underlying objects: inter " << InterAssumedUnderlyingObjects.size()
12028 <<
" objects, intra " << IntraAssumedUnderlyingObjects.size()
12030 if (!InterAssumedUnderlyingObjects.empty()) {
12031 OS <<
"inter objects:\n";
12032 for (
auto *Obj : InterAssumedUnderlyingObjects)
12033 OS << *Obj <<
'\n';
12035 if (!IntraAssumedUnderlyingObjects.empty()) {
12036 OS <<
"intra objects:\n";
12037 for (
auto *Obj : IntraAssumedUnderlyingObjects)
12038 OS << *
Obj <<
'\n';
12044 void trackStatistics()
const override {}
12048 auto &Ptr = getAssociatedValue();
12050 bool UsedAssumedInformation =
false;
12051 auto DoUpdate = [&](SmallSetVector<Value *, 8> &UnderlyingObjects,
12053 SmallPtrSet<Value *, 8> SeenObjects;
12057 Scope, UsedAssumedInformation))
12058 return UnderlyingObjects.
insert(&Ptr);
12062 for (
unsigned I = 0;
I < Values.
size(); ++
I) {
12063 auto &VAC = Values[
I];
12066 if (!SeenObjects.
insert(UO ? UO : Obj).second)
12068 if (UO && UO != Obj) {
12074 const auto *OtherAA =
A.getAAFor<AAUnderlyingObjects>(
12076 auto Pred = [&](
Value &
V) {
12084 if (!OtherAA || !OtherAA->forallUnderlyingObjects(Pred, Scope))
12086 "The forall call should not return false at this position");
12092 Changed |= handleIndirect(
A, *Obj, UnderlyingObjects, Scope,
12093 UsedAssumedInformation);
12099 for (
unsigned u = 0, e =
PHI->getNumIncomingValues(); u < e; u++) {
12101 handleIndirect(
A, *
PHI->getIncomingValue(u), UnderlyingObjects,
12102 Scope, UsedAssumedInformation);
12116 if (!UsedAssumedInformation)
12117 indicateOptimisticFixpoint();
12118 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
12121 bool forallUnderlyingObjects(
12122 function_ref<
bool(
Value &)> Pred,
12124 if (!isValidState())
12125 return Pred(getAssociatedValue());
12128 ? IntraAssumedUnderlyingObjects
12129 : InterAssumedUnderlyingObjects;
12130 for (
Value *Obj : AssumedUnderlyingObjects)
12140 bool handleIndirect(Attributor &
A,
Value &V,
12141 SmallSetVector<Value *, 8> &UnderlyingObjects,
12144 const auto *AA =
A.getAAFor<AAUnderlyingObjects>(
12146 auto Pred = [&](
Value &
V) {
12150 if (!AA || !AA->forallUnderlyingObjects(Pred, Scope))
12152 "The forall call should not return false at this position");
12158 SmallSetVector<Value *, 8> IntraAssumedUnderlyingObjects;
12160 SmallSetVector<Value *, 8> InterAssumedUnderlyingObjects;
12163struct AAUnderlyingObjectsFloating final : AAUnderlyingObjectsImpl {
12164 AAUnderlyingObjectsFloating(
const IRPosition &IRP, Attributor &
A)
12165 : AAUnderlyingObjectsImpl(IRP,
A) {}
12168struct AAUnderlyingObjectsArgument final : AAUnderlyingObjectsImpl {
12169 AAUnderlyingObjectsArgument(
const IRPosition &IRP, Attributor &
A)
12170 : AAUnderlyingObjectsImpl(IRP,
A) {}
12173struct AAUnderlyingObjectsCallSite final : AAUnderlyingObjectsImpl {
12174 AAUnderlyingObjectsCallSite(
const IRPosition &IRP, Attributor &
A)
12175 : AAUnderlyingObjectsImpl(IRP,
A) {}
12178struct AAUnderlyingObjectsCallSiteArgument final : AAUnderlyingObjectsImpl {
12179 AAUnderlyingObjectsCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
12180 : AAUnderlyingObjectsImpl(IRP,
A) {}
12183struct AAUnderlyingObjectsReturned final : AAUnderlyingObjectsImpl {
12184 AAUnderlyingObjectsReturned(
const IRPosition &IRP, Attributor &
A)
12185 : AAUnderlyingObjectsImpl(IRP,
A) {}
12188struct AAUnderlyingObjectsCallSiteReturned final : AAUnderlyingObjectsImpl {
12189 AAUnderlyingObjectsCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
12190 : AAUnderlyingObjectsImpl(IRP,
A) {}
12193struct AAUnderlyingObjectsFunction final : AAUnderlyingObjectsImpl {
12194 AAUnderlyingObjectsFunction(
const IRPosition &IRP, Attributor &
A)
12195 : AAUnderlyingObjectsImpl(IRP,
A) {}
12201struct AAGlobalValueInfoFloating :
public AAGlobalValueInfo {
12202 AAGlobalValueInfoFloating(
const IRPosition &IRP, Attributor &
A)
12203 : AAGlobalValueInfo(IRP,
A) {}
12208 bool checkUse(Attributor &
A,
const Use &U,
bool &Follow,
12209 SmallVectorImpl<const Value *> &Worklist) {
12216 LLVM_DEBUG(
dbgs() <<
"[AAGlobalValueInfo] Check use: " << *
U.get() <<
" in "
12217 << *UInst <<
"\n");
12220 int Idx = &
Cmp->getOperandUse(0) == &
U;
12223 return U == &getAnchorValue();
12228 auto CallSitePred = [&](AbstractCallSite ACS) {
12229 Worklist.
push_back(ACS.getInstruction());
12232 bool UsedAssumedInformation =
false;
12234 if (!
A.checkForAllCallSites(CallSitePred, *UInst->
getFunction(),
12236 UsedAssumedInformation))
12254 if (!Fn || !
A.isFunctionIPOAmendable(*Fn))
12263 unsigned NumUsesBefore =
Uses.size();
12265 SmallPtrSet<const Value *, 8> Visited;
12269 auto UsePred = [&](
const Use &
U,
bool &Follow) ->
bool {
12277 return checkUse(
A, U, Follow, Worklist);
12279 auto EquivalentUseCB = [&](
const Use &OldU,
const Use &NewU) {
12280 Uses.insert(&OldU);
12284 while (!Worklist.
empty()) {
12286 if (!Visited.
insert(V).second)
12288 if (!
A.checkForAllUses(UsePred, *
this, *V,
12290 DepClassTy::OPTIONAL,
12291 true, EquivalentUseCB)) {
12292 return indicatePessimisticFixpoint();
12296 return Uses.size() == NumUsesBefore ? ChangeStatus::UNCHANGED
12297 : ChangeStatus::CHANGED;
12300 bool isPotentialUse(
const Use &U)
const override {
12301 return !isValidState() ||
Uses.contains(&U);
12306 return ChangeStatus::UNCHANGED;
12310 const std::string getAsStr(Attributor *
A)
const override {
12311 return "[" + std::to_string(
Uses.size()) +
" uses]";
12314 void trackStatistics()
const override {
12320 SmallPtrSet<const Use *, 8>
Uses;
12326struct AAIndirectCallInfoCallSite :
public AAIndirectCallInfo {
12327 AAIndirectCallInfoCallSite(
const IRPosition &IRP, Attributor &
A)
12328 : AAIndirectCallInfo(IRP,
A) {}
12332 auto *MD = getCtxI()->getMetadata(LLVMContext::MD_callees);
12333 if (!MD && !
A.isClosedWorldModule())
12337 for (
const auto &
Op : MD->operands())
12339 PotentialCallees.insert(Callee);
12340 }
else if (
A.isClosedWorldModule()) {
12342 A.getInfoCache().getIndirectlyCallableFunctions(
A);
12343 PotentialCallees.insert_range(IndirectlyCallableFunctions);
12346 if (PotentialCallees.empty())
12347 indicateOptimisticFixpoint();
12355 SmallSetVector<Function *, 4> AssumedCalleesNow;
12356 bool AllCalleesKnownNow = AllCalleesKnown;
12358 auto CheckPotentialCalleeUse = [&](
Function &PotentialCallee,
12359 bool &UsedAssumedInformation) {
12360 const auto *GIAA =
A.getAAFor<AAGlobalValueInfo>(
12362 if (!GIAA || GIAA->isPotentialUse(CalleeUse))
12364 UsedAssumedInformation = !GIAA->isAtFixpoint();
12368 auto AddPotentialCallees = [&]() {
12369 for (
auto *PotentialCallee : PotentialCallees) {
12370 bool UsedAssumedInformation =
false;
12371 if (CheckPotentialCalleeUse(*PotentialCallee, UsedAssumedInformation))
12372 AssumedCalleesNow.
insert(PotentialCallee);
12378 bool UsedAssumedInformation =
false;
12381 AA::ValueScope::AnyScope,
12382 UsedAssumedInformation)) {
12383 if (PotentialCallees.empty())
12384 return indicatePessimisticFixpoint();
12385 AddPotentialCallees();
12390 auto CheckPotentialCallee = [&](
Function &Fn) {
12391 if (!PotentialCallees.empty() && !PotentialCallees.count(&Fn))
12394 auto &CachedResult = FilterResults[&Fn];
12395 if (CachedResult.has_value())
12396 return CachedResult.value();
12398 bool UsedAssumedInformation =
false;
12399 if (!CheckPotentialCalleeUse(Fn, UsedAssumedInformation)) {
12400 if (!UsedAssumedInformation)
12401 CachedResult =
false;
12410 for (
int I = NumCBArgs;
I < NumFnArgs; ++
I) {
12411 bool IsKnown =
false;
12414 DepClassTy::OPTIONAL, IsKnown)) {
12416 CachedResult =
false;
12421 CachedResult =
true;
12427 for (
auto &VAC : Values) {
12435 if (CheckPotentialCallee(*VACFn))
12436 AssumedCalleesNow.
insert(VACFn);
12439 if (!PotentialCallees.empty()) {
12440 AddPotentialCallees();
12443 AllCalleesKnownNow =
false;
12446 if (AssumedCalleesNow == AssumedCallees &&
12447 AllCalleesKnown == AllCalleesKnownNow)
12448 return ChangeStatus::UNCHANGED;
12450 std::swap(AssumedCallees, AssumedCalleesNow);
12451 AllCalleesKnown = AllCalleesKnownNow;
12452 return ChangeStatus::CHANGED;
12458 if (!AllCalleesKnown && AssumedCallees.empty())
12459 return ChangeStatus::UNCHANGED;
12462 bool UsedAssumedInformation =
false;
12463 if (
A.isAssumedDead(*CB,
this,
nullptr,
12464 UsedAssumedInformation))
12465 return ChangeStatus::UNCHANGED;
12469 if (
FP->getType()->getPointerAddressSpace())
12470 FP =
new AddrSpaceCastInst(
FP, PointerType::get(
FP->getContext(), 0),
12480 if (AssumedCallees.empty()) {
12481 assert(AllCalleesKnown &&
12482 "Expected all callees to be known if there are none.");
12483 A.changeToUnreachableAfterManifest(CB);
12484 return ChangeStatus::CHANGED;
12488 if (AllCalleesKnown && AssumedCallees.size() == 1) {
12489 auto *NewCallee = AssumedCallees.front();
12492 NumIndirectCallsPromoted++;
12493 return ChangeStatus::CHANGED;
12500 A.deleteAfterManifest(*CB);
12501 return ChangeStatus::CHANGED;
12511 bool SpecializedForAnyCallees =
false;
12512 bool SpecializedForAllCallees = AllCalleesKnown;
12513 ICmpInst *LastCmp =
nullptr;
12516 for (Function *NewCallee : AssumedCallees) {
12517 if (!
A.shouldSpecializeCallSiteForCallee(*
this, *CB, *NewCallee,
12518 AssumedCallees.size())) {
12519 SkippedAssumedCallees.
push_back(NewCallee);
12520 SpecializedForAllCallees =
false;
12523 SpecializedForAnyCallees =
true;
12529 A.registerManifestAddedBasicBlock(*ThenTI->
getParent());
12530 A.registerManifestAddedBasicBlock(*IP->getParent());
12536 A.registerManifestAddedBasicBlock(*ElseBB);
12538 SplitTI->replaceUsesOfWith(CBBB, ElseBB);
12543 CastInst *RetBC =
nullptr;
12544 CallInst *NewCall =
nullptr;
12549 NumIndirectCallsPromoted++;
12557 auto AttachCalleeMetadata = [&](CallBase &IndirectCB) {
12558 if (!AllCalleesKnown)
12559 return ChangeStatus::UNCHANGED;
12560 MDBuilder MDB(IndirectCB.getContext());
12561 MDNode *Callees = MDB.createCallees(SkippedAssumedCallees);
12562 IndirectCB.setMetadata(LLVMContext::MD_callees, Callees);
12563 return ChangeStatus::CHANGED;
12566 if (!SpecializedForAnyCallees)
12567 return AttachCalleeMetadata(*CB);
12570 if (SpecializedForAllCallees) {
12573 new UnreachableInst(IP->getContext(), IP);
12574 IP->eraseFromParent();
12577 CBClone->setName(CB->
getName());
12578 CBClone->insertBefore(*IP->getParent(), IP);
12579 NewCalls.
push_back({CBClone,
nullptr});
12580 AttachCalleeMetadata(*CBClone);
12587 CB->
getParent()->getFirstInsertionPt());
12588 for (
auto &It : NewCalls) {
12589 CallBase *NewCall = It.first;
12590 Instruction *CallRet = It.second ? It.second : It.first;
12602 A.deleteAfterManifest(*CB);
12603 Changed = ChangeStatus::CHANGED;
12609 const std::string getAsStr(Attributor *
A)
const override {
12610 return std::string(AllCalleesKnown ?
"eliminate" :
"specialize") +
12611 " indirect call site with " + std::to_string(AssumedCallees.size()) +
12615 void trackStatistics()
const override {
12616 if (AllCalleesKnown) {
12618 Eliminated, CallSites,
12619 "Number of indirect call sites eliminated via specialization")
12622 "Number of indirect call sites specialized")
12626 bool foreachCallee(function_ref<
bool(Function *)> CB)
const override {
12627 return isValidState() && AllCalleesKnown &&
all_of(AssumedCallees, CB);
12632 DenseMap<Function *, std::optional<bool>> FilterResults;
12636 SmallSetVector<Function *, 4> PotentialCallees;
12640 SmallSetVector<Function *, 4> AssumedCallees;
12644 bool AllCalleesKnown =
true;
12651struct AAInvariantLoadPointerImpl
12652 :
public StateWrapper<BitIntegerState<uint8_t, 15>,
12653 AAInvariantLoadPointer> {
12657 IS_NOALIAS = 1 << 0,
12660 IS_NOEFFECT = 1 << 1,
12662 IS_LOCALLY_INVARIANT = 1 << 2,
12664 IS_LOCALLY_CONSTRAINED = 1 << 3,
12666 IS_BEST_STATE = IS_NOALIAS | IS_NOEFFECT | IS_LOCALLY_INVARIANT |
12667 IS_LOCALLY_CONSTRAINED,
12669 static_assert(getBestState() == IS_BEST_STATE,
"Unexpected best state");
12672 StateWrapper<BitIntegerState<uint8_t, 15>, AAInvariantLoadPointer>;
12676 AAInvariantLoadPointerImpl(
const IRPosition &IRP, Attributor &
A)
12679 bool isKnownInvariant()
const final {
12680 return isKnownLocallyInvariant() && isKnown(IS_LOCALLY_CONSTRAINED);
12683 bool isKnownLocallyInvariant()
const final {
12684 if (isKnown(IS_LOCALLY_INVARIANT))
12686 return isKnown(IS_NOALIAS | IS_NOEFFECT);
12689 bool isAssumedInvariant()
const final {
12690 return isAssumedLocallyInvariant() && isAssumed(IS_LOCALLY_CONSTRAINED);
12693 bool isAssumedLocallyInvariant()
const final {
12694 if (isAssumed(IS_LOCALLY_INVARIANT))
12696 return isAssumed(IS_NOALIAS | IS_NOEFFECT);
12703 if (requiresNoAlias() && !isAssumed(IS_NOALIAS))
12704 return indicatePessimisticFixpoint();
12708 Changed |= updateLocalInvariance(
A);
12714 if (!isKnownInvariant())
12715 return ChangeStatus::UNCHANGED;
12718 const Value *Ptr = &getAssociatedValue();
12719 const auto TagInvariantLoads = [&](
const Use &
U,
bool &) {
12720 if (
U.get() != Ptr)
12728 if (!
A.isRunOn(
I->getFunction()))
12731 if (
I->hasMetadata(LLVMContext::MD_invariant_load))
12735 LI->setMetadata(LLVMContext::MD_invariant_load,
12737 Changed = ChangeStatus::CHANGED;
12742 (void)
A.checkForAllUses(TagInvariantLoads, *
this, *Ptr);
12747 const std::string getAsStr(Attributor *)
const override {
12748 if (isKnownInvariant())
12749 return "load-invariant pointer";
12750 return "non-invariant pointer";
12754 void trackStatistics()
const override {}
12758 bool requiresNoAlias()
const {
12759 switch (getPositionKind()) {
12765 case IRP_CALL_SITE:
12767 case IRP_CALL_SITE_RETURNED: {
12772 case IRP_ARGUMENT: {
12773 const Function *
F = getAssociatedFunction();
12774 assert(
F &&
"no associated function for argument");
12780 bool isExternal()
const {
12781 const Function *
F = getAssociatedFunction();
12785 getPositionKind() != IRP_CALL_SITE_RETURNED;
12789 if (isKnown(IS_NOALIAS) || !isAssumed(IS_NOALIAS))
12790 return ChangeStatus::UNCHANGED;
12793 if (
const auto *ANoAlias =
A.getOrCreateAAFor<AANoAlias>(
12794 getIRPosition(),
this, DepClassTy::REQUIRED)) {
12795 if (ANoAlias->isKnownNoAlias()) {
12796 addKnownBits(IS_NOALIAS);
12797 return ChangeStatus::CHANGED;
12800 if (!ANoAlias->isAssumedNoAlias()) {
12801 removeAssumedBits(IS_NOALIAS);
12802 return ChangeStatus::CHANGED;
12805 return ChangeStatus::UNCHANGED;
12810 if (
const Argument *Arg = getAssociatedArgument()) {
12812 addKnownBits(IS_NOALIAS);
12813 return ChangeStatus::UNCHANGED;
12818 removeAssumedBits(IS_NOALIAS);
12819 return ChangeStatus::CHANGED;
12822 return ChangeStatus::UNCHANGED;
12826 if (isKnown(IS_NOEFFECT) || !isAssumed(IS_NOEFFECT))
12827 return ChangeStatus::UNCHANGED;
12829 if (!getAssociatedFunction())
12830 return indicatePessimisticFixpoint();
12833 return indicatePessimisticFixpoint();
12835 const auto HasNoEffectLoads = [&](
const Use &
U,
bool &) {
12837 return !LI || !LI->mayHaveSideEffects();
12839 if (!
A.checkForAllUses(HasNoEffectLoads, *
this, getAssociatedValue()))
12840 return indicatePessimisticFixpoint();
12842 if (
const auto *AMemoryBehavior =
A.getOrCreateAAFor<AAMemoryBehavior>(
12843 getIRPosition(),
this, DepClassTy::REQUIRED)) {
12846 if (!AMemoryBehavior->isAssumedReadOnly())
12847 return indicatePessimisticFixpoint();
12849 if (AMemoryBehavior->isKnownReadOnly()) {
12850 addKnownBits(IS_NOEFFECT);
12851 return ChangeStatus::UNCHANGED;
12854 return ChangeStatus::UNCHANGED;
12857 if (
const Argument *Arg = getAssociatedArgument()) {
12859 addKnownBits(IS_NOEFFECT);
12860 return ChangeStatus::UNCHANGED;
12865 return indicatePessimisticFixpoint();
12868 return ChangeStatus::UNCHANGED;
12872 if (isKnown(IS_LOCALLY_INVARIANT) || !isAssumed(IS_LOCALLY_INVARIANT))
12873 return ChangeStatus::UNCHANGED;
12876 const auto *AUO =
A.getOrCreateAAFor<AAUnderlyingObjects>(
12877 getIRPosition(),
this, DepClassTy::REQUIRED);
12879 return ChangeStatus::UNCHANGED;
12881 bool UsedAssumedInformation =
false;
12882 const auto IsLocallyInvariantLoadIfPointer = [&](
const Value &
V) {
12883 if (!
V.getType()->isPointerTy())
12885 const auto *IsInvariantLoadPointer =
12887 DepClassTy::REQUIRED);
12889 if (!IsInvariantLoadPointer)
12892 if (IsInvariantLoadPointer->isKnownLocallyInvariant())
12894 if (!IsInvariantLoadPointer->isAssumedLocallyInvariant())
12897 UsedAssumedInformation =
true;
12900 if (!AUO->forallUnderlyingObjects(IsLocallyInvariantLoadIfPointer))
12901 return indicatePessimisticFixpoint();
12907 if (!IsLocallyInvariantLoadIfPointer(*Arg))
12908 return indicatePessimisticFixpoint();
12913 if (!UsedAssumedInformation) {
12915 addKnownBits(IS_LOCALLY_INVARIANT);
12916 return ChangeStatus::CHANGED;
12919 return ChangeStatus::UNCHANGED;
12923struct AAInvariantLoadPointerFloating final : AAInvariantLoadPointerImpl {
12924 AAInvariantLoadPointerFloating(
const IRPosition &IRP, Attributor &
A)
12925 : AAInvariantLoadPointerImpl(IRP,
A) {}
12928struct AAInvariantLoadPointerReturned final : AAInvariantLoadPointerImpl {
12929 AAInvariantLoadPointerReturned(
const IRPosition &IRP, Attributor &
A)
12930 : AAInvariantLoadPointerImpl(IRP,
A) {}
12933 removeAssumedBits(IS_LOCALLY_CONSTRAINED);
12937struct AAInvariantLoadPointerCallSiteReturned final
12938 : AAInvariantLoadPointerImpl {
12939 AAInvariantLoadPointerCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
12940 : AAInvariantLoadPointerImpl(IRP,
A) {}
12943 const Function *
F = getAssociatedFunction();
12944 assert(
F &&
"no associated function for return from call");
12946 if (!
F->isDeclaration() && !
F->isIntrinsic())
12947 return AAInvariantLoadPointerImpl::initialize(
A);
12952 return AAInvariantLoadPointerImpl::initialize(
A);
12954 if (
F->onlyReadsMemory() &&
F->hasNoSync())
12955 return AAInvariantLoadPointerImpl::initialize(
A);
12959 indicatePessimisticFixpoint();
12963struct AAInvariantLoadPointerArgument final : AAInvariantLoadPointerImpl {
12964 AAInvariantLoadPointerArgument(
const IRPosition &IRP, Attributor &
A)
12965 : AAInvariantLoadPointerImpl(IRP,
A) {}
12968 const Function *
F = getAssociatedFunction();
12969 assert(
F &&
"no associated function for argument");
12972 addKnownBits(IS_LOCALLY_CONSTRAINED);
12976 if (!
F->hasLocalLinkage())
12977 removeAssumedBits(IS_LOCALLY_CONSTRAINED);
12981struct AAInvariantLoadPointerCallSiteArgument final
12982 : AAInvariantLoadPointerImpl {
12983 AAInvariantLoadPointerCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
12984 : AAInvariantLoadPointerImpl(IRP,
A) {}
12991template <
typename InstType>
12992static bool makeChange(Attributor &
A, InstType *MemInst,
const Use &U,
12993 Value *OriginalValue, PointerType *NewPtrTy,
12994 bool UseOriginalValue) {
12995 if (
U.getOperandNo() != InstType::getPointerOperandIndex())
12998 if (MemInst->isVolatile()) {
12999 auto *
TTI =
A.getInfoCache().getAnalysisResultForFunction<TargetIRAnalysis>(
13000 *MemInst->getFunction());
13001 unsigned NewAS = NewPtrTy->getPointerAddressSpace();
13006 if (UseOriginalValue) {
13007 A.changeUseAfterManifest(
const_cast<Use &
>(U), *OriginalValue);
13011 Instruction *CastInst =
new AddrSpaceCastInst(OriginalValue, NewPtrTy);
13013 A.changeUseAfterManifest(
const_cast<Use &
>(U), *CastInst);
13017struct AAAddressSpaceImpl :
public AAAddressSpace {
13018 AAAddressSpaceImpl(
const IRPosition &IRP, Attributor &
A)
13019 : AAAddressSpace(IRP,
A) {}
13022 assert(isValidState() &&
"the AA is invalid");
13023 return AssumedAddressSpace;
13028 assert(getAssociatedType()->isPtrOrPtrVectorTy() &&
13029 "Associated value is not a pointer");
13031 if (!
A.getInfoCache().getFlatAddressSpace().has_value()) {
13032 indicatePessimisticFixpoint();
13036 unsigned FlatAS =
A.getInfoCache().getFlatAddressSpace().value();
13037 unsigned AS = getAssociatedType()->getPointerAddressSpace();
13038 if (AS != FlatAS) {
13039 [[maybe_unused]]
bool R = takeAddressSpace(AS);
13040 assert(R &&
"The take should happen");
13041 indicateOptimisticFixpoint();
13046 uint32_t OldAddressSpace = AssumedAddressSpace;
13047 unsigned FlatAS =
A.getInfoCache().getFlatAddressSpace().value();
13049 auto CheckAddressSpace = [&](
Value &
Obj) {
13055 unsigned ObjAS =
Obj.getType()->getPointerAddressSpace();
13056 if (ObjAS != FlatAS)
13057 return takeAddressSpace(ObjAS);
13071 A.getInfoCache().getAnalysisResultForFunction<TargetIRAnalysis>(*F);
13073 if (AssumedAS != ~0U)
13074 return takeAddressSpace(AssumedAS);
13078 return takeAddressSpace(FlatAS);
13081 auto *AUO =
A.getOrCreateAAFor<AAUnderlyingObjects>(getIRPosition(),
this,
13082 DepClassTy::REQUIRED);
13083 if (!AUO->forallUnderlyingObjects(CheckAddressSpace))
13084 return indicatePessimisticFixpoint();
13086 return OldAddressSpace == AssumedAddressSpace ? ChangeStatus::UNCHANGED
13087 : ChangeStatus::CHANGED;
13094 if (NewAS == InvalidAddressSpace ||
13096 return ChangeStatus::UNCHANGED;
13098 unsigned FlatAS =
A.getInfoCache().getFlatAddressSpace().value();
13100 Value *AssociatedValue = &getAssociatedValue();
13101 Value *OriginalValue = peelAddrspacecast(AssociatedValue, FlatAS);
13104 PointerType::get(getAssociatedType()->
getContext(), NewAS);
13105 bool UseOriginalValue =
13110 auto Pred = [&](
const Use &
U,
bool &) {
13111 if (
U.get() != AssociatedValue)
13122 makeChange(
A, LI, U, OriginalValue, NewPtrTy, UseOriginalValue);
13125 makeChange(
A, SI, U, OriginalValue, NewPtrTy, UseOriginalValue);
13128 makeChange(
A, RMW, U, OriginalValue, NewPtrTy, UseOriginalValue);
13131 makeChange(
A, CmpX, U, OriginalValue, NewPtrTy, UseOriginalValue);
13138 (void)
A.checkForAllUses(Pred, *
this, getAssociatedValue(),
13141 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
13145 const std::string getAsStr(Attributor *
A)
const override {
13146 if (!isValidState())
13147 return "addrspace(<invalid>)";
13148 return "addrspace(" +
13149 (AssumedAddressSpace == InvalidAddressSpace
13151 : std::to_string(AssumedAddressSpace)) +
13156 uint32_t AssumedAddressSpace = InvalidAddressSpace;
13158 bool takeAddressSpace(uint32_t AS) {
13159 if (AssumedAddressSpace == InvalidAddressSpace) {
13160 AssumedAddressSpace = AS;
13163 return AssumedAddressSpace == AS;
13166 static Value *peelAddrspacecast(
Value *V,
unsigned FlatAS) {
13168 assert(
I->getSrcAddressSpace() != FlatAS &&
13169 "there should not be flat AS -> non-flat AS");
13170 return I->getPointerOperand();
13173 if (
C->getOpcode() == Instruction::AddrSpaceCast) {
13174 assert(
C->getOperand(0)->getType()->getPointerAddressSpace() !=
13176 "there should not be flat AS -> non-flat AS X");
13177 return C->getOperand(0);
13183struct AAAddressSpaceFloating final : AAAddressSpaceImpl {
13184 AAAddressSpaceFloating(
const IRPosition &IRP, Attributor &
A)
13185 : AAAddressSpaceImpl(IRP,
A) {}
13187 void trackStatistics()
const override {
13192struct AAAddressSpaceReturned final : AAAddressSpaceImpl {
13193 AAAddressSpaceReturned(
const IRPosition &IRP, Attributor &
A)
13194 : AAAddressSpaceImpl(IRP,
A) {}
13200 (void)indicatePessimisticFixpoint();
13203 void trackStatistics()
const override {
13208struct AAAddressSpaceCallSiteReturned final : AAAddressSpaceImpl {
13209 AAAddressSpaceCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
13210 : AAAddressSpaceImpl(IRP,
A) {}
13212 void trackStatistics()
const override {
13217struct AAAddressSpaceArgument final : AAAddressSpaceImpl {
13218 AAAddressSpaceArgument(
const IRPosition &IRP, Attributor &
A)
13219 : AAAddressSpaceImpl(IRP,
A) {}
13224struct AAAddressSpaceCallSiteArgument final : AAAddressSpaceImpl {
13225 AAAddressSpaceCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
13226 : AAAddressSpaceImpl(IRP,
A) {}
13232 (void)indicatePessimisticFixpoint();
13235 void trackStatistics()
const override {
13250struct AANoAliasAddrSpaceImpl :
public AANoAliasAddrSpace {
13251 AANoAliasAddrSpaceImpl(
const IRPosition &IRP, Attributor &
A)
13252 : AANoAliasAddrSpace(IRP,
A) {}
13255 assert(getAssociatedType()->isPtrOrPtrVectorTy() &&
13256 "Associated value is not a pointer");
13260 std::optional<unsigned> FlatAS =
A.getInfoCache().getFlatAddressSpace();
13261 if (!FlatAS.has_value()) {
13262 indicatePessimisticFixpoint();
13268 unsigned AS = getAssociatedType()->getPointerAddressSpace();
13269 if (AS != *FlatAS) {
13271 indicateOptimisticFixpoint();
13276 unsigned FlatAS =
A.getInfoCache().getFlatAddressSpace().value();
13277 uint32_t OldAssumed = getAssumed();
13279 auto CheckAddressSpace = [&](
Value &
Obj) {
13283 unsigned AS =
Obj.getType()->getPointerAddressSpace();
13287 removeAS(
Obj.getType()->getPointerAddressSpace());
13291 const AAUnderlyingObjects *AUO =
A.getOrCreateAAFor<AAUnderlyingObjects>(
13292 getIRPosition(),
this, DepClassTy::REQUIRED);
13294 return indicatePessimisticFixpoint();
13296 return OldAssumed == getAssumed() ? ChangeStatus::UNCHANGED
13297 : ChangeStatus::CHANGED;
13302 unsigned FlatAS =
A.getInfoCache().getFlatAddressSpace().value();
13304 unsigned AS = getAssociatedType()->getPointerAddressSpace();
13305 if (AS != FlatAS ||
Map.empty())
13306 return ChangeStatus::UNCHANGED;
13308 LLVMContext &Ctx = getAssociatedValue().getContext();
13309 MDNode *NoAliasASNode =
nullptr;
13310 MDBuilder MDB(Ctx);
13312 for (RangeMap::const_iterator
I =
Map.begin();
I !=
Map.end();
I++) {
13315 unsigned Upper =
I.stop();
13316 unsigned Lower =
I.start();
13317 if (!NoAliasASNode) {
13318 NoAliasASNode = MDB.createRange(APInt(32,
Lower), APInt(32,
Upper + 1));
13321 MDNode *ASRange = MDB.createRange(APInt(32,
Lower), APInt(32,
Upper + 1));
13325 Value *AssociatedValue = &getAssociatedValue();
13328 auto AddNoAliasAttr = [&](
const Use &
U,
bool &) {
13329 if (
U.get() != AssociatedValue)
13332 if (!Inst || Inst->
hasMetadata(LLVMContext::MD_noalias_addrspace))
13339 Inst->
setMetadata(LLVMContext::MD_noalias_addrspace, NoAliasASNode);
13343 (void)
A.checkForAllUses(AddNoAliasAttr, *
this, *AssociatedValue,
13345 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
13349 const std::string getAsStr(Attributor *
A)
const override {
13350 if (!isValidState())
13351 return "<invalid>";
13353 raw_string_ostream OS(Str);
13354 OS <<
"CanNotBeAddrSpace(";
13355 for (RangeMap::const_iterator
I =
Map.begin();
I !=
Map.end();
I++) {
13356 unsigned Upper =
I.stop();
13357 unsigned Lower =
I.start();
13358 OS <<
' ' <<
'[' <<
Upper <<
',' <<
Lower + 1 <<
')';
13365 void removeAS(
unsigned AS) {
13366 RangeMap::iterator
I =
Map.find(AS);
13368 if (
I !=
Map.end()) {
13369 unsigned Upper =
I.stop();
13370 unsigned Lower =
I.start();
13374 if (AS != ~((
unsigned)0) && AS + 1 <=
Upper)
13376 if (AS != 0 &&
Lower <= AS - 1)
13381 void resetASRanges(Attributor &
A) {
13383 Map.insert(0,
A.getInfoCache().getMaxAddrSpace(),
true);
13387struct AANoAliasAddrSpaceFloating final : AANoAliasAddrSpaceImpl {
13388 AANoAliasAddrSpaceFloating(
const IRPosition &IRP, Attributor &
A)
13389 : AANoAliasAddrSpaceImpl(IRP,
A) {}
13391 void trackStatistics()
const override {
13396struct AANoAliasAddrSpaceReturned final : AANoAliasAddrSpaceImpl {
13397 AANoAliasAddrSpaceReturned(
const IRPosition &IRP, Attributor &
A)
13398 : AANoAliasAddrSpaceImpl(IRP,
A) {}
13400 void trackStatistics()
const override {
13405struct AANoAliasAddrSpaceCallSiteReturned final : AANoAliasAddrSpaceImpl {
13406 AANoAliasAddrSpaceCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
13407 : AANoAliasAddrSpaceImpl(IRP,
A) {}
13409 void trackStatistics()
const override {
13414struct AANoAliasAddrSpaceArgument final : AANoAliasAddrSpaceImpl {
13415 AANoAliasAddrSpaceArgument(
const IRPosition &IRP, Attributor &
A)
13416 : AANoAliasAddrSpaceImpl(IRP,
A) {}
13418 void trackStatistics()
const override {
13423struct AANoAliasAddrSpaceCallSiteArgument final : AANoAliasAddrSpaceImpl {
13424 AANoAliasAddrSpaceCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
13425 : AANoAliasAddrSpaceImpl(IRP,
A) {}
13427 void trackStatistics()
const override {
13434struct AAAllocationInfoImpl :
public AAAllocationInfo {
13435 AAAllocationInfoImpl(
const IRPosition &IRP, Attributor &
A)
13436 : AAAllocationInfo(IRP,
A) {}
13438 std::optional<TypeSize> getAllocatedSize()
const override {
13439 assert(isValidState() &&
"the AA is invalid");
13440 return AssumedAllocatedSize;
13443 std::optional<TypeSize> findInitialAllocationSize(Instruction *
I,
13444 const DataLayout &
DL) {
13447 switch (
I->getOpcode()) {
13448 case Instruction::Alloca: {
13453 return std::nullopt;
13459 const IRPosition &IRP = getIRPosition();
13464 return indicatePessimisticFixpoint();
13466 bool IsKnownNoCapture;
13468 A,
this, IRP, DepClassTy::OPTIONAL, IsKnownNoCapture))
13469 return indicatePessimisticFixpoint();
13471 const AAPointerInfo *PI =
13472 A.getOrCreateAAFor<AAPointerInfo>(IRP, *
this, DepClassTy::REQUIRED);
13475 return indicatePessimisticFixpoint();
13478 return indicatePessimisticFixpoint();
13480 const DataLayout &
DL =
A.getDataLayout();
13481 const auto AllocationSize = findInitialAllocationSize(
I,
DL);
13484 if (!AllocationSize)
13485 return indicatePessimisticFixpoint();
13489 if (*AllocationSize == 0)
13490 return indicatePessimisticFixpoint();
13496 return indicatePessimisticFixpoint();
13498 if (BinSize == 0) {
13499 auto NewAllocationSize = std::make_optional<TypeSize>(0,
false);
13500 if (!changeAllocationSize(NewAllocationSize))
13501 return ChangeStatus::UNCHANGED;
13502 return ChangeStatus::CHANGED;
13506 const auto &It = PI->
begin();
13509 if (It->first.Offset != 0)
13510 return indicatePessimisticFixpoint();
13512 uint64_t SizeOfBin = It->first.Offset + It->first.Size;
13514 if (SizeOfBin >= *AllocationSize)
13515 return indicatePessimisticFixpoint();
13517 auto NewAllocationSize = std::make_optional<TypeSize>(SizeOfBin * 8,
false);
13519 if (!changeAllocationSize(NewAllocationSize))
13520 return ChangeStatus::UNCHANGED;
13522 return ChangeStatus::CHANGED;
13528 assert(isValidState() &&
13529 "Manifest should only be called if the state is valid.");
13533 auto FixedAllocatedSizeInBits = getAllocatedSize()->getFixedValue();
13535 unsigned long NumBytesToAllocate = (FixedAllocatedSizeInBits + 7) / 8;
13537 switch (
I->getOpcode()) {
13539 case Instruction::Alloca: {
13543 Type *CharType = Type::getInt8Ty(
I->getContext());
13545 auto *NumBytesToValue =
13546 ConstantInt::get(
I->getContext(), APInt(32, NumBytesToAllocate));
13549 insertPt = std::next(insertPt);
13550 AllocaInst *NewAllocaInst =
13555 return ChangeStatus::CHANGED;
13563 return ChangeStatus::UNCHANGED;
13567 const std::string getAsStr(Attributor *
A)
const override {
13568 if (!isValidState())
13569 return "allocationinfo(<invalid>)";
13570 return "allocationinfo(" +
13571 (AssumedAllocatedSize == HasNoAllocationSize
13573 : std::to_string(AssumedAllocatedSize->getFixedValue())) +
13578 std::optional<TypeSize> AssumedAllocatedSize = HasNoAllocationSize;
13582 bool changeAllocationSize(std::optional<TypeSize>
Size) {
13583 if (AssumedAllocatedSize == HasNoAllocationSize ||
13584 AssumedAllocatedSize !=
Size) {
13585 AssumedAllocatedSize =
Size;
13592struct AAAllocationInfoFloating : AAAllocationInfoImpl {
13593 AAAllocationInfoFloating(
const IRPosition &IRP, Attributor &
A)
13594 : AAAllocationInfoImpl(IRP,
A) {}
13596 void trackStatistics()
const override {
13601struct AAAllocationInfoReturned : AAAllocationInfoImpl {
13602 AAAllocationInfoReturned(
const IRPosition &IRP, Attributor &
A)
13603 : AAAllocationInfoImpl(IRP,
A) {}
13609 (void)indicatePessimisticFixpoint();
13612 void trackStatistics()
const override {
13617struct AAAllocationInfoCallSiteReturned : AAAllocationInfoImpl {
13618 AAAllocationInfoCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
13619 : AAAllocationInfoImpl(IRP,
A) {}
13621 void trackStatistics()
const override {
13626struct AAAllocationInfoArgument : AAAllocationInfoImpl {
13627 AAAllocationInfoArgument(
const IRPosition &IRP, Attributor &
A)
13628 : AAAllocationInfoImpl(IRP,
A) {}
13630 void trackStatistics()
const override {
13635struct AAAllocationInfoCallSiteArgument : AAAllocationInfoImpl {
13636 AAAllocationInfoCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
13637 : AAAllocationInfoImpl(IRP,
A) {}
13642 (void)indicatePessimisticFixpoint();
13645 void trackStatistics()
const override {
13694#define SWITCH_PK_INV(CLASS, PK, POS_NAME) \
13695 case IRPosition::PK: \
13696 llvm_unreachable("Cannot create " #CLASS " for a " POS_NAME " position!");
13698#define SWITCH_PK_CREATE(CLASS, IRP, PK, SUFFIX) \
13699 case IRPosition::PK: \
13700 AA = new (A.Allocator) CLASS##SUFFIX(IRP, A); \
13704#define CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13705 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13706 CLASS *AA = nullptr; \
13707 switch (IRP.getPositionKind()) { \
13708 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13709 SWITCH_PK_INV(CLASS, IRP_FLOAT, "floating") \
13710 SWITCH_PK_INV(CLASS, IRP_ARGUMENT, "argument") \
13711 SWITCH_PK_INV(CLASS, IRP_RETURNED, "returned") \
13712 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_RETURNED, "call site returned") \
13713 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_ARGUMENT, "call site argument") \
13714 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
13715 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE, CallSite) \
13720#define CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13721 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13722 CLASS *AA = nullptr; \
13723 switch (IRP.getPositionKind()) { \
13724 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13725 SWITCH_PK_INV(CLASS, IRP_FUNCTION, "function") \
13726 SWITCH_PK_INV(CLASS, IRP_CALL_SITE, "call site") \
13727 SWITCH_PK_CREATE(CLASS, IRP, IRP_FLOAT, Floating) \
13728 SWITCH_PK_CREATE(CLASS, IRP, IRP_ARGUMENT, Argument) \
13729 SWITCH_PK_CREATE(CLASS, IRP, IRP_RETURNED, Returned) \
13730 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_RETURNED, CallSiteReturned) \
13731 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_ARGUMENT, CallSiteArgument) \
13736#define CREATE_ABSTRACT_ATTRIBUTE_FOR_ONE_POSITION(POS, SUFFIX, CLASS) \
13737 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13738 CLASS *AA = nullptr; \
13739 switch (IRP.getPositionKind()) { \
13740 SWITCH_PK_CREATE(CLASS, IRP, POS, SUFFIX) \
13742 llvm_unreachable("Cannot create " #CLASS " for position otherthan " #POS \
13748#define CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13749 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13750 CLASS *AA = nullptr; \
13751 switch (IRP.getPositionKind()) { \
13752 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13753 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
13754 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE, CallSite) \
13755 SWITCH_PK_CREATE(CLASS, IRP, IRP_FLOAT, Floating) \
13756 SWITCH_PK_CREATE(CLASS, IRP, IRP_ARGUMENT, Argument) \
13757 SWITCH_PK_CREATE(CLASS, IRP, IRP_RETURNED, Returned) \
13758 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_RETURNED, CallSiteReturned) \
13759 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_ARGUMENT, CallSiteArgument) \
13764#define CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13765 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13766 CLASS *AA = nullptr; \
13767 switch (IRP.getPositionKind()) { \
13768 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13769 SWITCH_PK_INV(CLASS, IRP_ARGUMENT, "argument") \
13770 SWITCH_PK_INV(CLASS, IRP_FLOAT, "floating") \
13771 SWITCH_PK_INV(CLASS, IRP_RETURNED, "returned") \
13772 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_RETURNED, "call site returned") \
13773 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_ARGUMENT, "call site argument") \
13774 SWITCH_PK_INV(CLASS, IRP_CALL_SITE, "call site") \
13775 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
13780#define CREATE_NON_RET_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13781 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13782 CLASS *AA = nullptr; \
13783 switch (IRP.getPositionKind()) { \
13784 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13785 SWITCH_PK_INV(CLASS, IRP_RETURNED, "returned") \
13786 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
13787 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE, CallSite) \
13788 SWITCH_PK_CREATE(CLASS, IRP, IRP_FLOAT, Floating) \
13789 SWITCH_PK_CREATE(CLASS, IRP, IRP_ARGUMENT, Argument) \
13790 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_RETURNED, CallSiteReturned) \
13791 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_ARGUMENT, CallSiteArgument) \
13843#undef CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION
13844#undef CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION
13845#undef CREATE_NON_RET_ABSTRACT_ATTRIBUTE_FOR_POSITION
13846#undef CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION
13847#undef CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION
13848#undef CREATE_ABSTRACT_ATTRIBUTE_FOR_ONE_POSITION
13849#undef SWITCH_PK_CREATE
13850#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)
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...
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)
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 if the block is well formed or null if the block is not well forme...
BinaryOps getOpcode() const
Conditional or Unconditional Branch instruction.
unsigned getNumSuccessors() const
static BranchInst * Create(BasicBlock *IfTrue, InsertPosition InsertBefore=nullptr)
BasicBlock * getSuccessor(unsigned i) const
Value * getCondition() 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
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.
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.
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 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 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.
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 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.
LLVM_ABI bool isIntrinsicReturningPointerAliasingArgumentWithoutCapturing(const CallBase *Call, bool MustPreserveNullness)
{launder,strip}.invariant.group returns pointer that aliases its argument, and it only captures point...
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.
constexpr StringRef AssumptionAttrKey
The key we use for assumption attributes.
constexpr bool isCallableCC(CallingConv::ID CC)
GenericCycleInfo< SSAContext > CycleInfo
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.
static LLVM_ABI bool isNoSyncIntrinsic(const Instruction *I)
Helper function specific for intrinsics which are potentially volatile.
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
static Access getTombstoneKey()
DenseMapInfo< Instruction * > Base
static bool isEqual(const Access &LHS, const Access &RHS)
static Access getEmptyKey()
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 Access getTombstoneKey()
static unsigned getHashValue(const Access &A)
static Access getEmptyKey()
AAPointerInfo::Access Access
static bool isEqual(const Access &LHS, const Access &RHS)
static bool isEqual(const AA::RangeTy &A, const AA::RangeTy B)
static AA::RangeTy getTombstoneKey()
static unsigned getHashValue(const AA::RangeTy &Range)
static AA::RangeTy getEmptyKey()
static ReachabilityQueryInfo< ToTy > EmptyKey
static ReachabilityQueryInfo< ToTy > TombstoneKey
static ReachabilityQueryInfo< ToTy > * getEmptyKey()
DenseMapInfo< std::pair< const Instruction *, const ToTy * > > PairDMI
static ReachabilityQueryInfo< ToTy > * getTombstoneKey()
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
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.