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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [gcc-4.5.1/] [gcc/] [c-omp.c] - Blame information for rev 859

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

Line No. Rev Author Line
1 280 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 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 "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.  LOC is the l*/
39
 
40
tree
41
c_finish_omp_master (location_t loc, tree stmt)
42
{
43
  tree t = add_stmt (build1 (OMP_MASTER, void_type_node, stmt));
44
  SET_EXPR_LOCATION (t, loc);
45
  return t;
46
}
47
 
48
/* Complete a #pragma omp critical construct.  STMT is the structured-block
49
   that follows the pragma, NAME is the identifier in the pragma, or null
50
   if it was omitted.  LOC is the location of the #pragma.  */
51
 
52
tree
53
c_finish_omp_critical (location_t loc, tree body, tree name)
54
{
55
  tree stmt = make_node (OMP_CRITICAL);
56
  TREE_TYPE (stmt) = void_type_node;
57
  OMP_CRITICAL_BODY (stmt) = body;
58
  OMP_CRITICAL_NAME (stmt) = name;
59
  SET_EXPR_LOCATION (stmt, loc);
60
  return add_stmt (stmt);
61
}
62
 
63
/* Complete a #pragma omp ordered construct.  STMT is the structured-block
64
   that follows the pragma.  LOC is the location of the #pragma.  */
65
 
66
tree
67
c_finish_omp_ordered (location_t loc, tree stmt)
68
{
69
  tree t = build1 (OMP_ORDERED, void_type_node, stmt);
70
  SET_EXPR_LOCATION (t, loc);
71
  return add_stmt (t);
72
}
73
 
74
 
75
/* Complete a #pragma omp barrier construct.  LOC is the location of
76
   the #pragma.  */
77
 
78
void
79
c_finish_omp_barrier (location_t loc)
80
{
81
  tree x;
82
 
83
  x = built_in_decls[BUILT_IN_GOMP_BARRIER];
84
  x = build_call_expr_loc (loc, x, 0);
85
  add_stmt (x);
86
}
87
 
88
 
89
/* Complete a #pragma omp taskwait construct.  LOC is the location of the
90
   pragma.  */
91
 
92
void
93
c_finish_omp_taskwait (location_t loc)
94
{
95
  tree x;
96
 
97
  x = built_in_decls[BUILT_IN_GOMP_TASKWAIT];
98
  x = build_call_expr_loc (loc, x, 0);
99
  add_stmt (x);
100
}
101
 
102
 
103
/* Complete a #pragma omp atomic construct.  The expression to be
104
   implemented atomically is LHS code= RHS.  LOC is the location of
105
   the atomic statement.  The value returned is either error_mark_node
106
   (if the construct was erroneous) or an OMP_ATOMIC node which should
107
   be added to the current statement tree with add_stmt.*/
108
 
109
tree
110
c_finish_omp_atomic (location_t loc, enum tree_code code, tree lhs, tree rhs)
111
{
112
  tree x, type, addr;
113
 
114
  if (lhs == error_mark_node || rhs == error_mark_node)
115
    return error_mark_node;
116
 
117
  /* ??? According to one reading of the OpenMP spec, complex type are
118
     supported, but there are no atomic stores for any architecture.
119
     But at least icc 9.0 doesn't support complex types here either.
120
     And lets not even talk about vector types...  */
121
  type = TREE_TYPE (lhs);
122
  if (!INTEGRAL_TYPE_P (type)
123
      && !POINTER_TYPE_P (type)
124
      && !SCALAR_FLOAT_TYPE_P (type))
125
    {
126
      error_at (loc, "invalid expression type for %<#pragma omp atomic%>");
127
      return error_mark_node;
128
    }
129
 
130
  /* ??? Validate that rhs does not overlap lhs.  */
131
 
132
  /* Take and save the address of the lhs.  From then on we'll reference it
133
     via indirection.  */
134
  addr = build_unary_op (loc, ADDR_EXPR, lhs, 0);
135
  if (addr == error_mark_node)
136
    return error_mark_node;
137
  addr = save_expr (addr);
138
  if (TREE_CODE (addr) != SAVE_EXPR
139
      && (TREE_CODE (addr) != ADDR_EXPR
140
          || TREE_CODE (TREE_OPERAND (addr, 0)) != VAR_DECL))
141
    {
142
      /* Make sure LHS is simple enough so that goa_lhs_expr_p can recognize
143
         it even after unsharing function body.  */
144
      tree var = create_tmp_var_raw (TREE_TYPE (addr), NULL);
145
      DECL_CONTEXT (var) = current_function_decl;
146
      addr = build4 (TARGET_EXPR, TREE_TYPE (addr), var, addr, NULL, NULL);
147
    }
148
  lhs = build_indirect_ref (loc, addr, RO_NULL);
149
 
150
  /* There are lots of warnings, errors, and conversions that need to happen
151
     in the course of interpreting a statement.  Use the normal mechanisms
152
     to do this, and then take it apart again.  */
153
  x = build_modify_expr (input_location, lhs, NULL_TREE, code,
154
                         input_location, rhs, NULL_TREE);
155
  if (x == error_mark_node)
156
    return error_mark_node;
157
  gcc_assert (TREE_CODE (x) == MODIFY_EXPR);
158
  rhs = TREE_OPERAND (x, 1);
159
 
160
  /* Punt the actual generation of atomic operations to common code.  */
161
  x = build2 (OMP_ATOMIC, void_type_node, addr, rhs);
162
  SET_EXPR_LOCATION (x, loc);
163
  return x;
164
}
165
 
166
 
167
/* Complete a #pragma omp flush construct.  We don't do anything with
168
   the variable list that the syntax allows.  LOC is the location of
169
   the #pragma.  */
170
 
171
void
172
c_finish_omp_flush (location_t loc)
173
{
174
  tree x;
175
 
176
  x = built_in_decls[BUILT_IN_SYNCHRONIZE];
177
  x = build_call_expr_loc (loc, x, 0);
178
  add_stmt (x);
179
}
180
 
181
 
182
/* Check and canonicalize #pragma omp for increment expression.
183
   Helper function for c_finish_omp_for.  */
184
 
185
static tree
186
check_omp_for_incr_expr (location_t loc, tree exp, tree decl)
187
{
188
  tree t;
189
 
190
  if (!INTEGRAL_TYPE_P (TREE_TYPE (exp))
191
      || TYPE_PRECISION (TREE_TYPE (exp)) < TYPE_PRECISION (TREE_TYPE (decl)))
192
    return error_mark_node;
193
 
194
  if (exp == decl)
195
    return build_int_cst (TREE_TYPE (exp), 0);
196
 
197
  switch (TREE_CODE (exp))
198
    {
199
    CASE_CONVERT:
200
      t = check_omp_for_incr_expr (loc, TREE_OPERAND (exp, 0), decl);
201
      if (t != error_mark_node)
202
        return fold_convert_loc (loc, TREE_TYPE (exp), t);
203
      break;
204
    case MINUS_EXPR:
205
      t = check_omp_for_incr_expr (loc, TREE_OPERAND (exp, 0), decl);
206
      if (t != error_mark_node)
207
        return fold_build2_loc (loc, MINUS_EXPR,
208
                            TREE_TYPE (exp), t, TREE_OPERAND (exp, 1));
209
      break;
210
    case PLUS_EXPR:
211
      t = check_omp_for_incr_expr (loc, TREE_OPERAND (exp, 0), decl);
212
      if (t != error_mark_node)
213
        return fold_build2_loc (loc, PLUS_EXPR,
214
                            TREE_TYPE (exp), t, TREE_OPERAND (exp, 1));
215
      t = check_omp_for_incr_expr (loc, TREE_OPERAND (exp, 1), decl);
216
      if (t != error_mark_node)
217
        return fold_build2_loc (loc, PLUS_EXPR,
218
                            TREE_TYPE (exp), TREE_OPERAND (exp, 0), t);
219
      break;
220
    default:
221
      break;
222
    }
223
 
224
  return error_mark_node;
225
}
226
 
227
/* Validate and emit code for the OpenMP directive #pragma omp for.
228
   DECLV is a vector of iteration variables, for each collapsed loop.
229
   INITV, CONDV and INCRV are vectors containing initialization
230
   expressions, controlling predicates and increment expressions.
231
   BODY is the body of the loop and PRE_BODY statements that go before
232
   the loop.  */
233
 
234
tree
235
c_finish_omp_for (location_t locus, tree declv, tree initv, tree condv,
236
                  tree incrv, tree body, tree pre_body)
237
{
238
  location_t elocus;
239
  bool fail = false;
240
  int i;
241
 
242
  gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (initv));
243
  gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (condv));
244
  gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (incrv));
245
  for (i = 0; i < TREE_VEC_LENGTH (declv); i++)
246
    {
247
      tree decl = TREE_VEC_ELT (declv, i);
248
      tree init = TREE_VEC_ELT (initv, i);
249
      tree cond = TREE_VEC_ELT (condv, i);
250
      tree incr = TREE_VEC_ELT (incrv, i);
251
 
252
      elocus = locus;
253
      if (EXPR_HAS_LOCATION (init))
254
        elocus = EXPR_LOCATION (init);
255
 
256
      /* Validate the iteration variable.  */
257
      if (!INTEGRAL_TYPE_P (TREE_TYPE (decl))
258
          && TREE_CODE (TREE_TYPE (decl)) != POINTER_TYPE)
259
        {
260
          error_at (elocus, "invalid type for iteration variable %qE", decl);
261
          fail = true;
262
        }
263
 
264
      /* In the case of "for (int i = 0...)", init will be a decl.  It should
265
         have a DECL_INITIAL that we can turn into an assignment.  */
266
      if (init == decl)
267
        {
268
          elocus = DECL_SOURCE_LOCATION (decl);
269
 
270
          init = DECL_INITIAL (decl);
271
          if (init == NULL)
272
            {
273
              error_at (elocus, "%qE is not initialized", decl);
274
              init = integer_zero_node;
275
              fail = true;
276
            }
277
 
278
          init = build_modify_expr (elocus, decl, NULL_TREE, NOP_EXPR,
279
                                    /* FIXME diagnostics: This should
280
                                       be the location of the INIT.  */
281
                                    elocus,
282
                                    init,
283
                                    NULL_TREE);
284
        }
285
      gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
286
      gcc_assert (TREE_OPERAND (init, 0) == decl);
287
 
288
      if (cond == NULL_TREE)
289
        {
290
          error_at (elocus, "missing controlling predicate");
291
          fail = true;
292
        }
293
      else
294
        {
295
          bool cond_ok = false;
296
 
297
          if (EXPR_HAS_LOCATION (cond))
298
            elocus = EXPR_LOCATION (cond);
299
 
300
          if (TREE_CODE (cond) == LT_EXPR
301
              || TREE_CODE (cond) == LE_EXPR
302
              || TREE_CODE (cond) == GT_EXPR
303
              || TREE_CODE (cond) == GE_EXPR
304
              || TREE_CODE (cond) == NE_EXPR
305
              || TREE_CODE (cond) == EQ_EXPR)
306
            {
307
              tree op0 = TREE_OPERAND (cond, 0);
308
              tree op1 = TREE_OPERAND (cond, 1);
309
 
310
              /* 2.5.1.  The comparison in the condition is computed in
311
                 the type of DECL, otherwise the behavior is undefined.
312
 
313
                 For example:
314
                 long n; int i;
315
                 i < n;
316
 
317
                 according to ISO will be evaluated as:
318
                 (long)i < n;
319
 
320
                 We want to force:
321
                 i < (int)n;  */
322
              if (TREE_CODE (op0) == NOP_EXPR
323
                  && decl == TREE_OPERAND (op0, 0))
324
                {
325
                  TREE_OPERAND (cond, 0) = TREE_OPERAND (op0, 0);
326
                  TREE_OPERAND (cond, 1)
327
                    = fold_build1_loc (elocus, NOP_EXPR, TREE_TYPE (decl),
328
                                   TREE_OPERAND (cond, 1));
329
                }
330
              else if (TREE_CODE (op1) == NOP_EXPR
331
                       && decl == TREE_OPERAND (op1, 0))
332
                {
333
                  TREE_OPERAND (cond, 1) = TREE_OPERAND (op1, 0);
334
                  TREE_OPERAND (cond, 0)
335
                    = fold_build1_loc (elocus, NOP_EXPR, TREE_TYPE (decl),
336
                                   TREE_OPERAND (cond, 0));
337
                }
338
 
339
              if (decl == TREE_OPERAND (cond, 0))
340
                cond_ok = true;
341
              else if (decl == TREE_OPERAND (cond, 1))
342
                {
343
                  TREE_SET_CODE (cond,
344
                                 swap_tree_comparison (TREE_CODE (cond)));
345
                  TREE_OPERAND (cond, 1) = TREE_OPERAND (cond, 0);
346
                  TREE_OPERAND (cond, 0) = decl;
347
                  cond_ok = true;
348
                }
349
 
350
              if (TREE_CODE (cond) == NE_EXPR
351
                  || TREE_CODE (cond) == EQ_EXPR)
352
                {
353
                  if (!INTEGRAL_TYPE_P (TREE_TYPE (decl)))
354
                    cond_ok = false;
355
                  else if (operand_equal_p (TREE_OPERAND (cond, 1),
356
                                            TYPE_MIN_VALUE (TREE_TYPE (decl)),
357
                                            0))
358
                    TREE_SET_CODE (cond, TREE_CODE (cond) == NE_EXPR
359
                                         ? GT_EXPR : LE_EXPR);
360
                  else if (operand_equal_p (TREE_OPERAND (cond, 1),
361
                                            TYPE_MAX_VALUE (TREE_TYPE (decl)),
362
                                            0))
363
                    TREE_SET_CODE (cond, TREE_CODE (cond) == NE_EXPR
364
                                         ? LT_EXPR : GE_EXPR);
365
                  else
366
                    cond_ok = false;
367
                }
368
            }
369
 
370
          if (!cond_ok)
371
            {
372
              error_at (elocus, "invalid controlling predicate");
373
              fail = true;
374
            }
375
        }
376
 
377
      if (incr == NULL_TREE)
378
        {
379
          error_at (elocus, "missing increment expression");
380
          fail = true;
381
        }
382
      else
383
        {
384
          bool incr_ok = false;
385
 
386
          if (EXPR_HAS_LOCATION (incr))
387
            elocus = EXPR_LOCATION (incr);
388
 
389
          /* Check all the valid increment expressions: v++, v--, ++v, --v,
390
             v = v + incr, v = incr + v and v = v - incr.  */
391
          switch (TREE_CODE (incr))
392
            {
393
            case POSTINCREMENT_EXPR:
394
            case PREINCREMENT_EXPR:
395
            case POSTDECREMENT_EXPR:
396
            case PREDECREMENT_EXPR:
397
              if (TREE_OPERAND (incr, 0) != decl)
398
                break;
399
 
400
              incr_ok = true;
401
              if (POINTER_TYPE_P (TREE_TYPE (decl))
402
                  && TREE_OPERAND (incr, 1))
403
                {
404
                  tree t = fold_convert_loc (elocus,
405
                                             sizetype, TREE_OPERAND (incr, 1));
406
 
407
                  if (TREE_CODE (incr) == POSTDECREMENT_EXPR
408
                      || TREE_CODE (incr) == PREDECREMENT_EXPR)
409
                    t = fold_build1_loc (elocus, NEGATE_EXPR, sizetype, t);
410
                  t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (decl), decl, t);
411
                  incr = build2 (MODIFY_EXPR, void_type_node, decl, t);
412
                }
413
              break;
414
 
415
            case MODIFY_EXPR:
416
              if (TREE_OPERAND (incr, 0) != decl)
417
                break;
418
              if (TREE_OPERAND (incr, 1) == decl)
419
                break;
420
              if (TREE_CODE (TREE_OPERAND (incr, 1)) == PLUS_EXPR
421
                  && (TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl
422
                      || TREE_OPERAND (TREE_OPERAND (incr, 1), 1) == decl))
423
                incr_ok = true;
424
              else if ((TREE_CODE (TREE_OPERAND (incr, 1)) == MINUS_EXPR
425
                        || (TREE_CODE (TREE_OPERAND (incr, 1))
426
                            == POINTER_PLUS_EXPR))
427
                       && TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl)
428
                incr_ok = true;
429
              else
430
                {
431
                  tree t = check_omp_for_incr_expr (elocus,
432
                                                    TREE_OPERAND (incr, 1),
433
                                                    decl);
434
                  if (t != error_mark_node)
435
                    {
436
                      incr_ok = true;
437
                      t = build2 (PLUS_EXPR, TREE_TYPE (decl), decl, t);
438
                      incr = build2 (MODIFY_EXPR, void_type_node, decl, t);
439
                    }
440
                }
441
              break;
442
 
443
            default:
444
              break;
445
            }
446
          if (!incr_ok)
447
            {
448
              error_at (elocus, "invalid increment expression");
449
              fail = true;
450
            }
451
        }
452
 
453
      TREE_VEC_ELT (initv, i) = init;
454
      TREE_VEC_ELT (incrv, i) = incr;
455
    }
456
 
457
  if (fail)
458
    return NULL;
459
  else
460
    {
461
      tree t = make_node (OMP_FOR);
462
 
463
      TREE_TYPE (t) = void_type_node;
464
      OMP_FOR_INIT (t) = initv;
465
      OMP_FOR_COND (t) = condv;
466
      OMP_FOR_INCR (t) = incrv;
467
      OMP_FOR_BODY (t) = body;
468
      OMP_FOR_PRE_BODY (t) = pre_body;
469
 
470
      SET_EXPR_LOCATION (t, locus);
471
      return add_stmt (t);
472
    }
473
}
474
 
475
 
476
/* Divide CLAUSES into two lists: those that apply to a parallel
477
   construct, and those that apply to a work-sharing construct.  Place
478
   the results in *PAR_CLAUSES and *WS_CLAUSES respectively.  In
479
   addition, add a nowait clause to the work-sharing list.  LOC is the
480
   location of the OMP_PARALLEL*.  */
481
 
482
void
483
c_split_parallel_clauses (location_t loc, tree clauses,
484
                          tree *par_clauses, tree *ws_clauses)
485
{
486
  tree next;
487
 
488
  *par_clauses = NULL;
489
  *ws_clauses = build_omp_clause (loc, OMP_CLAUSE_NOWAIT);
490
 
491
  for (; clauses ; clauses = next)
492
    {
493
      next = OMP_CLAUSE_CHAIN (clauses);
494
 
495
      switch (OMP_CLAUSE_CODE (clauses))
496
        {
497
        case OMP_CLAUSE_PRIVATE:
498
        case OMP_CLAUSE_SHARED:
499
        case OMP_CLAUSE_FIRSTPRIVATE:
500
        case OMP_CLAUSE_LASTPRIVATE:
501
        case OMP_CLAUSE_REDUCTION:
502
        case OMP_CLAUSE_COPYIN:
503
        case OMP_CLAUSE_IF:
504
        case OMP_CLAUSE_NUM_THREADS:
505
        case OMP_CLAUSE_DEFAULT:
506
          OMP_CLAUSE_CHAIN (clauses) = *par_clauses;
507
          *par_clauses = clauses;
508
          break;
509
 
510
        case OMP_CLAUSE_SCHEDULE:
511
        case OMP_CLAUSE_ORDERED:
512
        case OMP_CLAUSE_COLLAPSE:
513
          OMP_CLAUSE_CHAIN (clauses) = *ws_clauses;
514
          *ws_clauses = clauses;
515
          break;
516
 
517
        default:
518
          gcc_unreachable ();
519
        }
520
    }
521
}
522
 
523
/* True if OpenMP sharing attribute of DECL is predetermined.  */
524
 
525
enum omp_clause_default_kind
526
c_omp_predetermined_sharing (tree decl)
527
{
528
  /* Variables with const-qualified type having no mutable member
529
     are predetermined shared.  */
530
  if (TREE_READONLY (decl))
531
    return OMP_CLAUSE_DEFAULT_SHARED;
532
 
533
  return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
534
}

powered by: WebSVN 2.1.0

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