xref: /llvm-project/clang/test/OpenMP/atomic_read_codegen.c (revision 94473f4db6a6f5f12d7c4081455b5b596094eac5)
1 // RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -target-cpu core2 -fopenmp -x c -emit-llvm %s -o - | FileCheck %s
2 // RUN: %clang_cc1 -fopenmp -x c -triple x86_64-apple-darwin10 -target-cpu core2 -emit-pch -o %t %s
3 // RUN: %clang_cc1 -fopenmp -x c -triple x86_64-apple-darwin10 -target-cpu core2 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
4 
5 // RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -target-cpu core2 -fopenmp-simd -x c -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
6 // RUN: %clang_cc1 -fopenmp-simd -x c -triple x86_64-apple-darwin10 -target-cpu core2 -emit-pch -o %t %s
7 // RUN: %clang_cc1 -fopenmp-simd -x c -triple x86_64-apple-darwin10 -target-cpu core2 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
8 // SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
9 // expected-no-diagnostics
10 // REQUIRES: x86-registered-target
11 #ifndef HEADER
12 #define HEADER
13 
14 _Bool bv, bx;
15 char cv, cx;
16 unsigned char ucv, ucx;
17 short sv, sx;
18 unsigned short usv, usx;
19 int iv, ix;
20 unsigned int uiv, uix;
21 long lv, lx;
22 unsigned long ulv, ulx;
23 long long llv, llx;
24 unsigned long long ullv, ullx;
25 float fv, fx;
26 double dv, dx;
27 long double ldv, ldx;
28 _Complex int civ, cix;
29 _Complex float cfv, cfx;
30 _Complex double cdv, cdx;
31 
32 typedef int int4 __attribute__((__vector_size__(16)));
33 int4 int4x;
34 
35 struct BitFields {
36   int : 32;
37   int a : 31;
38 } bfx;
39 
40 struct BitFields_packed {
41   int : 32;
42   int a : 31;
43 } __attribute__ ((__packed__)) bfx_packed;
44 
45 struct BitFields2 {
46   int : 31;
47   int a : 1;
48 } bfx2;
49 
50 struct BitFields2_packed {
51   int : 31;
52   int a : 1;
53 } __attribute__ ((__packed__)) bfx2_packed;
54 
55 struct BitFields3 {
56   int : 11;
57   int a : 14;
58 } bfx3;
59 
60 struct BitFields3_packed {
61   int : 11;
62   int a : 14;
63 } __attribute__ ((__packed__)) bfx3_packed;
64 
65 struct BitFields4 {
66   short : 16;
67   int a: 1;
68   long b : 7;
69 } bfx4;
70 
71 struct BitFields4_packed {
72   short : 16;
73   int a: 1;
74   long b : 7;
75 } __attribute__ ((__packed__)) bfx4_packed;
76 
77 typedef float float2 __attribute__((ext_vector_type(2)));
78 float2 float2x;
79 
80 // Register "0" is currently an invalid register for global register variables.
81 // Use "esp" instead of "0".
82 // register int rix __asm__("0");
83 register int rix __asm__("esp");
84 
85 // CHECK-LABEL: @main(
86 int main(void) {
87 // CHECK: load atomic i8, ptr {{.*}} monotonic, align 1
88 // CHECK: store i8
89 #pragma omp atomic read
90   bv = bx;
91 // CHECK: load atomic i8, ptr {{.*}} monotonic, align 1
92 // CHECK: store i8
93 #pragma omp atomic read
94   cv = cx;
95 // CHECK: load atomic i8, ptr {{.*}} monotonic, align 1
96 // CHECK: store i8
97 #pragma omp atomic read
98   ucv = ucx;
99 // CHECK: load atomic i16, ptr {{.*}} monotonic, align 2
100 // CHECK: store i16
101 #pragma omp atomic read
102   sv = sx;
103 // CHECK: load atomic i16, ptr {{.*}} monotonic, align 2
104 // CHECK: store i16
105 #pragma omp atomic read
106   usv = usx;
107 // CHECK: load atomic i32, ptr {{.*}} monotonic, align 4
108 // CHECK: store i32
109 #pragma omp atomic read
110   iv = ix;
111 // CHECK: load atomic i32, ptr {{.*}} monotonic, align 4
112 // CHECK: store i32
113 #pragma omp atomic read
114   uiv = uix;
115 // CHECK: load atomic i64, ptr {{.*}} monotonic, align 8
116 // CHECK: store i64
117 #pragma omp atomic read
118   lv = lx;
119 // CHECK: load atomic i64, ptr {{.*}} monotonic, align 8
120 // CHECK: store i64
121 #pragma omp atomic read
122   ulv = ulx;
123 // CHECK: load atomic i64, ptr {{.*}} monotonic, align 8
124 // CHECK: store i64
125 #pragma omp atomic read
126   llv = llx;
127 // CHECK: load atomic i64, ptr {{.*}} monotonic, align 8
128 // CHECK: store i64
129 #pragma omp atomic read
130   ullv = ullx;
131 // CHECK: load atomic float, ptr {{.*}} monotonic, align 4
132 // CHECK: store float
133 #pragma omp atomic read
134   fv = fx;
135 // CHECK: load atomic double, ptr {{.*}} monotonic, align 8
136 // CHECK: store double
137 #pragma omp atomic read
138   dv = dx;
139 // CHECK: [[LD:%.+]] = load atomic i128, ptr {{.*}} monotonic, align 16
140 // CHECK: store i128 [[LD]], ptr [[LDTEMP:%.+]]
141 // CHECK: [[LD:%.+]] = load x86_fp80, ptr [[LDTEMP]]
142 // CHECK: store x86_fp80 [[LD]]
143 #pragma omp atomic read
144   ldv = ldx;
145 // CHECK: call{{.*}} void @__atomic_load(i64 noundef 8,
146 // CHECK: store i32
147 // CHECK: store i32
148 #pragma omp atomic read
149   civ = cix;
150 // CHECK: call{{.*}} void @__atomic_load(i64 noundef 8,
151 // CHECK: store float
152 // CHECK: store float
153 #pragma omp atomic read
154   cfv = cfx;
155 // CHECK: call{{.*}} void @__atomic_load(i64 noundef 16,
156 // CHECK: call{{.*}} @__kmpc_flush(
157 // CHECK: store double
158 // CHECK: store double
159 #pragma omp atomic seq_cst read
160   cdv = cdx;
161 // CHECK: load atomic i64, ptr {{.*}} monotonic, align 8
162 // CHECK: store i8
163 #pragma omp atomic read
164   bv = ulx;
165 // CHECK: load atomic i8, ptr {{.*}} monotonic, align 1
166 // CHECK: store i8
167 #pragma omp atomic read
168   cv = bx;
169 // CHECK: load atomic i8, ptr {{.*}} seq_cst, align 1
170 // CHECK: call{{.*}} @__kmpc_flush(
171 // CHECK: store i8
172 #pragma omp atomic read seq_cst
173   ucv = cx;
174 // CHECK: load atomic i64, ptr {{.*}} monotonic, align 8
175 // CHECK: store i16
176 #pragma omp atomic read
177   sv = ulx;
178 // CHECK: load atomic i64, ptr {{.*}} monotonic, align 8
179 // CHECK: store i16
180 #pragma omp atomic read
181   usv = lx;
182 // CHECK: load atomic i32, ptr {{.*}} seq_cst, align 4
183 // CHECK: call{{.*}} @__kmpc_flush(
184 // CHECK: store i32
185 #pragma omp atomic seq_cst, read
186   iv = uix;
187 // CHECK: load atomic i32, ptr {{.*}} monotonic, align 4
188 // CHECK: store i32
189 #pragma omp atomic read
190   uiv = ix;
191 // CHECK: call{{.*}} void @__atomic_load(i64 noundef 8,
192 // CHECK: store i64
193 #pragma omp atomic read
194   lv = cix;
195 // CHECK: load atomic float, ptr {{.*}} monotonic, align 4
196 // CHECK: store i64
197 #pragma omp atomic read
198   ulv = fx;
199 // CHECK: load atomic double, ptr {{.*}} monotonic, align 8
200 // CHECK: store i64
201 #pragma omp atomic read
202   llv = dx;
203 // CHECK: load atomic i128, ptr {{.*}} monotonic, align 16
204 // CHECK: store i64
205 #pragma omp atomic read
206   ullv = ldx;
207 // CHECK: call{{.*}} void @__atomic_load(i64 noundef 8,
208 // CHECK: store float
209 #pragma omp atomic read
210   fv = cix;
211 // CHECK: load atomic i16, ptr {{.*}} monotonic, align 2
212 // CHECK: store double
213 #pragma omp atomic read
214   dv = sx;
215 // CHECK: load atomic i8, ptr {{.*}} monotonic, align 1
216 // CHECK: store x86_fp80
217 #pragma omp atomic read
218   ldv = bx;
219 // CHECK: load atomic i8, ptr {{.*}} monotonic, align 1
220 // CHECK: store i32
221 // CHECK: store i32
222 #pragma omp atomic read
223   civ = bx;
224 // CHECK: load atomic i16, ptr {{.*}} monotonic, align 2
225 // CHECK: store float
226 // CHECK: store float
227 #pragma omp atomic read
228   cfv = usx;
229 // CHECK: load atomic i64, ptr {{.*}} monotonic, align 8
230 // CHECK: store double
231 // CHECK: store double
232 #pragma omp atomic read
233   cdv = llx;
234 // CHECK: [[I128VAL:%.+]] = load atomic i128, ptr @{{.+}} monotonic, align 16
235 // CHECK: store i128 [[I128VAL]], ptr [[LDTEMP:%.+]]
236 // CHECK: [[LD:%.+]] = load <4 x i32>, ptr [[LDTEMP]]
237 // CHECK: extractelement <4 x i32> [[LD]]
238 // CHECK: store i8
239 #pragma omp atomic read
240   bv = int4x[0];
241 // CHECK: [[LD:%.+]] = load atomic i32, ptr getelementptr (i8, ptr @{{.+}}, i64 4) monotonic, align 4
242 // CHECK: store i32 [[LD]], ptr [[LDTEMP:%.+]]
243 // CHECK: [[LD:%.+]] = load i32, ptr [[LDTEMP]]
244 // CHECK: [[SHL:%.+]] = shl i32 [[LD]], 1
245 // CHECK: ashr i32 [[SHL]], 1
246 // CHECK: store x86_fp80
247 #pragma omp atomic read
248   ldv = bfx.a;
249 // CHECK: call void @__atomic_load(i64 noundef 4, ptr noundef getelementptr (i8, ptr @bfx_packed, i64 4), ptr noundef [[LDTEMP:%.+]], i32 noundef 0)
250 // CHECK: [[LD:%.+]] = load i32, ptr [[LDTEMP]]
251 // CHECK: [[SHL:%.+]] = shl i32 [[LD]], 1
252 // CHECK: ashr i32 [[SHL]], 1
253 // CHECK: store x86_fp80
254 #pragma omp atomic read
255   ldv = bfx_packed.a;
256 // CHECK: [[LD:%.+]] = load atomic i32, ptr @bfx2 monotonic, align 4
257 // CHECK: store i32 [[LD]], ptr [[LDTEMP:%.+]]
258 // CHECK: [[LD:%.+]] = load i32, ptr [[LDTEMP]]
259 // CHECK: ashr i32 [[LD]], 31
260 // CHECK: store x86_fp80
261 #pragma omp atomic read
262   ldv = bfx2.a;
263 // CHECK: [[LD:%.+]] = load atomic i8, ptr getelementptr (i8, ptr @bfx2_packed, i64 3) monotonic, align 1
264 // CHECK: store i8 [[LD]], ptr [[LDTEMP:%.+]]
265 // CHECK: [[LD:%.+]] = load i8, ptr [[LDTEMP]]
266 // CHECK: ashr i8 [[LD]], 7
267 // CHECK: store x86_fp80
268 #pragma omp atomic read
269   ldv = bfx2_packed.a;
270 // CHECK: [[LD:%.+]] = load atomic i32, ptr @bfx3 monotonic, align 4
271 // CHECK: store i32 [[LD]], ptr [[LDTEMP:%.+]]
272 // CHECK: [[LD:%.+]] = load i32, ptr [[LDTEMP]]
273 // CHECK: [[SHL:%.+]] = shl i32 [[LD]], 7
274 // CHECK: ashr i32 [[SHL]], 18
275 // CHECK: store x86_fp80
276 #pragma omp atomic read
277   ldv = bfx3.a;
278 // CHECK: call void @__atomic_load(i64 noundef 3, ptr noundef getelementptr (i8, ptr @bfx3_packed, i64 1), ptr noundef [[LDTEMP:%.+]], i32 noundef 0)
279 // CHECK: [[LD:%.+]] = load i24, ptr [[LDTEMP]]
280 // CHECK: [[SHL:%.+]] = shl i24 [[LD]], 7
281 // CHECK: [[ASHR:%.+]] = ashr i24 [[SHL]], 10
282 // CHECK: sext i24 [[ASHR]] to i32
283 // CHECK: store x86_fp80
284 #pragma omp atomic read
285   ldv = bfx3_packed.a;
286 // CHECK: [[LD:%.+]] = load atomic i64, ptr @bfx4 monotonic, align 8
287 // CHECK: store i64 [[LD]], ptr [[LDTEMP:%.+]]
288 // CHECK: [[LD:%.+]] = load i64, ptr [[LDTEMP]]
289 // CHECK: [[SHL:%.+]] = shl i64 [[LD]], 47
290 // CHECK: [[ASHR:%.+]] = ashr i64 [[SHL]], 63
291 // CHECK: trunc i64 [[ASHR]] to i32
292 // CHECK: store x86_fp80
293 #pragma omp atomic read
294   ldv = bfx4.a;
295 // CHECK: [[LD:%.+]] = load atomic i8, ptr getelementptr inbounds nuw (%struct.BitFields4_packed, ptr @bfx4_packed, i32 0, i32 1) monotonic, align 1
296 // CHECK: store i8 [[LD]], ptr [[LDTEMP:%.+]]
297 // CHECK: [[LD:%.+]] = load i8, ptr [[LDTEMP]]
298 // CHECK: [[SHL:%.+]] = shl i8 [[LD]], 7
299 // CHECK: [[ASHR:%.+]] = ashr i8 [[SHL]], 7
300 // CHECK: sext i8 [[ASHR]] to i32
301 // CHECK: store x86_fp80
302 #pragma omp atomic relaxed read
303   ldv = bfx4_packed.a;
304 // CHECK: [[LD:%.+]] = load atomic i64, ptr @bfx4 monotonic, align 8
305 // CHECK: store i64 [[LD]], ptr [[LDTEMP:%.+]]
306 // CHECK: [[LD:%.+]] = load i64, ptr [[LDTEMP]]
307 // CHECK: [[SHL:%.+]] = shl i64 [[LD]], 40
308 // CHECK: [[ASHR:%.+]] = ashr i64 [[SHL]], 57
309 // CHECK: store x86_fp80
310 #pragma omp atomic read relaxed
311   ldv = bfx4.b;
312 // CHECK: [[LD:%.+]] = load atomic i8, ptr getelementptr inbounds nuw (%struct.BitFields4_packed, ptr @bfx4_packed, i32 0, i32 1) acquire, align 1
313 // CHECK: store i8 [[LD]], ptr [[LDTEMP:%.+]]
314 // CHECK: [[LD:%.+]] = load i8, ptr [[LDTEMP]]
315 // CHECK: [[ASHR:%.+]] = ashr i8 [[LD]], 1
316 // CHECK: sext i8 [[ASHR]] to i64
317 // CHECK: call{{.*}} @__kmpc_flush(
318 // CHECK: store x86_fp80
319 #pragma omp atomic read acquire
320   ldv = bfx4_packed.b;
321 // CHECK: [[LD:%.+]] = load atomic i64, ptr @{{.+}} monotonic, align 8
322 // CHECK: store i64 [[LD]], ptr [[LDTEMP:%.+]]
323 // CHECK: [[LD:%.+]] = load <2 x float>, ptr [[LDTEMP]]
324 // CHECK: extractelement <2 x float> [[LD]]
325 // CHECK: store i64
326 #pragma omp atomic read
327   ulv = float2x.x;
328 // CHECK: call{{.*}} i{{[0-9]+}} @llvm.read_register
329 // CHECK: call{{.*}} @__kmpc_flush(
330 // CHECK: store double
331 #pragma omp atomic read seq_cst
332   dv = rix;
333   return 0;
334 }
335 
336 #endif
337