OSDN Git Service

gcc/fortran:
[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       t = check_omp_for_incr_expr (TREE_OPERAND (exp, 0), decl);
176       if (t != error_mark_node)
177         return fold_convert (TREE_TYPE (exp), t);
178       break;
179     case MINUS_EXPR:
180       t = check_omp_for_incr_expr (TREE_OPERAND (exp, 0), decl);
181       if (t != error_mark_node)
182         return fold_build2 (MINUS_EXPR, TREE_TYPE (exp), t, TREE_OPERAND (exp, 1));
183       break;
184     case PLUS_EXPR:
185       t = check_omp_for_incr_expr (TREE_OPERAND (exp, 0), decl);
186       if (t != error_mark_node)
187         return fold_build2 (PLUS_EXPR, TREE_TYPE (exp), t, TREE_OPERAND (exp, 1));
188       t = check_omp_for_incr_expr (TREE_OPERAND (exp, 1), decl);
189       if (t != error_mark_node)
190         return fold_build2 (PLUS_EXPR, TREE_TYPE (exp), TREE_OPERAND (exp, 0), t);
191       break;
192     default:
193       break;
194     }
195
196   return error_mark_node;
197 }
198
199 /* Validate and emit code for the OpenMP directive #pragma omp for.
200    INIT, COND, INCR, BODY and PRE_BODY are the five basic elements
201    of the loop (initialization expression, controlling predicate, increment
202    expression, body of the loop and statements to go before the loop).
203    DECL is the iteration variable.  */
204
205 tree
206 c_finish_omp_for (location_t locus, tree decl, tree init, tree cond,
207                   tree incr, tree body, tree pre_body)
208 {
209   location_t elocus = locus;
210   bool fail = false;
211
212   if (EXPR_HAS_LOCATION (init))
213     elocus = EXPR_LOCATION (init);
214
215   /* Validate the iteration variable.  */
216   if (!INTEGRAL_TYPE_P (TREE_TYPE (decl)))
217     {
218       error ("%Hinvalid type for iteration variable %qE", &elocus, decl);
219       fail = true;
220     }
221   if (TYPE_UNSIGNED (TREE_TYPE (decl)))
222     warning (0, "%Hiteration variable %qE is unsigned", &elocus, decl);
223
224   /* In the case of "for (int i = 0...)", init will be a decl.  It should
225      have a DECL_INITIAL that we can turn into an assignment.  */
226   if (init == decl)
227     {
228       elocus = DECL_SOURCE_LOCATION (decl);
229
230       init = DECL_INITIAL (decl);
231       if (init == NULL)
232         {
233           error ("%H%qE is not initialized", &elocus, decl);
234           init = integer_zero_node;
235           fail = true;
236         }
237
238       init = build_modify_expr (decl, NOP_EXPR, init);
239       SET_EXPR_LOCATION (init, elocus);
240     }
241   gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
242   gcc_assert (TREE_OPERAND (init, 0) == decl);
243   
244   if (cond == NULL_TREE)
245     {
246       error ("%Hmissing controlling predicate", &elocus);
247       fail = true;
248     }
249   else
250     {
251       bool cond_ok = false;
252
253       if (EXPR_HAS_LOCATION (cond))
254         elocus = EXPR_LOCATION (cond);
255
256       if (TREE_CODE (cond) == LT_EXPR
257           || TREE_CODE (cond) == LE_EXPR
258           || TREE_CODE (cond) == GT_EXPR
259           || TREE_CODE (cond) == GE_EXPR)
260         {
261           tree op0 = TREE_OPERAND (cond, 0);
262           tree op1 = TREE_OPERAND (cond, 1);
263
264           /* 2.5.1.  The comparison in the condition is computed in the type
265              of DECL, otherwise the behavior is undefined.
266
267              For example:
268              long n; int i;
269              i < n;
270
271              according to ISO will be evaluated as:
272              (long)i < n;
273
274              We want to force:
275              i < (int)n;  */
276           if (TREE_CODE (op0) == NOP_EXPR
277               && decl == TREE_OPERAND (op0, 0))
278             {
279               TREE_OPERAND (cond, 0) = TREE_OPERAND (op0, 0);
280               TREE_OPERAND (cond, 1) = fold_build1 (NOP_EXPR, TREE_TYPE (decl),
281                                                     TREE_OPERAND (cond, 1));
282             }
283           else if (TREE_CODE (op1) == NOP_EXPR
284                    && decl == TREE_OPERAND (op1, 0))
285             {
286               TREE_OPERAND (cond, 1) = TREE_OPERAND (op1, 0);
287               TREE_OPERAND (cond, 0) = fold_build1 (NOP_EXPR, TREE_TYPE (decl),
288                                                     TREE_OPERAND (cond, 0));
289             }
290
291           if (decl == TREE_OPERAND (cond, 0))
292             cond_ok = true;
293           else if (decl == TREE_OPERAND (cond, 1))
294             {
295               TREE_SET_CODE (cond, swap_tree_comparison (TREE_CODE (cond)));
296               TREE_OPERAND (cond, 1) = TREE_OPERAND (cond, 0);
297               TREE_OPERAND (cond, 0) = decl;
298               cond_ok = true;
299             }
300         }
301
302       if (!cond_ok)
303         {
304           error ("%Hinvalid controlling predicate", &elocus);
305           fail = true;
306         }
307     }
308
309   if (incr == NULL_TREE)
310     {
311       error ("%Hmissing increment expression", &elocus);
312       fail = true;
313     }
314   else
315     {
316       bool incr_ok = false;
317
318       if (EXPR_HAS_LOCATION (incr))
319         elocus = EXPR_LOCATION (incr);
320
321       /* Check all the valid increment expressions: v++, v--, ++v, --v,
322          v = v + incr, v = incr + v and v = v - incr.  */
323       switch (TREE_CODE (incr))
324         {
325         case POSTINCREMENT_EXPR:
326         case PREINCREMENT_EXPR:
327         case POSTDECREMENT_EXPR:
328         case PREDECREMENT_EXPR:
329           incr_ok = (TREE_OPERAND (incr, 0) == decl);
330           break;
331
332         case MODIFY_EXPR:
333           if (TREE_OPERAND (incr, 0) != decl)
334             break;
335           if (TREE_OPERAND (incr, 1) == decl)
336             break;
337           if (TREE_CODE (TREE_OPERAND (incr, 1)) == PLUS_EXPR
338               && (TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl
339                   || TREE_OPERAND (TREE_OPERAND (incr, 1), 1) == decl))
340             incr_ok = true;
341           else if (TREE_CODE (TREE_OPERAND (incr, 1)) == MINUS_EXPR
342                    && TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl)
343             incr_ok = true;
344           else
345             {
346               tree t = check_omp_for_incr_expr (TREE_OPERAND (incr, 1), decl);
347               if (t != error_mark_node)
348                 {
349                   incr_ok = true;
350                   t = build2 (PLUS_EXPR, TREE_TYPE (decl), decl, t);
351                   incr = build2 (MODIFY_EXPR, void_type_node, decl, t);
352                 }
353             }
354           break;
355
356         default:
357           break;
358         }
359       if (!incr_ok)
360         {
361           error ("%Hinvalid increment expression", &elocus);
362           fail = true;
363         }
364     }
365
366   if (fail)
367     return NULL;
368   else
369     {
370       tree t = make_node (OMP_FOR);
371
372       TREE_TYPE (t) = void_type_node;
373       OMP_FOR_INIT (t) = init;
374       OMP_FOR_COND (t) = cond;
375       OMP_FOR_INCR (t) = incr;
376       OMP_FOR_BODY (t) = body;
377       OMP_FOR_PRE_BODY (t) = pre_body;
378
379       SET_EXPR_LOCATION (t, locus);
380       return add_stmt (t);
381     }
382 }
383
384
385 /* Divide CLAUSES into two lists: those that apply to a parallel construct,
386    and those that apply to a work-sharing construct.  Place the results in
387    *PAR_CLAUSES and *WS_CLAUSES respectively.  In addition, add a nowait
388    clause to the work-sharing list.  */
389
390 void
391 c_split_parallel_clauses (tree clauses, tree *par_clauses, tree *ws_clauses)
392 {
393   tree next;
394
395   *par_clauses = NULL;
396   *ws_clauses = build_omp_clause (OMP_CLAUSE_NOWAIT);
397
398   for (; clauses ; clauses = next)
399     {
400       next = OMP_CLAUSE_CHAIN (clauses);
401
402       switch (OMP_CLAUSE_CODE (clauses))
403         {
404         case OMP_CLAUSE_PRIVATE:
405         case OMP_CLAUSE_SHARED:
406         case OMP_CLAUSE_FIRSTPRIVATE:
407         case OMP_CLAUSE_LASTPRIVATE:
408         case OMP_CLAUSE_REDUCTION:
409         case OMP_CLAUSE_COPYIN:
410         case OMP_CLAUSE_IF:
411         case OMP_CLAUSE_NUM_THREADS:
412         case OMP_CLAUSE_DEFAULT:
413           OMP_CLAUSE_CHAIN (clauses) = *par_clauses;
414           *par_clauses = clauses;
415           break;
416
417         case OMP_CLAUSE_SCHEDULE:
418         case OMP_CLAUSE_ORDERED:
419           OMP_CLAUSE_CHAIN (clauses) = *ws_clauses;
420           *ws_clauses = clauses;
421           break;
422
423         default:
424           gcc_unreachable ();
425         }
426     }
427 }
428
429 /* True if OpenMP sharing attribute of DECL is predetermined.  */
430
431 enum omp_clause_default_kind
432 c_omp_predetermined_sharing (tree decl)
433 {
434   /* Variables with const-qualified type having no mutable member
435      are predetermined shared.  */
436   if (TREE_READONLY (decl))
437     return OMP_CLAUSE_DEFAULT_SHARED;
438
439   return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
440 }