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();
1471 for (
int i = 0, e = VT->getElementCount().getFixedValue(); i != e; ++i) {
1473 ConstContent, ConstantInt::get(Int32Ty, i));
1480 for (
auto &ElementOffset : ElementOffsets)
1481 ElementOffset += ElementSize;
1494 bool collectConstantsForGEP(Attributor &
A,
const DataLayout &
DL,
1495 OffsetInfo &UsrOI,
const OffsetInfo &PtrOI,
1496 const GEPOperator *
GEP);
1499 void trackStatistics()
const override {
1500 AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());
1504bool AAPointerInfoFloating::collectConstantsForGEP(Attributor &
A,
1505 const DataLayout &
DL,
1507 const OffsetInfo &PtrOI,
1508 const GEPOperator *
GEP) {
1509 unsigned BitWidth =
DL.getIndexTypeSizeInBits(
GEP->getType());
1510 SmallMapVector<Value *, APInt, 4> VariableOffsets;
1513 assert(!UsrOI.isUnknown() && !PtrOI.isUnknown() &&
1514 "Don't look for constant values if the offset has already been "
1515 "determined to be unknown.");
1517 if (!
GEP->collectOffset(
DL,
BitWidth, VariableOffsets, ConstantOffset)) {
1523 << (VariableOffsets.
empty() ?
"" :
"not") <<
" constant "
1527 Union.addToAll(ConstantOffset.getSExtValue());
1532 for (
const auto &VI : VariableOffsets) {
1533 auto *PotentialConstantsAA =
A.getAAFor<AAPotentialConstantValues>(
1535 if (!PotentialConstantsAA || !PotentialConstantsAA->isValidState()) {
1541 if (PotentialConstantsAA->undefIsContained())
1548 auto &AssumedSet = PotentialConstantsAA->getAssumedSet();
1549 if (AssumedSet.empty())
1553 for (
const auto &ConstOffset : AssumedSet) {
1554 auto CopyPerOffset =
Union;
1555 CopyPerOffset.addToAll(ConstOffset.getSExtValue() *
1556 VI.second.getZExtValue());
1557 Product.merge(CopyPerOffset);
1562 UsrOI = std::move(Union);
1566ChangeStatus AAPointerInfoFloating::updateImpl(Attributor &
A) {
1567 using namespace AA::PointerInfo;
1569 const DataLayout &
DL =
A.getDataLayout();
1570 Value &AssociatedValue = getAssociatedValue();
1572 DenseMap<Value *, OffsetInfo> OffsetInfoMap;
1573 OffsetInfoMap[&AssociatedValue].
insert(0);
1575 auto HandlePassthroughUser = [&](
Value *Usr,
Value *CurPtr,
bool &Follow) {
1586 "CurPtr does not exist in the map!");
1588 auto &UsrOI = OffsetInfoMap[Usr];
1589 auto &PtrOI = OffsetInfoMap[CurPtr];
1590 assert(!PtrOI.isUnassigned() &&
1591 "Cannot pass through if the input Ptr was not visited!");
1597 auto UsePred = [&](
const Use &
U,
bool &Follow) ->
bool {
1599 User *Usr =
U.getUser();
1600 LLVM_DEBUG(
dbgs() <<
"[AAPointerInfo] Analyze " << *CurPtr <<
" in " << *Usr
1603 "The current pointer offset should have been seeded!");
1604 assert(!OffsetInfoMap[CurPtr].isUnassigned() &&
1605 "Current pointer should be assigned");
1611 return HandlePassthroughUser(Usr, CurPtr, Follow);
1616 auto &UsrOI = OffsetInfoMap[Usr];
1617 auto &PtrOI = OffsetInfoMap[CurPtr];
1619 if (UsrOI.isUnknown())
1622 if (PtrOI.isUnknown()) {
1628 Follow = collectConstantsForGEP(
A,
DL, UsrOI, PtrOI,
GEP);
1632 return HandlePassthroughUser(Usr, CurPtr, Follow);
1637 if (RI->getFunction() == getAssociatedFunction()) {
1638 auto &PtrOI = OffsetInfoMap[CurPtr];
1639 Changed |= setReachesReturn(PtrOI);
1652 auto &UsrOI = PhiIt->second;
1653 auto &PtrOI = OffsetInfoMap[CurPtr];
1657 if (PtrOI.isUnknown()) {
1658 LLVM_DEBUG(
dbgs() <<
"[AAPointerInfo] PHI operand offset unknown "
1659 << *CurPtr <<
" in " << *
PHI <<
"\n");
1660 Follow = !UsrOI.isUnknown();
1666 if (UsrOI == PtrOI) {
1667 assert(!PtrOI.isUnassigned() &&
1668 "Cannot assign if the current Ptr was not visited!");
1669 LLVM_DEBUG(
dbgs() <<
"[AAPointerInfo] PHI is invariant (so far)");
1679 auto It = OffsetInfoMap.
find(CurPtrBase);
1680 if (It == OffsetInfoMap.
end()) {
1681 LLVM_DEBUG(
dbgs() <<
"[AAPointerInfo] PHI operand is too complex "
1682 << *CurPtr <<
" in " << *
PHI
1683 <<
" (base: " << *CurPtrBase <<
")\n");
1697 A.getInfoCache().getAnalysisResultForFunction<CycleAnalysis>(
1698 *
PHI->getFunction());
1700 auto BaseOI = It->getSecond();
1701 BaseOI.addToAll(
Offset.getZExtValue());
1702 if (IsFirstPHIUser || BaseOI == UsrOI) {
1703 LLVM_DEBUG(
dbgs() <<
"[AAPointerInfo] PHI is invariant " << *CurPtr
1704 <<
" in " << *Usr <<
"\n");
1705 return HandlePassthroughUser(Usr, CurPtr, Follow);
1709 dbgs() <<
"[AAPointerInfo] PHI operand pointer offset mismatch "
1710 << *CurPtr <<
" in " << *
PHI <<
"\n");
1729 if (!handleAccess(
A, *LoadI,
nullptr, AK,
1730 OffsetInfoMap[CurPtr].Offsets,
Changed,
1736 return II->isAssumeLikeIntrinsic();
1747 }
while (FromI && FromI != ToI);
1752 auto IsValidAssume = [&](IntrinsicInst &IntrI) {
1753 if (IntrI.getIntrinsicID() != Intrinsic::assume)
1756 if (IntrI.getParent() == BB) {
1757 if (IsImpactedInRange(LoadI->getNextNode(), &IntrI))
1763 if ((*PredIt) != BB)
1768 if (SuccBB == IntrBB)
1774 if (IsImpactedInRange(LoadI->getNextNode(), BB->
getTerminator()))
1776 if (IsImpactedInRange(&IntrBB->
front(), &IntrI))
1782 std::pair<Value *, IntrinsicInst *> Assumption;
1783 for (
const Use &LoadU : LoadI->uses()) {
1785 if (!CmpI->isEquality() || !CmpI->isTrueWhenEqual())
1787 for (
const Use &CmpU : CmpI->uses()) {
1789 if (!IsValidAssume(*IntrI))
1791 int Idx = CmpI->getOperandUse(0) == LoadU;
1792 Assumption = {CmpI->getOperand(Idx), IntrI};
1797 if (Assumption.first)
1802 if (!Assumption.first || !Assumption.second)
1806 << *Assumption.second <<
": " << *LoadI
1807 <<
" == " << *Assumption.first <<
"\n");
1808 bool UsedAssumedInformation =
false;
1809 std::optional<Value *> Content =
nullptr;
1810 if (Assumption.first)
1812 A.getAssumedSimplified(*Assumption.first, *
this,
1814 return handleAccess(
1815 A, *Assumption.second, Content, AccessKind::AK_ASSUMPTION,
1816 OffsetInfoMap[CurPtr].Offsets,
Changed, *LoadI->getType());
1821 for (
auto *OtherOp : OtherOps) {
1822 if (OtherOp == CurPtr) {
1825 <<
"[AAPointerInfo] Escaping use in store like instruction " <<
I
1837 bool UsedAssumedInformation =
false;
1838 std::optional<Value *> Content =
nullptr;
1840 Content =
A.getAssumedSimplified(
1842 return handleAccess(
A,
I, Content, AK, OffsetInfoMap[CurPtr].Offsets,
1847 return HandleStoreLike(*StoreI, StoreI->getValueOperand(),
1848 *StoreI->getValueOperand()->getType(),
1849 {StoreI->getValueOperand()}, AccessKind::AK_W);
1851 return HandleStoreLike(*RMWI,
nullptr, *RMWI->getValOperand()->getType(),
1852 {RMWI->getValOperand()}, AccessKind::AK_RW);
1854 return HandleStoreLike(
1855 *CXI,
nullptr, *CXI->getNewValOperand()->getType(),
1856 {CXI->getCompareOperand(), CXI->getNewValOperand()},
1863 A.getInfoCache().getTargetLibraryInfoForFunction(*CB->
getFunction());
1868 const auto *CSArgPI =
A.getAAFor<AAPointerInfo>(
1874 Changed = translateAndAddState(
A, *CSArgPI, OffsetInfoMap[CurPtr], *CB,
1877 if (!CSArgPI->reachesReturn())
1878 return isValidState();
1881 if (!Callee ||
Callee->arg_size() <= ArgNo)
1883 bool UsedAssumedInformation =
false;
1884 auto ReturnedValue =
A.getAssumedSimplified(
1889 auto *Arg =
Callee->getArg(ArgNo);
1890 if (ReturnedArg && Arg != ReturnedArg)
1892 bool IsRetMustAcc = IsArgMustAcc && (ReturnedArg == Arg);
1893 const auto *CSRetPI =
A.getAAFor<AAPointerInfo>(
1897 OffsetInfo OI = OffsetInfoMap[CurPtr];
1898 CSArgPI->addReturnedOffsetsTo(OI);
1900 translateAndAddState(
A, *CSRetPI, OI, *CB, IsRetMustAcc) |
Changed;
1901 return isValidState();
1903 LLVM_DEBUG(
dbgs() <<
"[AAPointerInfo] Call user not handled " << *CB
1908 LLVM_DEBUG(
dbgs() <<
"[AAPointerInfo] User not handled " << *Usr <<
"\n");
1911 auto EquivalentUseCB = [&](
const Use &OldU,
const Use &NewU) {
1912 assert(OffsetInfoMap.
count(OldU) &&
"Old use should be known already!");
1913 assert(!OffsetInfoMap[OldU].isUnassigned() &&
"Old use should be assinged");
1914 if (OffsetInfoMap.
count(NewU)) {
1916 if (!(OffsetInfoMap[NewU] == OffsetInfoMap[OldU])) {
1917 dbgs() <<
"[AAPointerInfo] Equivalent use callback failed: "
1918 << OffsetInfoMap[NewU] <<
" vs " << OffsetInfoMap[OldU]
1922 return OffsetInfoMap[NewU] == OffsetInfoMap[OldU];
1925 return HandlePassthroughUser(NewU.get(), OldU.
get(), Unused);
1927 if (!
A.checkForAllUses(UsePred, *
this, AssociatedValue,
1929 true, EquivalentUseCB)) {
1930 LLVM_DEBUG(
dbgs() <<
"[AAPointerInfo] Check for all uses failed, abort!\n");
1931 return indicatePessimisticFixpoint();
1935 dbgs() <<
"Accesses by bin after update:\n";
1942struct AAPointerInfoReturned final : AAPointerInfoImpl {
1943 AAPointerInfoReturned(
const IRPosition &IRP, Attributor &
A)
1944 : AAPointerInfoImpl(IRP,
A) {}
1948 return indicatePessimisticFixpoint();
1952 void trackStatistics()
const override {
1953 AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());
1957struct AAPointerInfoArgument final : AAPointerInfoFloating {
1958 AAPointerInfoArgument(
const IRPosition &IRP, Attributor &
A)
1959 : AAPointerInfoFloating(IRP,
A) {}
1962 void trackStatistics()
const override {
1963 AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());
1967struct AAPointerInfoCallSiteArgument final : AAPointerInfoFloating {
1968 AAPointerInfoCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
1969 : AAPointerInfoFloating(IRP,
A) {}
1973 using namespace AA::PointerInfo;
1979 if (
auto Length =
MI->getLengthInBytes())
1980 LengthVal =
Length->getSExtValue();
1981 unsigned ArgNo = getIRPosition().getCallSiteArgNo();
1984 LLVM_DEBUG(
dbgs() <<
"[AAPointerInfo] Unhandled memory intrinsic "
1986 return indicatePessimisticFixpoint();
1989 ArgNo == 0 ? AccessKind::AK_MUST_WRITE : AccessKind::AK_MUST_READ;
1991 Changed | addAccess(
A, {0, LengthVal}, *
MI,
nullptr,
Kind,
nullptr);
1994 dbgs() <<
"Accesses by bin after update:\n";
2005 Argument *Arg = getAssociatedArgument();
2009 A.getAAFor<AAPointerInfo>(*
this, ArgPos, DepClassTy::REQUIRED);
2010 if (ArgAA && ArgAA->getState().isValidState())
2011 return translateAndAddStateFromCallee(
A, *ArgAA,
2014 return indicatePessimisticFixpoint();
2017 bool IsKnownNoCapture;
2019 A,
this, getIRPosition(), DepClassTy::OPTIONAL, IsKnownNoCapture))
2020 return indicatePessimisticFixpoint();
2022 bool IsKnown =
false;
2024 return ChangeStatus::UNCHANGED;
2027 ReadOnly ? AccessKind::AK_MAY_READ : AccessKind::AK_MAY_READ_WRITE;
2033 void trackStatistics()
const override {
2034 AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());
2038struct AAPointerInfoCallSiteReturned final : AAPointerInfoFloating {
2039 AAPointerInfoCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
2040 : AAPointerInfoFloating(IRP,
A) {}
2043 void trackStatistics()
const override {
2044 AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());
2052struct AANoUnwindImpl : AANoUnwind {
2053 AANoUnwindImpl(
const IRPosition &IRP, Attributor &
A) : AANoUnwind(IRP,
A) {}
2059 A,
nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));
2063 const std::string getAsStr(Attributor *
A)
const override {
2064 return getAssumed() ?
"nounwind" :
"may-unwind";
2070 (unsigned)Instruction::Invoke, (
unsigned)Instruction::CallBr,
2071 (unsigned)Instruction::Call, (
unsigned)Instruction::CleanupRet,
2072 (unsigned)Instruction::CatchSwitch, (
unsigned)Instruction::Resume};
2075 if (!
I.mayThrow(
true))
2079 bool IsKnownNoUnwind;
2087 bool UsedAssumedInformation =
false;
2088 if (!
A.checkForAllInstructions(CheckForNoUnwind, *
this, Opcodes,
2089 UsedAssumedInformation))
2090 return indicatePessimisticFixpoint();
2092 return ChangeStatus::UNCHANGED;
2096struct AANoUnwindFunction final :
public AANoUnwindImpl {
2097 AANoUnwindFunction(
const IRPosition &IRP, Attributor &
A)
2098 : AANoUnwindImpl(IRP,
A) {}
2105struct AANoUnwindCallSite final
2106 : AACalleeToCallSite<AANoUnwind, AANoUnwindImpl> {
2107 AANoUnwindCallSite(
const IRPosition &IRP, Attributor &
A)
2108 : AACalleeToCallSite<AANoUnwind, AANoUnwindImpl>(IRP,
A) {}
2119 case Intrinsic::nvvm_barrier_cta_sync_aligned_all:
2120 case Intrinsic::nvvm_barrier_cta_sync_aligned_count:
2121 case Intrinsic::nvvm_barrier_cta_red_and_aligned_all:
2122 case Intrinsic::nvvm_barrier_cta_red_and_aligned_count:
2123 case Intrinsic::nvvm_barrier_cta_red_or_aligned_all:
2124 case Intrinsic::nvvm_barrier_cta_red_or_aligned_count:
2125 case Intrinsic::nvvm_barrier_cta_red_popc_aligned_all:
2126 case Intrinsic::nvvm_barrier_cta_red_popc_aligned_count:
2128 case Intrinsic::amdgcn_s_barrier:
2129 if (ExecutedAligned)
2152 switch (
I->getOpcode()) {
2153 case Instruction::AtomicRMW:
2156 case Instruction::Store:
2159 case Instruction::Load:
2164 "New atomic operations need to be known in the attributor.");
2183 const std::string getAsStr(Attributor *
A)
const override {
2184 return getAssumed() ?
"nosync" :
"may-sync";
2200 if (
I.mayReadOrWriteMemory())
2214 bool UsedAssumedInformation =
false;
2215 if (!
A.checkForAllReadWriteInstructions(CheckRWInstForNoSync, *
this,
2216 UsedAssumedInformation) ||
2217 !
A.checkForAllCallLikeInstructions(CheckForNoSync, *
this,
2218 UsedAssumedInformation))
2219 return indicatePessimisticFixpoint();
2224struct AANoSyncFunction final :
public AANoSyncImpl {
2225 AANoSyncFunction(
const IRPosition &IRP, Attributor &
A)
2226 : AANoSyncImpl(IRP,
A) {}
2233struct AANoSyncCallSite final : AACalleeToCallSite<AANoSync, AANoSyncImpl> {
2234 AANoSyncCallSite(
const IRPosition &IRP, Attributor &
A)
2235 : AACalleeToCallSite<AANoSync, AANoSyncImpl>(IRP,
A) {}
2245struct AANoFreeImpl :
public AANoFree {
2246 AANoFreeImpl(
const IRPosition &IRP, Attributor &
A) : AANoFree(IRP,
A) {}
2252 DepClassTy::NONE, IsKnown));
2270 bool UsedAssumedInformation =
false;
2271 if (!
A.checkForAllReadWriteInstructions(CheckForNoFree, *
this,
2272 UsedAssumedInformation) ||
2273 !
A.checkForAllCallLikeInstructions(CheckForNoFree, *
this,
2274 UsedAssumedInformation))
2275 return indicatePessimisticFixpoint();
2277 return ChangeStatus::UNCHANGED;
2281 const std::string getAsStr(Attributor *
A)
const override {
2282 return getAssumed() ?
"nofree" :
"may-free";
2286struct AANoFreeFunction final :
public AANoFreeImpl {
2287 AANoFreeFunction(
const IRPosition &IRP, Attributor &
A)
2288 : AANoFreeImpl(IRP,
A) {}
2295struct AANoFreeCallSite final : AACalleeToCallSite<AANoFree, AANoFreeImpl> {
2296 AANoFreeCallSite(
const IRPosition &IRP, Attributor &
A)
2297 : AACalleeToCallSite<AANoFree, AANoFreeImpl>(IRP,
A) {}
2304struct AANoFreeFloating : AANoFreeImpl {
2305 AANoFreeFloating(
const IRPosition &IRP, Attributor &
A)
2306 : AANoFreeImpl(IRP,
A) {}
2313 const IRPosition &IRP = getIRPosition();
2318 DepClassTy::OPTIONAL, IsKnown))
2319 return ChangeStatus::UNCHANGED;
2321 Value &AssociatedValue = getIRPosition().getAssociatedValue();
2322 auto Pred = [&](
const Use &
U,
bool &Follow) ->
bool {
2337 DepClassTy::REQUIRED, IsKnown))
2340 const AANoCapture *NoCaptureAA =
nullptr;
2343 DepClassTy::REQUIRED, IsKnown,
2344 false, &NoCaptureAA)) {
2369 if (!
A.checkForAllUses(Pred, *
this, AssociatedValue))
2370 return indicatePessimisticFixpoint();
2372 return ChangeStatus::UNCHANGED;
2377struct AANoFreeArgument final : AANoFreeFloating {
2378 AANoFreeArgument(
const IRPosition &IRP, Attributor &
A)
2379 : AANoFreeFloating(IRP,
A) {}
2386struct AANoFreeCallSiteArgument final : AANoFreeFloating {
2387 AANoFreeCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
2388 : AANoFreeFloating(IRP,
A) {}
2396 Argument *Arg = getAssociatedArgument();
2398 return indicatePessimisticFixpoint();
2402 DepClassTy::REQUIRED, IsKnown))
2403 return ChangeStatus::UNCHANGED;
2404 return indicatePessimisticFixpoint();
2412struct AANoFreeReturned final : AANoFreeFloating {
2413 AANoFreeReturned(
const IRPosition &IRP, Attributor &
A)
2414 : AANoFreeFloating(IRP,
A) {
2429 void trackStatistics()
const override {}
2433struct AANoFreeCallSiteReturned final : AANoFreeFloating {
2434 AANoFreeCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
2435 : AANoFreeFloating(IRP,
A) {}
2438 return ChangeStatus::UNCHANGED;
2449 bool IgnoreSubsumingPositions) {
2451 AttrKinds.
push_back(Attribute::NonNull);
2454 AttrKinds.
push_back(Attribute::Dereferenceable);
2455 if (
A.hasAttr(IRP, AttrKinds, IgnoreSubsumingPositions, Attribute::NonNull))
2462 if (!Fn->isDeclaration()) {
2472 bool UsedAssumedInformation =
false;
2473 if (!
A.checkForAllInstructions(
2475 Worklist.push_back({*cast<ReturnInst>(I).getReturnValue(), &I});
2479 UsedAssumedInformation,
false,
true))
2491 Attribute::NonNull)});
2496static int64_t getKnownNonNullAndDerefBytesForUse(
2497 Attributor &
A,
const AbstractAttribute &QueryingAA,
Value &AssociatedValue,
2498 const Use *U,
const Instruction *
I,
bool &IsNonNull,
bool &TrackUse) {
2501 const Value *UseV =
U->get();
2522 const DataLayout &
DL =
A.getInfoCache().getDL();
2526 U, {Attribute::NonNull, Attribute::Dereferenceable})) {
2543 bool IsKnownNonNull;
2546 IsNonNull |= IsKnownNonNull;
2549 return DerefAA ? DerefAA->getKnownDereferenceableBytes() : 0;
2553 if (!Loc || Loc->Ptr != UseV || !Loc->Size.isPrecise() ||
2554 Loc->Size.isScalable() ||
I->isVolatile())
2560 if (
Base &&
Base == &AssociatedValue) {
2561 int64_t DerefBytes = Loc->Size.getValue() +
Offset;
2563 return std::max(int64_t(0), DerefBytes);
2570 int64_t DerefBytes = Loc->Size.getValue();
2572 return std::max(int64_t(0), DerefBytes);
2578struct AANonNullImpl : AANonNull {
2579 AANonNullImpl(
const IRPosition &IRP, Attributor &
A) : AANonNull(IRP,
A) {}
2583 Value &
V = *getAssociatedValue().stripPointerCasts();
2585 indicatePessimisticFixpoint();
2589 if (Instruction *CtxI = getCtxI())
2590 followUsesInMBEC(*
this,
A, getState(), *CtxI);
2594 bool followUseInMBEC(Attributor &
A,
const Use *U,
const Instruction *
I,
2595 AANonNull::StateType &State) {
2596 bool IsNonNull =
false;
2597 bool TrackUse =
false;
2598 getKnownNonNullAndDerefBytesForUse(
A, *
this, getAssociatedValue(), U,
I,
2599 IsNonNull, TrackUse);
2600 State.setKnown(IsNonNull);
2605 const std::string getAsStr(Attributor *
A)
const override {
2606 return getAssumed() ?
"nonnull" :
"may-null";
2611struct AANonNullFloating :
public AANonNullImpl {
2612 AANonNullFloating(
const IRPosition &IRP, Attributor &
A)
2613 : AANonNullImpl(IRP,
A) {}
2617 auto CheckIRP = [&](
const IRPosition &IRP) {
2618 bool IsKnownNonNull;
2620 A, *
this, IRP, DepClassTy::OPTIONAL, IsKnownNonNull);
2624 bool UsedAssumedInformation =
false;
2625 Value *AssociatedValue = &getAssociatedValue();
2627 if (!
A.getAssumedSimplifiedValues(getIRPosition(), *
this,
Values,
2632 Values.size() != 1 ||
Values.front().getValue() != AssociatedValue;
2638 return AA::hasAssumedIRAttr<Attribute::NonNull>(
2639 A, this, IRPosition::value(*Op), DepClassTy::OPTIONAL,
2642 return ChangeStatus::UNCHANGED;
2646 DepClassTy::OPTIONAL, IsKnown) &&
2649 DepClassTy::OPTIONAL, IsKnown))
2650 return ChangeStatus::UNCHANGED;
2657 if (AVIRP == getIRPosition() || !CheckIRP(AVIRP))
2658 return indicatePessimisticFixpoint();
2659 return ChangeStatus::UNCHANGED;
2662 for (
const auto &VAC :
Values)
2664 return indicatePessimisticFixpoint();
2666 return ChangeStatus::UNCHANGED;
2674struct AANonNullReturned final
2675 : AAReturnedFromReturnedValues<AANonNull, AANonNull, AANonNull::StateType,
2676 false, AANonNull::IRAttributeKind, false> {
2677 AANonNullReturned(
const IRPosition &IRP, Attributor &
A)
2678 : AAReturnedFromReturnedValues<AANonNull, AANonNull, AANonNull::StateType,
2683 const std::string getAsStr(Attributor *
A)
const override {
2684 return getAssumed() ?
"nonnull" :
"may-null";
2692struct AANonNullArgument final
2693 : AAArgumentFromCallSiteArguments<AANonNull, AANonNullImpl> {
2694 AANonNullArgument(
const IRPosition &IRP, Attributor &
A)
2695 : AAArgumentFromCallSiteArguments<AANonNull, AANonNullImpl>(IRP,
A) {}
2701struct AANonNullCallSiteArgument final : AANonNullFloating {
2702 AANonNullCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
2703 : AANonNullFloating(IRP,
A) {}
2710struct AANonNullCallSiteReturned final
2711 : AACalleeToCallSite<AANonNull, AANonNullImpl> {
2712 AANonNullCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
2713 : AACalleeToCallSite<AANonNull, AANonNullImpl>(IRP,
A) {}
2722struct AAMustProgressImpl :
public AAMustProgress {
2723 AAMustProgressImpl(
const IRPosition &IRP, Attributor &
A)
2724 : AAMustProgress(IRP,
A) {}
2730 A,
nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));
2735 const std::string getAsStr(Attributor *
A)
const override {
2736 return getAssumed() ?
"mustprogress" :
"may-not-progress";
2740struct AAMustProgressFunction final : AAMustProgressImpl {
2741 AAMustProgressFunction(
const IRPosition &IRP, Attributor &
A)
2742 : AAMustProgressImpl(IRP,
A) {}
2748 A,
this, getIRPosition(), DepClassTy::OPTIONAL, IsKnown)) {
2750 return indicateOptimisticFixpoint();
2751 return ChangeStatus::UNCHANGED;
2754 auto CheckForMustProgress = [&](AbstractCallSite ACS) {
2756 bool IsKnownMustProgress;
2758 A,
this, IPos, DepClassTy::REQUIRED, IsKnownMustProgress,
2762 bool AllCallSitesKnown =
true;
2763 if (!
A.checkForAllCallSites(CheckForMustProgress, *
this,
2766 return indicatePessimisticFixpoint();
2768 return ChangeStatus::UNCHANGED;
2772 void trackStatistics()
const override {
2778struct AAMustProgressCallSite final : AAMustProgressImpl {
2779 AAMustProgressCallSite(
const IRPosition &IRP, Attributor &
A)
2780 : AAMustProgressImpl(IRP,
A) {}
2789 bool IsKnownMustProgress;
2791 A,
this, FnPos, DepClassTy::REQUIRED, IsKnownMustProgress))
2792 return indicatePessimisticFixpoint();
2793 return ChangeStatus::UNCHANGED;
2797 void trackStatistics()
const override {
2806struct AANoRecurseImpl :
public AANoRecurse {
2807 AANoRecurseImpl(
const IRPosition &IRP, Attributor &
A) : AANoRecurse(IRP,
A) {}
2813 A,
nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));
2818 const std::string getAsStr(Attributor *
A)
const override {
2819 return getAssumed() ?
"norecurse" :
"may-recurse";
2823struct AANoRecurseFunction final : AANoRecurseImpl {
2824 AANoRecurseFunction(
const IRPosition &IRP, Attributor &
A)
2825 : AANoRecurseImpl(IRP,
A) {}
2831 auto CallSitePred = [&](AbstractCallSite ACS) {
2832 bool IsKnownNoRecurse;
2836 DepClassTy::NONE, IsKnownNoRecurse))
2838 return IsKnownNoRecurse;
2840 bool UsedAssumedInformation =
false;
2841 if (
A.checkForAllCallSites(CallSitePred, *
this,
true,
2842 UsedAssumedInformation)) {
2848 if (!UsedAssumedInformation)
2849 indicateOptimisticFixpoint();
2850 return ChangeStatus::UNCHANGED;
2853 const AAInterFnReachability *EdgeReachability =
2854 A.getAAFor<AAInterFnReachability>(*
this, getIRPosition(),
2855 DepClassTy::REQUIRED);
2856 if (EdgeReachability && EdgeReachability->
canReach(
A, *getAnchorScope()))
2857 return indicatePessimisticFixpoint();
2858 return ChangeStatus::UNCHANGED;
2865struct AANoRecurseCallSite final
2866 : AACalleeToCallSite<AANoRecurse, AANoRecurseImpl> {
2867 AANoRecurseCallSite(
const IRPosition &IRP, Attributor &
A)
2868 : AACalleeToCallSite<AANoRecurse, AANoRecurseImpl>(IRP,
A) {}
2878struct AANonConvergentImpl :
public AANonConvergent {
2879 AANonConvergentImpl(
const IRPosition &IRP, Attributor &
A)
2880 : AANonConvergent(IRP,
A) {}
2883 const std::string getAsStr(Attributor *
A)
const override {
2884 return getAssumed() ?
"non-convergent" :
"may-be-convergent";
2888struct AANonConvergentFunction final : AANonConvergentImpl {
2889 AANonConvergentFunction(
const IRPosition &IRP, Attributor &
A)
2890 : AANonConvergentImpl(IRP,
A) {}
2896 auto CalleeIsNotConvergent = [&](
Instruction &Inst) {
2899 if (!Callee ||
Callee->isIntrinsic()) {
2902 if (
Callee->isDeclaration()) {
2903 return !
Callee->hasFnAttribute(Attribute::Convergent);
2905 const auto *ConvergentAA =
A.getAAFor<AANonConvergent>(
2907 return ConvergentAA && ConvergentAA->isAssumedNotConvergent();
2910 bool UsedAssumedInformation =
false;
2911 if (!
A.checkForAllCallLikeInstructions(CalleeIsNotConvergent, *
this,
2912 UsedAssumedInformation)) {
2913 return indicatePessimisticFixpoint();
2915 return ChangeStatus::UNCHANGED;
2919 if (isKnownNotConvergent() &&
2920 A.hasAttr(getIRPosition(), Attribute::Convergent)) {
2921 A.removeAttrs(getIRPosition(), {Attribute::Convergent});
2922 return ChangeStatus::CHANGED;
2924 return ChangeStatus::UNCHANGED;
2934struct AAUndefinedBehaviorImpl :
public AAUndefinedBehavior {
2935 AAUndefinedBehaviorImpl(
const IRPosition &IRP, Attributor &
A)
2936 : AAUndefinedBehavior(IRP,
A) {}
2942 UndefBranchCondition,
2944 NullReturnViolatesNonNull,
2946 NullArgViolatesNonNull,
2950 std::optional<unsigned> ArgNo;
2952 UBInfo(Kind K) :
K(
K), ArgNo(std::nullopt) {}
2954 UBInfo(Kind K, std::optional<unsigned> ArgNo) :
K(
K), ArgNo(ArgNo) {}
2960 const size_t UBPrevSize = KnownUBInsts.size();
2961 const size_t NoUBPrevSize = AssumedNoUBInsts.size();
2969 if (AssumedNoUBInsts.count(&
I) || KnownUBInsts.count(&
I))
2978 "Expected pointer operand of memory accessing instruction");
2982 std::optional<Value *> SimplifiedPtrOp =
2983 stopOnUndefOrAssumed(
A, PtrOp, &
I, UBInfo::UndefPtrAccess);
2984 if (!SimplifiedPtrOp || !*SimplifiedPtrOp)
2986 const Value *PtrOpVal = *SimplifiedPtrOp;
2992 AssumedNoUBInsts.insert(&
I);
3004 AssumedNoUBInsts.insert(&
I);
3006 KnownUBInsts.try_emplace(&
I, UBInfo::NullPtrAccess);
3015 if (AssumedNoUBInsts.count(&
I) || KnownUBInsts.count(&
I))
3023 std::optional<Value *> SimplifiedCond = stopOnUndefOrAssumed(
3024 A, BrInst->getCondition(), BrInst, UBInfo::UndefBranchCondition);
3025 if (!SimplifiedCond || !*SimplifiedCond)
3027 AssumedNoUBInsts.insert(&
I);
3035 if (AssumedNoUBInsts.count(&
I) || KnownUBInsts.count(&
I))
3044 for (
unsigned idx = 0; idx < CB.
arg_size(); idx++) {
3050 if (idx >=
Callee->arg_size())
3062 bool IsKnownNoUndef;
3064 A,
this, CalleeArgumentIRP, DepClassTy::NONE, IsKnownNoUndef);
3065 if (!IsKnownNoUndef)
3067 bool UsedAssumedInformation =
false;
3068 std::optional<Value *> SimplifiedVal =
3071 if (UsedAssumedInformation)
3073 if (SimplifiedVal && !*SimplifiedVal)
3076 KnownUBInsts.try_emplace(&
I, UBInfo(UBInfo::UndefCallArgument, idx));
3082 bool IsKnownNonNull;
3084 A,
this, CalleeArgumentIRP, DepClassTy::NONE, IsKnownNonNull);
3086 KnownUBInsts.try_emplace(&
I,
3087 UBInfo(UBInfo::NullArgViolatesNonNull, idx));
3096 std::optional<Value *> SimplifiedRetValue = stopOnUndefOrAssumed(
3097 A, RI.getReturnValue(), &
I, UBInfo::UndefReturnValue);
3098 if (!SimplifiedRetValue || !*SimplifiedRetValue)
3116 bool IsKnownNonNull;
3121 KnownUBInsts.try_emplace(&
I, UBInfo::NullReturnViolatesNonNull);
3127 bool UsedAssumedInformation =
false;
3128 A.checkForAllInstructions(InspectMemAccessInstForUB, *
this,
3129 {Instruction::Load, Instruction::Store,
3130 Instruction::AtomicCmpXchg,
3131 Instruction::AtomicRMW},
3132 UsedAssumedInformation,
3134 A.checkForAllInstructions(InspectBrInstForUB, *
this, {Instruction::CondBr},
3135 UsedAssumedInformation,
3137 A.checkForAllCallLikeInstructions(InspectCallSiteForUB, *
this,
3138 UsedAssumedInformation);
3142 if (!getAnchorScope()->getReturnType()->isVoidTy()) {
3144 if (!
A.isAssumedDead(ReturnIRP,
this,
nullptr, UsedAssumedInformation)) {
3145 bool IsKnownNoUndef;
3147 A,
this, ReturnIRP, DepClassTy::NONE, IsKnownNoUndef);
3149 A.checkForAllInstructions(InspectReturnInstForUB, *
this,
3150 {Instruction::Ret}, UsedAssumedInformation,
3155 if (NoUBPrevSize != AssumedNoUBInsts.size() ||
3156 UBPrevSize != KnownUBInsts.size())
3157 return ChangeStatus::CHANGED;
3158 return ChangeStatus::UNCHANGED;
3161 bool isKnownToCauseUB(Instruction *
I)
const override {
3162 return KnownUBInsts.count(
I);
3165 bool isAssumedToCauseUB(Instruction *
I)
const override {
3172 switch (
I->getOpcode()) {
3173 case Instruction::Load:
3174 case Instruction::Store:
3175 case Instruction::AtomicCmpXchg:
3176 case Instruction::AtomicRMW:
3177 case Instruction::CondBr:
3178 return !AssumedNoUBInsts.count(
I);
3187 static void emitUBRemark(Attributor &
A, Instruction *
I,
const UBInfo &Info) {
3188 auto Remark = [&](OptimizationRemark
OR) {
3190 case UBInfo::NullPtrAccess:
3191 case UBInfo::UndefPtrAccess: {
3192 return OR <<
"Memory access through a pointer known to be "
3195 <<
" is undefined behavior; replacing with 'unreachable'.";
3197 case UBInfo::UndefBranchCondition:
3198 return OR <<
"Branch condition known to be "
3200 <<
" is undefined behavior; replacing with 'unreachable'.";
3201 case UBInfo::UndefReturnValue:
3202 case UBInfo::NullReturnViolatesNonNull:
3203 return OR <<
"Value returned known to be "
3206 <<
" is undefined behavior; replacing with 'unreachable'.";
3207 case UBInfo::UndefCallArgument:
3208 case UBInfo::NullArgViolatesNonNull: {
3209 bool IsUndef =
Info.K == UBInfo::UndefCallArgument;
3212 <<
" passed to parameter of ";
3217 return OR <<
" known to be "
3218 <<
ore::NV(
"Argument", IsUndef ?
"undef" :
"null")
3219 <<
" is undefined behavior; replacing with 'unreachable'.";
3224 A.emitRemark<OptimizationRemark>(
I,
"UndefinedBehavior",
Remark);
3228 if (KnownUBInsts.empty())
3229 return ChangeStatus::UNCHANGED;
3230 for (
const auto &[
I, Info] : KnownUBInsts) {
3231 emitUBRemark(
A,
I, Info);
3232 A.changeToUnreachableAfterManifest(
I);
3234 return ChangeStatus::CHANGED;
3238 const std::string getAsStr(Attributor *
A)
const override {
3239 return getAssumed() ?
"undefined-behavior" :
"no-ub";
3268 MapVector<Instruction *, UBInfo> KnownUBInsts;
3272 SmallPtrSet<Instruction *, 8> AssumedNoUBInsts;
3283 std::optional<Value *> stopOnUndefOrAssumed(Attributor &
A,
Value *V,
3284 Instruction *
I, UBInfo::Kind K) {
3285 bool UsedAssumedInformation =
false;
3286 std::optional<Value *> SimplifiedV =
3289 if (!UsedAssumedInformation) {
3294 KnownUBInsts.try_emplace(
I, K);
3295 return std::nullopt;
3302 KnownUBInsts.try_emplace(
I, K);
3303 return std::nullopt;
3309struct AAUndefinedBehaviorFunction final : AAUndefinedBehaviorImpl {
3310 AAUndefinedBehaviorFunction(
const IRPosition &IRP, Attributor &
A)
3311 : AAUndefinedBehaviorImpl(IRP,
A) {}
3314 void trackStatistics()
const override {
3315 STATS_DECL(UndefinedBehaviorInstruction, Instruction,
3316 "Number of instructions known to have UB");
3318 KnownUBInsts.size();
3329static bool mayContainUnboundedCycle(
Function &
F, Attributor &
A) {
3330 ScalarEvolution *SE =
3331 A.getInfoCache().getAnalysisResultForFunction<ScalarEvolutionAnalysis>(
F);
3332 LoopInfo *LI =
A.getInfoCache().getAnalysisResultForFunction<LoopAnalysis>(
F);
3338 for (scc_iterator<Function *> SCCI =
scc_begin(&
F); !SCCI.isAtEnd(); ++SCCI)
3339 if (SCCI.hasCycle())
3349 for (
auto *L : LI->getLoopsInPreorder()) {
3356struct AAWillReturnImpl :
public AAWillReturn {
3357 AAWillReturnImpl(
const IRPosition &IRP, Attributor &
A)
3358 : AAWillReturn(IRP,
A) {}
3364 A,
nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));
3369 bool isImpliedByMustprogressAndReadonly(Attributor &
A,
bool KnownOnly) {
3370 if (!
A.hasAttr(getIRPosition(), {Attribute::MustProgress}))
3375 return IsKnown || !KnownOnly;
3381 if (isImpliedByMustprogressAndReadonly(
A,
false))
3382 return ChangeStatus::UNCHANGED;
3388 A,
this, IPos, DepClassTy::REQUIRED, IsKnown)) {
3394 bool IsKnownNoRecurse;
3396 A,
this, IPos, DepClassTy::REQUIRED, IsKnownNoRecurse);
3399 bool UsedAssumedInformation =
false;
3400 if (!
A.checkForAllCallLikeInstructions(CheckForWillReturn, *
this,
3401 UsedAssumedInformation))
3402 return indicatePessimisticFixpoint();
3406 return !
I.isVolatile();
3408 if (!
A.checkForAllInstructions(CheckForVolatile, *
this,
3409 {Instruction::Load, Instruction::Store,
3410 Instruction::AtomicCmpXchg,
3411 Instruction::AtomicRMW},
3412 UsedAssumedInformation))
3413 return indicatePessimisticFixpoint();
3415 return ChangeStatus::UNCHANGED;
3419 const std::string getAsStr(Attributor *
A)
const override {
3420 return getAssumed() ?
"willreturn" :
"may-noreturn";
3424struct AAWillReturnFunction final : AAWillReturnImpl {
3425 AAWillReturnFunction(
const IRPosition &IRP, Attributor &
A)
3426 : AAWillReturnImpl(IRP,
A) {}
3430 AAWillReturnImpl::initialize(
A);
3433 assert(
F &&
"Did expect an anchor function");
3434 if (
F->isDeclaration() || mayContainUnboundedCycle(*
F,
A))
3435 indicatePessimisticFixpoint();
3443struct AAWillReturnCallSite final
3444 : AACalleeToCallSite<AAWillReturn, AAWillReturnImpl> {
3445 AAWillReturnCallSite(
const IRPosition &IRP, Attributor &
A)
3446 : AACalleeToCallSite<AAWillReturn, AAWillReturnImpl>(IRP,
A) {}
3450 if (isImpliedByMustprogressAndReadonly(
A,
false))
3451 return ChangeStatus::UNCHANGED;
3453 return AACalleeToCallSite::updateImpl(
A);
3475 const ToTy *
To =
nullptr;
3502 if (!ES || ES->
empty()) {
3503 ExclusionSet = nullptr;
3504 }
else if (MakeUnique) {
3505 ExclusionSet =
A.getInfoCache().getOrCreateUniqueBlockExecutionSet(ES);
3523 if (!PairDMI::isEqual({LHS->From, LHS->To}, {RHS->From, RHS->To}))
3525 return InstSetDMI::isEqual(LHS->ExclusionSet, RHS->ExclusionSet);
3533template <
typename BaseTy,
typename ToTy>
3534struct CachedReachabilityAA :
public BaseTy {
3535 using RQITy = ReachabilityQueryInfo<ToTy>;
3537 CachedReachabilityAA(
const IRPosition &IRP, Attributor &
A) : BaseTy(IRP,
A) {}
3540 bool isQueryAA()
const override {
return true; }
3545 for (
unsigned u = 0, e = QueryVector.size(); u < e; ++u) {
3546 RQITy *RQI = QueryVector[
u];
3547 if (RQI->Result == RQITy::Reachable::No &&
3549 Changed = ChangeStatus::CHANGED;
3555 bool IsTemporaryRQI) = 0;
3557 bool rememberResult(Attributor &
A,
typename RQITy::Reachable Result,
3558 RQITy &RQI,
bool UsedExclusionSet,
bool IsTemporaryRQI) {
3563 QueryCache.erase(&RQI);
3569 if (Result == RQITy::Reachable::Yes || !UsedExclusionSet) {
3570 RQITy PlainRQI(RQI.From, RQI.To);
3571 if (!QueryCache.count(&PlainRQI)) {
3572 RQITy *RQIPtr =
new (
A.Allocator) RQITy(RQI.From, RQI.To);
3574 QueryVector.push_back(RQIPtr);
3575 QueryCache.insert(RQIPtr);
3580 if (IsTemporaryRQI && Result != RQITy::Reachable::Yes && UsedExclusionSet) {
3581 assert((!RQI.ExclusionSet || !RQI.ExclusionSet->empty()) &&
3582 "Did not expect empty set!");
3583 RQITy *RQIPtr =
new (
A.Allocator)
3584 RQITy(
A, *RQI.From, *RQI.To, RQI.ExclusionSet,
true);
3585 assert(RQIPtr->Result == RQITy::Reachable::No &&
"Already reachable?");
3587 assert(!QueryCache.count(RQIPtr));
3588 QueryVector.push_back(RQIPtr);
3589 QueryCache.insert(RQIPtr);
3592 if (Result == RQITy::Reachable::No && IsTemporaryRQI)
3593 A.registerForUpdate(*
this);
3594 return Result == RQITy::Reachable::Yes;
3597 const std::string getAsStr(Attributor *
A)
const override {
3599 return "#queries(" + std::to_string(QueryVector.size()) +
")";
3602 bool checkQueryCache(Attributor &
A, RQITy &StackRQI,
3603 typename RQITy::Reachable &Result) {
3604 if (!this->getState().isValidState()) {
3605 Result = RQITy::Reachable::Yes;
3611 if (StackRQI.ExclusionSet) {
3612 RQITy PlainRQI(StackRQI.From, StackRQI.To);
3613 auto It = QueryCache.find(&PlainRQI);
3614 if (It != QueryCache.end() && (*It)->Result == RQITy::Reachable::No) {
3615 Result = RQITy::Reachable::No;
3620 auto It = QueryCache.find(&StackRQI);
3621 if (It != QueryCache.end()) {
3628 QueryCache.insert(&StackRQI);
3634 DenseSet<RQITy *> QueryCache;
3637struct AAIntraFnReachabilityFunction final
3638 :
public CachedReachabilityAA<AAIntraFnReachability, Instruction> {
3639 using Base = CachedReachabilityAA<AAIntraFnReachability, Instruction>;
3640 AAIntraFnReachabilityFunction(
const IRPosition &IRP, Attributor &
A)
3642 DT =
A.getInfoCache().getAnalysisResultForFunction<DominatorTreeAnalysis>(
3646 bool isAssumedReachable(
3647 Attributor &
A,
const Instruction &From,
const Instruction &To,
3649 auto *NonConstThis =
const_cast<AAIntraFnReachabilityFunction *
>(
this);
3653 RQITy StackRQI(
A, From, To, ExclusionSet,
false);
3655 if (!NonConstThis->checkQueryCache(
A, StackRQI, Result))
3656 return NonConstThis->isReachableImpl(
A, StackRQI,
3658 return Result == RQITy::Reachable::Yes;
3665 A.getAAFor<AAIsDead>(*
this, getIRPosition(), DepClassTy::OPTIONAL);
3668 [&](
const auto &DeadEdge) {
3669 return LivenessAA->isEdgeDead(DeadEdge.first,
3673 return LivenessAA->isAssumedDead(BB);
3675 return ChangeStatus::UNCHANGED;
3679 return Base::updateImpl(
A);
3683 bool IsTemporaryRQI)
override {
3685 bool UsedExclusionSet =
false;
3690 while (IP && IP != &To) {
3691 if (ExclusionSet && IP != Origin && ExclusionSet->
count(IP)) {
3692 UsedExclusionSet =
true;
3700 const BasicBlock *FromBB = RQI.From->getParent();
3701 const BasicBlock *ToBB = RQI.To->getParent();
3703 "Not an intra-procedural query!");
3707 if (FromBB == ToBB &&
3708 WillReachInBlock(*RQI.From, *RQI.To, RQI.ExclusionSet))
3709 return rememberResult(
A, RQITy::Reachable::Yes, RQI, UsedExclusionSet,
3714 if (!WillReachInBlock(ToBB->
front(), *RQI.To, RQI.ExclusionSet))
3715 return rememberResult(
A, RQITy::Reachable::No, RQI, UsedExclusionSet,
3719 SmallPtrSet<const BasicBlock *, 16> ExclusionBlocks;
3720 if (RQI.ExclusionSet)
3721 for (
auto *
I : *RQI.ExclusionSet)
3722 if (
I->getFunction() == Fn)
3723 ExclusionBlocks.
insert(
I->getParent());
3726 if (ExclusionBlocks.
count(FromBB) &&
3729 return rememberResult(
A, RQITy::Reachable::No, RQI,
true, IsTemporaryRQI);
3732 A.getAAFor<AAIsDead>(*
this, getIRPosition(), DepClassTy::OPTIONAL);
3733 if (LivenessAA && LivenessAA->isAssumedDead(ToBB)) {
3734 DeadBlocks.insert(ToBB);
3735 return rememberResult(
A, RQITy::Reachable::No, RQI, UsedExclusionSet,
3739 SmallPtrSet<const BasicBlock *, 16> Visited;
3743 DenseSet<std::pair<const BasicBlock *, const BasicBlock *>> LocalDeadEdges;
3744 while (!Worklist.
empty()) {
3746 if (!Visited.
insert(BB).second)
3748 for (
const BasicBlock *SuccBB :
successors(BB)) {
3749 if (LivenessAA && LivenessAA->isEdgeDead(BB, SuccBB)) {
3750 LocalDeadEdges.
insert({BB, SuccBB});
3755 return rememberResult(
A, RQITy::Reachable::Yes, RQI, UsedExclusionSet,
3758 return rememberResult(
A, RQITy::Reachable::Yes, RQI, UsedExclusionSet,
3761 if (ExclusionBlocks.
count(SuccBB)) {
3762 UsedExclusionSet =
true;
3769 DeadEdges.insert_range(LocalDeadEdges);
3770 return rememberResult(
A, RQITy::Reachable::No, RQI, UsedExclusionSet,
3775 void trackStatistics()
const override {}
3780 DenseSet<const BasicBlock *> DeadBlocks;
3784 DenseSet<std::pair<const BasicBlock *, const BasicBlock *>> DeadEdges;
3787 const DominatorTree *DT =
nullptr;
3795 bool IgnoreSubsumingPositions) {
3796 assert(ImpliedAttributeKind == Attribute::NoAlias &&
3797 "Unexpected attribute kind");
3803 IgnoreSubsumingPositions =
true;
3814 if (
A.hasAttr(IRP, {Attribute::ByVal, Attribute::NoAlias},
3815 IgnoreSubsumingPositions, Attribute::NoAlias))
3825 "Noalias is a pointer attribute");
3828 const std::string getAsStr(
Attributor *
A)
const override {
3829 return getAssumed() ?
"noalias" :
"may-alias";
3834struct AANoAliasFloating final : AANoAliasImpl {
3835 AANoAliasFloating(
const IRPosition &IRP, Attributor &
A)
3836 : AANoAliasImpl(IRP,
A) {}
3841 return indicatePessimisticFixpoint();
3845 void trackStatistics()
const override {
3851struct AANoAliasArgument final
3852 : AAArgumentFromCallSiteArguments<AANoAlias, AANoAliasImpl> {
3853 using Base = AAArgumentFromCallSiteArguments<AANoAlias, AANoAliasImpl>;
3854 AANoAliasArgument(
const IRPosition &IRP, Attributor &
A) :
Base(IRP,
A) {}
3867 DepClassTy::OPTIONAL, IsKnownNoSycn))
3868 return Base::updateImpl(
A);
3873 return Base::updateImpl(
A);
3877 bool UsedAssumedInformation =
false;
3878 if (
A.checkForAllCallSites(
3879 [](AbstractCallSite ACS) { return !ACS.isCallbackCall(); }, *
this,
3880 true, UsedAssumedInformation))
3881 return Base::updateImpl(
A);
3889 return indicatePessimisticFixpoint();
3896struct AANoAliasCallSiteArgument final : AANoAliasImpl {
3897 AANoAliasCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
3898 : AANoAliasImpl(IRP,
A) {}
3902 bool mayAliasWithArgument(Attributor &
A, AAResults *&AAR,
3903 const AAMemoryBehavior &MemBehaviorAA,
3904 const CallBase &CB,
unsigned OtherArgNo) {
3906 if (this->getCallSiteArgNo() == (
int)OtherArgNo)
3914 auto *CBArgMemBehaviorAA =
A.getAAFor<AAMemoryBehavior>(
3918 if (CBArgMemBehaviorAA && CBArgMemBehaviorAA->isAssumedReadNone()) {
3919 A.recordDependence(*CBArgMemBehaviorAA, *
this, DepClassTy::OPTIONAL);
3926 if (CBArgMemBehaviorAA && CBArgMemBehaviorAA->isAssumedReadOnly() &&
3928 A.recordDependence(MemBehaviorAA, *
this, DepClassTy::OPTIONAL);
3929 A.recordDependence(*CBArgMemBehaviorAA, *
this, DepClassTy::OPTIONAL);
3935 AAR =
A.getInfoCache().getAnalysisResultForFunction<AAManager>(
3939 bool IsAliasing = !AAR || !AAR->
isNoAlias(&getAssociatedValue(), ArgOp);
3941 "callsite arguments: "
3942 << getAssociatedValue() <<
" " << *ArgOp <<
" => "
3943 << (IsAliasing ?
"" :
"no-") <<
"alias \n");
3948 bool isKnownNoAliasDueToNoAliasPreservation(
3949 Attributor &
A, AAResults *&AAR,
const AAMemoryBehavior &MemBehaviorAA) {
3962 auto UsePred = [&](
const Use &
U,
bool &Follow) ->
bool {
3978 bool IsKnownNoCapture;
3981 DepClassTy::OPTIONAL, IsKnownNoCapture))
3987 A, *UserI, *getCtxI(), *
this,
nullptr,
3988 [ScopeFn](
const Function &Fn) {
return &Fn != ScopeFn; }))
4003 LLVM_DEBUG(
dbgs() <<
"[AANoAliasCSArg] Unknown user: " << *UserI <<
"\n");
4007 bool IsKnownNoCapture;
4008 const AANoCapture *NoCaptureAA =
nullptr;
4010 A,
this, VIRP, DepClassTy::NONE, IsKnownNoCapture,
false, &NoCaptureAA);
4011 if (!IsAssumedNoCapture &&
4013 if (!
A.checkForAllUses(UsePred, *
this, getAssociatedValue())) {
4015 dbgs() <<
"[AANoAliasCSArg] " << getAssociatedValue()
4016 <<
" cannot be noalias as it is potentially captured\n");
4021 A.recordDependence(*NoCaptureAA, *
this, DepClassTy::OPTIONAL);
4027 for (
unsigned OtherArgNo = 0; OtherArgNo < CB.
arg_size(); OtherArgNo++)
4028 if (mayAliasWithArgument(
A, AAR, MemBehaviorAA, CB, OtherArgNo))
4038 auto *MemBehaviorAA =
4039 A.getAAFor<AAMemoryBehavior>(*
this, getIRPosition(), DepClassTy::NONE);
4041 A.recordDependence(*MemBehaviorAA, *
this, DepClassTy::OPTIONAL);
4042 return ChangeStatus::UNCHANGED;
4045 bool IsKnownNoAlias;
4048 A,
this, VIRP, DepClassTy::REQUIRED, IsKnownNoAlias)) {
4050 <<
" is not no-alias at the definition\n");
4051 return indicatePessimisticFixpoint();
4054 AAResults *AAR =
nullptr;
4055 if (MemBehaviorAA &&
4056 isKnownNoAliasDueToNoAliasPreservation(
A, AAR, *MemBehaviorAA)) {
4058 dbgs() <<
"[AANoAlias] No-Alias deduced via no-alias preservation\n");
4059 return ChangeStatus::UNCHANGED;
4062 return indicatePessimisticFixpoint();
4070struct AANoAliasReturned final : AANoAliasImpl {
4071 AANoAliasReturned(
const IRPosition &IRP, Attributor &
A)
4072 : AANoAliasImpl(IRP,
A) {}
4077 auto CheckReturnValue = [&](
Value &RV) ->
bool {
4088 bool IsKnownNoAlias;
4090 A,
this, RVPos, DepClassTy::REQUIRED, IsKnownNoAlias))
4093 bool IsKnownNoCapture;
4094 const AANoCapture *NoCaptureAA =
nullptr;
4096 A,
this, RVPos, DepClassTy::REQUIRED, IsKnownNoCapture,
false,
4098 return IsAssumedNoCapture ||
4102 if (!
A.checkForAllReturnedValues(CheckReturnValue, *
this))
4103 return indicatePessimisticFixpoint();
4105 return ChangeStatus::UNCHANGED;
4113struct AANoAliasCallSiteReturned final
4114 : AACalleeToCallSite<AANoAlias, AANoAliasImpl> {
4115 AANoAliasCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
4116 : AACalleeToCallSite<AANoAlias, AANoAliasImpl>(IRP,
A) {}
4126struct AAIsDeadValueImpl :
public AAIsDead {
4127 AAIsDeadValueImpl(
const IRPosition &IRP, Attributor &
A) : AAIsDead(IRP,
A) {}
4130 bool isAssumedDead()
const override {
return isAssumed(IS_DEAD); }
4133 bool isKnownDead()
const override {
return isKnown(IS_DEAD); }
4136 bool isAssumedDead(
const BasicBlock *BB)
const override {
return false; }
4139 bool isKnownDead(
const BasicBlock *BB)
const override {
return false; }
4142 bool isAssumedDead(
const Instruction *
I)
const override {
4143 return I == getCtxI() && isAssumedDead();
4147 bool isKnownDead(
const Instruction *
I)
const override {
4148 return isAssumedDead(
I) && isKnownDead();
4152 const std::string getAsStr(Attributor *
A)
const override {
4153 return isAssumedDead() ?
"assumed-dead" :
"assumed-live";
4157 bool areAllUsesAssumedDead(Attributor &
A,
Value &V) {
4159 if (
V.getType()->isVoidTy() ||
V.use_empty())
4165 if (!
A.isRunOn(*
I->getFunction()))
4167 bool UsedAssumedInformation =
false;
4168 std::optional<Constant *>
C =
4169 A.getAssumedConstant(V, *
this, UsedAssumedInformation);
4174 auto UsePred = [&](
const Use &
U,
bool &Follow) {
return false; };
4179 return A.checkForAllUses(UsePred, *
this, V,
false,
4180 DepClassTy::REQUIRED,
4185 bool isAssumedSideEffectFree(Attributor &
A, Instruction *
I) {
4189 if (!
I->isTerminator() && !
I->mayHaveSideEffects())
4198 bool IsKnownNoUnwind;
4200 A,
this, CallIRP, DepClassTy::OPTIONAL, IsKnownNoUnwind))
4208struct AAIsDeadFloating :
public AAIsDeadValueImpl {
4209 AAIsDeadFloating(
const IRPosition &IRP, Attributor &
A)
4210 : AAIsDeadValueImpl(IRP,
A) {}
4214 AAIsDeadValueImpl::initialize(
A);
4217 indicatePessimisticFixpoint();
4222 if (!isAssumedSideEffectFree(
A,
I)) {
4224 indicatePessimisticFixpoint();
4226 removeAssumedBits(HAS_NO_EFFECT);
4230 bool isDeadFence(Attributor &
A, FenceInst &FI) {
4231 const auto *ExecDomainAA =
A.lookupAAFor<AAExecutionDomain>(
4233 if (!ExecDomainAA || !ExecDomainAA->isNoOpFence(FI))
4235 A.recordDependence(*ExecDomainAA, *
this, DepClassTy::OPTIONAL);
4239 bool isDeadStore(Attributor &
A, StoreInst &SI,
4240 SmallSetVector<Instruction *, 8> *AssumeOnlyInst =
nullptr) {
4242 if (
SI.isVolatile())
4248 bool UsedAssumedInformation =
false;
4249 if (!AssumeOnlyInst) {
4250 PotentialCopies.clear();
4252 UsedAssumedInformation)) {
4255 <<
"[AAIsDead] Could not determine potential copies of store!\n");
4259 LLVM_DEBUG(
dbgs() <<
"[AAIsDead] Store has " << PotentialCopies.size()
4260 <<
" potential copies.\n");
4262 InformationCache &InfoCache =
A.getInfoCache();
4265 UsedAssumedInformation))
4269 auto &UserI = cast<Instruction>(*U.getUser());
4270 if (InfoCache.isOnlyUsedByAssume(UserI)) {
4272 AssumeOnlyInst->insert(&UserI);
4275 return A.isAssumedDead(U,
this,
nullptr, UsedAssumedInformation);
4281 <<
" is assumed live!\n");
4287 const std::string getAsStr(Attributor *
A)
const override {
4291 return "assumed-dead-store";
4294 return "assumed-dead-fence";
4295 return AAIsDeadValueImpl::getAsStr(
A);
4302 if (!isDeadStore(
A, *SI))
4303 return indicatePessimisticFixpoint();
4305 if (!isDeadFence(
A, *FI))
4306 return indicatePessimisticFixpoint();
4308 if (!isAssumedSideEffectFree(
A,
I))
4309 return indicatePessimisticFixpoint();
4310 if (!areAllUsesAssumedDead(
A, getAssociatedValue()))
4311 return indicatePessimisticFixpoint();
4316 bool isRemovableStore()
const override {
4317 return isAssumed(IS_REMOVABLE) &&
isa<StoreInst>(&getAssociatedValue());
4322 Value &
V = getAssociatedValue();
4329 SmallSetVector<Instruction *, 8> AssumeOnlyInst;
4330 bool IsDead = isDeadStore(
A, *SI, &AssumeOnlyInst);
4333 A.deleteAfterManifest(*
I);
4334 for (
size_t i = 0; i < AssumeOnlyInst.
size(); ++i) {
4336 for (
auto *Usr : AOI->
users())
4338 A.deleteAfterManifest(*AOI);
4344 A.deleteAfterManifest(*FI);
4347 if (isAssumedSideEffectFree(
A,
I) && !
I->isTerminator()) {
4348 A.deleteAfterManifest(*
I);
4356 void trackStatistics()
const override {
4362 SmallSetVector<Value *, 4> PotentialCopies;
4365struct AAIsDeadArgument :
public AAIsDeadFloating {
4366 AAIsDeadArgument(
const IRPosition &IRP, Attributor &
A)
4367 : AAIsDeadFloating(IRP,
A) {}
4371 Argument &Arg = *getAssociatedArgument();
4372 if (
A.isValidFunctionSignatureRewrite(Arg, {}))
4373 if (
A.registerFunctionSignatureRewrite(
4377 return ChangeStatus::CHANGED;
4379 return ChangeStatus::UNCHANGED;
4386struct AAIsDeadCallSiteArgument :
public AAIsDeadValueImpl {
4387 AAIsDeadCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
4388 : AAIsDeadValueImpl(IRP,
A) {}
4392 AAIsDeadValueImpl::initialize(
A);
4394 indicatePessimisticFixpoint();
4403 Argument *Arg = getAssociatedArgument();
4405 return indicatePessimisticFixpoint();
4407 auto *ArgAA =
A.getAAFor<AAIsDead>(*
this, ArgPos, DepClassTy::REQUIRED);
4409 return indicatePessimisticFixpoint();
4418 "Expected undef values to be filtered out!");
4420 if (
A.changeUseAfterManifest(U, UV))
4421 return ChangeStatus::CHANGED;
4422 return ChangeStatus::UNCHANGED;
4429struct AAIsDeadCallSiteReturned :
public AAIsDeadFloating {
4430 AAIsDeadCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
4431 : AAIsDeadFloating(IRP,
A) {}
4434 bool isAssumedDead()
const override {
4435 return AAIsDeadFloating::isAssumedDead() && IsAssumedSideEffectFree;
4440 AAIsDeadFloating::initialize(
A);
4442 indicatePessimisticFixpoint();
4447 IsAssumedSideEffectFree = isAssumedSideEffectFree(
A, getCtxI());
4453 if (IsAssumedSideEffectFree && !isAssumedSideEffectFree(
A, getCtxI())) {
4454 IsAssumedSideEffectFree =
false;
4455 Changed = ChangeStatus::CHANGED;
4457 if (!areAllUsesAssumedDead(
A, getAssociatedValue()))
4458 return indicatePessimisticFixpoint();
4463 void trackStatistics()
const override {
4464 if (IsAssumedSideEffectFree)
4471 const std::string getAsStr(Attributor *
A)
const override {
4472 return isAssumedDead()
4474 : (getAssumed() ?
"assumed-dead-users" :
"assumed-live");
4478 bool IsAssumedSideEffectFree =
true;
4481struct AAIsDeadReturned :
public AAIsDeadValueImpl {
4482 AAIsDeadReturned(
const IRPosition &IRP, Attributor &
A)
4483 : AAIsDeadValueImpl(IRP,
A) {}
4488 bool UsedAssumedInformation =
false;
4489 A.checkForAllInstructions([](Instruction &) {
return true; }, *
this,
4490 {Instruction::Ret}, UsedAssumedInformation);
4492 auto PredForCallSite = [&](AbstractCallSite ACS) {
4493 if (ACS.isCallbackCall() || !ACS.getInstruction())
4495 return areAllUsesAssumedDead(
A, *ACS.getInstruction());
4498 if (!
A.checkForAllCallSites(PredForCallSite, *
this,
true,
4499 UsedAssumedInformation))
4500 return indicatePessimisticFixpoint();
4502 return ChangeStatus::UNCHANGED;
4508 bool AnyChange =
false;
4509 UndefValue &UV = *
UndefValue::get(getAssociatedFunction()->getReturnType());
4516 bool UsedAssumedInformation =
false;
4517 A.checkForAllInstructions(RetInstPred, *
this, {Instruction::Ret},
4518 UsedAssumedInformation);
4519 return AnyChange ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
4526struct AAIsDeadFunction :
public AAIsDead {
4527 AAIsDeadFunction(
const IRPosition &IRP, Attributor &
A) : AAIsDead(IRP,
A) {}
4532 assert(
F &&
"Did expect an anchor function");
4533 if (!isAssumedDeadInternalFunction(
A)) {
4534 ToBeExploredFrom.insert(&
F->getEntryBlock().front());
4535 assumeLive(
A,
F->getEntryBlock());
4539 bool isAssumedDeadInternalFunction(Attributor &
A) {
4540 if (!getAnchorScope()->hasLocalLinkage())
4546 if (!
A.shouldUpdateAA<AAIsDead>(getIRPosition()))
4548 bool UsedAssumedInformation =
false;
4549 return A.checkForAllCallSites([](AbstractCallSite) {
return false; }, *
this,
4550 true, UsedAssumedInformation);
4554 const std::string getAsStr(Attributor *
A)
const override {
4555 return "Live[#BB " + std::to_string(AssumedLiveBlocks.size()) +
"/" +
4556 std::to_string(getAnchorScope()->
size()) +
"][#TBEP " +
4557 std::to_string(ToBeExploredFrom.size()) +
"][#KDE " +
4558 std::to_string(KnownDeadEnds.size()) +
"]";
4563 assert(getState().isValidState() &&
4564 "Attempted to manifest an invalid state!");
4569 if (AssumedLiveBlocks.empty()) {
4570 A.deleteAfterManifest(
F);
4571 return ChangeStatus::CHANGED;
4577 bool Invoke2CallAllowed = !mayCatchAsynchronousExceptions(
F);
4579 KnownDeadEnds.set_union(ToBeExploredFrom);
4580 for (
const Instruction *DeadEndI : KnownDeadEnds) {
4584 bool IsKnownNoReturn;
4592 A.registerInvokeWithDeadSuccessor(
const_cast<InvokeInst &
>(*
II));
4594 A.changeToUnreachableAfterManifest(
4595 const_cast<Instruction *
>(DeadEndI->getNextNode()));
4596 HasChanged = ChangeStatus::CHANGED;
4599 STATS_DECL(AAIsDead, BasicBlock,
"Number of dead basic blocks deleted.");
4600 for (BasicBlock &BB :
F)
4601 if (!AssumedLiveBlocks.count(&BB)) {
4602 A.deleteAfterManifest(BB);
4604 HasChanged = ChangeStatus::CHANGED;
4613 bool isEdgeDead(
const BasicBlock *From,
const BasicBlock *To)
const override {
4616 "Used AAIsDead of the wrong function");
4617 return isValidState() && !AssumedLiveEdges.count(std::make_pair(From, To));
4621 void trackStatistics()
const override {}
4624 bool isAssumedDead()
const override {
return false; }
4627 bool isKnownDead()
const override {
return false; }
4630 bool isAssumedDead(
const BasicBlock *BB)
const override {
4632 "BB must be in the same anchor scope function.");
4636 return !AssumedLiveBlocks.count(BB);
4640 bool isKnownDead(
const BasicBlock *BB)
const override {
4641 return getKnown() && isAssumedDead(BB);
4645 bool isAssumedDead(
const Instruction *
I)
const override {
4646 assert(
I->getParent()->getParent() == getAnchorScope() &&
4647 "Instruction must be in the same anchor scope function.");
4654 if (!AssumedLiveBlocks.count(
I->getParent()))
4660 if (KnownDeadEnds.count(PrevI) || ToBeExploredFrom.count(PrevI))
4668 bool isKnownDead(
const Instruction *
I)
const override {
4669 return getKnown() && isAssumedDead(
I);
4674 bool assumeLive(Attributor &
A,
const BasicBlock &BB) {
4675 if (!AssumedLiveBlocks.insert(&BB).second)
4678 if (!
A.isDuringDeduction())
4685 for (
const Instruction &
I : BB)
4688 if (
F->hasLocalLinkage()) {
4690 dbgs() <<
"[AAIsDead] Seeding live internal callee ";
4691 F->printAsOperand(
dbgs(),
false);
4693 BB.getParent()->printAsOperand(
dbgs(),
false);
4696 A.markLiveInternalFunction(*
F);
4703 SmallSetVector<const Instruction *, 8> ToBeExploredFrom;
4706 SmallSetVector<const Instruction *, 8> KnownDeadEnds;
4709 DenseSet<std::pair<const BasicBlock *, const BasicBlock *>> AssumedLiveEdges;
4712 DenseSet<const BasicBlock *> AssumedLiveBlocks;
4716identifyAliveSuccessors(Attributor &
A,
const CallBase &CB,
4717 AbstractAttribute &AA,
4718 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4721 bool IsKnownNoReturn;
4724 return !IsKnownNoReturn;
4733identifyAliveSuccessors(Attributor &
A,
const InvokeInst &
II,
4734 AbstractAttribute &AA,
4735 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4736 bool UsedAssumedInformation =
4742 if (AAIsDeadFunction::mayCatchAsynchronousExceptions(*
II.getFunction())) {
4743 AliveSuccessors.
push_back(&
II.getUnwindDest()->front());
4747 bool IsKnownNoUnwind;
4750 UsedAssumedInformation |= !IsKnownNoUnwind;
4752 AliveSuccessors.
push_back(&
II.getUnwindDest()->front());
4755 return UsedAssumedInformation;
4759identifyAliveSuccessors(Attributor &,
const UncondBrInst &BI,
4760 AbstractAttribute &,
4761 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4767identifyAliveSuccessors(Attributor &
A,
const CondBrInst &BI,
4768 AbstractAttribute &AA,
4769 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4770 bool UsedAssumedInformation =
false;
4771 std::optional<Constant *>
C =
4772 A.getAssumedConstant(*BI.
getCondition(), AA, UsedAssumedInformation);
4782 UsedAssumedInformation =
false;
4784 return UsedAssumedInformation;
4788identifyAliveSuccessors(Attributor &
A,
const SwitchInst &SI,
4789 AbstractAttribute &AA,
4790 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4791 bool UsedAssumedInformation =
false;
4795 UsedAssumedInformation)) {
4797 for (
const BasicBlock *SuccBB :
successors(
SI.getParent()))
4806 return UsedAssumedInformation;
4809 Type &Ty = *
SI.getCondition()->getType();
4810 SmallPtrSet<ConstantInt *, 8>
Constants;
4811 auto CheckForConstantInt = [&](
Value *
V) {
4820 return CheckForConstantInt(VAC.
getValue());
4822 for (
const BasicBlock *SuccBB :
successors(
SI.getParent()))
4824 return UsedAssumedInformation;
4827 unsigned MatchedCases = 0;
4828 for (
const auto &CaseIt :
SI.cases()) {
4829 if (
Constants.count(CaseIt.getCaseValue())) {
4831 AliveSuccessors.
push_back(&CaseIt.getCaseSuccessor()->front());
4838 AliveSuccessors.
push_back(&
SI.getDefaultDest()->front());
4839 return UsedAssumedInformation;
4845 if (AssumedLiveBlocks.empty()) {
4846 if (isAssumedDeadInternalFunction(
A))
4850 ToBeExploredFrom.insert(&
F->getEntryBlock().front());
4851 assumeLive(
A,
F->getEntryBlock());
4855 LLVM_DEBUG(
dbgs() <<
"[AAIsDead] Live [" << AssumedLiveBlocks.size() <<
"/"
4856 << getAnchorScope()->
size() <<
"] BBs and "
4857 << ToBeExploredFrom.size() <<
" exploration points and "
4858 << KnownDeadEnds.size() <<
" known dead ends\n");
4863 ToBeExploredFrom.end());
4864 decltype(ToBeExploredFrom) NewToBeExploredFrom;
4867 while (!Worklist.
empty()) {
4874 I =
I->getNextNode();
4876 AliveSuccessors.
clear();
4878 bool UsedAssumedInformation =
false;
4879 switch (
I->getOpcode()) {
4883 "Expected non-terminators to be handled already!");
4884 for (
const BasicBlock *SuccBB :
successors(
I->getParent()))
4887 case Instruction::Call:
4889 *
this, AliveSuccessors);
4891 case Instruction::Invoke:
4893 *
this, AliveSuccessors);
4895 case Instruction::UncondBr:
4896 UsedAssumedInformation = identifyAliveSuccessors(
4899 case Instruction::CondBr:
4901 *
this, AliveSuccessors);
4903 case Instruction::Switch:
4905 *
this, AliveSuccessors);
4909 if (UsedAssumedInformation) {
4910 NewToBeExploredFrom.insert(
I);
4911 }
else if (AliveSuccessors.
empty() ||
4912 (
I->isTerminator() &&
4913 AliveSuccessors.
size() <
I->getNumSuccessors())) {
4914 if (KnownDeadEnds.insert(
I))
4919 << AliveSuccessors.
size() <<
" UsedAssumedInformation: "
4920 << UsedAssumedInformation <<
"\n");
4922 for (
const Instruction *AliveSuccessor : AliveSuccessors) {
4923 if (!
I->isTerminator()) {
4924 assert(AliveSuccessors.size() == 1 &&
4925 "Non-terminator expected to have a single successor!");
4929 auto Edge = std::make_pair(
I->getParent(), AliveSuccessor->getParent());
4930 if (AssumedLiveEdges.insert(
Edge).second)
4932 if (assumeLive(
A, *AliveSuccessor->getParent()))
4939 if (NewToBeExploredFrom.size() != ToBeExploredFrom.size() ||
4940 llvm::any_of(NewToBeExploredFrom, [&](
const Instruction *
I) {
4941 return !ToBeExploredFrom.count(I);
4944 ToBeExploredFrom = std::move(NewToBeExploredFrom);
4953 if (ToBeExploredFrom.empty() &&
4954 getAnchorScope()->
size() == AssumedLiveBlocks.size() &&
4955 llvm::all_of(KnownDeadEnds, [](
const Instruction *DeadEndI) {
4956 return DeadEndI->isTerminator() && DeadEndI->getNumSuccessors() == 0;
4958 return indicatePessimisticFixpoint();
4963struct AAIsDeadCallSite final : AAIsDeadFunction {
4964 AAIsDeadCallSite(
const IRPosition &IRP, Attributor &
A)
4965 : AAIsDeadFunction(IRP,
A) {}
4974 "supported for call sites yet!");
4979 return indicatePessimisticFixpoint();
4983 void trackStatistics()
const override {}
4990struct AADereferenceableImpl : AADereferenceable {
4991 AADereferenceableImpl(
const IRPosition &IRP, Attributor &
A)
4992 : AADereferenceable(IRP,
A) {}
4993 using StateType = DerefState;
4997 Value &
V = *getAssociatedValue().stripPointerCasts();
4999 A.getAttrs(getIRPosition(),
5000 {Attribute::Dereferenceable, Attribute::DereferenceableOrNull},
5003 takeKnownDerefBytesMaximum(Attr.getValueAsInt());
5006 bool IsKnownNonNull;
5008 A,
this, getIRPosition(), DepClassTy::OPTIONAL, IsKnownNonNull);
5011 takeKnownDerefBytesMaximum(
V.getPointerDereferenceableBytes(
5012 A.getDataLayout(), CanBeNull,
nullptr));
5014 if (Instruction *CtxI = getCtxI())
5015 followUsesInMBEC(*
this,
A, getState(), *CtxI);
5020 StateType &getState()
override {
return *
this; }
5021 const StateType &getState()
const override {
return *
this; }
5025 void addAccessedBytesForUse(Attributor &
A,
const Use *U,
const Instruction *
I,
5026 DerefState &State) {
5027 const Value *UseV =
U->get();
5032 if (!Loc || Loc->Ptr != UseV || !Loc->Size.isPrecise() ||
I->isVolatile())
5037 Loc->Ptr,
Offset,
A.getDataLayout(),
true);
5038 if (
Base &&
Base == &getAssociatedValue())
5039 State.addAccessedBytes(
Offset, Loc->Size.getValue());
5043 bool followUseInMBEC(Attributor &
A,
const Use *U,
const Instruction *
I,
5044 AADereferenceable::StateType &State) {
5045 bool IsNonNull =
false;
5046 bool TrackUse =
false;
5047 int64_t DerefBytes = getKnownNonNullAndDerefBytesForUse(
5048 A, *
this, getAssociatedValue(), U,
I, IsNonNull, TrackUse);
5049 LLVM_DEBUG(
dbgs() <<
"[AADereferenceable] Deref bytes: " << DerefBytes
5050 <<
" for instruction " << *
I <<
"\n");
5052 addAccessedBytesForUse(
A, U,
I, State);
5053 State.takeKnownDerefBytesMaximum(DerefBytes);
5060 bool IsKnownNonNull;
5062 A,
this, getIRPosition(), DepClassTy::NONE, IsKnownNonNull);
5063 if (IsAssumedNonNull &&
5064 A.hasAttr(getIRPosition(), Attribute::DereferenceableOrNull)) {
5065 A.removeAttrs(getIRPosition(), {Attribute::DereferenceableOrNull});
5066 return ChangeStatus::CHANGED;
5071 void getDeducedAttributes(Attributor &
A, LLVMContext &Ctx,
5072 SmallVectorImpl<Attribute> &Attrs)
const override {
5074 bool IsKnownNonNull;
5076 A,
this, getIRPosition(), DepClassTy::NONE, IsKnownNonNull);
5077 if (IsAssumedNonNull)
5078 Attrs.emplace_back(Attribute::getWithDereferenceableBytes(
5079 Ctx, getAssumedDereferenceableBytes()));
5081 Attrs.emplace_back(Attribute::getWithDereferenceableOrNullBytes(
5082 Ctx, getAssumedDereferenceableBytes()));
5086 const std::string getAsStr(Attributor *
A)
const override {
5087 if (!getAssumedDereferenceableBytes())
5088 return "unknown-dereferenceable";
5089 bool IsKnownNonNull;
5090 bool IsAssumedNonNull =
false;
5093 *
A,
this, getIRPosition(), DepClassTy::NONE, IsKnownNonNull);
5094 return std::string(
"dereferenceable") +
5095 (IsAssumedNonNull ?
"" :
"_or_null") +
5096 (isAssumedGlobal() ?
"_globally" :
"") +
"<" +
5097 std::to_string(getKnownDereferenceableBytes()) +
"-" +
5098 std::to_string(getAssumedDereferenceableBytes()) +
">" +
5099 (!
A ?
" [non-null is unknown]" :
"");
5104struct AADereferenceableFloating : AADereferenceableImpl {
5105 AADereferenceableFloating(
const IRPosition &IRP, Attributor &
A)
5106 : AADereferenceableImpl(IRP,
A) {}
5111 bool UsedAssumedInformation =
false;
5113 if (!
A.getAssumedSimplifiedValues(getIRPosition(), *
this,
Values,
5115 Values.push_back({getAssociatedValue(), getCtxI()});
5118 Stripped =
Values.size() != 1 ||
5119 Values.front().getValue() != &getAssociatedValue();
5122 const DataLayout &
DL =
A.getDataLayout();
5125 auto VisitValueCB = [&](
const Value &
V) ->
bool {
5127 DL.getIndexSizeInBits(
V.getType()->getPointerAddressSpace());
5128 APInt
Offset(IdxWidth, 0);
5133 const auto *AA =
A.getAAFor<AADereferenceable>(
5135 int64_t DerefBytes = 0;
5136 if (!AA || (!Stripped &&
this == AA)) {
5140 DerefBytes =
Base->getPointerDereferenceableBytes(
5141 DL, CanBeNull,
nullptr);
5142 T.GlobalState.indicatePessimisticFixpoint();
5145 DerefBytes =
DS.DerefBytesState.getAssumed();
5146 T.GlobalState &=
DS.GlobalState;
5152 int64_t OffsetSExt =
Offset.getSExtValue();
5156 T.takeAssumedDerefBytesMinimum(
5157 std::max(int64_t(0), DerefBytes - OffsetSExt));
5162 T.takeKnownDerefBytesMaximum(
5163 std::max(int64_t(0), DerefBytes - OffsetSExt));
5164 T.indicatePessimisticFixpoint();
5165 }
else if (OffsetSExt > 0) {
5171 T.indicatePessimisticFixpoint();
5175 return T.isValidState();
5178 for (
const auto &VAC :
Values)
5179 if (!VisitValueCB(*VAC.
getValue()))
5180 return indicatePessimisticFixpoint();
5186 void trackStatistics()
const override {
5192struct AADereferenceableReturned final
5193 : AAReturnedFromReturnedValues<AADereferenceable, AADereferenceableImpl> {
5195 AAReturnedFromReturnedValues<AADereferenceable, AADereferenceableImpl>;
5196 AADereferenceableReturned(
const IRPosition &IRP, Attributor &
A)
5200 void trackStatistics()
const override {
5206struct AADereferenceableArgument final
5207 : AAArgumentFromCallSiteArguments<AADereferenceable,
5208 AADereferenceableImpl> {
5210 AAArgumentFromCallSiteArguments<AADereferenceable, AADereferenceableImpl>;
5211 AADereferenceableArgument(
const IRPosition &IRP, Attributor &
A)
5215 void trackStatistics()
const override {
5221struct AADereferenceableCallSiteArgument final : AADereferenceableFloating {
5222 AADereferenceableCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
5223 : AADereferenceableFloating(IRP,
A) {}
5226 void trackStatistics()
const override {
5232struct AADereferenceableCallSiteReturned final
5233 : AACalleeToCallSite<AADereferenceable, AADereferenceableImpl> {
5234 using Base = AACalleeToCallSite<AADereferenceable, AADereferenceableImpl>;
5235 AADereferenceableCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
5239 void trackStatistics()
const override {
5249static unsigned getKnownAlignForUse(Attributor &
A, AAAlign &QueryingAA,
5250 Value &AssociatedValue,
const Use *U,
5251 const Instruction *
I,
bool &TrackUse) {
5260 if (
GEP->hasAllConstantIndices())
5265 switch (
II->getIntrinsicID()) {
5266 case Intrinsic::ptrmask: {
5268 const auto *ConstVals =
A.getAAFor<AAPotentialConstantValues>(
5270 const auto *AlignAA =
A.getAAFor<AAAlign>(
5272 if (ConstVals && ConstVals->isValidState() && ConstVals->isAtFixpoint()) {
5273 unsigned ShiftValue = std::min(ConstVals->getAssumedMinTrailingZeros(),
5276 if (ConstAlign >= AlignAA->getKnownAlign())
5277 return Align(1).value();
5280 return AlignAA->getKnownAlign().
value();
5283 case Intrinsic::amdgcn_make_buffer_rsrc: {
5284 const auto *AlignAA =
A.getAAFor<AAAlign>(
5287 return AlignAA->getKnownAlign().
value();
5305 MA = MaybeAlign(AlignAA->getKnownAlign());
5308 const DataLayout &
DL =
A.getDataLayout();
5309 const Value *UseV =
U->get();
5311 if (
SI->getPointerOperand() == UseV)
5312 MA =
SI->getAlign();
5314 if (LI->getPointerOperand() == UseV)
5315 MA = LI->getAlign();
5317 if (AI->getPointerOperand() == UseV)
5318 MA = AI->getAlign();
5320 if (AI->getPointerOperand() == UseV)
5321 MA = AI->getAlign();
5331 if (
Base == &AssociatedValue) {
5336 uint32_t
gcd = std::gcd(uint32_t(
abs((int32_t)
Offset)), Alignment);
5344struct AAAlignImpl : AAAlign {
5345 AAAlignImpl(
const IRPosition &IRP, Attributor &
A) : AAAlign(IRP,
A) {}
5350 A.getAttrs(getIRPosition(), {Attribute::Alignment},
Attrs);
5352 takeKnownMaximum(Attr.getValueAsInt());
5354 Value &
V = *getAssociatedValue().stripPointerCasts();
5355 takeKnownMaximum(
V.getPointerAlignment(
A.getDataLayout()).value());
5357 if (Instruction *CtxI = getCtxI())
5358 followUsesInMBEC(*
this,
A, getState(), *CtxI);
5366 Value &AssociatedValue = getAssociatedValue();
5368 return ChangeStatus::UNCHANGED;
5370 for (
const Use &U : AssociatedValue.
uses()) {
5372 if (
SI->getPointerOperand() == &AssociatedValue)
5373 if (
SI->getAlign() < getAssumedAlign()) {
5375 "Number of times alignment added to a store");
5376 SI->setAlignment(getAssumedAlign());
5377 InstrChanged = ChangeStatus::CHANGED;
5380 if (LI->getPointerOperand() == &AssociatedValue)
5381 if (LI->getAlign() < getAssumedAlign()) {
5382 LI->setAlignment(getAssumedAlign());
5384 "Number of times alignment added to a load");
5385 InstrChanged = ChangeStatus::CHANGED;
5388 if (RMW->getPointerOperand() == &AssociatedValue) {
5389 if (RMW->getAlign() < getAssumedAlign()) {
5391 "Number of times alignment added to atomicrmw");
5393 RMW->setAlignment(getAssumedAlign());
5394 InstrChanged = ChangeStatus::CHANGED;
5398 if (CAS->getPointerOperand() == &AssociatedValue) {
5399 if (CAS->getAlign() < getAssumedAlign()) {
5401 "Number of times alignment added to cmpxchg");
5402 CAS->setAlignment(getAssumedAlign());
5403 InstrChanged = ChangeStatus::CHANGED;
5411 Align InheritAlign =
5412 getAssociatedValue().getPointerAlignment(
A.getDataLayout());
5413 if (InheritAlign >= getAssumedAlign())
5414 return InstrChanged;
5415 return Changed | InstrChanged;
5423 void getDeducedAttributes(Attributor &
A, LLVMContext &Ctx,
5424 SmallVectorImpl<Attribute> &Attrs)
const override {
5425 if (getAssumedAlign() > 1)
5427 Attribute::getWithAlignment(Ctx,
Align(getAssumedAlign())));
5431 bool followUseInMBEC(Attributor &
A,
const Use *U,
const Instruction *
I,
5432 AAAlign::StateType &State) {
5433 bool TrackUse =
false;
5435 unsigned int KnownAlign =
5436 getKnownAlignForUse(
A, *
this, getAssociatedValue(), U,
I, TrackUse);
5437 State.takeKnownMaximum(KnownAlign);
5443 const std::string getAsStr(Attributor *
A)
const override {
5444 return "align<" + std::to_string(getKnownAlign().value()) +
"-" +
5445 std::to_string(getAssumedAlign().value()) +
">";
5450struct AAAlignFloating : AAAlignImpl {
5451 AAAlignFloating(
const IRPosition &IRP, Attributor &
A) : AAAlignImpl(IRP,
A) {}
5455 const DataLayout &
DL =
A.getDataLayout();
5458 bool UsedAssumedInformation =
false;
5460 if (!
A.getAssumedSimplifiedValues(getIRPosition(), *
this,
Values,
5462 Values.push_back({getAssociatedValue(), getCtxI()});
5465 Stripped =
Values.size() != 1 ||
5466 Values.front().getValue() != &getAssociatedValue();
5470 auto VisitValueCB = [&](
Value &
V) ->
bool {
5474 DepClassTy::REQUIRED);
5475 if (!AA || (!Stripped &&
this == AA)) {
5493 T.takeKnownMaximum(Alignment);
5494 T.indicatePessimisticFixpoint();
5497 const AAAlign::StateType &
DS = AA->
getState();
5500 return T.isValidState();
5503 for (
const auto &VAC :
Values) {
5504 if (!VisitValueCB(*VAC.
getValue()))
5505 return indicatePessimisticFixpoint();
5518struct AAAlignReturned final
5519 : AAReturnedFromReturnedValues<AAAlign, AAAlignImpl> {
5520 using Base = AAReturnedFromReturnedValues<AAAlign, AAAlignImpl>;
5521 AAAlignReturned(
const IRPosition &IRP, Attributor &
A) :
Base(IRP,
A) {}
5528struct AAAlignArgument final
5529 : AAArgumentFromCallSiteArguments<AAAlign, AAAlignImpl> {
5530 using Base = AAArgumentFromCallSiteArguments<AAAlign, AAAlignImpl>;
5531 AAAlignArgument(
const IRPosition &IRP, Attributor &
A) :
Base(IRP,
A) {}
5538 if (
A.getInfoCache().isInvolvedInMustTailCall(*getAssociatedArgument()))
5539 return ChangeStatus::UNCHANGED;
5540 return Base::manifest(
A);
5547struct AAAlignCallSiteArgument final : AAAlignFloating {
5548 AAAlignCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
5549 : AAAlignFloating(IRP,
A) {}
5556 if (Argument *Arg = getAssociatedArgument())
5557 if (
A.getInfoCache().isInvolvedInMustTailCall(*Arg))
5558 return ChangeStatus::UNCHANGED;
5560 Align InheritAlign =
5561 getAssociatedValue().getPointerAlignment(
A.getDataLayout());
5562 if (InheritAlign >= getAssumedAlign())
5563 Changed = ChangeStatus::UNCHANGED;
5570 if (Argument *Arg = getAssociatedArgument()) {
5573 const auto *ArgAlignAA =
A.getAAFor<AAAlign>(
5576 takeKnownMaximum(ArgAlignAA->getKnownAlign().value());
5586struct AAAlignCallSiteReturned final
5587 : AACalleeToCallSite<AAAlign, AAAlignImpl> {
5588 using Base = AACalleeToCallSite<AAAlign, AAAlignImpl>;
5589 AAAlignCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
5595 switch (
II->getIntrinsicID()) {
5596 case Intrinsic::ptrmask: {
5600 const auto *ConstVals =
A.getAAFor<AAPotentialConstantValues>(
5602 if (ConstVals && ConstVals->isValidState()) {
5603 unsigned ShiftValue =
5604 std::min(ConstVals->getAssumedMinTrailingZeros(),
5605 Value::MaxAlignmentExponent);
5610 const auto *AlignAA =
5612 DepClassTy::REQUIRED);
5614 Alignment = std::max(AlignAA->getAssumedAlign(), Alignment);
5621 std::min(this->getAssumedAlign(), Alignment).value());
5627 case Intrinsic::amdgcn_make_buffer_rsrc: {
5628 const auto *AlignAA =
5630 DepClassTy::REQUIRED);
5633 this->getState(), AlignAA->getAssumedAlign().
value());
5640 return Base::updateImpl(
A);
5649struct AANoReturnImpl :
public AANoReturn {
5650 AANoReturnImpl(
const IRPosition &IRP, Attributor &
A) : AANoReturn(IRP,
A) {}
5656 A,
nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));
5661 const std::string getAsStr(Attributor *
A)
const override {
5662 return getAssumed() ?
"noreturn" :
"may-return";
5667 auto CheckForNoReturn = [](
Instruction &) {
return false; };
5668 bool UsedAssumedInformation =
false;
5669 if (!
A.checkForAllInstructions(CheckForNoReturn, *
this,
5670 {(unsigned)Instruction::Ret},
5671 UsedAssumedInformation))
5672 return indicatePessimisticFixpoint();
5673 return ChangeStatus::UNCHANGED;
5677struct AANoReturnFunction final : AANoReturnImpl {
5678 AANoReturnFunction(
const IRPosition &IRP, Attributor &
A)
5679 : AANoReturnImpl(IRP,
A) {}
5686struct AANoReturnCallSite final
5687 : AACalleeToCallSite<AANoReturn, AANoReturnImpl> {
5688 AANoReturnCallSite(
const IRPosition &IRP, Attributor &
A)
5689 : AACalleeToCallSite<AANoReturn, AANoReturnImpl>(IRP,
A) {}
5700struct AAInstanceInfoImpl :
public AAInstanceInfo {
5701 AAInstanceInfoImpl(
const IRPosition &IRP, Attributor &
A)
5702 : AAInstanceInfo(IRP,
A) {}
5706 Value &
V = getAssociatedValue();
5708 if (
C->isThreadDependent())
5709 indicatePessimisticFixpoint();
5711 indicateOptimisticFixpoint();
5717 indicateOptimisticFixpoint();
5722 A.getInfoCache().getAnalysisResultForFunction<CycleAnalysis>(
5725 indicatePessimisticFixpoint();
5735 Value &
V = getAssociatedValue();
5738 Scope =
I->getFunction();
5741 if (!
Scope->hasLocalLinkage())
5745 return indicateOptimisticFixpoint();
5747 bool IsKnownNoRecurse;
5753 auto UsePred = [&](
const Use &
U,
bool &Follow) {
5768 if (!Callee || !
Callee->hasLocalLinkage())
5772 const auto *ArgInstanceInfoAA =
A.getAAFor<AAInstanceInfo>(
5774 DepClassTy::OPTIONAL);
5775 if (!ArgInstanceInfoAA ||
5776 !ArgInstanceInfoAA->isAssumedUniqueForAnalysis())
5781 A, *CB, *Scope, *
this,
nullptr,
5789 auto EquivalentUseCB = [&](
const Use &OldU,
const Use &NewU) {
5791 auto *Ptr =
SI->getPointerOperand()->stripPointerCasts();
5799 if (!
A.checkForAllUses(UsePred, *
this, V,
true,
5800 DepClassTy::OPTIONAL,
5801 true, EquivalentUseCB))
5802 return indicatePessimisticFixpoint();
5808 const std::string getAsStr(Attributor *
A)
const override {
5809 return isAssumedUniqueForAnalysis() ?
"<unique [fAa]>" :
"<unknown>";
5813 void trackStatistics()
const override {}
5817struct AAInstanceInfoFloating : AAInstanceInfoImpl {
5818 AAInstanceInfoFloating(
const IRPosition &IRP, Attributor &
A)
5819 : AAInstanceInfoImpl(IRP,
A) {}
5823struct AAInstanceInfoArgument final : AAInstanceInfoFloating {
5824 AAInstanceInfoArgument(
const IRPosition &IRP, Attributor &
A)
5825 : AAInstanceInfoFloating(IRP,
A) {}
5829struct AAInstanceInfoCallSiteArgument final : AAInstanceInfoImpl {
5830 AAInstanceInfoCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
5831 : AAInstanceInfoImpl(IRP,
A) {}
5839 Argument *Arg = getAssociatedArgument();
5841 return indicatePessimisticFixpoint();
5844 A.getAAFor<AAInstanceInfo>(*
this, ArgPos, DepClassTy::REQUIRED);
5846 return indicatePessimisticFixpoint();
5852struct AAInstanceInfoReturned final : AAInstanceInfoImpl {
5853 AAInstanceInfoReturned(
const IRPosition &IRP, Attributor &
A)
5854 : AAInstanceInfoImpl(IRP,
A) {
5870struct AAInstanceInfoCallSiteReturned final : AAInstanceInfoFloating {
5871 AAInstanceInfoCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
5872 : AAInstanceInfoFloating(IRP,
A) {}
5879 bool IgnoreSubsumingPositions) {
5880 assert(ImpliedAttributeKind == Attribute::Captures &&
5881 "Unexpected attribute kind");
5895 A.getAttrs(IRP, {Attribute::Captures}, Attrs,
5905 {Attribute::Captures, Attribute::ByVal}, Attrs,
5943 bool NoThrow =
F.doesNotThrow();
5944 bool IsVoidReturn =
F.getReturnType()->isVoidTy();
5945 if (
ReadOnly && NoThrow && IsVoidReturn) {
5958 if (NoThrow && IsVoidReturn)
5963 if (!NoThrow || ArgNo < 0 ||
5964 !
F.getAttributes().hasAttrSomewhere(Attribute::Returned))
5967 for (
unsigned U = 0, E =
F.arg_size(); U < E; ++U)
5968 if (
F.hasParamAttribute(U, Attribute::Returned)) {
5969 if (U ==
unsigned(ArgNo))
5996 void getDeducedAttributes(Attributor &
A, LLVMContext &Ctx,
5997 SmallVectorImpl<Attribute> &Attrs)
const override {
5998 if (!isAssumedNoCaptureMaybeReturned())
6001 if (isArgumentPosition()) {
6002 if (isAssumedNoCapture())
6003 Attrs.emplace_back(Attribute::get(Ctx, Attribute::Captures));
6005 Attrs.emplace_back(Attribute::get(Ctx,
"no-capture-maybe-returned"));
6010 const std::string getAsStr(Attributor *
A)
const override {
6011 if (isKnownNoCapture())
6012 return "known not-captured";
6013 if (isAssumedNoCapture())
6014 return "assumed not-captured";
6015 if (isKnownNoCaptureMaybeReturned())
6016 return "known not-captured-maybe-returned";
6017 if (isAssumedNoCaptureMaybeReturned())
6018 return "assumed not-captured-maybe-returned";
6019 return "assumed-captured";
6024 bool checkUse(Attributor &
A, AANoCapture::StateType &State,
const Use &U,
6027 LLVM_DEBUG(
dbgs() <<
"[AANoCapture] Check use: " << *
U.get() <<
" in "
6033 return isCapturedIn(State,
true,
true,
6040 return isCapturedIn(State,
true,
true,
6046 return isCapturedIn(State,
false,
false,
6048 return isCapturedIn(State,
true,
true,
6056 return isCapturedIn(State,
true,
true,
6063 bool IsKnownNoCapture;
6064 const AANoCapture *ArgNoCaptureAA =
nullptr;
6066 A,
this, CSArgPos, DepClassTy::REQUIRED, IsKnownNoCapture,
false,
6068 if (IsAssumedNoCapture)
6069 return isCapturedIn(State,
false,
false,
6073 return isCapturedIn(State,
false,
false,
6078 return isCapturedIn(State,
true,
true,
6085 static bool isCapturedIn(AANoCapture::StateType &State,
bool CapturedInMem,
6086 bool CapturedInInt,
bool CapturedInRet) {
6087 LLVM_DEBUG(
dbgs() <<
" - captures [Mem " << CapturedInMem <<
"|Int "
6088 << CapturedInInt <<
"|Ret " << CapturedInRet <<
"]\n");
6100 const IRPosition &IRP = getIRPosition();
6104 return indicatePessimisticFixpoint();
6111 return indicatePessimisticFixpoint();
6119 T.addKnownBits(NOT_CAPTURED_IN_MEM);
6121 addKnownBits(NOT_CAPTURED_IN_MEM);
6128 auto CheckReturnedArgs = [&](
bool &UsedAssumedInformation) {
6132 UsedAssumedInformation))
6134 bool SeenConstant =
false;
6135 for (
const AA::ValueAndContext &VAC :
Values) {
6139 SeenConstant =
true;
6141 VAC.
getValue() == getAssociatedArgument())
6147 bool IsKnownNoUnwind;
6150 bool IsVoidTy =
F->getReturnType()->isVoidTy();
6151 bool UsedAssumedInformation =
false;
6152 if (IsVoidTy || CheckReturnedArgs(UsedAssumedInformation)) {
6153 T.addKnownBits(NOT_CAPTURED_IN_RET);
6154 if (
T.isKnown(NOT_CAPTURED_IN_MEM))
6156 if (IsKnownNoUnwind && (IsVoidTy || !UsedAssumedInformation)) {
6157 addKnownBits(NOT_CAPTURED_IN_RET);
6158 if (isKnown(NOT_CAPTURED_IN_MEM))
6159 return indicateOptimisticFixpoint();
6164 auto UseCheck = [&](
const Use &
U,
bool &Follow) ->
bool {
6173 return checkUse(
A,
T, U, Follow);
6176 if (!
A.checkForAllUses(UseCheck, *
this, *V))
6177 return indicatePessimisticFixpoint();
6180 auto Assumed = S.getAssumed();
6181 S.intersectAssumedBits(
T.getAssumed());
6182 if (!isAssumedNoCaptureMaybeReturned())
6183 return indicatePessimisticFixpoint();
6189struct AANoCaptureArgument final : AANoCaptureImpl {
6190 AANoCaptureArgument(
const IRPosition &IRP, Attributor &
A)
6191 : AANoCaptureImpl(IRP,
A) {}
6198struct AANoCaptureCallSiteArgument final : AANoCaptureImpl {
6199 AANoCaptureCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
6200 : AANoCaptureImpl(IRP,
A) {}
6208 Argument *Arg = getAssociatedArgument();
6210 return indicatePessimisticFixpoint();
6212 bool IsKnownNoCapture;
6213 const AANoCapture *ArgAA =
nullptr;
6215 A,
this, ArgPos, DepClassTy::REQUIRED, IsKnownNoCapture,
false,
6217 return ChangeStatus::UNCHANGED;
6219 return indicatePessimisticFixpoint();
6224 void trackStatistics()
const override {
6230struct AANoCaptureFloating final : AANoCaptureImpl {
6231 AANoCaptureFloating(
const IRPosition &IRP, Attributor &
A)
6232 : AANoCaptureImpl(IRP,
A) {}
6235 void trackStatistics()
const override {
6241struct AANoCaptureReturned final : AANoCaptureImpl {
6242 AANoCaptureReturned(
const IRPosition &IRP, Attributor &
A)
6243 : AANoCaptureImpl(IRP,
A) {
6258 void trackStatistics()
const override {}
6262struct AANoCaptureCallSiteReturned final : AANoCaptureImpl {
6263 AANoCaptureCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
6264 : AANoCaptureImpl(IRP,
A) {}
6270 determineFunctionCaptureCapabilities(getIRPosition(), *
F, *
this);
6274 void trackStatistics()
const override {
6291 dbgs() <<
"[ValueSimplify] is assumed to be "
6294 dbgs() <<
"[ValueSimplify] is assumed to be <none>\n";
6306 if (getAssociatedValue().
getType()->isVoidTy())
6307 indicatePessimisticFixpoint();
6308 if (
A.hasSimplificationCallback(getIRPosition()))
6309 indicatePessimisticFixpoint();
6313 const std::string getAsStr(Attributor *
A)
const override {
6315 dbgs() <<
"SAV: " << (bool)SimplifiedAssociatedValue <<
" ";
6316 if (SimplifiedAssociatedValue && *SimplifiedAssociatedValue)
6317 dbgs() <<
"SAV: " << **SimplifiedAssociatedValue <<
" ";
6319 return isValidState() ? (isAtFixpoint() ?
"simplified" :
"maybe-simple")
6324 void trackStatistics()
const override {}
6327 std::optional<Value *>
6328 getAssumedSimplifiedValue(Attributor &
A)
const override {
6329 return SimplifiedAssociatedValue;
6336 static Value *ensureType(Attributor &
A,
Value &V,
Type &Ty, Instruction *CtxI,
6340 if (CtxI &&
V.getType()->canLosslesslyBitCastTo(&Ty))
6342 : BitCastInst::CreatePointerBitCastOrAddrSpaceCast(
6351 static Value *reproduceInst(Attributor &
A,
6352 const AbstractAttribute &QueryingAA,
6353 Instruction &
I,
Type &Ty, Instruction *CtxI,
6355 assert(CtxI &&
"Cannot reproduce an instruction without context!");
6356 if (
Check && (
I.mayReadFromMemory() ||
6361 Value *NewOp = reproduceValue(
A, QueryingAA, *
Op, Ty, CtxI,
Check, VMap);
6363 assert(
Check &&
"Manifest of new value unexpectedly failed!");
6385 static Value *reproduceValue(Attributor &
A,
6386 const AbstractAttribute &QueryingAA,
Value &V,
6387 Type &Ty, Instruction *CtxI,
bool Check,
6389 if (
const auto &NewV = VMap.
lookup(&V))
6391 bool UsedAssumedInformation =
false;
6392 std::optional<Value *> SimpleV =
A.getAssumedSimplified(
6394 if (!SimpleV.has_value())
6398 EffectiveV = *SimpleV;
6403 return ensureType(
A, *EffectiveV, Ty, CtxI,
Check);
6405 if (
Value *NewV = reproduceInst(
A, QueryingAA, *
I, Ty, CtxI,
Check, VMap))
6406 return ensureType(
A, *NewV, Ty, CtxI,
Check);
6412 Value *manifestReplacementValue(Attributor &
A, Instruction *CtxI)
const {
6413 Value *NewV = SimplifiedAssociatedValue
6414 ? *SimplifiedAssociatedValue
6416 if (NewV && NewV != &getAssociatedValue()) {
6420 if (reproduceValue(
A, *
this, *NewV, *getAssociatedType(), CtxI,
6422 return reproduceValue(
A, *
this, *NewV, *getAssociatedType(), CtxI,
6430 bool checkAndUpdate(Attributor &
A,
const AbstractAttribute &QueryingAA,
6431 const IRPosition &IRP,
bool Simplify =
true) {
6432 bool UsedAssumedInformation =
false;
6435 QueryingValueSimplified =
A.getAssumedSimplified(
6437 return unionAssumed(QueryingValueSimplified);
6441 template <
typename AAType>
bool askSimplifiedValueFor(Attributor &
A) {
6442 if (!getAssociatedValue().
getType()->isIntegerTy())
6447 A.getAAFor<AAType>(*
this, getIRPosition(), DepClassTy::NONE);
6451 std::optional<Constant *> COpt = AA->getAssumedConstant(
A);
6454 SimplifiedAssociatedValue = std::nullopt;
6455 A.recordDependence(*AA, *
this, DepClassTy::OPTIONAL);
6458 if (
auto *
C = *COpt) {
6459 SimplifiedAssociatedValue =
C;
6460 A.recordDependence(*AA, *
this, DepClassTy::OPTIONAL);
6466 bool askSimplifiedValueForOtherAAs(Attributor &
A) {
6467 if (askSimplifiedValueFor<AAValueConstantRange>(
A))
6469 if (askSimplifiedValueFor<AAPotentialConstantValues>(
A))
6477 for (
auto &U : getAssociatedValue().uses()) {
6482 IP =
PHI->getIncomingBlock(U)->getTerminator();
6483 if (
auto *NewV = manifestReplacementValue(
A, IP)) {
6485 <<
" -> " << *NewV <<
" :: " << *
this <<
"\n");
6486 if (
A.changeUseAfterManifest(U, *NewV))
6487 Changed = ChangeStatus::CHANGED;
6491 return Changed | AAValueSimplify::manifest(
A);
6496 SimplifiedAssociatedValue = &getAssociatedValue();
6497 return AAValueSimplify::indicatePessimisticFixpoint();
6501struct AAValueSimplifyArgument final : AAValueSimplifyImpl {
6502 AAValueSimplifyArgument(
const IRPosition &IRP, Attributor &
A)
6503 : AAValueSimplifyImpl(IRP,
A) {}
6506 AAValueSimplifyImpl::initialize(
A);
6507 if (
A.hasAttr(getIRPosition(),
6508 {Attribute::InAlloca, Attribute::Preallocated,
6509 Attribute::StructRet, Attribute::Nest, Attribute::ByVal},
6511 indicatePessimisticFixpoint();
6518 Argument *Arg = getAssociatedArgument();
6524 return indicatePessimisticFixpoint();
6527 auto Before = SimplifiedAssociatedValue;
6529 auto PredForCallSite = [&](AbstractCallSite ACS) {
6530 const IRPosition &ACSArgPos =
6541 bool UsedAssumedInformation =
false;
6542 std::optional<Constant *> SimpleArgOp =
6543 A.getAssumedConstant(ACSArgPos, *
this, UsedAssumedInformation);
6550 return unionAssumed(*SimpleArgOp);
6555 bool UsedAssumedInformation =
false;
6556 if (hasCallBaseContext() &&
6557 getCallBaseContext()->getCalledOperand() == Arg->
getParent())
6559 AbstractCallSite(&getCallBaseContext()->getCalledOperandUse()));
6561 Success =
A.checkForAllCallSites(PredForCallSite, *
this,
true,
6562 UsedAssumedInformation);
6565 if (!askSimplifiedValueForOtherAAs(
A))
6566 return indicatePessimisticFixpoint();
6569 return Before == SimplifiedAssociatedValue ? ChangeStatus::UNCHANGED
6570 : ChangeStatus ::CHANGED;
6574 void trackStatistics()
const override {
6579struct AAValueSimplifyReturned : AAValueSimplifyImpl {
6580 AAValueSimplifyReturned(
const IRPosition &IRP, Attributor &
A)
6581 : AAValueSimplifyImpl(IRP,
A) {}
6584 std::optional<Value *>
6585 getAssumedSimplifiedValue(Attributor &
A)
const override {
6586 if (!isValidState())
6588 return SimplifiedAssociatedValue;
6593 auto Before = SimplifiedAssociatedValue;
6597 return checkAndUpdate(
6602 bool UsedAssumedInformation =
false;
6603 if (!
A.checkForAllInstructions(ReturnInstCB, *
this, {Instruction::Ret},
6604 UsedAssumedInformation))
6605 if (!askSimplifiedValueForOtherAAs(
A))
6606 return indicatePessimisticFixpoint();
6609 return Before == SimplifiedAssociatedValue ? ChangeStatus::UNCHANGED
6610 : ChangeStatus ::CHANGED;
6616 return ChangeStatus::UNCHANGED;
6620 void trackStatistics()
const override {
6625struct AAValueSimplifyFloating : AAValueSimplifyImpl {
6626 AAValueSimplifyFloating(
const IRPosition &IRP, Attributor &
A)
6627 : AAValueSimplifyImpl(IRP,
A) {}
6631 AAValueSimplifyImpl::initialize(
A);
6632 Value &
V = getAnchorValue();
6636 indicatePessimisticFixpoint();
6641 auto Before = SimplifiedAssociatedValue;
6642 if (!askSimplifiedValueForOtherAAs(
A))
6643 return indicatePessimisticFixpoint();
6646 return Before == SimplifiedAssociatedValue ? ChangeStatus::UNCHANGED
6647 : ChangeStatus ::CHANGED;
6651 void trackStatistics()
const override {
6656struct AAValueSimplifyFunction : AAValueSimplifyImpl {
6657 AAValueSimplifyFunction(
const IRPosition &IRP, Attributor &
A)
6658 : AAValueSimplifyImpl(IRP,
A) {}
6662 SimplifiedAssociatedValue =
nullptr;
6663 indicateOptimisticFixpoint();
6668 "AAValueSimplify(Function|CallSite)::updateImpl will not be called");
6671 void trackStatistics()
const override {
6676struct AAValueSimplifyCallSite : AAValueSimplifyFunction {
6677 AAValueSimplifyCallSite(
const IRPosition &IRP, Attributor &
A)
6678 : AAValueSimplifyFunction(IRP,
A) {}
6680 void trackStatistics()
const override {
6685struct AAValueSimplifyCallSiteReturned : AAValueSimplifyImpl {
6686 AAValueSimplifyCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
6687 : AAValueSimplifyImpl(IRP,
A) {}
6690 AAValueSimplifyImpl::initialize(
A);
6691 Function *Fn = getAssociatedFunction();
6692 assert(Fn &&
"Did expect an associted function");
6693 for (Argument &Arg : Fn->
args()) {
6698 checkAndUpdate(
A, *
this, IRP))
6699 indicateOptimisticFixpoint();
6701 indicatePessimisticFixpoint();
6709 return indicatePessimisticFixpoint();
6712 void trackStatistics()
const override {
6717struct AAValueSimplifyCallSiteArgument : AAValueSimplifyFloating {
6718 AAValueSimplifyCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
6719 : AAValueSimplifyFloating(IRP,
A) {}
6725 auto *FloatAA =
A.lookupAAFor<AAValueSimplify>(
6727 if (FloatAA && FloatAA->getState().isValidState())
6730 if (
auto *NewV = manifestReplacementValue(
A, getCtxI())) {
6732 ->getArgOperandUse(getCallSiteArgNo());
6733 if (
A.changeUseAfterManifest(U, *NewV))
6734 Changed = ChangeStatus::CHANGED;
6737 return Changed | AAValueSimplify::manifest(
A);
6740 void trackStatistics()
const override {
6748struct AAHeapToStackFunction final :
public AAHeapToStack {
6750 static bool isGlobalizedLocal(
const CallBase &CB) {
6752 return A.
isValid() &&
A.getValueAsString() ==
"__kmpc_alloc_shared";
6755 struct AllocationInfo {
6760 bool IsGlobalizedLocal =
false;
6767 } Status = STACK_DUE_TO_USE;
6771 bool HasPotentiallyFreeingUnknownUses =
false;
6775 bool MoveAllocaIntoEntry =
true;
6778 SmallSetVector<CallBase *, 1> PotentialFreeCalls{};
6781 struct DeallocationInfo {
6789 bool MightFreeUnknownObjects =
false;
6792 SmallSetVector<CallBase *, 1> PotentialAllocationCalls{};
6795 AAHeapToStackFunction(
const IRPosition &IRP, Attributor &
A)
6796 : AAHeapToStack(IRP,
A) {}
6798 ~AAHeapToStackFunction()
override {
6801 for (
auto &It : AllocationInfos)
6802 It.second->~AllocationInfo();
6803 for (
auto &It : DeallocationInfos)
6804 It.second->~DeallocationInfo();
6808 AAHeapToStack::initialize(
A);
6811 const auto *TLI =
A.getInfoCache().getTargetLibraryInfoForFunction(*
F);
6818 DeallocationInfos[CB] =
new (
A.Allocator) DeallocationInfo{CB, FreedOp};
6825 auto *I8Ty = Type::getInt8Ty(CB->
getParent()->getContext());
6827 AllocationInfo *AI =
new (
A.Allocator) AllocationInfo{CB};
6828 AllocationInfos[CB] = AI;
6829 AI->IsGlobalizedLocal = isGlobalizedLocal(*CB);
6835 bool UsedAssumedInformation =
false;
6836 bool Success =
A.checkForAllCallLikeInstructions(
6837 AllocationIdentifierCB, *
this, UsedAssumedInformation,
6841 assert(
Success &&
"Did not expect the call base visit callback to fail!");
6844 [](
const IRPosition &,
const AbstractAttribute *,
6845 bool &) -> std::optional<Value *> {
return nullptr; };
6846 for (
const auto &It : AllocationInfos)
6849 for (
const auto &It : DeallocationInfos)
6854 const std::string getAsStr(Attributor *
A)
const override {
6855 unsigned NumH2SMallocs = 0, NumInvalidMallocs = 0;
6856 for (
const auto &It : AllocationInfos) {
6857 if (It.second->Status == AllocationInfo::INVALID)
6858 ++NumInvalidMallocs;
6862 return "[H2S] Mallocs Good/Bad: " + std::to_string(NumH2SMallocs) +
"/" +
6863 std::to_string(NumInvalidMallocs);
6867 void trackStatistics()
const override {
6870 "Number of malloc/calloc/aligned_alloc calls converted to allocas");
6871 for (
const auto &It : AllocationInfos)
6872 if (It.second->Status != AllocationInfo::INVALID)
6876 bool isAssumedHeapToStack(
const CallBase &CB)
const override {
6878 if (AllocationInfo *AI =
6879 AllocationInfos.lookup(
const_cast<CallBase *
>(&CB)))
6880 return AI->Status != AllocationInfo::INVALID;
6884 bool isAssumedHeapToStackRemovedFree(CallBase &CB)
const override {
6885 if (!isValidState())
6888 for (
const auto &It : AllocationInfos) {
6889 AllocationInfo &AI = *It.second;
6890 if (AI.Status == AllocationInfo::INVALID)
6893 if (AI.PotentialFreeCalls.count(&CB))
6901 assert(getState().isValidState() &&
6902 "Attempted to manifest an invalid state!");
6906 const auto *TLI =
A.getInfoCache().getTargetLibraryInfoForFunction(*
F);
6908 for (
auto &It : AllocationInfos) {
6909 AllocationInfo &AI = *It.second;
6910 if (AI.Status == AllocationInfo::INVALID)
6913 for (CallBase *FreeCall : AI.PotentialFreeCalls) {
6914 LLVM_DEBUG(
dbgs() <<
"H2S: Removing free call: " << *FreeCall <<
"\n");
6915 A.deleteAfterManifest(*FreeCall);
6916 HasChanged = ChangeStatus::CHANGED;
6919 LLVM_DEBUG(
dbgs() <<
"H2S: Removing malloc-like call: " << *AI.CB
6922 auto Remark = [&](OptimizationRemark
OR) {
6923 if (AI.IsGlobalizedLocal)
6924 return OR <<
"Moving globalized variable to the stack.";
6925 return OR <<
"Moving memory allocation from the heap to the stack.";
6927 if (AI.IsGlobalizedLocal)
6928 A.emitRemark<OptimizationRemark>(AI.CB,
"OMP110",
Remark);
6930 A.emitRemark<OptimizationRemark>(AI.CB,
"HeapToStack",
Remark);
6932 const DataLayout &
DL =
A.getInfoCache().getDL();
6934 std::optional<APInt> SizeAPI =
getSize(
A, *
this, AI);
6936 Size = ConstantInt::get(AI.CB->getContext(), *SizeAPI);
6938 ObjectSizeOpts Opts;
6939 ObjectSizeOffsetEvaluator Eval(*AI.CB->getModule(), TLI, Opts);
6940 SizeOffsetValue SizeOffsetPair = Eval.compute(AI.CB);
6947 ?
F->getEntryBlock().begin()
6948 : AI.CB->getIterator();
6951 if (MaybeAlign RetAlign = AI.CB->getRetAlign())
6952 Alignment = std::max(Alignment, *RetAlign);
6954 std::optional<APInt> AlignmentAPI = getAPInt(
A, *
this, *Align);
6955 assert(AlignmentAPI && AlignmentAPI->getZExtValue() > 0 &&
6956 "Expected an alignment during manifest!");
6958 std::max(Alignment,
assumeAligned(AlignmentAPI->getZExtValue()));
6962 unsigned AS =
DL.getAllocaAddrSpace();
6964 new AllocaInst(Type::getInt8Ty(
F->getContext()), AS,
Size, Alignment,
6965 AI.CB->getName() +
".h2s", IP);
6967 if (Alloca->
getType() != AI.CB->getType())
6968 Alloca = BitCastInst::CreatePointerBitCastOrAddrSpaceCast(
6969 Alloca, AI.CB->getType(),
"malloc_cast", AI.CB->getIterator());
6971 auto *I8Ty = Type::getInt8Ty(
F->getContext());
6974 "Must be able to materialize initial memory state of allocation");
6979 auto *NBB =
II->getNormalDest();
6981 A.deleteAfterManifest(*AI.CB);
6983 A.deleteAfterManifest(*AI.CB);
6992 Builder.CreateMemSet(Alloca, InitVal,
Size, std::nullopt);
6994 HasChanged = ChangeStatus::CHANGED;
7000 std::optional<APInt> getAPInt(Attributor &
A,
const AbstractAttribute &AA,
7002 bool UsedAssumedInformation =
false;
7003 std::optional<Constant *> SimpleV =
7004 A.getAssumedConstant(V, AA, UsedAssumedInformation);
7006 return APInt(64, 0);
7008 return CI->getValue();
7009 return std::nullopt;
7012 std::optional<APInt>
getSize(Attributor &
A,
const AbstractAttribute &AA,
7013 AllocationInfo &AI) {
7015 bool UsedAssumedInformation =
false;
7016 if (std::optional<Constant *> SimpleV =
7017 A.getAssumedConstant(*V, AA, UsedAssumedInformation))
7024 const auto *TLI =
A.getInfoCache().getTargetLibraryInfoForFunction(*
F);
7030 MapVector<CallBase *, AllocationInfo *> AllocationInfos;
7034 MapVector<CallBase *, DeallocationInfo *> DeallocationInfos;
7039ChangeStatus AAHeapToStackFunction::updateImpl(Attributor &
A) {
7042 const auto *TLI =
A.getInfoCache().getTargetLibraryInfoForFunction(*
F);
7044 const auto *LivenessAA =
7047 MustBeExecutedContextExplorer *Explorer =
7048 A.getInfoCache().getMustBeExecutedContextExplorer();
7050 bool StackIsAccessibleByOtherThreads =
7051 A.getInfoCache().stackIsAccessibleByOtherThreads();
7054 A.getInfoCache().getAnalysisResultForFunction<LoopAnalysis>(*F);
7055 std::optional<bool> MayContainIrreducibleControl;
7057 if (&
F->getEntryBlock() == &BB)
7059 if (!MayContainIrreducibleControl.has_value())
7061 if (*MayContainIrreducibleControl)
7070 bool HasUpdatedFrees =
false;
7072 auto UpdateFrees = [&]() {
7073 HasUpdatedFrees =
true;
7075 for (
auto &It : DeallocationInfos) {
7076 DeallocationInfo &DI = *It.second;
7079 if (DI.MightFreeUnknownObjects)
7083 bool UsedAssumedInformation =
false;
7084 if (
A.isAssumedDead(*DI.CB,
this, LivenessAA, UsedAssumedInformation,
7091 LLVM_DEBUG(
dbgs() <<
"[H2S] Unknown underlying object for free!\n");
7092 DI.MightFreeUnknownObjects =
true;
7105 DI.MightFreeUnknownObjects =
true;
7109 AllocationInfo *AI = AllocationInfos.lookup(ObjCB);
7111 LLVM_DEBUG(
dbgs() <<
"[H2S] Free of a non-allocation object: " << *Obj
7113 DI.MightFreeUnknownObjects =
true;
7117 DI.PotentialAllocationCalls.insert(ObjCB);
7121 auto FreeCheck = [&](AllocationInfo &AI) {
7125 if (!StackIsAccessibleByOtherThreads) {
7130 dbgs() <<
"[H2S] found an escaping use, stack is not accessible by "
7131 "other threads and function is not nosync:\n");
7135 if (!HasUpdatedFrees)
7139 if (AI.PotentialFreeCalls.size() != 1) {
7141 << AI.PotentialFreeCalls.size() <<
"\n");
7144 CallBase *UniqueFree = *AI.PotentialFreeCalls.begin();
7145 DeallocationInfo *DI = DeallocationInfos.lookup(UniqueFree);
7148 dbgs() <<
"[H2S] unique free call was not known as deallocation call "
7149 << *UniqueFree <<
"\n");
7152 if (DI->MightFreeUnknownObjects) {
7154 dbgs() <<
"[H2S] unique free call might free unknown allocations\n");
7157 if (DI->PotentialAllocationCalls.empty())
7159 if (DI->PotentialAllocationCalls.size() > 1) {
7161 << DI->PotentialAllocationCalls.size()
7162 <<
" different allocations\n");
7165 if (*DI->PotentialAllocationCalls.begin() != AI.CB) {
7168 <<
"[H2S] unique free call not known to free this allocation but "
7169 << **DI->PotentialAllocationCalls.begin() <<
"\n");
7174 if (!AI.IsGlobalizedLocal) {
7176 if (!Explorer || !Explorer->findInContextOf(UniqueFree, CtxI)) {
7177 LLVM_DEBUG(
dbgs() <<
"[H2S] unique free call might not be executed "
7178 "with the allocation "
7179 << *UniqueFree <<
"\n");
7186 auto UsesCheck = [&](AllocationInfo &AI) {
7187 bool ValidUsesOnly =
true;
7189 auto Pred = [&](
const Use &
U,
bool &Follow) ->
bool {
7194 if (
SI->getValueOperand() ==
U.get()) {
7196 <<
"[H2S] escaping store to memory: " << *UserI <<
"\n");
7197 ValidUsesOnly =
false;
7206 if (DeallocationInfos.count(CB)) {
7207 AI.PotentialFreeCalls.insert(CB);
7214 bool IsKnownNoCapture;
7223 if (!IsAssumedNoCapture ||
7224 (!AI.IsGlobalizedLocal && !IsAssumedNoFree)) {
7225 AI.HasPotentiallyFreeingUnknownUses |= !IsAssumedNoFree;
7228 auto Remark = [&](OptimizationRemarkMissed ORM) {
7230 <<
"Could not move globalized variable to the stack. "
7231 "Variable is potentially captured in call. Mark "
7232 "parameter as `__attribute__((noescape))` to override.";
7235 if (ValidUsesOnly && AI.IsGlobalizedLocal)
7236 A.emitRemark<OptimizationRemarkMissed>(CB,
"OMP113",
Remark);
7239 ValidUsesOnly =
false;
7252 ValidUsesOnly =
false;
7255 if (!
A.checkForAllUses(Pred, *
this, *AI.CB,
false,
7257 [&](
const Use &OldU,
const Use &NewU) {
7258 auto *SI = dyn_cast<StoreInst>(OldU.getUser());
7259 return !SI || StackIsAccessibleByOtherThreads ||
7260 AA::isAssumedThreadLocalObject(
7261 A, *SI->getPointerOperand(), *this);
7264 return ValidUsesOnly;
7269 for (
auto &It : AllocationInfos) {
7270 AllocationInfo &AI = *It.second;
7271 if (AI.Status == AllocationInfo::INVALID)
7275 std::optional<APInt> APAlign = getAPInt(
A, *
this, *Align);
7279 LLVM_DEBUG(
dbgs() <<
"[H2S] Unknown allocation alignment: " << *AI.CB
7281 AI.Status = AllocationInfo::INVALID;
7286 !APAlign->isPowerOf2()) {
7287 LLVM_DEBUG(
dbgs() <<
"[H2S] Invalid allocation alignment: " << APAlign
7289 AI.Status = AllocationInfo::INVALID;
7300 dbgs() <<
"[H2S] Unknown allocation size: " << *AI.CB <<
"\n";
7302 dbgs() <<
"[H2S] Allocation size too large: " << *AI.CB <<
" vs. "
7306 AI.Status = AllocationInfo::INVALID;
7312 switch (AI.Status) {
7313 case AllocationInfo::STACK_DUE_TO_USE:
7316 AI.Status = AllocationInfo::STACK_DUE_TO_FREE;
7318 case AllocationInfo::STACK_DUE_TO_FREE:
7321 AI.Status = AllocationInfo::INVALID;
7324 case AllocationInfo::INVALID:
7331 bool IsGlobalizedLocal = AI.IsGlobalizedLocal;
7332 if (AI.MoveAllocaIntoEntry &&
7333 (!
Size.has_value() ||
7334 (!IsGlobalizedLocal && IsInLoop(*AI.CB->getParent()))))
7335 AI.MoveAllocaIntoEntry =
false;
7344struct AAPrivatizablePtrImpl :
public AAPrivatizablePtr {
7345 AAPrivatizablePtrImpl(
const IRPosition &IRP, Attributor &
A)
7346 : AAPrivatizablePtr(IRP,
A), PrivatizableType(std::nullopt) {}
7349 AAPrivatizablePtr::indicatePessimisticFixpoint();
7350 PrivatizableType =
nullptr;
7351 return ChangeStatus::CHANGED;
7357 virtual std::optional<Type *> identifyPrivatizableType(Attributor &
A) = 0;
7361 std::optional<Type *> combineTypes(std::optional<Type *> T0,
7362 std::optional<Type *>
T1) {
7372 std::optional<Type *> getPrivatizableType()
const override {
7373 return PrivatizableType;
7376 const std::string getAsStr(Attributor *
A)
const override {
7377 return isAssumedPrivatizablePtr() ?
"[priv]" :
"[no-priv]";
7381 std::optional<Type *> PrivatizableType;
7386struct AAPrivatizablePtrArgument final :
public AAPrivatizablePtrImpl {
7387 AAPrivatizablePtrArgument(
const IRPosition &IRP, Attributor &
A)
7388 : AAPrivatizablePtrImpl(IRP,
A) {}
7391 std::optional<Type *> identifyPrivatizableType(Attributor &
A)
override {
7394 bool UsedAssumedInformation =
false;
7396 A.getAttrs(getIRPosition(), {Attribute::ByVal},
Attrs,
7398 if (!
Attrs.empty() &&
7399 A.checkForAllCallSites([](AbstractCallSite ACS) { return true; }, *
this,
7400 true, UsedAssumedInformation))
7401 return Attrs[0].getValueAsType();
7403 std::optional<Type *> Ty;
7404 unsigned ArgNo = getIRPosition().getCallSiteArgNo();
7412 auto CallSiteCheck = [&](AbstractCallSite ACS) {
7421 A.getAAFor<AAPrivatizablePtr>(*
this, ACSArgPos, DepClassTy::REQUIRED);
7424 std::optional<Type *> CSTy = PrivCSArgAA->getPrivatizableType();
7427 dbgs() <<
"[AAPrivatizablePtr] ACSPos: " << ACSArgPos <<
", CSTy: ";
7431 dbgs() <<
"<nullptr>";
7436 Ty = combineTypes(Ty, CSTy);
7439 dbgs() <<
" : New Type: ";
7441 (*Ty)->print(
dbgs());
7443 dbgs() <<
"<nullptr>";
7452 if (!
A.checkForAllCallSites(CallSiteCheck, *
this,
true,
7453 UsedAssumedInformation))
7460 PrivatizableType = identifyPrivatizableType(
A);
7461 if (!PrivatizableType)
7462 return ChangeStatus::UNCHANGED;
7463 if (!*PrivatizableType)
7464 return indicatePessimisticFixpoint();
7469 DepClassTy::OPTIONAL);
7472 if (!
A.hasAttr(getIRPosition(), Attribute::ByVal) &&
7475 return indicatePessimisticFixpoint();
7481 identifyReplacementTypes(*PrivatizableType, ReplacementTypes);
7485 Function &Fn = *getIRPosition().getAnchorScope();
7487 A.getInfoCache().getAnalysisResultForFunction<TargetIRAnalysis>(Fn);
7489 LLVM_DEBUG(
dbgs() <<
"[AAPrivatizablePtr] Missing TTI for function "
7491 return indicatePessimisticFixpoint();
7494 auto CallSiteCheck = [&](AbstractCallSite ACS) {
7501 bool UsedAssumedInformation =
false;
7502 if (!
A.checkForAllCallSites(CallSiteCheck, *
this,
true,
7503 UsedAssumedInformation)) {
7505 dbgs() <<
"[AAPrivatizablePtr] ABI incompatibility detected for "
7507 return indicatePessimisticFixpoint();
7511 Argument *Arg = getAssociatedArgument();
7512 if (!
A.isValidFunctionSignatureRewrite(*Arg, ReplacementTypes)) {
7514 return indicatePessimisticFixpoint();
7521 auto IsCompatiblePrivArgOfCallback = [&](CallBase &CB) {
7524 for (
const Use *U : CallbackUses) {
7525 AbstractCallSite CBACS(U);
7526 assert(CBACS && CBACS.isCallbackCall());
7527 for (Argument &CBArg : CBACS.getCalledFunction()->args()) {
7528 int CBArgNo = CBACS.getCallArgOperandNo(CBArg);
7532 <<
"[AAPrivatizablePtr] Argument " << *Arg
7533 <<
"check if can be privatized in the context of its parent ("
7535 <<
")\n[AAPrivatizablePtr] because it is an argument in a "
7537 << CBArgNo <<
"@" << CBACS.getCalledFunction()->getName()
7538 <<
")\n[AAPrivatizablePtr] " << CBArg <<
" : "
7539 << CBACS.getCallArgOperand(CBArg) <<
" vs "
7541 <<
"[AAPrivatizablePtr] " << CBArg <<
" : "
7542 << CBACS.getCallArgOperandNo(CBArg) <<
" vs " << ArgNo <<
"\n";
7545 if (CBArgNo !=
int(ArgNo))
7547 const auto *CBArgPrivAA =
A.getAAFor<AAPrivatizablePtr>(
7549 if (CBArgPrivAA && CBArgPrivAA->isValidState()) {
7550 auto CBArgPrivTy = CBArgPrivAA->getPrivatizableType();
7553 if (*CBArgPrivTy == PrivatizableType)
7558 dbgs() <<
"[AAPrivatizablePtr] Argument " << *Arg
7559 <<
" cannot be privatized in the context of its parent ("
7561 <<
")\n[AAPrivatizablePtr] because it is an argument in a "
7563 << CBArgNo <<
"@" << CBACS.getCalledFunction()->getName()
7564 <<
").\n[AAPrivatizablePtr] for which the argument "
7565 "privatization is not compatible.\n";
7575 auto IsCompatiblePrivArgOfDirectCS = [&](AbstractCallSite ACS) {
7579 "Expected a direct call operand for callback call operand");
7584 dbgs() <<
"[AAPrivatizablePtr] Argument " << *Arg
7585 <<
" check if be privatized in the context of its parent ("
7587 <<
")\n[AAPrivatizablePtr] because it is an argument in a "
7589 << DCArgNo <<
"@" << DCCallee->
getName() <<
").\n";
7592 if (
unsigned(DCArgNo) < DCCallee->
arg_size()) {
7593 const auto *DCArgPrivAA =
A.getAAFor<AAPrivatizablePtr>(
7595 DepClassTy::REQUIRED);
7596 if (DCArgPrivAA && DCArgPrivAA->isValidState()) {
7597 auto DCArgPrivTy = DCArgPrivAA->getPrivatizableType();
7600 if (*DCArgPrivTy == PrivatizableType)
7606 dbgs() <<
"[AAPrivatizablePtr] Argument " << *Arg
7607 <<
" cannot be privatized in the context of its parent ("
7609 <<
")\n[AAPrivatizablePtr] because it is an argument in a "
7612 <<
").\n[AAPrivatizablePtr] for which the argument "
7613 "privatization is not compatible.\n";
7621 auto IsCompatiblePrivArgOfOtherCallSite = [&](AbstractCallSite ACS) {
7625 return IsCompatiblePrivArgOfDirectCS(ACS);
7629 if (!
A.checkForAllCallSites(IsCompatiblePrivArgOfOtherCallSite, *
this,
true,
7630 UsedAssumedInformation))
7631 return indicatePessimisticFixpoint();
7633 return ChangeStatus::UNCHANGED;
7639 identifyReplacementTypes(
Type *PrivType,
7640 SmallVectorImpl<Type *> &ReplacementTypes) {
7643 assert(PrivType &&
"Expected privatizable type!");
7647 for (
unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++)
7648 ReplacementTypes.
push_back(PrivStructType->getElementType(u));
7650 ReplacementTypes.
append(PrivArrayType->getNumElements(),
7651 PrivArrayType->getElementType());
7662 assert(PrivType &&
"Expected privatizable type!");
7665 const DataLayout &
DL =
F.getDataLayout();
7669 const StructLayout *PrivStructLayout =
DL.getStructLayout(PrivStructType);
7670 for (
unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++) {
7673 new StoreInst(
F.getArg(ArgNo + u), Ptr, IP);
7676 Type *PointeeTy = PrivArrayType->getElementType();
7677 uint64_t PointeeTySize =
DL.getTypeStoreSize(PointeeTy);
7678 for (
unsigned u = 0, e = PrivArrayType->getNumElements(); u < e; u++) {
7680 new StoreInst(
F.getArg(ArgNo + u), Ptr, IP);
7683 new StoreInst(
F.getArg(ArgNo), &
Base, IP);
7689 void createReplacementValues(Align Alignment,
Type *PrivType,
7691 SmallVectorImpl<Value *> &ReplacementValues) {
7693 assert(PrivType &&
"Expected privatizable type!");
7701 const StructLayout *PrivStructLayout =
DL.getStructLayout(PrivStructType);
7702 for (
unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++) {
7703 Type *PointeeTy = PrivStructType->getElementType(u);
7706 LoadInst *
L =
new LoadInst(PointeeTy, Ptr,
"", IP->
getIterator());
7707 L->setAlignment(Alignment);
7711 Type *PointeeTy = PrivArrayType->getElementType();
7712 uint64_t PointeeTySize =
DL.getTypeStoreSize(PointeeTy);
7713 for (
unsigned u = 0, e = PrivArrayType->getNumElements(); u < e; u++) {
7715 LoadInst *
L =
new LoadInst(PointeeTy, Ptr,
"", IP->
getIterator());
7716 L->setAlignment(Alignment);
7721 L->setAlignment(Alignment);
7728 if (!PrivatizableType)
7729 return ChangeStatus::UNCHANGED;
7730 assert(*PrivatizableType &&
"Expected privatizable type!");
7736 bool UsedAssumedInformation =
false;
7737 if (!
A.checkForAllInstructions(
7738 [&](Instruction &
I) {
7739 CallInst &CI = cast<CallInst>(I);
7740 if (CI.isTailCall())
7741 TailCalls.push_back(&CI);
7744 *
this, {Instruction::Call}, UsedAssumedInformation))
7745 return ChangeStatus::UNCHANGED;
7747 Argument *Arg = getAssociatedArgument();
7750 const auto *AlignAA =
7757 [=](
const Attributor::ArgumentReplacementInfo &ARI,
7759 BasicBlock &EntryBB = ReplacementFn.getEntryBlock();
7761 const DataLayout &
DL = IP->getDataLayout();
7762 unsigned AS =
DL.getAllocaAddrSpace();
7763 Instruction *AI =
new AllocaInst(*PrivatizableType, AS,
7764 Arg->
getName() +
".priv", IP);
7765 createInitialization(*PrivatizableType, *AI, ReplacementFn,
7766 ArgIt->getArgNo(), IP);
7769 AI = BitCastInst::CreatePointerBitCastOrAddrSpaceCast(
7773 for (CallInst *CI : TailCalls)
7774 CI->setTailCall(
false);
7781 [=](
const Attributor::ArgumentReplacementInfo &ARI,
7782 AbstractCallSite ACS, SmallVectorImpl<Value *> &NewArgOperands) {
7785 createReplacementValues(
7786 AlignAA ? AlignAA->getAssumedAlign() :
Align(0),
7787 *PrivatizableType, ACS,
7795 identifyReplacementTypes(*PrivatizableType, ReplacementTypes);
7798 if (
A.registerFunctionSignatureRewrite(*Arg, ReplacementTypes,
7799 std::move(FnRepairCB),
7800 std::move(ACSRepairCB)))
7801 return ChangeStatus::CHANGED;
7802 return ChangeStatus::UNCHANGED;
7806 void trackStatistics()
const override {
7811struct AAPrivatizablePtrFloating :
public AAPrivatizablePtrImpl {
7812 AAPrivatizablePtrFloating(
const IRPosition &IRP, Attributor &
A)
7813 : AAPrivatizablePtrImpl(IRP,
A) {}
7818 indicatePessimisticFixpoint();
7823 "updateImpl will not be called");
7827 std::optional<Type *> identifyPrivatizableType(Attributor &
A)
override {
7830 LLVM_DEBUG(
dbgs() <<
"[AAPrivatizablePtr] No underlying object found!\n");
7837 return AI->getAllocatedType();
7839 auto *PrivArgAA =
A.getAAFor<AAPrivatizablePtr>(
7841 if (PrivArgAA && PrivArgAA->isAssumedPrivatizablePtr())
7842 return PrivArgAA->getPrivatizableType();
7845 LLVM_DEBUG(
dbgs() <<
"[AAPrivatizablePtr] Underlying object neither valid "
7846 "alloca nor privatizable argument: "
7852 void trackStatistics()
const override {
7857struct AAPrivatizablePtrCallSiteArgument final
7858 :
public AAPrivatizablePtrFloating {
7859 AAPrivatizablePtrCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
7860 : AAPrivatizablePtrFloating(IRP,
A) {}
7864 if (
A.hasAttr(getIRPosition(), Attribute::ByVal))
7865 indicateOptimisticFixpoint();
7870 PrivatizableType = identifyPrivatizableType(
A);
7871 if (!PrivatizableType)
7872 return ChangeStatus::UNCHANGED;
7873 if (!*PrivatizableType)
7874 return indicatePessimisticFixpoint();
7876 const IRPosition &IRP = getIRPosition();
7877 bool IsKnownNoCapture;
7879 A,
this, IRP, DepClassTy::REQUIRED, IsKnownNoCapture);
7880 if (!IsAssumedNoCapture) {
7881 LLVM_DEBUG(
dbgs() <<
"[AAPrivatizablePtr] pointer might be captured!\n");
7882 return indicatePessimisticFixpoint();
7885 bool IsKnownNoAlias;
7887 A,
this, IRP, DepClassTy::REQUIRED, IsKnownNoAlias)) {
7888 LLVM_DEBUG(
dbgs() <<
"[AAPrivatizablePtr] pointer might alias!\n");
7889 return indicatePessimisticFixpoint();
7894 LLVM_DEBUG(
dbgs() <<
"[AAPrivatizablePtr] pointer is written!\n");
7895 return indicatePessimisticFixpoint();
7898 return ChangeStatus::UNCHANGED;
7902 void trackStatistics()
const override {
7907struct AAPrivatizablePtrCallSiteReturned final
7908 :
public AAPrivatizablePtrFloating {
7909 AAPrivatizablePtrCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
7910 : AAPrivatizablePtrFloating(IRP,
A) {}
7915 indicatePessimisticFixpoint();
7919 void trackStatistics()
const override {
7924struct AAPrivatizablePtrReturned final :
public AAPrivatizablePtrFloating {
7925 AAPrivatizablePtrReturned(
const IRPosition &IRP, Attributor &
A)
7926 : AAPrivatizablePtrFloating(IRP,
A) {}
7931 indicatePessimisticFixpoint();
7935 void trackStatistics()
const override {
7945struct AAMemoryBehaviorImpl :
public AAMemoryBehavior {
7946 AAMemoryBehaviorImpl(
const IRPosition &IRP, Attributor &
A)
7947 : AAMemoryBehavior(IRP,
A) {}
7951 intersectAssumedBits(BEST_STATE);
7952 getKnownStateFromValue(
A, getIRPosition(), getState());
7953 AAMemoryBehavior::initialize(
A);
7957 static void getKnownStateFromValue(Attributor &
A,
const IRPosition &IRP,
7958 BitIntegerState &State,
7959 bool IgnoreSubsumingPositions =
false) {
7961 A.getAttrs(IRP, AttrKinds, Attrs, IgnoreSubsumingPositions);
7963 switch (Attr.getKindAsEnum()) {
7964 case Attribute::ReadNone:
7967 case Attribute::ReadOnly:
7970 case Attribute::WriteOnly:
7979 if (!
I->mayReadFromMemory())
7981 if (!
I->mayWriteToMemory())
7987 void getDeducedAttributes(Attributor &
A, LLVMContext &Ctx,
7988 SmallVectorImpl<Attribute> &Attrs)
const override {
7991 Attrs.push_back(Attribute::get(Ctx, Attribute::ReadNone));
7993 Attrs.push_back(Attribute::get(Ctx, Attribute::ReadOnly));
7994 else if (isAssumedWriteOnly())
7995 Attrs.push_back(Attribute::get(Ctx, Attribute::WriteOnly));
8001 const IRPosition &IRP = getIRPosition();
8003 if (
A.hasAttr(IRP, Attribute::ReadNone,
8005 return ChangeStatus::UNCHANGED;
8014 return ChangeStatus::UNCHANGED;
8017 A.removeAttrs(IRP, AttrKinds);
8020 A.removeAttrs(IRP, Attribute::Writable);
8027 const std::string getAsStr(Attributor *
A)
const override {
8032 if (isAssumedWriteOnly())
8034 return "may-read/write";
8038 static const Attribute::AttrKind AttrKinds[3];
8042 Attribute::ReadNone, Attribute::ReadOnly, Attribute::WriteOnly};
8045struct AAMemoryBehaviorFloating : AAMemoryBehaviorImpl {
8046 AAMemoryBehaviorFloating(
const IRPosition &IRP, Attributor &
A)
8047 : AAMemoryBehaviorImpl(IRP,
A) {}
8053 void trackStatistics()
const override {
8058 else if (isAssumedWriteOnly())
8065 bool followUsersOfUseIn(Attributor &
A,
const Use &U,
8066 const Instruction *UserI);
8069 void analyzeUseIn(Attributor &
A,
const Use &U,
const Instruction *UserI);
8073struct AAMemoryBehaviorArgument : AAMemoryBehaviorFloating {
8074 AAMemoryBehaviorArgument(
const IRPosition &IRP, Attributor &
A)
8075 : AAMemoryBehaviorFloating(IRP,
A) {}
8079 intersectAssumedBits(BEST_STATE);
8080 const IRPosition &IRP = getIRPosition();
8084 bool HasByVal =
A.hasAttr(IRP, {Attribute::ByVal},
8086 getKnownStateFromValue(
A, IRP, getState(),
8093 return ChangeStatus::UNCHANGED;
8097 if (
A.hasAttr(getIRPosition(),
8098 {Attribute::InAlloca, Attribute::Preallocated})) {
8099 removeKnownBits(NO_WRITES);
8100 removeAssumedBits(NO_WRITES);
8102 A.removeAttrs(getIRPosition(), AttrKinds);
8103 return AAMemoryBehaviorFloating::manifest(
A);
8107 void trackStatistics()
const override {
8112 else if (isAssumedWriteOnly())
8117struct AAMemoryBehaviorCallSiteArgument final : AAMemoryBehaviorArgument {
8118 AAMemoryBehaviorCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
8119 : AAMemoryBehaviorArgument(IRP,
A) {}
8125 Argument *Arg = getAssociatedArgument();
8127 indicatePessimisticFixpoint();
8131 addKnownBits(NO_WRITES);
8132 removeKnownBits(NO_READS);
8133 removeAssumedBits(NO_READS);
8135 AAMemoryBehaviorArgument::initialize(
A);
8136 if (getAssociatedFunction()->isDeclaration())
8137 indicatePessimisticFixpoint();
8146 Argument *Arg = getAssociatedArgument();
8149 A.getAAFor<AAMemoryBehavior>(*
this, ArgPos, DepClassTy::REQUIRED);
8151 return indicatePessimisticFixpoint();
8156 void trackStatistics()
const override {
8161 else if (isAssumedWriteOnly())
8167struct AAMemoryBehaviorCallSiteReturned final : AAMemoryBehaviorFloating {
8168 AAMemoryBehaviorCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
8169 : AAMemoryBehaviorFloating(IRP,
A) {}
8173 AAMemoryBehaviorImpl::initialize(
A);
8178 return ChangeStatus::UNCHANGED;
8182 void trackStatistics()
const override {}
8186struct AAMemoryBehaviorFunction final :
public AAMemoryBehaviorImpl {
8187 AAMemoryBehaviorFunction(
const IRPosition &IRP, Attributor &
A)
8188 : AAMemoryBehaviorImpl(IRP,
A) {}
8204 else if (isAssumedWriteOnly())
8207 A.removeAttrs(getIRPosition(), AttrKinds);
8210 for (Argument &Arg :
F.args())
8212 return A.manifestAttrs(getIRPosition(),
8213 Attribute::getWithMemoryEffects(
F.getContext(), ME));
8217 void trackStatistics()
const override {
8222 else if (isAssumedWriteOnly())
8228struct AAMemoryBehaviorCallSite final
8229 : AACalleeToCallSite<AAMemoryBehavior, AAMemoryBehaviorImpl> {
8230 AAMemoryBehaviorCallSite(
const IRPosition &IRP, Attributor &
A)
8231 : AACalleeToCallSite<AAMemoryBehavior, AAMemoryBehaviorImpl>(IRP,
A) {}
8242 else if (isAssumedWriteOnly())
8245 A.removeAttrs(getIRPosition(), AttrKinds);
8248 for (Use &U : CB.
args())
8250 Attribute::Writable);
8251 return A.manifestAttrs(
8252 getIRPosition(), Attribute::getWithMemoryEffects(CB.
getContext(), ME));
8256 void trackStatistics()
const override {
8261 else if (isAssumedWriteOnly())
8266ChangeStatus AAMemoryBehaviorFunction::updateImpl(Attributor &
A) {
8269 auto AssumedState = getAssumed();
8276 const auto *MemBehaviorAA =
A.getAAFor<AAMemoryBehavior>(
8278 if (MemBehaviorAA) {
8279 intersectAssumedBits(MemBehaviorAA->
getAssumed());
8280 return !isAtFixpoint();
8285 if (
I.mayReadFromMemory())
8286 removeAssumedBits(NO_READS);
8287 if (
I.mayWriteToMemory())
8288 removeAssumedBits(NO_WRITES);
8289 return !isAtFixpoint();
8292 bool UsedAssumedInformation =
false;
8293 if (!
A.checkForAllReadWriteInstructions(CheckRWInst, *
this,
8294 UsedAssumedInformation))
8295 return indicatePessimisticFixpoint();
8301ChangeStatus AAMemoryBehaviorFloating::updateImpl(Attributor &
A) {
8303 const IRPosition &IRP = getIRPosition();
8314 const auto *FnMemAA =
8317 FnMemAssumedState = FnMemAA->getAssumed();
8318 S.addKnownBits(FnMemAA->getKnown());
8319 if ((S.getAssumed() & FnMemAA->getAssumed()) == S.getAssumed())
8325 auto AssumedState = S.getAssumed();
8331 bool IsKnownNoCapture;
8332 const AANoCapture *ArgNoCaptureAA =
nullptr;
8337 if (!IsAssumedNoCapture &&
8339 S.intersectAssumedBits(FnMemAssumedState);
8345 auto UsePred = [&](
const Use &
U,
bool &Follow) ->
bool {
8347 LLVM_DEBUG(
dbgs() <<
"[AAMemoryBehavior] Use: " << *U <<
" in " << *UserI
8355 Follow = followUsersOfUseIn(
A, U, UserI);
8359 analyzeUseIn(
A, U, UserI);
8361 return !isAtFixpoint();
8364 if (!
A.checkForAllUses(UsePred, *
this, getAssociatedValue()))
8365 return indicatePessimisticFixpoint();
8371bool AAMemoryBehaviorFloating::followUsersOfUseIn(Attributor &
A,
const Use &U,
8372 const Instruction *UserI) {
8390 if (
U.get()->getType()->isPointerTy()) {
8392 bool IsKnownNoCapture;
8401void AAMemoryBehaviorFloating::analyzeUseIn(Attributor &
A,
const Use &U,
8402 const Instruction *UserI) {
8409 case Instruction::Load:
8411 removeAssumedBits(NO_READS);
8414 case Instruction::Store:
8419 removeAssumedBits(NO_WRITES);
8421 indicatePessimisticFixpoint();
8424 case Instruction::Call:
8425 case Instruction::CallBr:
8426 case Instruction::Invoke: {
8433 indicatePessimisticFixpoint();
8440 removeAssumedBits(NO_READS);
8447 if (
U.get()->getType()->isPointerTy())
8451 const auto *MemBehaviorAA =
8457 intersectAssumedBits(MemBehaviorAA->
getAssumed());
8465 removeAssumedBits(NO_READS);
8467 removeAssumedBits(NO_WRITES);
8479 return "all memory";
8482 std::string S =
"memory:";
8488 S +=
"internal global,";
8490 S +=
"external global,";
8494 S +=
"inaccessible,";
8508 AccessKind2Accesses.fill(
nullptr);
8511 ~AAMemoryLocationImpl()
override {
8514 for (AccessSet *AS : AccessKind2Accesses)
8521 intersectAssumedBits(BEST_STATE);
8522 getKnownStateFromValue(
A, getIRPosition(), getState());
8523 AAMemoryLocation::initialize(
A);
8527 static void getKnownStateFromValue(Attributor &
A,
const IRPosition &IRP,
8528 BitIntegerState &State,
8529 bool IgnoreSubsumingPositions =
false) {
8538 bool UseArgMemOnly =
true;
8540 if (AnchorFn &&
A.isRunOn(*AnchorFn))
8544 A.getAttrs(IRP, {Attribute::Memory},
Attrs, IgnoreSubsumingPositions);
8553 State.
addKnownBits(inverseLocation(NO_INACCESSIBLE_MEM,
true,
true));
8558 State.
addKnownBits(inverseLocation(NO_ARGUMENT_MEM,
true,
true));
8562 A.manifestAttrs(IRP,
8563 Attribute::getWithMemoryEffects(
8572 NO_INACCESSIBLE_MEM | NO_ARGUMENT_MEM,
true,
true));
8576 A.manifestAttrs(IRP,
8577 Attribute::getWithMemoryEffects(
8587 void getDeducedAttributes(Attributor &
A, LLVMContext &Ctx,
8588 SmallVectorImpl<Attribute> &Attrs)
const override {
8595 else if (isAssumedInaccessibleMemOnly())
8596 Attrs.push_back(Attribute::getWithMemoryEffects(
8598 else if (isAssumedArgMemOnly())
8601 else if (isAssumedInaccessibleOrArgMemOnly())
8602 Attrs.push_back(Attribute::getWithMemoryEffects(
8612 const IRPosition &IRP = getIRPosition();
8616 if (DeducedAttrs.
size() != 1)
8617 return ChangeStatus::UNCHANGED;
8620 return A.manifestAttrs(IRP, Attribute::getWithMemoryEffects(
8625 bool checkForAllAccessesToMemoryKind(
8627 MemoryLocationsKind)>
8629 MemoryLocationsKind RequestedMLK)
const override {
8630 if (!isValidState())
8633 MemoryLocationsKind AssumedMLK = getAssumedNotAccessedLocation();
8634 if (AssumedMLK == NO_LOCATIONS)
8638 for (MemoryLocationsKind CurMLK = 1; CurMLK < NO_LOCATIONS;
8639 CurMLK *= 2, ++
Idx) {
8640 if (CurMLK & RequestedMLK)
8643 if (
const AccessSet *
Accesses = AccessKind2Accesses[Idx])
8644 for (
const AccessInfo &AI : *
Accesses)
8645 if (!Pred(AI.I, AI.Ptr, AI.Kind, CurMLK))
8658 MemoryLocationsKind KnownMLK = getKnown();
8660 for (MemoryLocationsKind CurMLK = 1; CurMLK < NO_LOCATIONS; CurMLK *= 2)
8661 if (!(CurMLK & KnownMLK))
8662 updateStateAndAccessesMap(getState(), CurMLK,
I,
nullptr,
Changed,
8663 getAccessKindFromInst(
I));
8664 return AAMemoryLocation::indicatePessimisticFixpoint();
8684 bool operator()(
const AccessInfo &
LHS,
const AccessInfo &
RHS)
const {
8688 return LHS.Ptr <
RHS.Ptr;
8689 if (
LHS.Kind !=
RHS.Kind)
8690 return LHS.Kind <
RHS.Kind;
8697 using AccessSet = SmallSet<AccessInfo, 2, AccessInfo>;
8698 std::array<AccessSet *, llvm::ConstantLog2<VALID_STATE>()>
8699 AccessKind2Accesses;
8704 categorizeArgumentPointerLocations(Attributor &
A, CallBase &CB,
8705 AAMemoryLocation::StateType &AccessedLocs,
8710 categorizeAccessedLocations(Attributor &
A, Instruction &
I,
bool &
Changed);
8713 AccessKind getAccessKindFromInst(
const Instruction *
I) {
8716 AK =
I->mayReadFromMemory() ? READ :
NONE;
8725 void updateStateAndAccessesMap(AAMemoryLocation::StateType &State,
8726 MemoryLocationsKind MLK,
const Instruction *
I,
8735 if (MLK == NO_UNKOWN_MEM)
8737 State.removeAssumedBits(MLK);
8742 void categorizePtrValue(Attributor &
A,
const Instruction &
I,
const Value &Ptr,
8743 AAMemoryLocation::StateType &State,
bool &
Changed,
8744 unsigned AccessAS = 0);
8750void AAMemoryLocationImpl::categorizePtrValue(
8751 Attributor &
A,
const Instruction &
I,
const Value &Ptr,
8753 LLVM_DEBUG(
dbgs() <<
"[AAMemoryLocation] Categorize pointer locations for "
8758 unsigned ObjectAS =
Obj.getType()->getPointerAddressSpace();
8760 MemoryLocationsKind MLK = NO_LOCATIONS;
8780 MLK = NO_ARGUMENT_MEM;
8786 if (GVar->isConstant())
8789 if (GV->hasLocalLinkage())
8790 MLK = NO_GLOBAL_INTERNAL_MEM;
8792 MLK = NO_GLOBAL_EXTERNAL_MEM;
8801 bool IsKnownNoAlias;
8805 MLK = NO_MALLOCED_MEM;
8807 MLK = NO_UNKOWN_MEM;
8809 MLK = NO_UNKOWN_MEM;
8812 assert(MLK != NO_LOCATIONS &&
"No location specified!");
8813 LLVM_DEBUG(
dbgs() <<
"[AAMemoryLocation] Ptr value can be categorized: "
8814 << Obj <<
" -> " << getMemoryLocationsAsStr(MLK) <<
"\n");
8816 getAccessKindFromInst(&
I));
8821 const auto *AA =
A.getAAFor<AAUnderlyingObjects>(
8825 dbgs() <<
"[AAMemoryLocation] Pointer locations not categorized\n");
8826 updateStateAndAccessesMap(
State, NO_UNKOWN_MEM, &
I,
nullptr,
Changed,
8827 getAccessKindFromInst(&
I));
8832 dbgs() <<
"[AAMemoryLocation] Accessed locations with pointer locations: "
8836void AAMemoryLocationImpl::categorizeArgumentPointerLocations(
8839 for (
unsigned ArgNo = 0,
E = CB.
arg_size(); ArgNo <
E; ++ArgNo) {
8848 const auto *ArgOpMemLocationAA =
8851 if (ArgOpMemLocationAA && ArgOpMemLocationAA->isAssumedReadNone())
8856 categorizePtrValue(
A, CB, *ArgOp, AccessedLocs,
Changed);
8861AAMemoryLocationImpl::categorizeAccessedLocations(Attributor &
A, Instruction &
I,
8863 LLVM_DEBUG(
dbgs() <<
"[AAMemoryLocation] Categorize accessed locations for "
8867 AccessedLocs.intersectAssumedBits(NO_LOCATIONS);
8872 const auto *CBMemLocationAA =
A.getAAFor<AAMemoryLocation>(
8875 <<
" [" << CBMemLocationAA <<
"]\n");
8876 if (!CBMemLocationAA) {
8877 updateStateAndAccessesMap(AccessedLocs, NO_UNKOWN_MEM, &
I,
nullptr,
8878 Changed, getAccessKindFromInst(&
I));
8879 return NO_UNKOWN_MEM;
8882 if (CBMemLocationAA->isAssumedReadNone())
8883 return NO_LOCATIONS;
8885 if (CBMemLocationAA->isAssumedInaccessibleMemOnly()) {
8886 updateStateAndAccessesMap(AccessedLocs, NO_INACCESSIBLE_MEM, &
I,
nullptr,
8887 Changed, getAccessKindFromInst(&
I));
8888 return AccessedLocs.getAssumed();
8891 uint32_t CBAssumedNotAccessedLocs =
8892 CBMemLocationAA->getAssumedNotAccessedLocation();
8895 uint32_t CBAssumedNotAccessedLocsNoArgMem =
8896 CBAssumedNotAccessedLocs | NO_ARGUMENT_MEM | NO_GLOBAL_MEM;
8898 for (MemoryLocationsKind CurMLK = 1; CurMLK < NO_LOCATIONS; CurMLK *= 2) {
8899 if (CBAssumedNotAccessedLocsNoArgMem & CurMLK)
8901 updateStateAndAccessesMap(AccessedLocs, CurMLK, &
I,
nullptr,
Changed,
8902 getAccessKindFromInst(&
I));
8907 bool HasGlobalAccesses = ((~CBAssumedNotAccessedLocs) & NO_GLOBAL_MEM);
8908 if (HasGlobalAccesses) {
8911 updateStateAndAccessesMap(AccessedLocs, MLK, &
I, Ptr,
Changed,
8912 getAccessKindFromInst(&
I));
8915 if (!CBMemLocationAA->checkForAllAccessesToMemoryKind(
8916 AccessPred, inverseLocation(NO_GLOBAL_MEM,
false,
false)))
8917 return AccessedLocs.getWorstState();
8921 dbgs() <<
"[AAMemoryLocation] Accessed state before argument handling: "
8922 << getMemoryLocationsAsStr(AccessedLocs.getAssumed()) <<
"\n");
8925 bool HasArgAccesses = ((~CBAssumedNotAccessedLocs) & NO_ARGUMENT_MEM);
8927 categorizeArgumentPointerLocations(
A, *CB, AccessedLocs,
Changed);
8930 dbgs() <<
"[AAMemoryLocation] Accessed state after argument handling: "
8931 << getMemoryLocationsAsStr(AccessedLocs.getAssumed()) <<
"\n");
8933 return AccessedLocs.getAssumed();
8938 dbgs() <<
"[AAMemoryLocation] Categorize memory access with pointer: "
8939 <<
I <<
" [" << *Ptr <<
"]\n");
8940 categorizePtrValue(
A,
I, *Ptr, AccessedLocs,
Changed,
8941 Ptr->getType()->getPointerAddressSpace());
8942 return AccessedLocs.getAssumed();
8945 LLVM_DEBUG(
dbgs() <<
"[AAMemoryLocation] Failed to categorize instruction: "
8947 updateStateAndAccessesMap(AccessedLocs, NO_UNKOWN_MEM, &
I,
nullptr,
Changed,
8948 getAccessKindFromInst(&
I));
8949 return AccessedLocs.getAssumed();
8953struct AAMemoryLocationFunction final :
public AAMemoryLocationImpl {
8954 AAMemoryLocationFunction(
const IRPosition &IRP, Attributor &
A)
8955 : AAMemoryLocationImpl(IRP,
A) {}
8960 const auto *MemBehaviorAA =
8961 A.getAAFor<AAMemoryBehavior>(*
this, getIRPosition(), DepClassTy::NONE);
8964 return indicateOptimisticFixpoint();
8966 "AAMemoryLocation was not read-none but AAMemoryBehavior was!");
8967 A.recordDependence(*MemBehaviorAA, *
this, DepClassTy::OPTIONAL);
8968 return ChangeStatus::UNCHANGED;
8972 auto AssumedState = getAssumed();
8976 MemoryLocationsKind MLK = categorizeAccessedLocations(
A,
I,
Changed);
8977 LLVM_DEBUG(
dbgs() <<
"[AAMemoryLocation] Accessed locations for " <<
I
8978 <<
": " << getMemoryLocationsAsStr(MLK) <<
"\n");
8979 removeAssumedBits(inverseLocation(MLK,
false,
false));
8982 return getAssumedNotAccessedLocation() != VALID_STATE;
8985 bool UsedAssumedInformation =
false;
8986 if (!
A.checkForAllReadWriteInstructions(CheckRWInst, *
this,
8987 UsedAssumedInformation))
8988 return indicatePessimisticFixpoint();
8990 Changed |= AssumedState != getAssumed();
8991 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
8995 void trackStatistics()
const override {
8998 else if (isAssumedArgMemOnly())
9000 else if (isAssumedInaccessibleMemOnly())
9002 else if (isAssumedInaccessibleOrArgMemOnly())
9008struct AAMemoryLocationCallSite final : AAMemoryLocationImpl {
9009 AAMemoryLocationCallSite(
const IRPosition &IRP, Attributor &
A)
9010 : AAMemoryLocationImpl(IRP,
A) {}
9021 A.getAAFor<AAMemoryLocation>(*
this, FnPos, DepClassTy::REQUIRED);
9023 return indicatePessimisticFixpoint();
9027 updateStateAndAccessesMap(getState(), MLK,
I, Ptr,
Changed,
9028 getAccessKindFromInst(
I));
9031 if (!FnAA->checkForAllAccessesToMemoryKind(AccessPred, ALL_LOCATIONS))
9032 return indicatePessimisticFixpoint();
9033 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
9037 void trackStatistics()
const override {
9047struct AADenormalFPMathImpl :
public AADenormalFPMath {
9048 AADenormalFPMathImpl(
const IRPosition &IRP, Attributor &
A)
9049 : AADenormalFPMath(IRP,
A) {}
9051 const std::string getAsStr(Attributor *
A)
const override {
9052 std::string Str(
"AADenormalFPMath[");
9053 raw_string_ostream OS(Str);
9055 DenormalState
Known = getKnown();
9056 if (
Known.Mode.isValid())
9057 OS <<
"denormal-fp-math=" <<
Known.Mode;
9061 if (
Known.ModeF32.isValid())
9062 OS <<
" denormal-fp-math-f32=" <<
Known.ModeF32;
9068struct AADenormalFPMathFunction final : AADenormalFPMathImpl {
9069 AADenormalFPMathFunction(
const IRPosition &IRP, Attributor &
A)
9070 : AADenormalFPMathImpl(IRP,
A) {}
9074 DenormalFPEnv DenormEnv =
F->getDenormalFPEnv();
9084 auto CheckCallSite = [=, &Change, &
A](AbstractCallSite CS) {
9087 <<
"->" << getAssociatedFunction()->
getName() <<
'\n');
9089 const auto *CallerInfo =
A.getAAFor<AADenormalFPMath>(
9095 CallerInfo->getState());
9099 bool AllCallSitesKnown =
true;
9100 if (!
A.checkForAllCallSites(CheckCallSite, *
this,
true, AllCallSitesKnown))
9101 return indicatePessimisticFixpoint();
9103 if (Change == ChangeStatus::CHANGED && isModeFixed())
9109 LLVMContext &Ctx = getAssociatedFunction()->getContext();
9115 DenormalFPEnv KnownEnv(
Known.Mode,
Known.ModeF32);
9118 AttrToRemove.
push_back(Attribute::DenormalFPEnv);
9121 Ctx, Attribute::DenormalFPEnv,
9122 DenormalFPEnv(
Known.Mode,
Known.ModeF32).toIntValue()));
9125 auto &IRP = getIRPosition();
9128 return A.removeAttrs(IRP, AttrToRemove) |
9129 A.manifestAttrs(IRP, AttrToAdd,
true);
9132 void trackStatistics()
const override {
9141struct AAValueConstantRangeImpl : AAValueConstantRange {
9142 using StateType = IntegerRangeState;
9143 AAValueConstantRangeImpl(
const IRPosition &IRP, Attributor &
A)
9144 : AAValueConstantRange(IRP,
A) {}
9148 if (
A.hasSimplificationCallback(getIRPosition())) {
9149 indicatePessimisticFixpoint();
9154 intersectKnown(getConstantRangeFromSCEV(
A, getCtxI()));
9157 intersectKnown(getConstantRangeFromLVI(
A, getCtxI()));
9161 const std::string getAsStr(Attributor *
A)
const override {
9163 llvm::raw_string_ostream OS(Str);
9165 getKnown().print(OS);
9167 getAssumed().print(OS);
9174 const SCEV *getSCEV(Attributor &
A,
const Instruction *
I =
nullptr)
const {
9175 if (!getAnchorScope())
9178 ScalarEvolution *SE =
9179 A.getInfoCache().getAnalysisResultForFunction<ScalarEvolutionAnalysis>(
9182 LoopInfo *LI =
A.getInfoCache().getAnalysisResultForFunction<LoopAnalysis>(
9188 const SCEV *S = SE->
getSCEV(&getAssociatedValue());
9197 ConstantRange getConstantRangeFromSCEV(Attributor &
A,
9198 const Instruction *
I =
nullptr)
const {
9199 if (!getAnchorScope())
9202 ScalarEvolution *SE =
9203 A.getInfoCache().getAnalysisResultForFunction<ScalarEvolutionAnalysis>(
9206 const SCEV *S = getSCEV(
A,
I);
9216 getConstantRangeFromLVI(Attributor &
A,
9217 const Instruction *CtxI =
nullptr)
const {
9218 if (!getAnchorScope())
9221 LazyValueInfo *LVI =
9222 A.getInfoCache().getAnalysisResultForFunction<LazyValueAnalysis>(
9237 bool isValidCtxInstructionForOutsideAnalysis(Attributor &
A,
9238 const Instruction *CtxI,
9239 bool AllowAACtxI)
const {
9240 if (!CtxI || (!AllowAACtxI && CtxI == getCtxI()))
9252 InformationCache &InfoCache =
A.getInfoCache();
9253 const DominatorTree *DT =
9264 getAssumedConstantRange(Attributor &
A,
9265 const Instruction *CtxI =
nullptr)
const override {
9270 if (!isValidCtxInstructionForOutsideAnalysis(
A, CtxI,
9272 return getAssumed();
9274 ConstantRange LVIR = getConstantRangeFromLVI(
A, CtxI);
9275 ConstantRange SCEVR = getConstantRangeFromSCEV(
A, CtxI);
9276 return getAssumed().intersectWith(SCEVR).intersectWith(LVIR);
9281 getMDNodeForConstantRange(
Type *Ty, LLVMContext &Ctx,
9282 const ConstantRange &AssumedConstantRange) {
9284 Ty, AssumedConstantRange.
getLower())),
9286 Ty, AssumedConstantRange.
getUpper()))};
9291 static bool isBetterRange(
const ConstantRange &Assumed,
9292 const Instruction &
I) {
9296 std::optional<ConstantRange>
Known;
9300 }
else if (MDNode *KnownRanges =
I.getMetadata(LLVMContext::MD_range)) {
9306 if (KnownRanges->getNumOperands() > 2)
9309 ConstantInt *
Lower =
9311 ConstantInt *
Upper =
9321 setRangeMetadataIfisBetterRange(Instruction *
I,
9322 const ConstantRange &AssumedConstantRange) {
9323 if (isBetterRange(AssumedConstantRange, *
I)) {
9324 I->setMetadata(LLVMContext::MD_range,
9325 getMDNodeForConstantRange(
I->getType(),
I->getContext(),
9326 AssumedConstantRange));
9333 setRangeRetAttrIfisBetterRange(Attributor &
A,
const IRPosition &IRP,
9335 const ConstantRange &AssumedConstantRange) {
9336 if (isBetterRange(AssumedConstantRange, *
I)) {
9337 A.manifestAttrs(IRP,
9338 Attribute::get(
I->getContext(), Attribute::Range,
9339 AssumedConstantRange),
9349 ConstantRange AssumedConstantRange = getAssumedConstantRange(
A);
9352 auto &
V = getAssociatedValue();
9356 assert(
I == getCtxI() &&
"Should not annotate an instruction which is "
9357 "not the context instruction");
9359 if (setRangeMetadataIfisBetterRange(
I, AssumedConstantRange))
9360 Changed = ChangeStatus::CHANGED;
9362 if (setRangeRetAttrIfisBetterRange(
A, getIRPosition(),
I,
9363 AssumedConstantRange))
9364 Changed = ChangeStatus::CHANGED;
9372struct AAValueConstantRangeArgument final
9373 : AAArgumentFromCallSiteArguments<
9374 AAValueConstantRange, AAValueConstantRangeImpl, IntegerRangeState,
9376 using Base = AAArgumentFromCallSiteArguments<
9377 AAValueConstantRange, AAValueConstantRangeImpl, IntegerRangeState,
9379 AAValueConstantRangeArgument(
const IRPosition &IRP, Attributor &
A)
9383 void trackStatistics()
const override {
9388struct AAValueConstantRangeReturned
9389 : AAReturnedFromReturnedValues<AAValueConstantRange,
9390 AAValueConstantRangeImpl,
9391 AAValueConstantRangeImpl::StateType,
9394 AAReturnedFromReturnedValues<AAValueConstantRange,
9395 AAValueConstantRangeImpl,
9396 AAValueConstantRangeImpl::StateType,
9398 AAValueConstantRangeReturned(
const IRPosition &IRP, Attributor &
A)
9403 if (!
A.isFunctionIPOAmendable(*getAssociatedFunction()))
9404 indicatePessimisticFixpoint();
9408 void trackStatistics()
const override {
9413struct AAValueConstantRangeFloating : AAValueConstantRangeImpl {
9414 AAValueConstantRangeFloating(
const IRPosition &IRP, Attributor &
A)
9415 : AAValueConstantRangeImpl(IRP,
A) {}
9419 AAValueConstantRangeImpl::initialize(
A);
9423 Value &
V = getAssociatedValue();
9426 unionAssumed(ConstantRange(
C->getValue()));
9427 indicateOptimisticFixpoint();
9433 unionAssumed(ConstantRange(APInt(
getBitWidth(), 0)));
9434 indicateOptimisticFixpoint();
9446 if (
auto *RangeMD = LI->getMetadata(LLVMContext::MD_range)) {
9457 indicatePessimisticFixpoint();
9460 << getAssociatedValue() <<
"\n");
9463 bool calculateBinaryOperator(
9464 Attributor &
A, BinaryOperator *BinOp, IntegerRangeState &
T,
9465 const Instruction *CtxI,
9466 SmallVectorImpl<const AAValueConstantRange *> &QuerriedAAs) {
9471 bool UsedAssumedInformation =
false;
9472 const auto &SimplifiedLHS =
A.getAssumedSimplified(
9475 if (!SimplifiedLHS.has_value())
9477 if (!*SimplifiedLHS)
9479 LHS = *SimplifiedLHS;
9481 const auto &SimplifiedRHS =
A.getAssumedSimplified(
9484 if (!SimplifiedRHS.has_value())
9486 if (!*SimplifiedRHS)
9488 RHS = *SimplifiedRHS;
9494 auto *LHSAA =
A.getAAFor<AAValueConstantRange>(
9496 DepClassTy::REQUIRED);
9500 auto LHSAARange = LHSAA->getAssumedConstantRange(
A, CtxI);
9502 auto *RHSAA =
A.getAAFor<AAValueConstantRange>(
9504 DepClassTy::REQUIRED);
9508 auto RHSAARange = RHSAA->getAssumedConstantRange(
A, CtxI);
9510 auto AssumedRange = LHSAARange.binaryOp(BinOp->
getOpcode(), RHSAARange);
9512 T.unionAssumed(AssumedRange);
9516 return T.isValidState();
9519 bool calculateCastInst(
9520 Attributor &
A, CastInst *CastI, IntegerRangeState &
T,
9521 const Instruction *CtxI,
9522 SmallVectorImpl<const AAValueConstantRange *> &QuerriedAAs) {
9528 bool UsedAssumedInformation =
false;
9529 const auto &SimplifiedOpV =
A.getAssumedSimplified(
9532 if (!SimplifiedOpV.has_value())
9534 if (!*SimplifiedOpV)
9536 OpV = *SimplifiedOpV;
9541 auto *OpAA =
A.getAAFor<AAValueConstantRange>(
9543 DepClassTy::REQUIRED);
9547 T.unionAssumed(OpAA->getAssumed().castOp(CastI->
getOpcode(),
9549 return T.isValidState();
9553 calculateCmpInst(Attributor &
A, CmpInst *CmpI, IntegerRangeState &
T,
9554 const Instruction *CtxI,
9555 SmallVectorImpl<const AAValueConstantRange *> &QuerriedAAs) {
9560 bool UsedAssumedInformation =
false;
9561 const auto &SimplifiedLHS =
A.getAssumedSimplified(
9564 if (!SimplifiedLHS.has_value())
9566 if (!*SimplifiedLHS)
9568 LHS = *SimplifiedLHS;
9570 const auto &SimplifiedRHS =
A.getAssumedSimplified(
9573 if (!SimplifiedRHS.has_value())
9575 if (!*SimplifiedRHS)
9577 RHS = *SimplifiedRHS;
9583 auto *LHSAA =
A.getAAFor<AAValueConstantRange>(
9585 DepClassTy::REQUIRED);
9589 auto *RHSAA =
A.getAAFor<AAValueConstantRange>(
9591 DepClassTy::REQUIRED);
9595 auto LHSAARange = LHSAA->getAssumedConstantRange(
A, CtxI);
9596 auto RHSAARange = RHSAA->getAssumedConstantRange(
A, CtxI);
9599 if (LHSAARange.isEmptySet() || RHSAARange.isEmptySet())
9602 bool MustTrue =
false, MustFalse =
false;
9604 auto AllowedRegion =
9607 if (AllowedRegion.intersectWith(LHSAARange).isEmptySet())
9613 assert((!MustTrue || !MustFalse) &&
9614 "Either MustTrue or MustFalse should be false!");
9617 T.unionAssumed(ConstantRange(APInt( 1, 1)));
9619 T.unionAssumed(ConstantRange(APInt( 1, 0)));
9621 T.unionAssumed(ConstantRange( 1,
true));
9623 LLVM_DEBUG(
dbgs() <<
"[AAValueConstantRange] " << *CmpI <<
" after "
9624 << (MustTrue ?
"true" : (MustFalse ?
"false" :
"unknown"))
9625 <<
": " <<
T <<
"\n\t" << *LHSAA <<
"\t<op>\n\t"
9629 return T.isValidState();
9641 bool UsedAssumedInformation =
false;
9642 const auto &SimplifiedOpV =
A.getAssumedSimplified(
9645 if (!SimplifiedOpV.has_value())
9647 if (!*SimplifiedOpV)
9649 Value *VPtr = *SimplifiedOpV;
9652 const auto *AA =
A.getAAFor<AAValueConstantRange>(
9654 DepClassTy::REQUIRED);
9658 T.unionAssumed(AA->getAssumedConstantRange(
A, CtxI));
9662 return T.isValidState();
9667 if (!calculateBinaryOperator(
A, BinOp,
T, CtxI, QuerriedAAs))
9670 if (!calculateCmpInst(
A, CmpI,
T, CtxI, QuerriedAAs))
9673 if (!calculateCastInst(
A, CastI,
T, CtxI, QuerriedAAs))
9679 T.indicatePessimisticFixpoint();
9686 for (
const AAValueConstantRange *QueriedAA : QuerriedAAs) {
9687 if (QueriedAA !=
this)
9690 if (
T.getAssumed() == getState().getAssumed())
9692 T.indicatePessimisticFixpoint();
9695 return T.isValidState();
9698 if (!VisitValueCB(getAssociatedValue(), getCtxI()))
9699 return indicatePessimisticFixpoint();
9704 return ChangeStatus::UNCHANGED;
9705 if (++NumChanges > MaxNumChanges) {
9706 LLVM_DEBUG(
dbgs() <<
"[AAValueConstantRange] performed " << NumChanges
9707 <<
" but only " << MaxNumChanges
9708 <<
" are allowed to avoid cyclic reasoning.");
9709 return indicatePessimisticFixpoint();
9711 return ChangeStatus::CHANGED;
9715 void trackStatistics()
const override {
9724 static constexpr int MaxNumChanges = 5;
9727struct AAValueConstantRangeFunction : AAValueConstantRangeImpl {
9728 AAValueConstantRangeFunction(
const IRPosition &IRP, Attributor &
A)
9729 : AAValueConstantRangeImpl(IRP,
A) {}
9733 llvm_unreachable(
"AAValueConstantRange(Function|CallSite)::updateImpl will "
9741struct AAValueConstantRangeCallSite : AAValueConstantRangeFunction {
9742 AAValueConstantRangeCallSite(
const IRPosition &IRP, Attributor &
A)
9743 : AAValueConstantRangeFunction(IRP,
A) {}
9749struct AAValueConstantRangeCallSiteReturned
9750 : AACalleeToCallSite<AAValueConstantRange, AAValueConstantRangeImpl,
9751 AAValueConstantRangeImpl::StateType,
9753 AAValueConstantRangeCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
9754 : AACalleeToCallSite<AAValueConstantRange, AAValueConstantRangeImpl,
9755 AAValueConstantRangeImpl::StateType,
9762 if (std::optional<ConstantRange>
Range = CI->getRange())
9763 intersectKnown(*
Range);
9766 AAValueConstantRangeImpl::initialize(
A);
9770 void trackStatistics()
const override {
9774struct AAValueConstantRangeCallSiteArgument : AAValueConstantRangeFloating {
9775 AAValueConstantRangeCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
9776 : AAValueConstantRangeFloating(IRP,
A) {}
9780 return ChangeStatus::UNCHANGED;
9784 void trackStatistics()
const override {
9793struct AAPotentialConstantValuesImpl : AAPotentialConstantValues {
9796 AAPotentialConstantValuesImpl(
const IRPosition &IRP, Attributor &
A)
9797 : AAPotentialConstantValues(IRP,
A) {}
9801 if (
A.hasSimplificationCallback(getIRPosition()))
9802 indicatePessimisticFixpoint();
9804 AAPotentialConstantValues::initialize(
A);
9807 bool fillSetWithConstantValues(Attributor &
A,
const IRPosition &IRP, SetTy &S,
9808 bool &ContainsUndef,
bool ForSelf) {
9810 bool UsedAssumedInformation =
false;
9812 UsedAssumedInformation)) {
9819 auto *PotentialValuesAA =
A.getAAFor<AAPotentialConstantValues>(
9820 *
this, IRP, DepClassTy::REQUIRED);
9821 if (!PotentialValuesAA || !PotentialValuesAA->getState().isValidState())
9823 ContainsUndef = PotentialValuesAA->getState().undefIsContained();
9824 S = PotentialValuesAA->getState().getAssumedSet();
9831 ContainsUndef =
false;
9832 for (
auto &It :
Values) {
9834 ContainsUndef =
true;
9840 S.insert(CI->getValue());
9842 ContainsUndef &= S.empty();
9848 const std::string getAsStr(Attributor *
A)
const override {
9850 llvm::raw_string_ostream OS(Str);
9857 return indicatePessimisticFixpoint();
9861struct AAPotentialConstantValuesArgument final
9862 : AAArgumentFromCallSiteArguments<AAPotentialConstantValues,
9863 AAPotentialConstantValuesImpl,
9864 PotentialConstantIntValuesState> {
9865 using Base = AAArgumentFromCallSiteArguments<AAPotentialConstantValues,
9866 AAPotentialConstantValuesImpl,
9868 AAPotentialConstantValuesArgument(
const IRPosition &IRP, Attributor &
A)
9872 void trackStatistics()
const override {
9877struct AAPotentialConstantValuesReturned
9878 : AAReturnedFromReturnedValues<AAPotentialConstantValues,
9879 AAPotentialConstantValuesImpl> {
9880 using Base = AAReturnedFromReturnedValues<AAPotentialConstantValues,
9881 AAPotentialConstantValuesImpl>;
9882 AAPotentialConstantValuesReturned(
const IRPosition &IRP, Attributor &
A)
9886 if (!
A.isFunctionIPOAmendable(*getAssociatedFunction()))
9887 indicatePessimisticFixpoint();
9888 Base::initialize(
A);
9892 void trackStatistics()
const override {
9897struct AAPotentialConstantValuesFloating : AAPotentialConstantValuesImpl {
9898 AAPotentialConstantValuesFloating(
const IRPosition &IRP, Attributor &
A)
9899 : AAPotentialConstantValuesImpl(IRP,
A) {}
9903 AAPotentialConstantValuesImpl::initialize(
A);
9907 Value &
V = getAssociatedValue();
9910 unionAssumed(
C->getValue());
9911 indicateOptimisticFixpoint();
9916 unionAssumedWithUndef();
9917 indicateOptimisticFixpoint();
9927 indicatePessimisticFixpoint();
9930 << getAssociatedValue() <<
"\n");
9933 static bool calculateICmpInst(
const ICmpInst *ICI,
const APInt &
LHS,
9938 static APInt calculateCastInst(
const CastInst *CI,
const APInt &Src,
9939 uint32_t ResultBitWidth) {
9944 case Instruction::Trunc:
9945 return Src.trunc(ResultBitWidth);
9946 case Instruction::SExt:
9947 return Src.sext(ResultBitWidth);
9948 case Instruction::ZExt:
9949 return Src.zext(ResultBitWidth);
9950 case Instruction::BitCast:
9955 static APInt calculateBinaryOperator(
const BinaryOperator *BinOp,
9956 const APInt &
LHS,
const APInt &
RHS,
9957 bool &SkipOperation,
bool &Unsupported) {
9964 switch (BinOpcode) {
9968 case Instruction::Add:
9970 case Instruction::Sub:
9972 case Instruction::Mul:
9974 case Instruction::UDiv:
9976 SkipOperation =
true;
9980 case Instruction::SDiv:
9982 SkipOperation =
true;
9986 case Instruction::URem:
9988 SkipOperation =
true;
9992 case Instruction::SRem:
9994 SkipOperation =
true;
9998 case Instruction::Shl:
10000 case Instruction::LShr:
10002 case Instruction::AShr:
10004 case Instruction::And:
10006 case Instruction::Or:
10008 case Instruction::Xor:
10013 bool calculateBinaryOperatorAndTakeUnion(
const BinaryOperator *BinOp,
10014 const APInt &
LHS,
const APInt &
RHS) {
10015 bool SkipOperation =
false;
10018 calculateBinaryOperator(BinOp,
LHS,
RHS, SkipOperation, Unsupported);
10022 if (!SkipOperation)
10023 unionAssumed(Result);
10024 return isValidState();
10027 ChangeStatus updateWithICmpInst(Attributor &
A, ICmpInst *ICI) {
10028 auto AssumedBefore = getAssumed();
10032 bool LHSContainsUndef =
false, RHSContainsUndef =
false;
10033 SetTy LHSAAPVS, RHSAAPVS;
10035 LHSContainsUndef,
false) ||
10037 RHSContainsUndef,
false))
10038 return indicatePessimisticFixpoint();
10041 bool MaybeTrue =
false, MaybeFalse =
false;
10043 if (LHSContainsUndef && RHSContainsUndef) {
10046 unionAssumedWithUndef();
10047 }
else if (LHSContainsUndef) {
10048 for (
const APInt &R : RHSAAPVS) {
10049 bool CmpResult = calculateICmpInst(ICI, Zero, R);
10050 MaybeTrue |= CmpResult;
10051 MaybeFalse |= !CmpResult;
10052 if (MaybeTrue & MaybeFalse)
10053 return indicatePessimisticFixpoint();
10055 }
else if (RHSContainsUndef) {
10056 for (
const APInt &L : LHSAAPVS) {
10057 bool CmpResult = calculateICmpInst(ICI, L, Zero);
10058 MaybeTrue |= CmpResult;
10059 MaybeFalse |= !CmpResult;
10060 if (MaybeTrue & MaybeFalse)
10061 return indicatePessimisticFixpoint();
10064 for (
const APInt &L : LHSAAPVS) {
10065 for (
const APInt &R : RHSAAPVS) {
10066 bool CmpResult = calculateICmpInst(ICI, L, R);
10067 MaybeTrue |= CmpResult;
10068 MaybeFalse |= !CmpResult;
10069 if (MaybeTrue & MaybeFalse)
10070 return indicatePessimisticFixpoint();
10075 unionAssumed(APInt( 1, 1));
10077 unionAssumed(APInt( 1, 0));
10078 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10079 : ChangeStatus::CHANGED;
10082 ChangeStatus updateWithSelectInst(Attributor &
A, SelectInst *SI) {
10083 auto AssumedBefore = getAssumed();
10087 bool UsedAssumedInformation =
false;
10088 std::optional<Constant *>
C =
A.getAssumedConstant(
10089 *
SI->getCondition(), *
this, UsedAssumedInformation);
10092 bool OnlyLeft =
false, OnlyRight =
false;
10093 if (
C && *
C && (*C)->isOneValue())
10095 else if (
C && *
C && (*C)->isNullValue())
10098 bool LHSContainsUndef =
false, RHSContainsUndef =
false;
10099 SetTy LHSAAPVS, RHSAAPVS;
10102 LHSContainsUndef,
false))
10103 return indicatePessimisticFixpoint();
10107 RHSContainsUndef,
false))
10108 return indicatePessimisticFixpoint();
10110 if (OnlyLeft || OnlyRight) {
10112 auto *OpAA = OnlyLeft ? &LHSAAPVS : &RHSAAPVS;
10113 auto Undef = OnlyLeft ? LHSContainsUndef : RHSContainsUndef;
10116 unionAssumedWithUndef();
10118 for (
const auto &It : *OpAA)
10122 }
else if (LHSContainsUndef && RHSContainsUndef) {
10124 unionAssumedWithUndef();
10126 for (
const auto &It : LHSAAPVS)
10128 for (
const auto &It : RHSAAPVS)
10131 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10132 : ChangeStatus::CHANGED;
10135 ChangeStatus updateWithCastInst(Attributor &
A, CastInst *CI) {
10136 auto AssumedBefore = getAssumed();
10138 return indicatePessimisticFixpoint();
10143 bool SrcContainsUndef =
false;
10146 SrcContainsUndef,
false))
10147 return indicatePessimisticFixpoint();
10149 if (SrcContainsUndef)
10150 unionAssumedWithUndef();
10152 for (
const APInt &S : SrcPVS) {
10153 APInt
T = calculateCastInst(CI, S, ResultBitWidth);
10157 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10158 : ChangeStatus::CHANGED;
10161 ChangeStatus updateWithBinaryOperator(Attributor &
A, BinaryOperator *BinOp) {
10162 auto AssumedBefore = getAssumed();
10166 bool LHSContainsUndef =
false, RHSContainsUndef =
false;
10167 SetTy LHSAAPVS, RHSAAPVS;
10169 LHSContainsUndef,
false) ||
10171 RHSContainsUndef,
false))
10172 return indicatePessimisticFixpoint();
10177 if (LHSContainsUndef && RHSContainsUndef) {
10178 if (!calculateBinaryOperatorAndTakeUnion(BinOp, Zero, Zero))
10179 return indicatePessimisticFixpoint();
10180 }
else if (LHSContainsUndef) {
10181 for (
const APInt &R : RHSAAPVS) {
10182 if (!calculateBinaryOperatorAndTakeUnion(BinOp, Zero, R))
10183 return indicatePessimisticFixpoint();
10185 }
else if (RHSContainsUndef) {
10186 for (
const APInt &L : LHSAAPVS) {
10187 if (!calculateBinaryOperatorAndTakeUnion(BinOp, L, Zero))
10188 return indicatePessimisticFixpoint();
10191 for (
const APInt &L : LHSAAPVS) {
10192 for (
const APInt &R : RHSAAPVS) {
10193 if (!calculateBinaryOperatorAndTakeUnion(BinOp, L, R))
10194 return indicatePessimisticFixpoint();
10198 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10199 : ChangeStatus::CHANGED;
10202 ChangeStatus updateWithInstruction(Attributor &
A, Instruction *Inst) {
10203 auto AssumedBefore = getAssumed();
10205 bool ContainsUndef;
10207 ContainsUndef,
true))
10208 return indicatePessimisticFixpoint();
10209 if (ContainsUndef) {
10210 unionAssumedWithUndef();
10212 for (
const auto &It : Incoming)
10215 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10216 : ChangeStatus::CHANGED;
10221 Value &
V = getAssociatedValue();
10225 return updateWithICmpInst(
A, ICI);
10228 return updateWithSelectInst(
A, SI);
10231 return updateWithCastInst(
A, CI);
10234 return updateWithBinaryOperator(
A, BinOp);
10237 return updateWithInstruction(
A,
I);
10239 return indicatePessimisticFixpoint();
10243 void trackStatistics()
const override {
10248struct AAPotentialConstantValuesFunction : AAPotentialConstantValuesImpl {
10249 AAPotentialConstantValuesFunction(
const IRPosition &IRP, Attributor &
A)
10250 : AAPotentialConstantValuesImpl(IRP,
A) {}
10255 "AAPotentialConstantValues(Function|CallSite)::updateImpl will "
10260 void trackStatistics()
const override {
10265struct AAPotentialConstantValuesCallSite : AAPotentialConstantValuesFunction {
10266 AAPotentialConstantValuesCallSite(
const IRPosition &IRP, Attributor &
A)
10267 : AAPotentialConstantValuesFunction(IRP,
A) {}
10270 void trackStatistics()
const override {
10275struct AAPotentialConstantValuesCallSiteReturned
10276 : AACalleeToCallSite<AAPotentialConstantValues,
10277 AAPotentialConstantValuesImpl> {
10278 AAPotentialConstantValuesCallSiteReturned(
const IRPosition &IRP,
10280 : AACalleeToCallSite<AAPotentialConstantValues,
10281 AAPotentialConstantValuesImpl>(IRP,
A) {}
10284 void trackStatistics()
const override {
10289struct AAPotentialConstantValuesCallSiteArgument
10290 : AAPotentialConstantValuesFloating {
10291 AAPotentialConstantValuesCallSiteArgument(
const IRPosition &IRP,
10293 : AAPotentialConstantValuesFloating(IRP,
A) {}
10297 AAPotentialConstantValuesImpl::initialize(
A);
10298 if (isAtFixpoint())
10301 Value &
V = getAssociatedValue();
10304 unionAssumed(
C->getValue());
10305 indicateOptimisticFixpoint();
10310 unionAssumedWithUndef();
10311 indicateOptimisticFixpoint();
10318 Value &
V = getAssociatedValue();
10319 auto AssumedBefore = getAssumed();
10320 auto *AA =
A.getAAFor<AAPotentialConstantValues>(
10323 return indicatePessimisticFixpoint();
10324 const auto &S = AA->getAssumed();
10326 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10327 : ChangeStatus::CHANGED;
10331 void trackStatistics()
const override {
10340 bool IgnoreSubsumingPositions) {
10341 assert(ImpliedAttributeKind == Attribute::NoUndef &&
10342 "Unexpected attribute kind");
10343 if (
A.hasAttr(IRP, {Attribute::NoUndef}, IgnoreSubsumingPositions,
10344 Attribute::NoUndef))
10364 Value &V = getAssociatedValue();
10366 indicatePessimisticFixpoint();
10367 assert(!isImpliedByIR(
A, getIRPosition(), Attribute::NoUndef));
10371 bool followUseInMBEC(Attributor &
A,
const Use *U,
const Instruction *
I,
10372 AANoUndef::StateType &State) {
10373 const Value *UseV =
U->get();
10374 const DominatorTree *DT =
nullptr;
10375 AssumptionCache *AC =
nullptr;
10376 InformationCache &InfoCache =
A.getInfoCache();
10382 bool TrackUse =
false;
10391 const std::string getAsStr(Attributor *
A)
const override {
10392 return getAssumed() ?
"noundef" :
"may-undef-or-poison";
10399 bool UsedAssumedInformation =
false;
10400 if (
A.isAssumedDead(getIRPosition(),
nullptr,
nullptr,
10401 UsedAssumedInformation))
10402 return ChangeStatus::UNCHANGED;
10406 if (!
A.getAssumedSimplified(getIRPosition(), *
this, UsedAssumedInformation,
10409 return ChangeStatus::UNCHANGED;
10410 return AANoUndef::manifest(
A);
10414struct AANoUndefFloating :
public AANoUndefImpl {
10415 AANoUndefFloating(
const IRPosition &IRP, Attributor &
A)
10416 : AANoUndefImpl(IRP,
A) {}
10420 AANoUndefImpl::initialize(
A);
10421 if (!getState().isAtFixpoint() && getAnchorScope() &&
10422 !getAnchorScope()->isDeclaration())
10423 if (Instruction *CtxI = getCtxI())
10424 followUsesInMBEC(*
this,
A, getState(), *CtxI);
10429 auto VisitValueCB = [&](
const IRPosition &IRP) ->
bool {
10430 bool IsKnownNoUndef;
10432 A,
this, IRP, DepClassTy::REQUIRED, IsKnownNoUndef);
10436 bool UsedAssumedInformation =
false;
10437 Value *AssociatedValue = &getAssociatedValue();
10439 if (!
A.getAssumedSimplifiedValues(getIRPosition(), *
this,
Values,
10444 Values.size() != 1 ||
Values.front().getValue() != AssociatedValue;
10452 if (AVIRP == getIRPosition() || !VisitValueCB(AVIRP))
10453 return indicatePessimisticFixpoint();
10454 return ChangeStatus::UNCHANGED;
10457 for (
const auto &VAC :
Values)
10459 return indicatePessimisticFixpoint();
10461 return ChangeStatus::UNCHANGED;
10468struct AANoUndefReturned final
10469 : AAReturnedFromReturnedValues<AANoUndef, AANoUndefImpl> {
10470 AANoUndefReturned(
const IRPosition &IRP, Attributor &
A)
10471 : AAReturnedFromReturnedValues<AANoUndef, AANoUndefImpl>(IRP,
A) {}
10477struct AANoUndefArgument final
10478 : AAArgumentFromCallSiteArguments<AANoUndef, AANoUndefImpl> {
10479 AANoUndefArgument(
const IRPosition &IRP, Attributor &
A)
10480 : AAArgumentFromCallSiteArguments<AANoUndef, AANoUndefImpl>(IRP,
A) {}
10486struct AANoUndefCallSiteArgument final : AANoUndefFloating {
10487 AANoUndefCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
10488 : AANoUndefFloating(IRP,
A) {}
10494struct AANoUndefCallSiteReturned final
10495 : AACalleeToCallSite<AANoUndef, AANoUndefImpl> {
10496 AANoUndefCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
10497 : AACalleeToCallSite<AANoUndef, AANoUndefImpl>(IRP,
A) {}
10505struct AANoFPClassImpl : AANoFPClass {
10506 AANoFPClassImpl(
const IRPosition &IRP, Attributor &
A) : AANoFPClass(IRP,
A) {}
10509 const IRPosition &IRP = getIRPosition();
10513 indicateOptimisticFixpoint();
10518 A.getAttrs(getIRPosition(), {Attribute::NoFPClass},
Attrs,
false);
10519 for (
const auto &Attr : Attrs) {
10526 const DataLayout &
DL =
A.getDataLayout();
10527 InformationCache &InfoCache =
A.getInfoCache();
10529 const DominatorTree *DT =
nullptr;
10530 AssumptionCache *AC =
nullptr;
10531 const TargetLibraryInfo *TLI =
nullptr;
10535 if (!
F->isDeclaration()) {
10542 SimplifyQuery Q(
DL, TLI, DT, AC, CtxI);
10549 followUsesInMBEC(*
this,
A, getState(), *CtxI);
10553 bool followUseInMBEC(Attributor &
A,
const Use *U,
const Instruction *
I,
10554 AANoFPClass::StateType &State) {
10565 if (
auto *NoFPAA =
A.getAAFor<AANoFPClass>(*
this, IRP, DepClassTy::NONE))
10566 State.addKnownBits(NoFPAA->getState().getKnown());
10570 const std::string getAsStr(Attributor *
A)
const override {
10571 std::string
Result =
"nofpclass";
10572 raw_string_ostream OS(Result);
10573 OS << getKnownNoFPClass() <<
'/' << getAssumedNoFPClass();
10577 void getDeducedAttributes(Attributor &
A, LLVMContext &Ctx,
10578 SmallVectorImpl<Attribute> &Attrs)
const override {
10579 Attrs.emplace_back(Attribute::getWithNoFPClass(Ctx, getAssumedNoFPClass()));
10583struct AANoFPClassFloating :
public AANoFPClassImpl {
10584 AANoFPClassFloating(
const IRPosition &IRP, Attributor &
A)
10585 : AANoFPClassImpl(IRP,
A) {}
10590 bool UsedAssumedInformation =
false;
10591 if (!
A.getAssumedSimplifiedValues(getIRPosition(), *
this,
Values,
10593 Values.push_back({getAssociatedValue(), getCtxI()});
10599 DepClassTy::REQUIRED);
10600 if (!AA ||
this == AA) {
10601 T.indicatePessimisticFixpoint();
10603 const AANoFPClass::StateType &S =
10604 static_cast<const AANoFPClass::StateType &
>(AA->
getState());
10607 return T.isValidState();
10610 for (
const auto &VAC :
Values)
10612 return indicatePessimisticFixpoint();
10618 void trackStatistics()
const override {
10623struct AANoFPClassReturned final
10624 : AAReturnedFromReturnedValues<AANoFPClass, AANoFPClassImpl,
10625 AANoFPClassImpl::StateType, false,
10626 Attribute::None, false> {
10627 AANoFPClassReturned(
const IRPosition &IRP, Attributor &
A)
10628 : AAReturnedFromReturnedValues<AANoFPClass, AANoFPClassImpl,
10629 AANoFPClassImpl::StateType,
false,
10633 void trackStatistics()
const override {
10638struct AANoFPClassArgument final
10639 : AAArgumentFromCallSiteArguments<AANoFPClass, AANoFPClassImpl> {
10640 AANoFPClassArgument(
const IRPosition &IRP, Attributor &
A)
10641 : AAArgumentFromCallSiteArguments<AANoFPClass, AANoFPClassImpl>(IRP,
A) {}
10647struct AANoFPClassCallSiteArgument final : AANoFPClassFloating {
10648 AANoFPClassCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
10649 : AANoFPClassFloating(IRP,
A) {}
10652 void trackStatistics()
const override {
10657struct AANoFPClassCallSiteReturned final
10658 : AACalleeToCallSite<AANoFPClass, AANoFPClassImpl> {
10659 AANoFPClassCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
10660 : AACalleeToCallSite<AANoFPClass, AANoFPClassImpl>(IRP,
A) {}
10663 void trackStatistics()
const override {
10668struct AACallEdgesImpl :
public AACallEdges {
10669 AACallEdgesImpl(
const IRPosition &IRP, Attributor &
A) : AACallEdges(IRP,
A) {}
10671 const SetVector<Function *> &getOptimisticEdges()
const override {
10672 return CalledFunctions;
10675 bool hasUnknownCallee()
const override {
return HasUnknownCallee; }
10677 bool hasNonAsmUnknownCallee()
const override {
10678 return HasUnknownCalleeNonAsm;
10681 const std::string getAsStr(Attributor *
A)
const override {
10682 return "CallEdges[" + std::to_string(HasUnknownCallee) +
"," +
10683 std::to_string(CalledFunctions.size()) +
"]";
10686 void trackStatistics()
const override {}
10690 if (CalledFunctions.insert(Fn)) {
10691 Change = ChangeStatus::CHANGED;
10697 void setHasUnknownCallee(
bool NonAsm,
ChangeStatus &Change) {
10698 if (!HasUnknownCallee)
10699 Change = ChangeStatus::CHANGED;
10700 if (NonAsm && !HasUnknownCalleeNonAsm)
10701 Change = ChangeStatus::CHANGED;
10702 HasUnknownCalleeNonAsm |= NonAsm;
10703 HasUnknownCallee =
true;
10708 SetVector<Function *> CalledFunctions;
10711 bool HasUnknownCallee =
false;
10714 bool HasUnknownCalleeNonAsm =
false;
10717struct AACallEdgesCallSite :
public AACallEdgesImpl {
10718 AACallEdgesCallSite(
const IRPosition &IRP, Attributor &
A)
10719 : AACallEdgesImpl(IRP,
A) {}
10726 addCalledFunction(Fn, Change);
10728 LLVM_DEBUG(
dbgs() <<
"[AACallEdges] Unrecognized value: " << V <<
"\n");
10729 setHasUnknownCallee(
true, Change);
10740 VisitValue(*V, CtxI);
10744 bool UsedAssumedInformation =
false;
10748 Values.push_back({*
V, CtxI});
10750 for (
auto &VAC :
Values)
10757 if (
IA->hasSideEffects() &&
10760 setHasUnknownCallee(
false, Change);
10766 if (
auto *IndirectCallAA =
A.getAAFor<AAIndirectCallInfo>(
10767 *
this, getIRPosition(), DepClassTy::OPTIONAL))
10768 if (IndirectCallAA->foreachCallee(
10769 [&](
Function *Fn) { return VisitValue(*Fn, CB); }))
10778 for (
const Use *U : CallbackUses)
10779 ProcessCalledOperand(
U->get(), CB);
10785struct AACallEdgesFunction :
public AACallEdgesImpl {
10786 AACallEdgesFunction(
const IRPosition &IRP, Attributor &
A)
10787 : AACallEdgesImpl(IRP,
A) {}
10796 auto *CBEdges =
A.getAAFor<AACallEdges>(
10800 if (CBEdges->hasNonAsmUnknownCallee())
10801 setHasUnknownCallee(
true, Change);
10802 if (CBEdges->hasUnknownCallee())
10803 setHasUnknownCallee(
false, Change);
10805 for (
Function *
F : CBEdges->getOptimisticEdges())
10806 addCalledFunction(
F, Change);
10812 bool UsedAssumedInformation =
false;
10813 if (!
A.checkForAllCallLikeInstructions(ProcessCallInst, *
this,
10814 UsedAssumedInformation,
10818 setHasUnknownCallee(
true, Change);
10827struct AAInterFnReachabilityFunction
10828 :
public CachedReachabilityAA<AAInterFnReachability, Function> {
10829 using Base = CachedReachabilityAA<AAInterFnReachability, Function>;
10830 AAInterFnReachabilityFunction(
const IRPosition &IRP, Attributor &
A)
10833 bool instructionCanReach(
10834 Attributor &
A,
const Instruction &From,
const Function &To,
10837 auto *NonConstThis =
const_cast<AAInterFnReachabilityFunction *
>(
this);
10839 RQITy StackRQI(
A, From, To, ExclusionSet,
false);
10840 RQITy::Reachable
Result;
10841 if (!NonConstThis->checkQueryCache(
A, StackRQI, Result))
10842 return NonConstThis->isReachableImpl(
A, StackRQI,
10844 return Result == RQITy::Reachable::Yes;
10848 bool IsTemporaryRQI)
override {
10850 &RQI.From->getFunction()->getEntryBlock().front();
10851 if (EntryI != RQI.From &&
10852 !instructionCanReach(
A, *EntryI, *RQI.To,
nullptr))
10853 return rememberResult(
A, RQITy::Reachable::No, RQI,
false,
10856 auto CheckReachableCallBase = [&](CallBase *CB) {
10857 auto *CBEdges =
A.getAAFor<AACallEdges>(
10859 if (!CBEdges || !CBEdges->getState().isValidState())
10862 if (CBEdges->hasUnknownCallee())
10865 for (
Function *Fn : CBEdges->getOptimisticEdges()) {
10876 if (Fn == getAnchorScope()) {
10877 if (EntryI == RQI.From)
10882 const AAInterFnReachability *InterFnReachability =
10884 DepClassTy::OPTIONAL);
10887 if (!InterFnReachability ||
10895 const auto *IntraFnReachability =
A.getAAFor<AAIntraFnReachability>(
10897 DepClassTy::OPTIONAL);
10905 return IntraFnReachability && !IntraFnReachability->isAssumedReachable(
10906 A, *RQI.From, CBInst, RQI.ExclusionSet);
10909 bool UsedExclusionSet =
true;
10910 bool UsedAssumedInformation =
false;
10911 if (!
A.checkForAllCallLikeInstructions(CheckCallBase, *
this,
10912 UsedAssumedInformation,
10914 return rememberResult(
A, RQITy::Reachable::Yes, RQI, UsedExclusionSet,
10917 return rememberResult(
A, RQITy::Reachable::No, RQI, UsedExclusionSet,
10921 void trackStatistics()
const override {}
10925template <
typename AAType>
10926static std::optional<Constant *>
10929 if (!Ty.isIntegerTy())
10937 std::optional<Constant *> COpt =
AA->getAssumedConstant(
A);
10939 if (!COpt.has_value()) {
10941 return std::nullopt;
10943 if (
auto *
C = *COpt) {
10954 std::optional<Value *> V;
10955 for (
auto &It :
Values) {
10957 if (V.has_value() && !*V)
10960 if (!V.has_value())
10974 if (
A.hasSimplificationCallback(getIRPosition())) {
10975 indicatePessimisticFixpoint();
10978 Value *Stripped = getAssociatedValue().stripPointerCasts();
10980 addValue(
A, getState(), *Stripped, getCtxI(),
AA::AnyScope,
10982 indicateOptimisticFixpoint();
10985 AAPotentialValues::initialize(
A);
10989 const std::string getAsStr(Attributor *
A)
const override {
10991 llvm::raw_string_ostream OS(Str);
10996 template <
typename AAType>
10997 static std::optional<Value *> askOtherAA(Attributor &
A,
10998 const AbstractAttribute &AA,
10999 const IRPosition &IRP,
Type &Ty) {
11004 return std::nullopt;
11011 virtual void addValue(Attributor &
A, StateType &State,
Value &V,
11017 for (
const auto &U : CB->
args()) {
11027 Type &Ty = *getAssociatedType();
11028 std::optional<Value *> SimpleV =
11029 askOtherAA<AAValueConstantRange>(
A, *
this, ValIRP, Ty);
11030 if (SimpleV.has_value() && !*SimpleV) {
11031 auto *PotentialConstantsAA =
A.getAAFor<AAPotentialConstantValues>(
11032 *
this, ValIRP, DepClassTy::OPTIONAL);
11033 if (PotentialConstantsAA && PotentialConstantsAA->isValidState()) {
11034 for (
const auto &It : PotentialConstantsAA->getAssumedSet())
11035 State.unionAssumed({{*ConstantInt::get(&Ty, It),
nullptr}, S});
11036 if (PotentialConstantsAA->undefIsContained())
11041 if (!SimpleV.has_value())
11053 State.unionAssumed({{*VPtr, CtxI}, S});
11059 AA::ValueAndContext
I;
11063 return II.I ==
I &&
II.S == S;
11066 return std::tie(
I, S) < std::tie(
II.I,
II.S);
11070 bool recurseForValue(Attributor &
A,
const IRPosition &IRP,
AA::ValueScope S) {
11071 SmallMapVector<AA::ValueAndContext, int, 8> ValueScopeMap;
11076 bool UsedAssumedInformation =
false;
11078 if (!
A.getAssumedSimplifiedValues(IRP,
this,
Values, CS,
11079 UsedAssumedInformation))
11083 ValueScopeMap[It] += CS;
11085 for (
auto &It : ValueScopeMap)
11086 addValue(
A, getState(), *It.first.getValue(), It.first.getCtxI(),
11092 void giveUpOnIntraprocedural(Attributor &
A) {
11093 auto NewS = StateType::getBestState(getState());
11094 for (
const auto &It : getAssumedSet()) {
11097 addValue(
A, NewS, *It.first.getValue(), It.first.getCtxI(),
11100 assert(!undefIsContained() &&
"Undef should be an explicit value!");
11108 getState() = StateType::getBestState(getState());
11109 getState().unionAssumed({{getAssociatedValue(), getCtxI()},
AA::AnyScope});
11110 AAPotentialValues::indicateOptimisticFixpoint();
11111 return ChangeStatus::CHANGED;
11116 return indicatePessimisticFixpoint();
11124 if (!getAssumedSimplifiedValues(
A,
Values, S))
11126 Value &OldV = getAssociatedValue();
11129 Value *NewV = getSingleValue(
A, *
this, getIRPosition(),
Values);
11130 if (!NewV || NewV == &OldV)
11135 if (
A.changeAfterManifest(getIRPosition(), *NewV))
11136 return ChangeStatus::CHANGED;
11138 return ChangeStatus::UNCHANGED;
11141 bool getAssumedSimplifiedValues(
11142 Attributor &
A, SmallVectorImpl<AA::ValueAndContext> &
Values,
11143 AA::ValueScope S,
bool RecurseForSelectAndPHI =
false)
const override {
11144 if (!isValidState())
11146 bool UsedAssumedInformation =
false;
11147 for (
const auto &It : getAssumedSet())
11148 if (It.second & S) {
11149 if (RecurseForSelectAndPHI && (
isa<PHINode>(It.first.getValue()) ||
11151 if (
A.getAssumedSimplifiedValues(
11153 this,
Values, S, UsedAssumedInformation))
11156 Values.push_back(It.first);
11158 assert(!undefIsContained() &&
"Undef should be an explicit value!");
11163struct AAPotentialValuesFloating : AAPotentialValuesImpl {
11164 AAPotentialValuesFloating(
const IRPosition &IRP, Attributor &
A)
11165 : AAPotentialValuesImpl(IRP,
A) {}
11169 auto AssumedBefore = getAssumed();
11171 genericValueTraversal(
A, &getAssociatedValue());
11173 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
11174 : ChangeStatus::CHANGED;
11178 struct LivenessInfo {
11179 const AAIsDead *LivenessAA =
nullptr;
11180 bool AnyDead =
false;
11190 SmallVectorImpl<ItemInfo> &Worklist) {
11193 bool UsedAssumedInformation =
false;
11195 auto GetSimplifiedValues = [&](
Value &
V,
11197 if (!
A.getAssumedSimplifiedValues(
11201 Values.push_back(AA::ValueAndContext{
V,
II.I.getCtxI()});
11205 if (GetSimplifiedValues(*
LHS, LHSValues))
11207 if (GetSimplifiedValues(*
RHS, RHSValues))
11212 InformationCache &InfoCache =
A.getInfoCache();
11219 F ?
A.getInfoCache().getTargetLibraryInfoForFunction(*
F) :
nullptr;
11224 const DataLayout &
DL =
A.getDataLayout();
11225 SimplifyQuery Q(
DL, TLI, DT, AC, CmpI);
11227 auto CheckPair = [&](
Value &LHSV,
Value &RHSV) {
11230 nullptr,
II.S, getAnchorScope());
11236 if (&LHSV == &RHSV &&
11238 Constant *NewV = ConstantInt::get(Type::getInt1Ty(Ctx),
11240 addValue(
A, getState(), *NewV,
nullptr,
II.S,
11247 if (TypedLHS && TypedRHS) {
11249 if (NewV && NewV != &Cmp) {
11250 addValue(
A, getState(), *NewV,
nullptr,
II.S,
11262 if (!LHSIsNull && !RHSIsNull)
11268 assert((LHSIsNull || RHSIsNull) &&
11269 "Expected nullptr versus non-nullptr comparison at this point");
11272 unsigned PtrIdx = LHSIsNull;
11273 bool IsKnownNonNull;
11276 DepClassTy::REQUIRED, IsKnownNonNull);
11277 if (!IsAssumedNonNull)
11283 addValue(
A, getState(), *NewV,
nullptr,
II.S,
11288 for (
auto &LHSValue : LHSValues)
11289 for (
auto &RHSValue : RHSValues)
11290 if (!CheckPair(*LHSValue.getValue(), *RHSValue.getValue()))
11295 bool handleSelectInst(Attributor &
A, SelectInst &SI, ItemInfo
II,
11296 SmallVectorImpl<ItemInfo> &Worklist) {
11298 bool UsedAssumedInformation =
false;
11300 std::optional<Constant *>
C =
11301 A.getAssumedConstant(*
SI.getCondition(), *
this, UsedAssumedInformation);
11302 bool NoValueYet = !
C.has_value();
11310 }
else if (&SI == &getAssociatedValue()) {
11315 std::optional<Value *> SimpleV =
A.getAssumedSimplified(
11317 if (!SimpleV.has_value())
11320 addValue(
A, getState(), **SimpleV, CtxI,
II.S, getAnchorScope());
11328 bool handleLoadInst(Attributor &
A, LoadInst &LI, ItemInfo
II,
11329 SmallVectorImpl<ItemInfo> &Worklist) {
11330 SmallSetVector<Value *, 4> PotentialCopies;
11331 SmallSetVector<Instruction *, 4> PotentialValueOrigins;
11332 bool UsedAssumedInformation =
false;
11334 PotentialValueOrigins, *
this,
11335 UsedAssumedInformation,
11337 LLVM_DEBUG(
dbgs() <<
"[AAPotentialValues] Failed to get potentially "
11338 "loaded values for load instruction "
11346 InformationCache &InfoCache =
A.getInfoCache();
11348 if (!
llvm::all_of(PotentialValueOrigins, [&](Instruction *
I) {
11352 return A.isAssumedDead(
SI->getOperandUse(0),
this,
11354 UsedAssumedInformation,
11356 return A.isAssumedDead(*
I,
this,
nullptr,
11357 UsedAssumedInformation,
11360 LLVM_DEBUG(
dbgs() <<
"[AAPotentialValues] Load is onl used by assumes "
11361 "and we cannot delete all the stores: "
11372 bool AllLocal = ScopeIsLocal;
11377 if (!DynamicallyUnique) {
11378 LLVM_DEBUG(
dbgs() <<
"[AAPotentialValues] Not all potentially loaded "
11379 "values are dynamically unique: "
11384 for (
auto *PotentialCopy : PotentialCopies) {
11386 Worklist.
push_back({{*PotentialCopy, CtxI},
II.S});
11391 if (!AllLocal && ScopeIsLocal)
11396 bool handlePHINode(
11397 Attributor &
A, PHINode &
PHI, ItemInfo
II,
11398 SmallVectorImpl<ItemInfo> &Worklist,
11399 SmallMapVector<const Function *, LivenessInfo, 4> &LivenessAAs) {
11400 auto GetLivenessInfo = [&](
const Function &
F) -> LivenessInfo & {
11401 LivenessInfo &LI = LivenessAAs[&
F];
11402 if (!LI.LivenessAA)
11408 if (&
PHI == &getAssociatedValue()) {
11409 LivenessInfo &LI = GetLivenessInfo(*
PHI.getFunction());
11411 A.getInfoCache().getAnalysisResultForFunction<CycleAnalysis>(
11412 *
PHI.getFunction());
11416 for (
unsigned u = 0, e =
PHI.getNumIncomingValues(); u < e; u++) {
11418 if (LI.LivenessAA &&
11419 LI.LivenessAA->isEdgeDead(IncomingBB,
PHI.getParent())) {
11438 bool UsedAssumedInformation =
false;
11439 std::optional<Value *> SimpleV =
A.getAssumedSimplified(
11441 if (!SimpleV.has_value())
11445 addValue(
A, getState(), **SimpleV, &
PHI,
II.S, getAnchorScope());
11452 bool handleGenericInst(Attributor &
A, Instruction &
I, ItemInfo
II,
11453 SmallVectorImpl<ItemInfo> &Worklist) {
11454 bool SomeSimplified =
false;
11455 bool UsedAssumedInformation =
false;
11457 SmallVector<Value *, 8> NewOps(
I.getNumOperands());
11460 const auto &SimplifiedOp =
A.getAssumedSimplified(
11465 if (!SimplifiedOp.has_value())
11469 NewOps[
Idx] = *SimplifiedOp;
11473 SomeSimplified |= (NewOps[
Idx] !=
Op);
11479 if (!SomeSimplified)
11482 InformationCache &InfoCache =
A.getInfoCache();
11486 const auto *TLI =
A.getInfoCache().getTargetLibraryInfoForFunction(*
F);
11489 const DataLayout &
DL =
I.getDataLayout();
11490 SimplifyQuery Q(
DL, TLI, DT, AC, &
I);
11492 if (!NewV || NewV == &
I)
11495 LLVM_DEBUG(
dbgs() <<
"Generic inst " <<
I <<
" assumed simplified to "
11502 Attributor &
A, Instruction &
I, ItemInfo
II,
11503 SmallVectorImpl<ItemInfo> &Worklist,
11504 SmallMapVector<const Function *, LivenessInfo, 4> &LivenessAAs) {
11507 CI->getPredicate(),
II, Worklist);
11509 switch (
I.getOpcode()) {
11510 case Instruction::Select:
11512 case Instruction::PHI:
11514 case Instruction::Load:
11517 return handleGenericInst(
A,
I,
II, Worklist);
11522 void genericValueTraversal(Attributor &
A,
Value *InitialV) {
11523 SmallMapVector<const Function *, LivenessInfo, 4> LivenessAAs;
11525 SmallSet<ItemInfo, 16> Visited;
11544 LLVM_DEBUG(
dbgs() <<
"Generic value traversal reached iteration limit: "
11545 << Iteration <<
"!\n");
11546 addValue(
A, getState(), *V, CtxI, S, getAnchorScope());
11552 Value *NewV =
nullptr;
11553 if (
V->getType()->isPointerTy()) {
11559 for (Argument &Arg :
Callee->args())
11566 if (NewV && NewV != V) {
11567 Worklist.
push_back({{*NewV, CtxI}, S});
11581 if (V == InitialV && CtxI == getCtxI()) {
11582 indicatePessimisticFixpoint();
11586 addValue(
A, getState(), *V, CtxI, S, getAnchorScope());
11587 }
while (!Worklist.
empty());
11591 for (
auto &It : LivenessAAs)
11592 if (It.second.AnyDead)
11593 A.recordDependence(*It.second.LivenessAA, *
this, DepClassTy::OPTIONAL);
11597 void trackStatistics()
const override {
11602struct AAPotentialValuesArgument final : AAPotentialValuesImpl {
11603 using Base = AAPotentialValuesImpl;
11604 AAPotentialValuesArgument(
const IRPosition &IRP, Attributor &
A)
11611 indicatePessimisticFixpoint();
11616 auto AssumedBefore = getAssumed();
11618 unsigned ArgNo = getCalleeArgNo();
11620 bool UsedAssumedInformation =
false;
11622 auto CallSitePred = [&](AbstractCallSite ACS) {
11624 if (CSArgIRP.getPositionKind() == IRP_INVALID)
11627 if (!
A.getAssumedSimplifiedValues(CSArgIRP,
this,
Values,
11629 UsedAssumedInformation))
11632 return isValidState();
11635 if (!
A.checkForAllCallSites(CallSitePred, *
this,
11637 UsedAssumedInformation))
11638 return indicatePessimisticFixpoint();
11640 Function *Fn = getAssociatedFunction();
11641 bool AnyNonLocal =
false;
11642 for (
auto &It :
Values) {
11644 addValue(
A, getState(), *It.getValue(), It.getCtxI(),
AA::AnyScope,
11649 return indicatePessimisticFixpoint();
11653 addValue(
A, getState(), *It.getValue(), It.getCtxI(),
AA::AnyScope,
11659 AnyNonLocal =
true;
11661 assert(!undefIsContained() &&
"Undef should be an explicit value!");
11663 giveUpOnIntraprocedural(
A);
11665 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
11666 : ChangeStatus::CHANGED;
11670 void trackStatistics()
const override {
11675struct AAPotentialValuesReturned :
public AAPotentialValuesFloating {
11676 using Base = AAPotentialValuesFloating;
11677 AAPotentialValuesReturned(
const IRPosition &IRP, Attributor &
A)
11683 if (!
F ||
F->isDeclaration() ||
F->getReturnType()->isVoidTy()) {
11684 indicatePessimisticFixpoint();
11688 for (Argument &Arg :
F->args())
11691 ReturnedArg = &Arg;
11694 if (!
A.isFunctionIPOAmendable(*
F) ||
11695 A.hasSimplificationCallback(getIRPosition())) {
11697 indicatePessimisticFixpoint();
11699 indicateOptimisticFixpoint();
11705 auto AssumedBefore = getAssumed();
11706 bool UsedAssumedInformation =
false;
11709 Function *AnchorScope = getAnchorScope();
11715 UsedAssumedInformation,
11721 bool AllInterAreIntra =
false;
11728 for (
const AA::ValueAndContext &VAC :
Values) {
11729 addValue(
A, getState(), *VAC.
getValue(),
11733 if (AllInterAreIntra)
11740 HandleReturnedValue(*ReturnedArg,
nullptr,
true);
11743 bool AddValues =
true;
11746 addValue(
A, getState(), *RetI.getOperand(0), &RetI,
AA::AnyScope,
11750 return HandleReturnedValue(*RetI.getOperand(0), &RetI, AddValues);
11753 if (!
A.checkForAllInstructions(RetInstPred, *
this, {Instruction::Ret},
11754 UsedAssumedInformation,
11756 return indicatePessimisticFixpoint();
11759 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
11760 : ChangeStatus::CHANGED;
11765 return ChangeStatus::UNCHANGED;
11767 if (!getAssumedSimplifiedValues(
A,
Values, AA::ValueScope::Intraprocedural,
11769 return ChangeStatus::UNCHANGED;
11770 Value *NewVal = getSingleValue(
A, *
this, getIRPosition(),
Values);
11772 return ChangeStatus::UNCHANGED;
11777 "Number of function with unique return");
11780 {Attribute::get(Arg->
getContext(), Attribute::Returned)});
11785 Value *RetOp = RetI.getOperand(0);
11789 if (
A.changeUseAfterManifest(RetI.getOperandUse(0), *NewVal))
11790 Changed = ChangeStatus::CHANGED;
11793 bool UsedAssumedInformation =
false;
11794 (void)
A.checkForAllInstructions(RetInstPred, *
this, {Instruction::Ret},
11795 UsedAssumedInformation,
11801 return AAPotentialValues::indicatePessimisticFixpoint();
11805 void trackStatistics()
const override{
11812struct AAPotentialValuesFunction : AAPotentialValuesImpl {
11813 AAPotentialValuesFunction(
const IRPosition &IRP, Attributor &
A)
11814 : AAPotentialValuesImpl(IRP,
A) {}
11823 void trackStatistics()
const override {
11828struct AAPotentialValuesCallSite : AAPotentialValuesFunction {
11829 AAPotentialValuesCallSite(
const IRPosition &IRP, Attributor &
A)
11830 : AAPotentialValuesFunction(IRP,
A) {}
11833 void trackStatistics()
const override {
11838struct AAPotentialValuesCallSiteReturned : AAPotentialValuesImpl {
11839 AAPotentialValuesCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
11840 : AAPotentialValuesImpl(IRP,
A) {}
11844 auto AssumedBefore = getAssumed();
11848 return indicatePessimisticFixpoint();
11850 bool UsedAssumedInformation =
false;
11854 UsedAssumedInformation))
11855 return indicatePessimisticFixpoint();
11862 Values, S, UsedAssumedInformation))
11865 for (
auto &It :
Values) {
11866 Value *
V = It.getValue();
11867 std::optional<Value *> CallerV =
A.translateArgumentToCallSiteContent(
11868 V, *CB, *
this, UsedAssumedInformation);
11869 if (!CallerV.has_value()) {
11873 V = *CallerV ? *CallerV :
V;
11879 giveUpOnIntraprocedural(
A);
11882 addValue(
A, getState(), *V, CB, S, getAnchorScope());
11887 return indicatePessimisticFixpoint();
11889 return indicatePessimisticFixpoint();
11890 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
11891 : ChangeStatus::CHANGED;
11895 return AAPotentialValues::indicatePessimisticFixpoint();
11899 void trackStatistics()
const override {
11904struct AAPotentialValuesCallSiteArgument : AAPotentialValuesFloating {
11905 AAPotentialValuesCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
11906 : AAPotentialValuesFloating(IRP,
A) {}
11909 void trackStatistics()
const override {
11917struct AAAssumptionInfoImpl :
public AAAssumptionInfo {
11918 AAAssumptionInfoImpl(
const IRPosition &IRP, Attributor &
A,
11919 const DenseSet<StringRef> &
Known)
11920 : AAAssumptionInfo(IRP,
A,
Known) {}
11925 if (getKnown().isUniversal())
11926 return ChangeStatus::UNCHANGED;
11928 const IRPosition &IRP = getIRPosition();
11930 getAssumed().getSet().
end());
11932 return A.manifestAttrs(IRP,
11939 bool hasAssumption(
const StringRef Assumption)
const override {
11940 return isValidState() && setContains(Assumption);
11944 const std::string getAsStr(Attributor *
A)
const override {
11945 const SetContents &
Known = getKnown();
11946 const SetContents &Assumed = getAssumed();
11950 const std::string KnownStr =
llvm::join(Set,
",");
11952 std::string AssumedStr =
"Universal";
11953 if (!Assumed.isUniversal()) {
11954 Set.assign(Assumed.getSet().begin(), Assumed.getSet().end());
11957 return "Known [" + KnownStr +
"]," +
" Assumed [" + AssumedStr +
"]";
11972struct AAAssumptionInfoFunction final : AAAssumptionInfoImpl {
11973 AAAssumptionInfoFunction(
const IRPosition &IRP, Attributor &
A)
11974 : AAAssumptionInfoImpl(IRP,
A,
11981 auto CallSitePred = [&](AbstractCallSite ACS) {
11982 const auto *AssumptionAA =
A.getAAFor<AAAssumptionInfo>(
11984 DepClassTy::REQUIRED);
11988 Changed |= getIntersection(AssumptionAA->getAssumed());
11989 return !getAssumed().empty() || !getKnown().empty();
11992 bool UsedAssumedInformation =
false;
11997 if (!
A.checkForAllCallSites(CallSitePred, *
this,
true,
11998 UsedAssumedInformation))
11999 return indicatePessimisticFixpoint();
12001 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
12004 void trackStatistics()
const override {}
12008struct AAAssumptionInfoCallSite final : AAAssumptionInfoImpl {
12010 AAAssumptionInfoCallSite(
const IRPosition &IRP, Attributor &
A)
12011 : AAAssumptionInfoImpl(IRP,
A, getInitialAssumptions(IRP)) {}
12016 A.getAAFor<AAAssumptionInfo>(*
this, FnPos, DepClassTy::REQUIRED);
12022 auto *AssumptionAA =
12023 A.getAAFor<AAAssumptionInfo>(*
this, FnPos, DepClassTy::REQUIRED);
12025 return indicatePessimisticFixpoint();
12026 bool Changed = getIntersection(AssumptionAA->getAssumed());
12027 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
12031 void trackStatistics()
const override {}
12036 DenseSet<StringRef> getInitialAssumptions(
const IRPosition &IRP) {
12043 return Assumptions;
12058struct AAUnderlyingObjectsImpl
12064 const std::string getAsStr(
Attributor *
A)
const override {
12065 if (!isValidState())
12066 return "<invalid>";
12069 OS <<
"underlying objects: inter " << InterAssumedUnderlyingObjects.size()
12070 <<
" objects, intra " << IntraAssumedUnderlyingObjects.size()
12072 if (!InterAssumedUnderlyingObjects.empty()) {
12073 OS <<
"inter objects:\n";
12074 for (
auto *Obj : InterAssumedUnderlyingObjects)
12075 OS << *Obj <<
'\n';
12077 if (!IntraAssumedUnderlyingObjects.empty()) {
12078 OS <<
"intra objects:\n";
12079 for (
auto *Obj : IntraAssumedUnderlyingObjects)
12080 OS << *
Obj <<
'\n';
12086 void trackStatistics()
const override {}
12090 auto &Ptr = getAssociatedValue();
12092 bool UsedAssumedInformation =
false;
12093 auto DoUpdate = [&](SmallSetVector<Value *, 8> &UnderlyingObjects,
12095 SmallPtrSet<Value *, 8> SeenObjects;
12099 Scope, UsedAssumedInformation))
12100 return UnderlyingObjects.
insert(&Ptr);
12104 for (
unsigned I = 0;
I <
Values.size(); ++
I) {
12108 if (!SeenObjects.
insert(UO ? UO : Obj).second)
12110 if (UO && UO != Obj) {
12116 const auto *OtherAA =
A.getAAFor<AAUnderlyingObjects>(
12118 auto Pred = [&](
Value &
V) {
12122 Values.emplace_back(V,
nullptr);
12126 if (!OtherAA || !OtherAA->forallUnderlyingObjects(Pred, Scope))
12128 "The forall call should not return false at this position");
12134 Changed |= handleIndirect(
A, *Obj, UnderlyingObjects, Scope,
12135 UsedAssumedInformation);
12141 for (
unsigned u = 0, e =
PHI->getNumIncomingValues(); u < e; u++) {
12143 handleIndirect(
A, *
PHI->getIncomingValue(u), UnderlyingObjects,
12144 Scope, UsedAssumedInformation);
12158 if (!UsedAssumedInformation)
12159 indicateOptimisticFixpoint();
12160 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
12163 bool forallUnderlyingObjects(
12164 function_ref<
bool(
Value &)> Pred,
12166 if (!isValidState())
12167 return Pred(getAssociatedValue());
12170 ? IntraAssumedUnderlyingObjects
12171 : InterAssumedUnderlyingObjects;
12172 for (
Value *Obj : AssumedUnderlyingObjects)
12182 bool handleIndirect(Attributor &
A,
Value &V,
12183 SmallSetVector<Value *, 8> &UnderlyingObjects,
12186 const auto *AA =
A.getAAFor<AAUnderlyingObjects>(
12188 auto Pred = [&](
Value &
V) {
12192 if (!AA || !AA->forallUnderlyingObjects(Pred, Scope))
12194 "The forall call should not return false at this position");
12200 SmallSetVector<Value *, 8> IntraAssumedUnderlyingObjects;
12202 SmallSetVector<Value *, 8> InterAssumedUnderlyingObjects;
12205struct AAUnderlyingObjectsFloating final : AAUnderlyingObjectsImpl {
12206 AAUnderlyingObjectsFloating(
const IRPosition &IRP, Attributor &
A)
12207 : AAUnderlyingObjectsImpl(IRP,
A) {}
12210struct AAUnderlyingObjectsArgument final : AAUnderlyingObjectsImpl {
12211 AAUnderlyingObjectsArgument(
const IRPosition &IRP, Attributor &
A)
12212 : AAUnderlyingObjectsImpl(IRP,
A) {}
12215struct AAUnderlyingObjectsCallSite final : AAUnderlyingObjectsImpl {
12216 AAUnderlyingObjectsCallSite(
const IRPosition &IRP, Attributor &
A)
12217 : AAUnderlyingObjectsImpl(IRP,
A) {}
12220struct AAUnderlyingObjectsCallSiteArgument final : AAUnderlyingObjectsImpl {
12221 AAUnderlyingObjectsCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
12222 : AAUnderlyingObjectsImpl(IRP,
A) {}
12225struct AAUnderlyingObjectsReturned final : AAUnderlyingObjectsImpl {
12226 AAUnderlyingObjectsReturned(
const IRPosition &IRP, Attributor &
A)
12227 : AAUnderlyingObjectsImpl(IRP,
A) {}
12230struct AAUnderlyingObjectsCallSiteReturned final : AAUnderlyingObjectsImpl {
12231 AAUnderlyingObjectsCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
12232 : AAUnderlyingObjectsImpl(IRP,
A) {}
12235struct AAUnderlyingObjectsFunction final : AAUnderlyingObjectsImpl {
12236 AAUnderlyingObjectsFunction(
const IRPosition &IRP, Attributor &
A)
12237 : AAUnderlyingObjectsImpl(IRP,
A) {}
12243struct AAGlobalValueInfoFloating :
public AAGlobalValueInfo {
12244 AAGlobalValueInfoFloating(
const IRPosition &IRP, Attributor &
A)
12245 : AAGlobalValueInfo(IRP,
A) {}
12250 bool checkUse(Attributor &
A,
const Use &U,
bool &Follow,
12251 SmallVectorImpl<const Value *> &Worklist) {
12257 if (!GV->hasLocalLinkage() && !
A.isClosedWorldModule())
12263 LLVM_DEBUG(
dbgs() <<
"[AAGlobalValueInfo] Check use: " << *
U.get() <<
" in "
12264 << *UInst <<
"\n");
12267 int Idx = &
Cmp->getOperandUse(0) == &
U;
12270 return U == &getAnchorValue();
12275 auto CallSitePred = [&](AbstractCallSite ACS) {
12276 Worklist.
push_back(ACS.getInstruction());
12279 bool UsedAssumedInformation =
false;
12281 if (!
A.checkForAllCallSites(CallSitePred, *UInst->
getFunction(),
12283 UsedAssumedInformation))
12301 if (!Fn || !
A.isFunctionIPOAmendable(*Fn))
12310 unsigned NumUsesBefore =
Uses.size();
12312 SmallPtrSet<const Value *, 8> Visited;
12316 auto UsePred = [&](
const Use &
U,
bool &Follow) ->
bool {
12324 return checkUse(
A, U, Follow, Worklist);
12326 auto EquivalentUseCB = [&](
const Use &OldU,
const Use &NewU) {
12327 Uses.insert(&OldU);
12331 while (!Worklist.
empty()) {
12333 if (!Visited.
insert(V).second)
12335 if (!
A.checkForAllUses(UsePred, *
this, *V,
12337 DepClassTy::OPTIONAL,
12338 true, EquivalentUseCB)) {
12339 return indicatePessimisticFixpoint();
12343 return Uses.size() == NumUsesBefore ? ChangeStatus::UNCHANGED
12344 : ChangeStatus::CHANGED;
12347 bool isPotentialUse(
const Use &U)
const override {
12348 return !isValidState() ||
Uses.contains(&U);
12353 return ChangeStatus::UNCHANGED;
12357 const std::string getAsStr(Attributor *
A)
const override {
12358 return "[" + std::to_string(
Uses.size()) +
" uses]";
12361 void trackStatistics()
const override {
12367 SmallPtrSet<const Use *, 8>
Uses;
12373struct AAIndirectCallInfoCallSite :
public AAIndirectCallInfo {
12374 AAIndirectCallInfoCallSite(
const IRPosition &IRP, Attributor &
A)
12375 : AAIndirectCallInfo(IRP,
A) {}
12379 auto *MD = getCtxI()->getMetadata(LLVMContext::MD_callees);
12380 if (!MD && !
A.isClosedWorldModule())
12384 for (
const auto &
Op : MD->operands())
12386 PotentialCallees.insert(Callee);
12387 }
else if (
A.isClosedWorldModule()) {
12389 A.getInfoCache().getIndirectlyCallableFunctions(
A);
12390 PotentialCallees.insert_range(IndirectlyCallableFunctions);
12393 if (PotentialCallees.empty())
12394 indicateOptimisticFixpoint();
12402 SmallSetVector<Function *, 4> AssumedCalleesNow;
12403 bool AllCalleesKnownNow = AllCalleesKnown;
12405 auto CheckPotentialCalleeUse = [&](
Function &PotentialCallee,
12406 bool &UsedAssumedInformation) {
12407 const auto *GIAA =
A.getAAFor<AAGlobalValueInfo>(
12409 if (!GIAA || GIAA->isPotentialUse(CalleeUse))
12411 UsedAssumedInformation = !GIAA->isAtFixpoint();
12415 auto AddPotentialCallees = [&]() {
12416 for (
auto *PotentialCallee : PotentialCallees) {
12417 bool UsedAssumedInformation =
false;
12418 if (CheckPotentialCalleeUse(*PotentialCallee, UsedAssumedInformation))
12419 AssumedCalleesNow.
insert(PotentialCallee);
12425 bool UsedAssumedInformation =
false;
12428 AA::ValueScope::AnyScope,
12429 UsedAssumedInformation)) {
12430 if (PotentialCallees.empty())
12431 return indicatePessimisticFixpoint();
12432 AddPotentialCallees();
12437 auto CheckPotentialCallee = [&](
Function &Fn) {
12438 if (!PotentialCallees.empty() && !PotentialCallees.count(&Fn))
12441 auto &CachedResult = FilterResults[&Fn];
12442 if (CachedResult.has_value())
12443 return CachedResult.value();
12445 bool UsedAssumedInformation =
false;
12446 if (!CheckPotentialCalleeUse(Fn, UsedAssumedInformation)) {
12447 if (!UsedAssumedInformation)
12448 CachedResult =
false;
12457 for (
int I = NumCBArgs;
I < NumFnArgs; ++
I) {
12458 bool IsKnown =
false;
12461 DepClassTy::OPTIONAL, IsKnown)) {
12463 CachedResult =
false;
12468 CachedResult =
true;
12474 for (
auto &VAC :
Values) {
12482 if (CheckPotentialCallee(*VACFn))
12483 AssumedCalleesNow.
insert(VACFn);
12486 if (!PotentialCallees.empty()) {
12487 AddPotentialCallees();
12490 AllCalleesKnownNow =
false;
12493 if (AssumedCalleesNow == AssumedCallees &&
12494 AllCalleesKnown == AllCalleesKnownNow)
12495 return ChangeStatus::UNCHANGED;
12497 std::swap(AssumedCallees, AssumedCalleesNow);
12498 AllCalleesKnown = AllCalleesKnownNow;
12499 return ChangeStatus::CHANGED;
12505 if (!AllCalleesKnown && AssumedCallees.empty())
12506 return ChangeStatus::UNCHANGED;
12509 bool UsedAssumedInformation =
false;
12510 if (
A.isAssumedDead(*CB,
this,
nullptr,
12511 UsedAssumedInformation))
12512 return ChangeStatus::UNCHANGED;
12517 if (
FP->getType()->getPointerAddressSpace() != ProgramAS)
12518 FP =
new AddrSpaceCastInst(
12519 FP, PointerType::get(
FP->getContext(), ProgramAS),
12520 FP->getName() +
".as" + Twine(ProgramAS), CB->
getIterator());
12529 if (AssumedCallees.empty()) {
12530 assert(AllCalleesKnown &&
12531 "Expected all callees to be known if there are none.");
12532 A.changeToUnreachableAfterManifest(CB);
12533 return ChangeStatus::CHANGED;
12537 if (AllCalleesKnown && AssumedCallees.size() == 1) {
12538 auto *NewCallee = AssumedCallees.front();
12541 NumIndirectCallsPromoted++;
12542 return ChangeStatus::CHANGED;
12549 A.deleteAfterManifest(*CB);
12550 return ChangeStatus::CHANGED;
12560 bool SpecializedForAnyCallees =
false;
12561 bool SpecializedForAllCallees = AllCalleesKnown;
12562 ICmpInst *LastCmp =
nullptr;
12565 for (
Function *NewCallee : AssumedCallees) {
12566 if (!
A.shouldSpecializeCallSiteForCallee(*
this, *CB, *NewCallee,
12567 AssumedCallees.size())) {
12568 SkippedAssumedCallees.
push_back(NewCallee);
12569 SpecializedForAllCallees =
false;
12572 SpecializedForAnyCallees =
true;
12578 A.registerManifestAddedBasicBlock(*ThenTI->
getParent());
12579 A.registerManifestAddedBasicBlock(*IP->getParent());
12585 A.registerManifestAddedBasicBlock(*ElseBB);
12587 SplitTI->replaceUsesOfWith(CBBB, ElseBB);
12592 CastInst *RetBC =
nullptr;
12593 CallInst *NewCall =
nullptr;
12598 NumIndirectCallsPromoted++;
12606 auto AttachCalleeMetadata = [&](CallBase &IndirectCB) {
12607 if (!AllCalleesKnown)
12608 return ChangeStatus::UNCHANGED;
12609 MDBuilder MDB(IndirectCB.getContext());
12610 MDNode *Callees = MDB.createCallees(SkippedAssumedCallees);
12611 IndirectCB.setMetadata(LLVMContext::MD_callees, Callees);
12612 return ChangeStatus::CHANGED;
12615 if (!SpecializedForAnyCallees)
12616 return AttachCalleeMetadata(*CB);
12619 if (SpecializedForAllCallees) {
12622 new UnreachableInst(IP->getContext(), IP);
12623 IP->eraseFromParent();
12626 CBClone->setName(CB->
getName());
12627 CBClone->insertBefore(*IP->getParent(), IP);
12628 NewCalls.
push_back({CBClone,
nullptr});
12629 AttachCalleeMetadata(*CBClone);
12636 CB->
getParent()->getFirstInsertionPt());
12637 for (
auto &It : NewCalls) {
12638 CallBase *NewCall = It.first;
12639 Instruction *CallRet = It.second ? It.second : It.first;
12651 A.deleteAfterManifest(*CB);
12652 Changed = ChangeStatus::CHANGED;
12658 const std::string getAsStr(Attributor *
A)
const override {
12659 return std::string(AllCalleesKnown ?
"eliminate" :
"specialize") +
12660 " indirect call site with " + std::to_string(AssumedCallees.size()) +
12664 void trackStatistics()
const override {
12665 if (AllCalleesKnown) {
12667 Eliminated, CallSites,
12668 "Number of indirect call sites eliminated via specialization")
12671 "Number of indirect call sites specialized")
12675 bool foreachCallee(function_ref<
bool(
Function *)> CB)
const override {
12676 return isValidState() && AllCalleesKnown &&
all_of(AssumedCallees, CB);
12681 DenseMap<Function *, std::optional<bool>> FilterResults;
12685 SmallSetVector<Function *, 4> PotentialCallees;
12689 SmallSetVector<Function *, 4> AssumedCallees;
12693 bool AllCalleesKnown =
true;
12700struct AAInvariantLoadPointerImpl
12701 :
public StateWrapper<BitIntegerState<uint8_t, 15>,
12702 AAInvariantLoadPointer> {
12706 IS_NOALIAS = 1 << 0,
12709 IS_NOEFFECT = 1 << 1,
12711 IS_LOCALLY_INVARIANT = 1 << 2,
12713 IS_LOCALLY_CONSTRAINED = 1 << 3,
12715 IS_BEST_STATE = IS_NOALIAS | IS_NOEFFECT | IS_LOCALLY_INVARIANT |
12716 IS_LOCALLY_CONSTRAINED,
12718 static_assert(getBestState() == IS_BEST_STATE,
"Unexpected best state");
12721 StateWrapper<BitIntegerState<uint8_t, 15>, AAInvariantLoadPointer>;
12725 AAInvariantLoadPointerImpl(
const IRPosition &IRP, Attributor &
A)
12728 bool isKnownInvariant()
const final {
12729 return isKnownLocallyInvariant() && isKnown(IS_LOCALLY_CONSTRAINED);
12732 bool isKnownLocallyInvariant()
const final {
12733 if (isKnown(IS_LOCALLY_INVARIANT))
12735 return isKnown(IS_NOALIAS | IS_NOEFFECT);
12738 bool isAssumedInvariant()
const final {
12739 return isAssumedLocallyInvariant() && isAssumed(IS_LOCALLY_CONSTRAINED);
12742 bool isAssumedLocallyInvariant()
const final {
12743 if (isAssumed(IS_LOCALLY_INVARIANT))
12745 return isAssumed(IS_NOALIAS | IS_NOEFFECT);
12752 if (requiresNoAlias() && !isAssumed(IS_NOALIAS))
12753 return indicatePessimisticFixpoint();
12757 Changed |= updateLocalInvariance(
A);
12763 if (!isKnownInvariant())
12764 return ChangeStatus::UNCHANGED;
12767 const Value *Ptr = &getAssociatedValue();
12768 const auto TagInvariantLoads = [&](
const Use &
U,
bool &) {
12769 if (
U.get() != Ptr)
12777 if (!
A.isRunOn(
I->getFunction()))
12780 if (
I->hasMetadata(LLVMContext::MD_invariant_load))
12784 LI->setMetadata(LLVMContext::MD_invariant_load,
12786 Changed = ChangeStatus::CHANGED;
12791 (void)
A.checkForAllUses(TagInvariantLoads, *
this, *Ptr);
12796 const std::string getAsStr(Attributor *)
const override {
12797 if (isKnownInvariant())
12798 return "load-invariant pointer";
12799 return "non-invariant pointer";
12803 void trackStatistics()
const override {}
12807 bool requiresNoAlias()
const {
12808 switch (getPositionKind()) {
12814 case IRP_CALL_SITE:
12816 case IRP_CALL_SITE_RETURNED: {
12821 case IRP_ARGUMENT: {
12822 const Function *
F = getAssociatedFunction();
12823 assert(
F &&
"no associated function for argument");
12829 bool isExternal()
const {
12830 const Function *
F = getAssociatedFunction();
12834 getPositionKind() != IRP_CALL_SITE_RETURNED;
12838 if (isKnown(IS_NOALIAS) || !isAssumed(IS_NOALIAS))
12839 return ChangeStatus::UNCHANGED;
12842 if (
const auto *ANoAlias =
A.getOrCreateAAFor<AANoAlias>(
12843 getIRPosition(),
this, DepClassTy::REQUIRED)) {
12844 if (ANoAlias->isKnownNoAlias()) {
12845 addKnownBits(IS_NOALIAS);
12846 return ChangeStatus::CHANGED;
12849 if (!ANoAlias->isAssumedNoAlias()) {
12850 removeAssumedBits(IS_NOALIAS);
12851 return ChangeStatus::CHANGED;
12854 return ChangeStatus::UNCHANGED;
12859 if (
const Argument *Arg = getAssociatedArgument()) {
12861 addKnownBits(IS_NOALIAS);
12862 return ChangeStatus::UNCHANGED;
12867 removeAssumedBits(IS_NOALIAS);
12868 return ChangeStatus::CHANGED;
12871 return ChangeStatus::UNCHANGED;
12875 if (isKnown(IS_NOEFFECT) || !isAssumed(IS_NOEFFECT))
12876 return ChangeStatus::UNCHANGED;
12878 if (!getAssociatedFunction())
12879 return indicatePessimisticFixpoint();
12882 return indicatePessimisticFixpoint();
12884 const auto HasNoEffectLoads = [&](
const Use &
U,
bool &) {
12886 return !LI || !LI->mayHaveSideEffects();
12888 if (!
A.checkForAllUses(HasNoEffectLoads, *
this, getAssociatedValue()))
12889 return indicatePessimisticFixpoint();
12891 if (
const auto *AMemoryBehavior =
A.getOrCreateAAFor<AAMemoryBehavior>(
12892 getIRPosition(),
this, DepClassTy::REQUIRED)) {
12895 if (!AMemoryBehavior->isAssumedReadOnly())
12896 return indicatePessimisticFixpoint();
12898 if (AMemoryBehavior->isKnownReadOnly()) {
12899 addKnownBits(IS_NOEFFECT);
12900 return ChangeStatus::UNCHANGED;
12903 return ChangeStatus::UNCHANGED;
12906 if (
const Argument *Arg = getAssociatedArgument()) {
12908 addKnownBits(IS_NOEFFECT);
12909 return ChangeStatus::UNCHANGED;
12914 return indicatePessimisticFixpoint();
12917 return ChangeStatus::UNCHANGED;
12921 if (isKnown(IS_LOCALLY_INVARIANT) || !isAssumed(IS_LOCALLY_INVARIANT))
12922 return ChangeStatus::UNCHANGED;
12925 const auto *AUO =
A.getOrCreateAAFor<AAUnderlyingObjects>(
12926 getIRPosition(),
this, DepClassTy::REQUIRED);
12928 return ChangeStatus::UNCHANGED;
12930 bool UsedAssumedInformation =
false;
12931 const auto IsLocallyInvariantLoadIfPointer = [&](
const Value &
V) {
12932 if (!
V.getType()->isPointerTy())
12934 const auto *IsInvariantLoadPointer =
12936 DepClassTy::REQUIRED);
12938 if (!IsInvariantLoadPointer)
12941 if (IsInvariantLoadPointer->isKnownLocallyInvariant())
12943 if (!IsInvariantLoadPointer->isAssumedLocallyInvariant())
12946 UsedAssumedInformation =
true;
12949 if (!AUO->forallUnderlyingObjects(IsLocallyInvariantLoadIfPointer))
12950 return indicatePessimisticFixpoint();
12956 if (!IsLocallyInvariantLoadIfPointer(*Arg))
12957 return indicatePessimisticFixpoint();
12962 if (!UsedAssumedInformation) {
12964 addKnownBits(IS_LOCALLY_INVARIANT);
12965 return ChangeStatus::CHANGED;
12968 return ChangeStatus::UNCHANGED;
12972struct AAInvariantLoadPointerFloating final : AAInvariantLoadPointerImpl {
12973 AAInvariantLoadPointerFloating(
const IRPosition &IRP, Attributor &
A)
12974 : AAInvariantLoadPointerImpl(IRP,
A) {}
12977struct AAInvariantLoadPointerReturned final : AAInvariantLoadPointerImpl {
12978 AAInvariantLoadPointerReturned(
const IRPosition &IRP, Attributor &
A)
12979 : AAInvariantLoadPointerImpl(IRP,
A) {}
12982 removeAssumedBits(IS_LOCALLY_CONSTRAINED);
12986struct AAInvariantLoadPointerCallSiteReturned final
12987 : AAInvariantLoadPointerImpl {
12988 AAInvariantLoadPointerCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
12989 : AAInvariantLoadPointerImpl(IRP,
A) {}
12992 const Function *
F = getAssociatedFunction();
12993 assert(
F &&
"no associated function for return from call");
12995 if (!
F->isDeclaration() && !
F->isIntrinsic())
12996 return AAInvariantLoadPointerImpl::initialize(
A);
13001 return AAInvariantLoadPointerImpl::initialize(
A);
13003 if (
F->onlyReadsMemory() &&
F->hasNoSync())
13004 return AAInvariantLoadPointerImpl::initialize(
A);
13008 indicatePessimisticFixpoint();
13012struct AAInvariantLoadPointerArgument final : AAInvariantLoadPointerImpl {
13013 AAInvariantLoadPointerArgument(
const IRPosition &IRP, Attributor &
A)
13014 : AAInvariantLoadPointerImpl(IRP,
A) {}
13017 const Function *
F = getAssociatedFunction();
13018 assert(
F &&
"no associated function for argument");
13021 addKnownBits(IS_LOCALLY_CONSTRAINED);
13025 if (!
F->hasLocalLinkage())
13026 removeAssumedBits(IS_LOCALLY_CONSTRAINED);
13030struct AAInvariantLoadPointerCallSiteArgument final
13031 : AAInvariantLoadPointerImpl {
13032 AAInvariantLoadPointerCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
13033 : AAInvariantLoadPointerImpl(IRP,
A) {}
13040template <
typename InstType>
13041static bool makeChange(Attributor &
A, InstType *MemInst,
const Use &U,
13042 Value *OriginalValue, PointerType *NewPtrTy,
13043 bool UseOriginalValue) {
13044 if (
U.getOperandNo() != InstType::getPointerOperandIndex())
13047 if (MemInst->isVolatile()) {
13048 auto *
TTI =
A.getInfoCache().getAnalysisResultForFunction<TargetIRAnalysis>(
13049 *MemInst->getFunction());
13050 unsigned NewAS = NewPtrTy->getPointerAddressSpace();
13055 if (UseOriginalValue) {
13056 A.changeUseAfterManifest(
const_cast<Use &
>(U), *OriginalValue);
13060 Instruction *CastInst =
new AddrSpaceCastInst(OriginalValue, NewPtrTy);
13062 A.changeUseAfterManifest(
const_cast<Use &
>(U), *CastInst);
13066struct AAAddressSpaceImpl :
public AAAddressSpace {
13067 AAAddressSpaceImpl(
const IRPosition &IRP, Attributor &
A)
13068 : AAAddressSpace(IRP,
A) {}
13071 assert(isValidState() &&
"the AA is invalid");
13072 return AssumedAddressSpace;
13077 assert(getAssociatedType()->isPtrOrPtrVectorTy() &&
13078 "Associated value is not a pointer");
13080 if (!
A.getInfoCache().getFlatAddressSpace().has_value()) {
13081 indicatePessimisticFixpoint();
13085 unsigned FlatAS =
A.getInfoCache().getFlatAddressSpace().value();
13086 unsigned AS = getAssociatedType()->getPointerAddressSpace();
13087 if (AS != FlatAS) {
13088 [[maybe_unused]]
bool R = takeAddressSpace(AS);
13089 assert(R &&
"The take should happen");
13090 indicateOptimisticFixpoint();
13095 uint32_t OldAddressSpace = AssumedAddressSpace;
13096 unsigned FlatAS =
A.getInfoCache().getFlatAddressSpace().value();
13098 auto CheckAddressSpace = [&](
Value &
Obj) {
13104 unsigned ObjAS =
Obj.getType()->getPointerAddressSpace();
13105 if (ObjAS != FlatAS)
13106 return takeAddressSpace(ObjAS);
13120 A.getInfoCache().getAnalysisResultForFunction<TargetIRAnalysis>(*F);
13122 if (AssumedAS != ~0U)
13123 return takeAddressSpace(AssumedAS);
13127 return takeAddressSpace(FlatAS);
13130 auto *AUO =
A.getOrCreateAAFor<AAUnderlyingObjects>(getIRPosition(),
this,
13131 DepClassTy::REQUIRED);
13132 if (!AUO->forallUnderlyingObjects(CheckAddressSpace))
13133 return indicatePessimisticFixpoint();
13135 return OldAddressSpace == AssumedAddressSpace ? ChangeStatus::UNCHANGED
13136 : ChangeStatus::CHANGED;
13143 if (NewAS == InvalidAddressSpace ||
13145 return ChangeStatus::UNCHANGED;
13147 unsigned FlatAS =
A.getInfoCache().getFlatAddressSpace().value();
13149 Value *AssociatedValue = &getAssociatedValue();
13150 Value *OriginalValue = peelAddrspacecast(AssociatedValue, FlatAS);
13153 PointerType::get(getAssociatedType()->
getContext(), NewAS);
13154 bool UseOriginalValue =
13159 auto Pred = [&](
const Use &
U,
bool &) {
13160 if (
U.get() != AssociatedValue)
13171 makeChange(
A, LI, U, OriginalValue, NewPtrTy, UseOriginalValue);
13174 makeChange(
A, SI, U, OriginalValue, NewPtrTy, UseOriginalValue);
13177 makeChange(
A, RMW, U, OriginalValue, NewPtrTy, UseOriginalValue);
13180 makeChange(
A, CmpX, U, OriginalValue, NewPtrTy, UseOriginalValue);
13187 (void)
A.checkForAllUses(Pred, *
this, getAssociatedValue(),
13190 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
13194 const std::string getAsStr(Attributor *
A)
const override {
13195 if (!isValidState())
13196 return "addrspace(<invalid>)";
13197 return "addrspace(" +
13198 (AssumedAddressSpace == InvalidAddressSpace
13200 : std::to_string(AssumedAddressSpace)) +
13205 uint32_t AssumedAddressSpace = InvalidAddressSpace;
13207 bool takeAddressSpace(uint32_t AS) {
13208 if (AssumedAddressSpace == InvalidAddressSpace) {
13209 AssumedAddressSpace = AS;
13212 return AssumedAddressSpace == AS;
13215 static Value *peelAddrspacecast(
Value *V,
unsigned FlatAS) {
13217 assert(
I->getSrcAddressSpace() != FlatAS &&
13218 "there should not be flat AS -> non-flat AS");
13219 return I->getPointerOperand();
13222 if (
C->getOpcode() == Instruction::AddrSpaceCast) {
13223 assert(
C->getOperand(0)->getType()->getPointerAddressSpace() !=
13225 "there should not be flat AS -> non-flat AS X");
13226 return C->getOperand(0);
13232struct AAAddressSpaceFloating final : AAAddressSpaceImpl {
13233 AAAddressSpaceFloating(
const IRPosition &IRP, Attributor &
A)
13234 : AAAddressSpaceImpl(IRP,
A) {}
13236 void trackStatistics()
const override {
13241struct AAAddressSpaceReturned final : AAAddressSpaceImpl {
13242 AAAddressSpaceReturned(
const IRPosition &IRP, Attributor &
A)
13243 : AAAddressSpaceImpl(IRP,
A) {}
13249 (void)indicatePessimisticFixpoint();
13252 void trackStatistics()
const override {
13257struct AAAddressSpaceCallSiteReturned final : AAAddressSpaceImpl {
13258 AAAddressSpaceCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
13259 : AAAddressSpaceImpl(IRP,
A) {}
13261 void trackStatistics()
const override {
13266struct AAAddressSpaceArgument final : AAAddressSpaceImpl {
13267 AAAddressSpaceArgument(
const IRPosition &IRP, Attributor &
A)
13268 : AAAddressSpaceImpl(IRP,
A) {}
13273struct AAAddressSpaceCallSiteArgument final : AAAddressSpaceImpl {
13274 AAAddressSpaceCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
13275 : AAAddressSpaceImpl(IRP,
A) {}
13281 (void)indicatePessimisticFixpoint();
13284 void trackStatistics()
const override {
13299struct AANoAliasAddrSpaceImpl :
public AANoAliasAddrSpace {
13300 AANoAliasAddrSpaceImpl(
const IRPosition &IRP, Attributor &
A)
13301 : AANoAliasAddrSpace(IRP,
A) {}
13304 assert(getAssociatedType()->isPtrOrPtrVectorTy() &&
13305 "Associated value is not a pointer");
13309 std::optional<unsigned> FlatAS =
A.getInfoCache().getFlatAddressSpace();
13310 if (!FlatAS.has_value()) {
13311 indicatePessimisticFixpoint();
13317 unsigned AS = getAssociatedType()->getPointerAddressSpace();
13318 if (AS != *FlatAS) {
13320 indicateOptimisticFixpoint();
13325 unsigned FlatAS =
A.getInfoCache().getFlatAddressSpace().value();
13326 uint32_t OldAssumed = getAssumed();
13328 auto CheckAddressSpace = [&](
Value &
Obj) {
13332 unsigned AS =
Obj.getType()->getPointerAddressSpace();
13336 removeAS(
Obj.getType()->getPointerAddressSpace());
13340 const AAUnderlyingObjects *AUO =
A.getOrCreateAAFor<AAUnderlyingObjects>(
13341 getIRPosition(),
this, DepClassTy::REQUIRED);
13343 return indicatePessimisticFixpoint();
13345 return OldAssumed == getAssumed() ? ChangeStatus::UNCHANGED
13346 : ChangeStatus::CHANGED;
13351 unsigned FlatAS =
A.getInfoCache().getFlatAddressSpace().value();
13353 unsigned AS = getAssociatedType()->getPointerAddressSpace();
13354 if (AS != FlatAS ||
Map.empty())
13355 return ChangeStatus::UNCHANGED;
13357 LLVMContext &Ctx = getAssociatedValue().getContext();
13358 MDNode *NoAliasASNode =
nullptr;
13359 MDBuilder MDB(Ctx);
13361 for (RangeMap::const_iterator
I =
Map.begin();
I !=
Map.end();
I++) {
13364 unsigned Upper =
I.stop();
13365 unsigned Lower =
I.start();
13366 if (!NoAliasASNode) {
13367 NoAliasASNode = MDB.createRange(APInt(32,
Lower), APInt(32,
Upper + 1));
13370 MDNode *ASRange = MDB.createRange(APInt(32,
Lower), APInt(32,
Upper + 1));
13374 Value *AssociatedValue = &getAssociatedValue();
13377 auto AddNoAliasAttr = [&](
const Use &
U,
bool &) {
13378 if (
U.get() != AssociatedValue)
13381 if (!Inst || Inst->
hasMetadata(LLVMContext::MD_noalias_addrspace))
13388 Inst->
setMetadata(LLVMContext::MD_noalias_addrspace, NoAliasASNode);
13392 (void)
A.checkForAllUses(AddNoAliasAttr, *
this, *AssociatedValue,
13394 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
13398 const std::string getAsStr(Attributor *
A)
const override {
13399 if (!isValidState())
13400 return "<invalid>";
13402 raw_string_ostream OS(Str);
13403 OS <<
"CanNotBeAddrSpace(";
13404 for (RangeMap::const_iterator
I =
Map.begin();
I !=
Map.end();
I++) {
13405 unsigned Upper =
I.stop();
13406 unsigned Lower =
I.start();
13407 OS <<
' ' <<
'[' <<
Upper <<
',' <<
Lower + 1 <<
')';
13414 void removeAS(
unsigned AS) {
13415 RangeMap::iterator
I =
Map.find(AS);
13417 if (
I !=
Map.end()) {
13418 unsigned Upper =
I.stop();
13419 unsigned Lower =
I.start();
13423 if (AS != ~((
unsigned)0) && AS + 1 <=
Upper)
13425 if (AS != 0 &&
Lower <= AS - 1)
13430 void resetASRanges(Attributor &
A) {
13432 Map.insert(0,
A.getInfoCache().getMaxAddrSpace(),
true);
13436struct AANoAliasAddrSpaceFloating final : AANoAliasAddrSpaceImpl {
13437 AANoAliasAddrSpaceFloating(
const IRPosition &IRP, Attributor &
A)
13438 : AANoAliasAddrSpaceImpl(IRP,
A) {}
13440 void trackStatistics()
const override {
13445struct AANoAliasAddrSpaceReturned final : AANoAliasAddrSpaceImpl {
13446 AANoAliasAddrSpaceReturned(
const IRPosition &IRP, Attributor &
A)
13447 : AANoAliasAddrSpaceImpl(IRP,
A) {}
13449 void trackStatistics()
const override {
13454struct AANoAliasAddrSpaceCallSiteReturned final : AANoAliasAddrSpaceImpl {
13455 AANoAliasAddrSpaceCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
13456 : AANoAliasAddrSpaceImpl(IRP,
A) {}
13458 void trackStatistics()
const override {
13463struct AANoAliasAddrSpaceArgument final : AANoAliasAddrSpaceImpl {
13464 AANoAliasAddrSpaceArgument(
const IRPosition &IRP, Attributor &
A)
13465 : AANoAliasAddrSpaceImpl(IRP,
A) {}
13467 void trackStatistics()
const override {
13472struct AANoAliasAddrSpaceCallSiteArgument final : AANoAliasAddrSpaceImpl {
13473 AANoAliasAddrSpaceCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
13474 : AANoAliasAddrSpaceImpl(IRP,
A) {}
13476 void trackStatistics()
const override {
13483struct AAAllocationInfoImpl :
public AAAllocationInfo {
13484 AAAllocationInfoImpl(
const IRPosition &IRP, Attributor &
A)
13485 : AAAllocationInfo(IRP,
A) {}
13487 std::optional<TypeSize> getAllocatedSize()
const override {
13488 assert(isValidState() &&
"the AA is invalid");
13489 return AssumedAllocatedSize;
13492 std::optional<TypeSize> findInitialAllocationSize(Instruction *
I,
13493 const DataLayout &
DL) {
13496 switch (
I->getOpcode()) {
13497 case Instruction::Alloca: {
13502 return std::nullopt;
13508 const IRPosition &IRP = getIRPosition();
13513 return indicatePessimisticFixpoint();
13515 bool IsKnownNoCapture;
13517 A,
this, IRP, DepClassTy::OPTIONAL, IsKnownNoCapture))
13518 return indicatePessimisticFixpoint();
13520 const AAPointerInfo *PI =
13521 A.getOrCreateAAFor<AAPointerInfo>(IRP, *
this, DepClassTy::REQUIRED);
13524 return indicatePessimisticFixpoint();
13527 return indicatePessimisticFixpoint();
13529 const DataLayout &
DL =
A.getDataLayout();
13530 const auto AllocationSize = findInitialAllocationSize(
I,
DL);
13533 if (!AllocationSize)
13534 return indicatePessimisticFixpoint();
13538 if (*AllocationSize == 0)
13539 return indicatePessimisticFixpoint();
13545 return indicatePessimisticFixpoint();
13547 if (BinSize == 0) {
13548 auto NewAllocationSize = std::make_optional<TypeSize>(0,
false);
13549 if (!changeAllocationSize(NewAllocationSize))
13550 return ChangeStatus::UNCHANGED;
13551 return ChangeStatus::CHANGED;
13555 const auto &It = PI->
begin();
13558 if (It->first.Offset != 0)
13559 return indicatePessimisticFixpoint();
13561 uint64_t SizeOfBin = It->first.Offset + It->first.Size;
13563 if (SizeOfBin >= *AllocationSize)
13564 return indicatePessimisticFixpoint();
13566 auto NewAllocationSize = std::make_optional<TypeSize>(SizeOfBin * 8,
false);
13568 if (!changeAllocationSize(NewAllocationSize))
13569 return ChangeStatus::UNCHANGED;
13571 return ChangeStatus::CHANGED;
13577 assert(isValidState() &&
13578 "Manifest should only be called if the state is valid.");
13582 auto FixedAllocatedSizeInBits = getAllocatedSize()->getFixedValue();
13584 unsigned long NumBytesToAllocate = (FixedAllocatedSizeInBits + 7) / 8;
13586 switch (
I->getOpcode()) {
13588 case Instruction::Alloca: {
13592 Type *CharType = Type::getInt8Ty(
I->getContext());
13594 auto *NumBytesToValue =
13595 ConstantInt::get(
I->getContext(), APInt(32, NumBytesToAllocate));
13598 insertPt = std::next(insertPt);
13599 AllocaInst *NewAllocaInst =
13604 return ChangeStatus::CHANGED;
13612 return ChangeStatus::UNCHANGED;
13616 const std::string getAsStr(Attributor *
A)
const override {
13617 if (!isValidState())
13618 return "allocationinfo(<invalid>)";
13619 return "allocationinfo(" +
13620 (AssumedAllocatedSize == HasNoAllocationSize
13622 : std::to_string(AssumedAllocatedSize->getFixedValue())) +
13627 std::optional<TypeSize> AssumedAllocatedSize = HasNoAllocationSize;
13631 bool changeAllocationSize(std::optional<TypeSize>
Size) {
13632 if (AssumedAllocatedSize == HasNoAllocationSize ||
13633 AssumedAllocatedSize !=
Size) {
13634 AssumedAllocatedSize =
Size;
13641struct AAAllocationInfoFloating : AAAllocationInfoImpl {
13642 AAAllocationInfoFloating(
const IRPosition &IRP, Attributor &
A)
13643 : AAAllocationInfoImpl(IRP,
A) {}
13645 void trackStatistics()
const override {
13650struct AAAllocationInfoReturned : AAAllocationInfoImpl {
13651 AAAllocationInfoReturned(
const IRPosition &IRP, Attributor &
A)
13652 : AAAllocationInfoImpl(IRP,
A) {}
13658 (void)indicatePessimisticFixpoint();
13661 void trackStatistics()
const override {
13666struct AAAllocationInfoCallSiteReturned : AAAllocationInfoImpl {
13667 AAAllocationInfoCallSiteReturned(
const IRPosition &IRP, Attributor &
A)
13668 : AAAllocationInfoImpl(IRP,
A) {}
13670 void trackStatistics()
const override {
13675struct AAAllocationInfoArgument : AAAllocationInfoImpl {
13676 AAAllocationInfoArgument(
const IRPosition &IRP, Attributor &
A)
13677 : AAAllocationInfoImpl(IRP,
A) {}
13679 void trackStatistics()
const override {
13684struct AAAllocationInfoCallSiteArgument : AAAllocationInfoImpl {
13685 AAAllocationInfoCallSiteArgument(
const IRPosition &IRP, Attributor &
A)
13686 : AAAllocationInfoImpl(IRP,
A) {}
13691 (void)indicatePessimisticFixpoint();
13694 void trackStatistics()
const override {
13743#define SWITCH_PK_INV(CLASS, PK, POS_NAME) \
13744 case IRPosition::PK: \
13745 llvm_unreachable("Cannot create " #CLASS " for a " POS_NAME " position!");
13747#define SWITCH_PK_CREATE(CLASS, IRP, PK, SUFFIX) \
13748 case IRPosition::PK: \
13749 AA = new (A.Allocator) CLASS##SUFFIX(IRP, A); \
13753#define CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13754 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13755 CLASS *AA = nullptr; \
13756 switch (IRP.getPositionKind()) { \
13757 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13758 SWITCH_PK_INV(CLASS, IRP_FLOAT, "floating") \
13759 SWITCH_PK_INV(CLASS, IRP_ARGUMENT, "argument") \
13760 SWITCH_PK_INV(CLASS, IRP_RETURNED, "returned") \
13761 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_RETURNED, "call site returned") \
13762 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_ARGUMENT, "call site argument") \
13763 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
13764 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE, CallSite) \
13769#define CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13770 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13771 CLASS *AA = nullptr; \
13772 switch (IRP.getPositionKind()) { \
13773 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13774 SWITCH_PK_INV(CLASS, IRP_FUNCTION, "function") \
13775 SWITCH_PK_INV(CLASS, IRP_CALL_SITE, "call site") \
13776 SWITCH_PK_CREATE(CLASS, IRP, IRP_FLOAT, Floating) \
13777 SWITCH_PK_CREATE(CLASS, IRP, IRP_ARGUMENT, Argument) \
13778 SWITCH_PK_CREATE(CLASS, IRP, IRP_RETURNED, Returned) \
13779 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_RETURNED, CallSiteReturned) \
13780 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_ARGUMENT, CallSiteArgument) \
13785#define CREATE_ABSTRACT_ATTRIBUTE_FOR_ONE_POSITION(POS, SUFFIX, CLASS) \
13786 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13787 CLASS *AA = nullptr; \
13788 switch (IRP.getPositionKind()) { \
13789 SWITCH_PK_CREATE(CLASS, IRP, POS, SUFFIX) \
13791 llvm_unreachable("Cannot create " #CLASS " for position otherthan " #POS \
13797#define CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13798 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13799 CLASS *AA = nullptr; \
13800 switch (IRP.getPositionKind()) { \
13801 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13802 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
13803 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE, CallSite) \
13804 SWITCH_PK_CREATE(CLASS, IRP, IRP_FLOAT, Floating) \
13805 SWITCH_PK_CREATE(CLASS, IRP, IRP_ARGUMENT, Argument) \
13806 SWITCH_PK_CREATE(CLASS, IRP, IRP_RETURNED, Returned) \
13807 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_RETURNED, CallSiteReturned) \
13808 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_ARGUMENT, CallSiteArgument) \
13813#define CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13814 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13815 CLASS *AA = nullptr; \
13816 switch (IRP.getPositionKind()) { \
13817 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13818 SWITCH_PK_INV(CLASS, IRP_ARGUMENT, "argument") \
13819 SWITCH_PK_INV(CLASS, IRP_FLOAT, "floating") \
13820 SWITCH_PK_INV(CLASS, IRP_RETURNED, "returned") \
13821 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_RETURNED, "call site returned") \
13822 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_ARGUMENT, "call site argument") \
13823 SWITCH_PK_INV(CLASS, IRP_CALL_SITE, "call site") \
13824 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
13829#define CREATE_NON_RET_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13830 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13831 CLASS *AA = nullptr; \
13832 switch (IRP.getPositionKind()) { \
13833 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13834 SWITCH_PK_INV(CLASS, IRP_RETURNED, "returned") \
13835 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
13836 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE, CallSite) \
13837 SWITCH_PK_CREATE(CLASS, IRP, IRP_FLOAT, Floating) \
13838 SWITCH_PK_CREATE(CLASS, IRP, IRP_ARGUMENT, Argument) \
13839 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_RETURNED, CallSiteReturned) \
13840 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_ARGUMENT, CallSiteArgument) \
13892#undef CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION
13893#undef CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION
13894#undef CREATE_NON_RET_ABSTRACT_ATTRIBUTE_FOR_POSITION
13895#undef CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION
13896#undef CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION
13897#undef CREATE_ABSTRACT_ATTRIBUTE_FOR_ONE_POSITION
13898#undef SWITCH_PK_CREATE
13899#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.