Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[clang] Simplify device kernel attributes #137882

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open

Conversation

sarnex
Copy link
Member

@sarnex sarnex commented Apr 29, 2025

We have multiple different attributes in clang representing device kernels for specific targets/languages. Refactor them into one attribute with different spellings to make it more easily scalable for new languages/targets.

@sarnex sarnex closed this Apr 29, 2025
@sarnex sarnex reopened this Apr 29, 2025
@sarnex sarnex force-pushed the spirattr branch 3 times, most recently from 711a62e to 20498a3 Compare April 30, 2025 17:26
Copy link

github-actions bot commented Apr 30, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

@sarnex sarnex marked this pull request as ready for review May 1, 2025 14:14
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:codegen IR generation bugs: mangling, exceptions, etc. debuginfo llvm:binary-utilities labels May 1, 2025
@llvmbot
Copy link
Member

llvmbot commented May 1, 2025

@llvm/pr-subscribers-backend-amdgpu
@llvm/pr-subscribers-backend-aarch64
@llvm/pr-subscribers-llvm-binary-utilities
@llvm/pr-subscribers-debuginfo
@llvm/pr-subscribers-clang-codegen

@llvm/pr-subscribers-clang

Author: Nick Sarnie (sarnex)

Changes

SPIR kernels have a specific calling convention, so add an attribute to explicitly specify this calling convention when targetting pure SPIR/SPIRV.


Full diff: https://github.com/llvm/llvm-project/pull/137882.diff

14 Files Affected:

  • (modified) clang/include/clang/Basic/Attr.td (+8)
  • (modified) clang/include/clang/Basic/Specifiers.h (+1)
  • (modified) clang/lib/AST/ItaniumMangle.cpp (+1)
  • (modified) clang/lib/AST/Type.cpp (+2)
  • (modified) clang/lib/AST/TypePrinter.cpp (+3)
  • (modified) clang/lib/Basic/Targets/SPIR.h (+4-2)
  • (modified) clang/lib/CodeGen/CGCall.cpp (+2)
  • (modified) clang/lib/CodeGen/CGDebugInfo.cpp (+2)
  • (modified) clang/lib/CodeGen/Targets/SPIR.cpp (+17)
  • (modified) clang/lib/Sema/SemaDeclAttr.cpp (+6)
  • (modified) clang/test/Misc/pragma-attribute-supported-attributes-list.test (+1)
  • (added) clang/test/Misc/spir-kernel-attr.c (+10)
  • (modified) llvm/include/llvm/BinaryFormat/Dwarf.def (+1)
  • (modified) llvm/include/llvm/DebugInfo/DWARF/DWARFTypePrinter.h (+3)
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index a734eb6658c3d..c3a3db095bb81 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -472,7 +472,9 @@ def TargetRISCV : TargetArch<["riscv32", "riscv64"]>;
 def TargetX86 : TargetArch<["x86"]>;
 def TargetX86_64 : TargetArch<["x86_64"]>;
 def TargetAnyX86 : TargetArch<["x86", "x86_64"]>;
+def TargetSPIR : TargetArch<["spir", "spir64"]>;
 def TargetSPIRV : TargetArch<["spirv", "spirv32", "spirv64"]>;
+def TargetAnySPIR : TargetArch<!listconcat(TargetSPIR.Arches, TargetSPIRV.Arches)>;
 def TargetWebAssembly : TargetArch<["wasm32", "wasm64"]>;
 def TargetNVPTX : TargetArch<["nvptx", "nvptx64"]>;
 def TargetWindows : TargetSpec {
@@ -1504,6 +1506,12 @@ def NVPTXKernel : InheritableAttr, TargetSpecificAttr<TargetNVPTX> {
   let Documentation = [Undocumented];
 }
 
+def SPIRKernel : InheritableAttr, TargetSpecificAttr<TargetAnySPIR> {
+  let Spellings = [Clang<"spir_kernel">];
+  let Subjects = SubjectList<[Function]>;
+  let Documentation = [Undocumented];
+}
+
 def HIPManaged : InheritableAttr {
   let Spellings = [GNU<"managed">, Declspec<"__managed__">];
   let Subjects = SubjectList<[Var]>;
diff --git a/clang/include/clang/Basic/Specifiers.h b/clang/include/clang/Basic/Specifiers.h
index 491badcc804e7..f9a72f378490e 100644
--- a/clang/include/clang/Basic/Specifiers.h
+++ b/clang/include/clang/Basic/Specifiers.h
@@ -289,6 +289,7 @@ namespace clang {
     CC_AAPCS_VFP,          // __attribute__((pcs("aapcs-vfp")))
     CC_IntelOclBicc,       // __attribute__((intel_ocl_bicc))
     CC_SpirFunction,       // default for OpenCL functions on SPIR target
+    CC_SpirKernel,         // __attribute__((spir_kernel))
     CC_OpenCLKernel,       // inferred for OpenCL kernels
     CC_Swift,              // __attribute__((swiftcall))
     CC_SwiftAsync,         // __attribute__((swiftasynccall))
diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index 33a8728728574..c16005ccaf51f 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -3532,6 +3532,7 @@ StringRef CXXNameMangler::getCallingConvQualifierName(CallingConv CC) {
   case CC_AMDGPUKernelCall:
   case CC_IntelOclBicc:
   case CC_SpirFunction:
+  case CC_SpirKernel:
   case CC_OpenCLKernel:
   case CC_PreserveMost:
   case CC_PreserveAll:
diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index 59369fba2e772..da9ba8e3e971a 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -3623,6 +3623,8 @@ StringRef FunctionType::getNameForCallConv(CallingConv CC) {
     return "intel_ocl_bicc";
   case CC_SpirFunction:
     return "spir_function";
+  case CC_SpirKernel:
+    return "spir_kernel";
   case CC_OpenCLKernel:
     return "opencl_kernel";
   case CC_Swift:
diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index cba1a2d98d660..5aa37ca9ec17f 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -1115,6 +1115,9 @@ void TypePrinter::printFunctionAfter(const FunctionType::ExtInfo &Info,
     case CC_OpenCLKernel:
       // Do nothing. These CCs are not available as attributes.
       break;
+    case CC_SpirKernel:
+      OS << " __attribute__((spir_kernel))";
+      break;
     case CC_Swift:
       OS << " __attribute__((swiftcall))";
       break;
diff --git a/clang/lib/Basic/Targets/SPIR.h b/clang/lib/Basic/Targets/SPIR.h
index bf249e271a870..43c71a1aeb5d5 100644
--- a/clang/lib/Basic/Targets/SPIR.h
+++ b/clang/lib/Basic/Targets/SPIR.h
@@ -191,8 +191,10 @@ class LLVM_LIBRARY_VISIBILITY BaseSPIRTargetInfo : public TargetInfo {
   }
 
   CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
-    return (CC == CC_SpirFunction || CC == CC_OpenCLKernel) ? CCCR_OK
-                                                            : CCCR_Warning;
+    return (CC == CC_SpirKernel || CC == CC_SpirFunction ||
+            CC == CC_OpenCLKernel)
+               ? CCCR_OK
+               : CCCR_Warning;
   }
 
   CallingConv getDefaultCallingConv() const override {
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index 83b0e8e965770..a7bbff116b584 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -84,6 +84,8 @@ unsigned CodeGenTypes::ClangCallConvToLLVMCallConv(CallingConv CC) {
     return llvm::CallingConv::AMDGPU_KERNEL;
   case CC_SpirFunction:
     return llvm::CallingConv::SPIR_FUNC;
+  case CC_SpirKernel:
+    return llvm::CallingConv::SPIR_KERNEL;
   case CC_OpenCLKernel:
     return CGM.getTargetCodeGenInfo().getOpenCLKernelCallingConv();
   case CC_PreserveMost:
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index f3ec498d4064b..10fba7b772486 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -1589,6 +1589,8 @@ static unsigned getDwarfCC(CallingConv CC) {
     return llvm::dwarf::DW_CC_LLVM_IntelOclBicc;
   case CC_SpirFunction:
     return llvm::dwarf::DW_CC_LLVM_SpirFunction;
+  case CC_SpirKernel:
+    return llvm::dwarf::DW_CC_LLVM_SpirKernel;
   case CC_OpenCLKernel:
   case CC_AMDGPUKernelCall:
     return llvm::dwarf::DW_CC_LLVM_OpenCLKernel;
diff --git a/clang/lib/CodeGen/Targets/SPIR.cpp b/clang/lib/CodeGen/Targets/SPIR.cpp
index f35c124f50aa0..29a258e457317 100644
--- a/clang/lib/CodeGen/Targets/SPIR.cpp
+++ b/clang/lib/CodeGen/Targets/SPIR.cpp
@@ -60,6 +60,8 @@ class CommonSPIRTargetCodeGenInfo : public TargetCodeGenInfo {
       llvm::Type *ElementType, llvm::LLVMContext &Ctx) const;
   void
   setOCLKernelStubCallingConvention(const FunctionType *&FT) const override;
+  void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
+                           CodeGen::CodeGenModule &M) const override;
 };
 class SPIRVTargetCodeGenInfo : public CommonSPIRTargetCodeGenInfo {
 public:
@@ -238,6 +240,20 @@ void CommonSPIRTargetCodeGenInfo::setOCLKernelStubCallingConvention(
       FT, FT->getExtInfo().withCallingConv(CC_SpirFunction));
 }
 
+void CommonSPIRTargetCodeGenInfo::setTargetAttributes(
+    const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &M) const {
+  const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
+  if (!FD)
+    return;
+
+  llvm::Function *F = cast<llvm::Function>(GV);
+
+  // Attach kernel metadata directly if compiling for SPIR.
+  if (FD->hasAttr<SPIRKernelAttr>()) {
+    F->setCallingConv(llvm::CallingConv::SPIR_KERNEL);
+  }
+}
+
 LangAS
 SPIRVTargetCodeGenInfo::getGlobalVarAddressSpace(CodeGenModule &CGM,
                                                  const VarDecl *D) const {
@@ -262,6 +278,7 @@ SPIRVTargetCodeGenInfo::getGlobalVarAddressSpace(CodeGenModule &CGM,
 
 void SPIRVTargetCodeGenInfo::setTargetAttributes(
     const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &M) const {
+  CommonSPIRTargetCodeGenInfo::setTargetAttributes(D, GV, M);
   if (!M.getLangOpts().HIP ||
       M.getTarget().getTriple().getVendor() != llvm::Triple::AMD)
     return;
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index ab66ae860f86b..56aea1e878f23 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -5503,6 +5503,9 @@ bool Sema::CheckCallingConvAttr(const ParsedAttr &Attrs, CallingConv &CC,
                                   llvm::Log2_64(ABIVLen) - 5);
     break;
   }
+  case ParsedAttr::AT_SPIRKernel:
+    CC = CC_SpirKernel;
+    break;
   default: llvm_unreachable("unexpected attribute kind");
   }
 
@@ -7152,6 +7155,9 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL,
   case ParsedAttr::AT_CUDALaunchBounds:
     handleLaunchBoundsAttr(S, D, AL);
     break;
+  case ParsedAttr::AT_SPIRKernel:
+    handleSimpleAttribute<SPIRKernelAttr>(S, D, AL);
+    break;
   case ParsedAttr::AT_Restrict:
     handleRestrictAttr(S, D, AL);
     break;
diff --git a/clang/test/Misc/pragma-attribute-supported-attributes-list.test b/clang/test/Misc/pragma-attribute-supported-attributes-list.test
index 7affacb1a109a..53a7ea4c8033b 100644
--- a/clang/test/Misc/pragma-attribute-supported-attributes-list.test
+++ b/clang/test/Misc/pragma-attribute-supported-attributes-list.test
@@ -181,6 +181,7 @@
 // CHECK-NEXT: ReturnTypestate (SubjectMatchRule_function, SubjectMatchRule_variable_is_parameter)
 // CHECK-NEXT: ReturnsNonNull (SubjectMatchRule_objc_method, SubjectMatchRule_function)
 // CHECK-NEXT: ReturnsTwice (SubjectMatchRule_function)
+// CHECK-NEXT: SPIRKernel (SubjectMatchRule_function)
 // CHECK-NEXT: SYCLKernelEntryPoint (SubjectMatchRule_function)
 // CHECK-NEXT: SYCLSpecialClass (SubjectMatchRule_record)
 // CHECK-NEXT: ScopedLockable (SubjectMatchRule_record)
diff --git a/clang/test/Misc/spir-kernel-attr.c b/clang/test/Misc/spir-kernel-attr.c
new file mode 100644
index 0000000000000..40de980716ff2
--- /dev/null
+++ b/clang/test/Misc/spir-kernel-attr.c
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -triple spir -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple spir64 -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple spirv-unknown-vulkan-compute -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple spirv32 -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple spirv64 -emit-llvm %s -o - | FileCheck %s
+__attribute__((spir_kernel)) void foo(void) {}
+
+[[clang::spir_kernel]] void bar(void) {}
+
+// CHECK-COUNT-2: spir_kernel
diff --git a/llvm/include/llvm/BinaryFormat/Dwarf.def b/llvm/include/llvm/BinaryFormat/Dwarf.def
index e52324a8ebc12..575ab05f4e3c4 100644
--- a/llvm/include/llvm/BinaryFormat/Dwarf.def
+++ b/llvm/include/llvm/BinaryFormat/Dwarf.def
@@ -1127,6 +1127,7 @@ HANDLE_DW_CC(0xcd, LLVM_PreserveNone)
 HANDLE_DW_CC(0xce, LLVM_RISCVVectorCall)
 HANDLE_DW_CC(0xcf, LLVM_SwiftTail)
 HANDLE_DW_CC(0xd0, LLVM_RISCVVLSCall)
+HANDLE_DW_CC(0xd1, LLVM_SpirKernel)
 // From GCC source code (include/dwarf2.h): This DW_CC_ value is not currently
 // generated by any toolchain.  It is used internally to GDB to indicate OpenCL
 // C functions that have been compiled with the IBM XL C for OpenCL compiler and
diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFTypePrinter.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFTypePrinter.h
index bd25f6c30ebf1..82337774f2396 100644
--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFTypePrinter.h
+++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFTypePrinter.h
@@ -741,6 +741,9 @@ void DWARFTypePrinter<DieType>::appendSubroutineNameAfter(
       // instantiated with function types with these calling conventions won't
       // have distinct names - so we'd need to fix that too)
       break;
+    case dwarf::CallingConvention::DW_CC_LLVM_SpirKernel:
+      OS << " __attribute((spir_kernel))";
+      break;
     case dwarf::CallingConvention::DW_CC_LLVM_Swift:
       // SwiftAsync missing
       OS << " __attribute__((swiftcall))";

@@ -5503,6 +5503,9 @@ bool Sema::CheckCallingConvAttr(const ParsedAttr &Attrs, CallingConv &CC,
llvm::Log2_64(ABIVLen) - 5);
break;
}
case ParsedAttr::AT_SPIRKernel:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps a silly request, but please sort this as 'not last'. It is too easy to miss when after a big block.

def SPIRKernel : InheritableAttr, TargetSpecificAttr<TargetAnySPIR> {
let Spellings = [Clang<"spir_kernel">];
let Subjects = SubjectList<[Function]>;
let Documentation = [Undocumented];
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this non-documented? WE very much don't approve/accept new undocumented attributes without good reason.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I wasn't sure how strict we were with that, will add documentation.

Copy link
Collaborator

@AaronBallman AaronBallman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need yet another calling convention or is there a way we can start to combine some of these for all the offloading languages? It seems we keep re-implementing the same concepts multiple times for each language and it would be nice to share as much of the frontend logic as possible rather than keep doing this dance of adding another case to every switch in the compiler. :-D

@sarnex
Copy link
Member Author

sarnex commented May 1, 2025

Do we need yet another calling convention or is there a way we can start to combine some of these for all the offloading languages? It seems we keep re-implementing the same concepts multiple times for each language and it would be nice to share as much of the frontend logic as possible rather than keep doing this dance of adding another case to every switch in the compiler. :-D

Do you have an idea? Maybe we could have a calling_convention attribute that takes in a string that specifies the calling convention?

@AaronBallman
Copy link
Collaborator

Do we need yet another calling convention or is there a way we can start to combine some of these for all the offloading languages? It seems we keep re-implementing the same concepts multiple times for each language and it would be nice to share as much of the frontend logic as possible rather than keep doing this dance of adding another case to every switch in the compiler. :-D

Do you have an idea? Maybe we could have a calling_convention attribute that takes in a string that specifies the calling convention?

I was thinking that orthogonal calling conventions could be combined so that we need fewer of them. e.g., if spir_kernel cannot be mixed with nvptx_kernel in the same TU, then there's no need for two distinct internal representations for the attributes, just two distinct spellings that are based on the target.

@sarnex
Copy link
Member Author

sarnex commented May 1, 2025

I was thinking that orthogonal calling conventions could be combined so that we need fewer of them. e.g., if spir_kernel cannot be mixed with nvptx_kernel in the same TU, then there's no need for two distinct internal representations for the attributes, just two distinct spellings that are based on the target.

Ah, I see.

Okay, I'll try, but it might take me a while. Thanks for the feedback. Marking this as a draft for now.

@sarnex sarnex marked this pull request as draft May 1, 2025 15:23
@sarnex
Copy link
Member Author

sarnex commented May 7, 2025

@AaronBallman I just pushed a first attempt to combine the attrs, however I'm not sure if it's much cleaner given the attrs have different subjects/allowed cases/expected warnings/etc. Do you mind taking a first look and seeing if you think the general direction is a good idea? Thanks

Copy link
Collaborator

@AaronBallman AaronBallman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CC @erichkeane and @jdoerfert for other opinions on the direction this is heading, but my initial thoughts are that this is not unreasonable. But I'd love to hear from others!

Comment on lines 1544 to 1553
inline bool isAMDGPUSpelling() const {
return isAMDGPUSpelling(*this);
}
template<typename T>
static inline bool isAMDGPUSpelling(const T& Attr) {
return Attr.getAttrName()->getName() == "amdgpu_kernel";
}
inline bool isNVPTXSpelling() const {
return isNVPTXSpelling(*this);
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's an easier way to do this, I think. We have:

  let Accessors = [Accessor<"isAMDGPU", [Clang<"amdgpu_kernel">]>,
                   Accessor<"isNVPTX", [Clang<"nvptx_kernel">]>];

which generates an accessor method for you which returns true/false based on the spelling.

Copy link
Member Author

@sarnex sarnex May 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah cool, thanks! Will do! I think I still need some of the methods to deal with the fact ParsedAttr isn't a subclass of Attr but also has a getAttrName() function, but maybe we can get rid of half of them

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried this, but we actually need to check the spelling mostly for ParsedAttr, so the accessors here won't help. I implemented Erich's idea to use the enum instead of the string. Let me know if you have some tablegen magic that we can use!

let Spellings = [Clang<"device_kernel">, Clang<"sycl_kernel">,
Clang<"nvptx_kernel">, Clang<"amdgpu_kernel">,
CustomKeyword<"__kernel">, CustomKeyword<"kernel">];
let LangOpts = [];
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can drop this entirely.

Copy link
Collaborator

@erichkeane erichkeane left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I honestly really like the approach. Those attributes really only differ by spelling and are almost semantically identical, so it makes a lot of sense to do it this way. So I'm happy.

The accessors could be cleaned up, otherwise this is a LGTM.

}
template<typename T>
static inline bool isOpenCLSpelling(const T& Attr) {
return Attr.getAttrName()->getName() == "kernel" ||
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even without the Accessors thing that Aaron suggests, you can check the spelling-id vs the generated enums which is better than string compares.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will try if it I hit an issue with Aaron's suggestion, thanks!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I ended up doing it this way using the enums.

@sarnex
Copy link
Member Author

sarnex commented May 8, 2025

Thanks a lot guys, I didn't expect this to be a good direction :)

@AlexVlx AlexVlx requested review from arsenm and yxsamliu May 8, 2025 17:49
@sarnex sarnex changed the title [clang] Add spir_kernel attribute [clang] Simplify device kernel attributes May 8, 2025
@sarnex sarnex marked this pull request as ready for review May 8, 2025 20:14
@@ -227,7 +227,7 @@ void SPIRVTargetCodeGenInfo::setCUDAKernelCallingConvention(
// Convert HIP kernels to SPIR-V kernels.
if (getABIInfo().getContext().getLangOpts().HIP) {
FT = getABIInfo().getContext().adjustFunctionType(
FT, FT->getExtInfo().withCallingConv(CC_OpenCLKernel));
FT, FT->getExtInfo().withCallingConv(CC_DeviceKernel));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure setCUDAKernelCallingConvention still needs to exist with this?

Comment on lines -295 to 296
if (FD->hasAttr<NVPTXKernelAttr>()) {
if (FD->hasAttr<DeviceKernelAttr>()) {
F->setCallingConv(llvm::CallingConv::PTX_Kernel);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is now set in the 2 language paths,, there's additional code that can be folded now

def DeviceKernel : DeclOrTypeAttr {
let Spellings = [Clang<"device_kernel">, Clang<"sycl_kernel">,
Clang<"nvptx_kernel">, Clang<"amdgpu_kernel">,
CustomKeyword<"__kernel">, CustomKeyword<"kernel">];
let Documentation = [SYCLKernelDocs];
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suspect we'll need to update the documentation because it's now going to list all of the various kernel attributes under SYCL kernel docs.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, will do, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend:AArch64 backend:AMDGPU backend:ARM backend:SystemZ clang:as-a-library libclang and C++ API clang:codegen IR generation bugs: mangling, exceptions, etc. clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category debuginfo llvm:binary-utilities
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants