| 1 | // RUN: %libomptarget-compilexx-run-and-check-generic |
| 2 | |
| 3 | #include <omp.h> |
| 4 | #include <stdio.h> |
| 5 | |
| 6 | typedef struct { |
| 7 | short x; |
| 8 | int *p; |
| 9 | long y; |
| 10 | } S; |
| 11 | |
| 12 | void f1() { |
| 13 | S s[10], *ps; |
| 14 | ps = &s[0]; |
| 15 | s[0].x = 111; |
| 16 | s[1].x = 222; |
| 17 | s[2].x = 333; |
| 18 | s[3].x = 444; |
| 19 | |
| 20 | #pragma omp target enter data map(to : s) |
| 21 | #pragma omp target enter data map(to : ps, ps->x) |
| 22 | |
| 23 | S **ps_mappedptr = (S **)omp_get_mapped_ptr(&ps, omp_get_default_device()); |
| 24 | short *s0_mappedptr = |
| 25 | (short *)omp_get_mapped_ptr(&s[0].x, omp_get_default_device()); |
| 26 | short *s0_hostaddr = &s[0].x; |
| 27 | |
| 28 | printf(format: "ps_mappedptr %s null\n" , ps_mappedptr == (S **)NULL ? "==" : "!=" ); |
| 29 | printf(format: "s0_mappedptr %s null\n" , s0_mappedptr == (short *)NULL ? "==" : "!=" ); |
| 30 | |
| 31 | // CHECK: ps_mappedptr != null |
| 32 | // CHECK: s0_mappedptr != null |
| 33 | |
| 34 | // ps is predetermined firstprivate, so its address will be different from |
| 35 | // the mapped address for this construct. So, any changes to p within the |
| 36 | // region will not be visible after the construct. |
| 37 | #pragma omp target map(ps->x) map(to : ps_mappedptr, s0_mappedptr, s0_hostaddr) |
| 38 | { |
| 39 | printf(format: "%d %d %d %d\n" , ps->x, ps_mappedptr == &ps, s0_mappedptr == &ps->x, |
| 40 | s0_hostaddr == &ps->x); |
| 41 | // CHECK: 111 0 1 0 |
| 42 | ps++; |
| 43 | } |
| 44 | |
| 45 | // For the remaining constructs, ps is not firstprivate, so its address will |
| 46 | // be the same as the mapped address, and changes to ps will be visible to any |
| 47 | // subsequent regions. |
| 48 | #pragma omp target map(to : ps->x, ps) \ |
| 49 | map(to : ps_mappedptr, s0_mappedptr, s0_hostaddr) |
| 50 | { |
| 51 | printf(format: "%d %d %d %d\n" , ps->x, ps_mappedptr == &ps, s0_mappedptr == &ps->x, |
| 52 | s0_hostaddr == &ps->x); |
| 53 | // EXPECTED: 111 1 1 0 |
| 54 | // CHECK: 111 0 1 0 |
| 55 | ps++; |
| 56 | } |
| 57 | |
| 58 | #pragma omp target map(to : ps, ps->x) \ |
| 59 | map(to : ps_mappedptr, s0_mappedptr, s0_hostaddr) |
| 60 | { |
| 61 | printf(format: "%d %d %d %d\n" , ps->x, ps_mappedptr == &ps, |
| 62 | s0_mappedptr == &ps[-1].x, s0_hostaddr == &ps[-1].x); |
| 63 | // EXPECTED: 222 1 1 0 |
| 64 | // CHECK: 111 0 0 0 |
| 65 | ps++; |
| 66 | } |
| 67 | |
| 68 | #pragma omp target map(present, alloc : ps) \ |
| 69 | map(to : ps_mappedptr, s0_mappedptr, s0_hostaddr) |
| 70 | { |
| 71 | printf(format: "%d %d %d %d\n" , ps->x, ps_mappedptr == &ps, |
| 72 | s0_mappedptr == &ps[-2].x, s0_hostaddr == &ps[-2].x); |
| 73 | // EXPECTED: 333 1 1 0 |
| 74 | // CHECK: 111 1 0 0 |
| 75 | } |
| 76 | |
| 77 | // The following map(from:ps) should not bring back ps, because ps is an |
| 78 | // attached pointer. So, it should still point to the same original |
| 79 | // location, &s[0], on host. |
| 80 | #pragma omp target exit data map(always, from : ps) |
| 81 | printf(format: "%d %d\n" , ps->x, ps == &s[0]); |
| 82 | // CHECK: 111 1 |
| 83 | |
| 84 | #pragma omp target exit data map(delete : ps, s) |
| 85 | } |
| 86 | |
| 87 | int main() { f1(); } |
| 88 | |