Files
llvm-project/clang/test/CodeGenHIP/sret-lifetime-markers.cpp
Vigneshwar Jayakumar 5d4b17e963 [Clang][SPIRV] Add getSRetAddrSpace() for SPIRV (#193875)
Override getSRetAddrSpace() so that sret pointers for non-trivially-
copyable types use the generic address space (addrspace 4), matching the
"this" pointer convention on spirv64-amd-amdhsa.
2026-04-23 23:31:27 -05:00

62 lines
3.7 KiB
C++

// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --functions ".*" --include-generated-funcs --version 6
// RUN: %clang_cc1 -triple amdgcn-amd-amdhsa -emit-llvm -O1 -x c++ -std=c++2b %s -o - | FileCheck --check-prefix=AMDGCN %s
// RUN: %clang_cc1 -triple spirv64-amd-amdhsa -emit-llvm -O1 -x c++ -std=c++2b %s -o - | FileCheck --check-prefix=SPIRV %s
// REQUIRES: amdgpu-registered-target
// Verify that lifetime markers for an sret temporary use the alloca address
// space (5), even when the sret pointer itself is in the default address
// space (0). Regression test for an assertion failure in EmitLifetimeEnd
// when the return value of a function returning a non-trivially-copyable
// type is discarded.
template <int N>
struct SuperScalar {
double val[N];
SuperScalar() {
for (int i = 0; i < N; i++) val[i] = 0.0;
}
SuperScalar(const SuperScalar& rhs) {
for (int i = 0; i < N; i++) val[i] = rhs.val[i];
}
SuperScalar& operator=(const SuperScalar& rhs) {
for (int i = 0; i < N; i++) val[i] = rhs.val[i];
return *this;
}
};
template <int N>
SuperScalar<N> atomic_fetch_add(SuperScalar<N>* dest, const SuperScalar<N>& val);
template <int N>
void add_functor(SuperScalar<N>* data, int i, SuperScalar<N>& update) {
atomic_fetch_add(&data[i], update);
}
template void add_functor<4>(SuperScalar<4>*, int, SuperScalar<4>&);
// AMDGCN-LABEL: define weak_odr void @_Z11add_functorILi4EEvP11SuperScalarIXT_EEiRS1_(
// AMDGCN-SAME: ptr noundef [[DATA:%.*]], i32 noundef [[I:%.*]], ptr noundef nonnull align 8 dereferenceable(32) [[UPDATE:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] comdat {
// AMDGCN-NEXT: [[ENTRY:.*:]]
// AMDGCN-NEXT: [[TMP:%.*]] = alloca [[STRUCT_SUPERSCALAR:%.*]], align 8, addrspace(5)
// AMDGCN-NEXT: [[IDXPROM:%.*]] = sext i32 [[I]] to i64
// AMDGCN-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [32 x i8], ptr [[DATA]], i64 [[IDXPROM]]
// AMDGCN-NEXT: call void @llvm.lifetime.start.p5(ptr addrspace(5) [[TMP]]) #[[ATTR3:[0-9]+]]
// AMDGCN-NEXT: [[TMP_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[TMP]] to ptr
// AMDGCN-NEXT: call void @_Z16atomic_fetch_addILi4EE11SuperScalarIXT_EEPS1_RKS1_(ptr dead_on_unwind writable sret([[STRUCT_SUPERSCALAR]]) align 8 [[TMP_ASCAST]], ptr noundef [[ARRAYIDX]], ptr noundef nonnull align 8 dereferenceable(32) [[UPDATE]]) #[[ATTR4:[0-9]+]]
// AMDGCN-NEXT: call void @llvm.lifetime.end.p5(ptr addrspace(5) [[TMP]]) #[[ATTR3]]
// AMDGCN-NEXT: ret void
//
//
// SPIRV-LABEL: define weak_odr spir_func void @_Z11add_functorILi4EEvP11SuperScalarIXT_EEiRS1_(
// SPIRV-SAME: ptr addrspace(4) noundef [[DATA:%.*]], i32 noundef [[I:%.*]], ptr addrspace(4) noundef align 8 dereferenceable(32) [[UPDATE:%.*]]) local_unnamed_addr addrspace(4) #[[ATTR0:[0-9]+]] comdat {
// SPIRV-NEXT: [[ENTRY:.*:]]
// SPIRV-NEXT: [[TMP:%.*]] = alloca [[STRUCT_SUPERSCALAR:%.*]], align 8
// SPIRV-NEXT: [[IDXPROM:%.*]] = sext i32 [[I]] to i64
// SPIRV-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [32 x i8], ptr addrspace(4) [[DATA]], i64 [[IDXPROM]]
// SPIRV-NEXT: call addrspace(4) void @llvm.lifetime.start.p0(ptr nonnull [[TMP]]) #[[ATTR3:[0-9]+]]
// SPIRV-NEXT: [[TMP_ASCAST:%.*]] = addrspacecast ptr [[TMP]] to ptr addrspace(4)
// SPIRV-NEXT: call spir_func addrspace(4) void @_Z16atomic_fetch_addILi4EE11SuperScalarIXT_EEPS1_RKS1_(ptr addrspace(4) dead_on_unwind writable sret([[STRUCT_SUPERSCALAR]]) align 8 [[TMP_ASCAST]], ptr addrspace(4) noundef [[ARRAYIDX]], ptr addrspace(4) noundef align 8 dereferenceable(32) [[UPDATE]]) #[[ATTR3]]
// SPIRV-NEXT: call addrspace(4) void @llvm.lifetime.end.p0(ptr nonnull [[TMP]]) #[[ATTR3]]
// SPIRV-NEXT: ret void
//