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())
4550 if (!
A.shouldUpdateAA<AAIsDead>(getIRPosition()))
4552 bool UsedAssumedInformation =
false;
4553 return A.checkForAllCallSites([](AbstractCallSite) {
return false; }, *
this,
4554 true, UsedAssumedInformation);
4558 const std::string getAsStr(Attributor *
A)
const override {
4559 return "Live[#BB " + std::to_string(AssumedLiveBlocks.size()) +
"/" +
4560 std::to_string(getAnchorScope()->
size()) +
"][#TBEP " +
4561 std::to_string(ToBeExploredFrom.size()) +
"][#KDE " +
4562 std::to_string(KnownDeadEnds.size()) +
"]";
4567 assert(getState().isValidState() &&
4568 "Attempted to manifest an invalid state!");
4573 if (AssumedLiveBlocks.empty()) {
4574 A.deleteAfterManifest(
F);
4575 return ChangeStatus::CHANGED;
4581 bool Invoke2CallAllowed = !mayCatchAsynchronousExceptions(
F);
4583 KnownDeadEnds.set_union(ToBeExploredFrom);
4584 for (
const Instruction *DeadEndI : KnownDeadEnds) {
4588 bool IsKnownNoReturn;
4596 A.registerInvokeWithDeadSuccessor(
const_cast<InvokeInst &
>(*
II));
4598 A.changeToUnreachableAfterManifest(
4599 const_cast<Instruction *
>(DeadEndI->getNextNode()));
4600 HasChanged = ChangeStatus::CHANGED;
4603 STATS_DECL(AAIsDead, BasicBlock,
"Number of dead basic blocks deleted.");
4604 for (BasicBlock &BB :
F)
4605 if (!AssumedLiveBlocks.count(&BB)) {
4606 A.deleteAfterManifest(BB);
4608 HasChanged = ChangeStatus::CHANGED;
4617 bool isEdgeDead(
const BasicBlock *From,
const BasicBlock *To)
const override {
4620 "Used AAIsDead of the wrong function");
4621 return isValidState() && !AssumedLiveEdges.count(std::make_pair(From, To));
4625 void trackStatistics()
const override {}
4628 bool isAssumedDead()
const override {
return false; }
4631 bool isKnownDead()
const override {
return false; }
4634 bool isAssumedDead(
const BasicBlock *BB)
const override {
4636 "BB must be in the same anchor scope function.");
4640 return !AssumedLiveBlocks.count(BB);
4644 bool isKnownDead(
const BasicBlock *BB)
const override {
4645 return getKnown() && isAssumedDead(BB);
4649 bool isAssumedDead(
const Instruction *
I)
const override {
4650 assert(
I->getParent()->getParent() == getAnchorScope() &&
4651 "Instruction must be in the same anchor scope function.");
4658 if (!AssumedLiveBlocks.count(
I->getParent()))
4664 if (KnownDeadEnds.count(PrevI) || ToBeExploredFrom.count(PrevI))
4672 bool isKnownDead(
const Instruction *
I)
const override {
4673 return getKnown() && isAssumedDead(
I);
4678 bool assumeLive(Attributor &
A,
const BasicBlock &BB) {
4679 if (!AssumedLiveBlocks.insert(&BB).second)
4682 if (!
A.isDuringDeduction())
4689 for (
const Instruction &
I : BB)
4692 if (
F->hasLocalLinkage()) {
4694 dbgs() <<
"[AAIsDead] Seeding live internal callee ";
4695 F->printAsOperand(
dbgs(),
false);
4697 BB.getParent()->printAsOperand(
dbgs(),
false);
4700 A.markLiveInternalFunction(*
F);
4707 SmallSetVector<const Instruction *, 8> ToBeExploredFrom;
4710 SmallSetVector<const Instruction *, 8> KnownDeadEnds;
4713 DenseSet<std::pair<const BasicBlock *, const BasicBlock *>> AssumedLiveEdges;
4716 DenseSet<const BasicBlock *> AssumedLiveBlocks;
4720identifyAliveSuccessors(Attributor &
A,
const CallBase &CB,
4721 AbstractAttribute &AA,
4722 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4725 bool IsKnownNoReturn;
4728 return !IsKnownNoReturn;
4737identifyAliveSuccessors(Attributor &
A,
const InvokeInst &
II,
4738 AbstractAttribute &AA,
4739 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4740 bool UsedAssumedInformation =
4746 if (AAIsDeadFunction::mayCatchAsynchronousExceptions(*
II.getFunction())) {
4747 AliveSuccessors.
push_back(&
II.getUnwindDest()->front());
4751 bool IsKnownNoUnwind;
4754 UsedAssumedInformation |= !IsKnownNoUnwind;
4756 AliveSuccessors.
push_back(&
II.getUnwindDest()->front());
4759 return UsedAssumedInformation;
4763identifyAliveSuccessors(Attributor &,
const UncondBrInst &BI,
4764 AbstractAttribute &,
4765 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4771identifyAliveSuccessors(Attributor &
A,
const CondBrInst &BI,
4772 AbstractAttribute &AA,
4773 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4774 bool UsedAssumedInformation =
false;
4775 std::optional<Constant *>
C =
4776 A.getAssumedConstant(*BI.
getCondition(), AA, UsedAssumedInformation);
4786 UsedAssumedInformation =
false;
4788 return UsedAssumedInformation;
4792identifyAliveSuccessors(Attributor &
A,
const SwitchInst &SI,
4793 AbstractAttribute &AA,
4794 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4795 bool UsedAssumedInformation =
false;
4799 UsedAssumedInformation)) {
4801 for (
const BasicBlock *SuccBB :
successors(
SI.getParent()))
4810 return UsedAssumedInformation;
4813 Type &Ty = *
SI.getCondition()->getType();
4814 SmallPtrSet<ConstantInt *, 8>
Constants;
4815 auto CheckForConstantInt = [&](
Value *
V) {
4824 return CheckForConstantInt(VAC.
getValue());
4826 for (
const BasicBlock *SuccBB :
successors(
SI.getParent()))
4828 return UsedAssumedInformation;
4831 unsigned MatchedCases = 0;
4832 for (
const auto &CaseIt :
SI.cases()) {
4833 if (
Constants.count(CaseIt.getCaseValue())) {
4835 AliveSuccessors.
push_back(&CaseIt.getCaseSuccessor()->front());
4842 AliveSuccessors.
push_back(&
SI.getDefaultDest()->front());
4843 return UsedAssumedInformation;
4849 if (AssumedLiveBlocks.empty()) {
4850 if (isAssumedDeadInternalFunction(
A))
4854 ToBeExploredFrom.insert(&
F->getEntryBlock().front());
4855 assumeLive(
A,
F->getEntryBlock());
4859 LLVM_DEBUG(
dbgs() <<
"[AAIsDead] Live [" << AssumedLiveBlocks.size() <<
"/"
4860 << getAnchorScope()->
size() <<
"] BBs and "
4861 << ToBeExploredFrom.size() <<
" exploration points and "
4862 << KnownDeadEnds.size() <<
" known dead ends\n");
4867 ToBeExploredFrom.end());
4868 decltype(ToBeExploredFrom) NewToBeExploredFrom;
4871 while (!Worklist.
empty()) {
4878 I =
I->getNextNode();
4880 AliveSuccessors.
clear();
4882 bool UsedAssumedInformation =
false;
4883 switch (
I->getOpcode()) {
4887 "Expected non-terminators to be handled already!");
4888 for (
const BasicBlock *SuccBB :
successors(
I->getParent()))
4891 case Instruction::Call:
4893 *
this, AliveSuccessors);
4895 case Instruction::Invoke:
4897 *
this, AliveSuccessors);
4899 case Instruction::UncondBr:
4900 UsedAssumedInformation = identifyAliveSuccessors(
4903 case Instruction::CondBr:
4905 *
this, AliveSuccessors);
4907 case Instruction::Switch:
4909 *
this, AliveSuccessors);
4913 if (UsedAssumedInformation) {
4914 NewToBeExploredFrom.insert(
I);
4915 }
else if (AliveSuccessors.
empty() ||
4916 (
I->isTerminator() &&
4917 AliveSuccessors.
size() <
I->getNumSuccessors())) {
4918 if (KnownDeadEnds.insert(
I))
4923 << AliveSuccessors.
size() <<
" UsedAssumedInformation: "
4924 << UsedAssumedInformation <<
"\n");
4926 for (
const Instruction *AliveSuccessor : AliveSuccessors) {
4927 if (!
I->isTerminator()) {
4928 assert(AliveSuccessors.size() == 1 &&
4929 "Non-terminator expected to have a single successor!");
4933 auto Edge = std::make_pair(
I->getParent(), AliveSuccessor->getParent());
4934 if (AssumedLiveEdges.insert(
Edge).second)
4936 if (assumeLive(
A, *AliveSuccessor->getParent()))
4943 if (NewToBeExploredFrom.size() != ToBeExploredFrom.size() ||
4944 llvm::any_of(NewToBeExploredFrom, [&](
const Instruction *
I) {
4945 return !ToBeExploredFrom.count(I);
4948 ToBeExploredFrom = std::move(NewToBeExploredFrom);
4957 if (ToBeExploredFrom.empty() &&
4958 getAnchorScope()->
size() == AssumedLiveBlocks.size() &&
4959 llvm::all_of(KnownDeadEnds, [](
const Instruction *DeadEndI) {
4960 return DeadEndI->isTerminator() && DeadEndI->getNumSuccessors() == 0;
4962 return indicatePessimisticFixpoint();
4967struct AAIsDeadCallSite final : AAIsDeadFunction {
4968 AAIsDeadCallSite(
const IRPosition &IRP, Attributor &
A)
4969 : AAIsDeadFunction(IRP,
A) {}
4978 "supported for call sites yet!");
4983 return indicatePessimisticFixpoint();
4987 void trackStatistics()
const override {}
4994struct AADereferenceableImpl : AADereferenceable {
4995 AADereferenceableImpl(
const IRPosition &IRP, Attributor &
A)
4996 : AADereferenceable(IRP,
A) {}
4997 using StateType = DerefState;
5001 Value &
V = *getAssociatedValue().stripPointerCasts();
5003 A.getAttrs(getIRPosition(),
5004 {Attribute::Dereferenceable, Attribute::DereferenceableOrNull},
5007 takeKnownDerefBytesMaximum(Attr.getValueAsInt());
5010 bool IsKnownNonNull;
5012 A,
this, getIRPosition(), DepClassTy::OPTIONAL, IsKnownNonNull);
5015 takeKnownDerefBytesMaximum(
V.getPointerDereferenceableBytes(
5016 A.getDataLayout(), CanBeNull,
nullptr));
5018 if (Instruction *CtxI = getCtxI())
5019 followUsesInMBEC(*
this,
A, getState(), *CtxI);
5024 StateType &getState()
override {
return *
this; }
5025 const StateType &getState()
const override {
return *
this; }
5029 void addAccessedBytesForUse(Attributor &
A,
const Use *U,
const Instruction *
I,
5030 DerefState &State) {
5031 const Value *UseV =
U->get();
5036 if (!Loc || Loc->Ptr != UseV || !Loc->Size.isPrecise() ||
I->isVolatile())
5041 Loc->Ptr,
Offset,
A.getDataLayout(),
true);
5042 if (
Base &&
Base == &getAssociatedValue())
5043 State.addAccessedBytes(
Offset, Loc->Size.getValue());
5047 bool followUseInMBEC(Attributor &
A,
const Use *U,
const Instruction *
I,
5048 AADereferenceable::StateType &State) {
5049 bool IsNonNull =
false;
5050 bool TrackUse =
false;
5051 int64_t DerefBytes = getKnownNonNullAndDerefBytesForUse(
5052 A, *
this, getAssociatedValue(), U,
I, IsNonNull, TrackUse);
5053 LLVM_DEBUG(
dbgs() <<
"[AADereferenceable] Deref bytes: " << DerefBytes
5054 <<
" for instruction " << *
I <<
"\n");
5056 addAccessedBytesForUse(
A, U,
I, State);
5057 State.takeKnownDerefBytesMaximum(DerefBytes);
5064 bool IsKnownNonNull;
5066 A,
this, getIRPosition(), DepClassTy::NONE, IsKnownNonNull);
5067 if (IsAssumedNonNull &&
5068 A.hasAttr(getIRPosition(), Attribute::DereferenceableOrNull)) {
5069 A.removeAttrs(getIRPosition(), {Attribute::DereferenceableOrNull});
5070 return ChangeStatus::CHANGED;
5075 void getDeducedAttributes(Attributor &
A, LLVMContext &Ctx,
5076 SmallVectorImpl<Attribute> &Attrs)
const override {
5078 bool IsKnownNonNull;
5080 A,
this, getIRPosition(), DepClassTy::NONE, IsKnownNonNull);
5081 if (IsAssumedNonNull)
5082 Attrs.emplace_back(Attribute::getWithDereferenceableBytes(
5083 Ctx, getAssumedDereferenceableBytes()));
5085 Attrs.emplace_back(Attribute::getWithDereferenceableOrNullBytes(
5086 Ctx, getAssumedDereferenceableBytes()));
5090 const std::string getAsStr(Attributor *
A)
const override {
5091 if (!getAssumedDereferenceableBytes())
5092 return "unknown-dereferenceable";
5093 bool IsKnownNonNull;
5094 bool IsAssumedNonNull =
false;
5097 *
A,
this, getIRPosition(), DepClassTy::NONE, IsKnownNonNull);
5098 return std::string(
"dereferenceable") +
5099 (IsAssumedNonNull ?
"" :
"_or_null") +
5100 (isAssumedGlobal() ?
"_globally" :
"") +
"<" +
5101 std::to_string(getKnownDereferenceableBytes()) +
"-" +
5102 std::to_string(getAssumedDereferenceableBytes()) +
">" +
5103 (!
A ?
" [non-null is unknown]" :
"");
5108struct AADereferenceableFloating : AADereferenceableImpl {
5109 AADereferenceableFloating(
const IRPosition &IRP, Attributor &
A)
5110 : AADereferenceableImpl(IRP,
A) {}
5115 bool UsedAssumedInformation =
false;
5117 if (!
A.getAssumedSimplifiedValues(getIRPosition(), *
this,
Values,
5119 Values.push_back({getAssociatedValue(), getCtxI()});
5122 Stripped =
Values.size() != 1 ||
5123 Values.front().getValue() != &getAssociatedValue();
5126 const DataLayout &
DL =
A.getDataLayout();
5129 auto VisitValueCB = [&](
const Value &
V) ->
bool {
5131 DL.getIndexSizeInBits(
V.getType()->getPointerAddressSpace());
5132 APInt
Offset(IdxWidth, 0);
5137 const auto *AA =
A.getAAFor<AADereferenceable>(
5139 int64_t DerefBytes = 0;
5140 if (!AA || (!Stripped &&
this == AA)) {
5144 DerefBytes =
Base->getPointerDereferenceableBytes(
5145 DL, CanBeNull,
nullptr);
5146 T.GlobalState.indicatePessimisticFixpoint();
5149 DerefBytes =
DS.DerefBytesState.getAssumed();
5150 T.GlobalState &=
DS.GlobalState;
5156 int64_t OffsetSExt =
Offset.getSExtValue();
5160 T.takeAssumedDerefBytesMinimum(
5161 std::max(int64_t(0), DerefBytes - OffsetSExt));
5166 T.takeKnownDerefBytesMaximum(
5167 std::max(int64_t(0), DerefBytes - OffsetSExt));
5168 T.indicatePessimisticFixpoint();
5169 }
else if (OffsetSExt > 0) {
5175 T.indicatePessimisticFixpoint();
5179 return T.isValidState();
5182 for (
const auto &VAC :
Values)
5183 if (!VisitValueCB(*VAC.
getValue()))
5184 return indicatePessimisticFixpoint();
5190 void trackStatistics()
const override {
5196struct AADereferenceableReturned final
5197 : AAReturnedFromReturnedValues<AADereferenceable, AADereferenceableImpl> {
5199 AAReturnedFromReturnedValues<AADereferenceable, AADereferenceableImpl>;
5200 AADereferenceableReturned(
const IRPosition &IRP, Attributor &
A)
5204 void trackStatistics()
const override {
5210struct AADereferenceableArgument final
5211 : AAArgumentFromCallSiteArguments<AADereferenceable,
5212 AADereferenceableImpl> {
5214 AAArgumentFromCallSiteArguments<AADereferenceable, AADereferenceableImpl>;
5215 AADereferenceableArgument(
const IRPosition &IRP, Attributor &
A)
5219 void trackStatistics()
const override {
5225struct AADereferenceableCallSiteArgument final : AADereferenceableFloating {
5226 AADereferenceableCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
5227 : AADereferenceableFloating(IRP,
A) {}
5230 void trackStatistics()
const override {
5236struct AADereferenceableCallSiteReturned final
5237 : AACalleeToCallSite<AADereferenceable, AADereferenceableImpl> {
5238 using Base = AACalleeToCallSite<AADereferenceable, AADereferenceableImpl>;
5239 AADereferenceableCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
5243 void trackStatistics()
const override {
5253static unsigned getKnownAlignForUse(Attributor &
A, AAAlign &QueryingAA,
5254 Value &AssociatedValue,
const Use *U,
5255 const Instruction *
I,
bool &TrackUse) {
5264 if (
GEP->hasAllConstantIndices())
5269 switch (
II->getIntrinsicID()) {
5270 case Intrinsic::ptrmask: {
5272 const auto *ConstVals =
A.getAAFor<AAPotentialConstantValues>(
5274 const auto *AlignAA =
A.getAAFor<AAAlign>(
5276 if (ConstVals && ConstVals->isValidState() && ConstVals->isAtFixpoint()) {
5277 unsigned ShiftValue = std::min(ConstVals->getAssumedMinTrailingZeros(),
5280 if (ConstAlign >= AlignAA->getKnownAlign())
5281 return Align(1).value();
5284 return AlignAA->getKnownAlign().
value();
5287 case Intrinsic::amdgcn_make_buffer_rsrc: {
5288 const auto *AlignAA =
A.getAAFor<AAAlign>(
5291 return AlignAA->getKnownAlign().
value();
5309 MA = MaybeAlign(AlignAA->getKnownAlign());
5312 const DataLayout &
DL =
A.getDataLayout();
5313 const Value *UseV =
U->get();
5315 if (
SI->getPointerOperand() == UseV)
5316 MA =
SI->getAlign();
5318 if (LI->getPointerOperand() == UseV)
5319 MA = LI->getAlign();
5321 if (AI->getPointerOperand() == UseV)
5322 MA = AI->getAlign();
5324 if (AI->getPointerOperand() == UseV)
5325 MA = AI->getAlign();
5335 if (
Base == &AssociatedValue) {
5340 uint32_t
gcd = std::gcd(uint32_t(
abs((int32_t)
Offset)), Alignment);
5348struct AAAlignImpl : AAAlign {
5349 AAAlignImpl(
const IRPosition &IRP, Attributor &
A) : AAAlign(IRP,
A) {}
5354 A.getAttrs(getIRPosition(), {Attribute::Alignment},
Attrs);
5356 takeKnownMaximum(Attr.getValueAsInt());
5358 Value &
V = *getAssociatedValue().stripPointerCasts();
5359 takeKnownMaximum(
V.getPointerAlignment(
A.getDataLayout()).value());
5361 if (Instruction *CtxI = getCtxI())
5362 followUsesInMBEC(*
this,
A, getState(), *CtxI);
5370 Value &AssociatedValue = getAssociatedValue();
5372 return ChangeStatus::UNCHANGED;
5374 for (
const Use &U : AssociatedValue.
uses()) {
5376 if (
SI->getPointerOperand() == &AssociatedValue)
5377 if (
SI->getAlign() < getAssumedAlign()) {
5379 "Number of times alignment added to a store");
5380 SI->setAlignment(getAssumedAlign());
5381 InstrChanged = ChangeStatus::CHANGED;
5384 if (LI->getPointerOperand() == &AssociatedValue)
5385 if (LI->getAlign() < getAssumedAlign()) {
5386 LI->setAlignment(getAssumedAlign());
5388 "Number of times alignment added to a load");
5389 InstrChanged = ChangeStatus::CHANGED;
5392 if (RMW->getPointerOperand() == &AssociatedValue) {
5393 if (RMW->getAlign() < getAssumedAlign()) {
5395 "Number of times alignment added to atomicrmw");
5397 RMW->setAlignment(getAssumedAlign());
5398 InstrChanged = ChangeStatus::CHANGED;
5402 if (CAS->getPointerOperand() == &AssociatedValue) {
5403 if (CAS->getAlign() < getAssumedAlign()) {
5405 "Number of times alignment added to cmpxchg");
5406 CAS->setAlignment(getAssumedAlign());
5407 InstrChanged = ChangeStatus::CHANGED;
5415 Align InheritAlign =
5416 getAssociatedValue().getPointerAlignment(
A.getDataLayout());
5417 if (InheritAlign >= getAssumedAlign())
5418 return InstrChanged;
5419 return Changed | InstrChanged;
5427 void getDeducedAttributes(Attributor &
A, LLVMContext &Ctx,
5428 SmallVectorImpl<Attribute> &Attrs)
const override {
5429 if (getAssumedAlign() > 1)
5431 Attribute::getWithAlignment(Ctx,
Align(getAssumedAlign())));
5435 bool followUseInMBEC(Attributor &
A,
const Use *U,
const Instruction *
I,
5436 AAAlign::StateType &State) {
5437 bool TrackUse =
false;
5439 unsigned int KnownAlign =
5440 getKnownAlignForUse(
A, *
this, getAssociatedValue(), U,
I, TrackUse);
5441 State.takeKnownMaximum(KnownAlign);
5447 const std::string getAsStr(Attributor *
A)
const override {
5448 return "align<" + std::to_string(getKnownAlign().value()) +
"-" +
5449 std::to_string(getAssumedAlign().value()) +
">";
5454struct AAAlignFloating : AAAlignImpl {
5455 AAAlignFloating(
const IRPosition &IRP, Attributor &
A) : AAAlignImpl(IRP,
A) {}
5459 const DataLayout &
DL =
A.getDataLayout();
5462 bool UsedAssumedInformation =
false;
5464 if (!
A.getAssumedSimplifiedValues(getIRPosition(), *
this,
Values,
5466 Values.push_back({getAssociatedValue(), getCtxI()});
5469 Stripped =
Values.size() != 1 ||
5470 Values.front().getValue() != &getAssociatedValue();
5474 auto VisitValueCB = [&](
Value &
V) ->
bool {
5478 DepClassTy::REQUIRED);
5479 if (!AA || (!Stripped &&
this == AA)) {
5497 T.takeKnownMaximum(Alignment);
5498 T.indicatePessimisticFixpoint();
5501 const AAAlign::StateType &
DS = AA->
getState();
5504 return T.isValidState();
5507 for (
const auto &VAC :
Values) {
5508 if (!VisitValueCB(*VAC.
getValue()))
5509 return indicatePessimisticFixpoint();
5522struct AAAlignReturned final
5523 : AAReturnedFromReturnedValues<AAAlign, AAAlignImpl> {
5524 using Base = AAReturnedFromReturnedValues<AAAlign, AAAlignImpl>;
5525 AAAlignReturned(
const IRPosition &IRP, Attributor &
A) :
Base(IRP,
A) {}
5532struct AAAlignArgument final
5533 : AAArgumentFromCallSiteArguments<AAAlign, AAAlignImpl> {
5534 using Base = AAArgumentFromCallSiteArguments<AAAlign, AAAlignImpl>;
5535 AAAlignArgument(
const IRPosition &IRP, Attributor &
A) :
Base(IRP,
A) {}
5542 if (
A.getInfoCache().isInvolvedInMustTailCall(*getAssociatedArgument()))
5543 return ChangeStatus::UNCHANGED;
5544 return Base::manifest(
A);
5551struct AAAlignCallSiteArgument final : AAAlignFloating {
5552 AAAlignCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
5553 : AAAlignFloating(IRP,
A) {}
5560 if (Argument *Arg = getAssociatedArgument())
5561 if (
A.getInfoCache().isInvolvedInMustTailCall(*Arg))
5562 return ChangeStatus::UNCHANGED;
5564 Align InheritAlign =
5565 getAssociatedValue().getPointerAlignment(
A.getDataLayout());
5566 if (InheritAlign >= getAssumedAlign())
5567 Changed = ChangeStatus::UNCHANGED;
5574 if (Argument *Arg = getAssociatedArgument()) {
5577 const auto *ArgAlignAA =
A.getAAFor<AAAlign>(
5580 takeKnownMaximum(ArgAlignAA->getKnownAlign().value());
5590struct AAAlignCallSiteReturned final
5591 : AACalleeToCallSite<AAAlign, AAAlignImpl> {
5592 using Base = AACalleeToCallSite<AAAlign, AAAlignImpl>;
5593 AAAlignCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
5599 switch (
II->getIntrinsicID()) {
5600 case Intrinsic::ptrmask: {
5604 const auto *ConstVals =
A.getAAFor<AAPotentialConstantValues>(
5606 if (ConstVals && ConstVals->isValidState()) {
5607 unsigned ShiftValue =
5608 std::min(ConstVals->getAssumedMinTrailingZeros(),
5609 Value::MaxAlignmentExponent);
5614 const auto *AlignAA =
5616 DepClassTy::REQUIRED);
5618 Alignment = std::max(AlignAA->getAssumedAlign(), Alignment);
5625 std::min(this->getAssumedAlign(), Alignment).value());
5631 case Intrinsic::amdgcn_make_buffer_rsrc: {
5632 const auto *AlignAA =
5634 DepClassTy::REQUIRED);
5637 this->getState(), AlignAA->getAssumedAlign().
value());
5644 return Base::updateImpl(
A);
5653struct AANoReturnImpl :
public AANoReturn {
5654 AANoReturnImpl(
const IRPosition &IRP, Attributor &
A) : AANoReturn(IRP,
A) {}
5660 A,
nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));
5665 const std::string getAsStr(Attributor *
A)
const override {
5666 return getAssumed() ?
"noreturn" :
"may-return";
5671 auto CheckForNoReturn = [](
Instruction &) {
return false; };
5672 bool UsedAssumedInformation =
false;
5673 if (!
A.checkForAllInstructions(CheckForNoReturn, *
this,
5674 {(unsigned)Instruction::Ret},
5675 UsedAssumedInformation))
5676 return indicatePessimisticFixpoint();
5677 return ChangeStatus::UNCHANGED;
5681struct AANoReturnFunction final : AANoReturnImpl {
5682 AANoReturnFunction(
const IRPosition &IRP, Attributor &
A)
5683 : AANoReturnImpl(IRP,
A) {}
5690struct AANoReturnCallSite final
5691 : AACalleeToCallSite<AANoReturn, AANoReturnImpl> {
5692 AANoReturnCallSite(
const IRPosition &IRP, Attributor &
A)
5693 : AACalleeToCallSite<AANoReturn, AANoReturnImpl>(IRP,
A) {}
5704struct AAInstanceInfoImpl :
public AAInstanceInfo {
5705 AAInstanceInfoImpl(
const IRPosition &IRP, Attributor &
A)
5706 : AAInstanceInfo(IRP,
A) {}
5710 Value &
V = getAssociatedValue();
5712 if (
C->isThreadDependent())
5713 indicatePessimisticFixpoint();
5715 indicateOptimisticFixpoint();
5721 indicateOptimisticFixpoint();
5726 A.getInfoCache().getAnalysisResultForFunction<CycleAnalysis>(
5729 indicatePessimisticFixpoint();
5739 Value &
V = getAssociatedValue();
5742 Scope =
I->getFunction();
5745 if (!
Scope->hasLocalLinkage())
5749 return indicateOptimisticFixpoint();
5751 bool IsKnownNoRecurse;
5757 auto UsePred = [&](
const Use &
U,
bool &Follow) {
5772 if (!Callee || !
Callee->hasLocalLinkage())
5776 const auto *ArgInstanceInfoAA =
A.getAAFor<AAInstanceInfo>(
5778 DepClassTy::OPTIONAL);
5779 if (!ArgInstanceInfoAA ||
5780 !ArgInstanceInfoAA->isAssumedUniqueForAnalysis())
5785 A, *CB, *Scope, *
this,
nullptr,
5793 auto EquivalentUseCB = [&](
const Use &OldU,
const Use &NewU) {
5795 auto *Ptr =
SI->getPointerOperand()->stripPointerCasts();
5803 if (!
A.checkForAllUses(UsePred, *
this, V,
true,
5804 DepClassTy::OPTIONAL,
5805 true, EquivalentUseCB))
5806 return indicatePessimisticFixpoint();
5812 const std::string getAsStr(Attributor *
A)
const override {
5813 return isAssumedUniqueForAnalysis() ?
"<unique [fAa]>" :
"<unknown>";
5817 void trackStatistics()
const override {}
5821struct AAInstanceInfoFloating : AAInstanceInfoImpl {
5822 AAInstanceInfoFloating(
const IRPosition &IRP, Attributor &
A)
5823 : AAInstanceInfoImpl(IRP,
A) {}
5827struct AAInstanceInfoArgument final : AAInstanceInfoFloating {
5828 AAInstanceInfoArgument(
const IRPosition &IRP, Attributor &
A)
5829 : AAInstanceInfoFloating(IRP,
A) {}
5833struct AAInstanceInfoCallSiteArgument final : AAInstanceInfoImpl {
5834 AAInstanceInfoCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
5835 : AAInstanceInfoImpl(IRP,
A) {}
5843 Argument *Arg = getAssociatedArgument();
5845 return indicatePessimisticFixpoint();
5848 A.getAAFor<AAInstanceInfo>(*
this, ArgPos, DepClassTy::REQUIRED);
5850 return indicatePessimisticFixpoint();
5856struct AAInstanceInfoReturned final : AAInstanceInfoImpl {
5857 AAInstanceInfoReturned(
const IRPosition &IRP, Attributor &
A)
5858 : AAInstanceInfoImpl(IRP,
A) {
5874struct AAInstanceInfoCallSiteReturned final : AAInstanceInfoFloating {
5875 AAInstanceInfoCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
5876 : AAInstanceInfoFloating(IRP,
A) {}
5883 bool IgnoreSubsumingPositions) {
5884 assert(ImpliedAttributeKind == Attribute::Captures &&
5885 "Unexpected attribute kind");
5899 A.getAttrs(IRP, {Attribute::Captures}, Attrs,
5909 {Attribute::Captures, Attribute::ByVal}, Attrs,
5947 bool NoThrow =
F.doesNotThrow();
5948 bool IsVoidReturn =
F.getReturnType()->isVoidTy();
5949 if (
ReadOnly && NoThrow && IsVoidReturn) {
5962 if (NoThrow && IsVoidReturn)
5967 if (!NoThrow || ArgNo < 0 ||
5968 !
F.getAttributes().hasAttrSomewhere(Attribute::Returned))
5971 for (
unsigned U = 0, E =
F.arg_size(); U < E; ++U)
5972 if (
F.hasParamAttribute(U, Attribute::Returned)) {
5973 if (U ==
unsigned(ArgNo))
6000 void getDeducedAttributes(Attributor &
A, LLVMContext &Ctx,
6001 SmallVectorImpl<Attribute> &Attrs)
const override {
6002 if (!isAssumedNoCaptureMaybeReturned())
6005 if (isArgumentPosition()) {
6006 if (isAssumedNoCapture())
6007 Attrs.emplace_back(Attribute::get(Ctx, Attribute::Captures));
6009 Attrs.emplace_back(Attribute::get(Ctx,
"no-capture-maybe-returned"));
6014 const std::string getAsStr(Attributor *
A)
const override {
6015 if (isKnownNoCapture())
6016 return "known not-captured";
6017 if (isAssumedNoCapture())
6018 return "assumed not-captured";
6019 if (isKnownNoCaptureMaybeReturned())
6020 return "known not-captured-maybe-returned";
6021 if (isAssumedNoCaptureMaybeReturned())
6022 return "assumed not-captured-maybe-returned";
6023 return "assumed-captured";
6028 bool checkUse(Attributor &
A, AANoCapture::StateType &State,
const Use &U,
6031 LLVM_DEBUG(
dbgs() <<
"[AANoCapture] Check use: " << *
U.get() <<
" in "
6037 return isCapturedIn(State,
true,
true,
6044 return isCapturedIn(State,
true,
true,
6050 return isCapturedIn(State,
false,
false,
6052 return isCapturedIn(State,
true,
true,
6060 return isCapturedIn(State,
true,
true,
6067 bool IsKnownNoCapture;
6068 const AANoCapture *ArgNoCaptureAA =
nullptr;
6070 A,
this, CSArgPos, DepClassTy::REQUIRED, IsKnownNoCapture,
false,
6072 if (IsAssumedNoCapture)
6073 return isCapturedIn(State,
false,
false,
6077 return isCapturedIn(State,
false,
false,
6082 return isCapturedIn(State,
true,
true,
6089 static bool isCapturedIn(AANoCapture::StateType &State,
bool CapturedInMem,
6090 bool CapturedInInt,
bool CapturedInRet) {
6091 LLVM_DEBUG(
dbgs() <<
" - captures [Mem " << CapturedInMem <<
"|Int "
6092 << CapturedInInt <<
"|Ret " << CapturedInRet <<
"]\n");
6104 const IRPosition &IRP = getIRPosition();
6108 return indicatePessimisticFixpoint();
6115 return indicatePessimisticFixpoint();
6123 T.addKnownBits(NOT_CAPTURED_IN_MEM);
6125 addKnownBits(NOT_CAPTURED_IN_MEM);
6132 auto CheckReturnedArgs = [&](
bool &UsedAssumedInformation) {
6136 UsedAssumedInformation))
6138 bool SeenConstant =
false;
6139 for (
const AA::ValueAndContext &VAC :
Values) {
6143 SeenConstant =
true;
6145 VAC.
getValue() == getAssociatedArgument())
6151 bool IsKnownNoUnwind;
6154 bool IsVoidTy =
F->getReturnType()->isVoidTy();
6155 bool UsedAssumedInformation =
false;
6156 if (IsVoidTy || CheckReturnedArgs(UsedAssumedInformation)) {
6157 T.addKnownBits(NOT_CAPTURED_IN_RET);
6158 if (
T.isKnown(NOT_CAPTURED_IN_MEM))
6160 if (IsKnownNoUnwind && (IsVoidTy || !UsedAssumedInformation)) {
6161 addKnownBits(NOT_CAPTURED_IN_RET);
6162 if (isKnown(NOT_CAPTURED_IN_MEM))
6163 return indicateOptimisticFixpoint();
6168 auto UseCheck = [&](
const Use &
U,
bool &Follow) ->
bool {
6177 return checkUse(
A,
T, U, Follow);
6180 if (!
A.checkForAllUses(UseCheck, *
this, *V))
6181 return indicatePessimisticFixpoint();
6184 auto Assumed = S.getAssumed();
6185 S.intersectAssumedBits(
T.getAssumed());
6186 if (!isAssumedNoCaptureMaybeReturned())
6187 return indicatePessimisticFixpoint();
6193struct AANoCaptureArgument final : AANoCaptureImpl {
6194 AANoCaptureArgument(
const IRPosition &IRP, Attributor &
A)
6195 : AANoCaptureImpl(IRP,
A) {}
6202struct AANoCaptureCallSiteArgument final : AANoCaptureImpl {
6203 AANoCaptureCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
6204 : AANoCaptureImpl(IRP,
A) {}
6212 Argument *Arg = getAssociatedArgument();
6214 return indicatePessimisticFixpoint();
6216 bool IsKnownNoCapture;
6217 const AANoCapture *ArgAA =
nullptr;
6219 A,
this, ArgPos, DepClassTy::REQUIRED, IsKnownNoCapture,
false,
6221 return ChangeStatus::UNCHANGED;
6223 return indicatePessimisticFixpoint();
6228 void trackStatistics()
const override {
6234struct AANoCaptureFloating final : AANoCaptureImpl {
6235 AANoCaptureFloating(
const IRPosition &IRP, Attributor &
A)
6236 : AANoCaptureImpl(IRP,
A) {}
6239 void trackStatistics()
const override {
6245struct AANoCaptureReturned final : AANoCaptureImpl {
6246 AANoCaptureReturned(
const IRPosition &IRP, Attributor &
A)
6247 : AANoCaptureImpl(IRP,
A) {
6262 void trackStatistics()
const override {}
6266struct AANoCaptureCallSiteReturned final : AANoCaptureImpl {
6267 AANoCaptureCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
6268 : AANoCaptureImpl(IRP,
A) {}
6274 determineFunctionCaptureCapabilities(getIRPosition(), *
F, *
this);
6278 void trackStatistics()
const override {
6295 dbgs() <<
"[ValueSimplify] is assumed to be "
6298 dbgs() <<
"[ValueSimplify] is assumed to be <none>\n";
6310 if (getAssociatedValue().
getType()->isVoidTy())
6311 indicatePessimisticFixpoint();
6312 if (
A.hasSimplificationCallback(getIRPosition()))
6313 indicatePessimisticFixpoint();
6317 const std::string getAsStr(Attributor *
A)
const override {
6319 dbgs() <<
"SAV: " << (bool)SimplifiedAssociatedValue <<
" ";
6320 if (SimplifiedAssociatedValue && *SimplifiedAssociatedValue)
6321 dbgs() <<
"SAV: " << **SimplifiedAssociatedValue <<
" ";
6323 return isValidState() ? (isAtFixpoint() ?
"simplified" :
"maybe-simple")
6328 void trackStatistics()
const override {}
6331 std::optional<Value *>
6332 getAssumedSimplifiedValue(Attributor &
A)
const override {
6333 return SimplifiedAssociatedValue;
6340 static Value *ensureType(Attributor &
A,
Value &V,
Type &Ty, Instruction *CtxI,
6344 if (CtxI &&
V.getType()->canLosslesslyBitCastTo(&Ty))
6346 : BitCastInst::CreatePointerBitCastOrAddrSpaceCast(
6355 static Value *reproduceInst(Attributor &
A,
6356 const AbstractAttribute &QueryingAA,
6357 Instruction &
I,
Type &Ty, Instruction *CtxI,
6359 assert(CtxI &&
"Cannot reproduce an instruction without context!");
6360 if (
Check && (
I.mayReadFromMemory() ||
6365 Value *NewOp = reproduceValue(
A, QueryingAA, *
Op, Ty, CtxI,
Check, VMap);
6367 assert(
Check &&
"Manifest of new value unexpectedly failed!");
6389 static Value *reproduceValue(Attributor &
A,
6390 const AbstractAttribute &QueryingAA,
Value &V,
6391 Type &Ty, Instruction *CtxI,
bool Check,
6393 if (
const auto &NewV = VMap.
lookup(&V))
6395 bool UsedAssumedInformation =
false;
6396 std::optional<Value *> SimpleV =
A.getAssumedSimplified(
6398 if (!SimpleV.has_value())
6402 EffectiveV = *SimpleV;
6407 return ensureType(
A, *EffectiveV, Ty, CtxI,
Check);
6409 if (
Value *NewV = reproduceInst(
A, QueryingAA, *
I, Ty, CtxI,
Check, VMap))
6410 return ensureType(
A, *NewV, Ty, CtxI,
Check);
6416 Value *manifestReplacementValue(Attributor &
A, Instruction *CtxI)
const {
6417 Value *NewV = SimplifiedAssociatedValue
6418 ? *SimplifiedAssociatedValue
6420 if (NewV && NewV != &getAssociatedValue()) {
6424 if (reproduceValue(
A, *
this, *NewV, *getAssociatedType(), CtxI,
6426 return reproduceValue(
A, *
this, *NewV, *getAssociatedType(), CtxI,
6434 bool checkAndUpdate(Attributor &
A,
const AbstractAttribute &QueryingAA,
6435 const IRPosition &IRP,
bool Simplify =
true) {
6436 bool UsedAssumedInformation =
false;
6439 QueryingValueSimplified =
A.getAssumedSimplified(
6441 return unionAssumed(QueryingValueSimplified);
6445 template <
typename AAType>
bool askSimplifiedValueFor(Attributor &
A) {
6446 if (!getAssociatedValue().
getType()->isIntegerTy())
6451 A.getAAFor<AAType>(*
this, getIRPosition(), DepClassTy::NONE);
6455 std::optional<Constant *> COpt = AA->getAssumedConstant(
A);
6458 SimplifiedAssociatedValue = std::nullopt;
6459 A.recordDependence(*AA, *
this, DepClassTy::OPTIONAL);
6462 if (
auto *
C = *COpt) {
6463 SimplifiedAssociatedValue =
C;
6464 A.recordDependence(*AA, *
this, DepClassTy::OPTIONAL);
6470 bool askSimplifiedValueForOtherAAs(Attributor &
A) {
6471 if (askSimplifiedValueFor<AAValueConstantRange>(
A))
6473 if (askSimplifiedValueFor<AAPotentialConstantValues>(
A))
6481 for (
auto &U : getAssociatedValue().uses()) {
6486 IP =
PHI->getIncomingBlock(U)->getTerminator();
6487 if (
auto *NewV = manifestReplacementValue(
A, IP)) {
6489 <<
" -> " << *NewV <<
" :: " << *
this <<
"\n");
6490 if (
A.changeUseAfterManifest(U, *NewV))
6491 Changed = ChangeStatus::CHANGED;
6495 return Changed | AAValueSimplify::manifest(
A);
6500 SimplifiedAssociatedValue = &getAssociatedValue();
6501 return AAValueSimplify::indicatePessimisticFixpoint();
6505struct AAValueSimplifyArgument final : AAValueSimplifyImpl {
6506 AAValueSimplifyArgument(
const IRPosition &IRP, Attributor &
A)
6507 : AAValueSimplifyImpl(IRP,
A) {}
6510 AAValueSimplifyImpl::initialize(
A);
6511 if (
A.hasAttr(getIRPosition(),
6512 {Attribute::InAlloca, Attribute::Preallocated,
6513 Attribute::StructRet, Attribute::Nest, Attribute::ByVal},
6515 indicatePessimisticFixpoint();
6522 Argument *Arg = getAssociatedArgument();
6528 return indicatePessimisticFixpoint();
6531 auto Before = SimplifiedAssociatedValue;
6533 auto PredForCallSite = [&](AbstractCallSite ACS) {
6534 const IRPosition &ACSArgPos =
6545 bool UsedAssumedInformation =
false;
6546 std::optional<Constant *> SimpleArgOp =
6547 A.getAssumedConstant(ACSArgPos, *
this, UsedAssumedInformation);
6554 return unionAssumed(*SimpleArgOp);
6559 bool UsedAssumedInformation =
false;
6560 if (hasCallBaseContext() &&
6561 getCallBaseContext()->getCalledOperand() == Arg->
getParent())
6563 AbstractCallSite(&getCallBaseContext()->getCalledOperandUse()));
6565 Success =
A.checkForAllCallSites(PredForCallSite, *
this,
true,
6566 UsedAssumedInformation);
6569 if (!askSimplifiedValueForOtherAAs(
A))
6570 return indicatePessimisticFixpoint();
6573 return Before == SimplifiedAssociatedValue ? ChangeStatus::UNCHANGED
6574 : ChangeStatus ::CHANGED;
6578 void trackStatistics()
const override {
6583struct AAValueSimplifyReturned : AAValueSimplifyImpl {
6584 AAValueSimplifyReturned(
const IRPosition &IRP, Attributor &
A)
6585 : AAValueSimplifyImpl(IRP,
A) {}
6588 std::optional<Value *>
6589 getAssumedSimplifiedValue(Attributor &
A)
const override {
6590 if (!isValidState())
6592 return SimplifiedAssociatedValue;
6597 auto Before = SimplifiedAssociatedValue;
6601 return checkAndUpdate(
6606 bool UsedAssumedInformation =
false;
6607 if (!
A.checkForAllInstructions(ReturnInstCB, *
this, {Instruction::Ret},
6608 UsedAssumedInformation))
6609 if (!askSimplifiedValueForOtherAAs(
A))
6610 return indicatePessimisticFixpoint();
6613 return Before == SimplifiedAssociatedValue ? ChangeStatus::UNCHANGED
6614 : ChangeStatus ::CHANGED;
6620 return ChangeStatus::UNCHANGED;
6624 void trackStatistics()
const override {
6629struct AAValueSimplifyFloating : AAValueSimplifyImpl {
6630 AAValueSimplifyFloating(
const IRPosition &IRP, Attributor &
A)
6631 : AAValueSimplifyImpl(IRP,
A) {}
6635 AAValueSimplifyImpl::initialize(
A);
6636 Value &
V = getAnchorValue();
6640 indicatePessimisticFixpoint();
6645 auto Before = SimplifiedAssociatedValue;
6646 if (!askSimplifiedValueForOtherAAs(
A))
6647 return indicatePessimisticFixpoint();
6650 return Before == SimplifiedAssociatedValue ? ChangeStatus::UNCHANGED
6651 : ChangeStatus ::CHANGED;
6655 void trackStatistics()
const override {
6660struct AAValueSimplifyFunction : AAValueSimplifyImpl {
6661 AAValueSimplifyFunction(
const IRPosition &IRP, Attributor &
A)
6662 : AAValueSimplifyImpl(IRP,
A) {}
6666 SimplifiedAssociatedValue =
nullptr;
6667 indicateOptimisticFixpoint();
6672 "AAValueSimplify(Function|CallSite)::updateImpl will not be called");
6675 void trackStatistics()
const override {
6680struct AAValueSimplifyCallSite : AAValueSimplifyFunction {
6681 AAValueSimplifyCallSite(
const IRPosition &IRP, Attributor &
A)
6682 : AAValueSimplifyFunction(IRP,
A) {}
6684 void trackStatistics()
const override {
6689struct AAValueSimplifyCallSiteReturned : AAValueSimplifyImpl {
6690 AAValueSimplifyCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
6691 : AAValueSimplifyImpl(IRP,
A) {}
6694 AAValueSimplifyImpl::initialize(
A);
6695 Function *Fn = getAssociatedFunction();
6696 assert(Fn &&
"Did expect an associted function");
6697 for (Argument &Arg : Fn->
args()) {
6702 checkAndUpdate(
A, *
this, IRP))
6703 indicateOptimisticFixpoint();
6705 indicatePessimisticFixpoint();
6713 return indicatePessimisticFixpoint();
6716 void trackStatistics()
const override {
6721struct AAValueSimplifyCallSiteArgument : AAValueSimplifyFloating {
6722 AAValueSimplifyCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
6723 : AAValueSimplifyFloating(IRP,
A) {}
6729 auto *FloatAA =
A.lookupAAFor<AAValueSimplify>(
6731 if (FloatAA && FloatAA->getState().isValidState())
6734 if (
auto *NewV = manifestReplacementValue(
A, getCtxI())) {
6736 ->getArgOperandUse(getCallSiteArgNo());
6737 if (
A.changeUseAfterManifest(U, *NewV))
6738 Changed = ChangeStatus::CHANGED;
6741 return Changed | AAValueSimplify::manifest(
A);
6744 void trackStatistics()
const override {
6752struct AAHeapToStackFunction final :
public AAHeapToStack {
6754 static bool isGlobalizedLocal(
const CallBase &CB) {
6756 return A.
isValid() &&
A.getValueAsString() ==
"__kmpc_alloc_shared";
6759 struct AllocationInfo {
6764 bool IsGlobalizedLocal =
false;
6771 } Status = STACK_DUE_TO_USE;
6775 bool HasPotentiallyFreeingUnknownUses =
false;
6779 bool MoveAllocaIntoEntry =
true;
6782 SmallSetVector<CallBase *, 1> PotentialFreeCalls{};
6785 struct DeallocationInfo {
6793 bool MightFreeUnknownObjects =
false;
6796 SmallSetVector<CallBase *, 1> PotentialAllocationCalls{};
6799 AAHeapToStackFunction(
const IRPosition &IRP, Attributor &
A)
6800 : AAHeapToStack(IRP,
A) {}
6802 ~AAHeapToStackFunction()
override {
6805 for (
auto &It : AllocationInfos)
6806 It.second->~AllocationInfo();
6807 for (
auto &It : DeallocationInfos)
6808 It.second->~DeallocationInfo();
6812 AAHeapToStack::initialize(
A);
6815 const auto *TLI =
A.getInfoCache().getTargetLibraryInfoForFunction(*
F);
6822 DeallocationInfos[CB] =
new (
A.Allocator) DeallocationInfo{CB, FreedOp};
6829 auto *I8Ty = Type::getInt8Ty(CB->
getParent()->getContext());
6831 AllocationInfo *AI =
new (
A.Allocator) AllocationInfo{CB};
6832 AllocationInfos[CB] = AI;
6833 AI->IsGlobalizedLocal = isGlobalizedLocal(*CB);
6839 bool UsedAssumedInformation =
false;
6840 bool Success =
A.checkForAllCallLikeInstructions(
6841 AllocationIdentifierCB, *
this, UsedAssumedInformation,
6845 assert(
Success &&
"Did not expect the call base visit callback to fail!");
6848 [](
const IRPosition &,
const AbstractAttribute *,
6849 bool &) -> std::optional<Value *> {
return nullptr; };
6850 for (
const auto &It : AllocationInfos)
6853 for (
const auto &It : DeallocationInfos)
6858 const std::string getAsStr(Attributor *
A)
const override {
6859 unsigned NumH2SMallocs = 0, NumInvalidMallocs = 0;
6860 for (
const auto &It : AllocationInfos) {
6861 if (It.second->Status == AllocationInfo::INVALID)
6862 ++NumInvalidMallocs;
6866 return "[H2S] Mallocs Good/Bad: " + std::to_string(NumH2SMallocs) +
"/" +
6867 std::to_string(NumInvalidMallocs);
6871 void trackStatistics()
const override {
6874 "Number of malloc/calloc/aligned_alloc calls converted to allocas");
6875 for (
const auto &It : AllocationInfos)
6876 if (It.second->Status != AllocationInfo::INVALID)
6880 bool isAssumedHeapToStack(
const CallBase &CB)
const override {
6882 if (AllocationInfo *AI =
6883 AllocationInfos.lookup(
const_cast<CallBase *
>(&CB)))
6884 return AI->Status != AllocationInfo::INVALID;
6888 bool isAssumedHeapToStackRemovedFree(CallBase &CB)
const override {
6889 if (!isValidState())
6892 for (
const auto &It : AllocationInfos) {
6893 AllocationInfo &AI = *It.second;
6894 if (AI.Status == AllocationInfo::INVALID)
6897 if (AI.PotentialFreeCalls.count(&CB))
6905 assert(getState().isValidState() &&
6906 "Attempted to manifest an invalid state!");
6910 const auto *TLI =
A.getInfoCache().getTargetLibraryInfoForFunction(*
F);
6912 for (
auto &It : AllocationInfos) {
6913 AllocationInfo &AI = *It.second;
6914 if (AI.Status == AllocationInfo::INVALID)
6917 for (CallBase *FreeCall : AI.PotentialFreeCalls) {
6918 LLVM_DEBUG(
dbgs() <<
"H2S: Removing free call: " << *FreeCall <<
"\n");
6919 A.deleteAfterManifest(*FreeCall);
6920 HasChanged = ChangeStatus::CHANGED;
6923 LLVM_DEBUG(
dbgs() <<
"H2S: Removing malloc-like call: " << *AI.CB
6926 auto Remark = [&](OptimizationRemark
OR) {
6927 if (AI.IsGlobalizedLocal)
6928 return OR <<
"Moving globalized variable to the stack.";
6929 return OR <<
"Moving memory allocation from the heap to the stack.";
6931 if (AI.IsGlobalizedLocal)
6932 A.emitRemark<OptimizationRemark>(AI.CB,
"OMP110",
Remark);
6934 A.emitRemark<OptimizationRemark>(AI.CB,
"HeapToStack",
Remark);
6936 const DataLayout &
DL =
A.getInfoCache().getDL();
6938 std::optional<APInt> SizeAPI =
getSize(
A, *
this, AI);
6940 Size = ConstantInt::get(AI.CB->getContext(), *SizeAPI);
6942 ObjectSizeOpts Opts;
6943 ObjectSizeOffsetEvaluator Eval(*AI.CB->getModule(), TLI, Opts);
6944 SizeOffsetValue SizeOffsetPair = Eval.compute(AI.CB);
6951 ?
F->getEntryBlock().begin()
6952 : AI.CB->getIterator();
6955 if (MaybeAlign RetAlign = AI.CB->getRetAlign())
6956 Alignment = std::max(Alignment, *RetAlign);
6958 std::optional<APInt> AlignmentAPI = getAPInt(
A, *
this, *Align);
6959 assert(AlignmentAPI && AlignmentAPI->getZExtValue() > 0 &&
6960 "Expected an alignment during manifest!");
6962 std::max(Alignment,
assumeAligned(AlignmentAPI->getZExtValue()));
6966 unsigned AS =
DL.getAllocaAddrSpace();
6968 new AllocaInst(Type::getInt8Ty(
F->getContext()), AS,
Size, Alignment,
6969 AI.CB->getName() +
".h2s", IP);
6971 if (Alloca->
getType() != AI.CB->getType())
6972 Alloca = BitCastInst::CreatePointerBitCastOrAddrSpaceCast(
6973 Alloca, AI.CB->getType(),
"malloc_cast", AI.CB->getIterator());
6975 auto *I8Ty = Type::getInt8Ty(
F->getContext());
6978 "Must be able to materialize initial memory state of allocation");
6983 auto *NBB =
II->getNormalDest();
6985 A.deleteAfterManifest(*AI.CB);
6987 A.deleteAfterManifest(*AI.CB);
6996 Builder.CreateMemSet(Alloca, InitVal,
Size, std::nullopt);
6998 HasChanged = ChangeStatus::CHANGED;
7004 std::optional<APInt> getAPInt(Attributor &
A,
const AbstractAttribute &AA,
7006 bool UsedAssumedInformation =
false;
7007 std::optional<Constant *> SimpleV =
7008 A.getAssumedConstant(V, AA, UsedAssumedInformation);
7010 return APInt(64, 0);
7012 return CI->getValue();
7013 return std::nullopt;
7016 std::optional<APInt>
getSize(Attributor &
A,
const AbstractAttribute &AA,
7017 AllocationInfo &AI) {
7019 bool UsedAssumedInformation =
false;
7020 if (std::optional<Constant *> SimpleV =
7021 A.getAssumedConstant(*V, AA, UsedAssumedInformation))
7028 const auto *TLI =
A.getInfoCache().getTargetLibraryInfoForFunction(*
F);
7034 MapVector<CallBase *, AllocationInfo *> AllocationInfos;
7038 MapVector<CallBase *, DeallocationInfo *> DeallocationInfos;
7043ChangeStatus AAHeapToStackFunction::updateImpl(Attributor &
A) {
7046 const auto *TLI =
A.getInfoCache().getTargetLibraryInfoForFunction(*
F);
7048 const auto *LivenessAA =
7051 MustBeExecutedContextExplorer *Explorer =
7052 A.getInfoCache().getMustBeExecutedContextExplorer();
7054 bool StackIsAccessibleByOtherThreads =
7055 A.getInfoCache().stackIsAccessibleByOtherThreads();
7058 A.getInfoCache().getAnalysisResultForFunction<LoopAnalysis>(*F);
7059 std::optional<bool> MayContainIrreducibleControl;
7061 if (&
F->getEntryBlock() == &BB)
7063 if (!MayContainIrreducibleControl.has_value())
7065 if (*MayContainIrreducibleControl)
7074 bool HasUpdatedFrees =
false;
7076 auto UpdateFrees = [&]() {
7077 HasUpdatedFrees =
true;
7079 for (
auto &It : DeallocationInfos) {
7080 DeallocationInfo &DI = *It.second;
7083 if (DI.MightFreeUnknownObjects)
7087 bool UsedAssumedInformation =
false;
7088 if (
A.isAssumedDead(*DI.CB,
this, LivenessAA, UsedAssumedInformation,
7095 LLVM_DEBUG(
dbgs() <<
"[H2S] Unknown underlying object for free!\n");
7096 DI.MightFreeUnknownObjects =
true;
7109 DI.MightFreeUnknownObjects =
true;
7113 AllocationInfo *AI = AllocationInfos.lookup(ObjCB);
7115 LLVM_DEBUG(
dbgs() <<
"[H2S] Free of a non-allocation object: " << *Obj
7117 DI.MightFreeUnknownObjects =
true;
7121 DI.PotentialAllocationCalls.insert(ObjCB);
7125 auto FreeCheck = [&](AllocationInfo &AI) {
7129 if (!StackIsAccessibleByOtherThreads) {
7134 dbgs() <<
"[H2S] found an escaping use, stack is not accessible by "
7135 "other threads and function is not nosync:\n");
7139 if (!HasUpdatedFrees)
7143 if (AI.PotentialFreeCalls.size() != 1) {
7145 << AI.PotentialFreeCalls.size() <<
"\n");
7148 CallBase *UniqueFree = *AI.PotentialFreeCalls.begin();
7149 DeallocationInfo *DI = DeallocationInfos.lookup(UniqueFree);
7152 dbgs() <<
"[H2S] unique free call was not known as deallocation call "
7153 << *UniqueFree <<
"\n");
7156 if (DI->MightFreeUnknownObjects) {
7158 dbgs() <<
"[H2S] unique free call might free unknown allocations\n");
7161 if (DI->PotentialAllocationCalls.empty())
7163 if (DI->PotentialAllocationCalls.size() > 1) {
7165 << DI->PotentialAllocationCalls.size()
7166 <<
" different allocations\n");
7169 if (*DI->PotentialAllocationCalls.begin() != AI.CB) {
7172 <<
"[H2S] unique free call not known to free this allocation but "
7173 << **DI->PotentialAllocationCalls.begin() <<
"\n");
7178 if (!AI.IsGlobalizedLocal) {
7180 if (!Explorer || !Explorer->findInContextOf(UniqueFree, CtxI)) {
7181 LLVM_DEBUG(
dbgs() <<
"[H2S] unique free call might not be executed "
7182 "with the allocation "
7183 << *UniqueFree <<
"\n");
7190 auto UsesCheck = [&](AllocationInfo &AI) {
7191 bool ValidUsesOnly =
true;
7193 auto Pred = [&](
const Use &
U,
bool &Follow) ->
bool {
7198 if (
SI->getValueOperand() ==
U.get()) {
7200 <<
"[H2S] escaping store to memory: " << *UserI <<
"\n");
7201 ValidUsesOnly =
false;
7210 if (DeallocationInfos.count(CB)) {
7211 AI.PotentialFreeCalls.insert(CB);
7218 bool IsKnownNoCapture;
7227 if (!IsAssumedNoCapture ||
7228 (!AI.IsGlobalizedLocal && !IsAssumedNoFree)) {
7229 AI.HasPotentiallyFreeingUnknownUses |= !IsAssumedNoFree;
7232 auto Remark = [&](OptimizationRemarkMissed ORM) {
7234 <<
"Could not move globalized variable to the stack. "
7235 "Variable is potentially captured in call. Mark "
7236 "parameter as `__attribute__((noescape))` to override.";
7239 if (ValidUsesOnly && AI.IsGlobalizedLocal)
7240 A.emitRemark<OptimizationRemarkMissed>(CB,
"OMP113",
Remark);
7243 ValidUsesOnly =
false;
7256 ValidUsesOnly =
false;
7259 if (!
A.checkForAllUses(Pred, *
this, *AI.CB,
false,
7261 [&](
const Use &OldU,
const Use &NewU) {
7262 auto *SI = dyn_cast<StoreInst>(OldU.getUser());
7263 return !SI || StackIsAccessibleByOtherThreads ||
7264 AA::isAssumedThreadLocalObject(
7265 A, *SI->getPointerOperand(), *this);
7268 return ValidUsesOnly;
7273 for (
auto &It : AllocationInfos) {
7274 AllocationInfo &AI = *It.second;
7275 if (AI.Status == AllocationInfo::INVALID)
7279 std::optional<APInt> APAlign = getAPInt(
A, *
this, *Align);
7283 LLVM_DEBUG(
dbgs() <<
"[H2S] Unknown allocation alignment: " << *AI.CB
7285 AI.Status = AllocationInfo::INVALID;
7290 !APAlign->isPowerOf2()) {
7291 LLVM_DEBUG(
dbgs() <<
"[H2S] Invalid allocation alignment: " << APAlign
7293 AI.Status = AllocationInfo::INVALID;
7304 dbgs() <<
"[H2S] Unknown allocation size: " << *AI.CB <<
"\n";
7306 dbgs() <<
"[H2S] Allocation size too large: " << *AI.CB <<
" vs. "
7310 AI.Status = AllocationInfo::INVALID;
7316 switch (AI.Status) {
7317 case AllocationInfo::STACK_DUE_TO_USE:
7320 AI.Status = AllocationInfo::STACK_DUE_TO_FREE;
7322 case AllocationInfo::STACK_DUE_TO_FREE:
7325 AI.Status = AllocationInfo::INVALID;
7328 case AllocationInfo::INVALID:
7335 bool IsGlobalizedLocal = AI.IsGlobalizedLocal;
7336 if (AI.MoveAllocaIntoEntry &&
7337 (!
Size.has_value() ||
7338 (!IsGlobalizedLocal && IsInLoop(*AI.CB->getParent()))))
7339 AI.MoveAllocaIntoEntry =
false;
7348struct AAPrivatizablePtrImpl :
public AAPrivatizablePtr {
7349 AAPrivatizablePtrImpl(
const IRPosition &IRP, Attributor &
A)
7350 : AAPrivatizablePtr(IRP,
A), PrivatizableType(std::nullopt) {}
7353 AAPrivatizablePtr::indicatePessimisticFixpoint();
7354 PrivatizableType =
nullptr;
7355 return ChangeStatus::CHANGED;
7361 virtual std::optional<Type *> identifyPrivatizableType(Attributor &
A) = 0;
7365 std::optional<Type *> combineTypes(std::optional<Type *> T0,
7366 std::optional<Type *>
T1) {
7376 std::optional<Type *> getPrivatizableType()
const override {
7377 return PrivatizableType;
7380 const std::string getAsStr(Attributor *
A)
const override {
7381 return isAssumedPrivatizablePtr() ?
"[priv]" :
"[no-priv]";
7385 std::optional<Type *> PrivatizableType;
7390struct AAPrivatizablePtrArgument final :
public AAPrivatizablePtrImpl {
7391 AAPrivatizablePtrArgument(
const IRPosition &IRP, Attributor &
A)
7392 : AAPrivatizablePtrImpl(IRP,
A) {}
7395 std::optional<Type *> identifyPrivatizableType(Attributor &
A)
override {
7398 bool UsedAssumedInformation =
false;
7400 A.getAttrs(getIRPosition(), {Attribute::ByVal},
Attrs,
7402 if (!
Attrs.empty() &&
7403 A.checkForAllCallSites([](AbstractCallSite ACS) { return true; }, *
this,
7404 true, UsedAssumedInformation))
7405 return Attrs[0].getValueAsType();
7407 std::optional<Type *> Ty;
7408 unsigned ArgNo = getIRPosition().getCallSiteArgNo();
7416 auto CallSiteCheck = [&](AbstractCallSite ACS) {
7425 A.getAAFor<AAPrivatizablePtr>(*
this, ACSArgPos, DepClassTy::REQUIRED);
7428 std::optional<Type *> CSTy = PrivCSArgAA->getPrivatizableType();
7431 dbgs() <<
"[AAPrivatizablePtr] ACSPos: " << ACSArgPos <<
", CSTy: ";
7435 dbgs() <<
"<nullptr>";
7440 Ty = combineTypes(Ty, CSTy);
7443 dbgs() <<
" : New Type: ";
7445 (*Ty)->print(
dbgs());
7447 dbgs() <<
"<nullptr>";
7456 if (!
A.checkForAllCallSites(CallSiteCheck, *
this,
true,
7457 UsedAssumedInformation))
7464 PrivatizableType = identifyPrivatizableType(
A);
7465 if (!PrivatizableType)
7466 return ChangeStatus::UNCHANGED;
7467 if (!*PrivatizableType)
7468 return indicatePessimisticFixpoint();
7473 DepClassTy::OPTIONAL);
7476 if (!
A.hasAttr(getIRPosition(), Attribute::ByVal) &&
7479 return indicatePessimisticFixpoint();
7485 identifyReplacementTypes(*PrivatizableType, ReplacementTypes);
7489 Function &Fn = *getIRPosition().getAnchorScope();
7491 A.getInfoCache().getAnalysisResultForFunction<TargetIRAnalysis>(Fn);
7493 LLVM_DEBUG(
dbgs() <<
"[AAPrivatizablePtr] Missing TTI for function "
7495 return indicatePessimisticFixpoint();
7498 auto CallSiteCheck = [&](AbstractCallSite ACS) {
7505 bool UsedAssumedInformation =
false;
7506 if (!
A.checkForAllCallSites(CallSiteCheck, *
this,
true,
7507 UsedAssumedInformation)) {
7509 dbgs() <<
"[AAPrivatizablePtr] ABI incompatibility detected for "
7511 return indicatePessimisticFixpoint();
7515 Argument *Arg = getAssociatedArgument();
7516 if (!
A.isValidFunctionSignatureRewrite(*Arg, ReplacementTypes)) {
7518 return indicatePessimisticFixpoint();
7525 auto IsCompatiblePrivArgOfCallback = [&](CallBase &CB) {
7528 for (
const Use *U : CallbackUses) {
7529 AbstractCallSite CBACS(U);
7530 assert(CBACS && CBACS.isCallbackCall());
7531 for (Argument &CBArg : CBACS.getCalledFunction()->args()) {
7532 int CBArgNo = CBACS.getCallArgOperandNo(CBArg);
7536 <<
"[AAPrivatizablePtr] Argument " << *Arg
7537 <<
"check if can be privatized in the context of its parent ("
7539 <<
")\n[AAPrivatizablePtr] because it is an argument in a "
7541 << CBArgNo <<
"@" << CBACS.getCalledFunction()->getName()
7542 <<
")\n[AAPrivatizablePtr] " << CBArg <<
" : "
7543 << CBACS.getCallArgOperand(CBArg) <<
" vs "
7545 <<
"[AAPrivatizablePtr] " << CBArg <<
" : "
7546 << CBACS.getCallArgOperandNo(CBArg) <<
" vs " << ArgNo <<
"\n";
7549 if (CBArgNo !=
int(ArgNo))
7551 const auto *CBArgPrivAA =
A.getAAFor<AAPrivatizablePtr>(
7553 if (CBArgPrivAA && CBArgPrivAA->isValidState()) {
7554 auto CBArgPrivTy = CBArgPrivAA->getPrivatizableType();
7557 if (*CBArgPrivTy == PrivatizableType)
7562 dbgs() <<
"[AAPrivatizablePtr] Argument " << *Arg
7563 <<
" cannot be privatized in the context of its parent ("
7565 <<
")\n[AAPrivatizablePtr] because it is an argument in a "
7567 << CBArgNo <<
"@" << CBACS.getCalledFunction()->getName()
7568 <<
").\n[AAPrivatizablePtr] for which the argument "
7569 "privatization is not compatible.\n";
7579 auto IsCompatiblePrivArgOfDirectCS = [&](AbstractCallSite ACS) {
7583 "Expected a direct call operand for callback call operand");
7588 dbgs() <<
"[AAPrivatizablePtr] Argument " << *Arg
7589 <<
" check if be privatized in the context of its parent ("
7591 <<
")\n[AAPrivatizablePtr] because it is an argument in a "
7593 << DCArgNo <<
"@" << DCCallee->
getName() <<
").\n";
7596 if (
unsigned(DCArgNo) < DCCallee->
arg_size()) {
7597 const auto *DCArgPrivAA =
A.getAAFor<AAPrivatizablePtr>(
7599 DepClassTy::REQUIRED);
7600 if (DCArgPrivAA && DCArgPrivAA->isValidState()) {
7601 auto DCArgPrivTy = DCArgPrivAA->getPrivatizableType();
7604 if (*DCArgPrivTy == PrivatizableType)
7610 dbgs() <<
"[AAPrivatizablePtr] Argument " << *Arg
7611 <<
" cannot be privatized in the context of its parent ("
7613 <<
")\n[AAPrivatizablePtr] because it is an argument in a "
7616 <<
").\n[AAPrivatizablePtr] for which the argument "
7617 "privatization is not compatible.\n";
7625 auto IsCompatiblePrivArgOfOtherCallSite = [&](AbstractCallSite ACS) {
7629 return IsCompatiblePrivArgOfDirectCS(ACS);
7633 if (!
A.checkForAllCallSites(IsCompatiblePrivArgOfOtherCallSite, *
this,
true,
7634 UsedAssumedInformation))
7635 return indicatePessimisticFixpoint();
7637 return ChangeStatus::UNCHANGED;
7643 identifyReplacementTypes(
Type *PrivType,
7644 SmallVectorImpl<Type *> &ReplacementTypes) {
7647 assert(PrivType &&
"Expected privatizable type!");
7651 for (
unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++)
7652 ReplacementTypes.
push_back(PrivStructType->getElementType(u));
7654 ReplacementTypes.
append(PrivArrayType->getNumElements(),
7655 PrivArrayType->getElementType());
7666 assert(PrivType &&
"Expected privatizable type!");
7669 const DataLayout &
DL =
F.getDataLayout();
7673 const StructLayout *PrivStructLayout =
DL.getStructLayout(PrivStructType);
7674 for (
unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++) {
7677 new StoreInst(
F.getArg(ArgNo + u), Ptr, IP);
7680 Type *PointeeTy = PrivArrayType->getElementType();
7681 uint64_t PointeeTySize =
DL.getTypeStoreSize(PointeeTy);
7682 for (
unsigned u = 0, e = PrivArrayType->getNumElements(); u < e; u++) {
7684 new StoreInst(
F.getArg(ArgNo + u), Ptr, IP);
7687 new StoreInst(
F.getArg(ArgNo), &
Base, IP);
7693 void createReplacementValues(Align Alignment,
Type *PrivType,
7695 SmallVectorImpl<Value *> &ReplacementValues) {
7697 assert(PrivType &&
"Expected privatizable type!");
7705 const StructLayout *PrivStructLayout =
DL.getStructLayout(PrivStructType);
7706 for (
unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++) {
7707 Type *PointeeTy = PrivStructType->getElementType(u);
7710 LoadInst *
L =
new LoadInst(PointeeTy, Ptr,
"", IP->
getIterator());
7711 L->setAlignment(Alignment);
7715 Type *PointeeTy = PrivArrayType->getElementType();
7716 uint64_t PointeeTySize =
DL.getTypeStoreSize(PointeeTy);
7717 for (
unsigned u = 0, e = PrivArrayType->getNumElements(); u < e; u++) {
7719 LoadInst *
L =
new LoadInst(PointeeTy, Ptr,
"", IP->
getIterator());
7720 L->setAlignment(Alignment);
7725 L->setAlignment(Alignment);
7732 if (!PrivatizableType)
7733 return ChangeStatus::UNCHANGED;
7734 assert(*PrivatizableType &&
"Expected privatizable type!");
7740 bool UsedAssumedInformation =
false;
7741 if (!
A.checkForAllInstructions(
7742 [&](Instruction &
I) {
7743 CallInst &CI = cast<CallInst>(I);
7744 if (CI.isTailCall())
7745 TailCalls.push_back(&CI);
7748 *
this, {Instruction::Call}, UsedAssumedInformation))
7749 return ChangeStatus::UNCHANGED;
7751 Argument *Arg = getAssociatedArgument();
7754 const auto *AlignAA =
7761 [=](
const Attributor::ArgumentReplacementInfo &ARI,
7763 BasicBlock &EntryBB = ReplacementFn.getEntryBlock();
7765 const DataLayout &
DL = IP->getDataLayout();
7766 unsigned AS =
DL.getAllocaAddrSpace();
7767 Instruction *AI =
new AllocaInst(*PrivatizableType, AS,
7768 Arg->
getName() +
".priv", IP);
7769 createInitialization(*PrivatizableType, *AI, ReplacementFn,
7770 ArgIt->getArgNo(), IP);
7773 AI = BitCastInst::CreatePointerBitCastOrAddrSpaceCast(
7777 for (CallInst *CI : TailCalls)
7778 CI->setTailCall(
false);
7785 [=](
const Attributor::ArgumentReplacementInfo &ARI,
7786 AbstractCallSite ACS, SmallVectorImpl<Value *> &NewArgOperands) {
7789 createReplacementValues(
7790 AlignAA ? AlignAA->getAssumedAlign() :
Align(0),
7791 *PrivatizableType, ACS,
7799 identifyReplacementTypes(*PrivatizableType, ReplacementTypes);
7802 if (
A.registerFunctionSignatureRewrite(*Arg, ReplacementTypes,
7803 std::move(FnRepairCB),
7804 std::move(ACSRepairCB)))
7805 return ChangeStatus::CHANGED;
7806 return ChangeStatus::UNCHANGED;
7810 void trackStatistics()
const override {
7815struct AAPrivatizablePtrFloating :
public AAPrivatizablePtrImpl {
7816 AAPrivatizablePtrFloating(
const IRPosition &IRP, Attributor &
A)
7817 : AAPrivatizablePtrImpl(IRP,
A) {}
7822 indicatePessimisticFixpoint();
7827 "updateImpl will not be called");
7831 std::optional<Type *> identifyPrivatizableType(Attributor &
A)
override {
7834 LLVM_DEBUG(
dbgs() <<
"[AAPrivatizablePtr] No underlying object found!\n");
7841 return AI->getAllocatedType();
7843 auto *PrivArgAA =
A.getAAFor<AAPrivatizablePtr>(
7845 if (PrivArgAA && PrivArgAA->isAssumedPrivatizablePtr())
7846 return PrivArgAA->getPrivatizableType();
7849 LLVM_DEBUG(
dbgs() <<
"[AAPrivatizablePtr] Underlying object neither valid "
7850 "alloca nor privatizable argument: "
7856 void trackStatistics()
const override {
7861struct AAPrivatizablePtrCallSiteArgument final
7862 :
public AAPrivatizablePtrFloating {
7863 AAPrivatizablePtrCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
7864 : AAPrivatizablePtrFloating(IRP,
A) {}
7868 if (
A.hasAttr(getIRPosition(), Attribute::ByVal))
7869 indicateOptimisticFixpoint();
7874 PrivatizableType = identifyPrivatizableType(
A);
7875 if (!PrivatizableType)
7876 return ChangeStatus::UNCHANGED;
7877 if (!*PrivatizableType)
7878 return indicatePessimisticFixpoint();
7880 const IRPosition &IRP = getIRPosition();
7881 bool IsKnownNoCapture;
7883 A,
this, IRP, DepClassTy::REQUIRED, IsKnownNoCapture);
7884 if (!IsAssumedNoCapture) {
7885 LLVM_DEBUG(
dbgs() <<
"[AAPrivatizablePtr] pointer might be captured!\n");
7886 return indicatePessimisticFixpoint();
7889 bool IsKnownNoAlias;
7891 A,
this, IRP, DepClassTy::REQUIRED, IsKnownNoAlias)) {
7892 LLVM_DEBUG(
dbgs() <<
"[AAPrivatizablePtr] pointer might alias!\n");
7893 return indicatePessimisticFixpoint();
7898 LLVM_DEBUG(
dbgs() <<
"[AAPrivatizablePtr] pointer is written!\n");
7899 return indicatePessimisticFixpoint();
7902 return ChangeStatus::UNCHANGED;
7906 void trackStatistics()
const override {
7911struct AAPrivatizablePtrCallSiteReturned final
7912 :
public AAPrivatizablePtrFloating {
7913 AAPrivatizablePtrCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
7914 : AAPrivatizablePtrFloating(IRP,
A) {}
7919 indicatePessimisticFixpoint();
7923 void trackStatistics()
const override {
7928struct AAPrivatizablePtrReturned final :
public AAPrivatizablePtrFloating {
7929 AAPrivatizablePtrReturned(
const IRPosition &IRP, Attributor &
A)
7930 : AAPrivatizablePtrFloating(IRP,
A) {}
7935 indicatePessimisticFixpoint();
7939 void trackStatistics()
const override {
7949struct AAMemoryBehaviorImpl :
public AAMemoryBehavior {
7950 AAMemoryBehaviorImpl(
const IRPosition &IRP, Attributor &
A)
7951 : AAMemoryBehavior(IRP,
A) {}
7955 intersectAssumedBits(BEST_STATE);
7956 getKnownStateFromValue(
A, getIRPosition(), getState());
7957 AAMemoryBehavior::initialize(
A);
7961 static void getKnownStateFromValue(Attributor &
A,
const IRPosition &IRP,
7962 BitIntegerState &State,
7963 bool IgnoreSubsumingPositions =
false) {
7965 A.getAttrs(IRP, AttrKinds, Attrs, IgnoreSubsumingPositions);
7967 switch (Attr.getKindAsEnum()) {
7968 case Attribute::ReadNone:
7971 case Attribute::ReadOnly:
7974 case Attribute::WriteOnly:
7983 if (!
I->mayReadFromMemory())
7985 if (!
I->mayWriteToMemory())
7991 void getDeducedAttributes(Attributor &
A, LLVMContext &Ctx,
7992 SmallVectorImpl<Attribute> &Attrs)
const override {
7995 Attrs.push_back(Attribute::get(Ctx, Attribute::ReadNone));
7997 Attrs.push_back(Attribute::get(Ctx, Attribute::ReadOnly));
7998 else if (isAssumedWriteOnly())
7999 Attrs.push_back(Attribute::get(Ctx, Attribute::WriteOnly));
8005 const IRPosition &IRP = getIRPosition();
8007 if (
A.hasAttr(IRP, Attribute::ReadNone,
8009 return ChangeStatus::UNCHANGED;
8018 return ChangeStatus::UNCHANGED;
8021 A.removeAttrs(IRP, AttrKinds);
8024 A.removeAttrs(IRP, Attribute::Writable);
8031 const std::string getAsStr(Attributor *
A)
const override {
8036 if (isAssumedWriteOnly())
8038 return "may-read/write";
8042 static const Attribute::AttrKind AttrKinds[3];
8046 Attribute::ReadNone, Attribute::ReadOnly, Attribute::WriteOnly};
8049struct AAMemoryBehaviorFloating : AAMemoryBehaviorImpl {
8050 AAMemoryBehaviorFloating(
const IRPosition &IRP, Attributor &
A)
8051 : AAMemoryBehaviorImpl(IRP,
A) {}
8057 void trackStatistics()
const override {
8062 else if (isAssumedWriteOnly())
8069 bool followUsersOfUseIn(Attributor &
A,
const Use &U,
8070 const Instruction *UserI);
8073 void analyzeUseIn(Attributor &
A,
const Use &U,
const Instruction *UserI);
8077struct AAMemoryBehaviorArgument : AAMemoryBehaviorFloating {
8078 AAMemoryBehaviorArgument(
const IRPosition &IRP, Attributor &
A)
8079 : AAMemoryBehaviorFloating(IRP,
A) {}
8083 intersectAssumedBits(BEST_STATE);
8084 const IRPosition &IRP = getIRPosition();
8088 bool HasByVal =
A.hasAttr(IRP, {Attribute::ByVal},
8090 getKnownStateFromValue(
A, IRP, getState(),
8097 return ChangeStatus::UNCHANGED;
8101 if (
A.hasAttr(getIRPosition(),
8102 {Attribute::InAlloca, Attribute::Preallocated})) {
8103 removeKnownBits(NO_WRITES);
8104 removeAssumedBits(NO_WRITES);
8106 A.removeAttrs(getIRPosition(), AttrKinds);
8107 return AAMemoryBehaviorFloating::manifest(
A);
8111 void trackStatistics()
const override {
8116 else if (isAssumedWriteOnly())
8121struct AAMemoryBehaviorCallSiteArgument final : AAMemoryBehaviorArgument {
8122 AAMemoryBehaviorCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
8123 : AAMemoryBehaviorArgument(IRP,
A) {}
8129 Argument *Arg = getAssociatedArgument();
8131 indicatePessimisticFixpoint();
8135 addKnownBits(NO_WRITES);
8136 removeKnownBits(NO_READS);
8137 removeAssumedBits(NO_READS);
8139 AAMemoryBehaviorArgument::initialize(
A);
8140 if (getAssociatedFunction()->isDeclaration())
8141 indicatePessimisticFixpoint();
8150 Argument *Arg = getAssociatedArgument();
8153 A.getAAFor<AAMemoryBehavior>(*
this, ArgPos, DepClassTy::REQUIRED);
8155 return indicatePessimisticFixpoint();
8160 void trackStatistics()
const override {
8165 else if (isAssumedWriteOnly())
8171struct AAMemoryBehaviorCallSiteReturned final : AAMemoryBehaviorFloating {
8172 AAMemoryBehaviorCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
8173 : AAMemoryBehaviorFloating(IRP,
A) {}
8177 AAMemoryBehaviorImpl::initialize(
A);
8182 return ChangeStatus::UNCHANGED;
8186 void trackStatistics()
const override {}
8190struct AAMemoryBehaviorFunction final :
public AAMemoryBehaviorImpl {
8191 AAMemoryBehaviorFunction(
const IRPosition &IRP, Attributor &
A)
8192 : AAMemoryBehaviorImpl(IRP,
A) {}
8208 else if (isAssumedWriteOnly())
8211 A.removeAttrs(getIRPosition(), AttrKinds);
8214 for (Argument &Arg :
F.args())
8216 return A.manifestAttrs(getIRPosition(),
8217 Attribute::getWithMemoryEffects(
F.getContext(), ME));
8221 void trackStatistics()
const override {
8226 else if (isAssumedWriteOnly())
8232struct AAMemoryBehaviorCallSite final
8233 : AACalleeToCallSite<AAMemoryBehavior, AAMemoryBehaviorImpl> {
8234 AAMemoryBehaviorCallSite(
const IRPosition &IRP, Attributor &
A)
8235 : AACalleeToCallSite<AAMemoryBehavior, AAMemoryBehaviorImpl>(IRP,
A) {}
8246 else if (isAssumedWriteOnly())
8249 A.removeAttrs(getIRPosition(), AttrKinds);
8252 for (Use &U : CB.
args())
8254 Attribute::Writable);
8255 return A.manifestAttrs(
8256 getIRPosition(), Attribute::getWithMemoryEffects(CB.
getContext(), ME));
8260 void trackStatistics()
const override {
8265 else if (isAssumedWriteOnly())
8270ChangeStatus AAMemoryBehaviorFunction::updateImpl(Attributor &
A) {
8273 auto AssumedState = getAssumed();
8280 const auto *MemBehaviorAA =
A.getAAFor<AAMemoryBehavior>(
8282 if (MemBehaviorAA) {
8283 intersectAssumedBits(MemBehaviorAA->
getAssumed());
8284 return !isAtFixpoint();
8289 if (
I.mayReadFromMemory())
8290 removeAssumedBits(NO_READS);
8291 if (
I.mayWriteToMemory())
8292 removeAssumedBits(NO_WRITES);
8293 return !isAtFixpoint();
8296 bool UsedAssumedInformation =
false;
8297 if (!
A.checkForAllReadWriteInstructions(CheckRWInst, *
this,
8298 UsedAssumedInformation))
8299 return indicatePessimisticFixpoint();
8305ChangeStatus AAMemoryBehaviorFloating::updateImpl(Attributor &
A) {
8307 const IRPosition &IRP = getIRPosition();
8318 const auto *FnMemAA =
8321 FnMemAssumedState = FnMemAA->getAssumed();
8322 S.addKnownBits(FnMemAA->getKnown());
8323 if ((S.getAssumed() & FnMemAA->getAssumed()) == S.getAssumed())
8329 auto AssumedState = S.getAssumed();
8335 bool IsKnownNoCapture;
8336 const AANoCapture *ArgNoCaptureAA =
nullptr;
8341 if (!IsAssumedNoCapture &&
8343 S.intersectAssumedBits(FnMemAssumedState);
8349 auto UsePred = [&](
const Use &
U,
bool &Follow) ->
bool {
8351 LLVM_DEBUG(
dbgs() <<
"[AAMemoryBehavior] Use: " << *U <<
" in " << *UserI
8359 Follow = followUsersOfUseIn(
A, U, UserI);
8363 analyzeUseIn(
A, U, UserI);
8365 return !isAtFixpoint();
8368 if (!
A.checkForAllUses(UsePred, *
this, getAssociatedValue()))
8369 return indicatePessimisticFixpoint();
8375bool AAMemoryBehaviorFloating::followUsersOfUseIn(Attributor &
A,
const Use &U,
8376 const Instruction *UserI) {
8394 if (
U.get()->getType()->isPointerTy()) {
8396 bool IsKnownNoCapture;
8405void AAMemoryBehaviorFloating::analyzeUseIn(Attributor &
A,
const Use &U,
8406 const Instruction *UserI) {
8413 case Instruction::Load:
8415 removeAssumedBits(NO_READS);
8418 case Instruction::Store:
8423 removeAssumedBits(NO_WRITES);
8425 indicatePessimisticFixpoint();
8428 case Instruction::Call:
8429 case Instruction::CallBr:
8430 case Instruction::Invoke: {
8437 indicatePessimisticFixpoint();
8444 removeAssumedBits(NO_READS);
8451 if (
U.get()->getType()->isPointerTy())
8455 const auto *MemBehaviorAA =
8461 intersectAssumedBits(MemBehaviorAA->
getAssumed());
8469 removeAssumedBits(NO_READS);
8471 removeAssumedBits(NO_WRITES);
8483 return "all memory";
8486 std::string S =
"memory:";
8492 S +=
"internal global,";
8494 S +=
"external global,";
8498 S +=
"inaccessible,";
8512 AccessKind2Accesses.fill(
nullptr);
8515 ~AAMemoryLocationImpl()
override {
8518 for (AccessSet *AS : AccessKind2Accesses)
8525 intersectAssumedBits(BEST_STATE);
8526 getKnownStateFromValue(
A, getIRPosition(), getState());
8527 AAMemoryLocation::initialize(
A);
8531 static void getKnownStateFromValue(Attributor &
A,
const IRPosition &IRP,
8532 BitIntegerState &State,
8533 bool IgnoreSubsumingPositions =
false) {
8542 bool UseArgMemOnly =
true;
8544 if (AnchorFn &&
A.isRunOn(*AnchorFn))
8548 A.getAttrs(IRP, {Attribute::Memory},
Attrs, IgnoreSubsumingPositions);
8557 State.
addKnownBits(inverseLocation(NO_INACCESSIBLE_MEM,
true,
true));
8562 State.
addKnownBits(inverseLocation(NO_ARGUMENT_MEM,
true,
true));
8566 A.manifestAttrs(IRP,
8567 Attribute::getWithMemoryEffects(
8576 NO_INACCESSIBLE_MEM | NO_ARGUMENT_MEM,
true,
true));
8580 A.manifestAttrs(IRP,
8581 Attribute::getWithMemoryEffects(
8591 void getDeducedAttributes(Attributor &
A, LLVMContext &Ctx,
8592 SmallVectorImpl<Attribute> &Attrs)
const override {
8599 else if (isAssumedInaccessibleMemOnly())
8600 Attrs.push_back(Attribute::getWithMemoryEffects(
8602 else if (isAssumedArgMemOnly())
8605 else if (isAssumedInaccessibleOrArgMemOnly())
8606 Attrs.push_back(Attribute::getWithMemoryEffects(
8616 const IRPosition &IRP = getIRPosition();
8620 if (DeducedAttrs.
size() != 1)
8621 return ChangeStatus::UNCHANGED;
8624 return A.manifestAttrs(IRP, Attribute::getWithMemoryEffects(
8629 bool checkForAllAccessesToMemoryKind(
8631 MemoryLocationsKind)>
8633 MemoryLocationsKind RequestedMLK)
const override {
8634 if (!isValidState())
8637 MemoryLocationsKind AssumedMLK = getAssumedNotAccessedLocation();
8638 if (AssumedMLK == NO_LOCATIONS)
8642 for (MemoryLocationsKind CurMLK = 1; CurMLK < NO_LOCATIONS;
8643 CurMLK *= 2, ++
Idx) {
8644 if (CurMLK & RequestedMLK)
8647 if (
const AccessSet *
Accesses = AccessKind2Accesses[Idx])
8648 for (
const AccessInfo &AI : *
Accesses)
8649 if (!Pred(AI.I, AI.Ptr, AI.Kind, CurMLK))
8662 MemoryLocationsKind KnownMLK = getKnown();
8664 for (MemoryLocationsKind CurMLK = 1; CurMLK < NO_LOCATIONS; CurMLK *= 2)
8665 if (!(CurMLK & KnownMLK))
8666 updateStateAndAccessesMap(getState(), CurMLK,
I,
nullptr,
Changed,
8667 getAccessKindFromInst(
I));
8668 return AAMemoryLocation::indicatePessimisticFixpoint();
8688 bool operator()(
const AccessInfo &
LHS,
const AccessInfo &
RHS)
const {
8692 return LHS.Ptr <
RHS.Ptr;
8693 if (
LHS.Kind !=
RHS.Kind)
8694 return LHS.Kind <
RHS.Kind;
8701 using AccessSet = SmallSet<AccessInfo, 2, AccessInfo>;
8702 std::array<AccessSet *, llvm::ConstantLog2<VALID_STATE>()>
8703 AccessKind2Accesses;
8708 categorizeArgumentPointerLocations(Attributor &
A, CallBase &CB,
8709 AAMemoryLocation::StateType &AccessedLocs,
8714 categorizeAccessedLocations(Attributor &
A, Instruction &
I,
bool &
Changed);
8717 AccessKind getAccessKindFromInst(
const Instruction *
I) {
8720 AK =
I->mayReadFromMemory() ? READ :
NONE;
8729 void updateStateAndAccessesMap(AAMemoryLocation::StateType &State,
8730 MemoryLocationsKind MLK,
const Instruction *
I,
8739 if (MLK == NO_UNKOWN_MEM)
8741 State.removeAssumedBits(MLK);
8746 void categorizePtrValue(Attributor &
A,
const Instruction &
I,
const Value &Ptr,
8747 AAMemoryLocation::StateType &State,
bool &
Changed,
8748 unsigned AccessAS = 0);
8754void AAMemoryLocationImpl::categorizePtrValue(
8755 Attributor &
A,
const Instruction &
I,
const Value &Ptr,
8757 LLVM_DEBUG(
dbgs() <<
"[AAMemoryLocation] Categorize pointer locations for "
8762 unsigned ObjectAS =
Obj.getType()->getPointerAddressSpace();
8764 MemoryLocationsKind MLK = NO_LOCATIONS;
8784 MLK = NO_ARGUMENT_MEM;
8790 if (GVar->isConstant())
8793 if (GV->hasLocalLinkage())
8794 MLK = NO_GLOBAL_INTERNAL_MEM;
8796 MLK = NO_GLOBAL_EXTERNAL_MEM;
8804 bool IsKnownNoAlias;
8808 MLK = NO_MALLOCED_MEM;
8810 MLK = NO_UNKOWN_MEM;
8812 MLK = NO_UNKOWN_MEM;
8815 assert(MLK != NO_LOCATIONS &&
"No location specified!");
8816 LLVM_DEBUG(
dbgs() <<
"[AAMemoryLocation] Ptr value can be categorized: "
8817 << Obj <<
" -> " << getMemoryLocationsAsStr(MLK) <<
"\n");
8819 getAccessKindFromInst(&
I));
8824 const auto *AA =
A.getAAFor<AAUnderlyingObjects>(
8828 dbgs() <<
"[AAMemoryLocation] Pointer locations not categorized\n");
8829 updateStateAndAccessesMap(
State, NO_UNKOWN_MEM, &
I,
nullptr,
Changed,
8830 getAccessKindFromInst(&
I));
8835 dbgs() <<
"[AAMemoryLocation] Accessed locations with pointer locations: "
8839void AAMemoryLocationImpl::categorizeArgumentPointerLocations(
8842 for (
unsigned ArgNo = 0,
E = CB.
arg_size(); ArgNo <
E; ++ArgNo) {
8851 const auto *ArgOpMemLocationAA =
8854 if (ArgOpMemLocationAA && ArgOpMemLocationAA->isAssumedReadNone())
8859 categorizePtrValue(
A, CB, *ArgOp, AccessedLocs,
Changed);
8864AAMemoryLocationImpl::categorizeAccessedLocations(Attributor &
A, Instruction &
I,
8866 LLVM_DEBUG(
dbgs() <<
"[AAMemoryLocation] Categorize accessed locations for "
8870 AccessedLocs.intersectAssumedBits(NO_LOCATIONS);
8875 const auto *CBMemLocationAA =
A.getAAFor<AAMemoryLocation>(
8878 <<
" [" << CBMemLocationAA <<
"]\n");
8879 if (!CBMemLocationAA) {
8880 updateStateAndAccessesMap(AccessedLocs, NO_UNKOWN_MEM, &
I,
nullptr,
8881 Changed, getAccessKindFromInst(&
I));
8882 return NO_UNKOWN_MEM;
8885 if (CBMemLocationAA->isAssumedReadNone())
8886 return NO_LOCATIONS;
8888 if (CBMemLocationAA->isAssumedInaccessibleMemOnly()) {
8889 updateStateAndAccessesMap(AccessedLocs, NO_INACCESSIBLE_MEM, &
I,
nullptr,
8890 Changed, getAccessKindFromInst(&
I));
8891 return AccessedLocs.getAssumed();
8894 uint32_t CBAssumedNotAccessedLocs =
8895 CBMemLocationAA->getAssumedNotAccessedLocation();
8898 uint32_t CBAssumedNotAccessedLocsNoArgMem =
8899 CBAssumedNotAccessedLocs | NO_ARGUMENT_MEM | NO_GLOBAL_MEM;
8901 for (MemoryLocationsKind CurMLK = 1; CurMLK < NO_LOCATIONS; CurMLK *= 2) {
8902 if (CBAssumedNotAccessedLocsNoArgMem & CurMLK)
8904 updateStateAndAccessesMap(AccessedLocs, CurMLK, &
I,
nullptr,
Changed,
8905 getAccessKindFromInst(&
I));
8910 bool HasGlobalAccesses = ((~CBAssumedNotAccessedLocs) & NO_GLOBAL_MEM);
8911 if (HasGlobalAccesses) {
8914 updateStateAndAccessesMap(AccessedLocs, MLK, &
I, Ptr,
Changed,
8915 getAccessKindFromInst(&
I));
8918 if (!CBMemLocationAA->checkForAllAccessesToMemoryKind(
8919 AccessPred, inverseLocation(NO_GLOBAL_MEM,
false,
false)))
8920 return AccessedLocs.getWorstState();
8924 dbgs() <<
"[AAMemoryLocation] Accessed state before argument handling: "
8925 << getMemoryLocationsAsStr(AccessedLocs.getAssumed()) <<
"\n");
8928 bool HasArgAccesses = ((~CBAssumedNotAccessedLocs) & NO_ARGUMENT_MEM);
8930 categorizeArgumentPointerLocations(
A, *CB, AccessedLocs,
Changed);
8933 dbgs() <<
"[AAMemoryLocation] Accessed state after argument handling: "
8934 << getMemoryLocationsAsStr(AccessedLocs.getAssumed()) <<
"\n");
8936 return AccessedLocs.getAssumed();
8941 dbgs() <<
"[AAMemoryLocation] Categorize memory access with pointer: "
8942 <<
I <<
" [" << *Ptr <<
"]\n");
8943 categorizePtrValue(
A,
I, *Ptr, AccessedLocs,
Changed,
8944 Ptr->getType()->getPointerAddressSpace());
8945 return AccessedLocs.getAssumed();
8948 LLVM_DEBUG(
dbgs() <<
"[AAMemoryLocation] Failed to categorize instruction: "
8950 updateStateAndAccessesMap(AccessedLocs, NO_UNKOWN_MEM, &
I,
nullptr,
Changed,
8951 getAccessKindFromInst(&
I));
8952 return AccessedLocs.getAssumed();
8956struct AAMemoryLocationFunction final :
public AAMemoryLocationImpl {
8957 AAMemoryLocationFunction(
const IRPosition &IRP, Attributor &
A)
8958 : AAMemoryLocationImpl(IRP,
A) {}
8963 const auto *MemBehaviorAA =
8964 A.getAAFor<AAMemoryBehavior>(*
this, getIRPosition(), DepClassTy::NONE);
8967 return indicateOptimisticFixpoint();
8969 "AAMemoryLocation was not read-none but AAMemoryBehavior was!");
8970 A.recordDependence(*MemBehaviorAA, *
this, DepClassTy::OPTIONAL);
8971 return ChangeStatus::UNCHANGED;
8975 auto AssumedState = getAssumed();
8979 MemoryLocationsKind MLK = categorizeAccessedLocations(
A,
I,
Changed);
8980 LLVM_DEBUG(
dbgs() <<
"[AAMemoryLocation] Accessed locations for " <<
I
8981 <<
": " << getMemoryLocationsAsStr(MLK) <<
"\n");
8982 removeAssumedBits(inverseLocation(MLK,
false,
false));
8985 return getAssumedNotAccessedLocation() != VALID_STATE;
8988 bool UsedAssumedInformation =
false;
8989 if (!
A.checkForAllReadWriteInstructions(CheckRWInst, *
this,
8990 UsedAssumedInformation))
8991 return indicatePessimisticFixpoint();
8993 Changed |= AssumedState != getAssumed();
8994 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
8998 void trackStatistics()
const override {
9001 else if (isAssumedArgMemOnly())
9003 else if (isAssumedInaccessibleMemOnly())
9005 else if (isAssumedInaccessibleOrArgMemOnly())
9011struct AAMemoryLocationCallSite final : AAMemoryLocationImpl {
9012 AAMemoryLocationCallSite(
const IRPosition &IRP, Attributor &
A)
9013 : AAMemoryLocationImpl(IRP,
A) {}
9024 A.getAAFor<AAMemoryLocation>(*
this, FnPos, DepClassTy::REQUIRED);
9026 return indicatePessimisticFixpoint();
9030 updateStateAndAccessesMap(getState(), MLK,
I, Ptr,
Changed,
9031 getAccessKindFromInst(
I));
9034 if (!FnAA->checkForAllAccessesToMemoryKind(AccessPred, ALL_LOCATIONS))
9035 return indicatePessimisticFixpoint();
9036 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
9040 void trackStatistics()
const override {
9050struct AADenormalFPMathImpl :
public AADenormalFPMath {
9051 AADenormalFPMathImpl(
const IRPosition &IRP, Attributor &
A)
9052 : AADenormalFPMath(IRP,
A) {}
9054 const std::string getAsStr(Attributor *
A)
const override {
9055 std::string Str(
"AADenormalFPMath[");
9056 raw_string_ostream OS(Str);
9058 DenormalState
Known = getKnown();
9059 if (
Known.Mode.isValid())
9060 OS <<
"denormal-fp-math=" <<
Known.Mode;
9064 if (
Known.ModeF32.isValid())
9065 OS <<
" denormal-fp-math-f32=" <<
Known.ModeF32;
9071struct AADenormalFPMathFunction final : AADenormalFPMathImpl {
9072 AADenormalFPMathFunction(
const IRPosition &IRP, Attributor &
A)
9073 : AADenormalFPMathImpl(IRP,
A) {}
9077 DenormalFPEnv DenormEnv =
F->getDenormalFPEnv();
9087 auto CheckCallSite = [=, &Change, &
A](AbstractCallSite CS) {
9090 <<
"->" << getAssociatedFunction()->
getName() <<
'\n');
9092 const auto *CallerInfo =
A.getAAFor<AADenormalFPMath>(
9098 CallerInfo->getState());
9102 bool AllCallSitesKnown =
true;
9103 if (!
A.checkForAllCallSites(CheckCallSite, *
this,
true, AllCallSitesKnown))
9104 return indicatePessimisticFixpoint();
9106 if (Change == ChangeStatus::CHANGED && isModeFixed())
9112 LLVMContext &Ctx = getAssociatedFunction()->getContext();
9118 DenormalFPEnv KnownEnv(
Known.Mode,
Known.ModeF32);
9121 AttrToRemove.
push_back(Attribute::DenormalFPEnv);
9124 Ctx, Attribute::DenormalFPEnv,
9125 DenormalFPEnv(
Known.Mode,
Known.ModeF32).toIntValue()));
9128 auto &IRP = getIRPosition();
9131 return A.removeAttrs(IRP, AttrToRemove) |
9132 A.manifestAttrs(IRP, AttrToAdd,
true);
9135 void trackStatistics()
const override {
9144struct AAValueConstantRangeImpl : AAValueConstantRange {
9145 using StateType = IntegerRangeState;
9146 AAValueConstantRangeImpl(
const IRPosition &IRP, Attributor &
A)
9147 : AAValueConstantRange(IRP,
A) {}
9151 if (
A.hasSimplificationCallback(getIRPosition())) {
9152 indicatePessimisticFixpoint();
9157 intersectKnown(getConstantRangeFromSCEV(
A, getCtxI()));
9160 intersectKnown(getConstantRangeFromLVI(
A, getCtxI()));
9164 const std::string getAsStr(Attributor *
A)
const override {
9166 llvm::raw_string_ostream OS(Str);
9168 getKnown().print(OS);
9170 getAssumed().print(OS);
9177 const SCEV *getSCEV(Attributor &
A,
const Instruction *
I =
nullptr)
const {
9178 if (!getAnchorScope())
9181 ScalarEvolution *SE =
9182 A.getInfoCache().getAnalysisResultForFunction<ScalarEvolutionAnalysis>(
9185 LoopInfo *LI =
A.getInfoCache().getAnalysisResultForFunction<LoopAnalysis>(
9191 const SCEV *S = SE->
getSCEV(&getAssociatedValue());
9200 ConstantRange getConstantRangeFromSCEV(Attributor &
A,
9201 const Instruction *
I =
nullptr)
const {
9202 if (!getAnchorScope())
9205 ScalarEvolution *SE =
9206 A.getInfoCache().getAnalysisResultForFunction<ScalarEvolutionAnalysis>(
9209 const SCEV *S = getSCEV(
A,
I);
9219 getConstantRangeFromLVI(Attributor &
A,
9220 const Instruction *CtxI =
nullptr)
const {
9221 if (!getAnchorScope())
9224 LazyValueInfo *LVI =
9225 A.getInfoCache().getAnalysisResultForFunction<LazyValueAnalysis>(
9240 bool isValidCtxInstructionForOutsideAnalysis(Attributor &
A,
9241 const Instruction *CtxI,
9242 bool AllowAACtxI)
const {
9243 if (!CtxI || (!AllowAACtxI && CtxI == getCtxI()))
9255 InformationCache &InfoCache =
A.getInfoCache();
9256 const DominatorTree *DT =
9267 getAssumedConstantRange(Attributor &
A,
9268 const Instruction *CtxI =
nullptr)
const override {
9273 if (!isValidCtxInstructionForOutsideAnalysis(
A, CtxI,
9275 return getAssumed();
9277 ConstantRange LVIR = getConstantRangeFromLVI(
A, CtxI);
9278 ConstantRange SCEVR = getConstantRangeFromSCEV(
A, CtxI);
9279 return getAssumed().intersectWith(SCEVR).intersectWith(LVIR);
9284 getMDNodeForConstantRange(
Type *Ty, LLVMContext &Ctx,
9285 const ConstantRange &AssumedConstantRange) {
9287 Ty, AssumedConstantRange.
getLower())),
9289 Ty, AssumedConstantRange.
getUpper()))};
9294 static bool isBetterRange(
const ConstantRange &Assumed,
9295 const Instruction &
I) {
9299 std::optional<ConstantRange>
Known;
9303 }
else if (MDNode *KnownRanges =
I.getMetadata(LLVMContext::MD_range)) {
9309 if (KnownRanges->getNumOperands() > 2)
9312 ConstantInt *
Lower =
9314 ConstantInt *
Upper =
9324 setRangeMetadataIfisBetterRange(Instruction *
I,
9325 const ConstantRange &AssumedConstantRange) {
9326 if (isBetterRange(AssumedConstantRange, *
I)) {
9327 I->setMetadata(LLVMContext::MD_range,
9328 getMDNodeForConstantRange(
I->getType(),
I->getContext(),
9329 AssumedConstantRange));
9336 setRangeRetAttrIfisBetterRange(Attributor &
A,
const IRPosition &IRP,
9338 const ConstantRange &AssumedConstantRange) {
9339 if (isBetterRange(AssumedConstantRange, *
I)) {
9340 A.manifestAttrs(IRP,
9341 Attribute::get(
I->getContext(), Attribute::Range,
9342 AssumedConstantRange),
9352 ConstantRange AssumedConstantRange = getAssumedConstantRange(
A);
9355 auto &
V = getAssociatedValue();
9359 assert(
I == getCtxI() &&
"Should not annotate an instruction which is "
9360 "not the context instruction");
9362 if (setRangeMetadataIfisBetterRange(
I, AssumedConstantRange))
9363 Changed = ChangeStatus::CHANGED;
9365 if (setRangeRetAttrIfisBetterRange(
A, getIRPosition(),
I,
9366 AssumedConstantRange))
9367 Changed = ChangeStatus::CHANGED;
9375struct AAValueConstantRangeArgument final
9376 : AAArgumentFromCallSiteArguments<
9377 AAValueConstantRange, AAValueConstantRangeImpl, IntegerRangeState,
9379 using Base = AAArgumentFromCallSiteArguments<
9380 AAValueConstantRange, AAValueConstantRangeImpl, IntegerRangeState,
9382 AAValueConstantRangeArgument(
const IRPosition &IRP, Attributor &
A)
9386 void trackStatistics()
const override {
9391struct AAValueConstantRangeReturned
9392 : AAReturnedFromReturnedValues<AAValueConstantRange,
9393 AAValueConstantRangeImpl,
9394 AAValueConstantRangeImpl::StateType,
9397 AAReturnedFromReturnedValues<AAValueConstantRange,
9398 AAValueConstantRangeImpl,
9399 AAValueConstantRangeImpl::StateType,
9401 AAValueConstantRangeReturned(
const IRPosition &IRP, Attributor &
A)
9406 if (!
A.isFunctionIPOAmendable(*getAssociatedFunction()))
9407 indicatePessimisticFixpoint();
9411 void trackStatistics()
const override {
9416struct AAValueConstantRangeFloating : AAValueConstantRangeImpl {
9417 AAValueConstantRangeFloating(
const IRPosition &IRP, Attributor &
A)
9418 : AAValueConstantRangeImpl(IRP,
A) {}
9422 AAValueConstantRangeImpl::initialize(
A);
9426 Value &
V = getAssociatedValue();
9429 unionAssumed(ConstantRange(
C->getValue()));
9430 indicateOptimisticFixpoint();
9436 unionAssumed(ConstantRange(APInt(
getBitWidth(), 0)));
9437 indicateOptimisticFixpoint();
9449 if (
auto *RangeMD = LI->getMetadata(LLVMContext::MD_range)) {
9460 indicatePessimisticFixpoint();
9463 << getAssociatedValue() <<
"\n");
9466 bool calculateBinaryOperator(
9467 Attributor &
A, BinaryOperator *BinOp, IntegerRangeState &
T,
9468 const Instruction *CtxI,
9469 SmallVectorImpl<const AAValueConstantRange *> &QuerriedAAs) {
9474 bool UsedAssumedInformation =
false;
9475 const auto &SimplifiedLHS =
A.getAssumedSimplified(
9478 if (!SimplifiedLHS.has_value())
9480 if (!*SimplifiedLHS)
9482 LHS = *SimplifiedLHS;
9484 const auto &SimplifiedRHS =
A.getAssumedSimplified(
9487 if (!SimplifiedRHS.has_value())
9489 if (!*SimplifiedRHS)
9491 RHS = *SimplifiedRHS;
9497 auto *LHSAA =
A.getAAFor<AAValueConstantRange>(
9499 DepClassTy::REQUIRED);
9503 auto LHSAARange = LHSAA->getAssumedConstantRange(
A, CtxI);
9505 auto *RHSAA =
A.getAAFor<AAValueConstantRange>(
9507 DepClassTy::REQUIRED);
9511 auto RHSAARange = RHSAA->getAssumedConstantRange(
A, CtxI);
9513 auto AssumedRange = LHSAARange.binaryOp(BinOp->
getOpcode(), RHSAARange);
9515 T.unionAssumed(AssumedRange);
9519 return T.isValidState();
9522 bool calculateCastInst(
9523 Attributor &
A, CastInst *CastI, IntegerRangeState &
T,
9524 const Instruction *CtxI,
9525 SmallVectorImpl<const AAValueConstantRange *> &QuerriedAAs) {
9531 bool UsedAssumedInformation =
false;
9532 const auto &SimplifiedOpV =
A.getAssumedSimplified(
9535 if (!SimplifiedOpV.has_value())
9537 if (!*SimplifiedOpV)
9539 OpV = *SimplifiedOpV;
9544 auto *OpAA =
A.getAAFor<AAValueConstantRange>(
9546 DepClassTy::REQUIRED);
9550 T.unionAssumed(OpAA->getAssumed().castOp(CastI->
getOpcode(),
9552 return T.isValidState();
9556 calculateCmpInst(Attributor &
A, CmpInst *CmpI, IntegerRangeState &
T,
9557 const Instruction *CtxI,
9558 SmallVectorImpl<const AAValueConstantRange *> &QuerriedAAs) {
9563 bool UsedAssumedInformation =
false;
9564 const auto &SimplifiedLHS =
A.getAssumedSimplified(
9567 if (!SimplifiedLHS.has_value())
9569 if (!*SimplifiedLHS)
9571 LHS = *SimplifiedLHS;
9573 const auto &SimplifiedRHS =
A.getAssumedSimplified(
9576 if (!SimplifiedRHS.has_value())
9578 if (!*SimplifiedRHS)
9580 RHS = *SimplifiedRHS;
9586 auto *LHSAA =
A.getAAFor<AAValueConstantRange>(
9588 DepClassTy::REQUIRED);
9592 auto *RHSAA =
A.getAAFor<AAValueConstantRange>(
9594 DepClassTy::REQUIRED);
9598 auto LHSAARange = LHSAA->getAssumedConstantRange(
A, CtxI);
9599 auto RHSAARange = RHSAA->getAssumedConstantRange(
A, CtxI);
9602 if (LHSAARange.isEmptySet() || RHSAARange.isEmptySet())
9605 bool MustTrue =
false, MustFalse =
false;
9607 auto AllowedRegion =
9610 if (AllowedRegion.intersectWith(LHSAARange).isEmptySet())
9616 assert((!MustTrue || !MustFalse) &&
9617 "Either MustTrue or MustFalse should be false!");
9620 T.unionAssumed(ConstantRange(APInt( 1, 1)));
9622 T.unionAssumed(ConstantRange(APInt( 1, 0)));
9624 T.unionAssumed(ConstantRange( 1,
true));
9626 LLVM_DEBUG(
dbgs() <<
"[AAValueConstantRange] " << *CmpI <<
" after "
9627 << (MustTrue ?
"true" : (MustFalse ?
"false" :
"unknown"))
9628 <<
": " <<
T <<
"\n\t" << *LHSAA <<
"\t<op>\n\t"
9632 return T.isValidState();
9644 bool UsedAssumedInformation =
false;
9645 const auto &SimplifiedOpV =
A.getAssumedSimplified(
9648 if (!SimplifiedOpV.has_value())
9650 if (!*SimplifiedOpV)
9652 Value *VPtr = *SimplifiedOpV;
9655 const auto *AA =
A.getAAFor<AAValueConstantRange>(
9657 DepClassTy::REQUIRED);
9661 T.unionAssumed(AA->getAssumedConstantRange(
A, CtxI));
9665 return T.isValidState();
9670 if (!calculateBinaryOperator(
A, BinOp,
T, CtxI, QuerriedAAs))
9673 if (!calculateCmpInst(
A, CmpI,
T, CtxI, QuerriedAAs))
9676 if (!calculateCastInst(
A, CastI,
T, CtxI, QuerriedAAs))
9682 T.indicatePessimisticFixpoint();
9689 for (
const AAValueConstantRange *QueriedAA : QuerriedAAs) {
9690 if (QueriedAA !=
this)
9693 if (
T.getAssumed() == getState().getAssumed())
9695 T.indicatePessimisticFixpoint();
9698 return T.isValidState();
9701 if (!VisitValueCB(getAssociatedValue(), getCtxI()))
9702 return indicatePessimisticFixpoint();
9707 return ChangeStatus::UNCHANGED;
9708 if (++NumChanges > MaxNumChanges) {
9709 LLVM_DEBUG(
dbgs() <<
"[AAValueConstantRange] performed " << NumChanges
9710 <<
" but only " << MaxNumChanges
9711 <<
" are allowed to avoid cyclic reasoning.");
9712 return indicatePessimisticFixpoint();
9714 return ChangeStatus::CHANGED;
9718 void trackStatistics()
const override {
9727 static constexpr int MaxNumChanges = 5;
9730struct AAValueConstantRangeFunction : AAValueConstantRangeImpl {
9731 AAValueConstantRangeFunction(
const IRPosition &IRP, Attributor &
A)
9732 : AAValueConstantRangeImpl(IRP,
A) {}
9736 llvm_unreachable(
"AAValueConstantRange(Function|CallSite)::updateImpl will "
9744struct AAValueConstantRangeCallSite : AAValueConstantRangeFunction {
9745 AAValueConstantRangeCallSite(
const IRPosition &IRP, Attributor &
A)
9746 : AAValueConstantRangeFunction(IRP,
A) {}
9752struct AAValueConstantRangeCallSiteReturned
9753 : AACalleeToCallSite<AAValueConstantRange, AAValueConstantRangeImpl,
9754 AAValueConstantRangeImpl::StateType,
9756 AAValueConstantRangeCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
9757 : AACalleeToCallSite<AAValueConstantRange, AAValueConstantRangeImpl,
9758 AAValueConstantRangeImpl::StateType,
9765 if (std::optional<ConstantRange>
Range = CI->getRange())
9766 intersectKnown(*
Range);
9769 AAValueConstantRangeImpl::initialize(
A);
9773 void trackStatistics()
const override {
9777struct AAValueConstantRangeCallSiteArgument : AAValueConstantRangeFloating {
9778 AAValueConstantRangeCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
9779 : AAValueConstantRangeFloating(IRP,
A) {}
9783 return ChangeStatus::UNCHANGED;
9787 void trackStatistics()
const override {
9796struct AAPotentialConstantValuesImpl : AAPotentialConstantValues {
9799 AAPotentialConstantValuesImpl(
const IRPosition &IRP, Attributor &
A)
9800 : AAPotentialConstantValues(IRP,
A) {}
9804 if (
A.hasSimplificationCallback(getIRPosition()))
9805 indicatePessimisticFixpoint();
9807 AAPotentialConstantValues::initialize(
A);
9810 bool fillSetWithConstantValues(Attributor &
A,
const IRPosition &IRP, SetTy &S,
9811 bool &ContainsUndef,
bool ForSelf) {
9813 bool UsedAssumedInformation =
false;
9815 UsedAssumedInformation)) {
9822 auto *PotentialValuesAA =
A.getAAFor<AAPotentialConstantValues>(
9823 *
this, IRP, DepClassTy::REQUIRED);
9824 if (!PotentialValuesAA || !PotentialValuesAA->getState().isValidState())
9826 ContainsUndef = PotentialValuesAA->getState().undefIsContained();
9827 S = PotentialValuesAA->getState().getAssumedSet();
9834 ContainsUndef =
false;
9835 for (
auto &It :
Values) {
9837 ContainsUndef =
true;
9843 S.insert(CI->getValue());
9845 ContainsUndef &= S.empty();
9851 const std::string getAsStr(Attributor *
A)
const override {
9853 llvm::raw_string_ostream OS(Str);
9860 return indicatePessimisticFixpoint();
9864struct AAPotentialConstantValuesArgument final
9865 : AAArgumentFromCallSiteArguments<AAPotentialConstantValues,
9866 AAPotentialConstantValuesImpl,
9867 PotentialConstantIntValuesState> {
9868 using Base = AAArgumentFromCallSiteArguments<AAPotentialConstantValues,
9869 AAPotentialConstantValuesImpl,
9871 AAPotentialConstantValuesArgument(
const IRPosition &IRP, Attributor &
A)
9875 void trackStatistics()
const override {
9880struct AAPotentialConstantValuesReturned
9881 : AAReturnedFromReturnedValues<AAPotentialConstantValues,
9882 AAPotentialConstantValuesImpl> {
9883 using Base = AAReturnedFromReturnedValues<AAPotentialConstantValues,
9884 AAPotentialConstantValuesImpl>;
9885 AAPotentialConstantValuesReturned(
const IRPosition &IRP, Attributor &
A)
9889 if (!
A.isFunctionIPOAmendable(*getAssociatedFunction()))
9890 indicatePessimisticFixpoint();
9891 Base::initialize(
A);
9895 void trackStatistics()
const override {
9900struct AAPotentialConstantValuesFloating : AAPotentialConstantValuesImpl {
9901 AAPotentialConstantValuesFloating(
const IRPosition &IRP, Attributor &
A)
9902 : AAPotentialConstantValuesImpl(IRP,
A) {}
9906 AAPotentialConstantValuesImpl::initialize(
A);
9910 Value &
V = getAssociatedValue();
9913 unionAssumed(
C->getValue());
9914 indicateOptimisticFixpoint();
9919 unionAssumedWithUndef();
9920 indicateOptimisticFixpoint();
9930 indicatePessimisticFixpoint();
9933 << getAssociatedValue() <<
"\n");
9936 static bool calculateICmpInst(
const ICmpInst *ICI,
const APInt &
LHS,
9941 static APInt calculateCastInst(
const CastInst *CI,
const APInt &Src,
9942 uint32_t ResultBitWidth) {
9947 case Instruction::Trunc:
9948 return Src.trunc(ResultBitWidth);
9949 case Instruction::SExt:
9950 return Src.sext(ResultBitWidth);
9951 case Instruction::ZExt:
9952 return Src.zext(ResultBitWidth);
9953 case Instruction::BitCast:
9958 static APInt calculateBinaryOperator(
const BinaryOperator *BinOp,
9959 const APInt &
LHS,
const APInt &
RHS,
9960 bool &SkipOperation,
bool &Unsupported) {
9967 switch (BinOpcode) {
9971 case Instruction::Add:
9973 case Instruction::Sub:
9975 case Instruction::Mul:
9977 case Instruction::UDiv:
9979 SkipOperation =
true;
9983 case Instruction::SDiv:
9985 SkipOperation =
true;
9989 case Instruction::URem:
9991 SkipOperation =
true;
9995 case Instruction::SRem:
9997 SkipOperation =
true;
10001 case Instruction::Shl:
10003 case Instruction::LShr:
10005 case Instruction::AShr:
10007 case Instruction::And:
10009 case Instruction::Or:
10011 case Instruction::Xor:
10016 bool calculateBinaryOperatorAndTakeUnion(
const BinaryOperator *BinOp,
10017 const APInt &
LHS,
const APInt &
RHS) {
10018 bool SkipOperation =
false;
10021 calculateBinaryOperator(BinOp,
LHS,
RHS, SkipOperation, Unsupported);
10025 if (!SkipOperation)
10026 unionAssumed(Result);
10027 return isValidState();
10030 ChangeStatus updateWithICmpInst(Attributor &
A, ICmpInst *ICI) {
10031 auto AssumedBefore = getAssumed();
10035 bool LHSContainsUndef =
false, RHSContainsUndef =
false;
10036 SetTy LHSAAPVS, RHSAAPVS;
10038 LHSContainsUndef,
false) ||
10040 RHSContainsUndef,
false))
10041 return indicatePessimisticFixpoint();
10044 bool MaybeTrue =
false, MaybeFalse =
false;
10046 if (LHSContainsUndef && RHSContainsUndef) {
10049 unionAssumedWithUndef();
10050 }
else if (LHSContainsUndef) {
10051 for (
const APInt &R : RHSAAPVS) {
10052 bool CmpResult = calculateICmpInst(ICI, Zero, R);
10053 MaybeTrue |= CmpResult;
10054 MaybeFalse |= !CmpResult;
10055 if (MaybeTrue & MaybeFalse)
10056 return indicatePessimisticFixpoint();
10058 }
else if (RHSContainsUndef) {
10059 for (
const APInt &L : LHSAAPVS) {
10060 bool CmpResult = calculateICmpInst(ICI, L, Zero);
10061 MaybeTrue |= CmpResult;
10062 MaybeFalse |= !CmpResult;
10063 if (MaybeTrue & MaybeFalse)
10064 return indicatePessimisticFixpoint();
10067 for (
const APInt &L : LHSAAPVS) {
10068 for (
const APInt &R : RHSAAPVS) {
10069 bool CmpResult = calculateICmpInst(ICI, L, R);
10070 MaybeTrue |= CmpResult;
10071 MaybeFalse |= !CmpResult;
10072 if (MaybeTrue & MaybeFalse)
10073 return indicatePessimisticFixpoint();
10078 unionAssumed(APInt( 1, 1));
10080 unionAssumed(APInt( 1, 0));
10081 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10082 : ChangeStatus::CHANGED;
10085 ChangeStatus updateWithSelectInst(Attributor &
A, SelectInst *SI) {
10086 auto AssumedBefore = getAssumed();
10090 bool UsedAssumedInformation =
false;
10091 std::optional<Constant *>
C =
A.getAssumedConstant(
10092 *
SI->getCondition(), *
this, UsedAssumedInformation);
10095 bool OnlyLeft =
false, OnlyRight =
false;
10096 if (
C && *
C && (*C)->isOneValue())
10098 else if (
C && *
C && (*C)->isNullValue())
10101 bool LHSContainsUndef =
false, RHSContainsUndef =
false;
10102 SetTy LHSAAPVS, RHSAAPVS;
10105 LHSContainsUndef,
false))
10106 return indicatePessimisticFixpoint();
10110 RHSContainsUndef,
false))
10111 return indicatePessimisticFixpoint();
10113 if (OnlyLeft || OnlyRight) {
10115 auto *OpAA = OnlyLeft ? &LHSAAPVS : &RHSAAPVS;
10116 auto Undef = OnlyLeft ? LHSContainsUndef : RHSContainsUndef;
10119 unionAssumedWithUndef();
10121 for (
const auto &It : *OpAA)
10125 }
else if (LHSContainsUndef && RHSContainsUndef) {
10127 unionAssumedWithUndef();
10129 for (
const auto &It : LHSAAPVS)
10131 for (
const auto &It : RHSAAPVS)
10134 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10135 : ChangeStatus::CHANGED;
10138 ChangeStatus updateWithCastInst(Attributor &
A, CastInst *CI) {
10139 auto AssumedBefore = getAssumed();
10141 return indicatePessimisticFixpoint();
10146 bool SrcContainsUndef =
false;
10149 SrcContainsUndef,
false))
10150 return indicatePessimisticFixpoint();
10152 if (SrcContainsUndef)
10153 unionAssumedWithUndef();
10155 for (
const APInt &S : SrcPVS) {
10156 APInt
T = calculateCastInst(CI, S, ResultBitWidth);
10160 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10161 : ChangeStatus::CHANGED;
10164 ChangeStatus updateWithBinaryOperator(Attributor &
A, BinaryOperator *BinOp) {
10165 auto AssumedBefore = getAssumed();
10169 bool LHSContainsUndef =
false, RHSContainsUndef =
false;
10170 SetTy LHSAAPVS, RHSAAPVS;
10172 LHSContainsUndef,
false) ||
10174 RHSContainsUndef,
false))
10175 return indicatePessimisticFixpoint();
10180 if (LHSContainsUndef && RHSContainsUndef) {
10181 if (!calculateBinaryOperatorAndTakeUnion(BinOp, Zero, Zero))
10182 return indicatePessimisticFixpoint();
10183 }
else if (LHSContainsUndef) {
10184 for (
const APInt &R : RHSAAPVS) {
10185 if (!calculateBinaryOperatorAndTakeUnion(BinOp, Zero, R))
10186 return indicatePessimisticFixpoint();
10188 }
else if (RHSContainsUndef) {
10189 for (
const APInt &L : LHSAAPVS) {
10190 if (!calculateBinaryOperatorAndTakeUnion(BinOp, L, Zero))
10191 return indicatePessimisticFixpoint();
10194 for (
const APInt &L : LHSAAPVS) {
10195 for (
const APInt &R : RHSAAPVS) {
10196 if (!calculateBinaryOperatorAndTakeUnion(BinOp, L, R))
10197 return indicatePessimisticFixpoint();
10201 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10202 : ChangeStatus::CHANGED;
10205 ChangeStatus updateWithInstruction(Attributor &
A, Instruction *Inst) {
10206 auto AssumedBefore = getAssumed();
10208 bool ContainsUndef;
10210 ContainsUndef,
true))
10211 return indicatePessimisticFixpoint();
10212 if (ContainsUndef) {
10213 unionAssumedWithUndef();
10215 for (
const auto &It : Incoming)
10218 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10219 : ChangeStatus::CHANGED;
10224 Value &
V = getAssociatedValue();
10228 return updateWithICmpInst(
A, ICI);
10231 return updateWithSelectInst(
A, SI);
10234 return updateWithCastInst(
A, CI);
10237 return updateWithBinaryOperator(
A, BinOp);
10240 return updateWithInstruction(
A,
I);
10242 return indicatePessimisticFixpoint();
10246 void trackStatistics()
const override {
10251struct AAPotentialConstantValuesFunction : AAPotentialConstantValuesImpl {
10252 AAPotentialConstantValuesFunction(
const IRPosition &IRP, Attributor &
A)
10253 : AAPotentialConstantValuesImpl(IRP,
A) {}
10258 "AAPotentialConstantValues(Function|CallSite)::updateImpl will "
10263 void trackStatistics()
const override {
10268struct AAPotentialConstantValuesCallSite : AAPotentialConstantValuesFunction {
10269 AAPotentialConstantValuesCallSite(
const IRPosition &IRP, Attributor &
A)
10270 : AAPotentialConstantValuesFunction(IRP,
A) {}
10273 void trackStatistics()
const override {
10278struct AAPotentialConstantValuesCallSiteReturned
10279 : AACalleeToCallSite<AAPotentialConstantValues,
10280 AAPotentialConstantValuesImpl> {
10281 AAPotentialConstantValuesCallSiteReturned(
const IRPosition &IRP,
10283 : AACalleeToCallSite<AAPotentialConstantValues,
10284 AAPotentialConstantValuesImpl>(IRP,
A) {}
10287 void trackStatistics()
const override {
10292struct AAPotentialConstantValuesCallSiteArgument
10293 : AAPotentialConstantValuesFloating {
10294 AAPotentialConstantValuesCallSiteArgument(
const IRPosition &IRP,
10296 : AAPotentialConstantValuesFloating(IRP,
A) {}
10300 AAPotentialConstantValuesImpl::initialize(
A);
10301 if (isAtFixpoint())
10304 Value &
V = getAssociatedValue();
10307 unionAssumed(
C->getValue());
10308 indicateOptimisticFixpoint();
10313 unionAssumedWithUndef();
10314 indicateOptimisticFixpoint();
10321 Value &
V = getAssociatedValue();
10322 auto AssumedBefore = getAssumed();
10323 auto *AA =
A.getAAFor<AAPotentialConstantValues>(
10326 return indicatePessimisticFixpoint();
10327 const auto &S = AA->getAssumed();
10329 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10330 : ChangeStatus::CHANGED;
10334 void trackStatistics()
const override {
10343 bool IgnoreSubsumingPositions) {
10344 assert(ImpliedAttributeKind == Attribute::NoUndef &&
10345 "Unexpected attribute kind");
10346 if (
A.hasAttr(IRP, {Attribute::NoUndef}, IgnoreSubsumingPositions,
10347 Attribute::NoUndef))
10367 Value &V = getAssociatedValue();
10369 indicatePessimisticFixpoint();
10370 assert(!isImpliedByIR(
A, getIRPosition(), Attribute::NoUndef));
10374 bool followUseInMBEC(Attributor &
A,
const Use *U,
const Instruction *
I,
10375 AANoUndef::StateType &State) {
10376 const Value *UseV =
U->get();
10377 const DominatorTree *DT =
nullptr;
10378 AssumptionCache *AC =
nullptr;
10379 InformationCache &InfoCache =
A.getInfoCache();
10385 bool TrackUse =
false;
10394 const std::string getAsStr(Attributor *
A)
const override {
10395 return getAssumed() ?
"noundef" :
"may-undef-or-poison";
10402 bool UsedAssumedInformation =
false;
10403 if (
A.isAssumedDead(getIRPosition(),
nullptr,
nullptr,
10404 UsedAssumedInformation))
10405 return ChangeStatus::UNCHANGED;
10409 if (!
A.getAssumedSimplified(getIRPosition(), *
this, UsedAssumedInformation,
10412 return ChangeStatus::UNCHANGED;
10413 return AANoUndef::manifest(
A);
10417struct AANoUndefFloating :
public AANoUndefImpl {
10418 AANoUndefFloating(
const IRPosition &IRP, Attributor &
A)
10419 : AANoUndefImpl(IRP,
A) {}
10423 AANoUndefImpl::initialize(
A);
10424 if (!getState().isAtFixpoint() && getAnchorScope() &&
10425 !getAnchorScope()->isDeclaration())
10426 if (Instruction *CtxI = getCtxI())
10427 followUsesInMBEC(*
this,
A, getState(), *CtxI);
10432 auto VisitValueCB = [&](
const IRPosition &IRP) ->
bool {
10433 bool IsKnownNoUndef;
10435 A,
this, IRP, DepClassTy::REQUIRED, IsKnownNoUndef);
10439 bool UsedAssumedInformation =
false;
10440 Value *AssociatedValue = &getAssociatedValue();
10442 if (!
A.getAssumedSimplifiedValues(getIRPosition(), *
this,
Values,
10447 Values.size() != 1 ||
Values.front().getValue() != AssociatedValue;
10455 if (AVIRP == getIRPosition() || !VisitValueCB(AVIRP))
10456 return indicatePessimisticFixpoint();
10457 return ChangeStatus::UNCHANGED;
10460 for (
const auto &VAC :
Values)
10462 return indicatePessimisticFixpoint();
10464 return ChangeStatus::UNCHANGED;
10471struct AANoUndefReturned final
10472 : AAReturnedFromReturnedValues<AANoUndef, AANoUndefImpl> {
10473 AANoUndefReturned(
const IRPosition &IRP, Attributor &
A)
10474 : AAReturnedFromReturnedValues<AANoUndef, AANoUndefImpl>(IRP,
A) {}
10480struct AANoUndefArgument final
10481 : AAArgumentFromCallSiteArguments<AANoUndef, AANoUndefImpl> {
10482 AANoUndefArgument(
const IRPosition &IRP, Attributor &
A)
10483 : AAArgumentFromCallSiteArguments<AANoUndef, AANoUndefImpl>(IRP,
A) {}
10489struct AANoUndefCallSiteArgument final : AANoUndefFloating {
10490 AANoUndefCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
10491 : AANoUndefFloating(IRP,
A) {}
10497struct AANoUndefCallSiteReturned final
10498 : AACalleeToCallSite<AANoUndef, AANoUndefImpl> {
10499 AANoUndefCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
10500 : AACalleeToCallSite<AANoUndef, AANoUndefImpl>(IRP,
A) {}
10508struct AANoFPClassImpl : AANoFPClass {
10509 AANoFPClassImpl(
const IRPosition &IRP, Attributor &
A) : AANoFPClass(IRP,
A) {}
10512 const IRPosition &IRP = getIRPosition();
10516 indicateOptimisticFixpoint();
10521 A.getAttrs(getIRPosition(), {Attribute::NoFPClass},
Attrs,
false);
10522 for (
const auto &Attr : Attrs) {
10529 const DataLayout &
DL =
A.getDataLayout();
10530 InformationCache &InfoCache =
A.getInfoCache();
10532 const DominatorTree *DT =
nullptr;
10533 AssumptionCache *AC =
nullptr;
10534 const TargetLibraryInfo *TLI =
nullptr;
10538 if (!
F->isDeclaration()) {
10545 SimplifyQuery Q(
DL, TLI, DT, AC, CtxI);
10552 followUsesInMBEC(*
this,
A, getState(), *CtxI);
10556 bool followUseInMBEC(Attributor &
A,
const Use *U,
const Instruction *
I,
10557 AANoFPClass::StateType &State) {
10568 if (
auto *NoFPAA =
A.getAAFor<AANoFPClass>(*
this, IRP, DepClassTy::NONE))
10569 State.addKnownBits(NoFPAA->getState().getKnown());
10573 const std::string getAsStr(Attributor *
A)
const override {
10574 std::string
Result =
"nofpclass";
10575 raw_string_ostream OS(Result);
10576 OS << getKnownNoFPClass() <<
'/' << getAssumedNoFPClass();
10580 void getDeducedAttributes(Attributor &
A, LLVMContext &Ctx,
10581 SmallVectorImpl<Attribute> &Attrs)
const override {
10582 Attrs.emplace_back(Attribute::getWithNoFPClass(Ctx, getAssumedNoFPClass()));
10586struct AANoFPClassFloating :
public AANoFPClassImpl {
10587 AANoFPClassFloating(
const IRPosition &IRP, Attributor &
A)
10588 : AANoFPClassImpl(IRP,
A) {}
10593 bool UsedAssumedInformation =
false;
10594 if (!
A.getAssumedSimplifiedValues(getIRPosition(), *
this,
Values,
10596 Values.push_back({getAssociatedValue(), getCtxI()});
10602 DepClassTy::REQUIRED);
10603 if (!AA ||
this == AA) {
10604 T.indicatePessimisticFixpoint();
10606 const AANoFPClass::StateType &S =
10607 static_cast<const AANoFPClass::StateType &
>(AA->
getState());
10610 return T.isValidState();
10613 for (
const auto &VAC :
Values)
10615 return indicatePessimisticFixpoint();
10621 void trackStatistics()
const override {
10626struct AANoFPClassReturned final
10627 : AAReturnedFromReturnedValues<AANoFPClass, AANoFPClassImpl,
10628 AANoFPClassImpl::StateType, false,
10629 Attribute::None, false> {
10630 AANoFPClassReturned(
const IRPosition &IRP, Attributor &
A)
10631 : AAReturnedFromReturnedValues<AANoFPClass, AANoFPClassImpl,
10632 AANoFPClassImpl::StateType,
false,
10636 void trackStatistics()
const override {
10641struct AANoFPClassArgument final
10642 : AAArgumentFromCallSiteArguments<AANoFPClass, AANoFPClassImpl> {
10643 AANoFPClassArgument(
const IRPosition &IRP, Attributor &
A)
10644 : AAArgumentFromCallSiteArguments<AANoFPClass, AANoFPClassImpl>(IRP,
A) {}
10650struct AANoFPClassCallSiteArgument final : AANoFPClassFloating {
10651 AANoFPClassCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
10652 : AANoFPClassFloating(IRP,
A) {}
10655 void trackStatistics()
const override {
10660struct AANoFPClassCallSiteReturned final
10661 : AACalleeToCallSite<AANoFPClass, AANoFPClassImpl> {
10662 AANoFPClassCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
10663 : AACalleeToCallSite<AANoFPClass, AANoFPClassImpl>(IRP,
A) {}
10666 void trackStatistics()
const override {
10671struct AACallEdgesImpl :
public AACallEdges {
10672 AACallEdgesImpl(
const IRPosition &IRP, Attributor &
A) : AACallEdges(IRP,
A) {}
10674 const SetVector<Function *> &getOptimisticEdges()
const override {
10675 return CalledFunctions;
10678 bool hasUnknownCallee()
const override {
return HasUnknownCallee; }
10680 bool hasNonAsmUnknownCallee()
const override {
10681 return HasUnknownCalleeNonAsm;
10684 const std::string getAsStr(Attributor *
A)
const override {
10685 return "CallEdges[" + std::to_string(HasUnknownCallee) +
"," +
10686 std::to_string(CalledFunctions.size()) +
"]";
10689 void trackStatistics()
const override {}
10693 if (CalledFunctions.insert(Fn)) {
10694 Change = ChangeStatus::CHANGED;
10700 void setHasUnknownCallee(
bool NonAsm,
ChangeStatus &Change) {
10701 if (!HasUnknownCallee)
10702 Change = ChangeStatus::CHANGED;
10703 if (NonAsm && !HasUnknownCalleeNonAsm)
10704 Change = ChangeStatus::CHANGED;
10705 HasUnknownCalleeNonAsm |= NonAsm;
10706 HasUnknownCallee =
true;
10711 SetVector<Function *> CalledFunctions;
10714 bool HasUnknownCallee =
false;
10717 bool HasUnknownCalleeNonAsm =
false;
10720struct AACallEdgesCallSite :
public AACallEdgesImpl {
10721 AACallEdgesCallSite(
const IRPosition &IRP, Attributor &
A)
10722 : AACallEdgesImpl(IRP,
A) {}
10729 addCalledFunction(Fn, Change);
10731 LLVM_DEBUG(
dbgs() <<
"[AACallEdges] Unrecognized value: " << V <<
"\n");
10732 setHasUnknownCallee(
true, Change);
10743 VisitValue(*V, CtxI);
10747 bool UsedAssumedInformation =
false;
10751 Values.push_back({*
V, CtxI});
10753 for (
auto &VAC :
Values)
10760 if (
IA->hasSideEffects() &&
10763 setHasUnknownCallee(
false, Change);
10769 if (
auto *IndirectCallAA =
A.getAAFor<AAIndirectCallInfo>(
10770 *
this, getIRPosition(), DepClassTy::OPTIONAL))
10771 if (IndirectCallAA->foreachCallee(
10772 [&](
Function *Fn) { return VisitValue(*Fn, CB); }))
10781 for (
const Use *U : CallbackUses)
10782 ProcessCalledOperand(
U->get(), CB);
10788struct AACallEdgesFunction :
public AACallEdgesImpl {
10789 AACallEdgesFunction(
const IRPosition &IRP, Attributor &
A)
10790 : AACallEdgesImpl(IRP,
A) {}
10799 auto *CBEdges =
A.getAAFor<AACallEdges>(
10803 if (CBEdges->hasNonAsmUnknownCallee())
10804 setHasUnknownCallee(
true, Change);
10805 if (CBEdges->hasUnknownCallee())
10806 setHasUnknownCallee(
false, Change);
10808 for (
Function *
F : CBEdges->getOptimisticEdges())
10809 addCalledFunction(
F, Change);
10815 bool UsedAssumedInformation =
false;
10816 if (!
A.checkForAllCallLikeInstructions(ProcessCallInst, *
this,
10817 UsedAssumedInformation,
10821 setHasUnknownCallee(
true, Change);
10830struct AAInterFnReachabilityFunction
10831 :
public CachedReachabilityAA<AAInterFnReachability, Function> {
10832 using Base = CachedReachabilityAA<AAInterFnReachability, Function>;
10833 AAInterFnReachabilityFunction(
const IRPosition &IRP, Attributor &
A)
10836 bool instructionCanReach(
10837 Attributor &
A,
const Instruction &From,
const Function &To,
10840 auto *NonConstThis =
const_cast<AAInterFnReachabilityFunction *
>(
this);
10842 RQITy StackRQI(
A, From, To, ExclusionSet,
false);
10843 RQITy::Reachable
Result;
10844 if (!NonConstThis->checkQueryCache(
A, StackRQI, Result))
10845 return NonConstThis->isReachableImpl(
A, StackRQI,
10847 return Result == RQITy::Reachable::Yes;
10851 bool IsTemporaryRQI)
override {
10853 &RQI.From->getFunction()->getEntryBlock().front();
10854 if (EntryI != RQI.From &&
10855 !instructionCanReach(
A, *EntryI, *RQI.To,
nullptr))
10856 return rememberResult(
A, RQITy::Reachable::No, RQI,
false,
10859 auto CheckReachableCallBase = [&](CallBase *CB) {
10860 auto *CBEdges =
A.getAAFor<AACallEdges>(
10862 if (!CBEdges || !CBEdges->getState().isValidState())
10865 if (CBEdges->hasUnknownCallee())
10868 for (
Function *Fn : CBEdges->getOptimisticEdges()) {
10879 if (Fn == getAnchorScope()) {
10880 if (EntryI == RQI.From)
10885 const AAInterFnReachability *InterFnReachability =
10887 DepClassTy::OPTIONAL);
10890 if (!InterFnReachability ||
10898 const auto *IntraFnReachability =
A.getAAFor<AAIntraFnReachability>(
10900 DepClassTy::OPTIONAL);
10908 return IntraFnReachability && !IntraFnReachability->isAssumedReachable(
10909 A, *RQI.From, CBInst, RQI.ExclusionSet);
10912 bool UsedExclusionSet =
true;
10913 bool UsedAssumedInformation =
false;
10914 if (!
A.checkForAllCallLikeInstructions(CheckCallBase, *
this,
10915 UsedAssumedInformation,
10917 return rememberResult(
A, RQITy::Reachable::Yes, RQI, UsedExclusionSet,
10920 return rememberResult(
A, RQITy::Reachable::No, RQI, UsedExclusionSet,
10924 void trackStatistics()
const override {}
10928template <
typename AAType>
10929static std::optional<Constant *>
10932 if (!Ty.isIntegerTy())
10940 std::optional<Constant *> COpt =
AA->getAssumedConstant(
A);
10942 if (!COpt.has_value()) {
10944 return std::nullopt;
10946 if (
auto *
C = *COpt) {
10957 std::optional<Value *> V;
10958 for (
auto &It :
Values) {
10960 if (V.has_value() && !*V)
10963 if (!V.has_value())
10977 if (
A.hasSimplificationCallback(getIRPosition())) {
10978 indicatePessimisticFixpoint();
10981 Value *Stripped = getAssociatedValue().stripPointerCasts();
10983 addValue(
A, getState(), *Stripped, getCtxI(),
AA::AnyScope,
10985 indicateOptimisticFixpoint();
10988 AAPotentialValues::initialize(
A);
10992 const std::string getAsStr(Attributor *
A)
const override {
10994 llvm::raw_string_ostream OS(Str);
10999 template <
typename AAType>
11000 static std::optional<Value *> askOtherAA(Attributor &
A,
11001 const AbstractAttribute &AA,
11002 const IRPosition &IRP,
Type &Ty) {
11007 return std::nullopt;
11014 virtual void addValue(Attributor &
A, StateType &State,
Value &V,
11020 for (
const auto &U : CB->
args()) {
11030 Type &Ty = *getAssociatedType();
11031 std::optional<Value *> SimpleV =
11032 askOtherAA<AAValueConstantRange>(
A, *
this, ValIRP, Ty);
11033 if (SimpleV.has_value() && !*SimpleV) {
11034 auto *PotentialConstantsAA =
A.getAAFor<AAPotentialConstantValues>(
11035 *
this, ValIRP, DepClassTy::OPTIONAL);
11036 if (PotentialConstantsAA && PotentialConstantsAA->isValidState()) {
11037 for (
const auto &It : PotentialConstantsAA->getAssumedSet())
11038 State.unionAssumed({{*ConstantInt::get(&Ty, It),
nullptr}, S});
11039 if (PotentialConstantsAA->undefIsContained())
11044 if (!SimpleV.has_value())
11056 State.unionAssumed({{*VPtr, CtxI}, S});
11062 AA::ValueAndContext
I;
11066 return II.I ==
I &&
II.S == S;
11069 return std::tie(
I, S) < std::tie(
II.I,
II.S);
11073 bool recurseForValue(Attributor &
A,
const IRPosition &IRP,
AA::ValueScope S) {
11074 SmallMapVector<AA::ValueAndContext, int, 8> ValueScopeMap;
11079 bool UsedAssumedInformation =
false;
11081 if (!
A.getAssumedSimplifiedValues(IRP,
this,
Values, CS,
11082 UsedAssumedInformation))
11086 ValueScopeMap[It] += CS;
11088 for (
auto &It : ValueScopeMap)
11089 addValue(
A, getState(), *It.first.getValue(), It.first.getCtxI(),
11095 void giveUpOnIntraprocedural(Attributor &
A) {
11096 auto NewS = StateType::getBestState(getState());
11097 for (
const auto &It : getAssumedSet()) {
11100 addValue(
A, NewS, *It.first.getValue(), It.first.getCtxI(),
11103 assert(!undefIsContained() &&
"Undef should be an explicit value!");
11111 getState() = StateType::getBestState(getState());
11112 getState().unionAssumed({{getAssociatedValue(), getCtxI()},
AA::AnyScope});
11113 AAPotentialValues::indicateOptimisticFixpoint();
11114 return ChangeStatus::CHANGED;
11119 return indicatePessimisticFixpoint();
11127 if (!getAssumedSimplifiedValues(
A,
Values, S))
11129 Value &OldV = getAssociatedValue();
11132 Value *NewV = getSingleValue(
A, *
this, getIRPosition(),
Values);
11133 if (!NewV || NewV == &OldV)
11138 if (
A.changeAfterManifest(getIRPosition(), *NewV))
11139 return ChangeStatus::CHANGED;
11141 return ChangeStatus::UNCHANGED;
11144 bool getAssumedSimplifiedValues(
11145 Attributor &
A, SmallVectorImpl<AA::ValueAndContext> &
Values,
11146 AA::ValueScope S,
bool RecurseForSelectAndPHI =
false)
const override {
11147 if (!isValidState())
11149 bool UsedAssumedInformation =
false;
11150 for (
const auto &It : getAssumedSet())
11151 if (It.second & S) {
11152 if (RecurseForSelectAndPHI && (
isa<PHINode>(It.first.getValue()) ||
11154 if (
A.getAssumedSimplifiedValues(
11156 this,
Values, S, UsedAssumedInformation))
11159 Values.push_back(It.first);
11161 assert(!undefIsContained() &&
"Undef should be an explicit value!");
11166struct AAPotentialValuesFloating : AAPotentialValuesImpl {
11167 AAPotentialValuesFloating(
const IRPosition &IRP, Attributor &
A)
11168 : AAPotentialValuesImpl(IRP,
A) {}
11172 auto AssumedBefore = getAssumed();
11174 genericValueTraversal(
A, &getAssociatedValue());
11176 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
11177 : ChangeStatus::CHANGED;
11181 struct LivenessInfo {
11182 const AAIsDead *LivenessAA =
nullptr;
11183 bool AnyDead =
false;
11193 SmallVectorImpl<ItemInfo> &Worklist) {
11196 bool UsedAssumedInformation =
false;
11198 auto GetSimplifiedValues = [&](
Value &
V,
11200 if (!
A.getAssumedSimplifiedValues(
11204 Values.push_back(AA::ValueAndContext{
V,
II.I.getCtxI()});
11208 if (GetSimplifiedValues(*
LHS, LHSValues))
11210 if (GetSimplifiedValues(*
RHS, RHSValues))
11215 InformationCache &InfoCache =
A.getInfoCache();
11222 F ?
A.getInfoCache().getTargetLibraryInfoForFunction(*
F) :
nullptr;
11227 const DataLayout &
DL =
A.getDataLayout();
11228 SimplifyQuery Q(
DL, TLI, DT, AC, CmpI);
11230 auto CheckPair = [&](
Value &LHSV,
Value &RHSV) {
11233 nullptr,
II.S, getAnchorScope());
11239 if (&LHSV == &RHSV &&
11241 Constant *NewV = ConstantInt::get(Type::getInt1Ty(Ctx),
11243 addValue(
A, getState(), *NewV,
nullptr,
II.S,
11250 if (TypedLHS && TypedRHS) {
11252 if (NewV && NewV != &Cmp) {
11253 addValue(
A, getState(), *NewV,
nullptr,
II.S,
11265 if (!LHSIsNull && !RHSIsNull)
11271 assert((LHSIsNull || RHSIsNull) &&
11272 "Expected nullptr versus non-nullptr comparison at this point");
11275 unsigned PtrIdx = LHSIsNull;
11276 bool IsKnownNonNull;
11279 DepClassTy::REQUIRED, IsKnownNonNull);
11280 if (!IsAssumedNonNull)
11286 addValue(
A, getState(), *NewV,
nullptr,
II.S,
11291 for (
auto &LHSValue : LHSValues)
11292 for (
auto &RHSValue : RHSValues)
11293 if (!CheckPair(*LHSValue.getValue(), *RHSValue.getValue()))
11298 bool handleSelectInst(Attributor &
A, SelectInst &SI, ItemInfo
II,
11299 SmallVectorImpl<ItemInfo> &Worklist) {
11301 bool UsedAssumedInformation =
false;
11303 std::optional<Constant *>
C =
11304 A.getAssumedConstant(*
SI.getCondition(), *
this, UsedAssumedInformation);
11305 bool NoValueYet = !
C.has_value();
11313 }
else if (&SI == &getAssociatedValue()) {
11318 std::optional<Value *> SimpleV =
A.getAssumedSimplified(
11320 if (!SimpleV.has_value())
11323 addValue(
A, getState(), **SimpleV, CtxI,
II.S, getAnchorScope());
11331 bool handleLoadInst(Attributor &
A, LoadInst &LI, ItemInfo
II,
11332 SmallVectorImpl<ItemInfo> &Worklist) {
11333 SmallSetVector<Value *, 4> PotentialCopies;
11334 SmallSetVector<Instruction *, 4> PotentialValueOrigins;
11335 bool UsedAssumedInformation =
false;
11337 PotentialValueOrigins, *
this,
11338 UsedAssumedInformation,
11340 LLVM_DEBUG(
dbgs() <<
"[AAPotentialValues] Failed to get potentially "
11341 "loaded values for load instruction "
11349 InformationCache &InfoCache =
A.getInfoCache();
11351 if (!
llvm::all_of(PotentialValueOrigins, [&](Instruction *
I) {
11355 return A.isAssumedDead(
SI->getOperandUse(0),
this,
11357 UsedAssumedInformation,
11359 return A.isAssumedDead(*
I,
this,
nullptr,
11360 UsedAssumedInformation,
11363 LLVM_DEBUG(
dbgs() <<
"[AAPotentialValues] Load is onl used by assumes "
11364 "and we cannot delete all the stores: "
11375 bool AllLocal = ScopeIsLocal;
11380 if (!DynamicallyUnique) {
11381 LLVM_DEBUG(
dbgs() <<
"[AAPotentialValues] Not all potentially loaded "
11382 "values are dynamically unique: "
11387 for (
auto *PotentialCopy : PotentialCopies) {
11389 Worklist.
push_back({{*PotentialCopy, CtxI},
II.S});
11394 if (!AllLocal && ScopeIsLocal)
11399 bool handlePHINode(
11400 Attributor &
A, PHINode &
PHI, ItemInfo
II,
11401 SmallVectorImpl<ItemInfo> &Worklist,
11402 SmallMapVector<const Function *, LivenessInfo, 4> &LivenessAAs) {
11403 auto GetLivenessInfo = [&](
const Function &
F) -> LivenessInfo & {
11404 LivenessInfo &LI = LivenessAAs[&
F];
11405 if (!LI.LivenessAA)
11411 if (&
PHI == &getAssociatedValue()) {
11412 LivenessInfo &LI = GetLivenessInfo(*
PHI.getFunction());
11414 A.getInfoCache().getAnalysisResultForFunction<CycleAnalysis>(
11415 *
PHI.getFunction());
11419 for (
unsigned u = 0, e =
PHI.getNumIncomingValues(); u < e; u++) {
11421 if (LI.LivenessAA &&
11422 LI.LivenessAA->isEdgeDead(IncomingBB,
PHI.getParent())) {
11441 bool UsedAssumedInformation =
false;
11442 std::optional<Value *> SimpleV =
A.getAssumedSimplified(
11444 if (!SimpleV.has_value())
11448 addValue(
A, getState(), **SimpleV, &
PHI,
II.S, getAnchorScope());
11455 bool handleGenericInst(Attributor &
A, Instruction &
I, ItemInfo
II,
11456 SmallVectorImpl<ItemInfo> &Worklist) {
11457 bool SomeSimplified =
false;
11458 bool UsedAssumedInformation =
false;
11460 SmallVector<Value *, 8> NewOps(
I.getNumOperands());
11463 const auto &SimplifiedOp =
A.getAssumedSimplified(
11468 if (!SimplifiedOp.has_value())
11472 NewOps[
Idx] = *SimplifiedOp;
11476 SomeSimplified |= (NewOps[
Idx] !=
Op);
11482 if (!SomeSimplified)
11485 InformationCache &InfoCache =
A.getInfoCache();
11489 const auto *TLI =
A.getInfoCache().getTargetLibraryInfoForFunction(*
F);
11492 const DataLayout &
DL =
I.getDataLayout();
11493 SimplifyQuery Q(
DL, TLI, DT, AC, &
I);
11495 if (!NewV || NewV == &
I)
11498 LLVM_DEBUG(
dbgs() <<
"Generic inst " <<
I <<
" assumed simplified to "
11505 Attributor &
A, Instruction &
I, ItemInfo
II,
11506 SmallVectorImpl<ItemInfo> &Worklist,
11507 SmallMapVector<const Function *, LivenessInfo, 4> &LivenessAAs) {
11510 CI->getPredicate(),
II, Worklist);
11512 switch (
I.getOpcode()) {
11513 case Instruction::Select:
11515 case Instruction::PHI:
11517 case Instruction::Load:
11520 return handleGenericInst(
A,
I,
II, Worklist);
11525 void genericValueTraversal(Attributor &
A,
Value *InitialV) {
11526 SmallMapVector<const Function *, LivenessInfo, 4> LivenessAAs;
11528 SmallSet<ItemInfo, 16> Visited;
11547 LLVM_DEBUG(
dbgs() <<
"Generic value traversal reached iteration limit: "
11548 << Iteration <<
"!\n");
11549 addValue(
A, getState(), *V, CtxI, S, getAnchorScope());
11555 Value *NewV =
nullptr;
11556 if (
V->getType()->isPointerTy()) {
11562 for (Argument &Arg :
Callee->args())
11569 if (NewV && NewV != V) {
11570 Worklist.
push_back({{*NewV, CtxI}, S});
11584 if (V == InitialV && CtxI == getCtxI()) {
11585 indicatePessimisticFixpoint();
11589 addValue(
A, getState(), *V, CtxI, S, getAnchorScope());
11590 }
while (!Worklist.
empty());
11594 for (
auto &It : LivenessAAs)
11595 if (It.second.AnyDead)
11596 A.recordDependence(*It.second.LivenessAA, *
this, DepClassTy::OPTIONAL);
11600 void trackStatistics()
const override {
11605struct AAPotentialValuesArgument final : AAPotentialValuesImpl {
11606 using Base = AAPotentialValuesImpl;
11607 AAPotentialValuesArgument(
const IRPosition &IRP, Attributor &
A)
11614 indicatePessimisticFixpoint();
11619 auto AssumedBefore = getAssumed();
11621 unsigned ArgNo = getCalleeArgNo();
11623 bool UsedAssumedInformation =
false;
11625 auto CallSitePred = [&](AbstractCallSite ACS) {
11627 if (CSArgIRP.getPositionKind() == IRP_INVALID)
11630 if (!
A.getAssumedSimplifiedValues(CSArgIRP,
this,
Values,
11632 UsedAssumedInformation))
11635 return isValidState();
11638 if (!
A.checkForAllCallSites(CallSitePred, *
this,
11640 UsedAssumedInformation))
11641 return indicatePessimisticFixpoint();
11643 Function *Fn = getAssociatedFunction();
11644 bool AnyNonLocal =
false;
11645 for (
auto &It :
Values) {
11647 addValue(
A, getState(), *It.getValue(), It.getCtxI(),
AA::AnyScope,
11652 return indicatePessimisticFixpoint();
11656 addValue(
A, getState(), *It.getValue(), It.getCtxI(),
AA::AnyScope,
11662 AnyNonLocal =
true;
11664 assert(!undefIsContained() &&
"Undef should be an explicit value!");
11666 giveUpOnIntraprocedural(
A);
11668 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
11669 : ChangeStatus::CHANGED;
11673 void trackStatistics()
const override {
11678struct AAPotentialValuesReturned :
public AAPotentialValuesFloating {
11679 using Base = AAPotentialValuesFloating;
11680 AAPotentialValuesReturned(
const IRPosition &IRP, Attributor &
A)
11686 if (!
F ||
F->isDeclaration() ||
F->getReturnType()->isVoidTy()) {
11687 indicatePessimisticFixpoint();
11691 for (Argument &Arg :
F->args())
11694 ReturnedArg = &Arg;
11697 if (!
A.isFunctionIPOAmendable(*
F) ||
11698 A.hasSimplificationCallback(getIRPosition())) {
11700 indicatePessimisticFixpoint();
11702 indicateOptimisticFixpoint();
11708 auto AssumedBefore = getAssumed();
11709 bool UsedAssumedInformation =
false;
11712 Function *AnchorScope = getAnchorScope();
11718 UsedAssumedInformation,
11724 bool AllInterAreIntra =
false;
11731 for (
const AA::ValueAndContext &VAC :
Values) {
11732 addValue(
A, getState(), *VAC.
getValue(),
11736 if (AllInterAreIntra)
11743 HandleReturnedValue(*ReturnedArg,
nullptr,
true);
11746 bool AddValues =
true;
11749 addValue(
A, getState(), *RetI.getOperand(0), &RetI,
AA::AnyScope,
11753 return HandleReturnedValue(*RetI.getOperand(0), &RetI, AddValues);
11756 if (!
A.checkForAllInstructions(RetInstPred, *
this, {Instruction::Ret},
11757 UsedAssumedInformation,
11759 return indicatePessimisticFixpoint();
11762 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
11763 : ChangeStatus::CHANGED;
11768 return ChangeStatus::UNCHANGED;
11770 if (!getAssumedSimplifiedValues(
A,
Values, AA::ValueScope::Intraprocedural,
11772 return ChangeStatus::UNCHANGED;
11773 Value *NewVal = getSingleValue(
A, *
this, getIRPosition(),
Values);
11775 return ChangeStatus::UNCHANGED;
11780 "Number of function with unique return");
11783 {Attribute::get(Arg->
getContext(), Attribute::Returned)});
11788 Value *RetOp = RetI.getOperand(0);
11792 if (
A.changeUseAfterManifest(RetI.getOperandUse(0), *NewVal))
11793 Changed = ChangeStatus::CHANGED;
11796 bool UsedAssumedInformation =
false;
11797 (void)
A.checkForAllInstructions(RetInstPred, *
this, {Instruction::Ret},
11798 UsedAssumedInformation,
11804 return AAPotentialValues::indicatePessimisticFixpoint();
11808 void trackStatistics()
const override{
11815struct AAPotentialValuesFunction : AAPotentialValuesImpl {
11816 AAPotentialValuesFunction(
const IRPosition &IRP, Attributor &
A)
11817 : AAPotentialValuesImpl(IRP,
A) {}
11826 void trackStatistics()
const override {
11831struct AAPotentialValuesCallSite : AAPotentialValuesFunction {
11832 AAPotentialValuesCallSite(
const IRPosition &IRP, Attributor &
A)
11833 : AAPotentialValuesFunction(IRP,
A) {}
11836 void trackStatistics()
const override {
11841struct AAPotentialValuesCallSiteReturned : AAPotentialValuesImpl {
11842 AAPotentialValuesCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
11843 : AAPotentialValuesImpl(IRP,
A) {}
11847 auto AssumedBefore = getAssumed();
11851 return indicatePessimisticFixpoint();
11853 bool UsedAssumedInformation =
false;
11857 UsedAssumedInformation))
11858 return indicatePessimisticFixpoint();
11865 Values, S, UsedAssumedInformation))
11868 for (
auto &It :
Values) {
11869 Value *
V = It.getValue();
11870 std::optional<Value *> CallerV =
A.translateArgumentToCallSiteContent(
11871 V, *CB, *
this, UsedAssumedInformation);
11872 if (!CallerV.has_value()) {
11876 V = *CallerV ? *CallerV :
V;
11882 giveUpOnIntraprocedural(
A);
11885 addValue(
A, getState(), *V, CB, S, getAnchorScope());
11890 return indicatePessimisticFixpoint();
11892 return indicatePessimisticFixpoint();
11893 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
11894 : ChangeStatus::CHANGED;
11898 return AAPotentialValues::indicatePessimisticFixpoint();
11902 void trackStatistics()
const override {
11907struct AAPotentialValuesCallSiteArgument : AAPotentialValuesFloating {
11908 AAPotentialValuesCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
11909 : AAPotentialValuesFloating(IRP,
A) {}
11912 void trackStatistics()
const override {
11920struct AAAssumptionInfoImpl :
public AAAssumptionInfo {
11921 AAAssumptionInfoImpl(
const IRPosition &IRP, Attributor &
A,
11922 const DenseSet<StringRef> &
Known)
11923 : AAAssumptionInfo(IRP,
A,
Known) {}
11928 if (getKnown().isUniversal())
11929 return ChangeStatus::UNCHANGED;
11931 const IRPosition &IRP = getIRPosition();
11933 getAssumed().getSet().
end());
11935 return A.manifestAttrs(IRP,
11942 bool hasAssumption(
const StringRef Assumption)
const override {
11943 return isValidState() && setContains(Assumption);
11947 const std::string getAsStr(Attributor *
A)
const override {
11948 const SetContents &
Known = getKnown();
11949 const SetContents &Assumed = getAssumed();
11953 const std::string KnownStr =
llvm::join(Set,
",");
11955 std::string AssumedStr =
"Universal";
11956 if (!Assumed.isUniversal()) {
11957 Set.assign(Assumed.getSet().begin(), Assumed.getSet().end());
11960 return "Known [" + KnownStr +
"]," +
" Assumed [" + AssumedStr +
"]";
11975struct AAAssumptionInfoFunction final : AAAssumptionInfoImpl {
11976 AAAssumptionInfoFunction(
const IRPosition &IRP, Attributor &
A)
11977 : AAAssumptionInfoImpl(IRP,
A,
11984 auto CallSitePred = [&](AbstractCallSite ACS) {
11985 const auto *AssumptionAA =
A.getAAFor<AAAssumptionInfo>(
11987 DepClassTy::REQUIRED);
11991 Changed |= getIntersection(AssumptionAA->getAssumed());
11992 return !getAssumed().empty() || !getKnown().empty();
11995 bool UsedAssumedInformation =
false;
12000 if (!
A.checkForAllCallSites(CallSitePred, *
this,
true,
12001 UsedAssumedInformation))
12002 return indicatePessimisticFixpoint();
12004 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
12007 void trackStatistics()
const override {}
12011struct AAAssumptionInfoCallSite final : AAAssumptionInfoImpl {
12013 AAAssumptionInfoCallSite(
const IRPosition &IRP, Attributor &
A)
12014 : AAAssumptionInfoImpl(IRP,
A, getInitialAssumptions(IRP)) {}
12019 A.getAAFor<AAAssumptionInfo>(*
this, FnPos, DepClassTy::REQUIRED);
12025 auto *AssumptionAA =
12026 A.getAAFor<AAAssumptionInfo>(*
this, FnPos, DepClassTy::REQUIRED);
12028 return indicatePessimisticFixpoint();
12029 bool Changed = getIntersection(AssumptionAA->getAssumed());
12030 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
12034 void trackStatistics()
const override {}
12039 DenseSet<StringRef> getInitialAssumptions(
const IRPosition &IRP) {
12046 return Assumptions;
12061struct AAUnderlyingObjectsImpl
12067 const std::string getAsStr(
Attributor *
A)
const override {
12068 if (!isValidState())
12069 return "<invalid>";
12072 OS <<
"underlying objects: inter " << InterAssumedUnderlyingObjects.size()
12073 <<
" objects, intra " << IntraAssumedUnderlyingObjects.size()
12075 if (!InterAssumedUnderlyingObjects.empty()) {
12076 OS <<
"inter objects:\n";
12077 for (
auto *Obj : InterAssumedUnderlyingObjects)
12078 OS << *Obj <<
'\n';
12080 if (!IntraAssumedUnderlyingObjects.empty()) {
12081 OS <<
"intra objects:\n";
12082 for (
auto *Obj : IntraAssumedUnderlyingObjects)
12083 OS << *
Obj <<
'\n';
12089 void trackStatistics()
const override {}
12093 auto &Ptr = getAssociatedValue();
12095 bool UsedAssumedInformation =
false;
12096 auto DoUpdate = [&](SmallSetVector<Value *, 8> &UnderlyingObjects,
12098 SmallPtrSet<Value *, 8> SeenObjects;
12102 Scope, UsedAssumedInformation))
12103 return UnderlyingObjects.
insert(&Ptr);
12107 for (
unsigned I = 0;
I <
Values.size(); ++
I) {
12111 if (!SeenObjects.
insert(UO ? UO : Obj).second)
12113 if (UO && UO != Obj) {
12119 const auto *OtherAA =
A.getAAFor<AAUnderlyingObjects>(
12121 auto Pred = [&](
Value &
V) {
12125 Values.emplace_back(V,
nullptr);
12129 if (!OtherAA || !OtherAA->forallUnderlyingObjects(Pred, Scope))
12131 "The forall call should not return false at this position");
12137 Changed |= handleIndirect(
A, *Obj, UnderlyingObjects, Scope,
12138 UsedAssumedInformation);
12144 for (
unsigned u = 0, e =
PHI->getNumIncomingValues(); u < e; u++) {
12146 handleIndirect(
A, *
PHI->getIncomingValue(u), UnderlyingObjects,
12147 Scope, UsedAssumedInformation);
12161 if (!UsedAssumedInformation)
12162 indicateOptimisticFixpoint();
12163 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
12166 bool forallUnderlyingObjects(
12167 function_ref<
bool(
Value &)> Pred,
12169 if (!isValidState())
12170 return Pred(getAssociatedValue());
12173 ? IntraAssumedUnderlyingObjects
12174 : InterAssumedUnderlyingObjects;
12175 for (
Value *Obj : AssumedUnderlyingObjects)
12185 bool handleIndirect(Attributor &
A,
Value &V,
12186 SmallSetVector<Value *, 8> &UnderlyingObjects,
12189 const auto *AA =
A.getAAFor<AAUnderlyingObjects>(
12191 auto Pred = [&](
Value &
V) {
12195 if (!AA || !AA->forallUnderlyingObjects(Pred, Scope))
12197 "The forall call should not return false at this position");
12203 SmallSetVector<Value *, 8> IntraAssumedUnderlyingObjects;
12205 SmallSetVector<Value *, 8> InterAssumedUnderlyingObjects;
12208struct AAUnderlyingObjectsFloating final : AAUnderlyingObjectsImpl {
12209 AAUnderlyingObjectsFloating(
const IRPosition &IRP, Attributor &
A)
12210 : AAUnderlyingObjectsImpl(IRP,
A) {}
12213struct AAUnderlyingObjectsArgument final : AAUnderlyingObjectsImpl {
12214 AAUnderlyingObjectsArgument(
const IRPosition &IRP, Attributor &
A)
12215 : AAUnderlyingObjectsImpl(IRP,
A) {}
12218struct AAUnderlyingObjectsCallSite final : AAUnderlyingObjectsImpl {
12219 AAUnderlyingObjectsCallSite(
const IRPosition &IRP, Attributor &
A)
12220 : AAUnderlyingObjectsImpl(IRP,
A) {}
12223struct AAUnderlyingObjectsCallSiteArgument final : AAUnderlyingObjectsImpl {
12224 AAUnderlyingObjectsCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
12225 : AAUnderlyingObjectsImpl(IRP,
A) {}
12228struct AAUnderlyingObjectsReturned final : AAUnderlyingObjectsImpl {
12229 AAUnderlyingObjectsReturned(
const IRPosition &IRP, Attributor &
A)
12230 : AAUnderlyingObjectsImpl(IRP,
A) {}
12233struct AAUnderlyingObjectsCallSiteReturned final : AAUnderlyingObjectsImpl {
12234 AAUnderlyingObjectsCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
12235 : AAUnderlyingObjectsImpl(IRP,
A) {}
12238struct AAUnderlyingObjectsFunction final : AAUnderlyingObjectsImpl {
12239 AAUnderlyingObjectsFunction(
const IRPosition &IRP, Attributor &
A)
12240 : AAUnderlyingObjectsImpl(IRP,
A) {}
12246struct AAGlobalValueInfoFloating :
public AAGlobalValueInfo {
12247 AAGlobalValueInfoFloating(
const IRPosition &IRP, Attributor &
A)
12248 : AAGlobalValueInfo(IRP,
A) {}
12253 bool checkUse(Attributor &
A,
const Use &U,
bool &Follow,
12254 SmallVectorImpl<const Value *> &Worklist) {
12260 if (!GV->hasLocalLinkage() && !
A.isClosedWorldModule())
12266 LLVM_DEBUG(
dbgs() <<
"[AAGlobalValueInfo] Check use: " << *
U.get() <<
" in "
12267 << *UInst <<
"\n");
12270 int Idx = &
Cmp->getOperandUse(0) == &
U;
12273 return U == &getAnchorValue();
12278 auto CallSitePred = [&](AbstractCallSite ACS) {
12279 Worklist.
push_back(ACS.getInstruction());
12282 bool UsedAssumedInformation =
false;
12284 if (!
A.checkForAllCallSites(CallSitePred, *UInst->
getFunction(),
12286 UsedAssumedInformation))
12304 if (!Fn || !
A.isFunctionIPOAmendable(*Fn))
12313 unsigned NumUsesBefore =
Uses.size();
12315 SmallPtrSet<const Value *, 8> Visited;
12319 auto UsePred = [&](
const Use &
U,
bool &Follow) ->
bool {
12327 return checkUse(
A, U, Follow, Worklist);
12329 auto EquivalentUseCB = [&](
const Use &OldU,
const Use &NewU) {
12330 Uses.insert(&OldU);
12334 while (!Worklist.
empty()) {
12336 if (!Visited.
insert(V).second)
12338 if (!
A.checkForAllUses(UsePred, *
this, *V,
12340 DepClassTy::OPTIONAL,
12341 true, EquivalentUseCB)) {
12342 return indicatePessimisticFixpoint();
12346 return Uses.size() == NumUsesBefore ? ChangeStatus::UNCHANGED
12347 : ChangeStatus::CHANGED;
12350 bool isPotentialUse(
const Use &U)
const override {
12351 return !isValidState() ||
Uses.contains(&U);
12356 return ChangeStatus::UNCHANGED;
12360 const std::string getAsStr(Attributor *
A)
const override {
12361 return "[" + std::to_string(
Uses.size()) +
" uses]";
12364 void trackStatistics()
const override {
12370 SmallPtrSet<const Use *, 8>
Uses;
12376struct AAIndirectCallInfoCallSite :
public AAIndirectCallInfo {
12377 AAIndirectCallInfoCallSite(
const IRPosition &IRP, Attributor &
A)
12378 : AAIndirectCallInfo(IRP,
A) {}
12382 auto *MD = getCtxI()->getMetadata(LLVMContext::MD_callees);
12383 if (!MD && !
A.isClosedWorldModule())
12387 for (
const auto &
Op : MD->operands())
12389 PotentialCallees.insert(Callee);
12390 }
else if (
A.isClosedWorldModule()) {
12392 A.getInfoCache().getIndirectlyCallableFunctions(
A);
12393 PotentialCallees.insert_range(IndirectlyCallableFunctions);
12396 if (PotentialCallees.empty())
12397 indicateOptimisticFixpoint();
12405 SmallSetVector<Function *, 4> AssumedCalleesNow;
12406 bool AllCalleesKnownNow = AllCalleesKnown;
12408 auto CheckPotentialCalleeUse = [&](
Function &PotentialCallee,
12409 bool &UsedAssumedInformation) {
12410 const auto *GIAA =
A.getAAFor<AAGlobalValueInfo>(
12412 if (!GIAA || GIAA->isPotentialUse(CalleeUse))
12414 UsedAssumedInformation = !GIAA->isAtFixpoint();
12418 auto AddPotentialCallees = [&]() {
12419 for (
auto *PotentialCallee : PotentialCallees) {
12420 bool UsedAssumedInformation =
false;
12421 if (CheckPotentialCalleeUse(*PotentialCallee, UsedAssumedInformation))
12422 AssumedCalleesNow.
insert(PotentialCallee);
12428 bool UsedAssumedInformation =
false;
12431 AA::ValueScope::AnyScope,
12432 UsedAssumedInformation)) {
12433 if (PotentialCallees.empty())
12434 return indicatePessimisticFixpoint();
12435 AddPotentialCallees();
12440 auto CheckPotentialCallee = [&](
Function &Fn) {
12441 if (!PotentialCallees.empty() && !PotentialCallees.count(&Fn))
12444 auto &CachedResult = FilterResults[&Fn];
12445 if (CachedResult.has_value())
12446 return CachedResult.value();
12448 bool UsedAssumedInformation =
false;
12449 if (!CheckPotentialCalleeUse(Fn, UsedAssumedInformation)) {
12450 if (!UsedAssumedInformation)
12451 CachedResult =
false;
12460 for (
int I = NumCBArgs;
I < NumFnArgs; ++
I) {
12461 bool IsKnown =
false;
12464 DepClassTy::OPTIONAL, IsKnown)) {
12466 CachedResult =
false;
12471 CachedResult =
true;
12477 for (
auto &VAC :
Values) {
12485 if (CheckPotentialCallee(*VACFn))
12486 AssumedCalleesNow.
insert(VACFn);
12489 if (!PotentialCallees.empty()) {
12490 AddPotentialCallees();
12493 AllCalleesKnownNow =
false;
12496 if (AssumedCalleesNow == AssumedCallees &&
12497 AllCalleesKnown == AllCalleesKnownNow)
12498 return ChangeStatus::UNCHANGED;
12500 std::swap(AssumedCallees, AssumedCalleesNow);
12501 AllCalleesKnown = AllCalleesKnownNow;
12502 return ChangeStatus::CHANGED;
12508 if (!AllCalleesKnown && AssumedCallees.empty())
12509 return ChangeStatus::UNCHANGED;
12512 bool UsedAssumedInformation =
false;
12513 if (
A.isAssumedDead(*CB,
this,
nullptr,
12514 UsedAssumedInformation))
12515 return ChangeStatus::UNCHANGED;
12520 if (
FP->getType()->getPointerAddressSpace() != ProgramAS)
12521 FP =
new AddrSpaceCastInst(
12522 FP, PointerType::get(
FP->getContext(), ProgramAS),
12523 FP->getName() +
".as" + Twine(ProgramAS), CB->
getIterator());
12532 if (AssumedCallees.empty()) {
12533 assert(AllCalleesKnown &&
12534 "Expected all callees to be known if there are none.");
12535 A.changeToUnreachableAfterManifest(CB);
12536 return ChangeStatus::CHANGED;
12540 if (AllCalleesKnown && AssumedCallees.size() == 1) {
12541 auto *NewCallee = AssumedCallees.front();
12544 NumIndirectCallsPromoted++;
12545 return ChangeStatus::CHANGED;
12552 A.deleteAfterManifest(*CB);
12553 return ChangeStatus::CHANGED;
12563 bool SpecializedForAnyCallees =
false;
12564 bool SpecializedForAllCallees = AllCalleesKnown;
12565 ICmpInst *LastCmp =
nullptr;
12568 for (
Function *NewCallee : AssumedCallees) {
12569 if (!
A.shouldSpecializeCallSiteForCallee(*
this, *CB, *NewCallee,
12570 AssumedCallees.size())) {
12571 SkippedAssumedCallees.
push_back(NewCallee);
12572 SpecializedForAllCallees =
false;
12575 SpecializedForAnyCallees =
true;
12581 A.registerManifestAddedBasicBlock(*ThenTI->
getParent());
12582 A.registerManifestAddedBasicBlock(*IP->getParent());
12588 A.registerManifestAddedBasicBlock(*ElseBB);
12590 SplitTI->replaceUsesOfWith(CBBB, ElseBB);
12595 CastInst *RetBC =
nullptr;
12596 CallInst *NewCall =
nullptr;
12601 NumIndirectCallsPromoted++;
12609 auto AttachCalleeMetadata = [&](CallBase &IndirectCB) {
12610 if (!AllCalleesKnown)
12611 return ChangeStatus::UNCHANGED;
12612 MDBuilder MDB(IndirectCB.getContext());
12613 MDNode *Callees = MDB.createCallees(SkippedAssumedCallees);
12614 IndirectCB.setMetadata(LLVMContext::MD_callees, Callees);
12615 return ChangeStatus::CHANGED;
12618 if (!SpecializedForAnyCallees)
12619 return AttachCalleeMetadata(*CB);
12622 if (SpecializedForAllCallees) {
12625 new UnreachableInst(IP->getContext(), IP);
12626 IP->eraseFromParent();
12629 CBClone->setName(CB->
getName());
12630 CBClone->insertBefore(*IP->getParent(), IP);
12631 NewCalls.
push_back({CBClone,
nullptr});
12632 AttachCalleeMetadata(*CBClone);
12639 CB->
getParent()->getFirstInsertionPt());
12640 for (
auto &It : NewCalls) {
12641 CallBase *NewCall = It.first;
12642 Instruction *CallRet = It.second ? It.second : It.first;
12654 A.deleteAfterManifest(*CB);
12655 Changed = ChangeStatus::CHANGED;
12661 const std::string getAsStr(Attributor *
A)
const override {
12662 return std::string(AllCalleesKnown ?
"eliminate" :
"specialize") +
12663 " indirect call site with " + std::to_string(AssumedCallees.size()) +
12667 void trackStatistics()
const override {
12668 if (AllCalleesKnown) {
12670 Eliminated, CallSites,
12671 "Number of indirect call sites eliminated via specialization")
12674 "Number of indirect call sites specialized")
12678 bool foreachCallee(function_ref<
bool(
Function *)> CB)
const override {
12679 return isValidState() && AllCalleesKnown &&
all_of(AssumedCallees, CB);
12684 DenseMap<Function *, std::optional<bool>> FilterResults;
12688 SmallSetVector<Function *, 4> PotentialCallees;
12692 SmallSetVector<Function *, 4> AssumedCallees;
12696 bool AllCalleesKnown =
true;
12703struct AAInvariantLoadPointerImpl
12704 :
public StateWrapper<BitIntegerState<uint8_t, 15>,
12705 AAInvariantLoadPointer> {
12709 IS_NOALIAS = 1 << 0,
12712 IS_NOEFFECT = 1 << 1,
12714 IS_LOCALLY_INVARIANT = 1 << 2,
12716 IS_LOCALLY_CONSTRAINED = 1 << 3,
12718 IS_BEST_STATE = IS_NOALIAS | IS_NOEFFECT | IS_LOCALLY_INVARIANT |
12719 IS_LOCALLY_CONSTRAINED,
12721 static_assert(getBestState() == IS_BEST_STATE,
"Unexpected best state");
12724 StateWrapper<BitIntegerState<uint8_t, 15>, AAInvariantLoadPointer>;
12728 AAInvariantLoadPointerImpl(
const IRPosition &IRP, Attributor &
A)
12731 bool isKnownInvariant()
const final {
12732 return isKnownLocallyInvariant() && isKnown(IS_LOCALLY_CONSTRAINED);
12735 bool isKnownLocallyInvariant()
const final {
12736 if (isKnown(IS_LOCALLY_INVARIANT))
12738 return isKnown(IS_NOALIAS | IS_NOEFFECT);
12741 bool isAssumedInvariant()
const final {
12742 return isAssumedLocallyInvariant() && isAssumed(IS_LOCALLY_CONSTRAINED);
12745 bool isAssumedLocallyInvariant()
const final {
12746 if (isAssumed(IS_LOCALLY_INVARIANT))
12748 return isAssumed(IS_NOALIAS | IS_NOEFFECT);
12755 if (requiresNoAlias() && !isAssumed(IS_NOALIAS))
12756 return indicatePessimisticFixpoint();
12760 Changed |= updateLocalInvariance(
A);
12766 if (!isKnownInvariant())
12767 return ChangeStatus::UNCHANGED;
12770 const Value *Ptr = &getAssociatedValue();
12771 const auto TagInvariantLoads = [&](
const Use &
U,
bool &) {
12772 if (
U.get() != Ptr)
12780 if (!
A.isRunOn(
I->getFunction()))
12783 if (
I->hasMetadata(LLVMContext::MD_invariant_load))
12787 LI->setMetadata(LLVMContext::MD_invariant_load,
12789 Changed = ChangeStatus::CHANGED;
12794 (void)
A.checkForAllUses(TagInvariantLoads, *
this, *Ptr);
12799 const std::string getAsStr(Attributor *)
const override {
12800 if (isKnownInvariant())
12801 return "load-invariant pointer";
12802 return "non-invariant pointer";
12806 void trackStatistics()
const override {}
12810 bool requiresNoAlias()
const {
12811 switch (getPositionKind()) {
12817 case IRP_CALL_SITE:
12819 case IRP_CALL_SITE_RETURNED: {
12824 case IRP_ARGUMENT: {
12825 const Function *
F = getAssociatedFunction();
12826 assert(
F &&
"no associated function for argument");
12832 bool isExternal()
const {
12833 const Function *
F = getAssociatedFunction();
12837 getPositionKind() != IRP_CALL_SITE_RETURNED;
12841 if (isKnown(IS_NOALIAS) || !isAssumed(IS_NOALIAS))
12842 return ChangeStatus::UNCHANGED;
12845 if (
const auto *ANoAlias =
A.getOrCreateAAFor<AANoAlias>(
12846 getIRPosition(),
this, DepClassTy::REQUIRED)) {
12847 if (ANoAlias->isKnownNoAlias()) {
12848 addKnownBits(IS_NOALIAS);
12849 return ChangeStatus::CHANGED;
12852 if (!ANoAlias->isAssumedNoAlias()) {
12853 removeAssumedBits(IS_NOALIAS);
12854 return ChangeStatus::CHANGED;
12857 return ChangeStatus::UNCHANGED;
12862 if (
const Argument *Arg = getAssociatedArgument()) {
12864 addKnownBits(IS_NOALIAS);
12865 return ChangeStatus::UNCHANGED;
12870 removeAssumedBits(IS_NOALIAS);
12871 return ChangeStatus::CHANGED;
12874 return ChangeStatus::UNCHANGED;
12878 if (isKnown(IS_NOEFFECT) || !isAssumed(IS_NOEFFECT))
12879 return ChangeStatus::UNCHANGED;
12881 if (!getAssociatedFunction())
12882 return indicatePessimisticFixpoint();
12885 return indicatePessimisticFixpoint();
12887 const auto HasNoEffectLoads = [&](
const Use &
U,
bool &) {
12889 return !LI || !LI->mayHaveSideEffects();
12891 if (!
A.checkForAllUses(HasNoEffectLoads, *
this, getAssociatedValue()))
12892 return indicatePessimisticFixpoint();
12894 if (
const auto *AMemoryBehavior =
A.getOrCreateAAFor<AAMemoryBehavior>(
12895 getIRPosition(),
this, DepClassTy::REQUIRED)) {
12898 if (!AMemoryBehavior->isAssumedReadOnly())
12899 return indicatePessimisticFixpoint();
12901 if (AMemoryBehavior->isKnownReadOnly()) {
12902 addKnownBits(IS_NOEFFECT);
12903 return ChangeStatus::UNCHANGED;
12906 return ChangeStatus::UNCHANGED;
12909 if (
const Argument *Arg = getAssociatedArgument()) {
12911 addKnownBits(IS_NOEFFECT);
12912 return ChangeStatus::UNCHANGED;
12917 return indicatePessimisticFixpoint();
12920 return ChangeStatus::UNCHANGED;
12924 if (isKnown(IS_LOCALLY_INVARIANT) || !isAssumed(IS_LOCALLY_INVARIANT))
12925 return ChangeStatus::UNCHANGED;
12928 const auto *AUO =
A.getOrCreateAAFor<AAUnderlyingObjects>(
12929 getIRPosition(),
this, DepClassTy::REQUIRED);
12931 return ChangeStatus::UNCHANGED;
12933 bool UsedAssumedInformation =
false;
12934 const auto IsLocallyInvariantLoadIfPointer = [&](
const Value &
V) {
12935 if (!
V.getType()->isPointerTy())
12937 const auto *IsInvariantLoadPointer =
12939 DepClassTy::REQUIRED);
12941 if (!IsInvariantLoadPointer)
12944 if (IsInvariantLoadPointer->isKnownLocallyInvariant())
12946 if (!IsInvariantLoadPointer->isAssumedLocallyInvariant())
12949 UsedAssumedInformation =
true;
12952 if (!AUO->forallUnderlyingObjects(IsLocallyInvariantLoadIfPointer))
12953 return indicatePessimisticFixpoint();
12959 if (!IsLocallyInvariantLoadIfPointer(*Arg))
12960 return indicatePessimisticFixpoint();
12965 if (!UsedAssumedInformation) {
12967 addKnownBits(IS_LOCALLY_INVARIANT);
12968 return ChangeStatus::CHANGED;
12971 return ChangeStatus::UNCHANGED;
12975struct AAInvariantLoadPointerFloating final : AAInvariantLoadPointerImpl {
12976 AAInvariantLoadPointerFloating(
const IRPosition &IRP, Attributor &
A)
12977 : AAInvariantLoadPointerImpl(IRP,
A) {}
12980struct AAInvariantLoadPointerReturned final : AAInvariantLoadPointerImpl {
12981 AAInvariantLoadPointerReturned(
const IRPosition &IRP, Attributor &
A)
12982 : AAInvariantLoadPointerImpl(IRP,
A) {}
12985 removeAssumedBits(IS_LOCALLY_CONSTRAINED);
12989struct AAInvariantLoadPointerCallSiteReturned final
12990 : AAInvariantLoadPointerImpl {
12991 AAInvariantLoadPointerCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
12992 : AAInvariantLoadPointerImpl(IRP,
A) {}
12995 const Function *
F = getAssociatedFunction();
12996 assert(
F &&
"no associated function for return from call");
12998 if (!
F->isDeclaration() && !
F->isIntrinsic())
12999 return AAInvariantLoadPointerImpl::initialize(
A);
13004 return AAInvariantLoadPointerImpl::initialize(
A);
13006 if (
F->onlyReadsMemory() &&
F->hasNoSync())
13007 return AAInvariantLoadPointerImpl::initialize(
A);
13011 indicatePessimisticFixpoint();
13015struct AAInvariantLoadPointerArgument final : AAInvariantLoadPointerImpl {
13016 AAInvariantLoadPointerArgument(
const IRPosition &IRP, Attributor &
A)
13017 : AAInvariantLoadPointerImpl(IRP,
A) {}
13020 const Function *
F = getAssociatedFunction();
13021 assert(
F &&
"no associated function for argument");
13024 addKnownBits(IS_LOCALLY_CONSTRAINED);
13028 if (!
F->hasLocalLinkage())
13029 removeAssumedBits(IS_LOCALLY_CONSTRAINED);
13033struct AAInvariantLoadPointerCallSiteArgument final
13034 : AAInvariantLoadPointerImpl {
13035 AAInvariantLoadPointerCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
13036 : AAInvariantLoadPointerImpl(IRP,
A) {}
13043template <
typename InstType>
13044static bool makeChange(Attributor &
A, InstType *MemInst,
const Use &U,
13045 Value *OriginalValue, PointerType *NewPtrTy,
13046 bool UseOriginalValue) {
13047 if (
U.getOperandNo() != InstType::getPointerOperandIndex())
13050 if (MemInst->isVolatile()) {
13051 auto *
TTI =
A.getInfoCache().getAnalysisResultForFunction<TargetIRAnalysis>(
13052 *MemInst->getFunction());
13053 unsigned NewAS = NewPtrTy->getPointerAddressSpace();
13058 if (UseOriginalValue) {
13059 A.changeUseAfterManifest(
const_cast<Use &
>(U), *OriginalValue);
13063 Instruction *CastInst =
new AddrSpaceCastInst(OriginalValue, NewPtrTy);
13065 A.changeUseAfterManifest(
const_cast<Use &
>(U), *CastInst);
13069struct AAAddressSpaceImpl :
public AAAddressSpace {
13070 AAAddressSpaceImpl(
const IRPosition &IRP, Attributor &
A)
13071 : AAAddressSpace(IRP,
A) {}
13074 assert(isValidState() &&
"the AA is invalid");
13075 return AssumedAddressSpace;
13080 assert(getAssociatedType()->isPtrOrPtrVectorTy() &&
13081 "Associated value is not a pointer");
13083 if (!
A.getInfoCache().getFlatAddressSpace().has_value()) {
13084 indicatePessimisticFixpoint();
13088 unsigned FlatAS =
A.getInfoCache().getFlatAddressSpace().value();
13089 unsigned AS = getAssociatedType()->getPointerAddressSpace();
13090 if (AS != FlatAS) {
13091 [[maybe_unused]]
bool R = takeAddressSpace(AS);
13092 assert(R &&
"The take should happen");
13093 indicateOptimisticFixpoint();
13098 uint32_t OldAddressSpace = AssumedAddressSpace;
13099 unsigned FlatAS =
A.getInfoCache().getFlatAddressSpace().value();
13101 auto CheckAddressSpace = [&](
Value &
Obj) {
13107 unsigned ObjAS =
Obj.getType()->getPointerAddressSpace();
13108 if (ObjAS != FlatAS)
13109 return takeAddressSpace(ObjAS);
13123 A.getInfoCache().getAnalysisResultForFunction<TargetIRAnalysis>(*F);
13125 if (AssumedAS != ~0U)
13126 return takeAddressSpace(AssumedAS);
13130 return takeAddressSpace(FlatAS);
13133 auto *AUO =
A.getOrCreateAAFor<AAUnderlyingObjects>(getIRPosition(),
this,
13134 DepClassTy::REQUIRED);
13135 if (!AUO->forallUnderlyingObjects(CheckAddressSpace))
13136 return indicatePessimisticFixpoint();
13138 return OldAddressSpace == AssumedAddressSpace ? ChangeStatus::UNCHANGED
13139 : ChangeStatus::CHANGED;
13146 if (NewAS == InvalidAddressSpace ||
13148 return ChangeStatus::UNCHANGED;
13150 unsigned FlatAS =
A.getInfoCache().getFlatAddressSpace().value();
13152 Value *AssociatedValue = &getAssociatedValue();
13153 Value *OriginalValue = peelAddrspacecast(AssociatedValue, FlatAS);
13156 PointerType::get(getAssociatedType()->
getContext(), NewAS);
13157 bool UseOriginalValue =
13162 auto Pred = [&](
const Use &
U,
bool &) {
13163 if (
U.get() != AssociatedValue)
13174 makeChange(
A, LI, U, OriginalValue, NewPtrTy, UseOriginalValue);
13177 makeChange(
A, SI, U, OriginalValue, NewPtrTy, UseOriginalValue);
13180 makeChange(
A, RMW, U, OriginalValue, NewPtrTy, UseOriginalValue);
13183 makeChange(
A, CmpX, U, OriginalValue, NewPtrTy, UseOriginalValue);
13190 (void)
A.checkForAllUses(Pred, *
this, getAssociatedValue(),
13193 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
13197 const std::string getAsStr(Attributor *
A)
const override {
13198 if (!isValidState())
13199 return "addrspace(<invalid>)";
13200 return "addrspace(" +
13201 (AssumedAddressSpace == InvalidAddressSpace
13203 : std::to_string(AssumedAddressSpace)) +
13208 uint32_t AssumedAddressSpace = InvalidAddressSpace;
13210 bool takeAddressSpace(uint32_t AS) {
13211 if (AssumedAddressSpace == InvalidAddressSpace) {
13212 AssumedAddressSpace = AS;
13215 return AssumedAddressSpace == AS;
13218 static Value *peelAddrspacecast(
Value *V,
unsigned FlatAS) {
13220 assert(
I->getSrcAddressSpace() != FlatAS &&
13221 "there should not be flat AS -> non-flat AS");
13222 return I->getPointerOperand();
13225 if (
C->getOpcode() == Instruction::AddrSpaceCast) {
13226 assert(
C->getOperand(0)->getType()->getPointerAddressSpace() !=
13228 "there should not be flat AS -> non-flat AS X");
13229 return C->getOperand(0);
13235struct AAAddressSpaceFloating final : AAAddressSpaceImpl {
13236 AAAddressSpaceFloating(
const IRPosition &IRP, Attributor &
A)
13237 : AAAddressSpaceImpl(IRP,
A) {}
13239 void trackStatistics()
const override {
13244struct AAAddressSpaceReturned final : AAAddressSpaceImpl {
13245 AAAddressSpaceReturned(
const IRPosition &IRP, Attributor &
A)
13246 : AAAddressSpaceImpl(IRP,
A) {}
13252 (void)indicatePessimisticFixpoint();
13255 void trackStatistics()
const override {
13260struct AAAddressSpaceCallSiteReturned final : AAAddressSpaceImpl {
13261 AAAddressSpaceCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
13262 : AAAddressSpaceImpl(IRP,
A) {}
13264 void trackStatistics()
const override {
13269struct AAAddressSpaceArgument final : AAAddressSpaceImpl {
13270 AAAddressSpaceArgument(
const IRPosition &IRP, Attributor &
A)
13271 : AAAddressSpaceImpl(IRP,
A) {}
13276struct AAAddressSpaceCallSiteArgument final : AAAddressSpaceImpl {
13277 AAAddressSpaceCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
13278 : AAAddressSpaceImpl(IRP,
A) {}
13284 (void)indicatePessimisticFixpoint();
13287 void trackStatistics()
const override {
13302struct AANoAliasAddrSpaceImpl :
public AANoAliasAddrSpace {
13303 AANoAliasAddrSpaceImpl(
const IRPosition &IRP, Attributor &
A)
13304 : AANoAliasAddrSpace(IRP,
A) {}
13307 assert(getAssociatedType()->isPtrOrPtrVectorTy() &&
13308 "Associated value is not a pointer");
13312 std::optional<unsigned> FlatAS =
A.getInfoCache().getFlatAddressSpace();
13313 if (!FlatAS.has_value()) {
13314 indicatePessimisticFixpoint();
13320 unsigned AS = getAssociatedType()->getPointerAddressSpace();
13321 if (AS != *FlatAS) {
13323 indicateOptimisticFixpoint();
13328 unsigned FlatAS =
A.getInfoCache().getFlatAddressSpace().value();
13329 uint32_t OldAssumed = getAssumed();
13331 auto CheckAddressSpace = [&](
Value &
Obj) {
13335 unsigned AS =
Obj.getType()->getPointerAddressSpace();
13339 removeAS(
Obj.getType()->getPointerAddressSpace());
13343 const AAUnderlyingObjects *AUO =
A.getOrCreateAAFor<AAUnderlyingObjects>(
13344 getIRPosition(),
this, DepClassTy::REQUIRED);
13346 return indicatePessimisticFixpoint();
13348 return OldAssumed == getAssumed() ? ChangeStatus::UNCHANGED
13349 : ChangeStatus::CHANGED;
13354 unsigned FlatAS =
A.getInfoCache().getFlatAddressSpace().value();
13356 unsigned AS = getAssociatedType()->getPointerAddressSpace();
13357 if (AS != FlatAS ||
Map.empty())
13358 return ChangeStatus::UNCHANGED;
13360 LLVMContext &Ctx = getAssociatedValue().getContext();
13361 MDNode *NoAliasASNode =
nullptr;
13362 MDBuilder MDB(Ctx);
13364 for (RangeMap::const_iterator
I =
Map.begin();
I !=
Map.end();
I++) {
13367 unsigned Upper =
I.stop();
13368 unsigned Lower =
I.start();
13369 if (!NoAliasASNode) {
13370 NoAliasASNode = MDB.createRange(APInt(32,
Lower), APInt(32,
Upper + 1));
13373 MDNode *ASRange = MDB.createRange(APInt(32,
Lower), APInt(32,
Upper + 1));
13377 Value *AssociatedValue = &getAssociatedValue();
13380 auto AddNoAliasAttr = [&](
const Use &
U,
bool &) {
13381 if (
U.get() != AssociatedValue)
13384 if (!Inst || Inst->
hasMetadata(LLVMContext::MD_noalias_addrspace))
13391 Inst->
setMetadata(LLVMContext::MD_noalias_addrspace, NoAliasASNode);
13395 (void)
A.checkForAllUses(AddNoAliasAttr, *
this, *AssociatedValue,
13397 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
13401 const std::string getAsStr(Attributor *
A)
const override {
13402 if (!isValidState())
13403 return "<invalid>";
13405 raw_string_ostream OS(Str);
13406 OS <<
"CanNotBeAddrSpace(";
13407 for (RangeMap::const_iterator
I =
Map.begin();
I !=
Map.end();
I++) {
13408 unsigned Upper =
I.stop();
13409 unsigned Lower =
I.start();
13410 OS <<
' ' <<
'[' <<
Upper <<
',' <<
Lower + 1 <<
')';
13417 void removeAS(
unsigned AS) {
13418 RangeMap::iterator
I =
Map.find(AS);
13420 if (
I !=
Map.end()) {
13421 unsigned Upper =
I.stop();
13422 unsigned Lower =
I.start();
13426 if (AS != ~((
unsigned)0) && AS + 1 <=
Upper)
13428 if (AS != 0 &&
Lower <= AS - 1)
13433 void resetASRanges(Attributor &
A) {
13435 Map.insert(0,
A.getInfoCache().getMaxAddrSpace(),
true);
13439struct AANoAliasAddrSpaceFloating final : AANoAliasAddrSpaceImpl {
13440 AANoAliasAddrSpaceFloating(
const IRPosition &IRP, Attributor &
A)
13441 : AANoAliasAddrSpaceImpl(IRP,
A) {}
13443 void trackStatistics()
const override {
13448struct AANoAliasAddrSpaceReturned final : AANoAliasAddrSpaceImpl {
13449 AANoAliasAddrSpaceReturned(
const IRPosition &IRP, Attributor &
A)
13450 : AANoAliasAddrSpaceImpl(IRP,
A) {}
13452 void trackStatistics()
const override {
13457struct AANoAliasAddrSpaceCallSiteReturned final : AANoAliasAddrSpaceImpl {
13458 AANoAliasAddrSpaceCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
13459 : AANoAliasAddrSpaceImpl(IRP,
A) {}
13461 void trackStatistics()
const override {
13466struct AANoAliasAddrSpaceArgument final : AANoAliasAddrSpaceImpl {
13467 AANoAliasAddrSpaceArgument(
const IRPosition &IRP, Attributor &
A)
13468 : AANoAliasAddrSpaceImpl(IRP,
A) {}
13470 void trackStatistics()
const override {
13475struct AANoAliasAddrSpaceCallSiteArgument final : AANoAliasAddrSpaceImpl {
13476 AANoAliasAddrSpaceCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
13477 : AANoAliasAddrSpaceImpl(IRP,
A) {}
13479 void trackStatistics()
const override {
13486struct AAAllocationInfoImpl :
public AAAllocationInfo {
13487 AAAllocationInfoImpl(
const IRPosition &IRP, Attributor &
A)
13488 : AAAllocationInfo(IRP,
A) {}
13490 std::optional<TypeSize> getAllocatedSize()
const override {
13491 assert(isValidState() &&
"the AA is invalid");
13492 return AssumedAllocatedSize;
13495 std::optional<TypeSize> findInitialAllocationSize(Instruction *
I,
13496 const DataLayout &
DL) {
13499 switch (
I->getOpcode()) {
13500 case Instruction::Alloca: {
13505 return std::nullopt;
13511 const IRPosition &IRP = getIRPosition();
13516 return indicatePessimisticFixpoint();
13518 bool IsKnownNoCapture;
13520 A,
this, IRP, DepClassTy::OPTIONAL, IsKnownNoCapture))
13521 return indicatePessimisticFixpoint();
13523 const AAPointerInfo *PI =
13524 A.getOrCreateAAFor<AAPointerInfo>(IRP, *
this, DepClassTy::REQUIRED);
13527 return indicatePessimisticFixpoint();
13530 return indicatePessimisticFixpoint();
13532 const DataLayout &
DL =
A.getDataLayout();
13533 const auto AllocationSize = findInitialAllocationSize(
I,
DL);
13536 if (!AllocationSize)
13537 return indicatePessimisticFixpoint();
13541 if (*AllocationSize == 0)
13542 return indicatePessimisticFixpoint();
13548 return indicatePessimisticFixpoint();
13550 if (BinSize == 0) {
13551 auto NewAllocationSize = std::make_optional<TypeSize>(0,
false);
13552 if (!changeAllocationSize(NewAllocationSize))
13553 return ChangeStatus::UNCHANGED;
13554 return ChangeStatus::CHANGED;
13558 const auto &It = PI->
begin();
13561 if (It->first.Offset != 0)
13562 return indicatePessimisticFixpoint();
13564 uint64_t SizeOfBin = It->first.Offset + It->first.Size;
13566 if (SizeOfBin >= *AllocationSize)
13567 return indicatePessimisticFixpoint();
13569 auto NewAllocationSize = std::make_optional<TypeSize>(SizeOfBin * 8,
false);
13571 if (!changeAllocationSize(NewAllocationSize))
13572 return ChangeStatus::UNCHANGED;
13574 return ChangeStatus::CHANGED;
13580 assert(isValidState() &&
13581 "Manifest should only be called if the state is valid.");
13585 auto FixedAllocatedSizeInBits = getAllocatedSize()->getFixedValue();
13587 unsigned long NumBytesToAllocate = (FixedAllocatedSizeInBits + 7) / 8;
13589 switch (
I->getOpcode()) {
13591 case Instruction::Alloca: {
13595 Type *CharType = Type::getInt8Ty(
I->getContext());
13597 auto *NumBytesToValue =
13598 ConstantInt::get(
I->getContext(), APInt(32, NumBytesToAllocate));
13601 insertPt = std::next(insertPt);
13602 AllocaInst *NewAllocaInst =
13607 return ChangeStatus::CHANGED;
13615 return ChangeStatus::UNCHANGED;
13619 const std::string getAsStr(Attributor *
A)
const override {
13620 if (!isValidState())
13621 return "allocationinfo(<invalid>)";
13622 return "allocationinfo(" +
13623 (AssumedAllocatedSize == HasNoAllocationSize
13625 : std::to_string(AssumedAllocatedSize->getFixedValue())) +
13630 std::optional<TypeSize> AssumedAllocatedSize = HasNoAllocationSize;
13634 bool changeAllocationSize(std::optional<TypeSize>
Size) {
13635 if (AssumedAllocatedSize == HasNoAllocationSize ||
13636 AssumedAllocatedSize !=
Size) {
13637 AssumedAllocatedSize =
Size;
13644struct AAAllocationInfoFloating : AAAllocationInfoImpl {
13645 AAAllocationInfoFloating(
const IRPosition &IRP, Attributor &
A)
13646 : AAAllocationInfoImpl(IRP,
A) {}
13648 void trackStatistics()
const override {
13653struct AAAllocationInfoReturned : AAAllocationInfoImpl {
13654 AAAllocationInfoReturned(
const IRPosition &IRP, Attributor &
A)
13655 : AAAllocationInfoImpl(IRP,
A) {}
13661 (void)indicatePessimisticFixpoint();
13664 void trackStatistics()
const override {
13669struct AAAllocationInfoCallSiteReturned : AAAllocationInfoImpl {
13670 AAAllocationInfoCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
13671 : AAAllocationInfoImpl(IRP,
A) {}
13673 void trackStatistics()
const override {
13678struct AAAllocationInfoArgument : AAAllocationInfoImpl {
13679 AAAllocationInfoArgument(
const IRPosition &IRP, Attributor &
A)
13680 : AAAllocationInfoImpl(IRP,
A) {}
13682 void trackStatistics()
const override {
13687struct AAAllocationInfoCallSiteArgument : AAAllocationInfoImpl {
13688 AAAllocationInfoCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
13689 : AAAllocationInfoImpl(IRP,
A) {}
13694 (void)indicatePessimisticFixpoint();
13697 void trackStatistics()
const override {
13746#define SWITCH_PK_INV(CLASS, PK, POS_NAME) \
13747 case IRPosition::PK: \
13748 llvm_unreachable("Cannot create " #CLASS " for a " POS_NAME " position!");
13750#define SWITCH_PK_CREATE(CLASS, IRP, PK, SUFFIX) \
13751 case IRPosition::PK: \
13752 AA = new (A.Allocator) CLASS##SUFFIX(IRP, A); \
13756#define CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13757 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13758 CLASS *AA = nullptr; \
13759 switch (IRP.getPositionKind()) { \
13760 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13761 SWITCH_PK_INV(CLASS, IRP_FLOAT, "floating") \
13762 SWITCH_PK_INV(CLASS, IRP_ARGUMENT, "argument") \
13763 SWITCH_PK_INV(CLASS, IRP_RETURNED, "returned") \
13764 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_RETURNED, "call site returned") \
13765 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_ARGUMENT, "call site argument") \
13766 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
13767 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE, CallSite) \
13772#define CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13773 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13774 CLASS *AA = nullptr; \
13775 switch (IRP.getPositionKind()) { \
13776 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13777 SWITCH_PK_INV(CLASS, IRP_FUNCTION, "function") \
13778 SWITCH_PK_INV(CLASS, IRP_CALL_SITE, "call site") \
13779 SWITCH_PK_CREATE(CLASS, IRP, IRP_FLOAT, Floating) \
13780 SWITCH_PK_CREATE(CLASS, IRP, IRP_ARGUMENT, Argument) \
13781 SWITCH_PK_CREATE(CLASS, IRP, IRP_RETURNED, Returned) \
13782 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_RETURNED, CallSiteReturned) \
13783 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_ARGUMENT, CallSiteArgument) \
13788#define CREATE_ABSTRACT_ATTRIBUTE_FOR_ONE_POSITION(POS, SUFFIX, CLASS) \
13789 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13790 CLASS *AA = nullptr; \
13791 switch (IRP.getPositionKind()) { \
13792 SWITCH_PK_CREATE(CLASS, IRP, POS, SUFFIX) \
13794 llvm_unreachable("Cannot create " #CLASS " for position otherthan " #POS \
13800#define CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13801 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13802 CLASS *AA = nullptr; \
13803 switch (IRP.getPositionKind()) { \
13804 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13805 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
13806 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE, CallSite) \
13807 SWITCH_PK_CREATE(CLASS, IRP, IRP_FLOAT, Floating) \
13808 SWITCH_PK_CREATE(CLASS, IRP, IRP_ARGUMENT, Argument) \
13809 SWITCH_PK_CREATE(CLASS, IRP, IRP_RETURNED, Returned) \
13810 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_RETURNED, CallSiteReturned) \
13811 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_ARGUMENT, CallSiteArgument) \
13816#define CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13817 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13818 CLASS *AA = nullptr; \
13819 switch (IRP.getPositionKind()) { \
13820 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13821 SWITCH_PK_INV(CLASS, IRP_ARGUMENT, "argument") \
13822 SWITCH_PK_INV(CLASS, IRP_FLOAT, "floating") \
13823 SWITCH_PK_INV(CLASS, IRP_RETURNED, "returned") \
13824 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_RETURNED, "call site returned") \
13825 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_ARGUMENT, "call site argument") \
13826 SWITCH_PK_INV(CLASS, IRP_CALL_SITE, "call site") \
13827 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
13832#define CREATE_NON_RET_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13833 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13834 CLASS *AA = nullptr; \
13835 switch (IRP.getPositionKind()) { \
13836 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13837 SWITCH_PK_INV(CLASS, IRP_RETURNED, "returned") \
13838 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
13839 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE, CallSite) \
13840 SWITCH_PK_CREATE(CLASS, IRP, IRP_FLOAT, Floating) \
13841 SWITCH_PK_CREATE(CLASS, IRP, IRP_ARGUMENT, Argument) \
13842 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_RETURNED, CallSiteReturned) \
13843 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_ARGUMENT, CallSiteArgument) \
13895#undef CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION
13896#undef CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION
13897#undef CREATE_NON_RET_ABSTRACT_ATTRIBUTE_FOR_POSITION
13898#undef CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION
13899#undef CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION
13900#undef CREATE_ABSTRACT_ATTRIBUTE_FOR_ONE_POSITION
13901#undef SWITCH_PK_CREATE
13902#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
PointerType * getType() const
Global values are always pointers.
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.
static constexpr Align fromLog2(unsigned Log2Value)
Returns an alignment of 1 << Log2Value bytes.
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.