57#include "llvm/IR/IntrinsicsAMDGPU.h"
58#include "llvm/IR/IntrinsicsNVPTX.h"
85#define DEBUG_TYPE "attributor"
89 cl::desc(
"Manifest Attributor internal string attributes."),
101 "attributor-max-potential-values",
cl::Hidden,
102 cl::desc(
"Maximum number of potential values to be "
103 "tracked for each position."),
108 "attributor-max-potential-values-iterations",
cl::Hidden,
110 "Maximum number of iterations we keep dismantling potential values."),
113STATISTIC(NumAAs,
"Number of abstract attributes created");
114STATISTIC(NumIndirectCallsPromoted,
"Number of indirect calls promoted");
129#define BUILD_STAT_MSG_IR_ATTR(TYPE, NAME) \
130 ("Number of " #TYPE " marked '" #NAME "'")
131#define BUILD_STAT_NAME(NAME, TYPE) NumIR##TYPE##_##NAME
132#define STATS_DECL_(NAME, MSG) STATISTIC(NAME, MSG);
133#define STATS_DECL(NAME, TYPE, MSG) \
134 STATS_DECL_(BUILD_STAT_NAME(NAME, TYPE), MSG);
135#define STATS_TRACK(NAME, TYPE) ++(BUILD_STAT_NAME(NAME, TYPE));
136#define STATS_DECLTRACK(NAME, TYPE, MSG) \
137 {STATS_DECL(NAME, TYPE, MSG) STATS_TRACK(NAME, TYPE)}
138#define STATS_DECLTRACK_ARG_ATTR(NAME) \
139 STATS_DECLTRACK(NAME, Arguments, BUILD_STAT_MSG_IR_ATTR(arguments, NAME))
140#define STATS_DECLTRACK_CSARG_ATTR(NAME) \
141 STATS_DECLTRACK(NAME, CSArguments, \
142 BUILD_STAT_MSG_IR_ATTR(call site arguments, NAME))
143#define STATS_DECLTRACK_FN_ATTR(NAME) \
144 STATS_DECLTRACK(NAME, Function, BUILD_STAT_MSG_IR_ATTR(functions, NAME))
145#define STATS_DECLTRACK_CS_ATTR(NAME) \
146 STATS_DECLTRACK(NAME, CS, BUILD_STAT_MSG_IR_ATTR(call site, NAME))
147#define STATS_DECLTRACK_FNRET_ATTR(NAME) \
148 STATS_DECLTRACK(NAME, FunctionReturn, \
149 BUILD_STAT_MSG_IR_ATTR(function returns, NAME))
150#define STATS_DECLTRACK_CSRET_ATTR(NAME) \
151 STATS_DECLTRACK(NAME, CSReturn, \
152 BUILD_STAT_MSG_IR_ATTR(call site returns, NAME))
153#define STATS_DECLTRACK_FLOATING_ATTR(NAME) \
154 STATS_DECLTRACK(NAME, Floating, \
155 ("Number of floating values known to be '" #NAME "'"))
160#define PIPE_OPERATOR(CLASS) \
161 raw_ostream &operator<<(raw_ostream &OS, const CLASS &AA) { \
162 return OS << static_cast<const AbstractAttribute &>(AA); \
219 bool HeaderOnly,
CycleRef *CPtr =
nullptr) {
222 auto *BB =
I->getParent();
239 if (
DL.getTypeSizeInBits(Ty) !=
DL.getTypeAllocSizeInBits(Ty))
264 StartPos +=
DL.getTypeAllocSizeInBits(ElTy);
275 bool AllowVolatile) {
276 if (!AllowVolatile &&
I->isVolatile())
280 return LI->getPointerOperand();
284 return SI->getPointerOperand();
288 return CXI->getPointerOperand();
292 return RMWI->getPointerOperand();
314 bool GetMinOffset,
bool AllowNonInbounds,
315 bool UseAssumed =
false) {
317 auto AttributorAnalysis = [&](
Value &V,
APInt &ROffset) ->
bool {
324 if (!ValueConstantRangeAA)
328 if (
Range.isFullSet())
334 ROffset =
Range.getSignedMin();
336 ROffset =
Range.getSignedMax();
347 const Value *Ptr, int64_t &BytesOffset,
352 true, AllowNonInbounds);
360template <
typename AAType,
typename StateType =
typename AAType::StateType,
362 bool RecurseForSelectAndPHI =
true>
364 Attributor &
A,
const AAType &QueryingAA, StateType &S,
366 LLVM_DEBUG(
dbgs() <<
"[Attributor] Clamp return value states for "
367 << QueryingAA <<
" into " << S <<
"\n");
369 assert((QueryingAA.getIRPosition().getPositionKind() ==
371 QueryingAA.getIRPosition().getPositionKind() ==
373 "Can only clamp returned value states for a function returned or call "
374 "site returned position!");
378 std::optional<StateType>
T;
381 auto CheckReturnValue = [&](
Value &RV) ->
bool {
395 <<
" AA: " <<
AA->getAsStr(&
A) <<
" @ " << RVPos <<
"\n");
396 const StateType &AAS =
AA->getState();
398 T = StateType::getBestState(AAS);
400 LLVM_DEBUG(
dbgs() <<
"[Attributor] AA State: " << AAS <<
" RV State: " <<
T
402 return T->isValidState();
405 if (!
A.checkForAllReturnedValues(CheckReturnValue, QueryingAA,
407 RecurseForSelectAndPHI))
408 S.indicatePessimisticFixpoint();
415template <
typename AAType,
typename BaseType,
416 typename StateType =
typename BaseType::StateType,
417 bool PropagateCallBaseContext =
false,
419 bool RecurseForSelectAndPHI =
true>
420struct AAReturnedFromReturnedValues :
public BaseType {
421 AAReturnedFromReturnedValues(
const IRPosition &IRP, Attributor &
A)
425 StateType S(StateType::getBestState(this->getState()));
427 RecurseForSelectAndPHI>(
429 PropagateCallBaseContext ? this->getCallBaseContext() : nullptr);
438template <
typename AAType,
typename StateType =
typename AAType::StateType,
440static void clampCallSiteArgumentStates(
Attributor &
A,
const AAType &QueryingAA,
442 LLVM_DEBUG(
dbgs() <<
"[Attributor] Clamp call site argument states for "
443 << QueryingAA <<
" into " << S <<
"\n");
445 assert(QueryingAA.getIRPosition().getPositionKind() ==
447 "Can only clamp call site argument states for an argument position!");
451 std::optional<StateType>
T;
454 unsigned ArgNo = QueryingAA.getIRPosition().getCallSiteArgNo();
474 LLVM_DEBUG(
dbgs() <<
"[Attributor] ACS: " << *ACS.getInstruction()
475 <<
" AA: " <<
AA->getAsStr(&
A) <<
" @" << ACSArgPos
477 const StateType &AAS =
AA->getState();
479 T = StateType::getBestState(AAS);
481 LLVM_DEBUG(
dbgs() <<
"[Attributor] AA State: " << AAS <<
" CSA State: " <<
T
483 return T->isValidState();
486 bool UsedAssumedInformation =
false;
487 if (!
A.checkForAllCallSites(CallSiteCheck, QueryingAA,
true,
488 UsedAssumedInformation))
489 S.indicatePessimisticFixpoint();
496template <
typename AAType,
typename BaseType,
497 typename StateType =
typename AAType::StateType,
499bool getArgumentStateFromCallBaseContext(
Attributor &
A,
503 "Expected an 'argument' position !");
509 assert(ArgNo >= 0 &&
"Invalid Arg No!");
523 const StateType &CBArgumentState =
524 static_cast<const StateType &
>(
AA->getState());
526 LLVM_DEBUG(
dbgs() <<
"[Attributor] Briding Call site context to argument"
527 <<
"Position:" << Pos <<
"CB Arg state:" << CBArgumentState
531 State ^= CBArgumentState;
536template <
typename AAType,
typename BaseType,
537 typename StateType =
typename AAType::StateType,
538 bool BridgeCallBaseContext =
false,
540struct AAArgumentFromCallSiteArguments :
public BaseType {
541 AAArgumentFromCallSiteArguments(
const IRPosition &IRP, Attributor &
A)
545 StateType S = StateType::getBestState(this->getState());
547 if (BridgeCallBaseContext) {
549 getArgumentStateFromCallBaseContext<AAType,
BaseType, StateType,
551 A, *
this, this->getIRPosition(), S);
555 clampCallSiteArgumentStates<AAType, StateType, IRAttributeKind>(
A, *
this,
565template <
typename AAType,
typename BaseType,
566 typename StateType =
typename BaseType::StateType,
567 bool IntroduceCallBaseContext =
false,
569struct AACalleeToCallSite :
public BaseType {
570 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) {
596 IntroduceCallBaseContext ? &CB :
nullptr)
598 *
Callee, IntroduceCallBaseContext ? &CB : nullptr);
600 if (Attribute::isEnumAttrKind(IRAttributeKind)) {
603 A,
this, FnPos, DepClassTy::REQUIRED, IsKnown))
609 A.getAAFor<AAType>(*
this, FnPos, DepClassTy::REQUIRED);
613 if (S.isAtFixpoint())
614 return S.isValidState();
618 if (!
A.checkForAllCallees(CalleePred, *
this, CB))
619 return S.indicatePessimisticFixpoint();
625template <
class AAType,
typename StateType =
typename AAType::StateType>
631 auto EIt = Explorer.
begin(CtxI), EEnd = Explorer.
end(CtxI);
632 for (
unsigned u = 0;
u <
Uses.size(); ++
u) {
636 if (Found &&
AA.followUseInMBEC(
A, U, UserI, State))
651template <
class AAType,
typename StateType =
typename AAType::StateType>
652static void followUsesInMBEC(AAType &
AA,
Attributor &
A, StateType &S,
654 const Value &Val =
AA.getIRPosition().getAssociatedValue();
659 A.getInfoCache().getMustBeExecutedContextExplorer();
665 for (
const Use &U : Val.
uses())
668 followUsesInContext<AAType>(
AA,
A, *Explorer, &CtxI,
Uses, S);
670 if (S.isAtFixpoint())
714 StateType ParentState;
718 ParentState.indicateOptimisticFixpoint();
720 for (
const BasicBlock *BB : Br->successors()) {
721 StateType ChildState;
723 size_t BeforeSize =
Uses.size();
724 followUsesInContext(
AA,
A, *Explorer, &BB->front(),
Uses, ChildState);
727 for (
auto It =
Uses.begin() + BeforeSize; It !=
Uses.end();)
730 ParentState &= ChildState;
781 R.indicatePessimisticFixpoint();
795 BS.indicateOptimisticFixpoint();
800 BS.indicatePessimisticFixpoint();
870 template <
typename F>
877 if (!
Range.mayOverlap(ItRange))
879 bool IsExact =
Range == ItRange && !
Range.offsetOrSizeAreUnknown();
880 for (
auto Index : It.getSecond()) {
890 template <
typename F>
901 for (
unsigned Index : LocalList->getSecond()) {
904 if (
Range.offsetAndSizeAreUnknown())
920 RemoteI = RemoteI ? RemoteI : &
I;
924 bool AccExists =
false;
926 for (
auto Index : LocalList) {
928 if (
A.getLocalInst() == &
I) {
937 <<
"[AAPointerInfo] Inserting access in new offset bins\n";);
939 for (
auto Key : ToAdd) {
946 AccessList.emplace_back(&
I, RemoteI, Ranges, Content, Kind, Ty);
948 "New Access should have been at AccIndex");
949 LocalList.push_back(AccIndex);
958 auto Before = Current;
960 if (Current == Before)
963 auto &ExistingRanges = Before.getRanges();
964 auto &NewRanges = Current.getRanges();
971 <<
"[AAPointerInfo] Removing access from old offset bins\n";);
978 "Expected bin to actually contain the Access.");
1000struct AAPointerInfoImpl
1001 :
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); }),
1020 return AAPointerInfo::manifest(
A);
1023 const_bin_iterator
begin()
const override {
return State::begin(); }
1024 const_bin_iterator
end()
const override {
return State::end(); }
1025 int64_t numOffsetBins()
const override {
return State::numOffsetBins(); }
1026 bool reachesReturn()
const override {
1027 return !ReturnedOffsets.isUnassigned();
1029 void addReturnedOffsetsTo(OffsetInfo &OI)
const override {
1030 if (ReturnedOffsets.isUnknown()) {
1035 OffsetInfo MergedOI;
1036 for (
auto Offset : ReturnedOffsets) {
1037 OffsetInfo TmpOI = OI;
1039 MergedOI.merge(TmpOI);
1041 OI = std::move(MergedOI);
1044 ChangeStatus setReachesReturn(
const OffsetInfo &ReachedReturnedOffsets) {
1045 if (ReturnedOffsets.isUnknown())
1046 return ChangeStatus::UNCHANGED;
1047 if (ReachedReturnedOffsets.isUnknown()) {
1048 ReturnedOffsets.setUnknown();
1049 return ChangeStatus::CHANGED;
1051 if (ReturnedOffsets.merge(ReachedReturnedOffsets))
1052 return ChangeStatus::CHANGED;
1053 return ChangeStatus::UNCHANGED;
1056 bool forallInterferingAccesses(
1058 function_ref<
bool(
const AAPointerInfo::Access &,
bool)> CB)
1060 return State::forallInterferingAccesses(
Range, CB);
1063 bool forallInterferingAccesses(
1064 Attributor &
A,
const AbstractAttribute &QueryingAA, Instruction &
I,
1065 bool FindInterferingWrites,
bool FindInterferingReads,
1066 function_ref<
bool(
const Access &,
bool)> UserCB,
bool &HasBeenWrittenTo,
1068 function_ref<
bool(
const Access &)> SkipCB)
const override {
1069 HasBeenWrittenTo =
false;
1071 SmallPtrSet<const Access *, 8> DominatingWrites;
1079 const auto *ExecDomainAA =
A.lookupAAFor<AAExecutionDomain>(
1081 bool AllInSameNoSyncFn = IsAssumedNoSync;
1082 bool InstIsExecutedByInitialThreadOnly =
1083 ExecDomainAA && ExecDomainAA->isExecutedByInitialThreadOnly(
I);
1090 bool InstIsExecutedInAlignedRegion =
1091 FindInterferingReads && ExecDomainAA &&
1092 ExecDomainAA->isExecutedInAlignedRegion(
A,
I);
1094 if (InstIsExecutedInAlignedRegion || InstIsExecutedByInitialThreadOnly)
1095 A.recordDependence(*ExecDomainAA, QueryingAA, DepClassTy::OPTIONAL);
1097 InformationCache &InfoCache =
A.getInfoCache();
1098 bool IsThreadLocalObj =
1107 auto CanIgnoreThreadingForInst = [&](
const Instruction &
I) ->
bool {
1108 if (IsThreadLocalObj || AllInSameNoSyncFn)
1110 const auto *FnExecDomainAA =
1111 I.getFunction() == &
Scope
1113 :
A.lookupAAFor<AAExecutionDomain>(
1116 if (!FnExecDomainAA)
1118 if (InstIsExecutedInAlignedRegion ||
1119 (FindInterferingWrites &&
1120 FnExecDomainAA->isExecutedInAlignedRegion(
A,
I))) {
1121 A.recordDependence(*FnExecDomainAA, QueryingAA, DepClassTy::OPTIONAL);
1124 if (InstIsExecutedByInitialThreadOnly &&
1125 FnExecDomainAA->isExecutedByInitialThreadOnly(
I)) {
1126 A.recordDependence(*FnExecDomainAA, QueryingAA, DepClassTy::OPTIONAL);
1135 auto CanIgnoreThreading = [&](
const Access &Acc) ->
bool {
1136 return CanIgnoreThreadingForInst(*Acc.getRemoteInst()) ||
1137 (Acc.getRemoteInst() != Acc.getLocalInst() &&
1138 CanIgnoreThreadingForInst(*Acc.getLocalInst()));
1142 bool IsKnownNoRecurse;
1150 bool InstInKernel =
A.getInfoCache().isKernel(Scope);
1151 bool ObjHasKernelLifetime =
false;
1152 const bool UseDominanceReasoning =
1153 FindInterferingWrites && IsKnownNoRecurse;
1154 const DominatorTree *DT =
1163 unsigned VAS =
V->getType()->getPointerAddressSpace();
1174 std::function<bool(
const Function &)> IsLiveInCalleeCB;
1179 const Function *AIFn = AI->getFunction();
1180 ObjHasKernelLifetime =
A.getInfoCache().isKernel(*AIFn);
1181 bool IsKnownNoRecurse;
1184 IsKnownNoRecurse)) {
1185 IsLiveInCalleeCB = [AIFn](
const Function &Fn) {
return AIFn != &Fn; };
1190 ObjHasKernelLifetime = HasKernelLifetime(GV, *GV->getParent());
1191 if (ObjHasKernelLifetime)
1192 IsLiveInCalleeCB = [&
A](
const Function &Fn) {
1193 return !
A.getInfoCache().isKernel(Fn);
1201 auto AccessCB = [&](
const Access &Acc,
bool Exact) {
1202 Function *AccScope = Acc.getRemoteInst()->getFunction();
1203 bool AccInSameScope = AccScope == &
Scope;
1207 if (InstInKernel && ObjHasKernelLifetime && !AccInSameScope &&
1208 A.getInfoCache().isKernel(*AccScope))
1211 if (Exact && Acc.isMustAccess() && Acc.getRemoteInst() != &
I) {
1212 if (Acc.isWrite() || (
isa<LoadInst>(
I) && Acc.isWriteOrAssumption()))
1213 ExclusionSet.
insert(Acc.getRemoteInst());
1216 if ((!FindInterferingWrites || !Acc.isWriteOrAssumption()) &&
1217 (!FindInterferingReads || !Acc.isRead()))
1220 bool Dominates = FindInterferingWrites && DT && Exact &&
1221 Acc.isMustAccess() && AccInSameScope &&
1224 DominatingWrites.
insert(&Acc);
1228 AllInSameNoSyncFn &= Acc.getRemoteInst()->getFunction() == &
Scope;
1230 InterferingAccesses.
push_back({&Acc, Exact});
1233 if (!State::forallInterferingAccesses(
I, AccessCB,
Range))
1236 HasBeenWrittenTo = !DominatingWrites.
empty();
1240 for (
const Access *Acc : DominatingWrites) {
1241 if (!LeastDominatingWriteInst) {
1242 LeastDominatingWriteInst = Acc->getRemoteInst();
1243 }
else if (DT->
dominates(LeastDominatingWriteInst,
1244 Acc->getRemoteInst())) {
1245 LeastDominatingWriteInst = Acc->getRemoteInst();
1250 auto CanSkipAccess = [&](
const Access &Acc,
bool Exact) {
1251 if (SkipCB && SkipCB(Acc))
1253 if (!CanIgnoreThreading(Acc))
1259 bool ReadChecked = !FindInterferingReads;
1260 bool WriteChecked = !FindInterferingWrites;
1266 &ExclusionSet, IsLiveInCalleeCB))
1271 if (!WriteChecked) {
1273 &ExclusionSet, IsLiveInCalleeCB))
1274 WriteChecked =
true;
1288 if (!WriteChecked && HasBeenWrittenTo &&
1289 Acc.getRemoteInst()->getFunction() != &Scope) {
1291 const auto *FnReachabilityAA =
A.getAAFor<AAInterFnReachability>(
1293 if (FnReachabilityAA) {
1299 if (!FnReachabilityAA->instructionCanReach(
1300 A, *LeastDominatingWriteInst,
1301 *Acc.getRemoteInst()->getFunction(), &ExclusionSet))
1302 WriteChecked =
true;
1309 if (ReadChecked && WriteChecked)
1312 if (!DT || !UseDominanceReasoning)
1314 if (!DominatingWrites.count(&Acc))
1316 return LeastDominatingWriteInst != Acc.getRemoteInst();
1321 for (
auto &It : InterferingAccesses) {
1322 if ((!AllInSameNoSyncFn && !IsThreadLocalObj && !ExecDomainAA) ||
1323 !CanSkipAccess(*It.first, It.second)) {
1324 if (!UserCB(*It.first, It.second))
1332 const AAPointerInfo &OtherAA,
1334 using namespace AA::PointerInfo;
1336 return indicatePessimisticFixpoint();
1339 const auto &OtherAAImpl =
static_cast<const AAPointerInfoImpl &
>(OtherAA);
1340 bool IsByval = OtherAAImpl.getAssociatedArgument()->hasByValAttr();
1341 Changed |= setReachesReturn(OtherAAImpl.ReturnedOffsets);
1344 const auto &State = OtherAAImpl.getState();
1345 for (
const auto &It : State) {
1346 for (
auto Index : It.getSecond()) {
1347 const auto &RAcc = State.getAccess(Index);
1348 if (IsByval && !RAcc.isRead())
1350 bool UsedAssumedInformation =
false;
1352 auto Content =
A.translateArgumentToCallSiteContent(
1353 RAcc.getContent(), CB, *
this, UsedAssumedInformation);
1354 AK =
AccessKind(AK & (IsByval ? AccessKind::AK_R : AccessKind::AK_RW));
1355 AK =
AccessKind(AK | (RAcc.isMayAccess() ? AK_MAY : AK_MUST));
1357 Changed |= addAccess(
A, RAcc.getRanges(), CB, Content, AK,
1358 RAcc.getType(), RAcc.getRemoteInst());
1364 ChangeStatus translateAndAddState(Attributor &
A,
const AAPointerInfo &OtherAA,
1365 const OffsetInfo &Offsets, CallBase &CB,
1367 using namespace AA::PointerInfo;
1369 return indicatePessimisticFixpoint();
1371 const auto &OtherAAImpl =
static_cast<const AAPointerInfoImpl &
>(OtherAA);
1375 const auto &State = OtherAAImpl.getState();
1376 for (
const auto &It : State) {
1377 for (
auto Index : It.getSecond()) {
1378 const auto &RAcc = State.getAccess(Index);
1379 if (!IsMustAcc && RAcc.isAssumption())
1381 for (
auto Offset : Offsets) {
1385 if (!NewRanges.isUnknown()) {
1386 NewRanges.addToAllOffsets(Offset);
1391 Changed |= addAccess(
A, NewRanges, CB, RAcc.getContent(), AK,
1392 RAcc.getType(), RAcc.getRemoteInst());
1400 void trackPointerInfoStatistics(
const IRPosition &IRP)
const {}
1403 void dumpState(raw_ostream &O) {
1404 for (
auto &It : OffsetBins) {
1405 O <<
"[" << It.first.Offset <<
"-" << It.first.Offset + It.first.Size
1406 <<
"] : " << It.getSecond().size() <<
"\n";
1407 for (
auto AccIndex : It.getSecond()) {
1408 auto &Acc = AccessList[AccIndex];
1409 O <<
" - " << Acc.getKind() <<
" - " << *Acc.getLocalInst() <<
"\n";
1410 if (Acc.getLocalInst() != Acc.getRemoteInst())
1411 O <<
" --> " << *Acc.getRemoteInst()
1413 if (!Acc.isWrittenValueYetUndetermined()) {
1415 O <<
" - c: func " << Acc.getWrittenValue()->getName()
1417 else if (Acc.getWrittenValue())
1418 O <<
" - c: " << *Acc.getWrittenValue() <<
"\n";
1420 O <<
" - c: <unknown>\n";
1427struct AAPointerInfoFloating :
public AAPointerInfoImpl {
1429 AAPointerInfoFloating(
const IRPosition &IRP, Attributor &
A)
1430 : AAPointerInfoImpl(IRP,
A) {}
1433 bool handleAccess(Attributor &
A, Instruction &
I,
1434 std::optional<Value *> Content,
AccessKind Kind,
1437 using namespace AA::PointerInfo;
1439 const DataLayout &
DL =
A.getDataLayout();
1440 TypeSize AccessSize =
DL.getTypeStoreSize(&Ty);
1449 if (!VT || VT->getElementCount().isScalable() ||
1451 (*Content)->getType() != VT ||
1452 DL.getTypeStoreSize(VT->getElementType()).isScalable()) {
1463 int64_t ElementSize =
DL.getTypeStoreSize(ElementType).getFixedValue();
1467 OffsetsSorted.end());
1469 for (
int i = 0, e = VT->getElementCount().getFixedValue(); i != e; ++i) {
1471 ConstContent, ConstantInt::get(Int32Ty, i));
1478 for (
auto &ElementOffset : ElementOffsets)
1479 ElementOffset += ElementSize;
1491 bool collectConstantsForGEP(Attributor &
A,
const DataLayout &
DL,
1492 OffsetInfo &UsrOI,
const OffsetInfo &PtrOI,
1493 const GEPOperator *
GEP);
1495 void trackStatistics()
const override {
1496 AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());
1500bool AAPointerInfoFloating::collectConstantsForGEP(Attributor &
A,
1501 const DataLayout &
DL,
1503 const OffsetInfo &PtrOI,
1504 const GEPOperator *
GEP) {
1505 unsigned BitWidth =
DL.getIndexTypeSizeInBits(
GEP->getType());
1506 SmallMapVector<Value *, APInt, 4> VariableOffsets;
1509 assert(!UsrOI.isUnknown() && !PtrOI.isUnknown() &&
1510 "Don't look for constant values if the offset has already been "
1511 "determined to be unknown.");
1513 if (!
GEP->collectOffset(
DL,
BitWidth, VariableOffsets, ConstantOffset)) {
1519 << (VariableOffsets.
empty() ?
"" :
"not") <<
" constant "
1523 Union.addToAll(ConstantOffset.getSExtValue());
1528 for (
const auto &VI : VariableOffsets) {
1529 auto *PotentialConstantsAA =
A.getAAFor<AAPotentialConstantValues>(
1531 if (!PotentialConstantsAA || !PotentialConstantsAA->isValidState()) {
1537 if (PotentialConstantsAA->undefIsContained())
1544 auto &AssumedSet = PotentialConstantsAA->getAssumedSet();
1545 if (AssumedSet.empty())
1549 for (
const auto &ConstOffset : AssumedSet) {
1550 auto CopyPerOffset =
Union;
1551 CopyPerOffset.addToAll(ConstOffset.getSExtValue() *
1552 VI.second.getZExtValue());
1553 Product.merge(CopyPerOffset);
1558 UsrOI = std::move(Union);
1562ChangeStatus AAPointerInfoFloating::updateImpl(Attributor &
A) {
1563 using namespace AA::PointerInfo;
1565 const DataLayout &
DL =
A.getDataLayout();
1566 Value &AssociatedValue = getAssociatedValue();
1568 DenseMap<Value *, OffsetInfo> OffsetInfoMap;
1569 OffsetInfoMap[&AssociatedValue].
insert(0);
1571 auto HandlePassthroughUser = [&](
Value *Usr,
Value *CurPtr,
bool &Follow) {
1582 "CurPtr does not exist in the map!");
1584 auto &UsrOI = OffsetInfoMap[Usr];
1585 auto &PtrOI = OffsetInfoMap[CurPtr];
1586 assert(!PtrOI.isUnassigned() &&
1587 "Cannot pass through if the input Ptr was not visited!");
1593 auto UsePred = [&](
const Use &
U,
bool &Follow) ->
bool {
1595 User *Usr =
U.getUser();
1596 LLVM_DEBUG(
dbgs() <<
"[AAPointerInfo] Analyze " << *CurPtr <<
" in " << *Usr
1599 "The current pointer offset should have been seeded!");
1600 assert(!OffsetInfoMap[CurPtr].isUnassigned() &&
1601 "Current pointer should be assigned");
1607 return HandlePassthroughUser(Usr, CurPtr, Follow);
1612 auto &UsrOI = OffsetInfoMap[Usr];
1613 auto &PtrOI = OffsetInfoMap[CurPtr];
1615 if (UsrOI.isUnknown())
1618 if (PtrOI.isUnknown()) {
1624 Follow = collectConstantsForGEP(
A,
DL, UsrOI, PtrOI,
GEP);
1628 return HandlePassthroughUser(Usr, CurPtr, Follow);
1633 if (RI->getFunction() == getAssociatedFunction()) {
1634 auto &PtrOI = OffsetInfoMap[CurPtr];
1635 Changed |= setReachesReturn(PtrOI);
1648 auto &UsrOI = PhiIt->second;
1649 auto &PtrOI = OffsetInfoMap[CurPtr];
1653 if (PtrOI.isUnknown()) {
1654 LLVM_DEBUG(
dbgs() <<
"[AAPointerInfo] PHI operand offset unknown "
1655 << *CurPtr <<
" in " << *
PHI <<
"\n");
1656 Follow = !UsrOI.isUnknown();
1662 if (UsrOI == PtrOI) {
1663 assert(!PtrOI.isUnassigned() &&
1664 "Cannot assign if the current Ptr was not visited!");
1665 LLVM_DEBUG(
dbgs() <<
"[AAPointerInfo] PHI is invariant (so far)");
1675 auto It = OffsetInfoMap.
find(CurPtrBase);
1676 if (It == OffsetInfoMap.
end()) {
1677 LLVM_DEBUG(
dbgs() <<
"[AAPointerInfo] PHI operand is too complex "
1678 << *CurPtr <<
" in " << *
PHI
1679 <<
" (base: " << *CurPtrBase <<
")\n");
1693 A.getInfoCache().getAnalysisResultForFunction<CycleAnalysis>(
1694 *
PHI->getFunction());
1696 auto BaseOI = It->getSecond();
1697 BaseOI.addToAll(
Offset.getZExtValue());
1698 if (IsFirstPHIUser || BaseOI == UsrOI) {
1699 LLVM_DEBUG(
dbgs() <<
"[AAPointerInfo] PHI is invariant " << *CurPtr
1700 <<
" in " << *Usr <<
"\n");
1701 return HandlePassthroughUser(Usr, CurPtr, Follow);
1705 dbgs() <<
"[AAPointerInfo] PHI operand pointer offset mismatch "
1706 << *CurPtr <<
" in " << *
PHI <<
"\n");
1725 if (!handleAccess(
A, *LoadI,
nullptr, AK,
1726 OffsetInfoMap[CurPtr].Offsets,
Changed,
1732 return II->isAssumeLikeIntrinsic();
1743 }
while (FromI && FromI != ToI);
1748 auto IsValidAssume = [&](IntrinsicInst &IntrI) {
1749 if (IntrI.getIntrinsicID() != Intrinsic::assume)
1752 if (IntrI.getParent() == BB) {
1753 if (IsImpactedInRange(LoadI->getNextNode(), &IntrI))
1759 if ((*PredIt) != BB)
1764 if (SuccBB == IntrBB)
1770 if (IsImpactedInRange(LoadI->getNextNode(), BB->
getTerminator()))
1772 if (IsImpactedInRange(&IntrBB->
front(), &IntrI))
1778 std::pair<Value *, IntrinsicInst *>
Assumption;
1779 for (
const Use &LoadU : LoadI->uses()) {
1781 if (!CmpI->isEquality() || !CmpI->isTrueWhenEqual())
1783 for (
const Use &CmpU : CmpI->uses()) {
1785 if (!IsValidAssume(*IntrI))
1787 int Idx = CmpI->getOperandUse(0) == LoadU;
1804 bool UsedAssumedInformation =
false;
1805 std::optional<Value *> Content =
nullptr;
1810 return handleAccess(
1811 A, *
Assumption.second, Content, AccessKind::AK_ASSUMPTION,
1812 OffsetInfoMap[CurPtr].Offsets,
Changed, *LoadI->getType());
1817 for (
auto *OtherOp : OtherOps) {
1818 if (OtherOp == CurPtr) {
1821 <<
"[AAPointerInfo] Escaping use in store like instruction " <<
I
1833 bool UsedAssumedInformation =
false;
1834 std::optional<Value *> Content =
nullptr;
1836 Content =
A.getAssumedSimplified(
1838 return handleAccess(
A,
I, Content, AK, OffsetInfoMap[CurPtr].Offsets,
1843 return HandleStoreLike(*StoreI, StoreI->getValueOperand(),
1844 *StoreI->getValueOperand()->getType(),
1845 {StoreI->getValueOperand()}, AccessKind::AK_W);
1847 return HandleStoreLike(*RMWI,
nullptr, *RMWI->getValOperand()->getType(),
1848 {RMWI->getValOperand()}, AccessKind::AK_RW);
1850 return HandleStoreLike(
1851 *CXI,
nullptr, *CXI->getNewValOperand()->getType(),
1852 {CXI->getCompareOperand(), CXI->getNewValOperand()},
1859 A.getInfoCache().getTargetLibraryInfoForFunction(*CB->
getFunction());
1864 const auto *CSArgPI =
A.getAAFor<AAPointerInfo>(
1870 Changed = translateAndAddState(
A, *CSArgPI, OffsetInfoMap[CurPtr], *CB,
1873 if (!CSArgPI->reachesReturn())
1874 return isValidState();
1877 if (!Callee ||
Callee->arg_size() <= ArgNo)
1879 bool UsedAssumedInformation =
false;
1880 auto ReturnedValue =
A.getAssumedSimplified(
1885 auto *Arg =
Callee->getArg(ArgNo);
1886 if (ReturnedArg && Arg != ReturnedArg)
1888 bool IsRetMustAcc = IsArgMustAcc && (ReturnedArg == Arg);
1889 const auto *CSRetPI =
A.getAAFor<AAPointerInfo>(
1893 OffsetInfo OI = OffsetInfoMap[CurPtr];
1894 CSArgPI->addReturnedOffsetsTo(OI);
1896 translateAndAddState(
A, *CSRetPI, OI, *CB, IsRetMustAcc) |
Changed;
1897 return isValidState();
1899 LLVM_DEBUG(
dbgs() <<
"[AAPointerInfo] Call user not handled " << *CB
1904 LLVM_DEBUG(
dbgs() <<
"[AAPointerInfo] User not handled " << *Usr <<
"\n");
1907 auto EquivalentUseCB = [&](
const Use &OldU,
const Use &NewU) {
1908 assert(OffsetInfoMap.
count(OldU) &&
"Old use should be known already!");
1909 assert(!OffsetInfoMap[OldU].isUnassigned() &&
"Old use should be assinged");
1910 if (OffsetInfoMap.
count(NewU)) {
1912 if (!(OffsetInfoMap[NewU] == OffsetInfoMap[OldU])) {
1913 dbgs() <<
"[AAPointerInfo] Equivalent use callback failed: "
1914 << OffsetInfoMap[NewU] <<
" vs " << OffsetInfoMap[OldU]
1918 return OffsetInfoMap[NewU] == OffsetInfoMap[OldU];
1921 return HandlePassthroughUser(NewU.get(), OldU.
get(), Unused);
1923 if (!
A.checkForAllUses(UsePred, *
this, AssociatedValue,
1925 true, EquivalentUseCB)) {
1926 LLVM_DEBUG(
dbgs() <<
"[AAPointerInfo] Check for all uses failed, abort!\n");
1927 return indicatePessimisticFixpoint();
1931 dbgs() <<
"Accesses by bin after update:\n";
1938struct AAPointerInfoReturned final : AAPointerInfoImpl {
1939 AAPointerInfoReturned(
const IRPosition &IRP, Attributor &
A)
1940 : AAPointerInfoImpl(IRP,
A) {}
1943 return indicatePessimisticFixpoint();
1946 void trackStatistics()
const override {
1947 AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());
1951struct AAPointerInfoArgument final : AAPointerInfoFloating {
1952 AAPointerInfoArgument(
const IRPosition &IRP, Attributor &
A)
1953 : AAPointerInfoFloating(IRP,
A) {}
1955 void trackStatistics()
const override {
1956 AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());
1960struct AAPointerInfoCallSiteArgument final : AAPointerInfoFloating {
1961 AAPointerInfoCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
1962 : AAPointerInfoFloating(IRP,
A) {}
1965 using namespace AA::PointerInfo;
1971 if (
auto Length =
MI->getLengthInBytes())
1972 LengthVal =
Length->getSExtValue();
1973 unsigned ArgNo = getIRPosition().getCallSiteArgNo();
1976 LLVM_DEBUG(
dbgs() <<
"[AAPointerInfo] Unhandled memory intrinsic "
1978 return indicatePessimisticFixpoint();
1981 ArgNo == 0 ? AccessKind::AK_MUST_WRITE : AccessKind::AK_MUST_READ;
1983 Changed | addAccess(
A, {0, LengthVal}, *
MI,
nullptr,
Kind,
nullptr);
1986 dbgs() <<
"Accesses by bin after update:\n";
1997 Argument *Arg = getAssociatedArgument();
2001 A.getAAFor<AAPointerInfo>(*
this, ArgPos, DepClassTy::REQUIRED);
2002 if (ArgAA && ArgAA->getState().isValidState())
2003 return translateAndAddStateFromCallee(
A, *ArgAA,
2006 return indicatePessimisticFixpoint();
2009 bool IsKnownNoCapture;
2011 A,
this, getIRPosition(), DepClassTy::OPTIONAL, IsKnownNoCapture))
2012 return indicatePessimisticFixpoint();
2014 bool IsKnown =
false;
2016 return ChangeStatus::UNCHANGED;
2019 ReadOnly ? AccessKind::AK_MAY_READ : AccessKind::AK_MAY_READ_WRITE;
2024 void trackStatistics()
const override {
2025 AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());
2029struct AAPointerInfoCallSiteReturned final : AAPointerInfoFloating {
2030 AAPointerInfoCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
2031 : AAPointerInfoFloating(IRP,
A) {}
2033 void trackStatistics()
const override {
2034 AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());
2042struct AANoUnwindImpl : AANoUnwind {
2043 AANoUnwindImpl(
const IRPosition &IRP, Attributor &
A) : AANoUnwind(IRP,
A) {}
2048 A,
nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));
2052 const std::string getAsStr(Attributor *
A)
const override {
2053 return getAssumed() ?
"nounwind" :
"may-unwind";
2058 (unsigned)Instruction::Invoke, (
unsigned)Instruction::CallBr,
2059 (unsigned)Instruction::Call, (
unsigned)Instruction::CleanupRet,
2060 (unsigned)Instruction::CatchSwitch, (
unsigned)Instruction::Resume};
2063 if (!
I.mayThrow(
true))
2067 bool IsKnownNoUnwind;
2075 bool UsedAssumedInformation =
false;
2076 if (!
A.checkForAllInstructions(CheckForNoUnwind, *
this, Opcodes,
2077 UsedAssumedInformation))
2078 return indicatePessimisticFixpoint();
2080 return ChangeStatus::UNCHANGED;
2084struct AANoUnwindFunction final :
public AANoUnwindImpl {
2085 AANoUnwindFunction(
const IRPosition &IRP, Attributor &
A)
2086 : AANoUnwindImpl(IRP,
A) {}
2092struct AANoUnwindCallSite final
2093 : AACalleeToCallSite<AANoUnwind, AANoUnwindImpl> {
2094 AANoUnwindCallSite(
const IRPosition &IRP, Attributor &
A)
2095 : AACalleeToCallSite<AANoUnwind, AANoUnwindImpl>(IRP,
A) {}
2105 case Intrinsic::nvvm_barrier_cta_sync_aligned_all:
2106 case Intrinsic::nvvm_barrier_cta_sync_aligned_count:
2107 case Intrinsic::nvvm_barrier_cta_red_and_aligned_all:
2108 case Intrinsic::nvvm_barrier_cta_red_and_aligned_count:
2109 case Intrinsic::nvvm_barrier_cta_red_or_aligned_all:
2110 case Intrinsic::nvvm_barrier_cta_red_or_aligned_count:
2111 case Intrinsic::nvvm_barrier_cta_red_popc_aligned_all:
2112 case Intrinsic::nvvm_barrier_cta_red_popc_aligned_count:
2114 case Intrinsic::amdgcn_s_barrier:
2115 if (ExecutedAligned)
2138 switch (
I->getOpcode()) {
2139 case Instruction::AtomicRMW:
2142 case Instruction::Store:
2145 case Instruction::Load:
2150 "New atomic operations need to be known in the attributor.");
2168 const std::string getAsStr(Attributor *
A)
const override {
2169 return getAssumed() ?
"nosync" :
"may-sync";
2184 if (
I.mayReadOrWriteMemory())
2198 bool UsedAssumedInformation =
false;
2199 if (!
A.checkForAllReadWriteInstructions(CheckRWInstForNoSync, *
this,
2200 UsedAssumedInformation) ||
2201 !
A.checkForAllCallLikeInstructions(CheckForNoSync, *
this,
2202 UsedAssumedInformation))
2203 return indicatePessimisticFixpoint();
2208struct AANoSyncFunction final :
public AANoSyncImpl {
2209 AANoSyncFunction(
const IRPosition &IRP, Attributor &
A)
2210 : AANoSyncImpl(IRP,
A) {}
2216struct AANoSyncCallSite final : AACalleeToCallSite<AANoSync, AANoSyncImpl> {
2217 AANoSyncCallSite(
const IRPosition &IRP, Attributor &
A)
2218 : AACalleeToCallSite<AANoSync, AANoSyncImpl>(IRP,
A) {}
2227struct AANoFreeImpl :
public AANoFree {
2228 AANoFreeImpl(
const IRPosition &IRP, Attributor &
A) : AANoFree(IRP,
A) {}
2233 DepClassTy::NONE, IsKnown));
2250 bool UsedAssumedInformation =
false;
2251 if (!
A.checkForAllReadWriteInstructions(CheckForNoFree, *
this,
2252 UsedAssumedInformation) ||
2253 !
A.checkForAllCallLikeInstructions(CheckForNoFree, *
this,
2254 UsedAssumedInformation))
2255 return indicatePessimisticFixpoint();
2257 return ChangeStatus::UNCHANGED;
2260 const std::string getAsStr(Attributor *
A)
const override {
2261 return getAssumed() ?
"nofree" :
"may-free";
2265struct AANoFreeFunction final :
public AANoFreeImpl {
2266 AANoFreeFunction(
const IRPosition &IRP, Attributor &
A)
2267 : AANoFreeImpl(IRP,
A) {}
2273struct AANoFreeCallSite final : AACalleeToCallSite<AANoFree, AANoFreeImpl> {
2274 AANoFreeCallSite(
const IRPosition &IRP, Attributor &
A)
2275 : AACalleeToCallSite<AANoFree, AANoFreeImpl>(IRP,
A) {}
2281struct AANoFreeFloating : AANoFreeImpl {
2282 AANoFreeFloating(
const IRPosition &IRP, Attributor &
A)
2283 : AANoFreeImpl(IRP,
A) {}
2289 const IRPosition &IRP = getIRPosition();
2294 DepClassTy::OPTIONAL, IsKnown))
2295 return ChangeStatus::UNCHANGED;
2297 Value &AssociatedValue = getIRPosition().getAssociatedValue();
2298 auto Pred = [&](
const Use &
U,
bool &Follow) ->
bool {
2313 DepClassTy::REQUIRED, IsKnown))
2316 const AANoCapture *NoCaptureAA =
nullptr;
2319 DepClassTy::REQUIRED, IsKnown,
2320 false, &NoCaptureAA)) {
2345 if (!
A.checkForAllUses(Pred, *
this, AssociatedValue))
2346 return indicatePessimisticFixpoint();
2348 return ChangeStatus::UNCHANGED;
2353struct AANoFreeArgument final : AANoFreeFloating {
2354 AANoFreeArgument(
const IRPosition &IRP, Attributor &
A)
2355 : AANoFreeFloating(IRP,
A) {}
2361struct AANoFreeCallSiteArgument final : AANoFreeFloating {
2362 AANoFreeCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
2363 : AANoFreeFloating(IRP,
A) {}
2370 Argument *Arg = getAssociatedArgument();
2372 return indicatePessimisticFixpoint();
2376 DepClassTy::REQUIRED, IsKnown))
2377 return ChangeStatus::UNCHANGED;
2378 return indicatePessimisticFixpoint();
2385struct AANoFreeReturned final : AANoFreeFloating {
2386 AANoFreeReturned(
const IRPosition &IRP, Attributor &
A)
2387 : AANoFreeFloating(IRP,
A) {
2399 void trackStatistics()
const override {}
2403struct AANoFreeCallSiteReturned final : AANoFreeFloating {
2404 AANoFreeCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
2405 : AANoFreeFloating(IRP,
A) {}
2408 return ChangeStatus::UNCHANGED;
2418 bool IgnoreSubsumingPositions) {
2420 AttrKinds.
push_back(Attribute::NonNull);
2423 AttrKinds.
push_back(Attribute::Dereferenceable);
2424 if (
A.hasAttr(IRP, AttrKinds, IgnoreSubsumingPositions, Attribute::NonNull))
2431 if (!Fn->isDeclaration()) {
2441 bool UsedAssumedInformation =
false;
2442 if (!
A.checkForAllInstructions(
2444 Worklist.push_back({*cast<ReturnInst>(I).getReturnValue(), &I});
2448 UsedAssumedInformation,
false,
true))
2460 Attribute::NonNull)});
2465static int64_t getKnownNonNullAndDerefBytesForUse(
2466 Attributor &
A,
const AbstractAttribute &QueryingAA,
Value &AssociatedValue,
2467 const Use *U,
const Instruction *
I,
bool &IsNonNull,
bool &TrackUse) {
2470 const Value *UseV =
U->get();
2491 const DataLayout &
DL =
A.getInfoCache().getDL();
2496 case BundleAttr::NonNull:
2499 case BundleAttr::Dereferenceable: {
2503 return CI->getZExtValue();
2520 bool IsKnownNonNull;
2523 IsNonNull |= IsKnownNonNull;
2526 return DerefAA ? DerefAA->getKnownDereferenceableBytes() : 0;
2530 if (!Loc || Loc->Ptr != UseV || !Loc->Size.isPrecise() ||
2531 Loc->Size.isScalable() ||
I->isVolatile())
2537 if (
Base &&
Base == &AssociatedValue) {
2538 int64_t DerefBytes = Loc->Size.getValue() +
Offset;
2540 return std::max(int64_t(0), DerefBytes);
2547 int64_t DerefBytes = Loc->Size.getValue();
2549 return std::max(int64_t(0), DerefBytes);
2555struct AANonNullImpl : AANonNull {
2556 AANonNullImpl(
const IRPosition &IRP, Attributor &
A) : AANonNull(IRP,
A) {}
2559 Value &
V = *getAssociatedValue().stripPointerCasts();
2561 indicatePessimisticFixpoint();
2565 if (Instruction *CtxI = getCtxI())
2566 followUsesInMBEC(*
this,
A, getState(), *CtxI);
2570 bool followUseInMBEC(Attributor &
A,
const Use *U,
const Instruction *
I,
2571 AANonNull::StateType &State) {
2572 bool IsNonNull =
false;
2573 bool TrackUse =
false;
2574 getKnownNonNullAndDerefBytesForUse(
A, *
this, getAssociatedValue(), U,
I,
2575 IsNonNull, TrackUse);
2576 State.setKnown(IsNonNull);
2580 const std::string getAsStr(Attributor *
A)
const override {
2581 return getAssumed() ?
"nonnull" :
"may-null";
2586struct AANonNullFloating :
public AANonNullImpl {
2587 AANonNullFloating(
const IRPosition &IRP, Attributor &
A)
2588 : AANonNullImpl(IRP,
A) {}
2591 auto CheckIRP = [&](
const IRPosition &IRP) {
2592 bool IsKnownNonNull;
2594 A, *
this, IRP, DepClassTy::OPTIONAL, IsKnownNonNull);
2598 bool UsedAssumedInformation =
false;
2599 Value *AssociatedValue = &getAssociatedValue();
2601 if (!
A.getAssumedSimplifiedValues(getIRPosition(), *
this,
Values,
2606 Values.size() != 1 ||
Values.front().getValue() != AssociatedValue;
2612 return AA::hasAssumedIRAttr<Attribute::NonNull>(
2613 A, this, IRPosition::value(*Op), DepClassTy::OPTIONAL,
2616 return ChangeStatus::UNCHANGED;
2620 DepClassTy::OPTIONAL, IsKnown) &&
2623 DepClassTy::OPTIONAL, IsKnown))
2624 return ChangeStatus::UNCHANGED;
2631 if (AVIRP == getIRPosition() || !CheckIRP(AVIRP))
2632 return indicatePessimisticFixpoint();
2633 return ChangeStatus::UNCHANGED;
2636 for (
const auto &VAC :
Values)
2638 return indicatePessimisticFixpoint();
2640 return ChangeStatus::UNCHANGED;
2647struct AANonNullReturned final
2648 : AAReturnedFromReturnedValues<AANonNull, AANonNull, AANonNull::StateType,
2649 false, AANonNull::IRAttributeKind, false> {
2650 AANonNullReturned(
const IRPosition &IRP, Attributor &
A)
2651 : AAReturnedFromReturnedValues<AANonNull, AANonNull, AANonNull::StateType,
2655 const std::string getAsStr(Attributor *
A)
const override {
2656 return getAssumed() ?
"nonnull" :
"may-null";
2663struct AANonNullArgument final
2664 : AAArgumentFromCallSiteArguments<AANonNull, AANonNullImpl> {
2665 AANonNullArgument(
const IRPosition &IRP, Attributor &
A)
2666 : AAArgumentFromCallSiteArguments<AANonNull, AANonNullImpl>(IRP,
A) {}
2671struct AANonNullCallSiteArgument final : AANonNullFloating {
2672 AANonNullCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
2673 : AANonNullFloating(IRP,
A) {}
2679struct AANonNullCallSiteReturned final
2680 : AACalleeToCallSite<AANonNull, AANonNullImpl> {
2681 AANonNullCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
2682 : AACalleeToCallSite<AANonNull, AANonNullImpl>(IRP,
A) {}
2690struct AAMustProgressImpl :
public AAMustProgress {
2691 AAMustProgressImpl(
const IRPosition &IRP, Attributor &
A)
2692 : AAMustProgress(IRP,
A) {}
2697 A,
nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));
2701 const std::string getAsStr(Attributor *
A)
const override {
2702 return getAssumed() ?
"mustprogress" :
"may-not-progress";
2706struct AAMustProgressFunction final : AAMustProgressImpl {
2707 AAMustProgressFunction(
const IRPosition &IRP, Attributor &
A)
2708 : AAMustProgressImpl(IRP,
A) {}
2713 A,
this, getIRPosition(), DepClassTy::OPTIONAL, IsKnown)) {
2715 return indicateOptimisticFixpoint();
2716 return ChangeStatus::UNCHANGED;
2719 auto CheckForMustProgress = [&](AbstractCallSite ACS) {
2721 bool IsKnownMustProgress;
2723 A,
this, IPos, DepClassTy::REQUIRED, IsKnownMustProgress,
2727 bool AllCallSitesKnown =
true;
2728 if (!
A.checkForAllCallSites(CheckForMustProgress, *
this,
2731 return indicatePessimisticFixpoint();
2733 return ChangeStatus::UNCHANGED;
2736 void trackStatistics()
const override {
2742struct AAMustProgressCallSite final : AAMustProgressImpl {
2743 AAMustProgressCallSite(
const IRPosition &IRP, Attributor &
A)
2744 : AAMustProgressImpl(IRP,
A) {}
2752 bool IsKnownMustProgress;
2754 A,
this, FnPos, DepClassTy::REQUIRED, IsKnownMustProgress))
2755 return indicatePessimisticFixpoint();
2756 return ChangeStatus::UNCHANGED;
2759 void trackStatistics()
const override {
2768struct AANoRecurseImpl :
public AANoRecurse {
2769 AANoRecurseImpl(
const IRPosition &IRP, Attributor &
A) : AANoRecurse(IRP,
A) {}
2774 A,
nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));
2778 const std::string getAsStr(Attributor *
A)
const override {
2779 return getAssumed() ?
"norecurse" :
"may-recurse";
2783struct AANoRecurseFunction final : AANoRecurseImpl {
2784 AANoRecurseFunction(
const IRPosition &IRP, Attributor &
A)
2785 : AANoRecurseImpl(IRP,
A) {}
2790 auto CallSitePred = [&](AbstractCallSite ACS) {
2791 bool IsKnownNoRecurse;
2795 DepClassTy::NONE, IsKnownNoRecurse))
2797 return IsKnownNoRecurse;
2799 bool UsedAssumedInformation =
false;
2800 if (
A.checkForAllCallSites(CallSitePred, *
this,
true,
2801 UsedAssumedInformation)) {
2807 if (!UsedAssumedInformation)
2808 indicateOptimisticFixpoint();
2809 return ChangeStatus::UNCHANGED;
2812 const AAInterFnReachability *EdgeReachability =
2813 A.getAAFor<AAInterFnReachability>(*
this, getIRPosition(),
2814 DepClassTy::REQUIRED);
2815 if (EdgeReachability && EdgeReachability->
canReach(
A, *getAnchorScope()))
2816 return indicatePessimisticFixpoint();
2817 return ChangeStatus::UNCHANGED;
2824struct AANoRecurseCallSite final
2825 : AACalleeToCallSite<AANoRecurse, AANoRecurseImpl> {
2826 AANoRecurseCallSite(
const IRPosition &IRP, Attributor &
A)
2827 : AACalleeToCallSite<AANoRecurse, AANoRecurseImpl>(IRP,
A) {}
2836struct AANonConvergentImpl :
public AANonConvergent {
2837 AANonConvergentImpl(
const IRPosition &IRP, Attributor &
A)
2838 : AANonConvergent(IRP,
A) {}
2840 const std::string getAsStr(Attributor *
A)
const override {
2841 return getAssumed() ?
"non-convergent" :
"may-be-convergent";
2845struct AANonConvergentFunction final : AANonConvergentImpl {
2846 AANonConvergentFunction(
const IRPosition &IRP, Attributor &
A)
2847 : AANonConvergentImpl(IRP,
A) {}
2852 auto CalleeIsNotConvergent = [&](
Instruction &Inst) {
2855 if (!Callee ||
Callee->isIntrinsic()) {
2858 if (
Callee->isDeclaration()) {
2859 return !
Callee->hasFnAttribute(Attribute::Convergent);
2861 const auto *ConvergentAA =
A.getAAFor<AANonConvergent>(
2863 return ConvergentAA && ConvergentAA->isAssumedNotConvergent();
2866 bool UsedAssumedInformation =
false;
2867 if (!
A.checkForAllCallLikeInstructions(CalleeIsNotConvergent, *
this,
2868 UsedAssumedInformation)) {
2869 return indicatePessimisticFixpoint();
2871 return ChangeStatus::UNCHANGED;
2875 if (isKnownNotConvergent() &&
2876 A.hasAttr(getIRPosition(), Attribute::Convergent)) {
2877 A.removeAttrs(getIRPosition(), {Attribute::Convergent});
2878 return ChangeStatus::CHANGED;
2880 return ChangeStatus::UNCHANGED;
2890struct AAUndefinedBehaviorImpl :
public AAUndefinedBehavior {
2891 AAUndefinedBehaviorImpl(
const IRPosition &IRP, Attributor &
A)
2892 : AAUndefinedBehavior(IRP,
A) {}
2898 UndefBranchCondition,
2900 NullReturnViolatesNonNull,
2902 NullArgViolatesNonNull,
2906 std::optional<unsigned> ArgNo;
2908 UBInfo(Kind K) :
K(
K), ArgNo(std::nullopt) {}
2910 UBInfo(Kind K, std::optional<unsigned> ArgNo) :
K(
K), ArgNo(ArgNo) {}
2914 const size_t UBPrevSize = KnownUBInsts.size();
2915 const size_t NoUBPrevSize = AssumedNoUBInsts.size();
2923 if (AssumedNoUBInsts.count(&
I) || KnownUBInsts.count(&
I))
2932 "Expected pointer operand of memory accessing instruction");
2936 std::optional<Value *> SimplifiedPtrOp =
2937 stopOnUndefOrAssumed(
A, PtrOp, &
I, UBInfo::UndefPtrAccess);
2938 if (!SimplifiedPtrOp || !*SimplifiedPtrOp)
2940 const Value *PtrOpVal = *SimplifiedPtrOp;
2946 AssumedNoUBInsts.insert(&
I);
2958 AssumedNoUBInsts.insert(&
I);
2960 KnownUBInsts.try_emplace(&
I, UBInfo::NullPtrAccess);
2969 if (AssumedNoUBInsts.count(&
I) || KnownUBInsts.count(&
I))
2977 std::optional<Value *> SimplifiedCond = stopOnUndefOrAssumed(
2978 A, BrInst->getCondition(), BrInst, UBInfo::UndefBranchCondition);
2979 if (!SimplifiedCond || !*SimplifiedCond)
2981 AssumedNoUBInsts.insert(&
I);
2989 if (AssumedNoUBInsts.count(&
I) || KnownUBInsts.count(&
I))
2998 for (
unsigned idx = 0; idx < CB.
arg_size(); idx++) {
3004 if (idx >=
Callee->arg_size())
3016 bool IsKnownNoUndef;
3018 A,
this, CalleeArgumentIRP, DepClassTy::NONE, IsKnownNoUndef);
3019 if (!IsKnownNoUndef)
3021 bool UsedAssumedInformation =
false;
3022 std::optional<Value *> SimplifiedVal =
3025 if (UsedAssumedInformation)
3027 if (SimplifiedVal && !*SimplifiedVal)
3030 KnownUBInsts.try_emplace(&
I, UBInfo(UBInfo::UndefCallArgument, idx));
3036 bool IsKnownNonNull;
3038 A,
this, CalleeArgumentIRP, DepClassTy::NONE, IsKnownNonNull);
3040 KnownUBInsts.try_emplace(&
I,
3041 UBInfo(UBInfo::NullArgViolatesNonNull, idx));
3050 std::optional<Value *> SimplifiedRetValue = stopOnUndefOrAssumed(
3051 A, RI.getReturnValue(), &
I, UBInfo::UndefReturnValue);
3052 if (!SimplifiedRetValue || !*SimplifiedRetValue)
3070 bool IsKnownNonNull;
3075 KnownUBInsts.try_emplace(&
I, UBInfo::NullReturnViolatesNonNull);
3081 bool UsedAssumedInformation =
false;
3082 A.checkForAllInstructions(InspectMemAccessInstForUB, *
this,
3083 {Instruction::Load, Instruction::Store,
3084 Instruction::AtomicCmpXchg,
3085 Instruction::AtomicRMW},
3086 UsedAssumedInformation,
3088 A.checkForAllInstructions(InspectBrInstForUB, *
this, {Instruction::CondBr},
3089 UsedAssumedInformation,
3091 A.checkForAllCallLikeInstructions(InspectCallSiteForUB, *
this,
3092 UsedAssumedInformation);
3096 if (!getAnchorScope()->getReturnType()->isVoidTy()) {
3098 if (!
A.isAssumedDead(ReturnIRP,
this,
nullptr, UsedAssumedInformation)) {
3099 bool IsKnownNoUndef;
3101 A,
this, ReturnIRP, DepClassTy::NONE, IsKnownNoUndef);
3103 A.checkForAllInstructions(InspectReturnInstForUB, *
this,
3104 {Instruction::Ret}, UsedAssumedInformation,
3109 if (NoUBPrevSize != AssumedNoUBInsts.size() ||
3110 UBPrevSize != KnownUBInsts.size())
3111 return ChangeStatus::CHANGED;
3112 return ChangeStatus::UNCHANGED;
3115 bool isKnownToCauseUB(Instruction *
I)
const override {
3116 return KnownUBInsts.count(
I);
3119 bool isAssumedToCauseUB(Instruction *
I)
const override {
3126 switch (
I->getOpcode()) {
3127 case Instruction::Load:
3128 case Instruction::Store:
3129 case Instruction::AtomicCmpXchg:
3130 case Instruction::AtomicRMW:
3131 case Instruction::CondBr:
3132 return !AssumedNoUBInsts.count(
I);
3141 static void emitUBRemark(Attributor &
A, Instruction *
I,
const UBInfo &Info) {
3142 auto Remark = [&](OptimizationRemark
OR) {
3144 case UBInfo::NullPtrAccess:
3145 case UBInfo::UndefPtrAccess: {
3146 return OR <<
"Memory access through a pointer known to be "
3149 <<
" is undefined behavior; replacing with 'unreachable'.";
3151 case UBInfo::UndefBranchCondition:
3152 return OR <<
"Branch condition known to be "
3154 <<
" is undefined behavior; replacing with 'unreachable'.";
3155 case UBInfo::UndefReturnValue:
3156 case UBInfo::NullReturnViolatesNonNull:
3157 return OR <<
"Value returned known to be "
3160 <<
" is undefined behavior; replacing with 'unreachable'.";
3161 case UBInfo::UndefCallArgument:
3162 case UBInfo::NullArgViolatesNonNull: {
3163 bool IsUndef =
Info.K == UBInfo::UndefCallArgument;
3166 <<
" passed to parameter of ";
3171 return OR <<
" known to be "
3172 <<
ore::NV(
"Argument", IsUndef ?
"undef" :
"null")
3173 <<
" is undefined behavior; replacing with 'unreachable'.";
3178 A.emitRemark<OptimizationRemark>(
I,
"UndefinedBehavior",
Remark);
3182 if (KnownUBInsts.empty())
3183 return ChangeStatus::UNCHANGED;
3184 for (
const auto &[
I, Info] : KnownUBInsts) {
3185 emitUBRemark(
A,
I, Info);
3186 A.changeToUnreachableAfterManifest(
I);
3188 return ChangeStatus::CHANGED;
3191 const std::string getAsStr(Attributor *
A)
const override {
3192 return getAssumed() ?
"undefined-behavior" :
"no-ub";
3221 MapVector<Instruction *, UBInfo> KnownUBInsts;
3225 SmallPtrSet<Instruction *, 8> AssumedNoUBInsts;
3236 std::optional<Value *> stopOnUndefOrAssumed(Attributor &
A,
Value *V,
3237 Instruction *
I, UBInfo::Kind K) {
3238 bool UsedAssumedInformation =
false;
3239 std::optional<Value *> SimplifiedV =
3242 if (!UsedAssumedInformation) {
3247 KnownUBInsts.try_emplace(
I, K);
3248 return std::nullopt;
3255 KnownUBInsts.try_emplace(
I, K);
3256 return std::nullopt;
3262struct AAUndefinedBehaviorFunction final : AAUndefinedBehaviorImpl {
3263 AAUndefinedBehaviorFunction(
const IRPosition &IRP, Attributor &
A)
3264 : AAUndefinedBehaviorImpl(IRP,
A) {}
3266 void trackStatistics()
const override {
3267 STATS_DECL(UndefinedBehaviorInstruction, Instruction,
3268 "Number of instructions known to have UB");
3270 KnownUBInsts.size();
3281static bool mayContainUnboundedCycle(
Function &
F, Attributor &
A) {
3282 ScalarEvolution *SE =
3283 A.getInfoCache().getAnalysisResultForFunction<ScalarEvolutionAnalysis>(
F);
3284 LoopInfo *LI =
A.getInfoCache().getAnalysisResultForFunction<LoopAnalysis>(
F);
3290 for (scc_iterator<Function *> SCCI =
scc_begin(&
F); !SCCI.isAtEnd(); ++SCCI)
3291 if (SCCI.hasCycle())
3301 for (
auto *L : LI->getLoopsInPreorder()) {
3308struct AAWillReturnImpl :
public AAWillReturn {
3309 AAWillReturnImpl(
const IRPosition &IRP, Attributor &
A)
3310 : AAWillReturn(IRP,
A) {}
3315 A,
nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));
3320 bool isImpliedByMustprogressAndReadonly(Attributor &
A,
bool KnownOnly) {
3321 if (!
A.hasAttr(getIRPosition(), {Attribute::MustProgress}))
3326 return IsKnown || !KnownOnly;
3331 if (isImpliedByMustprogressAndReadonly(
A,
false))
3332 return ChangeStatus::UNCHANGED;
3338 A,
this, IPos, DepClassTy::REQUIRED, IsKnown)) {
3344 bool IsKnownNoRecurse;
3346 A,
this, IPos, DepClassTy::REQUIRED, IsKnownNoRecurse);
3349 bool UsedAssumedInformation =
false;
3350 if (!
A.checkForAllCallLikeInstructions(CheckForWillReturn, *
this,
3351 UsedAssumedInformation))
3352 return indicatePessimisticFixpoint();
3356 return !
I.isVolatile();
3358 if (!
A.checkForAllInstructions(CheckForVolatile, *
this,
3359 {Instruction::Load, Instruction::Store,
3360 Instruction::AtomicCmpXchg,
3361 Instruction::AtomicRMW},
3362 UsedAssumedInformation))
3363 return indicatePessimisticFixpoint();
3365 return ChangeStatus::UNCHANGED;
3368 const std::string getAsStr(Attributor *
A)
const override {
3369 return getAssumed() ?
"willreturn" :
"may-noreturn";
3373struct AAWillReturnFunction final : AAWillReturnImpl {
3374 AAWillReturnFunction(
const IRPosition &IRP, Attributor &
A)
3375 : AAWillReturnImpl(IRP,
A) {}
3378 AAWillReturnImpl::initialize(
A);
3381 assert(
F &&
"Did expect an anchor function");
3382 if (
F->isDeclaration() || mayContainUnboundedCycle(*
F,
A))
3383 indicatePessimisticFixpoint();
3390struct AAWillReturnCallSite final
3391 : AACalleeToCallSite<AAWillReturn, AAWillReturnImpl> {
3392 AAWillReturnCallSite(
const IRPosition &IRP, Attributor &
A)
3393 : AACalleeToCallSite<AAWillReturn, AAWillReturnImpl>(IRP,
A) {}
3396 if (isImpliedByMustprogressAndReadonly(
A,
false))
3397 return ChangeStatus::UNCHANGED;
3399 return AACalleeToCallSite::updateImpl(
A);
3420 const ToTy *
To =
nullptr;
3447 if (!ES || ES->
empty()) {
3448 ExclusionSet = nullptr;
3449 }
else if (MakeUnique) {
3450 ExclusionSet =
A.getInfoCache().getOrCreateUniqueBlockExecutionSet(ES);
3468 if (!PairDMI::isEqual({LHS->From, LHS->To}, {RHS->From, RHS->To}))
3470 return InstSetDMI::isEqual(LHS->ExclusionSet, RHS->ExclusionSet);
3478template <
typename BaseTy,
typename ToTy>
3479struct CachedReachabilityAA :
public BaseTy {
3480 using RQITy = ReachabilityQueryInfo<ToTy>;
3482 CachedReachabilityAA(
const IRPosition &IRP, Attributor &
A) : BaseTy(IRP,
A) {}
3484 bool isQueryAA()
const override {
return true; }
3488 for (
unsigned u = 0, e = QueryVector.size(); u < e; ++u) {
3489 RQITy *RQI = QueryVector[
u];
3490 if (RQI->Result == RQITy::Reachable::No &&
3492 Changed = ChangeStatus::CHANGED;
3498 bool IsTemporaryRQI) = 0;
3500 bool rememberResult(Attributor &
A,
typename RQITy::Reachable Result,
3501 RQITy &RQI,
bool UsedExclusionSet,
bool IsTemporaryRQI) {
3506 QueryCache.erase(&RQI);
3512 if (Result == RQITy::Reachable::Yes || !UsedExclusionSet) {
3513 RQITy PlainRQI(RQI.From, RQI.To);
3514 if (!QueryCache.count(&PlainRQI)) {
3515 RQITy *RQIPtr =
new (
A.Allocator) RQITy(RQI.From, RQI.To);
3517 QueryVector.push_back(RQIPtr);
3518 QueryCache.insert(RQIPtr);
3523 if (IsTemporaryRQI && Result != RQITy::Reachable::Yes && UsedExclusionSet) {
3524 assert((!RQI.ExclusionSet || !RQI.ExclusionSet->empty()) &&
3525 "Did not expect empty set!");
3526 RQITy *RQIPtr =
new (
A.Allocator)
3527 RQITy(
A, *RQI.From, *RQI.To, RQI.ExclusionSet,
true);
3528 assert(RQIPtr->Result == RQITy::Reachable::No &&
"Already reachable?");
3530 assert(!QueryCache.count(RQIPtr));
3531 QueryVector.push_back(RQIPtr);
3532 QueryCache.insert(RQIPtr);
3535 if (Result == RQITy::Reachable::No && IsTemporaryRQI)
3536 A.registerForUpdate(*
this);
3537 return Result == RQITy::Reachable::Yes;
3540 const std::string getAsStr(Attributor *
A)
const override {
3542 return "#queries(" + std::to_string(QueryVector.size()) +
")";
3545 bool checkQueryCache(Attributor &
A, RQITy &StackRQI,
3546 typename RQITy::Reachable &Result) {
3547 if (!this->getState().isValidState()) {
3548 Result = RQITy::Reachable::Yes;
3554 if (StackRQI.ExclusionSet) {
3555 RQITy PlainRQI(StackRQI.From, StackRQI.To);
3556 auto It = QueryCache.find(&PlainRQI);
3557 if (It != QueryCache.end() && (*It)->Result == RQITy::Reachable::No) {
3558 Result = RQITy::Reachable::No;
3563 auto It = QueryCache.find(&StackRQI);
3564 if (It != QueryCache.end()) {
3571 QueryCache.insert(&StackRQI);
3577 DenseSet<RQITy *> QueryCache;
3580struct AAIntraFnReachabilityFunction final
3581 :
public CachedReachabilityAA<AAIntraFnReachability, Instruction> {
3582 using Base = CachedReachabilityAA<AAIntraFnReachability, Instruction>;
3583 AAIntraFnReachabilityFunction(
const IRPosition &IRP, Attributor &
A)
3585 DT =
A.getInfoCache().getAnalysisResultForFunction<DominatorTreeAnalysis>(
3589 bool isAssumedReachable(
3590 Attributor &
A,
const Instruction &From,
const Instruction &To,
3592 auto *NonConstThis =
const_cast<AAIntraFnReachabilityFunction *
>(
this);
3596 RQITy StackRQI(
A, From, To, ExclusionSet,
false);
3598 if (!NonConstThis->checkQueryCache(
A, StackRQI, Result))
3599 return NonConstThis->isReachableImpl(
A, StackRQI,
3601 return Result == RQITy::Reachable::Yes;
3608 A.getAAFor<AAIsDead>(*
this, getIRPosition(), DepClassTy::OPTIONAL);
3611 [&](
const auto &DeadEdge) {
3612 return LivenessAA->isEdgeDead(DeadEdge.first,
3616 return LivenessAA->isAssumedDead(BB);
3618 return ChangeStatus::UNCHANGED;
3622 return Base::updateImpl(
A);
3626 bool IsTemporaryRQI)
override {
3628 bool UsedExclusionSet =
false;
3633 while (IP && IP != &To) {
3634 if (ExclusionSet && IP != Origin && ExclusionSet->
count(IP)) {
3635 UsedExclusionSet =
true;
3643 const BasicBlock *FromBB = RQI.From->getParent();
3644 const BasicBlock *ToBB = RQI.To->getParent();
3646 "Not an intra-procedural query!");
3650 if (FromBB == ToBB &&
3651 WillReachInBlock(*RQI.From, *RQI.To, RQI.ExclusionSet))
3652 return rememberResult(
A, RQITy::Reachable::Yes, RQI, UsedExclusionSet,
3657 if (!WillReachInBlock(ToBB->
front(), *RQI.To, RQI.ExclusionSet))
3658 return rememberResult(
A, RQITy::Reachable::No, RQI, UsedExclusionSet,
3662 SmallPtrSet<const BasicBlock *, 16> ExclusionBlocks;
3663 if (RQI.ExclusionSet)
3664 for (
auto *
I : *RQI.ExclusionSet)
3665 if (
I->getFunction() == Fn)
3666 ExclusionBlocks.
insert(
I->getParent());
3669 if (ExclusionBlocks.
count(FromBB) &&
3672 return rememberResult(
A, RQITy::Reachable::No, RQI,
true, IsTemporaryRQI);
3675 A.getAAFor<AAIsDead>(*
this, getIRPosition(), DepClassTy::OPTIONAL);
3676 if (LivenessAA && LivenessAA->isAssumedDead(ToBB)) {
3677 DeadBlocks.insert(ToBB);
3678 return rememberResult(
A, RQITy::Reachable::No, RQI, UsedExclusionSet,
3682 SmallPtrSet<const BasicBlock *, 16> Visited;
3686 DenseSet<std::pair<const BasicBlock *, const BasicBlock *>> LocalDeadEdges;
3687 while (!Worklist.
empty()) {
3689 if (!Visited.
insert(BB).second)
3691 for (
const BasicBlock *SuccBB :
successors(BB)) {
3692 if (LivenessAA && LivenessAA->isEdgeDead(BB, SuccBB)) {
3693 LocalDeadEdges.
insert({BB, SuccBB});
3698 return rememberResult(
A, RQITy::Reachable::Yes, RQI, UsedExclusionSet,
3701 return rememberResult(
A, RQITy::Reachable::Yes, RQI, UsedExclusionSet,
3704 if (ExclusionBlocks.
count(SuccBB)) {
3705 UsedExclusionSet =
true;
3712 DeadEdges.insert_range(LocalDeadEdges);
3713 return rememberResult(
A, RQITy::Reachable::No, RQI, UsedExclusionSet,
3717 void trackStatistics()
const override {}
3722 DenseSet<const BasicBlock *> DeadBlocks;
3726 DenseSet<std::pair<const BasicBlock *, const BasicBlock *>> DeadEdges;
3729 const DominatorTree *DT =
nullptr;
3737 bool IgnoreSubsumingPositions) {
3738 assert(ImpliedAttributeKind == Attribute::NoAlias &&
3739 "Unexpected attribute kind");
3745 IgnoreSubsumingPositions =
true;
3756 if (
A.hasAttr(IRP, {Attribute::ByVal, Attribute::NoAlias},
3757 IgnoreSubsumingPositions, Attribute::NoAlias))
3767 "Noalias is a pointer attribute");
3770 const std::string getAsStr(
Attributor *
A)
const override {
3771 return getAssumed() ?
"noalias" :
"may-alias";
3776struct AANoAliasFloating final : AANoAliasImpl {
3777 AANoAliasFloating(
const IRPosition &IRP, Attributor &
A)
3778 : AANoAliasImpl(IRP,
A) {}
3782 return indicatePessimisticFixpoint();
3785 void trackStatistics()
const override {
3791struct AANoAliasArgument final
3792 : AAArgumentFromCallSiteArguments<AANoAlias, AANoAliasImpl> {
3793 using Base = AAArgumentFromCallSiteArguments<AANoAlias, AANoAliasImpl>;
3794 AANoAliasArgument(
const IRPosition &IRP, Attributor &
A) :
Base(IRP,
A) {}
3806 DepClassTy::OPTIONAL, IsKnownNoSycn))
3807 return Base::updateImpl(
A);
3812 return Base::updateImpl(
A);
3816 bool UsedAssumedInformation =
false;
3817 if (
A.checkForAllCallSites(
3818 [](AbstractCallSite ACS) { return !ACS.isCallbackCall(); }, *
this,
3819 true, UsedAssumedInformation))
3820 return Base::updateImpl(
A);
3828 return indicatePessimisticFixpoint();
3834struct AANoAliasCallSiteArgument final : AANoAliasImpl {
3835 AANoAliasCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
3836 : AANoAliasImpl(IRP,
A) {}
3840 bool mayAliasWithArgument(Attributor &
A, AAResults *&AAR,
3841 const AAMemoryBehavior &MemBehaviorAA,
3842 const CallBase &CB,
unsigned OtherArgNo) {
3844 if (this->getCallSiteArgNo() == (
int)OtherArgNo)
3852 auto *CBArgMemBehaviorAA =
A.getAAFor<AAMemoryBehavior>(
3856 if (CBArgMemBehaviorAA && CBArgMemBehaviorAA->isAssumedReadNone()) {
3857 A.recordDependence(*CBArgMemBehaviorAA, *
this, DepClassTy::OPTIONAL);
3864 if (CBArgMemBehaviorAA && CBArgMemBehaviorAA->isAssumedReadOnly() &&
3866 A.recordDependence(MemBehaviorAA, *
this, DepClassTy::OPTIONAL);
3867 A.recordDependence(*CBArgMemBehaviorAA, *
this, DepClassTy::OPTIONAL);
3873 AAR =
A.getInfoCache().getAnalysisResultForFunction<AAManager>(
3877 bool IsAliasing = !AAR || !AAR->
isNoAlias(&getAssociatedValue(), ArgOp);
3879 "callsite arguments: "
3880 << getAssociatedValue() <<
" " << *ArgOp <<
" => "
3881 << (IsAliasing ?
"" :
"no-") <<
"alias \n");
3886 bool isKnownNoAliasDueToNoAliasPreservation(
3887 Attributor &
A, AAResults *&AAR,
const AAMemoryBehavior &MemBehaviorAA) {
3900 auto UsePred = [&](
const Use &
U,
bool &Follow) ->
bool {
3916 bool IsKnownNoCapture;
3919 DepClassTy::OPTIONAL, IsKnownNoCapture))
3925 A, *UserI, *getCtxI(), *
this,
nullptr,
3926 [ScopeFn](
const Function &Fn) {
return &Fn != ScopeFn; }))
3941 LLVM_DEBUG(
dbgs() <<
"[AANoAliasCSArg] Unknown user: " << *UserI <<
"\n");
3945 bool IsKnownNoCapture;
3946 const AANoCapture *NoCaptureAA =
nullptr;
3948 A,
this, VIRP, DepClassTy::NONE, IsKnownNoCapture,
false, &NoCaptureAA);
3949 if (!IsAssumedNoCapture &&
3951 if (!
A.checkForAllUses(UsePred, *
this, getAssociatedValue())) {
3953 dbgs() <<
"[AANoAliasCSArg] " << getAssociatedValue()
3954 <<
" cannot be noalias as it is potentially captured\n");
3959 A.recordDependence(*NoCaptureAA, *
this, DepClassTy::OPTIONAL);
3965 for (
unsigned OtherArgNo = 0; OtherArgNo < CB.
arg_size(); OtherArgNo++)
3966 if (mayAliasWithArgument(
A, AAR, MemBehaviorAA, CB, OtherArgNo))
3975 auto *MemBehaviorAA =
3976 A.getAAFor<AAMemoryBehavior>(*
this, getIRPosition(), DepClassTy::NONE);
3978 A.recordDependence(*MemBehaviorAA, *
this, DepClassTy::OPTIONAL);
3979 return ChangeStatus::UNCHANGED;
3982 bool IsKnownNoAlias;
3985 A,
this, VIRP, DepClassTy::REQUIRED, IsKnownNoAlias)) {
3987 <<
" is not no-alias at the definition\n");
3988 return indicatePessimisticFixpoint();
3991 AAResults *AAR =
nullptr;
3992 if (MemBehaviorAA &&
3993 isKnownNoAliasDueToNoAliasPreservation(
A, AAR, *MemBehaviorAA)) {
3995 dbgs() <<
"[AANoAlias] No-Alias deduced via no-alias preservation\n");
3996 return ChangeStatus::UNCHANGED;
3999 return indicatePessimisticFixpoint();
4006struct AANoAliasReturned final : AANoAliasImpl {
4007 AANoAliasReturned(
const IRPosition &IRP, Attributor &
A)
4008 : AANoAliasImpl(IRP,
A) {}
4012 auto CheckReturnValue = [&](
Value &RV) ->
bool {
4023 bool IsKnownNoAlias;
4025 A,
this, RVPos, DepClassTy::REQUIRED, IsKnownNoAlias))
4028 bool IsKnownNoCapture;
4029 const AANoCapture *NoCaptureAA =
nullptr;
4031 A,
this, RVPos, DepClassTy::REQUIRED, IsKnownNoCapture,
false,
4033 return IsAssumedNoCapture ||
4037 if (!
A.checkForAllReturnedValues(CheckReturnValue, *
this))
4038 return indicatePessimisticFixpoint();
4040 return ChangeStatus::UNCHANGED;
4047struct AANoAliasCallSiteReturned final
4048 : AACalleeToCallSite<AANoAlias, AANoAliasImpl> {
4049 AANoAliasCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
4050 : AACalleeToCallSite<AANoAlias, AANoAliasImpl>(IRP,
A) {}
4059struct AAIsDeadValueImpl :
public AAIsDead {
4060 AAIsDeadValueImpl(
const IRPosition &IRP, Attributor &
A) : AAIsDead(IRP,
A) {}
4062 bool isAssumedDead()
const override {
return isAssumed(IS_DEAD); }
4064 bool isKnownDead()
const override {
return isKnown(IS_DEAD); }
4066 bool isAssumedDead(
const BasicBlock *BB)
const override {
return false; }
4068 bool isKnownDead(
const BasicBlock *BB)
const override {
return false; }
4070 bool isAssumedDead(
const Instruction *
I)
const override {
4071 return I == getCtxI() && isAssumedDead();
4074 bool isKnownDead(
const Instruction *
I)
const override {
4075 return isAssumedDead(
I) && isKnownDead();
4078 const std::string getAsStr(Attributor *
A)
const override {
4079 return isAssumedDead() ?
"assumed-dead" :
"assumed-live";
4083 bool areAllUsesAssumedDead(Attributor &
A,
Value &V) {
4085 if (
V.getType()->isVoidTy() ||
V.use_empty())
4091 if (!
A.isRunOn(*
I->getFunction()))
4093 bool UsedAssumedInformation =
false;
4094 std::optional<Constant *>
C =
4095 A.getAssumedConstant(V, *
this, UsedAssumedInformation);
4100 auto UsePred = [&](
const Use &
U,
bool &Follow) {
return false; };
4105 return A.checkForAllUses(UsePred, *
this, V,
false,
4106 DepClassTy::REQUIRED,
4111 bool isAssumedSideEffectFree(Attributor &
A, Instruction *
I) {
4115 if (!
I->isTerminator() && !
I->mayHaveSideEffects())
4124 bool IsKnownNoUnwind;
4126 A,
this, CallIRP, DepClassTy::OPTIONAL, IsKnownNoUnwind))
4134struct AAIsDeadFloating :
public AAIsDeadValueImpl {
4135 AAIsDeadFloating(
const IRPosition &IRP, Attributor &
A)
4136 : AAIsDeadValueImpl(IRP,
A) {}
4139 AAIsDeadValueImpl::initialize(
A);
4142 indicatePessimisticFixpoint();
4147 if (!isAssumedSideEffectFree(
A,
I)) {
4149 indicatePessimisticFixpoint();
4151 removeAssumedBits(HAS_NO_EFFECT);
4155 bool isDeadFence(Attributor &
A, FenceInst &FI) {
4156 const auto *ExecDomainAA =
A.lookupAAFor<AAExecutionDomain>(
4158 if (!ExecDomainAA || !ExecDomainAA->isNoOpFence(FI))
4160 A.recordDependence(*ExecDomainAA, *
this, DepClassTy::OPTIONAL);
4164 bool isDeadStore(Attributor &
A, StoreInst &SI,
4165 SmallSetVector<Instruction *, 8> *AssumeOnlyInst =
nullptr) {
4167 if (
SI.isVolatile())
4173 bool UsedAssumedInformation =
false;
4174 if (!AssumeOnlyInst) {
4175 PotentialCopies.clear();
4177 UsedAssumedInformation)) {
4180 <<
"[AAIsDead] Could not determine potential copies of store!\n");
4184 LLVM_DEBUG(
dbgs() <<
"[AAIsDead] Store has " << PotentialCopies.size()
4185 <<
" potential copies.\n");
4187 InformationCache &InfoCache =
A.getInfoCache();
4190 UsedAssumedInformation))
4194 auto &UserI = cast<Instruction>(*U.getUser());
4195 if (InfoCache.isOnlyUsedByAssume(UserI)) {
4197 AssumeOnlyInst->insert(&UserI);
4200 return A.isAssumedDead(U,
this,
nullptr, UsedAssumedInformation);
4206 <<
" is assumed live!\n");
4211 const std::string getAsStr(Attributor *
A)
const override {
4215 return "assumed-dead-store";
4218 return "assumed-dead-fence";
4219 return AAIsDeadValueImpl::getAsStr(
A);
4225 if (!isDeadStore(
A, *SI))
4226 return indicatePessimisticFixpoint();
4228 if (!isDeadFence(
A, *FI))
4229 return indicatePessimisticFixpoint();
4231 if (!isAssumedSideEffectFree(
A,
I))
4232 return indicatePessimisticFixpoint();
4233 if (!areAllUsesAssumedDead(
A, getAssociatedValue()))
4234 return indicatePessimisticFixpoint();
4239 bool isRemovableStore()
const override {
4240 return isAssumed(IS_REMOVABLE) &&
isa<StoreInst>(&getAssociatedValue());
4244 Value &
V = getAssociatedValue();
4251 SmallSetVector<Instruction *, 8> AssumeOnlyInst;
4252 bool IsDead = isDeadStore(
A, *SI, &AssumeOnlyInst);
4255 A.deleteAfterManifest(*
I);
4256 for (
size_t i = 0; i < AssumeOnlyInst.
size(); ++i) {
4258 for (
auto *Usr : AOI->
users())
4260 A.deleteAfterManifest(*AOI);
4266 A.deleteAfterManifest(*FI);
4269 if (isAssumedSideEffectFree(
A,
I) && !
I->isTerminator()) {
4270 A.deleteAfterManifest(*
I);
4277 void trackStatistics()
const override {
4283 SmallSetVector<Value *, 4> PotentialCopies;
4286struct AAIsDeadArgument :
public AAIsDeadFloating {
4287 AAIsDeadArgument(
const IRPosition &IRP, Attributor &
A)
4288 : AAIsDeadFloating(IRP,
A) {}
4291 Argument &Arg = *getAssociatedArgument();
4292 if (
A.isValidFunctionSignatureRewrite(Arg, {}))
4293 if (
A.registerFunctionSignatureRewrite(
4297 return ChangeStatus::CHANGED;
4299 return ChangeStatus::UNCHANGED;
4305struct AAIsDeadCallSiteArgument :
public AAIsDeadValueImpl {
4306 AAIsDeadCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
4307 : AAIsDeadValueImpl(IRP,
A) {}
4310 AAIsDeadValueImpl::initialize(
A);
4312 indicatePessimisticFixpoint();
4320 Argument *Arg = getAssociatedArgument();
4322 return indicatePessimisticFixpoint();
4324 auto *ArgAA =
A.getAAFor<AAIsDead>(*
this, ArgPos, DepClassTy::REQUIRED);
4326 return indicatePessimisticFixpoint();
4334 "Expected undef values to be filtered out!");
4336 if (
A.changeUseAfterManifest(U, UV))
4337 return ChangeStatus::CHANGED;
4338 return ChangeStatus::UNCHANGED;
4344struct AAIsDeadCallSiteReturned :
public AAIsDeadFloating {
4345 AAIsDeadCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
4346 : AAIsDeadFloating(IRP,
A) {}
4348 bool isAssumedDead()
const override {
4349 return AAIsDeadFloating::isAssumedDead() && IsAssumedSideEffectFree;
4353 AAIsDeadFloating::initialize(
A);
4355 indicatePessimisticFixpoint();
4360 IsAssumedSideEffectFree = isAssumedSideEffectFree(
A, getCtxI());
4365 if (IsAssumedSideEffectFree && !isAssumedSideEffectFree(
A, getCtxI())) {
4366 IsAssumedSideEffectFree =
false;
4367 Changed = ChangeStatus::CHANGED;
4369 if (!areAllUsesAssumedDead(
A, getAssociatedValue()))
4370 return indicatePessimisticFixpoint();
4374 void trackStatistics()
const override {
4375 if (IsAssumedSideEffectFree)
4381 const std::string getAsStr(Attributor *
A)
const override {
4382 return isAssumedDead()
4384 : (getAssumed() ?
"assumed-dead-users" :
"assumed-live");
4388 bool IsAssumedSideEffectFree =
true;
4391struct AAIsDeadReturned :
public AAIsDeadValueImpl {
4392 AAIsDeadReturned(
const IRPosition &IRP, Attributor &
A)
4393 : AAIsDeadValueImpl(IRP,
A) {}
4397 bool UsedAssumedInformation =
false;
4398 A.checkForAllInstructions([](Instruction &) {
return true; }, *
this,
4399 {Instruction::Ret}, UsedAssumedInformation);
4401 auto PredForCallSite = [&](AbstractCallSite ACS) {
4402 if (ACS.isCallbackCall() || !ACS.getInstruction())
4404 return areAllUsesAssumedDead(
A, *ACS.getInstruction());
4407 if (!
A.checkForAllCallSites(PredForCallSite, *
this,
true,
4408 UsedAssumedInformation))
4409 return indicatePessimisticFixpoint();
4411 return ChangeStatus::UNCHANGED;
4416 bool AnyChange =
false;
4417 UndefValue &UV = *
UndefValue::get(getAssociatedFunction()->getReturnType());
4424 bool UsedAssumedInformation =
false;
4425 A.checkForAllInstructions(RetInstPred, *
this, {Instruction::Ret},
4426 UsedAssumedInformation);
4427 return AnyChange ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
4433struct AAIsDeadFunction :
public AAIsDead {
4434 AAIsDeadFunction(
const IRPosition &IRP, Attributor &
A) : AAIsDead(IRP,
A) {}
4438 assert(
F &&
"Did expect an anchor function");
4439 if (!isAssumedDeadInternalFunction(
A)) {
4440 ToBeExploredFrom.insert(&
F->getEntryBlock().front());
4441 assumeLive(
A,
F->getEntryBlock());
4445 bool isAssumedDeadInternalFunction(Attributor &
A) {
4446 if (!getAnchorScope()->hasLocalLinkage())
4452 if (!
A.shouldUpdateAA<AAIsDead>(getIRPosition()))
4454 bool UsedAssumedInformation =
false;
4455 return A.checkForAllCallSites([](AbstractCallSite) {
return false; }, *
this,
4456 true, UsedAssumedInformation);
4459 const std::string getAsStr(Attributor *
A)
const override {
4460 return "Live[#BB " + std::to_string(AssumedLiveBlocks.size()) +
"/" +
4461 std::to_string(getAnchorScope()->
size()) +
"][#TBEP " +
4462 std::to_string(ToBeExploredFrom.size()) +
"][#KDE " +
4463 std::to_string(KnownDeadEnds.size()) +
"]";
4467 assert(getState().isValidState() &&
4468 "Attempted to manifest an invalid state!");
4473 if (AssumedLiveBlocks.empty()) {
4474 A.deleteAfterManifest(
F);
4475 return ChangeStatus::CHANGED;
4481 bool Invoke2CallAllowed = !mayCatchAsynchronousExceptions(
F);
4483 KnownDeadEnds.set_union(ToBeExploredFrom);
4484 for (
const Instruction *DeadEndI : KnownDeadEnds) {
4488 bool IsKnownNoReturn;
4496 A.registerInvokeWithDeadSuccessor(
const_cast<InvokeInst &
>(*
II));
4498 A.changeToUnreachableAfterManifest(
4499 const_cast<Instruction *
>(DeadEndI->getNextNode()));
4500 HasChanged = ChangeStatus::CHANGED;
4503 STATS_DECL(AAIsDead, BasicBlock,
"Number of dead basic blocks deleted.");
4504 for (BasicBlock &BB :
F)
4505 if (!AssumedLiveBlocks.count(&BB)) {
4506 A.deleteAfterManifest(BB);
4508 HasChanged = ChangeStatus::CHANGED;
4516 bool isEdgeDead(
const BasicBlock *From,
const BasicBlock *To)
const override {
4519 "Used AAIsDead of the wrong function");
4520 return isValidState() && !AssumedLiveEdges.count(std::make_pair(From, To));
4523 void trackStatistics()
const override {}
4526 bool isAssumedDead()
const override {
return false; }
4528 bool isKnownDead()
const override {
return false; }
4530 bool isAssumedDead(
const BasicBlock *BB)
const override {
4532 "BB must be in the same anchor scope function.");
4536 return !AssumedLiveBlocks.count(BB);
4539 bool isKnownDead(
const BasicBlock *BB)
const override {
4540 return getKnown() && isAssumedDead(BB);
4543 bool isAssumedDead(
const Instruction *
I)
const override {
4544 assert(
I->getParent()->getParent() == getAnchorScope() &&
4545 "Instruction must be in the same anchor scope function.");
4552 if (!AssumedLiveBlocks.count(
I->getParent()))
4558 if (KnownDeadEnds.count(PrevI) || ToBeExploredFrom.count(PrevI))
4565 bool isKnownDead(
const Instruction *
I)
const override {
4566 return getKnown() && isAssumedDead(
I);
4571 bool assumeLive(Attributor &
A,
const BasicBlock &BB) {
4572 if (!AssumedLiveBlocks.insert(&BB).second)
4575 if (!
A.isDuringDeduction())
4582 for (
const Instruction &
I : BB)
4585 if (
F->hasLocalLinkage()) {
4587 dbgs() <<
"[AAIsDead] Seeding live internal callee ";
4588 F->printAsOperand(
dbgs(),
false);
4590 BB.getParent()->printAsOperand(
dbgs(),
false);
4593 A.markLiveInternalFunction(*
F);
4600 SmallSetVector<const Instruction *, 8> ToBeExploredFrom;
4603 SmallSetVector<const Instruction *, 8> KnownDeadEnds;
4606 DenseSet<std::pair<const BasicBlock *, const BasicBlock *>> AssumedLiveEdges;
4609 DenseSet<const BasicBlock *> AssumedLiveBlocks;
4613identifyAliveSuccessors(Attributor &
A,
const CallBase &CB,
4614 AbstractAttribute &AA,
4615 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4618 bool IsKnownNoReturn;
4621 return !IsKnownNoReturn;
4630identifyAliveSuccessors(Attributor &
A,
const InvokeInst &
II,
4631 AbstractAttribute &AA,
4632 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4633 bool UsedAssumedInformation =
4639 if (AAIsDeadFunction::mayCatchAsynchronousExceptions(*
II.getFunction())) {
4640 AliveSuccessors.
push_back(&
II.getUnwindDest()->front());
4644 bool IsKnownNoUnwind;
4647 UsedAssumedInformation |= !IsKnownNoUnwind;
4649 AliveSuccessors.
push_back(&
II.getUnwindDest()->front());
4652 return UsedAssumedInformation;
4656identifyAliveSuccessors(Attributor &,
const UncondBrInst &BI,
4657 AbstractAttribute &,
4658 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4664identifyAliveSuccessors(Attributor &
A,
const CondBrInst &BI,
4665 AbstractAttribute &AA,
4666 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4667 bool UsedAssumedInformation =
false;
4668 std::optional<Constant *>
C =
4669 A.getAssumedConstant(*BI.
getCondition(), AA, UsedAssumedInformation);
4679 UsedAssumedInformation =
false;
4681 return UsedAssumedInformation;
4685identifyAliveSuccessors(Attributor &
A,
const SwitchInst &SI,
4686 AbstractAttribute &AA,
4687 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4688 bool UsedAssumedInformation =
false;
4692 UsedAssumedInformation)) {
4694 for (
const BasicBlock *SuccBB :
successors(
SI.getParent()))
4703 return UsedAssumedInformation;
4706 Type &Ty = *
SI.getCondition()->getType();
4707 SmallPtrSet<ConstantInt *, 8>
Constants;
4708 auto CheckForConstantInt = [&](
Value *
V) {
4717 return CheckForConstantInt(VAC.
getValue());
4719 for (
const BasicBlock *SuccBB :
successors(
SI.getParent()))
4721 return UsedAssumedInformation;
4724 unsigned MatchedCases = 0;
4725 for (
const auto &CaseIt :
SI.cases()) {
4726 if (
Constants.count(CaseIt.getCaseValue())) {
4728 AliveSuccessors.
push_back(&CaseIt.getCaseSuccessor()->front());
4735 AliveSuccessors.
push_back(&
SI.getDefaultDest()->front());
4736 return UsedAssumedInformation;
4742 if (AssumedLiveBlocks.empty()) {
4743 if (isAssumedDeadInternalFunction(
A))
4747 ToBeExploredFrom.insert(&
F->getEntryBlock().front());
4748 assumeLive(
A,
F->getEntryBlock());
4752 LLVM_DEBUG(
dbgs() <<
"[AAIsDead] Live [" << AssumedLiveBlocks.size() <<
"/"
4753 << getAnchorScope()->
size() <<
"] BBs and "
4754 << ToBeExploredFrom.size() <<
" exploration points and "
4755 << KnownDeadEnds.size() <<
" known dead ends\n");
4760 ToBeExploredFrom.end());
4761 decltype(ToBeExploredFrom) NewToBeExploredFrom;
4764 while (!Worklist.
empty()) {
4771 I =
I->getNextNode();
4773 AliveSuccessors.
clear();
4775 bool UsedAssumedInformation =
false;
4776 switch (
I->getOpcode()) {
4780 "Expected non-terminators to be handled already!");
4781 for (
const BasicBlock *SuccBB :
successors(
I->getParent()))
4784 case Instruction::Call:
4786 *
this, AliveSuccessors);
4788 case Instruction::Invoke:
4790 *
this, AliveSuccessors);
4792 case Instruction::UncondBr:
4793 UsedAssumedInformation = identifyAliveSuccessors(
4796 case Instruction::CondBr:
4798 *
this, AliveSuccessors);
4800 case Instruction::Switch:
4802 *
this, AliveSuccessors);
4806 if (UsedAssumedInformation) {
4807 NewToBeExploredFrom.insert(
I);
4808 }
else if (AliveSuccessors.
empty() ||
4809 (
I->isTerminator() &&
4810 AliveSuccessors.
size() <
I->getNumSuccessors())) {
4811 if (KnownDeadEnds.insert(
I))
4816 << AliveSuccessors.
size() <<
" UsedAssumedInformation: "
4817 << UsedAssumedInformation <<
"\n");
4819 for (
const Instruction *AliveSuccessor : AliveSuccessors) {
4820 if (!
I->isTerminator()) {
4821 assert(AliveSuccessors.size() == 1 &&
4822 "Non-terminator expected to have a single successor!");
4826 auto Edge = std::make_pair(
I->getParent(), AliveSuccessor->getParent());
4827 if (AssumedLiveEdges.insert(
Edge).second)
4829 if (assumeLive(
A, *AliveSuccessor->getParent()))
4836 if (NewToBeExploredFrom.size() != ToBeExploredFrom.size() ||
4837 llvm::any_of(NewToBeExploredFrom, [&](
const Instruction *
I) {
4838 return !ToBeExploredFrom.count(I);
4841 ToBeExploredFrom = std::move(NewToBeExploredFrom);
4850 if (ToBeExploredFrom.empty() &&
4851 getAnchorScope()->
size() == AssumedLiveBlocks.size() &&
4852 llvm::all_of(KnownDeadEnds, [](
const Instruction *DeadEndI) {
4853 return DeadEndI->isTerminator() && DeadEndI->getNumSuccessors() == 0;
4855 return indicatePessimisticFixpoint();
4860struct AAIsDeadCallSite final : AAIsDeadFunction {
4861 AAIsDeadCallSite(
const IRPosition &IRP, Attributor &
A)
4862 : AAIsDeadFunction(IRP,
A) {}
4870 "supported for call sites yet!");
4874 return indicatePessimisticFixpoint();
4877 void trackStatistics()
const override {}
4884struct AADereferenceableImpl : AADereferenceable {
4885 AADereferenceableImpl(
const IRPosition &IRP, Attributor &
A)
4886 : AADereferenceable(IRP,
A) {}
4887 using StateType = DerefState;
4890 Value &
V = *getAssociatedValue().stripPointerCasts();
4892 A.getAttrs(getIRPosition(),
4893 {Attribute::Dereferenceable, Attribute::DereferenceableOrNull},
4896 takeKnownDerefBytesMaximum(Attr.getValueAsInt());
4899 bool IsKnownNonNull;
4901 A,
this, getIRPosition(), DepClassTy::OPTIONAL, IsKnownNonNull);
4904 takeKnownDerefBytesMaximum(
V.getPointerDereferenceableBytes(
4905 A.getDataLayout(), CanBeNull,
nullptr));
4907 if (Instruction *CtxI = getCtxI())
4908 followUsesInMBEC(*
this,
A, getState(), *CtxI);
4911 StateType &getState()
override {
return *
this; }
4912 const StateType &getState()
const override {
return *
this; }
4915 void addAccessedBytesForUse(Attributor &
A,
const Use *U,
const Instruction *
I,
4916 DerefState &State) {
4917 const Value *UseV =
U->get();
4922 if (!Loc || Loc->Ptr != UseV || !Loc->Size.isPrecise() ||
I->isVolatile())
4927 Loc->Ptr,
Offset,
A.getDataLayout(),
true);
4928 if (
Base &&
Base == &getAssociatedValue())
4929 State.addAccessedBytes(
Offset, Loc->Size.getValue());
4933 bool followUseInMBEC(Attributor &
A,
const Use *U,
const Instruction *
I,
4934 AADereferenceable::StateType &State) {
4935 bool IsNonNull =
false;
4936 bool TrackUse =
false;
4937 int64_t DerefBytes = getKnownNonNullAndDerefBytesForUse(
4938 A, *
this, getAssociatedValue(), U,
I, IsNonNull, TrackUse);
4939 LLVM_DEBUG(
dbgs() <<
"[AADereferenceable] Deref bytes: " << DerefBytes
4940 <<
" for instruction " << *
I <<
"\n");
4942 addAccessedBytesForUse(
A, U,
I, State);
4943 State.takeKnownDerefBytesMaximum(DerefBytes);
4949 bool IsKnownNonNull;
4951 A,
this, getIRPosition(), DepClassTy::NONE, IsKnownNonNull);
4952 if (IsAssumedNonNull &&
4953 A.hasAttr(getIRPosition(), Attribute::DereferenceableOrNull)) {
4954 A.removeAttrs(getIRPosition(), {Attribute::DereferenceableOrNull});
4955 return ChangeStatus::CHANGED;
4960 void getDeducedAttributes(Attributor &
A, LLVMContext &Ctx,
4961 SmallVectorImpl<Attribute> &Attrs)
const override {
4963 bool IsKnownNonNull;
4965 A,
this, getIRPosition(), DepClassTy::NONE, IsKnownNonNull);
4966 if (IsAssumedNonNull)
4967 Attrs.emplace_back(Attribute::getWithDereferenceableBytes(
4968 Ctx, getAssumedDereferenceableBytes()));
4970 Attrs.emplace_back(Attribute::getWithDereferenceableOrNullBytes(
4971 Ctx, getAssumedDereferenceableBytes()));
4974 const std::string getAsStr(Attributor *
A)
const override {
4975 if (!getAssumedDereferenceableBytes())
4976 return "unknown-dereferenceable";
4977 bool IsKnownNonNull;
4978 bool IsAssumedNonNull =
false;
4981 *
A,
this, getIRPosition(), DepClassTy::NONE, IsKnownNonNull);
4982 return std::string(
"dereferenceable") +
4983 (IsAssumedNonNull ?
"" :
"_or_null") +
4984 (isAssumedGlobal() ?
"_globally" :
"") +
"<" +
4985 std::to_string(getKnownDereferenceableBytes()) +
"-" +
4986 std::to_string(getAssumedDereferenceableBytes()) +
">" +
4987 (!
A ?
" [non-null is unknown]" :
"");
4992struct AADereferenceableFloating : AADereferenceableImpl {
4993 AADereferenceableFloating(
const IRPosition &IRP, Attributor &
A)
4994 : AADereferenceableImpl(IRP,
A) {}
4998 bool UsedAssumedInformation =
false;
5000 if (!
A.getAssumedSimplifiedValues(getIRPosition(), *
this,
Values,
5002 Values.push_back({getAssociatedValue(), getCtxI()});
5005 Stripped =
Values.size() != 1 ||
5006 Values.front().getValue() != &getAssociatedValue();
5009 const DataLayout &
DL =
A.getDataLayout();
5012 auto VisitValueCB = [&](
const Value &
V) ->
bool {
5014 DL.getIndexSizeInBits(
V.getType()->getPointerAddressSpace());
5015 APInt
Offset(IdxWidth, 0);
5020 const auto *AA =
A.getAAFor<AADereferenceable>(
5022 int64_t DerefBytes = 0;
5023 if (!AA || (!Stripped &&
this == AA)) {
5027 DerefBytes =
Base->getPointerDereferenceableBytes(
5028 DL, CanBeNull,
nullptr);
5029 T.GlobalState.indicatePessimisticFixpoint();
5032 DerefBytes =
DS.DerefBytesState.getAssumed();
5033 T.GlobalState &=
DS.GlobalState;
5039 int64_t OffsetSExt =
Offset.getSExtValue();
5043 T.takeAssumedDerefBytesMinimum(
5044 std::max(int64_t(0), DerefBytes - OffsetSExt));
5049 T.takeKnownDerefBytesMaximum(
5050 std::max(int64_t(0), DerefBytes - OffsetSExt));
5051 T.indicatePessimisticFixpoint();
5052 }
else if (OffsetSExt > 0) {
5058 T.indicatePessimisticFixpoint();
5062 return T.isValidState();
5065 for (
const auto &VAC :
Values)
5066 if (!VisitValueCB(*VAC.
getValue()))
5067 return indicatePessimisticFixpoint();
5072 void trackStatistics()
const override {
5078struct AADereferenceableReturned final
5079 : AAReturnedFromReturnedValues<AADereferenceable, AADereferenceableImpl> {
5081 AAReturnedFromReturnedValues<AADereferenceable, AADereferenceableImpl>;
5082 AADereferenceableReturned(
const IRPosition &IRP, Attributor &
A)
5085 void trackStatistics()
const override {
5091struct AADereferenceableArgument final
5092 : AAArgumentFromCallSiteArguments<AADereferenceable,
5093 AADereferenceableImpl> {
5095 AAArgumentFromCallSiteArguments<AADereferenceable, AADereferenceableImpl>;
5096 AADereferenceableArgument(
const IRPosition &IRP, Attributor &
A)
5099 void trackStatistics()
const override {
5105struct AADereferenceableCallSiteArgument final : AADereferenceableFloating {
5106 AADereferenceableCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
5107 : AADereferenceableFloating(IRP,
A) {}
5109 void trackStatistics()
const override {
5115struct AADereferenceableCallSiteReturned final
5116 : AACalleeToCallSite<AADereferenceable, AADereferenceableImpl> {
5117 using Base = AACalleeToCallSite<AADereferenceable, AADereferenceableImpl>;
5118 AADereferenceableCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
5121 void trackStatistics()
const override {
5131static unsigned getKnownAlignForUse(Attributor &
A, AAAlign &QueryingAA,
5132 Value &AssociatedValue,
const Use *U,
5133 const Instruction *
I,
bool &TrackUse) {
5142 if (
GEP->hasAllConstantIndices())
5147 switch (
II->getIntrinsicID()) {
5148 case Intrinsic::ptrmask: {
5150 const auto *ConstVals =
A.getAAFor<AAPotentialConstantValues>(
5152 const auto *AlignAA =
A.getAAFor<AAAlign>(
5154 if (ConstVals && ConstVals->isValidState() && ConstVals->isAtFixpoint()) {
5155 unsigned ShiftValue = std::min(ConstVals->getAssumedMinTrailingZeros(),
5158 if (ConstAlign >= AlignAA->getKnownAlign())
5159 return Align(1).value();
5162 return AlignAA->getKnownAlign().
value();
5165 case Intrinsic::amdgcn_make_buffer_rsrc: {
5166 const auto *AlignAA =
A.getAAFor<AAAlign>(
5169 return AlignAA->getKnownAlign().
value();
5187 MA = MaybeAlign(AlignAA->getKnownAlign());
5190 const DataLayout &
DL =
A.getDataLayout();
5191 const Value *UseV =
U->get();
5193 if (
SI->getPointerOperand() == UseV)
5194 MA =
SI->getAlign();
5196 if (LI->getPointerOperand() == UseV)
5197 MA = LI->getAlign();
5199 if (AI->getPointerOperand() == UseV)
5200 MA = AI->getAlign();
5202 if (AI->getPointerOperand() == UseV)
5203 MA = AI->getAlign();
5213 if (
Base == &AssociatedValue) {
5218 uint32_t
gcd = std::gcd(uint32_t(
abs((int32_t)
Offset)), Alignment);
5226struct AAAlignImpl : AAAlign {
5227 AAAlignImpl(
const IRPosition &IRP, Attributor &
A) : AAAlign(IRP,
A) {}
5231 A.getAttrs(getIRPosition(), {Attribute::Alignment},
Attrs);
5233 takeKnownMaximum(Attr.getValueAsInt());
5235 Value &
V = *getAssociatedValue().stripPointerCasts();
5236 takeKnownMaximum(
V.getPointerAlignment(
A.getDataLayout()).value());
5238 if (Instruction *CtxI = getCtxI())
5239 followUsesInMBEC(*
this,
A, getState(), *CtxI);
5246 Value &AssociatedValue = getAssociatedValue();
5248 return ChangeStatus::UNCHANGED;
5250 for (
const Use &U : AssociatedValue.
uses()) {
5252 if (
SI->getPointerOperand() == &AssociatedValue)
5253 if (
SI->getAlign() < getAssumedAlign()) {
5255 "Number of times alignment added to a store");
5256 SI->setAlignment(getAssumedAlign());
5257 InstrChanged = ChangeStatus::CHANGED;
5260 if (LI->getPointerOperand() == &AssociatedValue)
5261 if (LI->getAlign() < getAssumedAlign()) {
5262 LI->setAlignment(getAssumedAlign());
5264 "Number of times alignment added to a load");
5265 InstrChanged = ChangeStatus::CHANGED;
5268 if (RMW->getPointerOperand() == &AssociatedValue) {
5269 if (RMW->getAlign() < getAssumedAlign()) {
5271 "Number of times alignment added to atomicrmw");
5273 RMW->setAlignment(getAssumedAlign());
5274 InstrChanged = ChangeStatus::CHANGED;
5278 if (CAS->getPointerOperand() == &AssociatedValue) {
5279 if (CAS->getAlign() < getAssumedAlign()) {
5281 "Number of times alignment added to cmpxchg");
5282 CAS->setAlignment(getAssumedAlign());
5283 InstrChanged = ChangeStatus::CHANGED;
5291 Align InheritAlign =
5292 getAssociatedValue().getPointerAlignment(
A.getDataLayout());
5293 if (InheritAlign >= getAssumedAlign())
5294 return InstrChanged;
5295 return Changed | InstrChanged;
5302 void getDeducedAttributes(Attributor &
A, LLVMContext &Ctx,
5303 SmallVectorImpl<Attribute> &Attrs)
const override {
5304 if (getAssumedAlign() > 1)
5306 Attribute::getWithAlignment(Ctx,
Align(getAssumedAlign())));
5310 bool followUseInMBEC(Attributor &
A,
const Use *U,
const Instruction *
I,
5311 AAAlign::StateType &State) {
5312 bool TrackUse =
false;
5314 unsigned int KnownAlign =
5315 getKnownAlignForUse(
A, *
this, getAssociatedValue(), U,
I, TrackUse);
5316 State.takeKnownMaximum(KnownAlign);
5321 const std::string getAsStr(Attributor *
A)
const override {
5322 return "align<" + std::to_string(getKnownAlign().value()) +
"-" +
5323 std::to_string(getAssumedAlign().value()) +
">";
5328struct AAAlignFloating : AAAlignImpl {
5329 AAAlignFloating(
const IRPosition &IRP, Attributor &
A) : AAAlignImpl(IRP,
A) {}
5332 const DataLayout &
DL =
A.getDataLayout();
5335 bool UsedAssumedInformation =
false;
5337 if (!
A.getAssumedSimplifiedValues(getIRPosition(), *
this,
Values,
5339 Values.push_back({getAssociatedValue(), getCtxI()});
5342 Stripped =
Values.size() != 1 ||
5343 Values.front().getValue() != &getAssociatedValue();
5347 auto VisitValueCB = [&](
Value &
V) ->
bool {
5351 DepClassTy::REQUIRED);
5352 if (!AA || (!Stripped &&
this == AA)) {
5370 T.takeKnownMaximum(Alignment);
5371 T.indicatePessimisticFixpoint();
5374 const AAAlign::StateType &
DS = AA->
getState();
5377 return T.isValidState();
5380 for (
const auto &VAC :
Values) {
5381 if (!VisitValueCB(*VAC.
getValue()))
5382 return indicatePessimisticFixpoint();
5394struct AAAlignReturned final
5395 : AAReturnedFromReturnedValues<AAAlign, AAAlignImpl> {
5396 using Base = AAReturnedFromReturnedValues<AAAlign, AAAlignImpl>;
5397 AAAlignReturned(
const IRPosition &IRP, Attributor &
A) :
Base(IRP,
A) {}
5403struct AAAlignArgument final
5404 : AAArgumentFromCallSiteArguments<AAAlign, AAAlignImpl> {
5405 using Base = AAArgumentFromCallSiteArguments<AAAlign, AAAlignImpl>;
5406 AAAlignArgument(
const IRPosition &IRP, Attributor &
A) :
Base(IRP,
A) {}
5412 if (
A.getInfoCache().isInvolvedInMustTailCall(*getAssociatedArgument()))
5413 return ChangeStatus::UNCHANGED;
5414 return Base::manifest(
A);
5420struct AAAlignCallSiteArgument final : AAAlignFloating {
5421 AAAlignCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
5422 : AAAlignFloating(IRP,
A) {}
5428 if (Argument *Arg = getAssociatedArgument())
5429 if (
A.getInfoCache().isInvolvedInMustTailCall(*Arg))
5430 return ChangeStatus::UNCHANGED;
5432 Align InheritAlign =
5433 getAssociatedValue().getPointerAlignment(
A.getDataLayout());
5434 if (InheritAlign >= getAssumedAlign())
5435 Changed = ChangeStatus::UNCHANGED;
5441 if (Argument *Arg = getAssociatedArgument()) {
5444 const auto *ArgAlignAA =
A.getAAFor<AAAlign>(
5447 takeKnownMaximum(ArgAlignAA->getKnownAlign().value());
5456struct AAAlignCallSiteReturned final
5457 : AACalleeToCallSite<AAAlign, AAAlignImpl> {
5458 using Base = AACalleeToCallSite<AAAlign, AAAlignImpl>;
5459 AAAlignCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
5465 switch (
II->getIntrinsicID()) {
5466 case Intrinsic::ptrmask: {
5470 const auto *ConstVals =
A.getAAFor<AAPotentialConstantValues>(
5472 if (ConstVals && ConstVals->isValidState()) {
5473 unsigned ShiftValue =
5474 std::min(ConstVals->getAssumedMinTrailingZeros(),
5475 Value::MaxAlignmentExponent);
5480 const auto *AlignAA =
5482 DepClassTy::REQUIRED);
5484 Alignment = std::max(AlignAA->getAssumedAlign(), Alignment);
5491 std::min(this->getAssumedAlign(), Alignment).value());
5497 case Intrinsic::amdgcn_make_buffer_rsrc: {
5498 const auto *AlignAA =
5500 DepClassTy::REQUIRED);
5503 this->getState(), AlignAA->getAssumedAlign().
value());
5510 return Base::updateImpl(
A);
5518struct AANoReturnImpl :
public AANoReturn {
5519 AANoReturnImpl(
const IRPosition &IRP, Attributor &
A) : AANoReturn(IRP,
A) {}
5524 A,
nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));
5528 const std::string getAsStr(Attributor *
A)
const override {
5529 return getAssumed() ?
"noreturn" :
"may-return";
5533 auto CheckForNoReturn = [](
Instruction &) {
return false; };
5534 bool UsedAssumedInformation =
false;
5535 if (!
A.checkForAllInstructions(CheckForNoReturn, *
this,
5536 {(unsigned)Instruction::Ret},
5537 UsedAssumedInformation))
5538 return indicatePessimisticFixpoint();
5539 return ChangeStatus::UNCHANGED;
5543struct AANoReturnFunction final : AANoReturnImpl {
5544 AANoReturnFunction(
const IRPosition &IRP, Attributor &
A)
5545 : AANoReturnImpl(IRP,
A) {}
5551struct AANoReturnCallSite final
5552 : AACalleeToCallSite<AANoReturn, AANoReturnImpl> {
5553 AANoReturnCallSite(
const IRPosition &IRP, Attributor &
A)
5554 : AACalleeToCallSite<AANoReturn, AANoReturnImpl>(IRP,
A) {}
5564struct AAInstanceInfoImpl :
public AAInstanceInfo {
5565 AAInstanceInfoImpl(
const IRPosition &IRP, Attributor &
A)
5566 : AAInstanceInfo(IRP,
A) {}
5569 Value &
V = getAssociatedValue();
5571 if (
C->isThreadDependent())
5572 indicatePessimisticFixpoint();
5574 indicateOptimisticFixpoint();
5580 indicateOptimisticFixpoint();
5585 A.getInfoCache().getAnalysisResultForFunction<CycleAnalysis>(
5588 indicatePessimisticFixpoint();
5597 Value &
V = getAssociatedValue();
5600 Scope =
I->getFunction();
5603 if (!
Scope->hasLocalLinkage())
5607 return indicateOptimisticFixpoint();
5609 bool IsKnownNoRecurse;
5615 auto UsePred = [&](
const Use &
U,
bool &Follow) {
5630 if (!Callee || !
Callee->hasLocalLinkage())
5634 const auto *ArgInstanceInfoAA =
A.getAAFor<AAInstanceInfo>(
5636 DepClassTy::OPTIONAL);
5637 if (!ArgInstanceInfoAA ||
5638 !ArgInstanceInfoAA->isAssumedUniqueForAnalysis())
5643 A, *CB, *Scope, *
this,
nullptr,
5651 auto EquivalentUseCB = [&](
const Use &OldU,
const Use &NewU) {
5653 auto *Ptr =
SI->getPointerOperand()->stripPointerCasts();
5661 if (!
A.checkForAllUses(UsePred, *
this, V,
true,
5662 DepClassTy::OPTIONAL,
5663 true, EquivalentUseCB))
5664 return indicatePessimisticFixpoint();
5669 const std::string getAsStr(Attributor *
A)
const override {
5670 return isAssumedUniqueForAnalysis() ?
"<unique [fAa]>" :
"<unknown>";
5673 void trackStatistics()
const override {}
5677struct AAInstanceInfoFloating : AAInstanceInfoImpl {
5678 AAInstanceInfoFloating(
const IRPosition &IRP, Attributor &
A)
5679 : AAInstanceInfoImpl(IRP,
A) {}
5683struct AAInstanceInfoArgument final : AAInstanceInfoFloating {
5684 AAInstanceInfoArgument(
const IRPosition &IRP, Attributor &
A)
5685 : AAInstanceInfoFloating(IRP,
A) {}
5689struct AAInstanceInfoCallSiteArgument final : AAInstanceInfoImpl {
5690 AAInstanceInfoCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
5691 : AAInstanceInfoImpl(IRP,
A) {}
5698 Argument *Arg = getAssociatedArgument();
5700 return indicatePessimisticFixpoint();
5703 A.getAAFor<AAInstanceInfo>(*
this, ArgPos, DepClassTy::REQUIRED);
5705 return indicatePessimisticFixpoint();
5711struct AAInstanceInfoReturned final : AAInstanceInfoImpl {
5712 AAInstanceInfoReturned(
const IRPosition &IRP, Attributor &
A)
5713 : AAInstanceInfoImpl(IRP,
A) {
5727struct AAInstanceInfoCallSiteReturned final : AAInstanceInfoFloating {
5728 AAInstanceInfoCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
5729 : AAInstanceInfoFloating(IRP,
A) {}
5736 bool IgnoreSubsumingPositions) {
5737 assert(ImpliedAttributeKind == Attribute::Captures &&
5738 "Unexpected attribute kind");
5752 A.getAttrs(IRP, {Attribute::Captures}, Attrs,
5762 {Attribute::Captures, Attribute::ByVal}, Attrs,
5800 bool NoThrow =
F.doesNotThrow();
5801 bool IsVoidReturn =
F.getReturnType()->isVoidTy();
5802 if (
ReadOnly && NoThrow && IsVoidReturn) {
5815 if (NoThrow && IsVoidReturn)
5820 if (!NoThrow || ArgNo < 0 ||
5821 !
F.getAttributes().hasAttrSomewhere(Attribute::Returned))
5824 for (
unsigned U = 0, E =
F.arg_size(); U < E; ++U)
5825 if (
F.hasParamAttribute(U, Attribute::Returned)) {
5826 if (U ==
unsigned(ArgNo))
5850 void getDeducedAttributes(Attributor &
A, LLVMContext &Ctx,
5851 SmallVectorImpl<Attribute> &Attrs)
const override {
5852 if (!isAssumedNoCaptureMaybeReturned())
5855 if (isArgumentPosition()) {
5856 if (isAssumedNoCapture())
5857 Attrs.emplace_back(Attribute::get(Ctx, Attribute::Captures));
5859 Attrs.emplace_back(Attribute::get(Ctx,
"no-capture-maybe-returned"));
5863 const std::string getAsStr(Attributor *
A)
const override {
5864 if (isKnownNoCapture())
5865 return "known not-captured";
5866 if (isAssumedNoCapture())
5867 return "assumed not-captured";
5868 if (isKnownNoCaptureMaybeReturned())
5869 return "known not-captured-maybe-returned";
5870 if (isAssumedNoCaptureMaybeReturned())
5871 return "assumed not-captured-maybe-returned";
5872 return "assumed-captured";
5877 bool checkUse(Attributor &
A, AANoCapture::StateType &State,
const Use &U,
5880 LLVM_DEBUG(
dbgs() <<
"[AANoCapture] Check use: " << *
U.get() <<
" in "
5886 return isCapturedIn(State,
true,
true,
5893 return isCapturedIn(State,
true,
true,
5899 return isCapturedIn(State,
false,
false,
5901 return isCapturedIn(State,
true,
true,
5909 return isCapturedIn(State,
true,
true,
5916 bool IsKnownNoCapture;
5917 const AANoCapture *ArgNoCaptureAA =
nullptr;
5919 A,
this, CSArgPos, DepClassTy::REQUIRED, IsKnownNoCapture,
false,
5921 if (IsAssumedNoCapture)
5922 return isCapturedIn(State,
false,
false,
5926 return isCapturedIn(State,
false,
false,
5931 return isCapturedIn(State,
true,
true,
5938 static bool isCapturedIn(AANoCapture::StateType &State,
bool CapturedInMem,
5939 bool CapturedInInt,
bool CapturedInRet) {
5940 LLVM_DEBUG(
dbgs() <<
" - captures [Mem " << CapturedInMem <<
"|Int "
5941 << CapturedInInt <<
"|Ret " << CapturedInRet <<
"]\n");
5953 const IRPosition &IRP = getIRPosition();
5957 return indicatePessimisticFixpoint();
5964 return indicatePessimisticFixpoint();
5972 T.addKnownBits(NOT_CAPTURED_IN_MEM);
5974 addKnownBits(NOT_CAPTURED_IN_MEM);
5981 auto CheckReturnedArgs = [&](
bool &UsedAssumedInformation) {
5985 UsedAssumedInformation))
5987 bool SeenConstant =
false;
5988 for (
const AA::ValueAndContext &VAC :
Values) {
5992 SeenConstant =
true;
5994 VAC.
getValue() == getAssociatedArgument())
6000 bool IsKnownNoUnwind;
6003 bool IsVoidTy =
F->getReturnType()->isVoidTy();
6004 bool UsedAssumedInformation =
false;
6005 if (IsVoidTy || CheckReturnedArgs(UsedAssumedInformation)) {
6006 T.addKnownBits(NOT_CAPTURED_IN_RET);
6007 if (
T.isKnown(NOT_CAPTURED_IN_MEM))
6009 if (IsKnownNoUnwind && (IsVoidTy || !UsedAssumedInformation)) {
6010 addKnownBits(NOT_CAPTURED_IN_RET);
6011 if (isKnown(NOT_CAPTURED_IN_MEM))
6012 return indicateOptimisticFixpoint();
6017 auto UseCheck = [&](
const Use &
U,
bool &Follow) ->
bool {
6026 return checkUse(
A,
T, U, Follow);
6029 if (!
A.checkForAllUses(UseCheck, *
this, *V))
6030 return indicatePessimisticFixpoint();
6033 auto Assumed = S.getAssumed();
6034 S.intersectAssumedBits(
T.getAssumed());
6035 if (!isAssumedNoCaptureMaybeReturned())
6036 return indicatePessimisticFixpoint();
6042struct AANoCaptureArgument final : AANoCaptureImpl {
6043 AANoCaptureArgument(
const IRPosition &IRP, Attributor &
A)
6044 : AANoCaptureImpl(IRP,
A) {}
6050struct AANoCaptureCallSiteArgument final : AANoCaptureImpl {
6051 AANoCaptureCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
6052 : AANoCaptureImpl(IRP,
A) {}
6059 Argument *Arg = getAssociatedArgument();
6061 return indicatePessimisticFixpoint();
6063 bool IsKnownNoCapture;
6064 const AANoCapture *ArgAA =
nullptr;
6066 A,
this, ArgPos, DepClassTy::REQUIRED, IsKnownNoCapture,
false,
6068 return ChangeStatus::UNCHANGED;
6070 return indicatePessimisticFixpoint();
6074 void trackStatistics()
const override {
6080struct AANoCaptureFloating final : AANoCaptureImpl {
6081 AANoCaptureFloating(
const IRPosition &IRP, Attributor &
A)
6082 : AANoCaptureImpl(IRP,
A) {}
6084 void trackStatistics()
const override {
6090struct AANoCaptureReturned final : AANoCaptureImpl {
6091 AANoCaptureReturned(
const IRPosition &IRP, Attributor &
A)
6092 : AANoCaptureImpl(IRP,
A) {
6104 void trackStatistics()
const override {}
6108struct AANoCaptureCallSiteReturned final : AANoCaptureImpl {
6109 AANoCaptureCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
6110 : AANoCaptureImpl(IRP,
A) {}
6115 determineFunctionCaptureCapabilities(getIRPosition(), *
F, *
this);
6118 void trackStatistics()
const override {
6135 dbgs() <<
"[ValueSimplify] is assumed to be "
6138 dbgs() <<
"[ValueSimplify] is assumed to be <none>\n";
6149 if (getAssociatedValue().
getType()->isVoidTy())
6150 indicatePessimisticFixpoint();
6151 if (
A.hasSimplificationCallback(getIRPosition()))
6152 indicatePessimisticFixpoint();
6155 const std::string getAsStr(Attributor *
A)
const override {
6157 dbgs() <<
"SAV: " << (bool)SimplifiedAssociatedValue <<
" ";
6158 if (SimplifiedAssociatedValue && *SimplifiedAssociatedValue)
6159 dbgs() <<
"SAV: " << **SimplifiedAssociatedValue <<
" ";
6161 return isValidState() ? (isAtFixpoint() ?
"simplified" :
"maybe-simple")
6165 void trackStatistics()
const override {}
6167 std::optional<Value *>
6168 getAssumedSimplifiedValue(Attributor &
A)
const override {
6169 return SimplifiedAssociatedValue;
6176 static Value *ensureType(Attributor &
A,
Value &V,
Type &Ty, Instruction *CtxI,
6180 if (CtxI &&
V.getType()->canLosslesslyBitCastTo(&Ty))
6182 : BitCastInst::CreatePointerBitCastOrAddrSpaceCast(
6191 static Value *reproduceInst(Attributor &
A,
6192 const AbstractAttribute &QueryingAA,
6193 Instruction &
I,
Type &Ty, Instruction *CtxI,
6195 assert(CtxI &&
"Cannot reproduce an instruction without context!");
6196 if (
Check && (
I.mayReadFromMemory() ||
6201 Value *NewOp = reproduceValue(
A, QueryingAA, *
Op, Ty, CtxI,
Check, VMap);
6203 assert(
Check &&
"Manifest of new value unexpectedly failed!");
6225 static Value *reproduceValue(Attributor &
A,
6226 const AbstractAttribute &QueryingAA,
Value &V,
6227 Type &Ty, Instruction *CtxI,
bool Check,
6229 if (
const auto &NewV = VMap.
lookup(&V))
6231 bool UsedAssumedInformation =
false;
6232 std::optional<Value *> SimpleV =
A.getAssumedSimplified(
6234 if (!SimpleV.has_value())
6238 EffectiveV = *SimpleV;
6243 return ensureType(
A, *EffectiveV, Ty, CtxI,
Check);
6245 if (
Value *NewV = reproduceInst(
A, QueryingAA, *
I, Ty, CtxI,
Check, VMap))
6246 return ensureType(
A, *NewV, Ty, CtxI,
Check);
6252 Value *manifestReplacementValue(Attributor &
A, Instruction *CtxI)
const {
6253 Value *NewV = SimplifiedAssociatedValue
6254 ? *SimplifiedAssociatedValue
6256 if (NewV && NewV != &getAssociatedValue()) {
6260 if (reproduceValue(
A, *
this, *NewV, *getAssociatedType(), CtxI,
6262 return reproduceValue(
A, *
this, *NewV, *getAssociatedType(), CtxI,
6270 bool checkAndUpdate(Attributor &
A,
const AbstractAttribute &QueryingAA,
6271 const IRPosition &IRP,
bool Simplify =
true) {
6272 bool UsedAssumedInformation =
false;
6275 QueryingValueSimplified =
A.getAssumedSimplified(
6277 return unionAssumed(QueryingValueSimplified);
6281 template <
typename AAType>
bool askSimplifiedValueFor(Attributor &
A) {
6282 if (!getAssociatedValue().
getType()->isIntegerTy())
6287 A.getAAFor<AAType>(*
this, getIRPosition(), DepClassTy::NONE);
6291 std::optional<Constant *> COpt = AA->getAssumedConstant(
A);
6294 SimplifiedAssociatedValue = std::nullopt;
6295 A.recordDependence(*AA, *
this, DepClassTy::OPTIONAL);
6298 if (
auto *
C = *COpt) {
6299 SimplifiedAssociatedValue =
C;
6300 A.recordDependence(*AA, *
this, DepClassTy::OPTIONAL);
6306 bool askSimplifiedValueForOtherAAs(Attributor &
A) {
6307 if (askSimplifiedValueFor<AAValueConstantRange>(
A))
6309 if (askSimplifiedValueFor<AAPotentialConstantValues>(
A))
6316 for (
auto &U : getAssociatedValue().uses()) {
6321 IP =
PHI->getIncomingBlock(U)->getTerminator();
6322 if (
auto *NewV = manifestReplacementValue(
A, IP)) {
6324 <<
" -> " << *NewV <<
" :: " << *
this <<
"\n");
6325 if (
A.changeUseAfterManifest(U, *NewV))
6326 Changed = ChangeStatus::CHANGED;
6330 return Changed | AAValueSimplify::manifest(
A);
6334 SimplifiedAssociatedValue = &getAssociatedValue();
6335 return AAValueSimplify::indicatePessimisticFixpoint();
6339struct AAValueSimplifyArgument final : AAValueSimplifyImpl {
6340 AAValueSimplifyArgument(
const IRPosition &IRP, Attributor &
A)
6341 : AAValueSimplifyImpl(IRP,
A) {}
6344 AAValueSimplifyImpl::initialize(
A);
6345 if (
A.hasAttr(getIRPosition(),
6346 {Attribute::InAlloca, Attribute::Preallocated,
6347 Attribute::StructRet, Attribute::Nest, Attribute::ByVal},
6349 indicatePessimisticFixpoint();
6355 Argument *Arg = getAssociatedArgument();
6361 return indicatePessimisticFixpoint();
6364 auto Before = SimplifiedAssociatedValue;
6366 auto PredForCallSite = [&](AbstractCallSite ACS) {
6367 const IRPosition &ACSArgPos =
6378 bool UsedAssumedInformation =
false;
6379 std::optional<Constant *> SimpleArgOp =
6380 A.getAssumedConstant(ACSArgPos, *
this, UsedAssumedInformation);
6387 return unionAssumed(*SimpleArgOp);
6392 bool UsedAssumedInformation =
false;
6393 if (hasCallBaseContext() &&
6394 getCallBaseContext()->getCalledOperand() == Arg->
getParent())
6396 AbstractCallSite(&getCallBaseContext()->getCalledOperandUse()));
6398 Success =
A.checkForAllCallSites(PredForCallSite, *
this,
true,
6399 UsedAssumedInformation);
6402 if (!askSimplifiedValueForOtherAAs(
A))
6403 return indicatePessimisticFixpoint();
6406 return Before == SimplifiedAssociatedValue ? ChangeStatus::UNCHANGED
6407 : ChangeStatus ::CHANGED;
6410 void trackStatistics()
const override {
6415struct AAValueSimplifyReturned : AAValueSimplifyImpl {
6416 AAValueSimplifyReturned(
const IRPosition &IRP, Attributor &
A)
6417 : AAValueSimplifyImpl(IRP,
A) {}
6419 std::optional<Value *>
6420 getAssumedSimplifiedValue(Attributor &
A)
const override {
6421 if (!isValidState())
6423 return SimplifiedAssociatedValue;
6427 auto Before = SimplifiedAssociatedValue;
6431 return checkAndUpdate(
6436 bool UsedAssumedInformation =
false;
6437 if (!
A.checkForAllInstructions(ReturnInstCB, *
this, {Instruction::Ret},
6438 UsedAssumedInformation))
6439 if (!askSimplifiedValueForOtherAAs(
A))
6440 return indicatePessimisticFixpoint();
6443 return Before == SimplifiedAssociatedValue ? ChangeStatus::UNCHANGED
6444 : ChangeStatus ::CHANGED;
6450 return ChangeStatus::UNCHANGED;
6453 void trackStatistics()
const override {
6458struct AAValueSimplifyFloating : AAValueSimplifyImpl {
6459 AAValueSimplifyFloating(
const IRPosition &IRP, Attributor &
A)
6460 : AAValueSimplifyImpl(IRP,
A) {}
6463 AAValueSimplifyImpl::initialize(
A);
6464 Value &
V = getAnchorValue();
6468 indicatePessimisticFixpoint();
6472 auto Before = SimplifiedAssociatedValue;
6473 if (!askSimplifiedValueForOtherAAs(
A))
6474 return indicatePessimisticFixpoint();
6477 return Before == SimplifiedAssociatedValue ? ChangeStatus::UNCHANGED
6478 : ChangeStatus ::CHANGED;
6481 void trackStatistics()
const override {
6486struct AAValueSimplifyFunction : AAValueSimplifyImpl {
6487 AAValueSimplifyFunction(
const IRPosition &IRP, Attributor &
A)
6488 : AAValueSimplifyImpl(IRP,
A) {}
6491 SimplifiedAssociatedValue =
nullptr;
6492 indicateOptimisticFixpoint();
6496 "AAValueSimplify(Function|CallSite)::updateImpl will not be called");
6498 void trackStatistics()
const override {
6503struct AAValueSimplifyCallSite : AAValueSimplifyFunction {
6504 AAValueSimplifyCallSite(
const IRPosition &IRP, Attributor &
A)
6505 : AAValueSimplifyFunction(IRP,
A) {}
6506 void trackStatistics()
const override {
6511struct AAValueSimplifyCallSiteReturned : AAValueSimplifyImpl {
6512 AAValueSimplifyCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
6513 : AAValueSimplifyImpl(IRP,
A) {}
6516 AAValueSimplifyImpl::initialize(
A);
6517 Function *Fn = getAssociatedFunction();
6518 assert(Fn &&
"Did expect an associted function");
6519 for (Argument &Arg : Fn->
args()) {
6524 checkAndUpdate(
A, *
this, IRP))
6525 indicateOptimisticFixpoint();
6527 indicatePessimisticFixpoint();
6534 return indicatePessimisticFixpoint();
6537 void trackStatistics()
const override {
6542struct AAValueSimplifyCallSiteArgument : AAValueSimplifyFloating {
6543 AAValueSimplifyCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
6544 : AAValueSimplifyFloating(IRP,
A) {}
6549 auto *FloatAA =
A.lookupAAFor<AAValueSimplify>(
6551 if (FloatAA && FloatAA->getState().isValidState())
6554 if (
auto *NewV = manifestReplacementValue(
A, getCtxI())) {
6556 ->getArgOperandUse(getCallSiteArgNo());
6557 if (
A.changeUseAfterManifest(U, *NewV))
6558 Changed = ChangeStatus::CHANGED;
6561 return Changed | AAValueSimplify::manifest(
A);
6564 void trackStatistics()
const override {
6572struct AAHeapToStackFunction final :
public AAHeapToStack {
6574 static bool isGlobalizedLocal(
const CallBase &CB) {
6576 return A.
isValid() &&
A.getValueAsString() ==
"__kmpc_alloc_shared";
6579 struct AllocationInfo {
6584 bool IsGlobalizedLocal =
false;
6591 } Status = STACK_DUE_TO_USE;
6595 bool HasPotentiallyFreeingUnknownUses =
false;
6599 bool MoveAllocaIntoEntry =
true;
6602 SmallSetVector<CallBase *, 1> PotentialFreeCalls{};
6605 struct DeallocationInfo {
6613 bool MightFreeUnknownObjects =
false;
6616 SmallSetVector<CallBase *, 1> PotentialAllocationCalls{};
6619 AAHeapToStackFunction(
const IRPosition &IRP, Attributor &
A)
6620 : AAHeapToStack(IRP,
A) {}
6622 ~AAHeapToStackFunction()
override {
6625 for (
auto &It : AllocationInfos)
6626 It.second->~AllocationInfo();
6627 for (
auto &It : DeallocationInfos)
6628 It.second->~DeallocationInfo();
6632 AAHeapToStack::initialize(
A);
6635 const auto *TLI =
A.getInfoCache().getTargetLibraryInfoForFunction(*
F);
6642 DeallocationInfos[CB] =
new (
A.Allocator) DeallocationInfo{CB, FreedOp};
6649 auto *I8Ty = Type::getInt8Ty(CB->
getParent()->getContext());
6651 AllocationInfo *AI =
new (
A.Allocator) AllocationInfo{CB};
6652 AllocationInfos[CB] = AI;
6653 AI->IsGlobalizedLocal = isGlobalizedLocal(*CB);
6659 bool UsedAssumedInformation =
false;
6660 bool Success =
A.checkForAllCallLikeInstructions(
6661 AllocationIdentifierCB, *
this, UsedAssumedInformation,
6665 assert(
Success &&
"Did not expect the call base visit callback to fail!");
6668 [](
const IRPosition &,
const AbstractAttribute *,
6669 bool &) -> std::optional<Value *> {
return nullptr; };
6670 for (
const auto &It : AllocationInfos)
6673 for (
const auto &It : DeallocationInfos)
6678 const std::string getAsStr(Attributor *
A)
const override {
6679 unsigned NumH2SMallocs = 0, NumInvalidMallocs = 0;
6680 for (
const auto &It : AllocationInfos) {
6681 if (It.second->Status == AllocationInfo::INVALID)
6682 ++NumInvalidMallocs;
6686 return "[H2S] Mallocs Good/Bad: " + std::to_string(NumH2SMallocs) +
"/" +
6687 std::to_string(NumInvalidMallocs);
6690 void trackStatistics()
const override {
6693 "Number of malloc/calloc/aligned_alloc calls converted to allocas");
6694 for (
const auto &It : AllocationInfos)
6695 if (It.second->Status != AllocationInfo::INVALID)
6699 bool isAssumedHeapToStack(
const CallBase &CB)
const override {
6701 if (AllocationInfo *AI =
6702 AllocationInfos.lookup(
const_cast<CallBase *
>(&CB)))
6703 return AI->Status != AllocationInfo::INVALID;
6707 bool isAssumedHeapToStackRemovedFree(CallBase &CB)
const override {
6708 if (!isValidState())
6711 for (
const auto &It : AllocationInfos) {
6712 AllocationInfo &AI = *It.second;
6713 if (AI.Status == AllocationInfo::INVALID)
6716 if (AI.PotentialFreeCalls.count(&CB))
6724 assert(getState().isValidState() &&
6725 "Attempted to manifest an invalid state!");
6729 const auto *TLI =
A.getInfoCache().getTargetLibraryInfoForFunction(*
F);
6731 for (
auto &It : AllocationInfos) {
6732 AllocationInfo &AI = *It.second;
6733 if (AI.Status == AllocationInfo::INVALID)
6736 for (CallBase *FreeCall : AI.PotentialFreeCalls) {
6737 LLVM_DEBUG(
dbgs() <<
"H2S: Removing free call: " << *FreeCall <<
"\n");
6738 A.deleteAfterManifest(*FreeCall);
6739 HasChanged = ChangeStatus::CHANGED;
6742 LLVM_DEBUG(
dbgs() <<
"H2S: Removing malloc-like call: " << *AI.CB
6745 auto Remark = [&](OptimizationRemark
OR) {
6746 if (AI.IsGlobalizedLocal)
6747 return OR <<
"Moving globalized variable to the stack.";
6748 return OR <<
"Moving memory allocation from the heap to the stack.";
6750 if (AI.IsGlobalizedLocal)
6751 A.emitRemark<OptimizationRemark>(AI.CB,
"OMP110",
Remark);
6753 A.emitRemark<OptimizationRemark>(AI.CB,
"HeapToStack",
Remark);
6755 const DataLayout &
DL =
A.getInfoCache().getDL();
6757 std::optional<APInt> SizeAPI =
getSize(
A, *
this, AI);
6759 Size = ConstantInt::get(AI.CB->getContext(), *SizeAPI);
6761 ObjectSizeOpts Opts;
6762 ObjectSizeOffsetEvaluator Eval(*AI.CB->getModule(), TLI, Opts);
6763 SizeOffsetValue SizeOffsetPair = Eval.compute(AI.CB);
6770 ?
F->getEntryBlock().begin()
6771 : AI.CB->getIterator();
6774 if (MaybeAlign RetAlign = AI.CB->getRetAlign())
6775 Alignment = std::max(Alignment, *RetAlign);
6777 std::optional<APInt> AlignmentAPI = getAPInt(
A, *
this, *Align);
6778 assert(AlignmentAPI && AlignmentAPI->getZExtValue() > 0 &&
6779 "Expected an alignment during manifest!");
6781 std::max(Alignment,
assumeAligned(AlignmentAPI->getZExtValue()));
6785 unsigned AS =
DL.getAllocaAddrSpace();
6787 new AllocaInst(Type::getInt8Ty(
F->getContext()), AS,
Size, Alignment,
6788 AI.CB->getName() +
".h2s", IP);
6790 if (Alloca->
getType() != AI.CB->getType())
6791 Alloca = BitCastInst::CreatePointerBitCastOrAddrSpaceCast(
6792 Alloca, AI.CB->getType(),
"malloc_cast", AI.CB->getIterator());
6794 auto *I8Ty = Type::getInt8Ty(
F->getContext());
6797 "Must be able to materialize initial memory state of allocation");
6802 auto *NBB =
II->getNormalDest();
6804 A.deleteAfterManifest(*AI.CB);
6806 A.deleteAfterManifest(*AI.CB);
6815 Builder.CreateMemSet(Alloca, InitVal,
Size, std::nullopt);
6817 HasChanged = ChangeStatus::CHANGED;
6823 std::optional<APInt> getAPInt(Attributor &
A,
const AbstractAttribute &AA,
6825 bool UsedAssumedInformation =
false;
6826 std::optional<Constant *> SimpleV =
6827 A.getAssumedConstant(V, AA, UsedAssumedInformation);
6829 return APInt(64, 0);
6831 return CI->getValue();
6832 return std::nullopt;
6835 std::optional<APInt>
getSize(Attributor &
A,
const AbstractAttribute &AA,
6836 AllocationInfo &AI) {
6838 bool UsedAssumedInformation =
false;
6839 if (std::optional<Constant *> SimpleV =
6840 A.getAssumedConstant(*V, AA, UsedAssumedInformation))
6847 const auto *TLI =
A.getInfoCache().getTargetLibraryInfoForFunction(*
F);
6853 MapVector<CallBase *, AllocationInfo *> AllocationInfos;
6857 MapVector<CallBase *, DeallocationInfo *> DeallocationInfos;
6862ChangeStatus AAHeapToStackFunction::updateImpl(Attributor &
A) {
6865 const auto *TLI =
A.getInfoCache().getTargetLibraryInfoForFunction(*
F);
6867 const auto *LivenessAA =
6870 MustBeExecutedContextExplorer *Explorer =
6871 A.getInfoCache().getMustBeExecutedContextExplorer();
6873 bool StackIsAccessibleByOtherThreads =
6874 A.getInfoCache().stackIsAccessibleByOtherThreads();
6877 A.getInfoCache().getAnalysisResultForFunction<LoopAnalysis>(*F);
6878 std::optional<bool> MayContainIrreducibleControl;
6880 if (&
F->getEntryBlock() == &BB)
6882 if (!MayContainIrreducibleControl.has_value())
6884 if (*MayContainIrreducibleControl)
6893 bool HasUpdatedFrees =
false;
6895 auto UpdateFrees = [&]() {
6896 HasUpdatedFrees =
true;
6898 for (
auto &It : DeallocationInfos) {
6899 DeallocationInfo &DI = *It.second;
6902 if (DI.MightFreeUnknownObjects)
6906 bool UsedAssumedInformation =
false;
6907 if (
A.isAssumedDead(*DI.CB,
this, LivenessAA, UsedAssumedInformation,
6914 LLVM_DEBUG(
dbgs() <<
"[H2S] Unknown underlying object for free!\n");
6915 DI.MightFreeUnknownObjects =
true;
6928 DI.MightFreeUnknownObjects =
true;
6932 AllocationInfo *AI = AllocationInfos.lookup(ObjCB);
6934 LLVM_DEBUG(
dbgs() <<
"[H2S] Free of a non-allocation object: " << *Obj
6936 DI.MightFreeUnknownObjects =
true;
6940 DI.PotentialAllocationCalls.insert(ObjCB);
6944 auto FreeCheck = [&](AllocationInfo &AI) {
6948 if (!StackIsAccessibleByOtherThreads) {
6953 dbgs() <<
"[H2S] found an escaping use, stack is not accessible by "
6954 "other threads and function is not nosync:\n");
6958 if (!HasUpdatedFrees)
6962 if (AI.PotentialFreeCalls.size() != 1) {
6964 << AI.PotentialFreeCalls.size() <<
"\n");
6967 CallBase *UniqueFree = *AI.PotentialFreeCalls.begin();
6968 DeallocationInfo *DI = DeallocationInfos.lookup(UniqueFree);
6971 dbgs() <<
"[H2S] unique free call was not known as deallocation call "
6972 << *UniqueFree <<
"\n");
6975 if (DI->MightFreeUnknownObjects) {
6977 dbgs() <<
"[H2S] unique free call might free unknown allocations\n");
6980 if (DI->PotentialAllocationCalls.empty())
6982 if (DI->PotentialAllocationCalls.size() > 1) {
6984 << DI->PotentialAllocationCalls.size()
6985 <<
" different allocations\n");
6988 if (*DI->PotentialAllocationCalls.begin() != AI.CB) {
6991 <<
"[H2S] unique free call not known to free this allocation but "
6992 << **DI->PotentialAllocationCalls.begin() <<
"\n");
6997 if (!AI.IsGlobalizedLocal) {
6999 if (!Explorer || !Explorer->findInContextOf(UniqueFree, CtxI)) {
7000 LLVM_DEBUG(
dbgs() <<
"[H2S] unique free call might not be executed "
7001 "with the allocation "
7002 << *UniqueFree <<
"\n");
7009 auto UsesCheck = [&](AllocationInfo &AI) {
7010 bool ValidUsesOnly =
true;
7012 auto Pred = [&](
const Use &
U,
bool &Follow) ->
bool {
7017 if (
SI->getValueOperand() ==
U.get()) {
7019 <<
"[H2S] escaping store to memory: " << *UserI <<
"\n");
7020 ValidUsesOnly =
false;
7029 if (DeallocationInfos.count(CB)) {
7030 AI.PotentialFreeCalls.insert(CB);
7037 bool IsKnownNoCapture;
7046 if (!IsAssumedNoCapture ||
7047 (!AI.IsGlobalizedLocal && !IsAssumedNoFree)) {
7048 AI.HasPotentiallyFreeingUnknownUses |= !IsAssumedNoFree;
7051 auto Remark = [&](OptimizationRemarkMissed ORM) {
7053 <<
"Could not move globalized variable to the stack. "
7054 "Variable is potentially captured in call. Mark "
7055 "parameter as `__attribute__((noescape))` to override.";
7058 if (ValidUsesOnly && AI.IsGlobalizedLocal)
7059 A.emitRemark<OptimizationRemarkMissed>(CB,
"OMP113",
Remark);
7062 ValidUsesOnly =
false;
7075 ValidUsesOnly =
false;
7078 if (!
A.checkForAllUses(Pred, *
this, *AI.CB,
false,
7080 [&](
const Use &OldU,
const Use &NewU) {
7081 auto *SI = dyn_cast<StoreInst>(OldU.getUser());
7082 return !SI || StackIsAccessibleByOtherThreads ||
7083 AA::isAssumedThreadLocalObject(
7084 A, *SI->getPointerOperand(), *this);
7087 return ValidUsesOnly;
7092 for (
auto &It : AllocationInfos) {
7093 AllocationInfo &AI = *It.second;
7094 if (AI.Status == AllocationInfo::INVALID)
7098 std::optional<APInt> APAlign = getAPInt(
A, *
this, *Align);
7102 LLVM_DEBUG(
dbgs() <<
"[H2S] Unknown allocation alignment: " << *AI.CB
7104 AI.Status = AllocationInfo::INVALID;
7109 !APAlign->isPowerOf2()) {
7110 LLVM_DEBUG(
dbgs() <<
"[H2S] Invalid allocation alignment: " << APAlign
7112 AI.Status = AllocationInfo::INVALID;
7123 dbgs() <<
"[H2S] Unknown allocation size: " << *AI.CB <<
"\n";
7125 dbgs() <<
"[H2S] Allocation size too large: " << *AI.CB <<
" vs. "
7129 AI.Status = AllocationInfo::INVALID;
7135 switch (AI.Status) {
7136 case AllocationInfo::STACK_DUE_TO_USE:
7139 AI.Status = AllocationInfo::STACK_DUE_TO_FREE;
7141 case AllocationInfo::STACK_DUE_TO_FREE:
7144 AI.Status = AllocationInfo::INVALID;
7147 case AllocationInfo::INVALID:
7154 bool IsGlobalizedLocal = AI.IsGlobalizedLocal;
7155 if (AI.MoveAllocaIntoEntry &&
7156 (!
Size.has_value() ||
7157 (!IsGlobalizedLocal && IsInLoop(*AI.CB->getParent()))))
7158 AI.MoveAllocaIntoEntry =
false;
7167struct AAPrivatizablePtrImpl :
public AAPrivatizablePtr {
7168 AAPrivatizablePtrImpl(
const IRPosition &IRP, Attributor &
A)
7169 : AAPrivatizablePtr(IRP,
A), PrivatizableType(std::nullopt) {}
7172 AAPrivatizablePtr::indicatePessimisticFixpoint();
7173 PrivatizableType =
nullptr;
7174 return ChangeStatus::CHANGED;
7180 virtual std::optional<Type *> identifyPrivatizableType(Attributor &
A) = 0;
7184 std::optional<Type *> combineTypes(std::optional<Type *> T0,
7185 std::optional<Type *>
T1) {
7195 std::optional<Type *> getPrivatizableType()
const override {
7196 return PrivatizableType;
7199 const std::string getAsStr(Attributor *
A)
const override {
7200 return isAssumedPrivatizablePtr() ?
"[priv]" :
"[no-priv]";
7204 std::optional<Type *> PrivatizableType;
7209struct AAPrivatizablePtrArgument final :
public AAPrivatizablePtrImpl {
7210 AAPrivatizablePtrArgument(
const IRPosition &IRP, Attributor &
A)
7211 : AAPrivatizablePtrImpl(IRP,
A) {}
7213 std::optional<Type *> identifyPrivatizableType(Attributor &
A)
override {
7216 bool UsedAssumedInformation =
false;
7218 A.getAttrs(getIRPosition(), {Attribute::ByVal},
Attrs,
7220 if (!
Attrs.empty() &&
7221 A.checkForAllCallSites([](AbstractCallSite ACS) { return true; }, *
this,
7222 true, UsedAssumedInformation))
7223 return Attrs[0].getValueAsType();
7225 std::optional<Type *> Ty;
7226 unsigned ArgNo = getIRPosition().getCallSiteArgNo();
7234 auto CallSiteCheck = [&](AbstractCallSite ACS) {
7243 A.getAAFor<AAPrivatizablePtr>(*
this, ACSArgPos, DepClassTy::REQUIRED);
7246 std::optional<Type *> CSTy = PrivCSArgAA->getPrivatizableType();
7249 dbgs() <<
"[AAPrivatizablePtr] ACSPos: " << ACSArgPos <<
", CSTy: ";
7253 dbgs() <<
"<nullptr>";
7258 Ty = combineTypes(Ty, CSTy);
7261 dbgs() <<
" : New Type: ";
7263 (*Ty)->print(
dbgs());
7265 dbgs() <<
"<nullptr>";
7274 if (!
A.checkForAllCallSites(CallSiteCheck, *
this,
true,
7275 UsedAssumedInformation))
7281 PrivatizableType = identifyPrivatizableType(
A);
7282 if (!PrivatizableType)
7283 return ChangeStatus::UNCHANGED;
7284 if (!*PrivatizableType)
7285 return indicatePessimisticFixpoint();
7290 DepClassTy::OPTIONAL);
7293 if (!
A.hasAttr(getIRPosition(), Attribute::ByVal) &&
7296 return indicatePessimisticFixpoint();
7302 identifyReplacementTypes(*PrivatizableType, ReplacementTypes);
7306 Function &Fn = *getIRPosition().getAnchorScope();
7308 A.getInfoCache().getAnalysisResultForFunction<TargetIRAnalysis>(Fn);
7310 LLVM_DEBUG(
dbgs() <<
"[AAPrivatizablePtr] Missing TTI for function "
7312 return indicatePessimisticFixpoint();
7315 auto CallSiteCheck = [&](AbstractCallSite ACS) {
7322 bool UsedAssumedInformation =
false;
7323 if (!
A.checkForAllCallSites(CallSiteCheck, *
this,
true,
7324 UsedAssumedInformation)) {
7326 dbgs() <<
"[AAPrivatizablePtr] ABI incompatibility detected for "
7328 return indicatePessimisticFixpoint();
7332 Argument *Arg = getAssociatedArgument();
7333 if (!
A.isValidFunctionSignatureRewrite(*Arg, ReplacementTypes)) {
7335 return indicatePessimisticFixpoint();
7342 auto IsCompatiblePrivArgOfCallback = [&](CallBase &CB) {
7345 for (
const Use *U : CallbackUses) {
7346 AbstractCallSite CBACS(U);
7347 assert(CBACS && CBACS.isCallbackCall());
7348 for (Argument &CBArg : CBACS.getCalledFunction()->args()) {
7349 int CBArgNo = CBACS.getCallArgOperandNo(CBArg);
7353 <<
"[AAPrivatizablePtr] Argument " << *Arg
7354 <<
"check if can be privatized in the context of its parent ("
7356 <<
")\n[AAPrivatizablePtr] because it is an argument in a "
7358 << CBArgNo <<
"@" << CBACS.getCalledFunction()->getName()
7359 <<
")\n[AAPrivatizablePtr] " << CBArg <<
" : "
7360 << CBACS.getCallArgOperand(CBArg) <<
" vs "
7362 <<
"[AAPrivatizablePtr] " << CBArg <<
" : "
7363 << CBACS.getCallArgOperandNo(CBArg) <<
" vs " << ArgNo <<
"\n";
7366 if (CBArgNo !=
int(ArgNo))
7368 const auto *CBArgPrivAA =
A.getAAFor<AAPrivatizablePtr>(
7370 if (CBArgPrivAA && CBArgPrivAA->isValidState()) {
7371 auto CBArgPrivTy = CBArgPrivAA->getPrivatizableType();
7374 if (*CBArgPrivTy == PrivatizableType)
7379 dbgs() <<
"[AAPrivatizablePtr] Argument " << *Arg
7380 <<
" cannot be privatized in the context of its parent ("
7382 <<
")\n[AAPrivatizablePtr] because it is an argument in a "
7384 << CBArgNo <<
"@" << CBACS.getCalledFunction()->getName()
7385 <<
").\n[AAPrivatizablePtr] for which the argument "
7386 "privatization is not compatible.\n";
7396 auto IsCompatiblePrivArgOfDirectCS = [&](AbstractCallSite ACS) {
7400 "Expected a direct call operand for callback call operand");
7405 dbgs() <<
"[AAPrivatizablePtr] Argument " << *Arg
7406 <<
" check if be privatized in the context of its parent ("
7408 <<
")\n[AAPrivatizablePtr] because it is an argument in a "
7410 << DCArgNo <<
"@" << DCCallee->
getName() <<
").\n";
7413 if (
unsigned(DCArgNo) < DCCallee->
arg_size()) {
7414 const auto *DCArgPrivAA =
A.getAAFor<AAPrivatizablePtr>(
7416 DepClassTy::REQUIRED);
7417 if (DCArgPrivAA && DCArgPrivAA->isValidState()) {
7418 auto DCArgPrivTy = DCArgPrivAA->getPrivatizableType();
7421 if (*DCArgPrivTy == PrivatizableType)
7427 dbgs() <<
"[AAPrivatizablePtr] Argument " << *Arg
7428 <<
" cannot be privatized in the context of its parent ("
7430 <<
")\n[AAPrivatizablePtr] because it is an argument in a "
7433 <<
").\n[AAPrivatizablePtr] for which the argument "
7434 "privatization is not compatible.\n";
7442 auto IsCompatiblePrivArgOfOtherCallSite = [&](AbstractCallSite ACS) {
7446 return IsCompatiblePrivArgOfDirectCS(ACS);
7450 if (!
A.checkForAllCallSites(IsCompatiblePrivArgOfOtherCallSite, *
this,
true,
7451 UsedAssumedInformation))
7452 return indicatePessimisticFixpoint();
7454 return ChangeStatus::UNCHANGED;
7460 identifyReplacementTypes(
Type *PrivType,
7461 SmallVectorImpl<Type *> &ReplacementTypes) {
7464 assert(PrivType &&
"Expected privatizable type!");
7468 for (
unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++)
7469 ReplacementTypes.
push_back(PrivStructType->getElementType(u));
7471 ReplacementTypes.
append(PrivArrayType->getNumElements(),
7472 PrivArrayType->getElementType());
7483 assert(PrivType &&
"Expected privatizable type!");
7486 const DataLayout &
DL =
F.getDataLayout();
7490 const StructLayout *PrivStructLayout =
DL.getStructLayout(PrivStructType);
7491 for (
unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++) {
7494 new StoreInst(
F.getArg(ArgNo + u), Ptr, IP);
7497 Type *PointeeTy = PrivArrayType->getElementType();
7498 uint64_t PointeeTySize =
DL.getTypeStoreSize(PointeeTy);
7499 for (
unsigned u = 0, e = PrivArrayType->getNumElements(); u < e; u++) {
7501 new StoreInst(
F.getArg(ArgNo + u), Ptr, IP);
7504 new StoreInst(
F.getArg(ArgNo), &
Base, IP);
7510 void createReplacementValues(Align Alignment,
Type *PrivType,
7512 SmallVectorImpl<Value *> &ReplacementValues) {
7514 assert(PrivType &&
"Expected privatizable type!");
7522 const StructLayout *PrivStructLayout =
DL.getStructLayout(PrivStructType);
7523 for (
unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++) {
7524 Type *PointeeTy = PrivStructType->getElementType(u);
7527 LoadInst *
L =
new LoadInst(PointeeTy, Ptr,
"", IP->
getIterator());
7528 L->setAlignment(Alignment);
7532 Type *PointeeTy = PrivArrayType->getElementType();
7533 uint64_t PointeeTySize =
DL.getTypeStoreSize(PointeeTy);
7534 for (
unsigned u = 0, e = PrivArrayType->getNumElements(); u < e; u++) {
7536 LoadInst *
L =
new LoadInst(PointeeTy, Ptr,
"", IP->
getIterator());
7537 L->setAlignment(Alignment);
7542 L->setAlignment(Alignment);
7548 if (!PrivatizableType)
7549 return ChangeStatus::UNCHANGED;
7550 assert(*PrivatizableType &&
"Expected privatizable type!");
7556 bool UsedAssumedInformation =
false;
7557 if (!
A.checkForAllInstructions(
7558 [&](Instruction &
I) {
7559 CallInst &CI = cast<CallInst>(I);
7560 if (CI.isTailCall())
7561 TailCalls.push_back(&CI);
7564 *
this, {Instruction::Call}, UsedAssumedInformation))
7565 return ChangeStatus::UNCHANGED;
7567 Argument *Arg = getAssociatedArgument();
7570 const auto *AlignAA =
7577 [=](
const Attributor::ArgumentReplacementInfo &ARI,
7579 BasicBlock &EntryBB = ReplacementFn.getEntryBlock();
7581 const DataLayout &
DL = IP->getDataLayout();
7582 unsigned AS =
DL.getAllocaAddrSpace();
7583 Instruction *AI =
new AllocaInst(*PrivatizableType, AS,
7584 Arg->
getName() +
".priv", IP);
7585 createInitialization(*PrivatizableType, *AI, ReplacementFn,
7586 ArgIt->getArgNo(), IP);
7589 AI = BitCastInst::CreatePointerBitCastOrAddrSpaceCast(
7593 for (CallInst *CI : TailCalls)
7594 CI->setTailCall(
false);
7601 [=](
const Attributor::ArgumentReplacementInfo &ARI,
7602 AbstractCallSite ACS, SmallVectorImpl<Value *> &NewArgOperands) {
7605 createReplacementValues(
7606 AlignAA ? AlignAA->getAssumedAlign() :
Align(0),
7607 *PrivatizableType, ACS,
7615 identifyReplacementTypes(*PrivatizableType, ReplacementTypes);
7618 if (
A.registerFunctionSignatureRewrite(*Arg, ReplacementTypes,
7619 std::move(FnRepairCB),
7620 std::move(ACSRepairCB)))
7621 return ChangeStatus::CHANGED;
7622 return ChangeStatus::UNCHANGED;
7625 void trackStatistics()
const override {
7630struct AAPrivatizablePtrFloating :
public AAPrivatizablePtrImpl {
7631 AAPrivatizablePtrFloating(
const IRPosition &IRP, Attributor &
A)
7632 : AAPrivatizablePtrImpl(IRP,
A) {}
7636 indicatePessimisticFixpoint();
7641 "updateImpl will not be called");
7644 std::optional<Type *> identifyPrivatizableType(Attributor &
A)
override {
7647 LLVM_DEBUG(
dbgs() <<
"[AAPrivatizablePtr] No underlying object found!\n");
7654 return AI->getAllocatedType();
7656 auto *PrivArgAA =
A.getAAFor<AAPrivatizablePtr>(
7658 if (PrivArgAA && PrivArgAA->isAssumedPrivatizablePtr())
7659 return PrivArgAA->getPrivatizableType();
7662 LLVM_DEBUG(
dbgs() <<
"[AAPrivatizablePtr] Underlying object neither valid "
7663 "alloca nor privatizable argument: "
7668 void trackStatistics()
const override {
7673struct AAPrivatizablePtrCallSiteArgument final
7674 :
public AAPrivatizablePtrFloating {
7675 AAPrivatizablePtrCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
7676 : AAPrivatizablePtrFloating(IRP,
A) {}
7679 if (
A.hasAttr(getIRPosition(), Attribute::ByVal))
7680 indicateOptimisticFixpoint();
7684 PrivatizableType = identifyPrivatizableType(
A);
7685 if (!PrivatizableType)
7686 return ChangeStatus::UNCHANGED;
7687 if (!*PrivatizableType)
7688 return indicatePessimisticFixpoint();
7690 const IRPosition &IRP = getIRPosition();
7691 bool IsKnownNoCapture;
7693 A,
this, IRP, DepClassTy::REQUIRED, IsKnownNoCapture);
7694 if (!IsAssumedNoCapture) {
7695 LLVM_DEBUG(
dbgs() <<
"[AAPrivatizablePtr] pointer might be captured!\n");
7696 return indicatePessimisticFixpoint();
7699 bool IsKnownNoAlias;
7701 A,
this, IRP, DepClassTy::REQUIRED, IsKnownNoAlias)) {
7702 LLVM_DEBUG(
dbgs() <<
"[AAPrivatizablePtr] pointer might alias!\n");
7703 return indicatePessimisticFixpoint();
7708 LLVM_DEBUG(
dbgs() <<
"[AAPrivatizablePtr] pointer is written!\n");
7709 return indicatePessimisticFixpoint();
7712 return ChangeStatus::UNCHANGED;
7715 void trackStatistics()
const override {
7720struct AAPrivatizablePtrCallSiteReturned final
7721 :
public AAPrivatizablePtrFloating {
7722 AAPrivatizablePtrCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
7723 : AAPrivatizablePtrFloating(IRP,
A) {}
7727 indicatePessimisticFixpoint();
7730 void trackStatistics()
const override {
7735struct AAPrivatizablePtrReturned final :
public AAPrivatizablePtrFloating {
7736 AAPrivatizablePtrReturned(
const IRPosition &IRP, Attributor &
A)
7737 : AAPrivatizablePtrFloating(IRP,
A) {}
7741 indicatePessimisticFixpoint();
7744 void trackStatistics()
const override {
7754struct AAMemoryBehaviorImpl :
public AAMemoryBehavior {
7755 AAMemoryBehaviorImpl(
const IRPosition &IRP, Attributor &
A)
7756 : AAMemoryBehavior(IRP,
A) {}
7759 intersectAssumedBits(BEST_STATE);
7760 getKnownStateFromValue(
A, getIRPosition(), getState());
7761 AAMemoryBehavior::initialize(
A);
7765 static void getKnownStateFromValue(Attributor &
A,
const IRPosition &IRP,
7766 BitIntegerState &State,
7767 bool IgnoreSubsumingPositions =
false) {
7769 A.getAttrs(IRP, AttrKinds, Attrs, IgnoreSubsumingPositions);
7771 switch (Attr.getKindAsEnum()) {
7772 case Attribute::ReadNone:
7775 case Attribute::ReadOnly:
7778 case Attribute::WriteOnly:
7793 if (!
I->mayReadFromMemory())
7795 if (!
I->mayWriteToMemory())
7801 void getDeducedAttributes(Attributor &
A, LLVMContext &Ctx,
7802 SmallVectorImpl<Attribute> &Attrs)
const override {
7805 Attrs.push_back(Attribute::get(Ctx, Attribute::ReadNone));
7807 Attrs.push_back(Attribute::get(Ctx, Attribute::ReadOnly));
7808 else if (isAssumedWriteOnly())
7809 Attrs.push_back(Attribute::get(Ctx, Attribute::WriteOnly));
7814 const IRPosition &IRP = getIRPosition();
7816 if (
A.hasAttr(IRP, Attribute::ReadNone,
7818 return ChangeStatus::UNCHANGED;
7827 return ChangeStatus::UNCHANGED;
7830 A.removeAttrs(IRP, AttrKinds);
7833 A.removeAttrs(IRP, Attribute::Writable);
7839 const std::string getAsStr(Attributor *
A)
const override {
7844 if (isAssumedWriteOnly())
7846 return "may-read/write";
7850 static const Attribute::AttrKind AttrKinds[3];
7854 Attribute::ReadNone, Attribute::ReadOnly, Attribute::WriteOnly};
7857struct AAMemoryBehaviorFloating : AAMemoryBehaviorImpl {
7858 AAMemoryBehaviorFloating(
const IRPosition &IRP, Attributor &
A)
7859 : AAMemoryBehaviorImpl(IRP,
A) {}
7863 void trackStatistics()
const override {
7868 else if (isAssumedWriteOnly())
7875 bool followUsersOfUseIn(Attributor &
A,
const Use &U,
7876 const Instruction *UserI);
7879 void analyzeUseIn(Attributor &
A,
const Use &U,
const Instruction *UserI);
7883struct AAMemoryBehaviorArgument : AAMemoryBehaviorFloating {
7884 AAMemoryBehaviorArgument(
const IRPosition &IRP, Attributor &
A)
7885 : AAMemoryBehaviorFloating(IRP,
A) {}
7888 intersectAssumedBits(BEST_STATE);
7889 const IRPosition &IRP = getIRPosition();
7893 bool HasByVal =
A.hasAttr(IRP, {Attribute::ByVal},
7895 getKnownStateFromValue(
A, IRP, getState(),
7902 return ChangeStatus::UNCHANGED;
7906 if (
A.hasAttr(getIRPosition(),
7907 {Attribute::InAlloca, Attribute::Preallocated})) {
7908 removeKnownBits(NO_WRITES);
7909 removeAssumedBits(NO_WRITES);
7911 A.removeAttrs(getIRPosition(), AttrKinds);
7912 return AAMemoryBehaviorFloating::manifest(
A);
7915 void trackStatistics()
const override {
7920 else if (isAssumedWriteOnly())
7925struct AAMemoryBehaviorCallSiteArgument final : AAMemoryBehaviorArgument {
7926 AAMemoryBehaviorCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
7927 : AAMemoryBehaviorArgument(IRP,
A) {}
7932 Argument *Arg = getAssociatedArgument();
7934 indicatePessimisticFixpoint();
7938 addKnownBits(NO_WRITES);
7939 removeKnownBits(NO_READS);
7940 removeAssumedBits(NO_READS);
7942 AAMemoryBehaviorArgument::initialize(
A);
7943 if (getAssociatedFunction()->isDeclaration())
7944 indicatePessimisticFixpoint();
7952 Argument *Arg = getAssociatedArgument();
7955 A.getAAFor<AAMemoryBehavior>(*
this, ArgPos, DepClassTy::REQUIRED);
7957 return indicatePessimisticFixpoint();
7961 void trackStatistics()
const override {
7966 else if (isAssumedWriteOnly())
7972struct AAMemoryBehaviorCallSiteReturned final : AAMemoryBehaviorFloating {
7973 AAMemoryBehaviorCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
7974 : AAMemoryBehaviorFloating(IRP,
A) {}
7977 AAMemoryBehaviorImpl::initialize(
A);
7981 return ChangeStatus::UNCHANGED;
7984 void trackStatistics()
const override {}
7988struct AAMemoryBehaviorFunction final :
public AAMemoryBehaviorImpl {
7989 AAMemoryBehaviorFunction(
const IRPosition &IRP, Attributor &
A)
7990 : AAMemoryBehaviorImpl(IRP,
A) {}
8004 else if (isAssumedWriteOnly())
8007 A.removeAttrs(getIRPosition(), AttrKinds);
8010 for (Argument &Arg :
F.args())
8012 return A.manifestAttrs(getIRPosition(),
8013 Attribute::getWithMemoryEffects(
F.getContext(), ME));
8016 void trackStatistics()
const override {
8021 else if (isAssumedWriteOnly())
8027struct AAMemoryBehaviorCallSite final
8028 : AACalleeToCallSite<AAMemoryBehavior, AAMemoryBehaviorImpl> {
8029 AAMemoryBehaviorCallSite(
const IRPosition &IRP, Attributor &
A)
8030 : AACalleeToCallSite<AAMemoryBehavior, AAMemoryBehaviorImpl>(IRP,
A) {}
8040 else if (isAssumedWriteOnly())
8043 A.removeAttrs(getIRPosition(), AttrKinds);
8046 for (Use &U : CB.
args())
8048 Attribute::Writable);
8049 return A.manifestAttrs(
8050 getIRPosition(), Attribute::getWithMemoryEffects(CB.
getContext(), ME));
8053 void trackStatistics()
const override {
8058 else if (isAssumedWriteOnly())
8063ChangeStatus AAMemoryBehaviorFunction::updateImpl(Attributor &
A) {
8066 auto AssumedState = getAssumed();
8073 const auto *MemBehaviorAA =
A.getAAFor<AAMemoryBehavior>(
8075 if (MemBehaviorAA) {
8076 intersectAssumedBits(MemBehaviorAA->
getAssumed());
8077 return !isAtFixpoint();
8082 if (
I.mayReadFromMemory())
8083 removeAssumedBits(NO_READS);
8084 if (
I.mayWriteToMemory())
8085 removeAssumedBits(NO_WRITES);
8086 return !isAtFixpoint();
8089 bool UsedAssumedInformation =
false;
8090 if (!
A.checkForAllReadWriteInstructions(CheckRWInst, *
this,
8091 UsedAssumedInformation))
8092 return indicatePessimisticFixpoint();
8098ChangeStatus AAMemoryBehaviorFloating::updateImpl(Attributor &
A) {
8100 const IRPosition &IRP = getIRPosition();
8111 const auto *FnMemAA =
8114 FnMemAssumedState = FnMemAA->getAssumed();
8115 S.addKnownBits(FnMemAA->getKnown());
8116 if ((S.getAssumed() & FnMemAA->getAssumed()) == S.getAssumed())
8122 auto AssumedState = S.getAssumed();
8128 bool IsKnownNoCapture;
8129 const AANoCapture *ArgNoCaptureAA =
nullptr;
8134 if (!IsAssumedNoCapture &&
8136 S.intersectAssumedBits(FnMemAssumedState);
8142 auto UsePred = [&](
const Use &
U,
bool &Follow) ->
bool {
8144 LLVM_DEBUG(
dbgs() <<
"[AAMemoryBehavior] Use: " << *U <<
" in " << *UserI
8152 Follow = followUsersOfUseIn(
A, U, UserI);
8156 analyzeUseIn(
A, U, UserI);
8158 return !isAtFixpoint();
8161 if (!
A.checkForAllUses(UsePred, *
this, getAssociatedValue()))
8162 return indicatePessimisticFixpoint();
8168bool AAMemoryBehaviorFloating::followUsersOfUseIn(Attributor &
A,
const Use &U,
8169 const Instruction *UserI) {
8187 if (
U.get()->getType()->isPointerTy()) {
8189 bool IsKnownNoCapture;
8198void AAMemoryBehaviorFloating::analyzeUseIn(Attributor &
A,
const Use &U,
8199 const Instruction *UserI) {
8206 case Instruction::Load:
8208 removeAssumedBits(NO_READS);
8211 case Instruction::Store:
8216 removeAssumedBits(NO_WRITES);
8218 indicatePessimisticFixpoint();
8221 case Instruction::Call:
8222 case Instruction::CallBr:
8223 case Instruction::Invoke: {
8230 indicatePessimisticFixpoint();
8237 removeAssumedBits(NO_READS);
8244 if (
U.get()->getType()->isPointerTy())
8248 const auto *MemBehaviorAA =
8254 intersectAssumedBits(MemBehaviorAA->
getAssumed());
8262 removeAssumedBits(NO_READS);
8264 removeAssumedBits(NO_WRITES);
8276 return "all memory";
8279 std::string S =
"memory:";
8285 S +=
"internal global,";
8287 S +=
"external global,";
8291 S +=
"inaccessible,";
8305 AccessKind2Accesses.fill(
nullptr);
8308 ~AAMemoryLocationImpl()
override {
8311 for (AccessSet *AS : AccessKind2Accesses)
8317 intersectAssumedBits(BEST_STATE);
8318 getKnownStateFromValue(
A, getIRPosition(), getState());
8319 AAMemoryLocation::initialize(
A);
8323 static void getKnownStateFromValue(Attributor &
A,
const IRPosition &IRP,
8324 BitIntegerState &State,
8325 bool IgnoreSubsumingPositions =
false) {
8334 bool UseArgMemOnly =
true;
8336 if (AnchorFn &&
A.isRunOn(*AnchorFn))
8340 A.getAttrs(IRP, {Attribute::Memory},
Attrs, IgnoreSubsumingPositions);
8349 State.
addKnownBits(inverseLocation(NO_INACCESSIBLE_MEM,
true,
true));
8354 State.
addKnownBits(inverseLocation(NO_ARGUMENT_MEM,
true,
true));
8358 A.manifestAttrs(IRP,
8359 Attribute::getWithMemoryEffects(
8368 NO_INACCESSIBLE_MEM | NO_ARGUMENT_MEM,
true,
true));
8372 A.manifestAttrs(IRP,
8373 Attribute::getWithMemoryEffects(
8382 void getDeducedAttributes(Attributor &
A, LLVMContext &Ctx,
8383 SmallVectorImpl<Attribute> &Attrs)
const override {
8390 else if (isAssumedInaccessibleMemOnly())
8391 Attrs.push_back(Attribute::getWithMemoryEffects(
8393 else if (isAssumedArgMemOnly())
8396 else if (isAssumedInaccessibleOrArgMemOnly())
8397 Attrs.push_back(Attribute::getWithMemoryEffects(
8406 const IRPosition &IRP = getIRPosition();
8410 if (DeducedAttrs.
size() != 1)
8411 return ChangeStatus::UNCHANGED;
8414 return A.manifestAttrs(IRP, Attribute::getWithMemoryEffects(
8418 bool checkForAllAccessesToMemoryKind(
8420 MemoryLocationsKind)>
8422 MemoryLocationsKind RequestedMLK)
const override {
8423 if (!isValidState())
8426 MemoryLocationsKind AssumedMLK = getAssumedNotAccessedLocation();
8427 if (AssumedMLK == NO_LOCATIONS)
8431 for (MemoryLocationsKind CurMLK = 1; CurMLK < NO_LOCATIONS;
8432 CurMLK *= 2, ++
Idx) {
8433 if (CurMLK & RequestedMLK)
8436 if (
const AccessSet *
Accesses = AccessKind2Accesses[Idx])
8437 for (
const AccessInfo &AI : *
Accesses)
8438 if (!Pred(AI.I, AI.Ptr, AI.Kind, CurMLK))
8451 MemoryLocationsKind KnownMLK = getKnown();
8453 for (MemoryLocationsKind CurMLK = 1; CurMLK < NO_LOCATIONS; CurMLK *= 2)
8454 if (!(CurMLK & KnownMLK))
8455 updateStateAndAccessesMap(getState(), CurMLK,
I,
nullptr,
Changed,
8456 getAccessKindFromInst(
I));
8457 return AAMemoryLocation::indicatePessimisticFixpoint();
8477 bool operator()(
const AccessInfo &
LHS,
const AccessInfo &
RHS)
const {
8481 return LHS.Ptr <
RHS.Ptr;
8482 if (
LHS.Kind !=
RHS.Kind)
8483 return LHS.Kind <
RHS.Kind;
8490 using AccessSet = SmallSet<AccessInfo, 2, AccessInfo>;
8491 std::array<AccessSet *, llvm::ConstantLog2<VALID_STATE>()>
8492 AccessKind2Accesses;
8497 categorizeArgumentPointerLocations(Attributor &
A, CallBase &CB,
8498 AAMemoryLocation::StateType &AccessedLocs,
8503 categorizeAccessedLocations(Attributor &
A, Instruction &
I,
bool &
Changed);
8506 AccessKind getAccessKindFromInst(
const Instruction *
I) {
8509 AK =
I->mayReadFromMemory() ? READ :
NONE;
8518 void updateStateAndAccessesMap(AAMemoryLocation::StateType &State,
8519 MemoryLocationsKind MLK,
const Instruction *
I,
8528 if (MLK == NO_UNKOWN_MEM)
8530 State.removeAssumedBits(MLK);
8535 void categorizePtrValue(Attributor &
A,
const Instruction &
I,
const Value &Ptr,
8536 AAMemoryLocation::StateType &State,
bool &
Changed,
8537 unsigned AccessAS = 0);
8543void AAMemoryLocationImpl::categorizePtrValue(
8544 Attributor &
A,
const Instruction &
I,
const Value &Ptr,
8546 LLVM_DEBUG(
dbgs() <<
"[AAMemoryLocation] Categorize pointer locations for "
8551 unsigned ObjectAS =
Obj.getType()->getPointerAddressSpace();
8553 MemoryLocationsKind MLK = NO_LOCATIONS;
8573 MLK = NO_ARGUMENT_MEM;
8579 if (GVar->isConstant())
8582 if (GV->hasLocalLinkage())
8583 MLK = NO_GLOBAL_INTERNAL_MEM;
8585 MLK = NO_GLOBAL_EXTERNAL_MEM;
8594 bool IsKnownNoAlias;
8598 MLK = NO_MALLOCED_MEM;
8600 MLK = NO_UNKOWN_MEM;
8602 MLK = NO_UNKOWN_MEM;
8605 assert(MLK != NO_LOCATIONS &&
"No location specified!");
8606 LLVM_DEBUG(
dbgs() <<
"[AAMemoryLocation] Ptr value can be categorized: "
8607 << Obj <<
" -> " << getMemoryLocationsAsStr(MLK) <<
"\n");
8609 getAccessKindFromInst(&
I));
8614 const auto *AA =
A.getAAFor<AAUnderlyingObjects>(
8618 dbgs() <<
"[AAMemoryLocation] Pointer locations not categorized\n");
8619 updateStateAndAccessesMap(
State, NO_UNKOWN_MEM, &
I,
nullptr,
Changed,
8620 getAccessKindFromInst(&
I));
8625 dbgs() <<
"[AAMemoryLocation] Accessed locations with pointer locations: "
8629void AAMemoryLocationImpl::categorizeArgumentPointerLocations(
8632 for (
unsigned ArgNo = 0,
E = CB.
arg_size(); ArgNo <
E; ++ArgNo) {
8641 const auto *ArgOpMemLocationAA =
8644 if (ArgOpMemLocationAA && ArgOpMemLocationAA->isAssumedReadNone())
8649 categorizePtrValue(
A, CB, *ArgOp, AccessedLocs,
Changed);
8654AAMemoryLocationImpl::categorizeAccessedLocations(Attributor &
A, Instruction &
I,
8656 LLVM_DEBUG(
dbgs() <<
"[AAMemoryLocation] Categorize accessed locations for "
8660 AccessedLocs.intersectAssumedBits(NO_LOCATIONS);
8665 const auto *CBMemLocationAA =
A.getAAFor<AAMemoryLocation>(
8668 <<
" [" << CBMemLocationAA <<
"]\n");
8669 if (!CBMemLocationAA) {
8670 updateStateAndAccessesMap(AccessedLocs, NO_UNKOWN_MEM, &
I,
nullptr,
8671 Changed, getAccessKindFromInst(&
I));
8672 return NO_UNKOWN_MEM;
8675 if (CBMemLocationAA->isAssumedReadNone())
8676 return NO_LOCATIONS;
8678 if (CBMemLocationAA->isAssumedInaccessibleMemOnly()) {
8679 updateStateAndAccessesMap(AccessedLocs, NO_INACCESSIBLE_MEM, &
I,
nullptr,
8680 Changed, getAccessKindFromInst(&
I));
8681 return AccessedLocs.getAssumed();
8684 uint32_t CBAssumedNotAccessedLocs =
8685 CBMemLocationAA->getAssumedNotAccessedLocation();
8688 uint32_t CBAssumedNotAccessedLocsNoArgMem =
8689 CBAssumedNotAccessedLocs | NO_ARGUMENT_MEM | NO_GLOBAL_MEM;
8691 for (MemoryLocationsKind CurMLK = 1; CurMLK < NO_LOCATIONS; CurMLK *= 2) {
8692 if (CBAssumedNotAccessedLocsNoArgMem & CurMLK)
8694 updateStateAndAccessesMap(AccessedLocs, CurMLK, &
I,
nullptr,
Changed,
8695 getAccessKindFromInst(&
I));
8700 bool HasGlobalAccesses = ((~CBAssumedNotAccessedLocs) & NO_GLOBAL_MEM);
8701 if (HasGlobalAccesses) {
8704 updateStateAndAccessesMap(AccessedLocs, MLK, &
I, Ptr,
Changed,
8705 getAccessKindFromInst(&
I));
8708 if (!CBMemLocationAA->checkForAllAccessesToMemoryKind(
8709 AccessPred, inverseLocation(NO_GLOBAL_MEM,
false,
false)))
8710 return AccessedLocs.getWorstState();
8714 dbgs() <<
"[AAMemoryLocation] Accessed state before argument handling: "
8715 << getMemoryLocationsAsStr(AccessedLocs.getAssumed()) <<
"\n");
8718 bool HasArgAccesses = ((~CBAssumedNotAccessedLocs) & NO_ARGUMENT_MEM);
8720 categorizeArgumentPointerLocations(
A, *CB, AccessedLocs,
Changed);
8723 dbgs() <<
"[AAMemoryLocation] Accessed state after argument handling: "
8724 << getMemoryLocationsAsStr(AccessedLocs.getAssumed()) <<
"\n");
8726 return AccessedLocs.getAssumed();
8731 dbgs() <<
"[AAMemoryLocation] Categorize memory access with pointer: "
8732 <<
I <<
" [" << *Ptr <<
"]\n");
8733 categorizePtrValue(
A,
I, *Ptr, AccessedLocs,
Changed,
8734 Ptr->getType()->getPointerAddressSpace());
8735 return AccessedLocs.getAssumed();
8738 LLVM_DEBUG(
dbgs() <<
"[AAMemoryLocation] Failed to categorize instruction: "
8740 updateStateAndAccessesMap(AccessedLocs, NO_UNKOWN_MEM, &
I,
nullptr,
Changed,
8741 getAccessKindFromInst(&
I));
8742 return AccessedLocs.getAssumed();
8746struct AAMemoryLocationFunction final :
public AAMemoryLocationImpl {
8747 AAMemoryLocationFunction(
const IRPosition &IRP, Attributor &
A)
8748 : AAMemoryLocationImpl(IRP,
A) {}
8752 const auto *MemBehaviorAA =
8753 A.getAAFor<AAMemoryBehavior>(*
this, getIRPosition(), DepClassTy::NONE);
8756 return indicateOptimisticFixpoint();
8758 "AAMemoryLocation was not read-none but AAMemoryBehavior was!");
8759 A.recordDependence(*MemBehaviorAA, *
this, DepClassTy::OPTIONAL);
8760 return ChangeStatus::UNCHANGED;
8764 auto AssumedState = getAssumed();
8768 MemoryLocationsKind MLK = categorizeAccessedLocations(
A,
I,
Changed);
8769 LLVM_DEBUG(
dbgs() <<
"[AAMemoryLocation] Accessed locations for " <<
I
8770 <<
": " << getMemoryLocationsAsStr(MLK) <<
"\n");
8771 removeAssumedBits(inverseLocation(MLK,
false,
false));
8774 return getAssumedNotAccessedLocation() != VALID_STATE;
8777 bool UsedAssumedInformation =
false;
8778 if (!
A.checkForAllReadWriteInstructions(CheckRWInst, *
this,
8779 UsedAssumedInformation))
8780 return indicatePessimisticFixpoint();
8782 Changed |= AssumedState != getAssumed();
8783 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
8786 void trackStatistics()
const override {
8789 else if (isAssumedArgMemOnly())
8791 else if (isAssumedInaccessibleMemOnly())
8793 else if (isAssumedInaccessibleOrArgMemOnly())
8799struct AAMemoryLocationCallSite final : AAMemoryLocationImpl {
8800 AAMemoryLocationCallSite(
const IRPosition &IRP, Attributor &
A)
8801 : AAMemoryLocationImpl(IRP,
A) {}
8811 A.getAAFor<AAMemoryLocation>(*
this, FnPos, DepClassTy::REQUIRED);
8813 return indicatePessimisticFixpoint();
8817 updateStateAndAccessesMap(getState(), MLK,
I, Ptr,
Changed,
8818 getAccessKindFromInst(
I));
8821 if (!FnAA->checkForAllAccessesToMemoryKind(AccessPred, ALL_LOCATIONS))
8822 return indicatePessimisticFixpoint();
8823 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
8826 void trackStatistics()
const override {
8836struct AADenormalFPMathImpl :
public AADenormalFPMath {
8837 AADenormalFPMathImpl(
const IRPosition &IRP, Attributor &
A)
8838 : AADenormalFPMath(IRP,
A) {}
8840 const std::string getAsStr(Attributor *
A)
const override {
8841 std::string Str(
"AADenormalFPMath[");
8842 raw_string_ostream OS(Str);
8844 DenormalState
Known = getKnown();
8845 if (
Known.Mode.isValid())
8846 OS <<
"denormal-fp-math=" <<
Known.Mode;
8850 if (
Known.ModeF32.isValid())
8851 OS <<
" denormal-fp-math-f32=" <<
Known.ModeF32;
8857struct AADenormalFPMathFunction final : AADenormalFPMathImpl {
8858 AADenormalFPMathFunction(
const IRPosition &IRP, Attributor &
A)
8859 : AADenormalFPMathImpl(IRP,
A) {}
8863 DenormalFPEnv DenormEnv =
F->getDenormalFPEnv();
8873 auto CheckCallSite = [=, &Change, &
A](AbstractCallSite CS) {
8876 <<
"->" << getAssociatedFunction()->
getName() <<
'\n');
8878 const auto *CallerInfo =
A.getAAFor<AADenormalFPMath>(
8884 CallerInfo->getState());
8888 bool AllCallSitesKnown =
true;
8889 if (!
A.checkForAllCallSites(CheckCallSite, *
this,
true, AllCallSitesKnown))
8890 return indicatePessimisticFixpoint();
8892 if (Change == ChangeStatus::CHANGED && isModeFixed())
8898 LLVMContext &Ctx = getAssociatedFunction()->getContext();
8904 DenormalFPEnv KnownEnv(
Known.Mode,
Known.ModeF32);
8907 AttrToRemove.
push_back(Attribute::DenormalFPEnv);
8910 Ctx, Attribute::DenormalFPEnv,
8911 DenormalFPEnv(
Known.Mode,
Known.ModeF32).toIntValue()));
8914 auto &IRP = getIRPosition();
8917 return A.removeAttrs(IRP, AttrToRemove) |
8918 A.manifestAttrs(IRP, AttrToAdd,
true);
8921 void trackStatistics()
const override {
8930struct AAValueConstantRangeImpl : AAValueConstantRange {
8931 using StateType = IntegerRangeState;
8932 AAValueConstantRangeImpl(
const IRPosition &IRP, Attributor &
A)
8933 : AAValueConstantRange(IRP,
A) {}
8936 if (
A.hasSimplificationCallback(getIRPosition())) {
8937 indicatePessimisticFixpoint();
8942 intersectKnown(getConstantRangeFromSCEV(
A, getCtxI()));
8945 intersectKnown(getConstantRangeFromLVI(
A, getCtxI()));
8948 const std::string getAsStr(Attributor *
A)
const override {
8950 llvm::raw_string_ostream OS(Str);
8952 getKnown().print(OS);
8954 getAssumed().print(OS);
8961 const SCEV *getSCEV(Attributor &
A,
const Instruction *
I =
nullptr)
const {
8962 if (!getAnchorScope())
8965 ScalarEvolution *SE =
8966 A.getInfoCache().getAnalysisResultForFunction<ScalarEvolutionAnalysis>(
8969 LoopInfo *LI =
A.getInfoCache().getAnalysisResultForFunction<LoopAnalysis>(
8975 const SCEV *S = SE->
getSCEV(&getAssociatedValue());
8984 ConstantRange getConstantRangeFromSCEV(Attributor &
A,
8985 const Instruction *
I =
nullptr)
const {
8986 if (!getAnchorScope())
8989 ScalarEvolution *SE =
8990 A.getInfoCache().getAnalysisResultForFunction<ScalarEvolutionAnalysis>(
8993 const SCEV *S = getSCEV(
A,
I);
9003 getConstantRangeFromLVI(Attributor &
A,
9004 const Instruction *CtxI =
nullptr)
const {
9005 if (!getAnchorScope())
9008 LazyValueInfo *LVI =
9009 A.getInfoCache().getAnalysisResultForFunction<LazyValueAnalysis>(
9024 bool isValidCtxInstructionForOutsideAnalysis(Attributor &
A,
9025 const Instruction *CtxI,
9026 bool AllowAACtxI)
const {
9027 if (!CtxI || (!AllowAACtxI && CtxI == getCtxI()))
9039 InformationCache &InfoCache =
A.getInfoCache();
9040 const DominatorTree *DT =
9050 getAssumedConstantRange(Attributor &
A,
9051 const Instruction *CtxI =
nullptr)
const override {
9056 if (!isValidCtxInstructionForOutsideAnalysis(
A, CtxI,
9058 return getAssumed();
9060 ConstantRange LVIR = getConstantRangeFromLVI(
A, CtxI);
9061 ConstantRange SCEVR = getConstantRangeFromSCEV(
A, CtxI);
9062 return getAssumed().intersectWith(SCEVR).intersectWith(LVIR);
9067 getMDNodeForConstantRange(
Type *Ty, LLVMContext &Ctx,
9068 const ConstantRange &AssumedConstantRange) {
9070 Ty, AssumedConstantRange.
getLower())),
9072 Ty, AssumedConstantRange.
getUpper()))};
9077 static bool isBetterRange(
const ConstantRange &Assumed,
9078 const Instruction &
I) {
9082 std::optional<ConstantRange>
Known;
9086 }
else if (MDNode *KnownRanges =
I.getMetadata(LLVMContext::MD_range)) {
9092 if (KnownRanges->getNumOperands() > 2)
9095 ConstantInt *
Lower =
9097 ConstantInt *
Upper =
9107 setRangeMetadataIfisBetterRange(Instruction *
I,
9108 const ConstantRange &AssumedConstantRange) {
9109 if (isBetterRange(AssumedConstantRange, *
I)) {
9110 I->setMetadata(LLVMContext::MD_range,
9111 getMDNodeForConstantRange(
I->getType(),
I->getContext(),
9112 AssumedConstantRange));
9119 setRangeRetAttrIfisBetterRange(Attributor &
A,
const IRPosition &IRP,
9121 const ConstantRange &AssumedConstantRange) {
9122 if (isBetterRange(AssumedConstantRange, *
I)) {
9123 A.manifestAttrs(IRP,
9124 Attribute::get(
I->getContext(), Attribute::Range,
9125 AssumedConstantRange),
9134 ConstantRange AssumedConstantRange = getAssumedConstantRange(
A);
9137 auto &
V = getAssociatedValue();
9141 assert(
I == getCtxI() &&
"Should not annotate an instruction which is "
9142 "not the context instruction");
9144 if (setRangeMetadataIfisBetterRange(
I, AssumedConstantRange))
9145 Changed = ChangeStatus::CHANGED;
9147 if (setRangeRetAttrIfisBetterRange(
A, getIRPosition(),
I,
9148 AssumedConstantRange))
9149 Changed = ChangeStatus::CHANGED;
9157struct AAValueConstantRangeArgument final
9158 : AAArgumentFromCallSiteArguments<
9159 AAValueConstantRange, AAValueConstantRangeImpl, IntegerRangeState,
9161 using Base = AAArgumentFromCallSiteArguments<
9162 AAValueConstantRange, AAValueConstantRangeImpl, IntegerRangeState,
9164 AAValueConstantRangeArgument(
const IRPosition &IRP, Attributor &
A)
9167 void trackStatistics()
const override {
9172struct AAValueConstantRangeReturned
9173 : AAReturnedFromReturnedValues<AAValueConstantRange,
9174 AAValueConstantRangeImpl,
9175 AAValueConstantRangeImpl::StateType,
9178 AAReturnedFromReturnedValues<AAValueConstantRange,
9179 AAValueConstantRangeImpl,
9180 AAValueConstantRangeImpl::StateType,
9182 AAValueConstantRangeReturned(
const IRPosition &IRP, Attributor &
A)
9186 if (!
A.isFunctionIPOAmendable(*getAssociatedFunction()))
9187 indicatePessimisticFixpoint();
9190 void trackStatistics()
const override {
9195struct AAValueConstantRangeFloating : AAValueConstantRangeImpl {
9196 AAValueConstantRangeFloating(
const IRPosition &IRP, Attributor &
A)
9197 : AAValueConstantRangeImpl(IRP,
A) {}
9200 AAValueConstantRangeImpl::initialize(
A);
9204 Value &
V = getAssociatedValue();
9207 unionAssumed(ConstantRange(
C->getValue()));
9208 indicateOptimisticFixpoint();
9214 unionAssumed(ConstantRange(APInt(
getBitWidth(), 0)));
9215 indicateOptimisticFixpoint();
9227 if (
auto *RangeMD = LI->getMetadata(LLVMContext::MD_range)) {
9238 indicatePessimisticFixpoint();
9241 << getAssociatedValue() <<
"\n");
9244 bool calculateBinaryOperator(
9245 Attributor &
A, BinaryOperator *BinOp, IntegerRangeState &
T,
9246 const Instruction *CtxI,
9247 SmallVectorImpl<const AAValueConstantRange *> &QuerriedAAs) {
9252 bool UsedAssumedInformation =
false;
9253 const auto &SimplifiedLHS =
A.getAssumedSimplified(
9256 if (!SimplifiedLHS.has_value())
9258 if (!*SimplifiedLHS)
9260 LHS = *SimplifiedLHS;
9262 const auto &SimplifiedRHS =
A.getAssumedSimplified(
9265 if (!SimplifiedRHS.has_value())
9267 if (!*SimplifiedRHS)
9269 RHS = *SimplifiedRHS;
9275 auto *LHSAA =
A.getAAFor<AAValueConstantRange>(
9277 DepClassTy::REQUIRED);
9281 auto LHSAARange = LHSAA->getAssumedConstantRange(
A, CtxI);
9283 auto *RHSAA =
A.getAAFor<AAValueConstantRange>(
9285 DepClassTy::REQUIRED);
9289 auto RHSAARange = RHSAA->getAssumedConstantRange(
A, CtxI);
9291 auto AssumedRange = LHSAARange.binaryOp(BinOp->
getOpcode(), RHSAARange);
9293 T.unionAssumed(AssumedRange);
9297 return T.isValidState();
9300 bool calculateCastInst(
9301 Attributor &
A, CastInst *CastI, IntegerRangeState &
T,
9302 const Instruction *CtxI,
9303 SmallVectorImpl<const AAValueConstantRange *> &QuerriedAAs) {
9309 bool UsedAssumedInformation =
false;
9310 const auto &SimplifiedOpV =
A.getAssumedSimplified(
9313 if (!SimplifiedOpV.has_value())
9315 if (!*SimplifiedOpV)
9317 OpV = *SimplifiedOpV;
9322 auto *OpAA =
A.getAAFor<AAValueConstantRange>(
9324 DepClassTy::REQUIRED);
9328 T.unionAssumed(OpAA->getAssumed().castOp(CastI->
getOpcode(),
9330 return T.isValidState();
9334 calculateCmpInst(Attributor &
A, CmpInst *CmpI, IntegerRangeState &
T,
9335 const Instruction *CtxI,
9336 SmallVectorImpl<const AAValueConstantRange *> &QuerriedAAs) {
9341 bool UsedAssumedInformation =
false;
9342 const auto &SimplifiedLHS =
A.getAssumedSimplified(
9345 if (!SimplifiedLHS.has_value())
9347 if (!*SimplifiedLHS)
9349 LHS = *SimplifiedLHS;
9351 const auto &SimplifiedRHS =
A.getAssumedSimplified(
9354 if (!SimplifiedRHS.has_value())
9356 if (!*SimplifiedRHS)
9358 RHS = *SimplifiedRHS;
9364 auto *LHSAA =
A.getAAFor<AAValueConstantRange>(
9366 DepClassTy::REQUIRED);
9370 auto *RHSAA =
A.getAAFor<AAValueConstantRange>(
9372 DepClassTy::REQUIRED);
9376 auto LHSAARange = LHSAA->getAssumedConstantRange(
A, CtxI);
9377 auto RHSAARange = RHSAA->getAssumedConstantRange(
A, CtxI);
9380 if (LHSAARange.isEmptySet() || RHSAARange.isEmptySet())
9383 bool MustTrue =
false, MustFalse =
false;
9385 auto AllowedRegion =
9388 if (AllowedRegion.intersectWith(LHSAARange).isEmptySet())
9394 assert((!MustTrue || !MustFalse) &&
9395 "Either MustTrue or MustFalse should be false!");
9398 T.unionAssumed(ConstantRange(APInt( 1, 1)));
9400 T.unionAssumed(ConstantRange(APInt( 1, 0)));
9402 T.unionAssumed(ConstantRange( 1,
true));
9404 LLVM_DEBUG(
dbgs() <<
"[AAValueConstantRange] " << *CmpI <<
" after "
9405 << (MustTrue ?
"true" : (MustFalse ?
"false" :
"unknown"))
9406 <<
": " <<
T <<
"\n\t" << *LHSAA <<
"\t<op>\n\t"
9410 return T.isValidState();
9421 bool UsedAssumedInformation =
false;
9422 const auto &SimplifiedOpV =
A.getAssumedSimplified(
9425 if (!SimplifiedOpV.has_value())
9427 if (!*SimplifiedOpV)
9429 Value *VPtr = *SimplifiedOpV;
9432 const auto *AA =
A.getAAFor<AAValueConstantRange>(
9434 DepClassTy::REQUIRED);
9438 T.unionAssumed(AA->getAssumedConstantRange(
A, CtxI));
9442 return T.isValidState();
9447 if (!calculateBinaryOperator(
A, BinOp,
T, CtxI, QuerriedAAs))
9450 if (!calculateCmpInst(
A, CmpI,
T, CtxI, QuerriedAAs))
9453 if (!calculateCastInst(
A, CastI,
T, CtxI, QuerriedAAs))
9459 T.indicatePessimisticFixpoint();
9466 for (
const AAValueConstantRange *QueriedAA : QuerriedAAs) {
9467 if (QueriedAA !=
this)
9470 if (
T.getAssumed() == getState().getAssumed())
9472 T.indicatePessimisticFixpoint();
9475 return T.isValidState();
9478 if (!VisitValueCB(getAssociatedValue(), getCtxI()))
9479 return indicatePessimisticFixpoint();
9484 return ChangeStatus::UNCHANGED;
9485 if (++NumChanges > MaxNumChanges) {
9486 LLVM_DEBUG(
dbgs() <<
"[AAValueConstantRange] performed " << NumChanges
9487 <<
" but only " << MaxNumChanges
9488 <<
" are allowed to avoid cyclic reasoning.");
9489 return indicatePessimisticFixpoint();
9491 return ChangeStatus::CHANGED;
9494 void trackStatistics()
const override {
9503 static constexpr int MaxNumChanges = 5;
9506struct AAValueConstantRangeFunction : AAValueConstantRangeImpl {
9507 AAValueConstantRangeFunction(
const IRPosition &IRP, Attributor &
A)
9508 : AAValueConstantRangeImpl(IRP,
A) {}
9511 llvm_unreachable(
"AAValueConstantRange(Function|CallSite)::updateImpl will "
9518struct AAValueConstantRangeCallSite : AAValueConstantRangeFunction {
9519 AAValueConstantRangeCallSite(
const IRPosition &IRP, Attributor &
A)
9520 : AAValueConstantRangeFunction(IRP,
A) {}
9525struct AAValueConstantRangeCallSiteReturned
9526 : AACalleeToCallSite<AAValueConstantRange, AAValueConstantRangeImpl,
9527 AAValueConstantRangeImpl::StateType,
9529 AAValueConstantRangeCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
9530 : AACalleeToCallSite<AAValueConstantRange, AAValueConstantRangeImpl,
9531 AAValueConstantRangeImpl::StateType,
9537 if (std::optional<ConstantRange>
Range = CI->getRange())
9538 intersectKnown(*
Range);
9541 AAValueConstantRangeImpl::initialize(
A);
9544 void trackStatistics()
const override {
9548struct AAValueConstantRangeCallSiteArgument : AAValueConstantRangeFloating {
9549 AAValueConstantRangeCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
9550 : AAValueConstantRangeFloating(IRP,
A) {}
9553 return ChangeStatus::UNCHANGED;
9556 void trackStatistics()
const override {
9565struct AAPotentialConstantValuesImpl : AAPotentialConstantValues {
9568 AAPotentialConstantValuesImpl(
const IRPosition &IRP, Attributor &
A)
9569 : AAPotentialConstantValues(IRP,
A) {}
9572 if (
A.hasSimplificationCallback(getIRPosition()))
9573 indicatePessimisticFixpoint();
9575 AAPotentialConstantValues::initialize(
A);
9578 bool fillSetWithConstantValues(Attributor &
A,
const IRPosition &IRP, SetTy &S,
9579 bool &ContainsUndef,
bool ForSelf) {
9581 bool UsedAssumedInformation =
false;
9583 UsedAssumedInformation)) {
9590 auto *PotentialValuesAA =
A.getAAFor<AAPotentialConstantValues>(
9591 *
this, IRP, DepClassTy::REQUIRED);
9592 if (!PotentialValuesAA || !PotentialValuesAA->getState().isValidState())
9594 ContainsUndef = PotentialValuesAA->getState().undefIsContained();
9595 S = PotentialValuesAA->getState().getAssumedSet();
9602 ContainsUndef =
false;
9603 for (
auto &It :
Values) {
9605 ContainsUndef =
true;
9611 S.insert(CI->getValue());
9613 ContainsUndef &= S.empty();
9618 const std::string getAsStr(Attributor *
A)
const override {
9620 llvm::raw_string_ostream OS(Str);
9626 return indicatePessimisticFixpoint();
9630struct AAPotentialConstantValuesArgument final
9631 : AAArgumentFromCallSiteArguments<AAPotentialConstantValues,
9632 AAPotentialConstantValuesImpl,
9633 PotentialConstantIntValuesState> {
9634 using Base = AAArgumentFromCallSiteArguments<AAPotentialConstantValues,
9635 AAPotentialConstantValuesImpl,
9637 AAPotentialConstantValuesArgument(
const IRPosition &IRP, Attributor &
A)
9640 void trackStatistics()
const override {
9645struct AAPotentialConstantValuesReturned
9646 : AAReturnedFromReturnedValues<AAPotentialConstantValues,
9647 AAPotentialConstantValuesImpl> {
9648 using Base = AAReturnedFromReturnedValues<AAPotentialConstantValues,
9649 AAPotentialConstantValuesImpl>;
9650 AAPotentialConstantValuesReturned(
const IRPosition &IRP, Attributor &
A)
9654 if (!
A.isFunctionIPOAmendable(*getAssociatedFunction()))
9655 indicatePessimisticFixpoint();
9656 Base::initialize(
A);
9659 void trackStatistics()
const override {
9664struct AAPotentialConstantValuesFloating : AAPotentialConstantValuesImpl {
9665 AAPotentialConstantValuesFloating(
const IRPosition &IRP, Attributor &
A)
9666 : AAPotentialConstantValuesImpl(IRP,
A) {}
9669 AAPotentialConstantValuesImpl::initialize(
A);
9673 Value &
V = getAssociatedValue();
9676 unionAssumed(
C->getValue());
9677 indicateOptimisticFixpoint();
9682 unionAssumedWithUndef();
9683 indicateOptimisticFixpoint();
9693 indicatePessimisticFixpoint();
9696 << getAssociatedValue() <<
"\n");
9699 static bool calculateICmpInst(
const ICmpInst *ICI,
const APInt &
LHS,
9704 static APInt calculateCastInst(
const CastInst *CI,
const APInt &Src,
9705 uint32_t ResultBitWidth) {
9710 case Instruction::Trunc:
9711 return Src.trunc(ResultBitWidth);
9712 case Instruction::SExt:
9713 return Src.sext(ResultBitWidth);
9714 case Instruction::ZExt:
9715 return Src.zext(ResultBitWidth);
9716 case Instruction::BitCast:
9721 static APInt calculateBinaryOperator(
const BinaryOperator *BinOp,
9722 const APInt &
LHS,
const APInt &
RHS,
9723 bool &SkipOperation,
bool &Unsupported) {
9730 switch (BinOpcode) {
9734 case Instruction::Add:
9736 case Instruction::Sub:
9738 case Instruction::Mul:
9740 case Instruction::UDiv:
9742 SkipOperation =
true;
9746 case Instruction::SDiv:
9748 SkipOperation =
true;
9752 case Instruction::URem:
9754 SkipOperation =
true;
9758 case Instruction::SRem:
9760 SkipOperation =
true;
9764 case Instruction::Shl:
9766 case Instruction::LShr:
9768 case Instruction::AShr:
9770 case Instruction::And:
9772 case Instruction::Or:
9774 case Instruction::Xor:
9779 bool calculateBinaryOperatorAndTakeUnion(
const BinaryOperator *BinOp,
9780 const APInt &
LHS,
const APInt &
RHS) {
9781 bool SkipOperation =
false;
9784 calculateBinaryOperator(BinOp,
LHS,
RHS, SkipOperation, Unsupported);
9789 unionAssumed(Result);
9790 return isValidState();
9793 ChangeStatus updateWithICmpInst(Attributor &
A, ICmpInst *ICI) {
9794 auto AssumedBefore = getAssumed();
9798 bool LHSContainsUndef =
false, RHSContainsUndef =
false;
9799 SetTy LHSAAPVS, RHSAAPVS;
9801 LHSContainsUndef,
false) ||
9803 RHSContainsUndef,
false))
9804 return indicatePessimisticFixpoint();
9807 bool MaybeTrue =
false, MaybeFalse =
false;
9809 if (LHSContainsUndef && RHSContainsUndef) {
9812 unionAssumedWithUndef();
9813 }
else if (LHSContainsUndef) {
9814 for (
const APInt &R : RHSAAPVS) {
9815 bool CmpResult = calculateICmpInst(ICI, Zero, R);
9816 MaybeTrue |= CmpResult;
9817 MaybeFalse |= !CmpResult;
9818 if (MaybeTrue & MaybeFalse)
9819 return indicatePessimisticFixpoint();
9821 }
else if (RHSContainsUndef) {
9822 for (
const APInt &L : LHSAAPVS) {
9823 bool CmpResult = calculateICmpInst(ICI, L, Zero);
9824 MaybeTrue |= CmpResult;
9825 MaybeFalse |= !CmpResult;
9826 if (MaybeTrue & MaybeFalse)
9827 return indicatePessimisticFixpoint();
9830 for (
const APInt &L : LHSAAPVS) {
9831 for (
const APInt &R : RHSAAPVS) {
9832 bool CmpResult = calculateICmpInst(ICI, L, R);
9833 MaybeTrue |= CmpResult;
9834 MaybeFalse |= !CmpResult;
9835 if (MaybeTrue & MaybeFalse)
9836 return indicatePessimisticFixpoint();
9841 unionAssumed(APInt( 1, 1));
9843 unionAssumed(APInt( 1, 0));
9844 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
9845 : ChangeStatus::CHANGED;
9848 ChangeStatus updateWithSelectInst(Attributor &
A, SelectInst *SI) {
9849 auto AssumedBefore = getAssumed();
9853 bool UsedAssumedInformation =
false;
9854 std::optional<Constant *>
C =
A.getAssumedConstant(
9855 *
SI->getCondition(), *
this, UsedAssumedInformation);
9858 bool OnlyLeft =
false, OnlyRight =
false;
9859 if (
C && *
C && (*C)->isOneValue())
9861 else if (
C && *
C && (*C)->isNullValue())
9864 bool LHSContainsUndef =
false, RHSContainsUndef =
false;
9865 SetTy LHSAAPVS, RHSAAPVS;
9868 LHSContainsUndef,
false))
9869 return indicatePessimisticFixpoint();
9873 RHSContainsUndef,
false))
9874 return indicatePessimisticFixpoint();
9876 if (OnlyLeft || OnlyRight) {
9878 auto *OpAA = OnlyLeft ? &LHSAAPVS : &RHSAAPVS;
9879 auto Undef = OnlyLeft ? LHSContainsUndef : RHSContainsUndef;
9882 unionAssumedWithUndef();
9884 for (
const auto &It : *OpAA)
9888 }
else if (LHSContainsUndef && RHSContainsUndef) {
9890 unionAssumedWithUndef();
9892 for (
const auto &It : LHSAAPVS)
9894 for (
const auto &It : RHSAAPVS)
9897 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
9898 : ChangeStatus::CHANGED;
9901 ChangeStatus updateWithCastInst(Attributor &
A, CastInst *CI) {
9902 auto AssumedBefore = getAssumed();
9904 return indicatePessimisticFixpoint();
9909 bool SrcContainsUndef =
false;
9912 SrcContainsUndef,
false))
9913 return indicatePessimisticFixpoint();
9915 if (SrcContainsUndef)
9916 unionAssumedWithUndef();
9918 for (
const APInt &S : SrcPVS) {
9919 APInt
T = calculateCastInst(CI, S, ResultBitWidth);
9923 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
9924 : ChangeStatus::CHANGED;
9927 ChangeStatus updateWithBinaryOperator(Attributor &
A, BinaryOperator *BinOp) {
9928 auto AssumedBefore = getAssumed();
9932 bool LHSContainsUndef =
false, RHSContainsUndef =
false;
9933 SetTy LHSAAPVS, RHSAAPVS;
9935 LHSContainsUndef,
false) ||
9937 RHSContainsUndef,
false))
9938 return indicatePessimisticFixpoint();
9943 if (LHSContainsUndef && RHSContainsUndef) {
9944 if (!calculateBinaryOperatorAndTakeUnion(BinOp, Zero, Zero))
9945 return indicatePessimisticFixpoint();
9946 }
else if (LHSContainsUndef) {
9947 for (
const APInt &R : RHSAAPVS) {
9948 if (!calculateBinaryOperatorAndTakeUnion(BinOp, Zero, R))
9949 return indicatePessimisticFixpoint();
9951 }
else if (RHSContainsUndef) {
9952 for (
const APInt &L : LHSAAPVS) {
9953 if (!calculateBinaryOperatorAndTakeUnion(BinOp, L, Zero))
9954 return indicatePessimisticFixpoint();
9957 for (
const APInt &L : LHSAAPVS) {
9958 for (
const APInt &R : RHSAAPVS) {
9959 if (!calculateBinaryOperatorAndTakeUnion(BinOp, L, R))
9960 return indicatePessimisticFixpoint();
9964 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
9965 : ChangeStatus::CHANGED;
9968 ChangeStatus updateWithInstruction(Attributor &
A, Instruction *Inst) {
9969 auto AssumedBefore = getAssumed();
9973 ContainsUndef,
true))
9974 return indicatePessimisticFixpoint();
9975 if (ContainsUndef) {
9976 unionAssumedWithUndef();
9978 for (
const auto &It : Incoming)
9981 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
9982 : ChangeStatus::CHANGED;
9986 Value &
V = getAssociatedValue();
9990 return updateWithICmpInst(
A, ICI);
9993 return updateWithSelectInst(
A, SI);
9996 return updateWithCastInst(
A, CI);
9999 return updateWithBinaryOperator(
A, BinOp);
10002 return updateWithInstruction(
A,
I);
10004 return indicatePessimisticFixpoint();
10007 void trackStatistics()
const override {
10012struct AAPotentialConstantValuesFunction : AAPotentialConstantValuesImpl {
10013 AAPotentialConstantValuesFunction(
const IRPosition &IRP, Attributor &
A)
10014 : AAPotentialConstantValuesImpl(IRP,
A) {}
10018 "AAPotentialConstantValues(Function|CallSite)::updateImpl will "
10022 void trackStatistics()
const override {
10027struct AAPotentialConstantValuesCallSite : AAPotentialConstantValuesFunction {
10028 AAPotentialConstantValuesCallSite(
const IRPosition &IRP, Attributor &
A)
10029 : AAPotentialConstantValuesFunction(IRP,
A) {}
10031 void trackStatistics()
const override {
10036struct AAPotentialConstantValuesCallSiteReturned
10037 : AACalleeToCallSite<AAPotentialConstantValues,
10038 AAPotentialConstantValuesImpl> {
10039 AAPotentialConstantValuesCallSiteReturned(
const IRPosition &IRP,
10041 : AACalleeToCallSite<AAPotentialConstantValues,
10042 AAPotentialConstantValuesImpl>(IRP,
A) {}
10044 void trackStatistics()
const override {
10049struct AAPotentialConstantValuesCallSiteArgument
10050 : AAPotentialConstantValuesFloating {
10051 AAPotentialConstantValuesCallSiteArgument(
const IRPosition &IRP,
10053 : AAPotentialConstantValuesFloating(IRP,
A) {}
10056 AAPotentialConstantValuesImpl::initialize(
A);
10057 if (isAtFixpoint())
10060 Value &
V = getAssociatedValue();
10063 unionAssumed(
C->getValue());
10064 indicateOptimisticFixpoint();
10069 unionAssumedWithUndef();
10070 indicateOptimisticFixpoint();
10076 Value &
V = getAssociatedValue();
10077 auto AssumedBefore = getAssumed();
10078 auto *AA =
A.getAAFor<AAPotentialConstantValues>(
10081 return indicatePessimisticFixpoint();
10082 const auto &S = AA->getAssumed();
10084 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10085 : ChangeStatus::CHANGED;
10088 void trackStatistics()
const override {
10097 bool IgnoreSubsumingPositions) {
10098 assert(ImpliedAttributeKind == Attribute::NoUndef &&
10099 "Unexpected attribute kind");
10100 if (
A.hasAttr(IRP, {Attribute::NoUndef}, IgnoreSubsumingPositions,
10101 Attribute::NoUndef))
10120 Value &V = getAssociatedValue();
10122 indicatePessimisticFixpoint();
10123 assert(!isImpliedByIR(
A, getIRPosition(), Attribute::NoUndef));
10127 bool followUseInMBEC(Attributor &
A,
const Use *U,
const Instruction *
I,
10128 AANoUndef::StateType &State) {
10129 const Value *UseV =
U->get();
10130 const DominatorTree *DT =
nullptr;
10131 AssumptionCache *AC =
nullptr;
10132 InformationCache &InfoCache =
A.getInfoCache();
10138 bool TrackUse =
false;
10146 const std::string getAsStr(Attributor *
A)
const override {
10147 return getAssumed() ?
"noundef" :
"may-undef-or-poison";
10154 bool UsedAssumedInformation =
false;
10155 if (
A.isAssumedDead(getIRPosition(),
nullptr,
nullptr,
10156 UsedAssumedInformation))
10157 return ChangeStatus::UNCHANGED;
10161 if (!
A.getAssumedSimplified(getIRPosition(), *
this, UsedAssumedInformation,
10164 return ChangeStatus::UNCHANGED;
10165 return AANoUndef::manifest(
A);
10169struct AANoUndefFloating :
public AANoUndefImpl {
10170 AANoUndefFloating(
const IRPosition &IRP, Attributor &
A)
10171 : AANoUndefImpl(IRP,
A) {}
10174 AANoUndefImpl::initialize(
A);
10175 if (!getState().isAtFixpoint() && getAnchorScope() &&
10176 !getAnchorScope()->isDeclaration())
10177 if (Instruction *CtxI = getCtxI())
10178 followUsesInMBEC(*
this,
A, getState(), *CtxI);
10182 auto VisitValueCB = [&](
const IRPosition &IRP) ->
bool {
10183 bool IsKnownNoUndef;
10185 A,
this, IRP, DepClassTy::REQUIRED, IsKnownNoUndef);
10189 bool UsedAssumedInformation =
false;
10190 Value *AssociatedValue = &getAssociatedValue();
10192 if (!
A.getAssumedSimplifiedValues(getIRPosition(), *
this,
Values,
10197 Values.size() != 1 ||
Values.front().getValue() != AssociatedValue;
10205 if (AVIRP == getIRPosition() || !VisitValueCB(AVIRP))
10206 return indicatePessimisticFixpoint();
10207 return ChangeStatus::UNCHANGED;
10210 for (
const auto &VAC :
Values)
10212 return indicatePessimisticFixpoint();
10214 return ChangeStatus::UNCHANGED;
10220struct AANoUndefReturned final
10221 : AAReturnedFromReturnedValues<AANoUndef, AANoUndefImpl> {
10222 AANoUndefReturned(
const IRPosition &IRP, Attributor &
A)
10223 : AAReturnedFromReturnedValues<AANoUndef, AANoUndefImpl>(IRP,
A) {}
10226 AAReturnedFromReturnedValues<AANoUndef, AANoUndefImpl>::initialize(
A);
10227 if (isAtFixpoint())
10232 AttributeMask AM = AttributeFuncs::getPoisonGeneratingAttributes();
10233 AttributeSet RetAttrs =
10234 getAssociatedFunction()->getAttributes().getRetAttrs();
10236 indicatePessimisticFixpoint();
10242struct AANoUndefArgument final
10243 : AAArgumentFromCallSiteArguments<AANoUndef, AANoUndefImpl> {
10244 AANoUndefArgument(
const IRPosition &IRP, Attributor &
A)
10245 : AAArgumentFromCallSiteArguments<AANoUndef, AANoUndefImpl>(IRP,
A) {}
10250struct AANoUndefCallSiteArgument final : AANoUndefFloating {
10251 AANoUndefCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
10252 : AANoUndefFloating(IRP,
A) {}
10257struct AANoUndefCallSiteReturned final
10258 : AACalleeToCallSite<AANoUndef, AANoUndefImpl> {
10259 AANoUndefCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
10260 : AACalleeToCallSite<AANoUndef, AANoUndefImpl>(IRP,
A) {}
10267struct AANoFPClassImpl : AANoFPClass {
10268 AANoFPClassImpl(
const IRPosition &IRP, Attributor &
A) : AANoFPClass(IRP,
A) {}
10271 const IRPosition &IRP = getIRPosition();
10275 indicateOptimisticFixpoint();
10280 A.getAttrs(getIRPosition(), {Attribute::NoFPClass},
Attrs,
false);
10281 for (
const auto &Attr : Attrs) {
10288 const DataLayout &
DL =
A.getDataLayout();
10289 InformationCache &InfoCache =
A.getInfoCache();
10291 const DominatorTree *DT =
nullptr;
10292 AssumptionCache *AC =
nullptr;
10293 const TargetLibraryInfo *TLI =
nullptr;
10297 if (!
F->isDeclaration()) {
10304 SimplifyQuery Q(
DL, TLI, DT, AC, CtxI);
10311 followUsesInMBEC(*
this,
A, getState(), *CtxI);
10315 bool followUseInMBEC(Attributor &
A,
const Use *U,
const Instruction *
I,
10316 AANoFPClass::StateType &State) {
10327 if (
auto *NoFPAA =
A.getAAFor<AANoFPClass>(*
this, IRP, DepClassTy::NONE))
10328 State.addKnownBits(NoFPAA->getState().getKnown());
10332 const std::string getAsStr(Attributor *
A)
const override {
10333 std::string
Result =
"nofpclass";
10334 raw_string_ostream OS(Result);
10335 OS << getKnownNoFPClass() <<
'/' << getAssumedNoFPClass();
10339 void getDeducedAttributes(Attributor &
A, LLVMContext &Ctx,
10340 SmallVectorImpl<Attribute> &Attrs)
const override {
10341 Attrs.emplace_back(Attribute::getWithNoFPClass(Ctx, getAssumedNoFPClass()));
10345struct AANoFPClassFloating :
public AANoFPClassImpl {
10346 AANoFPClassFloating(
const IRPosition &IRP, Attributor &
A)
10347 : AANoFPClassImpl(IRP,
A) {}
10351 bool UsedAssumedInformation =
false;
10352 if (!
A.getAssumedSimplifiedValues(getIRPosition(), *
this,
Values,
10354 Values.push_back({getAssociatedValue(), getCtxI()});
10360 DepClassTy::REQUIRED);
10361 if (!AA ||
this == AA) {
10362 T.indicatePessimisticFixpoint();
10364 const AANoFPClass::StateType &S =
10365 static_cast<const AANoFPClass::StateType &
>(AA->
getState());
10368 return T.isValidState();
10371 for (
const auto &VAC :
Values)
10373 return indicatePessimisticFixpoint();
10378 void trackStatistics()
const override {
10383struct AANoFPClassReturned final
10384 : AAReturnedFromReturnedValues<AANoFPClass, AANoFPClassImpl,
10385 AANoFPClassImpl::StateType, false,
10386 Attribute::None, false> {
10387 AANoFPClassReturned(
const IRPosition &IRP, Attributor &
A)
10388 : AAReturnedFromReturnedValues<AANoFPClass, AANoFPClassImpl,
10389 AANoFPClassImpl::StateType,
false,
10392 void trackStatistics()
const override {
10397struct AANoFPClassArgument final
10398 : AAArgumentFromCallSiteArguments<AANoFPClass, AANoFPClassImpl> {
10399 AANoFPClassArgument(
const IRPosition &IRP, Attributor &
A)
10400 : AAArgumentFromCallSiteArguments<AANoFPClass, AANoFPClassImpl>(IRP,
A) {}
10405struct AANoFPClassCallSiteArgument final : AANoFPClassFloating {
10406 AANoFPClassCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
10407 : AANoFPClassFloating(IRP,
A) {}
10409 void trackStatistics()
const override {
10414struct AANoFPClassCallSiteReturned final
10415 : AACalleeToCallSite<AANoFPClass, AANoFPClassImpl> {
10416 AANoFPClassCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
10417 : AACalleeToCallSite<AANoFPClass, AANoFPClassImpl>(IRP,
A) {}
10419 void trackStatistics()
const override {
10424struct AACallEdgesImpl :
public AACallEdges {
10425 AACallEdgesImpl(
const IRPosition &IRP, Attributor &
A) : AACallEdges(IRP,
A) {}
10427 const SetVector<Function *> &getOptimisticEdges()
const override {
10428 return CalledFunctions;
10431 bool hasUnknownCallee()
const override {
return HasUnknownCallee; }
10433 bool hasNonAsmUnknownCallee()
const override {
10434 return HasUnknownCalleeNonAsm;
10437 const std::string getAsStr(Attributor *
A)
const override {
10438 return "CallEdges[" + std::to_string(HasUnknownCallee) +
"," +
10439 std::to_string(CalledFunctions.size()) +
"]";
10442 void trackStatistics()
const override {}
10447 static Function *getOnlyCallee(
const CallBase &CB) {
10449 if (Callee && !
Callee->hasMetadata(LLVMContext::MD_callback))
10455 if (CalledFunctions.insert(Fn)) {
10456 Change = ChangeStatus::CHANGED;
10462 void setHasUnknownCallee(
bool NonAsm,
ChangeStatus &Change) {
10463 if (!HasUnknownCallee)
10464 Change = ChangeStatus::CHANGED;
10465 if (NonAsm && !HasUnknownCalleeNonAsm)
10466 Change = ChangeStatus::CHANGED;
10467 HasUnknownCalleeNonAsm |= NonAsm;
10468 HasUnknownCallee =
true;
10473 SetVector<Function *> CalledFunctions;
10476 bool HasUnknownCallee =
false;
10479 bool HasUnknownCalleeNonAsm =
false;
10482struct AACallEdgesCallSite :
public AACallEdgesImpl {
10483 AACallEdgesCallSite(
const IRPosition &IRP, Attributor &
A)
10484 : AACallEdgesImpl(IRP,
A) {}
10490 addCalledFunction(Callee, Change);
10491 indicateOptimisticFixpoint();
10500 addCalledFunction(Fn, Change);
10502 LLVM_DEBUG(
dbgs() <<
"[AACallEdges] Unrecognized value: " << V <<
"\n");
10503 setHasUnknownCallee(
true, Change);
10514 VisitValue(*V, CtxI);
10518 bool UsedAssumedInformation =
false;
10522 Values.push_back({*
V, CtxI});
10524 for (
auto &VAC :
Values)
10531 if (
IA->hasSideEffects() &&
10534 setHasUnknownCallee(
false, Change);
10540 if (
auto *IndirectCallAA =
A.getAAFor<AAIndirectCallInfo>(
10541 *
this, getIRPosition(), DepClassTy::OPTIONAL))
10542 if (IndirectCallAA->foreachCallee(
10543 [&](
Function *Fn) { return VisitValue(*Fn, CB); }))
10552 for (
const Use *U : CallbackUses)
10553 ProcessCalledOperand(
U->get(), CB);
10559struct AACallEdgesFunction :
public AACallEdgesImpl {
10560 AACallEdgesFunction(
const IRPosition &IRP, Attributor &
A)
10561 : AACallEdgesImpl(IRP,
A) {}
10565 bool AllCallsDirect =
true;
10572 if (
Function *Callee = getOnlyCallee(CB)) {
10573 addCalledFunction(Callee, Change);
10577 AllCallsDirect =
false;
10578 auto *CBEdges =
A.getAAFor<AACallEdges>(
10582 if (CBEdges->hasNonAsmUnknownCallee())
10583 setHasUnknownCallee(
true, Change);
10584 if (CBEdges->hasUnknownCallee())
10585 setHasUnknownCallee(
false, Change);
10587 for (
Function *
F : CBEdges->getOptimisticEdges())
10588 addCalledFunction(
F, Change);
10594 bool UsedAssumedInformation =
false;
10595 if (!
A.checkForAllCallLikeInstructions(ProcessCallInst, *
this,
10596 UsedAssumedInformation,
10600 setHasUnknownCallee(
true, Change);
10604 if (AllCallsDirect && !UsedAssumedInformation)
10605 indicateOptimisticFixpoint();
10613struct AAInterFnReachabilityFunction
10614 :
public CachedReachabilityAA<AAInterFnReachability, Function> {
10615 using Base = CachedReachabilityAA<AAInterFnReachability, Function>;
10616 AAInterFnReachabilityFunction(
const IRPosition &IRP, Attributor &
A)
10619 bool instructionCanReach(
10620 Attributor &
A,
const Instruction &From,
const Function &To,
10623 auto *NonConstThis =
const_cast<AAInterFnReachabilityFunction *
>(
this);
10625 RQITy StackRQI(
A, From, To, ExclusionSet,
false);
10626 RQITy::Reachable
Result;
10627 if (!NonConstThis->checkQueryCache(
A, StackRQI, Result))
10628 return NonConstThis->isReachableImpl(
A, StackRQI,
10630 return Result == RQITy::Reachable::Yes;
10634 bool IsTemporaryRQI)
override {
10636 &RQI.From->getFunction()->getEntryBlock().front();
10637 if (EntryI != RQI.From &&
10638 !instructionCanReach(
A, *EntryI, *RQI.To,
nullptr))
10639 return rememberResult(
A, RQITy::Reachable::No, RQI,
false,
10642 auto CheckReachableCallBase = [&](CallBase *CB) {
10643 auto *CBEdges =
A.getAAFor<AACallEdges>(
10645 if (!CBEdges || !CBEdges->getState().isValidState())
10648 if (CBEdges->hasUnknownCallee())
10651 for (
Function *Fn : CBEdges->getOptimisticEdges()) {
10662 if (Fn == getAnchorScope()) {
10663 if (EntryI == RQI.From)
10668 const AAInterFnReachability *InterFnReachability =
10670 DepClassTy::OPTIONAL);
10673 if (!InterFnReachability ||
10681 const auto *IntraFnReachability =
A.getAAFor<AAIntraFnReachability>(
10683 DepClassTy::OPTIONAL);
10691 return IntraFnReachability && !IntraFnReachability->isAssumedReachable(
10692 A, *RQI.From, CBInst, RQI.ExclusionSet);
10695 bool UsedExclusionSet =
true;
10696 bool UsedAssumedInformation =
false;
10697 if (!
A.checkForAllCallLikeInstructions(CheckCallBase, *
this,
10698 UsedAssumedInformation,
10700 return rememberResult(
A, RQITy::Reachable::Yes, RQI, UsedExclusionSet,
10703 return rememberResult(
A, RQITy::Reachable::No, RQI, UsedExclusionSet,
10707 void trackStatistics()
const override {}
10711template <
typename AAType>
10712static std::optional<Constant *>
10715 if (!Ty.isIntegerTy())
10723 std::optional<Constant *> COpt =
AA->getAssumedConstant(
A);
10725 if (!COpt.has_value()) {
10727 return std::nullopt;
10729 if (
auto *
C = *COpt) {
10740 std::optional<Value *> V;
10741 for (
auto &It :
Values) {
10743 if (V.has_value() && !*V)
10746 if (!V.has_value())
10759 if (
A.hasSimplificationCallback(getIRPosition())) {
10760 indicatePessimisticFixpoint();
10763 Value *Stripped = getAssociatedValue().stripPointerCasts();
10765 addValue(
A, getState(), *Stripped, getCtxI(),
AA::AnyScope,
10767 indicateOptimisticFixpoint();
10770 AAPotentialValues::initialize(
A);
10773 const std::string getAsStr(Attributor *
A)
const override {
10775 llvm::raw_string_ostream OS(Str);
10780 template <
typename AAType>
10781 static std::optional<Value *> askOtherAA(Attributor &
A,
10782 const AbstractAttribute &AA,
10783 const IRPosition &IRP,
Type &Ty) {
10788 return std::nullopt;
10795 virtual void addValue(Attributor &
A, StateType &State,
Value &V,
10801 for (
const auto &U : CB->
args()) {
10811 Type &Ty = *getAssociatedType();
10812 std::optional<Value *> SimpleV =
10813 askOtherAA<AAValueConstantRange>(
A, *
this, ValIRP, Ty);
10814 if (SimpleV.has_value() && !*SimpleV) {
10815 auto *PotentialConstantsAA =
A.getAAFor<AAPotentialConstantValues>(
10816 *
this, ValIRP, DepClassTy::OPTIONAL);
10817 if (PotentialConstantsAA && PotentialConstantsAA->isValidState()) {
10818 for (
const auto &It : PotentialConstantsAA->getAssumedSet())
10819 State.unionAssumed({{*ConstantInt::get(&Ty, It),
nullptr}, S});
10820 if (PotentialConstantsAA->undefIsContained())
10825 if (!SimpleV.has_value())
10837 State.unionAssumed({{*VPtr, CtxI}, S});
10843 AA::ValueAndContext
I;
10847 return II.I ==
I &&
II.S == S;
10850 return std::tie(
I, S) < std::tie(
II.I,
II.S);
10854 bool recurseForValue(Attributor &
A,
const IRPosition &IRP,
AA::ValueScope S) {
10855 SmallMapVector<AA::ValueAndContext, int, 8> ValueScopeMap;
10860 bool UsedAssumedInformation =
false;
10862 if (!
A.getAssumedSimplifiedValues(IRP,
this,
Values, CS,
10863 UsedAssumedInformation))
10867 ValueScopeMap[It] += CS;
10869 for (
auto &It : ValueScopeMap)
10870 addValue(
A, getState(), *It.first.getValue(), It.first.getCtxI(),
10876 void giveUpOnIntraprocedural(Attributor &
A) {
10877 auto NewS = StateType::getBestState(getState());
10878 for (
const auto &It : getAssumedSet()) {
10881 addValue(
A, NewS, *It.first.getValue(), It.first.getCtxI(),
10884 assert(!undefIsContained() &&
"Undef should be an explicit value!");
10891 getState() = StateType::getBestState(getState());
10892 getState().unionAssumed({{getAssociatedValue(), getCtxI()},
AA::AnyScope});
10893 AAPotentialValues::indicateOptimisticFixpoint();
10894 return ChangeStatus::CHANGED;
10898 return indicatePessimisticFixpoint();
10905 if (!getAssumedSimplifiedValues(
A,
Values, S))
10907 Value &OldV = getAssociatedValue();
10910 Value *NewV = getSingleValue(
A, *
this, getIRPosition(),
Values);
10911 if (!NewV || NewV == &OldV)
10916 if (
A.changeAfterManifest(getIRPosition(), *NewV))
10917 return ChangeStatus::CHANGED;
10919 return ChangeStatus::UNCHANGED;
10922 bool getAssumedSimplifiedValues(
10923 Attributor &
A, SmallVectorImpl<AA::ValueAndContext> &
Values,
10924 AA::ValueScope S,
bool RecurseForSelectAndPHI =
false)
const override {
10925 if (!isValidState())
10927 bool UsedAssumedInformation =
false;
10928 for (
const auto &It : getAssumedSet())
10929 if (It.second & S) {
10930 if (RecurseForSelectAndPHI && (
isa<PHINode>(It.first.getValue()) ||
10932 if (
A.getAssumedSimplifiedValues(
10934 this,
Values, S, UsedAssumedInformation))
10937 Values.push_back(It.first);
10939 assert(!undefIsContained() &&
"Undef should be an explicit value!");
10944struct AAPotentialValuesFloating : AAPotentialValuesImpl {
10945 AAPotentialValuesFloating(
const IRPosition &IRP, Attributor &
A)
10946 : AAPotentialValuesImpl(IRP,
A) {}
10949 auto AssumedBefore = getAssumed();
10951 genericValueTraversal(
A, &getAssociatedValue());
10953 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
10954 : ChangeStatus::CHANGED;
10958 struct LivenessInfo {
10959 const AAIsDead *LivenessAA =
nullptr;
10960 bool AnyDead =
false;
10970 SmallVectorImpl<ItemInfo> &Worklist) {
10973 bool UsedAssumedInformation =
false;
10975 auto GetSimplifiedValues = [&](
Value &
V,
10977 if (!
A.getAssumedSimplifiedValues(
10981 Values.push_back(AA::ValueAndContext{
V,
II.I.getCtxI()});
10985 if (GetSimplifiedValues(*
LHS, LHSValues))
10987 if (GetSimplifiedValues(*
RHS, RHSValues))
10992 InformationCache &InfoCache =
A.getInfoCache();
10999 F ?
A.getInfoCache().getTargetLibraryInfoForFunction(*
F) :
nullptr;
11004 const DataLayout &
DL =
A.getDataLayout();
11005 SimplifyQuery Q(
DL, TLI, DT, AC, CmpI);
11007 auto CheckPair = [&](
Value &LHSV,
Value &RHSV) {
11010 nullptr,
II.S, getAnchorScope());
11016 if (&LHSV == &RHSV &&
11018 Constant *NewV = ConstantInt::get(Type::getInt1Ty(Ctx),
11020 addValue(
A, getState(), *NewV,
nullptr,
II.S,
11027 if (TypedLHS && TypedRHS) {
11029 if (NewV && NewV != &Cmp) {
11030 addValue(
A, getState(), *NewV,
nullptr,
II.S,
11042 if (!LHSIsNull && !RHSIsNull)
11048 assert((LHSIsNull || RHSIsNull) &&
11049 "Expected nullptr versus non-nullptr comparison at this point");
11052 unsigned PtrIdx = LHSIsNull;
11053 bool IsKnownNonNull;
11056 DepClassTy::REQUIRED, IsKnownNonNull);
11057 if (!IsAssumedNonNull)
11063 addValue(
A, getState(), *NewV,
nullptr,
II.S,
11068 for (
auto &LHSValue : LHSValues)
11069 for (
auto &RHSValue : RHSValues)
11070 if (!CheckPair(*LHSValue.getValue(), *RHSValue.getValue()))
11075 bool handleSelectInst(Attributor &
A, SelectInst &SI, ItemInfo
II,
11076 SmallVectorImpl<ItemInfo> &Worklist) {
11078 bool UsedAssumedInformation =
false;
11080 std::optional<Constant *>
C =
11081 A.getAssumedConstant(*
SI.getCondition(), *
this, UsedAssumedInformation);
11082 bool NoValueYet = !
C.has_value();
11090 }
else if (&SI == &getAssociatedValue()) {
11095 std::optional<Value *> SimpleV =
A.getAssumedSimplified(
11097 if (!SimpleV.has_value())
11100 addValue(
A, getState(), **SimpleV, CtxI,
II.S, getAnchorScope());
11108 bool handleLoadInst(Attributor &
A, LoadInst &LI, ItemInfo
II,
11109 SmallVectorImpl<ItemInfo> &Worklist) {
11110 SmallSetVector<Value *, 4> PotentialCopies;
11111 SmallSetVector<Instruction *, 4> PotentialValueOrigins;
11112 bool UsedAssumedInformation =
false;
11114 PotentialValueOrigins, *
this,
11115 UsedAssumedInformation,
11117 LLVM_DEBUG(
dbgs() <<
"[AAPotentialValues] Failed to get potentially "
11118 "loaded values for load instruction "
11126 InformationCache &InfoCache =
A.getInfoCache();
11128 if (!
llvm::all_of(PotentialValueOrigins, [&](Instruction *
I) {
11132 return A.isAssumedDead(
SI->getOperandUse(0),
this,
11134 UsedAssumedInformation,
11136 return A.isAssumedDead(*
I,
this,
nullptr,
11137 UsedAssumedInformation,
11140 LLVM_DEBUG(
dbgs() <<
"[AAPotentialValues] Load is onl used by assumes "
11141 "and we cannot delete all the stores: "
11152 bool AllLocal = ScopeIsLocal;
11157 if (!DynamicallyUnique) {
11158 LLVM_DEBUG(
dbgs() <<
"[AAPotentialValues] Not all potentially loaded "
11159 "values are dynamically unique: "
11164 for (
auto *PotentialCopy : PotentialCopies) {
11166 Worklist.
push_back({{*PotentialCopy, CtxI},
II.S});
11171 if (!AllLocal && ScopeIsLocal)
11176 bool handlePHINode(
11177 Attributor &
A, PHINode &
PHI, ItemInfo
II,
11178 SmallVectorImpl<ItemInfo> &Worklist,
11179 SmallMapVector<const Function *, LivenessInfo, 4> &LivenessAAs) {
11180 auto GetLivenessInfo = [&](
const Function &
F) -> LivenessInfo & {
11181 LivenessInfo &LI = LivenessAAs[&
F];
11182 if (!LI.LivenessAA)
11188 if (&
PHI == &getAssociatedValue()) {
11189 LivenessInfo &LI = GetLivenessInfo(*
PHI.getFunction());
11191 A.getInfoCache().getAnalysisResultForFunction<CycleAnalysis>(
11192 *
PHI.getFunction());
11196 for (
unsigned u = 0, e =
PHI.getNumIncomingValues(); u < e; u++) {
11198 if (LI.LivenessAA &&
11199 LI.LivenessAA->isEdgeDead(IncomingBB,
PHI.getParent())) {
11218 bool UsedAssumedInformation =
false;
11219 std::optional<Value *> SimpleV =
A.getAssumedSimplified(
11221 if (!SimpleV.has_value())
11225 addValue(
A, getState(), **SimpleV, &
PHI,
II.S, getAnchorScope());
11232 bool handleGenericInst(Attributor &
A, Instruction &
I, ItemInfo
II,
11233 SmallVectorImpl<ItemInfo> &Worklist) {
11234 bool SomeSimplified =
false;
11235 bool UsedAssumedInformation =
false;
11237 SmallVector<Value *, 8> NewOps(
I.getNumOperands());
11240 const auto &SimplifiedOp =
A.getAssumedSimplified(
11245 if (!SimplifiedOp.has_value())
11249 NewOps[
Idx] = *SimplifiedOp;
11253 SomeSimplified |= (NewOps[
Idx] !=
Op);
11259 if (!SomeSimplified)
11262 InformationCache &InfoCache =
A.getInfoCache();
11266 const auto *TLI =
A.getInfoCache().getTargetLibraryInfoForFunction(*
F);
11269 const DataLayout &
DL =
I.getDataLayout();
11270 SimplifyQuery Q(
DL, TLI, DT, AC, &
I);
11272 if (!NewV || NewV == &
I)
11275 LLVM_DEBUG(
dbgs() <<
"Generic inst " <<
I <<
" assumed simplified to "
11282 Attributor &
A, Instruction &
I, ItemInfo
II,
11283 SmallVectorImpl<ItemInfo> &Worklist,
11284 SmallMapVector<const Function *, LivenessInfo, 4> &LivenessAAs) {
11287 CI->getPredicate(),
II, Worklist);
11289 switch (
I.getOpcode()) {
11290 case Instruction::Select:
11292 case Instruction::PHI:
11294 case Instruction::Load:
11297 return handleGenericInst(
A,
I,
II, Worklist);
11302 void genericValueTraversal(Attributor &
A,
Value *InitialV) {
11303 SmallMapVector<const Function *, LivenessInfo, 4> LivenessAAs;
11305 SmallSet<ItemInfo, 16> Visited;
11324 LLVM_DEBUG(
dbgs() <<
"Generic value traversal reached iteration limit: "
11325 << Iteration <<
"!\n");
11326 addValue(
A, getState(), *V, CtxI, S, getAnchorScope());
11332 Value *NewV =
nullptr;
11333 if (
V->getType()->isPointerTy()) {
11339 for (Argument &Arg :
Callee->args())
11346 if (NewV && NewV != V) {
11347 Worklist.
push_back({{*NewV, CtxI}, S});
11361 if (V == InitialV && CtxI == getCtxI()) {
11362 indicatePessimisticFixpoint();
11366 addValue(
A, getState(), *V, CtxI, S, getAnchorScope());
11367 }
while (!Worklist.
empty());
11371 for (
auto &It : LivenessAAs)
11372 if (It.second.AnyDead)
11373 A.recordDependence(*It.second.LivenessAA, *
this, DepClassTy::OPTIONAL);
11376 void trackStatistics()
const override {
11381struct AAPotentialValuesArgument final : AAPotentialValuesImpl {
11382 using Base = AAPotentialValuesImpl;
11383 AAPotentialValuesArgument(
const IRPosition &IRP, Attributor &
A)
11389 indicatePessimisticFixpoint();
11393 auto AssumedBefore = getAssumed();
11395 unsigned ArgNo = getCalleeArgNo();
11397 bool UsedAssumedInformation =
false;
11399 auto CallSitePred = [&](AbstractCallSite ACS) {
11401 if (CSArgIRP.getPositionKind() == IRP_INVALID)
11404 if (!
A.getAssumedSimplifiedValues(CSArgIRP,
this,
Values,
11406 UsedAssumedInformation))
11409 return isValidState();
11412 if (!
A.checkForAllCallSites(CallSitePred, *
this,
11414 UsedAssumedInformation))
11415 return indicatePessimisticFixpoint();
11417 Function *Fn = getAssociatedFunction();
11418 bool AnyNonLocal =
false;
11419 for (
auto &It :
Values) {
11421 addValue(
A, getState(), *It.getValue(), It.getCtxI(),
AA::AnyScope,
11426 return indicatePessimisticFixpoint();
11430 addValue(
A, getState(), *It.getValue(), It.getCtxI(),
AA::AnyScope,
11436 AnyNonLocal =
true;
11438 assert(!undefIsContained() &&
"Undef should be an explicit value!");
11440 giveUpOnIntraprocedural(
A);
11442 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
11443 : ChangeStatus::CHANGED;
11446 void trackStatistics()
const override {
11451struct AAPotentialValuesReturned :
public AAPotentialValuesFloating {
11452 using Base = AAPotentialValuesFloating;
11453 AAPotentialValuesReturned(
const IRPosition &IRP, Attributor &
A)
11458 if (!
F ||
F->isDeclaration() ||
F->getReturnType()->isVoidTy()) {
11459 indicatePessimisticFixpoint();
11463 for (Argument &Arg :
F->args())
11466 ReturnedArg = &Arg;
11469 if (!
A.isFunctionIPOAmendable(*
F) ||
11470 A.hasSimplificationCallback(getIRPosition())) {
11472 indicatePessimisticFixpoint();
11474 indicateOptimisticFixpoint();
11479 auto AssumedBefore = getAssumed();
11480 bool UsedAssumedInformation =
false;
11483 Function *AnchorScope = getAnchorScope();
11489 UsedAssumedInformation,
11495 bool AllInterAreIntra =
false;
11502 for (
const AA::ValueAndContext &VAC :
Values) {
11503 addValue(
A, getState(), *VAC.
getValue(),
11507 if (AllInterAreIntra)
11514 HandleReturnedValue(*ReturnedArg,
nullptr,
true);
11517 bool AddValues =
true;
11520 addValue(
A, getState(), *RetI.getOperand(0), &RetI,
AA::AnyScope,
11524 return HandleReturnedValue(*RetI.getOperand(0), &RetI, AddValues);
11527 if (!
A.checkForAllInstructions(RetInstPred, *
this, {Instruction::Ret},
11528 UsedAssumedInformation,
11530 return indicatePessimisticFixpoint();
11533 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
11534 : ChangeStatus::CHANGED;
11539 return ChangeStatus::UNCHANGED;
11541 if (!getAssumedSimplifiedValues(
A,
Values, AA::ValueScope::Intraprocedural,
11543 return ChangeStatus::UNCHANGED;
11544 Value *NewVal = getSingleValue(
A, *
this, getIRPosition(),
Values);
11546 return ChangeStatus::UNCHANGED;
11551 "Number of function with unique return");
11554 {Attribute::get(Arg->
getContext(), Attribute::Returned)});
11559 Value *RetOp = RetI.getOperand(0);
11563 if (
A.changeUseAfterManifest(RetI.getOperandUse(0), *NewVal))
11564 Changed = ChangeStatus::CHANGED;
11567 bool UsedAssumedInformation =
false;
11568 (void)
A.checkForAllInstructions(RetInstPred, *
this, {Instruction::Ret},
11569 UsedAssumedInformation,
11575 return AAPotentialValues::indicatePessimisticFixpoint();
11578 void trackStatistics()
const override{
11585struct AAPotentialValuesFunction : AAPotentialValuesImpl {
11586 AAPotentialValuesFunction(
const IRPosition &IRP, Attributor &
A)
11587 : AAPotentialValuesImpl(IRP,
A) {}
11594 void trackStatistics()
const override {
11599struct AAPotentialValuesCallSite : AAPotentialValuesFunction {
11600 AAPotentialValuesCallSite(
const IRPosition &IRP, Attributor &
A)
11601 : AAPotentialValuesFunction(IRP,
A) {}
11603 void trackStatistics()
const override {
11608struct AAPotentialValuesCallSiteReturned : AAPotentialValuesImpl {
11609 AAPotentialValuesCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
11610 : AAPotentialValuesImpl(IRP,
A) {}
11613 auto AssumedBefore = getAssumed();
11617 return indicatePessimisticFixpoint();
11619 bool UsedAssumedInformation =
false;
11623 UsedAssumedInformation))
11624 return indicatePessimisticFixpoint();
11631 Values, S, UsedAssumedInformation))
11634 for (
auto &It :
Values) {
11635 Value *
V = It.getValue();
11636 std::optional<Value *> CallerV =
A.translateArgumentToCallSiteContent(
11637 V, *CB, *
this, UsedAssumedInformation);
11638 if (!CallerV.has_value()) {
11642 V = *CallerV ? *CallerV :
V;
11648 giveUpOnIntraprocedural(
A);
11651 addValue(
A, getState(), *V, CB, S, getAnchorScope());
11656 return indicatePessimisticFixpoint();
11658 return indicatePessimisticFixpoint();
11659 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
11660 : ChangeStatus::CHANGED;
11664 return AAPotentialValues::indicatePessimisticFixpoint();
11667 void trackStatistics()
const override {
11672struct AAPotentialValuesCallSiteArgument : AAPotentialValuesFloating {
11673 AAPotentialValuesCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
11674 : AAPotentialValuesFloating(IRP,
A) {}
11676 void trackStatistics()
const override {
11684struct AAAssumptionInfoImpl :
public AAAssumptionInfo {
11685 AAAssumptionInfoImpl(
const IRPosition &IRP, Attributor &
A,
11686 const DenseSet<StringRef> &
Known)
11687 : AAAssumptionInfo(IRP,
A,
Known) {}
11691 if (getKnown().isUniversal())
11692 return ChangeStatus::UNCHANGED;
11694 const IRPosition &IRP = getIRPosition();
11696 getAssumed().getSet().
end());
11698 return A.manifestAttrs(IRP,
11705 bool hasAssumption(
const StringRef Assumption)
const override {
11706 return isValidState() && setContains(Assumption);
11709 const std::string getAsStr(Attributor *
A)
const override {
11710 const SetContents &
Known = getKnown();
11711 const SetContents &Assumed = getAssumed();
11715 const std::string KnownStr =
llvm::join(Set,
",");
11717 std::string AssumedStr =
"Universal";
11718 if (!Assumed.isUniversal()) {
11719 Set.assign(Assumed.getSet().begin(), Assumed.getSet().end());
11722 return "Known [" + KnownStr +
"]," +
" Assumed [" + AssumedStr +
"]";
11737struct AAAssumptionInfoFunction final : AAAssumptionInfoImpl {
11738 AAAssumptionInfoFunction(
const IRPosition &IRP, Attributor &
A)
11739 : AAAssumptionInfoImpl(IRP,
A,
11745 auto CallSitePred = [&](AbstractCallSite ACS) {
11746 const auto *AssumptionAA =
A.getAAFor<AAAssumptionInfo>(
11748 DepClassTy::REQUIRED);
11752 Changed |= getIntersection(AssumptionAA->getAssumed());
11753 return !getAssumed().empty() || !getKnown().empty();
11756 bool UsedAssumedInformation =
false;
11761 if (!
A.checkForAllCallSites(CallSitePred, *
this,
true,
11762 UsedAssumedInformation))
11763 return indicatePessimisticFixpoint();
11765 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
11768 void trackStatistics()
const override {}
11772struct AAAssumptionInfoCallSite final : AAAssumptionInfoImpl {
11774 AAAssumptionInfoCallSite(
const IRPosition &IRP, Attributor &
A)
11775 : AAAssumptionInfoImpl(IRP,
A, getInitialAssumptions(IRP)) {}
11779 A.getAAFor<AAAssumptionInfo>(*
this, FnPos, DepClassTy::REQUIRED);
11784 auto *AssumptionAA =
11785 A.getAAFor<AAAssumptionInfo>(*
this, FnPos, DepClassTy::REQUIRED);
11787 return indicatePessimisticFixpoint();
11788 bool Changed = getIntersection(AssumptionAA->getAssumed());
11789 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
11792 void trackStatistics()
const override {}
11797 DenseSet<StringRef> getInitialAssumptions(
const IRPosition &IRP) {
11804 return Assumptions;
11819struct AAUnderlyingObjectsImpl
11824 const std::string getAsStr(
Attributor *
A)
const override {
11825 if (!isValidState())
11826 return "<invalid>";
11829 OS <<
"underlying objects: inter " << InterAssumedUnderlyingObjects.size()
11830 <<
" objects, intra " << IntraAssumedUnderlyingObjects.size()
11832 if (!InterAssumedUnderlyingObjects.empty()) {
11833 OS <<
"inter objects:\n";
11834 for (
auto *Obj : InterAssumedUnderlyingObjects)
11835 OS << *Obj <<
'\n';
11837 if (!IntraAssumedUnderlyingObjects.empty()) {
11838 OS <<
"intra objects:\n";
11839 for (
auto *Obj : IntraAssumedUnderlyingObjects)
11840 OS << *
Obj <<
'\n';
11845 void trackStatistics()
const override {}
11848 auto &Ptr = getAssociatedValue();
11850 bool UsedAssumedInformation =
false;
11851 auto DoUpdate = [&](SmallSetVector<Value *, 8> &UnderlyingObjects,
11853 SmallPtrSet<Value *, 8> SeenObjects;
11857 Scope, UsedAssumedInformation))
11858 return UnderlyingObjects.
insert(&Ptr);
11862 for (
unsigned I = 0;
I <
Values.size(); ++
I) {
11866 if (!SeenObjects.
insert(UO ? UO : Obj).second)
11868 if (UO && UO != Obj) {
11874 const auto *OtherAA =
A.getAAFor<AAUnderlyingObjects>(
11876 auto Pred = [&](
Value &
V) {
11880 Values.emplace_back(V,
nullptr);
11884 if (!OtherAA || !OtherAA->forallUnderlyingObjects(Pred, Scope))
11886 "The forall call should not return false at this position");
11892 Changed |= handleIndirect(
A, *Obj, UnderlyingObjects, Scope,
11893 UsedAssumedInformation);
11899 for (
unsigned u = 0, e =
PHI->getNumIncomingValues(); u < e; u++) {
11901 handleIndirect(
A, *
PHI->getIncomingValue(u), UnderlyingObjects,
11902 Scope, UsedAssumedInformation);
11916 if (!UsedAssumedInformation)
11917 indicateOptimisticFixpoint();
11918 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
11921 bool forallUnderlyingObjects(
11922 function_ref<
bool(
Value &)> Pred,
11924 if (!isValidState())
11925 return Pred(getAssociatedValue());
11928 ? IntraAssumedUnderlyingObjects
11929 : InterAssumedUnderlyingObjects;
11930 for (
Value *Obj : AssumedUnderlyingObjects)
11940 bool handleIndirect(Attributor &
A,
Value &V,
11941 SmallSetVector<Value *, 8> &UnderlyingObjects,
11944 const auto *AA =
A.getAAFor<AAUnderlyingObjects>(
11946 auto Pred = [&](
Value &
V) {
11950 if (!AA || !AA->forallUnderlyingObjects(Pred, Scope))
11952 "The forall call should not return false at this position");
11958 SmallSetVector<Value *, 8> IntraAssumedUnderlyingObjects;
11960 SmallSetVector<Value *, 8> InterAssumedUnderlyingObjects;
11963struct AAUnderlyingObjectsFloating final : AAUnderlyingObjectsImpl {
11964 AAUnderlyingObjectsFloating(
const IRPosition &IRP, Attributor &
A)
11965 : AAUnderlyingObjectsImpl(IRP,
A) {}
11968struct AAUnderlyingObjectsArgument final : AAUnderlyingObjectsImpl {
11969 AAUnderlyingObjectsArgument(
const IRPosition &IRP, Attributor &
A)
11970 : AAUnderlyingObjectsImpl(IRP,
A) {}
11973struct AAUnderlyingObjectsCallSite final : AAUnderlyingObjectsImpl {
11974 AAUnderlyingObjectsCallSite(
const IRPosition &IRP, Attributor &
A)
11975 : AAUnderlyingObjectsImpl(IRP,
A) {}
11978struct AAUnderlyingObjectsCallSiteArgument final : AAUnderlyingObjectsImpl {
11979 AAUnderlyingObjectsCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
11980 : AAUnderlyingObjectsImpl(IRP,
A) {}
11983struct AAUnderlyingObjectsReturned final : AAUnderlyingObjectsImpl {
11984 AAUnderlyingObjectsReturned(
const IRPosition &IRP, Attributor &
A)
11985 : AAUnderlyingObjectsImpl(IRP,
A) {}
11988struct AAUnderlyingObjectsCallSiteReturned final : AAUnderlyingObjectsImpl {
11989 AAUnderlyingObjectsCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
11990 : AAUnderlyingObjectsImpl(IRP,
A) {}
11993struct AAUnderlyingObjectsFunction final : AAUnderlyingObjectsImpl {
11994 AAUnderlyingObjectsFunction(
const IRPosition &IRP, Attributor &
A)
11995 : AAUnderlyingObjectsImpl(IRP,
A) {}
12001struct AAGlobalValueInfoFloating :
public AAGlobalValueInfo {
12002 AAGlobalValueInfoFloating(
const IRPosition &IRP, Attributor &
A)
12003 : AAGlobalValueInfo(IRP,
A) {}
12007 bool checkUse(Attributor &
A,
const Use &U,
bool &Follow,
12008 SmallVectorImpl<const Value *> &Worklist) {
12014 if (!GV->hasLocalLinkage() && !
A.isClosedWorldModule())
12020 LLVM_DEBUG(
dbgs() <<
"[AAGlobalValueInfo] Check use: " << *
U.get() <<
" in "
12021 << *UInst <<
"\n");
12024 int Idx = &
Cmp->getOperandUse(0) == &
U;
12027 return U == &getAnchorValue();
12032 auto CallSitePred = [&](AbstractCallSite ACS) {
12033 Worklist.
push_back(ACS.getInstruction());
12036 bool UsedAssumedInformation =
false;
12038 if (!
A.checkForAllCallSites(CallSitePred, *UInst->
getFunction(),
12040 UsedAssumedInformation))
12058 if (!Fn || !
A.isFunctionIPOAmendable(*Fn))
12067 unsigned NumUsesBefore =
Uses.size();
12069 SmallPtrSet<const Value *, 8> Visited;
12073 auto UsePred = [&](
const Use &
U,
bool &Follow) ->
bool {
12081 return checkUse(
A, U, Follow, Worklist);
12083 auto EquivalentUseCB = [&](
const Use &OldU,
const Use &NewU) {
12084 Uses.insert(&OldU);
12088 while (!Worklist.
empty()) {
12090 if (!Visited.
insert(V).second)
12092 if (!
A.checkForAllUses(UsePred, *
this, *V,
12094 DepClassTy::OPTIONAL,
12095 true, EquivalentUseCB)) {
12096 return indicatePessimisticFixpoint();
12100 return Uses.size() == NumUsesBefore ? ChangeStatus::UNCHANGED
12101 : ChangeStatus::CHANGED;
12104 bool isPotentialUse(
const Use &U)
const override {
12105 return !isValidState() ||
Uses.contains(&U);
12109 return ChangeStatus::UNCHANGED;
12112 const std::string getAsStr(Attributor *
A)
const override {
12113 return "[" + std::to_string(
Uses.size()) +
" uses]";
12116 void trackStatistics()
const override {
12122 SmallPtrSet<const Use *, 8>
Uses;
12128struct AAIndirectCallInfoCallSite :
public AAIndirectCallInfo {
12129 AAIndirectCallInfoCallSite(
const IRPosition &IRP, Attributor &
A)
12130 : AAIndirectCallInfo(IRP,
A) {}
12133 auto *MD = getCtxI()->getMetadata(LLVMContext::MD_callees);
12134 if (!MD && !
A.isClosedWorldModule())
12138 for (
const auto &
Op : MD->operands())
12140 PotentialCallees.insert(Callee);
12141 }
else if (
A.isClosedWorldModule()) {
12143 A.getInfoCache().getIndirectlyCallableFunctions(
A);
12144 PotentialCallees.insert_range(IndirectlyCallableFunctions);
12147 if (PotentialCallees.empty())
12148 indicateOptimisticFixpoint();
12156 SmallSetVector<Function *, 4> AssumedCalleesNow;
12157 bool AllCalleesKnownNow = AllCalleesKnown;
12159 auto CheckPotentialCalleeUse = [&](
Function &PotentialCallee,
12160 bool &UsedAssumedInformation) {
12161 const auto *GIAA =
A.getAAFor<AAGlobalValueInfo>(
12163 if (!GIAA || GIAA->isPotentialUse(CalleeUse))
12165 UsedAssumedInformation = !GIAA->isAtFixpoint();
12169 auto AddPotentialCallees = [&]() {
12170 for (
auto *PotentialCallee : PotentialCallees) {
12171 bool UsedAssumedInformation =
false;
12172 if (CheckPotentialCalleeUse(*PotentialCallee, UsedAssumedInformation))
12173 AssumedCalleesNow.
insert(PotentialCallee);
12179 bool UsedAssumedInformation =
false;
12182 AA::ValueScope::AnyScope,
12183 UsedAssumedInformation)) {
12184 if (PotentialCallees.empty())
12185 return indicatePessimisticFixpoint();
12186 AddPotentialCallees();
12191 auto CheckPotentialCallee = [&](
Function &Fn) {
12192 if (!PotentialCallees.empty() && !PotentialCallees.count(&Fn))
12195 auto &CachedResult = FilterResults[&Fn];
12196 if (CachedResult.has_value())
12197 return CachedResult.value();
12199 bool UsedAssumedInformation =
false;
12200 if (!CheckPotentialCalleeUse(Fn, UsedAssumedInformation)) {
12201 if (!UsedAssumedInformation)
12202 CachedResult =
false;
12211 for (
int I = NumCBArgs;
I < NumFnArgs; ++
I) {
12212 bool IsKnown =
false;
12215 DepClassTy::OPTIONAL, IsKnown)) {
12217 CachedResult =
false;
12222 CachedResult =
true;
12228 for (
auto &VAC :
Values) {
12236 if (CheckPotentialCallee(*VACFn))
12237 AssumedCalleesNow.
insert(VACFn);
12240 if (!PotentialCallees.empty()) {
12241 AddPotentialCallees();
12244 AllCalleesKnownNow =
false;
12247 if (AssumedCalleesNow == AssumedCallees &&
12248 AllCalleesKnown == AllCalleesKnownNow)
12249 return ChangeStatus::UNCHANGED;
12251 std::swap(AssumedCallees, AssumedCalleesNow);
12252 AllCalleesKnown = AllCalleesKnownNow;
12253 return ChangeStatus::CHANGED;
12258 if (!AllCalleesKnown && AssumedCallees.empty())
12259 return ChangeStatus::UNCHANGED;
12262 bool UsedAssumedInformation =
false;
12263 if (
A.isAssumedDead(*CB,
this,
nullptr,
12264 UsedAssumedInformation))
12265 return ChangeStatus::UNCHANGED;
12270 if (
FP->getType()->getPointerAddressSpace() != ProgramAS)
12271 FP =
new AddrSpaceCastInst(
12272 FP, PointerType::get(
FP->getContext(), ProgramAS),
12273 FP->getName() +
".as" + Twine(ProgramAS), CB->
getIterator());
12282 if (AssumedCallees.empty()) {
12283 assert(AllCalleesKnown &&
12284 "Expected all callees to be known if there are none.");
12285 A.changeToUnreachableAfterManifest(CB);
12286 return ChangeStatus::CHANGED;
12290 if (AllCalleesKnown && AssumedCallees.size() == 1) {
12291 auto *NewCallee = AssumedCallees.front();
12294 NumIndirectCallsPromoted++;
12295 return ChangeStatus::CHANGED;
12302 A.deleteAfterManifest(*CB);
12303 return ChangeStatus::CHANGED;
12313 bool SpecializedForAnyCallees =
false;
12314 bool SpecializedForAllCallees = AllCalleesKnown;
12315 ICmpInst *LastCmp =
nullptr;
12318 for (
Function *NewCallee : AssumedCallees) {
12319 if (!
A.shouldSpecializeCallSiteForCallee(*
this, *CB, *NewCallee,
12320 AssumedCallees.size())) {
12321 SkippedAssumedCallees.
push_back(NewCallee);
12322 SpecializedForAllCallees =
false;
12325 SpecializedForAnyCallees =
true;
12331 A.registerManifestAddedBasicBlock(*ThenTI->
getParent());
12332 A.registerManifestAddedBasicBlock(*IP->getParent());
12338 A.registerManifestAddedBasicBlock(*ElseBB);
12340 SplitTI->replaceUsesOfWith(CBBB, ElseBB);
12345 CastInst *RetBC =
nullptr;
12346 CallInst *NewCall =
nullptr;
12351 NumIndirectCallsPromoted++;
12359 auto AttachCalleeMetadata = [&](CallBase &IndirectCB) {
12360 if (!AllCalleesKnown)
12361 return ChangeStatus::UNCHANGED;
12362 MDBuilder MDB(IndirectCB.getContext());
12363 MDNode *Callees = MDB.createCallees(SkippedAssumedCallees);
12364 IndirectCB.setMetadata(LLVMContext::MD_callees, Callees);
12365 return ChangeStatus::CHANGED;
12368 if (!SpecializedForAnyCallees)
12369 return AttachCalleeMetadata(*CB);
12372 if (SpecializedForAllCallees) {
12375 new UnreachableInst(IP->getContext(), IP);
12376 IP->eraseFromParent();
12379 CBClone->setName(CB->
getName());
12380 CBClone->insertBefore(*IP->getParent(), IP);
12381 NewCalls.
push_back({CBClone,
nullptr});
12382 AttachCalleeMetadata(*CBClone);
12389 CB->
getParent()->getFirstInsertionPt());
12390 for (
auto &It : NewCalls) {
12391 CallBase *NewCall = It.first;
12392 Instruction *CallRet = It.second ? It.second : It.first;
12404 A.deleteAfterManifest(*CB);
12405 Changed = ChangeStatus::CHANGED;
12410 const std::string getAsStr(Attributor *
A)
const override {
12411 return std::string(AllCalleesKnown ?
"eliminate" :
"specialize") +
12412 " indirect call site with " + std::to_string(AssumedCallees.size()) +
12416 void trackStatistics()
const override {
12417 if (AllCalleesKnown) {
12419 Eliminated, CallSites,
12420 "Number of indirect call sites eliminated via specialization")
12423 "Number of indirect call sites specialized")
12427 bool foreachCallee(function_ref<
bool(
Function *)> CB)
const override {
12428 return isValidState() && AllCalleesKnown &&
all_of(AssumedCallees, CB);
12433 DenseMap<Function *, std::optional<bool>> FilterResults;
12437 SmallSetVector<Function *, 4> PotentialCallees;
12441 SmallSetVector<Function *, 4> AssumedCallees;
12445 bool AllCalleesKnown =
true;
12452struct AAInvariantLoadPointerImpl
12453 :
public StateWrapper<BitIntegerState<uint8_t, 15>,
12454 AAInvariantLoadPointer> {
12458 IS_NOALIAS = 1 << 0,
12461 IS_NOEFFECT = 1 << 1,
12463 IS_LOCALLY_INVARIANT = 1 << 2,
12465 IS_LOCALLY_CONSTRAINED = 1 << 3,
12467 IS_BEST_STATE = IS_NOALIAS | IS_NOEFFECT | IS_LOCALLY_INVARIANT |
12468 IS_LOCALLY_CONSTRAINED,
12470 static_assert(getBestState() == IS_BEST_STATE,
"Unexpected best state");
12473 StateWrapper<BitIntegerState<uint8_t, 15>, AAInvariantLoadPointer>;
12477 AAInvariantLoadPointerImpl(
const IRPosition &IRP, Attributor &
A)
12480 bool isKnownInvariant()
const final {
12481 return isKnownLocallyInvariant() && isKnown(IS_LOCALLY_CONSTRAINED);
12484 bool isKnownLocallyInvariant()
const final {
12485 if (isKnown(IS_LOCALLY_INVARIANT))
12487 return isKnown(IS_NOALIAS | IS_NOEFFECT);
12490 bool isAssumedInvariant()
const final {
12491 return isAssumedLocallyInvariant() && isAssumed(IS_LOCALLY_CONSTRAINED);
12494 bool isAssumedLocallyInvariant()
const final {
12495 if (isAssumed(IS_LOCALLY_INVARIANT))
12497 return isAssumed(IS_NOALIAS | IS_NOEFFECT);
12504 if (requiresNoAlias() && !isAssumed(IS_NOALIAS))
12505 return indicatePessimisticFixpoint();
12509 Changed |= updateLocalInvariance(
A);
12515 if (!isKnownInvariant())
12516 return ChangeStatus::UNCHANGED;
12519 const Value *Ptr = &getAssociatedValue();
12520 const auto TagInvariantLoads = [&](
const Use &
U,
bool &) {
12521 if (
U.get() != Ptr)
12529 if (!
A.isRunOn(
I->getFunction()))
12532 if (
I->hasMetadata(LLVMContext::MD_invariant_load))
12536 LI->setMetadata(LLVMContext::MD_invariant_load,
12538 Changed = ChangeStatus::CHANGED;
12543 (void)
A.checkForAllUses(TagInvariantLoads, *
this, *Ptr);
12547 const std::string getAsStr(Attributor *)
const override {
12548 if (isKnownInvariant())
12549 return "load-invariant pointer";
12550 return "non-invariant pointer";
12553 void trackStatistics()
const override {}
12557 bool requiresNoAlias()
const {
12558 switch (getPositionKind()) {
12564 case IRP_CALL_SITE:
12566 case IRP_CALL_SITE_RETURNED: {
12571 case IRP_ARGUMENT: {
12572 const Function *
F = getAssociatedFunction();
12573 assert(
F &&
"no associated function for argument");
12579 bool isExternal()
const {
12580 const Function *
F = getAssociatedFunction();
12584 getPositionKind() != IRP_CALL_SITE_RETURNED;
12588 if (isKnown(IS_NOALIAS) || !isAssumed(IS_NOALIAS))
12589 return ChangeStatus::UNCHANGED;
12592 if (
const auto *ANoAlias =
A.getOrCreateAAFor<AANoAlias>(
12593 getIRPosition(),
this, DepClassTy::REQUIRED)) {
12594 if (ANoAlias->isKnownNoAlias()) {
12595 addKnownBits(IS_NOALIAS);
12596 return ChangeStatus::CHANGED;
12599 if (!ANoAlias->isAssumedNoAlias()) {
12600 removeAssumedBits(IS_NOALIAS);
12601 return ChangeStatus::CHANGED;
12604 return ChangeStatus::UNCHANGED;
12609 if (
const Argument *Arg = getAssociatedArgument()) {
12611 addKnownBits(IS_NOALIAS);
12612 return ChangeStatus::UNCHANGED;
12617 removeAssumedBits(IS_NOALIAS);
12618 return ChangeStatus::CHANGED;
12621 return ChangeStatus::UNCHANGED;
12625 if (isKnown(IS_NOEFFECT) || !isAssumed(IS_NOEFFECT))
12626 return ChangeStatus::UNCHANGED;
12628 if (!getAssociatedFunction())
12629 return indicatePessimisticFixpoint();
12632 return indicatePessimisticFixpoint();
12634 const auto HasNoEffectLoads = [&](
const Use &
U,
bool &) {
12636 return !LI || !LI->mayHaveSideEffects();
12638 if (!
A.checkForAllUses(HasNoEffectLoads, *
this, getAssociatedValue()))
12639 return indicatePessimisticFixpoint();
12641 if (
const auto *AMemoryBehavior =
A.getOrCreateAAFor<AAMemoryBehavior>(
12642 getIRPosition(),
this, DepClassTy::REQUIRED)) {
12645 if (!AMemoryBehavior->isAssumedReadOnly())
12646 return indicatePessimisticFixpoint();
12648 if (AMemoryBehavior->isKnownReadOnly()) {
12649 addKnownBits(IS_NOEFFECT);
12650 return ChangeStatus::UNCHANGED;
12653 return ChangeStatus::UNCHANGED;
12656 if (
const Argument *Arg = getAssociatedArgument()) {
12658 addKnownBits(IS_NOEFFECT);
12659 return ChangeStatus::UNCHANGED;
12664 return indicatePessimisticFixpoint();
12667 return ChangeStatus::UNCHANGED;
12671 if (isKnown(IS_LOCALLY_INVARIANT) || !isAssumed(IS_LOCALLY_INVARIANT))
12672 return ChangeStatus::UNCHANGED;
12675 const auto *AUO =
A.getOrCreateAAFor<AAUnderlyingObjects>(
12676 getIRPosition(),
this, DepClassTy::REQUIRED);
12678 return ChangeStatus::UNCHANGED;
12680 bool UsedAssumedInformation =
false;
12681 const auto IsLocallyInvariantLoadIfPointer = [&](
const Value &
V) {
12682 if (!
V.getType()->isPointerTy())
12684 const auto *IsInvariantLoadPointer =
12686 DepClassTy::REQUIRED);
12688 if (!IsInvariantLoadPointer)
12691 if (IsInvariantLoadPointer->isKnownLocallyInvariant())
12693 if (!IsInvariantLoadPointer->isAssumedLocallyInvariant())
12696 UsedAssumedInformation =
true;
12699 if (!AUO->forallUnderlyingObjects(IsLocallyInvariantLoadIfPointer))
12700 return indicatePessimisticFixpoint();
12706 if (!IsLocallyInvariantLoadIfPointer(*Arg))
12707 return indicatePessimisticFixpoint();
12712 if (!UsedAssumedInformation) {
12714 addKnownBits(IS_LOCALLY_INVARIANT);
12715 return ChangeStatus::CHANGED;
12718 return ChangeStatus::UNCHANGED;
12722struct AAInvariantLoadPointerFloating final : AAInvariantLoadPointerImpl {
12723 AAInvariantLoadPointerFloating(
const IRPosition &IRP, Attributor &
A)
12724 : AAInvariantLoadPointerImpl(IRP,
A) {}
12727struct AAInvariantLoadPointerReturned final : AAInvariantLoadPointerImpl {
12728 AAInvariantLoadPointerReturned(
const IRPosition &IRP, Attributor &
A)
12729 : AAInvariantLoadPointerImpl(IRP,
A) {}
12732 removeAssumedBits(IS_LOCALLY_CONSTRAINED);
12736struct AAInvariantLoadPointerCallSiteReturned final
12737 : AAInvariantLoadPointerImpl {
12738 AAInvariantLoadPointerCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
12739 : AAInvariantLoadPointerImpl(IRP,
A) {}
12743 const Function *
F = getAssociatedFunction();
12745 indicatePessimisticFixpoint();
12749 if (!
F->isDeclaration() && !
F->isIntrinsic())
12750 return AAInvariantLoadPointerImpl::initialize(
A);
12755 return AAInvariantLoadPointerImpl::initialize(
A);
12757 if (
F->onlyReadsMemory() &&
F->hasNoSync())
12758 return AAInvariantLoadPointerImpl::initialize(
A);
12762 indicatePessimisticFixpoint();
12766struct AAInvariantLoadPointerArgument final : AAInvariantLoadPointerImpl {
12767 AAInvariantLoadPointerArgument(
const IRPosition &IRP, Attributor &
A)
12768 : AAInvariantLoadPointerImpl(IRP,
A) {}
12771 const Function *
F = getAssociatedFunction();
12772 assert(
F &&
"no associated function for argument");
12775 addKnownBits(IS_LOCALLY_CONSTRAINED);
12779 if (!
F->hasLocalLinkage())
12780 removeAssumedBits(IS_LOCALLY_CONSTRAINED);
12784struct AAInvariantLoadPointerCallSiteArgument final
12785 : AAInvariantLoadPointerImpl {
12786 AAInvariantLoadPointerCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
12787 : AAInvariantLoadPointerImpl(IRP,
A) {}
12794template <
typename InstType>
12795static bool makeChange(Attributor &
A, InstType *MemInst,
const Use &U,
12796 Value *OriginalValue, PointerType *NewPtrTy,
12797 bool UseOriginalValue) {
12798 if (
U.getOperandNo() != InstType::getPointerOperandIndex())
12801 if (MemInst->isVolatile()) {
12802 auto *
TTI =
A.getInfoCache().getAnalysisResultForFunction<TargetIRAnalysis>(
12803 *MemInst->getFunction());
12804 unsigned NewAS = NewPtrTy->getPointerAddressSpace();
12809 if (UseOriginalValue) {
12810 A.changeUseAfterManifest(
const_cast<Use &
>(U), *OriginalValue);
12814 Instruction *CastInst =
new AddrSpaceCastInst(OriginalValue, NewPtrTy);
12816 A.changeUseAfterManifest(
const_cast<Use &
>(U), *CastInst);
12820struct AAAddressSpaceImpl :
public AAAddressSpace {
12821 AAAddressSpaceImpl(
const IRPosition &IRP, Attributor &
A)
12822 : AAAddressSpace(IRP,
A) {}
12825 assert(isValidState() &&
"the AA is invalid");
12826 return AssumedAddressSpace;
12830 assert(getAssociatedType()->isPtrOrPtrVectorTy() &&
12831 "Associated value is not a pointer");
12833 if (!
A.getInfoCache().getFlatAddressSpace().has_value()) {
12834 indicatePessimisticFixpoint();
12838 unsigned FlatAS =
A.getInfoCache().getFlatAddressSpace().value();
12839 unsigned AS = getAssociatedType()->getPointerAddressSpace();
12840 if (AS != FlatAS) {
12841 [[maybe_unused]]
bool R = takeAddressSpace(AS);
12842 assert(R &&
"The take should happen");
12843 indicateOptimisticFixpoint();
12848 uint32_t OldAddressSpace = AssumedAddressSpace;
12849 unsigned FlatAS =
A.getInfoCache().getFlatAddressSpace().value();
12851 auto CheckAddressSpace = [&](
Value &
Obj) {
12857 unsigned ObjAS =
Obj.getType()->getPointerAddressSpace();
12858 if (ObjAS != FlatAS)
12859 return takeAddressSpace(ObjAS);
12873 A.getInfoCache().getAnalysisResultForFunction<TargetIRAnalysis>(*F);
12875 if (AssumedAS != ~0U)
12876 return takeAddressSpace(AssumedAS);
12880 return takeAddressSpace(FlatAS);
12883 auto *AUO =
A.getOrCreateAAFor<AAUnderlyingObjects>(getIRPosition(),
this,
12884 DepClassTy::REQUIRED);
12885 if (!AUO->forallUnderlyingObjects(CheckAddressSpace))
12886 return indicatePessimisticFixpoint();
12888 return OldAddressSpace == AssumedAddressSpace ? ChangeStatus::UNCHANGED
12889 : ChangeStatus::CHANGED;
12895 if (NewAS == InvalidAddressSpace ||
12897 return ChangeStatus::UNCHANGED;
12899 unsigned FlatAS =
A.getInfoCache().getFlatAddressSpace().value();
12901 Value *AssociatedValue = &getAssociatedValue();
12902 Value *OriginalValue = peelAddrspacecast(AssociatedValue, FlatAS);
12905 PointerType::get(getAssociatedType()->
getContext(), NewAS);
12906 bool UseOriginalValue =
12911 auto Pred = [&](
const Use &
U,
bool &) {
12912 if (
U.get() != AssociatedValue)
12923 makeChange(
A, LI, U, OriginalValue, NewPtrTy, UseOriginalValue);
12926 makeChange(
A, SI, U, OriginalValue, NewPtrTy, UseOriginalValue);
12929 makeChange(
A, RMW, U, OriginalValue, NewPtrTy, UseOriginalValue);
12932 makeChange(
A, CmpX, U, OriginalValue, NewPtrTy, UseOriginalValue);
12939 (void)
A.checkForAllUses(Pred, *
this, getAssociatedValue(),
12942 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
12945 const std::string getAsStr(Attributor *
A)
const override {
12946 if (!isValidState())
12947 return "addrspace(<invalid>)";
12948 return "addrspace(" +
12949 (AssumedAddressSpace == InvalidAddressSpace
12951 : std::to_string(AssumedAddressSpace)) +
12956 uint32_t AssumedAddressSpace = InvalidAddressSpace;
12958 bool takeAddressSpace(uint32_t AS) {
12959 if (AssumedAddressSpace == InvalidAddressSpace) {
12960 AssumedAddressSpace = AS;
12963 return AssumedAddressSpace == AS;
12966 static Value *peelAddrspacecast(
Value *V,
unsigned FlatAS) {
12968 assert(
I->getSrcAddressSpace() != FlatAS &&
12969 "there should not be flat AS -> non-flat AS");
12970 return I->getPointerOperand();
12973 if (
C->getOpcode() == Instruction::AddrSpaceCast) {
12974 assert(
C->getOperand(0)->getType()->getPointerAddressSpace() !=
12976 "there should not be flat AS -> non-flat AS X");
12977 return C->getOperand(0);
12983struct AAAddressSpaceFloating final : AAAddressSpaceImpl {
12984 AAAddressSpaceFloating(
const IRPosition &IRP, Attributor &
A)
12985 : AAAddressSpaceImpl(IRP,
A) {}
12987 void trackStatistics()
const override {
12992struct AAAddressSpaceReturned final : AAAddressSpaceImpl {
12993 AAAddressSpaceReturned(
const IRPosition &IRP, Attributor &
A)
12994 : AAAddressSpaceImpl(IRP,
A) {}
12999 (void)indicatePessimisticFixpoint();
13002 void trackStatistics()
const override {
13007struct AAAddressSpaceCallSiteReturned final : AAAddressSpaceImpl {
13008 AAAddressSpaceCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
13009 : AAAddressSpaceImpl(IRP,
A) {}
13011 void trackStatistics()
const override {
13016struct AAAddressSpaceArgument final : AAAddressSpaceImpl {
13017 AAAddressSpaceArgument(
const IRPosition &IRP, Attributor &
A)
13018 : AAAddressSpaceImpl(IRP,
A) {}
13023struct AAAddressSpaceCallSiteArgument final : AAAddressSpaceImpl {
13024 AAAddressSpaceCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
13025 : AAAddressSpaceImpl(IRP,
A) {}
13030 (void)indicatePessimisticFixpoint();
13033 void trackStatistics()
const override {
13048struct AANoAliasAddrSpaceImpl :
public AANoAliasAddrSpace {
13049 AANoAliasAddrSpaceImpl(
const IRPosition &IRP, Attributor &
A)
13050 : AANoAliasAddrSpace(IRP,
A) {}
13053 assert(getAssociatedType()->isPtrOrPtrVectorTy() &&
13054 "Associated value is not a pointer");
13058 std::optional<unsigned> FlatAS =
A.getInfoCache().getFlatAddressSpace();
13059 if (!FlatAS.has_value()) {
13060 indicatePessimisticFixpoint();
13066 unsigned AS = getAssociatedType()->getPointerAddressSpace();
13067 if (AS != *FlatAS) {
13069 indicateOptimisticFixpoint();
13074 unsigned FlatAS =
A.getInfoCache().getFlatAddressSpace().value();
13075 uint32_t OldAssumed = getAssumed();
13077 auto CheckAddressSpace = [&](
Value &
Obj) {
13081 unsigned AS =
Obj.getType()->getPointerAddressSpace();
13085 removeAS(
Obj.getType()->getPointerAddressSpace());
13089 const AAUnderlyingObjects *AUO =
A.getOrCreateAAFor<AAUnderlyingObjects>(
13090 getIRPosition(),
this, DepClassTy::REQUIRED);
13092 return indicatePessimisticFixpoint();
13094 return OldAssumed == getAssumed() ? ChangeStatus::UNCHANGED
13095 : ChangeStatus::CHANGED;
13099 unsigned FlatAS =
A.getInfoCache().getFlatAddressSpace().value();
13101 unsigned AS = getAssociatedType()->getPointerAddressSpace();
13102 if (AS != FlatAS ||
Map.empty())
13103 return ChangeStatus::UNCHANGED;
13105 LLVMContext &Ctx = getAssociatedValue().getContext();
13106 MDNode *NoAliasASNode =
nullptr;
13107 MDBuilder MDB(Ctx);
13109 for (RangeMap::const_iterator
I =
Map.begin();
I !=
Map.end();
I++) {
13112 unsigned Upper =
I.stop();
13113 unsigned Lower =
I.start();
13114 if (!NoAliasASNode) {
13115 NoAliasASNode = MDB.createRange(APInt(32,
Lower), APInt(32,
Upper + 1));
13118 MDNode *ASRange = MDB.createRange(APInt(32,
Lower), APInt(32,
Upper + 1));
13122 Value *AssociatedValue = &getAssociatedValue();
13125 auto AddNoAliasAttr = [&](
const Use &
U,
bool &) {
13126 if (
U.get() != AssociatedValue)
13129 if (!Inst || Inst->
hasMetadata(LLVMContext::MD_noalias_addrspace))
13136 Inst->
setMetadata(LLVMContext::MD_noalias_addrspace, NoAliasASNode);
13140 (void)
A.checkForAllUses(AddNoAliasAttr, *
this, *AssociatedValue,
13142 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
13145 const std::string getAsStr(Attributor *
A)
const override {
13146 if (!isValidState())
13147 return "<invalid>";
13149 raw_string_ostream OS(Str);
13150 OS <<
"CanNotBeAddrSpace(";
13151 for (RangeMap::const_iterator
I =
Map.begin();
I !=
Map.end();
I++) {
13152 unsigned Upper =
I.stop();
13153 unsigned Lower =
I.start();
13154 OS <<
' ' <<
'[' <<
Upper <<
',' <<
Lower + 1 <<
')';
13161 void removeAS(
unsigned AS) {
13162 RangeMap::iterator
I =
Map.find(AS);
13164 if (
I !=
Map.end()) {
13165 unsigned Upper =
I.stop();
13166 unsigned Lower =
I.start();
13170 if (AS != ~((
unsigned)0) && AS + 1 <=
Upper)
13172 if (AS != 0 &&
Lower <= AS - 1)
13177 void resetASRanges(Attributor &
A) {
13179 Map.insert(0,
A.getInfoCache().getMaxAddrSpace(),
true);
13183struct AANoAliasAddrSpaceFloating final : AANoAliasAddrSpaceImpl {
13184 AANoAliasAddrSpaceFloating(
const IRPosition &IRP, Attributor &
A)
13185 : AANoAliasAddrSpaceImpl(IRP,
A) {}
13187 void trackStatistics()
const override {
13192struct AANoAliasAddrSpaceReturned final : AANoAliasAddrSpaceImpl {
13193 AANoAliasAddrSpaceReturned(
const IRPosition &IRP, Attributor &
A)
13194 : AANoAliasAddrSpaceImpl(IRP,
A) {}
13196 void trackStatistics()
const override {
13201struct AANoAliasAddrSpaceCallSiteReturned final : AANoAliasAddrSpaceImpl {
13202 AANoAliasAddrSpaceCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
13203 : AANoAliasAddrSpaceImpl(IRP,
A) {}
13205 void trackStatistics()
const override {
13210struct AANoAliasAddrSpaceArgument final : AANoAliasAddrSpaceImpl {
13211 AANoAliasAddrSpaceArgument(
const IRPosition &IRP, Attributor &
A)
13212 : AANoAliasAddrSpaceImpl(IRP,
A) {}
13214 void trackStatistics()
const override {
13219struct AANoAliasAddrSpaceCallSiteArgument final : AANoAliasAddrSpaceImpl {
13220 AANoAliasAddrSpaceCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
13221 : AANoAliasAddrSpaceImpl(IRP,
A) {}
13223 void trackStatistics()
const override {
13230struct AAAllocationInfoImpl :
public AAAllocationInfo {
13231 AAAllocationInfoImpl(
const IRPosition &IRP, Attributor &
A)
13232 : AAAllocationInfo(IRP,
A) {}
13234 std::optional<TypeSize> getAllocatedSize()
const override {
13235 assert(isValidState() &&
"the AA is invalid");
13236 return AssumedAllocatedSize;
13239 std::optional<TypeSize> findInitialAllocationSize(Instruction *
I,
13240 const DataLayout &
DL) {
13243 switch (
I->getOpcode()) {
13244 case Instruction::Alloca: {
13249 return std::nullopt;
13255 const IRPosition &IRP = getIRPosition();
13260 return indicatePessimisticFixpoint();
13262 bool IsKnownNoCapture;
13264 A,
this, IRP, DepClassTy::OPTIONAL, IsKnownNoCapture))
13265 return indicatePessimisticFixpoint();
13267 const AAPointerInfo *PI =
13268 A.getOrCreateAAFor<AAPointerInfo>(IRP, *
this, DepClassTy::REQUIRED);
13271 return indicatePessimisticFixpoint();
13274 return indicatePessimisticFixpoint();
13276 const DataLayout &
DL =
A.getDataLayout();
13277 const auto AllocationSize = findInitialAllocationSize(
I,
DL);
13280 if (!AllocationSize)
13281 return indicatePessimisticFixpoint();
13285 if (*AllocationSize == 0)
13286 return indicatePessimisticFixpoint();
13292 return indicatePessimisticFixpoint();
13294 if (BinSize == 0) {
13295 auto NewAllocationSize = std::make_optional<TypeSize>(0,
false);
13296 if (!changeAllocationSize(NewAllocationSize))
13297 return ChangeStatus::UNCHANGED;
13298 return ChangeStatus::CHANGED;
13302 const auto &It = PI->
begin();
13305 if (It->first.Offset != 0)
13306 return indicatePessimisticFixpoint();
13308 uint64_t SizeOfBin = It->first.Offset + It->first.Size;
13310 if (SizeOfBin >= *AllocationSize)
13311 return indicatePessimisticFixpoint();
13313 auto NewAllocationSize = std::make_optional<TypeSize>(SizeOfBin * 8,
false);
13315 if (!changeAllocationSize(NewAllocationSize))
13316 return ChangeStatus::UNCHANGED;
13318 return ChangeStatus::CHANGED;
13323 assert(isValidState() &&
13324 "Manifest should only be called if the state is valid.");
13328 auto FixedAllocatedSizeInBits = getAllocatedSize()->getFixedValue();
13330 unsigned long NumBytesToAllocate = (FixedAllocatedSizeInBits + 7) / 8;
13332 switch (
I->getOpcode()) {
13334 case Instruction::Alloca: {
13338 Type *CharType = Type::getInt8Ty(
I->getContext());
13340 auto *NumBytesToValue =
13341 ConstantInt::get(
I->getContext(), APInt(32, NumBytesToAllocate));
13344 insertPt = std::next(insertPt);
13345 AllocaInst *NewAllocaInst =
13350 return ChangeStatus::CHANGED;
13358 return ChangeStatus::UNCHANGED;
13361 const std::string getAsStr(Attributor *
A)
const override {
13362 if (!isValidState())
13363 return "allocationinfo(<invalid>)";
13364 return "allocationinfo(" +
13365 (AssumedAllocatedSize == HasNoAllocationSize
13367 : std::to_string(AssumedAllocatedSize->getFixedValue())) +
13372 std::optional<TypeSize> AssumedAllocatedSize = HasNoAllocationSize;
13376 bool changeAllocationSize(std::optional<TypeSize>
Size) {
13377 if (AssumedAllocatedSize == HasNoAllocationSize ||
13378 AssumedAllocatedSize !=
Size) {
13379 AssumedAllocatedSize =
Size;
13386struct AAAllocationInfoFloating : AAAllocationInfoImpl {
13387 AAAllocationInfoFloating(
const IRPosition &IRP, Attributor &
A)
13388 : AAAllocationInfoImpl(IRP,
A) {}
13390 void trackStatistics()
const override {
13395struct AAAllocationInfoReturned : AAAllocationInfoImpl {
13396 AAAllocationInfoReturned(
const IRPosition &IRP, Attributor &
A)
13397 : AAAllocationInfoImpl(IRP,
A) {}
13402 (void)indicatePessimisticFixpoint();
13405 void trackStatistics()
const override {
13410struct AAAllocationInfoCallSiteReturned : AAAllocationInfoImpl {
13411 AAAllocationInfoCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
13412 : AAAllocationInfoImpl(IRP,
A) {}
13414 void trackStatistics()
const override {
13419struct AAAllocationInfoArgument : AAAllocationInfoImpl {
13420 AAAllocationInfoArgument(
const IRPosition &IRP, Attributor &
A)
13421 : AAAllocationInfoImpl(IRP,
A) {}
13423 void trackStatistics()
const override {
13428struct AAAllocationInfoCallSiteArgument : AAAllocationInfoImpl {
13429 AAAllocationInfoCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
13430 : AAAllocationInfoImpl(IRP,
A) {}
13434 (void)indicatePessimisticFixpoint();
13437 void trackStatistics()
const override {
13486#define SWITCH_PK_INV(CLASS, PK, POS_NAME) \
13487 case IRPosition::PK: \
13488 llvm_unreachable("Cannot create " #CLASS " for a " POS_NAME " position!");
13490#define SWITCH_PK_CREATE(CLASS, IRP, PK, SUFFIX) \
13491 case IRPosition::PK: \
13492 AA = new (A.Allocator) CLASS##SUFFIX(IRP, A); \
13496#define CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13497 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13498 CLASS *AA = nullptr; \
13499 switch (IRP.getPositionKind()) { \
13500 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13501 SWITCH_PK_INV(CLASS, IRP_FLOAT, "floating") \
13502 SWITCH_PK_INV(CLASS, IRP_ARGUMENT, "argument") \
13503 SWITCH_PK_INV(CLASS, IRP_RETURNED, "returned") \
13504 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_RETURNED, "call site returned") \
13505 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_ARGUMENT, "call site argument") \
13506 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
13507 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE, CallSite) \
13512#define CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13513 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13514 CLASS *AA = nullptr; \
13515 switch (IRP.getPositionKind()) { \
13516 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13517 SWITCH_PK_INV(CLASS, IRP_FUNCTION, "function") \
13518 SWITCH_PK_INV(CLASS, IRP_CALL_SITE, "call site") \
13519 SWITCH_PK_CREATE(CLASS, IRP, IRP_FLOAT, Floating) \
13520 SWITCH_PK_CREATE(CLASS, IRP, IRP_ARGUMENT, Argument) \
13521 SWITCH_PK_CREATE(CLASS, IRP, IRP_RETURNED, Returned) \
13522 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_RETURNED, CallSiteReturned) \
13523 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_ARGUMENT, CallSiteArgument) \
13528#define CREATE_ABSTRACT_ATTRIBUTE_FOR_ONE_POSITION(POS, SUFFIX, CLASS) \
13529 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13530 CLASS *AA = nullptr; \
13531 switch (IRP.getPositionKind()) { \
13532 SWITCH_PK_CREATE(CLASS, IRP, POS, SUFFIX) \
13534 llvm_unreachable("Cannot create " #CLASS " for position otherthan " #POS \
13540#define CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13541 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13542 CLASS *AA = nullptr; \
13543 switch (IRP.getPositionKind()) { \
13544 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13545 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
13546 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE, CallSite) \
13547 SWITCH_PK_CREATE(CLASS, IRP, IRP_FLOAT, Floating) \
13548 SWITCH_PK_CREATE(CLASS, IRP, IRP_ARGUMENT, Argument) \
13549 SWITCH_PK_CREATE(CLASS, IRP, IRP_RETURNED, Returned) \
13550 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_RETURNED, CallSiteReturned) \
13551 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_ARGUMENT, CallSiteArgument) \
13556#define CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13557 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13558 CLASS *AA = nullptr; \
13559 switch (IRP.getPositionKind()) { \
13560 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13561 SWITCH_PK_INV(CLASS, IRP_ARGUMENT, "argument") \
13562 SWITCH_PK_INV(CLASS, IRP_FLOAT, "floating") \
13563 SWITCH_PK_INV(CLASS, IRP_RETURNED, "returned") \
13564 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_RETURNED, "call site returned") \
13565 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_ARGUMENT, "call site argument") \
13566 SWITCH_PK_INV(CLASS, IRP_CALL_SITE, "call site") \
13567 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
13572#define CREATE_NON_RET_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13573 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13574 CLASS *AA = nullptr; \
13575 switch (IRP.getPositionKind()) { \
13576 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13577 SWITCH_PK_INV(CLASS, IRP_RETURNED, "returned") \
13578 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
13579 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE, CallSite) \
13580 SWITCH_PK_CREATE(CLASS, IRP, IRP_FLOAT, Floating) \
13581 SWITCH_PK_CREATE(CLASS, IRP, IRP_ARGUMENT, Argument) \
13582 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_RETURNED, CallSiteReturned) \
13583 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_ARGUMENT, CallSiteArgument) \
13635#undef CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION
13636#undef CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION
13637#undef CREATE_NON_RET_ABSTRACT_ATTRIBUTE_FOR_POSITION
13638#undef CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION
13639#undef CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION
13640#undef CREATE_ABSTRACT_ATTRIBUTE_FOR_ONE_POSITION
13641#undef SWITCH_PK_CREATE
13642#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.
bool contains(Attribute::AttrKind A) const
Return true if the builder has the specified attribute.
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.
OperandBundleUse getOperandBundleForOperand(unsigned OpIdx) const
Return the operand bundle for the operand at index OpIdx.
LLVM_ABI std::optional< ConstantRange > getRange() const
If this return value has a range attribute, return the value range of the argument.
Value * getArgOperand(unsigned i) const
bool isBundleOperand(unsigned Idx) const
Return true if the operand at index Idx is a bundle operand.
bool isConvergent() const
Determine if the invoke is convergent.
FunctionType * getFunctionType() const
LLVM_ABI Intrinsic::ID getIntrinsicID() const
Returns the intrinsic ID of the intrinsic called or Intrinsic::not_intrinsic if the called function i...
iterator_range< User::op_iterator > args()
Iteration adapter for range-for loops.
unsigned getArgOperandNo(const Use *U) const
Given a use for a arg operand, get the arg operand number that corresponds to it.
unsigned arg_size() const
bool isArgOperand(const Use *U) const
LLVM_ABI Function * getCaller()
Helper to get the caller (the parent function).
static CallInst * Create(FunctionType *Ty, Value *F, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
static CaptureInfo none()
Create CaptureInfo that does not capture any components of the pointer.
Instruction::CastOps getOpcode() const
Return the opcode of this CastInst.
LLVM_ABI bool isIntegerCast() const
There are several places where we need to know if a cast instruction only deals with integer source a...
Type * getDestTy() const
Return the destination type, as a convenience.
bool isEquality() const
Determine if this is an equals/not equals predicate.
bool isFalseWhenEqual() const
This is just a convenience.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
bool isTrueWhenEqual() const
This is just a convenience.
Predicate getPredicate() const
Return the predicate for this instruction.
Conditional Branch instruction.
Value * getCondition() const
BasicBlock * getSuccessor(unsigned i) const
static LLVM_ABI Constant * getExtractElement(Constant *Vec, Constant *Idx, Type *OnlyIfReducedTy=nullptr)
static LLVM_ABI ConstantInt * getTrue(LLVMContext &Context)
This class represents a range of values.
const APInt & getLower() const
Return the lower value for this range.
LLVM_ABI bool isFullSet() const
Return true if this set contains all of the elements possible for this data-type.
LLVM_ABI bool isEmptySet() const
Return true if this set contains no members.
bool isSingleElement() const
Return true if this set contains exactly one member.
static LLVM_ABI ConstantRange makeAllowedICmpRegion(CmpInst::Predicate Pred, const ConstantRange &Other)
Produce the smallest range such that all values that may satisfy the given predicate with any value c...
const APInt & getUpper() const
Return the upper value for this range.
LLVM_ABI bool contains(const APInt &Val) const
Return true if the specified value is in the set.
Opaque handle to a cycle within a GenericCycleInfo that wraps the cycle's preorder index.
A parsed version of the target data layout string in and methods for querying it.
unsigned getProgramAddressSpace() const
bool contains(const_arg_type_t< KeyT > Val) const
Return true if the specified key is in the map, false otherwise.
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
iterator find(const_arg_type_t< KeyT > Val)
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
Analysis pass which computes a DominatorTree.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
LLVM_ABI bool dominates(const BasicBlock *BB, const Use &U) const
Return true if the (end of the) basic block BB dominates the use U.
const BasicBlock & getEntryBlock() const
iterator_range< arg_iterator > args()
const Function & getFunction() const
Argument * getArg(unsigned i) const
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
BlockT * getHeader(CycleRef C) const
CycleRef getCycle(const BlockT *Block) const
Find the innermost cycle containing Block.
LLVM_ABI bool isDeclaration() const
Return true if the primary definition of this global value is outside of the current translation unit...
bool hasLocalLinkage() const
PointerType * getType() const
Global values are always pointers.
static LLVM_ABI bool compare(const APInt &LHS, const APInt &RHS, ICmpInst::Predicate Pred)
Return result of LHS Pred RHS comparison.
Value * CreatePtrAdd(Value *Ptr, Value *Offset, const Twine &Name="", GEPNoWrapFlags NW=GEPNoWrapFlags::none())
ConstantInt * getInt64(uint64_t C)
Get a constant 64-bit value.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
LLVM_ABI Instruction * clone() const
Create a copy of 'this' instruction that is identical in all ways except the following:
LLVM_ABI bool isLifetimeStartOrEnd() const LLVM_READONLY
Return true if the instruction is a llvm.lifetime.start or llvm.lifetime.end marker.
bool mayReadOrWriteMemory() const
Return true if this instruction may read or write memory.
LLVM_ABI bool mayWriteToMemory() const LLVM_READONLY
Return true if this instruction may modify memory.
bool hasMetadata() const
Return true if this instruction has any metadata attached to it.
LLVM_ABI void insertBefore(InstListType::iterator InsertPos)
Insert an unlinked instruction into a basic block immediately before the specified position.
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
LLVM_ABI const Function * getFunction() const
Return the function this instruction belongs to.
LLVM_ABI BasicBlock * getSuccessor(unsigned Idx) const LLVM_READONLY
Return the specified successor. This instruction must be a terminator.
LLVM_ABI bool mayHaveSideEffects() const LLVM_READONLY
Return true if the instruction may have side effects.
bool isTerminator() const
LLVM_ABI bool mayReadFromMemory() const LLVM_READONLY
Return true if this instruction may read memory.
iterator_range< user_iterator > users()
LLVM_ABI void setMetadata(unsigned KindID, MDNode *Node)
Set the metadata of the specified kind to the specified node.
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
FPClassTest getKnownFPClasses() const
Floating-point classes the value could be one of.
This is an important class for using LLVM in a threaded context.
LLVM_ABI ConstantRange getConstantRange(Value *V, Instruction *CtxI, bool UndefAllowed)
Return the ConstantRange constraint that is known to hold for the specified value at the specified in...
LoopT * getLoopFor(const BlockT *BB) const
Return the inner most loop that BB lives in.
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
static LLVM_ABI MDNode * getMostGenericRange(MDNode *A, MDNode *B)
static MemoryEffectsBase readOnly()
bool doesNotAccessMemory() const
Whether this function accesses no memory.
static MemoryEffectsBase argMemOnly(ModRefInfo MR=ModRefInfo::ModRef)
static MemoryEffectsBase inaccessibleMemOnly(ModRefInfo MR=ModRefInfo::ModRef)
bool onlyAccessesInaccessibleMem() const
Whether this function only (at most) accesses inaccessible memory.
ModRefInfo getModRef(Location Loc) const
Get ModRefInfo for the given Location.
bool onlyAccessesArgPointees() const
Whether this function only (at most) accesses argument memory.
bool onlyReadsMemory() const
Whether this function only (at most) reads memory.
static MemoryEffectsBase writeOnly()
static MemoryEffectsBase inaccessibleOrArgMemOnly(ModRefInfo MR=ModRefInfo::ModRef)
static MemoryEffectsBase none()
bool onlyAccessesInaccessibleOrArgMem() const
Whether this function only (at most) accesses argument and inaccessible memory.
static MemoryEffectsBase unknown()
static LLVM_ABI std::optional< MemoryLocation > getOrNone(const Instruction *Inst)
static SizeOffsetValue unknown()
static PHINode * Create(Type *Ty, unsigned NumReservedValues, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
Constructors - NumReservedValues is a hint for the number of incoming edges that this phi node will h...
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
Value * getReturnValue() const
Convenience accessor. Returns null if there is no return value.
LLVM_ABI SCEVUse getSCEVAtScope(const SCEV *S, const Loop *L)
Return a SCEV expression for the specified value at the specified scope in the program.
LLVM_ABI const SCEV * getSCEV(Value *V)
Return a SCEV expression for the full generality of the specified expression.
LLVM_ABI unsigned getSmallConstantMaxTripCount(const Loop *L, SmallVectorImpl< const SCEVPredicate * > *Predicates=nullptr)
Returns the upper bound of the loop trip count as a normal unsigned value.
ConstantRange getUnsignedRange(const SCEV *S)
Determine the unsigned range for a particular SCEV.
A vector that has set insertion semantics.
size_type size() const
Determine the number of elements in the SetVector.
bool insert(const value_type &X)
Insert a new element into the SetVector.
bool erase(PtrType Ptr)
Remove pointer from the set.
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Used to lazily calculate structure layout information for a target machine, based on the DataLayout s...
TypeSize getElementOffset(unsigned Idx) const
TypeSize getSizeInBits() 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.
@ 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
BundleAttr getBundleAttrFromOBU(OperandBundleUse OBU)
@ Known
Known to have no common set bits.
@ Undef
Value of the register doesn't matter.
auto pred_end(const MachineBasicBlock *BB)
unsigned getPointerAddressSpace(const Type *T)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
auto successors(const MachineBasicBlock *BB)
LLVM_ABI bool isRemovableAlloc(const CallBase *V, const TargetLibraryInfo *TLI)
Return true if this is a call to an allocation function that does not have side effects that we are r...
APFloat abs(APFloat X)
Returns the absolute value of the argument.
@ Load
The value being inserted comes from a load (InsertElement only).
@ Store
The extracted value is stored (ExtractElement only).
LLVM_ABI raw_fd_ostream & outs()
This returns a reference to a raw_fd_ostream for standard output.
LLVM_ABI Value * getAllocAlignment(const CallBase *V, const TargetLibraryInfo *TLI)
Gets the alignment argument for an aligned_alloc-like function, using either built-in knowledge based...
auto dyn_cast_if_present(const Y &Val)
dyn_cast_if_present<X> - Functionally identical to dyn_cast, except that a null (or none in the case ...
LLVM_ABI Value * simplifyInstructionWithOperands(Instruction *I, ArrayRef< Value * > NewOps, const SimplifyQuery &Q)
Like simplifyInstruction but the operands of I are replaced with NewOps.
Value * GetPointerBaseWithConstantOffset(Value *Ptr, int64_t &Offset, const DataLayout &DL, bool AllowNonInbounds=true)
Analyze the specified pointer to see if it can be expressed as a base pointer plus a constant offset.
scc_iterator< T > scc_begin(const T &G)
Construct the begin iterator for a deduced graph type T.
LLVM_ABI bool isNoAliasCall(const Value *V)
Return true if this pointer is returned by a noalias function.
MemoryEffectsBase< IRMemLocation > MemoryEffects
Summary of how a function affects memory in the program.
raw_ostream & WriteGraph(raw_ostream &O, const GraphType &G, bool ShortNames=false, const Twine &Title="")
LLVM_ABI bool isSafeToSpeculativelyExecute(const Instruction *I, const Instruction *CtxI=nullptr, AssumptionCache *AC=nullptr, const DominatorTree *DT=nullptr, const TargetLibraryInfo *TLI=nullptr, bool UseVariableInfo=true, bool IgnoreUBImplyingAttrs=true)
Return true if the instruction does not have any effects besides calculating the result and does not ...
bool isa_and_nonnull(const Y &Val)
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
LLVM_ABI ConstantRange getConstantRangeFromMetadata(const MDNode &RangeMD)
Parse out a conservative ConstantRange from !range metadata.
auto map_range(ContainerTy &&C, FuncTy F)
Return a range that applies F to the elements of C.
const Value * getPointerOperand(const Value *V)
A helper function that returns the pointer operand of a load, store or GEP instruction.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
LLVM_ABI Value * simplifyInstruction(Instruction *I, const SimplifyQuery &Q)
See if we can compute a simplified version of this instruction.
auto dyn_cast_or_null(const Y &Val)
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
PotentialValuesState< std::pair< AA::ValueAndContext, AA::ValueScope > > PotentialLLVMValuesState
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI bool NullPointerIsDefined(const Function *F, unsigned AS=0)
Check whether null pointer dereferencing is considered undefined behavior for a given function or an ...
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool isPointerTy(const Type *T)
IRBuilder(LLVMContext &, FolderTy, InserterTy) -> IRBuilder< FolderTy, InserterTy >
LLVM_ABI bool wouldInstructionBeTriviallyDead(const Instruction *I, const TargetLibraryInfo *TLI=nullptr)
Return true if the result produced by the instruction would have no side effects if it was not used.
bool set_union(S1Ty &S1, const S2Ty &S2)
set_union(A, B) - Compute A := A u B, return whether A changed.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
LLVM_ABI CallBase & promoteCall(CallBase &CB, Function *Callee, CastInst **RetBitCast=nullptr)
Promote the given indirect call site to unconditionally call Callee.
LLVM_ABI const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth, bool MustPreserveProvenance=false)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ABI bool hasAssumption(const Function &F, const KnownAssumptionString &AssumptionStr)
Return true if F has the assumption AssumptionStr attached.
@ Success
The lock was released successfully.
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
LLVM_ABI bool isKnownNonZero(const Value *V, const SimplifyQuery &Q, unsigned Depth=0)
Return true if the given value is known to be non-zero when defined.
AtomicOrdering
Atomic ordering for LLVM's memory model.
PotentialValuesState< APInt > PotentialConstantIntValuesState
std::string join(IteratorT Begin, IteratorT End, StringRef Separator)
Joins the strings in the range [Begin, End), adding Separator between the elements.
InterleavedRange< Range > interleaved_array(const Range &R, StringRef Separator=", ")
Output range R as an array of interleaved elements.
ChangeStatus clampStateAndIndicateChange< DerefState >(DerefState &S, const DerefState &R)
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
void RemapInstruction(Instruction *I, ValueToValueMapTy &VM, RemapFlags Flags=RF_None, ValueMapTypeRemapper *TypeMapper=nullptr, ValueMaterializer *Materializer=nullptr, const MetadataPredicate *IdentityMD=nullptr)
Convert the instruction operands from referencing the current values into those specified by VM.
LLVM_ABI bool isIntrinsicReturningPointerAliasingArgumentWithoutCapturing(const CallBase *Call, bool MustPreserveOffset, bool MustPreserveProvenance=false)
launder.invariant.group and similar intrinsics return a pointer that aliases their argument,...
DWARFExpression::Operation Op
LLVM_ABI bool isGuaranteedNotToBeUndefOrPoison(const Value *V, AssumptionCache *AC=nullptr, const Instruction *CtxI=nullptr, const DominatorTree *DT=nullptr, unsigned Depth=0)
Return true if this function can prove that V does not have undef bits and is never poison.
ArrayRef(const T &OneElt) -> ArrayRef< T >
LLVM_ABI Value * getFreedOperand(const CallBase *CB, const TargetLibraryInfo *TLI)
If this if a call to a free function, return the freed operand.
ChangeStatus clampStateAndIndicateChange(StateType &S, const StateType &R)
Helper function to clamp a state S of type StateType with the information in R and indicate/return if...
constexpr unsigned BitWidth
ValueMap< const Value *, WeakTrackingVH > ValueToValueMapTy
auto pred_begin(const MachineBasicBlock *BB)
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
iterator_range< pointer_iterator< WrappedIteratorT > > make_pointer_range(RangeT &&Range)
LLVM_ABI std::optional< APInt > getAllocSize(const CallBase *CB, const TargetLibraryInfo *TLI, function_ref< const Value *(const Value *)> Mapper=[](const Value *V) { return V;})
Return the size of the requested allocation.
LLVM_ABI DenseSet< StringRef > getAssumptions(const Function &F)
Return the set of all assumptions for the function F.
Align assumeAligned(uint64_t Value)
Treats the value 0 as a 1, so Align is always at least 1.
LLVM_ABI Instruction * SplitBlockAndInsertIfThen(Value *Cond, BasicBlock::iterator SplitBefore, bool Unreachable, MDNode *BranchWeights=nullptr, DomTreeUpdater *DTU=nullptr, LoopInfo *LI=nullptr, BasicBlock *ThenBlock=nullptr)
Split the containing block at the specified instruction - everything before SplitBefore stays in the ...
@ OPTIONAL
The target may be valid if the source is not.
@ NONE
Do not track a dependence between source and target.
@ REQUIRED
The target cannot be valid if the source is not.
LLVM_ABI UseCaptureInfo DetermineUseCaptureKind(const Use &U, const Value *Base)
Determine what kind of capture behaviour U may exhibit.
LLVM_ABI Value * simplifyCmpInst(CmpPredicate Predicate, Value *LHS, Value *RHS, const SimplifyQuery &Q)
Given operands for a CmpInst, fold the result or return null.
LLVM_ABI bool mayContainIrreducibleControl(const Function &F, const LoopInfo *LI)
BumpPtrAllocatorImpl<> BumpPtrAllocator
The standard BumpPtrAllocator which just uses the default template parameters.
T bit_floor(T Value)
Returns the largest integral power of two no greater than Value if Value is nonzero.
bool capturesNothing(CaptureComponents CC)
LLVM_ABI AssumeDereferenceableInfo getAssumeDereferenceableInfo(OperandBundleUse)
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
Return if this abstract state is fixed, thus does not need to be updated if information changes as it...
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
Indicate that the abstract state should converge to the optimistic state.
State & operator=(const State &R)
ChangeStatus indicatePessimisticFixpoint() override
Indicate that the abstract state should converge to the pessimistic state.
const State & getAssumed() const
static State getBestState(const State &SIS)
Return the best possible representable state.
bool isValidState() const override
Return if this abstract state is in a valid state.
----------------—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)
---------------------— NoAlias Argument Attribute ---------------------—
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)
--------------------— Variable Capturing ------------------------------—
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)
---------------------— NoUndef Attribute ------------------------------—
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)
---------------------— NonNull Argument Attribute ---------------------—
A helper containing a list of offsets computed for a Use.
A container for a list of ranges.
static void set_difference(const RangeList &L, const RangeList &R, RangeList &D)
Copy ranges from L that are not in R, into D.
An abstract interface for struct information.
virtual bool reachesReturn() const =0
OffsetBinsTy::const_iterator const_bin_iterator
virtual const_bin_iterator begin() const =0
DenseMap< AA::RangeTy, SmallSet< unsigned, 4 > > OffsetBinsTy
static LLVM_ABI const char ID
Unique ID (due to the unique address)
virtual int64_t numOffsetBins() const =0
An abstract interface for potential values analysis.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
static LLVM_ABI const char ID
Unique ID (due to the unique address)
static LLVM_ABI Value * getSingleValue(Attributor &A, const AbstractAttribute &AA, const IRPosition &IRP, SmallVectorImpl< AA::ValueAndContext > &Values)
Extract the single value in Values if any.
An abstract interface for privatizability.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract attribute for undefined behavior.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract attribute for getting all assumption underlying objects.
virtual bool forallUnderlyingObjects(function_ref< bool(Value &)> Pred, AA::ValueScope Scope=AA::Interprocedural) const =0
Check Pred on all underlying objects in Scope collected so far.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for range value analysis.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for value simplify abstract attribute.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract attribute for willreturn.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
Helper to represent an access offset and size, with logic to deal with uncertainty and check for over...
static constexpr int64_t Unknown
static RangeTy getUnknown()
const Instruction * getCtxI() const
Base struct for all "concrete attribute" deductions.
void print(raw_ostream &OS) const
Helper functions, for debug purposes only.
virtual StateType & getState()=0
Return the internal abstract state for inspection.
An interface to query the internal state of an abstract attribute.
virtual bool isAtFixpoint() const =0
Return if this abstract state is fixed, thus does not need to be updated if information changes as it...
virtual bool isValidState() const =0
Return if this abstract state is in a valid state.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
static constexpr Align fromLog2(unsigned Log2Value)
Returns an alignment of 1 << Log2Value bytes.
std::function< void( const ArgumentReplacementInfo &, Function &, Function::arg_iterator)> CalleeRepairCBTy
Callee repair callback type.
const Argument & getReplacedArg() const
std::function< void(const ArgumentReplacementInfo &, AbstractCallSite, SmallVectorImpl< Value * > &)> ACSRepairCBTy
Abstract call site (ACS) repair callback type.
The fixpoint analysis framework that orchestrates the attribute deduction.
std::function< std::optional< Value * >( const IRPosition &, const AbstractAttribute *, bool &)> SimplifictionCallbackTy
Register CB as a simplification callback.
Specialization of the integer state for a bit-wise encoding.
BitIntegerState & addKnownBits(base_t Bits)
Add the bits in BitsEncoding to the "known bits".
Simple wrapper for a single bit (boolean) state.
static constexpr DenormalFPEnv getDefault()
static unsigned getHashValue(const Access &A)
AAPointerInfo::Access Access
static bool isEqual(const Access &LHS, const Access &RHS)
static bool isEqual(const AA::RangeTy &A, const AA::RangeTy B)
static unsigned getHashValue(const AA::RangeTy &Range)
DenseMapInfo< std::pair< const Instruction *, const ToTy * > > PairDMI
static bool isEqual(const ReachabilityQueryInfo< ToTy > *LHS, const ReachabilityQueryInfo< ToTy > *RHS)
DenseMapInfo< const AA::InstExclusionSetTy * > InstSetDMI
static unsigned getHashValue(const ReachabilityQueryInfo< ToTy > *RQI)
An information struct used to provide DenseMap with the various necessary components for a given valu...
State for dereferenceable attribute.
IncIntegerState DerefBytesState
State representing for dereferenceable bytes.
ChangeStatus manifest(Attributor &A) override
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.
Kind
The positions we distinguish in the IR.
@ 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...
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
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.