[llvm] Amdgpu resourceusage calledglobal (PR #192195)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Apr 14 23:50:15 PDT 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-amdgpu
Author: StevenYangCC
<details>
<summary>Changes</summary>
[AMDGPU] Recover direct callees from called globals
Teach resource usage analysis to consult MachineFunction called-global metadata before falling back to the named callee operand so direct calls are not conservatively treated as indirect.
---
Full diff: https://github.com/llvm/llvm-project/pull/192195.diff
2 Files Affected:
- (modified) llvm/lib/Target/AMDGPU/AMDGPUResourceUsageAnalysis.cpp (+16-10)
- (added) llvm/test/CodeGen/AMDGPU/resource-usage-called-global.mir (+298)
``````````diff
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUResourceUsageAnalysis.cpp b/llvm/lib/Target/AMDGPU/AMDGPUResourceUsageAnalysis.cpp
index 4e664e084fb88..46e09528b2ada 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUResourceUsageAnalysis.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUResourceUsageAnalysis.cpp
@@ -59,6 +59,21 @@ static const Function *getCalleeFunction(const MachineOperand &Op) {
return cast<Function>(Op.getGlobal()->stripPointerCastsAndAliases());
}
+static const Function *getCalleeFunction(const MachineFunction &MF,
+ const MachineInstr &MI,
+ const SIInstrInfo &TII) {
+ if (MachineFunction::CalledGlobalInfo CGI = MF.tryGetCalledGlobal(&MI);
+ CGI.Callee) {
+ if (const auto *F =
+ dyn_cast<Function>(CGI.Callee->stripPointerCastsAndAliases()))
+ return F;
+ }
+
+ const MachineOperand *CalleeOp =
+ TII.getNamedOperand(MI, AMDGPU::OpName::callee);
+ return CalleeOp ? getCalleeFunction(*CalleeOp) : nullptr;
+}
+
static bool hasAnyNonFlatUseOfReg(const MachineRegisterInfo &MRI,
const SIInstrInfo &TII, unsigned Reg) {
for (const MachineOperand &UseOp : MRI.reg_operands(Reg)) {
@@ -253,16 +268,7 @@ AMDGPUResourceUsageAnalysisImpl::analyzeResourceUsage(
}
if (MI.isCall()) {
- // Pseudo used just to encode the underlying global. Is there a better
- // way to track this?
-
- // TODO: Some of the generic call-like pseudos do not encode the callee,
- // so we overly conservatively treat this as an indirect call.
- const MachineOperand *CalleeOp =
- TII->getNamedOperand(MI, AMDGPU::OpName::callee);
-
- const Function *Callee =
- CalleeOp ? getCalleeFunction(*CalleeOp) : nullptr;
+ const Function *Callee = getCalleeFunction(MF, MI, *TII);
auto isSameFunction = [](const MachineFunction &MF, const Function *F) {
return F == &MF.getFunction();
diff --git a/llvm/test/CodeGen/AMDGPU/resource-usage-called-global.mir b/llvm/test/CodeGen/AMDGPU/resource-usage-called-global.mir
new file mode 100644
index 0000000000000..347e8d886aa41
--- /dev/null
+++ b/llvm/test/CodeGen/AMDGPU/resource-usage-called-global.mir
@@ -0,0 +1,298 @@
+# RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx900 -start-after=prologepilog %s -o - | FileCheck %s
+
+--- |
+ ; ModuleID = '/tmp/amdgpu_called_global_regression.ll'
+ source_filename = "/tmp/amdgpu_called_global_regression.ll"
+ target datalayout = "e-m:e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-p7:160:256:256:32-p8:128:128:128:48-p9:192:256:256:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5-G1-ni:7:8:9"
+ target triple = "amdgcn-amd-amdhsa"
+
+ define void @callee() #0 {
+ entry:
+ call void asm sideeffect "", "~{v0}"()
+ ret void
+ }
+
+ define void @caller() #0 {
+ entry:
+ call void @callee()
+ ret void
+ }
+
+ attributes #0 = { "target-cpu"="gfx900" }
+...
+---
+name: callee
+alignment: 4
+exposesReturnsTwice: false
+legalized: false
+regBankSelected: false
+selected: false
+failedISel: false
+tracksRegLiveness: true
+hasWinCFI: false
+noPhis: true
+isSSA: false
+noVRegs: true
+hasFakeUses: false
+callsEHReturn: false
+callsUnwindInit: false
+hasEHContTarget: false
+hasEHScopes: false
+hasEHFunclets: false
+isOutlined: false
+debugInstrRef: false
+failsVerification: false
+tracksDebugUserValues: true
+registers: []
+liveins: []
+frameInfo:
+ isFrameAddressTaken: false
+ isReturnAddressTaken: false
+ hasStackMap: false
+ hasPatchPoint: false
+ stackSize: 0
+ offsetAdjustment: 0
+ maxAlignment: 1
+ adjustsStack: false
+ hasCalls: false
+ stackProtector: ''
+ functionContext: ''
+ maxCallFrameSize: 0
+ cvBytesOfCalleeSavedRegisters: 0
+ hasOpaqueSPAdjustment: false
+ hasVAStart: false
+ hasMustTailInVarArgFunc: false
+ hasTailCall: false
+ isCalleeSavedInfoValid: true
+ localFrameSize: 0
+fixedStack: []
+stack: []
+entry_values: []
+callSites: []
+debugValueSubstitutions: []
+constants: []
+machineFunctionInfo:
+ explicitKernArgSize: 0
+ maxKernArgAlign: 1
+ ldsSize: 0
+ gdsSize: 0
+ dynLDSAlign: 1
+ isEntryFunction: false
+ isChainFunction: false
+ memoryBound: false
+ waveLimiter: false
+ hasSpilledSGPRs: false
+ hasSpilledVGPRs: false
+ numWaveDispatchSGPRs: 16
+ numWaveDispatchVGPRs: 0
+ scratchRSrcReg: '$sgpr0_sgpr1_sgpr2_sgpr3'
+ frameOffsetReg: '$sgpr33'
+ stackPtrOffsetReg: '$sgpr32'
+ bytesInStackArgArea: 0
+ returnsVoid: true
+ argumentInfo:
+ privateSegmentBuffer: { reg: '$sgpr0_sgpr1_sgpr2_sgpr3' }
+ dispatchPtr: { reg: '$sgpr4_sgpr5' }
+ queuePtr: { reg: '$sgpr6_sgpr7' }
+ dispatchID: { reg: '$sgpr10_sgpr11' }
+ workGroupIDX: { reg: '$sgpr12' }
+ workGroupIDY: { reg: '$sgpr13' }
+ workGroupIDZ: { reg: '$sgpr14' }
+ LDSKernelId: { reg: '$sgpr15' }
+ implicitArgPtr: { reg: '$sgpr8_sgpr9' }
+ workItemIDX: { reg: '$vgpr31', mask: 1023 }
+ workItemIDY: { reg: '$vgpr31', mask: 1047552 }
+ workItemIDZ: { reg: '$vgpr31', mask: 1072693248 }
+ psInputAddr: 0
+ psInputEnable: 0
+ maxMemoryClusterDWords: 8
+ mode:
+ ieee: true
+ dx10-clamp: true
+ fp32-input-denormals: true
+ fp32-output-denormals: true
+ fp64-fp16-input-denormals: true
+ fp64-fp16-output-denormals: true
+ highBitsOf32BitAddress: 0
+ occupancy: 10
+ vgprForAGPRCopy: ''
+ sgprForEXECCopy: ''
+ longBranchReservedReg: ''
+ hasInitWholeWave: false
+ dynamicVGPRBlockSize: 0
+ scratchReservedForDynamicVGPRs: 0
+ numKernargPreloadSGPRs: 0
+ isWholeWaveFunction: false
+body: |
+ ; CHECK-LABEL: {{^}}callee:
+ ; CHECK: .set callee.num_vgpr, 1
+ bb.0.entry:
+ INLINEASM &"", 1 /* sideeffect attdialect */, 12 /* clobber */, implicit-def dead early-clobber $vgpr0
+ SI_RETURN
+
+...
+---
+name: caller
+alignment: 4
+exposesReturnsTwice: false
+legalized: false
+regBankSelected: false
+selected: false
+failedISel: false
+tracksRegLiveness: true
+hasWinCFI: false
+noPhis: true
+isSSA: false
+noVRegs: true
+hasFakeUses: false
+callsEHReturn: false
+callsUnwindInit: false
+hasEHContTarget: false
+hasEHScopes: false
+hasEHFunclets: false
+isOutlined: false
+debugInstrRef: false
+failsVerification: false
+tracksDebugUserValues: true
+registers: []
+liveins:
+ - { reg: '$sgpr4_sgpr5', virtual-reg: '' }
+ - { reg: '$sgpr6_sgpr7', virtual-reg: '' }
+ - { reg: '$sgpr8_sgpr9', virtual-reg: '' }
+ - { reg: '$sgpr10_sgpr11', virtual-reg: '' }
+ - { reg: '$sgpr12', virtual-reg: '' }
+ - { reg: '$sgpr13', virtual-reg: '' }
+ - { reg: '$sgpr14', virtual-reg: '' }
+ - { reg: '$sgpr15', virtual-reg: '' }
+ - { reg: '$vgpr31', virtual-reg: '' }
+frameInfo:
+ isFrameAddressTaken: false
+ isReturnAddressTaken: false
+ hasStackMap: false
+ hasPatchPoint: false
+ stackSize: 16
+ offsetAdjustment: 0
+ maxAlignment: 4
+ adjustsStack: true
+ hasCalls: true
+ stackProtector: ''
+ functionContext: ''
+ maxCallFrameSize: 0
+ cvBytesOfCalleeSavedRegisters: 0
+ hasOpaqueSPAdjustment: false
+ hasVAStart: false
+ hasMustTailInVarArgFunc: false
+ hasTailCall: false
+ isCalleeSavedInfoValid: true
+ localFrameSize: 0
+fixedStack: []
+stack:
+ - { id: 2, name: '', type: spill-slot, offset: 0, size: 4, alignment: 4,
+ stack-id: default, callee-saved-register: '', callee-saved-restored: true,
+ debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
+ - { id: 3, name: '', type: spill-slot, offset: 0, size: 4, alignment: 4,
+ stack-id: sgpr-spill, callee-saved-register: '', callee-saved-restored: true,
+ debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
+ - { id: 4, name: '', type: default, offset: 4, size: 4, alignment: 4,
+ stack-id: default, callee-saved-register: '', callee-saved-restored: true,
+ debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
+entry_values: []
+callSites: []
+debugValueSubstitutions: []
+constants: []
+calledGlobals:
+ - { bb: 0, offset: 11, callee: callee, flags: 0 }
+machineFunctionInfo:
+ explicitKernArgSize: 0
+ maxKernArgAlign: 1
+ ldsSize: 0
+ gdsSize: 0
+ dynLDSAlign: 1
+ isEntryFunction: false
+ isChainFunction: false
+ memoryBound: false
+ waveLimiter: false
+ hasSpilledSGPRs: true
+ hasSpilledVGPRs: false
+ numWaveDispatchSGPRs: 16
+ numWaveDispatchVGPRs: 0
+ scratchRSrcReg: '$sgpr0_sgpr1_sgpr2_sgpr3'
+ frameOffsetReg: '$sgpr33'
+ stackPtrOffsetReg: '$sgpr32'
+ bytesInStackArgArea: 0
+ returnsVoid: true
+ argumentInfo:
+ privateSegmentBuffer: { reg: '$sgpr0_sgpr1_sgpr2_sgpr3' }
+ dispatchPtr: { reg: '$sgpr4_sgpr5' }
+ queuePtr: { reg: '$sgpr6_sgpr7' }
+ dispatchID: { reg: '$sgpr10_sgpr11' }
+ workGroupIDX: { reg: '$sgpr12' }
+ workGroupIDY: { reg: '$sgpr13' }
+ workGroupIDZ: { reg: '$sgpr14' }
+ LDSKernelId: { reg: '$sgpr15' }
+ implicitArgPtr: { reg: '$sgpr8_sgpr9' }
+ workItemIDX: { reg: '$vgpr31', mask: 1023 }
+ workItemIDY: { reg: '$vgpr31', mask: 1047552 }
+ workItemIDZ: { reg: '$vgpr31', mask: 1072693248 }
+ psInputAddr: 0
+ psInputEnable: 0
+ maxMemoryClusterDWords: 8
+ mode:
+ ieee: true
+ dx10-clamp: true
+ fp32-input-denormals: true
+ fp32-output-denormals: true
+ fp64-fp16-input-denormals: true
+ fp64-fp16-output-denormals: true
+ highBitsOf32BitAddress: 0
+ occupancy: 10
+ spillPhysVGPRs:
+ - '$vgpr40'
+ wwmReservedRegs:
+ - '$vgpr40'
+ vgprForAGPRCopy: ''
+ sgprForEXECCopy: ''
+ longBranchReservedReg: ''
+ hasInitWholeWave: false
+ dynamicVGPRBlockSize: 0
+ scratchReservedForDynamicVGPRs: 0
+ numKernargPreloadSGPRs: 0
+ isWholeWaveFunction: false
+body: |
+ ; CHECK-LABEL: {{^}}caller:
+ ; CHECK: .set caller.num_vgpr, max(41, callee.num_vgpr)
+ ; CHECK: .set caller.num_agpr, max(0, callee.num_agpr)
+ ; CHECK: .set caller.numbered_sgpr, max(34, callee.numbered_sgpr)
+ ; CHECK: .set caller.num_named_barrier, max(0, callee.num_named_barrier)
+ ; CHECK: .set caller.private_seg_size, 16+max(callee.private_seg_size)
+ ; CHECK: .set caller.uses_vcc, or(0, callee.uses_vcc)
+ ; CHECK: .set caller.uses_flat_scratch, or(0, callee.uses_flat_scratch)
+ ; CHECK: .set caller.has_dyn_sized_stack, or(0, callee.has_dyn_sized_stack)
+ ; CHECK: .set caller.has_recursion, or(1, callee.has_recursion)
+ ; CHECK: .set caller.has_indirect_call, or(0, callee.has_indirect_call)
+ bb.0.entry:
+ liveins: $sgpr12, $sgpr13, $sgpr14, $sgpr15, $sgpr30, $sgpr31, $vgpr31, $sgpr4_sgpr5, $sgpr6_sgpr7, $sgpr8_sgpr9, $sgpr10_sgpr11
+
+ $sgpr16 = COPY $sgpr33
+ $sgpr33 = frame-setup COPY $sgpr32
+ $sgpr18_sgpr19 = S_OR_SAVEEXEC_B64 -1, implicit-def $exec, implicit-def dead $scc, implicit $exec
+ BUFFER_STORE_DWORD_OFFSET killed $vgpr40, $sgpr0_sgpr1_sgpr2_sgpr3, $sgpr33, 0, 0, 0, implicit $exec :: ("amdgpu-thread-private" store (s32) into %stack.2, addrspace 5)
+ $exec = S_MOV_B64 killed $sgpr18_sgpr19
+ $vgpr40 = SI_SPILL_S32_TO_VGPR $sgpr16, 2, undef $vgpr40
+ $sgpr32 = frame-setup S_ADD_I32 $sgpr32, 1024, implicit-def dead $scc
+ $vgpr40 = SI_SPILL_S32_TO_VGPR killed $sgpr30, 0, $vgpr40
+ $vgpr40 = SI_SPILL_S32_TO_VGPR killed $sgpr31, 1, $vgpr40
+ renamable $sgpr16_sgpr17 = SI_PC_ADD_REL_OFFSET target-flags(amdgpu-gotprel32-lo) @callee, target-flags(amdgpu-gotprel32-hi) @callee, implicit-def dead $scc
+ renamable $sgpr16_sgpr17 = S_LOAD_DWORDX2_IMM killed renamable $sgpr16_sgpr17, 0, 0 :: (dereferenceable invariant load (s64) from got, addrspace 4)
+ dead $sgpr30_sgpr31 = S_SWAPPC_B64 killed renamable $sgpr16_sgpr17
+ $sgpr31 = SI_RESTORE_S32_FROM_VGPR $vgpr40, 1
+ $sgpr30 = SI_RESTORE_S32_FROM_VGPR $vgpr40, 0
+ $sgpr32 = frame-destroy COPY $sgpr33
+ $sgpr4 = SI_RESTORE_S32_FROM_VGPR $vgpr40, 2
+ $sgpr6_sgpr7 = S_OR_SAVEEXEC_B64 -1, implicit-def $exec, implicit-def dead $scc, implicit $exec
+ $vgpr40 = BUFFER_LOAD_DWORD_OFFSET $sgpr0_sgpr1_sgpr2_sgpr3, $sgpr33, 0, 0, 0, implicit $exec :: ("amdgpu-thread-private" load (s32) from %stack.2, addrspace 5)
+ $exec = S_MOV_B64 killed $sgpr6_sgpr7
+ $sgpr33 = COPY $sgpr4
+ SI_RETURN
+
+...
``````````
</details>
https://github.com/llvm/llvm-project/pull/192195
More information about the llvm-commits
mailing list