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, 2009, 2010 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. LOC is the l*/
41 c_finish_omp_master (location_t loc
, tree stmt
)
43 tree t
= add_stmt (build1 (OMP_MASTER
, void_type_node
, stmt
));
44 SET_EXPR_LOCATION (t
, loc
);
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
50 if it was omitted. LOC is the location of the #pragma. */
53 c_finish_omp_critical (location_t loc
, tree body
, tree name
)
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
;
59 SET_EXPR_LOCATION (stmt
, loc
);
60 return add_stmt (stmt
);
63 /* Complete a #pragma omp ordered construct. STMT is the structured-block
64 that follows the pragma. LOC is the location of the #pragma. */
67 c_finish_omp_ordered (location_t loc
, tree stmt
)
69 tree t
= build1 (OMP_ORDERED
, void_type_node
, stmt
);
70 SET_EXPR_LOCATION (t
, loc
);
75 /* Complete a #pragma omp barrier construct. LOC is the location of
79 c_finish_omp_barrier (location_t loc
)
83 x
= built_in_decls
[BUILT_IN_GOMP_BARRIER
];
84 x
= build_call_expr_loc (loc
, x
, 0);
89 /* Complete a #pragma omp taskwait construct. LOC is the location of the
93 c_finish_omp_taskwait (location_t loc
)
97 x
= built_in_decls
[BUILT_IN_GOMP_TASKWAIT
];
98 x
= build_call_expr_loc (loc
, x
, 0);
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.*/
110 c_finish_omp_atomic (location_t loc
, enum tree_code code
, tree lhs
, tree rhs
)
114 if (lhs
== error_mark_node
|| rhs
== error_mark_node
)
115 return error_mark_node
;
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
))
126 error_at (loc
, "invalid expression type for %<#pragma omp atomic%>");
127 return error_mark_node
;
130 /* ??? Validate that rhs does not overlap lhs. */
132 /* Take and save the address of the lhs. From then on we'll reference it
134 addr
= build_unary_op (loc
, ADDR_EXPR
, lhs
, 0);
135 if (addr
== error_mark_node
)
136 return error_mark_node
;
137 addr
= save_expr (addr
);
138 if (TREE_CODE (addr
) != SAVE_EXPR
139 && (TREE_CODE (addr
) != ADDR_EXPR
140 || TREE_CODE (TREE_OPERAND (addr
, 0)) != VAR_DECL
))
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
);
145 DECL_CONTEXT (var
) = current_function_decl
;
146 addr
= build4 (TARGET_EXPR
, TREE_TYPE (addr
), var
, addr
, NULL
, NULL
);
148 lhs
= build_indirect_ref (loc
, addr
, RO_NULL
);
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. */
153 x
= build_modify_expr (input_location
, lhs
, NULL_TREE
, code
,
154 input_location
, rhs
, NULL_TREE
);
155 if (x
== error_mark_node
)
156 return error_mark_node
;
157 gcc_assert (TREE_CODE (x
) == MODIFY_EXPR
);
158 rhs
= TREE_OPERAND (x
, 1);
160 /* Punt the actual generation of atomic operations to common code. */
161 x
= build2 (OMP_ATOMIC
, void_type_node
, addr
, rhs
);
162 SET_EXPR_LOCATION (x
, loc
);
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
172 c_finish_omp_flush (location_t loc
)
176 x
= built_in_decls
[BUILT_IN_SYNCHRONIZE
];
177 x
= build_call_expr_loc (loc
, x
, 0);
182 /* Check and canonicalize #pragma omp for increment expression.
183 Helper function for c_finish_omp_for. */
186 check_omp_for_incr_expr (location_t loc
, tree exp
, tree decl
)
190 if (!INTEGRAL_TYPE_P (TREE_TYPE (exp
))
191 || TYPE_PRECISION (TREE_TYPE (exp
)) < TYPE_PRECISION (TREE_TYPE (decl
)))
192 return error_mark_node
;
195 return build_int_cst (TREE_TYPE (exp
), 0);
197 switch (TREE_CODE (exp
))
200 t
= check_omp_for_incr_expr (loc
, TREE_OPERAND (exp
, 0), decl
);
201 if (t
!= error_mark_node
)
202 return fold_convert_loc (loc
, TREE_TYPE (exp
), t
);
205 t
= check_omp_for_incr_expr (loc
, TREE_OPERAND (exp
, 0), decl
);
206 if (t
!= error_mark_node
)
207 return fold_build2_loc (loc
, MINUS_EXPR
,
208 TREE_TYPE (exp
), t
, TREE_OPERAND (exp
, 1));
211 t
= check_omp_for_incr_expr (loc
, TREE_OPERAND (exp
, 0), decl
);
212 if (t
!= error_mark_node
)
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
);
216 if (t
!= error_mark_node
)
217 return fold_build2_loc (loc
, PLUS_EXPR
,
218 TREE_TYPE (exp
), TREE_OPERAND (exp
, 0), t
);
224 return error_mark_node
;
227 /* Validate and emit code for the OpenMP directive #pragma omp for.
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
235 c_finish_omp_for (location_t locus
, tree declv
, tree initv
, tree condv
,
236 tree incrv
, tree body
, tree pre_body
)
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
++)
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
);
253 if (EXPR_HAS_LOCATION (init
))
254 elocus
= EXPR_LOCATION (init
);
256 /* Validate the iteration variable. */
257 if (!INTEGRAL_TYPE_P (TREE_TYPE (decl
))
258 && TREE_CODE (TREE_TYPE (decl
)) != POINTER_TYPE
)
260 error_at (elocus
, "invalid type for iteration variable %qE", decl
);
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. */
268 elocus
= DECL_SOURCE_LOCATION (decl
);
270 init
= DECL_INITIAL (decl
);
273 error_at (elocus
, "%qE is not initialized", decl
);
274 init
= integer_zero_node
;
278 init
= build_modify_expr (elocus
, decl
, NULL_TREE
, NOP_EXPR
,
279 /* FIXME diagnostics: This should
280 be the location of the INIT. */
285 gcc_assert (TREE_CODE (init
) == MODIFY_EXPR
);
286 gcc_assert (TREE_OPERAND (init
, 0) == decl
);
288 if (cond
== NULL_TREE
)
290 error_at (elocus
, "missing controlling predicate");
295 bool cond_ok
= false;
297 if (EXPR_HAS_LOCATION (cond
))
298 elocus
= EXPR_LOCATION (cond
);
300 if (TREE_CODE (cond
) == LT_EXPR
301 || TREE_CODE (cond
) == LE_EXPR
302 || TREE_CODE (cond
) == GT_EXPR
303 || TREE_CODE (cond
) == GE_EXPR
304 || TREE_CODE (cond
) == NE_EXPR
305 || TREE_CODE (cond
) == EQ_EXPR
)
307 tree op0
= TREE_OPERAND (cond
, 0);
308 tree op1
= TREE_OPERAND (cond
, 1);
310 /* 2.5.1. The comparison in the condition is computed in
311 the type of DECL, otherwise the behavior is undefined.
317 according to ISO will be evaluated as:
322 if (TREE_CODE (op0
) == NOP_EXPR
323 && decl
== TREE_OPERAND (op0
, 0))
325 TREE_OPERAND (cond
, 0) = TREE_OPERAND (op0
, 0);
326 TREE_OPERAND (cond
, 1)
327 = fold_build1_loc (elocus
, NOP_EXPR
, TREE_TYPE (decl
),
328 TREE_OPERAND (cond
, 1));
330 else if (TREE_CODE (op1
) == NOP_EXPR
331 && decl
== TREE_OPERAND (op1
, 0))
333 TREE_OPERAND (cond
, 1) = TREE_OPERAND (op1
, 0);
334 TREE_OPERAND (cond
, 0)
335 = fold_build1_loc (elocus
, NOP_EXPR
, TREE_TYPE (decl
),
336 TREE_OPERAND (cond
, 0));
339 if (decl
== TREE_OPERAND (cond
, 0))
341 else if (decl
== TREE_OPERAND (cond
, 1))
344 swap_tree_comparison (TREE_CODE (cond
)));
345 TREE_OPERAND (cond
, 1) = TREE_OPERAND (cond
, 0);
346 TREE_OPERAND (cond
, 0) = decl
;
350 if (TREE_CODE (cond
) == NE_EXPR
351 || TREE_CODE (cond
) == EQ_EXPR
)
353 if (!INTEGRAL_TYPE_P (TREE_TYPE (decl
)))
355 else if (operand_equal_p (TREE_OPERAND (cond
, 1),
356 TYPE_MIN_VALUE (TREE_TYPE (decl
)),
358 TREE_SET_CODE (cond
, TREE_CODE (cond
) == NE_EXPR
359 ? GT_EXPR
: LE_EXPR
);
360 else if (operand_equal_p (TREE_OPERAND (cond
, 1),
361 TYPE_MAX_VALUE (TREE_TYPE (decl
)),
363 TREE_SET_CODE (cond
, TREE_CODE (cond
) == NE_EXPR
364 ? LT_EXPR
: GE_EXPR
);
372 error_at (elocus
, "invalid controlling predicate");
377 if (incr
== NULL_TREE
)
379 error_at (elocus
, "missing increment expression");
384 bool incr_ok
= false;
386 if (EXPR_HAS_LOCATION (incr
))
387 elocus
= EXPR_LOCATION (incr
);
389 /* Check all the valid increment expressions: v++, v--, ++v, --v,
390 v = v + incr, v = incr + v and v = v - incr. */
391 switch (TREE_CODE (incr
))
393 case POSTINCREMENT_EXPR
:
394 case PREINCREMENT_EXPR
:
395 case POSTDECREMENT_EXPR
:
396 case PREDECREMENT_EXPR
:
397 if (TREE_OPERAND (incr
, 0) != decl
)
401 if (POINTER_TYPE_P (TREE_TYPE (decl
))
402 && TREE_OPERAND (incr
, 1))
404 tree t
= fold_convert_loc (elocus
,
405 sizetype
, TREE_OPERAND (incr
, 1));
407 if (TREE_CODE (incr
) == POSTDECREMENT_EXPR
408 || TREE_CODE (incr
) == PREDECREMENT_EXPR
)
409 t
= fold_build1_loc (elocus
, NEGATE_EXPR
, sizetype
, t
);
410 t
= build2 (POINTER_PLUS_EXPR
, TREE_TYPE (decl
), decl
, t
);
411 incr
= build2 (MODIFY_EXPR
, void_type_node
, decl
, t
);
416 if (TREE_OPERAND (incr
, 0) != decl
)
418 if (TREE_OPERAND (incr
, 1) == decl
)
420 if (TREE_CODE (TREE_OPERAND (incr
, 1)) == PLUS_EXPR
421 && (TREE_OPERAND (TREE_OPERAND (incr
, 1), 0) == decl
422 || TREE_OPERAND (TREE_OPERAND (incr
, 1), 1) == decl
))
424 else if ((TREE_CODE (TREE_OPERAND (incr
, 1)) == MINUS_EXPR
425 || (TREE_CODE (TREE_OPERAND (incr
, 1))
426 == POINTER_PLUS_EXPR
))
427 && TREE_OPERAND (TREE_OPERAND (incr
, 1), 0) == decl
)
431 tree t
= check_omp_for_incr_expr (elocus
,
432 TREE_OPERAND (incr
, 1),
434 if (t
!= error_mark_node
)
437 t
= build2 (PLUS_EXPR
, TREE_TYPE (decl
), decl
, t
);
438 incr
= build2 (MODIFY_EXPR
, void_type_node
, decl
, t
);
448 error_at (elocus
, "invalid increment expression");
453 TREE_VEC_ELT (initv
, i
) = init
;
454 TREE_VEC_ELT (incrv
, i
) = incr
;
461 tree t
= make_node (OMP_FOR
);
463 TREE_TYPE (t
) = void_type_node
;
464 OMP_FOR_INIT (t
) = initv
;
465 OMP_FOR_COND (t
) = condv
;
466 OMP_FOR_INCR (t
) = incrv
;
467 OMP_FOR_BODY (t
) = body
;
468 OMP_FOR_PRE_BODY (t
) = pre_body
;
470 SET_EXPR_LOCATION (t
, locus
);
476 /* Divide CLAUSES into two lists: those that apply to a parallel
477 construct, and those that apply to a work-sharing construct. Place
478 the results in *PAR_CLAUSES and *WS_CLAUSES respectively. In
479 addition, add a nowait clause to the work-sharing list. LOC is the
480 location of the OMP_PARALLEL*. */
483 c_split_parallel_clauses (location_t loc
, tree clauses
,
484 tree
*par_clauses
, tree
*ws_clauses
)
489 *ws_clauses
= build_omp_clause (loc
, OMP_CLAUSE_NOWAIT
);
491 for (; clauses
; clauses
= next
)
493 next
= OMP_CLAUSE_CHAIN (clauses
);
495 switch (OMP_CLAUSE_CODE (clauses
))
497 case OMP_CLAUSE_PRIVATE
:
498 case OMP_CLAUSE_SHARED
:
499 case OMP_CLAUSE_FIRSTPRIVATE
:
500 case OMP_CLAUSE_LASTPRIVATE
:
501 case OMP_CLAUSE_REDUCTION
:
502 case OMP_CLAUSE_COPYIN
:
504 case OMP_CLAUSE_NUM_THREADS
:
505 case OMP_CLAUSE_DEFAULT
:
506 OMP_CLAUSE_CHAIN (clauses
) = *par_clauses
;
507 *par_clauses
= clauses
;
510 case OMP_CLAUSE_SCHEDULE
:
511 case OMP_CLAUSE_ORDERED
:
512 case OMP_CLAUSE_COLLAPSE
:
513 OMP_CLAUSE_CHAIN (clauses
) = *ws_clauses
;
514 *ws_clauses
= clauses
;
523 /* True if OpenMP sharing attribute of DECL is predetermined. */
525 enum omp_clause_default_kind
526 c_omp_predetermined_sharing (tree decl
)
528 /* Variables with const-qualified type having no mutable member
529 are predetermined shared. */
530 if (TREE_READONLY (decl
))
531 return OMP_CLAUSE_DEFAULT_SHARED
;
533 return OMP_CLAUSE_DEFAULT_UNSPECIFIED
;