1 /* This file contains routines to construct GNU OpenMP constructs,
2 called from parsing in the C and C++ front ends.
4 Copyright (C) 2005, 2007, 2008 Free Software Foundation, Inc.
5 Contributed by Richard Henderson <rth@redhat.com>,
6 Diego Novillo <dnovillo@redhat.com>.
8 This file is part of GCC.
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
12 Software Foundation; either version 3, or (at your option) any later
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
20 You should have received a copy of the GNU General Public License
21 along with GCC; see the file COPYING3. If not see
22 <http://www.gnu.org/licenses/>. */
26 #include "coretypes.h"
34 #include "langhooks.h"
37 /* Complete a #pragma omp master construct. STMT is the structured-block
38 that follows the pragma. */
41 c_finish_omp_master (tree stmt
)
43 return add_stmt (build1 (OMP_MASTER
, void_type_node
, stmt
));
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
51 c_finish_omp_critical (tree body
, tree name
)
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
);
60 /* Complete a #pragma omp ordered construct. STMT is the structured-block
61 that follows the pragma. */
64 c_finish_omp_ordered (tree stmt
)
66 return add_stmt (build1 (OMP_ORDERED
, void_type_node
, stmt
));
70 /* Complete a #pragma omp barrier construct. */
73 c_finish_omp_barrier (void)
77 x
= built_in_decls
[BUILT_IN_GOMP_BARRIER
];
78 x
= build_call_expr (x
, 0);
83 /* Complete a #pragma omp taskwait construct. */
86 c_finish_omp_taskwait (void)
90 x
= built_in_decls
[BUILT_IN_GOMP_TASKWAIT
];
91 x
= build_call_expr (x
, 0);
96 /* Complete a #pragma omp atomic construct. The expression to be
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
103 c_finish_omp_atomic (enum tree_code code
, tree lhs
, tree rhs
)
107 if (lhs
== error_mark_node
|| rhs
== error_mark_node
)
108 return error_mark_node
;
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
))
119 error ("invalid expression type for %<#pragma omp atomic%>");
120 return error_mark_node
;
123 /* ??? Validate that rhs does not overlap lhs. */
125 /* Take and save the address of the lhs. From then on we'll reference it
127 addr
= build_unary_op (input_location
, ADDR_EXPR
, lhs
, 0);
128 if (addr
== error_mark_node
)
129 return error_mark_node
;
130 addr
= save_expr (addr
);
131 if (TREE_CODE (addr
) != SAVE_EXPR
132 && (TREE_CODE (addr
) != ADDR_EXPR
133 || TREE_CODE (TREE_OPERAND (addr
, 0)) != VAR_DECL
))
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
);
140 lhs
= build_indirect_ref (input_location
, addr
, NULL
);
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. */
145 x
= build_modify_expr (input_location
, lhs
, code
, rhs
);
146 if (x
== error_mark_node
)
147 return error_mark_node
;
148 gcc_assert (TREE_CODE (x
) == MODIFY_EXPR
);
149 rhs
= TREE_OPERAND (x
, 1);
151 /* Punt the actual generation of atomic operations to common code. */
152 return build2 (OMP_ATOMIC
, void_type_node
, addr
, rhs
);
156 /* Complete a #pragma omp flush construct. We don't do anything with the
157 variable list that the syntax allows. */
160 c_finish_omp_flush (void)
164 x
= built_in_decls
[BUILT_IN_SYNCHRONIZE
];
165 x
= build_call_expr (x
, 0);
170 /* Check and canonicalize #pragma omp for increment expression.
171 Helper function for c_finish_omp_for. */
174 check_omp_for_incr_expr (tree exp
, tree decl
)
178 if (!INTEGRAL_TYPE_P (TREE_TYPE (exp
))
179 || TYPE_PRECISION (TREE_TYPE (exp
)) < TYPE_PRECISION (TREE_TYPE (decl
)))
180 return error_mark_node
;
183 return build_int_cst (TREE_TYPE (exp
), 0);
185 switch (TREE_CODE (exp
))
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
);
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));
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
);
209 return error_mark_node
;
212 /* Validate and emit code for the OpenMP directive #pragma omp for.
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
220 c_finish_omp_for (location_t locus
, tree declv
, tree initv
, tree condv
,
221 tree incrv
, tree body
, tree pre_body
)
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
++)
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
);
238 if (EXPR_HAS_LOCATION (init
))
239 elocus
= EXPR_LOCATION (init
);
241 /* Validate the iteration variable. */
242 if (!INTEGRAL_TYPE_P (TREE_TYPE (decl
))
243 && TREE_CODE (TREE_TYPE (decl
)) != POINTER_TYPE
)
245 error_at (elocus
, "invalid type for iteration variable %qE", decl
);
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. */
253 elocus
= DECL_SOURCE_LOCATION (decl
);
255 init
= DECL_INITIAL (decl
);
258 error_at (elocus
, "%qE is not initialized", decl
);
259 init
= integer_zero_node
;
263 init
= build_modify_expr (elocus
, decl
, NOP_EXPR
, init
);
265 gcc_assert (TREE_CODE (init
) == MODIFY_EXPR
);
266 gcc_assert (TREE_OPERAND (init
, 0) == decl
);
268 if (cond
== NULL_TREE
)
270 error_at (elocus
, "missing controlling predicate");
275 bool cond_ok
= false;
277 if (EXPR_HAS_LOCATION (cond
))
278 elocus
= EXPR_LOCATION (cond
);
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
)
285 tree op0
= TREE_OPERAND (cond
, 0);
286 tree op1
= TREE_OPERAND (cond
, 1);
288 /* 2.5.1. The comparison in the condition is computed in
289 the type of DECL, otherwise the behavior is undefined.
295 according to ISO will be evaluated as:
300 if (TREE_CODE (op0
) == NOP_EXPR
301 && decl
== TREE_OPERAND (op0
, 0))
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));
308 else if (TREE_CODE (op1
) == NOP_EXPR
309 && decl
== TREE_OPERAND (op1
, 0))
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));
317 if (decl
== TREE_OPERAND (cond
, 0))
319 else if (decl
== TREE_OPERAND (cond
, 1))
322 swap_tree_comparison (TREE_CODE (cond
)));
323 TREE_OPERAND (cond
, 1) = TREE_OPERAND (cond
, 0);
324 TREE_OPERAND (cond
, 0) = decl
;
331 error_at (elocus
, "invalid controlling predicate");
336 if (incr
== NULL_TREE
)
338 error_at (elocus
, "missing increment expression");
343 bool incr_ok
= false;
345 if (EXPR_HAS_LOCATION (incr
))
346 elocus
= EXPR_LOCATION (incr
);
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
))
352 case POSTINCREMENT_EXPR
:
353 case PREINCREMENT_EXPR
:
354 case POSTDECREMENT_EXPR
:
355 case PREDECREMENT_EXPR
:
356 if (TREE_OPERAND (incr
, 0) != decl
)
360 if (POINTER_TYPE_P (TREE_TYPE (decl
))
361 && TREE_OPERAND (incr
, 1))
363 tree t
= fold_convert (sizetype
, TREE_OPERAND (incr
, 1));
365 if (TREE_CODE (incr
) == POSTDECREMENT_EXPR
366 || TREE_CODE (incr
) == PREDECREMENT_EXPR
)
367 t
= fold_build1 (NEGATE_EXPR
, sizetype
, t
);
368 t
= build2 (POINTER_PLUS_EXPR
, TREE_TYPE (decl
), decl
, t
);
369 incr
= build2 (MODIFY_EXPR
, void_type_node
, decl
, t
);
374 if (TREE_OPERAND (incr
, 0) != decl
)
376 if (TREE_OPERAND (incr
, 1) == decl
)
378 if (TREE_CODE (TREE_OPERAND (incr
, 1)) == PLUS_EXPR
379 && (TREE_OPERAND (TREE_OPERAND (incr
, 1), 0) == decl
380 || TREE_OPERAND (TREE_OPERAND (incr
, 1), 1) == decl
))
382 else if ((TREE_CODE (TREE_OPERAND (incr
, 1)) == MINUS_EXPR
383 || (TREE_CODE (TREE_OPERAND (incr
, 1))
384 == POINTER_PLUS_EXPR
))
385 && TREE_OPERAND (TREE_OPERAND (incr
, 1), 0) == decl
)
389 tree t
= check_omp_for_incr_expr (TREE_OPERAND (incr
, 1),
391 if (t
!= error_mark_node
)
394 t
= build2 (PLUS_EXPR
, TREE_TYPE (decl
), decl
, t
);
395 incr
= build2 (MODIFY_EXPR
, void_type_node
, decl
, t
);
405 error_at (elocus
, "invalid increment expression");
410 TREE_VEC_ELT (initv
, i
) = init
;
411 TREE_VEC_ELT (incrv
, i
) = incr
;
418 tree t
= make_node (OMP_FOR
);
420 TREE_TYPE (t
) = void_type_node
;
421 OMP_FOR_INIT (t
) = initv
;
422 OMP_FOR_COND (t
) = condv
;
423 OMP_FOR_INCR (t
) = incrv
;
424 OMP_FOR_BODY (t
) = body
;
425 OMP_FOR_PRE_BODY (t
) = pre_body
;
427 SET_EXPR_LOCATION (t
, locus
);
433 /* Divide CLAUSES into two lists: those that apply to a parallel construct,
434 and those that apply to a work-sharing construct. Place the results in
435 *PAR_CLAUSES and *WS_CLAUSES respectively. In addition, add a nowait
436 clause to the work-sharing list. */
439 c_split_parallel_clauses (tree clauses
, tree
*par_clauses
, tree
*ws_clauses
)
444 *ws_clauses
= build_omp_clause (OMP_CLAUSE_NOWAIT
);
446 for (; clauses
; clauses
= next
)
448 next
= OMP_CLAUSE_CHAIN (clauses
);
450 switch (OMP_CLAUSE_CODE (clauses
))
452 case OMP_CLAUSE_PRIVATE
:
453 case OMP_CLAUSE_SHARED
:
454 case OMP_CLAUSE_FIRSTPRIVATE
:
455 case OMP_CLAUSE_LASTPRIVATE
:
456 case OMP_CLAUSE_REDUCTION
:
457 case OMP_CLAUSE_COPYIN
:
459 case OMP_CLAUSE_NUM_THREADS
:
460 case OMP_CLAUSE_DEFAULT
:
461 OMP_CLAUSE_CHAIN (clauses
) = *par_clauses
;
462 *par_clauses
= clauses
;
465 case OMP_CLAUSE_SCHEDULE
:
466 case OMP_CLAUSE_ORDERED
:
467 case OMP_CLAUSE_COLLAPSE
:
468 OMP_CLAUSE_CHAIN (clauses
) = *ws_clauses
;
469 *ws_clauses
= clauses
;
478 /* True if OpenMP sharing attribute of DECL is predetermined. */
480 enum omp_clause_default_kind
481 c_omp_predetermined_sharing (tree decl
)
483 /* Variables with const-qualified type having no mutable member
484 are predetermined shared. */
485 if (TREE_READONLY (decl
))
486 return OMP_CLAUSE_DEFAULT_SHARED
;
488 return OMP_CLAUSE_DEFAULT_UNSPECIFIED
;