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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [c-family/] [c-omp.c] - Blame information for rev 762

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

Line No. Rev Author Line
1 707 jeremybenn
/* 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, 2008, 2009, 2010, 2011
5
   Free Software Foundation, Inc.
6
   Contributed by Richard Henderson <rth@redhat.com>,
7
                  Diego Novillo <dnovillo@redhat.com>.
8
 
9
This file is part of GCC.
10
 
11
GCC is free software; you can redistribute it and/or modify it under
12
the terms of the GNU General Public License as published by the Free
13
Software Foundation; either version 3, or (at your option) any later
14
version.
15
 
16
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
17
WARRANTY; without even the implied warranty of MERCHANTABILITY or
18
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
19
for more details.
20
 
21
You should have received a copy of the GNU General Public License
22
along with GCC; see the file COPYING3.  If not see
23
<http://www.gnu.org/licenses/>.  */
24
 
25
#include "config.h"
26
#include "system.h"
27
#include "coretypes.h"
28
#include "tree.h"
29
#include "c-common.h"
30
#include "gimple.h"             /* For create_tmp_var_raw.  */
31
#include "langhooks.h"
32
 
33
 
34
/* Complete a #pragma omp master construct.  STMT is the structured-block
35
   that follows the pragma.  LOC is the l*/
36
 
37
tree
38
c_finish_omp_master (location_t loc, tree stmt)
39
{
40
  tree t = add_stmt (build1 (OMP_MASTER, void_type_node, stmt));
41
  SET_EXPR_LOCATION (t, loc);
42
  return t;
43
}
44
 
45
/* Complete a #pragma omp critical construct.  STMT is the structured-block
46
   that follows the pragma, NAME is the identifier in the pragma, or null
47
   if it was omitted.  LOC is the location of the #pragma.  */
48
 
49
tree
50
c_finish_omp_critical (location_t loc, tree body, tree name)
51
{
52
  tree stmt = make_node (OMP_CRITICAL);
53
  TREE_TYPE (stmt) = void_type_node;
54
  OMP_CRITICAL_BODY (stmt) = body;
55
  OMP_CRITICAL_NAME (stmt) = name;
56
  SET_EXPR_LOCATION (stmt, loc);
57
  return add_stmt (stmt);
58
}
59
 
60
/* Complete a #pragma omp ordered construct.  STMT is the structured-block
61
   that follows the pragma.  LOC is the location of the #pragma.  */
62
 
63
tree
64
c_finish_omp_ordered (location_t loc, tree stmt)
65
{
66
  tree t = build1 (OMP_ORDERED, void_type_node, stmt);
67
  SET_EXPR_LOCATION (t, loc);
68
  return add_stmt (t);
69
}
70
 
71
 
72
/* Complete a #pragma omp barrier construct.  LOC is the location of
73
   the #pragma.  */
74
 
75
void
76
c_finish_omp_barrier (location_t loc)
77
{
78
  tree x;
79
 
80
  x = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER);
81
  x = build_call_expr_loc (loc, x, 0);
82
  add_stmt (x);
83
}
84
 
85
 
86
/* Complete a #pragma omp taskwait construct.  LOC is the location of the
87
   pragma.  */
88
 
89
void
90
c_finish_omp_taskwait (location_t loc)
91
{
92
  tree x;
93
 
94
  x = builtin_decl_explicit (BUILT_IN_GOMP_TASKWAIT);
95
  x = build_call_expr_loc (loc, x, 0);
96
  add_stmt (x);
97
}
98
 
99
 
100
/* Complete a #pragma omp taskyield construct.  LOC is the location of the
101
   pragma.  */
102
 
103
void
104
c_finish_omp_taskyield (location_t loc)
105
{
106
  tree x;
107
 
108
  x = builtin_decl_explicit (BUILT_IN_GOMP_TASKYIELD);
109
  x = build_call_expr_loc (loc, x, 0);
110
  add_stmt (x);
111
}
112
 
113
 
114
/* Complete a #pragma omp atomic construct.  For CODE OMP_ATOMIC
115
   the expression to be implemented atomically is LHS opcode= RHS.
116
   For OMP_ATOMIC_READ V = LHS, for OMP_ATOMIC_CAPTURE_{NEW,OLD} LHS
117
   opcode= RHS with the new or old content of LHS returned.
118
   LOC is the location of the atomic statement.  The value returned
119
   is either error_mark_node (if the construct was erroneous) or an
120
   OMP_ATOMIC* node which should be added to the current statement
121
   tree with add_stmt.  */
122
 
123
tree
124
c_finish_omp_atomic (location_t loc, enum tree_code code,
125
                     enum tree_code opcode, tree lhs, tree rhs,
126
                     tree v, tree lhs1, tree rhs1)
127
{
128
  tree x, type, addr;
129
 
130
  if (lhs == error_mark_node || rhs == error_mark_node
131
      || v == error_mark_node || lhs1 == error_mark_node
132
      || rhs1 == error_mark_node)
133
    return error_mark_node;
134
 
135
  /* ??? According to one reading of the OpenMP spec, complex type are
136
     supported, but there are no atomic stores for any architecture.
137
     But at least icc 9.0 doesn't support complex types here either.
138
     And lets not even talk about vector types...  */
139
  type = TREE_TYPE (lhs);
140
  if (!INTEGRAL_TYPE_P (type)
141
      && !POINTER_TYPE_P (type)
142
      && !SCALAR_FLOAT_TYPE_P (type))
143
    {
144
      error_at (loc, "invalid expression type for %<#pragma omp atomic%>");
145
      return error_mark_node;
146
    }
147
 
148
  /* ??? Validate that rhs does not overlap lhs.  */
149
 
150
  /* Take and save the address of the lhs.  From then on we'll reference it
151
     via indirection.  */
152
  addr = build_unary_op (loc, ADDR_EXPR, lhs, 0);
153
  if (addr == error_mark_node)
154
    return error_mark_node;
155
  addr = save_expr (addr);
156
  if (TREE_CODE (addr) != SAVE_EXPR
157
      && (TREE_CODE (addr) != ADDR_EXPR
158
          || TREE_CODE (TREE_OPERAND (addr, 0)) != VAR_DECL))
159
    {
160
      /* Make sure LHS is simple enough so that goa_lhs_expr_p can recognize
161
         it even after unsharing function body.  */
162
      tree var = create_tmp_var_raw (TREE_TYPE (addr), NULL);
163
      DECL_CONTEXT (var) = current_function_decl;
164
      addr = build4 (TARGET_EXPR, TREE_TYPE (addr), var, addr, NULL, NULL);
165
    }
166
  lhs = build_indirect_ref (loc, addr, RO_NULL);
167
 
168
  if (code == OMP_ATOMIC_READ)
169
    {
170
      x = build1 (OMP_ATOMIC_READ, type, addr);
171
      SET_EXPR_LOCATION (x, loc);
172
      return build_modify_expr (loc, v, NULL_TREE, NOP_EXPR,
173
                                loc, x, NULL_TREE);
174
      return x;
175
    }
176
 
177
  /* There are lots of warnings, errors, and conversions that need to happen
178
     in the course of interpreting a statement.  Use the normal mechanisms
179
     to do this, and then take it apart again.  */
180
  x = build_modify_expr (input_location, lhs, NULL_TREE, opcode,
181
                         input_location, rhs, NULL_TREE);
182
  if (x == error_mark_node)
183
    return error_mark_node;
184
  gcc_assert (TREE_CODE (x) == MODIFY_EXPR);
185
  rhs = TREE_OPERAND (x, 1);
186
 
187
  /* Punt the actual generation of atomic operations to common code.  */
188
  if (code == OMP_ATOMIC)
189
    type = void_type_node;
190
  x = build2 (code, type, addr, rhs);
191
  SET_EXPR_LOCATION (x, loc);
192
 
193
  /* Generally it is hard to prove lhs1 and lhs are the same memory
194
     location, just diagnose different variables.  */
195
  if (rhs1
196
      && TREE_CODE (rhs1) == VAR_DECL
197
      && TREE_CODE (lhs) == VAR_DECL
198
      && rhs1 != lhs)
199
    {
200
      if (code == OMP_ATOMIC)
201
        error_at (loc, "%<#pragma omp atomic update%> uses two different variables for memory");
202
      else
203
        error_at (loc, "%<#pragma omp atomic capture%> uses two different variables for memory");
204
      return error_mark_node;
205
    }
206
 
207
  if (code != OMP_ATOMIC)
208
    {
209
      /* Generally it is hard to prove lhs1 and lhs are the same memory
210
         location, just diagnose different variables.  */
211
      if (lhs1 && TREE_CODE (lhs1) == VAR_DECL && TREE_CODE (lhs) == VAR_DECL)
212
        {
213
          if (lhs1 != lhs)
214
            {
215
              error_at (loc, "%<#pragma omp atomic capture%> uses two different variables for memory");
216
              return error_mark_node;
217
            }
218
        }
219
      x = build_modify_expr (loc, v, NULL_TREE, NOP_EXPR,
220
                             loc, x, NULL_TREE);
221
      if (rhs1 && rhs1 != lhs)
222
        {
223
          tree rhs1addr = build_unary_op (loc, ADDR_EXPR, rhs1, 0);
224
          if (rhs1addr == error_mark_node)
225
            return error_mark_node;
226
          x = omit_one_operand_loc (loc, type, x, rhs1addr);
227
        }
228
      if (lhs1 && lhs1 != lhs)
229
        {
230
          tree lhs1addr = build_unary_op (loc, ADDR_EXPR, lhs1, 0);
231
          if (lhs1addr == error_mark_node)
232
            return error_mark_node;
233
          if (code == OMP_ATOMIC_CAPTURE_OLD)
234
            x = omit_one_operand_loc (loc, type, x, lhs1addr);
235
          else
236
            {
237
              x = save_expr (x);
238
              x = omit_two_operands_loc (loc, type, x, x, lhs1addr);
239
            }
240
        }
241
    }
242
  else if (rhs1 && rhs1 != lhs)
243
    {
244
      tree rhs1addr = build_unary_op (loc, ADDR_EXPR, rhs1, 0);
245
      if (rhs1addr == error_mark_node)
246
        return error_mark_node;
247
      x = omit_one_operand_loc (loc, type, x, rhs1addr);
248
    }
249
 
250
  return x;
251
}
252
 
253
 
254
/* Complete a #pragma omp flush construct.  We don't do anything with
255
   the variable list that the syntax allows.  LOC is the location of
256
   the #pragma.  */
257
 
258
void
259
c_finish_omp_flush (location_t loc)
260
{
261
  tree x;
262
 
263
  x = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE);
264
  x = build_call_expr_loc (loc, x, 0);
265
  add_stmt (x);
266
}
267
 
268
 
269
/* Check and canonicalize #pragma omp for increment expression.
270
   Helper function for c_finish_omp_for.  */
271
 
272
static tree
273
check_omp_for_incr_expr (location_t loc, tree exp, tree decl)
274
{
275
  tree t;
276
 
277
  if (!INTEGRAL_TYPE_P (TREE_TYPE (exp))
278
      || TYPE_PRECISION (TREE_TYPE (exp)) < TYPE_PRECISION (TREE_TYPE (decl)))
279
    return error_mark_node;
280
 
281
  if (exp == decl)
282
    return build_int_cst (TREE_TYPE (exp), 0);
283
 
284
  switch (TREE_CODE (exp))
285
    {
286
    CASE_CONVERT:
287
      t = check_omp_for_incr_expr (loc, TREE_OPERAND (exp, 0), decl);
288
      if (t != error_mark_node)
289
        return fold_convert_loc (loc, TREE_TYPE (exp), t);
290
      break;
291
    case MINUS_EXPR:
292
      t = check_omp_for_incr_expr (loc, TREE_OPERAND (exp, 0), decl);
293
      if (t != error_mark_node)
294
        return fold_build2_loc (loc, MINUS_EXPR,
295
                            TREE_TYPE (exp), t, TREE_OPERAND (exp, 1));
296
      break;
297
    case PLUS_EXPR:
298
      t = check_omp_for_incr_expr (loc, TREE_OPERAND (exp, 0), decl);
299
      if (t != error_mark_node)
300
        return fold_build2_loc (loc, PLUS_EXPR,
301
                            TREE_TYPE (exp), t, TREE_OPERAND (exp, 1));
302
      t = check_omp_for_incr_expr (loc, TREE_OPERAND (exp, 1), decl);
303
      if (t != error_mark_node)
304
        return fold_build2_loc (loc, PLUS_EXPR,
305
                            TREE_TYPE (exp), TREE_OPERAND (exp, 0), t);
306
      break;
307
    case COMPOUND_EXPR:
308
      {
309
        /* cp_build_modify_expr forces preevaluation of the RHS to make
310
           sure that it is evaluated before the lvalue-rvalue conversion
311
           is applied to the LHS.  Reconstruct the original expression.  */
312
        tree op0 = TREE_OPERAND (exp, 0);
313
        if (TREE_CODE (op0) == TARGET_EXPR
314
            && !VOID_TYPE_P (TREE_TYPE (op0)))
315
          {
316
            tree op1 = TREE_OPERAND (exp, 1);
317
            tree temp = TARGET_EXPR_SLOT (op0);
318
            if (TREE_CODE_CLASS (TREE_CODE (op1)) == tcc_binary
319
                && TREE_OPERAND (op1, 1) == temp)
320
              {
321
                op1 = copy_node (op1);
322
                TREE_OPERAND (op1, 1) = TARGET_EXPR_INITIAL (op0);
323
                return check_omp_for_incr_expr (loc, op1, decl);
324
              }
325
          }
326
        break;
327
      }
328
    default:
329
      break;
330
    }
331
 
332
  return error_mark_node;
333
}
334
 
335
/* Validate and emit code for the OpenMP directive #pragma omp for.
336
   DECLV is a vector of iteration variables, for each collapsed loop.
337
   INITV, CONDV and INCRV are vectors containing initialization
338
   expressions, controlling predicates and increment expressions.
339
   BODY is the body of the loop and PRE_BODY statements that go before
340
   the loop.  */
341
 
342
tree
343
c_finish_omp_for (location_t locus, tree declv, tree initv, tree condv,
344
                  tree incrv, tree body, tree pre_body)
345
{
346
  location_t elocus;
347
  bool fail = false;
348
  int i;
349
 
350
  gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (initv));
351
  gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (condv));
352
  gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (incrv));
353
  for (i = 0; i < TREE_VEC_LENGTH (declv); i++)
354
    {
355
      tree decl = TREE_VEC_ELT (declv, i);
356
      tree init = TREE_VEC_ELT (initv, i);
357
      tree cond = TREE_VEC_ELT (condv, i);
358
      tree incr = TREE_VEC_ELT (incrv, i);
359
 
360
      elocus = locus;
361
      if (EXPR_HAS_LOCATION (init))
362
        elocus = EXPR_LOCATION (init);
363
 
364
      /* Validate the iteration variable.  */
365
      if (!INTEGRAL_TYPE_P (TREE_TYPE (decl))
366
          && TREE_CODE (TREE_TYPE (decl)) != POINTER_TYPE)
367
        {
368
          error_at (elocus, "invalid type for iteration variable %qE", decl);
369
          fail = true;
370
        }
371
 
372
      /* In the case of "for (int i = 0...)", init will be a decl.  It should
373
         have a DECL_INITIAL that we can turn into an assignment.  */
374
      if (init == decl)
375
        {
376
          elocus = DECL_SOURCE_LOCATION (decl);
377
 
378
          init = DECL_INITIAL (decl);
379
          if (init == NULL)
380
            {
381
              error_at (elocus, "%qE is not initialized", decl);
382
              init = integer_zero_node;
383
              fail = true;
384
            }
385
 
386
          init = build_modify_expr (elocus, decl, NULL_TREE, NOP_EXPR,
387
                                    /* FIXME diagnostics: This should
388
                                       be the location of the INIT.  */
389
                                    elocus,
390
                                    init,
391
                                    NULL_TREE);
392
        }
393
      gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
394
      gcc_assert (TREE_OPERAND (init, 0) == decl);
395
 
396
      if (cond == NULL_TREE)
397
        {
398
          error_at (elocus, "missing controlling predicate");
399
          fail = true;
400
        }
401
      else
402
        {
403
          bool cond_ok = false;
404
 
405
          if (EXPR_HAS_LOCATION (cond))
406
            elocus = EXPR_LOCATION (cond);
407
 
408
          if (TREE_CODE (cond) == LT_EXPR
409
              || TREE_CODE (cond) == LE_EXPR
410
              || TREE_CODE (cond) == GT_EXPR
411
              || TREE_CODE (cond) == GE_EXPR
412
              || TREE_CODE (cond) == NE_EXPR
413
              || TREE_CODE (cond) == EQ_EXPR)
414
            {
415
              tree op0 = TREE_OPERAND (cond, 0);
416
              tree op1 = TREE_OPERAND (cond, 1);
417
 
418
              /* 2.5.1.  The comparison in the condition is computed in
419
                 the type of DECL, otherwise the behavior is undefined.
420
 
421
                 For example:
422
                 long n; int i;
423
                 i < n;
424
 
425
                 according to ISO will be evaluated as:
426
                 (long)i < n;
427
 
428
                 We want to force:
429
                 i < (int)n;  */
430
              if (TREE_CODE (op0) == NOP_EXPR
431
                  && decl == TREE_OPERAND (op0, 0))
432
                {
433
                  TREE_OPERAND (cond, 0) = TREE_OPERAND (op0, 0);
434
                  TREE_OPERAND (cond, 1)
435
                    = fold_build1_loc (elocus, NOP_EXPR, TREE_TYPE (decl),
436
                                   TREE_OPERAND (cond, 1));
437
                }
438
              else if (TREE_CODE (op1) == NOP_EXPR
439
                       && decl == TREE_OPERAND (op1, 0))
440
                {
441
                  TREE_OPERAND (cond, 1) = TREE_OPERAND (op1, 0);
442
                  TREE_OPERAND (cond, 0)
443
                    = fold_build1_loc (elocus, NOP_EXPR, TREE_TYPE (decl),
444
                                   TREE_OPERAND (cond, 0));
445
                }
446
 
447
              if (decl == TREE_OPERAND (cond, 0))
448
                cond_ok = true;
449
              else if (decl == TREE_OPERAND (cond, 1))
450
                {
451
                  TREE_SET_CODE (cond,
452
                                 swap_tree_comparison (TREE_CODE (cond)));
453
                  TREE_OPERAND (cond, 1) = TREE_OPERAND (cond, 0);
454
                  TREE_OPERAND (cond, 0) = decl;
455
                  cond_ok = true;
456
                }
457
 
458
              if (TREE_CODE (cond) == NE_EXPR
459
                  || TREE_CODE (cond) == EQ_EXPR)
460
                {
461
                  if (!INTEGRAL_TYPE_P (TREE_TYPE (decl)))
462
                    cond_ok = false;
463
                  else if (operand_equal_p (TREE_OPERAND (cond, 1),
464
                                            TYPE_MIN_VALUE (TREE_TYPE (decl)),
465
                                            0))
466
                    TREE_SET_CODE (cond, TREE_CODE (cond) == NE_EXPR
467
                                         ? GT_EXPR : LE_EXPR);
468
                  else if (operand_equal_p (TREE_OPERAND (cond, 1),
469
                                            TYPE_MAX_VALUE (TREE_TYPE (decl)),
470
                                            0))
471
                    TREE_SET_CODE (cond, TREE_CODE (cond) == NE_EXPR
472
                                         ? LT_EXPR : GE_EXPR);
473
                  else
474
                    cond_ok = false;
475
                }
476
            }
477
 
478
          if (!cond_ok)
479
            {
480
              error_at (elocus, "invalid controlling predicate");
481
              fail = true;
482
            }
483
        }
484
 
485
      if (incr == NULL_TREE)
486
        {
487
          error_at (elocus, "missing increment expression");
488
          fail = true;
489
        }
490
      else
491
        {
492
          bool incr_ok = false;
493
 
494
          if (EXPR_HAS_LOCATION (incr))
495
            elocus = EXPR_LOCATION (incr);
496
 
497
          /* Check all the valid increment expressions: v++, v--, ++v, --v,
498
             v = v + incr, v = incr + v and v = v - incr.  */
499
          switch (TREE_CODE (incr))
500
            {
501
            case POSTINCREMENT_EXPR:
502
            case PREINCREMENT_EXPR:
503
            case POSTDECREMENT_EXPR:
504
            case PREDECREMENT_EXPR:
505
              if (TREE_OPERAND (incr, 0) != decl)
506
                break;
507
 
508
              incr_ok = true;
509
              if (POINTER_TYPE_P (TREE_TYPE (decl))
510
                  && TREE_OPERAND (incr, 1))
511
                {
512
                  tree t = fold_convert_loc (elocus,
513
                                             sizetype, TREE_OPERAND (incr, 1));
514
 
515
                  if (TREE_CODE (incr) == POSTDECREMENT_EXPR
516
                      || TREE_CODE (incr) == PREDECREMENT_EXPR)
517
                    t = fold_build1_loc (elocus, NEGATE_EXPR, sizetype, t);
518
                  t = fold_build_pointer_plus (decl, t);
519
                  incr = build2 (MODIFY_EXPR, void_type_node, decl, t);
520
                }
521
              break;
522
 
523
            case MODIFY_EXPR:
524
              if (TREE_OPERAND (incr, 0) != decl)
525
                break;
526
              if (TREE_OPERAND (incr, 1) == decl)
527
                break;
528
              if (TREE_CODE (TREE_OPERAND (incr, 1)) == PLUS_EXPR
529
                  && (TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl
530
                      || TREE_OPERAND (TREE_OPERAND (incr, 1), 1) == decl))
531
                incr_ok = true;
532
              else if ((TREE_CODE (TREE_OPERAND (incr, 1)) == MINUS_EXPR
533
                        || (TREE_CODE (TREE_OPERAND (incr, 1))
534
                            == POINTER_PLUS_EXPR))
535
                       && TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl)
536
                incr_ok = true;
537
              else
538
                {
539
                  tree t = check_omp_for_incr_expr (elocus,
540
                                                    TREE_OPERAND (incr, 1),
541
                                                    decl);
542
                  if (t != error_mark_node)
543
                    {
544
                      incr_ok = true;
545
                      t = build2 (PLUS_EXPR, TREE_TYPE (decl), decl, t);
546
                      incr = build2 (MODIFY_EXPR, void_type_node, decl, t);
547
                    }
548
                }
549
              break;
550
 
551
            default:
552
              break;
553
            }
554
          if (!incr_ok)
555
            {
556
              error_at (elocus, "invalid increment expression");
557
              fail = true;
558
            }
559
        }
560
 
561
      TREE_VEC_ELT (initv, i) = init;
562
      TREE_VEC_ELT (incrv, i) = incr;
563
    }
564
 
565
  if (fail)
566
    return NULL;
567
  else
568
    {
569
      tree t = make_node (OMP_FOR);
570
 
571
      TREE_TYPE (t) = void_type_node;
572
      OMP_FOR_INIT (t) = initv;
573
      OMP_FOR_COND (t) = condv;
574
      OMP_FOR_INCR (t) = incrv;
575
      OMP_FOR_BODY (t) = body;
576
      OMP_FOR_PRE_BODY (t) = pre_body;
577
 
578
      SET_EXPR_LOCATION (t, locus);
579
      return add_stmt (t);
580
    }
581
}
582
 
583
 
584
/* Divide CLAUSES into two lists: those that apply to a parallel
585
   construct, and those that apply to a work-sharing construct.  Place
586
   the results in *PAR_CLAUSES and *WS_CLAUSES respectively.  In
587
   addition, add a nowait clause to the work-sharing list.  LOC is the
588
   location of the OMP_PARALLEL*.  */
589
 
590
void
591
c_split_parallel_clauses (location_t loc, tree clauses,
592
                          tree *par_clauses, tree *ws_clauses)
593
{
594
  tree next;
595
 
596
  *par_clauses = NULL;
597
  *ws_clauses = build_omp_clause (loc, OMP_CLAUSE_NOWAIT);
598
 
599
  for (; clauses ; clauses = next)
600
    {
601
      next = OMP_CLAUSE_CHAIN (clauses);
602
 
603
      switch (OMP_CLAUSE_CODE (clauses))
604
        {
605
        case OMP_CLAUSE_PRIVATE:
606
        case OMP_CLAUSE_SHARED:
607
        case OMP_CLAUSE_FIRSTPRIVATE:
608
        case OMP_CLAUSE_LASTPRIVATE:
609
        case OMP_CLAUSE_REDUCTION:
610
        case OMP_CLAUSE_COPYIN:
611
        case OMP_CLAUSE_IF:
612
        case OMP_CLAUSE_NUM_THREADS:
613
        case OMP_CLAUSE_DEFAULT:
614
          OMP_CLAUSE_CHAIN (clauses) = *par_clauses;
615
          *par_clauses = clauses;
616
          break;
617
 
618
        case OMP_CLAUSE_SCHEDULE:
619
        case OMP_CLAUSE_ORDERED:
620
        case OMP_CLAUSE_COLLAPSE:
621
          OMP_CLAUSE_CHAIN (clauses) = *ws_clauses;
622
          *ws_clauses = clauses;
623
          break;
624
 
625
        default:
626
          gcc_unreachable ();
627
        }
628
    }
629
}
630
 
631
/* True if OpenMP sharing attribute of DECL is predetermined.  */
632
 
633
enum omp_clause_default_kind
634
c_omp_predetermined_sharing (tree decl)
635
{
636
  /* Variables with const-qualified type having no mutable member
637
     are predetermined shared.  */
638
  if (TREE_READONLY (decl))
639
    return OMP_CLAUSE_DEFAULT_SHARED;
640
 
641
  return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
642
}

powered by: WebSVN 2.1.0

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