* runtime/fpu.c (_GNU_SOURCE): Don't define here.
[official-gcc.git] / gcc / c-omp.c
blobae8af595ecb2bfb0304d12f6a03d8fe677cc9766
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 /* Validate and emit code for the OpenMP directive #pragma omp for.
147 INIT, COND, INCR and BODY are the four basic elements of the loop
148 (initialization expression, controlling predicate, increment
149 expression and body of the loop). DECL is the iteration variable. */
151 tree
152 c_finish_omp_for (location_t locus, tree decl, tree init, tree cond,
153 tree incr, tree body)
155 location_t elocus = locus;
156 bool fail = false;
158 if (EXPR_HAS_LOCATION (init))
159 elocus = EXPR_LOCATION (init);
161 /* Validate the iteration variable. */
162 if (!INTEGRAL_TYPE_P (TREE_TYPE (decl)))
164 error ("%Hinvalid type for iteration variable %qE", &elocus, decl);
165 fail = true;
167 if (TYPE_UNSIGNED (TREE_TYPE (decl)))
168 warning (0, "%Hiteration variable %qE is unsigned", &elocus, decl);
170 /* In the case of "for (int i = 0...)", init will be a decl. It should
171 have a DECL_INITIAL that we can turn into an assignment. */
172 if (init == decl)
174 elocus = DECL_SOURCE_LOCATION (decl);
176 init = DECL_INITIAL (decl);
177 if (init == NULL)
179 error ("%H%qE is not initialized", &elocus, decl);
180 init = integer_zero_node;
181 fail = true;
184 init = build_modify_expr (decl, NOP_EXPR, init);
185 SET_EXPR_LOCATION (init, elocus);
187 gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
188 gcc_assert (TREE_OPERAND (init, 0) == decl);
190 if (cond == NULL_TREE)
192 error ("%Hmissing controlling predicate", &elocus);
193 fail = true;
195 else
197 bool cond_ok = false;
199 if (EXPR_HAS_LOCATION (cond))
200 elocus = EXPR_LOCATION (cond);
202 if (TREE_CODE (cond) == LT_EXPR
203 || TREE_CODE (cond) == LE_EXPR
204 || TREE_CODE (cond) == GT_EXPR
205 || TREE_CODE (cond) == GE_EXPR)
207 if (decl == TREE_OPERAND (cond, 0))
208 cond_ok = true;
209 else if (decl == TREE_OPERAND (cond, 1))
211 TREE_SET_CODE (cond, swap_tree_comparison (TREE_CODE (cond)));
212 TREE_OPERAND (cond, 1) = TREE_OPERAND (cond, 0);
213 TREE_OPERAND (cond, 0) = decl;
214 cond_ok = true;
218 if (!cond_ok)
220 error ("%Hinvalid controlling predicate", &elocus);
221 fail = true;
225 if (incr == NULL_TREE)
227 error ("%Hmissing increment expression", &elocus);
228 fail = true;
230 else
232 bool incr_ok = false;
234 if (EXPR_HAS_LOCATION (incr))
235 elocus = EXPR_LOCATION (incr);
237 /* Check all the valid increment expressions: v++, v--, ++v, --v,
238 v = v + incr, v = incr + v and v = v - incr. */
239 switch (TREE_CODE (incr))
241 case POSTINCREMENT_EXPR:
242 case PREINCREMENT_EXPR:
243 case POSTDECREMENT_EXPR:
244 case PREDECREMENT_EXPR:
245 incr_ok = (TREE_OPERAND (incr, 0) == decl);
246 break;
248 case MODIFY_EXPR:
249 if (TREE_CODE (TREE_OPERAND (incr, 1)) == PLUS_EXPR
250 && (TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl
251 || TREE_OPERAND (TREE_OPERAND (incr, 1), 1) == decl))
252 incr_ok = true;
253 else if (TREE_CODE (TREE_OPERAND (incr, 1)) == MINUS_EXPR
254 && TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl)
255 incr_ok = true;
256 break;
258 default:
259 break;
261 if (!incr_ok)
263 error ("%Hinvalid increment expression", &elocus);
264 fail = true;
268 if (fail)
269 return NULL;
270 else
272 tree t = make_node (OMP_FOR);
274 TREE_TYPE (t) = void_type_node;
275 OMP_FOR_INIT (t) = init;
276 OMP_FOR_COND (t) = cond;
277 OMP_FOR_INCR (t) = incr;
278 OMP_FOR_BODY (t) = body;
280 SET_EXPR_LOCATION (t, locus);
281 return add_stmt (t);
286 /* Divide CLAUSES into two lists: those that apply to a parallel construct,
287 and those that apply to a work-sharing construct. Place the results in
288 *PAR_CLAUSES and *WS_CLAUSES respectively. In addition, add a nowait
289 clause to the work-sharing list. */
291 void
292 c_split_parallel_clauses (tree clauses, tree *par_clauses, tree *ws_clauses)
294 tree next;
296 *par_clauses = NULL;
297 *ws_clauses = make_node (OMP_CLAUSE_NOWAIT);
299 for (; clauses ; clauses = next)
301 next = OMP_CLAUSE_CHAIN (clauses);
303 switch (TREE_CODE (clauses))
305 case OMP_CLAUSE_PRIVATE:
306 case OMP_CLAUSE_SHARED:
307 case OMP_CLAUSE_FIRSTPRIVATE:
308 case OMP_CLAUSE_LASTPRIVATE:
309 case OMP_CLAUSE_REDUCTION:
310 case OMP_CLAUSE_COPYIN:
311 case OMP_CLAUSE_IF:
312 case OMP_CLAUSE_NUM_THREADS:
313 case OMP_CLAUSE_DEFAULT:
314 OMP_CLAUSE_CHAIN (clauses) = *par_clauses;
315 *par_clauses = clauses;
316 break;
318 case OMP_CLAUSE_SCHEDULE:
319 case OMP_CLAUSE_ORDERED:
320 OMP_CLAUSE_CHAIN (clauses) = *ws_clauses;
321 *ws_clauses = clauses;
322 break;
324 default:
325 gcc_unreachable ();
330 /* True if OpenMP sharing attribute of DECL is predetermined. */
332 enum omp_clause_default_kind
333 c_omp_predetermined_sharing (tree decl)
335 /* Variables with const-qualified type having no mutable member
336 are predetermined shared. */
337 if (TREE_READONLY (decl))
338 return OMP_CLAUSE_DEFAULT_SHARED;
340 return OMP_CLAUSE_DEFAULT_UNSPECIFIED;