OSDN Git Service

gcc/c-family:
[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_SYNC_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     case COMPOUND_EXPR:
217       {
218         /* cp_build_modify_expr forces preevaluation of the RHS to make
219            sure that it is evaluated before the lvalue-rvalue conversion
220            is applied to the LHS.  Reconstruct the original expression.  */
221         tree op0 = TREE_OPERAND (exp, 0);
222         if (TREE_CODE (op0) == TARGET_EXPR
223             && !VOID_TYPE_P (TREE_TYPE (op0)))
224           {
225             tree op1 = TREE_OPERAND (exp, 1);
226             tree temp = TARGET_EXPR_SLOT (op0);
227             if (TREE_CODE_CLASS (TREE_CODE (op1)) == tcc_binary
228                 && TREE_OPERAND (op1, 1) == temp)
229               {
230                 op1 = copy_node (op1);
231                 TREE_OPERAND (op1, 1) = TARGET_EXPR_INITIAL (op0);
232                 return check_omp_for_incr_expr (loc, op1, decl);
233               }
234           }
235         break;
236       }
237     default:
238       break;
239     }
240
241   return error_mark_node;
242 }
243
244 /* Validate and emit code for the OpenMP directive #pragma omp for.
245    DECLV is a vector of iteration variables, for each collapsed loop.
246    INITV, CONDV and INCRV are vectors containing initialization
247    expressions, controlling predicates and increment expressions.
248    BODY is the body of the loop and PRE_BODY statements that go before
249    the loop.  */
250
251 tree
252 c_finish_omp_for (location_t locus, tree declv, tree initv, tree condv,
253                   tree incrv, tree body, tree pre_body)
254 {
255   location_t elocus;
256   bool fail = false;
257   int i;
258
259   gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (initv));
260   gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (condv));
261   gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (incrv));
262   for (i = 0; i < TREE_VEC_LENGTH (declv); i++)
263     {
264       tree decl = TREE_VEC_ELT (declv, i);
265       tree init = TREE_VEC_ELT (initv, i);
266       tree cond = TREE_VEC_ELT (condv, i);
267       tree incr = TREE_VEC_ELT (incrv, i);
268
269       elocus = locus;
270       if (EXPR_HAS_LOCATION (init))
271         elocus = EXPR_LOCATION (init);
272
273       /* Validate the iteration variable.  */
274       if (!INTEGRAL_TYPE_P (TREE_TYPE (decl))
275           && TREE_CODE (TREE_TYPE (decl)) != POINTER_TYPE)
276         {
277           error_at (elocus, "invalid type for iteration variable %qE", decl);
278           fail = true;
279         }
280
281       /* In the case of "for (int i = 0...)", init will be a decl.  It should
282          have a DECL_INITIAL that we can turn into an assignment.  */
283       if (init == decl)
284         {
285           elocus = DECL_SOURCE_LOCATION (decl);
286
287           init = DECL_INITIAL (decl);
288           if (init == NULL)
289             {
290               error_at (elocus, "%qE is not initialized", decl);
291               init = integer_zero_node;
292               fail = true;
293             }
294
295           init = build_modify_expr (elocus, decl, NULL_TREE, NOP_EXPR,
296                                     /* FIXME diagnostics: This should
297                                        be the location of the INIT.  */
298                                     elocus,
299                                     init,
300                                     NULL_TREE);
301         }
302       gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
303       gcc_assert (TREE_OPERAND (init, 0) == decl);
304
305       if (cond == NULL_TREE)
306         {
307           error_at (elocus, "missing controlling predicate");
308           fail = true;
309         }
310       else
311         {
312           bool cond_ok = false;
313
314           if (EXPR_HAS_LOCATION (cond))
315             elocus = EXPR_LOCATION (cond);
316
317           if (TREE_CODE (cond) == LT_EXPR
318               || TREE_CODE (cond) == LE_EXPR
319               || TREE_CODE (cond) == GT_EXPR
320               || TREE_CODE (cond) == GE_EXPR
321               || TREE_CODE (cond) == NE_EXPR
322               || TREE_CODE (cond) == EQ_EXPR)
323             {
324               tree op0 = TREE_OPERAND (cond, 0);
325               tree op1 = TREE_OPERAND (cond, 1);
326
327               /* 2.5.1.  The comparison in the condition is computed in
328                  the type of DECL, otherwise the behavior is undefined.
329
330                  For example:
331                  long n; int i;
332                  i < n;
333
334                  according to ISO will be evaluated as:
335                  (long)i < n;
336
337                  We want to force:
338                  i < (int)n;  */
339               if (TREE_CODE (op0) == NOP_EXPR
340                   && decl == TREE_OPERAND (op0, 0))
341                 {
342                   TREE_OPERAND (cond, 0) = TREE_OPERAND (op0, 0);
343                   TREE_OPERAND (cond, 1)
344                     = fold_build1_loc (elocus, NOP_EXPR, TREE_TYPE (decl),
345                                    TREE_OPERAND (cond, 1));
346                 }
347               else if (TREE_CODE (op1) == NOP_EXPR
348                        && decl == TREE_OPERAND (op1, 0))
349                 {
350                   TREE_OPERAND (cond, 1) = TREE_OPERAND (op1, 0);
351                   TREE_OPERAND (cond, 0)
352                     = fold_build1_loc (elocus, NOP_EXPR, TREE_TYPE (decl),
353                                    TREE_OPERAND (cond, 0));
354                 }
355
356               if (decl == TREE_OPERAND (cond, 0))
357                 cond_ok = true;
358               else if (decl == TREE_OPERAND (cond, 1))
359                 {
360                   TREE_SET_CODE (cond,
361                                  swap_tree_comparison (TREE_CODE (cond)));
362                   TREE_OPERAND (cond, 1) = TREE_OPERAND (cond, 0);
363                   TREE_OPERAND (cond, 0) = decl;
364                   cond_ok = true;
365                 }
366
367               if (TREE_CODE (cond) == NE_EXPR
368                   || TREE_CODE (cond) == EQ_EXPR)
369                 {
370                   if (!INTEGRAL_TYPE_P (TREE_TYPE (decl)))
371                     cond_ok = false;
372                   else if (operand_equal_p (TREE_OPERAND (cond, 1),
373                                             TYPE_MIN_VALUE (TREE_TYPE (decl)),
374                                             0))
375                     TREE_SET_CODE (cond, TREE_CODE (cond) == NE_EXPR
376                                          ? GT_EXPR : LE_EXPR);
377                   else if (operand_equal_p (TREE_OPERAND (cond, 1),
378                                             TYPE_MAX_VALUE (TREE_TYPE (decl)),
379                                             0))
380                     TREE_SET_CODE (cond, TREE_CODE (cond) == NE_EXPR
381                                          ? LT_EXPR : GE_EXPR);
382                   else
383                     cond_ok = false;
384                 }
385             }
386
387           if (!cond_ok)
388             {
389               error_at (elocus, "invalid controlling predicate");
390               fail = true;
391             }
392         }
393
394       if (incr == NULL_TREE)
395         {
396           error_at (elocus, "missing increment expression");
397           fail = true;
398         }
399       else
400         {
401           bool incr_ok = false;
402
403           if (EXPR_HAS_LOCATION (incr))
404             elocus = EXPR_LOCATION (incr);
405
406           /* Check all the valid increment expressions: v++, v--, ++v, --v,
407              v = v + incr, v = incr + v and v = v - incr.  */
408           switch (TREE_CODE (incr))
409             {
410             case POSTINCREMENT_EXPR:
411             case PREINCREMENT_EXPR:
412             case POSTDECREMENT_EXPR:
413             case PREDECREMENT_EXPR:
414               if (TREE_OPERAND (incr, 0) != decl)
415                 break;
416
417               incr_ok = true;
418               if (POINTER_TYPE_P (TREE_TYPE (decl))
419                   && TREE_OPERAND (incr, 1))
420                 {
421                   tree t = fold_convert_loc (elocus,
422                                              sizetype, TREE_OPERAND (incr, 1));
423
424                   if (TREE_CODE (incr) == POSTDECREMENT_EXPR
425                       || TREE_CODE (incr) == PREDECREMENT_EXPR)
426                     t = fold_build1_loc (elocus, NEGATE_EXPR, sizetype, t);
427                   t = fold_build_pointer_plus (decl, t);
428                   incr = build2 (MODIFY_EXPR, void_type_node, decl, t);
429                 }
430               break;
431
432             case MODIFY_EXPR:
433               if (TREE_OPERAND (incr, 0) != decl)
434                 break;
435               if (TREE_OPERAND (incr, 1) == decl)
436                 break;
437               if (TREE_CODE (TREE_OPERAND (incr, 1)) == PLUS_EXPR
438                   && (TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl
439                       || TREE_OPERAND (TREE_OPERAND (incr, 1), 1) == decl))
440                 incr_ok = true;
441               else if ((TREE_CODE (TREE_OPERAND (incr, 1)) == MINUS_EXPR
442                         || (TREE_CODE (TREE_OPERAND (incr, 1))
443                             == POINTER_PLUS_EXPR))
444                        && TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl)
445                 incr_ok = true;
446               else
447                 {
448                   tree t = check_omp_for_incr_expr (elocus,
449                                                     TREE_OPERAND (incr, 1),
450                                                     decl);
451                   if (t != error_mark_node)
452                     {
453                       incr_ok = true;
454                       t = build2 (PLUS_EXPR, TREE_TYPE (decl), decl, t);
455                       incr = build2 (MODIFY_EXPR, void_type_node, decl, t);
456                     }
457                 }
458               break;
459
460             default:
461               break;
462             }
463           if (!incr_ok)
464             {
465               error_at (elocus, "invalid increment expression");
466               fail = true;
467             }
468         }
469
470       TREE_VEC_ELT (initv, i) = init;
471       TREE_VEC_ELT (incrv, i) = incr;
472     }
473
474   if (fail)
475     return NULL;
476   else
477     {
478       tree t = make_node (OMP_FOR);
479
480       TREE_TYPE (t) = void_type_node;
481       OMP_FOR_INIT (t) = initv;
482       OMP_FOR_COND (t) = condv;
483       OMP_FOR_INCR (t) = incrv;
484       OMP_FOR_BODY (t) = body;
485       OMP_FOR_PRE_BODY (t) = pre_body;
486
487       SET_EXPR_LOCATION (t, locus);
488       return add_stmt (t);
489     }
490 }
491
492
493 /* Divide CLAUSES into two lists: those that apply to a parallel
494    construct, and those that apply to a work-sharing construct.  Place
495    the results in *PAR_CLAUSES and *WS_CLAUSES respectively.  In
496    addition, add a nowait clause to the work-sharing list.  LOC is the
497    location of the OMP_PARALLEL*.  */
498
499 void
500 c_split_parallel_clauses (location_t loc, tree clauses,
501                           tree *par_clauses, tree *ws_clauses)
502 {
503   tree next;
504
505   *par_clauses = NULL;
506   *ws_clauses = build_omp_clause (loc, OMP_CLAUSE_NOWAIT);
507
508   for (; clauses ; clauses = next)
509     {
510       next = OMP_CLAUSE_CHAIN (clauses);
511
512       switch (OMP_CLAUSE_CODE (clauses))
513         {
514         case OMP_CLAUSE_PRIVATE:
515         case OMP_CLAUSE_SHARED:
516         case OMP_CLAUSE_FIRSTPRIVATE:
517         case OMP_CLAUSE_LASTPRIVATE:
518         case OMP_CLAUSE_REDUCTION:
519         case OMP_CLAUSE_COPYIN:
520         case OMP_CLAUSE_IF:
521         case OMP_CLAUSE_NUM_THREADS:
522         case OMP_CLAUSE_DEFAULT:
523           OMP_CLAUSE_CHAIN (clauses) = *par_clauses;
524           *par_clauses = clauses;
525           break;
526
527         case OMP_CLAUSE_SCHEDULE:
528         case OMP_CLAUSE_ORDERED:
529         case OMP_CLAUSE_COLLAPSE:
530           OMP_CLAUSE_CHAIN (clauses) = *ws_clauses;
531           *ws_clauses = clauses;
532           break;
533
534         default:
535           gcc_unreachable ();
536         }
537     }
538 }
539
540 /* True if OpenMP sharing attribute of DECL is predetermined.  */
541
542 enum omp_clause_default_kind
543 c_omp_predetermined_sharing (tree decl)
544 {
545   /* Variables with const-qualified type having no mutable member
546      are predetermined shared.  */
547   if (TREE_READONLY (decl))
548     return OMP_CLAUSE_DEFAULT_SHARED;
549
550   return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
551 }