OSDN Git Service

b949501d52b0750228788a9a7753e22ea6ca2a29
[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       addr = build4 (TARGET_EXPR, TREE_TYPE (addr), var, addr, NULL, NULL);
146     }
147   lhs = build_indirect_ref (loc, addr, NULL);
148
149   /* There are lots of warnings, errors, and conversions that need to happen
150      in the course of interpreting a statement.  Use the normal mechanisms
151      to do this, and then take it apart again.  */
152   x = build_modify_expr (input_location, lhs, NULL_TREE, code,
153                          input_location, rhs, NULL_TREE);
154   if (x == error_mark_node)
155     return error_mark_node;
156   gcc_assert (TREE_CODE (x) == MODIFY_EXPR);  
157   rhs = TREE_OPERAND (x, 1);
158
159   /* Punt the actual generation of atomic operations to common code.  */
160   x = build2 (OMP_ATOMIC, void_type_node, addr, rhs);
161   SET_EXPR_LOCATION (x, loc);
162   return x;
163 }
164
165
166 /* Complete a #pragma omp flush construct.  We don't do anything with
167    the variable list that the syntax allows.  LOC is the location of
168    the #pragma.  */
169
170 void
171 c_finish_omp_flush (location_t loc)
172 {
173   tree x;
174
175   x = built_in_decls[BUILT_IN_SYNCHRONIZE];
176   x = build_call_expr_loc (loc, x, 0);
177   add_stmt (x);
178 }
179
180
181 /* Check and canonicalize #pragma omp for increment expression.
182    Helper function for c_finish_omp_for.  */
183
184 static tree
185 check_omp_for_incr_expr (location_t loc, tree exp, tree decl)
186 {
187   tree t;
188
189   if (!INTEGRAL_TYPE_P (TREE_TYPE (exp))
190       || TYPE_PRECISION (TREE_TYPE (exp)) < TYPE_PRECISION (TREE_TYPE (decl)))
191     return error_mark_node;
192
193   if (exp == decl)
194     return build_int_cst (TREE_TYPE (exp), 0);
195
196   switch (TREE_CODE (exp))
197     {
198     CASE_CONVERT:
199       t = check_omp_for_incr_expr (loc, TREE_OPERAND (exp, 0), decl);
200       if (t != error_mark_node)
201         return fold_convert_loc (loc, TREE_TYPE (exp), t);
202       break;
203     case MINUS_EXPR:
204       t = check_omp_for_incr_expr (loc, TREE_OPERAND (exp, 0), decl);
205       if (t != error_mark_node)
206         return fold_build2_loc (loc, MINUS_EXPR,
207                             TREE_TYPE (exp), t, TREE_OPERAND (exp, 1));
208       break;
209     case PLUS_EXPR:
210       t = check_omp_for_incr_expr (loc, TREE_OPERAND (exp, 0), decl);
211       if (t != error_mark_node)
212         return fold_build2_loc (loc, PLUS_EXPR,
213                             TREE_TYPE (exp), t, TREE_OPERAND (exp, 1));
214       t = check_omp_for_incr_expr (loc, TREE_OPERAND (exp, 1), decl);
215       if (t != error_mark_node)
216         return fold_build2_loc (loc, PLUS_EXPR,
217                             TREE_TYPE (exp), TREE_OPERAND (exp, 0), t);
218       break;
219     default:
220       break;
221     }
222
223   return error_mark_node;
224 }
225
226 /* Validate and emit code for the OpenMP directive #pragma omp for.
227    DECLV is a vector of iteration variables, for each collapsed loop.
228    INITV, CONDV and INCRV are vectors containing initialization
229    expressions, controlling predicates and increment expressions.
230    BODY is the body of the loop and PRE_BODY statements that go before
231    the loop.  */
232
233 tree
234 c_finish_omp_for (location_t locus, tree declv, tree initv, tree condv,
235                   tree incrv, tree body, tree pre_body)
236 {
237   location_t elocus;
238   bool fail = false;
239   int i;
240
241   gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (initv));
242   gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (condv));
243   gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (incrv));
244   for (i = 0; i < TREE_VEC_LENGTH (declv); i++)
245     {
246       tree decl = TREE_VEC_ELT (declv, i);
247       tree init = TREE_VEC_ELT (initv, i);
248       tree cond = TREE_VEC_ELT (condv, i);
249       tree incr = TREE_VEC_ELT (incrv, i);
250
251       elocus = locus;
252       if (EXPR_HAS_LOCATION (init))
253         elocus = EXPR_LOCATION (init);
254
255       /* Validate the iteration variable.  */
256       if (!INTEGRAL_TYPE_P (TREE_TYPE (decl))
257           && TREE_CODE (TREE_TYPE (decl)) != POINTER_TYPE)
258         {
259           error_at (elocus, "invalid type for iteration variable %qE", decl);
260           fail = true;
261         }
262
263       /* In the case of "for (int i = 0...)", init will be a decl.  It should
264          have a DECL_INITIAL that we can turn into an assignment.  */
265       if (init == decl)
266         {
267           elocus = DECL_SOURCE_LOCATION (decl);
268
269           init = DECL_INITIAL (decl);
270           if (init == NULL)
271             {
272               error_at (elocus, "%qE is not initialized", decl);
273               init = integer_zero_node;
274               fail = true;
275             }
276
277           init = build_modify_expr (elocus, decl, NULL_TREE, NOP_EXPR, 
278                                     /* FIXME diagnostics: This should
279                                        be the location of the INIT.  */
280                                     elocus,
281                                     init,
282                                     NULL_TREE);
283         }
284       gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
285       gcc_assert (TREE_OPERAND (init, 0) == decl);
286
287       if (cond == NULL_TREE)
288         {
289           error_at (elocus, "missing controlling predicate");
290           fail = true;
291         }
292       else
293         {
294           bool cond_ok = false;
295
296           if (EXPR_HAS_LOCATION (cond))
297             elocus = EXPR_LOCATION (cond);
298
299           if (TREE_CODE (cond) == LT_EXPR
300               || TREE_CODE (cond) == LE_EXPR
301               || TREE_CODE (cond) == GT_EXPR
302               || TREE_CODE (cond) == GE_EXPR
303               || TREE_CODE (cond) == NE_EXPR)
304             {
305               tree op0 = TREE_OPERAND (cond, 0);
306               tree op1 = TREE_OPERAND (cond, 1);
307
308               /* 2.5.1.  The comparison in the condition is computed in
309                  the type of DECL, otherwise the behavior is undefined.
310
311                  For example:
312                  long n; int i;
313                  i < n;
314
315                  according to ISO will be evaluated as:
316                  (long)i < n;
317
318                  We want to force:
319                  i < (int)n;  */
320               if (TREE_CODE (op0) == NOP_EXPR
321                   && decl == TREE_OPERAND (op0, 0))
322                 {
323                   TREE_OPERAND (cond, 0) = TREE_OPERAND (op0, 0);
324                   TREE_OPERAND (cond, 1)
325                     = fold_build1_loc (elocus, NOP_EXPR, TREE_TYPE (decl),
326                                    TREE_OPERAND (cond, 1));
327                 }
328               else if (TREE_CODE (op1) == NOP_EXPR
329                        && decl == TREE_OPERAND (op1, 0))
330                 {
331                   TREE_OPERAND (cond, 1) = TREE_OPERAND (op1, 0);
332                   TREE_OPERAND (cond, 0)
333                     = fold_build1_loc (elocus, NOP_EXPR, TREE_TYPE (decl),
334                                    TREE_OPERAND (cond, 0));
335                 }
336
337               if (decl == TREE_OPERAND (cond, 0))
338                 cond_ok = true;
339               else if (decl == TREE_OPERAND (cond, 1))
340                 {
341                   TREE_SET_CODE (cond,
342                                  swap_tree_comparison (TREE_CODE (cond)));
343                   TREE_OPERAND (cond, 1) = TREE_OPERAND (cond, 0);
344                   TREE_OPERAND (cond, 0) = decl;
345                   cond_ok = true;
346                 }
347
348               if (TREE_CODE (cond) == NE_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, GT_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, LT_EXPR);
360                   else
361                     cond_ok = false;
362                 }
363             }
364
365           if (!cond_ok)
366             {
367               error_at (elocus, "invalid controlling predicate");
368               fail = true;
369             }
370         }
371
372       if (incr == NULL_TREE)
373         {
374           error_at (elocus, "missing increment expression");
375           fail = true;
376         }
377       else
378         {
379           bool incr_ok = false;
380
381           if (EXPR_HAS_LOCATION (incr))
382             elocus = EXPR_LOCATION (incr);
383
384           /* Check all the valid increment expressions: v++, v--, ++v, --v,
385              v = v + incr, v = incr + v and v = v - incr.  */
386           switch (TREE_CODE (incr))
387             {
388             case POSTINCREMENT_EXPR:
389             case PREINCREMENT_EXPR:
390             case POSTDECREMENT_EXPR:
391             case PREDECREMENT_EXPR:
392               if (TREE_OPERAND (incr, 0) != decl)
393                 break;
394
395               incr_ok = true;
396               if (POINTER_TYPE_P (TREE_TYPE (decl))
397                   && TREE_OPERAND (incr, 1))
398                 {
399                   tree t = fold_convert_loc (elocus,
400                                              sizetype, TREE_OPERAND (incr, 1));
401
402                   if (TREE_CODE (incr) == POSTDECREMENT_EXPR
403                       || TREE_CODE (incr) == PREDECREMENT_EXPR)
404                     t = fold_build1_loc (elocus, NEGATE_EXPR, sizetype, t);
405                   t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (decl), decl, t);
406                   incr = build2 (MODIFY_EXPR, void_type_node, decl, t);
407                 }
408               break;
409
410             case MODIFY_EXPR:
411               if (TREE_OPERAND (incr, 0) != decl)
412                 break;
413               if (TREE_OPERAND (incr, 1) == decl)
414                 break;
415               if (TREE_CODE (TREE_OPERAND (incr, 1)) == PLUS_EXPR
416                   && (TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl
417                       || TREE_OPERAND (TREE_OPERAND (incr, 1), 1) == decl))
418                 incr_ok = true;
419               else if ((TREE_CODE (TREE_OPERAND (incr, 1)) == MINUS_EXPR
420                         || (TREE_CODE (TREE_OPERAND (incr, 1))
421                             == POINTER_PLUS_EXPR))
422                        && TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl)
423                 incr_ok = true;
424               else
425                 {
426                   tree t = check_omp_for_incr_expr (elocus,
427                                                     TREE_OPERAND (incr, 1),
428                                                     decl);
429                   if (t != error_mark_node)
430                     {
431                       incr_ok = true;
432                       t = build2 (PLUS_EXPR, TREE_TYPE (decl), decl, t);
433                       incr = build2 (MODIFY_EXPR, void_type_node, decl, t);
434                     }
435                 }
436               break;
437
438             default:
439               break;
440             }
441           if (!incr_ok)
442             {
443               error_at (elocus, "invalid increment expression");
444               fail = true;
445             }
446         }
447
448       TREE_VEC_ELT (initv, i) = init;
449       TREE_VEC_ELT (incrv, i) = incr;
450     }
451
452   if (fail)
453     return NULL;
454   else
455     {
456       tree t = make_node (OMP_FOR);
457
458       TREE_TYPE (t) = void_type_node;
459       OMP_FOR_INIT (t) = initv;
460       OMP_FOR_COND (t) = condv;
461       OMP_FOR_INCR (t) = incrv;
462       OMP_FOR_BODY (t) = body;
463       OMP_FOR_PRE_BODY (t) = pre_body;
464
465       SET_EXPR_LOCATION (t, locus);
466       return add_stmt (t);
467     }
468 }
469
470
471 /* Divide CLAUSES into two lists: those that apply to a parallel
472    construct, and those that apply to a work-sharing construct.  Place
473    the results in *PAR_CLAUSES and *WS_CLAUSES respectively.  In
474    addition, add a nowait clause to the work-sharing list.  LOC is the
475    location of the OMP_PARALLEL*.  */
476
477 void
478 c_split_parallel_clauses (location_t loc, tree clauses,
479                           tree *par_clauses, tree *ws_clauses)
480 {
481   tree next;
482
483   *par_clauses = NULL;
484   *ws_clauses = build_omp_clause (loc, OMP_CLAUSE_NOWAIT);
485
486   for (; clauses ; clauses = next)
487     {
488       next = OMP_CLAUSE_CHAIN (clauses);
489
490       switch (OMP_CLAUSE_CODE (clauses))
491         {
492         case OMP_CLAUSE_PRIVATE:
493         case OMP_CLAUSE_SHARED:
494         case OMP_CLAUSE_FIRSTPRIVATE:
495         case OMP_CLAUSE_LASTPRIVATE:
496         case OMP_CLAUSE_REDUCTION:
497         case OMP_CLAUSE_COPYIN:
498         case OMP_CLAUSE_IF:
499         case OMP_CLAUSE_NUM_THREADS:
500         case OMP_CLAUSE_DEFAULT:
501           OMP_CLAUSE_CHAIN (clauses) = *par_clauses;
502           *par_clauses = clauses;
503           break;
504
505         case OMP_CLAUSE_SCHEDULE:
506         case OMP_CLAUSE_ORDERED:
507         case OMP_CLAUSE_COLLAPSE:
508           OMP_CLAUSE_CHAIN (clauses) = *ws_clauses;
509           *ws_clauses = clauses;
510           break;
511
512         default:
513           gcc_unreachable ();
514         }
515     }
516 }
517
518 /* True if OpenMP sharing attribute of DECL is predetermined.  */
519
520 enum omp_clause_default_kind
521 c_omp_predetermined_sharing (tree decl)
522 {
523   /* Variables with const-qualified type having no mutable member
524      are predetermined shared.  */
525   if (TREE_READONLY (decl))
526     return OMP_CLAUSE_DEFAULT_SHARED;
527
528   return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
529 }