55#include "llvm/IR/IntrinsicsAMDGPU.h"
56#include "llvm/IR/IntrinsicsNVPTX.h"
83#define DEBUG_TYPE "attributor"
87 cl::desc(
"Manifest Attributor internal string attributes."),
100 cl::desc(
"Maximum number of potential values to be "
101 "tracked for each position."),
106 "attributor-max-potential-values-iterations",
cl::Hidden,
108 "Maximum number of iterations we keep dismantling potential values."),
111STATISTIC(NumAAs,
"Number of abstract attributes created");
112STATISTIC(NumIndirectCallsPromoted,
"Number of indirect calls promoted");
127#define BUILD_STAT_MSG_IR_ATTR(TYPE, NAME) \
128 ("Number of " #TYPE " marked '" #NAME "'")
129#define BUILD_STAT_NAME(NAME, TYPE) NumIR##TYPE##_##NAME
130#define STATS_DECL_(NAME, MSG) STATISTIC(NAME, MSG);
131#define STATS_DECL(NAME, TYPE, MSG) \
132 STATS_DECL_(BUILD_STAT_NAME(NAME, TYPE), MSG);
133#define STATS_TRACK(NAME, TYPE) ++(BUILD_STAT_NAME(NAME, TYPE));
134#define STATS_DECLTRACK(NAME, TYPE, MSG) \
135 {STATS_DECL(NAME, TYPE, MSG) STATS_TRACK(NAME, TYPE)}
136#define STATS_DECLTRACK_ARG_ATTR(NAME) \
137 STATS_DECLTRACK(NAME, Arguments, BUILD_STAT_MSG_IR_ATTR(arguments, NAME))
138#define STATS_DECLTRACK_CSARG_ATTR(NAME) \
139 STATS_DECLTRACK(NAME, CSArguments, \
140 BUILD_STAT_MSG_IR_ATTR(call site arguments, NAME))
141#define STATS_DECLTRACK_FN_ATTR(NAME) \
142 STATS_DECLTRACK(NAME, Function, BUILD_STAT_MSG_IR_ATTR(functions, NAME))
143#define STATS_DECLTRACK_CS_ATTR(NAME) \
144 STATS_DECLTRACK(NAME, CS, BUILD_STAT_MSG_IR_ATTR(call site, NAME))
145#define STATS_DECLTRACK_FNRET_ATTR(NAME) \
146 STATS_DECLTRACK(NAME, FunctionReturn, \
147 BUILD_STAT_MSG_IR_ATTR(function returns, NAME))
148#define STATS_DECLTRACK_CSRET_ATTR(NAME) \
149 STATS_DECLTRACK(NAME, CSReturn, \
150 BUILD_STAT_MSG_IR_ATTR(call site returns, NAME))
151#define STATS_DECLTRACK_FLOATING_ATTR(NAME) \
152 STATS_DECLTRACK(NAME, Floating, \
153 ("Number of floating values known to be '" #NAME "'"))
158#define PIPE_OPERATOR(CLASS) \
159 raw_ostream &operator<<(raw_ostream &OS, const CLASS &AA) { \
160 return OS << static_cast<const AbstractAttribute &>(AA); \
217 bool HeaderOnly,
CycleRef *CPtr =
nullptr) {
220 auto *BB =
I->getParent();
237 if (
DL.getTypeSizeInBits(Ty) !=
DL.getTypeAllocSizeInBits(Ty))
262 StartPos +=
DL.getTypeAllocSizeInBits(ElTy);
272 bool AllowVolatile) {
273 if (!AllowVolatile &&
I->isVolatile())
277 return LI->getPointerOperand();
281 return SI->getPointerOperand();
285 return CXI->getPointerOperand();
289 return RMWI->getPointerOperand();
311 bool GetMinOffset,
bool AllowNonInbounds,
312 bool UseAssumed =
false) {
314 auto AttributorAnalysis = [&](
Value &V,
APInt &ROffset) ->
bool {
321 if (!ValueConstantRangeAA)
325 if (
Range.isFullSet())
331 ROffset =
Range.getSignedMin();
333 ROffset =
Range.getSignedMax();
344 const Value *Ptr, int64_t &BytesOffset,
349 true, AllowNonInbounds);
357template <
typename AAType,
typename StateType =
typename AAType::StateType,
359 bool RecurseForSelectAndPHI =
true>
361 Attributor &
A,
const AAType &QueryingAA, StateType &S,
363 LLVM_DEBUG(
dbgs() <<
"[Attributor] Clamp return value states for "
364 << QueryingAA <<
" into " << S <<
"\n");
366 assert((QueryingAA.getIRPosition().getPositionKind() ==
368 QueryingAA.getIRPosition().getPositionKind() ==
370 "Can only clamp returned value states for a function returned or call "
371 "site returned position!");
375 std::optional<StateType>
T;
378 auto CheckReturnValue = [&](
Value &RV) ->
bool {
392 <<
" AA: " <<
AA->getAsStr(&
A) <<
" @ " << RVPos <<
"\n");
393 const StateType &AAS =
AA->getState();
395 T = StateType::getBestState(AAS);
397 LLVM_DEBUG(
dbgs() <<
"[Attributor] AA State: " << AAS <<
" RV State: " <<
T
399 return T->isValidState();
402 if (!
A.checkForAllReturnedValues(CheckReturnValue, QueryingAA,
404 RecurseForSelectAndPHI))
405 S.indicatePessimisticFixpoint();
412template <
typename AAType,
typename BaseType,
413 typename StateType =
typename BaseType::StateType,
414 bool PropagateCallBaseContext =
false,
416 bool RecurseForSelectAndPHI =
true>
417struct AAReturnedFromReturnedValues :
public BaseType {
418 AAReturnedFromReturnedValues(
const IRPosition &IRP, Attributor &
A)
423 StateType S(StateType::getBestState(this->getState()));
425 RecurseForSelectAndPHI>(
427 PropagateCallBaseContext ? this->getCallBaseContext() : nullptr);
436template <
typename AAType,
typename StateType =
typename AAType::StateType,
438static void clampCallSiteArgumentStates(
Attributor &
A,
const AAType &QueryingAA,
440 LLVM_DEBUG(
dbgs() <<
"[Attributor] Clamp call site argument states for "
441 << QueryingAA <<
" into " << S <<
"\n");
443 assert(QueryingAA.getIRPosition().getPositionKind() ==
445 "Can only clamp call site argument states for an argument position!");
449 std::optional<StateType>
T;
452 unsigned ArgNo = QueryingAA.getIRPosition().getCallSiteArgNo();
472 LLVM_DEBUG(
dbgs() <<
"[Attributor] ACS: " << *ACS.getInstruction()
473 <<
" AA: " <<
AA->getAsStr(&
A) <<
" @" << ACSArgPos
475 const StateType &AAS =
AA->getState();
477 T = StateType::getBestState(AAS);
479 LLVM_DEBUG(
dbgs() <<
"[Attributor] AA State: " << AAS <<
" CSA State: " <<
T
481 return T->isValidState();
484 bool UsedAssumedInformation =
false;
485 if (!
A.checkForAllCallSites(CallSiteCheck, QueryingAA,
true,
486 UsedAssumedInformation))
487 S.indicatePessimisticFixpoint();
494template <
typename AAType,
typename BaseType,
495 typename StateType =
typename AAType::StateType,
497bool getArgumentStateFromCallBaseContext(
Attributor &
A,
501 "Expected an 'argument' position !");
507 assert(ArgNo >= 0 &&
"Invalid Arg No!");
521 const StateType &CBArgumentState =
522 static_cast<const StateType &
>(
AA->getState());
524 LLVM_DEBUG(
dbgs() <<
"[Attributor] Briding Call site context to argument"
525 <<
"Position:" << Pos <<
"CB Arg state:" << CBArgumentState
529 State ^= CBArgumentState;
534template <
typename AAType,
typename BaseType,
535 typename StateType =
typename AAType::StateType,
536 bool BridgeCallBaseContext =
false,
538struct AAArgumentFromCallSiteArguments :
public BaseType {
539 AAArgumentFromCallSiteArguments(
const IRPosition &IRP, Attributor &
A)
544 StateType S = StateType::getBestState(this->getState());
546 if (BridgeCallBaseContext) {
548 getArgumentStateFromCallBaseContext<AAType,
BaseType, StateType,
550 A, *
this, this->getIRPosition(), S);
554 clampCallSiteArgumentStates<AAType, StateType, IRAttributeKind>(
A, *
this,
564template <
typename AAType,
typename BaseType,
565 typename StateType =
typename BaseType::StateType,
566 bool IntroduceCallBaseContext =
false,
568struct AACalleeToCallSite :
public BaseType {
569 AACalleeToCallSite(
const IRPosition &IRP, Attributor &
A) :
BaseType(IRP,
A) {}
573 auto IRPKind = this->getIRPosition().getPositionKind();
576 "Can only wrap function returned positions for call site "
577 "returned positions!");
578 auto &S = this->getState();
581 if (IntroduceCallBaseContext)
582 LLVM_DEBUG(
dbgs() <<
"[Attributor] Introducing call base context:" << CB
587 for (
const Function *Callee : Callees) {
591 IntroduceCallBaseContext ? &CB :
nullptr)
593 *
Callee, IntroduceCallBaseContext ? &CB : nullptr);
595 if (Attribute::isEnumAttrKind(IRAttributeKind)) {
598 A,
this, FnPos, DepClassTy::REQUIRED, IsKnown))
604 A.getAAFor<AAType>(*
this, FnPos, DepClassTy::REQUIRED);
608 if (S.isAtFixpoint())
609 return S.isValidState();
613 if (!
A.checkForAllCallees(CalleePred, *
this, CB))
614 return S.indicatePessimisticFixpoint();
620template <
class AAType,
typename StateType =
typename AAType::StateType>
626 auto EIt = Explorer.
begin(CtxI), EEnd = Explorer.
end(CtxI);
627 for (
unsigned u = 0;
u <
Uses.size(); ++
u) {
631 if (Found &&
AA.followUseInMBEC(
A, U, UserI, State))
646template <
class AAType,
typename StateType =
typename AAType::StateType>
647static void followUsesInMBEC(AAType &
AA,
Attributor &
A, StateType &S,
649 const Value &Val =
AA.getIRPosition().getAssociatedValue();
654 A.getInfoCache().getMustBeExecutedContextExplorer();
660 for (
const Use &U : Val.
uses())
663 followUsesInContext<AAType>(
AA,
A, *Explorer, &CtxI,
Uses, S);
665 if (S.isAtFixpoint())
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;
776 R.indicatePessimisticFixpoint();
793 BS.indicateOptimisticFixpoint();
799 BS.indicatePessimisticFixpoint();
869 template <
typename F>
876 if (!
Range.mayOverlap(ItRange))
878 bool IsExact =
Range == ItRange && !
Range.offsetOrSizeAreUnknown();
879 for (
auto Index : It.getSecond()) {
889 template <
typename F>
900 for (
unsigned Index : LocalList->getSecond()) {
903 if (
Range.offsetAndSizeAreUnknown())
919 RemoteI = RemoteI ? RemoteI : &
I;
923 bool AccExists =
false;
925 for (
auto Index : LocalList) {
927 if (
A.getLocalInst() == &
I) {
936 <<
"[AAPointerInfo] Inserting access in new offset bins\n";);
938 for (
auto Key : ToAdd) {
945 AccessList.emplace_back(&
I, RemoteI, Ranges, Content, Kind, Ty);
947 "New Access should have been at AccIndex");
948 LocalList.push_back(AccIndex);
957 auto Before = Current;
959 if (Current == Before)
962 auto &ExistingRanges = Before.getRanges();
963 auto &NewRanges = Current.getRanges();
970 <<
"[AAPointerInfo] Removing access from old offset bins\n";);
977 "Expected bin to actually contain the Access.");
999struct AAPointerInfoImpl
1000 :
public StateWrapper<AA::PointerInfo::State, AAPointerInfo> {
1005 const std::string getAsStr(
Attributor *
A)
const override {
1006 return std::string(
"PointerInfo ") +
1007 (isValidState() ? (std::string(
"#") +
1008 std::to_string(OffsetBins.size()) +
" bins")
1013 [](int64_t O) {
return std::to_string(O); }),
1021 return AAPointerInfo::manifest(
A);
1024 const_bin_iterator
begin()
const override {
return State::begin(); }
1025 const_bin_iterator
end()
const override {
return State::end(); }
1026 int64_t numOffsetBins()
const override {
return State::numOffsetBins(); }
1027 bool reachesReturn()
const override {
1028 return !ReturnedOffsets.isUnassigned();
1030 void addReturnedOffsetsTo(OffsetInfo &OI)
const override {
1031 if (ReturnedOffsets.isUnknown()) {
1036 OffsetInfo MergedOI;
1037 for (
auto Offset : ReturnedOffsets) {
1038 OffsetInfo TmpOI = OI;
1040 MergedOI.merge(TmpOI);
1042 OI = std::move(MergedOI);
1045 ChangeStatus setReachesReturn(
const OffsetInfo &ReachedReturnedOffsets) {
1046 if (ReturnedOffsets.isUnknown())
1047 return ChangeStatus::UNCHANGED;
1048 if (ReachedReturnedOffsets.isUnknown()) {
1049 ReturnedOffsets.setUnknown();
1050 return ChangeStatus::CHANGED;
1052 if (ReturnedOffsets.merge(ReachedReturnedOffsets))
1053 return ChangeStatus::CHANGED;
1054 return ChangeStatus::UNCHANGED;
1057 bool forallInterferingAccesses(
1059 function_ref<
bool(
const AAPointerInfo::Access &,
bool)> CB)
1061 return State::forallInterferingAccesses(
Range, CB);
1064 bool forallInterferingAccesses(
1065 Attributor &
A,
const AbstractAttribute &QueryingAA, Instruction &
I,
1066 bool FindInterferingWrites,
bool FindInterferingReads,
1067 function_ref<
bool(
const Access &,
bool)> UserCB,
bool &HasBeenWrittenTo,
1069 function_ref<
bool(
const Access &)> SkipCB)
const override {
1070 HasBeenWrittenTo =
false;
1072 SmallPtrSet<const Access *, 8> DominatingWrites;
1080 const auto *ExecDomainAA =
A.lookupAAFor<AAExecutionDomain>(
1082 bool AllInSameNoSyncFn = IsAssumedNoSync;
1083 bool InstIsExecutedByInitialThreadOnly =
1084 ExecDomainAA && ExecDomainAA->isExecutedByInitialThreadOnly(
I);
1091 bool InstIsExecutedInAlignedRegion =
1092 FindInterferingReads && ExecDomainAA &&
1093 ExecDomainAA->isExecutedInAlignedRegion(
A,
I);
1095 if (InstIsExecutedInAlignedRegion || InstIsExecutedByInitialThreadOnly)
1096 A.recordDependence(*ExecDomainAA, QueryingAA, DepClassTy::OPTIONAL);
1098 InformationCache &InfoCache =
A.getInfoCache();
1099 bool IsThreadLocalObj =
1108 auto CanIgnoreThreadingForInst = [&](
const Instruction &
I) ->
bool {
1109 if (IsThreadLocalObj || AllInSameNoSyncFn)
1111 const auto *FnExecDomainAA =
1112 I.getFunction() == &
Scope
1114 :
A.lookupAAFor<AAExecutionDomain>(
1117 if (!FnExecDomainAA)
1119 if (InstIsExecutedInAlignedRegion ||
1120 (FindInterferingWrites &&
1121 FnExecDomainAA->isExecutedInAlignedRegion(
A,
I))) {
1122 A.recordDependence(*FnExecDomainAA, QueryingAA, DepClassTy::OPTIONAL);
1125 if (InstIsExecutedByInitialThreadOnly &&
1126 FnExecDomainAA->isExecutedByInitialThreadOnly(
I)) {
1127 A.recordDependence(*FnExecDomainAA, QueryingAA, DepClassTy::OPTIONAL);
1136 auto CanIgnoreThreading = [&](
const Access &Acc) ->
bool {
1137 return CanIgnoreThreadingForInst(*Acc.getRemoteInst()) ||
1138 (Acc.getRemoteInst() != Acc.getLocalInst() &&
1139 CanIgnoreThreadingForInst(*Acc.getLocalInst()));
1143 bool IsKnownNoRecurse;
1151 bool InstInKernel =
A.getInfoCache().isKernel(Scope);
1152 bool ObjHasKernelLifetime =
false;
1153 const bool UseDominanceReasoning =
1154 FindInterferingWrites && IsKnownNoRecurse;
1155 const DominatorTree *DT =
1164 unsigned VAS =
V->getType()->getPointerAddressSpace();
1175 std::function<bool(
const Function &)> IsLiveInCalleeCB;
1180 const Function *AIFn = AI->getFunction();
1181 ObjHasKernelLifetime =
A.getInfoCache().isKernel(*AIFn);
1182 bool IsKnownNoRecurse;
1185 IsKnownNoRecurse)) {
1186 IsLiveInCalleeCB = [AIFn](
const Function &Fn) {
return AIFn != &Fn; };
1191 ObjHasKernelLifetime = HasKernelLifetime(GV, *GV->getParent());
1192 if (ObjHasKernelLifetime)
1193 IsLiveInCalleeCB = [&
A](
const Function &Fn) {
1194 return !
A.getInfoCache().isKernel(Fn);
1202 auto AccessCB = [&](
const Access &Acc,
bool Exact) {
1203 Function *AccScope = Acc.getRemoteInst()->getFunction();
1204 bool AccInSameScope = AccScope == &
Scope;
1208 if (InstInKernel && ObjHasKernelLifetime && !AccInSameScope &&
1209 A.getInfoCache().isKernel(*AccScope))
1212 if (Exact && Acc.isMustAccess() && Acc.getRemoteInst() != &
I) {
1213 if (Acc.isWrite() || (
isa<LoadInst>(
I) && Acc.isWriteOrAssumption()))
1214 ExclusionSet.
insert(Acc.getRemoteInst());
1217 if ((!FindInterferingWrites || !Acc.isWriteOrAssumption()) &&
1218 (!FindInterferingReads || !Acc.isRead()))
1221 bool Dominates = FindInterferingWrites && DT && Exact &&
1222 Acc.isMustAccess() && AccInSameScope &&
1225 DominatingWrites.
insert(&Acc);
1229 AllInSameNoSyncFn &= Acc.getRemoteInst()->getFunction() == &
Scope;
1231 InterferingAccesses.
push_back({&Acc, Exact});
1234 if (!State::forallInterferingAccesses(
I, AccessCB,
Range))
1237 HasBeenWrittenTo = !DominatingWrites.
empty();
1241 for (
const Access *Acc : DominatingWrites) {
1242 if (!LeastDominatingWriteInst) {
1243 LeastDominatingWriteInst = Acc->getRemoteInst();
1244 }
else if (DT->
dominates(LeastDominatingWriteInst,
1245 Acc->getRemoteInst())) {
1246 LeastDominatingWriteInst = Acc->getRemoteInst();
1251 auto CanSkipAccess = [&](
const Access &Acc,
bool Exact) {
1252 if (SkipCB && SkipCB(Acc))
1254 if (!CanIgnoreThreading(Acc))
1260 bool ReadChecked = !FindInterferingReads;
1261 bool WriteChecked = !FindInterferingWrites;
1267 &ExclusionSet, IsLiveInCalleeCB))
1272 if (!WriteChecked) {
1274 &ExclusionSet, IsLiveInCalleeCB))
1275 WriteChecked =
true;
1289 if (!WriteChecked && HasBeenWrittenTo &&
1290 Acc.getRemoteInst()->getFunction() != &Scope) {
1292 const auto *FnReachabilityAA =
A.getAAFor<AAInterFnReachability>(
1294 if (FnReachabilityAA) {
1300 if (!FnReachabilityAA->instructionCanReach(
1301 A, *LeastDominatingWriteInst,
1302 *Acc.getRemoteInst()->getFunction(), &ExclusionSet))
1303 WriteChecked =
true;
1310 if (ReadChecked && WriteChecked)
1313 if (!DT || !UseDominanceReasoning)
1315 if (!DominatingWrites.count(&Acc))
1317 return LeastDominatingWriteInst != Acc.getRemoteInst();
1322 for (
auto &It : InterferingAccesses) {
1323 if ((!AllInSameNoSyncFn && !IsThreadLocalObj && !ExecDomainAA) ||
1324 !CanSkipAccess(*It.first, It.second)) {
1325 if (!UserCB(*It.first, It.second))
1333 const AAPointerInfo &OtherAA,
1335 using namespace AA::PointerInfo;
1337 return indicatePessimisticFixpoint();
1340 const auto &OtherAAImpl =
static_cast<const AAPointerInfoImpl &
>(OtherAA);
1341 bool IsByval = OtherAAImpl.getAssociatedArgument()->hasByValAttr();
1342 Changed |= setReachesReturn(OtherAAImpl.ReturnedOffsets);
1345 const auto &State = OtherAAImpl.getState();
1346 for (
const auto &It : State) {
1347 for (
auto Index : It.getSecond()) {
1348 const auto &RAcc = State.getAccess(Index);
1349 if (IsByval && !RAcc.isRead())
1351 bool UsedAssumedInformation =
false;
1353 auto Content =
A.translateArgumentToCallSiteContent(
1354 RAcc.getContent(), CB, *
this, UsedAssumedInformation);
1355 AK =
AccessKind(AK & (IsByval ? AccessKind::AK_R : AccessKind::AK_RW));
1356 AK =
AccessKind(AK | (RAcc.isMayAccess() ? AK_MAY : AK_MUST));
1358 Changed |= addAccess(
A, RAcc.getRanges(), CB, Content, AK,
1359 RAcc.getType(), RAcc.getRemoteInst());
1365 ChangeStatus translateAndAddState(Attributor &
A,
const AAPointerInfo &OtherAA,
1366 const OffsetInfo &Offsets, CallBase &CB,
1368 using namespace AA::PointerInfo;
1370 return indicatePessimisticFixpoint();
1372 const auto &OtherAAImpl =
static_cast<const AAPointerInfoImpl &
>(OtherAA);
1376 const auto &State = OtherAAImpl.getState();
1377 for (
const auto &It : State) {
1378 for (
auto Index : It.getSecond()) {
1379 const auto &RAcc = State.getAccess(Index);
1380 if (!IsMustAcc && RAcc.isAssumption())
1382 for (
auto Offset : Offsets) {
1386 if (!NewRanges.isUnknown()) {
1387 NewRanges.addToAllOffsets(Offset);
1392 Changed |= addAccess(
A, NewRanges, CB, RAcc.getContent(), AK,
1393 RAcc.getType(), RAcc.getRemoteInst());
1402 void trackPointerInfoStatistics(
const IRPosition &IRP)
const {}
1405 void dumpState(raw_ostream &O) {
1406 for (
auto &It : OffsetBins) {
1407 O <<
"[" << It.first.Offset <<
"-" << It.first.Offset + It.first.Size
1408 <<
"] : " << It.getSecond().size() <<
"\n";
1409 for (
auto AccIndex : It.getSecond()) {
1410 auto &Acc = AccessList[AccIndex];
1411 O <<
" - " << Acc.getKind() <<
" - " << *Acc.getLocalInst() <<
"\n";
1412 if (Acc.getLocalInst() != Acc.getRemoteInst())
1413 O <<
" --> " << *Acc.getRemoteInst()
1415 if (!Acc.isWrittenValueYetUndetermined()) {
1417 O <<
" - c: func " << Acc.getWrittenValue()->getName()
1419 else if (Acc.getWrittenValue())
1420 O <<
" - c: " << *Acc.getWrittenValue() <<
"\n";
1422 O <<
" - c: <unknown>\n";
1429struct AAPointerInfoFloating :
public AAPointerInfoImpl {
1431 AAPointerInfoFloating(
const IRPosition &IRP, Attributor &
A)
1432 : AAPointerInfoImpl(IRP,
A) {}
1435 bool handleAccess(Attributor &
A, Instruction &
I,
1436 std::optional<Value *> Content,
AccessKind Kind,
1439 using namespace AA::PointerInfo;
1441 const DataLayout &
DL =
A.getDataLayout();
1442 TypeSize AccessSize =
DL.getTypeStoreSize(&Ty);
1451 if (!VT || VT->getElementCount().isScalable() ||
1453 (*Content)->getType() != VT ||
1454 DL.getTypeStoreSize(VT->getElementType()).isScalable()) {
1465 int64_t ElementSize =
DL.getTypeStoreSize(ElementType).getFixedValue();
1470 for (
int i = 0, e = VT->getElementCount().getFixedValue(); i != e; ++i) {
1472 ConstContent, ConstantInt::get(Int32Ty, i));
1479 for (
auto &ElementOffset : ElementOffsets)
1480 ElementOffset += ElementSize;
1493 bool collectConstantsForGEP(Attributor &
A,
const DataLayout &
DL,
1494 OffsetInfo &UsrOI,
const OffsetInfo &PtrOI,
1495 const GEPOperator *
GEP);
1498 void trackStatistics()
const override {
1499 AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());
1503bool AAPointerInfoFloating::collectConstantsForGEP(Attributor &
A,
1504 const DataLayout &
DL,
1506 const OffsetInfo &PtrOI,
1507 const GEPOperator *
GEP) {
1508 unsigned BitWidth =
DL.getIndexTypeSizeInBits(
GEP->getType());
1509 SmallMapVector<Value *, APInt, 4> VariableOffsets;
1512 assert(!UsrOI.isUnknown() && !PtrOI.isUnknown() &&
1513 "Don't look for constant values if the offset has already been "
1514 "determined to be unknown.");
1516 if (!
GEP->collectOffset(
DL,
BitWidth, VariableOffsets, ConstantOffset)) {
1522 << (VariableOffsets.
empty() ?
"" :
"not") <<
" constant "
1526 Union.addToAll(ConstantOffset.getSExtValue());
1531 for (
const auto &VI : VariableOffsets) {
1532 auto *PotentialConstantsAA =
A.getAAFor<AAPotentialConstantValues>(
1534 if (!PotentialConstantsAA || !PotentialConstantsAA->isValidState()) {
1540 if (PotentialConstantsAA->undefIsContained())
1547 auto &AssumedSet = PotentialConstantsAA->getAssumedSet();
1548 if (AssumedSet.empty())
1552 for (
const auto &ConstOffset : AssumedSet) {
1553 auto CopyPerOffset =
Union;
1554 CopyPerOffset.addToAll(ConstOffset.getSExtValue() *
1555 VI.second.getZExtValue());
1556 Product.merge(CopyPerOffset);
1561 UsrOI = std::move(Union);
1565ChangeStatus AAPointerInfoFloating::updateImpl(Attributor &
A) {
1566 using namespace AA::PointerInfo;
1568 const DataLayout &
DL =
A.getDataLayout();
1569 Value &AssociatedValue = getAssociatedValue();
1571 DenseMap<Value *, OffsetInfo> OffsetInfoMap;
1572 OffsetInfoMap[&AssociatedValue].
insert(0);
1574 auto HandlePassthroughUser = [&](
Value *Usr,
Value *CurPtr,
bool &Follow) {
1585 "CurPtr does not exist in the map!");
1587 auto &UsrOI = OffsetInfoMap[Usr];
1588 auto &PtrOI = OffsetInfoMap[CurPtr];
1589 assert(!PtrOI.isUnassigned() &&
1590 "Cannot pass through if the input Ptr was not visited!");
1596 auto UsePred = [&](
const Use &
U,
bool &Follow) ->
bool {
1598 User *Usr =
U.getUser();
1599 LLVM_DEBUG(
dbgs() <<
"[AAPointerInfo] Analyze " << *CurPtr <<
" in " << *Usr
1602 "The current pointer offset should have been seeded!");
1603 assert(!OffsetInfoMap[CurPtr].isUnassigned() &&
1604 "Current pointer should be assigned");
1608 return HandlePassthroughUser(Usr, CurPtr, Follow);
1610 LLVM_DEBUG(
dbgs() <<
"[AAPointerInfo] Unhandled constant user " << *CE
1618 auto &UsrOI = OffsetInfoMap[Usr];
1619 auto &PtrOI = OffsetInfoMap[CurPtr];
1621 if (UsrOI.isUnknown())
1624 if (PtrOI.isUnknown()) {
1630 Follow = collectConstantsForGEP(
A,
DL, UsrOI, PtrOI,
GEP);
1636 return HandlePassthroughUser(Usr, CurPtr, Follow);
1641 if (RI->getFunction() == getAssociatedFunction()) {
1642 auto &PtrOI = OffsetInfoMap[CurPtr];
1643 Changed |= setReachesReturn(PtrOI);
1656 auto &UsrOI = PhiIt->second;
1657 auto &PtrOI = OffsetInfoMap[CurPtr];
1661 if (PtrOI.isUnknown()) {
1662 LLVM_DEBUG(
dbgs() <<
"[AAPointerInfo] PHI operand offset unknown "
1663 << *CurPtr <<
" in " << *
PHI <<
"\n");
1664 Follow = !UsrOI.isUnknown();
1670 if (UsrOI == PtrOI) {
1671 assert(!PtrOI.isUnassigned() &&
1672 "Cannot assign if the current Ptr was not visited!");
1673 LLVM_DEBUG(
dbgs() <<
"[AAPointerInfo] PHI is invariant (so far)");
1683 auto It = OffsetInfoMap.
find(CurPtrBase);
1684 if (It == OffsetInfoMap.
end()) {
1685 LLVM_DEBUG(
dbgs() <<
"[AAPointerInfo] PHI operand is too complex "
1686 << *CurPtr <<
" in " << *
PHI
1687 <<
" (base: " << *CurPtrBase <<
")\n");
1701 A.getInfoCache().getAnalysisResultForFunction<CycleAnalysis>(
1702 *
PHI->getFunction());
1704 auto BaseOI = It->getSecond();
1705 BaseOI.addToAll(
Offset.getZExtValue());
1706 if (IsFirstPHIUser || BaseOI == UsrOI) {
1707 LLVM_DEBUG(
dbgs() <<
"[AAPointerInfo] PHI is invariant " << *CurPtr
1708 <<
" in " << *Usr <<
"\n");
1709 return HandlePassthroughUser(Usr, CurPtr, Follow);
1713 dbgs() <<
"[AAPointerInfo] PHI operand pointer offset mismatch "
1714 << *CurPtr <<
" in " << *
PHI <<
"\n");
1733 if (!handleAccess(
A, *LoadI,
nullptr, AK,
1734 OffsetInfoMap[CurPtr].Offsets,
Changed,
1740 return II->isAssumeLikeIntrinsic();
1751 }
while (FromI && FromI != ToI);
1756 auto IsValidAssume = [&](IntrinsicInst &IntrI) {
1757 if (IntrI.getIntrinsicID() != Intrinsic::assume)
1760 if (IntrI.getParent() == BB) {
1761 if (IsImpactedInRange(LoadI->getNextNode(), &IntrI))
1767 if ((*PredIt) != BB)
1772 if (SuccBB == IntrBB)
1778 if (IsImpactedInRange(LoadI->getNextNode(), BB->
getTerminator()))
1780 if (IsImpactedInRange(&IntrBB->
front(), &IntrI))
1786 std::pair<Value *, IntrinsicInst *> Assumption;
1787 for (
const Use &LoadU : LoadI->uses()) {
1789 if (!CmpI->isEquality() || !CmpI->isTrueWhenEqual())
1791 for (
const Use &CmpU : CmpI->uses()) {
1793 if (!IsValidAssume(*IntrI))
1795 int Idx = CmpI->getOperandUse(0) == LoadU;
1796 Assumption = {CmpI->getOperand(Idx), IntrI};
1801 if (Assumption.first)
1806 if (!Assumption.first || !Assumption.second)
1810 << *Assumption.second <<
": " << *LoadI
1811 <<
" == " << *Assumption.first <<
"\n");
1812 bool UsedAssumedInformation =
false;
1813 std::optional<Value *> Content =
nullptr;
1814 if (Assumption.first)
1816 A.getAssumedSimplified(*Assumption.first, *
this,
1818 return handleAccess(
1819 A, *Assumption.second, Content, AccessKind::AK_ASSUMPTION,
1820 OffsetInfoMap[CurPtr].Offsets,
Changed, *LoadI->getType());
1825 for (
auto *OtherOp : OtherOps) {
1826 if (OtherOp == CurPtr) {
1829 <<
"[AAPointerInfo] Escaping use in store like instruction " <<
I
1841 bool UsedAssumedInformation =
false;
1842 std::optional<Value *> Content =
nullptr;
1844 Content =
A.getAssumedSimplified(
1846 return handleAccess(
A,
I, Content, AK, OffsetInfoMap[CurPtr].Offsets,
1851 return HandleStoreLike(*StoreI, StoreI->getValueOperand(),
1852 *StoreI->getValueOperand()->getType(),
1853 {StoreI->getValueOperand()}, AccessKind::AK_W);
1855 return HandleStoreLike(*RMWI,
nullptr, *RMWI->getValOperand()->getType(),
1856 {RMWI->getValOperand()}, AccessKind::AK_RW);
1858 return HandleStoreLike(
1859 *CXI,
nullptr, *CXI->getNewValOperand()->getType(),
1860 {CXI->getCompareOperand(), CXI->getNewValOperand()},
1867 A.getInfoCache().getTargetLibraryInfoForFunction(*CB->
getFunction());
1872 const auto *CSArgPI =
A.getAAFor<AAPointerInfo>(
1878 Changed = translateAndAddState(
A, *CSArgPI, OffsetInfoMap[CurPtr], *CB,
1881 if (!CSArgPI->reachesReturn())
1882 return isValidState();
1885 if (!Callee ||
Callee->arg_size() <= ArgNo)
1887 bool UsedAssumedInformation =
false;
1888 auto ReturnedValue =
A.getAssumedSimplified(
1893 auto *Arg =
Callee->getArg(ArgNo);
1894 if (ReturnedArg && Arg != ReturnedArg)
1896 bool IsRetMustAcc = IsArgMustAcc && (ReturnedArg == Arg);
1897 const auto *CSRetPI =
A.getAAFor<AAPointerInfo>(
1901 OffsetInfo OI = OffsetInfoMap[CurPtr];
1902 CSArgPI->addReturnedOffsetsTo(OI);
1904 translateAndAddState(
A, *CSRetPI, OI, *CB, IsRetMustAcc) |
Changed;
1905 return isValidState();
1907 LLVM_DEBUG(
dbgs() <<
"[AAPointerInfo] Call user not handled " << *CB
1912 LLVM_DEBUG(
dbgs() <<
"[AAPointerInfo] User not handled " << *Usr <<
"\n");
1915 auto EquivalentUseCB = [&](
const Use &OldU,
const Use &NewU) {
1916 assert(OffsetInfoMap.
count(OldU) &&
"Old use should be known already!");
1917 assert(!OffsetInfoMap[OldU].isUnassigned() &&
"Old use should be assinged");
1918 if (OffsetInfoMap.
count(NewU)) {
1920 if (!(OffsetInfoMap[NewU] == OffsetInfoMap[OldU])) {
1921 dbgs() <<
"[AAPointerInfo] Equivalent use callback failed: "
1922 << OffsetInfoMap[NewU] <<
" vs " << OffsetInfoMap[OldU]
1926 return OffsetInfoMap[NewU] == OffsetInfoMap[OldU];
1929 return HandlePassthroughUser(NewU.get(), OldU.
get(), Unused);
1931 if (!
A.checkForAllUses(UsePred, *
this, AssociatedValue,
1933 true, EquivalentUseCB)) {
1934 LLVM_DEBUG(
dbgs() <<
"[AAPointerInfo] Check for all uses failed, abort!\n");
1935 return indicatePessimisticFixpoint();
1939 dbgs() <<
"Accesses by bin after update:\n";
1946struct AAPointerInfoReturned final : AAPointerInfoImpl {
1947 AAPointerInfoReturned(
const IRPosition &IRP, Attributor &
A)
1948 : AAPointerInfoImpl(IRP,
A) {}
1952 return indicatePessimisticFixpoint();
1956 void trackStatistics()
const override {
1957 AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());
1961struct AAPointerInfoArgument final : AAPointerInfoFloating {
1962 AAPointerInfoArgument(
const IRPosition &IRP, Attributor &
A)
1963 : AAPointerInfoFloating(IRP,
A) {}
1966 void trackStatistics()
const override {
1967 AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());
1971struct AAPointerInfoCallSiteArgument final : AAPointerInfoFloating {
1972 AAPointerInfoCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
1973 : AAPointerInfoFloating(IRP,
A) {}
1977 using namespace AA::PointerInfo;
1983 if (
auto Length =
MI->getLengthInBytes())
1984 LengthVal =
Length->getSExtValue();
1985 unsigned ArgNo = getIRPosition().getCallSiteArgNo();
1988 LLVM_DEBUG(
dbgs() <<
"[AAPointerInfo] Unhandled memory intrinsic "
1990 return indicatePessimisticFixpoint();
1993 ArgNo == 0 ? AccessKind::AK_MUST_WRITE : AccessKind::AK_MUST_READ;
1995 Changed | addAccess(
A, {0, LengthVal}, *
MI,
nullptr,
Kind,
nullptr);
1998 dbgs() <<
"Accesses by bin after update:\n";
2009 Argument *Arg = getAssociatedArgument();
2013 A.getAAFor<AAPointerInfo>(*
this, ArgPos, DepClassTy::REQUIRED);
2014 if (ArgAA && ArgAA->getState().isValidState())
2015 return translateAndAddStateFromCallee(
A, *ArgAA,
2018 return indicatePessimisticFixpoint();
2021 bool IsKnownNoCapture;
2023 A,
this, getIRPosition(), DepClassTy::OPTIONAL, IsKnownNoCapture))
2024 return indicatePessimisticFixpoint();
2026 bool IsKnown =
false;
2028 return ChangeStatus::UNCHANGED;
2031 ReadOnly ? AccessKind::AK_MAY_READ : AccessKind::AK_MAY_READ_WRITE;
2037 void trackStatistics()
const override {
2038 AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());
2042struct AAPointerInfoCallSiteReturned final : AAPointerInfoFloating {
2043 AAPointerInfoCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
2044 : AAPointerInfoFloating(IRP,
A) {}
2047 void trackStatistics()
const override {
2048 AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());
2056struct AANoUnwindImpl : AANoUnwind {
2057 AANoUnwindImpl(
const IRPosition &IRP, Attributor &
A) : AANoUnwind(IRP,
A) {}
2063 A,
nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));
2067 const std::string getAsStr(Attributor *
A)
const override {
2068 return getAssumed() ?
"nounwind" :
"may-unwind";
2074 (unsigned)Instruction::Invoke, (
unsigned)Instruction::CallBr,
2075 (unsigned)Instruction::Call, (
unsigned)Instruction::CleanupRet,
2076 (unsigned)Instruction::CatchSwitch, (
unsigned)Instruction::Resume};
2079 if (!
I.mayThrow(
true))
2083 bool IsKnownNoUnwind;
2091 bool UsedAssumedInformation =
false;
2092 if (!
A.checkForAllInstructions(CheckForNoUnwind, *
this, Opcodes,
2093 UsedAssumedInformation))
2094 return indicatePessimisticFixpoint();
2096 return ChangeStatus::UNCHANGED;
2100struct AANoUnwindFunction final :
public AANoUnwindImpl {
2101 AANoUnwindFunction(
const IRPosition &IRP, Attributor &
A)
2102 : AANoUnwindImpl(IRP,
A) {}
2109struct AANoUnwindCallSite final
2110 : AACalleeToCallSite<AANoUnwind, AANoUnwindImpl> {
2111 AANoUnwindCallSite(
const IRPosition &IRP, Attributor &
A)
2112 : AACalleeToCallSite<AANoUnwind, AANoUnwindImpl>(IRP,
A) {}
2123 case Intrinsic::nvvm_barrier_cta_sync_aligned_all:
2124 case Intrinsic::nvvm_barrier_cta_sync_aligned_count:
2125 case Intrinsic::nvvm_barrier_cta_red_and_aligned_all:
2126 case Intrinsic::nvvm_barrier_cta_red_and_aligned_count:
2127 case Intrinsic::nvvm_barrier_cta_red_or_aligned_all:
2128 case Intrinsic::nvvm_barrier_cta_red_or_aligned_count:
2129 case Intrinsic::nvvm_barrier_cta_red_popc_aligned_all:
2130 case Intrinsic::nvvm_barrier_cta_red_popc_aligned_count:
2132 case Intrinsic::amdgcn_s_barrier:
2133 if (ExecutedAligned)
2156 switch (
I->getOpcode()) {
2157 case Instruction::AtomicRMW:
2160 case Instruction::Store:
2163 case Instruction::Load:
2168 "New atomic operations need to be known in the attributor.");
2187 const std::string getAsStr(Attributor *
A)
const override {
2188 return getAssumed() ?
"nosync" :
"may-sync";
2204 if (
I.mayReadOrWriteMemory())
2218 bool UsedAssumedInformation =
false;
2219 if (!
A.checkForAllReadWriteInstructions(CheckRWInstForNoSync, *
this,
2220 UsedAssumedInformation) ||
2221 !
A.checkForAllCallLikeInstructions(CheckForNoSync, *
this,
2222 UsedAssumedInformation))
2223 return indicatePessimisticFixpoint();
2228struct AANoSyncFunction final :
public AANoSyncImpl {
2229 AANoSyncFunction(
const IRPosition &IRP, Attributor &
A)
2230 : AANoSyncImpl(IRP,
A) {}
2237struct AANoSyncCallSite final : AACalleeToCallSite<AANoSync, AANoSyncImpl> {
2238 AANoSyncCallSite(
const IRPosition &IRP, Attributor &
A)
2239 : AACalleeToCallSite<AANoSync, AANoSyncImpl>(IRP,
A) {}
2249struct AANoFreeImpl :
public AANoFree {
2250 AANoFreeImpl(
const IRPosition &IRP, Attributor &
A) : AANoFree(IRP,
A) {}
2256 DepClassTy::NONE, IsKnown));
2274 bool UsedAssumedInformation =
false;
2275 if (!
A.checkForAllReadWriteInstructions(CheckForNoFree, *
this,
2276 UsedAssumedInformation) ||
2277 !
A.checkForAllCallLikeInstructions(CheckForNoFree, *
this,
2278 UsedAssumedInformation))
2279 return indicatePessimisticFixpoint();
2281 return ChangeStatus::UNCHANGED;
2285 const std::string getAsStr(Attributor *
A)
const override {
2286 return getAssumed() ?
"nofree" :
"may-free";
2290struct AANoFreeFunction final :
public AANoFreeImpl {
2291 AANoFreeFunction(
const IRPosition &IRP, Attributor &
A)
2292 : AANoFreeImpl(IRP,
A) {}
2299struct AANoFreeCallSite final : AACalleeToCallSite<AANoFree, AANoFreeImpl> {
2300 AANoFreeCallSite(
const IRPosition &IRP, Attributor &
A)
2301 : AACalleeToCallSite<AANoFree, AANoFreeImpl>(IRP,
A) {}
2308struct AANoFreeFloating : AANoFreeImpl {
2309 AANoFreeFloating(
const IRPosition &IRP, Attributor &
A)
2310 : AANoFreeImpl(IRP,
A) {}
2317 const IRPosition &IRP = getIRPosition();
2322 DepClassTy::OPTIONAL, IsKnown))
2323 return ChangeStatus::UNCHANGED;
2325 Value &AssociatedValue = getIRPosition().getAssociatedValue();
2326 auto Pred = [&](
const Use &
U,
bool &Follow) ->
bool {
2341 DepClassTy::REQUIRED, IsKnown))
2344 const AANoCapture *NoCaptureAA =
nullptr;
2347 DepClassTy::REQUIRED, IsKnown,
2348 false, &NoCaptureAA)) {
2373 if (!
A.checkForAllUses(Pred, *
this, AssociatedValue))
2374 return indicatePessimisticFixpoint();
2376 return ChangeStatus::UNCHANGED;
2381struct AANoFreeArgument final : AANoFreeFloating {
2382 AANoFreeArgument(
const IRPosition &IRP, Attributor &
A)
2383 : AANoFreeFloating(IRP,
A) {}
2390struct AANoFreeCallSiteArgument final : AANoFreeFloating {
2391 AANoFreeCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
2392 : AANoFreeFloating(IRP,
A) {}
2400 Argument *Arg = getAssociatedArgument();
2402 return indicatePessimisticFixpoint();
2406 DepClassTy::REQUIRED, IsKnown))
2407 return ChangeStatus::UNCHANGED;
2408 return indicatePessimisticFixpoint();
2416struct AANoFreeReturned final : AANoFreeFloating {
2417 AANoFreeReturned(
const IRPosition &IRP, Attributor &
A)
2418 : AANoFreeFloating(IRP,
A) {
2433 void trackStatistics()
const override {}
2437struct AANoFreeCallSiteReturned final : AANoFreeFloating {
2438 AANoFreeCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
2439 : AANoFreeFloating(IRP,
A) {}
2442 return ChangeStatus::UNCHANGED;
2453 bool IgnoreSubsumingPositions) {
2455 AttrKinds.
push_back(Attribute::NonNull);
2458 AttrKinds.
push_back(Attribute::Dereferenceable);
2459 if (
A.hasAttr(IRP, AttrKinds, IgnoreSubsumingPositions, Attribute::NonNull))
2466 if (!Fn->isDeclaration()) {
2476 bool UsedAssumedInformation =
false;
2477 if (!
A.checkForAllInstructions(
2479 Worklist.push_back({*cast<ReturnInst>(I).getReturnValue(), &I});
2483 UsedAssumedInformation,
false,
true))
2495 Attribute::NonNull)});
2500static int64_t getKnownNonNullAndDerefBytesForUse(
2501 Attributor &
A,
const AbstractAttribute &QueryingAA,
Value &AssociatedValue,
2502 const Use *U,
const Instruction *
I,
bool &IsNonNull,
bool &TrackUse) {
2505 const Value *UseV =
U->get();
2526 const DataLayout &
DL =
A.getInfoCache().getDL();
2530 U, {Attribute::NonNull, Attribute::Dereferenceable})) {
2547 bool IsKnownNonNull;
2550 IsNonNull |= IsKnownNonNull;
2553 return DerefAA ? DerefAA->getKnownDereferenceableBytes() : 0;
2557 if (!Loc || Loc->Ptr != UseV || !Loc->Size.isPrecise() ||
2558 Loc->Size.isScalable() ||
I->isVolatile())
2564 if (
Base &&
Base == &AssociatedValue) {
2565 int64_t DerefBytes = Loc->Size.getValue() +
Offset;
2567 return std::max(int64_t(0), DerefBytes);
2574 int64_t DerefBytes = Loc->Size.getValue();
2576 return std::max(int64_t(0), DerefBytes);
2582struct AANonNullImpl : AANonNull {
2583 AANonNullImpl(
const IRPosition &IRP, Attributor &
A) : AANonNull(IRP,
A) {}
2587 Value &
V = *getAssociatedValue().stripPointerCasts();
2589 indicatePessimisticFixpoint();
2593 if (Instruction *CtxI = getCtxI())
2594 followUsesInMBEC(*
this,
A, getState(), *CtxI);
2598 bool followUseInMBEC(Attributor &
A,
const Use *U,
const Instruction *
I,
2599 AANonNull::StateType &State) {
2600 bool IsNonNull =
false;
2601 bool TrackUse =
false;
2602 getKnownNonNullAndDerefBytesForUse(
A, *
this, getAssociatedValue(), U,
I,
2603 IsNonNull, TrackUse);
2604 State.setKnown(IsNonNull);
2609 const std::string getAsStr(Attributor *
A)
const override {
2610 return getAssumed() ?
"nonnull" :
"may-null";
2615struct AANonNullFloating :
public AANonNullImpl {
2616 AANonNullFloating(
const IRPosition &IRP, Attributor &
A)
2617 : AANonNullImpl(IRP,
A) {}
2621 auto CheckIRP = [&](
const IRPosition &IRP) {
2622 bool IsKnownNonNull;
2624 A, *
this, IRP, DepClassTy::OPTIONAL, IsKnownNonNull);
2628 bool UsedAssumedInformation =
false;
2629 Value *AssociatedValue = &getAssociatedValue();
2631 if (!
A.getAssumedSimplifiedValues(getIRPosition(), *
this,
Values,
2636 Values.size() != 1 ||
Values.front().getValue() != AssociatedValue;
2642 return AA::hasAssumedIRAttr<Attribute::NonNull>(
2643 A, this, IRPosition::value(*Op), DepClassTy::OPTIONAL,
2646 return ChangeStatus::UNCHANGED;
2650 DepClassTy::OPTIONAL, IsKnown) &&
2653 DepClassTy::OPTIONAL, IsKnown))
2654 return ChangeStatus::UNCHANGED;
2661 if (AVIRP == getIRPosition() || !CheckIRP(AVIRP))
2662 return indicatePessimisticFixpoint();
2663 return ChangeStatus::UNCHANGED;
2666 for (
const auto &VAC :
Values)
2668 return indicatePessimisticFixpoint();
2670 return ChangeStatus::UNCHANGED;
2678struct AANonNullReturned final
2679 : AAReturnedFromReturnedValues<AANonNull, AANonNull, AANonNull::StateType,
2680 false, AANonNull::IRAttributeKind, false> {
2681 AANonNullReturned(
const IRPosition &IRP, Attributor &
A)
2682 : AAReturnedFromReturnedValues<AANonNull, AANonNull, AANonNull::StateType,
2687 const std::string getAsStr(Attributor *
A)
const override {
2688 return getAssumed() ?
"nonnull" :
"may-null";
2696struct AANonNullArgument final
2697 : AAArgumentFromCallSiteArguments<AANonNull, AANonNullImpl> {
2698 AANonNullArgument(
const IRPosition &IRP, Attributor &
A)
2699 : AAArgumentFromCallSiteArguments<AANonNull, AANonNullImpl>(IRP,
A) {}
2705struct AANonNullCallSiteArgument final : AANonNullFloating {
2706 AANonNullCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
2707 : AANonNullFloating(IRP,
A) {}
2714struct AANonNullCallSiteReturned final
2715 : AACalleeToCallSite<AANonNull, AANonNullImpl> {
2716 AANonNullCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
2717 : AACalleeToCallSite<AANonNull, AANonNullImpl>(IRP,
A) {}
2726struct AAMustProgressImpl :
public AAMustProgress {
2727 AAMustProgressImpl(
const IRPosition &IRP, Attributor &
A)
2728 : AAMustProgress(IRP,
A) {}
2734 A,
nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));
2739 const std::string getAsStr(Attributor *
A)
const override {
2740 return getAssumed() ?
"mustprogress" :
"may-not-progress";
2744struct AAMustProgressFunction final : AAMustProgressImpl {
2745 AAMustProgressFunction(
const IRPosition &IRP, Attributor &
A)
2746 : AAMustProgressImpl(IRP,
A) {}
2752 A,
this, getIRPosition(), DepClassTy::OPTIONAL, IsKnown)) {
2754 return indicateOptimisticFixpoint();
2755 return ChangeStatus::UNCHANGED;
2758 auto CheckForMustProgress = [&](AbstractCallSite ACS) {
2760 bool IsKnownMustProgress;
2762 A,
this, IPos, DepClassTy::REQUIRED, IsKnownMustProgress,
2766 bool AllCallSitesKnown =
true;
2767 if (!
A.checkForAllCallSites(CheckForMustProgress, *
this,
2770 return indicatePessimisticFixpoint();
2772 return ChangeStatus::UNCHANGED;
2776 void trackStatistics()
const override {
2782struct AAMustProgressCallSite final : AAMustProgressImpl {
2783 AAMustProgressCallSite(
const IRPosition &IRP, Attributor &
A)
2784 : AAMustProgressImpl(IRP,
A) {}
2793 bool IsKnownMustProgress;
2795 A,
this, FnPos, DepClassTy::REQUIRED, IsKnownMustProgress))
2796 return indicatePessimisticFixpoint();
2797 return ChangeStatus::UNCHANGED;
2801 void trackStatistics()
const override {
2810struct AANoRecurseImpl :
public AANoRecurse {
2811 AANoRecurseImpl(
const IRPosition &IRP, Attributor &
A) : AANoRecurse(IRP,
A) {}
2817 A,
nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));
2822 const std::string getAsStr(Attributor *
A)
const override {
2823 return getAssumed() ?
"norecurse" :
"may-recurse";
2827struct AANoRecurseFunction final : AANoRecurseImpl {
2828 AANoRecurseFunction(
const IRPosition &IRP, Attributor &
A)
2829 : AANoRecurseImpl(IRP,
A) {}
2835 auto CallSitePred = [&](AbstractCallSite ACS) {
2836 bool IsKnownNoRecurse;
2840 DepClassTy::NONE, IsKnownNoRecurse))
2842 return IsKnownNoRecurse;
2844 bool UsedAssumedInformation =
false;
2845 if (
A.checkForAllCallSites(CallSitePred, *
this,
true,
2846 UsedAssumedInformation)) {
2852 if (!UsedAssumedInformation)
2853 indicateOptimisticFixpoint();
2854 return ChangeStatus::UNCHANGED;
2857 const AAInterFnReachability *EdgeReachability =
2858 A.getAAFor<AAInterFnReachability>(*
this, getIRPosition(),
2859 DepClassTy::REQUIRED);
2860 if (EdgeReachability && EdgeReachability->
canReach(
A, *getAnchorScope()))
2861 return indicatePessimisticFixpoint();
2862 return ChangeStatus::UNCHANGED;
2869struct AANoRecurseCallSite final
2870 : AACalleeToCallSite<AANoRecurse, AANoRecurseImpl> {
2871 AANoRecurseCallSite(
const IRPosition &IRP, Attributor &
A)
2872 : AACalleeToCallSite<AANoRecurse, AANoRecurseImpl>(IRP,
A) {}
2882struct AANonConvergentImpl :
public AANonConvergent {
2883 AANonConvergentImpl(
const IRPosition &IRP, Attributor &
A)
2884 : AANonConvergent(IRP,
A) {}
2887 const std::string getAsStr(Attributor *
A)
const override {
2888 return getAssumed() ?
"non-convergent" :
"may-be-convergent";
2892struct AANonConvergentFunction final : AANonConvergentImpl {
2893 AANonConvergentFunction(
const IRPosition &IRP, Attributor &
A)
2894 : AANonConvergentImpl(IRP,
A) {}
2900 auto CalleeIsNotConvergent = [&](
Instruction &Inst) {
2903 if (!Callee ||
Callee->isIntrinsic()) {
2906 if (
Callee->isDeclaration()) {
2907 return !
Callee->hasFnAttribute(Attribute::Convergent);
2909 const auto *ConvergentAA =
A.getAAFor<AANonConvergent>(
2911 return ConvergentAA && ConvergentAA->isAssumedNotConvergent();
2914 bool UsedAssumedInformation =
false;
2915 if (!
A.checkForAllCallLikeInstructions(CalleeIsNotConvergent, *
this,
2916 UsedAssumedInformation)) {
2917 return indicatePessimisticFixpoint();
2919 return ChangeStatus::UNCHANGED;
2923 if (isKnownNotConvergent() &&
2924 A.hasAttr(getIRPosition(), Attribute::Convergent)) {
2925 A.removeAttrs(getIRPosition(), {Attribute::Convergent});
2926 return ChangeStatus::CHANGED;
2928 return ChangeStatus::UNCHANGED;
2938struct AAUndefinedBehaviorImpl :
public AAUndefinedBehavior {
2939 AAUndefinedBehaviorImpl(
const IRPosition &IRP, Attributor &
A)
2940 : AAUndefinedBehavior(IRP,
A) {}
2946 UndefBranchCondition,
2948 NullReturnViolatesNonNull,
2950 NullArgViolatesNonNull,
2954 std::optional<unsigned> ArgNo;
2956 UBInfo(Kind K) :
K(
K), ArgNo(std::nullopt) {}
2958 UBInfo(Kind K, std::optional<unsigned> ArgNo) :
K(
K), ArgNo(ArgNo) {}
2964 const size_t UBPrevSize = KnownUBInsts.size();
2965 const size_t NoUBPrevSize = AssumedNoUBInsts.size();
2973 if (AssumedNoUBInsts.count(&
I) || KnownUBInsts.count(&
I))
2982 "Expected pointer operand of memory accessing instruction");
2986 std::optional<Value *> SimplifiedPtrOp =
2987 stopOnUndefOrAssumed(
A, PtrOp, &
I, UBInfo::UndefPtrAccess);
2988 if (!SimplifiedPtrOp || !*SimplifiedPtrOp)
2990 const Value *PtrOpVal = *SimplifiedPtrOp;
2996 AssumedNoUBInsts.insert(&
I);
3008 AssumedNoUBInsts.insert(&
I);
3010 KnownUBInsts.try_emplace(&
I, UBInfo::NullPtrAccess);
3019 if (AssumedNoUBInsts.count(&
I) || KnownUBInsts.count(&
I))
3027 std::optional<Value *> SimplifiedCond = stopOnUndefOrAssumed(
3028 A, BrInst->getCondition(), BrInst, UBInfo::UndefBranchCondition);
3029 if (!SimplifiedCond || !*SimplifiedCond)
3031 AssumedNoUBInsts.insert(&
I);
3039 if (AssumedNoUBInsts.count(&
I) || KnownUBInsts.count(&
I))
3048 for (
unsigned idx = 0; idx < CB.
arg_size(); idx++) {
3054 if (idx >=
Callee->arg_size())
3066 bool IsKnownNoUndef;
3068 A,
this, CalleeArgumentIRP, DepClassTy::NONE, IsKnownNoUndef);
3069 if (!IsKnownNoUndef)
3071 bool UsedAssumedInformation =
false;
3072 std::optional<Value *> SimplifiedVal =
3075 if (UsedAssumedInformation)
3077 if (SimplifiedVal && !*SimplifiedVal)
3080 KnownUBInsts.try_emplace(&
I, UBInfo(UBInfo::UndefCallArgument, idx));
3086 bool IsKnownNonNull;
3088 A,
this, CalleeArgumentIRP, DepClassTy::NONE, IsKnownNonNull);
3090 KnownUBInsts.try_emplace(&
I,
3091 UBInfo(UBInfo::NullArgViolatesNonNull, idx));
3100 std::optional<Value *> SimplifiedRetValue = stopOnUndefOrAssumed(
3101 A, RI.getReturnValue(), &
I, UBInfo::UndefReturnValue);
3102 if (!SimplifiedRetValue || !*SimplifiedRetValue)
3120 bool IsKnownNonNull;
3125 KnownUBInsts.try_emplace(&
I, UBInfo::NullReturnViolatesNonNull);
3131 bool UsedAssumedInformation =
false;
3132 A.checkForAllInstructions(InspectMemAccessInstForUB, *
this,
3133 {Instruction::Load, Instruction::Store,
3134 Instruction::AtomicCmpXchg,
3135 Instruction::AtomicRMW},
3136 UsedAssumedInformation,
3138 A.checkForAllInstructions(InspectBrInstForUB, *
this, {Instruction::CondBr},
3139 UsedAssumedInformation,
3141 A.checkForAllCallLikeInstructions(InspectCallSiteForUB, *
this,
3142 UsedAssumedInformation);
3146 if (!getAnchorScope()->getReturnType()->isVoidTy()) {
3148 if (!
A.isAssumedDead(ReturnIRP,
this,
nullptr, UsedAssumedInformation)) {
3149 bool IsKnownNoUndef;
3151 A,
this, ReturnIRP, DepClassTy::NONE, IsKnownNoUndef);
3153 A.checkForAllInstructions(InspectReturnInstForUB, *
this,
3154 {Instruction::Ret}, UsedAssumedInformation,
3159 if (NoUBPrevSize != AssumedNoUBInsts.size() ||
3160 UBPrevSize != KnownUBInsts.size())
3161 return ChangeStatus::CHANGED;
3162 return ChangeStatus::UNCHANGED;
3165 bool isKnownToCauseUB(Instruction *
I)
const override {
3166 return KnownUBInsts.count(
I);
3169 bool isAssumedToCauseUB(Instruction *
I)
const override {
3176 switch (
I->getOpcode()) {
3177 case Instruction::Load:
3178 case Instruction::Store:
3179 case Instruction::AtomicCmpXchg:
3180 case Instruction::AtomicRMW:
3181 case Instruction::CondBr:
3182 return !AssumedNoUBInsts.count(
I);
3191 static void emitUBRemark(Attributor &
A, Instruction *
I,
const UBInfo &Info) {
3192 auto Remark = [&](OptimizationRemark
OR) {
3194 case UBInfo::NullPtrAccess:
3195 case UBInfo::UndefPtrAccess: {
3196 return OR <<
"Memory access through a pointer known to be "
3199 <<
" is undefined behavior; replacing with 'unreachable'.";
3201 case UBInfo::UndefBranchCondition:
3202 return OR <<
"Branch condition known to be "
3204 <<
" is undefined behavior; replacing with 'unreachable'.";
3205 case UBInfo::UndefReturnValue:
3206 case UBInfo::NullReturnViolatesNonNull:
3207 return OR <<
"Value returned known to be "
3210 <<
" is undefined behavior; replacing with 'unreachable'.";
3211 case UBInfo::UndefCallArgument:
3212 case UBInfo::NullArgViolatesNonNull: {
3213 bool IsUndef =
Info.K == UBInfo::UndefCallArgument;
3216 <<
" passed to parameter of ";
3221 return OR <<
" known to be "
3222 <<
ore::NV(
"Argument", IsUndef ?
"undef" :
"null")
3223 <<
" is undefined behavior; replacing with 'unreachable'.";
3228 A.emitRemark<OptimizationRemark>(
I,
"UndefinedBehavior",
Remark);
3232 if (KnownUBInsts.empty())
3233 return ChangeStatus::UNCHANGED;
3234 for (
const auto &[
I, Info] : KnownUBInsts) {
3235 emitUBRemark(
A,
I, Info);
3236 A.changeToUnreachableAfterManifest(
I);
3238 return ChangeStatus::CHANGED;
3242 const std::string getAsStr(Attributor *
A)
const override {
3243 return getAssumed() ?
"undefined-behavior" :
"no-ub";
3272 MapVector<Instruction *, UBInfo> KnownUBInsts;
3276 SmallPtrSet<Instruction *, 8> AssumedNoUBInsts;
3287 std::optional<Value *> stopOnUndefOrAssumed(Attributor &
A,
Value *V,
3288 Instruction *
I, UBInfo::Kind K) {
3289 bool UsedAssumedInformation =
false;
3290 std::optional<Value *> SimplifiedV =
3293 if (!UsedAssumedInformation) {
3298 KnownUBInsts.try_emplace(
I, K);
3299 return std::nullopt;
3306 KnownUBInsts.try_emplace(
I, K);
3307 return std::nullopt;
3313struct AAUndefinedBehaviorFunction final : AAUndefinedBehaviorImpl {
3314 AAUndefinedBehaviorFunction(
const IRPosition &IRP, Attributor &
A)
3315 : AAUndefinedBehaviorImpl(IRP,
A) {}
3318 void trackStatistics()
const override {
3319 STATS_DECL(UndefinedBehaviorInstruction, Instruction,
3320 "Number of instructions known to have UB");
3322 KnownUBInsts.size();
3333static bool mayContainUnboundedCycle(
Function &
F, Attributor &
A) {
3334 ScalarEvolution *SE =
3335 A.getInfoCache().getAnalysisResultForFunction<ScalarEvolutionAnalysis>(
F);
3336 LoopInfo *LI =
A.getInfoCache().getAnalysisResultForFunction<LoopAnalysis>(
F);
3342 for (scc_iterator<Function *> SCCI =
scc_begin(&
F); !SCCI.isAtEnd(); ++SCCI)
3343 if (SCCI.hasCycle())
3353 for (
auto *L : LI->getLoopsInPreorder()) {
3360struct AAWillReturnImpl :
public AAWillReturn {
3361 AAWillReturnImpl(
const IRPosition &IRP, Attributor &
A)
3362 : AAWillReturn(IRP,
A) {}
3368 A,
nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));
3373 bool isImpliedByMustprogressAndReadonly(Attributor &
A,
bool KnownOnly) {
3374 if (!
A.hasAttr(getIRPosition(), {Attribute::MustProgress}))
3379 return IsKnown || !KnownOnly;
3385 if (isImpliedByMustprogressAndReadonly(
A,
false))
3386 return ChangeStatus::UNCHANGED;
3392 A,
this, IPos, DepClassTy::REQUIRED, IsKnown)) {
3398 bool IsKnownNoRecurse;
3400 A,
this, IPos, DepClassTy::REQUIRED, IsKnownNoRecurse);
3403 bool UsedAssumedInformation =
false;
3404 if (!
A.checkForAllCallLikeInstructions(CheckForWillReturn, *
this,
3405 UsedAssumedInformation))
3406 return indicatePessimisticFixpoint();
3410 return !
I.isVolatile();
3412 if (!
A.checkForAllInstructions(CheckForVolatile, *
this,
3413 {Instruction::Load, Instruction::Store,
3414 Instruction::AtomicCmpXchg,
3415 Instruction::AtomicRMW},
3416 UsedAssumedInformation))
3417 return indicatePessimisticFixpoint();
3419 return ChangeStatus::UNCHANGED;
3423 const std::string getAsStr(Attributor *
A)
const override {
3424 return getAssumed() ?
"willreturn" :
"may-noreturn";
3428struct AAWillReturnFunction final : AAWillReturnImpl {
3429 AAWillReturnFunction(
const IRPosition &IRP, Attributor &
A)
3430 : AAWillReturnImpl(IRP,
A) {}
3434 AAWillReturnImpl::initialize(
A);
3437 assert(
F &&
"Did expect an anchor function");
3438 if (
F->isDeclaration() || mayContainUnboundedCycle(*
F,
A))
3439 indicatePessimisticFixpoint();
3447struct AAWillReturnCallSite final
3448 : AACalleeToCallSite<AAWillReturn, AAWillReturnImpl> {
3449 AAWillReturnCallSite(
const IRPosition &IRP, Attributor &
A)
3450 : AACalleeToCallSite<AAWillReturn, AAWillReturnImpl>(IRP,
A) {}
3454 if (isImpliedByMustprogressAndReadonly(
A,
false))
3455 return ChangeStatus::UNCHANGED;
3457 return AACalleeToCallSite::updateImpl(
A);
3479 const ToTy *
To =
nullptr;
3506 if (!ES || ES->
empty()) {
3507 ExclusionSet = nullptr;
3508 }
else if (MakeUnique) {
3509 ExclusionSet =
A.getInfoCache().getOrCreateUniqueBlockExecutionSet(ES);
3527 if (!PairDMI::isEqual({LHS->From, LHS->To}, {RHS->From, RHS->To}))
3529 return InstSetDMI::isEqual(LHS->ExclusionSet, RHS->ExclusionSet);
3537template <
typename BaseTy,
typename ToTy>
3538struct CachedReachabilityAA :
public BaseTy {
3539 using RQITy = ReachabilityQueryInfo<ToTy>;
3541 CachedReachabilityAA(
const IRPosition &IRP, Attributor &
A) : BaseTy(IRP,
A) {}
3544 bool isQueryAA()
const override {
return true; }
3549 for (
unsigned u = 0, e = QueryVector.size(); u < e; ++u) {
3550 RQITy *RQI = QueryVector[
u];
3551 if (RQI->Result == RQITy::Reachable::No &&
3553 Changed = ChangeStatus::CHANGED;
3559 bool IsTemporaryRQI) = 0;
3561 bool rememberResult(Attributor &
A,
typename RQITy::Reachable Result,
3562 RQITy &RQI,
bool UsedExclusionSet,
bool IsTemporaryRQI) {
3567 QueryCache.erase(&RQI);
3573 if (Result == RQITy::Reachable::Yes || !UsedExclusionSet) {
3574 RQITy PlainRQI(RQI.From, RQI.To);
3575 if (!QueryCache.count(&PlainRQI)) {
3576 RQITy *RQIPtr =
new (
A.Allocator) RQITy(RQI.From, RQI.To);
3578 QueryVector.push_back(RQIPtr);
3579 QueryCache.insert(RQIPtr);
3584 if (IsTemporaryRQI && Result != RQITy::Reachable::Yes && UsedExclusionSet) {
3585 assert((!RQI.ExclusionSet || !RQI.ExclusionSet->empty()) &&
3586 "Did not expect empty set!");
3587 RQITy *RQIPtr =
new (
A.Allocator)
3588 RQITy(
A, *RQI.From, *RQI.To, RQI.ExclusionSet,
true);
3589 assert(RQIPtr->Result == RQITy::Reachable::No &&
"Already reachable?");
3591 assert(!QueryCache.count(RQIPtr));
3592 QueryVector.push_back(RQIPtr);
3593 QueryCache.insert(RQIPtr);
3596 if (Result == RQITy::Reachable::No && IsTemporaryRQI)
3597 A.registerForUpdate(*
this);
3598 return Result == RQITy::Reachable::Yes;
3601 const std::string getAsStr(Attributor *
A)
const override {
3603 return "#queries(" + std::to_string(QueryVector.size()) +
")";
3606 bool checkQueryCache(Attributor &
A, RQITy &StackRQI,
3607 typename RQITy::Reachable &Result) {
3608 if (!this->getState().isValidState()) {
3609 Result = RQITy::Reachable::Yes;
3615 if (StackRQI.ExclusionSet) {
3616 RQITy PlainRQI(StackRQI.From, StackRQI.To);
3617 auto It = QueryCache.find(&PlainRQI);
3618 if (It != QueryCache.end() && (*It)->Result == RQITy::Reachable::No) {
3619 Result = RQITy::Reachable::No;
3624 auto It = QueryCache.find(&StackRQI);
3625 if (It != QueryCache.end()) {
3632 QueryCache.insert(&StackRQI);
3638 DenseSet<RQITy *> QueryCache;
3641struct AAIntraFnReachabilityFunction final
3642 :
public CachedReachabilityAA<AAIntraFnReachability, Instruction> {
3643 using Base = CachedReachabilityAA<AAIntraFnReachability, Instruction>;
3644 AAIntraFnReachabilityFunction(
const IRPosition &IRP, Attributor &
A)
3646 DT =
A.getInfoCache().getAnalysisResultForFunction<DominatorTreeAnalysis>(
3650 bool isAssumedReachable(
3651 Attributor &
A,
const Instruction &From,
const Instruction &To,
3653 auto *NonConstThis =
const_cast<AAIntraFnReachabilityFunction *
>(
this);
3657 RQITy StackRQI(
A, From, To, ExclusionSet,
false);
3659 if (!NonConstThis->checkQueryCache(
A, StackRQI, Result))
3660 return NonConstThis->isReachableImpl(
A, StackRQI,
3662 return Result == RQITy::Reachable::Yes;
3669 A.getAAFor<AAIsDead>(*
this, getIRPosition(), DepClassTy::OPTIONAL);
3672 [&](
const auto &DeadEdge) {
3673 return LivenessAA->isEdgeDead(DeadEdge.first,
3677 return LivenessAA->isAssumedDead(BB);
3679 return ChangeStatus::UNCHANGED;
3683 return Base::updateImpl(
A);
3687 bool IsTemporaryRQI)
override {
3689 bool UsedExclusionSet =
false;
3694 while (IP && IP != &To) {
3695 if (ExclusionSet && IP != Origin && ExclusionSet->
count(IP)) {
3696 UsedExclusionSet =
true;
3704 const BasicBlock *FromBB = RQI.From->getParent();
3705 const BasicBlock *ToBB = RQI.To->getParent();
3707 "Not an intra-procedural query!");
3711 if (FromBB == ToBB &&
3712 WillReachInBlock(*RQI.From, *RQI.To, RQI.ExclusionSet))
3713 return rememberResult(
A, RQITy::Reachable::Yes, RQI, UsedExclusionSet,
3718 if (!WillReachInBlock(ToBB->
front(), *RQI.To, RQI.ExclusionSet))
3719 return rememberResult(
A, RQITy::Reachable::No, RQI, UsedExclusionSet,
3723 SmallPtrSet<const BasicBlock *, 16> ExclusionBlocks;
3724 if (RQI.ExclusionSet)
3725 for (
auto *
I : *RQI.ExclusionSet)
3726 if (
I->getFunction() == Fn)
3727 ExclusionBlocks.
insert(
I->getParent());
3730 if (ExclusionBlocks.
count(FromBB) &&
3733 return rememberResult(
A, RQITy::Reachable::No, RQI,
true, IsTemporaryRQI);
3736 A.getAAFor<AAIsDead>(*
this, getIRPosition(), DepClassTy::OPTIONAL);
3737 if (LivenessAA && LivenessAA->isAssumedDead(ToBB)) {
3738 DeadBlocks.insert(ToBB);
3739 return rememberResult(
A, RQITy::Reachable::No, RQI, UsedExclusionSet,
3743 SmallPtrSet<const BasicBlock *, 16> Visited;
3747 DenseSet<std::pair<const BasicBlock *, const BasicBlock *>> LocalDeadEdges;
3748 while (!Worklist.
empty()) {
3750 if (!Visited.
insert(BB).second)
3752 for (
const BasicBlock *SuccBB :
successors(BB)) {
3753 if (LivenessAA && LivenessAA->isEdgeDead(BB, SuccBB)) {
3754 LocalDeadEdges.
insert({BB, SuccBB});
3759 return rememberResult(
A, RQITy::Reachable::Yes, RQI, UsedExclusionSet,
3762 return rememberResult(
A, RQITy::Reachable::Yes, RQI, UsedExclusionSet,
3765 if (ExclusionBlocks.
count(SuccBB)) {
3766 UsedExclusionSet =
true;
3773 DeadEdges.insert_range(LocalDeadEdges);
3774 return rememberResult(
A, RQITy::Reachable::No, RQI, UsedExclusionSet,
3779 void trackStatistics()
const override {}
3784 DenseSet<const BasicBlock *> DeadBlocks;
3788 DenseSet<std::pair<const BasicBlock *, const BasicBlock *>> DeadEdges;
3791 const DominatorTree *DT =
nullptr;
3799 bool IgnoreSubsumingPositions) {
3800 assert(ImpliedAttributeKind == Attribute::NoAlias &&
3801 "Unexpected attribute kind");
3807 IgnoreSubsumingPositions =
true;
3818 if (
A.hasAttr(IRP, {Attribute::ByVal, Attribute::NoAlias},
3819 IgnoreSubsumingPositions, Attribute::NoAlias))
3829 "Noalias is a pointer attribute");
3832 const std::string getAsStr(
Attributor *
A)
const override {
3833 return getAssumed() ?
"noalias" :
"may-alias";
3838struct AANoAliasFloating final : AANoAliasImpl {
3839 AANoAliasFloating(
const IRPosition &IRP, Attributor &
A)
3840 : AANoAliasImpl(IRP,
A) {}
3845 return indicatePessimisticFixpoint();
3849 void trackStatistics()
const override {
3855struct AANoAliasArgument final
3856 : AAArgumentFromCallSiteArguments<AANoAlias, AANoAliasImpl> {
3857 using Base = AAArgumentFromCallSiteArguments<AANoAlias, AANoAliasImpl>;
3858 AANoAliasArgument(
const IRPosition &IRP, Attributor &
A) :
Base(IRP,
A) {}
3871 DepClassTy::OPTIONAL, IsKnownNoSycn))
3872 return Base::updateImpl(
A);
3877 return Base::updateImpl(
A);
3881 bool UsedAssumedInformation =
false;
3882 if (
A.checkForAllCallSites(
3883 [](AbstractCallSite ACS) { return !ACS.isCallbackCall(); }, *
this,
3884 true, UsedAssumedInformation))
3885 return Base::updateImpl(
A);
3893 return indicatePessimisticFixpoint();
3900struct AANoAliasCallSiteArgument final : AANoAliasImpl {
3901 AANoAliasCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
3902 : AANoAliasImpl(IRP,
A) {}
3906 bool mayAliasWithArgument(Attributor &
A, AAResults *&AAR,
3907 const AAMemoryBehavior &MemBehaviorAA,
3908 const CallBase &CB,
unsigned OtherArgNo) {
3910 if (this->getCallSiteArgNo() == (
int)OtherArgNo)
3918 auto *CBArgMemBehaviorAA =
A.getAAFor<AAMemoryBehavior>(
3922 if (CBArgMemBehaviorAA && CBArgMemBehaviorAA->isAssumedReadNone()) {
3923 A.recordDependence(*CBArgMemBehaviorAA, *
this, DepClassTy::OPTIONAL);
3930 if (CBArgMemBehaviorAA && CBArgMemBehaviorAA->isAssumedReadOnly() &&
3932 A.recordDependence(MemBehaviorAA, *
this, DepClassTy::OPTIONAL);
3933 A.recordDependence(*CBArgMemBehaviorAA, *
this, DepClassTy::OPTIONAL);
3939 AAR =
A.getInfoCache().getAnalysisResultForFunction<AAManager>(
3943 bool IsAliasing = !AAR || !AAR->
isNoAlias(&getAssociatedValue(), ArgOp);
3945 "callsite arguments: "
3946 << getAssociatedValue() <<
" " << *ArgOp <<
" => "
3947 << (IsAliasing ?
"" :
"no-") <<
"alias \n");
3952 bool isKnownNoAliasDueToNoAliasPreservation(
3953 Attributor &
A, AAResults *&AAR,
const AAMemoryBehavior &MemBehaviorAA) {
3966 auto UsePred = [&](
const Use &
U,
bool &Follow) ->
bool {
3982 bool IsKnownNoCapture;
3985 DepClassTy::OPTIONAL, IsKnownNoCapture))
3991 A, *UserI, *getCtxI(), *
this,
nullptr,
3992 [ScopeFn](
const Function &Fn) {
return &Fn != ScopeFn; }))
4007 LLVM_DEBUG(
dbgs() <<
"[AANoAliasCSArg] Unknown user: " << *UserI <<
"\n");
4011 bool IsKnownNoCapture;
4012 const AANoCapture *NoCaptureAA =
nullptr;
4014 A,
this, VIRP, DepClassTy::NONE, IsKnownNoCapture,
false, &NoCaptureAA);
4015 if (!IsAssumedNoCapture &&
4017 if (!
A.checkForAllUses(UsePred, *
this, getAssociatedValue())) {
4019 dbgs() <<
"[AANoAliasCSArg] " << getAssociatedValue()
4020 <<
" cannot be noalias as it is potentially captured\n");
4025 A.recordDependence(*NoCaptureAA, *
this, DepClassTy::OPTIONAL);
4031 for (
unsigned OtherArgNo = 0; OtherArgNo < CB.
arg_size(); OtherArgNo++)
4032 if (mayAliasWithArgument(
A, AAR, MemBehaviorAA, CB, OtherArgNo))
4042 auto *MemBehaviorAA =
4043 A.getAAFor<AAMemoryBehavior>(*
this, getIRPosition(), DepClassTy::NONE);
4045 A.recordDependence(*MemBehaviorAA, *
this, DepClassTy::OPTIONAL);
4046 return ChangeStatus::UNCHANGED;
4049 bool IsKnownNoAlias;
4052 A,
this, VIRP, DepClassTy::REQUIRED, IsKnownNoAlias)) {
4054 <<
" is not no-alias at the definition\n");
4055 return indicatePessimisticFixpoint();
4058 AAResults *AAR =
nullptr;
4059 if (MemBehaviorAA &&
4060 isKnownNoAliasDueToNoAliasPreservation(
A, AAR, *MemBehaviorAA)) {
4062 dbgs() <<
"[AANoAlias] No-Alias deduced via no-alias preservation\n");
4063 return ChangeStatus::UNCHANGED;
4066 return indicatePessimisticFixpoint();
4074struct AANoAliasReturned final : AANoAliasImpl {
4075 AANoAliasReturned(
const IRPosition &IRP, Attributor &
A)
4076 : AANoAliasImpl(IRP,
A) {}
4081 auto CheckReturnValue = [&](
Value &RV) ->
bool {
4092 bool IsKnownNoAlias;
4094 A,
this, RVPos, DepClassTy::REQUIRED, IsKnownNoAlias))
4097 bool IsKnownNoCapture;
4098 const AANoCapture *NoCaptureAA =
nullptr;
4100 A,
this, RVPos, DepClassTy::REQUIRED, IsKnownNoCapture,
false,
4102 return IsAssumedNoCapture ||
4106 if (!
A.checkForAllReturnedValues(CheckReturnValue, *
this))
4107 return indicatePessimisticFixpoint();
4109 return ChangeStatus::UNCHANGED;
4117struct AANoAliasCallSiteReturned final
4118 : AACalleeToCallSite<AANoAlias, AANoAliasImpl> {
4119 AANoAliasCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
4120 : AACalleeToCallSite<AANoAlias, AANoAliasImpl>(IRP,
A) {}
4130struct AAIsDeadValueImpl :
public AAIsDead {
4131 AAIsDeadValueImpl(
const IRPosition &IRP, Attributor &
A) : AAIsDead(IRP,
A) {}
4134 bool isAssumedDead()
const override {
return isAssumed(IS_DEAD); }
4137 bool isKnownDead()
const override {
return isKnown(IS_DEAD); }
4140 bool isAssumedDead(
const BasicBlock *BB)
const override {
return false; }
4143 bool isKnownDead(
const BasicBlock *BB)
const override {
return false; }
4146 bool isAssumedDead(
const Instruction *
I)
const override {
4147 return I == getCtxI() && isAssumedDead();
4151 bool isKnownDead(
const Instruction *
I)
const override {
4152 return isAssumedDead(
I) && isKnownDead();
4156 const std::string getAsStr(Attributor *
A)
const override {
4157 return isAssumedDead() ?
"assumed-dead" :
"assumed-live";
4161 bool areAllUsesAssumedDead(Attributor &
A,
Value &V) {
4163 if (
V.getType()->isVoidTy() ||
V.use_empty())
4169 if (!
A.isRunOn(*
I->getFunction()))
4171 bool UsedAssumedInformation =
false;
4172 std::optional<Constant *>
C =
4173 A.getAssumedConstant(V, *
this, UsedAssumedInformation);
4178 auto UsePred = [&](
const Use &
U,
bool &Follow) {
return false; };
4183 return A.checkForAllUses(UsePred, *
this, V,
false,
4184 DepClassTy::REQUIRED,
4189 bool isAssumedSideEffectFree(Attributor &
A, Instruction *
I) {
4193 if (!
I->isTerminator() && !
I->mayHaveSideEffects())
4202 bool IsKnownNoUnwind;
4204 A,
this, CallIRP, DepClassTy::OPTIONAL, IsKnownNoUnwind))
4212struct AAIsDeadFloating :
public AAIsDeadValueImpl {
4213 AAIsDeadFloating(
const IRPosition &IRP, Attributor &
A)
4214 : AAIsDeadValueImpl(IRP,
A) {}
4218 AAIsDeadValueImpl::initialize(
A);
4221 indicatePessimisticFixpoint();
4226 if (!isAssumedSideEffectFree(
A,
I)) {
4228 indicatePessimisticFixpoint();
4230 removeAssumedBits(HAS_NO_EFFECT);
4234 bool isDeadFence(Attributor &
A, FenceInst &FI) {
4235 const auto *ExecDomainAA =
A.lookupAAFor<AAExecutionDomain>(
4237 if (!ExecDomainAA || !ExecDomainAA->isNoOpFence(FI))
4239 A.recordDependence(*ExecDomainAA, *
this, DepClassTy::OPTIONAL);
4243 bool isDeadStore(Attributor &
A, StoreInst &SI,
4244 SmallSetVector<Instruction *, 8> *AssumeOnlyInst =
nullptr) {
4246 if (
SI.isVolatile())
4252 bool UsedAssumedInformation =
false;
4253 if (!AssumeOnlyInst) {
4254 PotentialCopies.clear();
4256 UsedAssumedInformation)) {
4259 <<
"[AAIsDead] Could not determine potential copies of store!\n");
4263 LLVM_DEBUG(
dbgs() <<
"[AAIsDead] Store has " << PotentialCopies.size()
4264 <<
" potential copies.\n");
4266 InformationCache &InfoCache =
A.getInfoCache();
4269 UsedAssumedInformation))
4273 auto &UserI = cast<Instruction>(*U.getUser());
4274 if (InfoCache.isOnlyUsedByAssume(UserI)) {
4276 AssumeOnlyInst->insert(&UserI);
4279 return A.isAssumedDead(U,
this,
nullptr, UsedAssumedInformation);
4285 <<
" is assumed live!\n");
4291 const std::string getAsStr(Attributor *
A)
const override {
4295 return "assumed-dead-store";
4298 return "assumed-dead-fence";
4299 return AAIsDeadValueImpl::getAsStr(
A);
4306 if (!isDeadStore(
A, *SI))
4307 return indicatePessimisticFixpoint();
4309 if (!isDeadFence(
A, *FI))
4310 return indicatePessimisticFixpoint();
4312 if (!isAssumedSideEffectFree(
A,
I))
4313 return indicatePessimisticFixpoint();
4314 if (!areAllUsesAssumedDead(
A, getAssociatedValue()))
4315 return indicatePessimisticFixpoint();
4320 bool isRemovableStore()
const override {
4321 return isAssumed(IS_REMOVABLE) &&
isa<StoreInst>(&getAssociatedValue());
4326 Value &
V = getAssociatedValue();
4333 SmallSetVector<Instruction *, 8> AssumeOnlyInst;
4334 bool IsDead = isDeadStore(
A, *SI, &AssumeOnlyInst);
4337 A.deleteAfterManifest(*
I);
4338 for (
size_t i = 0; i < AssumeOnlyInst.
size(); ++i) {
4340 for (
auto *Usr : AOI->
users())
4342 A.deleteAfterManifest(*AOI);
4348 A.deleteAfterManifest(*FI);
4351 if (isAssumedSideEffectFree(
A,
I) && !
I->isTerminator()) {
4352 A.deleteAfterManifest(*
I);
4360 void trackStatistics()
const override {
4366 SmallSetVector<Value *, 4> PotentialCopies;
4369struct AAIsDeadArgument :
public AAIsDeadFloating {
4370 AAIsDeadArgument(
const IRPosition &IRP, Attributor &
A)
4371 : AAIsDeadFloating(IRP,
A) {}
4375 Argument &Arg = *getAssociatedArgument();
4376 if (
A.isValidFunctionSignatureRewrite(Arg, {}))
4377 if (
A.registerFunctionSignatureRewrite(
4381 return ChangeStatus::CHANGED;
4383 return ChangeStatus::UNCHANGED;
4390struct AAIsDeadCallSiteArgument :
public AAIsDeadValueImpl {
4391 AAIsDeadCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
4392 : AAIsDeadValueImpl(IRP,
A) {}
4396 AAIsDeadValueImpl::initialize(
A);
4398 indicatePessimisticFixpoint();
4407 Argument *Arg = getAssociatedArgument();
4409 return indicatePessimisticFixpoint();
4411 auto *ArgAA =
A.getAAFor<AAIsDead>(*
this, ArgPos, DepClassTy::REQUIRED);
4413 return indicatePessimisticFixpoint();
4422 "Expected undef values to be filtered out!");
4424 if (
A.changeUseAfterManifest(U, UV))
4425 return ChangeStatus::CHANGED;
4426 return ChangeStatus::UNCHANGED;
4433struct AAIsDeadCallSiteReturned :
public AAIsDeadFloating {
4434 AAIsDeadCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
4435 : AAIsDeadFloating(IRP,
A) {}
4438 bool isAssumedDead()
const override {
4439 return AAIsDeadFloating::isAssumedDead() && IsAssumedSideEffectFree;
4444 AAIsDeadFloating::initialize(
A);
4446 indicatePessimisticFixpoint();
4451 IsAssumedSideEffectFree = isAssumedSideEffectFree(
A, getCtxI());
4457 if (IsAssumedSideEffectFree && !isAssumedSideEffectFree(
A, getCtxI())) {
4458 IsAssumedSideEffectFree =
false;
4459 Changed = ChangeStatus::CHANGED;
4461 if (!areAllUsesAssumedDead(
A, getAssociatedValue()))
4462 return indicatePessimisticFixpoint();
4467 void trackStatistics()
const override {
4468 if (IsAssumedSideEffectFree)
4475 const std::string getAsStr(Attributor *
A)
const override {
4476 return isAssumedDead()
4478 : (getAssumed() ?
"assumed-dead-users" :
"assumed-live");
4482 bool IsAssumedSideEffectFree =
true;
4485struct AAIsDeadReturned :
public AAIsDeadValueImpl {
4486 AAIsDeadReturned(
const IRPosition &IRP, Attributor &
A)
4487 : AAIsDeadValueImpl(IRP,
A) {}
4492 bool UsedAssumedInformation =
false;
4493 A.checkForAllInstructions([](Instruction &) {
return true; }, *
this,
4494 {Instruction::Ret}, UsedAssumedInformation);
4496 auto PredForCallSite = [&](AbstractCallSite ACS) {
4497 if (ACS.isCallbackCall() || !ACS.getInstruction())
4499 return areAllUsesAssumedDead(
A, *ACS.getInstruction());
4502 if (!
A.checkForAllCallSites(PredForCallSite, *
this,
true,
4503 UsedAssumedInformation))
4504 return indicatePessimisticFixpoint();
4506 return ChangeStatus::UNCHANGED;
4512 bool AnyChange =
false;
4513 UndefValue &UV = *
UndefValue::get(getAssociatedFunction()->getReturnType());
4520 bool UsedAssumedInformation =
false;
4521 A.checkForAllInstructions(RetInstPred, *
this, {Instruction::Ret},
4522 UsedAssumedInformation);
4523 return AnyChange ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
4530struct AAIsDeadFunction :
public AAIsDead {
4531 AAIsDeadFunction(
const IRPosition &IRP, Attributor &
A) : AAIsDead(IRP,
A) {}
4536 assert(
F &&
"Did expect an anchor function");
4537 if (!isAssumedDeadInternalFunction(
A)) {
4538 ToBeExploredFrom.insert(&
F->getEntryBlock().front());
4539 assumeLive(
A,
F->getEntryBlock());
4543 bool isAssumedDeadInternalFunction(Attributor &
A) {
4544 if (!getAnchorScope()->hasLocalLinkage())
4546 bool UsedAssumedInformation =
false;
4547 return A.checkForAllCallSites([](AbstractCallSite) {
return false; }, *
this,
4548 true, UsedAssumedInformation);
4552 const std::string getAsStr(Attributor *
A)
const override {
4553 return "Live[#BB " + std::to_string(AssumedLiveBlocks.size()) +
"/" +
4554 std::to_string(getAnchorScope()->
size()) +
"][#TBEP " +
4555 std::to_string(ToBeExploredFrom.size()) +
"][#KDE " +
4556 std::to_string(KnownDeadEnds.size()) +
"]";
4561 assert(getState().isValidState() &&
4562 "Attempted to manifest an invalid state!");
4567 if (AssumedLiveBlocks.empty()) {
4568 A.deleteAfterManifest(
F);
4569 return ChangeStatus::CHANGED;
4575 bool Invoke2CallAllowed = !mayCatchAsynchronousExceptions(
F);
4577 KnownDeadEnds.set_union(ToBeExploredFrom);
4578 for (
const Instruction *DeadEndI : KnownDeadEnds) {
4582 bool IsKnownNoReturn;
4590 A.registerInvokeWithDeadSuccessor(
const_cast<InvokeInst &
>(*
II));
4592 A.changeToUnreachableAfterManifest(
4593 const_cast<Instruction *
>(DeadEndI->getNextNode()));
4594 HasChanged = ChangeStatus::CHANGED;
4597 STATS_DECL(AAIsDead, BasicBlock,
"Number of dead basic blocks deleted.");
4598 for (BasicBlock &BB :
F)
4599 if (!AssumedLiveBlocks.count(&BB)) {
4600 A.deleteAfterManifest(BB);
4602 HasChanged = ChangeStatus::CHANGED;
4611 bool isEdgeDead(
const BasicBlock *From,
const BasicBlock *To)
const override {
4614 "Used AAIsDead of the wrong function");
4615 return isValidState() && !AssumedLiveEdges.count(std::make_pair(From, To));
4619 void trackStatistics()
const override {}
4622 bool isAssumedDead()
const override {
return false; }
4625 bool isKnownDead()
const override {
return false; }
4628 bool isAssumedDead(
const BasicBlock *BB)
const override {
4630 "BB must be in the same anchor scope function.");
4634 return !AssumedLiveBlocks.count(BB);
4638 bool isKnownDead(
const BasicBlock *BB)
const override {
4639 return getKnown() && isAssumedDead(BB);
4643 bool isAssumedDead(
const Instruction *
I)
const override {
4644 assert(
I->getParent()->getParent() == getAnchorScope() &&
4645 "Instruction must be in the same anchor scope function.");
4652 if (!AssumedLiveBlocks.count(
I->getParent()))
4658 if (KnownDeadEnds.count(PrevI) || ToBeExploredFrom.count(PrevI))
4666 bool isKnownDead(
const Instruction *
I)
const override {
4667 return getKnown() && isAssumedDead(
I);
4672 bool assumeLive(Attributor &
A,
const BasicBlock &BB) {
4673 if (!AssumedLiveBlocks.insert(&BB).second)
4676 if (!
A.isDuringDeduction())
4683 for (
const Instruction &
I : BB)
4686 if (
F->hasLocalLinkage()) {
4688 dbgs() <<
"[AAIsDead] Seeding live internal callee ";
4689 F->printAsOperand(
dbgs(),
false);
4691 BB.getParent()->printAsOperand(
dbgs(),
false);
4694 A.markLiveInternalFunction(*
F);
4701 SmallSetVector<const Instruction *, 8> ToBeExploredFrom;
4704 SmallSetVector<const Instruction *, 8> KnownDeadEnds;
4707 DenseSet<std::pair<const BasicBlock *, const BasicBlock *>> AssumedLiveEdges;
4710 DenseSet<const BasicBlock *> AssumedLiveBlocks;
4714identifyAliveSuccessors(Attributor &
A,
const CallBase &CB,
4715 AbstractAttribute &AA,
4716 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4719 bool IsKnownNoReturn;
4722 return !IsKnownNoReturn;
4731identifyAliveSuccessors(Attributor &
A,
const InvokeInst &
II,
4732 AbstractAttribute &AA,
4733 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4734 bool UsedAssumedInformation =
4740 if (AAIsDeadFunction::mayCatchAsynchronousExceptions(*
II.getFunction())) {
4741 AliveSuccessors.
push_back(&
II.getUnwindDest()->front());
4745 bool IsKnownNoUnwind;
4748 UsedAssumedInformation |= !IsKnownNoUnwind;
4750 AliveSuccessors.
push_back(&
II.getUnwindDest()->front());
4753 return UsedAssumedInformation;
4757identifyAliveSuccessors(Attributor &,
const UncondBrInst &BI,
4758 AbstractAttribute &,
4759 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4765identifyAliveSuccessors(Attributor &
A,
const CondBrInst &BI,
4766 AbstractAttribute &AA,
4767 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4768 bool UsedAssumedInformation =
false;
4769 std::optional<Constant *>
C =
4770 A.getAssumedConstant(*BI.
getCondition(), AA, UsedAssumedInformation);
4780 UsedAssumedInformation =
false;
4782 return UsedAssumedInformation;
4786identifyAliveSuccessors(Attributor &
A,
const SwitchInst &SI,
4787 AbstractAttribute &AA,
4788 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4789 bool UsedAssumedInformation =
false;
4793 UsedAssumedInformation)) {
4795 for (
const BasicBlock *SuccBB :
successors(
SI.getParent()))
4804 return UsedAssumedInformation;
4807 Type &Ty = *
SI.getCondition()->getType();
4808 SmallPtrSet<ConstantInt *, 8>
Constants;
4809 auto CheckForConstantInt = [&](
Value *
V) {
4818 return CheckForConstantInt(VAC.
getValue());
4820 for (
const BasicBlock *SuccBB :
successors(
SI.getParent()))
4822 return UsedAssumedInformation;
4825 unsigned MatchedCases = 0;
4826 for (
const auto &CaseIt :
SI.cases()) {
4827 if (
Constants.count(CaseIt.getCaseValue())) {
4829 AliveSuccessors.
push_back(&CaseIt.getCaseSuccessor()->front());
4836 AliveSuccessors.
push_back(&
SI.getDefaultDest()->front());
4837 return UsedAssumedInformation;
4843 if (AssumedLiveBlocks.empty()) {
4844 if (isAssumedDeadInternalFunction(
A))
4848 ToBeExploredFrom.insert(&
F->getEntryBlock().front());
4849 assumeLive(
A,
F->getEntryBlock());
4853 LLVM_DEBUG(
dbgs() <<
"[AAIsDead] Live [" << AssumedLiveBlocks.size() <<
"/"
4854 << getAnchorScope()->
size() <<
"] BBs and "
4855 << ToBeExploredFrom.size() <<
" exploration points and "
4856 << KnownDeadEnds.size() <<
" known dead ends\n");
4861 ToBeExploredFrom.end());
4862 decltype(ToBeExploredFrom) NewToBeExploredFrom;
4865 while (!Worklist.
empty()) {
4872 I =
I->getNextNode();
4874 AliveSuccessors.
clear();
4876 bool UsedAssumedInformation =
false;
4877 switch (
I->getOpcode()) {
4881 "Expected non-terminators to be handled already!");
4882 for (
const BasicBlock *SuccBB :
successors(
I->getParent()))
4885 case Instruction::Call:
4887 *
this, AliveSuccessors);
4889 case Instruction::Invoke:
4891 *
this, AliveSuccessors);
4893 case Instruction::UncondBr:
4894 UsedAssumedInformation = identifyAliveSuccessors(
4897 case Instruction::CondBr:
4899 *
this, AliveSuccessors);
4901 case Instruction::Switch:
4903 *
this, AliveSuccessors);
4907 if (UsedAssumedInformation) {
4908 NewToBeExploredFrom.insert(
I);
4909 }
else if (AliveSuccessors.
empty() ||
4910 (
I->isTerminator() &&
4911 AliveSuccessors.
size() <
I->getNumSuccessors())) {
4912 if (KnownDeadEnds.insert(
I))
4917 << AliveSuccessors.
size() <<
" UsedAssumedInformation: "
4918 << UsedAssumedInformation <<
"\n");
4920 for (
const Instruction *AliveSuccessor : AliveSuccessors) {
4921 if (!
I->isTerminator()) {
4922 assert(AliveSuccessors.size() == 1 &&
4923 "Non-terminator expected to have a single successor!");
4927 auto Edge = std::make_pair(
I->getParent(), AliveSuccessor->getParent());
4928 if (AssumedLiveEdges.insert(
Edge).second)
4930 if (assumeLive(
A, *AliveSuccessor->getParent()))
4937 if (NewToBeExploredFrom.size() != ToBeExploredFrom.size() ||
4938 llvm::any_of(NewToBeExploredFrom, [&](
const Instruction *
I) {
4939 return !ToBeExploredFrom.count(I);
4942 ToBeExploredFrom = std::move(NewToBeExploredFrom);
4951 if (ToBeExploredFrom.empty() &&
4952 getAnchorScope()->
size() == AssumedLiveBlocks.size() &&
4953 llvm::all_of(KnownDeadEnds, [](
const Instruction *DeadEndI) {
4954 return DeadEndI->isTerminator() && DeadEndI->getNumSuccessors() == 0;
4956 return indicatePessimisticFixpoint();
4961struct AAIsDeadCallSite final : AAIsDeadFunction {
4962 AAIsDeadCallSite(
const IRPosition &IRP, Attributor &
A)
4963 : AAIsDeadFunction(IRP,
A) {}
4972 "supported for call sites yet!");
4977 return indicatePessimisticFixpoint();
4981 void trackStatistics()
const override {}
4988struct AADereferenceableImpl : AADereferenceable {
4989 AADereferenceableImpl(
const IRPosition &IRP, Attributor &
A)
4990 : AADereferenceable(IRP,
A) {}
4991 using StateType = DerefState;
4995 Value &
V = *getAssociatedValue().stripPointerCasts();
4997 A.getAttrs(getIRPosition(),
4998 {Attribute::Dereferenceable, Attribute::DereferenceableOrNull},
5001 takeKnownDerefBytesMaximum(Attr.getValueAsInt());
5004 bool IsKnownNonNull;
5006 A,
this, getIRPosition(), DepClassTy::OPTIONAL, IsKnownNonNull);
5009 takeKnownDerefBytesMaximum(
V.getPointerDereferenceableBytes(
5010 A.getDataLayout(), CanBeNull,
nullptr));
5012 if (Instruction *CtxI = getCtxI())
5013 followUsesInMBEC(*
this,
A, getState(), *CtxI);
5018 StateType &getState()
override {
return *
this; }
5019 const StateType &getState()
const override {
return *
this; }
5023 void addAccessedBytesForUse(Attributor &
A,
const Use *U,
const Instruction *
I,
5024 DerefState &State) {
5025 const Value *UseV =
U->get();
5030 if (!Loc || Loc->Ptr != UseV || !Loc->Size.isPrecise() ||
I->isVolatile())
5035 Loc->Ptr,
Offset,
A.getDataLayout(),
true);
5036 if (
Base &&
Base == &getAssociatedValue())
5037 State.addAccessedBytes(
Offset, Loc->Size.getValue());
5041 bool followUseInMBEC(Attributor &
A,
const Use *U,
const Instruction *
I,
5042 AADereferenceable::StateType &State) {
5043 bool IsNonNull =
false;
5044 bool TrackUse =
false;
5045 int64_t DerefBytes = getKnownNonNullAndDerefBytesForUse(
5046 A, *
this, getAssociatedValue(), U,
I, IsNonNull, TrackUse);
5047 LLVM_DEBUG(
dbgs() <<
"[AADereferenceable] Deref bytes: " << DerefBytes
5048 <<
" for instruction " << *
I <<
"\n");
5050 addAccessedBytesForUse(
A, U,
I, State);
5051 State.takeKnownDerefBytesMaximum(DerefBytes);
5058 bool IsKnownNonNull;
5060 A,
this, getIRPosition(), DepClassTy::NONE, IsKnownNonNull);
5061 if (IsAssumedNonNull &&
5062 A.hasAttr(getIRPosition(), Attribute::DereferenceableOrNull)) {
5063 A.removeAttrs(getIRPosition(), {Attribute::DereferenceableOrNull});
5064 return ChangeStatus::CHANGED;
5069 void getDeducedAttributes(Attributor &
A, LLVMContext &Ctx,
5070 SmallVectorImpl<Attribute> &Attrs)
const override {
5072 bool IsKnownNonNull;
5074 A,
this, getIRPosition(), DepClassTy::NONE, IsKnownNonNull);
5075 if (IsAssumedNonNull)
5076 Attrs.emplace_back(Attribute::getWithDereferenceableBytes(
5077 Ctx, getAssumedDereferenceableBytes()));
5079 Attrs.emplace_back(Attribute::getWithDereferenceableOrNullBytes(
5080 Ctx, getAssumedDereferenceableBytes()));
5084 const std::string getAsStr(Attributor *
A)
const override {
5085 if (!getAssumedDereferenceableBytes())
5086 return "unknown-dereferenceable";
5087 bool IsKnownNonNull;
5088 bool IsAssumedNonNull =
false;
5091 *
A,
this, getIRPosition(), DepClassTy::NONE, IsKnownNonNull);
5092 return std::string(
"dereferenceable") +
5093 (IsAssumedNonNull ?
"" :
"_or_null") +
5094 (isAssumedGlobal() ?
"_globally" :
"") +
"<" +
5095 std::to_string(getKnownDereferenceableBytes()) +
"-" +
5096 std::to_string(getAssumedDereferenceableBytes()) +
">" +
5097 (!
A ?
" [non-null is unknown]" :
"");
5102struct AADereferenceableFloating : AADereferenceableImpl {
5103 AADereferenceableFloating(
const IRPosition &IRP, Attributor &
A)
5104 : AADereferenceableImpl(IRP,
A) {}
5109 bool UsedAssumedInformation =
false;
5111 if (!
A.getAssumedSimplifiedValues(getIRPosition(), *
this,
Values,
5113 Values.push_back({getAssociatedValue(), getCtxI()});
5116 Stripped =
Values.size() != 1 ||
5117 Values.front().getValue() != &getAssociatedValue();
5120 const DataLayout &
DL =
A.getDataLayout();
5123 auto VisitValueCB = [&](
const Value &
V) ->
bool {
5125 DL.getIndexSizeInBits(
V.getType()->getPointerAddressSpace());
5126 APInt
Offset(IdxWidth, 0);
5131 const auto *AA =
A.getAAFor<AADereferenceable>(
5133 int64_t DerefBytes = 0;
5134 if (!AA || (!Stripped &&
this == AA)) {
5138 DerefBytes =
Base->getPointerDereferenceableBytes(
5139 DL, CanBeNull,
nullptr);
5140 T.GlobalState.indicatePessimisticFixpoint();
5143 DerefBytes =
DS.DerefBytesState.getAssumed();
5144 T.GlobalState &=
DS.GlobalState;
5150 int64_t OffsetSExt =
Offset.getSExtValue();
5154 T.takeAssumedDerefBytesMinimum(
5155 std::max(int64_t(0), DerefBytes - OffsetSExt));
5160 T.takeKnownDerefBytesMaximum(
5161 std::max(int64_t(0), DerefBytes - OffsetSExt));
5162 T.indicatePessimisticFixpoint();
5163 }
else if (OffsetSExt > 0) {
5169 T.indicatePessimisticFixpoint();
5173 return T.isValidState();
5176 for (
const auto &VAC :
Values)
5177 if (!VisitValueCB(*VAC.
getValue()))
5178 return indicatePessimisticFixpoint();
5184 void trackStatistics()
const override {
5190struct AADereferenceableReturned final
5191 : AAReturnedFromReturnedValues<AADereferenceable, AADereferenceableImpl> {
5193 AAReturnedFromReturnedValues<AADereferenceable, AADereferenceableImpl>;
5194 AADereferenceableReturned(
const IRPosition &IRP, Attributor &
A)
5198 void trackStatistics()
const override {
5204struct AADereferenceableArgument final
5205 : AAArgumentFromCallSiteArguments<AADereferenceable,
5206 AADereferenceableImpl> {
5208 AAArgumentFromCallSiteArguments<AADereferenceable, AADereferenceableImpl>;
5209 AADereferenceableArgument(
const IRPosition &IRP, Attributor &
A)
5213 void trackStatistics()
const override {
5219struct AADereferenceableCallSiteArgument final : AADereferenceableFloating {
5220 AADereferenceableCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
5221 : AADereferenceableFloating(IRP,
A) {}
5224 void trackStatistics()
const override {
5230struct AADereferenceableCallSiteReturned final
5231 : AACalleeToCallSite<AADereferenceable, AADereferenceableImpl> {
5232 using Base = AACalleeToCallSite<AADereferenceable, AADereferenceableImpl>;
5233 AADereferenceableCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
5237 void trackStatistics()
const override {
5247static unsigned getKnownAlignForUse(Attributor &
A, AAAlign &QueryingAA,
5248 Value &AssociatedValue,
const Use *U,
5249 const Instruction *
I,
bool &TrackUse) {
5258 if (
GEP->hasAllConstantIndices())
5263 switch (
II->getIntrinsicID()) {
5264 case Intrinsic::ptrmask: {
5266 const auto *ConstVals =
A.getAAFor<AAPotentialConstantValues>(
5268 const auto *AlignAA =
A.getAAFor<AAAlign>(
5270 if (ConstVals && ConstVals->isValidState() && ConstVals->isAtFixpoint()) {
5271 unsigned ShiftValue = std::min(ConstVals->getAssumedMinTrailingZeros(),
5273 Align ConstAlign(UINT64_C(1) << ShiftValue);
5274 if (ConstAlign >= AlignAA->getKnownAlign())
5275 return Align(1).value();
5278 return AlignAA->getKnownAlign().
value();
5281 case Intrinsic::amdgcn_make_buffer_rsrc: {
5282 const auto *AlignAA =
A.getAAFor<AAAlign>(
5285 return AlignAA->getKnownAlign().
value();
5303 MA = MaybeAlign(AlignAA->getKnownAlign());
5306 const DataLayout &
DL =
A.getDataLayout();
5307 const Value *UseV =
U->get();
5309 if (
SI->getPointerOperand() == UseV)
5310 MA =
SI->getAlign();
5312 if (LI->getPointerOperand() == UseV)
5313 MA = LI->getAlign();
5315 if (AI->getPointerOperand() == UseV)
5316 MA = AI->getAlign();
5318 if (AI->getPointerOperand() == UseV)
5319 MA = AI->getAlign();
5329 if (
Base == &AssociatedValue) {
5334 uint32_t
gcd = std::gcd(uint32_t(
abs((int32_t)
Offset)), Alignment);
5342struct AAAlignImpl : AAAlign {
5343 AAAlignImpl(
const IRPosition &IRP, Attributor &
A) : AAAlign(IRP,
A) {}
5348 A.getAttrs(getIRPosition(), {Attribute::Alignment},
Attrs);
5350 takeKnownMaximum(Attr.getValueAsInt());
5352 Value &
V = *getAssociatedValue().stripPointerCasts();
5353 takeKnownMaximum(
V.getPointerAlignment(
A.getDataLayout()).value());
5355 if (Instruction *CtxI = getCtxI())
5356 followUsesInMBEC(*
this,
A, getState(), *CtxI);
5364 Value &AssociatedValue = getAssociatedValue();
5366 return ChangeStatus::UNCHANGED;
5368 for (
const Use &U : AssociatedValue.
uses()) {
5370 if (
SI->getPointerOperand() == &AssociatedValue)
5371 if (
SI->getAlign() < getAssumedAlign()) {
5373 "Number of times alignment added to a store");
5374 SI->setAlignment(getAssumedAlign());
5375 InstrChanged = ChangeStatus::CHANGED;
5378 if (LI->getPointerOperand() == &AssociatedValue)
5379 if (LI->getAlign() < getAssumedAlign()) {
5380 LI->setAlignment(getAssumedAlign());
5382 "Number of times alignment added to a load");
5383 InstrChanged = ChangeStatus::CHANGED;
5386 if (RMW->getPointerOperand() == &AssociatedValue) {
5387 if (RMW->getAlign() < getAssumedAlign()) {
5389 "Number of times alignment added to atomicrmw");
5391 RMW->setAlignment(getAssumedAlign());
5392 InstrChanged = ChangeStatus::CHANGED;
5396 if (CAS->getPointerOperand() == &AssociatedValue) {
5397 if (CAS->getAlign() < getAssumedAlign()) {
5399 "Number of times alignment added to cmpxchg");
5400 CAS->setAlignment(getAssumedAlign());
5401 InstrChanged = ChangeStatus::CHANGED;
5409 Align InheritAlign =
5410 getAssociatedValue().getPointerAlignment(
A.getDataLayout());
5411 if (InheritAlign >= getAssumedAlign())
5412 return InstrChanged;
5413 return Changed | InstrChanged;
5421 void getDeducedAttributes(Attributor &
A, LLVMContext &Ctx,
5422 SmallVectorImpl<Attribute> &Attrs)
const override {
5423 if (getAssumedAlign() > 1)
5425 Attribute::getWithAlignment(Ctx,
Align(getAssumedAlign())));
5429 bool followUseInMBEC(Attributor &
A,
const Use *U,
const Instruction *
I,
5430 AAAlign::StateType &State) {
5431 bool TrackUse =
false;
5433 unsigned int KnownAlign =
5434 getKnownAlignForUse(
A, *
this, getAssociatedValue(), U,
I, TrackUse);
5435 State.takeKnownMaximum(KnownAlign);
5441 const std::string getAsStr(Attributor *
A)
const override {
5442 return "align<" + std::to_string(getKnownAlign().value()) +
"-" +
5443 std::to_string(getAssumedAlign().value()) +
">";
5448struct AAAlignFloating : AAAlignImpl {
5449 AAAlignFloating(
const IRPosition &IRP, Attributor &
A) : AAAlignImpl(IRP,
A) {}
5453 const DataLayout &
DL =
A.getDataLayout();
5456 bool UsedAssumedInformation =
false;
5458 if (!
A.getAssumedSimplifiedValues(getIRPosition(), *
this,
Values,
5460 Values.push_back({getAssociatedValue(), getCtxI()});
5463 Stripped =
Values.size() != 1 ||
5464 Values.front().getValue() != &getAssociatedValue();
5468 auto VisitValueCB = [&](
Value &
V) ->
bool {
5472 DepClassTy::REQUIRED);
5473 if (!AA || (!Stripped &&
this == AA)) {
5491 T.takeKnownMaximum(Alignment);
5492 T.indicatePessimisticFixpoint();
5495 const AAAlign::StateType &
DS = AA->
getState();
5498 return T.isValidState();
5501 for (
const auto &VAC :
Values) {
5502 if (!VisitValueCB(*VAC.
getValue()))
5503 return indicatePessimisticFixpoint();
5516struct AAAlignReturned final
5517 : AAReturnedFromReturnedValues<AAAlign, AAAlignImpl> {
5518 using Base = AAReturnedFromReturnedValues<AAAlign, AAAlignImpl>;
5519 AAAlignReturned(
const IRPosition &IRP, Attributor &
A) :
Base(IRP,
A) {}
5526struct AAAlignArgument final
5527 : AAArgumentFromCallSiteArguments<AAAlign, AAAlignImpl> {
5528 using Base = AAArgumentFromCallSiteArguments<AAAlign, AAAlignImpl>;
5529 AAAlignArgument(
const IRPosition &IRP, Attributor &
A) :
Base(IRP,
A) {}
5536 if (
A.getInfoCache().isInvolvedInMustTailCall(*getAssociatedArgument()))
5537 return ChangeStatus::UNCHANGED;
5538 return Base::manifest(
A);
5545struct AAAlignCallSiteArgument final : AAAlignFloating {
5546 AAAlignCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
5547 : AAAlignFloating(IRP,
A) {}
5554 if (Argument *Arg = getAssociatedArgument())
5555 if (
A.getInfoCache().isInvolvedInMustTailCall(*Arg))
5556 return ChangeStatus::UNCHANGED;
5558 Align InheritAlign =
5559 getAssociatedValue().getPointerAlignment(
A.getDataLayout());
5560 if (InheritAlign >= getAssumedAlign())
5561 Changed = ChangeStatus::UNCHANGED;
5568 if (Argument *Arg = getAssociatedArgument()) {
5571 const auto *ArgAlignAA =
A.getAAFor<AAAlign>(
5574 takeKnownMaximum(ArgAlignAA->getKnownAlign().value());
5584struct AAAlignCallSiteReturned final
5585 : AACalleeToCallSite<AAAlign, AAAlignImpl> {
5586 using Base = AACalleeToCallSite<AAAlign, AAAlignImpl>;
5587 AAAlignCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
5593 switch (
II->getIntrinsicID()) {
5594 case Intrinsic::ptrmask: {
5598 const auto *ConstVals =
A.getAAFor<AAPotentialConstantValues>(
5600 if (ConstVals && ConstVals->isValidState()) {
5601 unsigned ShiftValue =
5602 std::min(ConstVals->getAssumedMinTrailingZeros(),
5603 Value::MaxAlignmentExponent);
5608 const auto *AlignAA =
5610 DepClassTy::REQUIRED);
5612 Alignment = std::max(AlignAA->getAssumedAlign(), Alignment);
5619 std::min(this->getAssumedAlign(), Alignment).value());
5625 case Intrinsic::amdgcn_make_buffer_rsrc: {
5626 const auto *AlignAA =
5628 DepClassTy::REQUIRED);
5631 this->getState(), AlignAA->getAssumedAlign().
value());
5638 return Base::updateImpl(
A);
5647struct AANoReturnImpl :
public AANoReturn {
5648 AANoReturnImpl(
const IRPosition &IRP, Attributor &
A) : AANoReturn(IRP,
A) {}
5654 A,
nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));
5659 const std::string getAsStr(Attributor *
A)
const override {
5660 return getAssumed() ?
"noreturn" :
"may-return";
5665 auto CheckForNoReturn = [](
Instruction &) {
return false; };
5666 bool UsedAssumedInformation =
false;
5667 if (!
A.checkForAllInstructions(CheckForNoReturn, *
this,
5668 {(unsigned)Instruction::Ret},
5669 UsedAssumedInformation))
5670 return indicatePessimisticFixpoint();
5671 return ChangeStatus::UNCHANGED;
5675struct AANoReturnFunction final : AANoReturnImpl {
5676 AANoReturnFunction(
const IRPosition &IRP, Attributor &
A)
5677 : AANoReturnImpl(IRP,
A) {}
5684struct AANoReturnCallSite final
5685 : AACalleeToCallSite<AANoReturn, AANoReturnImpl> {
5686 AANoReturnCallSite(
const IRPosition &IRP, Attributor &
A)
5687 : AACalleeToCallSite<AANoReturn, AANoReturnImpl>(IRP,
A) {}
5698struct AAInstanceInfoImpl :
public AAInstanceInfo {
5699 AAInstanceInfoImpl(
const IRPosition &IRP, Attributor &
A)
5700 : AAInstanceInfo(IRP,
A) {}
5704 Value &
V = getAssociatedValue();
5706 if (
C->isThreadDependent())
5707 indicatePessimisticFixpoint();
5709 indicateOptimisticFixpoint();
5715 indicateOptimisticFixpoint();
5720 A.getInfoCache().getAnalysisResultForFunction<CycleAnalysis>(
5723 indicatePessimisticFixpoint();
5733 Value &
V = getAssociatedValue();
5736 Scope =
I->getFunction();
5739 if (!
Scope->hasLocalLinkage())
5743 return indicateOptimisticFixpoint();
5745 bool IsKnownNoRecurse;
5751 auto UsePred = [&](
const Use &
U,
bool &Follow) {
5766 if (!Callee || !
Callee->hasLocalLinkage())
5770 const auto *ArgInstanceInfoAA =
A.getAAFor<AAInstanceInfo>(
5772 DepClassTy::OPTIONAL);
5773 if (!ArgInstanceInfoAA ||
5774 !ArgInstanceInfoAA->isAssumedUniqueForAnalysis())
5779 A, *CB, *Scope, *
this,
nullptr,
5787 auto EquivalentUseCB = [&](
const Use &OldU,
const Use &NewU) {
5789 auto *Ptr =
SI->getPointerOperand()->stripPointerCasts();
5797 if (!
A.checkForAllUses(UsePred, *
this, V,
true,
5798 DepClassTy::OPTIONAL,
5799 true, EquivalentUseCB))
5800 return indicatePessimisticFixpoint();
5806 const std::string getAsStr(Attributor *
A)
const override {
5807 return isAssumedUniqueForAnalysis() ?
"<unique [fAa]>" :
"<unknown>";
5811 void trackStatistics()
const override {}
5815struct AAInstanceInfoFloating : AAInstanceInfoImpl {
5816 AAInstanceInfoFloating(
const IRPosition &IRP, Attributor &
A)
5817 : AAInstanceInfoImpl(IRP,
A) {}
5821struct AAInstanceInfoArgument final : AAInstanceInfoFloating {
5822 AAInstanceInfoArgument(
const IRPosition &IRP, Attributor &
A)
5823 : AAInstanceInfoFloating(IRP,
A) {}
5827struct AAInstanceInfoCallSiteArgument final : AAInstanceInfoImpl {
5828 AAInstanceInfoCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
5829 : AAInstanceInfoImpl(IRP,
A) {}
5837 Argument *Arg = getAssociatedArgument();
5839 return indicatePessimisticFixpoint();
5842 A.getAAFor<AAInstanceInfo>(*
this, ArgPos, DepClassTy::REQUIRED);
5844 return indicatePessimisticFixpoint();
5850struct AAInstanceInfoReturned final : AAInstanceInfoImpl {
5851 AAInstanceInfoReturned(
const IRPosition &IRP, Attributor &
A)
5852 : AAInstanceInfoImpl(IRP,
A) {
5868struct AAInstanceInfoCallSiteReturned final : AAInstanceInfoFloating {
5869 AAInstanceInfoCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
5870 : AAInstanceInfoFloating(IRP,
A) {}
5877 bool IgnoreSubsumingPositions) {
5878 assert(ImpliedAttributeKind == Attribute::Captures &&
5879 "Unexpected attribute kind");
5889 V.getType()->getPointerAddressSpace() == 0)) {
5894 A.getAttrs(IRP, {Attribute::Captures}, Attrs,
5904 {Attribute::Captures, Attribute::ByVal}, Attrs,
5942 bool NoThrow =
F.doesNotThrow();
5943 bool IsVoidReturn =
F.getReturnType()->isVoidTy();
5944 if (
ReadOnly && NoThrow && IsVoidReturn) {
5957 if (NoThrow && IsVoidReturn)
5962 if (!NoThrow || ArgNo < 0 ||
5963 !
F.getAttributes().hasAttrSomewhere(Attribute::Returned))
5966 for (
unsigned U = 0, E =
F.arg_size(); U < E; ++U)
5967 if (
F.hasParamAttribute(U, Attribute::Returned)) {
5968 if (U ==
unsigned(ArgNo))
5995 void getDeducedAttributes(Attributor &
A, LLVMContext &Ctx,
5996 SmallVectorImpl<Attribute> &Attrs)
const override {
5997 if (!isAssumedNoCaptureMaybeReturned())
6000 if (isArgumentPosition()) {
6001 if (isAssumedNoCapture())
6002 Attrs.emplace_back(Attribute::get(Ctx, Attribute::Captures));
6004 Attrs.emplace_back(Attribute::get(Ctx,
"no-capture-maybe-returned"));
6009 const std::string getAsStr(Attributor *
A)
const override {
6010 if (isKnownNoCapture())
6011 return "known not-captured";
6012 if (isAssumedNoCapture())
6013 return "assumed not-captured";
6014 if (isKnownNoCaptureMaybeReturned())
6015 return "known not-captured-maybe-returned";
6016 if (isAssumedNoCaptureMaybeReturned())
6017 return "assumed not-captured-maybe-returned";
6018 return "assumed-captured";
6023 bool checkUse(Attributor &
A, AANoCapture::StateType &State,
const Use &U,
6026 LLVM_DEBUG(
dbgs() <<
"[AANoCapture] Check use: " << *
U.get() <<
" in "
6032 return isCapturedIn(State,
true,
true,
6039 return isCapturedIn(State,
true,
true,
6045 return isCapturedIn(State,
false,
false,
6047 return isCapturedIn(State,
true,
true,
6055 return isCapturedIn(State,
true,
true,
6062 bool IsKnownNoCapture;
6063 const AANoCapture *ArgNoCaptureAA =
nullptr;
6065 A,
this, CSArgPos, DepClassTy::REQUIRED, IsKnownNoCapture,
false,
6067 if (IsAssumedNoCapture)
6068 return isCapturedIn(State,
false,
false,
6072 return isCapturedIn(State,
false,
false,
6077 return isCapturedIn(State,
true,
true,
6084 static bool isCapturedIn(AANoCapture::StateType &State,
bool CapturedInMem,
6085 bool CapturedInInt,
bool CapturedInRet) {
6086 LLVM_DEBUG(
dbgs() <<
" - captures [Mem " << CapturedInMem <<
"|Int "
6087 << CapturedInInt <<
"|Ret " << CapturedInRet <<
"]\n");
6099 const IRPosition &IRP = getIRPosition();
6103 return indicatePessimisticFixpoint();
6110 return indicatePessimisticFixpoint();
6118 T.addKnownBits(NOT_CAPTURED_IN_MEM);
6120 addKnownBits(NOT_CAPTURED_IN_MEM);
6127 auto CheckReturnedArgs = [&](
bool &UsedAssumedInformation) {
6131 UsedAssumedInformation))
6133 bool SeenConstant =
false;
6134 for (
const AA::ValueAndContext &VAC :
Values) {
6138 SeenConstant =
true;
6140 VAC.
getValue() == getAssociatedArgument())
6146 bool IsKnownNoUnwind;
6149 bool IsVoidTy =
F->getReturnType()->isVoidTy();
6150 bool UsedAssumedInformation =
false;
6151 if (IsVoidTy || CheckReturnedArgs(UsedAssumedInformation)) {
6152 T.addKnownBits(NOT_CAPTURED_IN_RET);
6153 if (
T.isKnown(NOT_CAPTURED_IN_MEM))
6155 if (IsKnownNoUnwind && (IsVoidTy || !UsedAssumedInformation)) {
6156 addKnownBits(NOT_CAPTURED_IN_RET);
6157 if (isKnown(NOT_CAPTURED_IN_MEM))
6158 return indicateOptimisticFixpoint();
6163 auto UseCheck = [&](
const Use &
U,
bool &Follow) ->
bool {
6172 return checkUse(
A,
T, U, Follow);
6175 if (!
A.checkForAllUses(UseCheck, *
this, *V))
6176 return indicatePessimisticFixpoint();
6179 auto Assumed = S.getAssumed();
6180 S.intersectAssumedBits(
T.getAssumed());
6181 if (!isAssumedNoCaptureMaybeReturned())
6182 return indicatePessimisticFixpoint();
6188struct AANoCaptureArgument final : AANoCaptureImpl {
6189 AANoCaptureArgument(
const IRPosition &IRP, Attributor &
A)
6190 : AANoCaptureImpl(IRP,
A) {}
6197struct AANoCaptureCallSiteArgument final : AANoCaptureImpl {
6198 AANoCaptureCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
6199 : AANoCaptureImpl(IRP,
A) {}
6207 Argument *Arg = getAssociatedArgument();
6209 return indicatePessimisticFixpoint();
6211 bool IsKnownNoCapture;
6212 const AANoCapture *ArgAA =
nullptr;
6214 A,
this, ArgPos, DepClassTy::REQUIRED, IsKnownNoCapture,
false,
6216 return ChangeStatus::UNCHANGED;
6218 return indicatePessimisticFixpoint();
6223 void trackStatistics()
const override {
6229struct AANoCaptureFloating final : AANoCaptureImpl {
6230 AANoCaptureFloating(
const IRPosition &IRP, Attributor &
A)
6231 : AANoCaptureImpl(IRP,
A) {}
6234 void trackStatistics()
const override {
6240struct AANoCaptureReturned final : AANoCaptureImpl {
6241 AANoCaptureReturned(
const IRPosition &IRP, Attributor &
A)
6242 : AANoCaptureImpl(IRP,
A) {
6257 void trackStatistics()
const override {}
6261struct AANoCaptureCallSiteReturned final : AANoCaptureImpl {
6262 AANoCaptureCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
6263 : AANoCaptureImpl(IRP,
A) {}
6269 determineFunctionCaptureCapabilities(getIRPosition(), *
F, *
this);
6273 void trackStatistics()
const override {
6290 dbgs() <<
"[ValueSimplify] is assumed to be "
6293 dbgs() <<
"[ValueSimplify] is assumed to be <none>\n";
6305 if (getAssociatedValue().
getType()->isVoidTy())
6306 indicatePessimisticFixpoint();
6307 if (
A.hasSimplificationCallback(getIRPosition()))
6308 indicatePessimisticFixpoint();
6312 const std::string getAsStr(Attributor *
A)
const override {
6314 dbgs() <<
"SAV: " << (bool)SimplifiedAssociatedValue <<
" ";
6315 if (SimplifiedAssociatedValue && *SimplifiedAssociatedValue)
6316 dbgs() <<
"SAV: " << **SimplifiedAssociatedValue <<
" ";
6318 return isValidState() ? (isAtFixpoint() ?
"simplified" :
"maybe-simple")
6323 void trackStatistics()
const override {}
6326 std::optional<Value *>
6327 getAssumedSimplifiedValue(Attributor &
A)
const override {
6328 return SimplifiedAssociatedValue;
6335 static Value *ensureType(Attributor &
A,
Value &V,
Type &Ty, Instruction *CtxI,
6339 if (CtxI &&
V.getType()->canLosslesslyBitCastTo(&Ty))
6341 : BitCastInst::CreatePointerBitCastOrAddrSpaceCast(
6350 static Value *reproduceInst(Attributor &
A,
6351 const AbstractAttribute &QueryingAA,
6352 Instruction &
I,
Type &Ty, Instruction *CtxI,
6354 assert(CtxI &&
"Cannot reproduce an instruction without context!");
6355 if (
Check && (
I.mayReadFromMemory() ||
6360 Value *NewOp = reproduceValue(
A, QueryingAA, *
Op, Ty, CtxI,
Check, VMap);
6362 assert(
Check &&
"Manifest of new value unexpectedly failed!");
6384 static Value *reproduceValue(Attributor &
A,
6385 const AbstractAttribute &QueryingAA,
Value &V,
6386 Type &Ty, Instruction *CtxI,
bool Check,
6388 if (
const auto &NewV = VMap.
lookup(&V))
6390 bool UsedAssumedInformation =
false;
6391 std::optional<Value *> SimpleV =
A.getAssumedSimplified(
6393 if (!SimpleV.has_value())
6397 EffectiveV = *SimpleV;
6402 return ensureType(
A, *EffectiveV, Ty, CtxI,
Check);
6404 if (
Value *NewV = reproduceInst(
A, QueryingAA, *
I, Ty, CtxI,
Check, VMap))
6405 return ensureType(
A, *NewV, Ty, CtxI,
Check);
6411 Value *manifestReplacementValue(Attributor &
A, Instruction *CtxI)
const {
6412 Value *NewV = SimplifiedAssociatedValue
6413 ? *SimplifiedAssociatedValue
6415 if (NewV && NewV != &getAssociatedValue()) {
6419 if (reproduceValue(
A, *
this, *NewV, *getAssociatedType(), CtxI,
6421 return reproduceValue(
A, *
this, *NewV, *getAssociatedType(), CtxI,
6429 bool checkAndUpdate(Attributor &
A,
const AbstractAttribute &QueryingAA,
6430 const IRPosition &IRP,
bool Simplify =
true) {
6431 bool UsedAssumedInformation =
false;
6434 QueryingValueSimplified =
A.getAssumedSimplified(
6436 return unionAssumed(QueryingValueSimplified);
6440 template <
typename AAType>
bool askSimplifiedValueFor(Attributor &
A) {
6441 if (!getAssociatedValue().
getType()->isIntegerTy())
6446 A.getAAFor<AAType>(*
this, getIRPosition(), DepClassTy::NONE);
6450 std::optional<Constant *> COpt = AA->getAssumedConstant(
A);
6453 SimplifiedAssociatedValue = std::nullopt;
6454 A.recordDependence(*AA, *
this, DepClassTy::OPTIONAL);
6457 if (
auto *
C = *COpt) {
6458 SimplifiedAssociatedValue =
C;
6459 A.recordDependence(*AA, *
this, DepClassTy::OPTIONAL);
6465 bool askSimplifiedValueForOtherAAs(Attributor &
A) {
6466 if (askSimplifiedValueFor<AAValueConstantRange>(
A))
6468 if (askSimplifiedValueFor<AAPotentialConstantValues>(
A))
6476 for (
auto &U : getAssociatedValue().uses()) {
6481 IP =
PHI->getIncomingBlock(U)->getTerminator();
6482 if (
auto *NewV = manifestReplacementValue(
A, IP)) {
6484 <<
" -> " << *NewV <<
" :: " << *
this <<
"\n");
6485 if (
A.changeUseAfterManifest(U, *NewV))
6486 Changed = ChangeStatus::CHANGED;
6490 return Changed | AAValueSimplify::manifest(
A);
6495 SimplifiedAssociatedValue = &getAssociatedValue();
6496 return AAValueSimplify::indicatePessimisticFixpoint();
6500struct AAValueSimplifyArgument final : AAValueSimplifyImpl {
6501 AAValueSimplifyArgument(
const IRPosition &IRP, Attributor &
A)
6502 : AAValueSimplifyImpl(IRP,
A) {}
6505 AAValueSimplifyImpl::initialize(
A);
6506 if (
A.hasAttr(getIRPosition(),
6507 {Attribute::InAlloca, Attribute::Preallocated,
6508 Attribute::StructRet, Attribute::Nest, Attribute::ByVal},
6510 indicatePessimisticFixpoint();
6517 Argument *Arg = getAssociatedArgument();
6523 return indicatePessimisticFixpoint();
6526 auto Before = SimplifiedAssociatedValue;
6528 auto PredForCallSite = [&](AbstractCallSite ACS) {
6529 const IRPosition &ACSArgPos =
6540 bool UsedAssumedInformation =
false;
6541 std::optional<Constant *> SimpleArgOp =
6542 A.getAssumedConstant(ACSArgPos, *
this, UsedAssumedInformation);
6549 return unionAssumed(*SimpleArgOp);
6554 bool UsedAssumedInformation =
false;
6555 if (hasCallBaseContext() &&
6556 getCallBaseContext()->getCalledOperand() == Arg->
getParent())
6558 AbstractCallSite(&getCallBaseContext()->getCalledOperandUse()));
6560 Success =
A.checkForAllCallSites(PredForCallSite, *
this,
true,
6561 UsedAssumedInformation);
6564 if (!askSimplifiedValueForOtherAAs(
A))
6565 return indicatePessimisticFixpoint();
6568 return Before == SimplifiedAssociatedValue ? ChangeStatus::UNCHANGED
6569 : ChangeStatus ::CHANGED;
6573 void trackStatistics()
const override {
6578struct AAValueSimplifyReturned : AAValueSimplifyImpl {
6579 AAValueSimplifyReturned(
const IRPosition &IRP, Attributor &
A)
6580 : AAValueSimplifyImpl(IRP,
A) {}
6583 std::optional<Value *>
6584 getAssumedSimplifiedValue(Attributor &
A)
const override {
6585 if (!isValidState())
6587 return SimplifiedAssociatedValue;
6592 auto Before = SimplifiedAssociatedValue;
6596 return checkAndUpdate(
6601 bool UsedAssumedInformation =
false;
6602 if (!
A.checkForAllInstructions(ReturnInstCB, *
this, {Instruction::Ret},
6603 UsedAssumedInformation))
6604 if (!askSimplifiedValueForOtherAAs(
A))
6605 return indicatePessimisticFixpoint();
6608 return Before == SimplifiedAssociatedValue ? ChangeStatus::UNCHANGED
6609 : ChangeStatus ::CHANGED;
6615 return ChangeStatus::UNCHANGED;
6619 void trackStatistics()
const override {
6624struct AAValueSimplifyFloating : AAValueSimplifyImpl {
6625 AAValueSimplifyFloating(
const IRPosition &IRP, Attributor &
A)
6626 : AAValueSimplifyImpl(IRP,
A) {}
6630 AAValueSimplifyImpl::initialize(
A);
6631 Value &
V = getAnchorValue();
6635 indicatePessimisticFixpoint();
6640 auto Before = SimplifiedAssociatedValue;
6641 if (!askSimplifiedValueForOtherAAs(
A))
6642 return indicatePessimisticFixpoint();
6645 return Before == SimplifiedAssociatedValue ? ChangeStatus::UNCHANGED
6646 : ChangeStatus ::CHANGED;
6650 void trackStatistics()
const override {
6655struct AAValueSimplifyFunction : AAValueSimplifyImpl {
6656 AAValueSimplifyFunction(
const IRPosition &IRP, Attributor &
A)
6657 : AAValueSimplifyImpl(IRP,
A) {}
6661 SimplifiedAssociatedValue =
nullptr;
6662 indicateOptimisticFixpoint();
6667 "AAValueSimplify(Function|CallSite)::updateImpl will not be called");
6670 void trackStatistics()
const override {
6675struct AAValueSimplifyCallSite : AAValueSimplifyFunction {
6676 AAValueSimplifyCallSite(
const IRPosition &IRP, Attributor &
A)
6677 : AAValueSimplifyFunction(IRP,
A) {}
6679 void trackStatistics()
const override {
6684struct AAValueSimplifyCallSiteReturned : AAValueSimplifyImpl {
6685 AAValueSimplifyCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
6686 : AAValueSimplifyImpl(IRP,
A) {}
6689 AAValueSimplifyImpl::initialize(
A);
6690 Function *Fn = getAssociatedFunction();
6691 assert(Fn &&
"Did expect an associted function");
6692 for (Argument &Arg : Fn->
args()) {
6697 checkAndUpdate(
A, *
this, IRP))
6698 indicateOptimisticFixpoint();
6700 indicatePessimisticFixpoint();
6708 return indicatePessimisticFixpoint();
6711 void trackStatistics()
const override {
6716struct AAValueSimplifyCallSiteArgument : AAValueSimplifyFloating {
6717 AAValueSimplifyCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
6718 : AAValueSimplifyFloating(IRP,
A) {}
6724 auto *FloatAA =
A.lookupAAFor<AAValueSimplify>(
6726 if (FloatAA && FloatAA->getState().isValidState())
6729 if (
auto *NewV = manifestReplacementValue(
A, getCtxI())) {
6731 ->getArgOperandUse(getCallSiteArgNo());
6732 if (
A.changeUseAfterManifest(U, *NewV))
6733 Changed = ChangeStatus::CHANGED;
6736 return Changed | AAValueSimplify::manifest(
A);
6739 void trackStatistics()
const override {
6747struct AAHeapToStackFunction final :
public AAHeapToStack {
6749 static bool isGlobalizedLocal(
const CallBase &CB) {
6751 return A.
isValid() &&
A.getValueAsString() ==
"__kmpc_alloc_shared";
6754 struct AllocationInfo {
6759 bool IsGlobalizedLocal =
false;
6766 } Status = STACK_DUE_TO_USE;
6770 bool HasPotentiallyFreeingUnknownUses =
false;
6774 bool MoveAllocaIntoEntry =
true;
6777 SmallSetVector<CallBase *, 1> PotentialFreeCalls{};
6780 struct DeallocationInfo {
6788 bool MightFreeUnknownObjects =
false;
6791 SmallSetVector<CallBase *, 1> PotentialAllocationCalls{};
6794 AAHeapToStackFunction(
const IRPosition &IRP, Attributor &
A)
6795 : AAHeapToStack(IRP,
A) {}
6797 ~AAHeapToStackFunction()
override {
6800 for (
auto &It : AllocationInfos)
6801 It.second->~AllocationInfo();
6802 for (
auto &It : DeallocationInfos)
6803 It.second->~DeallocationInfo();
6807 AAHeapToStack::initialize(
A);
6810 const auto *TLI =
A.getInfoCache().getTargetLibraryInfoForFunction(*
F);
6817 DeallocationInfos[CB] =
new (
A.Allocator) DeallocationInfo{CB, FreedOp};
6824 auto *I8Ty = Type::getInt8Ty(CB->
getParent()->getContext());
6826 AllocationInfo *AI =
new (
A.Allocator) AllocationInfo{CB};
6827 AllocationInfos[CB] = AI;
6828 AI->IsGlobalizedLocal = isGlobalizedLocal(*CB);
6834 bool UsedAssumedInformation =
false;
6835 bool Success =
A.checkForAllCallLikeInstructions(
6836 AllocationIdentifierCB, *
this, UsedAssumedInformation,
6840 assert(
Success &&
"Did not expect the call base visit callback to fail!");
6843 [](
const IRPosition &,
const AbstractAttribute *,
6844 bool &) -> std::optional<Value *> {
return nullptr; };
6845 for (
const auto &It : AllocationInfos)
6848 for (
const auto &It : DeallocationInfos)
6853 const std::string getAsStr(Attributor *
A)
const override {
6854 unsigned NumH2SMallocs = 0, NumInvalidMallocs = 0;
6855 for (
const auto &It : AllocationInfos) {
6856 if (It.second->Status == AllocationInfo::INVALID)
6857 ++NumInvalidMallocs;
6861 return "[H2S] Mallocs Good/Bad: " + std::to_string(NumH2SMallocs) +
"/" +
6862 std::to_string(NumInvalidMallocs);
6866 void trackStatistics()
const override {
6869 "Number of malloc/calloc/aligned_alloc calls converted to allocas");
6870 for (
const auto &It : AllocationInfos)
6871 if (It.second->Status != AllocationInfo::INVALID)
6875 bool isAssumedHeapToStack(
const CallBase &CB)
const override {
6877 if (AllocationInfo *AI =
6878 AllocationInfos.lookup(
const_cast<CallBase *
>(&CB)))
6879 return AI->Status != AllocationInfo::INVALID;
6883 bool isAssumedHeapToStackRemovedFree(CallBase &CB)
const override {
6884 if (!isValidState())
6887 for (
const auto &It : AllocationInfos) {
6888 AllocationInfo &AI = *It.second;
6889 if (AI.Status == AllocationInfo::INVALID)
6892 if (AI.PotentialFreeCalls.count(&CB))
6900 assert(getState().isValidState() &&
6901 "Attempted to manifest an invalid state!");
6905 const auto *TLI =
A.getInfoCache().getTargetLibraryInfoForFunction(*
F);
6907 for (
auto &It : AllocationInfos) {
6908 AllocationInfo &AI = *It.second;
6909 if (AI.Status == AllocationInfo::INVALID)
6912 for (CallBase *FreeCall : AI.PotentialFreeCalls) {
6913 LLVM_DEBUG(
dbgs() <<
"H2S: Removing free call: " << *FreeCall <<
"\n");
6914 A.deleteAfterManifest(*FreeCall);
6915 HasChanged = ChangeStatus::CHANGED;
6918 LLVM_DEBUG(
dbgs() <<
"H2S: Removing malloc-like call: " << *AI.CB
6921 auto Remark = [&](OptimizationRemark
OR) {
6922 if (AI.IsGlobalizedLocal)
6923 return OR <<
"Moving globalized variable to the stack.";
6924 return OR <<
"Moving memory allocation from the heap to the stack.";
6926 if (AI.IsGlobalizedLocal)
6927 A.emitRemark<OptimizationRemark>(AI.CB,
"OMP110",
Remark);
6929 A.emitRemark<OptimizationRemark>(AI.CB,
"HeapToStack",
Remark);
6931 const DataLayout &
DL =
A.getInfoCache().getDL();
6933 std::optional<APInt> SizeAPI =
getSize(
A, *
this, AI);
6935 Size = ConstantInt::get(AI.CB->getContext(), *SizeAPI);
6937 ObjectSizeOpts Opts;
6938 ObjectSizeOffsetEvaluator Eval(*AI.CB->getModule(), TLI, Opts);
6939 SizeOffsetValue SizeOffsetPair = Eval.compute(AI.CB);
6946 ?
F->getEntryBlock().begin()
6947 : AI.CB->getIterator();
6950 if (MaybeAlign RetAlign = AI.CB->getRetAlign())
6951 Alignment = std::max(Alignment, *RetAlign);
6953 std::optional<APInt> AlignmentAPI = getAPInt(
A, *
this, *Align);
6954 assert(AlignmentAPI && AlignmentAPI->getZExtValue() > 0 &&
6955 "Expected an alignment during manifest!");
6957 std::max(Alignment,
assumeAligned(AlignmentAPI->getZExtValue()));
6961 unsigned AS =
DL.getAllocaAddrSpace();
6963 new AllocaInst(Type::getInt8Ty(
F->getContext()), AS,
Size, Alignment,
6964 AI.CB->getName() +
".h2s", IP);
6966 if (Alloca->
getType() != AI.CB->getType())
6967 Alloca = BitCastInst::CreatePointerBitCastOrAddrSpaceCast(
6968 Alloca, AI.CB->getType(),
"malloc_cast", AI.CB->getIterator());
6970 auto *I8Ty = Type::getInt8Ty(
F->getContext());
6973 "Must be able to materialize initial memory state of allocation");
6978 auto *NBB =
II->getNormalDest();
6980 A.deleteAfterManifest(*AI.CB);
6982 A.deleteAfterManifest(*AI.CB);
6991 Builder.CreateMemSet(Alloca, InitVal,
Size, std::nullopt);
6993 HasChanged = ChangeStatus::CHANGED;
6999 std::optional<APInt> getAPInt(Attributor &
A,
const AbstractAttribute &AA,
7001 bool UsedAssumedInformation =
false;
7002 std::optional<Constant *> SimpleV =
7003 A.getAssumedConstant(V, AA, UsedAssumedInformation);
7005 return APInt(64, 0);
7007 return CI->getValue();
7008 return std::nullopt;
7011 std::optional<APInt>
getSize(Attributor &
A,
const AbstractAttribute &AA,
7012 AllocationInfo &AI) {
7014 bool UsedAssumedInformation =
false;
7015 if (std::optional<Constant *> SimpleV =
7016 A.getAssumedConstant(*V, AA, UsedAssumedInformation))
7023 const auto *TLI =
A.getInfoCache().getTargetLibraryInfoForFunction(*
F);
7029 MapVector<CallBase *, AllocationInfo *> AllocationInfos;
7033 MapVector<CallBase *, DeallocationInfo *> DeallocationInfos;
7038ChangeStatus AAHeapToStackFunction::updateImpl(Attributor &
A) {
7041 const auto *TLI =
A.getInfoCache().getTargetLibraryInfoForFunction(*
F);
7043 const auto *LivenessAA =
7046 MustBeExecutedContextExplorer *Explorer =
7047 A.getInfoCache().getMustBeExecutedContextExplorer();
7049 bool StackIsAccessibleByOtherThreads =
7050 A.getInfoCache().stackIsAccessibleByOtherThreads();
7053 A.getInfoCache().getAnalysisResultForFunction<LoopAnalysis>(*F);
7054 std::optional<bool> MayContainIrreducibleControl;
7056 if (&
F->getEntryBlock() == &BB)
7058 if (!MayContainIrreducibleControl.has_value())
7060 if (*MayContainIrreducibleControl)
7069 bool HasUpdatedFrees =
false;
7071 auto UpdateFrees = [&]() {
7072 HasUpdatedFrees =
true;
7074 for (
auto &It : DeallocationInfos) {
7075 DeallocationInfo &DI = *It.second;
7078 if (DI.MightFreeUnknownObjects)
7082 bool UsedAssumedInformation =
false;
7083 if (
A.isAssumedDead(*DI.CB,
this, LivenessAA, UsedAssumedInformation,
7090 LLVM_DEBUG(
dbgs() <<
"[H2S] Unknown underlying object for free!\n");
7091 DI.MightFreeUnknownObjects =
true;
7104 DI.MightFreeUnknownObjects =
true;
7108 AllocationInfo *AI = AllocationInfos.lookup(ObjCB);
7110 LLVM_DEBUG(
dbgs() <<
"[H2S] Free of a non-allocation object: " << *Obj
7112 DI.MightFreeUnknownObjects =
true;
7116 DI.PotentialAllocationCalls.insert(ObjCB);
7120 auto FreeCheck = [&](AllocationInfo &AI) {
7124 if (!StackIsAccessibleByOtherThreads) {
7129 dbgs() <<
"[H2S] found an escaping use, stack is not accessible by "
7130 "other threads and function is not nosync:\n");
7134 if (!HasUpdatedFrees)
7138 if (AI.PotentialFreeCalls.size() != 1) {
7140 << AI.PotentialFreeCalls.size() <<
"\n");
7143 CallBase *UniqueFree = *AI.PotentialFreeCalls.begin();
7144 DeallocationInfo *DI = DeallocationInfos.lookup(UniqueFree);
7147 dbgs() <<
"[H2S] unique free call was not known as deallocation call "
7148 << *UniqueFree <<
"\n");
7151 if (DI->MightFreeUnknownObjects) {
7153 dbgs() <<
"[H2S] unique free call might free unknown allocations\n");
7156 if (DI->PotentialAllocationCalls.empty())
7158 if (DI->PotentialAllocationCalls.size() > 1) {
7160 << DI->PotentialAllocationCalls.size()
7161 <<
" different allocations\n");
7164 if (*DI->PotentialAllocationCalls.begin() != AI.CB) {
7167 <<
"[H2S] unique free call not known to free this allocation but "
7168 << **DI->PotentialAllocationCalls.begin() <<
"\n");
7173 if (!AI.IsGlobalizedLocal) {
7175 if (!Explorer || !Explorer->findInContextOf(UniqueFree, CtxI)) {
7176 LLVM_DEBUG(
dbgs() <<
"[H2S] unique free call might not be executed "
7177 "with the allocation "
7178 << *UniqueFree <<
"\n");
7185 auto UsesCheck = [&](AllocationInfo &AI) {
7186 bool ValidUsesOnly =
true;
7188 auto Pred = [&](
const Use &
U,
bool &Follow) ->
bool {
7193 if (
SI->getValueOperand() ==
U.get()) {
7195 <<
"[H2S] escaping store to memory: " << *UserI <<
"\n");
7196 ValidUsesOnly =
false;
7205 if (DeallocationInfos.count(CB)) {
7206 AI.PotentialFreeCalls.insert(CB);
7213 bool IsKnownNoCapture;
7222 if (!IsAssumedNoCapture ||
7223 (!AI.IsGlobalizedLocal && !IsAssumedNoFree)) {
7224 AI.HasPotentiallyFreeingUnknownUses |= !IsAssumedNoFree;
7227 auto Remark = [&](OptimizationRemarkMissed ORM) {
7229 <<
"Could not move globalized variable to the stack. "
7230 "Variable is potentially captured in call. Mark "
7231 "parameter as `__attribute__((noescape))` to override.";
7234 if (ValidUsesOnly && AI.IsGlobalizedLocal)
7235 A.emitRemark<OptimizationRemarkMissed>(CB,
"OMP113",
Remark);
7238 ValidUsesOnly =
false;
7251 ValidUsesOnly =
false;
7254 if (!
A.checkForAllUses(Pred, *
this, *AI.CB,
false,
7256 [&](
const Use &OldU,
const Use &NewU) {
7257 auto *SI = dyn_cast<StoreInst>(OldU.getUser());
7258 return !SI || StackIsAccessibleByOtherThreads ||
7259 AA::isAssumedThreadLocalObject(
7260 A, *SI->getPointerOperand(), *this);
7263 return ValidUsesOnly;
7268 for (
auto &It : AllocationInfos) {
7269 AllocationInfo &AI = *It.second;
7270 if (AI.Status == AllocationInfo::INVALID)
7274 std::optional<APInt> APAlign = getAPInt(
A, *
this, *Align);
7278 LLVM_DEBUG(
dbgs() <<
"[H2S] Unknown allocation alignment: " << *AI.CB
7280 AI.Status = AllocationInfo::INVALID;
7285 !APAlign->isPowerOf2()) {
7286 LLVM_DEBUG(
dbgs() <<
"[H2S] Invalid allocation alignment: " << APAlign
7288 AI.Status = AllocationInfo::INVALID;
7299 dbgs() <<
"[H2S] Unknown allocation size: " << *AI.CB <<
"\n";
7301 dbgs() <<
"[H2S] Allocation size too large: " << *AI.CB <<
" vs. "
7305 AI.Status = AllocationInfo::INVALID;
7311 switch (AI.Status) {
7312 case AllocationInfo::STACK_DUE_TO_USE:
7315 AI.Status = AllocationInfo::STACK_DUE_TO_FREE;
7317 case AllocationInfo::STACK_DUE_TO_FREE:
7320 AI.Status = AllocationInfo::INVALID;
7323 case AllocationInfo::INVALID:
7330 bool IsGlobalizedLocal = AI.IsGlobalizedLocal;
7331 if (AI.MoveAllocaIntoEntry &&
7332 (!
Size.has_value() ||
7333 (!IsGlobalizedLocal && IsInLoop(*AI.CB->getParent()))))
7334 AI.MoveAllocaIntoEntry =
false;
7343struct AAPrivatizablePtrImpl :
public AAPrivatizablePtr {
7344 AAPrivatizablePtrImpl(
const IRPosition &IRP, Attributor &
A)
7345 : AAPrivatizablePtr(IRP,
A), PrivatizableType(std::nullopt) {}
7348 AAPrivatizablePtr::indicatePessimisticFixpoint();
7349 PrivatizableType =
nullptr;
7350 return ChangeStatus::CHANGED;
7356 virtual std::optional<Type *> identifyPrivatizableType(Attributor &
A) = 0;
7360 std::optional<Type *> combineTypes(std::optional<Type *> T0,
7361 std::optional<Type *>
T1) {
7371 std::optional<Type *> getPrivatizableType()
const override {
7372 return PrivatizableType;
7375 const std::string getAsStr(Attributor *
A)
const override {
7376 return isAssumedPrivatizablePtr() ?
"[priv]" :
"[no-priv]";
7380 std::optional<Type *> PrivatizableType;
7385struct AAPrivatizablePtrArgument final :
public AAPrivatizablePtrImpl {
7386 AAPrivatizablePtrArgument(
const IRPosition &IRP, Attributor &
A)
7387 : AAPrivatizablePtrImpl(IRP,
A) {}
7390 std::optional<Type *> identifyPrivatizableType(Attributor &
A)
override {
7393 bool UsedAssumedInformation =
false;
7395 A.getAttrs(getIRPosition(), {Attribute::ByVal},
Attrs,
7397 if (!
Attrs.empty() &&
7398 A.checkForAllCallSites([](AbstractCallSite ACS) { return true; }, *
this,
7399 true, UsedAssumedInformation))
7400 return Attrs[0].getValueAsType();
7402 std::optional<Type *> Ty;
7403 unsigned ArgNo = getIRPosition().getCallSiteArgNo();
7411 auto CallSiteCheck = [&](AbstractCallSite ACS) {
7420 A.getAAFor<AAPrivatizablePtr>(*
this, ACSArgPos, DepClassTy::REQUIRED);
7423 std::optional<Type *> CSTy = PrivCSArgAA->getPrivatizableType();
7426 dbgs() <<
"[AAPrivatizablePtr] ACSPos: " << ACSArgPos <<
", CSTy: ";
7430 dbgs() <<
"<nullptr>";
7435 Ty = combineTypes(Ty, CSTy);
7438 dbgs() <<
" : New Type: ";
7440 (*Ty)->print(
dbgs());
7442 dbgs() <<
"<nullptr>";
7451 if (!
A.checkForAllCallSites(CallSiteCheck, *
this,
true,
7452 UsedAssumedInformation))
7459 PrivatizableType = identifyPrivatizableType(
A);
7460 if (!PrivatizableType)
7461 return ChangeStatus::UNCHANGED;
7462 if (!*PrivatizableType)
7463 return indicatePessimisticFixpoint();
7468 DepClassTy::OPTIONAL);
7471 if (!
A.hasAttr(getIRPosition(), Attribute::ByVal) &&
7474 return indicatePessimisticFixpoint();
7480 identifyReplacementTypes(*PrivatizableType, ReplacementTypes);
7484 Function &Fn = *getIRPosition().getAnchorScope();
7486 A.getInfoCache().getAnalysisResultForFunction<TargetIRAnalysis>(Fn);
7488 LLVM_DEBUG(
dbgs() <<
"[AAPrivatizablePtr] Missing TTI for function "
7490 return indicatePessimisticFixpoint();
7493 auto CallSiteCheck = [&](AbstractCallSite ACS) {
7500 bool UsedAssumedInformation =
false;
7501 if (!
A.checkForAllCallSites(CallSiteCheck, *
this,
true,
7502 UsedAssumedInformation)) {
7504 dbgs() <<
"[AAPrivatizablePtr] ABI incompatibility detected for "
7506 return indicatePessimisticFixpoint();
7510 Argument *Arg = getAssociatedArgument();
7511 if (!
A.isValidFunctionSignatureRewrite(*Arg, ReplacementTypes)) {
7513 return indicatePessimisticFixpoint();
7520 auto IsCompatiblePrivArgOfCallback = [&](CallBase &CB) {
7523 for (
const Use *U : CallbackUses) {
7524 AbstractCallSite CBACS(U);
7525 assert(CBACS && CBACS.isCallbackCall());
7526 for (Argument &CBArg : CBACS.getCalledFunction()->args()) {
7527 int CBArgNo = CBACS.getCallArgOperandNo(CBArg);
7531 <<
"[AAPrivatizablePtr] Argument " << *Arg
7532 <<
"check if can be privatized in the context of its parent ("
7534 <<
")\n[AAPrivatizablePtr] because it is an argument in a "
7536 << CBArgNo <<
"@" << CBACS.getCalledFunction()->getName()
7537 <<
")\n[AAPrivatizablePtr] " << CBArg <<
" : "
7538 << CBACS.getCallArgOperand(CBArg) <<
" vs "
7540 <<
"[AAPrivatizablePtr] " << CBArg <<
" : "
7541 << CBACS.getCallArgOperandNo(CBArg) <<
" vs " << ArgNo <<
"\n";
7544 if (CBArgNo !=
int(ArgNo))
7546 const auto *CBArgPrivAA =
A.getAAFor<AAPrivatizablePtr>(
7548 if (CBArgPrivAA && CBArgPrivAA->isValidState()) {
7549 auto CBArgPrivTy = CBArgPrivAA->getPrivatizableType();
7552 if (*CBArgPrivTy == PrivatizableType)
7557 dbgs() <<
"[AAPrivatizablePtr] Argument " << *Arg
7558 <<
" cannot be privatized in the context of its parent ("
7560 <<
")\n[AAPrivatizablePtr] because it is an argument in a "
7562 << CBArgNo <<
"@" << CBACS.getCalledFunction()->getName()
7563 <<
").\n[AAPrivatizablePtr] for which the argument "
7564 "privatization is not compatible.\n";
7574 auto IsCompatiblePrivArgOfDirectCS = [&](AbstractCallSite ACS) {
7578 "Expected a direct call operand for callback call operand");
7583 dbgs() <<
"[AAPrivatizablePtr] Argument " << *Arg
7584 <<
" check if be privatized in the context of its parent ("
7586 <<
")\n[AAPrivatizablePtr] because it is an argument in a "
7588 << DCArgNo <<
"@" << DCCallee->
getName() <<
").\n";
7591 if (
unsigned(DCArgNo) < DCCallee->
arg_size()) {
7592 const auto *DCArgPrivAA =
A.getAAFor<AAPrivatizablePtr>(
7594 DepClassTy::REQUIRED);
7595 if (DCArgPrivAA && DCArgPrivAA->isValidState()) {
7596 auto DCArgPrivTy = DCArgPrivAA->getPrivatizableType();
7599 if (*DCArgPrivTy == PrivatizableType)
7605 dbgs() <<
"[AAPrivatizablePtr] Argument " << *Arg
7606 <<
" cannot be privatized in the context of its parent ("
7608 <<
")\n[AAPrivatizablePtr] because it is an argument in a "
7611 <<
").\n[AAPrivatizablePtr] for which the argument "
7612 "privatization is not compatible.\n";
7620 auto IsCompatiblePrivArgOfOtherCallSite = [&](AbstractCallSite ACS) {
7624 return IsCompatiblePrivArgOfDirectCS(ACS);
7628 if (!
A.checkForAllCallSites(IsCompatiblePrivArgOfOtherCallSite, *
this,
true,
7629 UsedAssumedInformation))
7630 return indicatePessimisticFixpoint();
7632 return ChangeStatus::UNCHANGED;
7638 identifyReplacementTypes(
Type *PrivType,
7639 SmallVectorImpl<Type *> &ReplacementTypes) {
7642 assert(PrivType &&
"Expected privatizable type!");
7646 for (
unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++)
7647 ReplacementTypes.
push_back(PrivStructType->getElementType(u));
7649 ReplacementTypes.
append(PrivArrayType->getNumElements(),
7650 PrivArrayType->getElementType());
7661 assert(PrivType &&
"Expected privatizable type!");
7664 const DataLayout &
DL =
F.getDataLayout();
7668 const StructLayout *PrivStructLayout =
DL.getStructLayout(PrivStructType);
7669 for (
unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++) {
7672 new StoreInst(
F.getArg(ArgNo + u), Ptr, IP);
7675 Type *PointeeTy = PrivArrayType->getElementType();
7676 uint64_t PointeeTySize =
DL.getTypeStoreSize(PointeeTy);
7677 for (
unsigned u = 0, e = PrivArrayType->getNumElements(); u < e; u++) {
7679 new StoreInst(
F.getArg(ArgNo + u), Ptr, IP);
7682 new StoreInst(
F.getArg(ArgNo), &
Base, IP);
7688 void createReplacementValues(Align Alignment,
Type *PrivType,
7690 SmallVectorImpl<Value *> &ReplacementValues) {
7692 assert(PrivType &&
"Expected privatizable type!");
7700 const StructLayout *PrivStructLayout =
DL.getStructLayout(PrivStructType);
7701 for (
unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++) {
7702 Type *PointeeTy = PrivStructType->getElementType(u);
7705 LoadInst *
L =
new LoadInst(PointeeTy, Ptr,
"", IP->
getIterator());
7706 L->setAlignment(Alignment);
7710 Type *PointeeTy = PrivArrayType->getElementType();
7711 uint64_t PointeeTySize =
DL.getTypeStoreSize(PointeeTy);
7712 for (
unsigned u = 0, e = PrivArrayType->getNumElements(); u < e; u++) {
7714 LoadInst *
L =
new LoadInst(PointeeTy, Ptr,
"", IP->
getIterator());
7715 L->setAlignment(Alignment);
7720 L->setAlignment(Alignment);
7727 if (!PrivatizableType)
7728 return ChangeStatus::UNCHANGED;
7729 assert(*PrivatizableType &&
"Expected privatizable type!");
7735 bool UsedAssumedInformation =
false;
7736 if (!
A.checkForAllInstructions(
7737 [&](Instruction &
I) {
7738 CallInst &CI = cast<CallInst>(I);
7739 if (CI.isTailCall())
7740 TailCalls.push_back(&CI);
7743 *
this, {Instruction::Call}, UsedAssumedInformation))
7744 return ChangeStatus::UNCHANGED;
7746 Argument *Arg = getAssociatedArgument();
7749 const auto *AlignAA =
7756 [=](
const Attributor::ArgumentReplacementInfo &ARI,
7758 BasicBlock &EntryBB = ReplacementFn.getEntryBlock();
7760 const DataLayout &
DL = IP->getDataLayout();
7761 unsigned AS =
DL.getAllocaAddrSpace();
7762 Instruction *AI =
new AllocaInst(*PrivatizableType, AS,
7763 Arg->
getName() +
".priv", IP);
7764 createInitialization(*PrivatizableType, *AI, ReplacementFn,
7765 ArgIt->getArgNo(), IP);
7768 AI = BitCastInst::CreatePointerBitCastOrAddrSpaceCast(
7772 for (CallInst *CI : TailCalls)
7773 CI->setTailCall(
false);
7780 [=](
const Attributor::ArgumentReplacementInfo &ARI,
7781 AbstractCallSite ACS, SmallVectorImpl<Value *> &NewArgOperands) {
7784 createReplacementValues(
7785 AlignAA ? AlignAA->getAssumedAlign() :
Align(0),
7786 *PrivatizableType, ACS,
7794 identifyReplacementTypes(*PrivatizableType, ReplacementTypes);
7797 if (
A.registerFunctionSignatureRewrite(*Arg, ReplacementTypes,
7798 std::move(FnRepairCB),
7799 std::move(ACSRepairCB)))
7800 return ChangeStatus::CHANGED;
7801 return ChangeStatus::UNCHANGED;
7805 void trackStatistics()
const override {
7810struct AAPrivatizablePtrFloating :
public AAPrivatizablePtrImpl {
7811 AAPrivatizablePtrFloating(
const IRPosition &IRP, Attributor &
A)
7812 : AAPrivatizablePtrImpl(IRP,
A) {}
7817 indicatePessimisticFixpoint();
7822 "updateImpl will not be called");
7826 std::optional<Type *> identifyPrivatizableType(Attributor &
A)
override {
7829 LLVM_DEBUG(
dbgs() <<
"[AAPrivatizablePtr] No underlying object found!\n");
7836 return AI->getAllocatedType();
7838 auto *PrivArgAA =
A.getAAFor<AAPrivatizablePtr>(
7840 if (PrivArgAA && PrivArgAA->isAssumedPrivatizablePtr())
7841 return PrivArgAA->getPrivatizableType();
7844 LLVM_DEBUG(
dbgs() <<
"[AAPrivatizablePtr] Underlying object neither valid "
7845 "alloca nor privatizable argument: "
7851 void trackStatistics()
const override {
7856struct AAPrivatizablePtrCallSiteArgument final
7857 :
public AAPrivatizablePtrFloating {
7858 AAPrivatizablePtrCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
7859 : AAPrivatizablePtrFloating(IRP,
A) {}
7863 if (
A.hasAttr(getIRPosition(), Attribute::ByVal))
7864 indicateOptimisticFixpoint();
7869 PrivatizableType = identifyPrivatizableType(
A);
7870 if (!PrivatizableType)
7871 return ChangeStatus::UNCHANGED;
7872 if (!*PrivatizableType)
7873 return indicatePessimisticFixpoint();
7875 const IRPosition &IRP = getIRPosition();
7876 bool IsKnownNoCapture;
7878 A,
this, IRP, DepClassTy::REQUIRED, IsKnownNoCapture);
7879 if (!IsAssumedNoCapture) {
7880 LLVM_DEBUG(
dbgs() <<
"[AAPrivatizablePtr] pointer might be captured!\n");
7881 return indicatePessimisticFixpoint();
7884 bool IsKnownNoAlias;
7886 A,
this, IRP, DepClassTy::REQUIRED, IsKnownNoAlias)) {
7887 LLVM_DEBUG(
dbgs() <<
"[AAPrivatizablePtr] pointer might alias!\n");
7888 return indicatePessimisticFixpoint();
7893 LLVM_DEBUG(
dbgs() <<
"[AAPrivatizablePtr] pointer is written!\n");
7894 return indicatePessimisticFixpoint();
7897 return ChangeStatus::UNCHANGED;
7901 void trackStatistics()
const override {
7906struct AAPrivatizablePtrCallSiteReturned final
7907 :
public AAPrivatizablePtrFloating {
7908 AAPrivatizablePtrCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
7909 : AAPrivatizablePtrFloating(IRP,
A) {}
7914 indicatePessimisticFixpoint();
7918 void trackStatistics()
const override {
7923struct AAPrivatizablePtrReturned final :
public AAPrivatizablePtrFloating {
7924 AAPrivatizablePtrReturned(
const IRPosition &IRP, Attributor &
A)
7925 : AAPrivatizablePtrFloating(IRP,
A) {}
7930 indicatePessimisticFixpoint();
7934 void trackStatistics()
const override {
7944struct AAMemoryBehaviorImpl :
public AAMemoryBehavior {
7945 AAMemoryBehaviorImpl(
const IRPosition &IRP, Attributor &
A)
7946 : AAMemoryBehavior(IRP,
A) {}
7950 intersectAssumedBits(BEST_STATE);
7951 getKnownStateFromValue(
A, getIRPosition(), getState());
7952 AAMemoryBehavior::initialize(
A);
7956 static void getKnownStateFromValue(Attributor &
A,
const IRPosition &IRP,
7957 BitIntegerState &State,
7958 bool IgnoreSubsumingPositions =
false) {
7960 A.getAttrs(IRP, AttrKinds, Attrs, IgnoreSubsumingPositions);
7962 switch (Attr.getKindAsEnum()) {
7963 case Attribute::ReadNone:
7966 case Attribute::ReadOnly:
7969 case Attribute::WriteOnly:
7978 if (!
I->mayReadFromMemory())
7980 if (!
I->mayWriteToMemory())
7986 void getDeducedAttributes(Attributor &
A, LLVMContext &Ctx,
7987 SmallVectorImpl<Attribute> &Attrs)
const override {
7990 Attrs.push_back(Attribute::get(Ctx, Attribute::ReadNone));
7992 Attrs.push_back(Attribute::get(Ctx, Attribute::ReadOnly));
7993 else if (isAssumedWriteOnly())
7994 Attrs.push_back(Attribute::get(Ctx, Attribute::WriteOnly));
8000 const IRPosition &IRP = getIRPosition();
8002 if (
A.hasAttr(IRP, Attribute::ReadNone,
8004 return ChangeStatus::UNCHANGED;
8013 return ChangeStatus::UNCHANGED;
8016 A.removeAttrs(IRP, AttrKinds);
8019 A.removeAttrs(IRP, Attribute::Writable);
8026 const std::string getAsStr(Attributor *
A)
const override {
8031 if (isAssumedWriteOnly())
8033 return "may-read/write";
8037 static const Attribute::AttrKind AttrKinds[3];
8041 Attribute::ReadNone, Attribute::ReadOnly, Attribute::WriteOnly};
8044struct AAMemoryBehaviorFloating : AAMemoryBehaviorImpl {
8045 AAMemoryBehaviorFloating(
const IRPosition &IRP, Attributor &
A)
8046 : AAMemoryBehaviorImpl(IRP,
A) {}
8052 void trackStatistics()
const override {
8057 else if (isAssumedWriteOnly())
8064 bool followUsersOfUseIn(Attributor &
A,
const Use &U,
8065 const Instruction *UserI);
8068 void analyzeUseIn(Attributor &
A,
const Use &U,
const Instruction *UserI);
8072struct AAMemoryBehaviorArgument : AAMemoryBehaviorFloating {
8073 AAMemoryBehaviorArgument(
const IRPosition &IRP, Attributor &
A)
8074 : AAMemoryBehaviorFloating(IRP,
A) {}
8078 intersectAssumedBits(BEST_STATE);
8079 const IRPosition &IRP = getIRPosition();
8083 bool HasByVal =
A.hasAttr(IRP, {Attribute::ByVal},
8085 getKnownStateFromValue(
A, IRP, getState(),
8092 return ChangeStatus::UNCHANGED;
8096 if (
A.hasAttr(getIRPosition(),
8097 {Attribute::InAlloca, Attribute::Preallocated})) {
8098 removeKnownBits(NO_WRITES);
8099 removeAssumedBits(NO_WRITES);
8101 A.removeAttrs(getIRPosition(), AttrKinds);
8102 return AAMemoryBehaviorFloating::manifest(
A);
8106 void trackStatistics()
const override {
8111 else if (isAssumedWriteOnly())
8116struct AAMemoryBehaviorCallSiteArgument final : AAMemoryBehaviorArgument {
8117 AAMemoryBehaviorCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
8118 : AAMemoryBehaviorArgument(IRP,
A) {}
8124 Argument *Arg = getAssociatedArgument();
8126 indicatePessimisticFixpoint();
8130 addKnownBits(NO_WRITES);
8131 removeKnownBits(NO_READS);
8132 removeAssumedBits(NO_READS);
8134 AAMemoryBehaviorArgument::initialize(
A);
8135 if (getAssociatedFunction()->isDeclaration())
8136 indicatePessimisticFixpoint();
8145 Argument *Arg = getAssociatedArgument();
8148 A.getAAFor<AAMemoryBehavior>(*
this, ArgPos, DepClassTy::REQUIRED);
8150 return indicatePessimisticFixpoint();
8155 void trackStatistics()
const override {
8160 else if (isAssumedWriteOnly())
8166struct AAMemoryBehaviorCallSiteReturned final : AAMemoryBehaviorFloating {
8167 AAMemoryBehaviorCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
8168 : AAMemoryBehaviorFloating(IRP,
A) {}
8172 AAMemoryBehaviorImpl::initialize(
A);
8177 return ChangeStatus::UNCHANGED;
8181 void trackStatistics()
const override {}
8185struct AAMemoryBehaviorFunction final :
public AAMemoryBehaviorImpl {
8186 AAMemoryBehaviorFunction(
const IRPosition &IRP, Attributor &
A)
8187 : AAMemoryBehaviorImpl(IRP,
A) {}
8203 else if (isAssumedWriteOnly())
8206 A.removeAttrs(getIRPosition(), AttrKinds);
8209 for (Argument &Arg :
F.args())
8211 return A.manifestAttrs(getIRPosition(),
8212 Attribute::getWithMemoryEffects(
F.getContext(), ME));
8216 void trackStatistics()
const override {
8221 else if (isAssumedWriteOnly())
8227struct AAMemoryBehaviorCallSite final
8228 : AACalleeToCallSite<AAMemoryBehavior, AAMemoryBehaviorImpl> {
8229 AAMemoryBehaviorCallSite(
const IRPosition &IRP, Attributor &
A)
8230 : AACalleeToCallSite<AAMemoryBehavior, AAMemoryBehaviorImpl>(IRP,
A) {}
8241 else if (isAssumedWriteOnly())
8244 A.removeAttrs(getIRPosition(), AttrKinds);
8247 for (Use &U : CB.
args())
8249 Attribute::Writable);
8250 return A.manifestAttrs(
8251 getIRPosition(), Attribute::getWithMemoryEffects(CB.
getContext(), ME));
8255 void trackStatistics()
const override {
8260 else if (isAssumedWriteOnly())
8265ChangeStatus AAMemoryBehaviorFunction::updateImpl(Attributor &
A) {
8268 auto AssumedState = getAssumed();
8275 const auto *MemBehaviorAA =
A.getAAFor<AAMemoryBehavior>(
8277 if (MemBehaviorAA) {
8278 intersectAssumedBits(MemBehaviorAA->
getAssumed());
8279 return !isAtFixpoint();
8284 if (
I.mayReadFromMemory())
8285 removeAssumedBits(NO_READS);
8286 if (
I.mayWriteToMemory())
8287 removeAssumedBits(NO_WRITES);
8288 return !isAtFixpoint();
8291 bool UsedAssumedInformation =
false;
8292 if (!
A.checkForAllReadWriteInstructions(CheckRWInst, *
this,
8293 UsedAssumedInformation))
8294 return indicatePessimisticFixpoint();
8300ChangeStatus AAMemoryBehaviorFloating::updateImpl(Attributor &
A) {
8302 const IRPosition &IRP = getIRPosition();
8313 const auto *FnMemAA =
8316 FnMemAssumedState = FnMemAA->getAssumed();
8317 S.addKnownBits(FnMemAA->getKnown());
8318 if ((S.getAssumed() & FnMemAA->getAssumed()) == S.getAssumed())
8324 auto AssumedState = S.getAssumed();
8330 bool IsKnownNoCapture;
8331 const AANoCapture *ArgNoCaptureAA =
nullptr;
8336 if (!IsAssumedNoCapture &&
8338 S.intersectAssumedBits(FnMemAssumedState);
8344 auto UsePred = [&](
const Use &
U,
bool &Follow) ->
bool {
8346 LLVM_DEBUG(
dbgs() <<
"[AAMemoryBehavior] Use: " << *U <<
" in " << *UserI
8354 Follow = followUsersOfUseIn(
A, U, UserI);
8358 analyzeUseIn(
A, U, UserI);
8360 return !isAtFixpoint();
8363 if (!
A.checkForAllUses(UsePred, *
this, getAssociatedValue()))
8364 return indicatePessimisticFixpoint();
8370bool AAMemoryBehaviorFloating::followUsersOfUseIn(Attributor &
A,
const Use &U,
8371 const Instruction *UserI) {
8389 if (
U.get()->getType()->isPointerTy()) {
8391 bool IsKnownNoCapture;
8400void AAMemoryBehaviorFloating::analyzeUseIn(Attributor &
A,
const Use &U,
8401 const Instruction *UserI) {
8408 case Instruction::Load:
8410 removeAssumedBits(NO_READS);
8413 case Instruction::Store:
8418 removeAssumedBits(NO_WRITES);
8420 indicatePessimisticFixpoint();
8423 case Instruction::Call:
8424 case Instruction::CallBr:
8425 case Instruction::Invoke: {
8432 indicatePessimisticFixpoint();
8439 removeAssumedBits(NO_READS);
8446 if (
U.get()->getType()->isPointerTy())
8450 const auto *MemBehaviorAA =
8456 intersectAssumedBits(MemBehaviorAA->
getAssumed());
8464 removeAssumedBits(NO_READS);
8466 removeAssumedBits(NO_WRITES);
8478 return "all memory";
8481 std::string S =
"memory:";
8487 S +=
"internal global,";
8489 S +=
"external global,";
8493 S +=
"inaccessible,";
8507 AccessKind2Accesses.fill(
nullptr);
8510 ~AAMemoryLocationImpl()
override {
8513 for (AccessSet *AS : AccessKind2Accesses)
8520 intersectAssumedBits(BEST_STATE);
8521 getKnownStateFromValue(
A, getIRPosition(), getState());
8522 AAMemoryLocation::initialize(
A);
8526 static void getKnownStateFromValue(Attributor &
A,
const IRPosition &IRP,
8527 BitIntegerState &State,
8528 bool IgnoreSubsumingPositions =
false) {
8537 bool UseArgMemOnly =
true;
8539 if (AnchorFn &&
A.isRunOn(*AnchorFn))
8543 A.getAttrs(IRP, {Attribute::Memory},
Attrs, IgnoreSubsumingPositions);
8552 State.
addKnownBits(inverseLocation(NO_INACCESSIBLE_MEM,
true,
true));
8557 State.
addKnownBits(inverseLocation(NO_ARGUMENT_MEM,
true,
true));
8561 A.manifestAttrs(IRP,
8562 Attribute::getWithMemoryEffects(
8571 NO_INACCESSIBLE_MEM | NO_ARGUMENT_MEM,
true,
true));
8575 A.manifestAttrs(IRP,
8576 Attribute::getWithMemoryEffects(
8586 void getDeducedAttributes(Attributor &
A, LLVMContext &Ctx,
8587 SmallVectorImpl<Attribute> &Attrs)
const override {
8594 else if (isAssumedInaccessibleMemOnly())
8595 Attrs.push_back(Attribute::getWithMemoryEffects(
8597 else if (isAssumedArgMemOnly())
8600 else if (isAssumedInaccessibleOrArgMemOnly())
8601 Attrs.push_back(Attribute::getWithMemoryEffects(
8611 const IRPosition &IRP = getIRPosition();
8615 if (DeducedAttrs.
size() != 1)
8616 return ChangeStatus::UNCHANGED;
8619 return A.manifestAttrs(IRP, Attribute::getWithMemoryEffects(
8624 bool checkForAllAccessesToMemoryKind(
8626 MemoryLocationsKind)>
8628 MemoryLocationsKind RequestedMLK)
const override {
8629 if (!isValidState())
8632 MemoryLocationsKind AssumedMLK = getAssumedNotAccessedLocation();
8633 if (AssumedMLK == NO_LOCATIONS)
8637 for (MemoryLocationsKind CurMLK = 1; CurMLK < NO_LOCATIONS;
8638 CurMLK *= 2, ++
Idx) {
8639 if (CurMLK & RequestedMLK)
8642 if (
const AccessSet *
Accesses = AccessKind2Accesses[Idx])
8643 for (
const AccessInfo &AI : *
Accesses)
8644 if (!Pred(AI.I, AI.Ptr, AI.Kind, CurMLK))
8657 MemoryLocationsKind KnownMLK = getKnown();
8659 for (MemoryLocationsKind CurMLK = 1; CurMLK < NO_LOCATIONS; CurMLK *= 2)
8660 if (!(CurMLK & KnownMLK))
8661 updateStateAndAccessesMap(getState(), CurMLK,
I,
nullptr,
Changed,
8662 getAccessKindFromInst(
I));
8663 return AAMemoryLocation::indicatePessimisticFixpoint();
8683 bool operator()(
const AccessInfo &
LHS,
const AccessInfo &
RHS)
const {
8687 return LHS.Ptr <
RHS.Ptr;
8688 if (
LHS.Kind !=
RHS.Kind)
8689 return LHS.Kind <
RHS.Kind;
8696 using AccessSet = SmallSet<AccessInfo, 2, AccessInfo>;
8697 std::array<AccessSet *, llvm::ConstantLog2<VALID_STATE>()>
8698 AccessKind2Accesses;
8703 categorizeArgumentPointerLocations(Attributor &
A, CallBase &CB,
8704 AAMemoryLocation::StateType &AccessedLocs,
8709 categorizeAccessedLocations(Attributor &
A, Instruction &
I,
bool &
Changed);
8712 AccessKind getAccessKindFromInst(
const Instruction *
I) {
8715 AK =
I->mayReadFromMemory() ? READ :
NONE;
8724 void updateStateAndAccessesMap(AAMemoryLocation::StateType &State,
8725 MemoryLocationsKind MLK,
const Instruction *
I,
8734 if (MLK == NO_UNKOWN_MEM)
8736 State.removeAssumedBits(MLK);
8741 void categorizePtrValue(Attributor &
A,
const Instruction &
I,
const Value &Ptr,
8742 AAMemoryLocation::StateType &State,
bool &
Changed,
8743 unsigned AccessAS = 0);
8749void AAMemoryLocationImpl::categorizePtrValue(
8750 Attributor &
A,
const Instruction &
I,
const Value &Ptr,
8752 LLVM_DEBUG(
dbgs() <<
"[AAMemoryLocation] Categorize pointer locations for "
8757 unsigned ObjectAS =
Obj.getType()->getPointerAddressSpace();
8759 MemoryLocationsKind MLK = NO_LOCATIONS;
8779 MLK = NO_ARGUMENT_MEM;
8785 if (GVar->isConstant())
8788 if (GV->hasLocalLinkage())
8789 MLK = NO_GLOBAL_INTERNAL_MEM;
8791 MLK = NO_GLOBAL_EXTERNAL_MEM;
8799 bool IsKnownNoAlias;
8803 MLK = NO_MALLOCED_MEM;
8805 MLK = NO_UNKOWN_MEM;
8807 MLK = NO_UNKOWN_MEM;
8810 assert(MLK != NO_LOCATIONS &&
"No location specified!");
8811 LLVM_DEBUG(
dbgs() <<
"[AAMemoryLocation] Ptr value can be categorized: "
8812 << Obj <<
" -> " << getMemoryLocationsAsStr(MLK) <<
"\n");
8814 getAccessKindFromInst(&
I));
8819 const auto *AA =
A.getAAFor<AAUnderlyingObjects>(
8823 dbgs() <<
"[AAMemoryLocation] Pointer locations not categorized\n");
8824 updateStateAndAccessesMap(
State, NO_UNKOWN_MEM, &
I,
nullptr,
Changed,
8825 getAccessKindFromInst(&
I));
8830 dbgs() <<
"[AAMemoryLocation] Accessed locations with pointer locations: "
8834void AAMemoryLocationImpl::categorizeArgumentPointerLocations(
8837 for (
unsigned ArgNo = 0,
E = CB.
arg_size(); ArgNo <
E; ++ArgNo) {
8846 const auto *ArgOpMemLocationAA =
8849 if (ArgOpMemLocationAA && ArgOpMemLocationAA->isAssumedReadNone())
8854 categorizePtrValue(
A, CB, *ArgOp, AccessedLocs,
Changed);
8859AAMemoryLocationImpl::categorizeAccessedLocations(Attributor &
A, Instruction &
I,
8861 LLVM_DEBUG(
dbgs() <<
"[AAMemoryLocation] Categorize accessed locations for "
8865 AccessedLocs.intersectAssumedBits(NO_LOCATIONS);
8870 const auto *CBMemLocationAA =
A.getAAFor<AAMemoryLocation>(
8873 <<
" [" << CBMemLocationAA <<
"]\n");
8874 if (!CBMemLocationAA) {
8875 updateStateAndAccessesMap(AccessedLocs, NO_UNKOWN_MEM, &
I,
nullptr,
8876 Changed, getAccessKindFromInst(&
I));
8877 return NO_UNKOWN_MEM;
8880 if (CBMemLocationAA->isAssumedReadNone())
8881 return NO_LOCATIONS;
8883 if (CBMemLocationAA->isAssumedInaccessibleMemOnly()) {
8884 updateStateAndAccessesMap(AccessedLocs, NO_INACCESSIBLE_MEM, &
I,
nullptr,
8885 Changed, getAccessKindFromInst(&
I));
8886 return AccessedLocs.getAssumed();
8889 uint32_t CBAssumedNotAccessedLocs =
8890 CBMemLocationAA->getAssumedNotAccessedLocation();
8893 uint32_t CBAssumedNotAccessedLocsNoArgMem =
8894 CBAssumedNotAccessedLocs | NO_ARGUMENT_MEM | NO_GLOBAL_MEM;
8896 for (MemoryLocationsKind CurMLK = 1; CurMLK < NO_LOCATIONS; CurMLK *= 2) {
8897 if (CBAssumedNotAccessedLocsNoArgMem & CurMLK)
8899 updateStateAndAccessesMap(AccessedLocs, CurMLK, &
I,
nullptr,
Changed,
8900 getAccessKindFromInst(&
I));
8905 bool HasGlobalAccesses = ((~CBAssumedNotAccessedLocs) & NO_GLOBAL_MEM);
8906 if (HasGlobalAccesses) {
8909 updateStateAndAccessesMap(AccessedLocs, MLK, &
I, Ptr,
Changed,
8910 getAccessKindFromInst(&
I));
8913 if (!CBMemLocationAA->checkForAllAccessesToMemoryKind(
8914 AccessPred, inverseLocation(NO_GLOBAL_MEM,
false,
false)))
8915 return AccessedLocs.getWorstState();
8919 dbgs() <<
"[AAMemoryLocation] Accessed state before argument handling: "
8920 << getMemoryLocationsAsStr(AccessedLocs.getAssumed()) <<
"\n");
8923 bool HasArgAccesses = ((~CBAssumedNotAccessedLocs) & NO_ARGUMENT_MEM);
8925 categorizeArgumentPointerLocations(
A, *CB, AccessedLocs,
Changed);
8928 dbgs() <<
"[AAMemoryLocation] Accessed state after argument handling: "
8929 << getMemoryLocationsAsStr(AccessedLocs.getAssumed()) <<
"\n");
8931 return AccessedLocs.getAssumed();
8936 dbgs() <<
"[AAMemoryLocation] Categorize memory access with pointer: "
8937 <<
I <<
" [" << *Ptr <<
"]\n");
8938 categorizePtrValue(
A,
I, *Ptr, AccessedLocs,
Changed,
8939 Ptr->getType()->getPointerAddressSpace());
8940 return AccessedLocs.getAssumed();
8943 LLVM_DEBUG(
dbgs() <<
"[AAMemoryLocation] Failed to categorize instruction: "
8945 updateStateAndAccessesMap(AccessedLocs, NO_UNKOWN_MEM, &
I,
nullptr,
Changed,
8946 getAccessKindFromInst(&
I));
8947 return AccessedLocs.getAssumed();
8951struct AAMemoryLocationFunction final :
public AAMemoryLocationImpl {
8952 AAMemoryLocationFunction(
const IRPosition &IRP, Attributor &
A)
8953 : AAMemoryLocationImpl(IRP,
A) {}
8958 const auto *MemBehaviorAA =
8959 A.getAAFor<AAMemoryBehavior>(*
this, getIRPosition(), DepClassTy::NONE);
8962 return indicateOptimisticFixpoint();
8964 "AAMemoryLocation was not read-none but AAMemoryBehavior was!");
8965 A.recordDependence(*MemBehaviorAA, *
this, DepClassTy::OPTIONAL);
8966 return ChangeStatus::UNCHANGED;
8970 auto AssumedState = getAssumed();
8974 MemoryLocationsKind MLK = categorizeAccessedLocations(
A,
I,
Changed);
8975 LLVM_DEBUG(
dbgs() <<
"[AAMemoryLocation] Accessed locations for " <<
I
8976 <<
": " << getMemoryLocationsAsStr(MLK) <<
"\n");
8977 removeAssumedBits(inverseLocation(MLK,
false,
false));
8980 return getAssumedNotAccessedLocation() != VALID_STATE;
8983 bool UsedAssumedInformation =
false;
8984 if (!
A.checkForAllReadWriteInstructions(CheckRWInst, *
this,
8985 UsedAssumedInformation))
8986 return indicatePessimisticFixpoint();
8988 Changed |= AssumedState != getAssumed();
8989 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
8993 void trackStatistics()
const override {
8996 else if (isAssumedArgMemOnly())
8998 else if (isAssumedInaccessibleMemOnly())
9000 else if (isAssumedInaccessibleOrArgMemOnly())
9006struct AAMemoryLocationCallSite final : AAMemoryLocationImpl {
9007 AAMemoryLocationCallSite(
const IRPosition &IRP, Attributor &
A)
9008 : AAMemoryLocationImpl(IRP,
A) {}
9019 A.getAAFor<AAMemoryLocation>(*
this, FnPos, DepClassTy::REQUIRED);
9021 return indicatePessimisticFixpoint();
9025 updateStateAndAccessesMap(getState(), MLK,
I, Ptr,
Changed,
9026 getAccessKindFromInst(
I));
9029 if (!FnAA->checkForAllAccessesToMemoryKind(AccessPred, ALL_LOCATIONS))
9030 return indicatePessimisticFixpoint();
9031 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
9035 void trackStatistics()
const override {
9045struct AADenormalFPMathImpl :
public AADenormalFPMath {
9046 AADenormalFPMathImpl(
const IRPosition &IRP, Attributor &
A)
9047 : AADenormalFPMath(IRP,
A) {}
9049 const std::string getAsStr(Attributor *
A)
const override {
9050 std::string Str(
"AADenormalFPMath[");
9051 raw_string_ostream OS(Str);
9053 DenormalState
Known = getKnown();
9054 if (
Known.Mode.isValid())
9055 OS <<
"denormal-fp-math=" <<
Known.Mode;
9059 if (
Known.ModeF32.isValid())
9060 OS <<
" denormal-fp-math-f32=" <<
Known.ModeF32;
9066struct AADenormalFPMathFunction final : AADenormalFPMathImpl {
9067 AADenormalFPMathFunction(
const IRPosition &IRP, Attributor &
A)
9068 : AADenormalFPMathImpl(IRP,
A) {}
9072 DenormalFPEnv DenormEnv =
F->getDenormalFPEnv();
9082 auto CheckCallSite = [=, &Change, &
A](AbstractCallSite CS) {
9085 <<
"->" << getAssociatedFunction()->
getName() <<
'\n');
9087 const auto *CallerInfo =
A.getAAFor<AADenormalFPMath>(
9093 CallerInfo->getState());
9097 bool AllCallSitesKnown =
true;
9098 if (!
A.checkForAllCallSites(CheckCallSite, *
this,
true, AllCallSitesKnown))
9099 return indicatePessimisticFixpoint();
9101 if (Change == ChangeStatus::CHANGED && isModeFixed())
9107 LLVMContext &Ctx = getAssociatedFunction()->getContext();
9113 DenormalFPEnv KnownEnv(
Known.Mode,
Known.ModeF32);
9116 AttrToRemove.
push_back(Attribute::DenormalFPEnv);
9119 Ctx, Attribute::DenormalFPEnv,
9120 DenormalFPEnv(
Known.Mode,
Known.ModeF32).toIntValue()));
9123 auto &IRP = getIRPosition();
9126 return A.removeAttrs(IRP, AttrToRemove) |
9127 A.manifestAttrs(IRP, AttrToAdd,
true);
9130 void trackStatistics()
const override {
9139struct AAValueConstantRangeImpl : AAValueConstantRange {
9140 using StateType = IntegerRangeState;
9141 AAValueConstantRangeImpl(
const IRPosition &IRP, Attributor &
A)
9142 : AAValueConstantRange(IRP,
A) {}
9146 if (
A.hasSimplificationCallback(getIRPosition())) {
9147 indicatePessimisticFixpoint();
9152 intersectKnown(getConstantRangeFromSCEV(
A, getCtxI()));
9155 intersectKnown(getConstantRangeFromLVI(
A, getCtxI()));
9159 const std::string getAsStr(Attributor *
A)
const override {
9161 llvm::raw_string_ostream OS(Str);
9163 getKnown().print(OS);
9165 getAssumed().print(OS);
9172 const SCEV *getSCEV(Attributor &
A,
const Instruction *
I =
nullptr)
const {
9173 if (!getAnchorScope())
9176 ScalarEvolution *SE =
9177 A.getInfoCache().getAnalysisResultForFunction<ScalarEvolutionAnalysis>(
9180 LoopInfo *LI =
A.getInfoCache().getAnalysisResultForFunction<LoopAnalysis>(
9186 const SCEV *S = SE->
getSCEV(&getAssociatedValue());
9195 ConstantRange getConstantRangeFromSCEV(Attributor &
A,
9196 const Instruction *
I =
nullptr)
const {
9197 if (!getAnchorScope())
9200 ScalarEvolution *SE =
9201 A.getInfoCache().getAnalysisResultForFunction<ScalarEvolutionAnalysis>(
9204 const SCEV *S = getSCEV(
A,
I);
9214 getConstantRangeFromLVI(Attributor &
A,
9215 const Instruction *CtxI =
nullptr)
const {
9216 if (!getAnchorScope())
9219 LazyValueInfo *LVI =
9220 A.getInfoCache().getAnalysisResultForFunction<LazyValueAnalysis>(
9235 bool isValidCtxInstructionForOutsideAnalysis(Attributor &
A,
9236 const Instruction *CtxI,
9237 bool AllowAACtxI)
const {
9238 if (!CtxI || (!AllowAACtxI && CtxI == getCtxI()))
9250 InformationCache &InfoCache =
A.getInfoCache();
9251 const DominatorTree *DT =
9262 getAssumedConstantRange(Attributor &
A,
9263 const Instruction *CtxI =
nullptr)
const override {
9268 if (!isValidCtxInstructionForOutsideAnalysis(
A, CtxI,
9270 return getAssumed();
9272 ConstantRange LVIR = getConstantRangeFromLVI(
A, CtxI);
9273 ConstantRange SCEVR = getConstantRangeFromSCEV(
A, CtxI);
9274 return getAssumed().intersectWith(SCEVR).intersectWith(LVIR);
9279 getMDNodeForConstantRange(
Type *Ty, LLVMContext &Ctx,
9280 const ConstantRange &AssumedConstantRange) {
9282 Ty, AssumedConstantRange.
getLower())),
9284 Ty, AssumedConstantRange.
getUpper()))};
9289 static bool isBetterRange(
const ConstantRange &Assumed,
9290 const Instruction &
I) {
9294 std::optional<ConstantRange>
Known;
9298 }
else if (MDNode *KnownRanges =
I.getMetadata(LLVMContext::MD_range)) {
9304 if (KnownRanges->getNumOperands() > 2)
9307 ConstantInt *
Lower =
9309 ConstantInt *
Upper =
9319 setRangeMetadataIfisBetterRange(Instruction *
I,
9320 const ConstantRange &AssumedConstantRange) {
9321 if (isBetterRange(AssumedConstantRange, *
I)) {
9322 I->setMetadata(LLVMContext::MD_range,
9323 getMDNodeForConstantRange(
I->getType(),
I->getContext(),
9324 AssumedConstantRange));
9331 setRangeRetAttrIfisBetterRange(Attributor &
A,
const IRPosition &IRP,
9333 const ConstantRange &AssumedConstantRange) {
9334 if (isBetterRange(AssumedConstantRange, *
I)) {
9335 A.manifestAttrs(IRP,
9336 Attribute::get(
I->getContext(), Attribute::Range,
9337 AssumedConstantRange),
9347 ConstantRange AssumedConstantRange = getAssumedConstantRange(
A);
9350 auto &
V = getAssociatedValue();
9354 assert(
I == getCtxI() &&
"Should not annotate an instruction which is "
9355 "not the context instruction");
9357 if (setRangeMetadataIfisBetterRange(
I, AssumedConstantRange))
9358 Changed = ChangeStatus::CHANGED;
9360 if (setRangeRetAttrIfisBetterRange(
A, getIRPosition(),
I,
9361 AssumedConstantRange))
9362 Changed = ChangeStatus::CHANGED;
9370struct AAValueConstantRangeArgument final
9371 : AAArgumentFromCallSiteArguments<
9372 AAValueConstantRange, AAValueConstantRangeImpl, IntegerRangeState,
9374 using Base = AAArgumentFromCallSiteArguments<
9375 AAValueConstantRange, AAValueConstantRangeImpl, IntegerRangeState,
9377 AAValueConstantRangeArgument(
const IRPosition &IRP, Attributor &
A)
9381 void trackStatistics()
const override {
9386struct AAValueConstantRangeReturned
9387 : AAReturnedFromReturnedValues<AAValueConstantRange,
9388 AAValueConstantRangeImpl,
9389 AAValueConstantRangeImpl::StateType,
9392 AAReturnedFromReturnedValues<AAValueConstantRange,
9393 AAValueConstantRangeImpl,
9394 AAValueConstantRangeImpl::StateType,
9396 AAValueConstantRangeReturned(
const IRPosition &IRP, Attributor &
A)
9401 if (!
A.isFunctionIPOAmendable(*getAssociatedFunction()))
9402 indicatePessimisticFixpoint();
9406 void trackStatistics()
const override {
9411struct AAValueConstantRangeFloating : AAValueConstantRangeImpl {
9412 AAValueConstantRangeFloating(
const IRPosition &IRP, Attributor &
A)
9413 : AAValueConstantRangeImpl(IRP,
A) {}
9417 AAValueConstantRangeImpl::initialize(
A);
9421 Value &
V = getAssociatedValue();
9424 unionAssumed(ConstantRange(
C->getValue()));
9425 indicateOptimisticFixpoint();
9431 unionAssumed(ConstantRange(APInt(
getBitWidth(), 0)));
9432 indicateOptimisticFixpoint();
9444 if (
auto *RangeMD = LI->getMetadata(LLVMContext::MD_range)) {
9455 indicatePessimisticFixpoint();
9458 << getAssociatedValue() <<
"\n");
9461 bool calculateBinaryOperator(
9462 Attributor &
A, BinaryOperator *BinOp, IntegerRangeState &
T,
9463 const Instruction *CtxI,
9464 SmallVectorImpl<const AAValueConstantRange *> &QuerriedAAs) {
9469 bool UsedAssumedInformation =
false;
9470 const auto &SimplifiedLHS =
A.getAssumedSimplified(
9473 if (!SimplifiedLHS.has_value())
9475 if (!*SimplifiedLHS)
9477 LHS = *SimplifiedLHS;
9479 const auto &SimplifiedRHS =
A.getAssumedSimplified(
9482 if (!SimplifiedRHS.has_value())
9484 if (!*SimplifiedRHS)
9486 RHS = *SimplifiedRHS;
9492 auto *LHSAA =
A.getAAFor<AAValueConstantRange>(
9494 DepClassTy::REQUIRED);
9498 auto LHSAARange = LHSAA->getAssumedConstantRange(
A, CtxI);
9500 auto *RHSAA =
A.getAAFor<AAValueConstantRange>(
9502 DepClassTy::REQUIRED);
9506 auto RHSAARange = RHSAA->getAssumedConstantRange(
A, CtxI);
9508 auto AssumedRange = LHSAARange.binaryOp(BinOp->
getOpcode(), RHSAARange);
9510 T.unionAssumed(AssumedRange);
9514 return T.isValidState();
9517 bool calculateCastInst(
9518 Attributor &
A, CastInst *CastI, IntegerRangeState &
T,
9519 const Instruction *CtxI,
9520 SmallVectorImpl<const AAValueConstantRange *> &QuerriedAAs) {
9526 bool UsedAssumedInformation =
false;
9527 const auto &SimplifiedOpV =
A.getAssumedSimplified(
9530 if (!SimplifiedOpV.has_value())
9532 if (!*SimplifiedOpV)
9534 OpV = *SimplifiedOpV;
9539 auto *OpAA =
A.getAAFor<AAValueConstantRange>(
9541 DepClassTy::REQUIRED);
9545 T.unionAssumed(OpAA->getAssumed().castOp(CastI->
getOpcode(),
9547 return T.isValidState();
9551 calculateCmpInst(Attributor &
A, CmpInst *CmpI, IntegerRangeState &
T,
9552 const Instruction *CtxI,
9553 SmallVectorImpl<const AAValueConstantRange *> &QuerriedAAs) {
9558 bool UsedAssumedInformation =
false;
9559 const auto &SimplifiedLHS =
A.getAssumedSimplified(
9562 if (!SimplifiedLHS.has_value())
9564 if (!*SimplifiedLHS)
9566 LHS = *SimplifiedLHS;
9568 const auto &SimplifiedRHS =
A.getAssumedSimplified(
9571 if (!SimplifiedRHS.has_value())
9573 if (!*SimplifiedRHS)
9575 RHS = *SimplifiedRHS;
9581 auto *LHSAA =
A.getAAFor<AAValueConstantRange>(
9583 DepClassTy::REQUIRED);
9587 auto *RHSAA =
A.getAAFor<AAValueConstantRange>(
9589 DepClassTy::REQUIRED);
9593 auto LHSAARange = LHSAA->getAssumedConstantRange(
A, CtxI);
9594 auto RHSAARange = RHSAA->getAssumedConstantRange(
A, CtxI);
9597 if (LHSAARange.isEmptySet() || RHSAARange.isEmptySet())
9600 bool MustTrue =
false, MustFalse =
false;
9602 auto AllowedRegion =
9605 if (AllowedRegion.intersectWith(LHSAARange).isEmptySet())
9611 assert((!MustTrue || !MustFalse) &&
9612 "Either MustTrue or MustFalse should be false!");
9615 T.unionAssumed(ConstantRange(APInt( 1, 1)));
9617 T.unionAssumed(ConstantRange(APInt( 1, 0)));
9619 T.unionAssumed(ConstantRange( 1,
true));
9621 LLVM_DEBUG(
dbgs() <<
"[AAValueConstantRange] " << *CmpI <<
" after "
9622 << (MustTrue ?
"true" : (MustFalse ?
"false" :
"unknown"))
9623 <<
": " <<
T <<
"\n\t" << *LHSAA <<
"\t<op>\n\t"
9627 return T.isValidState();
9639 bool UsedAssumedInformation =
false;
9640 const auto &SimplifiedOpV =
A.getAssumedSimplified(
9643 if (!SimplifiedOpV.has_value())
9645 if (!*SimplifiedOpV)
9647 Value *VPtr = *SimplifiedOpV;
9650 const auto *AA =
A.getAAFor<AAValueConstantRange>(
9652 DepClassTy::REQUIRED);
9656 T.unionAssumed(AA->getAssumedConstantRange(
A, CtxI));
9660 return T.isValidState();
9665 if (!calculateBinaryOperator(
A, BinOp,
T, CtxI, QuerriedAAs))
9668 if (!calculateCmpInst(
A, CmpI,
T, CtxI, QuerriedAAs))
9671 if (!calculateCastInst(
A, CastI,
T, CtxI, QuerriedAAs))
9677 T.indicatePessimisticFixpoint();
9684 for (
const AAValueConstantRange *QueriedAA : QuerriedAAs) {
9685 if (QueriedAA !=
this)
9688 if (
T.getAssumed() == getState().getAssumed())
9690 T.indicatePessimisticFixpoint();
9693 return T.isValidState();
9696 if (!VisitValueCB(getAssociatedValue(), getCtxI()))
9697 return indicatePessimisticFixpoint();
9702 return ChangeStatus::UNCHANGED;
9703 if (++NumChanges > MaxNumChanges) {
9704 LLVM_DEBUG(
dbgs() <<
"[AAValueConstantRange] performed " << NumChanges
9705 <<
" but only " << MaxNumChanges
9706 <<
" are allowed to avoid cyclic reasoning.");
9707 return indicatePessimisticFixpoint();
9709 return ChangeStatus::CHANGED;
9713 void trackStatistics()
const override {
9722 static constexpr int MaxNumChanges = 5;
9725struct AAValueConstantRangeFunction : AAValueConstantRangeImpl {
9726 AAValueConstantRangeFunction(
const IRPosition &IRP, Attributor &
A)
9727 : AAValueConstantRangeImpl(IRP,
A) {}
9731 llvm_unreachable(
"AAValueConstantRange(Function|CallSite)::updateImpl will "
9739struct AAValueConstantRangeCallSite : AAValueConstantRangeFunction {
9740 AAValueConstantRangeCallSite(
const IRPosition &IRP, Attributor &
A)
9741 : AAValueConstantRangeFunction(IRP,
A) {}
9747struct AAValueConstantRangeCallSiteReturned
9748 : AACalleeToCallSite<AAValueConstantRange, AAValueConstantRangeImpl,
9749 AAValueConstantRangeImpl::StateType,
9751 AAValueConstantRangeCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
9752 : AACalleeToCallSite<AAValueConstantRange, AAValueConstantRangeImpl,
9753 AAValueConstantRangeImpl::StateType,
9760 if (std::optional<ConstantRange>
Range = CI->getRange())
9761 intersectKnown(*
Range);
9764 AAValueConstantRangeImpl::initialize(
A);
9768 void trackStatistics()
const override {
9772struct AAValueConstantRangeCallSiteArgument : AAValueConstantRangeFloating {
9773 AAValueConstantRangeCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
9774 : AAValueConstantRangeFloating(IRP,
A) {}
9778 return ChangeStatus::UNCHANGED;
9782 void trackStatistics()
const override {
9791struct AAPotentialConstantValuesImpl : AAPotentialConstantValues {
9794 AAPotentialConstantValuesImpl(
const IRPosition &IRP, Attributor &
A)
9795 : AAPotentialConstantValues(IRP,
A) {}
9799 if (
A.hasSimplificationCallback(getIRPosition()))
9800 indicatePessimisticFixpoint();
9802 AAPotentialConstantValues::initialize(
A);
9805 bool fillSetWithConstantValues(Attributor &
A,
const IRPosition &IRP, SetTy &S,
9806 bool &ContainsUndef,
bool ForSelf) {
9808 bool UsedAssumedInformation =
false;
9810 UsedAssumedInformation)) {
9817 auto *PotentialValuesAA =
A.getAAFor<AAPotentialConstantValues>(
9818 *
this, IRP, DepClassTy::REQUIRED);
9819 if (!PotentialValuesAA || !PotentialValuesAA->getState().isValidState())
9821 ContainsUndef = PotentialValuesAA->getState().undefIsContained();
9822 S = PotentialValuesAA->getState().getAssumedSet();
9829 ContainsUndef =
false;
9830 for (
auto &It :
Values) {
9832 ContainsUndef =
true;
9838 S.insert(CI->getValue());
9840 ContainsUndef &= S.empty();
9846 const std::string getAsStr(Attributor *
A)
const override {
9848 llvm::raw_string_ostream OS(Str);
9855 return indicatePessimisticFixpoint();
9859struct AAPotentialConstantValuesArgument final
9860 : AAArgumentFromCallSiteArguments<AAPotentialConstantValues,
9861 AAPotentialConstantValuesImpl,
9862 PotentialConstantIntValuesState> {
9863 using Base = AAArgumentFromCallSiteArguments<AAPotentialConstantValues,
9864 AAPotentialConstantValuesImpl,
9866 AAPotentialConstantValuesArgument(
const IRPosition &IRP, Attributor &
A)
9870 void trackStatistics()
const override {
9875struct AAPotentialConstantValuesReturned
9876 : AAReturnedFromReturnedValues<AAPotentialConstantValues,
9877 AAPotentialConstantValuesImpl> {
9878 using Base = AAReturnedFromReturnedValues<AAPotentialConstantValues,
9879 AAPotentialConstantValuesImpl>;
9880 AAPotentialConstantValuesReturned(
const IRPosition &IRP, Attributor &
A)
9884 if (!
A.isFunctionIPOAmendable(*getAssociatedFunction()))
9885 indicatePessimisticFixpoint();
9886 Base::initialize(
A);
9890 void trackStatistics()
const override {
9895struct AAPotentialConstantValuesFloating : AAPotentialConstantValuesImpl {
9896 AAPotentialConstantValuesFloating(
const IRPosition &IRP, Attributor &
A)
9897 : AAPotentialConstantValuesImpl(IRP,
A) {}
9901 AAPotentialConstantValuesImpl::initialize(
A);
9905 Value &
V = getAssociatedValue();
9908 unionAssumed(
C->getValue());
9909 indicateOptimisticFixpoint();
9914 unionAssumedWithUndef();
9915 indicateOptimisticFixpoint();
9925 indicatePessimisticFixpoint();
9928 << getAssociatedValue() <<
"\n");
9931 static bool calculateICmpInst(
const ICmpInst *ICI,
const APInt &
LHS,
9936 static APInt calculateCastInst(
const CastInst *CI,
const APInt &Src,
9937 uint32_t ResultBitWidth) {
9942 case Instruction::Trunc:
9943 return Src.trunc(ResultBitWidth);
9944 case Instruction::SExt:
9945 return Src.sext(ResultBitWidth);
9946 case Instruction::ZExt:
9947 return Src.zext(ResultBitWidth);
9948 case Instruction::BitCast:
9953 static APInt calculateBinaryOperator(
const BinaryOperator *BinOp,
9954 const APInt &
LHS,
const APInt &
RHS,
9955 bool &SkipOperation,
bool &Unsupported) {
9962 switch (BinOpcode) {
9966 case Instruction::Add:
9968 case Instruction::Sub:
9970 case Instruction::Mul:
9972 case Instruction::UDiv:
9974 SkipOperation =
true;
9978 case Instruction::SDiv:
9980 SkipOperation =
true;
9984 case Instruction::URem:
9986 SkipOperation =
true;
9990 case Instruction::SRem:
9992 SkipOperation =
true;
9996 case Instruction::Shl:
9998 case Instruction::LShr:
10000 case Instruction::AShr:
10002 case Instruction::And:
10004 case Instruction::Or:
10006 case Instruction::Xor:
10011 bool calculateBinaryOperatorAndTakeUnion(
const BinaryOperator *BinOp,
10012 const APInt &
LHS,
const APInt &
RHS) {
10013 bool SkipOperation =
false;
10016 calculateBinaryOperator(BinOp,
LHS,
RHS, SkipOperation, Unsupported);
10020 if (!SkipOperation)
10021 unionAssumed(Result);
10022 return isValidState();
10025 ChangeStatus updateWithICmpInst(Attributor &
A, ICmpInst *ICI) {
10026 auto AssumedBefore = getAssumed();
10030 bool LHSContainsUndef =
false, RHSContainsUndef =
false;
10031 SetTy LHSAAPVS, RHSAAPVS;
10033 LHSContainsUndef,
false) ||
10035 RHSContainsUndef,
false))
10036 return indicatePessimisticFixpoint();
10039 bool MaybeTrue =
false, MaybeFalse =
false;
10041 if (LHSContainsUndef && RHSContainsUndef) {
10044 unionAssumedWithUndef();
10045 }
else if (LHSContainsUndef) {
10046 for (
const APInt &R : RHSAAPVS) {
10047 bool CmpResult = calculateICmpInst(ICI, Zero, R);
10048 MaybeTrue |= CmpResult;
10049 MaybeFalse |= !CmpResult;
10050 if (MaybeTrue & MaybeFalse)
10051 return indicatePessimisticFixpoint();
10053 }
else if (RHSContainsUndef) {
10054 for (
const APInt &L : LHSAAPVS) {
10055 bool CmpResult = calculateICmpInst(ICI, L, Zero);
10056 MaybeTrue |= CmpResult;
10057 MaybeFalse |= !CmpResult;
10058 if (MaybeTrue & MaybeFalse)
10059 return indicatePessimisticFixpoint();
10062 for (
const APInt &L : LHSAAPVS) {
10063 for (
const APInt &R : RHSAAPVS) {
10064 bool CmpResult = calculateICmpInst(ICI, L, R);
10065 MaybeTrue |= CmpResult;
10066 MaybeFalse |= !CmpResult;
10067 if (MaybeTrue & MaybeFalse)
10068 return indicatePessimisticFixpoint();
10073 unionAssumed(APInt( 1, 1));
10075 unionAssumed(APInt( 1, 0));
10076 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10077 : ChangeStatus::CHANGED;
10080 ChangeStatus updateWithSelectInst(Attributor &
A, SelectInst *SI) {
10081 auto AssumedBefore = getAssumed();
10085 bool UsedAssumedInformation =
false;
10086 std::optional<Constant *>
C =
A.getAssumedConstant(
10087 *
SI->getCondition(), *
this, UsedAssumedInformation);
10090 bool OnlyLeft =
false, OnlyRight =
false;
10091 if (
C && *
C && (*C)->isOneValue())
10093 else if (
C && *
C && (*C)->isNullValue())
10096 bool LHSContainsUndef =
false, RHSContainsUndef =
false;
10097 SetTy LHSAAPVS, RHSAAPVS;
10100 LHSContainsUndef,
false))
10101 return indicatePessimisticFixpoint();
10105 RHSContainsUndef,
false))
10106 return indicatePessimisticFixpoint();
10108 if (OnlyLeft || OnlyRight) {
10110 auto *OpAA = OnlyLeft ? &LHSAAPVS : &RHSAAPVS;
10111 auto Undef = OnlyLeft ? LHSContainsUndef : RHSContainsUndef;
10114 unionAssumedWithUndef();
10116 for (
const auto &It : *OpAA)
10120 }
else if (LHSContainsUndef && RHSContainsUndef) {
10122 unionAssumedWithUndef();
10124 for (
const auto &It : LHSAAPVS)
10126 for (
const auto &It : RHSAAPVS)
10129 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10130 : ChangeStatus::CHANGED;
10133 ChangeStatus updateWithCastInst(Attributor &
A, CastInst *CI) {
10134 auto AssumedBefore = getAssumed();
10136 return indicatePessimisticFixpoint();
10141 bool SrcContainsUndef =
false;
10144 SrcContainsUndef,
false))
10145 return indicatePessimisticFixpoint();
10147 if (SrcContainsUndef)
10148 unionAssumedWithUndef();
10150 for (
const APInt &S : SrcPVS) {
10151 APInt
T = calculateCastInst(CI, S, ResultBitWidth);
10155 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10156 : ChangeStatus::CHANGED;
10159 ChangeStatus updateWithBinaryOperator(Attributor &
A, BinaryOperator *BinOp) {
10160 auto AssumedBefore = getAssumed();
10164 bool LHSContainsUndef =
false, RHSContainsUndef =
false;
10165 SetTy LHSAAPVS, RHSAAPVS;
10167 LHSContainsUndef,
false) ||
10169 RHSContainsUndef,
false))
10170 return indicatePessimisticFixpoint();
10175 if (LHSContainsUndef && RHSContainsUndef) {
10176 if (!calculateBinaryOperatorAndTakeUnion(BinOp, Zero, Zero))
10177 return indicatePessimisticFixpoint();
10178 }
else if (LHSContainsUndef) {
10179 for (
const APInt &R : RHSAAPVS) {
10180 if (!calculateBinaryOperatorAndTakeUnion(BinOp, Zero, R))
10181 return indicatePessimisticFixpoint();
10183 }
else if (RHSContainsUndef) {
10184 for (
const APInt &L : LHSAAPVS) {
10185 if (!calculateBinaryOperatorAndTakeUnion(BinOp, L, Zero))
10186 return indicatePessimisticFixpoint();
10189 for (
const APInt &L : LHSAAPVS) {
10190 for (
const APInt &R : RHSAAPVS) {
10191 if (!calculateBinaryOperatorAndTakeUnion(BinOp, L, R))
10192 return indicatePessimisticFixpoint();
10196 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10197 : ChangeStatus::CHANGED;
10200 ChangeStatus updateWithInstruction(Attributor &
A, Instruction *Inst) {
10201 auto AssumedBefore = getAssumed();
10203 bool ContainsUndef;
10205 ContainsUndef,
true))
10206 return indicatePessimisticFixpoint();
10207 if (ContainsUndef) {
10208 unionAssumedWithUndef();
10210 for (
const auto &It : Incoming)
10213 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10214 : ChangeStatus::CHANGED;
10219 Value &
V = getAssociatedValue();
10223 return updateWithICmpInst(
A, ICI);
10226 return updateWithSelectInst(
A, SI);
10229 return updateWithCastInst(
A, CI);
10232 return updateWithBinaryOperator(
A, BinOp);
10235 return updateWithInstruction(
A,
I);
10237 return indicatePessimisticFixpoint();
10241 void trackStatistics()
const override {
10246struct AAPotentialConstantValuesFunction : AAPotentialConstantValuesImpl {
10247 AAPotentialConstantValuesFunction(
const IRPosition &IRP, Attributor &
A)
10248 : AAPotentialConstantValuesImpl(IRP,
A) {}
10253 "AAPotentialConstantValues(Function|CallSite)::updateImpl will "
10258 void trackStatistics()
const override {
10263struct AAPotentialConstantValuesCallSite : AAPotentialConstantValuesFunction {
10264 AAPotentialConstantValuesCallSite(
const IRPosition &IRP, Attributor &
A)
10265 : AAPotentialConstantValuesFunction(IRP,
A) {}
10268 void trackStatistics()
const override {
10273struct AAPotentialConstantValuesCallSiteReturned
10274 : AACalleeToCallSite<AAPotentialConstantValues,
10275 AAPotentialConstantValuesImpl> {
10276 AAPotentialConstantValuesCallSiteReturned(
const IRPosition &IRP,
10278 : AACalleeToCallSite<AAPotentialConstantValues,
10279 AAPotentialConstantValuesImpl>(IRP,
A) {}
10282 void trackStatistics()
const override {
10287struct AAPotentialConstantValuesCallSiteArgument
10288 : AAPotentialConstantValuesFloating {
10289 AAPotentialConstantValuesCallSiteArgument(
const IRPosition &IRP,
10291 : AAPotentialConstantValuesFloating(IRP,
A) {}
10295 AAPotentialConstantValuesImpl::initialize(
A);
10296 if (isAtFixpoint())
10299 Value &
V = getAssociatedValue();
10302 unionAssumed(
C->getValue());
10303 indicateOptimisticFixpoint();
10308 unionAssumedWithUndef();
10309 indicateOptimisticFixpoint();
10316 Value &
V = getAssociatedValue();
10317 auto AssumedBefore = getAssumed();
10318 auto *AA =
A.getAAFor<AAPotentialConstantValues>(
10321 return indicatePessimisticFixpoint();
10322 const auto &S = AA->getAssumed();
10324 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10325 : ChangeStatus::CHANGED;
10329 void trackStatistics()
const override {
10338 bool IgnoreSubsumingPositions) {
10339 assert(ImpliedAttributeKind == Attribute::NoUndef &&
10340 "Unexpected attribute kind");
10341 if (
A.hasAttr(IRP, {Attribute::NoUndef}, IgnoreSubsumingPositions,
10342 Attribute::NoUndef))
10362 Value &V = getAssociatedValue();
10364 indicatePessimisticFixpoint();
10365 assert(!isImpliedByIR(
A, getIRPosition(), Attribute::NoUndef));
10369 bool followUseInMBEC(Attributor &
A,
const Use *U,
const Instruction *
I,
10370 AANoUndef::StateType &State) {
10371 const Value *UseV =
U->get();
10372 const DominatorTree *DT =
nullptr;
10373 AssumptionCache *AC =
nullptr;
10374 InformationCache &InfoCache =
A.getInfoCache();
10380 bool TrackUse =
false;
10389 const std::string getAsStr(Attributor *
A)
const override {
10390 return getAssumed() ?
"noundef" :
"may-undef-or-poison";
10397 bool UsedAssumedInformation =
false;
10398 if (
A.isAssumedDead(getIRPosition(),
nullptr,
nullptr,
10399 UsedAssumedInformation))
10400 return ChangeStatus::UNCHANGED;
10404 if (!
A.getAssumedSimplified(getIRPosition(), *
this, UsedAssumedInformation,
10407 return ChangeStatus::UNCHANGED;
10408 return AANoUndef::manifest(
A);
10412struct AANoUndefFloating :
public AANoUndefImpl {
10413 AANoUndefFloating(
const IRPosition &IRP, Attributor &
A)
10414 : AANoUndefImpl(IRP,
A) {}
10418 AANoUndefImpl::initialize(
A);
10419 if (!getState().isAtFixpoint() && getAnchorScope() &&
10420 !getAnchorScope()->isDeclaration())
10421 if (Instruction *CtxI = getCtxI())
10422 followUsesInMBEC(*
this,
A, getState(), *CtxI);
10427 auto VisitValueCB = [&](
const IRPosition &IRP) ->
bool {
10428 bool IsKnownNoUndef;
10430 A,
this, IRP, DepClassTy::REQUIRED, IsKnownNoUndef);
10434 bool UsedAssumedInformation =
false;
10435 Value *AssociatedValue = &getAssociatedValue();
10437 if (!
A.getAssumedSimplifiedValues(getIRPosition(), *
this,
Values,
10442 Values.size() != 1 ||
Values.front().getValue() != AssociatedValue;
10450 if (AVIRP == getIRPosition() || !VisitValueCB(AVIRP))
10451 return indicatePessimisticFixpoint();
10452 return ChangeStatus::UNCHANGED;
10455 for (
const auto &VAC :
Values)
10457 return indicatePessimisticFixpoint();
10459 return ChangeStatus::UNCHANGED;
10466struct AANoUndefReturned final
10467 : AAReturnedFromReturnedValues<AANoUndef, AANoUndefImpl> {
10468 AANoUndefReturned(
const IRPosition &IRP, Attributor &
A)
10469 : AAReturnedFromReturnedValues<AANoUndef, AANoUndefImpl>(IRP,
A) {}
10475struct AANoUndefArgument final
10476 : AAArgumentFromCallSiteArguments<AANoUndef, AANoUndefImpl> {
10477 AANoUndefArgument(
const IRPosition &IRP, Attributor &
A)
10478 : AAArgumentFromCallSiteArguments<AANoUndef, AANoUndefImpl>(IRP,
A) {}
10484struct AANoUndefCallSiteArgument final : AANoUndefFloating {
10485 AANoUndefCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
10486 : AANoUndefFloating(IRP,
A) {}
10492struct AANoUndefCallSiteReturned final
10493 : AACalleeToCallSite<AANoUndef, AANoUndefImpl> {
10494 AANoUndefCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
10495 : AACalleeToCallSite<AANoUndef, AANoUndefImpl>(IRP,
A) {}
10503struct AANoFPClassImpl : AANoFPClass {
10504 AANoFPClassImpl(
const IRPosition &IRP, Attributor &
A) : AANoFPClass(IRP,
A) {}
10507 const IRPosition &IRP = getIRPosition();
10511 indicateOptimisticFixpoint();
10516 A.getAttrs(getIRPosition(), {Attribute::NoFPClass},
Attrs,
false);
10517 for (
const auto &Attr : Attrs) {
10524 const DataLayout &
DL =
A.getDataLayout();
10525 InformationCache &InfoCache =
A.getInfoCache();
10527 const DominatorTree *DT =
nullptr;
10528 AssumptionCache *AC =
nullptr;
10529 const TargetLibraryInfo *TLI =
nullptr;
10533 if (!
F->isDeclaration()) {
10540 SimplifyQuery Q(
DL, TLI, DT, AC, CtxI);
10547 followUsesInMBEC(*
this,
A, getState(), *CtxI);
10551 bool followUseInMBEC(Attributor &
A,
const Use *U,
const Instruction *
I,
10552 AANoFPClass::StateType &State) {
10563 if (
auto *NoFPAA =
A.getAAFor<AANoFPClass>(*
this, IRP, DepClassTy::NONE))
10564 State.addKnownBits(NoFPAA->getState().getKnown());
10568 const std::string getAsStr(Attributor *
A)
const override {
10569 std::string
Result =
"nofpclass";
10570 raw_string_ostream OS(Result);
10571 OS << getKnownNoFPClass() <<
'/' << getAssumedNoFPClass();
10575 void getDeducedAttributes(Attributor &
A, LLVMContext &Ctx,
10576 SmallVectorImpl<Attribute> &Attrs)
const override {
10577 Attrs.emplace_back(Attribute::getWithNoFPClass(Ctx, getAssumedNoFPClass()));
10581struct AANoFPClassFloating :
public AANoFPClassImpl {
10582 AANoFPClassFloating(
const IRPosition &IRP, Attributor &
A)
10583 : AANoFPClassImpl(IRP,
A) {}
10588 bool UsedAssumedInformation =
false;
10589 if (!
A.getAssumedSimplifiedValues(getIRPosition(), *
this,
Values,
10591 Values.push_back({getAssociatedValue(), getCtxI()});
10597 DepClassTy::REQUIRED);
10598 if (!AA ||
this == AA) {
10599 T.indicatePessimisticFixpoint();
10601 const AANoFPClass::StateType &S =
10602 static_cast<const AANoFPClass::StateType &
>(AA->
getState());
10605 return T.isValidState();
10608 for (
const auto &VAC :
Values)
10610 return indicatePessimisticFixpoint();
10616 void trackStatistics()
const override {
10621struct AANoFPClassReturned final
10622 : AAReturnedFromReturnedValues<AANoFPClass, AANoFPClassImpl,
10623 AANoFPClassImpl::StateType, false,
10624 Attribute::None, false> {
10625 AANoFPClassReturned(
const IRPosition &IRP, Attributor &
A)
10626 : AAReturnedFromReturnedValues<AANoFPClass, AANoFPClassImpl,
10627 AANoFPClassImpl::StateType,
false,
10631 void trackStatistics()
const override {
10636struct AANoFPClassArgument final
10637 : AAArgumentFromCallSiteArguments<AANoFPClass, AANoFPClassImpl> {
10638 AANoFPClassArgument(
const IRPosition &IRP, Attributor &
A)
10639 : AAArgumentFromCallSiteArguments<AANoFPClass, AANoFPClassImpl>(IRP,
A) {}
10645struct AANoFPClassCallSiteArgument final : AANoFPClassFloating {
10646 AANoFPClassCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
10647 : AANoFPClassFloating(IRP,
A) {}
10650 void trackStatistics()
const override {
10655struct AANoFPClassCallSiteReturned final
10656 : AACalleeToCallSite<AANoFPClass, AANoFPClassImpl> {
10657 AANoFPClassCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
10658 : AACalleeToCallSite<AANoFPClass, AANoFPClassImpl>(IRP,
A) {}
10661 void trackStatistics()
const override {
10666struct AACallEdgesImpl :
public AACallEdges {
10667 AACallEdgesImpl(
const IRPosition &IRP, Attributor &
A) : AACallEdges(IRP,
A) {}
10669 const SetVector<Function *> &getOptimisticEdges()
const override {
10670 return CalledFunctions;
10673 bool hasUnknownCallee()
const override {
return HasUnknownCallee; }
10675 bool hasNonAsmUnknownCallee()
const override {
10676 return HasUnknownCalleeNonAsm;
10679 const std::string getAsStr(Attributor *
A)
const override {
10680 return "CallEdges[" + std::to_string(HasUnknownCallee) +
"," +
10681 std::to_string(CalledFunctions.size()) +
"]";
10684 void trackStatistics()
const override {}
10688 if (CalledFunctions.insert(Fn)) {
10689 Change = ChangeStatus::CHANGED;
10695 void setHasUnknownCallee(
bool NonAsm,
ChangeStatus &Change) {
10696 if (!HasUnknownCallee)
10697 Change = ChangeStatus::CHANGED;
10698 if (NonAsm && !HasUnknownCalleeNonAsm)
10699 Change = ChangeStatus::CHANGED;
10700 HasUnknownCalleeNonAsm |= NonAsm;
10701 HasUnknownCallee =
true;
10706 SetVector<Function *> CalledFunctions;
10709 bool HasUnknownCallee =
false;
10712 bool HasUnknownCalleeNonAsm =
false;
10715struct AACallEdgesCallSite :
public AACallEdgesImpl {
10716 AACallEdgesCallSite(
const IRPosition &IRP, Attributor &
A)
10717 : AACallEdgesImpl(IRP,
A) {}
10724 addCalledFunction(Fn, Change);
10726 LLVM_DEBUG(
dbgs() <<
"[AACallEdges] Unrecognized value: " << V <<
"\n");
10727 setHasUnknownCallee(
true, Change);
10738 VisitValue(*V, CtxI);
10742 bool UsedAssumedInformation =
false;
10746 Values.push_back({*
V, CtxI});
10748 for (
auto &VAC :
Values)
10755 if (
IA->hasSideEffects() &&
10758 setHasUnknownCallee(
false, Change);
10764 if (
auto *IndirectCallAA =
A.getAAFor<AAIndirectCallInfo>(
10765 *
this, getIRPosition(), DepClassTy::OPTIONAL))
10766 if (IndirectCallAA->foreachCallee(
10767 [&](
Function *Fn) { return VisitValue(*Fn, CB); }))
10776 for (
const Use *U : CallbackUses)
10777 ProcessCalledOperand(
U->get(), CB);
10783struct AACallEdgesFunction :
public AACallEdgesImpl {
10784 AACallEdgesFunction(
const IRPosition &IRP, Attributor &
A)
10785 : AACallEdgesImpl(IRP,
A) {}
10794 auto *CBEdges =
A.getAAFor<AACallEdges>(
10798 if (CBEdges->hasNonAsmUnknownCallee())
10799 setHasUnknownCallee(
true, Change);
10800 if (CBEdges->hasUnknownCallee())
10801 setHasUnknownCallee(
false, Change);
10803 for (
Function *
F : CBEdges->getOptimisticEdges())
10804 addCalledFunction(
F, Change);
10810 bool UsedAssumedInformation =
false;
10811 if (!
A.checkForAllCallLikeInstructions(ProcessCallInst, *
this,
10812 UsedAssumedInformation,
10816 setHasUnknownCallee(
true, Change);
10825struct AAInterFnReachabilityFunction
10826 :
public CachedReachabilityAA<AAInterFnReachability, Function> {
10827 using Base = CachedReachabilityAA<AAInterFnReachability, Function>;
10828 AAInterFnReachabilityFunction(
const IRPosition &IRP, Attributor &
A)
10831 bool instructionCanReach(
10832 Attributor &
A,
const Instruction &From,
const Function &To,
10835 auto *NonConstThis =
const_cast<AAInterFnReachabilityFunction *
>(
this);
10837 RQITy StackRQI(
A, From, To, ExclusionSet,
false);
10838 RQITy::Reachable
Result;
10839 if (!NonConstThis->checkQueryCache(
A, StackRQI, Result))
10840 return NonConstThis->isReachableImpl(
A, StackRQI,
10842 return Result == RQITy::Reachable::Yes;
10846 bool IsTemporaryRQI)
override {
10848 &RQI.From->getFunction()->getEntryBlock().front();
10849 if (EntryI != RQI.From &&
10850 !instructionCanReach(
A, *EntryI, *RQI.To,
nullptr))
10851 return rememberResult(
A, RQITy::Reachable::No, RQI,
false,
10854 auto CheckReachableCallBase = [&](CallBase *CB) {
10855 auto *CBEdges =
A.getAAFor<AACallEdges>(
10857 if (!CBEdges || !CBEdges->getState().isValidState())
10860 if (CBEdges->hasUnknownCallee())
10863 for (
Function *Fn : CBEdges->getOptimisticEdges()) {
10874 if (Fn == getAnchorScope()) {
10875 if (EntryI == RQI.From)
10880 const AAInterFnReachability *InterFnReachability =
10882 DepClassTy::OPTIONAL);
10885 if (!InterFnReachability ||
10893 const auto *IntraFnReachability =
A.getAAFor<AAIntraFnReachability>(
10895 DepClassTy::OPTIONAL);
10903 return IntraFnReachability && !IntraFnReachability->isAssumedReachable(
10904 A, *RQI.From, CBInst, RQI.ExclusionSet);
10907 bool UsedExclusionSet =
true;
10908 bool UsedAssumedInformation =
false;
10909 if (!
A.checkForAllCallLikeInstructions(CheckCallBase, *
this,
10910 UsedAssumedInformation,
10912 return rememberResult(
A, RQITy::Reachable::Yes, RQI, UsedExclusionSet,
10915 return rememberResult(
A, RQITy::Reachable::No, RQI, UsedExclusionSet,
10919 void trackStatistics()
const override {}
10923template <
typename AAType>
10924static std::optional<Constant *>
10927 if (!Ty.isIntegerTy())
10935 std::optional<Constant *> COpt =
AA->getAssumedConstant(
A);
10937 if (!COpt.has_value()) {
10939 return std::nullopt;
10941 if (
auto *
C = *COpt) {
10952 std::optional<Value *> V;
10953 for (
auto &It :
Values) {
10955 if (V.has_value() && !*V)
10958 if (!V.has_value())
10972 if (
A.hasSimplificationCallback(getIRPosition())) {
10973 indicatePessimisticFixpoint();
10976 Value *Stripped = getAssociatedValue().stripPointerCasts();
10978 addValue(
A, getState(), *Stripped, getCtxI(),
AA::AnyScope,
10980 indicateOptimisticFixpoint();
10983 AAPotentialValues::initialize(
A);
10987 const std::string getAsStr(Attributor *
A)
const override {
10989 llvm::raw_string_ostream OS(Str);
10994 template <
typename AAType>
10995 static std::optional<Value *> askOtherAA(Attributor &
A,
10996 const AbstractAttribute &AA,
10997 const IRPosition &IRP,
Type &Ty) {
11002 return std::nullopt;
11009 virtual void addValue(Attributor &
A, StateType &State,
Value &V,
11015 for (
const auto &U : CB->
args()) {
11025 Type &Ty = *getAssociatedType();
11026 std::optional<Value *> SimpleV =
11027 askOtherAA<AAValueConstantRange>(
A, *
this, ValIRP, Ty);
11028 if (SimpleV.has_value() && !*SimpleV) {
11029 auto *PotentialConstantsAA =
A.getAAFor<AAPotentialConstantValues>(
11030 *
this, ValIRP, DepClassTy::OPTIONAL);
11031 if (PotentialConstantsAA && PotentialConstantsAA->isValidState()) {
11032 for (
const auto &It : PotentialConstantsAA->getAssumedSet())
11033 State.unionAssumed({{*ConstantInt::get(&Ty, It),
nullptr}, S});
11034 if (PotentialConstantsAA->undefIsContained())
11039 if (!SimpleV.has_value())
11051 State.unionAssumed({{*VPtr, CtxI}, S});
11057 AA::ValueAndContext
I;
11061 return II.I ==
I &&
II.S == S;
11064 return std::tie(
I, S) < std::tie(
II.I,
II.S);
11068 bool recurseForValue(Attributor &
A,
const IRPosition &IRP,
AA::ValueScope S) {
11069 SmallMapVector<AA::ValueAndContext, int, 8> ValueScopeMap;
11074 bool UsedAssumedInformation =
false;
11076 if (!
A.getAssumedSimplifiedValues(IRP,
this,
Values, CS,
11077 UsedAssumedInformation))
11081 ValueScopeMap[It] += CS;
11083 for (
auto &It : ValueScopeMap)
11084 addValue(
A, getState(), *It.first.getValue(), It.first.getCtxI(),
11090 void giveUpOnIntraprocedural(Attributor &
A) {
11091 auto NewS = StateType::getBestState(getState());
11092 for (
const auto &It : getAssumedSet()) {
11095 addValue(
A, NewS, *It.first.getValue(), It.first.getCtxI(),
11098 assert(!undefIsContained() &&
"Undef should be an explicit value!");
11106 getState() = StateType::getBestState(getState());
11107 getState().unionAssumed({{getAssociatedValue(), getCtxI()},
AA::AnyScope});
11108 AAPotentialValues::indicateOptimisticFixpoint();
11109 return ChangeStatus::CHANGED;
11114 return indicatePessimisticFixpoint();
11122 if (!getAssumedSimplifiedValues(
A,
Values, S))
11124 Value &OldV = getAssociatedValue();
11127 Value *NewV = getSingleValue(
A, *
this, getIRPosition(),
Values);
11128 if (!NewV || NewV == &OldV)
11133 if (
A.changeAfterManifest(getIRPosition(), *NewV))
11134 return ChangeStatus::CHANGED;
11136 return ChangeStatus::UNCHANGED;
11139 bool getAssumedSimplifiedValues(
11140 Attributor &
A, SmallVectorImpl<AA::ValueAndContext> &
Values,
11141 AA::ValueScope S,
bool RecurseForSelectAndPHI =
false)
const override {
11142 if (!isValidState())
11144 bool UsedAssumedInformation =
false;
11145 for (
const auto &It : getAssumedSet())
11146 if (It.second & S) {
11147 if (RecurseForSelectAndPHI && (
isa<PHINode>(It.first.getValue()) ||
11149 if (
A.getAssumedSimplifiedValues(
11151 this,
Values, S, UsedAssumedInformation))
11154 Values.push_back(It.first);
11156 assert(!undefIsContained() &&
"Undef should be an explicit value!");
11161struct AAPotentialValuesFloating : AAPotentialValuesImpl {
11162 AAPotentialValuesFloating(
const IRPosition &IRP, Attributor &
A)
11163 : AAPotentialValuesImpl(IRP,
A) {}
11167 auto AssumedBefore = getAssumed();
11169 genericValueTraversal(
A, &getAssociatedValue());
11171 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
11172 : ChangeStatus::CHANGED;
11176 struct LivenessInfo {
11177 const AAIsDead *LivenessAA =
nullptr;
11178 bool AnyDead =
false;
11188 SmallVectorImpl<ItemInfo> &Worklist) {
11191 bool UsedAssumedInformation =
false;
11193 auto GetSimplifiedValues = [&](
Value &
V,
11195 if (!
A.getAssumedSimplifiedValues(
11199 Values.push_back(AA::ValueAndContext{
V,
II.I.getCtxI()});
11203 if (GetSimplifiedValues(*
LHS, LHSValues))
11205 if (GetSimplifiedValues(*
RHS, RHSValues))
11210 InformationCache &InfoCache =
A.getInfoCache();
11217 F ?
A.getInfoCache().getTargetLibraryInfoForFunction(*
F) :
nullptr;
11222 const DataLayout &
DL =
A.getDataLayout();
11223 SimplifyQuery Q(
DL, TLI, DT, AC, CmpI);
11225 auto CheckPair = [&](
Value &LHSV,
Value &RHSV) {
11228 nullptr,
II.S, getAnchorScope());
11234 if (&LHSV == &RHSV &&
11236 Constant *NewV = ConstantInt::get(Type::getInt1Ty(Ctx),
11238 addValue(
A, getState(), *NewV,
nullptr,
II.S,
11245 if (TypedLHS && TypedRHS) {
11247 if (NewV && NewV != &Cmp) {
11248 addValue(
A, getState(), *NewV,
nullptr,
II.S,
11260 if (!LHSIsNull && !RHSIsNull)
11266 assert((LHSIsNull || RHSIsNull) &&
11267 "Expected nullptr versus non-nullptr comparison at this point");
11270 unsigned PtrIdx = LHSIsNull;
11271 bool IsKnownNonNull;
11274 DepClassTy::REQUIRED, IsKnownNonNull);
11275 if (!IsAssumedNonNull)
11281 addValue(
A, getState(), *NewV,
nullptr,
II.S,
11286 for (
auto &LHSValue : LHSValues)
11287 for (
auto &RHSValue : RHSValues)
11288 if (!CheckPair(*LHSValue.getValue(), *RHSValue.getValue()))
11293 bool handleSelectInst(Attributor &
A, SelectInst &SI, ItemInfo
II,
11294 SmallVectorImpl<ItemInfo> &Worklist) {
11296 bool UsedAssumedInformation =
false;
11298 std::optional<Constant *>
C =
11299 A.getAssumedConstant(*
SI.getCondition(), *
this, UsedAssumedInformation);
11300 bool NoValueYet = !
C.has_value();
11308 }
else if (&SI == &getAssociatedValue()) {
11313 std::optional<Value *> SimpleV =
A.getAssumedSimplified(
11315 if (!SimpleV.has_value())
11318 addValue(
A, getState(), **SimpleV, CtxI,
II.S, getAnchorScope());
11326 bool handleLoadInst(Attributor &
A, LoadInst &LI, ItemInfo
II,
11327 SmallVectorImpl<ItemInfo> &Worklist) {
11328 SmallSetVector<Value *, 4> PotentialCopies;
11329 SmallSetVector<Instruction *, 4> PotentialValueOrigins;
11330 bool UsedAssumedInformation =
false;
11332 PotentialValueOrigins, *
this,
11333 UsedAssumedInformation,
11335 LLVM_DEBUG(
dbgs() <<
"[AAPotentialValues] Failed to get potentially "
11336 "loaded values for load instruction "
11344 InformationCache &InfoCache =
A.getInfoCache();
11346 if (!
llvm::all_of(PotentialValueOrigins, [&](Instruction *
I) {
11350 return A.isAssumedDead(
SI->getOperandUse(0),
this,
11352 UsedAssumedInformation,
11354 return A.isAssumedDead(*
I,
this,
nullptr,
11355 UsedAssumedInformation,
11358 LLVM_DEBUG(
dbgs() <<
"[AAPotentialValues] Load is onl used by assumes "
11359 "and we cannot delete all the stores: "
11370 bool AllLocal = ScopeIsLocal;
11375 if (!DynamicallyUnique) {
11376 LLVM_DEBUG(
dbgs() <<
"[AAPotentialValues] Not all potentially loaded "
11377 "values are dynamically unique: "
11382 for (
auto *PotentialCopy : PotentialCopies) {
11384 Worklist.
push_back({{*PotentialCopy, CtxI},
II.S});
11389 if (!AllLocal && ScopeIsLocal)
11394 bool handlePHINode(
11395 Attributor &
A, PHINode &
PHI, ItemInfo
II,
11396 SmallVectorImpl<ItemInfo> &Worklist,
11397 SmallMapVector<const Function *, LivenessInfo, 4> &LivenessAAs) {
11398 auto GetLivenessInfo = [&](
const Function &
F) -> LivenessInfo & {
11399 LivenessInfo &LI = LivenessAAs[&
F];
11400 if (!LI.LivenessAA)
11406 if (&
PHI == &getAssociatedValue()) {
11407 LivenessInfo &LI = GetLivenessInfo(*
PHI.getFunction());
11409 A.getInfoCache().getAnalysisResultForFunction<CycleAnalysis>(
11410 *
PHI.getFunction());
11414 for (
unsigned u = 0, e =
PHI.getNumIncomingValues(); u < e; u++) {
11416 if (LI.LivenessAA &&
11417 LI.LivenessAA->isEdgeDead(IncomingBB,
PHI.getParent())) {
11436 bool UsedAssumedInformation =
false;
11437 std::optional<Value *> SimpleV =
A.getAssumedSimplified(
11439 if (!SimpleV.has_value())
11443 addValue(
A, getState(), **SimpleV, &
PHI,
II.S, getAnchorScope());
11450 bool handleGenericInst(Attributor &
A, Instruction &
I, ItemInfo
II,
11451 SmallVectorImpl<ItemInfo> &Worklist) {
11452 bool SomeSimplified =
false;
11453 bool UsedAssumedInformation =
false;
11455 SmallVector<Value *, 8> NewOps(
I.getNumOperands());
11458 const auto &SimplifiedOp =
A.getAssumedSimplified(
11463 if (!SimplifiedOp.has_value())
11467 NewOps[
Idx] = *SimplifiedOp;
11471 SomeSimplified |= (NewOps[
Idx] !=
Op);
11477 if (!SomeSimplified)
11480 InformationCache &InfoCache =
A.getInfoCache();
11484 const auto *TLI =
A.getInfoCache().getTargetLibraryInfoForFunction(*
F);
11487 const DataLayout &
DL =
I.getDataLayout();
11488 SimplifyQuery Q(
DL, TLI, DT, AC, &
I);
11490 if (!NewV || NewV == &
I)
11493 LLVM_DEBUG(
dbgs() <<
"Generic inst " <<
I <<
" assumed simplified to "
11500 Attributor &
A, Instruction &
I, ItemInfo
II,
11501 SmallVectorImpl<ItemInfo> &Worklist,
11502 SmallMapVector<const Function *, LivenessInfo, 4> &LivenessAAs) {
11505 CI->getPredicate(),
II, Worklist);
11507 switch (
I.getOpcode()) {
11508 case Instruction::Select:
11510 case Instruction::PHI:
11512 case Instruction::Load:
11515 return handleGenericInst(
A,
I,
II, Worklist);
11520 void genericValueTraversal(Attributor &
A,
Value *InitialV) {
11521 SmallMapVector<const Function *, LivenessInfo, 4> LivenessAAs;
11523 SmallSet<ItemInfo, 16> Visited;
11542 LLVM_DEBUG(
dbgs() <<
"Generic value traversal reached iteration limit: "
11543 << Iteration <<
"!\n");
11544 addValue(
A, getState(), *V, CtxI, S, getAnchorScope());
11550 Value *NewV =
nullptr;
11551 if (
V->getType()->isPointerTy()) {
11557 for (Argument &Arg :
Callee->args())
11564 if (NewV && NewV != V) {
11565 Worklist.
push_back({{*NewV, CtxI}, S});
11579 if (V == InitialV && CtxI == getCtxI()) {
11580 indicatePessimisticFixpoint();
11584 addValue(
A, getState(), *V, CtxI, S, getAnchorScope());
11585 }
while (!Worklist.
empty());
11589 for (
auto &It : LivenessAAs)
11590 if (It.second.AnyDead)
11591 A.recordDependence(*It.second.LivenessAA, *
this, DepClassTy::OPTIONAL);
11595 void trackStatistics()
const override {
11600struct AAPotentialValuesArgument final : AAPotentialValuesImpl {
11601 using Base = AAPotentialValuesImpl;
11602 AAPotentialValuesArgument(
const IRPosition &IRP, Attributor &
A)
11609 indicatePessimisticFixpoint();
11614 auto AssumedBefore = getAssumed();
11616 unsigned ArgNo = getCalleeArgNo();
11618 bool UsedAssumedInformation =
false;
11620 auto CallSitePred = [&](AbstractCallSite ACS) {
11622 if (CSArgIRP.getPositionKind() == IRP_INVALID)
11625 if (!
A.getAssumedSimplifiedValues(CSArgIRP,
this,
Values,
11627 UsedAssumedInformation))
11630 return isValidState();
11633 if (!
A.checkForAllCallSites(CallSitePred, *
this,
11635 UsedAssumedInformation))
11636 return indicatePessimisticFixpoint();
11638 Function *Fn = getAssociatedFunction();
11639 bool AnyNonLocal =
false;
11640 for (
auto &It :
Values) {
11642 addValue(
A, getState(), *It.getValue(), It.getCtxI(),
AA::AnyScope,
11647 return indicatePessimisticFixpoint();
11651 addValue(
A, getState(), *It.getValue(), It.getCtxI(),
AA::AnyScope,
11657 AnyNonLocal =
true;
11659 assert(!undefIsContained() &&
"Undef should be an explicit value!");
11661 giveUpOnIntraprocedural(
A);
11663 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
11664 : ChangeStatus::CHANGED;
11668 void trackStatistics()
const override {
11673struct AAPotentialValuesReturned :
public AAPotentialValuesFloating {
11674 using Base = AAPotentialValuesFloating;
11675 AAPotentialValuesReturned(
const IRPosition &IRP, Attributor &
A)
11681 if (!
F ||
F->isDeclaration() ||
F->getReturnType()->isVoidTy()) {
11682 indicatePessimisticFixpoint();
11686 for (Argument &Arg :
F->args())
11689 ReturnedArg = &Arg;
11692 if (!
A.isFunctionIPOAmendable(*
F) ||
11693 A.hasSimplificationCallback(getIRPosition())) {
11695 indicatePessimisticFixpoint();
11697 indicateOptimisticFixpoint();
11703 auto AssumedBefore = getAssumed();
11704 bool UsedAssumedInformation =
false;
11707 Function *AnchorScope = getAnchorScope();
11713 UsedAssumedInformation,
11719 bool AllInterAreIntra =
false;
11726 for (
const AA::ValueAndContext &VAC :
Values) {
11727 addValue(
A, getState(), *VAC.
getValue(),
11731 if (AllInterAreIntra)
11738 HandleReturnedValue(*ReturnedArg,
nullptr,
true);
11741 bool AddValues =
true;
11744 addValue(
A, getState(), *RetI.getOperand(0), &RetI,
AA::AnyScope,
11748 return HandleReturnedValue(*RetI.getOperand(0), &RetI, AddValues);
11751 if (!
A.checkForAllInstructions(RetInstPred, *
this, {Instruction::Ret},
11752 UsedAssumedInformation,
11754 return indicatePessimisticFixpoint();
11757 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
11758 : ChangeStatus::CHANGED;
11763 return ChangeStatus::UNCHANGED;
11765 if (!getAssumedSimplifiedValues(
A,
Values, AA::ValueScope::Intraprocedural,
11767 return ChangeStatus::UNCHANGED;
11768 Value *NewVal = getSingleValue(
A, *
this, getIRPosition(),
Values);
11770 return ChangeStatus::UNCHANGED;
11775 "Number of function with unique return");
11778 {Attribute::get(Arg->
getContext(), Attribute::Returned)});
11783 Value *RetOp = RetI.getOperand(0);
11787 if (
A.changeUseAfterManifest(RetI.getOperandUse(0), *NewVal))
11788 Changed = ChangeStatus::CHANGED;
11791 bool UsedAssumedInformation =
false;
11792 (void)
A.checkForAllInstructions(RetInstPred, *
this, {Instruction::Ret},
11793 UsedAssumedInformation,
11799 return AAPotentialValues::indicatePessimisticFixpoint();
11803 void trackStatistics()
const override{
11810struct AAPotentialValuesFunction : AAPotentialValuesImpl {
11811 AAPotentialValuesFunction(
const IRPosition &IRP, Attributor &
A)
11812 : AAPotentialValuesImpl(IRP,
A) {}
11821 void trackStatistics()
const override {
11826struct AAPotentialValuesCallSite : AAPotentialValuesFunction {
11827 AAPotentialValuesCallSite(
const IRPosition &IRP, Attributor &
A)
11828 : AAPotentialValuesFunction(IRP,
A) {}
11831 void trackStatistics()
const override {
11836struct AAPotentialValuesCallSiteReturned : AAPotentialValuesImpl {
11837 AAPotentialValuesCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
11838 : AAPotentialValuesImpl(IRP,
A) {}
11842 auto AssumedBefore = getAssumed();
11846 return indicatePessimisticFixpoint();
11848 bool UsedAssumedInformation =
false;
11852 UsedAssumedInformation))
11853 return indicatePessimisticFixpoint();
11860 Values, S, UsedAssumedInformation))
11863 for (
auto &It :
Values) {
11864 Value *
V = It.getValue();
11865 std::optional<Value *> CallerV =
A.translateArgumentToCallSiteContent(
11866 V, *CB, *
this, UsedAssumedInformation);
11867 if (!CallerV.has_value()) {
11871 V = *CallerV ? *CallerV :
V;
11877 giveUpOnIntraprocedural(
A);
11880 addValue(
A, getState(), *V, CB, S, getAnchorScope());
11885 return indicatePessimisticFixpoint();
11887 return indicatePessimisticFixpoint();
11888 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
11889 : ChangeStatus::CHANGED;
11893 return AAPotentialValues::indicatePessimisticFixpoint();
11897 void trackStatistics()
const override {
11902struct AAPotentialValuesCallSiteArgument : AAPotentialValuesFloating {
11903 AAPotentialValuesCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
11904 : AAPotentialValuesFloating(IRP,
A) {}
11907 void trackStatistics()
const override {
11915struct AAAssumptionInfoImpl :
public AAAssumptionInfo {
11916 AAAssumptionInfoImpl(
const IRPosition &IRP, Attributor &
A,
11917 const DenseSet<StringRef> &
Known)
11918 : AAAssumptionInfo(IRP,
A,
Known) {}
11923 if (getKnown().isUniversal())
11924 return ChangeStatus::UNCHANGED;
11926 const IRPosition &IRP = getIRPosition();
11928 getAssumed().getSet().
end());
11930 return A.manifestAttrs(IRP,
11937 bool hasAssumption(
const StringRef Assumption)
const override {
11938 return isValidState() && setContains(Assumption);
11942 const std::string getAsStr(Attributor *
A)
const override {
11943 const SetContents &
Known = getKnown();
11944 const SetContents &Assumed = getAssumed();
11948 const std::string KnownStr =
llvm::join(Set,
",");
11950 std::string AssumedStr =
"Universal";
11951 if (!Assumed.isUniversal()) {
11952 Set.assign(Assumed.getSet().begin(), Assumed.getSet().end());
11955 return "Known [" + KnownStr +
"]," +
" Assumed [" + AssumedStr +
"]";
11970struct AAAssumptionInfoFunction final : AAAssumptionInfoImpl {
11971 AAAssumptionInfoFunction(
const IRPosition &IRP, Attributor &
A)
11972 : AAAssumptionInfoImpl(IRP,
A,
11979 auto CallSitePred = [&](AbstractCallSite ACS) {
11980 const auto *AssumptionAA =
A.getAAFor<AAAssumptionInfo>(
11982 DepClassTy::REQUIRED);
11986 Changed |= getIntersection(AssumptionAA->getAssumed());
11987 return !getAssumed().empty() || !getKnown().empty();
11990 bool UsedAssumedInformation =
false;
11995 if (!
A.checkForAllCallSites(CallSitePred, *
this,
true,
11996 UsedAssumedInformation))
11997 return indicatePessimisticFixpoint();
11999 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
12002 void trackStatistics()
const override {}
12006struct AAAssumptionInfoCallSite final : AAAssumptionInfoImpl {
12008 AAAssumptionInfoCallSite(
const IRPosition &IRP, Attributor &
A)
12009 : AAAssumptionInfoImpl(IRP,
A, getInitialAssumptions(IRP)) {}
12014 A.getAAFor<AAAssumptionInfo>(*
this, FnPos, DepClassTy::REQUIRED);
12020 auto *AssumptionAA =
12021 A.getAAFor<AAAssumptionInfo>(*
this, FnPos, DepClassTy::REQUIRED);
12023 return indicatePessimisticFixpoint();
12024 bool Changed = getIntersection(AssumptionAA->getAssumed());
12025 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
12029 void trackStatistics()
const override {}
12034 DenseSet<StringRef> getInitialAssumptions(
const IRPosition &IRP) {
12041 return Assumptions;
12056struct AAUnderlyingObjectsImpl
12062 const std::string getAsStr(
Attributor *
A)
const override {
12063 if (!isValidState())
12064 return "<invalid>";
12067 OS <<
"underlying objects: inter " << InterAssumedUnderlyingObjects.size()
12068 <<
" objects, intra " << IntraAssumedUnderlyingObjects.size()
12070 if (!InterAssumedUnderlyingObjects.empty()) {
12071 OS <<
"inter objects:\n";
12072 for (
auto *Obj : InterAssumedUnderlyingObjects)
12073 OS << *Obj <<
'\n';
12075 if (!IntraAssumedUnderlyingObjects.empty()) {
12076 OS <<
"intra objects:\n";
12077 for (
auto *Obj : IntraAssumedUnderlyingObjects)
12078 OS << *
Obj <<
'\n';
12084 void trackStatistics()
const override {}
12088 auto &Ptr = getAssociatedValue();
12090 bool UsedAssumedInformation =
false;
12091 auto DoUpdate = [&](SmallSetVector<Value *, 8> &UnderlyingObjects,
12093 SmallPtrSet<Value *, 8> SeenObjects;
12097 Scope, UsedAssumedInformation))
12098 return UnderlyingObjects.
insert(&Ptr);
12102 for (
unsigned I = 0;
I <
Values.size(); ++
I) {
12106 if (!SeenObjects.
insert(UO ? UO : Obj).second)
12108 if (UO && UO != Obj) {
12114 const auto *OtherAA =
A.getAAFor<AAUnderlyingObjects>(
12116 auto Pred = [&](
Value &
V) {
12120 Values.emplace_back(V,
nullptr);
12124 if (!OtherAA || !OtherAA->forallUnderlyingObjects(Pred, Scope))
12126 "The forall call should not return false at this position");
12132 Changed |= handleIndirect(
A, *Obj, UnderlyingObjects, Scope,
12133 UsedAssumedInformation);
12139 for (
unsigned u = 0, e =
PHI->getNumIncomingValues(); u < e; u++) {
12141 handleIndirect(
A, *
PHI->getIncomingValue(u), UnderlyingObjects,
12142 Scope, UsedAssumedInformation);
12156 if (!UsedAssumedInformation)
12157 indicateOptimisticFixpoint();
12158 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
12161 bool forallUnderlyingObjects(
12162 function_ref<
bool(
Value &)> Pred,
12164 if (!isValidState())
12165 return Pred(getAssociatedValue());
12168 ? IntraAssumedUnderlyingObjects
12169 : InterAssumedUnderlyingObjects;
12170 for (
Value *Obj : AssumedUnderlyingObjects)
12180 bool handleIndirect(Attributor &
A,
Value &V,
12181 SmallSetVector<Value *, 8> &UnderlyingObjects,
12184 const auto *AA =
A.getAAFor<AAUnderlyingObjects>(
12186 auto Pred = [&](
Value &
V) {
12190 if (!AA || !AA->forallUnderlyingObjects(Pred, Scope))
12192 "The forall call should not return false at this position");
12198 SmallSetVector<Value *, 8> IntraAssumedUnderlyingObjects;
12200 SmallSetVector<Value *, 8> InterAssumedUnderlyingObjects;
12203struct AAUnderlyingObjectsFloating final : AAUnderlyingObjectsImpl {
12204 AAUnderlyingObjectsFloating(
const IRPosition &IRP, Attributor &
A)
12205 : AAUnderlyingObjectsImpl(IRP,
A) {}
12208struct AAUnderlyingObjectsArgument final : AAUnderlyingObjectsImpl {
12209 AAUnderlyingObjectsArgument(
const IRPosition &IRP, Attributor &
A)
12210 : AAUnderlyingObjectsImpl(IRP,
A) {}
12213struct AAUnderlyingObjectsCallSite final : AAUnderlyingObjectsImpl {
12214 AAUnderlyingObjectsCallSite(
const IRPosition &IRP, Attributor &
A)
12215 : AAUnderlyingObjectsImpl(IRP,
A) {}
12218struct AAUnderlyingObjectsCallSiteArgument final : AAUnderlyingObjectsImpl {
12219 AAUnderlyingObjectsCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
12220 : AAUnderlyingObjectsImpl(IRP,
A) {}
12223struct AAUnderlyingObjectsReturned final : AAUnderlyingObjectsImpl {
12224 AAUnderlyingObjectsReturned(
const IRPosition &IRP, Attributor &
A)
12225 : AAUnderlyingObjectsImpl(IRP,
A) {}
12228struct AAUnderlyingObjectsCallSiteReturned final : AAUnderlyingObjectsImpl {
12229 AAUnderlyingObjectsCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
12230 : AAUnderlyingObjectsImpl(IRP,
A) {}
12233struct AAUnderlyingObjectsFunction final : AAUnderlyingObjectsImpl {
12234 AAUnderlyingObjectsFunction(
const IRPosition &IRP, Attributor &
A)
12235 : AAUnderlyingObjectsImpl(IRP,
A) {}
12241struct AAGlobalValueInfoFloating :
public AAGlobalValueInfo {
12242 AAGlobalValueInfoFloating(
const IRPosition &IRP, Attributor &
A)
12243 : AAGlobalValueInfo(IRP,
A) {}
12248 bool checkUse(Attributor &
A,
const Use &U,
bool &Follow,
12249 SmallVectorImpl<const Value *> &Worklist) {
12255 if (!GV->hasLocalLinkage() && !
A.isClosedWorldModule())
12261 LLVM_DEBUG(
dbgs() <<
"[AAGlobalValueInfo] Check use: " << *
U.get() <<
" in "
12262 << *UInst <<
"\n");
12265 int Idx = &
Cmp->getOperandUse(0) == &
U;
12268 return U == &getAnchorValue();
12273 auto CallSitePred = [&](AbstractCallSite ACS) {
12274 Worklist.
push_back(ACS.getInstruction());
12277 bool UsedAssumedInformation =
false;
12279 if (!
A.checkForAllCallSites(CallSitePred, *UInst->
getFunction(),
12281 UsedAssumedInformation))
12299 if (!Fn || !
A.isFunctionIPOAmendable(*Fn))
12308 unsigned NumUsesBefore =
Uses.size();
12310 SmallPtrSet<const Value *, 8> Visited;
12314 auto UsePred = [&](
const Use &
U,
bool &Follow) ->
bool {
12322 return checkUse(
A, U, Follow, Worklist);
12324 auto EquivalentUseCB = [&](
const Use &OldU,
const Use &NewU) {
12325 Uses.insert(&OldU);
12329 while (!Worklist.
empty()) {
12331 if (!Visited.
insert(V).second)
12333 if (!
A.checkForAllUses(UsePred, *
this, *V,
12335 DepClassTy::OPTIONAL,
12336 true, EquivalentUseCB)) {
12337 return indicatePessimisticFixpoint();
12341 return Uses.size() == NumUsesBefore ? ChangeStatus::UNCHANGED
12342 : ChangeStatus::CHANGED;
12345 bool isPotentialUse(
const Use &U)
const override {
12346 return !isValidState() ||
Uses.contains(&U);
12351 return ChangeStatus::UNCHANGED;
12355 const std::string getAsStr(Attributor *
A)
const override {
12356 return "[" + std::to_string(
Uses.size()) +
" uses]";
12359 void trackStatistics()
const override {
12365 SmallPtrSet<const Use *, 8>
Uses;
12371struct AAIndirectCallInfoCallSite :
public AAIndirectCallInfo {
12372 AAIndirectCallInfoCallSite(
const IRPosition &IRP, Attributor &
A)
12373 : AAIndirectCallInfo(IRP,
A) {}
12377 auto *MD = getCtxI()->getMetadata(LLVMContext::MD_callees);
12378 if (!MD && !
A.isClosedWorldModule())
12382 for (
const auto &
Op : MD->operands())
12384 PotentialCallees.insert(Callee);
12385 }
else if (
A.isClosedWorldModule()) {
12387 A.getInfoCache().getIndirectlyCallableFunctions(
A);
12388 PotentialCallees.insert_range(IndirectlyCallableFunctions);
12391 if (PotentialCallees.empty())
12392 indicateOptimisticFixpoint();
12400 SmallSetVector<Function *, 4> AssumedCalleesNow;
12401 bool AllCalleesKnownNow = AllCalleesKnown;
12403 auto CheckPotentialCalleeUse = [&](
Function &PotentialCallee,
12404 bool &UsedAssumedInformation) {
12405 const auto *GIAA =
A.getAAFor<AAGlobalValueInfo>(
12407 if (!GIAA || GIAA->isPotentialUse(CalleeUse))
12409 UsedAssumedInformation = !GIAA->isAtFixpoint();
12413 auto AddPotentialCallees = [&]() {
12414 for (
auto *PotentialCallee : PotentialCallees) {
12415 bool UsedAssumedInformation =
false;
12416 if (CheckPotentialCalleeUse(*PotentialCallee, UsedAssumedInformation))
12417 AssumedCalleesNow.
insert(PotentialCallee);
12423 bool UsedAssumedInformation =
false;
12426 AA::ValueScope::AnyScope,
12427 UsedAssumedInformation)) {
12428 if (PotentialCallees.empty())
12429 return indicatePessimisticFixpoint();
12430 AddPotentialCallees();
12435 auto CheckPotentialCallee = [&](
Function &Fn) {
12436 if (!PotentialCallees.empty() && !PotentialCallees.count(&Fn))
12439 auto &CachedResult = FilterResults[&Fn];
12440 if (CachedResult.has_value())
12441 return CachedResult.value();
12443 bool UsedAssumedInformation =
false;
12444 if (!CheckPotentialCalleeUse(Fn, UsedAssumedInformation)) {
12445 if (!UsedAssumedInformation)
12446 CachedResult =
false;
12455 for (
int I = NumCBArgs;
I < NumFnArgs; ++
I) {
12456 bool IsKnown =
false;
12459 DepClassTy::OPTIONAL, IsKnown)) {
12461 CachedResult =
false;
12466 CachedResult =
true;
12472 for (
auto &VAC :
Values) {
12480 if (CheckPotentialCallee(*VACFn))
12481 AssumedCalleesNow.
insert(VACFn);
12484 if (!PotentialCallees.empty()) {
12485 AddPotentialCallees();
12488 AllCalleesKnownNow =
false;
12491 if (AssumedCalleesNow == AssumedCallees &&
12492 AllCalleesKnown == AllCalleesKnownNow)
12493 return ChangeStatus::UNCHANGED;
12495 std::swap(AssumedCallees, AssumedCalleesNow);
12496 AllCalleesKnown = AllCalleesKnownNow;
12497 return ChangeStatus::CHANGED;
12503 if (!AllCalleesKnown && AssumedCallees.empty())
12504 return ChangeStatus::UNCHANGED;
12507 bool UsedAssumedInformation =
false;
12508 if (
A.isAssumedDead(*CB,
this,
nullptr,
12509 UsedAssumedInformation))
12510 return ChangeStatus::UNCHANGED;
12515 if (
FP->getType()->getPointerAddressSpace() != ProgramAS)
12516 FP =
new AddrSpaceCastInst(
12517 FP, PointerType::get(
FP->getContext(), ProgramAS),
12518 FP->getName() +
".as" + Twine(ProgramAS), CB->
getIterator());
12527 if (AssumedCallees.empty()) {
12528 assert(AllCalleesKnown &&
12529 "Expected all callees to be known if there are none.");
12530 A.changeToUnreachableAfterManifest(CB);
12531 return ChangeStatus::CHANGED;
12535 if (AllCalleesKnown && AssumedCallees.size() == 1) {
12536 auto *NewCallee = AssumedCallees.front();
12539 NumIndirectCallsPromoted++;
12540 return ChangeStatus::CHANGED;
12547 A.deleteAfterManifest(*CB);
12548 return ChangeStatus::CHANGED;
12558 bool SpecializedForAnyCallees =
false;
12559 bool SpecializedForAllCallees = AllCalleesKnown;
12560 ICmpInst *LastCmp =
nullptr;
12563 for (
Function *NewCallee : AssumedCallees) {
12564 if (!
A.shouldSpecializeCallSiteForCallee(*
this, *CB, *NewCallee,
12565 AssumedCallees.size())) {
12566 SkippedAssumedCallees.
push_back(NewCallee);
12567 SpecializedForAllCallees =
false;
12570 SpecializedForAnyCallees =
true;
12576 A.registerManifestAddedBasicBlock(*ThenTI->
getParent());
12577 A.registerManifestAddedBasicBlock(*IP->getParent());
12583 A.registerManifestAddedBasicBlock(*ElseBB);
12585 SplitTI->replaceUsesOfWith(CBBB, ElseBB);
12590 CastInst *RetBC =
nullptr;
12591 CallInst *NewCall =
nullptr;
12596 NumIndirectCallsPromoted++;
12604 auto AttachCalleeMetadata = [&](CallBase &IndirectCB) {
12605 if (!AllCalleesKnown)
12606 return ChangeStatus::UNCHANGED;
12607 MDBuilder MDB(IndirectCB.getContext());
12608 MDNode *Callees = MDB.createCallees(SkippedAssumedCallees);
12609 IndirectCB.setMetadata(LLVMContext::MD_callees, Callees);
12610 return ChangeStatus::CHANGED;
12613 if (!SpecializedForAnyCallees)
12614 return AttachCalleeMetadata(*CB);
12617 if (SpecializedForAllCallees) {
12620 new UnreachableInst(IP->getContext(), IP);
12621 IP->eraseFromParent();
12624 CBClone->setName(CB->
getName());
12625 CBClone->insertBefore(*IP->getParent(), IP);
12626 NewCalls.
push_back({CBClone,
nullptr});
12627 AttachCalleeMetadata(*CBClone);
12634 CB->
getParent()->getFirstInsertionPt());
12635 for (
auto &It : NewCalls) {
12636 CallBase *NewCall = It.first;
12637 Instruction *CallRet = It.second ? It.second : It.first;
12649 A.deleteAfterManifest(*CB);
12650 Changed = ChangeStatus::CHANGED;
12656 const std::string getAsStr(Attributor *
A)
const override {
12657 return std::string(AllCalleesKnown ?
"eliminate" :
"specialize") +
12658 " indirect call site with " + std::to_string(AssumedCallees.size()) +
12662 void trackStatistics()
const override {
12663 if (AllCalleesKnown) {
12665 Eliminated, CallSites,
12666 "Number of indirect call sites eliminated via specialization")
12669 "Number of indirect call sites specialized")
12673 bool foreachCallee(function_ref<
bool(
Function *)> CB)
const override {
12674 return isValidState() && AllCalleesKnown &&
all_of(AssumedCallees, CB);
12679 DenseMap<Function *, std::optional<bool>> FilterResults;
12683 SmallSetVector<Function *, 4> PotentialCallees;
12687 SmallSetVector<Function *, 4> AssumedCallees;
12691 bool AllCalleesKnown =
true;
12698struct AAInvariantLoadPointerImpl
12699 :
public StateWrapper<BitIntegerState<uint8_t, 15>,
12700 AAInvariantLoadPointer> {
12704 IS_NOALIAS = 1 << 0,
12707 IS_NOEFFECT = 1 << 1,
12709 IS_LOCALLY_INVARIANT = 1 << 2,
12711 IS_LOCALLY_CONSTRAINED = 1 << 3,
12713 IS_BEST_STATE = IS_NOALIAS | IS_NOEFFECT | IS_LOCALLY_INVARIANT |
12714 IS_LOCALLY_CONSTRAINED,
12716 static_assert(getBestState() == IS_BEST_STATE,
"Unexpected best state");
12719 StateWrapper<BitIntegerState<uint8_t, 15>, AAInvariantLoadPointer>;
12723 AAInvariantLoadPointerImpl(
const IRPosition &IRP, Attributor &
A)
12726 bool isKnownInvariant()
const final {
12727 return isKnownLocallyInvariant() && isKnown(IS_LOCALLY_CONSTRAINED);
12730 bool isKnownLocallyInvariant()
const final {
12731 if (isKnown(IS_LOCALLY_INVARIANT))
12733 return isKnown(IS_NOALIAS | IS_NOEFFECT);
12736 bool isAssumedInvariant()
const final {
12737 return isAssumedLocallyInvariant() && isAssumed(IS_LOCALLY_CONSTRAINED);
12740 bool isAssumedLocallyInvariant()
const final {
12741 if (isAssumed(IS_LOCALLY_INVARIANT))
12743 return isAssumed(IS_NOALIAS | IS_NOEFFECT);
12750 if (requiresNoAlias() && !isAssumed(IS_NOALIAS))
12751 return indicatePessimisticFixpoint();
12755 Changed |= updateLocalInvariance(
A);
12761 if (!isKnownInvariant())
12762 return ChangeStatus::UNCHANGED;
12765 const Value *Ptr = &getAssociatedValue();
12766 const auto TagInvariantLoads = [&](
const Use &
U,
bool &) {
12767 if (
U.get() != Ptr)
12775 if (!
A.isRunOn(
I->getFunction()))
12778 if (
I->hasMetadata(LLVMContext::MD_invariant_load))
12782 LI->setMetadata(LLVMContext::MD_invariant_load,
12784 Changed = ChangeStatus::CHANGED;
12789 (void)
A.checkForAllUses(TagInvariantLoads, *
this, *Ptr);
12794 const std::string getAsStr(Attributor *)
const override {
12795 if (isKnownInvariant())
12796 return "load-invariant pointer";
12797 return "non-invariant pointer";
12801 void trackStatistics()
const override {}
12805 bool requiresNoAlias()
const {
12806 switch (getPositionKind()) {
12812 case IRP_CALL_SITE:
12814 case IRP_CALL_SITE_RETURNED: {
12819 case IRP_ARGUMENT: {
12820 const Function *
F = getAssociatedFunction();
12821 assert(
F &&
"no associated function for argument");
12827 bool isExternal()
const {
12828 const Function *
F = getAssociatedFunction();
12832 getPositionKind() != IRP_CALL_SITE_RETURNED;
12836 if (isKnown(IS_NOALIAS) || !isAssumed(IS_NOALIAS))
12837 return ChangeStatus::UNCHANGED;
12840 if (
const auto *ANoAlias =
A.getOrCreateAAFor<AANoAlias>(
12841 getIRPosition(),
this, DepClassTy::REQUIRED)) {
12842 if (ANoAlias->isKnownNoAlias()) {
12843 addKnownBits(IS_NOALIAS);
12844 return ChangeStatus::CHANGED;
12847 if (!ANoAlias->isAssumedNoAlias()) {
12848 removeAssumedBits(IS_NOALIAS);
12849 return ChangeStatus::CHANGED;
12852 return ChangeStatus::UNCHANGED;
12857 if (
const Argument *Arg = getAssociatedArgument()) {
12859 addKnownBits(IS_NOALIAS);
12860 return ChangeStatus::UNCHANGED;
12865 removeAssumedBits(IS_NOALIAS);
12866 return ChangeStatus::CHANGED;
12869 return ChangeStatus::UNCHANGED;
12873 if (isKnown(IS_NOEFFECT) || !isAssumed(IS_NOEFFECT))
12874 return ChangeStatus::UNCHANGED;
12876 if (!getAssociatedFunction())
12877 return indicatePessimisticFixpoint();
12880 return indicatePessimisticFixpoint();
12882 const auto HasNoEffectLoads = [&](
const Use &
U,
bool &) {
12884 return !LI || !LI->mayHaveSideEffects();
12886 if (!
A.checkForAllUses(HasNoEffectLoads, *
this, getAssociatedValue()))
12887 return indicatePessimisticFixpoint();
12889 if (
const auto *AMemoryBehavior =
A.getOrCreateAAFor<AAMemoryBehavior>(
12890 getIRPosition(),
this, DepClassTy::REQUIRED)) {
12893 if (!AMemoryBehavior->isAssumedReadOnly())
12894 return indicatePessimisticFixpoint();
12896 if (AMemoryBehavior->isKnownReadOnly()) {
12897 addKnownBits(IS_NOEFFECT);
12898 return ChangeStatus::UNCHANGED;
12901 return ChangeStatus::UNCHANGED;
12904 if (
const Argument *Arg = getAssociatedArgument()) {
12906 addKnownBits(IS_NOEFFECT);
12907 return ChangeStatus::UNCHANGED;
12912 return indicatePessimisticFixpoint();
12915 return ChangeStatus::UNCHANGED;
12919 if (isKnown(IS_LOCALLY_INVARIANT) || !isAssumed(IS_LOCALLY_INVARIANT))
12920 return ChangeStatus::UNCHANGED;
12923 const auto *AUO =
A.getOrCreateAAFor<AAUnderlyingObjects>(
12924 getIRPosition(),
this, DepClassTy::REQUIRED);
12926 return ChangeStatus::UNCHANGED;
12928 bool UsedAssumedInformation =
false;
12929 const auto IsLocallyInvariantLoadIfPointer = [&](
const Value &
V) {
12930 if (!
V.getType()->isPointerTy())
12932 const auto *IsInvariantLoadPointer =
12934 DepClassTy::REQUIRED);
12936 if (!IsInvariantLoadPointer)
12939 if (IsInvariantLoadPointer->isKnownLocallyInvariant())
12941 if (!IsInvariantLoadPointer->isAssumedLocallyInvariant())
12944 UsedAssumedInformation =
true;
12947 if (!AUO->forallUnderlyingObjects(IsLocallyInvariantLoadIfPointer))
12948 return indicatePessimisticFixpoint();
12954 if (!IsLocallyInvariantLoadIfPointer(*Arg))
12955 return indicatePessimisticFixpoint();
12960 if (!UsedAssumedInformation) {
12962 addKnownBits(IS_LOCALLY_INVARIANT);
12963 return ChangeStatus::CHANGED;
12966 return ChangeStatus::UNCHANGED;
12970struct AAInvariantLoadPointerFloating final : AAInvariantLoadPointerImpl {
12971 AAInvariantLoadPointerFloating(
const IRPosition &IRP, Attributor &
A)
12972 : AAInvariantLoadPointerImpl(IRP,
A) {}
12975struct AAInvariantLoadPointerReturned final : AAInvariantLoadPointerImpl {
12976 AAInvariantLoadPointerReturned(
const IRPosition &IRP, Attributor &
A)
12977 : AAInvariantLoadPointerImpl(IRP,
A) {}
12980 removeAssumedBits(IS_LOCALLY_CONSTRAINED);
12984struct AAInvariantLoadPointerCallSiteReturned final
12985 : AAInvariantLoadPointerImpl {
12986 AAInvariantLoadPointerCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
12987 : AAInvariantLoadPointerImpl(IRP,
A) {}
12990 const Function *
F = getAssociatedFunction();
12991 assert(
F &&
"no associated function for return from call");
12993 if (!
F->isDeclaration() && !
F->isIntrinsic())
12994 return AAInvariantLoadPointerImpl::initialize(
A);
12999 return AAInvariantLoadPointerImpl::initialize(
A);
13001 if (
F->onlyReadsMemory() &&
F->hasNoSync())
13002 return AAInvariantLoadPointerImpl::initialize(
A);
13006 indicatePessimisticFixpoint();
13010struct AAInvariantLoadPointerArgument final : AAInvariantLoadPointerImpl {
13011 AAInvariantLoadPointerArgument(
const IRPosition &IRP, Attributor &
A)
13012 : AAInvariantLoadPointerImpl(IRP,
A) {}
13015 const Function *
F = getAssociatedFunction();
13016 assert(
F &&
"no associated function for argument");
13019 addKnownBits(IS_LOCALLY_CONSTRAINED);
13023 if (!
F->hasLocalLinkage())
13024 removeAssumedBits(IS_LOCALLY_CONSTRAINED);
13028struct AAInvariantLoadPointerCallSiteArgument final
13029 : AAInvariantLoadPointerImpl {
13030 AAInvariantLoadPointerCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
13031 : AAInvariantLoadPointerImpl(IRP,
A) {}
13038template <
typename InstType>
13039static bool makeChange(Attributor &
A, InstType *MemInst,
const Use &U,
13040 Value *OriginalValue, PointerType *NewPtrTy,
13041 bool UseOriginalValue) {
13042 if (
U.getOperandNo() != InstType::getPointerOperandIndex())
13045 if (MemInst->isVolatile()) {
13046 auto *
TTI =
A.getInfoCache().getAnalysisResultForFunction<TargetIRAnalysis>(
13047 *MemInst->getFunction());
13048 unsigned NewAS = NewPtrTy->getPointerAddressSpace();
13053 if (UseOriginalValue) {
13054 A.changeUseAfterManifest(
const_cast<Use &
>(U), *OriginalValue);
13058 Instruction *CastInst =
new AddrSpaceCastInst(OriginalValue, NewPtrTy);
13060 A.changeUseAfterManifest(
const_cast<Use &
>(U), *CastInst);
13064struct AAAddressSpaceImpl :
public AAAddressSpace {
13065 AAAddressSpaceImpl(
const IRPosition &IRP, Attributor &
A)
13066 : AAAddressSpace(IRP,
A) {}
13069 assert(isValidState() &&
"the AA is invalid");
13070 return AssumedAddressSpace;
13075 assert(getAssociatedType()->isPtrOrPtrVectorTy() &&
13076 "Associated value is not a pointer");
13078 if (!
A.getInfoCache().getFlatAddressSpace().has_value()) {
13079 indicatePessimisticFixpoint();
13083 unsigned FlatAS =
A.getInfoCache().getFlatAddressSpace().value();
13084 unsigned AS = getAssociatedType()->getPointerAddressSpace();
13085 if (AS != FlatAS) {
13086 [[maybe_unused]]
bool R = takeAddressSpace(AS);
13087 assert(R &&
"The take should happen");
13088 indicateOptimisticFixpoint();
13093 uint32_t OldAddressSpace = AssumedAddressSpace;
13094 unsigned FlatAS =
A.getInfoCache().getFlatAddressSpace().value();
13096 auto CheckAddressSpace = [&](
Value &
Obj) {
13102 unsigned ObjAS =
Obj.getType()->getPointerAddressSpace();
13103 if (ObjAS != FlatAS)
13104 return takeAddressSpace(ObjAS);
13118 A.getInfoCache().getAnalysisResultForFunction<TargetIRAnalysis>(*F);
13120 if (AssumedAS != ~0U)
13121 return takeAddressSpace(AssumedAS);
13125 return takeAddressSpace(FlatAS);
13128 auto *AUO =
A.getOrCreateAAFor<AAUnderlyingObjects>(getIRPosition(),
this,
13129 DepClassTy::REQUIRED);
13130 if (!AUO->forallUnderlyingObjects(CheckAddressSpace))
13131 return indicatePessimisticFixpoint();
13133 return OldAddressSpace == AssumedAddressSpace ? ChangeStatus::UNCHANGED
13134 : ChangeStatus::CHANGED;
13141 if (NewAS == InvalidAddressSpace ||
13143 return ChangeStatus::UNCHANGED;
13145 unsigned FlatAS =
A.getInfoCache().getFlatAddressSpace().value();
13147 Value *AssociatedValue = &getAssociatedValue();
13148 Value *OriginalValue = peelAddrspacecast(AssociatedValue, FlatAS);
13151 PointerType::get(getAssociatedType()->
getContext(), NewAS);
13152 bool UseOriginalValue =
13157 auto Pred = [&](
const Use &
U,
bool &) {
13158 if (
U.get() != AssociatedValue)
13169 makeChange(
A, LI, U, OriginalValue, NewPtrTy, UseOriginalValue);
13172 makeChange(
A, SI, U, OriginalValue, NewPtrTy, UseOriginalValue);
13175 makeChange(
A, RMW, U, OriginalValue, NewPtrTy, UseOriginalValue);
13178 makeChange(
A, CmpX, U, OriginalValue, NewPtrTy, UseOriginalValue);
13185 (void)
A.checkForAllUses(Pred, *
this, getAssociatedValue(),
13188 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
13192 const std::string getAsStr(Attributor *
A)
const override {
13193 if (!isValidState())
13194 return "addrspace(<invalid>)";
13195 return "addrspace(" +
13196 (AssumedAddressSpace == InvalidAddressSpace
13198 : std::to_string(AssumedAddressSpace)) +
13203 uint32_t AssumedAddressSpace = InvalidAddressSpace;
13205 bool takeAddressSpace(uint32_t AS) {
13206 if (AssumedAddressSpace == InvalidAddressSpace) {
13207 AssumedAddressSpace = AS;
13210 return AssumedAddressSpace == AS;
13213 static Value *peelAddrspacecast(
Value *V,
unsigned FlatAS) {
13215 assert(
I->getSrcAddressSpace() != FlatAS &&
13216 "there should not be flat AS -> non-flat AS");
13217 return I->getPointerOperand();
13220 if (
C->getOpcode() == Instruction::AddrSpaceCast) {
13221 assert(
C->getOperand(0)->getType()->getPointerAddressSpace() !=
13223 "there should not be flat AS -> non-flat AS X");
13224 return C->getOperand(0);
13230struct AAAddressSpaceFloating final : AAAddressSpaceImpl {
13231 AAAddressSpaceFloating(
const IRPosition &IRP, Attributor &
A)
13232 : AAAddressSpaceImpl(IRP,
A) {}
13234 void trackStatistics()
const override {
13239struct AAAddressSpaceReturned final : AAAddressSpaceImpl {
13240 AAAddressSpaceReturned(
const IRPosition &IRP, Attributor &
A)
13241 : AAAddressSpaceImpl(IRP,
A) {}
13247 (void)indicatePessimisticFixpoint();
13250 void trackStatistics()
const override {
13255struct AAAddressSpaceCallSiteReturned final : AAAddressSpaceImpl {
13256 AAAddressSpaceCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
13257 : AAAddressSpaceImpl(IRP,
A) {}
13259 void trackStatistics()
const override {
13264struct AAAddressSpaceArgument final : AAAddressSpaceImpl {
13265 AAAddressSpaceArgument(
const IRPosition &IRP, Attributor &
A)
13266 : AAAddressSpaceImpl(IRP,
A) {}
13271struct AAAddressSpaceCallSiteArgument final : AAAddressSpaceImpl {
13272 AAAddressSpaceCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
13273 : AAAddressSpaceImpl(IRP,
A) {}
13279 (void)indicatePessimisticFixpoint();
13282 void trackStatistics()
const override {
13297struct AANoAliasAddrSpaceImpl :
public AANoAliasAddrSpace {
13298 AANoAliasAddrSpaceImpl(
const IRPosition &IRP, Attributor &
A)
13299 : AANoAliasAddrSpace(IRP,
A) {}
13302 assert(getAssociatedType()->isPtrOrPtrVectorTy() &&
13303 "Associated value is not a pointer");
13307 std::optional<unsigned> FlatAS =
A.getInfoCache().getFlatAddressSpace();
13308 if (!FlatAS.has_value()) {
13309 indicatePessimisticFixpoint();
13315 unsigned AS = getAssociatedType()->getPointerAddressSpace();
13316 if (AS != *FlatAS) {
13318 indicateOptimisticFixpoint();
13323 unsigned FlatAS =
A.getInfoCache().getFlatAddressSpace().value();
13324 uint32_t OldAssumed = getAssumed();
13326 auto CheckAddressSpace = [&](
Value &
Obj) {
13330 unsigned AS =
Obj.getType()->getPointerAddressSpace();
13334 removeAS(
Obj.getType()->getPointerAddressSpace());
13338 const AAUnderlyingObjects *AUO =
A.getOrCreateAAFor<AAUnderlyingObjects>(
13339 getIRPosition(),
this, DepClassTy::REQUIRED);
13341 return indicatePessimisticFixpoint();
13343 return OldAssumed == getAssumed() ? ChangeStatus::UNCHANGED
13344 : ChangeStatus::CHANGED;
13349 unsigned FlatAS =
A.getInfoCache().getFlatAddressSpace().value();
13351 unsigned AS = getAssociatedType()->getPointerAddressSpace();
13352 if (AS != FlatAS ||
Map.empty())
13353 return ChangeStatus::UNCHANGED;
13355 LLVMContext &Ctx = getAssociatedValue().getContext();
13356 MDNode *NoAliasASNode =
nullptr;
13357 MDBuilder MDB(Ctx);
13359 for (RangeMap::const_iterator
I =
Map.begin();
I !=
Map.end();
I++) {
13362 unsigned Upper =
I.stop();
13363 unsigned Lower =
I.start();
13364 if (!NoAliasASNode) {
13365 NoAliasASNode = MDB.createRange(APInt(32,
Lower), APInt(32,
Upper + 1));
13368 MDNode *ASRange = MDB.createRange(APInt(32,
Lower), APInt(32,
Upper + 1));
13372 Value *AssociatedValue = &getAssociatedValue();
13375 auto AddNoAliasAttr = [&](
const Use &
U,
bool &) {
13376 if (
U.get() != AssociatedValue)
13379 if (!Inst || Inst->
hasMetadata(LLVMContext::MD_noalias_addrspace))
13386 Inst->
setMetadata(LLVMContext::MD_noalias_addrspace, NoAliasASNode);
13390 (void)
A.checkForAllUses(AddNoAliasAttr, *
this, *AssociatedValue,
13392 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
13396 const std::string getAsStr(Attributor *
A)
const override {
13397 if (!isValidState())
13398 return "<invalid>";
13400 raw_string_ostream OS(Str);
13401 OS <<
"CanNotBeAddrSpace(";
13402 for (RangeMap::const_iterator
I =
Map.begin();
I !=
Map.end();
I++) {
13403 unsigned Upper =
I.stop();
13404 unsigned Lower =
I.start();
13405 OS <<
' ' <<
'[' <<
Upper <<
',' <<
Lower + 1 <<
')';
13412 void removeAS(
unsigned AS) {
13413 RangeMap::iterator
I =
Map.find(AS);
13415 if (
I !=
Map.end()) {
13416 unsigned Upper =
I.stop();
13417 unsigned Lower =
I.start();
13421 if (AS != ~((
unsigned)0) && AS + 1 <=
Upper)
13423 if (AS != 0 &&
Lower <= AS - 1)
13428 void resetASRanges(Attributor &
A) {
13430 Map.insert(0,
A.getInfoCache().getMaxAddrSpace(),
true);
13434struct AANoAliasAddrSpaceFloating final : AANoAliasAddrSpaceImpl {
13435 AANoAliasAddrSpaceFloating(
const IRPosition &IRP, Attributor &
A)
13436 : AANoAliasAddrSpaceImpl(IRP,
A) {}
13438 void trackStatistics()
const override {
13443struct AANoAliasAddrSpaceReturned final : AANoAliasAddrSpaceImpl {
13444 AANoAliasAddrSpaceReturned(
const IRPosition &IRP, Attributor &
A)
13445 : AANoAliasAddrSpaceImpl(IRP,
A) {}
13447 void trackStatistics()
const override {
13452struct AANoAliasAddrSpaceCallSiteReturned final : AANoAliasAddrSpaceImpl {
13453 AANoAliasAddrSpaceCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
13454 : AANoAliasAddrSpaceImpl(IRP,
A) {}
13456 void trackStatistics()
const override {
13461struct AANoAliasAddrSpaceArgument final : AANoAliasAddrSpaceImpl {
13462 AANoAliasAddrSpaceArgument(
const IRPosition &IRP, Attributor &
A)
13463 : AANoAliasAddrSpaceImpl(IRP,
A) {}
13465 void trackStatistics()
const override {
13470struct AANoAliasAddrSpaceCallSiteArgument final : AANoAliasAddrSpaceImpl {
13471 AANoAliasAddrSpaceCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
13472 : AANoAliasAddrSpaceImpl(IRP,
A) {}
13474 void trackStatistics()
const override {
13481struct AAAllocationInfoImpl :
public AAAllocationInfo {
13482 AAAllocationInfoImpl(
const IRPosition &IRP, Attributor &
A)
13483 : AAAllocationInfo(IRP,
A) {}
13485 std::optional<TypeSize> getAllocatedSize()
const override {
13486 assert(isValidState() &&
"the AA is invalid");
13487 return AssumedAllocatedSize;
13490 std::optional<TypeSize> findInitialAllocationSize(Instruction *
I,
13491 const DataLayout &
DL) {
13494 switch (
I->getOpcode()) {
13495 case Instruction::Alloca: {
13500 return std::nullopt;
13506 const IRPosition &IRP = getIRPosition();
13511 return indicatePessimisticFixpoint();
13513 bool IsKnownNoCapture;
13515 A,
this, IRP, DepClassTy::OPTIONAL, IsKnownNoCapture))
13516 return indicatePessimisticFixpoint();
13518 const AAPointerInfo *PI =
13519 A.getOrCreateAAFor<AAPointerInfo>(IRP, *
this, DepClassTy::REQUIRED);
13522 return indicatePessimisticFixpoint();
13525 return indicatePessimisticFixpoint();
13527 const DataLayout &
DL =
A.getDataLayout();
13528 const auto AllocationSize = findInitialAllocationSize(
I,
DL);
13531 if (!AllocationSize)
13532 return indicatePessimisticFixpoint();
13536 if (*AllocationSize == 0)
13537 return indicatePessimisticFixpoint();
13543 return indicatePessimisticFixpoint();
13545 if (BinSize == 0) {
13546 auto NewAllocationSize = std::make_optional<TypeSize>(0,
false);
13547 if (!changeAllocationSize(NewAllocationSize))
13548 return ChangeStatus::UNCHANGED;
13549 return ChangeStatus::CHANGED;
13553 const auto &It = PI->
begin();
13556 if (It->first.Offset != 0)
13557 return indicatePessimisticFixpoint();
13559 uint64_t SizeOfBin = It->first.Offset + It->first.Size;
13561 if (SizeOfBin >= *AllocationSize)
13562 return indicatePessimisticFixpoint();
13564 auto NewAllocationSize = std::make_optional<TypeSize>(SizeOfBin * 8,
false);
13566 if (!changeAllocationSize(NewAllocationSize))
13567 return ChangeStatus::UNCHANGED;
13569 return ChangeStatus::CHANGED;
13575 assert(isValidState() &&
13576 "Manifest should only be called if the state is valid.");
13580 auto FixedAllocatedSizeInBits = getAllocatedSize()->getFixedValue();
13582 unsigned long NumBytesToAllocate = (FixedAllocatedSizeInBits + 7) / 8;
13584 switch (
I->getOpcode()) {
13586 case Instruction::Alloca: {
13590 Type *CharType = Type::getInt8Ty(
I->getContext());
13592 auto *NumBytesToValue =
13593 ConstantInt::get(
I->getContext(), APInt(32, NumBytesToAllocate));
13596 insertPt = std::next(insertPt);
13597 AllocaInst *NewAllocaInst =
13602 return ChangeStatus::CHANGED;
13610 return ChangeStatus::UNCHANGED;
13614 const std::string getAsStr(Attributor *
A)
const override {
13615 if (!isValidState())
13616 return "allocationinfo(<invalid>)";
13617 return "allocationinfo(" +
13618 (AssumedAllocatedSize == HasNoAllocationSize
13620 : std::to_string(AssumedAllocatedSize->getFixedValue())) +
13625 std::optional<TypeSize> AssumedAllocatedSize = HasNoAllocationSize;
13629 bool changeAllocationSize(std::optional<TypeSize>
Size) {
13630 if (AssumedAllocatedSize == HasNoAllocationSize ||
13631 AssumedAllocatedSize !=
Size) {
13632 AssumedAllocatedSize =
Size;
13639struct AAAllocationInfoFloating : AAAllocationInfoImpl {
13640 AAAllocationInfoFloating(
const IRPosition &IRP, Attributor &
A)
13641 : AAAllocationInfoImpl(IRP,
A) {}
13643 void trackStatistics()
const override {
13648struct AAAllocationInfoReturned : AAAllocationInfoImpl {
13649 AAAllocationInfoReturned(
const IRPosition &IRP, Attributor &
A)
13650 : AAAllocationInfoImpl(IRP,
A) {}
13656 (void)indicatePessimisticFixpoint();
13659 void trackStatistics()
const override {
13664struct AAAllocationInfoCallSiteReturned : AAAllocationInfoImpl {
13665 AAAllocationInfoCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
13666 : AAAllocationInfoImpl(IRP,
A) {}
13668 void trackStatistics()
const override {
13673struct AAAllocationInfoArgument : AAAllocationInfoImpl {
13674 AAAllocationInfoArgument(
const IRPosition &IRP, Attributor &
A)
13675 : AAAllocationInfoImpl(IRP,
A) {}
13677 void trackStatistics()
const override {
13682struct AAAllocationInfoCallSiteArgument : AAAllocationInfoImpl {
13683 AAAllocationInfoCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
13684 : AAAllocationInfoImpl(IRP,
A) {}
13689 (void)indicatePessimisticFixpoint();
13692 void trackStatistics()
const override {
13741#define SWITCH_PK_INV(CLASS, PK, POS_NAME) \
13742 case IRPosition::PK: \
13743 llvm_unreachable("Cannot create " #CLASS " for a " POS_NAME " position!");
13745#define SWITCH_PK_CREATE(CLASS, IRP, PK, SUFFIX) \
13746 case IRPosition::PK: \
13747 AA = new (A.Allocator) CLASS##SUFFIX(IRP, A); \
13751#define CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13752 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13753 CLASS *AA = nullptr; \
13754 switch (IRP.getPositionKind()) { \
13755 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13756 SWITCH_PK_INV(CLASS, IRP_FLOAT, "floating") \
13757 SWITCH_PK_INV(CLASS, IRP_ARGUMENT, "argument") \
13758 SWITCH_PK_INV(CLASS, IRP_RETURNED, "returned") \
13759 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_RETURNED, "call site returned") \
13760 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_ARGUMENT, "call site argument") \
13761 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
13762 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE, CallSite) \
13767#define CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13768 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13769 CLASS *AA = nullptr; \
13770 switch (IRP.getPositionKind()) { \
13771 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13772 SWITCH_PK_INV(CLASS, IRP_FUNCTION, "function") \
13773 SWITCH_PK_INV(CLASS, IRP_CALL_SITE, "call site") \
13774 SWITCH_PK_CREATE(CLASS, IRP, IRP_FLOAT, Floating) \
13775 SWITCH_PK_CREATE(CLASS, IRP, IRP_ARGUMENT, Argument) \
13776 SWITCH_PK_CREATE(CLASS, IRP, IRP_RETURNED, Returned) \
13777 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_RETURNED, CallSiteReturned) \
13778 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_ARGUMENT, CallSiteArgument) \
13783#define CREATE_ABSTRACT_ATTRIBUTE_FOR_ONE_POSITION(POS, SUFFIX, CLASS) \
13784 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13785 CLASS *AA = nullptr; \
13786 switch (IRP.getPositionKind()) { \
13787 SWITCH_PK_CREATE(CLASS, IRP, POS, SUFFIX) \
13789 llvm_unreachable("Cannot create " #CLASS " for position otherthan " #POS \
13795#define CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13796 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13797 CLASS *AA = nullptr; \
13798 switch (IRP.getPositionKind()) { \
13799 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13800 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
13801 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE, CallSite) \
13802 SWITCH_PK_CREATE(CLASS, IRP, IRP_FLOAT, Floating) \
13803 SWITCH_PK_CREATE(CLASS, IRP, IRP_ARGUMENT, Argument) \
13804 SWITCH_PK_CREATE(CLASS, IRP, IRP_RETURNED, Returned) \
13805 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_RETURNED, CallSiteReturned) \
13806 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_ARGUMENT, CallSiteArgument) \
13811#define CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13812 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13813 CLASS *AA = nullptr; \
13814 switch (IRP.getPositionKind()) { \
13815 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13816 SWITCH_PK_INV(CLASS, IRP_ARGUMENT, "argument") \
13817 SWITCH_PK_INV(CLASS, IRP_FLOAT, "floating") \
13818 SWITCH_PK_INV(CLASS, IRP_RETURNED, "returned") \
13819 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_RETURNED, "call site returned") \
13820 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_ARGUMENT, "call site argument") \
13821 SWITCH_PK_INV(CLASS, IRP_CALL_SITE, "call site") \
13822 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
13827#define CREATE_NON_RET_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13828 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13829 CLASS *AA = nullptr; \
13830 switch (IRP.getPositionKind()) { \
13831 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13832 SWITCH_PK_INV(CLASS, IRP_RETURNED, "returned") \
13833 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
13834 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE, CallSite) \
13835 SWITCH_PK_CREATE(CLASS, IRP, IRP_FLOAT, Floating) \
13836 SWITCH_PK_CREATE(CLASS, IRP, IRP_ARGUMENT, Argument) \
13837 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_RETURNED, CallSiteReturned) \
13838 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_ARGUMENT, CallSiteArgument) \
13890#undef CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION
13891#undef CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION
13892#undef CREATE_NON_RET_ABSTRACT_ATTRIBUTE_FOR_POSITION
13893#undef CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION
13894#undef CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION
13895#undef CREATE_ABSTRACT_ATTRIBUTE_FOR_ONE_POSITION
13896#undef SWITCH_PK_CREATE
13897#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)
#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)
static bool mayBeInCycle(const CycleInfo *CI, const Instruction *I, bool HeaderOnly, CycleRef *CPtr=nullptr)
#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< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static bool isReachableImpl(SmallVectorImpl< BasicBlock * > &Worklist, const StopSetT &StopSet, const SmallPtrSetImpl< BasicBlock * > *ExclusionSet, const DominatorTree *DT, const LoopInfo *LI, const CycleInfo *CI)
This file contains the declarations for the subclasses of Constant, which represent the different fla...
This file declares an analysis pass that computes CycleInfo for LLVM IR, specialized from GenericCycl...
static uint64_t align(uint64_t Size)
DXIL Forward Handle Accesses
This file defines DenseMapInfo traits for DenseMap.
This file defines the DenseMap class.
static Value * getCondition(Instruction *I)
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 ...
Func getContext().diagnose(DiagnosticInfoUnsupported(Func
std::pair< BasicBlock *, BasicBlock * > Edge
BaseType
A given derived pointer can have multiple base pointers through phi/selects.
This file defines generic set operations that may be used on set's of different types,...
This file implements a set that has insertion order iteration characteristics.
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static SymbolRef::Type getType(const Symbol *Sym)
static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, const llvm::StringTable &StandardNames, VectorLibrary VecLib)
Initialize the set of available library functions based on the specified target triple.
static unsigned getBitWidth(Type *Ty, const DataLayout &DL)
Returns the bitwidth of the given scalar or pointer type.
static unsigned getSize(unsigned Kind)
LLVM_ABI AACallGraphNode * operator*() const
bool isNoAlias(const MemoryLocation &LocA, const MemoryLocation &LocB)
A trivial helper function to check to see if the specified pointers are no-alias.
Class for arbitrary precision integers.
int64_t getSExtValue() const
Get sign extended value.
CallBase * getInstruction() const
Return the underlying instruction.
bool isCallbackCall() const
Return true if this ACS represents a callback call.
bool isDirectCall() const
Return true if this ACS represents a direct call.
static LLVM_ABI void getCallbackUses(const CallBase &CB, SmallVectorImpl< const Use * > &CallbackUses)
Add operand uses of CB that represent callback uses into CallbackUses.
int getCallArgOperandNo(Argument &Arg) const
Return the operand index of the underlying instruction associated with Arg.
Align getAlign() const
Return the alignment of the memory that is being allocated by the instruction.
unsigned getAddressSpace() const
Return the address space for the allocation.
LLVM_ABI std::optional< TypeSize > getAllocationSize(const DataLayout &DL) const
Get allocation size in bytes.
This class represents an incoming formal argument to a Function.
LLVM_ABI bool hasNoAliasAttr() const
Return true if this argument has the noalias attribute.
LLVM_ABI bool onlyReadsMemory() const
Return true if this argument has the readonly or readnone attribute.
LLVM_ABI bool hasPointeeInMemoryValueAttr() const
Return true if this argument has the byval, sret, inalloca, preallocated, or byref attribute.
LLVM_ABI bool hasReturnedAttr() const
Return true if this argument has the returned attribute.
LLVM_ABI bool hasByValAttr() const
Return true if this argument has the byval attribute.
const Function * getParent() const
unsigned getArgNo() const
Return the index of this formal argument in its containing function.
A function analysis which provides an AssumptionCache.
A cache of @llvm.assume calls within a function.
Functions, function parameters, and return types can have attributes to indicate how they should be t...
static LLVM_ABI Attribute get(LLVMContext &Context, AttrKind Kind, uint64_t Val=0)
Return a uniquified Attribute object.
LLVM_ABI FPClassTest getNoFPClass() const
Return the FPClassTest for nofpclass.
LLVM_ABI Attribute::AttrKind getKindAsEnum() const
Return the attribute's kind as an enum (Attribute::AttrKind).
LLVM_ABI MemoryEffects getMemoryEffects() const
Returns memory effects.
AttrKind
This enumeration lists the attributes that can be associated with parameters, function results,...
static LLVM_ABI Attribute getWithCaptureInfo(LLVMContext &Context, CaptureInfo CI)
static bool isEnumAttrKind(AttrKind Kind)
bool isValid() const
Return true if the attribute is any kind of attribute.
LLVM_ABI CaptureInfo getCaptureInfo() const
Returns information from captures attribute.
LLVM Basic Block Representation.
LLVM_ABI const_iterator getFirstInsertionPt() const
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
const Function * getParent() const
Return the enclosing method, or null if none.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
const Instruction & front() const
InstListType::iterator iterator
Instruction iterators...
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
BinaryOps getOpcode() const
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
LLVM_ABI bool isMustTailCall() const
Tests if this call site must be tail call optimized.
LLVM_ABI bool isIndirectCall() const
Return true if the callsite is an indirect call.
bool isCallee(Value::const_user_iterator UI) const
Determine whether the passed iterator points to the callee operand's Use.
Value * getCalledOperand() const
const Use & getCalledOperandUse() const
Attribute getFnAttr(StringRef Kind) const
Get the attribute of a given kind for the function.
const Use & getArgOperandUse(unsigned i) const
Wrappers for getting the Use of a call argument.
LLVM_ABI std::optional< ConstantRange > getRange() const
If this return value has a range attribute, return the value range of the argument.
Value * getArgOperand(unsigned i) const
bool isBundleOperand(unsigned Idx) const
Return true if the operand at index Idx is a bundle operand.
bool isConvergent() const
Determine if the invoke is convergent.
FunctionType * getFunctionType() const
LLVM_ABI Intrinsic::ID getIntrinsicID() const
Returns the intrinsic ID of the intrinsic called or Intrinsic::not_intrinsic if the called function i...
iterator_range< User::op_iterator > args()
Iteration adapter for range-for loops.
unsigned getArgOperandNo(const Use *U) const
Given a use for a arg operand, get the arg operand number that corresponds to it.
unsigned arg_size() const
bool isArgOperand(const Use *U) const
LLVM_ABI Function * getCaller()
Helper to get the caller (the parent function).
static CallInst * Create(FunctionType *Ty, Value *F, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
static CaptureInfo none()
Create CaptureInfo that does not capture any components of the pointer.
Instruction::CastOps getOpcode() const
Return the opcode of this CastInst.
LLVM_ABI bool isIntegerCast() const
There are several places where we need to know if a cast instruction only deals with integer source a...
Type * getDestTy() const
Return the destination type, as a convenience.
bool isEquality() const
Determine if this is an equals/not equals predicate.
bool isFalseWhenEqual() const
This is just a convenience.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
bool isTrueWhenEqual() const
This is just a convenience.
Predicate getPredicate() const
Return the predicate for this instruction.
Conditional Branch instruction.
Value * getCondition() const
BasicBlock * getSuccessor(unsigned i) const
static LLVM_ABI Constant * getExtractElement(Constant *Vec, Constant *Idx, Type *OnlyIfReducedTy=nullptr)
static LLVM_ABI ConstantInt * getTrue(LLVMContext &Context)
This class represents a range of values.
const APInt & getLower() const
Return the lower value for this range.
LLVM_ABI bool isFullSet() const
Return true if this set contains all of the elements possible for this data-type.
LLVM_ABI bool isEmptySet() const
Return true if this set contains no members.
bool isSingleElement() const
Return true if this set contains exactly one member.
static LLVM_ABI ConstantRange makeAllowedICmpRegion(CmpInst::Predicate Pred, const ConstantRange &Other)
Produce the smallest range such that all values that may satisfy the given predicate with any value c...
const APInt & getUpper() const
Return the upper value for this range.
LLVM_ABI bool contains(const APInt &Val) const
Return true if the specified value is in the set.
Opaque handle to a cycle within a GenericCycleInfo that wraps the cycle's preorder index.
A parsed version of the target data layout string in and methods for querying it.
unsigned getProgramAddressSpace() const
bool contains(const_arg_type_t< KeyT > Val) const
Return true if the specified key is in the map, false otherwise.
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
iterator find(const_arg_type_t< KeyT > Val)
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
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.
BlockT * getHeader(CycleRef C) const
CycleRef getCycle(const BlockT *Block) const
Find the innermost cycle containing 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.
iterator_range< user_iterator > users()
LLVM_ABI void setMetadata(unsigned KindID, MDNode *Node)
Set the metadata of the specified kind to the specified node.
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
This is an important class for using LLVM in a threaded context.
LLVM_ABI ConstantRange getConstantRange(Value *V, Instruction *CtxI, 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 SCEVUse 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...
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Used to lazily calculate structure layout information for a target machine, based on the DataLayout s...
TypeSize getElementOffset(unsigned Idx) const
TypeSize getElementOffsetInBits(unsigned Idx) const
Class to represent struct types.
unsigned getNumElements() const
Random access to the elements.
Type * getElementType(unsigned N) const
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM_ABI unsigned getIntegerBitWidth() const
bool isPointerTy() const
True if this is an instance of PointerType.
LLVM_ABI unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
bool isPtrOrPtrVectorTy() const
Return true if this is a pointer type or a vector of pointer types.
bool isIntegerTy() const
True if this is an instance of IntegerType.
bool isVoidTy() const
Return true if this is 'void'.
static UncondBrInst * Create(BasicBlock *Target, InsertPosition InsertBefore=nullptr)
BasicBlock * getSuccessor(unsigned i=0) const
static LLVM_ABI UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
A Use represents the edge between a Value definition and its users.
User * getUser() const
Returns the User that contains this Use.
const Use & getOperandUse(unsigned i) const
LLVM_ABI bool isDroppable() const
A droppable user is a user for which uses can be dropped without affecting correctness and should be ...
LLVM_ABI bool replaceUsesOfWith(Value *From, Value *To)
Replace uses of one Value with another.
Value * getOperand(unsigned i) const
unsigned getNumOperands() const
ValueT lookup(const KeyT &Val) const
lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
static constexpr uint64_t MaximumAlignment
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
LLVMContext & getContext() const
All values hold a context through their type.
LLVM_ABI const Value * stripAndAccumulateConstantOffsets(const DataLayout &DL, APInt &Offset, bool AllowNonInbounds, bool AllowInvariantGroup=false, function_ref< bool(Value &Value, APInt &Offset)> ExternalAnalysis=nullptr, bool LookThroughIntToPtr=false) const
Accumulate the constant offset this value has compared to a base pointer.
static constexpr unsigned MaxAlignmentExponent
The maximum alignment for instructions.
iterator_range< use_iterator > uses()
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
std::pair< iterator, bool > insert(const ValueT &V)
constexpr ScalarTy getFixedValue() const
constexpr bool isScalable() const
Returns whether the quantity is scaled by a runtime quantity (vscale).
const ParentTy * getParent() const
self_iterator getIterator()
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
SetVector< Function * >::iterator I
This class implements an extremely fast bulk output stream that can only output to a stream.
A raw_ostream that writes to an std::string.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Abstract Attribute helper functions.
LLVM_ABI bool isAssumedReadNone(Attributor &A, const IRPosition &IRP, const AbstractAttribute &QueryingAA, bool &IsKnown)
Return true if IRP is readnone.
LLVM_ABI bool isAssumedReadOnly(Attributor &A, const IRPosition &IRP, const AbstractAttribute &QueryingAA, bool &IsKnown)
Return true if IRP is readonly.
raw_ostream & operator<<(raw_ostream &OS, const RangeTy &R)
LLVM_ABI std::optional< Value * > combineOptionalValuesInAAValueLatice(const std::optional< Value * > &A, const std::optional< Value * > &B, Type *Ty)
Return the combination of A and B such that the result is a possible value of both.
LLVM_ABI bool isValidAtPosition(const ValueAndContext &VAC, InformationCache &InfoCache)
Return true if the value of VAC is a valid at the position of VAC, that is a constant,...
LLVM_ABI bool isAssumedThreadLocalObject(Attributor &A, Value &Obj, const AbstractAttribute &QueryingAA)
Return true if Obj is assumed to be a thread local object.
LLVM_ABI bool isGPUConstantAddressSpace(const Module &M, unsigned AS)
Check if the given address space AS corresponds to a GPU constant address space for the target triple...
LLVM_ABI bool isDynamicallyUnique(Attributor &A, const AbstractAttribute &QueryingAA, const Value &V, bool ForAnalysisOnly=true)
Return true if V is dynamically unique, that is, there are no two "instances" of V at runtime with di...
LLVM_ABI bool getPotentialCopiesOfStoredValue(Attributor &A, StoreInst &SI, SmallSetVector< Value *, 4 > &PotentialCopies, const AbstractAttribute &QueryingAA, bool &UsedAssumedInformation, bool OnlyExact=false)
Collect all potential values of the one stored by SI into PotentialCopies.
LLVM_ABI bool isGPUSharedAddressSpace(const Module &M, unsigned AS)
Check if the given address space AS corresponds to a GPU shared address space for the target triple i...
LLVM_ABI bool isGPULocalAddressSpace(const Module &M, unsigned AS)
Check if the given address space AS corresponds to a GPU local/private address space for the target t...
SmallPtrSet< Instruction *, 4 > InstExclusionSetTy
LLVM_ABI bool isGPU(const Module &M)
Return true iff M target a GPU (and we can use GPU AS reasoning).
ValueScope
Flags to distinguish intra-procedural queries from potentially inter-procedural queries.
LLVM_ABI bool isValidInScope(const Value &V, const Function *Scope)
Return true if V is a valid value in Scope, that is a constant or an instruction/argument of Scope.
LLVM_ABI bool isPotentiallyReachable(Attributor &A, const Instruction &FromI, const Instruction &ToI, const AbstractAttribute &QueryingAA, const AA::InstExclusionSetTy *ExclusionSet=nullptr, std::function< bool(const Function &F)> GoBackwardsCB=nullptr)
Return true if ToI is potentially reachable from FromI without running into any instruction in Exclus...
LLVM_ABI bool isNoSyncInst(Attributor &A, const Instruction &I, const AbstractAttribute &QueryingAA)
Return true if I is a nosync instruction.
bool hasAssumedIRAttr(Attributor &A, const AbstractAttribute *QueryingAA, const IRPosition &IRP, DepClassTy DepClass, bool &IsKnown, bool IgnoreSubsumingPositions=false, const AAType **AAPtr=nullptr)
Helper to avoid creating an AA for IR Attributes that might already be set.
LLVM_ABI bool getPotentiallyLoadedValues(Attributor &A, LoadInst &LI, SmallSetVector< Value *, 4 > &PotentialValues, SmallSetVector< Instruction *, 4 > &PotentialValueOrigins, const AbstractAttribute &QueryingAA, bool &UsedAssumedInformation, bool OnlyExact=false)
Collect all potential values LI could read into PotentialValues.
LLVM_ABI Value * getWithType(Value &V, Type &Ty)
Try to convert V to type Ty without introducing new instructions.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char Attrs[]
Key for Kernel::Metadata::mAttrs.
@ 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
DiagnosticInfoOptimizationBase::Argument NV
NodeAddr< UseNode * > Use
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)
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.
RelativeUniformCounterPtr Values
@ Known
Known to have no common set bits.
@ 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.
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.
@ Load
The value being inserted comes from a load (InsertElement only).
@ Store
The extracted value is stored (ExtractElement only).
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.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
LLVM_ABI Value * simplifyInstruction(Instruction *I, const SimplifyQuery &Q)
See if we can compute a simplified version of this instruction.
auto dyn_cast_or_null(const Y &Val)
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
PotentialValuesState< std::pair< AA::ValueAndContext, AA::ValueScope > > PotentialLLVMValuesState
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI bool NullPointerIsDefined(const Function *F, unsigned AS=0)
Check whether null pointer dereferencing is considered undefined behavior for a given function or an ...
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool isPointerTy(const Type *T)
IRBuilder(LLVMContext &, FolderTy, InserterTy) -> IRBuilder< FolderTy, InserterTy >
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.
LLVM_ABI const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth, bool MustPreserveProvenance=false)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
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.
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.
LLVM_ABI bool isIntrinsicReturningPointerAliasingArgumentWithoutCapturing(const CallBase *Call, bool MustPreserveOffset, bool MustPreserveProvenance=false)
launder.invariant.group and similar intrinsics return a pointer that aliases their argument,...
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.
bool capturesNothing(CaptureComponents CC)
LLVM_ABI bool isIdentifiedObject(const Value *V)
Return true if this pointer refers to a distinct and identifiable object.
bool capturesAnyProvenance(CaptureComponents CC)
constexpr StringRef AssumptionAttrKey
The key we use for assumption attributes.
constexpr bool isCallableCC(CallingConv::ID CC)
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
A type to track pointer/struct usage and accesses for AAPointerInfo.
bool forallInterferingAccesses(AA::RangeTy Range, F CB) const
See AAPointerInfo::forallInterferingAccesses.
AAPointerInfo::const_bin_iterator end() const
ChangeStatus addAccess(Attributor &A, const AAPointerInfo::RangeList &Ranges, Instruction &I, std::optional< Value * > Content, AAPointerInfo::AccessKind Kind, Type *Ty, Instruction *RemoteI=nullptr)
Add a new Access to the state at offset Offset and with size Size.
DenseMap< const Instruction *, SmallVector< unsigned > > RemoteIMap
AAPointerInfo::const_bin_iterator begin() const
AAPointerInfo::OffsetInfo ReturnedOffsets
Flag to determine if the underlying pointer is reaching a return statement in the associated function...
State & operator=(State &&R)
State(State &&SIS)=default
const AAPointerInfo::Access & getAccess(unsigned Index) const
SmallVector< AAPointerInfo::Access > AccessList
bool isAtFixpoint() const override
See AbstractState::isAtFixpoint().
bool forallInterferingAccesses(Instruction &I, F CB, AA::RangeTy &Range) const
See AAPointerInfo::forallInterferingAccesses.
static State getWorstState(const State &SIS)
Return the worst possible representable state.
int64_t numOffsetBins() const
AAPointerInfo::OffsetBinsTy OffsetBins
ChangeStatus indicateOptimisticFixpoint() override
See AbstractState::indicateOptimisticFixpoint().
State & operator=(const State &R)
ChangeStatus indicatePessimisticFixpoint() override
See AbstractState::indicatePessimisticFixpoint().
const State & getAssumed() const
static State getBestState(const State &SIS)
Return the best possible representable state.
bool isValidState() const override
See AbstractState::isValidState().
----------------—AAIntraFnReachability Attribute-----------------------—
ReachabilityQueryInfo(const ReachabilityQueryInfo &RQI)
unsigned Hash
Precomputed hash for this RQI.
const Instruction * From
Start here,.
Reachable Result
and remember if it worked:
ReachabilityQueryInfo(const Instruction *From, const ToTy *To)
ReachabilityQueryInfo(Attributor &A, const Instruction &From, const ToTy &To, const AA::InstExclusionSetTy *ES, bool MakeUnique)
Constructor replacement to ensure unique and stable sets are used for the cache.
const ToTy * To
reach this place,
const AA::InstExclusionSetTy * ExclusionSet
without going through any of these instructions,
unsigned computeHashValue() const
An abstract interface for address space information.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for all align attributes.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
Align getKnownAlign() const
Return known alignment.
static LLVM_ABI const char ID
An abstract attribute for getting assumption information.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract state for querying live call edges.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract Attribute for specializing "dynamic" components of denormal_fpenv to a known denormal mod...
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for all dereferenceable attribute.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for llvm::GlobalValue information interference.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for indirect call information interference.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface to track if a value leaves it's defining function instance.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract Attribute for computing reachability between functions.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
bool canReach(Attributor &A, const Function &Fn) const
If the function represented by this possition can reach Fn.
virtual bool instructionCanReach(Attributor &A, const Instruction &Inst, const Function &Fn, const AA::InstExclusionSetTy *ExclusionSet=nullptr) const =0
Can Inst reach Fn.
An abstract interface to determine reachability of point A to B.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for identifying pointers from which loads can be marked invariant.
static LLVM_ABI const char ID
Unique ID (due to the unique address).
An abstract interface for liveness abstract attribute.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for memory access kind related attributes (readnone/readonly/writeonly).
bool isAssumedReadOnly() const
Return true if we assume that the underlying value is not accessed (=written) in its respective scope...
bool isKnownReadNone() const
Return true if we know that the underlying value is not read or accessed in its respective scope.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
bool isAssumedReadNone() const
Return true if we assume that the underlying value is not read or accessed in its respective scope.
An abstract interface for all memory location attributes (readnone/argmemonly/inaccessiblememonly/ina...
static LLVM_ABI std::string getMemoryLocationsAsStr(MemoryLocationsKind MLK)
Return the locations encoded by MLK as a readable string.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
StateType::base_t MemoryLocationsKind
An abstract interface for all nonnull attributes.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for potential address space information.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for all noalias attributes.
static LLVM_ABI bool isImpliedByIR(Attributor &A, const IRPosition &IRP, Attribute::AttrKind ImpliedAttributeKind, bool IgnoreSubsumingPositions=false)
See IRAttribute::isImpliedByIR.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for all nocapture attributes.
@ NO_CAPTURE_MAYBE_RETURNED
If we do not capture the value in memory or through integers we can only communicate it back as a der...
@ NO_CAPTURE
If we do not capture the value in memory, through integers, or as a derived pointer we know it is not...
static LLVM_ABI const char ID
Unique ID (due to the unique address)
bool isAssumedNoCaptureMaybeReturned() const
Return true if we assume that the underlying value is not captured in its respective scope but we all...
static LLVM_ABI bool isImpliedByIR(Attributor &A, const IRPosition &IRP, Attribute::AttrKind ImpliedAttributeKind, bool IgnoreSubsumingPositions=false)
See IRAttribute::isImpliedByIR.
static LLVM_ABI void determineFunctionCaptureCapabilities(const IRPosition &IRP, const Function &F, BitIntegerState &State)
Update State according to the capture capabilities of F for position IRP.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An AbstractAttribute for nofree.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract attribute for norecurse.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An AbstractAttribute for noreturn.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
static LLVM_ABI const char ID
Unique ID (due to the unique address)
static LLVM_ABI bool isAlignedBarrier(const CallBase &CB, bool ExecutedAligned)
Helper function to determine if CB is an aligned (GPU) barrier.
static LLVM_ABI bool isNonRelaxedAtomic(const Instruction *I)
Helper function used to determine whether an instruction is non-relaxed atomic.
An abstract interface for all noundef attributes.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
static LLVM_ABI bool isImpliedByIR(Attributor &A, const IRPosition &IRP, Attribute::AttrKind ImpliedAttributeKind, bool IgnoreSubsumingPositions=false)
See IRAttribute::isImpliedByIR.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract Attribute for determining the necessity of the convergent attribute.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for all nonnull attributes.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
static LLVM_ABI bool isImpliedByIR(Attributor &A, const IRPosition &IRP, Attribute::AttrKind ImpliedAttributeKind, bool IgnoreSubsumingPositions=false)
See AbstractAttribute::isImpliedByIR(...).
A helper containing a list of offsets computed for a Use.
A container for a list of ranges.
static void set_difference(const RangeList &L, const RangeList &R, RangeList &D)
Copy ranges from L that are not in R, into D.
An abstract interface for struct information.
virtual bool reachesReturn() const =0
OffsetBinsTy::const_iterator const_bin_iterator
virtual const_bin_iterator begin() const =0
DenseMap< AA::RangeTy, SmallSet< unsigned, 4 > > OffsetBinsTy
static LLVM_ABI const char ID
Unique ID (due to the unique address)
virtual int64_t numOffsetBins() const =0
An abstract interface for potential values analysis.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
static LLVM_ABI const char ID
Unique ID (due to the unique address)
static LLVM_ABI Value * getSingleValue(Attributor &A, const AbstractAttribute &AA, const IRPosition &IRP, SmallVectorImpl< AA::ValueAndContext > &Values)
Extract the single value in Values if any.
An abstract interface for privatizability.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract attribute for undefined behavior.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract attribute for getting all assumption underlying objects.
virtual bool forallUnderlyingObjects(function_ref< bool(Value &)> Pred, AA::ValueScope Scope=AA::Interprocedural) const =0
Check Pred on all underlying objects in Scope collected so far.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for range value analysis.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for value simplify abstract attribute.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract attribute for willreturn.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
Helper to represent an access offset and size, with logic to deal with uncertainty and check for over...
static constexpr int64_t Unknown
static RangeTy getUnknown()
const Instruction * getCtxI() const
Base struct for all "concrete attribute" deductions.
void print(raw_ostream &OS) const
Helper functions, for debug purposes only.
virtual StateType & getState()=0
Return the internal abstract state for inspection.
An interface to query the internal state of an abstract attribute.
virtual bool isAtFixpoint() const =0
Return if this abstract state is fixed, thus does not need to be updated if information changes as it...
virtual bool isValidState() const =0
Return if this abstract state is in a valid state.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
std::function< void( const ArgumentReplacementInfo &, Function &, Function::arg_iterator)> CalleeRepairCBTy
Callee repair callback type.
const Argument & getReplacedArg() const
std::function< void(const ArgumentReplacementInfo &, AbstractCallSite, SmallVectorImpl< Value * > &)> ACSRepairCBTy
Abstract call site (ACS) repair callback type.
The fixpoint analysis framework that orchestrates the attribute deduction.
std::function< std::optional< Value * >( const IRPosition &, const AbstractAttribute *, bool &)> SimplifictionCallbackTy
Register CB as a simplification callback.
Specialization of the integer state for a bit-wise encoding.
BitIntegerState & addKnownBits(base_t Bits)
Add the bits in BitsEncoding to the "known bits".
Simple wrapper for a single bit (boolean) state.
static constexpr DenormalFPEnv getDefault()
static unsigned getHashValue(const Access &A)
AAPointerInfo::Access Access
static bool isEqual(const Access &LHS, const Access &RHS)
static bool isEqual(const AA::RangeTy &A, const AA::RangeTy B)
static unsigned getHashValue(const AA::RangeTy &Range)
DenseMapInfo< std::pair< const Instruction *, const ToTy * > > PairDMI
static bool isEqual(const ReachabilityQueryInfo< ToTy > *LHS, const ReachabilityQueryInfo< ToTy > *RHS)
DenseMapInfo< const AA::InstExclusionSetTy * > InstSetDMI
static unsigned getHashValue(const ReachabilityQueryInfo< ToTy > *RQI)
An information struct used to provide DenseMap with the various necessary components for a given valu...
State for dereferenceable attribute.
IncIntegerState DerefBytesState
State representing for dereferenceable bytes.
ChangeStatus manifest(Attributor &A) override
See AbstractAttribute::manifest(...).
Helper to describe and deal with positions in the LLVM-IR.
Function * getAssociatedFunction() const
Return the associated function, if any.
static const IRPosition callsite_returned(const CallBase &CB)
Create a position describing the returned value of CB.
static const IRPosition returned(const Function &F, const CallBaseContext *CBContext=nullptr)
Create a position describing the returned value of F.
LLVM_ABI Argument * getAssociatedArgument() const
Return the associated argument, if any.
static const IRPosition value(const Value &V, const CallBaseContext *CBContext=nullptr)
Create a position describing the value of V.
int getCalleeArgNo() const
Return the callee argument number of the associated value if it is an argument or call site argument,...
static const IRPosition inst(const Instruction &I, const CallBaseContext *CBContext=nullptr)
Create a position describing the instruction I.
static const IRPosition callsite_argument(const CallBase &CB, unsigned ArgNo)
Create a position describing the argument of CB at position ArgNo.
@ IRP_ARGUMENT
An attribute for a function argument.
@ IRP_RETURNED
An attribute for the function return value.
@ IRP_CALL_SITE
An attribute for a call site (function scope).
@ IRP_CALL_SITE_RETURNED
An attribute for a call site return value.
@ IRP_FUNCTION
An attribute for a function (scope).
@ IRP_CALL_SITE_ARGUMENT
An attribute for a call site argument.
@ IRP_INVALID
An invalid position.
Instruction * getCtxI() const
Return the context instruction, if any.
static const IRPosition argument(const Argument &Arg, const CallBaseContext *CBContext=nullptr)
Create a position describing the argument Arg.
Type * getAssociatedType() const
Return the type this abstract attribute is associated with.
static const IRPosition function(const Function &F, const CallBaseContext *CBContext=nullptr)
Create a position describing the function scope of F.
const CallBaseContext * getCallBaseContext() const
Get the call base context from the position.
Value & getAssociatedValue() const
Return the value this abstract attribute is associated with.
Value & getAnchorValue() const
Return the value this abstract attribute is anchored with.
int getCallSiteArgNo() const
Return the call site argument number of the associated value if it is an argument or call site argume...
static const IRPosition function_scope(const IRPosition &IRP, const CallBaseContext *CBContext=nullptr)
Create a position with function scope matching the "context" of IRP.
Kind getPositionKind() const
Return the associated position kind.
bool isArgumentPosition() const
Return true if the position is an argument or call site argument.
static const IRPosition callsite_function(const CallBase &CB)
Create a position describing the function scope of CB.
Function * getAnchorScope() const
Return the Function surrounding the anchor value.
ConstantRange getKnown() const
Return the known state encoding.
ConstantRange getAssumed() const
Return the assumed state encoding.
base_t getAssumed() const
Return the assumed state encoding.
static constexpr base_t getWorstState()
Helper that allows to insert a new assumption string in the known assumption set by creating a (stati...
FPClassTest getKnownFPClasses() const
Floating-point classes the value could be one of.
A "must be executed context" for a given program point PP is the set of instructions,...
iterator & end()
Return an universal end iterator.
bool findInContextOf(const Instruction *I, const Instruction *PP)
Helper to look for I in the context of PP.
iterator & begin(const Instruction *PP)
Return an iterator to explore the context around PP.
bool checkForAllContext(const Instruction *PP, function_ref< bool(const Instruction *)> Pred)
}
static unsigned MaxPotentialValues
Helper to tie a abstract state implementation to an abstract attribute.
StateType & getState() override
See AbstractAttribute::getState(...).
bool isPassthrough() const
CaptureComponents ResultCC
Components captured by the return value of the user of this Use.
LLVM_ABI bool unionAssumed(std::optional< Value * > Other)
Merge Other into the currently assumed simplified value.
std::optional< Value * > SimplifiedAssociatedValue
An assumed simplified value.
Type * Ty
The type of the original value.