| // RUN: %clang_cc1 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s |
| // RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s |
| // RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s |
| // expected-no-diagnostics |
| |
| #ifndef HEADER |
| #define HEADER |
| |
| /// ======================================================================== |
| /// Test: Firstprivate pointer handling in OpenMP target regions |
| /// ======================================================================== |
| /// |
| /// This test verifies that pointers with firstprivate semantics get the |
| /// OMP_MAP_LITERAL flag, enabling the runtime to pass pointer values directly |
| /// without performing present table lookups. |
| /// |
| /// Map type values: |
| /// 288 = OMP_MAP_TARGET_PARAM (32) + OMP_MAP_LITERAL (256) |
| /// Used for explicit firstprivate(ptr) |
| /// |
| /// 800 = OMP_MAP_TARGET_PARAM (32) + OMP_MAP_LITERAL (256) + OMP_MAP_IS_PTR (512) |
| /// Used for implicit firstprivate pointers (e.g., from defaultmap clauses) |
| /// Note: 512 is OMP_MAP_IS_PTR, not IMPLICIT. Implicitness is tracked separately. |
| /// |
| /// 544 = OMP_MAP_TARGET_PARAM (32) + OMP_MAP_IS_PTR (512) |
| /// Incorrect behavior - missing LITERAL flag, causes runtime present table lookup |
| /// |
| |
| ///========================================================================== |
| /// Test 1: Explicit firstprivate(pointer) → map type 288 |
| ///========================================================================== |
| |
| // CHECK-DAG: @.offload_maptypes{{[^.]*}} = private unnamed_addr constant [1 x i64] [i64 288] |
| // CHECK-DAG: @.offload_sizes{{[^.]*}} = private unnamed_addr constant [1 x i64] zeroinitializer |
| |
| void test1_explicit_firstprivate() { |
| double *ptr = nullptr; |
| |
| // Explicit firstprivate should generate map type 288 |
| // (TARGET_PARAM | LITERAL, no IS_PTR flag for explicit clauses) |
| #pragma omp target firstprivate(ptr) |
| { |
| if (ptr) ptr[0] = 1.0; |
| } |
| } |
| |
| ///========================================================================== |
| /// Test 2: defaultmap(firstprivate:pointer) → map type 800 |
| ///========================================================================== |
| |
| // CHECK-DAG: @.offload_maptypes{{.*}} = private unnamed_addr constant [1 x i64] [i64 800] |
| // CHECK-DAG: @.offload_sizes{{.*}} = private unnamed_addr constant [1 x i64] zeroinitializer |
| |
| void test2_defaultmap_firstprivate_pointer() { |
| double *ptr = nullptr; |
| |
| // defaultmap(firstprivate:pointer) creates implicit firstprivate |
| // Should generate map type 800 (TARGET_PARAM | LITERAL | IS_PTR) |
| #pragma omp target defaultmap(firstprivate:pointer) |
| { |
| if (ptr) ptr[0] = 2.0; |
| } |
| } |
| |
| ///========================================================================== |
| /// Test 3: defaultmap(firstprivate:scalar) with double → map type 800 |
| ///========================================================================== |
| |
| // CHECK-DAG: @.offload_maptypes{{.*}} = private unnamed_addr constant [1 x i64] [i64 800] |
| |
| void test3_defaultmap_scalar_double() { |
| double d = 3.0; |
| |
| // OpenMP's "scalar" category excludes pointers but includes arithmetic types |
| // Double gets implicit firstprivate → map type 800 |
| #pragma omp target defaultmap(firstprivate:scalar) |
| { |
| d += 1.0; |
| } |
| } |
| |
| ///========================================================================== |
| /// Test 4: Pointer with defaultmap(firstprivate:scalar) → map type 800 |
| ///========================================================================== |
| |
| // CHECK-DAG: @.offload_maptypes{{.*}} = private unnamed_addr constant [1 x i64] [i64 800] |
| // CHECK-DAG: @.offload_sizes{{.*}} = private unnamed_addr constant [1 x i64] zeroinitializer |
| |
| void test4_pointer_with_scalar_defaultmap() { |
| double *ptr = nullptr; |
| |
| // Note: defaultmap(firstprivate:scalar) does NOT apply to pointers (scalar excludes pointers). |
| // However, the pointer still gets 800 because in OpenMP 5.0+, pointers without explicit |
| // data-sharing attributes are implicitly firstprivate and lowered as IS_PTR|LITERAL|TARGET_PARAM. |
| // This is the default pointer behavior, NOT due to the scalar defaultmap. |
| #pragma omp target defaultmap(firstprivate:scalar) |
| { |
| if (ptr) ptr[0] = 4.0; |
| } |
| } |
| |
| ///========================================================================== |
| /// Test 5: Multiple pointers with explicit firstprivate → all get 288 |
| ///========================================================================== |
| |
| // CHECK-DAG: @.offload_maptypes{{.*}} = private unnamed_addr constant [3 x i64] [i64 288, i64 288, i64 288] |
| // CHECK-DAG: @.offload_sizes{{.*}} = private unnamed_addr constant [3 x i64] zeroinitializer |
| |
| void test5_multiple_firstprivate() { |
| int *a = nullptr; |
| float *b = nullptr; |
| double *c = nullptr; |
| |
| // All explicit firstprivate pointers get map type 288 |
| #pragma omp target firstprivate(a, b, c) |
| { |
| if (a) a[0] = 6; |
| if (b) b[0] = 7.0f; |
| if (c) c[0] = 8.0; |
| } |
| } |
| |
| ///========================================================================== |
| /// Test 6: Pointer to const with firstprivate → map type 288 |
| ///========================================================================== |
| |
| // CHECK-DAG: @.offload_maptypes{{.*}} = private unnamed_addr constant [1 x i64] [i64 288] |
| // CHECK-DAG: @.offload_sizes{{.*}} = private unnamed_addr constant [1 x i64] zeroinitializer |
| |
| void test6_const_pointer() { |
| const double *const_ptr = nullptr; |
| |
| // Const pointer with explicit firstprivate → 288 |
| #pragma omp target firstprivate(const_ptr) |
| { |
| if (const_ptr) { |
| double val = const_ptr[0]; |
| (void)val; |
| } |
| } |
| } |
| |
| ///========================================================================== |
| /// Test 7: Pointer-to-pointer with firstprivate → map type 288 |
| ///========================================================================== |
| |
| // CHECK-DAG: @.offload_maptypes{{.*}} = private unnamed_addr constant [1 x i64] [i64 288] |
| // CHECK-DAG: @.offload_sizes{{.*}} = private unnamed_addr constant [1 x i64] zeroinitializer |
| |
| void test7_pointer_to_pointer() { |
| int **pp = nullptr; |
| |
| // Pointer-to-pointer with explicit firstprivate → 288 |
| #pragma omp target firstprivate(pp) |
| { |
| if (pp && *pp) (*pp)[0] = 9; |
| } |
| } |
| |
| ///========================================================================== |
| /// Verification: The key fix is that firstprivate pointers now include |
| /// the LITERAL flag (256), which tells the runtime to pass the pointer |
| /// value directly instead of performing a present table lookup. |
| /// |
| /// Before fix: Pointers got 544 (TARGET_PARAM | IS_PTR) → runtime lookup |
| /// After fix: Pointers get 288 or 800 (includes LITERAL) → direct pass |
| ///========================================================================== |
| |
| #endif // HEADER |