OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gcc-4.2.2/] [gcc/] [c-omp.c] - Blame information for rev 865

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 38 julius
/* 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_function_call_expr (x, NULL);
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_function_call_expr (x, NULL);
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
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.