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,
5801 bool NoThrow =
F.doesNotThrow();
5802 bool WillReturn =
F.willReturn();
5803 bool IsVoidReturn =
F.getReturnType()->isVoidTy();
5804 if (
ReadOnly && NoThrow && WillReturn && IsVoidReturn) {
5817 if (NoThrow && IsVoidReturn)
5822 if (!NoThrow || ArgNo < 0 ||
5823 !
F.getAttributes().hasAttrSomewhere(Attribute::Returned))
5826 for (
unsigned U = 0, E =
F.arg_size(); U < E; ++U)
5827 if (
F.hasParamAttribute(U, Attribute::Returned)) {
5828 if (U ==
unsigned(ArgNo))
5852 void getDeducedAttributes(Attributor &
A, LLVMContext &Ctx,
5853 SmallVectorImpl<Attribute> &Attrs)
const override {
5854 if (!isAssumedNoCaptureMaybeReturned())
5857 if (isArgumentPosition()) {
5858 if (isAssumedNoCapture())
5859 Attrs.emplace_back(Attribute::get(Ctx, Attribute::Captures));
5861 Attrs.emplace_back(Attribute::get(Ctx,
"no-capture-maybe-returned"));
5865 const std::string getAsStr(Attributor *
A)
const override {
5866 if (isKnownNoCapture())
5867 return "known not-captured";
5868 if (isAssumedNoCapture())
5869 return "assumed not-captured";
5870 if (isKnownNoCaptureMaybeReturned())
5871 return "known not-captured-maybe-returned";
5872 if (isAssumedNoCaptureMaybeReturned())
5873 return "assumed not-captured-maybe-returned";
5874 return "assumed-captured";
5879 bool checkUse(Attributor &
A, AANoCapture::StateType &State,
const Use &U,
5882 LLVM_DEBUG(
dbgs() <<
"[AANoCapture] Check use: " << *
U.get() <<
" in "
5888 return isCapturedIn(State,
true,
true,
5895 return isCapturedIn(State,
true,
true,
5901 return isCapturedIn(State,
false,
false,
5903 return isCapturedIn(State,
true,
true,
5911 return isCapturedIn(State,
true,
true,
5918 bool IsKnownNoCapture;
5919 const AANoCapture *ArgNoCaptureAA =
nullptr;
5921 A,
this, CSArgPos, DepClassTy::REQUIRED, IsKnownNoCapture,
false,
5923 if (IsAssumedNoCapture)
5924 return isCapturedIn(State,
false,
false,
5928 return isCapturedIn(State,
false,
false,
5933 return isCapturedIn(State,
true,
true,
5940 static bool isCapturedIn(AANoCapture::StateType &State,
bool CapturedInMem,
5941 bool CapturedInInt,
bool CapturedInRet) {
5942 LLVM_DEBUG(
dbgs() <<
" - captures [Mem " << CapturedInMem <<
"|Int "
5943 << CapturedInInt <<
"|Ret " << CapturedInRet <<
"]\n");
5955 const IRPosition &IRP = getIRPosition();
5959 return indicatePessimisticFixpoint();
5966 return indicatePessimisticFixpoint();
5974 T.addKnownBits(NOT_CAPTURED_IN_MEM);
5976 addKnownBits(NOT_CAPTURED_IN_MEM);
5983 auto CheckReturnedArgs = [&](
bool &UsedAssumedInformation) {
5987 UsedAssumedInformation))
5989 bool SeenConstant =
false;
5990 for (
const AA::ValueAndContext &VAC :
Values) {
5994 SeenConstant =
true;
5996 VAC.
getValue() == getAssociatedArgument())
6002 bool IsKnownNoUnwind;
6005 bool IsVoidTy =
F->getReturnType()->isVoidTy();
6006 bool UsedAssumedInformation =
false;
6007 if (IsVoidTy || CheckReturnedArgs(UsedAssumedInformation)) {
6008 T.addKnownBits(NOT_CAPTURED_IN_RET);
6011 bool IsKnownWillReturn;
6014 if (IsAssumedWillReturn &&
T.isKnown(NOT_CAPTURED_IN_MEM))
6016 if (IsKnownNoUnwind && (IsVoidTy || !UsedAssumedInformation)) {
6017 addKnownBits(NOT_CAPTURED_IN_RET);
6018 if (IsKnownWillReturn && isKnown(NOT_CAPTURED_IN_MEM))
6019 return indicateOptimisticFixpoint();
6024 auto UseCheck = [&](
const Use &
U,
bool &Follow) ->
bool {
6033 return checkUse(
A,
T, U, Follow);
6036 if (!
A.checkForAllUses(UseCheck, *
this, *
V))
6037 return indicatePessimisticFixpoint();
6040 auto Assumed = S.getAssumed();
6041 S.intersectAssumedBits(
T.getAssumed());
6042 if (!isAssumedNoCaptureMaybeReturned())
6043 return indicatePessimisticFixpoint();
6049struct AANoCaptureArgument final : AANoCaptureImpl {
6050 AANoCaptureArgument(
const IRPosition &IRP, Attributor &
A)
6051 : AANoCaptureImpl(IRP,
A) {}
6057struct AANoCaptureCallSiteArgument final : AANoCaptureImpl {
6058 AANoCaptureCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
6059 : AANoCaptureImpl(IRP,
A) {}
6066 Argument *Arg = getAssociatedArgument();
6068 return indicatePessimisticFixpoint();
6070 bool IsKnownNoCapture;
6071 const AANoCapture *ArgAA =
nullptr;
6073 A,
this, ArgPos, DepClassTy::REQUIRED, IsKnownNoCapture,
false,
6075 return ChangeStatus::UNCHANGED;
6077 return indicatePessimisticFixpoint();
6081 void trackStatistics()
const override {
6087struct AANoCaptureFloating final : AANoCaptureImpl {
6088 AANoCaptureFloating(
const IRPosition &IRP, Attributor &
A)
6089 : AANoCaptureImpl(IRP,
A) {}
6091 void trackStatistics()
const override {
6097struct AANoCaptureReturned final : AANoCaptureImpl {
6098 AANoCaptureReturned(
const IRPosition &IRP, Attributor &
A)
6099 : AANoCaptureImpl(IRP,
A) {
6111 void trackStatistics()
const override {}
6115struct AANoCaptureCallSiteReturned final : AANoCaptureImpl {
6116 AANoCaptureCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
6117 : AANoCaptureImpl(IRP,
A) {}
6122 determineFunctionCaptureCapabilities(getIRPosition(), *
F, *
this);
6125 void trackStatistics()
const override {
6142 dbgs() <<
"[ValueSimplify] is assumed to be "
6145 dbgs() <<
"[ValueSimplify] is assumed to be <none>\n";
6156 if (getAssociatedValue().
getType()->isVoidTy())
6157 indicatePessimisticFixpoint();
6158 if (
A.hasSimplificationCallback(getIRPosition()))
6159 indicatePessimisticFixpoint();
6162 const std::string getAsStr(Attributor *
A)
const override {
6164 dbgs() <<
"SAV: " << (bool)SimplifiedAssociatedValue <<
" ";
6165 if (SimplifiedAssociatedValue && *SimplifiedAssociatedValue)
6166 dbgs() <<
"SAV: " << **SimplifiedAssociatedValue <<
" ";
6168 return isValidState() ? (isAtFixpoint() ?
"simplified" :
"maybe-simple")
6172 void trackStatistics()
const override {}
6174 std::optional<Value *>
6175 getAssumedSimplifiedValue(Attributor &
A)
const override {
6176 return SimplifiedAssociatedValue;
6183 static Value *ensureType(Attributor &
A,
Value &
V,
Type &Ty, Instruction *CtxI,
6187 if (CtxI &&
V.getType()->canLosslesslyBitCastTo(&Ty))
6189 : BitCastInst::CreatePointerBitCastOrAddrSpaceCast(
6198 static Value *reproduceInst(Attributor &
A,
6199 const AbstractAttribute &QueryingAA,
6200 Instruction &
I,
Type &Ty, Instruction *CtxI,
6202 assert(CtxI &&
"Cannot reproduce an instruction without context!");
6203 if (
Check && (
I.mayReadFromMemory() ||
6208 Value *NewOp = reproduceValue(
A, QueryingAA, *
Op, Ty, CtxI,
Check, VMap);
6210 assert(
Check &&
"Manifest of new value unexpectedly failed!");
6232 static Value *reproduceValue(Attributor &
A,
6233 const AbstractAttribute &QueryingAA,
Value &
V,
6234 Type &Ty, Instruction *CtxI,
bool Check,
6236 if (
const auto &NewV = VMap.
lookup(&
V))
6238 bool UsedAssumedInformation =
false;
6239 std::optional<Value *> SimpleV =
A.getAssumedSimplified(
6241 if (!SimpleV.has_value())
6245 EffectiveV = *SimpleV;
6250 return ensureType(
A, *EffectiveV, Ty, CtxI,
Check);
6252 if (
Value *NewV = reproduceInst(
A, QueryingAA, *
I, Ty, CtxI,
Check, VMap))
6253 return ensureType(
A, *NewV, Ty, CtxI,
Check);
6259 Value *manifestReplacementValue(Attributor &
A, Instruction *CtxI)
const {
6260 Value *NewV = SimplifiedAssociatedValue
6261 ? *SimplifiedAssociatedValue
6263 if (NewV && NewV != &getAssociatedValue()) {
6267 if (reproduceValue(
A, *
this, *NewV, *getAssociatedType(), CtxI,
6269 return reproduceValue(
A, *
this, *NewV, *getAssociatedType(), CtxI,
6277 bool checkAndUpdate(Attributor &
A,
const AbstractAttribute &QueryingAA,
6278 const IRPosition &IRP,
bool Simplify =
true) {
6279 bool UsedAssumedInformation =
false;
6282 QueryingValueSimplified =
A.getAssumedSimplified(
6284 return unionAssumed(QueryingValueSimplified);
6288 template <
typename AAType>
bool askSimplifiedValueFor(Attributor &
A) {
6289 if (!getAssociatedValue().
getType()->isIntegerTy())
6294 A.getAAFor<AAType>(*
this, getIRPosition(), DepClassTy::NONE);
6298 std::optional<Constant *> COpt = AA->getAssumedConstant(
A);
6301 SimplifiedAssociatedValue = std::nullopt;
6302 A.recordDependence(*AA, *
this, DepClassTy::OPTIONAL);
6305 if (
auto *
C = *COpt) {
6306 SimplifiedAssociatedValue =
C;
6307 A.recordDependence(*AA, *
this, DepClassTy::OPTIONAL);
6313 bool askSimplifiedValueForOtherAAs(Attributor &
A) {
6314 if (askSimplifiedValueFor<AAValueConstantRange>(
A))
6316 if (askSimplifiedValueFor<AAPotentialConstantValues>(
A))
6323 for (
auto &U : getAssociatedValue().uses()) {
6328 IP =
PHI->getIncomingBlock(U)->getTerminator();
6329 if (
auto *NewV = manifestReplacementValue(
A, IP)) {
6331 <<
" -> " << *NewV <<
" :: " << *
this <<
"\n");
6332 if (
A.changeUseAfterManifest(U, *NewV))
6333 Changed = ChangeStatus::CHANGED;
6337 return Changed | AAValueSimplify::manifest(
A);
6341 SimplifiedAssociatedValue = &getAssociatedValue();
6342 return AAValueSimplify::indicatePessimisticFixpoint();
6346struct AAValueSimplifyArgument final : AAValueSimplifyImpl {
6347 AAValueSimplifyArgument(
const IRPosition &IRP, Attributor &
A)
6348 : AAValueSimplifyImpl(IRP,
A) {}
6351 AAValueSimplifyImpl::initialize(
A);
6352 if (
A.hasAttr(getIRPosition(),
6353 {Attribute::InAlloca, Attribute::Preallocated,
6354 Attribute::StructRet, Attribute::Nest, Attribute::ByVal},
6356 indicatePessimisticFixpoint();
6362 Argument *Arg = getAssociatedArgument();
6368 return indicatePessimisticFixpoint();
6371 auto Before = SimplifiedAssociatedValue;
6373 auto PredForCallSite = [&](AbstractCallSite ACS) {
6374 const IRPosition &ACSArgPos =
6385 bool UsedAssumedInformation =
false;
6386 std::optional<Constant *> SimpleArgOp =
6387 A.getAssumedConstant(ACSArgPos, *
this, UsedAssumedInformation);
6394 return unionAssumed(*SimpleArgOp);
6399 bool UsedAssumedInformation =
false;
6400 if (hasCallBaseContext() &&
6401 getCallBaseContext()->getCalledOperand() == Arg->
getParent())
6403 AbstractCallSite(&getCallBaseContext()->getCalledOperandUse()));
6405 Success =
A.checkForAllCallSites(PredForCallSite, *
this,
true,
6406 UsedAssumedInformation);
6409 if (!askSimplifiedValueForOtherAAs(
A))
6410 return indicatePessimisticFixpoint();
6413 return Before == SimplifiedAssociatedValue ? ChangeStatus::UNCHANGED
6414 : ChangeStatus ::CHANGED;
6417 void trackStatistics()
const override {
6422struct AAValueSimplifyReturned : AAValueSimplifyImpl {
6423 AAValueSimplifyReturned(
const IRPosition &IRP, Attributor &
A)
6424 : AAValueSimplifyImpl(IRP,
A) {}
6426 std::optional<Value *>
6427 getAssumedSimplifiedValue(Attributor &
A)
const override {
6428 if (!isValidState())
6430 return SimplifiedAssociatedValue;
6434 auto Before = SimplifiedAssociatedValue;
6438 return checkAndUpdate(
6443 bool UsedAssumedInformation =
false;
6444 if (!
A.checkForAllInstructions(ReturnInstCB, *
this, {Instruction::Ret},
6445 UsedAssumedInformation))
6446 if (!askSimplifiedValueForOtherAAs(
A))
6447 return indicatePessimisticFixpoint();
6450 return Before == SimplifiedAssociatedValue ? ChangeStatus::UNCHANGED
6451 : ChangeStatus ::CHANGED;
6457 return ChangeStatus::UNCHANGED;
6460 void trackStatistics()
const override {
6465struct AAValueSimplifyFloating : AAValueSimplifyImpl {
6466 AAValueSimplifyFloating(
const IRPosition &IRP, Attributor &
A)
6467 : AAValueSimplifyImpl(IRP,
A) {}
6470 AAValueSimplifyImpl::initialize(
A);
6471 Value &
V = getAnchorValue();
6475 indicatePessimisticFixpoint();
6479 auto Before = SimplifiedAssociatedValue;
6480 if (!askSimplifiedValueForOtherAAs(
A))
6481 return indicatePessimisticFixpoint();
6484 return Before == SimplifiedAssociatedValue ? ChangeStatus::UNCHANGED
6485 : ChangeStatus ::CHANGED;
6488 void trackStatistics()
const override {
6493struct AAValueSimplifyFunction : AAValueSimplifyImpl {
6494 AAValueSimplifyFunction(
const IRPosition &IRP, Attributor &
A)
6495 : AAValueSimplifyImpl(IRP,
A) {}
6498 SimplifiedAssociatedValue =
nullptr;
6499 indicateOptimisticFixpoint();
6503 "AAValueSimplify(Function|CallSite)::updateImpl will not be called");
6505 void trackStatistics()
const override {
6510struct AAValueSimplifyCallSite : AAValueSimplifyFunction {
6511 AAValueSimplifyCallSite(
const IRPosition &IRP, Attributor &
A)
6512 : AAValueSimplifyFunction(IRP,
A) {}
6513 void trackStatistics()
const override {
6518struct AAValueSimplifyCallSiteReturned : AAValueSimplifyImpl {
6519 AAValueSimplifyCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
6520 : AAValueSimplifyImpl(IRP,
A) {}
6523 AAValueSimplifyImpl::initialize(
A);
6524 Function *Fn = getAssociatedFunction();
6525 assert(Fn &&
"Did expect an associted function");
6526 for (Argument &Arg : Fn->
args()) {
6531 checkAndUpdate(
A, *
this, IRP))
6532 indicateOptimisticFixpoint();
6534 indicatePessimisticFixpoint();
6541 return indicatePessimisticFixpoint();
6544 void trackStatistics()
const override {
6549struct AAValueSimplifyCallSiteArgument : AAValueSimplifyFloating {
6550 AAValueSimplifyCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
6551 : AAValueSimplifyFloating(IRP,
A) {}
6556 auto *FloatAA =
A.lookupAAFor<AAValueSimplify>(
6558 if (FloatAA && FloatAA->getState().isValidState())
6561 if (
auto *NewV = manifestReplacementValue(
A, getCtxI())) {
6563 ->getArgOperandUse(getCallSiteArgNo());
6564 if (
A.changeUseAfterManifest(U, *NewV))
6565 Changed = ChangeStatus::CHANGED;
6568 return Changed | AAValueSimplify::manifest(
A);
6571 void trackStatistics()
const override {
6582 bool UsedAssumedInformation =
false;
6583 return A.checkForAllInstructions(
6586 if (CI.isTailCall() && !CI.isMustTailCall())
6590 QueryingAA, {Instruction::Call}, UsedAssumedInformation);
6595struct AAHeapToStackFunction final :
public AAHeapToStack {
6597 static bool isGlobalizedLocal(
const CallBase &CB) {
6599 return A.
isValid() &&
A.getValueAsString() ==
"__kmpc_alloc_shared";
6602 struct AllocationInfo {
6607 bool IsGlobalizedLocal =
false;
6614 } Status = STACK_DUE_TO_USE;
6618 bool HasPotentiallyFreeingUnknownUses =
false;
6622 bool MoveAllocaIntoEntry =
true;
6625 SmallSetVector<CallBase *, 1> PotentialFreeCalls{};
6628 struct DeallocationInfo {
6636 bool MightFreeUnknownObjects =
false;
6639 SmallSetVector<CallBase *, 1> PotentialAllocationCalls{};
6642 AAHeapToStackFunction(
const IRPosition &IRP, Attributor &
A)
6643 : AAHeapToStack(IRP,
A) {}
6645 ~AAHeapToStackFunction()
override {
6648 for (
auto &It : AllocationInfos)
6649 It.second->~AllocationInfo();
6650 for (
auto &It : DeallocationInfos)
6651 It.second->~DeallocationInfo();
6655 AAHeapToStack::initialize(
A);
6658 const auto *
TLI =
A.getInfoCache().getTargetLibraryInfoForFunction(*
F);
6665 DeallocationInfos[CB] =
new (
A.Allocator) DeallocationInfo{CB, FreedOp};
6672 auto *I8Ty = Type::getInt8Ty(CB->
getParent()->getContext());
6674 AllocationInfo *AI =
new (
A.Allocator) AllocationInfo{CB};
6675 AllocationInfos[CB] = AI;
6676 AI->IsGlobalizedLocal = isGlobalizedLocal(*CB);
6682 bool UsedAssumedInformation =
false;
6683 bool Success =
A.checkForAllCallLikeInstructions(
6684 AllocationIdentifierCB, *
this, UsedAssumedInformation,
6688 assert(
Success &&
"Did not expect the call base visit callback to fail!");
6691 [](
const IRPosition &,
const AbstractAttribute *,
6692 bool &) -> std::optional<Value *> {
return nullptr; };
6693 for (
const auto &It : AllocationInfos)
6696 for (
const auto &It : DeallocationInfos)
6701 const std::string getAsStr(Attributor *
A)
const override {
6702 unsigned NumH2SMallocs = 0, NumInvalidMallocs = 0;
6703 for (
const auto &It : AllocationInfos) {
6704 if (It.second->Status == AllocationInfo::INVALID)
6705 ++NumInvalidMallocs;
6709 return "[H2S] Mallocs Good/Bad: " + std::to_string(NumH2SMallocs) +
"/" +
6710 std::to_string(NumInvalidMallocs);
6713 void trackStatistics()
const override {
6716 "Number of malloc/calloc/aligned_alloc calls converted to allocas");
6717 for (
const auto &It : AllocationInfos)
6718 if (It.second->Status != AllocationInfo::INVALID)
6722 bool isAssumedHeapToStack(
const CallBase &CB)
const override {
6724 if (AllocationInfo *AI =
6725 AllocationInfos.lookup(
const_cast<CallBase *
>(&CB)))
6726 return AI->Status != AllocationInfo::INVALID;
6730 bool isAssumedHeapToStackRemovedFree(CallBase &CB)
const override {
6731 if (!isValidState())
6734 for (
const auto &It : AllocationInfos) {
6735 AllocationInfo &AI = *It.second;
6736 if (AI.Status == AllocationInfo::INVALID)
6739 if (AI.PotentialFreeCalls.count(&CB))
6747 assert(getState().isValidState() &&
6748 "Attempted to manifest an invalid state!");
6752 const auto *
TLI =
A.getInfoCache().getTargetLibraryInfoForFunction(*
F);
6756 if (
any_of(AllocationInfos,
6757 [](
const std::pair<CallBase *, AllocationInfo *> &It) {
6758 return It.second->Status != AllocationInfo::INVALID;
6761 return ChangeStatus::UNCHANGED;
6763 for (
auto &It : AllocationInfos) {
6764 AllocationInfo &AI = *It.second;
6765 if (AI.Status == AllocationInfo::INVALID)
6768 for (CallBase *FreeCall : AI.PotentialFreeCalls) {
6769 LLVM_DEBUG(
dbgs() <<
"H2S: Removing free call: " << *FreeCall <<
"\n");
6770 A.deleteAfterManifest(*FreeCall);
6771 HasChanged = ChangeStatus::CHANGED;
6774 LLVM_DEBUG(
dbgs() <<
"H2S: Removing malloc-like call: " << *AI.CB
6777 auto Remark = [&](OptimizationRemark
OR) {
6778 if (AI.IsGlobalizedLocal)
6779 return OR <<
"Moving globalized variable to the stack.";
6780 return OR <<
"Moving memory allocation from the heap to the stack.";
6782 if (AI.IsGlobalizedLocal)
6783 A.emitRemark<OptimizationRemark>(AI.CB,
"OMP110",
Remark);
6785 A.emitRemark<OptimizationRemark>(AI.CB,
"HeapToStack",
Remark);
6787 const DataLayout &
DL =
A.getInfoCache().getDL();
6789 std::optional<APInt> SizeAPI =
getSize(
A, *
this, AI);
6791 Size = ConstantInt::get(AI.CB->getContext(), *SizeAPI);
6793 ObjectSizeOpts Opts;
6794 ObjectSizeOffsetEvaluator Eval(*AI.CB->getModule(),
TLI, Opts);
6795 SizeOffsetValue SizeOffsetPair = Eval.compute(AI.CB);
6802 ?
F->getEntryBlock().begin()
6803 : AI.CB->getIterator();
6806 if (MaybeAlign RetAlign = AI.CB->getRetAlign())
6807 Alignment = std::max(Alignment, *RetAlign);
6809 std::optional<APInt> AlignmentAPI = getAPInt(
A, *
this, *Align);
6810 assert(AlignmentAPI && AlignmentAPI->getZExtValue() > 0 &&
6811 "Expected an alignment during manifest!");
6813 std::max(Alignment,
assumeAligned(AlignmentAPI->getZExtValue()));
6817 unsigned AS =
DL.getAllocaAddrSpace();
6819 new AllocaInst(Type::getInt8Ty(
F->getContext()), AS,
Size, Alignment,
6820 AI.CB->getName() +
".h2s", IP);
6822 if (Alloca->
getType() != AI.CB->getType())
6823 Alloca = BitCastInst::CreatePointerBitCastOrAddrSpaceCast(
6824 Alloca, AI.CB->getType(),
"malloc_cast", AI.CB->getIterator());
6826 auto *I8Ty = Type::getInt8Ty(
F->getContext());
6829 "Must be able to materialize initial memory state of allocation");
6834 auto *NBB =
II->getNormalDest();
6836 A.deleteAfterManifest(*AI.CB);
6838 A.deleteAfterManifest(*AI.CB);
6847 Builder.CreateMemSet(Alloca, InitVal,
Size, std::nullopt);
6849 HasChanged = ChangeStatus::CHANGED;
6852 for (CallInst *CI : TailCalls)
6853 CI->setTailCall(
false);
6858 std::optional<APInt> getAPInt(Attributor &
A,
const AbstractAttribute &AA,
6860 bool UsedAssumedInformation =
false;
6861 std::optional<Constant *> SimpleV =
6862 A.getAssumedConstant(
V, AA, UsedAssumedInformation);
6864 return APInt(64, 0);
6866 return CI->getValue();
6867 return std::nullopt;
6870 std::optional<APInt>
getSize(Attributor &
A,
const AbstractAttribute &AA,
6871 AllocationInfo &AI) {
6873 bool UsedAssumedInformation =
false;
6874 if (std::optional<Constant *> SimpleV =
6875 A.getAssumedConstant(*
V, AA, UsedAssumedInformation))
6882 const auto *
TLI =
A.getInfoCache().getTargetLibraryInfoForFunction(*
F);
6888 MapVector<CallBase *, AllocationInfo *> AllocationInfos;
6892 MapVector<CallBase *, DeallocationInfo *> DeallocationInfos;
6897ChangeStatus AAHeapToStackFunction::updateImpl(Attributor &
A) {
6900 const auto *
TLI =
A.getInfoCache().getTargetLibraryInfoForFunction(*
F);
6902 const auto *LivenessAA =
6905 MustBeExecutedContextExplorer *Explorer =
6906 A.getInfoCache().getMustBeExecutedContextExplorer();
6908 bool StackIsAccessibleByOtherThreads =
6909 A.getInfoCache().stackIsAccessibleByOtherThreads();
6912 A.getInfoCache().getAnalysisResultForFunction<LoopAnalysis>(*F);
6913 std::optional<bool> MayContainIrreducibleControl;
6915 if (&
F->getEntryBlock() == &BB)
6917 if (!MayContainIrreducibleControl.has_value())
6919 if (*MayContainIrreducibleControl)
6928 bool HasUpdatedFrees =
false;
6930 auto UpdateFrees = [&]() {
6931 HasUpdatedFrees =
true;
6933 for (
auto &It : DeallocationInfos) {
6934 DeallocationInfo &DI = *It.second;
6937 if (DI.MightFreeUnknownObjects)
6941 bool UsedAssumedInformation =
false;
6942 if (
A.isAssumedDead(*DI.CB,
this, LivenessAA, UsedAssumedInformation,
6949 LLVM_DEBUG(
dbgs() <<
"[H2S] Unknown underlying object for free!\n");
6950 DI.MightFreeUnknownObjects =
true;
6963 DI.MightFreeUnknownObjects =
true;
6967 AllocationInfo *AI = AllocationInfos.lookup(ObjCB);
6969 LLVM_DEBUG(
dbgs() <<
"[H2S] Free of a non-allocation object: " << *Obj
6971 DI.MightFreeUnknownObjects =
true;
6975 DI.PotentialAllocationCalls.insert(ObjCB);
6979 auto FreeCheck = [&](AllocationInfo &AI) {
6983 if (!StackIsAccessibleByOtherThreads) {
6988 dbgs() <<
"[H2S] found an escaping use, stack is not accessible by "
6989 "other threads and function is not nosync:\n");
6993 if (!HasUpdatedFrees)
6997 if (AI.PotentialFreeCalls.size() != 1) {
6999 << AI.PotentialFreeCalls.size() <<
"\n");
7002 CallBase *UniqueFree = *AI.PotentialFreeCalls.begin();
7003 DeallocationInfo *DI = DeallocationInfos.lookup(UniqueFree);
7006 dbgs() <<
"[H2S] unique free call was not known as deallocation call "
7007 << *UniqueFree <<
"\n");
7010 if (DI->MightFreeUnknownObjects) {
7012 dbgs() <<
"[H2S] unique free call might free unknown allocations\n");
7015 if (DI->PotentialAllocationCalls.empty())
7017 if (DI->PotentialAllocationCalls.size() > 1) {
7019 << DI->PotentialAllocationCalls.size()
7020 <<
" different allocations\n");
7023 if (*DI->PotentialAllocationCalls.begin() != AI.CB) {
7026 <<
"[H2S] unique free call not known to free this allocation but "
7027 << **DI->PotentialAllocationCalls.begin() <<
"\n");
7032 if (!AI.IsGlobalizedLocal) {
7034 if (!Explorer || !Explorer->findInContextOf(UniqueFree, CtxI)) {
7035 LLVM_DEBUG(
dbgs() <<
"[H2S] unique free call might not be executed "
7036 "with the allocation "
7037 << *UniqueFree <<
"\n");
7044 auto UsesCheck = [&](AllocationInfo &AI) {
7045 bool ValidUsesOnly =
true;
7047 auto Pred = [&](
const Use &
U,
bool &Follow) ->
bool {
7052 if (
SI->getValueOperand() ==
U.get()) {
7054 <<
"[H2S] escaping store to memory: " << *UserI <<
"\n");
7055 ValidUsesOnly =
false;
7066 ValidUsesOnly =
false;
7072 if (DeallocationInfos.count(CB)) {
7073 AI.PotentialFreeCalls.insert(CB);
7080 bool IsKnownNoCapture;
7089 if (!IsAssumedNoCapture ||
7090 (!AI.IsGlobalizedLocal && !IsAssumedNoFree)) {
7091 AI.HasPotentiallyFreeingUnknownUses |= !IsAssumedNoFree;
7094 auto Remark = [&](OptimizationRemarkMissed ORM) {
7096 <<
"Could not move globalized variable to the stack. "
7097 "Variable is potentially captured in call. Mark "
7098 "parameter as `__attribute__((noescape))` to override.";
7101 if (ValidUsesOnly && AI.IsGlobalizedLocal)
7102 A.emitRemark<OptimizationRemarkMissed>(CB,
"OMP113",
Remark);
7105 ValidUsesOnly =
false;
7118 ValidUsesOnly =
false;
7121 if (!
A.checkForAllUses(
Pred, *
this, *AI.CB,
false,
7123 [&](
const Use &OldU,
const Use &NewU) {
7124 auto *SI = dyn_cast<StoreInst>(OldU.getUser());
7125 return !SI || StackIsAccessibleByOtherThreads ||
7126 AA::isAssumedThreadLocalObject(
7127 A, *SI->getPointerOperand(), *this);
7130 return ValidUsesOnly;
7135 for (
auto &It : AllocationInfos) {
7136 AllocationInfo &AI = *It.second;
7137 if (AI.Status == AllocationInfo::INVALID)
7141 std::optional<APInt> APAlign = getAPInt(
A, *
this, *Align);
7145 LLVM_DEBUG(
dbgs() <<
"[H2S] Unknown allocation alignment: " << *AI.CB
7147 AI.Status = AllocationInfo::INVALID;
7152 !APAlign->isPowerOf2()) {
7153 LLVM_DEBUG(
dbgs() <<
"[H2S] Invalid allocation alignment: " << APAlign
7155 AI.Status = AllocationInfo::INVALID;
7166 dbgs() <<
"[H2S] Unknown allocation size: " << *AI.CB <<
"\n";
7168 dbgs() <<
"[H2S] Allocation size too large: " << *AI.CB <<
" vs. "
7172 AI.Status = AllocationInfo::INVALID;
7178 switch (AI.Status) {
7179 case AllocationInfo::STACK_DUE_TO_USE:
7182 AI.Status = AllocationInfo::STACK_DUE_TO_FREE;
7184 case AllocationInfo::STACK_DUE_TO_FREE:
7187 AI.Status = AllocationInfo::INVALID;
7190 case AllocationInfo::INVALID:
7197 bool IsGlobalizedLocal = AI.IsGlobalizedLocal;
7198 if (AI.MoveAllocaIntoEntry &&
7199 (!
Size.has_value() ||
7200 (!IsGlobalizedLocal && IsInLoop(*AI.CB->getParent()))))
7201 AI.MoveAllocaIntoEntry =
false;
7210struct AAPrivatizablePtrImpl :
public AAPrivatizablePtr {
7211 AAPrivatizablePtrImpl(
const IRPosition &IRP, Attributor &
A)
7212 : AAPrivatizablePtr(IRP,
A), PrivatizableType(std::nullopt) {}
7215 AAPrivatizablePtr::indicatePessimisticFixpoint();
7216 PrivatizableType =
nullptr;
7217 return ChangeStatus::CHANGED;
7223 virtual std::optional<Type *> identifyPrivatizableType(Attributor &
A) = 0;
7227 std::optional<Type *> combineTypes(std::optional<Type *> T0,
7228 std::optional<Type *>
T1) {
7238 std::optional<Type *> getPrivatizableType()
const override {
7239 return PrivatizableType;
7242 const std::string getAsStr(Attributor *
A)
const override {
7243 return isAssumedPrivatizablePtr() ?
"[priv]" :
"[no-priv]";
7247 std::optional<Type *> PrivatizableType;
7252struct AAPrivatizablePtrArgument final :
public AAPrivatizablePtrImpl {
7253 AAPrivatizablePtrArgument(
const IRPosition &IRP, Attributor &
A)
7254 : AAPrivatizablePtrImpl(IRP,
A) {}
7256 std::optional<Type *> identifyPrivatizableType(Attributor &
A)
override {
7259 bool UsedAssumedInformation =
false;
7261 A.getAttrs(getIRPosition(), {Attribute::ByVal},
Attrs,
7263 if (!
Attrs.empty() &&
7264 A.checkForAllCallSites([](AbstractCallSite ACS) { return true; }, *
this,
7265 true, UsedAssumedInformation))
7266 return Attrs[0].getValueAsType();
7268 std::optional<Type *> Ty;
7269 unsigned ArgNo = getIRPosition().getCallSiteArgNo();
7277 auto CallSiteCheck = [&](AbstractCallSite ACS) {
7286 A.getAAFor<AAPrivatizablePtr>(*
this, ACSArgPos, DepClassTy::REQUIRED);
7289 std::optional<Type *> CSTy = PrivCSArgAA->getPrivatizableType();
7292 dbgs() <<
"[AAPrivatizablePtr] ACSPos: " << ACSArgPos <<
", CSTy: ";
7296 dbgs() <<
"<nullptr>";
7301 Ty = combineTypes(Ty, CSTy);
7304 dbgs() <<
" : New Type: ";
7306 (*Ty)->print(
dbgs());
7308 dbgs() <<
"<nullptr>";
7317 if (!
A.checkForAllCallSites(CallSiteCheck, *
this,
true,
7318 UsedAssumedInformation))
7324 PrivatizableType = identifyPrivatizableType(
A);
7325 if (!PrivatizableType)
7326 return ChangeStatus::UNCHANGED;
7327 if (!*PrivatizableType)
7328 return indicatePessimisticFixpoint();
7333 DepClassTy::OPTIONAL);
7336 if (!
A.hasAttr(getIRPosition(), Attribute::ByVal) &&
7339 return indicatePessimisticFixpoint();
7345 identifyReplacementTypes(*PrivatizableType, ReplacementTypes);
7349 Function &Fn = *getIRPosition().getAnchorScope();
7351 A.getInfoCache().getAnalysisResultForFunction<TargetIRAnalysis>(Fn);
7353 LLVM_DEBUG(
dbgs() <<
"[AAPrivatizablePtr] Missing TTI for function "
7355 return indicatePessimisticFixpoint();
7358 auto CallSiteCheck = [&](AbstractCallSite ACS) {
7365 bool UsedAssumedInformation =
false;
7366 if (!
A.checkForAllCallSites(CallSiteCheck, *
this,
true,
7367 UsedAssumedInformation)) {
7369 dbgs() <<
"[AAPrivatizablePtr] ABI incompatibility detected for "
7371 return indicatePessimisticFixpoint();
7375 Argument *Arg = getAssociatedArgument();
7376 if (!
A.isValidFunctionSignatureRewrite(*Arg, ReplacementTypes)) {
7378 return indicatePessimisticFixpoint();
7385 auto IsCompatiblePrivArgOfCallback = [&](CallBase &CB) {
7388 for (
const Use *U : CallbackUses) {
7389 AbstractCallSite CBACS(U);
7390 assert(CBACS && CBACS.isCallbackCall());
7391 for (Argument &CBArg : CBACS.getCalledFunction()->args()) {
7392 int CBArgNo = CBACS.getCallArgOperandNo(CBArg);
7396 <<
"[AAPrivatizablePtr] Argument " << *Arg
7397 <<
"check if can be privatized in the context of its parent ("
7399 <<
")\n[AAPrivatizablePtr] because it is an argument in a "
7401 << CBArgNo <<
"@" << CBACS.getCalledFunction()->getName()
7402 <<
")\n[AAPrivatizablePtr] " << CBArg <<
" : "
7403 << CBACS.getCallArgOperand(CBArg) <<
" vs "
7405 <<
"[AAPrivatizablePtr] " << CBArg <<
" : "
7406 << CBACS.getCallArgOperandNo(CBArg) <<
" vs " << ArgNo <<
"\n";
7409 if (CBArgNo !=
int(ArgNo))
7411 const auto *CBArgPrivAA =
A.getAAFor<AAPrivatizablePtr>(
7413 if (CBArgPrivAA && CBArgPrivAA->isValidState()) {
7414 auto CBArgPrivTy = CBArgPrivAA->getPrivatizableType();
7417 if (*CBArgPrivTy == PrivatizableType)
7422 dbgs() <<
"[AAPrivatizablePtr] Argument " << *Arg
7423 <<
" cannot be privatized in the context of its parent ("
7425 <<
")\n[AAPrivatizablePtr] because it is an argument in a "
7427 << CBArgNo <<
"@" << CBACS.getCalledFunction()->getName()
7428 <<
").\n[AAPrivatizablePtr] for which the argument "
7429 "privatization is not compatible.\n";
7439 auto IsCompatiblePrivArgOfDirectCS = [&](AbstractCallSite ACS) {
7443 "Expected a direct call operand for callback call operand");
7448 dbgs() <<
"[AAPrivatizablePtr] Argument " << *Arg
7449 <<
" check if be privatized in the context of its parent ("
7451 <<
")\n[AAPrivatizablePtr] because it is an argument in a "
7453 << DCArgNo <<
"@" << DCCallee->
getName() <<
").\n";
7456 if (
unsigned(DCArgNo) < DCCallee->
arg_size()) {
7457 const auto *DCArgPrivAA =
A.getAAFor<AAPrivatizablePtr>(
7459 DepClassTy::REQUIRED);
7460 if (DCArgPrivAA && DCArgPrivAA->isValidState()) {
7461 auto DCArgPrivTy = DCArgPrivAA->getPrivatizableType();
7464 if (*DCArgPrivTy == PrivatizableType)
7470 dbgs() <<
"[AAPrivatizablePtr] Argument " << *Arg
7471 <<
" cannot be privatized in the context of its parent ("
7473 <<
")\n[AAPrivatizablePtr] because it is an argument in a "
7476 <<
").\n[AAPrivatizablePtr] for which the argument "
7477 "privatization is not compatible.\n";
7485 auto IsCompatiblePrivArgOfOtherCallSite = [&](AbstractCallSite ACS) {
7489 return IsCompatiblePrivArgOfDirectCS(ACS);
7493 if (!
A.checkForAllCallSites(IsCompatiblePrivArgOfOtherCallSite, *
this,
true,
7494 UsedAssumedInformation))
7495 return indicatePessimisticFixpoint();
7497 return ChangeStatus::UNCHANGED;
7503 identifyReplacementTypes(
Type *PrivType,
7504 SmallVectorImpl<Type *> &ReplacementTypes) {
7507 assert(PrivType &&
"Expected privatizable type!");
7511 for (
unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++)
7512 ReplacementTypes.
push_back(PrivStructType->getElementType(u));
7514 ReplacementTypes.
append(PrivArrayType->getNumElements(),
7515 PrivArrayType->getElementType());
7526 assert(PrivType &&
"Expected privatizable type!");
7529 const DataLayout &
DL =
F.getDataLayout();
7533 const StructLayout *PrivStructLayout =
DL.getStructLayout(PrivStructType);
7534 for (
unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++) {
7537 new StoreInst(
F.getArg(ArgNo + u), Ptr, IP);
7540 Type *PointeeTy = PrivArrayType->getElementType();
7541 uint64_t PointeeTySize =
DL.getTypeStoreSize(PointeeTy);
7542 for (
unsigned u = 0, e = PrivArrayType->getNumElements(); u < e; u++) {
7544 new StoreInst(
F.getArg(ArgNo + u), Ptr, IP);
7547 new StoreInst(
F.getArg(ArgNo), &
Base, IP);
7553 void createReplacementValues(Align Alignment,
Type *PrivType,
7555 SmallVectorImpl<Value *> &ReplacementValues) {
7557 assert(PrivType &&
"Expected privatizable type!");
7565 const StructLayout *PrivStructLayout =
DL.getStructLayout(PrivStructType);
7566 for (
unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++) {
7567 Type *PointeeTy = PrivStructType->getElementType(u);
7570 LoadInst *
L =
new LoadInst(PointeeTy, Ptr,
"", IP->
getIterator());
7571 L->setAlignment(Alignment);
7575 Type *PointeeTy = PrivArrayType->getElementType();
7576 uint64_t PointeeTySize =
DL.getTypeStoreSize(PointeeTy);
7577 for (
unsigned u = 0, e = PrivArrayType->getNumElements(); u < e; u++) {
7579 LoadInst *
L =
new LoadInst(PointeeTy, Ptr,
"", IP->
getIterator());
7580 L->setAlignment(Alignment);
7585 L->setAlignment(Alignment);
7591 if (!PrivatizableType)
7592 return ChangeStatus::UNCHANGED;
7593 assert(*PrivatizableType &&
"Expected privatizable type!");
7595 Argument *Arg = getAssociatedArgument();
7598 const auto *AlignAA =
7605 [=](
const Attributor::ArgumentReplacementInfo &ARI,
7607 BasicBlock &EntryBB = ReplacementFn.getEntryBlock();
7609 const DataLayout &
DL = IP->getDataLayout();
7610 unsigned AS =
DL.getAllocaAddrSpace();
7611 Instruction *AI =
new AllocaInst(*PrivatizableType, AS,
7612 Arg->
getName() +
".priv", IP);
7613 createInitialization(*PrivatizableType, *AI, ReplacementFn,
7614 ArgIt->getArgNo(), IP);
7617 AI = BitCastInst::CreatePointerBitCastOrAddrSpaceCast(
7625 if (CI && CI->isTailCall() && !CI->isMustTailCall())
7626 CI->setTailCall(
false);
7634 [=](
const Attributor::ArgumentReplacementInfo &ARI,
7635 AbstractCallSite ACS, SmallVectorImpl<Value *> &NewArgOperands) {
7638 createReplacementValues(
7639 AlignAA ? AlignAA->getAssumedAlign() :
Align(0),
7640 *PrivatizableType, ACS,
7648 identifyReplacementTypes(*PrivatizableType, ReplacementTypes);
7651 if (
A.registerFunctionSignatureRewrite(*Arg, ReplacementTypes,
7652 std::move(FnRepairCB),
7653 std::move(ACSRepairCB)))
7654 return ChangeStatus::CHANGED;
7655 return ChangeStatus::UNCHANGED;
7658 void trackStatistics()
const override {
7663struct AAPrivatizablePtrFloating :
public AAPrivatizablePtrImpl {
7664 AAPrivatizablePtrFloating(
const IRPosition &IRP, Attributor &
A)
7665 : AAPrivatizablePtrImpl(IRP,
A) {}
7669 indicatePessimisticFixpoint();
7674 "updateImpl will not be called");
7677 std::optional<Type *> identifyPrivatizableType(Attributor &
A)
override {
7680 LLVM_DEBUG(
dbgs() <<
"[AAPrivatizablePtr] No underlying object found!\n");
7687 return AI->getAllocatedType();
7689 auto *PrivArgAA =
A.getAAFor<AAPrivatizablePtr>(
7691 if (PrivArgAA && PrivArgAA->isAssumedPrivatizablePtr())
7692 return PrivArgAA->getPrivatizableType();
7695 LLVM_DEBUG(
dbgs() <<
"[AAPrivatizablePtr] Underlying object neither valid "
7696 "alloca nor privatizable argument: "
7701 void trackStatistics()
const override {
7706struct AAPrivatizablePtrCallSiteArgument final
7707 :
public AAPrivatizablePtrFloating {
7708 AAPrivatizablePtrCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
7709 : AAPrivatizablePtrFloating(IRP,
A) {}
7712 if (
A.hasAttr(getIRPosition(), Attribute::ByVal))
7713 indicateOptimisticFixpoint();
7717 PrivatizableType = identifyPrivatizableType(
A);
7718 if (!PrivatizableType)
7719 return ChangeStatus::UNCHANGED;
7720 if (!*PrivatizableType)
7721 return indicatePessimisticFixpoint();
7723 const IRPosition &IRP = getIRPosition();
7724 bool IsKnownNoCapture;
7726 A,
this, IRP, DepClassTy::REQUIRED, IsKnownNoCapture);
7727 if (!IsAssumedNoCapture) {
7728 LLVM_DEBUG(
dbgs() <<
"[AAPrivatizablePtr] pointer might be captured!\n");
7729 return indicatePessimisticFixpoint();
7732 bool IsKnownNoAlias;
7734 A,
this, IRP, DepClassTy::REQUIRED, IsKnownNoAlias)) {
7735 LLVM_DEBUG(
dbgs() <<
"[AAPrivatizablePtr] pointer might alias!\n");
7736 return indicatePessimisticFixpoint();
7741 LLVM_DEBUG(
dbgs() <<
"[AAPrivatizablePtr] pointer is written!\n");
7742 return indicatePessimisticFixpoint();
7745 return ChangeStatus::UNCHANGED;
7748 void trackStatistics()
const override {
7753struct AAPrivatizablePtrCallSiteReturned final
7754 :
public AAPrivatizablePtrFloating {
7755 AAPrivatizablePtrCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
7756 : AAPrivatizablePtrFloating(IRP,
A) {}
7760 indicatePessimisticFixpoint();
7763 void trackStatistics()
const override {
7768struct AAPrivatizablePtrReturned final :
public AAPrivatizablePtrFloating {
7769 AAPrivatizablePtrReturned(
const IRPosition &IRP, Attributor &
A)
7770 : AAPrivatizablePtrFloating(IRP,
A) {}
7774 indicatePessimisticFixpoint();
7777 void trackStatistics()
const override {
7787struct AAMemoryBehaviorImpl :
public AAMemoryBehavior {
7788 AAMemoryBehaviorImpl(
const IRPosition &IRP, Attributor &
A)
7789 : AAMemoryBehavior(IRP,
A) {}
7792 intersectAssumedBits(BEST_STATE);
7793 getKnownStateFromValue(
A, getIRPosition(), getState());
7794 AAMemoryBehavior::initialize(
A);
7798 static void getKnownStateFromValue(Attributor &
A,
const IRPosition &IRP,
7799 BitIntegerState &State,
7800 bool IgnoreSubsumingPositions =
false) {
7802 A.getAttrs(IRP, AttrKinds, Attrs, IgnoreSubsumingPositions);
7804 switch (Attr.getKindAsEnum()) {
7805 case Attribute::ReadNone:
7808 case Attribute::ReadOnly:
7811 case Attribute::WriteOnly:
7826 if (!
I->mayReadFromMemory())
7828 if (!
I->mayWriteToMemory())
7834 void getDeducedAttributes(Attributor &
A, LLVMContext &Ctx,
7835 SmallVectorImpl<Attribute> &Attrs)
const override {
7838 Attrs.push_back(Attribute::get(Ctx, Attribute::ReadNone));
7840 Attrs.push_back(Attribute::get(Ctx, Attribute::ReadOnly));
7841 else if (isAssumedWriteOnly())
7842 Attrs.push_back(Attribute::get(Ctx, Attribute::WriteOnly));
7847 const IRPosition &IRP = getIRPosition();
7849 if (
A.hasAttr(IRP, Attribute::ReadNone,
7851 return ChangeStatus::UNCHANGED;
7860 return ChangeStatus::UNCHANGED;
7863 A.removeAttrs(IRP, AttrKinds);
7866 A.removeAttrs(IRP, Attribute::Writable);
7872 const std::string getAsStr(Attributor *
A)
const override {
7877 if (isAssumedWriteOnly())
7879 return "may-read/write";
7883 static const Attribute::AttrKind AttrKinds[3];
7887 Attribute::ReadNone, Attribute::ReadOnly, Attribute::WriteOnly};
7890struct AAMemoryBehaviorFloating : AAMemoryBehaviorImpl {
7891 AAMemoryBehaviorFloating(
const IRPosition &IRP, Attributor &
A)
7892 : AAMemoryBehaviorImpl(IRP,
A) {}
7896 void trackStatistics()
const override {
7901 else if (isAssumedWriteOnly())
7908 bool followUsersOfUseIn(Attributor &
A,
const Use &U,
7909 const Instruction *UserI);
7912 void analyzeUseIn(Attributor &
A,
const Use &U,
const Instruction *UserI);
7916struct AAMemoryBehaviorArgument : AAMemoryBehaviorFloating {
7917 AAMemoryBehaviorArgument(
const IRPosition &IRP, Attributor &
A)
7918 : AAMemoryBehaviorFloating(IRP,
A) {}
7921 intersectAssumedBits(BEST_STATE);
7922 const IRPosition &IRP = getIRPosition();
7926 bool HasByVal =
A.hasAttr(IRP, {Attribute::ByVal},
7928 getKnownStateFromValue(
A, IRP, getState(),
7935 return ChangeStatus::UNCHANGED;
7939 if (
A.hasAttr(getIRPosition(),
7940 {Attribute::InAlloca, Attribute::Preallocated})) {
7941 removeKnownBits(NO_WRITES);
7942 removeAssumedBits(NO_WRITES);
7944 A.removeAttrs(getIRPosition(), AttrKinds);
7945 return AAMemoryBehaviorFloating::manifest(
A);
7948 void trackStatistics()
const override {
7953 else if (isAssumedWriteOnly())
7958struct AAMemoryBehaviorCallSiteArgument final : AAMemoryBehaviorArgument {
7959 AAMemoryBehaviorCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
7960 : AAMemoryBehaviorArgument(IRP,
A) {}
7965 Argument *Arg = getAssociatedArgument();
7967 indicatePessimisticFixpoint();
7971 addKnownBits(NO_WRITES);
7972 removeKnownBits(NO_READS);
7973 removeAssumedBits(NO_READS);
7975 AAMemoryBehaviorArgument::initialize(
A);
7976 if (getAssociatedFunction()->isDeclaration())
7977 indicatePessimisticFixpoint();
7985 Argument *Arg = getAssociatedArgument();
7988 A.getAAFor<AAMemoryBehavior>(*
this, ArgPos, DepClassTy::REQUIRED);
7990 return indicatePessimisticFixpoint();
7994 void trackStatistics()
const override {
7999 else if (isAssumedWriteOnly())
8005struct AAMemoryBehaviorCallSiteReturned final : AAMemoryBehaviorFloating {
8006 AAMemoryBehaviorCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
8007 : AAMemoryBehaviorFloating(IRP,
A) {}
8010 AAMemoryBehaviorImpl::initialize(
A);
8014 return ChangeStatus::UNCHANGED;
8017 void trackStatistics()
const override {}
8021struct AAMemoryBehaviorFunction final :
public AAMemoryBehaviorImpl {
8022 AAMemoryBehaviorFunction(
const IRPosition &IRP, Attributor &
A)
8023 : AAMemoryBehaviorImpl(IRP,
A) {}
8037 else if (isAssumedWriteOnly())
8040 A.removeAttrs(getIRPosition(), AttrKinds);
8043 for (Argument &Arg :
F.args())
8045 return A.manifestAttrs(getIRPosition(),
8046 Attribute::getWithMemoryEffects(
F.getContext(), ME));
8049 void trackStatistics()
const override {
8054 else if (isAssumedWriteOnly())
8060struct AAMemoryBehaviorCallSite final
8061 : AACalleeToCallSite<AAMemoryBehavior, AAMemoryBehaviorImpl> {
8062 AAMemoryBehaviorCallSite(
const IRPosition &IRP, Attributor &
A)
8063 : AACalleeToCallSite<AAMemoryBehavior, AAMemoryBehaviorImpl>(IRP,
A) {}
8073 else if (isAssumedWriteOnly())
8076 A.removeAttrs(getIRPosition(), AttrKinds);
8079 for (Use &U : CB.
args())
8081 Attribute::Writable);
8082 return A.manifestAttrs(
8083 getIRPosition(), Attribute::getWithMemoryEffects(CB.
getContext(), ME));
8086 void trackStatistics()
const override {
8091 else if (isAssumedWriteOnly())
8096ChangeStatus AAMemoryBehaviorFunction::updateImpl(Attributor &
A) {
8099 auto AssumedState = getAssumed();
8106 const auto *MemBehaviorAA =
A.getAAFor<AAMemoryBehavior>(
8108 if (MemBehaviorAA) {
8109 intersectAssumedBits(MemBehaviorAA->
getAssumed());
8110 return !isAtFixpoint();
8115 if (
I.mayReadFromMemory())
8116 removeAssumedBits(NO_READS);
8117 if (
I.mayWriteToMemory())
8118 removeAssumedBits(NO_WRITES);
8119 return !isAtFixpoint();
8122 bool UsedAssumedInformation =
false;
8123 if (!
A.checkForAllReadWriteInstructions(CheckRWInst, *
this,
8124 UsedAssumedInformation))
8125 return indicatePessimisticFixpoint();
8131ChangeStatus AAMemoryBehaviorFloating::updateImpl(Attributor &
A) {
8133 const IRPosition &IRP = getIRPosition();
8144 const auto *FnMemAA =
8147 FnMemAssumedState = FnMemAA->getAssumed();
8148 S.addKnownBits(FnMemAA->getKnown());
8149 if ((S.getAssumed() & FnMemAA->getAssumed()) == S.getAssumed())
8155 auto AssumedState = S.getAssumed();
8161 bool IsKnownNoCapture;
8162 const AANoCapture *ArgNoCaptureAA =
nullptr;
8167 if (!IsAssumedNoCapture &&
8169 S.intersectAssumedBits(FnMemAssumedState);
8175 auto UsePred = [&](
const Use &
U,
bool &Follow) ->
bool {
8177 LLVM_DEBUG(
dbgs() <<
"[AAMemoryBehavior] Use: " << *U <<
" in " << *UserI
8185 Follow = followUsersOfUseIn(
A, U, UserI);
8189 analyzeUseIn(
A, U, UserI);
8191 return !isAtFixpoint();
8194 if (!
A.checkForAllUses(UsePred, *
this, getAssociatedValue()))
8195 return indicatePessimisticFixpoint();
8201bool AAMemoryBehaviorFloating::followUsersOfUseIn(Attributor &
A,
const Use &U,
8202 const Instruction *UserI) {
8220 if (
U.get()->getType()->isPointerTy()) {
8222 bool IsKnownNoCapture;
8231void AAMemoryBehaviorFloating::analyzeUseIn(Attributor &
A,
const Use &U,
8232 const Instruction *UserI) {
8239 case Instruction::Load:
8241 removeAssumedBits(NO_READS);
8244 case Instruction::Store:
8249 removeAssumedBits(NO_WRITES);
8251 indicatePessimisticFixpoint();
8254 case Instruction::Call:
8255 case Instruction::CallBr:
8256 case Instruction::Invoke: {
8263 indicatePessimisticFixpoint();
8270 removeAssumedBits(NO_READS);
8277 if (
U.get()->getType()->isPointerTy())
8281 const auto *MemBehaviorAA =
8287 intersectAssumedBits(MemBehaviorAA->
getAssumed());
8295 removeAssumedBits(NO_READS);
8297 removeAssumedBits(NO_WRITES);
8309 return "all memory";
8312 std::string S =
"memory:";
8318 S +=
"internal global,";
8320 S +=
"external global,";
8324 S +=
"inaccessible,";
8338 AccessKind2Accesses.fill(
nullptr);
8341 ~AAMemoryLocationImpl()
override {
8344 for (AccessSet *AS : AccessKind2Accesses)
8350 intersectAssumedBits(BEST_STATE);
8351 getKnownStateFromValue(
A, getIRPosition(), getState());
8352 AAMemoryLocation::initialize(
A);
8356 static void getKnownStateFromValue(Attributor &
A,
const IRPosition &IRP,
8357 BitIntegerState &State,
8358 bool IgnoreSubsumingPositions =
false) {
8367 bool UseArgMemOnly =
true;
8369 if (AnchorFn &&
A.isRunOn(*AnchorFn))
8373 A.getAttrs(IRP, {Attribute::Memory},
Attrs, IgnoreSubsumingPositions);
8382 State.
addKnownBits(inverseLocation(NO_INACCESSIBLE_MEM,
true,
true));
8387 State.
addKnownBits(inverseLocation(NO_ARGUMENT_MEM,
true,
true));
8391 A.manifestAttrs(IRP,
8392 Attribute::getWithMemoryEffects(
8401 NO_INACCESSIBLE_MEM | NO_ARGUMENT_MEM,
true,
true));
8405 A.manifestAttrs(IRP,
8406 Attribute::getWithMemoryEffects(
8415 void getDeducedAttributes(Attributor &
A, LLVMContext &Ctx,
8416 SmallVectorImpl<Attribute> &Attrs)
const override {
8423 else if (isAssumedInaccessibleMemOnly())
8424 Attrs.push_back(Attribute::getWithMemoryEffects(
8426 else if (isAssumedArgMemOnly())
8429 else if (isAssumedInaccessibleOrArgMemOnly())
8430 Attrs.push_back(Attribute::getWithMemoryEffects(
8439 const IRPosition &IRP = getIRPosition();
8443 if (DeducedAttrs.
size() != 1)
8444 return ChangeStatus::UNCHANGED;
8447 return A.manifestAttrs(IRP, Attribute::getWithMemoryEffects(
8451 bool checkForAllAccessesToMemoryKind(
8453 MemoryLocationsKind)>
8455 MemoryLocationsKind RequestedMLK)
const override {
8456 if (!isValidState())
8459 MemoryLocationsKind AssumedMLK = getAssumedNotAccessedLocation();
8460 if (AssumedMLK == NO_LOCATIONS)
8464 for (MemoryLocationsKind CurMLK = 1; CurMLK < NO_LOCATIONS;
8465 CurMLK *= 2, ++
Idx) {
8466 if (CurMLK & RequestedMLK)
8469 if (
const AccessSet *
Accesses = AccessKind2Accesses[Idx])
8470 for (
const AccessInfo &AI : *
Accesses)
8471 if (!
Pred(AI.I, AI.Ptr, AI.Kind, CurMLK))
8484 MemoryLocationsKind KnownMLK = getKnown();
8486 for (MemoryLocationsKind CurMLK = 1; CurMLK < NO_LOCATIONS; CurMLK *= 2)
8487 if (!(CurMLK & KnownMLK))
8488 updateStateAndAccessesMap(getState(), CurMLK,
I,
nullptr,
Changed,
8489 getAccessKindFromInst(
I));
8490 return AAMemoryLocation::indicatePessimisticFixpoint();
8510 bool operator()(
const AccessInfo &
LHS,
const AccessInfo &
RHS)
const {
8514 return LHS.Ptr <
RHS.Ptr;
8515 if (
LHS.Kind !=
RHS.Kind)
8516 return LHS.Kind <
RHS.Kind;
8523 using AccessSet = SmallSet<AccessInfo, 2, AccessInfo>;
8524 std::array<AccessSet *, llvm::ConstantLog2<VALID_STATE>()>
8525 AccessKind2Accesses;
8530 categorizeArgumentPointerLocations(Attributor &
A, CallBase &CB,
8531 AAMemoryLocation::StateType &AccessedLocs,
8536 categorizeAccessedLocations(Attributor &
A, Instruction &
I,
bool &
Changed);
8539 AccessKind getAccessKindFromInst(
const Instruction *
I) {
8542 AK =
I->mayReadFromMemory() ? READ :
NONE;
8551 void updateStateAndAccessesMap(AAMemoryLocation::StateType &State,
8552 MemoryLocationsKind MLK,
const Instruction *
I,
8561 if (MLK == NO_UNKOWN_MEM)
8563 State.removeAssumedBits(MLK);
8568 void categorizePtrValue(Attributor &
A,
const Instruction &
I,
const Value &Ptr,
8569 AAMemoryLocation::StateType &State,
bool &
Changed,
8570 unsigned AccessAS = 0);
8576void AAMemoryLocationImpl::categorizePtrValue(
8577 Attributor &
A,
const Instruction &
I,
const Value &Ptr,
8579 LLVM_DEBUG(
dbgs() <<
"[AAMemoryLocation] Categorize pointer locations for "
8584 unsigned ObjectAS =
Obj.getType()->getPointerAddressSpace();
8586 MemoryLocationsKind MLK = NO_LOCATIONS;
8606 MLK = NO_ARGUMENT_MEM;
8612 if (GVar->isConstant())
8615 if (GV->hasLocalLinkage())
8616 MLK = NO_GLOBAL_INTERNAL_MEM;
8618 MLK = NO_GLOBAL_EXTERNAL_MEM;
8627 bool IsKnownNoAlias;
8631 MLK = NO_MALLOCED_MEM;
8633 MLK = NO_UNKOWN_MEM;
8635 MLK = NO_UNKOWN_MEM;
8638 assert(MLK != NO_LOCATIONS &&
"No location specified!");
8639 LLVM_DEBUG(
dbgs() <<
"[AAMemoryLocation] Ptr value can be categorized: "
8640 << Obj <<
" -> " << getMemoryLocationsAsStr(MLK) <<
"\n");
8642 getAccessKindFromInst(&
I));
8647 const auto *AA =
A.getAAFor<AAUnderlyingObjects>(
8651 dbgs() <<
"[AAMemoryLocation] Pointer locations not categorized\n");
8652 updateStateAndAccessesMap(
State, NO_UNKOWN_MEM, &
I,
nullptr,
Changed,
8653 getAccessKindFromInst(&
I));
8658 dbgs() <<
"[AAMemoryLocation] Accessed locations with pointer locations: "
8662void AAMemoryLocationImpl::categorizeArgumentPointerLocations(
8665 for (
unsigned ArgNo = 0,
E = CB.
arg_size(); ArgNo <
E; ++ArgNo) {
8674 const auto *ArgOpMemLocationAA =
8677 if (ArgOpMemLocationAA && ArgOpMemLocationAA->isAssumedReadNone())
8682 categorizePtrValue(
A, CB, *ArgOp, AccessedLocs,
Changed);
8687AAMemoryLocationImpl::categorizeAccessedLocations(Attributor &
A, Instruction &
I,
8689 LLVM_DEBUG(
dbgs() <<
"[AAMemoryLocation] Categorize accessed locations for "
8693 AccessedLocs.intersectAssumedBits(NO_LOCATIONS);
8698 const auto *CBMemLocationAA =
A.getAAFor<AAMemoryLocation>(
8701 <<
" [" << CBMemLocationAA <<
"]\n");
8702 if (!CBMemLocationAA) {
8703 updateStateAndAccessesMap(AccessedLocs, NO_UNKOWN_MEM, &
I,
nullptr,
8704 Changed, getAccessKindFromInst(&
I));
8705 return NO_UNKOWN_MEM;
8708 if (CBMemLocationAA->isAssumedReadNone())
8709 return NO_LOCATIONS;
8711 if (CBMemLocationAA->isAssumedInaccessibleMemOnly()) {
8712 updateStateAndAccessesMap(AccessedLocs, NO_INACCESSIBLE_MEM, &
I,
nullptr,
8713 Changed, getAccessKindFromInst(&
I));
8714 return AccessedLocs.getAssumed();
8717 uint32_t CBAssumedNotAccessedLocs =
8718 CBMemLocationAA->getAssumedNotAccessedLocation();
8721 uint32_t CBAssumedNotAccessedLocsNoArgMem =
8722 CBAssumedNotAccessedLocs | NO_ARGUMENT_MEM | NO_GLOBAL_MEM;
8724 for (MemoryLocationsKind CurMLK = 1; CurMLK < NO_LOCATIONS; CurMLK *= 2) {
8725 if (CBAssumedNotAccessedLocsNoArgMem & CurMLK)
8727 updateStateAndAccessesMap(AccessedLocs, CurMLK, &
I,
nullptr,
Changed,
8728 getAccessKindFromInst(&
I));
8733 bool HasGlobalAccesses = ((~CBAssumedNotAccessedLocs) & NO_GLOBAL_MEM);
8734 if (HasGlobalAccesses) {
8737 updateStateAndAccessesMap(AccessedLocs, MLK, &
I, Ptr,
Changed,
8738 getAccessKindFromInst(&
I));
8741 if (!CBMemLocationAA->checkForAllAccessesToMemoryKind(
8742 AccessPred, inverseLocation(NO_GLOBAL_MEM,
false,
false)))
8743 return AccessedLocs.getWorstState();
8747 dbgs() <<
"[AAMemoryLocation] Accessed state before argument handling: "
8748 << getMemoryLocationsAsStr(AccessedLocs.getAssumed()) <<
"\n");
8751 bool HasArgAccesses = ((~CBAssumedNotAccessedLocs) & NO_ARGUMENT_MEM);
8753 categorizeArgumentPointerLocations(
A, *CB, AccessedLocs,
Changed);
8756 dbgs() <<
"[AAMemoryLocation] Accessed state after argument handling: "
8757 << getMemoryLocationsAsStr(AccessedLocs.getAssumed()) <<
"\n");
8759 return AccessedLocs.getAssumed();
8764 dbgs() <<
"[AAMemoryLocation] Categorize memory access with pointer: "
8765 <<
I <<
" [" << *Ptr <<
"]\n");
8766 categorizePtrValue(
A,
I, *Ptr, AccessedLocs,
Changed,
8767 Ptr->getType()->getPointerAddressSpace());
8768 return AccessedLocs.getAssumed();
8771 LLVM_DEBUG(
dbgs() <<
"[AAMemoryLocation] Failed to categorize instruction: "
8773 updateStateAndAccessesMap(AccessedLocs, NO_UNKOWN_MEM, &
I,
nullptr,
Changed,
8774 getAccessKindFromInst(&
I));
8775 return AccessedLocs.getAssumed();
8779struct AAMemoryLocationFunction final :
public AAMemoryLocationImpl {
8780 AAMemoryLocationFunction(
const IRPosition &IRP, Attributor &
A)
8781 : AAMemoryLocationImpl(IRP,
A) {}
8785 const auto *MemBehaviorAA =
8786 A.getAAFor<AAMemoryBehavior>(*
this, getIRPosition(), DepClassTy::NONE);
8789 return indicateOptimisticFixpoint();
8791 "AAMemoryLocation was not read-none but AAMemoryBehavior was!");
8792 A.recordDependence(*MemBehaviorAA, *
this, DepClassTy::OPTIONAL);
8793 return ChangeStatus::UNCHANGED;
8797 auto AssumedState = getAssumed();
8801 MemoryLocationsKind MLK = categorizeAccessedLocations(
A,
I,
Changed);
8802 LLVM_DEBUG(
dbgs() <<
"[AAMemoryLocation] Accessed locations for " <<
I
8803 <<
": " << getMemoryLocationsAsStr(MLK) <<
"\n");
8804 removeAssumedBits(inverseLocation(MLK,
false,
false));
8807 return getAssumedNotAccessedLocation() != VALID_STATE;
8810 bool UsedAssumedInformation =
false;
8811 if (!
A.checkForAllReadWriteInstructions(CheckRWInst, *
this,
8812 UsedAssumedInformation))
8813 return indicatePessimisticFixpoint();
8815 Changed |= AssumedState != getAssumed();
8816 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
8819 void trackStatistics()
const override {
8822 else if (isAssumedArgMemOnly())
8824 else if (isAssumedInaccessibleMemOnly())
8826 else if (isAssumedInaccessibleOrArgMemOnly())
8832struct AAMemoryLocationCallSite final : AAMemoryLocationImpl {
8833 AAMemoryLocationCallSite(
const IRPosition &IRP, Attributor &
A)
8834 : AAMemoryLocationImpl(IRP,
A) {}
8844 A.getAAFor<AAMemoryLocation>(*
this, FnPos, DepClassTy::REQUIRED);
8846 return indicatePessimisticFixpoint();
8850 updateStateAndAccessesMap(getState(), MLK,
I, Ptr,
Changed,
8851 getAccessKindFromInst(
I));
8854 if (!FnAA->checkForAllAccessesToMemoryKind(AccessPred, ALL_LOCATIONS))
8855 return indicatePessimisticFixpoint();
8856 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
8859 void trackStatistics()
const override {
8869struct AADenormalFPMathImpl :
public AADenormalFPMath {
8870 AADenormalFPMathImpl(
const IRPosition &IRP, Attributor &
A)
8871 : AADenormalFPMath(IRP,
A) {}
8873 const std::string getAsStr(Attributor *
A)
const override {
8874 std::string Str(
"AADenormalFPMath[");
8875 raw_string_ostream OS(Str);
8877 DenormalState
Known = getKnown();
8878 if (
Known.Mode.isValid())
8879 OS <<
"denormal-fp-math=" <<
Known.Mode;
8883 if (
Known.ModeF32.isValid())
8884 OS <<
" denormal-fp-math-f32=" <<
Known.ModeF32;
8890struct AADenormalFPMathFunction final : AADenormalFPMathImpl {
8891 AADenormalFPMathFunction(
const IRPosition &IRP, Attributor &
A)
8892 : AADenormalFPMathImpl(IRP,
A) {}
8896 DenormalFPEnv DenormEnv =
F->getDenormalFPEnv();
8906 auto CheckCallSite = [=, &Change, &
A](AbstractCallSite CS) {
8909 <<
"->" << getAssociatedFunction()->
getName() <<
'\n');
8911 const auto *CallerInfo =
A.getAAFor<AADenormalFPMath>(
8917 CallerInfo->getState());
8921 bool AllCallSitesKnown =
true;
8922 if (!
A.checkForAllCallSites(CheckCallSite, *
this,
true, AllCallSitesKnown))
8923 return indicatePessimisticFixpoint();
8925 if (Change == ChangeStatus::CHANGED && isModeFixed())
8931 LLVMContext &Ctx = getAssociatedFunction()->getContext();
8937 DenormalFPEnv KnownEnv(
Known.Mode,
Known.ModeF32);
8940 AttrToRemove.
push_back(Attribute::DenormalFPEnv);
8943 Ctx, Attribute::DenormalFPEnv,
8944 DenormalFPEnv(
Known.Mode,
Known.ModeF32).toIntValue()));
8947 auto &IRP = getIRPosition();
8950 return A.removeAttrs(IRP, AttrToRemove) |
8951 A.manifestAttrs(IRP, AttrToAdd,
true);
8954 void trackStatistics()
const override {
8963struct AAValueConstantRangeImpl : AAValueConstantRange {
8964 using StateType = IntegerRangeState;
8965 AAValueConstantRangeImpl(
const IRPosition &IRP, Attributor &
A)
8966 : AAValueConstantRange(IRP,
A) {}
8969 if (
A.hasSimplificationCallback(getIRPosition())) {
8970 indicatePessimisticFixpoint();
8975 intersectKnown(getConstantRangeFromSCEV(
A, getCtxI()));
8978 intersectKnown(getConstantRangeFromLVI(
A, getCtxI()));
8981 const std::string getAsStr(Attributor *
A)
const override {
8983 llvm::raw_string_ostream OS(Str);
8985 getKnown().print(OS);
8987 getAssumed().print(OS);
8994 const SCEV *getSCEV(Attributor &
A,
const Instruction *
I =
nullptr)
const {
8995 if (!getAnchorScope())
8998 ScalarEvolution *SE =
8999 A.getInfoCache().getAnalysisResultForFunction<ScalarEvolutionAnalysis>(
9002 LoopInfo *LI =
A.getInfoCache().getAnalysisResultForFunction<LoopAnalysis>(
9008 const SCEV *S = SE->
getSCEV(&getAssociatedValue());
9017 ConstantRange getConstantRangeFromSCEV(Attributor &
A,
9018 const Instruction *
I =
nullptr)
const {
9019 if (!getAnchorScope())
9022 ScalarEvolution *SE =
9023 A.getInfoCache().getAnalysisResultForFunction<ScalarEvolutionAnalysis>(
9026 const SCEV *S = getSCEV(
A,
I);
9036 getConstantRangeFromLVI(Attributor &
A,
9037 const Instruction *CtxI =
nullptr)
const {
9038 if (!getAnchorScope())
9041 LazyValueInfo *LVI =
9042 A.getInfoCache().getAnalysisResultForFunction<LazyValueAnalysis>(
9057 bool isValidCtxInstructionForOutsideAnalysis(Attributor &
A,
9058 const Instruction *CtxI,
9059 bool AllowAACtxI)
const {
9060 if (!CtxI || (!AllowAACtxI && CtxI == getCtxI()))
9072 InformationCache &InfoCache =
A.getInfoCache();
9073 const DominatorTree *DT =
9083 getAssumedConstantRange(Attributor &
A,
9084 const Instruction *CtxI =
nullptr)
const override {
9089 if (!isValidCtxInstructionForOutsideAnalysis(
A, CtxI,
9091 return getAssumed();
9093 ConstantRange LVIR = getConstantRangeFromLVI(
A, CtxI);
9094 ConstantRange SCEVR = getConstantRangeFromSCEV(
A, CtxI);
9095 return getAssumed().intersectWith(SCEVR).intersectWith(LVIR);
9100 getMDNodeForConstantRange(
Type *Ty, LLVMContext &Ctx,
9101 const ConstantRange &AssumedConstantRange) {
9103 Ty, AssumedConstantRange.
getLower())),
9105 Ty, AssumedConstantRange.
getUpper()))};
9110 static bool isBetterRange(
const ConstantRange &Assumed,
9111 const Instruction &
I) {
9115 std::optional<ConstantRange>
Known;
9119 }
else if (MDNode *KnownRanges =
I.getMetadata(LLVMContext::MD_range)) {
9125 if (KnownRanges->getNumOperands() > 2)
9128 ConstantInt *
Lower =
9130 ConstantInt *
Upper =
9140 setRangeMetadataIfisBetterRange(Instruction *
I,
9141 const ConstantRange &AssumedConstantRange) {
9142 if (isBetterRange(AssumedConstantRange, *
I)) {
9143 I->setMetadata(LLVMContext::MD_range,
9144 getMDNodeForConstantRange(
I->getType(),
I->getContext(),
9145 AssumedConstantRange));
9152 setRangeRetAttrIfisBetterRange(Attributor &
A,
const IRPosition &IRP,
9154 const ConstantRange &AssumedConstantRange) {
9155 if (isBetterRange(AssumedConstantRange, *
I)) {
9156 A.manifestAttrs(IRP,
9157 Attribute::get(
I->getContext(), Attribute::Range,
9158 AssumedConstantRange),
9167 ConstantRange AssumedConstantRange = getAssumedConstantRange(
A);
9170 auto &
V = getAssociatedValue();
9174 assert(
I == getCtxI() &&
"Should not annotate an instruction which is "
9175 "not the context instruction");
9177 if (setRangeMetadataIfisBetterRange(
I, AssumedConstantRange))
9178 Changed = ChangeStatus::CHANGED;
9180 if (setRangeRetAttrIfisBetterRange(
A, getIRPosition(),
I,
9181 AssumedConstantRange))
9182 Changed = ChangeStatus::CHANGED;
9190struct AAValueConstantRangeArgument final
9191 : AAArgumentFromCallSiteArguments<
9192 AAValueConstantRange, AAValueConstantRangeImpl, IntegerRangeState,
9194 using Base = AAArgumentFromCallSiteArguments<
9195 AAValueConstantRange, AAValueConstantRangeImpl, IntegerRangeState,
9197 AAValueConstantRangeArgument(
const IRPosition &IRP, Attributor &
A)
9200 void trackStatistics()
const override {
9205struct AAValueConstantRangeReturned
9206 : AAReturnedFromReturnedValues<AAValueConstantRange,
9207 AAValueConstantRangeImpl,
9208 AAValueConstantRangeImpl::StateType,
9211 AAReturnedFromReturnedValues<AAValueConstantRange,
9212 AAValueConstantRangeImpl,
9213 AAValueConstantRangeImpl::StateType,
9215 AAValueConstantRangeReturned(
const IRPosition &IRP, Attributor &
A)
9219 if (!
A.isFunctionIPOAmendable(*getAssociatedFunction()))
9220 indicatePessimisticFixpoint();
9223 void trackStatistics()
const override {
9228struct AAValueConstantRangeFloating : AAValueConstantRangeImpl {
9229 AAValueConstantRangeFloating(
const IRPosition &IRP, Attributor &
A)
9230 : AAValueConstantRangeImpl(IRP,
A) {}
9233 AAValueConstantRangeImpl::initialize(
A);
9237 Value &
V = getAssociatedValue();
9240 unionAssumed(ConstantRange(
C->getValue()));
9241 indicateOptimisticFixpoint();
9247 unionAssumed(ConstantRange(APInt(
getBitWidth(), 0)));
9248 indicateOptimisticFixpoint();
9260 if (
auto *RangeMD = LI->getMetadata(LLVMContext::MD_range)) {
9271 indicatePessimisticFixpoint();
9274 << getAssociatedValue() <<
"\n");
9277 bool calculateBinaryOperator(
9278 Attributor &
A, BinaryOperator *BinOp, IntegerRangeState &
T,
9279 const Instruction *CtxI,
9280 SmallVectorImpl<const AAValueConstantRange *> &QuerriedAAs) {
9285 bool UsedAssumedInformation =
false;
9286 const auto &SimplifiedLHS =
A.getAssumedSimplified(
9289 if (!SimplifiedLHS.has_value())
9291 if (!*SimplifiedLHS)
9293 LHS = *SimplifiedLHS;
9295 const auto &SimplifiedRHS =
A.getAssumedSimplified(
9298 if (!SimplifiedRHS.has_value())
9300 if (!*SimplifiedRHS)
9302 RHS = *SimplifiedRHS;
9308 auto *LHSAA =
A.getAAFor<AAValueConstantRange>(
9310 DepClassTy::REQUIRED);
9314 auto LHSAARange = LHSAA->getAssumedConstantRange(
A, CtxI);
9316 auto *RHSAA =
A.getAAFor<AAValueConstantRange>(
9318 DepClassTy::REQUIRED);
9322 auto RHSAARange = RHSAA->getAssumedConstantRange(
A, CtxI);
9324 auto AssumedRange = LHSAARange.binaryOp(BinOp->
getOpcode(), RHSAARange);
9326 T.unionAssumed(AssumedRange);
9330 return T.isValidState();
9333 bool calculateCastInst(
9334 Attributor &
A, CastInst *CastI, IntegerRangeState &
T,
9335 const Instruction *CtxI,
9336 SmallVectorImpl<const AAValueConstantRange *> &QuerriedAAs) {
9342 bool UsedAssumedInformation =
false;
9343 const auto &SimplifiedOpV =
A.getAssumedSimplified(
9346 if (!SimplifiedOpV.has_value())
9348 if (!*SimplifiedOpV)
9350 OpV = *SimplifiedOpV;
9355 auto *OpAA =
A.getAAFor<AAValueConstantRange>(
9357 DepClassTy::REQUIRED);
9361 T.unionAssumed(OpAA->getAssumed().castOp(CastI->
getOpcode(),
9363 return T.isValidState();
9367 calculateCmpInst(Attributor &
A, CmpInst *CmpI, IntegerRangeState &
T,
9368 const Instruction *CtxI,
9369 SmallVectorImpl<const AAValueConstantRange *> &QuerriedAAs) {
9374 bool UsedAssumedInformation =
false;
9375 const auto &SimplifiedLHS =
A.getAssumedSimplified(
9378 if (!SimplifiedLHS.has_value())
9380 if (!*SimplifiedLHS)
9382 LHS = *SimplifiedLHS;
9384 const auto &SimplifiedRHS =
A.getAssumedSimplified(
9387 if (!SimplifiedRHS.has_value())
9389 if (!*SimplifiedRHS)
9391 RHS = *SimplifiedRHS;
9397 auto *LHSAA =
A.getAAFor<AAValueConstantRange>(
9399 DepClassTy::REQUIRED);
9403 auto *RHSAA =
A.getAAFor<AAValueConstantRange>(
9405 DepClassTy::REQUIRED);
9409 auto LHSAARange = LHSAA->getAssumedConstantRange(
A, CtxI);
9410 auto RHSAARange = RHSAA->getAssumedConstantRange(
A, CtxI);
9413 if (LHSAARange.isEmptySet() || RHSAARange.isEmptySet())
9416 bool MustTrue =
false, MustFalse =
false;
9418 auto AllowedRegion =
9421 if (AllowedRegion.intersectWith(LHSAARange).isEmptySet())
9427 assert((!MustTrue || !MustFalse) &&
9428 "Either MustTrue or MustFalse should be false!");
9431 T.unionAssumed(ConstantRange(APInt( 1, 1)));
9433 T.unionAssumed(ConstantRange(APInt( 1, 0)));
9435 T.unionAssumed(ConstantRange( 1,
true));
9437 LLVM_DEBUG(
dbgs() <<
"[AAValueConstantRange] " << *CmpI <<
" after "
9438 << (MustTrue ?
"true" : (MustFalse ?
"false" :
"unknown"))
9439 <<
": " <<
T <<
"\n\t" << *LHSAA <<
"\t<op>\n\t"
9443 return T.isValidState();
9454 bool UsedAssumedInformation =
false;
9455 const auto &SimplifiedOpV =
A.getAssumedSimplified(
9458 if (!SimplifiedOpV.has_value())
9460 if (!*SimplifiedOpV)
9462 Value *VPtr = *SimplifiedOpV;
9465 const auto *AA =
A.getAAFor<AAValueConstantRange>(
9467 DepClassTy::REQUIRED);
9471 T.unionAssumed(AA->getAssumedConstantRange(
A, CtxI));
9475 return T.isValidState();
9480 if (!calculateBinaryOperator(
A, BinOp,
T, CtxI, QuerriedAAs))
9483 if (!calculateCmpInst(
A, CmpI,
T, CtxI, QuerriedAAs))
9486 if (!calculateCastInst(
A, CastI,
T, CtxI, QuerriedAAs))
9492 T.indicatePessimisticFixpoint();
9499 for (
const AAValueConstantRange *QueriedAA : QuerriedAAs) {
9500 if (QueriedAA !=
this)
9503 if (
T.getAssumed() == getState().getAssumed())
9505 T.indicatePessimisticFixpoint();
9508 return T.isValidState();
9511 if (!VisitValueCB(getAssociatedValue(), getCtxI()))
9512 return indicatePessimisticFixpoint();
9517 return ChangeStatus::UNCHANGED;
9518 if (++NumChanges > MaxNumChanges) {
9519 LLVM_DEBUG(
dbgs() <<
"[AAValueConstantRange] performed " << NumChanges
9520 <<
" but only " << MaxNumChanges
9521 <<
" are allowed to avoid cyclic reasoning.");
9522 return indicatePessimisticFixpoint();
9524 return ChangeStatus::CHANGED;
9527 void trackStatistics()
const override {
9536 static constexpr int MaxNumChanges = 5;
9539struct AAValueConstantRangeFunction : AAValueConstantRangeImpl {
9540 AAValueConstantRangeFunction(
const IRPosition &IRP, Attributor &
A)
9541 : AAValueConstantRangeImpl(IRP,
A) {}
9544 llvm_unreachable(
"AAValueConstantRange(Function|CallSite)::updateImpl will "
9551struct AAValueConstantRangeCallSite : AAValueConstantRangeFunction {
9552 AAValueConstantRangeCallSite(
const IRPosition &IRP, Attributor &
A)
9553 : AAValueConstantRangeFunction(IRP,
A) {}
9558struct AAValueConstantRangeCallSiteReturned
9559 : AACalleeToCallSite<AAValueConstantRange, AAValueConstantRangeImpl,
9560 AAValueConstantRangeImpl::StateType,
9562 AAValueConstantRangeCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
9563 : AACalleeToCallSite<AAValueConstantRange, AAValueConstantRangeImpl,
9564 AAValueConstantRangeImpl::StateType,
9570 if (std::optional<ConstantRange>
Range = CI->getRange())
9571 intersectKnown(*
Range);
9574 AAValueConstantRangeImpl::initialize(
A);
9577 void trackStatistics()
const override {
9581struct AAValueConstantRangeCallSiteArgument : AAValueConstantRangeFloating {
9582 AAValueConstantRangeCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
9583 : AAValueConstantRangeFloating(IRP,
A) {}
9586 return ChangeStatus::UNCHANGED;
9589 void trackStatistics()
const override {
9598struct AAPotentialConstantValuesImpl : AAPotentialConstantValues {
9601 AAPotentialConstantValuesImpl(
const IRPosition &IRP, Attributor &
A)
9602 : AAPotentialConstantValues(IRP,
A) {}
9605 if (
A.hasSimplificationCallback(getIRPosition()))
9606 indicatePessimisticFixpoint();
9608 AAPotentialConstantValues::initialize(
A);
9611 bool fillSetWithConstantValues(Attributor &
A,
const IRPosition &IRP, SetTy &S,
9612 bool &ContainsUndef,
bool ForSelf) {
9614 bool UsedAssumedInformation =
false;
9616 UsedAssumedInformation)) {
9623 auto *PotentialValuesAA =
A.getAAFor<AAPotentialConstantValues>(
9624 *
this, IRP, DepClassTy::REQUIRED);
9625 if (!PotentialValuesAA || !PotentialValuesAA->getState().isValidState())
9627 ContainsUndef = PotentialValuesAA->getState().undefIsContained();
9628 S = PotentialValuesAA->getState().getAssumedSet();
9635 ContainsUndef =
false;
9636 for (
auto &It :
Values) {
9638 ContainsUndef =
true;
9644 S.insert(CI->getValue());
9646 ContainsUndef &= S.empty();
9651 const std::string getAsStr(Attributor *
A)
const override {
9653 llvm::raw_string_ostream OS(Str);
9659 return indicatePessimisticFixpoint();
9663struct AAPotentialConstantValuesArgument final
9664 : AAArgumentFromCallSiteArguments<AAPotentialConstantValues,
9665 AAPotentialConstantValuesImpl,
9666 PotentialConstantIntValuesState> {
9667 using Base = AAArgumentFromCallSiteArguments<AAPotentialConstantValues,
9668 AAPotentialConstantValuesImpl,
9670 AAPotentialConstantValuesArgument(
const IRPosition &IRP, Attributor &
A)
9673 void trackStatistics()
const override {
9678struct AAPotentialConstantValuesReturned
9679 : AAReturnedFromReturnedValues<AAPotentialConstantValues,
9680 AAPotentialConstantValuesImpl> {
9681 using Base = AAReturnedFromReturnedValues<AAPotentialConstantValues,
9682 AAPotentialConstantValuesImpl>;
9683 AAPotentialConstantValuesReturned(
const IRPosition &IRP, Attributor &
A)
9687 if (!
A.isFunctionIPOAmendable(*getAssociatedFunction()))
9688 indicatePessimisticFixpoint();
9689 Base::initialize(
A);
9692 void trackStatistics()
const override {
9697struct AAPotentialConstantValuesFloating : AAPotentialConstantValuesImpl {
9698 AAPotentialConstantValuesFloating(
const IRPosition &IRP, Attributor &
A)
9699 : AAPotentialConstantValuesImpl(IRP,
A) {}
9702 AAPotentialConstantValuesImpl::initialize(
A);
9706 Value &
V = getAssociatedValue();
9709 unionAssumed(
C->getValue());
9710 indicateOptimisticFixpoint();
9715 unionAssumedWithUndef();
9716 indicateOptimisticFixpoint();
9726 indicatePessimisticFixpoint();
9729 << getAssociatedValue() <<
"\n");
9732 static bool calculateICmpInst(
const ICmpInst *ICI,
const APInt &
LHS,
9737 static APInt calculateCastInst(
const CastInst *CI,
const APInt &Src,
9738 uint32_t ResultBitWidth) {
9743 case Instruction::Trunc:
9744 return Src.trunc(ResultBitWidth);
9745 case Instruction::SExt:
9746 return Src.sext(ResultBitWidth);
9747 case Instruction::ZExt:
9748 return Src.zext(ResultBitWidth);
9749 case Instruction::BitCast:
9754 static APInt calculateBinaryOperator(
const BinaryOperator *BinOp,
9755 const APInt &
LHS,
const APInt &
RHS,
9756 bool &SkipOperation,
bool &Unsupported) {
9763 switch (BinOpcode) {
9767 case Instruction::Add:
9769 case Instruction::Sub:
9771 case Instruction::Mul:
9773 case Instruction::UDiv:
9775 SkipOperation =
true;
9779 case Instruction::SDiv:
9781 SkipOperation =
true;
9785 case Instruction::URem:
9787 SkipOperation =
true;
9791 case Instruction::SRem:
9793 SkipOperation =
true;
9797 case Instruction::Shl:
9799 case Instruction::LShr:
9801 case Instruction::AShr:
9803 case Instruction::And:
9805 case Instruction::Or:
9807 case Instruction::Xor:
9812 bool calculateBinaryOperatorAndTakeUnion(
const BinaryOperator *BinOp,
9813 const APInt &
LHS,
const APInt &
RHS) {
9814 bool SkipOperation =
false;
9817 calculateBinaryOperator(BinOp,
LHS,
RHS, SkipOperation, Unsupported);
9822 unionAssumed(Result);
9823 return isValidState();
9826 ChangeStatus updateWithICmpInst(Attributor &
A, ICmpInst *ICI) {
9827 auto AssumedBefore = getAssumed();
9831 bool LHSContainsUndef =
false, RHSContainsUndef =
false;
9832 SetTy LHSAAPVS, RHSAAPVS;
9834 LHSContainsUndef,
false) ||
9836 RHSContainsUndef,
false))
9837 return indicatePessimisticFixpoint();
9840 bool MaybeTrue =
false, MaybeFalse =
false;
9842 if (LHSContainsUndef && RHSContainsUndef) {
9845 unionAssumedWithUndef();
9846 }
else if (LHSContainsUndef) {
9847 for (
const APInt &R : RHSAAPVS) {
9848 bool CmpResult = calculateICmpInst(ICI,
Zero, R);
9849 MaybeTrue |= CmpResult;
9850 MaybeFalse |= !CmpResult;
9851 if (MaybeTrue & MaybeFalse)
9852 return indicatePessimisticFixpoint();
9854 }
else if (RHSContainsUndef) {
9855 for (
const APInt &L : LHSAAPVS) {
9856 bool CmpResult = calculateICmpInst(ICI, L,
Zero);
9857 MaybeTrue |= CmpResult;
9858 MaybeFalse |= !CmpResult;
9859 if (MaybeTrue & MaybeFalse)
9860 return indicatePessimisticFixpoint();
9863 for (
const APInt &L : LHSAAPVS) {
9864 for (
const APInt &R : RHSAAPVS) {
9865 bool CmpResult = calculateICmpInst(ICI, L, R);
9866 MaybeTrue |= CmpResult;
9867 MaybeFalse |= !CmpResult;
9868 if (MaybeTrue & MaybeFalse)
9869 return indicatePessimisticFixpoint();
9874 unionAssumed(APInt( 1, 1));
9876 unionAssumed(APInt( 1, 0));
9877 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
9878 : ChangeStatus::CHANGED;
9881 ChangeStatus updateWithSelectInst(Attributor &
A, SelectInst *SI) {
9882 auto AssumedBefore = getAssumed();
9886 bool UsedAssumedInformation =
false;
9887 std::optional<Constant *>
C =
A.getAssumedConstant(
9888 *
SI->getCondition(), *
this, UsedAssumedInformation);
9891 bool OnlyLeft =
false, OnlyRight =
false;
9892 if (
C && *
C && (*C)->isOneValue())
9894 else if (
C && *
C && (*C)->isNullValue())
9897 bool LHSContainsUndef =
false, RHSContainsUndef =
false;
9898 SetTy LHSAAPVS, RHSAAPVS;
9901 LHSContainsUndef,
false))
9902 return indicatePessimisticFixpoint();
9906 RHSContainsUndef,
false))
9907 return indicatePessimisticFixpoint();
9909 if (OnlyLeft || OnlyRight) {
9911 auto *OpAA = OnlyLeft ? &LHSAAPVS : &RHSAAPVS;
9912 auto Undef = OnlyLeft ? LHSContainsUndef : RHSContainsUndef;
9915 unionAssumedWithUndef();
9917 for (
const auto &It : *OpAA)
9921 }
else if (LHSContainsUndef && RHSContainsUndef) {
9923 unionAssumedWithUndef();
9925 for (
const auto &It : LHSAAPVS)
9927 for (
const auto &It : RHSAAPVS)
9930 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
9931 : ChangeStatus::CHANGED;
9934 ChangeStatus updateWithCastInst(Attributor &
A, CastInst *CI) {
9935 auto AssumedBefore = getAssumed();
9937 return indicatePessimisticFixpoint();
9942 bool SrcContainsUndef =
false;
9945 SrcContainsUndef,
false))
9946 return indicatePessimisticFixpoint();
9948 if (SrcContainsUndef)
9949 unionAssumedWithUndef();
9951 for (
const APInt &S : SrcPVS) {
9952 APInt
T = calculateCastInst(CI, S, ResultBitWidth);
9956 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
9957 : ChangeStatus::CHANGED;
9960 ChangeStatus updateWithBinaryOperator(Attributor &
A, BinaryOperator *BinOp) {
9961 auto AssumedBefore = getAssumed();
9965 bool LHSContainsUndef =
false, RHSContainsUndef =
false;
9966 SetTy LHSAAPVS, RHSAAPVS;
9968 LHSContainsUndef,
false) ||
9970 RHSContainsUndef,
false))
9971 return indicatePessimisticFixpoint();
9976 if (LHSContainsUndef && RHSContainsUndef) {
9977 if (!calculateBinaryOperatorAndTakeUnion(BinOp,
Zero,
Zero))
9978 return indicatePessimisticFixpoint();
9979 }
else if (LHSContainsUndef) {
9980 for (
const APInt &R : RHSAAPVS) {
9981 if (!calculateBinaryOperatorAndTakeUnion(BinOp,
Zero, R))
9982 return indicatePessimisticFixpoint();
9984 }
else if (RHSContainsUndef) {
9985 for (
const APInt &L : LHSAAPVS) {
9986 if (!calculateBinaryOperatorAndTakeUnion(BinOp, L,
Zero))
9987 return indicatePessimisticFixpoint();
9990 for (
const APInt &L : LHSAAPVS) {
9991 for (
const APInt &R : RHSAAPVS) {
9992 if (!calculateBinaryOperatorAndTakeUnion(BinOp, L, R))
9993 return indicatePessimisticFixpoint();
9997 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
9998 : ChangeStatus::CHANGED;
10001 ChangeStatus updateWithInstruction(Attributor &
A, Instruction *Inst) {
10002 auto AssumedBefore = getAssumed();
10004 bool ContainsUndef;
10006 ContainsUndef,
true))
10007 return indicatePessimisticFixpoint();
10008 if (ContainsUndef) {
10009 unionAssumedWithUndef();
10011 for (
const auto &It : Incoming)
10014 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10015 : ChangeStatus::CHANGED;
10019 Value &
V = getAssociatedValue();
10023 return updateWithICmpInst(
A, ICI);
10026 return updateWithSelectInst(
A, SI);
10029 return updateWithCastInst(
A, CI);
10032 return updateWithBinaryOperator(
A, BinOp);
10035 return updateWithInstruction(
A,
I);
10037 return indicatePessimisticFixpoint();
10040 void trackStatistics()
const override {
10045struct AAPotentialConstantValuesFunction : AAPotentialConstantValuesImpl {
10046 AAPotentialConstantValuesFunction(
const IRPosition &IRP, Attributor &
A)
10047 : AAPotentialConstantValuesImpl(IRP,
A) {}
10051 "AAPotentialConstantValues(Function|CallSite)::updateImpl will "
10055 void trackStatistics()
const override {
10060struct AAPotentialConstantValuesCallSite : AAPotentialConstantValuesFunction {
10061 AAPotentialConstantValuesCallSite(
const IRPosition &IRP, Attributor &
A)
10062 : AAPotentialConstantValuesFunction(IRP,
A) {}
10064 void trackStatistics()
const override {
10069struct AAPotentialConstantValuesCallSiteReturned
10070 : AACalleeToCallSite<AAPotentialConstantValues,
10071 AAPotentialConstantValuesImpl> {
10072 AAPotentialConstantValuesCallSiteReturned(
const IRPosition &IRP,
10074 : AACalleeToCallSite<AAPotentialConstantValues,
10075 AAPotentialConstantValuesImpl>(IRP,
A) {}
10077 void trackStatistics()
const override {
10082struct AAPotentialConstantValuesCallSiteArgument
10083 : AAPotentialConstantValuesFloating {
10084 AAPotentialConstantValuesCallSiteArgument(
const IRPosition &IRP,
10086 : AAPotentialConstantValuesFloating(IRP,
A) {}
10089 AAPotentialConstantValuesImpl::initialize(
A);
10090 if (isAtFixpoint())
10093 Value &
V = getAssociatedValue();
10096 unionAssumed(
C->getValue());
10097 indicateOptimisticFixpoint();
10102 unionAssumedWithUndef();
10103 indicateOptimisticFixpoint();
10109 Value &
V = getAssociatedValue();
10110 auto AssumedBefore = getAssumed();
10111 auto *AA =
A.getAAFor<AAPotentialConstantValues>(
10114 return indicatePessimisticFixpoint();
10115 const auto &S = AA->getAssumed();
10117 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10118 : ChangeStatus::CHANGED;
10121 void trackStatistics()
const override {
10130 bool IgnoreSubsumingPositions) {
10131 assert(ImpliedAttributeKind == Attribute::NoUndef &&
10132 "Unexpected attribute kind");
10133 if (
A.hasAttr(IRP, {Attribute::NoUndef}, IgnoreSubsumingPositions,
10134 Attribute::NoUndef))
10153 Value &
V = getAssociatedValue();
10155 indicatePessimisticFixpoint();
10156 assert(!isImpliedByIR(
A, getIRPosition(), Attribute::NoUndef));
10160 bool followUseInMBEC(Attributor &
A,
const Use *U,
const Instruction *
I,
10161 AANoUndef::StateType &State) {
10162 const Value *UseV =
U->get();
10163 const DominatorTree *DT =
nullptr;
10164 AssumptionCache *AC =
nullptr;
10165 InformationCache &InfoCache =
A.getInfoCache();
10171 bool TrackUse =
false;
10179 const std::string getAsStr(Attributor *
A)
const override {
10180 return getAssumed() ?
"noundef" :
"may-undef-or-poison";
10187 bool UsedAssumedInformation =
false;
10188 if (
A.isAssumedDead(getIRPosition(),
nullptr,
nullptr,
10189 UsedAssumedInformation))
10190 return ChangeStatus::UNCHANGED;
10194 if (!
A.getAssumedSimplified(getIRPosition(), *
this, UsedAssumedInformation,
10197 return ChangeStatus::UNCHANGED;
10198 return AANoUndef::manifest(
A);
10202struct AANoUndefFloating :
public AANoUndefImpl {
10203 AANoUndefFloating(
const IRPosition &IRP, Attributor &
A)
10204 : AANoUndefImpl(IRP,
A) {}
10207 AANoUndefImpl::initialize(
A);
10208 if (!getState().isAtFixpoint() && getAnchorScope() &&
10209 !getAnchorScope()->isDeclaration())
10210 if (Instruction *CtxI = getCtxI())
10211 followUsesInMBEC(*
this,
A, getState(), *CtxI);
10215 auto VisitValueCB = [&](
const IRPosition &IRP) ->
bool {
10216 bool IsKnownNoUndef;
10218 A,
this, IRP, DepClassTy::REQUIRED, IsKnownNoUndef);
10222 bool UsedAssumedInformation =
false;
10223 Value *AssociatedValue = &getAssociatedValue();
10225 if (!
A.getAssumedSimplifiedValues(getIRPosition(), *
this,
Values,
10230 Values.size() != 1 ||
Values.front().getValue() != AssociatedValue;
10238 if (AVIRP == getIRPosition() || !VisitValueCB(AVIRP))
10239 return indicatePessimisticFixpoint();
10240 return ChangeStatus::UNCHANGED;
10243 for (
const auto &VAC :
Values)
10245 return indicatePessimisticFixpoint();
10247 return ChangeStatus::UNCHANGED;
10253struct AANoUndefReturned final
10254 : AAReturnedFromReturnedValues<AANoUndef, AANoUndefImpl> {
10255 AANoUndefReturned(
const IRPosition &IRP, Attributor &
A)
10256 : AAReturnedFromReturnedValues<AANoUndef, AANoUndefImpl>(IRP,
A) {}
10259 AAReturnedFromReturnedValues<AANoUndef, AANoUndefImpl>::initialize(
A);
10260 if (isAtFixpoint())
10265 AttributeMask AM = AttributeFuncs::getPoisonGeneratingAttributes();
10266 AttributeSet RetAttrs =
10267 getAssociatedFunction()->getAttributes().getRetAttrs();
10269 indicatePessimisticFixpoint();
10275struct AANoUndefArgument final
10276 : AAArgumentFromCallSiteArguments<AANoUndef, AANoUndefImpl> {
10277 AANoUndefArgument(
const IRPosition &IRP, Attributor &
A)
10278 : AAArgumentFromCallSiteArguments<AANoUndef, AANoUndefImpl>(IRP,
A) {}
10283struct AANoUndefCallSiteArgument final : AANoUndefFloating {
10284 AANoUndefCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
10285 : AANoUndefFloating(IRP,
A) {}
10290struct AANoUndefCallSiteReturned final
10291 : AACalleeToCallSite<AANoUndef, AANoUndefImpl> {
10292 AANoUndefCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
10293 : AACalleeToCallSite<AANoUndef, AANoUndefImpl>(IRP,
A) {}
10300struct AANoFPClassImpl : AANoFPClass {
10301 AANoFPClassImpl(
const IRPosition &IRP, Attributor &
A) : AANoFPClass(IRP,
A) {}
10304 const IRPosition &IRP = getIRPosition();
10308 indicateOptimisticFixpoint();
10313 A.getAttrs(getIRPosition(), {Attribute::NoFPClass},
Attrs,
false);
10314 for (
const auto &Attr : Attrs) {
10321 const DataLayout &
DL =
A.getDataLayout();
10322 InformationCache &InfoCache =
A.getInfoCache();
10324 const DominatorTree *DT =
nullptr;
10325 AssumptionCache *AC =
nullptr;
10326 const TargetLibraryInfo *
TLI =
nullptr;
10330 if (!
F->isDeclaration()) {
10337 SimplifyQuery Q(
DL,
TLI, DT, AC, CtxI);
10344 followUsesInMBEC(*
this,
A, getState(), *CtxI);
10348 bool followUseInMBEC(Attributor &
A,
const Use *U,
const Instruction *
I,
10349 AANoFPClass::StateType &State) {
10360 if (
auto *NoFPAA =
A.getAAFor<AANoFPClass>(*
this, IRP, DepClassTy::NONE))
10361 State.addKnownBits(NoFPAA->getState().getKnown());
10365 const std::string getAsStr(Attributor *
A)
const override {
10366 std::string
Result =
"nofpclass";
10367 raw_string_ostream OS(Result);
10368 OS << getKnownNoFPClass() <<
'/' << getAssumedNoFPClass();
10372 void getDeducedAttributes(Attributor &
A, LLVMContext &Ctx,
10373 SmallVectorImpl<Attribute> &Attrs)
const override {
10374 Attrs.emplace_back(Attribute::getWithNoFPClass(Ctx, getAssumedNoFPClass()));
10378struct AANoFPClassFloating :
public AANoFPClassImpl {
10379 AANoFPClassFloating(
const IRPosition &IRP, Attributor &
A)
10380 : AANoFPClassImpl(IRP,
A) {}
10384 bool UsedAssumedInformation =
false;
10385 if (!
A.getAssumedSimplifiedValues(getIRPosition(), *
this,
Values,
10387 Values.push_back({getAssociatedValue(), getCtxI()});
10393 DepClassTy::REQUIRED);
10394 if (!AA ||
this == AA) {
10395 T.indicatePessimisticFixpoint();
10397 const AANoFPClass::StateType &S =
10398 static_cast<const AANoFPClass::StateType &
>(AA->
getState());
10401 return T.isValidState();
10404 for (
const auto &VAC :
Values)
10406 return indicatePessimisticFixpoint();
10411 void trackStatistics()
const override {
10416struct AANoFPClassReturned final
10417 : AAReturnedFromReturnedValues<AANoFPClass, AANoFPClassImpl,
10418 AANoFPClassImpl::StateType, false,
10419 Attribute::None, false> {
10420 AANoFPClassReturned(
const IRPosition &IRP, Attributor &
A)
10421 : AAReturnedFromReturnedValues<AANoFPClass, AANoFPClassImpl,
10422 AANoFPClassImpl::StateType,
false,
10425 void trackStatistics()
const override {
10430struct AANoFPClassArgument final
10431 : AAArgumentFromCallSiteArguments<AANoFPClass, AANoFPClassImpl> {
10432 AANoFPClassArgument(
const IRPosition &IRP, Attributor &
A)
10433 : AAArgumentFromCallSiteArguments<AANoFPClass, AANoFPClassImpl>(IRP,
A) {}
10438struct AANoFPClassCallSiteArgument final : AANoFPClassFloating {
10439 AANoFPClassCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
10440 : AANoFPClassFloating(IRP,
A) {}
10442 void trackStatistics()
const override {
10447struct AANoFPClassCallSiteReturned final
10448 : AACalleeToCallSite<AANoFPClass, AANoFPClassImpl> {
10449 AANoFPClassCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
10450 : AACalleeToCallSite<AANoFPClass, AANoFPClassImpl>(IRP,
A) {}
10452 void trackStatistics()
const override {
10457struct AACallEdgesImpl :
public AACallEdges {
10458 AACallEdgesImpl(
const IRPosition &IRP, Attributor &
A) : AACallEdges(IRP,
A) {}
10460 const SetVector<Function *> &getOptimisticEdges()
const override {
10461 return CalledFunctions;
10464 bool hasUnknownCallee()
const override {
return HasUnknownCallee; }
10466 bool hasNonAsmUnknownCallee()
const override {
10467 return HasUnknownCalleeNonAsm;
10470 const std::string getAsStr(Attributor *
A)
const override {
10471 return "CallEdges[" + std::to_string(HasUnknownCallee) +
"," +
10472 std::to_string(CalledFunctions.size()) +
"]";
10475 void trackStatistics()
const override {}
10480 static Function *getOnlyCallee(
const CallBase &CB) {
10482 if (Callee && !
Callee->hasMetadata(LLVMContext::MD_callback))
10488 if (CalledFunctions.insert(Fn)) {
10489 Change = ChangeStatus::CHANGED;
10495 void setHasUnknownCallee(
bool NonAsm,
ChangeStatus &Change) {
10496 if (!HasUnknownCallee)
10497 Change = ChangeStatus::CHANGED;
10498 if (NonAsm && !HasUnknownCalleeNonAsm)
10499 Change = ChangeStatus::CHANGED;
10500 HasUnknownCalleeNonAsm |= NonAsm;
10501 HasUnknownCallee =
true;
10506 SetVector<Function *> CalledFunctions;
10509 bool HasUnknownCallee =
false;
10512 bool HasUnknownCalleeNonAsm =
false;
10515struct AACallEdgesCallSite :
public AACallEdgesImpl {
10516 AACallEdgesCallSite(
const IRPosition &IRP, Attributor &
A)
10517 : AACallEdgesImpl(IRP,
A) {}
10523 addCalledFunction(Callee, Change);
10524 indicateOptimisticFixpoint();
10533 addCalledFunction(Fn, Change);
10535 LLVM_DEBUG(
dbgs() <<
"[AACallEdges] Unrecognized value: " <<
V <<
"\n");
10536 setHasUnknownCallee(
true, Change);
10547 VisitValue(*
V, CtxI);
10551 bool UsedAssumedInformation =
false;
10555 Values.push_back({*
V, CtxI});
10557 for (
auto &VAC :
Values)
10564 if (
IA->hasSideEffects() &&
10567 setHasUnknownCallee(
false, Change);
10573 if (
auto *IndirectCallAA =
A.getAAFor<AAIndirectCallInfo>(
10574 *
this, getIRPosition(), DepClassTy::OPTIONAL))
10575 if (IndirectCallAA->foreachCallee(
10576 [&](
Function *Fn) { return VisitValue(*Fn, CB); }))
10585 for (
const Use *U : CallbackUses)
10586 ProcessCalledOperand(
U->get(), CB);
10592struct AACallEdgesFunction :
public AACallEdgesImpl {
10593 AACallEdgesFunction(
const IRPosition &IRP, Attributor &
A)
10594 : AACallEdgesImpl(IRP,
A) {}
10598 bool AllCallsDirect =
true;
10605 if (
Function *Callee = getOnlyCallee(CB)) {
10606 addCalledFunction(Callee, Change);
10610 AllCallsDirect =
false;
10611 auto *CBEdges =
A.getAAFor<AACallEdges>(
10615 if (CBEdges->hasNonAsmUnknownCallee())
10616 setHasUnknownCallee(
true, Change);
10617 if (CBEdges->hasUnknownCallee())
10618 setHasUnknownCallee(
false, Change);
10620 for (
Function *
F : CBEdges->getOptimisticEdges())
10621 addCalledFunction(
F, Change);
10627 bool UsedAssumedInformation =
false;
10628 if (!
A.checkForAllCallLikeInstructions(ProcessCallInst, *
this,
10629 UsedAssumedInformation,
10633 setHasUnknownCallee(
true, Change);
10637 if (AllCallsDirect && !UsedAssumedInformation)
10638 indicateOptimisticFixpoint();
10646struct AAInterFnReachabilityFunction
10647 :
public CachedReachabilityAA<AAInterFnReachability, Function> {
10648 using Base = CachedReachabilityAA<AAInterFnReachability, Function>;
10649 AAInterFnReachabilityFunction(
const IRPosition &IRP, Attributor &
A)
10652 bool instructionCanReach(
10653 Attributor &
A,
const Instruction &From,
const Function &To,
10656 auto *NonConstThis =
const_cast<AAInterFnReachabilityFunction *
>(
this);
10658 RQITy StackRQI(
A, From, To, ExclusionSet,
false);
10659 RQITy::Reachable
Result;
10660 if (!NonConstThis->checkQueryCache(
A, StackRQI, Result))
10661 return NonConstThis->isReachableImpl(
A, StackRQI,
10663 return Result == RQITy::Reachable::Yes;
10667 bool IsTemporaryRQI)
override {
10669 &RQI.From->getFunction()->getEntryBlock().front();
10670 if (EntryI != RQI.From &&
10671 !instructionCanReach(
A, *EntryI, *RQI.To,
nullptr))
10672 return rememberResult(
A, RQITy::Reachable::No, RQI,
false,
10675 auto CheckReachableCallBase = [&](CallBase *CB) {
10676 auto *CBEdges =
A.getAAFor<AACallEdges>(
10678 if (!CBEdges || !CBEdges->getState().isValidState())
10681 if (CBEdges->hasUnknownCallee())
10684 for (
Function *Fn : CBEdges->getOptimisticEdges()) {
10695 if (Fn == getAnchorScope()) {
10696 if (EntryI == RQI.From)
10701 const AAInterFnReachability *InterFnReachability =
10703 DepClassTy::OPTIONAL);
10706 if (!InterFnReachability ||
10714 const auto *IntraFnReachability =
A.getAAFor<AAIntraFnReachability>(
10716 DepClassTy::OPTIONAL);
10724 return IntraFnReachability && !IntraFnReachability->isAssumedReachable(
10725 A, *RQI.From, CBInst, RQI.ExclusionSet);
10728 bool UsedExclusionSet =
true;
10729 bool UsedAssumedInformation =
false;
10730 if (!
A.checkForAllCallLikeInstructions(CheckCallBase, *
this,
10731 UsedAssumedInformation,
10733 return rememberResult(
A, RQITy::Reachable::Yes, RQI, UsedExclusionSet,
10736 return rememberResult(
A, RQITy::Reachable::No, RQI, UsedExclusionSet,
10740 void trackStatistics()
const override {}
10744template <
typename AAType>
10745static std::optional<Constant *>
10748 if (!Ty.isIntegerTy())
10756 std::optional<Constant *> COpt =
AA->getAssumedConstant(
A);
10758 if (!COpt.has_value()) {
10760 return std::nullopt;
10762 if (
auto *
C = *COpt) {
10773 std::optional<Value *> V;
10774 for (
auto &It :
Values) {
10776 if (V.has_value() && !*V)
10779 if (!V.has_value())
10792 if (
A.hasSimplificationCallback(getIRPosition())) {
10793 indicatePessimisticFixpoint();
10796 Value *Stripped = getAssociatedValue().stripPointerCasts();
10798 addValue(
A, getState(), *Stripped, getCtxI(),
AA::AnyScope,
10800 indicateOptimisticFixpoint();
10803 AAPotentialValues::initialize(
A);
10806 const std::string getAsStr(Attributor *
A)
const override {
10808 llvm::raw_string_ostream OS(Str);
10813 template <
typename AAType>
10814 static std::optional<Value *> askOtherAA(Attributor &
A,
10815 const AbstractAttribute &AA,
10816 const IRPosition &IRP,
Type &Ty) {
10821 return std::nullopt;
10828 virtual void addValue(Attributor &
A, StateType &State,
Value &
V,
10834 for (
const auto &U : CB->
args()) {
10844 Type &Ty = *getAssociatedType();
10845 std::optional<Value *> SimpleV =
10846 askOtherAA<AAValueConstantRange>(
A, *
this, ValIRP, Ty);
10847 if (SimpleV.has_value() && !*SimpleV) {
10848 auto *PotentialConstantsAA =
A.getAAFor<AAPotentialConstantValues>(
10849 *
this, ValIRP, DepClassTy::OPTIONAL);
10850 if (PotentialConstantsAA && PotentialConstantsAA->isValidState()) {
10851 for (
const auto &It : PotentialConstantsAA->getAssumedSet())
10852 State.unionAssumed({{*ConstantInt::get(&Ty, It),
nullptr}, S});
10853 if (PotentialConstantsAA->undefIsContained())
10858 if (!SimpleV.has_value())
10870 State.unionAssumed({{*VPtr, CtxI}, S});
10876 AA::ValueAndContext
I;
10880 return II.I ==
I &&
II.S == S;
10883 return std::tie(
I, S) < std::tie(
II.I,
II.S);
10887 bool recurseForValue(Attributor &
A,
const IRPosition &IRP,
AA::ValueScope S) {
10888 SmallMapVector<AA::ValueAndContext, int, 8> ValueScopeMap;
10893 bool UsedAssumedInformation =
false;
10895 if (!
A.getAssumedSimplifiedValues(IRP,
this,
Values, CS,
10896 UsedAssumedInformation))
10900 ValueScopeMap[It] += CS;
10902 for (
auto &It : ValueScopeMap)
10903 addValue(
A, getState(), *It.first.getValue(), It.first.getCtxI(),
10909 void giveUpOnIntraprocedural(Attributor &
A) {
10910 auto NewS = StateType::getBestState(getState());
10911 for (
const auto &It : getAssumedSet()) {
10914 addValue(
A, NewS, *It.first.getValue(), It.first.getCtxI(),
10917 assert(!undefIsContained() &&
"Undef should be an explicit value!");
10924 getState() = StateType::getBestState(getState());
10925 getState().unionAssumed({{getAssociatedValue(), getCtxI()},
AA::AnyScope});
10926 AAPotentialValues::indicateOptimisticFixpoint();
10927 return ChangeStatus::CHANGED;
10931 return indicatePessimisticFixpoint();
10938 if (!getAssumedSimplifiedValues(
A,
Values, S))
10940 Value &OldV = getAssociatedValue();
10943 Value *NewV = getSingleValue(
A, *
this, getIRPosition(),
Values);
10944 if (!NewV || NewV == &OldV)
10949 if (
A.changeAfterManifest(getIRPosition(), *NewV))
10950 return ChangeStatus::CHANGED;
10952 return ChangeStatus::UNCHANGED;
10955 bool getAssumedSimplifiedValues(
10956 Attributor &
A, SmallVectorImpl<AA::ValueAndContext> &
Values,
10957 AA::ValueScope S,
bool RecurseForSelectAndPHI =
false)
const override {
10958 if (!isValidState())
10960 bool UsedAssumedInformation =
false;
10961 for (
const auto &It : getAssumedSet())
10962 if (It.second & S) {
10963 if (RecurseForSelectAndPHI && (
isa<PHINode>(It.first.getValue()) ||
10965 if (
A.getAssumedSimplifiedValues(
10967 this,
Values, S, UsedAssumedInformation))
10970 Values.push_back(It.first);
10972 assert(!undefIsContained() &&
"Undef should be an explicit value!");
10977struct AAPotentialValuesFloating : AAPotentialValuesImpl {
10978 AAPotentialValuesFloating(
const IRPosition &IRP, Attributor &
A)
10979 : AAPotentialValuesImpl(IRP,
A) {}
10982 auto AssumedBefore = getAssumed();
10984 genericValueTraversal(
A, &getAssociatedValue());
10986 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
10987 : ChangeStatus::CHANGED;
10991 struct LivenessInfo {
10992 const AAIsDead *LivenessAA =
nullptr;
10993 bool AnyDead =
false;
11003 SmallVectorImpl<ItemInfo> &Worklist) {
11006 bool UsedAssumedInformation =
false;
11008 auto GetSimplifiedValues = [&](
Value &
V,
11010 if (!
A.getAssumedSimplifiedValues(
11014 Values.push_back(AA::ValueAndContext{
V,
II.I.getCtxI()});
11018 if (GetSimplifiedValues(*
LHS, LHSValues))
11020 if (GetSimplifiedValues(*
RHS, RHSValues))
11025 InformationCache &InfoCache =
A.getInfoCache();
11032 F ?
A.getInfoCache().getTargetLibraryInfoForFunction(*
F) :
nullptr;
11037 const DataLayout &
DL =
A.getDataLayout();
11038 SimplifyQuery Q(
DL,
TLI, DT, AC, CmpI);
11040 auto CheckPair = [&](
Value &LHSV,
Value &RHSV) {
11043 nullptr,
II.S, getAnchorScope());
11049 if (&LHSV == &RHSV &&
11051 Constant *NewV = ConstantInt::get(Type::getInt1Ty(Ctx),
11053 addValue(
A, getState(), *NewV,
nullptr,
II.S,
11060 if (TypedLHS && TypedRHS) {
11062 if (NewV && NewV != &Cmp) {
11063 addValue(
A, getState(), *NewV,
nullptr,
II.S,
11075 if (!LHSIsNull && !RHSIsNull)
11081 assert((LHSIsNull || RHSIsNull) &&
11082 "Expected nullptr versus non-nullptr comparison at this point");
11085 unsigned PtrIdx = LHSIsNull;
11086 bool IsKnownNonNull;
11089 DepClassTy::REQUIRED, IsKnownNonNull);
11090 if (!IsAssumedNonNull)
11096 addValue(
A, getState(), *NewV,
nullptr,
II.S,
11101 for (
auto &LHSValue : LHSValues)
11102 for (
auto &RHSValue : RHSValues)
11103 if (!CheckPair(*LHSValue.getValue(), *RHSValue.getValue()))
11108 bool handleSelectInst(Attributor &
A, SelectInst &SI, ItemInfo
II,
11109 SmallVectorImpl<ItemInfo> &Worklist) {
11111 bool UsedAssumedInformation =
false;
11113 std::optional<Constant *>
C =
11114 A.getAssumedConstant(*
SI.getCondition(), *
this, UsedAssumedInformation);
11115 bool NoValueYet = !
C.has_value();
11123 }
else if (&SI == &getAssociatedValue()) {
11128 std::optional<Value *> SimpleV =
A.getAssumedSimplified(
11130 if (!SimpleV.has_value())
11133 addValue(
A, getState(), **SimpleV, CtxI,
II.S, getAnchorScope());
11141 bool handleLoadInst(Attributor &
A, LoadInst &LI, ItemInfo
II,
11142 SmallVectorImpl<ItemInfo> &Worklist) {
11143 SmallSetVector<Value *, 4> PotentialCopies;
11144 SmallSetVector<Instruction *, 4> PotentialValueOrigins;
11145 bool UsedAssumedInformation =
false;
11147 PotentialValueOrigins, *
this,
11148 UsedAssumedInformation,
11150 LLVM_DEBUG(
dbgs() <<
"[AAPotentialValues] Failed to get potentially "
11151 "loaded values for load instruction "
11159 InformationCache &InfoCache =
A.getInfoCache();
11161 if (!
llvm::all_of(PotentialValueOrigins, [&](Instruction *
I) {
11165 return A.isAssumedDead(
SI->getOperandUse(0),
this,
11167 UsedAssumedInformation,
11169 return A.isAssumedDead(*
I,
this,
nullptr,
11170 UsedAssumedInformation,
11173 LLVM_DEBUG(
dbgs() <<
"[AAPotentialValues] Load is onl used by assumes "
11174 "and we cannot delete all the stores: "
11185 bool AllLocal = ScopeIsLocal;
11190 if (!DynamicallyUnique) {
11191 LLVM_DEBUG(
dbgs() <<
"[AAPotentialValues] Not all potentially loaded "
11192 "values are dynamically unique: "
11197 for (
auto *PotentialCopy : PotentialCopies) {
11199 Worklist.
push_back({{*PotentialCopy, CtxI},
II.S});
11204 if (!AllLocal && ScopeIsLocal)
11209 bool handlePHINode(
11210 Attributor &
A, PHINode &
PHI, ItemInfo
II,
11211 SmallVectorImpl<ItemInfo> &Worklist,
11212 SmallMapVector<const Function *, LivenessInfo, 4> &LivenessAAs) {
11213 auto GetLivenessInfo = [&](
const Function &
F) -> LivenessInfo & {
11214 LivenessInfo &LI = LivenessAAs[&
F];
11215 if (!LI.LivenessAA)
11221 if (&
PHI == &getAssociatedValue()) {
11222 LivenessInfo &LI = GetLivenessInfo(*
PHI.getFunction());
11224 A.getInfoCache().getAnalysisResultForFunction<CycleAnalysis>(
11225 *
PHI.getFunction());
11229 for (
unsigned u = 0, e =
PHI.getNumIncomingValues(); u < e; u++) {
11231 if (LI.LivenessAA &&
11232 LI.LivenessAA->isEdgeDead(IncomingBB,
PHI.getParent())) {
11251 bool UsedAssumedInformation =
false;
11252 std::optional<Value *> SimpleV =
A.getAssumedSimplified(
11254 if (!SimpleV.has_value())
11258 addValue(
A, getState(), **SimpleV, &
PHI,
II.S, getAnchorScope());
11265 bool handleGenericInst(Attributor &
A, Instruction &
I, ItemInfo
II,
11266 SmallVectorImpl<ItemInfo> &Worklist) {
11267 bool SomeSimplified =
false;
11268 bool UsedAssumedInformation =
false;
11270 SmallVector<Value *, 8> NewOps(
I.getNumOperands());
11273 const auto &SimplifiedOp =
A.getAssumedSimplified(
11278 if (!SimplifiedOp.has_value())
11282 NewOps[
Idx] = *SimplifiedOp;
11286 SomeSimplified |= (NewOps[
Idx] !=
Op);
11292 if (!SomeSimplified)
11295 InformationCache &InfoCache =
A.getInfoCache();
11299 const auto *
TLI =
A.getInfoCache().getTargetLibraryInfoForFunction(*
F);
11302 const DataLayout &
DL =
I.getDataLayout();
11303 SimplifyQuery Q(
DL,
TLI, DT, AC, &
I);
11305 if (!NewV || NewV == &
I)
11308 LLVM_DEBUG(
dbgs() <<
"Generic inst " <<
I <<
" assumed simplified to "
11315 Attributor &
A, Instruction &
I, ItemInfo
II,
11316 SmallVectorImpl<ItemInfo> &Worklist,
11317 SmallMapVector<const Function *, LivenessInfo, 4> &LivenessAAs) {
11320 CI->getPredicate(),
II, Worklist);
11322 switch (
I.getOpcode()) {
11323 case Instruction::Select:
11325 case Instruction::PHI:
11327 case Instruction::Load:
11330 return handleGenericInst(
A,
I,
II, Worklist);
11335 void genericValueTraversal(Attributor &
A,
Value *InitialV) {
11336 SmallMapVector<const Function *, LivenessInfo, 4> LivenessAAs;
11338 SmallSet<ItemInfo, 16> Visited;
11357 LLVM_DEBUG(
dbgs() <<
"Generic value traversal reached iteration limit: "
11358 << Iteration <<
"!\n");
11359 addValue(
A, getState(), *
V, CtxI, S, getAnchorScope());
11365 Value *NewV =
nullptr;
11366 if (
V->getType()->isPointerTy()) {
11372 for (Argument &Arg :
Callee->args())
11379 if (NewV && NewV !=
V) {
11380 Worklist.
push_back({{*NewV, CtxI}, S});
11394 if (
V == InitialV && CtxI == getCtxI()) {
11395 indicatePessimisticFixpoint();
11399 addValue(
A, getState(), *
V, CtxI, S, getAnchorScope());
11400 }
while (!Worklist.
empty());
11404 for (
auto &It : LivenessAAs)
11405 if (It.second.AnyDead)
11406 A.recordDependence(*It.second.LivenessAA, *
this, DepClassTy::OPTIONAL);
11409 void trackStatistics()
const override {
11414struct AAPotentialValuesArgument final : AAPotentialValuesImpl {
11415 using Base = AAPotentialValuesImpl;
11416 AAPotentialValuesArgument(
const IRPosition &IRP, Attributor &
A)
11422 indicatePessimisticFixpoint();
11426 auto AssumedBefore = getAssumed();
11428 unsigned ArgNo = getCalleeArgNo();
11430 bool UsedAssumedInformation =
false;
11432 auto CallSitePred = [&](AbstractCallSite ACS) {
11434 if (CSArgIRP.getPositionKind() == IRP_INVALID)
11437 if (!
A.getAssumedSimplifiedValues(CSArgIRP,
this,
Values,
11439 UsedAssumedInformation))
11442 return isValidState();
11445 if (!
A.checkForAllCallSites(CallSitePred, *
this,
11447 UsedAssumedInformation))
11448 return indicatePessimisticFixpoint();
11450 Function *Fn = getAssociatedFunction();
11451 bool AnyNonLocal =
false;
11452 for (
auto &It :
Values) {
11454 addValue(
A, getState(), *It.getValue(), It.getCtxI(),
AA::AnyScope,
11459 return indicatePessimisticFixpoint();
11463 addValue(
A, getState(), *It.getValue(), It.getCtxI(),
AA::AnyScope,
11469 AnyNonLocal =
true;
11471 assert(!undefIsContained() &&
"Undef should be an explicit value!");
11473 giveUpOnIntraprocedural(
A);
11475 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
11476 : ChangeStatus::CHANGED;
11479 void trackStatistics()
const override {
11484struct AAPotentialValuesReturned :
public AAPotentialValuesFloating {
11485 using Base = AAPotentialValuesFloating;
11486 AAPotentialValuesReturned(
const IRPosition &IRP, Attributor &
A)
11491 if (!
F ||
F->isDeclaration() ||
F->getReturnType()->isVoidTy()) {
11492 indicatePessimisticFixpoint();
11496 for (Argument &Arg :
F->args())
11499 ReturnedArg = &Arg;
11502 if (!
A.isFunctionIPOAmendable(*
F) ||
11503 A.hasSimplificationCallback(getIRPosition())) {
11505 indicatePessimisticFixpoint();
11507 indicateOptimisticFixpoint();
11512 auto AssumedBefore = getAssumed();
11513 bool UsedAssumedInformation =
false;
11516 Function *AnchorScope = getAnchorScope();
11522 UsedAssumedInformation,
11528 bool AllInterAreIntra =
false;
11535 for (
const AA::ValueAndContext &VAC :
Values) {
11536 addValue(
A, getState(), *VAC.
getValue(),
11540 if (AllInterAreIntra)
11547 HandleReturnedValue(*ReturnedArg,
nullptr,
true);
11550 bool AddValues =
true;
11553 addValue(
A, getState(), *RetI.getOperand(0), &RetI,
AA::AnyScope,
11557 return HandleReturnedValue(*RetI.getOperand(0), &RetI, AddValues);
11560 if (!
A.checkForAllInstructions(RetInstPred, *
this, {Instruction::Ret},
11561 UsedAssumedInformation,
11563 return indicatePessimisticFixpoint();
11566 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
11567 : ChangeStatus::CHANGED;
11572 return ChangeStatus::UNCHANGED;
11574 if (!getAssumedSimplifiedValues(
A,
Values, AA::ValueScope::Intraprocedural,
11576 return ChangeStatus::UNCHANGED;
11577 Value *NewVal = getSingleValue(
A, *
this, getIRPosition(),
Values);
11579 return ChangeStatus::UNCHANGED;
11584 "Number of function with unique return");
11587 {Attribute::get(Arg->
getContext(), Attribute::Returned)});
11592 Value *RetOp = RetI.getOperand(0);
11596 if (
A.changeUseAfterManifest(RetI.getOperandUse(0), *NewVal))
11597 Changed = ChangeStatus::CHANGED;
11600 bool UsedAssumedInformation =
false;
11601 (void)
A.checkForAllInstructions(RetInstPred, *
this, {Instruction::Ret},
11602 UsedAssumedInformation,
11608 return AAPotentialValues::indicatePessimisticFixpoint();
11611 void trackStatistics()
const override{
11618struct AAPotentialValuesFunction : AAPotentialValuesImpl {
11619 AAPotentialValuesFunction(
const IRPosition &IRP, Attributor &
A)
11620 : AAPotentialValuesImpl(IRP,
A) {}
11627 void trackStatistics()
const override {
11632struct AAPotentialValuesCallSite : AAPotentialValuesFunction {
11633 AAPotentialValuesCallSite(
const IRPosition &IRP, Attributor &
A)
11634 : AAPotentialValuesFunction(IRP,
A) {}
11636 void trackStatistics()
const override {
11641struct AAPotentialValuesCallSiteReturned : AAPotentialValuesImpl {
11642 AAPotentialValuesCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
11643 : AAPotentialValuesImpl(IRP,
A) {}
11646 auto AssumedBefore = getAssumed();
11650 return indicatePessimisticFixpoint();
11652 bool UsedAssumedInformation =
false;
11656 UsedAssumedInformation))
11657 return indicatePessimisticFixpoint();
11664 Values, S, UsedAssumedInformation))
11667 for (
auto &It :
Values) {
11668 Value *
V = It.getValue();
11669 std::optional<Value *> CallerV =
A.translateArgumentToCallSiteContent(
11670 V, *CB, *
this, UsedAssumedInformation);
11671 if (!CallerV.has_value()) {
11675 V = *CallerV ? *CallerV :
V;
11681 giveUpOnIntraprocedural(
A);
11684 addValue(
A, getState(), *
V, CB, S, getAnchorScope());
11689 return indicatePessimisticFixpoint();
11691 return indicatePessimisticFixpoint();
11692 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
11693 : ChangeStatus::CHANGED;
11697 return AAPotentialValues::indicatePessimisticFixpoint();
11700 void trackStatistics()
const override {
11705struct AAPotentialValuesCallSiteArgument : AAPotentialValuesFloating {
11706 AAPotentialValuesCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
11707 : AAPotentialValuesFloating(IRP,
A) {}
11709 void trackStatistics()
const override {
11717struct AAAssumptionInfoImpl :
public AAAssumptionInfo {
11718 AAAssumptionInfoImpl(
const IRPosition &IRP, Attributor &
A,
11719 const DenseSet<StringRef> &
Known)
11720 : AAAssumptionInfo(IRP,
A,
Known) {}
11724 if (getKnown().isUniversal())
11725 return ChangeStatus::UNCHANGED;
11727 const IRPosition &IRP = getIRPosition();
11729 getAssumed().getSet().
end());
11731 return A.manifestAttrs(IRP,
11738 bool hasAssumption(
const StringRef Assumption)
const override {
11739 return isValidState() && setContains(Assumption);
11742 const std::string getAsStr(Attributor *
A)
const override {
11743 const SetContents &
Known = getKnown();
11744 const SetContents &Assumed = getAssumed();
11748 const std::string KnownStr =
llvm::join(Set,
",");
11750 std::string AssumedStr =
"Universal";
11751 if (!Assumed.isUniversal()) {
11752 Set.assign(Assumed.getSet().begin(), Assumed.getSet().end());
11755 return "Known [" + KnownStr +
"]," +
" Assumed [" + AssumedStr +
"]";
11770struct AAAssumptionInfoFunction final : AAAssumptionInfoImpl {
11771 AAAssumptionInfoFunction(
const IRPosition &IRP, Attributor &
A)
11772 : AAAssumptionInfoImpl(IRP,
A,
11778 auto CallSitePred = [&](AbstractCallSite ACS) {
11779 const auto *AssumptionAA =
A.getAAFor<AAAssumptionInfo>(
11781 DepClassTy::REQUIRED);
11785 Changed |= getIntersection(AssumptionAA->getAssumed());
11786 return !getAssumed().empty() || !getKnown().empty();
11789 bool UsedAssumedInformation =
false;
11794 if (!
A.checkForAllCallSites(CallSitePred, *
this,
true,
11795 UsedAssumedInformation))
11796 return indicatePessimisticFixpoint();
11798 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
11801 void trackStatistics()
const override {}
11805struct AAAssumptionInfoCallSite final : AAAssumptionInfoImpl {
11807 AAAssumptionInfoCallSite(
const IRPosition &IRP, Attributor &
A)
11808 : AAAssumptionInfoImpl(IRP,
A, getInitialAssumptions(IRP)) {}
11812 A.getAAFor<AAAssumptionInfo>(*
this, FnPos, DepClassTy::REQUIRED);
11817 auto *AssumptionAA =
11818 A.getAAFor<AAAssumptionInfo>(*
this, FnPos, DepClassTy::REQUIRED);
11820 return indicatePessimisticFixpoint();
11821 bool Changed = getIntersection(AssumptionAA->getAssumed());
11822 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
11825 void trackStatistics()
const override {}
11830 DenseSet<StringRef> getInitialAssumptions(
const IRPosition &IRP) {
11837 return Assumptions;
11852struct AAUnderlyingObjectsImpl
11857 const std::string getAsStr(
Attributor *
A)
const override {
11858 if (!isValidState())
11859 return "<invalid>";
11862 OS <<
"underlying objects: inter " << InterAssumedUnderlyingObjects.size()
11863 <<
" objects, intra " << IntraAssumedUnderlyingObjects.size()
11865 if (!InterAssumedUnderlyingObjects.empty()) {
11866 OS <<
"inter objects:\n";
11867 for (
auto *Obj : InterAssumedUnderlyingObjects)
11868 OS << *Obj <<
'\n';
11870 if (!IntraAssumedUnderlyingObjects.empty()) {
11871 OS <<
"intra objects:\n";
11872 for (
auto *Obj : IntraAssumedUnderlyingObjects)
11873 OS << *
Obj <<
'\n';
11878 void trackStatistics()
const override {}
11881 auto &Ptr = getAssociatedValue();
11883 bool UsedAssumedInformation =
false;
11884 auto DoUpdate = [&](SmallSetVector<Value *, 8> &UnderlyingObjects,
11886 SmallPtrSet<Value *, 8> SeenObjects;
11890 Scope, UsedAssumedInformation))
11891 return UnderlyingObjects.
insert(&Ptr);
11895 for (
unsigned I = 0;
I <
Values.size(); ++
I) {
11899 if (!SeenObjects.
insert(UO ? UO : Obj).second)
11901 if (UO && UO != Obj) {
11907 const auto *OtherAA =
A.getAAFor<AAUnderlyingObjects>(
11913 Values.emplace_back(
V,
nullptr);
11917 if (!OtherAA || !OtherAA->forallUnderlyingObjects(
Pred, Scope))
11919 "The forall call should not return false at this position");
11925 Changed |= handleIndirect(
A, *Obj, UnderlyingObjects, Scope,
11926 UsedAssumedInformation);
11932 for (
unsigned u = 0, e =
PHI->getNumIncomingValues(); u < e; u++) {
11934 handleIndirect(
A, *
PHI->getIncomingValue(u), UnderlyingObjects,
11935 Scope, UsedAssumedInformation);
11949 if (!UsedAssumedInformation)
11950 indicateOptimisticFixpoint();
11951 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
11954 bool forallUnderlyingObjects(
11957 if (!isValidState())
11958 return Pred(getAssociatedValue());
11961 ? IntraAssumedUnderlyingObjects
11962 : InterAssumedUnderlyingObjects;
11963 for (
Value *Obj : AssumedUnderlyingObjects)
11973 bool handleIndirect(Attributor &
A,
Value &
V,
11974 SmallSetVector<Value *, 8> &UnderlyingObjects,
11977 const auto *AA =
A.getAAFor<AAUnderlyingObjects>(
11983 if (!AA || !AA->forallUnderlyingObjects(
Pred, Scope))
11985 "The forall call should not return false at this position");
11991 SmallSetVector<Value *, 8> IntraAssumedUnderlyingObjects;
11993 SmallSetVector<Value *, 8> InterAssumedUnderlyingObjects;
11996struct AAUnderlyingObjectsFloating final : AAUnderlyingObjectsImpl {
11997 AAUnderlyingObjectsFloating(
const IRPosition &IRP, Attributor &
A)
11998 : AAUnderlyingObjectsImpl(IRP,
A) {}
12001struct AAUnderlyingObjectsArgument final : AAUnderlyingObjectsImpl {
12002 AAUnderlyingObjectsArgument(
const IRPosition &IRP, Attributor &
A)
12003 : AAUnderlyingObjectsImpl(IRP,
A) {}
12006struct AAUnderlyingObjectsCallSite final : AAUnderlyingObjectsImpl {
12007 AAUnderlyingObjectsCallSite(
const IRPosition &IRP, Attributor &
A)
12008 : AAUnderlyingObjectsImpl(IRP,
A) {}
12011struct AAUnderlyingObjectsCallSiteArgument final : AAUnderlyingObjectsImpl {
12012 AAUnderlyingObjectsCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
12013 : AAUnderlyingObjectsImpl(IRP,
A) {}
12016struct AAUnderlyingObjectsReturned final : AAUnderlyingObjectsImpl {
12017 AAUnderlyingObjectsReturned(
const IRPosition &IRP, Attributor &
A)
12018 : AAUnderlyingObjectsImpl(IRP,
A) {}
12021struct AAUnderlyingObjectsCallSiteReturned final : AAUnderlyingObjectsImpl {
12022 AAUnderlyingObjectsCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
12023 : AAUnderlyingObjectsImpl(IRP,
A) {}
12026struct AAUnderlyingObjectsFunction final : AAUnderlyingObjectsImpl {
12027 AAUnderlyingObjectsFunction(
const IRPosition &IRP, Attributor &
A)
12028 : AAUnderlyingObjectsImpl(IRP,
A) {}
12034struct AAGlobalValueInfoFloating :
public AAGlobalValueInfo {
12035 AAGlobalValueInfoFloating(
const IRPosition &IRP, Attributor &
A)
12036 : AAGlobalValueInfo(IRP,
A) {}
12040 bool checkUse(Attributor &
A,
const Use &U,
bool &Follow,
12041 SmallVectorImpl<const Value *> &Worklist) {
12047 if (!GV->hasLocalLinkage() && !
A.isClosedWorldModule())
12053 LLVM_DEBUG(
dbgs() <<
"[AAGlobalValueInfo] Check use: " << *
U.get() <<
" in "
12054 << *UInst <<
"\n");
12057 int Idx = &
Cmp->getOperandUse(0) == &
U;
12060 return U == &getAnchorValue();
12065 auto CallSitePred = [&](AbstractCallSite ACS) {
12066 Worklist.
push_back(ACS.getInstruction());
12069 bool UsedAssumedInformation =
false;
12071 if (!
A.checkForAllCallSites(CallSitePred, *UInst->
getFunction(),
12073 UsedAssumedInformation))
12091 if (!Fn || !
A.isFunctionIPOAmendable(*Fn))
12100 unsigned NumUsesBefore =
Uses.size();
12102 SmallPtrSet<const Value *, 8> Visited;
12106 auto UsePred = [&](
const Use &
U,
bool &Follow) ->
bool {
12114 return checkUse(
A, U, Follow, Worklist);
12116 auto EquivalentUseCB = [&](
const Use &OldU,
const Use &NewU) {
12117 Uses.insert(&OldU);
12121 while (!Worklist.
empty()) {
12123 if (!Visited.
insert(
V).second)
12125 if (!
A.checkForAllUses(UsePred, *
this, *
V,
12127 DepClassTy::OPTIONAL,
12128 true, EquivalentUseCB)) {
12129 return indicatePessimisticFixpoint();
12133 return Uses.size() == NumUsesBefore ? ChangeStatus::UNCHANGED
12134 : ChangeStatus::CHANGED;
12137 bool isPotentialUse(
const Use &U)
const override {
12138 return !isValidState() ||
Uses.contains(&U);
12142 return ChangeStatus::UNCHANGED;
12145 const std::string getAsStr(Attributor *
A)
const override {
12146 return "[" + std::to_string(
Uses.size()) +
" uses]";
12149 void trackStatistics()
const override {
12155 SmallPtrSet<const Use *, 8>
Uses;
12161struct AAIndirectCallInfoCallSite :
public AAIndirectCallInfo {
12162 AAIndirectCallInfoCallSite(
const IRPosition &IRP, Attributor &
A)
12163 : AAIndirectCallInfo(IRP,
A) {}
12166 auto *MD = getCtxI()->getMetadata(LLVMContext::MD_callees);
12167 if (!MD && !
A.isClosedWorldModule())
12171 for (
const auto &
Op : MD->operands())
12173 PotentialCallees.insert(Callee);
12174 }
else if (
A.isClosedWorldModule()) {
12176 A.getInfoCache().getIndirectlyCallableFunctions(
A);
12177 PotentialCallees.insert_range(IndirectlyCallableFunctions);
12180 if (PotentialCallees.empty())
12181 indicateOptimisticFixpoint();
12189 SmallSetVector<Function *, 4> AssumedCalleesNow;
12190 bool AllCalleesKnownNow = AllCalleesKnown;
12192 auto CheckPotentialCalleeUse = [&](
Function &PotentialCallee,
12193 bool &UsedAssumedInformation) {
12194 const auto *GIAA =
A.getAAFor<AAGlobalValueInfo>(
12196 if (!GIAA || GIAA->isPotentialUse(CalleeUse))
12198 UsedAssumedInformation = !GIAA->isAtFixpoint();
12202 auto AddPotentialCallees = [&]() {
12203 for (
auto *PotentialCallee : PotentialCallees) {
12204 bool UsedAssumedInformation =
false;
12205 if (CheckPotentialCalleeUse(*PotentialCallee, UsedAssumedInformation))
12206 AssumedCalleesNow.
insert(PotentialCallee);
12212 bool UsedAssumedInformation =
false;
12215 AA::ValueScope::AnyScope,
12216 UsedAssumedInformation)) {
12217 if (PotentialCallees.empty())
12218 return indicatePessimisticFixpoint();
12219 AddPotentialCallees();
12224 auto CheckPotentialCallee = [&](
Function &Fn) {
12225 if (!PotentialCallees.empty() && !PotentialCallees.count(&Fn))
12228 auto &CachedResult = FilterResults[&Fn];
12229 if (CachedResult.has_value())
12230 return CachedResult.value();
12232 bool UsedAssumedInformation =
false;
12233 if (!CheckPotentialCalleeUse(Fn, UsedAssumedInformation)) {
12234 if (!UsedAssumedInformation)
12235 CachedResult =
false;
12244 for (
int I = NumCBArgs;
I < NumFnArgs; ++
I) {
12245 bool IsKnown =
false;
12248 DepClassTy::OPTIONAL, IsKnown)) {
12250 CachedResult =
false;
12255 CachedResult =
true;
12261 for (
auto &VAC :
Values) {
12269 if (CheckPotentialCallee(*VACFn))
12270 AssumedCalleesNow.
insert(VACFn);
12273 if (!PotentialCallees.empty()) {
12274 AddPotentialCallees();
12277 AllCalleesKnownNow =
false;
12280 if (AssumedCalleesNow == AssumedCallees &&
12281 AllCalleesKnown == AllCalleesKnownNow)
12282 return ChangeStatus::UNCHANGED;
12284 std::swap(AssumedCallees, AssumedCalleesNow);
12285 AllCalleesKnown = AllCalleesKnownNow;
12286 return ChangeStatus::CHANGED;
12291 if (!AllCalleesKnown && AssumedCallees.empty())
12292 return ChangeStatus::UNCHANGED;
12295 bool UsedAssumedInformation =
false;
12296 if (
A.isAssumedDead(*CB,
this,
nullptr,
12297 UsedAssumedInformation))
12298 return ChangeStatus::UNCHANGED;
12303 if (
FP->getType()->getPointerAddressSpace() != ProgramAS)
12304 FP =
new AddrSpaceCastInst(
12305 FP, PointerType::get(
FP->getContext(), ProgramAS),
12306 FP->getName() +
".as" + Twine(ProgramAS), CB->
getIterator());
12315 if (AssumedCallees.empty()) {
12316 assert(AllCalleesKnown &&
12317 "Expected all callees to be known if there are none.");
12318 A.changeToUnreachableAfterManifest(CB);
12319 return ChangeStatus::CHANGED;
12323 if (AllCalleesKnown && AssumedCallees.size() == 1) {
12324 auto *NewCallee = AssumedCallees.front();
12327 NumIndirectCallsPromoted++;
12328 return ChangeStatus::CHANGED;
12335 A.deleteAfterManifest(*CB);
12336 return ChangeStatus::CHANGED;
12346 bool SpecializedForAnyCallees =
false;
12347 bool SpecializedForAllCallees = AllCalleesKnown;
12348 ICmpInst *LastCmp =
nullptr;
12351 for (
Function *NewCallee : AssumedCallees) {
12352 if (!
A.shouldSpecializeCallSiteForCallee(*
this, *CB, *NewCallee,
12353 AssumedCallees.size())) {
12354 SkippedAssumedCallees.
push_back(NewCallee);
12355 SpecializedForAllCallees =
false;
12358 SpecializedForAnyCallees =
true;
12364 A.registerManifestAddedBasicBlock(*ThenTI->
getParent());
12365 A.registerManifestAddedBasicBlock(*IP->getParent());
12371 A.registerManifestAddedBasicBlock(*ElseBB);
12373 SplitTI->replaceUsesOfWith(CBBB, ElseBB);
12378 CastInst *RetBC =
nullptr;
12379 CallInst *NewCall =
nullptr;
12384 NumIndirectCallsPromoted++;
12392 auto AttachCalleeMetadata = [&](CallBase &IndirectCB) {
12393 if (!AllCalleesKnown)
12394 return ChangeStatus::UNCHANGED;
12395 MDBuilder MDB(IndirectCB.getContext());
12396 MDNode *Callees = MDB.createCallees(SkippedAssumedCallees);
12397 IndirectCB.setMetadata(LLVMContext::MD_callees, Callees);
12398 return ChangeStatus::CHANGED;
12401 if (!SpecializedForAnyCallees)
12402 return AttachCalleeMetadata(*CB);
12405 if (SpecializedForAllCallees) {
12408 new UnreachableInst(IP->getContext(), IP);
12409 IP->eraseFromParent();
12412 CBClone->setName(CB->
getName());
12413 CBClone->insertBefore(*IP->getParent(), IP);
12414 NewCalls.
push_back({CBClone,
nullptr});
12415 AttachCalleeMetadata(*CBClone);
12422 CB->
getParent()->getFirstInsertionPt());
12423 for (
auto &It : NewCalls) {
12424 CallBase *NewCall = It.first;
12425 Instruction *CallRet = It.second ? It.second : It.first;
12437 A.deleteAfterManifest(*CB);
12438 Changed = ChangeStatus::CHANGED;
12443 const std::string getAsStr(Attributor *
A)
const override {
12444 return std::string(AllCalleesKnown ?
"eliminate" :
"specialize") +
12445 " indirect call site with " + std::to_string(AssumedCallees.size()) +
12449 void trackStatistics()
const override {
12450 if (AllCalleesKnown) {
12452 Eliminated, CallSites,
12453 "Number of indirect call sites eliminated via specialization")
12456 "Number of indirect call sites specialized")
12460 bool foreachCallee(function_ref<
bool(
Function *)> CB)
const override {
12461 return isValidState() && AllCalleesKnown &&
all_of(AssumedCallees, CB);
12466 DenseMap<Function *, std::optional<bool>> FilterResults;
12470 SmallSetVector<Function *, 4> PotentialCallees;
12474 SmallSetVector<Function *, 4> AssumedCallees;
12478 bool AllCalleesKnown =
true;
12485struct AAInvariantLoadPointerImpl
12486 :
public StateWrapper<BitIntegerState<uint8_t, 15>,
12487 AAInvariantLoadPointer> {
12491 IS_NOALIAS = 1 << 0,
12494 IS_NOEFFECT = 1 << 1,
12496 IS_LOCALLY_INVARIANT = 1 << 2,
12498 IS_LOCALLY_CONSTRAINED = 1 << 3,
12500 IS_BEST_STATE = IS_NOALIAS | IS_NOEFFECT | IS_LOCALLY_INVARIANT |
12501 IS_LOCALLY_CONSTRAINED,
12503 static_assert(getBestState() == IS_BEST_STATE,
"Unexpected best state");
12506 StateWrapper<BitIntegerState<uint8_t, 15>, AAInvariantLoadPointer>;
12510 AAInvariantLoadPointerImpl(
const IRPosition &IRP, Attributor &
A)
12513 bool isKnownInvariant()
const final {
12514 return isKnownLocallyInvariant() && isKnown(IS_LOCALLY_CONSTRAINED);
12517 bool isKnownLocallyInvariant()
const final {
12518 if (isKnown(IS_LOCALLY_INVARIANT))
12520 return isKnown(IS_NOALIAS | IS_NOEFFECT);
12523 bool isAssumedInvariant()
const final {
12524 return isAssumedLocallyInvariant() && isAssumed(IS_LOCALLY_CONSTRAINED);
12527 bool isAssumedLocallyInvariant()
const final {
12528 if (isAssumed(IS_LOCALLY_INVARIANT))
12530 return isAssumed(IS_NOALIAS | IS_NOEFFECT);
12537 if (requiresNoAlias() && !isAssumed(IS_NOALIAS))
12538 return indicatePessimisticFixpoint();
12542 Changed |= updateLocalInvariance(
A);
12548 if (!isKnownInvariant())
12549 return ChangeStatus::UNCHANGED;
12552 const Value *Ptr = &getAssociatedValue();
12553 const auto TagInvariantLoads = [&](
const Use &
U,
bool &) {
12554 if (
U.get() != Ptr)
12562 if (!
A.isRunOn(
I->getFunction()))
12565 if (
I->hasMetadata(LLVMContext::MD_invariant_load))
12569 LI->setMetadata(LLVMContext::MD_invariant_load,
12571 Changed = ChangeStatus::CHANGED;
12576 (void)
A.checkForAllUses(TagInvariantLoads, *
this, *Ptr);
12580 const std::string getAsStr(Attributor *)
const override {
12581 if (isKnownInvariant())
12582 return "load-invariant pointer";
12583 return "non-invariant pointer";
12586 void trackStatistics()
const override {}
12590 bool requiresNoAlias()
const {
12591 switch (getPositionKind()) {
12597 case IRP_CALL_SITE:
12599 case IRP_CALL_SITE_RETURNED: {
12604 case IRP_ARGUMENT: {
12605 const Function *
F = getAssociatedFunction();
12606 assert(
F &&
"no associated function for argument");
12612 bool isExternal()
const {
12613 const Function *
F = getAssociatedFunction();
12617 getPositionKind() != IRP_CALL_SITE_RETURNED;
12621 if (isKnown(IS_NOALIAS) || !isAssumed(IS_NOALIAS))
12622 return ChangeStatus::UNCHANGED;
12625 if (
const auto *ANoAlias =
A.getOrCreateAAFor<AANoAlias>(
12626 getIRPosition(),
this, DepClassTy::REQUIRED)) {
12627 if (ANoAlias->isKnownNoAlias()) {
12628 addKnownBits(IS_NOALIAS);
12629 return ChangeStatus::CHANGED;
12632 if (!ANoAlias->isAssumedNoAlias()) {
12633 removeAssumedBits(IS_NOALIAS);
12634 return ChangeStatus::CHANGED;
12637 return ChangeStatus::UNCHANGED;
12642 if (
const Argument *Arg = getAssociatedArgument()) {
12644 addKnownBits(IS_NOALIAS);
12645 return ChangeStatus::UNCHANGED;
12650 removeAssumedBits(IS_NOALIAS);
12651 return ChangeStatus::CHANGED;
12654 return ChangeStatus::UNCHANGED;
12658 if (isKnown(IS_NOEFFECT) || !isAssumed(IS_NOEFFECT))
12659 return ChangeStatus::UNCHANGED;
12661 if (!getAssociatedFunction())
12662 return indicatePessimisticFixpoint();
12665 return indicatePessimisticFixpoint();
12667 const auto HasNoEffectLoads = [&](
const Use &
U,
bool &) {
12669 return !LI || !LI->mayHaveSideEffects();
12671 if (!
A.checkForAllUses(HasNoEffectLoads, *
this, getAssociatedValue()))
12672 return indicatePessimisticFixpoint();
12674 if (
const auto *AMemoryBehavior =
A.getOrCreateAAFor<AAMemoryBehavior>(
12675 getIRPosition(),
this, DepClassTy::REQUIRED)) {
12678 if (!AMemoryBehavior->isAssumedReadOnly())
12679 return indicatePessimisticFixpoint();
12681 if (AMemoryBehavior->isKnownReadOnly()) {
12682 addKnownBits(IS_NOEFFECT);
12683 return ChangeStatus::UNCHANGED;
12686 return ChangeStatus::UNCHANGED;
12689 if (
const Argument *Arg = getAssociatedArgument()) {
12691 addKnownBits(IS_NOEFFECT);
12692 return ChangeStatus::UNCHANGED;
12697 return indicatePessimisticFixpoint();
12700 return ChangeStatus::UNCHANGED;
12704 if (isKnown(IS_LOCALLY_INVARIANT) || !isAssumed(IS_LOCALLY_INVARIANT))
12705 return ChangeStatus::UNCHANGED;
12708 const auto *AUO =
A.getOrCreateAAFor<AAUnderlyingObjects>(
12709 getIRPosition(),
this, DepClassTy::REQUIRED);
12711 return ChangeStatus::UNCHANGED;
12713 bool UsedAssumedInformation =
false;
12714 const auto IsLocallyInvariantLoadIfPointer = [&](
const Value &
V) {
12715 if (!
V.getType()->isPointerTy())
12717 const auto *IsInvariantLoadPointer =
12719 DepClassTy::REQUIRED);
12721 if (!IsInvariantLoadPointer)
12724 if (IsInvariantLoadPointer->isKnownLocallyInvariant())
12726 if (!IsInvariantLoadPointer->isAssumedLocallyInvariant())
12729 UsedAssumedInformation =
true;
12732 if (!AUO->forallUnderlyingObjects(IsLocallyInvariantLoadIfPointer))
12733 return indicatePessimisticFixpoint();
12739 if (!IsLocallyInvariantLoadIfPointer(*Arg))
12740 return indicatePessimisticFixpoint();
12745 if (!UsedAssumedInformation) {
12747 addKnownBits(IS_LOCALLY_INVARIANT);
12748 return ChangeStatus::CHANGED;
12751 return ChangeStatus::UNCHANGED;
12755struct AAInvariantLoadPointerFloating final : AAInvariantLoadPointerImpl {
12756 AAInvariantLoadPointerFloating(
const IRPosition &IRP, Attributor &
A)
12757 : AAInvariantLoadPointerImpl(IRP,
A) {}
12760struct AAInvariantLoadPointerReturned final : AAInvariantLoadPointerImpl {
12761 AAInvariantLoadPointerReturned(
const IRPosition &IRP, Attributor &
A)
12762 : AAInvariantLoadPointerImpl(IRP,
A) {}
12765 removeAssumedBits(IS_LOCALLY_CONSTRAINED);
12769struct AAInvariantLoadPointerCallSiteReturned final
12770 : AAInvariantLoadPointerImpl {
12771 AAInvariantLoadPointerCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
12772 : AAInvariantLoadPointerImpl(IRP,
A) {}
12776 const Function *
F = getAssociatedFunction();
12778 indicatePessimisticFixpoint();
12782 if (!
F->isDeclaration() && !
F->isIntrinsic())
12783 return AAInvariantLoadPointerImpl::initialize(
A);
12788 return AAInvariantLoadPointerImpl::initialize(
A);
12790 if (
F->onlyReadsMemory() &&
F->hasNoSync())
12791 return AAInvariantLoadPointerImpl::initialize(
A);
12795 indicatePessimisticFixpoint();
12799struct AAInvariantLoadPointerArgument final : AAInvariantLoadPointerImpl {
12800 AAInvariantLoadPointerArgument(
const IRPosition &IRP, Attributor &
A)
12801 : AAInvariantLoadPointerImpl(IRP,
A) {}
12804 const Function *
F = getAssociatedFunction();
12805 assert(
F &&
"no associated function for argument");
12808 addKnownBits(IS_LOCALLY_CONSTRAINED);
12812 if (!
F->hasLocalLinkage())
12813 removeAssumedBits(IS_LOCALLY_CONSTRAINED);
12817struct AAInvariantLoadPointerCallSiteArgument final
12818 : AAInvariantLoadPointerImpl {
12819 AAInvariantLoadPointerCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
12820 : AAInvariantLoadPointerImpl(IRP,
A) {}
12827template <
typename InstType>
12828static bool makeChange(Attributor &
A, InstType *MemInst,
const Use &U,
12829 Value *OriginalValue, PointerType *NewPtrTy,
12830 bool UseOriginalValue) {
12831 if (
U.getOperandNo() != InstType::getPointerOperandIndex())
12834 if (MemInst->isVolatile()) {
12835 auto *
TTI =
A.getInfoCache().getAnalysisResultForFunction<TargetIRAnalysis>(
12836 *MemInst->getFunction());
12837 unsigned NewAS = NewPtrTy->getPointerAddressSpace();
12842 if (UseOriginalValue) {
12843 A.changeUseAfterManifest(
const_cast<Use &
>(U), *OriginalValue);
12847 Instruction *CastInst =
new AddrSpaceCastInst(OriginalValue, NewPtrTy);
12849 A.changeUseAfterManifest(
const_cast<Use &
>(U), *CastInst);
12853struct AAAddressSpaceImpl :
public AAAddressSpace {
12854 AAAddressSpaceImpl(
const IRPosition &IRP, Attributor &
A)
12855 : AAAddressSpace(IRP,
A) {}
12858 assert(isValidState() &&
"the AA is invalid");
12859 return AssumedAddressSpace;
12863 assert(getAssociatedType()->isPtrOrPtrVectorTy() &&
12864 "Associated value is not a pointer");
12866 if (!
A.getInfoCache().getFlatAddressSpace().has_value()) {
12867 indicatePessimisticFixpoint();
12871 unsigned FlatAS =
A.getInfoCache().getFlatAddressSpace().value();
12872 unsigned AS = getAssociatedType()->getPointerAddressSpace();
12873 if (AS != FlatAS) {
12874 [[maybe_unused]]
bool R = takeAddressSpace(AS);
12875 assert(R &&
"The take should happen");
12876 indicateOptimisticFixpoint();
12881 uint32_t OldAddressSpace = AssumedAddressSpace;
12882 unsigned FlatAS =
A.getInfoCache().getFlatAddressSpace().value();
12884 auto CheckAddressSpace = [&](
Value &
Obj) {
12890 unsigned ObjAS =
Obj.getType()->getPointerAddressSpace();
12891 if (ObjAS != FlatAS)
12892 return takeAddressSpace(ObjAS);
12906 A.getInfoCache().getAnalysisResultForFunction<TargetIRAnalysis>(*F);
12908 if (AssumedAS != ~0U)
12909 return takeAddressSpace(AssumedAS);
12913 return takeAddressSpace(FlatAS);
12916 auto *AUO =
A.getOrCreateAAFor<AAUnderlyingObjects>(getIRPosition(),
this,
12917 DepClassTy::REQUIRED);
12918 if (!AUO->forallUnderlyingObjects(CheckAddressSpace))
12919 return indicatePessimisticFixpoint();
12921 return OldAddressSpace == AssumedAddressSpace ? ChangeStatus::UNCHANGED
12922 : ChangeStatus::CHANGED;
12928 if (NewAS == InvalidAddressSpace ||
12930 return ChangeStatus::UNCHANGED;
12932 unsigned FlatAS =
A.getInfoCache().getFlatAddressSpace().value();
12934 Value *AssociatedValue = &getAssociatedValue();
12935 Value *OriginalValue = peelAddrspacecast(AssociatedValue, FlatAS);
12938 PointerType::get(getAssociatedType()->
getContext(), NewAS);
12939 bool UseOriginalValue =
12944 auto Pred = [&](
const Use &
U,
bool &) {
12945 if (
U.get() != AssociatedValue)
12956 makeChange(
A, LI, U, OriginalValue, NewPtrTy, UseOriginalValue);
12959 makeChange(
A, SI, U, OriginalValue, NewPtrTy, UseOriginalValue);
12962 makeChange(
A, RMW, U, OriginalValue, NewPtrTy, UseOriginalValue);
12965 makeChange(
A, CmpX, U, OriginalValue, NewPtrTy, UseOriginalValue);
12972 (void)
A.checkForAllUses(
Pred, *
this, getAssociatedValue(),
12975 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
12978 const std::string getAsStr(Attributor *
A)
const override {
12979 if (!isValidState())
12980 return "addrspace(<invalid>)";
12981 return "addrspace(" +
12982 (AssumedAddressSpace == InvalidAddressSpace
12984 : std::to_string(AssumedAddressSpace)) +
12989 uint32_t AssumedAddressSpace = InvalidAddressSpace;
12991 bool takeAddressSpace(uint32_t AS) {
12992 if (AssumedAddressSpace == InvalidAddressSpace) {
12993 AssumedAddressSpace = AS;
12996 return AssumedAddressSpace == AS;
12999 static Value *peelAddrspacecast(
Value *
V,
unsigned FlatAS) {
13001 assert(
I->getSrcAddressSpace() != FlatAS &&
13002 "there should not be flat AS -> non-flat AS");
13003 return I->getPointerOperand();
13006 if (
C->getOpcode() == Instruction::AddrSpaceCast) {
13007 assert(
C->getOperand(0)->getType()->getPointerAddressSpace() !=
13009 "there should not be flat AS -> non-flat AS X");
13010 return C->getOperand(0);
13016struct AAAddressSpaceFloating final : AAAddressSpaceImpl {
13017 AAAddressSpaceFloating(
const IRPosition &IRP, Attributor &
A)
13018 : AAAddressSpaceImpl(IRP,
A) {}
13020 void trackStatistics()
const override {
13025struct AAAddressSpaceReturned final : AAAddressSpaceImpl {
13026 AAAddressSpaceReturned(
const IRPosition &IRP, Attributor &
A)
13027 : AAAddressSpaceImpl(IRP,
A) {}
13032 (void)indicatePessimisticFixpoint();
13035 void trackStatistics()
const override {
13040struct AAAddressSpaceCallSiteReturned final : AAAddressSpaceImpl {
13041 AAAddressSpaceCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
13042 : AAAddressSpaceImpl(IRP,
A) {}
13044 void trackStatistics()
const override {
13049struct AAAddressSpaceArgument final : AAAddressSpaceImpl {
13050 AAAddressSpaceArgument(
const IRPosition &IRP, Attributor &
A)
13051 : AAAddressSpaceImpl(IRP,
A) {}
13056struct AAAddressSpaceCallSiteArgument final : AAAddressSpaceImpl {
13057 AAAddressSpaceCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
13058 : AAAddressSpaceImpl(IRP,
A) {}
13063 (void)indicatePessimisticFixpoint();
13066 void trackStatistics()
const override {
13081struct AANoAliasAddrSpaceImpl :
public AANoAliasAddrSpace {
13082 AANoAliasAddrSpaceImpl(
const IRPosition &IRP, Attributor &
A)
13083 : AANoAliasAddrSpace(IRP,
A) {}
13086 assert(getAssociatedType()->isPtrOrPtrVectorTy() &&
13087 "Associated value is not a pointer");
13091 std::optional<unsigned> FlatAS =
A.getInfoCache().getFlatAddressSpace();
13092 if (!FlatAS.has_value()) {
13093 indicatePessimisticFixpoint();
13099 unsigned AS = getAssociatedType()->getPointerAddressSpace();
13100 if (AS != *FlatAS) {
13102 indicateOptimisticFixpoint();
13107 unsigned FlatAS =
A.getInfoCache().getFlatAddressSpace().value();
13108 uint32_t OldAssumed = getAssumed();
13110 auto CheckAddressSpace = [&](
Value &
Obj) {
13114 unsigned AS =
Obj.getType()->getPointerAddressSpace();
13118 removeAS(
Obj.getType()->getPointerAddressSpace());
13122 const AAUnderlyingObjects *AUO =
A.getOrCreateAAFor<AAUnderlyingObjects>(
13123 getIRPosition(),
this, DepClassTy::REQUIRED);
13125 return indicatePessimisticFixpoint();
13127 return OldAssumed == getAssumed() ? ChangeStatus::UNCHANGED
13128 : ChangeStatus::CHANGED;
13132 unsigned FlatAS =
A.getInfoCache().getFlatAddressSpace().value();
13134 unsigned AS = getAssociatedType()->getPointerAddressSpace();
13135 if (AS != FlatAS ||
Map.empty())
13136 return ChangeStatus::UNCHANGED;
13138 LLVMContext &Ctx = getAssociatedValue().getContext();
13139 MDNode *NoAliasASNode =
nullptr;
13140 MDBuilder MDB(Ctx);
13142 for (RangeMap::const_iterator
I =
Map.begin();
I !=
Map.end();
I++) {
13145 unsigned Upper =
I.stop();
13146 unsigned Lower =
I.start();
13147 if (!NoAliasASNode) {
13148 NoAliasASNode = MDB.createRange(APInt(32,
Lower), APInt(32,
Upper + 1));
13151 MDNode *ASRange = MDB.createRange(APInt(32,
Lower), APInt(32,
Upper + 1));
13155 Value *AssociatedValue = &getAssociatedValue();
13158 auto AddNoAliasAttr = [&](
const Use &
U,
bool &) {
13159 if (
U.get() != AssociatedValue)
13162 if (!Inst || Inst->
hasMetadata(LLVMContext::MD_noalias_addrspace))
13169 Inst->
setMetadata(LLVMContext::MD_noalias_addrspace, NoAliasASNode);
13173 (void)
A.checkForAllUses(AddNoAliasAttr, *
this, *AssociatedValue,
13175 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
13178 const std::string getAsStr(Attributor *
A)
const override {
13179 if (!isValidState())
13180 return "<invalid>";
13182 raw_string_ostream OS(Str);
13183 OS <<
"CanNotBeAddrSpace(";
13184 for (RangeMap::const_iterator
I =
Map.begin();
I !=
Map.end();
I++) {
13185 unsigned Upper =
I.stop();
13186 unsigned Lower =
I.start();
13187 OS <<
' ' <<
'[' <<
Upper <<
',' <<
Lower + 1 <<
')';
13194 void removeAS(
unsigned AS) {
13195 RangeMap::iterator
I =
Map.find(AS);
13197 if (
I !=
Map.end()) {
13198 unsigned Upper =
I.stop();
13199 unsigned Lower =
I.start();
13203 if (AS != ~((
unsigned)0) && AS + 1 <=
Upper)
13205 if (AS != 0 &&
Lower <= AS - 1)
13210 void resetASRanges(Attributor &
A) {
13212 Map.insert(0,
A.getInfoCache().getMaxAddrSpace(),
true);
13216struct AANoAliasAddrSpaceFloating final : AANoAliasAddrSpaceImpl {
13217 AANoAliasAddrSpaceFloating(
const IRPosition &IRP, Attributor &
A)
13218 : AANoAliasAddrSpaceImpl(IRP,
A) {}
13220 void trackStatistics()
const override {
13225struct AANoAliasAddrSpaceReturned final : AANoAliasAddrSpaceImpl {
13226 AANoAliasAddrSpaceReturned(
const IRPosition &IRP, Attributor &
A)
13227 : AANoAliasAddrSpaceImpl(IRP,
A) {}
13229 void trackStatistics()
const override {
13234struct AANoAliasAddrSpaceCallSiteReturned final : AANoAliasAddrSpaceImpl {
13235 AANoAliasAddrSpaceCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
13236 : AANoAliasAddrSpaceImpl(IRP,
A) {}
13238 void trackStatistics()
const override {
13243struct AANoAliasAddrSpaceArgument final : AANoAliasAddrSpaceImpl {
13244 AANoAliasAddrSpaceArgument(
const IRPosition &IRP, Attributor &
A)
13245 : AANoAliasAddrSpaceImpl(IRP,
A) {}
13247 void trackStatistics()
const override {
13252struct AANoAliasAddrSpaceCallSiteArgument final : AANoAliasAddrSpaceImpl {
13253 AANoAliasAddrSpaceCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
13254 : AANoAliasAddrSpaceImpl(IRP,
A) {}
13256 void trackStatistics()
const override {
13263struct AAAllocationInfoImpl :
public AAAllocationInfo {
13264 AAAllocationInfoImpl(
const IRPosition &IRP, Attributor &
A)
13265 : AAAllocationInfo(IRP,
A) {}
13267 std::optional<TypeSize> getAllocatedSize()
const override {
13268 assert(isValidState() &&
"the AA is invalid");
13269 return AssumedAllocatedSize;
13272 std::optional<TypeSize> findInitialAllocationSize(Instruction *
I,
13273 const DataLayout &
DL) {
13276 switch (
I->getOpcode()) {
13277 case Instruction::Alloca: {
13282 return std::nullopt;
13288 const IRPosition &IRP = getIRPosition();
13293 return indicatePessimisticFixpoint();
13295 bool IsKnownNoCapture;
13297 A,
this, IRP, DepClassTy::OPTIONAL, IsKnownNoCapture))
13298 return indicatePessimisticFixpoint();
13300 const AAPointerInfo *PI =
13301 A.getOrCreateAAFor<AAPointerInfo>(IRP, *
this, DepClassTy::REQUIRED);
13304 return indicatePessimisticFixpoint();
13307 return indicatePessimisticFixpoint();
13309 const DataLayout &
DL =
A.getDataLayout();
13310 const auto AllocationSize = findInitialAllocationSize(
I,
DL);
13313 if (!AllocationSize)
13314 return indicatePessimisticFixpoint();
13318 if (*AllocationSize == 0)
13319 return indicatePessimisticFixpoint();
13325 return indicatePessimisticFixpoint();
13327 if (BinSize == 0) {
13328 auto NewAllocationSize = std::make_optional<TypeSize>(0,
false);
13329 if (!changeAllocationSize(NewAllocationSize))
13330 return ChangeStatus::UNCHANGED;
13331 return ChangeStatus::CHANGED;
13335 const auto &It = PI->
begin();
13338 if (It->first.Offset != 0)
13339 return indicatePessimisticFixpoint();
13341 uint64_t SizeOfBin = It->first.Offset + It->first.Size;
13343 if (SizeOfBin >= *AllocationSize)
13344 return indicatePessimisticFixpoint();
13346 auto NewAllocationSize = std::make_optional<TypeSize>(SizeOfBin * 8,
false);
13348 if (!changeAllocationSize(NewAllocationSize))
13349 return ChangeStatus::UNCHANGED;
13351 return ChangeStatus::CHANGED;
13356 assert(isValidState() &&
13357 "Manifest should only be called if the state is valid.");
13361 auto FixedAllocatedSizeInBits = getAllocatedSize()->getFixedValue();
13363 unsigned long NumBytesToAllocate = (FixedAllocatedSizeInBits + 7) / 8;
13365 switch (
I->getOpcode()) {
13367 case Instruction::Alloca: {
13371 Type *CharType = Type::getInt8Ty(
I->getContext());
13373 auto *NumBytesToValue =
13374 ConstantInt::get(
I->getContext(), APInt(32, NumBytesToAllocate));
13377 insertPt = std::next(insertPt);
13378 AllocaInst *NewAllocaInst =
13383 return ChangeStatus::CHANGED;
13391 return ChangeStatus::UNCHANGED;
13394 const std::string getAsStr(Attributor *
A)
const override {
13395 if (!isValidState())
13396 return "allocationinfo(<invalid>)";
13397 return "allocationinfo(" +
13398 (AssumedAllocatedSize == HasNoAllocationSize
13400 : std::to_string(AssumedAllocatedSize->getFixedValue())) +
13405 std::optional<TypeSize> AssumedAllocatedSize = HasNoAllocationSize;
13409 bool changeAllocationSize(std::optional<TypeSize>
Size) {
13410 if (AssumedAllocatedSize == HasNoAllocationSize ||
13411 AssumedAllocatedSize !=
Size) {
13412 AssumedAllocatedSize =
Size;
13419struct AAAllocationInfoFloating : AAAllocationInfoImpl {
13420 AAAllocationInfoFloating(
const IRPosition &IRP, Attributor &
A)
13421 : AAAllocationInfoImpl(IRP,
A) {}
13423 void trackStatistics()
const override {
13428struct AAAllocationInfoReturned : AAAllocationInfoImpl {
13429 AAAllocationInfoReturned(
const IRPosition &IRP, Attributor &
A)
13430 : AAAllocationInfoImpl(IRP,
A) {}
13435 (void)indicatePessimisticFixpoint();
13438 void trackStatistics()
const override {
13443struct AAAllocationInfoCallSiteReturned : AAAllocationInfoImpl {
13444 AAAllocationInfoCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
13445 : AAAllocationInfoImpl(IRP,
A) {}
13447 void trackStatistics()
const override {
13452struct AAAllocationInfoArgument : AAAllocationInfoImpl {
13453 AAAllocationInfoArgument(
const IRPosition &IRP, Attributor &
A)
13454 : AAAllocationInfoImpl(IRP,
A) {}
13456 void trackStatistics()
const override {
13461struct AAAllocationInfoCallSiteArgument : AAAllocationInfoImpl {
13462 AAAllocationInfoCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
13463 : AAAllocationInfoImpl(IRP,
A) {}
13467 (void)indicatePessimisticFixpoint();
13470 void trackStatistics()
const override {
13519#define SWITCH_PK_INV(CLASS, PK, POS_NAME) \
13520 case IRPosition::PK: \
13521 llvm_unreachable("Cannot create " #CLASS " for a " POS_NAME " position!");
13523#define SWITCH_PK_CREATE(CLASS, IRP, PK, SUFFIX) \
13524 case IRPosition::PK: \
13525 AA = new (A.Allocator) CLASS##SUFFIX(IRP, A); \
13529#define CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13530 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13531 CLASS *AA = nullptr; \
13532 switch (IRP.getPositionKind()) { \
13533 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13534 SWITCH_PK_INV(CLASS, IRP_FLOAT, "floating") \
13535 SWITCH_PK_INV(CLASS, IRP_ARGUMENT, "argument") \
13536 SWITCH_PK_INV(CLASS, IRP_RETURNED, "returned") \
13537 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_RETURNED, "call site returned") \
13538 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_ARGUMENT, "call site argument") \
13539 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
13540 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE, CallSite) \
13545#define CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13546 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13547 CLASS *AA = nullptr; \
13548 switch (IRP.getPositionKind()) { \
13549 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13550 SWITCH_PK_INV(CLASS, IRP_FUNCTION, "function") \
13551 SWITCH_PK_INV(CLASS, IRP_CALL_SITE, "call site") \
13552 SWITCH_PK_CREATE(CLASS, IRP, IRP_FLOAT, Floating) \
13553 SWITCH_PK_CREATE(CLASS, IRP, IRP_ARGUMENT, Argument) \
13554 SWITCH_PK_CREATE(CLASS, IRP, IRP_RETURNED, Returned) \
13555 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_RETURNED, CallSiteReturned) \
13556 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_ARGUMENT, CallSiteArgument) \
13561#define CREATE_ABSTRACT_ATTRIBUTE_FOR_ONE_POSITION(POS, SUFFIX, CLASS) \
13562 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13563 CLASS *AA = nullptr; \
13564 switch (IRP.getPositionKind()) { \
13565 SWITCH_PK_CREATE(CLASS, IRP, POS, SUFFIX) \
13567 llvm_unreachable("Cannot create " #CLASS " for position otherthan " #POS \
13573#define CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13574 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13575 CLASS *AA = nullptr; \
13576 switch (IRP.getPositionKind()) { \
13577 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
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_RETURNED, Returned) \
13583 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_RETURNED, CallSiteReturned) \
13584 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_ARGUMENT, CallSiteArgument) \
13589#define CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13590 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13591 CLASS *AA = nullptr; \
13592 switch (IRP.getPositionKind()) { \
13593 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13594 SWITCH_PK_INV(CLASS, IRP_ARGUMENT, "argument") \
13595 SWITCH_PK_INV(CLASS, IRP_FLOAT, "floating") \
13596 SWITCH_PK_INV(CLASS, IRP_RETURNED, "returned") \
13597 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_RETURNED, "call site returned") \
13598 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_ARGUMENT, "call site argument") \
13599 SWITCH_PK_INV(CLASS, IRP_CALL_SITE, "call site") \
13600 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
13605#define CREATE_NON_RET_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13606 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13607 CLASS *AA = nullptr; \
13608 switch (IRP.getPositionKind()) { \
13609 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13610 SWITCH_PK_INV(CLASS, IRP_RETURNED, "returned") \
13611 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
13612 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE, CallSite) \
13613 SWITCH_PK_CREATE(CLASS, IRP, IRP_FLOAT, Floating) \
13614 SWITCH_PK_CREATE(CLASS, IRP, IRP_ARGUMENT, Argument) \
13615 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_RETURNED, CallSiteReturned) \
13616 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_ARGUMENT, CallSiteArgument) \
13668#undef CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION
13669#undef CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION
13670#undef CREATE_NON_RET_ABSTRACT_ATTRIBUTE_FOR_POSITION
13671#undef CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION
13672#undef CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION
13673#undef CREATE_ABSTRACT_ATTRIBUTE_FOR_ONE_POSITION
13674#undef SWITCH_PK_CREATE
13675#undef SWITCH_PK_INV
const TargetLowering & TLI
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
Expand Atomic instructions
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 bool collectTailCalls(Attributor &A, const AbstractAttribute &QueryingAA, SmallVectorImpl< CallInst * > &TailCalls)
Collect the non-musttail tail calls in the function of QueryingAA.
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)
bpf unwind BPF Unwind Lower
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 * CreatePtrAddWithSignedOffset(Value *Ptr, int64_t Offset, const Twine &Name="", GEPNoWrapFlags NW=GEPNoWrapFlags::none())
Create a ptradd with a signed constant offset.
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.
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.
LLVM_ABI bool mayReadOrWriteMemory() const LLVM_READONLY
Return true if this instruction may read or write memory.
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.