[clang] [llvm] [IR] Add TargetExtType::CanBeLocal property (PR #99016)

Jay Foad via llvm-commits llvm-commits at lists.llvm.org
Thu Nov 21 04:00:41 PST 2024


https://github.com/jayfoad updated https://github.com/llvm/llvm-project/pull/99016

>From c2eda0aaeeaf9c8711cf64830df9bb3fee842f80 Mon Sep 17 00:00:00 2001
From: Jay Foad <jay.foad at amd.com>
Date: Tue, 16 Jul 2024 11:29:05 +0100
Subject: [PATCH 1/5] [IR] Add TargetExtType::CanBeAlloca property

Add a property to allow marking target extension types that cannot be
used in an alloca instruction, similar to CanBeGlobal for global
variables.
---
 llvm/include/llvm/IR/DerivedTypes.h           | 2 ++
 llvm/lib/IR/Type.cpp                          | 6 ++++--
 llvm/lib/IR/Verifier.cpp                      | 6 ++++++
 llvm/test/Assembler/target-type-properties.ll | 8 ++++++++
 4 files changed, 20 insertions(+), 2 deletions(-)

diff --git a/llvm/include/llvm/IR/DerivedTypes.h b/llvm/include/llvm/IR/DerivedTypes.h
index 01f76d49327808..054cb370bc316c 100644
--- a/llvm/include/llvm/IR/DerivedTypes.h
+++ b/llvm/include/llvm/IR/DerivedTypes.h
@@ -769,6 +769,8 @@ class TargetExtType : public Type {
     HasZeroInit = 1U << 0,
     /// This type may be used as the value type of a global variable.
     CanBeGlobal = 1U << 1,
+    /// This type may be used as the allocated type of an alloca instruction.
+    CanBeAlloca = 1U << 2,
   };
 
   /// Returns true if the target extension type contains the given property.
diff --git a/llvm/lib/IR/Type.cpp b/llvm/lib/IR/Type.cpp
index 9ddccce7f959c7..3f94ca95d2d8a0 100644
--- a/llvm/lib/IR/Type.cpp
+++ b/llvm/lib/IR/Type.cpp
@@ -826,12 +826,14 @@ static TargetTypeInfo getTargetTypeInfo(const TargetExtType *Ty) {
     return TargetTypeInfo(PointerType::get(C, 0), TargetExtType::CanBeGlobal);
   if (Name.starts_with("spirv."))
     return TargetTypeInfo(PointerType::get(C, 0), TargetExtType::HasZeroInit,
-                          TargetExtType::CanBeGlobal);
+                          TargetExtType::CanBeGlobal,
+                          TargetExtType::CanBeAlloca);
 
   // Opaque types in the AArch64 name space.
   if (Name == "aarch64.svcount")
     return TargetTypeInfo(ScalableVectorType::get(Type::getInt1Ty(C), 16),
-                          TargetExtType::HasZeroInit);
+                          TargetExtType::HasZeroInit,
+                          TargetExtType::CanBeAlloca);
 
   return TargetTypeInfo(Type::getVoidTy(C));
 }
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index c095e47996ba17..ab932b591b638e 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -4285,6 +4285,12 @@ void Verifier::visitAllocaInst(AllocaInst &AI) {
   SmallPtrSet<Type*, 4> Visited;
   Check(AI.getAllocatedType()->isSized(&Visited),
         "Cannot allocate unsized type", &AI);
+  // Check if it's a target extension type that disallows being used in an
+  // alloca.
+  if (auto *TTy = dyn_cast<TargetExtType>(AI.getAllocatedType())) {
+    Check(TTy->hasProperty(TargetExtType::CanBeAlloca),
+          "Alloca has illegal target extension type", &AI);
+  }
   Check(AI.getArraySize()->getType()->isIntegerTy(),
         "Alloca array size must have integer type", &AI);
   if (MaybeAlign A = AI.getAlign()) {
diff --git a/llvm/test/Assembler/target-type-properties.ll b/llvm/test/Assembler/target-type-properties.ll
index 49c9d812f1cf4a..eae5eec04da856 100644
--- a/llvm/test/Assembler/target-type-properties.ll
+++ b/llvm/test/Assembler/target-type-properties.ll
@@ -1,6 +1,7 @@
 ; RUN: split-file %s %t
 ; RUN: not llvm-as < %t/zeroinit-error.ll -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-ZEROINIT %s
 ; RUN: not llvm-as < %t/global-var.ll -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-GLOBALVAR %s
+; RUN: not llvm-as < %t/alloca.ll -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-ALLOCA %s
 ; Check target extension type properties are verified in the assembler.
 
 ;--- zeroinit-error.ll
@@ -14,3 +15,10 @@ define void @foo() {
 ;--- global-var.ll
 @global = external global target("unknown_target_type")
 ; CHECK-GLOBALVAR: Global @global has illegal target extension type
+
+;--- alloca.ll
+define void @foo() {
+  %val = alloca target("spirv.Image")
+; CHECK-ALLOCA: Alloca has illegal target extension type
+  ret void
+}

>From 73839348def7318183e24022bc00fd2705d51e3b Mon Sep 17 00:00:00 2001
From: Jay Foad <jay.foad at amd.com>
Date: Wed, 21 Aug 2024 10:34:32 +0100
Subject: [PATCH 2/5] Rename to CanBeLocal. Check byval arguments.

---
 llvm/include/llvm/IR/DerivedTypes.h           |  5 +++--
 llvm/lib/IR/Type.cpp                          |  4 ++--
 llvm/lib/IR/Verifier.cpp                      | 12 +++++++++---
 llvm/test/Assembler/target-type-properties.ll |  5 +++++
 4 files changed, 19 insertions(+), 7 deletions(-)

diff --git a/llvm/include/llvm/IR/DerivedTypes.h b/llvm/include/llvm/IR/DerivedTypes.h
index 054cb370bc316c..46f812dda16c9e 100644
--- a/llvm/include/llvm/IR/DerivedTypes.h
+++ b/llvm/include/llvm/IR/DerivedTypes.h
@@ -769,8 +769,9 @@ class TargetExtType : public Type {
     HasZeroInit = 1U << 0,
     /// This type may be used as the value type of a global variable.
     CanBeGlobal = 1U << 1,
-    /// This type may be used as the allocated type of an alloca instruction.
-    CanBeAlloca = 1U << 2,
+    /// This type may be allocated on the stack, either as the allocated type
+    // of an alloca instruction or as a byval function parameter.
+    CanBeLocal = 1U << 2,
   };
 
   /// Returns true if the target extension type contains the given property.
diff --git a/llvm/lib/IR/Type.cpp b/llvm/lib/IR/Type.cpp
index 3f94ca95d2d8a0..22f4da553e542f 100644
--- a/llvm/lib/IR/Type.cpp
+++ b/llvm/lib/IR/Type.cpp
@@ -827,13 +827,13 @@ static TargetTypeInfo getTargetTypeInfo(const TargetExtType *Ty) {
   if (Name.starts_with("spirv."))
     return TargetTypeInfo(PointerType::get(C, 0), TargetExtType::HasZeroInit,
                           TargetExtType::CanBeGlobal,
-                          TargetExtType::CanBeAlloca);
+                          TargetExtType::CanBeLocal);
 
   // Opaque types in the AArch64 name space.
   if (Name == "aarch64.svcount")
     return TargetTypeInfo(ScalableVectorType::get(Type::getInt1Ty(C), 16),
                           TargetExtType::HasZeroInit,
-                          TargetExtType::CanBeAlloca);
+                          TargetExtType::CanBeLocal);
 
   return TargetTypeInfo(Type::getVoidTy(C));
 }
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index ab932b591b638e..68ed1e3afbb8eb 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -2021,6 +2021,12 @@ void Verifier::verifyParameterAttrs(AttributeSet Attrs, Type *Ty,
       SmallPtrSet<Type *, 4> Visited;
       Check(Attrs.getByValType()->isSized(&Visited),
             "Attribute 'byval' does not support unsized types!", V);
+      // Check if it's a target extension type that disallows being used on the
+      // stack.
+      if (auto *TTy = dyn_cast<TargetExtType>(Attrs.getByValType())) {
+        Check(TTy->hasProperty(TargetExtType::CanBeLocal),
+              "'byval' argument has illegal target extension type", V);
+      }
       Check(DL.getTypeAllocSize(Attrs.getByValType()).getKnownMinValue() <
                 (1ULL << 32),
             "huge 'byval' arguments are unsupported", V);
@@ -4285,10 +4291,10 @@ void Verifier::visitAllocaInst(AllocaInst &AI) {
   SmallPtrSet<Type*, 4> Visited;
   Check(AI.getAllocatedType()->isSized(&Visited),
         "Cannot allocate unsized type", &AI);
-  // Check if it's a target extension type that disallows being used in an
-  // alloca.
+  // Check if it's a target extension type that disallows being used on the
+  // stack.
   if (auto *TTy = dyn_cast<TargetExtType>(AI.getAllocatedType())) {
-    Check(TTy->hasProperty(TargetExtType::CanBeAlloca),
+    Check(TTy->hasProperty(TargetExtType::CanBeLocal),
           "Alloca has illegal target extension type", &AI);
   }
   Check(AI.getArraySize()->getType()->isIntegerTy(),
diff --git a/llvm/test/Assembler/target-type-properties.ll b/llvm/test/Assembler/target-type-properties.ll
index eae5eec04da856..c5fab693115121 100644
--- a/llvm/test/Assembler/target-type-properties.ll
+++ b/llvm/test/Assembler/target-type-properties.ll
@@ -2,6 +2,7 @@
 ; RUN: not llvm-as < %t/zeroinit-error.ll -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-ZEROINIT %s
 ; RUN: not llvm-as < %t/global-var.ll -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-GLOBALVAR %s
 ; RUN: not llvm-as < %t/alloca.ll -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-ALLOCA %s
+; RUN: not llvm-as < %t/byval.ll -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-BYVAL %s
 ; Check target extension type properties are verified in the assembler.
 
 ;--- zeroinit-error.ll
@@ -22,3 +23,7 @@ define void @foo() {
 ; CHECK-ALLOCA: Alloca has illegal target extension type
   ret void
 }
+
+;--- byval.ll
+declare void @foo(ptr byval(target("spirv.Image")))
+; CHECK-BYVAL: 'byval' argument has illegal target extension type

>From c2e94eabb3a3dcd96fcb5b00fc3ac3d1c113dfcb Mon Sep 17 00:00:00 2001
From: Jay Foad <jay.foad at gmail.com>
Date: Wed, 21 Aug 2024 11:52:04 +0100
Subject: [PATCH 3/5] Update llvm/include/llvm/IR/DerivedTypes.h

Co-authored-by: Nikita Popov <github at npopov.com>
---
 llvm/include/llvm/IR/DerivedTypes.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/include/llvm/IR/DerivedTypes.h b/llvm/include/llvm/IR/DerivedTypes.h
index 46f812dda16c9e..626dcb65e8eeb2 100644
--- a/llvm/include/llvm/IR/DerivedTypes.h
+++ b/llvm/include/llvm/IR/DerivedTypes.h
@@ -770,7 +770,7 @@ class TargetExtType : public Type {
     /// This type may be used as the value type of a global variable.
     CanBeGlobal = 1U << 1,
     /// This type may be allocated on the stack, either as the allocated type
-    // of an alloca instruction or as a byval function parameter.
+    /// of an alloca instruction or as a byval function parameter.
     CanBeLocal = 1U << 2,
   };
 

>From f834c163dcc47de9a1860239ab02b29634b90b1e Mon Sep 17 00:00:00 2001
From: Jay Foad <jay.foad at amd.com>
Date: Tue, 19 Nov 2024 15:36:03 +0000
Subject: [PATCH 4/5] Fix tests

---
 clang/test/CodeGen/amdgpu-barrier-type-debug-info.c | 2 +-
 llvm/lib/IR/Type.cpp                                | 3 ++-
 llvm/test/Assembler/target-type-properties.ll       | 4 ++--
 3 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/clang/test/CodeGen/amdgpu-barrier-type-debug-info.c b/clang/test/CodeGen/amdgpu-barrier-type-debug-info.c
index f595f1b222c4f6..4eafbba0ad9a0e 100644
--- a/clang/test/CodeGen/amdgpu-barrier-type-debug-info.c
+++ b/clang/test/CodeGen/amdgpu-barrier-type-debug-info.c
@@ -4,5 +4,5 @@
 // CHECK: name: "__amdgpu_named_workgroup_barrier_t",{{.*}}baseType: ![[BT:[0-9]+]]
 // CHECK: [[BT]] = !DIBasicType(name: "__amdgpu_named_workgroup_barrier_t", size: 128, encoding: DW_ATE_unsigned)
 void test_locals(void) {
-  __amdgpu_named_workgroup_barrier_t k0;
+  __amdgpu_named_workgroup_barrier_t *k0;
 }
diff --git a/llvm/lib/IR/Type.cpp b/llvm/lib/IR/Type.cpp
index 8a2cc71588742f..d1211c0b622cbb 100644
--- a/llvm/lib/IR/Type.cpp
+++ b/llvm/lib/IR/Type.cpp
@@ -951,7 +951,8 @@ static TargetTypeInfo getTargetTypeInfo(const TargetExtType *Ty) {
 
   // DirectX resources
   if (Name.starts_with("dx."))
-    return TargetTypeInfo(PointerType::get(C, 0), TargetExtType::CanBeGlobal);
+    return TargetTypeInfo(PointerType::get(C, 0), TargetExtType::CanBeGlobal,
+                          TargetExtType::CanBeLocal);
 
   // Opaque types in the AMDGPU name space.
   if (Name == "amdgcn.named.barrier") {
diff --git a/llvm/test/Assembler/target-type-properties.ll b/llvm/test/Assembler/target-type-properties.ll
index 0648e21ed82bc7..2c1970baad01f0 100644
--- a/llvm/test/Assembler/target-type-properties.ll
+++ b/llvm/test/Assembler/target-type-properties.ll
@@ -29,11 +29,11 @@ define void @foo() {
 
 ;--- alloca.ll
 define void @foo() {
-  %val = alloca target("spirv.Image")
+  %val = alloca target("amdgcn.named.barrier", 0)
 ; CHECK-ALLOCA: Alloca has illegal target extension type
   ret void
 }
 
 ;--- byval.ll
-declare void @foo(ptr byval(target("spirv.Image")))
+declare void @foo(ptr byval(target("amdgcn.named.barrier", 0)))
 ; CHECK-BYVAL: 'byval' argument has illegal target extension type

>From 44fafe6105bc743579109a66b882c4d8d8c19105 Mon Sep 17 00:00:00 2001
From: Jay Foad <jay.foad at amd.com>
Date: Thu, 21 Nov 2024 11:29:11 +0000
Subject: [PATCH 5/5] Check for nested non-CanBeLocal types

---
 llvm/include/llvm/IR/DerivedTypes.h           |  8 ++++
 llvm/include/llvm/IR/Type.h                   |  6 +++
 llvm/lib/IR/Type.cpp                          | 44 +++++++++++++++++++
 llvm/lib/IR/Verifier.cpp                      | 29 +++++-------
 llvm/test/Assembler/target-type-properties.ll | 13 ++++++
 5 files changed, 83 insertions(+), 17 deletions(-)

diff --git a/llvm/include/llvm/IR/DerivedTypes.h b/llvm/include/llvm/IR/DerivedTypes.h
index 1b46f1672e0cd9..b44f4f8c8687dc 100644
--- a/llvm/include/llvm/IR/DerivedTypes.h
+++ b/llvm/include/llvm/IR/DerivedTypes.h
@@ -228,6 +228,8 @@ class StructType : public Type {
     SCDB_NotContainsScalableVector = 32,
     SCDB_ContainsNonGlobalTargetExtType = 64,
     SCDB_NotContainsNonGlobalTargetExtType = 128,
+    SCDB_ContainsNonLocalTargetExtType = 64,
+    SCDB_NotContainsNonLocalTargetExtType = 128,
   };
 
   /// For a named struct that actually has a name, this is a pointer to the
@@ -302,6 +304,12 @@ class StructType : public Type {
   containsNonGlobalTargetExtType(SmallPtrSetImpl<const Type *> &Visited) const;
   using Type::containsNonGlobalTargetExtType;
 
+  /// Return true if this type is or contains a target extension type that
+  /// disallows being used as a local.
+  bool
+  containsNonLocalTargetExtType(SmallPtrSetImpl<const Type *> &Visited) const;
+  using Type::containsNonLocalTargetExtType;
+
   /// Returns true if this struct contains homogeneous scalable vector types.
   /// Note that the definition of homogeneous scalable vector type is not
   /// recursive here. That means the following structure will return false
diff --git a/llvm/include/llvm/IR/Type.h b/llvm/include/llvm/IR/Type.h
index 000fdee45bb861..6dadf158a739fc 100644
--- a/llvm/include/llvm/IR/Type.h
+++ b/llvm/include/llvm/IR/Type.h
@@ -215,6 +215,12 @@ class Type {
   containsNonGlobalTargetExtType(SmallPtrSetImpl<const Type *> &Visited) const;
   bool containsNonGlobalTargetExtType() const;
 
+  /// Return true if this type is or contains a target extension type that
+  /// disallows being used as a local.
+  bool
+  containsNonLocalTargetExtType(SmallPtrSetImpl<const Type *> &Visited) const;
+  bool containsNonLocalTargetExtType() const;
+
   /// Return true if this is a FP type or a vector of FP.
   bool isFPOrFPVectorTy() const { return getScalarType()->isFloatingPointTy(); }
 
diff --git a/llvm/lib/IR/Type.cpp b/llvm/lib/IR/Type.cpp
index d1211c0b622cbb..ac6b8b4c197002 100644
--- a/llvm/lib/IR/Type.cpp
+++ b/llvm/lib/IR/Type.cpp
@@ -88,6 +88,22 @@ bool Type::containsNonGlobalTargetExtType() const {
   return containsNonGlobalTargetExtType(Visited);
 }
 
+bool Type::containsNonLocalTargetExtType(
+    SmallPtrSetImpl<const Type *> &Visited) const {
+  if (const auto *ATy = dyn_cast<ArrayType>(this))
+    return ATy->getElementType()->containsNonLocalTargetExtType(Visited);
+  if (const auto *STy = dyn_cast<StructType>(this))
+    return STy->containsNonLocalTargetExtType(Visited);
+  if (auto *TT = dyn_cast<TargetExtType>(this))
+    return !TT->hasProperty(TargetExtType::CanBeLocal);
+  return false;
+}
+
+bool Type::containsNonLocalTargetExtType() const {
+  SmallPtrSet<const Type *, 4> Visited;
+  return containsNonLocalTargetExtType(Visited);
+}
+
 const fltSemantics &Type::getFltSemantics() const {
   switch (getTypeID()) {
   case HalfTyID: return APFloat::IEEEhalf();
@@ -469,6 +485,34 @@ bool StructType::containsNonGlobalTargetExtType(
   return false;
 }
 
+bool StructType::containsNonLocalTargetExtType(
+    SmallPtrSetImpl<const Type *> &Visited) const {
+  if ((getSubclassData() & SCDB_ContainsNonLocalTargetExtType) != 0)
+    return true;
+
+  if ((getSubclassData() & SCDB_NotContainsNonLocalTargetExtType) != 0)
+    return false;
+
+  if (!Visited.insert(this).second)
+    return false;
+
+  for (Type *Ty : elements()) {
+    if (Ty->containsNonLocalTargetExtType(Visited)) {
+      const_cast<StructType *>(this)->setSubclassData(
+          getSubclassData() | SCDB_ContainsNonLocalTargetExtType);
+      return true;
+    }
+  }
+
+  // For structures that are opaque, return false but do not set the
+  // SCDB_NotContainsNonLocalTargetExtType flag since it may gain non-local
+  // target extension types when it becomes non-opaque.
+  if (!isOpaque())
+    const_cast<StructType *>(this)->setSubclassData(
+        getSubclassData() | SCDB_NotContainsNonLocalTargetExtType);
+  return false;
+}
+
 bool StructType::containsHomogeneousScalableVectorTypes() const {
   if (getNumElements() <= 0 || !isa<ScalableVectorType>(elements().front()))
     return false;
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 0270b4b986991c..67834631b3c50d 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -2026,17 +2026,15 @@ void Verifier::verifyParameterAttrs(AttributeSet Attrs, Type *Ty,
             "huge alignment values are unsupported", V);
     }
     if (Attrs.hasAttribute(Attribute::ByVal)) {
+      Type *ByValTy = Attrs.getByValType();
       SmallPtrSet<Type *, 4> Visited;
-      Check(Attrs.getByValType()->isSized(&Visited),
+      Check(ByValTy->isSized(&Visited),
             "Attribute 'byval' does not support unsized types!", V);
-      // Check if it's a target extension type that disallows being used on the
-      // stack.
-      if (auto *TTy = dyn_cast<TargetExtType>(Attrs.getByValType())) {
-        Check(TTy->hasProperty(TargetExtType::CanBeLocal),
-              "'byval' argument has illegal target extension type", V);
-      }
-      Check(DL.getTypeAllocSize(Attrs.getByValType()).getKnownMinValue() <
-                (1ULL << 32),
+      // Check if it is or contains a target extension type that disallows being
+      // used on the stack.
+      Check(!ByValTy->containsNonLocalTargetExtType(),
+            "'byval' argument has illegal target extension type", V);
+      Check(DL.getTypeAllocSize(ByValTy).getKnownMinValue() < (1ULL << 32),
             "huge 'byval' arguments are unsupported", V);
     }
     if (Attrs.hasAttribute(Attribute::ByRef)) {
@@ -4329,15 +4327,13 @@ void Verifier::verifySwiftErrorValue(const Value *SwiftErrorVal) {
 }
 
 void Verifier::visitAllocaInst(AllocaInst &AI) {
+  Type *Ty = AI.getAllocatedType();
   SmallPtrSet<Type*, 4> Visited;
-  Check(AI.getAllocatedType()->isSized(&Visited),
-        "Cannot allocate unsized type", &AI);
+  Check(Ty->isSized(&Visited), "Cannot allocate unsized type", &AI);
   // Check if it's a target extension type that disallows being used on the
   // stack.
-  if (auto *TTy = dyn_cast<TargetExtType>(AI.getAllocatedType())) {
-    Check(TTy->hasProperty(TargetExtType::CanBeLocal),
-          "Alloca has illegal target extension type", &AI);
-  }
+  Check(!Ty->containsNonLocalTargetExtType(),
+        "Alloca has illegal target extension type", &AI);
   Check(AI.getArraySize()->getType()->isIntegerTy(),
         "Alloca array size must have integer type", &AI);
   if (MaybeAlign A = AI.getAlign()) {
@@ -4346,8 +4342,7 @@ void Verifier::visitAllocaInst(AllocaInst &AI) {
   }
 
   if (AI.isSwiftError()) {
-    Check(AI.getAllocatedType()->isPointerTy(),
-          "swifterror alloca must have pointer type", &AI);
+    Check(Ty->isPointerTy(), "swifterror alloca must have pointer type", &AI);
     Check(!AI.isArrayAllocation(),
           "swifterror alloca must not be array allocation", &AI);
     verifySwiftErrorValue(&AI);
diff --git a/llvm/test/Assembler/target-type-properties.ll b/llvm/test/Assembler/target-type-properties.ll
index 2c1970baad01f0..8d58b09d3b1702 100644
--- a/llvm/test/Assembler/target-type-properties.ll
+++ b/llvm/test/Assembler/target-type-properties.ll
@@ -4,7 +4,9 @@
 ; RUN: not llvm-as < %t/global-array.ll -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-GLOBAL-ARRAY %s
 ; RUN: not llvm-as < %t/global-struct.ll -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-GLOBAL-STRUCT %s
 ; RUN: not llvm-as < %t/alloca.ll -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-ALLOCA %s
+; RUN: not llvm-as < %t/alloca-struct.ll -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-ALLOCA-STRUCT %s
 ; RUN: not llvm-as < %t/byval.ll -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-BYVAL %s
+; RUN: not llvm-as < %t/byval-array.ll -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-BYVAL-ARRAY %s
 ; Check target extension type properties are verified in the assembler.
 
 ;--- zeroinit-error.ll
@@ -34,6 +36,17 @@ define void @foo() {
   ret void
 }
 
+;--- alloca-struct.ll
+define void @foo() {
+  %val = alloca {target("amdgcn.named.barrier", 0), target("amdgcn.named.barrier", 0)}
+; CHECK-ALLOCA-STRUCT: Alloca has illegal target extension type
+  ret void
+}
+
 ;--- byval.ll
 declare void @foo(ptr byval(target("amdgcn.named.barrier", 0)))
 ; CHECK-BYVAL: 'byval' argument has illegal target extension type
+
+;--- byval-array.ll
+declare void @foo(ptr byval([4 x target("amdgcn.named.barrier", 0)]))
+; CHECK-BYVAL-ARRAY: 'byval' argument has illegal target extension type



More information about the llvm-commits mailing list