]>
Commit | Line | Data |
---|---|---|
b8698a0f | 1 | /* This file contains routines to construct GNU OpenMP constructs, |
953ff289 DN |
2 | called from parsing in the C and C++ front ends. |
3 | ||
ea1199ee | 4 | Copyright (C) 2005, 2007, 2008, 2009 Free Software Foundation, Inc. |
953ff289 DN |
5 | Contributed by Richard Henderson <rth@redhat.com>, |
6 | Diego Novillo <dnovillo@redhat.com>. | |
7 | ||
8 | This file is part of GCC. | |
9 | ||
10 | GCC is free software; you can redistribute it and/or modify it under | |
11 | the terms of the GNU General Public License as published by the Free | |
9dcd6f09 | 12 | Software Foundation; either version 3, or (at your option) any later |
953ff289 DN |
13 | version. |
14 | ||
15 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
16 | WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
17 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
18 | for more details. | |
19 | ||
20 | You should have received a copy of the GNU General Public License | |
9dcd6f09 NC |
21 | along with GCC; see the file COPYING3. If not see |
22 | <http://www.gnu.org/licenses/>. */ | |
953ff289 DN |
23 | |
24 | #include "config.h" | |
25 | #include "system.h" | |
26 | #include "coretypes.h" | |
27 | #include "tm.h" | |
28 | #include "tree.h" | |
29 | #include "function.h" | |
30 | #include "c-common.h" | |
31 | #include "toplev.h" | |
726a989a | 32 | #include "gimple.h" |
953ff289 DN |
33 | #include "bitmap.h" |
34 | #include "langhooks.h" | |
35 | ||
36 | ||
37 | /* Complete a #pragma omp master construct. STMT is the structured-block | |
c2255bc4 | 38 | that follows the pragma. LOC is the l*/ |
953ff289 DN |
39 | |
40 | tree | |
c2255bc4 | 41 | c_finish_omp_master (location_t loc, tree stmt) |
953ff289 | 42 | { |
c2255bc4 AH |
43 | tree t = add_stmt (build1 (OMP_MASTER, void_type_node, stmt)); |
44 | SET_EXPR_LOCATION (t, loc); | |
45 | return t; | |
953ff289 DN |
46 | } |
47 | ||
48 | /* Complete a #pragma omp critical construct. STMT is the structured-block | |
49 | that follows the pragma, NAME is the identifier in the pragma, or null | |
c2255bc4 | 50 | if it was omitted. LOC is the location of the #pragma. */ |
953ff289 DN |
51 | |
52 | tree | |
c2255bc4 | 53 | c_finish_omp_critical (location_t loc, tree body, tree name) |
953ff289 DN |
54 | { |
55 | tree stmt = make_node (OMP_CRITICAL); | |
56 | TREE_TYPE (stmt) = void_type_node; | |
57 | OMP_CRITICAL_BODY (stmt) = body; | |
58 | OMP_CRITICAL_NAME (stmt) = name; | |
c2255bc4 | 59 | SET_EXPR_LOCATION (stmt, loc); |
953ff289 DN |
60 | return add_stmt (stmt); |
61 | } | |
62 | ||
63 | /* Complete a #pragma omp ordered construct. STMT is the structured-block | |
c2255bc4 | 64 | that follows the pragma. LOC is the location of the #pragma. */ |
953ff289 DN |
65 | |
66 | tree | |
c2255bc4 | 67 | c_finish_omp_ordered (location_t loc, tree stmt) |
953ff289 | 68 | { |
c2255bc4 AH |
69 | tree t = build1 (OMP_ORDERED, void_type_node, stmt); |
70 | SET_EXPR_LOCATION (t, loc); | |
71 | return add_stmt (t); | |
953ff289 DN |
72 | } |
73 | ||
74 | ||
c2255bc4 AH |
75 | /* Complete a #pragma omp barrier construct. LOC is the location of |
76 | the #pragma. */ | |
953ff289 DN |
77 | |
78 | void | |
c2255bc4 | 79 | c_finish_omp_barrier (location_t loc) |
953ff289 DN |
80 | { |
81 | tree x; | |
82 | ||
83 | x = built_in_decls[BUILT_IN_GOMP_BARRIER]; | |
db3927fb | 84 | x = build_call_expr_loc (loc, x, 0); |
953ff289 DN |
85 | add_stmt (x); |
86 | } | |
87 | ||
88 | ||
c2255bc4 AH |
89 | /* Complete a #pragma omp taskwait construct. LOC is the location of the |
90 | pragma. */ | |
a68ab351 JJ |
91 | |
92 | void | |
c2255bc4 | 93 | c_finish_omp_taskwait (location_t loc) |
a68ab351 JJ |
94 | { |
95 | tree x; | |
96 | ||
97 | x = built_in_decls[BUILT_IN_GOMP_TASKWAIT]; | |
db3927fb | 98 | x = build_call_expr_loc (loc, x, 0); |
a68ab351 JJ |
99 | add_stmt (x); |
100 | } | |
101 | ||
102 | ||
c2255bc4 AH |
103 | /* Complete a #pragma omp atomic construct. The expression to be |
104 | implemented atomically is LHS code= RHS. LOC is the location of | |
105 | the atomic statement. The value returned is either error_mark_node | |
106 | (if the construct was erroneous) or an OMP_ATOMIC node which should | |
107 | be added to the current statement tree with add_stmt.*/ | |
953ff289 | 108 | |
fe89d797 | 109 | tree |
c2255bc4 | 110 | c_finish_omp_atomic (location_t loc, enum tree_code code, tree lhs, tree rhs) |
953ff289 DN |
111 | { |
112 | tree x, type, addr; | |
113 | ||
114 | if (lhs == error_mark_node || rhs == error_mark_node) | |
fe89d797 | 115 | return error_mark_node; |
953ff289 DN |
116 | |
117 | /* ??? According to one reading of the OpenMP spec, complex type are | |
118 | supported, but there are no atomic stores for any architecture. | |
119 | But at least icc 9.0 doesn't support complex types here either. | |
120 | And lets not even talk about vector types... */ | |
121 | type = TREE_TYPE (lhs); | |
122 | if (!INTEGRAL_TYPE_P (type) | |
123 | && !POINTER_TYPE_P (type) | |
124 | && !SCALAR_FLOAT_TYPE_P (type)) | |
125 | { | |
c2255bc4 | 126 | error_at (loc, "invalid expression type for %<#pragma omp atomic%>"); |
fe89d797 | 127 | return error_mark_node; |
953ff289 DN |
128 | } |
129 | ||
130 | /* ??? Validate that rhs does not overlap lhs. */ | |
131 | ||
132 | /* Take and save the address of the lhs. From then on we'll reference it | |
133 | via indirection. */ | |
c2255bc4 | 134 | addr = build_unary_op (loc, ADDR_EXPR, lhs, 0); |
953ff289 | 135 | if (addr == error_mark_node) |
fe89d797 | 136 | return error_mark_node; |
953ff289 | 137 | addr = save_expr (addr); |
66bb4f32 JJ |
138 | if (TREE_CODE (addr) != SAVE_EXPR |
139 | && (TREE_CODE (addr) != ADDR_EXPR | |
140 | || TREE_CODE (TREE_OPERAND (addr, 0)) != VAR_DECL)) | |
141 | { | |
142 | /* Make sure LHS is simple enough so that goa_lhs_expr_p can recognize | |
143 | it even after unsharing function body. */ | |
144 | tree var = create_tmp_var_raw (TREE_TYPE (addr), NULL); | |
a406865a | 145 | DECL_CONTEXT (var) = current_function_decl; |
66bb4f32 JJ |
146 | addr = build4 (TARGET_EXPR, TREE_TYPE (addr), var, addr, NULL, NULL); |
147 | } | |
c2255bc4 | 148 | lhs = build_indirect_ref (loc, addr, NULL); |
953ff289 DN |
149 | |
150 | /* There are lots of warnings, errors, and conversions that need to happen | |
151 | in the course of interpreting a statement. Use the normal mechanisms | |
152 | to do this, and then take it apart again. */ | |
c2255bc4 AH |
153 | x = build_modify_expr (input_location, lhs, NULL_TREE, code, |
154 | input_location, rhs, NULL_TREE); | |
953ff289 | 155 | if (x == error_mark_node) |
fe89d797 | 156 | return error_mark_node; |
b8698a0f | 157 | gcc_assert (TREE_CODE (x) == MODIFY_EXPR); |
953ff289 DN |
158 | rhs = TREE_OPERAND (x, 1); |
159 | ||
160 | /* Punt the actual generation of atomic operations to common code. */ | |
c2255bc4 AH |
161 | x = build2 (OMP_ATOMIC, void_type_node, addr, rhs); |
162 | SET_EXPR_LOCATION (x, loc); | |
163 | return x; | |
953ff289 DN |
164 | } |
165 | ||
166 | ||
c2255bc4 AH |
167 | /* Complete a #pragma omp flush construct. We don't do anything with |
168 | the variable list that the syntax allows. LOC is the location of | |
169 | the #pragma. */ | |
953ff289 DN |
170 | |
171 | void | |
c2255bc4 | 172 | c_finish_omp_flush (location_t loc) |
953ff289 DN |
173 | { |
174 | tree x; | |
175 | ||
176 | x = built_in_decls[BUILT_IN_SYNCHRONIZE]; | |
db3927fb | 177 | x = build_call_expr_loc (loc, x, 0); |
953ff289 DN |
178 | add_stmt (x); |
179 | } | |
180 | ||
181 | ||
182 | /* Check and canonicalize #pragma omp for increment expression. | |
183 | Helper function for c_finish_omp_for. */ | |
184 | ||
185 | static tree | |
db3927fb | 186 | check_omp_for_incr_expr (location_t loc, tree exp, tree decl) |
953ff289 DN |
187 | { |
188 | tree t; | |
189 | ||
190 | if (!INTEGRAL_TYPE_P (TREE_TYPE (exp)) | |
191 | || TYPE_PRECISION (TREE_TYPE (exp)) < TYPE_PRECISION (TREE_TYPE (decl))) | |
192 | return error_mark_node; | |
193 | ||
194 | if (exp == decl) | |
195 | return build_int_cst (TREE_TYPE (exp), 0); | |
196 | ||
197 | switch (TREE_CODE (exp)) | |
198 | { | |
1043771b | 199 | CASE_CONVERT: |
db3927fb | 200 | t = check_omp_for_incr_expr (loc, TREE_OPERAND (exp, 0), decl); |
953ff289 | 201 | if (t != error_mark_node) |
db3927fb | 202 | return fold_convert_loc (loc, TREE_TYPE (exp), t); |
953ff289 DN |
203 | break; |
204 | case MINUS_EXPR: | |
db3927fb | 205 | t = check_omp_for_incr_expr (loc, TREE_OPERAND (exp, 0), decl); |
953ff289 | 206 | if (t != error_mark_node) |
db3927fb AH |
207 | return fold_build2_loc (loc, MINUS_EXPR, |
208 | TREE_TYPE (exp), t, TREE_OPERAND (exp, 1)); | |
953ff289 DN |
209 | break; |
210 | case PLUS_EXPR: | |
db3927fb | 211 | t = check_omp_for_incr_expr (loc, TREE_OPERAND (exp, 0), decl); |
953ff289 | 212 | if (t != error_mark_node) |
db3927fb AH |
213 | return fold_build2_loc (loc, PLUS_EXPR, |
214 | TREE_TYPE (exp), t, TREE_OPERAND (exp, 1)); | |
215 | t = check_omp_for_incr_expr (loc, TREE_OPERAND (exp, 1), decl); | |
953ff289 | 216 | if (t != error_mark_node) |
db3927fb AH |
217 | return fold_build2_loc (loc, PLUS_EXPR, |
218 | TREE_TYPE (exp), TREE_OPERAND (exp, 0), t); | |
953ff289 DN |
219 | break; |
220 | default: | |
221 | break; | |
222 | } | |
223 | ||
224 | return error_mark_node; | |
225 | } | |
226 | ||
227 | /* Validate and emit code for the OpenMP directive #pragma omp for. | |
a68ab351 JJ |
228 | DECLV is a vector of iteration variables, for each collapsed loop. |
229 | INITV, CONDV and INCRV are vectors containing initialization | |
230 | expressions, controlling predicates and increment expressions. | |
231 | BODY is the body of the loop and PRE_BODY statements that go before | |
232 | the loop. */ | |
953ff289 DN |
233 | |
234 | tree | |
a68ab351 JJ |
235 | c_finish_omp_for (location_t locus, tree declv, tree initv, tree condv, |
236 | tree incrv, tree body, tree pre_body) | |
953ff289 | 237 | { |
a68ab351 | 238 | location_t elocus; |
953ff289 | 239 | bool fail = false; |
a68ab351 | 240 | int i; |
953ff289 | 241 | |
a68ab351 JJ |
242 | gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (initv)); |
243 | gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (condv)); | |
244 | gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (incrv)); | |
245 | for (i = 0; i < TREE_VEC_LENGTH (declv); i++) | |
953ff289 | 246 | { |
a68ab351 JJ |
247 | tree decl = TREE_VEC_ELT (declv, i); |
248 | tree init = TREE_VEC_ELT (initv, i); | |
249 | tree cond = TREE_VEC_ELT (condv, i); | |
250 | tree incr = TREE_VEC_ELT (incrv, i); | |
251 | ||
252 | elocus = locus; | |
253 | if (EXPR_HAS_LOCATION (init)) | |
254 | elocus = EXPR_LOCATION (init); | |
255 | ||
256 | /* Validate the iteration variable. */ | |
257 | if (!INTEGRAL_TYPE_P (TREE_TYPE (decl)) | |
258 | && TREE_CODE (TREE_TYPE (decl)) != POINTER_TYPE) | |
259 | { | |
c9f9eb5d | 260 | error_at (elocus, "invalid type for iteration variable %qE", decl); |
a68ab351 JJ |
261 | fail = true; |
262 | } | |
953ff289 | 263 | |
a68ab351 JJ |
264 | /* In the case of "for (int i = 0...)", init will be a decl. It should |
265 | have a DECL_INITIAL that we can turn into an assignment. */ | |
266 | if (init == decl) | |
267 | { | |
268 | elocus = DECL_SOURCE_LOCATION (decl); | |
269 | ||
270 | init = DECL_INITIAL (decl); | |
271 | if (init == NULL) | |
272 | { | |
c9f9eb5d | 273 | error_at (elocus, "%qE is not initialized", decl); |
a68ab351 JJ |
274 | init = integer_zero_node; |
275 | fail = true; | |
276 | } | |
953ff289 | 277 | |
b8698a0f | 278 | init = build_modify_expr (elocus, decl, NULL_TREE, NOP_EXPR, |
c2255bc4 AH |
279 | /* FIXME diagnostics: This should |
280 | be the location of the INIT. */ | |
281 | elocus, | |
282 | init, | |
32e8bb8e | 283 | NULL_TREE); |
a68ab351 JJ |
284 | } |
285 | gcc_assert (TREE_CODE (init) == MODIFY_EXPR); | |
286 | gcc_assert (TREE_OPERAND (init, 0) == decl); | |
287 | ||
288 | if (cond == NULL_TREE) | |
953ff289 | 289 | { |
c9f9eb5d | 290 | error_at (elocus, "missing controlling predicate"); |
953ff289 DN |
291 | fail = true; |
292 | } | |
a68ab351 JJ |
293 | else |
294 | { | |
295 | bool cond_ok = false; | |
953ff289 | 296 | |
a68ab351 JJ |
297 | if (EXPR_HAS_LOCATION (cond)) |
298 | elocus = EXPR_LOCATION (cond); | |
953ff289 | 299 | |
a68ab351 JJ |
300 | if (TREE_CODE (cond) == LT_EXPR |
301 | || TREE_CODE (cond) == LE_EXPR | |
302 | || TREE_CODE (cond) == GT_EXPR | |
ea1199ee JJ |
303 | || TREE_CODE (cond) == GE_EXPR |
304 | || TREE_CODE (cond) == NE_EXPR) | |
a68ab351 JJ |
305 | { |
306 | tree op0 = TREE_OPERAND (cond, 0); | |
307 | tree op1 = TREE_OPERAND (cond, 1); | |
953ff289 | 308 | |
a68ab351 JJ |
309 | /* 2.5.1. The comparison in the condition is computed in |
310 | the type of DECL, otherwise the behavior is undefined. | |
953ff289 | 311 | |
a68ab351 JJ |
312 | For example: |
313 | long n; int i; | |
314 | i < n; | |
953ff289 | 315 | |
a68ab351 JJ |
316 | according to ISO will be evaluated as: |
317 | (long)i < n; | |
953ff289 | 318 | |
a68ab351 JJ |
319 | We want to force: |
320 | i < (int)n; */ | |
321 | if (TREE_CODE (op0) == NOP_EXPR | |
322 | && decl == TREE_OPERAND (op0, 0)) | |
323 | { | |
324 | TREE_OPERAND (cond, 0) = TREE_OPERAND (op0, 0); | |
325 | TREE_OPERAND (cond, 1) | |
db3927fb | 326 | = fold_build1_loc (elocus, NOP_EXPR, TREE_TYPE (decl), |
a68ab351 JJ |
327 | TREE_OPERAND (cond, 1)); |
328 | } | |
329 | else if (TREE_CODE (op1) == NOP_EXPR | |
330 | && decl == TREE_OPERAND (op1, 0)) | |
331 | { | |
332 | TREE_OPERAND (cond, 1) = TREE_OPERAND (op1, 0); | |
333 | TREE_OPERAND (cond, 0) | |
db3927fb | 334 | = fold_build1_loc (elocus, NOP_EXPR, TREE_TYPE (decl), |
a68ab351 JJ |
335 | TREE_OPERAND (cond, 0)); |
336 | } | |
953ff289 | 337 | |
a68ab351 JJ |
338 | if (decl == TREE_OPERAND (cond, 0)) |
339 | cond_ok = true; | |
340 | else if (decl == TREE_OPERAND (cond, 1)) | |
341 | { | |
342 | TREE_SET_CODE (cond, | |
343 | swap_tree_comparison (TREE_CODE (cond))); | |
344 | TREE_OPERAND (cond, 1) = TREE_OPERAND (cond, 0); | |
345 | TREE_OPERAND (cond, 0) = decl; | |
346 | cond_ok = true; | |
347 | } | |
ea1199ee JJ |
348 | |
349 | if (TREE_CODE (cond) == NE_EXPR) | |
350 | { | |
351 | if (!INTEGRAL_TYPE_P (TREE_TYPE (decl))) | |
352 | cond_ok = false; | |
353 | else if (operand_equal_p (TREE_OPERAND (cond, 1), | |
354 | TYPE_MIN_VALUE (TREE_TYPE (decl)), | |
355 | 0)) | |
356 | TREE_SET_CODE (cond, GT_EXPR); | |
357 | else if (operand_equal_p (TREE_OPERAND (cond, 1), | |
358 | TYPE_MAX_VALUE (TREE_TYPE (decl)), | |
359 | 0)) | |
360 | TREE_SET_CODE (cond, LT_EXPR); | |
361 | else | |
362 | cond_ok = false; | |
363 | } | |
953ff289 DN |
364 | } |
365 | ||
a68ab351 | 366 | if (!cond_ok) |
953ff289 | 367 | { |
c9f9eb5d | 368 | error_at (elocus, "invalid controlling predicate"); |
a68ab351 | 369 | fail = true; |
953ff289 DN |
370 | } |
371 | } | |
372 | ||
a68ab351 | 373 | if (incr == NULL_TREE) |
953ff289 | 374 | { |
c9f9eb5d | 375 | error_at (elocus, "missing increment expression"); |
953ff289 DN |
376 | fail = true; |
377 | } | |
a68ab351 | 378 | else |
953ff289 | 379 | { |
a68ab351 | 380 | bool incr_ok = false; |
953ff289 | 381 | |
a68ab351 JJ |
382 | if (EXPR_HAS_LOCATION (incr)) |
383 | elocus = EXPR_LOCATION (incr); | |
384 | ||
385 | /* Check all the valid increment expressions: v++, v--, ++v, --v, | |
386 | v = v + incr, v = incr + v and v = v - incr. */ | |
387 | switch (TREE_CODE (incr)) | |
953ff289 | 388 | { |
a68ab351 JJ |
389 | case POSTINCREMENT_EXPR: |
390 | case PREINCREMENT_EXPR: | |
391 | case POSTDECREMENT_EXPR: | |
392 | case PREDECREMENT_EXPR: | |
393 | if (TREE_OPERAND (incr, 0) != decl) | |
394 | break; | |
395 | ||
396 | incr_ok = true; | |
956adfaf JJ |
397 | if (POINTER_TYPE_P (TREE_TYPE (decl)) |
398 | && TREE_OPERAND (incr, 1)) | |
953ff289 | 399 | { |
db3927fb AH |
400 | tree t = fold_convert_loc (elocus, |
401 | sizetype, TREE_OPERAND (incr, 1)); | |
a68ab351 JJ |
402 | |
403 | if (TREE_CODE (incr) == POSTDECREMENT_EXPR | |
404 | || TREE_CODE (incr) == PREDECREMENT_EXPR) | |
db3927fb | 405 | t = fold_build1_loc (elocus, NEGATE_EXPR, sizetype, t); |
a68ab351 | 406 | t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (decl), decl, t); |
953ff289 DN |
407 | incr = build2 (MODIFY_EXPR, void_type_node, decl, t); |
408 | } | |
a68ab351 JJ |
409 | break; |
410 | ||
411 | case MODIFY_EXPR: | |
412 | if (TREE_OPERAND (incr, 0) != decl) | |
413 | break; | |
414 | if (TREE_OPERAND (incr, 1) == decl) | |
415 | break; | |
416 | if (TREE_CODE (TREE_OPERAND (incr, 1)) == PLUS_EXPR | |
417 | && (TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl | |
418 | || TREE_OPERAND (TREE_OPERAND (incr, 1), 1) == decl)) | |
419 | incr_ok = true; | |
420 | else if ((TREE_CODE (TREE_OPERAND (incr, 1)) == MINUS_EXPR | |
421 | || (TREE_CODE (TREE_OPERAND (incr, 1)) | |
422 | == POINTER_PLUS_EXPR)) | |
423 | && TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl) | |
424 | incr_ok = true; | |
425 | else | |
426 | { | |
db3927fb AH |
427 | tree t = check_omp_for_incr_expr (elocus, |
428 | TREE_OPERAND (incr, 1), | |
a68ab351 JJ |
429 | decl); |
430 | if (t != error_mark_node) | |
431 | { | |
432 | incr_ok = true; | |
433 | t = build2 (PLUS_EXPR, TREE_TYPE (decl), decl, t); | |
434 | incr = build2 (MODIFY_EXPR, void_type_node, decl, t); | |
435 | } | |
436 | } | |
437 | break; | |
953ff289 | 438 | |
a68ab351 JJ |
439 | default: |
440 | break; | |
441 | } | |
442 | if (!incr_ok) | |
443 | { | |
c9f9eb5d | 444 | error_at (elocus, "invalid increment expression"); |
a68ab351 JJ |
445 | fail = true; |
446 | } | |
953ff289 | 447 | } |
a68ab351 JJ |
448 | |
449 | TREE_VEC_ELT (initv, i) = init; | |
450 | TREE_VEC_ELT (incrv, i) = incr; | |
953ff289 DN |
451 | } |
452 | ||
453 | if (fail) | |
454 | return NULL; | |
455 | else | |
456 | { | |
457 | tree t = make_node (OMP_FOR); | |
458 | ||
459 | TREE_TYPE (t) = void_type_node; | |
a68ab351 JJ |
460 | OMP_FOR_INIT (t) = initv; |
461 | OMP_FOR_COND (t) = condv; | |
462 | OMP_FOR_INCR (t) = incrv; | |
953ff289 DN |
463 | OMP_FOR_BODY (t) = body; |
464 | OMP_FOR_PRE_BODY (t) = pre_body; | |
465 | ||
466 | SET_EXPR_LOCATION (t, locus); | |
467 | return add_stmt (t); | |
468 | } | |
469 | } | |
470 | ||
471 | ||
c2255bc4 AH |
472 | /* Divide CLAUSES into two lists: those that apply to a parallel |
473 | construct, and those that apply to a work-sharing construct. Place | |
474 | the results in *PAR_CLAUSES and *WS_CLAUSES respectively. In | |
475 | addition, add a nowait clause to the work-sharing list. LOC is the | |
476 | location of the OMP_PARALLEL*. */ | |
953ff289 DN |
477 | |
478 | void | |
c2255bc4 AH |
479 | c_split_parallel_clauses (location_t loc, tree clauses, |
480 | tree *par_clauses, tree *ws_clauses) | |
953ff289 DN |
481 | { |
482 | tree next; | |
483 | ||
484 | *par_clauses = NULL; | |
c2255bc4 | 485 | *ws_clauses = build_omp_clause (loc, OMP_CLAUSE_NOWAIT); |
953ff289 DN |
486 | |
487 | for (; clauses ; clauses = next) | |
488 | { | |
489 | next = OMP_CLAUSE_CHAIN (clauses); | |
490 | ||
aaf46ef9 | 491 | switch (OMP_CLAUSE_CODE (clauses)) |
953ff289 DN |
492 | { |
493 | case OMP_CLAUSE_PRIVATE: | |
494 | case OMP_CLAUSE_SHARED: | |
495 | case OMP_CLAUSE_FIRSTPRIVATE: | |
496 | case OMP_CLAUSE_LASTPRIVATE: | |
497 | case OMP_CLAUSE_REDUCTION: | |
498 | case OMP_CLAUSE_COPYIN: | |
499 | case OMP_CLAUSE_IF: | |
500 | case OMP_CLAUSE_NUM_THREADS: | |
501 | case OMP_CLAUSE_DEFAULT: | |
502 | OMP_CLAUSE_CHAIN (clauses) = *par_clauses; | |
503 | *par_clauses = clauses; | |
504 | break; | |
505 | ||
506 | case OMP_CLAUSE_SCHEDULE: | |
507 | case OMP_CLAUSE_ORDERED: | |
a68ab351 | 508 | case OMP_CLAUSE_COLLAPSE: |
953ff289 DN |
509 | OMP_CLAUSE_CHAIN (clauses) = *ws_clauses; |
510 | *ws_clauses = clauses; | |
511 | break; | |
512 | ||
513 | default: | |
514 | gcc_unreachable (); | |
515 | } | |
516 | } | |
517 | } | |
518 | ||
519 | /* True if OpenMP sharing attribute of DECL is predetermined. */ | |
520 | ||
521 | enum omp_clause_default_kind | |
522 | c_omp_predetermined_sharing (tree decl) | |
523 | { | |
524 | /* Variables with const-qualified type having no mutable member | |
525 | are predetermined shared. */ | |
526 | if (TREE_READONLY (decl)) | |
527 | return OMP_CLAUSE_DEFAULT_SHARED; | |
528 | ||
529 | return OMP_CLAUSE_DEFAULT_UNSPECIFIED; | |
530 | } |