comparison gcc/c-family/c-omp.c @ 68:561a7518be6b

update gcc-4.6
author Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
date Sun, 21 Aug 2011 07:07:55 +0900
parents
children 04ced10e8804
comparison
equal deleted inserted replaced
67:f6334be47118 68:561a7518be6b
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, 2010 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 "tree.h"
28 #include "c-common.h"
29 #include "gimple.h" /* For create_tmp_var_raw. */
30 #include "langhooks.h"
31
32
33 /* Complete a #pragma omp master construct. STMT is the structured-block
34 that follows the pragma. LOC is the l*/
35
36 tree
37 c_finish_omp_master (location_t loc, tree stmt)
38 {
39 tree t = add_stmt (build1 (OMP_MASTER, void_type_node, stmt));
40 SET_EXPR_LOCATION (t, loc);
41 return t;
42 }
43
44 /* Complete a #pragma omp critical construct. STMT is the structured-block
45 that follows the pragma, NAME is the identifier in the pragma, or null
46 if it was omitted. LOC is the location of the #pragma. */
47
48 tree
49 c_finish_omp_critical (location_t loc, tree body, tree name)
50 {
51 tree stmt = make_node (OMP_CRITICAL);
52 TREE_TYPE (stmt) = void_type_node;
53 OMP_CRITICAL_BODY (stmt) = body;
54 OMP_CRITICAL_NAME (stmt) = name;
55 SET_EXPR_LOCATION (stmt, loc);
56 return add_stmt (stmt);
57 }
58
59 /* Complete a #pragma omp ordered construct. STMT is the structured-block
60 that follows the pragma. LOC is the location of the #pragma. */
61
62 tree
63 c_finish_omp_ordered (location_t loc, tree stmt)
64 {
65 tree t = build1 (OMP_ORDERED, void_type_node, stmt);
66 SET_EXPR_LOCATION (t, loc);
67 return add_stmt (t);
68 }
69
70
71 /* Complete a #pragma omp barrier construct. LOC is the location of
72 the #pragma. */
73
74 void
75 c_finish_omp_barrier (location_t loc)
76 {
77 tree x;
78
79 x = built_in_decls[BUILT_IN_GOMP_BARRIER];
80 x = build_call_expr_loc (loc, x, 0);
81 add_stmt (x);
82 }
83
84
85 /* Complete a #pragma omp taskwait construct. LOC is the location of the
86 pragma. */
87
88 void
89 c_finish_omp_taskwait (location_t loc)
90 {
91 tree x;
92
93 x = built_in_decls[BUILT_IN_GOMP_TASKWAIT];
94 x = build_call_expr_loc (loc, x, 0);
95 add_stmt (x);
96 }
97
98
99 /* Complete a #pragma omp atomic construct. The expression to be
100 implemented atomically is LHS code= RHS. LOC is the location of
101 the atomic statement. The value returned is either error_mark_node
102 (if the construct was erroneous) or an OMP_ATOMIC node which should
103 be added to the current statement tree with add_stmt.*/
104
105 tree
106 c_finish_omp_atomic (location_t loc, enum tree_code code, tree lhs, tree rhs)
107 {
108 tree x, type, addr;
109
110 if (lhs == error_mark_node || rhs == error_mark_node)
111 return error_mark_node;
112
113 /* ??? According to one reading of the OpenMP spec, complex type are
114 supported, but there are no atomic stores for any architecture.
115 But at least icc 9.0 doesn't support complex types here either.
116 And lets not even talk about vector types... */
117 type = TREE_TYPE (lhs);
118 if (!INTEGRAL_TYPE_P (type)
119 && !POINTER_TYPE_P (type)
120 && !SCALAR_FLOAT_TYPE_P (type))
121 {
122 error_at (loc, "invalid expression type for %<#pragma omp atomic%>");
123 return error_mark_node;
124 }
125
126 /* ??? Validate that rhs does not overlap lhs. */
127
128 /* Take and save the address of the lhs. From then on we'll reference it
129 via indirection. */
130 addr = build_unary_op (loc, ADDR_EXPR, lhs, 0);
131 if (addr == error_mark_node)
132 return error_mark_node;
133 addr = save_expr (addr);
134 if (TREE_CODE (addr) != SAVE_EXPR
135 && (TREE_CODE (addr) != ADDR_EXPR
136 || TREE_CODE (TREE_OPERAND (addr, 0)) != VAR_DECL))
137 {
138 /* Make sure LHS is simple enough so that goa_lhs_expr_p can recognize
139 it even after unsharing function body. */
140 tree var = create_tmp_var_raw (TREE_TYPE (addr), NULL);
141 DECL_CONTEXT (var) = current_function_decl;
142 addr = build4 (TARGET_EXPR, TREE_TYPE (addr), var, addr, NULL, NULL);
143 }
144 lhs = build_indirect_ref (loc, addr, RO_NULL);
145
146 /* There are lots of warnings, errors, and conversions that need to happen
147 in the course of interpreting a statement. Use the normal mechanisms
148 to do this, and then take it apart again. */
149 x = build_modify_expr (input_location, lhs, NULL_TREE, code,
150 input_location, rhs, NULL_TREE);
151 if (x == error_mark_node)
152 return error_mark_node;
153 gcc_assert (TREE_CODE (x) == MODIFY_EXPR);
154 rhs = TREE_OPERAND (x, 1);
155
156 /* Punt the actual generation of atomic operations to common code. */
157 x = build2 (OMP_ATOMIC, void_type_node, addr, rhs);
158 SET_EXPR_LOCATION (x, loc);
159 return x;
160 }
161
162
163 /* Complete a #pragma omp flush construct. We don't do anything with
164 the variable list that the syntax allows. LOC is the location of
165 the #pragma. */
166
167 void
168 c_finish_omp_flush (location_t loc)
169 {
170 tree x;
171
172 x = built_in_decls[BUILT_IN_SYNCHRONIZE];
173 x = build_call_expr_loc (loc, x, 0);
174 add_stmt (x);
175 }
176
177
178 /* Check and canonicalize #pragma omp for increment expression.
179 Helper function for c_finish_omp_for. */
180
181 static tree
182 check_omp_for_incr_expr (location_t loc, tree exp, tree decl)
183 {
184 tree t;
185
186 if (!INTEGRAL_TYPE_P (TREE_TYPE (exp))
187 || TYPE_PRECISION (TREE_TYPE (exp)) < TYPE_PRECISION (TREE_TYPE (decl)))
188 return error_mark_node;
189
190 if (exp == decl)
191 return build_int_cst (TREE_TYPE (exp), 0);
192
193 switch (TREE_CODE (exp))
194 {
195 CASE_CONVERT:
196 t = check_omp_for_incr_expr (loc, TREE_OPERAND (exp, 0), decl);
197 if (t != error_mark_node)
198 return fold_convert_loc (loc, TREE_TYPE (exp), t);
199 break;
200 case MINUS_EXPR:
201 t = check_omp_for_incr_expr (loc, TREE_OPERAND (exp, 0), decl);
202 if (t != error_mark_node)
203 return fold_build2_loc (loc, MINUS_EXPR,
204 TREE_TYPE (exp), t, TREE_OPERAND (exp, 1));
205 break;
206 case PLUS_EXPR:
207 t = check_omp_for_incr_expr (loc, TREE_OPERAND (exp, 0), decl);
208 if (t != error_mark_node)
209 return fold_build2_loc (loc, PLUS_EXPR,
210 TREE_TYPE (exp), t, TREE_OPERAND (exp, 1));
211 t = check_omp_for_incr_expr (loc, TREE_OPERAND (exp, 1), decl);
212 if (t != error_mark_node)
213 return fold_build2_loc (loc, PLUS_EXPR,
214 TREE_TYPE (exp), TREE_OPERAND (exp, 0), t);
215 break;
216 default:
217 break;
218 }
219
220 return error_mark_node;
221 }
222
223 /* Validate and emit code for the OpenMP directive #pragma omp for.
224 DECLV is a vector of iteration variables, for each collapsed loop.
225 INITV, CONDV and INCRV are vectors containing initialization
226 expressions, controlling predicates and increment expressions.
227 BODY is the body of the loop and PRE_BODY statements that go before
228 the loop. */
229
230 tree
231 c_finish_omp_for (location_t locus, tree declv, tree initv, tree condv,
232 tree incrv, tree body, tree pre_body)
233 {
234 location_t elocus;
235 bool fail = false;
236 int i;
237
238 gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (initv));
239 gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (condv));
240 gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (incrv));
241 for (i = 0; i < TREE_VEC_LENGTH (declv); i++)
242 {
243 tree decl = TREE_VEC_ELT (declv, i);
244 tree init = TREE_VEC_ELT (initv, i);
245 tree cond = TREE_VEC_ELT (condv, i);
246 tree incr = TREE_VEC_ELT (incrv, i);
247
248 elocus = locus;
249 if (EXPR_HAS_LOCATION (init))
250 elocus = EXPR_LOCATION (init);
251
252 /* Validate the iteration variable. */
253 if (!INTEGRAL_TYPE_P (TREE_TYPE (decl))
254 && TREE_CODE (TREE_TYPE (decl)) != POINTER_TYPE)
255 {
256 error_at (elocus, "invalid type for iteration variable %qE", decl);
257 fail = true;
258 }
259
260 /* In the case of "for (int i = 0...)", init will be a decl. It should
261 have a DECL_INITIAL that we can turn into an assignment. */
262 if (init == decl)
263 {
264 elocus = DECL_SOURCE_LOCATION (decl);
265
266 init = DECL_INITIAL (decl);
267 if (init == NULL)
268 {
269 error_at (elocus, "%qE is not initialized", decl);
270 init = integer_zero_node;
271 fail = true;
272 }
273
274 init = build_modify_expr (elocus, decl, NULL_TREE, NOP_EXPR,
275 /* FIXME diagnostics: This should
276 be the location of the INIT. */
277 elocus,
278 init,
279 NULL_TREE);
280 }
281 gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
282 gcc_assert (TREE_OPERAND (init, 0) == decl);
283
284 if (cond == NULL_TREE)
285 {
286 error_at (elocus, "missing controlling predicate");
287 fail = true;
288 }
289 else
290 {
291 bool cond_ok = false;
292
293 if (EXPR_HAS_LOCATION (cond))
294 elocus = EXPR_LOCATION (cond);
295
296 if (TREE_CODE (cond) == LT_EXPR
297 || TREE_CODE (cond) == LE_EXPR
298 || TREE_CODE (cond) == GT_EXPR
299 || TREE_CODE (cond) == GE_EXPR
300 || TREE_CODE (cond) == NE_EXPR
301 || TREE_CODE (cond) == EQ_EXPR)
302 {
303 tree op0 = TREE_OPERAND (cond, 0);
304 tree op1 = TREE_OPERAND (cond, 1);
305
306 /* 2.5.1. The comparison in the condition is computed in
307 the type of DECL, otherwise the behavior is undefined.
308
309 For example:
310 long n; int i;
311 i < n;
312
313 according to ISO will be evaluated as:
314 (long)i < n;
315
316 We want to force:
317 i < (int)n; */
318 if (TREE_CODE (op0) == NOP_EXPR
319 && decl == TREE_OPERAND (op0, 0))
320 {
321 TREE_OPERAND (cond, 0) = TREE_OPERAND (op0, 0);
322 TREE_OPERAND (cond, 1)
323 = fold_build1_loc (elocus, NOP_EXPR, TREE_TYPE (decl),
324 TREE_OPERAND (cond, 1));
325 }
326 else if (TREE_CODE (op1) == NOP_EXPR
327 && decl == TREE_OPERAND (op1, 0))
328 {
329 TREE_OPERAND (cond, 1) = TREE_OPERAND (op1, 0);
330 TREE_OPERAND (cond, 0)
331 = fold_build1_loc (elocus, NOP_EXPR, TREE_TYPE (decl),
332 TREE_OPERAND (cond, 0));
333 }
334
335 if (decl == TREE_OPERAND (cond, 0))
336 cond_ok = true;
337 else if (decl == TREE_OPERAND (cond, 1))
338 {
339 TREE_SET_CODE (cond,
340 swap_tree_comparison (TREE_CODE (cond)));
341 TREE_OPERAND (cond, 1) = TREE_OPERAND (cond, 0);
342 TREE_OPERAND (cond, 0) = decl;
343 cond_ok = true;
344 }
345
346 if (TREE_CODE (cond) == NE_EXPR
347 || TREE_CODE (cond) == EQ_EXPR)
348 {
349 if (!INTEGRAL_TYPE_P (TREE_TYPE (decl)))
350 cond_ok = false;
351 else if (operand_equal_p (TREE_OPERAND (cond, 1),
352 TYPE_MIN_VALUE (TREE_TYPE (decl)),
353 0))
354 TREE_SET_CODE (cond, TREE_CODE (cond) == NE_EXPR
355 ? GT_EXPR : LE_EXPR);
356 else if (operand_equal_p (TREE_OPERAND (cond, 1),
357 TYPE_MAX_VALUE (TREE_TYPE (decl)),
358 0))
359 TREE_SET_CODE (cond, TREE_CODE (cond) == NE_EXPR
360 ? LT_EXPR : GE_EXPR);
361 else
362 cond_ok = false;
363 }
364 }
365
366 if (!cond_ok)
367 {
368 error_at (elocus, "invalid controlling predicate");
369 fail = true;
370 }
371 }
372
373 if (incr == NULL_TREE)
374 {
375 error_at (elocus, "missing increment expression");
376 fail = true;
377 }
378 else
379 {
380 bool incr_ok = false;
381
382 if (EXPR_HAS_LOCATION (incr))
383 elocus = EXPR_LOCATION (incr);
384
385 /* Check all the valid increment expressions: v++, v--, ++v, --v,
386 v = v + incr, v = incr + v and v = v - incr. */
387 switch (TREE_CODE (incr))
388 {
389 case POSTINCREMENT_EXPR:
390 case PREINCREMENT_EXPR:
391 case POSTDECREMENT_EXPR:
392 case PREDECREMENT_EXPR:
393 if (TREE_OPERAND (incr, 0) != decl)
394 break;
395
396 incr_ok = true;
397 if (POINTER_TYPE_P (TREE_TYPE (decl))
398 && TREE_OPERAND (incr, 1))
399 {
400 tree t = fold_convert_loc (elocus,
401 sizetype, TREE_OPERAND (incr, 1));
402
403 if (TREE_CODE (incr) == POSTDECREMENT_EXPR
404 || TREE_CODE (incr) == PREDECREMENT_EXPR)
405 t = fold_build1_loc (elocus, NEGATE_EXPR, sizetype, t);
406 t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (decl), decl, t);
407 incr = build2 (MODIFY_EXPR, void_type_node, decl, t);
408 }
409 break;
410
411 case MODIFY_EXPR:
412 if (TREE_OPERAND (incr, 0) != decl)
413 break;
414 if (TREE_OPERAND (incr, 1) == decl)
415 break;
416 if (TREE_CODE (TREE_OPERAND (incr, 1)) == PLUS_EXPR
417 && (TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl
418 || TREE_OPERAND (TREE_OPERAND (incr, 1), 1) == decl))
419 incr_ok = true;
420 else if ((TREE_CODE (TREE_OPERAND (incr, 1)) == MINUS_EXPR
421 || (TREE_CODE (TREE_OPERAND (incr, 1))
422 == POINTER_PLUS_EXPR))
423 && TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl)
424 incr_ok = true;
425 else
426 {
427 tree t = check_omp_for_incr_expr (elocus,
428 TREE_OPERAND (incr, 1),
429 decl);
430 if (t != error_mark_node)
431 {
432 incr_ok = true;
433 t = build2 (PLUS_EXPR, TREE_TYPE (decl), decl, t);
434 incr = build2 (MODIFY_EXPR, void_type_node, decl, t);
435 }
436 }
437 break;
438
439 default:
440 break;
441 }
442 if (!incr_ok)
443 {
444 error_at (elocus, "invalid increment expression");
445 fail = true;
446 }
447 }
448
449 TREE_VEC_ELT (initv, i) = init;
450 TREE_VEC_ELT (incrv, i) = incr;
451 }
452
453 if (fail)
454 return NULL;
455 else
456 {
457 tree t = make_node (OMP_FOR);
458
459 TREE_TYPE (t) = void_type_node;
460 OMP_FOR_INIT (t) = initv;
461 OMP_FOR_COND (t) = condv;
462 OMP_FOR_INCR (t) = incrv;
463 OMP_FOR_BODY (t) = body;
464 OMP_FOR_PRE_BODY (t) = pre_body;
465
466 SET_EXPR_LOCATION (t, locus);
467 return add_stmt (t);
468 }
469 }
470
471
472 /* Divide CLAUSES into two lists: those that apply to a parallel
473 construct, and those that apply to a work-sharing construct. Place
474 the results in *PAR_CLAUSES and *WS_CLAUSES respectively. In
475 addition, add a nowait clause to the work-sharing list. LOC is the
476 location of the OMP_PARALLEL*. */
477
478 void
479 c_split_parallel_clauses (location_t loc, tree clauses,
480 tree *par_clauses, tree *ws_clauses)
481 {
482 tree next;
483
484 *par_clauses = NULL;
485 *ws_clauses = build_omp_clause (loc, OMP_CLAUSE_NOWAIT);
486
487 for (; clauses ; clauses = next)
488 {
489 next = OMP_CLAUSE_CHAIN (clauses);
490
491 switch (OMP_CLAUSE_CODE (clauses))
492 {
493 case OMP_CLAUSE_PRIVATE:
494 case OMP_CLAUSE_SHARED:
495 case OMP_CLAUSE_FIRSTPRIVATE:
496 case OMP_CLAUSE_LASTPRIVATE:
497 case OMP_CLAUSE_REDUCTION:
498 case OMP_CLAUSE_COPYIN:
499 case OMP_CLAUSE_IF:
500 case OMP_CLAUSE_NUM_THREADS:
501 case OMP_CLAUSE_DEFAULT:
502 OMP_CLAUSE_CHAIN (clauses) = *par_clauses;
503 *par_clauses = clauses;
504 break;
505
506 case OMP_CLAUSE_SCHEDULE:
507 case OMP_CLAUSE_ORDERED:
508 case OMP_CLAUSE_COLLAPSE:
509 OMP_CLAUSE_CHAIN (clauses) = *ws_clauses;
510 *ws_clauses = clauses;
511 break;
512
513 default:
514 gcc_unreachable ();
515 }
516 }
517 }
518
519 /* True if OpenMP sharing attribute of DECL is predetermined. */
520
521 enum omp_clause_default_kind
522 c_omp_predetermined_sharing (tree decl)
523 {
524 /* Variables with const-qualified type having no mutable member
525 are predetermined shared. */
526 if (TREE_READONLY (decl))
527 return OMP_CLAUSE_DEFAULT_SHARED;
528
529 return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
530 }