55#include "llvm/IR/IntrinsicsAMDGPU.h"
56#include "llvm/IR/IntrinsicsNVPTX.h"
83#define DEBUG_TYPE "attributor"
87 cl::desc(
"Manifest Attributor internal string attributes."),
100 cl::desc(
"Maximum number of potential values to be "
101 "tracked for each position."),
106 "attributor-max-potential-values-iterations",
cl::Hidden,
108 "Maximum number of iterations we keep dismantling potential values."),
111STATISTIC(NumAAs,
"Number of abstract attributes created");
112STATISTIC(NumIndirectCallsPromoted,
"Number of indirect calls promoted");
127#define BUILD_STAT_MSG_IR_ATTR(TYPE, NAME) \
128 ("Number of " #TYPE " marked '" #NAME "'")
129#define BUILD_STAT_NAME(NAME, TYPE) NumIR##TYPE##_##NAME
130#define STATS_DECL_(NAME, MSG) STATISTIC(NAME, MSG);
131#define STATS_DECL(NAME, TYPE, MSG) \
132 STATS_DECL_(BUILD_STAT_NAME(NAME, TYPE), MSG);
133#define STATS_TRACK(NAME, TYPE) ++(BUILD_STAT_NAME(NAME, TYPE));
134#define STATS_DECLTRACK(NAME, TYPE, MSG) \
135 {STATS_DECL(NAME, TYPE, MSG) STATS_TRACK(NAME, TYPE)}
136#define STATS_DECLTRACK_ARG_ATTR(NAME) \
137 STATS_DECLTRACK(NAME, Arguments, BUILD_STAT_MSG_IR_ATTR(arguments, NAME))
138#define STATS_DECLTRACK_CSARG_ATTR(NAME) \
139 STATS_DECLTRACK(NAME, CSArguments, \
140 BUILD_STAT_MSG_IR_ATTR(call site arguments, NAME))
141#define STATS_DECLTRACK_FN_ATTR(NAME) \
142 STATS_DECLTRACK(NAME, Function, BUILD_STAT_MSG_IR_ATTR(functions, NAME))
143#define STATS_DECLTRACK_CS_ATTR(NAME) \
144 STATS_DECLTRACK(NAME, CS, BUILD_STAT_MSG_IR_ATTR(call site, NAME))
145#define STATS_DECLTRACK_FNRET_ATTR(NAME) \
146 STATS_DECLTRACK(NAME, FunctionReturn, \
147 BUILD_STAT_MSG_IR_ATTR(function returns, NAME))
148#define STATS_DECLTRACK_CSRET_ATTR(NAME) \
149 STATS_DECLTRACK(NAME, CSReturn, \
150 BUILD_STAT_MSG_IR_ATTR(call site returns, NAME))
151#define STATS_DECLTRACK_FLOATING_ATTR(NAME) \
152 STATS_DECLTRACK(NAME, Floating, \
153 ("Number of floating values known to be '" #NAME "'"))
158#define PIPE_OPERATOR(CLASS) \
159 raw_ostream &operator<<(raw_ostream &OS, const CLASS &AA) { \
160 return OS << static_cast<const AbstractAttribute &>(AA); \
217 bool HeaderOnly,
CycleRef *CPtr =
nullptr) {
220 auto *BB =
I->getParent();
237 if (
DL.getTypeSizeInBits(Ty) !=
DL.getTypeAllocSizeInBits(Ty))
262 StartPos +=
DL.getTypeAllocSizeInBits(ElTy);
273 bool AllowVolatile) {
274 if (!AllowVolatile &&
I->isVolatile())
278 return LI->getPointerOperand();
282 return SI->getPointerOperand();
286 return CXI->getPointerOperand();
290 return RMWI->getPointerOperand();
312 bool GetMinOffset,
bool AllowNonInbounds,
313 bool UseAssumed =
false) {
315 auto AttributorAnalysis = [&](
Value &V,
APInt &ROffset) ->
bool {
322 if (!ValueConstantRangeAA)
326 if (
Range.isFullSet())
332 ROffset =
Range.getSignedMin();
334 ROffset =
Range.getSignedMax();
345 const Value *Ptr, int64_t &BytesOffset,
350 true, AllowNonInbounds);
358template <
typename AAType,
typename StateType =
typename AAType::StateType,
360 bool RecurseForSelectAndPHI =
true>
362 Attributor &
A,
const AAType &QueryingAA, StateType &S,
364 LLVM_DEBUG(
dbgs() <<
"[Attributor] Clamp return value states for "
365 << QueryingAA <<
" into " << S <<
"\n");
367 assert((QueryingAA.getIRPosition().getPositionKind() ==
369 QueryingAA.getIRPosition().getPositionKind() ==
371 "Can only clamp returned value states for a function returned or call "
372 "site returned position!");
376 std::optional<StateType>
T;
379 auto CheckReturnValue = [&](
Value &RV) ->
bool {
393 <<
" AA: " <<
AA->getAsStr(&
A) <<
" @ " << RVPos <<
"\n");
394 const StateType &AAS =
AA->getState();
396 T = StateType::getBestState(AAS);
398 LLVM_DEBUG(
dbgs() <<
"[Attributor] AA State: " << AAS <<
" RV State: " <<
T
400 return T->isValidState();
403 if (!
A.checkForAllReturnedValues(CheckReturnValue, QueryingAA,
405 RecurseForSelectAndPHI))
406 S.indicatePessimisticFixpoint();
413template <
typename AAType,
typename BaseType,
414 typename StateType =
typename BaseType::StateType,
415 bool PropagateCallBaseContext =
false,
417 bool RecurseForSelectAndPHI =
true>
418struct AAReturnedFromReturnedValues :
public BaseType {
419 AAReturnedFromReturnedValues(
const IRPosition &IRP, Attributor &
A)
424 StateType S(StateType::getBestState(this->getState()));
426 RecurseForSelectAndPHI>(
428 PropagateCallBaseContext ? this->getCallBaseContext() : nullptr);
437template <
typename AAType,
typename StateType =
typename AAType::StateType,
439static void clampCallSiteArgumentStates(
Attributor &
A,
const AAType &QueryingAA,
441 LLVM_DEBUG(
dbgs() <<
"[Attributor] Clamp call site argument states for "
442 << QueryingAA <<
" into " << S <<
"\n");
444 assert(QueryingAA.getIRPosition().getPositionKind() ==
446 "Can only clamp call site argument states for an argument position!");
450 std::optional<StateType>
T;
453 unsigned ArgNo = QueryingAA.getIRPosition().getCallSiteArgNo();
473 LLVM_DEBUG(
dbgs() <<
"[Attributor] ACS: " << *ACS.getInstruction()
474 <<
" AA: " <<
AA->getAsStr(&
A) <<
" @" << ACSArgPos
476 const StateType &AAS =
AA->getState();
478 T = StateType::getBestState(AAS);
480 LLVM_DEBUG(
dbgs() <<
"[Attributor] AA State: " << AAS <<
" CSA State: " <<
T
482 return T->isValidState();
485 bool UsedAssumedInformation =
false;
486 if (!
A.checkForAllCallSites(CallSiteCheck, QueryingAA,
true,
487 UsedAssumedInformation))
488 S.indicatePessimisticFixpoint();
495template <
typename AAType,
typename BaseType,
496 typename StateType =
typename AAType::StateType,
498bool getArgumentStateFromCallBaseContext(
Attributor &
A,
502 "Expected an 'argument' position !");
508 assert(ArgNo >= 0 &&
"Invalid Arg No!");
522 const StateType &CBArgumentState =
523 static_cast<const StateType &
>(
AA->getState());
525 LLVM_DEBUG(
dbgs() <<
"[Attributor] Briding Call site context to argument"
526 <<
"Position:" << Pos <<
"CB Arg state:" << CBArgumentState
530 State ^= CBArgumentState;
535template <
typename AAType,
typename BaseType,
536 typename StateType =
typename AAType::StateType,
537 bool BridgeCallBaseContext =
false,
539struct AAArgumentFromCallSiteArguments :
public BaseType {
540 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) {}
574 auto IRPKind = this->getIRPosition().getPositionKind();
577 "Can only wrap function returned positions for call site "
578 "returned positions!");
579 auto &S = this->getState();
582 if (IntroduceCallBaseContext)
583 LLVM_DEBUG(
dbgs() <<
"[Attributor] Introducing call base context:" << CB
588 for (
const Function *Callee : Callees) {
592 IntroduceCallBaseContext ? &CB :
nullptr)
594 *
Callee, IntroduceCallBaseContext ? &CB : nullptr);
596 if (Attribute::isEnumAttrKind(IRAttributeKind)) {
599 A,
this, FnPos, DepClassTy::REQUIRED, IsKnown))
605 A.getAAFor<AAType>(*
this, FnPos, DepClassTy::REQUIRED);
609 if (S.isAtFixpoint())
610 return S.isValidState();
614 if (!
A.checkForAllCallees(CalleePred, *
this, CB))
615 return S.indicatePessimisticFixpoint();
621template <
class AAType,
typename StateType =
typename AAType::StateType>
627 auto EIt = Explorer.
begin(CtxI), EEnd = Explorer.
end(CtxI);
628 for (
unsigned u = 0;
u <
Uses.size(); ++
u) {
632 if (Found &&
AA.followUseInMBEC(
A, U, UserI, State))
647template <
class AAType,
typename StateType =
typename AAType::StateType>
648static void followUsesInMBEC(AAType &
AA,
Attributor &
A, StateType &S,
650 const Value &Val =
AA.getIRPosition().getAssociatedValue();
655 A.getInfoCache().getMustBeExecutedContextExplorer();
661 for (
const Use &U : Val.
uses())
664 followUsesInContext<AAType>(
AA,
A, *Explorer, &CtxI,
Uses, S);
666 if (S.isAtFixpoint())
710 StateType ParentState;
714 ParentState.indicateOptimisticFixpoint();
716 for (
const BasicBlock *BB : Br->successors()) {
717 StateType ChildState;
719 size_t BeforeSize =
Uses.size();
720 followUsesInContext(
AA,
A, *Explorer, &BB->front(),
Uses, ChildState);
723 for (
auto It =
Uses.begin() + BeforeSize; It !=
Uses.end();)
726 ParentState &= ChildState;
777 R.indicatePessimisticFixpoint();
794 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> {
1006 const std::string getAsStr(
Attributor *
A)
const override {
1007 return std::string(
"PointerInfo ") +
1008 (isValidState() ? (std::string(
"#") +
1009 std::to_string(OffsetBins.size()) +
" bins")
1014 [](int64_t O) {
return std::to_string(O); }),
1022 return AAPointerInfo::manifest(
A);
1025 const_bin_iterator
begin()
const override {
return State::begin(); }
1026 const_bin_iterator
end()
const override {
return State::end(); }
1027 int64_t numOffsetBins()
const override {
return State::numOffsetBins(); }
1028 bool reachesReturn()
const override {
1029 return !ReturnedOffsets.isUnassigned();
1031 void addReturnedOffsetsTo(OffsetInfo &OI)
const override {
1032 if (ReturnedOffsets.isUnknown()) {
1037 OffsetInfo MergedOI;
1038 for (
auto Offset : ReturnedOffsets) {
1039 OffsetInfo TmpOI = OI;
1041 MergedOI.merge(TmpOI);
1043 OI = std::move(MergedOI);
1046 ChangeStatus setReachesReturn(
const OffsetInfo &ReachedReturnedOffsets) {
1047 if (ReturnedOffsets.isUnknown())
1048 return ChangeStatus::UNCHANGED;
1049 if (ReachedReturnedOffsets.isUnknown()) {
1050 ReturnedOffsets.setUnknown();
1051 return ChangeStatus::CHANGED;
1053 if (ReturnedOffsets.merge(ReachedReturnedOffsets))
1054 return ChangeStatus::CHANGED;
1055 return ChangeStatus::UNCHANGED;
1058 bool forallInterferingAccesses(
1060 function_ref<
bool(
const AAPointerInfo::Access &,
bool)> CB)
1062 return State::forallInterferingAccesses(
Range, CB);
1065 bool forallInterferingAccesses(
1066 Attributor &
A,
const AbstractAttribute &QueryingAA, Instruction &
I,
1067 bool FindInterferingWrites,
bool FindInterferingReads,
1068 function_ref<
bool(
const Access &,
bool)> UserCB,
bool &HasBeenWrittenTo,
1070 function_ref<
bool(
const Access &)> SkipCB)
const override {
1071 HasBeenWrittenTo =
false;
1073 SmallPtrSet<const Access *, 8> DominatingWrites;
1081 const auto *ExecDomainAA =
A.lookupAAFor<AAExecutionDomain>(
1083 bool AllInSameNoSyncFn = IsAssumedNoSync;
1084 bool InstIsExecutedByInitialThreadOnly =
1085 ExecDomainAA && ExecDomainAA->isExecutedByInitialThreadOnly(
I);
1092 bool InstIsExecutedInAlignedRegion =
1093 FindInterferingReads && ExecDomainAA &&
1094 ExecDomainAA->isExecutedInAlignedRegion(
A,
I);
1096 if (InstIsExecutedInAlignedRegion || InstIsExecutedByInitialThreadOnly)
1097 A.recordDependence(*ExecDomainAA, QueryingAA, DepClassTy::OPTIONAL);
1099 InformationCache &InfoCache =
A.getInfoCache();
1100 bool IsThreadLocalObj =
1109 auto CanIgnoreThreadingForInst = [&](
const Instruction &
I) ->
bool {
1110 if (IsThreadLocalObj || AllInSameNoSyncFn)
1112 const auto *FnExecDomainAA =
1113 I.getFunction() == &
Scope
1115 :
A.lookupAAFor<AAExecutionDomain>(
1118 if (!FnExecDomainAA)
1120 if (InstIsExecutedInAlignedRegion ||
1121 (FindInterferingWrites &&
1122 FnExecDomainAA->isExecutedInAlignedRegion(
A,
I))) {
1123 A.recordDependence(*FnExecDomainAA, QueryingAA, DepClassTy::OPTIONAL);
1126 if (InstIsExecutedByInitialThreadOnly &&
1127 FnExecDomainAA->isExecutedByInitialThreadOnly(
I)) {
1128 A.recordDependence(*FnExecDomainAA, QueryingAA, DepClassTy::OPTIONAL);
1137 auto CanIgnoreThreading = [&](
const Access &Acc) ->
bool {
1138 return CanIgnoreThreadingForInst(*Acc.getRemoteInst()) ||
1139 (Acc.getRemoteInst() != Acc.getLocalInst() &&
1140 CanIgnoreThreadingForInst(*Acc.getLocalInst()));
1144 bool IsKnownNoRecurse;
1152 bool InstInKernel =
A.getInfoCache().isKernel(Scope);
1153 bool ObjHasKernelLifetime =
false;
1154 const bool UseDominanceReasoning =
1155 FindInterferingWrites && IsKnownNoRecurse;
1156 const DominatorTree *DT =
1165 unsigned VAS =
V->getType()->getPointerAddressSpace();
1176 std::function<bool(
const Function &)> IsLiveInCalleeCB;
1181 const Function *AIFn = AI->getFunction();
1182 ObjHasKernelLifetime =
A.getInfoCache().isKernel(*AIFn);
1183 bool IsKnownNoRecurse;
1186 IsKnownNoRecurse)) {
1187 IsLiveInCalleeCB = [AIFn](
const Function &Fn) {
return AIFn != &Fn; };
1192 ObjHasKernelLifetime = HasKernelLifetime(GV, *GV->getParent());
1193 if (ObjHasKernelLifetime)
1194 IsLiveInCalleeCB = [&
A](
const Function &Fn) {
1195 return !
A.getInfoCache().isKernel(Fn);
1203 auto AccessCB = [&](
const Access &Acc,
bool Exact) {
1204 Function *AccScope = Acc.getRemoteInst()->getFunction();
1205 bool AccInSameScope = AccScope == &
Scope;
1209 if (InstInKernel && ObjHasKernelLifetime && !AccInSameScope &&
1210 A.getInfoCache().isKernel(*AccScope))
1213 if (Exact && Acc.isMustAccess() && Acc.getRemoteInst() != &
I) {
1214 if (Acc.isWrite() || (
isa<LoadInst>(
I) && Acc.isWriteOrAssumption()))
1215 ExclusionSet.
insert(Acc.getRemoteInst());
1218 if ((!FindInterferingWrites || !Acc.isWriteOrAssumption()) &&
1219 (!FindInterferingReads || !Acc.isRead()))
1222 bool Dominates = FindInterferingWrites && DT && Exact &&
1223 Acc.isMustAccess() && AccInSameScope &&
1226 DominatingWrites.
insert(&Acc);
1230 AllInSameNoSyncFn &= Acc.getRemoteInst()->getFunction() == &
Scope;
1232 InterferingAccesses.
push_back({&Acc, Exact});
1235 if (!State::forallInterferingAccesses(
I, AccessCB,
Range))
1238 HasBeenWrittenTo = !DominatingWrites.
empty();
1242 for (
const Access *Acc : DominatingWrites) {
1243 if (!LeastDominatingWriteInst) {
1244 LeastDominatingWriteInst = Acc->getRemoteInst();
1245 }
else if (DT->
dominates(LeastDominatingWriteInst,
1246 Acc->getRemoteInst())) {
1247 LeastDominatingWriteInst = Acc->getRemoteInst();
1252 auto CanSkipAccess = [&](
const Access &Acc,
bool Exact) {
1253 if (SkipCB && SkipCB(Acc))
1255 if (!CanIgnoreThreading(Acc))
1261 bool ReadChecked = !FindInterferingReads;
1262 bool WriteChecked = !FindInterferingWrites;
1268 &ExclusionSet, IsLiveInCalleeCB))
1273 if (!WriteChecked) {
1275 &ExclusionSet, IsLiveInCalleeCB))
1276 WriteChecked =
true;
1290 if (!WriteChecked && HasBeenWrittenTo &&
1291 Acc.getRemoteInst()->getFunction() != &Scope) {
1293 const auto *FnReachabilityAA =
A.getAAFor<AAInterFnReachability>(
1295 if (FnReachabilityAA) {
1301 if (!FnReachabilityAA->instructionCanReach(
1302 A, *LeastDominatingWriteInst,
1303 *Acc.getRemoteInst()->getFunction(), &ExclusionSet))
1304 WriteChecked =
true;
1311 if (ReadChecked && WriteChecked)
1314 if (!DT || !UseDominanceReasoning)
1316 if (!DominatingWrites.count(&Acc))
1318 return LeastDominatingWriteInst != Acc.getRemoteInst();
1323 for (
auto &It : InterferingAccesses) {
1324 if ((!AllInSameNoSyncFn && !IsThreadLocalObj && !ExecDomainAA) ||
1325 !CanSkipAccess(*It.first, It.second)) {
1326 if (!UserCB(*It.first, It.second))
1334 const AAPointerInfo &OtherAA,
1336 using namespace AA::PointerInfo;
1338 return indicatePessimisticFixpoint();
1341 const auto &OtherAAImpl =
static_cast<const AAPointerInfoImpl &
>(OtherAA);
1342 bool IsByval = OtherAAImpl.getAssociatedArgument()->hasByValAttr();
1343 Changed |= setReachesReturn(OtherAAImpl.ReturnedOffsets);
1346 const auto &State = OtherAAImpl.getState();
1347 for (
const auto &It : State) {
1348 for (
auto Index : It.getSecond()) {
1349 const auto &RAcc = State.getAccess(Index);
1350 if (IsByval && !RAcc.isRead())
1352 bool UsedAssumedInformation =
false;
1354 auto Content =
A.translateArgumentToCallSiteContent(
1355 RAcc.getContent(), CB, *
this, UsedAssumedInformation);
1356 AK =
AccessKind(AK & (IsByval ? AccessKind::AK_R : AccessKind::AK_RW));
1357 AK =
AccessKind(AK | (RAcc.isMayAccess() ? AK_MAY : AK_MUST));
1359 Changed |= addAccess(
A, RAcc.getRanges(), CB, Content, AK,
1360 RAcc.getType(), RAcc.getRemoteInst());
1366 ChangeStatus translateAndAddState(Attributor &
A,
const AAPointerInfo &OtherAA,
1367 const OffsetInfo &Offsets, CallBase &CB,
1369 using namespace AA::PointerInfo;
1371 return indicatePessimisticFixpoint();
1373 const auto &OtherAAImpl =
static_cast<const AAPointerInfoImpl &
>(OtherAA);
1377 const auto &State = OtherAAImpl.getState();
1378 for (
const auto &It : State) {
1379 for (
auto Index : It.getSecond()) {
1380 const auto &RAcc = State.getAccess(Index);
1381 if (!IsMustAcc && RAcc.isAssumption())
1383 for (
auto Offset : Offsets) {
1387 if (!NewRanges.isUnknown()) {
1388 NewRanges.addToAllOffsets(Offset);
1393 Changed |= addAccess(
A, NewRanges, CB, RAcc.getContent(), AK,
1394 RAcc.getType(), RAcc.getRemoteInst());
1403 void trackPointerInfoStatistics(
const IRPosition &IRP)
const {}
1406 void dumpState(raw_ostream &O) {
1407 for (
auto &It : OffsetBins) {
1408 O <<
"[" << It.first.Offset <<
"-" << It.first.Offset + It.first.Size
1409 <<
"] : " << It.getSecond().size() <<
"\n";
1410 for (
auto AccIndex : It.getSecond()) {
1411 auto &Acc = AccessList[AccIndex];
1412 O <<
" - " << Acc.getKind() <<
" - " << *Acc.getLocalInst() <<
"\n";
1413 if (Acc.getLocalInst() != Acc.getRemoteInst())
1414 O <<
" --> " << *Acc.getRemoteInst()
1416 if (!Acc.isWrittenValueYetUndetermined()) {
1418 O <<
" - c: func " << Acc.getWrittenValue()->getName()
1420 else if (Acc.getWrittenValue())
1421 O <<
" - c: " << *Acc.getWrittenValue() <<
"\n";
1423 O <<
" - c: <unknown>\n";
1430struct AAPointerInfoFloating :
public AAPointerInfoImpl {
1432 AAPointerInfoFloating(
const IRPosition &IRP, Attributor &
A)
1433 : AAPointerInfoImpl(IRP,
A) {}
1436 bool handleAccess(Attributor &
A, Instruction &
I,
1437 std::optional<Value *> Content,
AccessKind Kind,
1440 using namespace AA::PointerInfo;
1442 const DataLayout &
DL =
A.getDataLayout();
1443 TypeSize AccessSize =
DL.getTypeStoreSize(&Ty);
1452 if (!VT || VT->getElementCount().isScalable() ||
1454 (*Content)->getType() != VT ||
1455 DL.getTypeStoreSize(VT->getElementType()).isScalable()) {
1466 int64_t ElementSize =
DL.getTypeStoreSize(ElementType).getFixedValue();
1470 OffsetsSorted.end());
1472 for (
int i = 0, e = VT->getElementCount().getFixedValue(); i != e; ++i) {
1474 ConstContent, ConstantInt::get(Int32Ty, i));
1481 for (
auto &ElementOffset : ElementOffsets)
1482 ElementOffset += ElementSize;
1495 bool collectConstantsForGEP(Attributor &
A,
const DataLayout &
DL,
1496 OffsetInfo &UsrOI,
const OffsetInfo &PtrOI,
1497 const GEPOperator *
GEP);
1500 void trackStatistics()
const override {
1501 AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());
1505bool AAPointerInfoFloating::collectConstantsForGEP(Attributor &
A,
1506 const DataLayout &
DL,
1508 const OffsetInfo &PtrOI,
1509 const GEPOperator *
GEP) {
1510 unsigned BitWidth =
DL.getIndexTypeSizeInBits(
GEP->getType());
1511 SmallMapVector<Value *, APInt, 4> VariableOffsets;
1514 assert(!UsrOI.isUnknown() && !PtrOI.isUnknown() &&
1515 "Don't look for constant values if the offset has already been "
1516 "determined to be unknown.");
1518 if (!
GEP->collectOffset(
DL,
BitWidth, VariableOffsets, ConstantOffset)) {
1524 << (VariableOffsets.
empty() ?
"" :
"not") <<
" constant "
1528 Union.addToAll(ConstantOffset.getSExtValue());
1533 for (
const auto &VI : VariableOffsets) {
1534 auto *PotentialConstantsAA =
A.getAAFor<AAPotentialConstantValues>(
1536 if (!PotentialConstantsAA || !PotentialConstantsAA->isValidState()) {
1542 if (PotentialConstantsAA->undefIsContained())
1549 auto &AssumedSet = PotentialConstantsAA->getAssumedSet();
1550 if (AssumedSet.empty())
1554 for (
const auto &ConstOffset : AssumedSet) {
1555 auto CopyPerOffset =
Union;
1556 CopyPerOffset.addToAll(ConstOffset.getSExtValue() *
1557 VI.second.getZExtValue());
1558 Product.merge(CopyPerOffset);
1563 UsrOI = std::move(Union);
1567ChangeStatus AAPointerInfoFloating::updateImpl(Attributor &
A) {
1568 using namespace AA::PointerInfo;
1570 const DataLayout &
DL =
A.getDataLayout();
1571 Value &AssociatedValue = getAssociatedValue();
1573 DenseMap<Value *, OffsetInfo> OffsetInfoMap;
1574 OffsetInfoMap[&AssociatedValue].
insert(0);
1576 auto HandlePassthroughUser = [&](
Value *Usr,
Value *CurPtr,
bool &Follow) {
1587 "CurPtr does not exist in the map!");
1589 auto &UsrOI = OffsetInfoMap[Usr];
1590 auto &PtrOI = OffsetInfoMap[CurPtr];
1591 assert(!PtrOI.isUnassigned() &&
1592 "Cannot pass through if the input Ptr was not visited!");
1598 auto UsePred = [&](
const Use &
U,
bool &Follow) ->
bool {
1600 User *Usr =
U.getUser();
1601 LLVM_DEBUG(
dbgs() <<
"[AAPointerInfo] Analyze " << *CurPtr <<
" in " << *Usr
1604 "The current pointer offset should have been seeded!");
1605 assert(!OffsetInfoMap[CurPtr].isUnassigned() &&
1606 "Current pointer should be assigned");
1612 return HandlePassthroughUser(Usr, CurPtr, Follow);
1617 auto &UsrOI = OffsetInfoMap[Usr];
1618 auto &PtrOI = OffsetInfoMap[CurPtr];
1620 if (UsrOI.isUnknown())
1623 if (PtrOI.isUnknown()) {
1629 Follow = collectConstantsForGEP(
A,
DL, UsrOI, PtrOI,
GEP);
1633 return HandlePassthroughUser(Usr, CurPtr, Follow);
1638 if (RI->getFunction() == getAssociatedFunction()) {
1639 auto &PtrOI = OffsetInfoMap[CurPtr];
1640 Changed |= setReachesReturn(PtrOI);
1653 auto &UsrOI = PhiIt->second;
1654 auto &PtrOI = OffsetInfoMap[CurPtr];
1658 if (PtrOI.isUnknown()) {
1659 LLVM_DEBUG(
dbgs() <<
"[AAPointerInfo] PHI operand offset unknown "
1660 << *CurPtr <<
" in " << *
PHI <<
"\n");
1661 Follow = !UsrOI.isUnknown();
1667 if (UsrOI == PtrOI) {
1668 assert(!PtrOI.isUnassigned() &&
1669 "Cannot assign if the current Ptr was not visited!");
1670 LLVM_DEBUG(
dbgs() <<
"[AAPointerInfo] PHI is invariant (so far)");
1680 auto It = OffsetInfoMap.
find(CurPtrBase);
1681 if (It == OffsetInfoMap.
end()) {
1682 LLVM_DEBUG(
dbgs() <<
"[AAPointerInfo] PHI operand is too complex "
1683 << *CurPtr <<
" in " << *
PHI
1684 <<
" (base: " << *CurPtrBase <<
")\n");
1698 A.getInfoCache().getAnalysisResultForFunction<CycleAnalysis>(
1699 *
PHI->getFunction());
1701 auto BaseOI = It->getSecond();
1702 BaseOI.addToAll(
Offset.getZExtValue());
1703 if (IsFirstPHIUser || BaseOI == UsrOI) {
1704 LLVM_DEBUG(
dbgs() <<
"[AAPointerInfo] PHI is invariant " << *CurPtr
1705 <<
" in " << *Usr <<
"\n");
1706 return HandlePassthroughUser(Usr, CurPtr, Follow);
1710 dbgs() <<
"[AAPointerInfo] PHI operand pointer offset mismatch "
1711 << *CurPtr <<
" in " << *
PHI <<
"\n");
1730 if (!handleAccess(
A, *LoadI,
nullptr, AK,
1731 OffsetInfoMap[CurPtr].Offsets,
Changed,
1737 return II->isAssumeLikeIntrinsic();
1748 }
while (FromI && FromI != ToI);
1753 auto IsValidAssume = [&](IntrinsicInst &IntrI) {
1754 if (IntrI.getIntrinsicID() != Intrinsic::assume)
1757 if (IntrI.getParent() == BB) {
1758 if (IsImpactedInRange(LoadI->getNextNode(), &IntrI))
1764 if ((*PredIt) != BB)
1769 if (SuccBB == IntrBB)
1775 if (IsImpactedInRange(LoadI->getNextNode(), BB->
getTerminator()))
1777 if (IsImpactedInRange(&IntrBB->
front(), &IntrI))
1783 std::pair<Value *, IntrinsicInst *>
Assumption;
1784 for (
const Use &LoadU : LoadI->uses()) {
1786 if (!CmpI->isEquality() || !CmpI->isTrueWhenEqual())
1788 for (
const Use &CmpU : CmpI->uses()) {
1790 if (!IsValidAssume(*IntrI))
1792 int Idx = CmpI->getOperandUse(0) == LoadU;
1809 bool UsedAssumedInformation =
false;
1810 std::optional<Value *> Content =
nullptr;
1815 return handleAccess(
1816 A, *
Assumption.second, Content, AccessKind::AK_ASSUMPTION,
1817 OffsetInfoMap[CurPtr].Offsets,
Changed, *LoadI->getType());
1822 for (
auto *OtherOp : OtherOps) {
1823 if (OtherOp == CurPtr) {
1826 <<
"[AAPointerInfo] Escaping use in store like instruction " <<
I
1838 bool UsedAssumedInformation =
false;
1839 std::optional<Value *> Content =
nullptr;
1841 Content =
A.getAssumedSimplified(
1843 return handleAccess(
A,
I, Content, AK, OffsetInfoMap[CurPtr].Offsets,
1848 return HandleStoreLike(*StoreI, StoreI->getValueOperand(),
1849 *StoreI->getValueOperand()->getType(),
1850 {StoreI->getValueOperand()}, AccessKind::AK_W);
1852 return HandleStoreLike(*RMWI,
nullptr, *RMWI->getValOperand()->getType(),
1853 {RMWI->getValOperand()}, AccessKind::AK_RW);
1855 return HandleStoreLike(
1856 *CXI,
nullptr, *CXI->getNewValOperand()->getType(),
1857 {CXI->getCompareOperand(), CXI->getNewValOperand()},
1864 A.getInfoCache().getTargetLibraryInfoForFunction(*CB->
getFunction());
1869 const auto *CSArgPI =
A.getAAFor<AAPointerInfo>(
1875 Changed = translateAndAddState(
A, *CSArgPI, OffsetInfoMap[CurPtr], *CB,
1878 if (!CSArgPI->reachesReturn())
1879 return isValidState();
1882 if (!Callee ||
Callee->arg_size() <= ArgNo)
1884 bool UsedAssumedInformation =
false;
1885 auto ReturnedValue =
A.getAssumedSimplified(
1890 auto *Arg =
Callee->getArg(ArgNo);
1891 if (ReturnedArg && Arg != ReturnedArg)
1893 bool IsRetMustAcc = IsArgMustAcc && (ReturnedArg == Arg);
1894 const auto *CSRetPI =
A.getAAFor<AAPointerInfo>(
1898 OffsetInfo OI = OffsetInfoMap[CurPtr];
1899 CSArgPI->addReturnedOffsetsTo(OI);
1901 translateAndAddState(
A, *CSRetPI, OI, *CB, IsRetMustAcc) |
Changed;
1902 return isValidState();
1904 LLVM_DEBUG(
dbgs() <<
"[AAPointerInfo] Call user not handled " << *CB
1909 LLVM_DEBUG(
dbgs() <<
"[AAPointerInfo] User not handled " << *Usr <<
"\n");
1912 auto EquivalentUseCB = [&](
const Use &OldU,
const Use &NewU) {
1913 assert(OffsetInfoMap.
count(OldU) &&
"Old use should be known already!");
1914 assert(!OffsetInfoMap[OldU].isUnassigned() &&
"Old use should be assinged");
1915 if (OffsetInfoMap.
count(NewU)) {
1917 if (!(OffsetInfoMap[NewU] == OffsetInfoMap[OldU])) {
1918 dbgs() <<
"[AAPointerInfo] Equivalent use callback failed: "
1919 << OffsetInfoMap[NewU] <<
" vs " << OffsetInfoMap[OldU]
1923 return OffsetInfoMap[NewU] == OffsetInfoMap[OldU];
1926 return HandlePassthroughUser(NewU.get(), OldU.
get(), Unused);
1928 if (!
A.checkForAllUses(UsePred, *
this, AssociatedValue,
1930 true, EquivalentUseCB)) {
1931 LLVM_DEBUG(
dbgs() <<
"[AAPointerInfo] Check for all uses failed, abort!\n");
1932 return indicatePessimisticFixpoint();
1936 dbgs() <<
"Accesses by bin after update:\n";
1943struct AAPointerInfoReturned final : AAPointerInfoImpl {
1944 AAPointerInfoReturned(
const IRPosition &IRP, Attributor &
A)
1945 : AAPointerInfoImpl(IRP,
A) {}
1949 return indicatePessimisticFixpoint();
1953 void trackStatistics()
const override {
1954 AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());
1958struct AAPointerInfoArgument final : AAPointerInfoFloating {
1959 AAPointerInfoArgument(
const IRPosition &IRP, Attributor &
A)
1960 : AAPointerInfoFloating(IRP,
A) {}
1963 void trackStatistics()
const override {
1964 AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());
1968struct AAPointerInfoCallSiteArgument final : AAPointerInfoFloating {
1969 AAPointerInfoCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
1970 : AAPointerInfoFloating(IRP,
A) {}
1974 using namespace AA::PointerInfo;
1980 if (
auto Length =
MI->getLengthInBytes())
1981 LengthVal =
Length->getSExtValue();
1982 unsigned ArgNo = getIRPosition().getCallSiteArgNo();
1985 LLVM_DEBUG(
dbgs() <<
"[AAPointerInfo] Unhandled memory intrinsic "
1987 return indicatePessimisticFixpoint();
1990 ArgNo == 0 ? AccessKind::AK_MUST_WRITE : AccessKind::AK_MUST_READ;
1992 Changed | addAccess(
A, {0, LengthVal}, *
MI,
nullptr,
Kind,
nullptr);
1995 dbgs() <<
"Accesses by bin after update:\n";
2006 Argument *Arg = getAssociatedArgument();
2010 A.getAAFor<AAPointerInfo>(*
this, ArgPos, DepClassTy::REQUIRED);
2011 if (ArgAA && ArgAA->getState().isValidState())
2012 return translateAndAddStateFromCallee(
A, *ArgAA,
2015 return indicatePessimisticFixpoint();
2018 bool IsKnownNoCapture;
2020 A,
this, getIRPosition(), DepClassTy::OPTIONAL, IsKnownNoCapture))
2021 return indicatePessimisticFixpoint();
2023 bool IsKnown =
false;
2025 return ChangeStatus::UNCHANGED;
2028 ReadOnly ? AccessKind::AK_MAY_READ : AccessKind::AK_MAY_READ_WRITE;
2034 void trackStatistics()
const override {
2035 AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());
2039struct AAPointerInfoCallSiteReturned final : AAPointerInfoFloating {
2040 AAPointerInfoCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
2041 : AAPointerInfoFloating(IRP,
A) {}
2044 void trackStatistics()
const override {
2045 AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());
2053struct AANoUnwindImpl : AANoUnwind {
2054 AANoUnwindImpl(
const IRPosition &IRP, Attributor &
A) : AANoUnwind(IRP,
A) {}
2060 A,
nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));
2064 const std::string getAsStr(Attributor *
A)
const override {
2065 return getAssumed() ?
"nounwind" :
"may-unwind";
2071 (unsigned)Instruction::Invoke, (
unsigned)Instruction::CallBr,
2072 (unsigned)Instruction::Call, (
unsigned)Instruction::CleanupRet,
2073 (unsigned)Instruction::CatchSwitch, (
unsigned)Instruction::Resume};
2076 if (!
I.mayThrow(
true))
2080 bool IsKnownNoUnwind;
2088 bool UsedAssumedInformation =
false;
2089 if (!
A.checkForAllInstructions(CheckForNoUnwind, *
this, Opcodes,
2090 UsedAssumedInformation))
2091 return indicatePessimisticFixpoint();
2093 return ChangeStatus::UNCHANGED;
2097struct AANoUnwindFunction final :
public AANoUnwindImpl {
2098 AANoUnwindFunction(
const IRPosition &IRP, Attributor &
A)
2099 : AANoUnwindImpl(IRP,
A) {}
2106struct AANoUnwindCallSite final
2107 : AACalleeToCallSite<AANoUnwind, AANoUnwindImpl> {
2108 AANoUnwindCallSite(
const IRPosition &IRP, Attributor &
A)
2109 : AACalleeToCallSite<AANoUnwind, AANoUnwindImpl>(IRP,
A) {}
2120 case Intrinsic::nvvm_barrier_cta_sync_aligned_all:
2121 case Intrinsic::nvvm_barrier_cta_sync_aligned_count:
2122 case Intrinsic::nvvm_barrier_cta_red_and_aligned_all:
2123 case Intrinsic::nvvm_barrier_cta_red_and_aligned_count:
2124 case Intrinsic::nvvm_barrier_cta_red_or_aligned_all:
2125 case Intrinsic::nvvm_barrier_cta_red_or_aligned_count:
2126 case Intrinsic::nvvm_barrier_cta_red_popc_aligned_all:
2127 case Intrinsic::nvvm_barrier_cta_red_popc_aligned_count:
2129 case Intrinsic::amdgcn_s_barrier:
2130 if (ExecutedAligned)
2153 switch (
I->getOpcode()) {
2154 case Instruction::AtomicRMW:
2157 case Instruction::Store:
2160 case Instruction::Load:
2165 "New atomic operations need to be known in the attributor.");
2184 const std::string getAsStr(Attributor *
A)
const override {
2185 return getAssumed() ?
"nosync" :
"may-sync";
2201 if (
I.mayReadOrWriteMemory())
2215 bool UsedAssumedInformation =
false;
2216 if (!
A.checkForAllReadWriteInstructions(CheckRWInstForNoSync, *
this,
2217 UsedAssumedInformation) ||
2218 !
A.checkForAllCallLikeInstructions(CheckForNoSync, *
this,
2219 UsedAssumedInformation))
2220 return indicatePessimisticFixpoint();
2225struct AANoSyncFunction final :
public AANoSyncImpl {
2226 AANoSyncFunction(
const IRPosition &IRP, Attributor &
A)
2227 : AANoSyncImpl(IRP,
A) {}
2234struct AANoSyncCallSite final : AACalleeToCallSite<AANoSync, AANoSyncImpl> {
2235 AANoSyncCallSite(
const IRPosition &IRP, Attributor &
A)
2236 : AACalleeToCallSite<AANoSync, AANoSyncImpl>(IRP,
A) {}
2246struct AANoFreeImpl :
public AANoFree {
2247 AANoFreeImpl(
const IRPosition &IRP, Attributor &
A) : AANoFree(IRP,
A) {}
2253 DepClassTy::NONE, IsKnown));
2271 bool UsedAssumedInformation =
false;
2272 if (!
A.checkForAllReadWriteInstructions(CheckForNoFree, *
this,
2273 UsedAssumedInformation) ||
2274 !
A.checkForAllCallLikeInstructions(CheckForNoFree, *
this,
2275 UsedAssumedInformation))
2276 return indicatePessimisticFixpoint();
2278 return ChangeStatus::UNCHANGED;
2282 const std::string getAsStr(Attributor *
A)
const override {
2283 return getAssumed() ?
"nofree" :
"may-free";
2287struct AANoFreeFunction final :
public AANoFreeImpl {
2288 AANoFreeFunction(
const IRPosition &IRP, Attributor &
A)
2289 : AANoFreeImpl(IRP,
A) {}
2296struct AANoFreeCallSite final : AACalleeToCallSite<AANoFree, AANoFreeImpl> {
2297 AANoFreeCallSite(
const IRPosition &IRP, Attributor &
A)
2298 : AACalleeToCallSite<AANoFree, AANoFreeImpl>(IRP,
A) {}
2305struct AANoFreeFloating : AANoFreeImpl {
2306 AANoFreeFloating(
const IRPosition &IRP, Attributor &
A)
2307 : AANoFreeImpl(IRP,
A) {}
2314 const IRPosition &IRP = getIRPosition();
2319 DepClassTy::OPTIONAL, IsKnown))
2320 return ChangeStatus::UNCHANGED;
2322 Value &AssociatedValue = getIRPosition().getAssociatedValue();
2323 auto Pred = [&](
const Use &
U,
bool &Follow) ->
bool {
2338 DepClassTy::REQUIRED, IsKnown))
2341 const AANoCapture *NoCaptureAA =
nullptr;
2344 DepClassTy::REQUIRED, IsKnown,
2345 false, &NoCaptureAA)) {
2370 if (!
A.checkForAllUses(Pred, *
this, AssociatedValue))
2371 return indicatePessimisticFixpoint();
2373 return ChangeStatus::UNCHANGED;
2378struct AANoFreeArgument final : AANoFreeFloating {
2379 AANoFreeArgument(
const IRPosition &IRP, Attributor &
A)
2380 : AANoFreeFloating(IRP,
A) {}
2387struct AANoFreeCallSiteArgument final : AANoFreeFloating {
2388 AANoFreeCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
2389 : AANoFreeFloating(IRP,
A) {}
2397 Argument *Arg = getAssociatedArgument();
2399 return indicatePessimisticFixpoint();
2403 DepClassTy::REQUIRED, IsKnown))
2404 return ChangeStatus::UNCHANGED;
2405 return indicatePessimisticFixpoint();
2413struct AANoFreeReturned final : AANoFreeFloating {
2414 AANoFreeReturned(
const IRPosition &IRP, Attributor &
A)
2415 : AANoFreeFloating(IRP,
A) {
2430 void trackStatistics()
const override {}
2434struct AANoFreeCallSiteReturned final : AANoFreeFloating {
2435 AANoFreeCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
2436 : AANoFreeFloating(IRP,
A) {}
2439 return ChangeStatus::UNCHANGED;
2450 bool IgnoreSubsumingPositions) {
2452 AttrKinds.
push_back(Attribute::NonNull);
2455 AttrKinds.
push_back(Attribute::Dereferenceable);
2456 if (
A.hasAttr(IRP, AttrKinds, IgnoreSubsumingPositions, Attribute::NonNull))
2463 if (!Fn->isDeclaration()) {
2473 bool UsedAssumedInformation =
false;
2474 if (!
A.checkForAllInstructions(
2476 Worklist.push_back({*cast<ReturnInst>(I).getReturnValue(), &I});
2480 UsedAssumedInformation,
false,
true))
2492 Attribute::NonNull)});
2497static int64_t getKnownNonNullAndDerefBytesForUse(
2498 Attributor &
A,
const AbstractAttribute &QueryingAA,
Value &AssociatedValue,
2499 const Use *U,
const Instruction *
I,
bool &IsNonNull,
bool &TrackUse) {
2502 const Value *UseV =
U->get();
2523 const DataLayout &
DL =
A.getInfoCache().getDL();
2527 U, {Attribute::NonNull, Attribute::Dereferenceable})) {
2544 bool IsKnownNonNull;
2547 IsNonNull |= IsKnownNonNull;
2550 return DerefAA ? DerefAA->getKnownDereferenceableBytes() : 0;
2554 if (!Loc || Loc->Ptr != UseV || !Loc->Size.isPrecise() ||
2555 Loc->Size.isScalable() ||
I->isVolatile())
2561 if (
Base &&
Base == &AssociatedValue) {
2562 int64_t DerefBytes = Loc->Size.getValue() +
Offset;
2564 return std::max(int64_t(0), DerefBytes);
2571 int64_t DerefBytes = Loc->Size.getValue();
2573 return std::max(int64_t(0), DerefBytes);
2579struct AANonNullImpl : AANonNull {
2580 AANonNullImpl(
const IRPosition &IRP, Attributor &
A) : AANonNull(IRP,
A) {}
2584 Value &
V = *getAssociatedValue().stripPointerCasts();
2586 indicatePessimisticFixpoint();
2590 if (Instruction *CtxI = getCtxI())
2591 followUsesInMBEC(*
this,
A, getState(), *CtxI);
2595 bool followUseInMBEC(Attributor &
A,
const Use *U,
const Instruction *
I,
2596 AANonNull::StateType &State) {
2597 bool IsNonNull =
false;
2598 bool TrackUse =
false;
2599 getKnownNonNullAndDerefBytesForUse(
A, *
this, getAssociatedValue(), U,
I,
2600 IsNonNull, TrackUse);
2601 State.setKnown(IsNonNull);
2606 const std::string getAsStr(Attributor *
A)
const override {
2607 return getAssumed() ?
"nonnull" :
"may-null";
2612struct AANonNullFloating :
public AANonNullImpl {
2613 AANonNullFloating(
const IRPosition &IRP, Attributor &
A)
2614 : AANonNullImpl(IRP,
A) {}
2618 auto CheckIRP = [&](
const IRPosition &IRP) {
2619 bool IsKnownNonNull;
2621 A, *
this, IRP, DepClassTy::OPTIONAL, IsKnownNonNull);
2625 bool UsedAssumedInformation =
false;
2626 Value *AssociatedValue = &getAssociatedValue();
2628 if (!
A.getAssumedSimplifiedValues(getIRPosition(), *
this,
Values,
2633 Values.size() != 1 ||
Values.front().getValue() != AssociatedValue;
2639 return AA::hasAssumedIRAttr<Attribute::NonNull>(
2640 A, this, IRPosition::value(*Op), DepClassTy::OPTIONAL,
2643 return ChangeStatus::UNCHANGED;
2647 DepClassTy::OPTIONAL, IsKnown) &&
2650 DepClassTy::OPTIONAL, IsKnown))
2651 return ChangeStatus::UNCHANGED;
2658 if (AVIRP == getIRPosition() || !CheckIRP(AVIRP))
2659 return indicatePessimisticFixpoint();
2660 return ChangeStatus::UNCHANGED;
2663 for (
const auto &VAC :
Values)
2665 return indicatePessimisticFixpoint();
2667 return ChangeStatus::UNCHANGED;
2675struct AANonNullReturned final
2676 : AAReturnedFromReturnedValues<AANonNull, AANonNull, AANonNull::StateType,
2677 false, AANonNull::IRAttributeKind, false> {
2678 AANonNullReturned(
const IRPosition &IRP, Attributor &
A)
2679 : AAReturnedFromReturnedValues<AANonNull, AANonNull, AANonNull::StateType,
2684 const std::string getAsStr(Attributor *
A)
const override {
2685 return getAssumed() ?
"nonnull" :
"may-null";
2693struct AANonNullArgument final
2694 : AAArgumentFromCallSiteArguments<AANonNull, AANonNullImpl> {
2695 AANonNullArgument(
const IRPosition &IRP, Attributor &
A)
2696 : AAArgumentFromCallSiteArguments<AANonNull, AANonNullImpl>(IRP,
A) {}
2702struct AANonNullCallSiteArgument final : AANonNullFloating {
2703 AANonNullCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
2704 : AANonNullFloating(IRP,
A) {}
2711struct AANonNullCallSiteReturned final
2712 : AACalleeToCallSite<AANonNull, AANonNullImpl> {
2713 AANonNullCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
2714 : AACalleeToCallSite<AANonNull, AANonNullImpl>(IRP,
A) {}
2723struct AAMustProgressImpl :
public AAMustProgress {
2724 AAMustProgressImpl(
const IRPosition &IRP, Attributor &
A)
2725 : AAMustProgress(IRP,
A) {}
2731 A,
nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));
2736 const std::string getAsStr(Attributor *
A)
const override {
2737 return getAssumed() ?
"mustprogress" :
"may-not-progress";
2741struct AAMustProgressFunction final : AAMustProgressImpl {
2742 AAMustProgressFunction(
const IRPosition &IRP, Attributor &
A)
2743 : AAMustProgressImpl(IRP,
A) {}
2749 A,
this, getIRPosition(), DepClassTy::OPTIONAL, IsKnown)) {
2751 return indicateOptimisticFixpoint();
2752 return ChangeStatus::UNCHANGED;
2755 auto CheckForMustProgress = [&](AbstractCallSite ACS) {
2757 bool IsKnownMustProgress;
2759 A,
this, IPos, DepClassTy::REQUIRED, IsKnownMustProgress,
2763 bool AllCallSitesKnown =
true;
2764 if (!
A.checkForAllCallSites(CheckForMustProgress, *
this,
2767 return indicatePessimisticFixpoint();
2769 return ChangeStatus::UNCHANGED;
2773 void trackStatistics()
const override {
2779struct AAMustProgressCallSite final : AAMustProgressImpl {
2780 AAMustProgressCallSite(
const IRPosition &IRP, Attributor &
A)
2781 : AAMustProgressImpl(IRP,
A) {}
2790 bool IsKnownMustProgress;
2792 A,
this, FnPos, DepClassTy::REQUIRED, IsKnownMustProgress))
2793 return indicatePessimisticFixpoint();
2794 return ChangeStatus::UNCHANGED;
2798 void trackStatistics()
const override {
2807struct AANoRecurseImpl :
public AANoRecurse {
2808 AANoRecurseImpl(
const IRPosition &IRP, Attributor &
A) : AANoRecurse(IRP,
A) {}
2814 A,
nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));
2819 const std::string getAsStr(Attributor *
A)
const override {
2820 return getAssumed() ?
"norecurse" :
"may-recurse";
2824struct AANoRecurseFunction final : AANoRecurseImpl {
2825 AANoRecurseFunction(
const IRPosition &IRP, Attributor &
A)
2826 : AANoRecurseImpl(IRP,
A) {}
2832 auto CallSitePred = [&](AbstractCallSite ACS) {
2833 bool IsKnownNoRecurse;
2837 DepClassTy::NONE, IsKnownNoRecurse))
2839 return IsKnownNoRecurse;
2841 bool UsedAssumedInformation =
false;
2842 if (
A.checkForAllCallSites(CallSitePred, *
this,
true,
2843 UsedAssumedInformation)) {
2849 if (!UsedAssumedInformation)
2850 indicateOptimisticFixpoint();
2851 return ChangeStatus::UNCHANGED;
2854 const AAInterFnReachability *EdgeReachability =
2855 A.getAAFor<AAInterFnReachability>(*
this, getIRPosition(),
2856 DepClassTy::REQUIRED);
2857 if (EdgeReachability && EdgeReachability->
canReach(
A, *getAnchorScope()))
2858 return indicatePessimisticFixpoint();
2859 return ChangeStatus::UNCHANGED;
2866struct AANoRecurseCallSite final
2867 : AACalleeToCallSite<AANoRecurse, AANoRecurseImpl> {
2868 AANoRecurseCallSite(
const IRPosition &IRP, Attributor &
A)
2869 : AACalleeToCallSite<AANoRecurse, AANoRecurseImpl>(IRP,
A) {}
2879struct AANonConvergentImpl :
public AANonConvergent {
2880 AANonConvergentImpl(
const IRPosition &IRP, Attributor &
A)
2881 : AANonConvergent(IRP,
A) {}
2884 const std::string getAsStr(Attributor *
A)
const override {
2885 return getAssumed() ?
"non-convergent" :
"may-be-convergent";
2889struct AANonConvergentFunction final : AANonConvergentImpl {
2890 AANonConvergentFunction(
const IRPosition &IRP, Attributor &
A)
2891 : AANonConvergentImpl(IRP,
A) {}
2897 auto CalleeIsNotConvergent = [&](
Instruction &Inst) {
2900 if (!Callee ||
Callee->isIntrinsic()) {
2903 if (
Callee->isDeclaration()) {
2904 return !
Callee->hasFnAttribute(Attribute::Convergent);
2906 const auto *ConvergentAA =
A.getAAFor<AANonConvergent>(
2908 return ConvergentAA && ConvergentAA->isAssumedNotConvergent();
2911 bool UsedAssumedInformation =
false;
2912 if (!
A.checkForAllCallLikeInstructions(CalleeIsNotConvergent, *
this,
2913 UsedAssumedInformation)) {
2914 return indicatePessimisticFixpoint();
2916 return ChangeStatus::UNCHANGED;
2920 if (isKnownNotConvergent() &&
2921 A.hasAttr(getIRPosition(), Attribute::Convergent)) {
2922 A.removeAttrs(getIRPosition(), {Attribute::Convergent});
2923 return ChangeStatus::CHANGED;
2925 return ChangeStatus::UNCHANGED;
2935struct AAUndefinedBehaviorImpl :
public AAUndefinedBehavior {
2936 AAUndefinedBehaviorImpl(
const IRPosition &IRP, Attributor &
A)
2937 : AAUndefinedBehavior(IRP,
A) {}
2943 UndefBranchCondition,
2945 NullReturnViolatesNonNull,
2947 NullArgViolatesNonNull,
2951 std::optional<unsigned> ArgNo;
2953 UBInfo(Kind K) :
K(
K), ArgNo(std::nullopt) {}
2955 UBInfo(Kind K, std::optional<unsigned> ArgNo) :
K(
K), ArgNo(ArgNo) {}
2961 const size_t UBPrevSize = KnownUBInsts.size();
2962 const size_t NoUBPrevSize = AssumedNoUBInsts.size();
2970 if (AssumedNoUBInsts.count(&
I) || KnownUBInsts.count(&
I))
2979 "Expected pointer operand of memory accessing instruction");
2983 std::optional<Value *> SimplifiedPtrOp =
2984 stopOnUndefOrAssumed(
A, PtrOp, &
I, UBInfo::UndefPtrAccess);
2985 if (!SimplifiedPtrOp || !*SimplifiedPtrOp)
2987 const Value *PtrOpVal = *SimplifiedPtrOp;
2993 AssumedNoUBInsts.insert(&
I);
3005 AssumedNoUBInsts.insert(&
I);
3007 KnownUBInsts.try_emplace(&
I, UBInfo::NullPtrAccess);
3016 if (AssumedNoUBInsts.count(&
I) || KnownUBInsts.count(&
I))
3024 std::optional<Value *> SimplifiedCond = stopOnUndefOrAssumed(
3025 A, BrInst->getCondition(), BrInst, UBInfo::UndefBranchCondition);
3026 if (!SimplifiedCond || !*SimplifiedCond)
3028 AssumedNoUBInsts.insert(&
I);
3036 if (AssumedNoUBInsts.count(&
I) || KnownUBInsts.count(&
I))
3045 for (
unsigned idx = 0; idx < CB.
arg_size(); idx++) {
3051 if (idx >=
Callee->arg_size())
3063 bool IsKnownNoUndef;
3065 A,
this, CalleeArgumentIRP, DepClassTy::NONE, IsKnownNoUndef);
3066 if (!IsKnownNoUndef)
3068 bool UsedAssumedInformation =
false;
3069 std::optional<Value *> SimplifiedVal =
3072 if (UsedAssumedInformation)
3074 if (SimplifiedVal && !*SimplifiedVal)
3077 KnownUBInsts.try_emplace(&
I, UBInfo(UBInfo::UndefCallArgument, idx));
3083 bool IsKnownNonNull;
3085 A,
this, CalleeArgumentIRP, DepClassTy::NONE, IsKnownNonNull);
3087 KnownUBInsts.try_emplace(&
I,
3088 UBInfo(UBInfo::NullArgViolatesNonNull, idx));
3097 std::optional<Value *> SimplifiedRetValue = stopOnUndefOrAssumed(
3098 A, RI.getReturnValue(), &
I, UBInfo::UndefReturnValue);
3099 if (!SimplifiedRetValue || !*SimplifiedRetValue)
3117 bool IsKnownNonNull;
3122 KnownUBInsts.try_emplace(&
I, UBInfo::NullReturnViolatesNonNull);
3128 bool UsedAssumedInformation =
false;
3129 A.checkForAllInstructions(InspectMemAccessInstForUB, *
this,
3130 {Instruction::Load, Instruction::Store,
3131 Instruction::AtomicCmpXchg,
3132 Instruction::AtomicRMW},
3133 UsedAssumedInformation,
3135 A.checkForAllInstructions(InspectBrInstForUB, *
this, {Instruction::CondBr},
3136 UsedAssumedInformation,
3138 A.checkForAllCallLikeInstructions(InspectCallSiteForUB, *
this,
3139 UsedAssumedInformation);
3143 if (!getAnchorScope()->getReturnType()->isVoidTy()) {
3145 if (!
A.isAssumedDead(ReturnIRP,
this,
nullptr, UsedAssumedInformation)) {
3146 bool IsKnownNoUndef;
3148 A,
this, ReturnIRP, DepClassTy::NONE, IsKnownNoUndef);
3150 A.checkForAllInstructions(InspectReturnInstForUB, *
this,
3151 {Instruction::Ret}, UsedAssumedInformation,
3156 if (NoUBPrevSize != AssumedNoUBInsts.size() ||
3157 UBPrevSize != KnownUBInsts.size())
3158 return ChangeStatus::CHANGED;
3159 return ChangeStatus::UNCHANGED;
3162 bool isKnownToCauseUB(Instruction *
I)
const override {
3163 return KnownUBInsts.count(
I);
3166 bool isAssumedToCauseUB(Instruction *
I)
const override {
3173 switch (
I->getOpcode()) {
3174 case Instruction::Load:
3175 case Instruction::Store:
3176 case Instruction::AtomicCmpXchg:
3177 case Instruction::AtomicRMW:
3178 case Instruction::CondBr:
3179 return !AssumedNoUBInsts.count(
I);
3188 static void emitUBRemark(Attributor &
A, Instruction *
I,
const UBInfo &Info) {
3189 auto Remark = [&](OptimizationRemark
OR) {
3191 case UBInfo::NullPtrAccess:
3192 case UBInfo::UndefPtrAccess: {
3193 return OR <<
"Memory access through a pointer known to be "
3196 <<
" is undefined behavior; replacing with 'unreachable'.";
3198 case UBInfo::UndefBranchCondition:
3199 return OR <<
"Branch condition known to be "
3201 <<
" is undefined behavior; replacing with 'unreachable'.";
3202 case UBInfo::UndefReturnValue:
3203 case UBInfo::NullReturnViolatesNonNull:
3204 return OR <<
"Value returned known to be "
3207 <<
" is undefined behavior; replacing with 'unreachable'.";
3208 case UBInfo::UndefCallArgument:
3209 case UBInfo::NullArgViolatesNonNull: {
3210 bool IsUndef =
Info.K == UBInfo::UndefCallArgument;
3213 <<
" passed to parameter of ";
3218 return OR <<
" known to be "
3219 <<
ore::NV(
"Argument", IsUndef ?
"undef" :
"null")
3220 <<
" is undefined behavior; replacing with 'unreachable'.";
3225 A.emitRemark<OptimizationRemark>(
I,
"UndefinedBehavior",
Remark);
3229 if (KnownUBInsts.empty())
3230 return ChangeStatus::UNCHANGED;
3231 for (
const auto &[
I, Info] : KnownUBInsts) {
3232 emitUBRemark(
A,
I, Info);
3233 A.changeToUnreachableAfterManifest(
I);
3235 return ChangeStatus::CHANGED;
3239 const std::string getAsStr(Attributor *
A)
const override {
3240 return getAssumed() ?
"undefined-behavior" :
"no-ub";
3269 MapVector<Instruction *, UBInfo> KnownUBInsts;
3273 SmallPtrSet<Instruction *, 8> AssumedNoUBInsts;
3284 std::optional<Value *> stopOnUndefOrAssumed(Attributor &
A,
Value *V,
3285 Instruction *
I, UBInfo::Kind K) {
3286 bool UsedAssumedInformation =
false;
3287 std::optional<Value *> SimplifiedV =
3290 if (!UsedAssumedInformation) {
3295 KnownUBInsts.try_emplace(
I, K);
3296 return std::nullopt;
3303 KnownUBInsts.try_emplace(
I, K);
3304 return std::nullopt;
3310struct AAUndefinedBehaviorFunction final : AAUndefinedBehaviorImpl {
3311 AAUndefinedBehaviorFunction(
const IRPosition &IRP, Attributor &
A)
3312 : AAUndefinedBehaviorImpl(IRP,
A) {}
3315 void trackStatistics()
const override {
3316 STATS_DECL(UndefinedBehaviorInstruction, Instruction,
3317 "Number of instructions known to have UB");
3319 KnownUBInsts.size();
3330static bool mayContainUnboundedCycle(
Function &
F, Attributor &
A) {
3331 ScalarEvolution *SE =
3332 A.getInfoCache().getAnalysisResultForFunction<ScalarEvolutionAnalysis>(
F);
3333 LoopInfo *LI =
A.getInfoCache().getAnalysisResultForFunction<LoopAnalysis>(
F);
3339 for (scc_iterator<Function *> SCCI =
scc_begin(&
F); !SCCI.isAtEnd(); ++SCCI)
3340 if (SCCI.hasCycle())
3350 for (
auto *L : LI->getLoopsInPreorder()) {
3357struct AAWillReturnImpl :
public AAWillReturn {
3358 AAWillReturnImpl(
const IRPosition &IRP, Attributor &
A)
3359 : AAWillReturn(IRP,
A) {}
3365 A,
nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));
3370 bool isImpliedByMustprogressAndReadonly(Attributor &
A,
bool KnownOnly) {
3371 if (!
A.hasAttr(getIRPosition(), {Attribute::MustProgress}))
3376 return IsKnown || !KnownOnly;
3382 if (isImpliedByMustprogressAndReadonly(
A,
false))
3383 return ChangeStatus::UNCHANGED;
3389 A,
this, IPos, DepClassTy::REQUIRED, IsKnown)) {
3395 bool IsKnownNoRecurse;
3397 A,
this, IPos, DepClassTy::REQUIRED, IsKnownNoRecurse);
3400 bool UsedAssumedInformation =
false;
3401 if (!
A.checkForAllCallLikeInstructions(CheckForWillReturn, *
this,
3402 UsedAssumedInformation))
3403 return indicatePessimisticFixpoint();
3407 return !
I.isVolatile();
3409 if (!
A.checkForAllInstructions(CheckForVolatile, *
this,
3410 {Instruction::Load, Instruction::Store,
3411 Instruction::AtomicCmpXchg,
3412 Instruction::AtomicRMW},
3413 UsedAssumedInformation))
3414 return indicatePessimisticFixpoint();
3416 return ChangeStatus::UNCHANGED;
3420 const std::string getAsStr(Attributor *
A)
const override {
3421 return getAssumed() ?
"willreturn" :
"may-noreturn";
3425struct AAWillReturnFunction final : AAWillReturnImpl {
3426 AAWillReturnFunction(
const IRPosition &IRP, Attributor &
A)
3427 : AAWillReturnImpl(IRP,
A) {}
3431 AAWillReturnImpl::initialize(
A);
3434 assert(
F &&
"Did expect an anchor function");
3435 if (
F->isDeclaration() || mayContainUnboundedCycle(*
F,
A))
3436 indicatePessimisticFixpoint();
3444struct AAWillReturnCallSite final
3445 : AACalleeToCallSite<AAWillReturn, AAWillReturnImpl> {
3446 AAWillReturnCallSite(
const IRPosition &IRP, Attributor &
A)
3447 : AACalleeToCallSite<AAWillReturn, AAWillReturnImpl>(IRP,
A) {}
3451 if (isImpliedByMustprogressAndReadonly(
A,
false))
3452 return ChangeStatus::UNCHANGED;
3454 return AACalleeToCallSite::updateImpl(
A);
3476 const ToTy *
To =
nullptr;
3503 if (!ES || ES->
empty()) {
3504 ExclusionSet = nullptr;
3505 }
else if (MakeUnique) {
3506 ExclusionSet =
A.getInfoCache().getOrCreateUniqueBlockExecutionSet(ES);
3524 if (!PairDMI::isEqual({LHS->From, LHS->To}, {RHS->From, RHS->To}))
3526 return InstSetDMI::isEqual(LHS->ExclusionSet, RHS->ExclusionSet);
3534template <
typename BaseTy,
typename ToTy>
3535struct CachedReachabilityAA :
public BaseTy {
3536 using RQITy = ReachabilityQueryInfo<ToTy>;
3538 CachedReachabilityAA(
const IRPosition &IRP, Attributor &
A) : BaseTy(IRP,
A) {}
3541 bool isQueryAA()
const override {
return true; }
3546 for (
unsigned u = 0, e = QueryVector.size(); u < e; ++u) {
3547 RQITy *RQI = QueryVector[
u];
3548 if (RQI->Result == RQITy::Reachable::No &&
3550 Changed = ChangeStatus::CHANGED;
3556 bool IsTemporaryRQI) = 0;
3558 bool rememberResult(Attributor &
A,
typename RQITy::Reachable Result,
3559 RQITy &RQI,
bool UsedExclusionSet,
bool IsTemporaryRQI) {
3564 QueryCache.erase(&RQI);
3570 if (Result == RQITy::Reachable::Yes || !UsedExclusionSet) {
3571 RQITy PlainRQI(RQI.From, RQI.To);
3572 if (!QueryCache.count(&PlainRQI)) {
3573 RQITy *RQIPtr =
new (
A.Allocator) RQITy(RQI.From, RQI.To);
3575 QueryVector.push_back(RQIPtr);
3576 QueryCache.insert(RQIPtr);
3581 if (IsTemporaryRQI && Result != RQITy::Reachable::Yes && UsedExclusionSet) {
3582 assert((!RQI.ExclusionSet || !RQI.ExclusionSet->empty()) &&
3583 "Did not expect empty set!");
3584 RQITy *RQIPtr =
new (
A.Allocator)
3585 RQITy(
A, *RQI.From, *RQI.To, RQI.ExclusionSet,
true);
3586 assert(RQIPtr->Result == RQITy::Reachable::No &&
"Already reachable?");
3588 assert(!QueryCache.count(RQIPtr));
3589 QueryVector.push_back(RQIPtr);
3590 QueryCache.insert(RQIPtr);
3593 if (Result == RQITy::Reachable::No && IsTemporaryRQI)
3594 A.registerForUpdate(*
this);
3595 return Result == RQITy::Reachable::Yes;
3598 const std::string getAsStr(Attributor *
A)
const override {
3600 return "#queries(" + std::to_string(QueryVector.size()) +
")";
3603 bool checkQueryCache(Attributor &
A, RQITy &StackRQI,
3604 typename RQITy::Reachable &Result) {
3605 if (!this->getState().isValidState()) {
3606 Result = RQITy::Reachable::Yes;
3612 if (StackRQI.ExclusionSet) {
3613 RQITy PlainRQI(StackRQI.From, StackRQI.To);
3614 auto It = QueryCache.find(&PlainRQI);
3615 if (It != QueryCache.end() && (*It)->Result == RQITy::Reachable::No) {
3616 Result = RQITy::Reachable::No;
3621 auto It = QueryCache.find(&StackRQI);
3622 if (It != QueryCache.end()) {
3629 QueryCache.insert(&StackRQI);
3635 DenseSet<RQITy *> QueryCache;
3638struct AAIntraFnReachabilityFunction final
3639 :
public CachedReachabilityAA<AAIntraFnReachability, Instruction> {
3640 using Base = CachedReachabilityAA<AAIntraFnReachability, Instruction>;
3641 AAIntraFnReachabilityFunction(
const IRPosition &IRP, Attributor &
A)
3643 DT =
A.getInfoCache().getAnalysisResultForFunction<DominatorTreeAnalysis>(
3647 bool isAssumedReachable(
3648 Attributor &
A,
const Instruction &From,
const Instruction &To,
3650 auto *NonConstThis =
const_cast<AAIntraFnReachabilityFunction *
>(
this);
3654 RQITy StackRQI(
A, From, To, ExclusionSet,
false);
3656 if (!NonConstThis->checkQueryCache(
A, StackRQI, Result))
3657 return NonConstThis->isReachableImpl(
A, StackRQI,
3659 return Result == RQITy::Reachable::Yes;
3666 A.getAAFor<AAIsDead>(*
this, getIRPosition(), DepClassTy::OPTIONAL);
3669 [&](
const auto &DeadEdge) {
3670 return LivenessAA->isEdgeDead(DeadEdge.first,
3674 return LivenessAA->isAssumedDead(BB);
3676 return ChangeStatus::UNCHANGED;
3680 return Base::updateImpl(
A);
3684 bool IsTemporaryRQI)
override {
3686 bool UsedExclusionSet =
false;
3691 while (IP && IP != &To) {
3692 if (ExclusionSet && IP != Origin && ExclusionSet->
count(IP)) {
3693 UsedExclusionSet =
true;
3701 const BasicBlock *FromBB = RQI.From->getParent();
3702 const BasicBlock *ToBB = RQI.To->getParent();
3704 "Not an intra-procedural query!");
3708 if (FromBB == ToBB &&
3709 WillReachInBlock(*RQI.From, *RQI.To, RQI.ExclusionSet))
3710 return rememberResult(
A, RQITy::Reachable::Yes, RQI, UsedExclusionSet,
3715 if (!WillReachInBlock(ToBB->
front(), *RQI.To, RQI.ExclusionSet))
3716 return rememberResult(
A, RQITy::Reachable::No, RQI, UsedExclusionSet,
3720 SmallPtrSet<const BasicBlock *, 16> ExclusionBlocks;
3721 if (RQI.ExclusionSet)
3722 for (
auto *
I : *RQI.ExclusionSet)
3723 if (
I->getFunction() == Fn)
3724 ExclusionBlocks.
insert(
I->getParent());
3727 if (ExclusionBlocks.
count(FromBB) &&
3730 return rememberResult(
A, RQITy::Reachable::No, RQI,
true, IsTemporaryRQI);
3733 A.getAAFor<AAIsDead>(*
this, getIRPosition(), DepClassTy::OPTIONAL);
3734 if (LivenessAA && LivenessAA->isAssumedDead(ToBB)) {
3735 DeadBlocks.insert(ToBB);
3736 return rememberResult(
A, RQITy::Reachable::No, RQI, UsedExclusionSet,
3740 SmallPtrSet<const BasicBlock *, 16> Visited;
3744 DenseSet<std::pair<const BasicBlock *, const BasicBlock *>> LocalDeadEdges;
3745 while (!Worklist.
empty()) {
3747 if (!Visited.
insert(BB).second)
3749 for (
const BasicBlock *SuccBB :
successors(BB)) {
3750 if (LivenessAA && LivenessAA->isEdgeDead(BB, SuccBB)) {
3751 LocalDeadEdges.
insert({BB, SuccBB});
3756 return rememberResult(
A, RQITy::Reachable::Yes, RQI, UsedExclusionSet,
3759 return rememberResult(
A, RQITy::Reachable::Yes, RQI, UsedExclusionSet,
3762 if (ExclusionBlocks.
count(SuccBB)) {
3763 UsedExclusionSet =
true;
3770 DeadEdges.insert_range(LocalDeadEdges);
3771 return rememberResult(
A, RQITy::Reachable::No, RQI, UsedExclusionSet,
3776 void trackStatistics()
const override {}
3781 DenseSet<const BasicBlock *> DeadBlocks;
3785 DenseSet<std::pair<const BasicBlock *, const BasicBlock *>> DeadEdges;
3788 const DominatorTree *DT =
nullptr;
3796 bool IgnoreSubsumingPositions) {
3797 assert(ImpliedAttributeKind == Attribute::NoAlias &&
3798 "Unexpected attribute kind");
3804 IgnoreSubsumingPositions =
true;
3815 if (
A.hasAttr(IRP, {Attribute::ByVal, Attribute::NoAlias},
3816 IgnoreSubsumingPositions, Attribute::NoAlias))
3826 "Noalias is a pointer attribute");
3829 const std::string getAsStr(
Attributor *
A)
const override {
3830 return getAssumed() ?
"noalias" :
"may-alias";
3835struct AANoAliasFloating final : AANoAliasImpl {
3836 AANoAliasFloating(
const IRPosition &IRP, Attributor &
A)
3837 : AANoAliasImpl(IRP,
A) {}
3842 return indicatePessimisticFixpoint();
3846 void trackStatistics()
const override {
3852struct AANoAliasArgument final
3853 : AAArgumentFromCallSiteArguments<AANoAlias, AANoAliasImpl> {
3854 using Base = AAArgumentFromCallSiteArguments<AANoAlias, AANoAliasImpl>;
3855 AANoAliasArgument(
const IRPosition &IRP, Attributor &
A) :
Base(IRP,
A) {}
3868 DepClassTy::OPTIONAL, IsKnownNoSycn))
3869 return Base::updateImpl(
A);
3874 return Base::updateImpl(
A);
3878 bool UsedAssumedInformation =
false;
3879 if (
A.checkForAllCallSites(
3880 [](AbstractCallSite ACS) { return !ACS.isCallbackCall(); }, *
this,
3881 true, UsedAssumedInformation))
3882 return Base::updateImpl(
A);
3890 return indicatePessimisticFixpoint();
3897struct AANoAliasCallSiteArgument final : AANoAliasImpl {
3898 AANoAliasCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
3899 : AANoAliasImpl(IRP,
A) {}
3903 bool mayAliasWithArgument(Attributor &
A, AAResults *&AAR,
3904 const AAMemoryBehavior &MemBehaviorAA,
3905 const CallBase &CB,
unsigned OtherArgNo) {
3907 if (this->getCallSiteArgNo() == (
int)OtherArgNo)
3915 auto *CBArgMemBehaviorAA =
A.getAAFor<AAMemoryBehavior>(
3919 if (CBArgMemBehaviorAA && CBArgMemBehaviorAA->isAssumedReadNone()) {
3920 A.recordDependence(*CBArgMemBehaviorAA, *
this, DepClassTy::OPTIONAL);
3927 if (CBArgMemBehaviorAA && CBArgMemBehaviorAA->isAssumedReadOnly() &&
3929 A.recordDependence(MemBehaviorAA, *
this, DepClassTy::OPTIONAL);
3930 A.recordDependence(*CBArgMemBehaviorAA, *
this, DepClassTy::OPTIONAL);
3936 AAR =
A.getInfoCache().getAnalysisResultForFunction<AAManager>(
3940 bool IsAliasing = !AAR || !AAR->
isNoAlias(&getAssociatedValue(), ArgOp);
3942 "callsite arguments: "
3943 << getAssociatedValue() <<
" " << *ArgOp <<
" => "
3944 << (IsAliasing ?
"" :
"no-") <<
"alias \n");
3949 bool isKnownNoAliasDueToNoAliasPreservation(
3950 Attributor &
A, AAResults *&AAR,
const AAMemoryBehavior &MemBehaviorAA) {
3963 auto UsePred = [&](
const Use &
U,
bool &Follow) ->
bool {
3979 bool IsKnownNoCapture;
3982 DepClassTy::OPTIONAL, IsKnownNoCapture))
3988 A, *UserI, *getCtxI(), *
this,
nullptr,
3989 [ScopeFn](
const Function &Fn) {
return &Fn != ScopeFn; }))
4004 LLVM_DEBUG(
dbgs() <<
"[AANoAliasCSArg] Unknown user: " << *UserI <<
"\n");
4008 bool IsKnownNoCapture;
4009 const AANoCapture *NoCaptureAA =
nullptr;
4011 A,
this, VIRP, DepClassTy::NONE, IsKnownNoCapture,
false, &NoCaptureAA);
4012 if (!IsAssumedNoCapture &&
4014 if (!
A.checkForAllUses(UsePred, *
this, getAssociatedValue())) {
4016 dbgs() <<
"[AANoAliasCSArg] " << getAssociatedValue()
4017 <<
" cannot be noalias as it is potentially captured\n");
4022 A.recordDependence(*NoCaptureAA, *
this, DepClassTy::OPTIONAL);
4028 for (
unsigned OtherArgNo = 0; OtherArgNo < CB.
arg_size(); OtherArgNo++)
4029 if (mayAliasWithArgument(
A, AAR, MemBehaviorAA, CB, OtherArgNo))
4039 auto *MemBehaviorAA =
4040 A.getAAFor<AAMemoryBehavior>(*
this, getIRPosition(), DepClassTy::NONE);
4042 A.recordDependence(*MemBehaviorAA, *
this, DepClassTy::OPTIONAL);
4043 return ChangeStatus::UNCHANGED;
4046 bool IsKnownNoAlias;
4049 A,
this, VIRP, DepClassTy::REQUIRED, IsKnownNoAlias)) {
4051 <<
" is not no-alias at the definition\n");
4052 return indicatePessimisticFixpoint();
4055 AAResults *AAR =
nullptr;
4056 if (MemBehaviorAA &&
4057 isKnownNoAliasDueToNoAliasPreservation(
A, AAR, *MemBehaviorAA)) {
4059 dbgs() <<
"[AANoAlias] No-Alias deduced via no-alias preservation\n");
4060 return ChangeStatus::UNCHANGED;
4063 return indicatePessimisticFixpoint();
4071struct AANoAliasReturned final : AANoAliasImpl {
4072 AANoAliasReturned(
const IRPosition &IRP, Attributor &
A)
4073 : AANoAliasImpl(IRP,
A) {}
4078 auto CheckReturnValue = [&](
Value &RV) ->
bool {
4089 bool IsKnownNoAlias;
4091 A,
this, RVPos, DepClassTy::REQUIRED, IsKnownNoAlias))
4094 bool IsKnownNoCapture;
4095 const AANoCapture *NoCaptureAA =
nullptr;
4097 A,
this, RVPos, DepClassTy::REQUIRED, IsKnownNoCapture,
false,
4099 return IsAssumedNoCapture ||
4103 if (!
A.checkForAllReturnedValues(CheckReturnValue, *
this))
4104 return indicatePessimisticFixpoint();
4106 return ChangeStatus::UNCHANGED;
4114struct AANoAliasCallSiteReturned final
4115 : AACalleeToCallSite<AANoAlias, AANoAliasImpl> {
4116 AANoAliasCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
4117 : AACalleeToCallSite<AANoAlias, AANoAliasImpl>(IRP,
A) {}
4127struct AAIsDeadValueImpl :
public AAIsDead {
4128 AAIsDeadValueImpl(
const IRPosition &IRP, Attributor &
A) : AAIsDead(IRP,
A) {}
4131 bool isAssumedDead()
const override {
return isAssumed(IS_DEAD); }
4134 bool isKnownDead()
const override {
return isKnown(IS_DEAD); }
4137 bool isAssumedDead(
const BasicBlock *BB)
const override {
return false; }
4140 bool isKnownDead(
const BasicBlock *BB)
const override {
return false; }
4143 bool isAssumedDead(
const Instruction *
I)
const override {
4144 return I == getCtxI() && isAssumedDead();
4148 bool isKnownDead(
const Instruction *
I)
const override {
4149 return isAssumedDead(
I) && isKnownDead();
4153 const std::string getAsStr(Attributor *
A)
const override {
4154 return isAssumedDead() ?
"assumed-dead" :
"assumed-live";
4158 bool areAllUsesAssumedDead(Attributor &
A,
Value &V) {
4160 if (
V.getType()->isVoidTy() ||
V.use_empty())
4166 if (!
A.isRunOn(*
I->getFunction()))
4168 bool UsedAssumedInformation =
false;
4169 std::optional<Constant *>
C =
4170 A.getAssumedConstant(V, *
this, UsedAssumedInformation);
4175 auto UsePred = [&](
const Use &
U,
bool &Follow) {
return false; };
4180 return A.checkForAllUses(UsePred, *
this, V,
false,
4181 DepClassTy::REQUIRED,
4186 bool isAssumedSideEffectFree(Attributor &
A, Instruction *
I) {
4190 if (!
I->isTerminator() && !
I->mayHaveSideEffects())
4199 bool IsKnownNoUnwind;
4201 A,
this, CallIRP, DepClassTy::OPTIONAL, IsKnownNoUnwind))
4209struct AAIsDeadFloating :
public AAIsDeadValueImpl {
4210 AAIsDeadFloating(
const IRPosition &IRP, Attributor &
A)
4211 : AAIsDeadValueImpl(IRP,
A) {}
4215 AAIsDeadValueImpl::initialize(
A);
4218 indicatePessimisticFixpoint();
4223 if (!isAssumedSideEffectFree(
A,
I)) {
4225 indicatePessimisticFixpoint();
4227 removeAssumedBits(HAS_NO_EFFECT);
4231 bool isDeadFence(Attributor &
A, FenceInst &FI) {
4232 const auto *ExecDomainAA =
A.lookupAAFor<AAExecutionDomain>(
4234 if (!ExecDomainAA || !ExecDomainAA->isNoOpFence(FI))
4236 A.recordDependence(*ExecDomainAA, *
this, DepClassTy::OPTIONAL);
4240 bool isDeadStore(Attributor &
A, StoreInst &SI,
4241 SmallSetVector<Instruction *, 8> *AssumeOnlyInst =
nullptr) {
4243 if (
SI.isVolatile())
4249 bool UsedAssumedInformation =
false;
4250 if (!AssumeOnlyInst) {
4251 PotentialCopies.clear();
4253 UsedAssumedInformation)) {
4256 <<
"[AAIsDead] Could not determine potential copies of store!\n");
4260 LLVM_DEBUG(
dbgs() <<
"[AAIsDead] Store has " << PotentialCopies.size()
4261 <<
" potential copies.\n");
4263 InformationCache &InfoCache =
A.getInfoCache();
4266 UsedAssumedInformation))
4270 auto &UserI = cast<Instruction>(*U.getUser());
4271 if (InfoCache.isOnlyUsedByAssume(UserI)) {
4273 AssumeOnlyInst->insert(&UserI);
4276 return A.isAssumedDead(U,
this,
nullptr, UsedAssumedInformation);
4282 <<
" is assumed live!\n");
4288 const std::string getAsStr(Attributor *
A)
const override {
4292 return "assumed-dead-store";
4295 return "assumed-dead-fence";
4296 return AAIsDeadValueImpl::getAsStr(
A);
4303 if (!isDeadStore(
A, *SI))
4304 return indicatePessimisticFixpoint();
4306 if (!isDeadFence(
A, *FI))
4307 return indicatePessimisticFixpoint();
4309 if (!isAssumedSideEffectFree(
A,
I))
4310 return indicatePessimisticFixpoint();
4311 if (!areAllUsesAssumedDead(
A, getAssociatedValue()))
4312 return indicatePessimisticFixpoint();
4317 bool isRemovableStore()
const override {
4318 return isAssumed(IS_REMOVABLE) &&
isa<StoreInst>(&getAssociatedValue());
4323 Value &
V = getAssociatedValue();
4330 SmallSetVector<Instruction *, 8> AssumeOnlyInst;
4331 bool IsDead = isDeadStore(
A, *SI, &AssumeOnlyInst);
4334 A.deleteAfterManifest(*
I);
4335 for (
size_t i = 0; i < AssumeOnlyInst.
size(); ++i) {
4337 for (
auto *Usr : AOI->
users())
4339 A.deleteAfterManifest(*AOI);
4345 A.deleteAfterManifest(*FI);
4348 if (isAssumedSideEffectFree(
A,
I) && !
I->isTerminator()) {
4349 A.deleteAfterManifest(*
I);
4357 void trackStatistics()
const override {
4363 SmallSetVector<Value *, 4> PotentialCopies;
4366struct AAIsDeadArgument :
public AAIsDeadFloating {
4367 AAIsDeadArgument(
const IRPosition &IRP, Attributor &
A)
4368 : AAIsDeadFloating(IRP,
A) {}
4372 Argument &Arg = *getAssociatedArgument();
4373 if (
A.isValidFunctionSignatureRewrite(Arg, {}))
4374 if (
A.registerFunctionSignatureRewrite(
4378 return ChangeStatus::CHANGED;
4380 return ChangeStatus::UNCHANGED;
4387struct AAIsDeadCallSiteArgument :
public AAIsDeadValueImpl {
4388 AAIsDeadCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
4389 : AAIsDeadValueImpl(IRP,
A) {}
4393 AAIsDeadValueImpl::initialize(
A);
4395 indicatePessimisticFixpoint();
4404 Argument *Arg = getAssociatedArgument();
4406 return indicatePessimisticFixpoint();
4408 auto *ArgAA =
A.getAAFor<AAIsDead>(*
this, ArgPos, DepClassTy::REQUIRED);
4410 return indicatePessimisticFixpoint();
4419 "Expected undef values to be filtered out!");
4421 if (
A.changeUseAfterManifest(U, UV))
4422 return ChangeStatus::CHANGED;
4423 return ChangeStatus::UNCHANGED;
4430struct AAIsDeadCallSiteReturned :
public AAIsDeadFloating {
4431 AAIsDeadCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
4432 : AAIsDeadFloating(IRP,
A) {}
4435 bool isAssumedDead()
const override {
4436 return AAIsDeadFloating::isAssumedDead() && IsAssumedSideEffectFree;
4441 AAIsDeadFloating::initialize(
A);
4443 indicatePessimisticFixpoint();
4448 IsAssumedSideEffectFree = isAssumedSideEffectFree(
A, getCtxI());
4454 if (IsAssumedSideEffectFree && !isAssumedSideEffectFree(
A, getCtxI())) {
4455 IsAssumedSideEffectFree =
false;
4456 Changed = ChangeStatus::CHANGED;
4458 if (!areAllUsesAssumedDead(
A, getAssociatedValue()))
4459 return indicatePessimisticFixpoint();
4464 void trackStatistics()
const override {
4465 if (IsAssumedSideEffectFree)
4472 const std::string getAsStr(Attributor *
A)
const override {
4473 return isAssumedDead()
4475 : (getAssumed() ?
"assumed-dead-users" :
"assumed-live");
4479 bool IsAssumedSideEffectFree =
true;
4482struct AAIsDeadReturned :
public AAIsDeadValueImpl {
4483 AAIsDeadReturned(
const IRPosition &IRP, Attributor &
A)
4484 : AAIsDeadValueImpl(IRP,
A) {}
4489 bool UsedAssumedInformation =
false;
4490 A.checkForAllInstructions([](Instruction &) {
return true; }, *
this,
4491 {Instruction::Ret}, UsedAssumedInformation);
4493 auto PredForCallSite = [&](AbstractCallSite ACS) {
4494 if (ACS.isCallbackCall() || !ACS.getInstruction())
4496 return areAllUsesAssumedDead(
A, *ACS.getInstruction());
4499 if (!
A.checkForAllCallSites(PredForCallSite, *
this,
true,
4500 UsedAssumedInformation))
4501 return indicatePessimisticFixpoint();
4503 return ChangeStatus::UNCHANGED;
4509 bool AnyChange =
false;
4510 UndefValue &UV = *
UndefValue::get(getAssociatedFunction()->getReturnType());
4517 bool UsedAssumedInformation =
false;
4518 A.checkForAllInstructions(RetInstPred, *
this, {Instruction::Ret},
4519 UsedAssumedInformation);
4520 return AnyChange ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
4527struct AAIsDeadFunction :
public AAIsDead {
4528 AAIsDeadFunction(
const IRPosition &IRP, Attributor &
A) : AAIsDead(IRP,
A) {}
4533 assert(
F &&
"Did expect an anchor function");
4534 if (!isAssumedDeadInternalFunction(
A)) {
4535 ToBeExploredFrom.insert(&
F->getEntryBlock().front());
4536 assumeLive(
A,
F->getEntryBlock());
4540 bool isAssumedDeadInternalFunction(Attributor &
A) {
4541 if (!getAnchorScope()->hasLocalLinkage())
4547 if (!
A.shouldUpdateAA<AAIsDead>(getIRPosition()))
4549 bool UsedAssumedInformation =
false;
4550 return A.checkForAllCallSites([](AbstractCallSite) {
return false; }, *
this,
4551 true, UsedAssumedInformation);
4555 const std::string getAsStr(Attributor *
A)
const override {
4556 return "Live[#BB " + std::to_string(AssumedLiveBlocks.size()) +
"/" +
4557 std::to_string(getAnchorScope()->
size()) +
"][#TBEP " +
4558 std::to_string(ToBeExploredFrom.size()) +
"][#KDE " +
4559 std::to_string(KnownDeadEnds.size()) +
"]";
4564 assert(getState().isValidState() &&
4565 "Attempted to manifest an invalid state!");
4570 if (AssumedLiveBlocks.empty()) {
4571 A.deleteAfterManifest(
F);
4572 return ChangeStatus::CHANGED;
4578 bool Invoke2CallAllowed = !mayCatchAsynchronousExceptions(
F);
4580 KnownDeadEnds.set_union(ToBeExploredFrom);
4581 for (
const Instruction *DeadEndI : KnownDeadEnds) {
4585 bool IsKnownNoReturn;
4593 A.registerInvokeWithDeadSuccessor(
const_cast<InvokeInst &
>(*
II));
4595 A.changeToUnreachableAfterManifest(
4596 const_cast<Instruction *
>(DeadEndI->getNextNode()));
4597 HasChanged = ChangeStatus::CHANGED;
4600 STATS_DECL(AAIsDead, BasicBlock,
"Number of dead basic blocks deleted.");
4601 for (BasicBlock &BB :
F)
4602 if (!AssumedLiveBlocks.count(&BB)) {
4603 A.deleteAfterManifest(BB);
4605 HasChanged = ChangeStatus::CHANGED;
4614 bool isEdgeDead(
const BasicBlock *From,
const BasicBlock *To)
const override {
4617 "Used AAIsDead of the wrong function");
4618 return isValidState() && !AssumedLiveEdges.count(std::make_pair(From, To));
4622 void trackStatistics()
const override {}
4625 bool isAssumedDead()
const override {
return false; }
4628 bool isKnownDead()
const override {
return false; }
4631 bool isAssumedDead(
const BasicBlock *BB)
const override {
4633 "BB must be in the same anchor scope function.");
4637 return !AssumedLiveBlocks.count(BB);
4641 bool isKnownDead(
const BasicBlock *BB)
const override {
4642 return getKnown() && isAssumedDead(BB);
4646 bool isAssumedDead(
const Instruction *
I)
const override {
4647 assert(
I->getParent()->getParent() == getAnchorScope() &&
4648 "Instruction must be in the same anchor scope function.");
4655 if (!AssumedLiveBlocks.count(
I->getParent()))
4661 if (KnownDeadEnds.count(PrevI) || ToBeExploredFrom.count(PrevI))
4669 bool isKnownDead(
const Instruction *
I)
const override {
4670 return getKnown() && isAssumedDead(
I);
4675 bool assumeLive(Attributor &
A,
const BasicBlock &BB) {
4676 if (!AssumedLiveBlocks.insert(&BB).second)
4679 if (!
A.isDuringDeduction())
4686 for (
const Instruction &
I : BB)
4689 if (
F->hasLocalLinkage()) {
4691 dbgs() <<
"[AAIsDead] Seeding live internal callee ";
4692 F->printAsOperand(
dbgs(),
false);
4694 BB.getParent()->printAsOperand(
dbgs(),
false);
4697 A.markLiveInternalFunction(*
F);
4704 SmallSetVector<const Instruction *, 8> ToBeExploredFrom;
4707 SmallSetVector<const Instruction *, 8> KnownDeadEnds;
4710 DenseSet<std::pair<const BasicBlock *, const BasicBlock *>> AssumedLiveEdges;
4713 DenseSet<const BasicBlock *> AssumedLiveBlocks;
4717identifyAliveSuccessors(Attributor &
A,
const CallBase &CB,
4718 AbstractAttribute &AA,
4719 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4722 bool IsKnownNoReturn;
4725 return !IsKnownNoReturn;
4734identifyAliveSuccessors(Attributor &
A,
const InvokeInst &
II,
4735 AbstractAttribute &AA,
4736 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4737 bool UsedAssumedInformation =
4743 if (AAIsDeadFunction::mayCatchAsynchronousExceptions(*
II.getFunction())) {
4744 AliveSuccessors.
push_back(&
II.getUnwindDest()->front());
4748 bool IsKnownNoUnwind;
4751 UsedAssumedInformation |= !IsKnownNoUnwind;
4753 AliveSuccessors.
push_back(&
II.getUnwindDest()->front());
4756 return UsedAssumedInformation;
4760identifyAliveSuccessors(Attributor &,
const UncondBrInst &BI,
4761 AbstractAttribute &,
4762 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4768identifyAliveSuccessors(Attributor &
A,
const CondBrInst &BI,
4769 AbstractAttribute &AA,
4770 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4771 bool UsedAssumedInformation =
false;
4772 std::optional<Constant *>
C =
4773 A.getAssumedConstant(*BI.
getCondition(), AA, UsedAssumedInformation);
4783 UsedAssumedInformation =
false;
4785 return UsedAssumedInformation;
4789identifyAliveSuccessors(Attributor &
A,
const SwitchInst &SI,
4790 AbstractAttribute &AA,
4791 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4792 bool UsedAssumedInformation =
false;
4796 UsedAssumedInformation)) {
4798 for (
const BasicBlock *SuccBB :
successors(
SI.getParent()))
4807 return UsedAssumedInformation;
4810 Type &Ty = *
SI.getCondition()->getType();
4811 SmallPtrSet<ConstantInt *, 8>
Constants;
4812 auto CheckForConstantInt = [&](
Value *
V) {
4821 return CheckForConstantInt(VAC.
getValue());
4823 for (
const BasicBlock *SuccBB :
successors(
SI.getParent()))
4825 return UsedAssumedInformation;
4828 unsigned MatchedCases = 0;
4829 for (
const auto &CaseIt :
SI.cases()) {
4830 if (
Constants.count(CaseIt.getCaseValue())) {
4832 AliveSuccessors.
push_back(&CaseIt.getCaseSuccessor()->front());
4839 AliveSuccessors.
push_back(&
SI.getDefaultDest()->front());
4840 return UsedAssumedInformation;
4846 if (AssumedLiveBlocks.empty()) {
4847 if (isAssumedDeadInternalFunction(
A))
4851 ToBeExploredFrom.insert(&
F->getEntryBlock().front());
4852 assumeLive(
A,
F->getEntryBlock());
4856 LLVM_DEBUG(
dbgs() <<
"[AAIsDead] Live [" << AssumedLiveBlocks.size() <<
"/"
4857 << getAnchorScope()->
size() <<
"] BBs and "
4858 << ToBeExploredFrom.size() <<
" exploration points and "
4859 << KnownDeadEnds.size() <<
" known dead ends\n");
4864 ToBeExploredFrom.end());
4865 decltype(ToBeExploredFrom) NewToBeExploredFrom;
4868 while (!Worklist.
empty()) {
4875 I =
I->getNextNode();
4877 AliveSuccessors.
clear();
4879 bool UsedAssumedInformation =
false;
4880 switch (
I->getOpcode()) {
4884 "Expected non-terminators to be handled already!");
4885 for (
const BasicBlock *SuccBB :
successors(
I->getParent()))
4888 case Instruction::Call:
4890 *
this, AliveSuccessors);
4892 case Instruction::Invoke:
4894 *
this, AliveSuccessors);
4896 case Instruction::UncondBr:
4897 UsedAssumedInformation = identifyAliveSuccessors(
4900 case Instruction::CondBr:
4902 *
this, AliveSuccessors);
4904 case Instruction::Switch:
4906 *
this, AliveSuccessors);
4910 if (UsedAssumedInformation) {
4911 NewToBeExploredFrom.insert(
I);
4912 }
else if (AliveSuccessors.
empty() ||
4913 (
I->isTerminator() &&
4914 AliveSuccessors.
size() <
I->getNumSuccessors())) {
4915 if (KnownDeadEnds.insert(
I))
4920 << AliveSuccessors.
size() <<
" UsedAssumedInformation: "
4921 << UsedAssumedInformation <<
"\n");
4923 for (
const Instruction *AliveSuccessor : AliveSuccessors) {
4924 if (!
I->isTerminator()) {
4925 assert(AliveSuccessors.size() == 1 &&
4926 "Non-terminator expected to have a single successor!");
4930 auto Edge = std::make_pair(
I->getParent(), AliveSuccessor->getParent());
4931 if (AssumedLiveEdges.insert(
Edge).second)
4933 if (assumeLive(
A, *AliveSuccessor->getParent()))
4940 if (NewToBeExploredFrom.size() != ToBeExploredFrom.size() ||
4941 llvm::any_of(NewToBeExploredFrom, [&](
const Instruction *
I) {
4942 return !ToBeExploredFrom.count(I);
4945 ToBeExploredFrom = std::move(NewToBeExploredFrom);
4954 if (ToBeExploredFrom.empty() &&
4955 getAnchorScope()->
size() == AssumedLiveBlocks.size() &&
4956 llvm::all_of(KnownDeadEnds, [](
const Instruction *DeadEndI) {
4957 return DeadEndI->isTerminator() && DeadEndI->getNumSuccessors() == 0;
4959 return indicatePessimisticFixpoint();
4964struct AAIsDeadCallSite final : AAIsDeadFunction {
4965 AAIsDeadCallSite(
const IRPosition &IRP, Attributor &
A)
4966 : AAIsDeadFunction(IRP,
A) {}
4975 "supported for call sites yet!");
4980 return indicatePessimisticFixpoint();
4984 void trackStatistics()
const override {}
4991struct AADereferenceableImpl : AADereferenceable {
4992 AADereferenceableImpl(
const IRPosition &IRP, Attributor &
A)
4993 : AADereferenceable(IRP,
A) {}
4994 using StateType = DerefState;
4998 Value &
V = *getAssociatedValue().stripPointerCasts();
5000 A.getAttrs(getIRPosition(),
5001 {Attribute::Dereferenceable, Attribute::DereferenceableOrNull},
5004 takeKnownDerefBytesMaximum(Attr.getValueAsInt());
5007 bool IsKnownNonNull;
5009 A,
this, getIRPosition(), DepClassTy::OPTIONAL, IsKnownNonNull);
5012 takeKnownDerefBytesMaximum(
V.getPointerDereferenceableBytes(
5013 A.getDataLayout(), CanBeNull,
nullptr));
5015 if (Instruction *CtxI = getCtxI())
5016 followUsesInMBEC(*
this,
A, getState(), *CtxI);
5021 StateType &getState()
override {
return *
this; }
5022 const StateType &getState()
const override {
return *
this; }
5026 void addAccessedBytesForUse(Attributor &
A,
const Use *U,
const Instruction *
I,
5027 DerefState &State) {
5028 const Value *UseV =
U->get();
5033 if (!Loc || Loc->Ptr != UseV || !Loc->Size.isPrecise() ||
I->isVolatile())
5038 Loc->Ptr,
Offset,
A.getDataLayout(),
true);
5039 if (
Base &&
Base == &getAssociatedValue())
5040 State.addAccessedBytes(
Offset, Loc->Size.getValue());
5044 bool followUseInMBEC(Attributor &
A,
const Use *U,
const Instruction *
I,
5045 AADereferenceable::StateType &State) {
5046 bool IsNonNull =
false;
5047 bool TrackUse =
false;
5048 int64_t DerefBytes = getKnownNonNullAndDerefBytesForUse(
5049 A, *
this, getAssociatedValue(), U,
I, IsNonNull, TrackUse);
5050 LLVM_DEBUG(
dbgs() <<
"[AADereferenceable] Deref bytes: " << DerefBytes
5051 <<
" for instruction " << *
I <<
"\n");
5053 addAccessedBytesForUse(
A, U,
I, State);
5054 State.takeKnownDerefBytesMaximum(DerefBytes);
5061 bool IsKnownNonNull;
5063 A,
this, getIRPosition(), DepClassTy::NONE, IsKnownNonNull);
5064 if (IsAssumedNonNull &&
5065 A.hasAttr(getIRPosition(), Attribute::DereferenceableOrNull)) {
5066 A.removeAttrs(getIRPosition(), {Attribute::DereferenceableOrNull});
5067 return ChangeStatus::CHANGED;
5072 void getDeducedAttributes(Attributor &
A, LLVMContext &Ctx,
5073 SmallVectorImpl<Attribute> &Attrs)
const override {
5075 bool IsKnownNonNull;
5077 A,
this, getIRPosition(), DepClassTy::NONE, IsKnownNonNull);
5078 if (IsAssumedNonNull)
5079 Attrs.emplace_back(Attribute::getWithDereferenceableBytes(
5080 Ctx, getAssumedDereferenceableBytes()));
5082 Attrs.emplace_back(Attribute::getWithDereferenceableOrNullBytes(
5083 Ctx, getAssumedDereferenceableBytes()));
5087 const std::string getAsStr(Attributor *
A)
const override {
5088 if (!getAssumedDereferenceableBytes())
5089 return "unknown-dereferenceable";
5090 bool IsKnownNonNull;
5091 bool IsAssumedNonNull =
false;
5094 *
A,
this, getIRPosition(), DepClassTy::NONE, IsKnownNonNull);
5095 return std::string(
"dereferenceable") +
5096 (IsAssumedNonNull ?
"" :
"_or_null") +
5097 (isAssumedGlobal() ?
"_globally" :
"") +
"<" +
5098 std::to_string(getKnownDereferenceableBytes()) +
"-" +
5099 std::to_string(getAssumedDereferenceableBytes()) +
">" +
5100 (!
A ?
" [non-null is unknown]" :
"");
5105struct AADereferenceableFloating : AADereferenceableImpl {
5106 AADereferenceableFloating(
const IRPosition &IRP, Attributor &
A)
5107 : AADereferenceableImpl(IRP,
A) {}
5112 bool UsedAssumedInformation =
false;
5114 if (!
A.getAssumedSimplifiedValues(getIRPosition(), *
this,
Values,
5116 Values.push_back({getAssociatedValue(), getCtxI()});
5119 Stripped =
Values.size() != 1 ||
5120 Values.front().getValue() != &getAssociatedValue();
5123 const DataLayout &
DL =
A.getDataLayout();
5126 auto VisitValueCB = [&](
const Value &
V) ->
bool {
5128 DL.getIndexSizeInBits(
V.getType()->getPointerAddressSpace());
5129 APInt
Offset(IdxWidth, 0);
5134 const auto *AA =
A.getAAFor<AADereferenceable>(
5136 int64_t DerefBytes = 0;
5137 if (!AA || (!Stripped &&
this == AA)) {
5141 DerefBytes =
Base->getPointerDereferenceableBytes(
5142 DL, CanBeNull,
nullptr);
5143 T.GlobalState.indicatePessimisticFixpoint();
5146 DerefBytes =
DS.DerefBytesState.getAssumed();
5147 T.GlobalState &=
DS.GlobalState;
5153 int64_t OffsetSExt =
Offset.getSExtValue();
5157 T.takeAssumedDerefBytesMinimum(
5158 std::max(int64_t(0), DerefBytes - OffsetSExt));
5163 T.takeKnownDerefBytesMaximum(
5164 std::max(int64_t(0), DerefBytes - OffsetSExt));
5165 T.indicatePessimisticFixpoint();
5166 }
else if (OffsetSExt > 0) {
5172 T.indicatePessimisticFixpoint();
5176 return T.isValidState();
5179 for (
const auto &VAC :
Values)
5180 if (!VisitValueCB(*VAC.
getValue()))
5181 return indicatePessimisticFixpoint();
5187 void trackStatistics()
const override {
5193struct AADereferenceableReturned final
5194 : AAReturnedFromReturnedValues<AADereferenceable, AADereferenceableImpl> {
5196 AAReturnedFromReturnedValues<AADereferenceable, AADereferenceableImpl>;
5197 AADereferenceableReturned(
const IRPosition &IRP, Attributor &
A)
5201 void trackStatistics()
const override {
5207struct AADereferenceableArgument final
5208 : AAArgumentFromCallSiteArguments<AADereferenceable,
5209 AADereferenceableImpl> {
5211 AAArgumentFromCallSiteArguments<AADereferenceable, AADereferenceableImpl>;
5212 AADereferenceableArgument(
const IRPosition &IRP, Attributor &
A)
5216 void trackStatistics()
const override {
5222struct AADereferenceableCallSiteArgument final : AADereferenceableFloating {
5223 AADereferenceableCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
5224 : AADereferenceableFloating(IRP,
A) {}
5227 void trackStatistics()
const override {
5233struct AADereferenceableCallSiteReturned final
5234 : AACalleeToCallSite<AADereferenceable, AADereferenceableImpl> {
5235 using Base = AACalleeToCallSite<AADereferenceable, AADereferenceableImpl>;
5236 AADereferenceableCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
5240 void trackStatistics()
const override {
5250static unsigned getKnownAlignForUse(Attributor &
A, AAAlign &QueryingAA,
5251 Value &AssociatedValue,
const Use *U,
5252 const Instruction *
I,
bool &TrackUse) {
5261 if (
GEP->hasAllConstantIndices())
5266 switch (
II->getIntrinsicID()) {
5267 case Intrinsic::ptrmask: {
5269 const auto *ConstVals =
A.getAAFor<AAPotentialConstantValues>(
5271 const auto *AlignAA =
A.getAAFor<AAAlign>(
5273 if (ConstVals && ConstVals->isValidState() && ConstVals->isAtFixpoint()) {
5274 unsigned ShiftValue = std::min(ConstVals->getAssumedMinTrailingZeros(),
5277 if (ConstAlign >= AlignAA->getKnownAlign())
5278 return Align(1).value();
5281 return AlignAA->getKnownAlign().
value();
5284 case Intrinsic::amdgcn_make_buffer_rsrc: {
5285 const auto *AlignAA =
A.getAAFor<AAAlign>(
5288 return AlignAA->getKnownAlign().
value();
5306 MA = MaybeAlign(AlignAA->getKnownAlign());
5309 const DataLayout &
DL =
A.getDataLayout();
5310 const Value *UseV =
U->get();
5312 if (
SI->getPointerOperand() == UseV)
5313 MA =
SI->getAlign();
5315 if (LI->getPointerOperand() == UseV)
5316 MA = LI->getAlign();
5318 if (AI->getPointerOperand() == UseV)
5319 MA = AI->getAlign();
5321 if (AI->getPointerOperand() == UseV)
5322 MA = AI->getAlign();
5332 if (
Base == &AssociatedValue) {
5337 uint32_t
gcd = std::gcd(uint32_t(
abs((int32_t)
Offset)), Alignment);
5345struct AAAlignImpl : AAAlign {
5346 AAAlignImpl(
const IRPosition &IRP, Attributor &
A) : AAAlign(IRP,
A) {}
5351 A.getAttrs(getIRPosition(), {Attribute::Alignment},
Attrs);
5353 takeKnownMaximum(Attr.getValueAsInt());
5355 Value &
V = *getAssociatedValue().stripPointerCasts();
5356 takeKnownMaximum(
V.getPointerAlignment(
A.getDataLayout()).value());
5358 if (Instruction *CtxI = getCtxI())
5359 followUsesInMBEC(*
this,
A, getState(), *CtxI);
5367 Value &AssociatedValue = getAssociatedValue();
5369 return ChangeStatus::UNCHANGED;
5371 for (
const Use &U : AssociatedValue.
uses()) {
5373 if (
SI->getPointerOperand() == &AssociatedValue)
5374 if (
SI->getAlign() < getAssumedAlign()) {
5376 "Number of times alignment added to a store");
5377 SI->setAlignment(getAssumedAlign());
5378 InstrChanged = ChangeStatus::CHANGED;
5381 if (LI->getPointerOperand() == &AssociatedValue)
5382 if (LI->getAlign() < getAssumedAlign()) {
5383 LI->setAlignment(getAssumedAlign());
5385 "Number of times alignment added to a load");
5386 InstrChanged = ChangeStatus::CHANGED;
5389 if (RMW->getPointerOperand() == &AssociatedValue) {
5390 if (RMW->getAlign() < getAssumedAlign()) {
5392 "Number of times alignment added to atomicrmw");
5394 RMW->setAlignment(getAssumedAlign());
5395 InstrChanged = ChangeStatus::CHANGED;
5399 if (CAS->getPointerOperand() == &AssociatedValue) {
5400 if (CAS->getAlign() < getAssumedAlign()) {
5402 "Number of times alignment added to cmpxchg");
5403 CAS->setAlignment(getAssumedAlign());
5404 InstrChanged = ChangeStatus::CHANGED;
5412 Align InheritAlign =
5413 getAssociatedValue().getPointerAlignment(
A.getDataLayout());
5414 if (InheritAlign >= getAssumedAlign())
5415 return InstrChanged;
5416 return Changed | InstrChanged;
5424 void getDeducedAttributes(Attributor &
A, LLVMContext &Ctx,
5425 SmallVectorImpl<Attribute> &Attrs)
const override {
5426 if (getAssumedAlign() > 1)
5428 Attribute::getWithAlignment(Ctx,
Align(getAssumedAlign())));
5432 bool followUseInMBEC(Attributor &
A,
const Use *U,
const Instruction *
I,
5433 AAAlign::StateType &State) {
5434 bool TrackUse =
false;
5436 unsigned int KnownAlign =
5437 getKnownAlignForUse(
A, *
this, getAssociatedValue(), U,
I, TrackUse);
5438 State.takeKnownMaximum(KnownAlign);
5444 const std::string getAsStr(Attributor *
A)
const override {
5445 return "align<" + std::to_string(getKnownAlign().value()) +
"-" +
5446 std::to_string(getAssumedAlign().value()) +
">";
5451struct AAAlignFloating : AAAlignImpl {
5452 AAAlignFloating(
const IRPosition &IRP, Attributor &
A) : AAAlignImpl(IRP,
A) {}
5456 const DataLayout &
DL =
A.getDataLayout();
5459 bool UsedAssumedInformation =
false;
5461 if (!
A.getAssumedSimplifiedValues(getIRPosition(), *
this,
Values,
5463 Values.push_back({getAssociatedValue(), getCtxI()});
5466 Stripped =
Values.size() != 1 ||
5467 Values.front().getValue() != &getAssociatedValue();
5471 auto VisitValueCB = [&](
Value &
V) ->
bool {
5475 DepClassTy::REQUIRED);
5476 if (!AA || (!Stripped &&
this == AA)) {
5494 T.takeKnownMaximum(Alignment);
5495 T.indicatePessimisticFixpoint();
5498 const AAAlign::StateType &
DS = AA->
getState();
5501 return T.isValidState();
5504 for (
const auto &VAC :
Values) {
5505 if (!VisitValueCB(*VAC.
getValue()))
5506 return indicatePessimisticFixpoint();
5519struct AAAlignReturned final
5520 : AAReturnedFromReturnedValues<AAAlign, AAAlignImpl> {
5521 using Base = AAReturnedFromReturnedValues<AAAlign, AAAlignImpl>;
5522 AAAlignReturned(
const IRPosition &IRP, Attributor &
A) :
Base(IRP,
A) {}
5529struct AAAlignArgument final
5530 : AAArgumentFromCallSiteArguments<AAAlign, AAAlignImpl> {
5531 using Base = AAArgumentFromCallSiteArguments<AAAlign, AAAlignImpl>;
5532 AAAlignArgument(
const IRPosition &IRP, Attributor &
A) :
Base(IRP,
A) {}
5539 if (
A.getInfoCache().isInvolvedInMustTailCall(*getAssociatedArgument()))
5540 return ChangeStatus::UNCHANGED;
5541 return Base::manifest(
A);
5548struct AAAlignCallSiteArgument final : AAAlignFloating {
5549 AAAlignCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
5550 : AAAlignFloating(IRP,
A) {}
5557 if (Argument *Arg = getAssociatedArgument())
5558 if (
A.getInfoCache().isInvolvedInMustTailCall(*Arg))
5559 return ChangeStatus::UNCHANGED;
5561 Align InheritAlign =
5562 getAssociatedValue().getPointerAlignment(
A.getDataLayout());
5563 if (InheritAlign >= getAssumedAlign())
5564 Changed = ChangeStatus::UNCHANGED;
5571 if (Argument *Arg = getAssociatedArgument()) {
5574 const auto *ArgAlignAA =
A.getAAFor<AAAlign>(
5577 takeKnownMaximum(ArgAlignAA->getKnownAlign().value());
5587struct AAAlignCallSiteReturned final
5588 : AACalleeToCallSite<AAAlign, AAAlignImpl> {
5589 using Base = AACalleeToCallSite<AAAlign, AAAlignImpl>;
5590 AAAlignCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
5596 switch (
II->getIntrinsicID()) {
5597 case Intrinsic::ptrmask: {
5601 const auto *ConstVals =
A.getAAFor<AAPotentialConstantValues>(
5603 if (ConstVals && ConstVals->isValidState()) {
5604 unsigned ShiftValue =
5605 std::min(ConstVals->getAssumedMinTrailingZeros(),
5606 Value::MaxAlignmentExponent);
5611 const auto *AlignAA =
5613 DepClassTy::REQUIRED);
5615 Alignment = std::max(AlignAA->getAssumedAlign(), Alignment);
5622 std::min(this->getAssumedAlign(), Alignment).value());
5628 case Intrinsic::amdgcn_make_buffer_rsrc: {
5629 const auto *AlignAA =
5631 DepClassTy::REQUIRED);
5634 this->getState(), AlignAA->getAssumedAlign().
value());
5641 return Base::updateImpl(
A);
5650struct AANoReturnImpl :
public AANoReturn {
5651 AANoReturnImpl(
const IRPosition &IRP, Attributor &
A) : AANoReturn(IRP,
A) {}
5657 A,
nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));
5662 const std::string getAsStr(Attributor *
A)
const override {
5663 return getAssumed() ?
"noreturn" :
"may-return";
5668 auto CheckForNoReturn = [](
Instruction &) {
return false; };
5669 bool UsedAssumedInformation =
false;
5670 if (!
A.checkForAllInstructions(CheckForNoReturn, *
this,
5671 {(unsigned)Instruction::Ret},
5672 UsedAssumedInformation))
5673 return indicatePessimisticFixpoint();
5674 return ChangeStatus::UNCHANGED;
5678struct AANoReturnFunction final : AANoReturnImpl {
5679 AANoReturnFunction(
const IRPosition &IRP, Attributor &
A)
5680 : AANoReturnImpl(IRP,
A) {}
5687struct AANoReturnCallSite final
5688 : AACalleeToCallSite<AANoReturn, AANoReturnImpl> {
5689 AANoReturnCallSite(
const IRPosition &IRP, Attributor &
A)
5690 : AACalleeToCallSite<AANoReturn, AANoReturnImpl>(IRP,
A) {}
5701struct AAInstanceInfoImpl :
public AAInstanceInfo {
5702 AAInstanceInfoImpl(
const IRPosition &IRP, Attributor &
A)
5703 : AAInstanceInfo(IRP,
A) {}
5707 Value &
V = getAssociatedValue();
5709 if (
C->isThreadDependent())
5710 indicatePessimisticFixpoint();
5712 indicateOptimisticFixpoint();
5718 indicateOptimisticFixpoint();
5723 A.getInfoCache().getAnalysisResultForFunction<CycleAnalysis>(
5726 indicatePessimisticFixpoint();
5736 Value &
V = getAssociatedValue();
5739 Scope =
I->getFunction();
5742 if (!
Scope->hasLocalLinkage())
5746 return indicateOptimisticFixpoint();
5748 bool IsKnownNoRecurse;
5754 auto UsePred = [&](
const Use &
U,
bool &Follow) {
5769 if (!Callee || !
Callee->hasLocalLinkage())
5773 const auto *ArgInstanceInfoAA =
A.getAAFor<AAInstanceInfo>(
5775 DepClassTy::OPTIONAL);
5776 if (!ArgInstanceInfoAA ||
5777 !ArgInstanceInfoAA->isAssumedUniqueForAnalysis())
5782 A, *CB, *Scope, *
this,
nullptr,
5790 auto EquivalentUseCB = [&](
const Use &OldU,
const Use &NewU) {
5792 auto *Ptr =
SI->getPointerOperand()->stripPointerCasts();
5800 if (!
A.checkForAllUses(UsePred, *
this, V,
true,
5801 DepClassTy::OPTIONAL,
5802 true, EquivalentUseCB))
5803 return indicatePessimisticFixpoint();
5809 const std::string getAsStr(Attributor *
A)
const override {
5810 return isAssumedUniqueForAnalysis() ?
"<unique [fAa]>" :
"<unknown>";
5814 void trackStatistics()
const override {}
5818struct AAInstanceInfoFloating : AAInstanceInfoImpl {
5819 AAInstanceInfoFloating(
const IRPosition &IRP, Attributor &
A)
5820 : AAInstanceInfoImpl(IRP,
A) {}
5824struct AAInstanceInfoArgument final : AAInstanceInfoFloating {
5825 AAInstanceInfoArgument(
const IRPosition &IRP, Attributor &
A)
5826 : AAInstanceInfoFloating(IRP,
A) {}
5830struct AAInstanceInfoCallSiteArgument final : AAInstanceInfoImpl {
5831 AAInstanceInfoCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
5832 : AAInstanceInfoImpl(IRP,
A) {}
5840 Argument *Arg = getAssociatedArgument();
5842 return indicatePessimisticFixpoint();
5845 A.getAAFor<AAInstanceInfo>(*
this, ArgPos, DepClassTy::REQUIRED);
5847 return indicatePessimisticFixpoint();
5853struct AAInstanceInfoReturned final : AAInstanceInfoImpl {
5854 AAInstanceInfoReturned(
const IRPosition &IRP, Attributor &
A)
5855 : AAInstanceInfoImpl(IRP,
A) {
5871struct AAInstanceInfoCallSiteReturned final : AAInstanceInfoFloating {
5872 AAInstanceInfoCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
5873 : AAInstanceInfoFloating(IRP,
A) {}
5880 bool IgnoreSubsumingPositions) {
5881 assert(ImpliedAttributeKind == Attribute::Captures &&
5882 "Unexpected attribute kind");
5896 A.getAttrs(IRP, {Attribute::Captures}, Attrs,
5906 {Attribute::Captures, Attribute::ByVal}, Attrs,
5944 bool NoThrow =
F.doesNotThrow();
5945 bool IsVoidReturn =
F.getReturnType()->isVoidTy();
5946 if (
ReadOnly && NoThrow && IsVoidReturn) {
5959 if (NoThrow && IsVoidReturn)
5964 if (!NoThrow || ArgNo < 0 ||
5965 !
F.getAttributes().hasAttrSomewhere(Attribute::Returned))
5968 for (
unsigned U = 0, E =
F.arg_size(); U < E; ++U)
5969 if (
F.hasParamAttribute(U, Attribute::Returned)) {
5970 if (U ==
unsigned(ArgNo))
5997 void getDeducedAttributes(Attributor &
A, LLVMContext &Ctx,
5998 SmallVectorImpl<Attribute> &Attrs)
const override {
5999 if (!isAssumedNoCaptureMaybeReturned())
6002 if (isArgumentPosition()) {
6003 if (isAssumedNoCapture())
6004 Attrs.emplace_back(Attribute::get(Ctx, Attribute::Captures));
6006 Attrs.emplace_back(Attribute::get(Ctx,
"no-capture-maybe-returned"));
6011 const std::string getAsStr(Attributor *
A)
const override {
6012 if (isKnownNoCapture())
6013 return "known not-captured";
6014 if (isAssumedNoCapture())
6015 return "assumed not-captured";
6016 if (isKnownNoCaptureMaybeReturned())
6017 return "known not-captured-maybe-returned";
6018 if (isAssumedNoCaptureMaybeReturned())
6019 return "assumed not-captured-maybe-returned";
6020 return "assumed-captured";
6025 bool checkUse(Attributor &
A, AANoCapture::StateType &State,
const Use &U,
6028 LLVM_DEBUG(
dbgs() <<
"[AANoCapture] Check use: " << *
U.get() <<
" in "
6034 return isCapturedIn(State,
true,
true,
6041 return isCapturedIn(State,
true,
true,
6047 return isCapturedIn(State,
false,
false,
6049 return isCapturedIn(State,
true,
true,
6057 return isCapturedIn(State,
true,
true,
6064 bool IsKnownNoCapture;
6065 const AANoCapture *ArgNoCaptureAA =
nullptr;
6067 A,
this, CSArgPos, DepClassTy::REQUIRED, IsKnownNoCapture,
false,
6069 if (IsAssumedNoCapture)
6070 return isCapturedIn(State,
false,
false,
6074 return isCapturedIn(State,
false,
false,
6079 return isCapturedIn(State,
true,
true,
6086 static bool isCapturedIn(AANoCapture::StateType &State,
bool CapturedInMem,
6087 bool CapturedInInt,
bool CapturedInRet) {
6088 LLVM_DEBUG(
dbgs() <<
" - captures [Mem " << CapturedInMem <<
"|Int "
6089 << CapturedInInt <<
"|Ret " << CapturedInRet <<
"]\n");
6101 const IRPosition &IRP = getIRPosition();
6105 return indicatePessimisticFixpoint();
6112 return indicatePessimisticFixpoint();
6120 T.addKnownBits(NOT_CAPTURED_IN_MEM);
6122 addKnownBits(NOT_CAPTURED_IN_MEM);
6129 auto CheckReturnedArgs = [&](
bool &UsedAssumedInformation) {
6133 UsedAssumedInformation))
6135 bool SeenConstant =
false;
6136 for (
const AA::ValueAndContext &VAC :
Values) {
6140 SeenConstant =
true;
6142 VAC.
getValue() == getAssociatedArgument())
6148 bool IsKnownNoUnwind;
6151 bool IsVoidTy =
F->getReturnType()->isVoidTy();
6152 bool UsedAssumedInformation =
false;
6153 if (IsVoidTy || CheckReturnedArgs(UsedAssumedInformation)) {
6154 T.addKnownBits(NOT_CAPTURED_IN_RET);
6155 if (
T.isKnown(NOT_CAPTURED_IN_MEM))
6157 if (IsKnownNoUnwind && (IsVoidTy || !UsedAssumedInformation)) {
6158 addKnownBits(NOT_CAPTURED_IN_RET);
6159 if (isKnown(NOT_CAPTURED_IN_MEM))
6160 return indicateOptimisticFixpoint();
6165 auto UseCheck = [&](
const Use &
U,
bool &Follow) ->
bool {
6174 return checkUse(
A,
T, U, Follow);
6177 if (!
A.checkForAllUses(UseCheck, *
this, *V))
6178 return indicatePessimisticFixpoint();
6181 auto Assumed = S.getAssumed();
6182 S.intersectAssumedBits(
T.getAssumed());
6183 if (!isAssumedNoCaptureMaybeReturned())
6184 return indicatePessimisticFixpoint();
6190struct AANoCaptureArgument final : AANoCaptureImpl {
6191 AANoCaptureArgument(
const IRPosition &IRP, Attributor &
A)
6192 : AANoCaptureImpl(IRP,
A) {}
6199struct AANoCaptureCallSiteArgument final : AANoCaptureImpl {
6200 AANoCaptureCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
6201 : AANoCaptureImpl(IRP,
A) {}
6209 Argument *Arg = getAssociatedArgument();
6211 return indicatePessimisticFixpoint();
6213 bool IsKnownNoCapture;
6214 const AANoCapture *ArgAA =
nullptr;
6216 A,
this, ArgPos, DepClassTy::REQUIRED, IsKnownNoCapture,
false,
6218 return ChangeStatus::UNCHANGED;
6220 return indicatePessimisticFixpoint();
6225 void trackStatistics()
const override {
6231struct AANoCaptureFloating final : AANoCaptureImpl {
6232 AANoCaptureFloating(
const IRPosition &IRP, Attributor &
A)
6233 : AANoCaptureImpl(IRP,
A) {}
6236 void trackStatistics()
const override {
6242struct AANoCaptureReturned final : AANoCaptureImpl {
6243 AANoCaptureReturned(
const IRPosition &IRP, Attributor &
A)
6244 : AANoCaptureImpl(IRP,
A) {
6259 void trackStatistics()
const override {}
6263struct AANoCaptureCallSiteReturned final : AANoCaptureImpl {
6264 AANoCaptureCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
6265 : AANoCaptureImpl(IRP,
A) {}
6271 determineFunctionCaptureCapabilities(getIRPosition(), *
F, *
this);
6275 void trackStatistics()
const override {
6292 dbgs() <<
"[ValueSimplify] is assumed to be "
6295 dbgs() <<
"[ValueSimplify] is assumed to be <none>\n";
6307 if (getAssociatedValue().
getType()->isVoidTy())
6308 indicatePessimisticFixpoint();
6309 if (
A.hasSimplificationCallback(getIRPosition()))
6310 indicatePessimisticFixpoint();
6314 const std::string getAsStr(Attributor *
A)
const override {
6316 dbgs() <<
"SAV: " << (bool)SimplifiedAssociatedValue <<
" ";
6317 if (SimplifiedAssociatedValue && *SimplifiedAssociatedValue)
6318 dbgs() <<
"SAV: " << **SimplifiedAssociatedValue <<
" ";
6320 return isValidState() ? (isAtFixpoint() ?
"simplified" :
"maybe-simple")
6325 void trackStatistics()
const override {}
6328 std::optional<Value *>
6329 getAssumedSimplifiedValue(Attributor &
A)
const override {
6330 return SimplifiedAssociatedValue;
6337 static Value *ensureType(Attributor &
A,
Value &V,
Type &Ty, Instruction *CtxI,
6341 if (CtxI &&
V.getType()->canLosslesslyBitCastTo(&Ty))
6343 : BitCastInst::CreatePointerBitCastOrAddrSpaceCast(
6352 static Value *reproduceInst(Attributor &
A,
6353 const AbstractAttribute &QueryingAA,
6354 Instruction &
I,
Type &Ty, Instruction *CtxI,
6356 assert(CtxI &&
"Cannot reproduce an instruction without context!");
6357 if (
Check && (
I.mayReadFromMemory() ||
6362 Value *NewOp = reproduceValue(
A, QueryingAA, *
Op, Ty, CtxI,
Check, VMap);
6364 assert(
Check &&
"Manifest of new value unexpectedly failed!");
6386 static Value *reproduceValue(Attributor &
A,
6387 const AbstractAttribute &QueryingAA,
Value &V,
6388 Type &Ty, Instruction *CtxI,
bool Check,
6390 if (
const auto &NewV = VMap.
lookup(&V))
6392 bool UsedAssumedInformation =
false;
6393 std::optional<Value *> SimpleV =
A.getAssumedSimplified(
6395 if (!SimpleV.has_value())
6399 EffectiveV = *SimpleV;
6404 return ensureType(
A, *EffectiveV, Ty, CtxI,
Check);
6406 if (
Value *NewV = reproduceInst(
A, QueryingAA, *
I, Ty, CtxI,
Check, VMap))
6407 return ensureType(
A, *NewV, Ty, CtxI,
Check);
6413 Value *manifestReplacementValue(Attributor &
A, Instruction *CtxI)
const {
6414 Value *NewV = SimplifiedAssociatedValue
6415 ? *SimplifiedAssociatedValue
6417 if (NewV && NewV != &getAssociatedValue()) {
6421 if (reproduceValue(
A, *
this, *NewV, *getAssociatedType(), CtxI,
6423 return reproduceValue(
A, *
this, *NewV, *getAssociatedType(), CtxI,
6431 bool checkAndUpdate(Attributor &
A,
const AbstractAttribute &QueryingAA,
6432 const IRPosition &IRP,
bool Simplify =
true) {
6433 bool UsedAssumedInformation =
false;
6436 QueryingValueSimplified =
A.getAssumedSimplified(
6438 return unionAssumed(QueryingValueSimplified);
6442 template <
typename AAType>
bool askSimplifiedValueFor(Attributor &
A) {
6443 if (!getAssociatedValue().
getType()->isIntegerTy())
6448 A.getAAFor<AAType>(*
this, getIRPosition(), DepClassTy::NONE);
6452 std::optional<Constant *> COpt = AA->getAssumedConstant(
A);
6455 SimplifiedAssociatedValue = std::nullopt;
6456 A.recordDependence(*AA, *
this, DepClassTy::OPTIONAL);
6459 if (
auto *
C = *COpt) {
6460 SimplifiedAssociatedValue =
C;
6461 A.recordDependence(*AA, *
this, DepClassTy::OPTIONAL);
6467 bool askSimplifiedValueForOtherAAs(Attributor &
A) {
6468 if (askSimplifiedValueFor<AAValueConstantRange>(
A))
6470 if (askSimplifiedValueFor<AAPotentialConstantValues>(
A))
6478 for (
auto &U : getAssociatedValue().uses()) {
6483 IP =
PHI->getIncomingBlock(U)->getTerminator();
6484 if (
auto *NewV = manifestReplacementValue(
A, IP)) {
6486 <<
" -> " << *NewV <<
" :: " << *
this <<
"\n");
6487 if (
A.changeUseAfterManifest(U, *NewV))
6488 Changed = ChangeStatus::CHANGED;
6492 return Changed | AAValueSimplify::manifest(
A);
6497 SimplifiedAssociatedValue = &getAssociatedValue();
6498 return AAValueSimplify::indicatePessimisticFixpoint();
6502struct AAValueSimplifyArgument final : AAValueSimplifyImpl {
6503 AAValueSimplifyArgument(
const IRPosition &IRP, Attributor &
A)
6504 : AAValueSimplifyImpl(IRP,
A) {}
6507 AAValueSimplifyImpl::initialize(
A);
6508 if (
A.hasAttr(getIRPosition(),
6509 {Attribute::InAlloca, Attribute::Preallocated,
6510 Attribute::StructRet, Attribute::Nest, Attribute::ByVal},
6512 indicatePessimisticFixpoint();
6519 Argument *Arg = getAssociatedArgument();
6525 return indicatePessimisticFixpoint();
6528 auto Before = SimplifiedAssociatedValue;
6530 auto PredForCallSite = [&](AbstractCallSite ACS) {
6531 const IRPosition &ACSArgPos =
6542 bool UsedAssumedInformation =
false;
6543 std::optional<Constant *> SimpleArgOp =
6544 A.getAssumedConstant(ACSArgPos, *
this, UsedAssumedInformation);
6551 return unionAssumed(*SimpleArgOp);
6556 bool UsedAssumedInformation =
false;
6557 if (hasCallBaseContext() &&
6558 getCallBaseContext()->getCalledOperand() == Arg->
getParent())
6560 AbstractCallSite(&getCallBaseContext()->getCalledOperandUse()));
6562 Success =
A.checkForAllCallSites(PredForCallSite, *
this,
true,
6563 UsedAssumedInformation);
6566 if (!askSimplifiedValueForOtherAAs(
A))
6567 return indicatePessimisticFixpoint();
6570 return Before == SimplifiedAssociatedValue ? ChangeStatus::UNCHANGED
6571 : ChangeStatus ::CHANGED;
6575 void trackStatistics()
const override {
6580struct AAValueSimplifyReturned : AAValueSimplifyImpl {
6581 AAValueSimplifyReturned(
const IRPosition &IRP, Attributor &
A)
6582 : AAValueSimplifyImpl(IRP,
A) {}
6585 std::optional<Value *>
6586 getAssumedSimplifiedValue(Attributor &
A)
const override {
6587 if (!isValidState())
6589 return SimplifiedAssociatedValue;
6594 auto Before = SimplifiedAssociatedValue;
6598 return checkAndUpdate(
6603 bool UsedAssumedInformation =
false;
6604 if (!
A.checkForAllInstructions(ReturnInstCB, *
this, {Instruction::Ret},
6605 UsedAssumedInformation))
6606 if (!askSimplifiedValueForOtherAAs(
A))
6607 return indicatePessimisticFixpoint();
6610 return Before == SimplifiedAssociatedValue ? ChangeStatus::UNCHANGED
6611 : ChangeStatus ::CHANGED;
6617 return ChangeStatus::UNCHANGED;
6621 void trackStatistics()
const override {
6626struct AAValueSimplifyFloating : AAValueSimplifyImpl {
6627 AAValueSimplifyFloating(
const IRPosition &IRP, Attributor &
A)
6628 : AAValueSimplifyImpl(IRP,
A) {}
6632 AAValueSimplifyImpl::initialize(
A);
6633 Value &
V = getAnchorValue();
6637 indicatePessimisticFixpoint();
6642 auto Before = SimplifiedAssociatedValue;
6643 if (!askSimplifiedValueForOtherAAs(
A))
6644 return indicatePessimisticFixpoint();
6647 return Before == SimplifiedAssociatedValue ? ChangeStatus::UNCHANGED
6648 : ChangeStatus ::CHANGED;
6652 void trackStatistics()
const override {
6657struct AAValueSimplifyFunction : AAValueSimplifyImpl {
6658 AAValueSimplifyFunction(
const IRPosition &IRP, Attributor &
A)
6659 : AAValueSimplifyImpl(IRP,
A) {}
6663 SimplifiedAssociatedValue =
nullptr;
6664 indicateOptimisticFixpoint();
6669 "AAValueSimplify(Function|CallSite)::updateImpl will not be called");
6672 void trackStatistics()
const override {
6677struct AAValueSimplifyCallSite : AAValueSimplifyFunction {
6678 AAValueSimplifyCallSite(
const IRPosition &IRP, Attributor &
A)
6679 : AAValueSimplifyFunction(IRP,
A) {}
6681 void trackStatistics()
const override {
6686struct AAValueSimplifyCallSiteReturned : AAValueSimplifyImpl {
6687 AAValueSimplifyCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
6688 : AAValueSimplifyImpl(IRP,
A) {}
6691 AAValueSimplifyImpl::initialize(
A);
6692 Function *Fn = getAssociatedFunction();
6693 assert(Fn &&
"Did expect an associted function");
6694 for (Argument &Arg : Fn->
args()) {
6699 checkAndUpdate(
A, *
this, IRP))
6700 indicateOptimisticFixpoint();
6702 indicatePessimisticFixpoint();
6710 return indicatePessimisticFixpoint();
6713 void trackStatistics()
const override {
6718struct AAValueSimplifyCallSiteArgument : AAValueSimplifyFloating {
6719 AAValueSimplifyCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
6720 : AAValueSimplifyFloating(IRP,
A) {}
6726 auto *FloatAA =
A.lookupAAFor<AAValueSimplify>(
6728 if (FloatAA && FloatAA->getState().isValidState())
6731 if (
auto *NewV = manifestReplacementValue(
A, getCtxI())) {
6733 ->getArgOperandUse(getCallSiteArgNo());
6734 if (
A.changeUseAfterManifest(U, *NewV))
6735 Changed = ChangeStatus::CHANGED;
6738 return Changed | AAValueSimplify::manifest(
A);
6741 void trackStatistics()
const override {
6749struct AAHeapToStackFunction final :
public AAHeapToStack {
6751 static bool isGlobalizedLocal(
const CallBase &CB) {
6753 return A.
isValid() &&
A.getValueAsString() ==
"__kmpc_alloc_shared";
6756 struct AllocationInfo {
6761 bool IsGlobalizedLocal =
false;
6768 } Status = STACK_DUE_TO_USE;
6772 bool HasPotentiallyFreeingUnknownUses =
false;
6776 bool MoveAllocaIntoEntry =
true;
6779 SmallSetVector<CallBase *, 1> PotentialFreeCalls{};
6782 struct DeallocationInfo {
6790 bool MightFreeUnknownObjects =
false;
6793 SmallSetVector<CallBase *, 1> PotentialAllocationCalls{};
6796 AAHeapToStackFunction(
const IRPosition &IRP, Attributor &
A)
6797 : AAHeapToStack(IRP,
A) {}
6799 ~AAHeapToStackFunction()
override {
6802 for (
auto &It : AllocationInfos)
6803 It.second->~AllocationInfo();
6804 for (
auto &It : DeallocationInfos)
6805 It.second->~DeallocationInfo();
6809 AAHeapToStack::initialize(
A);
6812 const auto *TLI =
A.getInfoCache().getTargetLibraryInfoForFunction(*
F);
6819 DeallocationInfos[CB] =
new (
A.Allocator) DeallocationInfo{CB, FreedOp};
6826 auto *I8Ty = Type::getInt8Ty(CB->
getParent()->getContext());
6828 AllocationInfo *AI =
new (
A.Allocator) AllocationInfo{CB};
6829 AllocationInfos[CB] = AI;
6830 AI->IsGlobalizedLocal = isGlobalizedLocal(*CB);
6836 bool UsedAssumedInformation =
false;
6837 bool Success =
A.checkForAllCallLikeInstructions(
6838 AllocationIdentifierCB, *
this, UsedAssumedInformation,
6842 assert(
Success &&
"Did not expect the call base visit callback to fail!");
6845 [](
const IRPosition &,
const AbstractAttribute *,
6846 bool &) -> std::optional<Value *> {
return nullptr; };
6847 for (
const auto &It : AllocationInfos)
6850 for (
const auto &It : DeallocationInfos)
6855 const std::string getAsStr(Attributor *
A)
const override {
6856 unsigned NumH2SMallocs = 0, NumInvalidMallocs = 0;
6857 for (
const auto &It : AllocationInfos) {
6858 if (It.second->Status == AllocationInfo::INVALID)
6859 ++NumInvalidMallocs;
6863 return "[H2S] Mallocs Good/Bad: " + std::to_string(NumH2SMallocs) +
"/" +
6864 std::to_string(NumInvalidMallocs);
6868 void trackStatistics()
const override {
6871 "Number of malloc/calloc/aligned_alloc calls converted to allocas");
6872 for (
const auto &It : AllocationInfos)
6873 if (It.second->Status != AllocationInfo::INVALID)
6877 bool isAssumedHeapToStack(
const CallBase &CB)
const override {
6879 if (AllocationInfo *AI =
6880 AllocationInfos.lookup(
const_cast<CallBase *
>(&CB)))
6881 return AI->Status != AllocationInfo::INVALID;
6885 bool isAssumedHeapToStackRemovedFree(CallBase &CB)
const override {
6886 if (!isValidState())
6889 for (
const auto &It : AllocationInfos) {
6890 AllocationInfo &AI = *It.second;
6891 if (AI.Status == AllocationInfo::INVALID)
6894 if (AI.PotentialFreeCalls.count(&CB))
6902 assert(getState().isValidState() &&
6903 "Attempted to manifest an invalid state!");
6907 const auto *TLI =
A.getInfoCache().getTargetLibraryInfoForFunction(*
F);
6909 for (
auto &It : AllocationInfos) {
6910 AllocationInfo &AI = *It.second;
6911 if (AI.Status == AllocationInfo::INVALID)
6914 for (CallBase *FreeCall : AI.PotentialFreeCalls) {
6915 LLVM_DEBUG(
dbgs() <<
"H2S: Removing free call: " << *FreeCall <<
"\n");
6916 A.deleteAfterManifest(*FreeCall);
6917 HasChanged = ChangeStatus::CHANGED;
6920 LLVM_DEBUG(
dbgs() <<
"H2S: Removing malloc-like call: " << *AI.CB
6923 auto Remark = [&](OptimizationRemark
OR) {
6924 if (AI.IsGlobalizedLocal)
6925 return OR <<
"Moving globalized variable to the stack.";
6926 return OR <<
"Moving memory allocation from the heap to the stack.";
6928 if (AI.IsGlobalizedLocal)
6929 A.emitRemark<OptimizationRemark>(AI.CB,
"OMP110",
Remark);
6931 A.emitRemark<OptimizationRemark>(AI.CB,
"HeapToStack",
Remark);
6933 const DataLayout &
DL =
A.getInfoCache().getDL();
6935 std::optional<APInt> SizeAPI =
getSize(
A, *
this, AI);
6937 Size = ConstantInt::get(AI.CB->getContext(), *SizeAPI);
6939 ObjectSizeOpts Opts;
6940 ObjectSizeOffsetEvaluator Eval(*AI.CB->getModule(), TLI, Opts);
6941 SizeOffsetValue SizeOffsetPair = Eval.compute(AI.CB);
6948 ?
F->getEntryBlock().begin()
6949 : AI.CB->getIterator();
6952 if (MaybeAlign RetAlign = AI.CB->getRetAlign())
6953 Alignment = std::max(Alignment, *RetAlign);
6955 std::optional<APInt> AlignmentAPI = getAPInt(
A, *
this, *Align);
6956 assert(AlignmentAPI && AlignmentAPI->getZExtValue() > 0 &&
6957 "Expected an alignment during manifest!");
6959 std::max(Alignment,
assumeAligned(AlignmentAPI->getZExtValue()));
6963 unsigned AS =
DL.getAllocaAddrSpace();
6965 new AllocaInst(Type::getInt8Ty(
F->getContext()), AS,
Size, Alignment,
6966 AI.CB->getName() +
".h2s", IP);
6968 if (Alloca->
getType() != AI.CB->getType())
6969 Alloca = BitCastInst::CreatePointerBitCastOrAddrSpaceCast(
6970 Alloca, AI.CB->getType(),
"malloc_cast", AI.CB->getIterator());
6972 auto *I8Ty = Type::getInt8Ty(
F->getContext());
6975 "Must be able to materialize initial memory state of allocation");
6980 auto *NBB =
II->getNormalDest();
6982 A.deleteAfterManifest(*AI.CB);
6984 A.deleteAfterManifest(*AI.CB);
6993 Builder.CreateMemSet(Alloca, InitVal,
Size, std::nullopt);
6995 HasChanged = ChangeStatus::CHANGED;
7001 std::optional<APInt> getAPInt(Attributor &
A,
const AbstractAttribute &AA,
7003 bool UsedAssumedInformation =
false;
7004 std::optional<Constant *> SimpleV =
7005 A.getAssumedConstant(V, AA, UsedAssumedInformation);
7007 return APInt(64, 0);
7009 return CI->getValue();
7010 return std::nullopt;
7013 std::optional<APInt>
getSize(Attributor &
A,
const AbstractAttribute &AA,
7014 AllocationInfo &AI) {
7016 bool UsedAssumedInformation =
false;
7017 if (std::optional<Constant *> SimpleV =
7018 A.getAssumedConstant(*V, AA, UsedAssumedInformation))
7025 const auto *TLI =
A.getInfoCache().getTargetLibraryInfoForFunction(*
F);
7031 MapVector<CallBase *, AllocationInfo *> AllocationInfos;
7035 MapVector<CallBase *, DeallocationInfo *> DeallocationInfos;
7040ChangeStatus AAHeapToStackFunction::updateImpl(Attributor &
A) {
7043 const auto *TLI =
A.getInfoCache().getTargetLibraryInfoForFunction(*
F);
7045 const auto *LivenessAA =
7048 MustBeExecutedContextExplorer *Explorer =
7049 A.getInfoCache().getMustBeExecutedContextExplorer();
7051 bool StackIsAccessibleByOtherThreads =
7052 A.getInfoCache().stackIsAccessibleByOtherThreads();
7055 A.getInfoCache().getAnalysisResultForFunction<LoopAnalysis>(*F);
7056 std::optional<bool> MayContainIrreducibleControl;
7058 if (&
F->getEntryBlock() == &BB)
7060 if (!MayContainIrreducibleControl.has_value())
7062 if (*MayContainIrreducibleControl)
7071 bool HasUpdatedFrees =
false;
7073 auto UpdateFrees = [&]() {
7074 HasUpdatedFrees =
true;
7076 for (
auto &It : DeallocationInfos) {
7077 DeallocationInfo &DI = *It.second;
7080 if (DI.MightFreeUnknownObjects)
7084 bool UsedAssumedInformation =
false;
7085 if (
A.isAssumedDead(*DI.CB,
this, LivenessAA, UsedAssumedInformation,
7092 LLVM_DEBUG(
dbgs() <<
"[H2S] Unknown underlying object for free!\n");
7093 DI.MightFreeUnknownObjects =
true;
7106 DI.MightFreeUnknownObjects =
true;
7110 AllocationInfo *AI = AllocationInfos.lookup(ObjCB);
7112 LLVM_DEBUG(
dbgs() <<
"[H2S] Free of a non-allocation object: " << *Obj
7114 DI.MightFreeUnknownObjects =
true;
7118 DI.PotentialAllocationCalls.insert(ObjCB);
7122 auto FreeCheck = [&](AllocationInfo &AI) {
7126 if (!StackIsAccessibleByOtherThreads) {
7131 dbgs() <<
"[H2S] found an escaping use, stack is not accessible by "
7132 "other threads and function is not nosync:\n");
7136 if (!HasUpdatedFrees)
7140 if (AI.PotentialFreeCalls.size() != 1) {
7142 << AI.PotentialFreeCalls.size() <<
"\n");
7145 CallBase *UniqueFree = *AI.PotentialFreeCalls.begin();
7146 DeallocationInfo *DI = DeallocationInfos.lookup(UniqueFree);
7149 dbgs() <<
"[H2S] unique free call was not known as deallocation call "
7150 << *UniqueFree <<
"\n");
7153 if (DI->MightFreeUnknownObjects) {
7155 dbgs() <<
"[H2S] unique free call might free unknown allocations\n");
7158 if (DI->PotentialAllocationCalls.empty())
7160 if (DI->PotentialAllocationCalls.size() > 1) {
7162 << DI->PotentialAllocationCalls.size()
7163 <<
" different allocations\n");
7166 if (*DI->PotentialAllocationCalls.begin() != AI.CB) {
7169 <<
"[H2S] unique free call not known to free this allocation but "
7170 << **DI->PotentialAllocationCalls.begin() <<
"\n");
7175 if (!AI.IsGlobalizedLocal) {
7177 if (!Explorer || !Explorer->findInContextOf(UniqueFree, CtxI)) {
7178 LLVM_DEBUG(
dbgs() <<
"[H2S] unique free call might not be executed "
7179 "with the allocation "
7180 << *UniqueFree <<
"\n");
7187 auto UsesCheck = [&](AllocationInfo &AI) {
7188 bool ValidUsesOnly =
true;
7190 auto Pred = [&](
const Use &
U,
bool &Follow) ->
bool {
7195 if (
SI->getValueOperand() ==
U.get()) {
7197 <<
"[H2S] escaping store to memory: " << *UserI <<
"\n");
7198 ValidUsesOnly =
false;
7207 if (DeallocationInfos.count(CB)) {
7208 AI.PotentialFreeCalls.insert(CB);
7215 bool IsKnownNoCapture;
7224 if (!IsAssumedNoCapture ||
7225 (!AI.IsGlobalizedLocal && !IsAssumedNoFree)) {
7226 AI.HasPotentiallyFreeingUnknownUses |= !IsAssumedNoFree;
7229 auto Remark = [&](OptimizationRemarkMissed ORM) {
7231 <<
"Could not move globalized variable to the stack. "
7232 "Variable is potentially captured in call. Mark "
7233 "parameter as `__attribute__((noescape))` to override.";
7236 if (ValidUsesOnly && AI.IsGlobalizedLocal)
7237 A.emitRemark<OptimizationRemarkMissed>(CB,
"OMP113",
Remark);
7240 ValidUsesOnly =
false;
7253 ValidUsesOnly =
false;
7256 if (!
A.checkForAllUses(Pred, *
this, *AI.CB,
false,
7258 [&](
const Use &OldU,
const Use &NewU) {
7259 auto *SI = dyn_cast<StoreInst>(OldU.getUser());
7260 return !SI || StackIsAccessibleByOtherThreads ||
7261 AA::isAssumedThreadLocalObject(
7262 A, *SI->getPointerOperand(), *this);
7265 return ValidUsesOnly;
7270 for (
auto &It : AllocationInfos) {
7271 AllocationInfo &AI = *It.second;
7272 if (AI.Status == AllocationInfo::INVALID)
7276 std::optional<APInt> APAlign = getAPInt(
A, *
this, *Align);
7280 LLVM_DEBUG(
dbgs() <<
"[H2S] Unknown allocation alignment: " << *AI.CB
7282 AI.Status = AllocationInfo::INVALID;
7287 !APAlign->isPowerOf2()) {
7288 LLVM_DEBUG(
dbgs() <<
"[H2S] Invalid allocation alignment: " << APAlign
7290 AI.Status = AllocationInfo::INVALID;
7301 dbgs() <<
"[H2S] Unknown allocation size: " << *AI.CB <<
"\n";
7303 dbgs() <<
"[H2S] Allocation size too large: " << *AI.CB <<
" vs. "
7307 AI.Status = AllocationInfo::INVALID;
7313 switch (AI.Status) {
7314 case AllocationInfo::STACK_DUE_TO_USE:
7317 AI.Status = AllocationInfo::STACK_DUE_TO_FREE;
7319 case AllocationInfo::STACK_DUE_TO_FREE:
7322 AI.Status = AllocationInfo::INVALID;
7325 case AllocationInfo::INVALID:
7332 bool IsGlobalizedLocal = AI.IsGlobalizedLocal;
7333 if (AI.MoveAllocaIntoEntry &&
7334 (!
Size.has_value() ||
7335 (!IsGlobalizedLocal && IsInLoop(*AI.CB->getParent()))))
7336 AI.MoveAllocaIntoEntry =
false;
7345struct AAPrivatizablePtrImpl :
public AAPrivatizablePtr {
7346 AAPrivatizablePtrImpl(
const IRPosition &IRP, Attributor &
A)
7347 : AAPrivatizablePtr(IRP,
A), PrivatizableType(std::nullopt) {}
7350 AAPrivatizablePtr::indicatePessimisticFixpoint();
7351 PrivatizableType =
nullptr;
7352 return ChangeStatus::CHANGED;
7358 virtual std::optional<Type *> identifyPrivatizableType(Attributor &
A) = 0;
7362 std::optional<Type *> combineTypes(std::optional<Type *> T0,
7363 std::optional<Type *>
T1) {
7373 std::optional<Type *> getPrivatizableType()
const override {
7374 return PrivatizableType;
7377 const std::string getAsStr(Attributor *
A)
const override {
7378 return isAssumedPrivatizablePtr() ?
"[priv]" :
"[no-priv]";
7382 std::optional<Type *> PrivatizableType;
7387struct AAPrivatizablePtrArgument final :
public AAPrivatizablePtrImpl {
7388 AAPrivatizablePtrArgument(
const IRPosition &IRP, Attributor &
A)
7389 : AAPrivatizablePtrImpl(IRP,
A) {}
7392 std::optional<Type *> identifyPrivatizableType(Attributor &
A)
override {
7395 bool UsedAssumedInformation =
false;
7397 A.getAttrs(getIRPosition(), {Attribute::ByVal},
Attrs,
7399 if (!
Attrs.empty() &&
7400 A.checkForAllCallSites([](AbstractCallSite ACS) { return true; }, *
this,
7401 true, UsedAssumedInformation))
7402 return Attrs[0].getValueAsType();
7404 std::optional<Type *> Ty;
7405 unsigned ArgNo = getIRPosition().getCallSiteArgNo();
7413 auto CallSiteCheck = [&](AbstractCallSite ACS) {
7422 A.getAAFor<AAPrivatizablePtr>(*
this, ACSArgPos, DepClassTy::REQUIRED);
7425 std::optional<Type *> CSTy = PrivCSArgAA->getPrivatizableType();
7428 dbgs() <<
"[AAPrivatizablePtr] ACSPos: " << ACSArgPos <<
", CSTy: ";
7432 dbgs() <<
"<nullptr>";
7437 Ty = combineTypes(Ty, CSTy);
7440 dbgs() <<
" : New Type: ";
7442 (*Ty)->print(
dbgs());
7444 dbgs() <<
"<nullptr>";
7453 if (!
A.checkForAllCallSites(CallSiteCheck, *
this,
true,
7454 UsedAssumedInformation))
7461 PrivatizableType = identifyPrivatizableType(
A);
7462 if (!PrivatizableType)
7463 return ChangeStatus::UNCHANGED;
7464 if (!*PrivatizableType)
7465 return indicatePessimisticFixpoint();
7470 DepClassTy::OPTIONAL);
7473 if (!
A.hasAttr(getIRPosition(), Attribute::ByVal) &&
7476 return indicatePessimisticFixpoint();
7482 identifyReplacementTypes(*PrivatizableType, ReplacementTypes);
7486 Function &Fn = *getIRPosition().getAnchorScope();
7488 A.getInfoCache().getAnalysisResultForFunction<TargetIRAnalysis>(Fn);
7490 LLVM_DEBUG(
dbgs() <<
"[AAPrivatizablePtr] Missing TTI for function "
7492 return indicatePessimisticFixpoint();
7495 auto CallSiteCheck = [&](AbstractCallSite ACS) {
7502 bool UsedAssumedInformation =
false;
7503 if (!
A.checkForAllCallSites(CallSiteCheck, *
this,
true,
7504 UsedAssumedInformation)) {
7506 dbgs() <<
"[AAPrivatizablePtr] ABI incompatibility detected for "
7508 return indicatePessimisticFixpoint();
7512 Argument *Arg = getAssociatedArgument();
7513 if (!
A.isValidFunctionSignatureRewrite(*Arg, ReplacementTypes)) {
7515 return indicatePessimisticFixpoint();
7522 auto IsCompatiblePrivArgOfCallback = [&](CallBase &CB) {
7525 for (
const Use *U : CallbackUses) {
7526 AbstractCallSite CBACS(U);
7527 assert(CBACS && CBACS.isCallbackCall());
7528 for (Argument &CBArg : CBACS.getCalledFunction()->args()) {
7529 int CBArgNo = CBACS.getCallArgOperandNo(CBArg);
7533 <<
"[AAPrivatizablePtr] Argument " << *Arg
7534 <<
"check if can be privatized in the context of its parent ("
7536 <<
")\n[AAPrivatizablePtr] because it is an argument in a "
7538 << CBArgNo <<
"@" << CBACS.getCalledFunction()->getName()
7539 <<
")\n[AAPrivatizablePtr] " << CBArg <<
" : "
7540 << CBACS.getCallArgOperand(CBArg) <<
" vs "
7542 <<
"[AAPrivatizablePtr] " << CBArg <<
" : "
7543 << CBACS.getCallArgOperandNo(CBArg) <<
" vs " << ArgNo <<
"\n";
7546 if (CBArgNo !=
int(ArgNo))
7548 const auto *CBArgPrivAA =
A.getAAFor<AAPrivatizablePtr>(
7550 if (CBArgPrivAA && CBArgPrivAA->isValidState()) {
7551 auto CBArgPrivTy = CBArgPrivAA->getPrivatizableType();
7554 if (*CBArgPrivTy == PrivatizableType)
7559 dbgs() <<
"[AAPrivatizablePtr] Argument " << *Arg
7560 <<
" cannot be privatized in the context of its parent ("
7562 <<
")\n[AAPrivatizablePtr] because it is an argument in a "
7564 << CBArgNo <<
"@" << CBACS.getCalledFunction()->getName()
7565 <<
").\n[AAPrivatizablePtr] for which the argument "
7566 "privatization is not compatible.\n";
7576 auto IsCompatiblePrivArgOfDirectCS = [&](AbstractCallSite ACS) {
7580 "Expected a direct call operand for callback call operand");
7585 dbgs() <<
"[AAPrivatizablePtr] Argument " << *Arg
7586 <<
" check if be privatized in the context of its parent ("
7588 <<
")\n[AAPrivatizablePtr] because it is an argument in a "
7590 << DCArgNo <<
"@" << DCCallee->
getName() <<
").\n";
7593 if (
unsigned(DCArgNo) < DCCallee->
arg_size()) {
7594 const auto *DCArgPrivAA =
A.getAAFor<AAPrivatizablePtr>(
7596 DepClassTy::REQUIRED);
7597 if (DCArgPrivAA && DCArgPrivAA->isValidState()) {
7598 auto DCArgPrivTy = DCArgPrivAA->getPrivatizableType();
7601 if (*DCArgPrivTy == PrivatizableType)
7607 dbgs() <<
"[AAPrivatizablePtr] Argument " << *Arg
7608 <<
" cannot be privatized in the context of its parent ("
7610 <<
")\n[AAPrivatizablePtr] because it is an argument in a "
7613 <<
").\n[AAPrivatizablePtr] for which the argument "
7614 "privatization is not compatible.\n";
7622 auto IsCompatiblePrivArgOfOtherCallSite = [&](AbstractCallSite ACS) {
7626 return IsCompatiblePrivArgOfDirectCS(ACS);
7630 if (!
A.checkForAllCallSites(IsCompatiblePrivArgOfOtherCallSite, *
this,
true,
7631 UsedAssumedInformation))
7632 return indicatePessimisticFixpoint();
7634 return ChangeStatus::UNCHANGED;
7640 identifyReplacementTypes(
Type *PrivType,
7641 SmallVectorImpl<Type *> &ReplacementTypes) {
7644 assert(PrivType &&
"Expected privatizable type!");
7648 for (
unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++)
7649 ReplacementTypes.
push_back(PrivStructType->getElementType(u));
7651 ReplacementTypes.
append(PrivArrayType->getNumElements(),
7652 PrivArrayType->getElementType());
7663 assert(PrivType &&
"Expected privatizable type!");
7666 const DataLayout &
DL =
F.getDataLayout();
7670 const StructLayout *PrivStructLayout =
DL.getStructLayout(PrivStructType);
7671 for (
unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++) {
7674 new StoreInst(
F.getArg(ArgNo + u), Ptr, IP);
7677 Type *PointeeTy = PrivArrayType->getElementType();
7678 uint64_t PointeeTySize =
DL.getTypeStoreSize(PointeeTy);
7679 for (
unsigned u = 0, e = PrivArrayType->getNumElements(); u < e; u++) {
7681 new StoreInst(
F.getArg(ArgNo + u), Ptr, IP);
7684 new StoreInst(
F.getArg(ArgNo), &
Base, IP);
7690 void createReplacementValues(Align Alignment,
Type *PrivType,
7692 SmallVectorImpl<Value *> &ReplacementValues) {
7694 assert(PrivType &&
"Expected privatizable type!");
7702 const StructLayout *PrivStructLayout =
DL.getStructLayout(PrivStructType);
7703 for (
unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++) {
7704 Type *PointeeTy = PrivStructType->getElementType(u);
7707 LoadInst *
L =
new LoadInst(PointeeTy, Ptr,
"", IP->
getIterator());
7708 L->setAlignment(Alignment);
7712 Type *PointeeTy = PrivArrayType->getElementType();
7713 uint64_t PointeeTySize =
DL.getTypeStoreSize(PointeeTy);
7714 for (
unsigned u = 0, e = PrivArrayType->getNumElements(); u < e; u++) {
7716 LoadInst *
L =
new LoadInst(PointeeTy, Ptr,
"", IP->
getIterator());
7717 L->setAlignment(Alignment);
7722 L->setAlignment(Alignment);
7729 if (!PrivatizableType)
7730 return ChangeStatus::UNCHANGED;
7731 assert(*PrivatizableType &&
"Expected privatizable type!");
7737 bool UsedAssumedInformation =
false;
7738 if (!
A.checkForAllInstructions(
7739 [&](Instruction &
I) {
7740 CallInst &CI = cast<CallInst>(I);
7741 if (CI.isTailCall())
7742 TailCalls.push_back(&CI);
7745 *
this, {Instruction::Call}, UsedAssumedInformation))
7746 return ChangeStatus::UNCHANGED;
7748 Argument *Arg = getAssociatedArgument();
7751 const auto *AlignAA =
7758 [=](
const Attributor::ArgumentReplacementInfo &ARI,
7760 BasicBlock &EntryBB = ReplacementFn.getEntryBlock();
7762 const DataLayout &
DL = IP->getDataLayout();
7763 unsigned AS =
DL.getAllocaAddrSpace();
7764 Instruction *AI =
new AllocaInst(*PrivatizableType, AS,
7765 Arg->
getName() +
".priv", IP);
7766 createInitialization(*PrivatizableType, *AI, ReplacementFn,
7767 ArgIt->getArgNo(), IP);
7770 AI = BitCastInst::CreatePointerBitCastOrAddrSpaceCast(
7774 for (CallInst *CI : TailCalls)
7775 CI->setTailCall(
false);
7782 [=](
const Attributor::ArgumentReplacementInfo &ARI,
7783 AbstractCallSite ACS, SmallVectorImpl<Value *> &NewArgOperands) {
7786 createReplacementValues(
7787 AlignAA ? AlignAA->getAssumedAlign() :
Align(0),
7788 *PrivatizableType, ACS,
7796 identifyReplacementTypes(*PrivatizableType, ReplacementTypes);
7799 if (
A.registerFunctionSignatureRewrite(*Arg, ReplacementTypes,
7800 std::move(FnRepairCB),
7801 std::move(ACSRepairCB)))
7802 return ChangeStatus::CHANGED;
7803 return ChangeStatus::UNCHANGED;
7807 void trackStatistics()
const override {
7812struct AAPrivatizablePtrFloating :
public AAPrivatizablePtrImpl {
7813 AAPrivatizablePtrFloating(
const IRPosition &IRP, Attributor &
A)
7814 : AAPrivatizablePtrImpl(IRP,
A) {}
7819 indicatePessimisticFixpoint();
7824 "updateImpl will not be called");
7828 std::optional<Type *> identifyPrivatizableType(Attributor &
A)
override {
7831 LLVM_DEBUG(
dbgs() <<
"[AAPrivatizablePtr] No underlying object found!\n");
7838 return AI->getAllocatedType();
7840 auto *PrivArgAA =
A.getAAFor<AAPrivatizablePtr>(
7842 if (PrivArgAA && PrivArgAA->isAssumedPrivatizablePtr())
7843 return PrivArgAA->getPrivatizableType();
7846 LLVM_DEBUG(
dbgs() <<
"[AAPrivatizablePtr] Underlying object neither valid "
7847 "alloca nor privatizable argument: "
7853 void trackStatistics()
const override {
7858struct AAPrivatizablePtrCallSiteArgument final
7859 :
public AAPrivatizablePtrFloating {
7860 AAPrivatizablePtrCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
7861 : AAPrivatizablePtrFloating(IRP,
A) {}
7865 if (
A.hasAttr(getIRPosition(), Attribute::ByVal))
7866 indicateOptimisticFixpoint();
7871 PrivatizableType = identifyPrivatizableType(
A);
7872 if (!PrivatizableType)
7873 return ChangeStatus::UNCHANGED;
7874 if (!*PrivatizableType)
7875 return indicatePessimisticFixpoint();
7877 const IRPosition &IRP = getIRPosition();
7878 bool IsKnownNoCapture;
7880 A,
this, IRP, DepClassTy::REQUIRED, IsKnownNoCapture);
7881 if (!IsAssumedNoCapture) {
7882 LLVM_DEBUG(
dbgs() <<
"[AAPrivatizablePtr] pointer might be captured!\n");
7883 return indicatePessimisticFixpoint();
7886 bool IsKnownNoAlias;
7888 A,
this, IRP, DepClassTy::REQUIRED, IsKnownNoAlias)) {
7889 LLVM_DEBUG(
dbgs() <<
"[AAPrivatizablePtr] pointer might alias!\n");
7890 return indicatePessimisticFixpoint();
7895 LLVM_DEBUG(
dbgs() <<
"[AAPrivatizablePtr] pointer is written!\n");
7896 return indicatePessimisticFixpoint();
7899 return ChangeStatus::UNCHANGED;
7903 void trackStatistics()
const override {
7908struct AAPrivatizablePtrCallSiteReturned final
7909 :
public AAPrivatizablePtrFloating {
7910 AAPrivatizablePtrCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
7911 : AAPrivatizablePtrFloating(IRP,
A) {}
7916 indicatePessimisticFixpoint();
7920 void trackStatistics()
const override {
7925struct AAPrivatizablePtrReturned final :
public AAPrivatizablePtrFloating {
7926 AAPrivatizablePtrReturned(
const IRPosition &IRP, Attributor &
A)
7927 : AAPrivatizablePtrFloating(IRP,
A) {}
7932 indicatePessimisticFixpoint();
7936 void trackStatistics()
const override {
7946struct AAMemoryBehaviorImpl :
public AAMemoryBehavior {
7947 AAMemoryBehaviorImpl(
const IRPosition &IRP, Attributor &
A)
7948 : AAMemoryBehavior(IRP,
A) {}
7952 intersectAssumedBits(BEST_STATE);
7953 getKnownStateFromValue(
A, getIRPosition(), getState());
7954 AAMemoryBehavior::initialize(
A);
7958 static void getKnownStateFromValue(Attributor &
A,
const IRPosition &IRP,
7959 BitIntegerState &State,
7960 bool IgnoreSubsumingPositions =
false) {
7962 A.getAttrs(IRP, AttrKinds, Attrs, IgnoreSubsumingPositions);
7964 switch (Attr.getKindAsEnum()) {
7965 case Attribute::ReadNone:
7968 case Attribute::ReadOnly:
7971 case Attribute::WriteOnly:
7980 if (!
I->mayReadFromMemory())
7982 if (!
I->mayWriteToMemory())
7988 void getDeducedAttributes(Attributor &
A, LLVMContext &Ctx,
7989 SmallVectorImpl<Attribute> &Attrs)
const override {
7992 Attrs.push_back(Attribute::get(Ctx, Attribute::ReadNone));
7994 Attrs.push_back(Attribute::get(Ctx, Attribute::ReadOnly));
7995 else if (isAssumedWriteOnly())
7996 Attrs.push_back(Attribute::get(Ctx, Attribute::WriteOnly));
8002 const IRPosition &IRP = getIRPosition();
8004 if (
A.hasAttr(IRP, Attribute::ReadNone,
8006 return ChangeStatus::UNCHANGED;
8015 return ChangeStatus::UNCHANGED;
8018 A.removeAttrs(IRP, AttrKinds);
8021 A.removeAttrs(IRP, Attribute::Writable);
8028 const std::string getAsStr(Attributor *
A)
const override {
8033 if (isAssumedWriteOnly())
8035 return "may-read/write";
8039 static const Attribute::AttrKind AttrKinds[3];
8043 Attribute::ReadNone, Attribute::ReadOnly, Attribute::WriteOnly};
8046struct AAMemoryBehaviorFloating : AAMemoryBehaviorImpl {
8047 AAMemoryBehaviorFloating(
const IRPosition &IRP, Attributor &
A)
8048 : AAMemoryBehaviorImpl(IRP,
A) {}
8054 void trackStatistics()
const override {
8059 else if (isAssumedWriteOnly())
8066 bool followUsersOfUseIn(Attributor &
A,
const Use &U,
8067 const Instruction *UserI);
8070 void analyzeUseIn(Attributor &
A,
const Use &U,
const Instruction *UserI);
8074struct AAMemoryBehaviorArgument : AAMemoryBehaviorFloating {
8075 AAMemoryBehaviorArgument(
const IRPosition &IRP, Attributor &
A)
8076 : AAMemoryBehaviorFloating(IRP,
A) {}
8080 intersectAssumedBits(BEST_STATE);
8081 const IRPosition &IRP = getIRPosition();
8085 bool HasByVal =
A.hasAttr(IRP, {Attribute::ByVal},
8087 getKnownStateFromValue(
A, IRP, getState(),
8094 return ChangeStatus::UNCHANGED;
8098 if (
A.hasAttr(getIRPosition(),
8099 {Attribute::InAlloca, Attribute::Preallocated})) {
8100 removeKnownBits(NO_WRITES);
8101 removeAssumedBits(NO_WRITES);
8103 A.removeAttrs(getIRPosition(), AttrKinds);
8104 return AAMemoryBehaviorFloating::manifest(
A);
8108 void trackStatistics()
const override {
8113 else if (isAssumedWriteOnly())
8118struct AAMemoryBehaviorCallSiteArgument final : AAMemoryBehaviorArgument {
8119 AAMemoryBehaviorCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
8120 : AAMemoryBehaviorArgument(IRP,
A) {}
8126 Argument *Arg = getAssociatedArgument();
8128 indicatePessimisticFixpoint();
8132 addKnownBits(NO_WRITES);
8133 removeKnownBits(NO_READS);
8134 removeAssumedBits(NO_READS);
8136 AAMemoryBehaviorArgument::initialize(
A);
8137 if (getAssociatedFunction()->isDeclaration())
8138 indicatePessimisticFixpoint();
8147 Argument *Arg = getAssociatedArgument();
8150 A.getAAFor<AAMemoryBehavior>(*
this, ArgPos, DepClassTy::REQUIRED);
8152 return indicatePessimisticFixpoint();
8157 void trackStatistics()
const override {
8162 else if (isAssumedWriteOnly())
8168struct AAMemoryBehaviorCallSiteReturned final : AAMemoryBehaviorFloating {
8169 AAMemoryBehaviorCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
8170 : AAMemoryBehaviorFloating(IRP,
A) {}
8174 AAMemoryBehaviorImpl::initialize(
A);
8179 return ChangeStatus::UNCHANGED;
8183 void trackStatistics()
const override {}
8187struct AAMemoryBehaviorFunction final :
public AAMemoryBehaviorImpl {
8188 AAMemoryBehaviorFunction(
const IRPosition &IRP, Attributor &
A)
8189 : AAMemoryBehaviorImpl(IRP,
A) {}
8205 else if (isAssumedWriteOnly())
8208 A.removeAttrs(getIRPosition(), AttrKinds);
8211 for (Argument &Arg :
F.args())
8213 return A.manifestAttrs(getIRPosition(),
8214 Attribute::getWithMemoryEffects(
F.getContext(), ME));
8218 void trackStatistics()
const override {
8223 else if (isAssumedWriteOnly())
8229struct AAMemoryBehaviorCallSite final
8230 : AACalleeToCallSite<AAMemoryBehavior, AAMemoryBehaviorImpl> {
8231 AAMemoryBehaviorCallSite(
const IRPosition &IRP, Attributor &
A)
8232 : AACalleeToCallSite<AAMemoryBehavior, AAMemoryBehaviorImpl>(IRP,
A) {}
8243 else if (isAssumedWriteOnly())
8246 A.removeAttrs(getIRPosition(), AttrKinds);
8249 for (Use &U : CB.
args())
8251 Attribute::Writable);
8252 return A.manifestAttrs(
8253 getIRPosition(), Attribute::getWithMemoryEffects(CB.
getContext(), ME));
8257 void trackStatistics()
const override {
8262 else if (isAssumedWriteOnly())
8267ChangeStatus AAMemoryBehaviorFunction::updateImpl(Attributor &
A) {
8270 auto AssumedState = getAssumed();
8277 const auto *MemBehaviorAA =
A.getAAFor<AAMemoryBehavior>(
8279 if (MemBehaviorAA) {
8280 intersectAssumedBits(MemBehaviorAA->
getAssumed());
8281 return !isAtFixpoint();
8286 if (
I.mayReadFromMemory())
8287 removeAssumedBits(NO_READS);
8288 if (
I.mayWriteToMemory())
8289 removeAssumedBits(NO_WRITES);
8290 return !isAtFixpoint();
8293 bool UsedAssumedInformation =
false;
8294 if (!
A.checkForAllReadWriteInstructions(CheckRWInst, *
this,
8295 UsedAssumedInformation))
8296 return indicatePessimisticFixpoint();
8302ChangeStatus AAMemoryBehaviorFloating::updateImpl(Attributor &
A) {
8304 const IRPosition &IRP = getIRPosition();
8315 const auto *FnMemAA =
8318 FnMemAssumedState = FnMemAA->getAssumed();
8319 S.addKnownBits(FnMemAA->getKnown());
8320 if ((S.getAssumed() & FnMemAA->getAssumed()) == S.getAssumed())
8326 auto AssumedState = S.getAssumed();
8332 bool IsKnownNoCapture;
8333 const AANoCapture *ArgNoCaptureAA =
nullptr;
8338 if (!IsAssumedNoCapture &&
8340 S.intersectAssumedBits(FnMemAssumedState);
8346 auto UsePred = [&](
const Use &
U,
bool &Follow) ->
bool {
8348 LLVM_DEBUG(
dbgs() <<
"[AAMemoryBehavior] Use: " << *U <<
" in " << *UserI
8356 Follow = followUsersOfUseIn(
A, U, UserI);
8360 analyzeUseIn(
A, U, UserI);
8362 return !isAtFixpoint();
8365 if (!
A.checkForAllUses(UsePred, *
this, getAssociatedValue()))
8366 return indicatePessimisticFixpoint();
8372bool AAMemoryBehaviorFloating::followUsersOfUseIn(Attributor &
A,
const Use &U,
8373 const Instruction *UserI) {
8391 if (
U.get()->getType()->isPointerTy()) {
8393 bool IsKnownNoCapture;
8402void AAMemoryBehaviorFloating::analyzeUseIn(Attributor &
A,
const Use &U,
8403 const Instruction *UserI) {
8410 case Instruction::Load:
8412 removeAssumedBits(NO_READS);
8415 case Instruction::Store:
8420 removeAssumedBits(NO_WRITES);
8422 indicatePessimisticFixpoint();
8425 case Instruction::Call:
8426 case Instruction::CallBr:
8427 case Instruction::Invoke: {
8434 indicatePessimisticFixpoint();
8441 removeAssumedBits(NO_READS);
8448 if (
U.get()->getType()->isPointerTy())
8452 const auto *MemBehaviorAA =
8458 intersectAssumedBits(MemBehaviorAA->
getAssumed());
8466 removeAssumedBits(NO_READS);
8468 removeAssumedBits(NO_WRITES);
8480 return "all memory";
8483 std::string S =
"memory:";
8489 S +=
"internal global,";
8491 S +=
"external global,";
8495 S +=
"inaccessible,";
8509 AccessKind2Accesses.fill(
nullptr);
8512 ~AAMemoryLocationImpl()
override {
8515 for (AccessSet *AS : AccessKind2Accesses)
8522 intersectAssumedBits(BEST_STATE);
8523 getKnownStateFromValue(
A, getIRPosition(), getState());
8524 AAMemoryLocation::initialize(
A);
8528 static void getKnownStateFromValue(Attributor &
A,
const IRPosition &IRP,
8529 BitIntegerState &State,
8530 bool IgnoreSubsumingPositions =
false) {
8539 bool UseArgMemOnly =
true;
8541 if (AnchorFn &&
A.isRunOn(*AnchorFn))
8545 A.getAttrs(IRP, {Attribute::Memory},
Attrs, IgnoreSubsumingPositions);
8554 State.
addKnownBits(inverseLocation(NO_INACCESSIBLE_MEM,
true,
true));
8559 State.
addKnownBits(inverseLocation(NO_ARGUMENT_MEM,
true,
true));
8563 A.manifestAttrs(IRP,
8564 Attribute::getWithMemoryEffects(
8573 NO_INACCESSIBLE_MEM | NO_ARGUMENT_MEM,
true,
true));
8577 A.manifestAttrs(IRP,
8578 Attribute::getWithMemoryEffects(
8588 void getDeducedAttributes(Attributor &
A, LLVMContext &Ctx,
8589 SmallVectorImpl<Attribute> &Attrs)
const override {
8596 else if (isAssumedInaccessibleMemOnly())
8597 Attrs.push_back(Attribute::getWithMemoryEffects(
8599 else if (isAssumedArgMemOnly())
8602 else if (isAssumedInaccessibleOrArgMemOnly())
8603 Attrs.push_back(Attribute::getWithMemoryEffects(
8613 const IRPosition &IRP = getIRPosition();
8617 if (DeducedAttrs.
size() != 1)
8618 return ChangeStatus::UNCHANGED;
8621 return A.manifestAttrs(IRP, Attribute::getWithMemoryEffects(
8626 bool checkForAllAccessesToMemoryKind(
8628 MemoryLocationsKind)>
8630 MemoryLocationsKind RequestedMLK)
const override {
8631 if (!isValidState())
8634 MemoryLocationsKind AssumedMLK = getAssumedNotAccessedLocation();
8635 if (AssumedMLK == NO_LOCATIONS)
8639 for (MemoryLocationsKind CurMLK = 1; CurMLK < NO_LOCATIONS;
8640 CurMLK *= 2, ++
Idx) {
8641 if (CurMLK & RequestedMLK)
8644 if (
const AccessSet *
Accesses = AccessKind2Accesses[Idx])
8645 for (
const AccessInfo &AI : *
Accesses)
8646 if (!Pred(AI.I, AI.Ptr, AI.Kind, CurMLK))
8659 MemoryLocationsKind KnownMLK = getKnown();
8661 for (MemoryLocationsKind CurMLK = 1; CurMLK < NO_LOCATIONS; CurMLK *= 2)
8662 if (!(CurMLK & KnownMLK))
8663 updateStateAndAccessesMap(getState(), CurMLK,
I,
nullptr,
Changed,
8664 getAccessKindFromInst(
I));
8665 return AAMemoryLocation::indicatePessimisticFixpoint();
8685 bool operator()(
const AccessInfo &
LHS,
const AccessInfo &
RHS)
const {
8689 return LHS.Ptr <
RHS.Ptr;
8690 if (
LHS.Kind !=
RHS.Kind)
8691 return LHS.Kind <
RHS.Kind;
8698 using AccessSet = SmallSet<AccessInfo, 2, AccessInfo>;
8699 std::array<AccessSet *, llvm::ConstantLog2<VALID_STATE>()>
8700 AccessKind2Accesses;
8705 categorizeArgumentPointerLocations(Attributor &
A, CallBase &CB,
8706 AAMemoryLocation::StateType &AccessedLocs,
8711 categorizeAccessedLocations(Attributor &
A, Instruction &
I,
bool &
Changed);
8714 AccessKind getAccessKindFromInst(
const Instruction *
I) {
8717 AK =
I->mayReadFromMemory() ? READ :
NONE;
8726 void updateStateAndAccessesMap(AAMemoryLocation::StateType &State,
8727 MemoryLocationsKind MLK,
const Instruction *
I,
8736 if (MLK == NO_UNKOWN_MEM)
8738 State.removeAssumedBits(MLK);
8743 void categorizePtrValue(Attributor &
A,
const Instruction &
I,
const Value &Ptr,
8744 AAMemoryLocation::StateType &State,
bool &
Changed,
8745 unsigned AccessAS = 0);
8751void AAMemoryLocationImpl::categorizePtrValue(
8752 Attributor &
A,
const Instruction &
I,
const Value &Ptr,
8754 LLVM_DEBUG(
dbgs() <<
"[AAMemoryLocation] Categorize pointer locations for "
8759 unsigned ObjectAS =
Obj.getType()->getPointerAddressSpace();
8761 MemoryLocationsKind MLK = NO_LOCATIONS;
8781 MLK = NO_ARGUMENT_MEM;
8787 if (GVar->isConstant())
8790 if (GV->hasLocalLinkage())
8791 MLK = NO_GLOBAL_INTERNAL_MEM;
8793 MLK = NO_GLOBAL_EXTERNAL_MEM;
8802 bool IsKnownNoAlias;
8806 MLK = NO_MALLOCED_MEM;
8808 MLK = NO_UNKOWN_MEM;
8810 MLK = NO_UNKOWN_MEM;
8813 assert(MLK != NO_LOCATIONS &&
"No location specified!");
8814 LLVM_DEBUG(
dbgs() <<
"[AAMemoryLocation] Ptr value can be categorized: "
8815 << Obj <<
" -> " << getMemoryLocationsAsStr(MLK) <<
"\n");
8817 getAccessKindFromInst(&
I));
8822 const auto *AA =
A.getAAFor<AAUnderlyingObjects>(
8826 dbgs() <<
"[AAMemoryLocation] Pointer locations not categorized\n");
8827 updateStateAndAccessesMap(
State, NO_UNKOWN_MEM, &
I,
nullptr,
Changed,
8828 getAccessKindFromInst(&
I));
8833 dbgs() <<
"[AAMemoryLocation] Accessed locations with pointer locations: "
8837void AAMemoryLocationImpl::categorizeArgumentPointerLocations(
8840 for (
unsigned ArgNo = 0,
E = CB.
arg_size(); ArgNo <
E; ++ArgNo) {
8849 const auto *ArgOpMemLocationAA =
8852 if (ArgOpMemLocationAA && ArgOpMemLocationAA->isAssumedReadNone())
8857 categorizePtrValue(
A, CB, *ArgOp, AccessedLocs,
Changed);
8862AAMemoryLocationImpl::categorizeAccessedLocations(Attributor &
A, Instruction &
I,
8864 LLVM_DEBUG(
dbgs() <<
"[AAMemoryLocation] Categorize accessed locations for "
8868 AccessedLocs.intersectAssumedBits(NO_LOCATIONS);
8873 const auto *CBMemLocationAA =
A.getAAFor<AAMemoryLocation>(
8876 <<
" [" << CBMemLocationAA <<
"]\n");
8877 if (!CBMemLocationAA) {
8878 updateStateAndAccessesMap(AccessedLocs, NO_UNKOWN_MEM, &
I,
nullptr,
8879 Changed, getAccessKindFromInst(&
I));
8880 return NO_UNKOWN_MEM;
8883 if (CBMemLocationAA->isAssumedReadNone())
8884 return NO_LOCATIONS;
8886 if (CBMemLocationAA->isAssumedInaccessibleMemOnly()) {
8887 updateStateAndAccessesMap(AccessedLocs, NO_INACCESSIBLE_MEM, &
I,
nullptr,
8888 Changed, getAccessKindFromInst(&
I));
8889 return AccessedLocs.getAssumed();
8892 uint32_t CBAssumedNotAccessedLocs =
8893 CBMemLocationAA->getAssumedNotAccessedLocation();
8896 uint32_t CBAssumedNotAccessedLocsNoArgMem =
8897 CBAssumedNotAccessedLocs | NO_ARGUMENT_MEM | NO_GLOBAL_MEM;
8899 for (MemoryLocationsKind CurMLK = 1; CurMLK < NO_LOCATIONS; CurMLK *= 2) {
8900 if (CBAssumedNotAccessedLocsNoArgMem & CurMLK)
8902 updateStateAndAccessesMap(AccessedLocs, CurMLK, &
I,
nullptr,
Changed,
8903 getAccessKindFromInst(&
I));
8908 bool HasGlobalAccesses = ((~CBAssumedNotAccessedLocs) & NO_GLOBAL_MEM);
8909 if (HasGlobalAccesses) {
8912 updateStateAndAccessesMap(AccessedLocs, MLK, &
I, Ptr,
Changed,
8913 getAccessKindFromInst(&
I));
8916 if (!CBMemLocationAA->checkForAllAccessesToMemoryKind(
8917 AccessPred, inverseLocation(NO_GLOBAL_MEM,
false,
false)))
8918 return AccessedLocs.getWorstState();
8922 dbgs() <<
"[AAMemoryLocation] Accessed state before argument handling: "
8923 << getMemoryLocationsAsStr(AccessedLocs.getAssumed()) <<
"\n");
8926 bool HasArgAccesses = ((~CBAssumedNotAccessedLocs) & NO_ARGUMENT_MEM);
8928 categorizeArgumentPointerLocations(
A, *CB, AccessedLocs,
Changed);
8931 dbgs() <<
"[AAMemoryLocation] Accessed state after argument handling: "
8932 << getMemoryLocationsAsStr(AccessedLocs.getAssumed()) <<
"\n");
8934 return AccessedLocs.getAssumed();
8939 dbgs() <<
"[AAMemoryLocation] Categorize memory access with pointer: "
8940 <<
I <<
" [" << *Ptr <<
"]\n");
8941 categorizePtrValue(
A,
I, *Ptr, AccessedLocs,
Changed,
8942 Ptr->getType()->getPointerAddressSpace());
8943 return AccessedLocs.getAssumed();
8946 LLVM_DEBUG(
dbgs() <<
"[AAMemoryLocation] Failed to categorize instruction: "
8948 updateStateAndAccessesMap(AccessedLocs, NO_UNKOWN_MEM, &
I,
nullptr,
Changed,
8949 getAccessKindFromInst(&
I));
8950 return AccessedLocs.getAssumed();
8954struct AAMemoryLocationFunction final :
public AAMemoryLocationImpl {
8955 AAMemoryLocationFunction(
const IRPosition &IRP, Attributor &
A)
8956 : AAMemoryLocationImpl(IRP,
A) {}
8961 const auto *MemBehaviorAA =
8962 A.getAAFor<AAMemoryBehavior>(*
this, getIRPosition(), DepClassTy::NONE);
8965 return indicateOptimisticFixpoint();
8967 "AAMemoryLocation was not read-none but AAMemoryBehavior was!");
8968 A.recordDependence(*MemBehaviorAA, *
this, DepClassTy::OPTIONAL);
8969 return ChangeStatus::UNCHANGED;
8973 auto AssumedState = getAssumed();
8977 MemoryLocationsKind MLK = categorizeAccessedLocations(
A,
I,
Changed);
8978 LLVM_DEBUG(
dbgs() <<
"[AAMemoryLocation] Accessed locations for " <<
I
8979 <<
": " << getMemoryLocationsAsStr(MLK) <<
"\n");
8980 removeAssumedBits(inverseLocation(MLK,
false,
false));
8983 return getAssumedNotAccessedLocation() != VALID_STATE;
8986 bool UsedAssumedInformation =
false;
8987 if (!
A.checkForAllReadWriteInstructions(CheckRWInst, *
this,
8988 UsedAssumedInformation))
8989 return indicatePessimisticFixpoint();
8991 Changed |= AssumedState != getAssumed();
8992 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
8996 void trackStatistics()
const override {
8999 else if (isAssumedArgMemOnly())
9001 else if (isAssumedInaccessibleMemOnly())
9003 else if (isAssumedInaccessibleOrArgMemOnly())
9009struct AAMemoryLocationCallSite final : AAMemoryLocationImpl {
9010 AAMemoryLocationCallSite(
const IRPosition &IRP, Attributor &
A)
9011 : AAMemoryLocationImpl(IRP,
A) {}
9022 A.getAAFor<AAMemoryLocation>(*
this, FnPos, DepClassTy::REQUIRED);
9024 return indicatePessimisticFixpoint();
9028 updateStateAndAccessesMap(getState(), MLK,
I, Ptr,
Changed,
9029 getAccessKindFromInst(
I));
9032 if (!FnAA->checkForAllAccessesToMemoryKind(AccessPred, ALL_LOCATIONS))
9033 return indicatePessimisticFixpoint();
9034 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
9038 void trackStatistics()
const override {
9048struct AADenormalFPMathImpl :
public AADenormalFPMath {
9049 AADenormalFPMathImpl(
const IRPosition &IRP, Attributor &
A)
9050 : AADenormalFPMath(IRP,
A) {}
9052 const std::string getAsStr(Attributor *
A)
const override {
9053 std::string Str(
"AADenormalFPMath[");
9054 raw_string_ostream OS(Str);
9056 DenormalState
Known = getKnown();
9057 if (
Known.Mode.isValid())
9058 OS <<
"denormal-fp-math=" <<
Known.Mode;
9062 if (
Known.ModeF32.isValid())
9063 OS <<
" denormal-fp-math-f32=" <<
Known.ModeF32;
9069struct AADenormalFPMathFunction final : AADenormalFPMathImpl {
9070 AADenormalFPMathFunction(
const IRPosition &IRP, Attributor &
A)
9071 : AADenormalFPMathImpl(IRP,
A) {}
9075 DenormalFPEnv DenormEnv =
F->getDenormalFPEnv();
9085 auto CheckCallSite = [=, &Change, &
A](AbstractCallSite CS) {
9088 <<
"->" << getAssociatedFunction()->
getName() <<
'\n');
9090 const auto *CallerInfo =
A.getAAFor<AADenormalFPMath>(
9096 CallerInfo->getState());
9100 bool AllCallSitesKnown =
true;
9101 if (!
A.checkForAllCallSites(CheckCallSite, *
this,
true, AllCallSitesKnown))
9102 return indicatePessimisticFixpoint();
9104 if (Change == ChangeStatus::CHANGED && isModeFixed())
9110 LLVMContext &Ctx = getAssociatedFunction()->getContext();
9116 DenormalFPEnv KnownEnv(
Known.Mode,
Known.ModeF32);
9119 AttrToRemove.
push_back(Attribute::DenormalFPEnv);
9122 Ctx, Attribute::DenormalFPEnv,
9123 DenormalFPEnv(
Known.Mode,
Known.ModeF32).toIntValue()));
9126 auto &IRP = getIRPosition();
9129 return A.removeAttrs(IRP, AttrToRemove) |
9130 A.manifestAttrs(IRP, AttrToAdd,
true);
9133 void trackStatistics()
const override {
9142struct AAValueConstantRangeImpl : AAValueConstantRange {
9143 using StateType = IntegerRangeState;
9144 AAValueConstantRangeImpl(
const IRPosition &IRP, Attributor &
A)
9145 : AAValueConstantRange(IRP,
A) {}
9149 if (
A.hasSimplificationCallback(getIRPosition())) {
9150 indicatePessimisticFixpoint();
9155 intersectKnown(getConstantRangeFromSCEV(
A, getCtxI()));
9158 intersectKnown(getConstantRangeFromLVI(
A, getCtxI()));
9162 const std::string getAsStr(Attributor *
A)
const override {
9164 llvm::raw_string_ostream OS(Str);
9166 getKnown().print(OS);
9168 getAssumed().print(OS);
9175 const SCEV *getSCEV(Attributor &
A,
const Instruction *
I =
nullptr)
const {
9176 if (!getAnchorScope())
9179 ScalarEvolution *SE =
9180 A.getInfoCache().getAnalysisResultForFunction<ScalarEvolutionAnalysis>(
9183 LoopInfo *LI =
A.getInfoCache().getAnalysisResultForFunction<LoopAnalysis>(
9189 const SCEV *S = SE->
getSCEV(&getAssociatedValue());
9198 ConstantRange getConstantRangeFromSCEV(Attributor &
A,
9199 const Instruction *
I =
nullptr)
const {
9200 if (!getAnchorScope())
9203 ScalarEvolution *SE =
9204 A.getInfoCache().getAnalysisResultForFunction<ScalarEvolutionAnalysis>(
9207 const SCEV *S = getSCEV(
A,
I);
9217 getConstantRangeFromLVI(Attributor &
A,
9218 const Instruction *CtxI =
nullptr)
const {
9219 if (!getAnchorScope())
9222 LazyValueInfo *LVI =
9223 A.getInfoCache().getAnalysisResultForFunction<LazyValueAnalysis>(
9238 bool isValidCtxInstructionForOutsideAnalysis(Attributor &
A,
9239 const Instruction *CtxI,
9240 bool AllowAACtxI)
const {
9241 if (!CtxI || (!AllowAACtxI && CtxI == getCtxI()))
9253 InformationCache &InfoCache =
A.getInfoCache();
9254 const DominatorTree *DT =
9265 getAssumedConstantRange(Attributor &
A,
9266 const Instruction *CtxI =
nullptr)
const override {
9271 if (!isValidCtxInstructionForOutsideAnalysis(
A, CtxI,
9273 return getAssumed();
9275 ConstantRange LVIR = getConstantRangeFromLVI(
A, CtxI);
9276 ConstantRange SCEVR = getConstantRangeFromSCEV(
A, CtxI);
9277 return getAssumed().intersectWith(SCEVR).intersectWith(LVIR);
9282 getMDNodeForConstantRange(
Type *Ty, LLVMContext &Ctx,
9283 const ConstantRange &AssumedConstantRange) {
9285 Ty, AssumedConstantRange.
getLower())),
9287 Ty, AssumedConstantRange.
getUpper()))};
9292 static bool isBetterRange(
const ConstantRange &Assumed,
9293 const Instruction &
I) {
9297 std::optional<ConstantRange>
Known;
9301 }
else if (MDNode *KnownRanges =
I.getMetadata(LLVMContext::MD_range)) {
9307 if (KnownRanges->getNumOperands() > 2)
9310 ConstantInt *
Lower =
9312 ConstantInt *
Upper =
9322 setRangeMetadataIfisBetterRange(Instruction *
I,
9323 const ConstantRange &AssumedConstantRange) {
9324 if (isBetterRange(AssumedConstantRange, *
I)) {
9325 I->setMetadata(LLVMContext::MD_range,
9326 getMDNodeForConstantRange(
I->getType(),
I->getContext(),
9327 AssumedConstantRange));
9334 setRangeRetAttrIfisBetterRange(Attributor &
A,
const IRPosition &IRP,
9336 const ConstantRange &AssumedConstantRange) {
9337 if (isBetterRange(AssumedConstantRange, *
I)) {
9338 A.manifestAttrs(IRP,
9339 Attribute::get(
I->getContext(), Attribute::Range,
9340 AssumedConstantRange),
9350 ConstantRange AssumedConstantRange = getAssumedConstantRange(
A);
9353 auto &
V = getAssociatedValue();
9357 assert(
I == getCtxI() &&
"Should not annotate an instruction which is "
9358 "not the context instruction");
9360 if (setRangeMetadataIfisBetterRange(
I, AssumedConstantRange))
9361 Changed = ChangeStatus::CHANGED;
9363 if (setRangeRetAttrIfisBetterRange(
A, getIRPosition(),
I,
9364 AssumedConstantRange))
9365 Changed = ChangeStatus::CHANGED;
9373struct AAValueConstantRangeArgument final
9374 : AAArgumentFromCallSiteArguments<
9375 AAValueConstantRange, AAValueConstantRangeImpl, IntegerRangeState,
9377 using Base = AAArgumentFromCallSiteArguments<
9378 AAValueConstantRange, AAValueConstantRangeImpl, IntegerRangeState,
9380 AAValueConstantRangeArgument(
const IRPosition &IRP, Attributor &
A)
9384 void trackStatistics()
const override {
9389struct AAValueConstantRangeReturned
9390 : AAReturnedFromReturnedValues<AAValueConstantRange,
9391 AAValueConstantRangeImpl,
9392 AAValueConstantRangeImpl::StateType,
9395 AAReturnedFromReturnedValues<AAValueConstantRange,
9396 AAValueConstantRangeImpl,
9397 AAValueConstantRangeImpl::StateType,
9399 AAValueConstantRangeReturned(
const IRPosition &IRP, Attributor &
A)
9404 if (!
A.isFunctionIPOAmendable(*getAssociatedFunction()))
9405 indicatePessimisticFixpoint();
9409 void trackStatistics()
const override {
9414struct AAValueConstantRangeFloating : AAValueConstantRangeImpl {
9415 AAValueConstantRangeFloating(
const IRPosition &IRP, Attributor &
A)
9416 : AAValueConstantRangeImpl(IRP,
A) {}
9420 AAValueConstantRangeImpl::initialize(
A);
9424 Value &
V = getAssociatedValue();
9427 unionAssumed(ConstantRange(
C->getValue()));
9428 indicateOptimisticFixpoint();
9434 unionAssumed(ConstantRange(APInt(
getBitWidth(), 0)));
9435 indicateOptimisticFixpoint();
9447 if (
auto *RangeMD = LI->getMetadata(LLVMContext::MD_range)) {
9458 indicatePessimisticFixpoint();
9461 << getAssociatedValue() <<
"\n");
9464 bool calculateBinaryOperator(
9465 Attributor &
A, BinaryOperator *BinOp, IntegerRangeState &
T,
9466 const Instruction *CtxI,
9467 SmallVectorImpl<const AAValueConstantRange *> &QuerriedAAs) {
9472 bool UsedAssumedInformation =
false;
9473 const auto &SimplifiedLHS =
A.getAssumedSimplified(
9476 if (!SimplifiedLHS.has_value())
9478 if (!*SimplifiedLHS)
9480 LHS = *SimplifiedLHS;
9482 const auto &SimplifiedRHS =
A.getAssumedSimplified(
9485 if (!SimplifiedRHS.has_value())
9487 if (!*SimplifiedRHS)
9489 RHS = *SimplifiedRHS;
9495 auto *LHSAA =
A.getAAFor<AAValueConstantRange>(
9497 DepClassTy::REQUIRED);
9501 auto LHSAARange = LHSAA->getAssumedConstantRange(
A, CtxI);
9503 auto *RHSAA =
A.getAAFor<AAValueConstantRange>(
9505 DepClassTy::REQUIRED);
9509 auto RHSAARange = RHSAA->getAssumedConstantRange(
A, CtxI);
9511 auto AssumedRange = LHSAARange.binaryOp(BinOp->
getOpcode(), RHSAARange);
9513 T.unionAssumed(AssumedRange);
9517 return T.isValidState();
9520 bool calculateCastInst(
9521 Attributor &
A, CastInst *CastI, IntegerRangeState &
T,
9522 const Instruction *CtxI,
9523 SmallVectorImpl<const AAValueConstantRange *> &QuerriedAAs) {
9529 bool UsedAssumedInformation =
false;
9530 const auto &SimplifiedOpV =
A.getAssumedSimplified(
9533 if (!SimplifiedOpV.has_value())
9535 if (!*SimplifiedOpV)
9537 OpV = *SimplifiedOpV;
9542 auto *OpAA =
A.getAAFor<AAValueConstantRange>(
9544 DepClassTy::REQUIRED);
9548 T.unionAssumed(OpAA->getAssumed().castOp(CastI->
getOpcode(),
9550 return T.isValidState();
9554 calculateCmpInst(Attributor &
A, CmpInst *CmpI, IntegerRangeState &
T,
9555 const Instruction *CtxI,
9556 SmallVectorImpl<const AAValueConstantRange *> &QuerriedAAs) {
9561 bool UsedAssumedInformation =
false;
9562 const auto &SimplifiedLHS =
A.getAssumedSimplified(
9565 if (!SimplifiedLHS.has_value())
9567 if (!*SimplifiedLHS)
9569 LHS = *SimplifiedLHS;
9571 const auto &SimplifiedRHS =
A.getAssumedSimplified(
9574 if (!SimplifiedRHS.has_value())
9576 if (!*SimplifiedRHS)
9578 RHS = *SimplifiedRHS;
9584 auto *LHSAA =
A.getAAFor<AAValueConstantRange>(
9586 DepClassTy::REQUIRED);
9590 auto *RHSAA =
A.getAAFor<AAValueConstantRange>(
9592 DepClassTy::REQUIRED);
9596 auto LHSAARange = LHSAA->getAssumedConstantRange(
A, CtxI);
9597 auto RHSAARange = RHSAA->getAssumedConstantRange(
A, CtxI);
9600 if (LHSAARange.isEmptySet() || RHSAARange.isEmptySet())
9603 bool MustTrue =
false, MustFalse =
false;
9605 auto AllowedRegion =
9608 if (AllowedRegion.intersectWith(LHSAARange).isEmptySet())
9614 assert((!MustTrue || !MustFalse) &&
9615 "Either MustTrue or MustFalse should be false!");
9618 T.unionAssumed(ConstantRange(APInt( 1, 1)));
9620 T.unionAssumed(ConstantRange(APInt( 1, 0)));
9622 T.unionAssumed(ConstantRange( 1,
true));
9624 LLVM_DEBUG(
dbgs() <<
"[AAValueConstantRange] " << *CmpI <<
" after "
9625 << (MustTrue ?
"true" : (MustFalse ?
"false" :
"unknown"))
9626 <<
": " <<
T <<
"\n\t" << *LHSAA <<
"\t<op>\n\t"
9630 return T.isValidState();
9642 bool UsedAssumedInformation =
false;
9643 const auto &SimplifiedOpV =
A.getAssumedSimplified(
9646 if (!SimplifiedOpV.has_value())
9648 if (!*SimplifiedOpV)
9650 Value *VPtr = *SimplifiedOpV;
9653 const auto *AA =
A.getAAFor<AAValueConstantRange>(
9655 DepClassTy::REQUIRED);
9659 T.unionAssumed(AA->getAssumedConstantRange(
A, CtxI));
9663 return T.isValidState();
9668 if (!calculateBinaryOperator(
A, BinOp,
T, CtxI, QuerriedAAs))
9671 if (!calculateCmpInst(
A, CmpI,
T, CtxI, QuerriedAAs))
9674 if (!calculateCastInst(
A, CastI,
T, CtxI, QuerriedAAs))
9680 T.indicatePessimisticFixpoint();
9687 for (
const AAValueConstantRange *QueriedAA : QuerriedAAs) {
9688 if (QueriedAA !=
this)
9691 if (
T.getAssumed() == getState().getAssumed())
9693 T.indicatePessimisticFixpoint();
9696 return T.isValidState();
9699 if (!VisitValueCB(getAssociatedValue(), getCtxI()))
9700 return indicatePessimisticFixpoint();
9705 return ChangeStatus::UNCHANGED;
9706 if (++NumChanges > MaxNumChanges) {
9707 LLVM_DEBUG(
dbgs() <<
"[AAValueConstantRange] performed " << NumChanges
9708 <<
" but only " << MaxNumChanges
9709 <<
" are allowed to avoid cyclic reasoning.");
9710 return indicatePessimisticFixpoint();
9712 return ChangeStatus::CHANGED;
9716 void trackStatistics()
const override {
9725 static constexpr int MaxNumChanges = 5;
9728struct AAValueConstantRangeFunction : AAValueConstantRangeImpl {
9729 AAValueConstantRangeFunction(
const IRPosition &IRP, Attributor &
A)
9730 : AAValueConstantRangeImpl(IRP,
A) {}
9734 llvm_unreachable(
"AAValueConstantRange(Function|CallSite)::updateImpl will "
9742struct AAValueConstantRangeCallSite : AAValueConstantRangeFunction {
9743 AAValueConstantRangeCallSite(
const IRPosition &IRP, Attributor &
A)
9744 : AAValueConstantRangeFunction(IRP,
A) {}
9750struct AAValueConstantRangeCallSiteReturned
9751 : AACalleeToCallSite<AAValueConstantRange, AAValueConstantRangeImpl,
9752 AAValueConstantRangeImpl::StateType,
9754 AAValueConstantRangeCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
9755 : AACalleeToCallSite<AAValueConstantRange, AAValueConstantRangeImpl,
9756 AAValueConstantRangeImpl::StateType,
9763 if (std::optional<ConstantRange>
Range = CI->getRange())
9764 intersectKnown(*
Range);
9767 AAValueConstantRangeImpl::initialize(
A);
9771 void trackStatistics()
const override {
9775struct AAValueConstantRangeCallSiteArgument : AAValueConstantRangeFloating {
9776 AAValueConstantRangeCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
9777 : AAValueConstantRangeFloating(IRP,
A) {}
9781 return ChangeStatus::UNCHANGED;
9785 void trackStatistics()
const override {
9794struct AAPotentialConstantValuesImpl : AAPotentialConstantValues {
9797 AAPotentialConstantValuesImpl(
const IRPosition &IRP, Attributor &
A)
9798 : AAPotentialConstantValues(IRP,
A) {}
9802 if (
A.hasSimplificationCallback(getIRPosition()))
9803 indicatePessimisticFixpoint();
9805 AAPotentialConstantValues::initialize(
A);
9808 bool fillSetWithConstantValues(Attributor &
A,
const IRPosition &IRP, SetTy &S,
9809 bool &ContainsUndef,
bool ForSelf) {
9811 bool UsedAssumedInformation =
false;
9813 UsedAssumedInformation)) {
9820 auto *PotentialValuesAA =
A.getAAFor<AAPotentialConstantValues>(
9821 *
this, IRP, DepClassTy::REQUIRED);
9822 if (!PotentialValuesAA || !PotentialValuesAA->getState().isValidState())
9824 ContainsUndef = PotentialValuesAA->getState().undefIsContained();
9825 S = PotentialValuesAA->getState().getAssumedSet();
9832 ContainsUndef =
false;
9833 for (
auto &It :
Values) {
9835 ContainsUndef =
true;
9841 S.insert(CI->getValue());
9843 ContainsUndef &= S.empty();
9849 const std::string getAsStr(Attributor *
A)
const override {
9851 llvm::raw_string_ostream OS(Str);
9858 return indicatePessimisticFixpoint();
9862struct AAPotentialConstantValuesArgument final
9863 : AAArgumentFromCallSiteArguments<AAPotentialConstantValues,
9864 AAPotentialConstantValuesImpl,
9865 PotentialConstantIntValuesState> {
9866 using Base = AAArgumentFromCallSiteArguments<AAPotentialConstantValues,
9867 AAPotentialConstantValuesImpl,
9869 AAPotentialConstantValuesArgument(
const IRPosition &IRP, Attributor &
A)
9873 void trackStatistics()
const override {
9878struct AAPotentialConstantValuesReturned
9879 : AAReturnedFromReturnedValues<AAPotentialConstantValues,
9880 AAPotentialConstantValuesImpl> {
9881 using Base = AAReturnedFromReturnedValues<AAPotentialConstantValues,
9882 AAPotentialConstantValuesImpl>;
9883 AAPotentialConstantValuesReturned(
const IRPosition &IRP, Attributor &
A)
9887 if (!
A.isFunctionIPOAmendable(*getAssociatedFunction()))
9888 indicatePessimisticFixpoint();
9889 Base::initialize(
A);
9893 void trackStatistics()
const override {
9898struct AAPotentialConstantValuesFloating : AAPotentialConstantValuesImpl {
9899 AAPotentialConstantValuesFloating(
const IRPosition &IRP, Attributor &
A)
9900 : AAPotentialConstantValuesImpl(IRP,
A) {}
9904 AAPotentialConstantValuesImpl::initialize(
A);
9908 Value &
V = getAssociatedValue();
9911 unionAssumed(
C->getValue());
9912 indicateOptimisticFixpoint();
9917 unionAssumedWithUndef();
9918 indicateOptimisticFixpoint();
9928 indicatePessimisticFixpoint();
9931 << getAssociatedValue() <<
"\n");
9934 static bool calculateICmpInst(
const ICmpInst *ICI,
const APInt &
LHS,
9939 static APInt calculateCastInst(
const CastInst *CI,
const APInt &Src,
9940 uint32_t ResultBitWidth) {
9945 case Instruction::Trunc:
9946 return Src.trunc(ResultBitWidth);
9947 case Instruction::SExt:
9948 return Src.sext(ResultBitWidth);
9949 case Instruction::ZExt:
9950 return Src.zext(ResultBitWidth);
9951 case Instruction::BitCast:
9956 static APInt calculateBinaryOperator(
const BinaryOperator *BinOp,
9957 const APInt &
LHS,
const APInt &
RHS,
9958 bool &SkipOperation,
bool &Unsupported) {
9965 switch (BinOpcode) {
9969 case Instruction::Add:
9971 case Instruction::Sub:
9973 case Instruction::Mul:
9975 case Instruction::UDiv:
9977 SkipOperation =
true;
9981 case Instruction::SDiv:
9983 SkipOperation =
true;
9987 case Instruction::URem:
9989 SkipOperation =
true;
9993 case Instruction::SRem:
9995 SkipOperation =
true;
9999 case Instruction::Shl:
10001 case Instruction::LShr:
10003 case Instruction::AShr:
10005 case Instruction::And:
10007 case Instruction::Or:
10009 case Instruction::Xor:
10014 bool calculateBinaryOperatorAndTakeUnion(
const BinaryOperator *BinOp,
10015 const APInt &
LHS,
const APInt &
RHS) {
10016 bool SkipOperation =
false;
10019 calculateBinaryOperator(BinOp,
LHS,
RHS, SkipOperation, Unsupported);
10023 if (!SkipOperation)
10024 unionAssumed(Result);
10025 return isValidState();
10028 ChangeStatus updateWithICmpInst(Attributor &
A, ICmpInst *ICI) {
10029 auto AssumedBefore = getAssumed();
10033 bool LHSContainsUndef =
false, RHSContainsUndef =
false;
10034 SetTy LHSAAPVS, RHSAAPVS;
10036 LHSContainsUndef,
false) ||
10038 RHSContainsUndef,
false))
10039 return indicatePessimisticFixpoint();
10042 bool MaybeTrue =
false, MaybeFalse =
false;
10044 if (LHSContainsUndef && RHSContainsUndef) {
10047 unionAssumedWithUndef();
10048 }
else if (LHSContainsUndef) {
10049 for (
const APInt &R : RHSAAPVS) {
10050 bool CmpResult = calculateICmpInst(ICI, Zero, R);
10051 MaybeTrue |= CmpResult;
10052 MaybeFalse |= !CmpResult;
10053 if (MaybeTrue & MaybeFalse)
10054 return indicatePessimisticFixpoint();
10056 }
else if (RHSContainsUndef) {
10057 for (
const APInt &L : LHSAAPVS) {
10058 bool CmpResult = calculateICmpInst(ICI, L, Zero);
10059 MaybeTrue |= CmpResult;
10060 MaybeFalse |= !CmpResult;
10061 if (MaybeTrue & MaybeFalse)
10062 return indicatePessimisticFixpoint();
10065 for (
const APInt &L : LHSAAPVS) {
10066 for (
const APInt &R : RHSAAPVS) {
10067 bool CmpResult = calculateICmpInst(ICI, L, R);
10068 MaybeTrue |= CmpResult;
10069 MaybeFalse |= !CmpResult;
10070 if (MaybeTrue & MaybeFalse)
10071 return indicatePessimisticFixpoint();
10076 unionAssumed(APInt( 1, 1));
10078 unionAssumed(APInt( 1, 0));
10079 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10080 : ChangeStatus::CHANGED;
10083 ChangeStatus updateWithSelectInst(Attributor &
A, SelectInst *SI) {
10084 auto AssumedBefore = getAssumed();
10088 bool UsedAssumedInformation =
false;
10089 std::optional<Constant *>
C =
A.getAssumedConstant(
10090 *
SI->getCondition(), *
this, UsedAssumedInformation);
10093 bool OnlyLeft =
false, OnlyRight =
false;
10094 if (
C && *
C && (*C)->isOneValue())
10096 else if (
C && *
C && (*C)->isNullValue())
10099 bool LHSContainsUndef =
false, RHSContainsUndef =
false;
10100 SetTy LHSAAPVS, RHSAAPVS;
10103 LHSContainsUndef,
false))
10104 return indicatePessimisticFixpoint();
10108 RHSContainsUndef,
false))
10109 return indicatePessimisticFixpoint();
10111 if (OnlyLeft || OnlyRight) {
10113 auto *OpAA = OnlyLeft ? &LHSAAPVS : &RHSAAPVS;
10114 auto Undef = OnlyLeft ? LHSContainsUndef : RHSContainsUndef;
10117 unionAssumedWithUndef();
10119 for (
const auto &It : *OpAA)
10123 }
else if (LHSContainsUndef && RHSContainsUndef) {
10125 unionAssumedWithUndef();
10127 for (
const auto &It : LHSAAPVS)
10129 for (
const auto &It : RHSAAPVS)
10132 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10133 : ChangeStatus::CHANGED;
10136 ChangeStatus updateWithCastInst(Attributor &
A, CastInst *CI) {
10137 auto AssumedBefore = getAssumed();
10139 return indicatePessimisticFixpoint();
10144 bool SrcContainsUndef =
false;
10147 SrcContainsUndef,
false))
10148 return indicatePessimisticFixpoint();
10150 if (SrcContainsUndef)
10151 unionAssumedWithUndef();
10153 for (
const APInt &S : SrcPVS) {
10154 APInt
T = calculateCastInst(CI, S, ResultBitWidth);
10158 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10159 : ChangeStatus::CHANGED;
10162 ChangeStatus updateWithBinaryOperator(Attributor &
A, BinaryOperator *BinOp) {
10163 auto AssumedBefore = getAssumed();
10167 bool LHSContainsUndef =
false, RHSContainsUndef =
false;
10168 SetTy LHSAAPVS, RHSAAPVS;
10170 LHSContainsUndef,
false) ||
10172 RHSContainsUndef,
false))
10173 return indicatePessimisticFixpoint();
10178 if (LHSContainsUndef && RHSContainsUndef) {
10179 if (!calculateBinaryOperatorAndTakeUnion(BinOp, Zero, Zero))
10180 return indicatePessimisticFixpoint();
10181 }
else if (LHSContainsUndef) {
10182 for (
const APInt &R : RHSAAPVS) {
10183 if (!calculateBinaryOperatorAndTakeUnion(BinOp, Zero, R))
10184 return indicatePessimisticFixpoint();
10186 }
else if (RHSContainsUndef) {
10187 for (
const APInt &L : LHSAAPVS) {
10188 if (!calculateBinaryOperatorAndTakeUnion(BinOp, L, Zero))
10189 return indicatePessimisticFixpoint();
10192 for (
const APInt &L : LHSAAPVS) {
10193 for (
const APInt &R : RHSAAPVS) {
10194 if (!calculateBinaryOperatorAndTakeUnion(BinOp, L, R))
10195 return indicatePessimisticFixpoint();
10199 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10200 : ChangeStatus::CHANGED;
10203 ChangeStatus updateWithInstruction(Attributor &
A, Instruction *Inst) {
10204 auto AssumedBefore = getAssumed();
10206 bool ContainsUndef;
10208 ContainsUndef,
true))
10209 return indicatePessimisticFixpoint();
10210 if (ContainsUndef) {
10211 unionAssumedWithUndef();
10213 for (
const auto &It : Incoming)
10216 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10217 : ChangeStatus::CHANGED;
10222 Value &
V = getAssociatedValue();
10226 return updateWithICmpInst(
A, ICI);
10229 return updateWithSelectInst(
A, SI);
10232 return updateWithCastInst(
A, CI);
10235 return updateWithBinaryOperator(
A, BinOp);
10238 return updateWithInstruction(
A,
I);
10240 return indicatePessimisticFixpoint();
10244 void trackStatistics()
const override {
10249struct AAPotentialConstantValuesFunction : AAPotentialConstantValuesImpl {
10250 AAPotentialConstantValuesFunction(
const IRPosition &IRP, Attributor &
A)
10251 : AAPotentialConstantValuesImpl(IRP,
A) {}
10256 "AAPotentialConstantValues(Function|CallSite)::updateImpl will "
10261 void trackStatistics()
const override {
10266struct AAPotentialConstantValuesCallSite : AAPotentialConstantValuesFunction {
10267 AAPotentialConstantValuesCallSite(
const IRPosition &IRP, Attributor &
A)
10268 : AAPotentialConstantValuesFunction(IRP,
A) {}
10271 void trackStatistics()
const override {
10276struct AAPotentialConstantValuesCallSiteReturned
10277 : AACalleeToCallSite<AAPotentialConstantValues,
10278 AAPotentialConstantValuesImpl> {
10279 AAPotentialConstantValuesCallSiteReturned(
const IRPosition &IRP,
10281 : AACalleeToCallSite<AAPotentialConstantValues,
10282 AAPotentialConstantValuesImpl>(IRP,
A) {}
10285 void trackStatistics()
const override {
10290struct AAPotentialConstantValuesCallSiteArgument
10291 : AAPotentialConstantValuesFloating {
10292 AAPotentialConstantValuesCallSiteArgument(
const IRPosition &IRP,
10294 : AAPotentialConstantValuesFloating(IRP,
A) {}
10298 AAPotentialConstantValuesImpl::initialize(
A);
10299 if (isAtFixpoint())
10302 Value &
V = getAssociatedValue();
10305 unionAssumed(
C->getValue());
10306 indicateOptimisticFixpoint();
10311 unionAssumedWithUndef();
10312 indicateOptimisticFixpoint();
10319 Value &
V = getAssociatedValue();
10320 auto AssumedBefore = getAssumed();
10321 auto *AA =
A.getAAFor<AAPotentialConstantValues>(
10324 return indicatePessimisticFixpoint();
10325 const auto &S = AA->getAssumed();
10327 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10328 : ChangeStatus::CHANGED;
10332 void trackStatistics()
const override {
10341 bool IgnoreSubsumingPositions) {
10342 assert(ImpliedAttributeKind == Attribute::NoUndef &&
10343 "Unexpected attribute kind");
10344 if (
A.hasAttr(IRP, {Attribute::NoUndef}, IgnoreSubsumingPositions,
10345 Attribute::NoUndef))
10365 Value &V = getAssociatedValue();
10367 indicatePessimisticFixpoint();
10368 assert(!isImpliedByIR(
A, getIRPosition(), Attribute::NoUndef));
10372 bool followUseInMBEC(Attributor &
A,
const Use *U,
const Instruction *
I,
10373 AANoUndef::StateType &State) {
10374 const Value *UseV =
U->get();
10375 const DominatorTree *DT =
nullptr;
10376 AssumptionCache *AC =
nullptr;
10377 InformationCache &InfoCache =
A.getInfoCache();
10383 bool TrackUse =
false;
10392 const std::string getAsStr(Attributor *
A)
const override {
10393 return getAssumed() ?
"noundef" :
"may-undef-or-poison";
10400 bool UsedAssumedInformation =
false;
10401 if (
A.isAssumedDead(getIRPosition(),
nullptr,
nullptr,
10402 UsedAssumedInformation))
10403 return ChangeStatus::UNCHANGED;
10407 if (!
A.getAssumedSimplified(getIRPosition(), *
this, UsedAssumedInformation,
10410 return ChangeStatus::UNCHANGED;
10411 return AANoUndef::manifest(
A);
10415struct AANoUndefFloating :
public AANoUndefImpl {
10416 AANoUndefFloating(
const IRPosition &IRP, Attributor &
A)
10417 : AANoUndefImpl(IRP,
A) {}
10421 AANoUndefImpl::initialize(
A);
10422 if (!getState().isAtFixpoint() && getAnchorScope() &&
10423 !getAnchorScope()->isDeclaration())
10424 if (Instruction *CtxI = getCtxI())
10425 followUsesInMBEC(*
this,
A, getState(), *CtxI);
10430 auto VisitValueCB = [&](
const IRPosition &IRP) ->
bool {
10431 bool IsKnownNoUndef;
10433 A,
this, IRP, DepClassTy::REQUIRED, IsKnownNoUndef);
10437 bool UsedAssumedInformation =
false;
10438 Value *AssociatedValue = &getAssociatedValue();
10440 if (!
A.getAssumedSimplifiedValues(getIRPosition(), *
this,
Values,
10445 Values.size() != 1 ||
Values.front().getValue() != AssociatedValue;
10453 if (AVIRP == getIRPosition() || !VisitValueCB(AVIRP))
10454 return indicatePessimisticFixpoint();
10455 return ChangeStatus::UNCHANGED;
10458 for (
const auto &VAC :
Values)
10460 return indicatePessimisticFixpoint();
10462 return ChangeStatus::UNCHANGED;
10469struct AANoUndefReturned final
10470 : AAReturnedFromReturnedValues<AANoUndef, AANoUndefImpl> {
10471 AANoUndefReturned(
const IRPosition &IRP, Attributor &
A)
10472 : AAReturnedFromReturnedValues<AANoUndef, AANoUndefImpl>(IRP,
A) {}
10478struct AANoUndefArgument final
10479 : AAArgumentFromCallSiteArguments<AANoUndef, AANoUndefImpl> {
10480 AANoUndefArgument(
const IRPosition &IRP, Attributor &
A)
10481 : AAArgumentFromCallSiteArguments<AANoUndef, AANoUndefImpl>(IRP,
A) {}
10487struct AANoUndefCallSiteArgument final : AANoUndefFloating {
10488 AANoUndefCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
10489 : AANoUndefFloating(IRP,
A) {}
10495struct AANoUndefCallSiteReturned final
10496 : AACalleeToCallSite<AANoUndef, AANoUndefImpl> {
10497 AANoUndefCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
10498 : AACalleeToCallSite<AANoUndef, AANoUndefImpl>(IRP,
A) {}
10506struct AANoFPClassImpl : AANoFPClass {
10507 AANoFPClassImpl(
const IRPosition &IRP, Attributor &
A) : AANoFPClass(IRP,
A) {}
10510 const IRPosition &IRP = getIRPosition();
10514 indicateOptimisticFixpoint();
10519 A.getAttrs(getIRPosition(), {Attribute::NoFPClass},
Attrs,
false);
10520 for (
const auto &Attr : Attrs) {
10527 const DataLayout &
DL =
A.getDataLayout();
10528 InformationCache &InfoCache =
A.getInfoCache();
10530 const DominatorTree *DT =
nullptr;
10531 AssumptionCache *AC =
nullptr;
10532 const TargetLibraryInfo *TLI =
nullptr;
10536 if (!
F->isDeclaration()) {
10543 SimplifyQuery Q(
DL, TLI, DT, AC, CtxI);
10550 followUsesInMBEC(*
this,
A, getState(), *CtxI);
10554 bool followUseInMBEC(Attributor &
A,
const Use *U,
const Instruction *
I,
10555 AANoFPClass::StateType &State) {
10566 if (
auto *NoFPAA =
A.getAAFor<AANoFPClass>(*
this, IRP, DepClassTy::NONE))
10567 State.addKnownBits(NoFPAA->getState().getKnown());
10571 const std::string getAsStr(Attributor *
A)
const override {
10572 std::string
Result =
"nofpclass";
10573 raw_string_ostream OS(Result);
10574 OS << getKnownNoFPClass() <<
'/' << getAssumedNoFPClass();
10578 void getDeducedAttributes(Attributor &
A, LLVMContext &Ctx,
10579 SmallVectorImpl<Attribute> &Attrs)
const override {
10580 Attrs.emplace_back(Attribute::getWithNoFPClass(Ctx, getAssumedNoFPClass()));
10584struct AANoFPClassFloating :
public AANoFPClassImpl {
10585 AANoFPClassFloating(
const IRPosition &IRP, Attributor &
A)
10586 : AANoFPClassImpl(IRP,
A) {}
10591 bool UsedAssumedInformation =
false;
10592 if (!
A.getAssumedSimplifiedValues(getIRPosition(), *
this,
Values,
10594 Values.push_back({getAssociatedValue(), getCtxI()});
10600 DepClassTy::REQUIRED);
10601 if (!AA ||
this == AA) {
10602 T.indicatePessimisticFixpoint();
10604 const AANoFPClass::StateType &S =
10605 static_cast<const AANoFPClass::StateType &
>(AA->
getState());
10608 return T.isValidState();
10611 for (
const auto &VAC :
Values)
10613 return indicatePessimisticFixpoint();
10619 void trackStatistics()
const override {
10624struct AANoFPClassReturned final
10625 : AAReturnedFromReturnedValues<AANoFPClass, AANoFPClassImpl,
10626 AANoFPClassImpl::StateType, false,
10627 Attribute::None, false> {
10628 AANoFPClassReturned(
const IRPosition &IRP, Attributor &
A)
10629 : AAReturnedFromReturnedValues<AANoFPClass, AANoFPClassImpl,
10630 AANoFPClassImpl::StateType,
false,
10634 void trackStatistics()
const override {
10639struct AANoFPClassArgument final
10640 : AAArgumentFromCallSiteArguments<AANoFPClass, AANoFPClassImpl> {
10641 AANoFPClassArgument(
const IRPosition &IRP, Attributor &
A)
10642 : AAArgumentFromCallSiteArguments<AANoFPClass, AANoFPClassImpl>(IRP,
A) {}
10648struct AANoFPClassCallSiteArgument final : AANoFPClassFloating {
10649 AANoFPClassCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
10650 : AANoFPClassFloating(IRP,
A) {}
10653 void trackStatistics()
const override {
10658struct AANoFPClassCallSiteReturned final
10659 : AACalleeToCallSite<AANoFPClass, AANoFPClassImpl> {
10660 AANoFPClassCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
10661 : AACalleeToCallSite<AANoFPClass, AANoFPClassImpl>(IRP,
A) {}
10664 void trackStatistics()
const override {
10669struct AACallEdgesImpl :
public AACallEdges {
10670 AACallEdgesImpl(
const IRPosition &IRP, Attributor &
A) : AACallEdges(IRP,
A) {}
10672 const SetVector<Function *> &getOptimisticEdges()
const override {
10673 return CalledFunctions;
10676 bool hasUnknownCallee()
const override {
return HasUnknownCallee; }
10678 bool hasNonAsmUnknownCallee()
const override {
10679 return HasUnknownCalleeNonAsm;
10682 const std::string getAsStr(Attributor *
A)
const override {
10683 return "CallEdges[" + std::to_string(HasUnknownCallee) +
"," +
10684 std::to_string(CalledFunctions.size()) +
"]";
10687 void trackStatistics()
const override {}
10691 if (CalledFunctions.insert(Fn)) {
10692 Change = ChangeStatus::CHANGED;
10698 void setHasUnknownCallee(
bool NonAsm,
ChangeStatus &Change) {
10699 if (!HasUnknownCallee)
10700 Change = ChangeStatus::CHANGED;
10701 if (NonAsm && !HasUnknownCalleeNonAsm)
10702 Change = ChangeStatus::CHANGED;
10703 HasUnknownCalleeNonAsm |= NonAsm;
10704 HasUnknownCallee =
true;
10709 SetVector<Function *> CalledFunctions;
10712 bool HasUnknownCallee =
false;
10715 bool HasUnknownCalleeNonAsm =
false;
10718struct AACallEdgesCallSite :
public AACallEdgesImpl {
10719 AACallEdgesCallSite(
const IRPosition &IRP, Attributor &
A)
10720 : AACallEdgesImpl(IRP,
A) {}
10727 addCalledFunction(Fn, Change);
10729 LLVM_DEBUG(
dbgs() <<
"[AACallEdges] Unrecognized value: " << V <<
"\n");
10730 setHasUnknownCallee(
true, Change);
10741 VisitValue(*V, CtxI);
10745 bool UsedAssumedInformation =
false;
10749 Values.push_back({*
V, CtxI});
10751 for (
auto &VAC :
Values)
10758 if (
IA->hasSideEffects() &&
10761 setHasUnknownCallee(
false, Change);
10767 if (
auto *IndirectCallAA =
A.getAAFor<AAIndirectCallInfo>(
10768 *
this, getIRPosition(), DepClassTy::OPTIONAL))
10769 if (IndirectCallAA->foreachCallee(
10770 [&](
Function *Fn) { return VisitValue(*Fn, CB); }))
10779 for (
const Use *U : CallbackUses)
10780 ProcessCalledOperand(
U->get(), CB);
10786struct AACallEdgesFunction :
public AACallEdgesImpl {
10787 AACallEdgesFunction(
const IRPosition &IRP, Attributor &
A)
10788 : AACallEdgesImpl(IRP,
A) {}
10797 auto *CBEdges =
A.getAAFor<AACallEdges>(
10801 if (CBEdges->hasNonAsmUnknownCallee())
10802 setHasUnknownCallee(
true, Change);
10803 if (CBEdges->hasUnknownCallee())
10804 setHasUnknownCallee(
false, Change);
10806 for (
Function *
F : CBEdges->getOptimisticEdges())
10807 addCalledFunction(
F, Change);
10813 bool UsedAssumedInformation =
false;
10814 if (!
A.checkForAllCallLikeInstructions(ProcessCallInst, *
this,
10815 UsedAssumedInformation,
10819 setHasUnknownCallee(
true, Change);
10828struct AAInterFnReachabilityFunction
10829 :
public CachedReachabilityAA<AAInterFnReachability, Function> {
10830 using Base = CachedReachabilityAA<AAInterFnReachability, Function>;
10831 AAInterFnReachabilityFunction(
const IRPosition &IRP, Attributor &
A)
10834 bool instructionCanReach(
10835 Attributor &
A,
const Instruction &From,
const Function &To,
10838 auto *NonConstThis =
const_cast<AAInterFnReachabilityFunction *
>(
this);
10840 RQITy StackRQI(
A, From, To, ExclusionSet,
false);
10841 RQITy::Reachable
Result;
10842 if (!NonConstThis->checkQueryCache(
A, StackRQI, Result))
10843 return NonConstThis->isReachableImpl(
A, StackRQI,
10845 return Result == RQITy::Reachable::Yes;
10849 bool IsTemporaryRQI)
override {
10851 &RQI.From->getFunction()->getEntryBlock().front();
10852 if (EntryI != RQI.From &&
10853 !instructionCanReach(
A, *EntryI, *RQI.To,
nullptr))
10854 return rememberResult(
A, RQITy::Reachable::No, RQI,
false,
10857 auto CheckReachableCallBase = [&](CallBase *CB) {
10858 auto *CBEdges =
A.getAAFor<AACallEdges>(
10860 if (!CBEdges || !CBEdges->getState().isValidState())
10863 if (CBEdges->hasUnknownCallee())
10866 for (
Function *Fn : CBEdges->getOptimisticEdges()) {
10877 if (Fn == getAnchorScope()) {
10878 if (EntryI == RQI.From)
10883 const AAInterFnReachability *InterFnReachability =
10885 DepClassTy::OPTIONAL);
10888 if (!InterFnReachability ||
10896 const auto *IntraFnReachability =
A.getAAFor<AAIntraFnReachability>(
10898 DepClassTy::OPTIONAL);
10906 return IntraFnReachability && !IntraFnReachability->isAssumedReachable(
10907 A, *RQI.From, CBInst, RQI.ExclusionSet);
10910 bool UsedExclusionSet =
true;
10911 bool UsedAssumedInformation =
false;
10912 if (!
A.checkForAllCallLikeInstructions(CheckCallBase, *
this,
10913 UsedAssumedInformation,
10915 return rememberResult(
A, RQITy::Reachable::Yes, RQI, UsedExclusionSet,
10918 return rememberResult(
A, RQITy::Reachable::No, RQI, UsedExclusionSet,
10922 void trackStatistics()
const override {}
10926template <
typename AAType>
10927static std::optional<Constant *>
10930 if (!Ty.isIntegerTy())
10938 std::optional<Constant *> COpt =
AA->getAssumedConstant(
A);
10940 if (!COpt.has_value()) {
10942 return std::nullopt;
10944 if (
auto *
C = *COpt) {
10955 std::optional<Value *> V;
10956 for (
auto &It :
Values) {
10958 if (V.has_value() && !*V)
10961 if (!V.has_value())
10975 if (
A.hasSimplificationCallback(getIRPosition())) {
10976 indicatePessimisticFixpoint();
10979 Value *Stripped = getAssociatedValue().stripPointerCasts();
10981 addValue(
A, getState(), *Stripped, getCtxI(),
AA::AnyScope,
10983 indicateOptimisticFixpoint();
10986 AAPotentialValues::initialize(
A);
10990 const std::string getAsStr(Attributor *
A)
const override {
10992 llvm::raw_string_ostream OS(Str);
10997 template <
typename AAType>
10998 static std::optional<Value *> askOtherAA(Attributor &
A,
10999 const AbstractAttribute &AA,
11000 const IRPosition &IRP,
Type &Ty) {
11005 return std::nullopt;
11012 virtual void addValue(Attributor &
A, StateType &State,
Value &V,
11018 for (
const auto &U : CB->
args()) {
11028 Type &Ty = *getAssociatedType();
11029 std::optional<Value *> SimpleV =
11030 askOtherAA<AAValueConstantRange>(
A, *
this, ValIRP, Ty);
11031 if (SimpleV.has_value() && !*SimpleV) {
11032 auto *PotentialConstantsAA =
A.getAAFor<AAPotentialConstantValues>(
11033 *
this, ValIRP, DepClassTy::OPTIONAL);
11034 if (PotentialConstantsAA && PotentialConstantsAA->isValidState()) {
11035 for (
const auto &It : PotentialConstantsAA->getAssumedSet())
11036 State.unionAssumed({{*ConstantInt::get(&Ty, It),
nullptr}, S});
11037 if (PotentialConstantsAA->undefIsContained())
11042 if (!SimpleV.has_value())
11054 State.unionAssumed({{*VPtr, CtxI}, S});
11060 AA::ValueAndContext
I;
11064 return II.I ==
I &&
II.S == S;
11067 return std::tie(
I, S) < std::tie(
II.I,
II.S);
11071 bool recurseForValue(Attributor &
A,
const IRPosition &IRP,
AA::ValueScope S) {
11072 SmallMapVector<AA::ValueAndContext, int, 8> ValueScopeMap;
11077 bool UsedAssumedInformation =
false;
11079 if (!
A.getAssumedSimplifiedValues(IRP,
this,
Values, CS,
11080 UsedAssumedInformation))
11084 ValueScopeMap[It] += CS;
11086 for (
auto &It : ValueScopeMap)
11087 addValue(
A, getState(), *It.first.getValue(), It.first.getCtxI(),
11093 void giveUpOnIntraprocedural(Attributor &
A) {
11094 auto NewS = StateType::getBestState(getState());
11095 for (
const auto &It : getAssumedSet()) {
11098 addValue(
A, NewS, *It.first.getValue(), It.first.getCtxI(),
11101 assert(!undefIsContained() &&
"Undef should be an explicit value!");
11109 getState() = StateType::getBestState(getState());
11110 getState().unionAssumed({{getAssociatedValue(), getCtxI()},
AA::AnyScope});
11111 AAPotentialValues::indicateOptimisticFixpoint();
11112 return ChangeStatus::CHANGED;
11117 return indicatePessimisticFixpoint();
11125 if (!getAssumedSimplifiedValues(
A,
Values, S))
11127 Value &OldV = getAssociatedValue();
11130 Value *NewV = getSingleValue(
A, *
this, getIRPosition(),
Values);
11131 if (!NewV || NewV == &OldV)
11136 if (
A.changeAfterManifest(getIRPosition(), *NewV))
11137 return ChangeStatus::CHANGED;
11139 return ChangeStatus::UNCHANGED;
11142 bool getAssumedSimplifiedValues(
11143 Attributor &
A, SmallVectorImpl<AA::ValueAndContext> &
Values,
11144 AA::ValueScope S,
bool RecurseForSelectAndPHI =
false)
const override {
11145 if (!isValidState())
11147 bool UsedAssumedInformation =
false;
11148 for (
const auto &It : getAssumedSet())
11149 if (It.second & S) {
11150 if (RecurseForSelectAndPHI && (
isa<PHINode>(It.first.getValue()) ||
11152 if (
A.getAssumedSimplifiedValues(
11154 this,
Values, S, UsedAssumedInformation))
11157 Values.push_back(It.first);
11159 assert(!undefIsContained() &&
"Undef should be an explicit value!");
11164struct AAPotentialValuesFloating : AAPotentialValuesImpl {
11165 AAPotentialValuesFloating(
const IRPosition &IRP, Attributor &
A)
11166 : AAPotentialValuesImpl(IRP,
A) {}
11170 auto AssumedBefore = getAssumed();
11172 genericValueTraversal(
A, &getAssociatedValue());
11174 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
11175 : ChangeStatus::CHANGED;
11179 struct LivenessInfo {
11180 const AAIsDead *LivenessAA =
nullptr;
11181 bool AnyDead =
false;
11191 SmallVectorImpl<ItemInfo> &Worklist) {
11194 bool UsedAssumedInformation =
false;
11196 auto GetSimplifiedValues = [&](
Value &
V,
11198 if (!
A.getAssumedSimplifiedValues(
11202 Values.push_back(AA::ValueAndContext{
V,
II.I.getCtxI()});
11206 if (GetSimplifiedValues(*
LHS, LHSValues))
11208 if (GetSimplifiedValues(*
RHS, RHSValues))
11213 InformationCache &InfoCache =
A.getInfoCache();
11220 F ?
A.getInfoCache().getTargetLibraryInfoForFunction(*
F) :
nullptr;
11225 const DataLayout &
DL =
A.getDataLayout();
11226 SimplifyQuery Q(
DL, TLI, DT, AC, CmpI);
11228 auto CheckPair = [&](
Value &LHSV,
Value &RHSV) {
11231 nullptr,
II.S, getAnchorScope());
11237 if (&LHSV == &RHSV &&
11239 Constant *NewV = ConstantInt::get(Type::getInt1Ty(Ctx),
11241 addValue(
A, getState(), *NewV,
nullptr,
II.S,
11248 if (TypedLHS && TypedRHS) {
11250 if (NewV && NewV != &Cmp) {
11251 addValue(
A, getState(), *NewV,
nullptr,
II.S,
11263 if (!LHSIsNull && !RHSIsNull)
11269 assert((LHSIsNull || RHSIsNull) &&
11270 "Expected nullptr versus non-nullptr comparison at this point");
11273 unsigned PtrIdx = LHSIsNull;
11274 bool IsKnownNonNull;
11277 DepClassTy::REQUIRED, IsKnownNonNull);
11278 if (!IsAssumedNonNull)
11284 addValue(
A, getState(), *NewV,
nullptr,
II.S,
11289 for (
auto &LHSValue : LHSValues)
11290 for (
auto &RHSValue : RHSValues)
11291 if (!CheckPair(*LHSValue.getValue(), *RHSValue.getValue()))
11296 bool handleSelectInst(Attributor &
A, SelectInst &SI, ItemInfo
II,
11297 SmallVectorImpl<ItemInfo> &Worklist) {
11299 bool UsedAssumedInformation =
false;
11301 std::optional<Constant *>
C =
11302 A.getAssumedConstant(*
SI.getCondition(), *
this, UsedAssumedInformation);
11303 bool NoValueYet = !
C.has_value();
11311 }
else if (&SI == &getAssociatedValue()) {
11316 std::optional<Value *> SimpleV =
A.getAssumedSimplified(
11318 if (!SimpleV.has_value())
11321 addValue(
A, getState(), **SimpleV, CtxI,
II.S, getAnchorScope());
11329 bool handleLoadInst(Attributor &
A, LoadInst &LI, ItemInfo
II,
11330 SmallVectorImpl<ItemInfo> &Worklist) {
11331 SmallSetVector<Value *, 4> PotentialCopies;
11332 SmallSetVector<Instruction *, 4> PotentialValueOrigins;
11333 bool UsedAssumedInformation =
false;
11335 PotentialValueOrigins, *
this,
11336 UsedAssumedInformation,
11338 LLVM_DEBUG(
dbgs() <<
"[AAPotentialValues] Failed to get potentially "
11339 "loaded values for load instruction "
11347 InformationCache &InfoCache =
A.getInfoCache();
11349 if (!
llvm::all_of(PotentialValueOrigins, [&](Instruction *
I) {
11353 return A.isAssumedDead(
SI->getOperandUse(0),
this,
11355 UsedAssumedInformation,
11357 return A.isAssumedDead(*
I,
this,
nullptr,
11358 UsedAssumedInformation,
11361 LLVM_DEBUG(
dbgs() <<
"[AAPotentialValues] Load is onl used by assumes "
11362 "and we cannot delete all the stores: "
11373 bool AllLocal = ScopeIsLocal;
11378 if (!DynamicallyUnique) {
11379 LLVM_DEBUG(
dbgs() <<
"[AAPotentialValues] Not all potentially loaded "
11380 "values are dynamically unique: "
11385 for (
auto *PotentialCopy : PotentialCopies) {
11387 Worklist.
push_back({{*PotentialCopy, CtxI},
II.S});
11392 if (!AllLocal && ScopeIsLocal)
11397 bool handlePHINode(
11398 Attributor &
A, PHINode &
PHI, ItemInfo
II,
11399 SmallVectorImpl<ItemInfo> &Worklist,
11400 SmallMapVector<const Function *, LivenessInfo, 4> &LivenessAAs) {
11401 auto GetLivenessInfo = [&](
const Function &
F) -> LivenessInfo & {
11402 LivenessInfo &LI = LivenessAAs[&
F];
11403 if (!LI.LivenessAA)
11409 if (&
PHI == &getAssociatedValue()) {
11410 LivenessInfo &LI = GetLivenessInfo(*
PHI.getFunction());
11412 A.getInfoCache().getAnalysisResultForFunction<CycleAnalysis>(
11413 *
PHI.getFunction());
11417 for (
unsigned u = 0, e =
PHI.getNumIncomingValues(); u < e; u++) {
11419 if (LI.LivenessAA &&
11420 LI.LivenessAA->isEdgeDead(IncomingBB,
PHI.getParent())) {
11439 bool UsedAssumedInformation =
false;
11440 std::optional<Value *> SimpleV =
A.getAssumedSimplified(
11442 if (!SimpleV.has_value())
11446 addValue(
A, getState(), **SimpleV, &
PHI,
II.S, getAnchorScope());
11453 bool handleGenericInst(Attributor &
A, Instruction &
I, ItemInfo
II,
11454 SmallVectorImpl<ItemInfo> &Worklist) {
11455 bool SomeSimplified =
false;
11456 bool UsedAssumedInformation =
false;
11458 SmallVector<Value *, 8> NewOps(
I.getNumOperands());
11461 const auto &SimplifiedOp =
A.getAssumedSimplified(
11466 if (!SimplifiedOp.has_value())
11470 NewOps[
Idx] = *SimplifiedOp;
11474 SomeSimplified |= (NewOps[
Idx] !=
Op);
11480 if (!SomeSimplified)
11483 InformationCache &InfoCache =
A.getInfoCache();
11487 const auto *TLI =
A.getInfoCache().getTargetLibraryInfoForFunction(*
F);
11490 const DataLayout &
DL =
I.getDataLayout();
11491 SimplifyQuery Q(
DL, TLI, DT, AC, &
I);
11493 if (!NewV || NewV == &
I)
11496 LLVM_DEBUG(
dbgs() <<
"Generic inst " <<
I <<
" assumed simplified to "
11503 Attributor &
A, Instruction &
I, ItemInfo
II,
11504 SmallVectorImpl<ItemInfo> &Worklist,
11505 SmallMapVector<const Function *, LivenessInfo, 4> &LivenessAAs) {
11508 CI->getPredicate(),
II, Worklist);
11510 switch (
I.getOpcode()) {
11511 case Instruction::Select:
11513 case Instruction::PHI:
11515 case Instruction::Load:
11518 return handleGenericInst(
A,
I,
II, Worklist);
11523 void genericValueTraversal(Attributor &
A,
Value *InitialV) {
11524 SmallMapVector<const Function *, LivenessInfo, 4> LivenessAAs;
11526 SmallSet<ItemInfo, 16> Visited;
11545 LLVM_DEBUG(
dbgs() <<
"Generic value traversal reached iteration limit: "
11546 << Iteration <<
"!\n");
11547 addValue(
A, getState(), *V, CtxI, S, getAnchorScope());
11553 Value *NewV =
nullptr;
11554 if (
V->getType()->isPointerTy()) {
11560 for (Argument &Arg :
Callee->args())
11567 if (NewV && NewV != V) {
11568 Worklist.
push_back({{*NewV, CtxI}, S});
11582 if (V == InitialV && CtxI == getCtxI()) {
11583 indicatePessimisticFixpoint();
11587 addValue(
A, getState(), *V, CtxI, S, getAnchorScope());
11588 }
while (!Worklist.
empty());
11592 for (
auto &It : LivenessAAs)
11593 if (It.second.AnyDead)
11594 A.recordDependence(*It.second.LivenessAA, *
this, DepClassTy::OPTIONAL);
11598 void trackStatistics()
const override {
11603struct AAPotentialValuesArgument final : AAPotentialValuesImpl {
11604 using Base = AAPotentialValuesImpl;
11605 AAPotentialValuesArgument(
const IRPosition &IRP, Attributor &
A)
11612 indicatePessimisticFixpoint();
11617 auto AssumedBefore = getAssumed();
11619 unsigned ArgNo = getCalleeArgNo();
11621 bool UsedAssumedInformation =
false;
11623 auto CallSitePred = [&](AbstractCallSite ACS) {
11625 if (CSArgIRP.getPositionKind() == IRP_INVALID)
11628 if (!
A.getAssumedSimplifiedValues(CSArgIRP,
this,
Values,
11630 UsedAssumedInformation))
11633 return isValidState();
11636 if (!
A.checkForAllCallSites(CallSitePred, *
this,
11638 UsedAssumedInformation))
11639 return indicatePessimisticFixpoint();
11641 Function *Fn = getAssociatedFunction();
11642 bool AnyNonLocal =
false;
11643 for (
auto &It :
Values) {
11645 addValue(
A, getState(), *It.getValue(), It.getCtxI(),
AA::AnyScope,
11650 return indicatePessimisticFixpoint();
11654 addValue(
A, getState(), *It.getValue(), It.getCtxI(),
AA::AnyScope,
11660 AnyNonLocal =
true;
11662 assert(!undefIsContained() &&
"Undef should be an explicit value!");
11664 giveUpOnIntraprocedural(
A);
11666 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
11667 : ChangeStatus::CHANGED;
11671 void trackStatistics()
const override {
11676struct AAPotentialValuesReturned :
public AAPotentialValuesFloating {
11677 using Base = AAPotentialValuesFloating;
11678 AAPotentialValuesReturned(
const IRPosition &IRP, Attributor &
A)
11684 if (!
F ||
F->isDeclaration() ||
F->getReturnType()->isVoidTy()) {
11685 indicatePessimisticFixpoint();
11689 for (Argument &Arg :
F->args())
11692 ReturnedArg = &Arg;
11695 if (!
A.isFunctionIPOAmendable(*
F) ||
11696 A.hasSimplificationCallback(getIRPosition())) {
11698 indicatePessimisticFixpoint();
11700 indicateOptimisticFixpoint();
11706 auto AssumedBefore = getAssumed();
11707 bool UsedAssumedInformation =
false;
11710 Function *AnchorScope = getAnchorScope();
11716 UsedAssumedInformation,
11722 bool AllInterAreIntra =
false;
11729 for (
const AA::ValueAndContext &VAC :
Values) {
11730 addValue(
A, getState(), *VAC.
getValue(),
11734 if (AllInterAreIntra)
11741 HandleReturnedValue(*ReturnedArg,
nullptr,
true);
11744 bool AddValues =
true;
11747 addValue(
A, getState(), *RetI.getOperand(0), &RetI,
AA::AnyScope,
11751 return HandleReturnedValue(*RetI.getOperand(0), &RetI, AddValues);
11754 if (!
A.checkForAllInstructions(RetInstPred, *
this, {Instruction::Ret},
11755 UsedAssumedInformation,
11757 return indicatePessimisticFixpoint();
11760 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
11761 : ChangeStatus::CHANGED;
11766 return ChangeStatus::UNCHANGED;
11768 if (!getAssumedSimplifiedValues(
A,
Values, AA::ValueScope::Intraprocedural,
11770 return ChangeStatus::UNCHANGED;
11771 Value *NewVal = getSingleValue(
A, *
this, getIRPosition(),
Values);
11773 return ChangeStatus::UNCHANGED;
11778 "Number of function with unique return");
11781 {Attribute::get(Arg->
getContext(), Attribute::Returned)});
11786 Value *RetOp = RetI.getOperand(0);
11790 if (
A.changeUseAfterManifest(RetI.getOperandUse(0), *NewVal))
11791 Changed = ChangeStatus::CHANGED;
11794 bool UsedAssumedInformation =
false;
11795 (void)
A.checkForAllInstructions(RetInstPred, *
this, {Instruction::Ret},
11796 UsedAssumedInformation,
11802 return AAPotentialValues::indicatePessimisticFixpoint();
11806 void trackStatistics()
const override{
11813struct AAPotentialValuesFunction : AAPotentialValuesImpl {
11814 AAPotentialValuesFunction(
const IRPosition &IRP, Attributor &
A)
11815 : AAPotentialValuesImpl(IRP,
A) {}
11824 void trackStatistics()
const override {
11829struct AAPotentialValuesCallSite : AAPotentialValuesFunction {
11830 AAPotentialValuesCallSite(
const IRPosition &IRP, Attributor &
A)
11831 : AAPotentialValuesFunction(IRP,
A) {}
11834 void trackStatistics()
const override {
11839struct AAPotentialValuesCallSiteReturned : AAPotentialValuesImpl {
11840 AAPotentialValuesCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
11841 : AAPotentialValuesImpl(IRP,
A) {}
11845 auto AssumedBefore = getAssumed();
11849 return indicatePessimisticFixpoint();
11851 bool UsedAssumedInformation =
false;
11855 UsedAssumedInformation))
11856 return indicatePessimisticFixpoint();
11863 Values, S, UsedAssumedInformation))
11866 for (
auto &It :
Values) {
11867 Value *
V = It.getValue();
11868 std::optional<Value *> CallerV =
A.translateArgumentToCallSiteContent(
11869 V, *CB, *
this, UsedAssumedInformation);
11870 if (!CallerV.has_value()) {
11874 V = *CallerV ? *CallerV :
V;
11880 giveUpOnIntraprocedural(
A);
11883 addValue(
A, getState(), *V, CB, S, getAnchorScope());
11888 return indicatePessimisticFixpoint();
11890 return indicatePessimisticFixpoint();
11891 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
11892 : ChangeStatus::CHANGED;
11896 return AAPotentialValues::indicatePessimisticFixpoint();
11900 void trackStatistics()
const override {
11905struct AAPotentialValuesCallSiteArgument : AAPotentialValuesFloating {
11906 AAPotentialValuesCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
11907 : AAPotentialValuesFloating(IRP,
A) {}
11910 void trackStatistics()
const override {
11918struct AAAssumptionInfoImpl :
public AAAssumptionInfo {
11919 AAAssumptionInfoImpl(
const IRPosition &IRP, Attributor &
A,
11920 const DenseSet<StringRef> &
Known)
11921 : AAAssumptionInfo(IRP,
A,
Known) {}
11926 if (getKnown().isUniversal())
11927 return ChangeStatus::UNCHANGED;
11929 const IRPosition &IRP = getIRPosition();
11931 getAssumed().getSet().
end());
11933 return A.manifestAttrs(IRP,
11940 bool hasAssumption(
const StringRef Assumption)
const override {
11941 return isValidState() && setContains(Assumption);
11945 const std::string getAsStr(Attributor *
A)
const override {
11946 const SetContents &
Known = getKnown();
11947 const SetContents &Assumed = getAssumed();
11951 const std::string KnownStr =
llvm::join(Set,
",");
11953 std::string AssumedStr =
"Universal";
11954 if (!Assumed.isUniversal()) {
11955 Set.assign(Assumed.getSet().begin(), Assumed.getSet().end());
11958 return "Known [" + KnownStr +
"]," +
" Assumed [" + AssumedStr +
"]";
11973struct AAAssumptionInfoFunction final : AAAssumptionInfoImpl {
11974 AAAssumptionInfoFunction(
const IRPosition &IRP, Attributor &
A)
11975 : AAAssumptionInfoImpl(IRP,
A,
11982 auto CallSitePred = [&](AbstractCallSite ACS) {
11983 const auto *AssumptionAA =
A.getAAFor<AAAssumptionInfo>(
11985 DepClassTy::REQUIRED);
11989 Changed |= getIntersection(AssumptionAA->getAssumed());
11990 return !getAssumed().empty() || !getKnown().empty();
11993 bool UsedAssumedInformation =
false;
11998 if (!
A.checkForAllCallSites(CallSitePred, *
this,
true,
11999 UsedAssumedInformation))
12000 return indicatePessimisticFixpoint();
12002 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
12005 void trackStatistics()
const override {}
12009struct AAAssumptionInfoCallSite final : AAAssumptionInfoImpl {
12011 AAAssumptionInfoCallSite(
const IRPosition &IRP, Attributor &
A)
12012 : AAAssumptionInfoImpl(IRP,
A, getInitialAssumptions(IRP)) {}
12017 A.getAAFor<AAAssumptionInfo>(*
this, FnPos, DepClassTy::REQUIRED);
12023 auto *AssumptionAA =
12024 A.getAAFor<AAAssumptionInfo>(*
this, FnPos, DepClassTy::REQUIRED);
12026 return indicatePessimisticFixpoint();
12027 bool Changed = getIntersection(AssumptionAA->getAssumed());
12028 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
12032 void trackStatistics()
const override {}
12037 DenseSet<StringRef> getInitialAssumptions(
const IRPosition &IRP) {
12044 return Assumptions;
12059struct AAUnderlyingObjectsImpl
12065 const std::string getAsStr(
Attributor *
A)
const override {
12066 if (!isValidState())
12067 return "<invalid>";
12070 OS <<
"underlying objects: inter " << InterAssumedUnderlyingObjects.size()
12071 <<
" objects, intra " << IntraAssumedUnderlyingObjects.size()
12073 if (!InterAssumedUnderlyingObjects.empty()) {
12074 OS <<
"inter objects:\n";
12075 for (
auto *Obj : InterAssumedUnderlyingObjects)
12076 OS << *Obj <<
'\n';
12078 if (!IntraAssumedUnderlyingObjects.empty()) {
12079 OS <<
"intra objects:\n";
12080 for (
auto *Obj : IntraAssumedUnderlyingObjects)
12081 OS << *
Obj <<
'\n';
12087 void trackStatistics()
const override {}
12091 auto &Ptr = getAssociatedValue();
12093 bool UsedAssumedInformation =
false;
12094 auto DoUpdate = [&](SmallSetVector<Value *, 8> &UnderlyingObjects,
12096 SmallPtrSet<Value *, 8> SeenObjects;
12100 Scope, UsedAssumedInformation))
12101 return UnderlyingObjects.
insert(&Ptr);
12105 for (
unsigned I = 0;
I <
Values.size(); ++
I) {
12109 if (!SeenObjects.
insert(UO ? UO : Obj).second)
12111 if (UO && UO != Obj) {
12117 const auto *OtherAA =
A.getAAFor<AAUnderlyingObjects>(
12119 auto Pred = [&](
Value &
V) {
12123 Values.emplace_back(V,
nullptr);
12127 if (!OtherAA || !OtherAA->forallUnderlyingObjects(Pred, Scope))
12129 "The forall call should not return false at this position");
12135 Changed |= handleIndirect(
A, *Obj, UnderlyingObjects, Scope,
12136 UsedAssumedInformation);
12142 for (
unsigned u = 0, e =
PHI->getNumIncomingValues(); u < e; u++) {
12144 handleIndirect(
A, *
PHI->getIncomingValue(u), UnderlyingObjects,
12145 Scope, UsedAssumedInformation);
12159 if (!UsedAssumedInformation)
12160 indicateOptimisticFixpoint();
12161 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
12164 bool forallUnderlyingObjects(
12165 function_ref<
bool(
Value &)> Pred,
12167 if (!isValidState())
12168 return Pred(getAssociatedValue());
12171 ? IntraAssumedUnderlyingObjects
12172 : InterAssumedUnderlyingObjects;
12173 for (
Value *Obj : AssumedUnderlyingObjects)
12183 bool handleIndirect(Attributor &
A,
Value &V,
12184 SmallSetVector<Value *, 8> &UnderlyingObjects,
12187 const auto *AA =
A.getAAFor<AAUnderlyingObjects>(
12189 auto Pred = [&](
Value &
V) {
12193 if (!AA || !AA->forallUnderlyingObjects(Pred, Scope))
12195 "The forall call should not return false at this position");
12201 SmallSetVector<Value *, 8> IntraAssumedUnderlyingObjects;
12203 SmallSetVector<Value *, 8> InterAssumedUnderlyingObjects;
12206struct AAUnderlyingObjectsFloating final : AAUnderlyingObjectsImpl {
12207 AAUnderlyingObjectsFloating(
const IRPosition &IRP, Attributor &
A)
12208 : AAUnderlyingObjectsImpl(IRP,
A) {}
12211struct AAUnderlyingObjectsArgument final : AAUnderlyingObjectsImpl {
12212 AAUnderlyingObjectsArgument(
const IRPosition &IRP, Attributor &
A)
12213 : AAUnderlyingObjectsImpl(IRP,
A) {}
12216struct AAUnderlyingObjectsCallSite final : AAUnderlyingObjectsImpl {
12217 AAUnderlyingObjectsCallSite(
const IRPosition &IRP, Attributor &
A)
12218 : AAUnderlyingObjectsImpl(IRP,
A) {}
12221struct AAUnderlyingObjectsCallSiteArgument final : AAUnderlyingObjectsImpl {
12222 AAUnderlyingObjectsCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
12223 : AAUnderlyingObjectsImpl(IRP,
A) {}
12226struct AAUnderlyingObjectsReturned final : AAUnderlyingObjectsImpl {
12227 AAUnderlyingObjectsReturned(
const IRPosition &IRP, Attributor &
A)
12228 : AAUnderlyingObjectsImpl(IRP,
A) {}
12231struct AAUnderlyingObjectsCallSiteReturned final : AAUnderlyingObjectsImpl {
12232 AAUnderlyingObjectsCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
12233 : AAUnderlyingObjectsImpl(IRP,
A) {}
12236struct AAUnderlyingObjectsFunction final : AAUnderlyingObjectsImpl {
12237 AAUnderlyingObjectsFunction(
const IRPosition &IRP, Attributor &
A)
12238 : AAUnderlyingObjectsImpl(IRP,
A) {}
12244struct AAGlobalValueInfoFloating :
public AAGlobalValueInfo {
12245 AAGlobalValueInfoFloating(
const IRPosition &IRP, Attributor &
A)
12246 : AAGlobalValueInfo(IRP,
A) {}
12251 bool checkUse(Attributor &
A,
const Use &U,
bool &Follow,
12252 SmallVectorImpl<const Value *> &Worklist) {
12258 if (!GV->hasLocalLinkage() && !
A.isClosedWorldModule())
12264 LLVM_DEBUG(
dbgs() <<
"[AAGlobalValueInfo] Check use: " << *
U.get() <<
" in "
12265 << *UInst <<
"\n");
12268 int Idx = &
Cmp->getOperandUse(0) == &
U;
12271 return U == &getAnchorValue();
12276 auto CallSitePred = [&](AbstractCallSite ACS) {
12277 Worklist.
push_back(ACS.getInstruction());
12280 bool UsedAssumedInformation =
false;
12282 if (!
A.checkForAllCallSites(CallSitePred, *UInst->
getFunction(),
12284 UsedAssumedInformation))
12302 if (!Fn || !
A.isFunctionIPOAmendable(*Fn))
12311 unsigned NumUsesBefore =
Uses.size();
12313 SmallPtrSet<const Value *, 8> Visited;
12317 auto UsePred = [&](
const Use &
U,
bool &Follow) ->
bool {
12325 return checkUse(
A, U, Follow, Worklist);
12327 auto EquivalentUseCB = [&](
const Use &OldU,
const Use &NewU) {
12328 Uses.insert(&OldU);
12332 while (!Worklist.
empty()) {
12334 if (!Visited.
insert(V).second)
12336 if (!
A.checkForAllUses(UsePred, *
this, *V,
12338 DepClassTy::OPTIONAL,
12339 true, EquivalentUseCB)) {
12340 return indicatePessimisticFixpoint();
12344 return Uses.size() == NumUsesBefore ? ChangeStatus::UNCHANGED
12345 : ChangeStatus::CHANGED;
12348 bool isPotentialUse(
const Use &U)
const override {
12349 return !isValidState() ||
Uses.contains(&U);
12354 return ChangeStatus::UNCHANGED;
12358 const std::string getAsStr(Attributor *
A)
const override {
12359 return "[" + std::to_string(
Uses.size()) +
" uses]";
12362 void trackStatistics()
const override {
12368 SmallPtrSet<const Use *, 8>
Uses;
12374struct AAIndirectCallInfoCallSite :
public AAIndirectCallInfo {
12375 AAIndirectCallInfoCallSite(
const IRPosition &IRP, Attributor &
A)
12376 : AAIndirectCallInfo(IRP,
A) {}
12380 auto *MD = getCtxI()->getMetadata(LLVMContext::MD_callees);
12381 if (!MD && !
A.isClosedWorldModule())
12385 for (
const auto &
Op : MD->operands())
12387 PotentialCallees.insert(Callee);
12388 }
else if (
A.isClosedWorldModule()) {
12390 A.getInfoCache().getIndirectlyCallableFunctions(
A);
12391 PotentialCallees.insert_range(IndirectlyCallableFunctions);
12394 if (PotentialCallees.empty())
12395 indicateOptimisticFixpoint();
12403 SmallSetVector<Function *, 4> AssumedCalleesNow;
12404 bool AllCalleesKnownNow = AllCalleesKnown;
12406 auto CheckPotentialCalleeUse = [&](
Function &PotentialCallee,
12407 bool &UsedAssumedInformation) {
12408 const auto *GIAA =
A.getAAFor<AAGlobalValueInfo>(
12410 if (!GIAA || GIAA->isPotentialUse(CalleeUse))
12412 UsedAssumedInformation = !GIAA->isAtFixpoint();
12416 auto AddPotentialCallees = [&]() {
12417 for (
auto *PotentialCallee : PotentialCallees) {
12418 bool UsedAssumedInformation =
false;
12419 if (CheckPotentialCalleeUse(*PotentialCallee, UsedAssumedInformation))
12420 AssumedCalleesNow.
insert(PotentialCallee);
12426 bool UsedAssumedInformation =
false;
12429 AA::ValueScope::AnyScope,
12430 UsedAssumedInformation)) {
12431 if (PotentialCallees.empty())
12432 return indicatePessimisticFixpoint();
12433 AddPotentialCallees();
12438 auto CheckPotentialCallee = [&](
Function &Fn) {
12439 if (!PotentialCallees.empty() && !PotentialCallees.count(&Fn))
12442 auto &CachedResult = FilterResults[&Fn];
12443 if (CachedResult.has_value())
12444 return CachedResult.value();
12446 bool UsedAssumedInformation =
false;
12447 if (!CheckPotentialCalleeUse(Fn, UsedAssumedInformation)) {
12448 if (!UsedAssumedInformation)
12449 CachedResult =
false;
12458 for (
int I = NumCBArgs;
I < NumFnArgs; ++
I) {
12459 bool IsKnown =
false;
12462 DepClassTy::OPTIONAL, IsKnown)) {
12464 CachedResult =
false;
12469 CachedResult =
true;
12475 for (
auto &VAC :
Values) {
12483 if (CheckPotentialCallee(*VACFn))
12484 AssumedCalleesNow.
insert(VACFn);
12487 if (!PotentialCallees.empty()) {
12488 AddPotentialCallees();
12491 AllCalleesKnownNow =
false;
12494 if (AssumedCalleesNow == AssumedCallees &&
12495 AllCalleesKnown == AllCalleesKnownNow)
12496 return ChangeStatus::UNCHANGED;
12498 std::swap(AssumedCallees, AssumedCalleesNow);
12499 AllCalleesKnown = AllCalleesKnownNow;
12500 return ChangeStatus::CHANGED;
12506 if (!AllCalleesKnown && AssumedCallees.empty())
12507 return ChangeStatus::UNCHANGED;
12510 bool UsedAssumedInformation =
false;
12511 if (
A.isAssumedDead(*CB,
this,
nullptr,
12512 UsedAssumedInformation))
12513 return ChangeStatus::UNCHANGED;
12518 if (
FP->getType()->getPointerAddressSpace() != ProgramAS)
12519 FP =
new AddrSpaceCastInst(
12520 FP, PointerType::get(
FP->getContext(), ProgramAS),
12521 FP->getName() +
".as" + Twine(ProgramAS), CB->
getIterator());
12530 if (AssumedCallees.empty()) {
12531 assert(AllCalleesKnown &&
12532 "Expected all callees to be known if there are none.");
12533 A.changeToUnreachableAfterManifest(CB);
12534 return ChangeStatus::CHANGED;
12538 if (AllCalleesKnown && AssumedCallees.size() == 1) {
12539 auto *NewCallee = AssumedCallees.front();
12542 NumIndirectCallsPromoted++;
12543 return ChangeStatus::CHANGED;
12550 A.deleteAfterManifest(*CB);
12551 return ChangeStatus::CHANGED;
12561 bool SpecializedForAnyCallees =
false;
12562 bool SpecializedForAllCallees = AllCalleesKnown;
12563 ICmpInst *LastCmp =
nullptr;
12566 for (
Function *NewCallee : AssumedCallees) {
12567 if (!
A.shouldSpecializeCallSiteForCallee(*
this, *CB, *NewCallee,
12568 AssumedCallees.size())) {
12569 SkippedAssumedCallees.
push_back(NewCallee);
12570 SpecializedForAllCallees =
false;
12573 SpecializedForAnyCallees =
true;
12579 A.registerManifestAddedBasicBlock(*ThenTI->
getParent());
12580 A.registerManifestAddedBasicBlock(*IP->getParent());
12586 A.registerManifestAddedBasicBlock(*ElseBB);
12588 SplitTI->replaceUsesOfWith(CBBB, ElseBB);
12593 CastInst *RetBC =
nullptr;
12594 CallInst *NewCall =
nullptr;
12599 NumIndirectCallsPromoted++;
12607 auto AttachCalleeMetadata = [&](CallBase &IndirectCB) {
12608 if (!AllCalleesKnown)
12609 return ChangeStatus::UNCHANGED;
12610 MDBuilder MDB(IndirectCB.getContext());
12611 MDNode *Callees = MDB.createCallees(SkippedAssumedCallees);
12612 IndirectCB.setMetadata(LLVMContext::MD_callees, Callees);
12613 return ChangeStatus::CHANGED;
12616 if (!SpecializedForAnyCallees)
12617 return AttachCalleeMetadata(*CB);
12620 if (SpecializedForAllCallees) {
12623 new UnreachableInst(IP->getContext(), IP);
12624 IP->eraseFromParent();
12627 CBClone->setName(CB->
getName());
12628 CBClone->insertBefore(*IP->getParent(), IP);
12629 NewCalls.
push_back({CBClone,
nullptr});
12630 AttachCalleeMetadata(*CBClone);
12637 CB->
getParent()->getFirstInsertionPt());
12638 for (
auto &It : NewCalls) {
12639 CallBase *NewCall = It.first;
12640 Instruction *CallRet = It.second ? It.second : It.first;
12652 A.deleteAfterManifest(*CB);
12653 Changed = ChangeStatus::CHANGED;
12659 const std::string getAsStr(Attributor *
A)
const override {
12660 return std::string(AllCalleesKnown ?
"eliminate" :
"specialize") +
12661 " indirect call site with " + std::to_string(AssumedCallees.size()) +
12665 void trackStatistics()
const override {
12666 if (AllCalleesKnown) {
12668 Eliminated, CallSites,
12669 "Number of indirect call sites eliminated via specialization")
12672 "Number of indirect call sites specialized")
12676 bool foreachCallee(function_ref<
bool(
Function *)> CB)
const override {
12677 return isValidState() && AllCalleesKnown &&
all_of(AssumedCallees, CB);
12682 DenseMap<Function *, std::optional<bool>> FilterResults;
12686 SmallSetVector<Function *, 4> PotentialCallees;
12690 SmallSetVector<Function *, 4> AssumedCallees;
12694 bool AllCalleesKnown =
true;
12701struct AAInvariantLoadPointerImpl
12702 :
public StateWrapper<BitIntegerState<uint8_t, 15>,
12703 AAInvariantLoadPointer> {
12707 IS_NOALIAS = 1 << 0,
12710 IS_NOEFFECT = 1 << 1,
12712 IS_LOCALLY_INVARIANT = 1 << 2,
12714 IS_LOCALLY_CONSTRAINED = 1 << 3,
12716 IS_BEST_STATE = IS_NOALIAS | IS_NOEFFECT | IS_LOCALLY_INVARIANT |
12717 IS_LOCALLY_CONSTRAINED,
12719 static_assert(getBestState() == IS_BEST_STATE,
"Unexpected best state");
12722 StateWrapper<BitIntegerState<uint8_t, 15>, AAInvariantLoadPointer>;
12726 AAInvariantLoadPointerImpl(
const IRPosition &IRP, Attributor &
A)
12729 bool isKnownInvariant()
const final {
12730 return isKnownLocallyInvariant() && isKnown(IS_LOCALLY_CONSTRAINED);
12733 bool isKnownLocallyInvariant()
const final {
12734 if (isKnown(IS_LOCALLY_INVARIANT))
12736 return isKnown(IS_NOALIAS | IS_NOEFFECT);
12739 bool isAssumedInvariant()
const final {
12740 return isAssumedLocallyInvariant() && isAssumed(IS_LOCALLY_CONSTRAINED);
12743 bool isAssumedLocallyInvariant()
const final {
12744 if (isAssumed(IS_LOCALLY_INVARIANT))
12746 return isAssumed(IS_NOALIAS | IS_NOEFFECT);
12753 if (requiresNoAlias() && !isAssumed(IS_NOALIAS))
12754 return indicatePessimisticFixpoint();
12758 Changed |= updateLocalInvariance(
A);
12764 if (!isKnownInvariant())
12765 return ChangeStatus::UNCHANGED;
12768 const Value *Ptr = &getAssociatedValue();
12769 const auto TagInvariantLoads = [&](
const Use &
U,
bool &) {
12770 if (
U.get() != Ptr)
12778 if (!
A.isRunOn(
I->getFunction()))
12781 if (
I->hasMetadata(LLVMContext::MD_invariant_load))
12785 LI->setMetadata(LLVMContext::MD_invariant_load,
12787 Changed = ChangeStatus::CHANGED;
12792 (void)
A.checkForAllUses(TagInvariantLoads, *
this, *Ptr);
12797 const std::string getAsStr(Attributor *)
const override {
12798 if (isKnownInvariant())
12799 return "load-invariant pointer";
12800 return "non-invariant pointer";
12804 void trackStatistics()
const override {}
12808 bool requiresNoAlias()
const {
12809 switch (getPositionKind()) {
12815 case IRP_CALL_SITE:
12817 case IRP_CALL_SITE_RETURNED: {
12822 case IRP_ARGUMENT: {
12823 const Function *
F = getAssociatedFunction();
12824 assert(
F &&
"no associated function for argument");
12830 bool isExternal()
const {
12831 const Function *
F = getAssociatedFunction();
12835 getPositionKind() != IRP_CALL_SITE_RETURNED;
12839 if (isKnown(IS_NOALIAS) || !isAssumed(IS_NOALIAS))
12840 return ChangeStatus::UNCHANGED;
12843 if (
const auto *ANoAlias =
A.getOrCreateAAFor<AANoAlias>(
12844 getIRPosition(),
this, DepClassTy::REQUIRED)) {
12845 if (ANoAlias->isKnownNoAlias()) {
12846 addKnownBits(IS_NOALIAS);
12847 return ChangeStatus::CHANGED;
12850 if (!ANoAlias->isAssumedNoAlias()) {
12851 removeAssumedBits(IS_NOALIAS);
12852 return ChangeStatus::CHANGED;
12855 return ChangeStatus::UNCHANGED;
12860 if (
const Argument *Arg = getAssociatedArgument()) {
12862 addKnownBits(IS_NOALIAS);
12863 return ChangeStatus::UNCHANGED;
12868 removeAssumedBits(IS_NOALIAS);
12869 return ChangeStatus::CHANGED;
12872 return ChangeStatus::UNCHANGED;
12876 if (isKnown(IS_NOEFFECT) || !isAssumed(IS_NOEFFECT))
12877 return ChangeStatus::UNCHANGED;
12879 if (!getAssociatedFunction())
12880 return indicatePessimisticFixpoint();
12883 return indicatePessimisticFixpoint();
12885 const auto HasNoEffectLoads = [&](
const Use &
U,
bool &) {
12887 return !LI || !LI->mayHaveSideEffects();
12889 if (!
A.checkForAllUses(HasNoEffectLoads, *
this, getAssociatedValue()))
12890 return indicatePessimisticFixpoint();
12892 if (
const auto *AMemoryBehavior =
A.getOrCreateAAFor<AAMemoryBehavior>(
12893 getIRPosition(),
this, DepClassTy::REQUIRED)) {
12896 if (!AMemoryBehavior->isAssumedReadOnly())
12897 return indicatePessimisticFixpoint();
12899 if (AMemoryBehavior->isKnownReadOnly()) {
12900 addKnownBits(IS_NOEFFECT);
12901 return ChangeStatus::UNCHANGED;
12904 return ChangeStatus::UNCHANGED;
12907 if (
const Argument *Arg = getAssociatedArgument()) {
12909 addKnownBits(IS_NOEFFECT);
12910 return ChangeStatus::UNCHANGED;
12915 return indicatePessimisticFixpoint();
12918 return ChangeStatus::UNCHANGED;
12922 if (isKnown(IS_LOCALLY_INVARIANT) || !isAssumed(IS_LOCALLY_INVARIANT))
12923 return ChangeStatus::UNCHANGED;
12926 const auto *AUO =
A.getOrCreateAAFor<AAUnderlyingObjects>(
12927 getIRPosition(),
this, DepClassTy::REQUIRED);
12929 return ChangeStatus::UNCHANGED;
12931 bool UsedAssumedInformation =
false;
12932 const auto IsLocallyInvariantLoadIfPointer = [&](
const Value &
V) {
12933 if (!
V.getType()->isPointerTy())
12935 const auto *IsInvariantLoadPointer =
12937 DepClassTy::REQUIRED);
12939 if (!IsInvariantLoadPointer)
12942 if (IsInvariantLoadPointer->isKnownLocallyInvariant())
12944 if (!IsInvariantLoadPointer->isAssumedLocallyInvariant())
12947 UsedAssumedInformation =
true;
12950 if (!AUO->forallUnderlyingObjects(IsLocallyInvariantLoadIfPointer))
12951 return indicatePessimisticFixpoint();
12957 if (!IsLocallyInvariantLoadIfPointer(*Arg))
12958 return indicatePessimisticFixpoint();
12963 if (!UsedAssumedInformation) {
12965 addKnownBits(IS_LOCALLY_INVARIANT);
12966 return ChangeStatus::CHANGED;
12969 return ChangeStatus::UNCHANGED;
12973struct AAInvariantLoadPointerFloating final : AAInvariantLoadPointerImpl {
12974 AAInvariantLoadPointerFloating(
const IRPosition &IRP, Attributor &
A)
12975 : AAInvariantLoadPointerImpl(IRP,
A) {}
12978struct AAInvariantLoadPointerReturned final : AAInvariantLoadPointerImpl {
12979 AAInvariantLoadPointerReturned(
const IRPosition &IRP, Attributor &
A)
12980 : AAInvariantLoadPointerImpl(IRP,
A) {}
12983 removeAssumedBits(IS_LOCALLY_CONSTRAINED);
12987struct AAInvariantLoadPointerCallSiteReturned final
12988 : AAInvariantLoadPointerImpl {
12989 AAInvariantLoadPointerCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
12990 : AAInvariantLoadPointerImpl(IRP,
A) {}
12994 const Function *
F = getAssociatedFunction();
12996 indicatePessimisticFixpoint();
13000 if (!
F->isDeclaration() && !
F->isIntrinsic())
13001 return AAInvariantLoadPointerImpl::initialize(
A);
13006 return AAInvariantLoadPointerImpl::initialize(
A);
13008 if (
F->onlyReadsMemory() &&
F->hasNoSync())
13009 return AAInvariantLoadPointerImpl::initialize(
A);
13013 indicatePessimisticFixpoint();
13017struct AAInvariantLoadPointerArgument final : AAInvariantLoadPointerImpl {
13018 AAInvariantLoadPointerArgument(
const IRPosition &IRP, Attributor &
A)
13019 : AAInvariantLoadPointerImpl(IRP,
A) {}
13022 const Function *
F = getAssociatedFunction();
13023 assert(
F &&
"no associated function for argument");
13026 addKnownBits(IS_LOCALLY_CONSTRAINED);
13030 if (!
F->hasLocalLinkage())
13031 removeAssumedBits(IS_LOCALLY_CONSTRAINED);
13035struct AAInvariantLoadPointerCallSiteArgument final
13036 : AAInvariantLoadPointerImpl {
13037 AAInvariantLoadPointerCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
13038 : AAInvariantLoadPointerImpl(IRP,
A) {}
13045template <
typename InstType>
13046static bool makeChange(Attributor &
A, InstType *MemInst,
const Use &U,
13047 Value *OriginalValue, PointerType *NewPtrTy,
13048 bool UseOriginalValue) {
13049 if (
U.getOperandNo() != InstType::getPointerOperandIndex())
13052 if (MemInst->isVolatile()) {
13053 auto *
TTI =
A.getInfoCache().getAnalysisResultForFunction<TargetIRAnalysis>(
13054 *MemInst->getFunction());
13055 unsigned NewAS = NewPtrTy->getPointerAddressSpace();
13060 if (UseOriginalValue) {
13061 A.changeUseAfterManifest(
const_cast<Use &
>(U), *OriginalValue);
13065 Instruction *CastInst =
new AddrSpaceCastInst(OriginalValue, NewPtrTy);
13067 A.changeUseAfterManifest(
const_cast<Use &
>(U), *CastInst);
13071struct AAAddressSpaceImpl :
public AAAddressSpace {
13072 AAAddressSpaceImpl(
const IRPosition &IRP, Attributor &
A)
13073 : AAAddressSpace(IRP,
A) {}
13076 assert(isValidState() &&
"the AA is invalid");
13077 return AssumedAddressSpace;
13082 assert(getAssociatedType()->isPtrOrPtrVectorTy() &&
13083 "Associated value is not a pointer");
13085 if (!
A.getInfoCache().getFlatAddressSpace().has_value()) {
13086 indicatePessimisticFixpoint();
13090 unsigned FlatAS =
A.getInfoCache().getFlatAddressSpace().value();
13091 unsigned AS = getAssociatedType()->getPointerAddressSpace();
13092 if (AS != FlatAS) {
13093 [[maybe_unused]]
bool R = takeAddressSpace(AS);
13094 assert(R &&
"The take should happen");
13095 indicateOptimisticFixpoint();
13100 uint32_t OldAddressSpace = AssumedAddressSpace;
13101 unsigned FlatAS =
A.getInfoCache().getFlatAddressSpace().value();
13103 auto CheckAddressSpace = [&](
Value &
Obj) {
13109 unsigned ObjAS =
Obj.getType()->getPointerAddressSpace();
13110 if (ObjAS != FlatAS)
13111 return takeAddressSpace(ObjAS);
13125 A.getInfoCache().getAnalysisResultForFunction<TargetIRAnalysis>(*F);
13127 if (AssumedAS != ~0U)
13128 return takeAddressSpace(AssumedAS);
13132 return takeAddressSpace(FlatAS);
13135 auto *AUO =
A.getOrCreateAAFor<AAUnderlyingObjects>(getIRPosition(),
this,
13136 DepClassTy::REQUIRED);
13137 if (!AUO->forallUnderlyingObjects(CheckAddressSpace))
13138 return indicatePessimisticFixpoint();
13140 return OldAddressSpace == AssumedAddressSpace ? ChangeStatus::UNCHANGED
13141 : ChangeStatus::CHANGED;
13148 if (NewAS == InvalidAddressSpace ||
13150 return ChangeStatus::UNCHANGED;
13152 unsigned FlatAS =
A.getInfoCache().getFlatAddressSpace().value();
13154 Value *AssociatedValue = &getAssociatedValue();
13155 Value *OriginalValue = peelAddrspacecast(AssociatedValue, FlatAS);
13158 PointerType::get(getAssociatedType()->
getContext(), NewAS);
13159 bool UseOriginalValue =
13164 auto Pred = [&](
const Use &
U,
bool &) {
13165 if (
U.get() != AssociatedValue)
13176 makeChange(
A, LI, U, OriginalValue, NewPtrTy, UseOriginalValue);
13179 makeChange(
A, SI, U, OriginalValue, NewPtrTy, UseOriginalValue);
13182 makeChange(
A, RMW, U, OriginalValue, NewPtrTy, UseOriginalValue);
13185 makeChange(
A, CmpX, U, OriginalValue, NewPtrTy, UseOriginalValue);
13192 (void)
A.checkForAllUses(Pred, *
this, getAssociatedValue(),
13195 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
13199 const std::string getAsStr(Attributor *
A)
const override {
13200 if (!isValidState())
13201 return "addrspace(<invalid>)";
13202 return "addrspace(" +
13203 (AssumedAddressSpace == InvalidAddressSpace
13205 : std::to_string(AssumedAddressSpace)) +
13210 uint32_t AssumedAddressSpace = InvalidAddressSpace;
13212 bool takeAddressSpace(uint32_t AS) {
13213 if (AssumedAddressSpace == InvalidAddressSpace) {
13214 AssumedAddressSpace = AS;
13217 return AssumedAddressSpace == AS;
13220 static Value *peelAddrspacecast(
Value *V,
unsigned FlatAS) {
13222 assert(
I->getSrcAddressSpace() != FlatAS &&
13223 "there should not be flat AS -> non-flat AS");
13224 return I->getPointerOperand();
13227 if (
C->getOpcode() == Instruction::AddrSpaceCast) {
13228 assert(
C->getOperand(0)->getType()->getPointerAddressSpace() !=
13230 "there should not be flat AS -> non-flat AS X");
13231 return C->getOperand(0);
13237struct AAAddressSpaceFloating final : AAAddressSpaceImpl {
13238 AAAddressSpaceFloating(
const IRPosition &IRP, Attributor &
A)
13239 : AAAddressSpaceImpl(IRP,
A) {}
13241 void trackStatistics()
const override {
13246struct AAAddressSpaceReturned final : AAAddressSpaceImpl {
13247 AAAddressSpaceReturned(
const IRPosition &IRP, Attributor &
A)
13248 : AAAddressSpaceImpl(IRP,
A) {}
13254 (void)indicatePessimisticFixpoint();
13257 void trackStatistics()
const override {
13262struct AAAddressSpaceCallSiteReturned final : AAAddressSpaceImpl {
13263 AAAddressSpaceCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
13264 : AAAddressSpaceImpl(IRP,
A) {}
13266 void trackStatistics()
const override {
13271struct AAAddressSpaceArgument final : AAAddressSpaceImpl {
13272 AAAddressSpaceArgument(
const IRPosition &IRP, Attributor &
A)
13273 : AAAddressSpaceImpl(IRP,
A) {}
13278struct AAAddressSpaceCallSiteArgument final : AAAddressSpaceImpl {
13279 AAAddressSpaceCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
13280 : AAAddressSpaceImpl(IRP,
A) {}
13286 (void)indicatePessimisticFixpoint();
13289 void trackStatistics()
const override {
13304struct AANoAliasAddrSpaceImpl :
public AANoAliasAddrSpace {
13305 AANoAliasAddrSpaceImpl(
const IRPosition &IRP, Attributor &
A)
13306 : AANoAliasAddrSpace(IRP,
A) {}
13309 assert(getAssociatedType()->isPtrOrPtrVectorTy() &&
13310 "Associated value is not a pointer");
13314 std::optional<unsigned> FlatAS =
A.getInfoCache().getFlatAddressSpace();
13315 if (!FlatAS.has_value()) {
13316 indicatePessimisticFixpoint();
13322 unsigned AS = getAssociatedType()->getPointerAddressSpace();
13323 if (AS != *FlatAS) {
13325 indicateOptimisticFixpoint();
13330 unsigned FlatAS =
A.getInfoCache().getFlatAddressSpace().value();
13331 uint32_t OldAssumed = getAssumed();
13333 auto CheckAddressSpace = [&](
Value &
Obj) {
13337 unsigned AS =
Obj.getType()->getPointerAddressSpace();
13341 removeAS(
Obj.getType()->getPointerAddressSpace());
13345 const AAUnderlyingObjects *AUO =
A.getOrCreateAAFor<AAUnderlyingObjects>(
13346 getIRPosition(),
this, DepClassTy::REQUIRED);
13348 return indicatePessimisticFixpoint();
13350 return OldAssumed == getAssumed() ? ChangeStatus::UNCHANGED
13351 : ChangeStatus::CHANGED;
13356 unsigned FlatAS =
A.getInfoCache().getFlatAddressSpace().value();
13358 unsigned AS = getAssociatedType()->getPointerAddressSpace();
13359 if (AS != FlatAS ||
Map.empty())
13360 return ChangeStatus::UNCHANGED;
13362 LLVMContext &Ctx = getAssociatedValue().getContext();
13363 MDNode *NoAliasASNode =
nullptr;
13364 MDBuilder MDB(Ctx);
13366 for (RangeMap::const_iterator
I =
Map.begin();
I !=
Map.end();
I++) {
13369 unsigned Upper =
I.stop();
13370 unsigned Lower =
I.start();
13371 if (!NoAliasASNode) {
13372 NoAliasASNode = MDB.createRange(APInt(32,
Lower), APInt(32,
Upper + 1));
13375 MDNode *ASRange = MDB.createRange(APInt(32,
Lower), APInt(32,
Upper + 1));
13379 Value *AssociatedValue = &getAssociatedValue();
13382 auto AddNoAliasAttr = [&](
const Use &
U,
bool &) {
13383 if (
U.get() != AssociatedValue)
13386 if (!Inst || Inst->
hasMetadata(LLVMContext::MD_noalias_addrspace))
13393 Inst->
setMetadata(LLVMContext::MD_noalias_addrspace, NoAliasASNode);
13397 (void)
A.checkForAllUses(AddNoAliasAttr, *
this, *AssociatedValue,
13399 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
13403 const std::string getAsStr(Attributor *
A)
const override {
13404 if (!isValidState())
13405 return "<invalid>";
13407 raw_string_ostream OS(Str);
13408 OS <<
"CanNotBeAddrSpace(";
13409 for (RangeMap::const_iterator
I =
Map.begin();
I !=
Map.end();
I++) {
13410 unsigned Upper =
I.stop();
13411 unsigned Lower =
I.start();
13412 OS <<
' ' <<
'[' <<
Upper <<
',' <<
Lower + 1 <<
')';
13419 void removeAS(
unsigned AS) {
13420 RangeMap::iterator
I =
Map.find(AS);
13422 if (
I !=
Map.end()) {
13423 unsigned Upper =
I.stop();
13424 unsigned Lower =
I.start();
13428 if (AS != ~((
unsigned)0) && AS + 1 <=
Upper)
13430 if (AS != 0 &&
Lower <= AS - 1)
13435 void resetASRanges(Attributor &
A) {
13437 Map.insert(0,
A.getInfoCache().getMaxAddrSpace(),
true);
13441struct AANoAliasAddrSpaceFloating final : AANoAliasAddrSpaceImpl {
13442 AANoAliasAddrSpaceFloating(
const IRPosition &IRP, Attributor &
A)
13443 : AANoAliasAddrSpaceImpl(IRP,
A) {}
13445 void trackStatistics()
const override {
13450struct AANoAliasAddrSpaceReturned final : AANoAliasAddrSpaceImpl {
13451 AANoAliasAddrSpaceReturned(
const IRPosition &IRP, Attributor &
A)
13452 : AANoAliasAddrSpaceImpl(IRP,
A) {}
13454 void trackStatistics()
const override {
13459struct AANoAliasAddrSpaceCallSiteReturned final : AANoAliasAddrSpaceImpl {
13460 AANoAliasAddrSpaceCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
13461 : AANoAliasAddrSpaceImpl(IRP,
A) {}
13463 void trackStatistics()
const override {
13468struct AANoAliasAddrSpaceArgument final : AANoAliasAddrSpaceImpl {
13469 AANoAliasAddrSpaceArgument(
const IRPosition &IRP, Attributor &
A)
13470 : AANoAliasAddrSpaceImpl(IRP,
A) {}
13472 void trackStatistics()
const override {
13477struct AANoAliasAddrSpaceCallSiteArgument final : AANoAliasAddrSpaceImpl {
13478 AANoAliasAddrSpaceCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
13479 : AANoAliasAddrSpaceImpl(IRP,
A) {}
13481 void trackStatistics()
const override {
13488struct AAAllocationInfoImpl :
public AAAllocationInfo {
13489 AAAllocationInfoImpl(
const IRPosition &IRP, Attributor &
A)
13490 : AAAllocationInfo(IRP,
A) {}
13492 std::optional<TypeSize> getAllocatedSize()
const override {
13493 assert(isValidState() &&
"the AA is invalid");
13494 return AssumedAllocatedSize;
13497 std::optional<TypeSize> findInitialAllocationSize(Instruction *
I,
13498 const DataLayout &
DL) {
13501 switch (
I->getOpcode()) {
13502 case Instruction::Alloca: {
13507 return std::nullopt;
13513 const IRPosition &IRP = getIRPosition();
13518 return indicatePessimisticFixpoint();
13520 bool IsKnownNoCapture;
13522 A,
this, IRP, DepClassTy::OPTIONAL, IsKnownNoCapture))
13523 return indicatePessimisticFixpoint();
13525 const AAPointerInfo *PI =
13526 A.getOrCreateAAFor<AAPointerInfo>(IRP, *
this, DepClassTy::REQUIRED);
13529 return indicatePessimisticFixpoint();
13532 return indicatePessimisticFixpoint();
13534 const DataLayout &
DL =
A.getDataLayout();
13535 const auto AllocationSize = findInitialAllocationSize(
I,
DL);
13538 if (!AllocationSize)
13539 return indicatePessimisticFixpoint();
13543 if (*AllocationSize == 0)
13544 return indicatePessimisticFixpoint();
13550 return indicatePessimisticFixpoint();
13552 if (BinSize == 0) {
13553 auto NewAllocationSize = std::make_optional<TypeSize>(0,
false);
13554 if (!changeAllocationSize(NewAllocationSize))
13555 return ChangeStatus::UNCHANGED;
13556 return ChangeStatus::CHANGED;
13560 const auto &It = PI->
begin();
13563 if (It->first.Offset != 0)
13564 return indicatePessimisticFixpoint();
13566 uint64_t SizeOfBin = It->first.Offset + It->first.Size;
13568 if (SizeOfBin >= *AllocationSize)
13569 return indicatePessimisticFixpoint();
13571 auto NewAllocationSize = std::make_optional<TypeSize>(SizeOfBin * 8,
false);
13573 if (!changeAllocationSize(NewAllocationSize))
13574 return ChangeStatus::UNCHANGED;
13576 return ChangeStatus::CHANGED;
13582 assert(isValidState() &&
13583 "Manifest should only be called if the state is valid.");
13587 auto FixedAllocatedSizeInBits = getAllocatedSize()->getFixedValue();
13589 unsigned long NumBytesToAllocate = (FixedAllocatedSizeInBits + 7) / 8;
13591 switch (
I->getOpcode()) {
13593 case Instruction::Alloca: {
13597 Type *CharType = Type::getInt8Ty(
I->getContext());
13599 auto *NumBytesToValue =
13600 ConstantInt::get(
I->getContext(), APInt(32, NumBytesToAllocate));
13603 insertPt = std::next(insertPt);
13604 AllocaInst *NewAllocaInst =
13609 return ChangeStatus::CHANGED;
13617 return ChangeStatus::UNCHANGED;
13621 const std::string getAsStr(Attributor *
A)
const override {
13622 if (!isValidState())
13623 return "allocationinfo(<invalid>)";
13624 return "allocationinfo(" +
13625 (AssumedAllocatedSize == HasNoAllocationSize
13627 : std::to_string(AssumedAllocatedSize->getFixedValue())) +
13632 std::optional<TypeSize> AssumedAllocatedSize = HasNoAllocationSize;
13636 bool changeAllocationSize(std::optional<TypeSize>
Size) {
13637 if (AssumedAllocatedSize == HasNoAllocationSize ||
13638 AssumedAllocatedSize !=
Size) {
13639 AssumedAllocatedSize =
Size;
13646struct AAAllocationInfoFloating : AAAllocationInfoImpl {
13647 AAAllocationInfoFloating(
const IRPosition &IRP, Attributor &
A)
13648 : AAAllocationInfoImpl(IRP,
A) {}
13650 void trackStatistics()
const override {
13655struct AAAllocationInfoReturned : AAAllocationInfoImpl {
13656 AAAllocationInfoReturned(
const IRPosition &IRP, Attributor &
A)
13657 : AAAllocationInfoImpl(IRP,
A) {}
13663 (void)indicatePessimisticFixpoint();
13666 void trackStatistics()
const override {
13671struct AAAllocationInfoCallSiteReturned : AAAllocationInfoImpl {
13672 AAAllocationInfoCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
13673 : AAAllocationInfoImpl(IRP,
A) {}
13675 void trackStatistics()
const override {
13680struct AAAllocationInfoArgument : AAAllocationInfoImpl {
13681 AAAllocationInfoArgument(
const IRPosition &IRP, Attributor &
A)
13682 : AAAllocationInfoImpl(IRP,
A) {}
13684 void trackStatistics()
const override {
13689struct AAAllocationInfoCallSiteArgument : AAAllocationInfoImpl {
13690 AAAllocationInfoCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
13691 : AAAllocationInfoImpl(IRP,
A) {}
13696 (void)indicatePessimisticFixpoint();
13699 void trackStatistics()
const override {
13748#define SWITCH_PK_INV(CLASS, PK, POS_NAME) \
13749 case IRPosition::PK: \
13750 llvm_unreachable("Cannot create " #CLASS " for a " POS_NAME " position!");
13752#define SWITCH_PK_CREATE(CLASS, IRP, PK, SUFFIX) \
13753 case IRPosition::PK: \
13754 AA = new (A.Allocator) CLASS##SUFFIX(IRP, A); \
13758#define CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13759 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13760 CLASS *AA = nullptr; \
13761 switch (IRP.getPositionKind()) { \
13762 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13763 SWITCH_PK_INV(CLASS, IRP_FLOAT, "floating") \
13764 SWITCH_PK_INV(CLASS, IRP_ARGUMENT, "argument") \
13765 SWITCH_PK_INV(CLASS, IRP_RETURNED, "returned") \
13766 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_RETURNED, "call site returned") \
13767 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_ARGUMENT, "call site argument") \
13768 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
13769 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE, CallSite) \
13774#define CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13775 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13776 CLASS *AA = nullptr; \
13777 switch (IRP.getPositionKind()) { \
13778 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13779 SWITCH_PK_INV(CLASS, IRP_FUNCTION, "function") \
13780 SWITCH_PK_INV(CLASS, IRP_CALL_SITE, "call site") \
13781 SWITCH_PK_CREATE(CLASS, IRP, IRP_FLOAT, Floating) \
13782 SWITCH_PK_CREATE(CLASS, IRP, IRP_ARGUMENT, Argument) \
13783 SWITCH_PK_CREATE(CLASS, IRP, IRP_RETURNED, Returned) \
13784 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_RETURNED, CallSiteReturned) \
13785 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_ARGUMENT, CallSiteArgument) \
13790#define CREATE_ABSTRACT_ATTRIBUTE_FOR_ONE_POSITION(POS, SUFFIX, CLASS) \
13791 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13792 CLASS *AA = nullptr; \
13793 switch (IRP.getPositionKind()) { \
13794 SWITCH_PK_CREATE(CLASS, IRP, POS, SUFFIX) \
13796 llvm_unreachable("Cannot create " #CLASS " for position otherthan " #POS \
13802#define CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13803 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13804 CLASS *AA = nullptr; \
13805 switch (IRP.getPositionKind()) { \
13806 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13807 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
13808 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE, CallSite) \
13809 SWITCH_PK_CREATE(CLASS, IRP, IRP_FLOAT, Floating) \
13810 SWITCH_PK_CREATE(CLASS, IRP, IRP_ARGUMENT, Argument) \
13811 SWITCH_PK_CREATE(CLASS, IRP, IRP_RETURNED, Returned) \
13812 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_RETURNED, CallSiteReturned) \
13813 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_ARGUMENT, CallSiteArgument) \
13818#define CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13819 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13820 CLASS *AA = nullptr; \
13821 switch (IRP.getPositionKind()) { \
13822 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13823 SWITCH_PK_INV(CLASS, IRP_ARGUMENT, "argument") \
13824 SWITCH_PK_INV(CLASS, IRP_FLOAT, "floating") \
13825 SWITCH_PK_INV(CLASS, IRP_RETURNED, "returned") \
13826 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_RETURNED, "call site returned") \
13827 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_ARGUMENT, "call site argument") \
13828 SWITCH_PK_INV(CLASS, IRP_CALL_SITE, "call site") \
13829 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
13834#define CREATE_NON_RET_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13835 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13836 CLASS *AA = nullptr; \
13837 switch (IRP.getPositionKind()) { \
13838 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13839 SWITCH_PK_INV(CLASS, IRP_RETURNED, "returned") \
13840 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
13841 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE, CallSite) \
13842 SWITCH_PK_CREATE(CLASS, IRP, IRP_FLOAT, Floating) \
13843 SWITCH_PK_CREATE(CLASS, IRP, IRP_ARGUMENT, Argument) \
13844 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_RETURNED, CallSiteReturned) \
13845 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_ARGUMENT, CallSiteArgument) \
13897#undef CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION
13898#undef CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION
13899#undef CREATE_NON_RET_ABSTRACT_ATTRIBUTE_FOR_POSITION
13900#undef CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION
13901#undef CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION
13902#undef CREATE_ABSTRACT_ATTRIBUTE_FOR_ONE_POSITION
13903#undef SWITCH_PK_CREATE
13904#undef SWITCH_PK_INV
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU Register Bank Select
This file implements a class to represent arbitrary precision integral constant values and operations...
ReachingDefInfo InstSet & ToRemove
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Function Alias Analysis false
This file contains the simple types necessary to represent the attributes associated with functions a...
#define STATS_DECLTRACK(NAME, TYPE, MSG)
static std::optional< Constant * > askForAssumedConstant(Attributor &A, const AbstractAttribute &QueryingAA, const IRPosition &IRP, Type &Ty)
static cl::opt< unsigned, true > MaxPotentialValues("attributor-max-potential-values", cl::Hidden, cl::desc("Maximum number of potential values to be " "tracked for each position."), cl::location(llvm::PotentialConstantIntValuesState::MaxPotentialValues), cl::init(7))
static void clampReturnedValueStates(Attributor &A, const AAType &QueryingAA, StateType &S, const IRPosition::CallBaseContext *CBContext=nullptr)
Clamp the information known for all returned values of a function (identified by QueryingAA) into S.
#define STATS_DECLTRACK_FN_ATTR(NAME)
#define CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS)
static cl::opt< int > MaxPotentialValuesIterations("attributor-max-potential-values-iterations", cl::Hidden, cl::desc("Maximum number of iterations we keep dismantling potential values."), cl::init(64))
#define STATS_DECLTRACK_CS_ATTR(NAME)
#define PIPE_OPERATOR(CLASS)
#define STATS_DECLTRACK_ARG_ATTR(NAME)
static const Value * stripAndAccumulateOffsets(Attributor &A, const AbstractAttribute &QueryingAA, const Value *Val, const DataLayout &DL, APInt &Offset, bool GetMinOffset, bool AllowNonInbounds, bool UseAssumed=false)
#define STATS_DECLTRACK_CSRET_ATTR(NAME)
static cl::opt< bool > ManifestInternal("attributor-manifest-internal", cl::Hidden, cl::desc("Manifest Attributor internal string attributes."), cl::init(false))
static Value * constructPointer(Value *Ptr, int64_t Offset, IRBuilder< NoFolder > &IRB)
Helper function to create a pointer based on Ptr, and advanced by Offset bytes.
#define CREATE_NON_RET_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS)
#define BUILD_STAT_NAME(NAME, TYPE)
static bool isDenselyPacked(Type *Ty, const DataLayout &DL)
Checks if a type could have padding bytes.
#define CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS)
static const Value * getMinimalBaseOfPointer(Attributor &A, const AbstractAttribute &QueryingAA, const Value *Ptr, int64_t &BytesOffset, const DataLayout &DL, bool AllowNonInbounds=false)
static bool mayBeInCycle(const CycleInfo *CI, const Instruction *I, bool HeaderOnly, CycleRef *CPtr=nullptr)
#define STATS_DECLTRACK_FNRET_ATTR(NAME)
#define STATS_DECLTRACK_CSARG_ATTR(NAME)
#define CREATE_ABSTRACT_ATTRIBUTE_FOR_ONE_POSITION(POS, SUFFIX, CLASS)
#define CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS)
static cl::opt< int > MaxHeapToStackSize("max-heap-to-stack-size", cl::init(128), cl::Hidden)
#define CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS)
#define STATS_DECLTRACK_FLOATING_ATTR(NAME)
#define STATS_DECL(NAME, TYPE, MSG)
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static bool isReachableImpl(SmallVectorImpl< BasicBlock * > &Worklist, const StopSetT &StopSet, const SmallPtrSetImpl< BasicBlock * > *ExclusionSet, const DominatorTree *DT, const LoopInfo *LI, const CycleInfo *CI)
This file contains the declarations for the subclasses of Constant, which represent the different fla...
This file declares an analysis pass that computes CycleInfo for LLVM IR, specialized from GenericCycl...
static uint64_t align(uint64_t Size)
DXIL Forward Handle Accesses
This file defines DenseMapInfo traits for DenseMap.
This file defines the DenseMap class.
static Value * getCondition(Instruction *I)
Machine Check Debug Module
This file implements a map that provides insertion order iteration.
static unsigned getAddressSpace(const Value *V, unsigned MaxLookup)
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
uint64_t IntrinsicInst * II
static StringRef getName(Value *V)
dot regions Print regions of function to dot true view regions View regions of function(with no function bodies)"
Remove Loads Into Fake Uses
This builds on the llvm/ADT/GraphTraits.h file to find the strongly connected components (SCCs) of a ...
Func getContext().diagnose(DiagnosticInfoUnsupported(Func
std::pair< BasicBlock *, BasicBlock * > Edge
BaseType
A given derived pointer can have multiple base pointers through phi/selects.
This file defines generic set operations that may be used on set's of different types,...
This file implements a set that has insertion order iteration characteristics.
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static SymbolRef::Type getType(const Symbol *Sym)
static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, const llvm::StringTable &StandardNames, VectorLibrary VecLib)
Initialize the set of available library functions based on the specified target triple.
static unsigned getBitWidth(Type *Ty, const DataLayout &DL)
Returns the bitwidth of the given scalar or pointer type.
static unsigned getSize(unsigned Kind)
LLVM_ABI AACallGraphNode * operator*() const
bool isNoAlias(const MemoryLocation &LocA, const MemoryLocation &LocB)
A trivial helper function to check to see if the specified pointers are no-alias.
Class for arbitrary precision integers.
int64_t getSExtValue() const
Get sign extended value.
CallBase * getInstruction() const
Return the underlying instruction.
bool isCallbackCall() const
Return true if this ACS represents a callback call.
bool isDirectCall() const
Return true if this ACS represents a direct call.
static LLVM_ABI void getCallbackUses(const CallBase &CB, SmallVectorImpl< const Use * > &CallbackUses)
Add operand uses of CB that represent callback uses into CallbackUses.
int getCallArgOperandNo(Argument &Arg) const
Return the operand index of the underlying instruction associated with Arg.
Align getAlign() const
Return the alignment of the memory that is being allocated by the instruction.
unsigned getAddressSpace() const
Return the address space for the allocation.
LLVM_ABI std::optional< TypeSize > getAllocationSize(const DataLayout &DL) const
Get allocation size in bytes.
This class represents an incoming formal argument to a Function.
LLVM_ABI bool hasNoAliasAttr() const
Return true if this argument has the noalias attribute.
LLVM_ABI bool onlyReadsMemory() const
Return true if this argument has the readonly or readnone attribute.
LLVM_ABI bool hasPointeeInMemoryValueAttr() const
Return true if this argument has the byval, sret, inalloca, preallocated, or byref attribute.
LLVM_ABI bool hasReturnedAttr() const
Return true if this argument has the returned attribute.
LLVM_ABI bool hasByValAttr() const
Return true if this argument has the byval attribute.
const Function * getParent() const
unsigned getArgNo() const
Return the index of this formal argument in its containing function.
A function analysis which provides an AssumptionCache.
A cache of @llvm.assume calls within a function.
Functions, function parameters, and return types can have attributes to indicate how they should be t...
static LLVM_ABI Attribute get(LLVMContext &Context, AttrKind Kind, uint64_t Val=0)
Return a uniquified Attribute object.
LLVM_ABI FPClassTest getNoFPClass() const
Return the FPClassTest for nofpclass.
LLVM_ABI Attribute::AttrKind getKindAsEnum() const
Return the attribute's kind as an enum (Attribute::AttrKind).
LLVM_ABI MemoryEffects getMemoryEffects() const
Returns memory effects.
AttrKind
This enumeration lists the attributes that can be associated with parameters, function results,...
static LLVM_ABI Attribute getWithCaptureInfo(LLVMContext &Context, CaptureInfo CI)
static bool isEnumAttrKind(AttrKind Kind)
bool isValid() const
Return true if the attribute is any kind of attribute.
LLVM_ABI CaptureInfo getCaptureInfo() const
Returns information from captures attribute.
LLVM Basic Block Representation.
LLVM_ABI const_iterator getFirstInsertionPt() const
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
const Function * getParent() const
Return the enclosing method, or null if none.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
const Instruction & front() const
InstListType::iterator iterator
Instruction iterators...
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
BinaryOps getOpcode() const
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
LLVM_ABI bool isMustTailCall() const
Tests if this call site must be tail call optimized.
LLVM_ABI bool isIndirectCall() const
Return true if the callsite is an indirect call.
bool isCallee(Value::const_user_iterator UI) const
Determine whether the passed iterator points to the callee operand's Use.
Value * getCalledOperand() const
const Use & getCalledOperandUse() const
Attribute getFnAttr(StringRef Kind) const
Get the attribute of a given kind for the function.
const Use & getArgOperandUse(unsigned i) const
Wrappers for getting the Use of a call argument.
LLVM_ABI std::optional< ConstantRange > getRange() const
If this return value has a range attribute, return the value range of the argument.
Value * getArgOperand(unsigned i) const
bool isBundleOperand(unsigned Idx) const
Return true if the operand at index Idx is a bundle operand.
bool isConvergent() const
Determine if the invoke is convergent.
FunctionType * getFunctionType() const
LLVM_ABI Intrinsic::ID getIntrinsicID() const
Returns the intrinsic ID of the intrinsic called or Intrinsic::not_intrinsic if the called function i...
iterator_range< User::op_iterator > args()
Iteration adapter for range-for loops.
unsigned getArgOperandNo(const Use *U) const
Given a use for a arg operand, get the arg operand number that corresponds to it.
unsigned arg_size() const
bool isArgOperand(const Use *U) const
LLVM_ABI Function * getCaller()
Helper to get the caller (the parent function).
static CallInst * Create(FunctionType *Ty, Value *F, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
static CaptureInfo none()
Create CaptureInfo that does not capture any components of the pointer.
Instruction::CastOps getOpcode() const
Return the opcode of this CastInst.
LLVM_ABI bool isIntegerCast() const
There are several places where we need to know if a cast instruction only deals with integer source a...
Type * getDestTy() const
Return the destination type, as a convenience.
bool isEquality() const
Determine if this is an equals/not equals predicate.
bool isFalseWhenEqual() const
This is just a convenience.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
bool isTrueWhenEqual() const
This is just a convenience.
Predicate getPredicate() const
Return the predicate for this instruction.
Conditional Branch instruction.
Value * getCondition() const
BasicBlock * getSuccessor(unsigned i) const
static LLVM_ABI Constant * getExtractElement(Constant *Vec, Constant *Idx, Type *OnlyIfReducedTy=nullptr)
static LLVM_ABI ConstantInt * getTrue(LLVMContext &Context)
This class represents a range of values.
const APInt & getLower() const
Return the lower value for this range.
LLVM_ABI bool isFullSet() const
Return true if this set contains all of the elements possible for this data-type.
LLVM_ABI bool isEmptySet() const
Return true if this set contains no members.
bool isSingleElement() const
Return true if this set contains exactly one member.
static LLVM_ABI ConstantRange makeAllowedICmpRegion(CmpInst::Predicate Pred, const ConstantRange &Other)
Produce the smallest range such that all values that may satisfy the given predicate with any value c...
const APInt & getUpper() const
Return the upper value for this range.
LLVM_ABI bool contains(const APInt &Val) const
Return true if the specified value is in the set.
Opaque handle to a cycle within a GenericCycleInfo that wraps the cycle's preorder index.
A parsed version of the target data layout string in and methods for querying it.
unsigned getProgramAddressSpace() const
bool contains(const_arg_type_t< KeyT > Val) const
Return true if the specified key is in the map, false otherwise.
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
iterator find(const_arg_type_t< KeyT > Val)
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
Analysis pass which computes a DominatorTree.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
LLVM_ABI bool dominates(const BasicBlock *BB, const Use &U) const
Return true if the (end of the) basic block BB dominates the use U.
const BasicBlock & getEntryBlock() const
iterator_range< arg_iterator > args()
const Function & getFunction() const
Argument * getArg(unsigned i) const
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
BlockT * getHeader(CycleRef C) const
CycleRef getCycle(const BlockT *Block) const
Find the innermost cycle containing Block.
LLVM_ABI bool isDeclaration() const
Return true if the primary definition of this global value is outside of the current translation unit...
bool hasLocalLinkage() const
PointerType * getType() const
Global values are always pointers.
static LLVM_ABI bool compare(const APInt &LHS, const APInt &RHS, ICmpInst::Predicate Pred)
Return result of LHS Pred RHS comparison.
Value * CreatePtrAdd(Value *Ptr, Value *Offset, const Twine &Name="", GEPNoWrapFlags NW=GEPNoWrapFlags::none())
ConstantInt * getInt64(uint64_t C)
Get a constant 64-bit value.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
LLVM_ABI Instruction * clone() const
Create a copy of 'this' instruction that is identical in all ways except the following:
LLVM_ABI bool isLifetimeStartOrEnd() const LLVM_READONLY
Return true if the instruction is a llvm.lifetime.start or llvm.lifetime.end marker.
bool mayReadOrWriteMemory() const
Return true if this instruction may read or write memory.
LLVM_ABI bool mayWriteToMemory() const LLVM_READONLY
Return true if this instruction may modify memory.
bool hasMetadata() const
Return true if this instruction has any metadata attached to it.
LLVM_ABI void insertBefore(InstListType::iterator InsertPos)
Insert an unlinked instruction into a basic block immediately before the specified position.
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
LLVM_ABI const Function * getFunction() const
Return the function this instruction belongs to.
LLVM_ABI BasicBlock * getSuccessor(unsigned Idx) const LLVM_READONLY
Return the specified successor. This instruction must be a terminator.
LLVM_ABI bool mayHaveSideEffects() const LLVM_READONLY
Return true if the instruction may have side effects.
bool isTerminator() const
LLVM_ABI bool mayReadFromMemory() const LLVM_READONLY
Return true if this instruction may read memory.
iterator_range< user_iterator > users()
LLVM_ABI void setMetadata(unsigned KindID, MDNode *Node)
Set the metadata of the specified kind to the specified node.
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
This is an important class for using LLVM in a threaded context.
LLVM_ABI ConstantRange getConstantRange(Value *V, Instruction *CtxI, bool UndefAllowed)
Return the ConstantRange constraint that is known to hold for the specified value at the specified in...
LoopT * getLoopFor(const BlockT *BB) const
Return the inner most loop that BB lives in.
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
static LLVM_ABI MDNode * getMostGenericRange(MDNode *A, MDNode *B)
static MemoryEffectsBase readOnly()
bool doesNotAccessMemory() const
Whether this function accesses no memory.
static MemoryEffectsBase argMemOnly(ModRefInfo MR=ModRefInfo::ModRef)
static MemoryEffectsBase inaccessibleMemOnly(ModRefInfo MR=ModRefInfo::ModRef)
bool onlyAccessesInaccessibleMem() const
Whether this function only (at most) accesses inaccessible memory.
ModRefInfo getModRef(Location Loc) const
Get ModRefInfo for the given Location.
bool onlyAccessesArgPointees() const
Whether this function only (at most) accesses argument memory.
bool onlyReadsMemory() const
Whether this function only (at most) reads memory.
static MemoryEffectsBase writeOnly()
static MemoryEffectsBase inaccessibleOrArgMemOnly(ModRefInfo MR=ModRefInfo::ModRef)
static MemoryEffectsBase none()
bool onlyAccessesInaccessibleOrArgMem() const
Whether this function only (at most) accesses argument and inaccessible memory.
static MemoryEffectsBase unknown()
static LLVM_ABI std::optional< MemoryLocation > getOrNone(const Instruction *Inst)
static SizeOffsetValue unknown()
static PHINode * Create(Type *Ty, unsigned NumReservedValues, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
Constructors - NumReservedValues is a hint for the number of incoming edges that this phi node will h...
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
Value * getReturnValue() const
Convenience accessor. Returns null if there is no return value.
LLVM_ABI SCEVUse getSCEVAtScope(const SCEV *S, const Loop *L)
Return a SCEV expression for the specified value at the specified scope in the program.
LLVM_ABI const SCEV * getSCEV(Value *V)
Return a SCEV expression for the full generality of the specified expression.
LLVM_ABI unsigned getSmallConstantMaxTripCount(const Loop *L, SmallVectorImpl< const SCEVPredicate * > *Predicates=nullptr)
Returns the upper bound of the loop trip count as a normal unsigned value.
ConstantRange getUnsignedRange(const SCEV *S)
Determine the unsigned range for a particular SCEV.
A vector that has set insertion semantics.
size_type size() const
Determine the number of elements in the SetVector.
bool insert(const value_type &X)
Insert a new element into the SetVector.
bool erase(PtrType Ptr)
Remove pointer from the set.
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Used to lazily calculate structure layout information for a target machine, based on the DataLayout s...
TypeSize getElementOffset(unsigned Idx) const
TypeSize 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
@ Known
Known to have no common set bits.
@ Undef
Value of the register doesn't matter.
auto pred_end(const MachineBasicBlock *BB)
unsigned getPointerAddressSpace(const Type *T)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
auto successors(const MachineBasicBlock *BB)
LLVM_ABI bool isRemovableAlloc(const CallBase *V, const TargetLibraryInfo *TLI)
Return true if this is a call to an allocation function that does not have side effects that we are r...
APFloat abs(APFloat X)
Returns the absolute value of the argument.
@ Load
The value being inserted comes from a load (InsertElement only).
@ Store
The extracted value is stored (ExtractElement only).
LLVM_ABI raw_fd_ostream & outs()
This returns a reference to a raw_fd_ostream for standard output.
LLVM_ABI Value * getAllocAlignment(const CallBase *V, const TargetLibraryInfo *TLI)
Gets the alignment argument for an aligned_alloc-like function, using either built-in knowledge based...
auto dyn_cast_if_present(const Y &Val)
dyn_cast_if_present<X> - Functionally identical to dyn_cast, except that a null (or none in the case ...
LLVM_ABI Value * simplifyInstructionWithOperands(Instruction *I, ArrayRef< Value * > NewOps, const SimplifyQuery &Q)
Like simplifyInstruction but the operands of I are replaced with NewOps.
Value * GetPointerBaseWithConstantOffset(Value *Ptr, int64_t &Offset, const DataLayout &DL, bool AllowNonInbounds=true)
Analyze the specified pointer to see if it can be expressed as a base pointer plus a constant offset.
scc_iterator< T > scc_begin(const T &G)
Construct the begin iterator for a deduced graph type T.
LLVM_ABI bool isNoAliasCall(const Value *V)
Return true if this pointer is returned by a noalias function.
MemoryEffectsBase< IRMemLocation > MemoryEffects
Summary of how a function affects memory in the program.
raw_ostream & WriteGraph(raw_ostream &O, const GraphType &G, bool ShortNames=false, const Twine &Title="")
LLVM_ABI bool isSafeToSpeculativelyExecute(const Instruction *I, const Instruction *CtxI=nullptr, AssumptionCache *AC=nullptr, const DominatorTree *DT=nullptr, const TargetLibraryInfo *TLI=nullptr, bool UseVariableInfo=true, bool IgnoreUBImplyingAttrs=true)
Return true if the instruction does not have any effects besides calculating the result and does not ...
bool isa_and_nonnull(const Y &Val)
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
LLVM_ABI ConstantRange getConstantRangeFromMetadata(const MDNode &RangeMD)
Parse out a conservative ConstantRange from !range metadata.
auto map_range(ContainerTy &&C, FuncTy F)
Return a range that applies F to the elements of C.
const Value * getPointerOperand(const Value *V)
A helper function that returns the pointer operand of a load, store or GEP instruction.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
LLVM_ABI Value * simplifyInstruction(Instruction *I, const SimplifyQuery &Q)
See if we can compute a simplified version of this instruction.
auto dyn_cast_or_null(const Y &Val)
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
PotentialValuesState< std::pair< AA::ValueAndContext, AA::ValueScope > > PotentialLLVMValuesState
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI bool NullPointerIsDefined(const Function *F, unsigned AS=0)
Check whether null pointer dereferencing is considered undefined behavior for a given function or an ...
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool isPointerTy(const Type *T)
IRBuilder(LLVMContext &, FolderTy, InserterTy) -> IRBuilder< FolderTy, InserterTy >
LLVM_ABI bool wouldInstructionBeTriviallyDead(const Instruction *I, const TargetLibraryInfo *TLI=nullptr)
Return true if the result produced by the instruction would have no side effects if it was not used.
bool set_union(S1Ty &S1, const S2Ty &S2)
set_union(A, B) - Compute A := A u B, return whether A changed.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
LLVM_ABI CallBase & promoteCall(CallBase &CB, Function *Callee, CastInst **RetBitCast=nullptr)
Promote the given indirect call site to unconditionally call Callee.
LLVM_ABI const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth, bool MustPreserveProvenance=false)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ABI bool hasAssumption(const Function &F, const KnownAssumptionString &AssumptionStr)
Return true if F has the assumption AssumptionStr attached.
LLVM_ABI RetainedKnowledge getKnowledgeFromUse(const Use *U, ArrayRef< Attribute::AttrKind > AttrKinds)
Return a valid Knowledge associated to the Use U if its Attribute kind is in AttrKinds.
@ Success
The lock was released successfully.
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
LLVM_ABI bool isKnownNonZero(const Value *V, const SimplifyQuery &Q, unsigned Depth=0)
Return true if the given value is known to be non-zero when defined.
AtomicOrdering
Atomic ordering for LLVM's memory model.
PotentialValuesState< APInt > PotentialConstantIntValuesState
std::string join(IteratorT Begin, IteratorT End, StringRef Separator)
Joins the strings in the range [Begin, End), adding Separator between the elements.
InterleavedRange< Range > interleaved_array(const Range &R, StringRef Separator=", ")
Output range R as an array of interleaved elements.
ChangeStatus clampStateAndIndicateChange< DerefState >(DerefState &S, const DerefState &R)
void RemapInstruction(Instruction *I, ValueToValueMapTy &VM, RemapFlags Flags=RF_None, ValueMapTypeRemapper *TypeMapper=nullptr, ValueMaterializer *Materializer=nullptr, const MetadataPredicate *IdentityMD=nullptr)
Convert the instruction operands from referencing the current values into those specified by VM.
LLVM_ABI bool isIntrinsicReturningPointerAliasingArgumentWithoutCapturing(const CallBase *Call, bool MustPreserveOffset, bool MustPreserveProvenance=false)
launder.invariant.group and similar intrinsics return a pointer that aliases their argument,...
DWARFExpression::Operation Op
LLVM_ABI bool isGuaranteedNotToBeUndefOrPoison(const Value *V, AssumptionCache *AC=nullptr, const Instruction *CtxI=nullptr, const DominatorTree *DT=nullptr, unsigned Depth=0)
Return true if this function can prove that V does not have undef bits and is never poison.
ArrayRef(const T &OneElt) -> ArrayRef< T >
LLVM_ABI Value * getFreedOperand(const CallBase *CB, const TargetLibraryInfo *TLI)
If this if a call to a free function, return the freed operand.
ChangeStatus clampStateAndIndicateChange(StateType &S, const StateType &R)
Helper function to clamp a state S of type StateType with the information in R and indicate/return if...
constexpr unsigned BitWidth
ValueMap< const Value *, WeakTrackingVH > ValueToValueMapTy
auto pred_begin(const MachineBasicBlock *BB)
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
iterator_range< pointer_iterator< WrappedIteratorT > > make_pointer_range(RangeT &&Range)
LLVM_ABI std::optional< APInt > getAllocSize(const CallBase *CB, const TargetLibraryInfo *TLI, function_ref< const Value *(const Value *)> Mapper=[](const Value *V) { return V;})
Return the size of the requested allocation.
LLVM_ABI DenseSet< StringRef > getAssumptions(const Function &F)
Return the set of all assumptions for the function F.
Align assumeAligned(uint64_t Value)
Treats the value 0 as a 1, so Align is always at least 1.
LLVM_ABI Instruction * SplitBlockAndInsertIfThen(Value *Cond, BasicBlock::iterator SplitBefore, bool Unreachable, MDNode *BranchWeights=nullptr, DomTreeUpdater *DTU=nullptr, LoopInfo *LI=nullptr, BasicBlock *ThenBlock=nullptr)
Split the containing block at the specified instruction - everything before SplitBefore stays in the ...
@ OPTIONAL
The target may be valid if the source is not.
@ NONE
Do not track a dependence between source and target.
@ REQUIRED
The target cannot be valid if the source is not.
LLVM_ABI UseCaptureInfo DetermineUseCaptureKind(const Use &U, const Value *Base)
Determine what kind of capture behaviour U may exhibit.
LLVM_ABI Value * simplifyCmpInst(CmpPredicate Predicate, Value *LHS, Value *RHS, const SimplifyQuery &Q)
Given operands for a CmpInst, fold the result or return null.
LLVM_ABI bool mayContainIrreducibleControl(const Function &F, const LoopInfo *LI)
BumpPtrAllocatorImpl<> BumpPtrAllocator
The standard BumpPtrAllocator which just uses the default template parameters.
T bit_floor(T Value)
Returns the largest integral power of two no greater than Value if Value is nonzero.
bool capturesNothing(CaptureComponents CC)
LLVM_ABI bool isIdentifiedObject(const Value *V)
Return true if this pointer refers to a distinct and identifiable object.
bool capturesAnyProvenance(CaptureComponents CC)
constexpr StringRef AssumptionAttrKey
The key we use for assumption attributes.
constexpr bool isCallableCC(CallingConv::ID CC)
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
A type to track pointer/struct usage and accesses for AAPointerInfo.
bool forallInterferingAccesses(AA::RangeTy Range, F CB) const
See AAPointerInfo::forallInterferingAccesses.
AAPointerInfo::const_bin_iterator end() const
ChangeStatus addAccess(Attributor &A, const AAPointerInfo::RangeList &Ranges, Instruction &I, std::optional< Value * > Content, AAPointerInfo::AccessKind Kind, Type *Ty, Instruction *RemoteI=nullptr)
Add a new Access to the state at offset Offset and with size Size.
DenseMap< const Instruction *, SmallVector< unsigned > > RemoteIMap
AAPointerInfo::const_bin_iterator begin() const
AAPointerInfo::OffsetInfo ReturnedOffsets
Flag to determine if the underlying pointer is reaching a return statement in the associated function...
State & operator=(State &&R)
State(State &&SIS)=default
const AAPointerInfo::Access & getAccess(unsigned Index) const
SmallVector< AAPointerInfo::Access > AccessList
bool isAtFixpoint() const override
See AbstractState::isAtFixpoint().
bool forallInterferingAccesses(Instruction &I, F CB, AA::RangeTy &Range) const
See AAPointerInfo::forallInterferingAccesses.
static State getWorstState(const State &SIS)
Return the worst possible representable state.
int64_t numOffsetBins() const
AAPointerInfo::OffsetBinsTy OffsetBins
ChangeStatus indicateOptimisticFixpoint() override
See AbstractState::indicateOptimisticFixpoint().
State & operator=(const State &R)
ChangeStatus indicatePessimisticFixpoint() override
See AbstractState::indicatePessimisticFixpoint().
const State & getAssumed() const
static State getBestState(const State &SIS)
Return the best possible representable state.
bool isValidState() const override
See AbstractState::isValidState().
----------------—AAIntraFnReachability Attribute-----------------------—
ReachabilityQueryInfo(const ReachabilityQueryInfo &RQI)
unsigned Hash
Precomputed hash for this RQI.
const Instruction * From
Start here,.
Reachable Result
and remember if it worked:
ReachabilityQueryInfo(const Instruction *From, const ToTy *To)
ReachabilityQueryInfo(Attributor &A, const Instruction &From, const ToTy &To, const AA::InstExclusionSetTy *ES, bool MakeUnique)
Constructor replacement to ensure unique and stable sets are used for the cache.
const ToTy * To
reach this place,
const AA::InstExclusionSetTy * ExclusionSet
without going through any of these instructions,
unsigned computeHashValue() const
An abstract interface for address space information.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for all align attributes.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
Align getKnownAlign() const
Return known alignment.
static LLVM_ABI const char ID
An abstract attribute for getting assumption information.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract state for querying live call edges.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract Attribute for specializing "dynamic" components of denormal_fpenv to a known denormal mod...
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for all dereferenceable attribute.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for llvm::GlobalValue information interference.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for indirect call information interference.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface to track if a value leaves it's defining function instance.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract Attribute for computing reachability between functions.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
bool canReach(Attributor &A, const Function &Fn) const
If the function represented by this possition can reach Fn.
virtual bool instructionCanReach(Attributor &A, const Instruction &Inst, const Function &Fn, const AA::InstExclusionSetTy *ExclusionSet=nullptr) const =0
Can Inst reach Fn.
An abstract interface to determine reachability of point A to B.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for identifying pointers from which loads can be marked invariant.
static LLVM_ABI const char ID
Unique ID (due to the unique address).
An abstract interface for liveness abstract attribute.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for memory access kind related attributes (readnone/readonly/writeonly).
bool isAssumedReadOnly() const
Return true if we assume that the underlying value is not accessed (=written) in its respective scope...
bool isKnownReadNone() const
Return true if we know that the underlying value is not read or accessed in its respective scope.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
bool isAssumedReadNone() const
Return true if we assume that the underlying value is not read or accessed in its respective scope.
An abstract interface for all memory location attributes (readnone/argmemonly/inaccessiblememonly/ina...
static LLVM_ABI std::string getMemoryLocationsAsStr(MemoryLocationsKind MLK)
Return the locations encoded by MLK as a readable string.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
StateType::base_t MemoryLocationsKind
An abstract interface for all nonnull attributes.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for potential address space information.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for all noalias attributes.
static LLVM_ABI bool isImpliedByIR(Attributor &A, const IRPosition &IRP, Attribute::AttrKind ImpliedAttributeKind, bool IgnoreSubsumingPositions=false)
See IRAttribute::isImpliedByIR.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for all nocapture attributes.
@ NO_CAPTURE_MAYBE_RETURNED
If we do not capture the value in memory or through integers we can only communicate it back as a der...
@ NO_CAPTURE
If we do not capture the value in memory, through integers, or as a derived pointer we know it is not...
static LLVM_ABI const char ID
Unique ID (due to the unique address)
bool isAssumedNoCaptureMaybeReturned() const
Return true if we assume that the underlying value is not captured in its respective scope but we all...
static LLVM_ABI bool isImpliedByIR(Attributor &A, const IRPosition &IRP, Attribute::AttrKind ImpliedAttributeKind, bool IgnoreSubsumingPositions=false)
See IRAttribute::isImpliedByIR.
static LLVM_ABI void determineFunctionCaptureCapabilities(const IRPosition &IRP, const Function &F, BitIntegerState &State)
Update State according to the capture capabilities of F for position IRP.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An AbstractAttribute for nofree.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract attribute for norecurse.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An AbstractAttribute for noreturn.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
static LLVM_ABI const char ID
Unique ID (due to the unique address)
static LLVM_ABI bool isAlignedBarrier(const CallBase &CB, bool ExecutedAligned)
Helper function to determine if CB is an aligned (GPU) barrier.
static LLVM_ABI bool isNonRelaxedAtomic(const Instruction *I)
Helper function used to determine whether an instruction is non-relaxed atomic.
An abstract interface for all noundef attributes.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
static LLVM_ABI bool isImpliedByIR(Attributor &A, const IRPosition &IRP, Attribute::AttrKind ImpliedAttributeKind, bool IgnoreSubsumingPositions=false)
See IRAttribute::isImpliedByIR.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract Attribute for determining the necessity of the convergent attribute.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for all nonnull attributes.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
static LLVM_ABI bool isImpliedByIR(Attributor &A, const IRPosition &IRP, Attribute::AttrKind ImpliedAttributeKind, bool IgnoreSubsumingPositions=false)
See AbstractAttribute::isImpliedByIR(...).
A helper containing a list of offsets computed for a Use.
A container for a list of ranges.
static void set_difference(const RangeList &L, const RangeList &R, RangeList &D)
Copy ranges from L that are not in R, into D.
An abstract interface for struct information.
virtual bool reachesReturn() const =0
OffsetBinsTy::const_iterator const_bin_iterator
virtual const_bin_iterator begin() const =0
DenseMap< AA::RangeTy, SmallSet< unsigned, 4 > > OffsetBinsTy
static LLVM_ABI const char ID
Unique ID (due to the unique address)
virtual int64_t numOffsetBins() const =0
An abstract interface for potential values analysis.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
static LLVM_ABI const char ID
Unique ID (due to the unique address)
static LLVM_ABI Value * getSingleValue(Attributor &A, const AbstractAttribute &AA, const IRPosition &IRP, SmallVectorImpl< AA::ValueAndContext > &Values)
Extract the single value in Values if any.
An abstract interface for privatizability.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract attribute for undefined behavior.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract attribute for getting all assumption underlying objects.
virtual bool forallUnderlyingObjects(function_ref< bool(Value &)> Pred, AA::ValueScope Scope=AA::Interprocedural) const =0
Check Pred on all underlying objects in Scope collected so far.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for range value analysis.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for value simplify abstract attribute.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract attribute for willreturn.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
Helper to represent an access offset and size, with logic to deal with uncertainty and check for over...
static constexpr int64_t Unknown
static RangeTy getUnknown()
const Instruction * getCtxI() const
Base struct for all "concrete attribute" deductions.
void print(raw_ostream &OS) const
Helper functions, for debug purposes only.
virtual StateType & getState()=0
Return the internal abstract state for inspection.
An interface to query the internal state of an abstract attribute.
virtual bool isAtFixpoint() const =0
Return if this abstract state is fixed, thus does not need to be updated if information changes as it...
virtual bool isValidState() const =0
Return if this abstract state is in a valid state.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
static constexpr Align fromLog2(unsigned Log2Value)
Returns an alignment of 1 << Log2Value bytes.
std::function< void( const ArgumentReplacementInfo &, Function &, Function::arg_iterator)> CalleeRepairCBTy
Callee repair callback type.
const Argument & getReplacedArg() const
std::function< void(const ArgumentReplacementInfo &, AbstractCallSite, SmallVectorImpl< Value * > &)> ACSRepairCBTy
Abstract call site (ACS) repair callback type.
The fixpoint analysis framework that orchestrates the attribute deduction.
std::function< std::optional< Value * >( const IRPosition &, const AbstractAttribute *, bool &)> SimplifictionCallbackTy
Register CB as a simplification callback.
Specialization of the integer state for a bit-wise encoding.
BitIntegerState & addKnownBits(base_t Bits)
Add the bits in BitsEncoding to the "known bits".
Simple wrapper for a single bit (boolean) state.
static constexpr DenormalFPEnv getDefault()
static unsigned getHashValue(const Access &A)
AAPointerInfo::Access Access
static bool isEqual(const Access &LHS, const Access &RHS)
static bool isEqual(const AA::RangeTy &A, const AA::RangeTy B)
static unsigned getHashValue(const AA::RangeTy &Range)
DenseMapInfo< std::pair< const Instruction *, const ToTy * > > PairDMI
static bool isEqual(const ReachabilityQueryInfo< ToTy > *LHS, const ReachabilityQueryInfo< ToTy > *RHS)
DenseMapInfo< const AA::InstExclusionSetTy * > InstSetDMI
static unsigned getHashValue(const ReachabilityQueryInfo< ToTy > *RQI)
An information struct used to provide DenseMap with the various necessary components for a given valu...
State for dereferenceable attribute.
IncIntegerState DerefBytesState
State representing for dereferenceable bytes.
ChangeStatus manifest(Attributor &A) override
See AbstractAttribute::manifest(...).
Helper to describe and deal with positions in the LLVM-IR.
Function * getAssociatedFunction() const
Return the associated function, if any.
static const IRPosition callsite_returned(const CallBase &CB)
Create a position describing the returned value of CB.
static const IRPosition returned(const Function &F, const CallBaseContext *CBContext=nullptr)
Create a position describing the returned value of F.
LLVM_ABI Argument * getAssociatedArgument() const
Return the associated argument, if any.
static const IRPosition value(const Value &V, const CallBaseContext *CBContext=nullptr)
Create a position describing the value of V.
int getCalleeArgNo() const
Return the callee argument number of the associated value if it is an argument or call site argument,...
static const IRPosition inst(const Instruction &I, const CallBaseContext *CBContext=nullptr)
Create a position describing the instruction I.
static const IRPosition callsite_argument(const CallBase &CB, unsigned ArgNo)
Create a position describing the argument of CB at position ArgNo.
@ IRP_ARGUMENT
An attribute for a function argument.
@ IRP_RETURNED
An attribute for the function return value.
@ IRP_CALL_SITE
An attribute for a call site (function scope).
@ IRP_CALL_SITE_RETURNED
An attribute for a call site return value.
@ IRP_FUNCTION
An attribute for a function (scope).
@ IRP_CALL_SITE_ARGUMENT
An attribute for a call site argument.
@ IRP_INVALID
An invalid position.
Instruction * getCtxI() const
Return the context instruction, if any.
static const IRPosition argument(const Argument &Arg, const CallBaseContext *CBContext=nullptr)
Create a position describing the argument Arg.
Type * getAssociatedType() const
Return the type this abstract attribute is associated with.
static const IRPosition function(const Function &F, const CallBaseContext *CBContext=nullptr)
Create a position describing the function scope of F.
const CallBaseContext * getCallBaseContext() const
Get the call base context from the position.
Value & getAssociatedValue() const
Return the value this abstract attribute is associated with.
Value & getAnchorValue() const
Return the value this abstract attribute is anchored with.
int getCallSiteArgNo() const
Return the call site argument number of the associated value if it is an argument or call site argume...
static const IRPosition function_scope(const IRPosition &IRP, const CallBaseContext *CBContext=nullptr)
Create a position with function scope matching the "context" of IRP.
Kind getPositionKind() const
Return the associated position kind.
bool isArgumentPosition() const
Return true if the position is an argument or call site argument.
static const IRPosition callsite_function(const CallBase &CB)
Create a position describing the function scope of CB.
Function * getAnchorScope() const
Return the Function surrounding the anchor value.
ConstantRange getKnown() const
Return the known state encoding.
ConstantRange getAssumed() const
Return the assumed state encoding.
base_t getAssumed() const
Return the assumed state encoding.
static constexpr base_t getWorstState()
Helper that allows to insert a new assumption string in the known assumption set by creating a (stati...
FPClassTest getKnownFPClasses() const
Floating-point classes the value could be one of.
A "must be executed context" for a given program point PP is the set of instructions,...
iterator & end()
Return an universal end iterator.
bool findInContextOf(const Instruction *I, const Instruction *PP)
Helper to look for I in the context of PP.
iterator & begin(const Instruction *PP)
Return an iterator to explore the context around PP.
bool checkForAllContext(const Instruction *PP, function_ref< bool(const Instruction *)> Pred)
}
static unsigned MaxPotentialValues
Helper to tie a abstract state implementation to an abstract attribute.
StateType & getState() override
See AbstractAttribute::getState(...).
bool isPassthrough() const
CaptureComponents ResultCC
Components captured by the return value of the user of this Use.
LLVM_ABI bool unionAssumed(std::optional< Value * > Other)
Merge Other into the currently assumed simplified value.
std::optional< Value * > SimplifiedAssociatedValue
An assumed simplified value.
Type * Ty
The type of the original value.