Skip to content

[IR] Add TargetExtType::CanBeLocal property #99016

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

Merged
merged 7 commits into from
Nov 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion clang/test/CodeGen/amdgpu-barrier-type-debug-info.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
11 changes: 11 additions & 0 deletions llvm/include/llvm/IR/DerivedTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,8 @@ class StructType : public Type {
SCDB_NotContainsScalableVector = 32,
SCDB_ContainsNonGlobalTargetExtType = 64,
SCDB_NotContainsNonGlobalTargetExtType = 128,
SCDB_ContainsNonLocalTargetExtType = 64,
SCDB_NotContainsNonLocalTargetExtType = 128,
Comment on lines +231 to +232
Copy link
Contributor Author

Choose a reason for hiding this comment

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

TBH I'm not sure if it's really worth adding these flags, just for an IR verifier check. I guess it accelerates recursive checking of pathological struct types with lots of repeated element types.

};

/// For a named struct that actually has a name, this is a pointer to the
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -798,6 +806,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 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.
Expand Down
6 changes: 6 additions & 0 deletions llvm/include/llvm/IR/Type.h
Original file line number Diff line number Diff line change
Expand Up @@ -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(); }

Expand Down
59 changes: 54 additions & 5 deletions llvm/lib/IR/Type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -922,15 +966,18 @@ static TargetTypeInfo getTargetTypeInfo(const TargetExtType *Ty) {
LLVMContext &C = Ty->getContext();
StringRef Name = Ty->getName();
if (Name == "spirv.Image")
return TargetTypeInfo(PointerType::get(C, 0), TargetExtType::CanBeGlobal);
return TargetTypeInfo(PointerType::get(C, 0), TargetExtType::CanBeGlobal,
TargetExtType::CanBeLocal);
if (Name.starts_with("spirv."))
return TargetTypeInfo(PointerType::get(C, 0), TargetExtType::HasZeroInit,
TargetExtType::CanBeGlobal);
TargetExtType::CanBeGlobal,
TargetExtType::CanBeLocal);

// Opaque types in the AArch64 name space.
if (Name == "aarch64.svcount")
return TargetTypeInfo(ScalableVectorType::get(Type::getInt1Ty(C), 16),
TargetExtType::HasZeroInit);
TargetExtType::HasZeroInit,
TargetExtType::CanBeLocal);

// RISC-V vector tuple type. The layout is represented as the type that needs
// the same number of vector registers(VREGS) as this tuple type, represented
Expand All @@ -942,12 +989,14 @@ static TargetTypeInfo getTargetTypeInfo(const TargetExtType *Ty) {
RISCV::RVVBitsPerBlock / 8) *
Ty->getIntParameter(0);
return TargetTypeInfo(
ScalableVectorType::get(Type::getInt8Ty(C), TotalNumElts));
ScalableVectorType::get(Type::getInt8Ty(C), TotalNumElts),
TargetExtType::CanBeLocal);
}

// 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") {
Expand Down
21 changes: 14 additions & 7 deletions llvm/lib/IR/Verifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2026,11 +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(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)) {
Expand Down Expand Up @@ -4323,9 +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.
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()) {
Expand All @@ -4334,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);
Expand Down
26 changes: 26 additions & 0 deletions llvm/test/Assembler/target-type-properties.ll
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
; RUN: not llvm-as < %t/global-var.ll -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-GLOBAL-VAR %s
; 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
Expand All @@ -24,3 +28,25 @@ define void @foo() {
;--- global-struct.ll
@global_struct = external global {target("unknown_target_type")}
; CHECK-GLOBAL-STRUCT: Global @global_struct has illegal target extension type

;--- alloca.ll
define void @foo() {
%val = alloca target("amdgcn.named.barrier", 0)
; CHECK-ALLOCA: Alloca has illegal target extension type
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
Loading