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