OSDN Git Service

2009-07-07 Manuel López-Ibáñez <manu@gcc.gnu.org>
[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 (x, 0);
85   SET_EXPR_LOCATION (x, loc);
86   add_stmt (x);
87 }
88
89
90 /* Complete a #pragma omp taskwait construct.  LOC is the location of the
91    pragma.  */
92
93 void
94 c_finish_omp_taskwait (location_t loc)
95 {
96   tree x;
97
98   x = built_in_decls[BUILT_IN_GOMP_TASKWAIT];
99   x = build_call_expr (x, 0);
100   SET_EXPR_LOCATION (x, loc);
101   add_stmt (x);
102 }
103
104
105 /* Complete a #pragma omp atomic construct.  The expression to be
106    implemented atomically is LHS code= RHS.  LOC is the location of
107    the atomic statement.  The value returned is either error_mark_node
108    (if the construct was erroneous) or an OMP_ATOMIC node which should
109    be added to the current statement tree with add_stmt.*/
110
111 tree
112 c_finish_omp_atomic (location_t loc, enum tree_code code, tree lhs, tree rhs)
113 {
114   tree x, type, addr;
115
116   if (lhs == error_mark_node || rhs == error_mark_node)
117     return error_mark_node;
118
119   /* ??? According to one reading of the OpenMP spec, complex type are
120      supported, but there are no atomic stores for any architecture.
121      But at least icc 9.0 doesn't support complex types here either.
122      And lets not even talk about vector types...  */
123   type = TREE_TYPE (lhs);
124   if (!INTEGRAL_TYPE_P (type)
125       && !POINTER_TYPE_P (type)
126       && !SCALAR_FLOAT_TYPE_P (type))
127     {
128       error_at (loc, "invalid expression type for %<#pragma omp atomic%>");
129       return error_mark_node;
130     }
131
132   /* ??? Validate that rhs does not overlap lhs.  */
133
134   /* Take and save the address of the lhs.  From then on we'll reference it
135      via indirection.  */
136   addr = build_unary_op (loc, ADDR_EXPR, lhs, 0);
137   if (addr == error_mark_node)
138     return error_mark_node;
139   addr = save_expr (addr);
140   if (TREE_CODE (addr) != SAVE_EXPR
141       && (TREE_CODE (addr) != ADDR_EXPR
142           || TREE_CODE (TREE_OPERAND (addr, 0)) != VAR_DECL))
143     {
144       /* Make sure LHS is simple enough so that goa_lhs_expr_p can recognize
145          it even after unsharing function body.  */
146       tree var = create_tmp_var_raw (TREE_TYPE (addr), NULL);
147       addr = build4 (TARGET_EXPR, TREE_TYPE (addr), var, addr, NULL, NULL);
148     }
149   lhs = build_indirect_ref (loc, addr, NULL);
150
151   /* There are lots of warnings, errors, and conversions that need to happen
152      in the course of interpreting a statement.  Use the normal mechanisms
153      to do this, and then take it apart again.  */
154   x = build_modify_expr (input_location, lhs, NULL_TREE, code,
155                          input_location, rhs, NULL_TREE);
156   if (x == error_mark_node)
157     return error_mark_node;
158   gcc_assert (TREE_CODE (x) == MODIFY_EXPR);  
159   rhs = TREE_OPERAND (x, 1);
160
161   /* Punt the actual generation of atomic operations to common code.  */
162   x = build2 (OMP_ATOMIC, void_type_node, addr, rhs);
163   SET_EXPR_LOCATION (x, loc);
164   return x;
165 }
166
167
168 /* Complete a #pragma omp flush construct.  We don't do anything with
169    the variable list that the syntax allows.  LOC is the location of
170    the #pragma.  */
171
172 void
173 c_finish_omp_flush (location_t loc)
174 {
175   tree x;
176
177   x = built_in_decls[BUILT_IN_SYNCHRONIZE];
178   x = build_call_expr (x, 0);
179   SET_EXPR_LOCATION (x, loc);
180   add_stmt (x);
181 }
182
183
184 /* Check and canonicalize #pragma omp for increment expression.
185    Helper function for c_finish_omp_for.  */
186
187 static tree
188 check_omp_for_incr_expr (tree exp, tree decl)
189 {
190   tree t;
191
192   if (!INTEGRAL_TYPE_P (TREE_TYPE (exp))
193       || TYPE_PRECISION (TREE_TYPE (exp)) < TYPE_PRECISION (TREE_TYPE (decl)))
194     return error_mark_node;
195
196   if (exp == decl)
197     return build_int_cst (TREE_TYPE (exp), 0);
198
199   switch (TREE_CODE (exp))
200     {
201     CASE_CONVERT:
202       t = check_omp_for_incr_expr (TREE_OPERAND (exp, 0), decl);
203       if (t != error_mark_node)
204         return fold_convert (TREE_TYPE (exp), t);
205       break;
206     case MINUS_EXPR:
207       t = check_omp_for_incr_expr (TREE_OPERAND (exp, 0), decl);
208       if (t != error_mark_node)
209         return fold_build2 (MINUS_EXPR, TREE_TYPE (exp), t, TREE_OPERAND (exp, 1));
210       break;
211     case PLUS_EXPR:
212       t = check_omp_for_incr_expr (TREE_OPERAND (exp, 0), decl);
213       if (t != error_mark_node)
214         return fold_build2 (PLUS_EXPR, TREE_TYPE (exp), t, TREE_OPERAND (exp, 1));
215       t = check_omp_for_incr_expr (TREE_OPERAND (exp, 1), decl);
216       if (t != error_mark_node)
217         return fold_build2 (PLUS_EXPR, 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 (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 (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 (sizetype, TREE_OPERAND (incr, 1));
400
401                   if (TREE_CODE (incr) == POSTDECREMENT_EXPR
402                       || TREE_CODE (incr) == PREDECREMENT_EXPR)
403                     t = fold_build1 (NEGATE_EXPR, sizetype, t);
404                   t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (decl), decl, t);
405                   incr = build2 (MODIFY_EXPR, void_type_node, decl, t);
406                 }
407               break;
408
409             case MODIFY_EXPR:
410               if (TREE_OPERAND (incr, 0) != decl)
411                 break;
412               if (TREE_OPERAND (incr, 1) == decl)
413                 break;
414               if (TREE_CODE (TREE_OPERAND (incr, 1)) == PLUS_EXPR
415                   && (TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl
416                       || TREE_OPERAND (TREE_OPERAND (incr, 1), 1) == decl))
417                 incr_ok = true;
418               else if ((TREE_CODE (TREE_OPERAND (incr, 1)) == MINUS_EXPR
419                         || (TREE_CODE (TREE_OPERAND (incr, 1))
420                             == POINTER_PLUS_EXPR))
421                        && TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl)
422                 incr_ok = true;
423               else
424                 {
425                   tree t = check_omp_for_incr_expr (TREE_OPERAND (incr, 1),
426                                                     decl);
427                   if (t != error_mark_node)
428                     {
429                       incr_ok = true;
430                       t = build2 (PLUS_EXPR, TREE_TYPE (decl), decl, t);
431                       incr = build2 (MODIFY_EXPR, void_type_node, decl, t);
432                     }
433                 }
434               break;
435
436             default:
437               break;
438             }
439           if (!incr_ok)
440             {
441               error_at (elocus, "invalid increment expression");
442               fail = true;
443             }
444         }
445
446       TREE_VEC_ELT (initv, i) = init;
447       TREE_VEC_ELT (incrv, i) = incr;
448     }
449
450   if (fail)
451     return NULL;
452   else
453     {
454       tree t = make_node (OMP_FOR);
455
456       TREE_TYPE (t) = void_type_node;
457       OMP_FOR_INIT (t) = initv;
458       OMP_FOR_COND (t) = condv;
459       OMP_FOR_INCR (t) = incrv;
460       OMP_FOR_BODY (t) = body;
461       OMP_FOR_PRE_BODY (t) = pre_body;
462
463       SET_EXPR_LOCATION (t, locus);
464       return add_stmt (t);
465     }
466 }
467
468
469 /* Divide CLAUSES into two lists: those that apply to a parallel
470    construct, and those that apply to a work-sharing construct.  Place
471    the results in *PAR_CLAUSES and *WS_CLAUSES respectively.  In
472    addition, add a nowait clause to the work-sharing list.  LOC is the
473    location of the OMP_PARALLEL*.  */
474
475 void
476 c_split_parallel_clauses (location_t loc, tree clauses,
477                           tree *par_clauses, tree *ws_clauses)
478 {
479   tree next;
480
481   *par_clauses = NULL;
482   *ws_clauses = build_omp_clause (loc, OMP_CLAUSE_NOWAIT);
483
484   for (; clauses ; clauses = next)
485     {
486       next = OMP_CLAUSE_CHAIN (clauses);
487
488       switch (OMP_CLAUSE_CODE (clauses))
489         {
490         case OMP_CLAUSE_PRIVATE:
491         case OMP_CLAUSE_SHARED:
492         case OMP_CLAUSE_FIRSTPRIVATE:
493         case OMP_CLAUSE_LASTPRIVATE:
494         case OMP_CLAUSE_REDUCTION:
495         case OMP_CLAUSE_COPYIN:
496         case OMP_CLAUSE_IF:
497         case OMP_CLAUSE_NUM_THREADS:
498         case OMP_CLAUSE_DEFAULT:
499           OMP_CLAUSE_CHAIN (clauses) = *par_clauses;
500           *par_clauses = clauses;
501           break;
502
503         case OMP_CLAUSE_SCHEDULE:
504         case OMP_CLAUSE_ORDERED:
505         case OMP_CLAUSE_COLLAPSE:
506           OMP_CLAUSE_CHAIN (clauses) = *ws_clauses;
507           *ws_clauses = clauses;
508           break;
509
510         default:
511           gcc_unreachable ();
512         }
513     }
514 }
515
516 /* True if OpenMP sharing attribute of DECL is predetermined.  */
517
518 enum omp_clause_default_kind
519 c_omp_predetermined_sharing (tree decl)
520 {
521   /* Variables with const-qualified type having no mutable member
522      are predetermined shared.  */
523   if (TREE_READONLY (decl))
524     return OMP_CLAUSE_DEFAULT_SHARED;
525
526   return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
527 }