[llvm] f6f71ed - [AMDGPU] Introduce address space 13 for VGPR as memory (#208557)

via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 9 12:47:50 PDT 2026


Author: Gheorghe-Teodor Bercea
Date: 2026-09-09T15:47:44-04:00
New Revision: f6f71edb4346d586bb97485116175efd9a696ee8

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

LOG: [AMDGPU] Introduce address space 13 for VGPR as memory (#208557)

Introduce address space 13 (enum, datalayout, verifier allowance, docs)
for VGPR as memory. No codegen in this PR.

Co-authored-by: Nicolai Hähnle <Nicolai.Haehnle at amd.com>

Added: 
    llvm/test/Verifier/AMDGPU/global-variable.ll

Modified: 
    llvm/docs/AMDGPUUsage.rst
    llvm/include/llvm/Support/AMDGPUAddrSpace.h
    llvm/lib/IR/Verifier.cpp
    llvm/lib/IR/VerifierAMDGPU.cpp
    llvm/lib/IR/VerifierInternal.h
    llvm/lib/Target/AMDGPU/AMDGPU.h
    llvm/lib/Target/AMDGPU/AMDGPUInstructions.td
    llvm/test/CodeGen/AMDGPU/amdgpu-alias-analysis.ll
    llvm/test/CodeGen/AMDGPU/nullptr.ll
    llvm/test/Verifier/AMDGPU/alloca.ll

Removed: 
    


################################################################################
diff  --git a/llvm/docs/AMDGPUUsage.rst b/llvm/docs/AMDGPUUsage.rst
index 7a0f8a6d434a9..0d1fcf0700122 100644
--- a/llvm/docs/AMDGPUUsage.rst
+++ b/llvm/docs/AMDGPUUsage.rst
@@ -1145,7 +1145,7 @@ supported for the ``amdgcn`` target.
      *reserved for future use*             10
      *reserved for future use*             11
      *reserved for downstream use (LLPC)*  12
-     *reserved for future use*             13
+     VGPR                                  13              N/A         VGPR             32      0xFFFFFFFF
      *reserved for future use*             14
      Barrier                               15              N/A         N/A              32      0
      *reserved for future use*             16
@@ -1364,6 +1364,23 @@ supported for the ``amdgcn`` target.
   a buffer strided pointer, this means that the base pointer is ``align(4)``, that
   the offset is a multiple of 4 bytes, and that the stride is a multiple of 4.
 
+**VGPR**
+  The VGPR address space presents a memory view of the wave's vector registers.
+  The 32-bit address is a byte address into the thread's view of vector
+  registers. For example, loading 4 bytes from address ``12`` reads the contents
+  of ``v3``. Storing 8 bytes to address ``32`` overwrites the contents of
+  ``v[8:9]``.
+
+  Use of this address space by frontends is strongly discouraged. It has unusual
+  and subtle lifetime rules due to the potential for interaction with normal
+  register allocation. It exists primarily for internal purposes of the backend,
+  such as promoting ``alloca`` instructions from the private address space into
+  VGPRs.
+
+  In particular, memory in this address space that was allocated by an
+  ``alloca`` is not visible while in a called function. Attempting to dereference
+  a pointer to such memory in a called function is undefined behavior.
+
 **Barrier**
   This address space represents barrier IDs (introduced in GFX12) as addresses.
   It does not map directly to any addressable memory and is implemented using

diff  --git a/llvm/include/llvm/Support/AMDGPUAddrSpace.h b/llvm/include/llvm/Support/AMDGPUAddrSpace.h
index 25dd9f54813fd..006ae1e9039ef 100644
--- a/llvm/include/llvm/Support/AMDGPUAddrSpace.h
+++ b/llvm/include/llvm/Support/AMDGPUAddrSpace.h
@@ -50,7 +50,10 @@ enum : unsigned {
 
   RESERVED_ADDRESS_SPACE_11 = 11, ///< Reserved for downstream use.
 
-  RESERVED_ADDRESS_SPACE_13 = 13, ///< Reserved for downstream use.
+  VGPR = 13, ///< Address space for VGPRs. The 32-bit address is a byte offset
+             ///< into the wave's view of its vector registers. Note this shares
+             ///< its numeric value with CONSTANT_BUFFER_5, which is only used
+             ///< by the (graphics) R600 path.
 
   RESERVED_ADDRESS_SPACE_14 = 14, ///< Reserved for downstream use.
 
@@ -194,6 +197,7 @@ constexpr int64_t getNullPointerValue(unsigned AS) {
   case PRIVATE_ADDRESS:
   case LOCAL_ADDRESS:
   case REGION_ADDRESS:
+  case VGPR:
     return -1;
   default:
     return 0;

diff  --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 0006682b969a0..12ab6e9c34a5e 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -712,6 +712,10 @@ void Verifier::visitGlobalValue(const GlobalValue &GV) {
 }
 
 void Verifier::visitGlobalVariable(const GlobalVariable &GV) {
+  // Target-specific global variable checks. Done first because this function
+  // returns early for a global without an initializer.
+  verifyAMDGPUGlobalVariable(*this, GV);
+
   Type *GVType = GV.getValueType();
 
   if (MaybeAlign A = GV.getAlign()) {

diff  --git a/llvm/lib/IR/VerifierAMDGPU.cpp b/llvm/lib/IR/VerifierAMDGPU.cpp
index 9f2cd159ad60f..5d7b46357d284 100644
--- a/llvm/lib/IR/VerifierAMDGPU.cpp
+++ b/llvm/lib/IR/VerifierAMDGPU.cpp
@@ -23,6 +23,7 @@
 #include "llvm/IR/Constants.h"
 #include "llvm/IR/DerivedTypes.h"
 #include "llvm/IR/Function.h"
+#include "llvm/IR/GlobalVariable.h"
 #include "llvm/IR/IntrinsicInst.h"
 #include "llvm/IR/IntrinsicsAMDGPU.h"
 #include "llvm/Support/AMDGPUAddrSpace.h"
@@ -134,13 +135,35 @@ void llvm::verifyAMDGPUFunctionMetadata(VerifierSupport &VS,
   verifyAMDGPUReqdWorkGroupSize(VS, F);
 }
 
+void llvm::verifyAMDGPUGlobalVariable(VerifierSupport &VS,
+                                      const GlobalVariable &GV) {
+  // This is not required for other targets so we only check for AMDGPU.
+  if (!VS.TT.isAMDGPU())
+    return;
+
+  // The VGPR address space is a view of one wave's own vector registers, which
+  // exist only while that wave runs. A global variable needs storage that
+  // outlives any particular wave, so there is nothing here for it to name.
+  if (GV.getAddressSpace() == AMDGPUAS::VGPR)
+    VS.CheckFailed("global variable on amdgpu must not be in addrspace(13)",
+                   &GV);
+}
+
 void llvm::verifyAMDGPUAlloca(VerifierSupport &VS, const AllocaInst &AI) {
   // This is not required for other targets so we only check for AMDGPU.
   if (!VS.TT.isAMDGPU())
     return;
 
-  if (AI.getAddressSpace() != AMDGPUAS::PRIVATE_ADDRESS)
-    VS.CheckFailed("alloca on amdgpu must be in addrspace(5)", &AI);
+  if (AI.getAddressSpace() != AMDGPUAS::PRIVATE_ADDRESS &&
+      AI.getAddressSpace() != AMDGPUAS::VGPR)
+    VS.CheckFailed("alloca on amdgpu must be in addrspace(5) or addrspace(13)",
+                   &AI);
+
+  // Only static allocas can live in VGPRs; a dynamically sized one has no
+  // register-file representation. (Other address spaces are already rejected
+  // above, so this only adds the more specific diagnostic for addrspace(13).)
+  if (!AI.isStaticAlloca() && AI.getAddressSpace() == AMDGPUAS::VGPR)
+    VS.CheckFailed("dynamic alloca on amdgpu must be in addrspace(5)", &AI);
 }
 
 bool llvm::isAMDGPUCallBrIntrinsic(Intrinsic::ID ID) {

diff  --git a/llvm/lib/IR/VerifierInternal.h b/llvm/lib/IR/VerifierInternal.h
index 70d1521475198..0a7381f27d404 100644
--- a/llvm/lib/IR/VerifierInternal.h
+++ b/llvm/lib/IR/VerifierInternal.h
@@ -219,6 +219,8 @@ void verifyAMDGPUModuleFlag(VerifierSupport &VS, const MDString *ID,
 
 void verifyAMDGPUFunctionMetadata(VerifierSupport &VS, const Function &F);
 
+void verifyAMDGPUGlobalVariable(VerifierSupport &VS, const GlobalVariable &GV);
+
 void verifyAMDGPUAlloca(VerifierSupport &VS, const AllocaInst &AI);
 
 void verifyAMDGPUIntrinsicCall(VerifierSupport &VS, Intrinsic::ID ID,

diff  --git a/llvm/lib/Target/AMDGPU/AMDGPU.h b/llvm/lib/Target/AMDGPU/AMDGPU.h
index dc79dcfe9c9f0..86afda9e4bf49 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPU.h
+++ b/llvm/lib/Target/AMDGPU/AMDGPU.h
@@ -677,7 +677,7 @@ static inline bool addrspacesMayAlias(unsigned AS1, unsigned AS2) {
 
   // clang-format off
   static const bool ASAliasRules[][AMDGPUAS::MAX_AMDGPU_ADDRESS + 1] = {
-    /*                       Flat   Global Region  Local Constant Private Const32 BufFatPtr BufRsrc BufStrdPtr Reserved Reserved Reserved Reserved Reserved Barrier */
+    /*                       Flat   Global Region  Local Constant Private Const32 BufFatPtr BufRsrc BufStrdPtr Reserved Reserved Reserved VGPR Reserved Barrier */
     /* Flat     */            {true,  true,  false, true,  true,  true,  true,  true,  true,  true, false, false, false, false, false, false},
     /* Global   */            {true,  true,  false, false, true,  false, true,  true,  true,  true, false, false, false, false, false, false},
     /* Region   */            {false, false, true,  false, false, false, false, false, false, false, false, false, false, false, false, false},
@@ -691,7 +691,10 @@ static inline bool addrspacesMayAlias(unsigned AS1, unsigned AS2) {
     /* Reserved  */          {false,  false,  false, false, false,  false, false,  false,  false,  false, false, false, false, false, false, false},
     /* Reserved  */          {false,  false,  false, false, false,  false, false,  false,  false,  false, false, false, false, false, false, false},
     /* Reserved  */          {false,  false,  false, false, false,  false, false,  false,  false,  false, false, false, false, false, false, false},
-    /* Reserved  */          {false,  false,  false, false, false,  false, false,  false,  false,  false, false, false, false, false, false, false},
+    // A VGPR ("as memory") access only ever touches the wave's own registers,
+    // which no other address space can reach: a flat pointer obtained by casting
+    // one cannot be dereferenced.
+    /* VGPR     */           {false,  false,  false, false, false,  false, false,  false,  false,  false, false, false, false, true,  false, false},
     /* Reserved  */          {false,  false,  false, false, false,  false, false,  false,  false,  false, false, false, false, false, false, false},
     /* Barrier  */           {false,  false,  false, false, false,  false, false,  false,  false,  false, false, false, false, false, false, true},
   };

diff  --git a/llvm/lib/Target/AMDGPU/AMDGPUInstructions.td b/llvm/lib/Target/AMDGPU/AMDGPUInstructions.td
index d0607a2961a9b..28193a52f71d2 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUInstructions.td
+++ b/llvm/lib/Target/AMDGPU/AMDGPUInstructions.td
@@ -19,6 +19,7 @@ def AddrSpaces {
   int Constant = 4;
   int Private = 5;
   int Constant32Bit = 6;
+  int VGPR = 13;
 }
 
 

diff  --git a/llvm/test/CodeGen/AMDGPU/amdgpu-alias-analysis.ll b/llvm/test/CodeGen/AMDGPU/amdgpu-alias-analysis.ll
index 7e64ed4d95390..4b7549f8fae10 100644
--- a/llvm/test/CodeGen/AMDGPU/amdgpu-alias-analysis.ll
+++ b/llvm/test/CodeGen/AMDGPU/amdgpu-alias-analysis.ll
@@ -319,6 +319,45 @@ define void @test_9_9(ptr addrspace(9) %p, ptr addrspace(9) %p1) {
   ret void
 }
 
+; The VGPR address space is only reachable through its own indexed accesses, so
+; it aliases nothing else - not even flat, since a flat pointer obtained by
+; casting one cannot be dereferenced.
+
+; CHECK: NoAlias:  i8 addrspace(13)* %p, i8* %p1
+define void @test_13_0(ptr addrspace(13) %p, ptr addrspace(0) %p1) {
+  load i8, ptr addrspace(13) %p
+  load i8, ptr addrspace(0) %p1
+  ret void
+}
+
+; CHECK: NoAlias:  i8 addrspace(13)* %p, i8 addrspace(1)* %p1
+define void @test_13_1(ptr addrspace(13) %p, ptr addrspace(1) %p1) {
+  load i8, ptr addrspace(13) %p
+  load i8, ptr addrspace(1) %p1
+  ret void
+}
+
+; CHECK: NoAlias:  i8 addrspace(13)* %p, i8 addrspace(3)* %p1
+define void @test_13_3(ptr addrspace(13) %p, ptr addrspace(3) %p1) {
+  load i8, ptr addrspace(13) %p
+  load i8, ptr addrspace(3) %p1
+  ret void
+}
+
+; CHECK: NoAlias:  i8 addrspace(13)* %p, i8 addrspace(5)* %p1
+define void @test_13_5(ptr addrspace(13) %p, ptr addrspace(5) %p1) {
+  load i8, ptr addrspace(13) %p
+  load i8, ptr addrspace(5) %p1
+  ret void
+}
+
+; CHECK: MayAlias:  i8 addrspace(13)* %p, i8 addrspace(13)* %p1
+define void @test_13_13(ptr addrspace(13) %p, ptr addrspace(13) %p1) {
+  load i8, ptr addrspace(13) %p
+  load i8, ptr addrspace(13) %p1
+  ret void
+}
+
 ; CHECK-LABEL: Function: test_kernel_arg_local_ptr
 ; CHECK: MayAlias:   i32 addrspace(3)* %arg, i32 addrspace(3)* %arg1
 ; CHECK: MayAlias:   i32 addrspace(3)* %arg, i32* %arg2

diff  --git a/llvm/test/CodeGen/AMDGPU/nullptr.ll b/llvm/test/CodeGen/AMDGPU/nullptr.ll
index da74ad5d5fda8..9945d65edfe3b 100644
--- a/llvm/test/CodeGen/AMDGPU/nullptr.ll
+++ b/llvm/test/CodeGen/AMDGPU/nullptr.ll
@@ -54,8 +54,11 @@
 ; R600-NEXT: .long 0
 @nullptr12 = global ptr addrspace(12) addrspacecast (ptr null to ptr addrspace(12))
 
+; Address space 13 is the VGPR address space, whose null pointer is -1 like the
+; other address spaces where zero is a valid address. R600 reaches the same
+; value through the shared numbering, where 13 is CONSTANT_BUFFER_5.
 ; CHECK-LABEL: nullptr13:
-; R600-NEXT: .long 0
+; CHECK-NEXT: .long -1
 @nullptr13 = global ptr addrspace(13) addrspacecast (ptr null to ptr addrspace(13))
 
 ; CHECK-LABEL: nullptr14:

diff  --git a/llvm/test/Verifier/AMDGPU/alloca.ll b/llvm/test/Verifier/AMDGPU/alloca.ll
index a9f43b30eb8a4..8bb91c17a8f16 100644
--- a/llvm/test/Verifier/AMDGPU/alloca.ll
+++ b/llvm/test/Verifier/AMDGPU/alloca.ll
@@ -2,23 +2,25 @@
 
 target triple = "amdgpu7.00-amd-amdhsa"
 
-; CHECK: alloca on amdgpu must be in addrspace(5)
+; A static alloca is allowed in addrspace(5) (private) and addrspace(13) (VGPR);
+; any other address space is rejected.
+; CHECK: alloca on amdgpu must be in addrspace(5) or addrspace(13)
 ; CHECK-NEXT: %alloca.0 = alloca i32, align 4
-; CHECK-NEXT: alloca on amdgpu must be in addrspace(5)
+; CHECK-NEXT: alloca on amdgpu must be in addrspace(5) or addrspace(13)
 ; CHECK-NEXT: %alloca.1 = alloca i32, align 4, addrspace(1)
-; CHECK-NEXT: alloca on amdgpu must be in addrspace(5)
+; CHECK-NEXT: alloca on amdgpu must be in addrspace(5) or addrspace(13)
 ; CHECK-NEXT: %alloca.2 = alloca i32, align 4, addrspace(2)
-; CHECK-NEXT: alloca on amdgpu must be in addrspace(5)
+; CHECK-NEXT: alloca on amdgpu must be in addrspace(5) or addrspace(13)
 ; CHECK-NEXT: %alloca.3 = alloca i32, align 4, addrspace(3)
-; CHECK-NEXT: alloca on amdgpu must be in addrspace(5)
+; CHECK-NEXT: alloca on amdgpu must be in addrspace(5) or addrspace(13)
 ; CHECK-NEXT: %alloca.4 = alloca i32, align 4, addrspace(4)
-; CHECK-NEXT: alloca on amdgpu must be in addrspace(5)
+; CHECK-NEXT: alloca on amdgpu must be in addrspace(5) or addrspace(13)
 ; CHECK-NEXT: %alloca.6 = alloca i32, align 4, addrspace(6)
-; CHECK-NEXT: alloca on amdgpu must be in addrspace(5)
+; CHECK-NEXT: alloca on amdgpu must be in addrspace(5) or addrspace(13)
 ; CHECK-NEXT: %alloca.7 = alloca i32, align 4, addrspace(7)
-; CHECK-NEXT: alloca on amdgpu must be in addrspace(5)
+; CHECK-NEXT: alloca on amdgpu must be in addrspace(5) or addrspace(13)
 ; CHECK-NEXT: %alloca.8 = alloca i32, align 4, addrspace(8)
-; CHECK-NEXT: alloca on amdgpu must be in addrspace(5)
+; CHECK-NEXT: alloca on amdgpu must be in addrspace(5) or addrspace(13)
 ; CHECK-NEXT: %alloca.9 = alloca i32, align 4, addrspace(9)
 define void @static_alloca() {
 entry:
@@ -32,27 +34,32 @@ entry:
   %alloca.7 = alloca i32, align 4, addrspace(7)
   %alloca.8 = alloca i32, align 4, addrspace(8)
   %alloca.9 = alloca i32, align 4, addrspace(9)
+  %alloca.13 = alloca i32, align 4, addrspace(13)
   ret void
 }
 
-; CHECK: alloca on amdgpu must be in addrspace(5)
+; A dynamically sized alloca is only allowed in addrspace(5); addrspace(13) is
+; rejected because it has no register-file representation.
+; CHECK: alloca on amdgpu must be in addrspace(5) or addrspace(13)
 ; CHECK-NEXT: %alloca.0 = alloca i32, i32 %n, align 4
-; CHECK-NEXT: alloca on amdgpu must be in addrspace(5)
+; CHECK-NEXT: alloca on amdgpu must be in addrspace(5) or addrspace(13)
 ; CHECK-NEXT: %alloca.1 = alloca i32, i32 %n, align 4, addrspace(1)
-; CHECK-NEXT: alloca on amdgpu must be in addrspace(5)
+; CHECK-NEXT: alloca on amdgpu must be in addrspace(5) or addrspace(13)
 ; CHECK-NEXT: %alloca.2 = alloca i32, i32 %n, align 4, addrspace(2)
-; CHECK-NEXT: alloca on amdgpu must be in addrspace(5)
+; CHECK-NEXT: alloca on amdgpu must be in addrspace(5) or addrspace(13)
 ; CHECK-NEXT: %alloca.3 = alloca i32, i32 %n, align 4, addrspace(3)
-; CHECK-NEXT: alloca on amdgpu must be in addrspace(5)
+; CHECK-NEXT: alloca on amdgpu must be in addrspace(5) or addrspace(13)
 ; CHECK-NEXT: %alloca.4 = alloca i32, i32 %n, align 4, addrspace(4)
-; CHECK-NEXT: alloca on amdgpu must be in addrspace(5)
+; CHECK-NEXT: alloca on amdgpu must be in addrspace(5) or addrspace(13)
 ; CHECK-NEXT: %alloca.6 = alloca i32, i32 %n, align 4, addrspace(6)
-; CHECK-NEXT: alloca on amdgpu must be in addrspace(5)
+; CHECK-NEXT: alloca on amdgpu must be in addrspace(5) or addrspace(13)
 ; CHECK-NEXT: %alloca.7 = alloca i32, i32 %n, align 4, addrspace(7)
-; CHECK-NEXT: alloca on amdgpu must be in addrspace(5)
+; CHECK-NEXT: alloca on amdgpu must be in addrspace(5) or addrspace(13)
 ; CHECK-NEXT: %alloca.8 = alloca i32, i32 %n, align 4, addrspace(8)
-; CHECK-NEXT: alloca on amdgpu must be in addrspace(5)
+; CHECK-NEXT: alloca on amdgpu must be in addrspace(5) or addrspace(13)
 ; CHECK-NEXT: %alloca.9 = alloca i32, i32 %n, align 4, addrspace(9)
+; CHECK-NEXT: dynamic alloca on amdgpu must be in addrspace(5)
+; CHECK-NEXT: %alloca.13 = alloca i32, i32 %n, align 4, addrspace(13)
 define void @dynamic_alloca_i32(i32 %n) {
 entry:
   %alloca.0 = alloca i32, i32 %n, align 4
@@ -65,26 +72,27 @@ entry:
   %alloca.7 = alloca i32, i32 %n, align 4, addrspace(7)
   %alloca.8 = alloca i32, i32 %n, align 4, addrspace(8)
   %alloca.9 = alloca i32, i32 %n, align 4, addrspace(9)
+  %alloca.13 = alloca i32, i32 %n, align 4, addrspace(13)
   ret void
 }
 
-; CHECK: alloca on amdgpu must be in addrspace(5)
+; CHECK: alloca on amdgpu must be in addrspace(5) or addrspace(13)
 ; CHECK-NEXT: %alloca.0 = alloca i32, i64 %n, align 4
-; CHECK-NEXT: alloca on amdgpu must be in addrspace(5)
+; CHECK-NEXT: alloca on amdgpu must be in addrspace(5) or addrspace(13)
 ; CHECK-NEXT: %alloca.1 = alloca i32, i64 %n, align 4, addrspace(1)
-; CHECK-NEXT: alloca on amdgpu must be in addrspace(5)
+; CHECK-NEXT: alloca on amdgpu must be in addrspace(5) or addrspace(13)
 ; CHECK-NEXT: %alloca.2 = alloca i32, i64 %n, align 4, addrspace(2)
-; CHECK-NEXT: alloca on amdgpu must be in addrspace(5)
+; CHECK-NEXT: alloca on amdgpu must be in addrspace(5) or addrspace(13)
 ; CHECK-NEXT: %alloca.3 = alloca i32, i64 %n, align 4, addrspace(3)
-; CHECK-NEXT: alloca on amdgpu must be in addrspace(5)
+; CHECK-NEXT: alloca on amdgpu must be in addrspace(5) or addrspace(13)
 ; CHECK-NEXT: %alloca.4 = alloca i32, i64 %n, align 4, addrspace(4)
-; CHECK-NEXT: alloca on amdgpu must be in addrspace(5)
+; CHECK-NEXT: alloca on amdgpu must be in addrspace(5) or addrspace(13)
 ; CHECK-NEXT: %alloca.6 = alloca i32, i64 %n, align 4, addrspace(6)
-; CHECK-NEXT: alloca on amdgpu must be in addrspace(5)
+; CHECK-NEXT: alloca on amdgpu must be in addrspace(5) or addrspace(13)
 ; CHECK-NEXT: %alloca.7 = alloca i32, i64 %n, align 4, addrspace(7)
-; CHECK-NEXT: alloca on amdgpu must be in addrspace(5)
+; CHECK-NEXT: alloca on amdgpu must be in addrspace(5) or addrspace(13)
 ; CHECK-NEXT: %alloca.8 = alloca i32, i64 %n, align 4, addrspace(8)
-; CHECK-NEXT: alloca on amdgpu must be in addrspace(5)
+; CHECK-NEXT: alloca on amdgpu must be in addrspace(5) or addrspace(13)
 ; CHECK-NEXT: %alloca.9 = alloca i32, i64 %n, align 4, addrspace(9)
 define void @dynamic_alloca_i64(i64 %n) {
 entry:
@@ -100,3 +108,16 @@ entry:
   %alloca.9 = alloca i32, i64 %n, align 4, addrspace(9)
   ret void
 }
+
+; A static alloca that is not in the entry block is treated as dynamic, so
+; addrspace(13) is rejected there too.
+; CHECK: dynamic alloca on amdgpu must be in addrspace(5)
+; CHECK-NEXT: %alloca.13 = alloca i32, align 4, addrspace(13)
+define void @nonentry_alloca() {
+entry:
+  br label %nonentry
+
+nonentry:
+  %alloca.13 = alloca i32, align 4, addrspace(13)
+  ret void
+}

diff  --git a/llvm/test/Verifier/AMDGPU/global-variable.ll b/llvm/test/Verifier/AMDGPU/global-variable.ll
new file mode 100644
index 0000000000000..bfea4c1831e4a
--- /dev/null
+++ b/llvm/test/Verifier/AMDGPU/global-variable.ll
@@ -0,0 +1,27 @@
+; RUN: not llvm-as %s --disable-output 2>&1 | FileCheck %s
+
+target triple = "amdgpu7.00-amd-amdhsa"
+
+; A global variable is never allowed in addrspace(13) (VGPR). That address space
+; is a view of one wave's vector registers, so it cannot provide the storage a
+; global needs. Every other address space is left alone.
+
+; CHECK: global variable on amdgpu must not be in addrspace(13)
+; CHECK-NEXT: ptr addrspace(13) @gv.13
+ at gv.13 = addrspace(13) global i32 0, align 4
+
+; A declaration has no initializer, so this covers the path that returns early.
+; CHECK: global variable on amdgpu must not be in addrspace(13)
+; CHECK-NEXT: ptr addrspace(13) @gv.13.extern
+ at gv.13.extern = external addrspace(13) global i32, align 4
+
+; CHECK: global variable on amdgpu must not be in addrspace(13)
+; CHECK-NEXT: ptr addrspace(13) @gv.13.const
+ at gv.13.const = addrspace(13) constant [4 x i32] zeroinitializer, align 4
+
+; CHECK-NOT: global variable on amdgpu
+ at gv.0 = global i32 0, align 4
+ at gv.1 = addrspace(1) global i32 0, align 4
+ at gv.3 = addrspace(3) global i32 poison, align 4
+ at gv.4 = addrspace(4) constant i32 0, align 4
+ at gv.5 = addrspace(5) global i32 0, align 4


        


More information about the llvm-commits mailing list