OSDN Git Service

Fix PR42186.
[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 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.  LOC is the l*/
39
40 tree
41 c_finish_omp_master (location_t loc, tree stmt)
42 {
43   tree t = add_stmt (build1 (OMP_MASTER, void_type_node, stmt));
44   SET_EXPR_LOCATION (t, loc);
45   return t;
46 }
47
48 /* Complete a #pragma omp critical construct.  STMT is the structured-block
49    that follows the pragma, NAME is the identifier in the pragma, or null
50    if it was omitted.  LOC is the location of the #pragma.  */
51
52 tree
53 c_finish_omp_critical (location_t loc, tree body, tree name)
54 {
55   tree stmt = make_node (OMP_CRITICAL);
56   TREE_TYPE (stmt) = void_type_node;
57   OMP_CRITICAL_BODY (stmt) = body;
58   OMP_CRITICAL_NAME (stmt) = name;
59   SET_EXPR_LOCATION (stmt, loc);
60   return add_stmt (stmt);
61 }
62
63 /* Complete a #pragma omp ordered construct.  STMT is the structured-block
64    that follows the pragma.  LOC is the location of the #pragma.  */
65
66 tree
67 c_finish_omp_ordered (location_t loc, tree stmt)
68 {
69   tree t = build1 (OMP_ORDERED, void_type_node, stmt);
70   SET_EXPR_LOCATION (t, loc);
71   return add_stmt (t);
72 }
73
74
75 /* Complete a #pragma omp barrier construct.  LOC is the location of
76    the #pragma.  */
77
78 void
79 c_finish_omp_barrier (location_t loc)
80 {
81   tree x;
82
83   x = built_in_decls[BUILT_IN_GOMP_BARRIER];
84   x = build_call_expr_loc (loc, x, 0);
85   add_stmt (x);
86 }
87
88
89 /* Complete a #pragma omp taskwait construct.  LOC is the location of the
90    pragma.  */
91
92 void
93 c_finish_omp_taskwait (location_t loc)
94 {
95   tree x;
96
97   x = built_in_decls[BUILT_IN_GOMP_TASKWAIT];
98   x = build_call_expr_loc (loc, x, 0);
99   add_stmt (x);
100 }
101
102
103 /* Complete a #pragma omp atomic construct.  The expression to be
104    implemented atomically is LHS code= RHS.  LOC is the location of
105    the atomic statement.  The value returned is either error_mark_node
106    (if the construct was erroneous) or an OMP_ATOMIC node which should
107    be added to the current statement tree with add_stmt.*/
108
109 tree
110 c_finish_omp_atomic (location_t loc, enum tree_code code, tree lhs, tree rhs)
111 {
112   tree x, type, addr;
113
114   if (lhs == error_mark_node || rhs == error_mark_node)
115     return error_mark_node;
116
117   /* ??? According to one reading of the OpenMP spec, complex type are
118      supported, but there are no atomic stores for any architecture.
119      But at least icc 9.0 doesn't support complex types here either.
120      And lets not even talk about vector types...  */
121   type = TREE_TYPE (lhs);
122   if (!INTEGRAL_TYPE_P (type)
123       && !POINTER_TYPE_P (type)
124       && !SCALAR_FLOAT_TYPE_P (type))
125     {
126       error_at (loc, "invalid expression type for %<#pragma omp atomic%>");
127       return error_mark_node;
128     }
129
130   /* ??? Validate that rhs does not overlap lhs.  */
131
132   /* Take and save the address of the lhs.  From then on we'll reference it
133      via indirection.  */
134   addr = build_unary_op (loc, ADDR_EXPR, lhs, 0);
135   if (addr == error_mark_node)
136     return error_mark_node;
137   addr = save_expr (addr);
138   if (TREE_CODE (addr) != SAVE_EXPR
139       && (TREE_CODE (addr) != ADDR_EXPR
140           || TREE_CODE (TREE_OPERAND (addr, 0)) != VAR_DECL))
141     {
142       /* Make sure LHS is simple enough so that goa_lhs_expr_p can recognize
143          it even after unsharing function body.  */
144       tree var = create_tmp_var_raw (TREE_TYPE (addr), NULL);
145       DECL_CONTEXT (var) = current_function_decl;
146       addr = build4 (TARGET_EXPR, TREE_TYPE (addr), var, addr, NULL, NULL);
147     }
148   lhs = build_indirect_ref (loc, addr, RO_NULL);
149
150   /* There are lots of warnings, errors, and conversions that need to happen
151      in the course of interpreting a statement.  Use the normal mechanisms
152      to do this, and then take it apart again.  */
153   x = build_modify_expr (input_location, lhs, NULL_TREE, code,
154                          input_location, rhs, NULL_TREE);
155   if (x == error_mark_node)
156     return error_mark_node;
157   gcc_assert (TREE_CODE (x) == MODIFY_EXPR);
158   rhs = TREE_OPERAND (x, 1);
159
160   /* Punt the actual generation of atomic operations to common code.  */
161   x = build2 (OMP_ATOMIC, void_type_node, addr, rhs);
162   SET_EXPR_LOCATION (x, loc);
163   return x;
164 }
165
166
167 /* Complete a #pragma omp flush construct.  We don't do anything with
168    the variable list that the syntax allows.  LOC is the location of
169    the #pragma.  */
170
171 void
172 c_finish_omp_flush (location_t loc)
173 {
174   tree x;
175
176   x = built_in_decls[BUILT_IN_SYNCHRONIZE];
177   x = build_call_expr_loc (loc, x, 0);
178   add_stmt (x);
179 }
180
181
182 /* Check and canonicalize #pragma omp for increment expression.
183    Helper function for c_finish_omp_for.  */
184
185 static tree
186 check_omp_for_incr_expr (location_t loc, tree exp, tree decl)
187 {
188   tree t;
189
190   if (!INTEGRAL_TYPE_P (TREE_TYPE (exp))
191       || TYPE_PRECISION (TREE_TYPE (exp)) < TYPE_PRECISION (TREE_TYPE (decl)))
192     return error_mark_node;
193
194   if (exp == decl)
195     return build_int_cst (TREE_TYPE (exp), 0);
196
197   switch (TREE_CODE (exp))
198     {
199     CASE_CONVERT:
200       t = check_omp_for_incr_expr (loc, TREE_OPERAND (exp, 0), decl);
201       if (t != error_mark_node)
202         return fold_convert_loc (loc, TREE_TYPE (exp), t);
203       break;
204     case MINUS_EXPR:
205       t = check_omp_for_incr_expr (loc, TREE_OPERAND (exp, 0), decl);
206       if (t != error_mark_node)
207         return fold_build2_loc (loc, MINUS_EXPR,
208                             TREE_TYPE (exp), t, TREE_OPERAND (exp, 1));
209       break;
210     case PLUS_EXPR:
211       t = check_omp_for_incr_expr (loc, TREE_OPERAND (exp, 0), decl);
212       if (t != error_mark_node)
213         return fold_build2_loc (loc, PLUS_EXPR,
214                             TREE_TYPE (exp), t, TREE_OPERAND (exp, 1));
215       t = check_omp_for_incr_expr (loc, TREE_OPERAND (exp, 1), decl);
216       if (t != error_mark_node)
217         return fold_build2_loc (loc, PLUS_EXPR,
218                             TREE_TYPE (exp), TREE_OPERAND (exp, 0), t);
219       break;
220     default:
221       break;
222     }
223
224   return error_mark_node;
225 }
226
227 /* Validate and emit code for the OpenMP directive #pragma omp for.
228    DECLV is a vector of iteration variables, for each collapsed loop.
229    INITV, CONDV and INCRV are vectors containing initialization
230    expressions, controlling predicates and increment expressions.
231    BODY is the body of the loop and PRE_BODY statements that go before
232    the loop.  */
233
234 tree
235 c_finish_omp_for (location_t locus, tree declv, tree initv, tree condv,
236                   tree incrv, tree body, tree pre_body)
237 {
238   location_t elocus;
239   bool fail = false;
240   int i;
241
242   gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (initv));
243   gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (condv));
244   gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (incrv));
245   for (i = 0; i < TREE_VEC_LENGTH (declv); i++)
246     {
247       tree decl = TREE_VEC_ELT (declv, i);
248       tree init = TREE_VEC_ELT (initv, i);
249       tree cond = TREE_VEC_ELT (condv, i);
250       tree incr = TREE_VEC_ELT (incrv, i);
251
252       elocus = locus;
253       if (EXPR_HAS_LOCATION (init))
254         elocus = EXPR_LOCATION (init);
255
256       /* Validate the iteration variable.  */
257       if (!INTEGRAL_TYPE_P (TREE_TYPE (decl))
258           && TREE_CODE (TREE_TYPE (decl)) != POINTER_TYPE)
259         {
260           error_at (elocus, "invalid type for iteration variable %qE", decl);
261           fail = true;
262         }
263
264       /* In the case of "for (int i = 0...)", init will be a decl.  It should
265          have a DECL_INITIAL that we can turn into an assignment.  */
266       if (init == decl)
267         {
268           elocus = DECL_SOURCE_LOCATION (decl);
269
270           init = DECL_INITIAL (decl);
271           if (init == NULL)
272             {
273               error_at (elocus, "%qE is not initialized", decl);
274               init = integer_zero_node;
275               fail = true;
276             }
277
278           init = build_modify_expr (elocus, decl, NULL_TREE, NOP_EXPR,
279                                     /* FIXME diagnostics: This should
280                                        be the location of the INIT.  */
281                                     elocus,
282                                     init,
283                                     NULL_TREE);
284         }
285       gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
286       gcc_assert (TREE_OPERAND (init, 0) == decl);
287
288       if (cond == NULL_TREE)
289         {
290           error_at (elocus, "missing controlling predicate");
291           fail = true;
292         }
293       else
294         {
295           bool cond_ok = false;
296
297           if (EXPR_HAS_LOCATION (cond))
298             elocus = EXPR_LOCATION (cond);
299
300           if (TREE_CODE (cond) == LT_EXPR
301               || TREE_CODE (cond) == LE_EXPR
302               || TREE_CODE (cond) == GT_EXPR
303               || TREE_CODE (cond) == GE_EXPR
304               || TREE_CODE (cond) == NE_EXPR)
305             {
306               tree op0 = TREE_OPERAND (cond, 0);
307               tree op1 = TREE_OPERAND (cond, 1);
308
309               /* 2.5.1.  The comparison in the condition is computed in
310                  the type of DECL, otherwise the behavior is undefined.
311
312                  For example:
313                  long n; int i;
314                  i < n;
315
316                  according to ISO will be evaluated as:
317                  (long)i < n;
318
319                  We want to force:
320                  i < (int)n;  */
321               if (TREE_CODE (op0) == NOP_EXPR
322                   && decl == TREE_OPERAND (op0, 0))
323                 {
324                   TREE_OPERAND (cond, 0) = TREE_OPERAND (op0, 0);
325                   TREE_OPERAND (cond, 1)
326                     = fold_build1_loc (elocus, NOP_EXPR, TREE_TYPE (decl),
327                                    TREE_OPERAND (cond, 1));
328                 }
329               else if (TREE_CODE (op1) == NOP_EXPR
330                        && decl == TREE_OPERAND (op1, 0))
331                 {
332                   TREE_OPERAND (cond, 1) = TREE_OPERAND (op1, 0);
333                   TREE_OPERAND (cond, 0)
334                     = fold_build1_loc (elocus, NOP_EXPR, TREE_TYPE (decl),
335                                    TREE_OPERAND (cond, 0));
336                 }
337
338               if (decl == TREE_OPERAND (cond, 0))
339                 cond_ok = true;
340               else if (decl == TREE_OPERAND (cond, 1))
341                 {
342                   TREE_SET_CODE (cond,
343                                  swap_tree_comparison (TREE_CODE (cond)));
344                   TREE_OPERAND (cond, 1) = TREE_OPERAND (cond, 0);
345                   TREE_OPERAND (cond, 0) = decl;
346                   cond_ok = true;
347                 }
348
349               if (TREE_CODE (cond) == NE_EXPR)
350                 {
351                   if (!INTEGRAL_TYPE_P (TREE_TYPE (decl)))
352                     cond_ok = false;
353                   else if (operand_equal_p (TREE_OPERAND (cond, 1),
354                                             TYPE_MIN_VALUE (TREE_TYPE (decl)),
355                                             0))
356                     TREE_SET_CODE (cond, GT_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, LT_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 }