OSDN Git Service

gcc/
[pf3gnuchains/gcc-fork.git] / gcc / c-family / 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 "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 }