1 // RUN: %libomptarget-compile-generic -fopenmp-extensions
2 // RUN: %libomptarget-run-generic | %fcheck-generic -strict-whitespace
7 #pragma omp begin declare target
8 #define MAX_NAME_SIZE 100
9 char N1
[MAX_NAME_SIZE
], N2
[MAX_NAME_SIZE
];
11 void copy_name(char *dst
, char *src
) {
13 for (i
= 0; i
< MAX_NAME_SIZE
- 1 && src
[i
]; ++i
)
17 #pragma omp end declare target
19 #define CHECK_PRESENCE(Var1, Var2, Var3) \
20 printf(" presence of %s, %s, %s: %d, %d, %d\n", #Var1, #Var2, #Var3, \
21 omp_target_is_present(&(Var1), omp_get_default_device()), \
22 omp_target_is_present(&(Var2), omp_get_default_device()), \
23 omp_target_is_present(&(Var3), omp_get_default_device()))
25 #define CHECK_VALUES_HELPER(N1, N2, Var1, Var2) \
26 printf(" values of %s, %s: %d, %d\n", N1, N2, (Var1), (Var2))
28 #define CHECK_VALUES_DELAYED(Var1, Var2) \
29 copy_name(N1, #Var1); \
30 copy_name(N2, #Var2); \
34 #define CHECK_DELAYED_VALUES() \
35 _Pragma("omp target update from(N1, N2, V1, V2)") \
36 CHECK_VALUES_HELPER(N1, N2, V1, V2)
38 #define CHECK_VALUES(Var1, Var2) \
39 CHECK_VALUES_HELPER(#Var1, #Var2, (Var1), (Var2))
46 // CHECK: presence of s, s.i, s.j: 0, 0, 0
47 CHECK_PRESENCE(s
, s
.i
, s
.j
);
49 // =======================================================================
50 // Check that ompx_hold keeps entire struct present.
52 // -----------------------------------------------------------------------
53 // CHECK-LABEL: check:{{.*}}
54 printf("check: ompx_hold only on first member\n");
57 #pragma omp target data map(tofrom : s) map(ompx_hold, tofrom : s.i) \
60 // CHECK-NEXT: presence of s, s.i, s.j: 1, 1, 1
61 CHECK_PRESENCE(s
, s
.i
, s
.j
);
62 #pragma omp target map(tofrom : s)
67 #pragma omp target exit data map(delete : s, s.i)
68 // ompx_hold on s.i applies to all of s.
69 // CHECK-NEXT: presence of s, s.i, s.j: 1, 1, 1
70 // CHECK-NEXT: values of s.i, s.j: 20, 30
71 CHECK_PRESENCE(s
, s
.i
, s
.j
);
72 CHECK_VALUES(s
.i
, s
.j
);
74 // CHECK-NEXT: presence of s, s.i, s.j: 0, 0, 0
75 // CHECK-NEXT: values of s.i, s.j: 21, 31
76 CHECK_PRESENCE(s
, s
.i
, s
.j
);
77 CHECK_VALUES(s
.i
, s
.j
);
79 // -----------------------------------------------------------------------
80 // CHECK-LABEL: check:{{.*}}
81 printf("check: ompx_hold only on last member\n");
84 #pragma omp target data map(tofrom : s) map(tofrom : s.i) \
85 map(ompx_hold, tofrom : s.j)
87 // CHECK-NEXT: presence of s, s.i, s.j: 1, 1, 1
88 CHECK_PRESENCE(s
, s
.i
, s
.j
);
89 #pragma omp target map(tofrom : s)
94 #pragma omp target exit data map(delete : s, s.i)
95 // ompx_hold on s.j applies to all of s.
96 // CHECK-NEXT: presence of s, s.i, s.j: 1, 1, 1
97 // CHECK-NEXT: values of s.i, s.j: 20, 30
98 CHECK_PRESENCE(s
, s
.i
, s
.j
);
99 CHECK_VALUES(s
.i
, s
.j
);
101 // CHECK-NEXT: presence of s, s.i, s.j: 0, 0, 0
102 // CHECK-NEXT: values of s.i, s.j: 21, 31
103 CHECK_PRESENCE(s
, s
.i
, s
.j
);
104 CHECK_VALUES(s
.i
, s
.j
);
106 // -----------------------------------------------------------------------
107 // CHECK-LABEL: check:{{.*}}
108 printf("check: ompx_hold only on struct\n");
111 #pragma omp target data map(ompx_hold, tofrom : s) map(tofrom : s.i) \
114 // CHECK-NEXT: presence of s, s.i, s.j: 1, 1, 1
115 CHECK_PRESENCE(s
, s
.i
, s
.j
);
116 #pragma omp target map(tofrom : s)
121 #pragma omp target exit data map(delete : s, s.i)
122 // CHECK-NEXT: presence of s, s.i, s.j: 1, 1, 1
123 // CHECK-NEXT: values of s.i, s.j: 20, 30
124 CHECK_PRESENCE(s
, s
.i
, s
.j
);
125 CHECK_VALUES(s
.i
, s
.j
);
127 // CHECK-NEXT: presence of s, s.i, s.j: 0, 0, 0
128 // CHECK-NEXT: values of s.i, s.j: 21, 31
129 CHECK_PRESENCE(s
, s
.i
, s
.j
);
130 CHECK_VALUES(s
.i
, s
.j
);
132 // =======================================================================
133 // Check that transfer to/from host checks reference count correctly.
135 // -----------------------------------------------------------------------
136 // CHECK-LABEL: check:{{.*}}
137 printf("check: parent DynRefCount=1 is not sufficient for transfer\n");
140 #pragma omp target data map(ompx_hold, tofrom : s)
141 #pragma omp target data map(ompx_hold, tofrom : s)
143 // CHECK-NEXT: presence of s, s.i, s.j: 1, 1, 1
144 CHECK_PRESENCE(s
, s
.i
, s
.j
);
145 #pragma omp target map(from : s.i, s.j)
149 } // No transfer here even though parent's DynRefCount=1.
150 // CHECK-NEXT: presence of s, s.i, s.j: 1, 1, 1
151 // CHECK-NEXT: values of s.i, s.j: 20, 30
152 CHECK_PRESENCE(s
, s
.i
, s
.j
);
153 CHECK_VALUES(s
.i
, s
.j
);
154 #pragma omp target map(to : s.i, s.j)
155 { // No transfer here even though parent's DynRefCount=1.
156 // CHECK-NEXT: values of s.i, s.j: 21, 31
157 CHECK_VALUES_DELAYED(s
.i
, s
.j
);
159 CHECK_DELAYED_VALUES();
161 // CHECK-NEXT: presence of s, s.i, s.j: 0, 0, 0
162 // CHECK-NEXT: values of s.i, s.j: 21, 31
163 CHECK_PRESENCE(s
, s
.i
, s
.j
);
164 CHECK_VALUES(s
.i
, s
.j
);
166 // -----------------------------------------------------------------------
167 // CHECK-LABEL: check:{{.*}}
168 printf("check: parent HoldRefCount=1 is not sufficient for transfer\n");
171 #pragma omp target data map(tofrom : s)
172 #pragma omp target data map(tofrom : s)
174 // CHECK-NEXT: presence of s, s.i, s.j: 1, 1, 1
175 CHECK_PRESENCE(s
, s
.i
, s
.j
);
176 #pragma omp target map(ompx_hold, from : s.i, s.j)
180 } // No transfer here even though parent's HoldRefCount=1.
181 // CHECK-NEXT: presence of s, s.i, s.j: 1, 1, 1
182 // CHECK-NEXT: values of s.i, s.j: 20, 30
183 CHECK_PRESENCE(s
, s
.i
, s
.j
);
184 CHECK_VALUES(s
.i
, s
.j
);
185 #pragma omp target map(ompx_hold, to : s.i, s.j)
186 { // No transfer here even though parent's HoldRefCount=1.
187 // CHECK-NEXT: values of s.i, s.j: 21, 31
188 CHECK_VALUES_DELAYED(s
.i
, s
.j
);
190 CHECK_DELAYED_VALUES();
192 // CHECK-NEXT: presence of s, s.i, s.j: 0, 0, 0
193 // CHECK-NEXT: values of s.i, s.j: 21, 31
194 CHECK_PRESENCE(s
, s
.i
, s
.j
);
195 CHECK_VALUES(s
.i
, s
.j
);
197 // -----------------------------------------------------------------------
198 // CHECK-LABEL: check:{{.*}}
200 // At the beginning of a region, if the parent's TotalRefCount=1, then the
201 // transfer should happen.
203 // At the end of a region, it also must be true that the reference count being
204 // decremented is the reference count that is 1.
205 printf("check: parent TotalRefCount=1 is not sufficient for transfer\n");
208 #pragma omp target data map(ompx_hold, tofrom : s)
210 // CHECK-NEXT: presence of s, s.i, s.j: 1, 1, 1
211 CHECK_PRESENCE(s
, s
.i
, s
.j
);
212 #pragma omp target map(ompx_hold, tofrom : s.i, s.j)
217 #pragma omp target exit data map(from : s.i, s.j)
218 // No transfer here even though parent's TotalRefCount=1.
219 // CHECK-NEXT: presence of s, s.i, s.j: 1, 1, 1
220 // CHECK-NEXT: values of s.i, s.j: 20, 30
221 CHECK_PRESENCE(s
, s
.i
, s
.j
);
222 CHECK_VALUES(s
.i
, s
.j
);
224 // CHECK-NEXT: presence of s, s.i, s.j: 0, 0, 0
225 // CHECK-NEXT: values of s.i, s.j: 21, 31
226 CHECK_PRESENCE(s
, s
.i
, s
.j
);
227 CHECK_VALUES(s
.i
, s
.j
);