Index: llvm/lib/Target/AMDGPU/AMDGPUAnnotateKernelFeatures.cpp =================================================================== --- llvm/lib/Target/AMDGPU/AMDGPUAnnotateKernelFeatures.cpp +++ llvm/lib/Target/AMDGPU/AMDGPUAnnotateKernelFeatures.cpp @@ -32,6 +32,8 @@ bool addFeatureAttributes(Function &F); + bool handleInlineAsm(const CallBase *CB) const; + public: static char ID; @@ -59,10 +61,29 @@ INITIALIZE_PASS(AMDGPUAnnotateKernelFeatures, DEBUG_TYPE, "Add AMDGPU function attributes", false, false) +bool AMDGPUAnnotateKernelFeatures::handleInlineAsm(const CallBase *CB) const { + const TargetSubtargetInfo *ST = TM->getSubtargetImpl(*CB->getFunction()); + const TargetRegisterInfo *TRI = ST->getRegisterInfo(); + const TargetLowering *TLI = ST->getTargetLowering(); + const InlineAsm *IA = cast(CB->getCalledOperand()); + + for (const auto &CI: IA->ParseConstraints()) { + for (const StringRef Code : CI.Codes) { + const TargetRegisterClass *RC = + TLI->getRegForInlineAsmConstraint(TRI, Code, MVT::i32).second; + if (RC && SIRegisterInfo::isAGPRClass(RC)) + return true; + } + } + + return false; +} + bool AMDGPUAnnotateKernelFeatures::addFeatureAttributes(Function &F) { bool HaveStackObjects = false; bool Changed = false; bool HaveCall = false; + bool HaveAGPR = false; bool IsFunc = !AMDGPU::isEntryFunctionCC(F.getCallingConv()); for (BasicBlock &BB : F) { @@ -78,7 +99,9 @@ // Note the occurrence of indirect call. if (!Callee) { - if (!CB->isInlineAsm()) + if (CB->isInlineAsm()) + HaveAGPR |= handleInlineAsm(CB); + else HaveCall = true; continue; @@ -106,6 +129,11 @@ Changed = true; } + if (HaveAGPR) { + F.addFnAttr("amdgpu-has-agpr-in-asm"); + Changed = true; + } + return Changed; } Index: llvm/test/CodeGen/AMDGPU/inline-asm-agpr.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/AMDGPU/inline-asm-agpr.ll @@ -0,0 +1,40 @@ +; RUN: opt -mtriple=amdgcn-unknown-amdhsa -mcpu=gfx90a -S -amdgpu-annotate-kernel-features < %s | FileCheck %s + +; CHECK-LABEL: define amdgpu_kernel void @def_a0() #0 { +define amdgpu_kernel void @def_a0() { + %acc = call i32 asm sideeffect "; def $0", "={a0}"() + ret void +} + +; CHECK-LABEL: define amdgpu_kernel void @clobber_a128() #0 { +define amdgpu_kernel void @clobber_a128() { + call void asm sideeffect "; clobber $1", "~{v0},~{a128},~{v14}"() + ret void +} + +; CHECK-LABEL: define amdgpu_kernel void @use_a4() #0 { +define amdgpu_kernel void @use_a4() { + call void asm sideeffect "; use $0", "{a4}"(i32 undef) + ret void +} + +; CHECK-LABEL: define amdgpu_kernel void @def_a() #0 { +define amdgpu_kernel void @def_a() { + %acc = call i32 asm sideeffect "; def $0", "=a"() + ret void +} + +; CHECK-LABEL: define amdgpu_kernel void @use_a() #0 { +define amdgpu_kernel void @use_a() { + call void asm sideeffect "; use $0", "a"(i32 undef) + ret void +} + +; CHECK-LABEL: define amdgpu_kernel void @asm_no_agprs() #1 { +define amdgpu_kernel void @asm_no_agprs() { + %v = call i32 asm sideeffect "; ref $0, $1, $2", "={v0},v,~{s0}"(i32 undef) + ret void +} + +; CHECK: attributes #0 = { "amdgpu-has-agpr-in-asm" "target-cpu"="gfx90a" } +; CHECK: attributes #1 = { "target-cpu"="gfx90a" }