// 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 -x c++ -std=c++2b %s -o - | FileCheck --check-prefix=AMDGCN %s // RUN: %clang_cc1 -triple spirv64-amd-amdhsa -emit-llvm -x c++ -std=c++2b %s -o - | FileCheck --check-prefix=SPIRV %s // REQUIRES: amdgpu-registered-target // Verify that a non-trivially-copyable type returned via sret into a member // field uses addrspace(0) for the sret pointer (not addrspace(5)). So // in-place construction through the addrspace(0) is the only legal option. struct NontrivialPtr { void *p; NontrivialPtr() noexcept; NontrivialPtr(const NontrivialPtr &) = delete; NontrivialPtr(NontrivialPtr &&) = delete; ~NontrivialPtr() noexcept; }; NontrivialPtr make() noexcept; struct Wrapper { NontrivialPtr field; Wrapper() noexcept; virtual ~Wrapper() noexcept; }; Wrapper::Wrapper() noexcept : field(make()) {} // AMDGCN-LABEL: define dso_local void @_ZN7WrapperC2Ev( // AMDGCN-SAME: ptr noundef nonnull align 8 dereferenceable(16) [[THIS:%.*]]) unnamed_addr #[[ATTR0:[0-9]+]] align 2 { // AMDGCN-NEXT: [[ENTRY:.*:]] // AMDGCN-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8, addrspace(5) // AMDGCN-NEXT: [[THIS_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[THIS_ADDR]] to ptr // AMDGCN-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR_ASCAST]], align 8 // AMDGCN-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR_ASCAST]], align 8 // AMDGCN-NEXT: store ptr addrspace(1) getelementptr inbounds inrange(-16, 16) ({ [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTV7Wrapper, i32 0, i32 0, i32 2), ptr [[THIS1]], align 8 // AMDGCN-NEXT: [[FIELD:%.*]] = getelementptr inbounds nuw [[STRUCT_WRAPPER:%.*]], ptr [[THIS1]], i32 0, i32 1 // AMDGCN-NEXT: call void @_Z4makev(ptr dead_on_unwind writable sret([[STRUCT_NONTRIVIALPTR:%.*]]) align 8 [[FIELD]]) #[[ATTR2:[0-9]+]] // AMDGCN-NEXT: ret void // // // AMDGCN-LABEL: define dso_local void @_ZN7WrapperC1Ev( // AMDGCN-SAME: ptr noundef nonnull align 8 dereferenceable(16) [[THIS:%.*]]) unnamed_addr #[[ATTR0]] align 2 { // AMDGCN-NEXT: [[ENTRY:.*:]] // AMDGCN-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8, addrspace(5) // AMDGCN-NEXT: [[THIS_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[THIS_ADDR]] to ptr // AMDGCN-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR_ASCAST]], align 8 // AMDGCN-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR_ASCAST]], align 8 // AMDGCN-NEXT: call void @_ZN7WrapperC2Ev(ptr noundef nonnull align 8 dereferenceable(16) [[THIS1]]) #[[ATTR2]] // AMDGCN-NEXT: ret void // // // SPIRV-LABEL: define spir_func void @_ZN7WrapperC2Ev( // SPIRV-SAME: ptr addrspace(4) noundef align 8 dereferenceable_or_null(16) [[THIS:%.*]]) unnamed_addr addrspace(4) #[[ATTR0:[0-9]+]] align 2 { // SPIRV-NEXT: [[ENTRY:.*:]] // SPIRV-NEXT: [[THIS_ADDR:%.*]] = alloca ptr addrspace(4), align 8 // SPIRV-NEXT: [[THIS_ADDR_ASCAST:%.*]] = addrspacecast ptr [[THIS_ADDR]] to ptr addrspace(4) // SPIRV-NEXT: store ptr addrspace(4) [[THIS]], ptr addrspace(4) [[THIS_ADDR_ASCAST]], align 8 // SPIRV-NEXT: [[THIS1:%.*]] = load ptr addrspace(4), ptr addrspace(4) [[THIS_ADDR_ASCAST]], align 8 // SPIRV-NEXT: store ptr addrspace(1) getelementptr inbounds inrange(-16, 16) ({ [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTV7Wrapper, i32 0, i32 0, i32 2), ptr addrspace(4) [[THIS1]], align 8 // SPIRV-NEXT: [[FIELD:%.*]] = getelementptr inbounds nuw [[STRUCT_WRAPPER:%.*]], ptr addrspace(4) [[THIS1]], i32 0, i32 1 // SPIRV-NEXT: call spir_func addrspace(4) void @_Z4makev(ptr addrspace(4) dead_on_unwind writable sret([[STRUCT_NONTRIVIALPTR:%.*]]) align 8 [[FIELD]]) #[[ATTR2:[0-9]+]] // SPIRV-NEXT: ret void // // // SPIRV-LABEL: define spir_func void @_ZN7WrapperC1Ev( // SPIRV-SAME: ptr addrspace(4) noundef align 8 dereferenceable_or_null(16) [[THIS:%.*]]) unnamed_addr addrspace(4) #[[ATTR0]] align 2 { // SPIRV-NEXT: [[ENTRY:.*:]] // SPIRV-NEXT: [[THIS_ADDR:%.*]] = alloca ptr addrspace(4), align 8 // SPIRV-NEXT: [[THIS_ADDR_ASCAST:%.*]] = addrspacecast ptr [[THIS_ADDR]] to ptr addrspace(4) // SPIRV-NEXT: store ptr addrspace(4) [[THIS]], ptr addrspace(4) [[THIS_ADDR_ASCAST]], align 8 // SPIRV-NEXT: [[THIS1:%.*]] = load ptr addrspace(4), ptr addrspace(4) [[THIS_ADDR_ASCAST]], align 8 // SPIRV-NEXT: call spir_func addrspace(4) void @_ZN7WrapperC2Ev(ptr addrspace(4) noundef align 8 dereferenceable_or_null(16) [[THIS1]]) #[[ATTR2]] // SPIRV-NEXT: ret void //