comparison gcc/c-omp.c @ 0:a06113de4d67

first commit
author kent <kent@cr.ie.u-ryukyu.ac.jp>
date Fri, 17 Jul 2009 14:47:48 +0900
parents
children 77e2b8dfacca
comparison
equal deleted inserted replaced
-1:000000000000 0:a06113de4d67
1 /* This file contains routines to construct GNU OpenMP constructs,
2 called from parsing in the C and C++ front ends.
3
4 Copyright (C) 2005, 2007, 2008, 2009 Free Software Foundation, Inc.
5 Contributed by Richard Henderson <rth@redhat.com>,
6 Diego Novillo <dnovillo@redhat.com>.
7
8 This file is part of GCC.
9
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
13 version.
14
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.
19
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/>. */
23
24 #include "config.h"
25 #include "system.h"
26 #include "coretypes.h"
27 #include "tm.h"
28 #include "tree.h"
29 #include "function.h"
30 #include "c-common.h"
31 #include "toplev.h"
32 #include "gimple.h"
33 #include "bitmap.h"
34 #include "langhooks.h"
35
36
37 /* Complete a #pragma omp master construct. STMT is the structured-block
38 that follows the pragma. */
39
40 tree
41 c_finish_omp_master (tree stmt)
42 {
43 return add_stmt (build1 (OMP_MASTER, void_type_node, stmt));
44 }
45
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
48 if it was omitted. */
49
50 tree
51 c_finish_omp_critical (tree body, tree name)
52 {
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);
58 }
59
60 /* Complete a #pragma omp ordered construct. STMT is the structured-block
61 that follows the pragma. */
62
63 tree
64 c_finish_omp_ordered (tree stmt)
65 {
66 return add_stmt (build1 (OMP_ORDERED, void_type_node, stmt));
67 }
68
69
70 /* Complete a #pragma omp barrier construct. */
71
72 void
73 c_finish_omp_barrier (void)
74 {
75 tree x;
76
77 x = built_in_decls[BUILT_IN_GOMP_BARRIER];
78 x = build_call_expr (x, 0);
79 add_stmt (x);
80 }
81
82
83 /* Complete a #pragma omp taskwait construct. */
84
85 void
86 c_finish_omp_taskwait (void)
87 {
88 tree x;
89
90 x = built_in_decls[BUILT_IN_GOMP_TASKWAIT];
91 x = build_call_expr (x, 0);
92 add_stmt (x);
93 }
94
95
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
100 with add_stmt. */
101
102 tree
103 c_finish_omp_atomic (enum tree_code code, tree lhs, tree rhs)
104 {
105 tree x, type, addr;
106
107 if (lhs == error_mark_node || rhs == error_mark_node)
108 return error_mark_node;
109
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))
118 {
119 error ("invalid expression type for %<#pragma omp atomic%>");
120 return error_mark_node;
121 }
122
123 /* ??? Validate that rhs does not overlap lhs. */
124
125 /* Take and save the address of the lhs. From then on we'll reference it
126 via indirection. */
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))
134 {
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);
139 }
140 lhs = build_indirect_ref (input_location, addr, NULL);
141
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);
150
151 /* Punt the actual generation of atomic operations to common code. */
152 return build2 (OMP_ATOMIC, void_type_node, addr, rhs);
153 }
154
155
156 /* Complete a #pragma omp flush construct. We don't do anything with the
157 variable list that the syntax allows. */
158
159 void
160 c_finish_omp_flush (void)
161 {
162 tree x;
163
164 x = built_in_decls[BUILT_IN_SYNCHRONIZE];
165 x = build_call_expr (x, 0);
166 add_stmt (x);
167 }
168
169
170 /* Check and canonicalize #pragma omp for increment expression.
171 Helper function for c_finish_omp_for. */
172
173 static tree
174 check_omp_for_incr_expr (tree exp, tree decl)
175 {
176 tree t;
177
178 if (!INTEGRAL_TYPE_P (TREE_TYPE (exp))
179 || TYPE_PRECISION (TREE_TYPE (exp)) < TYPE_PRECISION (TREE_TYPE (decl)))
180 return error_mark_node;
181
182 if (exp == decl)
183 return build_int_cst (TREE_TYPE (exp), 0);
184
185 switch (TREE_CODE (exp))
186 {
187 CASE_CONVERT:
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);
191 break;
192 case MINUS_EXPR:
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));
196 break;
197 case PLUS_EXPR:
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);
204 break;
205 default:
206 break;
207 }
208
209 return error_mark_node;
210 }
211
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
217 the loop. */
218
219 tree
220 c_finish_omp_for (location_t locus, tree declv, tree initv, tree condv,
221 tree incrv, tree body, tree pre_body)
222 {
223 location_t elocus;
224 bool fail = false;
225 int i;
226
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++)
231 {
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);
236
237 elocus = locus;
238 if (EXPR_HAS_LOCATION (init))
239 elocus = EXPR_LOCATION (init);
240
241 /* Validate the iteration variable. */
242 if (!INTEGRAL_TYPE_P (TREE_TYPE (decl))
243 && TREE_CODE (TREE_TYPE (decl)) != POINTER_TYPE)
244 {
245 error_at (elocus, "invalid type for iteration variable %qE", decl);
246 fail = true;
247 }
248
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. */
251 if (init == decl)
252 {
253 elocus = DECL_SOURCE_LOCATION (decl);
254
255 init = DECL_INITIAL (decl);
256 if (init == NULL)
257 {
258 error_at (elocus, "%qE is not initialized", decl);
259 init = integer_zero_node;
260 fail = true;
261 }
262
263 init = build_modify_expr (elocus, decl, NOP_EXPR, init);
264 }
265 gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
266 gcc_assert (TREE_OPERAND (init, 0) == decl);
267
268 if (cond == NULL_TREE)
269 {
270 error_at (elocus, "missing controlling predicate");
271 fail = true;
272 }
273 else
274 {
275 bool cond_ok = false;
276
277 if (EXPR_HAS_LOCATION (cond))
278 elocus = EXPR_LOCATION (cond);
279
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
284 || TREE_CODE (cond) == NE_EXPR)
285 {
286 tree op0 = TREE_OPERAND (cond, 0);
287 tree op1 = TREE_OPERAND (cond, 1);
288
289 /* 2.5.1. The comparison in the condition is computed in
290 the type of DECL, otherwise the behavior is undefined.
291
292 For example:
293 long n; int i;
294 i < n;
295
296 according to ISO will be evaluated as:
297 (long)i < n;
298
299 We want to force:
300 i < (int)n; */
301 if (TREE_CODE (op0) == NOP_EXPR
302 && decl == TREE_OPERAND (op0, 0))
303 {
304 TREE_OPERAND (cond, 0) = TREE_OPERAND (op0, 0);
305 TREE_OPERAND (cond, 1)
306 = fold_build1 (NOP_EXPR, TREE_TYPE (decl),
307 TREE_OPERAND (cond, 1));
308 }
309 else if (TREE_CODE (op1) == NOP_EXPR
310 && decl == TREE_OPERAND (op1, 0))
311 {
312 TREE_OPERAND (cond, 1) = TREE_OPERAND (op1, 0);
313 TREE_OPERAND (cond, 0)
314 = fold_build1 (NOP_EXPR, TREE_TYPE (decl),
315 TREE_OPERAND (cond, 0));
316 }
317
318 if (decl == TREE_OPERAND (cond, 0))
319 cond_ok = true;
320 else if (decl == TREE_OPERAND (cond, 1))
321 {
322 TREE_SET_CODE (cond,
323 swap_tree_comparison (TREE_CODE (cond)));
324 TREE_OPERAND (cond, 1) = TREE_OPERAND (cond, 0);
325 TREE_OPERAND (cond, 0) = decl;
326 cond_ok = true;
327 }
328
329 if (TREE_CODE (cond) == NE_EXPR)
330 {
331 if (!INTEGRAL_TYPE_P (TREE_TYPE (decl)))
332 cond_ok = false;
333 else if (operand_equal_p (TREE_OPERAND (cond, 1),
334 TYPE_MIN_VALUE (TREE_TYPE (decl)),
335 0))
336 TREE_SET_CODE (cond, GT_EXPR);
337 else if (operand_equal_p (TREE_OPERAND (cond, 1),
338 TYPE_MAX_VALUE (TREE_TYPE (decl)),
339 0))
340 TREE_SET_CODE (cond, LT_EXPR);
341 else
342 cond_ok = false;
343 }
344 }
345
346 if (!cond_ok)
347 {
348 error_at (elocus, "invalid controlling predicate");
349 fail = true;
350 }
351 }
352
353 if (incr == NULL_TREE)
354 {
355 error_at (elocus, "missing increment expression");
356 fail = true;
357 }
358 else
359 {
360 bool incr_ok = false;
361
362 if (EXPR_HAS_LOCATION (incr))
363 elocus = EXPR_LOCATION (incr);
364
365 /* Check all the valid increment expressions: v++, v--, ++v, --v,
366 v = v + incr, v = incr + v and v = v - incr. */
367 switch (TREE_CODE (incr))
368 {
369 case POSTINCREMENT_EXPR:
370 case PREINCREMENT_EXPR:
371 case POSTDECREMENT_EXPR:
372 case PREDECREMENT_EXPR:
373 if (TREE_OPERAND (incr, 0) != decl)
374 break;
375
376 incr_ok = true;
377 if (POINTER_TYPE_P (TREE_TYPE (decl))
378 && TREE_OPERAND (incr, 1))
379 {
380 tree t = fold_convert (sizetype, TREE_OPERAND (incr, 1));
381
382 if (TREE_CODE (incr) == POSTDECREMENT_EXPR
383 || TREE_CODE (incr) == PREDECREMENT_EXPR)
384 t = fold_build1 (NEGATE_EXPR, sizetype, t);
385 t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (decl), decl, t);
386 incr = build2 (MODIFY_EXPR, void_type_node, decl, t);
387 }
388 break;
389
390 case MODIFY_EXPR:
391 if (TREE_OPERAND (incr, 0) != decl)
392 break;
393 if (TREE_OPERAND (incr, 1) == decl)
394 break;
395 if (TREE_CODE (TREE_OPERAND (incr, 1)) == PLUS_EXPR
396 && (TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl
397 || TREE_OPERAND (TREE_OPERAND (incr, 1), 1) == decl))
398 incr_ok = true;
399 else if ((TREE_CODE (TREE_OPERAND (incr, 1)) == MINUS_EXPR
400 || (TREE_CODE (TREE_OPERAND (incr, 1))
401 == POINTER_PLUS_EXPR))
402 && TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl)
403 incr_ok = true;
404 else
405 {
406 tree t = check_omp_for_incr_expr (TREE_OPERAND (incr, 1),
407 decl);
408 if (t != error_mark_node)
409 {
410 incr_ok = true;
411 t = build2 (PLUS_EXPR, TREE_TYPE (decl), decl, t);
412 incr = build2 (MODIFY_EXPR, void_type_node, decl, t);
413 }
414 }
415 break;
416
417 default:
418 break;
419 }
420 if (!incr_ok)
421 {
422 error_at (elocus, "invalid increment expression");
423 fail = true;
424 }
425 }
426
427 TREE_VEC_ELT (initv, i) = init;
428 TREE_VEC_ELT (incrv, i) = incr;
429 }
430
431 if (fail)
432 return NULL;
433 else
434 {
435 tree t = make_node (OMP_FOR);
436
437 TREE_TYPE (t) = void_type_node;
438 OMP_FOR_INIT (t) = initv;
439 OMP_FOR_COND (t) = condv;
440 OMP_FOR_INCR (t) = incrv;
441 OMP_FOR_BODY (t) = body;
442 OMP_FOR_PRE_BODY (t) = pre_body;
443
444 SET_EXPR_LOCATION (t, locus);
445 return add_stmt (t);
446 }
447 }
448
449
450 /* Divide CLAUSES into two lists: those that apply to a parallel construct,
451 and those that apply to a work-sharing construct. Place the results in
452 *PAR_CLAUSES and *WS_CLAUSES respectively. In addition, add a nowait
453 clause to the work-sharing list. */
454
455 void
456 c_split_parallel_clauses (tree clauses, tree *par_clauses, tree *ws_clauses)
457 {
458 tree next;
459
460 *par_clauses = NULL;
461 *ws_clauses = build_omp_clause (OMP_CLAUSE_NOWAIT);
462
463 for (; clauses ; clauses = next)
464 {
465 next = OMP_CLAUSE_CHAIN (clauses);
466
467 switch (OMP_CLAUSE_CODE (clauses))
468 {
469 case OMP_CLAUSE_PRIVATE:
470 case OMP_CLAUSE_SHARED:
471 case OMP_CLAUSE_FIRSTPRIVATE:
472 case OMP_CLAUSE_LASTPRIVATE:
473 case OMP_CLAUSE_REDUCTION:
474 case OMP_CLAUSE_COPYIN:
475 case OMP_CLAUSE_IF:
476 case OMP_CLAUSE_NUM_THREADS:
477 case OMP_CLAUSE_DEFAULT:
478 OMP_CLAUSE_CHAIN (clauses) = *par_clauses;
479 *par_clauses = clauses;
480 break;
481
482 case OMP_CLAUSE_SCHEDULE:
483 case OMP_CLAUSE_ORDERED:
484 case OMP_CLAUSE_COLLAPSE:
485 OMP_CLAUSE_CHAIN (clauses) = *ws_clauses;
486 *ws_clauses = clauses;
487 break;
488
489 default:
490 gcc_unreachable ();
491 }
492 }
493 }
494
495 /* True if OpenMP sharing attribute of DECL is predetermined. */
496
497 enum omp_clause_default_kind
498 c_omp_predetermined_sharing (tree decl)
499 {
500 /* Variables with const-qualified type having no mutable member
501 are predetermined shared. */
502 if (TREE_READONLY (decl))
503 return OMP_CLAUSE_DEFAULT_SHARED;
504
505 return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
506 }