97#ifndef LLVM_TRANSFORMS_IPO_ATTRIBUTOR_H
98#define LLVM_TRANSFORMS_IPO_ATTRIBUTOR_H
141template <
typename Fn>
class function_ref;
142struct AADepGraphNode;
145struct AbstractAttribute;
146struct InformationCache;
148struct AttributorCallGraph;
176 using Base = std::pair<Value *, const Instruction *>;
196 const Value &V,
bool ForAnalysisOnly =
true);
220std::optional<Value *>
222 const std::optional<Value *> &
B,
Type *Ty);
248 "Inconsistent state!");
284 return L.Offset < R.Offset;
293 static constexpr int64_t
Unassigned = std::numeric_limits<int32_t>::min();
294 static constexpr int64_t
Unknown = std::numeric_limits<int32_t>::max();
298 OS <<
"[" << R.Offset <<
", " << R.Size <<
"]";
303 return A.Offset ==
B.Offset &&
A.Size ==
B.Size;
312 RangeTy *RangePtr =
nullptr);
329 bool OnlyExact =
false);
343 bool OnlyExact =
false);
367 std::function<
bool(
const Function &
F)> GoBackwardsCB =
nullptr);
374 std::function<
bool(
const Function &
F)> GoBackwardsCB =
nullptr);
393 return Base::getEmptyKey();
396 return Base::getTombstoneKey();
399 return Base::getHashValue(VAC);
404 return Base::isEqual(
LHS,
RHS);
418 return Base::getHashValue(S);
422 return Base::isEqual(
LHS,
RHS);
435 super::getTombstoneKey());
440 for (
const auto *II : *BES)
448 if (
LHS == getEmptyKey() ||
RHS == getEmptyKey() ||
449 LHS == getTombstoneKey() ||
RHS == getTombstoneKey())
451 auto SizeLHS =
LHS ?
LHS->size() : 0;
452 auto SizeRHS =
RHS ?
RHS->size() : 0;
453 if (SizeLHS != SizeRHS)
497 return cast<AbstractAttribute>(DT.
getPointer());
586 if (
auto *
Arg = dyn_cast<Argument>(&V))
588 if (
auto *CB = dyn_cast<CallBase>(&V))
667 return Enc ==
RHS.Enc &&
RHS.CBContext == CBContext;
678 switch (getEncodingBits()) {
680 case ENC_RETURNED_VALUE:
681 case ENC_FLOATING_FUNCTION:
682 return *getAsValuePtr();
683 case ENC_CALL_SITE_ARGUMENT_USE:
684 return *(getAsUsePtr()->getUser());
697 return Arg->getParent();
698 return CB->getCalledFunction();
722 if (isa<Function>(V))
723 return &cast<Function>(V);
724 if (isa<Argument>(V))
725 return cast<Argument>(V).getParent();
726 if (isa<Instruction>(V))
727 return cast<Instruction>(V).getFunction();
734 if (
auto *
I = dyn_cast<Instruction>(&V))
736 if (
auto *
Arg = dyn_cast<Argument>(&V))
737 if (!
Arg->getParent()->isDeclaration())
738 return &
Arg->getParent()->getEntryBlock().front();
739 if (
auto *
F = dyn_cast<Function>(&V))
740 if (!
F->isDeclaration())
741 return &(
F->getEntryBlock().front());
767 return getArgNo(
true);
776 return getArgNo(
false);
796 "There is no attribute index for a floating or invalid position!");
801 char EncodingBits = getEncodingBits();
802 if (EncodingBits == ENC_CALL_SITE_ARGUMENT_USE)
804 if (EncodingBits == ENC_FLOATING_FUNCTION)
807 Value *V = getAsValuePtr();
810 if (isa<Argument>(V))
812 if (isa<Function>(V))
814 if (isa<CallBase>(V))
829 bool IgnoreSubsumingPositions =
false,
842 bool IgnoreSubsumingPositions =
false,
862 CB->setAttributes(AttrList);
892 Result.CBContext =
nullptr;
915 : CBContext(CBContext) {
922 : CBContext(CBContext) {
929 if (isa<Function>(AnchorVal) || isa<CallBase>(AnchorVal))
930 Enc = {&AnchorVal, ENC_FLOATING_FUNCTION};
932 Enc = {&AnchorVal, ENC_VALUE};
936 Enc = {&AnchorVal, ENC_VALUE};
940 Enc = {&AnchorVal, ENC_RETURNED_VALUE};
943 Enc = {&AnchorVal, ENC_VALUE};
947 "Cannot create call site argument IRP with an anchor value!");
956 int getArgNo(
bool CallbackCalleeArgIfApplicable)
const {
957 if (CallbackCalleeArgIfApplicable)
959 return Arg->getArgNo();
962 return cast<Argument>(getAsValuePtr())->getArgNo();
964 Use &
U = *getAsUsePtr();
965 return cast<CallBase>(
U.getUser())->getArgOperandNo(&U);
977 "Use constructor is for call site arguments only!");
978 Enc = {&
U, ENC_CALL_SITE_ARGUMENT_USE};
987 SmallVectorImpl<Attribute> &Attrs)
const;
992 SmallVectorImpl<Attribute> &Attrs,
993 Attributor &
A)
const;
997 Value *getAsValuePtr()
const {
998 assert(getEncodingBits() != ENC_CALL_SITE_ARGUMENT_USE &&
999 "Not a value pointer!");
1005 Use *getAsUsePtr()
const {
1006 assert(getEncodingBits() == ENC_CALL_SITE_ARGUMENT_USE &&
1007 "Not a value pointer!");
1008 return reinterpret_cast<Use *
>(Enc.
getPointer());
1013 static bool isReturnPosition(
char EncodingBits) {
1014 return EncodingBits == ENC_RETURNED_VALUE;
1019 bool isReturnPosition()
const {
return isReturnPosition(getEncodingBits()); }
1029 ENC_RETURNED_VALUE = 0b01,
1030 ENC_FLOATING_FUNCTION = 0b10,
1031 ENC_CALL_SITE_ARGUMENT_USE = 0b11,
1036 static constexpr int NumEncodingBits =
1037 PointerLikeTypeTraits<void *>::NumLowBitsAvailable;
1038 static_assert(NumEncodingBits >= 2,
"At least two bits are required!");
1041 PointerIntPair<void *, NumEncodingBits, char> Enc;
1048 char getEncodingBits()
const {
return Enc.getInt(); }
1093 using iterator =
decltype(IRPositions)::iterator;
1116 template <
typename Analysis>
1120 if constexpr (HasLegacyWrapper<Analysis>)
1135 Pass *LegacyPass =
nullptr;
1138template <
typename Analysis>
1140 Analysis, std::void_t<typename Analysis::LegacyWrapper>> =
true;
1168 [&](
const Function &
F) {
1171 AG(AG), TargetTriple(
M.getTargetTriple()) {
1179 for (
auto &It : FuncInfoMap)
1180 It.getSecond()->~FunctionInfo();
1183 for (
auto *BES : BESets)
1184 BES->~InstExclusionSetTy();
1190 template <
typename CBTy>
1192 bool LookThroughConstantExprUses =
true) {
1199 if (LookThroughConstantExprUses && isa<ConstantExpr>(U.getUser())) {
1200 for (
Use &CEU : cast<ConstantExpr>(U.getUser())->
uses())
1220 while (!Worklist.
empty()) {
1225 if (
auto *CB = dyn_cast<CallBase>(&
I))
1232 Worklist.
append(SCC.begin(), SCC.end());
1233 while (!Worklist.
empty()) {
1239 if (
auto *UsrI = dyn_cast<Instruction>(U.getUser()))
1240 if (Seen.
insert(UsrI->getFunction()).second)
1241 Worklist.
push_back(UsrI->getFunction());
1258 return getFunctionInfo(
F).OpcodeInstMap;
1263 return getFunctionInfo(
F).RWInsts;
1282 FunctionInfo &FI = getFunctionInfo(*
Arg.getParent());
1283 return FI.CalledViaMustTail || FI.ContainsMustTailCall;
1287 return AssumeOnlyValues.contains(&
I);
1291 template <
typename AP>
1305 auto It = BESets.find(BES);
1306 if (It != BESets.end())
1309 bool Success = BESets.insert(UniqueBES).second;
1329 struct FunctionInfo {
1341 bool CalledViaMustTail;
1344 bool ContainsMustTailCall;
1348 DenseMap<const Function *, FunctionInfo *> FuncInfoMap;
1351 FunctionInfo &getFunctionInfo(
const Function &
F) {
1352 FunctionInfo *&FI = FuncInfoMap[&
F];
1354 FI =
new (Allocator) FunctionInfo();
1355 initializeInformationCache(
F, *FI);
1364 void initializeInformationCache(
const Function &
F, FunctionInfo &FI);
1367 const DataLayout &DL;
1373 MustBeExecutedContextExplorer Explorer;
1379 SetVector<const Instruction *> AssumeOnlyValues;
1382 DenseSet<const AA::InstExclusionSetTy *> BESets;
1388 SmallPtrSet<const Function *, 8> InlineableFunctions;
1391 Triple TargetTriple;
1485 InfoCache(InfoCache), Configuration(Configuration) {}
1517 template <
typename AAType>
1520 return getOrCreateAAFor<AAType>(IRP, &QueryingAA, DepClass,
1529 template <
typename AAType>
1532 return getOrCreateAAFor<AAType>(IRP, &QueryingAA, DepClass,
1541 template <
typename AAType>
1544 DepClassTy DepClass,
bool ForceUpdate =
false,
1545 bool UpdateAfterInit =
true) {
1546 if (!shouldPropagateCallBaseContext(IRP))
1549 if (AAType *AAPtr = lookupAAFor<AAType>(IRP, QueryingAA, DepClass,
1551 if (ForceUpdate && Phase == AttributorPhase::UPDATE)
1558 auto &AA = AAType::createForPosition(IRP, *
this);
1565 if (Phase == AttributorPhase::SEEDING && !shouldSeedAttribute(AA)) {
1566 AA.getState().indicatePessimisticFixpoint();
1588 AA.getState().indicatePessimisticFixpoint();
1594 ++InitializationChainLength;
1595 AA.initialize(*
this);
1596 --InitializationChainLength;
1603 AA.getState().indicatePessimisticFixpoint();
1609 if (Phase == AttributorPhase::MANIFEST ||
1610 Phase == AttributorPhase::CLEANUP) {
1611 AA.getState().indicatePessimisticFixpoint();
1617 if (UpdateAfterInit) {
1618 AttributorPhase OldPhase = Phase;
1619 Phase = AttributorPhase::UPDATE;
1631 template <
typename AAType>
1633 return getOrCreateAAFor<AAType>(IRP,
nullptr,
1639 template <
typename AAType>
1643 bool AllowInvalidState =
false) {
1644 static_assert(std::is_base_of<AbstractAttribute, AAType>::value,
1645 "Cannot query an attribute with a type not derived from "
1646 "'AbstractAttribute'!");
1653 AAType *AA =
static_cast<AAType *
>(AAPtr);
1662 if (!AllowInvalidState && !AA->getState().isValidState())
1692 static_assert(std::is_base_of<AbstractAttribute, AAType>::value,
1693 "Cannot register an attribute with a type not derived from "
1694 "'AbstractAttribute'!");
1700 assert(!AAPtr &&
"Attribute already in map!");
1704 if (Phase == AttributorPhase::SEEDING || Phase == AttributorPhase::UPDATE)
1720 return Functions.
empty() || Functions.
count(Fn);
1740 return F.hasExactDefinition() || InfoCache.InlineableFunctions.count(&
F);
1749 "Only local linkage is assumed dead initially.");
1768 Value *&V = ToBeChangedUses[&U];
1769 if (V && (V->stripPointerCasts() == NV.stripPointerCasts() ||
1770 isa_and_nonnull<UndefValue>(V)))
1772 assert((!V || V == &NV || isa<UndefValue>(NV)) &&
1773 "Use was registered twice for replacement with different values!");
1782 bool ChangeDroppable =
true) {
1784 auto *CB = cast<CallBase>(IRP.
getCtxI());
1789 auto &Entry = ToBeChangedValues[&V];
1790 Value *CurNV = get<0>(Entry);
1792 isa<UndefValue>(CurNV)))
1794 assert((!CurNV || CurNV == &NV || isa<UndefValue>(NV)) &&
1795 "Value replacement was registered twice with different values!");
1796 Entry = {&NV, ChangeDroppable};
1803 ToBeChangedToUnreachableInsts.insert(
I);
1810 InvokeWithDeadSuccessor.insert(&II);
1824 ManifestAddedBlocks.insert(&BB);
1830 ToBeDeletedFunctions.insert(&
F);
1837 bool &UsedAssumedInformation);
1840 bool &UsedAssumedInformation) {
1848 bool &UsedAssumedInformation,
1854 bool &UsedAssumedInformation,
1857 UsedAssumedInformation, S);
1866 bool &UsedAssumedInformation,
1879 bool &UsedAssumedInformation);
1890 SimplificationCallbacks[IRP].emplace_back(CB);
1895 return SimplificationCallbacks.count(IRP);
1902 VirtualUseCallbacks[&V].emplace_back(CB);
1908 SimplificationCallbacks;
1911 VirtualUseCallbacks;
1915 std::optional<Value *>
1918 bool &UsedAssumedInformation);
1924 bool &UsedAssumedInformation,
1925 bool CheckBBLivenessOnly =
false,
1932 const AAIsDead *LivenessAA,
bool &UsedAssumedInformation,
1933 bool CheckBBLivenessOnly =
false,
1935 bool CheckForDeadStore =
false);
1941 const AAIsDead *FnLivenessAA,
bool &UsedAssumedInformation,
1942 bool CheckBBLivenessOnly =
false,
1949 const AAIsDead *FnLivenessAA,
bool &UsedAssumedInformation,
1950 bool CheckBBLivenessOnly =
false,
1971 bool CheckBBLivenessOnly =
false,
1973 bool IgnoreDroppableUses =
true,
1975 EquivalentUseCB =
nullptr);
1988 template <
typename RemarkKind,
typename RemarkCallBack>
1990 RemarkCallBack &&RemarkCB)
const {
1999 return RemarkCB(RemarkKind(Configuration.
PassName, RemarkName,
I))
2000 <<
" [" << RemarkName <<
"]";
2004 return RemarkCB(RemarkKind(Configuration.
PassName, RemarkName,
I));
2009 template <
typename RemarkKind,
typename RemarkCallBack>
2011 RemarkCallBack &&RemarkCB)
const {
2019 return RemarkCB(RemarkKind(Configuration.
PassName, RemarkName,
F))
2020 <<
" [" << RemarkName <<
"]";
2024 return RemarkCB(RemarkKind(Configuration.
PassName, RemarkName,
F));
2066 return ReplacementTypes;
2080 ReplacementTypes(ReplacementTypes.begin(), ReplacementTypes.end()),
2081 CalleeRepairCB(
std::
move(CalleeRepairCB)),
2082 ACSRepairCB(
std::
move(ACSRepairCB)) {}
2138 bool RequireAllCallSites,
2139 bool &UsedAssumedInformation);
2149 const Function &Fn,
bool RequireAllCallSites,
2151 bool &UsedAssumedInformation,
2152 bool CheckPotentiallyDead =
false);
2180 bool &UsedAssumedInformation,
2181 bool CheckBBLivenessOnly =
false,
2182 bool CheckPotentiallyDead =
false);
2191 bool &UsedAssumedInformation,
2192 bool CheckBBLivenessOnly =
false,
2193 bool CheckPotentiallyDead =
false);
2200 bool &UsedAssumedInformation,
2201 bool CheckBBLivenessOnly =
false,
2202 bool CheckPotentiallyDead =
false) {
2205 {(
unsigned)Instruction::Invoke, (
unsigned)Instruction::CallBr,
2207 UsedAssumedInformation, CheckBBLivenessOnly, CheckPotentiallyDead);
2217 bool &UsedAssumedInformation);
2283 void runTillFixpoint();
2295 void identifyDeadInternalFunctions();
2303 void rememberDependences();
2306 bool shouldPropagateCallBaseContext(
const IRPosition &IRP);
2322 using AAMapKeyTy = std::pair<const char *, IRPosition>;
2328 ArgumentReplacementMap;
2381 enum class AttributorPhase {
2386 } Phase = AttributorPhase::SEEDING;
2389 unsigned InitializationChainLength = 0;
2394 SmallPtrSet<BasicBlock *, 8> ManifestAddedBlocks;
2395 SmallSetVector<Function *, 8> ToBeDeletedFunctions;
2396 SmallSetVector<BasicBlock *, 8> ToBeDeletedBlocks;
2397 SmallSetVector<WeakVH, 8> ToBeDeletedInsts;
2402 SmallSetVector<AbstractAttribute *, 16> QueryAAsAwaitingUpdate;
2405 const AttributorConfig Configuration;
2408 friend AttributorCallGraph;
2466template <
typename base_ty, base_ty BestState, base_ty WorstState>
2520 return !(*
this == R);
2538 joinOR(R.getAssumed(), R.getKnown());
2542 joinAND(R.getAssumed(), R.getKnown());
2566template <
typename base_ty =
uint32_t, base_ty BestState = ~base_ty(0),
2567 base_ty WorstState = 0>
2577 return (this->
Known & BitsEncoding) == BitsEncoding;
2582 return (this->
Assumed & BitsEncoding) == BitsEncoding;
2589 this->
Known |= Bits;
2612 void handleNewAssumedValue(
base_t Value)
override {
2616 void joinOR(
base_t AssumedValue,
base_t KnownValue)
override {
2617 this->
Known |= KnownValue;
2618 this->
Assumed |= AssumedValue;
2620 void joinAND(
base_t AssumedValue,
base_t KnownValue)
override {
2621 this->
Known &= KnownValue;
2622 this->
Assumed &= AssumedValue;
2628template <
typename base_ty =
uint32_t, base_ty BestState = ~base_ty(0),
2629 base_ty WorstState = 0>
2661 void handleNewAssumedValue(
base_t Value)
override {
2665 void joinOR(
base_t AssumedValue,
base_t KnownValue)
override {
2666 this->
Known = std::max(this->
Known, KnownValue);
2669 void joinAND(
base_t AssumedValue,
base_t KnownValue)
override {
2670 this->
Known = std::min(this->
Known, KnownValue);
2677template <
typename base_ty = u
int32_t>
2697 void handleNewAssumedValue(
base_t Value)
override {
2701 void joinOR(
base_t AssumedValue,
base_t KnownValue)
override {
2705 void joinAND(
base_t AssumedValue,
base_t KnownValue)
override {
2735 void handleNewAssumedValue(
base_t Value)
override {
2739 void handleNewKnownValue(
base_t Value)
override {
2743 void joinOR(
base_t AssumedValue,
base_t KnownValue)
override {
2744 Known |= KnownValue;
2747 void joinAND(
base_t AssumedValue,
base_t KnownValue)
override {
2748 Known &= KnownValue;
2775 return ConstantRange::getFull(
BitWidth);
2780 return ConstantRange::getEmpty(
BitWidth);
2875 : Universal(
false), Set(Assumptions) {}
2878 : Universal(Universal), Set(Assumptions) {}
2889 bool IsUniversal = Universal;
2893 if (
RHS.isUniversal())
2902 Universal &=
RHS.isUniversal();
2903 return IsUniversal != Universal ||
Size != Set.
size();
2909 bool IsUniversal = Universal;
2913 if (!
RHS.isUniversal() && !Universal)
2916 Universal |=
RHS.isUniversal();
2917 return IsUniversal != Universal ||
Size != Set.
size();
2933 : Known(Known), Assumed(
true), IsAtFixedpoint(
false) {}
2943 IsAtFixedpoint =
true;
2950 IsAtFixedpoint =
true;
2969 unsigned SizeBefore = Assumed.
getSet().
size();
2976 return SizeBefore != Assumed.
getSet().
size();
2988 SetContents Assumed;
2990 bool IsAtFixedpoint;
2998 bool ForceReplace =
false);
3018template <Attribute::AttrKind AK,
typename BaseType>
3024 const IRPosition &IRP = this->getIRPosition();
3028 this->getState().indicateOptimisticFixpoint();
3041 if (IsFnInterface && (!FnScope || !
A.isFunctionIPOAmendable(*FnScope)))
3042 this->getState().indicatePessimisticFixpoint();
3047 if (isa<UndefValue>(this->getIRPosition().getAssociatedValue()))
3211template <
typename base_ty, base_ty BestState, base_ty WorstState>
3218raw_ostream &
operator<<(raw_ostream &
OS,
const IntegerRangeState &State);
3232template <
typename StateType>
3234 auto Assumed = S.getAssumed();
3246 :
public IRAttribute<Attribute::Returned, AbstractAttribute> {
3275 const std::string
getName()
const override {
return "AAReturnedValues"; }
3292 StateWrapper<BooleanState, AbstractAttribute>> {
3305 const std::string
getName()
const override {
return "AANoUnwind"; }
3321 StateWrapper<BooleanState, AbstractAttribute>> {
3349 const std::string
getName()
const override {
return "AANoSync"; }
3366 StateWrapper<BooleanState, AbstractAttribute>> {
3379 const std::string
getName()
const override {
return "AANonNull"; }
3396 StateWrapper<BooleanState, AbstractAttribute>> {
3409 const std::string
getName()
const override {
return "AANoRecurse"; }
3426 StateWrapper<BooleanState, AbstractAttribute>> {
3439 const std::string
getName()
const override {
return "AAWillReturn"; }
3455 :
public StateWrapper<BooleanState, AbstractAttribute> {
3476 const std::string
getName()
const override {
return "AAUndefinedBehavior"; }
3493 :
public StateWrapper<BooleanState, AbstractAttribute> {
3509 const std::string
getName()
const override {
return "AAIntraFnReachability"; }
3527 StateWrapper<BooleanState, AbstractAttribute>> {
3540 const std::string
getName()
const override {
return "AANoAlias"; }
3557 StateWrapper<BooleanState, AbstractAttribute>> {
3570 const std::string
getName()
const override {
return "AANoFree"; }
3587 StateWrapper<BooleanState, AbstractAttribute>> {
3600 const std::string
getName()
const override {
return "AANoReturn"; }
3616 :
public StateWrapper<BitIntegerState<uint8_t, 3, 0>, AbstractAttribute> {
3659 "Instruction must be in the same anchor scope function.");
3687 const std::string
getName()
const override {
return "AAIsDead"; }
3712 DS.indicatePessimisticFixpoint();
3749 void computeKnownDerefBytesFromAccessedMap() {
3752 if (KnownBytes < Access.first)
3754 KnownBytes = std::max(KnownBytes, Access.first + (int64_t)Access.second);
3787 void takeKnownDerefBytesMaximum(
uint64_t Bytes) {
3791 computeKnownDerefBytesFromAccessedMap();
3795 void takeAssumedDerefBytesMinimum(
uint64_t Bytes) {
3802 AccessedBytes = std::max(AccessedBytes,
Size);
3805 computeKnownDerefBytesFromAccessedMap();
3810 return this->DerefBytesState ==
R.DerefBytesState &&
3811 this->GlobalState ==
R.GlobalState;
3815 bool operator!=(
const DerefState &R)
const {
return !(*
this ==
R); }
3820 GlobalState ^=
R.GlobalState;
3827 GlobalState +=
R.GlobalState;
3834 GlobalState &=
R.GlobalState;
3841 GlobalState |=
R.GlobalState;
3846 const AANonNull *NonNullAA =
nullptr;
3852 StateWrapper<DerefState, AbstractAttribute>> {
3857 return NonNullAA && NonNullAA->isAssumedNonNull();
3862 return NonNullAA && NonNullAA->isKnownNonNull();
3888 const std::string
getName()
const override {
return "AADereferenceable"; }
3907 Attribute::Alignment,
3908 StateWrapper<AAAlignmentStateType, AbstractAttribute>> {
3918 const std::string
getName()
const override {
return "AAAlign"; }
3960 const std::string
getName()
const override {
return "AAInstanceInfo"; }
3978 Attribute::NoCapture,
3979 StateWrapper<BitIntegerState<uint16_t, 7, 0>, AbstractAttribute>> {
4023 const std::string
getName()
const override {
return "AANoCapture"; }
4051 DS.indicatePessimisticFixpoint();
4113 :
public StateWrapper<ValueSimplifyStateType, AbstractAttribute, Type *> {
4123 const std::string
getName()
const override {
return "AAValueSimplify"; }
4143 virtual std::optional<Value *>
4144 getAssumedSimplifiedValue(
Attributor &
A)
const = 0;
4164 const std::string
getName()
const override {
return "AAHeapToStack"; }
4189 :
public StateWrapper<BooleanState, AbstractAttribute> {
4209 const std::string
getName()
const override {
return "AAPrivatizablePtr"; }
4228 Attribute::ReadNone,
4229 StateWrapper<BitIntegerState<uint8_t, 3>, AbstractAttribute>> {
4272 const std::string
getName()
const override {
return "AAMemoryBehavior"; }
4291 Attribute::ReadNone,
4292 StateWrapper<BitIntegerState<uint32_t, 511>, AbstractAttribute>> {