OSDN Git Service

Note which PR this was related to.
[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 "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               || TREE_CODE (cond) == EQ_EXPR)
306             {
307               tree op0 = TREE_OPERAND (cond, 0);
308               tree op1 = TREE_OPERAND (cond, 1);
309
310               /* 2.5.1.  The comparison in the condition is computed in
311                  the type of DECL, otherwise the behavior is undefined.
312
313                  For example:
314                  long n; int i;
315                  i < n;
316
317                  according to ISO will be evaluated as:
318                  (long)i < n;
319
320                  We want to force:
321                  i < (int)n;  */
322               if (TREE_CODE (op0) == NOP_EXPR
323                   && decl == TREE_OPERAND (op0, 0))
324                 {
325                   TREE_OPERAND (cond, 0) = TREE_OPERAND (op0, 0);
326                   TREE_OPERAND (cond, 1)
327                     = fold_build1_loc (elocus, NOP_EXPR, TREE_TYPE (decl),
328                                    TREE_OPERAND (cond, 1));
329                 }
330               else if (TREE_CODE (op1) == NOP_EXPR
331                        && decl == TREE_OPERAND (op1, 0))
332                 {
333                   TREE_OPERAND (cond, 1) = TREE_OPERAND (op1, 0);
334                   TREE_OPERAND (cond, 0)
335                     = fold_build1_loc (elocus, NOP_EXPR, TREE_TYPE (decl),
336                                    TREE_OPERAND (cond, 0));
337                 }
338
339               if (decl == TREE_OPERAND (cond, 0))
340                 cond_ok = true;
341               else if (decl == TREE_OPERAND (cond, 1))
342                 {
343                   TREE_SET_CODE (cond,
344                                  swap_tree_comparison (TREE_CODE (cond)));
345                   TREE_OPERAND (cond, 1) = TREE_OPERAND (cond, 0);
346                   TREE_OPERAND (cond, 0) = decl;
347                   cond_ok = true;
348                 }
349
350               if (TREE_CODE (cond) == NE_EXPR
351                   || TREE_CODE (cond) == EQ_EXPR)
352                 {
353                   if (!INTEGRAL_TYPE_P (TREE_TYPE (decl)))
354                     cond_ok = false;
355                   else if (operand_equal_p (TREE_OPERAND (cond, 1),
356                                             TYPE_MIN_VALUE (TREE_TYPE (decl)),
357                                             0))
358                     TREE_SET_CODE (cond, TREE_CODE (cond) == NE_EXPR
359                                          ? GT_EXPR : LE_EXPR);
360                   else if (operand_equal_p (TREE_OPERAND (cond, 1),
361                                             TYPE_MAX_VALUE (TREE_TYPE (decl)),
362                                             0))
363                     TREE_SET_CODE (cond, TREE_CODE (cond) == NE_EXPR
364                                          ? LT_EXPR : GE_EXPR);
365                   else
366                     cond_ok = false;
367                 }
368             }
369
370           if (!cond_ok)
371             {
372               error_at (elocus, "invalid controlling predicate");
373               fail = true;
374             }
375         }
376
377       if (incr == NULL_TREE)
378         {
379           error_at (elocus, "missing increment expression");
380           fail = true;
381         }
382       else
383         {
384           bool incr_ok = false;
385
386           if (EXPR_HAS_LOCATION (incr))
387             elocus = EXPR_LOCATION (incr);
388
389           /* Check all the valid increment expressions: v++, v--, ++v, --v,
390              v = v + incr, v = incr + v and v = v - incr.  */
391           switch (TREE_CODE (incr))
392             {
393             case POSTINCREMENT_EXPR:
394             case PREINCREMENT_EXPR:
395             case POSTDECREMENT_EXPR:
396             case PREDECREMENT_EXPR:
397               if (TREE_OPERAND (incr, 0) != decl)
398                 break;
399
400               incr_ok = true;
401               if (POINTER_TYPE_P (TREE_TYPE (decl))
402                   && TREE_OPERAND (incr, 1))
403                 {
404                   tree t = fold_convert_loc (elocus,
405                                              sizetype, TREE_OPERAND (incr, 1));
406
407                   if (TREE_CODE (incr) == POSTDECREMENT_EXPR
408                       || TREE_CODE (incr) == PREDECREMENT_EXPR)
409                     t = fold_build1_loc (elocus, NEGATE_EXPR, sizetype, t);
410                   t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (decl), decl, t);
411                   incr = build2 (MODIFY_EXPR, void_type_node, decl, t);
412                 }
413               break;
414
415             case MODIFY_EXPR:
416               if (TREE_OPERAND (incr, 0) != decl)
417                 break;
418               if (TREE_OPERAND (incr, 1) == decl)
419                 break;
420               if (TREE_CODE (TREE_OPERAND (incr, 1)) == PLUS_EXPR
421                   && (TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl
422                       || TREE_OPERAND (TREE_OPERAND (incr, 1), 1) == decl))
423                 incr_ok = true;
424               else if ((TREE_CODE (TREE_OPERAND (incr, 1)) == MINUS_EXPR
425                         || (TREE_CODE (TREE_OPERAND (incr, 1))
426                             == POINTER_PLUS_EXPR))
427                        && TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl)
428                 incr_ok = true;
429               else
430                 {
431                   tree t = check_omp_for_incr_expr (elocus,
432                                                     TREE_OPERAND (incr, 1),
433                                                     decl);
434                   if (t != error_mark_node)
435                     {
436                       incr_ok = true;
437                       t = build2 (PLUS_EXPR, TREE_TYPE (decl), decl, t);
438                       incr = build2 (MODIFY_EXPR, void_type_node, decl, t);
439                     }
440                 }
441               break;
442
443             default:
444               break;
445             }
446           if (!incr_ok)
447             {
448               error_at (elocus, "invalid increment expression");
449               fail = true;
450             }
451         }
452
453       TREE_VEC_ELT (initv, i) = init;
454       TREE_VEC_ELT (incrv, i) = incr;
455     }
456
457   if (fail)
458     return NULL;
459   else
460     {
461       tree t = make_node (OMP_FOR);
462
463       TREE_TYPE (t) = void_type_node;
464       OMP_FOR_INIT (t) = initv;
465       OMP_FOR_COND (t) = condv;
466       OMP_FOR_INCR (t) = incrv;
467       OMP_FOR_BODY (t) = body;
468       OMP_FOR_PRE_BODY (t) = pre_body;
469
470       SET_EXPR_LOCATION (t, locus);
471       return add_stmt (t);
472     }
473 }
474
475
476 /* Divide CLAUSES into two lists: those that apply to a parallel
477    construct, and those that apply to a work-sharing construct.  Place
478    the results in *PAR_CLAUSES and *WS_CLAUSES respectively.  In
479    addition, add a nowait clause to the work-sharing list.  LOC is the
480    location of the OMP_PARALLEL*.  */
481
482 void
483 c_split_parallel_clauses (location_t loc, tree clauses,
484                           tree *par_clauses, tree *ws_clauses)
485 {
486   tree next;
487
488   *par_clauses = NULL;
489   *ws_clauses = build_omp_clause (loc, OMP_CLAUSE_NOWAIT);
490
491   for (; clauses ; clauses = next)
492     {
493       next = OMP_CLAUSE_CHAIN (clauses);
494
495       switch (OMP_CLAUSE_CODE (clauses))
496         {
497         case OMP_CLAUSE_PRIVATE:
498         case OMP_CLAUSE_SHARED:
499         case OMP_CLAUSE_FIRSTPRIVATE:
500         case OMP_CLAUSE_LASTPRIVATE:
501         case OMP_CLAUSE_REDUCTION:
502         case OMP_CLAUSE_COPYIN:
503         case OMP_CLAUSE_IF:
504         case OMP_CLAUSE_NUM_THREADS:
505         case OMP_CLAUSE_DEFAULT:
506           OMP_CLAUSE_CHAIN (clauses) = *par_clauses;
507           *par_clauses = clauses;
508           break;
509
510         case OMP_CLAUSE_SCHEDULE:
511         case OMP_CLAUSE_ORDERED:
512         case OMP_CLAUSE_COLLAPSE:
513           OMP_CLAUSE_CHAIN (clauses) = *ws_clauses;
514           *ws_clauses = clauses;
515           break;
516
517         default:
518           gcc_unreachable ();
519         }
520     }
521 }
522
523 /* True if OpenMP sharing attribute of DECL is predetermined.  */
524
525 enum omp_clause_default_kind
526 c_omp_predetermined_sharing (tree decl)
527 {
528   /* Variables with const-qualified type having no mutable member
529      are predetermined shared.  */
530   if (TREE_READONLY (decl))
531     return OMP_CLAUSE_DEFAULT_SHARED;
532
533   return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
534 }