[llvm] [AMDGPU] Added amdgpu-register-budget attribute to distribute the VGPR and AGPR budget from the kernels to the functions (PR #215705)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Aug 11 17:45:58 PDT 2026
github-actions[bot] wrote:
<!--LLVM CODE FORMAT COMMENT: {clang-format}-->
:warning: C/C++ code formatter, clang-format found issues in your code. :warning:
<details>
<summary>
You can test this locally with the following command:
</summary>
``````````bash
git-clang-format --diff origin/main HEAD --extensions cpp -- llvm/lib/Target/AMDGPU/AMDGPUAttributor.cpp llvm/lib/Target/AMDGPU/GCNSubtarget.cpp --diff_from_common_commit
``````````
:warning:
The reproduction instructions above might return results for more than one PR
in a stack if you are using a stacked PR workflow. You can limit the results by
changing `origin/main` to the base branch/commit you want to compare against.
:warning:
</details>
<details>
<summary>
View the diff from clang-format here.
</summary>
``````````diff
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUAttributor.cpp b/llvm/lib/Target/AMDGPU/AMDGPUAttributor.cpp
index 09405f244..5b9f974e7 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUAttributor.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUAttributor.cpp
@@ -1442,7 +1442,8 @@ struct RegisterBudgetState {
bool Unknown = true;
bool operator==(const RegisterBudgetState &Other) const {
- return Unknown == Other.Unknown && VGPRs == Other.VGPRs && AGPRs == Other.AGPRs;
+ return Unknown == Other.Unknown && VGPRs == Other.VGPRs &&
+ AGPRs == Other.AGPRs;
}
bool operator!=(const RegisterBudgetState &Other) const {
return !(*this == Other);
@@ -1464,27 +1465,28 @@ struct RegisterBudgetState {
/// An abstract attribute to propagate the register file split a kernel was
/// compiled with down the call graph to its device functions, emitted as
-/// "amdgpu-register-budget". Entry functions seed the split from their own vector
-/// register budget; every other function inherits the tightest split over its
-/// callers.
+/// "amdgpu-register-budget". Entry functions seed the split from their own
+/// vector register budget; every other function inherits the tightest split
+/// over its callers.
struct AAAMDGPURegisterBudget
: public StateWrapper<BooleanState, AbstractAttribute> {
using Base = StateWrapper<BooleanState, AbstractAttribute>;
AAAMDGPURegisterBudget(const IRPosition &IRP, Attributor &A) : Base(IRP) {}
static AAAMDGPURegisterBudget &createForPosition(const IRPosition &IRP,
- Attributor &A) {
+ Attributor &A) {
if (IRP.getPositionKind() == IRPosition::IRP_FUNCTION)
return *new (A.Allocator) AAAMDGPURegisterBudget(IRP, A);
llvm_unreachable(
"AAAMDGPURegisterBudget is only valid for function position");
}
- // When we known not all callers are known, we know that any unknown caller that reaches
- // this function will have a pessimistic amdgpu-agpr-alloc attribute. This being pessimistic
- // means that the budget for the number of VGPRs and AGPRs will be split in half for the unknown
- // caller. We also know that the FlatWorkGroupSize attribute will also be pessimistic for at
- // least the current function (the one being called in the indirect callsite)
+ // When we known not all callers are known, we know that any unknown caller
+ // that reaches this function will have a pessimistic amdgpu-agpr-alloc
+ // attribute. This being pessimistic means that the budget for the number of
+ // VGPRs and AGPRs will be split in half for the unknown caller. We also know
+ // that the FlatWorkGroupSize attribute will also be pessimistic for at least
+ // the current function (the one being called in the indirect callsite)
unsigned computePessimisticValue(Attributor &A) const {
Function *F = getAssociatedFunction();
auto &InfoCache = static_cast<AMDGPUInformationCache &>(A.getInfoCache());
@@ -1492,8 +1494,9 @@ struct AAAMDGPURegisterBudget
unsigned MaxWG = ST.getMaxFlatWorkGroupSize();
unsigned Occ = std::clamp(ST.getWavesPerEUForWorkGroup(MaxWG), 1u,
ST.getMaxWavesPerEU());
- unsigned Budget = ST.getMaxNumVGPRs(Occ, AMDGPU::getDynamicVGPRBlockSize(*F));
- return Budget / 2; // 128/2 == 64 on gfx90a at the max work-group size
+ unsigned Budget =
+ ST.getMaxNumVGPRs(Occ, AMDGPU::getDynamicVGPRBlockSize(*F));
+ return Budget / 2; // 128/2 == 64 on gfx90a at the max work-group size
}
ChangeStatus updateImpl(Attributor &A) override {
@@ -1514,18 +1517,17 @@ struct AAAMDGPURegisterBudget
unsigned MaxRegs = ST.getMaxNumVGPRs(*F);
if (!AGPRAlloc || !AGPRAlloc->isValidState()) {
VGPRBudget = AGPRBudget = MaxRegs / 2; // pessimistic
- if(VGPRBudget == computePessimisticValue(A))
+ if (VGPRBudget == computePessimisticValue(A))
return indicatePessimisticFixpoint();
- }
- else
- {
+ } else {
AGPRBudget = AGPRAlloc->getAssumed();
AGPRBudget = alignTo(AGPRBudget, 4);
VGPRBudget = MaxRegs - std::min(MaxRegs, AGPRBudget);
}
-
+
Budget = {VGPRBudget, AGPRBudget, /*Unknown=*/false};
- LLVM_DEBUG(dbgs() << "Register budget for " << F->getName() << ": " << VGPRBudget << ", " << AGPRBudget << "\n");
+ LLVM_DEBUG(dbgs() << "Register budget for " << F->getName() << ": "
+ << VGPRBudget << ", " << AGPRBudget << "\n");
} else {
RegisterBudgetState Merged;
@@ -1541,17 +1543,19 @@ struct AAAMDGPURegisterBudget
return true;
}
AbstractCallSite ACS(&U);
- const Use *EffectiveUse = ACS && ACS.isCallbackCall() ? &ACS.getCalleeUseForCallback() : &U;
- if(!ACS || !ACS.isCallee(EffectiveUse))
+ const Use *EffectiveUse =
+ ACS && ACS.isCallbackCall() ? &ACS.getCalleeUseForCallback() : &U;
+ if (!ACS || !ACS.isCallee(EffectiveUse))
return true;
Function *Caller = ACS.getInstruction()->getFunction();
- const auto *CallerAA = A.getAAFor<AAAMDGPURegisterBudget>(*this, IRPosition::function(*Caller), DepClassTy::REQUIRED);
- if(!CallerAA || !CallerAA->isValidState())
+ const auto *CallerAA = A.getAAFor<AAAMDGPURegisterBudget>(
+ *this, IRPosition::function(*Caller), DepClassTy::REQUIRED);
+ if (!CallerAA || !CallerAA->isValidState())
return true;
const RegisterBudgetState &CallerBudget = CallerAA->getBudget();
- if(!CallerBudget.Unknown)
+ if (!CallerBudget.Unknown)
Merged.merge(CallerBudget);
return true;
};
@@ -1560,11 +1564,15 @@ struct AAAMDGPURegisterBudget
// Checks for unknown call sites.
bool DummyUAI = false;
- bool AllCallsitesKnown = A.checkForAllCallSites([](AbstractCallSite) { return true; }, *this, true, DummyUAI);
+ bool AllCallsitesKnown = A.checkForAllCallSites(
+ [](AbstractCallSite) { return true; }, *this, true, DummyUAI);
if (!AllCallsitesKnown && !Merged.Unknown) {
- if (std::optional<unsigned> PessimisticValue = computePessimisticValue(A)) {
- Merged.merge({*PessimisticValue, *PessimisticValue, /*Unknown=*/false});
- } else return indicatePessimisticFixpoint();
+ if (std::optional<unsigned> PessimisticValue =
+ computePessimisticValue(A)) {
+ Merged.merge(
+ {*PessimisticValue, *PessimisticValue, /*Unknown=*/false});
+ } else
+ return indicatePessimisticFixpoint();
}
// Stays unknown when no caller contributed a budget, so that functions
// outside any kernel's reach are left unconstrained.
diff --git a/llvm/lib/Target/AMDGPU/GCNSubtarget.cpp b/llvm/lib/Target/AMDGPU/GCNSubtarget.cpp
index f6e56a9c7..e14ac289c 100644
--- a/llvm/lib/Target/AMDGPU/GCNSubtarget.cpp
+++ b/llvm/lib/Target/AMDGPU/GCNSubtarget.cpp
@@ -675,11 +675,13 @@ GCNSubtarget::getMaxNumVectorRegs(const Function &F) const {
std::tie(MinNumAGPRs, MaxNumAGPRs) =
AMDGPU::getIntegerPairAttribute(F, "amdgpu-agpr-alloc", DefaultNumAGPR,
/*OnlyFirstRequired=*/true);
- std::tie(VGPRCap, AGPRCap) =
- AMDGPU::getIntegerPairAttribute(F, "amdgpu-register-budget", DefaultRegisterBudget,
- /*OnlyFirstRequired=*/false);
-
- if (MinNumAGPRs == DefaultNumAGPR.first || (VGPRCap == DefaultRegisterBudget.first && !AMDGPU::isEntryFunctionCC(F.getCallingConv()))) {
+ std::tie(VGPRCap, AGPRCap) = AMDGPU::getIntegerPairAttribute(
+ F, "amdgpu-register-budget", DefaultRegisterBudget,
+ /*OnlyFirstRequired=*/false);
+
+ if (MinNumAGPRs == DefaultNumAGPR.first ||
+ (VGPRCap == DefaultRegisterBudget.first &&
+ !AMDGPU::isEntryFunctionCC(F.getCallingConv()))) {
MinNumAGPRs = MaxNumAGPRs = MaxVectorRegs / 2;
} else {
// Align to accum_offset's allocation granularity.
@@ -692,7 +694,8 @@ GCNSubtarget::getMaxNumVectorRegs(const Function &F) const {
MaxNumAGPRs = std::min(std::max(MinNumAGPRs, MaxNumAGPRs), MaxVectorRegs);
MinNumAGPRs = std::min({MinNumAGPRs, TotalNumAGPRs, MaxNumAGPRs});
- MaxNumVGPRs = std::min({MaxVectorRegs - MinNumAGPRs, NumArchVGPRs, VGPRCap});
+ MaxNumVGPRs =
+ std::min({MaxVectorRegs - MinNumAGPRs, NumArchVGPRs, VGPRCap});
MaxNumAGPRs = std::min({MaxVectorRegs - MaxNumVGPRs, MaxNumAGPRs, AGPRCap});
LLVM_DEBUG(dbgs() << "MaxNumVGPRs: " << MaxNumVGPRs << ", MaxNumAGPRs: "
``````````
</details>
https://github.com/llvm/llvm-project/pull/215705
More information about the llvm-commits
mailing list