blob: c07d2f426ce5093c7bab3c255710a16ae8540e67 [file] [edit]
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --function-signature --include-generated-funcs --replace-value-regex "__omp_offloading_[0-9a-z]+_[0-9a-z]+" "reduction_size[.].+[.]" "pl_cond[.].+[.|,]" --prefix-filecheck-ir-name _
// RUN: %clang_cc1 -verify=omp60 -fopenmp -fopenmp-version=60 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=amdgpu-amd-amdhsa -emit-llvm %s -o - | FileCheck %s --check-prefix=HOST
// RUN: %clang_cc1 -verify=omp60 -fopenmp -fopenmp-version=60 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=amdgpu-amd-amdhsa -emit-llvm-bc %s -o %t-host.bc
// RUN: %clang_cc1 -verify=omp60 -fopenmp -fopenmp-version=60 -x c++ -triple amdgpu-amd-amdhsa -emit-llvm %s -fopenmp-is-target-device -fvisibility=protected -fopenmp-host-ir-file-path %t-host.bc -o - | FileCheck %s --check-prefix=DEVICE
// RUN: %clang_cc1 -verify=omp60 -fopenmp -fopenmp-version=60 -x c++ -triple amdgpu-amd-amdhsa %s -fopenmp-is-target-device -fvisibility=protected -fopenmp-host-ir-file-path %t-host.bc -emit-pch -o %t
// RUN: %clang_cc1 -fopenmp -fopenmp-version=60 -x c++ -triple amdgpu-amd-amdhsa -emit-llvm %s -fopenmp-is-target-device -fvisibility=protected -fopenmp-host-ir-file-path %t-host.bc -include-pch %t -o - | FileCheck %s --check-prefix=DEVICE
#ifndef HEADER
#define HEADER
// ---------------------------------------------------------------------------
// Explicit local clause (default device_type is 'any')
// ---------------------------------------------------------------------------
int local_scalar;
#pragma omp declare target local(local_scalar)
int local_array[64];
#pragma omp declare target local(local_array)
// ---------------------------------------------------------------------------
// local + device_type(nohost)
// ---------------------------------------------------------------------------
int local_nohost_var;
#pragma omp declare target local(local_nohost_var) device_type(nohost) // omp60-warning {{'device_type(nohost)' is not yet supported with 'local' clause; treating as 'device_type(any)'}}
double local_nohost_arr[32];
#pragma omp declare target local(local_nohost_arr) device_type(nohost) // omp60-warning {{'device_type(nohost)' is not yet supported with 'local' clause; treating as 'device_type(any)'}}
// ---------------------------------------------------------------------------
// Template with local variable
// ---------------------------------------------------------------------------
template <typename T>
struct LocalStorage {
static T value;
};
template <typename T>
T LocalStorage<T>::value;
#pragma omp declare target local(LocalStorage<int>::value)
#pragma omp declare target local(LocalStorage<double>::value)
#pragma omp begin declare target
template <typename T>
T read_local_storage() {
return LocalStorage<T>::value;
}
#pragma omp end declare target
// ---------------------------------------------------------------------------
// Non-template static data member with local
// ---------------------------------------------------------------------------
struct PlainStruct {
static int s_member;
};
int PlainStruct::s_member;
#pragma omp declare target local(PlainStruct::s_member)
// ---------------------------------------------------------------------------
// Initialized local variable
// ---------------------------------------------------------------------------
int local_init_var = 42;
#pragma omp declare target local(local_init_var)
// ---------------------------------------------------------------------------
// Use local variables in a target region
// ---------------------------------------------------------------------------
int use_local_vars() {
int result = 0;
#pragma omp target map(from: result)
{
local_scalar = 42;
local_array[0] = 1;
LocalStorage<int>::value = 100;
result = local_scalar + local_array[0]
+ read_local_storage<int>();
}
return result;
}
// ---------------------------------------------------------------------------
// Use nohost local variables in a target region
// ---------------------------------------------------------------------------
int use_nohost_local_vars() {
int result = 0;
#pragma omp target map(from: result)
{
local_nohost_var = 7;
result = local_nohost_var;
}
return result;
}
// ---------------------------------------------------------------------------
// Use static data member, initialized var, and static local in target region
// ---------------------------------------------------------------------------
int use_new_local_vars() {
int result = 0;
#pragma omp target map(from: result)
{
PlainStruct::s_member = 55;
local_init_var = 77;
result = PlainStruct::s_member + local_init_var;
}
return result;
}
#endif
// HOST-LABEL: define {{[^@]+}}@_Z14use_local_varsv
// HOST-SAME: () #[[ATTR0:[0-9]+]] {
// HOST-NEXT: entry:
// HOST-NEXT: [[RESULT:%.*]] = alloca i32, align 4
// HOST-NEXT: [[DOTOFFLOAD_BASEPTRS:%.*]] = alloca [2 x ptr], align 8
// HOST-NEXT: [[DOTOFFLOAD_PTRS:%.*]] = alloca [2 x ptr], align 8
// HOST-NEXT: [[DOTOFFLOAD_MAPPERS:%.*]] = alloca [2 x ptr], align 8
// HOST-NEXT: [[KERNEL_ARGS:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], align 8
// HOST-NEXT: store i32 0, ptr [[RESULT]], align 4
// HOST-NEXT: [[TMP0:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
// HOST-NEXT: store ptr [[RESULT]], ptr [[TMP0]], align 8
// HOST-NEXT: [[TMP1:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
// HOST-NEXT: store ptr [[RESULT]], ptr [[TMP1]], align 8
// HOST-NEXT: [[TMP2:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 0
// HOST-NEXT: store ptr null, ptr [[TMP2]], align 8
// HOST-NEXT: [[TMP3:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
// HOST-NEXT: store ptr null, ptr [[TMP3]], align 8
// HOST-NEXT: [[TMP4:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
// HOST-NEXT: store ptr null, ptr [[TMP4]], align 8
// HOST-NEXT: [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
// HOST-NEXT: store ptr null, ptr [[TMP5]], align 8
// HOST-NEXT: [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
// HOST-NEXT: [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
// HOST-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0
// HOST-NEXT: store i32 5, ptr [[TMP8]], align 4
// HOST-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1
// HOST-NEXT: store i32 2, ptr [[TMP9]], align 4
// HOST-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2
// HOST-NEXT: store ptr [[TMP6]], ptr [[TMP10]], align 8
// HOST-NEXT: [[TMP11:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 3
// HOST-NEXT: store ptr [[TMP7]], ptr [[TMP11]], align 8
// HOST-NEXT: [[TMP12:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 4
// HOST-NEXT: store ptr @.offload_sizes, ptr [[TMP12]], align 8
// HOST-NEXT: [[TMP13:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 5
// HOST-NEXT: store ptr @.offload_maptypes, ptr [[TMP13]], align 8
// HOST-NEXT: [[TMP14:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 6
// HOST-NEXT: store ptr null, ptr [[TMP14]], align 8
// HOST-NEXT: [[TMP15:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 7
// HOST-NEXT: store ptr null, ptr [[TMP15]], align 8
// HOST-NEXT: [[TMP16:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 8
// HOST-NEXT: store i64 0, ptr [[TMP16]], align 8
// HOST-NEXT: [[TMP17:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 9
// HOST-NEXT: store i64 0, ptr [[TMP17]], align 8
// HOST-NEXT: [[TMP18:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 10
// HOST-NEXT: store [3 x i32] [i32 -1, i32 0, i32 0], ptr [[TMP18]], align 4
// HOST-NEXT: [[TMP19:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 11
// HOST-NEXT: store [3 x i32] zeroinitializer, ptr [[TMP19]], align 4
// HOST-NEXT: [[TMP20:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 12
// HOST-NEXT: store i32 0, ptr [[TMP20]], align 4
// HOST-NEXT: [[TMP21:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1:[0-9]+]], i64 -1, i32 -1, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z14use_local_varsv_l70.region_id, ptr [[KERNEL_ARGS]])
// HOST-NEXT: [[TMP22:%.*]] = icmp ne i32 [[TMP21]], 0
// HOST-NEXT: br i1 [[TMP22]], label [[OMP_OFFLOAD_FAILED:%.*]], label [[OMP_OFFLOAD_CONT:%.*]]
// HOST: omp_offload.failed:
// HOST-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z14use_local_varsv_l70(ptr [[RESULT]], ptr null) #[[ATTR2:[0-9]+]]
// HOST-NEXT: br label [[OMP_OFFLOAD_CONT]]
// HOST: omp_offload.cont:
// HOST-NEXT: [[TMP23:%.*]] = load i32, ptr [[RESULT]], align 4
// HOST-NEXT: ret i32 [[TMP23]]
//
//
// HOST-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z14use_local_varsv_l70
// HOST-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[RESULT:%.*]], ptr noalias noundef [[DYN_PTR:%.*]]) #[[ATTR1:[0-9]+]] {
// HOST-NEXT: entry:
// HOST-NEXT: [[RESULT_ADDR:%.*]] = alloca ptr, align 8
// HOST-NEXT: [[DYN_PTR_ADDR:%.*]] = alloca ptr, align 8
// HOST-NEXT: store ptr [[RESULT]], ptr [[RESULT_ADDR]], align 8
// HOST-NEXT: store ptr [[DYN_PTR]], ptr [[DYN_PTR_ADDR]], align 8
// HOST-NEXT: [[TMP0:%.*]] = load ptr, ptr [[RESULT_ADDR]], align 8, !nonnull [[META8:![0-9]+]], !align [[META9:![0-9]+]]
// HOST-NEXT: store i32 42, ptr @local_scalar, align 4
// HOST-NEXT: store i32 1, ptr @local_array, align 4
// HOST-NEXT: store i32 100, ptr @_ZN12LocalStorageIiE5valueE, align 4
// HOST-NEXT: [[TMP1:%.*]] = load i32, ptr @local_scalar, align 4
// HOST-NEXT: [[TMP2:%.*]] = load i32, ptr @local_array, align 4
// HOST-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP1]], [[TMP2]]
// HOST-NEXT: [[CALL:%.*]] = call noundef signext i32 @_Z18read_local_storageIiET_v()
// HOST-NEXT: [[ADD1:%.*]] = add nsw i32 [[ADD]], [[CALL]]
// HOST-NEXT: store i32 [[ADD1]], ptr [[TMP0]], align 4
// HOST-NEXT: ret void
//
//
// HOST-LABEL: define {{[^@]+}}@_Z18read_local_storageIiET_v
// HOST-SAME: () #[[ATTR0]] comdat {
// HOST-NEXT: entry:
// HOST-NEXT: [[TMP0:%.*]] = load i32, ptr @_ZN12LocalStorageIiE5valueE, align 4
// HOST-NEXT: ret i32 [[TMP0]]
//
//
// HOST-LABEL: define {{[^@]+}}@_Z21use_nohost_local_varsv
// HOST-SAME: () #[[ATTR0]] {
// HOST-NEXT: entry:
// HOST-NEXT: [[RESULT:%.*]] = alloca i32, align 4
// HOST-NEXT: [[DOTOFFLOAD_BASEPTRS:%.*]] = alloca [2 x ptr], align 8
// HOST-NEXT: [[DOTOFFLOAD_PTRS:%.*]] = alloca [2 x ptr], align 8
// HOST-NEXT: [[DOTOFFLOAD_MAPPERS:%.*]] = alloca [2 x ptr], align 8
// HOST-NEXT: [[KERNEL_ARGS:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], align 8
// HOST-NEXT: store i32 0, ptr [[RESULT]], align 4
// HOST-NEXT: [[TMP0:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
// HOST-NEXT: store ptr [[RESULT]], ptr [[TMP0]], align 8
// HOST-NEXT: [[TMP1:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
// HOST-NEXT: store ptr [[RESULT]], ptr [[TMP1]], align 8
// HOST-NEXT: [[TMP2:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 0
// HOST-NEXT: store ptr null, ptr [[TMP2]], align 8
// HOST-NEXT: [[TMP3:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
// HOST-NEXT: store ptr null, ptr [[TMP3]], align 8
// HOST-NEXT: [[TMP4:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
// HOST-NEXT: store ptr null, ptr [[TMP4]], align 8
// HOST-NEXT: [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
// HOST-NEXT: store ptr null, ptr [[TMP5]], align 8
// HOST-NEXT: [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
// HOST-NEXT: [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
// HOST-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0
// HOST-NEXT: store i32 5, ptr [[TMP8]], align 4
// HOST-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1
// HOST-NEXT: store i32 2, ptr [[TMP9]], align 4
// HOST-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2
// HOST-NEXT: store ptr [[TMP6]], ptr [[TMP10]], align 8
// HOST-NEXT: [[TMP11:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 3
// HOST-NEXT: store ptr [[TMP7]], ptr [[TMP11]], align 8
// HOST-NEXT: [[TMP12:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 4
// HOST-NEXT: store ptr @.offload_sizes.1, ptr [[TMP12]], align 8
// HOST-NEXT: [[TMP13:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 5
// HOST-NEXT: store ptr @.offload_maptypes.2, ptr [[TMP13]], align 8
// HOST-NEXT: [[TMP14:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 6
// HOST-NEXT: store ptr null, ptr [[TMP14]], align 8
// HOST-NEXT: [[TMP15:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 7
// HOST-NEXT: store ptr null, ptr [[TMP15]], align 8
// HOST-NEXT: [[TMP16:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 8
// HOST-NEXT: store i64 0, ptr [[TMP16]], align 8
// HOST-NEXT: [[TMP17:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 9
// HOST-NEXT: store i64 0, ptr [[TMP17]], align 8
// HOST-NEXT: [[TMP18:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 10
// HOST-NEXT: store [3 x i32] [i32 -1, i32 0, i32 0], ptr [[TMP18]], align 4
// HOST-NEXT: [[TMP19:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 11
// HOST-NEXT: store [3 x i32] zeroinitializer, ptr [[TMP19]], align 4
// HOST-NEXT: [[TMP20:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 12
// HOST-NEXT: store i32 0, ptr [[TMP20]], align 4
// HOST-NEXT: [[TMP21:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1]], i64 -1, i32 -1, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z21use_nohost_local_varsv_l86.region_id, ptr [[KERNEL_ARGS]])
// HOST-NEXT: [[TMP22:%.*]] = icmp ne i32 [[TMP21]], 0
// HOST-NEXT: br i1 [[TMP22]], label [[OMP_OFFLOAD_FAILED:%.*]], label [[OMP_OFFLOAD_CONT:%.*]]
// HOST: omp_offload.failed:
// HOST-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z21use_nohost_local_varsv_l86(ptr [[RESULT]], ptr null) #[[ATTR2]]
// HOST-NEXT: br label [[OMP_OFFLOAD_CONT]]
// HOST: omp_offload.cont:
// HOST-NEXT: [[TMP23:%.*]] = load i32, ptr [[RESULT]], align 4
// HOST-NEXT: ret i32 [[TMP23]]
//
//
// HOST-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z21use_nohost_local_varsv_l86
// HOST-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[RESULT:%.*]], ptr noalias noundef [[DYN_PTR:%.*]]) #[[ATTR1]] {
// HOST-NEXT: entry:
// HOST-NEXT: [[RESULT_ADDR:%.*]] = alloca ptr, align 8
// HOST-NEXT: [[DYN_PTR_ADDR:%.*]] = alloca ptr, align 8
// HOST-NEXT: store ptr [[RESULT]], ptr [[RESULT_ADDR]], align 8
// HOST-NEXT: store ptr [[DYN_PTR]], ptr [[DYN_PTR_ADDR]], align 8
// HOST-NEXT: [[TMP0:%.*]] = load ptr, ptr [[RESULT_ADDR]], align 8, !nonnull [[META8]], !align [[META9]]
// HOST-NEXT: store i32 7, ptr @local_nohost_var, align 4
// HOST-NEXT: [[TMP1:%.*]] = load i32, ptr @local_nohost_var, align 4
// HOST-NEXT: store i32 [[TMP1]], ptr [[TMP0]], align 4
// HOST-NEXT: ret void
//
//
// HOST-LABEL: define {{[^@]+}}@_Z18use_new_local_varsv
// HOST-SAME: () #[[ATTR0]] {
// HOST-NEXT: entry:
// HOST-NEXT: [[RESULT:%.*]] = alloca i32, align 4
// HOST-NEXT: [[DOTOFFLOAD_BASEPTRS:%.*]] = alloca [2 x ptr], align 8
// HOST-NEXT: [[DOTOFFLOAD_PTRS:%.*]] = alloca [2 x ptr], align 8
// HOST-NEXT: [[DOTOFFLOAD_MAPPERS:%.*]] = alloca [2 x ptr], align 8
// HOST-NEXT: [[KERNEL_ARGS:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], align 8
// HOST-NEXT: store i32 0, ptr [[RESULT]], align 4
// HOST-NEXT: [[TMP0:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
// HOST-NEXT: store ptr [[RESULT]], ptr [[TMP0]], align 8
// HOST-NEXT: [[TMP1:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
// HOST-NEXT: store ptr [[RESULT]], ptr [[TMP1]], align 8
// HOST-NEXT: [[TMP2:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 0
// HOST-NEXT: store ptr null, ptr [[TMP2]], align 8
// HOST-NEXT: [[TMP3:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
// HOST-NEXT: store ptr null, ptr [[TMP3]], align 8
// HOST-NEXT: [[TMP4:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
// HOST-NEXT: store ptr null, ptr [[TMP4]], align 8
// HOST-NEXT: [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
// HOST-NEXT: store ptr null, ptr [[TMP5]], align 8
// HOST-NEXT: [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
// HOST-NEXT: [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
// HOST-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0
// HOST-NEXT: store i32 5, ptr [[TMP8]], align 4
// HOST-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1
// HOST-NEXT: store i32 2, ptr [[TMP9]], align 4
// HOST-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2
// HOST-NEXT: store ptr [[TMP6]], ptr [[TMP10]], align 8
// HOST-NEXT: [[TMP11:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 3
// HOST-NEXT: store ptr [[TMP7]], ptr [[TMP11]], align 8
// HOST-NEXT: [[TMP12:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 4
// HOST-NEXT: store ptr @.offload_sizes.3, ptr [[TMP12]], align 8
// HOST-NEXT: [[TMP13:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 5
// HOST-NEXT: store ptr @.offload_maptypes.4, ptr [[TMP13]], align 8
// HOST-NEXT: [[TMP14:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 6
// HOST-NEXT: store ptr null, ptr [[TMP14]], align 8
// HOST-NEXT: [[TMP15:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 7
// HOST-NEXT: store ptr null, ptr [[TMP15]], align 8
// HOST-NEXT: [[TMP16:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 8
// HOST-NEXT: store i64 0, ptr [[TMP16]], align 8
// HOST-NEXT: [[TMP17:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 9
// HOST-NEXT: store i64 0, ptr [[TMP17]], align 8
// HOST-NEXT: [[TMP18:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 10
// HOST-NEXT: store [3 x i32] [i32 -1, i32 0, i32 0], ptr [[TMP18]], align 4
// HOST-NEXT: [[TMP19:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 11
// HOST-NEXT: store [3 x i32] zeroinitializer, ptr [[TMP19]], align 4
// HOST-NEXT: [[TMP20:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 12
// HOST-NEXT: store i32 0, ptr [[TMP20]], align 4
// HOST-NEXT: [[TMP21:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1]], i64 -1, i32 -1, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z18use_new_local_varsv_l99.region_id, ptr [[KERNEL_ARGS]])
// HOST-NEXT: [[TMP22:%.*]] = icmp ne i32 [[TMP21]], 0
// HOST-NEXT: br i1 [[TMP22]], label [[OMP_OFFLOAD_FAILED:%.*]], label [[OMP_OFFLOAD_CONT:%.*]]
// HOST: omp_offload.failed:
// HOST-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z18use_new_local_varsv_l99(ptr [[RESULT]], ptr null) #[[ATTR2]]
// HOST-NEXT: br label [[OMP_OFFLOAD_CONT]]
// HOST: omp_offload.cont:
// HOST-NEXT: [[TMP23:%.*]] = load i32, ptr [[RESULT]], align 4
// HOST-NEXT: ret i32 [[TMP23]]
//
//
// HOST-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z18use_new_local_varsv_l99
// HOST-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[RESULT:%.*]], ptr noalias noundef [[DYN_PTR:%.*]]) #[[ATTR1]] {
// HOST-NEXT: entry:
// HOST-NEXT: [[RESULT_ADDR:%.*]] = alloca ptr, align 8
// HOST-NEXT: [[DYN_PTR_ADDR:%.*]] = alloca ptr, align 8
// HOST-NEXT: store ptr [[RESULT]], ptr [[RESULT_ADDR]], align 8
// HOST-NEXT: store ptr [[DYN_PTR]], ptr [[DYN_PTR_ADDR]], align 8
// HOST-NEXT: [[TMP0:%.*]] = load ptr, ptr [[RESULT_ADDR]], align 8, !nonnull [[META8]], !align [[META9]]
// HOST-NEXT: store i32 55, ptr @_ZN11PlainStruct8s_memberE, align 4
// HOST-NEXT: store i32 77, ptr @local_init_var, align 4
// HOST-NEXT: [[TMP1:%.*]] = load i32, ptr @_ZN11PlainStruct8s_memberE, align 4
// HOST-NEXT: [[TMP2:%.*]] = load i32, ptr @local_init_var, align 4
// HOST-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP1]], [[TMP2]]
// HOST-NEXT: store i32 [[ADD]], ptr [[TMP0]], align 4
// HOST-NEXT: ret void
//
//
// DEVICE-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z14use_local_varsv_l70
// DEVICE-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[RESULT:%.*]], ptr noalias noundef [[DYN_PTR:%.*]]) #[[ATTR0:[0-9]+]] {
// DEVICE-NEXT: entry:
// DEVICE-NEXT: [[RESULT_ADDR:%.*]] = alloca ptr, align 8, addrspace(5)
// DEVICE-NEXT: [[DYN_PTR_ADDR:%.*]] = alloca ptr, align 8, addrspace(5)
// DEVICE-NEXT: [[RESULT_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[RESULT_ADDR]] to ptr
// DEVICE-NEXT: [[DYN_PTR_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[DYN_PTR_ADDR]] to ptr
// DEVICE-NEXT: store ptr [[RESULT]], ptr [[RESULT_ADDR_ASCAST]], align 8
// DEVICE-NEXT: store ptr [[DYN_PTR]], ptr [[DYN_PTR_ADDR_ASCAST]], align 8
// DEVICE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[RESULT_ADDR_ASCAST]], align 8, !nonnull [[META7:![0-9]+]], !align [[META8:![0-9]+]]
// DEVICE-NEXT: [[TMP1:%.*]] = call i32 @__kmpc_target_init(ptr addrspacecast (ptr addrspace(1) @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z14use_local_varsv_l70_kernel_environment to ptr), ptr [[DYN_PTR]])
// DEVICE-NEXT: [[EXEC_USER_CODE:%.*]] = icmp eq i32 [[TMP1]], -1
// DEVICE-NEXT: br i1 [[EXEC_USER_CODE]], label [[USER_CODE_ENTRY:%.*]], label [[WORKER_EXIT:%.*]]
// DEVICE: user_code.entry:
// DEVICE-NEXT: store i32 42, ptr addrspacecast (ptr addrspace(1) @local_scalar to ptr), align 4
// DEVICE-NEXT: store i32 1, ptr addrspacecast (ptr addrspace(1) @local_array to ptr), align 4
// DEVICE-NEXT: store i32 100, ptr addrspacecast (ptr addrspace(1) @_ZN12LocalStorageIiE5valueE to ptr), align 4
// DEVICE-NEXT: [[TMP2:%.*]] = load i32, ptr addrspacecast (ptr addrspace(1) @local_scalar to ptr), align 4
// DEVICE-NEXT: [[TMP3:%.*]] = load i32, ptr addrspacecast (ptr addrspace(1) @local_array to ptr), align 4
// DEVICE-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP2]], [[TMP3]]
// DEVICE-NEXT: [[CALL:%.*]] = call noundef i32 @_Z18read_local_storageIiET_v() #[[ATTR2:[0-9]+]]
// DEVICE-NEXT: [[ADD1:%.*]] = add nsw i32 [[ADD]], [[CALL]]
// DEVICE-NEXT: store i32 [[ADD1]], ptr [[TMP0]], align 4
// DEVICE-NEXT: call void @__kmpc_target_deinit()
// DEVICE-NEXT: ret void
// DEVICE: worker.exit:
// DEVICE-NEXT: ret void
//
//
// DEVICE-LABEL: define {{[^@]+}}@_Z18read_local_storageIiET_v
// DEVICE-SAME: () #[[ATTR1:[0-9]+]] comdat {
// DEVICE-NEXT: entry:
// DEVICE-NEXT: [[TMP0:%.*]] = load i32, ptr addrspacecast (ptr addrspace(1) @_ZN12LocalStorageIiE5valueE to ptr), align 4
// DEVICE-NEXT: ret i32 [[TMP0]]
//
//
// DEVICE-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z21use_nohost_local_varsv_l86
// DEVICE-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[RESULT:%.*]], ptr noalias noundef [[DYN_PTR:%.*]]) #[[ATTR0]] {
// DEVICE-NEXT: entry:
// DEVICE-NEXT: [[RESULT_ADDR:%.*]] = alloca ptr, align 8, addrspace(5)
// DEVICE-NEXT: [[DYN_PTR_ADDR:%.*]] = alloca ptr, align 8, addrspace(5)
// DEVICE-NEXT: [[RESULT_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[RESULT_ADDR]] to ptr
// DEVICE-NEXT: [[DYN_PTR_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[DYN_PTR_ADDR]] to ptr
// DEVICE-NEXT: store ptr [[RESULT]], ptr [[RESULT_ADDR_ASCAST]], align 8
// DEVICE-NEXT: store ptr [[DYN_PTR]], ptr [[DYN_PTR_ADDR_ASCAST]], align 8
// DEVICE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[RESULT_ADDR_ASCAST]], align 8, !nonnull [[META7]], !align [[META8]]
// DEVICE-NEXT: [[TMP1:%.*]] = call i32 @__kmpc_target_init(ptr addrspacecast (ptr addrspace(1) @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z21use_nohost_local_varsv_l86_kernel_environment to ptr), ptr [[DYN_PTR]])
// DEVICE-NEXT: [[EXEC_USER_CODE:%.*]] = icmp eq i32 [[TMP1]], -1
// DEVICE-NEXT: br i1 [[EXEC_USER_CODE]], label [[USER_CODE_ENTRY:%.*]], label [[WORKER_EXIT:%.*]]
// DEVICE: user_code.entry:
// DEVICE-NEXT: store i32 7, ptr addrspacecast (ptr addrspace(1) @local_nohost_var to ptr), align 4
// DEVICE-NEXT: [[TMP2:%.*]] = load i32, ptr addrspacecast (ptr addrspace(1) @local_nohost_var to ptr), align 4
// DEVICE-NEXT: store i32 [[TMP2]], ptr [[TMP0]], align 4
// DEVICE-NEXT: call void @__kmpc_target_deinit()
// DEVICE-NEXT: ret void
// DEVICE: worker.exit:
// DEVICE-NEXT: ret void
//
//
// DEVICE-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z18use_new_local_varsv_l99
// DEVICE-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[RESULT:%.*]], ptr noalias noundef [[DYN_PTR:%.*]]) #[[ATTR0]] {
// DEVICE-NEXT: entry:
// DEVICE-NEXT: [[RESULT_ADDR:%.*]] = alloca ptr, align 8, addrspace(5)
// DEVICE-NEXT: [[DYN_PTR_ADDR:%.*]] = alloca ptr, align 8, addrspace(5)
// DEVICE-NEXT: [[RESULT_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[RESULT_ADDR]] to ptr
// DEVICE-NEXT: [[DYN_PTR_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[DYN_PTR_ADDR]] to ptr
// DEVICE-NEXT: store ptr [[RESULT]], ptr [[RESULT_ADDR_ASCAST]], align 8
// DEVICE-NEXT: store ptr [[DYN_PTR]], ptr [[DYN_PTR_ADDR_ASCAST]], align 8
// DEVICE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[RESULT_ADDR_ASCAST]], align 8, !nonnull [[META7]], !align [[META8]]
// DEVICE-NEXT: [[TMP1:%.*]] = call i32 @__kmpc_target_init(ptr addrspacecast (ptr addrspace(1) @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z18use_new_local_varsv_l99_kernel_environment to ptr), ptr [[DYN_PTR]])
// DEVICE-NEXT: [[EXEC_USER_CODE:%.*]] = icmp eq i32 [[TMP1]], -1
// DEVICE-NEXT: br i1 [[EXEC_USER_CODE]], label [[USER_CODE_ENTRY:%.*]], label [[WORKER_EXIT:%.*]]
// DEVICE: user_code.entry:
// DEVICE-NEXT: store i32 55, ptr addrspacecast (ptr addrspace(1) @_ZN11PlainStruct8s_memberE to ptr), align 4
// DEVICE-NEXT: store i32 77, ptr addrspacecast (ptr addrspace(1) @local_init_var to ptr), align 4
// DEVICE-NEXT: [[TMP2:%.*]] = load i32, ptr addrspacecast (ptr addrspace(1) @_ZN11PlainStruct8s_memberE to ptr), align 4
// DEVICE-NEXT: [[TMP3:%.*]] = load i32, ptr addrspacecast (ptr addrspace(1) @local_init_var to ptr), align 4
// DEVICE-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP2]], [[TMP3]]
// DEVICE-NEXT: store i32 [[ADD]], ptr [[TMP0]], align 4
// DEVICE-NEXT: call void @__kmpc_target_deinit()
// DEVICE-NEXT: ret void
// DEVICE: worker.exit:
// DEVICE-NEXT: ret void
//