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.f...@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.f...@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.f...@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 <git...@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.f...@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.f...@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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits