2006-08-07 Andrew John Hughes <gnu_andrew@member.fsf.org>
[official-gcc.git] / gcc / c-omp.c
blobac107e6773743c8b0f7408f24ce8ac942251f626
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
13 version.
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.
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
23 02110-1301, USA. */
25 #include "config.h"
26 #include "system.h"
27 #include "coretypes.h"
28 #include "tm.h"
29 #include "tree.h"
30 #include "function.h"
31 #include "c-common.h"
32 #include "toplev.h"
33 #include "tree-gimple.h"
34 #include "bitmap.h"
35 #include "langhooks.h"
38 /* Complete a #pragma omp master construct. STMT is the structured-block
39 that follows the pragma. */
41 tree
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
49 if it was omitted. */
51 tree
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. */
64 tree
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. */
73 void
74 c_finish_omp_barrier (void)
76 tree x;
78 x = built_in_decls[BUILT_IN_GOMP_BARRIER];
79 x = build_function_call_expr (x, NULL);
80 add_stmt (x);
84 /* Complete a #pragma omp atomic construct. The expression to be
85 implemented atomically is LHS code= RHS. */
87 void
88 c_finish_omp_atomic (enum tree_code code, tree lhs, tree rhs)
90 tree x, type, addr;
92 if (lhs == error_mark_node || rhs == error_mark_node)
93 return;
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%>");
105 return;
108 /* ??? Validate that rhs does not overlap lhs. */
110 /* Take and save the address of the lhs. From then on we'll reference it
111 via indirection. */
112 addr = build_unary_op (ADDR_EXPR, lhs, 0);
113 if (addr == error_mark_node)
114 return;
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)
123 return;
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. */
135 void
136 c_finish_omp_flush (void)
138 tree x;
140 x = built_in_decls[BUILT_IN_SYNCHRONIZE];
141 x = build_function_call_expr (x, NULL);
142 add_stmt (x);
146 /* Check and canonicalize #pragma omp for increment expression.
147 Helper function for c_finish_omp_for. */
149 static tree
150 check_omp_for_incr_expr (tree exp, tree decl)
152 tree t;
154 if (!INTEGRAL_TYPE_P (TREE_TYPE (exp))
155 || TYPE_PRECISION (TREE_TYPE (exp)) < TYPE_PRECISION (TREE_TYPE (decl)))
156 return error_mark_node;
158 if (exp == decl)
159 return build_int_cst (TREE_TYPE (exp), 0);
161 switch (TREE_CODE (exp))
163 case NOP_EXPR:
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);
167 break;
168 case MINUS_EXPR:
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));
172 break;
173 case PLUS_EXPR:
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);
180 break;
181 default:
182 break;
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. */
194 tree
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;
199 bool fail = false;
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);
208 fail = true;
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. */
215 if (init == decl)
217 elocus = DECL_SOURCE_LOCATION (decl);
219 init = DECL_INITIAL (decl);
220 if (init == NULL)
222 error ("%H%qE is not initialized", &elocus, decl);
223 init = integer_zero_node;
224 fail = true;
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);
236 fail = true;
238 else
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.
256 For example:
257 long n; int i;
258 i < n;
260 according to ISO will be evaluated as:
261 (long)i < n;
263 We want to force:
264 i < (int)n; */
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))
281 cond_ok = true;
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;
287 cond_ok = true;
291 if (!cond_ok)
293 error ("%Hinvalid controlling predicate", &elocus);
294 fail = true;
298 if (incr == NULL_TREE)
300 error ("%Hmissing increment expression", &elocus);
301 fail = true;
303 else
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);
319 break;
321 case MODIFY_EXPR:
322 if (TREE_OPERAND (incr, 0) != decl)
323 break;
324 if (TREE_OPERAND (incr, 1) == decl)
325 break;
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))
329 incr_ok = true;
330 else if (TREE_CODE (TREE_OPERAND (incr, 1)) == MINUS_EXPR
331 && TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl)
332 incr_ok = true;
333 else
335 tree t = check_omp_for_incr_expr (TREE_OPERAND (incr, 1), decl);
336 if (t != error_mark_node)
338 incr_ok = true;
339 t = build2 (PLUS_EXPR, TREE_TYPE (decl), decl, t);
340 incr = build2 (MODIFY_EXPR, void_type_node, decl, t);
343 break;
345 default:
346 break;
348 if (!incr_ok)
350 error ("%Hinvalid increment expression", &elocus);
351 fail = true;
355 if (fail)
356 return NULL;
357 else
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);
369 return add_stmt (t);
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. */
379 void
380 c_split_parallel_clauses (tree clauses, tree *par_clauses, tree *ws_clauses)
382 tree next;
384 *par_clauses = NULL;
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:
399 case OMP_CLAUSE_IF:
400 case OMP_CLAUSE_NUM_THREADS:
401 case OMP_CLAUSE_DEFAULT:
402 OMP_CLAUSE_CHAIN (clauses) = *par_clauses;
403 *par_clauses = clauses;
404 break;
406 case OMP_CLAUSE_SCHEDULE:
407 case OMP_CLAUSE_ORDERED:
408 OMP_CLAUSE_CHAIN (clauses) = *ws_clauses;
409 *ws_clauses = clauses;
410 break;
412 default:
413 gcc_unreachable ();
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;