| // 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 |
| // |