OSDN Git Service

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