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.
62 lines
3.7 KiB
C++
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
|
|
//
|