17#include "llvm/IR/IntrinsicsAMDGPU.h"
18#include "llvm/IR/IntrinsicsR600.h"
23#define DEBUG_TYPE "amdgpu-attributor"
28 "amdgpu-indirect-call-specialization-threshold",
30 "A threshold controls whether an indirect call will be specialized"),
33#define AMDGPU_ATTRIBUTE(Name, Str) Name##_POS,
36#include "AMDGPUAttributes.def"
40#define AMDGPU_ATTRIBUTE(Name, Str) Name = 1 << Name##_POS,
44#include "AMDGPUAttributes.def"
49#define AMDGPU_ATTRIBUTE(Name, Str) {Name, Str},
50static constexpr std::pair<ImplicitArgumentMask, StringLiteral>
52#include "AMDGPUAttributes.def"
62 bool HasApertureRegs,
bool SupportsGetDoorBellID,
63 unsigned CodeObjectVersion) {
65 case Intrinsic::amdgcn_workitem_id_x:
68 case Intrinsic::amdgcn_workgroup_id_x:
70 return WORKGROUP_ID_X;
71 case Intrinsic::amdgcn_workitem_id_y:
72 case Intrinsic::r600_read_tidig_y:
74 case Intrinsic::amdgcn_workitem_id_z:
75 case Intrinsic::r600_read_tidig_z:
77 case Intrinsic::amdgcn_workgroup_id_y:
78 case Intrinsic::r600_read_tgid_y:
79 return WORKGROUP_ID_Y;
80 case Intrinsic::amdgcn_workgroup_id_z:
81 case Intrinsic::r600_read_tgid_z:
82 return WORKGROUP_ID_Z;
83 case Intrinsic::amdgcn_cluster_id_x:
86 case Intrinsic::amdgcn_cluster_id_y:
88 case Intrinsic::amdgcn_cluster_id_z:
90 case Intrinsic::amdgcn_lds_kernel_id:
92 case Intrinsic::amdgcn_dispatch_ptr:
94 case Intrinsic::amdgcn_dispatch_id:
96 case Intrinsic::amdgcn_implicitarg_ptr:
97 return IMPLICIT_ARG_PTR;
100 case Intrinsic::amdgcn_queue_ptr:
103 case Intrinsic::amdgcn_is_shared:
104 case Intrinsic::amdgcn_is_private:
112 case Intrinsic::amdgcn_wwm:
113 case Intrinsic::amdgcn_strict_wwm:
114 return WHOLE_WAVE_MODE;
115 case Intrinsic::trap:
116 case Intrinsic::debugtrap:
117 case Intrinsic::ubsantrap:
118 if (SupportsGetDoorBellID)
142 return F.hasFnAttribute(Attribute::SanitizeAddress) ||
143 F.hasFnAttribute(Attribute::SanitizeThread) ||
144 F.hasFnAttribute(Attribute::SanitizeMemory) ||
145 F.hasFnAttribute(Attribute::SanitizeHWAddress) ||
146 F.hasFnAttribute(Attribute::SanitizeMemTag);
152 AMDGPUInformationCache(
const Module &M, AnalysisGetter &AG,
154 SetVector<Function *> *
CGSCC, TargetMachine &TM)
160 unsigned COV = CodeObjectVersion;
161 ImplicitArgRanges = {
169 ImplicitArgRanges.push_back(
171 ImplicitArgRanges.push_back(
176 for (
auto [Mask,
Range] : ImplicitArgRanges) {
177 ImplicitArgsMask |=
Mask;
178 Begin = std::min(Begin,
Range.Offset);
182 ImplicitArgsRange = AA::RangeTy(Begin,
End - Begin);
187 enum ConstantStatus : uint8_t {
190 ADDR_SPACE_CAST_PRIVATE_TO_FLAT = 1 << 1,
191 ADDR_SPACE_CAST_LOCAL_TO_FLAT = 1 << 2,
192 ADDR_SPACE_CAST_BOTH_TO_FLAT =
193 ADDR_SPACE_CAST_PRIVATE_TO_FLAT | ADDR_SPACE_CAST_LOCAL_TO_FLAT,
194 CS_WORST = DS_GLOBAL | ADDR_SPACE_CAST_BOTH_TO_FLAT,
197 std::optional<std::pair<unsigned, unsigned>>
198 getFlatWorkGroupSizeAttr(
const Function &
F)
const {
202 return std::make_pair(
R->first, *(
R->second));
205 std::pair<unsigned, unsigned>
206 getDefaultFlatWorkGroupSize(
const Function &
F)
const {
207 const GCNSubtarget &
ST = TM.getSubtarget<GCNSubtarget>(
F);
208 return ST.getDefaultFlatWorkGroupSize(
F.getCallingConv());
211 std::pair<unsigned, unsigned> getMaximumFlatWorkGroupRange()
const {
217 unsigned getCodeObjectVersion()
const {
return CodeObjectVersion; }
222 getImplicitArgRanges()
const {
223 return ImplicitArgRanges;
227 uint32_t getImplicitArgsMask()
const {
return ImplicitArgsMask; }
230 AA::RangeTy getImplicitArgsRange()
const {
return ImplicitArgsRange; }
235 std::optional<std::pair<unsigned, unsigned>>
243 return std::make_pair(Val->first, *(Val->second));
250 unsigned getMaxAddrSpace()
const override {
257 static uint8_t visitConstExpr(
const ConstantExpr *CE) {
258 uint8_t Status = NONE;
260 if (
CE->getOpcode() == Instruction::AddrSpaceCast) {
261 unsigned SrcAS =
CE->getOperand(0)->getType()->getPointerAddressSpace();
263 Status |= ADDR_SPACE_CAST_PRIVATE_TO_FLAT;
265 Status |= ADDR_SPACE_CAST_LOCAL_TO_FLAT;
272 uint8_t getConstantAccess(
const Constant *
C) {
276 const auto &It = ConstantStatus.find(
C);
277 if (It != ConstantStatus.end())
278 return It->second.value();
280 SmallPtrSet<const Constant *, 8> Visited;
286 while (Result != CS_WORST && !Worklist.
empty()) {
289 std::optional<uint8_t> &CurCResultOrNone = ConstantStatus[CurC];
290 if (CurCResultOrNone) {
291 Result |= CurCResultOrNone.value();
294 uint8_t CurCResult = 0;
297 CurCResult |= DS_GLOBAL;
300 CurCResult |= visitConstExpr(CE);
302 for (
const Use &U : CurC->
operands()) {
304 if (Visited.
insert(OpC).second)
309 CurCResultOrNone = CurCResult;
319 bool needsQueuePtr(
const Constant *
C,
Function &Fn) {
321 bool HasAperture = Features.test(AMDGPU::FEAT_APERTURE_REGS);
324 if (!IsNonEntryFunc && HasAperture)
327 uint8_t
Access = getConstantAccess(
C);
330 if (IsNonEntryFunc && (
Access & DS_GLOBAL))
333 return !HasAperture && (
Access & ADDR_SPACE_CAST_BOTH_TO_FLAT);
336 bool checkConstForAddrSpaceCastFromPrivate(
const Constant *
C) {
337 uint8_t
Access = getConstantAccess(
C);
338 return Access & ADDR_SPACE_CAST_PRIVATE_TO_FLAT;
343 DenseMap<const Constant *, std::optional<uint8_t>> ConstantStatus;
346 const unsigned CodeObjectVersion;
349 uint32_t ImplicitArgsMask = 0;
350 AA::RangeTy ImplicitArgsRange;
353struct AAAMDAttributes
354 :
public StateWrapper<BitIntegerState<uint32_t, ALL_ARGUMENT_MASK, 0>,
356 using Base = StateWrapper<BitIntegerState<uint32_t, ALL_ARGUMENT_MASK, 0>,
359 AAAMDAttributes(
const IRPosition &IRP, Attributor &
A) : Base(IRP) {}
362 static AAAMDAttributes &createForPosition(
const IRPosition &IRP,
366 StringRef
getName()
const override {
return "AAAMDAttributes"; }
369 const char *getIdAddr()
const override {
return &ID; }
373 static bool classof(
const AbstractAttribute *AA) {
378 static const char ID;
380const char AAAMDAttributes::ID = 0;
382struct AAUniformWorkGroupSize
383 :
public StateWrapper<BooleanState, AbstractAttribute> {
384 using Base = StateWrapper<BooleanState, AbstractAttribute>;
385 AAUniformWorkGroupSize(
const IRPosition &IRP, Attributor &
A) : Base(IRP) {}
388 static AAUniformWorkGroupSize &createForPosition(
const IRPosition &IRP,
392 StringRef
getName()
const override {
return "AAUniformWorkGroupSize"; }
395 const char *getIdAddr()
const override {
return &ID; }
399 static bool classof(
const AbstractAttribute *AA) {
404 static const char ID;
406const char AAUniformWorkGroupSize::ID = 0;
408struct AAUniformWorkGroupSizeFunction :
public AAUniformWorkGroupSize {
409 AAUniformWorkGroupSizeFunction(
const IRPosition &IRP, Attributor &
A)
410 : AAUniformWorkGroupSize(IRP,
A) {}
414 CallingConv::ID CC =
F->getCallingConv();
416 if (CC != CallingConv::AMDGPU_KERNEL)
419 bool InitialValue =
F->hasFnAttribute(
"uniform-work-group-size");
422 indicateOptimisticFixpoint();
424 indicatePessimisticFixpoint();
430 auto CheckCallSite = [&](AbstractCallSite CS) {
433 <<
"->" << getAssociatedFunction()->
getName() <<
"\n");
435 const auto *CallerInfo =
A.getAAFor<AAUniformWorkGroupSize>(
437 if (!CallerInfo || !CallerInfo->isValidState())
441 CallerInfo->getState());
446 bool AllCallSitesKnown =
true;
447 if (!
A.checkForAllCallSites(CheckCallSite, *
this,
true, AllCallSitesKnown))
448 return indicatePessimisticFixpoint();
455 return ChangeStatus::UNCHANGED;
457 LLVMContext &Ctx = getAssociatedFunction()->getContext();
458 return A.manifestAttrs(getIRPosition(),
459 {Attribute::get(Ctx,
"uniform-work-group-size")},
463 bool isValidState()
const override {
468 const std::string getAsStr(Attributor *)
const override {
469 return "AMDWorkGroupSize[" + std::to_string(getAssumed()) +
"]";
473 void trackStatistics()
const override {}
476AAUniformWorkGroupSize &
477AAUniformWorkGroupSize::createForPosition(
const IRPosition &IRP,
480 return *
new (
A.Allocator) AAUniformWorkGroupSizeFunction(IRP,
A);
482 "AAUniformWorkGroupSize is only valid for function position");
485struct AAAMDAttributesFunction :
public AAAMDAttributes {
486 AAAMDAttributesFunction(
const IRPosition &IRP, Attributor &
A)
487 : AAAMDAttributes(IRP,
A) {}
499 if (HasSanitizerAttrs) {
500 removeAssumedBits(IMPLICIT_ARG_PTR);
501 removeAssumedBits(HOSTCALL_PTR);
502 removeAssumedBits(FLAT_SCRATCH_INIT);
506 if (HasSanitizerAttrs &&
507 (Attr.first == IMPLICIT_ARG_PTR || Attr.first == HOSTCALL_PTR ||
508 Attr.first == FLAT_SCRATCH_INIT))
511 if (
F->hasFnAttribute(Attr.second))
512 addKnownBits(Attr.first);
515 if (
F->isDeclaration())
521 indicatePessimisticFixpoint();
529 auto OrigAssumed = getAssumed();
532 const AACallEdges *AAEdges =
A.getAAFor<AACallEdges>(
533 *
this, this->getIRPosition(), DepClassTy::REQUIRED);
536 return indicatePessimisticFixpoint();
540 bool NeedsImplicit =
false;
541 auto &InfoCache =
static_cast<AMDGPUInformationCache &
>(
A.getInfoCache());
543 bool HasApertureRegs = Features.
test(AMDGPU::FEAT_APERTURE_REGS);
544 bool SupportsGetDoorbellID = Features.
test(AMDGPU::FEAT_GET_DOORBELL_ID);
545 unsigned COV = InfoCache.getCodeObjectVersion();
550 const AAAMDAttributes *AAAMD =
A.getAAFor<AAAMDAttributes>(
552 if (!AAAMD || !AAAMD->isValidState())
553 return indicatePessimisticFixpoint();
558 bool NonKernelOnly =
false;
561 HasApertureRegs, SupportsGetDoorbellID, COV);
572 if (!
Callee->hasFnAttribute(Attribute::NoCallback))
573 return indicatePessimisticFixpoint();
578 if ((IsNonEntryFunc || !NonKernelOnly))
579 removeAssumedBits(AttrMask);
585 removeAssumedBits(IMPLICIT_ARG_PTR);
587 if (isAssumed(QUEUE_PTR) && checkForQueuePtr(
A)) {
591 removeAssumedBits(IMPLICIT_ARG_PTR);
593 removeAssumedBits(QUEUE_PTR);
596 uint32_t Retrieved = getRetrievedImplicitArgs(
A);
598 if (Retrieved & MULTIGRID_SYNC_ARG) {
599 assert(!isAssumed(IMPLICIT_ARG_PTR) &&
600 "multigrid_sync_arg needs implicitarg_ptr");
601 removeAssumedBits(MULTIGRID_SYNC_ARG);
604 if (Retrieved & HOSTCALL_PTR) {
605 assert(!isAssumed(IMPLICIT_ARG_PTR) &&
"hostcall needs implicitarg_ptr");
606 removeAssumedBits(HOSTCALL_PTR);
609 if (Retrieved & HEAP_PTR) {
610 assert(!isAssumed(IMPLICIT_ARG_PTR) &&
"heap_ptr needs implicitarg_ptr");
611 removeAssumedBits(HEAP_PTR);
614 if (isAssumed(QUEUE_PTR) && (Retrieved & QUEUE_PTR)) {
615 assert(!isAssumed(IMPLICIT_ARG_PTR) &&
"queue_ptr needs implicitarg_ptr");
616 removeAssumedBits(QUEUE_PTR);
619 if (isAssumed(LDS_KERNEL_ID) && (Retrieved & LDS_KERNEL_ID)) {
620 removeAssumedBits(LDS_KERNEL_ID);
623 if (isAssumed(DEFAULT_QUEUE) && (Retrieved & DEFAULT_QUEUE))
624 removeAssumedBits(DEFAULT_QUEUE);
626 if (isAssumed(COMPLETION_ACTION) && (Retrieved & COMPLETION_ACTION))
627 removeAssumedBits(COMPLETION_ACTION);
629 if (isAssumed(FLAT_SCRATCH_INIT) && needFlatScratchInit(
A))
630 removeAssumedBits(FLAT_SCRATCH_INIT);
632 return getAssumed() != OrigAssumed ? ChangeStatus::CHANGED
633 : ChangeStatus::UNCHANGED;
638 LLVMContext &Ctx = getAssociatedFunction()->getContext();
641 if (isKnown(Attr.first))
642 AttrList.
push_back(Attribute::get(Ctx, Attr.second));
645 return A.manifestAttrs(getIRPosition(), AttrList,
649 const std::string getAsStr(Attributor *)
const override {
651 raw_string_ostream OS(Str);
654 if (isAssumed(Attr.first))
655 OS <<
' ' << Attr.second;
661 void trackStatistics()
const override {}
664 bool checkForQueuePtr(Attributor &
A) {
668 auto &InfoCache =
static_cast<AMDGPUInformationCache &
>(
A.getInfoCache());
670 bool NeedsQueuePtr =
false;
673 unsigned SrcAS =
static_cast<AddrSpaceCastInst &
>(
I).getSrcAddressSpace();
675 NeedsQueuePtr =
true;
681 bool HasApertureRegs =
682 InfoCache.getFeatures().test(AMDGPU::FEAT_APERTURE_REGS);
688 if (!HasApertureRegs) {
689 bool UsedAssumedInformation =
false;
690 A.checkForAllInstructions(CheckAddrSpaceCasts, *
this,
691 {Instruction::AddrSpaceCast},
692 UsedAssumedInformation);
699 if (!IsNonEntryFunc && HasApertureRegs)
702 for (BasicBlock &BB : *
F) {
703 for (Instruction &
I : BB) {
704 for (
const Use &U :
I.operands()) {
706 if (InfoCache.needsQueuePtr(
C, *
F))
718 uint32_t getImplicitArgsReadThrough(Attributor &
A,
const CallBase &
Call) {
719 auto &InfoCache =
static_cast<AMDGPUInformationCache &
>(
A.getInfoCache());
720 uint32_t ArgsMask = InfoCache.getImplicitArgsMask();
721 const auto *PointerInfoAA =
A.getAAFor<AAPointerInfo>(
723 if (!PointerInfoAA || !PointerInfoAA->getState().isValidState())
730 auto CheckAccess = [&](
const AAPointerInfo::Access &Acc, bool) {
733 for (
const AA::RangeTy &AccRange : Acc.
getRanges()) {
734 for (
auto [Mask,
Range] : InfoCache.getImplicitArgRanges()) {
735 if (AccRange.mayOverlap(
Range))
740 return Read != ArgsMask;
743 if (!PointerInfoAA->forallInterferingAccesses(
744 InfoCache.getImplicitArgsRange(), CheckAccess))
751 uint32_t getRetrievedImplicitArgs(Attributor &
A) {
752 auto &InfoCache =
static_cast<AMDGPUInformationCache &
>(
A.getInfoCache());
753 uint32_t
All = InfoCache.getImplicitArgsMask() | LDS_KERNEL_ID;
754 uint32_t Retrieved = 0;
758 case Intrinsic::amdgcn_implicitarg_ptr:
759 Retrieved |= getImplicitArgsReadThrough(
A,
Call);
761 case Intrinsic::amdgcn_lds_kernel_id:
762 Retrieved |= LDS_KERNEL_ID;
770 return Retrieved !=
All;
773 bool UsedAssumedInformation =
false;
774 if (!
A.checkForAllCallLikeInstructions(CheckCall, *
this,
775 UsedAssumedInformation))
782 bool needFlatScratchInit(Attributor &
A) {
783 assert(isAssumed(FLAT_SCRATCH_INIT));
792 bool UsedAssumedInformation =
false;
793 if (!
A.checkForAllInstructions(AddrSpaceCastNotFromPrivate, *
this,
794 {Instruction::AddrSpaceCast},
795 UsedAssumedInformation))
799 auto &InfoCache =
static_cast<AMDGPUInformationCache &
>(
A.getInfoCache());
803 for (
const Use &U :
I.operands()) {
805 if (InfoCache.checkConstForAddrSpaceCastFromPrivate(
C))
815AAAMDAttributes &AAAMDAttributes::createForPosition(
const IRPosition &IRP,
818 return *
new (
A.Allocator) AAAMDAttributesFunction(IRP,
A);
823struct AAAMDSizeRangeAttribute
824 :
public StateWrapper<IntegerRangeState, AbstractAttribute, uint32_t> {
825 using Base = StateWrapper<IntegerRangeState, AbstractAttribute, uint32_t>;
829 AAAMDSizeRangeAttribute(
const IRPosition &IRP, Attributor &
A,
831 :
Base(IRP, 32), AttrName(AttrName) {}
834 void trackStatistics()
const override {}
836 template <
class AttributeImpl>
ChangeStatus updateImplImpl(Attributor &
A) {
839 auto CheckCallSite = [&](AbstractCallSite CS) {
842 <<
"->" << getAssociatedFunction()->
getName() <<
'\n');
844 const auto *CallerInfo =
A.getAAFor<AttributeImpl>(
846 if (!CallerInfo || !CallerInfo->isValidState())
855 bool AllCallSitesKnown =
true;
856 if (!
A.checkForAllCallSites(CheckCallSite, *
this,
859 return indicatePessimisticFixpoint();
867 emitAttributeIfNotDefaultAfterClamp(Attributor &
A,
868 std::pair<unsigned, unsigned>
Default) {
870 unsigned Lower = getAssumed().getLower().getZExtValue();
871 unsigned Upper = getAssumed().getUpper().getZExtValue();
881 return ChangeStatus::UNCHANGED;
884 LLVMContext &Ctx =
F->getContext();
885 SmallString<10> Buffer;
886 raw_svector_ostream OS(Buffer);
888 return A.manifestAttrs(getIRPosition(),
889 {Attribute::get(Ctx, AttrName, OS.str())},
893 const std::string getAsStr(Attributor *)
const override {
895 raw_string_ostream OS(Str);
897 OS << getAssumed().getLower() <<
',' << getAssumed().getUpper() - 1;
904struct AAAMDFlatWorkGroupSize :
public AAAMDSizeRangeAttribute {
905 AAAMDFlatWorkGroupSize(
const IRPosition &IRP, Attributor &
A)
906 : AAAMDSizeRangeAttribute(IRP,
A,
"amdgpu-flat-work-group-size") {}
910 auto &InfoCache =
static_cast<AMDGPUInformationCache &
>(
A.getInfoCache());
912 bool HasAttr =
false;
913 auto Range = InfoCache.getDefaultFlatWorkGroupSize(*
F);
914 auto MaxRange = InfoCache.getMaximumFlatWorkGroupRange();
916 if (
auto Attr = InfoCache.getFlatWorkGroupSizeAttr(*
F)) {
920 if (*Attr != MaxRange) {
928 if (
Range == MaxRange)
932 ConstantRange CR(APInt(32, Min), APInt(32, Max + 1));
933 IntegerRangeState IRS(CR);
937 indicateOptimisticFixpoint();
941 return updateImplImpl<AAAMDFlatWorkGroupSize>(
A);
945 static AAAMDFlatWorkGroupSize &createForPosition(
const IRPosition &IRP,
949 auto &InfoCache =
static_cast<AMDGPUInformationCache &
>(
A.getInfoCache());
950 return emitAttributeIfNotDefaultAfterClamp(
951 A, InfoCache.getMaximumFlatWorkGroupRange());
955 StringRef
getName()
const override {
return "AAAMDFlatWorkGroupSize"; }
958 const char *getIdAddr()
const override {
return &
ID; }
962 static bool classof(
const AbstractAttribute *AA) {
967 static const char ID;
970const char AAAMDFlatWorkGroupSize::ID = 0;
972AAAMDFlatWorkGroupSize &
973AAAMDFlatWorkGroupSize::createForPosition(
const IRPosition &IRP,
976 return *
new (
A.Allocator) AAAMDFlatWorkGroupSize(IRP,
A);
978 "AAAMDFlatWorkGroupSize is only valid for function position");
981struct TupleDecIntegerRangeState :
public AbstractState {
982 DecIntegerState<uint32_t>
X,
Y, Z;
984 bool isValidState()
const override {
985 return X.isValidState() &&
Y.isValidState() &&
Z.isValidState();
988 bool isAtFixpoint()
const override {
989 return X.isAtFixpoint() &&
Y.isAtFixpoint() &&
Z.isAtFixpoint();
993 return X.indicateOptimisticFixpoint() |
Y.indicateOptimisticFixpoint() |
994 Z.indicateOptimisticFixpoint();
998 return X.indicatePessimisticFixpoint() |
Y.indicatePessimisticFixpoint() |
999 Z.indicatePessimisticFixpoint();
1002 TupleDecIntegerRangeState
operator^=(
const TupleDecIntegerRangeState &
Other) {
1013 TupleDecIntegerRangeState &getAssumed() {
return *
this; }
1014 const TupleDecIntegerRangeState &getAssumed()
const {
return *
this; }
1017using AAAMDMaxNumWorkgroupsState =
1018 StateWrapper<TupleDecIntegerRangeState, AbstractAttribute, uint32_t>;
1021struct AAAMDMaxNumWorkgroups
1022 :
public StateWrapper<TupleDecIntegerRangeState, AbstractAttribute> {
1023 using Base = StateWrapper<TupleDecIntegerRangeState, AbstractAttribute>;
1025 AAAMDMaxNumWorkgroups(
const IRPosition &IRP, Attributor &
A) :
Base(IRP) {}
1032 X.takeKnownMinimum(MaxNumWorkgroups[0]);
1033 Y.takeKnownMinimum(MaxNumWorkgroups[1]);
1034 Z.takeKnownMinimum(MaxNumWorkgroups[2]);
1037 indicatePessimisticFixpoint();
1043 auto CheckCallSite = [&](AbstractCallSite CS) {
1046 <<
"->" << getAssociatedFunction()->
getName() <<
'\n');
1048 const auto *CallerInfo =
A.getAAFor<AAAMDMaxNumWorkgroups>(
1050 if (!CallerInfo || !CallerInfo->isValidState())
1058 bool AllCallSitesKnown =
true;
1059 if (!
A.checkForAllCallSites(CheckCallSite, *
this,
1062 return indicatePessimisticFixpoint();
1068 static AAAMDMaxNumWorkgroups &createForPosition(
const IRPosition &IRP,
1073 LLVMContext &Ctx =
F->getContext();
1074 SmallString<32> Buffer;
1075 raw_svector_ostream OS(Buffer);
1076 OS <<
X.getAssumed() <<
',' <<
Y.getAssumed() <<
',' <<
Z.getAssumed();
1080 return A.manifestAttrs(
1082 {Attribute::get(Ctx,
"amdgpu-max-num-workgroups", OS.str())},
1086 StringRef
getName()
const override {
return "AAAMDMaxNumWorkgroups"; }
1088 const std::string getAsStr(Attributor *)
const override {
1089 std::string Buffer =
"AAAMDMaxNumWorkgroupsState[";
1090 raw_string_ostream OS(Buffer);
1091 OS <<
X.getAssumed() <<
',' <<
Y.getAssumed() <<
',' <<
Z.getAssumed()
1096 const char *getIdAddr()
const override {
return &
ID; }
1100 static bool classof(
const AbstractAttribute *AA) {
1104 void trackStatistics()
const override {}
1107 static const char ID;
1110const char AAAMDMaxNumWorkgroups::ID = 0;
1112AAAMDMaxNumWorkgroups &
1113AAAMDMaxNumWorkgroups::createForPosition(
const IRPosition &IRP, Attributor &
A) {
1115 return *
new (
A.Allocator) AAAMDMaxNumWorkgroups(IRP,
A);
1116 llvm_unreachable(
"AAAMDMaxNumWorkgroups is only valid for function position");
1120struct AAAMDWavesPerEU :
public AAAMDSizeRangeAttribute {
1121 AAAMDWavesPerEU(
const IRPosition &IRP, Attributor &
A)
1122 : AAAMDSizeRangeAttribute(IRP,
A,
"amdgpu-waves-per-eu") {}
1126 auto &InfoCache =
static_cast<AMDGPUInformationCache &
>(
A.getInfoCache());
1129 if (
auto Attr = InfoCache.getWavesPerEUAttr(*
F)) {
1130 std::pair<unsigned, unsigned> MaxWavesPerEURange{
1131 1U, InfoCache.getMaxWavesPerEU()};
1132 if (*Attr != MaxWavesPerEURange) {
1133 auto [Min,
Max] = *Attr;
1134 ConstantRange
Range(APInt(32, Min), APInt(32, Max + 1));
1135 IntegerRangeState RangeState(
Range);
1136 this->getState() = RangeState;
1137 indicateOptimisticFixpoint();
1143 indicatePessimisticFixpoint();
1149 auto CheckCallSite = [&](AbstractCallSite CS) {
1153 <<
"->" <<
Func->getName() <<
'\n');
1156 const auto *CallerAA =
A.getAAFor<AAAMDWavesPerEU>(
1158 if (!CallerAA || !CallerAA->isValidState())
1161 ConstantRange Assumed = getAssumed();
1163 CallerAA->getAssumed().getLower().getZExtValue());
1165 CallerAA->getAssumed().getUpper().getZExtValue());
1166 ConstantRange
Range(APInt(32, Min), APInt(32, Max));
1167 IntegerRangeState RangeState(
Range);
1168 getState() = RangeState;
1169 Change |= getState() == Assumed ? ChangeStatus::UNCHANGED
1170 : ChangeStatus::CHANGED;
1175 bool AllCallSitesKnown =
true;
1176 if (!
A.checkForAllCallSites(CheckCallSite, *
this,
true, AllCallSitesKnown))
1177 return indicatePessimisticFixpoint();
1183 static AAAMDWavesPerEU &createForPosition(
const IRPosition &IRP,
1187 auto &InfoCache =
static_cast<AMDGPUInformationCache &
>(
A.getInfoCache());
1188 return emitAttributeIfNotDefaultAfterClamp(
1189 A, {1U, InfoCache.getMaxWavesPerEU()});
1193 StringRef
getName()
const override {
return "AAAMDWavesPerEU"; }
1196 const char *getIdAddr()
const override {
return &
ID; }
1200 static bool classof(
const AbstractAttribute *AA) {
1205 static const char ID;
1208const char AAAMDWavesPerEU::ID = 0;
1210AAAMDWavesPerEU &AAAMDWavesPerEU::createForPosition(
const IRPosition &IRP,
1213 return *
new (
A.Allocator) AAAMDWavesPerEU(IRP,
A);
1218static unsigned inlineAsmGetNumRequiredAGPRs(
const InlineAsm *IA,
1219 const CallBase &
Call) {
1222 unsigned AGPRDefCount = 0;
1223 unsigned AGPRUseCount = 0;
1224 unsigned MaxPhysReg = 0;
1228 for (
const InlineAsm::ConstraintInfo &CI :
IA->ParseConstraints()) {
1234 Ty = STy->getElementType(ResNo);
1249 for (StringRef Code : CI.Codes) {
1250 unsigned RegCount = 0;
1251 if (
Code.starts_with(
"a")) {
1262 MaxPhysReg = std::max(MaxPhysReg, std::min(RegIdx + NumRegs, 256u));
1272 AGPRDefCount =
alignTo(AGPRDefCount, RegCount);
1274 AGPRDefCount += RegCount;
1275 if (CI.isEarlyClobber) {
1276 AGPRUseCount =
alignTo(AGPRUseCount, RegCount);
1277 AGPRUseCount += RegCount;
1280 AGPRUseCount =
alignTo(AGPRUseCount, RegCount);
1281 AGPRUseCount += RegCount;
1286 unsigned MaxVirtReg = std::max(AGPRUseCount, AGPRDefCount);
1291 return std::min(MaxVirtReg + MaxPhysReg, 256u);
1294struct AAAMDGPUMinAGPRAlloc
1295 :
public StateWrapper<DecIntegerState<>, AbstractAttribute> {
1296 using Base = StateWrapper<DecIntegerState<>, AbstractAttribute>;
1297 AAAMDGPUMinAGPRAlloc(
const IRPosition &IRP, Attributor &
A) :
Base(IRP) {}
1299 static AAAMDGPUMinAGPRAlloc &createForPosition(
const IRPosition &IRP,
1302 return *
new (
A.Allocator) AAAMDGPUMinAGPRAlloc(IRP,
A);
1304 "AAAMDGPUMinAGPRAlloc is only valid for function position");
1309 auto [MinNumAGPR, MaxNumAGPR] =
1312 if (MinNumAGPR == 0) {
1313 indicateOptimisticFixpoint();
1318 indicatePessimisticFixpoint();
1321 const std::string getAsStr(Attributor *
A)
const override {
1322 std::string Str =
"amdgpu-agpr-alloc=";
1323 raw_string_ostream OS(Str);
1328 void trackStatistics()
const override {}
1331 DecIntegerState<> Maximum;
1338 const Value *CalleeOp = CB.getCalledOperand();
1343 unsigned NumRegs = inlineAsmGetNumRequiredAGPRs(IA, CB);
1347 switch (CB.getIntrinsicID()) {
1350 case Intrinsic::write_register:
1351 case Intrinsic::read_register:
1352 case Intrinsic::read_volatile_register: {
1357 auto [
Kind, RegIdx, NumRegs] =
1371 case Intrinsic::trap:
1372 case Intrinsic::debugtrap:
1373 case Intrinsic::ubsantrap:
1374 return CB.hasFnAttr(Attribute::NoCallback) ||
1375 !CB.hasFnAttr(
"trap-func-name");
1381 return CB.hasFnAttr(Attribute::NoCallback);
1385 auto *CBEdges =
A.getAAFor<AACallEdges>(
1387 if (!CBEdges || CBEdges->hasUnknownCallee()) {
1392 for (
const Function *PossibleCallee : CBEdges->getOptimisticEdges()) {
1393 const auto *CalleeInfo =
A.getAAFor<AAAMDGPUMinAGPRAlloc>(
1395 if (!CalleeInfo || !CalleeInfo->isValidState()) {
1406 bool UsedAssumedInformation =
false;
1407 if (!
A.checkForAllCallLikeInstructions(CheckForMinAGPRAllocs, *
this,
1408 UsedAssumedInformation))
1409 return indicatePessimisticFixpoint();
1415 LLVMContext &Ctx = getAssociatedFunction()->getContext();
1416 SmallString<4> Buffer;
1417 raw_svector_ostream OS(Buffer);
1420 return A.manifestAttrs(
1421 getIRPosition(), {Attribute::get(Ctx,
"amdgpu-agpr-alloc", OS.str())});
1424 StringRef
getName()
const override {
return "AAAMDGPUMinAGPRAlloc"; }
1425 const char *getIdAddr()
const override {
return &
ID; }
1429 static bool classof(
const AbstractAttribute *AA) {
1433 static const char ID;
1436const char AAAMDGPUMinAGPRAlloc::ID = 0;
1439struct AAAMDGPUNoLDSDMA :
public StateWrapper<BooleanState, AbstractAttribute> {
1440 using Base = StateWrapper<BooleanState, AbstractAttribute>;
1441 AAAMDGPUNoLDSDMA(
const IRPosition &IRP, Attributor &
A) :
Base(IRP) {}
1444 static AAAMDGPUNoLDSDMA &createForPosition(
const IRPosition &IRP,
1447 "AAAMDGPUNoLDSDMA is only valid for function position");
1448 return *
new (
A.Allocator) AAAMDGPUNoLDSDMA(IRP,
A);
1452 const Function *
F = getAssociatedFunction();
1453 if (
F->hasFnAttribute(
"amdgpu-no-lds-dma")) {
1454 indicateOptimisticFixpoint();
1458 if (
F->isDeclaration())
1459 indicatePessimisticFixpoint();
1476 CB.hasFnAttr(Attribute::NoCallback);
1479 const auto *CBEdges =
A.getAAFor<AACallEdges>(
1481 if (!CBEdges || CBEdges->hasUnknownCallee())
1484 for (
const Function *PossibleCallee : CBEdges->getOptimisticEdges()) {
1485 const auto *CalleeInfo =
A.getAAFor<AAAMDGPUNoLDSDMA>(
1487 if (!CalleeInfo || !CalleeInfo->getAssumed())
1494 bool UsedAssumedInformation =
false;
1495 if (!
A.checkForAllCallLikeInstructions(CheckNoLDSDMA, *
this,
1496 UsedAssumedInformation))
1497 return indicatePessimisticFixpoint();
1499 return ChangeStatus::UNCHANGED;
1504 return ChangeStatus::UNCHANGED;
1506 LLVMContext &Ctx = getAssociatedFunction()->getContext();
1507 return A.manifestAttrs(getIRPosition(),
1508 {Attribute::get(Ctx,
"amdgpu-no-lds-dma")});
1511 bool isValidState()
const override {
return true; }
1513 const std::string getAsStr(Attributor *
A)
const override {
1514 return "AMDGPUNoLDSDMA[" + std::to_string(getAssumed()) +
"]";
1517 void trackStatistics()
const override {}
1519 StringRef
getName()
const override {
return "AAAMDGPUNoLDSDMA"; }
1520 const char *getIdAddr()
const override {
return &
ID; }
1524 static bool classof(
const AbstractAttribute *AA) {
1528 static const char ID;
1531const char AAAMDGPUNoLDSDMA::ID = 0;
1535struct AAAMDGPUClusterDims
1536 :
public StateWrapper<BooleanState, AbstractAttribute> {
1537 using Base = StateWrapper<BooleanState, AbstractAttribute>;
1538 AAAMDGPUClusterDims(
const IRPosition &IRP, Attributor &
A) :
Base(IRP) {}
1541 static AAAMDGPUClusterDims &createForPosition(
const IRPosition &IRP,
1545 StringRef
getName()
const override {
return "AAAMDGPUClusterDims"; }
1548 const char *getIdAddr()
const override {
return &
ID; }
1552 static bool classof(
const AbstractAttribute *AA) {
1556 virtual const AMDGPU::ClusterDimsAttr &getClusterDims()
const = 0;
1559 static const char ID;
1562const char AAAMDGPUClusterDims::ID = 0;
1564struct AAAMDGPUClusterDimsFunction :
public AAAMDGPUClusterDims {
1565 AAAMDGPUClusterDimsFunction(
const IRPosition &IRP, Attributor &
A)
1566 : AAAMDGPUClusterDims(IRP,
A) {}
1570 assert(
F &&
"empty associated function");
1577 indicatePessimisticFixpoint();
1579 indicateOptimisticFixpoint();
1583 const std::string getAsStr(Attributor *
A)
const override {
1593 void trackStatistics()
const override {}
1596 auto OldState = Attr;
1598 auto CheckCallSite = [&](AbstractCallSite CS) {
1599 const auto *CallerAA =
A.getAAFor<AAAMDGPUClusterDims>(
1601 DepClassTy::REQUIRED);
1602 if (!CallerAA || !CallerAA->isValidState())
1605 return merge(CallerAA->getClusterDims());
1608 bool UsedAssumedInformation =
false;
1609 if (!
A.checkForAllCallSites(CheckCallSite, *
this,
1611 UsedAssumedInformation))
1612 return indicatePessimisticFixpoint();
1614 return OldState == Attr ? ChangeStatus::UNCHANGED : ChangeStatus::CHANGED;
1619 return ChangeStatus::UNCHANGED;
1620 return A.manifestAttrs(
1622 {Attribute::get(getAssociatedFunction()->
getContext(), AttrName,
1627 const AMDGPU::ClusterDimsAttr &getClusterDims()
const override {
1632 bool merge(
const AMDGPU::ClusterDimsAttr &
Other) {
1647 if (
Other.isUnknown())
1672 AMDGPU::ClusterDimsAttr Attr;
1674 static constexpr char AttrName[] =
"amdgpu-cluster-dims";
1677AAAMDGPUClusterDims &
1678AAAMDGPUClusterDims::createForPosition(
const IRPosition &IRP, Attributor &
A) {
1680 return *
new (
A.Allocator) AAAMDGPUClusterDimsFunction(IRP,
A);
1681 llvm_unreachable(
"AAAMDGPUClusterDims is only valid for function position");
1684static bool runImpl(SetVector<Function *> &Functions,
bool IsModulePass,
1685 bool DeleteFns,
Module &M, AnalysisGetter &AG,
1686 TargetMachine &TM, AMDGPUAttributorOptions
Options,
1689 CallGraphUpdater CGUpdater;
1691 AMDGPUInformationCache InfoCache(M, AG,
Allocator,
nullptr, TM);
1692 DenseSet<const char *>
Allowed(
1693 {&AAAMDAttributes::ID, &AAUniformWorkGroupSize::ID,
1695 &AAAMDMaxNumWorkgroups::ID, &AAAMDWavesPerEU::ID,
1699 &AAAMDGPUClusterDims::ID, &AAAMDGPUNoLDSDMA::ID, &
AAAlign::ID});
1701 AttributorConfig AC(CGUpdater);
1702 AC.IsClosedWorldModule =
Options.IsClosedWorld;
1704 AC.IsModulePass = IsModulePass;
1705 AC.DeleteFns = DeleteFns;
1706 AC.DefaultInitializeLiveInternals =
false;
1708 AC.UseLiveness =
false;
1709 AC.IndirectCalleeSpecializationCallback =
1710 [](Attributor &
A,
const AbstractAttribute &AA, CallBase &CB,
1715 AC.IPOAmendableCB = [](
const Function &
F) {
1716 return F.getCallingConv() == CallingConv::AMDGPU_KERNEL;
1719 Attributor
A(Functions, InfoCache, AC);
1722 StringRef LTOPhaseStr =
to_string(LTOPhase);
1723 dbgs() <<
"[AMDGPUAttributor] Running at phase " << LTOPhaseStr <<
'\n'
1724 <<
"[AMDGPUAttributor] Module " <<
M.getName() <<
" is "
1725 << (AC.IsClosedWorldModule ?
"" :
"not ")
1726 <<
"assumed to be a closed world.\n";
1729 for (
auto *
F : Functions) {
1734 CallingConv::ID CC =
F->getCallingConv();
1741 if (!
F->isDeclaration() && Features.
test(AMDGPU::FEAT_CLUSTERS))
1744 if (Features.
test(AMDGPU::FEAT_AGPR_ALLOC))
1748 Value *Ptr =
nullptr;
1750 Ptr = LI->getPointerOperand();
1752 Ptr =
SI->getPointerOperand();
1754 Ptr = RMW->getPointerOperand();
1756 Ptr = CmpX->getPointerOperand();
1762 if (
II->getIntrinsicID() == Intrinsic::amdgcn_make_buffer_rsrc)
1769 return A.run() == ChangeStatus::CHANGED;
1782 if (!
F.isDeclaration())
1783 Functions.insert(&
F);
1787 return runImpl(Functions,
true,
true, M, AG,
1788 TM, Options, LTOPhase)
1805 if (!
F->isIntrinsic())
1806 Functions.insert(
F);
1810 Module *M =
C.begin()->getFunction().getParent();
1813 return runImpl(Functions,
false,
false, *M, AG,
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static bool isDSAddress(const Constant *C)
static constexpr std::pair< ImplicitArgumentMask, StringLiteral > ImplicitAttrs[]
static cl::opt< unsigned > IndirectCallSpecializationThreshold("amdgpu-indirect-call-specialization-threshold", cl::desc("A threshold controls whether an indirect call will be specialized"), cl::init(3))
static ImplicitArgumentMask intrinsicToAttrMask(Intrinsic::ID ID, bool &NonKernelOnly, bool &NeedsImplicit, bool HasApertureRegs, bool SupportsGetDoorBellID, unsigned CodeObjectVersion)
static bool hasSanitizerAttributes(const Function &F)
Returns true if sanitizer attributes are present on a function.
ImplicitArgumentPositions
static bool castRequiresQueuePtr(unsigned SrcAS)
The AMDGPU TargetMachine interface definition for hw codegen targets.
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Expand Atomic instructions
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 bool runImpl(MachineFunction &MF)
AMD GCN specific subclass of TargetSubtarget.
static LoopDeletionResult merge(LoopDeletionResult A, LoopDeletionResult B)
static FeatureBitset getFeatures(MCSubtargetInfo &STI, StringRef CPU, StringRef TuneCPU, StringRef FS, StringTable ProcNames, ArrayRef< SubtargetSubTypeKV > ProcDesc, ArrayRef< SubtargetFeatureKV > ProcFeatures)
Machine Check Debug Module
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
uint64_t IntrinsicInst * II
FunctionAnalysisManager FAM
static StringRef getName(Value *V)
Func getContext().diagnose(DiagnosticInfoUnsupported(Func
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
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.
PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG, CGSCCUpdateResult &UR)
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
static ClusterDimsAttr get(const Function &F)
std::string to_string() const
bool isVariableDims() const
uint64_t getZExtValue() const
Get zero extended value.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
constexpr bool test(unsigned I) const
Value * getArgOperand(unsigned i) const
LLVM_ABI Intrinsic::ID getIntrinsicID() const
Returns the intrinsic ID of the intrinsic called or Intrinsic::not_intrinsic if the called function i...
const APInt & getLower() const
Return the lower value for this range.
const APInt & getUpper() const
Return the upper value for this range.
This is an important base class in LLVM.
A proxy from a FunctionAnalysisManager to an SCC.
const DataLayout & getDataLayout() const
Get the data layout of the module this function belongs to.
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
unsigned getAddressSpace() const
LLVM_ABI const Function * getFunction() const
Return the function this instruction belongs to.
A node in the call graph.
An SCC of the call graph.
A lazily constructed view of the call graph of a module.
A Module instance is used to store all the information related to an LLVM module.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
A vector that has set insertion semantics.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
void push_back(const T &Elt)
std::string str() const
Get the contents as an std::string.
LLVM_ABI bool isDroppable() const
A droppable user is a user for which uses can be dropped without affecting correctness and should be ...
Type * getType() const
All values are typed, get the type of this value.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ REGION_ADDRESS
Address space for region memory. (GDS)
@ LOCAL_ADDRESS
Address space for local memory.
@ PRIVATE_ADDRESS
Address space for private memory.
LLVM_ABI unsigned getMaxWavesPerEU(GPUKind AK)
constexpr unsigned getMaxFlatWorkGroupSize()
constexpr unsigned getMinFlatWorkGroupSize()
unsigned getAMDHSACodeObjectVersion(const Module &M)
unsigned getDefaultQueueImplicitArgPosition(unsigned CodeObjectVersion)
std::tuple< char, unsigned, unsigned > parseAsmPhysRegName(StringRef RegName)
Returns a valid charcode or 0 in the first entry if this is a valid physical register name.
bool isLDSDMAIntrinsic(unsigned IntrID)
Bitset< NUM_FEATURES > AMDGPUFeatureBitset
LLVM_READNONE constexpr bool isEntryFunctionCC(CallingConv::ID CC)
LLVM_ABI Triple::SubArchType getSubArch(GPUKind AK)
std::tuple< char, unsigned, unsigned > parseAsmConstraintPhysReg(StringRef Constraint)
Returns a valid charcode or 0 in the first entry if this is a valid physical register constraint.
unsigned getHostcallImplicitArgPosition(unsigned CodeObjectVersion)
LLVM_ABI GPUKind getGPUKindFromSubArch(Triple::SubArchType SubArch)
SmallVector< unsigned > getMaxNumWorkGroups(const Function &F)
LLVM_ABI const AMDGPUFeatureBitset & getFeatureBitset(GPUKind AK)
Returns AK's feature bitset, or an empty bitset if unknown.
unsigned getCompletionActionImplicitArgPosition(unsigned CodeObjectVersion)
std::pair< unsigned, unsigned > getIntegerPairAttribute(const Function &F, StringRef Name, std::pair< unsigned, unsigned > Default, bool OnlyFirstRequired)
LLVM_READNONE constexpr bool isGraphics(CallingConv::ID CC)
unsigned getMultigridSyncArgImplicitArgPosition(unsigned CodeObjectVersion)
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
E & operator^=(E &LHS, E RHS)
@ CE
Windows NT (Windows on ARM)
initializer< Ty > init(const Ty &Val)
NodeAddr< CodeNode * > Code
NodeAddr< FuncNode * > Func
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
InnerAnalysisManagerProxy< FunctionAnalysisManager, Module > FunctionAnalysisManagerModuleProxy
Provide the FunctionAnalysisManager to Module proxy.
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
AnalysisManager< LazyCallGraph::SCC, LazyCallGraph & > CGSCCAnalysisManager
The CGSCC analysis manager.
ThinOrFullLTOPhase
This enumerates the LLVM full LTO or ThinLTO optimization phases.
@ None
No LTO/ThinLTO behavior needed.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
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...
const char * to_string(ThinOrFullLTOPhase Phase)
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
ArrayRef(const T &OneElt) -> ArrayRef< T >
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...
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
BumpPtrAllocatorImpl<> BumpPtrAllocator
The standard BumpPtrAllocator which just uses the default template parameters.
@ End
Run the machine verifier once, at the end of the pipeline.
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
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)
virtual const SetVector< Function * > & getOptimisticEdges() const =0
Get the optimistic edges.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
virtual bool hasNonAsmUnknownCallee() const =0
Is there any call with a unknown callee, excluding any inline asm.
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)
const RangeList & getRanges() const
Instruction * getRemoteInst() const
Return the actual instruction that causes the access.
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 const char ID
Unique ID (due to the unique address)
static LLVM_ABI const char ID
Unique ID (due to the unique address)
virtual const char * getIdAddr() const =0
This function should return the address of the ID of the AbstractAttribute.
Wrapper for FunctionAnalysisManager.
The fixpoint analysis framework that orchestrates the attribute deduction.
Support structure for SCC passes to communicate updates the call graph back to the CGSCC pass manager...
DecIntegerState & takeAssumedMaximum(base_t Value)
Take maximum of assumed and Value.
Helper to describe and deal with positions in the LLVM-IR.
static const IRPosition callsite_returned(const CallBase &CB)
Create a position describing the returned value of CB.
static const IRPosition value(const Value &V, const CallBaseContext *CBContext=nullptr)
Create a position describing the value of V.
@ IRP_FUNCTION
An attribute for a function (scope).
static const IRPosition function(const Function &F, const CallBaseContext *CBContext=nullptr)
Create a position describing the function scope of F.
Kind getPositionKind() const
Return the associated position kind.
static const IRPosition callsite_function(const CallBase &CB)
Create a position describing the function scope of CB.
bool isValidState() const override
See AbstractState::isValidState() NOTE: For now we simply pretend that the worst possible state is in...
ChangeStatus indicatePessimisticFixpoint() override
See AbstractState::indicatePessimisticFixpoint(...)
Helper to tie a abstract state implementation to an abstract attribute.