blob: abc99e5e770ce85594b13ec25e82081e4bc18fcc [file] [edit]
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fopenmp \
// RUN: -fopenmp-targets=amdgpu-amd-amdhsa -fclangir -emit-llvm %s -o - \
// RUN: | FileCheck %s --check-prefix=LLVM
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fopenmp \
// RUN: -fopenmp-targets=amdgpu-amd-amdhsa -emit-llvm %s -o - \
// RUN: | FileCheck %s --check-prefix=OGCG
void use(int);
void target_map_to(int x) {
#pragma omp target map(to : x)
{
use(x);
}
}
void target_map_from(int x) {
#pragma omp target map(from : x)
{
x = 42;
}
}
void target_map_tofrom(int x) {
#pragma omp target map(tofrom : x)
{
x = x + 1;
}
}
void target_map_multiple(int a, int b) {
#pragma omp target map(to : a) map(from : b)
{
b = a;
}
}
// Host wrappers
//
// LLVM-LABEL: define {{.*}} void @target_map_to(
// LLVM-SAME: i32 noundef %[[ARG:[^,)]+]]
// LLVM: %[[X_ADDR:.*]] = alloca i32, i64 1, align 4
// LLVM: store i32 %[[ARG]], ptr %[[X_ADDR]], align 4
// LLVM: %[[BP:.*]] = getelementptr inbounds [2 x ptr], ptr %.offload_baseptrs, i32 0, i32 0
// LLVM: store ptr %[[X_ADDR]], ptr %[[BP]], align 8
// LLVM: %[[P:.*]] = getelementptr inbounds [2 x ptr], ptr %.offload_ptrs, i32 0, i32 0
// LLVM: store ptr %[[X_ADDR]], ptr %[[P]], align 8
// LLVM: call i32 @__tgt_target_kernel(
// LLVM: omp_offload.failed:
// LLVM: call void @__omp_offloading_{{.*}}_target_map_to_l{{.*}}(ptr %[[X_ADDR]], ptr null)
// LLVM-LABEL: define {{.*}} void @target_map_from(
// LLVM-SAME: i32 noundef %[[ARG:[^,)]+]]
// LLVM: %[[X_ADDR:.*]] = alloca i32, i64 1, align 4
// LLVM: store i32 %[[ARG]], ptr %[[X_ADDR]], align 4
// LLVM: %[[BP:.*]] = getelementptr inbounds [2 x ptr], ptr %.offload_baseptrs, i32 0, i32 0
// LLVM: store ptr %[[X_ADDR]], ptr %[[BP]], align 8
// LLVM: %[[P:.*]] = getelementptr inbounds [2 x ptr], ptr %.offload_ptrs, i32 0, i32 0
// LLVM: store ptr %[[X_ADDR]], ptr %[[P]], align 8
// LLVM: call i32 @__tgt_target_kernel(
// LLVM: omp_offload.failed:
// LLVM: call void @__omp_offloading_{{.*}}_target_map_from_l{{.*}}(ptr %[[X_ADDR]], ptr null)
// LLVM-LABEL: define {{.*}} void @target_map_tofrom(
// LLVM-SAME: i32 noundef %[[ARG:[^,)]+]]
// LLVM: %[[X_ADDR:.*]] = alloca i32, i64 1, align 4
// LLVM: store i32 %[[ARG]], ptr %[[X_ADDR]], align 4
// LLVM: %[[BP:.*]] = getelementptr inbounds [2 x ptr], ptr %.offload_baseptrs, i32 0, i32 0
// LLVM: store ptr %[[X_ADDR]], ptr %[[BP]], align 8
// LLVM: %[[P:.*]] = getelementptr inbounds [2 x ptr], ptr %.offload_ptrs, i32 0, i32 0
// LLVM: store ptr %[[X_ADDR]], ptr %[[P]], align 8
// LLVM: call i32 @__tgt_target_kernel(
// LLVM: omp_offload.failed:
// LLVM: call void @__omp_offloading_{{.*}}_target_map_tofrom_l{{.*}}(ptr %[[X_ADDR]], ptr null)
// LLVM-LABEL: define {{.*}} void @target_map_multiple(
// LLVM-SAME: i32 noundef %[[ARG_A:[^,)]+]], i32 noundef %[[ARG_B:[^,)]+]]
// LLVM: %[[A_ADDR:.*]] = alloca i32, i64 1, align 4
// LLVM: %[[B_ADDR:.*]] = alloca i32, i64 1, align 4
// LLVM: store i32 %[[ARG_A]], ptr %[[A_ADDR]], align 4
// LLVM: store i32 %[[ARG_B]], ptr %[[B_ADDR]], align 4
// LLVM: %[[BP_A:.*]] = getelementptr inbounds [3 x ptr], ptr %.offload_baseptrs, i32 0, i32 0
// LLVM: store ptr %[[A_ADDR]], ptr %[[BP_A]], align 8
// LLVM: %[[P_A:.*]] = getelementptr inbounds [3 x ptr], ptr %.offload_ptrs, i32 0, i32 0
// LLVM: store ptr %[[A_ADDR]], ptr %[[P_A]], align 8
// LLVM: %[[BP_B:.*]] = getelementptr inbounds [3 x ptr], ptr %.offload_baseptrs, i32 0, i32 1
// LLVM: store ptr %[[B_ADDR]], ptr %[[BP_B]], align 8
// LLVM: %[[P_B:.*]] = getelementptr inbounds [3 x ptr], ptr %.offload_ptrs, i32 0, i32 1
// LLVM: store ptr %[[B_ADDR]], ptr %[[P_B]], align 8
// LLVM: call i32 @__tgt_target_kernel(
// LLVM: omp_offload.failed:
// LLVM: call void @__omp_offloading_{{.*}}_target_map_multiple_l{{.*}}(ptr %[[A_ADDR]], ptr %[[B_ADDR]], ptr null)
// Outlined target functions
//
// The mapped pointer arrives as the first function argument; load/store the
// user value directly through it.
// LLVM-LABEL: define internal void @__omp_offloading_{{.*}}_target_map_to_l
// LLVM-SAME: (ptr %[[ARG:[^,]+]], ptr
// LLVM: %[[V:.*]] = load i32, ptr %[[ARG]], align 4
// LLVM: call void @use(i32 {{.*}} %[[V]])
// LLVM: ret void
// LLVM-LABEL: define internal void @__omp_offloading_{{.*}}_target_map_from_l
// LLVM-SAME: (ptr %[[ARG:[^,]+]], ptr
// LLVM: store i32 42, ptr %[[ARG]], align 4
// LLVM: ret void
// LLVM-LABEL: define internal void @__omp_offloading_{{.*}}_target_map_tofrom_l
// LLVM-SAME: (ptr %[[ARG:[^,]+]], ptr
// LLVM: %[[LD:.*]] = load i32, ptr %[[ARG]], align 4
// LLVM: %[[ADD:.*]] = add nsw i32 %[[LD]], 1
// LLVM: store i32 %[[ADD]], ptr %[[ARG]], align 4
// LLVM: ret void
// LLVM-LABEL: define internal void @__omp_offloading_{{.*}}_target_map_multiple_l
// LLVM-SAME: (ptr %[[ARG_A:[^,]+]], ptr %[[ARG_B:[^,]+]], ptr
// LLVM: %[[A:.*]] = load i32, ptr %[[ARG_A]], align 4
// LLVM: store i32 %[[A]], ptr %[[ARG_B]], align 4
// LLVM: ret void
// OGCG interleaves host wrapper and outlined function per target region.
// OGCG-LABEL: define {{.*}} void @target_map_to(i32
// OGCG: call i32 @__tgt_target_kernel(
// OGCG: omp_offload.failed:
// OGCG: call void @__omp_offloading_{{.*}}_target_map_to_l
// OGCG-LABEL: define internal void @__omp_offloading_{{.*}}_target_map_to_l
// OGCG: %[[V:.*]] = load i32, ptr %{{.*}}, align 4
// OGCG: call void @use(i32 {{.*}} %[[V]])
// OGCG: ret void
// OGCG-LABEL: define {{.*}} void @target_map_from(i32
// OGCG: call i32 @__tgt_target_kernel(
// OGCG: omp_offload.failed:
// OGCG: call void @__omp_offloading_{{.*}}_target_map_from_l
// OGCG-LABEL: define internal void @__omp_offloading_{{.*}}_target_map_from_l
// OGCG: store i32 42, ptr %{{.*}}, align 4
// OGCG: ret void
// OGCG-LABEL: define {{.*}} void @target_map_tofrom(i32
// OGCG: call i32 @__tgt_target_kernel(
// OGCG: omp_offload.failed:
// OGCG: call void @__omp_offloading_{{.*}}_target_map_tofrom_l
// OGCG-LABEL: define internal void @__omp_offloading_{{.*}}_target_map_tofrom_l
// OGCG: %[[LD:.*]] = load i32, ptr %{{.*}}, align 4
// OGCG: %[[ADD:.*]] = add nsw i32 %[[LD]], 1
// OGCG: store i32 %[[ADD]], ptr %{{.*}}, align 4
// OGCG: ret void
// OGCG-LABEL: define {{.*}} void @target_map_multiple(i32
// OGCG: call i32 @__tgt_target_kernel(
// OGCG: omp_offload.failed:
// OGCG: call void @__omp_offloading_{{.*}}_target_map_multiple_l
// OGCG-LABEL: define internal void @__omp_offloading_{{.*}}_target_map_multiple_l
// OGCG: %[[A:.*]] = load i32, ptr %{{.*}}, align 4
// OGCG: store i32 %[[A]], ptr %{{.*}}, align 4
// OGCG: ret void