[llvm] 29dcc4c - [AMDGPU] Add amdgpu_cs_chain[_preserve] CCs to IR & verifier

Diana Picus via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 22 01:04:31 PDT 2023


Author: Diana Picus
Date: 2023-06-22T10:02:45+02:00
New Revision: 29dcc4c143a7fbe9bb8d4d6e60745b33760e93fd

URL: https://github.com/llvm/llvm-project/commit/29dcc4c143a7fbe9bb8d4d6e60745b33760e93fd
DIFF: https://github.com/llvm/llvm-project/commit/29dcc4c143a7fbe9bb8d4d6e60745b33760e93fd.diff

LOG: [AMDGPU] Add amdgpu_cs_chain[_preserve] CCs to IR & verifier

Add the amdgpu_cs_chain and amdgpu_cs_chain_preserve keywords to
LLVM IR and make sure we can parse and print them. Also make sure we
perform some basic checks in the IR verifier - similar to what we check
for many of the other AMDGPU calling conventions, plus the additional
restriction that we can't have direct calls to functions with these
calling conventions.

Differential Revision: https://reviews.llvm.org/D151994

Added: 
    llvm/test/Assembler/amdgpu-cs-chain-cc.ll

Modified: 
    llvm/include/llvm/AsmParser/LLToken.h
    llvm/include/llvm/IR/CallingConv.h
    llvm/lib/AsmParser/LLLexer.cpp
    llvm/lib/AsmParser/LLParser.cpp
    llvm/lib/IR/AsmWriter.cpp
    llvm/lib/IR/Verifier.cpp
    llvm/test/Verifier/amdgpu-cc.ll

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/AsmParser/LLToken.h b/llvm/include/llvm/AsmParser/LLToken.h
index 38e6170b6b810..673dc58ce6451 100644
--- a/llvm/include/llvm/AsmParser/LLToken.h
+++ b/llvm/include/llvm/AsmParser/LLToken.h
@@ -170,6 +170,8 @@ enum Kind {
   kw_amdgpu_gs,
   kw_amdgpu_ps,
   kw_amdgpu_cs,
+  kw_amdgpu_cs_chain,
+  kw_amdgpu_cs_chain_preserve,
   kw_amdgpu_kernel,
   kw_amdgpu_gfx,
   kw_tailcc,

diff  --git a/llvm/include/llvm/IR/CallingConv.h b/llvm/include/llvm/IR/CallingConv.h
index 395a19d595de9..e97623b29f523 100644
--- a/llvm/include/llvm/IR/CallingConv.h
+++ b/llvm/include/llvm/IR/CallingConv.h
@@ -237,6 +237,14 @@ namespace CallingConv {
     /// Preserve X2-X15, X19-X29, SP, Z0-Z31, P0-P15.
     AArch64_SME_ABI_Support_Routines_PreserveMost_From_X2 = 103,
 
+    /// Used on AMDGPUs to give the middle-end more control over argument
+    /// placement.
+    AMDGPU_CS_Chain = 104,
+
+    /// Used on AMDGPUs to give the middle-end more control over argument
+    /// placement. Preserves active lane values for input VGPRs.
+    AMDGPU_CS_ChainPreserve = 105,
+
     /// The highest possible ID. Must be some 2^k - 1.
     MaxID = 1023
   };

diff  --git a/llvm/lib/AsmParser/LLLexer.cpp b/llvm/lib/AsmParser/LLLexer.cpp
index 7568fd43e1d08..f754c185272fb 100644
--- a/llvm/lib/AsmParser/LLLexer.cpp
+++ b/llvm/lib/AsmParser/LLLexer.cpp
@@ -627,6 +627,8 @@ lltok::Kind LLLexer::LexIdentifier() {
   KEYWORD(amdgpu_gs);
   KEYWORD(amdgpu_ps);
   KEYWORD(amdgpu_cs);
+  KEYWORD(amdgpu_cs_chain);
+  KEYWORD(amdgpu_cs_chain_preserve);
   KEYWORD(amdgpu_kernel);
   KEYWORD(amdgpu_gfx);
   KEYWORD(tailcc);

diff  --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index 7f887bb839b25..7ee5184a1e43c 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -2027,6 +2027,8 @@ void LLParser::parseOptionalDLLStorageClass(unsigned &Res) {
 ///   ::= 'amdgpu_gs'
 ///   ::= 'amdgpu_ps'
 ///   ::= 'amdgpu_cs'
+///   ::= 'amdgpu_cs_chain'
+///   ::= 'amdgpu_cs_chain_preserve'
 ///   ::= 'amdgpu_kernel'
 ///   ::= 'tailcc'
 ///   ::= 'cc' UINT
@@ -2089,6 +2091,12 @@ bool LLParser::parseOptionalCallingConv(unsigned &CC) {
   case lltok::kw_amdgpu_gs:      CC = CallingConv::AMDGPU_GS; break;
   case lltok::kw_amdgpu_ps:      CC = CallingConv::AMDGPU_PS; break;
   case lltok::kw_amdgpu_cs:      CC = CallingConv::AMDGPU_CS; break;
+  case lltok::kw_amdgpu_cs_chain:
+    CC = CallingConv::AMDGPU_CS_Chain;
+    break;
+  case lltok::kw_amdgpu_cs_chain_preserve:
+    CC = CallingConv::AMDGPU_CS_ChainPreserve;
+    break;
   case lltok::kw_amdgpu_kernel:  CC = CallingConv::AMDGPU_KERNEL; break;
   case lltok::kw_tailcc:         CC = CallingConv::Tail; break;
   case lltok::kw_cc: {

diff  --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp
index 16d77d14ad2b3..6df22f150929c 100644
--- a/llvm/lib/IR/AsmWriter.cpp
+++ b/llvm/lib/IR/AsmWriter.cpp
@@ -342,6 +342,12 @@ static void PrintCallingConv(unsigned cc, raw_ostream &Out) {
   case CallingConv::AMDGPU_GS:     Out << "amdgpu_gs"; break;
   case CallingConv::AMDGPU_PS:     Out << "amdgpu_ps"; break;
   case CallingConv::AMDGPU_CS:     Out << "amdgpu_cs"; break;
+  case CallingConv::AMDGPU_CS_Chain:
+    Out << "amdgpu_cs_chain";
+    break;
+  case CallingConv::AMDGPU_CS_ChainPreserve:
+    Out << "amdgpu_cs_chain_preserve";
+    break;
   case CallingConv::AMDGPU_KERNEL: Out << "amdgpu_kernel"; break;
   case CallingConv::AMDGPU_Gfx:    Out << "amdgpu_gfx"; break;
   }

diff  --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 293d443d754a4..753f5c37ecb2d 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -2581,6 +2581,8 @@ void Verifier::visitFunction(const Function &F) {
   }
   case CallingConv::AMDGPU_KERNEL:
   case CallingConv::SPIR_KERNEL:
+  case CallingConv::AMDGPU_CS_Chain:
+  case CallingConv::AMDGPU_CS_ChainPreserve:
     Check(F.getReturnType()->isVoidTy(),
           "Calling convention requires void return type", &F);
     [[fallthrough]];
@@ -3287,6 +3289,15 @@ void Verifier::visitCallBase(CallBase &Call) {
     Check(Callee->getValueType() == FTy,
           "Intrinsic called with incompatible signature", Call);
 
+  // Disallow calls to functions with the amdgpu_cs_chain[_preserve] calling
+  // convention.
+  auto CC = Call.getCallingConv();
+  Check(CC != CallingConv::AMDGPU_CS_Chain &&
+            CC != CallingConv::AMDGPU_CS_ChainPreserve,
+        "Direct calls to amdgpu_cs_chain/amdgpu_cs_chain_preserve functions "
+        "not allowed. Please use the @llvm.amdgpu.cs.chain intrinsic instead.",
+        Call);
+
   auto VerifyTypeAlign = [&](Type *Ty, const Twine &Message) {
     if (!Ty->isSized())
       return;

diff  --git a/llvm/test/Assembler/amdgpu-cs-chain-cc.ll b/llvm/test/Assembler/amdgpu-cs-chain-cc.ll
new file mode 100644
index 0000000000000..d5ca3e358604c
--- /dev/null
+++ b/llvm/test/Assembler/amdgpu-cs-chain-cc.ll
@@ -0,0 +1,13 @@
+; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s
+
+; CHECK: amdgpu_cs_chain void @amdgpu_cs_chain_cc
+define amdgpu_cs_chain void @amdgpu_cs_chain_cc() {
+entry:
+  ret void
+}
+
+; CHECK: amdgpu_cs_chain_preserve void @amdgpu_cs_chain_preserve_cc
+define amdgpu_cs_chain_preserve void @amdgpu_cs_chain_preserve_cc() {
+entry:
+  ret void
+}

diff  --git a/llvm/test/Verifier/amdgpu-cc.ll b/llvm/test/Verifier/amdgpu-cc.ll
index 9a3342c7219ff..ce48d1fdae3e5 100644
--- a/llvm/test/Verifier/amdgpu-cc.ll
+++ b/llvm/test/Verifier/amdgpu-cc.ll
@@ -127,3 +127,116 @@ define amdgpu_kernel void @inalloca_as0_cc_amdgpu_kernel(ptr inalloca(i32) %ptr)
 define amdgpu_kernel void @byref_as5_cc_amdgpu_kernel(ptr addrspace(5) byref(i32) %ptr) {
   ret void
 }
+
+; CHECK: Calling convention requires void return type
+; CHECK-NEXT: ptr @nonvoid_cc_amdgpu_cs_chain
+define amdgpu_cs_chain i32 @nonvoid_cc_amdgpu_cs_chain() {
+  ret i32 0
+}
+
+; CHECK: Calling convention does not support varargs or perfect forwarding!
+; CHECK-NEXT: ptr @varargs_amdgpu_cs_chain
+define amdgpu_cs_chain void @varargs_amdgpu_cs_chain(...) {
+  ret void
+}
+
+; CHECK: Calling convention does not allow sret
+; CHECK-NEXT: ptr @sret_cc_amdgpu_cs_chain_as0
+define amdgpu_cs_chain void @sret_cc_amdgpu_cs_chain_as0(ptr sret(i32) %ptr) {
+  ret void
+}
+
+; CHECK: Calling convention disallows byval
+; CHECK-NEXT: ptr @byval_cc_amdgpu_cs_chain
+define amdgpu_cs_chain void @byval_cc_amdgpu_cs_chain(ptr addrspace(1) byval(i32) %ptr) {
+  ret void
+}
+
+; CHECK: Calling convention disallows stack byref
+; CHECK-NEXT: ptr @byref_cc_amdgpu_cs_chain
+define amdgpu_cs_chain void @byref_cc_amdgpu_cs_chain(ptr addrspace(5) byref(i32) %ptr) {
+  ret void
+}
+
+; CHECK: Calling convention disallows preallocated
+; CHECK-NEXT: ptr @preallocated_cc_amdgpu_cs_chain
+define amdgpu_cs_chain void @preallocated_cc_amdgpu_cs_chain(ptr preallocated(i32) %ptr) {
+  ret void
+}
+
+; CHECK: Calling convention disallows inalloca
+; CHECK-NEXT: ptr @inalloca_cc_amdgpu_cs_chain
+define amdgpu_cs_chain void @inalloca_cc_amdgpu_cs_chain(ptr inalloca(i32) %ptr) {
+  ret void
+}
+
+; CHECK: Calling convention requires void return type
+; CHECK-NEXT: ptr @nonvoid_cc_amdgpu_cs_chain_preserve
+define amdgpu_cs_chain_preserve i32 @nonvoid_cc_amdgpu_cs_chain_preserve() {
+  ret i32 0
+}
+
+; CHECK: Calling convention does not support varargs or perfect forwarding!
+; CHECK-NEXT: ptr @varargs_amdgpu_cs_chain_preserve
+define amdgpu_cs_chain_preserve void @varargs_amdgpu_cs_chain_preserve(...) {
+  ret void
+}
+
+; CHECK: Calling convention does not allow sret
+; CHECK-NEXT: ptr @sret_cc_amdgpu_cs_chain_preserve_as0
+define amdgpu_cs_chain_preserve void @sret_cc_amdgpu_cs_chain_preserve_as0(ptr sret(i32) %ptr) {
+  ret void
+}
+
+; CHECK: Calling convention does not allow sret
+; CHECK-NEXT: ptr @sret_cc_amdgpu_cs_chain_preserve
+define amdgpu_cs_chain_preserve void @sret_cc_amdgpu_cs_chain_preserve(ptr addrspace(5) sret(i32) %ptr) {
+  ret void
+}
+
+; CHECK: Calling convention disallows byval
+; CHECK-NEXT: ptr @byval_cc_amdgpu_cs_chain_preserve
+define amdgpu_cs_chain_preserve void @byval_cc_amdgpu_cs_chain_preserve(ptr addrspace(1) byval(i32) %ptr) {
+  ret void
+}
+
+; CHECK: Calling convention disallows stack byref
+; CHECK-NEXT: ptr @byref_cc_amdgpu_cs_chain_preserve
+define amdgpu_cs_chain_preserve void @byref_cc_amdgpu_cs_chain_preserve(ptr addrspace(5) byref(i32) %ptr) {
+  ret void
+}
+
+; CHECK: Calling convention disallows preallocated
+; CHECK-NEXT: ptr @preallocated_cc_amdgpu_cs_chain_preserve
+define amdgpu_cs_chain_preserve void @preallocated_cc_amdgpu_cs_chain_preserve(ptr preallocated(i32) %ptr) {
+  ret void
+}
+
+; CHECK: Calling convention disallows inalloca
+; CHECK-NEXT: ptr @inalloca_cc_amdgpu_cs_chain_preserve
+define amdgpu_cs_chain_preserve void @inalloca_cc_amdgpu_cs_chain_preserve(ptr inalloca(i32) %ptr) {
+  ret void
+}
+
+declare amdgpu_cs_chain void @amdgpu_cs_chain_call_target()
+declare amdgpu_cs_chain_preserve void @amdgpu_cs_chain_preserve_call_target()
+
+define amdgpu_cs_chain void @cant_call_amdgpu_cs_chain_functions(ptr %f) {
+  ; CHECK: Direct calls to amdgpu_cs_chain/amdgpu_cs_chain_preserve functions not allowed. Please use the @llvm.amdgpu.cs.chain intrinsic instead.
+  ; CHECK-NEXT: call amdgpu_cs_chain
+  call amdgpu_cs_chain void @amdgpu_cs_chain_call_target()
+
+  ; CHECK: Direct calls to amdgpu_cs_chain/amdgpu_cs_chain_preserve functions not allowed. Please use the @llvm.amdgpu.cs.chain intrinsic instead.
+  ; CHECK-NEXT: call amdgpu_cs_chain_preserve
+  call amdgpu_cs_chain_preserve void @amdgpu_cs_chain_preserve_call_target()
+
+  ; CHECK: Direct calls to amdgpu_cs_chain/amdgpu_cs_chain_preserve functions not allowed. Please use the @llvm.amdgpu.cs.chain intrinsic instead.
+  ; CHECK-NEXT: call amdgpu_cs_chain
+  call amdgpu_cs_chain void %f()
+
+  ; CHECK: Direct calls to amdgpu_cs_chain/amdgpu_cs_chain_preserve functions not allowed. Please use the @llvm.amdgpu.cs.chain intrinsic instead.
+  ; CHECK-NEXT: call amdgpu_cs_chain
+  call amdgpu_cs_chain_preserve void %f()
+
+  ret void
+}


        


More information about the llvm-commits mailing list