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->getCalleeArgNo() == (
int)OtherArgNo)
3918 auto *CBArgMemBehaviorAA =
A.getAAFor<AAMemoryBehavior>(
3922 if (CBArgMemBehaviorAA && CBArgMemBehaviorAA->isAssumedReadNone()) {
3923 A.recordDependence(*CBArgMemBehaviorAA, *
this, DepClassTy::OPTIONAL);
3930 if (CBArgMemBehaviorAA && CBArgMemBehaviorAA->isAssumedReadOnly() &&
3932 A.recordDependence(MemBehaviorAA, *
this, DepClassTy::OPTIONAL);
3933 A.recordDependence(*CBArgMemBehaviorAA, *
this, DepClassTy::OPTIONAL);
3939 AAR =
A.getInfoCache().getAnalysisResultForFunction<AAManager>(
3943 bool IsAliasing = !AAR || !AAR->
isNoAlias(&getAssociatedValue(), ArgOp);
3945 "callsite arguments: "
3946 << getAssociatedValue() <<
" " << *ArgOp <<
" => "
3947 << (IsAliasing ?
"" :
"no-") <<
"alias \n");
3952 bool isKnownNoAliasDueToNoAliasPreservation(
3953 Attributor &
A, AAResults *&AAR,
const AAMemoryBehavior &MemBehaviorAA) {
3966 auto UsePred = [&](
const Use &
U,
bool &Follow) ->
bool {
3982 bool IsKnownNoCapture;
3985 DepClassTy::OPTIONAL, IsKnownNoCapture))
3991 A, *UserI, *getCtxI(), *
this,
nullptr,
3992 [ScopeFn](
const Function &Fn) {
return &Fn != ScopeFn; }))
4007 LLVM_DEBUG(
dbgs() <<
"[AANoAliasCSArg] Unknown user: " << *UserI <<
"\n");
4011 bool IsKnownNoCapture;
4012 const AANoCapture *NoCaptureAA =
nullptr;
4014 A,
this, VIRP, DepClassTy::NONE, IsKnownNoCapture,
false, &NoCaptureAA);
4015 if (!IsAssumedNoCapture &&
4017 if (!
A.checkForAllUses(UsePred, *
this, getAssociatedValue())) {
4019 dbgs() <<
"[AANoAliasCSArg] " << getAssociatedValue()
4020 <<
" cannot be noalias as it is potentially captured\n");
4025 A.recordDependence(*NoCaptureAA, *
this, DepClassTy::OPTIONAL);
4031 for (
unsigned OtherArgNo = 0; OtherArgNo < CB.
arg_size(); OtherArgNo++)
4032 if (mayAliasWithArgument(
A, AAR, MemBehaviorAA, CB, OtherArgNo))
4042 auto *MemBehaviorAA =
4043 A.getAAFor<AAMemoryBehavior>(*
this, getIRPosition(), DepClassTy::NONE);
4045 A.recordDependence(*MemBehaviorAA, *
this, DepClassTy::OPTIONAL);
4046 return ChangeStatus::UNCHANGED;
4049 bool IsKnownNoAlias;
4052 A,
this, VIRP, DepClassTy::REQUIRED, IsKnownNoAlias)) {
4054 <<
" is not no-alias at the definition\n");
4055 return indicatePessimisticFixpoint();
4058 AAResults *AAR =
nullptr;
4059 if (MemBehaviorAA &&
4060 isKnownNoAliasDueToNoAliasPreservation(
A, AAR, *MemBehaviorAA)) {
4062 dbgs() <<
"[AANoAlias] No-Alias deduced via no-alias preservation\n");
4063 return ChangeStatus::UNCHANGED;
4066 return indicatePessimisticFixpoint();
4074struct AANoAliasReturned final : AANoAliasImpl {
4075 AANoAliasReturned(
const IRPosition &IRP, Attributor &
A)
4076 : AANoAliasImpl(IRP,
A) {}
4081 auto CheckReturnValue = [&](
Value &RV) ->
bool {
4092 bool IsKnownNoAlias;
4094 A,
this, RVPos, DepClassTy::REQUIRED, IsKnownNoAlias))
4097 bool IsKnownNoCapture;
4098 const AANoCapture *NoCaptureAA =
nullptr;
4100 A,
this, RVPos, DepClassTy::REQUIRED, IsKnownNoCapture,
false,
4102 return IsAssumedNoCapture ||
4106 if (!
A.checkForAllReturnedValues(CheckReturnValue, *
this))
4107 return indicatePessimisticFixpoint();
4109 return ChangeStatus::UNCHANGED;
4117struct AANoAliasCallSiteReturned final
4118 : AACalleeToCallSite<AANoAlias, AANoAliasImpl> {
4119 AANoAliasCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
4120 : AACalleeToCallSite<AANoAlias, AANoAliasImpl>(IRP,
A) {}
4130struct AAIsDeadValueImpl :
public AAIsDead {
4131 AAIsDeadValueImpl(
const IRPosition &IRP, Attributor &
A) : AAIsDead(IRP,
A) {}
4134 bool isAssumedDead()
const override {
return isAssumed(IS_DEAD); }
4137 bool isKnownDead()
const override {
return isKnown(IS_DEAD); }
4140 bool isAssumedDead(
const BasicBlock *BB)
const override {
return false; }
4143 bool isKnownDead(
const BasicBlock *BB)
const override {
return false; }
4146 bool isAssumedDead(
const Instruction *
I)
const override {
4147 return I == getCtxI() && isAssumedDead();
4151 bool isKnownDead(
const Instruction *
I)
const override {
4152 return isAssumedDead(
I) && isKnownDead();
4156 const std::string getAsStr(Attributor *
A)
const override {
4157 return isAssumedDead() ?
"assumed-dead" :
"assumed-live";
4161 bool areAllUsesAssumedDead(Attributor &
A,
Value &V) {
4163 if (
V.getType()->isVoidTy() ||
V.use_empty())
4169 if (!
A.isRunOn(*
I->getFunction()))
4171 bool UsedAssumedInformation =
false;
4172 std::optional<Constant *>
C =
4173 A.getAssumedConstant(V, *
this, UsedAssumedInformation);
4178 auto UsePred = [&](
const Use &
U,
bool &Follow) {
return false; };
4183 return A.checkForAllUses(UsePred, *
this, V,
false,
4184 DepClassTy::REQUIRED,
4189 bool isAssumedSideEffectFree(Attributor &
A, Instruction *
I) {
4193 if (!
I->isTerminator() && !
I->mayHaveSideEffects())
4202 bool IsKnownNoUnwind;
4204 A,
this, CallIRP, DepClassTy::OPTIONAL, IsKnownNoUnwind))
4212struct AAIsDeadFloating :
public AAIsDeadValueImpl {
4213 AAIsDeadFloating(
const IRPosition &IRP, Attributor &
A)
4214 : AAIsDeadValueImpl(IRP,
A) {}
4218 AAIsDeadValueImpl::initialize(
A);
4221 indicatePessimisticFixpoint();
4226 if (!isAssumedSideEffectFree(
A,
I)) {
4228 indicatePessimisticFixpoint();
4230 removeAssumedBits(HAS_NO_EFFECT);
4234 bool isDeadFence(Attributor &
A, FenceInst &FI) {
4235 const auto *ExecDomainAA =
A.lookupAAFor<AAExecutionDomain>(
4237 if (!ExecDomainAA || !ExecDomainAA->isNoOpFence(FI))
4239 A.recordDependence(*ExecDomainAA, *
this, DepClassTy::OPTIONAL);
4243 bool isDeadStore(Attributor &
A, StoreInst &SI,
4244 SmallSetVector<Instruction *, 8> *AssumeOnlyInst =
nullptr) {
4246 if (
SI.isVolatile())
4252 bool UsedAssumedInformation =
false;
4253 if (!AssumeOnlyInst) {
4254 PotentialCopies.clear();
4256 UsedAssumedInformation)) {
4259 <<
"[AAIsDead] Could not determine potential copies of store!\n");
4263 LLVM_DEBUG(
dbgs() <<
"[AAIsDead] Store has " << PotentialCopies.size()
4264 <<
" potential copies.\n");
4266 InformationCache &InfoCache =
A.getInfoCache();
4269 UsedAssumedInformation))
4273 auto &UserI = cast<Instruction>(*U.getUser());
4274 if (InfoCache.isOnlyUsedByAssume(UserI)) {
4276 AssumeOnlyInst->insert(&UserI);
4279 return A.isAssumedDead(U,
this,
nullptr, UsedAssumedInformation);
4285 <<
" is assumed live!\n");
4291 const std::string getAsStr(Attributor *
A)
const override {
4295 return "assumed-dead-store";
4298 return "assumed-dead-fence";
4299 return AAIsDeadValueImpl::getAsStr(
A);
4306 if (!isDeadStore(
A, *SI))
4307 return indicatePessimisticFixpoint();
4309 if (!isDeadFence(
A, *FI))
4310 return indicatePessimisticFixpoint();
4312 if (!isAssumedSideEffectFree(
A,
I))
4313 return indicatePessimisticFixpoint();
4314 if (!areAllUsesAssumedDead(
A, getAssociatedValue()))
4315 return indicatePessimisticFixpoint();
4320 bool isRemovableStore()
const override {
4321 return isAssumed(IS_REMOVABLE) &&
isa<StoreInst>(&getAssociatedValue());
4326 Value &
V = getAssociatedValue();
4333 SmallSetVector<Instruction *, 8> AssumeOnlyInst;
4334 bool IsDead = isDeadStore(
A, *SI, &AssumeOnlyInst);
4337 A.deleteAfterManifest(*
I);
4338 for (
size_t i = 0; i < AssumeOnlyInst.
size(); ++i) {
4340 for (
auto *Usr : AOI->
users())
4342 A.deleteAfterManifest(*AOI);
4348 A.deleteAfterManifest(*FI);
4351 if (isAssumedSideEffectFree(
A,
I) && !
I->isTerminator()) {
4352 A.deleteAfterManifest(*
I);
4360 void trackStatistics()
const override {
4366 SmallSetVector<Value *, 4> PotentialCopies;
4369struct AAIsDeadArgument :
public AAIsDeadFloating {
4370 AAIsDeadArgument(
const IRPosition &IRP, Attributor &
A)
4371 : AAIsDeadFloating(IRP,
A) {}
4375 Argument &Arg = *getAssociatedArgument();
4376 if (
A.isValidFunctionSignatureRewrite(Arg, {}))
4377 if (
A.registerFunctionSignatureRewrite(
4381 return ChangeStatus::CHANGED;
4383 return ChangeStatus::UNCHANGED;
4390struct AAIsDeadCallSiteArgument :
public AAIsDeadValueImpl {
4391 AAIsDeadCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
4392 : AAIsDeadValueImpl(IRP,
A) {}
4396 AAIsDeadValueImpl::initialize(
A);
4398 indicatePessimisticFixpoint();
4407 Argument *Arg = getAssociatedArgument();
4409 return indicatePessimisticFixpoint();
4411 auto *ArgAA =
A.getAAFor<AAIsDead>(*
this, ArgPos, DepClassTy::REQUIRED);
4413 return indicatePessimisticFixpoint();
4422 "Expected undef values to be filtered out!");
4424 if (
A.changeUseAfterManifest(U, UV))
4425 return ChangeStatus::CHANGED;
4426 return ChangeStatus::UNCHANGED;
4433struct AAIsDeadCallSiteReturned :
public AAIsDeadFloating {
4434 AAIsDeadCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
4435 : AAIsDeadFloating(IRP,
A) {}
4438 bool isAssumedDead()
const override {
4439 return AAIsDeadFloating::isAssumedDead() && IsAssumedSideEffectFree;
4444 AAIsDeadFloating::initialize(
A);
4446 indicatePessimisticFixpoint();
4451 IsAssumedSideEffectFree = isAssumedSideEffectFree(
A, getCtxI());
4457 if (IsAssumedSideEffectFree && !isAssumedSideEffectFree(
A, getCtxI())) {
4458 IsAssumedSideEffectFree =
false;
4459 Changed = ChangeStatus::CHANGED;
4461 if (!areAllUsesAssumedDead(
A, getAssociatedValue()))
4462 return indicatePessimisticFixpoint();
4467 void trackStatistics()
const override {
4468 if (IsAssumedSideEffectFree)
4475 const std::string getAsStr(Attributor *
A)
const override {
4476 return isAssumedDead()
4478 : (getAssumed() ?
"assumed-dead-users" :
"assumed-live");
4482 bool IsAssumedSideEffectFree =
true;
4485struct AAIsDeadReturned :
public AAIsDeadValueImpl {
4486 AAIsDeadReturned(
const IRPosition &IRP, Attributor &
A)
4487 : AAIsDeadValueImpl(IRP,
A) {}
4492 bool UsedAssumedInformation =
false;
4493 A.checkForAllInstructions([](Instruction &) {
return true; }, *
this,
4494 {Instruction::Ret}, UsedAssumedInformation);
4496 auto PredForCallSite = [&](AbstractCallSite ACS) {
4497 if (ACS.isCallbackCall() || !ACS.getInstruction())
4499 return areAllUsesAssumedDead(
A, *ACS.getInstruction());
4502 if (!
A.checkForAllCallSites(PredForCallSite, *
this,
true,
4503 UsedAssumedInformation))
4504 return indicatePessimisticFixpoint();
4506 return ChangeStatus::UNCHANGED;
4512 bool AnyChange =
false;
4513 UndefValue &UV = *
UndefValue::get(getAssociatedFunction()->getReturnType());
4520 bool UsedAssumedInformation =
false;
4521 A.checkForAllInstructions(RetInstPred, *
this, {Instruction::Ret},
4522 UsedAssumedInformation);
4523 return AnyChange ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
4530struct AAIsDeadFunction :
public AAIsDead {
4531 AAIsDeadFunction(
const IRPosition &IRP, Attributor &
A) : AAIsDead(IRP,
A) {}
4536 assert(
F &&
"Did expect an anchor function");
4537 if (!isAssumedDeadInternalFunction(
A)) {
4538 ToBeExploredFrom.insert(&
F->getEntryBlock().front());
4539 assumeLive(
A,
F->getEntryBlock());
4543 bool isAssumedDeadInternalFunction(Attributor &
A) {
4544 if (!getAnchorScope()->hasLocalLinkage())
4546 bool UsedAssumedInformation =
false;
4547 return A.checkForAllCallSites([](AbstractCallSite) {
return false; }, *
this,
4548 true, UsedAssumedInformation);
4552 const std::string getAsStr(Attributor *
A)
const override {
4553 return "Live[#BB " + std::to_string(AssumedLiveBlocks.size()) +
"/" +
4554 std::to_string(getAnchorScope()->
size()) +
"][#TBEP " +
4555 std::to_string(ToBeExploredFrom.size()) +
"][#KDE " +
4556 std::to_string(KnownDeadEnds.size()) +
"]";
4561 assert(getState().isValidState() &&
4562 "Attempted to manifest an invalid state!");
4567 if (AssumedLiveBlocks.empty()) {
4568 A.deleteAfterManifest(
F);
4569 return ChangeStatus::CHANGED;
4575 bool Invoke2CallAllowed = !mayCatchAsynchronousExceptions(
F);
4577 KnownDeadEnds.set_union(ToBeExploredFrom);
4578 for (
const Instruction *DeadEndI : KnownDeadEnds) {
4582 bool IsKnownNoReturn;
4590 A.registerInvokeWithDeadSuccessor(
const_cast<InvokeInst &
>(*
II));
4592 A.changeToUnreachableAfterManifest(
4593 const_cast<Instruction *
>(DeadEndI->getNextNode()));
4594 HasChanged = ChangeStatus::CHANGED;
4597 STATS_DECL(AAIsDead, BasicBlock,
"Number of dead basic blocks deleted.");
4598 for (BasicBlock &BB :
F)
4599 if (!AssumedLiveBlocks.count(&BB)) {
4600 A.deleteAfterManifest(BB);
4602 HasChanged = ChangeStatus::CHANGED;
4611 bool isEdgeDead(
const BasicBlock *From,
const BasicBlock *To)
const override {
4614 "Used AAIsDead of the wrong function");
4615 return isValidState() && !AssumedLiveEdges.count(std::make_pair(From, To));
4619 void trackStatistics()
const override {}
4622 bool isAssumedDead()
const override {
return false; }
4625 bool isKnownDead()
const override {
return false; }
4628 bool isAssumedDead(
const BasicBlock *BB)
const override {
4630 "BB must be in the same anchor scope function.");
4634 return !AssumedLiveBlocks.count(BB);
4638 bool isKnownDead(
const BasicBlock *BB)
const override {
4639 return getKnown() && isAssumedDead(BB);
4643 bool isAssumedDead(
const Instruction *
I)
const override {
4644 assert(
I->getParent()->getParent() == getAnchorScope() &&
4645 "Instruction must be in the same anchor scope function.");
4652 if (!AssumedLiveBlocks.count(
I->getParent()))
4658 if (KnownDeadEnds.count(PrevI) || ToBeExploredFrom.count(PrevI))
4666 bool isKnownDead(
const Instruction *
I)
const override {
4667 return getKnown() && isAssumedDead(
I);
4672 bool assumeLive(Attributor &
A,
const BasicBlock &BB) {
4673 if (!AssumedLiveBlocks.insert(&BB).second)
4676 if (!
A.isDuringDeduction())
4683 for (
const Instruction &
I : BB)
4686 if (
F->hasLocalLinkage()) {
4688 dbgs() <<
"[AAIsDead] Seeding live internal callee ";
4689 F->printAsOperand(
dbgs(),
false);
4691 BB.getParent()->printAsOperand(
dbgs(),
false);
4694 A.markLiveInternalFunction(*
F);
4701 SmallSetVector<const Instruction *, 8> ToBeExploredFrom;
4704 SmallSetVector<const Instruction *, 8> KnownDeadEnds;
4707 DenseSet<std::pair<const BasicBlock *, const BasicBlock *>> AssumedLiveEdges;
4710 DenseSet<const BasicBlock *> AssumedLiveBlocks;
4714identifyAliveSuccessors(Attributor &
A,
const CallBase &CB,
4715 AbstractAttribute &AA,
4716 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4719 bool IsKnownNoReturn;
4722 return !IsKnownNoReturn;
4731identifyAliveSuccessors(Attributor &
A,
const InvokeInst &
II,
4732 AbstractAttribute &AA,
4733 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4734 bool UsedAssumedInformation =
4740 if (AAIsDeadFunction::mayCatchAsynchronousExceptions(*
II.getFunction())) {
4741 AliveSuccessors.
push_back(&
II.getUnwindDest()->front());
4745 bool IsKnownNoUnwind;
4748 UsedAssumedInformation |= !IsKnownNoUnwind;
4750 AliveSuccessors.
push_back(&
II.getUnwindDest()->front());
4753 return UsedAssumedInformation;
4757identifyAliveSuccessors(Attributor &,
const UncondBrInst &BI,
4758 AbstractAttribute &,
4759 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4765identifyAliveSuccessors(Attributor &
A,
const CondBrInst &BI,
4766 AbstractAttribute &AA,
4767 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4768 bool UsedAssumedInformation =
false;
4769 std::optional<Constant *>
C =
4770 A.getAssumedConstant(*BI.
getCondition(), AA, UsedAssumedInformation);
4780 UsedAssumedInformation =
false;
4782 return UsedAssumedInformation;
4786identifyAliveSuccessors(Attributor &
A,
const SwitchInst &SI,
4787 AbstractAttribute &AA,
4788 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4789 bool UsedAssumedInformation =
false;
4793 UsedAssumedInformation)) {
4795 for (
const BasicBlock *SuccBB :
successors(
SI.getParent()))
4804 return UsedAssumedInformation;
4807 Type &Ty = *
SI.getCondition()->getType();
4808 SmallPtrSet<ConstantInt *, 8>
Constants;
4809 auto CheckForConstantInt = [&](
Value *
V) {
4818 return CheckForConstantInt(VAC.
getValue());
4820 for (
const BasicBlock *SuccBB :
successors(
SI.getParent()))
4822 return UsedAssumedInformation;
4825 unsigned MatchedCases = 0;
4826 for (
const auto &CaseIt :
SI.cases()) {
4827 if (
Constants.count(CaseIt.getCaseValue())) {
4829 AliveSuccessors.
push_back(&CaseIt.getCaseSuccessor()->front());
4836 AliveSuccessors.
push_back(&
SI.getDefaultDest()->front());
4837 return UsedAssumedInformation;
4843 if (AssumedLiveBlocks.empty()) {
4844 if (isAssumedDeadInternalFunction(
A))
4848 ToBeExploredFrom.insert(&
F->getEntryBlock().front());
4849 assumeLive(
A,
F->getEntryBlock());
4853 LLVM_DEBUG(
dbgs() <<
"[AAIsDead] Live [" << AssumedLiveBlocks.size() <<
"/"
4854 << getAnchorScope()->
size() <<
"] BBs and "
4855 << ToBeExploredFrom.size() <<
" exploration points and "
4856 << KnownDeadEnds.size() <<
" known dead ends\n");
4861 ToBeExploredFrom.end());
4862 decltype(ToBeExploredFrom) NewToBeExploredFrom;
4865 while (!Worklist.
empty()) {
4872 I =
I->getNextNode();
4874 AliveSuccessors.
clear();
4876 bool UsedAssumedInformation =
false;
4877 switch (
I->getOpcode()) {
4881 "Expected non-terminators to be handled already!");
4882 for (
const BasicBlock *SuccBB :
successors(
I->getParent()))
4885 case Instruction::Call:
4887 *
this, AliveSuccessors);
4889 case Instruction::Invoke:
4891 *
this, AliveSuccessors);
4893 case Instruction::UncondBr:
4894 UsedAssumedInformation = identifyAliveSuccessors(
4897 case Instruction::CondBr:
4899 *
this, AliveSuccessors);
4901 case Instruction::Switch:
4903 *
this, AliveSuccessors);
4907 if (UsedAssumedInformation) {
4908 NewToBeExploredFrom.insert(
I);
4909 }
else if (AliveSuccessors.
empty() ||
4910 (
I->isTerminator() &&
4911 AliveSuccessors.
size() <
I->getNumSuccessors())) {
4912 if (KnownDeadEnds.insert(
I))
4917 << AliveSuccessors.
size() <<
" UsedAssumedInformation: "
4918 << UsedAssumedInformation <<
"\n");
4920 for (
const Instruction *AliveSuccessor : AliveSuccessors) {
4921 if (!
I->isTerminator()) {
4922 assert(AliveSuccessors.size() == 1 &&
4923 "Non-terminator expected to have a single successor!");
4927 auto Edge = std::make_pair(
I->getParent(), AliveSuccessor->getParent());
4928 if (AssumedLiveEdges.insert(
Edge).second)
4930 if (assumeLive(
A, *AliveSuccessor->getParent()))
4937 if (NewToBeExploredFrom.size() != ToBeExploredFrom.size() ||
4938 llvm::any_of(NewToBeExploredFrom, [&](
const Instruction *
I) {
4939 return !ToBeExploredFrom.count(I);
4942 ToBeExploredFrom = std::move(NewToBeExploredFrom);
4951 if (ToBeExploredFrom.empty() &&
4952 getAnchorScope()->
size() == AssumedLiveBlocks.size() &&
4953 llvm::all_of(KnownDeadEnds, [](
const Instruction *DeadEndI) {
4954 return DeadEndI->isTerminator() && DeadEndI->getNumSuccessors() == 0;
4956 return indicatePessimisticFixpoint();
4961struct AAIsDeadCallSite final : AAIsDeadFunction {
4962 AAIsDeadCallSite(
const IRPosition &IRP, Attributor &
A)
4963 : AAIsDeadFunction(IRP,
A) {}
4972 "supported for call sites yet!");
4977 return indicatePessimisticFixpoint();
4981 void trackStatistics()
const override {}
4988struct AADereferenceableImpl : AADereferenceable {
4989 AADereferenceableImpl(
const IRPosition &IRP, Attributor &
A)
4990 : AADereferenceable(IRP,
A) {}
4991 using StateType = DerefState;
4995 Value &
V = *getAssociatedValue().stripPointerCasts();
4997 A.getAttrs(getIRPosition(),
4998 {Attribute::Dereferenceable, Attribute::DereferenceableOrNull},
5001 takeKnownDerefBytesMaximum(Attr.getValueAsInt());
5004 bool IsKnownNonNull;
5006 A,
this, getIRPosition(), DepClassTy::OPTIONAL, IsKnownNonNull);
5009 takeKnownDerefBytesMaximum(
V.getPointerDereferenceableBytes(
5010 A.getDataLayout(), CanBeNull,
nullptr));
5012 if (Instruction *CtxI = getCtxI())
5013 followUsesInMBEC(*
this,
A, getState(), *CtxI);
5018 StateType &getState()
override {
return *
this; }
5019 const StateType &getState()
const override {
return *
this; }
5023 void addAccessedBytesForUse(Attributor &
A,
const Use *U,
const Instruction *
I,
5024 DerefState &State) {
5025 const Value *UseV =
U->get();
5030 if (!Loc || Loc->Ptr != UseV || !Loc->Size.isPrecise() ||
I->isVolatile())
5035 Loc->Ptr,
Offset,
A.getDataLayout(),
true);
5036 if (
Base &&
Base == &getAssociatedValue())
5037 State.addAccessedBytes(
Offset, Loc->Size.getValue());
5041 bool followUseInMBEC(Attributor &
A,
const Use *U,
const Instruction *
I,
5042 AADereferenceable::StateType &State) {
5043 bool IsNonNull =
false;
5044 bool TrackUse =
false;
5045 int64_t DerefBytes = getKnownNonNullAndDerefBytesForUse(
5046 A, *
this, getAssociatedValue(), U,
I, IsNonNull, TrackUse);
5047 LLVM_DEBUG(
dbgs() <<
"[AADereferenceable] Deref bytes: " << DerefBytes
5048 <<
" for instruction " << *
I <<
"\n");
5050 addAccessedBytesForUse(
A, U,
I, State);
5051 State.takeKnownDerefBytesMaximum(DerefBytes);
5058 bool IsKnownNonNull;
5060 A,
this, getIRPosition(), DepClassTy::NONE, IsKnownNonNull);
5061 if (IsAssumedNonNull &&
5062 A.hasAttr(getIRPosition(), Attribute::DereferenceableOrNull)) {
5063 A.removeAttrs(getIRPosition(), {Attribute::DereferenceableOrNull});
5064 return ChangeStatus::CHANGED;
5069 void getDeducedAttributes(Attributor &
A, LLVMContext &Ctx,
5070 SmallVectorImpl<Attribute> &Attrs)
const override {
5072 bool IsKnownNonNull;
5074 A,
this, getIRPosition(), DepClassTy::NONE, IsKnownNonNull);
5075 if (IsAssumedNonNull)
5076 Attrs.emplace_back(Attribute::getWithDereferenceableBytes(
5077 Ctx, getAssumedDereferenceableBytes()));
5079 Attrs.emplace_back(Attribute::getWithDereferenceableOrNullBytes(
5080 Ctx, getAssumedDereferenceableBytes()));
5084 const std::string getAsStr(Attributor *
A)
const override {
5085 if (!getAssumedDereferenceableBytes())
5086 return "unknown-dereferenceable";
5087 bool IsKnownNonNull;
5088 bool IsAssumedNonNull =
false;
5091 *
A,
this, getIRPosition(), DepClassTy::NONE, IsKnownNonNull);
5092 return std::string(
"dereferenceable") +
5093 (IsAssumedNonNull ?
"" :
"_or_null") +
5094 (isAssumedGlobal() ?
"_globally" :
"") +
"<" +
5095 std::to_string(getKnownDereferenceableBytes()) +
"-" +
5096 std::to_string(getAssumedDereferenceableBytes()) +
">" +
5097 (!
A ?
" [non-null is unknown]" :
"");
5102struct AADereferenceableFloating : AADereferenceableImpl {
5103 AADereferenceableFloating(
const IRPosition &IRP, Attributor &
A)
5104 : AADereferenceableImpl(IRP,
A) {}
5109 bool UsedAssumedInformation =
false;
5111 if (!
A.getAssumedSimplifiedValues(getIRPosition(), *
this,
Values,
5113 Values.push_back({getAssociatedValue(), getCtxI()});
5116 Stripped =
Values.size() != 1 ||
5117 Values.front().getValue() != &getAssociatedValue();
5120 const DataLayout &
DL =
A.getDataLayout();
5123 auto VisitValueCB = [&](
const Value &
V) ->
bool {
5125 DL.getIndexSizeInBits(
V.getType()->getPointerAddressSpace());
5126 APInt
Offset(IdxWidth, 0);
5131 const auto *AA =
A.getAAFor<AADereferenceable>(
5133 int64_t DerefBytes = 0;
5134 if (!AA || (!Stripped &&
this == AA)) {
5138 DerefBytes =
Base->getPointerDereferenceableBytes(
5139 DL, CanBeNull,
nullptr);
5140 T.GlobalState.indicatePessimisticFixpoint();
5143 DerefBytes =
DS.DerefBytesState.getAssumed();
5144 T.GlobalState &=
DS.GlobalState;
5150 int64_t OffsetSExt =
Offset.getSExtValue();
5154 T.takeAssumedDerefBytesMinimum(
5155 std::max(int64_t(0), DerefBytes - OffsetSExt));
5160 T.takeKnownDerefBytesMaximum(
5161 std::max(int64_t(0), DerefBytes - OffsetSExt));
5162 T.indicatePessimisticFixpoint();
5163 }
else if (OffsetSExt > 0) {
5169 T.indicatePessimisticFixpoint();
5173 return T.isValidState();
5176 for (
const auto &VAC :
Values)
5177 if (!VisitValueCB(*VAC.
getValue()))
5178 return indicatePessimisticFixpoint();
5184 void trackStatistics()
const override {
5190struct AADereferenceableReturned final
5191 : AAReturnedFromReturnedValues<AADereferenceable, AADereferenceableImpl> {
5193 AAReturnedFromReturnedValues<AADereferenceable, AADereferenceableImpl>;
5194 AADereferenceableReturned(
const IRPosition &IRP, Attributor &
A)
5198 void trackStatistics()
const override {
5204struct AADereferenceableArgument final
5205 : AAArgumentFromCallSiteArguments<AADereferenceable,
5206 AADereferenceableImpl> {
5208 AAArgumentFromCallSiteArguments<AADereferenceable, AADereferenceableImpl>;
5209 AADereferenceableArgument(
const IRPosition &IRP, Attributor &
A)
5213 void trackStatistics()
const override {
5219struct AADereferenceableCallSiteArgument final : AADereferenceableFloating {
5220 AADereferenceableCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
5221 : AADereferenceableFloating(IRP,
A) {}
5224 void trackStatistics()
const override {
5230struct AADereferenceableCallSiteReturned final
5231 : AACalleeToCallSite<AADereferenceable, AADereferenceableImpl> {
5232 using Base = AACalleeToCallSite<AADereferenceable, AADereferenceableImpl>;
5233 AADereferenceableCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
5237 void trackStatistics()
const override {
5247static unsigned getKnownAlignForUse(Attributor &
A, AAAlign &QueryingAA,
5248 Value &AssociatedValue,
const Use *U,
5249 const Instruction *
I,
bool &TrackUse) {
5258 if (
GEP->hasAllConstantIndices())
5263 switch (
II->getIntrinsicID()) {
5264 case Intrinsic::ptrmask: {
5266 const auto *ConstVals =
A.getAAFor<AAPotentialConstantValues>(
5268 const auto *AlignAA =
A.getAAFor<AAAlign>(
5270 if (ConstVals && ConstVals->isValidState() && ConstVals->isAtFixpoint()) {
5271 unsigned ShiftValue = std::min(ConstVals->getAssumedMinTrailingZeros(),
5273 Align ConstAlign(UINT64_C(1) << ShiftValue);
5274 if (ConstAlign >= AlignAA->getKnownAlign())
5275 return Align(1).value();
5278 return AlignAA->getKnownAlign().
value();
5281 case Intrinsic::amdgcn_make_buffer_rsrc: {
5282 const auto *AlignAA =
A.getAAFor<AAAlign>(
5285 return AlignAA->getKnownAlign().
value();
5303 MA = MaybeAlign(AlignAA->getKnownAlign());
5306 const DataLayout &
DL =
A.getDataLayout();
5307 const Value *UseV =
U->get();
5309 if (
SI->getPointerOperand() == UseV)
5310 MA =
SI->getAlign();
5312 if (LI->getPointerOperand() == UseV)
5313 MA = LI->getAlign();
5315 if (AI->getPointerOperand() == UseV)
5316 MA = AI->getAlign();
5318 if (AI->getPointerOperand() == UseV)
5319 MA = AI->getAlign();
5329 if (
Base == &AssociatedValue) {
5334 uint32_t
gcd = std::gcd(uint32_t(
abs((int32_t)
Offset)), Alignment);
5342struct AAAlignImpl : AAAlign {
5343 AAAlignImpl(
const IRPosition &IRP, Attributor &
A) : AAAlign(IRP,
A) {}
5348 A.getAttrs(getIRPosition(), {Attribute::Alignment},
Attrs);
5350 takeKnownMaximum(Attr.getValueAsInt());
5352 Value &
V = *getAssociatedValue().stripPointerCasts();
5353 takeKnownMaximum(
V.getPointerAlignment(
A.getDataLayout()).value());
5355 if (Instruction *CtxI = getCtxI())
5356 followUsesInMBEC(*
this,
A, getState(), *CtxI);
5364 Value &AssociatedValue = getAssociatedValue();
5366 return ChangeStatus::UNCHANGED;
5368 for (
const Use &U : AssociatedValue.
uses()) {
5370 if (
SI->getPointerOperand() == &AssociatedValue)
5371 if (
SI->getAlign() < getAssumedAlign()) {
5373 "Number of times alignment added to a store");
5374 SI->setAlignment(getAssumedAlign());
5375 InstrChanged = ChangeStatus::CHANGED;
5378 if (LI->getPointerOperand() == &AssociatedValue)
5379 if (LI->getAlign() < getAssumedAlign()) {
5380 LI->setAlignment(getAssumedAlign());
5382 "Number of times alignment added to a load");
5383 InstrChanged = ChangeStatus::CHANGED;
5386 if (RMW->getPointerOperand() == &AssociatedValue) {
5387 if (RMW->getAlign() < getAssumedAlign()) {
5389 "Number of times alignment added to atomicrmw");
5391 RMW->setAlignment(getAssumedAlign());
5392 InstrChanged = ChangeStatus::CHANGED;
5396 if (CAS->getPointerOperand() == &AssociatedValue) {
5397 if (CAS->getAlign() < getAssumedAlign()) {
5399 "Number of times alignment added to cmpxchg");
5400 CAS->setAlignment(getAssumedAlign());
5401 InstrChanged = ChangeStatus::CHANGED;
5409 Align InheritAlign =
5410 getAssociatedValue().getPointerAlignment(
A.getDataLayout());
5411 if (InheritAlign >= getAssumedAlign())
5412 return InstrChanged;
5413 return Changed | InstrChanged;
5421 void getDeducedAttributes(Attributor &
A, LLVMContext &Ctx,
5422 SmallVectorImpl<Attribute> &Attrs)
const override {
5423 if (getAssumedAlign() > 1)
5425 Attribute::getWithAlignment(Ctx,
Align(getAssumedAlign())));
5429 bool followUseInMBEC(Attributor &
A,
const Use *U,
const Instruction *
I,
5430 AAAlign::StateType &State) {
5431 bool TrackUse =
false;
5433 unsigned int KnownAlign =
5434 getKnownAlignForUse(
A, *
this, getAssociatedValue(), U,
I, TrackUse);
5435 State.takeKnownMaximum(KnownAlign);
5441 const std::string getAsStr(Attributor *
A)
const override {
5442 return "align<" + std::to_string(getKnownAlign().value()) +
"-" +
5443 std::to_string(getAssumedAlign().value()) +
">";
5448struct AAAlignFloating : AAAlignImpl {
5449 AAAlignFloating(
const IRPosition &IRP, Attributor &
A) : AAAlignImpl(IRP,
A) {}
5453 const DataLayout &
DL =
A.getDataLayout();
5456 bool UsedAssumedInformation =
false;
5458 if (!
A.getAssumedSimplifiedValues(getIRPosition(), *
this,
Values,
5460 Values.push_back({getAssociatedValue(), getCtxI()});
5463 Stripped =
Values.size() != 1 ||
5464 Values.front().getValue() != &getAssociatedValue();
5468 auto VisitValueCB = [&](
Value &
V) ->
bool {
5472 DepClassTy::REQUIRED);
5473 if (!AA || (!Stripped &&
this == AA)) {
5491 T.takeKnownMaximum(Alignment);
5492 T.indicatePessimisticFixpoint();
5495 const AAAlign::StateType &
DS = AA->
getState();
5498 return T.isValidState();
5501 for (
const auto &VAC :
Values) {
5502 if (!VisitValueCB(*VAC.
getValue()))
5503 return indicatePessimisticFixpoint();
5516struct AAAlignReturned final
5517 : AAReturnedFromReturnedValues<AAAlign, AAAlignImpl> {
5518 using Base = AAReturnedFromReturnedValues<AAAlign, AAAlignImpl>;
5519 AAAlignReturned(
const IRPosition &IRP, Attributor &
A) :
Base(IRP,
A) {}
5526struct AAAlignArgument final
5527 : AAArgumentFromCallSiteArguments<AAAlign, AAAlignImpl> {
5528 using Base = AAArgumentFromCallSiteArguments<AAAlign, AAAlignImpl>;
5529 AAAlignArgument(
const IRPosition &IRP, Attributor &
A) :
Base(IRP,
A) {}
5536 if (
A.getInfoCache().isInvolvedInMustTailCall(*getAssociatedArgument()))
5537 return ChangeStatus::UNCHANGED;
5538 return Base::manifest(
A);
5545struct AAAlignCallSiteArgument final : AAAlignFloating {
5546 AAAlignCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
5547 : AAAlignFloating(IRP,
A) {}
5554 if (Argument *Arg = getAssociatedArgument())
5555 if (
A.getInfoCache().isInvolvedInMustTailCall(*Arg))
5556 return ChangeStatus::UNCHANGED;
5558 Align InheritAlign =
5559 getAssociatedValue().getPointerAlignment(
A.getDataLayout());
5560 if (InheritAlign >= getAssumedAlign())
5561 Changed = ChangeStatus::UNCHANGED;
5568 if (Argument *Arg = getAssociatedArgument()) {
5571 const auto *ArgAlignAA =
A.getAAFor<AAAlign>(
5574 takeKnownMaximum(ArgAlignAA->getKnownAlign().value());
5584struct AAAlignCallSiteReturned final
5585 : AACalleeToCallSite<AAAlign, AAAlignImpl> {
5586 using Base = AACalleeToCallSite<AAAlign, AAAlignImpl>;
5587 AAAlignCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
5593 switch (
II->getIntrinsicID()) {
5594 case Intrinsic::ptrmask: {
5598 const auto *ConstVals =
A.getAAFor<AAPotentialConstantValues>(
5600 if (ConstVals && ConstVals->isValidState()) {
5601 unsigned ShiftValue =
5602 std::min(ConstVals->getAssumedMinTrailingZeros(),
5603 Value::MaxAlignmentExponent);
5608 const auto *AlignAA =
5610 DepClassTy::REQUIRED);
5612 Alignment = std::max(AlignAA->getAssumedAlign(), Alignment);
5619 std::min(this->getAssumedAlign(), Alignment).value());
5625 case Intrinsic::amdgcn_make_buffer_rsrc: {
5626 const auto *AlignAA =
5628 DepClassTy::REQUIRED);
5631 this->getState(), AlignAA->getAssumedAlign().
value());
5638 return Base::updateImpl(
A);
5647struct AANoReturnImpl :
public AANoReturn {
5648 AANoReturnImpl(
const IRPosition &IRP, Attributor &
A) : AANoReturn(IRP,
A) {}
5654 A,
nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));
5659 const std::string getAsStr(Attributor *
A)
const override {
5660 return getAssumed() ?
"noreturn" :
"may-return";
5665 auto CheckForNoReturn = [](
Instruction &) {
return false; };
5666 bool UsedAssumedInformation =
false;
5667 if (!
A.checkForAllInstructions(CheckForNoReturn, *
this,
5668 {(unsigned)Instruction::Ret},
5669 UsedAssumedInformation))
5670 return indicatePessimisticFixpoint();
5671 return ChangeStatus::UNCHANGED;
5675struct AANoReturnFunction final : AANoReturnImpl {
5676 AANoReturnFunction(
const IRPosition &IRP, Attributor &
A)
5677 : AANoReturnImpl(IRP,
A) {}
5684struct AANoReturnCallSite final
5685 : AACalleeToCallSite<AANoReturn, AANoReturnImpl> {
5686 AANoReturnCallSite(
const IRPosition &IRP, Attributor &
A)
5687 : AACalleeToCallSite<AANoReturn, AANoReturnImpl>(IRP,
A) {}
5698struct AAInstanceInfoImpl :
public AAInstanceInfo {
5699 AAInstanceInfoImpl(
const IRPosition &IRP, Attributor &
A)
5700 : AAInstanceInfo(IRP,
A) {}
5704 Value &
V = getAssociatedValue();
5706 if (
C->isThreadDependent())
5707 indicatePessimisticFixpoint();
5709 indicateOptimisticFixpoint();
5715 indicateOptimisticFixpoint();
5720 A.getInfoCache().getAnalysisResultForFunction<CycleAnalysis>(
5723 indicatePessimisticFixpoint();
5733 Value &
V = getAssociatedValue();
5736 Scope =
I->getFunction();
5739 if (!
Scope->hasLocalLinkage())
5743 return indicateOptimisticFixpoint();
5745 bool IsKnownNoRecurse;
5751 auto UsePred = [&](
const Use &
U,
bool &Follow) {
5766 if (!Callee || !
Callee->hasLocalLinkage())
5770 const auto *ArgInstanceInfoAA =
A.getAAFor<AAInstanceInfo>(
5772 DepClassTy::OPTIONAL);
5773 if (!ArgInstanceInfoAA ||
5774 !ArgInstanceInfoAA->isAssumedUniqueForAnalysis())
5779 A, *CB, *Scope, *
this,
nullptr,
5787 auto EquivalentUseCB = [&](
const Use &OldU,
const Use &NewU) {
5789 auto *Ptr =
SI->getPointerOperand()->stripPointerCasts();
5797 if (!
A.checkForAllUses(UsePred, *
this, V,
true,
5798 DepClassTy::OPTIONAL,
5799 true, EquivalentUseCB))
5800 return indicatePessimisticFixpoint();
5806 const std::string getAsStr(Attributor *
A)
const override {
5807 return isAssumedUniqueForAnalysis() ?
"<unique [fAa]>" :
"<unknown>";
5811 void trackStatistics()
const override {}
5815struct AAInstanceInfoFloating : AAInstanceInfoImpl {
5816 AAInstanceInfoFloating(
const IRPosition &IRP, Attributor &
A)
5817 : AAInstanceInfoImpl(IRP,
A) {}
5821struct AAInstanceInfoArgument final : AAInstanceInfoFloating {
5822 AAInstanceInfoArgument(
const IRPosition &IRP, Attributor &
A)
5823 : AAInstanceInfoFloating(IRP,
A) {}
5827struct AAInstanceInfoCallSiteArgument final : AAInstanceInfoImpl {
5828 AAInstanceInfoCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
5829 : AAInstanceInfoImpl(IRP,
A) {}
5837 Argument *Arg = getAssociatedArgument();
5839 return indicatePessimisticFixpoint();
5842 A.getAAFor<AAInstanceInfo>(*
this, ArgPos, DepClassTy::REQUIRED);
5844 return indicatePessimisticFixpoint();
5850struct AAInstanceInfoReturned final : AAInstanceInfoImpl {
5851 AAInstanceInfoReturned(
const IRPosition &IRP, Attributor &
A)
5852 : AAInstanceInfoImpl(IRP,
A) {
5868struct AAInstanceInfoCallSiteReturned final : AAInstanceInfoFloating {
5869 AAInstanceInfoCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
5870 : AAInstanceInfoFloating(IRP,
A) {}
5877 bool IgnoreSubsumingPositions) {
5878 assert(ImpliedAttributeKind == Attribute::Captures &&
5879 "Unexpected attribute kind");
5889 V.getType()->getPointerAddressSpace() == 0)) {
5894 A.getAttrs(IRP, {Attribute::Captures}, Attrs,
5904 {Attribute::Captures, Attribute::ByVal}, Attrs,
5942 bool NoThrow =
F.doesNotThrow();
5943 bool IsVoidReturn =
F.getReturnType()->isVoidTy();
5944 if (
ReadOnly && NoThrow && IsVoidReturn) {
5957 if (NoThrow && IsVoidReturn)
5962 if (!NoThrow || ArgNo < 0 ||
5963 !
F.getAttributes().hasAttrSomewhere(Attribute::Returned))
5966 for (
unsigned U = 0, E =
F.arg_size(); U < E; ++U)
5967 if (
F.hasParamAttribute(U, Attribute::Returned)) {
5968 if (U ==
unsigned(ArgNo))
5995 void getDeducedAttributes(Attributor &
A, LLVMContext &Ctx,
5996 SmallVectorImpl<Attribute> &Attrs)
const override {
5997 if (!isAssumedNoCaptureMaybeReturned())
6000 if (isArgumentPosition()) {
6001 if (isAssumedNoCapture())
6002 Attrs.emplace_back(Attribute::get(Ctx, Attribute::Captures));
6004 Attrs.emplace_back(Attribute::get(Ctx,
"no-capture-maybe-returned"));
6009 const std::string getAsStr(Attributor *
A)
const override {
6010 if (isKnownNoCapture())
6011 return "known not-captured";
6012 if (isAssumedNoCapture())
6013 return "assumed not-captured";
6014 if (isKnownNoCaptureMaybeReturned())
6015 return "known not-captured-maybe-returned";
6016 if (isAssumedNoCaptureMaybeReturned())
6017 return "assumed not-captured-maybe-returned";
6018 return "assumed-captured";
6023 bool checkUse(Attributor &
A, AANoCapture::StateType &State,
const Use &U,
6026 LLVM_DEBUG(
dbgs() <<
"[AANoCapture] Check use: " << *
U.get() <<
" in "
6032 return isCapturedIn(State,
true,
true,
6039 return isCapturedIn(State,
true,
true,
6045 return isCapturedIn(State,
false,
false,
6047 return isCapturedIn(State,
true,
true,
6055 return isCapturedIn(State,
true,
true,
6062 bool IsKnownNoCapture;
6063 const AANoCapture *ArgNoCaptureAA =
nullptr;
6065 A,
this, CSArgPos, DepClassTy::REQUIRED, IsKnownNoCapture,
false,
6067 if (IsAssumedNoCapture)
6068 return isCapturedIn(State,
false,
false,
6072 return isCapturedIn(State,
false,
false,
6077 return isCapturedIn(State,
true,
true,
6084 static bool isCapturedIn(AANoCapture::StateType &State,
bool CapturedInMem,
6085 bool CapturedInInt,
bool CapturedInRet) {
6086 LLVM_DEBUG(
dbgs() <<
" - captures [Mem " << CapturedInMem <<
"|Int "
6087 << CapturedInInt <<
"|Ret " << CapturedInRet <<
"]\n");
6099 const IRPosition &IRP = getIRPosition();
6103 return indicatePessimisticFixpoint();
6110 return indicatePessimisticFixpoint();
6118 T.addKnownBits(NOT_CAPTURED_IN_MEM);
6120 addKnownBits(NOT_CAPTURED_IN_MEM);
6127 auto CheckReturnedArgs = [&](
bool &UsedAssumedInformation) {
6131 UsedAssumedInformation))
6133 bool SeenConstant =
false;
6134 for (
const AA::ValueAndContext &VAC :
Values) {
6138 SeenConstant =
true;
6140 VAC.
getValue() == getAssociatedArgument())
6146 bool IsKnownNoUnwind;
6149 bool IsVoidTy =
F->getReturnType()->isVoidTy();
6150 bool UsedAssumedInformation =
false;
6151 if (IsVoidTy || CheckReturnedArgs(UsedAssumedInformation)) {
6152 T.addKnownBits(NOT_CAPTURED_IN_RET);
6153 if (
T.isKnown(NOT_CAPTURED_IN_MEM))
6155 if (IsKnownNoUnwind && (IsVoidTy || !UsedAssumedInformation)) {
6156 addKnownBits(NOT_CAPTURED_IN_RET);
6157 if (isKnown(NOT_CAPTURED_IN_MEM))
6158 return indicateOptimisticFixpoint();
6163 auto UseCheck = [&](
const Use &
U,
bool &Follow) ->
bool {
6172 return checkUse(
A,
T, U, Follow);
6175 if (!
A.checkForAllUses(UseCheck, *
this, *V))
6176 return indicatePessimisticFixpoint();
6179 auto Assumed = S.getAssumed();
6180 S.intersectAssumedBits(
T.getAssumed());
6181 if (!isAssumedNoCaptureMaybeReturned())
6182 return indicatePessimisticFixpoint();
6188struct AANoCaptureArgument final : AANoCaptureImpl {
6189 AANoCaptureArgument(
const IRPosition &IRP, Attributor &
A)
6190 : AANoCaptureImpl(IRP,
A) {}
6197struct AANoCaptureCallSiteArgument final : AANoCaptureImpl {
6198 AANoCaptureCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
6199 : AANoCaptureImpl(IRP,
A) {}
6207 Argument *Arg = getAssociatedArgument();
6209 return indicatePessimisticFixpoint();
6211 bool IsKnownNoCapture;
6212 const AANoCapture *ArgAA =
nullptr;
6214 A,
this, ArgPos, DepClassTy::REQUIRED, IsKnownNoCapture,
false,
6216 return ChangeStatus::UNCHANGED;
6218 return indicatePessimisticFixpoint();
6223 void trackStatistics()
const override {
6229struct AANoCaptureFloating final : AANoCaptureImpl {
6230 AANoCaptureFloating(
const IRPosition &IRP, Attributor &
A)
6231 : AANoCaptureImpl(IRP,
A) {}
6234 void trackStatistics()
const override {
6240struct AANoCaptureReturned final : AANoCaptureImpl {
6241 AANoCaptureReturned(
const IRPosition &IRP, Attributor &
A)
6242 : AANoCaptureImpl(IRP,
A) {
6257 void trackStatistics()
const override {}
6261struct AANoCaptureCallSiteReturned final : AANoCaptureImpl {
6262 AANoCaptureCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
6263 : AANoCaptureImpl(IRP,
A) {}
6269 determineFunctionCaptureCapabilities(getIRPosition(), *
F, *
this);
6273 void trackStatistics()
const override {
6290 dbgs() <<
"[ValueSimplify] is assumed to be "
6293 dbgs() <<
"[ValueSimplify] is assumed to be <none>\n";
6305 if (getAssociatedValue().
getType()->isVoidTy())
6306 indicatePessimisticFixpoint();
6307 if (
A.hasSimplificationCallback(getIRPosition()))
6308 indicatePessimisticFixpoint();
6312 const std::string getAsStr(Attributor *
A)
const override {
6314 dbgs() <<
"SAV: " << (bool)SimplifiedAssociatedValue <<
" ";
6315 if (SimplifiedAssociatedValue && *SimplifiedAssociatedValue)
6316 dbgs() <<
"SAV: " << **SimplifiedAssociatedValue <<
" ";
6318 return isValidState() ? (isAtFixpoint() ?
"simplified" :
"maybe-simple")
6323 void trackStatistics()
const override {}
6326 std::optional<Value *>
6327 getAssumedSimplifiedValue(Attributor &
A)
const override {
6328 return SimplifiedAssociatedValue;
6335 static Value *ensureType(Attributor &
A,
Value &V,
Type &Ty, Instruction *CtxI,
6339 if (CtxI &&
V.getType()->canLosslesslyBitCastTo(&Ty))
6341 : BitCastInst::CreatePointerBitCastOrAddrSpaceCast(
6350 static Value *reproduceInst(Attributor &
A,
6351 const AbstractAttribute &QueryingAA,
6352 Instruction &
I,
Type &Ty, Instruction *CtxI,
6354 assert(CtxI &&
"Cannot reproduce an instruction without context!");
6355 if (
Check && (
I.mayReadFromMemory() ||
6360 Value *NewOp = reproduceValue(
A, QueryingAA, *
Op, Ty, CtxI,
Check, VMap);
6362 assert(
Check &&
"Manifest of new value unexpectedly failed!");
6384 static Value *reproduceValue(Attributor &
A,
6385 const AbstractAttribute &QueryingAA,
Value &V,
6386 Type &Ty, Instruction *CtxI,
bool Check,
6388 if (
const auto &NewV = VMap.
lookup(&V))
6390 bool UsedAssumedInformation =
false;
6391 std::optional<Value *> SimpleV =
A.getAssumedSimplified(
6393 if (!SimpleV.has_value())
6397 EffectiveV = *SimpleV;
6402 return ensureType(
A, *EffectiveV, Ty, CtxI,
Check);
6404 if (
Value *NewV = reproduceInst(
A, QueryingAA, *
I, Ty, CtxI,
Check, VMap))
6405 return ensureType(
A, *NewV, Ty, CtxI,
Check);
6411 Value *manifestReplacementValue(Attributor &
A, Instruction *CtxI)
const {
6412 Value *NewV = SimplifiedAssociatedValue
6413 ? *SimplifiedAssociatedValue
6415 if (NewV && NewV != &getAssociatedValue()) {
6419 if (reproduceValue(
A, *
this, *NewV, *getAssociatedType(), CtxI,
6421 return reproduceValue(
A, *
this, *NewV, *getAssociatedType(), CtxI,
6429 bool checkAndUpdate(Attributor &
A,
const AbstractAttribute &QueryingAA,
6430 const IRPosition &IRP,
bool Simplify =
true) {
6431 bool UsedAssumedInformation =
false;
6434 QueryingValueSimplified =
A.getAssumedSimplified(
6436 return unionAssumed(QueryingValueSimplified);
6440 template <
typename AAType>
bool askSimplifiedValueFor(Attributor &
A) {
6441 if (!getAssociatedValue().
getType()->isIntegerTy())
6446 A.getAAFor<AAType>(*
this, getIRPosition(), DepClassTy::NONE);
6450 std::optional<Constant *> COpt = AA->getAssumedConstant(
A);
6453 SimplifiedAssociatedValue = std::nullopt;
6454 A.recordDependence(*AA, *
this, DepClassTy::OPTIONAL);
6457 if (
auto *
C = *COpt) {
6458 SimplifiedAssociatedValue =
C;
6459 A.recordDependence(*AA, *
this, DepClassTy::OPTIONAL);
6465 bool askSimplifiedValueForOtherAAs(Attributor &
A) {
6466 if (askSimplifiedValueFor<AAValueConstantRange>(
A))
6468 if (askSimplifiedValueFor<AAPotentialConstantValues>(
A))
6476 for (
auto &U : getAssociatedValue().uses()) {
6481 IP =
PHI->getIncomingBlock(U)->getTerminator();
6482 if (
auto *NewV = manifestReplacementValue(
A, IP)) {
6484 <<
" -> " << *NewV <<
" :: " << *
this <<
"\n");
6485 if (
A.changeUseAfterManifest(U, *NewV))
6486 Changed = ChangeStatus::CHANGED;
6490 return Changed | AAValueSimplify::manifest(
A);
6495 SimplifiedAssociatedValue = &getAssociatedValue();
6496 return AAValueSimplify::indicatePessimisticFixpoint();
6500struct AAValueSimplifyArgument final : AAValueSimplifyImpl {
6501 AAValueSimplifyArgument(
const IRPosition &IRP, Attributor &
A)
6502 : AAValueSimplifyImpl(IRP,
A) {}
6505 AAValueSimplifyImpl::initialize(
A);
6506 if (
A.hasAttr(getIRPosition(),
6507 {Attribute::InAlloca, Attribute::Preallocated,
6508 Attribute::StructRet, Attribute::Nest, Attribute::ByVal},
6510 indicatePessimisticFixpoint();
6517 Argument *Arg = getAssociatedArgument();
6523 return indicatePessimisticFixpoint();
6526 auto Before = SimplifiedAssociatedValue;
6528 auto PredForCallSite = [&](AbstractCallSite ACS) {
6529 const IRPosition &ACSArgPos =
6540 bool UsedAssumedInformation =
false;
6541 std::optional<Constant *> SimpleArgOp =
6542 A.getAssumedConstant(ACSArgPos, *
this, UsedAssumedInformation);
6549 return unionAssumed(*SimpleArgOp);
6554 bool UsedAssumedInformation =
false;
6555 if (hasCallBaseContext() &&
6556 getCallBaseContext()->getCalledOperand() == Arg->
getParent())
6558 AbstractCallSite(&getCallBaseContext()->getCalledOperandUse()));
6560 Success =
A.checkForAllCallSites(PredForCallSite, *
this,
true,
6561 UsedAssumedInformation);
6564 if (!askSimplifiedValueForOtherAAs(
A))
6565 return indicatePessimisticFixpoint();
6568 return Before == SimplifiedAssociatedValue ? ChangeStatus::UNCHANGED
6569 : ChangeStatus ::CHANGED;
6573 void trackStatistics()
const override {
6578struct AAValueSimplifyReturned : AAValueSimplifyImpl {
6579 AAValueSimplifyReturned(
const IRPosition &IRP, Attributor &
A)
6580 : AAValueSimplifyImpl(IRP,
A) {}
6583 std::optional<Value *>
6584 getAssumedSimplifiedValue(Attributor &
A)
const override {
6585 if (!isValidState())
6587 return SimplifiedAssociatedValue;
6592 auto Before = SimplifiedAssociatedValue;
6596 return checkAndUpdate(
6601 bool UsedAssumedInformation =
false;
6602 if (!
A.checkForAllInstructions(ReturnInstCB, *
this, {Instruction::Ret},
6603 UsedAssumedInformation))
6604 if (!askSimplifiedValueForOtherAAs(
A))
6605 return indicatePessimisticFixpoint();
6608 return Before == SimplifiedAssociatedValue ? ChangeStatus::UNCHANGED
6609 : ChangeStatus ::CHANGED;
6615 return ChangeStatus::UNCHANGED;
6619 void trackStatistics()
const override {
6624struct AAValueSimplifyFloating : AAValueSimplifyImpl {
6625 AAValueSimplifyFloating(
const IRPosition &IRP, Attributor &
A)
6626 : AAValueSimplifyImpl(IRP,
A) {}
6630 AAValueSimplifyImpl::initialize(
A);
6631 Value &
V = getAnchorValue();
6635 indicatePessimisticFixpoint();
6640 auto Before = SimplifiedAssociatedValue;
6641 if (!askSimplifiedValueForOtherAAs(
A))
6642 return indicatePessimisticFixpoint();
6645 return Before == SimplifiedAssociatedValue ? ChangeStatus::UNCHANGED
6646 : ChangeStatus ::CHANGED;
6650 void trackStatistics()
const override {
6655struct AAValueSimplifyFunction : AAValueSimplifyImpl {
6656 AAValueSimplifyFunction(
const IRPosition &IRP, Attributor &
A)
6657 : AAValueSimplifyImpl(IRP,
A) {}
6661 SimplifiedAssociatedValue =
nullptr;
6662 indicateOptimisticFixpoint();
6667 "AAValueSimplify(Function|CallSite)::updateImpl will not be called");
6670 void trackStatistics()
const override {
6675struct AAValueSimplifyCallSite : AAValueSimplifyFunction {
6676 AAValueSimplifyCallSite(
const IRPosition &IRP, Attributor &
A)
6677 : AAValueSimplifyFunction(IRP,
A) {}
6679 void trackStatistics()
const override {
6684struct AAValueSimplifyCallSiteReturned : AAValueSimplifyImpl {
6685 AAValueSimplifyCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
6686 : AAValueSimplifyImpl(IRP,
A) {}
6689 AAValueSimplifyImpl::initialize(
A);
6690 Function *Fn = getAssociatedFunction();
6691 assert(Fn &&
"Did expect an associted function");
6692 for (Argument &Arg : Fn->
args()) {
6697 checkAndUpdate(
A, *
this, IRP))
6698 indicateOptimisticFixpoint();
6700 indicatePessimisticFixpoint();
6708 return indicatePessimisticFixpoint();
6711 void trackStatistics()
const override {
6716struct AAValueSimplifyCallSiteArgument : AAValueSimplifyFloating {
6717 AAValueSimplifyCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
6718 : AAValueSimplifyFloating(IRP,
A) {}
6724 auto *FloatAA =
A.lookupAAFor<AAValueSimplify>(
6726 if (FloatAA && FloatAA->getState().isValidState())
6729 if (
auto *NewV = manifestReplacementValue(
A, getCtxI())) {
6731 ->getArgOperandUse(getCallSiteArgNo());
6732 if (
A.changeUseAfterManifest(U, *NewV))
6733 Changed = ChangeStatus::CHANGED;
6736 return Changed | AAValueSimplify::manifest(
A);
6739 void trackStatistics()
const override {
6747struct AAHeapToStackFunction final :
public AAHeapToStack {
6749 static bool isGlobalizedLocal(
const CallBase &CB) {
6751 return A.
isValid() &&
A.getValueAsString() ==
"__kmpc_alloc_shared";
6754 struct AllocationInfo {
6759 bool IsGlobalizedLocal =
false;
6766 } Status = STACK_DUE_TO_USE;
6770 bool HasPotentiallyFreeingUnknownUses =
false;
6774 bool MoveAllocaIntoEntry =
true;
6777 SmallSetVector<CallBase *, 1> PotentialFreeCalls{};
6780 struct DeallocationInfo {
6788 bool MightFreeUnknownObjects =
false;
6791 SmallSetVector<CallBase *, 1> PotentialAllocationCalls{};
6794 AAHeapToStackFunction(
const IRPosition &IRP, Attributor &
A)
6795 : AAHeapToStack(IRP,
A) {}
6797 ~AAHeapToStackFunction()
override {
6800 for (
auto &It : AllocationInfos)
6801 It.second->~AllocationInfo();
6802 for (
auto &It : DeallocationInfos)
6803 It.second->~DeallocationInfo();
6807 AAHeapToStack::initialize(
A);
6810 const auto *TLI =
A.getInfoCache().getTargetLibraryInfoForFunction(*
F);
6817 DeallocationInfos[CB] =
new (
A.Allocator) DeallocationInfo{CB, FreedOp};
6824 auto *I8Ty = Type::getInt8Ty(CB->
getParent()->getContext());
6826 AllocationInfo *AI =
new (
A.Allocator) AllocationInfo{CB};
6827 AllocationInfos[CB] = AI;
6828 AI->IsGlobalizedLocal = isGlobalizedLocal(*CB);
6834 bool UsedAssumedInformation =
false;
6835 bool Success =
A.checkForAllCallLikeInstructions(
6836 AllocationIdentifierCB, *
this, UsedAssumedInformation,
6840 assert(
Success &&
"Did not expect the call base visit callback to fail!");
6843 [](
const IRPosition &,
const AbstractAttribute *,
6844 bool &) -> std::optional<Value *> {
return nullptr; };
6845 for (
const auto &It : AllocationInfos)
6848 for (
const auto &It : DeallocationInfos)
6853 const std::string getAsStr(Attributor *
A)
const override {
6854 unsigned NumH2SMallocs = 0, NumInvalidMallocs = 0;
6855 for (
const auto &It : AllocationInfos) {
6856 if (It.second->Status == AllocationInfo::INVALID)
6857 ++NumInvalidMallocs;
6861 return "[H2S] Mallocs Good/Bad: " + std::to_string(NumH2SMallocs) +
"/" +
6862 std::to_string(NumInvalidMallocs);
6866 void trackStatistics()
const override {
6869 "Number of malloc/calloc/aligned_alloc calls converted to allocas");
6870 for (
const auto &It : AllocationInfos)
6871 if (It.second->Status != AllocationInfo::INVALID)
6875 bool isAssumedHeapToStack(
const CallBase &CB)
const override {
6877 if (AllocationInfo *AI =
6878 AllocationInfos.lookup(
const_cast<CallBase *
>(&CB)))
6879 return AI->Status != AllocationInfo::INVALID;
6883 bool isAssumedHeapToStackRemovedFree(CallBase &CB)
const override {
6884 if (!isValidState())
6887 for (
const auto &It : AllocationInfos) {
6888 AllocationInfo &AI = *It.second;
6889 if (AI.Status == AllocationInfo::INVALID)
6892 if (AI.PotentialFreeCalls.count(&CB))
6900 assert(getState().isValidState() &&
6901 "Attempted to manifest an invalid state!");
6905 const auto *TLI =
A.getInfoCache().getTargetLibraryInfoForFunction(*
F);
6907 for (
auto &It : AllocationInfos) {
6908 AllocationInfo &AI = *It.second;
6909 if (AI.Status == AllocationInfo::INVALID)
6912 for (CallBase *FreeCall : AI.PotentialFreeCalls) {
6913 LLVM_DEBUG(
dbgs() <<
"H2S: Removing free call: " << *FreeCall <<
"\n");
6914 A.deleteAfterManifest(*FreeCall);
6915 HasChanged = ChangeStatus::CHANGED;
6918 LLVM_DEBUG(
dbgs() <<
"H2S: Removing malloc-like call: " << *AI.CB
6921 auto Remark = [&](OptimizationRemark
OR) {
6922 if (AI.IsGlobalizedLocal)
6923 return OR <<
"Moving globalized variable to the stack.";
6924 return OR <<
"Moving memory allocation from the heap to the stack.";
6926 if (AI.IsGlobalizedLocal)
6927 A.emitRemark<OptimizationRemark>(AI.CB,
"OMP110",
Remark);
6929 A.emitRemark<OptimizationRemark>(AI.CB,
"HeapToStack",
Remark);
6931 const DataLayout &
DL =
A.getInfoCache().getDL();
6933 std::optional<APInt> SizeAPI =
getSize(
A, *
this, AI);
6935 Size = ConstantInt::get(AI.CB->getContext(), *SizeAPI);
6937 LLVMContext &Ctx = AI.CB->getContext();
6938 ObjectSizeOpts Opts;
6939 ObjectSizeOffsetEvaluator Eval(
DL, TLI, Ctx, Opts);
6940 SizeOffsetValue SizeOffsetPair = Eval.compute(AI.CB);
6947 ?
F->getEntryBlock().begin()
6948 : AI.CB->getIterator();
6951 if (MaybeAlign RetAlign = AI.CB->getRetAlign())
6952 Alignment = std::max(Alignment, *RetAlign);
6954 std::optional<APInt> AlignmentAPI = getAPInt(
A, *
this, *Align);
6955 assert(AlignmentAPI && AlignmentAPI->getZExtValue() > 0 &&
6956 "Expected an alignment during manifest!");
6958 std::max(Alignment,
assumeAligned(AlignmentAPI->getZExtValue()));
6962 unsigned AS =
DL.getAllocaAddrSpace();
6964 new AllocaInst(Type::getInt8Ty(
F->getContext()), AS,
Size, Alignment,
6965 AI.CB->getName() +
".h2s", IP);
6967 if (Alloca->
getType() != AI.CB->getType())
6968 Alloca = BitCastInst::CreatePointerBitCastOrAddrSpaceCast(
6969 Alloca, AI.CB->getType(),
"malloc_cast", AI.CB->getIterator());
6971 auto *I8Ty = Type::getInt8Ty(
F->getContext());
6974 "Must be able to materialize initial memory state of allocation");
6979 auto *NBB =
II->getNormalDest();
6981 A.deleteAfterManifest(*AI.CB);
6983 A.deleteAfterManifest(*AI.CB);
6992 Builder.CreateMemSet(Alloca, InitVal,
Size, std::nullopt);
6994 HasChanged = ChangeStatus::CHANGED;
7000 std::optional<APInt> getAPInt(Attributor &
A,
const AbstractAttribute &AA,
7002 bool UsedAssumedInformation =
false;
7003 std::optional<Constant *> SimpleV =
7004 A.getAssumedConstant(V, AA, UsedAssumedInformation);
7006 return APInt(64, 0);
7008 return CI->getValue();
7009 return std::nullopt;
7012 std::optional<APInt>
getSize(Attributor &
A,
const AbstractAttribute &AA,
7013 AllocationInfo &AI) {
7015 bool UsedAssumedInformation =
false;
7016 if (std::optional<Constant *> SimpleV =
7017 A.getAssumedConstant(*V, AA, UsedAssumedInformation))
7024 const auto *TLI =
A.getInfoCache().getTargetLibraryInfoForFunction(*
F);
7030 MapVector<CallBase *, AllocationInfo *> AllocationInfos;
7034 MapVector<CallBase *, DeallocationInfo *> DeallocationInfos;
7039ChangeStatus AAHeapToStackFunction::updateImpl(Attributor &
A) {
7042 const auto *TLI =
A.getInfoCache().getTargetLibraryInfoForFunction(*
F);
7044 const auto *LivenessAA =
7047 MustBeExecutedContextExplorer *Explorer =
7048 A.getInfoCache().getMustBeExecutedContextExplorer();
7050 bool StackIsAccessibleByOtherThreads =
7051 A.getInfoCache().stackIsAccessibleByOtherThreads();
7054 A.getInfoCache().getAnalysisResultForFunction<LoopAnalysis>(*F);
7055 std::optional<bool> MayContainIrreducibleControl;
7057 if (&
F->getEntryBlock() == &BB)
7059 if (!MayContainIrreducibleControl.has_value())
7061 if (*MayContainIrreducibleControl)
7070 bool HasUpdatedFrees =
false;
7072 auto UpdateFrees = [&]() {
7073 HasUpdatedFrees =
true;
7075 for (
auto &It : DeallocationInfos) {
7076 DeallocationInfo &DI = *It.second;
7079 if (DI.MightFreeUnknownObjects)
7083 bool UsedAssumedInformation =
false;
7084 if (
A.isAssumedDead(*DI.CB,
this, LivenessAA, UsedAssumedInformation,
7091 LLVM_DEBUG(
dbgs() <<
"[H2S] Unknown underlying object for free!\n");
7092 DI.MightFreeUnknownObjects =
true;
7105 DI.MightFreeUnknownObjects =
true;
7109 AllocationInfo *AI = AllocationInfos.lookup(ObjCB);
7111 LLVM_DEBUG(
dbgs() <<
"[H2S] Free of a non-allocation object: " << *Obj
7113 DI.MightFreeUnknownObjects =
true;
7117 DI.PotentialAllocationCalls.insert(ObjCB);
7121 auto FreeCheck = [&](AllocationInfo &AI) {
7125 if (!StackIsAccessibleByOtherThreads) {
7130 dbgs() <<
"[H2S] found an escaping use, stack is not accessible by "
7131 "other threads and function is not nosync:\n");
7135 if (!HasUpdatedFrees)
7139 if (AI.PotentialFreeCalls.size() != 1) {
7141 << AI.PotentialFreeCalls.size() <<
"\n");
7144 CallBase *UniqueFree = *AI.PotentialFreeCalls.begin();
7145 DeallocationInfo *DI = DeallocationInfos.lookup(UniqueFree);
7148 dbgs() <<
"[H2S] unique free call was not known as deallocation call "
7149 << *UniqueFree <<
"\n");
7152 if (DI->MightFreeUnknownObjects) {
7154 dbgs() <<
"[H2S] unique free call might free unknown allocations\n");
7157 if (DI->PotentialAllocationCalls.empty())
7159 if (DI->PotentialAllocationCalls.size() > 1) {
7161 << DI->PotentialAllocationCalls.size()
7162 <<
" different allocations\n");
7165 if (*DI->PotentialAllocationCalls.begin() != AI.CB) {
7168 <<
"[H2S] unique free call not known to free this allocation but "
7169 << **DI->PotentialAllocationCalls.begin() <<
"\n");
7174 if (!AI.IsGlobalizedLocal) {
7176 if (!Explorer || !Explorer->findInContextOf(UniqueFree, CtxI)) {
7177 LLVM_DEBUG(
dbgs() <<
"[H2S] unique free call might not be executed "
7178 "with the allocation "
7179 << *UniqueFree <<
"\n");
7186 auto UsesCheck = [&](AllocationInfo &AI) {
7187 bool ValidUsesOnly =
true;
7189 auto Pred = [&](
const Use &
U,
bool &Follow) ->
bool {
7194 if (
SI->getValueOperand() ==
U.get()) {
7196 <<
"[H2S] escaping store to memory: " << *UserI <<
"\n");
7197 ValidUsesOnly =
false;
7206 if (DeallocationInfos.count(CB)) {
7207 AI.PotentialFreeCalls.insert(CB);
7214 bool IsKnownNoCapture;
7223 if (!IsAssumedNoCapture ||
7224 (!AI.IsGlobalizedLocal && !IsAssumedNoFree)) {
7225 AI.HasPotentiallyFreeingUnknownUses |= !IsAssumedNoFree;
7228 auto Remark = [&](OptimizationRemarkMissed ORM) {
7230 <<
"Could not move globalized variable to the stack. "
7231 "Variable is potentially captured in call. Mark "
7232 "parameter as `__attribute__((noescape))` to override.";
7235 if (ValidUsesOnly && AI.IsGlobalizedLocal)
7236 A.emitRemark<OptimizationRemarkMissed>(CB,
"OMP113",
Remark);
7239 ValidUsesOnly =
false;
7252 ValidUsesOnly =
false;
7255 if (!
A.checkForAllUses(Pred, *
this, *AI.CB,
false,
7257 [&](
const Use &OldU,
const Use &NewU) {
7258 auto *SI = dyn_cast<StoreInst>(OldU.getUser());
7259 return !SI || StackIsAccessibleByOtherThreads ||
7260 AA::isAssumedThreadLocalObject(
7261 A, *SI->getPointerOperand(), *this);
7264 return ValidUsesOnly;
7269 for (
auto &It : AllocationInfos) {
7270 AllocationInfo &AI = *It.second;
7271 if (AI.Status == AllocationInfo::INVALID)
7275 std::optional<APInt> APAlign = getAPInt(
A, *
this, *Align);
7279 LLVM_DEBUG(
dbgs() <<
"[H2S] Unknown allocation alignment: " << *AI.CB
7281 AI.Status = AllocationInfo::INVALID;
7286 !APAlign->isPowerOf2()) {
7287 LLVM_DEBUG(
dbgs() <<
"[H2S] Invalid allocation alignment: " << APAlign
7289 AI.Status = AllocationInfo::INVALID;
7300 dbgs() <<
"[H2S] Unknown allocation size: " << *AI.CB <<
"\n";
7302 dbgs() <<
"[H2S] Allocation size too large: " << *AI.CB <<
" vs. "
7306 AI.Status = AllocationInfo::INVALID;
7312 switch (AI.Status) {
7313 case AllocationInfo::STACK_DUE_TO_USE:
7316 AI.Status = AllocationInfo::STACK_DUE_TO_FREE;
7318 case AllocationInfo::STACK_DUE_TO_FREE:
7321 AI.Status = AllocationInfo::INVALID;
7324 case AllocationInfo::INVALID:
7331 bool IsGlobalizedLocal = AI.IsGlobalizedLocal;
7332 if (AI.MoveAllocaIntoEntry &&
7333 (!
Size.has_value() ||
7334 (!IsGlobalizedLocal && IsInLoop(*AI.CB->getParent()))))
7335 AI.MoveAllocaIntoEntry =
false;
7344struct AAPrivatizablePtrImpl :
public AAPrivatizablePtr {
7345 AAPrivatizablePtrImpl(
const IRPosition &IRP, Attributor &
A)
7346 : AAPrivatizablePtr(IRP,
A), PrivatizableType(std::nullopt) {}
7349 AAPrivatizablePtr::indicatePessimisticFixpoint();
7350 PrivatizableType =
nullptr;
7351 return ChangeStatus::CHANGED;
7357 virtual std::optional<Type *> identifyPrivatizableType(Attributor &
A) = 0;
7361 std::optional<Type *> combineTypes(std::optional<Type *> T0,
7362 std::optional<Type *>
T1) {
7372 std::optional<Type *> getPrivatizableType()
const override {
7373 return PrivatizableType;
7376 const std::string getAsStr(Attributor *
A)
const override {
7377 return isAssumedPrivatizablePtr() ?
"[priv]" :
"[no-priv]";
7381 std::optional<Type *> PrivatizableType;
7386struct AAPrivatizablePtrArgument final :
public AAPrivatizablePtrImpl {
7387 AAPrivatizablePtrArgument(
const IRPosition &IRP, Attributor &
A)
7388 : AAPrivatizablePtrImpl(IRP,
A) {}
7391 std::optional<Type *> identifyPrivatizableType(Attributor &
A)
override {
7394 bool UsedAssumedInformation =
false;
7396 A.getAttrs(getIRPosition(), {Attribute::ByVal},
Attrs,
7398 if (!
Attrs.empty() &&
7399 A.checkForAllCallSites([](AbstractCallSite ACS) { return true; }, *
this,
7400 true, UsedAssumedInformation))
7401 return Attrs[0].getValueAsType();
7403 std::optional<Type *> Ty;
7404 unsigned ArgNo = getIRPosition().getCallSiteArgNo();
7412 auto CallSiteCheck = [&](AbstractCallSite ACS) {
7421 A.getAAFor<AAPrivatizablePtr>(*
this, ACSArgPos, DepClassTy::REQUIRED);
7424 std::optional<Type *> CSTy = PrivCSArgAA->getPrivatizableType();
7427 dbgs() <<
"[AAPrivatizablePtr] ACSPos: " << ACSArgPos <<
", CSTy: ";
7431 dbgs() <<
"<nullptr>";
7436 Ty = combineTypes(Ty, CSTy);
7439 dbgs() <<
" : New Type: ";
7441 (*Ty)->print(
dbgs());
7443 dbgs() <<
"<nullptr>";
7452 if (!
A.checkForAllCallSites(CallSiteCheck, *
this,
true,
7453 UsedAssumedInformation))
7460 PrivatizableType = identifyPrivatizableType(
A);
7461 if (!PrivatizableType)
7462 return ChangeStatus::UNCHANGED;
7463 if (!*PrivatizableType)
7464 return indicatePessimisticFixpoint();
7469 DepClassTy::OPTIONAL);
7472 if (!
A.hasAttr(getIRPosition(), Attribute::ByVal) &&
7475 return indicatePessimisticFixpoint();
7481 identifyReplacementTypes(*PrivatizableType, ReplacementTypes);
7485 Function &Fn = *getIRPosition().getAnchorScope();
7487 A.getInfoCache().getAnalysisResultForFunction<TargetIRAnalysis>(Fn);
7489 LLVM_DEBUG(
dbgs() <<
"[AAPrivatizablePtr] Missing TTI for function "
7491 return indicatePessimisticFixpoint();
7494 auto CallSiteCheck = [&](AbstractCallSite ACS) {
7501 bool UsedAssumedInformation =
false;
7502 if (!
A.checkForAllCallSites(CallSiteCheck, *
this,
true,
7503 UsedAssumedInformation)) {
7505 dbgs() <<
"[AAPrivatizablePtr] ABI incompatibility detected for "
7507 return indicatePessimisticFixpoint();
7511 Argument *Arg = getAssociatedArgument();
7512 if (!
A.isValidFunctionSignatureRewrite(*Arg, ReplacementTypes)) {
7514 return indicatePessimisticFixpoint();
7521 auto IsCompatiblePrivArgOfCallback = [&](CallBase &CB) {
7524 for (
const Use *U : CallbackUses) {
7525 AbstractCallSite CBACS(U);
7526 assert(CBACS && CBACS.isCallbackCall());
7527 for (Argument &CBArg : CBACS.getCalledFunction()->args()) {
7528 int CBArgNo = CBACS.getCallArgOperandNo(CBArg);
7532 <<
"[AAPrivatizablePtr] Argument " << *Arg
7533 <<
"check if can be privatized in the context of its parent ("
7535 <<
")\n[AAPrivatizablePtr] because it is an argument in a "
7537 << CBArgNo <<
"@" << CBACS.getCalledFunction()->getName()
7538 <<
")\n[AAPrivatizablePtr] " << CBArg <<
" : "
7539 << CBACS.getCallArgOperand(CBArg) <<
" vs "
7541 <<
"[AAPrivatizablePtr] " << CBArg <<
" : "
7542 << CBACS.getCallArgOperandNo(CBArg) <<
" vs " << ArgNo <<
"\n";
7545 if (CBArgNo !=
int(ArgNo))
7547 const auto *CBArgPrivAA =
A.getAAFor<AAPrivatizablePtr>(
7549 if (CBArgPrivAA && CBArgPrivAA->isValidState()) {
7550 auto CBArgPrivTy = CBArgPrivAA->getPrivatizableType();
7553 if (*CBArgPrivTy == PrivatizableType)
7558 dbgs() <<
"[AAPrivatizablePtr] Argument " << *Arg
7559 <<
" cannot be privatized in the context of its parent ("
7561 <<
")\n[AAPrivatizablePtr] because it is an argument in a "
7563 << CBArgNo <<
"@" << CBACS.getCalledFunction()->getName()
7564 <<
").\n[AAPrivatizablePtr] for which the argument "
7565 "privatization is not compatible.\n";
7575 auto IsCompatiblePrivArgOfDirectCS = [&](AbstractCallSite ACS) {
7579 "Expected a direct call operand for callback call operand");
7584 dbgs() <<
"[AAPrivatizablePtr] Argument " << *Arg
7585 <<
" check if be privatized in the context of its parent ("
7587 <<
")\n[AAPrivatizablePtr] because it is an argument in a "
7589 << DCArgNo <<
"@" << DCCallee->
getName() <<
").\n";
7592 if (
unsigned(DCArgNo) < DCCallee->
arg_size()) {
7593 const auto *DCArgPrivAA =
A.getAAFor<AAPrivatizablePtr>(
7595 DepClassTy::REQUIRED);
7596 if (DCArgPrivAA && DCArgPrivAA->isValidState()) {
7597 auto DCArgPrivTy = DCArgPrivAA->getPrivatizableType();
7600 if (*DCArgPrivTy == PrivatizableType)
7606 dbgs() <<
"[AAPrivatizablePtr] Argument " << *Arg
7607 <<
" cannot be privatized in the context of its parent ("
7609 <<
")\n[AAPrivatizablePtr] because it is an argument in a "
7612 <<
").\n[AAPrivatizablePtr] for which the argument "
7613 "privatization is not compatible.\n";
7621 auto IsCompatiblePrivArgOfOtherCallSite = [&](AbstractCallSite ACS) {
7625 return IsCompatiblePrivArgOfDirectCS(ACS);
7629 if (!
A.checkForAllCallSites(IsCompatiblePrivArgOfOtherCallSite, *
this,
true,
7630 UsedAssumedInformation))
7631 return indicatePessimisticFixpoint();
7633 return ChangeStatus::UNCHANGED;
7639 identifyReplacementTypes(
Type *PrivType,
7640 SmallVectorImpl<Type *> &ReplacementTypes) {
7643 assert(PrivType &&
"Expected privatizable type!");
7647 for (
unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++)
7648 ReplacementTypes.
push_back(PrivStructType->getElementType(u));
7650 ReplacementTypes.
append(PrivArrayType->getNumElements(),
7651 PrivArrayType->getElementType());
7662 assert(PrivType &&
"Expected privatizable type!");
7665 const DataLayout &
DL =
F.getDataLayout();
7669 const StructLayout *PrivStructLayout =
DL.getStructLayout(PrivStructType);
7670 for (
unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++) {
7673 new StoreInst(
F.getArg(ArgNo + u), Ptr, IP);
7676 Type *PointeeTy = PrivArrayType->getElementType();
7677 uint64_t PointeeTySize =
DL.getTypeStoreSize(PointeeTy);
7678 for (
unsigned u = 0, e = PrivArrayType->getNumElements(); u < e; u++) {
7680 new StoreInst(
F.getArg(ArgNo + u), Ptr, IP);
7683 new StoreInst(
F.getArg(ArgNo), &
Base, IP);
7689 void createReplacementValues(Align Alignment,
Type *PrivType,
7691 SmallVectorImpl<Value *> &ReplacementValues) {
7693 assert(PrivType &&
"Expected privatizable type!");
7701 const StructLayout *PrivStructLayout =
DL.getStructLayout(PrivStructType);
7702 for (
unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++) {
7703 Type *PointeeTy = PrivStructType->getElementType(u);
7706 LoadInst *
L =
new LoadInst(PointeeTy, Ptr,
"", IP->
getIterator());
7707 L->setAlignment(Alignment);
7711 Type *PointeeTy = PrivArrayType->getElementType();
7712 uint64_t PointeeTySize =
DL.getTypeStoreSize(PointeeTy);
7713 for (
unsigned u = 0, e = PrivArrayType->getNumElements(); u < e; u++) {
7715 LoadInst *
L =
new LoadInst(PointeeTy, Ptr,
"", IP->
getIterator());
7716 L->setAlignment(Alignment);
7721 L->setAlignment(Alignment);
7728 if (!PrivatizableType)
7729 return ChangeStatus::UNCHANGED;
7730 assert(*PrivatizableType &&
"Expected privatizable type!");
7736 bool UsedAssumedInformation =
false;
7737 if (!
A.checkForAllInstructions(
7738 [&](Instruction &
I) {
7739 CallInst &CI = cast<CallInst>(I);
7740 if (CI.isTailCall())
7741 TailCalls.push_back(&CI);
7744 *
this, {Instruction::Call}, UsedAssumedInformation))
7745 return ChangeStatus::UNCHANGED;
7747 Argument *Arg = getAssociatedArgument();
7750 const auto *AlignAA =
7757 [=](
const Attributor::ArgumentReplacementInfo &ARI,
7759 BasicBlock &EntryBB = ReplacementFn.getEntryBlock();
7761 const DataLayout &
DL = IP->getDataLayout();
7762 unsigned AS =
DL.getAllocaAddrSpace();
7763 Instruction *AI =
new AllocaInst(*PrivatizableType, AS,
7764 Arg->
getName() +
".priv", IP);
7765 createInitialization(*PrivatizableType, *AI, ReplacementFn,
7766 ArgIt->getArgNo(), IP);
7769 AI = BitCastInst::CreatePointerBitCastOrAddrSpaceCast(
7773 for (CallInst *CI : TailCalls)
7774 CI->setTailCall(
false);
7781 [=](
const Attributor::ArgumentReplacementInfo &ARI,
7782 AbstractCallSite ACS, SmallVectorImpl<Value *> &NewArgOperands) {
7785 createReplacementValues(
7786 AlignAA ? AlignAA->getAssumedAlign() :
Align(0),
7787 *PrivatizableType, ACS,
7795 identifyReplacementTypes(*PrivatizableType, ReplacementTypes);
7798 if (
A.registerFunctionSignatureRewrite(*Arg, ReplacementTypes,
7799 std::move(FnRepairCB),
7800 std::move(ACSRepairCB)))
7801 return ChangeStatus::CHANGED;
7802 return ChangeStatus::UNCHANGED;
7806 void trackStatistics()
const override {
7811struct AAPrivatizablePtrFloating :
public AAPrivatizablePtrImpl {
7812 AAPrivatizablePtrFloating(
const IRPosition &IRP, Attributor &
A)
7813 : AAPrivatizablePtrImpl(IRP,
A) {}
7818 indicatePessimisticFixpoint();
7823 "updateImpl will not be called");
7827 std::optional<Type *> identifyPrivatizableType(Attributor &
A)
override {
7830 LLVM_DEBUG(
dbgs() <<
"[AAPrivatizablePtr] No underlying object found!\n");
7837 return AI->getAllocatedType();
7839 auto *PrivArgAA =
A.getAAFor<AAPrivatizablePtr>(
7841 if (PrivArgAA && PrivArgAA->isAssumedPrivatizablePtr())
7842 return PrivArgAA->getPrivatizableType();
7845 LLVM_DEBUG(
dbgs() <<
"[AAPrivatizablePtr] Underlying object neither valid "
7846 "alloca nor privatizable argument: "
7852 void trackStatistics()
const override {
7857struct AAPrivatizablePtrCallSiteArgument final
7858 :
public AAPrivatizablePtrFloating {
7859 AAPrivatizablePtrCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
7860 : AAPrivatizablePtrFloating(IRP,
A) {}
7864 if (
A.hasAttr(getIRPosition(), Attribute::ByVal))
7865 indicateOptimisticFixpoint();
7870 PrivatizableType = identifyPrivatizableType(
A);
7871 if (!PrivatizableType)
7872 return ChangeStatus::UNCHANGED;
7873 if (!*PrivatizableType)
7874 return indicatePessimisticFixpoint();
7876 const IRPosition &IRP = getIRPosition();
7877 bool IsKnownNoCapture;
7879 A,
this, IRP, DepClassTy::REQUIRED, IsKnownNoCapture);
7880 if (!IsAssumedNoCapture) {
7881 LLVM_DEBUG(
dbgs() <<
"[AAPrivatizablePtr] pointer might be captured!\n");
7882 return indicatePessimisticFixpoint();
7885 bool IsKnownNoAlias;
7887 A,
this, IRP, DepClassTy::REQUIRED, IsKnownNoAlias)) {
7888 LLVM_DEBUG(
dbgs() <<
"[AAPrivatizablePtr] pointer might alias!\n");
7889 return indicatePessimisticFixpoint();
7894 LLVM_DEBUG(
dbgs() <<
"[AAPrivatizablePtr] pointer is written!\n");
7895 return indicatePessimisticFixpoint();
7898 return ChangeStatus::UNCHANGED;
7902 void trackStatistics()
const override {
7907struct AAPrivatizablePtrCallSiteReturned final
7908 :
public AAPrivatizablePtrFloating {
7909 AAPrivatizablePtrCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
7910 : AAPrivatizablePtrFloating(IRP,
A) {}
7915 indicatePessimisticFixpoint();
7919 void trackStatistics()
const override {
7924struct AAPrivatizablePtrReturned final :
public AAPrivatizablePtrFloating {
7925 AAPrivatizablePtrReturned(
const IRPosition &IRP, Attributor &
A)
7926 : AAPrivatizablePtrFloating(IRP,
A) {}
7931 indicatePessimisticFixpoint();
7935 void trackStatistics()
const override {
7945struct AAMemoryBehaviorImpl :
public AAMemoryBehavior {
7946 AAMemoryBehaviorImpl(
const IRPosition &IRP, Attributor &
A)
7947 : AAMemoryBehavior(IRP,
A) {}
7951 intersectAssumedBits(BEST_STATE);
7952 getKnownStateFromValue(
A, getIRPosition(), getState());
7953 AAMemoryBehavior::initialize(
A);
7957 static void getKnownStateFromValue(Attributor &
A,
const IRPosition &IRP,
7958 BitIntegerState &State,
7959 bool IgnoreSubsumingPositions =
false) {
7961 A.getAttrs(IRP, AttrKinds, Attrs, IgnoreSubsumingPositions);
7963 switch (Attr.getKindAsEnum()) {
7964 case Attribute::ReadNone:
7967 case Attribute::ReadOnly:
7970 case Attribute::WriteOnly:
7979 if (!
I->mayReadFromMemory())
7981 if (!
I->mayWriteToMemory())
7987 void getDeducedAttributes(Attributor &
A, LLVMContext &Ctx,
7988 SmallVectorImpl<Attribute> &Attrs)
const override {
7991 Attrs.push_back(Attribute::get(Ctx, Attribute::ReadNone));
7993 Attrs.push_back(Attribute::get(Ctx, Attribute::ReadOnly));
7994 else if (isAssumedWriteOnly())
7995 Attrs.push_back(Attribute::get(Ctx, Attribute::WriteOnly));
8001 const IRPosition &IRP = getIRPosition();
8003 if (
A.hasAttr(IRP, Attribute::ReadNone,
8005 return ChangeStatus::UNCHANGED;
8014 return ChangeStatus::UNCHANGED;
8017 A.removeAttrs(IRP, AttrKinds);
8020 A.removeAttrs(IRP, Attribute::Writable);
8027 const std::string getAsStr(Attributor *
A)
const override {
8032 if (isAssumedWriteOnly())
8034 return "may-read/write";
8038 static const Attribute::AttrKind AttrKinds[3];
8042 Attribute::ReadNone, Attribute::ReadOnly, Attribute::WriteOnly};
8045struct AAMemoryBehaviorFloating : AAMemoryBehaviorImpl {
8046 AAMemoryBehaviorFloating(
const IRPosition &IRP, Attributor &
A)
8047 : AAMemoryBehaviorImpl(IRP,
A) {}
8053 void trackStatistics()
const override {
8058 else if (isAssumedWriteOnly())
8065 bool followUsersOfUseIn(Attributor &
A,
const Use &U,
8066 const Instruction *UserI);
8069 void analyzeUseIn(Attributor &
A,
const Use &U,
const Instruction *UserI);
8073struct AAMemoryBehaviorArgument : AAMemoryBehaviorFloating {
8074 AAMemoryBehaviorArgument(
const IRPosition &IRP, Attributor &
A)
8075 : AAMemoryBehaviorFloating(IRP,
A) {}
8079 intersectAssumedBits(BEST_STATE);
8080 const IRPosition &IRP = getIRPosition();
8084 bool HasByVal =
A.hasAttr(IRP, {Attribute::ByVal},
8086 getKnownStateFromValue(
A, IRP, getState(),
8093 return ChangeStatus::UNCHANGED;
8097 if (
A.hasAttr(getIRPosition(),
8098 {Attribute::InAlloca, Attribute::Preallocated})) {
8099 removeKnownBits(NO_WRITES);
8100 removeAssumedBits(NO_WRITES);
8102 A.removeAttrs(getIRPosition(), AttrKinds);
8103 return AAMemoryBehaviorFloating::manifest(
A);
8107 void trackStatistics()
const override {
8112 else if (isAssumedWriteOnly())
8117struct AAMemoryBehaviorCallSiteArgument final : AAMemoryBehaviorArgument {
8118 AAMemoryBehaviorCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
8119 : AAMemoryBehaviorArgument(IRP,
A) {}
8125 Argument *Arg = getAssociatedArgument();
8127 indicatePessimisticFixpoint();
8131 addKnownBits(NO_WRITES);
8132 removeKnownBits(NO_READS);
8133 removeAssumedBits(NO_READS);
8135 AAMemoryBehaviorArgument::initialize(
A);
8136 if (getAssociatedFunction()->isDeclaration())
8137 indicatePessimisticFixpoint();
8146 Argument *Arg = getAssociatedArgument();
8149 A.getAAFor<AAMemoryBehavior>(*
this, ArgPos, DepClassTy::REQUIRED);
8151 return indicatePessimisticFixpoint();
8156 void trackStatistics()
const override {
8161 else if (isAssumedWriteOnly())
8167struct AAMemoryBehaviorCallSiteReturned final : AAMemoryBehaviorFloating {
8168 AAMemoryBehaviorCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
8169 : AAMemoryBehaviorFloating(IRP,
A) {}
8173 AAMemoryBehaviorImpl::initialize(
A);
8178 return ChangeStatus::UNCHANGED;
8182 void trackStatistics()
const override {}
8186struct AAMemoryBehaviorFunction final :
public AAMemoryBehaviorImpl {
8187 AAMemoryBehaviorFunction(
const IRPosition &IRP, Attributor &
A)
8188 : AAMemoryBehaviorImpl(IRP,
A) {}
8204 else if (isAssumedWriteOnly())
8207 A.removeAttrs(getIRPosition(), AttrKinds);
8210 for (Argument &Arg :
F.args())
8212 return A.manifestAttrs(getIRPosition(),
8213 Attribute::getWithMemoryEffects(
F.getContext(), ME));
8217 void trackStatistics()
const override {
8222 else if (isAssumedWriteOnly())
8228struct AAMemoryBehaviorCallSite final
8229 : AACalleeToCallSite<AAMemoryBehavior, AAMemoryBehaviorImpl> {
8230 AAMemoryBehaviorCallSite(
const IRPosition &IRP, Attributor &
A)
8231 : AACalleeToCallSite<AAMemoryBehavior, AAMemoryBehaviorImpl>(IRP,
A) {}
8242 else if (isAssumedWriteOnly())
8245 A.removeAttrs(getIRPosition(), AttrKinds);
8248 for (Use &U : CB.
args())
8250 Attribute::Writable);
8251 return A.manifestAttrs(
8252 getIRPosition(), Attribute::getWithMemoryEffects(CB.
getContext(), ME));
8256 void trackStatistics()
const override {
8261 else if (isAssumedWriteOnly())
8266ChangeStatus AAMemoryBehaviorFunction::updateImpl(Attributor &
A) {
8269 auto AssumedState = getAssumed();
8276 const auto *MemBehaviorAA =
A.getAAFor<AAMemoryBehavior>(
8278 if (MemBehaviorAA) {
8279 intersectAssumedBits(MemBehaviorAA->
getAssumed());
8280 return !isAtFixpoint();
8285 if (
I.mayReadFromMemory())
8286 removeAssumedBits(NO_READS);
8287 if (
I.mayWriteToMemory())
8288 removeAssumedBits(NO_WRITES);
8289 return !isAtFixpoint();
8292 bool UsedAssumedInformation =
false;
8293 if (!
A.checkForAllReadWriteInstructions(CheckRWInst, *
this,
8294 UsedAssumedInformation))
8295 return indicatePessimisticFixpoint();
8301ChangeStatus AAMemoryBehaviorFloating::updateImpl(Attributor &
A) {
8303 const IRPosition &IRP = getIRPosition();
8314 const auto *FnMemAA =
8317 FnMemAssumedState = FnMemAA->getAssumed();
8318 S.addKnownBits(FnMemAA->getKnown());
8319 if ((S.getAssumed() & FnMemAA->getAssumed()) == S.getAssumed())
8325 auto AssumedState = S.getAssumed();
8331 bool IsKnownNoCapture;
8332 const AANoCapture *ArgNoCaptureAA =
nullptr;
8337 if (!IsAssumedNoCapture &&
8339 S.intersectAssumedBits(FnMemAssumedState);
8345 auto UsePred = [&](
const Use &
U,
bool &Follow) ->
bool {
8347 LLVM_DEBUG(
dbgs() <<
"[AAMemoryBehavior] Use: " << *U <<
" in " << *UserI
8355 Follow = followUsersOfUseIn(
A, U, UserI);
8359 analyzeUseIn(
A, U, UserI);
8361 return !isAtFixpoint();
8364 if (!
A.checkForAllUses(UsePred, *
this, getAssociatedValue()))
8365 return indicatePessimisticFixpoint();
8371bool AAMemoryBehaviorFloating::followUsersOfUseIn(Attributor &
A,
const Use &U,
8372 const Instruction *UserI) {
8390 if (
U.get()->getType()->isPointerTy()) {
8392 bool IsKnownNoCapture;
8401void AAMemoryBehaviorFloating::analyzeUseIn(Attributor &
A,
const Use &U,
8402 const Instruction *UserI) {
8409 case Instruction::Load:
8411 removeAssumedBits(NO_READS);
8414 case Instruction::Store:
8419 removeAssumedBits(NO_WRITES);
8421 indicatePessimisticFixpoint();
8424 case Instruction::Call:
8425 case Instruction::CallBr:
8426 case Instruction::Invoke: {
8433 indicatePessimisticFixpoint();
8440 removeAssumedBits(NO_READS);
8447 if (
U.get()->getType()->isPointerTy())
8451 const auto *MemBehaviorAA =
8457 intersectAssumedBits(MemBehaviorAA->
getAssumed());
8465 removeAssumedBits(NO_READS);
8467 removeAssumedBits(NO_WRITES);
8479 return "all memory";
8482 std::string S =
"memory:";
8488 S +=
"internal global,";
8490 S +=
"external global,";
8494 S +=
"inaccessible,";
8508 AccessKind2Accesses.fill(
nullptr);
8511 ~AAMemoryLocationImpl()
override {
8514 for (AccessSet *AS : AccessKind2Accesses)
8521 intersectAssumedBits(BEST_STATE);
8522 getKnownStateFromValue(
A, getIRPosition(), getState());
8523 AAMemoryLocation::initialize(
A);
8527 static void getKnownStateFromValue(Attributor &
A,
const IRPosition &IRP,
8528 BitIntegerState &State,
8529 bool IgnoreSubsumingPositions =
false) {
8538 bool UseArgMemOnly =
true;
8540 if (AnchorFn &&
A.isRunOn(*AnchorFn))
8544 A.getAttrs(IRP, {Attribute::Memory},
Attrs, IgnoreSubsumingPositions);
8553 State.
addKnownBits(inverseLocation(NO_INACCESSIBLE_MEM,
true,
true));
8558 State.
addKnownBits(inverseLocation(NO_ARGUMENT_MEM,
true,
true));
8562 A.manifestAttrs(IRP,
8563 Attribute::getWithMemoryEffects(
8572 NO_INACCESSIBLE_MEM | NO_ARGUMENT_MEM,
true,
true));
8576 A.manifestAttrs(IRP,
8577 Attribute::getWithMemoryEffects(
8587 void getDeducedAttributes(Attributor &
A, LLVMContext &Ctx,
8588 SmallVectorImpl<Attribute> &Attrs)
const override {
8595 else if (isAssumedInaccessibleMemOnly())
8596 Attrs.push_back(Attribute::getWithMemoryEffects(
8598 else if (isAssumedArgMemOnly())
8601 else if (isAssumedInaccessibleOrArgMemOnly())
8602 Attrs.push_back(Attribute::getWithMemoryEffects(
8612 const IRPosition &IRP = getIRPosition();
8616 if (DeducedAttrs.
size() != 1)
8617 return ChangeStatus::UNCHANGED;
8620 return A.manifestAttrs(IRP, Attribute::getWithMemoryEffects(
8625 bool checkForAllAccessesToMemoryKind(
8627 MemoryLocationsKind)>
8629 MemoryLocationsKind RequestedMLK)
const override {
8630 if (!isValidState())
8633 MemoryLocationsKind AssumedMLK = getAssumedNotAccessedLocation();
8634 if (AssumedMLK == NO_LOCATIONS)
8638 for (MemoryLocationsKind CurMLK = 1; CurMLK < NO_LOCATIONS;
8639 CurMLK *= 2, ++Idx) {
8640 if (CurMLK & RequestedMLK)
8643 if (
const AccessSet *
Accesses = AccessKind2Accesses[Idx])
8644 for (
const AccessInfo &AI : *
Accesses)
8645 if (!Pred(AI.I, AI.Ptr, AI.Kind, CurMLK))
8658 MemoryLocationsKind KnownMLK = getKnown();
8660 for (MemoryLocationsKind CurMLK = 1; CurMLK < NO_LOCATIONS; CurMLK *= 2)
8661 if (!(CurMLK & KnownMLK))
8662 updateStateAndAccessesMap(getState(), CurMLK,
I,
nullptr,
Changed,
8663 getAccessKindFromInst(
I));
8664 return AAMemoryLocation::indicatePessimisticFixpoint();
8684 bool operator()(
const AccessInfo &
LHS,
const AccessInfo &
RHS)
const {
8688 return LHS.Ptr <
RHS.Ptr;
8689 if (
LHS.Kind !=
RHS.Kind)
8690 return LHS.Kind <
RHS.Kind;
8697 using AccessSet = SmallSet<AccessInfo, 2, AccessInfo>;
8698 std::array<AccessSet *, llvm::ConstantLog2<VALID_STATE>()>
8699 AccessKind2Accesses;
8704 categorizeArgumentPointerLocations(Attributor &
A, CallBase &CB,
8705 AAMemoryLocation::StateType &AccessedLocs,
8710 categorizeAccessedLocations(Attributor &
A, Instruction &
I,
bool &
Changed);
8713 AccessKind getAccessKindFromInst(
const Instruction *
I) {
8716 AK =
I->mayReadFromMemory() ? READ :
NONE;
8725 void updateStateAndAccessesMap(AAMemoryLocation::StateType &State,
8726 MemoryLocationsKind MLK,
const Instruction *
I,
8735 if (MLK == NO_UNKOWN_MEM)
8737 State.removeAssumedBits(MLK);
8742 void categorizePtrValue(Attributor &
A,
const Instruction &
I,
const Value &Ptr,
8743 AAMemoryLocation::StateType &State,
bool &
Changed,
8744 unsigned AccessAS = 0);
8750void AAMemoryLocationImpl::categorizePtrValue(
8751 Attributor &
A,
const Instruction &
I,
const Value &Ptr,
8753 LLVM_DEBUG(
dbgs() <<
"[AAMemoryLocation] Categorize pointer locations for "
8758 unsigned ObjectAS =
Obj.getType()->getPointerAddressSpace();
8760 MemoryLocationsKind MLK = NO_LOCATIONS;
8780 MLK = NO_ARGUMENT_MEM;
8786 if (GVar->isConstant())
8789 if (GV->hasLocalLinkage())
8790 MLK = NO_GLOBAL_INTERNAL_MEM;
8792 MLK = NO_GLOBAL_EXTERNAL_MEM;
8800 bool IsKnownNoAlias;
8804 MLK = NO_MALLOCED_MEM;
8806 MLK = NO_UNKOWN_MEM;
8808 MLK = NO_UNKOWN_MEM;
8811 assert(MLK != NO_LOCATIONS &&
"No location specified!");
8812 LLVM_DEBUG(
dbgs() <<
"[AAMemoryLocation] Ptr value can be categorized: "
8813 << Obj <<
" -> " << getMemoryLocationsAsStr(MLK) <<
"\n");
8815 getAccessKindFromInst(&
I));
8820 const auto *AA =
A.getAAFor<AAUnderlyingObjects>(
8824 dbgs() <<
"[AAMemoryLocation] Pointer locations not categorized\n");
8825 updateStateAndAccessesMap(
State, NO_UNKOWN_MEM, &
I,
nullptr,
Changed,
8826 getAccessKindFromInst(&
I));
8831 dbgs() <<
"[AAMemoryLocation] Accessed locations with pointer locations: "
8835void AAMemoryLocationImpl::categorizeArgumentPointerLocations(
8838 for (
unsigned ArgNo = 0,
E = CB.
arg_size(); ArgNo <
E; ++ArgNo) {
8847 const auto *ArgOpMemLocationAA =
8850 if (ArgOpMemLocationAA && ArgOpMemLocationAA->isAssumedReadNone())
8855 categorizePtrValue(
A, CB, *ArgOp, AccessedLocs,
Changed);
8860AAMemoryLocationImpl::categorizeAccessedLocations(Attributor &
A, Instruction &
I,
8862 LLVM_DEBUG(
dbgs() <<
"[AAMemoryLocation] Categorize accessed locations for "
8866 AccessedLocs.intersectAssumedBits(NO_LOCATIONS);
8871 const auto *CBMemLocationAA =
A.getAAFor<AAMemoryLocation>(
8874 <<
" [" << CBMemLocationAA <<
"]\n");
8875 if (!CBMemLocationAA) {
8876 updateStateAndAccessesMap(AccessedLocs, NO_UNKOWN_MEM, &
I,
nullptr,
8877 Changed, getAccessKindFromInst(&
I));
8878 return NO_UNKOWN_MEM;
8881 if (CBMemLocationAA->isAssumedReadNone())
8882 return NO_LOCATIONS;
8884 if (CBMemLocationAA->isAssumedInaccessibleMemOnly()) {
8885 updateStateAndAccessesMap(AccessedLocs, NO_INACCESSIBLE_MEM, &
I,
nullptr,
8886 Changed, getAccessKindFromInst(&
I));
8887 return AccessedLocs.getAssumed();
8890 uint32_t CBAssumedNotAccessedLocs =
8891 CBMemLocationAA->getAssumedNotAccessedLocation();
8894 uint32_t CBAssumedNotAccessedLocsNoArgMem =
8895 CBAssumedNotAccessedLocs | NO_ARGUMENT_MEM | NO_GLOBAL_MEM;
8897 for (MemoryLocationsKind CurMLK = 1; CurMLK < NO_LOCATIONS; CurMLK *= 2) {
8898 if (CBAssumedNotAccessedLocsNoArgMem & CurMLK)
8900 updateStateAndAccessesMap(AccessedLocs, CurMLK, &
I,
nullptr,
Changed,
8901 getAccessKindFromInst(&
I));
8906 bool HasGlobalAccesses = ((~CBAssumedNotAccessedLocs) & NO_GLOBAL_MEM);
8907 if (HasGlobalAccesses) {
8910 updateStateAndAccessesMap(AccessedLocs, MLK, &
I, Ptr,
Changed,
8911 getAccessKindFromInst(&
I));
8914 if (!CBMemLocationAA->checkForAllAccessesToMemoryKind(
8915 AccessPred, inverseLocation(NO_GLOBAL_MEM,
false,
false)))
8916 return AccessedLocs.getWorstState();
8920 dbgs() <<
"[AAMemoryLocation] Accessed state before argument handling: "
8921 << getMemoryLocationsAsStr(AccessedLocs.getAssumed()) <<
"\n");
8924 bool HasArgAccesses = ((~CBAssumedNotAccessedLocs) & NO_ARGUMENT_MEM);
8926 categorizeArgumentPointerLocations(
A, *CB, AccessedLocs,
Changed);
8929 dbgs() <<
"[AAMemoryLocation] Accessed state after argument handling: "
8930 << getMemoryLocationsAsStr(AccessedLocs.getAssumed()) <<
"\n");
8932 return AccessedLocs.getAssumed();
8937 dbgs() <<
"[AAMemoryLocation] Categorize memory access with pointer: "
8938 <<
I <<
" [" << *Ptr <<
"]\n");
8939 categorizePtrValue(
A,
I, *Ptr, AccessedLocs,
Changed,
8940 Ptr->getType()->getPointerAddressSpace());
8941 return AccessedLocs.getAssumed();
8944 LLVM_DEBUG(
dbgs() <<
"[AAMemoryLocation] Failed to categorize instruction: "
8946 updateStateAndAccessesMap(AccessedLocs, NO_UNKOWN_MEM, &
I,
nullptr,
Changed,
8947 getAccessKindFromInst(&
I));
8948 return AccessedLocs.getAssumed();
8952struct AAMemoryLocationFunction final :
public AAMemoryLocationImpl {
8953 AAMemoryLocationFunction(
const IRPosition &IRP, Attributor &
A)
8954 : AAMemoryLocationImpl(IRP,
A) {}
8959 const auto *MemBehaviorAA =
8960 A.getAAFor<AAMemoryBehavior>(*
this, getIRPosition(), DepClassTy::NONE);
8963 return indicateOptimisticFixpoint();
8965 "AAMemoryLocation was not read-none but AAMemoryBehavior was!");
8966 A.recordDependence(*MemBehaviorAA, *
this, DepClassTy::OPTIONAL);
8967 return ChangeStatus::UNCHANGED;
8971 auto AssumedState = getAssumed();
8975 MemoryLocationsKind MLK = categorizeAccessedLocations(
A,
I,
Changed);
8976 LLVM_DEBUG(
dbgs() <<
"[AAMemoryLocation] Accessed locations for " <<
I
8977 <<
": " << getMemoryLocationsAsStr(MLK) <<
"\n");
8978 removeAssumedBits(inverseLocation(MLK,
false,
false));
8981 return getAssumedNotAccessedLocation() != VALID_STATE;
8984 bool UsedAssumedInformation =
false;
8985 if (!
A.checkForAllReadWriteInstructions(CheckRWInst, *
this,
8986 UsedAssumedInformation))
8987 return indicatePessimisticFixpoint();
8989 Changed |= AssumedState != getAssumed();
8990 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
8994 void trackStatistics()
const override {
8997 else if (isAssumedArgMemOnly())
8999 else if (isAssumedInaccessibleMemOnly())
9001 else if (isAssumedInaccessibleOrArgMemOnly())
9007struct AAMemoryLocationCallSite final : AAMemoryLocationImpl {
9008 AAMemoryLocationCallSite(
const IRPosition &IRP, Attributor &
A)
9009 : AAMemoryLocationImpl(IRP,
A) {}
9020 A.getAAFor<AAMemoryLocation>(*
this, FnPos, DepClassTy::REQUIRED);
9022 return indicatePessimisticFixpoint();
9026 updateStateAndAccessesMap(getState(), MLK,
I, Ptr,
Changed,
9027 getAccessKindFromInst(
I));
9030 if (!FnAA->checkForAllAccessesToMemoryKind(AccessPred, ALL_LOCATIONS))
9031 return indicatePessimisticFixpoint();
9032 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
9036 void trackStatistics()
const override {
9046struct AADenormalFPMathImpl :
public AADenormalFPMath {
9047 AADenormalFPMathImpl(
const IRPosition &IRP, Attributor &
A)
9048 : AADenormalFPMath(IRP,
A) {}
9050 const std::string getAsStr(Attributor *
A)
const override {
9051 std::string Str(
"AADenormalFPMath[");
9052 raw_string_ostream OS(Str);
9054 DenormalState
Known = getKnown();
9055 if (
Known.Mode.isValid())
9056 OS <<
"denormal-fp-math=" <<
Known.Mode;
9060 if (
Known.ModeF32.isValid())
9061 OS <<
" denormal-fp-math-f32=" <<
Known.ModeF32;
9067struct AADenormalFPMathFunction final : AADenormalFPMathImpl {
9068 AADenormalFPMathFunction(
const IRPosition &IRP, Attributor &
A)
9069 : AADenormalFPMathImpl(IRP,
A) {}
9073 DenormalFPEnv DenormEnv =
F->getDenormalFPEnv();
9083 auto CheckCallSite = [=, &Change, &
A](AbstractCallSite CS) {
9086 <<
"->" << getAssociatedFunction()->
getName() <<
'\n');
9088 const auto *CallerInfo =
A.getAAFor<AADenormalFPMath>(
9094 CallerInfo->getState());
9098 bool AllCallSitesKnown =
true;
9099 if (!
A.checkForAllCallSites(CheckCallSite, *
this,
true, AllCallSitesKnown))
9100 return indicatePessimisticFixpoint();
9102 if (Change == ChangeStatus::CHANGED && isModeFixed())
9108 LLVMContext &Ctx = getAssociatedFunction()->getContext();
9114 DenormalFPEnv KnownEnv(
Known.Mode,
Known.ModeF32);
9117 AttrToRemove.
push_back(Attribute::DenormalFPEnv);
9120 Ctx, Attribute::DenormalFPEnv,
9121 DenormalFPEnv(
Known.Mode,
Known.ModeF32).toIntValue()));
9124 auto &IRP = getIRPosition();
9127 return A.removeAttrs(IRP, AttrToRemove) |
9128 A.manifestAttrs(IRP, AttrToAdd,
true);
9131 void trackStatistics()
const override {
9140struct AAValueConstantRangeImpl : AAValueConstantRange {
9141 using StateType = IntegerRangeState;
9142 AAValueConstantRangeImpl(
const IRPosition &IRP, Attributor &
A)
9143 : AAValueConstantRange(IRP,
A) {}
9147 if (
A.hasSimplificationCallback(getIRPosition())) {
9148 indicatePessimisticFixpoint();
9153 intersectKnown(getConstantRangeFromSCEV(
A, getCtxI()));
9156 intersectKnown(getConstantRangeFromLVI(
A, getCtxI()));
9160 const std::string getAsStr(Attributor *
A)
const override {
9162 llvm::raw_string_ostream OS(Str);
9164 getKnown().print(OS);
9166 getAssumed().print(OS);
9173 const SCEV *getSCEV(Attributor &
A,
const Instruction *
I =
nullptr)
const {
9174 if (!getAnchorScope())
9177 ScalarEvolution *SE =
9178 A.getInfoCache().getAnalysisResultForFunction<ScalarEvolutionAnalysis>(
9181 LoopInfo *LI =
A.getInfoCache().getAnalysisResultForFunction<LoopAnalysis>(
9187 const SCEV *S = SE->
getSCEV(&getAssociatedValue());
9196 ConstantRange getConstantRangeFromSCEV(Attributor &
A,
9197 const Instruction *
I =
nullptr)
const {
9198 if (!getAnchorScope())
9201 ScalarEvolution *SE =
9202 A.getInfoCache().getAnalysisResultForFunction<ScalarEvolutionAnalysis>(
9205 const SCEV *S = getSCEV(
A,
I);
9215 getConstantRangeFromLVI(Attributor &
A,
9216 const Instruction *CtxI =
nullptr)
const {
9217 if (!getAnchorScope())
9220 LazyValueInfo *LVI =
9221 A.getInfoCache().getAnalysisResultForFunction<LazyValueAnalysis>(
9236 bool isValidCtxInstructionForOutsideAnalysis(Attributor &
A,
9237 const Instruction *CtxI,
9238 bool AllowAACtxI)
const {
9239 if (!CtxI || (!AllowAACtxI && CtxI == getCtxI()))
9251 InformationCache &InfoCache =
A.getInfoCache();
9252 const DominatorTree *DT =
9263 getAssumedConstantRange(Attributor &
A,
9264 const Instruction *CtxI =
nullptr)
const override {
9269 if (!isValidCtxInstructionForOutsideAnalysis(
A, CtxI,
9271 return getAssumed();
9273 ConstantRange LVIR = getConstantRangeFromLVI(
A, CtxI);
9274 ConstantRange SCEVR = getConstantRangeFromSCEV(
A, CtxI);
9275 return getAssumed().intersectWith(SCEVR).intersectWith(LVIR);
9280 getMDNodeForConstantRange(
Type *Ty, LLVMContext &Ctx,
9281 const ConstantRange &AssumedConstantRange) {
9283 Ty, AssumedConstantRange.
getLower())),
9285 Ty, AssumedConstantRange.
getUpper()))};
9290 static bool isBetterRange(
const ConstantRange &Assumed,
9291 const Instruction &
I) {
9295 std::optional<ConstantRange>
Known;
9299 }
else if (MDNode *KnownRanges =
I.getMetadata(LLVMContext::MD_range)) {
9305 if (KnownRanges->getNumOperands() > 2)
9308 ConstantInt *
Lower =
9310 ConstantInt *
Upper =
9320 setRangeMetadataIfisBetterRange(Instruction *
I,
9321 const ConstantRange &AssumedConstantRange) {
9322 if (isBetterRange(AssumedConstantRange, *
I)) {
9323 I->setMetadata(LLVMContext::MD_range,
9324 getMDNodeForConstantRange(
I->getType(),
I->getContext(),
9325 AssumedConstantRange));
9332 setRangeRetAttrIfisBetterRange(Attributor &
A,
const IRPosition &IRP,
9334 const ConstantRange &AssumedConstantRange) {
9335 if (isBetterRange(AssumedConstantRange, *
I)) {
9336 A.manifestAttrs(IRP,
9337 Attribute::get(
I->getContext(), Attribute::Range,
9338 AssumedConstantRange),
9348 ConstantRange AssumedConstantRange = getAssumedConstantRange(
A);
9351 auto &
V = getAssociatedValue();
9355 assert(
I == getCtxI() &&
"Should not annotate an instruction which is "
9356 "not the context instruction");
9358 if (setRangeMetadataIfisBetterRange(
I, AssumedConstantRange))
9359 Changed = ChangeStatus::CHANGED;
9361 if (setRangeRetAttrIfisBetterRange(
A, getIRPosition(),
I,
9362 AssumedConstantRange))
9363 Changed = ChangeStatus::CHANGED;
9371struct AAValueConstantRangeArgument final
9372 : AAArgumentFromCallSiteArguments<
9373 AAValueConstantRange, AAValueConstantRangeImpl, IntegerRangeState,
9375 using Base = AAArgumentFromCallSiteArguments<
9376 AAValueConstantRange, AAValueConstantRangeImpl, IntegerRangeState,
9378 AAValueConstantRangeArgument(
const IRPosition &IRP, Attributor &
A)
9382 void trackStatistics()
const override {
9387struct AAValueConstantRangeReturned
9388 : AAReturnedFromReturnedValues<AAValueConstantRange,
9389 AAValueConstantRangeImpl,
9390 AAValueConstantRangeImpl::StateType,
9393 AAReturnedFromReturnedValues<AAValueConstantRange,
9394 AAValueConstantRangeImpl,
9395 AAValueConstantRangeImpl::StateType,
9397 AAValueConstantRangeReturned(
const IRPosition &IRP, Attributor &
A)
9402 if (!
A.isFunctionIPOAmendable(*getAssociatedFunction()))
9403 indicatePessimisticFixpoint();
9407 void trackStatistics()
const override {
9412struct AAValueConstantRangeFloating : AAValueConstantRangeImpl {
9413 AAValueConstantRangeFloating(
const IRPosition &IRP, Attributor &
A)
9414 : AAValueConstantRangeImpl(IRP,
A) {}
9418 AAValueConstantRangeImpl::initialize(
A);
9422 Value &
V = getAssociatedValue();
9425 unionAssumed(ConstantRange(
C->getValue()));
9426 indicateOptimisticFixpoint();
9432 unionAssumed(ConstantRange(APInt(
getBitWidth(), 0)));
9433 indicateOptimisticFixpoint();
9445 if (
auto *RangeMD = LI->getMetadata(LLVMContext::MD_range)) {
9456 indicatePessimisticFixpoint();
9459 << getAssociatedValue() <<
"\n");
9462 bool calculateBinaryOperator(
9463 Attributor &
A, BinaryOperator *BinOp, IntegerRangeState &
T,
9464 const Instruction *CtxI,
9465 SmallVectorImpl<const AAValueConstantRange *> &QuerriedAAs) {
9470 bool UsedAssumedInformation =
false;
9471 const auto &SimplifiedLHS =
A.getAssumedSimplified(
9474 if (!SimplifiedLHS.has_value())
9476 if (!*SimplifiedLHS)
9478 LHS = *SimplifiedLHS;
9480 const auto &SimplifiedRHS =
A.getAssumedSimplified(
9483 if (!SimplifiedRHS.has_value())
9485 if (!*SimplifiedRHS)
9487 RHS = *SimplifiedRHS;
9493 auto *LHSAA =
A.getAAFor<AAValueConstantRange>(
9495 DepClassTy::REQUIRED);
9499 auto LHSAARange = LHSAA->getAssumedConstantRange(
A, CtxI);
9501 auto *RHSAA =
A.getAAFor<AAValueConstantRange>(
9503 DepClassTy::REQUIRED);
9507 auto RHSAARange = RHSAA->getAssumedConstantRange(
A, CtxI);
9509 auto AssumedRange = LHSAARange.binaryOp(BinOp->
getOpcode(), RHSAARange);
9511 T.unionAssumed(AssumedRange);
9515 return T.isValidState();
9518 bool calculateCastInst(
9519 Attributor &
A, CastInst *CastI, IntegerRangeState &
T,
9520 const Instruction *CtxI,
9521 SmallVectorImpl<const AAValueConstantRange *> &QuerriedAAs) {
9527 bool UsedAssumedInformation =
false;
9528 const auto &SimplifiedOpV =
A.getAssumedSimplified(
9531 if (!SimplifiedOpV.has_value())
9533 if (!*SimplifiedOpV)
9535 OpV = *SimplifiedOpV;
9540 auto *OpAA =
A.getAAFor<AAValueConstantRange>(
9542 DepClassTy::REQUIRED);
9546 T.unionAssumed(OpAA->getAssumed().castOp(CastI->
getOpcode(),
9548 return T.isValidState();
9552 calculateCmpInst(Attributor &
A, CmpInst *CmpI, IntegerRangeState &
T,
9553 const Instruction *CtxI,
9554 SmallVectorImpl<const AAValueConstantRange *> &QuerriedAAs) {
9559 bool UsedAssumedInformation =
false;
9560 const auto &SimplifiedLHS =
A.getAssumedSimplified(
9563 if (!SimplifiedLHS.has_value())
9565 if (!*SimplifiedLHS)
9567 LHS = *SimplifiedLHS;
9569 const auto &SimplifiedRHS =
A.getAssumedSimplified(
9572 if (!SimplifiedRHS.has_value())
9574 if (!*SimplifiedRHS)
9576 RHS = *SimplifiedRHS;
9582 auto *LHSAA =
A.getAAFor<AAValueConstantRange>(
9584 DepClassTy::REQUIRED);
9588 auto *RHSAA =
A.getAAFor<AAValueConstantRange>(
9590 DepClassTy::REQUIRED);
9594 auto LHSAARange = LHSAA->getAssumedConstantRange(
A, CtxI);
9595 auto RHSAARange = RHSAA->getAssumedConstantRange(
A, CtxI);
9598 if (LHSAARange.isEmptySet() || RHSAARange.isEmptySet())
9601 bool MustTrue =
false, MustFalse =
false;
9603 auto AllowedRegion =
9606 if (AllowedRegion.intersectWith(LHSAARange).isEmptySet())
9612 assert((!MustTrue || !MustFalse) &&
9613 "Either MustTrue or MustFalse should be false!");
9616 T.unionAssumed(ConstantRange(APInt( 1, 1)));
9618 T.unionAssumed(ConstantRange(APInt( 1, 0)));
9620 T.unionAssumed(ConstantRange( 1,
true));
9622 LLVM_DEBUG(
dbgs() <<
"[AAValueConstantRange] " << *CmpI <<
" after "
9623 << (MustTrue ?
"true" : (MustFalse ?
"false" :
"unknown"))
9624 <<
": " <<
T <<
"\n\t" << *LHSAA <<
"\t<op>\n\t"
9628 return T.isValidState();
9640 bool UsedAssumedInformation =
false;
9641 const auto &SimplifiedOpV =
A.getAssumedSimplified(
9644 if (!SimplifiedOpV.has_value())
9646 if (!*SimplifiedOpV)
9648 Value *VPtr = *SimplifiedOpV;
9651 const auto *AA =
A.getAAFor<AAValueConstantRange>(
9653 DepClassTy::REQUIRED);
9657 T.unionAssumed(AA->getAssumedConstantRange(
A, CtxI));
9661 return T.isValidState();
9666 if (!calculateBinaryOperator(
A, BinOp,
T, CtxI, QuerriedAAs))
9669 if (!calculateCmpInst(
A, CmpI,
T, CtxI, QuerriedAAs))
9672 if (!calculateCastInst(
A, CastI,
T, CtxI, QuerriedAAs))
9678 T.indicatePessimisticFixpoint();
9685 for (
const AAValueConstantRange *QueriedAA : QuerriedAAs) {
9686 if (QueriedAA !=
this)
9689 if (
T.getAssumed() == getState().getAssumed())
9691 T.indicatePessimisticFixpoint();
9694 return T.isValidState();
9697 if (!VisitValueCB(getAssociatedValue(), getCtxI()))
9698 return indicatePessimisticFixpoint();
9703 return ChangeStatus::UNCHANGED;
9704 if (++NumChanges > MaxNumChanges) {
9705 LLVM_DEBUG(
dbgs() <<
"[AAValueConstantRange] performed " << NumChanges
9706 <<
" but only " << MaxNumChanges
9707 <<
" are allowed to avoid cyclic reasoning.");
9708 return indicatePessimisticFixpoint();
9710 return ChangeStatus::CHANGED;
9714 void trackStatistics()
const override {
9723 static constexpr int MaxNumChanges = 5;
9726struct AAValueConstantRangeFunction : AAValueConstantRangeImpl {
9727 AAValueConstantRangeFunction(
const IRPosition &IRP, Attributor &
A)
9728 : AAValueConstantRangeImpl(IRP,
A) {}
9732 llvm_unreachable(
"AAValueConstantRange(Function|CallSite)::updateImpl will "
9740struct AAValueConstantRangeCallSite : AAValueConstantRangeFunction {
9741 AAValueConstantRangeCallSite(
const IRPosition &IRP, Attributor &
A)
9742 : AAValueConstantRangeFunction(IRP,
A) {}
9748struct AAValueConstantRangeCallSiteReturned
9749 : AACalleeToCallSite<AAValueConstantRange, AAValueConstantRangeImpl,
9750 AAValueConstantRangeImpl::StateType,
9752 AAValueConstantRangeCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
9753 : AACalleeToCallSite<AAValueConstantRange, AAValueConstantRangeImpl,
9754 AAValueConstantRangeImpl::StateType,
9761 if (std::optional<ConstantRange>
Range = CI->getRange())
9762 intersectKnown(*
Range);
9765 AAValueConstantRangeImpl::initialize(
A);
9769 void trackStatistics()
const override {
9773struct AAValueConstantRangeCallSiteArgument : AAValueConstantRangeFloating {
9774 AAValueConstantRangeCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
9775 : AAValueConstantRangeFloating(IRP,
A) {}
9779 return ChangeStatus::UNCHANGED;
9783 void trackStatistics()
const override {
9792struct AAPotentialConstantValuesImpl : AAPotentialConstantValues {
9795 AAPotentialConstantValuesImpl(
const IRPosition &IRP, Attributor &
A)
9796 : AAPotentialConstantValues(IRP,
A) {}
9800 if (
A.hasSimplificationCallback(getIRPosition()))
9801 indicatePessimisticFixpoint();
9803 AAPotentialConstantValues::initialize(
A);
9806 bool fillSetWithConstantValues(Attributor &
A,
const IRPosition &IRP, SetTy &S,
9807 bool &ContainsUndef,
bool ForSelf) {
9809 bool UsedAssumedInformation =
false;
9811 UsedAssumedInformation)) {
9818 auto *PotentialValuesAA =
A.getAAFor<AAPotentialConstantValues>(
9819 *
this, IRP, DepClassTy::REQUIRED);
9820 if (!PotentialValuesAA || !PotentialValuesAA->getState().isValidState())
9822 ContainsUndef = PotentialValuesAA->getState().undefIsContained();
9823 S = PotentialValuesAA->getState().getAssumedSet();
9830 ContainsUndef =
false;
9831 for (
auto &It :
Values) {
9833 ContainsUndef =
true;
9839 S.insert(CI->getValue());
9841 ContainsUndef &= S.empty();
9847 const std::string getAsStr(Attributor *
A)
const override {
9849 llvm::raw_string_ostream OS(Str);
9856 return indicatePessimisticFixpoint();
9860struct AAPotentialConstantValuesArgument final
9861 : AAArgumentFromCallSiteArguments<AAPotentialConstantValues,
9862 AAPotentialConstantValuesImpl,
9863 PotentialConstantIntValuesState> {
9864 using Base = AAArgumentFromCallSiteArguments<AAPotentialConstantValues,
9865 AAPotentialConstantValuesImpl,
9867 AAPotentialConstantValuesArgument(
const IRPosition &IRP, Attributor &
A)
9871 void trackStatistics()
const override {
9876struct AAPotentialConstantValuesReturned
9877 : AAReturnedFromReturnedValues<AAPotentialConstantValues,
9878 AAPotentialConstantValuesImpl> {
9879 using Base = AAReturnedFromReturnedValues<AAPotentialConstantValues,
9880 AAPotentialConstantValuesImpl>;
9881 AAPotentialConstantValuesReturned(
const IRPosition &IRP, Attributor &
A)
9885 if (!
A.isFunctionIPOAmendable(*getAssociatedFunction()))
9886 indicatePessimisticFixpoint();
9887 Base::initialize(
A);
9891 void trackStatistics()
const override {
9896struct AAPotentialConstantValuesFloating : AAPotentialConstantValuesImpl {
9897 AAPotentialConstantValuesFloating(
const IRPosition &IRP, Attributor &
A)
9898 : AAPotentialConstantValuesImpl(IRP,
A) {}
9902 AAPotentialConstantValuesImpl::initialize(
A);
9906 Value &
V = getAssociatedValue();
9909 unionAssumed(
C->getValue());
9910 indicateOptimisticFixpoint();
9915 unionAssumedWithUndef();
9916 indicateOptimisticFixpoint();
9926 indicatePessimisticFixpoint();
9929 << getAssociatedValue() <<
"\n");
9932 static bool calculateICmpInst(
const ICmpInst *ICI,
const APInt &
LHS,
9937 static APInt calculateCastInst(
const CastInst *CI,
const APInt &Src,
9938 uint32_t ResultBitWidth) {
9943 case Instruction::Trunc:
9944 return Src.trunc(ResultBitWidth);
9945 case Instruction::SExt:
9946 return Src.sext(ResultBitWidth);
9947 case Instruction::ZExt:
9948 return Src.zext(ResultBitWidth);
9949 case Instruction::BitCast:
9954 static APInt calculateBinaryOperator(
const BinaryOperator *BinOp,
9955 const APInt &
LHS,
const APInt &
RHS,
9956 bool &SkipOperation,
bool &Unsupported) {
9963 switch (BinOpcode) {
9967 case Instruction::Add:
9969 case Instruction::Sub:
9971 case Instruction::Mul:
9973 case Instruction::UDiv:
9975 SkipOperation =
true;
9979 case Instruction::SDiv:
9981 SkipOperation =
true;
9985 case Instruction::URem:
9987 SkipOperation =
true;
9991 case Instruction::SRem:
9993 SkipOperation =
true;
9997 case Instruction::Shl:
9999 case Instruction::LShr:
10001 case Instruction::AShr:
10003 case Instruction::And:
10005 case Instruction::Or:
10007 case Instruction::Xor:
10012 bool calculateBinaryOperatorAndTakeUnion(
const BinaryOperator *BinOp,
10013 const APInt &
LHS,
const APInt &
RHS) {
10014 bool SkipOperation =
false;
10017 calculateBinaryOperator(BinOp,
LHS,
RHS, SkipOperation, Unsupported);
10021 if (!SkipOperation)
10022 unionAssumed(Result);
10023 return isValidState();
10026 ChangeStatus updateWithICmpInst(Attributor &
A, ICmpInst *ICI) {
10027 auto AssumedBefore = getAssumed();
10031 bool LHSContainsUndef =
false, RHSContainsUndef =
false;
10032 SetTy LHSAAPVS, RHSAAPVS;
10034 LHSContainsUndef,
false) ||
10036 RHSContainsUndef,
false))
10037 return indicatePessimisticFixpoint();
10040 bool MaybeTrue =
false, MaybeFalse =
false;
10042 if (LHSContainsUndef && RHSContainsUndef) {
10045 unionAssumedWithUndef();
10046 }
else if (LHSContainsUndef) {
10047 for (
const APInt &R : RHSAAPVS) {
10048 bool CmpResult = calculateICmpInst(ICI, Zero, R);
10049 MaybeTrue |= CmpResult;
10050 MaybeFalse |= !CmpResult;
10051 if (MaybeTrue & MaybeFalse)
10052 return indicatePessimisticFixpoint();
10054 }
else if (RHSContainsUndef) {
10055 for (
const APInt &L : LHSAAPVS) {
10056 bool CmpResult = calculateICmpInst(ICI, L, Zero);
10057 MaybeTrue |= CmpResult;
10058 MaybeFalse |= !CmpResult;
10059 if (MaybeTrue & MaybeFalse)
10060 return indicatePessimisticFixpoint();
10063 for (
const APInt &L : LHSAAPVS) {
10064 for (
const APInt &R : RHSAAPVS) {
10065 bool CmpResult = calculateICmpInst(ICI, L, R);
10066 MaybeTrue |= CmpResult;
10067 MaybeFalse |= !CmpResult;
10068 if (MaybeTrue & MaybeFalse)
10069 return indicatePessimisticFixpoint();
10074 unionAssumed(APInt( 1, 1));
10076 unionAssumed(APInt( 1, 0));
10077 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10078 : ChangeStatus::CHANGED;
10081 ChangeStatus updateWithSelectInst(Attributor &
A, SelectInst *SI) {
10082 auto AssumedBefore = getAssumed();
10086 bool UsedAssumedInformation =
false;
10087 std::optional<Constant *>
C =
A.getAssumedConstant(
10088 *
SI->getCondition(), *
this, UsedAssumedInformation);
10091 bool OnlyLeft =
false, OnlyRight =
false;
10092 if (
C && *
C && (*C)->isOneValue())
10094 else if (
C && *
C && (*C)->isNullValue())
10097 bool LHSContainsUndef =
false, RHSContainsUndef =
false;
10098 SetTy LHSAAPVS, RHSAAPVS;
10101 LHSContainsUndef,
false))
10102 return indicatePessimisticFixpoint();
10106 RHSContainsUndef,
false))
10107 return indicatePessimisticFixpoint();
10109 if (OnlyLeft || OnlyRight) {
10111 auto *OpAA = OnlyLeft ? &LHSAAPVS : &RHSAAPVS;
10112 auto Undef = OnlyLeft ? LHSContainsUndef : RHSContainsUndef;
10115 unionAssumedWithUndef();
10117 for (
const auto &It : *OpAA)
10121 }
else if (LHSContainsUndef && RHSContainsUndef) {
10123 unionAssumedWithUndef();
10125 for (
const auto &It : LHSAAPVS)
10127 for (
const auto &It : RHSAAPVS)
10130 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10131 : ChangeStatus::CHANGED;
10134 ChangeStatus updateWithCastInst(Attributor &
A, CastInst *CI) {
10135 auto AssumedBefore = getAssumed();
10137 return indicatePessimisticFixpoint();
10142 bool SrcContainsUndef =
false;
10145 SrcContainsUndef,
false))
10146 return indicatePessimisticFixpoint();
10148 if (SrcContainsUndef)
10149 unionAssumedWithUndef();
10151 for (
const APInt &S : SrcPVS) {
10152 APInt
T = calculateCastInst(CI, S, ResultBitWidth);
10156 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10157 : ChangeStatus::CHANGED;
10160 ChangeStatus updateWithBinaryOperator(Attributor &
A, BinaryOperator *BinOp) {
10161 auto AssumedBefore = getAssumed();
10165 bool LHSContainsUndef =
false, RHSContainsUndef =
false;
10166 SetTy LHSAAPVS, RHSAAPVS;
10168 LHSContainsUndef,
false) ||
10170 RHSContainsUndef,
false))
10171 return indicatePessimisticFixpoint();
10176 if (LHSContainsUndef && RHSContainsUndef) {
10177 if (!calculateBinaryOperatorAndTakeUnion(BinOp, Zero, Zero))
10178 return indicatePessimisticFixpoint();
10179 }
else if (LHSContainsUndef) {
10180 for (
const APInt &R : RHSAAPVS) {
10181 if (!calculateBinaryOperatorAndTakeUnion(BinOp, Zero, R))
10182 return indicatePessimisticFixpoint();
10184 }
else if (RHSContainsUndef) {
10185 for (
const APInt &L : LHSAAPVS) {
10186 if (!calculateBinaryOperatorAndTakeUnion(BinOp, L, Zero))
10187 return indicatePessimisticFixpoint();
10190 for (
const APInt &L : LHSAAPVS) {
10191 for (
const APInt &R : RHSAAPVS) {
10192 if (!calculateBinaryOperatorAndTakeUnion(BinOp, L, R))
10193 return indicatePessimisticFixpoint();
10197 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10198 : ChangeStatus::CHANGED;
10201 ChangeStatus updateWithInstruction(Attributor &
A, Instruction *Inst) {
10202 auto AssumedBefore = getAssumed();
10204 bool ContainsUndef;
10206 ContainsUndef,
true))
10207 return indicatePessimisticFixpoint();
10208 if (ContainsUndef) {
10209 unionAssumedWithUndef();
10211 for (
const auto &It : Incoming)
10214 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10215 : ChangeStatus::CHANGED;
10220 Value &
V = getAssociatedValue();
10224 return updateWithICmpInst(
A, ICI);
10227 return updateWithSelectInst(
A, SI);
10230 return updateWithCastInst(
A, CI);
10233 return updateWithBinaryOperator(
A, BinOp);
10236 return updateWithInstruction(
A,
I);
10238 return indicatePessimisticFixpoint();
10242 void trackStatistics()
const override {
10247struct AAPotentialConstantValuesFunction : AAPotentialConstantValuesImpl {
10248 AAPotentialConstantValuesFunction(
const IRPosition &IRP, Attributor &
A)
10249 : AAPotentialConstantValuesImpl(IRP,
A) {}
10254 "AAPotentialConstantValues(Function|CallSite)::updateImpl will "
10259 void trackStatistics()
const override {
10264struct AAPotentialConstantValuesCallSite : AAPotentialConstantValuesFunction {
10265 AAPotentialConstantValuesCallSite(
const IRPosition &IRP, Attributor &
A)
10266 : AAPotentialConstantValuesFunction(IRP,
A) {}
10269 void trackStatistics()
const override {
10274struct AAPotentialConstantValuesCallSiteReturned
10275 : AACalleeToCallSite<AAPotentialConstantValues,
10276 AAPotentialConstantValuesImpl> {
10277 AAPotentialConstantValuesCallSiteReturned(
const IRPosition &IRP,
10279 : AACalleeToCallSite<AAPotentialConstantValues,
10280 AAPotentialConstantValuesImpl>(IRP,
A) {}
10283 void trackStatistics()
const override {
10288struct AAPotentialConstantValuesCallSiteArgument
10289 : AAPotentialConstantValuesFloating {
10290 AAPotentialConstantValuesCallSiteArgument(
const IRPosition &IRP,
10292 : AAPotentialConstantValuesFloating(IRP,
A) {}
10296 AAPotentialConstantValuesImpl::initialize(
A);
10297 if (isAtFixpoint())
10300 Value &
V = getAssociatedValue();
10303 unionAssumed(
C->getValue());
10304 indicateOptimisticFixpoint();
10309 unionAssumedWithUndef();
10310 indicateOptimisticFixpoint();
10317 Value &
V = getAssociatedValue();
10318 auto AssumedBefore = getAssumed();
10319 auto *AA =
A.getAAFor<AAPotentialConstantValues>(
10322 return indicatePessimisticFixpoint();
10323 const auto &S = AA->getAssumed();
10325 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10326 : ChangeStatus::CHANGED;
10330 void trackStatistics()
const override {
10339 bool IgnoreSubsumingPositions) {
10340 assert(ImpliedAttributeKind == Attribute::NoUndef &&
10341 "Unexpected attribute kind");
10342 if (
A.hasAttr(IRP, {Attribute::NoUndef}, IgnoreSubsumingPositions,
10343 Attribute::NoUndef))
10363 Value &V = getAssociatedValue();
10365 indicatePessimisticFixpoint();
10366 assert(!isImpliedByIR(
A, getIRPosition(), Attribute::NoUndef));
10370 bool followUseInMBEC(Attributor &
A,
const Use *U,
const Instruction *
I,
10371 AANoUndef::StateType &State) {
10372 const Value *UseV =
U->get();
10373 const DominatorTree *DT =
nullptr;
10374 AssumptionCache *AC =
nullptr;
10375 InformationCache &InfoCache =
A.getInfoCache();
10381 bool TrackUse =
false;
10390 const std::string getAsStr(Attributor *
A)
const override {
10391 return getAssumed() ?
"noundef" :
"may-undef-or-poison";
10398 bool UsedAssumedInformation =
false;
10399 if (
A.isAssumedDead(getIRPosition(),
nullptr,
nullptr,
10400 UsedAssumedInformation))
10401 return ChangeStatus::UNCHANGED;
10405 if (!
A.getAssumedSimplified(getIRPosition(), *
this, UsedAssumedInformation,
10408 return ChangeStatus::UNCHANGED;
10409 return AANoUndef::manifest(
A);
10413struct AANoUndefFloating :
public AANoUndefImpl {
10414 AANoUndefFloating(
const IRPosition &IRP, Attributor &
A)
10415 : AANoUndefImpl(IRP,
A) {}
10419 AANoUndefImpl::initialize(
A);
10420 if (!getState().isAtFixpoint() && getAnchorScope() &&
10421 !getAnchorScope()->isDeclaration())
10422 if (Instruction *CtxI = getCtxI())
10423 followUsesInMBEC(*
this,
A, getState(), *CtxI);
10428 auto VisitValueCB = [&](
const IRPosition &IRP) ->
bool {
10429 bool IsKnownNoUndef;
10431 A,
this, IRP, DepClassTy::REQUIRED, IsKnownNoUndef);
10435 bool UsedAssumedInformation =
false;
10436 Value *AssociatedValue = &getAssociatedValue();
10438 if (!
A.getAssumedSimplifiedValues(getIRPosition(), *
this,
Values,
10443 Values.size() != 1 ||
Values.front().getValue() != AssociatedValue;
10451 if (AVIRP == getIRPosition() || !VisitValueCB(AVIRP))
10452 return indicatePessimisticFixpoint();
10453 return ChangeStatus::UNCHANGED;
10456 for (
const auto &VAC :
Values)
10458 return indicatePessimisticFixpoint();
10460 return ChangeStatus::UNCHANGED;
10467struct AANoUndefReturned final
10468 : AAReturnedFromReturnedValues<AANoUndef, AANoUndefImpl> {
10469 AANoUndefReturned(
const IRPosition &IRP, Attributor &
A)
10470 : AAReturnedFromReturnedValues<AANoUndef, AANoUndefImpl>(IRP,
A) {}
10476struct AANoUndefArgument final
10477 : AAArgumentFromCallSiteArguments<AANoUndef, AANoUndefImpl> {
10478 AANoUndefArgument(
const IRPosition &IRP, Attributor &
A)
10479 : AAArgumentFromCallSiteArguments<AANoUndef, AANoUndefImpl>(IRP,
A) {}
10485struct AANoUndefCallSiteArgument final : AANoUndefFloating {
10486 AANoUndefCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
10487 : AANoUndefFloating(IRP,
A) {}
10493struct AANoUndefCallSiteReturned final
10494 : AACalleeToCallSite<AANoUndef, AANoUndefImpl> {
10495 AANoUndefCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
10496 : AACalleeToCallSite<AANoUndef, AANoUndefImpl>(IRP,
A) {}
10504struct AANoFPClassImpl : AANoFPClass {
10505 AANoFPClassImpl(
const IRPosition &IRP, Attributor &
A) : AANoFPClass(IRP,
A) {}
10508 const IRPosition &IRP = getIRPosition();
10512 indicateOptimisticFixpoint();
10517 A.getAttrs(getIRPosition(), {Attribute::NoFPClass},
Attrs,
false);
10518 for (
const auto &Attr : Attrs) {
10525 const DataLayout &
DL =
A.getDataLayout();
10526 InformationCache &InfoCache =
A.getInfoCache();
10528 const DominatorTree *DT =
nullptr;
10529 AssumptionCache *AC =
nullptr;
10530 const TargetLibraryInfo *TLI =
nullptr;
10534 if (!
F->isDeclaration()) {
10541 SimplifyQuery Q(
DL, TLI, DT, AC, CtxI);
10548 followUsesInMBEC(*
this,
A, getState(), *CtxI);
10552 bool followUseInMBEC(Attributor &
A,
const Use *U,
const Instruction *
I,
10553 AANoFPClass::StateType &State) {
10564 if (
auto *NoFPAA =
A.getAAFor<AANoFPClass>(*
this, IRP, DepClassTy::NONE))
10565 State.addKnownBits(NoFPAA->getState().getKnown());
10569 const std::string getAsStr(Attributor *
A)
const override {
10570 std::string
Result =
"nofpclass";
10571 raw_string_ostream OS(Result);
10572 OS << getKnownNoFPClass() <<
'/' << getAssumedNoFPClass();
10576 void getDeducedAttributes(Attributor &
A, LLVMContext &Ctx,
10577 SmallVectorImpl<Attribute> &Attrs)
const override {
10578 Attrs.emplace_back(Attribute::getWithNoFPClass(Ctx, getAssumedNoFPClass()));
10582struct AANoFPClassFloating :
public AANoFPClassImpl {
10583 AANoFPClassFloating(
const IRPosition &IRP, Attributor &
A)
10584 : AANoFPClassImpl(IRP,
A) {}
10589 bool UsedAssumedInformation =
false;
10590 if (!
A.getAssumedSimplifiedValues(getIRPosition(), *
this,
Values,
10592 Values.push_back({getAssociatedValue(), getCtxI()});
10598 DepClassTy::REQUIRED);
10599 if (!AA ||
this == AA) {
10600 T.indicatePessimisticFixpoint();
10602 const AANoFPClass::StateType &S =
10603 static_cast<const AANoFPClass::StateType &
>(AA->
getState());
10606 return T.isValidState();
10609 for (
const auto &VAC :
Values)
10611 return indicatePessimisticFixpoint();
10617 void trackStatistics()
const override {
10622struct AANoFPClassReturned final
10623 : AAReturnedFromReturnedValues<AANoFPClass, AANoFPClassImpl,
10624 AANoFPClassImpl::StateType, false,
10625 Attribute::None, false> {
10626 AANoFPClassReturned(
const IRPosition &IRP, Attributor &
A)
10627 : AAReturnedFromReturnedValues<AANoFPClass, AANoFPClassImpl,
10628 AANoFPClassImpl::StateType,
false,
10632 void trackStatistics()
const override {
10637struct AANoFPClassArgument final
10638 : AAArgumentFromCallSiteArguments<AANoFPClass, AANoFPClassImpl> {
10639 AANoFPClassArgument(
const IRPosition &IRP, Attributor &
A)
10640 : AAArgumentFromCallSiteArguments<AANoFPClass, AANoFPClassImpl>(IRP,
A) {}
10646struct AANoFPClassCallSiteArgument final : AANoFPClassFloating {
10647 AANoFPClassCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
10648 : AANoFPClassFloating(IRP,
A) {}
10651 void trackStatistics()
const override {
10656struct AANoFPClassCallSiteReturned final
10657 : AACalleeToCallSite<AANoFPClass, AANoFPClassImpl> {
10658 AANoFPClassCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
10659 : AACalleeToCallSite<AANoFPClass, AANoFPClassImpl>(IRP,
A) {}
10662 void trackStatistics()
const override {
10667struct AACallEdgesImpl :
public AACallEdges {
10668 AACallEdgesImpl(
const IRPosition &IRP, Attributor &
A) : AACallEdges(IRP,
A) {}
10670 const SetVector<Function *> &getOptimisticEdges()
const override {
10671 return CalledFunctions;
10674 bool hasUnknownCallee()
const override {
return HasUnknownCallee; }
10676 bool hasNonAsmUnknownCallee()
const override {
10677 return HasUnknownCalleeNonAsm;
10680 const std::string getAsStr(Attributor *
A)
const override {
10681 return "CallEdges[" + std::to_string(HasUnknownCallee) +
"," +
10682 std::to_string(CalledFunctions.size()) +
"]";
10685 void trackStatistics()
const override {}
10689 if (CalledFunctions.insert(Fn)) {
10690 Change = ChangeStatus::CHANGED;
10696 void setHasUnknownCallee(
bool NonAsm,
ChangeStatus &Change) {
10697 if (!HasUnknownCallee)
10698 Change = ChangeStatus::CHANGED;
10699 if (NonAsm && !HasUnknownCalleeNonAsm)
10700 Change = ChangeStatus::CHANGED;
10701 HasUnknownCalleeNonAsm |= NonAsm;
10702 HasUnknownCallee =
true;
10707 SetVector<Function *> CalledFunctions;
10710 bool HasUnknownCallee =
false;
10713 bool HasUnknownCalleeNonAsm =
false;
10716struct AACallEdgesCallSite :
public AACallEdgesImpl {
10717 AACallEdgesCallSite(
const IRPosition &IRP, Attributor &
A)
10718 : AACallEdgesImpl(IRP,
A) {}
10725 addCalledFunction(Fn, Change);
10727 LLVM_DEBUG(
dbgs() <<
"[AACallEdges] Unrecognized value: " << V <<
"\n");
10728 setHasUnknownCallee(
true, Change);
10739 VisitValue(*V, CtxI);
10743 bool UsedAssumedInformation =
false;
10747 Values.push_back({*
V, CtxI});
10749 for (
auto &VAC :
Values)
10756 if (
IA->hasSideEffects() &&
10759 setHasUnknownCallee(
false, Change);
10765 if (
auto *IndirectCallAA =
A.getAAFor<AAIndirectCallInfo>(
10766 *
this, getIRPosition(), DepClassTy::OPTIONAL))
10767 if (IndirectCallAA->foreachCallee(
10768 [&](
Function *Fn) { return VisitValue(*Fn, CB); }))
10777 for (
const Use *U : CallbackUses)
10778 ProcessCalledOperand(
U->get(), CB);
10784struct AACallEdgesFunction :
public AACallEdgesImpl {
10785 AACallEdgesFunction(
const IRPosition &IRP, Attributor &
A)
10786 : AACallEdgesImpl(IRP,
A) {}
10795 auto *CBEdges =
A.getAAFor<AACallEdges>(
10799 if (CBEdges->hasNonAsmUnknownCallee())
10800 setHasUnknownCallee(
true, Change);
10801 if (CBEdges->hasUnknownCallee())
10802 setHasUnknownCallee(
false, Change);
10804 for (
Function *
F : CBEdges->getOptimisticEdges())
10805 addCalledFunction(
F, Change);
10811 bool UsedAssumedInformation =
false;
10812 if (!
A.checkForAllCallLikeInstructions(ProcessCallInst, *
this,
10813 UsedAssumedInformation,
10817 setHasUnknownCallee(
true, Change);
10826struct AAInterFnReachabilityFunction
10827 :
public CachedReachabilityAA<AAInterFnReachability, Function> {
10828 using Base = CachedReachabilityAA<AAInterFnReachability, Function>;
10829 AAInterFnReachabilityFunction(
const IRPosition &IRP, Attributor &
A)
10832 bool instructionCanReach(
10833 Attributor &
A,
const Instruction &From,
const Function &To,
10836 auto *NonConstThis =
const_cast<AAInterFnReachabilityFunction *
>(
this);
10838 RQITy StackRQI(
A, From, To, ExclusionSet,
false);
10839 RQITy::Reachable
Result;
10840 if (!NonConstThis->checkQueryCache(
A, StackRQI, Result))
10841 return NonConstThis->isReachableImpl(
A, StackRQI,
10843 return Result == RQITy::Reachable::Yes;
10847 bool IsTemporaryRQI)
override {
10849 &RQI.From->getFunction()->getEntryBlock().front();
10850 if (EntryI != RQI.From &&
10851 !instructionCanReach(
A, *EntryI, *RQI.To,
nullptr))
10852 return rememberResult(
A, RQITy::Reachable::No, RQI,
false,
10855 auto CheckReachableCallBase = [&](CallBase *CB) {
10856 auto *CBEdges =
A.getAAFor<AACallEdges>(
10858 if (!CBEdges || !CBEdges->getState().isValidState())
10861 if (CBEdges->hasUnknownCallee())
10864 for (
Function *Fn : CBEdges->getOptimisticEdges()) {
10875 if (Fn == getAnchorScope()) {
10876 if (EntryI == RQI.From)
10881 const AAInterFnReachability *InterFnReachability =
10883 DepClassTy::OPTIONAL);
10886 if (!InterFnReachability ||
10894 const auto *IntraFnReachability =
A.getAAFor<AAIntraFnReachability>(
10896 DepClassTy::OPTIONAL);
10904 return IntraFnReachability && !IntraFnReachability->isAssumedReachable(
10905 A, *RQI.From, CBInst, RQI.ExclusionSet);
10908 bool UsedExclusionSet =
true;
10909 bool UsedAssumedInformation =
false;
10910 if (!
A.checkForAllCallLikeInstructions(CheckCallBase, *
this,
10911 UsedAssumedInformation,
10913 return rememberResult(
A, RQITy::Reachable::Yes, RQI, UsedExclusionSet,
10916 return rememberResult(
A, RQITy::Reachable::No, RQI, UsedExclusionSet,
10920 void trackStatistics()
const override {}
10924template <
typename AAType>
10925static std::optional<Constant *>
10928 if (!Ty.isIntegerTy())
10936 std::optional<Constant *> COpt =
AA->getAssumedConstant(
A);
10938 if (!COpt.has_value()) {
10940 return std::nullopt;
10942 if (
auto *
C = *COpt) {
10953 std::optional<Value *> V;
10954 for (
auto &It :
Values) {
10956 if (V.has_value() && !*V)
10959 if (!V.has_value())
10973 if (
A.hasSimplificationCallback(getIRPosition())) {
10974 indicatePessimisticFixpoint();
10977 Value *Stripped = getAssociatedValue().stripPointerCasts();
10979 addValue(
A, getState(), *Stripped, getCtxI(),
AA::AnyScope,
10981 indicateOptimisticFixpoint();
10984 AAPotentialValues::initialize(
A);
10988 const std::string getAsStr(Attributor *
A)
const override {
10990 llvm::raw_string_ostream OS(Str);
10995 template <
typename AAType>
10996 static std::optional<Value *> askOtherAA(Attributor &
A,
10997 const AbstractAttribute &AA,
10998 const IRPosition &IRP,
Type &Ty) {
11003 return std::nullopt;
11010 virtual void addValue(Attributor &
A, StateType &State,
Value &V,
11016 for (
const auto &U : CB->
args()) {
11026 Type &Ty = *getAssociatedType();
11027 std::optional<Value *> SimpleV =
11028 askOtherAA<AAValueConstantRange>(
A, *
this, ValIRP, Ty);
11029 if (SimpleV.has_value() && !*SimpleV) {
11030 auto *PotentialConstantsAA =
A.getAAFor<AAPotentialConstantValues>(
11031 *
this, ValIRP, DepClassTy::OPTIONAL);
11032 if (PotentialConstantsAA && PotentialConstantsAA->isValidState()) {
11033 for (
const auto &It : PotentialConstantsAA->getAssumedSet())
11034 State.unionAssumed({{*ConstantInt::get(&Ty, It),
nullptr}, S});
11035 if (PotentialConstantsAA->undefIsContained())
11040 if (!SimpleV.has_value())
11052 State.unionAssumed({{*VPtr, CtxI}, S});
11058 AA::ValueAndContext
I;
11062 return II.I ==
I &&
II.S == S;
11065 return std::tie(
I, S) < std::tie(
II.I,
II.S);
11069 bool recurseForValue(Attributor &
A,
const IRPosition &IRP,
AA::ValueScope S) {
11070 SmallMapVector<AA::ValueAndContext, int, 8> ValueScopeMap;
11075 bool UsedAssumedInformation =
false;
11077 if (!
A.getAssumedSimplifiedValues(IRP,
this,
Values, CS,
11078 UsedAssumedInformation))
11082 ValueScopeMap[It] += CS;
11084 for (
auto &It : ValueScopeMap)
11085 addValue(
A, getState(), *It.first.getValue(), It.first.getCtxI(),
11091 void giveUpOnIntraprocedural(Attributor &
A) {
11092 auto NewS = StateType::getBestState(getState());
11093 for (
const auto &It : getAssumedSet()) {
11096 addValue(
A, NewS, *It.first.getValue(), It.first.getCtxI(),
11099 assert(!undefIsContained() &&
"Undef should be an explicit value!");
11107 getState() = StateType::getBestState(getState());
11108 getState().unionAssumed({{getAssociatedValue(), getCtxI()},
AA::AnyScope});
11109 AAPotentialValues::indicateOptimisticFixpoint();
11110 return ChangeStatus::CHANGED;
11115 return indicatePessimisticFixpoint();
11123 if (!getAssumedSimplifiedValues(
A,
Values, S))
11125 Value &OldV = getAssociatedValue();
11128 Value *NewV = getSingleValue(
A, *
this, getIRPosition(),
Values);
11129 if (!NewV || NewV == &OldV)
11134 if (
A.changeAfterManifest(getIRPosition(), *NewV))
11135 return ChangeStatus::CHANGED;
11137 return ChangeStatus::UNCHANGED;
11140 bool getAssumedSimplifiedValues(
11141 Attributor &
A, SmallVectorImpl<AA::ValueAndContext> &
Values,
11142 AA::ValueScope S,
bool RecurseForSelectAndPHI =
false)
const override {
11143 if (!isValidState())
11145 bool UsedAssumedInformation =
false;
11146 for (
const auto &It : getAssumedSet())
11147 if (It.second & S) {
11148 if (RecurseForSelectAndPHI && (
isa<PHINode>(It.first.getValue()) ||
11150 if (
A.getAssumedSimplifiedValues(
11152 this,
Values, S, UsedAssumedInformation))
11155 Values.push_back(It.first);
11157 assert(!undefIsContained() &&
"Undef should be an explicit value!");
11162struct AAPotentialValuesFloating : AAPotentialValuesImpl {
11163 AAPotentialValuesFloating(
const IRPosition &IRP, Attributor &
A)
11164 : AAPotentialValuesImpl(IRP,
A) {}
11168 auto AssumedBefore = getAssumed();
11170 genericValueTraversal(
A, &getAssociatedValue());
11172 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
11173 : ChangeStatus::CHANGED;
11177 struct LivenessInfo {
11178 const AAIsDead *LivenessAA =
nullptr;
11179 bool AnyDead =
false;
11189 SmallVectorImpl<ItemInfo> &Worklist) {
11192 bool UsedAssumedInformation =
false;
11194 auto GetSimplifiedValues = [&](
Value &
V,
11196 if (!
A.getAssumedSimplifiedValues(
11200 Values.push_back(AA::ValueAndContext{
V,
II.I.getCtxI()});
11204 if (GetSimplifiedValues(*
LHS, LHSValues))
11206 if (GetSimplifiedValues(*
RHS, RHSValues))
11211 InformationCache &InfoCache =
A.getInfoCache();
11218 F ?
A.getInfoCache().getTargetLibraryInfoForFunction(*
F) :
nullptr;
11223 const DataLayout &
DL =
A.getDataLayout();
11224 SimplifyQuery Q(
DL, TLI, DT, AC, CmpI);
11226 auto CheckPair = [&](
Value &LHSV,
Value &RHSV) {
11229 nullptr,
II.S, getAnchorScope());
11235 if (&LHSV == &RHSV &&
11237 Constant *NewV = ConstantInt::get(Type::getInt1Ty(Ctx),
11239 addValue(
A, getState(), *NewV,
nullptr,
II.S,
11246 if (TypedLHS && TypedRHS) {
11248 if (NewV && NewV != &Cmp) {
11249 addValue(
A, getState(), *NewV,
nullptr,
II.S,
11261 if (!LHSIsNull && !RHSIsNull)
11267 assert((LHSIsNull || RHSIsNull) &&
11268 "Expected nullptr versus non-nullptr comparison at this point");
11271 unsigned PtrIdx = LHSIsNull;
11272 bool IsKnownNonNull;
11275 DepClassTy::REQUIRED, IsKnownNonNull);
11276 if (!IsAssumedNonNull)
11282 addValue(
A, getState(), *NewV,
nullptr,
II.S,
11287 for (
auto &LHSValue : LHSValues)
11288 for (
auto &RHSValue : RHSValues)
11289 if (!CheckPair(*LHSValue.getValue(), *RHSValue.getValue()))
11294 bool handleSelectInst(Attributor &
A, SelectInst &SI, ItemInfo
II,
11295 SmallVectorImpl<ItemInfo> &Worklist) {
11297 bool UsedAssumedInformation =
false;
11299 std::optional<Constant *>
C =
11300 A.getAssumedConstant(*
SI.getCondition(), *
this, UsedAssumedInformation);
11301 bool NoValueYet = !
C.has_value();
11309 }
else if (&SI == &getAssociatedValue()) {
11314 std::optional<Value *> SimpleV =
A.getAssumedSimplified(
11316 if (!SimpleV.has_value())
11319 addValue(
A, getState(), **SimpleV, CtxI,
II.S, getAnchorScope());
11327 bool handleLoadInst(Attributor &
A, LoadInst &LI, ItemInfo
II,
11328 SmallVectorImpl<ItemInfo> &Worklist) {
11329 SmallSetVector<Value *, 4> PotentialCopies;
11330 SmallSetVector<Instruction *, 4> PotentialValueOrigins;
11331 bool UsedAssumedInformation =
false;
11333 PotentialValueOrigins, *
this,
11334 UsedAssumedInformation,
11336 LLVM_DEBUG(
dbgs() <<
"[AAPotentialValues] Failed to get potentially "
11337 "loaded values for load instruction "
11345 InformationCache &InfoCache =
A.getInfoCache();
11347 if (!
llvm::all_of(PotentialValueOrigins, [&](Instruction *
I) {
11351 return A.isAssumedDead(
SI->getOperandUse(0),
this,
11353 UsedAssumedInformation,
11355 return A.isAssumedDead(*
I,
this,
nullptr,
11356 UsedAssumedInformation,
11359 LLVM_DEBUG(
dbgs() <<
"[AAPotentialValues] Load is onl used by assumes "
11360 "and we cannot delete all the stores: "
11371 bool AllLocal = ScopeIsLocal;
11376 if (!DynamicallyUnique) {
11377 LLVM_DEBUG(
dbgs() <<
"[AAPotentialValues] Not all potentially loaded "
11378 "values are dynamically unique: "
11383 for (
auto *PotentialCopy : PotentialCopies) {
11385 Worklist.
push_back({{*PotentialCopy, CtxI},
II.S});
11390 if (!AllLocal && ScopeIsLocal)
11395 bool handlePHINode(
11396 Attributor &
A, PHINode &
PHI, ItemInfo
II,
11397 SmallVectorImpl<ItemInfo> &Worklist,
11398 SmallMapVector<const Function *, LivenessInfo, 4> &LivenessAAs) {
11399 auto GetLivenessInfo = [&](
const Function &
F) -> LivenessInfo & {
11400 LivenessInfo &LI = LivenessAAs[&
F];
11401 if (!LI.LivenessAA)
11407 if (&
PHI == &getAssociatedValue()) {
11408 LivenessInfo &LI = GetLivenessInfo(*
PHI.getFunction());
11410 A.getInfoCache().getAnalysisResultForFunction<CycleAnalysis>(
11411 *
PHI.getFunction());
11415 for (
unsigned u = 0, e =
PHI.getNumIncomingValues(); u < e; u++) {
11417 if (LI.LivenessAA &&
11418 LI.LivenessAA->isEdgeDead(IncomingBB,
PHI.getParent())) {
11437 bool UsedAssumedInformation =
false;
11438 std::optional<Value *> SimpleV =
A.getAssumedSimplified(
11440 if (!SimpleV.has_value())
11444 addValue(
A, getState(), **SimpleV, &
PHI,
II.S, getAnchorScope());
11451 bool handleGenericInst(Attributor &
A, Instruction &
I, ItemInfo
II,
11452 SmallVectorImpl<ItemInfo> &Worklist) {
11453 bool SomeSimplified =
false;
11454 bool UsedAssumedInformation =
false;
11456 SmallVector<Value *, 8> NewOps(
I.getNumOperands());
11459 const auto &SimplifiedOp =
A.getAssumedSimplified(
11464 if (!SimplifiedOp.has_value())
11468 NewOps[Idx] = *SimplifiedOp;
11472 SomeSimplified |= (NewOps[Idx] !=
Op);
11478 if (!SomeSimplified)
11481 InformationCache &InfoCache =
A.getInfoCache();
11485 const auto *TLI =
A.getInfoCache().getTargetLibraryInfoForFunction(*
F);
11488 const DataLayout &
DL =
I.getDataLayout();
11489 SimplifyQuery Q(
DL, TLI, DT, AC, &
I);
11491 if (!NewV || NewV == &
I)
11494 LLVM_DEBUG(
dbgs() <<
"Generic inst " <<
I <<
" assumed simplified to "
11501 Attributor &
A, Instruction &
I, ItemInfo
II,
11502 SmallVectorImpl<ItemInfo> &Worklist,
11503 SmallMapVector<const Function *, LivenessInfo, 4> &LivenessAAs) {
11506 CI->getPredicate(),
II, Worklist);
11508 switch (
I.getOpcode()) {
11509 case Instruction::Select:
11511 case Instruction::PHI:
11513 case Instruction::Load:
11516 return handleGenericInst(
A,
I,
II, Worklist);
11521 void genericValueTraversal(Attributor &
A,
Value *InitialV) {
11522 SmallMapVector<const Function *, LivenessInfo, 4> LivenessAAs;
11524 SmallSet<ItemInfo, 16> Visited;
11543 LLVM_DEBUG(
dbgs() <<
"Generic value traversal reached iteration limit: "
11544 << Iteration <<
"!\n");
11545 addValue(
A, getState(), *V, CtxI, S, getAnchorScope());
11551 Value *NewV =
nullptr;
11552 if (
V->getType()->isPointerTy()) {
11558 for (Argument &Arg :
Callee->args())
11565 if (NewV && NewV != V) {
11566 Worklist.
push_back({{*NewV, CtxI}, S});
11580 if (V == InitialV && CtxI == getCtxI()) {
11581 indicatePessimisticFixpoint();
11585 addValue(
A, getState(), *V, CtxI, S, getAnchorScope());
11586 }
while (!Worklist.
empty());
11590 for (
auto &It : LivenessAAs)
11591 if (It.second.AnyDead)
11592 A.recordDependence(*It.second.LivenessAA, *
this, DepClassTy::OPTIONAL);
11596 void trackStatistics()
const override {
11601struct AAPotentialValuesArgument final : AAPotentialValuesImpl {
11602 using Base = AAPotentialValuesImpl;
11603 AAPotentialValuesArgument(
const IRPosition &IRP, Attributor &
A)
11610 indicatePessimisticFixpoint();
11615 auto AssumedBefore = getAssumed();
11617 unsigned ArgNo = getCalleeArgNo();
11619 bool UsedAssumedInformation =
false;
11621 auto CallSitePred = [&](AbstractCallSite ACS) {
11623 if (CSArgIRP.getPositionKind() == IRP_INVALID)
11626 if (!
A.getAssumedSimplifiedValues(CSArgIRP,
this,
Values,
11628 UsedAssumedInformation))
11631 return isValidState();
11634 if (!
A.checkForAllCallSites(CallSitePred, *
this,
11636 UsedAssumedInformation))
11637 return indicatePessimisticFixpoint();
11639 Function *Fn = getAssociatedFunction();
11640 bool AnyNonLocal =
false;
11641 for (
auto &It :
Values) {
11643 addValue(
A, getState(), *It.getValue(), It.getCtxI(),
AA::AnyScope,
11648 return indicatePessimisticFixpoint();
11652 addValue(
A, getState(), *It.getValue(), It.getCtxI(),
AA::AnyScope,
11658 AnyNonLocal =
true;
11660 assert(!undefIsContained() &&
"Undef should be an explicit value!");
11662 giveUpOnIntraprocedural(
A);
11664 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
11665 : ChangeStatus::CHANGED;
11669 void trackStatistics()
const override {
11674struct AAPotentialValuesReturned :
public AAPotentialValuesFloating {
11675 using Base = AAPotentialValuesFloating;
11676 AAPotentialValuesReturned(
const IRPosition &IRP, Attributor &
A)
11682 if (!
F ||
F->isDeclaration() ||
F->getReturnType()->isVoidTy()) {
11683 indicatePessimisticFixpoint();
11687 for (Argument &Arg :
F->args())
11690 ReturnedArg = &Arg;
11693 if (!
A.isFunctionIPOAmendable(*
F) ||
11694 A.hasSimplificationCallback(getIRPosition())) {
11696 indicatePessimisticFixpoint();
11698 indicateOptimisticFixpoint();
11704 auto AssumedBefore = getAssumed();
11705 bool UsedAssumedInformation =
false;
11708 Function *AnchorScope = getAnchorScope();
11714 UsedAssumedInformation,
11720 bool AllInterAreIntra =
false;
11727 for (
const AA::ValueAndContext &VAC :
Values) {
11728 addValue(
A, getState(), *VAC.
getValue(),
11732 if (AllInterAreIntra)
11739 HandleReturnedValue(*ReturnedArg,
nullptr,
true);
11742 bool AddValues =
true;
11745 addValue(
A, getState(), *RetI.getOperand(0), &RetI,
AA::AnyScope,
11749 return HandleReturnedValue(*RetI.getOperand(0), &RetI, AddValues);
11752 if (!
A.checkForAllInstructions(RetInstPred, *
this, {Instruction::Ret},
11753 UsedAssumedInformation,
11755 return indicatePessimisticFixpoint();
11758 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
11759 : ChangeStatus::CHANGED;
11764 return ChangeStatus::UNCHANGED;
11766 if (!getAssumedSimplifiedValues(
A,
Values, AA::ValueScope::Intraprocedural,
11768 return ChangeStatus::UNCHANGED;
11769 Value *NewVal = getSingleValue(
A, *
this, getIRPosition(),
Values);
11771 return ChangeStatus::UNCHANGED;
11776 "Number of function with unique return");
11779 {Attribute::get(Arg->
getContext(), Attribute::Returned)});
11784 Value *RetOp = RetI.getOperand(0);
11788 if (
A.changeUseAfterManifest(RetI.getOperandUse(0), *NewVal))
11789 Changed = ChangeStatus::CHANGED;
11792 bool UsedAssumedInformation =
false;
11793 (void)
A.checkForAllInstructions(RetInstPred, *
this, {Instruction::Ret},
11794 UsedAssumedInformation,
11800 return AAPotentialValues::indicatePessimisticFixpoint();
11804 void trackStatistics()
const override{
11811struct AAPotentialValuesFunction : AAPotentialValuesImpl {
11812 AAPotentialValuesFunction(
const IRPosition &IRP, Attributor &
A)
11813 : AAPotentialValuesImpl(IRP,
A) {}
11822 void trackStatistics()
const override {
11827struct AAPotentialValuesCallSite : AAPotentialValuesFunction {
11828 AAPotentialValuesCallSite(
const IRPosition &IRP, Attributor &
A)
11829 : AAPotentialValuesFunction(IRP,
A) {}
11832 void trackStatistics()
const override {
11837struct AAPotentialValuesCallSiteReturned : AAPotentialValuesImpl {
11838 AAPotentialValuesCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
11839 : AAPotentialValuesImpl(IRP,
A) {}
11843 auto AssumedBefore = getAssumed();
11847 return indicatePessimisticFixpoint();
11849 bool UsedAssumedInformation =
false;
11853 UsedAssumedInformation))
11854 return indicatePessimisticFixpoint();
11861 Values, S, UsedAssumedInformation))
11864 for (
auto &It :
Values) {
11865 Value *
V = It.getValue();
11866 std::optional<Value *> CallerV =
A.translateArgumentToCallSiteContent(
11867 V, *CB, *
this, UsedAssumedInformation);
11868 if (!CallerV.has_value()) {
11872 V = *CallerV ? *CallerV :
V;
11878 giveUpOnIntraprocedural(
A);
11881 addValue(
A, getState(), *V, CB, S, getAnchorScope());
11886 return indicatePessimisticFixpoint();
11888 return indicatePessimisticFixpoint();
11889 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
11890 : ChangeStatus::CHANGED;
11894 return AAPotentialValues::indicatePessimisticFixpoint();
11898 void trackStatistics()
const override {
11903struct AAPotentialValuesCallSiteArgument : AAPotentialValuesFloating {
11904 AAPotentialValuesCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
11905 : AAPotentialValuesFloating(IRP,
A) {}
11908 void trackStatistics()
const override {
11916struct AAAssumptionInfoImpl :
public AAAssumptionInfo {
11917 AAAssumptionInfoImpl(
const IRPosition &IRP, Attributor &
A,
11918 const DenseSet<StringRef> &
Known)
11919 : AAAssumptionInfo(IRP,
A,
Known) {}
11924 if (getKnown().isUniversal())
11925 return ChangeStatus::UNCHANGED;
11927 const IRPosition &IRP = getIRPosition();
11929 getAssumed().getSet().
end());
11931 return A.manifestAttrs(IRP,
11938 bool hasAssumption(
const StringRef Assumption)
const override {
11939 return isValidState() && setContains(Assumption);
11943 const std::string getAsStr(Attributor *
A)
const override {
11944 const SetContents &
Known = getKnown();
11945 const SetContents &Assumed = getAssumed();
11949 const std::string KnownStr =
llvm::join(Set,
",");
11951 std::string AssumedStr =
"Universal";
11952 if (!Assumed.isUniversal()) {
11953 Set.assign(Assumed.getSet().begin(), Assumed.getSet().end());
11956 return "Known [" + KnownStr +
"]," +
" Assumed [" + AssumedStr +
"]";
11971struct AAAssumptionInfoFunction final : AAAssumptionInfoImpl {
11972 AAAssumptionInfoFunction(
const IRPosition &IRP, Attributor &
A)
11973 : AAAssumptionInfoImpl(IRP,
A,
11980 auto CallSitePred = [&](AbstractCallSite ACS) {
11981 const auto *AssumptionAA =
A.getAAFor<AAAssumptionInfo>(
11983 DepClassTy::REQUIRED);
11987 Changed |= getIntersection(AssumptionAA->getAssumed());
11988 return !getAssumed().empty() || !getKnown().empty();
11991 bool UsedAssumedInformation =
false;
11996 if (!
A.checkForAllCallSites(CallSitePred, *
this,
true,
11997 UsedAssumedInformation))
11998 return indicatePessimisticFixpoint();
12000 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
12003 void trackStatistics()
const override {}
12007struct AAAssumptionInfoCallSite final : AAAssumptionInfoImpl {
12009 AAAssumptionInfoCallSite(
const IRPosition &IRP, Attributor &
A)
12010 : AAAssumptionInfoImpl(IRP,
A, getInitialAssumptions(IRP)) {}
12015 A.getAAFor<AAAssumptionInfo>(*
this, FnPos, DepClassTy::REQUIRED);
12021 auto *AssumptionAA =
12022 A.getAAFor<AAAssumptionInfo>(*
this, FnPos, DepClassTy::REQUIRED);
12024 return indicatePessimisticFixpoint();
12025 bool Changed = getIntersection(AssumptionAA->getAssumed());
12026 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
12030 void trackStatistics()
const override {}
12035 DenseSet<StringRef> getInitialAssumptions(
const IRPosition &IRP) {
12042 return Assumptions;
12057struct AAUnderlyingObjectsImpl
12063 const std::string getAsStr(
Attributor *
A)
const override {
12064 if (!isValidState())
12065 return "<invalid>";
12068 OS <<
"underlying objects: inter " << InterAssumedUnderlyingObjects.size()
12069 <<
" objects, intra " << IntraAssumedUnderlyingObjects.size()
12071 if (!InterAssumedUnderlyingObjects.empty()) {
12072 OS <<
"inter objects:\n";
12073 for (
auto *Obj : InterAssumedUnderlyingObjects)
12074 OS << *Obj <<
'\n';
12076 if (!IntraAssumedUnderlyingObjects.empty()) {
12077 OS <<
"intra objects:\n";
12078 for (
auto *Obj : IntraAssumedUnderlyingObjects)
12079 OS << *
Obj <<
'\n';
12085 void trackStatistics()
const override {}
12089 auto &Ptr = getAssociatedValue();
12091 bool UsedAssumedInformation =
false;
12092 auto DoUpdate = [&](SmallSetVector<Value *, 8> &UnderlyingObjects,
12094 SmallPtrSet<Value *, 8> SeenObjects;
12098 Scope, UsedAssumedInformation))
12099 return UnderlyingObjects.
insert(&Ptr);
12103 for (
unsigned I = 0;
I <
Values.size(); ++
I) {
12107 if (!SeenObjects.
insert(UO ? UO : Obj).second)
12109 if (UO && UO != Obj) {
12115 const auto *OtherAA =
A.getAAFor<AAUnderlyingObjects>(
12117 auto Pred = [&](
Value &
V) {
12121 Values.emplace_back(V,
nullptr);
12125 if (!OtherAA || !OtherAA->forallUnderlyingObjects(Pred, Scope))
12127 "The forall call should not return false at this position");
12133 Changed |= handleIndirect(
A, *Obj, UnderlyingObjects, Scope,
12134 UsedAssumedInformation);
12140 for (
unsigned u = 0, e =
PHI->getNumIncomingValues(); u < e; u++) {
12142 handleIndirect(
A, *
PHI->getIncomingValue(u), UnderlyingObjects,
12143 Scope, UsedAssumedInformation);
12157 if (!UsedAssumedInformation)
12158 indicateOptimisticFixpoint();
12159 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
12162 bool forallUnderlyingObjects(
12163 function_ref<
bool(
Value &)> Pred,
12165 if (!isValidState())
12166 return Pred(getAssociatedValue());
12169 ? IntraAssumedUnderlyingObjects
12170 : InterAssumedUnderlyingObjects;
12171 for (
Value *Obj : AssumedUnderlyingObjects)
12181 bool handleIndirect(Attributor &
A,
Value &V,
12182 SmallSetVector<Value *, 8> &UnderlyingObjects,
12185 const auto *AA =
A.getAAFor<AAUnderlyingObjects>(
12187 auto Pred = [&](
Value &
V) {
12191 if (!AA || !AA->forallUnderlyingObjects(Pred, Scope))
12193 "The forall call should not return false at this position");
12199 SmallSetVector<Value *, 8> IntraAssumedUnderlyingObjects;
12201 SmallSetVector<Value *, 8> InterAssumedUnderlyingObjects;
12204struct AAUnderlyingObjectsFloating final : AAUnderlyingObjectsImpl {
12205 AAUnderlyingObjectsFloating(
const IRPosition &IRP, Attributor &
A)
12206 : AAUnderlyingObjectsImpl(IRP,
A) {}
12209struct AAUnderlyingObjectsArgument final : AAUnderlyingObjectsImpl {
12210 AAUnderlyingObjectsArgument(
const IRPosition &IRP, Attributor &
A)
12211 : AAUnderlyingObjectsImpl(IRP,
A) {}
12214struct AAUnderlyingObjectsCallSite final : AAUnderlyingObjectsImpl {
12215 AAUnderlyingObjectsCallSite(
const IRPosition &IRP, Attributor &
A)
12216 : AAUnderlyingObjectsImpl(IRP,
A) {}
12219struct AAUnderlyingObjectsCallSiteArgument final : AAUnderlyingObjectsImpl {
12220 AAUnderlyingObjectsCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
12221 : AAUnderlyingObjectsImpl(IRP,
A) {}
12224struct AAUnderlyingObjectsReturned final : AAUnderlyingObjectsImpl {
12225 AAUnderlyingObjectsReturned(
const IRPosition &IRP, Attributor &
A)
12226 : AAUnderlyingObjectsImpl(IRP,
A) {}
12229struct AAUnderlyingObjectsCallSiteReturned final : AAUnderlyingObjectsImpl {
12230 AAUnderlyingObjectsCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
12231 : AAUnderlyingObjectsImpl(IRP,
A) {}
12234struct AAUnderlyingObjectsFunction final : AAUnderlyingObjectsImpl {
12235 AAUnderlyingObjectsFunction(
const IRPosition &IRP, Attributor &
A)
12236 : AAUnderlyingObjectsImpl(IRP,
A) {}
12242struct AAGlobalValueInfoFloating :
public AAGlobalValueInfo {
12243 AAGlobalValueInfoFloating(
const IRPosition &IRP, Attributor &
A)
12244 : AAGlobalValueInfo(IRP,
A) {}
12249 bool checkUse(Attributor &
A,
const Use &U,
bool &Follow,
12250 SmallVectorImpl<const Value *> &Worklist) {
12257 LLVM_DEBUG(
dbgs() <<
"[AAGlobalValueInfo] Check use: " << *
U.get() <<
" in "
12258 << *UInst <<
"\n");
12261 int Idx = &
Cmp->getOperandUse(0) == &
U;
12264 return U == &getAnchorValue();
12269 auto CallSitePred = [&](AbstractCallSite ACS) {
12270 Worklist.
push_back(ACS.getInstruction());
12273 bool UsedAssumedInformation =
false;
12275 if (!
A.checkForAllCallSites(CallSitePred, *UInst->
getFunction(),
12277 UsedAssumedInformation))
12295 if (!Fn || !
A.isFunctionIPOAmendable(*Fn))
12304 unsigned NumUsesBefore =
Uses.size();
12306 SmallPtrSet<const Value *, 8> Visited;
12310 auto UsePred = [&](
const Use &
U,
bool &Follow) ->
bool {
12318 return checkUse(
A, U, Follow, Worklist);
12320 auto EquivalentUseCB = [&](
const Use &OldU,
const Use &NewU) {
12321 Uses.insert(&OldU);
12325 while (!Worklist.
empty()) {
12327 if (!Visited.
insert(V).second)
12329 if (!
A.checkForAllUses(UsePred, *
this, *V,
12331 DepClassTy::OPTIONAL,
12332 true, EquivalentUseCB)) {
12333 return indicatePessimisticFixpoint();
12337 return Uses.size() == NumUsesBefore ? ChangeStatus::UNCHANGED
12338 : ChangeStatus::CHANGED;
12341 bool isPotentialUse(
const Use &U)
const override {
12342 return !isValidState() ||
Uses.contains(&U);
12347 return ChangeStatus::UNCHANGED;
12351 const std::string getAsStr(Attributor *
A)
const override {
12352 return "[" + std::to_string(
Uses.size()) +
" uses]";
12355 void trackStatistics()
const override {
12361 SmallPtrSet<const Use *, 8>
Uses;
12367struct AAIndirectCallInfoCallSite :
public AAIndirectCallInfo {
12368 AAIndirectCallInfoCallSite(
const IRPosition &IRP, Attributor &
A)
12369 : AAIndirectCallInfo(IRP,
A) {}
12373 auto *MD = getCtxI()->getMetadata(LLVMContext::MD_callees);
12374 if (!MD && !
A.isClosedWorldModule())
12378 for (
const auto &
Op : MD->operands())
12380 PotentialCallees.insert(Callee);
12381 }
else if (
A.isClosedWorldModule()) {
12383 A.getInfoCache().getIndirectlyCallableFunctions(
A);
12384 PotentialCallees.insert_range(IndirectlyCallableFunctions);
12387 if (PotentialCallees.empty())
12388 indicateOptimisticFixpoint();
12396 SmallSetVector<Function *, 4> AssumedCalleesNow;
12397 bool AllCalleesKnownNow = AllCalleesKnown;
12399 auto CheckPotentialCalleeUse = [&](
Function &PotentialCallee,
12400 bool &UsedAssumedInformation) {
12401 const auto *GIAA =
A.getAAFor<AAGlobalValueInfo>(
12403 if (!GIAA || GIAA->isPotentialUse(CalleeUse))
12405 UsedAssumedInformation = !GIAA->isAtFixpoint();
12409 auto AddPotentialCallees = [&]() {
12410 for (
auto *PotentialCallee : PotentialCallees) {
12411 bool UsedAssumedInformation =
false;
12412 if (CheckPotentialCalleeUse(*PotentialCallee, UsedAssumedInformation))
12413 AssumedCalleesNow.
insert(PotentialCallee);
12419 bool UsedAssumedInformation =
false;
12422 AA::ValueScope::AnyScope,
12423 UsedAssumedInformation)) {
12424 if (PotentialCallees.empty())
12425 return indicatePessimisticFixpoint();
12426 AddPotentialCallees();
12431 auto CheckPotentialCallee = [&](
Function &Fn) {
12432 if (!PotentialCallees.empty() && !PotentialCallees.count(&Fn))
12435 auto &CachedResult = FilterResults[&Fn];
12436 if (CachedResult.has_value())
12437 return CachedResult.value();
12439 bool UsedAssumedInformation =
false;
12440 if (!CheckPotentialCalleeUse(Fn, UsedAssumedInformation)) {
12441 if (!UsedAssumedInformation)
12442 CachedResult =
false;
12451 for (
int I = NumCBArgs;
I < NumFnArgs; ++
I) {
12452 bool IsKnown =
false;
12455 DepClassTy::OPTIONAL, IsKnown)) {
12457 CachedResult =
false;
12462 CachedResult =
true;
12468 for (
auto &VAC :
Values) {
12476 if (CheckPotentialCallee(*VACFn))
12477 AssumedCalleesNow.
insert(VACFn);
12480 if (!PotentialCallees.empty()) {
12481 AddPotentialCallees();
12484 AllCalleesKnownNow =
false;
12487 if (AssumedCalleesNow == AssumedCallees &&
12488 AllCalleesKnown == AllCalleesKnownNow)
12489 return ChangeStatus::UNCHANGED;
12491 std::swap(AssumedCallees, AssumedCalleesNow);
12492 AllCalleesKnown = AllCalleesKnownNow;
12493 return ChangeStatus::CHANGED;
12499 if (!AllCalleesKnown && AssumedCallees.empty())
12500 return ChangeStatus::UNCHANGED;
12503 bool UsedAssumedInformation =
false;
12504 if (
A.isAssumedDead(*CB,
this,
nullptr,
12505 UsedAssumedInformation))
12506 return ChangeStatus::UNCHANGED;
12511 if (
FP->getType()->getPointerAddressSpace() != ProgramAS)
12512 FP =
new AddrSpaceCastInst(
12513 FP, PointerType::get(
FP->getContext(), ProgramAS),
12514 FP->getName() +
".as" + Twine(ProgramAS), CB->
getIterator());
12523 if (AssumedCallees.empty()) {
12524 assert(AllCalleesKnown &&
12525 "Expected all callees to be known if there are none.");
12526 A.changeToUnreachableAfterManifest(CB);
12527 return ChangeStatus::CHANGED;
12531 if (AllCalleesKnown && AssumedCallees.size() == 1) {
12532 auto *NewCallee = AssumedCallees.front();
12535 NumIndirectCallsPromoted++;
12536 return ChangeStatus::CHANGED;
12543 A.deleteAfterManifest(*CB);
12544 return ChangeStatus::CHANGED;
12554 bool SpecializedForAnyCallees =
false;
12555 bool SpecializedForAllCallees = AllCalleesKnown;
12556 ICmpInst *LastCmp =
nullptr;
12559 for (
Function *NewCallee : AssumedCallees) {
12560 if (!
A.shouldSpecializeCallSiteForCallee(*
this, *CB, *NewCallee,
12561 AssumedCallees.size())) {
12562 SkippedAssumedCallees.
push_back(NewCallee);
12563 SpecializedForAllCallees =
false;
12566 SpecializedForAnyCallees =
true;
12572 A.registerManifestAddedBasicBlock(*ThenTI->
getParent());
12573 A.registerManifestAddedBasicBlock(*IP->getParent());
12579 A.registerManifestAddedBasicBlock(*ElseBB);
12581 SplitTI->replaceUsesOfWith(CBBB, ElseBB);
12586 CastInst *RetBC =
nullptr;
12587 CallInst *NewCall =
nullptr;
12592 NumIndirectCallsPromoted++;
12600 auto AttachCalleeMetadata = [&](CallBase &IndirectCB) {
12601 if (!AllCalleesKnown)
12602 return ChangeStatus::UNCHANGED;
12603 MDBuilder MDB(IndirectCB.getContext());
12604 MDNode *Callees = MDB.createCallees(SkippedAssumedCallees);
12605 IndirectCB.setMetadata(LLVMContext::MD_callees, Callees);
12606 return ChangeStatus::CHANGED;
12609 if (!SpecializedForAnyCallees)
12610 return AttachCalleeMetadata(*CB);
12613 if (SpecializedForAllCallees) {
12616 new UnreachableInst(IP->getContext(), IP);
12617 IP->eraseFromParent();
12620 CBClone->setName(CB->
getName());
12621 CBClone->insertBefore(*IP->getParent(), IP);
12622 NewCalls.
push_back({CBClone,
nullptr});
12623 AttachCalleeMetadata(*CBClone);
12630 CB->
getParent()->getFirstInsertionPt());
12631 for (
auto &It : NewCalls) {
12632 CallBase *NewCall = It.first;
12633 Instruction *CallRet = It.second ? It.second : It.first;
12645 A.deleteAfterManifest(*CB);
12646 Changed = ChangeStatus::CHANGED;
12652 const std::string getAsStr(Attributor *
A)
const override {
12653 return std::string(AllCalleesKnown ?
"eliminate" :
"specialize") +
12654 " indirect call site with " + std::to_string(AssumedCallees.size()) +
12658 void trackStatistics()
const override {
12659 if (AllCalleesKnown) {
12661 Eliminated, CallSites,
12662 "Number of indirect call sites eliminated via specialization")
12665 "Number of indirect call sites specialized")
12669 bool foreachCallee(function_ref<
bool(
Function *)> CB)
const override {
12670 return isValidState() && AllCalleesKnown &&
all_of(AssumedCallees, CB);
12675 DenseMap<Function *, std::optional<bool>> FilterResults;
12679 SmallSetVector<Function *, 4> PotentialCallees;
12683 SmallSetVector<Function *, 4> AssumedCallees;
12687 bool AllCalleesKnown =
true;
12694struct AAInvariantLoadPointerImpl
12695 :
public StateWrapper<BitIntegerState<uint8_t, 15>,
12696 AAInvariantLoadPointer> {
12700 IS_NOALIAS = 1 << 0,
12703 IS_NOEFFECT = 1 << 1,
12705 IS_LOCALLY_INVARIANT = 1 << 2,
12707 IS_LOCALLY_CONSTRAINED = 1 << 3,
12709 IS_BEST_STATE = IS_NOALIAS | IS_NOEFFECT | IS_LOCALLY_INVARIANT |
12710 IS_LOCALLY_CONSTRAINED,
12712 static_assert(getBestState() == IS_BEST_STATE,
"Unexpected best state");
12715 StateWrapper<BitIntegerState<uint8_t, 15>, AAInvariantLoadPointer>;
12719 AAInvariantLoadPointerImpl(
const IRPosition &IRP, Attributor &
A)
12722 bool isKnownInvariant()
const final {
12723 return isKnownLocallyInvariant() && isKnown(IS_LOCALLY_CONSTRAINED);
12726 bool isKnownLocallyInvariant()
const final {
12727 if (isKnown(IS_LOCALLY_INVARIANT))
12729 return isKnown(IS_NOALIAS | IS_NOEFFECT);
12732 bool isAssumedInvariant()
const final {
12733 return isAssumedLocallyInvariant() && isAssumed(IS_LOCALLY_CONSTRAINED);
12736 bool isAssumedLocallyInvariant()
const final {
12737 if (isAssumed(IS_LOCALLY_INVARIANT))
12739 return isAssumed(IS_NOALIAS | IS_NOEFFECT);
12746 if (requiresNoAlias() && !isAssumed(IS_NOALIAS))
12747 return indicatePessimisticFixpoint();
12751 Changed |= updateLocalInvariance(
A);
12757 if (!isKnownInvariant())
12758 return ChangeStatus::UNCHANGED;
12761 const Value *Ptr = &getAssociatedValue();
12762 const auto TagInvariantLoads = [&](
const Use &
U,
bool &) {
12763 if (
U.get() != Ptr)
12771 if (!
A.isRunOn(
I->getFunction()))
12774 if (
I->hasMetadata(LLVMContext::MD_invariant_load))
12778 LI->setMetadata(LLVMContext::MD_invariant_load,
12780 Changed = ChangeStatus::CHANGED;
12785 (void)
A.checkForAllUses(TagInvariantLoads, *
this, *Ptr);
12790 const std::string getAsStr(Attributor *)
const override {
12791 if (isKnownInvariant())
12792 return "load-invariant pointer";
12793 return "non-invariant pointer";
12797 void trackStatistics()
const override {}
12801 bool requiresNoAlias()
const {
12802 switch (getPositionKind()) {
12808 case IRP_CALL_SITE:
12810 case IRP_CALL_SITE_RETURNED: {
12815 case IRP_ARGUMENT: {
12816 const Function *
F = getAssociatedFunction();
12817 assert(
F &&
"no associated function for argument");
12823 bool isExternal()
const {
12824 const Function *
F = getAssociatedFunction();
12828 getPositionKind() != IRP_CALL_SITE_RETURNED;
12832 if (isKnown(IS_NOALIAS) || !isAssumed(IS_NOALIAS))
12833 return ChangeStatus::UNCHANGED;
12836 if (
const auto *ANoAlias =
A.getOrCreateAAFor<AANoAlias>(
12837 getIRPosition(),
this, DepClassTy::REQUIRED)) {
12838 if (ANoAlias->isKnownNoAlias()) {
12839 addKnownBits(IS_NOALIAS);
12840 return ChangeStatus::CHANGED;
12843 if (!ANoAlias->isAssumedNoAlias()) {
12844 removeAssumedBits(IS_NOALIAS);
12845 return ChangeStatus::CHANGED;
12848 return ChangeStatus::UNCHANGED;
12853 if (
const Argument *Arg = getAssociatedArgument()) {
12855 addKnownBits(IS_NOALIAS);
12856 return ChangeStatus::UNCHANGED;
12861 removeAssumedBits(IS_NOALIAS);
12862 return ChangeStatus::CHANGED;
12865 return ChangeStatus::UNCHANGED;
12869 if (isKnown(IS_NOEFFECT) || !isAssumed(IS_NOEFFECT))
12870 return ChangeStatus::UNCHANGED;
12872 if (!getAssociatedFunction())
12873 return indicatePessimisticFixpoint();
12876 return indicatePessimisticFixpoint();
12878 const auto HasNoEffectLoads = [&](
const Use &
U,
bool &) {
12880 return !LI || !LI->mayHaveSideEffects();
12882 if (!
A.checkForAllUses(HasNoEffectLoads, *
this, getAssociatedValue()))
12883 return indicatePessimisticFixpoint();
12885 if (
const auto *AMemoryBehavior =
A.getOrCreateAAFor<AAMemoryBehavior>(
12886 getIRPosition(),
this, DepClassTy::REQUIRED)) {
12889 if (!AMemoryBehavior->isAssumedReadOnly())
12890 return indicatePessimisticFixpoint();
12892 if (AMemoryBehavior->isKnownReadOnly()) {
12893 addKnownBits(IS_NOEFFECT);
12894 return ChangeStatus::UNCHANGED;
12897 return ChangeStatus::UNCHANGED;
12900 if (
const Argument *Arg = getAssociatedArgument()) {
12902 addKnownBits(IS_NOEFFECT);
12903 return ChangeStatus::UNCHANGED;
12908 return indicatePessimisticFixpoint();
12911 return ChangeStatus::UNCHANGED;
12915 if (isKnown(IS_LOCALLY_INVARIANT) || !isAssumed(IS_LOCALLY_INVARIANT))
12916 return ChangeStatus::UNCHANGED;
12919 const auto *AUO =
A.getOrCreateAAFor<AAUnderlyingObjects>(
12920 getIRPosition(),
this, DepClassTy::REQUIRED);
12922 return ChangeStatus::UNCHANGED;
12924 bool UsedAssumedInformation =
false;
12925 const auto IsLocallyInvariantLoadIfPointer = [&](
const Value &
V) {
12926 if (!
V.getType()->isPointerTy())
12928 const auto *IsInvariantLoadPointer =
12930 DepClassTy::REQUIRED);
12932 if (!IsInvariantLoadPointer)
12935 if (IsInvariantLoadPointer->isKnownLocallyInvariant())
12937 if (!IsInvariantLoadPointer->isAssumedLocallyInvariant())
12940 UsedAssumedInformation =
true;
12943 if (!AUO->forallUnderlyingObjects(IsLocallyInvariantLoadIfPointer))
12944 return indicatePessimisticFixpoint();
12950 if (!IsLocallyInvariantLoadIfPointer(*Arg))
12951 return indicatePessimisticFixpoint();
12956 if (!UsedAssumedInformation) {
12958 addKnownBits(IS_LOCALLY_INVARIANT);
12959 return ChangeStatus::CHANGED;
12962 return ChangeStatus::UNCHANGED;
12966struct AAInvariantLoadPointerFloating final : AAInvariantLoadPointerImpl {
12967 AAInvariantLoadPointerFloating(
const IRPosition &IRP, Attributor &
A)
12968 : AAInvariantLoadPointerImpl(IRP,
A) {}
12971struct AAInvariantLoadPointerReturned final : AAInvariantLoadPointerImpl {
12972 AAInvariantLoadPointerReturned(
const IRPosition &IRP, Attributor &
A)
12973 : AAInvariantLoadPointerImpl(IRP,
A) {}
12976 removeAssumedBits(IS_LOCALLY_CONSTRAINED);
12980struct AAInvariantLoadPointerCallSiteReturned final
12981 : AAInvariantLoadPointerImpl {
12982 AAInvariantLoadPointerCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
12983 : AAInvariantLoadPointerImpl(IRP,
A) {}
12986 const Function *
F = getAssociatedFunction();
12987 assert(
F &&
"no associated function for return from call");
12989 if (!
F->isDeclaration() && !
F->isIntrinsic())
12990 return AAInvariantLoadPointerImpl::initialize(
A);
12995 return AAInvariantLoadPointerImpl::initialize(
A);
12997 if (
F->onlyReadsMemory() &&
F->hasNoSync())
12998 return AAInvariantLoadPointerImpl::initialize(
A);
13002 indicatePessimisticFixpoint();
13006struct AAInvariantLoadPointerArgument final : AAInvariantLoadPointerImpl {
13007 AAInvariantLoadPointerArgument(
const IRPosition &IRP, Attributor &
A)
13008 : AAInvariantLoadPointerImpl(IRP,
A) {}
13011 const Function *
F = getAssociatedFunction();
13012 assert(
F &&
"no associated function for argument");
13015 addKnownBits(IS_LOCALLY_CONSTRAINED);
13019 if (!
F->hasLocalLinkage())
13020 removeAssumedBits(IS_LOCALLY_CONSTRAINED);
13024struct AAInvariantLoadPointerCallSiteArgument final
13025 : AAInvariantLoadPointerImpl {
13026 AAInvariantLoadPointerCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
13027 : AAInvariantLoadPointerImpl(IRP,
A) {}
13034template <
typename InstType>
13035static bool makeChange(Attributor &
A, InstType *MemInst,
const Use &U,
13036 Value *OriginalValue, PointerType *NewPtrTy,
13037 bool UseOriginalValue) {
13038 if (
U.getOperandNo() != InstType::getPointerOperandIndex())
13041 if (MemInst->isVolatile()) {
13042 auto *
TTI =
A.getInfoCache().getAnalysisResultForFunction<TargetIRAnalysis>(
13043 *MemInst->getFunction());
13044 unsigned NewAS = NewPtrTy->getPointerAddressSpace();
13049 if (UseOriginalValue) {
13050 A.changeUseAfterManifest(
const_cast<Use &
>(U), *OriginalValue);
13054 Instruction *CastInst =
new AddrSpaceCastInst(OriginalValue, NewPtrTy);
13056 A.changeUseAfterManifest(
const_cast<Use &
>(U), *CastInst);
13060struct AAAddressSpaceImpl :
public AAAddressSpace {
13061 AAAddressSpaceImpl(
const IRPosition &IRP, Attributor &
A)
13062 : AAAddressSpace(IRP,
A) {}
13065 assert(isValidState() &&
"the AA is invalid");
13066 return AssumedAddressSpace;
13071 assert(getAssociatedType()->isPtrOrPtrVectorTy() &&
13072 "Associated value is not a pointer");
13074 if (!
A.getInfoCache().getFlatAddressSpace().has_value()) {
13075 indicatePessimisticFixpoint();
13079 unsigned FlatAS =
A.getInfoCache().getFlatAddressSpace().value();
13080 unsigned AS = getAssociatedType()->getPointerAddressSpace();
13081 if (AS != FlatAS) {
13082 [[maybe_unused]]
bool R = takeAddressSpace(AS);
13083 assert(R &&
"The take should happen");
13084 indicateOptimisticFixpoint();
13089 uint32_t OldAddressSpace = AssumedAddressSpace;
13090 unsigned FlatAS =
A.getInfoCache().getFlatAddressSpace().value();
13092 auto CheckAddressSpace = [&](
Value &
Obj) {
13098 unsigned ObjAS =
Obj.getType()->getPointerAddressSpace();
13099 if (ObjAS != FlatAS)
13100 return takeAddressSpace(ObjAS);
13114 A.getInfoCache().getAnalysisResultForFunction<TargetIRAnalysis>(*F);
13116 if (AssumedAS != ~0U)
13117 return takeAddressSpace(AssumedAS);
13121 return takeAddressSpace(FlatAS);
13124 auto *AUO =
A.getOrCreateAAFor<AAUnderlyingObjects>(getIRPosition(),
this,
13125 DepClassTy::REQUIRED);
13126 if (!AUO->forallUnderlyingObjects(CheckAddressSpace))
13127 return indicatePessimisticFixpoint();
13129 return OldAddressSpace == AssumedAddressSpace ? ChangeStatus::UNCHANGED
13130 : ChangeStatus::CHANGED;
13137 if (NewAS == InvalidAddressSpace ||
13139 return ChangeStatus::UNCHANGED;
13141 unsigned FlatAS =
A.getInfoCache().getFlatAddressSpace().value();
13143 Value *AssociatedValue = &getAssociatedValue();
13144 Value *OriginalValue = peelAddrspacecast(AssociatedValue, FlatAS);
13147 PointerType::get(getAssociatedType()->
getContext(), NewAS);
13148 bool UseOriginalValue =
13153 auto Pred = [&](
const Use &
U,
bool &) {
13154 if (
U.get() != AssociatedValue)
13165 makeChange(
A, LI, U, OriginalValue, NewPtrTy, UseOriginalValue);
13168 makeChange(
A, SI, U, OriginalValue, NewPtrTy, UseOriginalValue);
13171 makeChange(
A, RMW, U, OriginalValue, NewPtrTy, UseOriginalValue);
13174 makeChange(
A, CmpX, U, OriginalValue, NewPtrTy, UseOriginalValue);
13181 (void)
A.checkForAllUses(Pred, *
this, getAssociatedValue(),
13184 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
13188 const std::string getAsStr(Attributor *
A)
const override {
13189 if (!isValidState())
13190 return "addrspace(<invalid>)";
13191 return "addrspace(" +
13192 (AssumedAddressSpace == InvalidAddressSpace
13194 : std::to_string(AssumedAddressSpace)) +
13199 uint32_t AssumedAddressSpace = InvalidAddressSpace;
13201 bool takeAddressSpace(uint32_t AS) {
13202 if (AssumedAddressSpace == InvalidAddressSpace) {
13203 AssumedAddressSpace = AS;
13206 return AssumedAddressSpace == AS;
13209 static Value *peelAddrspacecast(
Value *V,
unsigned FlatAS) {
13211 assert(
I->getSrcAddressSpace() != FlatAS &&
13212 "there should not be flat AS -> non-flat AS");
13213 return I->getPointerOperand();
13216 if (
C->getOpcode() == Instruction::AddrSpaceCast) {
13217 assert(
C->getOperand(0)->getType()->getPointerAddressSpace() !=
13219 "there should not be flat AS -> non-flat AS X");
13220 return C->getOperand(0);
13226struct AAAddressSpaceFloating final : AAAddressSpaceImpl {
13227 AAAddressSpaceFloating(
const IRPosition &IRP, Attributor &
A)
13228 : AAAddressSpaceImpl(IRP,
A) {}
13230 void trackStatistics()
const override {
13235struct AAAddressSpaceReturned final : AAAddressSpaceImpl {
13236 AAAddressSpaceReturned(
const IRPosition &IRP, Attributor &
A)
13237 : AAAddressSpaceImpl(IRP,
A) {}
13243 (void)indicatePessimisticFixpoint();
13246 void trackStatistics()
const override {
13251struct AAAddressSpaceCallSiteReturned final : AAAddressSpaceImpl {
13252 AAAddressSpaceCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
13253 : AAAddressSpaceImpl(IRP,
A) {}
13255 void trackStatistics()
const override {
13260struct AAAddressSpaceArgument final : AAAddressSpaceImpl {
13261 AAAddressSpaceArgument(
const IRPosition &IRP, Attributor &
A)
13262 : AAAddressSpaceImpl(IRP,
A) {}
13267struct AAAddressSpaceCallSiteArgument final : AAAddressSpaceImpl {
13268 AAAddressSpaceCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
13269 : AAAddressSpaceImpl(IRP,
A) {}
13275 (void)indicatePessimisticFixpoint();
13278 void trackStatistics()
const override {
13293struct AANoAliasAddrSpaceImpl :
public AANoAliasAddrSpace {
13294 AANoAliasAddrSpaceImpl(
const IRPosition &IRP, Attributor &
A)
13295 : AANoAliasAddrSpace(IRP,
A) {}
13298 assert(getAssociatedType()->isPtrOrPtrVectorTy() &&
13299 "Associated value is not a pointer");
13303 std::optional<unsigned> FlatAS =
A.getInfoCache().getFlatAddressSpace();
13304 if (!FlatAS.has_value()) {
13305 indicatePessimisticFixpoint();
13311 unsigned AS = getAssociatedType()->getPointerAddressSpace();
13312 if (AS != *FlatAS) {
13314 indicateOptimisticFixpoint();
13319 unsigned FlatAS =
A.getInfoCache().getFlatAddressSpace().value();
13320 uint32_t OldAssumed = getAssumed();
13322 auto CheckAddressSpace = [&](
Value &
Obj) {
13326 unsigned AS =
Obj.getType()->getPointerAddressSpace();
13330 removeAS(
Obj.getType()->getPointerAddressSpace());
13334 const AAUnderlyingObjects *AUO =
A.getOrCreateAAFor<AAUnderlyingObjects>(
13335 getIRPosition(),
this, DepClassTy::REQUIRED);
13337 return indicatePessimisticFixpoint();
13339 return OldAssumed == getAssumed() ? ChangeStatus::UNCHANGED
13340 : ChangeStatus::CHANGED;
13345 unsigned FlatAS =
A.getInfoCache().getFlatAddressSpace().value();
13347 unsigned AS = getAssociatedType()->getPointerAddressSpace();
13348 if (AS != FlatAS ||
Map.empty())
13349 return ChangeStatus::UNCHANGED;
13351 LLVMContext &Ctx = getAssociatedValue().getContext();
13352 MDNode *NoAliasASNode =
nullptr;
13353 MDBuilder MDB(Ctx);
13355 for (RangeMap::const_iterator
I =
Map.begin();
I !=
Map.end();
I++) {
13358 unsigned Upper =
I.stop();
13359 unsigned Lower =
I.start();
13360 if (!NoAliasASNode) {
13361 NoAliasASNode = MDB.createRange(APInt(32,
Lower), APInt(32,
Upper + 1));
13364 MDNode *ASRange = MDB.createRange(APInt(32,
Lower), APInt(32,
Upper + 1));
13368 Value *AssociatedValue = &getAssociatedValue();
13371 auto AddNoAliasAttr = [&](
const Use &
U,
bool &) {
13372 if (
U.get() != AssociatedValue)
13375 if (!Inst || Inst->
hasMetadata(LLVMContext::MD_noalias_addrspace))
13382 Inst->
setMetadata(LLVMContext::MD_noalias_addrspace, NoAliasASNode);
13386 (void)
A.checkForAllUses(AddNoAliasAttr, *
this, *AssociatedValue,
13388 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
13392 const std::string getAsStr(Attributor *
A)
const override {
13393 if (!isValidState())
13394 return "<invalid>";
13396 raw_string_ostream OS(Str);
13397 OS <<
"CanNotBeAddrSpace(";
13398 for (RangeMap::const_iterator
I =
Map.begin();
I !=
Map.end();
I++) {
13399 unsigned Upper =
I.stop();
13400 unsigned Lower =
I.start();
13401 OS <<
' ' <<
'[' <<
Upper <<
',' <<
Lower + 1 <<
')';
13408 void removeAS(
unsigned AS) {
13409 RangeMap::iterator
I =
Map.find(AS);
13411 if (
I !=
Map.end()) {
13412 unsigned Upper =
I.stop();
13413 unsigned Lower =
I.start();
13417 if (AS != ~((
unsigned)0) && AS + 1 <=
Upper)
13419 if (AS != 0 &&
Lower <= AS - 1)
13424 void resetASRanges(Attributor &
A) {
13426 Map.insert(0,
A.getInfoCache().getMaxAddrSpace(),
true);
13430struct AANoAliasAddrSpaceFloating final : AANoAliasAddrSpaceImpl {
13431 AANoAliasAddrSpaceFloating(
const IRPosition &IRP, Attributor &
A)
13432 : AANoAliasAddrSpaceImpl(IRP,
A) {}
13434 void trackStatistics()
const override {
13439struct AANoAliasAddrSpaceReturned final : AANoAliasAddrSpaceImpl {
13440 AANoAliasAddrSpaceReturned(
const IRPosition &IRP, Attributor &
A)
13441 : AANoAliasAddrSpaceImpl(IRP,
A) {}
13443 void trackStatistics()
const override {
13448struct AANoAliasAddrSpaceCallSiteReturned final : AANoAliasAddrSpaceImpl {
13449 AANoAliasAddrSpaceCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
13450 : AANoAliasAddrSpaceImpl(IRP,
A) {}
13452 void trackStatistics()
const override {
13457struct AANoAliasAddrSpaceArgument final : AANoAliasAddrSpaceImpl {
13458 AANoAliasAddrSpaceArgument(
const IRPosition &IRP, Attributor &
A)
13459 : AANoAliasAddrSpaceImpl(IRP,
A) {}
13461 void trackStatistics()
const override {
13466struct AANoAliasAddrSpaceCallSiteArgument final : AANoAliasAddrSpaceImpl {
13467 AANoAliasAddrSpaceCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
13468 : AANoAliasAddrSpaceImpl(IRP,
A) {}
13470 void trackStatistics()
const override {
13477struct AAAllocationInfoImpl :
public AAAllocationInfo {
13478 AAAllocationInfoImpl(
const IRPosition &IRP, Attributor &
A)
13479 : AAAllocationInfo(IRP,
A) {}
13481 std::optional<TypeSize> getAllocatedSize()
const override {
13482 assert(isValidState() &&
"the AA is invalid");
13483 return AssumedAllocatedSize;
13486 std::optional<TypeSize> findInitialAllocationSize(Instruction *
I,
13487 const DataLayout &
DL) {
13490 switch (
I->getOpcode()) {
13491 case Instruction::Alloca: {
13496 return std::nullopt;
13502 const IRPosition &IRP = getIRPosition();
13507 return indicatePessimisticFixpoint();
13509 bool IsKnownNoCapture;
13511 A,
this, IRP, DepClassTy::OPTIONAL, IsKnownNoCapture))
13512 return indicatePessimisticFixpoint();
13514 const AAPointerInfo *PI =
13515 A.getOrCreateAAFor<AAPointerInfo>(IRP, *
this, DepClassTy::REQUIRED);
13518 return indicatePessimisticFixpoint();
13521 return indicatePessimisticFixpoint();
13523 const DataLayout &
DL =
A.getDataLayout();
13524 const auto AllocationSize = findInitialAllocationSize(
I,
DL);
13527 if (!AllocationSize)
13528 return indicatePessimisticFixpoint();
13532 if (*AllocationSize == 0)
13533 return indicatePessimisticFixpoint();
13539 return indicatePessimisticFixpoint();
13541 if (BinSize == 0) {
13542 auto NewAllocationSize = std::make_optional<TypeSize>(0,
false);
13543 if (!changeAllocationSize(NewAllocationSize))
13544 return ChangeStatus::UNCHANGED;
13545 return ChangeStatus::CHANGED;
13549 const auto &It = PI->
begin();
13552 if (It->first.Offset != 0)
13553 return indicatePessimisticFixpoint();
13555 uint64_t SizeOfBin = It->first.Offset + It->first.Size;
13557 if (SizeOfBin >= *AllocationSize)
13558 return indicatePessimisticFixpoint();
13560 auto NewAllocationSize = std::make_optional<TypeSize>(SizeOfBin * 8,
false);
13562 if (!changeAllocationSize(NewAllocationSize))
13563 return ChangeStatus::UNCHANGED;
13565 return ChangeStatus::CHANGED;
13571 assert(isValidState() &&
13572 "Manifest should only be called if the state is valid.");
13576 auto FixedAllocatedSizeInBits = getAllocatedSize()->getFixedValue();
13578 unsigned long NumBytesToAllocate = (FixedAllocatedSizeInBits + 7) / 8;
13580 switch (
I->getOpcode()) {
13582 case Instruction::Alloca: {
13586 Type *CharType = Type::getInt8Ty(
I->getContext());
13588 auto *NumBytesToValue =
13589 ConstantInt::get(
I->getContext(), APInt(32, NumBytesToAllocate));
13592 insertPt = std::next(insertPt);
13593 AllocaInst *NewAllocaInst =
13598 return ChangeStatus::CHANGED;
13606 return ChangeStatus::UNCHANGED;
13610 const std::string getAsStr(Attributor *
A)
const override {
13611 if (!isValidState())
13612 return "allocationinfo(<invalid>)";
13613 return "allocationinfo(" +
13614 (AssumedAllocatedSize == HasNoAllocationSize
13616 : std::to_string(AssumedAllocatedSize->getFixedValue())) +
13621 std::optional<TypeSize> AssumedAllocatedSize = HasNoAllocationSize;
13625 bool changeAllocationSize(std::optional<TypeSize>
Size) {
13626 if (AssumedAllocatedSize == HasNoAllocationSize ||
13627 AssumedAllocatedSize !=
Size) {
13628 AssumedAllocatedSize =
Size;
13635struct AAAllocationInfoFloating : AAAllocationInfoImpl {
13636 AAAllocationInfoFloating(
const IRPosition &IRP, Attributor &
A)
13637 : AAAllocationInfoImpl(IRP,
A) {}
13639 void trackStatistics()
const override {
13644struct AAAllocationInfoReturned : AAAllocationInfoImpl {
13645 AAAllocationInfoReturned(
const IRPosition &IRP, Attributor &
A)
13646 : AAAllocationInfoImpl(IRP,
A) {}
13652 (void)indicatePessimisticFixpoint();
13655 void trackStatistics()
const override {
13660struct AAAllocationInfoCallSiteReturned : AAAllocationInfoImpl {
13661 AAAllocationInfoCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
13662 : AAAllocationInfoImpl(IRP,
A) {}
13664 void trackStatistics()
const override {
13669struct AAAllocationInfoArgument : AAAllocationInfoImpl {
13670 AAAllocationInfoArgument(
const IRPosition &IRP, Attributor &
A)
13671 : AAAllocationInfoImpl(IRP,
A) {}
13673 void trackStatistics()
const override {
13678struct AAAllocationInfoCallSiteArgument : AAAllocationInfoImpl {
13679 AAAllocationInfoCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
13680 : AAAllocationInfoImpl(IRP,
A) {}
13685 (void)indicatePessimisticFixpoint();
13688 void trackStatistics()
const override {
13737#define SWITCH_PK_INV(CLASS, PK, POS_NAME) \
13738 case IRPosition::PK: \
13739 llvm_unreachable("Cannot create " #CLASS " for a " POS_NAME " position!");
13741#define SWITCH_PK_CREATE(CLASS, IRP, PK, SUFFIX) \
13742 case IRPosition::PK: \
13743 AA = new (A.Allocator) CLASS##SUFFIX(IRP, A); \
13747#define CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13748 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13749 CLASS *AA = nullptr; \
13750 switch (IRP.getPositionKind()) { \
13751 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13752 SWITCH_PK_INV(CLASS, IRP_FLOAT, "floating") \
13753 SWITCH_PK_INV(CLASS, IRP_ARGUMENT, "argument") \
13754 SWITCH_PK_INV(CLASS, IRP_RETURNED, "returned") \
13755 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_RETURNED, "call site returned") \
13756 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_ARGUMENT, "call site argument") \
13757 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
13758 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE, CallSite) \
13763#define CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13764 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13765 CLASS *AA = nullptr; \
13766 switch (IRP.getPositionKind()) { \
13767 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13768 SWITCH_PK_INV(CLASS, IRP_FUNCTION, "function") \
13769 SWITCH_PK_INV(CLASS, IRP_CALL_SITE, "call site") \
13770 SWITCH_PK_CREATE(CLASS, IRP, IRP_FLOAT, Floating) \
13771 SWITCH_PK_CREATE(CLASS, IRP, IRP_ARGUMENT, Argument) \
13772 SWITCH_PK_CREATE(CLASS, IRP, IRP_RETURNED, Returned) \
13773 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_RETURNED, CallSiteReturned) \
13774 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_ARGUMENT, CallSiteArgument) \
13779#define CREATE_ABSTRACT_ATTRIBUTE_FOR_ONE_POSITION(POS, SUFFIX, CLASS) \
13780 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13781 CLASS *AA = nullptr; \
13782 switch (IRP.getPositionKind()) { \
13783 SWITCH_PK_CREATE(CLASS, IRP, POS, SUFFIX) \
13785 llvm_unreachable("Cannot create " #CLASS " for position otherthan " #POS \
13791#define CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13792 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13793 CLASS *AA = nullptr; \
13794 switch (IRP.getPositionKind()) { \
13795 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13796 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
13797 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE, CallSite) \
13798 SWITCH_PK_CREATE(CLASS, IRP, IRP_FLOAT, Floating) \
13799 SWITCH_PK_CREATE(CLASS, IRP, IRP_ARGUMENT, Argument) \
13800 SWITCH_PK_CREATE(CLASS, IRP, IRP_RETURNED, Returned) \
13801 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_RETURNED, CallSiteReturned) \
13802 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_ARGUMENT, CallSiteArgument) \
13807#define CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13808 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13809 CLASS *AA = nullptr; \
13810 switch (IRP.getPositionKind()) { \
13811 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13812 SWITCH_PK_INV(CLASS, IRP_ARGUMENT, "argument") \
13813 SWITCH_PK_INV(CLASS, IRP_FLOAT, "floating") \
13814 SWITCH_PK_INV(CLASS, IRP_RETURNED, "returned") \
13815 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_RETURNED, "call site returned") \
13816 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_ARGUMENT, "call site argument") \
13817 SWITCH_PK_INV(CLASS, IRP_CALL_SITE, "call site") \
13818 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
13823#define CREATE_NON_RET_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13824 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13825 CLASS *AA = nullptr; \
13826 switch (IRP.getPositionKind()) { \
13827 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13828 SWITCH_PK_INV(CLASS, IRP_RETURNED, "returned") \
13829 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
13830 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE, CallSite) \
13831 SWITCH_PK_CREATE(CLASS, IRP, IRP_FLOAT, Floating) \
13832 SWITCH_PK_CREATE(CLASS, IRP, IRP_ARGUMENT, Argument) \
13833 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_RETURNED, CallSiteReturned) \
13834 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_ARGUMENT, CallSiteArgument) \
13886#undef CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION
13887#undef CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION
13888#undef CREATE_NON_RET_ABSTRACT_ATTRIBUTE_FOR_POSITION
13889#undef CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION
13890#undef CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION
13891#undef CREATE_ABSTRACT_ATTRIBUTE_FOR_ONE_POSITION
13892#undef SWITCH_PK_CREATE
13893#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
iterator find(const_arg_type_t< KeyT > Val)
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
bool contains(const_arg_type_t< KeyT > Val) const
Return true if the specified key is in the map, false otherwise.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Analysis pass which computes a DominatorTree.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
LLVM_ABI bool dominates(const BasicBlock *BB, const Use &U) const
Return true if the (end of the) basic block BB dominates the use U.
const BasicBlock & getEntryBlock() const
iterator_range< arg_iterator > args()
const Function & getFunction() const
Argument * getArg(unsigned i) const
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
BlockT * getHeader(CycleRef C) const
CycleRef getCycle(const BlockT *Block) const
Find the innermost cycle containing Block.
LLVM_ABI bool isDeclaration() const
Return true if the primary definition of this global value is outside of the current translation unit...
bool hasLocalLinkage() const
static LLVM_ABI bool compare(const APInt &LHS, const APInt &RHS, ICmpInst::Predicate Pred)
Return result of LHS Pred RHS comparison.
Value * CreatePtrAdd(Value *Ptr, Value *Offset, const Twine &Name="", GEPNoWrapFlags NW=GEPNoWrapFlags::none())
ConstantInt * getInt64(uint64_t C)
Get a constant 64-bit value.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
LLVM_ABI Instruction * clone() const
Create a copy of 'this' instruction that is identical in all ways except the following:
LLVM_ABI bool isLifetimeStartOrEnd() const LLVM_READONLY
Return true if the instruction is a llvm.lifetime.start or llvm.lifetime.end marker.
bool mayReadOrWriteMemory() const
Return true if this instruction may read or write memory.
LLVM_ABI bool mayWriteToMemory() const LLVM_READONLY
Return true if this instruction may modify memory.
bool hasMetadata() const
Return true if this instruction has any metadata attached to it.
LLVM_ABI void insertBefore(InstListType::iterator InsertPos)
Insert an unlinked instruction into a basic block immediately before the specified position.
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
LLVM_ABI const Function * getFunction() const
Return the function this instruction belongs to.
LLVM_ABI BasicBlock * getSuccessor(unsigned Idx) const LLVM_READONLY
Return the specified successor. This instruction must be a terminator.
LLVM_ABI bool mayHaveSideEffects() const LLVM_READONLY
Return true if the instruction may have side effects.
bool isTerminator() const
LLVM_ABI bool mayReadFromMemory() const LLVM_READONLY
Return true if this instruction may read memory.
iterator_range< user_iterator > users()
LLVM_ABI void setMetadata(unsigned KindID, MDNode *Node)
Set the metadata of the specified kind to the specified node.
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
This is an important class for using LLVM in a threaded context.
LLVM_ABI ConstantRange getConstantRange(Value *V, Instruction *CxtI, bool UndefAllowed)
Return the ConstantRange constraint that is known to hold for the specified value at the specified in...
LoopT * getLoopFor(const BlockT *BB) const
Return the inner most loop that BB lives in.
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
static LLVM_ABI MDNode * getMostGenericRange(MDNode *A, MDNode *B)
static MemoryEffectsBase readOnly()
bool doesNotAccessMemory() const
Whether this function accesses no memory.
static MemoryEffectsBase argMemOnly(ModRefInfo MR=ModRefInfo::ModRef)
static MemoryEffectsBase inaccessibleMemOnly(ModRefInfo MR=ModRefInfo::ModRef)
bool onlyAccessesInaccessibleMem() const
Whether this function only (at most) accesses inaccessible memory.
ModRefInfo getModRef(Location Loc) const
Get ModRefInfo for the given Location.
bool onlyAccessesArgPointees() const
Whether this function only (at most) accesses argument memory.
bool onlyReadsMemory() const
Whether this function only (at most) reads memory.
static MemoryEffectsBase writeOnly()
static MemoryEffectsBase inaccessibleOrArgMemOnly(ModRefInfo MR=ModRefInfo::ModRef)
static MemoryEffectsBase none()
bool onlyAccessesInaccessibleOrArgMem() const
Whether this function only (at most) accesses argument and inaccessible memory.
static MemoryEffectsBase unknown()
static LLVM_ABI std::optional< MemoryLocation > getOrNone(const Instruction *Inst)
static SizeOffsetValue unknown()
static PHINode * Create(Type *Ty, unsigned NumReservedValues, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
Constructors - NumReservedValues is a hint for the number of incoming edges that this phi node will h...
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
Value * getReturnValue() const
Convenience accessor. Returns null if there is no return value.
LLVM_ABI 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)
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.
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
InterleavedRange< Range > interleaved_array(const Range &R, StringRef Separator=", ")
Output range R as an array of interleaved elements.
ChangeStatus clampStateAndIndicateChange< DerefState >(DerefState &S, const DerefState &R)
void RemapInstruction(Instruction *I, ValueToValueMapTy &VM, RemapFlags Flags=RF_None, ValueMapTypeRemapper *TypeMapper=nullptr, ValueMaterializer *Materializer=nullptr, const MetadataPredicate *IdentityMD=nullptr)
Convert the instruction operands from referencing the current values into those specified by VM.
LLVM_ABI bool isIntrinsicReturningPointerAliasingArgumentWithoutCapturing(const CallBase *Call, bool MustPreserveOffset, bool MustPreserveProvenance=false)
{launder,strip}.invariant.group returns pointer that aliases its argument, and it only captures point...
DWARFExpression::Operation Op
LLVM_ABI bool isGuaranteedNotToBeUndefOrPoison(const Value *V, AssumptionCache *AC=nullptr, const Instruction *CtxI=nullptr, const DominatorTree *DT=nullptr, unsigned Depth=0)
Return true if this function can prove that V does not have undef bits and is never poison.
ArrayRef(const T &OneElt) -> ArrayRef< T >
LLVM_ABI Value * getFreedOperand(const CallBase *CB, const TargetLibraryInfo *TLI)
If this if a call to a free function, return the freed operand.
ChangeStatus clampStateAndIndicateChange(StateType &S, const StateType &R)
Helper function to clamp a state S of type StateType with the information in R and indicate/return if...
constexpr unsigned BitWidth
ValueMap< const Value *, WeakTrackingVH > ValueToValueMapTy
auto pred_begin(const MachineBasicBlock *BB)
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
iterator_range< pointer_iterator< WrappedIteratorT > > make_pointer_range(RangeT &&Range)
LLVM_ABI std::optional< APInt > getAllocSize(const CallBase *CB, const TargetLibraryInfo *TLI, function_ref< const Value *(const Value *)> Mapper=[](const Value *V) { return V;})
Return the size of the requested allocation.
LLVM_ABI DenseSet< StringRef > getAssumptions(const Function &F)
Return the set of all assumptions for the function F.
Align assumeAligned(uint64_t Value)
Treats the value 0 as a 1, so Align is always at least 1.
LLVM_ABI Instruction * SplitBlockAndInsertIfThen(Value *Cond, BasicBlock::iterator SplitBefore, bool Unreachable, MDNode *BranchWeights=nullptr, DomTreeUpdater *DTU=nullptr, LoopInfo *LI=nullptr, BasicBlock *ThenBlock=nullptr)
Split the containing block at the specified instruction - everything before SplitBefore stays in the ...
@ OPTIONAL
The target may be valid if the source is not.
@ NONE
Do not track a dependence between source and target.
@ REQUIRED
The target cannot be valid if the source is not.
LLVM_ABI UseCaptureInfo DetermineUseCaptureKind(const Use &U, const Value *Base)
Determine what kind of capture behaviour U may exhibit.
LLVM_ABI Value * simplifyCmpInst(CmpPredicate Predicate, Value *LHS, Value *RHS, const SimplifyQuery &Q)
Given operands for a CmpInst, fold the result or return null.
LLVM_ABI bool mayContainIrreducibleControl(const Function &F, const LoopInfo *LI)
BumpPtrAllocatorImpl<> BumpPtrAllocator
The standard BumpPtrAllocator which just uses the default template parameters.
T bit_floor(T Value)
Returns the largest integral power of two no greater than Value if Value is nonzero.
bool capturesNothing(CaptureComponents CC)
LLVM_ABI bool isIdentifiedObject(const Value *V)
Return true if this pointer refers to a distinct and identifiable object.
bool capturesAnyProvenance(CaptureComponents CC)
constexpr StringRef AssumptionAttrKey
The key we use for assumption attributes.
constexpr bool isCallableCC(CallingConv::ID CC)
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
A type to track pointer/struct usage and accesses for AAPointerInfo.
bool forallInterferingAccesses(AA::RangeTy Range, F CB) const
See AAPointerInfo::forallInterferingAccesses.
AAPointerInfo::const_bin_iterator end() const
ChangeStatus addAccess(Attributor &A, const AAPointerInfo::RangeList &Ranges, Instruction &I, std::optional< Value * > Content, AAPointerInfo::AccessKind Kind, Type *Ty, Instruction *RemoteI=nullptr)
Add a new Access to the state at offset Offset and with size Size.
DenseMap< const Instruction *, SmallVector< unsigned > > RemoteIMap
AAPointerInfo::const_bin_iterator begin() const
AAPointerInfo::OffsetInfo ReturnedOffsets
Flag to determine if the underlying pointer is reaching a return statement in the associated function...
State & operator=(State &&R)
State(State &&SIS)=default
const AAPointerInfo::Access & getAccess(unsigned Index) const
SmallVector< AAPointerInfo::Access > AccessList
bool isAtFixpoint() const override
See AbstractState::isAtFixpoint().
bool forallInterferingAccesses(Instruction &I, F CB, AA::RangeTy &Range) const
See AAPointerInfo::forallInterferingAccesses.
static State getWorstState(const State &SIS)
Return the worst possible representable state.
int64_t numOffsetBins() const
AAPointerInfo::OffsetBinsTy OffsetBins
ChangeStatus indicateOptimisticFixpoint() override
See AbstractState::indicateOptimisticFixpoint().
State & operator=(const State &R)
ChangeStatus indicatePessimisticFixpoint() override
See AbstractState::indicatePessimisticFixpoint().
const State & getAssumed() const
static State getBestState(const State &SIS)
Return the best possible representable state.
bool isValidState() const override
See AbstractState::isValidState().
----------------—AAIntraFnReachability Attribute-----------------------—
ReachabilityQueryInfo(const ReachabilityQueryInfo &RQI)
unsigned Hash
Precomputed hash for this RQI.
const Instruction * From
Start here,.
Reachable Result
and remember if it worked:
ReachabilityQueryInfo(const Instruction *From, const ToTy *To)
ReachabilityQueryInfo(Attributor &A, const Instruction &From, const ToTy &To, const AA::InstExclusionSetTy *ES, bool MakeUnique)
Constructor replacement to ensure unique and stable sets are used for the cache.
const ToTy * To
reach this place,
const AA::InstExclusionSetTy * ExclusionSet
without going through any of these instructions,
unsigned computeHashValue() const
An abstract interface for address space information.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for all align attributes.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
Align getKnownAlign() const
Return known alignment.
static LLVM_ABI const char ID
An abstract attribute for getting assumption information.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract state for querying live call edges.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract Attribute for specializing "dynamic" components of denormal_fpenv to a known denormal mod...
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for all dereferenceable attribute.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for llvm::GlobalValue information interference.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for indirect call information interference.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface to track if a value leaves it's defining function instance.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract Attribute for computing reachability between functions.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
bool canReach(Attributor &A, const Function &Fn) const
If the function represented by this possition can reach Fn.
virtual bool instructionCanReach(Attributor &A, const Instruction &Inst, const Function &Fn, const AA::InstExclusionSetTy *ExclusionSet=nullptr) const =0
Can Inst reach Fn.
An abstract interface to determine reachability of point A to B.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for identifying pointers from which loads can be marked invariant.
static LLVM_ABI const char ID
Unique ID (due to the unique address).
An abstract interface for liveness abstract attribute.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for memory access kind related attributes (readnone/readonly/writeonly).
bool isAssumedReadOnly() const
Return true if we assume that the underlying value is not accessed (=written) in its respective scope...
bool isKnownReadNone() const
Return true if we know that the underlying value is not read or accessed in its respective scope.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
bool isAssumedReadNone() const
Return true if we assume that the underlying value is not read or accessed in its respective scope.
An abstract interface for all memory location attributes (readnone/argmemonly/inaccessiblememonly/ina...
static LLVM_ABI std::string getMemoryLocationsAsStr(MemoryLocationsKind MLK)
Return the locations encoded by MLK as a readable string.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
StateType::base_t MemoryLocationsKind
An abstract interface for all nonnull attributes.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for potential address space information.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for all noalias attributes.
static LLVM_ABI bool isImpliedByIR(Attributor &A, const IRPosition &IRP, Attribute::AttrKind ImpliedAttributeKind, bool IgnoreSubsumingPositions=false)
See IRAttribute::isImpliedByIR.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for all nocapture attributes.
@ NO_CAPTURE_MAYBE_RETURNED
If we do not capture the value in memory or through integers we can only communicate it back as a der...
@ NO_CAPTURE
If we do not capture the value in memory, through integers, or as a derived pointer we know it is not...
static LLVM_ABI const char ID
Unique ID (due to the unique address)
bool isAssumedNoCaptureMaybeReturned() const
Return true if we assume that the underlying value is not captured in its respective scope but we all...
static LLVM_ABI bool isImpliedByIR(Attributor &A, const IRPosition &IRP, Attribute::AttrKind ImpliedAttributeKind, bool IgnoreSubsumingPositions=false)
See IRAttribute::isImpliedByIR.
static LLVM_ABI void determineFunctionCaptureCapabilities(const IRPosition &IRP, const Function &F, BitIntegerState &State)
Update State according to the capture capabilities of F for position IRP.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An AbstractAttribute for nofree.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract attribute for norecurse.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An AbstractAttribute for noreturn.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
static LLVM_ABI const char ID
Unique ID (due to the unique address)
static LLVM_ABI bool isAlignedBarrier(const CallBase &CB, bool ExecutedAligned)
Helper function to determine if CB is an aligned (GPU) barrier.
static LLVM_ABI bool isNonRelaxedAtomic(const Instruction *I)
Helper function used to determine whether an instruction is non-relaxed atomic.
An abstract interface for all noundef attributes.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
static LLVM_ABI bool isImpliedByIR(Attributor &A, const IRPosition &IRP, Attribute::AttrKind ImpliedAttributeKind, bool IgnoreSubsumingPositions=false)
See IRAttribute::isImpliedByIR.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract Attribute for determining the necessity of the convergent attribute.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for all nonnull attributes.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
static LLVM_ABI bool isImpliedByIR(Attributor &A, const IRPosition &IRP, Attribute::AttrKind ImpliedAttributeKind, bool IgnoreSubsumingPositions=false)
See AbstractAttribute::isImpliedByIR(...).
A helper containing a list of offsets computed for a Use.
A container for a list of ranges.
static void set_difference(const RangeList &L, const RangeList &R, RangeList &D)
Copy ranges from L that are not in R, into D.
An abstract interface for struct information.
virtual bool reachesReturn() const =0
OffsetBinsTy::const_iterator const_bin_iterator
virtual const_bin_iterator begin() const =0
DenseMap< AA::RangeTy, SmallSet< unsigned, 4 > > OffsetBinsTy
static LLVM_ABI const char ID
Unique ID (due to the unique address)
virtual int64_t numOffsetBins() const =0
An abstract interface for potential values analysis.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
static LLVM_ABI const char ID
Unique ID (due to the unique address)
static LLVM_ABI Value * getSingleValue(Attributor &A, const AbstractAttribute &AA, const IRPosition &IRP, SmallVectorImpl< AA::ValueAndContext > &Values)
Extract the single value in Values if any.
An abstract interface for privatizability.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract attribute for undefined behavior.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract attribute for getting all assumption underlying objects.
virtual bool forallUnderlyingObjects(function_ref< bool(Value &)> Pred, AA::ValueScope Scope=AA::Interprocedural) const =0
Check Pred on all underlying objects in Scope collected so far.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for range value analysis.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for value simplify abstract attribute.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract attribute for willreturn.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
Helper to represent an access offset and size, with logic to deal with uncertainty and check for over...
static constexpr int64_t Unknown
static RangeTy getUnknown()
const Instruction * getCtxI() const
Base struct for all "concrete attribute" deductions.
void print(raw_ostream &OS) const
Helper functions, for debug purposes only.
virtual StateType & getState()=0
Return the internal abstract state for inspection.
An interface to query the internal state of an abstract attribute.
virtual bool isAtFixpoint() const =0
Return if this abstract state is fixed, thus does not need to be updated if information changes as it...
virtual bool isValidState() const =0
Return if this abstract state is in a valid state.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
std::function< void( const ArgumentReplacementInfo &, Function &, Function::arg_iterator)> CalleeRepairCBTy
Callee repair callback type.
const Argument & getReplacedArg() const
std::function< void(const ArgumentReplacementInfo &, AbstractCallSite, SmallVectorImpl< Value * > &)> ACSRepairCBTy
Abstract call site (ACS) repair callback type.
The fixpoint analysis framework that orchestrates the attribute deduction.
std::function< std::optional< Value * >( const IRPosition &, const AbstractAttribute *, bool &)> SimplifictionCallbackTy
Register CB as a simplification callback.
Specialization of the integer state for a bit-wise encoding.
BitIntegerState & addKnownBits(base_t Bits)
Add the bits in BitsEncoding to the "known bits".
Simple wrapper for a single bit (boolean) state.
static constexpr DenormalFPEnv getDefault()
static unsigned getHashValue(const Access &A)
AAPointerInfo::Access Access
static bool isEqual(const Access &LHS, const Access &RHS)
static bool isEqual(const AA::RangeTy &A, const AA::RangeTy B)
static unsigned getHashValue(const AA::RangeTy &Range)
DenseMapInfo< std::pair< const Instruction *, const ToTy * > > PairDMI
static bool isEqual(const ReachabilityQueryInfo< ToTy > *LHS, const ReachabilityQueryInfo< ToTy > *RHS)
DenseMapInfo< const AA::InstExclusionSetTy * > InstSetDMI
static unsigned getHashValue(const ReachabilityQueryInfo< ToTy > *RQI)
An information struct used to provide DenseMap with the various necessary components for a given valu...
State for dereferenceable attribute.
IncIntegerState DerefBytesState
State representing for dereferenceable bytes.
ChangeStatus manifest(Attributor &A) override
See AbstractAttribute::manifest(...).
Helper to describe and deal with positions in the LLVM-IR.
Function * getAssociatedFunction() const
Return the associated function, if any.
static const IRPosition callsite_returned(const CallBase &CB)
Create a position describing the returned value of CB.
static const IRPosition returned(const Function &F, const CallBaseContext *CBContext=nullptr)
Create a position describing the returned value of F.
LLVM_ABI Argument * getAssociatedArgument() const
Return the associated argument, if any.
static const IRPosition value(const Value &V, const CallBaseContext *CBContext=nullptr)
Create a position describing the value of V.
int getCalleeArgNo() const
Return the callee argument number of the associated value if it is an argument or call site argument,...
static const IRPosition inst(const Instruction &I, const CallBaseContext *CBContext=nullptr)
Create a position describing the instruction I.
static const IRPosition callsite_argument(const CallBase &CB, unsigned ArgNo)
Create a position describing the argument of CB at position ArgNo.
@ IRP_ARGUMENT
An attribute for a function argument.
@ IRP_RETURNED
An attribute for the function return value.
@ IRP_CALL_SITE
An attribute for a call site (function scope).
@ IRP_CALL_SITE_RETURNED
An attribute for a call site return value.
@ IRP_FUNCTION
An attribute for a function (scope).
@ IRP_CALL_SITE_ARGUMENT
An attribute for a call site argument.
@ IRP_INVALID
An invalid position.
Instruction * getCtxI() const
Return the context instruction, if any.
static const IRPosition argument(const Argument &Arg, const CallBaseContext *CBContext=nullptr)
Create a position describing the argument Arg.
Type * getAssociatedType() const
Return the type this abstract attribute is associated with.
static const IRPosition function(const Function &F, const CallBaseContext *CBContext=nullptr)
Create a position describing the function scope of F.
const CallBaseContext * getCallBaseContext() const
Get the call base context from the position.
Value & getAssociatedValue() const
Return the value this abstract attribute is associated with.
Value & getAnchorValue() const
Return the value this abstract attribute is anchored with.
int getCallSiteArgNo() const
Return the call site argument number of the associated value if it is an argument or call site argume...
static const IRPosition function_scope(const IRPosition &IRP, const CallBaseContext *CBContext=nullptr)
Create a position with function scope matching the "context" of IRP.
Kind getPositionKind() const
Return the associated position kind.
bool isArgumentPosition() const
Return true if the position is an argument or call site argument.
static const IRPosition callsite_function(const CallBase &CB)
Create a position describing the function scope of CB.
Function * getAnchorScope() const
Return the Function surrounding the anchor value.
ConstantRange getKnown() const
Return the known state encoding.
ConstantRange getAssumed() const
Return the assumed state encoding.
base_t getAssumed() const
Return the assumed state encoding.
static constexpr base_t getWorstState()
Helper that allows to insert a new assumption string in the known assumption set by creating a (stati...
FPClassTest getKnownFPClasses() const
Floating-point classes the value could be one of.
A "must be executed context" for a given program point PP is the set of instructions,...
iterator & end()
Return an universal end iterator.
bool findInContextOf(const Instruction *I, const Instruction *PP)
Helper to look for I in the context of PP.
iterator & begin(const Instruction *PP)
Return an iterator to explore the context around PP.
bool checkForAllContext(const Instruction *PP, function_ref< bool(const Instruction *)> Pred)
}
static unsigned MaxPotentialValues
Helper to tie a abstract state implementation to an abstract attribute.
StateType & getState() override
See AbstractAttribute::getState(...).
bool isPassthrough() const
CaptureComponents ResultCC
Components captured by the return value of the user of this Use.
LLVM_ABI bool unionAssumed(std::optional< Value * > Other)
Merge Other into the currently assumed simplified value.
std::optional< Value * > SimplifiedAssociatedValue
An assumed simplified value.
Type * Ty
The type of the original value.