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