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 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 2, 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 COPYING. If not, write to the Free
22 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
27 #include "coretypes.h"
33 #include "tree-gimple.h"
35 #include "langhooks.h"
38 /* Complete a #pragma omp master construct. STMT is the structured-block
39 that follows the pragma. */
42 c_finish_omp_master (tree stmt
)
44 return add_stmt (build1 (OMP_MASTER
, void_type_node
, stmt
));
47 /* Complete a #pragma omp critical construct. STMT is the structured-block
48 that follows the pragma, NAME is the identifier in the pragma, or null
52 c_finish_omp_critical (tree body
, tree name
)
54 tree stmt
= make_node (OMP_CRITICAL
);
55 TREE_TYPE (stmt
) = void_type_node
;
56 OMP_CRITICAL_BODY (stmt
) = body
;
57 OMP_CRITICAL_NAME (stmt
) = name
;
58 return add_stmt (stmt
);
61 /* Complete a #pragma omp ordered construct. STMT is the structured-block
62 that follows the pragma. */
65 c_finish_omp_ordered (tree stmt
)
67 return add_stmt (build1 (OMP_ORDERED
, void_type_node
, stmt
));
71 /* Complete a #pragma omp barrier construct. */
74 c_finish_omp_barrier (void)
78 x
= built_in_decls
[BUILT_IN_GOMP_BARRIER
];
79 x
= build_function_call_expr (x
, NULL
);
84 /* Complete a #pragma omp atomic construct. The expression to be
85 implemented atomically is LHS code= RHS. */
88 c_finish_omp_atomic (enum tree_code code
, tree lhs
, tree rhs
)
92 if (lhs
== error_mark_node
|| rhs
== error_mark_node
)
95 /* ??? According to one reading of the OpenMP spec, complex type are
96 supported, but there are no atomic stores for any architecture.
97 But at least icc 9.0 doesn't support complex types here either.
98 And lets not even talk about vector types... */
99 type
= TREE_TYPE (lhs
);
100 if (!INTEGRAL_TYPE_P (type
)
101 && !POINTER_TYPE_P (type
)
102 && !SCALAR_FLOAT_TYPE_P (type
))
104 error ("invalid expression type for %<#pragma omp atomic%>");
108 /* ??? Validate that rhs does not overlap lhs. */
110 /* Take and save the address of the lhs. From then on we'll reference it
112 addr
= build_unary_op (ADDR_EXPR
, lhs
, 0);
113 if (addr
== error_mark_node
)
115 addr
= save_expr (addr
);
116 lhs
= build_indirect_ref (addr
, NULL
);
118 /* There are lots of warnings, errors, and conversions that need to happen
119 in the course of interpreting a statement. Use the normal mechanisms
120 to do this, and then take it apart again. */
121 x
= build_modify_expr (lhs
, code
, rhs
);
122 if (x
== error_mark_node
)
124 gcc_assert (TREE_CODE (x
) == MODIFY_EXPR
);
125 rhs
= TREE_OPERAND (x
, 1);
127 /* Punt the actual generation of atomic operations to common code. */
128 add_stmt (build2 (OMP_ATOMIC
, void_type_node
, addr
, rhs
));
132 /* Complete a #pragma omp flush construct. We don't do anything with the
133 variable list that the syntax allows. */
136 c_finish_omp_flush (void)
140 x
= built_in_decls
[BUILT_IN_SYNCHRONIZE
];
141 x
= build_function_call_expr (x
, NULL
);
146 /* Check and canonicalize #pragma omp for increment expression.
147 Helper function for c_finish_omp_for. */
150 check_omp_for_incr_expr (tree exp
, tree decl
)
154 if (!INTEGRAL_TYPE_P (TREE_TYPE (exp
))
155 || TYPE_PRECISION (TREE_TYPE (exp
)) < TYPE_PRECISION (TREE_TYPE (decl
)))
156 return error_mark_node
;
159 return build_int_cst (TREE_TYPE (exp
), 0);
161 switch (TREE_CODE (exp
))
164 t
= check_omp_for_incr_expr (TREE_OPERAND (exp
, 0), decl
);
165 if (t
!= error_mark_node
)
166 return fold_convert (TREE_TYPE (exp
), t
);
169 t
= check_omp_for_incr_expr (TREE_OPERAND (exp
, 0), decl
);
170 if (t
!= error_mark_node
)
171 return fold_build2 (MINUS_EXPR
, TREE_TYPE (exp
), t
, TREE_OPERAND (exp
, 1));
174 t
= check_omp_for_incr_expr (TREE_OPERAND (exp
, 0), decl
);
175 if (t
!= error_mark_node
)
176 return fold_build2 (PLUS_EXPR
, TREE_TYPE (exp
), t
, TREE_OPERAND (exp
, 1));
177 t
= check_omp_for_incr_expr (TREE_OPERAND (exp
, 1), decl
);
178 if (t
!= error_mark_node
)
179 return fold_build2 (PLUS_EXPR
, TREE_TYPE (exp
), TREE_OPERAND (exp
, 0), t
);
185 return error_mark_node
;
188 /* Validate and emit code for the OpenMP directive #pragma omp for.
189 INIT, COND, INCR, BODY and PRE_BODY are the five basic elements
190 of the loop (initialization expression, controlling predicate, increment
191 expression, body of the loop and statements to go before the loop).
192 DECL is the iteration variable. */
195 c_finish_omp_for (location_t locus
, tree decl
, tree init
, tree cond
,
196 tree incr
, tree body
, tree pre_body
)
198 location_t elocus
= locus
;
201 if (EXPR_HAS_LOCATION (init
))
202 elocus
= EXPR_LOCATION (init
);
204 /* Validate the iteration variable. */
205 if (!INTEGRAL_TYPE_P (TREE_TYPE (decl
)))
207 error ("%Hinvalid type for iteration variable %qE", &elocus
, decl
);
210 if (TYPE_UNSIGNED (TREE_TYPE (decl
)))
211 warning (0, "%Hiteration variable %qE is unsigned", &elocus
, decl
);
213 /* In the case of "for (int i = 0...)", init will be a decl. It should
214 have a DECL_INITIAL that we can turn into an assignment. */
217 elocus
= DECL_SOURCE_LOCATION (decl
);
219 init
= DECL_INITIAL (decl
);
222 error ("%H%qE is not initialized", &elocus
, decl
);
223 init
= integer_zero_node
;
227 init
= build_modify_expr (decl
, NOP_EXPR
, init
);
228 SET_EXPR_LOCATION (init
, elocus
);
230 gcc_assert (TREE_CODE (init
) == MODIFY_EXPR
);
231 gcc_assert (TREE_OPERAND (init
, 0) == decl
);
233 if (cond
== NULL_TREE
)
235 error ("%Hmissing controlling predicate", &elocus
);
240 bool cond_ok
= false;
242 if (EXPR_HAS_LOCATION (cond
))
243 elocus
= EXPR_LOCATION (cond
);
245 if (TREE_CODE (cond
) == LT_EXPR
246 || TREE_CODE (cond
) == LE_EXPR
247 || TREE_CODE (cond
) == GT_EXPR
248 || TREE_CODE (cond
) == GE_EXPR
)
250 tree op0
= TREE_OPERAND (cond
, 0);
251 tree op1
= TREE_OPERAND (cond
, 1);
253 /* 2.5.1. The comparison in the condition is computed in the type
254 of DECL, otherwise the behavior is undefined.
260 according to ISO will be evaluated as:
265 if (TREE_CODE (op0
) == NOP_EXPR
266 && decl
== TREE_OPERAND (op0
, 0))
268 TREE_OPERAND (cond
, 0) = TREE_OPERAND (op0
, 0);
269 TREE_OPERAND (cond
, 1) = fold_build1 (NOP_EXPR
, TREE_TYPE (decl
),
270 TREE_OPERAND (cond
, 1));
272 else if (TREE_CODE (op1
) == NOP_EXPR
273 && decl
== TREE_OPERAND (op1
, 0))
275 TREE_OPERAND (cond
, 1) = TREE_OPERAND (op1
, 0);
276 TREE_OPERAND (cond
, 0) = fold_build1 (NOP_EXPR
, TREE_TYPE (decl
),
277 TREE_OPERAND (cond
, 0));
280 if (decl
== TREE_OPERAND (cond
, 0))
282 else if (decl
== TREE_OPERAND (cond
, 1))
284 TREE_SET_CODE (cond
, swap_tree_comparison (TREE_CODE (cond
)));
285 TREE_OPERAND (cond
, 1) = TREE_OPERAND (cond
, 0);
286 TREE_OPERAND (cond
, 0) = decl
;
293 error ("%Hinvalid controlling predicate", &elocus
);
298 if (incr
== NULL_TREE
)
300 error ("%Hmissing increment expression", &elocus
);
305 bool incr_ok
= false;
307 if (EXPR_HAS_LOCATION (incr
))
308 elocus
= EXPR_LOCATION (incr
);
310 /* Check all the valid increment expressions: v++, v--, ++v, --v,
311 v = v + incr, v = incr + v and v = v - incr. */
312 switch (TREE_CODE (incr
))
314 case POSTINCREMENT_EXPR
:
315 case PREINCREMENT_EXPR
:
316 case POSTDECREMENT_EXPR
:
317 case PREDECREMENT_EXPR
:
318 incr_ok
= (TREE_OPERAND (incr
, 0) == decl
);
322 if (TREE_OPERAND (incr
, 0) != decl
)
324 if (TREE_OPERAND (incr
, 1) == decl
)
326 if (TREE_CODE (TREE_OPERAND (incr
, 1)) == PLUS_EXPR
327 && (TREE_OPERAND (TREE_OPERAND (incr
, 1), 0) == decl
328 || TREE_OPERAND (TREE_OPERAND (incr
, 1), 1) == decl
))
330 else if (TREE_CODE (TREE_OPERAND (incr
, 1)) == MINUS_EXPR
331 && TREE_OPERAND (TREE_OPERAND (incr
, 1), 0) == decl
)
335 tree t
= check_omp_for_incr_expr (TREE_OPERAND (incr
, 1), decl
);
336 if (t
!= error_mark_node
)
339 t
= build2 (PLUS_EXPR
, TREE_TYPE (decl
), decl
, t
);
340 incr
= build2 (MODIFY_EXPR
, void_type_node
, decl
, t
);
350 error ("%Hinvalid increment expression", &elocus
);
359 tree t
= make_node (OMP_FOR
);
361 TREE_TYPE (t
) = void_type_node
;
362 OMP_FOR_INIT (t
) = init
;
363 OMP_FOR_COND (t
) = cond
;
364 OMP_FOR_INCR (t
) = incr
;
365 OMP_FOR_BODY (t
) = body
;
366 OMP_FOR_PRE_BODY (t
) = pre_body
;
368 SET_EXPR_LOCATION (t
, locus
);
374 /* Divide CLAUSES into two lists: those that apply to a parallel construct,
375 and those that apply to a work-sharing construct. Place the results in
376 *PAR_CLAUSES and *WS_CLAUSES respectively. In addition, add a nowait
377 clause to the work-sharing list. */
380 c_split_parallel_clauses (tree clauses
, tree
*par_clauses
, tree
*ws_clauses
)
385 *ws_clauses
= build_omp_clause (OMP_CLAUSE_NOWAIT
);
387 for (; clauses
; clauses
= next
)
389 next
= OMP_CLAUSE_CHAIN (clauses
);
391 switch (OMP_CLAUSE_CODE (clauses
))
393 case OMP_CLAUSE_PRIVATE
:
394 case OMP_CLAUSE_SHARED
:
395 case OMP_CLAUSE_FIRSTPRIVATE
:
396 case OMP_CLAUSE_LASTPRIVATE
:
397 case OMP_CLAUSE_REDUCTION
:
398 case OMP_CLAUSE_COPYIN
:
400 case OMP_CLAUSE_NUM_THREADS
:
401 case OMP_CLAUSE_DEFAULT
:
402 OMP_CLAUSE_CHAIN (clauses
) = *par_clauses
;
403 *par_clauses
= clauses
;
406 case OMP_CLAUSE_SCHEDULE
:
407 case OMP_CLAUSE_ORDERED
:
408 OMP_CLAUSE_CHAIN (clauses
) = *ws_clauses
;
409 *ws_clauses
= clauses
;
418 /* True if OpenMP sharing attribute of DECL is predetermined. */
420 enum omp_clause_default_kind
421 c_omp_predetermined_sharing (tree decl
)
423 /* Variables with const-qualified type having no mutable member
424 are predetermined shared. */
425 if (TREE_READONLY (decl
))
426 return OMP_CLAUSE_DEFAULT_SHARED
;
428 return OMP_CLAUSE_DEFAULT_UNSPECIFIED
;