OSDN Git Service

* gcc.dg/debug/dwarf2/aranges-fnsec-1.c: Add -w to dg-options.
[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 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 "tree-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 atomic construct.  The expression to be 
84    implemented atomically is LHS code= RHS.  The value returned is
85    either error_mark_node (if the construct was erroneous) or an
86    OMP_ATOMIC node which should be added to the current statement tree
87    with add_stmt.  */
88
89 tree
90 c_finish_omp_atomic (enum tree_code code, tree lhs, tree rhs)
91 {
92   tree x, type, addr;
93
94   if (lhs == error_mark_node || rhs == error_mark_node)
95     return error_mark_node;
96
97   /* ??? According to one reading of the OpenMP spec, complex type are
98      supported, but there are no atomic stores for any architecture.
99      But at least icc 9.0 doesn't support complex types here either.
100      And lets not even talk about vector types...  */
101   type = TREE_TYPE (lhs);
102   if (!INTEGRAL_TYPE_P (type)
103       && !POINTER_TYPE_P (type)
104       && !SCALAR_FLOAT_TYPE_P (type))
105     {
106       error ("invalid expression type for %<#pragma omp atomic%>");
107       return error_mark_node;
108     }
109
110   /* ??? Validate that rhs does not overlap lhs.  */
111
112   /* Take and save the address of the lhs.  From then on we'll reference it
113      via indirection.  */
114   addr = build_unary_op (ADDR_EXPR, lhs, 0);
115   if (addr == error_mark_node)
116     return error_mark_node;
117   addr = save_expr (addr);
118   if (TREE_CODE (addr) != SAVE_EXPR
119       && (TREE_CODE (addr) != ADDR_EXPR
120           || TREE_CODE (TREE_OPERAND (addr, 0)) != VAR_DECL))
121     {
122       /* Make sure LHS is simple enough so that goa_lhs_expr_p can recognize
123          it even after unsharing function body.  */
124       tree var = create_tmp_var_raw (TREE_TYPE (addr), NULL);
125       addr = build4 (TARGET_EXPR, TREE_TYPE (addr), var, addr, NULL, NULL);
126     }
127   lhs = build_indirect_ref (addr, NULL);
128
129   /* There are lots of warnings, errors, and conversions that need to happen
130      in the course of interpreting a statement.  Use the normal mechanisms
131      to do this, and then take it apart again.  */
132   x = build_modify_expr (lhs, code, rhs);
133   if (x == error_mark_node)
134     return error_mark_node;
135   gcc_assert (TREE_CODE (x) == MODIFY_EXPR);  
136   rhs = TREE_OPERAND (x, 1);
137
138   /* Punt the actual generation of atomic operations to common code.  */
139   return build2 (OMP_ATOMIC, void_type_node, addr, rhs);
140 }
141
142
143 /* Complete a #pragma omp flush construct.  We don't do anything with the
144    variable list that the syntax allows.  */
145
146 void
147 c_finish_omp_flush (void)
148 {
149   tree x;
150
151   x = built_in_decls[BUILT_IN_SYNCHRONIZE];
152   x = build_call_expr (x, 0);
153   add_stmt (x);
154 }
155
156
157 /* Check and canonicalize #pragma omp for increment expression.
158    Helper function for c_finish_omp_for.  */
159
160 static tree
161 check_omp_for_incr_expr (tree exp, tree decl)
162 {
163   tree t;
164
165   if (!INTEGRAL_TYPE_P (TREE_TYPE (exp))
166       || TYPE_PRECISION (TREE_TYPE (exp)) < TYPE_PRECISION (TREE_TYPE (decl)))
167     return error_mark_node;
168
169   if (exp == decl)
170     return build_int_cst (TREE_TYPE (exp), 0);
171
172   switch (TREE_CODE (exp))
173     {
174     case NOP_EXPR:
175     case CONVERT_EXPR:
176       t = check_omp_for_incr_expr (TREE_OPERAND (exp, 0), decl);
177       if (t != error_mark_node)
178         return fold_convert (TREE_TYPE (exp), t);
179       break;
180     case MINUS_EXPR:
181       t = check_omp_for_incr_expr (TREE_OPERAND (exp, 0), decl);
182       if (t != error_mark_node)
183         return fold_build2 (MINUS_EXPR, TREE_TYPE (exp), t, TREE_OPERAND (exp, 1));
184       break;
185     case PLUS_EXPR:
186       t = check_omp_for_incr_expr (TREE_OPERAND (exp, 0), decl);
187       if (t != error_mark_node)
188         return fold_build2 (PLUS_EXPR, TREE_TYPE (exp), t, TREE_OPERAND (exp, 1));
189       t = check_omp_for_incr_expr (TREE_OPERAND (exp, 1), decl);
190       if (t != error_mark_node)
191         return fold_build2 (PLUS_EXPR, TREE_TYPE (exp), TREE_OPERAND (exp, 0), t);
192       break;
193     default:
194       break;
195     }
196
197   return error_mark_node;
198 }
199
200 /* Validate and emit code for the OpenMP directive #pragma omp for.
201    INIT, COND, INCR, BODY and PRE_BODY are the five basic elements
202    of the loop (initialization expression, controlling predicate, increment
203    expression, body of the loop and statements to go before the loop).
204    DECL is the iteration variable.  */
205
206 tree
207 c_finish_omp_for (location_t locus, tree decl, tree init, tree cond,
208                   tree incr, tree body, tree pre_body)
209 {
210   location_t elocus = locus;
211   bool fail = false;
212
213   if (EXPR_HAS_LOCATION (init))
214     elocus = EXPR_LOCATION (init);
215
216   /* Validate the iteration variable.  */
217   if (!INTEGRAL_TYPE_P (TREE_TYPE (decl)))
218     {
219       error ("%Hinvalid type for iteration variable %qE", &elocus, decl);
220       fail = true;
221     }
222   if (TYPE_UNSIGNED (TREE_TYPE (decl)))
223     warning (0, "%Hiteration variable %qE is unsigned", &elocus, decl);
224
225   /* In the case of "for (int i = 0...)", init will be a decl.  It should
226      have a DECL_INITIAL that we can turn into an assignment.  */
227   if (init == decl)
228     {
229       elocus = DECL_SOURCE_LOCATION (decl);
230
231       init = DECL_INITIAL (decl);
232       if (init == NULL)
233         {
234           error ("%H%qE is not initialized", &elocus, decl);
235           init = integer_zero_node;
236           fail = true;
237         }
238
239       init = build_modify_expr (decl, NOP_EXPR, init);
240       SET_EXPR_LOCATION (init, elocus);
241     }
242   gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
243   gcc_assert (TREE_OPERAND (init, 0) == decl);
244   
245   if (cond == NULL_TREE)
246     {
247       error ("%Hmissing controlling predicate", &elocus);
248       fail = true;
249     }
250   else
251     {
252       bool cond_ok = false;
253
254       if (EXPR_HAS_LOCATION (cond))
255         elocus = EXPR_LOCATION (cond);
256
257       if (TREE_CODE (cond) == LT_EXPR
258           || TREE_CODE (cond) == LE_EXPR
259           || TREE_CODE (cond) == GT_EXPR
260           || TREE_CODE (cond) == GE_EXPR)
261         {
262           tree op0 = TREE_OPERAND (cond, 0);
263           tree op1 = TREE_OPERAND (cond, 1);
264
265           /* 2.5.1.  The comparison in the condition is computed in the type
266              of DECL, otherwise the behavior is undefined.
267
268              For example:
269              long n; int i;
270              i < n;
271
272              according to ISO will be evaluated as:
273              (long)i < n;
274
275              We want to force:
276              i < (int)n;  */
277           if (TREE_CODE (op0) == NOP_EXPR
278               && decl == TREE_OPERAND (op0, 0))
279             {
280               TREE_OPERAND (cond, 0) = TREE_OPERAND (op0, 0);
281               TREE_OPERAND (cond, 1) = fold_build1 (NOP_EXPR, TREE_TYPE (decl),
282                                                     TREE_OPERAND (cond, 1));
283             }
284           else if (TREE_CODE (op1) == NOP_EXPR
285                    && decl == TREE_OPERAND (op1, 0))
286             {
287               TREE_OPERAND (cond, 1) = TREE_OPERAND (op1, 0);
288               TREE_OPERAND (cond, 0) = fold_build1 (NOP_EXPR, TREE_TYPE (decl),
289                                                     TREE_OPERAND (cond, 0));
290             }
291
292           if (decl == TREE_OPERAND (cond, 0))
293             cond_ok = true;
294           else if (decl == TREE_OPERAND (cond, 1))
295             {
296               TREE_SET_CODE (cond, swap_tree_comparison (TREE_CODE (cond)));
297               TREE_OPERAND (cond, 1) = TREE_OPERAND (cond, 0);
298               TREE_OPERAND (cond, 0) = decl;
299               cond_ok = true;
300             }
301         }
302
303       if (!cond_ok)
304         {
305           error ("%Hinvalid controlling predicate", &elocus);
306           fail = true;
307         }
308     }
309
310   if (incr == NULL_TREE)
311     {
312       error ("%Hmissing increment expression", &elocus);
313       fail = true;
314     }
315   else
316     {
317       bool incr_ok = false;
318
319       if (EXPR_HAS_LOCATION (incr))
320         elocus = EXPR_LOCATION (incr);
321
322       /* Check all the valid increment expressions: v++, v--, ++v, --v,
323          v = v + incr, v = incr + v and v = v - incr.  */
324       switch (TREE_CODE (incr))
325         {
326         case POSTINCREMENT_EXPR:
327         case PREINCREMENT_EXPR:
328         case POSTDECREMENT_EXPR:
329         case PREDECREMENT_EXPR:
330           incr_ok = (TREE_OPERAND (incr, 0) == decl);
331           break;
332
333         case MODIFY_EXPR:
334           if (TREE_OPERAND (incr, 0) != decl)
335             break;
336           if (TREE_OPERAND (incr, 1) == decl)
337             break;
338           if (TREE_CODE (TREE_OPERAND (incr, 1)) == PLUS_EXPR
339               && (TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl
340                   || TREE_OPERAND (TREE_OPERAND (incr, 1), 1) == decl))
341             incr_ok = true;
342           else if (TREE_CODE (TREE_OPERAND (incr, 1)) == MINUS_EXPR
343                    && TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl)
344             incr_ok = true;
345           else
346             {
347               tree t = check_omp_for_incr_expr (TREE_OPERAND (incr, 1), decl);
348               if (t != error_mark_node)
349                 {
350                   incr_ok = true;
351                   t = build2 (PLUS_EXPR, TREE_TYPE (decl), decl, t);
352                   incr = build2 (MODIFY_EXPR, void_type_node, decl, t);
353                 }
354             }
355           break;
356
357         default:
358           break;
359         }
360       if (!incr_ok)
361         {
362           error ("%Hinvalid increment expression", &elocus);
363           fail = true;
364         }
365     }
366
367   if (fail)
368     return NULL;
369   else
370     {
371       tree t = make_node (OMP_FOR);
372
373       TREE_TYPE (t) = void_type_node;
374       OMP_FOR_INIT (t) = init;
375       OMP_FOR_COND (t) = cond;
376       OMP_FOR_INCR (t) = incr;
377       OMP_FOR_BODY (t) = body;
378       OMP_FOR_PRE_BODY (t) = pre_body;
379
380       SET_EXPR_LOCATION (t, locus);
381       return add_stmt (t);
382     }
383 }
384
385
386 /* Divide CLAUSES into two lists: those that apply to a parallel construct,
387    and those that apply to a work-sharing construct.  Place the results in
388    *PAR_CLAUSES and *WS_CLAUSES respectively.  In addition, add a nowait
389    clause to the work-sharing list.  */
390
391 void
392 c_split_parallel_clauses (tree clauses, tree *par_clauses, tree *ws_clauses)
393 {
394   tree next;
395
396   *par_clauses = NULL;
397   *ws_clauses = build_omp_clause (OMP_CLAUSE_NOWAIT);
398
399   for (; clauses ; clauses = next)
400     {
401       next = OMP_CLAUSE_CHAIN (clauses);
402
403       switch (OMP_CLAUSE_CODE (clauses))
404         {
405         case OMP_CLAUSE_PRIVATE:
406         case OMP_CLAUSE_SHARED:
407         case OMP_CLAUSE_FIRSTPRIVATE:
408         case OMP_CLAUSE_LASTPRIVATE:
409         case OMP_CLAUSE_REDUCTION:
410         case OMP_CLAUSE_COPYIN:
411         case OMP_CLAUSE_IF:
412         case OMP_CLAUSE_NUM_THREADS:
413         case OMP_CLAUSE_DEFAULT:
414           OMP_CLAUSE_CHAIN (clauses) = *par_clauses;
415           *par_clauses = clauses;
416           break;
417
418         case OMP_CLAUSE_SCHEDULE:
419         case OMP_CLAUSE_ORDERED:
420           OMP_CLAUSE_CHAIN (clauses) = *ws_clauses;
421           *ws_clauses = clauses;
422           break;
423
424         default:
425           gcc_unreachable ();
426         }
427     }
428 }
429
430 /* True if OpenMP sharing attribute of DECL is predetermined.  */
431
432 enum omp_clause_default_kind
433 c_omp_predetermined_sharing (tree decl)
434 {
435   /* Variables with const-qualified type having no mutable member
436      are predetermined shared.  */
437   if (TREE_READONLY (decl))
438     return OMP_CLAUSE_DEFAULT_SHARED;
439
440   return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
441 }