OSDN Git Service

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