OSDN Git Service

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